commit 42d6da63027312d531824fadb28c1a43554ae060 Author: TheM14 Date: Fri Sep 25 04:17:30 2026 +0800 Initial pure C++ implementation diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ff17a1a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,38 @@ +name: ci + +on: + push: + pull_request: + +jobs: + build: + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - uses: actions/checkout@v4 + + - name: Configure + run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release + + - name: Build + run: cmake --build build --config Release --parallel + + - name: Test + run: ctest --test-dir build --output-on-failure -C Release + + # Publish the install tree: the shared library and the CLI. + - name: Stage + run: cmake --install build --config Release --prefix stage + + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: joc-core-${{ runner.os }} + path: | + stage/bin/* + stage/lib/* + if-no-files-found: error diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f0e3153 --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +/build/ +/output/ +/out/ +/traces/ +/vectors/ +/testdata/ +/devtools/ +.vs/ +.vscode/ +CMakeUserPresets.json +__pycache__/ +*.spool.f32 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e6c96de --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,330 @@ +cmake_minimum_required(VERSION 3.20) + +project(joc_core VERSION 0.1.0 LANGUAGES C CXX) + +# --------------------------------------------------------------------------- +# Products +# joc_core shared library: the execution core (E-AC-3/EMDF/JOC/OAMD +# bitstream, DSP, speaker and binaural rendering, ADM-BWF/WAV +# writing, file task and the streaming push/pull surface) +# joc_cli command line frontend for file tasks +# +# Public headers: include/joc_core.h engine, telemetry and file task +# include/joc_stream.h embedder-facing streaming surface +# +# Options +# JOC_BUILD_TESTS unit tests (CTest), on by default +# JOC_BUILD_DEVTOOLS in-tree verification tools, off: those sources live in +# devtools/, which is not part of the repository +# JOC_ENABLE_AVX2 build the runtime-dispatched AVX2 kernels, on by default +# JOC_ENABLE_AVX512 build the runtime-dispatched AVX-512 kernels, on by default +# +# Only the MSVC toolchain is validated locally; other platforms are built by CI. +# The floating-point flags of the original native library are preserved on +# purpose: /fp:precise on MSVC, -fno-fast-math elsewhere, and a static CRT so +# that no redistributable is required. +# --------------------------------------------------------------------------- + +option(JOC_BUILD_TESTS "Build the unit tests" ON) +option(JOC_BUILD_DEVTOOLS "Build the in-tree verification tools (needs devtools/)" OFF) +# The DSP kernels are dispatched at run time (see src/simd/simd.h): the +# baseline units stay on the ISA every x86-64 CPU has, and these two options +# decide whether the wider units are linked in at all. Both are on by default. +# The instruction set actually executed is chosen from CPUID/XGETBV (or the +# AArch64 baseline) when the library is first used, so a binary carrying the +# AVX-512 unit still runs on a CPU without it, and JOC_SIMD=scalar|sse2|avx2| +# avx512|neon pins one tier for verification. +option(JOC_ENABLE_AVX2 "Build the runtime-dispatched AVX2 kernels" ON) +option(JOC_ENABLE_AVX512 "Build the runtime-dispatched AVX-512 kernels" ON) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) +endif() + +find_package(Threads REQUIRED) + +# Ninja learns MSVC's header dependencies by parsing the compiler's /showIncludes +# notes, and it only recognises the prefix it is told about. A localized MSVC +# prints a translated prefix, and when CMake cannot detect it the notes are +# silently dropped: the build then reuses stale objects after a header changes and +# produces a binary that does not match its sources -- wrong, not just slow. This +# only warns, because supplying the value is not always possible either: it has to +# survive the cache code page to be usable, and a build driver can compensate more +# reliably by dropping objects when a header is newer than they are. +if(MSVC AND CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_CL_SHOWINCLUDES_PREFIX) + message(WARNING + "No /showIncludes prefix was detected, so Ninja will not track header " + "dependencies and a header change will not rebuild what includes it. " + "Configure with -DCMAKE_CL_SHOWINCLUDES_PREFIX=, or make sure the compiler emits its " + "messages in the language CMake probes for.") +endif() + +# Verbatim copies of the upstream native library; see THIRD_PARTY_NOTICES.md. +# These files are never edited: they are the validated DSP kernels. +set(JOC_REUSED_SOURCES + src/joc_core/eac3joc_core.cpp + src/speaker/speaker_renderer.cpp + src/binaural/binaural_renderer.cpp +) + +set(JOC_INTERNAL_SOURCES + src/adm/adm_metadata.cpp + src/adm/adm_tracks.cpp + src/binaural/binaural_runtime.cpp + src/binaural/sofa_binaural_renderer.cpp + src/eac3_transport/eac3_reader.cpp + src/emdf/emdf_parser.cpp + src/foundation/bit_reader.cpp + src/foundation/fft.cpp + src/foundation/fs_utf8.cpp + src/foundation/mini_json.cpp + src/foundation/sha256.cpp + src/hrtf/jochrtf.cpp + src/hrtf/public_filterbank.cpp + src/hrtf/rosella_model.cpp + src/hrtf/rosella_renderer.cpp + src/hrtf/kernel_tables.cpp + src/hrtf/sofa.cpp + src/hrtf/sofa_cache.cpp + src/hrtf/sofa_field.cpp + src/io/adm_writer.cpp + src/io/hdf5.cpp + src/io/inflate.cpp + src/io/npy.cpp + src/io/npy_writer.cpp + src/io/process.cpp + src/io/wav_writer.cpp + src/io/zip_reader.cpp + src/joc_bitstream/joc_parser.cpp + src/joc_core/objects16.cpp + src/oamd/oamd_parser.cpp + src/speaker/speaker_layout_lookup.cpp + src/speaker/speaker_step.cpp + src/stream/stream.cpp + src/task/task.cpp + src/telemetry/event_bus.cpp + src/timeline/position_timeline.cpp +) + +# --------------------------------------------------------------------------- +# Runtime-dispatched SIMD kernels (src/simd/simd.h explains the contract). +# +# One flat directory, the ISA in the file name (`kernels_intrin_.cpp`), +# never in a subdirectory. MSVC has no function-level ISA attribute, so every +# ISA lives in its own translation unit compiled with its own flag, and +# dispatch.cpp -- built for the baseline ISA -- picks one when the library is +# first used. Only a `kernels_intrin_*.cpp` unit ever gets a wider flag, so a +# baseline unit cannot inherit one by accident. +# +# The x86-64 baseline is SSE2 and there is no SSE2 unit on purpose: a 128-bit +# SSE2 register is the register a scalar double already occupies, so SSE2 cannot +# widen double-precision arithmetic and hand-written SSE2 would only add moves. +# AArch64 needs no probe either; ASIMD is architectural, and the NEON unit is +# how a vector path gets selected there. +# --------------------------------------------------------------------------- +set(JOC_SIMD_SOURCES + src/simd/cpu_probe.cpp + src/simd/dispatch.cpp + src/simd/kernels_scalar.cpp +) +set(JOC_SIMD_DEFINES "") + +set(JOC_ARCH "") +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(AMD64|amd64|x86_64|X86_64|EM64T)$") + set(JOC_ARCH x86_64) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(ARM64|arm64|aarch64|AARCH64)$") + set(JOC_ARCH aarch64) + endif() +endif() +if(NOT JOC_ARCH AND DEFINED CMAKE_CXX_COMPILER_ARCHITECTURE_ID) + if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "x64") + set(JOC_ARCH x86_64) + elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "ARM64") + set(JOC_ARCH aarch64) + endif() +endif() + +if(JOC_ARCH STREQUAL "x86_64") + list(APPEND JOC_SIMD_DEFINES JOC_SIMD_HAVE_SSE2=1) + if(JOC_ENABLE_AVX2) + list(APPEND JOC_SIMD_SOURCES src/simd/kernels_intrin_avx2.cpp) + list(APPEND JOC_SIMD_DEFINES JOC_SIMD_HAVE_AVX2=1) + if(MSVC) + set_source_files_properties(src/simd/kernels_intrin_avx2.cpp + PROPERTIES COMPILE_OPTIONS "/arch:AVX2") + else() + set_source_files_properties(src/simd/kernels_intrin_avx2.cpp + PROPERTIES COMPILE_OPTIONS "-mavx2") + endif() + endif() + if(JOC_ENABLE_AVX512) + list(APPEND JOC_SIMD_SOURCES src/simd/kernels_intrin_avx512.cpp) + list(APPEND JOC_SIMD_DEFINES JOC_SIMD_HAVE_AVX512=1) + if(MSVC) + set_source_files_properties(src/simd/kernels_intrin_avx512.cpp + PROPERTIES COMPILE_OPTIONS "/arch:AVX512") + else() + set_source_files_properties(src/simd/kernels_intrin_avx512.cpp + PROPERTIES COMPILE_OPTIONS "-mavx512f") + endif() + endif() +elseif(JOC_ARCH STREQUAL "aarch64") + list(APPEND JOC_SIMD_DEFINES JOC_SIMD_HAVE_NEON=1) + list(APPEND JOC_SIMD_SOURCES src/simd/kernels_intrin_neon.cpp) +endif() + +add_library(joc_simd OBJECT ${JOC_SIMD_SOURCES}) +target_include_directories(joc_simd PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") +target_compile_definitions(joc_simd PRIVATE ${JOC_SIMD_DEFINES}) +# The objects are linked into the shared library as well, so they must be +# position independent even though an object library does not inherit that. +set_target_properties(joc_simd PROPERTIES POSITION_INDEPENDENT_CODE ON) + +# Static form of the engine, used by the in-tree tools and tests so they can use +# internal modules without exporting them from the shared library. +if(JOC_BUILD_TESTS OR JOC_BUILD_DEVTOOLS) + add_library(joc_core_impl STATIC ${JOC_INTERNAL_SOURCES} ${JOC_REUSED_SOURCES} + $) + target_include_directories(joc_core_impl + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" + ) + target_link_libraries(joc_core_impl PUBLIC Threads::Threads) +endif() + +add_library(joc_core SHARED + src/api/joc_api.cpp + src/api/joc_stream_api.cpp + src/api/joc_task_api.cpp + ${JOC_INTERNAL_SOURCES} + ${JOC_REUSED_SOURCES} + $ +) +target_include_directories(joc_core + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src" +) +target_compile_definitions(joc_core PRIVATE JOC_BUILD_DLL) +target_link_libraries(joc_core PRIVATE Threads::Threads) +set_target_properties(joc_core PROPERTIES + OUTPUT_NAME "joc_core" + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN YES + POSITION_INDEPENDENT_CODE YES +) + +# The frontend compiles the UTF-8 path shim itself: it is small, and the shared +# library keeps its internals unexported. +add_executable(joc_cli src/cli/joc_cli.cpp src/foundation/fs_utf8.cpp) +target_link_libraries(joc_cli PRIVATE joc_core) +target_include_directories(joc_cli PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + +# The installed CLI is in bin/ and the shared library in lib/, and ELF/Mach-O +# strip the build rpath on install, so the relative lookup has to be recorded +# here or `bin/joc_cli` cannot find `../lib/libjoc_core.*`. +if(UNIX) + if(APPLE) + set_target_properties(joc_cli PROPERTIES INSTALL_RPATH "@loader_path/../lib") + else() + set_target_properties(joc_cli PROPERTIES INSTALL_RPATH "$ORIGIN/../lib") + endif() +endif() + +if(JOC_BUILD_TESTS) + enable_testing() + add_executable(joc_tests tests/test_core.cpp) + target_link_libraries(joc_tests PRIVATE joc_core_impl) + target_include_directories(joc_tests PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + add_test(NAME core COMMAND joc_tests) + # The public headers must stay valid C and C++: these targets exist to prove it. + add_library(joc_headers_c OBJECT tests/test_headers.c) + target_include_directories(joc_headers_c PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") + add_library(joc_headers_cpp OBJECT tests/test_headers.cpp) + target_link_libraries(joc_headers_cpp PRIVATE joc_core) +endif() + +if(JOC_BUILD_DEVTOOLS) + add_executable(joc_dump devtools/joc_dump/main.cpp) + target_link_libraries(joc_dump PRIVATE joc_core joc_core_impl) + target_include_directories(joc_dump PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + # SOFA reader probe: the C++ side of devtools/checks/check_sofa.py. + add_executable(joc_sofa_field_probe devtools/sofa_field_probe/main.cpp) + add_executable(joc_dictionary_probe devtools/sofa_field_probe/dictionary_main.cpp) + target_link_libraries(joc_dictionary_probe PRIVATE joc_core_impl) + target_include_directories(joc_dictionary_probe PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + target_link_libraries(joc_sofa_field_probe PRIVATE joc_core_impl) + target_include_directories(joc_sofa_field_probe PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + # Rosella model probe: the C++ side of devtools/checks/check_rosella.py. + add_executable(joc_rosella_probe devtools/rosella_probe/main.cpp) + target_link_libraries(joc_rosella_probe PRIVATE joc_core_impl) + target_include_directories(joc_rosella_probe PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + add_executable(joc_sofa_probe devtools/sofa_probe/main.cpp) + target_link_libraries(joc_sofa_probe PRIVATE joc_core_impl) + target_include_directories(joc_sofa_probe PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src") + # Probe for the streaming surface: the acceptance harness and the usage + # example for joc_stream.h. Not shipped: a player integrates the library. + add_executable(joc_stream_probe devtools/joc_stream/main.cpp) + target_link_libraries(joc_stream_probe PRIVATE joc_core) +endif() + +set(JOC_MSVC_TARGETS joc_core joc_cli joc_simd) +if(JOC_BUILD_TESTS OR JOC_BUILD_DEVTOOLS) + list(APPEND JOC_MSVC_TARGETS joc_core_impl) +endif() +if(JOC_BUILD_TESTS) + list(APPEND JOC_MSVC_TARGETS joc_tests joc_headers_c joc_headers_cpp) +endif() +if(JOC_BUILD_DEVTOOLS) + list(APPEND JOC_MSVC_TARGETS joc_rosella_probe joc_dump joc_stream_probe joc_sofa_probe joc_sofa_field_probe joc_dictionary_probe) +endif() + +if(MSVC) + set(JOC_MSVC_FLAGS /W4 /permissive- /Zc:__cplusplus /utf-8 /EHsc /GR- /fp:precise) + # The writers use std::fopen for seekable, byte-exact output. + set(JOC_MSVC_DEFINES _CRT_SECURE_NO_WARNINGS) + # C4324 comes from the reused kernel's std::barrier member at /W4; it is + # pre-existing behaviour of a verbatim file, so the warning is silenced + # rather than the file edited. + set_source_files_properties(src/joc_core/eac3joc_core.cpp + PROPERTIES COMPILE_OPTIONS "/wd4324") + foreach(target IN LISTS JOC_MSVC_TARGETS) + set_property(TARGET ${target} PROPERTY + MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + # No /arch here on purpose: the baseline units keep the architecture's + # guaranteed ISA and only the src/simd `kernels_intrin_*` units carry a + # wider one (their flags are set per source file above). + target_compile_options(${target} PRIVATE ${JOC_MSVC_FLAGS} + $<$:/O2> + $<$:/Oi>) + target_compile_definitions(${target} PRIVATE ${JOC_MSVC_DEFINES}) + endforeach() + target_link_options(joc_core PRIVATE /INCREMENTAL:NO /OPT:REF /OPT:ICF) + target_link_options(joc_cli PRIVATE /INCREMENTAL:NO) +else() + foreach(target IN LISTS JOC_MSVC_TARGETS) + target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -fno-fast-math + $<$:-O3>) + endforeach() +endif() + +# Headers listed for IDE visibility. +target_sources(joc_core PRIVATE + include/joc_core.h + include/joc_stream.h + include/eac3joc_core.h + src/joc_bitstream/joc_huffman_tables.h + src/joc_core/qmf_tables.h + src/speaker/speaker_layouts.h +) + +install(TARGETS joc_core joc_cli + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..676e3b7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 TheM14 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..c010fec --- /dev/null +++ b/README.en.md @@ -0,0 +1,159 @@ +# JustOneCacophony — C++ Core + +[中文](README.md) · [Mathematics](docs/math.en.md) · [Binaural rendering](docs/binaural.en.md) · [SIMD dispatch](docs/simd.en.md) + +The C++ implementation of JustOneCacophony: an execution core for E-AC-3 JOC +bitstream parsing, object reconstruction and rendering. It extracts EMDF, ID14 JOC +parameters and ID11 OAMD metadata from E-AC-3 syncframes, combines them with the +core 5.1 PCM decoded by FFmpeg to rebuild the LFE and 15 object signals, and writes +ADM BWF, a WAV for a chosen speaker layout, or a binaural WAV using a compiled HRTF +directional field. + +This is research code, not a complete, standard-conformant or production JOC +decoder. It covers the bitstream forms it implements and reports an explicit error +on unknown variants instead of pretending everything is in harmony. + +## Building + +```powershell +cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release +cmake --build build +ctest --test-dir build --output-on-failure +``` + +Only MSVC (VS 2022, static CRT) is validated locally; Linux and macOS are built and +unit-tested by `.github/workflows/ci.yml`. Floating-point behaviour is part of the +byte-exact acceptance, so fast-math is never enabled: `/fp:precise` on MSVC, +`-fno-fast-math` elsewhere. + +Windows Release builds target AVX2 by default (`JOC_ENABLE_AVX2`, ON, see +`CMakeLists.txt`). That switch is itself part of the byte-exact acceptance — the +SHA-256 of every rendered output is identical — and buys 12.4% on the SOFA binaural +kernel and 1.8% on Rosella. The price is a runtime requirement: such a `joc_core.dll` +executes AVX2 instructions and dies on an illegal instruction on pre-2013 x86. There +is no runtime dispatch, so a binary is one or the other: + +```powershell +cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DJOC_ENABLE_AVX2=OFF +``` + +gives a baseline-ISA (SSE2) build that runs on any x86-64. Non-MSVC builds never +receive the flag. + +### Paths and encoding + +Every path inside the library is **UTF-8**, converted only at the OS boundary +(`src/foundation/fs_utf8.*`): on Windows through `std::filesystem::path` (UTF-16 +inside) into `_wfopen`/`CreateProcessW`, and as plain bytes elsewhere. Command line +arguments are re-parsed from `GetCommandLineW` + `CommandLineToArgvW` on Windows and +the console code page is set to UTF-8, so non-ASCII paths (Japanese, Chinese, ...) +work for the input, the ffmpeg child process and the output files alike; a +non-ASCII path regression case runs in `ctest`. + +## Artifacts + +| Artifact | Purpose | +|---|---| +| `joc_core.dll` | The engine: bitstream parsing, JOC/OAMD, DSP, speaker and binaural rendering, ADM BWF/WAV writing, file task, streaming surface | +| `joc_cli.exe` | Command line frontend for file tasks | +| `include/joc_core.h` | Engine, telemetry and file-task interface (pure C) | +| `include/joc_stream.h` | Embedder-facing streaming push/pull interface (pure C, self-contained) | + +## Command line + +The arguments match the reference Python CLI exactly: the input is positional, +**ADM BWF is the default output**, `--speaker-layout` or `--binaural` selects the +other two modes, and without `-o` the result lands in `output/`. + +```powershell +# Default: ADM BWF (inherently 24-bit, so there is no format option) +joc_cli "07. Gold Forever (2021 Master).m4a" +# -> output/07. Gold Forever (2021 Master).adm.wav + +joc_cli input.m4a -o out/adm.wav # explicit output + +# Speaker layout +joc_cli input.m4a --speaker-layout 5.1 # -> output/.5.1.wav +joc_cli input.m4a --speaker-layout 7.1.4 --speaker-output out/714.wav --speaker-format int24 + +# Binaural (HRTF defaults to /HRTF/binaural.sofa, then /HRTF/binaural.personalized_headphone) +joc_cli input.m4a --binaural +joc_cli input.m4a --binaural --sofa-hrtf HRTF/other.sofa # another SOFA +joc_cli input.m4a --binaural --personalized-headphone # Rosella personalisation +# -> output/.binaural.wav + +# Other common switches +joc_cli input.m4a --duration 30 --gain-db -3 --trajectory-mode dense64 +joc_cli input.eac3 --metadata-only --print-metadata summary # parse and print metadata only +``` + +`--speaker-format` / `--binaural-format` default to `float32`; an `int24` request that +would clip follows `--clip-action` (default `ask`; a non-interactive terminal must +pass `continue`, `float32` or `abort`). `--duration` is in **seconds**, and +`--object-delay-samples`, `--speaker-metadata-offset`, `--binaural-tail-seconds` and +`--binaural-tail-threshold` (1e-8, the binaural tail trim) keep the reference +defaults. A run always writes `.report.json` (`--report-json` overrides it). + +**Differences from the reference:** `--sofa-hrtf`, `--personalized-headphone`, +`--backend python` and the metadata sidecars (`--metadata-dir`, `--metadata-cache`, +`--metadata-backend sidecar`) are unavailable in this build and fail immediately +with an explanation instead of being ignored. This build adds `--bed` (pre-decoded +6-channel float32 PCM, which skips ffmpeg decoding), `--kernels`, `--work-dir`, +`--report-json`, `--dry-run` and `--quiet`. + +## Library integration + +The engine and the file task are exposed by `joc_core.h`: `joc_task_validate` / +`joc_task_execute` run a file task and report state events through a callback, and +`joc_task_result` carries frame counts, peak, byte count and SHA-256. + +Players and decoder components use `joc_stream.h`: the caller pushes E-AC-3 bytes +and the matching core PCM (or already-rebuilt objects16) at its own pace and pulls +rendered PCM. Any chunking is allowed, and the result is byte-identical to the file +task. + +```c +joc_stream_config config = {0}; +config.struct_size = sizeof(config); +config.input = JOC_STREAM_IN_EAC3; /* or JOC_STREAM_IN_PCM_OBJECTS16 */ +config.output = JOC_STREAM_OUT_SPEAKER; /* or BINAURAL / PCM_OBJECTS16 */ +config.speaker_layout_name = "5.1"; +joc_stream* stream = NULL; +joc_stream_create(&config, &stream); +/* loop: joc_stream_push(...) / joc_stream_pull(...) */ +joc_stream_flush(stream); +joc_stream_destroy(stream); +``` + +Contract: state is instance-private, so streams coexist; push and pull on one +instance must come from the same thread; rendering is stateful, so **this version +offers no seek** - repositioning means decoding from the start of the stream. The +kernel latency is 961 samples for speaker/binaural output and `joc_stream_flush` +drains the binaural room tail. + +## Layout + +```text +include/ public C ABI: joc_core.h (engine/file task), joc_stream.h (streaming), + eac3joc_core.h (upstream ABI) +src/ implementation: eac3_transport, emdf, joc_bitstream, joc_core, oamd, + timeline, speaker, binaural, hrtf, adm, io, telemetry, task, stream, + api, cli, simd +tests/ unit tests (CTest, self-contained, no external data) +docs/ mathematics, the binaural rendering flow and SIMD dispatch +``` + +Eight files under `src/` are byte-identical copies of the upstream JustOneCacophony +native library and are never edited (see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)). + +## Compatibility note + +`object_delay_samples` defaults to **1473**, preserving the behaviour of the existing +implementation; it is a configurable field and changing it changes the OAMD/ADM time +alignment. Upstream investigation suggests the value should be 0; this project keeps +the current default to stay byte-identical. + +## License + +MIT, see [LICENSE](LICENSE). Third-party provenance and patent boundaries are in +[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). diff --git a/README.md b/README.md new file mode 100644 index 0000000..3afc34b --- /dev/null +++ b/README.md @@ -0,0 +1,138 @@ +# JustOneCacophony — C++ Core + +[English](README.en.md) · [数学说明](docs/math.md) · [双耳渲染](docs/binaural.md) · [SIMD 派发](docs/simd.md) + +JustOneCacophony 的 C++ 实现:E-AC-3 JOC 码流解析、对象重建与渲染的执行内核。它从 E-AC-3 +同步帧中提取 EMDF、ID14 JOC 参数与 ID11 OAMD 元数据,结合 FFmpeg 解码出的核心 5.1 PCM +重建 LFE 与 15 路对象 PCM,并输出 ADM BWF、指定扬声器布局的 WAV,或用编译好的 HRTF 方向场 +直接输出双耳 WAV。 + +这是研究代码,不是完整、标准兼容或生产级的 JOC 解码器。它只覆盖已实现的码流形态,遇到未知 +变体时明确报错,而不是假装一切都很和谐。 + +## 构建 + +```powershell +cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release +cmake --build build +ctest --test-dir build --output-on-failure +``` + +Windows(MSVC / VS 2022,静态 CRT)、Linux 与 macOS 由 `.github/workflows/ci.yml` 同时构建并跑 +单元测试;本地只验证 MSVC。浮点行为是逐字节验收的一部分,因此不启用 fast-math:MSVC 用 +`/fp:precise`,其他编译器用 `-fno-fast-math`。 + +Windows Release 默认带 `/arch:AVX2`(`JOC_ENABLE_AVX2`,默认 ON,见 `CMakeLists.txt`)。这个 +开关是逐字节验收过的:所有渲染产物的 SHA-256 完全一致,换来 SOFA 双耳内核 12.4%、Rosella +1.8% 的提升。代价是运行要求——这样的 `joc_core.dll` 会执行 AVX2 指令,在 2013 年以前的 x86 上 +直接非法指令退出。没有运行时派发,一个二进制只能二选一,所以: + +```powershell +cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DJOC_ENABLE_AVX2=OFF +``` + +得到基线 ISA(SSE2)、任何 x86-64 都能跑的产物。非 MSVC 构建永远不会带上这个开关。 + +### 路径与编码 + +库内部所有路径都是 **UTF-8**,只在系统边界转换(`src/foundation/fs_utf8.*`):Windows 上经 +`std::filesystem::path`(内部 UTF-16)落到 `_wfopen`/`CreateProcessW`,其他平台直接是字节。 +命令行参数在 Windows 上由 `GetCommandLineW` + `CommandLineToArgvW` 重新解析,控制台设为 +UTF-8,因此日文/中文等非 ASCII 路径(含 ffmpeg 子进程与输出文件)都能正常工作;单元测试里有 +一条非 ASCII 路径的回归用例守在 `ctest` 里。 + +## 产物 + +| 产物 | 说明 | +|---|---| +| `joc_core.dll` | 执行内核:码流解析、JOC/OAMD、DSP、扬声器与双耳渲染、ADM BWF/WAV 落盘、文件任务、流式接口 | +| `joc_cli.exe` | 文件任务命令行前端 | +| `include/joc_core.h` | 引擎、遥测与文件任务接口(纯 C) | +| `include/joc_stream.h` | 面向嵌入者的流式 push/pull 接口(纯 C,仅包含它即可) | + +## 命令行 + +参数与上游 Python CLI 完全一致:输入是位置参数,**默认输出 25 通道 ADM BWF**,用 +`--speaker-layout` 或 `--binaural` 切换到另外两种模式;未指定 `-o` 时产物落在 `output/`。 + +```powershell +# 默认:ADM BWF(本身就是 24-bit,没有也不需要格式参数) +joc_cli "07. Gold Forever (2021 Master).m4a" +# -> output/07. Gold Forever (2021 Master).adm.wav + +joc_cli input.m4a -o out/adm.wav # 指定输出 + +# 扬声器布局 +joc_cli input.m4a --speaker-layout 5.1 # -> output/<名称>.5.1.wav +joc_cli input.m4a --speaker-layout 7.1.4 --speaker-output out/714.wav --speaker-format int24 + +# 双耳(HRTF 默认取 /HRTF/binaural.sofa,其次 /HRTF/binaural.personalized_headphone) +joc_cli input.m4a --binaural +joc_cli input.m4a --binaural --sofa-hrtf HRTF/other.sofa # 换一个 SOFA +joc_cli input.m4a --binaural --personalized-headphone # Rosella 个性化模型 +# -> output/<名称>.binaural.wav + +# 其它常用开关 +joc_cli input.m4a --duration 30 --gain-db -3 --trajectory-mode dense64 +joc_cli input.eac3 --metadata-only --print-metadata summary # 只解析并打印元数据 +``` + +`--speaker-format` / `--binaural-format` 默认 `float32`;`int24` 若会削波按 `--clip-action` +处理(默认 `ask`,非交互终端下需显式给出 `continue`/`float32`/`abort`)。`--duration` 以**秒** +为单位;`--object-delay-samples`、`--speaker-metadata-offset`、`--binaural-tail-seconds`、 +`--binaural-tail-threshold`(默认 1e-8,双耳尾音裁切阈值)等默认值与上游一致。命令总是写出 +`<输出>.report.json`(`--report-json` 可改路径)。 + +**与上游参数的差异**:`--sofa-hrtf`、`--personalized-headphone`、`--backend python` 以及 +metadata sidecar(`--metadata-dir`/`--metadata-cache`/`--metadata-backend sidecar`)在本构建中 +不可用,给出时立刻报错并说明原因,而不是静默忽略。本构建额外提供 `--bed`(已解码的 6 通道 +float32 PCM,给出后不调用 ffmpeg 解码)、`--kernels`(滤波器组表路径)、`--work-dir`、 +`--report-json`、`--dry-run`、`--quiet`。 + +## 库集成 + +引擎与文件任务使用 `joc_core.h`:`joc_task_validate` / `joc_task_execute` 跑一个文件任务并 +通过回调返回状态事件,`joc_task_result` 给出帧数、峰值、字节数与 SHA-256。 + +播放器或解码组件使用 `joc_stream.h`:调用方按自己的节奏推入 E-AC-3 字节与对应的核心 PCM +(或已重建的 objects16),再拉取渲染后的 PCM;分块粒度任意,输出与文件任务逐字节一致。 + +```c +joc_stream_config config = {0}; +config.struct_size = sizeof(config); +config.input = JOC_STREAM_IN_EAC3; /* 或 JOC_STREAM_IN_PCM_OBJECTS16 */ +config.output = JOC_STREAM_OUT_SPEAKER; /* 或 BINAURAL / PCM_OBJECTS16 */ +config.speaker_layout_name = "5.1"; +joc_stream* stream = NULL; +joc_stream_create(&config, &stream); +/* 循环:joc_stream_push(...) / joc_stream_pull(...) */ +joc_stream_flush(stream); +joc_stream_destroy(stream); +``` + +契约:状态实例私有、可并存;同一实例的 push/pull 必须在同一线程;渲染是有状态的, +因此**本版本不提供 seek**——定位需要从流起点重新解码。扬声器/双耳通路的内核延迟为 +961 样本,`joc_stream_flush` 负责排空双耳房间尾音。 + +## 目录 + +```text +include/ 公共 C ABI:joc_core.h(引擎/文件任务)、joc_stream.h(流式)、eac3joc_core.h(上游 ABI) +src/ 实现:eac3_transport、emdf、joc_bitstream、joc_core、oamd、timeline、speaker、 + binaural、hrtf、adm、io、telemetry、task、stream、api、cli、simd +tests/ 单元测试(CTest,自足,不需要外部素材) +docs/ 数学说明、双耳渲染流程与 SIMD 派发 +``` + +`src/` 下 8 个文件是 JustOneCacophony 原生库的逐字节副本,永不修改(见 +[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md))。 + +## 兼容性说明 + +`object_delay_samples` 默认 **1473**,与既有实现的行为保持一致;它是可配置字段,改动它会 +改变 OAMD/ADM 时间对齐。上游调查认为该值应为 0,本项目为保持逐字节等价暂不改默认值。 + +## 许可 + +MIT,见 [LICENSE](LICENSE);第三方来源与专利边界见 +[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。 diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..00def60 --- /dev/null +++ b/THIRD_PARTY_NOTICES.md @@ -0,0 +1,62 @@ +# Third-party notices / 第三方通知 + +本仓库包含 JustOneCacophony 原生库的逐字节副本(下称"复用文件"),以及遵循公开标准实现的 +滤波器组表。本文件记录这些来源、公开标准依据与权利边界。 + +## 复用文件 + +以下文件是本项目(JustOneCacophony,MIT)原生 C++ 库的逐字节副本,不修改、不追加注释: + +| 本仓库路径 | 上游路径 | SHA-256(前 16 位) | +|---|---|---| +| `src/joc_core/eac3joc_core.cpp` | `native/src/eac3joc_core.cpp` | `1978eea64a2616fa` | +| `src/joc_core/qmf_tables.h` | `native/src/qmf_tables.h` | `c205ea187e956e87` | +| `src/speaker/speaker_renderer.cpp` | `native/src/speaker_renderer.cpp` | `96f36f40daf86eec` | +| `src/speaker/speaker_layouts.h` | `native/src/speaker_layouts.h` | `51e24c11be09787f` | +| `src/binaural/binaural_renderer.cpp` | `native/src/binaural_renderer.cpp` | `d579803f0f5a6699` | +| `src/joc_bitstream/joc_huffman_tables.h` | `native/src/joc_huffman_tables.h` | `698498b3778d88db` | +| `include/eac3joc_core.h` | `native/include/eac3joc_core.h` | `7392f48dfd840656` | + +上游修订:`6bc2c2885666bb151bb66af93472199af9a99b81`。 + +## 派生文件 + +`src/binaural/sofa_binaural_renderer.cpp` 是上游 `native/src/sofa_binaural_renderer.cpp` 的派生 +实现:同一 `ejoc_sofa_binaural_*` C ABI,增加表提升、结果记忆化、输入校验与 SIMD 派发。它 +**不属于**逐字节副本,也不受"不得修改"约束,但来源固定为上述上游修订,对应上游源文件的 +SHA-256 为 `81b485e4c71907672ab308ddc382284acf29161cee93d7906785a4cce58941c7`,输出与原 +实现逐位相同(见该文件头部的验证记录)。 + +## 公开标准来源 + +64-QMF → 77-hybrid 结构与 13-tap 低带 prototype 定义于 +[3GPP TS 26.405 / ETSI TS 126 405](https://www.etsi.org/deliver/etsi_ts/126400_126499/126405/06.00.00_60/ts_126405v060000p.pdf) +第 5.2.2 节(Table 1 的 $Q=8$/$Q=4$ 系数,delay 6): + +$$G_q^p[n] = g^p[n]\cdot\exp\Bigl(j\,\frac{2\pi}{Q^p}\bigl(q+\tfrac12\bigr)(n-6)\Bigr)$$ + +64-band QMF analysis 即 ISO/IEC 14496-3/AMD1:2003 第 4.B.18.2 节的 MPEG-4 +AAC/SBR 64 complex QMF bank;打包的 $64\times10$ 表是公开 640-tap prototype 的多相重排: + +$$A_{r,t} = \frac{(-1)^t}{128}\,c_{63-r+64t}$$ + +QMF synthesis 表为 analysis 多相矩阵 $\mathbf{A}$ 的因果左逆 +$\mathbf{A}\,\mathbf{W}=\mathbf{P}$($\mathbf{P}$ 为 577-sample 延迟置换; +全链 $961 = 577 + 6\times64$),rank-4 分解存储: + +$$W_{b,l} = \sum_{r=1}^{4} t_{b,l,r}\,\mathbf{b}_{b,r}^{\top}$$ + +hybrid synthesis 表为 77→64 重组:高频带恒等 $Y_{3+b}=X_{16+b}$,低频带: + +$$Y_p = \sum_{q\in C_p}\Bigl(\mathrm{Re}X_q + j\,s_q\,\mathrm{Im}X_q\Bigr),\qquad s_q\in\{\pm1\}$$ + +相同数值可在 FFmpeg(`aacps_tablegen.h`、`aacsbrdata.h`)等公开实现中查到。 + +## HRTF 数据与 `.jochrtf` + +`.jochrtf` 含有特定源 SOFA/HRTF 数据集的变换系数与 delay;其使用、复制与再分发仍受源 +数据集许可约束,权限不明确时应作为私有 cache 保存。本仓库不分发任何 HRTF 数据集。 + +## 专利说明 + +标准可公开获取不等于获准实施相关专利。 diff --git a/docs/binaural.en.md b/docs/binaural.en.md new file mode 100644 index 0000000..1d891cc --- /dev/null +++ b/docs/binaural.en.md @@ -0,0 +1,246 @@ +# Binaural rendering + +[中文](binaural.md) · [Back to README](../README.en.md) + +JustOneCacophony's binaural backend supports three HRTF sources: +`SimpleFreeFieldHRIR` SOFA, the Rosella `.personalized_headphone` model exported +by Dolby's official personalization scan (its JSON parsing is implemented by +this project and invokes no Dolby software), and the `.jochrtf` cache compiled +from SOFA. SOFA is compiled into an in-memory directional field when the model +is loaded. A `.jochrtf` file is only a disposable, reproducible JOC compiled +HRTF cache; it is neither an interchange format nor a prerequisite for using +SOFA. + +```text +SOFA FIR + -> CanonicalHrtf + -> 48 kHz / one radius shell / delay-phase policy + -> 64-QMF / 77-hybrid projection + -> fifth-order ACN/N3D real-SH field + -> per-object direct + early reflections + -> shared unitary-FDN late room + -> float64 stereo +``` + +## Inputs + +The binaural backend consumes a compiled directional field (a JOC compiled HRTF cache, +`.jochrtf`) plus the shared filterbank tables. Both are read-only inputs: this library +performs no parsing or conversion of measurement data formats. + +```powershell +joc_cli input.m4a --binaural ` + --compiled-hrtf-cache path\to\subject.jochrtf ` + --kernels data\rosella_kernels.npz ` + --binaural-mode mid --binaural-tail-seconds 5.0 +``` + +The library exposes the same fields: `joc_task_config` for a file task, +`joc_stream_config` for streaming, where `hrtf_path`, `kernels_path`, +`binaural_mode` and `binaural_tail_seconds` configure the binaural path. + +The `.jochrtf` file is an **input**, not a product of this library: compiling it from +SOFA data or measurements belongs to the toolchain and is decoupled from this +repository. Loading validates the member set, dtypes and shapes, C-contiguity, +CRC-32 and a payload hash recomputed over the members (see `.jochrtf` below). + +`binaural_mode` is `near`, `mid` or `far` and selects one of the backend's three +preset parameter sets; `binaural_tail_seconds` sets the room-tail length drained on +flush (default 5.0 s). + +## Binaural render mode + +`--binaural-mode off|near|mid|far` (default `mid`) is a **human-specified +rendering hint**, not original binaural metadata extracted or recovered from the +input E-AC-3 JOC bitstream: + +- Direct binaural rendering (`--binaural`): near/mid/far apply, default `mid`; + `off` is an error; +- ADM BWF: the low 3 binaural-render-mode bits of the last 15 JOC object entries + in DBMD segment 10 carry `off=0/near=1/far=2/mid=3`, leaving the first 10 bed + entries unchanged; the default is `mid`, and `off` explicitly disables the + binaural metadata hint. + +## Canonical SOFA contract + +The strict importer currently accepts: + +- `Conventions=SOFA`; +- `SOFAConventions=SimpleFreeFieldHRIR`, version `0.4`, `1.0`, or `1.1`; +- `DataType=FIR` and `Data.IR[M,2,N]`; +- one positive finite `Data.SamplingRate` in hertz/Hz; +- spherical or Cartesian `SourcePosition`; +- singleton or per-measurement `ListenerPosition/View/Up`; +- two receivers whose listener-local lateral geometry uniquely identifies L/R; +- one zero-offset emitter; +- causal `Data.Delay[I,2]` or `[M,2]`; +- an explicitly free-field/anechoic `RoomType`. + +Receiver order comes from geometry, never from the receiver array index. SOFA +listener coordinates are $+X$ front, +$+Y$ left, +$+Z$ up; ADM coordinates are +$+X$ right, +$+Y$ front, +$+Z$ up: + +$$\bigl(x_{\mathrm{SOFA}},\ y_{\mathrm{SOFA}},\ z_{\mathrm{SOFA}}\bigr) = \bigl(y_{\mathrm{ADM}},\ -x_{\mathrm{ADM}},\ z_{\mathrm{ADM}}\bigr)$$ + +`CanonicalHrtf` keeps `Data.IR` and `Data.Delay` separate. Only a time-domain +baseline calls `materialized_measurement()` to apply delay once; the runtime SH +path never materializes and then restores the delay. Non-48-kHz HRIRs are +normalized with float64 `scipy.signal.resample_poly`, and delay samples scale by +the same ratio. + +GeneralFIR, BRIR, TF, multiple emitters, ambiguous receivers, and non-free-field +data require convention-specific adapters. They cannot enter the core importer +through a reshape. + +## Exactly-once delay and phase + +The compiler recognizes three mutually exclusive representations: + +1. Nonzero `Data.Delay` is external to `Data.IR`; the FIR is not de-rotated and + runtime applies the delay once. +2. With `Data.Delay=0` and an ordinary positive-onset HRIR, each ear's main peak + supplies arrival time. Compilation separates it and runtime restores it once. + The current threshold is a peak index greater than two samples. +3. With `Data.Delay=0` and both FIRs at a shared sample-zero origin, no external + delay is invented. The authored complex phase stays in the fifth-order field. + +No path may add a second ear delay or phase-group delay. + +## Public filterbank and directional field + +The runtime is fixed at: + +- 48 kHz; +- a 64-sample QMF hop; +- 64-QMF / 77 hybrid bands; +- 961 samples of analysis/synthesis latency; +- fifth order, 36 terms, ACN/N3D real spherical harmonics; +- float64 PCM, delay, SH, and room state; complex128 band transfers and spectra. + +Real and imaginary unit gains for every hybrid band pass through the same +analysis/synthesis chain to form a 154-real-parameter impulse dictionary. The +compiler does not sample 77 FFT bins. Defaults are `1e-3` projection ridge and +`1e-5` SH ridge. Coincident directions are merged before a spherical-Voronoi +weighted ridge fit. + +The fixed resource is `data/rosella_kernels.npz`, which implements publicly +standardized filter banks, computable from the following formulas. + +The hybrid analysis kernels are defined in [3GPP TS 26.405 / ETSI TS 126 405](https://www.etsi.org/deliver/etsi_ts/126400_126499/126405/06.00.00_60/ts_126405v060000p.pdf), +Section 5.2.2 (Table 1 $Q=8$/ +$Q=4$ coefficients, delay 6): + +$$G_q^p[n] = g^p[n]\cdot\exp\Bigl(j\,\frac{2\pi}{Q^p}\bigl(q+\tfrac12\bigr)(n-6)\Bigr),\qquad n=0,\dots,12$$ + +The QMF analysis table is the MPEG-4 AAC/SBR 64 complex QMF bank of +ISO/IEC 14496-3/AMD1:2003, subclause 4.B.18.2, stored as the polyphase +reordering of the public 640-tap prototype $c_0,\dots,c_{639}$: + +$$A_{r,t} = \frac{(-1)^t}{128}\,c_{63-r+64t},\qquad r=0,\dots,63,\ t=0,\dots,9$$ + +The QMF synthesis table is the causal left inverse of the analysis polyphase +matrix $\mathbf{A}$, i.e. the solution of +$\mathbf{A}\,\mathbf{W}=\mathbf{P}$ +($\mathbf{P}$ is the 577-sample delay permutation; total latency +$961 = 577 + 6\times64$), stored as a rank-4 factorization: + +$$W_{b,l} = \sum_{r=1}^{4} t_{b,l,r}\,\mathbf{b}_{b,r}^{\top}$$ + +The hybrid synthesis table is the 77→64 recombination: identity for the high +bands, $Y_{3+b}=X_{16+b}$, and for the low bands( +$C_p$ is the +$8+4+4$ child partition): + +$$Y_p = \sum_{q\in C_p}\Bigl(\mathrm{Re}X_q + j\,s_q\,\mathrm{Im}X_q\Bigr),\qquad s_q\in\{\pm1\}$$ + +The loader verifies the archive and every array by SHA-256; the table version, +all array hashes, and the 77 reference band-center values are part of the cache +key. Public availability of a standard does not by itself grant permission to +practice related patent claims. See +[`data/README.en.md`](../data/README.en.md) and +[`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md) for the sources and the +rights boundary. + +## `.jochrtf` + +A `.jochrtf` file is a pickle-free compressed NumPy archive with an exact member set: + +| key | dtype / shape | +|---|---| +| `metadata_json` | NumPy Unicode scalar containing JSON text (`dtype.kind == "U"`) | +| `band_center_frequencies_hz` | little-endian `float64[77]` | +| `coefficients` | little-endian `complex128[36,2,77]` | +| `delay_coefficients` | little-endian `float64[36,2]` | +| `delay_bounds` | little-endian `float64[2,2]` | + +Metadata uses the `JOC-HRTF-CACHE` magic and records the schema, compiler and +phase-policy versions, ACN/N3D convention, filterbank hashes, SOFA content +SHA-256, sample rate, radius, order, both ridge values, payload hash, and fit +report. Every setting that changes compilation participates in the cache key. +Metadata never persists an absolute local `source_path`; it may keep a display +name only. + +Before constructing a field, the loader uses `allow_pickle=False` and validates +ZIP members and expanded sizes, shapes, dtypes, byte order, contiguous layout, +finite values, delay bounds, band centers, payload hash, and cache key. The +writer uses a same-directory temporary file, `fsync`, a process-held OS file +lock, and atomic `os.replace`. Its hidden `.lock` sidecar may remain and does not +mean that a writer still owns the lock. Outdated, damaged, or mismatched +caches cannot hit. SOFA input rebuilds an invalid cache; an explicitly selected +cache reports the error. + +Deleting a disk cache must not change the field or render produced from the same +SOFA and compiler configuration. + +A `.jochrtf` file contains directional-field coefficients and delay data +transformed from the source HRIRs. Its reproducibility therefore does not make +it licence-free. Creating a cache does not enlarge the rights granted by the +source SOFA/HRTF dataset: use, copying, and redistribution remain subject to +that dataset's terms. If those terms are unclear, keep `.jochrtf` as a private +local cache and do not ship it with the program or another build artifact. +`source_sha256` is only a content-integrity identifier, not proof of provenance +or permission. + +## JOC objects and room behavior + +The production adapter retains the existing JOC schedule: + +- `[1536,16]` input per frame; +- channel 0 is special LFE and channels 1..15 are JOC objects; +- ID11/OAMD positions use a sample-timed timeline; +- source parameters update every 512 samples; +- every object owns independent direct/early history while one late FDN is shared; +- `finish()` drains early/late tails; output gain is explicit, with no implicit + limiter or programme loudness normalization. + +Near/Mid/Far, equal-power direct level, six first-order shoebox image sources, +late sends, the unitary FDN, the 120–180 Hz cosine-squared LFE low-pass, and room +calibration are JOC project-defined behavior, not constants published by SOFA or +Dolby. + +The binaural renderer is implemented inside this library: the filterbank, the SH +directional-field evaluation, the per-object early/direct histories and the shared +FDN all run in `joc_core` (the `ejoc_sofa_binaural_*` kernel), consuming a compiled +directional field and 512-sample metadata updates. + +## Technical references and rights boundary + +- [SOFA SimpleFreeFieldHRIR convention](https://www.sofaconventions.org/mediawiki/index.php/SimpleFreeFieldHRIR) +- [3GPP TS 26.405 / ETSI TS 126 405 (64-QMF/77-hybrid definition)](https://www.etsi.org/deliver/etsi_ts/126400_126499/126405/06.00.00_60/ts_126405v060000p.pdf) +- [Dolby binaural render-mode workflow](https://professionalsupport.dolby.com/s/article/What-is-Binaural-Render-Mode-and-how-do-the-settings-affect-my-mix) +- [EP3090576A1](https://patents.google.com/patent/EP3090576A1/en), used only as + architectural background for direct/early/late, subbands, and FDNs; it does + not establish that any product uses a particular embodiment. + +Public availability of a specification, source file, or patent document does +not by itself authorize copying its contents, redistribution of derivatives, +or practice of patent claims. These technical references grant no patent +licence and make no non-infringement representation. Anyone preparing a release +or product integration must assess the applicable data and software licences, +patent permissions, and freedom to operate. See +[`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md) for the public-standard +provenance and rights boundary. diff --git a/docs/binaural.md b/docs/binaural.md new file mode 100644 index 0000000..f93d193 --- /dev/null +++ b/docs/binaural.md @@ -0,0 +1,211 @@ +# 双耳渲染 + +[English](binaural.en.md) · [返回 README](../README.md) + +JustOneCacophony 的双耳后端支持三种 HRTF 来源:`SimpleFreeFieldHRIR` SOFA、 +杜比官方软件个性化扫描导出的 Rosella `.personalized_headphone`(JSON 解析由本项目 +自行实现,不调用杜比软件),以及从 SOFA 编译出的 `.jochrtf` 缓存。SOFA 在模型加载 +时编译成内存方向场;`.jochrtf` 只是可删除、可重建的 JOC compiled HRTF cache, +不是交换格式,也不是使用 SOFA 的前置步骤。 + +```text +SOFA FIR + -> CanonicalHrtf + -> 48 kHz / 单 radius shell / delay-phase policy + -> 64-QMF / 77-hybrid projection + -> 五阶 ACN/N3D 实球谐场 + -> 逐对象 direct + early reflections + -> shared unitary-FDN late room + -> stereo float64 +``` + +## 输入接口 + +双耳后端消费一个已编译的方向场(JOC compiled HRTF cache,`.jochrtf`)与共享滤波器组表; +两者都是只读输入,本库不做任何测量数据格式的解析或转换: + +```powershell +joc_cli input.m4a --binaural ` + --compiled-hrtf-cache path\to\subject.jochrtf ` + --kernels data\rosella_kernels.npz ` + --binaural-mode mid --binaural-tail-seconds 5.0 +``` + +库接口使用同一组字段:文件任务用 `joc_task_config`,流式用 `joc_stream_config`, +其中 `hrtf_path`、`kernels_path`、`binaural_mode`、`binaural_tail_seconds` 决定双耳通路。 + +`.jochrtf` 是**输入**而不是本库的产物:从 SOFA 或测量数据编译该缓存属于工具链的职责, +与本仓库解耦。缓存加载时会校验成员集合、dtype 与形状、C 连续性、CRC-32 以及按成员重算的 +载荷哈希(见下文 `.jochrtf` 一节)。 + +`binaural_mode` 取 `near`、`mid`、`far`,选择后端的三组预置参数;`binaural_tail_seconds` +决定 flush 时排空的房间尾音长度(默认 5.0 s)。 + +## 双耳渲染模式 + +`--binaural-mode off|near|mid|far`(默认 `mid`)是**人为指定的渲染提示**,不是 +从输入 E-AC-3 JOC 码流提取或还原的原始双耳元数据: + +- 直接双耳渲染(`--binaural`):near/mid/far 生效,默认 `mid`;`off` 报错; +- ADM BWF:DBMD segment 10 中后 15 个 JOC 对象的 binaural render mode 写 + `off=0/near=1/far=2/mid=3`,前 10 个 bed 保持不变,默认 `mid`;`off` 用于显式 + 关闭双耳元数据提示。 + +## Canonical SOFA 契约 + +当前 strict importer 接受: + +- `Conventions=SOFA`; +- `SOFAConventions=SimpleFreeFieldHRIR`,version `0.4`、`1.0` 或 `1.1`; +- `DataType=FIR`,`Data.IR[M,2,N]`; +- 单一正有限 `Data.SamplingRate`,单位为 hertz/Hz; +- spherical 或 Cartesian `SourcePosition`; +- 单值或 per-measurement 的 `ListenerPosition/View/Up`; +- 两个能由 listener-local lateral 坐标唯一识别左右的 receiver; +- 单一且零偏移的 emitter; +- causal `Data.Delay[I,2]` 或 `[M,2]`; +- 明确的 free-field/anechoic `RoomType`。 + +receiver 左右顺序由几何决定,不能假定 `Data.IR` 的 receiver index。SOFA listener +坐标为 $+X$ front、 +$+Y$ left、 +$+Z$ up;ADM 坐标为 +$+X$ right、 +$+Y$ front、 +$+Z$ up,转换为: + +$$\bigl(x_{\mathrm{SOFA}},\ y_{\mathrm{SOFA}},\ z_{\mathrm{SOFA}}\bigr) = \bigl(y_{\mathrm{ADM}},\ -x_{\mathrm{ADM}},\ z_{\mathrm{ADM}}\bigr)$$ + +`CanonicalHrtf` 将 `Data.IR` 与 `Data.Delay` 分开保存。只有时域 baseline 才调用 +`materialized_measurement()` 将 delay 应用一次;运行时 SH 路径不先 materialize。 +非 48 kHz HRIR 使用 float64 `scipy.signal.resample_poly` 规范化,delay samples 按 +相同比例缩放。 + +GeneralFIR、BRIR、TF、多 emitter、多义 receiver 或非 free-field 数据需要单独的 +convention adapter,不能只通过 reshape 进入核心 importer。 + +## Delay/phase:exactly once + +编译器只允许三种互斥语义: + +1. 非零 `Data.Delay` 是 `Data.IR` 外部 delay;FIR 不去旋,运行时应用一次。 +2. `Data.Delay=0` 且 HRIR 有普通正 onset:以每耳 main peak 分离 arrival,拟合后 + 在运行时恢复一次;当前阈值为 peak index 大于 2 samples。 +3. `Data.Delay=0` 且双耳 FIR 共享 sample-0 起点:不发明外部 delay,原 complex + phase 直接进入五阶场。 + +任何路径都不能再叠加第二套 ear delay 或 phase-group delay。 + +## 公开 filterbank 与方向场 + +运行时固定为: + +- 48 kHz; +- 64-sample QMF hop; +- 64-QMF / 77-hybrid; +- analysis/synthesis latency 961 samples; +- 五阶、36 项、ACN/N3D real spherical harmonics; +- PCM、delay、SH、room state 为 float64;频带传递和频域状态为 complex128。 + +每个 hybrid band 的 real/imaginary 单位增益都通过同一套 analysis/synthesis 链生成 +脉冲字典,共 154 个实参数;编译不是直接读取 77 个 FFT bin。默认 projection +ridge 为 `1e-3`,SH ridge 为 `1e-5`。同方向 measurement 先合并,再用球面 Voronoi +面积权重做 ridge fit。 + +固定表位于 `data/rosella_kernels.npz`,实现公开标准化的滤波器组,各表可由如下 +公式计算。 + +hybrid 分析核定义于 [3GPP TS 26.405 / ETSI TS 126 405](https://www.etsi.org/deliver/etsi_ts/126400_126499/126405/06.00.00_60/ts_126405v060000p.pdf) +第 5.2.2 节(Table 1 的 $Q=8$/ +$Q=4$ 系数,delay 6): + +$$G_q^p[n] = g^p[n]\cdot\exp\Bigl(j\,\frac{2\pi}{Q^p}\bigl(q+\tfrac12\bigr)(n-6)\Bigr),\qquad n=0,\dots,12$$ + +QMF analysis 表即 MPEG-4 AAC/SBR(ISO/IEC 14496-3/AMD1:2003 第 4.B.18.2 节) +的 64 complex QMF bank;打包的 $64\times10$ 表是公开 640-tap prototype +$c_0,\dots,c_{639}$ 的多相重排: + +$$A_{r,t} = \frac{(-1)^t}{128}\,c_{63-r+64t},\qquad r=0,\dots,63,\ t=0,\dots,9$$ + +QMF synthesis 表为上述 analysis 多相矩阵 $\mathbf{A}$ 的因果左逆,即求解 +$\mathbf{A}\,\mathbf{W}=\mathbf{P}$( +$\mathbf{P}$ 为 577-sample 延迟置换; +全链 $961 = 577 + 6\times64$),以 rank-4 分解形式存储: + +$$W_{b,l} = \sum_{r=1}^{4} t_{b,l,r}\,\mathbf{b}_{b,r}^{\top}$$ + +hybrid synthesis 表为 77→64 重组:高频带恒等 $Y_{3+b}=X_{16+b}$;低频带( +$C_p$ 为 +$8+4+4$ 子带划分): + +$$Y_p = \sum_{q\in C_p}\Bigl(\mathrm{Re}X_q + j\,s_q\,\mathrm{Im}X_q\Bigr),\qquad s_q\in\{\pm1\}$$ + +loader 校验 archive 和每个数组的 SHA-256;table version、所有数组 hash 与 +77 个 band-center 参考值都属于 cache key。标准可公开获取不等于获准实施相关 +专利;更多来源信息见 [`data/README.md`](../data/README.md) 与 +[`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md)。 + +## `.jochrtf` + +`.jochrtf` 是无 pickle 的压缩 NumPy archive,固定包含: + +| key | dtype / shape | +|---|---| +| `metadata_json` | 含 JSON 文本的 NumPy Unicode scalar(`dtype.kind == "U"`) | +| `band_center_frequencies_hz` | little-endian `float64[77]` | +| `coefficients` | little-endian `complex128[36,2,77]` | +| `delay_coefficients` | little-endian `float64[36,2]` | +| `delay_bounds` | little-endian `float64[2,2]` | + +metadata magic 固定为 `JOC-HRTF-CACHE`,并记录 schema/compiler/phase-policy、 +ACN/N3D、filterbank table hashes、SOFA content SHA-256、采样率、radius、order、 +两个 ridge、payload hash 和 fit report。cache key 覆盖所有会改变编译结果的字段。 +metadata 不保存本机绝对 `source_path`,仅可保存 source display name。 + +loader 使用 `allow_pickle=False`,并在构造对象前检查 ZIP 成员集、解压大小、shape、 +dtype、端序、连续布局、有限值、delay bounds、band centers、payload hash 和 cache +key。writer 使用同目录临时文件、`fsync`、进程持有的 OS 文件锁和原子 +`os.replace`;对应的隐藏 `.lock` sidecar 可保留,但不代表仍有 writer 持锁。 +旧版本、损坏或配置不匹配的 cache 不能命中;从 SOFA 启动时会重建,显式 cache +入口则直接报错。 + +删除磁盘 cache 后,从同一 SOFA 和同一编译配置得到的场与渲染结果不得改变。 + +`.jochrtf` 包含由源 HRIR 变换得到的方向场系数与 delay 数据,因此“可以重建”不表示 +它不受数据许可约束。生成 cache 不会扩大源 SOFA/HRTF 数据集授予的权利;cache 的 +使用、复制和再分发仍须遵守源数据集条款。不能确认条款时,应把 `.jochrtf` 作为本地 +私有 cache,不随程序或构建产物发布。`source_sha256` 只用于内容一致性校验,不是许可 +或来源证明。 + +## JOC 对象与房间 + +生产适配器继续使用现有 JOC 调度: + +- 每帧输入 `[1536,16]`; +- channel 0 是 special LFE,channel 1..15 是 JOC objects; +- ID11/OAMD position 使用 sample-timed timeline; +- 每 512 samples 更新方向/profile; +- 每个对象拥有独立 direct/early history,late FDN 全局共享; +- `finish()` 排空 early/late tail;输出增益显式应用,不隐含 limiter 或节目响度归一化。 + +Near/Mid/Far、equal-power direct level、六面 shoebox 一阶 image source、late send、 +unitary FDN、LFE 120–180 Hz cosine-squared 低通及 room calibration 都是 JOC +项目定义行为,不是 SOFA 或 Dolby 公布常数。 + +双耳渲染在本库内实现:filterbank、SH 方向场求值、逐对象 early/direct 历史与共享 FDN +全部执行于 `joc_core`(`ejoc_sofa_binaural_*` 内核),对外只消费编译好的方向场与 +512-sample 粒度的元数据更新。 + +## 技术引用与权利边界 + +- [SOFA SimpleFreeFieldHRIR convention](https://www.sofaconventions.org/mediawiki/index.php/SimpleFreeFieldHRIR) +- [3GPP TS 26.405 / ETSI TS 126 405(64-QMF/77-hybrid 定义)](https://www.etsi.org/deliver/etsi_ts/126400_126499/126405/06.00.00_60/ts_126405v060000p.pdf) +- [Dolby binaural render mode workflow](https://professionalsupport.dolby.com/s/article/What-is-Binaural-Render-Mode-and-how-do-the-settings-affect-my-mix) +- [EP3090576A1](https://patents.google.com/patent/EP3090576A1/en),仅作 direct/early/late、 + subband 与 FDN 架构背景,不证明某个产品使用特定实施例。 + +规范、源码或专利文献可公开获取,不等于获准复制其内容、再分发派生产物或实施其中的 +专利权利要求。本项目的技术引用本身不授予专利许可,也不作不侵权保证;准备发布或集成 +到产品的一方应自行审查适用的数据许可、软件许可、专利许可及 freedom-to-operate。 +公开标准来源与权利边界见 +[`THIRD_PARTY_NOTICES.md`](../THIRD_PARTY_NOTICES.md)。 diff --git a/docs/math.en.md b/docs/math.en.md new file mode 100644 index 0000000..20e55b1 --- /dev/null +++ b/docs/math.en.md @@ -0,0 +1,607 @@ +# JustOneCacophony — E-AC-3 JOC decoding and rendering mathematics + +[中文](math.md) · [Back to README](../README.en.md) + +This document covers only the signal model and formulas used in the JustOneCacophony research path: how JOC parameters combine with core PCM to reconstruct object signals, and how OAMD coordinates become speaker gains. + +The formulas describe the JOC matrix parameters (both the dense and the sparse differential syntax) and the ordinary point-object paths studied by the project. They are not a complete definition of every E-AC-3 JOC variant. + +## 1. Overall path and notation + +Object reconstruction: + +```text +E-AC-3 core 5.1 PCM + + ID14 JOC matrix parameters + → analysis QMF + → parameter-band expansion and time interpolation + → object matrix + → inverse QMF + → LFE + 15 object PCM channels +``` + +Speaker rendering: + +```text +LFE + 15 object PCM channels + + ID11 OAMD coordinates and update timing + → target-layout region + → equal-power panning + → position compensation + → sample-wise gain ramp + → speaker PCM +``` + +Main notation: + +| Symbol | Meaning | +|---|---| +| $c=0\ldots4$ | core channels L, R, C, Ls, Rs | +| $o=0\ldots14$ | 15 JOC objects | +| $b=0\ldots63$ | complex QMF subbands | +| $t=0\ldots23$ | 24 64-sample slots per frame | +| $p(b)$ | JOC parameter band corresponding to QMF subband $b$ | +| $X_{c,b,t}$ | analysis-QMF value for a core channel | +| $M_{o,c,b,t}$ | object-matrix coefficient | +| $Z_{o,b,t}$ | inverse-QMF input for an object | +| $y_o[n]$ | time-domain object PCM | + +The number of samples in one frame is + +$$ +N_f=1536=24\times64. +$$ + +## 2. JOC matrix parameters + +For every object and data point, the quantized matrix `joc_mix_mtx_q` is defined on $N_q$ quantization levels. The `b_joc_sparse` flag selects one of two differential syntaxes: dense sends one MTX difference per core channel, while sparse sends one active channel plus one coefficient difference per parameter band. + +### 2.1 Dense differential reconstruction + +Let `quant_idx` be $q_i\in\{0,1\}$. The number of quantization levels is + +$$ +N_q= +\begin{cases} +96, & q_i=0,\\ +192, & q_i=1. +\end{cases} +$$ + +The center offset is + +$$ +O_q=\frac{N_q}{2}. +$$ + +For object $o$, data point $d$, core channel $c$, and parameter band $p$, the coded difference $\Delta_{o,d,c,p}$ reconstructs to + +$$ +Q_{o,d,c,0}= +\left(O_q+\Delta_{o,d,c,0}\right)\bmod N_q, +$$ + +$$ +Q_{o,d,c,p}= +\left(Q_{o,d,c,p-1}+\Delta_{o,d,c,p}\right)\bmod N_q, +\qquad p>0. +$$ + +### 2.2 Sparse differential reconstruction + +Let $I_{o,d,p}$ be the `joc_channel_idx` symbol (IDX), $V_{o,d,p}$ the `joc_vec` symbol (VEC), and $N_c\in\lbrace5,7\rbrace$ the number of core channels. Each parameter band has exactly one active channel: + +$$ +A_{o,d,p}= +\begin{cases} +I_{o,d,0}, & p=0,\\ +\left(A_{o,d,p-1}+I_{o,d,p}\right)\bmod N_c, & p>0, +\end{cases} +$$ + +where $I_{o,d,0}$ is a 3-bit absolute channel index and every later IDX symbol is an increment relative to the previous **active channel**. The coefficient is a single accumulator running across parameter bands: + +$$ +\kappa_{o,d,-1}=O^{(s)}_q,\qquad +\kappa_{o,d,p}= +\left(\kappa_{o,d,p-1}+V_{o,d,p}\right)\bmod N_q, +$$ + +with a sparse starting point two quantization levels above the dense center offset: + +$$ +O^{(s)}_q= +\begin{cases} +50, & q_i=0,\\ +100, & q_i=1. +\end{cases} +$$ + +The accumulator is **not** reset when the active channel changes. The complete matrix is + +$$ +Q_{o,d,c,p}= +\begin{cases} +\kappa_{o,d,p}, & c=A_{o,d,p},\\ +\dfrac{N_q}{2}, & c\neq A_{o,d,p}. +\end{cases} +$$ + +Non-active entries take $N_q/2$, which dequantizes to exactly 0. + +### 2.3 Dequantization + +The dequantized matrix coefficient is + +$$ +D_{o,d,c,p}= +\left(Q_{o,d,c,p}-\frac{N_q}{2}\right) +\frac{820}{4096(1+q_i)}. +$$ + +The effective denominator is therefore 4096 in coarse mode and 8192 in fine mode. + +### 2.4 JOC clipgain + +If the clipgain field consists of integer $x$ and mantissa $y$, then + +$$ +G_{\mathrm{clip}}= +1+\frac{y}{32}2^{x-4}. +$$ + +It is applied to object PCM after inverse QMF and does not apply to LFE. + +## 3. Parameter-band expansion and time interpolation + +### 3.1 Parameter bands to QMF subbands + +The JOC matrix is coded in parameter bands, while the QMF contains 64 subbands. Let $p(b)$ identify the parameter band containing subband $b$. A parameter-band coefficient expands as + +$$ +D_{o,d,c,b}=D_{o,d,c,p(b)}. +$$ + +The common 12-band mapping is + +$$ +\begin{aligned} +\mathcal B_0 &= \{0\}, & +\mathcal B_1 &= \{1\}, & +\mathcal B_2 &= \{2\}, & +\mathcal B_3 &= \{3\},\\ +\mathcal B_4 &= \{4,5\}, & +\mathcal B_5 &= \{6,7\}, & +\mathcal B_6 &= \{8,9,10\}, & +\mathcal B_7 &= \{11,12,13\},\\ +\mathcal B_8 &= \{14,15,16,17\}, & +\mathcal B_9 &= \{18,\ldots,22\},\\ +\mathcal B_{10} &= \{23,\ldots,34\}, & +\mathcal B_{11} &= \{35,\ldots,63\}. +\end{aligned} +$$ + +Thus $p(b)=k$ if and only if $b\in\mathcal B_k$. Other parameter-band counts use their corresponding subband boundaries. + +### 3.2 One-data-point interpolation + +Let $P_{o,c,b}$ be the previous frame-end value and $D_{o,c,p(b)}$ the current target. For slot $t=0\ldots23$: + +$$ +\alpha_t=\frac{t+1}{24}, +$$ + +$$ +M_{o,c,b,t}= +(1-\alpha_t)P_{o,c,b} ++\alpha_tD_{o,c,p(b)}. +$$ + +The first slot has therefore advanced by $1/24$ of the ramp, while the last slot equals the current target: + +$$ +M_{o,c,b,23}=D_{o,c,p(b)}. +$$ + +This value then becomes the previous state for the next frame. + +### 3.3 Multiple data points + +When a frame contains two data points, `offset_ts` gives the segment boundary. Each segment uses the same linear relation between the previous and next targets; step mode switches targets at the designated slot. + +## 4. Analysis QMF for core PCM + +The matrix input uses core channels L, R, C, Ls, and Rs; LFE follows a separate path. Core PCM is first scaled as + +$$ +\widetilde x_c[n]=\frac{x_c[n]}{16}. +$$ + +Let $\mathcal A_b$ denote the 64-band analysis-QMF operator with polyphase history state. Then + +$$ +X_{c,b,t}= +\mathcal A_b\left( +\widetilde x_c[64t],\ldots,\widetilde x_c[64t+63]; +\mathbf s^{\mathrm A}_{c,t} +\right). +$$ + +This consists of the analysis window/polyphase stage, modulation, a 64-point FFT, and subband reordering. History state advances continuously across slots and frames. + +## 5. QMF-domain processing of core channels + +L, R, and C are delayed by ten QMF slots before entering the object matrix: + +$$ +\widehat X_{c,b,t}=X_{c,b,t-10}, +\qquad c\in\{L,R,C\}. +$$ + +Ls and Rs use the same ten-slot delay and a $-j$ rotation for $b>0$: + +$$ +\widehat X_{c,b,t}=-jX_{c,b,t-10}, +\qquad c\in\{Ls,Rs\},\ b>0. +$$ + +Band 0 of each surround channel additionally passes through a 21-tap complex FIR: + +$$ +\widehat X_{c,0,t}= +\sum_{k=0}^{20}h_kX_{c,0,t-k}. +$$ + +These delays and filter histories are decoder state and cannot be reset independently for every frame. + +## 6. Object matrix + +For each object $o$, subband $b$, and slot $t$, the object's frequency-domain value is a linear combination of the five core channels: + +$$ +Z_{o,b,t}= +\sum_{c=0}^{4} +M_{o,c,b,t}\widehat X_{c,b,t}. +$$ + +The $1/16$ analysis-input scale is canceled by the $\times16$ factor after inverse QMF, so the matrix itself needs no additional empirical gain. + +## 7. Object inverse QMF + +### 7.1 Subband reorder + +Write the 64 complex subbands as 128 interleaved real values in `src`. For $k=0\ldots31$: + +$$ +\begin{aligned} +\mathrm{zone}[2k] &= \mathrm{src}[4k],\\ +\mathrm{zone}[2k+1] &= -\mathrm{src}[4k+1],\\ +\mathrm{zone}[126-2k] &= \mathrm{src}[4k+2],\\ +\mathrm{zone}[127-2k] &= \mathrm{src}[4k+3]. +\end{aligned} +$$ + +Treat `zone` as 64 complex values and apply an unnormalized 64-point FFT: + +$$ +F_k= +\sum_{n=0}^{63} +\mathrm{zone}_n +\exp\left(-j\frac{2\pi kn}{64}\right). +$$ + +### 7.2 Modulation and synthesis + +Define the rotation coefficient + +$$ +r_k= +\frac12\left( +\sin\frac{\pi k}{128} ++j\cos\frac{\pi k}{128} +\right), +$$ + +and compute + +$$ +R_k=2F_kr_k. +$$ + +Let $\mathcal S$ denote polyphase synthesis with a 640-value synthesis window and cross-slot state: + +$$ +\mathbf y_{o,t}= +\mathcal S\left( +\mathbf R_{o,t},W,\mathbf s^{\mathrm S}_{o,t} +\right). +$$ + +Object output is + +$$ +y_o[64t+r]= +\mathrm{clip}\left( +16\,\mathbf y_{o,t}[r],-1,1 +\right)G_{\mathrm{clip}}, +$$ + +where $r=0\ldots63$. Synthesis state must advance continuously by slot. + +## 8. LFE path + +LFE bypasses the object matrix and inverse QMF and uses a 1217-sample delay. After the input and output scale factors cancel: + +$$ +y_{\mathrm{LFE}}[n]= +\mathrm{clip}\left( +x_{\mathrm{LFE,core}}[n-1217],-1,1 +\right). +$$ + +## 9. OAMD coordinates + +The lateral and longitudinal grids use $N=62$; the height grid uses $N=15$. The quantizer is + +$$ +q_N(k)= +\min\left( +32767, +\left\lfloor\frac{32768k}{N}+\frac12\right\rfloor +\right). +$$ + +OAR coordinates are + +$$ +u=\frac{q_1}{32768}, +\qquad +v=\frac{q_2}{32768}, +\qquad +w=\frac{q_3}{32768}. +$$ + +Their maximum runtime value is $32767/32768$, not exactly 1. + +For conversion to the ADM grid: + +$$ +k_1=\mathrm{round}\left(\frac{62q_1}{32767}\right), +\quad +k_2=\mathrm{round}\left(\frac{62q_2}{32767}\right), +\quad +k_3=\mathrm{round}\left(\frac{15q_3}{32767}\right), +$$ + +$$ +X=2\frac{k_1}{62}-1, +\qquad +Y=1-2\frac{k_2}{62}, +\qquad +Z=\frac{k_3}{15}. +$$ + +The continuous-coordinate relation is + +$$ +u=\frac{X+1}{2}, +\qquad +v=\frac{1-Y}{2}, +\qquad +w=Z. +$$ + +## 10. Equal-power speaker panning + +### 10.1 One-dimensional interpolation + +Let adjacent speaker coordinates be $a_00. +$$ + +### 2.2 Sparse 差分还原 + +令 $I_{o,d,p}$ 为 `joc_channel_idx` 符号(IDX), $V_{o,d,p}$ 为 `joc_vec` 符号(VEC), $N_c\in\lbrace5,7\rbrace$ 为核心声道数。每参数带只有一个 active 声道 + +$$ +A_{o,d,p}= +\begin{cases} +I_{o,d,0}, & p=0,\\ +\left(A_{o,d,p-1}+I_{o,d,p}\right)\bmod N_c, & p>0, +\end{cases} +$$ + +其中 $I_{o,d,0}$ 是 3 bit 绝对声道号,其余 IDX 符号是相对上一个 **active 声道**的增量。系数是一个跨参数带连续的单累加器 + +$$ +\kappa_{o,d,-1}=O^{(s)}_q,\qquad +\kappa_{o,d,p}= +\left(\kappa_{o,d,p-1}+V_{o,d,p}\right)\bmod N_q, +$$ + +sparse 起点比 dense 的中心偏移高两个量化级: + +$$ +O^{(s)}_q= +\begin{cases} +50, & q_i=0,\\ +100, & q_i=1. +\end{cases} +$$ + +active 声道切换时累加器**不**重置。完整矩阵为 + +$$ +Q_{o,d,c,p}= +\begin{cases} +\kappa_{o,d,p}, & c=A_{o,d,p},\\ +\dfrac{N_q}{2}, & c\neq A_{o,d,p}. +\end{cases} +$$ + +非 active 项取 $N_q/2$,即去量化后恰为 0。 + +### 2.3 去量化 + +矩阵系数的去量化值为 + +$$ +D_{o,d,c,p}= +\left(Q_{o,d,c,p}-\frac{N_q}{2}\right) +\frac{820}{4096(1+q_i)}. +$$ + +因此 coarse 模式的有效分母为 4096,fine 模式为 8192。 + +### 2.4 JOC clipgain + +若 clipgain 字段由整数 $x$ 和尾数 $y$ 组成,则 + +$$ +G_{\mathrm{clip}}= +1+\frac{y}{32}2^{x-4}. +$$ + +它在对象 inverse QMF 之后作用于对象 PCM,不作用于 LFE。 + +## 3. 参数带展开与时间插值 + +### 3.1 参数带到 QMF 子带 + +JOC 矩阵按参数带编码,而 QMF 使用 64 个子带。令 $p(b)$ 表示子带 $b$ 所属的参数带,则每个参数带系数展开为 + +$$ +D_{o,d,c,b}=D_{o,d,c,p(b)}. +$$ + +常见的 12-band 映射为 + +$$ +\begin{aligned} +\mathcal B_0 &= \{0\}, & +\mathcal B_1 &= \{1\}, & +\mathcal B_2 &= \{2\}, & +\mathcal B_3 &= \{3\},\\ +\mathcal B_4 &= \{4,5\}, & +\mathcal B_5 &= \{6,7\}, & +\mathcal B_6 &= \{8,9,10\}, & +\mathcal B_7 &= \{11,12,13\},\\ +\mathcal B_8 &= \{14,15,16,17\}, & +\mathcal B_9 &= \{18,\ldots,22\},\\ +\mathcal B_{10} &= \{23,\ldots,34\}, & +\mathcal B_{11} &= \{35,\ldots,63\}. +\end{aligned} +$$ + +其中 $p(b)=k$ 当且仅当 $b\in\mathcal B_k$。其他参数带数使用各自的子带边界。 + +### 3.2 单数据点插值 + +令上一帧末值为 $P_{o,c,b}$,当前目标值为 $D_{o,c,p(b)}$。对时槽 $t=0\ldots23$: + +$$ +\alpha_t=\frac{t+1}{24}, +$$ + +$$ +M_{o,c,b,t}= +(1-\alpha_t)P_{o,c,b} ++\alpha_tD_{o,c,p(b)}. +$$ + +因此第一时槽已经推进 ramp 的 $1/24$,最后一时槽等于当前目标: + +$$ +M_{o,c,b,23}=D_{o,c,p(b)}. +$$ + +该值随后成为下一帧的 previous 状态。 + +### 3.3 多数据点 + +当一帧含两个数据点时,`offset_ts` 给出分段边界。每一段在上一目标和下一目标之间使用相同的线性关系;阶跃模式则在指定时槽直接切换目标。 + +## 4. 核心 PCM 的 analysis QMF + +矩阵输入使用核心声道 L、R、C、Ls、Rs;LFE 走独立路径。核心 PCM 先缩放为 + +$$ +\widetilde x_c[n]=\frac{x_c[n]}{16}. +$$ + +令 $\mathcal A_b$ 表示带 polyphase 历史状态的 64-band analysis-QMF 算子,则 + +$$ +X_{c,b,t}= +\mathcal A_b\left( +\widetilde x_c[64t],\ldots,\widetilde x_c[64t+63]; +\mathbf s^{\mathrm A}_{c,t} +\right). +$$ + +该过程依次包含 analysis window/polyphase、调制、64 点 FFT 和子带重排。历史状态跨时槽和帧连续推进。 + +## 5. 核心声道的 QMF 域处理 + +L、R、C 在进入对象矩阵前延迟 10 个 QMF 时槽: + +$$ +\widehat X_{c,b,t}=X_{c,b,t-10}, +\qquad c\in\{L,R,C\}. +$$ + +Ls、Rs 同样延迟 10 个时槽,并在 $b>0$ 时作 $-j$ 旋转: + +$$ +\widehat X_{c,b,t}=-jX_{c,b,t-10}, +\qquad c\in\{Ls,Rs\},\ b>0. +$$ + +环绕声道的 band 0 还经过 21-tap 复 FIR: + +$$ +\widehat X_{c,0,t}= +\sum_{k=0}^{20}h_kX_{c,0,t-k}. +$$ + +这些延迟和滤波历史属于解码状态,不能按帧独立清零。 + +## 6. 对象矩阵 + +对每个对象 $o$、子带 $b$ 和时槽 $t$,对象频域值为五个核心声道的线性组合: + +$$ +Z_{o,b,t}= +\sum_{c=0}^{4} +M_{o,c,b,t}\widehat X_{c,b,t}. +$$ + +analysis 输入的 $1/16$ 缩放会在 inverse QMF 输出端由 $\times16$ 抵消,因此矩阵本身不需要额外经验增益。 + +## 7. 对象 inverse QMF + +### 7.1 子带重排 + +将 64 个复子带写成 128 个交织实数 `src`。对 $k=0\ldots31$: + +$$ +\begin{aligned} +\mathrm{zone}[2k] &= \mathrm{src}[4k],\\ +\mathrm{zone}[2k+1] &= -\mathrm{src}[4k+1],\\ +\mathrm{zone}[126-2k] &= \mathrm{src}[4k+2],\\ +\mathrm{zone}[127-2k] &= \mathrm{src}[4k+3]. +\end{aligned} +$$ + +把 `zone` 重新视为 64 个复数后执行未归一化 64 点 FFT: + +$$ +F_k= +\sum_{n=0}^{63} +\mathrm{zone}_n +\exp\left(-j\frac{2\pi kn}{64}\right). +$$ + +### 7.2 调制与合成 + +定义旋转系数 + +$$ +r_k= +\frac12\left( +\sin\frac{\pi k}{128} ++j\cos\frac{\pi k}{128} +\right), +$$ + +并计算 + +$$ +R_k=2F_kr_k. +$$ + +令 $\mathcal S$ 表示带 640 项 synthesis window 和跨时槽状态的 polyphase 合成算子: + +$$ +\mathbf y_{o,t}= +\mathcal S\left( +\mathbf R_{o,t},W,\mathbf s^{\mathrm S}_{o,t} +\right). +$$ + +对象输出为 + +$$ +y_o[64t+r]= +\mathrm{clip}\left( +16\,\mathbf y_{o,t}[r],-1,1 +\right)G_{\mathrm{clip}}, +$$ + +其中 $r=0\ldots63$。synthesis 状态必须按时槽连续推进。 + +## 8. LFE 路径 + +LFE 不经过对象矩阵或 inverse QMF,而是使用 1217-sample 延迟。输入与输出端的比例因子抵消后: + +$$ +y_{\mathrm{LFE}}[n]= +\mathrm{clip}\left( +x_{\mathrm{LFE,core}}[n-1217],-1,1 +\right). +$$ + +## 9. OAMD 坐标 + +横向和纵向网格使用 $N=62$,高度网格使用 $N=15$。量化函数为 + +$$ +q_N(k)= +\min\left( +32767, +\left\lfloor\frac{32768k}{N}+\frac12\right\rfloor +\right). +$$ + +OAR 坐标为 + +$$ +u=\frac{q_1}{32768}, +\qquad +v=\frac{q_2}{32768}, +\qquad +w=\frac{q_3}{32768}. +$$ + +其最大运行值为 $32767/32768$,不是精确的 1。 + +转换为 ADM 网格时: + +$$ +k_1=\mathrm{round}\left(\frac{62q_1}{32767}\right), +\quad +k_2=\mathrm{round}\left(\frac{62q_2}{32767}\right), +\quad +k_3=\mathrm{round}\left(\frac{15q_3}{32767}\right), +$$ + +$$ +X=2\frac{k_1}{62}-1, +\qquad +Y=1-2\frac{k_2}{62}, +\qquad +Z=\frac{k_3}{15}. +$$ + +连续坐标关系为 + +$$ +u=\frac{X+1}{2}, +\qquad +v=\frac{1-Y}{2}, +\qquad +w=Z. +$$ + +## 10. 等功率扬声器声像 + +### 10.1 一维插值 + +相邻扬声器坐标为 $a_0.cpp`, implementing the slots you have and leaving the + rest `nullptr` — the dispatcher falls back per kernel (that is how + `qmf_synthesis_basis` is handled in the AVX-512 unit). +2. Add it to `JOC_SIMD_SOURCES` in `CMakeLists.txt` with `JOC_SIMD_HAVE_=1` and + its flag, and extend `Isa`, `isa_rank`, `isa_compiled`, `isa_supported` and the + `JOC_SIMD` name table in `simd.h` / `dispatch.cpp`. +3. Verify: the kernel digests must match the scalar unit byte for byte, and the + reference renders must keep their SHA-256 on every tier. diff --git a/docs/simd.md b/docs/simd.md new file mode 100644 index 0000000..e3066da --- /dev/null +++ b/docs/simd.md @@ -0,0 +1,107 @@ +# SIMD 与运行时派发 + +[English](simd.en.md) · [返回 README](../README.md) + +双耳通路里最重的那几段循环(QMF 分析/合成、混合分析的低频拼接、混合域路径渲染、 +ROOM 的 FFT、球谐对齐)都有一份运行时分派的向量实现:同一份二进制里装多套 ISA 代码, +启动时问一次 CPU,然后选最宽的那套跑。**输出逐字节不变**——这是硬约束,不是目标。 + +```text +JOC_SIMD=auto|scalar|sse2|avx2|avx512|neon 强制某一层(验收用) +JOC_SIMD_LOG=1 打印每个 kernel 实际生效的 ISA +``` + +## 为什么必须"按编译单元分 ISA" + +MSVC 没有 `__attribute__((target("avx2")))` 这类函数级多版本能力,一个 .cpp 只能有 +一个 `/arch`。所以每个 ISA 一个编译单元,各自带自己的 `/arch:AVX2` / `/arch:AVX512` +(GCC/Clang 是 `-mavx2` / `-mavx512f`),由 `dispatch.cpp` 在运行时填函数表。 +基线单元(含派发器本身、CPU 探测、标量参考实现)**不带任何 `/arch`**,它们只使用 +x86-64 架构保证的 SSE2。 + +历史坑:早先的 `JOC_ENABLE_AVX2` 是**全局**的,一旦打开,连"给老 CPU 用"的基线路径 +都带 AVX2 指令。现在这个选项只决定是否把 AVX2 单元编进二进制。 + +## 目录布局 + +一个扁平目录,**ISA 写在文件名里,不写进子目录**——这是 FLAC 的做法 +(`src/libFLAC/lpc.c` 旁边就是 `lpc_intrin_sse2.c` / `lpc_intrin_avx2.c` / +`lpc_intrin_neon.c`,CPU 探测单独放在 `cpu.c`)。 + +```text +src/simd/ + simd.h 唯一契约头:Isa / Kernel / Kernels / 维度常量 + cpu_probe.{h,cpp} "这台机器能不能跑 ISA X":CPUID+XGETBV / __builtin_cpu_supports / getauxval + dispatch.cpp 策略:JOC_SIMD 解析、回退阶梯、填函数表、日志 + kernels_scalar.cpp 参考实现(Isa::scalar,永远编译、永远可选中) + kernels_intrin_avx2.cpp /arch:AVX2 -mavx2 + kernels_intrin_avx512.cpp /arch:AVX512 -mavx512f + kernels_intrin_neon.cpp AArch64 默认 -march=armv8-a+simd +``` + +`simd.h` 的头注释里有一份同样的模块地图,改布局时两处一起改。 + +模块放在 `src/simd/` 而不是 `src/dsp/simd/`:这些 kernel 被 `foundation/`、`hrtf/`、 +`binaural/` 三个模块共用,是横切的一层,不是 DSP 的子模块(更何况 `src/dsp/` 里除了 +`simd/` 空无一物)。 + +## 三条规则 + +1. **只有 `kernels_intrin_*.cpp` 拿更宽的编译开关。** `CMakeLists.txt` 用 + `set_source_files_properties` 逐个点名,其余目标一律留在架构保证的 ISA 上。 + 任何不属于这个命名却带了宽指令的单元都会被 `devtools/vec/isa_audit.ps1` 判失败。 +2. **ISA 单元里不许有动态初始化。** 它们和基线代码链进同一个镜像,全局构造函数会在 + 派发器看 CPU 之前就跑宽指令。常量表没问题(落在 `.rdata`)。 +3. **逐位一致靠的是 lane 的划分,不是 ISA。** lane 里只能放**互相独立**的输出;单个输出 + 的舍入序列、乘加分离(绝不用 FMA)、求和顺序都保持 `kernels_scalar.cpp` 原样。 + 只改变 double **存放顺序**的布局改造(基函数表转秩小序、抽头表按项序、蝶形因子表 + 按级连续化、ROOM 谱平面改频带主序)是允许的。 + +## 运行时怎么选 + +`dispatch.cpp` 先解析 `JOC_SIMD`(强制一个本机不支持的层会打印诊断并回退,而不是假装 +选中然后崩),再走阶梯 `avx512 → avx2 → sse2 → neon`,每个 kernel 单独挑"已编进本 +二进制 **且** 本机可跑"的最宽实现,挑不到就落到标量参考实现。所以 AVX-512 单元在 +不支持它的 CPU 上只是不被选中,不影响启动。 + +x86 的探测要 CPUID 与 XGETBV **同时**成立:CPUID 说明硅片有这个能力,XCR0 说明操作 +系统会保存对应寄存器状态,缺一个就不能用(否则上下文切换会踩坏别的线程)。AArch64 +不需要探测,ASIMD 是架构基线。 + +`sse2` 是一个有意保留的档位但**没有单独的单元**:128 位 SSE2 寄存器就是标量 double +已经在用的寄存器,SSE2 加宽不了双精度运算,手写只会多出搬运指令,所以它选中的是基线 +单元。 + +## 效果 + +30 s 参考用例,同一二进制只切 `JOC_SIMD`(DSP 阶段 `t_render_dsp`): + +| 用例 | `scalar` | `auto` | DSP 加速 | 端到端墙钟 | +|---|---|---|---|---| +| 双耳 Rosella | 1.256 s | **0.640 s** | **1.96×** | 1.690 → **0.941 s** | +| 双耳 SOFA | 1.560 s | **0.654 s** | **2.39×** | 1.859 → **0.849 s** | +| 扬声器 5.1 / 9.1.6 / ADM | — | — | 1.00× | 0 回归(不走这些 kernel) | + +单看被向量化的循环,红利更大:合成基函数 5.89×、13 抽头低频拼接 4.50×、 +SOFA QMF 合成 4.27×、128 点 FFT 2.24×。整条流水线到不了 8×,是因为相当一部分时间在 +参数设置、直通拷贝、写盘这些没有独立工作项的代码上,以及 SOFA 每次采样的 33 M 次 +sin/cos 按逐位契约不能向量化。 + +## 验证 + +```powershell +$env:JOC_SIMD_LOG='1' # 本机每个 kernel 实际选中的 ISA +$env:JOC_SIMD='scalar' # 强制参考路径:哈希必须一动不动 +pwsh -NoProfile -File devtools\vec\isa_audit.ps1 # 反汇编全部 .obj:0 个无守卫的宽指令 +pwsh -NoProfile -File devtools\vec\sha_matrix.ps1 # 5 档 × 2 渲染,逐字节比对参考摘要 +cmd /c devtools\vec\build_kernel_probe.bat # kernel 级逐字节摘要(8 个 kernel) +``` + +## 加一个新的 ISA + +1. 写 `kernels_intrin_.cpp`,实现能实现的槽位,其余留 `nullptr`——派发器会逐 + kernel 回退(AVX-512 单元里的 `qmf_synthesis_basis` 就是这么处理的)。 +2. 在 `CMakeLists.txt` 里加进 `JOC_SIMD_SOURCES`、`JOC_SIMD_HAVE_=1` 和它的编译 + 开关,并在 `simd.h` / `dispatch.cpp` 里补上 `Isa`、`isa_rank`、`isa_compiled`、 + `isa_supported` 与 `JOC_SIMD` 名字表。 +3. 验证:kernel 摘要必须与标量逐字节相同,参考渲染在每个档位上的 SHA-256 都不能变。 diff --git a/include/eac3joc_core.h b/include/eac3joc_core.h new file mode 100644 index 0000000..53e8bd4 --- /dev/null +++ b/include/eac3joc_core.h @@ -0,0 +1,235 @@ +#pragma once + +#include + +#if defined(_WIN32) + #if defined(EJOC_BUILD_DLL) + #define EJOC_API __declspec(dllexport) + #else + #define EJOC_API __declspec(dllimport) + #endif + #define EJOC_CALL __cdecl +#else + #define EJOC_API __attribute__((visibility("default"))) + #define EJOC_CALL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + EJOC_ABI_VERSION = 1, + EJOC_FRAME_SAMPLES = 1536, + EJOC_TIMESLOTS = 24, + EJOC_SUBBANDS = 64, + EJOC_CORE_CHANNELS = 5, + EJOC_OUTPUT_CHANNELS = 16, + EJOC_MAX_OBJECTS = 15, + EJOC_MAX_DPOINTS = 2, + EJOC_MAX_PARAMETER_BANDS = 23, + EJOC_SPEAKER_BLOCK_SAMPLES = 32, + EJOC_SPEAKER_COORDINATES = 3, + EJOC_BINAURAL_BLOCK_SAMPLES = 512, + EJOC_BINAURAL_INPUT_CHANNELS = 16, + EJOC_BINAURAL_OUTPUT_CHANNELS = 2, + EJOC_BINAURAL_QMF_BANDS = 64, + EJOC_BINAURAL_HYBRID_BANDS = 77 +}; + +typedef void* ejoc_renderer_handle; +typedef void* ejoc_speaker_renderer_handle; +typedef void* ejoc_binaural_renderer_handle; + +/* +Fixed array layouts used by ejoc_renderer_process(): + bed5_planar [5][1536] + lfe [1536] or NULL + n_bands [15] + n_dpoints [15] + slope_idx [15] + offset_ts [15][2] + dq [15][2][5][23] + output16 [16][1536] + +Only objects selected by object_mask are read from the descriptor arrays. +dq carries already dequantized matrix coefficients in double precision; the +caller performs the JOC bitstream differential decoding for both dense and +sparse objects, so this ABI is identical for both syntaxes. +*/ + +EJOC_API uint32_t EJOC_CALL ejoc_abi_version(void); +EJOC_API const char* EJOC_CALL ejoc_build_info(void); +EJOC_API ejoc_renderer_handle EJOC_CALL ejoc_renderer_create(void); +EJOC_API void EJOC_CALL ejoc_renderer_destroy(ejoc_renderer_handle handle); +EJOC_API int EJOC_CALL ejoc_renderer_reset(ejoc_renderer_handle handle); +EJOC_API int EJOC_CALL ejoc_renderer_set_threads(ejoc_renderer_handle handle, uint32_t total_threads); +EJOC_API uint32_t EJOC_CALL ejoc_renderer_thread_count(ejoc_renderer_handle handle); +EJOC_API const char* EJOC_CALL ejoc_renderer_last_error(ejoc_renderer_handle handle); + +EJOC_API int EJOC_CALL ejoc_renderer_process( + ejoc_renderer_handle handle, + const float* bed5_planar, + const float* lfe, + uint32_t object_mask, + const uint8_t* n_bands, + const uint8_t* n_dpoints, + const uint8_t* slope_idx, + const uint8_t* offset_ts, + const double* dq, + double clipgain, + float phase_new, + float output_scale, + float* output16_planar); + +/* +High-precision object-to-speaker renderer. + +The renderer consumes interleaved float32 input PCM arranged as: + objects16_interleaved [sample_count][16] +where channel 0 is LFE and channels 1..15 are point objects. All spatial +calculations, gain ramps, and accumulation use double. Output is interleaved: + output_interleaved [sample_count][layout_channel_count] + +Each metadata entry is a complete object-state snapshot: + metadata_offsets [metadata_count], relative to this process call + ramp_durations [metadata_count], in samples + positions_q15 [metadata_count][15][3] + region_indices [metadata_count][15] or NULL (all region 0) + height_enabled [metadata_count][15] or NULL (all enabled) + object_gains [metadata_count][15] or NULL (all 1.0) + +metadata_offsets must be nondecreasing and <= sample_count. sample_count must +be a multiple of EJOC_SPEAKER_BLOCK_SAMPLES. State and unfinished ramps are +preserved across calls. +*/ +EJOC_API uint32_t EJOC_CALL ejoc_speaker_layout_channel_count(uint32_t speaker_bitfield); +EJOC_API ejoc_speaker_renderer_handle EJOC_CALL ejoc_speaker_renderer_create(uint32_t speaker_bitfield); +EJOC_API void EJOC_CALL ejoc_speaker_renderer_destroy(ejoc_speaker_renderer_handle handle); +EJOC_API int EJOC_CALL ejoc_speaker_renderer_reset(ejoc_speaker_renderer_handle handle); +EJOC_API const char* EJOC_CALL ejoc_speaker_renderer_last_error(ejoc_speaker_renderer_handle handle); +EJOC_API int EJOC_CALL ejoc_speaker_renderer_process( + ejoc_speaker_renderer_handle handle, + const float* objects16_interleaved, + uint32_t sample_count, + uint32_t metadata_count, + const uint32_t* metadata_offsets, + const uint32_t* ramp_durations, + const uint16_t* positions_q15, + const uint8_t* region_indices, + const uint8_t* height_enabled, + const double* object_gains, + double* output_interleaved); + +EJOC_API ejoc_binaural_renderer_handle EJOC_CALL ejoc_binaural_renderer_create(void); +EJOC_API void EJOC_CALL ejoc_binaural_renderer_destroy(ejoc_binaural_renderer_handle handle); +EJOC_API int EJOC_CALL ejoc_binaural_renderer_reset(ejoc_binaural_renderer_handle handle); +EJOC_API const char* EJOC_CALL ejoc_binaural_renderer_last_error( + ejoc_binaural_renderer_handle handle); +EJOC_API int EJOC_CALL ejoc_binaural_renderer_configure_kernels( + ejoc_binaural_renderer_handle handle, + const double* qmf_analysis, + const double* hybrid_low, + const int16_t* hybrid_indices, + const double* hybrid_values, + uint32_t hybrid_count, + const double* qmf_basis, + const double* qmf_taps); +EJOC_API int EJOC_CALL ejoc_binaural_renderer_configure_room( + ejoc_binaural_renderer_handle handle, + uint32_t bands, + uint32_t allpass_count, + const uint32_t* allpass_delays, + const double* allpass_gains, + const uint32_t* fdn_delays, + const double* fdn_matrix, + uint32_t output_tap_delay, + const double* feedback_complex, + const double* output_taps, + const double* output_complex, + uint32_t extra_count, + const uint32_t* extra_delays, + const double* extra_fields_complex, + const double* extra_matrices); +EJOC_API int EJOC_CALL ejoc_binaural_renderer_process( + ejoc_binaural_renderer_handle handle, + const double* input16_interleaved, + const double* gains_complex, + const double* room_sends, + double output_gain, + double* output_stereo_interleaved); + +/* +Native SOFA binaural renderer. + +The handle owns the complete runtime: 64-QMF/77-hybrid analysis and synthesis, +fifth-order ACN/N3D real spherical-harmonic direction-field evaluation, +per-object whole-QMF-slot delay histories, six first-order image-source early +reflections, the shared unitary-FDN late room, the 120-180 Hz LFE low-pass and +the 961-sample latency compensation. The caller configures the filterbank +tables, the compiled HRTF field and the room constants once, then per 512-sample +block updates every source with ejoc_sofa_binaural_set_source() and calls +ejoc_sofa_binaural_process(). Process returns the number of trimmed stereo +samples written; the first 961 processed samples across calls are discarded. +*/ +typedef void* ejoc_sofa_binaural_handle; + +EJOC_API ejoc_sofa_binaural_handle EJOC_CALL ejoc_sofa_binaural_create(void); +EJOC_API void EJOC_CALL ejoc_sofa_binaural_destroy(ejoc_sofa_binaural_handle handle); +EJOC_API int EJOC_CALL ejoc_sofa_binaural_reset(ejoc_sofa_binaural_handle handle); +EJOC_API const char* EJOC_CALL ejoc_sofa_binaural_last_error( + ejoc_sofa_binaural_handle handle); +EJOC_API int EJOC_CALL ejoc_sofa_binaural_configure_kernels( + ejoc_sofa_binaural_handle handle, + const double* qmf_analysis, + const double* hybrid_low, + const int16_t* hybrid_indices, + const double* hybrid_values, + uint32_t hybrid_count, + const double* qmf_basis, + const double* qmf_taps); +EJOC_API int EJOC_CALL ejoc_sofa_binaural_configure_field( + ejoc_sofa_binaural_handle handle, + const double* coefficients, + const double* delay_coefficients, + const double* delay_bounds, + const double* band_centers, + double measurement_radius_m); +EJOC_API int EJOC_CALL ejoc_sofa_binaural_configure_room( + ejoc_sofa_binaural_handle handle, + const double* room_dims, + const double* listener_pos, + const double* wall_gains, + double speed_of_sound, + const uint32_t* fdn_delays, + const double* fdn_feedback, + double damping, + double fdn_output_gain, + const uint32_t* allpass_delays, + const double* allpass_gains, + uint32_t enable_early_reflections, + uint32_t enable_late_room); +EJOC_API int EJOC_CALL ejoc_sofa_binaural_set_source( + ejoc_sofa_binaural_handle handle, + uint32_t source, + const double* position_adm, + uint32_t profile, + double gain, + uint32_t enabled, + uint32_t special_lfe, + uint32_t fade); +EJOC_API int EJOC_CALL ejoc_sofa_binaural_process( + ejoc_sofa_binaural_handle handle, + const double* input16_interleaved, + uint32_t sample_count, + double output_gain, + double* output_stereo_interleaved); +EJOC_API int EJOC_CALL ejoc_sofa_binaural_finish( + ejoc_sofa_binaural_handle handle, + uint32_t flush_samples, + double* output_stereo_interleaved, + uint32_t capacity); + +#ifdef __cplusplus +} +#endif diff --git a/include/joc_core.h b/include/joc_core.h new file mode 100644 index 0000000..c5cf216 --- /dev/null +++ b/include/joc_core.h @@ -0,0 +1,486 @@ +/* + * joc_core.h -- JustOneCacophony C++ Core, public ABI. Pure C. + * + * This header is the single authoritative definition of the Core's public + * parameter/error surface. Frontends (thin Python CLI, joc_dump, foobar2000, + * MPV, FFmpeg) only ever fill these POD structs and read these POD results; + * no audio data, no internal DSP concept, and no Python type crosses this + * boundary. + * + * Stability tiers + * --------------- + * [T1] host tier + * joc_abi_version / joc_version_string / joc_build_info, joc_error, + * joc_error_name / joc_error_stage, joc_last_error_detail. + * Stable, versioned, safe for media hosts. + * + * [T2] bitstream / verification tier + * joc_parse_eac3_frame, joc_parse_id14, joc_frame_params, joc_emdf_info. + * These deliberately expose the dequantized JOC matrix coefficients so the + * bitstream front-end can be validated bit-exactly and driven by tooling + * (joc_dump) and A/B harnesses. Media hosts must NOT use this tier; they + * use the task/stream API (added in later milestones). + * + * Conventions + * ----------- + * * every struct's first two fields are struct_size / struct_version; + * * all arrays are fixed size and POD, no pointers, no allocation; + * * every function returns joc_error (JOC_OK == 0); + * * joc_last_error_detail() returns a thread-local message that stays valid + * until the next Core call on the same thread. + */ +#pragma once + +#include +#include + +#define JOC_ABI_VERSION 3u +#define JOC_FRAME_PARAMS_VERSION 1u +#define JOC_EMDF_INFO_VERSION 1u +#define JOC_TASK_CONFIG_VERSION 3u +#define JOC_TASK_RESULT_VERSION 2u +#define JOC_EVENT_VERSION 1u + +#if defined(_WIN32) + #if defined(JOC_BUILD_DLL) + #define JOC_API __declspec(dllexport) + #else + #define JOC_API __declspec(dllimport) + #endif + #define JOC_CALL __cdecl +#else + #define JOC_API __attribute__((visibility("default"))) + #define JOC_CALL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ------------------------------------------------------------------ */ +/* Fixed layout constants (single source of truth for every frontend) */ +/* ------------------------------------------------------------------ */ +enum { + JOC_FRAME_SAMPLES = 1536, /* E-AC-3 frame = 24 * 64 */ + JOC_TIMESLOTS = 24, + JOC_SUBBANDS = 64, + JOC_CORE_CHANNELS = 5, /* L R C Ls Rs (JOC order) */ + JOC_MAX_CORE_CHANNELS = 7, /* dmx_config_idx 1/2/4 declare 7 */ + JOC_OUTPUT_CHANNELS = 16, /* ch0 = LFE, ch1..15 = objects */ + JOC_MAX_OBJECTS = 15, + JOC_MAX_DPOINTS = 2, + JOC_MAX_PARAMETER_BANDS = 23, + JOC_MAX_EMDF_PAYLOADS = 16, + JOC_SPEAKER_BLOCK_SAMPLES = 32, + JOC_BINAURAL_BLOCK_SAMPLES = 512, + JOC_BINAURAL_QMF_BANDS = 64, + JOC_BINAURAL_HYBRID_BANDS = 77, + JOC_QMF_HOP_SAMPLES = 64, + JOC_BINAURAL_LATENCY_SAMPLES = 961, + JOC_LFE_DELAY_SAMPLES = 1217 +}; + +/* ------------------------------------------------------------------ */ +/* [T1] library / error surface */ +/* ------------------------------------------------------------------ */ +typedef enum joc_error { + JOC_OK = 0, + JOC_ERR_INVALID_ARGUMENT, + JOC_ERR_INVALID_CONFIG, + JOC_ERR_OUT_OF_MEMORY, + JOC_ERR_IO, + JOC_ERR_UNSUPPORTED_PLATFORM, + JOC_ERR_LIBRARY_MISSING, + /* input / bitstream */ + JOC_ERR_INPUT_NOT_FOUND, + JOC_ERR_INPUT_FORMAT, + JOC_ERR_EAC3_SYNCFRAME, + JOC_ERR_EMDF_TRANSPORT, + JOC_ERR_EMDF_SYNTAX, + JOC_ERR_JOC_SYNTAX, + JOC_ERR_JOC_UNSUPPORTED_VARIANT, + JOC_ERR_OAMD_SYNTAX, + JOC_ERR_OAMD_UNSUPPORTED_VARIANT, + JOC_ERR_BITSTREAM_TRUNCATED, + JOC_ERR_BITSTREAM_PADDING, + /* resources */ + JOC_ERR_HRTF_NOT_FOUND, + JOC_ERR_HRTF_FORMAT, + JOC_ERR_HRTF_VERSION, + JOC_ERR_HRTF_HASH, + JOC_ERR_HRTF_UNSUPPORTED_CONVENTION, + /* rendering / output */ + JOC_ERR_LAYOUT_UNSUPPORTED, + JOC_ERR_RENDER_FAILED, + JOC_ERR_OUTPUT_OPEN, + JOC_ERR_OUTPUT_WRITE, + JOC_ERR_OUTPUT_CLIP_ABORT, + JOC_ERR_ADM_VALIDATION, + /* task / stream */ + JOC_ERR_CANCELLED, + JOC_ERR_STATE, + JOC_ERR_NOT_SUPPORTED, + JOC_ERR_INTERNAL +} joc_error; + +JOC_API uint32_t JOC_CALL joc_abi_version(void); +JOC_API const char* JOC_CALL joc_version_string(void); +JOC_API const char* JOC_CALL joc_build_info(void); +/* Struct sizes, so a binding can assert its layout matches the library instead of + * assuming (mismatches are otherwise silent memory corruption). */ +JOC_API uint32_t JOC_CALL joc_event_size(void); +JOC_API uint32_t JOC_CALL joc_task_config_size(void); +JOC_API uint32_t JOC_CALL joc_task_result_size(void); +JOC_API const char* JOC_CALL joc_error_name(joc_error code); +JOC_API const char* JOC_CALL joc_error_stage(joc_error code); +/* Thread-local structured detail for the most recent failing call. */ +JOC_API const char* JOC_CALL joc_last_error_detail(void); + +/* ------------------------------------------------------------------ */ +/* [T2] bitstream / verification tier */ +/* ------------------------------------------------------------------ */ + +/* One EMDF payload directory entry. bit_offset is the MSB-first bit + * position of the payload's first byte inside the syncframe, exactly as the + * EMDF container syntax defines it (payloads are not byte aligned in general). */ +typedef struct joc_emdf_payload_info { + uint8_t id; + uint8_t reserved[3]; + uint16_t sample_offset; /* EMDF outer smpoffst, 11 bits */ + uint16_t reserved2; + uint32_t bit_offset; + uint32_t size; /* payload bytes */ +} joc_emdf_payload_info; + +typedef struct joc_emdf_info { + uint32_t struct_size; + uint32_t struct_version; + uint32_t start_bit; /* container syncword bit position */ + uint32_t container_bytes; /* 4 + declared length */ + uint32_t payload_count; + uint32_t reserved; + joc_emdf_payload_info payloads[JOC_MAX_EMDF_PAYLOADS]; +} joc_emdf_info; + +/* Per-object ID14/JOC descriptor plus its dequantized matrix. + * dq[dp][ch][pb] is zero filled outside [0,n_dpoints) x [0,n_channels) x + * [0,n_bands). Absent objects are entirely zero. */ +typedef struct joc_object_params { + uint8_t present; + uint8_t num_bands_idx; + uint8_t n_bands; + uint8_t sparse; /* 0 = dense (MTX), 1 = sparse (IDX+VEC) */ + uint8_t quant_idx; /* 0 = 96 levels, 1 = 192 levels */ + uint8_t slope_idx; /* 0 = interpolate, 1 = step at offset_ts */ + uint8_t num_dpoints_bits; + uint8_t n_dpoints; + uint8_t offset_ts[JOC_MAX_DPOINTS]; + uint8_t reserved[2]; + double dq[JOC_MAX_DPOINTS][JOC_MAX_CORE_CHANNELS][JOC_MAX_PARAMETER_BANDS]; +} joc_object_params; + +typedef struct joc_frame_params { + uint32_t struct_size; + uint32_t struct_version; + uint8_t dmx_config_idx; + uint8_t num_objects_bits; + uint8_t ext_config_idx; + uint8_t n_objects; + uint8_t n_channels; /* 5 or 7 */ + uint8_t clipgain_x_bits; + uint8_t clipgain_y_bits; + uint8_t reserved; + uint32_t seq_count; /* 10-bit JOC sequence counter, parsed only */ + uint32_t present_mask; /* bit i == object i present */ + uint32_t data_end_bits; /* bit position just after joc_data */ + uint32_t trailing_bits; /* bits left after joc_data (padding/ext) */ + uint8_t tail_bytes[8]; /* first up to 8 trailing bytes, for A/B */ + double clipgain; /* 1 + (y/32) * 2^(x-4), bit-exact */ + joc_object_params objects[JOC_MAX_OBJECTS]; +} joc_frame_params; + +/* Parse an EMDF ID14 (JOC) payload. */ +JOC_API joc_error JOC_CALL joc_parse_id14(const uint8_t* payload, size_t payload_size, + joc_frame_params* out_params); + +/* Locate the contiguous JOC EMDF container inside one E-AC-3 syncframe and + * parse its ID14 payload. out_emdf may be NULL. */ +JOC_API joc_error JOC_CALL joc_parse_eac3_frame(const uint8_t* frame, size_t frame_size, + joc_frame_params* out_params, + joc_emdf_info* out_emdf); + +/* Copy one payload's bytes out of a syncframe (MSB-first bit extraction, which + * equals a memcpy for byte-aligned containers). out_size receives the payload + * byte count; pass out == NULL to query only the size. */ +JOC_API joc_error JOC_CALL joc_extract_payload(const uint8_t* frame, size_t frame_size, + const joc_emdf_payload_info* payload, + uint8_t* out, size_t out_capacity, + size_t* out_size); + +/* E-AC-3 syncframe traversal: given the offset of a frame start, report its + * byte length so a host can walk a bare E-AC-3 stream without duplicating + * frmsiz logic. Rejects resynchronisation (no silent recovery). */ +JOC_API joc_error JOC_CALL joc_eac3_frame_bytes(const uint8_t* data, size_t size, + size_t offset, size_t* out_frame_bytes); + +/* Strict trailing-bit check for the JOC payload (A/B robustness corpus). + * Returns JOC_ERR_BITSTREAM_PADDING when more than 7 bits are left over or the + * leftover bits are not zero. */ +JOC_API joc_error JOC_CALL joc_check_id14_padding(const uint8_t* payload, size_t payload_size, + uint32_t* out_trailing_bits); + +/* ================================================================== */ +/* [T1] host tier: task, telemetry and control */ +/* ================================================================== */ + +/* ---- 1. events ---------------------------------------------------- */ +/* + * Events carry state only: frame/sample counters, stage, progress, statistics, + * warnings, errors and paths. Audio never travels through an event; a fixed + * size POD with no pointers keeps that enforceable (see the static assertion in + * the implementation). + */ +typedef enum joc_event_type { + JOC_EV_TASK_STARTED = 0x0001, + JOC_EV_TASK_STATE_CHANGED = 0x0002, + JOC_EV_TASK_COMPLETED = 0x0003, + JOC_EV_TASK_FAILED = 0x0004, + JOC_EV_TASK_CANCELLED = 0x0005, + JOC_EV_INPUT_OPENED = 0x0101, + JOC_EV_METADATA_INDEXED = 0x0103, + JOC_EV_HRTF_LOADED = 0x0110, + JOC_EV_RENDERER_INITIALIZED = 0x0120, + JOC_EV_PROGRESS = 0x0201, + JOC_EV_STAGE_CHANGED = 0x0202, + JOC_EV_JOC_FRAME_STATS = 0x0301, + JOC_EV_OAMD_STATS = 0x0302, + JOC_EV_OUTPUT_STATS = 0x0303, + JOC_EV_OUTPUT_OPENED = 0x0401, + JOC_EV_OUTPUT_FORMAT_DECIDED = 0x0402, + JOC_EV_OUTPUT_FINALIZED = 0x0403, + JOC_EV_LOG = 0x0501, + JOC_EV_WARNING = 0x0502, + JOC_EV_ERROR = 0x0503 +} joc_event_type; + +typedef enum joc_stage { + JOC_STAGE_IDLE = 0, + JOC_STAGE_INPUT = 1, + JOC_STAGE_METADATA = 2, + JOC_STAGE_DECODE = 3, + JOC_STAGE_JOC = 4, + JOC_STAGE_RENDER = 5, + JOC_STAGE_OUTPUT = 6, + JOC_STAGE_DONE = 7 +} joc_stage; + +enum { JOC_LOG_TRACE = 0, JOC_LOG_DEBUG = 1, JOC_LOG_INFO = 2, JOC_LOG_NOTICE = 3, + JOC_LOG_WARNING = 4, JOC_LOG_ERROR = 5, JOC_LOG_FATAL = 6 }; + +typedef struct joc_event { + uint32_t struct_size; + uint32_t type; + uint64_t sequence; + uint64_t timestamp_us; + uint64_t current_frame; + uint64_t total_frames; + uint64_t current_sample; + uint64_t total_samples; + uint32_t stage; + uint32_t backend; + double progress; /* 0..1, -1 = unknown */ + double elapsed_seconds; + double realtime_factor; + uint64_t output_samples; + uint64_t output_bytes; + double output_duration_seconds; + joc_error error_code; + uint32_t log_level; + char stage_name[32]; + char message[256]; +} joc_event; + +typedef void (JOC_CALL *joc_event_fn)(void* user, const joc_event* event); + +typedef struct joc_event_sink { + uint32_t struct_size; + joc_event_fn callback; + void* user; + uint32_t min_type; /* 0 = no filter */ + uint32_t max_type; /* 0 = no filter */ +} joc_event_sink; + +/* ---- 2. cancellation ---------------------------------------------- */ +typedef struct joc_cancel_token joc_cancel_token; + +JOC_API joc_cancel_token* JOC_CALL joc_cancel_token_create(void); +JOC_API void JOC_CALL joc_cancel_token_request(joc_cancel_token* token); +JOC_API int32_t JOC_CALL joc_cancel_token_is_requested(const joc_cancel_token* token); +JOC_API void JOC_CALL joc_cancel_token_destroy(joc_cancel_token* token); + +/* ---- 3. task configuration and results ---------------------------- */ +typedef enum joc_operation { + JOC_OP_ADM_BWF = 0, + JOC_OP_SPEAKER = 1, + JOC_OP_BINAURAL = 2 +} joc_operation; + +typedef enum joc_output_format { + JOC_FORMAT_FLOAT32 = 0, + JOC_FORMAT_PCM24 = 1 +} joc_output_format; + +typedef enum joc_binaural_mode { + JOC_BINAURAL_OFF = 0, + JOC_BINAURAL_NEAR = 1, + JOC_BINAURAL_FAR = 2, + JOC_BINAURAL_MID = 3 +} joc_binaural_mode; + +typedef enum joc_trajectory_mode { + JOC_TRAJECTORY_COMPACT = 0, + JOC_TRAJECTORY_DENSE64 = 1 +} joc_trajectory_mode; + +/* What to do when an int24 WAV would clip (peak outside [-1, 1]). Mirrors the + * reference CLI's --clip-action; ADM BWF output is always int24 and does not + * consult this because no alternative format exists there. */ +typedef enum joc_clip_action { + JOC_CLIP_ASK = 0, /* prompt on stdin; an error when stdin is not a terminal */ + JOC_CLIP_CONTINUE = 1, /* write int24, truncating out-of-range values */ + JOC_CLIP_FLOAT32 = 2, /* switch the output to float32 */ + JOC_CLIP_ABORT = 3 /* fail the task */ +} joc_clip_action; + +/* Compiled-HRTF cache policy for a SOFA input; the .jochrtf itself is an + * internal artifact of the compile step. */ +typedef enum joc_hrtf_cache_policy { + JOC_HRTF_CACHE_NONE = 0, /* compile and discard */ + JOC_HRTF_CACHE_MEMORY = 1, /* compile and keep in this process (default) */ + JOC_HRTF_CACHE_DISK = 2 /* compile, reuse and write /*.jochrtf */ +} joc_hrtf_cache_policy; + +enum { JOC_TASK_F_SKIP_SHA256 = 1u, JOC_TASK_F_KEEP_INTERMEDIATE = 2u, + JOC_TASK_F_QUIET = 4u, JOC_TASK_F_METADATA_ONLY = 8u }; + +typedef struct joc_task_config { + uint32_t struct_size; + uint32_t struct_version; + + /* input */ + const char* input_path; /* .eac3/.ec3/.m4a/... */ + const char* ffmpeg_path; /* NULL = "ffmpeg" from PATH */ + const char* bed_path; /* NULL = decode the core PCM with ffmpeg */ + const char* work_dir; /* NULL = a temporary directory */ + double eac3_drc_scale; /* 0 = DRC off (reference default) */ + int32_t eac3_target_level; /* -31..0, 0 = not applied */ + + /* output */ + uint32_t operation; + const char* output_path; + uint32_t output_format; /* requested format for speaker/binaural */ + uint32_t flags; + uint32_t clip_action; /* joc_clip_action; JOC_CLIP_ASK by default */ + + /* rendering */ + const char* speaker_layout_name; + uint32_t speaker_metadata_offset; /* default 1473 */ + uint32_t binaural_mode; + const char* hrtf_path; /* .jochrtf */ + const char* kernels_path; /* rosella_kernels.npz */ + double binaural_tail_seconds; /* default 5.0 */ + double binaural_tail_threshold; /* binaural only; 0 disables trimming */ + uint32_t binaural_chunk_frames; /* accepted for CLI parity; no effect */ + + /* ADM */ + uint32_t adm_binaural_mode; /* DBMD segment 10 encoding */ + uint32_t trajectory_mode; + + /* generic */ + uint32_t object_delay_samples; /* default 1473 */ + double gain_db; /* default 0 */ + uint64_t duration_frames; /* 0 = the whole stream */ + uint32_t progress_interval_frames; /* default 1000 */ + uint32_t native_threads; /* 0 = automatic */ + + /* diagnostics */ + uint32_t print_metadata; /* 0 none, 1 summary, 2 per frame */ + const char* metadata_json_path; /* NULL = no JSON summary */ + + joc_cancel_token* cancel; /* optional */ + + /* Binaural HRTF input (config version 2): when hrtf_sofa_path is set the + * library compiles it with hrtf_cache_policy / hrtf_cache_dir / hrtf_radius_m + * and hrtf_path is unused. hrtf_path stays the advanced override that reads + * a .jochrtf directly. */ + const char* hrtf_sofa_path; /* SOFA SimpleFreeFieldHRIR input */ + const char* personalized_headphone_path; /* Rosella .personalized_headphone input */ + const char* hrtf_cache_dir; /* disk policy directory */ + uint32_t hrtf_cache_policy; /* joc_hrtf_cache_policy */ + uint32_t reserved0; + double hrtf_radius_m; /* SOFA measurement-radius shell */ +} joc_task_config; + +typedef enum joc_task_status { + JOC_TASK_OK = 0, + JOC_TASK_FAILED = 1, + JOC_TASK_CANCELLED = 2 +} joc_task_status; + +typedef struct joc_task_result { + uint32_t struct_size; + uint32_t struct_version; + uint32_t status; + uint32_t error_code; + char error_message[512]; + char error_stage[32]; + uint64_t input_frames; + uint64_t output_samples; + double duration_sec; + uint32_t output_format_actual; + double output_peak; + uint64_t output_over_unity_values; + uint64_t output_file_bytes; + char output_sha256[65]; /* empty when skipped */ + uint64_t oamd_payloads; + uint64_t oamd_transitions; + double t_decode_bed; + double t_render; + double t_write; + double t_total; + double t_render_dsp; /* speaker/binaural DSP calls only; 0 for ADM */ + double t_write_file; /* disk writes including the finalize; >= t_write */ +} joc_task_result; + +typedef struct joc_validation_issue { + joc_error code; + uint32_t severity; /* 0 = info, 1 = warning, 2 = error */ + char field[48]; + char message[256]; +} joc_validation_issue; + +/* ---- 4. entry points ---------------------------------------------- */ +/* Fills `issues` (up to `capacity`) and reports how many were produced. + * Returns JOC_OK when no *error*-severity issue was found. */ +JOC_API joc_error JOC_CALL joc_task_validate(const joc_task_config* config, + joc_validation_issue* issues, uint32_t capacity, + uint32_t* count); + +/* Runs the whole task on the calling thread. `sink` may be NULL; `out` may be + * NULL. On cancellation the partial output is removed and JOC_ERR_CANCELLED is + * returned with out->status = JOC_TASK_CANCELLED. */ +JOC_API joc_error JOC_CALL joc_task_execute(const joc_task_config* config, + const joc_event_sink* sink, joc_task_result* out); + +/* Serialises the stable subset of the result as JSON (no environment fields - + * those belong to the frontend). `needed` receives the required size including + * the terminator; a NULL buffer queries only the size. */ +JOC_API joc_error JOC_CALL joc_task_result_to_json(const joc_task_result* result, char* buffer, + size_t capacity, size_t* needed); + +/* The streaming (push/pull) tier lives in "joc_stream.h" so an embedder can + * include the narrow surface without the bitstream/verification tier. */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/include/joc_stream.h b/include/joc_stream.h new file mode 100644 index 0000000..755e984 --- /dev/null +++ b/include/joc_stream.h @@ -0,0 +1,120 @@ +/* + * joc_stream.h -- streaming (push/pull) interface of the JustOneCacophony core. + * + * This is the narrow, embedder-facing surface: a player or decoder component + * includes only this header. It is the same shared library as joc_core.h, split + * so an integrator never has to see the bitstream/verification tier. + * + * A stream is a stateful instance for hosts that cannot wait for a whole file: + * the caller feeds E-AC-3 bytes and the core PCM of the same frames (or already + * rebuilt objects16) and pulls rendered PCM as soon as it is available. It + * mirrors the two library shapes a decoder library normally offers: this + * push/pull form for host-owned I/O, and joc_task_execute() in joc_core.h for + * library-owned file I/O. + * + * Contract: + * - all state is instance-private, so several streams coexist; + * - a stream is NOT thread safe: push and pull must come from one thread; + * - rendering is stateful (matrix interpolation, gain ramps, room tail), so a + * new position on the timeline requires decoding to continue from the start + * of the stream; there is no seek in this version; + * - the kernel latency is 961 samples for speaker/binaural output: the first + * pull after two 512-sample blocks, and flush() drains the binaural tail. + */ +#pragma once + +#include "joc_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct joc_stream joc_stream; + +typedef enum joc_stream_input { + JOC_STREAM_IN_EAC3 = 0, /* bare E-AC-3 syncframes (the metadata stream) */ + JOC_STREAM_IN_PCM_OBJECTS16 = 1, /* 16-channel objects16, decoded by the host */ + JOC_STREAM_IN_CORE_PCM = 3 /* the 5.1 core PCM of the pushed E-AC-3 frames */ +} joc_stream_input; + +typedef enum joc_stream_output { + JOC_STREAM_OUT_PCM_OBJECTS16 = 0, /* planar [16][samples] float32 */ + JOC_STREAM_OUT_SPEAKER = 1, /* interleaved [samples][channels] f32 */ + JOC_STREAM_OUT_BINAURAL = 2 /* interleaved [samples][2] f32 */ +} joc_stream_output; + +typedef struct joc_stream_config { + uint32_t struct_size; + uint32_t struct_version; + uint32_t input; + uint32_t output; + const char* speaker_layout_name; + uint32_t speaker_metadata_offset; /* default 1473 */ + uint32_t binaural_mode; /* near|mid|far; 0 means mid */ + const char* hrtf_path; /* binaural only */ + const char* kernels_path; /* binaural only */ + double binaural_tail_seconds; /* default 5.0 */ + uint32_t object_delay_samples; /* default 1473 */ + double gain_db; /* default 0 */ + uint32_t native_threads; + uint32_t reserved; +} joc_stream_config; + +typedef struct joc_stream_buffer { + uint32_t struct_size; + uint32_t struct_version; + uint32_t kind; /* which joc_stream_input/output this buffer carries */ + uint32_t channels; + uint32_t sample_rate; + uint32_t sample_count; /* in: capacity / out: produced (per channel) */ + uint32_t byte_count; /* in: capacity / out: consumed or produced bytes */ + uint32_t reserved; + const uint8_t* bytes; /* EAC3 input */ + const float* pcm; /* PCM input */ + uint8_t* out_bytes; /* reserved for encoded outputs */ + float* out_pcm; /* PCM output */ +} joc_stream_buffer; + +typedef struct joc_stream_status_info { + uint32_t struct_size; + uint32_t struct_version; + uint64_t frames_in; + uint64_t frames_out; + uint64_t samples_in; + uint64_t samples_out; + uint64_t bytes_in; + uint64_t buffered_samples; /* rendered but not yet pulled, per channel */ + uint64_t oamd_payloads; + uint64_t oamd_transitions; + uint32_t output_channels; + uint32_t ended; /* 1 after flush() */ +} joc_stream_status_info; + +JOC_API joc_error JOC_CALL joc_stream_create(const joc_stream_config* config, joc_stream** out); + +/* Feeds one buffer. Kind selects the path: EAC3 bytes, the core PCM of those + * frames, or objects16. Consumed counts are reported so a caller can resume + * from a partial push. */ +JOC_API joc_error JOC_CALL joc_stream_push(joc_stream* stream, const joc_stream_buffer* input, + uint32_t* consumed_samples, uint32_t* consumed_bytes); + +/* Copies as many rendered samples as fit into `output` (interleaved, or planar + * for PCM_OBJECTS16) and reports how many were produced; 0 means "push more". */ +JOC_API joc_error JOC_CALL joc_stream_pull(joc_stream* stream, joc_stream_buffer* output, + uint32_t* produced_samples); + +/* Marks the end of input and drains whatever the renderer still holds (the + * binaural room tail); pull the remaining samples afterwards. */ +JOC_API joc_error JOC_CALL joc_stream_flush(joc_stream* stream); + +/* Returns the instance to its initial state (kernel, ramps, timeline, room, + * parser, counters) so the same stream can be reused for another pass. */ +JOC_API joc_error JOC_CALL joc_stream_reset(joc_stream* stream); + +JOC_API joc_error JOC_CALL joc_stream_status(const joc_stream* stream, + joc_stream_status_info* out); +JOC_API joc_error JOC_CALL joc_stream_destroy(joc_stream* stream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/src/adm/adm_metadata.cpp b/src/adm/adm_metadata.cpp new file mode 100644 index 0000000..63dedf8 --- /dev/null +++ b/src/adm/adm_metadata.cpp @@ -0,0 +1,333 @@ +#include "adm/adm_metadata.h" + +#include +#include +#include + +#include "foundation/py_num.h" + +namespace joc::adm { + +namespace { + +constexpr const char* kBedNames[10] = { + "RoomCentricLeft", "RoomCentricRight", "RoomCentricCenter", "RoomCentricLFE", + "RoomCentricLeftSideSurround", "RoomCentricRightSideSurround", + "RoomCentricLeftRearSurround", "RoomCentricRightRearSurround", + "RoomCentricLeftTopSurround", "RoomCentricRightTopSurround"}; +constexpr const char* kBedLabels[10] = {"RC_L", "RC_R", "RC_C", "RC_LFE", "RC_Lss", + "RC_Rss", "RC_Lrs", "RC_Rrs", "RC_Lts", "RC_Rts"}; +constexpr double kBedPos[10][3] = {{-1.0, 1.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, + {-1.0, 1.0, -1.0}, {-1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, + {-1.0, -1.0, 0.0}, {1.0, -1.0, 0.0}, {-1.0, 0.0, 1.0}, + {1.0, 0.0, 1.0}}; + +std::string hex4(std::uint32_t value) { + char buffer[16]; + std::snprintf(buffer, sizeof(buffer), "%04x", value); + return std::string(buffer); +} + +std::string hex8(std::uint32_t value) { + char buffer[16]; + std::snprintf(buffer, sizeof(buffer), "%08x", value); + return std::string(buffer); +} + +void put_u16(std::string* out, std::uint16_t value) { + char buffer[2]; + std::memcpy(buffer, &value, 2); + out->append(buffer, 2); +} + +void put_u32(std::string* out, std::uint32_t value) { + char buffer[4]; + std::memcpy(buffer, &value, 4); + out->append(buffer, 4); +} + +std::uint8_t checksum(const std::string& segment) { + int sum = static_cast(segment.size()); + for (const char raw : segment) { + sum += static_cast(raw); + } + return static_cast((~sum + 1) & 0xFF); +} + +} // namespace + +std::string ts(double seconds) { + long long whole = static_cast(seconds); + long long fraction = pynum::py_round((seconds - static_cast(whole)) * 100000.0); + if (fraction >= 100000) { + whole += 1; + fraction = 0; + } + char buffer[32]; + std::snprintf(buffer, sizeof(buffer), "%02lld:%02lld:%02lld.%05lld", whole / 3600, + (whole % 3600) / 60, whole % 60, fraction); + return std::string(buffer); +} + +bool binaural_mode_from_name(const char* name, BinauralMode* out) { + if (name == nullptr || out == nullptr) { + return false; + } + if (std::strcmp(name, "off") == 0) { *out = BinauralMode::Off; return true; } + if (std::strcmp(name, "near") == 0) { *out = BinauralMode::Near; return true; } + if (std::strcmp(name, "far") == 0) { *out = BinauralMode::Far; return true; } + if (std::strcmp(name, "mid") == 0) { *out = BinauralMode::Mid; return true; } + if (std::strcmp(name, "unspecified") == 0) { *out = BinauralMode::Unspecified; return true; } + return false; +} + +std::string build_chna() { + std::string out; + put_u16(&out, static_cast(kTrackCount)); + put_u16(&out, static_cast(kTrackCount)); + for (std::uint32_t i = 0; i < 10; ++i) { + put_u16(&out, static_cast(i + 1)); + out += "ATU_" + hex8(i + 1); + out += "AT_0001" + hex4(0x1001 + i) + "_01"; + out += "AP_00011001"; + out.push_back('\0'); + } + for (std::uint32_t i = 0; i < kObjectCount; ++i) { + put_u16(&out, static_cast(i + 11)); + out += "ATU_" + hex8(i + 11); + out += "AT_0003" + hex4(0x1001 + i) + "_01"; + out += "AP_0003" + hex4(0x1001 + i); + out.push_back('\0'); + } + return out; +} + +Status build_dbmd(std::uint32_t object_count, BinauralMode mode, std::string* out) { + if (out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, "null output"); + } + const std::uint32_t mode_value = static_cast(mode); + if (mode_value > 4u) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, + "invalid JOC binaural render mode"); + } + out->clear(); + put_u32(out, 0x01000006u); + + std::string segment7(96, '\0'); + segment7[1] = static_cast(0x47); + segment7[5] = static_cast(0x60); + segment7[8] = static_cast(0x24); + segment7[9] = static_cast(0x24); + out->push_back(7); + put_u16(out, 96); + out->append(segment7); + out->push_back(static_cast(checksum(segment7))); + + std::string segment9(248, '\0'); + const std::string creator = "Created with EAC3JOC"; + const std::string renderer = "EAC3JOC Python Renderer"; + std::memcpy(&segment9[0], creator.data(), creator.size()); + std::memcpy(&segment9[32], renderer.data(), renderer.size()); + segment9[96] = 2; + segment9[97] = 1; + segment9[98] = 0; + segment9[103] = 0x03; + segment9[106] = 0x01; + segment9[111] = 0x22; + segment9[112] = static_cast(0xFF); + out->push_back(9); + put_u16(out, 248); + out->append(segment9); + out->push_back(static_cast(checksum(segment9))); + + // The reference allocates the body zeroed and then fills only the trailing + // `object_count` bytes with 0x84, so the template region stays zero. + const std::size_t object_body = 5u + 262u + object_count; + std::string segment10(object_body, '\0'); + const std::uint32_t sync = 0xF8726FBDu; + std::memcpy(&segment10[0], &sync, 4); + segment10[4] = static_cast(object_count); + for (std::size_t i = 5u + 262u; i < segment10.size(); ++i) { + segment10[i] = static_cast(0x84); + } + const std::size_t object_modes = 4u + 2u + 1u + 9u * 15u + object_count; + for (std::uint32_t i = 10; i < std::min(object_count, 10u + kObjectCount); ++i) { + const std::size_t index = object_modes + i; + if (index >= segment10.size()) { + return Status::fail(JOC_ERR_INTERNAL, stage::kOutput, "dbmd object slot out of range"); + } + segment10[index] = static_cast((static_cast(segment10[index]) & 0xF8u) | + mode_value); + } + out->push_back(10); + put_u16(out, static_cast(segment10.size())); + out->append(segment10); + out->push_back(static_cast(checksum(segment10))); + out->append("\0\0", 2); + return Status::success(); +} + +std::string build_axml(const std::vector& tracks, double duration_sec, std::uint32_t rate) { + const double scale = static_cast(rate); + std::string out; + out.reserve(64u * 1024u); + const std::string duration_ts = ts(duration_sec); + + out += ""; + out += ""; + out += ""; + out += ""; + out += "ACO_1001"; + out += "ACO_1002"; + out += ""; + out += ""; + out += "AO_1001"; + out += "2"; + out += ""; + out += ""; + for (std::uint32_t i = 0; i < kObjectCount; ++i) { + out += "AO_" + hex4(0x100b + i) + ""; + } + out += "2"; + out += ""; + out += ""; + out += "AP_00011001"; + for (std::uint32_t i = 0; i < 10; ++i) { + out += "ATU_" + hex8(i + 1) + ""; + } + out += ""; + for (std::uint32_t i = 0; i < kObjectCount; ++i) { + out += ""; + out += "AP_0003" + hex4(0x1001 + i) + ""; + out += "ATU_" + hex8(11 + i) + ""; + out += ""; + } + out += ""; + for (std::uint32_t i = 0; i < 10; ++i) { + out += "AC_0001" + hex4(0x1001 + i) + + ""; + } + out += ""; + for (std::uint32_t i = 0; i < kObjectCount; ++i) { + out += ""; + out += "AC_0003" + hex4(0x1001 + i) + + ""; + out += ""; + } + for (std::uint32_t i = 0; i < 10; ++i) { + out += ""; + out += ""; + out += "1"; + out += "" + pynum::format_fixed(kBedPos[i][0], 10) + + ""; + out += "" + pynum::format_fixed(kBedPos[i][1], 10) + + ""; + if (kBedPos[i][2] != 0.0) { + out += "" + pynum::format_fixed(kBedPos[i][2], 10) + + ""; + } + out += std::string("") + kBedLabels[i] + ""; + out += ""; + out += ""; + } + for (std::size_t i = 0; i < tracks.size(); ++i) { + const Track& track = tracks[i]; + out += "(i)) + "\" audioChannelFormatName=\"" + + track.name + "\" typeDefinition=\"Objects\" typeLabel=\"0003\">"; + for (std::size_t k = 0; k < track.blocks.size(); ++k) { + const Keyframe& block = track.blocks[k]; + out += "(i)) + "_" + + hex8(static_cast(k + 1)) + "\" rtime=\"" + + ts(static_cast(block.rtime_samples) / scale) + "\" duration=\"" + + ts(static_cast(block.duration_samples) / scale) + "\">"; + out += "1"; + out += "" + pynum::format_fixed(block.x, 10) + ""; + out += "" + pynum::format_fixed(block.y, 10) + ""; + if (block.z != 0.0) { + out += "" + pynum::format_fixed(block.z, 10) + + ""; + } + out += "(block.interpolation_samples) / scale, + 5) + + "\">1"; + out += ""; + } + out += ""; + } + for (std::uint32_t i = 0; i < 10; ++i) { + out += ""; + out += "AT_0001" + hex4(0x1001 + i) + "_01"; + out += "AP_00011001"; + out += ""; + } + for (std::uint32_t i = 0; i < kObjectCount; ++i) { + out += ""; + out += "AT_0003" + hex4(0x1001 + i) + "_01"; + out += "AP_0003" + hex4(0x1001 + i) + ""; + out += ""; + } + for (std::uint32_t i = 0; i < 10; ++i) { + out += ""; + out += "AS_0001" + hex4(0x1001 + i) + + ""; + out += ""; + } + for (std::uint32_t i = 0; i < kObjectCount; ++i) { + out += ""; + out += "AS_0003" + hex4(0x1001 + i) + + ""; + out += ""; + } + for (std::uint32_t i = 0; i < 10; ++i) { + out += ""; + out += "AC_0001" + hex4(0x1001 + i) + + ""; + out += "AP_00011001"; + out += "AT_0001" + hex4(0x1001 + i) + + "_01"; + out += ""; + } + for (std::uint32_t i = 0; i < kObjectCount; ++i) { + out += ""; + out += "AC_0003" + hex4(0x1001 + i) + + ""; + out += "AP_0003" + hex4(0x1001 + i) + ""; + out += "AT_0003" + hex4(0x1001 + i) + + "_01"; + out += ""; + } + out += ""; + out += ""; + return out; +} + +} // namespace joc::adm diff --git a/src/adm/adm_metadata.h b/src/adm/adm_metadata.h new file mode 100644 index 0000000..8049a7c --- /dev/null +++ b/src/adm/adm_metadata.h @@ -0,0 +1,43 @@ +// Port of src/adm_atmos.py. + +#pragma once + +#include +#include +#include + +#include "foundation/status.h" + +namespace joc::adm { + +inline constexpr int kObjectCount = 15; +inline constexpr std::uint32_t kTrackCount = 25; + +struct Keyframe { + std::int64_t rtime_samples = 0; + double x = 0.0; + double y = 0.0; + double z = 0.0; + std::int64_t duration_samples = 0; + std::int64_t interpolation_samples = 0; +}; + +struct Track { + std::string name; + std::vector blocks; +}; + +// HH:MM:SS.fffff with the reference's truncation + round-half-even carry. +std::string ts(double seconds); + +enum class BinauralMode : std::uint32_t { Off = 0, Near = 1, Far = 2, Mid = 3, Unspecified = 4 }; + +bool binaural_mode_from_name(const char* name, BinauralMode* out); + +std::string build_axml(const std::vector& tracks, double duration_sec, std::uint32_t rate); + +std::string build_chna(); + +Status build_dbmd(std::uint32_t object_count, BinauralMode mode, std::string* out); + +} // namespace joc::adm diff --git a/src/adm/adm_tracks.cpp b/src/adm/adm_tracks.cpp new file mode 100644 index 0000000..fbf0fe5 --- /dev/null +++ b/src/adm/adm_tracks.cpp @@ -0,0 +1,281 @@ +#include "adm/adm_tracks.h" + +#include +#include + +#include "foundation/geometry.h" + +namespace joc::adm { + +namespace { + +struct Point { + std::int64_t sample = 0; + double x = 0.0; + double y = 0.0; + double z = 0.0; + std::int64_t interpolation_samples = 0; +}; + +// otherwise (the reference drops silently). +void append_point(std::vector* points, std::int64_t sample, double x, double y, double z, + std::int64_t interpolation_samples) { + if (!points->empty() && sample == points->back().sample) { + points->back() = Point{sample, x, y, z, interpolation_samples}; + } else if (points->empty() || sample > points->back().sample) { + points->push_back(Point{sample, x, y, z, interpolation_samples}); + } +} + +void lerp(double ax, double ay, double az, double bx, double by, double bz, double amount, + double* x, double* y, double* z) { + *x = ax + (bx - ax) * amount; + *y = ay + (by - ay) * amount; + *z = az + (bz - az) * amount; +} + +void points_to_blocks(const std::vector& points, std::int64_t total_samples, + std::vector* out) { + for (std::size_t index = 0; index < points.size(); ++index) { + const Point& point = points[index]; + const std::int64_t end = + (index + 1 < points.size()) ? points[index + 1].sample : total_samples; + const std::int64_t duration = std::max(0, end - point.sample); + if (duration == 0) { + continue; + } + Keyframe keyframe; + keyframe.rtime_samples = point.sample; + keyframe.x = point.x; + keyframe.y = point.y; + keyframe.z = point.z; + keyframe.duration_samples = duration; + keyframe.interpolation_samples = std::min(point.interpolation_samples, duration); + out->push_back(keyframe); + } +} + +Status non_monotonic(const char* name, const char* message, int object_index, std::int64_t sample, + std::int64_t previous_sample) { + return Status::fail(JOC_ERR_OAMD_UNSUPPORTED_VARIANT, stage::kOamd, + std::string(name) + ": " + message + " (object " + + std::to_string(object_index) + ", sample " + std::to_string(sample) + + ", previous " + std::to_string(previous_sample) + ")"); +} + +} // namespace + +Status expand_compact(const std::vector& events, std::int64_t total_samples, std::uint32_t rate, + std::int64_t update_quantum_samples, std::int64_t object_delay_samples, + int object_index, std::vector* out) { + out->clear(); + const double scale = static_cast(rate); + if (events.empty()) { + Keyframe keyframe; + keyframe.rtime_samples = 0; + keyframe.duration_samples = total_samples; + keyframe.interpolation_samples = 0; + keyframe.x = 0.0; + keyframe.y = 0.0; + keyframe.z = 0.0; + out->push_back(keyframe); + return Status::success(); + } + + std::vector points; + double current[3] = {events[0].x, events[0].y, events[0].z}; + append_point(&points, 0, current[0], current[1], current[2], 0); + + for (std::size_t index = 1; index < events.size(); ++index) { + const OamdEvent& event = events[index]; + const std::int64_t event_start = event.sample + object_delay_samples; + if (event_start >= total_samples) { + break; + } + const std::int64_t effective_ramp = + std::max(0, event.ramp_samples - update_quantum_samples); + const std::int64_t block_start = + event_start + (effective_ramp != 0 ? update_quantum_samples : 0); + if (block_start >= total_samples) { + break; + } + const std::int64_t ramp_end = block_start + effective_ramp; + + if (block_start < points.back().sample) { + return non_monotonic("non_monotonic_compact_position_updates", + "compact object position update moved backwards", object_index, + block_start, points.back().sample); + } + if (index + 1 < events.size()) { + const std::int64_t next_event_start = events[index + 1].sample + object_delay_samples; + const std::int64_t next_effective = + std::max(0, events[index + 1].ramp_samples - update_quantum_samples); + const std::int64_t next_block_start = + next_event_start + (next_effective != 0 ? update_quantum_samples : 0); + if (next_block_start < ramp_end) { + return non_monotonic("overlapping_compact_position_ramps", + "a new position update arrived before the previous compact " + "ramp finished", + object_index, block_start, ramp_end); + } + } + + double target[3] = {event.x, event.y, event.z}; + std::int64_t interpolation = effective_ramp; + const std::int64_t available = total_samples - block_start; + if (effective_ramp > available) { + const double amount = + static_cast(available) / static_cast(effective_ramp); + double x = 0.0; + double y = 0.0; + double z = 0.0; + lerp(current[0], current[1], current[2], event.x, event.y, event.z, amount, &x, &y, &z); + target[0] = x; + target[1] = y; + target[2] = z; + interpolation = available; + } + append_point(&points, block_start, target[0], target[1], target[2], interpolation); + current[0] = event.x; + current[1] = event.y; + current[2] = event.z; + } + + points_to_blocks(points, total_samples, out); + (void)scale; + return Status::success(); +} + +Status expand_dense64(const std::vector& events, std::int64_t total_samples, std::uint32_t rate, + std::int64_t update_quantum_samples, std::int64_t object_delay_samples, + int object_index, std::vector* out) { + out->clear(); + (void)rate; + if (events.empty()) { + Keyframe keyframe; + keyframe.duration_samples = total_samples; + out->push_back(keyframe); + return Status::success(); + } + + std::vector points; + double current[3] = {events[0].x, events[0].y, events[0].z}; + append_point(&points, 0, current[0], current[1], current[2], 0); + + for (std::size_t index = 1; index < events.size(); ++index) { + const OamdEvent& event = events[index]; + const std::int64_t start = event.sample + object_delay_samples; + if (start >= total_samples) { + break; + } + if (start < points.back().sample) { + return non_monotonic("non_monotonic_position_updates", + "object position update moved backwards", object_index, start, + points.back().sample); + } + if (start > points.back().sample) { + append_point(&points, start, current[0], current[1], current[2], 0); + } + const std::int64_t effective_ramp = + std::max(0, event.ramp_samples - update_quantum_samples); + if (effective_ramp == 0) { + append_point(&points, start, event.x, event.y, event.z, 0); + current[0] = event.x; + current[1] = event.y; + current[2] = event.z; + continue; + } + const std::int64_t steps = + (effective_ramp + update_quantum_samples - 1) / update_quantum_samples; + const std::int64_t end = start + steps * update_quantum_samples; + if (index + 1 < events.size()) { + const std::int64_t next_start = events[index + 1].sample + object_delay_samples; + if (next_start < end) { + return non_monotonic("overlapping_position_ramps", + "a new position update arrived before the previous ramp " + "finished", + object_index, start, end); + } + } + std::int64_t future = effective_ramp; + std::int64_t elapsed = 0; + double position[3] = {current[0], current[1], current[2]}; + while (future > 0) { + const double amount = + std::min(static_cast(update_quantum_samples) / static_cast(future), + 1.0); + double x = 0.0; + double y = 0.0; + double z = 0.0; + lerp(position[0], position[1], position[2], event.x, event.y, event.z, amount, &x, &y, + &z); + position[0] = x; + position[1] = y; + position[2] = z; + elapsed += update_quantum_samples; + const std::int64_t sample = start + elapsed; + if (sample >= total_samples) { + break; + } + append_point(&points, sample, position[0], position[1], position[2], + update_quantum_samples); + future -= update_quantum_samples; + } + current[0] = event.x; + current[1] = event.y; + current[2] = event.z; + } + + points_to_blocks(points, total_samples, out); + return Status::success(); +} + +void TrajectoryBuilder::submit_frame(std::int64_t frame_index, const oamd::OamdUpdate* update, + std::int64_t outer_offset) { + std::int64_t event_sample = frame_index * 1536; + std::int64_t ramp_samples = 0; + if (update != nullptr) { + state_.apply(*update); + event_sample += outer_offset + static_cast(update->block_offset_samples); + ramp_samples = static_cast(update->ramp_duration_samples); + } + for (int object = 1; object <= kObjectCount; ++object) { + double x = 0.0; + double y = 0.0; + double z = 0.0; + geometry::q_to_adm_xyz(state_.q(object, 0), state_.q(object, 1), state_.q(object, 2), &x, + &y, &z); + const int slot = object - 1; + if (!has_previous_[slot] || previous_[slot][0] != x || previous_[slot][1] != y || + previous_[slot][2] != z) { + events_[slot].push_back(OamdEvent{event_sample, x, y, z, ramp_samples}); + previous_[slot][0] = x; + previous_[slot][1] = y; + previous_[slot][2] = z; + has_previous_[slot] = true; + } + } +} + +Status TrajectoryBuilder::build(std::int64_t total_samples, TrajectoryMode mode, + std::vector* out) const { + out->clear(); + out->reserve(kObjectCount); + for (int object = 1; object <= kObjectCount; ++object) { + Track track; + track.name = "JOC_Object_" + std::to_string(object); + const Status status = + (mode == TrajectoryMode::Compact) + ? expand_compact(events_[object - 1], total_samples, rate_, quantum_, + object_delay_, object, &track.blocks) + : expand_dense64(events_[object - 1], total_samples, rate_, quantum_, + object_delay_, object, &track.blocks); + if (!status.ok()) { + return status; + } + out->push_back(std::move(track)); + } + return Status::success(); +} + +} // namespace joc::adm diff --git a/src/adm/adm_tracks.h b/src/adm/adm_tracks.h new file mode 100644 index 0000000..a2ebe0e --- /dev/null +++ b/src/adm/adm_tracks.h @@ -0,0 +1,61 @@ +// Port of src/oamd_tracks.py. + +#pragma once + +#include +#include +#include + +#include "adm/adm_metadata.h" +#include "foundation/status.h" +#include "oamd/oamd_parser.h" + +namespace joc::adm { + +struct OamdEvent { + std::int64_t sample = 0; + double x = 0.0; + double y = 0.0; + double z = 0.0; + std::int64_t ramp_samples = 0; +}; + +enum class TrajectoryMode { Compact, Dense64 }; + +// Feeds the same per-frame OAMD state machine the reference's build_adm_tracks +// runs, and records one event per object whenever its coordinates change. +class TrajectoryBuilder { +public: + TrajectoryBuilder(std::uint32_t rate = 48000, std::int64_t update_quantum_samples = 64, + std::int64_t object_delay_samples = 1473) + : rate_(rate), + quantum_(update_quantum_samples), + object_delay_(object_delay_samples) {} + + void submit_frame(std::int64_t frame_index, const oamd::OamdUpdate* update, std::int64_t outer_offset); + + Status build(std::int64_t total_samples, TrajectoryMode mode, std::vector* out) const; + + const std::vector& events(int object_index) const { return events_[object_index]; } + std::uint32_t rate() const { return rate_; } + std::int64_t object_delay_samples() const { return object_delay_; } + +private: + std::uint32_t rate_; + std::int64_t quantum_; + std::int64_t object_delay_; + oamd::OamdState state_; + std::vector events_[kObjectCount]; + bool has_previous_[kObjectCount] = {}; + double previous_[kObjectCount][3] = {}; +}; + +Status expand_compact(const std::vector& events, std::int64_t total_samples, std::uint32_t rate, + std::int64_t update_quantum_samples, std::int64_t object_delay_samples, + int object_index, std::vector* out); + +Status expand_dense64(const std::vector& events, std::int64_t total_samples, std::uint32_t rate, + std::int64_t update_quantum_samples, std::int64_t object_delay_samples, + int object_index, std::vector* out); + +} // namespace joc::adm diff --git a/src/api/joc_api.cpp b/src/api/joc_api.cpp new file mode 100644 index 0000000..a0c56ce --- /dev/null +++ b/src/api/joc_api.cpp @@ -0,0 +1,249 @@ + +#include "joc_core.h" + +#include +#include + +#include "eac3_transport/eac3_reader.h" +#include "emdf/emdf_parser.h" +#include "foundation/status.h" +#include "joc_bitstream/joc_parser.h" + +namespace { + +thread_local std::string g_detail; + +joc_error finish(const joc::Status& status) { + if (status.ok()) { + g_detail.clear(); + return JOC_OK; + } + g_detail.assign(status.stage()); + g_detail.append(": "); + g_detail.append(status.message()); + return status.code(); +} + +joc_error arg_fail(const char* message) { + return finish(joc::Status::fail(JOC_ERR_INVALID_ARGUMENT, "core", message)); +} + +void fill_emdf_info(const joc::emdf::Container& container, joc_emdf_info* out) { + std::memset(out, 0, sizeof(*out)); + out->struct_size = sizeof(joc_emdf_info); + out->struct_version = JOC_EMDF_INFO_VERSION; + out->start_bit = static_cast(container.start_bit); + out->container_bytes = static_cast(container.raw_size); + out->payload_count = static_cast(container.payload_count); + for (std::size_t i = 0; i < container.payload_count; ++i) { + out->payloads[i].id = container.payloads[i].id; + out->payloads[i].sample_offset = container.payloads[i].sample_offset; + out->payloads[i].bit_offset = static_cast(container.payloads[i].bit_offset); + out->payloads[i].size = static_cast(container.payloads[i].size); + } +} + +} // namespace + +extern "C" { + +std::uint32_t JOC_CALL joc_abi_version(void) { return JOC_ABI_VERSION; } + +const char* JOC_CALL joc_version_string(void) { return "0.1.0-m1"; } + +std::uint32_t JOC_CALL joc_event_size(void) { return static_cast(sizeof(joc_event)); } +std::uint32_t JOC_CALL joc_task_config_size(void) { + return static_cast(sizeof(joc_task_config)); +} +std::uint32_t JOC_CALL joc_task_result_size(void) { + return static_cast(sizeof(joc_task_result)); +} + +const char* JOC_CALL joc_build_info(void) { + static const std::string info = [] { + std::string text = "joc_core 0.1.0-m1 ("; +#if defined(_MSC_VER) + text += "msvc " + std::to_string(_MSC_VER); +#elif defined(__clang__) + text += std::string("clang ") + __clang_version__; +#elif defined(__GNUC__) + text += "gcc " + std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__); +#else + text += "unknown-compiler"; +#endif +#if defined(_M_AMD64) || defined(__x86_64__) + text += ", x64"; +#elif defined(_M_ARM64) || defined(__aarch64__) + text += ", arm64"; +#elif defined(_M_IX86) || defined(__i386__) + text += ", x86"; +#endif + text += ", c++"; + text += std::to_string(static_cast(__cplusplus / 100 % 100)); + text += ")"; + return text; + }(); + return info.c_str(); +} + +const char* JOC_CALL joc_error_name(joc_error code) { + switch (code) { + case JOC_OK: return "JOC_OK"; + case JOC_ERR_INVALID_ARGUMENT: return "JOC_ERR_INVALID_ARGUMENT"; + case JOC_ERR_INVALID_CONFIG: return "JOC_ERR_INVALID_CONFIG"; + case JOC_ERR_OUT_OF_MEMORY: return "JOC_ERR_OUT_OF_MEMORY"; + case JOC_ERR_IO: return "JOC_ERR_IO"; + case JOC_ERR_UNSUPPORTED_PLATFORM: return "JOC_ERR_UNSUPPORTED_PLATFORM"; + case JOC_ERR_LIBRARY_MISSING: return "JOC_ERR_LIBRARY_MISSING"; + case JOC_ERR_INPUT_NOT_FOUND: return "JOC_ERR_INPUT_NOT_FOUND"; + case JOC_ERR_INPUT_FORMAT: return "JOC_ERR_INPUT_FORMAT"; + case JOC_ERR_EAC3_SYNCFRAME: return "JOC_ERR_EAC3_SYNCFRAME"; + case JOC_ERR_EMDF_TRANSPORT: return "JOC_ERR_EMDF_TRANSPORT"; + case JOC_ERR_EMDF_SYNTAX: return "JOC_ERR_EMDF_SYNTAX"; + case JOC_ERR_JOC_SYNTAX: return "JOC_ERR_JOC_SYNTAX"; + case JOC_ERR_JOC_UNSUPPORTED_VARIANT: return "JOC_ERR_JOC_UNSUPPORTED_VARIANT"; + case JOC_ERR_OAMD_SYNTAX: return "JOC_ERR_OAMD_SYNTAX"; + case JOC_ERR_OAMD_UNSUPPORTED_VARIANT: return "JOC_ERR_OAMD_UNSUPPORTED_VARIANT"; + case JOC_ERR_BITSTREAM_TRUNCATED: return "JOC_ERR_BITSTREAM_TRUNCATED"; + case JOC_ERR_BITSTREAM_PADDING: return "JOC_ERR_BITSTREAM_PADDING"; + case JOC_ERR_HRTF_NOT_FOUND: return "JOC_ERR_HRTF_NOT_FOUND"; + case JOC_ERR_HRTF_FORMAT: return "JOC_ERR_HRTF_FORMAT"; + case JOC_ERR_HRTF_VERSION: return "JOC_ERR_HRTF_VERSION"; + case JOC_ERR_HRTF_HASH: return "JOC_ERR_HRTF_HASH"; + case JOC_ERR_HRTF_UNSUPPORTED_CONVENTION: return "JOC_ERR_HRTF_UNSUPPORTED_CONVENTION"; + case JOC_ERR_LAYOUT_UNSUPPORTED: return "JOC_ERR_LAYOUT_UNSUPPORTED"; + case JOC_ERR_RENDER_FAILED: return "JOC_ERR_RENDER_FAILED"; + case JOC_ERR_OUTPUT_OPEN: return "JOC_ERR_OUTPUT_OPEN"; + case JOC_ERR_OUTPUT_WRITE: return "JOC_ERR_OUTPUT_WRITE"; + case JOC_ERR_OUTPUT_CLIP_ABORT: return "JOC_ERR_OUTPUT_CLIP_ABORT"; + case JOC_ERR_ADM_VALIDATION: return "JOC_ERR_ADM_VALIDATION"; + case JOC_ERR_CANCELLED: return "JOC_ERR_CANCELLED"; + case JOC_ERR_STATE: return "JOC_ERR_STATE"; + case JOC_ERR_NOT_SUPPORTED: return "JOC_ERR_NOT_SUPPORTED"; + case JOC_ERR_INTERNAL: return "JOC_ERR_INTERNAL"; + default: return "JOC_ERR_UNKNOWN"; + } +} + +const char* JOC_CALL joc_error_stage(joc_error code) { + switch (code) { + case JOC_ERR_EAC3_SYNCFRAME: + case JOC_ERR_INPUT_NOT_FOUND: + case JOC_ERR_INPUT_FORMAT: + return "eac3_transport"; + case JOC_ERR_EMDF_TRANSPORT: + case JOC_ERR_EMDF_SYNTAX: + return "emdf"; + case JOC_ERR_JOC_SYNTAX: + case JOC_ERR_JOC_UNSUPPORTED_VARIANT: + return "joc"; + case JOC_ERR_OAMD_SYNTAX: + case JOC_ERR_OAMD_UNSUPPORTED_VARIANT: + return "oamd"; + case JOC_ERR_BITSTREAM_TRUNCATED: + case JOC_ERR_BITSTREAM_PADDING: + return "bitstream"; + case JOC_ERR_HRTF_NOT_FOUND: + case JOC_ERR_HRTF_FORMAT: + case JOC_ERR_HRTF_VERSION: + case JOC_ERR_HRTF_HASH: + case JOC_ERR_HRTF_UNSUPPORTED_CONVENTION: + return "hrtf"; + case JOC_ERR_LAYOUT_UNSUPPORTED: + case JOC_ERR_RENDER_FAILED: + return "render"; + case JOC_ERR_OUTPUT_OPEN: + case JOC_ERR_OUTPUT_WRITE: + case JOC_ERR_OUTPUT_CLIP_ABORT: + case JOC_ERR_ADM_VALIDATION: + return "output"; + case JOC_ERR_CANCELLED: + case JOC_ERR_STATE: + case JOC_ERR_NOT_SUPPORTED: + case JOC_ERR_INTERNAL: + return "task"; + default: + return "core"; + } +} + +const char* JOC_CALL joc_last_error_detail(void) { return g_detail.c_str(); } + +joc_error JOC_CALL joc_parse_id14(const std::uint8_t* payload, std::size_t payload_size, + joc_frame_params* out_params) { + if (payload == nullptr || out_params == nullptr || payload_size == 0) { + return arg_fail("joc_parse_id14 requires a non-empty payload and an output struct"); + } + return finish(joc::joc::parse_id14(payload, payload_size, out_params, nullptr)); +} + +joc_error JOC_CALL joc_parse_eac3_frame(const std::uint8_t* frame, std::size_t frame_size, + joc_frame_params* out_params, joc_emdf_info* out_emdf) { + if (frame == nullptr || out_params == nullptr || frame_size == 0) { + return arg_fail("joc_parse_eac3_frame requires a frame and an output struct"); + } + joc::emdf::Container container; + const joc::Status status = + joc::joc::parse_eac3_frame(frame, frame_size, out_params, &container, nullptr); + if (!status.ok()) { + return finish(status); + } + if (out_emdf != nullptr) { + fill_emdf_info(container, out_emdf); + } + return JOC_OK; +} + +joc_error JOC_CALL joc_extract_payload(const std::uint8_t* frame, std::size_t frame_size, + const joc_emdf_payload_info* payload, std::uint8_t* out, + std::size_t out_capacity, std::size_t* out_size) { + if (frame == nullptr || payload == nullptr || out_size == nullptr) { + return arg_fail("joc_extract_payload requires frame, payload and out_size"); + } + *out_size = payload->size; + if (out == nullptr) { + return JOC_OK; + } + if (out_capacity < payload->size) { + return arg_fail("joc_extract_payload output buffer too small"); + } + joc::emdf::Payload entry; + entry.id = payload->id; + entry.sample_offset = payload->sample_offset; + entry.bit_offset = payload->bit_offset; + entry.size = payload->size; + std::vector bytes; + const joc::Status status = joc::emdf::extract_payload_bytes(frame, frame_size, entry, &bytes); + if (!status.ok()) { + return finish(status); + } + if (!bytes.empty()) { + std::memcpy(out, bytes.data(), bytes.size()); + } + *out_size = bytes.size(); + return JOC_OK; +} + +joc_error JOC_CALL joc_eac3_frame_bytes(const std::uint8_t* data, std::size_t size, std::size_t offset, + std::size_t* out_frame_bytes) { + if (data == nullptr || out_frame_bytes == nullptr) { + return arg_fail("joc_eac3_frame_bytes requires data and out_frame_bytes"); + } + const joc_error code = joc::eac3::FrameReader::frame_bytes(data, size, offset, out_frame_bytes); + if (code != JOC_OK) { + return finish(joc::Status::fail(code, joc::stage::kEac3, + "invalid or truncated E-AC-3 syncframe at byte " + + std::to_string(offset))); + } + return JOC_OK; +} + +joc_error JOC_CALL joc_check_id14_padding(const std::uint8_t* payload, std::size_t payload_size, + std::uint32_t* out_trailing_bits) { + if (payload == nullptr || payload_size == 0) { + return arg_fail("joc_check_id14_padding requires a payload"); + } + return finish(joc::joc::check_id14_padding(payload, payload_size, out_trailing_bits)); +} + +} // extern "C" diff --git a/src/api/joc_stream_api.cpp b/src/api/joc_stream_api.cpp new file mode 100644 index 0000000..177838c --- /dev/null +++ b/src/api/joc_stream_api.cpp @@ -0,0 +1,152 @@ +#include +#include + +#include "foundation/status.h" +#include "joc_core.h" +#include "joc_stream.h" +#include "stream/stream.h" + +struct joc_stream { + joc::stream::Stream instance; +}; + +namespace { + +joc_error finish_stream(const joc::Status& status) { + return status.code(); +} + +joc::stream::Config to_config(const joc_stream_config& config) { + joc::stream::Config out; + out.input = config.input; + out.output = config.output; + if (config.speaker_layout_name != nullptr) { out.layout = config.speaker_layout_name; } + if (config.speaker_metadata_offset != 0u) { + out.metadata_offset = config.speaker_metadata_offset; + } + out.binaural_mode = config.binaural_mode != 0u ? config.binaural_mode : JOC_BINAURAL_MID; + if (config.hrtf_path != nullptr) { out.hrtf_path = config.hrtf_path; } + if (config.kernels_path != nullptr) { out.kernels_path = config.kernels_path; } + if (config.binaural_tail_seconds > 0.0) { out.tail_seconds = config.binaural_tail_seconds; } + if (config.object_delay_samples != 0u) { + out.object_delay_samples = config.object_delay_samples; + } + out.gain_db = config.gain_db; + out.native_threads = config.native_threads; + return out; +} + +} // namespace + +extern "C" { + +joc_error JOC_CALL joc_stream_create(const joc_stream_config* config, joc_stream** out) { + if (config == nullptr || out == nullptr || config->struct_size != sizeof(joc_stream_config)) { + return JOC_ERR_INVALID_ARGUMENT; + } + auto* stream = new (std::nothrow) joc_stream(); + if (stream == nullptr) { + return JOC_ERR_OUT_OF_MEMORY; + } + const joc::Status status = stream->instance.create(to_config(*config)); + if (!status.ok()) { + delete stream; + return finish_stream(status); + } + *out = stream; + return JOC_OK; +} + +joc_error JOC_CALL joc_stream_push(joc_stream* stream, const joc_stream_buffer* input, + std::uint32_t* consumed_samples, std::uint32_t* consumed_bytes) { + if (stream == nullptr || input == nullptr || + input->struct_size != sizeof(joc_stream_buffer)) { + return JOC_ERR_INVALID_ARGUMENT; + } + const joc::Status status = [&] { + if (input->kind == JOC_STREAM_IN_EAC3) { + std::size_t consumed = 0; + const joc::Status pushed = + stream->instance.push_eac3(input->bytes, input->byte_count, &consumed); + if (consumed_bytes != nullptr) { + *consumed_bytes = static_cast(consumed); + } + return pushed; + } + if (input->kind == JOC_STREAM_IN_PCM_OBJECTS16) { + std::size_t consumed = 0; + const joc::Status pushed = + stream->instance.push_objects16(input->pcm, input->sample_count, &consumed); + if (consumed_samples != nullptr) { + *consumed_samples = static_cast(consumed); + } + return pushed; + } + std::size_t consumed = 0; + const joc::Status pushed = + stream->instance.push_bed(input->pcm, input->sample_count, &consumed); + if (consumed_samples != nullptr) { + *consumed_samples = static_cast(consumed); + } + return pushed; }(); + return finish_stream(status); +} + +joc_error JOC_CALL joc_stream_pull(joc_stream* stream, joc_stream_buffer* output, + std::uint32_t* produced_samples) { + if (stream == nullptr || output == nullptr || output->out_pcm == nullptr || + output->struct_size != sizeof(joc_stream_buffer)) { + return JOC_ERR_INVALID_ARGUMENT; + } + std::size_t produced = 0; + const joc::Status status = + stream->instance.pull(output->out_pcm, output->sample_count, &produced); + if (!status.ok()) { + return finish_stream(status); + } + if (produced_samples != nullptr) { + *produced_samples = static_cast(produced); + } + output->sample_count = static_cast(produced); + return JOC_OK; +} + +joc_error JOC_CALL joc_stream_flush(joc_stream* stream) { + if (stream == nullptr) { + return JOC_ERR_INVALID_ARGUMENT; + } + return finish_stream(stream->instance.flush()); +} + +joc_error JOC_CALL joc_stream_reset(joc_stream* stream) { + if (stream == nullptr) { + return JOC_ERR_INVALID_ARGUMENT; + } + return finish_stream(stream->instance.reset()); +} + +joc_error JOC_CALL joc_stream_status(const joc_stream* stream, joc_stream_status_info* out) { + if (stream == nullptr || out == nullptr || + out->struct_size != sizeof(joc_stream_status_info)) { + return JOC_ERR_INVALID_ARGUMENT; + } + const joc::stream::Info& info = stream->instance.info(); + out->frames_in = info.frames_in; + out->frames_out = info.frames_out; + out->samples_in = info.samples_in; + out->samples_out = info.samples_out; + out->bytes_in = info.bytes_in; + out->buffered_samples = stream->instance.buffered_samples(); + out->oamd_payloads = info.oamd_payloads; + out->oamd_transitions = info.oamd_transitions; + out->output_channels = info.output_channels; + out->ended = info.ended; + return JOC_OK; +} + +joc_error JOC_CALL joc_stream_destroy(joc_stream* stream) { + delete stream; + return JOC_OK; +} + +} // extern "C" diff --git a/src/api/joc_task_api.cpp b/src/api/joc_task_api.cpp new file mode 100644 index 0000000..5e172f1 --- /dev/null +++ b/src/api/joc_task_api.cpp @@ -0,0 +1,120 @@ + +#include +#include +#include +#include +#include + +#include "foundation/status.h" +#include "joc_core.h" +#include "task/task.h" + +// task and whichever frontend wants to stop it (plan 29.1/29.2). +struct joc_cancel_token { + std::atomic requested{0u}; +}; + +namespace { + +thread_local std::string g_task_detail; + +joc_error finish_task(const joc::Status& status) { + if (status.ok()) { + g_task_detail.clear(); + return JOC_OK; + } + g_task_detail.assign(status.stage()); + g_task_detail.append(": "); + g_task_detail.append(status.message()); + return status.code(); +} + +} // namespace + +extern "C" { + +joc_cancel_token* JOC_CALL joc_cancel_token_create(void) { + return new (std::nothrow) joc_cancel_token(); +} + +void JOC_CALL joc_cancel_token_request(joc_cancel_token* token) { + if (token != nullptr) { + token->requested.store(1u, std::memory_order_relaxed); + } +} + +std::int32_t JOC_CALL joc_cancel_token_is_requested(const joc_cancel_token* token) { + return (token != nullptr && token->requested.load(std::memory_order_relaxed) != 0u) ? 1 : 0; +} + +void JOC_CALL joc_cancel_token_destroy(joc_cancel_token* token) { delete token; } + +joc_error JOC_CALL joc_task_validate(const joc_task_config* config, + joc_validation_issue* issues, std::uint32_t capacity, + std::uint32_t* count) { + if (config == nullptr) { + return JOC_ERR_INVALID_ARGUMENT; + } + if (config->struct_size != sizeof(joc_task_config)) { + return JOC_ERR_INVALID_ARGUMENT; + } + std::vector found; + std::uint32_t errors = 0; + const joc::Status status = joc::task::validate(*config, &found, &errors); + if (count != nullptr) { + *count = static_cast(found.size()); + } + if (issues != nullptr) { + for (std::uint32_t i = 0; i < capacity && i < found.size(); ++i) { + issues[i] = found[i]; + } + } + return status.ok() ? JOC_OK : JOC_ERR_INVALID_CONFIG; +} + +joc_error JOC_CALL joc_task_execute(const joc_task_config* config, const joc_event_sink* sink, + joc_task_result* out) { + if (config == nullptr || config->struct_size != sizeof(joc_task_config)) { + return JOC_ERR_INVALID_ARGUMENT; + } + if (out != nullptr) { + std::memset(out, 0, sizeof(*out)); + out->struct_size = sizeof(joc_task_result); + out->struct_version = JOC_TASK_RESULT_VERSION; + } + const joc::Status status = joc::task::run(*config, sink, out); + if (!status.ok() && out != nullptr && out->status == 0u) { + out->status = JOC_TASK_FAILED; + out->error_code = static_cast(status.code()); + std::snprintf(out->error_stage, sizeof(out->error_stage), "%s", status.stage().c_str()); + std::snprintf(out->error_message, sizeof(out->error_message), "%s", + status.message().c_str()); + } + g_task_detail = status.ok() ? std::string() : status.message(); + return status.code(); +} + +joc_error JOC_CALL joc_task_result_to_json(const joc_task_result* result, char* buffer, + std::size_t capacity, std::size_t* needed) { + if (result == nullptr) { + return JOC_ERR_INVALID_ARGUMENT; + } + std::string json; + const joc::Status status = joc::task::result_to_json(*result, &json); + if (!status.ok()) { + return status.code(); + } + if (needed != nullptr) { + *needed = json.size() + 1u; + } + if (buffer == nullptr) { + return JOC_OK; + } + if (capacity < json.size() + 1u) { + return JOC_ERR_INVALID_ARGUMENT; + } + std::memcpy(buffer, json.c_str(), json.size() + 1u); + return JOC_OK; +} + +} // extern "C" diff --git a/src/binaural/binaural_renderer.cpp b/src/binaural/binaural_renderer.cpp new file mode 100644 index 0000000..1456d2a --- /dev/null +++ b/src/binaural/binaural_renderer.cpp @@ -0,0 +1,664 @@ +#define EJOC_BUILD_DLL +#include "eac3joc_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ejoc::binaural { + +struct Complex { + double re; + double im; +}; + +inline Complex add(Complex a, Complex b) noexcept { + return {a.re + b.re, a.im + b.im}; +} + +inline Complex mul(Complex a, Complex b) noexcept { + return {a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re}; +} + +inline Complex scale(Complex value, double gain) noexcept { + return {value.re * gain, value.im * gain}; +} + +constexpr double kPi = 3.141592653589793238462643383279502884; +constexpr int kChannels = EJOC_BINAURAL_INPUT_CHANNELS; +constexpr int kEars = EJOC_BINAURAL_OUTPUT_CHANNELS; +constexpr int kBlock = EJOC_BINAURAL_BLOCK_SAMPLES; +constexpr int kSlots = kBlock / 64; +constexpr int kQmf = EJOC_BINAURAL_QMF_BANDS; +constexpr int kHybrid = EJOC_BINAURAL_HYBRID_BANDS; +constexpr int kRank = 4; + +class Renderer final { +public: + Renderer() noexcept { + initialize_fft(); + reset(); + } + + int configure_kernels( + const double* qmf_analysis, + const double* hybrid_low, + const int16_t* hybrid_indices, + const double* hybrid_values, + uint32_t hybrid_count, + const double* qmf_basis, + const double* qmf_taps) noexcept { + if (!qmf_analysis || !hybrid_low || !hybrid_indices || !hybrid_values || + !qmf_basis || !qmf_taps || hybrid_count == 0) { + return fail("invalid binaural kernel configuration"); + } + std::memcpy(qmf_analysis_.data(), qmf_analysis, + qmf_analysis_.size() * sizeof(double)); + hybrid_low_.assign(hybrid_low, hybrid_low + 3 * 2 * 13 * 16 * 2); + hybrid_indices_.assign(hybrid_indices, hybrid_indices + hybrid_count * 4); + hybrid_values_.assign(hybrid_values, hybrid_values + hybrid_count); + std::memcpy(qmf_basis_.data(), qmf_basis, + qmf_basis_.size() * sizeof(double)); + std::memcpy(qmf_taps_.data(), qmf_taps, + qmf_taps_.size() * sizeof(double)); + kernels_ready_ = true; + reset(); + return 0; + } + + int configure_room( + uint32_t bands, + uint32_t allpass_count, + const uint32_t* allpass_delays, + const double* allpass_gains, + const uint32_t* fdn_delays, + const double* fdn_matrix, + uint32_t output_tap_delay, + const double* feedback_complex, + const double* output_taps, + const double* output_complex, + uint32_t extra_count, + const uint32_t* extra_delays, + const double* extra_fields_complex, + const double* extra_matrices) noexcept { + if (bands != 64 || !fdn_delays || !fdn_matrix || !feedback_complex || + !output_taps || !output_complex || + (allpass_count && (!allpass_delays || !allpass_gains)) || + (extra_count && (!extra_delays || !extra_fields_complex || !extra_matrices))) { + return fail("invalid binaural room configuration"); + } + room_bands_ = bands; + if (allpass_count) { + allpass_delays_.assign(allpass_delays, allpass_delays + allpass_count); + allpass_gains_.assign(allpass_gains, allpass_gains + allpass_count); + } else { + allpass_delays_.clear(); + allpass_gains_.clear(); + } + allpass_offsets_.resize(allpass_count); + allpass_positions_.assign(allpass_count, 0); + size_t allpass_size = 0; + for (uint32_t index = 0; index < allpass_count; ++index) { + if (allpass_delays_[index] == 0) { + return fail("binaural allpass delay must be positive"); + } + allpass_offsets_[index] = allpass_size; + allpass_size += static_cast(allpass_delays_[index]) * bands; + } + allpass_memory_.assign(allpass_size, {}); + + room_capacity_ = 0; + for (int branch = 0; branch < 4; ++branch) { + fdn_delays_[branch] = fdn_delays[branch]; + room_capacity_ = std::max(room_capacity_, fdn_delays_[branch]); + } + if (room_capacity_ == 0) { + return fail("binaural room delay must be positive"); + } + std::copy(fdn_matrix, fdn_matrix + 16, fdn_matrix_.begin()); + output_tap_delay_ = output_tap_delay; + for (int band = 0; band < 64; ++band) { + for (int branch = 0; branch < 4; ++branch) { + const size_t complex_index = (static_cast(band) * 4 + branch) * 2; + feedback_[band][branch] = { + feedback_complex[complex_index], feedback_complex[complex_index + 1]}; + output_taps_[band][branch] = output_taps[band * 4 + branch]; + for (int ear = 0; ear < 2; ++ear) { + const size_t output_index = + ((static_cast(ear) * 64 + band) * 4 + branch) * 2; + output_matrix_[ear][band][branch] = { + output_complex[output_index], output_complex[output_index + 1]}; + } + } + } + room_memory_.assign(static_cast(room_capacity_) * 64 * 4, {}); + if (extra_count) { + extra_delays_.assign(extra_delays, extra_delays + extra_count); + } else { + extra_delays_.clear(); + } + extra_fields_.resize(static_cast(extra_count) * 64); + extra_matrices_.resize(static_cast(extra_count) * 16); + for (uint32_t extra = 0; extra < extra_count; ++extra) { + for (int band = 0; band < 64; ++band) { + const size_t source = (static_cast(extra) * 64 + band) * 2; + extra_fields_[static_cast(extra) * 64 + band] = { + extra_fields_complex[source], extra_fields_complex[source + 1]}; + } + std::copy(extra_matrices + static_cast(extra) * 16, + extra_matrices + static_cast(extra + 1) * 16, + extra_matrices_.begin() + static_cast(extra) * 16); + } + room_ready_ = true; + reset(); + return 0; + } + + int reset() noexcept { + qmf_history_.fill(0.0); + hybrid_low_history_.fill({}); + hybrid_high_history_.fill({}); + synthesis_history_.fill(0.0); + std::fill(allpass_memory_.begin(), allpass_memory_.end(), Complex{}); + std::fill(allpass_positions_.begin(), allpass_positions_.end(), 0u); + std::fill(room_memory_.begin(), room_memory_.end(), Complex{}); + room_position_ = 0; + error_[0] = '\0'; + return 0; + } + + const char* error() const noexcept { + return error_[0] ? error_ : ""; + } + + int process( + const double* input, + const double* gains, + const double* room_sends, + double output_gain, + double* output) noexcept { + if (!kernels_ready_ || !room_ready_) { + return fail("binaural renderer is not configured"); + } + if (!input || !gains || !room_sends || !output || !std::isfinite(output_gain)) { + return fail("invalid binaural process arguments"); + } + for (int slot = 0; slot < kSlots; ++slot) { + std::array qmf{}; + std::array hybrid{}; + analyze_qmf(input + static_cast(slot) * 64 * kChannels, qmf); + analyze_hybrid(qmf, hybrid); + + std::array rendered{}; + std::array room_input{}; + for (int source = kChannels - 1; source >= 0; --source) { + for (int band = 0; band < kHybrid; ++band) { + const Complex value = hybrid[source * kHybrid + band]; + room_input[band] = add(room_input[band], scale(value, room_sends[source])); + for (int ear = 0; ear < kEars; ++ear) { + const size_t gain_index = + (((static_cast(source) * kEars + ear) * kHybrid + band) * 2); + const Complex gain{gains[gain_index], gains[gain_index + 1]}; + rendered[ear * kHybrid + band] = add( + rendered[ear * kHybrid + band], mul(value, gain)); + } + } + } + const auto room = process_room(room_input); + for (size_t index = 0; index < rendered.size(); ++index) { + rendered[index] = add(rendered[index], room[index]); + } + + std::array qmf_output{}; + synthesize_hybrid(rendered, qmf_output); + for (int ear = 0; ear < kEars; ++ear) { + std::array samples{}; + synthesize_qmf(qmf_output.data() + ear * kQmf, ear, samples); + for (int sample = 0; sample < 64; ++sample) { + output[(static_cast(slot) * 64 + sample) * 2 + ear] = + samples[sample] * output_gain; + } + } + } + return 0; + } + +private: + int fail(const char* message) noexcept { + std::snprintf(error_, sizeof(error_), "%s", message); + return -1; + } + + void initialize_fft() noexcept { + for (int index = 0; index < 128; ++index) { + int value = index; + int reversed = 0; + for (int bit = 0; bit < 7; ++bit) { + reversed = (reversed << 1) | (value & 1); + value >>= 1; + } + bit_reverse_[index] = static_cast(reversed); + } + for (int phase = 0; phase < 64; ++phase) { + const double angle = -kPi * static_cast(phase) / 128.0; + premod_[phase] = {std::cos(angle), std::sin(angle)}; + const double post_angle = + -3.0 * (static_cast(phase) + 0.5) * kPi / 128.0; + post_[phase] = {std::cos(post_angle), std::sin(post_angle)}; + even_post_[phase] = {0.0, (phase & 1) ? -1.0 : 1.0}; + } + } + + void fft128(std::array& values) const noexcept { + for (int index = 0; index < 128; ++index) { + const int reversed = bit_reverse_[index]; + if (reversed > index) { + std::swap(values[index], values[reversed]); + } + } + for (int length = 2; length <= 128; length <<= 1) { + const double angle = -2.0 * kPi / static_cast(length); + const Complex step{std::cos(angle), std::sin(angle)}; + for (int start = 0; start < 128; start += length) { + Complex rotation{1.0, 0.0}; + for (int offset = 0; offset < length / 2; ++offset) { + const Complex even = values[start + offset]; + const Complex odd = mul(values[start + offset + length / 2], rotation); + values[start + offset] = {even.re + odd.re, even.im + odd.im}; + values[start + offset + length / 2] = { + even.re - odd.re, even.im - odd.im}; + rotation = mul(rotation, step); + } + } + } + } + + void qmf_transform(const std::array& source, + std::array& target) const noexcept { + std::array work{}; + for (int phase = 0; phase < 64; ++phase) { + work[phase] = scale(premod_[phase], source[phase]); + } + fft128(work); + for (int band = 0; band < 64; ++band) { + target[band] = mul(work[band], post_[band]); + } + } + + void analyze_qmf(const double* input, + std::array& output) noexcept { + for (int channel = 0; channel < kChannels; ++channel) { + for (int lag = 9; lag > 0; --lag) { + for (int phase = 0; phase < 64; ++phase) { + qmf_history_[qmf_history_index(lag, channel, phase)] = + qmf_history_[qmf_history_index(lag - 1, channel, phase)]; + } + } + for (int phase = 0; phase < 64; ++phase) { + qmf_history_[qmf_history_index(0, channel, phase)] = + input[phase * kChannels + channel]; + } + std::array even{}; + std::array odd{}; + for (int phase = 0; phase < 64; ++phase) { + for (int lag = 0; lag < 10; ++lag) { + const double value = + qmf_history_[qmf_history_index(lag, channel, phase)] * + qmf_analysis_[phase * 10 + lag]; + (lag & 1 ? odd[phase] : even[phase]) += value; + } + } + std::array even_fft{}; + std::array odd_fft{}; + qmf_transform(even, even_fft); + qmf_transform(odd, odd_fft); + for (int band = 0; band < 64; ++band) { + output[channel * 64 + band] = add( + odd_fft[band], mul(even_fft[band], even_post_[band])); + } + } + } + + void analyze_hybrid( + const std::array& qmf, + std::array& output) noexcept { + for (int channel = 0; channel < kChannels; ++channel) { + for (int lag = 12; lag > 0; --lag) { + for (int band = 0; band < 3; ++band) { + hybrid_low_history_[hybrid_low_history_index(lag, channel, band)] = + hybrid_low_history_[hybrid_low_history_index(lag - 1, channel, band)]; + } + } + for (int band = 0; band < 3; ++band) { + hybrid_low_history_[hybrid_low_history_index(0, channel, band)] = + qmf[channel * 64 + band]; + } + for (int output_band = 0; output_band < 16; ++output_band) { + Complex value{}; + for (int lag = 0; lag < 13; ++lag) { + for (int input_band = 0; input_band < 3; ++input_band) { + const Complex source = hybrid_low_history_[ + hybrid_low_history_index(lag, channel, input_band)]; + const double components[2]{source.re, source.im}; + for (int input_component = 0; input_component < 2; ++input_component) { + value.re += components[input_component] * hybrid_low_[ + hybrid_low_kernel_index(input_band, input_component, lag, + output_band, 0)]; + value.im += components[input_component] * hybrid_low_[ + hybrid_low_kernel_index(input_band, input_component, lag, + output_band, 1)]; + } + } + } + output[channel * kHybrid + output_band] = value; + } + for (int band = 0; band < 61; ++band) { + output[channel * kHybrid + 16 + band] = + hybrid_high_history_[hybrid_high_history_index(0, channel, band)]; + for (int delay = 0; delay < 5; ++delay) { + hybrid_high_history_[hybrid_high_history_index(delay, channel, band)] = + hybrid_high_history_[hybrid_high_history_index(delay + 1, channel, band)]; + } + hybrid_high_history_[hybrid_high_history_index(5, channel, band)] = + qmf[channel * 64 + 3 + band]; + } + } + } + + std::array process_room( + const std::array& input) noexcept { + std::array filtered{}; + for (int band = 0; band < 64; ++band) { + filtered[band] = scale(input[band], 0.70710677); + } + for (size_t stage = 0; stage < allpass_delays_.size(); ++stage) { + const uint32_t position = allpass_positions_[stage]; + const double gain = allpass_gains_[stage]; + for (int band = 0; band < 64; ++band) { + Complex& memory = allpass_memory_[ + allpass_offsets_[stage] + static_cast(position) * 64 + band]; + const Complex residual = add(filtered[band], scale(memory, -gain)); + filtered[band] = add(scale(residual, gain), memory); + memory = residual; + } + allpass_positions_[stage] = (position + 1) % allpass_delays_[stage]; + } + + std::array branches{}; + std::array taps{}; + for (int band = 0; band < 64; ++band) { + for (int branch = 0; branch < 4; ++branch) { + Complex value = filtered[band]; + for (int source = 0; source < 4; ++source) { + const uint32_t position = + (room_position_ + room_capacity_ - fdn_delays_[source]) % room_capacity_; + value = add(value, scale(room_memory_[ + room_memory_index(position, band, source)], + fdn_matrix_[branch * 4 + source])); + } + branches[band * 4 + branch] = value; + const uint32_t tap_position = + (room_position_ + room_capacity_ - + (output_tap_delay_ % room_capacity_)) % room_capacity_; + taps[band * 4 + branch] = + room_memory_[room_memory_index(tap_position, band, branch)]; + } + } + for (int band = 0; band < 64; ++band) { + for (int branch = 0; branch < 4; ++branch) { + room_memory_[room_memory_index(room_position_, band, branch)] = + mul(branches[band * 4 + branch], feedback_[band][branch]); + } + } + room_position_ = (room_position_ + 1) % room_capacity_; + + std::array extra{}; + for (size_t index = 0; index < extra_delays_.size(); ++index) { + const uint32_t position = + (room_position_ + room_capacity_ - + ((extra_delays_[index] + 1) % room_capacity_)) % room_capacity_; + for (int band = 0; band < 64; ++band) { + for (int target = 0; target < 4; ++target) { + Complex mixed{}; + for (int source = 0; source < 4; ++source) { + mixed = add(mixed, scale(room_memory_[ + room_memory_index(position, band, source)], + extra_matrices_[index * 16 + target * 4 + source])); + } + extra[band * 4 + target] = add( + extra[band * 4 + target], + mul(mixed, extra_fields_[index * 64 + band])); + } + } + } + + std::array output{}; + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < 64; ++band) { + Complex value{}; + for (int branch = 0; branch < 4; ++branch) { + const Complex signal = add( + scale(taps[band * 4 + branch], output_taps_[band][branch]), + extra[band * 4 + branch]); + value = add(value, mul( + signal, output_matrix_[ear][band][branch])); + } + output[ear * kHybrid + band] = value; + } + } + return output; + } + + void synthesize_hybrid( + const std::array& input, + std::array& output) const noexcept { + for (size_t mapping = 0; mapping < hybrid_values_.size(); ++mapping) { + const int16_t* index = hybrid_indices_.data() + mapping * 4; + const int input_band = index[0]; + const int input_component = index[1]; + const int output_band = index[2]; + const int output_component = index[3]; + const double gain = hybrid_values_[mapping]; + for (int ear = 0; ear < 2; ++ear) { + const Complex source = input[ear * kHybrid + input_band]; + Complex& target = output[ear * kQmf + output_band]; + const double component = input_component == 0 ? source.re : source.im; + (output_component == 0 ? target.re : target.im) += component * gain; + } + } + } + + void synthesize_qmf(const Complex* input, int ear, + std::array& output) noexcept { + std::array features{}; + std::array flat{}; + for (int band = 0; band < 64; ++band) { + flat[band * 2] = input[band].re; + flat[band * 2 + 1] = input[band].im; + } + for (int phase = 0; phase < 64; ++phase) { + for (int rank = 0; rank < kRank; ++rank) { + double value = 0.0; + const size_t base = (static_cast(phase) * kRank + rank) * 128; + for (int component = 0; component < 128; ++component) { + value += flat[component] * qmf_basis_[base + component]; + } + features[phase * kRank + rank] = value; + } + } + for (int phase = 0; phase < 64; ++phase) { + double value = 0.0; + for (int lag = 0; lag < 10; ++lag) { + for (int rank = 0; rank < kRank; ++rank) { + const double feature = lag == 0 + ? features[phase * kRank + rank] + : synthesis_history_[synthesis_history_index( + ear, lag - 1, phase, rank)]; + value += feature * qmf_taps_[ + ((static_cast(phase) * 10 + lag) * kRank + rank)]; + } + } + output[phase] = value; + } + for (int lag = 8; lag > 0; --lag) { + for (int phase = 0; phase < 64; ++phase) { + for (int rank = 0; rank < kRank; ++rank) { + synthesis_history_[synthesis_history_index(ear, lag, phase, rank)] = + synthesis_history_[synthesis_history_index( + ear, lag - 1, phase, rank)]; + } + } + } + for (int phase = 0; phase < 64; ++phase) { + for (int rank = 0; rank < kRank; ++rank) { + synthesis_history_[synthesis_history_index(ear, 0, phase, rank)] = + features[phase * kRank + rank]; + } + } + } + + static size_t qmf_history_index(int lag, int channel, int phase) noexcept { + return (static_cast(lag) * kChannels + channel) * 64 + phase; + } + + static size_t hybrid_low_history_index(int lag, int channel, int band) noexcept { + return (static_cast(lag) * kChannels + channel) * 3 + band; + } + + static size_t hybrid_high_history_index(int delay, int channel, int band) noexcept { + return (static_cast(delay) * kChannels + channel) * 61 + band; + } + + static size_t hybrid_low_kernel_index( + int input_band, int input_component, int lag, + int output_band, int output_component) noexcept { + return (((static_cast(input_band) * 2 + input_component) * 13 + lag) * + 16 + output_band) * 2 + output_component; + } + + size_t room_memory_index(uint32_t position, int band, int branch) const noexcept { + return (static_cast(position) * 64 + band) * 4 + branch; + } + + static size_t synthesis_history_index( + int ear, int lag, int phase, int rank) noexcept { + return (((static_cast(ear) * 9 + lag) * 64 + phase) * kRank + rank); + } + + bool kernels_ready_ = false; + bool room_ready_ = false; + std::array qmf_analysis_{}; + std::vector hybrid_low_; + std::vector hybrid_indices_; + std::vector hybrid_values_; + std::array qmf_basis_{}; + std::array qmf_taps_{}; + + std::array qmf_history_{}; + std::array hybrid_low_history_{}; + std::array hybrid_high_history_{}; + std::array synthesis_history_{}; + + uint32_t room_bands_ = 0; + std::vector allpass_delays_; + std::vector allpass_gains_; + std::vector allpass_offsets_; + std::vector allpass_positions_; + std::vector allpass_memory_; + std::array fdn_delays_{}; + std::array fdn_matrix_{}; + uint32_t room_capacity_ = 0; + uint32_t output_tap_delay_ = 0; + std::array, 64> feedback_{}; + std::array, 64> output_taps_{}; + std::array, 64>, 2> output_matrix_{}; + std::vector room_memory_; + uint32_t room_position_ = 0; + std::vector extra_delays_; + std::vector extra_fields_; + std::vector extra_matrices_; + + std::array bit_reverse_{}; + std::array premod_{}; + std::array post_{}; + std::array even_post_{}; + char error_[256]{}; +}; + +} // namespace ejoc::binaural + +extern "C" { + +ejoc_binaural_renderer_handle EJOC_CALL ejoc_binaural_renderer_create(void) { + return new (std::nothrow) ejoc::binaural::Renderer(); +} + +void EJOC_CALL ejoc_binaural_renderer_destroy(ejoc_binaural_renderer_handle handle) { + delete static_cast(handle); +} + +int EJOC_CALL ejoc_binaural_renderer_reset(ejoc_binaural_renderer_handle handle) { + return handle ? static_cast(handle)->reset() : -1; +} + +const char* EJOC_CALL ejoc_binaural_renderer_last_error( + ejoc_binaural_renderer_handle handle) { + return handle ? static_cast(handle)->error() + : "null binaural renderer handle"; +} + +int EJOC_CALL ejoc_binaural_renderer_configure_kernels( + ejoc_binaural_renderer_handle handle, + const double* qmf_analysis, + const double* hybrid_low, + const int16_t* hybrid_indices, + const double* hybrid_values, + uint32_t hybrid_count, + const double* qmf_basis, + const double* qmf_taps) { + return handle ? static_cast(handle)->configure_kernels( + qmf_analysis, hybrid_low, hybrid_indices, hybrid_values, + hybrid_count, qmf_basis, qmf_taps) : -1; +} + +int EJOC_CALL ejoc_binaural_renderer_configure_room( + ejoc_binaural_renderer_handle handle, + uint32_t bands, + uint32_t allpass_count, + const uint32_t* allpass_delays, + const double* allpass_gains, + const uint32_t* fdn_delays, + const double* fdn_matrix, + uint32_t output_tap_delay, + const double* feedback_complex, + const double* output_taps, + const double* output_complex, + uint32_t extra_count, + const uint32_t* extra_delays, + const double* extra_fields_complex, + const double* extra_matrices) { + return handle ? static_cast(handle)->configure_room( + bands, allpass_count, allpass_delays, allpass_gains, + fdn_delays, fdn_matrix, output_tap_delay, + feedback_complex, output_taps, output_complex, + extra_count, extra_delays, extra_fields_complex, extra_matrices) : -1; +} + +int EJOC_CALL ejoc_binaural_renderer_process( + ejoc_binaural_renderer_handle handle, + const double* input16_interleaved, + const double* gains_complex, + const double* room_sends, + double output_gain, + double* output_stereo_interleaved) { + return handle ? static_cast(handle)->process( + input16_interleaved, gains_complex, room_sends, + output_gain, output_stereo_interleaved) : -1; +} + +} // extern "C" diff --git a/src/binaural/binaural_runtime.cpp b/src/binaural/binaural_runtime.cpp new file mode 100644 index 0000000..deb3ac1 --- /dev/null +++ b/src/binaural/binaural_runtime.cpp @@ -0,0 +1,251 @@ +#include "binaural/binaural_runtime.h" + +#include +#include +#include +#include + +namespace joc::binaural { + +namespace { + +double max_delay_bound(const hrtf::Field& field) { + double maximum = 0.0; + for (const double value : field.delay_bounds) { + maximum = std::max(maximum, value); + } + return maximum; +} + +} // namespace + +bool profile_from_name(const char* name, Profile* out) { + if (name == nullptr || out == nullptr) { + return false; + } + if (std::strcmp(name, "near") == 0) { *out = Profile::Near; return true; } + if (std::strcmp(name, "mid") == 0) { *out = Profile::Mid; return true; } + if (std::strcmp(name, "far") == 0) { *out = Profile::Far; return true; } + return false; +} + +SofaBinauralRuntime::~SofaBinauralRuntime() { + if (handle_ != nullptr) { + ejoc_sofa_binaural_destroy(handle_); + handle_ = nullptr; + } +} + +Status SofaBinauralRuntime::open(const hrtf::Field& field, const hrtf::Kernels& kernels, + Profile profile, const RoomConstants& room) { + if (handle_ != nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kRender, "binaural runtime already open"); + } + if (field.coefficients.size() != static_cast(hrtf::kShTerms * hrtf::kEars * + hrtf::kHybridBands * 2) || + field.band_centers_hz.size() != static_cast(hrtf::kHybridBands)) { + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + "compiled HRTF field has unexpected array sizes"); + } + handle_ = ejoc_sofa_binaural_create(); + if (handle_ == nullptr) { + return Status::fail(JOC_ERR_OUT_OF_MEMORY, stage::kRender, + "ejoc_sofa_binaural_create failed"); + } + profile_ = profile; + + if (ejoc_sofa_binaural_configure_kernels( + handle_, kernels.qmf_analysis.data(), kernels.hybrid_low.data(), + kernels.hybrid_indices.data(), kernels.hybrid_values.data(), kernels.hybrid_count, + kernels.qmf_basis.data(), kernels.qmf_taps.data()) != 0) { + const char* message = ejoc_sofa_binaural_last_error(handle_); + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + std::string("configure_kernels failed: ") + + (message != nullptr ? message : "unknown")); + } + if (ejoc_sofa_binaural_configure_field(handle_, field.coefficients.data(), + field.delay_coefficients.data(), + field.delay_bounds.data(), field.band_centers_hz.data(), + field.measurement_radius_m) != 0) { + const char* message = ejoc_sofa_binaural_last_error(handle_); + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + std::string("configure_field failed: ") + + (message != nullptr ? message : "unknown")); + } + if (ejoc_sofa_binaural_configure_room( + handle_, room.dims, room.listener, room.walls, room.speed_of_sound, room.fdn_delays, + room.fdn_feedback, room.damping, room.fdn_output_gain, room.allpass_delays, + room.allpass_gains, room.enable_early_reflections, room.enable_late_room) != 0) { + const char* message = ejoc_sofa_binaural_last_error(handle_); + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, + std::string("configure_room failed: ") + + (message != nullptr ? message : "unknown")); + } + + maximum_hrtf_delay_ = + static_cast(std::ceil(max_delay_bound(field) - 1e-9)); + hrtf_history_slots_ = static_cast(std::max(1, (maximum_hrtf_delay_ + 63) / 64)); + staging_.assign(kBlockSamples * kSourceCount, 0.0); + block_output_.assign(kBlockSamples * 2u, 0.0); + output_.clear(); + staged_ = 0; + input_samples_ = 0; + processed_samples_ = 0; + blocks_processed_ = 0; + return Status::success(); +} + +Status SofaBinauralRuntime::process_block() { + double positions[timeline::kTimelineObjects][3] = {}; + const Status queried = timeline_.positions_at(static_cast(processed_samples_), + positions); + if (!queried.ok()) { + return queried; + } + // The reference adapter calls set_source without a `fade` argument, so the + // backend default (fade enabled) applies - the per-object path crossfade is + // part of the reference behaviour, not an optional extra. + constexpr std::uint32_t kFade = 1u; + if (ejoc_sofa_binaural_set_source(handle_, 0u, kLfePosition, + static_cast(profile_), 1.0, 1u, 1u, + kFade) != 0) { + const char* message = ejoc_sofa_binaural_last_error(handle_); + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, + std::string("set_source(LFE) failed: ") + + (message != nullptr ? message : "unknown")); + } + for (std::uint32_t source = 0; source < timeline::kTimelineObjects; ++source) { + if (ejoc_sofa_binaural_set_source(handle_, source + 1u, positions[source], + static_cast(profile_), 1.0, 1u, 0u, + kFade) != 0) { + const char* message = ejoc_sofa_binaural_last_error(handle_); + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, + std::string("set_source(object ") + std::to_string(source + 1u) + + ") failed: " + (message != nullptr ? message : "unknown")); + } + } + const int trimmed = ejoc_sofa_binaural_process(handle_, staging_.data(), kBlockSamples, 1.0, + block_output_.data()); + if (trimmed < 0) { + const char* message = ejoc_sofa_binaural_last_error(handle_); + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, + std::string("sofa process failed: ") + + (message != nullptr ? message : "unknown")); + } + if (trimmed > 0) { + output_.insert(output_.end(), block_output_.begin(), + block_output_.begin() + static_cast(trimmed) * 2); + } + staged_ = 0; + processed_samples_ += kBlockSamples; + ++blocks_processed_; + return Status::success(); +} + +Status SofaBinauralRuntime::submit_frame(const float* objects16_planar, + const oamd::OamdUpdate* update, std::int64_t frame_index, + std::int64_t outer_sample_offset, + std::int64_t object_delay_samples) { + if (handle_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kRender, "binaural runtime is not open"); + } + if (objects16_planar == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kRender, "null frame"); + } + // A frame without an ID11 payload submits nothing at all (the reference only + if (update != nullptr) { + const Status submitted = timeline_.submit_update( + *update, frame_index * JOC_FRAME_SAMPLES, outer_sample_offset, object_delay_samples, + static_cast(input_samples_)); + if (!submitted.ok()) { + return submitted; + } + } + + std::size_t offset = 0; + while (offset < JOC_FRAME_SAMPLES) { + const std::size_t room = kBlockSamples - staged_; + const std::size_t count = std::min(room, JOC_FRAME_SAMPLES - offset); + for (std::size_t sample = 0; sample < count; ++sample) { + double* row = staging_.data() + (staged_ + sample) * kSourceCount; + for (std::size_t channel = 0; channel < kSourceCount; ++channel) { + row[channel] = static_cast( + objects16_planar[channel * JOC_FRAME_SAMPLES + offset + sample]); + } + } + staged_ += count; + offset += count; + if (staged_ == kBlockSamples) { + const Status status = process_block(); + if (!status.ok()) { + return status; + } + } + } + input_samples_ += JOC_FRAME_SAMPLES; + return Status::success(); +} + +std::uint32_t SofaBinauralRuntime::finish_capacity(double tail_seconds) const { + std::int64_t requested = tail_samples_; + if (tail_seconds >= 0.0) { + requested = static_cast(std::ceil(tail_seconds * 48000.0 - 1e-9)); + } + const std::int64_t hrtf_bound = static_cast(hrtf_history_slots_) * 64; + const std::int64_t early_bound = hrtf_bound + 2048 + 256 * 64; + std::int64_t drain = std::max(requested, early_bound) + 961; + drain = ((drain + 63) / 64) * 64; + return static_cast(drain); +} + +Status SofaBinauralRuntime::reset() { + if (handle_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kRender, "binaural runtime is not open"); + } + if (ejoc_sofa_binaural_reset(handle_) != 0) { + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, "sofa reset failed"); + } + timeline_ = timeline::OamdPositionTimeline(); + output_.clear(); + staged_ = 0; + input_samples_ = 0; + processed_samples_ = 0; + blocks_processed_ = 0; + return Status::success(); +} + +Status SofaBinauralRuntime::finish(std::uint32_t flush_samples, std::vector* out) { + if (handle_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kRender, "binaural runtime is not open"); + } + if (out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kRender, "null output"); + } + out->clear(); + if (flush_samples == 0u) { + return Status::success(); + } + std::vector chunk(static_cast(kBlockSamples) * 2u, 0.0); + std::uint32_t produced_total = 0; + std::uint32_t remaining = flush_samples; + while (remaining > 0) { + const std::uint32_t request = std::min(remaining, kBlockSamples); + const int produced = ejoc_sofa_binaural_finish(handle_, request, chunk.data(), request); + if (produced < 0) { + const char* message = ejoc_sofa_binaural_last_error(handle_); + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, + std::string("sofa finish failed: ") + + (message != nullptr ? message : "unknown")); + } + if (produced == 0) { + break; + } + out->insert(out->end(), chunk.begin(), + chunk.begin() + static_cast(produced) * 2); + produced_total += static_cast(produced); + remaining -= std::min(remaining, static_cast(produced)); + } + return Status::success(); +} + +} // namespace joc::binaural diff --git a/src/binaural/binaural_runtime.h b/src/binaural/binaural_runtime.h new file mode 100644 index 0000000..79111db --- /dev/null +++ b/src/binaural/binaural_runtime.h @@ -0,0 +1,96 @@ + +#pragma once + +#include +#include + +#include "eac3joc_core.h" +#include "foundation/status.h" +#include "hrtf/jochrtf.h" +#include "oamd/oamd_parser.h" +#include "timeline/position_timeline.h" + +namespace joc::binaural { + +// ADM direction of the LFE source, as the reference passes it. +inline constexpr double kLfePosition[3] = {0.0, 1.0, 0.0}; +inline constexpr int kSourceCount = 16; +inline constexpr std::uint32_t kBlockSamples = 512; + +// Room constants the reference's native bridge passes for the default shoebox. +struct RoomConstants { + double dims[3] = {18.0, 18.0, 14.0}; + double listener[3] = {9.0, 9.0, 7.0}; + double walls[6] = {0.62, 0.60, 0.58, 0.61, 0.52, 0.56}; + double speed_of_sound = 343.3; + std::uint32_t fdn_delays[4] = {1427u, 1783u, 1973u, 2099u}; + double fdn_feedback[4] = {0.7853685923259284, 0.7394299865898056, 0.7160221718631921, + 0.7009092068085467}; + double damping = 0.32; + double fdn_output_gain = 0.22; + std::uint32_t allpass_delays[2] = {113u, 331u}; + double allpass_gains[2] = {0.63, 0.51}; + std::uint32_t enable_early_reflections = 1; + std::uint32_t enable_late_room = 1; +}; + +enum class Profile : std::uint32_t { Near = 0, Mid = 1, Far = 2 }; + +bool profile_from_name(const char* name, Profile* out); + +class SofaBinauralRuntime { +public: + SofaBinauralRuntime() = default; + ~SofaBinauralRuntime(); + + SofaBinauralRuntime(const SofaBinauralRuntime&) = delete; + SofaBinauralRuntime& operator=(const SofaBinauralRuntime&) = delete; + + Status open(const hrtf::Field& field, const hrtf::Kernels& kernels, Profile profile, + const RoomConstants& room = RoomConstants{}); + + Status submit_frame(const float* objects16_planar, const oamd::OamdUpdate* update, + std::int64_t frame_index, std::int64_t outer_sample_offset, + std::int64_t object_delay_samples); + + // Resets the kernel, the timeline and the counters (plan 31.2). + Status reset(); + + // Drains the room tail. `flush_samples` is the drain length; the reference + Status finish(std::uint32_t flush_samples, std::vector* out); + + // Program output (input minus the 961-sample kernel latency), interleaved. + const std::vector& output() const { return output_; } + + void take_output(std::vector* out) { + out->swap(output_); + output_.clear(); + } + + std::uint64_t input_samples() const { return input_samples_; } + std::uint64_t blocks_processed() const { return blocks_processed_; } + std::size_t staged_samples() const { return staged_; } + const timeline::OamdPositionTimeline& timeline() const { return timeline_; } + + // finish_output_capacity as the reference computes it (plan 21.4). + std::uint32_t finish_capacity(double tail_seconds) const; + +private: + Status process_block(); + + ejoc_sofa_binaural_handle handle_ = nullptr; + Profile profile_ = Profile::Mid; + timeline::OamdPositionTimeline timeline_; + std::vector staging_; + std::size_t staged_ = 0; + std::vector block_output_; + std::vector output_; + std::uint64_t input_samples_ = 0; + std::uint64_t processed_samples_ = 0; + std::uint64_t blocks_processed_ = 0; + std::int64_t maximum_hrtf_delay_ = 0; + std::uint32_t hrtf_history_slots_ = 1; + std::uint32_t tail_samples_ = 61200; +}; + +} // namespace joc::binaural diff --git a/src/binaural/sofa_binaural_renderer.cpp b/src/binaural/sofa_binaural_renderer.cpp new file mode 100644 index 0000000..84bf999 --- /dev/null +++ b/src/binaural/sofa_binaural_renderer.cpp @@ -0,0 +1,1462 @@ +// Derived from the upstream native/src/sofa_binaural_renderer.cpp (JustOneCacophony +// @ 6bc2c2885666bb151bb66af93472199af9a99b81, sha256 81b485e4c71907672ab308ddc38228 +// 4acf29161cee93d7906785a4cce58941c7) and a drop-in replacement for it: the same +// ejoc_sofa_binaural_* C ABI. The changes are table hoisting, result memoisation, +// input validation and a dispatched SIMD cascade -- no arithmetic is reordered, +// reassociated or contracted, so the output is bit-identical to the upstream +// implementation (verified: identical FNV-1a over the exact output bit patterns at +// 8/64/512/2000 blocks -- ef7ca498a6bb19b0 at 2000 -- and identical SHA-256 of the +// joc_dump --binaural-out float64 stream for 1000/2000/4000 frames): +// +// The deviations from the upstream implementation, and why each one keeps the +// output bit-identical: +// +// Hoisted invariants. QmfAnalysis::configure builds the two modulation tables +// (cos/sin of -kPi*p/128 and of -3.0*(b+0.5)*kPi/128) once, instead of +// recomputing 384 transcendental calls per slot and per channel (49,152 per +// 512-sample block); RealSh::evaluate hoists the normalization (which depends +// only on (degree, |order|)) and the six pmm_value(m, x) Legendre seeds out of +// the 36-term loop. In both cases the stored values are std::cos/std::sin of +// the identical double expressions, evaluated once, so they are the same bits. +// +// Memoised results. set_source memoises the seven paths it derives from a +// source position. The wrapper calls it for every source on every 512-sample +// block and the timeline holds a position constant between OAMD updates, so +// most calls were rebuilding an identical result. A hit requires the exact bit +// pattern of every input make_path reads to match the call that produced the +// stored paths; the fade state machine and the late-send envelope are +// unchanged, so the emitted samples are the same bits. +// +// Input validation. configure_room rejects zero FDN / allpass delay-line +// lengths, which would otherwise reach an integer divide-by-zero from the +// public C ABI, and render_paths wraps the history index with an explicit +// conditional that is identical to `% slots` for every index in [0, 2*slots) -- +// which is every index the shipped room can form -- turning a negative index +// (a delay longer than the 256-slot early history) into an in-range one instead +// of reading out of bounds. Neither can change an accepted input. +// +// Dispatched SIMD cascade. Fft128::butterflies hands the 128-point cascade, +// QmfSynthesis::process the basis application and HybridAnalysis::process the +// 78-term low join to the runtime-dispatched kernels in src/simd. Only +// mutually independent outputs share a vector lane and every lane keeps the +// corresponding loop's own term order and its own two roundings: each butterfly +// keeps its two, the synthesis keeps the j = 0..127 order with one multiply and +// one add per term, and the hybrid join keeps its 32 independent accumulations. +// The kernels read their tables contiguously, so the constructors materialise +// them in the order the kernel wants (same doubles, same order, same table). +// +// Under JOC_SIMD=scalar and under every forced SIMD tier the output is still +// bit-identical: the joc_dump --binaural-out stream and the rendered WAV keep the +// SHA-256 they had before the change. +#define EJOC_BUILD_DLL +#include "eac3joc_core.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "simd/simd.h" + +namespace ejoc::sofa_binaural { + +constexpr double kPi = 3.141592653589793238462643383279502884; +constexpr int kChannels = EJOC_BINAURAL_INPUT_CHANNELS; +constexpr int kHop = 64; +constexpr int kQmf = EJOC_BINAURAL_QMF_BANDS; +constexpr int kHybrid = EJOC_BINAURAL_HYBRID_BANDS; +constexpr int kRank = 4; +constexpr int kLatency = 961; +constexpr int kOrder = 5; +constexpr int kTerms = (kOrder + 1) * (kOrder + 1); +constexpr int kEarlyHistory = 256; +constexpr int kTransitionSlots = 8; +constexpr double kSampleRate = 48000.0; +constexpr int kFftSize = 128; +constexpr int kMaxBlockSamples = 512; + +struct Complex { + double re; + double im; +}; + +inline Complex add(Complex a, Complex b) noexcept { + return {a.re + b.re, a.im + b.im}; +} + +inline Complex mul(Complex a, Complex b) noexcept { + return {a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re}; +} + +inline Complex mulr(Complex a, double b) noexcept { + return {a.re * b, a.im * b}; +} + +inline Complex addmul(Complex acc, Complex b, Complex c) noexcept { + return {acc.re + b.re * c.re - b.im * c.im, acc.im + b.re * c.im + b.im * c.re}; +} + +// --------------------------------------------------------------------------- +// 128-point FFT, forward: X[k] = sum_p x[p] exp(-2j pi k p / N) (radix-2 DIT) +// --------------------------------------------------------------------------- +class Fft128 final { +public: + Fft128() noexcept { + for (int k = 0; k < kFftSize; ++k) { + const double angle = -2.0 * kPi * k / kFftSize; + twiddle_[k] = {std::cos(angle), std::sin(angle)}; + } + // The bit-reversal permutation depends only on the index, so it is + // derived once here instead of by a seven-iteration bit loop inside every + // one of the 256 transforms a 512-sample block runs. Same indices, same + // destinations, same store order. + for (int index = 0; index < kFftSize; ++index) { + unsigned int reversed = 0; + for (int bit = 0; bit < 7; ++bit) { + reversed = (reversed << 1) + | ((static_cast(index) >> bit) & 1u); + } + reverse_[index] = static_cast(reversed); + } + // The dispatched butterfly kernel reads a stage's factors as one + // contiguous run, so the per-stage stride `offset * step` is resolved once + // here. The entries are copies of the same doubles in the same order. + int cursor = 0; + int stage = 0; + for (int size = 2; size <= kFftSize; size <<= 1, ++stage) { + stage_begin_[stage] = static_cast(cursor); + const int step = kFftSize / size; + for (int offset = 0; offset < size / 2; ++offset) { + stage_twiddle_[cursor] = twiddle_[offset * step]; + ++cursor; + } + } + } + + // The transform is split so a caller that can produce its input already + // bit-reversed does not have to stage it through a second array and permute it + // afterwards. `permuted(index)` is the destination the permutation used, and + // `butterflies` runs the stages in place on a permuted buffer. + int permuted(int index) const noexcept { return reverse_[index]; } + + void butterflies(Complex* data) const noexcept { + joc::simd::fft_butterflies(reinterpret_cast(data), kFftSize, + reinterpret_cast(stage_twiddle_), + stage_begin_); + } + +private: + Complex twiddle_[kFftSize]; + int reverse_[kFftSize]; + // 1 + 2 + 4 + ... + 64 factors, one contiguous run per stage. + Complex stage_twiddle_[kFftSize - 1]; + std::size_t stage_begin_[7]; +}; + +// --------------------------------------------------------------------------- +// QMF analysis (mirrors QmfAnalysis: joined history, lag 0..9, modulations) +// --------------------------------------------------------------------------- +class QmfAnalysis final { +public: + void configure(const double* coefficients) noexcept { + std::memcpy(coeff_, coefficients, sizeof(coeff_)); + for (int p = 0; p < kQmf; ++p) { + const double pre_angle = -kPi * p / kFftSize; + pre_cos_[p] = std::cos(pre_angle); + pre_sin_[p] = std::sin(pre_angle); + } + for (int b = 0; b < kQmf; ++b) { + const double post_angle = -3.0 * (b + 0.5) * kPi / kFftSize; + post_cos_[b] = std::cos(post_angle); + post_sin_[b] = std::sin(post_angle); + } + } + + void reset() noexcept { + std::memset(history_, 0, sizeof(history_)); + } + + // input: interleaved [samples][16]; output: [slots][16][64] complex + void process(const double* input, int slots, Complex* output) noexcept { + // joined[9 + slots][16][64] + for (int lag = 0; lag < 9; ++lag) { + std::memcpy(joined_[lag], history_[lag], sizeof(joined_[0])); + } + for (int slot = 0; slot < slots; ++slot) { + for (int channel = 0; channel < kChannels; ++channel) { + for (int p = 0; p < 64; ++p) { + joined_[9 + slot][channel][p] = + input[(static_cast(slot) * 64 + p) * kChannels + + channel]; + } + } + } + for (int slot = 0; slot < slots; ++slot) { + for (int channel = 0; channel < kChannels; ++channel) { + Complex even_fft[kFftSize]; + Complex odd_fft[kFftSize]; + // The polyphase sums are written straight to the bit-reversed + // positions the DIT permutation would have put them in, so the two + // staging arrays and the permutation pass over them are gone. Each + // destination is still written exactly once, with the same value, so + // the permuted buffers hold the same bits as before, and only the zero-padded + // upper half still needs clearing. + for (int p = kQmf; p < kFftSize; ++p) { + even_fft[fft_.permuted(p)] = {0.0, 0.0}; + odd_fft[fft_.permuted(p)] = {0.0, 0.0}; + } + // 64 polyphase positions; the 128-point FFT zero-pads the rest + for (int p = 0; p < kQmf; ++p) { + double even_re = 0.0; + double odd_re = 0.0; + for (int lag = 0; lag < 5; ++lag) { + even_re += joined_[9 + slot - 2 * lag][channel][p] + * coeff_[p][2 * lag]; + } + for (int lag = 0; lag < 5; ++lag) { + odd_re += joined_[9 + slot - (2 * lag + 1)][channel][p] + * coeff_[p][2 * lag + 1]; + } + even_fft[fft_.permuted(p)] = {even_re * pre_cos_[p], + even_re * pre_sin_[p]}; + odd_fft[fft_.permuted(p)] = {odd_re * pre_cos_[p], + odd_re * pre_sin_[p]}; + } + fft_.butterflies(even_fft); + fft_.butterflies(odd_fft); + Complex* band = output + + (static_cast(slot) * kChannels + channel) * kQmf; + for (int b = 0; b < kQmf; ++b) { + const Complex post = {post_cos_[b], post_sin_[b]}; + const Complex even_post = {0.0, (b % 2 == 0) ? 1.0 : -1.0}; + // python: (odd_fft + even_fft * even_post) * post + band[b] = mul(post, add(odd_fft[b], + mul(even_fft[b], even_post))); + } + } + } + for (int lag = 0; lag < 9; ++lag) { + std::memcpy(history_[lag], joined_[slots + lag], sizeof(history_[0])); + } + } + +private: + double coeff_[kQmf][10]; + // The two modulation tables depend only on the loop index, so they are + // built once with the identical expressions used in process(). + double pre_cos_[kQmf]; + double pre_sin_[kQmf]; + double post_cos_[kQmf]; + double post_sin_[kQmf]; + double history_[9][kChannels][64]; + double joined_[9 + kMaxBlockSamples / kHop][kChannels][64]; + Fft128 fft_; +}; + +// --------------------------------------------------------------------------- +// Hybrid analysis (mirrors HybridAnalysis: 13-tap low join, 6-slot high join) +// --------------------------------------------------------------------------- +class HybridAnalysis final { +public: + void configure(const double* low_kernel) noexcept { + std::memcpy(low_, low_kernel, sizeof(low_)); + // The dispatched join walks its terms in the order this class + // accumulates them -- parent, then component, then lag -- and adds the 32 + // weights of one term at once, so the table is regrouped once here. Same + // weights, same order. + int cursor = 0; + for (int parent = 0; parent < 3; ++parent) { + for (int comp = 0; comp < 2; ++comp) { + for (int lag = 0; lag < 13; ++lag) { + for (int hb = 0; hb < 16; ++hb) { + low_by_term_[cursor++] = low_[parent][comp][lag][hb][0]; + low_by_term_[cursor++] = low_[parent][comp][lag][hb][1]; + } + } + } + } + } + + void reset() noexcept { + std::memset(history_, 0, sizeof(history_)); + std::memset(high_history_, 0, sizeof(high_history_)); + } + + // qmf: [slots][16][64] complex; output: [slots][16][77] complex + void process(const Complex* qmf, int slots, Complex* output) noexcept { + for (int lag = 0; lag < 12; ++lag) { + std::memcpy(low_joined_[lag], history_[lag], sizeof(low_joined_[0])); + } + for (int lag = 0; lag < 6; ++lag) { + std::memcpy(high_joined_[lag], high_history_[lag], + sizeof(high_joined_[0])); + } + for (int slot = 0; slot < slots; ++slot) { + for (int channel = 0; channel < kChannels; ++channel) { + const Complex* band = qmf + + (static_cast(slot) * kChannels + channel) * kQmf; + for (int parent = 0; parent < 3; ++parent) { + low_joined_[12 + slot][channel][parent][0] = band[parent].re; + low_joined_[12 + slot][channel][parent][1] = band[parent].im; + } + for (int b = 0; b < 61; ++b) { + high_joined_[6 + slot][channel][b] = band[3 + b]; + } + } + } + // The low bands are a 78-term join into 32 outputs, and the 32 outputs + // of a row are independent accumulations over the same terms -- that is what + // the dispatched kernel puts in its lanes, keeping this loop's term order + // (parent, component, lag) and its two roundings per term. Rows are staged + // in blocks so the gathered values stay in the first-level cache. + const std::size_t rows = static_cast(slots) * kChannels; + const std::size_t block = joc::simd::kHybridJoinBlock; + const std::size_t terms = joc::simd::kHybridTerms; + for (std::size_t first = 0u; first < rows; first += block) { + const std::size_t count = std::min(block, rows - first); + for (std::size_t index = 0u; index < count; ++index) { + const std::size_t row = first + index; + const int slot = static_cast(row / kChannels); + const int channel = static_cast(row % kChannels); + double* staged = low_values_ + index * terms; + for (int parent = 0; parent < 3; ++parent) { + for (int comp = 0; comp < 2; ++comp) { + for (int lag = 0; lag < 13; ++lag) { + staged[(static_cast(parent) * 2u + + static_cast(comp)) * 13u + + static_cast(lag)] = + low_joined_[12 + slot - lag][channel][parent][comp]; + } + } + } + } + joc::simd::hybrid_low_join(low_values_, low_by_term_, low_out_, count); + for (std::size_t index = 0u; index < count; ++index) { + Complex* out = output + (first + index) * kHybrid; + const double* values = low_out_ + index * joc::simd::kHybridOutputs; + for (int hb = 0; hb < 16; ++hb) { + out[hb] = {values[static_cast(hb) * 2u], + values[static_cast(hb) * 2u + 1u]}; + } + } + } + for (int slot = 0; slot < slots; ++slot) { + for (int channel = 0; channel < kChannels; ++channel) { + Complex* out = output + + (static_cast(slot) * kChannels + channel) * kHybrid; + for (int b = 0; b < 61; ++b) { + out[16 + b] = high_joined_[slot][channel][b]; + } + } + } + for (int lag = 0; lag < 12; ++lag) { + std::memcpy(history_[lag], low_joined_[slots + lag], sizeof(history_[0])); + } + for (int lag = 0; lag < 6; ++lag) { + std::memcpy(high_history_[lag], high_joined_[slots + lag], + sizeof(high_history_[0])); + } + } + +private: + double low_[3][2][13][16][2]; + double low_by_term_[78 * 32]; // S3: the same weights in this class's term order + double low_values_[joc::simd::kHybridJoinBlock * 78]; // scratch + double low_out_[joc::simd::kHybridJoinBlock * 32]; // scratch + double history_[12][kChannels][3][2]; + double low_joined_[12 + kMaxBlockSamples / kHop][kChannels][3][2]; + Complex high_history_[6][kChannels][61]; + Complex high_joined_[6 + kMaxBlockSamples / kHop][kChannels][61]; +}; + +// --------------------------------------------------------------------------- +// Hybrid synthesis sparse map (mirrors HybridSynthesis) +// --------------------------------------------------------------------------- +struct SynthesisEntry { + int in_band; + int in_comp; + int out_band; + int out_comp; + double gain; +}; + +class HybridSynthesis final { +public: + void configure(const int16_t* indices, const double* values, + uint32_t count) noexcept { + entries_.clear(); + for (uint32_t i = 0; i < count; ++i) { + entries_.push_back({static_cast(indices[i * 4]), + static_cast(indices[i * 4 + 1]), + static_cast(indices[i * 4 + 2]), + static_cast(indices[i * 4 + 3]), + values[i]}); + } + } + + // hybrid: [slots][2][77]; output: [slots][2][64] + void process(const Complex* hybrid, int slots, Complex* output) noexcept { + for (int slot = 0; slot < slots; ++slot) { + for (int channel = 0; channel < 2; ++channel) { + const Complex* source = hybrid + + (static_cast(slot) * 2 + channel) * kHybrid; + Complex* target = output + + (static_cast(slot) * 2 + channel) * kQmf; + for (int b = 0; b < kQmf; ++b) { + target[b] = {0.0, 0.0}; + } + for (const auto& entry : entries_) { + const Complex value = source[entry.in_band]; + const double component = + (entry.in_comp == 0) ? value.re : value.im; + if (entry.out_comp == 0) { + target[entry.out_band].re += component * entry.gain; + } else { + target[entry.out_band].im += component * entry.gain; + } + } + } + } + } + +private: + std::vector entries_; +}; + +// --------------------------------------------------------------------------- +// QMF synthesis, rank-4 (mirrors QmfSynthesis: joined history, lag 0..9) +// --------------------------------------------------------------------------- +class QmfSynthesis final { +public: + void configure(const double* basis, const double* taps) noexcept { + std::memcpy(basis_, basis, sizeof(basis_)); + std::memcpy(taps_, taps, sizeof(taps_)); + // The dispatched basis kernel reads the four ranks of one (band, tap) + // as one vector, so the shipped [band][rank][tap] table is reordered once + // here. Same doubles, different order. + int cursor = 0; + for (int b = 0; b < kQmf; ++b) { + for (int j = 0; j < kFftSize; ++j) { + for (int r = 0; r < kRank; ++r) { + basis_by_tap_[cursor] = basis_[b][r][j]; + ++cursor; + } + } + } + } + + void reset() noexcept { + std::memset(history_, 0, sizeof(history_)); + } + + // qmf: [slots][2][64]; output: [slots][2][64] real + void process(const Complex* qmf, int slots, double* output) noexcept { + for (int lag = 0; lag < 9; ++lag) { + std::memcpy(joined_[lag], history_[lag], sizeof(joined_[0])); + } + for (int slot = 0; slot < slots; ++slot) { + // Both channels consume the same basis_[b][r][*] row. The + // dispatched kernel does the same thing a vector at a time: the + // four ranks of a band are four independent dot products over one + // channel's 128 values, so they fill the lanes while each lane keeps + // the original j = 0..127 order and its own two roundings. + for (int channel = 0; channel < 2; ++channel) { + const Complex* values = qmf + + (static_cast(slot) * 2 + channel) * kQmf; + for (int b = 0; b < kQmf; ++b) { + flat_[slot][channel][2 * b] = values[b].re; + flat_[slot][channel][2 * b + 1] = values[b].im; + } + } + } + // Every slot is handed over at once rather than one at a time: a band's + // accumulation is 128 dependent adds, and the kernel hides that latency by + // running several rows side by side, so it needs more than the two rows of + // a single slot to work with. + joc::simd::qmf_synthesis_basis(&flat_[0][0][0], basis_by_tap_, + &joined_[9][0][0][0], + static_cast(slots) * 2u); + for (int slot = 0; slot < slots; ++slot) { + for (int channel = 0; channel < 2; ++channel) { + for (int b = 0; b < kQmf; ++b) { + double value = 0.0; + for (int lag = 0; lag < 10; ++lag) { + for (int r = 0; r < kRank; ++r) { + value += joined_[9 + slot - lag][channel][b][r] + * taps_[b][lag][r]; + } + } + output[(static_cast(slot) * 2 + channel) * 64 + b] + = value; + } + } + } + for (int lag = 0; lag < 9; ++lag) { + std::memcpy(history_[lag], joined_[slots + lag], sizeof(history_[0])); + } + } + +private: + double basis_[kQmf][kRank][kFftSize]; + double basis_by_tap_[kQmf * kFftSize * kRank]; // S2: the same weights, transposed + double taps_[kQmf][10][kRank]; + double flat_[kMaxBlockSamples / kHop][2][kFftSize]; // S2: staging for the kernel + double history_[9][2][kQmf][kRank]; + double joined_[9 + kMaxBlockSamples / kHop][2][kQmf][kRank]; +}; + +// --------------------------------------------------------------------------- +// Fifth-order ACN/N3D real spherical harmonics +// --------------------------------------------------------------------------- +class RealSh final { +public: + static void evaluate(const double* direction, double* basis) noexcept { + const double azimuth = std::atan2(direction[1], direction[0]); + const double x = std::max(-1.0, std::min(1.0, direction[2])); + // Normalization depends only on (degree, |order|) and the Legendre + // seed pmm_value(m, x) only on (m, x): 6 seeds, not 36 recomputations. + double pmm[kOrder + 1]; + for (int m = 0; m <= kOrder; ++m) { + pmm[m] = pmm_value(m, x); + } + double norm[kOrder + 1][kOrder + 1]; + for (int degree = 0; degree <= kOrder; ++degree) { + for (int absolute = 0; absolute <= degree; ++absolute) { + norm[degree][absolute] = std::sqrt( + (2.0 * degree + 1.0) / (4.0 * kPi) + * factorial_ratio(degree, absolute)); + } + } + int index = 0; + for (int degree = 0; degree <= kOrder; ++degree) { + for (int order = -degree; order <= degree; ++order) { + const int absolute = std::abs(order); + const double normalization = norm[degree][absolute]; + const double legendre = associated_legendre( + degree, absolute, x, pmm[absolute]); + if (order > 0) { + basis[index] = std::sqrt(2.0) * normalization * legendre + * std::cos(order * azimuth); + } else if (order < 0) { + basis[index] = std::sqrt(2.0) * normalization * legendre + * std::sin(absolute * azimuth); + } else { + basis[index] = normalization * legendre; + } + ++index; + } + } + } + +private: + static double factorial_ratio(int degree, int order) noexcept { + double ratio = 1.0; + for (int value = degree - order + 1; value <= degree + order; ++value) { + ratio /= static_cast(value); + } + return ratio; + } + + static double pmm_value(int m, double x) noexcept { + if (m == 0) { + return 1.0; + } + double double_factorial = 1.0; + for (int value = 1; value <= 2 * m - 1; value += 2) { + double_factorial *= static_cast(value); + } + double value = double_factorial + * std::pow(std::max(0.0, 1.0 - x * x), 0.5 * m); + if (m % 2 == 1) { + value = -value; + } + return value; + } + + static double associated_legendre(int degree, int order, double x, + double pmm) noexcept { + if (degree == order) { + return pmm; + } + double pm1 = pmm; + double pmm1 = (2.0 * order + 1.0) * x * pmm; + if (degree == order + 1) { + return pmm1; + } + double result = 0.0; + for (int l = order + 2; l <= degree; ++l) { + result = ((2.0 * l - 1.0) * x * pmm1 + - (l + order - 1.0) * pm1) / (l - order); + pm1 = pmm1; + pmm1 = result; + } + return result; + } +}; + +// --------------------------------------------------------------------------- +// Renderer +// --------------------------------------------------------------------------- +struct Path { + int delay_slots[2]; + Complex transfer[2][kHybrid]; +}; + +struct SourceState { + double position[3]; + int profile; + double gain; + int enabled; + int special_lfe; + std::vector current; + std::vector target; + int fade_position; + int fade_total; + double late_current; + double late_start; + double late_target; + int64_t late_fade_position; + int64_t late_fade_total; + // The seven paths are a pure function of (position, profile, effective + // gain, special_lfe) plus the configuration that only configure_* can change. + // The wrapper calls set_source for every source on every 512-sample block and + // the timeline holds a position constant between OAMD updates, so the same + // paths were rebuilt from scratch over and over. The memo stores the last + // result and the exact bit pattern of the arguments that produced it; a hit + // reuses those bits instead of recomputing them. The fade state machine and + // the late-send envelope below run identically either way. + double memo_position[3] = {0.0, 0.0, 0.0}; + double memo_effective = 0.0; + int memo_profile = 0; + int memo_special_lfe = 0; + int memo_valid = 0; + std::vector memo_paths; +}; + +constexpr double kDistanceM[3] = {1.00000465, 2.19327927, 6.40177584}; +constexpr double kMinimumDistance = 0.10; +constexpr double kCoupling = 0.01318359375; +constexpr double kRoomCalibration = 1.4; +constexpr double kLateSend[3] = {0.06, 0.16, 0.28}; +constexpr double kAir = 0.002; + +class Renderer final { +public: + Renderer() noexcept { + reset_state(); + } + + int configure_kernels(const double* qmf_analysis, const double* hybrid_low, + const int16_t* hybrid_indices, const double* hybrid_values, + uint32_t hybrid_count, const double* qmf_basis, + const double* qmf_taps) noexcept { + if (!qmf_analysis || !hybrid_low || !hybrid_indices || !hybrid_values + || !qmf_basis || !qmf_taps || hybrid_count == 0) { + return fail("invalid sofa binaural kernel configuration"); + } + analysis_.configure(qmf_analysis); + hybrid_analysis_.configure(hybrid_low); + hybrid_synthesis_.configure(hybrid_indices, hybrid_values, hybrid_count); + synthesis_.configure(qmf_basis, qmf_taps); + kernels_ready_ = true; + reset(); + return 0; + } + + int configure_field(const double* coefficients, const double* delay_coefficients, + const double* delay_bounds, const double* band_centers, + double measurement_radius_m) noexcept { + if (!coefficients || !delay_coefficients || !delay_bounds || !band_centers + || !std::isfinite(measurement_radius_m) || measurement_radius_m <= 0.0) { + return fail("invalid sofa binaural field configuration"); + } + for (int term = 0; term < kTerms; ++term) { + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kHybrid; ++band) { + const size_t source = + ((static_cast(term) * 2 + ear) * kHybrid + band) * 2; + field_coeff_[term][ear][band] = { + coefficients[source], coefficients[source + 1]}; + } + delay_coeff_[term][ear] = + delay_coefficients[static_cast(term) * 2 + ear]; + } + } + std::memcpy(delay_bounds_, delay_bounds, sizeof(delay_bounds_)); + std::memcpy(centers_, band_centers, sizeof(centers_)); + measurement_radius_ = measurement_radius_m; + const double maximum = std::max(delay_bounds_[0][1], delay_bounds_[1][1]); + hrtf_slots_ = static_cast( + std::ceil(maximum / static_cast(kHop))); + field_ready_ = true; + reset(); + return 0; + } + + int configure_room(const double* dims, const double* listener, + const double* wall_gains, double speed, + const uint32_t* fdn_delays, const double* fdn_feedback, + double damping, double fdn_gain, + const uint32_t* allpass_delays, const double* allpass_gains, + uint32_t enable_early, uint32_t enable_late) noexcept { + if (!dims || !listener || !wall_gains || !fdn_delays || !fdn_feedback + || !allpass_delays || !allpass_gains || !(speed > 0.0) + || !(damping >= 0.0 && damping < 1.0)) { + return fail("invalid sofa binaural room configuration"); + } + // A zero delay-line length makes the per-sample `% delay` an integer + // divide by zero. Rejecting it here cannot change any accepted input. + for (int line = 0; line < 4; ++line) { + if (fdn_delays[line] == 0u) { + return fail("invalid sofa binaural room configuration"); + } + } + for (int line = 0; line < 2; ++line) { + if (allpass_delays[line] == 0u) { + return fail("invalid sofa binaural room configuration"); + } + } + std::memcpy(dims_, dims, sizeof(dims_)); + std::memcpy(listener_, listener, sizeof(listener_)); + std::memcpy(wall_gain_, wall_gains, sizeof(wall_gain_)); + speed_ = speed; + std::memcpy(fdn_delays_, fdn_delays, sizeof(fdn_delays_)); + std::memcpy(fdn_feedback_, fdn_feedback, sizeof(fdn_feedback_)); + damping_ = damping; + fdn_gain_ = fdn_gain; + std::memcpy(allpass_delays_, allpass_delays, sizeof(allpass_delays_)); + std::memcpy(allpass_gains_, allpass_gains, sizeof(allpass_gains_)); + enable_early_reflections_ = enable_early != 0; + enable_late_room_ = enable_late != 0; + for (int line = 0; line < 4; ++line) { + fdn_buffers_[line].assign(fdn_delays_[line], 0.0); + } + for (int line = 0; line < 2; ++line) { + allpass_buffers_[line].assign(allpass_delays_[line], 0.0); + } + room_ready_ = true; + reset(); + return 0; + } + + int reset() noexcept { + analysis_.reset(); + hybrid_analysis_.reset(); + synthesis_.reset(); + reset_state(); + return 0; + } + + const char* error() const noexcept { + return error_[0] ? error_ : ""; + } + + int set_source(uint32_t source, const double* position, uint32_t profile, + double gain, uint32_t enabled, uint32_t special_lfe, + uint32_t fade) noexcept { + if (!kernels_ready_ || !field_ready_ || !room_ready_) { + return fail("sofa binaural renderer is not configured"); + } + if (source >= kChannels || !position || profile > 2) { + return fail("invalid sofa binaural source update"); + } + SourceState& state = sources_[source]; + state.position[0] = position[0]; + state.position[1] = position[1]; + state.position[2] = position[2]; + state.profile = static_cast(profile); + state.gain = gain; + state.enabled = enabled != 0; + state.special_lfe = special_lfe != 0; + + const double effective = enabled ? gain : 0.0; + // Reuse the memoised paths when the arguments are bit-identical to the + // ones that produced them. Everything make_path reads -- the direction and + // distance derived from `position`, the profile, the effective gain, the LFE + // flag, and the field/room tables -- is covered by this key or fixed by + // configure_*, and the side effect ordinary_paths has on + // maximum_early_delay_ is a maximum of the same values, so reusing the + // stored bits is the same as recomputing them. + const int memo_special_lfe = state.special_lfe ? 1 : 0; + const bool memo_hit = state.memo_valid != 0 && state.memo_profile == state.profile + && state.memo_special_lfe == memo_special_lfe + && std::memcmp(state.memo_position, position, sizeof(state.memo_position)) == 0 + && std::memcmp(&state.memo_effective, &effective, sizeof(effective)) == 0; + std::vector& paths = state.memo_paths; + double late_send = 0.0; + double direction[3]; + double radius; + normalize_adm(position, direction, radius); + const double distance = + std::max(kMinimumDistance, radius * kDistanceM[state.profile]); + if (!memo_hit) { + paths.clear(); + if (state.special_lfe) { + paths.push_back(lfe_path(effective)); + } else { + paths = ordinary_paths(direction, distance, state.profile, effective); + } + std::memcpy(state.memo_position, position, sizeof(state.memo_position)); + std::memcpy(&state.memo_effective, &effective, sizeof(effective)); + state.memo_profile = state.profile; + state.memo_special_lfe = memo_special_lfe; + state.memo_valid = 1; + } + if (!state.special_lfe && enabled && enable_late_room_) { + const double base = kLateSend[state.profile]; + const double radial = std::min( + std::max(std::sqrt(std::max(radius, 0.0)), 0.25), 1.5); + late_send = effective * kRoomCalibration * base * radial; + } + set_late_target(source, late_send, fade != 0); + + const int fade_slots = (fade && processed_slots_ > 0) ? kTransitionSlots : 0; + if (!state.target.empty()) { + state.current = state.target; + state.target.clear(); + } + if (processed_slots_ == 0 || fade_slots == 0) { + state.current = paths; + state.target.clear(); + state.fade_position = 0; + state.fade_total = 0; + } else { + state.target = paths; + state.fade_position = 0; + state.fade_total = fade_slots; + } + return 0; + } + + int process(const double* input, uint32_t sample_count, double output_gain, + double* output) noexcept { + if (!kernels_ready_ || !field_ready_ || !room_ready_) { + return fail("sofa binaural renderer is not configured"); + } + if (sample_count == 0 || sample_count > kMaxBlockSamples + || sample_count % kHop != 0 || !output) { + return fail("sofa binaural process requires 64-sample alignment"); + } + const int slots = static_cast(sample_count / kHop); + process_internal(input, slots, output_gain); + uint32_t skip = std::min(latency_to_discard_, sample_count); + latency_to_discard_ -= skip; + processed_input_samples_ += sample_count; + std::memcpy(output, output_.data() + static_cast(skip) * 2, + static_cast(sample_count - skip) * 2 * sizeof(double)); + return static_cast(sample_count - skip); + } + + int finish(uint32_t flush_samples, double* output, uint32_t capacity) noexcept { + if (!kernels_ready_ || !field_ready_ || !room_ready_) { + return fail("sofa binaural renderer is not configured"); + } + if (flush_samples == 0 || flush_samples > kMaxBlockSamples + || flush_samples % kHop != 0 || !output || capacity < flush_samples) { + return fail("invalid sofa binaural finish request"); + } + const int slots = static_cast(flush_samples / kHop); + process_internal(nullptr, slots, 1.0); + uint32_t skip = std::min(latency_to_discard_, flush_samples); + latency_to_discard_ -= skip; + processed_input_samples_ += flush_samples; + std::memcpy(output, output_.data() + static_cast(skip) * 2, + static_cast(flush_samples - skip) * 2 * sizeof(double)); + return static_cast(flush_samples - skip); + } + +private: + static void normalize_adm(const double* position, double* direction, + double& radius) noexcept { + const double r = std::sqrt(position[0] * position[0] + + position[1] * position[1] + + position[2] * position[2]); + radius = r; + if (r > 1.0e-15) { + direction[0] = position[0] / r; + direction[1] = position[1] / r; + direction[2] = position[2] / r; + } else { + direction[0] = 0.0; + direction[1] = 1.0; + direction[2] = 0.0; + } + } + + static double direct_level_gain(int profile, double distance) noexcept { + if (profile == 0) { + return 1.0; + } + return 1.0 / std::sqrt(1.0 + kCoupling * distance * distance); + } + + double inverse_distance_gain(double path_distance) const noexcept { + return measurement_radius_ / path_distance; + } + + Path make_path(const double* direction, double extra_delay, + double amplitude) noexcept { + double basis[kTerms]; + // ADM (+X right, +Y front, +Z up) -> SOFA listener (+X front, +Y left): + // (x, y, z)_sofa = (y_adm, -x_adm, z_adm) + const double listener_direction[3] = { + direction[1], -direction[0], direction[2]}; + RealSh::evaluate(listener_direction, basis); + Complex aligned[2][kHybrid]; + double delay[2]; + double delay_value[2] = {0.0, 0.0}; + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kHybrid; ++band) { + aligned[ear][band] = {0.0, 0.0}; + } + } + // The 36 spherical-harmonic terms are independent contributions to the + // same 2 x 77 bands, so the band axis is what the dispatched accumulate + // spreads across its lanes. Each band still adds `field * term` once per + // term, in term order, with the same two roundings; only the delay sum -- + // which is a reduction -- stays scalar and keeps its own order. + for (int term = 0; term < kTerms; ++term) { + for (int ear = 0; ear < 2; ++ear) { + delay_value[ear] += basis[term] * delay_coeff_[term][ear]; + } + joc::simd::complex_axpy( + reinterpret_cast(&aligned[0][0]), + reinterpret_cast(&field_coeff_[term][0][0]), basis[term], + 2u * kHybrid); + } + for (int ear = 0; ear < 2; ++ear) { + delay[ear] = std::min(std::max(delay_value[ear], delay_bounds_[ear][0]), + delay_bounds_[ear][1]); + } + Path path; + for (int ear = 0; ear < 2; ++ear) { + const double total = delay[ear] + extra_delay; + const double slots = std::floor(total / kHop); + path.delay_slots[ear] = static_cast(slots); + const double residual = total - slots * kHop; + for (int band = 0; band < kHybrid; ++band) { + // Python transfer = raw aligned gains x residual-delay phase x + // amplitude (the integer-slot part is the delay_slots history). + const double phase = -2.0 * kPi * centers_[band] + * residual / kSampleRate; + const Complex rotated = { + aligned[ear][band].re * std::cos(phase) + - aligned[ear][band].im * std::sin(phase), + aligned[ear][band].re * std::sin(phase) + + aligned[ear][band].im * std::cos(phase)}; + path.transfer[ear][band] = mulr(rotated, amplitude); + } + } + return path; + } + + Path lfe_path(double gain) noexcept { + Path path; + path.delay_slots[0] = 0; + path.delay_slots[1] = 0; + for (int band = 0; band < kHybrid; ++band) { + const double frequency = centers_[band]; + double lowpass = 1.0; + if (frequency >= 180.0) { + lowpass = 0.0; + } else if (frequency > 120.0) { + const double amount = (frequency - 120.0) / 60.0; + const double value = std::cos(0.5 * kPi * amount); + lowpass = value * value; + } + path.transfer[0][band] = {gain * lowpass / std::sqrt(2.0), 0.0}; + path.transfer[1][band] = {gain * lowpass / std::sqrt(2.0), 0.0}; + } + return path; + } + + std::vector ordinary_paths(const double* direction, double distance, + int profile, double gain) noexcept { + std::vector paths; + paths.push_back( + make_path(direction, 0.0, gain * direct_level_gain(profile, distance))); + if (enable_early_reflections_) { + double source[3] = { + listener_[0] + direction[0] * distance, + listener_[1] + direction[1] * distance, + listener_[2] + direction[2] * distance, + }; + for (int axis = 0; axis < 3; ++axis) { + for (int side = 0; side < 2; ++side) { + double image[3] = {source[0], source[1], source[2]}; + image[axis] = (side == 0) ? -image[axis] + : 2.0 * dims_[axis] - image[axis]; + double vector[3] = { + image[0] - listener_[0], + image[1] - listener_[1], + image[2] - listener_[2], + }; + const double path_distance = std::sqrt( + vector[0] * vector[0] + vector[1] * vector[1] + + vector[2] * vector[2]); + double path_direction[3] = { + vector[0] / path_distance, + vector[1] / path_distance, + vector[2] / path_distance, + }; + const double extra = std::max( + 0.0, (path_distance - distance) * kSampleRate / speed_); + const double air = + std::exp(-kAir * std::max(path_distance - distance, 0.0)); + const double amplitude = gain * kRoomCalibration + * wall_gain_[axis * 2 + side] * air + * inverse_distance_gain(path_distance); + paths.push_back(make_path(path_direction, extra, amplitude)); + maximum_early_delay_ = std::max(maximum_early_delay_, extra); + } + } + } + return paths; + } + + void set_late_target(int source, double value, int fade) noexcept { + const int64_t fade_samples = + (fade && processed_input_samples_ > 0) ? kTransitionSlots * kHop : 0; + SourceState& state = sources_[source]; + if (fade_samples == 0) { + state.late_current = value; + state.late_start = value; + state.late_target = value; + state.late_fade_position = 0; + state.late_fade_total = 0; + } else { + state.late_start = state.late_current; + state.late_target = value; + state.late_fade_position = 0; + state.late_fade_total = fade_samples; + } + } + + void process_internal(const double* input, int slots, double output_gain) noexcept { + const uint32_t sample_count = static_cast(slots) * kHop; + // These four planes are written in full before they are read, so they + // are reused scratch buffers. `assign` keeps the capacity, so after the + // first block each one is a fill with no allocation, and the fills that are + // load-bearing (the mono and late accumulators, and the direct/early output + // that is only added into) are preserved exactly. + // 1) late send envelopes -> mono + std::vector& mono = mono_; + mono.assign(sample_count, 0.0); + for (int source = 0; source < kChannels; ++source) { + SourceState& state = sources_[source]; + const int64_t total = state.late_fade_total; + if (total == 0) { + if (input && state.late_current != 0.0) { + for (uint32_t s = 0; s < sample_count; ++s) { + mono[s] += input[static_cast(s) * kChannels + source] + * state.late_current; + } + } + continue; + } + int64_t position = state.late_fade_position; + for (uint32_t s = 0; s < sample_count; ++s) { + position += 1; + double amount = static_cast(position) + / static_cast(total); + amount = std::min(std::max(amount, 0.0), 1.0); + const double value = state.late_start * (1.0 - amount) + + state.late_target * amount; + if (input) { + mono[s] += input[static_cast(s) * kChannels + source] + * value; + } + } + if (position >= total) { + state.late_current = state.late_target; + state.late_start = state.late_target; + state.late_fade_position = 0; + state.late_fade_total = 0; + } else { + double amount = static_cast(position) + / static_cast(total); + amount = std::min(std::max(amount, 0.0), 1.0); + state.late_current = + state.late_start * (1.0 - amount) + state.late_target * amount; + state.late_fade_position = position; + } + } + + // 2) FDN + 961-sample stereo delay + std::vector& late_pcm = late_pcm_; + late_pcm.assign(static_cast(sample_count) * 2, 0.0); + if (enable_late_room_) { + diffused_.assign(mono.begin(), mono.end()); + for (int line = 0; line < 2; ++line) { + allpass(line, diffused_, &allpass_work_); + diffused_.swap(allpass_work_); + } + const std::vector& diffused = diffused_; + for (uint32_t s = 0; s < sample_count; ++s) { + const double value = diffused[s]; + double delayed[4]; + for (int line = 0; line < 4; ++line) { + delayed[line] = fdn_buffers_[line][fdn_positions_[line]]; + } + double damping_state[4]; + for (int line = 0; line < 4; ++line) { + damping_state[line] = damping_ * damping_state_[line] + + (1.0 - damping_) * delayed[line]; + damping_state_[line] = damping_state[line]; + } + const double fdn_left = damping_state[0] + damping_state[1] + - damping_state[2] - damping_state[3]; + const double fdn_right = damping_state[0] - damping_state[1] + + damping_state[2] - damping_state[3]; + const double out_left = + late_ring_[static_cast(late_pos_) * 2]; + const double out_right = + late_ring_[static_cast(late_pos_) * 2 + 1]; + late_pcm[s * 2] = out_left; + late_pcm[s * 2 + 1] = out_right; + late_ring_[static_cast(late_pos_) * 2] = + fdn_gain_ * 0.5 * fdn_left; + late_ring_[static_cast(late_pos_) * 2 + 1] = + fdn_gain_ * 0.5 * fdn_right; + late_pos_ = (late_pos_ + 1) % kLatency; + // feedback = hadamard4/2 @ (damping_state * feedback_gain) + // H4[i][j] = -1 when popcount(i & j) is odd + double feedback[4]; + for (int target = 0; target < 4; ++target) { + double acc = 0.0; + for (int source_line = 0; source_line < 4; ++source_line) { + const bool odd = (static_cast(target & source_line) + ? (std::popcount(static_cast( + target & source_line)) & 1u) != 0u + : false); + const double sign = odd ? -1.0 : 1.0; + acc += sign * damping_state[source_line] + * fdn_feedback_[source_line]; + } + feedback[target] = 0.5 * acc; + } + const double input_vector[4] = {0.5, -0.5, 0.5, 0.5}; + for (int line = 0; line < 4; ++line) { + const double write = + input_vector[line] * value + feedback[line]; + fdn_buffers_[line][fdn_positions_[line]] = write; + fdn_positions_[line] = + (fdn_positions_[line] + 1) % fdn_delays_[line]; + } + } + } + + // 3) analysis chain + analysis_.process(input ? input : zeros_.data(), slots, qmf_work_.data()); + hybrid_analysis_.process(qmf_work_.data(), slots, hybrid_work_.data()); + // 4) per-object direct/early with crossfade + std::vector& direct_and_early = direct_early_; + direct_and_early.assign(static_cast(slots) * 2 * kHybrid, Complex{0.0, 0.0}); + for (int slot = 0; slot < slots; ++slot) { + const Complex* hybrid_slot = + hybrid_work_.data() + static_cast(slot) * kChannels * kHybrid; + for (int source = 0; source < kChannels; ++source) { + std::memcpy(history_[source].data() + + static_cast(position_) * kHybrid, + hybrid_slot + static_cast(source) * kHybrid, + kHybrid * sizeof(Complex)); + } + Complex* out_slot = + direct_and_early.data() + static_cast(slot) * 2 * kHybrid; + for (int source = kChannels - 1; source >= 0; --source) { + SourceState& state = sources_[source]; + if (state.target.empty()) { + render_paths(source, state.current, 1.0, out_slot); + continue; + } + state.fade_position += 1; + double amount = static_cast(state.fade_position) + / static_cast(state.fade_total); + amount = std::min(std::max(amount, 0.0), 1.0); + render_paths(source, state.current, 1.0 - amount, out_slot); + render_paths(source, state.target, amount, out_slot); + if (state.fade_position >= state.fade_total) { + state.current = state.target; + state.target.clear(); + state.fade_position = 0; + state.fade_total = 0; + } + } + position_ = (position_ + 1) % history_slots_; + processed_slots_ += 1; + } + // 5) synthesis chain + hybrid_synthesis_.process(direct_and_early.data(), slots, + qmf_synth_work_.data()); + synthesis_.process(qmf_synth_work_.data(), slots, pcm_work_.data()); + // 6) mix, gain, interleave [samples][2] + for (uint32_t s = 0; s < sample_count; ++s) { + const int slot = static_cast(s / kHop); + const int b = static_cast(s % kHop); + const double direct_left = + pcm_work_[(static_cast(slot) * 2) * 64 + b]; + const double direct_right = + pcm_work_[(static_cast(slot) * 2 + 1) * 64 + b]; + output_[static_cast(s) * 2] = + (direct_left + late_pcm[static_cast(s) * 2]) * output_gain; + output_[static_cast(s) * 2 + 1] = + (direct_right + late_pcm[static_cast(s) * 2 + 1]) * output_gain; + } + } + + void render_paths(int source, const std::vector& paths, double scale, + Complex* out) const noexcept { + for (const Path& path : paths) { + const int slots = static_cast(history_slots_); + // The history index: position_ is in [0, slots), so for any delay_slots + // <= slots the raw index lands in [0, 2*slots) and this conditional is + // exactly `% slots`. A longer delay can make the raw index negative, + // where C++ `%` would produce an out-of-bounds negative index; the + // `raw < 0` arm wraps it into range instead. + const int raw0 = static_cast(position_) + slots - path.delay_slots[0]; + const int raw1 = static_cast(position_) + slots - path.delay_slots[1]; + const int index0 = raw0 >= slots ? raw0 - slots : (raw0 < 0 ? raw0 + slots : raw0); + const int index1 = raw1 >= slots ? raw1 - slots : (raw1 < 0 ? raw1 + slots : raw1); + const Complex* history = history_[source].data(); + // The 77 bands of an ear are independent accumulations into + // independent outputs, so they are what the dispatched kernel spreads + // across its lanes; each lane keeps this loop's `h * t * scale` with its + // own two roundings, and the ears read their own history rows. + joc::simd::render_hybrid_path( + reinterpret_cast(out), + reinterpret_cast(path.transfer), + reinterpret_cast(history + index0 * kHybrid), + reinterpret_cast(history + index1 * kHybrid), scale); + } + } + + void allpass(int line, const std::vector& source, + std::vector* output) noexcept { + // Every element is assigned below, so only the size has to be established. + output->resize(source.size()); + const double gain = allpass_gains_[line]; + const uint32_t delay = allpass_delays_[line]; + for (size_t i = 0; i < source.size(); ++i) { + const double delayed = allpass_buffers_[line][allpass_positions_[line]]; + const double result = delayed - gain * source[i]; + allpass_buffers_[line][allpass_positions_[line]] = + source[i] + gain * result; + allpass_positions_[line] = (allpass_positions_[line] + 1) % delay; + (*output)[i] = result; + } + } + + int fail(const char* message) noexcept { + std::snprintf(error_, sizeof(error_), "%s", message); + return -1; + } + + void reset_state() noexcept { + latency_to_discard_ = kLatency; + processed_input_samples_ = 0; + processed_slots_ = 0; + position_ = 0; + maximum_early_delay_ = 0.0; + history_slots_ = kEarlyHistory + hrtf_slots_; + history_.assign(kChannels, + std::vector( + static_cast(history_slots_) * kHybrid, + Complex{0.0, 0.0})); + // Re-assigning the source states is also what invalidates the + // set_source path memo, because the memo fields are SourceState members + // and a fresh SourceState starts with memo_valid == 0. Every configure_* + // reaches reset_state() through reset(), so a reconfigured renderer can + // never serve a path derived from the previous configuration. If this + // function is ever changed to reset the fields in place, clear the memo + // explicitly here instead. + sources_.assign(kChannels, SourceState{}); + for (int source = 0; source < kChannels; ++source) { + sources_[source].position[0] = 0.0; + sources_[source].position[1] = 1.0; + sources_[source].position[2] = 0.0; + sources_[source].profile = 1; + sources_[source].gain = 1.0; + sources_[source].enabled = 1; + sources_[source].special_lfe = 0; + sources_[source].fade_position = 0; + sources_[source].fade_total = 0; + sources_[source].late_current = 0.0; + sources_[source].late_start = 0.0; + sources_[source].late_target = 0.0; + sources_[source].late_fade_position = 0; + sources_[source].late_fade_total = 0; + } + for (int line = 0; line < 4; ++line) { + fdn_positions_[line] = 0; + damping_state_[line] = 0.0; + if (!fdn_buffers_[line].empty()) { + std::fill(fdn_buffers_[line].begin(), fdn_buffers_[line].end(), 0.0); + } + } + for (int line = 0; line < 2; ++line) { + allpass_positions_[line] = 0; + if (!allpass_buffers_[line].empty()) { + std::fill(allpass_buffers_[line].begin(), + allpass_buffers_[line].end(), 0.0); + } + } + late_pos_ = 0; + late_ring_.fill(0.0); + error_[0] = '\0'; + } + + QmfAnalysis analysis_; + HybridAnalysis hybrid_analysis_; + HybridSynthesis hybrid_synthesis_; + QmfSynthesis synthesis_; + bool kernels_ready_ = false; + bool field_ready_ = false; + bool room_ready_ = false; + + Complex field_coeff_[kTerms][2][kHybrid]; + double delay_coeff_[kTerms][2]; + double delay_bounds_[2][2]; + double centers_[kHybrid]; + double measurement_radius_ = 1.0; + uint32_t hrtf_slots_ = 0; + + double dims_[3]; + double listener_[3]; + double wall_gain_[6]; + double speed_ = 343.3; + uint32_t fdn_delays_[4]; + double fdn_feedback_[4]; + double damping_ = 0.32; + double fdn_gain_ = 0.22; + uint32_t allpass_delays_[2]; + double allpass_gains_[2]; + + uint32_t latency_to_discard_ = kLatency; + uint64_t processed_input_samples_ = 0; + int64_t processed_slots_ = 0; + uint32_t history_slots_ = kEarlyHistory; + uint32_t position_ = 0; + double maximum_early_delay_ = 0.0; + std::vector> history_; + std::vector sources_; + + std::vector fdn_buffers_[4]; + uint32_t fdn_positions_[4]; + double damping_state_[4]; + std::vector allpass_buffers_[2]; + uint32_t allpass_positions_[2]; + std::array late_ring_{}; + uint32_t late_pos_ = 0; + + std::array qmf_work_{}; + std::array hybrid_work_{}; + std::array qmf_synth_work_{}; + std::array pcm_work_{}; + std::array output_{}; + std::array zeros_{}; + // Reused per-block scratch (sized once by the first block's `assign`). + std::vector mono_; + std::vector late_pcm_; + std::vector diffused_; + std::vector allpass_work_; + std::vector direct_early_; + + char error_[256]; + bool enable_early_reflections_ = true; + bool enable_late_room_ = true; +}; + +} // namespace ejoc::sofa_binaural + +using ejoc::sofa_binaural::Renderer; + +extern "C" { + +ejoc_sofa_binaural_handle EJOC_CALL ejoc_sofa_binaural_create(void) { + try { + return new (std::nothrow) Renderer(); + } catch (...) { + return nullptr; + } +} + +void EJOC_CALL ejoc_sofa_binaural_destroy(ejoc_sofa_binaural_handle handle) { + delete static_cast(handle); +} + +int EJOC_CALL ejoc_sofa_binaural_reset(ejoc_sofa_binaural_handle handle) { + return handle ? static_cast(handle)->reset() : -1; +} + +const char* EJOC_CALL ejoc_sofa_binaural_last_error( + ejoc_sofa_binaural_handle handle) { + return handle ? static_cast(handle)->error() : "null handle"; +} + +int EJOC_CALL ejoc_sofa_binaural_configure_kernels( + ejoc_sofa_binaural_handle handle, const double* qmf_analysis, + const double* hybrid_low, const int16_t* hybrid_indices, + const double* hybrid_values, uint32_t hybrid_count, const double* qmf_basis, + const double* qmf_taps) { + return handle ? static_cast(handle)->configure_kernels( + qmf_analysis, hybrid_low, hybrid_indices, hybrid_values, hybrid_count, + qmf_basis, qmf_taps) : -1; +} + +int EJOC_CALL ejoc_sofa_binaural_configure_field( + ejoc_sofa_binaural_handle handle, const double* coefficients, + const double* delay_coefficients, const double* delay_bounds, + const double* band_centers, double measurement_radius_m) { + return handle ? static_cast(handle)->configure_field( + coefficients, delay_coefficients, delay_bounds, band_centers, + measurement_radius_m) : -1; +} + +int EJOC_CALL ejoc_sofa_binaural_configure_room( + ejoc_sofa_binaural_handle handle, const double* room_dims, + const double* listener_pos, const double* wall_gains, double speed_of_sound, + const uint32_t* fdn_delays, const double* fdn_feedback, double damping, + double fdn_output_gain, const uint32_t* allpass_delays, + const double* allpass_gains, uint32_t enable_early, uint32_t enable_late) { + return handle ? static_cast(handle)->configure_room( + room_dims, listener_pos, wall_gains, speed_of_sound, fdn_delays, + fdn_feedback, damping, fdn_output_gain, allpass_delays, allpass_gains, + enable_early, enable_late) : -1; +} + +int EJOC_CALL ejoc_sofa_binaural_set_source( + ejoc_sofa_binaural_handle handle, uint32_t source, const double* position_adm, + uint32_t profile, double gain, uint32_t enabled, uint32_t special_lfe, + uint32_t fade) { + return handle ? static_cast(handle)->set_source( + source, position_adm, profile, gain, enabled, special_lfe, fade) : -1; +} + +int EJOC_CALL ejoc_sofa_binaural_process( + ejoc_sofa_binaural_handle handle, const double* input16_interleaved, + uint32_t sample_count, double output_gain, double* output_stereo_interleaved) { + return handle ? static_cast(handle)->process( + input16_interleaved, sample_count, output_gain, output_stereo_interleaved) + : -1; +} + +int EJOC_CALL ejoc_sofa_binaural_finish( + ejoc_sofa_binaural_handle handle, uint32_t flush_samples, + double* output_stereo_interleaved, uint32_t capacity) { + return handle ? static_cast(handle)->finish( + flush_samples, output_stereo_interleaved, capacity) : -1; +} + + + + + + + + +} // extern "C" diff --git a/src/cli/joc_cli.cpp b/src/cli/joc_cli.cpp new file mode 100644 index 0000000..4ace304 --- /dev/null +++ b/src/cli/joc_cli.cpp @@ -0,0 +1,795 @@ +// joc_cli -- command line frontend, argument-compatible with the reference +// Python CLI (main.py): the same positional input, the same mode selection +// (ADM BWF by default, --speaker-layout or --binaural), the same option names, +// choices and defaults, and the same default output naming under output/. +// +// Options that exist only because this build has no Python side or no Rosella +// import chain (--backend python, --sofa-hrtf, --personalized-headphone, +// metadata sidecars) fail with an explicit message instead of being ignored. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "foundation/fs_utf8.h" +#include "joc_core.h" + +namespace { + +namespace fs = std::filesystem; +namespace fs_utf8 = joc::fs_utf8; + +constexpr double kRate = 48000.0; +constexpr int kFrameSamples = 1536; + +struct Options { + std::string input; + std::string output; + std::string speaker_output; + std::string binaural_output; + std::string speaker_layout; + bool binaural = false; + std::string speaker_format = "float32"; + std::string binaural_format = "float32"; + std::string clip_action = "ask"; + int speaker_metadata_offset = 1473; + std::string binaural_mode = "mid"; + std::string sofa_hrtf; + std::string compiled_hrtf_cache; + std::string personalized_headphone; + bool personalized_headphone_used = false; + std::string hrtf_cache_policy; + std::string hrtf_cache_dir; + double hrtf_radius_m = 1.0; + double binaural_tail_seconds = 5.0; + double binaural_tail_threshold = 1.0e-8; + int binaural_chunk_frames = 64; + double gain_db = 0.0; + double duration = 0.0; + bool duration_set = false; + int object_delay_samples = 1473; + std::string trajectory_mode = "compact"; + std::string ffmpeg; + double eac3_drc_scale = 0.0; + int eac3_target_level = 0; + std::string backend = "auto"; + std::string native_library; + int native_threads = 0; + bool native_threads_set = false; + std::string metadata_dir; + std::string metadata_cache; + std::string metadata_backend = "auto"; + std::string print_metadata = "none"; + std::string metadata_json; + bool metadata_only = false; + bool keep_raw = false; + bool skip_sha256 = false; + int progress_every = 1000; + // C++-side additions (documented as such; the Python CLI has no equivalent). + std::string bed; + std::string kernels; + std::string work_dir; + std::string report_json; + bool report_json_set = false; + bool dry_run = false; + bool quiet = false; + bool help = false; +}; + +const char* kLayoutChoices = + "2.0 3.0 3.1 4.0 5.0 5.1 5.1.2 5.1.4 6.1 7.0 7.1 7.1.2 7.1.4 9.1.4 9.1.6 22.2"; + +void print_usage() { + std::printf( + "usage: joc_cli [options] input\n" + "\n" + "JustOneCacophony (JOC):E-AC-3 JOC → 25ch ADM BWF、扬声器 WAV 或双耳 WAV\n" + "\n" + "位置参数:\n" + " input 输入 .m4a/.eac3/.ec3\n" + "\n" + "模式(默认输出 ADM BWF):\n" + " --speaker-layout L 直接扬声器渲染布局,例如 2.0、5.1、7.1.2\n" + " 可选值: %s\n" + " --binaural 直接双耳渲染;不生成临时 ADM BWF\n" + "\n" + "输出:\n" + " -o, --output PATH 输出文件;默认 output/<名称>.adm.wav、\n" + " output/<名称>.<布局>.wav 或 output/<名称>.binaural.wav\n" + " --speaker-output PATH 扬声器 WAV 路径;仅与 --speaker-layout 一起使用\n" + " --binaural-output PATH 双耳 WAV 路径;仅与 --binaural 一起使用\n" + " --speaker-format F 扬声器 WAV 格式 float32|int24,默认 float32\n" + " --binaural-format F 双耳 WAV 格式 float32|int24,默认 float32\n" + " --clip-action A int24 削波处理 ask|continue|float32|abort,默认 ask\n" + "\n" + "渲染:\n" + " --speaker-metadata-offset N 扬声器渲染 metadata 相对帧偏移,默认 1473 samples\n" + " --binaural-mode M 双耳渲染模式 off|near|mid|far,默认 mid;\n" + " off 仅用于 ADM BWF(关闭 DBMD 双耳提示)\n" + " --sofa-hrtf PATH SOFA SimpleFreeFieldHRIR 输入;.jochrtf 由本工具内部编译\n" + " --personalized-headphone [PATH] Rosella 个性化模型,默认 " + "HRTF/binaural.personalized_headphone\n" + " --compiled-hrtf-cache PATH 直接读取 .jochrtf(高级用法,跳过 SOFA 编译)\n" + " --hrtf-cache-policy P SOFA 编译缓存策略 none|memory|disk,默认 memory\n" + " --hrtf-cache-dir DIR disk cache 目录,默认 /output/hrtf-cache\n" + " --hrtf-radius-m R 选择最近的 SOFA measurement-radius shell,默认 1.0 m\n" + " --binaural-tail-seconds S 双耳 room/filterbank flush 上限,默认 5 秒\n" + " --binaural-tail-threshold T 双耳尾声裁切阈值,默认 1e-8;主体至少保留原时长\n" + " --binaural-chunk-frames N 双耳内部批处理帧数,默认 64(本构建按 512 块渲染,\n" + " 取值不影响输出)\n" + " --gain-db X 成品增益 dB,默认 0;双耳路径以 float64 应用\n" + " --duration S 只处理开头指定秒数\n" + " --object-delay-samples N 对象 PCM/OAMD 时间补偿,默认 1473 samples\n" + " --trajectory-mode M ADM 对象轨迹表示 compact|dense64,默认 compact\n" + "\n" + "输入与解码:\n" + " --ffmpeg PATH ffmpeg 可执行文件,默认取 FFMPEG 环境变量或 PATH\n" + " --eac3-drc-scale X E-AC-3 解码器 -drc_scale,0=关闭码流 dynrng,默认 0\n" + " --eac3-target-level N E-AC-3 解码器 -target_level,0=不施加,默认 0\n" + " --backend B JOC/扬声器 DSP 后端 auto|native;本构建无 python 后端\n" + " --native-threads N 原生 DSP 总线程数;默认在 4 核以上使用 2\n" + "\n" + "诊断:\n" + " --print-metadata M 诊断元数据输出 none|summary|frames,默认 none\n" + " --metadata-json PATH 元数据汇总 JSON 路径\n" + " --metadata-only 解析/打印元数据后退出\n" + " --keep-raw 额外保留 16ch f32le 对象中间文件\n" + " --skip-sha256 跳过最终文件 SHA-256 全量复扫\n" + " --progress-every N 进度输出间隔,默认 1000 帧(渲染与收尾写盘同一节奏)\n" + "\n" + "本构建特有(Python 版没有对应参数):\n" + " --bed PATH 已解码的 6 通道 float32 PCM;给出后不调用 ffmpeg 解码\n" + " --kernels PATH 双耳滤波器组表 rosella_kernels.npz\n" + " --work-dir DIR 临时目录\n" + " --report-json PATH 结果 JSON 路径;默认 <输出>.report.json\n" + " --dry-run 只校验配置\n" + " --quiet 只输出警告与错误\n", + kLayoutChoices); +} + +[[noreturn]] void fail(const std::string& message) { throw std::runtime_error(message); } + +std::string require_value(const std::vector& arguments, int* index) { + if (static_cast(*index) + 1u >= arguments.size()) { + fail("argument " + arguments[static_cast(*index)] + + ": expected one argument"); + } + return arguments[static_cast(++(*index))]; +} + +double to_double(const std::string& text, const char* name) { + try { + std::size_t used = 0; + const double value = std::stod(text, &used); + if (used != text.size()) { + fail(std::string(name) + ": invalid float value: " + text); + } + return value; + } catch (const std::exception&) { + fail(std::string(name) + ": invalid float value: " + text); + } +} + +long long to_int(const std::string& text, const char* name) { + try { + std::size_t used = 0; + const long long value = std::stoll(text, &used); + if (used != text.size()) { + fail(std::string(name) + ": invalid int value: " + text); + } + return value; + } catch (const std::exception&) { + fail(std::string(name) + ": invalid int value: " + text); + } +} + +void check_choice(const std::string& value, const char* name, + std::initializer_list allowed) { + for (const char* candidate : allowed) { + if (value == candidate) { + return; + } + } + std::string list; + for (const char* candidate : allowed) { + list += list.empty() ? candidate : (", " + std::string(candidate)); + } + fail(std::string(name) + ": invalid choice: '" + value + "' (choose from " + list + ")"); +} + +void parse_args(const std::vector& arguments, Options* options) { + std::vector positional; + const int argc = static_cast(arguments.size()); + for (int index = 1; index < argc; ++index) { + const std::string arg = arguments[static_cast(index)]; + if (arg == "-h" || arg == "--help") { options->help = true; } + else if (arg == "-o" || arg == "--output") { options->output = require_value(arguments, &index); } + else if (arg == "--speaker-output") { options->speaker_output = require_value(arguments, &index); } + else if (arg == "--binaural-output") { options->binaural_output = require_value(arguments, &index); } + else if (arg == "--speaker-layout") { options->speaker_layout = require_value(arguments, &index); } + else if (arg == "--binaural") { options->binaural = true; } + else if (arg == "--speaker-format") { options->speaker_format = require_value(arguments, &index); } + else if (arg == "--binaural-format") { options->binaural_format = require_value(arguments, &index); } + else if (arg == "--clip-action") { options->clip_action = require_value(arguments, &index); } + else if (arg == "--speaker-metadata-offset") { + options->speaker_metadata_offset = static_cast( + to_int(require_value(arguments, &index), "--speaker-metadata-offset")); + } + else if (arg == "--binaural-mode") { options->binaural_mode = require_value(arguments, &index); } + else if (arg == "--sofa-hrtf") { options->sofa_hrtf = require_value(arguments, &index); } + else if (arg == "--compiled-hrtf-cache") { options->compiled_hrtf_cache = require_value(arguments, &index); } + else if (arg == "--personalized-headphone") { + options->personalized_headphone_used = true; + // nargs="?": the path is optional, so the next token may be the input. + // Without a path the executable-anchored default is resolved later. + if (static_cast(index) + 1u < arguments.size() && + arguments[static_cast(index) + 1u][0] != '-') { + options->personalized_headphone = require_value(arguments, &index); + } + } + else if (arg == "--hrtf-cache-policy") { options->hrtf_cache_policy = require_value(arguments, &index); } + else if (arg == "--hrtf-cache-dir") { options->hrtf_cache_dir = require_value(arguments, &index); } + else if (arg == "--hrtf-radius-m") { options->hrtf_radius_m = to_double(require_value(arguments, &index), "--hrtf-radius-m"); } + else if (arg == "--binaural-tail-seconds") { options->binaural_tail_seconds = to_double(require_value(arguments, &index), "--binaural-tail-seconds"); } + else if (arg == "--binaural-tail-threshold") { options->binaural_tail_threshold = to_double(require_value(arguments, &index), "--binaural-tail-threshold"); } + else if (arg == "--binaural-chunk-frames") { options->binaural_chunk_frames = static_cast(to_int(require_value(arguments, &index), "--binaural-chunk-frames")); } + else if (arg == "--gain-db") { options->gain_db = to_double(require_value(arguments, &index), "--gain-db"); } + else if (arg == "--duration") { options->duration = to_double(require_value(arguments, &index), "--duration"); options->duration_set = true; } + else if (arg == "--object-delay-samples") { options->object_delay_samples = static_cast(to_int(require_value(arguments, &index), "--object-delay-samples")); } + else if (arg == "--trajectory-mode") { options->trajectory_mode = require_value(arguments, &index); } + else if (arg == "--ffmpeg") { options->ffmpeg = require_value(arguments, &index); } + else if (arg == "--eac3-drc-scale") { options->eac3_drc_scale = to_double(require_value(arguments, &index), "--eac3-drc-scale"); } + else if (arg == "--eac3-target-level") { options->eac3_target_level = static_cast(to_int(require_value(arguments, &index), "--eac3-target-level")); } + else if (arg == "--backend") { options->backend = require_value(arguments, &index); } + else if (arg == "--native-library") { options->native_library = require_value(arguments, &index); } + else if (arg == "--native-threads") { options->native_threads = static_cast(to_int(require_value(arguments, &index), "--native-threads")); options->native_threads_set = true; } + else if (arg == "--metadata-dir") { options->metadata_dir = require_value(arguments, &index); } + else if (arg == "--metadata-cache") { options->metadata_cache = require_value(arguments, &index); } + else if (arg == "--metadata-backend") { options->metadata_backend = require_value(arguments, &index); } + else if (arg == "--print-metadata") { options->print_metadata = require_value(arguments, &index); } + else if (arg == "--metadata-json") { options->metadata_json = require_value(arguments, &index); } + else if (arg == "--metadata-only") { options->metadata_only = true; } + else if (arg == "--keep-raw") { options->keep_raw = true; } + else if (arg == "--skip-sha256") { options->skip_sha256 = true; } + else if (arg == "--progress-every") { options->progress_every = static_cast(to_int(require_value(arguments, &index), "--progress-every")); } + else if (arg == "--bed") { options->bed = require_value(arguments, &index); } + else if (arg == "--kernels") { options->kernels = require_value(arguments, &index); } + else if (arg == "--work-dir") { options->work_dir = require_value(arguments, &index); } + else if (arg == "--report-json") { options->report_json = require_value(arguments, &index); options->report_json_set = true; } + else if (arg == "--dry-run") { options->dry_run = true; } + else if (arg == "--quiet") { options->quiet = true; } + else if (!arg.empty() && arg[0] == '-' && arg != "-") { fail("unrecognized argument: " + arg); } + else { positional.push_back(arg); } + } + if (positional.size() > 1u) { + fail("unrecognized extra arguments: " + positional[1] + + (positional.size() > 2u ? " ..." : "")); + } + if (!positional.empty()) { + options->input = positional.front(); + } +} + +// Mirrors the reference resolve_output(): /output plus a mode-specific +// name. The project directory is the executable's directory, as upstream uses +// the script's directory, so the layout does not depend on the working directory. +std::string resolve_output(const Options& options, const std::string& source, + const std::string& executable_directory) { + const std::string requested = !options.speaker_output.empty() ? options.speaker_output + : !options.binaural_output.empty() ? options.binaural_output + : options.output; + if (!requested.empty()) { + std::error_code error; + const fs::path absolute = fs::absolute(fs_utf8::to_path(requested), error); + return error ? requested : fs_utf8::from_path(absolute); + } + const fs::path directory = fs_utf8::to_path(executable_directory) / "output"; + const std::string stem = fs_utf8::from_path(fs_utf8::to_path(source).stem()); + if (!options.speaker_layout.empty()) { + return fs_utf8::from_path(directory / + fs_utf8::to_path(stem + "." + options.speaker_layout + ".wav")); + } + if (options.binaural) { + return fs_utf8::from_path(directory / fs_utf8::to_path(stem + ".binaural.wav")); + } + return fs_utf8::from_path(directory / fs_utf8::to_path(stem + ".adm.wav")); +} + +// The project directory the reference anchors its defaults at: the directory of +// the running executable, never the working directory. +std::string executable_dir(const std::string& argv0) { + const std::string own_path = fs_utf8::executable_path(); + if (!own_path.empty()) { + const fs::path path = fs_utf8::to_path(own_path); + if (path.has_parent_path()) { + return fs_utf8::from_path(path.parent_path()); + } + } + if (argv0.empty()) { + return "."; + } + std::error_code error; + const fs::path path = fs::absolute(fs_utf8::to_path(argv0), error); + if (error || path.empty()) { + return "."; + } + return fs_utf8::from_path(path.parent_path()); +} + +std::string find_kernels(const Options& options, const std::string& argv0) { + (void)argv0; + if (!options.kernels.empty() && !fs_utf8::exists(options.kernels)) { + fail("--kernels 指向的文件不存在: " + options.kernels); + } + // Empty means the tables compiled into the library. + return options.kernels; +} + +// Mirrors the reference binaural HRTF resolution (main.py:89-160): the SOFA file +// is the user-facing input and the .jochrtf is only its compiled cache. Paths +// are anchored at the executable directory, as the reference anchors them at the +// project directory. +struct HrtfInput { + std::string sofa_path; // compile this + std::string compiled_path; // or read this .jochrtf directly + std::string cache_dir; // disk policy directory + std::string personalized_path; // Rosella .personalized_headphone + bool disk = false; +}; + +std::string resolve_compiled_hrtf(const Options& options, const std::string& project_directory) { + if (!options.compiled_hrtf_cache.empty()) { + return options.compiled_hrtf_cache; + } + const std::string directory_utf8 = + options.hrtf_cache_dir.empty() + ? fs_utf8::from_path(fs_utf8::to_path(project_directory) / "output" / "hrtf-cache") + : options.hrtf_cache_dir; + if (!fs_utf8::is_directory(directory_utf8)) { + return std::string(); + } + const fs::path directory = fs_utf8::to_path(directory_utf8); + std::vector candidates; + for (const fs::directory_entry& entry : fs::directory_iterator(directory)) { + if (entry.is_regular_file() && entry.path().extension() == ".jochrtf") { + candidates.push_back(entry.path()); + } + } + std::sort(candidates.begin(), candidates.end()); + if (candidates.size() > 1u) { + fail(directory_utf8 + + " 下有多个 .jochrtf 缓存,无法自动选择;请用 --sofa-hrtf PATH 或 " + "--compiled-hrtf-cache PATH 显式指定"); + } + return candidates.empty() ? std::string() : fs_utf8::from_path(candidates.front()); +} + +HrtfInput resolve_hrtf_input(const Options& options, const std::string& project_directory) { + HrtfInput input; + const std::string default_sofa = + fs_utf8::from_path(fs_utf8::to_path(project_directory) / "HRTF" / "binaural.sofa"); + const std::string default_private = fs_utf8::from_path( + fs_utf8::to_path(project_directory) / "HRTF" / "binaural.personalized_headphone"); + const std::string default_cache_dir = + fs_utf8::from_path(fs_utf8::to_path(project_directory) / "output" / "hrtf-cache"); + + if (!options.compiled_hrtf_cache.empty() && !options.hrtf_cache_policy.empty()) { + fail("显式 .jochrtf 输入不能再指定 --hrtf-cache-policy"); + } + if (!options.compiled_hrtf_cache.empty() && options.hrtf_radius_m != 1.0) { + fail("显式 .jochrtf 输入不能再选择 SOFA radius shell"); + } + if (options.personalized_headphone_used && + (!options.hrtf_cache_policy.empty() || !options.hrtf_cache_dir.empty() || + options.hrtf_radius_m != 1.0)) { + fail("Rosella 模型输入不能使用 --hrtf-cache-policy/--hrtf-cache-dir/--hrtf-radius-m"); + } + + std::string sofa = options.sofa_hrtf; + std::string compiled = options.compiled_hrtf_cache; + std::string personalized = + options.personalized_headphone_used ? options.personalized_headphone : std::string(); + if (options.personalized_headphone_used && personalized.empty()) { + // "--personalized-headphone" without a path means the project default. + personalized = default_private; + } + if (sofa.empty() && compiled.empty() && personalized.empty()) { + // The reference order: the SOFA file, then the unique compiled cache, then the + // personalized model. + if (fs_utf8::exists(default_sofa)) { + sofa = default_sofa; + } else { + compiled = resolve_compiled_hrtf(options, project_directory); + if (compiled.empty() && fs_utf8::exists(default_private)) { + personalized = default_private; + } + } + } + if (!personalized.empty()) { + if (!fs_utf8::exists(personalized)) { + fail("双耳模型不存在: " + personalized); + } + input.personalized_path = personalized; + return input; + } + if (sofa.empty() && compiled.empty()) { + if (!options.hrtf_cache_policy.empty() || !options.hrtf_cache_dir.empty() || + options.hrtf_radius_m != 1.0) { + fail("HRTF cache/radius 选项需要 --sofa-hrtf"); + } + fail("--binaural 未找到 HRTF 输入:默认 " + default_sofa + "、" + default_private + + " 或 " + default_cache_dir + + " 下的 .jochrtf 都不存在,请用 --sofa-hrtf PATH、--personalized-headphone PATH " + "或 --compiled-hrtf-cache PATH 指定"); + } + if (sofa.empty() && (!options.hrtf_cache_policy.empty() || !options.hrtf_cache_dir.empty() || + options.hrtf_radius_m != 1.0)) { + fail("HRTF cache/radius 选项需要 --sofa-hrtf"); + } + if (sofa.empty()) { + input.compiled_path = compiled; + return input; + } + const std::string effective_policy = + options.hrtf_cache_policy.empty() ? "memory" : options.hrtf_cache_policy; + if (!options.hrtf_cache_dir.empty() && effective_policy != "disk") { + fail("--hrtf-cache-dir 需要 SOFA 与 disk cache policy 一起使用"); + } + input.sofa_path = sofa; + input.disk = effective_policy == "disk"; + input.cache_dir = options.hrtf_cache_dir.empty() ? default_cache_dir : options.hrtf_cache_dir; + if (!fs_utf8::exists(input.sofa_path)) { + fail("SOFA HRTF 不存在: " + input.sofa_path); + } + return input; +} + +std::uint32_t binaural_mode_value(const std::string& name) { + if (name == "off") { return JOC_BINAURAL_OFF; } + if (name == "near") { return JOC_BINAURAL_NEAR; } + if (name == "far") { return JOC_BINAURAL_FAR; } + return JOC_BINAURAL_MID; +} + +std::uint32_t clip_action_value(const std::string& name) { + if (name == "continue") { return JOC_CLIP_CONTINUE; } + if (name == "float32") { return JOC_CLIP_FLOAT32; } + if (name == "abort") { return JOC_CLIP_ABORT; } + return JOC_CLIP_ASK; +} + +std::string format_eta(double seconds) { + if (seconds < 0.0 || seconds > 86400.0) { + return "--"; + } + char buffer[64]; + std::snprintf(buffer, sizeof(buffer), "%.0fs", seconds); + return buffer; +} + +void JOC_CALL on_event(void* user, const joc_event* event) { + const Options* options = static_cast(user); + if (event == nullptr) { + return; + } + switch (event->type) { + case JOC_EV_PROGRESS: { + if (options->quiet) { + return; + } + const double fraction = event->progress >= 0.0 ? event->progress : 0.0; + const double remaining = + fraction > 0.0 ? event->elapsed_seconds * (1.0 - fraction) / fraction : -1.0; + std::printf("[%s] %llu/%llu %.1fx realtime ETA %s\n", event->stage_name, + static_cast(event->current_frame), + static_cast(event->total_frames), + event->realtime_factor, format_eta(remaining).c_str()); + std::fflush(stdout); + return; + } + case JOC_EV_LOG: { + if (options->quiet || event->log_level < JOC_LOG_INFO || event->message[0] == '\0') { + return; + } + std::printf("[%s] %s\n", event->stage_name, event->message); + std::fflush(stdout); + return; + } + case JOC_EV_WARNING: + std::printf("[warning] %s\n", event->message); + return; + case JOC_EV_ERROR: + std::fprintf(stderr, "[error] %s (%s)\n", event->message, + joc_error_name(event->error_code)); + return; + default: + if (options->quiet || event->log_level < JOC_LOG_INFO || event->message[0] == '\0') { + return; + } + std::printf("[%s] %s\n", event->stage_name, event->message); + return; + } +} + +} // namespace + +int main(int argc, char** argv) { + fs_utf8::configure_console(); + const std::vector arguments = fs_utf8::command_line_arguments(argc, argv); + Options options; + try { + parse_args(arguments, &options); + } catch (const std::exception& error) { + std::fprintf(stderr, "joc_cli: error: %s\n", error.what()); + return 2; + } + if (options.help) { + print_usage(); + return 0; + } + if (options.input.empty()) { + print_usage(); + return 2; + } + + try { + check_choice(options.speaker_format, "--speaker-format", {"float32", "int24"}); + check_choice(options.binaural_format, "--binaural-format", {"float32", "int24"}); + check_choice(options.clip_action, "--clip-action", + {"ask", "continue", "float32", "abort"}); + check_choice(options.binaural_mode, "--binaural-mode", {"off", "near", "mid", "far"}); + check_choice(options.trajectory_mode, "--trajectory-mode", {"compact", "dense64"}); + check_choice(options.backend, "--backend", {"auto", "native", "python"}); + check_choice(options.print_metadata, "--print-metadata", {"none", "summary", "frames"}); + check_choice(options.metadata_backend, "--metadata-backend", {"auto", "emdf", "sidecar"}); + if (!options.hrtf_cache_policy.empty()) { + check_choice(options.hrtf_cache_policy, "--hrtf-cache-policy", + {"none", "memory", "disk"}); + } + + const bool speaker_mode = !options.speaker_layout.empty(); + const bool binaural_mode = options.binaural; + if (speaker_mode && binaural_mode) { + fail("argument --binaural: not allowed with argument --speaker-layout"); + } + if (options.binaural_mode == "off" && (speaker_mode || binaural_mode)) { + fail("--binaural-mode off 仅用于 ADM BWF 输出(关闭 DBMD 双耳提示);" + "直接双耳渲染请使用 near/mid/far"); + } + if (!options.speaker_output.empty() && !speaker_mode) { + fail("--speaker-output 必须与 --speaker-layout 一起使用"); + } + if (!options.binaural_output.empty() && !binaural_mode) { + fail("--binaural-output 必须与 --binaural 一起使用"); + } + const bool specific_output = + !options.speaker_output.empty() || !options.binaural_output.empty(); + if (!options.output.empty() && specific_output) { + fail("-o/--output 与 --speaker-output/--binaural-output 不能同时使用"); + } + if (!options.speaker_output.empty() && !options.binaural_output.empty()) { + fail("--speaker-output 与 --binaural-output 不能同时使用"); + } + if (options.speaker_metadata_offset < 0) { + fail("speaker-metadata-offset 不能为负数"); + } + const bool hrtf_options_used = + !options.sofa_hrtf.empty() || !options.compiled_hrtf_cache.empty() || + options.personalized_headphone_used || !options.hrtf_cache_policy.empty() || + !options.hrtf_cache_dir.empty() || options.hrtf_radius_m != 1.0; + if (hrtf_options_used && !binaural_mode) { + fail("SOFA/HRTF 选项仅与 --binaural 一起使用"); + } + if (!std::isfinite(options.binaural_tail_seconds) || + options.binaural_tail_seconds < 0.0) { + fail("binaural-tail-seconds 必须是非负有限值"); + } + if (!std::isfinite(options.binaural_tail_threshold) || + options.binaural_tail_threshold < 0.0) { + fail("binaural-tail-threshold 必须是非负有限值"); + } + if (options.binaural_chunk_frames <= 0) { + fail("binaural-chunk-frames 必须大于 0"); + } + if (!std::isfinite(options.hrtf_radius_m) || options.hrtf_radius_m <= 0.0) { + fail("hrtf-radius-m 必须是正有限值"); + } + if (options.duration_set && options.duration <= 0.0) { + fail("duration 必须大于 0"); + } + if (options.object_delay_samples < 0) { + fail("object-delay-samples 不能为负数"); + } + if (options.native_threads_set && options.native_threads < 1) { + fail("native-threads 必须大于 0"); + } + if (!std::isfinite(options.gain_db) || std::abs(options.gain_db) > 200.0) { + fail("gain-db 超出支持范围"); + } + // Options this build cannot honour: fail loudly instead of ignoring them. + if (options.backend == "python") { + fail("--backend python 在本构建中不可用(已无 Python 后端);请使用 auto 或 native"); + } + if (options.metadata_backend == "sidecar" || !options.metadata_dir.empty() || + !options.metadata_cache.empty()) { + fail("metadata sidecar 在本构建中不可用(始终直接扫描 EMDF)"); + } + if (!options.native_library.empty()) { + std::fprintf(stderr, "[info] --native-library 在本构建中忽略(单一 joc_core.dll)\n"); + } + if (!fs_utf8::exists(options.input)) { + fail("输入文件不存在: " + options.input); + } + } catch (const std::exception& error) { + std::fprintf(stderr, "joc_cli: error: %s\n", error.what()); + return 2; + } + + const bool speaker_mode = !options.speaker_layout.empty(); + const bool binaural_mode = options.binaural; + const std::string project_directory = + executable_dir(arguments.empty() ? std::string() : arguments.front()); + const std::string output_path = resolve_output(options, options.input, project_directory); + std::error_code directory_error; + fs::create_directories(fs_utf8::to_path(output_path).parent_path(), directory_error); + + joc_task_config config{}; + config.struct_size = sizeof(config); + config.struct_version = JOC_TASK_CONFIG_VERSION; + config.input_path = options.input.c_str(); + config.output_path = output_path.c_str(); + config.ffmpeg_path = options.ffmpeg.empty() ? nullptr : options.ffmpeg.c_str(); + config.bed_path = options.bed.empty() ? nullptr : options.bed.c_str(); + config.work_dir = options.work_dir.empty() ? nullptr : options.work_dir.c_str(); + config.eac3_drc_scale = options.eac3_drc_scale; + config.eac3_target_level = options.eac3_target_level; + config.operation = + binaural_mode ? JOC_OP_BINAURAL : speaker_mode ? JOC_OP_SPEAKER : JOC_OP_ADM_BWF; + const std::string& requested_format = + binaural_mode ? options.binaural_format : options.speaker_format; + config.output_format = + requested_format == "int24" ? JOC_FORMAT_PCM24 : JOC_FORMAT_FLOAT32; + config.clip_action = clip_action_value(options.clip_action); + config.speaker_layout_name = speaker_mode ? options.speaker_layout.c_str() : nullptr; + config.speaker_metadata_offset = static_cast(options.speaker_metadata_offset); + config.binaural_mode = binaural_mode_value(options.binaural_mode); + config.adm_binaural_mode = binaural_mode_value(options.binaural_mode); + config.binaural_tail_seconds = options.binaural_tail_seconds; + config.binaural_tail_threshold = options.binaural_tail_threshold; + config.binaural_chunk_frames = static_cast(options.binaural_chunk_frames); + config.object_delay_samples = static_cast(options.object_delay_samples); + config.trajectory_mode = + options.trajectory_mode == "dense64" ? JOC_TRAJECTORY_DENSE64 : JOC_TRAJECTORY_COMPACT; + config.gain_db = options.gain_db; + config.progress_interval_frames = static_cast(options.progress_every); + config.native_threads = + options.native_threads_set ? static_cast(options.native_threads) : 0u; + config.print_metadata = options.print_metadata == "frames" ? 2u + : options.print_metadata == "summary" ? 1u + : 0u; + config.metadata_json_path = + options.metadata_json.empty() ? nullptr : options.metadata_json.c_str(); + config.duration_frames = + options.duration_set + ? static_cast( + std::ceil(options.duration * kRate / static_cast(kFrameSamples))) + : 0u; + config.flags = 0u; + if (options.skip_sha256) { config.flags |= JOC_TASK_F_SKIP_SHA256; } + if (options.keep_raw) { config.flags |= JOC_TASK_F_KEEP_INTERMEDIATE; } + if (options.metadata_only) { config.flags |= JOC_TASK_F_METADATA_ONLY; } + if (options.quiet) { config.flags |= JOC_TASK_F_QUIET; } + + std::string hrtf_path; + std::string hrtf_sofa_path; + std::string hrtf_cache_dir; + std::string personalized_path; + std::string kernels_path; + if (binaural_mode) { + try { + const HrtfInput input = resolve_hrtf_input(options, project_directory); + hrtf_path = input.compiled_path; + hrtf_sofa_path = input.sofa_path; + hrtf_cache_dir = input.cache_dir; + personalized_path = input.personalized_path; + kernels_path = find_kernels(options, arguments.empty() ? std::string() + : arguments.front()); + } catch (const std::exception& error) { + std::fprintf(stderr, "joc_cli: error: %s\n", error.what()); + return 2; + } + } + config.hrtf_path = hrtf_path.empty() ? nullptr : hrtf_path.c_str(); + config.hrtf_sofa_path = hrtf_sofa_path.empty() ? nullptr : hrtf_sofa_path.c_str(); + config.hrtf_cache_dir = hrtf_cache_dir.empty() ? nullptr : hrtf_cache_dir.c_str(); + config.personalized_headphone_path = + personalized_path.empty() ? nullptr : personalized_path.c_str(); + config.hrtf_cache_policy = options.hrtf_cache_policy == "disk" ? JOC_HRTF_CACHE_DISK + : options.hrtf_cache_policy == "none" ? JOC_HRTF_CACHE_NONE + : JOC_HRTF_CACHE_MEMORY; + config.hrtf_radius_m = options.hrtf_radius_m; + config.kernels_path = kernels_path.empty() ? nullptr : kernels_path.c_str(); + + joc_validation_issue issues[32]; + std::uint32_t issue_count = 0; + const joc_error validated = joc_task_validate(&config, issues, 32u, &issue_count); + for (std::uint32_t index = 0; index < std::min(issue_count, 32u); ++index) { + if (issues[index].severity >= 2u) { + std::fprintf(stderr, "[error] %s: %s\n", issues[index].field, issues[index].message); + } else if (!options.quiet) { + std::fprintf(stderr, "[warning] %s: %s\n", issues[index].field, + issues[index].message); + } + } + if (validated != JOC_OK) { + std::fprintf(stderr, "joc_cli: error: configuration rejected (%u issue(s))\n", issue_count); + return 2; + } + if (options.dry_run) { + std::printf("configuration accepted (%u issue(s))\n", issue_count); + return 0; + } + + joc_event_sink sink{}; + sink.struct_size = sizeof(sink); + sink.callback = &on_event; + sink.user = &options; + + if (!options.quiet) { + const char* mode_name = binaural_mode ? "binaural" : speaker_mode ? "speaker" : "adm"; + std::printf("[cli] %s -> %s (%s)\n", options.input.c_str(), output_path.c_str(), + mode_name); + std::fflush(stdout); + } + + joc_task_result result{}; + const joc_error status = joc_task_execute(&config, &sink, &result); + + const std::string report_path = + options.report_json_set ? options.report_json : (output_path + ".report.json"); + { + std::size_t needed = 0; + joc_task_result_to_json(&result, nullptr, 0u, &needed); + std::vector buffer(needed + 1u); + if (joc_task_result_to_json(&result, buffer.data(), buffer.size(), &needed) == JOC_OK) { + if (std::FILE* file = fs_utf8::fopen(report_path, "wb")) { + std::fwrite(buffer.data(), 1, std::strlen(buffer.data()), file); + std::fputc('\n', file); + std::fclose(file); + } + } + } + + std::printf("\nresult: %s\n", status == JOC_OK ? "ok" : joc_error_name(status)); + std::printf(" output : %s\n", output_path.c_str()); + std::printf(" frames : %llu (%.2f s)\n", + static_cast(result.input_frames), result.duration_sec); + std::printf(" output samples: %llu\n", + static_cast(result.output_samples)); + std::printf(" output bytes : %llu\n", + static_cast(result.output_file_bytes)); + std::printf(" format : %s\n", + result.output_format_actual == JOC_FORMAT_PCM24 ? "int24" : "float32"); + std::printf(" peak : %.9g (%llu sample(s) above full scale)\n", result.output_peak, + static_cast(result.output_over_unity_values)); + std::printf(" sha256 : %s\n", + result.output_sha256[0] != '\0' ? result.output_sha256 : "(skipped)"); + std::printf(" report : %s\n", report_path.c_str()); + // Each stage time is measured where that stage actually runs, and the three + // stages now overlap (see the pipeline in src/task/task.cpp), so the stage + // times deliberately do not add up to the wall-clock total. + std::printf(" timings : decode %.2fs, joc %.2fs, dsp %.2fs, write %.2fs" + " (stage times, concurrent), total %.2fs\n", + result.t_decode_bed, result.t_render, result.t_render_dsp, result.t_write_file, + result.t_total); + if (status != JOC_OK) { + std::fprintf(stderr, "joc_cli: error: %s: %s\n", result.error_stage, result.error_message); + } + return status == JOC_OK ? 0 : 1; +} diff --git a/src/eac3_transport/eac3_reader.cpp b/src/eac3_transport/eac3_reader.cpp new file mode 100644 index 0000000..568bdd1 --- /dev/null +++ b/src/eac3_transport/eac3_reader.cpp @@ -0,0 +1,113 @@ +#include "eac3_transport/eac3_reader.h" + +#include + +#include "foundation/status.h" + +namespace joc::eac3 { + +namespace { +constexpr std::size_t kHeaderBytes = 4; +} // namespace + +void FrameReader::push(const std::uint8_t* data, std::size_t size) { + if (failed_ || data == nullptr || size == 0) { + return; + } + if (consumed_ > 0) { + compact(); + } + buffer_.insert(buffer_.end(), data, data + size); +} + +void FrameReader::compact() { + if (consumed_ == 0) { + return; + } + buffer_.erase(buffer_.begin(), buffer_.begin() + static_cast(consumed_)); + base_offset_ += consumed_; + consumed_ = 0; +} + +void FrameReader::fail(joc_error code, std::string message) { + failed_ = true; + error_ = code; + message_ = std::move(message); +} + +FrameReader::Next FrameReader::next(Frame* out) { + if (failed_) { + return Next::Fail; + } + const std::size_t available = buffer_.size() - consumed_; + if (available == 0) { + return Next::End; + } + const std::uint8_t* p = buffer_.data() + consumed_; + + // The reference implementation rejects a frame whose header does not fit, + // rather than silently resynchronising on the next 0x0B77. + if (available < kHeaderBytes) { + if (finished_) { + fail(JOC_ERR_EAC3_SYNCFRAME, "E-AC-3 syncframe header truncated at end of input"); + return Next::Fail; + } + return Next::End; + } + + const std::uint16_t syncword = static_cast((static_cast(p[0]) << 8) | p[1]); + if (syncword != kSyncword) { + fail(JOC_ERR_EAC3_SYNCFRAME, "invalid E-AC-3 syncword (silent resynchronisation is not allowed)"); + return Next::Fail; + } + + // frmsiz: 11 bits spread over the low 3 bits of byte 2 and all of byte 3, + const std::size_t words = + static_cast(((p[2] & 0x07u) << 8) | p[3]) + 1u; + const std::size_t frame_bytes = words * 2u; + + if (frame_bytes > available) { + if (!finished_) { + return Next::End; + } + fail(JOC_ERR_BITSTREAM_TRUNCATED, + "last E-AC-3 syncframe extends past end of input (declared " + + std::to_string(frame_bytes) + " bytes, remaining " + + std::to_string(available) + ")"); + return Next::Fail; + } + + if (out != nullptr) { + out->data = p; + out->size = frame_bytes; + out->offset = base_offset_ + consumed_; + } + consumed_ += frame_bytes; + stream_offset_ = base_offset_ + consumed_; + ++frames_emitted_; + return Next::Ok; +} + +joc_error FrameReader::frame_bytes(const std::uint8_t* data, std::size_t size, std::size_t offset, + std::size_t* out_frame_bytes) { + if (data == nullptr || out_frame_bytes == nullptr) { + return JOC_ERR_INVALID_ARGUMENT; + } + if (offset + kHeaderBytes > size) { + return JOC_ERR_EAC3_SYNCFRAME; + } + if (static_cast((static_cast(data[offset]) << 8) | data[offset + 1]) != + kSyncword) { + return JOC_ERR_EAC3_SYNCFRAME; + } + const std::size_t words = + static_cast(((data[offset + 2] & 0x07u) << 8) | data[offset + 3]) + 1u; + const std::size_t frame_bytes = words * 2u; + if (offset + frame_bytes > size) { + return JOC_ERR_BITSTREAM_TRUNCATED; + } + *out_frame_bytes = frame_bytes; + return JOC_OK; +} + +} // namespace joc::eac3 diff --git a/src/eac3_transport/eac3_reader.h b/src/eac3_transport/eac3_reader.h new file mode 100644 index 0000000..11ad854 --- /dev/null +++ b/src/eac3_transport/eac3_reader.h @@ -0,0 +1,68 @@ + +#pragma once + +#include +#include +#include +#include + +#include "joc_core.h" + +namespace joc::eac3 { + +struct Frame { + const std::uint8_t* data = nullptr; + std::size_t size = 0; + std::size_t offset = 0; // byte offset of the frame start in the fed stream +}; + +class FrameReader { +public: + enum class Next { + Ok, + End, + Fail + }; + + FrameReader() = default; + FrameReader(const std::uint8_t* data, std::size_t size) { + push(data, size); + finish(); + } + + // Appends bytes to the internal buffer (used in incremental mode). + void push(const std::uint8_t* data, std::size_t size); + + // Declares that no further bytes will arrive; a frame that is still + void finish() { finished_ = true; } + + Next next(Frame* out); + + joc_error error() const { return error_; } + const std::string& error_message() const { return message_; } + + std::size_t frames_emitted() const { return frames_emitted_; } + std::size_t stream_offset() const { return stream_offset_; } + + // report its declared byte length. + static joc_error frame_bytes(const std::uint8_t* data, std::size_t size, std::size_t offset, + std::size_t* out_frame_bytes); + + static constexpr std::uint16_t kSyncword = 0x0B77; + +private: + void compact(); + void fail(joc_error code, std::string message); + + std::vector buffer_; + std::size_t consumed_ = 0; // bytes of buffer_ already turned into frames + std::size_t base_offset_ = 0; + bool finished_ = false; + bool failed_ = false; + joc_error error_ = JOC_OK; + std::string message_; + std::size_t frames_emitted_ = 0; + std::size_t stream_offset_ = 0; +}; + +} // namespace joc::eac3 diff --git a/src/emdf/emdf_parser.cpp b/src/emdf/emdf_parser.cpp new file mode 100644 index 0000000..20ec67f --- /dev/null +++ b/src/emdf/emdf_parser.cpp @@ -0,0 +1,305 @@ +#include "emdf/emdf_parser.h" + +#include +#include + +#include "foundation/bit_reader.h" + +namespace joc::emdf { + +namespace { + +Status syntax_fail(const std::string& message) { + return Status::fail(JOC_ERR_EMDF_SYNTAX, stage::kEmdf, message); +} + +Status truncated_fail(const bits::BitReader& reader) { + return Status::fail(JOC_ERR_BITSTREAM_TRUNCATED, stage::kEmdf, + std::string("EMDF bitstream truncated: ") + reader.error_message()); +} + +} // namespace + +Status parse_at(const std::uint8_t* data, std::size_t size, std::size_t start_bit, Container* out) { + if (data == nullptr || out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kEmdf, "null buffer or output"); + } + if (start_bit + 16u > size * 8u) { + return syntax_fail("EMDF syncword position beyond buffer"); + } + + bits::BitReader reader; + reader.reset(data, size, start_bit); + + if (reader.read(16) != kSyncword) { + return syntax_fail("EMDF syncword mismatch at bit " + std::to_string(start_bit)); + } + const std::uint32_t length = reader.read(16); + const std::size_t body_start = reader.position(); + const std::size_t body_end = body_start + static_cast(length) * 8u; + if (body_end > reader.limit()) { + return syntax_fail("EMDF container length " + std::to_string(length) + + " exceeds buffer at bit " + std::to_string(start_bit)); + } + reader.set_limit_bits(body_end); + + std::uint32_t version = reader.read(2); + if (version == 3u) { + std::uint32_t extra = 0; + if (!bits::variable_bits(reader, 2, 8, &extra)) { + return reader.error() == JOC_ERR_BITSTREAM_TRUNCATED ? truncated_fail(reader) + : syntax_fail(reader.error_message()); + } + version += extra; + } + std::uint32_t key_id = reader.read(3); + if (key_id == 7u) { + std::uint32_t extra = 0; + if (!bits::variable_bits(reader, 3, 8, &extra)) { + return reader.error() == JOC_ERR_BITSTREAM_TRUNCATED ? truncated_fail(reader) + : syntax_fail(reader.error_message()); + } + key_id += extra; + } + if (reader.failed()) { + return truncated_fail(reader); + } + // TS 103 420 JOC uses version 0 / key_id 0; the strict check also rejects + // false 0x5838 markers that happen to sit inside audio data. + if (version != 0u || key_id != 0u) { + return syntax_fail("unsupported EMDF version/key_id " + std::to_string(version) + "/" + + std::to_string(key_id)); + } + + Container container; + container.start_bit = start_bit; + bool terminated = false; + + while (reader.position() + 5u <= body_end) { + std::uint32_t payload_id = reader.read(5); + if (reader.failed()) { + return truncated_fail(reader); + } + if (payload_id == 0u) { + terminated = true; + break; + } + if (payload_id == 0x1Fu) { + std::uint32_t extra = 0; + if (!bits::variable_bits(reader, 5, 8, &extra)) { + return reader.error() == JOC_ERR_BITSTREAM_TRUNCATED ? truncated_fail(reader) + : syntax_fail(reader.error_message()); + } + payload_id += extra; + } + for (std::size_t i = 0; i < container.payload_count; ++i) { + if (container.payloads[i].id == static_cast(payload_id)) { + return syntax_fail("duplicate EMDF payload id " + std::to_string(payload_id)); + } + } + if (container.payload_count >= kMaxPayloads) { + return syntax_fail("EMDF payload count exceeds " + std::to_string(kMaxPayloads)); + } + + const std::uint32_t has_sample_offset = reader.read(1); + std::uint16_t sample_offset = 0; + if (has_sample_offset != 0u) { + sample_offset = static_cast(reader.read(12) >> 1); + } + if (reader.read(1) != 0u) { + std::uint32_t ignored = 0; + if (!bits::variable_bits(reader, 11, 8, &ignored)) { + return reader.error() == JOC_ERR_BITSTREAM_TRUNCATED ? truncated_fail(reader) + : syntax_fail(reader.error_message()); + } + } + if (reader.read(1) != 0u) { + std::uint32_t ignored = 0; + if (!bits::variable_bits(reader, 2, 8, &ignored)) { + return reader.error() == JOC_ERR_BITSTREAM_TRUNCATED ? truncated_fail(reader) + : syntax_fail(reader.error_message()); + } + } + if (reader.read(1) != 0u) { + if (!reader.skip(8)) { + return truncated_fail(reader); + } + } + if (reader.read(1) == 0u) { + bool frame_aligned = false; + if (has_sample_offset == 0u) { + frame_aligned = reader.read(1) != 0u; + if (frame_aligned) { + if (!reader.skip(2)) { + return truncated_fail(reader); + } + } + } + if (has_sample_offset != 0u || frame_aligned) { + if (!reader.skip(7)) { + return truncated_fail(reader); + } + } + } + if (reader.failed()) { + return truncated_fail(reader); + } + + std::uint32_t payload_size = 0; + if (!bits::variable_bits(reader, 8, 8, &payload_size)) { + return reader.error() == JOC_ERR_BITSTREAM_TRUNCATED ? truncated_fail(reader) + : syntax_fail(reader.error_message()); + } + const std::size_t payload_bits = static_cast(payload_size) * 8u; + if (reader.position() + payload_bits > body_end) { + return syntax_fail("EMDF payload id " + std::to_string(payload_id) + + " extends past container body (size " + std::to_string(payload_size) + + " at bit " + std::to_string(reader.position()) + ")"); + } + + Payload& entry = container.payloads[container.payload_count++]; + entry.id = static_cast(payload_id); + entry.sample_offset = sample_offset; + entry.bit_offset = reader.position(); + entry.size = payload_size; + + if (!reader.skip(payload_bits)) { + return truncated_fail(reader); + } + } + + if (!terminated) { + return syntax_fail("EMDF container has no payload id 0 terminator"); + } + container.raw_size = 4u + static_cast(length); + *out = container; + return Status::success(); +} + +void marker_offsets(const std::uint8_t* data, std::size_t size, std::vector* out) { + out->clear(); + if (data == nullptr || size < 4u) { + return; + } + // Eight global bit alignments. For shift != 0 the reference builds an + // (n-1)-byte shifted view and only scans pairs inside it, which is what the + // bounds below reproduce exactly. + for (std::size_t shift = 0; shift < 8u; ++shift) { + const std::size_t aligned_len = (shift == 0u) ? size : (size - 1u); + auto aligned_byte = [&](std::size_t index) -> std::uint8_t { + if (shift == 0u) { + return data[index]; + } + const std::uint16_t high = static_cast(data[index]) << shift; + const std::uint16_t low = static_cast(data[index + 1u]) >> (8u - shift); + return static_cast((high | low) & 0xFFu); + }; + if (aligned_len < 2u) { + continue; + } + for (std::size_t i = 0; i + 1u < aligned_len; ++i) { + if (aligned_byte(i) == 0x58u && aligned_byte(i + 1u) == 0x38u) { + out->push_back(i * 8u + shift); + } + } + } + std::sort(out->begin(), out->end()); +} + +Status find_joc_emdf(const std::uint8_t* data, std::size_t size, Container* out) { + if (data == nullptr || out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kEmdf, "null buffer or output"); + } + std::vector offsets; + marker_offsets(data, size, &offsets); + + std::vector matches; + std::size_t parse_errors = 0; + std::string first_parse_error; + for (const std::size_t start_bit : offsets) { + Container candidate; + const Status status = parse_at(data, size, start_bit, &candidate); + if (!status.ok()) { + ++parse_errors; + if (first_parse_error.empty()) { + first_parse_error = "@bit" + std::to_string(start_bit) + ": " + status.message(); + } + continue; + } + if (candidate.find(kIdOamd) != nullptr && candidate.find(kIdJoc) != nullptr) { + matches.push_back(candidate); + } + } + + if (matches.empty()) { + // Classification stays at the transport level (identical to the reference + // implementation, which raises emdf_transport here), but the underlying + std::string message = + "no contiguous EMDF container carrying ID11+ID14 in this syncframe (markers=" + + std::to_string(offsets.size()) + ", parse_failures=" + std::to_string(parse_errors) + + ")"; + if (!first_parse_error.empty()) { + message += "; first candidate error " + first_parse_error; + } + return Status::fail(JOC_ERR_EMDF_TRANSPORT, stage::kEmdf, message); + } + + std::sort(matches.begin(), matches.end(), + [](const Container& a, const Container& b) { return a.start_bit < b.start_bit; }); + + // A payload may contain bytes that look like another 0x5838 container; a + std::vector top_level; + for (const Container& candidate : matches) { + bool nested = false; + for (const Container& parent : top_level) { + if (parent.start_bit < candidate.start_bit && + candidate.start_bit < parent.start_bit + parent.raw_size * 8u) { + nested = true; + break; + } + } + if (!nested) { + top_level.push_back(candidate); + } + } + + if (top_level.size() != 1u) { + return Status::fail(JOC_ERR_EMDF_TRANSPORT, stage::kEmdf, + "multiple top-level JOC EMDF containers (" + + std::to_string(top_level.size()) + + "); automatic selection is not defined"); + } + *out = top_level.front(); + return Status::success(); +} + +void extract_container_bytes(const std::uint8_t* data, std::size_t size, const Container& container, + std::vector* out) { + out->assign(container.raw_size, 0u); + if (out->empty()) { + return; + } + bits::BitReader reader; + reader.reset(data, size, container.start_bit); + reader.read_bytes(out->data(), out->size()); +} + +Status extract_payload_bytes(const std::uint8_t* data, std::size_t size, const Payload& payload, + std::vector* out) { + if (data == nullptr || out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kEmdf, "null buffer or output"); + } + out->assign(payload.size, 0u); + if (out->empty()) { + return Status::success(); + } + bits::BitReader reader; + reader.reset(data, size, payload.bit_offset); + if (!reader.read_bytes(out->data(), out->size())) { + return Status::fail(JOC_ERR_BITSTREAM_TRUNCATED, stage::kEmdf, + "payload bytes extend past the syncframe"); + } + return Status::success(); +} + +} // namespace joc::emdf diff --git a/src/emdf/emdf_parser.h b/src/emdf/emdf_parser.h new file mode 100644 index 0000000..ad68491 --- /dev/null +++ b/src/emdf/emdf_parser.h @@ -0,0 +1,57 @@ + +#pragma once + +#include +#include +#include + +#include "joc_core.h" +#include "foundation/status.h" + +namespace joc::emdf { + +inline constexpr std::uint16_t kSyncword = 0x5838; +inline constexpr std::uint8_t kIdOamd = 11; +inline constexpr std::uint8_t kIdJoc = 14; +inline constexpr std::size_t kMaxPayloads = JOC_MAX_EMDF_PAYLOADS; + +struct Payload { + std::uint8_t id = 0; + std::uint16_t sample_offset = 0; + std::size_t bit_offset = 0; // MSB-first bit position of the payload bytes + std::size_t size = 0; // payload byte count +}; + +struct Container { + std::size_t start_bit = 0; + std::size_t raw_size = 0; + std::size_t payload_count = 0; + Payload payloads[kMaxPayloads] = {}; + + const Payload* find(std::uint8_t id) const { + for (std::size_t i = 0; i < payload_count; ++i) { + if (payloads[i].id == id) { + return &payloads[i]; + } + } + return nullptr; + } +}; + +Status parse_at(const std::uint8_t* data, std::size_t size, std::size_t start_bit, Container* out); + +// All candidate 0x5838 bit offsets over the eight alignments, ascending. +void marker_offsets(const std::uint8_t* data, std::size_t size, std::vector* out); + +Status find_joc_emdf(const std::uint8_t* data, std::size_t size, Container* out); + +// Extract the container's bytes exactly as the bit reader sees them (identical +// to a memcpy for byte-aligned containers). +void extract_container_bytes(const std::uint8_t* data, std::size_t size, const Container& container, + std::vector* out); + +// Extract one payload's bytes with the same MSB-first semantics. +Status extract_payload_bytes(const std::uint8_t* data, std::size_t size, const Payload& payload, + std::vector* out); + +} // namespace joc::emdf diff --git a/src/foundation/bit_reader.cpp b/src/foundation/bit_reader.cpp new file mode 100644 index 0000000..0a2e307 --- /dev/null +++ b/src/foundation/bit_reader.cpp @@ -0,0 +1,30 @@ +#include "foundation/bit_reader.h" + +namespace joc::bits { + +bool variable_bits(BitReader& reader, unsigned width, unsigned max_groups, std::uint32_t* out_value) { + std::uint32_t value = 0; + for (unsigned group = 0; group < max_groups; ++group) { + value += reader.read(width); + if (reader.failed()) { + return false; + } + const std::uint32_t more = reader.read(1); + if (reader.failed()) { + return false; + } + if (more == 0u) { + if (out_value != nullptr) { + *out_value = value; + } + return true; + } + value = (value + 1u) << width; + } + // Same failure mode as the reference implementation: an extension chain + // that never terminates is a syntax error, not a truncation. + reader.fail(JOC_ERR_EMDF_SYNTAX, "variable_bits extension groups exceeded"); + return false; +} + +} // namespace joc::bits diff --git a/src/foundation/bit_reader.h b/src/foundation/bit_reader.h new file mode 100644 index 0000000..b7febce --- /dev/null +++ b/src/foundation/bit_reader.h @@ -0,0 +1,125 @@ + +#pragma once + +#include +#include + +#include "joc_core.h" + +namespace joc::bits { + +class BitReader { +public: + BitReader() = default; + BitReader(const std::uint8_t* data, std::size_t size) { reset(data, size); } + + void reset(const std::uint8_t* data, std::size_t size, std::size_t start_bit = 0) { + data_ = data; + size_bits_ = size * 8u; + pos_ = start_bit; + limit_ = size_bits_; + error_ = JOC_OK; + message_ = ""; + } + + void set_limit_bits(std::size_t limit_bits) { + limit_ = limit_bits < size_bits_ ? limit_bits : size_bits_; + } + + std::size_t position() const { return pos_; } + std::size_t limit() const { return limit_; } + std::size_t remaining_bits() const { return pos_ <= limit_ ? limit_ - pos_ : 0; } + const std::uint8_t* data() const { return data_; } + + bool failed() const { return error_ != JOC_OK; } + joc_error error() const { return error_; } + const char* error_message() const { return message_; } + + std::uint32_t read(unsigned count) { + if (count == 0) { + return 0; + } + if (!can_read(count)) { + fail_truncated(count); + return 0; + } + std::uint32_t value = 0; + if ((pos_ & 7u) == 0u && count >= 8u) { + while (count >= 8u) { + value = (value << 8) | data_[pos_ >> 3]; + pos_ += 8u; + count -= 8u; + } + } + while (count-- > 0u) { + const std::uint32_t bit = (data_[pos_ >> 3] >> (7u - (pos_ & 7u))) & 1u; + value = (value << 1) | bit; + ++pos_; + } + return value; + } + + std::uint64_t read64(unsigned count) { + if (count <= 32u) { + return static_cast(read(count)); + } + const std::uint64_t high = static_cast(read(count - 32u)); + const std::uint64_t low = static_cast(read(32u)); + return (high << 32) | low; + } + + bool skip(std::size_t count) { + if (!can_read(count)) { + fail_truncated(count); + return false; + } + pos_ += count; + return true; + } + + bool read_bytes(std::uint8_t* out, std::size_t count) { + if (count == 0) { + return true; + } + if (!can_read(count * 8u)) { + fail_truncated(count * 8u); + return false; + } + for (std::size_t i = 0; i < count; ++i) { + out[i] = static_cast(read(8u)); + } + return true; + } + + bool can_read(std::size_t count) const { + return !failed() && count <= limit_ && pos_ <= limit_ - count; + } + + // semantic check fails, so the reader never continues past it). + void fail(joc_error code, const char* message) { + if (!failed()) { + error_ = code; + message_ = message; + } + } + +private: + void fail_truncated(std::size_t count) { + fail(JOC_ERR_BITSTREAM_TRUNCATED, "bit read past end of buffer"); + last_request_ = count; + } + + const std::uint8_t* data_ = nullptr; + std::size_t size_bits_ = 0; + std::size_t pos_ = 0; + std::size_t limit_ = 0; + std::size_t last_request_ = 0; + joc_error error_ = JOC_OK; + const char* message_ = ""; +}; + +// followed by a continuation bit. Mirrors src/emdf.py:variable_bits(). +bool variable_bits(BitReader& reader, unsigned width, unsigned max_groups, + std::uint32_t* out_value); + +} // namespace joc::bits diff --git a/src/foundation/fft.cpp b/src/foundation/fft.cpp new file mode 100644 index 0000000..70b698c --- /dev/null +++ b/src/foundation/fft.cpp @@ -0,0 +1,206 @@ +#include "foundation/fft.h" + +#include + +#include "simd/simd.h" + +namespace joc::dsp { + +// The dispatched kernels read and write the spectrum as interleaved doubles, and +// an array of std::complex is exactly that: two doubles per element, no +// padding, no vtable. +static_assert(sizeof(Complex) == 2u * sizeof(double), "complex layout"); + +namespace { + +constexpr double kPi = 3.14159265358979323846; + +template +void fft_in_place(Container* data, bool inverse) { + const std::size_t count = data->size(); + if (count < 2u) { + return; + } + for (std::size_t index = 1u, reversed = 0u; index < count; ++index) { + std::size_t bit = count >> 1u; + for (; (reversed & bit) != 0u; bit >>= 1u) { + reversed ^= bit; + } + reversed ^= bit; + if (index < reversed) { + std::swap((*data)[index], (*data)[reversed]); + } + } + for (std::size_t length = 2u; length <= count; length <<= 1u) { + const double angle = (inverse ? 2.0 : -2.0) * kPi / static_cast(length); + const Complex step(std::cos(angle), std::sin(angle)); + for (std::size_t start = 0u; start < count; start += length) { + Complex factor(1.0, 0.0); + for (std::size_t offset = 0u; offset < length / 2u; ++offset) { + const Complex even = (*data)[start + offset]; + const Complex odd = (*data)[start + offset + length / 2u] * factor; + (*data)[start + offset] = even + odd; + (*data)[start + offset + length / 2u] = even - odd; + factor *= step; + } + } + } + if (inverse) { + for (Complex& value : *data) { + value /= static_cast(count); + } + } +} + +bool is_power_of_two(std::size_t value) { return value != 0u && (value & (value - 1u)) == 0u; } + +} // namespace + +FftPlan::FftPlan(std::size_t size, bool inverse) : size_(size), inverse_(inverse) { + reverse_.resize(size); + for (std::size_t index = 1u, reversed = 0u; index < size; ++index) { + std::size_t bit = size >> 1u; + for (; (reversed & bit) != 0u; bit >>= 1u) { + reversed ^= bit; + } + reversed ^= bit; + reverse_[index] = reversed; + } + for (std::size_t length = 2u; length <= size; length <<= 1u) { + const double angle = (inverse ? 2.0 : -2.0) * kPi / static_cast(length); + const Complex step(std::cos(angle), std::sin(angle)); + stage_begin_.push_back(twiddle_.size()); + Complex factor(1.0, 0.0); + for (std::size_t offset = 0u; offset < length / 2u; ++offset) { + twiddle_.push_back(factor); + factor *= step; + } + } +} + +// Exactly the operations fft_in_place performs, in the same order, with the +// twiddles read from the precomputed recurrence instead of being re-derived. +template +void FftPlan::apply(Container* data) const { + const std::size_t count = data->size(); + if (count < 2u) { + return; + } + const std::size_t* reverse = reverse_.data(); + for (std::size_t index = 1u; index < count; ++index) { + const std::size_t reversed = reverse[index]; + if (index < reversed) { + std::swap((*data)[index], (*data)[reversed]); + } + } + // The cascade is dispatched for every power-of-two size the kernels can pack + // whole groups into a vector (JOC_SIMD pins one tier for verification). A + // kernel only ever puts independent butterflies in the same vector, so every + // output keeps the operation sequence and the roundings written below; small + // transforms -- and the caller's own table -- keep the portable loop. + if (count >= simd::kMinVectorFftSize && (count & (count - 1u)) == 0u) { + simd::fft_butterflies(reinterpret_cast(data->data()), count, + reinterpret_cast(twiddle_.data()), + stage_begin_.data()); + } else { + std::size_t stage = 0u; + for (std::size_t length = 2u; length <= count; length <<= 1u, ++stage) { + const Complex* table = twiddle_.data() + stage_begin_[stage]; + for (std::size_t start = 0u; start < count; start += length) { + for (std::size_t offset = 0u; offset < length / 2u; ++offset) { + const Complex even = (*data)[start + offset]; + const Complex odd = (*data)[start + offset + length / 2u] * table[offset]; + (*data)[start + offset] = even + odd; + (*data)[start + offset + length / 2u] = even - odd; + } + } + } + } + if (inverse_) { + for (Complex& value : *data) { + value /= static_cast(count); + } + } +} + +void fft_radix2(std::vector* data, const FftPlan& plan) { plan.apply(data); } + +void fft_radix2(std::array* data, const FftPlan& plan) { plan.apply(data); } + +void fft_radix2(std::vector* data, bool inverse) { fft_in_place(data, inverse); } + +void fft_radix2(std::array* data, bool inverse) { + fft_in_place(data, inverse); +} + +void fft_any(const std::vector& input, bool inverse, std::vector* output) { + const std::size_t count = input.size(); + if (is_power_of_two(count)) { + *output = input; + fft_radix2(output, inverse); + return; + } + std::size_t size = 1u; + while (size < 2u * count + 1u) { + size <<= 1u; + } + const double sign = inverse ? 1.0 : -1.0; + std::vector left(size, Complex(0.0, 0.0)); + std::vector right(size, Complex(0.0, 0.0)); + for (std::size_t index = 0u; index < count; ++index) { + const std::size_t wrapped = (index * index) % (2u * count); + const double angle = kPi * static_cast(wrapped) / static_cast(count); + const Complex chirp(std::cos(angle), sign * std::sin(angle)); + left[index] = input[index] * chirp; + right[index] = std::conj(chirp); + if (index != 0u) { + right[size - index] = std::conj(chirp); + } + } + fft_radix2(&left, false); + fft_radix2(&right, false); + for (std::size_t index = 0u; index < size; ++index) { + left[index] *= right[index]; + } + fft_radix2(&left, true); + output->resize(count); + for (std::size_t index = 0u; index < count; ++index) { + const std::size_t wrapped = (index * index) % (2u * count); + const double angle = kPi * static_cast(wrapped) / static_cast(count); + const Complex chirp(std::cos(angle), sign * std::sin(angle)); + (*output)[index] = left[index] * chirp; + if (inverse) { + (*output)[index] /= static_cast(count); + } + } +} + +std::size_t next_fast_len(std::size_t value) { + if (value <= 6u) { + return value; + } + std::size_t best = value; + for (std::size_t power2 = 1u; power2 < value * 2u; power2 *= 2u) { + for (std::size_t power3 = power2; power3 < value * 2u; power3 *= 3u) { + std::size_t power5 = power3; + while (power5 < value) { + power5 *= 5u; + } + best = std::min(best, power5); + if (power3 >= value) { + break; + } + } + } + return best; +} + +std::size_t next_power_of_two(std::size_t value) { + std::size_t result = 1u; + while (result < value) { + result <<= 1u; + } + return result; +} + +} // namespace joc::dsp diff --git a/src/foundation/fft.h b/src/foundation/fft.h new file mode 100644 index 0000000..dee38d3 --- /dev/null +++ b/src/foundation/fft.h @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include + +// Complex transforms shared by the HRTF and Rosella DSP cores. The convention is +// NumPy's: the forward transform is unnormalised and the inverse scales by 1/N, +// so a ported pipeline keeps the reference's arithmetic bit for bit. +namespace joc::dsp { + +using Complex = std::complex; + +inline constexpr std::size_t kQmfFftSize = 128; + +// Precomputed radix-2 plan for one size and direction. +// +// The transform derives each butterfly's twiddle by multiplying the previous one +// by the stage step, so the twiddle at offset k is `step` multiplied k times in +// that order, independently of the group. Materialising that exact recurrence -- +// and the bit-reversal permutation -- removes one complex multiply and a +// (length/2)-deep serial dependency from every stage's inner loop. The table +// entries are the recurrence's own values, so the transform is bit-identical. +// +// The 128-point cascade is executed by the runtime-dispatched SIMD kernel +// (src/simd/simd.h): it computes independent butterflies in parallel lanes, +// which leaves both the table and every output's summation order untouched. +class FftPlan { +public: + FftPlan(std::size_t size, bool inverse); + + std::size_t size() const { return size_; } + bool inverse() const { return inverse_; } + +private: + template + void apply(Container* data) const; + + friend void fft_radix2(std::vector* data, const FftPlan& plan); + friend void fft_radix2(std::array* data, const FftPlan& plan); + + std::size_t size_ = 0; + bool inverse_ = false; + std::vector reverse_; // bit-reversal permutation, [size] + std::vector stage_begin_; // twiddle offset of each stage + std::vector twiddle_; // per stage, length/2 entries, concatenated +}; + +// In-place radix-2 transform; the size must be a power of two. +void fft_radix2(std::vector* data, bool inverse); +void fft_radix2(std::array* data, bool inverse); + +// Plan-driven forms: the plan carries the size and the direction, so a caller that +// transforms the same length repeatedly builds it once. +void fft_radix2(std::vector* data, const FftPlan& plan); +void fft_radix2(std::array* data, const FftPlan& plan); + +// Exact-length transform: radix-2 when the size allows it, Bluestein otherwise. +// scipy/numpy use a mixed-radix transform, which is the same transform. +void fft_any(const std::vector& input, bool inverse, std::vector* output); + +// scipy's next_fast_len: the smallest 5-smooth number that is not smaller. +std::size_t next_fast_len(std::size_t value); + +std::size_t next_power_of_two(std::size_t value); + +} // namespace joc::dsp diff --git a/src/foundation/fs_utf8.cpp b/src/foundation/fs_utf8.cpp new file mode 100644 index 0000000..dbee379 --- /dev/null +++ b/src/foundation/fs_utf8.cpp @@ -0,0 +1,163 @@ +#include "foundation/fs_utf8.h" + +#include +#include +#include + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include +#include +#include +#else +#include +#endif + +namespace joc::fs_utf8 { + +namespace fs = std::filesystem; + +fs::path to_path(const std::string& utf8) { + return fs::path(std::u8string(reinterpret_cast(utf8.data()), utf8.size())); +} + +std::string from_path(const fs::path& path) { + const std::u8string text = path.u8string(); + return std::string(reinterpret_cast(text.data()), text.size()); +} + +std::FILE* fopen(const std::string& utf8_path, const char* mode) { +#if defined(_WIN32) + const std::wstring wide_mode(mode, mode + std::strlen(mode)); + return ::_wfopen(to_path(utf8_path).c_str(), wide_mode.c_str()); +#else + return std::fopen(utf8_path.c_str(), mode); +#endif +} + +std::FILE* fopen_spool(const std::string& utf8_path) { +#if defined(_WIN32) + // Delete-on-close handed to the CRT: if the process is killed the file goes with + // it, which is what stops an aborted run from leaving hundreds of gigabytes. + HANDLE handle = ::CreateFileW( + to_path(utf8_path).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_ALWAYS, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, nullptr); + if (handle == INVALID_HANDLE_VALUE) { + return nullptr; + } + const int descriptor = ::_open_osfhandle(reinterpret_cast(handle), 0); + if (descriptor == -1) { + ::CloseHandle(handle); + return nullptr; + } + return ::_fdopen(descriptor, "wb+"); +#else + return std::fopen(utf8_path.c_str(), "wb+"); +#endif +} + +int remove(const std::string& utf8_path) { +#if defined(_WIN32) + return ::_wremove(to_path(utf8_path).c_str()); +#else + return std::remove(utf8_path.c_str()); +#endif +} + +bool exists(const std::string& utf8_path) { + std::error_code error; + return fs::exists(to_path(utf8_path), error); +} + +bool is_directory(const std::string& utf8_path) { + std::error_code error; + return fs::is_directory(to_path(utf8_path), error); +} + +std::uintmax_t file_size(const std::string& utf8_path, std::error_code& error) { + return fs::file_size(to_path(utf8_path), error); +} + +std::string temp_directory() { + std::error_code error; + const fs::path directory = fs::temp_directory_path(error); + return error ? std::string(".") : from_path(directory); +} + +std::string executable_path() { +#if defined(_WIN32) + std::vector buffer(MAX_PATH); + while (true) { + const DWORD written = + ::GetModuleFileNameW(nullptr, buffer.data(), static_cast(buffer.size())); + if (written == 0) { + return std::string(); + } + if (written < buffer.size()) { + return from_path(fs::path(std::wstring(buffer.data(), written))); + } + buffer.resize(buffer.size() * 2u); + } +#elif defined(__linux__) + std::vector buffer(4096u, '\0'); + const ssize_t written = ::readlink("/proc/self/exe", buffer.data(), buffer.size() - 1u); + return written > 0 ? std::string(buffer.data(), static_cast(written)) + : std::string(); +#else + return std::string(); +#endif +} + +std::ifstream open_input(const std::string& utf8_path) { + return std::ifstream(to_path(utf8_path), std::ios::binary); +} + +std::ofstream open_output(const std::string& utf8_path) { + return std::ofstream(to_path(utf8_path), std::ios::binary); +} + +std::vector command_line_arguments(int argc, char** argv) { +#if defined(_WIN32) + (void)argc; + (void)argv; + int count = 0; + LPWSTR* wide = ::CommandLineToArgvW(::GetCommandLineW(), &count); + std::vector arguments; + if (wide == nullptr) { + return arguments; + } + arguments.reserve(static_cast(count)); + for (int index = 0; index < count; ++index) { + const std::wstring_view text(wide[index]); + const int size = ::WideCharToMultiByte(CP_UTF8, 0, text.data(), + static_cast(text.size()), nullptr, 0, nullptr, + nullptr); + std::string utf8(static_cast(size), '\0'); + if (size > 0) { + ::WideCharToMultiByte(CP_UTF8, 0, text.data(), static_cast(text.size()), + utf8.data(), size, nullptr, nullptr); + } + arguments.push_back(std::move(utf8)); + } + ::LocalFree(wide); + return arguments; +#else + std::vector arguments; + arguments.reserve(static_cast(argc)); + for (int index = 0; index < argc; ++index) { + arguments.emplace_back(argv[index]); + } + return arguments; +#endif +} + +void configure_console() { +#if defined(_WIN32) + ::SetConsoleOutputCP(CP_UTF8); +#endif +} + +} // namespace joc::fs_utf8 diff --git a/src/foundation/fs_utf8.h b/src/foundation/fs_utf8.h new file mode 100644 index 0000000..55675e2 --- /dev/null +++ b/src/foundation/fs_utf8.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +// Paths inside this library are always UTF-8, on every platform. std::filesystem +// stores UTF-16 on Windows and bytes elsewhere, and the narrow CRT uses the ANSI +// code page on Windows, so every path crosses into the OS through this shim: that +// is what makes non-ASCII names (Japanese, Chinese, ...) work. +namespace joc::fs_utf8 { + +std::filesystem::path to_path(const std::string& utf8); +std::string from_path(const std::filesystem::path& path); + +// File handles and queries take a UTF-8 path: _wfopen on Windows, plain calls +// elsewhere. Nothing else in the library may call the narrow CRT with a path. +std::FILE* fopen(const std::string& utf8_path, const char* mode); +// Temporary spool handle: on Windows the file is opened delete-on-close, so killing +// the process removes it instead of leaving a multi-gigabyte leftover behind. +std::FILE* fopen_spool(const std::string& utf8_path); +int remove(const std::string& utf8_path); +bool exists(const std::string& utf8_path); +bool is_directory(const std::string& utf8_path); +std::uintmax_t file_size(const std::string& utf8_path, std::error_code& error); +std::string temp_directory(); + +// The running executable's own path, UTF-8, or empty when the platform cannot +// report it. Defaults are anchored here so they never depend on the CWD. +std::string executable_path(); + +// Streams: std::ifstream/ofstream accept a std::filesystem::path, which is the +// portable way to open a UTF-8 path. +std::ifstream open_input(const std::string& utf8_path); +std::ofstream open_output(const std::string& utf8_path); + +// Command line arguments as UTF-8. Windows hands the process UTF-16 and the +// narrow CRT would convert it through the ANSI code page, so the wide command +// line is re-parsed there; on POSIX argv is already bytes in the user's locale. +std::vector command_line_arguments(int argc, char** argv); +void configure_console(); + +} // namespace joc::fs_utf8 diff --git a/src/foundation/geometry.h b/src/foundation/geometry.h new file mode 100644 index 0000000..fd0b9ec --- /dev/null +++ b/src/foundation/geometry.h @@ -0,0 +1,25 @@ +// Port of the reference's adm_atmos.q_to_adm_xyz: OAMD Q15 coordinates to the ADM +// cartesian triple. It lives in foundation because both the ADM writer and the +// object position timeline need it, and the timeline must not depend on output. +#pragma once + +#include + +#include "foundation/py_num.h" + +namespace joc::geometry { + +inline void q_to_adm_xyz(int q1, int q2, int q3, double* x, double* y, double* z) { + const double posX = std::min(1.0, static_cast(pynum::py_round( + static_cast(q1) * 62.0 / 32767.0)) / 62.0); + const double posY = std::min(1.0, static_cast(pynum::py_round( + static_cast(q2) * 62.0 / 32767.0)) / 62.0); + double posZ = static_cast(pynum::py_round( + static_cast(q3) * 15.0 / 32767.0)) / 15.0; + posZ = std::max(-1.0, std::min(1.0, posZ)); + *x = posX * 2.0 - 1.0; + *y = 1.0 - posY * 2.0; + *z = posZ; +} + +} // namespace joc::geometry diff --git a/src/foundation/mini_json.cpp b/src/foundation/mini_json.cpp new file mode 100644 index 0000000..e139661 --- /dev/null +++ b/src/foundation/mini_json.cpp @@ -0,0 +1,227 @@ +#include "foundation/mini_json.h" + +#include +#include + +namespace joc::json { + +namespace { + +void skip_space(const std::string& text, std::size_t* index) { + while (*index < text.size() && + (text[*index] == ' ' || text[*index] == '\t' || text[*index] == '\n' || + text[*index] == '\r')) { + ++(*index); + } +} + +bool read_string(const std::string& text, std::size_t* index, std::string* out) { + if (*index >= text.size() || text[*index] != '"') { + return false; + } + ++(*index); + out->clear(); + while (*index < text.size()) { + const char c = text[*index]; + if (c == '\\') { + if (*index + 1 >= text.size()) { + return false; + } + const char escape = text[*index + 1]; + *index += 2; + switch (escape) { + case '"': out->push_back('"'); break; + case '\\': out->push_back('\\'); break; + case '/': out->push_back('/'); break; + case 'b': out->push_back('\b'); break; + case 'f': out->push_back('\f'); break; + case 'n': out->push_back('\n'); break; + case 'r': out->push_back('\r'); break; + case 't': out->push_back('\t'); break; + case 'u': { + if (*index + 4 > text.size()) { + return false; + } + unsigned code = 0; + for (int i = 0; i < 4; ++i) { + const char digit = text[*index + static_cast(i)]; + code <<= 4; + if (digit >= '0' && digit <= '9') { code |= static_cast(digit - '0'); } + else if (digit >= 'a' && digit <= 'f') { code |= static_cast(digit - 'a' + 10); } + else if (digit >= 'A' && digit <= 'F') { code |= static_cast(digit - 'A' + 10); } + else { return false; } + } + *index += 4; + if (code < 0x80u) { + out->push_back(static_cast(code)); + } else if (code < 0x800u) { + out->push_back(static_cast(0xC0u | (code >> 6))); + out->push_back(static_cast(0x80u | (code & 0x3Fu))); + } else { + out->push_back(static_cast(0xE0u | (code >> 12))); + out->push_back(static_cast(0x80u | ((code >> 6) & 0x3Fu))); + out->push_back(static_cast(0x80u | (code & 0x3Fu))); + } + break; + } + default: return false; + } + continue; + } + if (c == '"') { + ++(*index); + return true; + } + out->push_back(c); + ++(*index); + } + return false; +} + +bool read_compound(const std::string& text, std::size_t* index, std::string* out) { + const char open = text[*index]; + const char close = open == '{' ? '}' : ']'; + int depth = 0; + const std::size_t start = *index; + while (*index < text.size()) { + const char c = text[*index]; + if (c == '"') { + std::string ignored; + if (!read_string(text, index, &ignored)) { + return false; + } + continue; + } + if (c == open) { + ++depth; + } else if (c == close) { + --depth; + if (depth == 0) { + ++(*index); + *out = text.substr(start, *index - start); + return true; + } + } + ++(*index); + } + return false; +} + +} // namespace + +bool parse_object(const std::string& text, std::vector* out, std::string* error) { + out->clear(); + std::size_t index = 0; + skip_space(text, &index); + if (index >= text.size() || text[index] != '{') { + if (error != nullptr) { *error = "metadata is not a JSON object"; } + return false; + } + ++index; + for (;;) { + skip_space(text, &index); + if (index < text.size() && text[index] == '}') { + ++index; + break; + } + if (index >= text.size() || text[index] == ',') { + if (index >= text.size()) { + if (error != nullptr) { *error = "unterminated JSON object"; } + return false; + } + ++index; + continue; + } + Member member; + if (!read_string(text, &index, &member.key)) { + if (error != nullptr) { *error = "expected a JSON key"; } + return false; + } + skip_space(text, &index); + if (index >= text.size() || text[index] != ':') { + if (error != nullptr) { *error = "expected ':' after JSON key " + member.key; } + return false; + } + ++index; + skip_space(text, &index); + if (index >= text.size()) { + if (error != nullptr) { *error = "missing JSON value for " + member.key; } + return false; + } + if (text[index] == '"') { + member.is_string = true; + if (!read_string(text, &index, &member.raw)) { + if (error != nullptr) { *error = "bad JSON string for " + member.key; } + return false; + } + } else if (text[index] == '{' || text[index] == '[') { + if (!read_compound(text, &index, &member.raw)) { + if (error != nullptr) { *error = "bad JSON container for " + member.key; } + return false; + } + } else { + const std::size_t start = index; + while (index < text.size() && text[index] != ',' && text[index] != '}') { + ++index; + } + member.raw = text.substr(start, index - start); + while (!member.raw.empty() && + (member.raw.back() == ' ' || member.raw.back() == '\n' || + member.raw.back() == '\r' || member.raw.back() == '\t')) { + member.raw.pop_back(); + } + } + for (const Member& existing : *out) { + if (existing.key == member.key) { + if (error != nullptr) { *error = "duplicate JSON key " + member.key; } + return false; + } + } + out->push_back(std::move(member)); + } + return true; +} + +const Member* find(const std::vector& members, const std::string& key) { + for (const Member& member : members) { + if (member.key == key) { + return &member; + } + } + return nullptr; +} + +bool as_string(const Member& member, std::string* out) { + if (!member.is_string || out == nullptr) { + return false; + } + *out = member.raw; + return true; +} + +bool as_number(const Member& member, double* out) { + if (member.is_string || out == nullptr) { + return false; + } + char* end = nullptr; + const double value = std::strtod(member.raw.c_str(), &end); + if (end == member.raw.c_str() || !std::isfinite(value)) { + return false; + } + *out = value; + return true; +} + +bool as_integer(const Member& member, long long* out) { + double value = 0.0; + if (!as_number(member, &value) || out == nullptr) { + return false; + } + if (value != std::floor(value)) { + return false; + } + *out = static_cast(value); + return true; +} + +} // namespace joc::json diff --git a/src/foundation/mini_json.h b/src/foundation/mini_json.h new file mode 100644 index 0000000..13f3cb8 --- /dev/null +++ b/src/foundation/mini_json.h @@ -0,0 +1,25 @@ + +#pragma once + +#include +#include +#include + +namespace joc::json { + +struct Member { + std::string key; + std::string raw; + bool is_string = false; +}; + +// Parses a top-level JSON object. Rejects non-objects and duplicate keys. +bool parse_object(const std::string& text, std::vector* out, std::string* error); + +const Member* find(const std::vector& members, const std::string& key); + +bool as_string(const Member& member, std::string* out); +bool as_number(const Member& member, double* out); +bool as_integer(const Member& member, long long* out); + +} // namespace joc::json diff --git a/src/foundation/py_num.h b/src/foundation/py_num.h new file mode 100644 index 0000000..73b4f34 --- /dev/null +++ b/src/foundation/py_num.h @@ -0,0 +1,25 @@ + +#pragma once + +#include +#include +#include +#include + +namespace joc::pynum { + +inline long long py_round(double value) { + return static_cast(std::nearbyint(value)); +} + +inline std::string format_fixed(double value, int decimals) { + char buffer[64]; + std::snprintf(buffer, sizeof(buffer), "%.*f", decimals, value); + return std::string(buffer); +} + +inline long long trunc_to_ll(double value) { + return static_cast(value); +} + +} // namespace joc::pynum diff --git a/src/foundation/sha256.cpp b/src/foundation/sha256.cpp new file mode 100644 index 0000000..8954e22 --- /dev/null +++ b/src/foundation/sha256.cpp @@ -0,0 +1,165 @@ +#include "foundation/sha256.h" + +#include + +namespace joc::crypto { + +namespace { + +constexpr std::uint32_t kK[64] = { + 0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, 0x59f111f1u, 0x923f82a4u, + 0xab1c5ed5u, 0xd807aa98u, 0x12835b01u, 0x243185beu, 0x550c7dc3u, 0x72be5d74u, 0x80deb1feu, + 0x9bdc06a7u, 0xc19bf174u, 0xe49b69c1u, 0xefbe4786u, 0x0fc19dc6u, 0x240ca1ccu, 0x2de92c6fu, + 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau, 0x983e5152u, 0xa831c66du, 0xb00327c8u, 0xbf597fc7u, + 0xc6e00bf3u, 0xd5a79147u, 0x06ca6351u, 0x14292967u, 0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, + 0x53380d13u, 0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u, 0xa2bfe8a1u, 0xa81a664bu, + 0xc24b8b70u, 0xc76c51a3u, 0xd192e819u, 0xd6990624u, 0xf40e3585u, 0x106aa070u, 0x19a4c116u, + 0x1e376c08u, 0x2748774cu, 0x34b0bcb5u, 0x391c0cb3u, 0x4ed8aa4au, 0x5b9cca4fu, 0x682e6ff3u, + 0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u, 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, + 0xc67178f2u}; + +inline std::uint32_t rotr(std::uint32_t value, unsigned count) { + return (value >> count) | (value << (32u - count)); +} + +} // namespace + +void Sha256::reset() { + state_[0] = 0x6a09e667u; + state_[1] = 0xbb67ae85u; + state_[2] = 0x3c6ef372u; + state_[3] = 0xa54ff53au; + state_[4] = 0x510e527fu; + state_[5] = 0x9b05688cu; + state_[6] = 0x1f83d9abu; + state_[7] = 0x5be0cd19u; + bit_count_ = 0; + buffer_used_ = 0; + std::memset(buffer_, 0, sizeof(buffer_)); +} + +void Sha256::transform(const std::uint8_t block[64]) { + std::uint32_t w[64]; + for (unsigned i = 0; i < 16; ++i) { + w[i] = (static_cast(block[i * 4]) << 24) | + (static_cast(block[i * 4 + 1]) << 16) | + (static_cast(block[i * 4 + 2]) << 8) | + static_cast(block[i * 4 + 3]); + } + for (unsigned i = 16; i < 64; ++i) { + const std::uint32_t s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >> 3); + const std::uint32_t s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >> 10); + w[i] = w[i - 16] + s0 + w[i - 7] + s1; + } + std::uint32_t a = state_[0]; + std::uint32_t b = state_[1]; + std::uint32_t c = state_[2]; + std::uint32_t d = state_[3]; + std::uint32_t e = state_[4]; + std::uint32_t f = state_[5]; + std::uint32_t g = state_[6]; + std::uint32_t h = state_[7]; + for (unsigned i = 0; i < 64; ++i) { + const std::uint32_t s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25); + const std::uint32_t ch = (e & f) ^ (~e & g); + const std::uint32_t temp1 = h + s1 + ch + kK[i] + w[i]; + const std::uint32_t s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22); + const std::uint32_t maj = (a & b) ^ (a & c) ^ (b & c); + const std::uint32_t temp2 = s0 + maj; + h = g; + g = f; + f = e; + e = d + temp1; + d = c; + c = b; + b = a; + a = temp1 + temp2; + } + state_[0] += a; + state_[1] += b; + state_[2] += c; + state_[3] += d; + state_[4] += e; + state_[5] += f; + state_[6] += g; + state_[7] += h; +} + +void Sha256::update(const void* data, std::size_t size) { + const std::uint8_t* bytes = static_cast(data); + bit_count_ += static_cast(size) * 8u; + while (size > 0) { + const std::size_t space = 64u - buffer_used_; + const std::size_t take = size < space ? size : space; + std::memcpy(buffer_ + buffer_used_, bytes, take); + buffer_used_ += take; + bytes += take; + size -= take; + if (buffer_used_ == 64u) { + transform(buffer_); + buffer_used_ = 0; + } + } +} + +void Sha256::finish(std::uint8_t out[32]) { + const std::uint64_t total_bits = bit_count_; + const std::uint8_t pad = 0x80u; + update(&pad, 1); + const std::uint8_t zero = 0x00u; + while (buffer_used_ != 56u) { + update(&zero, 1); + } + std::uint8_t length_bytes[8]; + for (unsigned i = 0; i < 8; ++i) { + length_bytes[i] = static_cast((total_bits >> (56u - i * 8u)) & 0xFFu); + } + std::memcpy(buffer_ + buffer_used_, length_bytes, 8); + buffer_used_ += 8; + transform(buffer_); + buffer_used_ = 0; + for (unsigned i = 0; i < 8; ++i) { + out[i * 4 + 0] = static_cast((state_[i] >> 24) & 0xFFu); + out[i * 4 + 1] = static_cast((state_[i] >> 16) & 0xFFu); + out[i * 4 + 2] = static_cast((state_[i] >> 8) & 0xFFu); + out[i * 4 + 3] = static_cast(state_[i] & 0xFFu); + } +} + +std::string Sha256::finish_hex() { + std::uint8_t digest[32]; + finish(digest); + static const char* kHex = "0123456789abcdef"; + std::string text; + text.resize(64); + for (unsigned i = 0; i < 32; ++i) { + text[i * 2] = kHex[(digest[i] >> 4) & 0x0Fu]; + text[i * 2 + 1] = kHex[digest[i] & 0x0Fu]; + } + return text; +} + +std::string sha256_hex(const void* data, std::size_t size) { + Sha256 hash; + hash.update(data, size); + return hash.finish_hex(); +} + +bool sha256_hex_matches(const void* data, std::size_t size, const std::string& expected_hex) { + if (expected_hex.size() != 64) { + return false; + } + std::string actual = sha256_hex(data, size); + for (std::size_t i = 0; i < 64; ++i) { + char expected = expected_hex[i]; + if (expected >= 'A' && expected <= 'F') { + expected = static_cast(expected - 'A' + 'a'); + } + if (actual[i] != expected) { + return false; + } + } + return true; +} + +} // namespace joc::crypto diff --git a/src/foundation/sha256.h b/src/foundation/sha256.h new file mode 100644 index 0000000..ff1dcab --- /dev/null +++ b/src/foundation/sha256.h @@ -0,0 +1,31 @@ + +#pragma once + +#include +#include +#include + +namespace joc::crypto { + +class Sha256 { +public: + Sha256() { reset(); } + + void reset(); + void update(const void* data, std::size_t size); + void finish(std::uint8_t out[32]); + std::string finish_hex(); + +private: + void transform(const std::uint8_t block[64]); + + std::uint32_t state_[8] = {}; + std::uint64_t bit_count_ = 0; + std::uint8_t buffer_[64] = {}; + std::size_t buffer_used_ = 0; +}; + +std::string sha256_hex(const void* data, std::size_t size); +bool sha256_hex_matches(const void* data, std::size_t size, const std::string& expected_hex); + +} // namespace joc::crypto diff --git a/src/foundation/status.h b/src/foundation/status.h new file mode 100644 index 0000000..c126fd6 --- /dev/null +++ b/src/foundation/status.h @@ -0,0 +1,48 @@ + +#pragma once + +#include +#include + +#include "joc_core.h" + +namespace joc { + +class Status { +public: + Status() = default; + + static Status success() { return Status(); } + + static Status fail(joc_error code, std::string stage, std::string message) { + Status s; + s.code_ = code; + s.stage_ = std::move(stage); + s.message_ = std::move(message); + return s; + } + + bool ok() const { return code_ == JOC_OK; } + joc_error code() const { return code_; } + const std::string& stage() const { return stage_; } + const std::string& message() const { return message_; } + +private: + joc_error code_ = JOC_OK; + std::string stage_ = "none"; + std::string message_; +}; + +// Stage names are kept as plain literals so that C++ and the Python frontend +namespace stage { +inline constexpr const char* kFoundation = "foundation"; +inline constexpr const char* kEac3 = "eac3_transport"; +inline constexpr const char* kEmdf = "emdf"; +inline constexpr const char* kJoc = "joc"; +inline constexpr const char* kOamd = "oamd"; +inline constexpr const char* kDsp = "dsp"; +inline constexpr const char* kRender = "render"; +inline constexpr const char* kOutput = "output"; +} // namespace stage + +} // namespace joc diff --git a/src/hrtf/jochrtf.cpp b/src/hrtf/jochrtf.cpp new file mode 100644 index 0000000..cfc5ffd --- /dev/null +++ b/src/hrtf/jochrtf.cpp @@ -0,0 +1,401 @@ +#include "hrtf/jochrtf.h" + +#include +#include +#include +#include + +#include "foundation/mini_json.h" +#include "foundation/sha256.h" +#include "io/npy.h" +#include "io/zip_reader.h" + +namespace joc::hrtf { + +namespace { + +std::string to_upper(std::string text) { + for (char& c : text) { + if (c >= 'a' && c <= 'z') { + c = static_cast(c - 'a' + 'A'); + } + } + return text; +} + +bool is_sha256_hex(const std::string& text) { + if (text.size() != 64) { + return false; + } + for (const char c : text) { + const bool digit = c >= '0' && c <= '9'; + const bool upper = c >= 'A' && c <= 'F'; + if (!digit && !upper) { + return false; + } + } + return true; +} + +// json.dumps(list(shape)) as the reference writes it, e.g. "[36, 2, 77]". +std::string shape_json(const std::vector& shape) { + std::string text = "["; + for (std::size_t i = 0; i < shape.size(); ++i) { + text += (i == 0 ? "" : ", "); + text += std::to_string(shape[i]); + } + text += "]"; + return text; +} + +Status hrtf_fail(const std::string& message) { + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, message); +} + +std::string payload_sha256(const std::vector& centers, + const std::vector& coefficients, + const std::vector& delay_coefficients, + const std::vector& delay_bounds) { + crypto::Sha256 hash; + const char prefix[] = "JOC-HRTF-CACHE-PAYLOAD-V1"; + hash.update(prefix, sizeof(prefix) - 1); + const std::uint8_t zero = 0; + hash.update(&zero, 1); + + struct Entry { + const char* name; + const char* dtype; + const std::vector* values; + std::vector shape; + }; + const Entry entries[4] = { + {"band_center_frequencies_hz", "data(), entry.values->size() * sizeof(double)); + } + return hash.finish_hex(); +} + +} // namespace + +Status load_jochrtf(const std::string& path, Field* out) { + if (out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kRender, "null field"); + } + io::ZipArchive archive; + std::string error; + if (!archive.open(path, &error)) { + return Status::fail(JOC_ERR_HRTF_NOT_FOUND, stage::kRender, + "cannot read compiled HRTF " + path + ": " + error); + } + + // Member set must be exactly the five expected names. + static const char* kMembers[5] = {"metadata_json.npy", "band_center_frequencies_hz.npy", + "coefficients.npy", "delay_coefficients.npy", + "delay_bounds.npy"}; + if (archive.entries().size() != 5u) { + return hrtf_fail("compiled HRTF cache has an invalid member set (" + + std::to_string(archive.entries().size()) + " members)"); + } + for (const char* name : kMembers) { + if (archive.find(name) == nullptr) { + return hrtf_fail(std::string("compiled HRTF cache is missing ") + name); + } + } + + auto read_member = [&](const char* name, std::vector* raw, + io::NpyArray* array) -> Status { + if (!archive.read_member(name, raw, &error)) { + return hrtf_fail(std::string("compiled HRTF member ") + name + ": " + error); + } + if (!io::parse_npy(raw->data(), raw->size(), array, &error)) { + return hrtf_fail(std::string("compiled HRTF member ") + name + ": " + error); + } + if (array->fortran_order) { + return hrtf_fail(std::string("compiled HRTF member must be C-contiguous: ") + name); + } + return Status::success(); + }; + + std::vector raw; + io::NpyArray array; + + Status status = read_member("metadata_json.npy", &raw, &array); + if (!status.ok()) { + return status; + } + std::string metadata_text; + if (!io::npy_unicode_to_utf8(array, &metadata_text, &error)) { + return hrtf_fail("compiled HRTF metadata: " + error); + } + if (metadata_text.size() > 64u * 1024u) { + return hrtf_fail("compiled HRTF metadata is too large"); + } + + status = read_member("band_center_frequencies_hz.npy", &raw, &array); + if (!status.ok()) { + return status; + } + if (array.descr != " centers; + io::npy_to_double(array, ¢ers, &error); + + status = read_member("coefficients.npy", &raw, &array); + if (!status.ok()) { + return status; + } + if (array.descr != " coefficients; + if (!io::npy_to_double(array, &coefficients, &error)) { + return hrtf_fail("coefficients: " + error); + } + + status = read_member("delay_coefficients.npy", &raw, &array); + if (!status.ok()) { + return status; + } + if (array.descr != " delay_coefficients; + io::npy_to_double(array, &delay_coefficients, &error); + + status = read_member("delay_bounds.npy", &raw, &array); + if (!status.ok()) { + return status; + } + if (array.descr != " delay_bounds; + io::npy_to_double(array, &delay_bounds, &error); + + std::vector members; + if (!json::parse_object(metadata_text, &members, &error)) { + return hrtf_fail("compiled HRTF metadata: " + error); + } + auto require_string = [&](const char* key, std::string* value) -> Status { + const json::Member* member = json::find(members, key); + if (member == nullptr || !json::as_string(*member, value)) { + return hrtf_fail(std::string("compiled HRTF metadata is missing ") + key); + } + return Status::success(); + }; + std::string magic; + std::string schema; + std::string source_sha256; + std::string cache_key; + std::string payload_hash; + std::string delay_source; + status = require_string("magic", &magic); + if (!status.ok()) { return status; } + status = require_string("cache_schema", &schema); + if (!status.ok()) { return status; } + status = require_string("source_sha256", &source_sha256); + if (!status.ok()) { return status; } + status = require_string("cache_key", &cache_key); + if (!status.ok()) { return status; } + status = require_string("payload_sha256", &payload_hash); + if (!status.ok()) { return status; } + status = require_string("delay_source", &delay_source); + if (!status.ok()) { return status; } + + if (magic != kMagic) { + return hrtf_fail("compiled HRTF magic mismatch: " + magic); + } + if (schema != kCacheSchema) { + return hrtf_fail("compiled HRTF cache schema mismatch: " + schema); + } + const json::Member* version_member = json::find(members, "format_version"); + long long version = -1; + if (version_member == nullptr || !json::as_integer(*version_member, &version)) { + return hrtf_fail("compiled HRTF metadata is missing format_version"); + } + if (version != kFormatVersion) { + return Status::fail(JOC_ERR_HRTF_VERSION, stage::kRender, + "unsupported .jochrtf version " + std::to_string(version) + + "; rebuild it from the source SOFA"); + } + out->source_sha256 = to_upper(source_sha256); + out->cache_key = to_upper(cache_key); + if (!is_sha256_hex(out->source_sha256)) { + return hrtf_fail("compiled HRTF source_sha256 is not a 64-digit digest"); + } + if (!is_sha256_hex(out->cache_key)) { + return hrtf_fail("compiled HRTF cache_key is not a 64-digit digest"); + } + + const std::string expected = payload_sha256(centers, coefficients, delay_coefficients, + delay_bounds); + if (to_upper(payload_hash) != to_upper(expected)) { + return Status::fail(JOC_ERR_HRTF_HASH, stage::kRender, + "compiled HRTF payload hash mismatch"); + } + out->payload_sha256 = to_upper(payload_hash); + + const json::Member* radius_member = json::find(members, "measurement_radius_m"); + double radius = 0.0; + if (radius_member == nullptr || !json::as_number(*radius_member, &radius) || radius <= 0.0) { + return hrtf_fail("compiled HRTF measurement_radius_m must be a positive number"); + } + out->measurement_radius_m = radius; + const json::Member* order_member = json::find(members, "order"); + long long order = 0; + if (order_member == nullptr || !json::as_integer(*order_member, &order) || order <= 0 || + order * order > kShTerms) { + return hrtf_fail("compiled HRTF order is out of range"); + } + out->order = order; + + for (const double value : coefficients) { + if (!std::isfinite(value)) { + return hrtf_fail("compiled HRTF coefficients contain non-finite values"); + } + } + for (const double value : delay_coefficients) { + if (!std::isfinite(value) || std::abs(value) > 48000.0 * 64.0) { + return hrtf_fail("compiled HRTF delay coefficients are out of range"); + } + } + for (const double value : delay_bounds) { + if (!std::isfinite(value)) { + return hrtf_fail("compiled HRTF delay bounds contain non-finite values"); + } + } + if (delay_bounds.size() == 4u && delay_bounds[0] > delay_bounds[1]) { + return hrtf_fail("compiled HRTF delay bounds are inverted"); + } + + if (const json::Member* member = json::find(members, "compiler_version")) { + json::as_string(*member, &out->compiler_version); + } + if (const json::Member* member = json::find(members, "phase_policy_version")) { + json::as_string(*member, &out->phase_policy_version); + } + if (const json::Member* member = json::find(members, "sh_convention")) { + json::as_string(*member, &out->sh_convention); + } + if (const json::Member* member = json::find(members, "source_display_name")) { + json::as_string(*member, &out->source_display_name); + } + if (const json::Member* member = json::find(members, "projection_ridge")) { + json::as_number(*member, &out->projection_ridge); + } + if (const json::Member* member = json::find(members, "spherical_harmonic_ridge")) { + json::as_number(*member, &out->spherical_harmonic_ridge); + } + if (const json::Member* member = json::find(members, "fit_report")) { + out->fit_report_json = member->raw; + } + if (const json::Member* member = json::find(members, "filterbank")) { + out->filterbank_json = member->raw; + } + out->delay_source = delay_source; + out->metadata_json = metadata_text; + out->coefficients = std::move(coefficients); + out->delay_coefficients = std::move(delay_coefficients); + out->delay_bounds = std::move(delay_bounds); + out->band_centers_hz = std::move(centers); + return Status::success(); +} + +Status load_kernels(const std::string& npz_path, Kernels* out) { + if (out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kRender, "null kernels"); + } + io::ZipArchive archive; + std::string error; + if (!archive.open(npz_path, &error)) { + return Status::fail(JOC_ERR_HRTF_NOT_FOUND, stage::kRender, + "cannot read kernel tables " + npz_path + ": " + error); + } + + struct Request { + const char* member; + const char* shape_text; + std::vector shape; + }; + const Request requests[6] = { + {"qmf_analysis_coefficients.npy", " raw; + std::vector ordered; + for (const Request& request : requests) { + const std::string name = request.member; + if (!archive.read_member(name, &raw, &error)) { + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + "kernel table member " + name + ": " + error); + } + io::NpyArray array; + if (!io::parse_npy(raw.data(), raw.size(), &array, &error)) { + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + "kernel table member " + name + ": " + error); + } + if (array.descr != request.shape_text || !io::npy_shape_is(array, request.shape)) { + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + "kernel table member " + name + " has an unexpected dtype/shape"); + } + // Logical C order: required because the reused kernel indexes the hybrid + // synthesis table row-major while the shipped member is Fortran-order. + if (!io::npy_to_c_order(array, &ordered, &error)) { + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + "kernel table member " + name + ": " + error); + } + const std::size_t count = array.element_count(); + if (std::strcmp(request.member, "qmf_analysis_coefficients.npy") == 0) { + std::vector values(count); + std::memcpy(values.data(), ordered.data(), count * sizeof(float)); + out->qmf_analysis.assign(values.begin(), values.end()); + } else if (std::strcmp(request.member, "hybrid_analysis_low_kernel.npy") == 0) { + std::vector values(count); + std::memcpy(values.data(), ordered.data(), count * sizeof(float)); + out->hybrid_low.assign(values.begin(), values.end()); + } else if (std::strcmp(request.member, "hybrid_synthesis_indices.npy") == 0) { + out->hybrid_indices.resize(count); + std::memcpy(out->hybrid_indices.data(), ordered.data(), count * sizeof(std::int16_t)); + } else if (std::strcmp(request.member, "hybrid_synthesis_values.npy") == 0) { + std::vector values(count); + std::memcpy(values.data(), ordered.data(), count * sizeof(float)); + out->hybrid_values.assign(values.begin(), values.end()); + } else if (std::strcmp(request.member, "qmf_synthesis_basis.npy") == 0) { + std::memcpy(out->qmf_basis.empty() ? (out->qmf_basis.resize(count), out->qmf_basis.data()) + : out->qmf_basis.data(), + ordered.data(), count * sizeof(double)); + out->qmf_basis.resize(count); + } else { + out->qmf_taps.resize(count); + std::memcpy(out->qmf_taps.data(), ordered.data(), count * sizeof(double)); + } + } + out->hybrid_count = static_cast(out->hybrid_values.size()); + if (out->hybrid_count == 0u) { + return Status::fail(JOC_ERR_HRTF_FORMAT, stage::kRender, + "kernel tables contain no hybrid synthesis entries"); + } + return Status::success(); +} + +} // namespace joc::hrtf diff --git a/src/hrtf/jochrtf.h b/src/hrtf/jochrtf.h new file mode 100644 index 0000000..15e69a7 --- /dev/null +++ b/src/hrtf/jochrtf.h @@ -0,0 +1,66 @@ + +#pragma once + +#include +#include +#include + +#include "foundation/status.h" + +namespace joc::hrtf { + +inline constexpr int kShTerms = 36; +inline constexpr int kEars = 2; +inline constexpr int kHybridBands = 77; +inline constexpr int kFormatVersion = 1; +inline constexpr const char* kMagic = "JOC-HRTF-CACHE"; +inline constexpr const char* kCacheSchema = "joc-compiled-hrtf-v1"; + +struct Field { + std::vector coefficients; + std::vector delay_coefficients; + std::vector delay_bounds; + std::vector band_centers_hz; + double measurement_radius_m = 1.0; + long long order = 5; + std::string source_sha256; + std::string cache_key; + std::string payload_sha256; + std::string delay_source; + std::string compiler_version; + std::string phase_policy_version; + std::string sh_convention; + std::string filterbank_json; + std::string metadata_json; + // Compile-side metadata, needed to write the cache back out unchanged. + std::string source_display_name; + std::string fit_report_json; + double projection_ridge = 0.0; + double spherical_harmonic_ridge = 0.0; +}; + +Status load_jochrtf(const std::string& path, Field* out); + +// Binaural filterbank kernels, as the reused kernel expects them (C order, the +// exact dtypes of the ABI parameters). +struct Kernels { + std::vector qmf_analysis; + std::vector hybrid_low; + std::vector hybrid_indices; + std::vector hybrid_values; + std::vector qmf_basis; + std::vector qmf_taps; + std::uint32_t hybrid_count = 0; +}; + +// Loads a kernel-table archive. The file path is an override for verification; +// the shipped tables are embedded (see builtin_kernels) so no data file is needed. +// The Fortran-order index member is transposed into C order on purpose: the reused +// kernel indexes the hybrid synthesis table row-major. +Status load_kernels(const std::string& npz_path, Kernels* out); + +// The public filterbank tables compiled into the library (identical values to the +// archive the file loader accepts; the unit test checks their hashes). +const Kernels& builtin_kernels(); + +} // namespace joc::hrtf diff --git a/src/hrtf/kernel_tables.cpp b/src/hrtf/kernel_tables.cpp new file mode 100644 index 0000000..810cd8a --- /dev/null +++ b/src/hrtf/kernel_tables.cpp @@ -0,0 +1,9523 @@ +// Public binaural filterbank tables, embedded verbatim. +// +// Values are hex float literals so every bit survives the trip through source; +// they are copied from the standard-defined tables, not recomputed, because the +// rank-4 synthesis decomposition and the delay permutation cannot be re-derived +// from the documents alone. The unit test checks the per-member SHA-256 below. +// +// Source archive members and their content hashes: +// qmf_analysis_coefficients aeff6c7117d41664b9c4bf03bbf563f5319ec1b8c551f171adbb90cf19d9d306 +// hybrid_analysis_low_kernel d00d36133b81ba699a7630c4df1be203fa1b7e371e595eaaebbe8957db322627 +// hybrid_synthesis_values 99409fdd9d20d1d7c2be16bbc1e2159c8042487227c72160850745164c9cee7f +// qmf_synthesis_basis a0c4a55385f6d6c7c92d7615c83ad5fbda51046d9ef785cac0b9ac9a760dc527 +// qmf_synthesis_taps cd7756d060d51fbf02f44c1ce53cb6225b221099505c94c3f58d3bee6f428150 +// hybrid_synthesis_indices f5beb3220e4530fcf28e7f4da7f07e821074265d118c911d61a590e00753a573 + +#include "hrtf/jochrtf.h" + +#include + +namespace joc::hrtf { +namespace { + +// Source format_version: 1 +constexpr std::size_t kQmfAnalysisCount = 640; +constexpr std::size_t kHybridLowCount = 2496; +constexpr std::size_t kHybridIndexCount = 616; +constexpr std::size_t kHybridValueCount = 154; +constexpr std::size_t kQmfBasisCount = 32768; +constexpr std::size_t kQmfTapsCount = 2560; + + +// qmf_analysis_coefficients: 64x10 float32, sha256 aeff6c7117d41664 +const float qmf_analysis_coefficients[640] = { + 0x1.42c5dc0000000p-16f, 0x1.8f47300000000p-14f, 0x1.2533d60000000p-11f, 0x1.6664260000000p-9f, 0x1.b507660000000p-8f, -0x1.7d51100000000p-9f, + 0x1.1a7c840000000p-11f, -0x1.d78bfc0000000p-14f, 0x1.6d4dc00000000p-16f, 0x1.21af240000000p-18f, 0x1.2db1180000000p-16f, 0x1.6cc2400000000p-14f, + 0x1.29afd80000000p-11f, 0x1.5b01540000000p-9f, 0x1.b4c9cc0000000p-8f, -0x1.88d79c0000000p-9f, 0x1.1449140000000p-11f, -0x1.fd3b9e0000000p-14f, + 0x1.82430e0000000p-16f, 0x1.2687640000000p-18f, 0x1.194d1e0000000p-16f, 0x1.4b72f40000000p-14f, 0x1.2da1c20000000p-11f, 0x1.4fadc80000000p-9f, + 0x1.b461460000000p-8f, -0x1.9466380000000p-9f, 0x1.0d63de0000000p-11f, -0x1.1225100000000p-13f, 0x1.97f7940000000p-16f, 0x1.0364740000000p-18f, + 0x1.040fd20000000p-16f, 0x1.2b413c0000000p-14f, 0x1.3103b80000000p-11f, 0x1.446e880000000p-9f, 0x1.b3d01a0000000p-8f, -0x1.9ffb380000000p-9f, + 0x1.05eaa60000000p-11f, -0x1.25fbd00000000p-13f, 0x1.ad1fea0000000p-16f, 0x1.ff34660000000p-19f, 0x1.e0fd200000000p-17f, 0x1.0c09540000000p-14f, + 0x1.33d87c0000000p-11f, 0x1.39406e0000000p-9f, 0x1.b3166c0000000p-8f, -0x1.ab97640000000p-9f, 0x1.fb941e0000000p-12f, -0x1.3a5d200000000p-13f, + 0x1.c322960000000p-16f, 0x1.00935a0000000p-18f, 0x1.ba2fc80000000p-17f, 0x1.dbe5200000000p-15f, 0x1.3631440000000p-11f, 0x1.2e27440000000p-9f, + 0x1.b231320000000p-8f, -0x1.b734b40000000p-9f, 0x1.ea04a00000000p-12f, -0x1.4f1ad80000000p-13f, 0x1.d7f7b20000000p-16f, 0x1.0847520000000p-18f, + 0x1.94d5b20000000p-17f, 0x1.a211b60000000p-15f, 0x1.38031c0000000p-11f, 0x1.2325280000000p-9f, 0x1.b124860000000p-8f, -0x1.c2d24e0000000p-9f, + 0x1.d72a440000000p-12f, -0x1.644c800000000p-13f, 0x1.ece1d40000000p-16f, 0x1.1205c20000000p-18f, 0x1.6c72100000000p-17f, 0x1.6aa8700000000p-15f, + 0x1.395d600000000p-11f, 0x1.183b360000000p-9f, 0x1.afef740000000p-8f, -0x1.ce70240000000p-9f, 0x1.c2efd40000000p-12f, -0x1.79f2460000000p-13f, + 0x1.00f3280000000p-15f, 0x1.1e9b000000000p-18f, 0x1.49b8c20000000p-17f, 0x1.357a5e0000000p-15f, 0x1.3a3f440000000p-11f, 0x1.0d6b7c0000000p-9f, + 0x1.ae91880000000p-8f, -0x1.da0a880000000p-9f, 0x1.ad566e0000000p-12f, -0x1.9008880000000p-13f, 0x1.0b842c0000000p-15f, 0x1.29ae2e0000000p-18f, + 0x1.26ea840000000p-17f, 0x1.02381e0000000p-15f, 0x1.3aaac20000000p-11f, 0x1.02b62a0000000p-9f, 0x1.ad0aa20000000p-8f, -0x1.e5a0900000000p-9f, + 0x1.964e440000000p-12f, -0x1.a680f80000000p-13f, 0x1.14fbae0000000p-15f, 0x1.33ce4c0000000p-18f, 0x1.0327be0000000p-17f, 0x1.a28ffa0000000p-16f, + 0x1.3aa4e20000000p-11f, 0x1.f03bdc0000000p-10f, 0x1.ab5cfa0000000p-8f, -0x1.f12d8c0000000p-9f, 0x1.7dfee20000000p-12f, -0x1.bd6a1a0000000p-13f, + 0x1.1e97f80000000p-15f, 0x1.4188580000000p-18f, 0x1.c354920000000p-18f, 0x1.4568aa0000000p-16f, 0x1.3a33960000000p-11f, 0x1.db470a0000000p-10f, + 0x1.a986720000000p-8f, -0x1.fcb17e0000000p-9f, 0x1.6429a00000000p-12f, -0x1.d4b35e0000000p-13f, 0x1.28498c0000000p-15f, 0x1.4af4da0000000p-18f, + 0x1.8703ee0000000p-18f, 0x1.d8e4d80000000p-17f, 0x1.39573e0000000p-11f, 0x1.c695ba0000000p-10f, 0x1.a78a5e0000000p-8f, -0x1.04162e0000000p-8f, + 0x1.48dfe80000000p-12f, -0x1.ec57f20000000p-13f, 0x1.3170a80000000p-15f, 0x1.56e6de0000000p-18f, 0x1.471f7e0000000p-18f, 0x1.2f40720000000p-17f, + 0x1.381cb40000000p-11f, 0x1.b21f340000000p-10f, 0x1.a565c20000000p-8f, -0x1.09ca8e0000000p-8f, 0x1.2c2b720000000p-12f, -0x1.020ffc0000000p-12f, + 0x1.3a217c0000000p-15f, 0x1.6358a00000000p-18f, 0x1.0bc6360000000p-18f, 0x1.1e7c560000000p-18f, 0x1.367af00000000p-11f, 0x1.9df3b80000000p-10f, + 0x1.a31c9a0000000p-8f, -0x1.0f79880000000p-8f, 0x1.0dfec20000000p-12f, -0x1.0e22720000000p-12f, 0x1.4207380000000p-15f, 0x1.6bf0c60000000p-18f, + 0x1.a6369c0000000p-19f, -0x1.cf20820000000p-23f, 0x1.347c2c0000000p-11f, 0x1.8a07440000000p-10f, 0x1.a0ace60000000p-8f, -0x1.151f6c0000000p-8f, + 0x1.dc7c6e0000000p-13f, -0x1.1a50400000000p-12f, 0x1.4a41760000000p-15f, 0x1.7745840000000p-18f, 0x1.3547e00000000p-19f, -0x1.31c7520000000p-18f, + 0x1.3228140000000p-11f, 0x1.7668e40000000p-10f, 0x1.9e170a0000000p-8f, -0x1.1abaa40000000p-8f, 0x1.9a1a9a0000000p-13f, -0x1.26aa0c0000000p-12f, + 0x1.50e73a0000000p-15f, 0x1.7c5f8a0000000p-18f, 0x1.ac73a20000000p-20f, -0x1.1dcc4a0000000p-17f, 0x1.2f83de0000000p-11f, 0x1.63157c0000000p-10f, + 0x1.9b5d9c0000000p-8f, -0x1.204be20000000p-8f, 0x1.54c84a0000000p-13f, -0x1.330bf40000000p-12f, 0x1.57cf3c0000000p-15f, 0x1.861ea20000000p-18f, + 0x1.cb047e0000000p-21f, -0x1.9dc9340000000p-17f, 0x1.2c7da80000000p-11f, 0x1.5011800000000p-10f, 0x1.987f580000000p-8f, -0x1.25cffc0000000p-8f, + 0x1.0c35480000000p-13f, -0x1.3f88300000000p-12f, 0x1.5e6e980000000p-15f, 0x1.88b91a0000000p-18f, 0x1.c4d0f20000000p-24f, -0x1.09bcd80000000p-16f, + 0x1.293d560000000p-11f, 0x1.3d5c0c0000000p-10f, 0x1.957d900000000p-8f, -0x1.2b48de0000000p-8f, 0x1.816e060000000p-14f, -0x1.4c0fe20000000p-12f, + 0x1.632f1a0000000p-15f, 0x1.92b9a00000000p-18f, -0x1.02edc60000000p-21f, -0x1.413d040000000p-16f, 0x1.25af2e0000000p-11f, 0x1.2af5cc0000000p-10f, + 0x1.9259020000000p-8f, -0x1.30b2900000000p-8f, 0x1.c85f420000000p-15f, -0x1.5898800000000p-12f, 0x1.67a2b80000000p-15f, 0x1.95012a0000000p-18f, + -0x1.2f53fc0000000p-20f, -0x1.74db7a0000000p-16f, 0x1.21d8400000000p-11f, 0x1.18e4d00000000p-10f, 0x1.8f11480000000p-8f, -0x1.360e5e0000000p-8f, + 0x1.0312580000000p-16f, -0x1.6540480000000p-12f, 0x1.6b90cc0000000p-15f, 0x1.9abe9e0000000p-18f, -0x1.b80da20000000p-20f, -0x1.a4a2800000000p-16f, + 0x1.1dbfd60000000p-11f, 0x1.072b280000000p-10f, 0x1.8ba9920000000p-8f, -0x1.3b58b00000000p-8f, -0x1.a491c20000000p-16f, -0x1.71dbfc0000000p-12f, + 0x1.6e986c0000000p-15f, 0x1.97e3a40000000p-18f, -0x1.2fc5400000000p-19f, -0x1.d002de0000000p-16f, 0x1.1969c40000000p-11f, 0x1.eb8d4c0000000p-11f, + 0x1.881fc80000000p-8f, -0x1.40935c0000000p-8f, -0x1.18dc3a0000000p-14f, -0x1.7e70140000000p-12f, 0x1.7072960000000p-15f, 0x1.9923040000000p-18f, + -0x1.6f1ffa0000000p-19f, -0x1.f80e4a0000000p-16f, 0x1.14ebb40000000p-11f, 0x1.c973ca0000000p-11f, 0x1.8475600000000p-8f, -0x1.45bbbe0000000p-8f, + -0x1.cef9a60000000p-14f, -0x1.8afd780000000p-12f, 0x1.71fc180000000p-15f, 0x1.9905480000000p-18f, -0x1.ad67920000000p-19f, -0x1.0e58c60000000p-15f, + 0x1.101ffc0000000p-11f, 0x1.a8122c0000000p-11f, 0x1.80ac320000000p-8f, -0x1.4ad1280000000p-8f, -0x1.45c5140000000p-13f, -0x1.9775580000000p-12f, + 0x1.718d600000000p-15f, 0x1.96bdce0000000p-18f, -0x1.e3021a0000000p-19f, -0x1.1f0f540000000p-15f, 0x1.0b290e0000000p-11f, 0x1.8762f00000000p-11f, + 0x1.7cc3fe0000000p-8f, -0x1.4fd2540000000p-8f, -0x1.a7145e0000000p-13f, -0x1.a3e2d00000000p-12f, 0x1.70bee00000000p-15f, 0x1.9012c60000000p-18f, + -0x1.0dc6b40000000p-18f, -0x1.2db9820000000p-15f, 0x1.0607120000000p-11f, 0x1.6771860000000p-11f, 0x1.78bd8c0000000p-8f, -0x1.54be3e0000000p-8f, + -0x1.05c2900000000p-12f, -0x1.b03c2e0000000p-12f, 0x1.6e75600000000p-15f, 0x1.8ac9f80000000p-18f, -0x1.23be7a0000000p-18f, -0x1.3b4a4c0000000p-15f, + 0x1.00c2ce0000000p-11f, 0x1.483e0a0000000p-11f, 0x1.749afa0000000p-8f, -0x1.5995300000000p-8f, -0x1.3992100000000p-12f, -0x1.bc60960000000p-12f, + 0x1.6b19180000000p-15f, 0x1.7fbec00000000p-18f, -0x1.37bf760000000p-18f, -0x1.46a11e0000000p-15f, 0x1.f68ae00000000p-12f, 0x1.29c1880000000p-11f, + 0x1.705b420000000p-8f, -0x1.5e54180000000p-8f, -0x1.6ed7e60000000p-12f, -0x1.c86fc80000000p-12f, 0x1.66d59a0000000p-15f, 0x1.7a4b5a0000000p-18f, + -0x1.4c7b720000000p-18f, -0x1.50bd280000000p-15f, 0x1.eb630c0000000p-12f, 0x1.0c0bd80000000p-11f, 0x1.6c00760000000p-8f, -0x1.62fbec0000000p-8f, + -0x1.a5ba420000000p-12f, -0x1.d444a80000000p-12f, 0x1.60d6d00000000p-15f, 0x1.6ab2fc0000000p-18f, -0x1.5cac5c0000000p-18f, -0x1.597a5e0000000p-15f, + 0x1.dffb6a0000000p-12f, 0x1.de2be20000000p-12f, 0x1.678bda0000000p-8f, -0x1.678bda0000000p-8f, -0x1.de2be20000000p-12f, -0x1.dffb6a0000000p-12f, + 0x1.597a5e0000000p-15f, 0x1.5cac5c0000000p-18f, -0x1.6ab2fc0000000p-18f, -0x1.60d6d00000000p-15f, 0x1.d444a80000000p-12f, 0x1.a5ba420000000p-12f, + 0x1.62fbec0000000p-8f, -0x1.6c00760000000p-8f, -0x1.0c0bd60000000p-11f, -0x1.eb630a0000000p-12f, 0x1.50bd280000000p-15f, 0x1.4c7b720000000p-18f, + -0x1.7a4b5a0000000p-18f, -0x1.66d59a0000000p-15f, 0x1.c86fc80000000p-12f, 0x1.6ed7e60000000p-12f, 0x1.5e54180000000p-8f, -0x1.705b420000000p-8f, + -0x1.29c1880000000p-11f, -0x1.f68ae00000000p-12f, 0x1.46a11c0000000p-15f, 0x1.37bf760000000p-18f, -0x1.7fbebe0000000p-18f, -0x1.6b19180000000p-15f, + 0x1.bc60960000000p-12f, 0x1.3992100000000p-12f, 0x1.59952e0000000p-8f, -0x1.749af80000000p-8f, -0x1.483e0a0000000p-11f, -0x1.00c2ce0000000p-11f, + 0x1.3b4a4a0000000p-15f, 0x1.23be7a0000000p-18f, -0x1.8ac9f60000000p-18f, -0x1.6e75600000000p-15f, 0x1.b03c2e0000000p-12f, 0x1.05c2900000000p-12f, + 0x1.54be3e0000000p-8f, -0x1.78bd8c0000000p-8f, -0x1.6771860000000p-11f, -0x1.0607100000000p-11f, 0x1.2db9820000000p-15f, 0x1.0dc6b40000000p-18f, + -0x1.9012c60000000p-18f, -0x1.70bee00000000p-15f, 0x1.a3e2d00000000p-12f, 0x1.a714600000000p-13f, 0x1.4fd2560000000p-8f, -0x1.7cc3fc0000000p-8f, + -0x1.8762f00000000p-11f, -0x1.0b29100000000p-11f, 0x1.1f0f540000000p-15f, 0x1.e3021a0000000p-19f, -0x1.96bdce0000000p-18f, -0x1.718d600000000p-15f, + 0x1.9775580000000p-12f, 0x1.45c5120000000p-13f, 0x1.4ad1280000000p-8f, -0x1.80ac320000000p-8f, -0x1.a8122a0000000p-11f, -0x1.101ffc0000000p-11f, + 0x1.0e58c40000000p-15f, 0x1.ad67940000000p-19f, -0x1.9905480000000p-18f, -0x1.71fc1a0000000p-15f, 0x1.8afd780000000p-12f, 0x1.cef9a60000000p-14f, + 0x1.45bbbe0000000p-8f, -0x1.8475620000000p-8f, -0x1.c973ca0000000p-11f, -0x1.14ebb40000000p-11f, 0x1.f80e4a0000000p-16f, 0x1.6f1ffa0000000p-19f, + -0x1.9923040000000p-18f, -0x1.7072960000000p-15f, 0x1.7e70140000000p-12f, 0x1.18dc3a0000000p-14f, 0x1.40935c0000000p-8f, -0x1.881fc80000000p-8f, + -0x1.eb8d4c0000000p-11f, -0x1.1969c40000000p-11f, 0x1.d002de0000000p-16f, 0x1.2fc5400000000p-19f, -0x1.97e3a40000000p-18f, -0x1.6e986e0000000p-15f, + 0x1.71dbfc0000000p-12f, 0x1.a491c40000000p-16f, 0x1.3b58b00000000p-8f, -0x1.8ba9940000000p-8f, -0x1.072b280000000p-10f, -0x1.1dbfd60000000p-11f, + 0x1.a4a2800000000p-16f, 0x1.b80da20000000p-20f, -0x1.9abe9e0000000p-18f, -0x1.6b90cc0000000p-15f, 0x1.6540480000000p-12f, -0x1.03125a0000000p-16f, + 0x1.360e5e0000000p-8f, -0x1.8f11480000000p-8f, -0x1.18e4d00000000p-10f, -0x1.21d8400000000p-11f, 0x1.74db7a0000000p-16f, 0x1.2f53fc0000000p-20f, + -0x1.95012a0000000p-18f, -0x1.67a2b80000000p-15f, 0x1.5898800000000p-12f, -0x1.c85f420000000p-15f, 0x1.30b2900000000p-8f, -0x1.9259020000000p-8f, + -0x1.2af5cc0000000p-10f, -0x1.25af2e0000000p-11f, 0x1.413d040000000p-16f, 0x1.02edc60000000p-21f, -0x1.92b9a00000000p-18f, -0x1.632f1a0000000p-15f, + 0x1.4c0fe20000000p-12f, -0x1.816e060000000p-14f, 0x1.2b48de0000000p-8f, -0x1.957d900000000p-8f, -0x1.3d5c0a0000000p-10f, -0x1.293d560000000p-11f, + 0x1.09bcd80000000p-16f, -0x1.c4d0f20000000p-24f, -0x1.88b91a0000000p-18f, -0x1.5e6e980000000p-15f, 0x1.3f88300000000p-12f, -0x1.0c35480000000p-13f, + 0x1.25cffc0000000p-8f, -0x1.987f580000000p-8f, -0x1.5011800000000p-10f, -0x1.2c7da80000000p-11f, 0x1.9dc9360000000p-17f, -0x1.cb047c0000000p-21f, + -0x1.861ea20000000p-18f, -0x1.57cf3a0000000p-15f, 0x1.330bf40000000p-12f, -0x1.54c84c0000000p-13f, 0x1.204be20000000p-8f, -0x1.9b5d9c0000000p-8f, + -0x1.63157c0000000p-10f, -0x1.2f83de0000000p-11f, 0x1.1dcc4a0000000p-17f, -0x1.ac73a40000000p-20f, -0x1.7c5f8a0000000p-18f, -0x1.50e73a0000000p-15f, + 0x1.26aa0c0000000p-12f, -0x1.9a1a9a0000000p-13f, 0x1.1abaa40000000p-8f, -0x1.9e170a0000000p-8f, -0x1.7668e40000000p-10f, -0x1.3228140000000p-11f, + 0x1.31c7540000000p-18f, -0x1.3547e00000000p-19f, -0x1.7745840000000p-18f, -0x1.4a41760000000p-15f, 0x1.1a50400000000p-12f, -0x1.dc7c6e0000000p-13f, + 0x1.151f6a0000000p-8f, -0x1.a0ace60000000p-8f, -0x1.8a07440000000p-10f, -0x1.347c2c0000000p-11f, 0x1.cf20820000000p-23f, -0x1.a6369c0000000p-19f, + -0x1.6bf0c60000000p-18f, -0x1.4207360000000p-15f, 0x1.0e22720000000p-12f, -0x1.0dfec20000000p-12f, 0x1.0f79880000000p-8f, -0x1.a31c9a0000000p-8f, + -0x1.9df3b80000000p-10f, -0x1.367af00000000p-11f, -0x1.1e7c560000000p-18f, -0x1.0bc6360000000p-18f, -0x1.6358a00000000p-18f, -0x1.3a217c0000000p-15f, + 0x1.020ffc0000000p-12f, -0x1.2c2b720000000p-12f, 0x1.09ca8e0000000p-8f, -0x1.a565c20000000p-8f, -0x1.b21f340000000p-10f, -0x1.381cb20000000p-11f, + -0x1.2f40720000000p-17f, -0x1.471f7e0000000p-18f, -0x1.56e6de0000000p-18f, -0x1.3170a80000000p-15f, 0x1.ec57f40000000p-13f, -0x1.48dfe80000000p-12f, + 0x1.0416300000000p-8f, -0x1.a78a5e0000000p-8f, -0x1.c695b80000000p-10f, -0x1.39573e0000000p-11f, -0x1.d8e4d80000000p-17f, -0x1.8703ec0000000p-18f, + -0x1.4af4da0000000p-18f, -0x1.28498c0000000p-15f, 0x1.d4b35e0000000p-13f, -0x1.6429a00000000p-12f, 0x1.fcb17c0000000p-9f, -0x1.a986700000000p-8f, + -0x1.db470a0000000p-10f, -0x1.3a33940000000p-11f, -0x1.4568aa0000000p-16f, -0x1.c354920000000p-18f, -0x1.4188560000000p-18f, -0x1.1e97f80000000p-15f, + 0x1.bd6a1a0000000p-13f, -0x1.7dfee20000000p-12f, 0x1.f12d8c0000000p-9f, -0x1.ab5cf80000000p-8f, -0x1.f03bdc0000000p-10f, -0x1.3aa4e20000000p-11f, + -0x1.a28ff80000000p-16f, -0x1.0327be0000000p-17f, -0x1.33ce4c0000000p-18f, -0x1.14fbae0000000p-15f, 0x1.a680f80000000p-13f, -0x1.964e440000000p-12f, + 0x1.e5a0900000000p-9f, -0x1.ad0aa20000000p-8f, -0x1.02b6280000000p-9f, -0x1.3aaac20000000p-11f, -0x1.02381c0000000p-15f, -0x1.26ea840000000p-17f, + -0x1.29ae2e0000000p-18f, -0x1.0b842c0000000p-15f, 0x1.9008880000000p-13f, -0x1.ad566e0000000p-12f, 0x1.da0a860000000p-9f, -0x1.ae91880000000p-8f, + -0x1.0d6b7c0000000p-9f, -0x1.3a3f440000000p-11f, -0x1.357a5e0000000p-15f, -0x1.49b8c20000000p-17f, -0x1.1e9b000000000p-18f, -0x1.00f3280000000p-15f, + 0x1.79f2460000000p-13f, -0x1.c2efd40000000p-12f, 0x1.ce70240000000p-9f, -0x1.afef740000000p-8f, -0x1.183b360000000p-9f, -0x1.395d600000000p-11f, + -0x1.6aa8700000000p-15f, -0x1.6c72100000000p-17f, -0x1.1205c20000000p-18f, -0x1.ece1d40000000p-16f, 0x1.644c800000000p-13f, -0x1.d72a440000000p-12f, + 0x1.c2d24e0000000p-9f, -0x1.b124860000000p-8f, -0x1.2325280000000p-9f, -0x1.38031a0000000p-11f, -0x1.a211b60000000p-15f, -0x1.94d5b20000000p-17f, + -0x1.0847520000000p-18f, -0x1.d7f7b20000000p-16f, 0x1.4f1ad80000000p-13f, -0x1.ea04a00000000p-12f, 0x1.b734b20000000p-9f, -0x1.b231320000000p-8f, + -0x1.2e27440000000p-9f, -0x1.3631440000000p-11f, -0x1.dbe5200000000p-15f, -0x1.ba2fc80000000p-17f, -0x1.00935a0000000p-18f, -0x1.c322940000000p-16f, + 0x1.3a5d220000000p-13f, -0x1.fb94200000000p-12f, 0x1.ab97640000000p-9f, -0x1.b3166e0000000p-8f, -0x1.3940700000000p-9f, -0x1.33d87c0000000p-11f, + -0x1.0c09540000000p-14f, -0x1.e0fd200000000p-17f, -0x1.ff34660000000p-19f, -0x1.ad1fea0000000p-16f, 0x1.25fbd00000000p-13f, -0x1.05eaa60000000p-11f, + 0x1.9ffb380000000p-9f, -0x1.b3d01a0000000p-8f, -0x1.446e880000000p-9f, -0x1.3103b80000000p-11f, -0x1.2b413c0000000p-14f, -0x1.040fd20000000p-16f, + -0x1.0364740000000p-18f, -0x1.97f7940000000p-16f, 0x1.1225100000000p-13f, -0x1.0d63de0000000p-11f, 0x1.9466380000000p-9f, -0x1.b461460000000p-8f, + -0x1.4fadc80000000p-9f, -0x1.2da1c20000000p-11f, -0x1.4b72f40000000p-14f, -0x1.194d200000000p-16f, -0x1.2687640000000p-18f, -0x1.82430e0000000p-16f, + 0x1.fd3b9e0000000p-14f, -0x1.1449140000000p-11f, 0x1.88d79c0000000p-9f, -0x1.b4c9cc0000000p-8f, -0x1.5b01540000000p-9f, -0x1.29afd80000000p-11f, + -0x1.6cc2400000000p-14f, -0x1.2db1180000000p-16f, -0x1.21af240000000p-18f, -0x1.6d4dc20000000p-16f, 0x1.d78bfa0000000p-14f, -0x1.1a7c840000000p-11f, + 0x1.7d51100000000p-9f, -0x1.b507660000000p-8f, -0x1.6664260000000p-9f, -0x1.2533d60000000p-11f, -0x1.8f472e0000000p-14f, -0x1.42c5dc0000000p-16f, + 0x0.0p+0f, -0x1.576e840000000p-16f, 0x1.b2e41c0000000p-14f, -0x1.202aca0000000p-11f, 0x1.71d3aa0000000p-9f, -0x1.b51d380000000p-8f, + -0x1.71d3aa0000000p-9f, -0x1.202aca0000000p-11f, -0x1.b2e41c0000000p-14f, -0x1.576e840000000p-16f, +}; + +// hybrid_analysis_low_kernel: 3x2x13x16x2 float32, sha256 d00d36133b81ba69 +const float hybrid_analysis_low_kernel[2496] = { + -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, + 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.1cb4a20000000p-7f, -0x1.57ab880000000p-6f, -0x1.1cb4a00000000p-7f, -0x1.57ab880000000p-6f, + 0x1.57ab880000000p-6f, 0x1.1cb4a00000000p-7f, 0x1.57ab880000000p-6f, 0x1.1cb4a20000000p-7f, -0x1.57ab880000000p-6f, 0x1.1cb4a20000000p-7f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.1cb4a00000000p-7f, -0x1.57ab880000000p-6f, 0x1.1cb4a20000000p-7f, 0x1.57ab880000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.57ab880000000p-6f, -0x1.1cb4a00000000p-7f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.747ab00000000p-5f, + 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x1.747ab00000000p-5f, 0x0.0p+0f, 0x1.747ab00000000p-5f, + 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.747ab00000000p-5f, + 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.747ab00000000p-5f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.c793b60000000p-6f, -0x1.12f70c0000000p-4f, 0x1.c793b20000000p-6f, -0x1.12f70c0000000p-4f, -0x1.12f70c0000000p-4f, 0x1.c793b20000000p-6f, + -0x1.12f70c0000000p-4f, 0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, 0x1.c793b60000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.c793b20000000p-6f, -0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.12f70c0000000p-4f, -0x1.c793b20000000p-6f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, + -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, + 0x1.be4c800000000p-4f, -0x1.71b9e00000000p-5f, 0x1.71b9e00000000p-5f, -0x1.be4c800000000p-4f, 0x1.71b9de0000000p-5f, -0x1.be4c800000000p-4f, + -0x1.71b9de0000000p-5f, -0x1.be4c800000000p-4f, 0x0.0p+0f, 0x0.0p+0f, -0x1.be4c800000000p-4f, -0x1.71b9e00000000p-5f, + -0x1.be4c800000000p-4f, 0x1.71b9de0000000p-5f, 0x0.0p+0f, 0x0.0p+0f, -0x1.71b9e00000000p-5f, 0x1.be4c800000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.0000000000000p-3f, 0x0.0p+0f, 0x1.0000000000000p-3f, -0x0.0p+0f, 0x1.0000000000000p-3f, 0x0.0p+0f, + 0x1.0000000000000p-3f, -0x0.0p+0f, 0x1.0000000000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.0000000000000p-3f, 0x0.0p+0f, 0x1.0000000000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.0000000000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.be4c800000000p-4f, 0x1.71b9de0000000p-5f, 0x1.be4c800000000p-4f, 0x1.71b9e00000000p-5f, + 0x1.71b9e00000000p-5f, 0x1.be4c800000000p-4f, 0x1.71b9de0000000p-5f, 0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, 0x1.be4c800000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.be4c800000000p-4f, 0x1.71b9e00000000p-5f, -0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.71b9e00000000p-5f, -0x1.be4c800000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, + 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, + -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, + 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, 0x1.c793b20000000p-6f, 0x1.12f70c0000000p-4f, -0x1.12f70c0000000p-4f, -0x1.c793b20000000p-6f, + -0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.c793b20000000p-6f, 0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, -0x1.12f70c0000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.12f70c0000000p-4f, 0x1.c793b20000000p-6f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.747ab00000000p-5f, 0x0.0p+0f, 0x1.747ab00000000p-5f, + 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x1.747ab00000000p-5f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x1.747ab00000000p-5f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.1cb4a20000000p-7f, 0x1.57ab880000000p-6f, + -0x1.1cb4a00000000p-7f, 0x1.57ab880000000p-6f, 0x1.57ab880000000p-6f, -0x1.1cb4a00000000p-7f, 0x1.57ab880000000p-6f, -0x1.1cb4a20000000p-7f, + -0x1.57ab880000000p-6f, -0x1.1cb4a20000000p-7f, 0x0.0p+0f, 0x0.0p+0f, 0x1.1cb4a00000000p-7f, 0x1.57ab880000000p-6f, + 0x1.1cb4a20000000p-7f, -0x1.57ab880000000p-6f, 0x0.0p+0f, 0x0.0p+0f, -0x1.57ab880000000p-6f, 0x1.1cb4a00000000p-7f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, + 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, + 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.57ab880000000p-6f, -0x1.1cb4a20000000p-7f, + -0x1.57ab880000000p-6f, 0x1.1cb4a00000000p-7f, -0x1.1cb4a00000000p-7f, 0x1.57ab880000000p-6f, 0x1.1cb4a20000000p-7f, -0x1.57ab880000000p-6f, + -0x1.1cb4a20000000p-7f, -0x1.57ab880000000p-6f, 0x0.0p+0f, 0x0.0p+0f, 0x1.57ab880000000p-6f, 0x1.1cb4a00000000p-7f, + -0x1.57ab880000000p-6f, 0x1.1cb4a20000000p-7f, 0x0.0p+0f, 0x0.0p+0f, 0x1.1cb4a00000000p-7f, -0x1.57ab880000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.747ab00000000p-5f, 0x0.0p+0f, -0x1.747ab00000000p-5f, -0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, + 0x1.747ab00000000p-5f, -0x0.0p+0f, 0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.12f70c0000000p-4f, 0x1.c793b60000000p-6f, -0x1.12f70c0000000p-4f, -0x1.c793b20000000p-6f, + -0x1.c793b20000000p-6f, -0x1.12f70c0000000p-4f, 0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.12f70c0000000p-4f, -0x1.c793b20000000p-6f, -0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.c793b20000000p-6f, 0x1.12f70c0000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, + -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, + -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, + 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.71b9de0000000p-5f, 0x1.be4c800000000p-4f, -0x1.71b9e00000000p-5f, -0x1.be4c800000000p-4f, 0x1.be4c800000000p-4f, 0x1.71b9e00000000p-5f, + -0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, 0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.71b9e00000000p-5f, -0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, -0x1.be4c800000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.be4c800000000p-4f, -0x1.71b9e00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-3f, 0x0.0p+0f, -0x1.0000000000000p-3f, + 0x0.0p+0f, 0x1.0000000000000p-3f, 0x0.0p+0f, -0x1.0000000000000p-3f, 0x0.0p+0f, 0x1.0000000000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-3f, 0x0.0p+0f, 0x1.0000000000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.71b9de0000000p-5f, 0x1.be4c800000000p-4f, + 0x1.71b9e00000000p-5f, -0x1.be4c800000000p-4f, -0x1.be4c800000000p-4f, 0x1.71b9e00000000p-5f, 0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, + -0x1.be4c800000000p-4f, -0x1.71b9de0000000p-5f, 0x0.0p+0f, 0x0.0p+0f, -0x1.71b9e00000000p-5f, -0x1.be4c800000000p-4f, + 0x1.71b9de0000000p-5f, -0x1.be4c800000000p-4f, 0x0.0p+0f, 0x0.0p+0f, 0x1.be4c800000000p-4f, -0x1.71b9e00000000p-5f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, + 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.1e4da60000000p-4f, -0x1.1e4da60000000p-4f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.12f70c0000000p-4f, 0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, -0x1.c793b20000000p-6f, + 0x1.c793b20000000p-6f, -0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, 0x1.c793b60000000p-6f, 0x1.12f70c0000000p-4f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.12f70c0000000p-4f, -0x1.c793b20000000p-6f, 0x1.12f70c0000000p-4f, -0x1.c793b60000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.c793b20000000p-6f, 0x1.12f70c0000000p-4f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.747ab00000000p-5f, 0x0.0p+0f, + 0x1.747ab00000000p-5f, -0x0.0p+0f, 0x1.747ab00000000p-5f, 0x0.0p+0f, -0x1.747ab00000000p-5f, -0x0.0p+0f, + -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.747ab00000000p-5f, 0x0.0p+0f, + -0x1.747ab00000000p-5f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.747ab00000000p-5f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.57ab880000000p-6f, -0x1.1cb4a20000000p-7f, 0x1.57ab880000000p-6f, 0x1.1cb4a00000000p-7f, 0x1.1cb4a00000000p-7f, 0x1.57ab880000000p-6f, + -0x1.1cb4a20000000p-7f, -0x1.57ab880000000p-6f, 0x1.1cb4a20000000p-7f, -0x1.57ab880000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.57ab880000000p-6f, 0x1.1cb4a00000000p-7f, 0x1.57ab880000000p-6f, 0x1.1cb4a20000000p-7f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.1cb4a00000000p-7f, -0x1.57ab880000000p-6f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, + -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, -0x1.59bdee0000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.59bdee0000000p-8f, 0x1.59bdee0000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, + 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, + 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, + -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, + 0x1.0000000000000p-2f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, + 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, + -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, + 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, + -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.00de8e0000000p-3f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, + 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, + 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x1.0000000000000p-2f, 0x0.0p+0f, 0x1.0000000000000p-2f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x1.3369560000000p-3f, 0x1.3369560000000p-3f, + 0x0.0p+0f, 0x0.0p+0f, -0x1.3369560000000p-3f, 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, -0x1.3369560000000p-3f, + 0x1.3369560000000p-3f, -0x1.3369560000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, + 0x1.00de8e0000000p-3f, 0x0.0p+0f, -0x1.00de8e0000000p-3f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, -0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, 0x1.f45b8a0000000p-6f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, + -0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x1.7058c40000000p-8f, -0x1.7058c40000000p-8f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, -0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, -0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + 0x0.0p+0f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x0.0p+0f, 0x0.0p+0f, + -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, 0x1.8ff7fe0000000p-9f, 0x0.0p+0f, -0x1.8ff7fe0000000p-9f, 0x0.0p+0f, +}; + +// hybrid_synthesis_values: 154 float32, sha256 99409fdd9d20d1d7 +const float hybrid_synthesis_values[154] = { + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, -0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, -0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, + 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, 0x1.0000000000000p+0f, +}; + +// qmf_synthesis_basis: 64x4x128 float64, sha256 a0c4a55385f6d6c7 +const double qmf_synthesis_basis[32768] = { + -0x1.921d212fd72dep-10, -0x1.fff6227275953p-4, 0x1.2d86585ab6f74p-8, 0x1.ffa72e2bf41c2p-4, + -0x1.f656e86de871bp-8, -0x1.ff09560835adbp-4, 0x1.5f6cfef4b1332p-7, 0x1.fe1caf142bcd6p-4, + -0x1.c3785bd3a6281p-7, -0x1.fce15ed8a65a8p-4, 0x1.139f0b58668cap-6, 0x1.fb5798c69b16ep-4, + -0x1.45576b2b66a22p-6, -0x1.f97f92daefcd4p-4, 0x1.76dd9dddd2842p-6, 0x1.f7599a576a548p-4, + -0x1.a82a029278d12p-6, -0x1.f4e6038b09b32p-4, 0x1.d934fda584d77p-6, 0x1.f22530e9133e0p-4, + -0x1.04fb80821570ap-5, -0x1.ef1789843f75ap-4, 0x1.1d344433692e7p-5, 0x1.ebbd8bd7f3b6ep-4, + -0x1.35410b145d685p-5, -0x1.e817b8b5e2e5fp-4, 0x1.4d1e236747a18p-5, 0x1.e426a3b279d19p-4, + -0x1.64c7deb69c911p-5, -0x1.dfeae51afc0dcp-4, 0x1.7c3a938e2baaap-5, 0x1.db6525a903ca7p-4, + -0x1.9372a4fccbb1cp-5, -0x1.d696175086c08p-4, 0x1.aa6c80f032469p-5, 0x1.d17e77d7e3055p-4, + -0x1.c1249d41b1cffp-5, -0x1.cc1f10badcf8fp-4, 0x1.d79775f02af4fp-5, 0x1.c678b4cc8c59dp-4, + -0x1.edc195e2a24f1p-5, -0x1.c08c429c5a0dap-4, 0x1.01cfc84349cf8p-4, 0x1.ba5aa6c7d0089p-4, + -0x1.0c97041f4bae0p-4, -0x1.b3e4d4e5df2e3p-4, 0x1.1734d64028613p-4, 0x1.ad2bca1392262p-4, + -0x1.21a79a60cebc9p-4, -0x1.a63091390a2b9p-4, 0x1.2bedb1a6ffccdp-4, 0x1.9ef43ee1b6551p-4, + -0x1.36058cd61c0f7p-4, -0x1.9777f0c625d2fp-4, 0x1.3fed9551045c3p-4, 0x1.8fbcc982f9d20p-4, + -0x1.49a44b09efc11p-4, -0x1.87c4007de37c4p-4, 0x1.5328290a5afdep-4, 0x1.7f8ecd784c893p-4, + -0x1.5c77bae975149p-4, -0x1.771e75e47708dp-4, 0x1.659190bca35e9p-4, 0x1.6e7446900b2f5p-4, + -0x1.6e7446900b2f5p-4, -0x1.659190bca35e9p-4, 0x1.771e75e47708dp-4, 0x1.5c77bae975149p-4, + -0x1.7f8ecd784c893p-4, -0x1.5328290a5afdep-4, 0x1.87c4007de37c4p-4, 0x1.49a44b09efc11p-4, + -0x1.8fbcc982f9d20p-4, -0x1.3fed9551045c3p-4, 0x1.9777f0c625d2fp-4, 0x1.36058cd61c0f7p-4, + -0x1.9ef43ee1b6551p-4, -0x1.2bedb1a6ffccdp-4, 0x1.a63091390a2b9p-4, 0x1.21a79a60cebc9p-4, + -0x1.ad2bca1392262p-4, -0x1.1734d64028613p-4, 0x1.b3e4d4e5df2e3p-4, 0x1.0c97041f4bae0p-4, + -0x1.ba5aa6c7d0089p-4, -0x1.01cfc84349cf8p-4, 0x1.c08c429c5a0dap-4, 0x1.edc195e2a24f1p-5, + -0x1.c678b4cc8c59dp-4, -0x1.d79775f02af4fp-5, 0x1.cc1f10badcf8fp-4, 0x1.c1249d41b1cffp-5, + -0x1.d17e77d7e3055p-4, -0x1.aa6c80f032469p-5, 0x1.d696175086c08p-4, 0x1.9372a4fccbb1cp-5, + -0x1.db6525a903ca7p-4, -0x1.7c3a938e2baaap-5, 0x1.dfeae51afc0dcp-4, 0x1.64c7deb69c911p-5, + -0x1.e426a3b279d19p-4, -0x1.4d1e236747a18p-5, 0x1.e817b8b5e2e5fp-4, 0x1.35410b145d685p-5, + -0x1.ebbd8bd7f3b6ep-4, -0x1.1d344433692e7p-5, 0x1.ef1789843f75ap-4, 0x1.04fb80821570ap-5, + -0x1.f22530e9133e0p-4, -0x1.d934fda584d77p-6, 0x1.f4e6038b09b32p-4, 0x1.a82a029278d12p-6, + -0x1.f7599a576a548p-4, -0x1.76dd9dddd2842p-6, 0x1.f97f92daefcd4p-4, 0x1.45576b2b66a22p-6, + -0x1.fb5798c69b16ep-4, -0x1.139f0b58668cap-6, 0x1.fce15ed8a65a8p-4, 0x1.c3785bd3a6281p-7, + -0x1.fe1caf142bcd6p-4, -0x1.5f6cfef4b1332p-7, 0x1.ff09560835adbp-4, 0x1.f656e86de871bp-8, + -0x1.ffa72e2bf41c2p-4, -0x1.2d86585ab6f74p-8, 0x1.fff6227275962p-4, 0x1.921d212fd724bp-10, + 0x1.fff622a1cf02ep-4, -0x1.921d24f54d70ap-10, 0x1.ffa72deecd83fp-4, -0x1.2d86560cd9406p-8, + 0x1.ff095521a4708p-4, -0x1.f656e965f7e2bp-8, 0x1.fe1cb12ca7cdbp-4, -0x1.5f6cffc9c44c7p-7, + 0x1.fce1607a6a8ccp-4, -0x1.c3785c138dba5p-7, 0x1.fb5797b6af9fdp-4, -0x1.139f0bfeb1b90p-6, + 0x1.f97f90f2c8645p-4, -0x1.45576c601ad74p-6, 0x1.f75999cbeca33p-4, -0x1.76dd9eb62d048p-6, + 0x1.f4e60275ba0a9p-4, -0x1.a82a015ebd9ebp-6, 0x1.f2252ebaeea9dp-4, -0x1.d934fe33a7bf8p-6, + 0x1.ef178a746476ap-4, -0x1.04fb80018cfaep-5, 0x1.ebbd8cda7cc3cp-4, -0x1.1d34441bf9309p-5, + 0x1.e817baa9f50a1p-4, -0x1.35410bde8f97dp-5, 0x1.e426a40c67850p-4, -0x1.4d1e2316a7a80p-5, + 0x1.dfeae6a1c06bbp-4, -0x1.64c7dd9701d7fp-5, 0x1.db6525fe9647cp-4, -0x1.7c3a93a7f9f96p-5, + 0x1.d69618a55419cp-4, -0x1.9372a58cb8238p-5, 0x1.d17e785ae9ef6p-4, -0x1.aa6c8057d470fp-5, + 0x1.cc1f0efb07310p-4, -0x1.c1249e9185460p-5, 0x1.c678b4c4cc9a9p-4, -0x1.d79775a51e65bp-5, + 0x1.c08c416738a92p-4, -0x1.edc1963a29ef4p-5, 0x1.ba5aa615521bap-4, -0x1.01cfc755eed5ap-4, + 0x1.b3e4d360429bap-4, -0x1.0c970443581a9p-4, 0x1.ad2bcb1e47669p-4, -0x1.1734d58da75ddp-4, + 0x1.a630913d99163p-4, -0x1.21a799a74d36fp-4, 0x1.9ef43dc1a6151p-4, -0x1.2bedb2140366cp-4, + 0x1.9777f040bb3cdp-4, -0x1.36058c7de8cc0p-4, 0x1.8fbcc91571415p-4, -0x1.3fed958027f1ep-4, + 0x1.87c400b81467ep-4, -0x1.49a449f961d8bp-4, 0x1.7f8ecdb338ff1p-4, -0x1.532829ed035b3p-4, + 0x1.771e76504b726p-4, -0x1.5c77bbe54fa76p-4, 0x1.6e744744ba091p-4, -0x1.659191eab526ep-4, + 0x1.659191eab526ep-4, -0x1.6e744744ba091p-4, 0x1.5c77bbe54fa76p-4, -0x1.771e76504b726p-4, + 0x1.532829ed035b3p-4, -0x1.7f8ecdb338ff1p-4, 0x1.49a449f961d8bp-4, -0x1.87c400b81467ep-4, + 0x1.3fed958027f1ep-4, -0x1.8fbcc91571415p-4, 0x1.36058c7de8cc0p-4, -0x1.9777f040bb3cdp-4, + 0x1.2bedb2140366cp-4, -0x1.9ef43dc1a6151p-4, 0x1.21a799a74d36fp-4, -0x1.a630913d99163p-4, + 0x1.1734d58da75ddp-4, -0x1.ad2bcb1e47669p-4, 0x1.0c970443581a9p-4, -0x1.b3e4d360429bap-4, + 0x1.01cfc755eed5ap-4, -0x1.ba5aa615521bap-4, 0x1.edc1963a29ef4p-5, -0x1.c08c416738a92p-4, + 0x1.d79775a51e65bp-5, -0x1.c678b4c4cc9a9p-4, 0x1.c1249e9185460p-5, -0x1.cc1f0efb07310p-4, + 0x1.aa6c8057d470fp-5, -0x1.d17e785ae9ef6p-4, 0x1.9372a58cb8238p-5, -0x1.d69618a55419cp-4, + 0x1.7c3a93a7f9f96p-5, -0x1.db6525fe9647cp-4, 0x1.64c7dd9701d7fp-5, -0x1.dfeae6a1c06bbp-4, + 0x1.4d1e2316a7a80p-5, -0x1.e426a40c67850p-4, 0x1.35410bde8f97dp-5, -0x1.e817baa9f50a1p-4, + 0x1.1d34441bf9309p-5, -0x1.ebbd8cda7cc3cp-4, 0x1.04fb80018cfaep-5, -0x1.ef178a746476ap-4, + 0x1.d934fe33a7bf8p-6, -0x1.f2252ebaeea9dp-4, 0x1.a82a015ebd9ebp-6, -0x1.f4e60275ba0a9p-4, + 0x1.76dd9eb62d048p-6, -0x1.f75999cbeca33p-4, 0x1.45576c601ad74p-6, -0x1.f97f90f2c8645p-4, + 0x1.139f0bfeb1b90p-6, -0x1.fb5797b6af9fdp-4, 0x1.c3785c138dba5p-7, -0x1.fce1607a6a8ccp-4, + 0x1.5f6cffc9c44c7p-7, -0x1.fe1cb12ca7cdbp-4, 0x1.f656e965f7e2bp-8, -0x1.ff095521a4708p-4, + 0x1.2d86560cd9406p-8, -0x1.ffa72deecd83bp-4, 0x1.921d24f54d70ap-10, -0x1.fff622a1cf02ap-4, + -0x1.15f984c94985ep-6, 0x1.e5cb5f0b50e61p-4, -0x1.c266eb41a9c35p-6, -0x1.df915bb173625p-4, + -0x1.178995698f818p-6, -0x1.6fb7511a4ebadp-6, 0x1.339aa570e9808p-9, -0x1.03e75f3bc6d85p-5, + -0x1.9f516c172687ep-6, -0x1.e4ca2bfcaa0dbp-3, 0x1.15a93e0bcd9fap-6, -0x1.11118a39c9113p-4, + -0x1.8f1f259640bd4p-6, -0x1.2284eddf82295p-4, -0x1.0a03b32235288p-6, 0x1.03f57e57d5c63p-5, + -0x1.d783f995c0337p-9, 0x1.be1a177e17dddp-4, -0x1.c2be478bc5ed0p-5, -0x1.b5593e62bf8e3p-3, + -0x1.961bb40197925p-6, -0x1.97450dc77c795p-5, -0x1.4115d5316a4dbp-5, 0x1.0f726e79808eap-3, + -0x1.a85525276610ep-5, -0x1.13f94fc5a80c5p-2, -0x1.a3fd43c97d16ep-8, -0x1.dba4574053d38p-5, + 0x1.c8024b24b8356p-6, 0x1.c738a1c643cffp-4, -0x1.d77117eb29140p-8, -0x1.05b67bbcc37ecp-6, + -0x1.1595c4f54a628p-4, -0x1.27c144f1bfccep-3, 0x1.a15c7dab79ed2p-8, -0x1.68f41d3bd7bd0p-4, + -0x1.4aee975ffe89bp-5, -0x1.1cd95efd86a03p-4, -0x1.12c1a4929d46ap-7, -0x1.6119f732ba3f7p-3, + -0x1.2d29e660efe9dp-7, 0x1.ae0fb79843e4fp-7, -0x1.97d881752bc68p-4, -0x1.2d54e50fdf1fbp-3, + -0x1.11df00a56440cp-4, 0x1.dd3f04ae3e3aap-4, -0x1.aeec46209fc5ap-6, 0x1.2a1cd343911f0p-4, + -0x1.f97ea120df773p-6, -0x1.d7a0ec5c86c0ap-4, 0x1.36625754ed8cep-6, -0x1.93d4efd7ea3e1p-6, + -0x1.bdefdacb263afp-8, 0x1.fc37617bfe704p-6, 0x1.e84fb36e459e5p-6, 0x1.4f136b62ab205p-4, + 0x1.0e9de085f8f18p-3, 0x1.52e97d2c3d3d9p-7, 0x1.fb8617e0e847ep-4, 0x1.1fd2c88017a21p-4, + -0x1.ae7e78e5c5d07p-4, -0x1.352210328282ap-7, 0x1.466e7074dcfa1p-4, -0x1.2de95cccc36fcp-3, + 0x1.2de95cccc36fcp-3, -0x1.466e7074dcfa1p-4, 0x1.352210328282ap-7, 0x1.ae7e78e5c5d07p-4, + -0x1.1fd2c88017a21p-4, -0x1.fb8617e0e847ep-4, -0x1.52e97d2c3d3d9p-7, -0x1.0e9de085f8f18p-3, + -0x1.4f136b62ab205p-4, -0x1.e84fb36e459e5p-6, -0x1.fc37617bfe704p-6, 0x1.bdefdacb263afp-8, + 0x1.93d4efd7ea3e1p-6, -0x1.36625754ed8cep-6, 0x1.d7a0ec5c86c0ap-4, 0x1.f97ea120df773p-6, + -0x1.2a1cd343911f0p-4, 0x1.aeec46209fc5ap-6, -0x1.dd3f04ae3e3aap-4, 0x1.11df00a56440cp-4, + 0x1.2d54e50fdf1fbp-3, 0x1.97d881752bc68p-4, -0x1.ae0fb79843e4fp-7, 0x1.2d29e660efe9dp-7, + 0x1.6119f732ba3f7p-3, 0x1.12c1a4929d46ap-7, 0x1.1cd95efd86a03p-4, 0x1.4aee975ffe89bp-5, + 0x1.68f41d3bd7bd0p-4, -0x1.a15c7dab79ed2p-8, 0x1.27c144f1bfccep-3, 0x1.1595c4f54a628p-4, + 0x1.05b67bbcc37ecp-6, 0x1.d77117eb29140p-8, -0x1.c738a1c643cffp-4, -0x1.c8024b24b8356p-6, + 0x1.dba4574053d38p-5, 0x1.a3fd43c97d16ep-8, 0x1.13f94fc5a80c5p-2, 0x1.a85525276610ep-5, + -0x1.0f726e79808eap-3, 0x1.4115d5316a4dbp-5, 0x1.97450dc77c795p-5, 0x1.961bb40197925p-6, + 0x1.b5593e62bf8e3p-3, 0x1.c2be478bc5ed0p-5, -0x1.be1a177e17dddp-4, 0x1.d783f995c0337p-9, + -0x1.03f57e57d5c63p-5, 0x1.0a03b32235288p-6, 0x1.2284eddf82295p-4, 0x1.8f1f259640bd4p-6, + 0x1.11118a39c9113p-4, -0x1.15a93e0bcd9fap-6, 0x1.e4ca2bfcaa0dbp-3, 0x1.9f516c172687ep-6, + 0x1.03e75f3bc6d85p-5, -0x1.339aa570e9808p-9, 0x1.6fb7511a4eb91p-6, 0x1.178995698f812p-6, + 0x1.df915bb173619p-4, 0x1.c266eb4219b9cp-6, -0x1.e5cb5e3e4a7d5p-4, 0x1.15f9847cb94cdp-6, + 0x1.fbc9ccc013e60p-4, 0x1.5ffdd3eeaa4d8p-14, 0x1.a1950e48c04e6p-5, -0x1.a7a4db4112cd3p-11, + -0x1.4e1007cf7198dp-4, -0x1.125b5f882a425p-6, 0x1.cba7301f6b8a4p-4, -0x1.8689e58c2002cp-7, + 0x1.ff82916c2358bp-4, -0x1.1f0bdda553a92p-6, 0x1.a85be86a82376p-5, -0x1.841139853cd34p-8, + -0x1.92cd4edff2812p-3, 0x1.ff6c2047fecbcp-8, 0x1.a807102cb9f19p-4, -0x1.5e86f96c95109p-6, + -0x1.f7fce4042bfb8p-3, 0x1.0ac5317b231a3p-5, -0x1.7f75b1afc0d93p-3, -0x1.564f45920508ep-5, + -0x1.6a4bce0bbf90fp-9, 0x1.2404aa334aae5p-7, 0x1.b18a79d42d490p-3, 0x1.ce68676181e30p-6, + 0x1.07b0bfd5c2848p-4, 0x1.8abe6c7339980p-5, 0x1.8ed9522e8c34cp-4, 0x1.01adc70762f0fp-5, + 0x1.a3488b987cdbcp-5, 0x1.5f474a14e0b9dp-5, 0x1.305680a104348p-5, -0x1.acbdcbb13ef86p-8, + 0x1.7507dd2553f16p-3, 0x1.73605cd9e9af3p-6, -0x1.16cd75042a37cp-6, 0x1.62f7019167f96p-4, + -0x1.396177e070cf9p-3, -0x1.5df1c4a4c8102p-4, -0x1.a2ec5bd2f5842p-7, -0x1.57f779768ea98p-7, + 0x1.e14fa3f155110p-5, 0x1.860b6bd24e812p-6, -0x1.4051f90db54ffp-4, 0x1.31701c789b928p-5, + -0x1.069523f884444p-3, -0x1.0d20d41ef2ca6p-4, 0x1.7cfce6269fe7cp-6, 0x1.66a7ae6759551p-6, + -0x1.fd16bf7ccadcfp-7, 0x1.8a47c1fca64a2p-6, -0x1.063e7dedaa9f6p-6, -0x1.e61dfbcfde683p-6, + 0x1.86c6d734ba378p-5, 0x1.c90463a0c8a85p-5, -0x1.8301923e9832ap-3, 0x1.e0f8e2c96e39fp-4, + 0x1.61bcaab715069p-3, 0x1.09363e10d0e6cp-7, -0x1.dfa690761e79fp-4, 0x1.f93916181df66p-11, + 0x1.77b21fda49f05p-5, -0x1.5aa8ffa0b0056p-4, 0x1.339fae212695ap-5, 0x1.9923cd2f88733p-4, + -0x1.9923cd2f88733p-4, -0x1.339fae212695ap-5, 0x1.5aa8ffa0b0056p-4, -0x1.77b21fda49f05p-5, + -0x1.f93916181df66p-11, 0x1.dfa690761e79fp-4, -0x1.09363e10d0e6cp-7, -0x1.61bcaab715069p-3, + -0x1.e0f8e2c96e39fp-4, 0x1.8301923e9832ap-3, -0x1.c90463a0c8a85p-5, -0x1.86c6d734ba378p-5, + 0x1.e61dfbcfde683p-6, 0x1.063e7dedaa9f6p-6, -0x1.8a47c1fca64a2p-6, 0x1.fd16bf7ccadcfp-7, + -0x1.66a7ae6759551p-6, -0x1.7cfce6269fe7cp-6, 0x1.0d20d41ef2ca6p-4, 0x1.069523f884444p-3, + -0x1.31701c789b928p-5, 0x1.4051f90db54ffp-4, -0x1.860b6bd24e812p-6, -0x1.e14fa3f155110p-5, + 0x1.57f779768ea98p-7, 0x1.a2ec5bd2f5842p-7, 0x1.5df1c4a4c8102p-4, 0x1.396177e070cf9p-3, + -0x1.62f7019167f96p-4, 0x1.16cd75042a37cp-6, -0x1.73605cd9e9af3p-6, -0x1.7507dd2553f16p-3, + 0x1.acbdcbb13ef86p-8, -0x1.305680a104348p-5, -0x1.5f474a14e0b9dp-5, -0x1.a3488b987cdbcp-5, + -0x1.01adc70762f0fp-5, -0x1.8ed9522e8c34cp-4, -0x1.8abe6c7339980p-5, -0x1.07b0bfd5c2848p-4, + -0x1.ce68676181e30p-6, -0x1.b18a79d42d490p-3, -0x1.2404aa334aae5p-7, 0x1.6a4bce0bbf90fp-9, + 0x1.564f45920508ep-5, 0x1.7f75b1afc0d93p-3, -0x1.0ac5317b231a3p-5, 0x1.f7fce4042bfb8p-3, + 0x1.5e86f96c95109p-6, -0x1.a807102cb9f19p-4, -0x1.ff6c2047fecbcp-8, 0x1.92cd4edff2812p-3, + 0x1.841139853cd34p-8, -0x1.a85be86a82376p-5, 0x1.1f0bdda553a92p-6, -0x1.ff82916c2358bp-4, + 0x1.8689e58c2002cp-7, -0x1.cba7301f6b8a4p-4, 0x1.125b5f882a423p-6, 0x1.4e1007cf71985p-4, + 0x1.a7a4db4112b80p-11, -0x1.a1950ec2163efp-5, -0x1.5ffd710e43bc0p-14, -0x1.fbc9cca33fe50p-4, + -0x1.2d86590a69425p-8, -0x1.ffa72ebe0ec6ap-4, 0x1.c378649870804p-7, 0x1.fce15cc2dc83bp-4, + -0x1.76dd9bccd9107p-6, -0x1.f7599a3875569p-4, 0x1.04fb822a59fd5p-5, 0x1.ef17894c953b2p-4, + -0x1.4d1e242491020p-5, -0x1.e426a432aa9ffp-4, 0x1.9372a9743f41fp-5, 0x1.d69617d27cdfep-4, + -0x1.d7977550bfcc5p-5, -0x1.c678b32f617dap-4, 0x1.0c970251a7963p-4, 0x1.b3e4d72bb20c3p-4, + -0x1.2bedafdd1f852p-4, -0x1.9ef43e324a77dp-4, 0x1.49a4496c1f51fp-4, 0x1.87c4010741c6bp-4, + -0x1.65919252d019dp-4, -0x1.6e744931ed167p-4, 0x1.7f8ece76fb3eap-4, 0x1.5328273edc92fp-4, + -0x1.9777f0897904dp-4, -0x1.36058b179e084p-4, 0x1.ad2bcab0d11f1p-4, 0x1.1734d45b5d9aep-4, + -0x1.c08c429cf4855p-4, -0x1.edc1973ac315ap-5, 0x1.d17e7685126ebp-4, 0x1.aa6c7f626fde6p-5, + -0x1.dfeae57327c76p-4, -0x1.64c7dd293023bp-5, 0x1.ebbd8ae848e54p-4, 0x1.1d34440effe98p-5, + -0x1.f4e602927f016p-4, -0x1.a82a04a1eb1dep-6, 0x1.fb579824dd1bcp-4, 0x1.139f11a7a7b06p-6, + -0x1.ff0955c18e0aep-4, -0x1.f656ceddf2af9p-8, 0x1.fff6224de698cp-4, -0x1.921d3dd75bfedp-10, + -0x1.fe1cb10ce83fep-4, 0x1.5f6cef548088ep-7, 0x1.f97f9213376e1p-4, -0x1.455768426c92fp-6, + -0x1.f2252b34d285fp-4, 0x1.d934fcb82430fp-6, 0x1.e817ba613469fp-4, -0x1.35410b328b424p-5, + -0x1.db6529049f2e0p-4, 0x1.7c3a91f9bf86ep-5, 0x1.cc1f110666b2ep-4, -0x1.c1249db8eb68dp-5, + -0x1.ba5aa4e2c9d82p-4, 0x1.01cfca8c5f3d8p-4, 0x1.a630940951021p-4, -0x1.21a799908c231p-4, + -0x1.8fbccb1e577b5p-4, 0x1.3fed961b540ccp-4, 0x1.771e76df0ce8cp-4, -0x1.5c77bd39469a8p-4, + -0x1.5c77bd39469a8p-4, 0x1.771e76df0ce8cp-4, 0x1.3fed961b540ccp-4, -0x1.8fbccb1e577b5p-4, + -0x1.21a799908c231p-4, 0x1.a630940951021p-4, 0x1.01cfca8c5f3d8p-4, -0x1.ba5aa4e2c9d82p-4, + -0x1.c1249db8eb68dp-5, 0x1.cc1f110666b2ep-4, 0x1.7c3a91f9bf86ep-5, -0x1.db6529049f2e0p-4, + -0x1.35410b328b424p-5, 0x1.e817ba613469fp-4, 0x1.d934fcb82430fp-6, -0x1.f2252b34d285fp-4, + -0x1.455768426c92fp-6, 0x1.f97f9213376e1p-4, 0x1.5f6cef548088ep-7, -0x1.fe1cb10ce83fep-4, + -0x1.921d3dd75bfedp-10, 0x1.fff6224de698cp-4, -0x1.f656ceddf2af9p-8, -0x1.ff0955c18e0aep-4, + 0x1.139f11a7a7b06p-6, 0x1.fb579824dd1bcp-4, -0x1.a82a04a1eb1dep-6, -0x1.f4e602927f016p-4, + 0x1.1d34440effe98p-5, 0x1.ebbd8ae848e54p-4, -0x1.64c7dd293023bp-5, -0x1.dfeae57327c76p-4, + 0x1.aa6c7f626fde6p-5, 0x1.d17e7685126ebp-4, -0x1.edc1973ac315ap-5, -0x1.c08c429cf4855p-4, + 0x1.1734d45b5d9aep-4, 0x1.ad2bcab0d11f1p-4, -0x1.36058b179e084p-4, -0x1.9777f0897904dp-4, + 0x1.5328273edc92fp-4, 0x1.7f8ece76fb3eap-4, -0x1.6e744931ed167p-4, -0x1.65919252d019dp-4, + 0x1.87c4010741c6bp-4, 0x1.49a4496c1f51fp-4, -0x1.9ef43e324a77dp-4, -0x1.2bedafdd1f852p-4, + 0x1.b3e4d72bb20c3p-4, 0x1.0c970251a7963p-4, -0x1.c678b32f617dap-4, -0x1.d7977550bfcc5p-5, + 0x1.d69617d27cdfep-4, 0x1.9372a9743f41fp-5, -0x1.e426a432aa9ffp-4, -0x1.4d1e242491020p-5, + 0x1.ef17894c953b2p-4, 0x1.04fb822a59fd5p-5, -0x1.f7599a3875569p-4, -0x1.76dd9bccd9107p-6, + 0x1.fce15cc2dc83bp-4, 0x1.c378649870804p-7, -0x1.ffa72ebe0ec7ep-4, -0x1.2d86590a6941cp-8, + 0x1.ffa72edb2011cp-4, -0x1.2d865984f93a7p-8, 0x1.fce15cb6d5936p-4, -0x1.c37863ea29b4dp-7, + 0x1.f7599a69f4dafp-4, -0x1.76dd9ce987296p-6, 0x1.ef17894b41400p-4, -0x1.04fb81b8c7ce3p-5, + 0x1.e426a421b4658p-4, -0x1.4d1e2441b1901p-5, 0x1.d69618e744955p-4, -0x1.9372aaf699421p-5, + 0x1.c678b4c888a3ep-4, -0x1.d7977416f41f2p-5, 0x1.b3e4d5962d4b1p-4, -0x1.0c97021e32e19p-4, + 0x1.9ef43deb70e29p-4, -0x1.2bedb08c24872p-4, 0x1.87c4004ee63b9p-4, -0x1.49a44a290abd8p-4, + 0x1.6e7447d392b63p-4, -0x1.65919274a5978p-4, 0x1.5328283a97c71p-4, -0x1.7f8ecdc914efep-4, + 0x1.36058ab0deed0p-4, -0x1.9777f099b99a3p-4, 0x1.1734d3e50cbcbp-4, -0x1.ad2bc97784ab2p-4, + 0x1.edc195a332960p-5, -0x1.c08c4261e7e59p-4, 0x1.aa6c7fc58433bp-5, -0x1.d17e76ac153a6p-4, + 0x1.64c7dec1ff52bp-5, -0x1.dfeae6660458ep-4, 0x1.1d34443ffb6c9p-5, -0x1.ebbd8b13ac2c9p-4, + 0x1.a82a03e4ef056p-6, -0x1.f4e60272376bfp-4, 0x1.139f125557fd1p-6, -0x1.fb5798913fd3cp-4, + 0x1.f656cf725cfa5p-8, -0x1.ff09564a888dep-4, -0x1.921d3c3d5f006p-10, -0x1.fff6221012bfbp-4, + -0x1.5f6cf08a90168p-7, -0x1.fe1cb291efa59p-4, -0x1.455767ce21620p-6, -0x1.f97f925d63daep-4, + -0x1.d934fd8168f52p-6, -0x1.f2252cacf6e93p-4, -0x1.35410c361f8a2p-5, -0x1.e817b9e2882a6p-4, + -0x1.7c3a92173846dp-5, -0x1.db6527f8c6e1bp-4, -0x1.c1249db9b5a95p-5, -0x1.cc1f0fb1fbaa3p-4, + -0x1.01cfca2735726p-4, -0x1.ba5aa4c54c678p-4, -0x1.21a79a2887bf9p-4, -0x1.a630943908cc4p-4, + -0x1.3fed963022ffap-4, -0x1.8fbcca5ac763ap-4, -0x1.5c77bd06bc9c0p-4, -0x1.771e759817d3ep-4, + -0x1.771e759817d3ep-4, -0x1.5c77bd06bc9c0p-4, -0x1.8fbcca5ac763ap-4, -0x1.3fed963022ffap-4, + -0x1.a630943908cc4p-4, -0x1.21a79a2887bf9p-4, -0x1.ba5aa4c54c678p-4, -0x1.01cfca2735726p-4, + -0x1.cc1f0fb1fbaa3p-4, -0x1.c1249db9b5a95p-5, -0x1.db6527f8c6e1bp-4, -0x1.7c3a92173846dp-5, + -0x1.e817b9e2882a6p-4, -0x1.35410c361f8a2p-5, -0x1.f2252cacf6e93p-4, -0x1.d934fd8168f52p-6, + -0x1.f97f925d63daep-4, -0x1.455767ce21620p-6, -0x1.fe1cb291efa59p-4, -0x1.5f6cf08a90168p-7, + -0x1.fff6221012bfbp-4, -0x1.921d3c3d5f006p-10, -0x1.ff09564a888dep-4, 0x1.f656cf725cfa5p-8, + -0x1.fb5798913fd3cp-4, 0x1.139f125557fd1p-6, -0x1.f4e60272376bfp-4, 0x1.a82a03e4ef056p-6, + -0x1.ebbd8b13ac2c9p-4, 0x1.1d34443ffb6c9p-5, -0x1.dfeae6660458ep-4, 0x1.64c7dec1ff52bp-5, + -0x1.d17e76ac153a6p-4, 0x1.aa6c7fc58433bp-5, -0x1.c08c4261e7e59p-4, 0x1.edc195a332960p-5, + -0x1.ad2bc97784ab2p-4, 0x1.1734d3e50cbcbp-4, -0x1.9777f099b99a3p-4, 0x1.36058ab0deed0p-4, + -0x1.7f8ecdc914efep-4, 0x1.5328283a97c71p-4, -0x1.65919274a5978p-4, 0x1.6e7447d392b63p-4, + -0x1.49a44a290abd8p-4, 0x1.87c4004ee63b9p-4, -0x1.2bedb08c24872p-4, 0x1.9ef43deb70e29p-4, + -0x1.0c97021e32e19p-4, 0x1.b3e4d5962d4b1p-4, -0x1.d7977416f41f2p-5, 0x1.c678b4c888a3ep-4, + -0x1.9372aaf699421p-5, 0x1.d69618e744955p-4, -0x1.4d1e2441b1901p-5, 0x1.e426a421b4658p-4, + -0x1.04fb81b8c7ce3p-5, 0x1.ef17894b41400p-4, -0x1.76dd9ce987296p-6, 0x1.f7599a69f4dafp-4, + -0x1.c37863ea29b4dp-7, 0x1.fce15cb6d5936p-4, -0x1.2d865984f93a6p-8, 0x1.ffa72edb200ecp-4, + 0x1.e6cc23b25ca7ap-5, -0x1.18718249c08a9p-7, -0x1.61f11f7ce78a4p-3, -0x1.3ef968f892f2ap-5, + -0x1.ad72e53dadcb1p-4, 0x1.28500137fe0dbp-5, 0x1.5c6711d2e8c23p-5, -0x1.b1ad7bf5c3f60p-6, + 0x1.726af2b3a84ccp-6, 0x1.2155cddd48c14p-5, -0x1.45e3679a03397p-3, 0x1.e17621e58f012p-6, + -0x1.098cd2835cc16p-3, -0x1.2fd7ed4409ecdp-4, 0x1.eebcef523d363p-5, 0x1.7c0fcbb38c1dfp-5, + -0x1.960979b1f470fp-4, 0x1.3040f74c3356fp-8, -0x1.6d0485a9b2179p-3, -0x1.7e56ae8943807p-4, + 0x1.a5f64b409ae0ap-8, -0x1.0392406f1a4f2p-4, -0x1.28f3b11837302p-8, -0x1.3fa9e2de27b69p-5, + -0x1.4a8685c0165efp-8, -0x1.b84f1fd330254p-3, 0x1.24b91cc666bebp-6, -0x1.4abf581c331ddp-5, + -0x1.21e5229ded2c2p-8, -0x1.15621fa80e232p-2, -0x1.0f007ade42ba4p-7, -0x1.54f7b4916c1d7p-6, + 0x1.0dba84f101437p-5, -0x1.e7b2a081e3052p-4, -0x1.b097cc0a954f6p-7, 0x1.f17b714d8323dp-4, + 0x1.f6698662a8abap-6, 0x1.d536620c13312p-4, 0x1.939c18b883dfdp-8, -0x1.371c051259d37p-4, + -0x1.2030871bd8e33p-8, -0x1.0f6b8022844ffp-2, 0x1.0ed67c2e5589bp-8, 0x1.72dcf892887eap-4, + -0x1.98fd8ea2dc5bdp-9, -0x1.4bd3d9a3b2b55p-5, 0x1.89add74368215p-7, 0x1.feaed34d0ba8dp-4, + -0x1.d9189486fa4f8p-6, -0x1.65a17bd2dc21cp-4, -0x1.8c96e8e2128c5p-6, 0x1.b73976d19ee41p-4, + 0x1.f0d141b485faep-5, 0x1.a473ceefaee40p-5, -0x1.9a243e162173ap-4, 0x1.233a849fcf1f7p-13, + 0x1.32513fe0934b9p-6, 0x1.e56e16d0469f5p-4, 0x1.f2b4665ffc34dp-7, -0x1.557bdedcf0ddep-4, + -0x1.aee7b5dfcdcfep-9, 0x1.bcc21f8f539a1p-6, -0x1.843927076f393p-4, 0x1.7250f1dc84a8fp-5, + 0x1.7250f1dc84a8fp-5, -0x1.843927076f393p-4, 0x1.bcc21f8f539a1p-6, -0x1.aee7b5dfcdcfep-9, + -0x1.557bdedcf0ddep-4, 0x1.f2b4665ffc34dp-7, 0x1.e56e16d0469f5p-4, 0x1.32513fe0934b9p-6, + 0x1.233a849fcf1f7p-13, -0x1.9a243e162173ap-4, 0x1.a473ceefaee40p-5, 0x1.f0d141b485faep-5, + 0x1.b73976d19ee41p-4, -0x1.8c96e8e2128c5p-6, -0x1.65a17bd2dc21cp-4, -0x1.d9189486fa4f8p-6, + 0x1.feaed34d0ba8dp-4, 0x1.89add74368215p-7, -0x1.4bd3d9a3b2b55p-5, -0x1.98fd8ea2dc5bdp-9, + 0x1.72dcf892887eap-4, 0x1.0ed67c2e5589bp-8, -0x1.0f6b8022844ffp-2, -0x1.2030871bd8e33p-8, + -0x1.371c051259d37p-4, 0x1.939c18b883dfdp-8, 0x1.d536620c13312p-4, 0x1.f6698662a8abap-6, + 0x1.f17b714d8323dp-4, -0x1.b097cc0a954f6p-7, -0x1.e7b2a081e3052p-4, 0x1.0dba84f101437p-5, + -0x1.54f7b4916c1d7p-6, -0x1.0f007ade42ba4p-7, -0x1.15621fa80e232p-2, -0x1.21e5229ded2c2p-8, + -0x1.4abf581c331ddp-5, 0x1.24b91cc666bebp-6, -0x1.b84f1fd330254p-3, -0x1.4a8685c0165efp-8, + -0x1.3fa9e2de27b69p-5, -0x1.28f3b11837302p-8, -0x1.0392406f1a4f2p-4, 0x1.a5f64b409ae0ap-8, + -0x1.7e56ae8943807p-4, -0x1.6d0485a9b2179p-3, 0x1.3040f74c3356fp-8, -0x1.960979b1f470fp-4, + 0x1.7c0fcbb38c1dfp-5, 0x1.eebcef523d363p-5, -0x1.2fd7ed4409ecdp-4, -0x1.098cd2835cc16p-3, + 0x1.e17621e58f012p-6, -0x1.45e3679a03397p-3, 0x1.2155cddd48c14p-5, 0x1.726af2b3a84ccp-6, + -0x1.b1ad7bf5c3f60p-6, 0x1.5c6711d2e8c2dp-5, 0x1.28500137fe0d7p-5, -0x1.ad72e53dadcadp-4, + -0x1.3ef968f892f2ap-5, -0x1.61f11f7ce78a9p-3, -0x1.1871824f59f48p-7, 0x1.e6cc21c5073d7p-5, + 0x1.3ec984185cf5ep-7, 0x1.d6b845588e9e1p-3, -0x1.7f7a1adeff943p-8, -0x1.6818358e2447ep-6, + -0x1.749483b6e156dp-6, -0x1.978f9baf99137p-5, 0x1.f9d47d305b3c8p-7, 0x1.23132548ebed7p-4, + 0x1.00f6d209e8af5p-6, -0x1.3dd25b35e1dbap-4, 0x1.5198d998343c7p-5, 0x1.6250fc13d6fa5p-5, + 0x1.9420ccb62d4acp-5, -0x1.acd219b27da48p-3, 0x1.dd5c4394c009ep-9, -0x1.11d9ee5850b8ap-4, + -0x1.8de45c77525b6p-4, 0x1.6dd0af19eb47fp-5, 0x1.4bf00078af00dp-3, -0x1.005095d9fe339p-3, + -0x1.12864bc10b691p-4, 0x1.2bb9456611d85p-3, -0x1.1883f51366a3dp-8, 0x1.75c9d75ed7726p-4, + 0x1.03918baf99d85p-6, 0x1.78216fa2bc3adp-4, -0x1.ee67b109dc949p-6, 0x1.d1da56b4685b6p-5, + -0x1.f5696fab2deaep-5, 0x1.ee2c687e6c9e6p-8, 0x1.e86a21b60a4b3p-4, 0x1.e25014f27b56fp-5, + -0x1.39d7ca9db508dp-2, -0x1.f6d01ee6103c9p-4, -0x1.4860f20ccc0a2p-4, 0x1.56b11c35d1cdcp-5, + 0x1.1ca6003e1a7e5p-4, -0x1.3d95cf5b3dd84p-8, -0x1.760a377c8000cp-6, -0x1.3be3a8ce1f7bap-7, + 0x1.8fdfc1fb57e45p-5, -0x1.db60b20a37985p-6, 0x1.4011d86151a3cp-5, -0x1.85c0aad52d819p-8, + -0x1.fc46786107b78p-8, 0x1.0907d023373bep-6, -0x1.8b2db8223f6bbp-4, 0x1.fcf74cbb053fbp-7, + -0x1.2014b5555fbb0p-7, -0x1.c9069c232054ep-6, 0x1.24bdfc8c1d17cp-4, -0x1.656a0f0e50feap-4, + 0x1.6aa58c670f1a3p-3, 0x1.6d7f31e6c1b90p-6, -0x1.85d39f406c7dep-4, -0x1.a7715f36d67e2p-4, + 0x1.4b6ae742a2692p-4, -0x1.ddd9ce0a4586dp-5, 0x1.706b6a217d71fp-6, -0x1.7ce42dacd800fp-4, + 0x1.b843eb71e5736p-4, 0x1.0028b6c914da1p-5, -0x1.23c0eb405ef35p-4, 0x1.078cbb6e4cc87p-3, + 0x1.078cbb6e4cc87p-3, -0x1.23c0eb405ef35p-4, 0x1.0028b6c914da1p-5, 0x1.b843eb71e5736p-4, + -0x1.7ce42dacd800fp-4, 0x1.706b6a217d71fp-6, -0x1.ddd9ce0a4586dp-5, 0x1.4b6ae742a2692p-4, + -0x1.a7715f36d67e2p-4, -0x1.85d39f406c7dep-4, 0x1.6d7f31e6c1b90p-6, 0x1.6aa58c670f1a3p-3, + -0x1.656a0f0e50feap-4, 0x1.24bdfc8c1d17cp-4, -0x1.c9069c232054ep-6, -0x1.2014b5555fbb0p-7, + 0x1.fcf74cbb053fbp-7, -0x1.8b2db8223f6bbp-4, 0x1.0907d023373bep-6, -0x1.fc46786107b78p-8, + -0x1.85c0aad52d819p-8, 0x1.4011d86151a3cp-5, -0x1.db60b20a37985p-6, 0x1.8fdfc1fb57e45p-5, + -0x1.3be3a8ce1f7bap-7, -0x1.760a377c8000cp-6, -0x1.3d95cf5b3dd84p-8, 0x1.1ca6003e1a7e5p-4, + 0x1.56b11c35d1cdcp-5, -0x1.4860f20ccc0a2p-4, -0x1.f6d01ee6103c9p-4, -0x1.39d7ca9db508dp-2, + 0x1.e25014f27b56fp-5, 0x1.e86a21b60a4b3p-4, 0x1.ee2c687e6c9e6p-8, -0x1.f5696fab2deaep-5, + 0x1.d1da56b4685b6p-5, -0x1.ee67b109dc949p-6, 0x1.78216fa2bc3adp-4, 0x1.03918baf99d85p-6, + 0x1.75c9d75ed7726p-4, -0x1.1883f51366a3dp-8, 0x1.2bb9456611d85p-3, -0x1.12864bc10b691p-4, + -0x1.005095d9fe339p-3, 0x1.4bf00078af00dp-3, 0x1.6dd0af19eb47fp-5, -0x1.8de45c77525b6p-4, + -0x1.11d9ee5850b8ap-4, 0x1.dd5c4394c009ep-9, -0x1.acd219b27da48p-3, 0x1.9420ccb62d4acp-5, + 0x1.6250fc13d6fa5p-5, 0x1.5198d998343c7p-5, -0x1.3dd25b35e1dbap-4, 0x1.00f6d209e8af5p-6, + 0x1.23132548ebed6p-4, 0x1.f9d47d305b3cfp-7, -0x1.978f9baf9913cp-5, -0x1.749483b6e1564p-6, + -0x1.6818358e24466p-6, -0x1.7f7a1adeff8fcp-8, 0x1.d6b846c0734a5p-3, 0x1.3ec983f2a65cdp-7, + -0x1.f656e87c33651p-8, -0x1.ff0958dac7fd2p-4, 0x1.76dd9e473d80bp-6, 0x1.f759956c48702p-4, + -0x1.35410f633cbf2p-5, -0x1.e817ba4c75d41p-4, 0x1.aa6c7fc645327p-5, 0x1.d17e7665b78a4p-4, + -0x1.0c9704ad0af84p-4, -0x1.b3e4d29ef00d5p-4, 0x1.3fed93fd79774p-4, 0x1.8fbcc96d341eep-4, + -0x1.6e744621da45fp-4, -0x1.659191d397dfbp-4, 0x1.9777f1335ca00p-4, 0x1.36058c7614009p-4, + -0x1.ba5aa64822b34p-4, -0x1.01cfc81bf1d49p-4, 0x1.d69613fa38ffbp-4, 0x1.9372a828a56bap-5, + -0x1.ebbd8da303ad2p-4, -0x1.1d3444b4df059p-5, 0x1.f97f8fd51afd9p-4, 0x1.455769b92dbc6p-6, + -0x1.ffa72e5d33956p-4, -0x1.2d8654b739332p-8, 0x1.fe1caee767aafp-4, -0x1.5f6cfadc826dbp-7, + -0x1.f4e6055c2c91ap-4, 0x1.a82a03a441063p-6, 0x1.e426a4d8dffb6p-4, -0x1.4d1e2493049d1p-5, + -0x1.cc1f11759ae63p-4, 0x1.c1249e2771691p-5, 0x1.ad2bc9abc4fedp-4, -0x1.1734d6903a938p-4, + -0x1.87c3ffc4269f9p-4, 0x1.49a44b274418bp-4, 0x1.5c77ba2407735p-4, -0x1.771e770e9c567p-4, + -0x1.2bedb00f522dbp-4, 0x1.9ef43f9eca7f4p-4, 0x1.edc1957edfdc9p-5, -0x1.c08c44cdc36afp-4, + -0x1.7c3a915af510cp-5, 0x1.db6527be00cdep-4, 0x1.04fb81e5ebd87p-5, -0x1.ef178b0df0702p-4, + -0x1.139f0c1984041p-6, 0x1.fb57947e8efb2p-4, 0x1.921d3ba5a67abp-10, -0x1.fff6214ab4600p-4, + 0x1.c37859749866bp-7, 0x1.fce161be6f95fp-4, -0x1.d9350077f8598p-6, -0x1.f2252f7271bdcp-4, + 0x1.64c7dedffa7dbp-5, 0x1.dfeae5962a9cdp-4, -0x1.d79774d2d1abfp-5, -0x1.c678b3a2f4f2dp-4, + 0x1.21a79a8a81b35p-4, 0x1.a63091b5158fep-4, -0x1.53282a21f0c28p-4, -0x1.7f8ed103e1ec0p-4, + 0x1.7f8ed103e1ec0p-4, 0x1.53282a21f0c28p-4, -0x1.a63091b5158fep-4, -0x1.21a79a8a81b35p-4, + 0x1.c678b3a2f4f2dp-4, 0x1.d79774d2d1abfp-5, -0x1.dfeae5962a9cdp-4, -0x1.64c7dedffa7dbp-5, + 0x1.f2252f7271bdcp-4, 0x1.d9350077f8598p-6, -0x1.fce161be6f95fp-4, -0x1.c37859749866bp-7, + 0x1.fff6214ab4600p-4, -0x1.921d3ba5a67abp-10, -0x1.fb57947e8efb2p-4, 0x1.139f0c1984041p-6, + 0x1.ef178b0df0702p-4, -0x1.04fb81e5ebd87p-5, -0x1.db6527be00cdep-4, 0x1.7c3a915af510cp-5, + 0x1.c08c44cdc36afp-4, -0x1.edc1957edfdc9p-5, -0x1.9ef43f9eca7f4p-4, 0x1.2bedb00f522dbp-4, + 0x1.771e770e9c567p-4, -0x1.5c77ba2407735p-4, -0x1.49a44b274418bp-4, 0x1.87c3ffc4269f9p-4, + 0x1.1734d6903a938p-4, -0x1.ad2bc9abc4fedp-4, -0x1.c1249e2771691p-5, 0x1.cc1f11759ae63p-4, + 0x1.4d1e2493049d1p-5, -0x1.e426a4d8dffb6p-4, -0x1.a82a03a441063p-6, 0x1.f4e6055c2c91ap-4, + 0x1.5f6cfadc826dbp-7, -0x1.fe1caee767aafp-4, 0x1.2d8654b739332p-8, 0x1.ffa72e5d33956p-4, + -0x1.455769b92dbc6p-6, -0x1.f97f8fd51afd9p-4, 0x1.1d3444b4df059p-5, 0x1.ebbd8da303ad2p-4, + -0x1.9372a828a56bap-5, -0x1.d69613fa38ffbp-4, 0x1.01cfc81bf1d49p-4, 0x1.ba5aa64822b34p-4, + -0x1.36058c7614009p-4, -0x1.9777f1335ca00p-4, 0x1.659191d397dfbp-4, 0x1.6e744621da45fp-4, + -0x1.8fbcc96d341eep-4, -0x1.3fed93fd79774p-4, 0x1.b3e4d29ef00d5p-4, 0x1.0c9704ad0af84p-4, + -0x1.d17e7665b78a4p-4, -0x1.aa6c7fc645327p-5, 0x1.e817ba4c75d41p-4, 0x1.35410f633cbf2p-5, + -0x1.f759956c48702p-4, -0x1.76dd9e473d80bp-6, 0x1.ff0958dac7fc0p-4, 0x1.f656e87c3364dp-8, + 0x1.ff09589f2ee24p-4, -0x1.f656eb2cf8583p-8, 0x1.f75996caf2ac8p-4, -0x1.76dd9d4b8224ep-6, + 0x1.e817b9685ea97p-4, -0x1.35410ef763542p-5, 0x1.d17e7639b2dc4p-4, -0x1.aa6c805a9f9a7p-5, + 0x1.b3e4d2d5c9c4ep-4, -0x1.0c97046cc5e83p-4, 0x1.8fbccac4e5eb3p-4, -0x1.3fed9456e12f4p-4, + 0x1.6591918ea26e7p-4, -0x1.6e74460567f3bp-4, 0x1.36058c0b6ed13p-4, -0x1.9777f08ade437p-4, + 0x1.01cfc7ac569a3p-4, -0x1.ba5aa577d6ab5p-4, 0x1.9372a8b2c926ap-5, -0x1.d696137f6bbfap-4, + 0x1.1d3444a1e11a1p-5, -0x1.ebbd8cc54d63dp-4, 0x1.455768a541768p-6, -0x1.f97f913863406p-4, + 0x1.2d865420e389fp-8, -0x1.ffa72f16e1cedp-4, -0x1.5f6cf8ee58757p-7, -0x1.fe1cae67acd1bp-4, + -0x1.a82a0606f4302p-6, -0x1.f4e6042ff05f1p-4, -0x1.4d1e247dcc5f6p-5, -0x1.e426a57dd2128p-4, + -0x1.c1249f0ffea2ap-5, -0x1.cc1f10890b09bp-4, -0x1.1734d6b6050a2p-4, -0x1.ad2bc9cfd907ap-4, + -0x1.49a44a605159ep-4, -0x1.87c400c4ba846p-4, -0x1.771e771025251p-4, -0x1.5c77ba26aa546p-4, + -0x1.9ef43fc27d305p-4, -0x1.2bedb06ab398dp-4, -0x1.c08c4515591ffp-4, -0x1.edc194c08606cp-5, + -0x1.db6528478e4cbp-4, -0x1.7c3a926562694p-5, -0x1.ef178973f955ap-4, -0x1.04fb82e2ad8cep-5, + -0x1.fb57956c720ecp-4, -0x1.139f0c31b0001p-6, -0x1.fff61fe942274p-4, -0x1.921d428151937p-10, + -0x1.fce162273f24ep-4, 0x1.c3785a7fffe3ep-7, -0x1.f22530c62703ep-4, 0x1.d935005851193p-6, + -0x1.dfeae7576dfbcp-4, 0x1.64c7de88a63b6p-5, -0x1.c678b24ed3725p-4, 0x1.d79773dac8e0bp-5, + -0x1.a630922b3f066p-4, 0x1.21a79a1ceddeap-4, -0x1.7f8ed05f81cf6p-4, 0x1.53282a20b1557p-4, + -0x1.53282a20b1557p-4, 0x1.7f8ed05f81cf6p-4, -0x1.21a79a1ceddeap-4, 0x1.a630922b3f066p-4, + -0x1.d79773dac8e0bp-5, 0x1.c678b24ed3725p-4, -0x1.64c7de88a63b6p-5, 0x1.dfeae7576dfbcp-4, + -0x1.d935005851193p-6, 0x1.f22530c62703ep-4, -0x1.c3785a7fffe3ep-7, 0x1.fce162273f24ep-4, + 0x1.921d428151937p-10, 0x1.fff61fe942274p-4, 0x1.139f0c31b0001p-6, 0x1.fb57956c720ecp-4, + 0x1.04fb82e2ad8cep-5, 0x1.ef178973f955ap-4, 0x1.7c3a926562694p-5, 0x1.db6528478e4cbp-4, + 0x1.edc194c08606cp-5, 0x1.c08c4515591ffp-4, 0x1.2bedb06ab398dp-4, 0x1.9ef43fc27d305p-4, + 0x1.5c77ba26aa546p-4, 0x1.771e771025251p-4, 0x1.87c400c4ba846p-4, 0x1.49a44a605159ep-4, + 0x1.ad2bc9cfd907ap-4, 0x1.1734d6b6050a2p-4, 0x1.cc1f10890b09bp-4, 0x1.c1249f0ffea2ap-5, + 0x1.e426a57dd2128p-4, 0x1.4d1e247dcc5f6p-5, 0x1.f4e6042ff05f1p-4, 0x1.a82a0606f4302p-6, + 0x1.fe1cae67acd1bp-4, 0x1.5f6cf8ee58757p-7, 0x1.ffa72f16e1cedp-4, -0x1.2d865420e389fp-8, + 0x1.f97f913863406p-4, -0x1.455768a541768p-6, 0x1.ebbd8cc54d63dp-4, -0x1.1d3444a1e11a1p-5, + 0x1.d696137f6bbfap-4, -0x1.9372a8b2c926ap-5, 0x1.ba5aa577d6ab5p-4, -0x1.01cfc7ac569a3p-4, + 0x1.9777f08ade437p-4, -0x1.36058c0b6ed13p-4, 0x1.6e74460567f3bp-4, -0x1.6591918ea26e7p-4, + 0x1.3fed9456e12f4p-4, -0x1.8fbccac4e5eb3p-4, 0x1.0c97046cc5e83p-4, -0x1.b3e4d2d5c9c4ep-4, + 0x1.aa6c805a9f9a7p-5, -0x1.d17e7639b2dc4p-4, 0x1.35410ef763542p-5, -0x1.e817b9685ea97p-4, + 0x1.76dd9d4b8224ep-6, -0x1.f75996caf2ac8p-4, 0x1.f656eb2cf8583p-8, -0x1.ff09589f2ee1ap-4, + -0x1.127dc70323ad5p-3, -0x1.b07765a15ee98p-8, 0x1.577791dacef4fp-3, -0x1.f0a3c51bd9583p-6, + 0x1.13e77469f66a9p-4, -0x1.5736005bbaf02p-5, 0x1.f58a984d831adp-4, -0x1.b8382a577179fp-5, + 0x1.5f499eca899edp-4, -0x1.090219ff48de2p-3, -0x1.081be7460dc0bp-10, -0x1.2436ae0691f46p-3, + 0x1.41e382794245ep-4, -0x1.abbeee577328ep-5, -0x1.24db47f4c11f4p-5, -0x1.6fb0e4d2848e6p-3, + 0x1.139faa143c95bp-5, 0x1.8020fe311f5d2p-5, -0x1.446ec6d3b87bcp-5, 0x1.7f22129528cecp-5, + 0x1.2a05a71694d0dp-8, 0x1.0ce1466b45d30p-2, -0x1.368ff59ebeccep-9, 0x1.3d2ed9d84e88bp-5, + 0x1.4a47b18b78d72p-9, -0x1.648af13c523a3p-4, 0x1.80ee309f0c746p-9, 0x1.15f5684a4569fp-3, + -0x1.059fb91ffb7e3p-5, -0x1.8fbb17474e5f4p-8, 0x1.7a776997b4f71p-6, 0x1.5fd30bf9481d0p-6, + -0x1.e8014d6e5e5c7p-4, 0x1.99b446a01f976p-3, -0x1.6a6f53b254a50p-5, -0x1.3765e1438d00ap-3, + 0x1.05d7f222986d9p-4, -0x1.92f7cc5c373adp-6, -0x1.02f3d4db0487bp-8, 0x1.8858b62e1752cp-8, + -0x1.0b760aa10093fp-6, 0x1.120a065cc07dbp-4, 0x1.6510452c29ac3p-6, -0x1.4102296355854p-4, + -0x1.393336d96e893p-5, 0x1.5ce39e02df0dfp-8, -0x1.5005b33aae06dp-6, 0x1.2b654eaec8d64p-7, + 0x1.a8be019c5c13ap-5, 0x1.1b948c500b02ap-9, 0x1.36930f6d78b1ep-5, -0x1.b9dbb7841c098p-10, + -0x1.3b6bd0e8b68d1p-3, 0x1.c453352aa5cdcp-7, 0x1.ef356b2f50b2fp-3, 0x1.17448418af925p-6, + -0x1.bf056e43583cdp-7, -0x1.274a4ded3b2efp-6, -0x1.077a233939980p-6, 0x1.fac5a3c51e1cbp-6, + 0x1.c27443dc061b3p-3, -0x1.612c49036afd4p-6, 0x1.fb11b326dc408p-12, 0x1.3f495e990bae9p-5, + -0x1.3f495e990bae9p-5, -0x1.fb11b326dc408p-12, 0x1.612c49036afd4p-6, -0x1.c27443dc061b3p-3, + -0x1.fac5a3c51e1cbp-6, 0x1.077a233939980p-6, 0x1.274a4ded3b2efp-6, 0x1.bf056e43583cdp-7, + -0x1.17448418af925p-6, -0x1.ef356b2f50b2fp-3, -0x1.c453352aa5cdcp-7, 0x1.3b6bd0e8b68d1p-3, + 0x1.b9dbb7841c098p-10, -0x1.36930f6d78b1ep-5, -0x1.1b948c500b02ap-9, -0x1.a8be019c5c13ap-5, + -0x1.2b654eaec8d64p-7, 0x1.5005b33aae06dp-6, -0x1.5ce39e02df0dfp-8, 0x1.393336d96e893p-5, + 0x1.4102296355854p-4, -0x1.6510452c29ac3p-6, -0x1.120a065cc07dbp-4, 0x1.0b760aa10093fp-6, + -0x1.8858b62e1752cp-8, 0x1.02f3d4db0487bp-8, 0x1.92f7cc5c373adp-6, -0x1.05d7f222986d9p-4, + 0x1.3765e1438d00ap-3, 0x1.6a6f53b254a50p-5, -0x1.99b446a01f976p-3, 0x1.e8014d6e5e5c7p-4, + -0x1.5fd30bf9481d0p-6, -0x1.7a776997b4f71p-6, 0x1.8fbb17474e5f4p-8, 0x1.059fb91ffb7e3p-5, + -0x1.15f5684a4569fp-3, -0x1.80ee309f0c746p-9, 0x1.648af13c523a3p-4, -0x1.4a47b18b78d72p-9, + -0x1.3d2ed9d84e88bp-5, 0x1.368ff59ebeccep-9, -0x1.0ce1466b45d30p-2, -0x1.2a05a71694d0dp-8, + -0x1.7f22129528cecp-5, 0x1.446ec6d3b87bcp-5, -0x1.8020fe311f5d2p-5, -0x1.139faa143c95bp-5, + 0x1.6fb0e4d2848e6p-3, 0x1.24db47f4c11f4p-5, 0x1.abbeee577328ep-5, -0x1.41e382794245ep-4, + 0x1.2436ae0691f46p-3, 0x1.081be7460dc0bp-10, 0x1.090219ff48de2p-3, -0x1.5f499eca899edp-4, + 0x1.b8382a577179fp-5, -0x1.f58a984d831acp-4, 0x1.5736005bbaefdp-5, -0x1.13e77469f66a9p-4, + 0x1.f0a3c51bd9574p-6, -0x1.577791dacef48p-3, 0x1.b07765960e248p-8, 0x1.127dc70408f6fp-3, + -0x1.4a7cfdb65b152p-6, 0x1.4081b8d2da45cp-3, 0x1.78d7e089d7294p-9, -0x1.c18095cf221d2p-5, + 0x1.11c7849c685fcp-4, -0x1.72ff965e42baep-5, 0x1.c5c7e852d5bbbp-6, -0x1.526dc4ee12ea9p-4, + 0x1.ddaf1a5d0f6b5p-6, 0x1.6bca1894417a2p-4, 0x1.0ec66f3335651p-4, 0x1.2249cebc61c2cp-3, + -0x1.275c2f9b80ab8p-4, -0x1.3f681757ba6bcp-5, -0x1.9d0c04f6273ebp-4, -0x1.b0541db6921efp-4, + -0x1.190010a6447e3p-4, -0x1.24049d15da6a8p-5, 0x1.5e4a2a67f4121p-3, 0x1.78daf7af326e8p-10, + 0x1.d38e44e3e7f5ap-4, 0x1.b830bbc936a1fp-5, 0x1.4923008916118p-3, -0x1.3080f5c6983b8p-5, + -0x1.d7fb124f4c6c3p-5, -0x1.2519083b60772p-6, -0x1.ccdae2b81dfddp-3, 0x1.838871d9a8274p-6, + 0x1.603663513402fp-5, 0x1.a00e74186b72ep-5, -0x1.944451facaf6dp-5, 0x1.69e7d8c72636ep-5, + 0x1.65de34b153947p-5, 0x1.56fcff9c3f456p-4, 0x1.43c83040ac29dp-5, 0x1.b8be3f69c6b0fp-4, + -0x1.f25b4e7d4102cp-4, -0x1.202d0d70f0194p-6, 0x1.9491b6cdc7c1ap-12, 0x1.52822bb625691p-5, + -0x1.896d9a0dcf59dp-5, -0x1.a21a32dfe8b48p-4, -0x1.f285ef11492edp-6, 0x1.f97796454a7b7p-4, + -0x1.da65416b536fdp-5, 0x1.6f65fdaf241b7p-3, 0x1.a64c0644387c5p-6, 0x1.dc7e97e3aaf36p-3, + 0x1.816635b7f89e5p-9, 0x1.21fcb0e22a654p-4, 0x1.ae3c2b46220bep-8, 0x1.77338187012f2p-4, + -0x1.3aea0460095d6p-8, 0x1.2cc472d0f94fdp-3, 0x1.812ae0c30b2cbp-7, -0x1.201e7e280992cp-3, + -0x1.0ca0cdb799e05p-5, 0x1.6ab75192b33a9p-3, 0x1.94b3c2395723bp-6, 0x1.db27362fb3816p-6, + 0x1.9f39a5255fc27p-5, 0x1.a41cc89f3cd58p-6, -0x1.cd3127ca911e1p-5, 0x1.2f2e1a63d102bp-5, + -0x1.2f2e1a63d102bp-5, 0x1.cd3127ca911e1p-5, -0x1.a41cc89f3cd58p-6, -0x1.9f39a5255fc27p-5, + -0x1.db27362fb3816p-6, -0x1.94b3c2395723bp-6, -0x1.6ab75192b33a9p-3, 0x1.0ca0cdb799e05p-5, + 0x1.201e7e280992cp-3, -0x1.812ae0c30b2cbp-7, -0x1.2cc472d0f94fdp-3, 0x1.3aea0460095d6p-8, + -0x1.77338187012f2p-4, -0x1.ae3c2b46220bep-8, -0x1.21fcb0e22a654p-4, -0x1.816635b7f89e5p-9, + -0x1.dc7e97e3aaf36p-3, -0x1.a64c0644387c5p-6, -0x1.6f65fdaf241b7p-3, 0x1.da65416b536fdp-5, + -0x1.f97796454a7b7p-4, 0x1.f285ef11492edp-6, 0x1.a21a32dfe8b48p-4, 0x1.896d9a0dcf59dp-5, + -0x1.52822bb625691p-5, -0x1.9491b6cdc7c1ap-12, 0x1.202d0d70f0194p-6, 0x1.f25b4e7d4102cp-4, + -0x1.b8be3f69c6b0fp-4, -0x1.43c83040ac29dp-5, -0x1.56fcff9c3f456p-4, -0x1.65de34b153947p-5, + -0x1.69e7d8c72636ep-5, 0x1.944451facaf6dp-5, -0x1.a00e74186b72ep-5, -0x1.603663513402fp-5, + -0x1.838871d9a8274p-6, 0x1.ccdae2b81dfddp-3, 0x1.2519083b60772p-6, 0x1.d7fb124f4c6c3p-5, + 0x1.3080f5c6983b8p-5, -0x1.4923008916118p-3, -0x1.b830bbc936a1fp-5, -0x1.d38e44e3e7f5ap-4, + -0x1.78daf7af326e8p-10, -0x1.5e4a2a67f4121p-3, 0x1.24049d15da6a8p-5, 0x1.190010a6447e3p-4, + 0x1.b0541db6921efp-4, 0x1.9d0c04f6273ebp-4, 0x1.3f681757ba6bcp-5, 0x1.275c2f9b80ab8p-4, + -0x1.2249cebc61c2cp-3, -0x1.0ec66f3335651p-4, -0x1.6bca1894417a2p-4, -0x1.ddaf1a5d0f6b5p-6, + 0x1.526dc4ee12eabp-4, -0x1.c5c7e852d5bb9p-6, 0x1.72ff965e42ba5p-5, -0x1.11c7849c685fdp-4, + 0x1.c18095cf221e5p-5, -0x1.78d7e089d72d6p-9, -0x1.4081b8c8c9b10p-3, 0x1.4a7cfda007297p-6, + -0x1.5f6d03a54c97ep-7, -0x1.fe1cae4fe1d1ep-4, 0x1.04fb7fe1edda8p-5, 0x1.ef178bbe6d205p-4, + -0x1.aa6c82648153cp-5, -0x1.d17e7ad87d469p-4, 0x1.21a79a36f1ff3p-4, 0x1.a630906012a52p-4, + -0x1.659191b6374b1p-4, -0x1.6e7443eeb9852p-4, 0x1.9ef44064af5b6p-4, 0x1.2bedb4731f5b4p-4, + -0x1.cc1f0bb3d408dp-4, -0x1.c1249f83ba1e4p-5, 0x1.ebbd8ce7f6bb3p-4, 0x1.1d3443fbef357p-5, + -0x1.fce15e59a0dcep-4, -0x1.c378577555909p-7, 0x1.ff095649c24b7p-4, -0x1.f656ef7562c28p-8, + -0x1.f2252f7ee7fc8p-4, 0x1.d934fd2a86e46p-6, 0x1.d696189c1018ep-4, -0x1.9372a4ec82e26p-5, + -0x1.ad2bcb893d054p-4, 0x1.1734d667a98cdp-4, 0x1.771e75f35fd39p-4, -0x1.5c77ba5a2fe48p-4, + -0x1.36058903ce551p-4, 0x1.9777f0b34a75ap-4, 0x1.d797758b59d78p-5, -0x1.c678b35a938c1p-4, + -0x1.35410bbb1e1a0p-5, 0x1.e817bb3e9e952p-4, 0x1.139f10846e624p-6, -0x1.fb5797a8b9dbbp-4, + 0x1.2d864017a1116p-8, 0x1.ffa72e57b3b7dp-4, -0x1.a82a00e1a8324p-6, -0x1.f4e6055b864ccp-4, + 0x1.7c3a963d381f4p-5, 0x1.db6526c781b02p-4, -0x1.0c970492a3d1dp-4, -0x1.b3e4d17c64f97p-4, + 0x1.532827753a39cp-4, 0x1.7f8ece980cab6p-4, -0x1.8fbcc8c0303cdp-4, -0x1.3fed9500bb6c4p-4, + 0x1.c08c407695248p-4, 0x1.edc19181db73ep-5, -0x1.e426a3667e091p-4, -0x1.4d1e202e535d0p-5, + 0x1.f97f929c57938p-4, 0x1.45577010bc14dp-6, -0x1.fff623c165a90p-4, 0x1.921d4edf27fa7p-10, + 0x1.f75997dd9620ap-4, -0x1.76dda567b0451p-6, -0x1.dfeae76e1fd6cp-4, 0x1.64c7df81980c1p-5, + 0x1.ba5aa6e561bb3p-4, -0x1.01cfca3aa6c5bp-4, -0x1.87c403366c9eep-4, 0x1.49a44943d3a49p-4, + 0x1.49a44943d3a49p-4, -0x1.87c403366c9eep-4, -0x1.01cfca3aa6c5bp-4, 0x1.ba5aa6e561bb3p-4, + 0x1.64c7df81980c1p-5, -0x1.dfeae76e1fd6cp-4, -0x1.76dda567b0451p-6, 0x1.f75997dd9620ap-4, + 0x1.921d4edf27fa7p-10, -0x1.fff623c165a90p-4, 0x1.45577010bc14dp-6, 0x1.f97f929c57938p-4, + -0x1.4d1e202e535d0p-5, -0x1.e426a3667e091p-4, 0x1.edc19181db73ep-5, 0x1.c08c407695248p-4, + -0x1.3fed9500bb6c4p-4, -0x1.8fbcc8c0303cdp-4, 0x1.7f8ece980cab6p-4, 0x1.532827753a39cp-4, + -0x1.b3e4d17c64f97p-4, -0x1.0c970492a3d1dp-4, 0x1.db6526c781b02p-4, 0x1.7c3a963d381f4p-5, + -0x1.f4e6055b864ccp-4, -0x1.a82a00e1a8324p-6, 0x1.ffa72e57b3b7dp-4, 0x1.2d864017a1116p-8, + -0x1.fb5797a8b9dbbp-4, 0x1.139f10846e624p-6, 0x1.e817bb3e9e952p-4, -0x1.35410bbb1e1a0p-5, + -0x1.c678b35a938c1p-4, 0x1.d797758b59d78p-5, 0x1.9777f0b34a75ap-4, -0x1.36058903ce551p-4, + -0x1.5c77ba5a2fe48p-4, 0x1.771e75f35fd39p-4, 0x1.1734d667a98cdp-4, -0x1.ad2bcb893d054p-4, + -0x1.9372a4ec82e26p-5, 0x1.d696189c1018ep-4, 0x1.d934fd2a86e46p-6, -0x1.f2252f7ee7fc8p-4, + -0x1.f656ef7562c28p-8, 0x1.ff095649c24b7p-4, -0x1.c378577555909p-7, -0x1.fce15e59a0dcep-4, + 0x1.1d3443fbef357p-5, 0x1.ebbd8ce7f6bb3p-4, -0x1.c1249f83ba1e4p-5, -0x1.cc1f0bb3d408dp-4, + 0x1.2bedb4731f5b4p-4, 0x1.9ef44064af5b6p-4, -0x1.6e7443eeb9852p-4, -0x1.659191b6374b1p-4, + 0x1.a630906012a52p-4, 0x1.21a79a36f1ff3p-4, -0x1.d17e7ad87d469p-4, -0x1.aa6c82648153cp-5, + 0x1.ef178bbe6d205p-4, 0x1.04fb7fe1edda8p-5, -0x1.fe1cae4fe1d32p-4, -0x1.5f6d03a54c97fp-7, + 0x1.fe1cae62bb0e5p-4, -0x1.5f6d02b1547f4p-7, 0x1.ef178a8d9a6a3p-4, -0x1.04fb80623959fp-5, + 0x1.d17e7b4870c14p-4, -0x1.aa6c82bf762cep-5, 0x1.a63090d6d974fp-4, -0x1.21a79affb1328p-4, + 0x1.6e7443ec6fe67p-4, -0x1.65919237b9899p-4, 0x1.2bedb44ea821cp-4, -0x1.9ef4408c964cap-4, + 0x1.c1249eaf69859p-5, -0x1.cc1f0c7e7ef55p-4, 0x1.1d344478af965p-5, -0x1.ebbd8d1798028p-4, + 0x1.c37857f948c55p-7, -0x1.fce15e613daeap-4, -0x1.f656eef0f0b05p-8, -0x1.ff0956650a3c1p-4, + -0x1.d934fd0ccecd9p-6, -0x1.f2252ed71704fp-4, -0x1.9372a4de8aa37p-5, -0x1.d6961877d9dc9p-4, + -0x1.1734d65bcce7cp-4, -0x1.ad2bcae027c28p-4, -0x1.5c77ba1b3b254p-4, -0x1.771e779ad2916p-4, + -0x1.9777efb0d2cb8p-4, -0x1.360587ea84502p-4, -0x1.c678b2b65513fp-4, -0x1.d797753c73473p-5, + -0x1.e817b9ab27dc5p-4, -0x1.35410c5a81b17p-5, -0x1.fb57996c52b78p-4, -0x1.139f10a62e01cp-6, + -0x1.ffa72e2bcf1e4p-4, 0x1.2d8642723af00p-8, -0x1.f4e605ad4e00ap-4, 0x1.a829ff2b6ff82p-6, + -0x1.db6527954a4a2p-4, 0x1.7c3a96db0f642p-5, -0x1.b3e4d2875ff26p-4, 0x1.0c97049c477c6p-4, + -0x1.7f8ece65482e6p-4, 0x1.53282659e7ebap-4, -0x1.3fed9481b21abp-4, 0x1.8fbcc852df656p-4, + -0x1.edc190f24b5eap-5, 0x1.c08c40e612ac5p-4, -0x1.4d1e206e84d61p-5, 0x1.e426a2f2e189bp-4, + -0x1.45576fe22341ep-6, 0x1.f97f92c4a5c67p-4, 0x1.921d48e33791ep-10, 0x1.fff6224cdd33ap-4, + 0x1.76dda495d0671p-6, 0x1.f759995dc17b2p-4, 0x1.64c7e0ba233e6p-5, 0x1.dfeae723b00c0p-4, + 0x1.01cfca7f6f12cp-4, 0x1.ba5aa71bae861p-4, 0x1.49a44a3a1bfd7p-4, 0x1.87c4025810100p-4, + 0x1.87c4025810100p-4, 0x1.49a44a3a1bfd7p-4, 0x1.ba5aa71bae861p-4, 0x1.01cfca7f6f12cp-4, + 0x1.dfeae723b00c0p-4, 0x1.64c7e0ba233e6p-5, 0x1.f759995dc17b2p-4, 0x1.76dda495d0671p-6, + 0x1.fff6224cdd33ap-4, 0x1.921d48e33791ep-10, 0x1.f97f92c4a5c67p-4, -0x1.45576fe22341ep-6, + 0x1.e426a2f2e189bp-4, -0x1.4d1e206e84d61p-5, 0x1.c08c40e612ac5p-4, -0x1.edc190f24b5eap-5, + 0x1.8fbcc852df656p-4, -0x1.3fed9481b21abp-4, 0x1.53282659e7ebap-4, -0x1.7f8ece65482e6p-4, + 0x1.0c97049c477c6p-4, -0x1.b3e4d2875ff26p-4, 0x1.7c3a96db0f642p-5, -0x1.db6527954a4a2p-4, + 0x1.a829ff2b6ff82p-6, -0x1.f4e605ad4e00ap-4, 0x1.2d8642723af00p-8, -0x1.ffa72e2bcf1e4p-4, + -0x1.139f10a62e01cp-6, -0x1.fb57996c52b78p-4, -0x1.35410c5a81b17p-5, -0x1.e817b9ab27dc5p-4, + -0x1.d797753c73473p-5, -0x1.c678b2b65513fp-4, -0x1.360587ea84502p-4, -0x1.9777efb0d2cb8p-4, + -0x1.771e779ad2916p-4, -0x1.5c77ba1b3b254p-4, -0x1.ad2bcae027c28p-4, -0x1.1734d65bcce7cp-4, + -0x1.d6961877d9dc9p-4, -0x1.9372a4de8aa37p-5, -0x1.f2252ed71704fp-4, -0x1.d934fd0ccecd9p-6, + -0x1.ff0956650a3c1p-4, -0x1.f656eef0f0b05p-8, -0x1.fce15e613daeap-4, 0x1.c37857f948c55p-7, + -0x1.ebbd8d1798028p-4, 0x1.1d344478af965p-5, -0x1.cc1f0c7e7ef55p-4, 0x1.c1249eaf69859p-5, + -0x1.9ef4408c964cap-4, 0x1.2bedb44ea821cp-4, -0x1.65919237b9899p-4, 0x1.6e7443ec6fe67p-4, + -0x1.21a79affb1328p-4, 0x1.a63090d6d974fp-4, -0x1.aa6c82bf762cep-5, 0x1.d17e7b4870c14p-4, + -0x1.04fb80623959fp-5, 0x1.ef178a8d9a6a3p-4, -0x1.5f6d02b1547f5p-7, 0x1.fe1cae62bb0ddp-4, + 0x1.da3068e3f6426p-4, -0x1.405ec999735d3p-8, 0x1.11525c49b6d0cp-3, 0x1.87ca0c0508085p-5, + -0x1.75ed035a63713p-4, -0x1.b7cfc3a8f43ccp-4, -0x1.6ea582c7f9af1p-3, -0x1.27f1845ae2826p-10, + 0x1.d64204234a1edp-4, 0x1.2484a3d155141p-5, -0x1.d904ce9a99a8cp-6, -0x1.1533d8190c7bbp-3, + 0x1.20210c3c9d411p-6, 0x1.eb95493b2898ep-4, 0x1.ecf3ba2cd91d7p-8, 0x1.1bdb93473f5d8p-2, + -0x1.a47d9b44b1356p-7, -0x1.58cd3bd00105ep-4, 0x1.08d0ca7331643p-6, -0x1.99dc7b8c8e3e4p-5, + 0x1.cf11074c1a146p-8, -0x1.55cfb6f986377p-5, 0x1.12518d88a9f8dp-4, 0x1.54f48e3b863d1p-6, + 0x1.826ba77f1185cp-4, -0x1.87bf5f6257bb4p-5, -0x1.dae9b88128bb2p-4, 0x1.7f0768d86a803p-5, + 0x1.84132c83ba89fp-6, 0x1.8869730523835p-5, -0x1.4d683d82a6ac8p-5, -0x1.14b21526f924cp-4, + 0x1.80c7bf46651a4p-5, -0x1.250e4ef84c865p-5, -0x1.55a1794665bb4p-4, -0x1.57d72eeac657cp-6, + 0x1.6fff53bf1cd08p-6, 0x1.df89bfaf94aabp-8, -0x1.b551f00c3dba4p-4, -0x1.3a068a956c1c2p-6, + 0x1.96fd305460693p-4, -0x1.26dade772f710p-4, 0x1.af09f3b00ada4p-4, -0x1.435f667e78d2cp-4, + 0x1.5a972c0b838c6p-4, -0x1.2b52bb031ff27p-4, 0x1.eb7d4a854db78p-7, -0x1.8ee364ff819d2p-5, + 0x1.c73da651cd39bp-4, -0x1.54cb96573c657p-3, -0x1.f0876836161b2p-5, 0x1.66d6a8fcb630ap-3, + -0x1.1ed3947483daep-7, 0x1.f699d4ac7fd28p-3, 0x1.86fc9665c170ap-15, 0x1.b7b12c3e8130ap-4, + 0x1.8f73f0c36f4b9p-7, 0x1.e92a97d22581dp-5, -0x1.2c374d0d068f9p-5, -0x1.8f5910ba163cdp-6, + -0x1.a81b4ebef3781p-6, -0x1.b7a240d9e313cp-4, -0x1.94413265a570bp-6, 0x1.2e54feb03b26dp-5, + 0x1.2e54feb03b26dp-5, -0x1.94413265a570bp-6, -0x1.b7a240d9e313cp-4, -0x1.a81b4ebef3781p-6, + -0x1.8f5910ba163cdp-6, -0x1.2c374d0d068f9p-5, 0x1.e92a97d22581dp-5, 0x1.8f73f0c36f4b9p-7, + 0x1.b7b12c3e8130ap-4, 0x1.86fc9665c170ap-15, 0x1.f699d4ac7fd28p-3, -0x1.1ed3947483daep-7, + 0x1.66d6a8fcb630ap-3, -0x1.f0876836161b2p-5, -0x1.54cb96573c657p-3, 0x1.c73da651cd39bp-4, + -0x1.8ee364ff819d2p-5, 0x1.eb7d4a854db78p-7, -0x1.2b52bb031ff27p-4, 0x1.5a972c0b838c6p-4, + -0x1.435f667e78d2cp-4, 0x1.af09f3b00ada4p-4, -0x1.26dade772f710p-4, 0x1.96fd305460693p-4, + -0x1.3a068a956c1c2p-6, -0x1.b551f00c3dba4p-4, 0x1.df89bfaf94aabp-8, 0x1.6fff53bf1cd08p-6, + -0x1.57d72eeac657cp-6, -0x1.55a1794665bb4p-4, -0x1.250e4ef84c865p-5, 0x1.80c7bf46651a4p-5, + -0x1.14b21526f924cp-4, -0x1.4d683d82a6ac8p-5, 0x1.8869730523835p-5, 0x1.84132c83ba89fp-6, + 0x1.7f0768d86a803p-5, -0x1.dae9b88128bb2p-4, -0x1.87bf5f6257bb4p-5, 0x1.826ba77f1185cp-4, + 0x1.54f48e3b863d1p-6, 0x1.12518d88a9f8dp-4, -0x1.55cfb6f986377p-5, 0x1.cf11074c1a146p-8, + -0x1.99dc7b8c8e3e4p-5, 0x1.08d0ca7331643p-6, -0x1.58cd3bd00105ep-4, -0x1.a47d9b44b1356p-7, + 0x1.1bdb93473f5d8p-2, 0x1.ecf3ba2cd91d7p-8, 0x1.eb95493b2898ep-4, 0x1.20210c3c9d411p-6, + -0x1.1533d8190c7bbp-3, -0x1.d904ce9a99a8cp-6, 0x1.2484a3d155141p-5, 0x1.d64204234a1edp-4, + -0x1.27f1845ae281cp-10, -0x1.6ea582c7f9af4p-3, -0x1.b7cfc3a8f43cap-4, -0x1.75ed035a63715p-4, + 0x1.87ca0c050808dp-5, 0x1.11525c49b6d11p-3, -0x1.405ec98e8bcb1p-8, 0x1.da306b19098cdp-4, + -0x1.14bd9592eb24dp-12, -0x1.766913350f7bcp-3, 0x1.c7333b0583610p-5, -0x1.80225092f6291p-8, + -0x1.976f0deb9f6f7p-8, -0x1.f10b4edbe40bdp-5, 0x1.e624410e688c9p-6, 0x1.ed311335dc675p-5, + -0x1.f7a7c9bf0e77fp-5, -0x1.3ccd75b45760ap-4, 0x1.e4a70482de252p-7, 0x1.75d5554cc7bc8p-7, + -0x1.c6efd72d62cf4p-6, 0x1.ce4ee55ee761fp-4, -0x1.8fcef6b64781bp-4, -0x1.c682c38c500d7p-10, + -0x1.60752fc71bb93p-4, -0x1.c9aabc38c2abdp-7, 0x1.800dfd7eef9e3p-3, 0x1.730d4872f9b15p-8, + 0x1.335bc0caaecbfp-2, -0x1.08544a61372cap-5, 0x1.749cc527a5afbp-4, 0x1.11d371ba4f8a9p-5, + 0x1.d54cc96323484p-5, -0x1.4ec2c81a386dap-9, 0x1.150f36bbd7c14p-4, 0x1.b338ba13ac027p-6, + 0x1.c3902d0c6d670p-4, 0x1.68d1c5dc7ee85p-9, -0x1.d742660bf738ap-11, 0x1.6e350410af548p-5, + -0x1.a8af18b1c0eb1p-5, 0x1.511f95b8d87cdp-4, 0x1.f31f9fe9119ffp-7, -0x1.512f0401d54e9p-6, + 0x1.f34c34b2d3c98p-9, -0x1.a79a2d4f2e513p-5, 0x1.7743c68179aa8p-7, 0x1.cba642b54a046p-4, + 0x1.df56786683a0ap-12, 0x1.48b982504fb35p-7, 0x1.0fa3d52c8185dp-4, -0x1.25769ba815d97p-3, + -0x1.9040373be2a7fp-3, -0x1.17ff95afa920ap-8, 0x1.fcbdf48a39496p-4, 0x1.21be0315f0931p-3, + 0x1.5294a71db40d3p-5, 0x1.ee4cf71617871p-6, 0x1.f619b550f60b3p-7, -0x1.4461ddb228845p-5, + 0x1.d7ced6a5abc59p-4, -0x1.e090e4d2a2e2ep-9, 0x1.cd1a79098d608p-3, -0x1.644419cb69c84p-8, + 0x1.7a04f43fe4595p-6, 0x1.a71e1f83e2a2ap-6, 0x1.1a797fc1ab802p-7, 0x1.aef9bda48d426p-4, + 0x1.311a3a9049fc5p-4, -0x1.2dbcf62fd9820p-6, 0x1.3c141ef1707bep-3, 0x1.2b1e150769766p-3, + 0x1.2b1e150769766p-3, 0x1.3c141ef1707bep-3, -0x1.2dbcf62fd9820p-6, 0x1.311a3a9049fc5p-4, + 0x1.aef9bda48d426p-4, 0x1.1a797fc1ab802p-7, 0x1.a71e1f83e2a2ap-6, 0x1.7a04f43fe4595p-6, + -0x1.644419cb69c84p-8, 0x1.cd1a79098d608p-3, -0x1.e090e4d2a2e2ep-9, 0x1.d7ced6a5abc59p-4, + -0x1.4461ddb228845p-5, 0x1.f619b550f60b3p-7, 0x1.ee4cf71617871p-6, 0x1.5294a71db40d3p-5, + 0x1.21be0315f0931p-3, 0x1.fcbdf48a39496p-4, -0x1.17ff95afa920ap-8, -0x1.9040373be2a7fp-3, + -0x1.25769ba815d97p-3, 0x1.0fa3d52c8185dp-4, 0x1.48b982504fb35p-7, 0x1.df56786683a0ap-12, + 0x1.cba642b54a046p-4, 0x1.7743c68179aa8p-7, -0x1.a79a2d4f2e513p-5, 0x1.f34c34b2d3c98p-9, + -0x1.512f0401d54e9p-6, 0x1.f31f9fe9119ffp-7, 0x1.511f95b8d87cdp-4, -0x1.a8af18b1c0eb1p-5, + 0x1.6e350410af548p-5, -0x1.d742660bf738ap-11, 0x1.68d1c5dc7ee85p-9, 0x1.c3902d0c6d670p-4, + 0x1.b338ba13ac027p-6, 0x1.150f36bbd7c14p-4, -0x1.4ec2c81a386dap-9, 0x1.d54cc96323484p-5, + 0x1.11d371ba4f8a9p-5, 0x1.749cc527a5afbp-4, -0x1.08544a61372cap-5, 0x1.335bc0caaecbfp-2, + 0x1.730d4872f9b15p-8, 0x1.800dfd7eef9e3p-3, -0x1.c9aabc38c2abdp-7, -0x1.60752fc71bb93p-4, + -0x1.c682c38c500d7p-10, -0x1.8fcef6b64781bp-4, 0x1.ce4ee55ee761fp-4, -0x1.c6efd72d62cf4p-6, + 0x1.75d5554cc7bc8p-7, 0x1.e4a70482de252p-7, -0x1.3ccd75b45760ap-4, -0x1.f7a7c9bf0e77fp-5, + 0x1.ed311335dc67fp-5, 0x1.e624410e688bep-6, -0x1.f10b4edbe40c4p-5, -0x1.976f0deb9f6cdp-8, + -0x1.80225092f62eap-8, 0x1.c7333b058360ap-5, -0x1.7669134960cb0p-3, -0x1.14bdafe45d8bep-12, + -0x1.c3785f89aeee1p-7, -0x1.fce15ffceb421p-4, 0x1.4d1e242bf0f82p-5, 0x1.e426a191066c0p-4, + -0x1.0c970463c3113p-4, -0x1.b3e4d35583ae0p-4, 0x1.65919209300a9p-4, 0x1.6e74458a45433p-4, + -0x1.ad2bcb2f217e0p-4, -0x1.1734d6c2c783ep-4, 0x1.dfeae65b6bb33p-4, 0x1.64c7deabf6b99p-5, + -0x1.fb57975db8b3bp-4, -0x1.139f0b9cca68bp-6, 0x1.fe1cb195bc8e9p-4, -0x1.5f6cfebdd11cdp-7, + -0x1.e817bbd3ebe7bp-4, 0x1.35410d8bd33d8p-5, 0x1.ba5aa78f2d653p-4, -0x1.01cfc849a7f91p-4, + -0x1.771e762d55b1dp-4, 0x1.5c77bc7863e8fp-4, 0x1.21a79a084c384p-4, -0x1.a630916529fa5p-4, + -0x1.7c3a92b2e90f0p-5, 0x1.db652574704a6p-4, 0x1.4557685b88205p-6, -0x1.f97f90254d217p-4, + 0x1.f656ef635ba31p-8, 0x1.ff09562923678p-4, -0x1.1d3444a3932edp-5, -0x1.ebbd8c1c31b2ep-4, + 0x1.edc1938fc6e7ep-5, 0x1.c08c453d6c067p-4, -0x1.5328275071384p-4, -0x1.7f8ecf92fef1fp-4, + 0x1.9ef4401ce99e7p-4, 0x1.2bedb29a24837p-4, -0x1.d69615fe3258fp-4, -0x1.9372a5b9dda6ap-5, + 0x1.f7599a332efbfp-4, 0x1.76dd991fe33b0p-6, -0x1.ffa72f1c5ecf9p-4, 0x1.2d8648522ea51p-8, + 0x1.ef178a07cf66fp-4, -0x1.04fb80b87c074p-5, -0x1.c678b3836bab4p-4, 0x1.d797764754682p-5, + 0x1.87c4017e0b374p-4, -0x1.49a44acadc52cp-4, -0x1.36058a6945a1bp-4, 0x1.9777eeb60fe7fp-4, + 0x1.aa6c827deb340p-5, -0x1.d17e78bc669c9p-4, -0x1.a82a03e06bad4p-6, 0x1.f4e6055c40538p-4, + -0x1.921d943049a8dp-10, -0x1.fff6204d28b90p-4, 0x1.d934fcd3b7c7fp-6, 0x1.f2252d6d84627p-4, + -0x1.c1249c94b7896p-5, -0x1.cc1f0e3dfc558p-4, 0x1.3fed9524c321bp-4, 0x1.8fbcca3c6b61bp-4, + -0x1.8fbcca3c6b61bp-4, -0x1.3fed9524c321bp-4, 0x1.cc1f0e3dfc558p-4, 0x1.c1249c94b7896p-5, + -0x1.f2252d6d84627p-4, -0x1.d934fcd3b7c7fp-6, 0x1.fff6204d28b90p-4, 0x1.921d943049a8dp-10, + -0x1.f4e6055c40538p-4, 0x1.a82a03e06bad4p-6, 0x1.d17e78bc669c9p-4, -0x1.aa6c827deb340p-5, + -0x1.9777eeb60fe7fp-4, 0x1.36058a6945a1bp-4, 0x1.49a44acadc52cp-4, -0x1.87c4017e0b374p-4, + -0x1.d797764754682p-5, 0x1.c678b3836bab4p-4, 0x1.04fb80b87c074p-5, -0x1.ef178a07cf66fp-4, + -0x1.2d8648522ea51p-8, 0x1.ffa72f1c5ecf9p-4, -0x1.76dd991fe33b0p-6, -0x1.f7599a332efbfp-4, + 0x1.9372a5b9dda6ap-5, 0x1.d69615fe3258fp-4, -0x1.2bedb29a24837p-4, -0x1.9ef4401ce99e7p-4, + 0x1.7f8ecf92fef1fp-4, 0x1.5328275071384p-4, -0x1.c08c453d6c067p-4, -0x1.edc1938fc6e7ep-5, + 0x1.ebbd8c1c31b2ep-4, 0x1.1d3444a3932edp-5, -0x1.ff09562923678p-4, -0x1.f656ef635ba31p-8, + 0x1.f97f90254d217p-4, -0x1.4557685b88205p-6, -0x1.db652574704a6p-4, 0x1.7c3a92b2e90f0p-5, + 0x1.a630916529fa5p-4, -0x1.21a79a084c384p-4, -0x1.5c77bc7863e8fp-4, 0x1.771e762d55b1dp-4, + 0x1.01cfc849a7f91p-4, -0x1.ba5aa78f2d653p-4, -0x1.35410d8bd33d8p-5, 0x1.e817bbd3ebe7bp-4, + 0x1.5f6cfebdd11cdp-7, -0x1.fe1cb195bc8e9p-4, 0x1.139f0b9cca68bp-6, 0x1.fb57975db8b3bp-4, + -0x1.64c7deabf6b99p-5, -0x1.dfeae65b6bb33p-4, 0x1.1734d6c2c783ep-4, 0x1.ad2bcb2f217e0p-4, + -0x1.6e74458a45433p-4, -0x1.65919209300a9p-4, 0x1.b3e4d35583ae0p-4, 0x1.0c970463c3113p-4, + -0x1.e426a191066c0p-4, -0x1.4d1e242bf0f82p-5, 0x1.fce15ffceb3ffp-4, 0x1.c3785f89aeedcp-7, + 0x1.fce160a2e3619p-4, -0x1.c378602c83b5ap-7, 0x1.e426a2aae4b94p-4, -0x1.4d1e23785e22ap-5, + 0x1.b3e4d41755c60p-4, -0x1.0c97040f5c9e4p-4, 0x1.6e744607aa2fcp-4, -0x1.6591928e2f37fp-4, + 0x1.1734d5d8ac7b5p-4, -0x1.ad2bca3689feep-4, 0x1.64c7dee8d2697p-5, -0x1.dfeae666643cfp-4, + 0x1.139f0bc25a938p-6, -0x1.fb579783d1c10p-4, -0x1.5f6cff4db4d21p-7, -0x1.fe1cb1682b1c2p-4, + -0x1.35410c667471ep-5, -0x1.e817bc9f7fcb3p-4, -0x1.01cfc8263b547p-4, -0x1.ba5aa6ee2d4edp-4, + -0x1.5c77bc7fcf042p-4, -0x1.771e76fd33146p-4, -0x1.a63092377cc85p-4, -0x1.21a79a6512e70p-4, + -0x1.db652404c80d6p-4, -0x1.7c3a9255bacbep-5, -0x1.f97f901e9322dp-4, -0x1.45576855adc97p-6, + -0x1.ff0956caf0a01p-4, 0x1.f656f021cd74ap-8, -0x1.ebbd8bc68071dp-4, 0x1.1d34439bb58cbp-5, + -0x1.c08c4369953a3p-4, 0x1.edc1952a154a4p-5, -0x1.7f8ece272f035p-4, 0x1.53282863c4469p-4, + -0x1.2bedb235b654dp-4, 0x1.9ef440ee700ddp-4, -0x1.9372a67080537p-5, 0x1.d696162cc8326p-4, + -0x1.76dd980061f6ap-6, 0x1.f7599af91c347p-4, 0x1.2d864653571bcp-8, 0x1.ffa72e55a93a7p-4, + 0x1.04fb803f7daa9p-5, 0x1.ef1789718871cp-4, 0x1.d79776157bc06p-5, 0x1.c678b2c5bd817p-4, + 0x1.49a44a891fcdep-4, 0x1.87c402b2bff2fp-4, 0x1.9777ef0d847ddp-4, 0x1.36058a7d06a27p-4, + 0x1.d17e78190c707p-4, 0x1.aa6c816d8eb97p-5, 0x1.f4e603f8a6f61p-4, 0x1.a82a056dfabd6p-6, + 0x1.fff6204d84886p-4, -0x1.921d9a5de7399p-10, 0x1.f2252e7004045p-4, -0x1.d934fc77b710bp-6, + 0x1.cc1f0ef152c14p-4, -0x1.c1249ce505d1dp-5, 0x1.8fbcca51af51ap-4, -0x1.3fed94ca43a3cp-4, + 0x1.3fed94ca43a3cp-4, -0x1.8fbcca51af51ap-4, 0x1.c1249ce505d1dp-5, -0x1.cc1f0ef152c14p-4, + 0x1.d934fc77b710bp-6, -0x1.f2252e7004045p-4, 0x1.921d9a5de7399p-10, -0x1.fff6204d84886p-4, + -0x1.a82a056dfabd6p-6, -0x1.f4e603f8a6f61p-4, -0x1.aa6c816d8eb97p-5, -0x1.d17e78190c707p-4, + -0x1.36058a7d06a27p-4, -0x1.9777ef0d847ddp-4, -0x1.87c402b2bff2fp-4, -0x1.49a44a891fcdep-4, + -0x1.c678b2c5bd817p-4, -0x1.d79776157bc06p-5, -0x1.ef1789718871cp-4, -0x1.04fb803f7daa9p-5, + -0x1.ffa72e55a93a7p-4, -0x1.2d864653571bcp-8, -0x1.f7599af91c347p-4, 0x1.76dd980061f6ap-6, + -0x1.d696162cc8326p-4, 0x1.9372a67080537p-5, -0x1.9ef440ee700ddp-4, 0x1.2bedb235b654dp-4, + -0x1.53282863c4469p-4, 0x1.7f8ece272f035p-4, -0x1.edc1952a154a4p-5, 0x1.c08c4369953a3p-4, + -0x1.1d34439bb58cbp-5, 0x1.ebbd8bc68071dp-4, -0x1.f656f021cd74ap-8, 0x1.ff0956caf0a01p-4, + 0x1.45576855adc97p-6, 0x1.f97f901e9322dp-4, 0x1.7c3a9255bacbep-5, 0x1.db652404c80d6p-4, + 0x1.21a79a6512e70p-4, 0x1.a63092377cc85p-4, 0x1.771e76fd33146p-4, 0x1.5c77bc7fcf042p-4, + 0x1.ba5aa6ee2d4edp-4, 0x1.01cfc8263b547p-4, 0x1.e817bc9f7fcb3p-4, 0x1.35410c667471ep-5, + 0x1.fe1cb1682b1c2p-4, 0x1.5f6cff4db4d21p-7, 0x1.fb579783d1c10p-4, -0x1.139f0bc25a938p-6, + 0x1.dfeae666643cfp-4, -0x1.64c7dee8d2697p-5, 0x1.ad2bca3689feep-4, -0x1.1734d5d8ac7b5p-4, + 0x1.6591928e2f37fp-4, -0x1.6e744607aa2fcp-4, 0x1.0c97040f5c9e4p-4, -0x1.b3e4d41755c60p-4, + 0x1.4d1e23785e22ap-5, -0x1.e426a2aae4b94p-4, 0x1.c378602c83b5ap-7, -0x1.fce160a2e3605p-4, + -0x1.07601a5629c5bp-3, 0x1.27493583c9e6dp-5, 0x1.8a1cc5756bae3p-4, -0x1.5862b0a7d07b0p-4, + 0x1.e45bb228beb5bp-9, 0x1.9e3b4568e9d68p-5, 0x1.19bdbcf6f6dd9p-3, -0x1.1b74e9d6d7d5cp-5, + 0x1.fe18a741f98bfp-5, 0x1.3b9acbaf92d87p-5, -0x1.0f0d9f7e1ca05p-4, 0x1.11adc042c62c9p-3, + 0x1.17b06c43dd548p-7, 0x1.d33127bb2a87fp-5, -0x1.05b75d251e695p-6, -0x1.34245fa6485d9p-4, + -0x1.d561e10b7efc4p-6, -0x1.846e954acde5ep-6, -0x1.2c7abd83fb748p-4, 0x1.8e29143af72c9p-4, + 0x1.89174d90d575ap-4, 0x1.5c1285ef3e0fbp-4, 0x1.d89bbbc125ee3p-3, 0x1.f35c6567c5ac1p-4, + -0x1.b29a6e3e79cb4p-4, 0x1.6f84566d281b1p-7, -0x1.5a92b8d2ea115p-4, -0x1.cf45dd6bbf386p-9, + -0x1.172ab130b8e2ap-3, -0x1.450864729ea86p-6, 0x1.1ac5cb564d418p-3, 0x1.22b48ca0eafb7p-5, + -0x1.f11fcfde4c3a3p-5, 0x1.48c97da7d9432p-6, -0x1.638de64476d42p-5, -0x1.37a6a7199e12dp-5, + 0x1.96fb2b7400503p-4, 0x1.abfc816d3c47dp-4, -0x1.e5a60d394bf5dp-7, 0x1.d20279b6208d0p-3, + 0x1.62fd0f74f5fd1p-6, 0x1.ad9273679e6eap-5, 0x1.01d951bd9e01dp-6, 0x1.57cccba25d4f7p-6, + -0x1.46503aa0c2e9ap-5, -0x1.4b252c6f5aa6fp-4, 0x1.360730b13ec22p-4, 0x1.bf401b738dd2fp-4, + 0x1.2745f426452c9p-5, -0x1.71874e5d717aep-3, -0x1.d7915e1dc996ep-6, -0x1.d4c11ff3f3e0ep-10, + 0x1.9da5a244a637dp-4, -0x1.6df72c59cb819p-5, -0x1.80ff37a92249ap-3, -0x1.813a7841b3d1dp-5, + -0x1.45e24e4c1bc4ap-6, 0x1.0859e5730907dp-6, 0x1.104036d594012p-3, -0x1.d1838bd162dbap-7, + -0x1.3f93a9e9aacb9p-5, 0x1.2cb12040097a6p-3, 0x1.b795e1e021fb7p-4, 0x1.018fdea627842p-6, + -0x1.018fdea627842p-6, -0x1.b795e1e021fb7p-4, -0x1.2cb12040097a6p-3, 0x1.3f93a9e9aacb9p-5, + 0x1.d1838bd162dbap-7, -0x1.104036d594012p-3, -0x1.0859e5730907dp-6, 0x1.45e24e4c1bc4ap-6, + 0x1.813a7841b3d1dp-5, 0x1.80ff37a92249ap-3, 0x1.6df72c59cb819p-5, -0x1.9da5a244a637dp-4, + 0x1.d4c11ff3f3e0ep-10, 0x1.d7915e1dc996ep-6, 0x1.71874e5d717aep-3, -0x1.2745f426452c9p-5, + -0x1.bf401b738dd2fp-4, -0x1.360730b13ec22p-4, 0x1.4b252c6f5aa6fp-4, 0x1.46503aa0c2e9ap-5, + -0x1.57cccba25d4f7p-6, -0x1.01d951bd9e01dp-6, -0x1.ad9273679e6eap-5, -0x1.62fd0f74f5fd1p-6, + -0x1.d20279b6208d0p-3, 0x1.e5a60d394bf5dp-7, -0x1.abfc816d3c47dp-4, -0x1.96fb2b7400503p-4, + 0x1.37a6a7199e12dp-5, 0x1.638de64476d42p-5, -0x1.48c97da7d9432p-6, 0x1.f11fcfde4c3a3p-5, + -0x1.22b48ca0eafb7p-5, -0x1.1ac5cb564d418p-3, 0x1.450864729ea86p-6, 0x1.172ab130b8e2ap-3, + 0x1.cf45dd6bbf386p-9, 0x1.5a92b8d2ea115p-4, -0x1.6f84566d281b1p-7, 0x1.b29a6e3e79cb4p-4, + -0x1.f35c6567c5ac1p-4, -0x1.d89bbbc125ee3p-3, -0x1.5c1285ef3e0fbp-4, -0x1.89174d90d575ap-4, + -0x1.8e29143af72c9p-4, 0x1.2c7abd83fb748p-4, 0x1.846e954acde5ep-6, 0x1.d561e10b7efc4p-6, + 0x1.34245fa6485d9p-4, 0x1.05b75d251e695p-6, -0x1.d33127bb2a87fp-5, -0x1.17b06c43dd548p-7, + -0x1.11adc042c62c9p-3, 0x1.0f0d9f7e1ca05p-4, -0x1.3b9acbaf92d87p-5, -0x1.fe18a741f98bfp-5, + 0x1.1b74e9d6d7d5cp-5, -0x1.19bdbcf6f6dd7p-3, -0x1.9e3b4568e9d6fp-5, -0x1.e45bb228bea70p-9, + 0x1.5862b0a7d07b0p-4, -0x1.8a1cc5756baf0p-4, -0x1.2749358d2396bp-5, 0x1.07601aee712f3p-3, + 0x1.a55e46300e469p-8, 0x1.01c38c6851eaap-3, -0x1.2d42fa7a40178p-7, -0x1.da139564d3b08p-4, + -0x1.2ddff25b8f8b3p-7, 0x1.f2ef3bb93dc04p-6, 0x1.4b46e2db4594bp-5, -0x1.0a366f2abbd7dp-3, + -0x1.49c920ceb8ca3p-5, -0x1.883f08ffbdaa4p-8, 0x1.0621e485a2c2ap-4, -0x1.36173cec5b5fcp-8, + -0x1.58c1162f8a27cp-4, 0x1.441ab75c5bf89p-7, 0x1.56586dfb00770p-4, 0x1.2ea2ec00d408dp-6, + 0x1.2a57eeacfe51dp-3, 0x1.077e537b0fe31p-5, 0x1.ee98ed372c078p-3, -0x1.96ac12066235dp-6, + 0x1.01f35484f6459p-4, 0x1.f66494770391dp-5, -0x1.01aefdb9689e0p-3, 0x1.4773033fb9c28p-3, + -0x1.72278d87c6b0fp-5, 0x1.0db43ed126905p-3, 0x1.3d440c35997d9p-7, 0x1.f96f52403e87fp-4, + 0x1.4ba27e40aeedbp-6, -0x1.d2d8fe41dc44dp-4, -0x1.119c2d4e29c98p-5, 0x1.4975b47c573c5p-6, + -0x1.3f858f948abf8p-5, 0x1.88eaa637c6571p-3, 0x1.8626e551364dap-4, -0x1.80db57a300a54p-4, + -0x1.ae585937958f4p-4, 0x1.44fe3723f8aabp-4, 0x1.e7318cbf5717ap-4, 0x1.2980be9ad5084p-5, + 0x1.861fa44fbfd75p-15, 0x1.b6ed351d3aea4p-6, -0x1.1c86cbfb2d216p-3, 0x1.ff4f02347b2ffp-9, + -0x1.dcc4ce5ea308ap-15, -0x1.046f40436f6f6p-5, -0x1.b203eb83b684ap-5, 0x1.449d4fc820064p-6, + -0x1.7dfe28aabf859p-3, -0x1.3ed929013d192p-7, -0x1.e2842a0ae110bp-7, 0x1.b2ae145a081c2p-7, + 0x1.1281682e2a73bp-5, -0x1.81b06609dd909p-6, 0x1.64dac8302d282p-5, 0x1.1167376458118p-2, + 0x1.12df39b629f00p-8, -0x1.fd70fe001d555p-5, 0x1.cae471fc36e18p-7, -0x1.05f6933677138p-4, + 0x1.a9bc53d9a070dp-9, 0x1.4396b5c8bbd48p-4, 0x1.35ed9085b7af7p-4, -0x1.5e11bec9ab540p-4, + 0x1.5e11bec9ab540p-4, -0x1.35ed9085b7af7p-4, -0x1.4396b5c8bbd48p-4, -0x1.a9bc53d9a070dp-9, + 0x1.05f6933677138p-4, -0x1.cae471fc36e18p-7, 0x1.fd70fe001d555p-5, -0x1.12df39b629f00p-8, + -0x1.1167376458118p-2, -0x1.64dac8302d282p-5, 0x1.81b06609dd909p-6, -0x1.1281682e2a73bp-5, + -0x1.b2ae145a081c2p-7, 0x1.e2842a0ae110bp-7, 0x1.3ed929013d192p-7, 0x1.7dfe28aabf859p-3, + -0x1.449d4fc820064p-6, 0x1.b203eb83b684ap-5, 0x1.046f40436f6f6p-5, 0x1.dcc4ce5ea308ap-15, + -0x1.ff4f02347b2ffp-9, 0x1.1c86cbfb2d216p-3, -0x1.b6ed351d3aea4p-6, -0x1.861fa44fbfd75p-15, + -0x1.2980be9ad5084p-5, -0x1.e7318cbf5717ap-4, -0x1.44fe3723f8aabp-4, 0x1.ae585937958f4p-4, + 0x1.80db57a300a54p-4, -0x1.8626e551364dap-4, -0x1.88eaa637c6571p-3, 0x1.3f858f948abf8p-5, + -0x1.4975b47c573c5p-6, 0x1.119c2d4e29c98p-5, 0x1.d2d8fe41dc44dp-4, -0x1.4ba27e40aeedbp-6, + -0x1.f96f52403e87fp-4, -0x1.3d440c35997d9p-7, -0x1.0db43ed126905p-3, 0x1.72278d87c6b0fp-5, + -0x1.4773033fb9c28p-3, 0x1.01aefdb9689e0p-3, -0x1.f66494770391dp-5, -0x1.01f35484f6459p-4, + 0x1.96ac12066235dp-6, -0x1.ee98ed372c078p-3, -0x1.077e537b0fe31p-5, -0x1.2a57eeacfe51dp-3, + -0x1.2ea2ec00d408dp-6, -0x1.56586dfb00770p-4, -0x1.441ab75c5bf89p-7, 0x1.58c1162f8a27cp-4, + 0x1.36173cec5b5fcp-8, -0x1.0621e485a2c2ap-4, 0x1.883f08ffbdaa4p-8, 0x1.49c920ceb8ca3p-5, + 0x1.0a366f2abbd80p-3, -0x1.4b46e2db45950p-5, -0x1.f2ef3bb93dc28p-6, 0x1.2ddff25b8f8c0p-7, + 0x1.da139564d3b07p-4, 0x1.2d42fa7a4017ap-7, -0x1.01c38d9bad64ep-3, -0x1.a55e469fd6e6ep-8, + -0x1.139f0d009042dp-6, -0x1.fb5797da026ebp-4, 0x1.9372a94a17d6ap-5, 0x1.d696161bedfc4p-4, + -0x1.3fed94692459cp-4, -0x1.8fbccaf9301fep-4, 0x1.9ef43cf053eabp-4, 0x1.2bedb10c777bbp-4, + -0x1.dfeae6d6a79e9p-4, -0x1.64c7df5a49d3cp-5, 0x1.fe1caebd53319p-4, 0x1.5f6d03460f669p-7, + -0x1.f75999f1e8190p-4, 0x1.76dd9d97a40c0p-6, 0x1.cc1f139be6bfep-4, -0x1.c124970728566p-5, + -0x1.7f8ed03831662p-4, 0x1.532827ed04730p-4, 0x1.1734d571aba58p-4, -0x1.ad2bca342e601p-4, + -0x1.35410deac627cp-5, 0x1.e817b8b39d35bp-4, 0x1.2d8647bacb558p-8, -0x1.ffa72d7ebb133p-4, + 0x1.d934fc54b64abp-6, 0x1.f2252e1b696bdp-4, -0x1.edc1972273c8fp-5, -0x1.c08c40b5cf9b4p-4, + 0x1.65919430e2182p-4, 0x1.6e7446587256cp-4, -0x1.ba5aa680b715cp-4, -0x1.01cfc7dff9e90p-4, + 0x1.ef178b5db50fbp-4, 0x1.04fb81c85b4d4p-5, -0x1.fff6241f4ec15p-4, 0x1.921d0ed3fae63p-10, + 0x1.ebbd8e6e1ba8ap-4, -0x1.1d343fa224932p-5, -0x1.b3e4d295c19cap-4, 0x1.0c9703741e320p-4, + 0x1.5c77bb2537ed5p-4, -0x1.771e752e23f70p-4, -0x1.d7977806e3850p-5, 0x1.c678b12e6ade0p-4, + 0x1.a82a0b2a291b4p-6, -0x1.f4e60347be255p-4, 0x1.f656e2d232d2ep-8, 0x1.ff0957c6c4e0bp-4, + -0x1.4d1e21b8bc6e3p-5, -0x1.e426a0d3bbb60p-4, 0x1.21a799c966594p-4, 0x1.a63090523ecafp-4, + -0x1.87c4022be638dp-4, -0x1.49a44e709d6c8p-4, 0x1.d17e77f097202p-4, 0x1.aa6c806a4a5a6p-5, + -0x1.f97f9195c5665p-4, -0x1.4557635841b47p-6, 0x1.fce1616766a07p-4, -0x1.c3786a2feef74p-7, + -0x1.db65286d12f14p-4, 0x1.7c3a9240fbe63p-5, 0x1.9777ef328a989p-4, -0x1.360589f770145p-4, + -0x1.360589f770145p-4, 0x1.9777ef328a989p-4, 0x1.7c3a9240fbe63p-5, -0x1.db65286d12f14p-4, + -0x1.c3786a2feef74p-7, 0x1.fce1616766a07p-4, -0x1.4557635841b47p-6, -0x1.f97f9195c5665p-4, + 0x1.aa6c806a4a5a6p-5, 0x1.d17e77f097202p-4, -0x1.49a44e709d6c8p-4, -0x1.87c4022be638dp-4, + 0x1.a63090523ecafp-4, 0x1.21a799c966594p-4, -0x1.e426a0d3bbb60p-4, -0x1.4d1e21b8bc6e3p-5, + 0x1.ff0957c6c4e0bp-4, 0x1.f656e2d232d2ep-8, -0x1.f4e60347be255p-4, 0x1.a82a0b2a291b4p-6, + 0x1.c678b12e6ade0p-4, -0x1.d7977806e3850p-5, -0x1.771e752e23f70p-4, 0x1.5c77bb2537ed5p-4, + 0x1.0c9703741e320p-4, -0x1.b3e4d295c19cap-4, -0x1.1d343fa224932p-5, 0x1.ebbd8e6e1ba8ap-4, + 0x1.921d0ed3fae63p-10, -0x1.fff6241f4ec15p-4, 0x1.04fb81c85b4d4p-5, 0x1.ef178b5db50fbp-4, + -0x1.01cfc7dff9e90p-4, -0x1.ba5aa680b715cp-4, 0x1.6e7446587256cp-4, 0x1.65919430e2182p-4, + -0x1.c08c40b5cf9b4p-4, -0x1.edc1972273c8fp-5, 0x1.f2252e1b696bdp-4, 0x1.d934fc54b64abp-6, + -0x1.ffa72d7ebb133p-4, 0x1.2d8647bacb558p-8, 0x1.e817b8b39d35bp-4, -0x1.35410deac627cp-5, + -0x1.ad2bca342e601p-4, 0x1.1734d571aba58p-4, 0x1.532827ed04730p-4, -0x1.7f8ed03831662p-4, + -0x1.c124970728566p-5, 0x1.cc1f139be6bfep-4, 0x1.76dd9d97a40c0p-6, -0x1.f75999f1e8190p-4, + 0x1.5f6d03460f669p-7, 0x1.fe1caebd53319p-4, -0x1.64c7df5a49d3cp-5, -0x1.dfeae6d6a79e9p-4, + 0x1.2bedb10c777bbp-4, 0x1.9ef43cf053eabp-4, -0x1.8fbccaf9301fep-4, -0x1.3fed94692459cp-4, + 0x1.d696161bedfc4p-4, 0x1.9372a94a17d6ap-5, -0x1.fb5797da026f7p-4, -0x1.139f0d0090429p-6, + 0x1.fb57966a41484p-4, -0x1.139f0d058641ep-6, 0x1.d6961768f6ad9p-4, -0x1.9372a9b5cda44p-5, + 0x1.8fbccb2d460c3p-4, -0x1.3fed93a927916p-4, 0x1.2bedb1970c7e7p-4, -0x1.9ef43d5d0135ep-4, + 0x1.64c7df3479844p-5, -0x1.dfeae7a97011ap-4, 0x1.5f6d02f0cb62bp-7, -0x1.fe1caece9940ep-4, + -0x1.76dd9cc5c665dp-6, -0x1.f75999d449163p-4, -0x1.c12496cf16407p-5, -0x1.cc1f12e8417d9p-4, + -0x1.532827a7d93abp-4, -0x1.7f8ecf6a365bep-4, -0x1.ad2bc9b69beb7p-4, -0x1.1734d5bba504ap-4, + -0x1.e817b8adc50f9p-4, -0x1.35410d6514013p-5, -0x1.ffa72c6c95727p-4, -0x1.2d86475d09722p-8, + -0x1.f2252edbdef22p-4, 0x1.d934fdf65addep-6, -0x1.c08c413aa9390p-4, 0x1.edc197f3da54ap-5, + -0x1.6e7446d953d88p-4, 0x1.659193c932437p-4, -0x1.01cfc724a9c14p-4, 0x1.ba5aa7f7c0e2cp-4, + -0x1.04fb81d2dc1c0p-5, 0x1.ef178b71c450dp-4, 0x1.921d0f99198aap-10, 0x1.fff62330299adp-4, + 0x1.1d343f79e1bc9p-5, 0x1.ebbd8f4312c54p-4, 0x1.0c9703ef1b3eap-4, 0x1.b3e4d391f47e5p-4, + 0x1.771e753c13719p-4, 0x1.5c77bb201bb7cp-4, 0x1.c678b1c7bb832p-4, 0x1.d79776bf5a724p-5, + 0x1.f4e6034916988p-4, 0x1.a82a0aef887a3p-6, 0x1.ff095799538e7p-4, -0x1.f656e3f9914ccp-8, + 0x1.e426a0b44b537p-4, -0x1.4d1e208c0981dp-5, 0x1.a63091d23d197p-4, -0x1.21a799365d634p-4, + 0x1.49a44dbe2c0c3p-4, -0x1.87c400b571551p-4, 0x1.aa6c8086bff59p-5, -0x1.d17e769c53a2bp-4, + 0x1.4557631ca621ep-6, -0x1.f97f9178b431cp-4, -0x1.c378688c71d5dp-7, -0x1.fce161e857c39p-4, + -0x1.7c3a935fc6282p-5, -0x1.db6528f744e4fp-4, -0x1.360589741efcdp-4, -0x1.9777ef0640ac9p-4, + -0x1.9777ef0640ac9p-4, -0x1.360589741efcdp-4, -0x1.db6528f744e4fp-4, -0x1.7c3a935fc6282p-5, + -0x1.fce161e857c39p-4, -0x1.c378688c71d5dp-7, -0x1.f97f9178b431cp-4, 0x1.4557631ca621ep-6, + -0x1.d17e769c53a2bp-4, 0x1.aa6c8086bff59p-5, -0x1.87c400b571551p-4, 0x1.49a44dbe2c0c3p-4, + -0x1.21a799365d634p-4, 0x1.a63091d23d197p-4, -0x1.4d1e208c0981dp-5, 0x1.e426a0b44b537p-4, + -0x1.f656e3f9914ccp-8, 0x1.ff095799538e7p-4, 0x1.a82a0aef887a3p-6, 0x1.f4e6034916988p-4, + 0x1.d79776bf5a724p-5, 0x1.c678b1c7bb832p-4, 0x1.5c77bb201bb7cp-4, 0x1.771e753c13719p-4, + 0x1.b3e4d391f47e5p-4, 0x1.0c9703ef1b3eap-4, 0x1.ebbd8f4312c54p-4, 0x1.1d343f79e1bc9p-5, + 0x1.fff62330299adp-4, 0x1.921d0f99198aap-10, 0x1.ef178b71c450dp-4, -0x1.04fb81d2dc1c0p-5, + 0x1.ba5aa7f7c0e2cp-4, -0x1.01cfc724a9c14p-4, 0x1.659193c932437p-4, -0x1.6e7446d953d88p-4, + 0x1.edc197f3da54ap-5, -0x1.c08c413aa9390p-4, 0x1.d934fdf65addep-6, -0x1.f2252edbdef22p-4, + -0x1.2d86475d09722p-8, -0x1.ffa72c6c95727p-4, -0x1.35410d6514013p-5, -0x1.e817b8adc50f9p-4, + -0x1.1734d5bba504ap-4, -0x1.ad2bc9b69beb7p-4, -0x1.7f8ecf6a365bep-4, -0x1.532827a7d93abp-4, + -0x1.cc1f12e8417d9p-4, -0x1.c12496cf16407p-5, -0x1.f75999d449163p-4, -0x1.76dd9cc5c665dp-6, + -0x1.fe1caece9940ep-4, 0x1.5f6d02f0cb62bp-7, -0x1.dfeae7a97011ap-4, 0x1.64c7df3479844p-5, + -0x1.9ef43d5d0135ep-4, 0x1.2bedb1970c7e7p-4, -0x1.3fed93a927916p-4, 0x1.8fbccb2d460c3p-4, + -0x1.9372a9b5cda44p-5, 0x1.d6961768f6ad9p-4, -0x1.139f0d058641dp-6, 0x1.fb57966a4145bp-4, + 0x1.45829a29dfebap-6, -0x1.12a271a960ba0p-8, 0x1.09e9c9c46b374p-3, -0x1.0c8dbf764f2eep-5, + 0x1.6a2704f794774p-4, -0x1.c8913996a4903p-5, 0x1.43fc26b11c07cp-4, 0x1.2030bbace74a2p-4, + -0x1.9d5e490ebc4cep-5, -0x1.1fc4047e3028bp-3, -0x1.41491832d80b7p-8, 0x1.45b42a334daa3p-3, + -0x1.2be8aaba95224p-5, 0x1.b4b99000dbdb0p-4, -0x1.12bc9ee6066a8p-4, 0x1.866aac336b200p-6, + -0x1.8ed2aecc1dc31p-5, -0x1.5cd6521f77712p-7, 0x1.5c67c99886239p-3, -0x1.87ab681153a1ap-4, + 0x1.706a2c5276e08p-3, -0x1.c9178f593bb62p-6, 0x1.dda985cbf89cfp-8, -0x1.7ae730482ffbbp-9, + -0x1.861cc153074c3p-3, 0x1.6ff817bc97c9ap-8, 0x1.8d4ec5678b31ep-9, -0x1.3a5707b32a40bp-6, + -0x1.52082d442a54dp-3, -0x1.6800503a41faep-3, -0x1.047db3c14bc13p-5, -0x1.1ee2a0139e07bp-4, + -0x1.7634479d80ff0p-5, -0x1.240a1db6a877dp-3, 0x1.4e3e900abae5fp-9, 0x1.8bbea595e16c0p-5, + -0x1.b96de73cac1d5p-8, 0x1.2368c26958b3dp-5, 0x1.7d7c886770110p-5, 0x1.07bb04547b1dcp-4, + 0x1.0589813c24fc2p-6, 0x1.2d4458360c1d6p-3, 0x1.6f0e21656c9d9p-4, -0x1.859616ccc3e73p-4, + 0x1.2077b29479f83p-5, -0x1.8927ea5af6d07p-7, 0x1.ea2eccfbb15c0p-4, -0x1.f81e0eda1a5b8p-8, + -0x1.16e6c24114dcdp-3, -0x1.f4443436fb1a9p-7, -0x1.aa7f9935949c9p-8, -0x1.e66623d087d27p-5, + -0x1.241532cbb0993p-3, 0x1.0628444847dc2p-6, 0x1.1afa14136305fp-6, -0x1.8ef868f137ef1p-4, + 0x1.16b419707d5a6p-5, -0x1.1685e1f246127p-3, 0x1.1ff7583d79a83p-8, 0x1.b6125229aded2p-4, + 0x1.57993a1ce7b77p-10, 0x1.835c705b6e11dp-3, 0x1.9fd64027a936ap-4, 0x1.9ff9ed342b98dp-5, + 0x1.9ff9ed342b98dp-5, 0x1.9fd64027a936ap-4, 0x1.835c705b6e11dp-3, 0x1.57993a1ce7b77p-10, + 0x1.b6125229aded2p-4, 0x1.1ff7583d79a83p-8, -0x1.1685e1f246127p-3, 0x1.16b419707d5a6p-5, + -0x1.8ef868f137ef1p-4, 0x1.1afa14136305fp-6, 0x1.0628444847dc2p-6, -0x1.241532cbb0993p-3, + -0x1.e66623d087d27p-5, -0x1.aa7f9935949c9p-8, -0x1.f4443436fb1a9p-7, -0x1.16e6c24114dcdp-3, + -0x1.f81e0eda1a5b8p-8, 0x1.ea2eccfbb15c0p-4, -0x1.8927ea5af6d07p-7, 0x1.2077b29479f83p-5, + -0x1.859616ccc3e73p-4, 0x1.6f0e21656c9d9p-4, 0x1.2d4458360c1d6p-3, 0x1.0589813c24fc2p-6, + 0x1.07bb04547b1dcp-4, 0x1.7d7c886770110p-5, 0x1.2368c26958b3dp-5, -0x1.b96de73cac1d5p-8, + 0x1.8bbea595e16c0p-5, 0x1.4e3e900abae5fp-9, -0x1.240a1db6a877dp-3, -0x1.7634479d80ff0p-5, + -0x1.1ee2a0139e07bp-4, -0x1.047db3c14bc13p-5, -0x1.6800503a41faep-3, -0x1.52082d442a54dp-3, + -0x1.3a5707b32a40bp-6, 0x1.8d4ec5678b31ep-9, 0x1.6ff817bc97c9ap-8, -0x1.861cc153074c3p-3, + -0x1.7ae730482ffbbp-9, 0x1.dda985cbf89cfp-8, -0x1.c9178f593bb62p-6, 0x1.706a2c5276e08p-3, + -0x1.87ab681153a1ap-4, 0x1.5c67c99886239p-3, -0x1.5cd6521f77712p-7, -0x1.8ed2aecc1dc31p-5, + 0x1.866aac336b200p-6, -0x1.12bc9ee6066a8p-4, 0x1.b4b99000dbdb0p-4, -0x1.2be8aaba95224p-5, + 0x1.45b42a334daa3p-3, -0x1.41491832d80b7p-8, -0x1.1fc4047e3028bp-3, -0x1.9d5e490ebc4cep-5, + 0x1.2030bbace74a2p-4, 0x1.43fc26b11c07ap-4, -0x1.c8913996a4901p-5, 0x1.6a2704f794778p-4, + -0x1.0c8dbf764f2f2p-5, 0x1.09e9c9c46b379p-3, -0x1.12a27168f932fp-8, 0x1.458299cbc2441p-6, + -0x1.062a53f209365p-5, 0x1.1b867f6b0bd87p-6, -0x1.87cf4085d5483p-6, 0x1.233c8fe3090d7p-5, + 0x1.868b54a314accp-4, -0x1.112db3ec4e66fp-4, 0x1.1499ee48767ecp-4, 0x1.a5005c3c2901fp-6, + -0x1.b215e3008adc5p-4, -0x1.a58ad273341a2p-9, 0x1.58d65304d2170p-3, -0x1.6ab4686ef47c3p-8, + 0x1.9007d268929b8p-6, 0x1.d602b87a45fd0p-8, 0x1.aa8bd89d69e2fp-4, -0x1.1f2803d9c6ecbp-4, + 0x1.0dc086d992c04p-3, -0x1.990cc4805d69dp-5, -0x1.db7e5bd674c8dp-6, 0x1.4b579a7852194p-3, + 0x1.7c69c607f341fp-5, 0x1.83927d929fbadp-7, 0x1.09e6b11832633p-8, 0x1.468c2cb528c28p-3, + 0x1.41ad1b345c231p-4, -0x1.ac547d99d0895p-8, 0x1.c1d8db9ee1869p-7, -0x1.4ede8d836e0b4p-3, + -0x1.b83752e5fb00ep-4, 0x1.1490f027d39c1p-3, -0x1.0225193694d42p-2, -0x1.628b557563a14p-5, + -0x1.beb648f4b3521p-4, 0x1.6a4243b77c083p-6, 0x1.a679f95476c50p-3, -0x1.2ec7ac25f2f2ep-7, + -0x1.d536664bbad83p-5, 0x1.e59256e05580bp-6, -0x1.dfc2b2092c8b7p-3, 0x1.ddc038bfaabadp-5, + 0x1.2cc361be0b731p-7, 0x1.f60def25ffe33p-5, 0x1.b00ee886a39bfp-4, 0x1.e4440aa06bf41p-5, + 0x1.d2fa8fcbdd8f4p-8, 0x1.25d8c196acdc0p-7, -0x1.e1b278ef25fe1p-7, -0x1.14cd15d46e0c6p-4, + 0x1.8d9801e961960p-6, -0x1.d03ec011f999fp-5, -0x1.2e90594ea37ccp-7, 0x1.a43db93d71299p-4, + 0x1.39fbb576971b0p-4, 0x1.0ce65b8e16d23p-3, 0x1.0021b44248432p-4, -0x1.10b51ae1f8fecp-5, + 0x1.984aa5f7427f6p-4, 0x1.61b8926a86c21p-6, -0x1.09b665e0ad5d9p-3, 0x1.01e2017d033adp-7, + -0x1.9cb5a2285df25p-11, 0x1.5c25b23245b0ap-4, 0x1.07d52cbc8c889p-5, 0x1.a771bfd5978b8p-7, + 0x1.a771bfd5978b8p-7, 0x1.07d52cbc8c889p-5, 0x1.5c25b23245b0ap-4, -0x1.9cb5a2285df25p-11, + 0x1.01e2017d033adp-7, -0x1.09b665e0ad5d9p-3, 0x1.61b8926a86c21p-6, 0x1.984aa5f7427f6p-4, + -0x1.10b51ae1f8fecp-5, 0x1.0021b44248432p-4, 0x1.0ce65b8e16d23p-3, 0x1.39fbb576971b0p-4, + 0x1.a43db93d71299p-4, -0x1.2e90594ea37ccp-7, -0x1.d03ec011f999fp-5, 0x1.8d9801e961960p-6, + -0x1.14cd15d46e0c6p-4, -0x1.e1b278ef25fe1p-7, 0x1.25d8c196acdc0p-7, 0x1.d2fa8fcbdd8f4p-8, + 0x1.e4440aa06bf41p-5, 0x1.b00ee886a39bfp-4, 0x1.f60def25ffe33p-5, 0x1.2cc361be0b731p-7, + 0x1.ddc038bfaabadp-5, -0x1.dfc2b2092c8b7p-3, 0x1.e59256e05580bp-6, -0x1.d536664bbad83p-5, + -0x1.2ec7ac25f2f2ep-7, 0x1.a679f95476c50p-3, 0x1.6a4243b77c083p-6, -0x1.beb648f4b3521p-4, + -0x1.628b557563a14p-5, -0x1.0225193694d42p-2, 0x1.1490f027d39c1p-3, -0x1.b83752e5fb00ep-4, + -0x1.4ede8d836e0b4p-3, 0x1.c1d8db9ee1869p-7, -0x1.ac547d99d0895p-8, 0x1.41ad1b345c231p-4, + 0x1.468c2cb528c28p-3, 0x1.09e6b11832633p-8, 0x1.83927d929fbadp-7, 0x1.7c69c607f341fp-5, + 0x1.4b579a7852194p-3, -0x1.db7e5bd674c8dp-6, -0x1.990cc4805d69dp-5, 0x1.0dc086d992c04p-3, + -0x1.1f2803d9c6ecbp-4, 0x1.aa8bd89d69e2fp-4, 0x1.d602b87a45fd0p-8, 0x1.9007d268929b8p-6, + -0x1.6ab4686ef47c3p-8, 0x1.58d65304d2170p-3, -0x1.a58ad273341a2p-9, -0x1.b215e3008adc5p-4, + 0x1.a5005c3c2902dp-6, 0x1.1499ee48767eep-4, -0x1.112db3ec4e66cp-4, 0x1.868b54a314acdp-4, + 0x1.233c8fe3090d2p-5, -0x1.87cf4085d5488p-6, 0x1.1b868d82c21c2p-6, -0x1.062a53dafb731p-5, + -0x1.45576d5313ed0p-6, -0x1.f97f93d01c287p-4, 0x1.d79775156517ap-5, 0x1.c678b29ce9bfcp-4, + -0x1.6e7444d9e6973p-4, -0x1.6591922932fd8p-4, 0x1.cc1f0d7d0b433p-4, 0x1.c1249c51585c2p-5, + -0x1.fb5796f28e31cp-4, -0x1.139f0c5c1b8c4p-6, 0x1.f7599be3defe1p-4, -0x1.76dd9e8586eefp-6, + -0x1.c08c4352a7c47p-4, 0x1.edc1972bacedep-5, 0x1.5c77bc7f7bb2dp-4, -0x1.771e7763614f6p-4, + -0x1.aa6c833f6f23bp-5, 0x1.d17e76518bb28p-4, 0x1.c3785da60e894p-7, -0x1.fce15e83c9918p-4, + 0x1.a82a011c44a2dp-6, 0x1.f4e6040a616aap-4, -0x1.01cfc818914c4p-4, -0x1.ba5aa4872d74fp-4, + 0x1.7f8ecce1bf245p-4, 0x1.532827d7ee48cp-4, -0x1.d69618c8ff82bp-4, -0x1.9372a813a0aa3p-5, + 0x1.fe1caf886aa61p-4, 0x1.5f6d035822eb7p-7, -0x1.f2252f5ec3489p-4, 0x1.d935041b05645p-6, + 0x1.b3e4d4bebfa81p-4, -0x1.0c97042cf0b4bp-4, -0x1.49a44b55a522fp-4, 0x1.87c3ffb747b9bp-4, + 0x1.7c3a91b6a9703p-5, -0x1.db6527d3578c8p-4, -0x1.f656f82a101a9p-8, 0x1.ff09588ccada6p-4, + -0x1.04fb80354cd00p-5, -0x1.ef178a53ff36dp-4, 0x1.1734d4c4a2719p-4, 0x1.ad2bc9647c297p-4, + -0x1.8fbcc8354394dp-4, -0x1.3fed96b0bf0a8p-4, 0x1.dfeae69d695e4p-4, 0x1.64c7df5884049p-5, + -0x1.ffa72f1154f43p-4, -0x1.2d865760e2720p-8, 0x1.ebbd8d3262b1dp-4, -0x1.1d344434167d7p-5, + -0x1.a630919b62f0cp-4, 0x1.21a798a775214p-4, 0x1.3605882fdd029p-4, -0x1.9777f13f38693p-4, + -0x1.4d1e215fa08b7p-5, 0x1.e426a21314082p-4, 0x1.921ce0ff6c15ap-10, -0x1.fff6229786040p-4, + 0x1.354107806abecp-5, 0x1.e817b9b4bf800p-4, -0x1.2bedb1be6f089p-4, -0x1.9ef4415b6f23ap-4, + 0x1.9ef4415b6f23ap-4, 0x1.2bedb1be6f089p-4, -0x1.e817b9b4bf800p-4, -0x1.354107806abecp-5, + 0x1.fff6229786040p-4, -0x1.921ce0ff6c15ap-10, -0x1.e426a21314082p-4, 0x1.4d1e215fa08b7p-5, + 0x1.9777f13f38693p-4, -0x1.3605882fdd029p-4, -0x1.21a798a775214p-4, 0x1.a630919b62f0cp-4, + 0x1.1d344434167d7p-5, -0x1.ebbd8d3262b1dp-4, 0x1.2d865760e2720p-8, 0x1.ffa72f1154f43p-4, + -0x1.64c7df5884049p-5, -0x1.dfeae69d695e4p-4, 0x1.3fed96b0bf0a8p-4, 0x1.8fbcc8354394dp-4, + -0x1.ad2bc9647c297p-4, -0x1.1734d4c4a2719p-4, 0x1.ef178a53ff36dp-4, 0x1.04fb80354cd00p-5, + -0x1.ff09588ccada6p-4, 0x1.f656f82a101a9p-8, 0x1.db6527d3578c8p-4, -0x1.7c3a91b6a9703p-5, + -0x1.87c3ffb747b9bp-4, 0x1.49a44b55a522fp-4, 0x1.0c97042cf0b4bp-4, -0x1.b3e4d4bebfa81p-4, + -0x1.d935041b05645p-6, 0x1.f2252f5ec3489p-4, -0x1.5f6d035822eb7p-7, -0x1.fe1caf886aa61p-4, + 0x1.9372a813a0aa3p-5, 0x1.d69618c8ff82bp-4, -0x1.532827d7ee48cp-4, -0x1.7f8ecce1bf245p-4, + 0x1.ba5aa4872d74fp-4, 0x1.01cfc818914c4p-4, -0x1.f4e6040a616aap-4, -0x1.a82a011c44a2dp-6, + 0x1.fce15e83c9918p-4, -0x1.c3785da60e894p-7, -0x1.d17e76518bb28p-4, 0x1.aa6c833f6f23bp-5, + 0x1.771e7763614f6p-4, -0x1.5c77bc7f7bb2dp-4, -0x1.edc1972bacedep-5, 0x1.c08c4352a7c47p-4, + 0x1.76dd9e8586eefp-6, -0x1.f7599be3defe1p-4, 0x1.139f0c5c1b8c4p-6, 0x1.fb5796f28e31cp-4, + -0x1.c1249c51585c2p-5, -0x1.cc1f0d7d0b433p-4, 0x1.6591922932fd8p-4, 0x1.6e7444d9e6973p-4, + -0x1.c678b29ce9bfcp-4, -0x1.d79775156517ap-5, 0x1.f97f93d01c299p-4, 0x1.45576d5313ed0p-6, + 0x1.f97f93fea7176p-4, -0x1.45576c3a43e43p-6, 0x1.c678b222ea5e2p-4, -0x1.d79774e48aafbp-5, + 0x1.659192c9cc014p-4, -0x1.6e7443cd59486p-4, 0x1.c1249d03449fep-5, -0x1.cc1f0e68b841ep-4, + 0x1.139f0be8417ecp-6, -0x1.fb57961dfab16p-4, -0x1.76dd9eadcfda4p-6, -0x1.f7599d67ec93cp-4, + -0x1.edc1976a4b7cep-5, -0x1.c08c425c8c2acp-4, -0x1.771e76ccf553dp-4, -0x1.5c77bbe48979bp-4, + -0x1.d17e7594a1921p-4, -0x1.aa6c8442d161ep-5, -0x1.fce15eef88902p-4, -0x1.c3785d2288ebcp-7, + -0x1.f4e604437777ep-4, 0x1.a82a0093ef8bep-6, -0x1.ba5aa4776967ap-4, 0x1.01cfc89eeb6c1p-4, + -0x1.5328286d5ae0fp-4, 0x1.7f8ecd235b926p-4, -0x1.9372a8185998dp-5, 0x1.d69618a4ff85dp-4, + -0x1.5f6d04298ee13p-7, 0x1.fe1caf1a13f78p-4, 0x1.d93503b764540p-6, 0x1.f2252e7ae5449p-4, + 0x1.0c9704c6c9babp-4, 0x1.b3e4d3a484e44p-4, 0x1.87c4005032d70p-4, 0x1.49a44cbc15faep-4, + 0x1.db652914e0eafp-4, 0x1.7c3a924a15c7ep-5, 0x1.ff0958c3f5183p-4, 0x1.f656f9f258d26p-8, + 0x1.ef178ab91cf54p-4, -0x1.04fb8089f4c26p-5, 0x1.ad2bc90b51117p-4, -0x1.1734d41f6e9acp-4, + 0x1.3fed95e07d572p-4, -0x1.8fbcc90c06356p-4, 0x1.64c7de36b8c7cp-5, -0x1.dfeae5dbc8a0dp-4, + 0x1.2d865731d0bcdp-8, -0x1.ffa72e295942fp-4, -0x1.1d3443f008abbp-5, -0x1.ebbd8cc89c420p-4, + -0x1.21a798562f740p-4, -0x1.a63091f052339p-4, -0x1.9777f058c1825p-4, -0x1.360588adccd79p-4, + -0x1.e426a1f613f41p-4, -0x1.4d1e21d54f720p-5, -0x1.fff6237b497f1p-4, -0x1.921ce4c51c739p-10, + -0x1.e817babffdf05p-4, 0x1.3541088184a63p-5, -0x1.9ef44078d2b9fp-4, 0x1.2bedb22fdfb97p-4, + -0x1.2bedb22fdfb97p-4, 0x1.9ef44078d2b9fp-4, -0x1.3541088184a63p-5, 0x1.e817babffdf05p-4, + 0x1.921ce4c51c739p-10, 0x1.fff6237b497f1p-4, 0x1.4d1e21d54f720p-5, 0x1.e426a1f613f41p-4, + 0x1.360588adccd79p-4, 0x1.9777f058c1825p-4, 0x1.a63091f052339p-4, 0x1.21a798562f740p-4, + 0x1.ebbd8cc89c420p-4, 0x1.1d3443f008abbp-5, 0x1.ffa72e295942fp-4, -0x1.2d865731d0bcdp-8, + 0x1.dfeae5dbc8a0dp-4, -0x1.64c7de36b8c7cp-5, 0x1.8fbcc90c06356p-4, -0x1.3fed95e07d572p-4, + 0x1.1734d41f6e9acp-4, -0x1.ad2bc90b51117p-4, 0x1.04fb8089f4c26p-5, -0x1.ef178ab91cf54p-4, + -0x1.f656f9f258d26p-8, -0x1.ff0958c3f5183p-4, -0x1.7c3a924a15c7ep-5, -0x1.db652914e0eafp-4, + -0x1.49a44cbc15faep-4, -0x1.87c4005032d70p-4, -0x1.b3e4d3a484e44p-4, -0x1.0c9704c6c9babp-4, + -0x1.f2252e7ae5449p-4, -0x1.d93503b764540p-6, -0x1.fe1caf1a13f78p-4, 0x1.5f6d04298ee13p-7, + -0x1.d69618a4ff85dp-4, 0x1.9372a8185998dp-5, -0x1.7f8ecd235b926p-4, 0x1.5328286d5ae0fp-4, + -0x1.01cfc89eeb6c1p-4, 0x1.ba5aa4776967ap-4, -0x1.a82a0093ef8bep-6, 0x1.f4e604437777ep-4, + 0x1.c3785d2288ebcp-7, 0x1.fce15eef88902p-4, 0x1.aa6c8442d161ep-5, 0x1.d17e7594a1921p-4, + 0x1.5c77bbe48979bp-4, 0x1.771e76ccf553dp-4, 0x1.c08c425c8c2acp-4, 0x1.edc1976a4b7cep-5, + 0x1.f7599d67ec93cp-4, 0x1.76dd9eadcfda4p-6, 0x1.fb57961dfab16p-4, -0x1.139f0be8417ecp-6, + 0x1.cc1f0e68b841ep-4, -0x1.c1249d03449fep-5, 0x1.6e7443cd59486p-4, -0x1.659192c9cc014p-4, + 0x1.d79774e48aafbp-5, -0x1.c678b222ea5e2p-4, 0x1.45576c3a43e45p-6, -0x1.f97f93fea7153p-4, + -0x1.8d119eb0aa74bp-4, -0x1.fe78c175aa1e6p-13, 0x1.28005f595b13bp-3, 0x1.9e201bddf084dp-5, + -0x1.e6c5470d210f4p-4, -0x1.4979c42283612p-3, -0x1.41e429a6b1efdp-5, 0x1.72309a8681fc5p-3, + -0x1.0d513e5734fd6p-7, -0x1.2807886765685p-5, 0x1.f9cf50c26f386p-8, -0x1.bb62315b69811p-5, + -0x1.1d995f2ea0ad6p-6, -0x1.8f28bcb9ee3d3p-3, 0x1.08272332ab8f4p-3, 0x1.75e3692f3b200p-7, + 0x1.364ebf39294f9p-6, -0x1.0f5190e4a65f6p-5, -0x1.e8c4ca7b93a7fp-4, 0x1.270cc0a032e54p-7, + 0x1.3b18afcde4afep-4, 0x1.895b5a15093ecp-6, -0x1.11a0cdd3c3098p-3, 0x1.a5b22ccd18e49p-5, + 0x1.1d73c46cef749p-4, -0x1.f999137036557p-6, -0x1.026d191129d8bp-5, 0x1.73560aac6f429p-3, + -0x1.fa6083af91918p-10, 0x1.f1a76fd89d4bcp-8, 0x1.2bba19c041b3ap-5, -0x1.3da6fc0aa650bp-5, + 0x1.1ecc333ff78cdp-5, -0x1.b8ba0c1641f47p-4, -0x1.c293b2afbed43p-4, 0x1.b739788c263dep-6, + -0x1.5087164f4d7d0p-4, -0x1.1fc90e483694fp-7, -0x1.7bdd32fe55c73p-5, -0x1.3a5a8c9c8f410p-6, + -0x1.3787cb865a60dp-3, 0x1.de80830d072edp-5, -0x1.8b06cba2d58dap-5, -0x1.8845011a66d8ep-4, + 0x1.435a9086269b4p-3, 0x1.5db9e6baf8150p-4, 0x1.0548844a2883fp-4, -0x1.fb092a71f0342p-4, + 0x1.4e20f2751d66ep-7, -0x1.99dd9279f3a0fp-3, 0x1.44a9ea550bd30p-5, 0x1.6293761db90acp-7, + 0x1.b133be2cca906p-4, -0x1.5427b7920d992p-4, 0x1.421e421f43ba1p-4, 0x1.80f61e7fbe657p-7, + 0x1.0694bd374c878p-3, -0x1.27707f261dedep-6, -0x1.286e15e403188p-6, 0x1.adbcc2d508efep-8, + -0x1.bd19177406e74p-4, -0x1.66302d105d040p-5, 0x1.09446859b076dp-3, -0x1.927a0c6cb684cp-4, + 0x1.927a0c6cb684cp-4, -0x1.09446859b076dp-3, 0x1.66302d105d040p-5, 0x1.bd19177406e74p-4, + -0x1.adbcc2d508efep-8, 0x1.286e15e403188p-6, 0x1.27707f261dedep-6, -0x1.0694bd374c878p-3, + -0x1.80f61e7fbe657p-7, -0x1.421e421f43ba1p-4, 0x1.5427b7920d992p-4, -0x1.b133be2cca906p-4, + -0x1.6293761db90acp-7, -0x1.44a9ea550bd30p-5, 0x1.99dd9279f3a0fp-3, -0x1.4e20f2751d66ep-7, + 0x1.fb092a71f0342p-4, -0x1.0548844a2883fp-4, -0x1.5db9e6baf8150p-4, -0x1.435a9086269b4p-3, + 0x1.8845011a66d8ep-4, 0x1.8b06cba2d58dap-5, -0x1.de80830d072edp-5, 0x1.3787cb865a60dp-3, + 0x1.3a5a8c9c8f410p-6, 0x1.7bdd32fe55c73p-5, 0x1.1fc90e483694fp-7, 0x1.5087164f4d7d0p-4, + -0x1.b739788c263dep-6, 0x1.c293b2afbed43p-4, 0x1.b8ba0c1641f47p-4, -0x1.1ecc333ff78cdp-5, + 0x1.3da6fc0aa650bp-5, -0x1.2bba19c041b3ap-5, -0x1.f1a76fd89d4bcp-8, 0x1.fa6083af91918p-10, + -0x1.73560aac6f429p-3, 0x1.026d191129d8bp-5, 0x1.f999137036557p-6, -0x1.1d73c46cef749p-4, + -0x1.a5b22ccd18e49p-5, 0x1.11a0cdd3c3098p-3, -0x1.895b5a15093ecp-6, -0x1.3b18afcde4afep-4, + -0x1.270cc0a032e54p-7, 0x1.e8c4ca7b93a7fp-4, 0x1.0f5190e4a65f6p-5, -0x1.364ebf39294f9p-6, + -0x1.75e3692f3b200p-7, -0x1.08272332ab8f4p-3, 0x1.8f28bcb9ee3d3p-3, 0x1.1d995f2ea0ad6p-6, + 0x1.bb62315b69811p-5, -0x1.f9cf50c26f386p-8, 0x1.2807886765685p-5, 0x1.0d513e5734fd6p-7, + -0x1.72309a8681fc5p-3, 0x1.41e429a6b1effp-5, 0x1.4979c42283612p-3, 0x1.e6c5470d210f0p-4, + -0x1.9e201bddf084cp-5, -0x1.28005f595b13ap-3, 0x1.fe78ce41c07e1p-13, 0x1.8d119c59eaaa0p-4, + 0x1.f141f1b26d0a5p-6, -0x1.e119c02c8643bp-5, -0x1.6bc9192bf5b37p-6, -0x1.dad9a0fdb70ddp-5, + 0x1.28459caec98c4p-5, -0x1.318b35876e331p-6, 0x1.70f7d7432f401p-3, 0x1.397d3f6ec9520p-5, + -0x1.cd522b0a528dcp-4, -0x1.3dd1c5a42e234p-7, 0x1.3953c0711bfbcp-5, -0x1.fa8fbf75b4ffep-7, + 0x1.e87cb76c91af3p-3, -0x1.2e826adf283b7p-4, 0x1.ad2196a8e8931p-5, 0x1.4c2a70c166f0fp-4, + -0x1.15a4e0c015f01p-4, 0x1.58efeacc697f4p-4, -0x1.cec7d6360af85p-6, -0x1.51eec56894d89p-3, + -0x1.33b2885ef6d08p-6, -0x1.eccd1b34dd749p-5, -0x1.74397e9e9143ep-4, -0x1.ccb1e5995371fp-5, + 0x1.24f860991332dp-6, 0x1.9dd32663e311cp-4, 0x1.537bcbe91cae9p-5, -0x1.6c4e0ae1a6e2fp-5, + -0x1.c891d9cd5eaa8p-3, 0x1.3366dee70cde0p-7, 0x1.d1f31c4727c9fp-5, 0x1.1cdc750eb21c2p-6, + -0x1.77810958e8bb6p-10, -0x1.c2e01ce1ec219p-4, -0x1.82da1d16bd284p-3, 0x1.df0cc9729e783p-5, + 0x1.6364c7534497bp-4, -0x1.333a19594842ap-3, -0x1.400ae6b174703p-6, -0x1.859a24e6c0ca4p-4, + -0x1.1439063647efep-6, -0x1.eec60de488f79p-6, -0x1.412c8e0f23ed2p-4, -0x1.96be4d92cac66p-4, + -0x1.42f1b555080eep-4, -0x1.4dc1a6874228ap-8, -0x1.007a0d77d0980p-3, -0x1.ce7e97c7e8ef9p-5, + 0x1.7dcd401ea3b9cp-4, -0x1.41dc6527a9346p-6, -0x1.481420c75f405p-3, -0x1.64aee8868216cp-6, + -0x1.6550a36b85fd8p-4, -0x1.70c10cdc42939p-5, 0x1.2ae29b57aa369p-5, 0x1.7469b2c4bfd83p-3, + -0x1.dec95f246855cp-7, 0x1.4c1e9c54cdb0cp-5, 0x1.21fff2355f44fp-7, -0x1.9f8cc1d8a1c64p-5, + 0x1.611bb4cc571aep-4, 0x1.6efa2a1c51493p-6, -0x1.8ae90d4017fe7p-5, 0x1.24728a33321e5p-3, + -0x1.24728a33321e5p-3, 0x1.8ae90d4017fe7p-5, -0x1.6efa2a1c51493p-6, -0x1.611bb4cc571aep-4, + 0x1.9f8cc1d8a1c64p-5, -0x1.21fff2355f44fp-7, -0x1.4c1e9c54cdb0cp-5, 0x1.dec95f246855cp-7, + -0x1.7469b2c4bfd83p-3, -0x1.2ae29b57aa369p-5, 0x1.70c10cdc42939p-5, 0x1.6550a36b85fd8p-4, + 0x1.64aee8868216cp-6, 0x1.481420c75f405p-3, 0x1.41dc6527a9346p-6, -0x1.7dcd401ea3b9cp-4, + 0x1.ce7e97c7e8ef9p-5, 0x1.007a0d77d0980p-3, 0x1.4dc1a6874228ap-8, 0x1.42f1b555080eep-4, + 0x1.96be4d92cac66p-4, 0x1.412c8e0f23ed2p-4, 0x1.eec60de488f79p-6, 0x1.1439063647efep-6, + 0x1.859a24e6c0ca4p-4, 0x1.400ae6b174703p-6, 0x1.333a19594842ap-3, -0x1.6364c7534497bp-4, + -0x1.df0cc9729e783p-5, 0x1.82da1d16bd284p-3, 0x1.c2e01ce1ec219p-4, 0x1.77810958e8bb6p-10, + -0x1.1cdc750eb21c2p-6, -0x1.d1f31c4727c9fp-5, -0x1.3366dee70cde0p-7, 0x1.c891d9cd5eaa8p-3, + 0x1.6c4e0ae1a6e2fp-5, -0x1.537bcbe91cae9p-5, -0x1.9dd32663e311cp-4, -0x1.24f860991332dp-6, + 0x1.ccb1e5995371fp-5, 0x1.74397e9e9143ep-4, 0x1.eccd1b34dd749p-5, 0x1.33b2885ef6d08p-6, + 0x1.51eec56894d89p-3, 0x1.cec7d6360af85p-6, -0x1.58efeacc697f4p-4, 0x1.15a4e0c015f01p-4, + -0x1.4c2a70c166f0fp-4, -0x1.ad2196a8e8931p-5, 0x1.2e826adf283b7p-4, -0x1.e87cb76c91af3p-3, + 0x1.fa8fbf75b4ffep-7, -0x1.3953c0711bfbcp-5, 0x1.3dd1c5a42e234p-7, 0x1.cd522b0a528dcp-4, + -0x1.397d3f6ec952ap-5, -0x1.70f7d7432f400p-3, 0x1.318b35876e318p-6, -0x1.28459caec98c2p-5, + 0x1.dad9a0fdb70d6p-5, 0x1.6bc9192bf5b3dp-6, 0x1.e119bac3aaf1ep-5, -0x1.f141f291e1aa5p-6, + -0x1.76dd9eddab583p-6, -0x1.f7599b4e07ddfp-4, 0x1.0c97040bbbda2p-4, 0x1.b3e4d01d0a985p-4, + -0x1.9777ee85aa4aep-4, -0x1.36058c4650b1fp-4, 0x1.ebbd8d3134dc6p-4, 0x1.1d3441b0a6a72p-5, + -0x1.fe1cad0a29079p-4, 0x1.5f6cfc0c98ce4p-7, 0x1.cc1f108306e1bp-4, -0x1.c124a0b3328efp-5, + -0x1.5c77bc759a3f5p-4, 0x1.771e7793288e2p-4, 0x1.7c3a94c617425p-5, -0x1.db652823e1fd1p-4, + -0x1.921d1cbfdad3ap-10, 0x1.fff622e9f98b6p-4, -0x1.64c7e0125071cp-5, -0x1.dfeae6679e9aap-4, + 0x1.53282709393f8p-4, 0x1.7f8eced4daab0p-4, -0x1.c678afc14d35fp-4, -0x1.d7977476f0c3dp-5, + 0x1.fce15eff67313p-4, 0x1.c3785b49de10ap-7, -0x1.ef178831198f1p-4, 0x1.04fb801d37584p-5, + 0x1.9ef43e04796dfp-4, -0x1.2bedb3ccf5f32p-4, -0x1.1734d3bc48a06p-4, 0x1.ad2bca8008becp-4, + 0x1.a82a03ac04ebep-6, -0x1.f4e6044aa950ap-4, 0x1.45576c6aa2769p-6, 0x1.f97f93ee06c07p-4, + -0x1.01cfc5e34c135p-4, -0x1.ba5aa451da0bdp-4, 0x1.8fbccbda45ab7p-4, 0x1.3fed97091d6b6p-4, + -0x1.e817b9b00fddbp-4, -0x1.35410c8c2de43p-5, 0x1.ff095899f81fbp-4, -0x1.f656efbdb53e6p-8, + -0x1.d17e78f8772e9p-4, 0x1.aa6c80ec7d7fbp-5, 0x1.659192d681b54p-4, -0x1.6e7444fa23a82p-4, + -0x1.9372a2b4b99ecp-5, 0x1.d69616d5d2fb6p-4, 0x1.2d86480a6b7bep-8, -0x1.ffa72dbe1428ap-4, + 0x1.4d1e23e74d21ap-5, 0x1.e426a75b90691p-4, -0x1.49a44a32997a5p-4, -0x1.87c40012df423p-4, + 0x1.c08c40dbf643ep-4, 0x1.edc1933efe58fp-5, -0x1.fb5796a5fccf7p-4, -0x1.139f08748f3b2p-6, + 0x1.f225321dc4307p-4, -0x1.d9350272c2289p-6, -0x1.a63092ffbad0dp-4, 0x1.21a799527e34ep-4, + 0x1.21a799527e34ep-4, -0x1.a63092ffbad0dp-4, -0x1.d9350272c2289p-6, 0x1.f225321dc4307p-4, + -0x1.139f08748f3b2p-6, -0x1.fb5796a5fccf7p-4, 0x1.edc1933efe58fp-5, 0x1.c08c40dbf643ep-4, + -0x1.87c40012df423p-4, -0x1.49a44a32997a5p-4, 0x1.e426a75b90691p-4, 0x1.4d1e23e74d21ap-5, + -0x1.ffa72dbe1428ap-4, 0x1.2d86480a6b7bep-8, 0x1.d69616d5d2fb6p-4, -0x1.9372a2b4b99ecp-5, + -0x1.6e7444fa23a82p-4, 0x1.659192d681b54p-4, 0x1.aa6c80ec7d7fbp-5, -0x1.d17e78f8772e9p-4, + -0x1.f656efbdb53e6p-8, 0x1.ff095899f81fbp-4, -0x1.35410c8c2de43p-5, -0x1.e817b9b00fddbp-4, + 0x1.3fed97091d6b6p-4, 0x1.8fbccbda45ab7p-4, -0x1.ba5aa451da0bdp-4, -0x1.01cfc5e34c135p-4, + 0x1.f97f93ee06c07p-4, 0x1.45576c6aa2769p-6, -0x1.f4e6044aa950ap-4, 0x1.a82a03ac04ebep-6, + 0x1.ad2bca8008becp-4, -0x1.1734d3bc48a06p-4, -0x1.2bedb3ccf5f32p-4, 0x1.9ef43e04796dfp-4, + 0x1.04fb801d37584p-5, -0x1.ef178831198f1p-4, 0x1.c3785b49de10ap-7, 0x1.fce15eff67313p-4, + -0x1.d7977476f0c3dp-5, -0x1.c678afc14d35fp-4, 0x1.7f8eced4daab0p-4, 0x1.53282709393f8p-4, + -0x1.dfeae6679e9aap-4, -0x1.64c7e0125071cp-5, 0x1.fff622e9f98b6p-4, -0x1.921d1cbfdad3ap-10, + -0x1.db652823e1fd1p-4, 0x1.7c3a94c617425p-5, 0x1.771e7793288e2p-4, -0x1.5c77bc759a3f5p-4, + -0x1.c124a0b3328efp-5, 0x1.cc1f108306e1bp-4, 0x1.5f6cfc0c98ce4p-7, -0x1.fe1cad0a29079p-4, + 0x1.1d3441b0a6a72p-5, 0x1.ebbd8d3134dc6p-4, -0x1.36058c4650b1fp-4, -0x1.9777ee85aa4aep-4, + 0x1.b3e4d01d0a985p-4, 0x1.0c97040bbbda2p-4, -0x1.f7599b4e07dd1p-4, -0x1.76dd9eddab584p-6, + 0x1.f7599bcfdf11dp-4, -0x1.76dd9eb841e07p-6, 0x1.b3e4cfd5f7441p-4, -0x1.0c9703c6292c5p-4, + 0x1.36058c6d5f8cap-4, -0x1.9777edd270e2bp-4, 0x1.1d3442406d6a4p-5, -0x1.ebbd8e7af8515p-4, + -0x1.5f6cfc3d3d859p-7, -0x1.fe1cadbf79bd8p-4, -0x1.c124a0730d6e3p-5, -0x1.cc1f103a1ead8p-4, + -0x1.771e77ddef50dp-4, -0x1.5c77bb73e3e18p-4, -0x1.db652899b982cp-4, -0x1.7c3a9423252f9p-5, + -0x1.fff622545391cp-4, -0x1.921d18c32cdadp-10, -0x1.dfeae5b36434dp-4, 0x1.64c7df8f2717ep-5, + -0x1.7f8ecebdc41e3p-4, 0x1.532828073e5f2p-4, -0x1.d79774655cffap-5, 0x1.c678b0c91d5dcp-4, + -0x1.c3785b423d46bp-7, 0x1.fce1607a44be0p-4, 0x1.04fb7f8dd463bp-5, 0x1.ef1787b315570p-4, + 0x1.2bedb49c89cb2p-4, 0x1.9ef43ddd52204p-4, 0x1.ad2bc97c21d10p-4, 0x1.1734d4a772957p-4, + 0x1.f4e604615c8e8p-4, 0x1.a82a03d970c92p-6, 0x1.f97f94902bea5p-4, -0x1.45576b3c0b291p-6, + 0x1.ba5aa334bfdedp-4, -0x1.01cfc6a1bb2c9p-4, 0x1.3fed95d842e70p-4, -0x1.8fbccb41b03fcp-4, + 0x1.35410bae8f1b7p-5, -0x1.e817b98938d85p-4, -0x1.f656ef03b613ep-8, -0x1.ff0958f879fafp-4, + -0x1.aa6c80439a84fp-5, -0x1.d17e7a8dc0ae6p-4, -0x1.6e7444a8b7e08p-4, -0x1.659191721979cp-4, + -0x1.d6961581e7572p-4, -0x1.9372a458b39d3p-5, -0x1.ffa72d1fd1e94p-4, -0x1.2d864a6fd80ddp-8, + -0x1.e426a901576aap-4, 0x1.4d1e244f9d4f8p-5, -0x1.87c400aa3755bp-4, 0x1.49a44a1a1b16ep-4, + -0x1.edc192e560151p-5, 0x1.c08c40304d497p-4, -0x1.139f087114ed9p-6, 0x1.fb5797235bdbep-4, + 0x1.d93502c52cf85p-6, 0x1.f225319edfe56p-4, 0x1.21a79996d17e5p-4, 0x1.a630915be86dep-4, + 0x1.a630915be86dep-4, 0x1.21a79996d17e5p-4, 0x1.f225319edfe56p-4, 0x1.d93502c52cf85p-6, + 0x1.fb5797235bdbep-4, -0x1.139f087114ed9p-6, 0x1.c08c40304d497p-4, -0x1.edc192e560151p-5, + 0x1.49a44a1a1b16ep-4, -0x1.87c400aa3755bp-4, 0x1.4d1e244f9d4f8p-5, -0x1.e426a901576aap-4, + -0x1.2d864a6fd80ddp-8, -0x1.ffa72d1fd1e94p-4, -0x1.9372a458b39d3p-5, -0x1.d6961581e7572p-4, + -0x1.659191721979cp-4, -0x1.6e7444a8b7e08p-4, -0x1.d17e7a8dc0ae6p-4, -0x1.aa6c80439a84fp-5, + -0x1.ff0958f879fafp-4, -0x1.f656ef03b613ep-8, -0x1.e817b98938d85p-4, 0x1.35410bae8f1b7p-5, + -0x1.8fbccb41b03fcp-4, 0x1.3fed95d842e70p-4, -0x1.01cfc6a1bb2c9p-4, 0x1.ba5aa334bfdedp-4, + -0x1.45576b3c0b291p-6, 0x1.f97f94902bea5p-4, 0x1.a82a03d970c92p-6, 0x1.f4e604615c8e8p-4, + 0x1.1734d4a772957p-4, 0x1.ad2bc97c21d10p-4, 0x1.9ef43ddd52204p-4, 0x1.2bedb49c89cb2p-4, + 0x1.ef1787b315570p-4, 0x1.04fb7f8dd463bp-5, 0x1.fce1607a44be0p-4, -0x1.c3785b423d46bp-7, + 0x1.c678b0c91d5dcp-4, -0x1.d79774655cffap-5, 0x1.532828073e5f2p-4, -0x1.7f8ecebdc41e3p-4, + 0x1.64c7df8f2717ep-5, -0x1.dfeae5b36434dp-4, -0x1.921d18c32cdadp-10, -0x1.fff622545391cp-4, + -0x1.7c3a9423252f9p-5, -0x1.db652899b982cp-4, -0x1.5c77bb73e3e18p-4, -0x1.771e77ddef50dp-4, + -0x1.cc1f103a1ead8p-4, -0x1.c124a0730d6e3p-5, -0x1.fe1cadbf79bd8p-4, -0x1.5f6cfc3d3d859p-7, + -0x1.ebbd8e7af8515p-4, 0x1.1d3442406d6a4p-5, -0x1.9777edd270e2bp-4, 0x1.36058c6d5f8cap-4, + -0x1.0c9703c6292c5p-4, 0x1.b3e4cfd5f7441p-4, -0x1.76dd9eb841e07p-6, 0x1.f7599bcfdf122p-4, + 0x1.6a615b30c4326p-3, -0x1.67fb51f064f1cp-7, -0x1.360ec1f1615fep-4, -0x1.f298ed905e3e7p-4, + -0x1.f42f09ef29e12p-9, -0x1.87d84a0ddf851p-4, -0x1.6bece70638a77p-6, 0x1.b9afade06a9dep-5, + -0x1.073741fab9268p-7, -0x1.41b953718e264p-4, 0x1.753110f7d8caap-4, -0x1.d55387cadf514p-7, + 0x1.83e57ae97a52dp-5, -0x1.c694fa48a0b1fp-12, 0x1.8099c12882c51p-3, 0x1.b87dff4a56707p-7, + -0x1.61fdddb53b1f8p-5, -0x1.b7048d74762c0p-8, -0x1.140f96492c551p-3, -0x1.3eb1cdb3c8589p-10, + 0x1.d6aee36340df1p-4, 0x1.b04b32452411cp-4, -0x1.a62cbaddbe7e0p-7, 0x1.127b19808d78ep-4, + -0x1.fc6c3d8ff4de1p-8, -0x1.15a3dda26a101p-3, 0x1.9da00710ecc05p-5, 0x1.1a4971fedeaeap-3, + -0x1.5163f200a844ep-4, -0x1.8838b853d83aap-4, 0x1.c54f0ebb4d9e3p-3, 0x1.5ac9d8a3a4c66p-11, + 0x1.bd2d6af5f06d3p-3, -0x1.8a327da4cf3bep-5, -0x1.0930d0a37bb5ep-4, -0x1.03d309b141436p-7, + 0x1.1bb4e915bd400p-6, 0x1.bcca60a9c8213p-7, -0x1.ab4aeabc30f97p-4, -0x1.c65b663168b38p-8, + 0x1.d7607963e291ep-5, -0x1.85160cd8be7c6p-5, 0x1.91823fc2be69bp-9, 0x1.263b479cc9593p-4, + 0x1.b05d961ab5ec3p-9, 0x1.d7777e4111b32p-3, 0x1.4cd1553e8b466p-5, 0x1.4555ab6f42387p-5, + -0x1.46fae1e018460p-5, -0x1.64a497344b913p-6, -0x1.2788891d87313p-4, 0x1.90eb7a223b9bbp-8, + -0x1.39cbac8bd9381p-4, -0x1.6b2bf44059788p-5, 0x1.a96065e62fc1dp-3, -0x1.98aecebc56ba6p-4, + 0x1.d1c5672d367fdp-6, 0x1.863c65149ba24p-4, -0x1.93ab801adc6afp-6, 0x1.397b80bf0c4d1p-6, + -0x1.5c354c36c150cp-6, -0x1.e87d9e380a158p-4, -0x1.1d56b88e4a3f1p-5, -0x1.5d0f07a3c3ebcp-5, + -0x1.5d0f07a3c3ebcp-5, -0x1.1d56b88e4a3f1p-5, -0x1.e87d9e380a158p-4, -0x1.5c354c36c150cp-6, + 0x1.397b80bf0c4d1p-6, -0x1.93ab801adc6afp-6, 0x1.863c65149ba24p-4, 0x1.d1c5672d367fdp-6, + -0x1.98aecebc56ba6p-4, 0x1.a96065e62fc1dp-3, -0x1.6b2bf44059788p-5, -0x1.39cbac8bd9381p-4, + 0x1.90eb7a223b9bbp-8, -0x1.2788891d87313p-4, -0x1.64a497344b913p-6, -0x1.46fae1e018460p-5, + 0x1.4555ab6f42387p-5, 0x1.4cd1553e8b466p-5, 0x1.d7777e4111b32p-3, 0x1.b05d961ab5ec3p-9, + 0x1.263b479cc9593p-4, 0x1.91823fc2be69bp-9, -0x1.85160cd8be7c6p-5, 0x1.d7607963e291ep-5, + -0x1.c65b663168b38p-8, -0x1.ab4aeabc30f97p-4, 0x1.bcca60a9c8213p-7, 0x1.1bb4e915bd400p-6, + -0x1.03d309b141436p-7, -0x1.0930d0a37bb5ep-4, -0x1.8a327da4cf3bep-5, 0x1.bd2d6af5f06d3p-3, + 0x1.5ac9d8a3a4c66p-11, 0x1.c54f0ebb4d9e3p-3, -0x1.8838b853d83aap-4, -0x1.5163f200a844ep-4, + 0x1.1a4971fedeaeap-3, 0x1.9da00710ecc05p-5, -0x1.15a3dda26a101p-3, -0x1.fc6c3d8ff4de1p-8, + 0x1.127b19808d78ep-4, -0x1.a62cbaddbe7e0p-7, 0x1.b04b32452411cp-4, 0x1.d6aee36340df1p-4, + -0x1.3eb1cdb3c8589p-10, -0x1.140f96492c551p-3, -0x1.b7048d74762c0p-8, -0x1.61fdddb53b1f8p-5, + 0x1.b87dff4a56707p-7, 0x1.8099c12882c51p-3, -0x1.c694fa48a0b1fp-12, 0x1.83e57ae97a52dp-5, + -0x1.d55387cadf514p-7, 0x1.753110f7d8caap-4, -0x1.41b953718e264p-4, -0x1.073741fab9268p-7, + 0x1.b9afade06a9ddp-5, -0x1.6bece70638a5fp-6, -0x1.87d84a0ddf84bp-4, -0x1.f42f09ef29ff5p-9, + -0x1.f298ed905e3e7p-4, -0x1.360ec1f1615f5p-4, -0x1.67fb520c20507p-7, 0x1.6a615a0acb589p-3, + 0x1.9624ad69e2156p-9, -0x1.fd4e22b78bcfcp-4, -0x1.0959f1d12050ep-8, -0x1.0f58b47e9be5fp-4, + 0x1.a9c2ea8b6d01fp-5, 0x1.675094e558114p-5, 0x1.bdbb5f3960310p-3, 0x1.d3d291ec89376p-5, + -0x1.d7a99a6182593p-3, 0x1.f224e6597c0b6p-7, 0x1.086288231391dp-6, 0x1.d0507358b5d33p-5, + 0x1.cf1a0cef32db2p-6, 0x1.b7d88c41a5846p-5, -0x1.4cc57a6cf3e80p-5, -0x1.45cbea1c0abd1p-6, + 0x1.28cbaba8458cdp-9, -0x1.57e834b34b524p-3, 0x1.0d9cbad65bcdep-8, 0x1.c47b2ac5c74fbp-4, + 0x1.fa94077d420b9p-5, -0x1.2e6bc9cdc07a1p-3, -0x1.55cecf949abf2p-6, 0x1.3eb6b5785b633p-8, + 0x1.5af08cfb264eap-3, 0x1.64e361c232e66p-7, 0x1.c065640c9e887p-4, 0x1.45704661a70e2p-7, + -0x1.4ae489049375ep-5, -0x1.1b38b9887e9e1p-4, -0x1.542565273a1d6p-5, -0x1.1b39d4f5ffdfep-3, + -0x1.09641e9afafafp-6, -0x1.39cede2f8bce7p-4, -0x1.34d641df8f3c7p-6, 0x1.97a818520d4ccp-6, + 0x1.4a18a87cf11c0p-5, 0x1.8d2415fc254dcp-6, 0x1.245c3c0c55053p-6, -0x1.eb669a7886f34p-5, + 0x1.38c5732b0f85ap-9, 0x1.ceb23e9d7bc71p-6, -0x1.4aa879154e63fp-4, -0x1.b31007f9ebbe5p-8, + -0x1.35e325f256420p-4, 0x1.41e422124ea5bp-8, -0x1.462c1f37d6482p-3, 0x1.77a0a00724f96p-4, + -0x1.953f2f74ee88dp-4, 0x1.aa22957bb8818p-6, 0x1.82bb45f927bccp-8, -0x1.ef3c97b018afep-4, + 0x1.a1f1d6d1e1916p-5, 0x1.c23204283a228p-3, 0x1.fbff7d1a53f35p-5, -0x1.5ff21019d7279p-4, + -0x1.5b5d7ac8672c0p-3, 0x1.5a1618937b79cp-5, 0x1.813985742d940p-4, 0x1.7a9ead8c96babp-7, + -0x1.4c385585e0bdap-3, -0x1.91b9aa657d305p-6, 0x1.2e7b61b8b38b6p-4, 0x1.781f0c515eab7p-4, + 0x1.781f0c515eab7p-4, 0x1.2e7b61b8b38b6p-4, -0x1.91b9aa657d305p-6, -0x1.4c385585e0bdap-3, + 0x1.7a9ead8c96babp-7, 0x1.813985742d940p-4, 0x1.5a1618937b79cp-5, -0x1.5b5d7ac8672c0p-3, + -0x1.5ff21019d7279p-4, 0x1.fbff7d1a53f35p-5, 0x1.c23204283a228p-3, 0x1.a1f1d6d1e1916p-5, + -0x1.ef3c97b018afep-4, 0x1.82bb45f927bccp-8, 0x1.aa22957bb8818p-6, -0x1.953f2f74ee88dp-4, + 0x1.77a0a00724f96p-4, -0x1.462c1f37d6482p-3, 0x1.41e422124ea5bp-8, -0x1.35e325f256420p-4, + -0x1.b31007f9ebbe5p-8, -0x1.4aa879154e63fp-4, 0x1.ceb23e9d7bc71p-6, 0x1.38c5732b0f85ap-9, + -0x1.eb669a7886f34p-5, 0x1.245c3c0c55053p-6, 0x1.8d2415fc254dcp-6, 0x1.4a18a87cf11c0p-5, + 0x1.97a818520d4ccp-6, -0x1.34d641df8f3c7p-6, -0x1.39cede2f8bce7p-4, -0x1.09641e9afafafp-6, + -0x1.1b39d4f5ffdfep-3, -0x1.542565273a1d6p-5, -0x1.1b38b9887e9e1p-4, -0x1.4ae489049375ep-5, + 0x1.45704661a70e2p-7, 0x1.c065640c9e887p-4, 0x1.64e361c232e66p-7, 0x1.5af08cfb264eap-3, + 0x1.3eb6b5785b633p-8, -0x1.55cecf949abf2p-6, -0x1.2e6bc9cdc07a1p-3, 0x1.fa94077d420b9p-5, + 0x1.c47b2ac5c74fbp-4, 0x1.0d9cbad65bcdep-8, -0x1.57e834b34b524p-3, 0x1.28cbaba8458cdp-9, + -0x1.45cbea1c0abd1p-6, -0x1.4cc57a6cf3e80p-5, 0x1.b7d88c41a5846p-5, 0x1.cf1a0cef32db2p-6, + 0x1.d0507358b5d33p-5, 0x1.086288231391dp-6, 0x1.f224e6597c0b6p-7, -0x1.d7a99a6182593p-3, + 0x1.d3d291ec89369p-5, 0x1.bdbb5f3960311p-3, 0x1.675094e55810ap-5, 0x1.a9c2ea8b6d01ap-5, + -0x1.0f58b47e9be5dp-4, -0x1.0959f1d120549p-8, -0x1.fd4e2244e5e2ep-4, 0x1.9624b085551b3p-9, + -0x1.a82a02902f3abp-6, -0x1.f4e6039fe9e81p-4, 0x1.2bedb2bfafe5ap-4, 0x1.9ef43dcc72790p-4, + -0x1.ba5aa6db1a352p-4, -0x1.01cfc8d85107dp-4, 0x1.fce1601dc31e3p-4, 0x1.c37860ed49883p-7, + -0x1.e817ba404e772p-4, 0x1.35410ba23ba9ep-5, 0x1.7f8ecec5f035bp-4, -0x1.532829cf0f254p-4, + -0x1.aa6c815a81ce4p-5, 0x1.d17e76bfa6d2bp-4, 0x1.921d1d1078fb4p-10, -0x1.fff621d486e14p-4, + 0x1.9372a70176b4dp-5, 0x1.d696181ae9f68p-4, -0x1.771e7763cc7d4p-4, -0x1.5c77bb8434bafp-4, + 0x1.e426a1cec3c44p-4, 0x1.4d1e253625275p-5, -0x1.fe1cae8707985p-4, 0x1.5f6cfca53ca53p-7, + 0x1.c08c42771fa3cp-4, -0x1.edc19534d2558p-5, -0x1.360589c12b2b4p-4, 0x1.9777ed64d98ecp-4, + 0x1.d934fb8633c76p-6, -0x1.f2253212633d8p-4, 0x1.76dd9fc4d7be8p-6, 0x1.f759994692c99p-4, + -0x1.21a79af806cadp-4, -0x1.a63090a90093cp-4, 0x1.b3e4cfe98103ep-4, 0x1.0c97042f7aae5p-4, + -0x1.fb579819ae830p-4, -0x1.139f0f5500c9fp-6, 0x1.ebbd8fbfdb764p-4, -0x1.1d34427cfd32ep-5, + -0x1.87c40081c2a5dp-4, 0x1.49a44a18e7930p-4, 0x1.c1249d78212dap-5, -0x1.cc1f0df68fba8p-4, + -0x1.2d86694e6f80cp-8, 0x1.ffa72f6b03243p-4, -0x1.7c3a943bee78dp-5, -0x1.db652607fa925p-4, + 0x1.6e74439077430p-4, 0x1.65919276392ddp-4, -0x1.dfeae55e3f615p-4, -0x1.64c7dd8c282adp-5, + 0x1.ff0958cad2f3ep-4, -0x1.f656def1f1127p-8, -0x1.c678b55acb59ap-4, 0x1.d797776410a62p-5, + 0x1.3fed959d13a35p-4, -0x1.8fbcc9d8a57bcp-4, -0x1.04fb80a36271ep-5, 0x1.ef178ab5af0eep-4, + -0x1.45576df2201b7p-6, -0x1.f97f91eeec63fp-4, 0x1.1734d4a76420fp-4, 0x1.ad2bcb8d63c50p-4, + -0x1.ad2bcb8d63c50p-4, -0x1.1734d4a76420fp-4, 0x1.f97f91eeec63fp-4, 0x1.45576df2201b7p-6, + -0x1.ef178ab5af0eep-4, 0x1.04fb80a36271ep-5, 0x1.8fbcc9d8a57bcp-4, -0x1.3fed959d13a35p-4, + -0x1.d797776410a62p-5, 0x1.c678b55acb59ap-4, 0x1.f656def1f1127p-8, -0x1.ff0958cad2f3ep-4, + 0x1.64c7dd8c282adp-5, 0x1.dfeae55e3f615p-4, -0x1.65919276392ddp-4, -0x1.6e74439077430p-4, + 0x1.db652607fa925p-4, 0x1.7c3a943bee78dp-5, -0x1.ffa72f6b03243p-4, 0x1.2d86694e6f80cp-8, + 0x1.cc1f0df68fba8p-4, -0x1.c1249d78212dap-5, -0x1.49a44a18e7930p-4, 0x1.87c40081c2a5dp-4, + 0x1.1d34427cfd32ep-5, -0x1.ebbd8fbfdb764p-4, 0x1.139f0f5500c9fp-6, 0x1.fb579819ae830p-4, + -0x1.0c97042f7aae5p-4, -0x1.b3e4cfe98103ep-4, 0x1.a63090a90093cp-4, 0x1.21a79af806cadp-4, + -0x1.f759994692c99p-4, -0x1.76dd9fc4d7be8p-6, 0x1.f2253212633d8p-4, -0x1.d934fb8633c76p-6, + -0x1.9777ed64d98ecp-4, 0x1.360589c12b2b4p-4, 0x1.edc19534d2558p-5, -0x1.c08c42771fa3cp-4, + -0x1.5f6cfca53ca53p-7, 0x1.fe1cae8707985p-4, -0x1.4d1e253625275p-5, -0x1.e426a1cec3c44p-4, + 0x1.5c77bb8434bafp-4, 0x1.771e7763cc7d4p-4, -0x1.d696181ae9f68p-4, -0x1.9372a70176b4dp-5, + 0x1.fff621d486e14p-4, -0x1.921d1d1078fb4p-10, -0x1.d17e76bfa6d2bp-4, 0x1.aa6c815a81ce4p-5, + 0x1.532829cf0f254p-4, -0x1.7f8ecec5f035bp-4, -0x1.35410ba23ba9ep-5, 0x1.e817ba404e772p-4, + -0x1.c37860ed49883p-7, -0x1.fce1601dc31e3p-4, 0x1.01cfc8d85107dp-4, 0x1.ba5aa6db1a352p-4, + -0x1.9ef43dcc72790p-4, -0x1.2bedb2bfafe5ap-4, 0x1.f4e6039fe9eacp-4, 0x1.a82a02902f3a9p-6, + 0x1.f4e603863e84ep-4, -0x1.a82a018017f54p-6, 0x1.9ef43c14bf448p-4, -0x1.2bedb23b5a753p-4, + 0x1.01cfc8aed6a6dp-4, -0x1.ba5aa68878950p-4, 0x1.c3785f076067bp-7, -0x1.fce1608bf3653p-4, + -0x1.35410c5cf7bd5p-5, -0x1.e817baf68874dp-4, -0x1.53282843a90ddp-4, -0x1.7f8ecee853165p-4, + -0x1.d17e7686a32a0p-4, -0x1.aa6c81d5fa7f9p-5, -0x1.fff6206b7858ep-4, -0x1.921d1605debabp-10, + -0x1.d696176c16746p-4, 0x1.9372a76c25238p-5, -0x1.5c77bb3c61d3ep-4, 0x1.771e7791a5f2ap-4, + -0x1.4d1e249ecca4ap-5, 0x1.e426a2818bae4p-4, 0x1.5f6cfe0349dabp-7, 0x1.fe1cb0344c670p-4, + 0x1.edc194c9c415dp-5, 0x1.c08c43212dd78p-4, 0x1.9777ec6096720p-4, 0x1.36058a2312d7dp-4, + 0x1.f22531840ccc4p-4, 0x1.d934fb519d2afp-6, 0x1.f7599a4b6dbd4p-4, -0x1.76dd9f33268e6p-6, + 0x1.a6309116f93cep-4, -0x1.21a799ddad840p-4, 0x1.0c9704decff95p-4, -0x1.b3e4d09fa2f23p-4, + 0x1.139f0f9f00021p-6, -0x1.fb5797bd622e6p-4, -0x1.1d3443d60a232p-5, -0x1.ebbd8fd91555dp-4, + -0x1.49a44abc93a9ep-4, -0x1.87c400b18d67fp-4, -0x1.cc1f0c1bd5774p-4, -0x1.c1249c5d34647p-5, + -0x1.ffa72f7ebe0b2p-4, -0x1.2d866b0a5123ep-8, -0x1.db6525e2c0181p-4, 0x1.7c3a95c559bb4p-5, + -0x1.6591930a84cefp-4, 0x1.6e74446f60c79p-4, -0x1.64c7de2d075e6p-5, 0x1.dfeae41717ac6p-4, + 0x1.f656dded7f6b7p-8, 0x1.ff095910326b7p-4, 0x1.d7977786c1b47p-5, 0x1.c678b44dd9811p-4, + 0x1.8fbccada4622cp-4, 0x1.3fed95c0cd49bp-4, 0x1.ef178b2dd2b85p-4, 0x1.04fb809db7759p-5, + 0x1.f97f935a6dd9ep-4, -0x1.45576dba1a838p-6, 0x1.ad2bcbb1e265dp-4, -0x1.1734d45a14a5cp-4, + 0x1.1734d45a14a5cp-4, -0x1.ad2bcbb1e265dp-4, 0x1.45576dba1a838p-6, -0x1.f97f935a6dd9ep-4, + -0x1.04fb809db7759p-5, -0x1.ef178b2dd2b85p-4, -0x1.3fed95c0cd49bp-4, -0x1.8fbccada4622cp-4, + -0x1.c678b44dd9811p-4, -0x1.d7977786c1b47p-5, -0x1.ff095910326b7p-4, -0x1.f656dded7f6b7p-8, + -0x1.dfeae41717ac6p-4, 0x1.64c7de2d075e6p-5, -0x1.6e74446f60c79p-4, 0x1.6591930a84cefp-4, + -0x1.7c3a95c559bb4p-5, 0x1.db6525e2c0181p-4, 0x1.2d866b0a5123ep-8, 0x1.ffa72f7ebe0b2p-4, + 0x1.c1249c5d34647p-5, 0x1.cc1f0c1bd5774p-4, 0x1.87c400b18d67fp-4, 0x1.49a44abc93a9ep-4, + 0x1.ebbd8fd91555dp-4, 0x1.1d3443d60a232p-5, 0x1.fb5797bd622e6p-4, -0x1.139f0f9f00021p-6, + 0x1.b3e4d09fa2f23p-4, -0x1.0c9704decff95p-4, 0x1.21a799ddad840p-4, -0x1.a6309116f93cep-4, + 0x1.76dd9f33268e6p-6, -0x1.f7599a4b6dbd4p-4, -0x1.d934fb519d2afp-6, -0x1.f22531840ccc4p-4, + -0x1.36058a2312d7dp-4, -0x1.9777ec6096720p-4, -0x1.c08c43212dd78p-4, -0x1.edc194c9c415dp-5, + -0x1.fe1cb0344c670p-4, -0x1.5f6cfe0349dabp-7, -0x1.e426a2818bae4p-4, 0x1.4d1e249ecca4ap-5, + -0x1.771e7791a5f2ap-4, 0x1.5c77bb3c61d3ep-4, -0x1.9372a76c25238p-5, 0x1.d696176c16746p-4, + 0x1.921d1605debabp-10, 0x1.fff6206b7858ep-4, 0x1.aa6c81d5fa7f9p-5, 0x1.d17e7686a32a0p-4, + 0x1.7f8ecee853165p-4, 0x1.53282843a90ddp-4, 0x1.e817baf68874dp-4, 0x1.35410c5cf7bd5p-5, + 0x1.fce1608bf3653p-4, -0x1.c3785f076067bp-7, 0x1.ba5aa68878950p-4, -0x1.01cfc8aed6a6dp-4, + 0x1.2bedb23b5a753p-4, -0x1.9ef43c14bf448p-4, 0x1.a82a018017f53p-6, -0x1.f4e603863e82cp-4, + -0x1.4424fa5775abfp-3, -0x1.34779aa2b09e4p-10, 0x1.98cfea6556f20p-7, -0x1.3421ed09dff88p-4, + 0x1.e68e9242f66f7p-9, -0x1.3903ebb958c35p-3, -0x1.3c30133109569p-8, -0x1.ab25dac4e29eap-5, + 0x1.d44f75f39af85p-5, -0x1.15cbb95e2fd7ep-4, -0x1.1287b5a411de9p-4, -0x1.676c32eeba6a1p-4, + -0x1.82309c8596e4fp-3, 0x1.d2d7420e258b9p-5, -0x1.f817e154950b5p-8, 0x1.c593757d17377p-9, + -0x1.11072bd4a775fp-7, -0x1.e7fea49675ed9p-7, -0x1.d57e85690521ep-8, 0x1.9c5a07dadb03cp-6, + -0x1.a01c2236b626ep-6, 0x1.22da3f686e937p-4, -0x1.46398bb4566c4p-9, 0x1.2ffe01b351354p-5, + -0x1.b04ab87001d8ap-4, -0x1.73ddad799fa3fp-4, 0x1.baaf5c758e5dap-4, 0x1.a21d9a2666a8dp-5, + -0x1.30b988ed745e8p-4, 0x1.7e3269f66a3c0p-7, 0x1.5e81f494157b2p-4, -0x1.4c7dc5372e229p-6, + 0x1.e86437daf1729p-4, -0x1.5143f62232198p-3, -0x1.e88183c843af4p-5, 0x1.ab9c9ef6ff0b0p-7, + 0x1.128e2e330afaap-6, 0x1.02c8e56b9b00ep-3, 0x1.1868b46426aaep-5, 0x1.078b5860c0b81p-4, + 0x1.cdc77da12beedp-7, -0x1.015731af086bdp-4, -0x1.4b8c66c9cd0e4p-6, 0x1.4176fecf1ec8ep-10, + 0x1.2a0201c0ae590p-2, -0x1.81a3d4ec1d119p-7, 0x1.7716e6001cee1p-4, -0x1.3af1fe374324bp-4, + 0x1.358fadab0f62ep-4, 0x1.f2e00461d4a5ap-4, 0x1.72c9dad126e5ap-5, -0x1.8345d364d772ap-5, + -0x1.43b0cbdacbf03p-7, 0x1.e05dd55bf99cbp-4, -0x1.22b30063244eep-6, 0x1.2bf607d8c6ac7p-4, + -0x1.10f43d345af4bp-3, -0x1.3a878cb4e97d0p-4, -0x1.d493f8e642eaep-3, 0x1.f5cc44e4d4be5p-6, + 0x1.2cd64ac383c13p-3, 0x1.1fe3d80958d64p-6, -0x1.d893d19a8c415p-4, -0x1.7bb642ef56811p-5, + 0x1.7bb642ef56811p-5, 0x1.d893d19a8c415p-4, -0x1.1fe3d80958d64p-6, -0x1.2cd64ac383c13p-3, + -0x1.f5cc44e4d4be5p-6, 0x1.d493f8e642eaep-3, 0x1.3a878cb4e97d0p-4, 0x1.10f43d345af4bp-3, + -0x1.2bf607d8c6ac7p-4, 0x1.22b30063244eep-6, -0x1.e05dd55bf99cbp-4, 0x1.43b0cbdacbf03p-7, + 0x1.8345d364d772ap-5, -0x1.72c9dad126e5ap-5, -0x1.f2e00461d4a5ap-4, -0x1.358fadab0f62ep-4, + 0x1.3af1fe374324bp-4, -0x1.7716e6001cee1p-4, 0x1.81a3d4ec1d119p-7, -0x1.2a0201c0ae590p-2, + -0x1.4176fecf1ec8ep-10, 0x1.4b8c66c9cd0e4p-6, 0x1.015731af086bdp-4, -0x1.cdc77da12beedp-7, + -0x1.078b5860c0b81p-4, -0x1.1868b46426aaep-5, -0x1.02c8e56b9b00ep-3, -0x1.128e2e330afaap-6, + -0x1.ab9c9ef6ff0b0p-7, 0x1.e88183c843af4p-5, 0x1.5143f62232198p-3, -0x1.e86437daf1729p-4, + 0x1.4c7dc5372e229p-6, -0x1.5e81f494157b2p-4, -0x1.7e3269f66a3c0p-7, 0x1.30b988ed745e8p-4, + -0x1.a21d9a2666a8dp-5, -0x1.baaf5c758e5dap-4, 0x1.73ddad799fa3fp-4, 0x1.b04ab87001d8ap-4, + -0x1.2ffe01b351354p-5, 0x1.46398bb4566c4p-9, -0x1.22da3f686e937p-4, 0x1.a01c2236b626ep-6, + -0x1.9c5a07dadb03cp-6, 0x1.d57e85690521ep-8, 0x1.e7fea49675ed9p-7, 0x1.11072bd4a775fp-7, + -0x1.c593757d17377p-9, 0x1.f817e154950b5p-8, -0x1.d2d7420e258b9p-5, 0x1.82309c8596e4fp-3, + 0x1.676c32eeba6a1p-4, 0x1.1287b5a411de9p-4, 0x1.15cbb95e2fd7ep-4, -0x1.d44f75f39af85p-5, + 0x1.ab25dac4e29eap-5, 0x1.3c30133109554p-8, 0x1.3903ebb958c33p-3, -0x1.e68e9242f658bp-9, + 0x1.3421ed09dff87p-4, -0x1.98cfea6556f48p-7, 0x1.34779c9d99adep-10, 0x1.4424faead78b4p-3, + 0x1.5b33337da6c2dp-6, -0x1.4ba8fe45903e6p-5, 0x1.6f521bedcae16p-5, 0x1.49871c63610e6p-3, + -0x1.6c5bbf378d52cp-4, -0x1.5fdce9cef9a38p-5, -0x1.907700defc605p-3, 0x1.42b82edec563fp-5, + -0x1.b01e65e71351ep-6, 0x1.0a50a119f0d2ep-7, -0x1.826f68557fe55p-9, -0x1.c1b637963c462p-4, + -0x1.b48663aa20e14p-6, -0x1.774c8741b9aefp-5, 0x1.93d41e7c85bcap-6, -0x1.55fe2ae060b6ep-3, + 0x1.52f09de7eb58bp-5, 0x1.8386cb49b17bbp-3, -0x1.eb08ae993c71bp-7, -0x1.b12494a8bc5bep-5, + -0x1.2b225b435d67cp-3, -0x1.5a6a63f475b11p-6, 0x1.55253a0552be7p-6, -0x1.542808e9d0711p-5, + -0x1.6ab81b109b38ap-4, 0x1.5bd036496dc8ep-5, 0x1.b1a15b25b7458p-5, 0x1.247104289cd1dp-6, + -0x1.ed9dfe46e0820p-6, -0x1.e2c486f9f0be1p-3, -0x1.fdd13ff797597p-11, -0x1.e12daf2d3640ep-5, + -0x1.2cfe0767f38b4p-4, -0x1.9e04822db3ef7p-5, -0x1.56c30c59892abp-3, -0x1.671f31feaaeffp-5, + -0x1.2d08eb74ae0bep-4, -0x1.8c3757186de8ep-8, -0x1.004d12af6eadep-7, 0x1.2a2c86d59ecc0p-5, + 0x1.a90ff4fcc778ep-5, -0x1.c2d68ee9057a9p-4, 0x1.47838fa8ff56cp-4, -0x1.5ca023ca154e1p-3, + 0x1.7993b5906a4e4p-8, -0x1.c249de045cdcap-5, 0x1.deadf2f18c8f3p-5, 0x1.ef24031f891cap-10, + -0x1.18fd658e7de75p-3, -0x1.5412227d45d7cp-5, -0x1.ecfc09bf69e6ep-5, 0x1.91475414b78aap-5, + -0x1.e11ea833ea872p-4, -0x1.fa9c4d587e072p-6, -0x1.e4e7daba17044p-6, 0x1.402857268c889p-5, + 0x1.0eb2ce8cf8e9bp-4, 0x1.28c5b330e5f71p-3, -0x1.66507aca9f37cp-5, 0x1.4cff70d7da7f8p-6, + -0x1.04ce8cfb151dep-5, 0x1.04d42e9e04330p-2, 0x1.27f8b016f3c3ap-7, 0x1.4f8de3a2cee6dp-6, + -0x1.4f8de3a2cee6dp-6, -0x1.27f8b016f3c3ap-7, -0x1.04d42e9e04330p-2, 0x1.04ce8cfb151dep-5, + -0x1.4cff70d7da7f8p-6, 0x1.66507aca9f37cp-5, -0x1.28c5b330e5f71p-3, -0x1.0eb2ce8cf8e9bp-4, + -0x1.402857268c889p-5, 0x1.e4e7daba17044p-6, 0x1.fa9c4d587e072p-6, 0x1.e11ea833ea872p-4, + -0x1.91475414b78aap-5, 0x1.ecfc09bf69e6ep-5, 0x1.5412227d45d7cp-5, 0x1.18fd658e7de75p-3, + -0x1.ef24031f891cap-10, -0x1.deadf2f18c8f3p-5, 0x1.c249de045cdcap-5, -0x1.7993b5906a4e4p-8, + 0x1.5ca023ca154e1p-3, -0x1.47838fa8ff56cp-4, 0x1.c2d68ee9057a9p-4, -0x1.a90ff4fcc778ep-5, + -0x1.2a2c86d59ecc0p-5, 0x1.004d12af6eadep-7, 0x1.8c3757186de8ep-8, 0x1.2d08eb74ae0bep-4, + 0x1.671f31feaaeffp-5, 0x1.56c30c59892abp-3, 0x1.9e04822db3ef7p-5, 0x1.2cfe0767f38b4p-4, + 0x1.e12daf2d3640ep-5, 0x1.fdd13ff797597p-11, 0x1.e2c486f9f0be1p-3, 0x1.ed9dfe46e0820p-6, + -0x1.247104289cd1dp-6, -0x1.b1a15b25b7458p-5, -0x1.5bd036496dc8ep-5, 0x1.6ab81b109b38ap-4, + 0x1.542808e9d0711p-5, -0x1.55253a0552be7p-6, 0x1.5a6a63f475b11p-6, 0x1.2b225b435d67cp-3, + 0x1.b12494a8bc5bep-5, 0x1.eb08ae993c71bp-7, -0x1.8386cb49b17bbp-3, -0x1.52f09de7eb58bp-5, + 0x1.55fe2ae060b6ep-3, -0x1.93d41e7c85bcap-6, 0x1.774c8741b9aefp-5, 0x1.b48663aa20e14p-6, + 0x1.c1b637963c462p-4, 0x1.826f68557fe55p-9, -0x1.0a50a119f0d2ep-7, 0x1.b01e65e71351ep-6, + -0x1.42b82edec5638p-5, 0x1.907700defc605p-3, 0x1.5fdce9cef9a3fp-5, 0x1.6c5bbf378d530p-4, + -0x1.49871c63610ecp-3, -0x1.6f521bedcae12p-5, 0x1.4ba9049d135a2p-5, -0x1.5b3333beecdcfp-6, + -0x1.d934feada680bp-6, -0x1.f225328146b45p-4, 0x1.49a4463a3c2c8p-4, 0x1.87c3fdfd2503ep-4, + -0x1.d696165a28c4cp-4, -0x1.9372a723dca3ep-5, 0x1.ff095887bd9fcp-4, -0x1.f656f1cd87420p-8, + -0x1.ba5aa81ccd200p-4, 0x1.01cfc8ecec5dep-4, 0x1.1734d5094cb24p-4, -0x1.ad2bcc3691111p-4, + -0x1.c37866ad43df8p-7, 0x1.fce15e60a85ecp-4, -0x1.64c7da2115391p-5, -0x1.dfeae91d122e0p-4, + 0x1.771e74464cafbp-4, 0x1.5c77bc356377dp-4, -0x1.ebbd8ab5a387ep-4, -0x1.1d343e6dbd2bep-5, + 0x1.f7599a71847bdp-4, -0x1.76dd997badd5ep-6, -0x1.9777ec918d9dfp-4, 0x1.36058c153b3dbp-4, + 0x1.c12499e6709c7p-5, -0x1.cc1f0fcf8d65ep-4, 0x1.921d84fd53433p-10, 0x1.fff623c910f3ap-4, + -0x1.d7977558b953fp-5, -0x1.c678b1f481d8fp-4, 0x1.9ef43cc5572ddp-4, 0x1.2bedb047a42a4p-4, + -0x1.f97f92dce4f4ep-4, -0x1.45576c6ed9849p-6, 0x1.e817bbfd5ce3dp-4, -0x1.35410905c2afep-5, + -0x1.6e744556369a3p-4, 0x1.659190f1332dep-4, 0x1.4d1e25fbd7b90p-5, -0x1.e426a666c1074p-4, + 0x1.139f103839c7ap-6, 0x1.fb579512446ccp-4, -0x1.21a79cd3f8637p-4, -0x1.a63091cef7ebdp-4, + 0x1.c08c433815d63p-4, 0x1.edc19aa89c361p-5, -0x1.ffa72f097326ap-4, -0x1.2d865f52b2c33p-8, + 0x1.d17e765160750p-4, -0x1.aa6c80ef534bfp-5, -0x1.3fed948471619p-4, 0x1.8fbcc8676971dp-4, + 0x1.a82a0d19c0a46p-6, -0x1.f4e60606a53e5p-4, 0x1.04fb80cca3fc4p-5, 0x1.ef178ad01a897p-4, + -0x1.53282b73ee48dp-4, -0x1.7f8eca066141bp-4, 0x1.db6525fc7f85bp-4, 0x1.7c3a9358ca0d8p-5, + -0x1.fe1cae989a066p-4, 0x1.5f6d078be8261p-7, 0x1.b3e4d5698265ep-4, -0x1.0c970566c2239p-4, + -0x1.0c970566c2239p-4, 0x1.b3e4d5698265ep-4, 0x1.5f6d078be8261p-7, -0x1.fe1cae989a066p-4, + 0x1.7c3a9358ca0d8p-5, 0x1.db6525fc7f85bp-4, -0x1.7f8eca066141bp-4, -0x1.53282b73ee48dp-4, + 0x1.ef178ad01a897p-4, 0x1.04fb80cca3fc4p-5, -0x1.f4e60606a53e5p-4, 0x1.a82a0d19c0a46p-6, + 0x1.8fbcc8676971dp-4, -0x1.3fed948471619p-4, -0x1.aa6c80ef534bfp-5, 0x1.d17e765160750p-4, + -0x1.2d865f52b2c33p-8, -0x1.ffa72f097326ap-4, 0x1.edc19aa89c361p-5, 0x1.c08c433815d63p-4, + -0x1.a63091cef7ebdp-4, -0x1.21a79cd3f8637p-4, 0x1.fb579512446ccp-4, 0x1.139f103839c7ap-6, + -0x1.e426a666c1074p-4, 0x1.4d1e25fbd7b90p-5, 0x1.659190f1332dep-4, -0x1.6e744556369a3p-4, + -0x1.35410905c2afep-5, 0x1.e817bbfd5ce3dp-4, -0x1.45576c6ed9849p-6, -0x1.f97f92dce4f4ep-4, + 0x1.2bedb047a42a4p-4, 0x1.9ef43cc5572ddp-4, -0x1.c678b1f481d8fp-4, -0x1.d7977558b953fp-5, + 0x1.fff623c910f3ap-4, 0x1.921d84fd53433p-10, -0x1.cc1f0fcf8d65ep-4, 0x1.c12499e6709c7p-5, + 0x1.36058c153b3dbp-4, -0x1.9777ec918d9dfp-4, -0x1.76dd997badd5ep-6, 0x1.f7599a71847bdp-4, + -0x1.1d343e6dbd2bep-5, -0x1.ebbd8ab5a387ep-4, 0x1.5c77bc356377dp-4, 0x1.771e74464cafbp-4, + -0x1.dfeae91d122e0p-4, -0x1.64c7da2115391p-5, 0x1.fce15e60a85ecp-4, -0x1.c37866ad43df8p-7, + -0x1.ad2bcc3691111p-4, 0x1.1734d5094cb24p-4, 0x1.01cfc8ecec5dep-4, -0x1.ba5aa81ccd200p-4, + -0x1.f656f1cd87420p-8, 0x1.ff095887bd9fcp-4, -0x1.9372a723dca3ep-5, -0x1.d696165a28c4cp-4, + 0x1.87c3fdfd2503ep-4, 0x1.49a4463a3c2c8p-4, -0x1.f225328146b43p-4, -0x1.d934feada6808p-6, + 0x1.f2253173d63bap-4, -0x1.d934fe2a3f8e6p-6, 0x1.87c3fd8ee825bp-4, -0x1.49a44662108f2p-4, + 0x1.9372a730c4802p-5, -0x1.d69614f9c28cep-4, -0x1.f656f496340fep-8, -0x1.ff0957db31179p-4, + -0x1.01cfc8ddabce6p-4, -0x1.ba5aa66c3cfacp-4, -0x1.ad2bcd690d3d6p-4, -0x1.1734d47db6732p-4, + -0x1.fce15fa4f2aafp-4, -0x1.c37866e52a32ap-7, -0x1.dfeae98efcbadp-4, 0x1.64c7d987fedeap-5, + -0x1.5c77bd49e593bp-4, 0x1.771e7499510cfp-4, -0x1.1d343f234f26dp-5, 0x1.ebbd8b47345cbp-4, + 0x1.76dd9886b6333p-6, 0x1.f7599b2fcd95dp-4, 0x1.36058b87b3bb5p-4, 0x1.9777edf1207aep-4, + 0x1.cc1f0eb16205cp-4, 0x1.c12499dfc8858p-5, 0x1.fff623abbd50bp-4, -0x1.921d8a9834a4fp-10, + 0x1.c678b17627f40p-4, -0x1.d79775730150ep-5, 0x1.2bedb16e7f8e1p-4, -0x1.9ef43cccb6167p-4, + 0x1.45576d8e66e5bp-6, -0x1.f97f93185b213p-4, -0x1.354108a838c07p-5, -0x1.e817bbb78b0c9p-4, + -0x1.659191c10260fp-4, -0x1.6e7444cbb37a4p-4, -0x1.e426a5dbecde0p-4, -0x1.4d1e270a9bf01p-5, + -0x1.fb5795715d1a4p-4, 0x1.139f0fd9154f0p-6, -0x1.a63090c03a3ebp-4, 0x1.21a79c5f3a8dbp-4, + -0x1.edc19a019514fp-5, 0x1.c08c428fe0fa2p-4, -0x1.2d865dc51796dp-8, 0x1.ffa7301a0764dp-4, + 0x1.aa6c80e924879p-5, 0x1.d17e7526f2190p-4, 0x1.8fbcc94888bdap-4, 0x1.3fed94500288cp-4, + 0x1.f4e605c65b0e9p-4, 0x1.a82a0d6d1445fp-6, 0x1.ef178be50bcf1p-4, -0x1.04fb817d3799bp-5, + 0x1.7f8eca78fc7c9p-4, -0x1.53282a2cbc39ep-4, 0x1.7c3a9353c504dp-5, -0x1.db6525a94fd02p-4, + -0x1.5f6d06f0f5b26p-7, -0x1.fe1cb02cf69d0p-4, -0x1.0c9704cd7f286p-4, -0x1.b3e4d5699ef20p-4, + -0x1.b3e4d5699ef20p-4, -0x1.0c9704cd7f286p-4, -0x1.fe1cb02cf69d0p-4, -0x1.5f6d06f0f5b26p-7, + -0x1.db6525a94fd02p-4, 0x1.7c3a9353c504dp-5, -0x1.53282a2cbc39ep-4, 0x1.7f8eca78fc7c9p-4, + -0x1.04fb817d3799bp-5, 0x1.ef178be50bcf1p-4, 0x1.a82a0d6d1445fp-6, 0x1.f4e605c65b0e9p-4, + 0x1.3fed94500288cp-4, 0x1.8fbcc94888bdap-4, 0x1.d17e7526f2190p-4, 0x1.aa6c80e924879p-5, + 0x1.ffa7301a0764dp-4, -0x1.2d865dc51796dp-8, 0x1.c08c428fe0fa2p-4, -0x1.edc19a019514fp-5, + 0x1.21a79c5f3a8dbp-4, -0x1.a63090c03a3ebp-4, 0x1.139f0fd9154f0p-6, -0x1.fb5795715d1a4p-4, + -0x1.4d1e270a9bf01p-5, -0x1.e426a5dbecde0p-4, -0x1.6e7444cbb37a4p-4, -0x1.659191c10260fp-4, + -0x1.e817bbb78b0c9p-4, -0x1.354108a838c07p-5, -0x1.f97f93185b213p-4, 0x1.45576d8e66e5bp-6, + -0x1.9ef43cccb6167p-4, 0x1.2bedb16e7f8e1p-4, -0x1.d79775730150ep-5, 0x1.c678b17627f40p-4, + -0x1.921d8a9834a4fp-10, 0x1.fff623abbd50bp-4, 0x1.c12499dfc8858p-5, 0x1.cc1f0eb16205cp-4, + 0x1.9777edf1207aep-4, 0x1.36058b87b3bb5p-4, 0x1.f7599b2fcd95dp-4, 0x1.76dd9886b6333p-6, + 0x1.ebbd8b47345cbp-4, -0x1.1d343f234f26dp-5, 0x1.771e7499510cfp-4, -0x1.5c77bd49e593bp-4, + 0x1.64c7d987fedeap-5, -0x1.dfeae98efcbadp-4, -0x1.c37866e52a32ap-7, -0x1.fce15fa4f2aafp-4, + -0x1.1734d47db6732p-4, -0x1.ad2bcd690d3d6p-4, -0x1.ba5aa66c3cfacp-4, -0x1.01cfc8ddabce6p-4, + -0x1.ff0957db31179p-4, -0x1.f656f496340fep-8, -0x1.d69614f9c28cep-4, 0x1.9372a730c4802p-5, + -0x1.49a44662108f2p-4, 0x1.87c3fd8ee825bp-4, -0x1.d934fe2a3f8e5p-6, 0x1.f2253173d63b7p-4, + 0x1.c0bd2d00fa63fp-3, -0x1.62efda5519981p-5, -0x1.cac1d54012856p-4, 0x1.81e2a37f74e44p-7, + -0x1.9d6b8ac5ff9d8p-6, -0x1.699128bcc5012p-4, 0x1.a9b4d71f5d8ddp-9, 0x1.d3e1379e08978p-7, + 0x1.a64c63eb4326bp-7, -0x1.d1ac696decfe3p-5, 0x1.14b7ab13910f7p-4, -0x1.1f861a9095daap-3, + 0x1.1791a0dcfbd04p-4, -0x1.aeeee39d73b88p-8, -0x1.96b5bb9211351p-5, -0x1.e6ab7894c8c85p-6, + -0x1.da7c1b31572cdp-5, 0x1.1db7905266d57p-3, 0x1.57e20ba8c90d8p-5, -0x1.0c864b95f40e3p-6, + -0x1.7f340ad831779p-6, -0x1.4ca30906c5c65p-4, -0x1.e6f4d6e414cfep-4, -0x1.3f9d901bd83d1p-5, + 0x1.10a7eb1b05f27p-3, 0x1.5922135ece8dap-7, -0x1.9f1e52263917cp-3, 0x1.c1df8e139f22dp-10, + 0x1.d2eb7185914f1p-5, -0x1.89defe360b76ep-8, -0x1.b1a981aca27fap-6, -0x1.b0eaf87935e33p-5, + 0x1.955db1e3f01f0p-7, 0x1.154848cabba7dp-3, -0x1.2e5425c82e2c6p-4, 0x1.04f9c3d81b622p-3, + 0x1.36e05a0f529acp-6, -0x1.ba6deb6e24a6bp-4, 0x1.48c5a628bc4ddp-3, 0x1.2b3d523d84c91p-4, + 0x1.a6b43030437d6p-3, -0x1.5419f38f1e352p-7, -0x1.728d318fbcf11p-5, 0x1.762c011ffb090p-5, + 0x1.c9faeefca624ep-9, 0x1.7779bfea945d5p-3, -0x1.ef106f80e1325p-8, 0x1.53d5c49e24d88p-3, + -0x1.18f311515be37p-6, 0x1.13ddd35812669p-3, 0x1.44473ec8db4b8p-5, 0x1.8cda1fad9f656p-4, + -0x1.32d2e9296cd98p-3, 0x1.97ebb8e85af41p-6, 0x1.b8e45acf2ee74p-4, -0x1.03a59bb2bcaf8p-5, + 0x1.c049f58b57f76p-7, -0x1.2caaccaf13f29p-4, -0x1.03bd1cb9fc8c2p-5, 0x1.037fa688684c8p-4, + -0x1.a38ddd5495bf2p-7, 0x1.0bd97804bf16bp-4, 0x1.01fd1c0de3133p-5, 0x1.5d81d21dbcc82p-4, + 0x1.5d81d21dbcc82p-4, 0x1.01fd1c0de3133p-5, 0x1.0bd97804bf16bp-4, -0x1.a38ddd5495bf2p-7, + 0x1.037fa688684c8p-4, -0x1.03bd1cb9fc8c2p-5, -0x1.2caaccaf13f29p-4, 0x1.c049f58b57f76p-7, + -0x1.03a59bb2bcaf8p-5, 0x1.b8e45acf2ee74p-4, 0x1.97ebb8e85af41p-6, -0x1.32d2e9296cd98p-3, + 0x1.8cda1fad9f656p-4, 0x1.44473ec8db4b8p-5, 0x1.13ddd35812669p-3, -0x1.18f311515be37p-6, + 0x1.53d5c49e24d88p-3, -0x1.ef106f80e1325p-8, 0x1.7779bfea945d5p-3, 0x1.c9faeefca624ep-9, + 0x1.762c011ffb090p-5, -0x1.728d318fbcf11p-5, -0x1.5419f38f1e352p-7, 0x1.a6b43030437d6p-3, + 0x1.2b3d523d84c91p-4, 0x1.48c5a628bc4ddp-3, -0x1.ba6deb6e24a6bp-4, 0x1.36e05a0f529acp-6, + 0x1.04f9c3d81b622p-3, -0x1.2e5425c82e2c6p-4, 0x1.154848cabba7dp-3, 0x1.955db1e3f01f0p-7, + -0x1.b0eaf87935e33p-5, -0x1.b1a981aca27fap-6, -0x1.89defe360b76ep-8, 0x1.d2eb7185914f1p-5, + 0x1.c1df8e139f22dp-10, -0x1.9f1e52263917cp-3, 0x1.5922135ece8dap-7, 0x1.10a7eb1b05f27p-3, + -0x1.3f9d901bd83d1p-5, -0x1.e6f4d6e414cfep-4, -0x1.4ca30906c5c65p-4, -0x1.7f340ad831779p-6, + -0x1.0c864b95f40e3p-6, 0x1.57e20ba8c90d8p-5, 0x1.1db7905266d57p-3, -0x1.da7c1b31572cdp-5, + -0x1.e6ab7894c8c85p-6, -0x1.96b5bb9211351p-5, -0x1.aeeee39d73b88p-8, 0x1.1791a0dcfbd04p-4, + -0x1.1f861a9095daap-3, 0x1.14b7ab13910f7p-4, -0x1.d1ac696decfe3p-5, 0x1.a64c63eb4326bp-7, + 0x1.d3e1379e08979p-7, 0x1.a9b4d71f5d8dcp-9, -0x1.699128bcc5013p-4, -0x1.9d6b8ac5ff9cep-6, + 0x1.81e2a37f74e4bp-7, -0x1.cac1d5401284ep-4, -0x1.62efda492486bp-5, 0x1.c0bd2cb3d7937p-3, + -0x1.298f875a49d65p-7, 0x1.198e07a4eab01p-3, 0x1.819f4353f017dp-4, -0x1.273ecea47c01fp-3, + 0x1.2a29b7d4ed78ep-3, -0x1.d84e3a7b8f264p-9, -0x1.318c2d33f4438p-5, -0x1.5c0db37d4f9adp-6, + 0x1.7dbd1b2263a9cp-3, -0x1.edeafbace14c0p-6, -0x1.2fd681a7e3318p-5, -0x1.e29ec4f7ba812p-4, + 0x1.5fccc775bea23p-8, 0x1.2ef4450298c81p-3, 0x1.667a4dd4c9c41p-4, -0x1.9d88d42e53be5p-4, + 0x1.1e4f96ff1d774p-4, 0x1.7bdcd3e59a3bep-4, 0x1.0944735bb0316p-6, -0x1.6151228b9aa99p-6, + 0x1.91a62dbc590ecp-3, 0x1.33930b36cc990p-5, -0x1.3afe60b3eef60p-4, -0x1.d570b67b28f14p-3, + -0x1.b2c81efacc59cp-4, 0x1.67f4cf37d1309p-4, 0x1.0598b3f1347aap-5, 0x1.7d64e76c35067p-5, + -0x1.c44a09a53f965p-9, 0x1.5adde7d05a8f9p-5, 0x1.6807f469a5449p-4, 0x1.6281e04e25b6ap-3, + 0x1.18b05267996fep-4, -0x1.bf9dfc47b2601p-5, -0x1.6a20ac272a867p-3, 0x1.5ccf9c3f1d2c9p-6, + -0x1.1f64bc2c65268p-6, -0x1.42dbfaec4ee52p-5, 0x1.d4a4a0a24c899p-5, 0x1.1a62c57065064p-4, + -0x1.3058b816cec1ep-5, 0x1.1ebd07f924acdp-8, 0x1.6f2f61244e488p-9, -0x1.165ab86df2eb6p-4, + 0x1.68a197429d2eap-4, 0x1.b313d32996a22p-8, -0x1.4dc88979e2c14p-4, -0x1.1b6fc5febb1d4p-6, + -0x1.ba24142b892e5p-4, -0x1.a3fc77aa3e8b7p-5, -0x1.5d1f6161d5d09p-4, 0x1.bae3b7cb39536p-5, + 0x1.a20e29e3c2abdp-12, -0x1.1eb39839ec968p-5, -0x1.23fda0ec263bep-9, -0x1.0ef764fa4bf75p-5, + 0x1.f0bc265bbf20cp-5, -0x1.a90ed06eb8ac6p-3, 0x1.c0a0d7098cf20p-5, -0x1.c7d0fafb8a3c1p-5, + 0x1.7cce753f9735ep-6, -0x1.2946066f82c05p-8, -0x1.d6489c62d28a3p-4, -0x1.09d3757ce9a13p-11, + -0x1.09d3757ce9a13p-11, -0x1.d6489c62d28a3p-4, -0x1.2946066f82c05p-8, 0x1.7cce753f9735ep-6, + -0x1.c7d0fafb8a3c1p-5, 0x1.c0a0d7098cf20p-5, -0x1.a90ed06eb8ac6p-3, 0x1.f0bc265bbf20cp-5, + -0x1.0ef764fa4bf75p-5, -0x1.23fda0ec263bep-9, -0x1.1eb39839ec968p-5, 0x1.a20e29e3c2abdp-12, + 0x1.bae3b7cb39536p-5, -0x1.5d1f6161d5d09p-4, -0x1.a3fc77aa3e8b7p-5, -0x1.ba24142b892e5p-4, + -0x1.1b6fc5febb1d4p-6, -0x1.4dc88979e2c14p-4, 0x1.b313d32996a22p-8, 0x1.68a197429d2eap-4, + -0x1.165ab86df2eb6p-4, 0x1.6f2f61244e488p-9, 0x1.1ebd07f924acdp-8, -0x1.3058b816cec1ep-5, + 0x1.1a62c57065064p-4, 0x1.d4a4a0a24c899p-5, -0x1.42dbfaec4ee52p-5, -0x1.1f64bc2c65268p-6, + 0x1.5ccf9c3f1d2c9p-6, -0x1.6a20ac272a867p-3, -0x1.bf9dfc47b2601p-5, 0x1.18b05267996fep-4, + 0x1.6281e04e25b6ap-3, 0x1.6807f469a5449p-4, 0x1.5adde7d05a8f9p-5, -0x1.c44a09a53f965p-9, + 0x1.7d64e76c35067p-5, 0x1.0598b3f1347aap-5, 0x1.67f4cf37d1309p-4, -0x1.b2c81efacc59cp-4, + -0x1.d570b67b28f14p-3, -0x1.3afe60b3eef60p-4, 0x1.33930b36cc990p-5, 0x1.91a62dbc590ecp-3, + -0x1.6151228b9aa99p-6, 0x1.0944735bb0316p-6, 0x1.7bdcd3e59a3bep-4, 0x1.1e4f96ff1d774p-4, + -0x1.9d88d42e53be5p-4, 0x1.667a4dd4c9c41p-4, 0x1.2ef4450298c81p-3, 0x1.5fccc775bea23p-8, + -0x1.e29ec4f7ba812p-4, -0x1.2fd681a7e3318p-5, -0x1.edeafbace14c0p-6, 0x1.7dbd1b2263a9cp-3, + -0x1.5c0db37d4f9a1p-6, -0x1.318c2d33f4445p-5, -0x1.d84e3a7b8f218p-9, 0x1.2a29b7d4ed790p-3, + -0x1.273ecea47c021p-3, 0x1.819f4353f017bp-4, 0x1.198e08621cb6ep-3, -0x1.298f875b38e5cp-7, + -0x1.04fb7fca2724dp-5, -0x1.ef178b7140c20p-4, 0x1.6591904280407p-4, 0x1.6e74453d45e5cp-4, + -0x1.ebbd8c5c23354p-4, -0x1.1d34409b59c5cp-5, 0x1.f2252f3164a73p-4, -0x1.d934fe28885e3p-6, + -0x1.771e73ddd007ep-4, 0x1.5c77bcb7e98cfp-4, 0x1.35410b5262241p-5, -0x1.e817b7d4d681dp-4, + 0x1.a82a04c914b7cp-6, 0x1.f4e607af68103p-4, -0x1.53282a1355796p-4, -0x1.7f8ecfccc36f0p-4, + 0x1.e426a40338f68p-4, 0x1.4d1e2452e188cp-5, -0x1.f7599aff1d50fp-4, 0x1.76dd930428989p-6, + 0x1.87c3ff8662516p-4, -0x1.49a449a5768e7p-4, -0x1.64c7db6ddc529p-5, 0x1.dfeae7813d7dcp-4, + -0x1.455769fa41b7fp-6, -0x1.f97f90fda40b7p-4, 0x1.3fed9520ff8d7p-4, 0x1.8fbcc9d7940f9p-4, + -0x1.db6526c20b589p-4, -0x1.7c3a94015b444p-5, 0x1.fb57985ead012p-4, -0x1.139f0f310378ap-6, + -0x1.9777ef6f6c3fep-4, 0x1.36058c3856de2p-4, 0x1.9372a511508fbp-5, -0x1.d696175fdf223p-4, + 0x1.c37863b3767a1p-7, 0x1.fce15db69ee38p-4, -0x1.2bedb2282836cp-4, -0x1.9ef43e55a322bp-4, + 0x1.d17e780d964f0p-4, 0x1.aa6c82a408b1cp-5, -0x1.fe1cb1280f42ep-4, 0x1.5f6d09ab6235cp-7, + 0x1.a630916c96da5p-4, -0x1.21a799ab3e80cp-4, -0x1.c124a0696913bp-5, 0x1.cc1f119198359p-4, + -0x1.f656e6ee84185p-8, -0x1.ff0954ca3ba7bp-4, 0x1.1734d45777a83p-4, 0x1.ad2bc78447cd9p-4, + -0x1.c678b33f3c0b9p-4, -0x1.d797798b583c6p-5, 0x1.ffa72e45f387dp-4, -0x1.2d865a1d57d13p-8, + -0x1.b3e4d33cfe94ap-4, 0x1.0c97046ed02fbp-4, 0x1.edc194e2bfab6p-5, -0x1.c08c402770298p-4, + 0x1.921cdadb5a527p-10, 0x1.fff6235e4fe7ap-4, -0x1.01cfc8ac57d01p-4, -0x1.ba5aa8f7fd032p-4, + 0x1.ba5aa8f7fd032p-4, 0x1.01cfc8ac57d01p-4, -0x1.fff6235e4fe7ap-4, -0x1.921cdadb5a527p-10, + 0x1.c08c402770298p-4, -0x1.edc194e2bfab6p-5, -0x1.0c97046ed02fbp-4, 0x1.b3e4d33cfe94ap-4, + 0x1.2d865a1d57d13p-8, -0x1.ffa72e45f387dp-4, 0x1.d797798b583c6p-5, 0x1.c678b33f3c0b9p-4, + -0x1.ad2bc78447cd9p-4, -0x1.1734d45777a83p-4, 0x1.ff0954ca3ba7bp-4, 0x1.f656e6ee84185p-8, + -0x1.cc1f119198359p-4, 0x1.c124a0696913bp-5, 0x1.21a799ab3e80cp-4, -0x1.a630916c96da5p-4, + -0x1.5f6d09ab6235cp-7, 0x1.fe1cb1280f42ep-4, -0x1.aa6c82a408b1cp-5, -0x1.d17e780d964f0p-4, + 0x1.9ef43e55a322bp-4, 0x1.2bedb2282836cp-4, -0x1.fce15db69ee38p-4, -0x1.c37863b3767a1p-7, + 0x1.d696175fdf223p-4, -0x1.9372a511508fbp-5, -0x1.36058c3856de2p-4, 0x1.9777ef6f6c3fep-4, + 0x1.139f0f310378ap-6, -0x1.fb57985ead012p-4, 0x1.7c3a94015b444p-5, 0x1.db6526c20b589p-4, + -0x1.8fbcc9d7940f9p-4, -0x1.3fed9520ff8d7p-4, 0x1.f97f90fda40b7p-4, 0x1.455769fa41b7fp-6, + -0x1.dfeae7813d7dcp-4, 0x1.64c7db6ddc529p-5, 0x1.49a449a5768e7p-4, -0x1.87c3ff8662516p-4, + -0x1.76dd930428989p-6, 0x1.f7599aff1d50fp-4, -0x1.4d1e2452e188cp-5, -0x1.e426a40338f68p-4, + 0x1.7f8ecfccc36f0p-4, 0x1.53282a1355796p-4, -0x1.f4e607af68103p-4, -0x1.a82a04c914b7cp-6, + 0x1.e817b7d4d681dp-4, -0x1.35410b5262241p-5, -0x1.5c77bcb7e98cfp-4, 0x1.771e73ddd007ep-4, + 0x1.d934fe28885e3p-6, -0x1.f2252f3164a73p-4, 0x1.1d34409b59c5cp-5, 0x1.ebbd8c5c23354p-4, + -0x1.6e74453d45e5cp-4, -0x1.6591904280407p-4, 0x1.ef178b7140c0dp-4, 0x1.04fb7fca2724ep-5, + 0x1.ef178c1412707p-4, -0x1.04fb7fd4bf28bp-5, 0x1.6e74446fbd585p-4, -0x1.65918fd55d3cap-4, + 0x1.1d344145d6464p-5, -0x1.ebbd8baf8c61ap-4, -0x1.d934ff3fd6edfp-6, -0x1.f2252e6815fa0p-4, + -0x1.5c77bcf8f9cffp-4, -0x1.771e7485ca12ep-4, -0x1.e817b7fdf1fdcp-4, -0x1.35410caec1824p-5, + -0x1.f4e606f7e9279p-4, 0x1.a82a042dc4623p-6, -0x1.7f8ecfb2568b7p-4, 0x1.53282a8fcd620p-4, + -0x1.4d1e247716ea9p-5, 0x1.e426a3caf56a2p-4, 0x1.76dd93a0ea3e7p-6, 0x1.f7599a85d7006p-4, + 0x1.49a44a15946b5p-4, 0x1.87c401041c8cdp-4, 0x1.dfeae72f59f4fp-4, 0x1.64c7db343b1c0p-5, + 0x1.f97f9055643b7p-4, -0x1.455768a8fefa3p-6, 0x1.8fbcc9af5e9fbp-4, -0x1.3fed93932a4e1p-4, + 0x1.7c3a94902e153p-5, -0x1.db65266977debp-4, -0x1.139f0f1579fcbp-6, -0x1.fb57990981cd7p-4, + -0x1.36058c0cf82e9p-4, -0x1.9777efb7e0b92p-4, -0x1.d6961733d87eep-4, -0x1.9372a60caf302p-5, + -0x1.fce15f16bd278p-4, 0x1.c37862f3a7092p-7, -0x1.9ef43e5a569a3p-4, 0x1.2bedb2bb4fb26p-4, + -0x1.aa6c81f0fe713p-5, 0x1.d17e792d8c056p-4, 0x1.5f6d0986bd216p-7, 0x1.fe1cb0c5e3ddcp-4, + 0x1.21a79ab4f6c6ep-4, 0x1.a6309003dfda0p-4, 0x1.cc1f10ba8a870p-4, 0x1.c124a046eda75p-5, + 0x1.ff09540907b47p-4, -0x1.f656e549f4521p-8, 0x1.ad2bc8f517184p-4, -0x1.1734d4c1a8e38p-4, + 0x1.d797798205fb0p-5, -0x1.c678b444d3041p-4, -0x1.2d865cca212d6p-8, -0x1.ffa72ecb0ab27p-4, + -0x1.0c97041e06f01p-4, -0x1.b3e4d350762bcp-4, -0x1.c08c40073e437p-4, -0x1.edc193fcce669p-5, + -0x1.fff624236d881p-4, 0x1.921cd0ed2b977p-10, -0x1.ba5aa7724e878p-4, 0x1.01cfc82f04cd2p-4, + -0x1.01cfc82f04cd2p-4, 0x1.ba5aa7724e878p-4, -0x1.921cd0ed2b977p-10, 0x1.fff624236d881p-4, + 0x1.edc193fcce669p-5, 0x1.c08c40073e437p-4, 0x1.b3e4d350762bcp-4, 0x1.0c97041e06f01p-4, + 0x1.ffa72ecb0ab27p-4, 0x1.2d865cca212d6p-8, 0x1.c678b444d3041p-4, -0x1.d797798205fb0p-5, + 0x1.1734d4c1a8e38p-4, -0x1.ad2bc8f517184p-4, 0x1.f656e549f4521p-8, -0x1.ff09540907b47p-4, + -0x1.c124a046eda75p-5, -0x1.cc1f10ba8a870p-4, -0x1.a6309003dfda0p-4, -0x1.21a79ab4f6c6ep-4, + -0x1.fe1cb0c5e3ddcp-4, -0x1.5f6d0986bd216p-7, -0x1.d17e792d8c056p-4, 0x1.aa6c81f0fe713p-5, + -0x1.2bedb2bb4fb26p-4, 0x1.9ef43e5a569a3p-4, -0x1.c37862f3a7092p-7, 0x1.fce15f16bd278p-4, + 0x1.9372a60caf302p-5, 0x1.d6961733d87eep-4, 0x1.9777efb7e0b92p-4, 0x1.36058c0cf82e9p-4, + 0x1.fb57990981cd7p-4, 0x1.139f0f1579fcbp-6, 0x1.db65266977debp-4, -0x1.7c3a94902e153p-5, + 0x1.3fed93932a4e1p-4, -0x1.8fbcc9af5e9fbp-4, 0x1.455768a8fefa3p-6, -0x1.f97f9055643b7p-4, + -0x1.64c7db343b1c0p-5, -0x1.dfeae72f59f4fp-4, -0x1.87c401041c8cdp-4, -0x1.49a44a15946b5p-4, + -0x1.f7599a85d7006p-4, -0x1.76dd93a0ea3e7p-6, -0x1.e426a3caf56a2p-4, 0x1.4d1e247716ea9p-5, + -0x1.53282a8fcd620p-4, 0x1.7f8ecfb2568b7p-4, -0x1.a82a042dc4623p-6, 0x1.f4e606f7e9279p-4, + 0x1.35410caec1824p-5, 0x1.e817b7fdf1fdcp-4, 0x1.771e7485ca12ep-4, 0x1.5c77bcf8f9cffp-4, + 0x1.f2252e6815fa0p-4, 0x1.d934ff3fd6edfp-6, 0x1.ebbd8baf8c61ap-4, -0x1.1d344145d6464p-5, + 0x1.65918fd55d3cap-4, -0x1.6e74446fbd585p-4, 0x1.04fb7fd4bf28bp-5, -0x1.ef178c141271dp-4, + 0x1.94540c01dba6cp-3, 0x1.3423a51737d5dp-5, 0x1.0dbb98ff09674p-4, -0x1.9743a758db35fp-3, + -0x1.5881441cf8c88p-4, -0x1.d05f77b25313cp-6, -0x1.65117ee32e4dbp-6, 0x1.3199a42beadfcp-4, + 0x1.51c3165d6c79ap-4, 0x1.8ba01b9acb038p-6, -0x1.3fe9658f7df7dp-6, -0x1.a01441c349bf6p-7, + 0x1.214889ac2b23dp-5, -0x1.8f01792cd9aafp-11, -0x1.1270c57494a5dp-4, -0x1.88dab558c8dc8p-4, + 0x1.b49be6efbc470p-7, 0x1.edb8bea511dc6p-5, -0x1.a5c0f7a448d39p-6, 0x1.e6da6b8e2da7bp-5, + 0x1.79b9ae95c356ap-4, -0x1.c3ffaa0bb54b2p-6, -0x1.21079f7f7b1d0p-5, 0x1.088c2f62fce4ep-5, + -0x1.64c89169266edp-4, -0x1.52c49f4203083p-6, 0x1.646c496742bd3p-3, -0x1.7557c12ae5093p-5, + 0x1.0dd630bcf0b3cp-4, 0x1.2ccd74018a315p-5, 0x1.3f092520e6e73p-6, -0x1.9a4a8a9717a40p-4, + -0x1.cb5d72430ffecp-6, -0x1.cd9bfb9bed3a7p-4, 0x1.e0f39a9ead8a6p-4, 0x1.318bad85d356dp-4, + 0x1.3d2386aeb6ed1p-3, -0x1.8c9213523fa60p-8, 0x1.4b9e4a0578cbfp-5, 0x1.af41f2ed12316p-7, + -0x1.8a7f4a447656ap-5, -0x1.28219642d8d92p-7, 0x1.423a7196c132bp-6, -0x1.0b3f4b091e5a2p-2, + -0x1.26a45746f3f49p-4, -0x1.0a61851bd4466p-4, 0x1.e8b485104aa2cp-8, -0x1.5f2c284386f57p-4, + 0x1.86dc4672e9bd1p-3, -0x1.394def1788255p-9, 0x1.fcba9586a6980p-6, -0x1.68286cdb29da1p-4, + -0x1.d6499c2b5b365p-5, -0x1.3ce544a3d5c17p-5, 0x1.c6413cdad6170p-7, 0x1.c1444bd686f79p-3, + -0x1.26ea34833c8a0p-4, 0x1.8d06b01cb7c0fp-4, -0x1.947cba219aac0p-4, -0x1.bfd3501ead9c4p-6, + 0x1.15b2ccf3e8fdcp-3, 0x1.3ece49edf9455p-7, -0x1.3ed2aa91bd81ap-4, 0x1.7da14fee8f411p-4, + -0x1.7da14fee8f411p-4, 0x1.3ed2aa91bd81ap-4, -0x1.3ece49edf9455p-7, -0x1.15b2ccf3e8fdcp-3, + 0x1.bfd3501ead9c4p-6, 0x1.947cba219aac0p-4, -0x1.8d06b01cb7c0fp-4, 0x1.26ea34833c8a0p-4, + -0x1.c1444bd686f79p-3, -0x1.c6413cdad6170p-7, 0x1.3ce544a3d5c17p-5, 0x1.d6499c2b5b365p-5, + 0x1.68286cdb29da1p-4, -0x1.fcba9586a6980p-6, 0x1.394def1788255p-9, -0x1.86dc4672e9bd1p-3, + 0x1.5f2c284386f57p-4, -0x1.e8b485104aa2cp-8, 0x1.0a61851bd4466p-4, 0x1.26a45746f3f49p-4, + 0x1.0b3f4b091e5a2p-2, -0x1.423a7196c132bp-6, 0x1.28219642d8d92p-7, 0x1.8a7f4a447656ap-5, + -0x1.af41f2ed12316p-7, -0x1.4b9e4a0578cbfp-5, 0x1.8c9213523fa60p-8, -0x1.3d2386aeb6ed1p-3, + -0x1.318bad85d356dp-4, -0x1.e0f39a9ead8a6p-4, 0x1.cd9bfb9bed3a7p-4, 0x1.cb5d72430ffecp-6, + 0x1.9a4a8a9717a40p-4, -0x1.3f092520e6e73p-6, -0x1.2ccd74018a315p-5, -0x1.0dd630bcf0b3cp-4, + 0x1.7557c12ae5093p-5, -0x1.646c496742bd3p-3, 0x1.52c49f4203083p-6, 0x1.64c89169266edp-4, + -0x1.088c2f62fce4ep-5, 0x1.21079f7f7b1d0p-5, 0x1.c3ffaa0bb54b2p-6, -0x1.79b9ae95c356ap-4, + -0x1.e6da6b8e2da7bp-5, 0x1.a5c0f7a448d39p-6, -0x1.edb8bea511dc6p-5, -0x1.b49be6efbc470p-7, + 0x1.88dab558c8dc8p-4, 0x1.1270c57494a5dp-4, 0x1.8f01792cd9aafp-11, -0x1.214889ac2b23dp-5, + 0x1.a01441c349bf6p-7, 0x1.3fe9658f7df7dp-6, -0x1.8ba01b9acb038p-6, -0x1.51c3165d6c79ap-4, + -0x1.3199a42beadfcp-4, 0x1.65117ee32e4ddp-6, 0x1.d05f77b25313ep-6, 0x1.5881441cf8c88p-4, + 0x1.9743a758db35fp-3, -0x1.0dbb98ff09676p-4, -0x1.3423a51ec89bdp-5, -0x1.94540bb52dee4p-3, + -0x1.fa3702e131d36p-6, -0x1.f4b2a73ebf781p-3, 0x1.296c32cab980ep-6, -0x1.d3b4de544c566p-4, + -0x1.6b5ae840ef4a5p-3, -0x1.109128ba2127bp-5, -0x1.5d484009e3521p-4, -0x1.b549c8f538349p-5, + -0x1.91fdd8ecab467p-5, -0x1.25abb9ca38cb2p-4, 0x1.e1d0b451bc049p-6, -0x1.4c559cbb60b5fp-6, + 0x1.e15c53df9ab4cp-8, -0x1.8d2dba71399c3p-4, -0x1.0116fd35b16ccp-3, -0x1.7bf3c20f60a4ep-14, + -0x1.0c628210c7004p-4, -0x1.032bbc3390662p-7, 0x1.8b7713e0958a5p-3, -0x1.384ed7d6822e8p-7, + 0x1.5081de9ff2300p-3, -0x1.6501a62215c85p-4, -0x1.286ad8fcaf04bp-6, -0x1.a43bd7826d3a0p-4, + 0x1.a023e7093ec80p-6, 0x1.590fd419e1dccp-4, -0x1.e814517833ba3p-5, 0x1.85b8a4b0d69b2p-4, + -0x1.c7b41dbd601eap-4, -0x1.0053fb343d835p-6, -0x1.968019ace8393p-6, 0x1.cfb1d00845ab2p-8, + -0x1.cc90be6b5d46fp-5, -0x1.184afbbab1fadp-7, 0x1.56000c86ca0cap-4, 0x1.4b47d784c70cfp-5, + -0x1.9109c2a69524ep-8, 0x1.6014c655664a8p-4, -0x1.48a98cc88f1c5p-4, 0x1.32e447b285ccep-6, + -0x1.d94ce057f0858p-5, 0x1.ddc7b60cc4517p-5, 0x1.3939c511e7695p-3, 0x1.0aaa8731296f1p-6, + -0x1.0d8be7ac5615cp-3, -0x1.4f9b55efa67c7p-4, -0x1.92dae8eb99372p-5, -0x1.6c8769387225bp-10, + -0x1.cecdc9646b625p-7, 0x1.61d935eb158cap-5, -0x1.5ae75ad75ca2cp-5, 0x1.1de86ba9e7b96p-3, + -0x1.eefa59dd571d5p-5, 0x1.801cd3efae90ep-4, 0x1.c4d52e4908effp-4, -0x1.6540e9f53302cp-6, + 0x1.b5e1eeb02e120p-3, -0x1.42dd1bfaa4373p-4, -0x1.282afd339d587p-5, -0x1.9b517118662dfp-4, + -0x1.2d2dffbf8bdefp-6, 0x1.f9a6fcde52070p-5, 0x1.6de4a12c487bap-4, 0x1.2c4d02f77cf77p-3, + -0x1.2c4d02f77cf77p-3, -0x1.6de4a12c487bap-4, -0x1.f9a6fcde52070p-5, 0x1.2d2dffbf8bdefp-6, + 0x1.9b517118662dfp-4, 0x1.282afd339d587p-5, 0x1.42dd1bfaa4373p-4, -0x1.b5e1eeb02e120p-3, + 0x1.6540e9f53302cp-6, -0x1.c4d52e4908effp-4, -0x1.801cd3efae90ep-4, 0x1.eefa59dd571d5p-5, + -0x1.1de86ba9e7b96p-3, 0x1.5ae75ad75ca2cp-5, -0x1.61d935eb158cap-5, 0x1.cecdc9646b625p-7, + 0x1.6c8769387225bp-10, 0x1.92dae8eb99372p-5, 0x1.4f9b55efa67c7p-4, 0x1.0d8be7ac5615cp-3, + -0x1.0aaa8731296f1p-6, -0x1.3939c511e7695p-3, -0x1.ddc7b60cc4517p-5, 0x1.d94ce057f0858p-5, + -0x1.32e447b285ccep-6, 0x1.48a98cc88f1c5p-4, -0x1.6014c655664a8p-4, 0x1.9109c2a69524ep-8, + -0x1.4b47d784c70cfp-5, -0x1.56000c86ca0cap-4, 0x1.184afbbab1fadp-7, 0x1.cc90be6b5d46fp-5, + -0x1.cfb1d00845ab2p-8, 0x1.968019ace8393p-6, 0x1.0053fb343d835p-6, 0x1.c7b41dbd601eap-4, + -0x1.85b8a4b0d69b2p-4, 0x1.e814517833ba3p-5, -0x1.590fd419e1dccp-4, -0x1.a023e7093ec80p-6, + 0x1.a43bd7826d3a0p-4, 0x1.286ad8fcaf04bp-6, 0x1.6501a62215c85p-4, -0x1.5081de9ff2300p-3, + 0x1.384ed7d6822e8p-7, -0x1.8b7713e0958a5p-3, 0x1.032bbc3390662p-7, 0x1.0c628210c7004p-4, + 0x1.7bf3c20f60a4ep-14, 0x1.0116fd35b16ccp-3, 0x1.8d2dba71399c3p-4, -0x1.e15c53df9ab4cp-8, + 0x1.4c559cbb60b5fp-6, -0x1.e1d0b451bc049p-6, 0x1.25abb9ca38cb2p-4, 0x1.91fdd8ecab467p-5, + 0x1.b549c8f53834ap-5, 0x1.5d484009e3521p-4, 0x1.109128ba212a1p-5, 0x1.6b5ae840ef4a4p-3, + 0x1.d3b4de544c559p-4, -0x1.296c32cab97ffp-6, 0x1.f4b2a6ab6d4a1p-3, 0x1.fa37026a3ad66p-6, + -0x1.1d3444190bd25p-5, -0x1.ebbd8ed18a45ep-4, 0x1.7f8ecf04e845bp-4, 0x1.5328286ca3e79p-4, + -0x1.f97f955706bfep-4, -0x1.45577277949f2p-6, 0x1.d69616c93c1c1p-4, -0x1.9372a7ef58e3fp-5, + -0x1.21a798c69795ep-4, 0x1.a630920b5cdc7p-4, 0x1.2d865ffaad8b7p-8, -0x1.ffa72e16f9de3p-4, + 0x1.01cfc90da2816p-4, 0x1.ba5aa4c1d3dd4p-4, -0x1.c678b2cb997c4p-4, -0x1.d79778cfb0ab9p-5, + 0x1.fe1cafbf6835ap-4, -0x1.5f6cffd2309e3p-7, -0x1.9777ef5b0f85ep-4, 0x1.3605896d3be0bp-4, + 0x1.64c7dc8ff7f0fp-5, -0x1.dfeae54242098p-4, 0x1.a829fc6fde697p-6, 0x1.f4e604aa93f99p-4, + -0x1.6591904462be2p-4, -0x1.6e7444111d255p-4, 0x1.f2253196b6db0p-4, 0x1.d93500c3e09bbp-6, + -0x1.e426a5fc655ecp-4, 0x1.4d1e2a7e79a02p-5, 0x1.3fed94cb910f9p-4, -0x1.8fbccb4315720p-4, + -0x1.c3786584a1df8p-7, 0x1.fce160503b734p-4, -0x1.c1249ce09191fp-5, -0x1.cc1f0e5a874a7p-4, + 0x1.b3e4d3e2a04c2p-4, 0x1.0c9706c3a6ac9p-4, -0x1.fff6237d47577p-4, 0x1.921d022974692p-10, + 0x1.ad2bc7f879785p-4, -0x1.1734d890c432ep-4, -0x1.aa6c82a16adcep-5, 0x1.d17e752ddcfdbp-4, + -0x1.139f02208ec31p-6, -0x1.fb57980ec2811p-4, 0x1.49a448004f39fp-4, 0x1.87c40021f2463p-4, + -0x1.e817b8448d594p-4, -0x1.3541079167cabp-5, 0x1.ef17890d53b42p-4, -0x1.04fb80a5b58e7p-5, + -0x1.5c77bb863c08dp-4, 0x1.771e743fabac4p-4, 0x1.76dd99c0b838cp-6, -0x1.f7599b2aea35ap-4, + 0x1.7c3a96620df11p-5, 0x1.db65251da7965p-4, -0x1.9ef440efafb39p-4, -0x1.2bedb008e8461p-4, + 0x1.ff095673a9af7p-4, 0x1.f656e02ad182dp-8, -0x1.c08c43bb3ef42p-4, 0x1.edc193fdc6602p-5, + 0x1.edc193fdc6602p-5, -0x1.c08c43bb3ef42p-4, 0x1.f656e02ad182dp-8, 0x1.ff095673a9af7p-4, + -0x1.2bedb008e8461p-4, -0x1.9ef440efafb39p-4, 0x1.db65251da7965p-4, 0x1.7c3a96620df11p-5, + -0x1.f7599b2aea35ap-4, 0x1.76dd99c0b838cp-6, 0x1.771e743fabac4p-4, -0x1.5c77bb863c08dp-4, + -0x1.04fb80a5b58e7p-5, 0x1.ef17890d53b42p-4, -0x1.3541079167cabp-5, -0x1.e817b8448d594p-4, + 0x1.87c40021f2463p-4, 0x1.49a448004f39fp-4, -0x1.fb57980ec2811p-4, -0x1.139f02208ec31p-6, + 0x1.d17e752ddcfdbp-4, -0x1.aa6c82a16adcep-5, -0x1.1734d890c432ep-4, 0x1.ad2bc7f879785p-4, + 0x1.921d022974692p-10, -0x1.fff6237d47577p-4, 0x1.0c9706c3a6ac9p-4, 0x1.b3e4d3e2a04c2p-4, + -0x1.cc1f0e5a874a7p-4, -0x1.c1249ce09191fp-5, 0x1.fce160503b734p-4, -0x1.c3786584a1df8p-7, + -0x1.8fbccb4315720p-4, 0x1.3fed94cb910f9p-4, 0x1.4d1e2a7e79a02p-5, -0x1.e426a5fc655ecp-4, + 0x1.d93500c3e09bbp-6, 0x1.f2253196b6db0p-4, -0x1.6e7444111d255p-4, -0x1.6591904462be2p-4, + 0x1.f4e604aa93f99p-4, 0x1.a829fc6fde697p-6, -0x1.dfeae54242098p-4, 0x1.64c7dc8ff7f0fp-5, + 0x1.3605896d3be0bp-4, -0x1.9777ef5b0f85ep-4, -0x1.5f6cffd2309e3p-7, 0x1.fe1cafbf6835ap-4, + -0x1.d79778cfb0ab9p-5, -0x1.c678b2cb997c4p-4, 0x1.ba5aa4c1d3dd4p-4, 0x1.01cfc90da2816p-4, + -0x1.ffa72e16f9de3p-4, 0x1.2d865ffaad8b7p-8, 0x1.a630920b5cdc7p-4, -0x1.21a798c69795ep-4, + -0x1.9372a7ef58e3fp-5, 0x1.d69616c93c1c1p-4, -0x1.45577277949f2p-6, -0x1.f97f955706bfep-4, + 0x1.5328286ca3e79p-4, 0x1.7f8ecf04e845bp-4, -0x1.ebbd8ed18a474p-4, -0x1.1d3444190bd23p-5, + 0x1.ebbd8e3913259p-4, -0x1.1d3445678001ep-5, 0x1.532827e1066e3p-4, -0x1.7f8ece91cd49ep-4, + 0x1.455773595a80bp-6, -0x1.f97f956f9512ap-4, -0x1.9372a8d82682cp-5, -0x1.d696177eca380p-4, + -0x1.a6309288662cep-4, -0x1.21a798fe86474p-4, -0x1.ffa72e9ed81d9p-4, -0x1.2d865f69c3bd5p-8, + -0x1.ba5aa4a01ee48p-4, 0x1.01cfc882dfa8fp-4, -0x1.d79778d761857p-5, 0x1.c678b223cd4dep-4, + 0x1.5f6d00e4c42f5p-7, 0x1.fe1caeed83637p-4, 0x1.360587ee1ad78p-4, 0x1.9777eec7b37e3p-4, + 0x1.dfeae4f31dfd7p-4, 0x1.64c7dc4ca0bb3p-5, 0x1.f4e604e0c2cf5p-4, -0x1.a829fbed28712p-6, + 0x1.6e74454449a2cp-4, -0x1.659190f65b537p-4, 0x1.d935015f6bfcap-6, -0x1.f225313d02892p-4, + -0x1.4d1e2a82a3e36p-5, -0x1.e426a70d0be17p-4, -0x1.8fbccb4284a4bp-4, -0x1.3fed94832d9e0p-4, + -0x1.fce160671992fp-4, -0x1.c378648dff4fdp-7, -0x1.cc1f0ef087915p-4, 0x1.c1249ce39d8afp-5, + -0x1.0c97067ebae10p-4, 0x1.b3e4d2558a5a9p-4, 0x1.921d0133df544p-10, 0x1.fff6239f3f08dp-4, + 0x1.1734d82482b02p-4, 0x1.ad2bc93076151p-4, 0x1.d17e74513630ap-4, 0x1.aa6c832dc718ep-5, + 0x1.fb5797ac6660cp-4, -0x1.139f02225aeedp-6, 0x1.87c400951d79fp-4, -0x1.49a447f38f189p-4, + 0x1.3541092743b30p-5, -0x1.e817b8f9c7c59p-4, -0x1.04fb804057315p-5, -0x1.ef1788865ce23p-4, + -0x1.771e7489038e6p-4, -0x1.5c77bcf537fe8p-4, -0x1.f75999f99eeb9p-4, -0x1.76dd99bcbf53fp-6, + -0x1.db65251ec3a36p-4, 0x1.7c3a96a7ddf1bp-5, -0x1.2bedb09d60014p-4, 0x1.9ef440d8a2b21p-4, + -0x1.f656e0b247b9dp-8, 0x1.ff0956bb0cbc3p-4, 0x1.edc1946ef3c2ep-5, 0x1.c08c43d41ad18p-4, + 0x1.c08c43d41ad18p-4, 0x1.edc1946ef3c2ep-5, 0x1.ff0956bb0cbc3p-4, -0x1.f656e0b247b9dp-8, + 0x1.9ef440d8a2b21p-4, -0x1.2bedb09d60014p-4, 0x1.7c3a96a7ddf1bp-5, -0x1.db65251ec3a36p-4, + -0x1.76dd99bcbf53fp-6, -0x1.f75999f99eeb9p-4, -0x1.5c77bcf537fe8p-4, -0x1.771e7489038e6p-4, + -0x1.ef1788865ce23p-4, -0x1.04fb804057315p-5, -0x1.e817b8f9c7c59p-4, 0x1.3541092743b30p-5, + -0x1.49a447f38f189p-4, 0x1.87c400951d79fp-4, -0x1.139f02225aeedp-6, 0x1.fb5797ac6660cp-4, + 0x1.aa6c832dc718ep-5, 0x1.d17e74513630ap-4, 0x1.ad2bc93076151p-4, 0x1.1734d82482b02p-4, + 0x1.fff6239f3f08dp-4, 0x1.921d0133df544p-10, 0x1.b3e4d2558a5a9p-4, -0x1.0c97067ebae10p-4, + 0x1.c1249ce39d8afp-5, -0x1.cc1f0ef087915p-4, -0x1.c378648dff4fdp-7, -0x1.fce160671992fp-4, + -0x1.3fed94832d9e0p-4, -0x1.8fbccb4284a4bp-4, -0x1.e426a70d0be17p-4, -0x1.4d1e2a82a3e36p-5, + -0x1.f225313d02892p-4, 0x1.d935015f6bfcap-6, -0x1.659190f65b537p-4, 0x1.6e74454449a2cp-4, + -0x1.a829fbed28712p-6, 0x1.f4e604e0c2cf5p-4, 0x1.64c7dc4ca0bb3p-5, 0x1.dfeae4f31dfd7p-4, + 0x1.9777eec7b37e3p-4, 0x1.360587ee1ad78p-4, 0x1.fe1caeed83637p-4, 0x1.5f6d00e4c42f5p-7, + 0x1.c678b223cd4dep-4, -0x1.d79778d761857p-5, 0x1.01cfc882dfa8fp-4, -0x1.ba5aa4a01ee48p-4, + -0x1.2d865f69c3bd5p-8, -0x1.ffa72e9ed81d9p-4, -0x1.21a798fe86474p-4, -0x1.a6309288662cep-4, + -0x1.d696177eca380p-4, -0x1.9372a8d82682cp-5, -0x1.f97f956f9512ap-4, 0x1.455773595a80bp-6, + -0x1.7f8ece91cd49ep-4, 0x1.532827e1066e3p-4, -0x1.1d3445678001fp-5, 0x1.ebbd8e3913258p-4, + 0x1.ad14b58074146p-3, -0x1.91f93b57a6d24p-6, -0x1.7f80845c50986p-6, 0x1.18a89a8e9bc4bp-3, + -0x1.51ca7b7567c4ap-6, 0x1.a6b0546f70c3fp-3, -0x1.68cec2bf72b96p-7, 0x1.a342833ec26e7p-5, + -0x1.5f9619df08601p-3, 0x1.6a0ba5fe7de24p-5, -0x1.b2188c77920efp-12, -0x1.cb0f1360434eap-6, + 0x1.7b76ca9ded6e7p-6, 0x1.b33f5ad373549p-7, 0x1.1c8ae5ae5e9d4p-5, 0x1.b90377602e610p-7, + 0x1.d7b2b20a80503p-6, -0x1.bb81cbfc6fd79p-6, 0x1.66f5a594f6756p-4, 0x1.06fc5e3fc153dp-4, + -0x1.9865d440e6999p-4, -0x1.2fc91d8effc7fp-4, 0x1.ddc29ca84a46fp-5, 0x1.ab3f83c364f1ep-6, + 0x1.449c318ca13fep-7, 0x1.59afae8650345p-3, -0x1.9e897fbfc9409p-6, 0x1.44c3a03515bc7p-5, + -0x1.b3c33ddcf1442p-7, -0x1.25d7d818eb7f2p-4, -0x1.e3f0ae67acfc8p-10, -0x1.83b857ca38ec8p-6, + -0x1.e9fa03136a76fp-4, 0x1.27f69b9030670p-8, 0x1.ea2883ff95c5bp-4, -0x1.b22a2020683aap-8, + -0x1.7c1c98e7169a3p-7, 0x1.5c96db3a72e2ap-3, -0x1.cf898c5c1f623p-6, -0x1.6930d4c0f4c60p-4, + -0x1.404d31396db34p-4, -0x1.2e435e723e671p-3, 0x1.a157126cd5239p-8, -0x1.60a7823ae1d29p-5, + -0x1.da9123a2dfecdp-4, -0x1.11abf8b2e4a48p-5, -0x1.faef61a778022p-4, -0x1.a030be35a5da1p-3, + -0x1.1cf787b77efa6p-3, 0x1.e051e88b37b8ep-4, 0x1.a8f7602c1bd8ap-6, -0x1.9cf7d294d0158p-4, + -0x1.5f84384ece96cp-3, -0x1.1b1a5c1bc3b87p-4, -0x1.3f9c1c70a1236p-4, -0x1.9155625cbd2d0p-5, + -0x1.0cb4d14b9e9c5p-4, -0x1.b7414bb8cd5f6p-5, 0x1.184f7929421eap-4, 0x1.8fb6e24a2e70dp-4, + 0x1.6e2c314be7c6bp-6, -0x1.e491bca7de47ep-5, 0x1.ea6b98e54bb2bp-5, 0x1.e8cb0479acf67p-5, + 0x1.e8cb0479acf67p-5, 0x1.ea6b98e54bb2bp-5, -0x1.e491bca7de47ep-5, 0x1.6e2c314be7c6bp-6, + 0x1.8fb6e24a2e70dp-4, 0x1.184f7929421eap-4, -0x1.b7414bb8cd5f6p-5, -0x1.0cb4d14b9e9c5p-4, + -0x1.9155625cbd2d0p-5, -0x1.3f9c1c70a1236p-4, -0x1.1b1a5c1bc3b87p-4, -0x1.5f84384ece96cp-3, + -0x1.9cf7d294d0158p-4, 0x1.a8f7602c1bd8ap-6, 0x1.e051e88b37b8ep-4, -0x1.1cf787b77efa6p-3, + -0x1.a030be35a5da1p-3, -0x1.faef61a778022p-4, -0x1.11abf8b2e4a48p-5, -0x1.da9123a2dfecdp-4, + -0x1.60a7823ae1d29p-5, 0x1.a157126cd5239p-8, -0x1.2e435e723e671p-3, -0x1.404d31396db34p-4, + -0x1.6930d4c0f4c60p-4, -0x1.cf898c5c1f623p-6, 0x1.5c96db3a72e2ap-3, -0x1.7c1c98e7169a3p-7, + -0x1.b22a2020683aap-8, 0x1.ea2883ff95c5bp-4, 0x1.27f69b9030670p-8, -0x1.e9fa03136a76fp-4, + -0x1.83b857ca38ec8p-6, -0x1.e3f0ae67acfc8p-10, -0x1.25d7d818eb7f2p-4, -0x1.b3c33ddcf1442p-7, + 0x1.44c3a03515bc7p-5, -0x1.9e897fbfc9409p-6, 0x1.59afae8650345p-3, 0x1.449c318ca13fep-7, + 0x1.ab3f83c364f1ep-6, 0x1.ddc29ca84a46fp-5, -0x1.2fc91d8effc7fp-4, -0x1.9865d440e6999p-4, + 0x1.06fc5e3fc153dp-4, 0x1.66f5a594f6756p-4, -0x1.bb81cbfc6fd79p-6, 0x1.d7b2b20a80503p-6, + 0x1.b90377602e610p-7, 0x1.1c8ae5ae5e9d4p-5, 0x1.b33f5ad373549p-7, 0x1.7b76ca9ded6e7p-6, + -0x1.cb0f1360434eap-6, -0x1.b2188c77920efp-12, 0x1.6a0ba5fe7de24p-5, -0x1.5f9619df08601p-3, + 0x1.a342833ec26e7p-5, -0x1.68cec2bf72bc8p-7, 0x1.a6b0546f70c43p-3, -0x1.51ca7b7567c1cp-6, + 0x1.18a89a8e9bc4bp-3, -0x1.7f80845c5097fp-6, -0x1.91f93b6b1d418p-6, 0x1.ad14b56a3b52fp-3, + 0x1.22ee50c2a0528p-6, -0x1.0d280d68c470ep-5, -0x1.0842fbec515cdp-3, 0x1.7f95879c4e679p-5, + -0x1.b703e58214b81p-6, 0x1.d8ac52b55d414p-7, 0x1.2861aa58f3a5ap-3, -0x1.ac2aed8f676eap-5, + -0x1.44848be1ea37dp-5, 0x1.52ff7eba8906cp-3, 0x1.80d895d10f663p-7, -0x1.d0bcc3dcee1fbp-6, + -0x1.ffdb0e81d1bb4p-5, -0x1.3e3f702eca50ep-3, 0x1.676afe6dc0e7fp-4, -0x1.ba17b1860ed9ep-5, + 0x1.1ce13c3aabfe2p-5, -0x1.8965b7b4a7a51p-6, 0x1.068f9ef84fffcp-3, -0x1.567aed9c49460p-4, + -0x1.37cd5df459d4bp-5, 0x1.4e81a991de0a0p-3, 0x1.585545bd34f5cp-8, 0x1.7baeb7e3fc417p-3, + -0x1.62cbffeb5a04fp-4, -0x1.add203bce9166p-4, -0x1.0b4c3cfa11975p-3, -0x1.2eae0306dcfbdp-6, + -0x1.2dcb4e03d2cf2p-3, -0x1.8b0756e682ec9p-6, -0x1.b6e8e3378bd6dp-6, 0x1.d1b5e8e6d49f6p-5, + -0x1.098607c217617p-6, -0x1.3517cc262a715p-5, -0x1.68c3a0a7595cep-7, 0x1.383108b182b04p-5, + -0x1.c7b5cdac91b95p-3, 0x1.2b81ffbacacdep-5, -0x1.c1d05ef6c3b4fp-7, -0x1.8d3b974161b4ap-6, + 0x1.bb86e67add9fep-3, -0x1.3318b5c2b49adp-4, 0x1.699f552f02859p-5, 0x1.5859bfcea75b9p-4, + -0x1.8aee956a730b0p-5, 0x1.0d816e61f1178p-2, 0x1.1253adadbc94bp-7, 0x1.275603193ba5bp-4, + 0x1.6986db5f092b2p-6, -0x1.29547c2b30384p-7, -0x1.378d694b33ea3p-4, 0x1.1ba74d1fe0977p-6, + -0x1.555b0cd3cd4efp-4, -0x1.301b6cf67de9dp-5, 0x1.d548d7b8f9262p-6, 0x1.6a32ca00a69cdp-4, + 0x1.0688fcda83591p-4, 0x1.11785307f96bdp-4, -0x1.1de62998834aap-5, 0x1.ef68c0f3456d6p-7, + 0x1.bd8467d565b84p-6, -0x1.634d54ec00489p-6, -0x1.07bc584f9ff17p-5, 0x1.63f115b95121dp-4, + 0x1.63f115b95121dp-4, -0x1.07bc584f9ff17p-5, -0x1.634d54ec00489p-6, 0x1.bd8467d565b84p-6, + 0x1.ef68c0f3456d6p-7, -0x1.1de62998834aap-5, 0x1.11785307f96bdp-4, 0x1.0688fcda83591p-4, + 0x1.6a32ca00a69cdp-4, 0x1.d548d7b8f9262p-6, -0x1.301b6cf67de9dp-5, -0x1.555b0cd3cd4efp-4, + 0x1.1ba74d1fe0977p-6, -0x1.378d694b33ea3p-4, -0x1.29547c2b30384p-7, 0x1.6986db5f092b2p-6, + 0x1.275603193ba5bp-4, 0x1.1253adadbc94bp-7, 0x1.0d816e61f1178p-2, -0x1.8aee956a730b0p-5, + 0x1.5859bfcea75b9p-4, 0x1.699f552f02859p-5, -0x1.3318b5c2b49adp-4, 0x1.bb86e67add9fep-3, + -0x1.8d3b974161b4ap-6, -0x1.c1d05ef6c3b4fp-7, 0x1.2b81ffbacacdep-5, -0x1.c7b5cdac91b95p-3, + 0x1.383108b182b04p-5, -0x1.68c3a0a7595cep-7, -0x1.3517cc262a715p-5, -0x1.098607c217617p-6, + 0x1.d1b5e8e6d49f6p-5, -0x1.b6e8e3378bd6dp-6, -0x1.8b0756e682ec9p-6, -0x1.2dcb4e03d2cf2p-3, + -0x1.2eae0306dcfbdp-6, -0x1.0b4c3cfa11975p-3, -0x1.add203bce9166p-4, -0x1.62cbffeb5a04fp-4, + 0x1.7baeb7e3fc417p-3, 0x1.585545bd34f5cp-8, 0x1.4e81a991de0a0p-3, -0x1.37cd5df459d4bp-5, + -0x1.567aed9c49460p-4, 0x1.068f9ef84fffcp-3, -0x1.8965b7b4a7a51p-6, 0x1.1ce13c3aabfe2p-5, + -0x1.ba17b1860ed9ep-5, 0x1.676afe6dc0e7fp-4, -0x1.3e3f702eca50ep-3, -0x1.ffdb0e81d1bb4p-5, + -0x1.d0bcc3dcee1fbp-6, 0x1.80d895d10f663p-7, 0x1.52ff7eba8906cp-3, -0x1.44848be1ea37dp-5, + -0x1.ac2aed8f676e5p-5, 0x1.2861aa58f3a5cp-3, 0x1.d8ac52b55d444p-7, -0x1.b703e58214b76p-6, + 0x1.7f95879c4e677p-5, -0x1.0842fbec515d3p-3, -0x1.0d280c11ba1a9p-5, 0x1.22ee50824a649p-6, + -0x1.35410ce5bded7p-5, -0x1.e817bbee492b0p-4, 0x1.9777f09ad849ap-4, 0x1.3605885df66aep-4, + -0x1.ffa72e01ee6c8p-4, -0x1.2d8651ef75084p-8, 0x1.ad2bcb509e664p-4, -0x1.1734d7f60da12p-4, + -0x1.7c3a94ab590d1p-5, 0x1.db652722833bap-4, -0x1.d934f8a4480c0p-6, -0x1.f2252f40750dap-4, + 0x1.7f8ec9c00fa64p-4, 0x1.5328281507c39p-4, -0x1.fce15fe49381cp-4, -0x1.c37857a78421ep-7, + 0x1.c08c4598f9e03p-4, -0x1.edc1932ac84c2p-5, -0x1.c1249c24f4566p-5, 0x1.cc1f0ecdd0162p-4, + -0x1.455767c8583f5p-6, -0x1.f97f907e15e0ap-4, 0x1.6591944c4e4fbp-4, 0x1.6e7443b5d1051p-4, + -0x1.f759996756fd8p-4, -0x1.76dd9d4cab7cfp-6, 0x1.d17e75875a370p-4, -0x1.aa6c836e7c447p-5, + -0x1.01cfc7ef6cbd1p-4, 0x1.ba5aa789a84e5p-4, -0x1.5f6d07dc69c7ep-7, -0x1.fe1cb16ce75f6p-4, + 0x1.49a449402ab43p-4, 0x1.87c4035d1fd39p-4, -0x1.ef1788b3bf034p-4, -0x1.04fb840d9a4f7p-5, + 0x1.dfeae7599e74bp-4, -0x1.64c7dc5001fb8p-5, -0x1.21a79825c05c0p-4, 0x1.a6309289918cep-4, + -0x1.921d3a209672ap-10, -0x1.fff621b1c1b86p-4, 0x1.2bedb208d19afp-4, 0x1.9ef43e944a049p-4, + -0x1.e426a586ae390p-4, -0x1.4d1e2483235f8p-5, 0x1.ebbd8b70fe4d7p-4, -0x1.1d34460edf67cp-5, + -0x1.3fed97071d6e2p-4, 0x1.8fbccb6059de8p-4, 0x1.f656d61939760p-8, -0x1.ff09551aa75a3p-4, + 0x1.0c9706626f8e4p-4, 0x1.b3e4d488c76c8p-4, -0x1.d69617432677bp-4, -0x1.9372a6a4823d2p-5, + 0x1.f4e601fb2d94cp-4, -0x1.a82a06bbf35aap-6, -0x1.5c77bbaada80cp-4, 0x1.771e770cda42dp-4, + 0x1.139f146f9a82bp-6, -0x1.fb57955aa7cb4p-4, 0x1.d797753cea389p-5, 0x1.c678b41e6c58ap-4, + -0x1.c678b41e6c58ap-4, -0x1.d797753cea389p-5, 0x1.fb57955aa7cb4p-4, -0x1.139f146f9a82bp-6, + -0x1.771e770cda42dp-4, 0x1.5c77bbaada80cp-4, 0x1.a82a06bbf35aap-6, -0x1.f4e601fb2d94cp-4, + 0x1.9372a6a4823d2p-5, 0x1.d69617432677bp-4, -0x1.b3e4d488c76c8p-4, -0x1.0c9706626f8e4p-4, + 0x1.ff09551aa75a3p-4, -0x1.f656d61939760p-8, -0x1.8fbccb6059de8p-4, 0x1.3fed97071d6e2p-4, + 0x1.1d34460edf67cp-5, -0x1.ebbd8b70fe4d7p-4, 0x1.4d1e2483235f8p-5, 0x1.e426a586ae390p-4, + -0x1.9ef43e944a049p-4, -0x1.2bedb208d19afp-4, 0x1.fff621b1c1b86p-4, 0x1.921d3a209672ap-10, + -0x1.a6309289918cep-4, 0x1.21a79825c05c0p-4, 0x1.64c7dc5001fb8p-5, -0x1.dfeae7599e74bp-4, + 0x1.04fb840d9a4f7p-5, 0x1.ef1788b3bf034p-4, -0x1.87c4035d1fd39p-4, -0x1.49a449402ab43p-4, + 0x1.fe1cb16ce75f6p-4, 0x1.5f6d07dc69c7ep-7, -0x1.ba5aa789a84e5p-4, 0x1.01cfc7ef6cbd1p-4, + 0x1.aa6c836e7c447p-5, -0x1.d17e75875a370p-4, 0x1.76dd9d4cab7cfp-6, 0x1.f759996756fd8p-4, + -0x1.6e7443b5d1051p-4, -0x1.6591944c4e4fbp-4, 0x1.f97f907e15e0ap-4, 0x1.455767c8583f5p-6, + -0x1.cc1f0ecdd0162p-4, 0x1.c1249c24f4566p-5, 0x1.edc1932ac84c2p-5, -0x1.c08c4598f9e03p-4, + 0x1.c37857a78421ep-7, 0x1.fce15fe49381cp-4, -0x1.5328281507c39p-4, -0x1.7f8ec9c00fa64p-4, + 0x1.f2252f40750dap-4, 0x1.d934f8a4480c0p-6, -0x1.db652722833bap-4, 0x1.7c3a94ab590d1p-5, + 0x1.1734d7f60da12p-4, -0x1.ad2bcb509e664p-4, 0x1.2d8651ef75084p-8, 0x1.ffa72e01ee6c8p-4, + -0x1.3605885df66aep-4, -0x1.9777f09ad849ap-4, 0x1.e817bbee492a9p-4, 0x1.35410ce5bded6p-5, + 0x1.e817bba5292b9p-4, -0x1.35410b1f03f68p-5, 0x1.360587fa8b8e1p-4, -0x1.9777f0ca5994ap-4, + 0x1.2d8652ea6ac42p-8, -0x1.ffa72d607bdecp-4, -0x1.1734d7b551cb3p-4, -0x1.ad2bcc705dd13p-4, + -0x1.db6526be85f57p-4, -0x1.7c3a94052efdcp-5, -0x1.f2253028cbf3bp-4, 0x1.d934f97f1c9fcp-6, + -0x1.532827e8a9734p-4, 0x1.7f8eca4b146dfp-4, -0x1.c378572bf6262p-7, 0x1.fce15ffdffc4bp-4, + 0x1.edc193f1c447ap-5, 0x1.c08c442a36ce5p-4, 0x1.cc1f0e46343c1p-4, 0x1.c1249b7aba082p-5, + 0x1.f97f908afd23ap-4, -0x1.4557673f12977p-6, 0x1.6e744379d0a66p-4, -0x1.659194b08a4e0p-4, + 0x1.76dd9c8a5cc78p-6, -0x1.f7599b169ef17p-4, -0x1.aa6c840bb1e4cp-5, -0x1.d17e741eb53bfp-4, + -0x1.ba5aa864bca75p-4, -0x1.01cfc8099daa6p-4, -0x1.fe1cb0f3bb56bp-4, 0x1.5f6d0a1efbecbp-7, + -0x1.87c402c086bb6p-4, 0x1.49a44a456ee25p-4, -0x1.04fb83a78188bp-5, 0x1.ef1787eeab5a3p-4, + 0x1.64c7dca25c41dp-5, 0x1.dfeae8fde518dp-4, 0x1.a63091f8312f8p-4, 0x1.21a7978ff988cp-4, + 0x1.fff62227a661dp-4, -0x1.921d346975e92p-10, 0x1.9ef43ec440de1p-4, -0x1.2bedb23c60b00p-4, + 0x1.4d1e23e70af54p-5, -0x1.e426a4d24dfebp-4, -0x1.1d34467932043p-5, -0x1.ebbd8b744a113p-4, + -0x1.8fbcca759ecc5p-4, -0x1.3fed96e7056e8p-4, -0x1.ff09548d9d5edp-4, -0x1.f656d45f8cfbap-8, + -0x1.b3e4d43db7c45p-4, 0x1.0c9705b4f8c14p-4, -0x1.9372a6b502eaap-5, 0x1.d69617d5c3b78p-4, + 0x1.a82a049ea21c5p-6, 0x1.f4e6018cc0b9ap-4, 0x1.771e76b043e3ap-4, 0x1.5c77bc3be9e39p-4, + 0x1.fb5796a0c5634p-4, 0x1.139f14c0cdd42p-6, 0x1.c678b4e6fbcd5p-4, -0x1.d797753a21371p-5, + 0x1.d797753a21371p-5, -0x1.c678b4e6fbcd5p-4, -0x1.139f14c0cdd42p-6, -0x1.fb5796a0c5634p-4, + -0x1.5c77bc3be9e39p-4, -0x1.771e76b043e3ap-4, -0x1.f4e6018cc0b9ap-4, -0x1.a82a049ea21c5p-6, + -0x1.d69617d5c3b78p-4, 0x1.9372a6b502eaap-5, -0x1.0c9705b4f8c14p-4, 0x1.b3e4d43db7c45p-4, + 0x1.f656d45f8cfbap-8, 0x1.ff09548d9d5edp-4, 0x1.3fed96e7056e8p-4, 0x1.8fbcca759ecc5p-4, + 0x1.ebbd8b744a113p-4, 0x1.1d34467932043p-5, 0x1.e426a4d24dfebp-4, -0x1.4d1e23e70af54p-5, + 0x1.2bedb23c60b00p-4, -0x1.9ef43ec440de1p-4, 0x1.921d346975e92p-10, -0x1.fff62227a661dp-4, + -0x1.21a7978ff988cp-4, -0x1.a63091f8312f8p-4, -0x1.dfeae8fde518dp-4, -0x1.64c7dca25c41dp-5, + -0x1.ef1787eeab5a3p-4, 0x1.04fb83a78188bp-5, -0x1.49a44a456ee25p-4, 0x1.87c402c086bb6p-4, + -0x1.5f6d0a1efbecbp-7, 0x1.fe1cb0f3bb56bp-4, 0x1.01cfc8099daa6p-4, 0x1.ba5aa864bca75p-4, + 0x1.d17e741eb53bfp-4, 0x1.aa6c840bb1e4cp-5, 0x1.f7599b169ef17p-4, -0x1.76dd9c8a5cc78p-6, + 0x1.659194b08a4e0p-4, -0x1.6e744379d0a66p-4, 0x1.4557673f12977p-6, -0x1.f97f908afd23ap-4, + -0x1.c1249b7aba082p-5, -0x1.cc1f0e46343c1p-4, -0x1.c08c442a36ce5p-4, -0x1.edc193f1c447ap-5, + -0x1.fce15ffdffc4bp-4, 0x1.c378572bf6262p-7, -0x1.7f8eca4b146dfp-4, 0x1.532827e8a9734p-4, + -0x1.d934f97f1c9fcp-6, 0x1.f2253028cbf3bp-4, 0x1.7c3a94052efdcp-5, 0x1.db6526be85f57p-4, + 0x1.ad2bcc705dd13p-4, 0x1.1734d7b551cb3p-4, 0x1.ffa72d607bdecp-4, -0x1.2d8652ea6ac42p-8, + 0x1.9777f0ca5994ap-4, -0x1.360587fa8b8e1p-4, 0x1.35410b1f03f68p-5, -0x1.e817bba5292c8p-4, + 0x1.0c1c4f70f1183p-3, -0x1.cb7456f02b5b3p-4, 0x1.52c822d9ad8dep-4, 0x1.d5cb9d0fdf602p-4, + 0x1.7ec34fe6350bep-8, 0x1.82fc098ae4c4dp-7, -0x1.1519267af15d4p-3, 0x1.91d4718ff923bp-8, + 0x1.68eb2cd93ba6cp-3, -0x1.5c9f7c82d6719p-5, -0x1.04551680915f1p-6, -0x1.9c4527bd06f39p-6, + -0x1.60e5d57bf24cdp-4, -0x1.07130f99c7b6bp-4, 0x1.0cce199048621p-10, 0x1.3030c0ec41f9fp-4, + -0x1.015f68a0373dcp-4, 0x1.07c70b17d230ap-3, -0x1.fa7a9d971affap-4, 0x1.91d3415867683p-6, + 0x1.6681ccf6bb547p-4, 0x1.e401ddbe315ccp-6, 0x1.7544dafe2f86bp-3, -0x1.8471cddbe7526p-6, + 0x1.443fcd34f520fp-5, -0x1.82cefde4c2510p-8, 0x1.1e87434cf6819p-5, 0x1.d77be80bc5b32p-4, + -0x1.acb0dce899ba8p-4, 0x1.f60359ab4d141p-6, 0x1.26d89fe58a6fep-3, 0x1.d97e9ad734a36p-17, + -0x1.df66a907b2cdbp-5, 0x1.0466cc83aa44ep-4, -0x1.18971ba974f63p-6, 0x1.f12a2ae7c24fcp-6, + -0x1.33088d70f22cfp-9, -0x1.b9430d4fd4119p-3, 0x1.0e8d8b2c02491p-3, 0x1.2e21985207d9cp-4, + 0x1.1e932c0032e18p-3, -0x1.ea915b7401f30p-10, -0x1.69df18876837ep-3, -0x1.7baa338d7120fp-7, + -0x1.13908a6fb57c4p-7, 0x1.78e41572901a0p-4, -0x1.ceea52aee24f3p-5, -0x1.21c8dd35f567ep-3, + 0x1.44d7b59715371p-5, 0x1.3555c13446a5fp-3, -0x1.3bd4fd14a5e24p-4, -0x1.31a4e483c908dp-7, + -0x1.7c8fdbea2b1e9p-4, -0x1.5b9a6f95b4e46p-9, 0x1.7e56d4469520cp-8, 0x1.576a827511126p-6, + 0x1.1d5823a29869bp-7, 0x1.2bd93a9711d0fp-6, -0x1.23ce5701f6cfep-3, -0x1.4731aa3359f81p-4, + -0x1.88ed3a68510eap-4, 0x1.b5fd0b57c12bbp-11, -0x1.a657fe09322bep-5, 0x1.ea5899eb042b8p-4, + -0x1.ea5899eb042b8p-4, 0x1.a657fe09322bep-5, -0x1.b5fd0b57c12bbp-11, 0x1.88ed3a68510eap-4, + 0x1.4731aa3359f81p-4, 0x1.23ce5701f6cfep-3, -0x1.2bd93a9711d0fp-6, -0x1.1d5823a29869bp-7, + -0x1.576a827511126p-6, -0x1.7e56d4469520cp-8, 0x1.5b9a6f95b4e46p-9, 0x1.7c8fdbea2b1e9p-4, + 0x1.31a4e483c908dp-7, 0x1.3bd4fd14a5e24p-4, -0x1.3555c13446a5fp-3, -0x1.44d7b59715371p-5, + 0x1.21c8dd35f567ep-3, 0x1.ceea52aee24f3p-5, -0x1.78e41572901a0p-4, 0x1.13908a6fb57c4p-7, + 0x1.7baa338d7120fp-7, 0x1.69df18876837ep-3, 0x1.ea915b7401f30p-10, -0x1.1e932c0032e18p-3, + -0x1.2e21985207d9cp-4, -0x1.0e8d8b2c02491p-3, 0x1.b9430d4fd4119p-3, 0x1.33088d70f22cfp-9, + -0x1.f12a2ae7c24fcp-6, 0x1.18971ba974f63p-6, -0x1.0466cc83aa44ep-4, 0x1.df66a907b2cdbp-5, + -0x1.d97e9ad734a36p-17, -0x1.26d89fe58a6fep-3, -0x1.f60359ab4d141p-6, 0x1.acb0dce899ba8p-4, + -0x1.d77be80bc5b32p-4, -0x1.1e87434cf6819p-5, 0x1.82cefde4c2510p-8, -0x1.443fcd34f520fp-5, + 0x1.8471cddbe7526p-6, -0x1.7544dafe2f86bp-3, -0x1.e401ddbe315ccp-6, -0x1.6681ccf6bb547p-4, + -0x1.91d3415867683p-6, 0x1.fa7a9d971affap-4, -0x1.07c70b17d230ap-3, 0x1.015f68a0373dcp-4, + -0x1.3030c0ec41f9fp-4, -0x1.0cce199048621p-10, 0x1.07130f99c7b6bp-4, 0x1.60e5d57bf24cdp-4, + 0x1.9c4527bd06f39p-6, 0x1.04551680915f1p-6, 0x1.5c9f7c82d6719p-5, -0x1.68eb2cd93ba6cp-3, + -0x1.91d4718ff923bp-8, 0x1.1519267af15d5p-3, -0x1.82fc098ae4c4bp-7, -0x1.7ec34fe6350dap-8, + -0x1.d5cb9d0fdf606p-4, -0x1.52c822d9ad8d4p-4, 0x1.cb7456f682458p-4, -0x1.0c1c4ed351662p-3, + 0x1.b7dff0f8313dbp-5, -0x1.206c373073db0p-3, -0x1.be5e554725f4bp-7, 0x1.441912766aa91p-6, + 0x1.5b51457ef5da6p-5, 0x1.b84ff8034e3fcp-7, 0x1.28c53c033a2b8p-3, -0x1.b8115b8c3ba4bp-7, + 0x1.9fdee8a640ddap-5, -0x1.581dcbf84c720p-3, -0x1.7eba8f75a4971p-6, -0x1.3f509f8bceef3p-2, + 0x1.3e65c451628d3p-4, -0x1.1458715749a1ap-5, -0x1.2b2717ecb754ap-3, 0x1.da0056b75bcaap-7, + -0x1.e5cb12c141185p-5, -0x1.0abd1466df37ep-3, 0x1.9d7c9cb69c430p-6, 0x1.d41e41db33cecp-7, + 0x1.19bd820d3654dp-6, 0x1.2d53598db888dp-8, 0x1.72c6a29a4b1f7p-4, 0x1.afa1d4141e8c1p-4, + -0x1.6481c873e0103p-4, 0x1.09008c4066f2ep-6, -0x1.0e5ee8e103383p-3, -0x1.b3cff36cd8aacp-5, + 0x1.a75c505f3d7bep-7, 0x1.54427c87bdf62p-7, 0x1.9a6f35c6517abp-8, -0x1.3a231d8f1f4aep-7, + 0x1.0aa6f4fa64b23p-3, -0x1.9e784226360b9p-4, 0x1.07e04b0281617p-3, 0x1.985144eec5c2dp-5, + 0x1.559495af26763p-8, 0x1.e14b74dd0aa2ep-6, 0x1.08f1c6ef7dcb5p-4, 0x1.a5259358290a0p-4, + 0x1.8ea4bdc5b9fedp-8, -0x1.e29097deebd15p-5, -0x1.0abbeeab770f5p-5, -0x1.918e096f05e5bp-7, + 0x1.c8f4f0448f7cap-3, 0x1.527be67dd2648p-5, 0x1.e211fb74bfd06p-5, 0x1.9f1bb2b2f9fbdp-12, + 0x1.5803eff1134f8p-4, -0x1.7928af5d8deb3p-3, 0x1.e4b8b5576d969p-7, 0x1.105819ade7513p-4, + -0x1.e29ce85574c28p-4, 0x1.230f288eabc8dp-3, -0x1.a1466d1674aa7p-8, 0x1.0a87a1c23290ep-5, + -0x1.e6fd7fef34ffdp-4, 0x1.e663945e67a7bp-6, -0x1.fc22add677f51p-7, -0x1.8e741435d1d4ep-5, + -0x1.f109252bed326p-6, -0x1.f1095800ed8d9p-9, -0x1.855bb27d67cafp-5, -0x1.eae7c1b08b14fp-5, + 0x1.eae7c1b08b14fp-5, 0x1.855bb27d67cafp-5, 0x1.f1095800ed8d9p-9, 0x1.f109252bed326p-6, + 0x1.8e741435d1d4ep-5, 0x1.fc22add677f51p-7, -0x1.e663945e67a7bp-6, 0x1.e6fd7fef34ffdp-4, + -0x1.0a87a1c23290ep-5, 0x1.a1466d1674aa7p-8, -0x1.230f288eabc8dp-3, 0x1.e29ce85574c28p-4, + -0x1.105819ade7513p-4, -0x1.e4b8b5576d969p-7, 0x1.7928af5d8deb3p-3, -0x1.5803eff1134f8p-4, + -0x1.9f1bb2b2f9fbdp-12, -0x1.e211fb74bfd06p-5, -0x1.527be67dd2648p-5, -0x1.c8f4f0448f7cap-3, + 0x1.918e096f05e5bp-7, 0x1.0abbeeab770f5p-5, 0x1.e29097deebd15p-5, -0x1.8ea4bdc5b9fedp-8, + -0x1.a5259358290a0p-4, -0x1.08f1c6ef7dcb5p-4, -0x1.e14b74dd0aa2ep-6, -0x1.559495af26763p-8, + -0x1.985144eec5c2dp-5, -0x1.07e04b0281617p-3, 0x1.9e784226360b9p-4, -0x1.0aa6f4fa64b23p-3, + 0x1.3a231d8f1f4aep-7, -0x1.9a6f35c6517abp-8, -0x1.54427c87bdf62p-7, -0x1.a75c505f3d7bep-7, + 0x1.b3cff36cd8aacp-5, 0x1.0e5ee8e103383p-3, -0x1.09008c4066f2ep-6, 0x1.6481c873e0103p-4, + -0x1.afa1d4141e8c1p-4, -0x1.72c6a29a4b1f7p-4, -0x1.2d53598db888dp-8, -0x1.19bd820d3654dp-6, + -0x1.d41e41db33cecp-7, -0x1.9d7c9cb69c430p-6, 0x1.0abd1466df37ep-3, 0x1.e5cb12c141185p-5, + -0x1.da0056b75bcaap-7, 0x1.2b2717ecb754ap-3, 0x1.1458715749a1ap-5, -0x1.3e65c451628d3p-4, + 0x1.3f509f8bceef3p-2, 0x1.7eba8f75a4971p-6, 0x1.581dcbf84c720p-3, -0x1.9fdee8a640ddap-5, + 0x1.b8115b8c3ba64p-7, -0x1.28c53c033a2b9p-3, -0x1.b84ff8034e38cp-7, -0x1.5b51457ef5da6p-5, + -0x1.441912766aa7cp-6, 0x1.be5e554725f56p-7, 0x1.206c36734ef65p-3, -0x1.b7dff0d43948cp-5, + -0x1.4d1e25ee5cce0p-5, -0x1.e426a545218adp-4, 0x1.ad2bc9bb329b5p-4, 0x1.1734d508cc4c3p-4, + -0x1.fe1cb0272f89dp-4, 0x1.5f6cfdfd3c627p-7, 0x1.771e73b85ef1ap-4, -0x1.5c77bca58a37cp-4, + -0x1.455767c6be440p-6, 0x1.f97f93eb04a67p-4, -0x1.edc19317a3b52p-5, -0x1.c08c4491752bcp-4, + 0x1.d696196705b30p-4, 0x1.9372a91ae6d0ap-5, -0x1.ef178c94294d7p-4, 0x1.04fb781f09b51p-5, + 0x1.36058d290f463p-4, -0x1.9777ed58fb1fap-4, 0x1.921d3f97e6f3dp-10, 0x1.fff620292a42ap-4, + -0x1.3fed953f67432p-4, -0x1.8fbccaa55f7fbp-4, 0x1.f2252de167ca3p-4, 0x1.d934fa3ced67dp-6, + -0x1.d17e75bcb8272p-4, 0x1.aa6c81cfd2a82p-5, 0x1.d79774283991dp-5, -0x1.c678b1b549eddp-4, + 0x1.76dd9e29fff5fp-6, 0x1.f7599abab0170p-4, -0x1.7f8ecfe0e4a5fp-4, -0x1.532829c52097cp-4, + 0x1.ff0954d0081c2p-4, 0x1.f656e1213e26ap-8, -0x1.a63093d752cdep-4, 0x1.21a79a81b1beep-4, + 0x1.35410e2c5933ep-5, -0x1.e817bd423d7cep-4, 0x1.64c7d859463a4p-5, 0x1.dfeae7b28f3a7p-4, + -0x1.b3e4d51f28136p-4, -0x1.0c9704c58df64p-4, 0x1.fce15d779433dp-4, -0x1.c37850523e77cp-7, + -0x1.6e74463bec4a2p-4, 0x1.6591905b3af1cp-4, 0x1.139f106d235c5p-6, -0x1.fb5796dd8283ep-4, + 0x1.01cfc61359a41p-4, 0x1.ba5aa25b44a1ep-4, -0x1.db6524144db0bp-4, -0x1.7c3a93ccc9c16p-5, + 0x1.ebbd9004c8036p-4, -0x1.1d3442abe6b30p-5, -0x1.2bedb09c01f99p-4, 0x1.9ef43fcf52721p-4, + -0x1.2d8670c70e869p-8, -0x1.ffa72c17aa46ep-4, 0x1.49a4498b1a9ddp-4, 0x1.87c4012329f56p-4, + -0x1.f4e6072992420p-4, -0x1.a829fbca164e2p-6, 0x1.cc1f104ec9cb0p-4, -0x1.c1249a4278fd6p-5, + -0x1.c1249a4278fd6p-5, 0x1.cc1f104ec9cb0p-4, -0x1.a829fbca164e2p-6, -0x1.f4e6072992420p-4, + 0x1.87c4012329f56p-4, 0x1.49a4498b1a9ddp-4, -0x1.ffa72c17aa46ep-4, -0x1.2d8670c70e869p-8, + 0x1.9ef43fcf52721p-4, -0x1.2bedb09c01f99p-4, -0x1.1d3442abe6b30p-5, 0x1.ebbd9004c8036p-4, + -0x1.7c3a93ccc9c16p-5, -0x1.db6524144db0bp-4, 0x1.ba5aa25b44a1ep-4, 0x1.01cfc61359a41p-4, + -0x1.fb5796dd8283ep-4, 0x1.139f106d235c5p-6, 0x1.6591905b3af1cp-4, -0x1.6e74463bec4a2p-4, + -0x1.c37850523e77cp-7, 0x1.fce15d779433dp-4, -0x1.0c9704c58df64p-4, -0x1.b3e4d51f28136p-4, + 0x1.dfeae7b28f3a7p-4, 0x1.64c7d859463a4p-5, -0x1.e817bd423d7cep-4, 0x1.35410e2c5933ep-5, + 0x1.21a79a81b1beep-4, -0x1.a63093d752cdep-4, 0x1.f656e1213e26ap-8, 0x1.ff0954d0081c2p-4, + -0x1.532829c52097cp-4, -0x1.7f8ecfe0e4a5fp-4, 0x1.f7599abab0170p-4, 0x1.76dd9e29fff5fp-6, + -0x1.c678b1b549eddp-4, 0x1.d79774283991dp-5, 0x1.aa6c81cfd2a82p-5, -0x1.d17e75bcb8272p-4, + 0x1.d934fa3ced67dp-6, 0x1.f2252de167ca3p-4, -0x1.8fbccaa55f7fbp-4, -0x1.3fed953f67432p-4, + 0x1.fff620292a42ap-4, 0x1.921d3f97e6f3dp-10, -0x1.9777ed58fb1fap-4, 0x1.36058d290f463p-4, + 0x1.04fb781f09b51p-5, -0x1.ef178c94294d7p-4, 0x1.9372a91ae6d0ap-5, 0x1.d696196705b30p-4, + -0x1.c08c4491752bcp-4, -0x1.edc19317a3b52p-5, 0x1.f97f93eb04a67p-4, -0x1.455767c6be440p-6, + -0x1.5c77bca58a37cp-4, 0x1.771e73b85ef1ap-4, 0x1.5f6cfdfd3c627p-7, -0x1.fe1cb0272f89dp-4, + 0x1.1734d508cc4c3p-4, 0x1.ad2bc9bb329b5p-4, -0x1.e426a54521894p-4, -0x1.4d1e25ee5cce3p-5, + 0x1.e426a453398c0p-4, -0x1.4d1e270d02dd7p-5, 0x1.1734d461aed50p-4, -0x1.ad2bcb7cc07a4p-4, + -0x1.5f6cfda3839dap-7, -0x1.fe1cb0319bb95p-4, -0x1.5c77bc5f20f2cp-4, -0x1.771e744088f3dp-4, + -0x1.f97f93100d976p-4, -0x1.4557688205079p-6, -0x1.c08c458f9754ap-4, 0x1.edc1933ac5e4ep-5, + -0x1.9372a89286c46p-5, 0x1.d6961936c9246p-4, 0x1.04fb7808a7dd4p-5, 0x1.ef178dec0a7fcp-4, + 0x1.9777ec67caf21p-4, 0x1.36058be03302ep-4, 0x1.fff6216e3ece2p-4, -0x1.921d3d97f451bp-10, + 0x1.8fbcca60ccbfap-4, -0x1.3fed9441b00d3p-4, 0x1.d934fbe173174p-6, -0x1.f2252d726f7eap-4, + -0x1.aa6c835f9b1bcp-5, -0x1.d17e751852c03p-4, -0x1.c678b0c2d32c3p-4, -0x1.d7977582d9903p-5, + -0x1.f7599a9ef5686p-4, 0x1.76dd9ef2dccc8p-6, -0x1.532829053fbe8p-4, 0x1.7f8ecf6964959p-4, + -0x1.f656e12daa2a9p-8, 0x1.ff09553699c76p-4, 0x1.21a79b4572965p-4, 0x1.a6309333a897ap-4, + 0x1.e817bc9d0b13bp-4, 0x1.35410ede578d2p-5, 0x1.dfeae72832105p-4, -0x1.64c7d90ddbed8p-5, + 0x1.0c9704fea79a6p-4, -0x1.b3e4d43ed091ep-4, -0x1.c378507e1078bp-7, -0x1.fce15d09591b5p-4, + -0x1.659191057160bp-4, -0x1.6e7446e08fca8p-4, -0x1.fb5796551287fp-4, -0x1.139f1108633c9p-6, + -0x1.ba5aa389152dbp-4, 0x1.01cfc71c61b9bp-4, -0x1.7c3a943ff497ep-5, 0x1.db652486f79ffp-4, + 0x1.1d3441dd8c611p-5, 0x1.ebbd8e5dd5c17p-4, 0x1.9ef441113d075p-4, 0x1.2bedb0ffe3205p-4, + 0x1.ffa72c387dc3bp-4, -0x1.2d86714f68b22p-8, 0x1.87c4006b764c0p-4, -0x1.49a44970a2a9bp-4, + 0x1.a829fd547dfc7p-6, -0x1.f4e6072b58396p-4, -0x1.c1249ae0ade47p-5, -0x1.cc1f11bb3cf2fp-4, + -0x1.cc1f11bb3cf2fp-4, -0x1.c1249ae0ade47p-5, -0x1.f4e6072b58396p-4, 0x1.a829fd547dfc7p-6, + -0x1.49a44970a2a9bp-4, 0x1.87c4006b764c0p-4, -0x1.2d86714f68b22p-8, 0x1.ffa72c387dc3bp-4, + 0x1.2bedb0ffe3205p-4, 0x1.9ef441113d075p-4, 0x1.ebbd8e5dd5c17p-4, 0x1.1d3441dd8c611p-5, + 0x1.db652486f79ffp-4, -0x1.7c3a943ff497ep-5, 0x1.01cfc71c61b9bp-4, -0x1.ba5aa389152dbp-4, + -0x1.139f1108633c9p-6, -0x1.fb5796551287fp-4, -0x1.6e7446e08fca8p-4, -0x1.659191057160bp-4, + -0x1.fce15d09591b5p-4, -0x1.c378507e1078bp-7, -0x1.b3e4d43ed091ep-4, 0x1.0c9704fea79a6p-4, + -0x1.64c7d90ddbed8p-5, 0x1.dfeae72832105p-4, 0x1.35410ede578d2p-5, 0x1.e817bc9d0b13bp-4, + 0x1.a6309333a897ap-4, 0x1.21a79b4572965p-4, 0x1.ff09553699c76p-4, -0x1.f656e12daa2a9p-8, + 0x1.7f8ecf6964959p-4, -0x1.532829053fbe8p-4, 0x1.76dd9ef2dccc8p-6, -0x1.f7599a9ef5686p-4, + -0x1.d7977582d9903p-5, -0x1.c678b0c2d32c3p-4, -0x1.d17e751852c03p-4, -0x1.aa6c835f9b1bcp-5, + -0x1.f2252d726f7eap-4, 0x1.d934fbe173174p-6, -0x1.3fed9441b00d3p-4, 0x1.8fbcca60ccbfap-4, + -0x1.921d3d97f451bp-10, 0x1.fff6216e3ece2p-4, 0x1.36058be03302ep-4, 0x1.9777ec67caf21p-4, + 0x1.ef178dec0a7fcp-4, 0x1.04fb7808a7dd4p-5, 0x1.d6961936c9246p-4, -0x1.9372a89286c46p-5, + 0x1.edc1933ac5e4ep-5, -0x1.c08c458f9754ap-4, -0x1.4557688205079p-6, -0x1.f97f93100d976p-4, + -0x1.771e744088f3dp-4, -0x1.5c77bc5f20f2cp-4, -0x1.fe1cb0319bb95p-4, -0x1.5f6cfda3839dap-7, + -0x1.ad2bcb7cc07a4p-4, 0x1.1734d461aed50p-4, -0x1.4d1e270d02dd7p-5, 0x1.e426a453398d0p-4, + -0x1.0c9aba621617ep-8, 0x1.b253d1eac8161p-7, -0x1.1aa8573b6c278p-6, -0x1.15a3ee47dc6d6p-6, + 0x1.34a732678530cp-6, 0x1.0a02fcf257ff1p-9, -0x1.7b4a45ac0529ap-3, -0x1.5142332d3ed11p-3, + -0x1.1caaeffc320b5p-5, -0x1.5817d2e2d5c02p-6, 0x1.c0e3fe69cf05dp-4, -0x1.58740d57c3687p-4, + 0x1.adc765165986dp-6, -0x1.8884af0a1aa8ep-3, -0x1.c94856f09764cp-8, -0x1.19ddd94806c9bp-5, + -0x1.8eb9b72014da4p-5, 0x1.126157891d70dp-5, 0x1.77ba55528a654p-6, 0x1.64c876f7dd2a6p-8, + -0x1.31be3a5763264p-4, -0x1.beabcd19b9077p-3, -0x1.44b2ca91a9959p-8, 0x1.ad50079b9573ap-3, + 0x1.7c112c68e6134p-4, -0x1.6a7d158325bfdp-4, -0x1.15380c29eaa66p-3, 0x1.7bc4851a8a365p-4, + -0x1.c3650be591d04p-5, -0x1.017c8f8ae2ba6p-5, 0x1.ff3ab137a46ecp-7, 0x1.7bd73c26894e7p-5, + 0x1.caea8c744dcb5p-8, 0x1.37b42d7c868d3p-4, -0x1.04ad0193f5dc8p-3, -0x1.857adff535b71p-5, + 0x1.1793d6ee4f808p-4, 0x1.2e8c1625903f0p-5, -0x1.c270af09cf137p-5, 0x1.0ff1108808aa2p-4, + -0x1.7607f1195d862p-4, -0x1.a4e7e8c6e6a96p-6, -0x1.4bbcd42a054dcp-11, -0x1.449e6e0276470p-3, + -0x1.b2bf32cf6bd9dp-5, 0x1.44ddb9ea8bc00p-5, -0x1.b62daa5af1d5ep-3, 0x1.569a4bd26897ap-7, + 0x1.e7ceb9df6f55ep-5, -0x1.d0ac2ddf7e7f1p-4, -0x1.6f884a5440792p-7, -0x1.3f7f824b3064fp-5, + 0x1.443d81e5826e6p-4, 0x1.95201c7967adbp-5, 0x1.80b2a5d88088cp-6, -0x1.615fdc244cb4bp-3, + 0x1.c981ccf18b566p-4, 0x1.6a3b9d9285e8ap-8, -0x1.464e2a6471c51p-4, 0x1.d7f139f1283f6p-4, + -0x1.0ce9d335258c6p-4, 0x1.09f444c122fc8p-4, 0x1.557f2a48eae43p-4, 0x1.0dfb967491bc0p-6, + 0x1.0dfb967491bc0p-6, 0x1.557f2a48eae43p-4, 0x1.09f444c122fc8p-4, -0x1.0ce9d335258c6p-4, + 0x1.d7f139f1283f6p-4, -0x1.464e2a6471c51p-4, 0x1.6a3b9d9285e8ap-8, 0x1.c981ccf18b566p-4, + -0x1.615fdc244cb4bp-3, 0x1.80b2a5d88088cp-6, 0x1.95201c7967adbp-5, 0x1.443d81e5826e6p-4, + -0x1.3f7f824b3064fp-5, -0x1.6f884a5440792p-7, -0x1.d0ac2ddf7e7f1p-4, 0x1.e7ceb9df6f55ep-5, + 0x1.569a4bd26897ap-7, -0x1.b62daa5af1d5ep-3, 0x1.44ddb9ea8bc00p-5, -0x1.b2bf32cf6bd9dp-5, + -0x1.449e6e0276470p-3, -0x1.4bbcd42a054dcp-11, -0x1.a4e7e8c6e6a96p-6, -0x1.7607f1195d862p-4, + 0x1.0ff1108808aa2p-4, -0x1.c270af09cf137p-5, 0x1.2e8c1625903f0p-5, 0x1.1793d6ee4f808p-4, + -0x1.857adff535b71p-5, -0x1.04ad0193f5dc8p-3, 0x1.37b42d7c868d3p-4, 0x1.caea8c744dcb5p-8, + 0x1.7bd73c26894e7p-5, 0x1.ff3ab137a46ecp-7, -0x1.017c8f8ae2ba6p-5, -0x1.c3650be591d04p-5, + 0x1.7bc4851a8a365p-4, -0x1.15380c29eaa66p-3, -0x1.6a7d158325bfdp-4, 0x1.7c112c68e6134p-4, + 0x1.ad50079b9573ap-3, -0x1.44b2ca91a9959p-8, -0x1.beabcd19b9077p-3, -0x1.31be3a5763264p-4, + 0x1.64c876f7dd2a6p-8, 0x1.77ba55528a654p-6, 0x1.126157891d70dp-5, -0x1.8eb9b72014da4p-5, + -0x1.19ddd94806c9bp-5, -0x1.c94856f09764cp-8, -0x1.8884af0a1aa8ep-3, 0x1.adc765165986dp-6, + -0x1.58740d57c3687p-4, 0x1.c0e3fe69cf05dp-4, -0x1.5817d2e2d5c02p-6, -0x1.1caaeffc320b5p-5, + -0x1.5142332d3ed11p-3, -0x1.7b4a45ac05296p-3, 0x1.0a02fcf258034p-9, 0x1.34a73267852c2p-6, + -0x1.15a3ee47dc6c4p-6, -0x1.1aa8573b6c236p-6, 0x1.b253d274d323ep-7, -0x1.0c9abdfaa7dc7p-8, + 0x1.068f008deace3p-5, -0x1.c395eed375543p-4, -0x1.ec731633adf88p-4, 0x1.637c1f8931358p-5, + 0x1.e36c28a7ef7b4p-3, 0x1.a5369aa78eeecp-8, -0x1.68e06f271abb3p-4, -0x1.3e58dd9f64205p-10, + 0x1.150b63e4780b6p-5, -0x1.45555a3c32bd9p-6, -0x1.094f800145278p-6, 0x1.6ee8acb335507p-4, + -0x1.15a0140a87dd0p-5, 0x1.36911e1343635p-5, 0x1.5653de4acc147p-4, 0x1.c969c9a60a376p-10, + 0x1.3ba13c8ac2ae4p-8, -0x1.a871312a9a967p-4, 0x1.e5e9bb0596f2ep-10, 0x1.07eca5006586fp-4, + 0x1.f3990065e85fap-9, -0x1.54656b021d6a1p-6, -0x1.f2770ff7a9ebcp-5, -0x1.2799377ef79a8p-5, + -0x1.d025262730f5cp-8, 0x1.322fa55b51f32p-7, -0x1.359f5204f2a58p-5, -0x1.56896d80de6a3p-3, + -0x1.53c796a16f669p-7, -0x1.d0ce0ae6d8927p-4, -0x1.a0deae371054dp-3, -0x1.1b7b8c3b3e898p-3, + -0x1.494351bace112p-5, 0x1.adea0a7690ed3p-9, -0x1.843e16f5ef6dcp-4, -0x1.53fef7dbc5380p-6, + -0x1.71c4469987945p-6, 0x1.06669280c0506p-6, -0x1.97dc4267edaa2p-6, 0x1.bee18e9014c75p-4, + 0x1.a14ced3669cbbp-6, -0x1.0c3ef9d6e0af3p-4, 0x1.65ad866147e0bp-3, 0x1.415433ce22551p-7, + 0x1.4f51cf31a9902p-4, -0x1.966deaa6ff506p-6, 0x1.ffc78ef4f5306p-6, -0x1.e8a723a4f0c32p-6, + -0x1.2a16e85eba50ep-3, -0x1.ce5e9cceed4bcp-9, 0x1.55c1e8b66c850p-3, 0x1.08170280db3abp-5, + 0x1.92e9ab1880741p-4, -0x1.04101a1cc8111p-5, -0x1.9a58c0c1bec64p-5, -0x1.6c062c9dba83ap-4, + -0x1.1bd319241bbc6p-6, 0x1.f483d1340781ap-3, 0x1.76cd39ab0f3f3p-3, 0x1.82e7a4b5bbd36p-4, + -0x1.134fc0934425cp-3, 0x1.bd5ca81b2f143p-5, -0x1.1d86ff98112e7p-6, 0x1.22c09baf3d56ep-7, + 0x1.22c09baf3d56ep-7, -0x1.1d86ff98112e7p-6, 0x1.bd5ca81b2f143p-5, -0x1.134fc0934425cp-3, + 0x1.82e7a4b5bbd36p-4, 0x1.76cd39ab0f3f3p-3, 0x1.f483d1340781ap-3, -0x1.1bd319241bbc6p-6, + -0x1.6c062c9dba83ap-4, -0x1.9a58c0c1bec64p-5, -0x1.04101a1cc8111p-5, 0x1.92e9ab1880741p-4, + 0x1.08170280db3abp-5, 0x1.55c1e8b66c850p-3, -0x1.ce5e9cceed4bcp-9, -0x1.2a16e85eba50ep-3, + -0x1.e8a723a4f0c32p-6, 0x1.ffc78ef4f5306p-6, -0x1.966deaa6ff506p-6, 0x1.4f51cf31a9902p-4, + 0x1.415433ce22551p-7, 0x1.65ad866147e0bp-3, -0x1.0c3ef9d6e0af3p-4, 0x1.a14ced3669cbbp-6, + 0x1.bee18e9014c75p-4, -0x1.97dc4267edaa2p-6, 0x1.06669280c0506p-6, -0x1.71c4469987945p-6, + -0x1.53fef7dbc5380p-6, -0x1.843e16f5ef6dcp-4, 0x1.adea0a7690ed3p-9, -0x1.494351bace112p-5, + -0x1.1b7b8c3b3e898p-3, -0x1.a0deae371054dp-3, -0x1.d0ce0ae6d8927p-4, -0x1.53c796a16f669p-7, + -0x1.56896d80de6a3p-3, -0x1.359f5204f2a58p-5, 0x1.322fa55b51f32p-7, -0x1.d025262730f5cp-8, + -0x1.2799377ef79a8p-5, -0x1.f2770ff7a9ebcp-5, -0x1.54656b021d6a1p-6, 0x1.f3990065e85fap-9, + 0x1.07eca5006586fp-4, 0x1.e5e9bb0596f2ep-10, -0x1.a871312a9a967p-4, 0x1.3ba13c8ac2ae4p-8, + 0x1.c969c9a60a376p-10, 0x1.5653de4acc147p-4, 0x1.36911e1343635p-5, -0x1.15a0140a87dd0p-5, + 0x1.6ee8acb335507p-4, -0x1.094f800145278p-6, -0x1.45555a3c32bd9p-6, 0x1.150b63e4780b6p-5, + -0x1.3e58dd9f641a6p-10, -0x1.68e06f271abb3p-4, 0x1.a5369aa78eeb4p-8, 0x1.e36c28a7ef7b6p-3, + 0x1.637c1f893137bp-5, -0x1.ec731633adf8bp-4, -0x1.c395eba2d5e9cp-4, 0x1.068f0074fa02fp-5, + -0x1.64c7dddc05dd8p-5, -0x1.dfeae6e1c1de0p-4, 0x1.c08c4048a8984p-4, 0x1.edc194db37e67p-5, + -0x1.f4e602e8bc767p-4, 0x1.a82a0830a2a50p-6, 0x1.36058c48bd613p-4, -0x1.9777ed9ed7764p-4, + 0x1.f656f0f6efa96p-8, 0x1.ff0956782b6eap-4, -0x1.65919358716fap-4, -0x1.6e744626005b6p-4, + 0x1.fe1cafeac8258p-4, 0x1.5f6cf7c585e85p-7, -0x1.9ef441c724d47p-4, 0x1.2bedb27ab1dabp-4, + 0x1.d934ff74092f6p-6, -0x1.f22531d8221fdp-4, 0x1.d79770ecb2cdfp-5, 0x1.c678b5d88f7cfp-4, + -0x1.db652780949eep-4, -0x1.7c3a9192284fcp-5, 0x1.e426a39706439p-4, -0x1.4d1e22c2e51a2p-5, + -0x1.01cfc5b6f2d77p-4, 0x1.ba5aa43d77a5ap-4, -0x1.76dd9313045c2p-6, -0x1.f7599be33abe2p-4, + 0x1.8fbcc7d25a956p-4, 0x1.3fed94a567434p-4, -0x1.ffa72f1fdb5bcp-4, 0x1.2d865eeb94449p-8, + 0x1.771e76db93d5ap-4, -0x1.5c77bcdbd7119p-4, -0x1.c378649afb849p-7, 0x1.fce15fd7a87ebp-4, + -0x1.21a79c5bd0528p-4, -0x1.a6308f6122d66p-4, 0x1.ef1789d30eaefp-4, 0x1.04fb8511883c1p-5, + -0x1.cc1f11aa23d3fp-4, 0x1.c124a16926fdep-5, 0x1.9372a3af39e1ap-5, -0x1.d69616a2110f9p-4, + 0x1.3541091467af3p-5, 0x1.e817b82a56d4ap-4, -0x1.b3e4d467471ccp-4, -0x1.0c970404f6f81p-4, + 0x1.f97f91c2eb510p-4, -0x1.45576b27954f1p-6, -0x1.49a449b9ee92cp-4, 0x1.87c3fd55f7ba7p-4, + -0x1.921d0620f154fp-10, -0x1.fff6217ac865cp-4, 0x1.532829d9c67d5p-4, 0x1.7f8ecce4a73dap-4, + -0x1.fb5796e2130e8p-4, -0x1.139f0c757ce40p-6, 0x1.ad2bcb6a17348p-4, -0x1.1734d6b2a9163p-4, + -0x1.1d344a91aa6dap-5, 0x1.ebbd8bb105fccp-4, -0x1.aa6c81610b66ep-5, -0x1.d17e79498d3dap-4, + 0x1.d17e79498d3dap-4, 0x1.aa6c81610b66ep-5, -0x1.ebbd8bb105fccp-4, 0x1.1d344a91aa6dap-5, + 0x1.1734d6b2a9163p-4, -0x1.ad2bcb6a17348p-4, 0x1.139f0c757ce40p-6, 0x1.fb5796e2130e8p-4, + -0x1.7f8ecce4a73dap-4, -0x1.532829d9c67d5p-4, 0x1.fff6217ac865cp-4, 0x1.921d0620f154fp-10, + -0x1.87c3fd55f7ba7p-4, 0x1.49a449b9ee92cp-4, 0x1.45576b27954f1p-6, -0x1.f97f91c2eb510p-4, + 0x1.0c970404f6f81p-4, 0x1.b3e4d467471ccp-4, -0x1.e817b82a56d4ap-4, -0x1.3541091467af3p-5, + 0x1.d69616a2110f9p-4, -0x1.9372a3af39e1ap-5, -0x1.c124a16926fdep-5, 0x1.cc1f11aa23d3fp-4, + -0x1.04fb8511883c1p-5, -0x1.ef1789d30eaefp-4, 0x1.a6308f6122d66p-4, 0x1.21a79c5bd0528p-4, + -0x1.fce15fd7a87ebp-4, 0x1.c378649afb849p-7, 0x1.5c77bcdbd7119p-4, -0x1.771e76db93d5ap-4, + -0x1.2d865eeb94449p-8, 0x1.ffa72f1fdb5bcp-4, -0x1.3fed94a567434p-4, -0x1.8fbcc7d25a956p-4, + 0x1.f7599be33abe2p-4, 0x1.76dd9313045c2p-6, -0x1.ba5aa43d77a5ap-4, 0x1.01cfc5b6f2d77p-4, + 0x1.4d1e22c2e51a2p-5, -0x1.e426a39706439p-4, 0x1.7c3a9192284fcp-5, 0x1.db652780949eep-4, + -0x1.c678b5d88f7cfp-4, -0x1.d79770ecb2cdfp-5, 0x1.f22531d8221fdp-4, -0x1.d934ff74092f6p-6, + -0x1.2bedb27ab1dabp-4, 0x1.9ef441c724d47p-4, -0x1.5f6cf7c585e85p-7, -0x1.fe1cafeac8258p-4, + 0x1.6e744626005b6p-4, 0x1.65919358716fap-4, -0x1.ff0956782b6eap-4, -0x1.f656f0f6efa96p-8, + 0x1.9777ed9ed7764p-4, -0x1.36058c48bd613p-4, -0x1.a82a0830a2a50p-6, 0x1.f4e602e8bc767p-4, + -0x1.edc194db37e67p-5, -0x1.c08c4048a8984p-4, 0x1.dfeae6e1c1dedp-4, 0x1.64c7dddc05ddbp-5, + 0x1.dfeae6d962d92p-4, -0x1.64c7de52515a0p-5, 0x1.edc195fe6822ap-5, -0x1.c08c40c2ceec0p-4, + -0x1.a82a08a76a904p-6, -0x1.f4e60312c60bcp-4, -0x1.9777ee882fe9ep-4, -0x1.36058c65c61d2p-4, + -0x1.ff09577dd84f4p-4, 0x1.f656f1f2c9cd7p-8, -0x1.6e74470e406f9p-4, 0x1.659192c93bbc1p-4, + -0x1.5f6cf75b8ee61p-7, 0x1.fe1cb0f4897d4p-4, 0x1.2bedb2e2461cfp-4, 0x1.9ef44169a48e5p-4, + 0x1.f2253088098ebp-4, 0x1.d93500a057c08p-6, 0x1.c678b4da3ad9bp-4, -0x1.d797707138ca2p-5, + 0x1.7c3a921826804p-5, -0x1.db6526dbd0ef6p-4, -0x1.4d1e227673803p-5, -0x1.e426a3fe05019p-4, + -0x1.ba5aa4227d917p-4, -0x1.01cfc5706d105p-4, -0x1.f7599a5f8e5aep-4, 0x1.76dd92f9e3c39p-6, + -0x1.3fed952f87a2bp-4, 0x1.8fbcc8f55384dp-4, 0x1.2d865d28bc873p-8, 0x1.ffa72e57de66ep-4, + 0x1.5c77bd0fee5f3p-4, 0x1.771e7633311abp-4, 0x1.fce1605776ff2p-4, 0x1.c37865324c1e0p-7, + 0x1.a63090c252990p-4, -0x1.21a79cf64c7efp-4, 0x1.04fb840a27b27p-5, -0x1.ef1789c26d48dp-4, + -0x1.c124a117861ffp-5, -0x1.cc1f10f9e9d68p-4, -0x1.d6961655a2647p-4, -0x1.9372a30b5bcd3p-5, + -0x1.e817b7e333a28p-4, 0x1.354108ad1e6a9p-5, -0x1.0c9705220f4dfp-4, 0x1.b3e4d4adbc29ap-4, + 0x1.45576b012920fp-6, 0x1.f97f9179bc7a7p-4, 0x1.87c3fe86ec0a0p-4, 0x1.49a44b2f866b3p-4, + 0x1.fff62130285acp-4, -0x1.921d0ac451f97p-10, 0x1.7f8ecc0fb457ep-4, -0x1.53282adf6d35ap-4, + 0x1.139f0bcd27453p-6, -0x1.fb5797cd7d17bp-4, -0x1.1734d63f247a3p-4, -0x1.ad2bca2aab358p-4, + -0x1.ebbd8a9f40b49p-4, -0x1.1d3449f048a39p-5, -0x1.d17e788c28d1dp-4, 0x1.aa6c7fe96053ep-5, + -0x1.aa6c7fe96053ep-5, 0x1.d17e788c28d1dp-4, 0x1.1d3449f048a39p-5, 0x1.ebbd8a9f40b49p-4, + 0x1.ad2bca2aab358p-4, 0x1.1734d63f247a3p-4, 0x1.fb5797cd7d17bp-4, -0x1.139f0bcd27453p-6, + 0x1.53282adf6d35ap-4, -0x1.7f8ecc0fb457ep-4, 0x1.921d0ac451f97p-10, -0x1.fff62130285acp-4, + -0x1.49a44b2f866b3p-4, -0x1.87c3fe86ec0a0p-4, -0x1.f97f9179bc7a7p-4, -0x1.45576b012920fp-6, + -0x1.b3e4d4adbc29ap-4, 0x1.0c9705220f4dfp-4, -0x1.354108ad1e6a9p-5, 0x1.e817b7e333a28p-4, + 0x1.9372a30b5bcd3p-5, 0x1.d6961655a2647p-4, 0x1.cc1f10f9e9d68p-4, 0x1.c124a117861ffp-5, + 0x1.ef1789c26d48dp-4, -0x1.04fb840a27b27p-5, 0x1.21a79cf64c7efp-4, -0x1.a63090c252990p-4, + -0x1.c37865324c1e0p-7, -0x1.fce1605776ff2p-4, -0x1.771e7633311abp-4, -0x1.5c77bd0fee5f3p-4, + -0x1.ffa72e57de66ep-4, -0x1.2d865d28bc873p-8, -0x1.8fbcc8f55384dp-4, 0x1.3fed952f87a2bp-4, + -0x1.76dd92f9e3c39p-6, 0x1.f7599a5f8e5aep-4, 0x1.01cfc5706d105p-4, 0x1.ba5aa4227d917p-4, + 0x1.e426a3fe05019p-4, 0x1.4d1e227673803p-5, 0x1.db6526dbd0ef6p-4, -0x1.7c3a921826804p-5, + 0x1.d797707138ca2p-5, -0x1.c678b4da3ad9bp-4, -0x1.d93500a057c08p-6, -0x1.f2253088098ebp-4, + -0x1.9ef44169a48e5p-4, -0x1.2bedb2e2461cfp-4, -0x1.fe1cb0f4897d4p-4, 0x1.5f6cf75b8ee61p-7, + -0x1.659192c93bbc1p-4, 0x1.6e74470e406f9p-4, -0x1.f656f1f2c9cd7p-8, 0x1.ff09577dd84f4p-4, + 0x1.36058c65c61d2p-4, 0x1.9777ee882fe9ep-4, 0x1.f4e60312c60bcp-4, 0x1.a82a08a76a904p-6, + 0x1.c08c40c2ceec0p-4, -0x1.edc195fe6822ap-5, 0x1.64c7de52515a0p-5, -0x1.dfeae6d962d8ap-4, + -0x1.d8d14e034ee82p-5, 0x1.7051a52100840p-6, -0x1.0154998c4b607p-5, 0x1.a15b30191fe80p-7, + -0x1.062c85b2ffbddp-5, 0x1.a19487a3b08a1p-4, -0x1.8b0c398fa2b11p-4, -0x1.95b95f0ecd97bp-4, + 0x1.ca05d6fd5c117p-3, 0x1.6a2af5fd9d71fp-7, 0x1.2aed4b83b9195p-5, -0x1.602aa5105573fp-3, + 0x1.077acfc244b1cp-6, 0x1.8aacc46b74a15p-5, -0x1.150c154338dd7p-3, -0x1.4a7a0dbdb192fp-5, + 0x1.2ffe25008e537p-3, 0x1.6fcb2fa91055fp-11, -0x1.fad9012111b4cp-4, -0x1.e9dc6cd3b319ep-5, + 0x1.0cd4a3c3b4dbap-4, -0x1.5b7a7d1ae8b33p-6, -0x1.573af2c6d12cep-5, -0x1.14368f33a50e2p-4, + -0x1.6f12b6c5e8326p-4, -0x1.ae5db7da331ebp-4, 0x1.e665b9e107023p-8, 0x1.ded44cd56beadp-7, + -0x1.67e9bab44473bp-5, 0x1.bb7c802a5426dp-5, -0x1.2ac5b2683f1acp-10, -0x1.b68fc110b316fp-8, + -0x1.956d7c9f30018p-4, 0x1.df30b02a48394p-5, 0x1.0d5d7f35696a9p-3, 0x1.8dc66fb62a76bp-6, + -0x1.a07564daeaffcp-4, 0x1.b323fb758c16ep-4, 0x1.7db54da3bf9c2p-4, -0x1.1711a15529b7ap-3, + 0x1.8661c7f179ebap-5, 0x1.8cf90d19d721ep-3, -0x1.e6eabffeb678cp-9, -0x1.11fbb8edd1c57p-4, + -0x1.40a143f85ec7cp-3, 0x1.5b3119a17f752p-5, 0x1.6b6c1af109182p-5, -0x1.5d28de64244c0p-10, + 0x1.910a362b1967cp-7, -0x1.ce9aeb62e31d7p-7, 0x1.1103ce80ef3d8p-7, -0x1.b2217735990b5p-3, + -0x1.ebc95a1945bd5p-4, -0x1.c9491191245c8p-10, 0x1.ad34937269176p-6, 0x1.b74b4fddbb266p-4, + -0x1.30cb275fbc2c3p-6, 0x1.e96fdfb5da715p-6, -0x1.711333fa3cb4ep-4, -0x1.4ede391f70aa3p-3, + -0x1.47dda9e3adca7p-4, 0x1.d838cf2db9d4bp-6, -0x1.ff00c54416a79p-5, 0x1.d1dab10adc383p-4, + -0x1.d1dab10adc383p-4, 0x1.ff00c54416a79p-5, -0x1.d838cf2db9d4bp-6, 0x1.47dda9e3adca7p-4, + 0x1.4ede391f70aa3p-3, 0x1.711333fa3cb4ep-4, -0x1.e96fdfb5da715p-6, 0x1.30cb275fbc2c3p-6, + -0x1.b74b4fddbb266p-4, -0x1.ad34937269176p-6, 0x1.c9491191245c8p-10, 0x1.ebc95a1945bd5p-4, + 0x1.b2217735990b5p-3, -0x1.1103ce80ef3d8p-7, 0x1.ce9aeb62e31d7p-7, -0x1.910a362b1967cp-7, + 0x1.5d28de64244c0p-10, -0x1.6b6c1af109182p-5, -0x1.5b3119a17f752p-5, 0x1.40a143f85ec7cp-3, + 0x1.11fbb8edd1c57p-4, 0x1.e6eabffeb678cp-9, -0x1.8cf90d19d721ep-3, -0x1.8661c7f179ebap-5, + 0x1.1711a15529b7ap-3, -0x1.7db54da3bf9c2p-4, -0x1.b323fb758c16ep-4, 0x1.a07564daeaffcp-4, + -0x1.8dc66fb62a76bp-6, -0x1.0d5d7f35696a9p-3, -0x1.df30b02a48394p-5, 0x1.956d7c9f30018p-4, + 0x1.b68fc110b316fp-8, 0x1.2ac5b2683f1acp-10, -0x1.bb7c802a5426dp-5, 0x1.67e9bab44473bp-5, + -0x1.ded44cd56beadp-7, -0x1.e665b9e107023p-8, 0x1.ae5db7da331ebp-4, 0x1.6f12b6c5e8326p-4, + 0x1.14368f33a50e2p-4, 0x1.573af2c6d12cep-5, 0x1.5b7a7d1ae8b33p-6, -0x1.0cd4a3c3b4dbap-4, + 0x1.e9dc6cd3b319ep-5, 0x1.fad9012111b4cp-4, -0x1.6fcb2fa91055fp-11, -0x1.2ffe25008e537p-3, + 0x1.4a7a0dbdb192fp-5, 0x1.150c154338dd7p-3, -0x1.8aacc46b74a15p-5, -0x1.077acfc244b1cp-6, + 0x1.602aa5105573fp-3, -0x1.2aed4b83b9195p-5, -0x1.6a2af5fd9d71fp-7, -0x1.ca05d6fd5c117p-3, + 0x1.95b95f0ecd97bp-4, 0x1.8b0c398fa2b0ep-4, -0x1.a19487a3b089fp-4, 0x1.062c85b2ffbd6p-5, + -0x1.a15b30191fe80p-7, 0x1.0154998c4b5fdp-5, -0x1.7051a51c1c28dp-6, 0x1.d8d14ae19a6c7p-5, + 0x1.191c3f1807886p-4, 0x1.9d6b50f506952p-6, 0x1.b675eb7e3177dp-10, 0x1.d8392e5033edap-6, + -0x1.0c4719def3f78p-7, -0x1.736ffaf709874p-8, -0x1.c9ec89fdf5f03p-4, 0x1.e6426c6c6a831p-4, + 0x1.d149bbe89cd03p-8, 0x1.9caa34e4cb977p-5, -0x1.2876632b8b923p-5, 0x1.a6b1421fc371dp-5, + -0x1.043b4ea6ecf94p-4, 0x1.14708b3fa9e00p-9, -0x1.6e4948fe1ea1dp-3, -0x1.989cb227eee87p-7, + -0x1.3a10b05017f82p-5, -0x1.51a1fe3133f83p-3, 0x1.2b28e11cc9130p-5, 0x1.ef7eb72c4c899p-4, + -0x1.c441a4d07f2fcp-6, 0x1.94aac2e02b245p-5, -0x1.bcf267766b039p-4, -0x1.2eea165b9d1a3p-4, + 0x1.9035279b6b33dp-4, -0x1.ee5aaa45daa75p-7, 0x1.926a1d0480379p-6, -0x1.4d1f5bd2aa26fp-4, + -0x1.31379a60a1e77p-3, -0x1.49136fde5ee90p-7, 0x1.f4f0cad054c40p-4, 0x1.0c039528d6f06p-9, + 0x1.912509fa31f69p-4, 0x1.602494f0fe87fp-5, 0x1.8798c365cf60ep-6, -0x1.04ff5a67d1a77p-3, + -0x1.64fa56c47fcb8p-7, -0x1.984bdcb61b0d7p-9, -0x1.77e23568e7e42p-3, 0x1.216678bcc8e82p-10, + 0x1.9a6f7cbe196b5p-8, 0x1.0c9789ddb2d60p-8, 0x1.f8b25efb57e5cp-6, 0x1.45ab6d2118bf4p-3, + 0x1.7815d1d33df51p-7, -0x1.9297871261ce4p-3, -0x1.0133d5daaccc0p-3, 0x1.3148b3738ceb6p-5, + 0x1.528805a4b54d3p-3, 0x1.d8f1ff6b0af30p-10, 0x1.93328a44dff89p-4, -0x1.c528d64586024p-4, + -0x1.d42c3fddcd0c2p-8, -0x1.d0efc83c238b1p-3, -0x1.b63cbae5dca61p-5, 0x1.4fae3daf6d6c4p-5, + -0x1.e50545d21d433p-4, -0x1.48db40ca33fbep-7, 0x1.0787238281293p-3, -0x1.220d872014364p-3, + -0x1.6ceec3db34d58p-5, 0x1.0ba6750488440p-6, -0x1.8de2204148f0cp-5, -0x1.aa9c0f4c7d39dp-10, + 0x1.aa9c0f4c7d39dp-10, 0x1.8de2204148f0cp-5, -0x1.0ba6750488440p-6, 0x1.6ceec3db34d58p-5, + 0x1.220d872014364p-3, -0x1.0787238281293p-3, 0x1.48db40ca33fbep-7, 0x1.e50545d21d433p-4, + -0x1.4fae3daf6d6c4p-5, 0x1.b63cbae5dca61p-5, 0x1.d0efc83c238b1p-3, 0x1.d42c3fddcd0c2p-8, + 0x1.c528d64586024p-4, -0x1.93328a44dff89p-4, -0x1.d8f1ff6b0af30p-10, -0x1.528805a4b54d3p-3, + -0x1.3148b3738ceb6p-5, 0x1.0133d5daaccc0p-3, 0x1.9297871261ce4p-3, -0x1.7815d1d33df51p-7, + -0x1.45ab6d2118bf4p-3, -0x1.f8b25efb57e5cp-6, -0x1.0c9789ddb2d60p-8, -0x1.9a6f7cbe196b5p-8, + -0x1.216678bcc8e82p-10, 0x1.77e23568e7e42p-3, 0x1.984bdcb61b0d7p-9, 0x1.64fa56c47fcb8p-7, + 0x1.04ff5a67d1a77p-3, -0x1.8798c365cf60ep-6, -0x1.602494f0fe87fp-5, -0x1.912509fa31f69p-4, + -0x1.0c039528d6f06p-9, -0x1.f4f0cad054c40p-4, 0x1.49136fde5ee90p-7, 0x1.31379a60a1e77p-3, + 0x1.4d1f5bd2aa26fp-4, -0x1.926a1d0480379p-6, 0x1.ee5aaa45daa75p-7, -0x1.9035279b6b33dp-4, + 0x1.2eea165b9d1a3p-4, 0x1.bcf267766b039p-4, -0x1.94aac2e02b245p-5, 0x1.c441a4d07f2fcp-6, + -0x1.ef7eb72c4c899p-4, -0x1.2b28e11cc9130p-5, 0x1.51a1fe3133f83p-3, 0x1.3a10b05017f82p-5, + 0x1.989cb227eee87p-7, 0x1.6e4948fe1ea1dp-3, -0x1.14708b3fa9e00p-9, 0x1.043b4ea6ecf94p-4, + -0x1.a6b1421fc371dp-5, 0x1.2876632b8b923p-5, -0x1.9caa34e4cb977p-5, -0x1.d149bbe89cd03p-8, + -0x1.e6426c6c6a82ep-4, 0x1.c9ec89fdf5f01p-4, 0x1.736ffaf7097c4p-8, 0x1.0c4719def3f82p-7, + -0x1.d8392e5033ee2p-6, -0x1.b675eb7e315eep-10, -0x1.9d6b5255a4c1fp-6, -0x1.191c3f34241bcp-4, + -0x1.7c3a9461e44dep-5, -0x1.db6526f06cba1p-4, 0x1.d17e753ba1880p-4, 0x1.aa6c7ed2da705p-5, + -0x1.e426a2b4401a8p-4, 0x1.4d1e213130dd3p-5, 0x1.d79776eec6838p-5, -0x1.c678b31ab2c59p-4, + 0x1.1d3443ad07b46p-5, 0x1.ebbd88ffc8405p-4, -0x1.ba5aa9afc21b9p-4, -0x1.01cfc7df71508p-4, + 0x1.f2252f0d1da21p-4, -0x1.d934ff334ec69p-6, -0x1.1734d867a01c9p-4, 0x1.ad2bcab4602cep-4, + -0x1.76dda0fc182c8p-6, -0x1.f7599c7ee5072p-4, 0x1.9ef43f2eed53ap-4, 0x1.2bedb046eda0ep-4, + -0x1.fb5799f3441e3p-4, 0x1.139f09cf51e42p-6, 0x1.3fed94256a324p-4, -0x1.8fbcc79064707p-4, + 0x1.5f6d01628f81cp-7, 0x1.fe1cb102ef8ebp-4, -0x1.7f8eca78bfd28p-4, -0x1.532826cf10852p-4, + 0x1.ffa72ed8e0943p-4, -0x1.2d867136b33d1p-8, -0x1.65918ee671c8cp-4, 0x1.6e7446041dab5p-4, + 0x1.921d3b9a515dap-10, -0x1.fff621854485bp-4, 0x1.5c77bea5414a0p-4, 0x1.771e784cbe673p-4, + -0x1.ff095349f69cbp-4, -0x1.f656deba2cc9dp-8, 0x1.87c40422deea1p-4, -0x1.49a44b76d0cd0p-4, + -0x1.c37856ebea75fp-7, 0x1.fce1608949f2bp-4, -0x1.36058c506a8e2p-4, -0x1.9777efe3a4b46p-4, + 0x1.f97f9314c8ee1p-4, 0x1.45576eb605947p-6, -0x1.a6309301683eep-4, 0x1.21a797a7b3270p-4, + 0x1.a829fc1ed914fp-6, -0x1.f4e60201be59ap-4, 0x1.0c97041623a2fp-4, 0x1.b3e4d4f902c73p-4, + -0x1.ef178cbf8e4b7p-4, -0x1.04fb854e62bc4p-5, 0x1.c08c412e9ccfdp-4, -0x1.edc1968fad3fcp-5, + -0x1.35410bedad572p-5, 0x1.e817b8d9641a8p-4, -0x1.c1249ad5d5a98p-5, -0x1.cc1f104651bd2p-4, + 0x1.dfeae7ceef227p-4, 0x1.64c7dad285f83p-5, -0x1.d696176660c90p-4, 0x1.9372a53646019p-5, + 0x1.9372a53646019p-5, -0x1.d696176660c90p-4, 0x1.64c7dad285f83p-5, 0x1.dfeae7ceef227p-4, + -0x1.cc1f104651bd2p-4, -0x1.c1249ad5d5a98p-5, 0x1.e817b8d9641a8p-4, -0x1.35410bedad572p-5, + -0x1.edc1968fad3fcp-5, 0x1.c08c412e9ccfdp-4, -0x1.04fb854e62bc4p-5, -0x1.ef178cbf8e4b7p-4, + 0x1.b3e4d4f902c73p-4, 0x1.0c97041623a2fp-4, -0x1.f4e60201be59ap-4, 0x1.a829fc1ed914fp-6, + 0x1.21a797a7b3270p-4, -0x1.a6309301683eep-4, 0x1.45576eb605947p-6, 0x1.f97f9314c8ee1p-4, + -0x1.9777efe3a4b46p-4, -0x1.36058c506a8e2p-4, 0x1.fce1608949f2bp-4, -0x1.c37856ebea75fp-7, + -0x1.49a44b76d0cd0p-4, 0x1.87c40422deea1p-4, -0x1.f656deba2cc9dp-8, -0x1.ff095349f69cbp-4, + 0x1.771e784cbe673p-4, 0x1.5c77bea5414a0p-4, -0x1.fff621854485bp-4, 0x1.921d3b9a515dap-10, + 0x1.6e7446041dab5p-4, -0x1.65918ee671c8cp-4, -0x1.2d867136b33d1p-8, 0x1.ffa72ed8e0943p-4, + -0x1.532826cf10852p-4, -0x1.7f8eca78bfd28p-4, 0x1.fe1cb102ef8ebp-4, 0x1.5f6d01628f81cp-7, + -0x1.8fbcc79064707p-4, 0x1.3fed94256a324p-4, 0x1.139f09cf51e42p-6, -0x1.fb5799f3441e3p-4, + 0x1.2bedb046eda0ep-4, 0x1.9ef43f2eed53ap-4, -0x1.f7599c7ee5072p-4, -0x1.76dda0fc182c8p-6, + 0x1.ad2bcab4602cep-4, -0x1.1734d867a01c9p-4, -0x1.d934ff334ec69p-6, 0x1.f2252f0d1da21p-4, + -0x1.01cfc7df71508p-4, -0x1.ba5aa9afc21b9p-4, 0x1.ebbd88ffc8405p-4, 0x1.1d3443ad07b46p-5, + -0x1.c678b31ab2c59p-4, 0x1.d79776eec6838p-5, 0x1.4d1e213130dd3p-5, -0x1.e426a2b4401a8p-4, + 0x1.aa6c7ed2da705p-5, 0x1.d17e753ba1880p-4, -0x1.db6526f06cb9fp-4, -0x1.7c3a9461e44e1p-5, + 0x1.db65271fad35fp-4, -0x1.7c3a939ff2035p-5, 0x1.aa6c7ec605883p-5, -0x1.d17e74c2ccbffp-4, + -0x1.4d1e1ff3c7dc0p-5, -0x1.e426a48a70c03p-4, -0x1.c678b462c0c48p-4, -0x1.d79776b162041p-5, + -0x1.ebbd8a75c461ep-4, 0x1.1d3444cebf2fbp-5, -0x1.01cfc750e6b6ap-4, 0x1.ba5aaa027afb1p-4, + 0x1.d934fe0cdfed9p-6, 0x1.f2253135821e8p-4, 0x1.ad2bc92390fbcp-4, 0x1.1734d72828060p-4, + 0x1.f7599af3b0b7cp-4, -0x1.76dda1f7a0c91p-6, 0x1.2bedb006497a1p-4, -0x1.9ef44011c6003p-4, + -0x1.139f0a44927fcp-6, -0x1.fb57981cee8dap-4, -0x1.8fbcc79e8685cp-4, -0x1.3fed93297f7d6p-4, + -0x1.fe1caf0a75b7dp-4, 0x1.5f6d00c8fe005p-7, -0x1.5328278f5957dp-4, 0x1.7f8ec9a562c15p-4, + 0x1.2d867267b5648p-8, 0x1.ffa72e160006fp-4, 0x1.6e7445e53700cp-4, 0x1.6591909cabfbfp-4, + 0x1.fff620b9da7fep-4, 0x1.921d37d28bd00p-10, 0x1.771e78345ac4cp-4, -0x1.5c77bdbbbb790p-4, + 0x1.f656dcda0d936p-8, -0x1.ff09549794bacp-4, -0x1.49a44babb1da3p-4, -0x1.87c403f3541a2p-4, + -0x1.fce15e93665acp-4, -0x1.c37855f1c71a8p-7, -0x1.9777f05dcd541p-4, 0x1.36058b3eb8ea3p-4, + -0x1.45576ecad19fap-6, 0x1.f97f9414ca280p-4, 0x1.21a797b879b8bp-4, 0x1.a630940ee5041p-4, + 0x1.f4e602b0ba75ep-4, 0x1.a829fa83168a2p-6, 0x1.b3e4d46ebc565p-4, -0x1.0c9704598903ap-4, + 0x1.04fb855b033e2p-5, -0x1.ef178d244f4b9p-4, -0x1.edc1989996936p-5, -0x1.c08c41a04a231p-4, + -0x1.e817b91ba481bp-4, -0x1.35410be143172p-5, -0x1.cc1f10860c92bp-4, 0x1.c1249b8009b2ep-5, + -0x1.64c7d9b793abep-5, 0x1.dfeae73da9472p-4, 0x1.9372a61188a3fp-5, 0x1.d696179387a1dp-4, + 0x1.d696179387a1dp-4, 0x1.9372a61188a3fp-5, 0x1.dfeae73da9472p-4, -0x1.64c7d9b793abep-5, + 0x1.c1249b8009b2ep-5, -0x1.cc1f10860c92bp-4, -0x1.35410be143172p-5, -0x1.e817b91ba481bp-4, + -0x1.c08c41a04a231p-4, -0x1.edc1989996936p-5, -0x1.ef178d244f4b9p-4, 0x1.04fb855b033e2p-5, + -0x1.0c9704598903ap-4, 0x1.b3e4d46ebc565p-4, 0x1.a829fa83168a2p-6, 0x1.f4e602b0ba75ep-4, + 0x1.a630940ee5041p-4, 0x1.21a797b879b8bp-4, 0x1.f97f9414ca280p-4, -0x1.45576ecad19fap-6, + 0x1.36058b3eb8ea3p-4, -0x1.9777f05dcd541p-4, -0x1.c37855f1c71a8p-7, -0x1.fce15e93665acp-4, + -0x1.87c403f3541a2p-4, -0x1.49a44babb1da3p-4, -0x1.ff09549794bacp-4, 0x1.f656dcda0d936p-8, + -0x1.5c77bdbbbb790p-4, 0x1.771e78345ac4cp-4, 0x1.921d37d28bd00p-10, 0x1.fff620b9da7fep-4, + 0x1.6591909cabfbfp-4, 0x1.6e7445e53700cp-4, 0x1.ffa72e160006fp-4, 0x1.2d867267b5648p-8, + 0x1.7f8ec9a562c15p-4, -0x1.5328278f5957dp-4, 0x1.5f6d00c8fe005p-7, -0x1.fe1caf0a75b7dp-4, + -0x1.3fed93297f7d6p-4, -0x1.8fbcc79e8685cp-4, -0x1.fb57981cee8dap-4, -0x1.139f0a44927fcp-6, + -0x1.9ef44011c6003p-4, 0x1.2bedb006497a1p-4, -0x1.76dda1f7a0c91p-6, 0x1.f7599af3b0b7cp-4, + 0x1.1734d72828060p-4, 0x1.ad2bc92390fbcp-4, 0x1.f2253135821e8p-4, 0x1.d934fe0cdfed9p-6, + 0x1.ba5aaa027afb1p-4, -0x1.01cfc750e6b6ap-4, 0x1.1d3444cebf2fbp-5, -0x1.ebbd8a75c461ep-4, + -0x1.d79776b162041p-5, -0x1.c678b462c0c48p-4, -0x1.e426a48a70c03p-4, -0x1.4d1e1ff3c7dc0p-5, + -0x1.d17e74c2ccbffp-4, 0x1.aa6c7ec605883p-5, -0x1.7c3a939ff2036p-5, 0x1.db65271fad382p-4, + 0x1.264594dd9a2b5p-4, 0x1.ab650f865802fp-6, 0x1.3b2a1e5d81839p-9, -0x1.29b1f7f7d544cp-11, + 0x1.9a2f2a6ce1721p-7, 0x1.2ea74becfed84p-7, 0x1.1d2418f18a952p-3, 0x1.0edffb9986649p-4, + 0x1.5f256b7e43593p-3, -0x1.c4af9407fb465p-7, -0x1.f3acf6a0481c4p-4, 0x1.a368d6e4f53a2p-4, + 0x1.e336ac09b5bd4p-7, -0x1.d7c30989fab12p-3, -0x1.0b25ad5c16c27p-5, 0x1.1a5da0d8d6ea5p-4, + 0x1.21fcbc4b33123p-4, -0x1.0b428cfb78c53p-9, 0x1.a8bc198444a38p-5, -0x1.d9d58f2925d28p-6, + -0x1.211b9dc6b2e7bp-7, -0x1.60c43f30804c9p-3, -0x1.2dd68f3d37319p-3, -0x1.261050ebeec6ep-4, + -0x1.afd74cb8eb0b7p-4, 0x1.bc895f403b087p-8, -0x1.48c87d7090b58p-4, 0x1.7fbc301933c2fp-6, + -0x1.7d2deb5404684p-7, -0x1.827968f07d793p-5, -0x1.2301825b95e45p-5, -0x1.d27f9bfc290e1p-6, + 0x1.4ba96adc2d748p-3, 0x1.47b0266b2dc96p-7, 0x1.187e890c0ffe5p-5, 0x1.38788af64f00fp-4, + 0x1.aab131157bd9dp-7, 0x1.50882cb642a70p-3, -0x1.eb976ee9763f1p-4, -0x1.f764544ad2162p-5, + -0x1.5a0dc2984322cp-3, -0x1.1d47ae6e71adfp-7, 0x1.38e805e54a92bp-3, 0x1.ac4c530be274ap-7, + -0x1.18f1a27d085acp-5, -0x1.4018cbb60ac35p-4, -0x1.c6ca056909a8bp-8, 0x1.8e6c9a56514e4p-4, + -0x1.61b75f7a7b4dbp-5, 0x1.f43687aa655d5p-6, -0x1.15c8614646056p-3, 0x1.cd674f5083969p-6, + 0x1.689a496443c44p-5, 0x1.de7104c3d6a28p-4, 0x1.090f65e1ce0bep-5, -0x1.493d1bc2353c8p-3, + 0x1.76c286b39d1e5p-3, -0x1.849a6c174ed4cp-6, 0x1.cf6a653115e20p-4, 0x1.d48a5ecdc2a4cp-7, + 0x1.ce1cf9c7fe1a9p-7, 0x1.e0e5585a83777p-9, -0x1.c5e7e8f738c9bp-5, 0x1.3bfe3b21a0bf1p-4, + 0x1.3bfe3b21a0bf1p-4, -0x1.c5e7e8f738c9bp-5, 0x1.e0e5585a83777p-9, 0x1.ce1cf9c7fe1a9p-7, + 0x1.d48a5ecdc2a4cp-7, 0x1.cf6a653115e20p-4, -0x1.849a6c174ed4cp-6, 0x1.76c286b39d1e5p-3, + -0x1.493d1bc2353c8p-3, 0x1.090f65e1ce0bep-5, 0x1.de7104c3d6a28p-4, 0x1.689a496443c44p-5, + 0x1.cd674f5083969p-6, -0x1.15c8614646056p-3, 0x1.f43687aa655d5p-6, -0x1.61b75f7a7b4dbp-5, + 0x1.8e6c9a56514e4p-4, -0x1.c6ca056909a8bp-8, -0x1.4018cbb60ac35p-4, -0x1.18f1a27d085acp-5, + 0x1.ac4c530be274ap-7, 0x1.38e805e54a92bp-3, -0x1.1d47ae6e71adfp-7, -0x1.5a0dc2984322cp-3, + -0x1.f764544ad2162p-5, -0x1.eb976ee9763f1p-4, 0x1.50882cb642a70p-3, 0x1.aab131157bd9dp-7, + 0x1.38788af64f00fp-4, 0x1.187e890c0ffe5p-5, 0x1.47b0266b2dc96p-7, 0x1.4ba96adc2d748p-3, + -0x1.d27f9bfc290e1p-6, -0x1.2301825b95e45p-5, -0x1.827968f07d793p-5, -0x1.7d2deb5404684p-7, + 0x1.7fbc301933c2fp-6, -0x1.48c87d7090b58p-4, 0x1.bc895f403b087p-8, -0x1.afd74cb8eb0b7p-4, + -0x1.261050ebeec6ep-4, -0x1.2dd68f3d37319p-3, -0x1.60c43f30804c9p-3, -0x1.211b9dc6b2e7bp-7, + -0x1.d9d58f2925d28p-6, 0x1.a8bc198444a38p-5, -0x1.0b428cfb78c53p-9, 0x1.21fcbc4b33123p-4, + 0x1.1a5da0d8d6ea5p-4, -0x1.0b25ad5c16c27p-5, -0x1.d7c30989fab12p-3, 0x1.e336ac09b5bd4p-7, + 0x1.a368d6e4f53a2p-4, -0x1.f3acf6a0481c4p-4, -0x1.c4af9407fb465p-7, 0x1.5f256b7e43593p-3, + 0x1.0edffb9986649p-4, 0x1.1d2418f18a94fp-3, 0x1.2ea74becfed89p-7, 0x1.9a2f2a6ce1717p-7, + -0x1.29b1f7f7d5628p-11, 0x1.3b2a1e5d815d7p-9, 0x1.ab650f83deee5p-6, 0x1.2645945bca6dap-4, + -0x1.ab4c3fa796424p-7, -0x1.e80c55c1dd923p-3, -0x1.95666a59e50b3p-5, -0x1.e290bb9eb3c66p-6, + -0x1.bfc3c5d6ab333p-3, -0x1.b4799725c38dbp-6, -0x1.83af862bde386p-4, 0x1.892b017cfd958p-6, + -0x1.b4683a68ab112p-9, 0x1.b587977803f34p-3, -0x1.2c5bdf6769b04p-5, 0x1.71646c3e25f13p-5, + 0x1.59fc57579bbb2p-7, 0x1.04f05394595a6p-8, 0x1.4ca10d0615b17p-4, -0x1.20c52d530dd7dp-4, + -0x1.eec55225bd791p-5, 0x1.c1533b8d6ad71p-6, 0x1.aacd5172aafe5p-11, 0x1.95e3b62a5cb5bp-6, + -0x1.d7a058237ade9p-6, 0x1.74b2245b470bbp-6, -0x1.f0e79fd6f288ep-6, 0x1.575ab5831835dp-5, + 0x1.1799066a16a90p-7, -0x1.7ccc8b1f443dap-3, 0x1.673e168188c91p-4, -0x1.4c2f0e97a2c03p-3, + -0x1.531b273e90609p-8, -0x1.01b46097fd06dp-12, -0x1.8ceed08a775b9p-5, 0x1.6b7928f7d58abp-8, + -0x1.10871671d4d98p-6, -0x1.184bbd5f67266p-6, -0x1.fb3e6ee3e9379p-5, 0x1.3b8cb36318828p-8, + 0x1.5b2c8be8d9592p-6, -0x1.d138da008aa1cp-8, 0x1.562b7ed74d617p-5, -0x1.54b5ea91d37c5p-4, + 0x1.5eb8b0b147e67p-6, 0x1.a846733e49503p-5, 0x1.a13758af6ef21p-4, -0x1.c18a1e85fedf7p-6, + -0x1.12292e9b0f841p-5, 0x1.4951344574f5cp-6, -0x1.03487dc5c1123p-2, 0x1.b1d42a9146fc5p-5, + -0x1.00af86fd71bc3p-5, 0x1.f13f8d6032cdfp-4, -0x1.08104200bc09dp-4, -0x1.09b62612471c9p-3, + 0x1.088f16ce5b70cp-3, -0x1.b7876848a86acp-9, 0x1.1fa6bea29c291p-3, -0x1.3d431d475bdacp-4, + -0x1.5cde948b0d3edp-6, -0x1.d83e4548f0e57p-3, 0x1.3380f927a7509p-9, -0x1.39e882d1901b0p-6, + -0x1.6dbc39f79af25p-5, -0x1.819b1b841db92p-5, 0x1.491e064a99245p-4, 0x1.c732bdccd5fe2p-6, + 0x1.c732bdccd5fe2p-6, 0x1.491e064a99245p-4, -0x1.819b1b841db92p-5, -0x1.6dbc39f79af25p-5, + -0x1.39e882d1901b0p-6, 0x1.3380f927a7509p-9, -0x1.d83e4548f0e57p-3, -0x1.5cde948b0d3edp-6, + -0x1.3d431d475bdacp-4, 0x1.1fa6bea29c291p-3, -0x1.b7876848a86acp-9, 0x1.088f16ce5b70cp-3, + -0x1.09b62612471c9p-3, -0x1.08104200bc09dp-4, 0x1.f13f8d6032cdfp-4, -0x1.00af86fd71bc3p-5, + 0x1.b1d42a9146fc5p-5, -0x1.03487dc5c1123p-2, 0x1.4951344574f5cp-6, -0x1.12292e9b0f841p-5, + -0x1.c18a1e85fedf7p-6, 0x1.a13758af6ef21p-4, 0x1.a846733e49503p-5, 0x1.5eb8b0b147e67p-6, + -0x1.54b5ea91d37c5p-4, 0x1.562b7ed74d617p-5, -0x1.d138da008aa1cp-8, 0x1.5b2c8be8d9592p-6, + 0x1.3b8cb36318828p-8, -0x1.fb3e6ee3e9379p-5, -0x1.184bbd5f67266p-6, -0x1.10871671d4d98p-6, + 0x1.6b7928f7d58abp-8, -0x1.8ceed08a775b9p-5, -0x1.01b46097fd06dp-12, -0x1.531b273e90609p-8, + -0x1.4c2f0e97a2c03p-3, 0x1.673e168188c91p-4, -0x1.7ccc8b1f443dap-3, 0x1.1799066a16a90p-7, + 0x1.575ab5831835dp-5, -0x1.f0e79fd6f288ep-6, 0x1.74b2245b470bbp-6, -0x1.d7a058237ade9p-6, + 0x1.95e3b62a5cb5bp-6, 0x1.aacd5172aafe5p-11, 0x1.c1533b8d6ad71p-6, -0x1.eec55225bd791p-5, + -0x1.20c52d530dd7dp-4, 0x1.4ca10d0615b17p-4, 0x1.04f05394595a6p-8, 0x1.59fc57579bbb2p-7, + 0x1.71646c3e25f13p-5, -0x1.2c5bdf6769b04p-5, 0x1.b587977803f34p-3, -0x1.b4683a68ab112p-9, + 0x1.892b017cfd944p-6, -0x1.83af862bde38dp-4, -0x1.b4799725c38d3p-6, -0x1.bfc3c5d6ab333p-3, + -0x1.e290bb9eb3c97p-6, -0x1.95666a59e50bap-5, -0x1.e80c55efc1fa8p-3, -0x1.ab4c404115431p-7, + -0x1.9372a60c5fbecp-5, -0x1.d696175325632p-4, 0x1.dfeae54935cc5p-4, 0x1.64c7defb7da1ap-5, + -0x1.cc1f0e52f989dp-4, 0x1.c1249bedc3d31p-5, 0x1.35410d36196c7p-5, -0x1.e817ba8eae953p-4, + 0x1.edc1961b021dep-5, 0x1.c08c402ca3997p-4, -0x1.ef178a79ddc68p-4, -0x1.04fb821a97322p-5, + 0x1.b3e4d3bbd7be1p-4, -0x1.0c9704fb951ddp-4, -0x1.a82a0285c182fp-6, 0x1.f4e605971efa5p-4, + -0x1.21a798af1da13p-4, -0x1.a63092203600ap-4, 0x1.f97f92562d9a1p-4, 0x1.45576d9119973p-6, + -0x1.9777edf56c101p-4, 0x1.36058a5140f32p-4, 0x1.c378580248ee8p-7, -0x1.fce15e2f236a6p-4, + 0x1.49a448f0ca515p-4, 0x1.87c3fe8ab44f0p-4, -0x1.ff0953dd0e874p-4, -0x1.f656dffcbeec5p-8, + 0x1.771e76026cf8ep-4, -0x1.5c77bd4be1a75p-4, -0x1.921d006a41966p-10, 0x1.fff620363bcc7p-4, + -0x1.6e74439e74a9ep-4, -0x1.659192892ebaap-4, 0x1.ffa7323fa7e99p-4, -0x1.2d86511f2fabap-8, + -0x1.53282ab6e17a9p-4, 0x1.7f8ecf31638ccp-4, -0x1.5f6cf8bc6536ep-7, -0x1.fe1cb146a271cp-4, + 0x1.8fbccbe3995dep-4, 0x1.3fed94e99f992p-4, -0x1.fb579800d8797p-4, 0x1.139f08def790bp-6, + 0x1.2bedb25823cc6p-4, -0x1.9ef43dd361ce9p-4, 0x1.76dd9d407134ap-6, 0x1.f7599bd35d389p-4, + -0x1.ad2bcdc4f1a7bp-4, -0x1.1734d40b7d6bap-4, 0x1.f2252cfbaa576p-4, -0x1.d934f91a7fe16p-6, + -0x1.01cfc861d8d1fp-4, 0x1.ba5aa94f7a73fp-4, -0x1.1d3444a98d487p-5, -0x1.ebbd8c97722f7p-4, + 0x1.c678b3be2b409p-4, 0x1.d79773bf5d709p-5, -0x1.e426a55280be6p-4, 0x1.4d1e25dec469cp-5, + 0x1.aa6c85c02a075p-5, -0x1.d17e7797d6d13p-4, 0x1.7c3a93db52514p-5, 0x1.db65240513311p-4, + -0x1.db65240513311p-4, -0x1.7c3a93db52514p-5, 0x1.d17e7797d6d13p-4, -0x1.aa6c85c02a075p-5, + -0x1.4d1e25dec469cp-5, 0x1.e426a55280be6p-4, -0x1.d79773bf5d709p-5, -0x1.c678b3be2b409p-4, + 0x1.ebbd8c97722f7p-4, 0x1.1d3444a98d487p-5, -0x1.ba5aa94f7a73fp-4, 0x1.01cfc861d8d1fp-4, + 0x1.d934f91a7fe16p-6, -0x1.f2252cfbaa576p-4, 0x1.1734d40b7d6bap-4, 0x1.ad2bcdc4f1a7bp-4, + -0x1.f7599bd35d389p-4, -0x1.76dd9d407134ap-6, 0x1.9ef43dd361ce9p-4, -0x1.2bedb25823cc6p-4, + -0x1.139f08def790bp-6, 0x1.fb579800d8797p-4, -0x1.3fed94e99f992p-4, -0x1.8fbccbe3995dep-4, + 0x1.fe1cb146a271cp-4, 0x1.5f6cf8bc6536ep-7, -0x1.7f8ecf31638ccp-4, 0x1.53282ab6e17a9p-4, + 0x1.2d86511f2fabap-8, -0x1.ffa7323fa7e99p-4, 0x1.659192892ebaap-4, 0x1.6e74439e74a9ep-4, + -0x1.fff620363bcc7p-4, 0x1.921d006a41966p-10, 0x1.5c77bd4be1a75p-4, -0x1.771e76026cf8ep-4, + 0x1.f656dffcbeec5p-8, 0x1.ff0953dd0e874p-4, -0x1.87c3fe8ab44f0p-4, -0x1.49a448f0ca515p-4, + 0x1.fce15e2f236a6p-4, -0x1.c378580248ee8p-7, -0x1.36058a5140f32p-4, 0x1.9777edf56c101p-4, + -0x1.45576d9119973p-6, -0x1.f97f92562d9a1p-4, 0x1.a63092203600ap-4, 0x1.21a798af1da13p-4, + -0x1.f4e605971efa5p-4, 0x1.a82a0285c182fp-6, 0x1.0c9704fb951ddp-4, -0x1.b3e4d3bbd7be1p-4, + 0x1.04fb821a97322p-5, 0x1.ef178a79ddc68p-4, -0x1.c08c402ca3997p-4, -0x1.edc1961b021dep-5, + 0x1.e817ba8eae953p-4, -0x1.35410d36196c7p-5, -0x1.c1249bedc3d31p-5, 0x1.cc1f0e52f989dp-4, + -0x1.64c7defb7da1ap-5, -0x1.dfeae54935cc5p-4, 0x1.d696175325620p-4, 0x1.9372a60c5fbedp-5, + 0x1.d696169cdd129p-4, -0x1.9372a675f770fp-5, 0x1.64c7dee6a9f2ep-5, -0x1.dfeae47d23e8ep-4, + -0x1.c1249d5592de3p-5, -0x1.cc1f0f2837110p-4, -0x1.e817ba63f509cp-4, -0x1.35410d5152788p-5, + -0x1.c08c4160825fcp-4, 0x1.edc19528ecbc9p-5, -0x1.04fb826a5e5b8p-5, 0x1.ef178a56d5ee5p-4, + 0x1.0c9703e5ae1acp-4, 0x1.b3e4d349960c5p-4, 0x1.f4e603d55faedp-4, 0x1.a82a02c6ebb15p-6, + 0x1.a630930014c25p-4, -0x1.21a797dc00b38p-4, 0x1.45576e20b1da9p-6, -0x1.f97f92a91f6c2p-4, + -0x1.36058ad7d008ep-4, -0x1.9777eef02e2d9p-4, -0x1.fce15ea1e2347p-4, -0x1.c37859b4dff5fp-7, + -0x1.87c3ff16053b9p-4, 0x1.49a448e4d2132p-4, -0x1.f656e0a42f0aap-8, 0x1.ff0953da355c2p-4, + 0x1.5c77bcef15002p-4, 0x1.771e766feac48p-4, 0x1.fff6219b41de4p-4, 0x1.921d00f6c0557p-10, + 0x1.6591926ad9167p-4, -0x1.6e7444b512681p-4, -0x1.2d865179dcd95p-8, -0x1.ffa731126bf28p-4, + -0x1.7f8ecfb9cc609p-4, -0x1.53282a69f539fp-4, -0x1.fe1cb1d68848ap-4, 0x1.5f6cf83b0bdfap-7, + -0x1.3fed94d440b9bp-4, 0x1.8fbccbc0d0c0bp-4, 0x1.139f086b5a31dp-6, 0x1.fb57981d866b9p-4, + 0x1.9ef43f520f3c6p-4, 0x1.2bedb2d56c615p-4, 0x1.f7599b4bf2ee3p-4, -0x1.76dd9c1aea201p-6, + 0x1.1734d41d7c8cfp-4, -0x1.ad2bcde117336p-4, -0x1.d934f7f96a06bp-6, -0x1.f2252c0f2ff4fp-4, + -0x1.ba5aa9815eb67p-4, -0x1.01cfc842bf699p-4, -0x1.ebbd8d5f12a97p-4, 0x1.1d34453b59804p-5, + -0x1.d797748504f17p-5, 0x1.c678b24b3da89p-4, 0x1.4d1e24aef1a2dp-5, 0x1.e426a4f4603b4p-4, + 0x1.d17e76cc90630p-4, 0x1.aa6c8500ab84cp-5, 0x1.db6523b7452fep-4, -0x1.7c3a935cd2091p-5, + 0x1.7c3a935cd2091p-5, -0x1.db6523b7452fep-4, -0x1.aa6c8500ab84cp-5, -0x1.d17e76cc90630p-4, + -0x1.e426a4f4603b4p-4, -0x1.4d1e24aef1a2dp-5, -0x1.c678b24b3da89p-4, 0x1.d797748504f17p-5, + -0x1.1d34453b59804p-5, 0x1.ebbd8d5f12a97p-4, 0x1.01cfc842bf699p-4, 0x1.ba5aa9815eb67p-4, + 0x1.f2252c0f2ff4fp-4, 0x1.d934f7f96a06bp-6, 0x1.ad2bcde117336p-4, -0x1.1734d41d7c8cfp-4, + 0x1.76dd9c1aea201p-6, -0x1.f7599b4bf2ee3p-4, -0x1.2bedb2d56c615p-4, -0x1.9ef43f520f3c6p-4, + -0x1.fb57981d866b9p-4, -0x1.139f086b5a31dp-6, -0x1.8fbccbc0d0c0bp-4, 0x1.3fed94d440b9bp-4, + -0x1.5f6cf83b0bdfap-7, 0x1.fe1cb1d68848ap-4, 0x1.53282a69f539fp-4, 0x1.7f8ecfb9cc609p-4, + 0x1.ffa731126bf28p-4, 0x1.2d865179dcd95p-8, 0x1.6e7444b512681p-4, -0x1.6591926ad9167p-4, + -0x1.921d00f6c0557p-10, -0x1.fff6219b41de4p-4, -0x1.771e766feac48p-4, -0x1.5c77bcef15002p-4, + -0x1.ff0953da355c2p-4, 0x1.f656e0a42f0aap-8, -0x1.49a448e4d2132p-4, 0x1.87c3ff16053b9p-4, + 0x1.c37859b4dff5fp-7, 0x1.fce15ea1e2347p-4, 0x1.9777eef02e2d9p-4, 0x1.36058ad7d008ep-4, + 0x1.f97f92a91f6c2p-4, -0x1.45576e20b1da9p-6, 0x1.21a797dc00b38p-4, -0x1.a630930014c25p-4, + -0x1.a82a02c6ebb15p-6, -0x1.f4e603d55faedp-4, -0x1.b3e4d349960c5p-4, -0x1.0c9703e5ae1acp-4, + -0x1.ef178a56d5ee5p-4, 0x1.04fb826a5e5b8p-5, -0x1.edc19528ecbc9p-5, 0x1.c08c4160825fcp-4, + 0x1.35410d5152788p-5, 0x1.e817ba63f509cp-4, 0x1.cc1f0f2837110p-4, 0x1.c1249d5592de3p-5, + 0x1.dfeae47d23e8ep-4, -0x1.64c7dee6a9f2ep-5, 0x1.9372a675f770fp-5, -0x1.d696169cdd130p-4, + -0x1.7e718a4a3cf3dp-5, -0x1.1cb17a8d18195p-4, -0x1.6228d4eee08b3p-6, 0x1.a0fb27340cdb8p-4, + 0x1.3da86f73e4430p-6, -0x1.695522d30eae0p-4, -0x1.9ae28bea35a12p-3, 0x1.23d5ceb1df2fcp-5, + 0x1.a6a892382da59p-3, -0x1.624bcd04465c1p-4, 0x1.46cfd54229871p-6, 0x1.f9c568a0c3c5bp-4, + 0x1.baa8d08fdec7dp-4, 0x1.77bd88a94b5efp-4, 0x1.3956a92d06ab6p-6, -0x1.dc1cab02e36e4p-6, + -0x1.4c6705a7af3f9p-5, -0x1.633fb3e29c3b1p-5, 0x1.c066f7d91b255p-6, -0x1.6367d60f608fdp-4, + 0x1.f52c9a8a222f4p-4, 0x1.731390bf0bfa9p-4, -0x1.6bc5a48004bafp-5, 0x1.0bd4de22b57dbp-6, + -0x1.2406410739d5dp-7, -0x1.087b8c8ec1700p-5, -0x1.abec78f17e999p-9, 0x1.00f976fbceb8ap-3, + 0x1.7cf3d1d00defdp-6, 0x1.ea1443b353d49p-4, -0x1.67ed85d0291c1p-3, -0x1.5a7d3c60030e5p-8, + -0x1.89b96a7f47694p-7, -0x1.fc25ce273877cp-5, 0x1.fc23c62cd6187p-11, 0x1.1595ff72ad6d2p-3, + 0x1.053be2fd32756p-3, 0x1.5d0ef7fe18c59p-5, 0x1.c9f42a20910a2p-3, 0x1.47e494580494fp-6, + 0x1.9dd3d3d2656e0p-5, -0x1.2b2672c92204ap-4, -0x1.dd473916fe2f9p-8, -0x1.3833b7235569bp-4, + 0x1.1f0977be6b3dfp-4, 0x1.987c3f88ffd70p-5, -0x1.13233219f08f1p-4, 0x1.81e17cf7bdc19p-7, + -0x1.701983d8aaecap-6, -0x1.53d30e76d589cp-7, -0x1.4353618bcc0a2p-5, -0x1.bc4a0377733a2p-6, + 0x1.2d5e72e67adb6p-3, 0x1.7457cde6dcee2p-5, -0x1.73894ab403f67p-4, -0x1.46ed4221aeb52p-4, + -0x1.41ac98a5f3008p-4, 0x1.3947b4435acbbp-4, 0x1.fb55ea1332d4fp-7, 0x1.4a499ea3ef1c7p-3, + 0x1.0c84b93a1f72ep-5, -0x1.200d496c9e9f8p-4, 0x1.aac66cb076e2cp-3, -0x1.fc7f38c17c8e2p-10, + 0x1.fc7f38c17c8e2p-10, -0x1.aac66cb076e2cp-3, 0x1.200d496c9e9f8p-4, -0x1.0c84b93a1f72ep-5, + -0x1.4a499ea3ef1c7p-3, -0x1.fb55ea1332d4fp-7, -0x1.3947b4435acbbp-4, 0x1.41ac98a5f3008p-4, + 0x1.46ed4221aeb52p-4, 0x1.73894ab403f67p-4, -0x1.7457cde6dcee2p-5, -0x1.2d5e72e67adb6p-3, + 0x1.bc4a0377733a2p-6, 0x1.4353618bcc0a2p-5, 0x1.53d30e76d589cp-7, 0x1.701983d8aaecap-6, + -0x1.81e17cf7bdc19p-7, 0x1.13233219f08f1p-4, -0x1.987c3f88ffd70p-5, -0x1.1f0977be6b3dfp-4, + 0x1.3833b7235569bp-4, 0x1.dd473916fe2f9p-8, 0x1.2b2672c92204ap-4, -0x1.9dd3d3d2656e0p-5, + -0x1.47e494580494fp-6, -0x1.c9f42a20910a2p-3, -0x1.5d0ef7fe18c59p-5, -0x1.053be2fd32756p-3, + -0x1.1595ff72ad6d2p-3, -0x1.fc23c62cd6187p-11, 0x1.fc25ce273877cp-5, 0x1.89b96a7f47694p-7, + 0x1.5a7d3c60030e5p-8, 0x1.67ed85d0291c1p-3, -0x1.ea1443b353d49p-4, -0x1.7cf3d1d00defdp-6, + -0x1.00f976fbceb8ap-3, 0x1.abec78f17e999p-9, 0x1.087b8c8ec1700p-5, 0x1.2406410739d5dp-7, + -0x1.0bd4de22b57dbp-6, 0x1.6bc5a48004bafp-5, -0x1.731390bf0bfa9p-4, -0x1.f52c9a8a222f4p-4, + 0x1.6367d60f608fdp-4, -0x1.c066f7d91b255p-6, 0x1.633fb3e29c3b1p-5, 0x1.4c6705a7af3f9p-5, + 0x1.dc1cab02e36e4p-6, -0x1.3956a92d06ab6p-6, -0x1.77bd88a94b5efp-4, -0x1.baa8d08fdec7dp-4, + -0x1.f9c568a0c3c5bp-4, -0x1.46cfd54229871p-6, 0x1.624bcd04465c1p-4, -0x1.a6a892382da59p-3, + -0x1.23d5ceb1df2fcp-5, 0x1.9ae28bea35a0fp-3, 0x1.695522d30eae1p-4, -0x1.3da86f73e4402p-6, + -0x1.a0fb27340cdbbp-4, 0x1.6228d4eee0886p-6, 0x1.1cb17a83573cdp-4, 0x1.7e71890596997p-5, + 0x1.04b65de89d3bap-6, -0x1.2967bd8a247c0p-4, -0x1.c07e6966f1833p-5, -0x1.138bf087f730ap-5, + 0x1.129da9f2c86efp-3, -0x1.918dba0ebcdcbp-4, 0x1.d057f10f82839p-6, 0x1.6b26d8a2c4d2fp-4, + 0x1.36f8c58517daep-4, -0x1.c65ac5e976b35p-3, 0x1.42a4bb9f1ac00p-3, 0x1.7c4ee2942a61ap-5, + -0x1.b69ab2e6f332bp-6, -0x1.783e4c5be9482p-4, 0x1.0c55e84d51077p-6, -0x1.b60749c4919abp-5, + -0x1.880bc7e22cd35p-8, 0x1.53ecc839c1c66p-4, -0x1.97bfe7e285b92p-6, -0x1.fd05d28e7e7f2p-8, + 0x1.0c393a79c45e8p-7, -0x1.11125196b12f0p-5, 0x1.ada2b22974a42p-7, -0x1.7e973b847f62ap-4, + 0x1.02609ab01cf49p-3, -0x1.f7da28852df9fp-8, -0x1.de907d91e6fb2p-6, -0x1.3815b40e5de49p-6, + -0x1.1d62a2c5dd093p-3, -0x1.fbe048b773554p-4, 0x1.41bff2d84abaep-5, 0x1.7d2cc90ccb758p-4, + 0x1.913f6d1b1e0ecp-3, 0x1.307e5a41b16c7p-5, 0x1.990eee28980cap-5, -0x1.ce7b74c99484ep-6, + -0x1.3f96f3f225908p-4, 0x1.4335943af1eeap-3, -0x1.57af8ac99cfe4p-5, -0x1.8ae99ce6e2450p-3, + 0x1.08ad452a6e2ecp-4, 0x1.5799f6b190373p-4, 0x1.deec98aa4cb3ep-6, 0x1.3274663dc4c03p-5, + 0x1.eaae213ea9e64p-5, 0x1.12b7370c24099p-4, 0x1.d345eaef665fdp-6, 0x1.7bb951ab95825p-5, + -0x1.6463a8ed4ddcbp-3, -0x1.68b749bffd075p-6, 0x1.8f128f8e21839p-4, -0x1.53244b19c9a0dp-5, + 0x1.11d2a4b92d1dcp-7, -0x1.d9180b787d6d6p-4, -0x1.21a7a43786c5ep-7, -0x1.45762c79435c3p-5, + 0x1.ae0e97281996ep-6, 0x1.c7d9474eac004p-6, -0x1.df427cdd68558p-9, 0x1.d886c6b45006ep-6, + 0x1.b0d907f0eed40p-4, -0x1.beac3b1b30adfp-6, 0x1.2adf5345cf5f0p-6, -0x1.10a3357048b8bp-2, + 0x1.10a3357048b8bp-2, -0x1.2adf5345cf5f0p-6, 0x1.beac3b1b30adfp-6, -0x1.b0d907f0eed40p-4, + -0x1.d886c6b45006ep-6, 0x1.df427cdd68558p-9, -0x1.c7d9474eac004p-6, -0x1.ae0e97281996ep-6, + 0x1.45762c79435c3p-5, 0x1.21a7a43786c5ep-7, 0x1.d9180b787d6d6p-4, -0x1.11d2a4b92d1dcp-7, + 0x1.53244b19c9a0dp-5, -0x1.8f128f8e21839p-4, 0x1.68b749bffd075p-6, 0x1.6463a8ed4ddcbp-3, + -0x1.7bb951ab95825p-5, -0x1.d345eaef665fdp-6, -0x1.12b7370c24099p-4, -0x1.eaae213ea9e64p-5, + -0x1.3274663dc4c03p-5, -0x1.deec98aa4cb3ep-6, -0x1.5799f6b190373p-4, -0x1.08ad452a6e2ecp-4, + 0x1.8ae99ce6e2450p-3, 0x1.57af8ac99cfe4p-5, -0x1.4335943af1eeap-3, 0x1.3f96f3f225908p-4, + 0x1.ce7b74c99484ep-6, -0x1.990eee28980cap-5, -0x1.307e5a41b16c7p-5, -0x1.913f6d1b1e0ecp-3, + -0x1.7d2cc90ccb758p-4, -0x1.41bff2d84abaep-5, 0x1.fbe048b773554p-4, 0x1.1d62a2c5dd093p-3, + 0x1.3815b40e5de49p-6, 0x1.de907d91e6fb2p-6, 0x1.f7da28852df9fp-8, -0x1.02609ab01cf49p-3, + 0x1.7e973b847f62ap-4, -0x1.ada2b22974a42p-7, 0x1.11125196b12f0p-5, -0x1.0c393a79c45e8p-7, + 0x1.fd05d28e7e7f2p-8, 0x1.97bfe7e285b92p-6, -0x1.53ecc839c1c66p-4, 0x1.880bc7e22cd35p-8, + 0x1.b60749c4919abp-5, -0x1.0c55e84d51077p-6, 0x1.783e4c5be9482p-4, 0x1.b69ab2e6f332bp-6, + -0x1.7c4ee2942a61ap-5, -0x1.42a4bb9f1ac00p-3, 0x1.c65ac5e976b35p-3, -0x1.36f8c58517daep-4, + -0x1.6b26d8a2c4d32p-4, -0x1.d057f10f82830p-6, 0x1.918dba0ebcdd0p-4, -0x1.129da9f2c86eep-3, + 0x1.138bf087f72f2p-5, 0x1.c07e6966f1854p-5, 0x1.2967bc4ad3e37p-4, -0x1.04b65dcc5215fp-6, + -0x1.aa6c82867f244p-5, -0x1.d17e78ba2d760p-4, 0x1.ebbd8ad4c94fap-4, 0x1.1d343f850998fp-5, + -0x1.ad2bc9abbfd70p-4, 0x1.1734d561784f6p-4, 0x1.139f06f2e8199p-6, -0x1.fb5797847dbffp-4, + 0x1.532828b4059c4p-4, 0x1.7f8ecf2ffb34dp-4, -0x1.fff622fd20d27p-4, 0x1.921d849e735fep-10, + 0x1.49a44b00dc1edp-4, -0x1.87c3fea35f5eep-4, 0x1.455764aa90831p-6, 0x1.f97f941827f1cp-4, + -0x1.b3e4d2e64b1bbp-4, -0x1.0c9706201df61p-4, 0x1.e817b7562b00dp-4, -0x1.35410f91f7702p-5, + -0x1.9372a8cc4a6f8p-5, 0x1.d69617602e291p-4, -0x1.c124a0dd13c59p-5, -0x1.cc1f0cf11d974p-4, + 0x1.ef178c8061547p-4, 0x1.04fb82addfce1p-5, -0x1.a6308ff5ecb9dp-4, 0x1.21a79c2fb90ffp-4, + 0x1.c378601972aecp-7, -0x1.fce15ef7ed53ap-4, 0x1.5c77bcea2be82p-4, 0x1.771e729684eecp-4, + -0x1.ffa73009273c2p-4, 0x1.2d863e4be420ap-8, 0x1.3fed93b5ea034p-4, -0x1.8fbcc9c24c0c8p-4, + 0x1.76dd99c4d025ap-6, 0x1.f75999fd7fe99p-4, -0x1.ba5aa86b817dep-4, -0x1.01cfc994c546fp-4, + 0x1.e426a19f37b36p-4, -0x1.4d1e2324d78fcp-5, -0x1.7c3a9191e73f1p-5, 0x1.db652845e7d24p-4, + -0x1.d797720f93141p-5, -0x1.c678b7cad163ep-4, 0x1.f2252f956e5b2p-4, 0x1.d934fcde2ed84p-6, + -0x1.9ef43b2d9ecedp-4, 0x1.2bedaf63d4487p-4, 0x1.5f6d001547cfep-7, -0x1.fe1caf25188bap-4, + 0x1.659191b8add5dp-4, 0x1.6e74486a63f70p-4, -0x1.ff0958f6a27c5p-4, 0x1.f656f04396d0dp-8, + 0x1.360587a0c690ep-4, -0x1.9777eeb15433cp-4, 0x1.a82a04e9f9760p-6, 0x1.f4e604a1e6d12p-4, + -0x1.c08c43c11b6bcp-4, -0x1.edc1935a3ae58p-5, 0x1.dfeae7c7b80a6p-4, -0x1.64c7db02c0234p-5, + -0x1.64c7db02c0234p-5, 0x1.dfeae7c7b80a6p-4, -0x1.edc1935a3ae58p-5, -0x1.c08c43c11b6bcp-4, + 0x1.f4e604a1e6d12p-4, 0x1.a82a04e9f9760p-6, -0x1.9777eeb15433cp-4, 0x1.360587a0c690ep-4, + 0x1.f656f04396d0dp-8, -0x1.ff0958f6a27c5p-4, 0x1.6e74486a63f70p-4, 0x1.659191b8add5dp-4, + -0x1.fe1caf25188bap-4, 0x1.5f6d001547cfep-7, 0x1.2bedaf63d4487p-4, -0x1.9ef43b2d9ecedp-4, + 0x1.d934fcde2ed84p-6, 0x1.f2252f956e5b2p-4, -0x1.c678b7cad163ep-4, -0x1.d797720f93141p-5, + 0x1.db652845e7d24p-4, -0x1.7c3a9191e73f1p-5, -0x1.4d1e2324d78fcp-5, 0x1.e426a19f37b36p-4, + -0x1.01cfc994c546fp-4, -0x1.ba5aa86b817dep-4, 0x1.f75999fd7fe99p-4, 0x1.76dd99c4d025ap-6, + -0x1.8fbcc9c24c0c8p-4, 0x1.3fed93b5ea034p-4, 0x1.2d863e4be420ap-8, -0x1.ffa73009273c2p-4, + 0x1.771e729684eecp-4, 0x1.5c77bcea2be82p-4, -0x1.fce15ef7ed53ap-4, 0x1.c378601972aecp-7, + 0x1.21a79c2fb90ffp-4, -0x1.a6308ff5ecb9dp-4, 0x1.04fb82addfce1p-5, 0x1.ef178c8061547p-4, + -0x1.cc1f0cf11d974p-4, -0x1.c124a0dd13c59p-5, 0x1.d69617602e291p-4, -0x1.9372a8cc4a6f8p-5, + -0x1.35410f91f7702p-5, 0x1.e817b7562b00dp-4, -0x1.0c9706201df61p-4, -0x1.b3e4d2e64b1bbp-4, + 0x1.f97f941827f1cp-4, 0x1.455764aa90831p-6, -0x1.87c3fea35f5eep-4, 0x1.49a44b00dc1edp-4, + 0x1.921d849e735fep-10, -0x1.fff622fd20d27p-4, 0x1.7f8ecf2ffb34dp-4, 0x1.532828b4059c4p-4, + -0x1.fb5797847dbffp-4, 0x1.139f06f2e8199p-6, 0x1.1734d561784f6p-4, -0x1.ad2bc9abbfd70p-4, + 0x1.1d343f850998fp-5, 0x1.ebbd8ad4c94fap-4, -0x1.d17e78ba2d777p-4, -0x1.aa6c82867f247p-5, + 0x1.d17e774145ffdp-4, -0x1.aa6c817b4f6ddp-5, 0x1.1d343ebc75837p-5, -0x1.ebbd893267ccdp-4, + -0x1.1734d5075d667p-4, -0x1.ad2bc9e72f20ap-4, -0x1.fb5797baa6fb8p-4, -0x1.139f069859b97p-6, + -0x1.7f8ed04d24b01p-4, 0x1.532827c89256bp-4, 0x1.921d8a05036f3p-10, 0x1.fff62314cf713p-4, + 0x1.87c3ff6c72a50p-4, 0x1.49a44c481bfd1p-4, 0x1.f97f940f774f3p-4, -0x1.455764f45ef10p-6, + 0x1.0c9705d3c58e4p-4, -0x1.b3e4d232dfba4p-4, -0x1.35410fc1ab023p-5, -0x1.e817b8c72a7b5p-4, + -0x1.d69616bd92e52p-4, -0x1.9372aa59739f8p-5, -0x1.cc1f0e5ae5b8ep-4, 0x1.c124a0d0ec13cp-5, + -0x1.04fb82ea880dap-5, 0x1.ef178b2a47b69p-4, 0x1.21a79b450802dp-4, 0x1.a630909a409a3p-4, + 0x1.fce15e950e5acp-4, 0x1.c37860771ab1fp-7, 0x1.771e744f7705bp-4, -0x1.5c77bb822def3p-4, + -0x1.2d863c6ca4494p-8, -0x1.ffa731550c4ecp-4, -0x1.8fbcc96ca2c57p-4, -0x1.3fed93aadfdb2p-4, + -0x1.f75998ce33bb8p-4, 0x1.76dd995b26a7dp-6, -0x1.01cfc948fe5fap-4, 0x1.ba5aa72eccca6p-4, + 0x1.4d1e23466aaeap-5, 0x1.e426a1269e197p-4, 0x1.db65291a50149p-4, 0x1.7c3a918a6fa0fp-5, + 0x1.c678b7faabd8ep-4, -0x1.d797733628eb4p-5, 0x1.d934fd790bb6ap-6, -0x1.f2252efad1af6p-4, + -0x1.2bedaf612922bp-4, -0x1.9ef43bc7e183ap-4, -0x1.fe1cae9d1fe30p-4, -0x1.5f6cfee1e03abp-7, + -0x1.6e74484aee571p-4, 0x1.659190f644aa8p-4, 0x1.f656f13da66d5p-8, 0x1.ff095863ba946p-4, + 0x1.9777f037a8980p-4, 0x1.3605880d027b2p-4, 0x1.f4e606c751993p-4, -0x1.a82a04f692a18p-6, + 0x1.edc193ee28974p-5, -0x1.c08c43324ddb1p-4, -0x1.64c7dcd1f1d33p-5, -0x1.dfeae7abaaa8cp-4, + -0x1.dfeae7abaaa8cp-4, -0x1.64c7dcd1f1d33p-5, -0x1.c08c43324ddb1p-4, 0x1.edc193ee28974p-5, + -0x1.a82a04f692a18p-6, 0x1.f4e606c751993p-4, 0x1.3605880d027b2p-4, 0x1.9777f037a8980p-4, + 0x1.ff095863ba946p-4, 0x1.f656f13da66d5p-8, 0x1.659190f644aa8p-4, -0x1.6e74484aee571p-4, + -0x1.5f6cfee1e03abp-7, -0x1.fe1cae9d1fe30p-4, -0x1.9ef43bc7e183ap-4, -0x1.2bedaf612922bp-4, + -0x1.f2252efad1af6p-4, 0x1.d934fd790bb6ap-6, -0x1.d797733628eb4p-5, 0x1.c678b7faabd8ep-4, + 0x1.7c3a918a6fa0fp-5, 0x1.db65291a50149p-4, 0x1.e426a1269e197p-4, 0x1.4d1e23466aaeap-5, + 0x1.ba5aa72eccca6p-4, -0x1.01cfc948fe5fap-4, 0x1.76dd995b26a7dp-6, -0x1.f75998ce33bb8p-4, + -0x1.3fed93aadfdb2p-4, -0x1.8fbcc96ca2c57p-4, -0x1.ffa731550c4ecp-4, -0x1.2d863c6ca4494p-8, + -0x1.5c77bb822def3p-4, 0x1.771e744f7705bp-4, 0x1.c37860771ab1fp-7, 0x1.fce15e950e5acp-4, + 0x1.a630909a409a3p-4, 0x1.21a79b450802dp-4, 0x1.ef178b2a47b69p-4, -0x1.04fb82ea880dap-5, + 0x1.c124a0d0ec13cp-5, -0x1.cc1f0e5ae5b8ep-4, -0x1.9372aa59739f8p-5, -0x1.d69616bd92e52p-4, + -0x1.e817b8c72a7b5p-4, -0x1.35410fc1ab023p-5, -0x1.b3e4d232dfba4p-4, 0x1.0c9705d3c58e4p-4, + -0x1.455764f45ef10p-6, 0x1.f97f940f774f3p-4, 0x1.49a44c481bfd1p-4, 0x1.87c3ff6c72a50p-4, + 0x1.fff62314cf713p-4, 0x1.921d8a05036f3p-10, 0x1.532827c89256bp-4, -0x1.7f8ed04d24b01p-4, + -0x1.139f069859b97p-6, -0x1.fb5797baa6fb8p-4, -0x1.ad2bc9e72f20ap-4, -0x1.1734d5075d667p-4, + -0x1.ebbd893267ccdp-4, 0x1.1d343ebc75837p-5, -0x1.aa6c817b4f6dep-5, 0x1.d17e774145ff0p-4, + -0x1.39c5ea10ad80cp-5, 0x1.b5e587c572c36p-5, 0x1.cb87e90c178fcp-6, -0x1.4f53b0209863ap-3, + -0x1.ce6958247df7fp-6, 0x1.78dcb4edf262bp-4, -0x1.2871ff991e9e8p-5, -0x1.0a20e7ba1fec1p-5, + 0x1.bcda72d3d1424p-7, -0x1.e5e90441a77a9p-5, -0x1.58ea1afe83fb8p-7, -0x1.0d88dc63af359p-2, + -0x1.aa321e5b53fefp-9, 0x1.7ba92a228f7b9p-12, -0x1.aff0b20339a55p-5, 0x1.ca0ab4249615ap-7, + 0x1.d2ac7bd0a278ap-5, 0x1.7bee4d923381fp-5, -0x1.2a506c13ca68cp-5, 0x1.a59dfcaa8809bp-5, + -0x1.52ffc4e5a85cap-3, -0x1.310e8fb20106dp-5, 0x1.09480356bfc01p-3, -0x1.33febbf90b70ep-4, + 0x1.22003157aec3dp-4, -0x1.e1f8190efc3eep-7, 0x1.181d86741bdbdp-4, 0x1.73dfc225d02eep-5, + 0x1.84ead4d3aa9b1p-3, 0x1.e5b1ff5b28e2fp-10, -0x1.afbe3c64f9614p-5, -0x1.f89c27ad03c26p-5, + -0x1.d227a2cf5418bp-7, 0x1.3393a75009f11p-3, -0x1.bf0c03d3aea4fp-5, -0x1.2762b79e7d399p-5, + -0x1.f8b4a3cfd41dfp-4, 0x1.c18b2153895a3p-6, -0x1.e6300edaf5006p-4, 0x1.86ae37b55cbb7p-5, + 0x1.4d9f721a4a778p-5, 0x1.92b16026d61bfp-4, -0x1.ada8ca06aee6ap-3, 0x1.2f5f062165aedp-6, + 0x1.3cf2df53ba9e0p-4, 0x1.cebef879dbef5p-7, 0x1.3656f0ab4f398p-5, -0x1.48735bed70b9bp-3, + 0x1.a99e4863c2481p-7, 0x1.e8e7191ea3edfp-6, -0x1.77ded1b5e4c0dp-3, -0x1.dcaa7ac613bfep-7, + -0x1.3e2630333c46fp-5, 0x1.79ca10df93941p-6, -0x1.4c399caf12879p-7, -0x1.6d6ffcfe46072p-3, + -0x1.16af08ab54aa1p-4, 0x1.8e25c7ffeac17p-5, -0x1.158e3af5f5a9bp-3, 0x1.4bfdda264569bp-5, + -0x1.e34c251304d94p-6, -0x1.234380c8a936fp-4, -0x1.3f19a9014a102p-7, 0x1.f349d65b94fe8p-4, + 0x1.f349d65b94fe8p-4, -0x1.3f19a9014a102p-7, -0x1.234380c8a936fp-4, -0x1.e34c251304d94p-6, + 0x1.4bfdda264569bp-5, -0x1.158e3af5f5a9bp-3, 0x1.8e25c7ffeac17p-5, -0x1.16af08ab54aa1p-4, + -0x1.6d6ffcfe46072p-3, -0x1.4c399caf12879p-7, 0x1.79ca10df93941p-6, -0x1.3e2630333c46fp-5, + -0x1.dcaa7ac613bfep-7, -0x1.77ded1b5e4c0dp-3, 0x1.e8e7191ea3edfp-6, 0x1.a99e4863c2481p-7, + -0x1.48735bed70b9bp-3, 0x1.3656f0ab4f398p-5, 0x1.cebef879dbef5p-7, 0x1.3cf2df53ba9e0p-4, + 0x1.2f5f062165aedp-6, -0x1.ada8ca06aee6ap-3, 0x1.92b16026d61bfp-4, 0x1.4d9f721a4a778p-5, + 0x1.86ae37b55cbb7p-5, -0x1.e6300edaf5006p-4, 0x1.c18b2153895a3p-6, -0x1.f8b4a3cfd41dfp-4, + -0x1.2762b79e7d399p-5, -0x1.bf0c03d3aea4fp-5, 0x1.3393a75009f11p-3, -0x1.d227a2cf5418bp-7, + -0x1.f89c27ad03c26p-5, -0x1.afbe3c64f9614p-5, 0x1.e5b1ff5b28e2fp-10, 0x1.84ead4d3aa9b1p-3, + 0x1.73dfc225d02eep-5, 0x1.181d86741bdbdp-4, -0x1.e1f8190efc3eep-7, 0x1.22003157aec3dp-4, + -0x1.33febbf90b70ep-4, 0x1.09480356bfc01p-3, -0x1.310e8fb20106dp-5, -0x1.52ffc4e5a85cap-3, + 0x1.a59dfcaa8809bp-5, -0x1.2a506c13ca68cp-5, 0x1.7bee4d923381fp-5, 0x1.d2ac7bd0a278ap-5, + 0x1.ca0ab4249615ap-7, -0x1.aff0b20339a55p-5, 0x1.7ba92a228f7b9p-12, -0x1.aa321e5b53fefp-9, + -0x1.0d88dc63af359p-2, -0x1.58ea1afe83fb8p-7, -0x1.e5e90441a77a9p-5, 0x1.bcda72d3d1424p-7, + -0x1.0a20e7ba1fec1p-5, -0x1.2871ff991e9edp-5, 0x1.78dcb4edf2631p-4, -0x1.ce6958247df7ep-6, + -0x1.4f53b02098638p-3, 0x1.cb87e90c17906p-6, 0x1.b5e587c86ecffp-5, -0x1.39c5e9aaec1c8p-5, + -0x1.a158f5a05b94fp-5, -0x1.fc9885d75ecc0p-5, 0x1.2d25a4ba2d479p-5, 0x1.370a87a1f5cd8p-5, + 0x1.0d1bbea60febdp-5, -0x1.24d5d33806aaap-5, -0x1.5648ba5a32c7ep-10, -0x1.301706c3381c3p-4, + 0x1.4017d478d2125p-3, 0x1.80589a916889bp-9, -0x1.2bd3787891d3dp-4, -0x1.8b5e551b7d834p-6, + -0x1.4369f541adec9p-4, 0x1.3e92631ca5d64p-3, 0x1.0ee93373271d2p-6, -0x1.79c22a6a94c71p-4, + -0x1.9ee40a8feec5cp-3, 0x1.36d6f90bdb1cfp-8, -0x1.5ca75cf6fac49p-5, 0x1.ce2f8f5b19174p-5, + 0x1.2db1dd6cfa6b1p-5, 0x1.c4df3f94e64eap-5, -0x1.4d5e86fdfdbd5p-5, 0x1.a100cc8a1f604p-4, + 0x1.3176b9a9321bep-4, -0x1.50fd83e9df35cp-7, -0x1.96952cab51383p-4, -0x1.37913940fa5c4p-5, + -0x1.16775c171a62bp-8, 0x1.6307ce618312fp-4, 0x1.4b311a0c5af70p-3, -0x1.7a2facb3f42b2p-5, + -0x1.5825041a41974p-3, 0x1.41ab2d3316ff6p-7, -0x1.0bc9cb1493c7fp-4, -0x1.4605f751ced7bp-7, + 0x1.2119679e7fbdbp-6, -0x1.5d3b6c740b2e5p-6, -0x1.93194d8a583f5p-3, 0x1.28cf9a5ca25fcp-8, + 0x1.badaecdc32553p-4, 0x1.e3e0e9d5c88e1p-6, 0x1.bd8308255d4b8p-8, -0x1.6a59095e58123p-5, + 0x1.e17100c32deeap-8, 0x1.1c031b336edc0p-3, -0x1.03be38d41e88ap-7, 0x1.c2074493cd3cdp-7, + 0x1.88e74731906cbp-5, 0x1.d21cc96a259c3p-5, 0x1.a4cfdbbca5fbcp-6, 0x1.477731a99312ep-3, + -0x1.c55953d828b16p-5, 0x1.072d13d364ca7p-3, -0x1.897544a932c7dp-3, -0x1.7490ecbe9db0dp-6, + -0x1.f7c9048d429f1p-5, 0x1.0d64e1c116126p-3, 0x1.34b84d0c8a008p-6, -0x1.fe109dca977e3p-3, + 0x1.e9fe30c1d0f10p-4, 0x1.4677eb0d368e6p-5, -0x1.af8cd20f987a4p-6, 0x1.b68bc4e8662fep-5, + 0x1.b68bc4e8662fep-5, -0x1.af8cd20f987a4p-6, 0x1.4677eb0d368e6p-5, 0x1.e9fe30c1d0f10p-4, + -0x1.fe109dca977e3p-3, 0x1.34b84d0c8a008p-6, 0x1.0d64e1c116126p-3, -0x1.f7c9048d429f1p-5, + -0x1.7490ecbe9db0dp-6, -0x1.897544a932c7dp-3, 0x1.072d13d364ca7p-3, -0x1.c55953d828b16p-5, + 0x1.477731a99312ep-3, 0x1.a4cfdbbca5fbcp-6, 0x1.d21cc96a259c3p-5, 0x1.88e74731906cbp-5, + 0x1.c2074493cd3cdp-7, -0x1.03be38d41e88ap-7, 0x1.1c031b336edc0p-3, 0x1.e17100c32deeap-8, + -0x1.6a59095e58123p-5, 0x1.bd8308255d4b8p-8, 0x1.e3e0e9d5c88e1p-6, 0x1.badaecdc32553p-4, + 0x1.28cf9a5ca25fcp-8, -0x1.93194d8a583f5p-3, -0x1.5d3b6c740b2e5p-6, 0x1.2119679e7fbdbp-6, + -0x1.4605f751ced7bp-7, -0x1.0bc9cb1493c7fp-4, 0x1.41ab2d3316ff6p-7, -0x1.5825041a41974p-3, + -0x1.7a2facb3f42b2p-5, 0x1.4b311a0c5af70p-3, 0x1.6307ce618312fp-4, -0x1.16775c171a62bp-8, + -0x1.37913940fa5c4p-5, -0x1.96952cab51383p-4, -0x1.50fd83e9df35cp-7, 0x1.3176b9a9321bep-4, + 0x1.a100cc8a1f604p-4, -0x1.4d5e86fdfdbd5p-5, 0x1.c4df3f94e64eap-5, 0x1.2db1dd6cfa6b1p-5, + 0x1.ce2f8f5b19174p-5, -0x1.5ca75cf6fac49p-5, 0x1.36d6f90bdb1cfp-8, -0x1.9ee40a8feec5cp-3, + -0x1.79c22a6a94c71p-4, 0x1.0ee93373271d2p-6, 0x1.3e92631ca5d64p-3, -0x1.4369f541adec9p-4, + -0x1.8b5e551b7d834p-6, -0x1.2bd3787891d3dp-4, 0x1.80589a916889bp-9, 0x1.4017d478d2125p-3, + -0x1.301706c3381bdp-4, -0x1.5648ba5a32bddp-10, -0x1.24d5d33806a9ap-5, 0x1.0d1bbea60febbp-5, + 0x1.370a87a1f5c99p-5, 0x1.2d25a4ba2d47dp-5, -0x1.fc9888782792bp-5, -0x1.a158f5bf4ae84p-5, + -0x1.c1249cf68224dp-5, -0x1.cc1f110d4c0b4p-4, 0x1.f4e600c954509p-4, 0x1.a829fb1972a81p-6, + -0x1.87c401f1d8c53p-4, 0x1.49a449c488f74p-4, -0x1.2d86609727bf2p-8, -0x1.ffa72f032c300p-4, + 0x1.9ef43e89ce507p-4, 0x1.2bedb03aea5abp-4, -0x1.ebbd8c737e5f3p-4, 0x1.1d3443791e972p-5, + 0x1.7c3a93b0d578ep-5, -0x1.db65251ce1ca2p-4, 0x1.01cfc8396bf0dp-4, 0x1.ba5aa7de9d497p-4, + -0x1.fb579766f5556p-4, -0x1.139f10771d4ebp-6, 0x1.6e74438ef7ba1p-4, -0x1.65918ed4c159bp-4, + 0x1.c37850e537c4ep-7, 0x1.fce15f56c9bb2p-4, -0x1.b3e4d3f8150a6p-4, -0x1.0c97040509938p-4, + 0x1.dfeae601a3242p-4, -0x1.64c7dbd6ff829p-5, -0x1.35410c5f15bdap-5, 0x1.e817b8ff201e4p-4, + -0x1.21a798577a73dp-4, -0x1.a6309274907dcp-4, 0x1.ff09593394ce0p-4, 0x1.f656ded36f47ep-8, + -0x1.53282cb529a43p-4, 0x1.7f8ecfa7dd9b8p-4, -0x1.76dda0d4fb8afp-6, -0x1.f7599c303049fp-4, + 0x1.c678b42743a02p-4, 0x1.d79771317a93ap-5, -0x1.d17e74bd55e55p-4, 0x1.aa6c8354412d8p-5, + 0x1.d934fb644799ep-6, -0x1.f225308bea988p-4, 0x1.3fed95f9a9bdep-4, 0x1.8fbcca5447b9dp-4, + -0x1.fff6216911d88p-4, 0x1.921d3ed2b4dd9p-10, 0x1.36058b8f359c5p-4, -0x1.9777ef4ba21d4p-4, + 0x1.04fb7f6977056p-5, 0x1.ef178a286f23cp-4, -0x1.d69618216cc34p-4, -0x1.9372a41a32c43p-5, + 0x1.c08c431ed15c4p-4, -0x1.edc193795140fp-5, -0x1.4557688c8c02ep-6, 0x1.f97f92c650dfdp-4, + -0x1.5c77bccef0122p-4, -0x1.771e77353d82cp-4, 0x1.fe1caee4dba2ap-4, -0x1.5f6d07d62c8a2p-7, + -0x1.1734d893acd66p-4, 0x1.ad2bc7afe561bp-4, -0x1.4d1e24d6755d5p-5, -0x1.e426a5062637cp-4, + 0x1.e426a5062637cp-4, 0x1.4d1e24d6755d5p-5, -0x1.ad2bc7afe561bp-4, 0x1.1734d893acd66p-4, + 0x1.5f6d07d62c8a2p-7, -0x1.fe1caee4dba2ap-4, 0x1.771e77353d82cp-4, 0x1.5c77bccef0122p-4, + -0x1.f97f92c650dfdp-4, 0x1.4557688c8c02ep-6, 0x1.edc193795140fp-5, -0x1.c08c431ed15c4p-4, + 0x1.9372a41a32c43p-5, 0x1.d69618216cc34p-4, -0x1.ef178a286f23cp-4, -0x1.04fb7f6977056p-5, + 0x1.9777ef4ba21d4p-4, -0x1.36058b8f359c5p-4, -0x1.921d3ed2b4dd9p-10, 0x1.fff6216911d88p-4, + -0x1.8fbcca5447b9dp-4, -0x1.3fed95f9a9bdep-4, 0x1.f225308bea988p-4, -0x1.d934fb644799ep-6, + -0x1.aa6c8354412d8p-5, 0x1.d17e74bd55e55p-4, -0x1.d79771317a93ap-5, -0x1.c678b42743a02p-4, + 0x1.f7599c303049fp-4, 0x1.76dda0d4fb8afp-6, -0x1.7f8ecfa7dd9b8p-4, 0x1.53282cb529a43p-4, + -0x1.f656ded36f47ep-8, -0x1.ff09593394ce0p-4, 0x1.a6309274907dcp-4, 0x1.21a798577a73dp-4, + -0x1.e817b8ff201e4p-4, 0x1.35410c5f15bdap-5, 0x1.64c7dbd6ff829p-5, -0x1.dfeae601a3242p-4, + 0x1.0c97040509938p-4, 0x1.b3e4d3f8150a6p-4, -0x1.fce15f56c9bb2p-4, -0x1.c37850e537c4ep-7, + 0x1.65918ed4c159bp-4, -0x1.6e74438ef7ba1p-4, 0x1.139f10771d4ebp-6, 0x1.fb579766f5556p-4, + -0x1.ba5aa7de9d497p-4, -0x1.01cfc8396bf0dp-4, 0x1.db65251ce1ca2p-4, -0x1.7c3a93b0d578ep-5, + -0x1.1d3443791e972p-5, 0x1.ebbd8c737e5f3p-4, -0x1.2bedb03aea5abp-4, -0x1.9ef43e89ce507p-4, + 0x1.ffa72f032c300p-4, 0x1.2d86609727bf2p-8, -0x1.49a449c488f74p-4, 0x1.87c401f1d8c53p-4, + -0x1.a829fb1972a81p-6, -0x1.f4e600c954509p-4, 0x1.cc1f110d4c092p-4, 0x1.c1249cf68224bp-5, + 0x1.cc1f0f075b9eep-4, -0x1.c1249dfd745a2p-5, 0x1.a829f9fe8300bp-6, -0x1.f4e5fedd823f4p-4, + -0x1.49a44a79802a3p-4, -0x1.87c401b6169d7p-4, -0x1.ffa72ce019988p-4, 0x1.2d8660641f5a6p-8, + -0x1.2bedb086001aap-4, 0x1.9ef43e4b9d804p-4, 0x1.1d3443aec44fcp-5, 0x1.ebbd8bdae7ff0p-4, + 0x1.db652525775d6p-4, 0x1.7c3a94b09e817p-5, 0x1.ba5aa818bfa83p-4, -0x1.01cfc7c19374cp-4, + 0x1.139f0f71ea1b1p-6, -0x1.fb5796de735e3p-4, -0x1.6591909d4b57fp-4, -0x1.6e74440799e99p-4, + -0x1.fce160a0efdd8p-4, 0x1.c3784f2c43c39p-7, -0x1.0c97043164923p-4, 0x1.b3e4d4b5090f6p-4, + 0x1.64c7dcd37f511p-5, 0x1.dfeae5f21fc2bp-4, 0x1.e817bac60244ap-4, 0x1.35410b8883b7ap-5, + 0x1.a63092b59e0f1p-4, -0x1.21a79751c2ecep-4, 0x1.f656e03050d59p-8, -0x1.ff0956903b052p-4, + -0x1.7f8ed08fdeb23p-4, -0x1.53282c6303e13p-4, -0x1.f7599cb9739a0p-4, 0x1.76dda073ff0b0p-6, + -0x1.d79770adff96fp-5, 0x1.c678b4b841b92p-4, 0x1.aa6c838b1690bp-5, 0x1.d17e72e3e517bp-4, + 0x1.f225312f47615p-4, 0x1.d934fc767b68bp-6, 0x1.8fbcc9ad09bd1p-4, -0x1.3fed963f0b662p-4, + -0x1.921d3d9a9d3eep-10, -0x1.fff622a3f1dacp-4, -0x1.9777f03b3e796p-4, -0x1.36058b622568dp-4, + -0x1.ef1789de8f5a0p-4, 0x1.04fb7fee654d1p-5, -0x1.9372a487a3ce3p-5, 0x1.d69617b0c27c0p-4, + 0x1.edc1958b1a612p-5, 0x1.c08c448518d27p-4, 0x1.f97f930911159p-4, 0x1.45576729b46bcp-6, + 0x1.771e76320e8d4p-4, -0x1.5c77bbda4564fp-4, -0x1.5f6d0845c5fe2p-7, -0x1.fe1cb12754678p-4, + -0x1.ad2bc8622b745p-4, -0x1.1734d81d68109p-4, -0x1.e426a4c1902c4p-4, 0x1.4d1e23c66c30ep-5, + -0x1.4d1e23c66c30ep-5, 0x1.e426a4c1902c4p-4, 0x1.1734d81d68109p-4, 0x1.ad2bc8622b745p-4, + 0x1.fe1cb12754678p-4, 0x1.5f6d0845c5fe2p-7, 0x1.5c77bbda4564fp-4, -0x1.771e76320e8d4p-4, + -0x1.45576729b46bcp-6, -0x1.f97f930911159p-4, -0x1.c08c448518d27p-4, -0x1.edc1958b1a612p-5, + -0x1.d69617b0c27c0p-4, 0x1.9372a487a3ce3p-5, -0x1.04fb7fee654d1p-5, 0x1.ef1789de8f5a0p-4, + 0x1.36058b622568dp-4, 0x1.9777f03b3e796p-4, 0x1.fff622a3f1dacp-4, 0x1.921d3d9a9d3eep-10, + 0x1.3fed963f0b662p-4, -0x1.8fbcc9ad09bd1p-4, -0x1.d934fc767b68bp-6, -0x1.f225312f47615p-4, + -0x1.d17e72e3e517bp-4, -0x1.aa6c838b1690bp-5, -0x1.c678b4b841b92p-4, 0x1.d79770adff96fp-5, + -0x1.76dda073ff0b0p-6, 0x1.f7599cb9739a0p-4, 0x1.53282c6303e13p-4, 0x1.7f8ed08fdeb23p-4, + 0x1.ff0956903b052p-4, -0x1.f656e03050d59p-8, 0x1.21a79751c2ecep-4, -0x1.a63092b59e0f1p-4, + -0x1.35410b8883b7ap-5, -0x1.e817bac60244ap-4, -0x1.dfeae5f21fc2bp-4, -0x1.64c7dcd37f511p-5, + -0x1.b3e4d4b5090f6p-4, 0x1.0c97043164923p-4, -0x1.c3784f2c43c39p-7, 0x1.fce160a0efdd8p-4, + 0x1.6e74440799e99p-4, 0x1.6591909d4b57fp-4, 0x1.fb5796de735e3p-4, -0x1.139f0f71ea1b1p-6, + 0x1.01cfc7c19374cp-4, -0x1.ba5aa818bfa83p-4, -0x1.7c3a94b09e817p-5, -0x1.db652525775d6p-4, + -0x1.ebbd8bdae7ff0p-4, -0x1.1d3443aec44fcp-5, -0x1.9ef43e4b9d804p-4, 0x1.2bedb086001aap-4, + -0x1.2d8660641f5a6p-8, 0x1.ffa72ce019988p-4, 0x1.87c401b6169d7p-4, 0x1.49a44a79802a3p-4, + 0x1.f4e5fedd823f4p-4, -0x1.a829f9fe8300bp-6, 0x1.c1249dfd745a3p-5, -0x1.cc1f0f075b9e8p-4, + 0x1.8d17f1d54bbadp-4, 0x1.0e9197dffeebbp-6, 0x1.db112e698e2eep-6, -0x1.a68bdfcab04c8p-3, + 0x1.b4073ae8180bcp-4, -0x1.8919283a305c6p-4, -0x1.b38a50e640663p-5, 0x1.6863595eeec5fp-8, + 0x1.b7c9a5db5480ep-4, -0x1.8c481396908e5p-4, 0x1.5b3975407f497p-5, -0x1.cc5d7ac22ceedp-4, + 0x1.99255a9e1597bp-6, -0x1.096f51242dbc5p-5, 0x1.042c5778059c0p-3, -0x1.c1e32000629c6p-4, + 0x1.aff8d15ea810ep-7, -0x1.83ba7f0fd64abp-3, 0x1.d08ece4c34bc1p-4, -0x1.18306d68618d6p-4, + 0x1.1578b9b2a6b65p-3, 0x1.a8694f5e5822ap-6, -0x1.16124afc3a8ffp-4, 0x1.3c3daec084325p-5, + -0x1.bba237815cdd0p-7, 0x1.1c8899fa09b07p-4, -0x1.4fd19f9e5b89dp-3, 0x1.4a93e9020e9fcp-5, + -0x1.10c96a8bd4a79p-3, -0x1.9d3caf1b591d0p-6, -0x1.32db4f05d59e3p-7, -0x1.61222f3f0bbadp-3, + -0x1.5ce110b60efbbp-5, -0x1.976db9821d7eap-7, 0x1.697d41fbdcc4dp-3, 0x1.cbb280de6fd7ep-6, + -0x1.285ad772a42b5p-3, -0x1.9578ee1b0d543p-3, 0x1.ac125dd5c4ffcp-6, 0x1.6f03846f74051p-3, + -0x1.9bb22403fdc55p-4, -0x1.704125bea202ap-10, 0x1.4b61da9e622bap-5, 0x1.4e3f3658a998ap-5, + -0x1.3912a6170b983p-11, 0x1.12ba55830861cp-4, -0x1.bdb4439d7c3fep-10, -0x1.b1ff6ba5ff322p-4, + 0x1.6dcc6228e90b5p-5, 0x1.8aa246754cd80p-6, 0x1.2ead0b6a26e39p-4, -0x1.e4250d3b98e46p-5, + -0x1.742d243a65deap-4, 0x1.9312f2d2b447bp-5, -0x1.16e194a824773p-4, 0x1.2ea6ee71bbe29p-8, + -0x1.0cc51f410cbcdp-4, -0x1.4990f0f3f2397p-7, -0x1.1feb2a487d837p-8, 0x1.0681358d8cfeap-4, + -0x1.47d85486f1294p-4, -0x1.06e58b0bf9804p-11, -0x1.6debf22436321p-7, -0x1.e369b1c6d54f2p-9, + 0x1.e369b1c6d54f2p-9, 0x1.6debf22436321p-7, 0x1.06e58b0bf9804p-11, 0x1.47d85486f1294p-4, + -0x1.0681358d8cfeap-4, 0x1.1feb2a487d837p-8, 0x1.4990f0f3f2397p-7, 0x1.0cc51f410cbcdp-4, + -0x1.2ea6ee71bbe29p-8, 0x1.16e194a824773p-4, -0x1.9312f2d2b447bp-5, 0x1.742d243a65deap-4, + 0x1.e4250d3b98e46p-5, -0x1.2ead0b6a26e39p-4, -0x1.8aa246754cd80p-6, -0x1.6dcc6228e90b5p-5, + 0x1.b1ff6ba5ff322p-4, 0x1.bdb4439d7c3fep-10, -0x1.12ba55830861cp-4, 0x1.3912a6170b983p-11, + -0x1.4e3f3658a998ap-5, -0x1.4b61da9e622bap-5, 0x1.704125bea202ap-10, 0x1.9bb22403fdc55p-4, + -0x1.6f03846f74051p-3, -0x1.ac125dd5c4ffcp-6, 0x1.9578ee1b0d543p-3, 0x1.285ad772a42b5p-3, + -0x1.cbb280de6fd7ep-6, -0x1.697d41fbdcc4dp-3, 0x1.976db9821d7eap-7, 0x1.5ce110b60efbbp-5, + 0x1.61222f3f0bbadp-3, 0x1.32db4f05d59e3p-7, 0x1.9d3caf1b591d0p-6, 0x1.10c96a8bd4a79p-3, + -0x1.4a93e9020e9fcp-5, 0x1.4fd19f9e5b89dp-3, -0x1.1c8899fa09b07p-4, 0x1.bba237815cdd0p-7, + -0x1.3c3daec084325p-5, 0x1.16124afc3a8ffp-4, -0x1.a8694f5e5822ap-6, -0x1.1578b9b2a6b65p-3, + 0x1.18306d68618d6p-4, -0x1.d08ece4c34bc1p-4, 0x1.83ba7f0fd64abp-3, -0x1.aff8d15ea810ep-7, + 0x1.c1e32000629c6p-4, -0x1.042c5778059c0p-3, 0x1.096f51242dbc5p-5, -0x1.99255a9e1597bp-6, + 0x1.cc5d7ac22ceedp-4, -0x1.5b3975407f497p-5, 0x1.8c481396908e5p-4, -0x1.b7c9a5db5480ep-4, + -0x1.6863595eeec60p-8, 0x1.b38a50e640667p-5, 0x1.8919283a305c6p-4, -0x1.b4073ae8180bcp-4, + 0x1.a68bdfcab04c7p-3, -0x1.db112e698e2f1p-6, -0x1.0e9197f4ee3ccp-6, -0x1.8d17f45b3192fp-4, + 0x1.22a6330f836dbp-3, -0x1.96404d8a7b506p-9, -0x1.9156fb29cf24dp-4, 0x1.79d060a2dad9bp-5, + 0x1.0593010bde9e6p-4, 0x1.3393064d56505p-6, -0x1.63062ecfae463p-7, -0x1.0952401cf1c91p-2, + 0x1.068dfcbd2f3a1p-4, 0x1.0419a891d4266p-5, -0x1.30054bec241aap-3, -0x1.7231590b8c9afp-5, + 0x1.86359b3cb4f57p-6, 0x1.911a2a80a86a1p-6, 0x1.2e424636c3f11p-4, 0x1.0dcc6db4e64a4p-4, + 0x1.8bb3143909e1cp-3, 0x1.4df45b3ab335cp-7, -0x1.637da964253e8p-4, 0x1.e5329bfb24a24p-3, + 0x1.ac613aed17f07p-7, 0x1.84339bf8b4afdp-6, 0x1.9db7c54b3f273p-4, 0x1.c5d2bddc2453bp-8, + -0x1.71a100f61614bp-5, 0x1.d363bf1c87c55p-5, 0x1.8c4510a53ef91p-7, -0x1.42a4926664aa0p-4, + -0x1.ab405aa725a8ep-4, -0x1.f5e0b1f5fa328p-6, 0x1.18150763b9262p-3, 0x1.9f188aa0f7e4ep-8, + -0x1.8a2f53660071fp-5, 0x1.30cdf9e3db802p-5, -0x1.def58de8ac43bp-5, 0x1.547cf0a19a775p-4, + -0x1.5581fa8b6d44dp-4, -0x1.00c6cfa64edc9p-4, 0x1.9a3563b7cf511p-5, -0x1.37cca12cb5923p-4, + -0x1.487298330c80cp-5, -0x1.09982480b43d3p-3, 0x1.45942747139eep-5, -0x1.586bac7aeb8b4p-5, + -0x1.1de363e36940bp-5, -0x1.6de507b3f906cp-7, -0x1.618a09a781144p-6, 0x1.10eda0122cc86p-6, + -0x1.fd089e39a54f9p-5, -0x1.b7f1e54a259ddp-4, -0x1.1326a16e23371p-3, 0x1.855cedef02e96p-6, + 0x1.0673c574874a6p-6, 0x1.1c1fec9992ffap-6, -0x1.881eea6c8921fp-8, 0x1.e5508ee012428p-4, + -0x1.5aa467ba0bd1fp-3, -0x1.7164756652416p-4, -0x1.901eb749a3dbdp-3, 0x1.4df338b778af6p-9, + -0x1.3bf4aed8fdb56p-5, -0x1.c24d4ee03b838p-4, -0x1.0cd7d03715810p-5, -0x1.4ef78cb33a456p-4, + 0x1.4ef78cb33a456p-4, 0x1.0cd7d03715810p-5, 0x1.c24d4ee03b838p-4, 0x1.3bf4aed8fdb56p-5, + -0x1.4df338b778af6p-9, 0x1.901eb749a3dbdp-3, 0x1.7164756652416p-4, 0x1.5aa467ba0bd1fp-3, + -0x1.e5508ee012428p-4, 0x1.881eea6c8921fp-8, -0x1.1c1fec9992ffap-6, -0x1.0673c574874a6p-6, + -0x1.855cedef02e96p-6, 0x1.1326a16e23371p-3, 0x1.b7f1e54a259ddp-4, 0x1.fd089e39a54f9p-5, + -0x1.10eda0122cc86p-6, 0x1.618a09a781144p-6, 0x1.6de507b3f906cp-7, 0x1.1de363e36940bp-5, + 0x1.586bac7aeb8b4p-5, -0x1.45942747139eep-5, 0x1.09982480b43d3p-3, 0x1.487298330c80cp-5, + 0x1.37cca12cb5923p-4, -0x1.9a3563b7cf511p-5, 0x1.00c6cfa64edc9p-4, 0x1.5581fa8b6d44dp-4, + -0x1.547cf0a19a775p-4, 0x1.def58de8ac43bp-5, -0x1.30cdf9e3db802p-5, 0x1.8a2f53660071fp-5, + -0x1.9f188aa0f7e4ep-8, -0x1.18150763b9262p-3, 0x1.f5e0b1f5fa328p-6, 0x1.ab405aa725a8ep-4, + 0x1.42a4926664aa0p-4, -0x1.8c4510a53ef91p-7, -0x1.d363bf1c87c55p-5, 0x1.71a100f61614bp-5, + -0x1.c5d2bddc2453bp-8, -0x1.9db7c54b3f273p-4, -0x1.84339bf8b4afdp-6, -0x1.ac613aed17f07p-7, + -0x1.e5329bfb24a24p-3, 0x1.637da964253e8p-4, -0x1.4df45b3ab335cp-7, -0x1.8bb3143909e1cp-3, + -0x1.0dcc6db4e64a4p-4, -0x1.2e424636c3f11p-4, -0x1.911a2a80a86a1p-6, -0x1.86359b3cb4f57p-6, + 0x1.7231590b8c9afp-5, 0x1.30054bec241aap-3, -0x1.0419a891d4266p-5, -0x1.068dfcbd2f3a1p-4, + 0x1.0952401cf1c90p-2, 0x1.63062ecfae451p-7, -0x1.3393064d564ccp-6, -0x1.0593010bde9e8p-4, + -0x1.79d060a2dad9cp-5, 0x1.9156fb29cf247p-4, 0x1.9640112d49528p-9, -0x1.22a632ff14504p-3, + -0x1.d797746de21e8p-5, -0x1.c678b3d15ce96p-4, 0x1.fb579766fcd7fp-4, 0x1.139f077bdbb3dp-6, + -0x1.5c77bdbb7a705p-4, 0x1.771e785b434e1p-4, -0x1.a82a04a2a9abap-6, -0x1.f4e603a03fbe5p-4, + 0x1.d69617dce34ccp-4, 0x1.9372a3bd761d7p-5, -0x1.b3e4d56a938fbp-4, 0x1.0c9705a3d77edp-4, + 0x1.f656f331f649fp-8, -0x1.ff09548a43372p-4, 0x1.8fbcc975f9ac7p-4, 0x1.3fed959c8318cp-4, + -0x1.ebbd8cb5e1ee8p-4, 0x1.1d3445282ea9bp-5, 0x1.4d1e235c89a25p-5, -0x1.e426a4e06f2c1p-4, + 0x1.2bedb1d2c07afp-4, 0x1.9ef43e3d73d06p-4, -0x1.fff621396d49ep-4, 0x1.921ccd73e0325p-10, + 0x1.21a79a8fd8b36p-4, -0x1.a6308fe96608dp-4, 0x1.64c7df69efe53p-5, 0x1.dfeae579cd1ffp-4, + -0x1.ef178ad5f8384p-4, -0x1.04fb7c5741339p-5, 0x1.87c3ffec8e04dp-4, -0x1.49a448b8bff35p-4, + 0x1.5f6cff3c5d561p-7, 0x1.fe1cb002f3f26p-4, -0x1.ba5aa939a623ep-4, -0x1.01cfc96eca975p-4, + 0x1.d17e77b8a9279p-4, -0x1.aa6c7e92ebc34p-5, -0x1.76dda50602cd0p-6, 0x1.f7599cadcf7c8p-4, + -0x1.65919361e1aecp-4, -0x1.6e74439e49e70p-4, 0x1.f97f9198b073cp-4, -0x1.455769c976fb3p-6, + -0x1.c124a41cfff20p-5, 0x1.cc1f0bc664937p-4, -0x1.edc1919a75a1ap-5, -0x1.c08c442a29895p-4, + 0x1.fce15b32aa978p-4, 0x1.c378525bca5d9p-7, -0x1.532827ee96004p-4, 0x1.7f8ecc4a663f3p-4, + -0x1.d934fa70e9f1dp-6, -0x1.f225300be43bap-4, 0x1.db65295329e5cp-4, 0x1.7c3a8f809a906p-5, + -0x1.ad2bc92bb8e45p-4, 0x1.1734d81714ff6p-4, 0x1.2d863cfa46cb1p-8, -0x1.ffa72fd92a9adp-4, + 0x1.9777f0fea0a73p-4, 0x1.36058a642ef20p-4, -0x1.e817ba166e2bep-4, 0x1.35410cf840bdbp-5, + 0x1.35410cf840bdbp-5, -0x1.e817ba166e2bep-4, 0x1.36058a642ef20p-4, 0x1.9777f0fea0a73p-4, + -0x1.ffa72fd92a9adp-4, 0x1.2d863cfa46cb1p-8, 0x1.1734d81714ff6p-4, -0x1.ad2bc92bb8e45p-4, + 0x1.7c3a8f809a906p-5, 0x1.db65295329e5cp-4, -0x1.f225300be43bap-4, -0x1.d934fa70e9f1dp-6, + 0x1.7f8ecc4a663f3p-4, -0x1.532827ee96004p-4, 0x1.c378525bca5d9p-7, 0x1.fce15b32aa978p-4, + -0x1.c08c442a29895p-4, -0x1.edc1919a75a1ap-5, 0x1.cc1f0bc664937p-4, -0x1.c124a41cfff20p-5, + -0x1.455769c976fb3p-6, 0x1.f97f9198b073cp-4, -0x1.6e74439e49e70p-4, -0x1.65919361e1aecp-4, + 0x1.f7599cadcf7c8p-4, -0x1.76dda50602cd0p-6, -0x1.aa6c7e92ebc34p-5, 0x1.d17e77b8a9279p-4, + -0x1.01cfc96eca975p-4, -0x1.ba5aa939a623ep-4, 0x1.fe1cb002f3f26p-4, 0x1.5f6cff3c5d561p-7, + -0x1.49a448b8bff35p-4, 0x1.87c3ffec8e04dp-4, -0x1.04fb7c5741339p-5, -0x1.ef178ad5f8384p-4, + 0x1.dfeae579cd1ffp-4, 0x1.64c7df69efe53p-5, -0x1.a6308fe96608dp-4, 0x1.21a79a8fd8b36p-4, + 0x1.921ccd73e0325p-10, -0x1.fff621396d49ep-4, 0x1.9ef43e3d73d06p-4, 0x1.2bedb1d2c07afp-4, + -0x1.e426a4e06f2c1p-4, 0x1.4d1e235c89a25p-5, 0x1.1d3445282ea9bp-5, -0x1.ebbd8cb5e1ee8p-4, + 0x1.3fed959c8318cp-4, 0x1.8fbcc975f9ac7p-4, -0x1.ff09548a43372p-4, 0x1.f656f331f649fp-8, + 0x1.0c9705a3d77edp-4, -0x1.b3e4d56a938fbp-4, 0x1.9372a3bd761d7p-5, 0x1.d69617dce34ccp-4, + -0x1.f4e603a03fbe5p-4, -0x1.a82a04a2a9abap-6, 0x1.771e785b434e1p-4, -0x1.5c77bdbb7a705p-4, + 0x1.139f077bdbb3dp-6, 0x1.fb579766fcd7fp-4, -0x1.c678b3d15cea1p-4, -0x1.d797746de21ebp-5, + 0x1.c678b390e1f49p-4, -0x1.d797743dd130cp-5, 0x1.139f0776a3c3dp-6, -0x1.fb579813795b5p-4, + -0x1.771e77c7fc1e4p-4, -0x1.5c77be42cfda1p-4, -0x1.f4e602fa047f7p-4, 0x1.a82a05a08a3e9p-6, + -0x1.9372a482bb58ep-5, 0x1.d6961828d3ef0p-4, 0x1.0c97062b2e602p-4, 0x1.b3e4d5f7f6250p-4, + 0x1.ff09539e84eb0p-4, 0x1.f656f685e3a5cp-8, 0x1.3fed9559e5528p-4, -0x1.8fbcca2b35b9ep-4, + -0x1.1d34454cf2e3ep-5, -0x1.ebbd8cb1d6620p-4, -0x1.e426a32fcd84bp-4, -0x1.4d1e231184196p-5, + -0x1.9ef43dc79f93bp-4, 0x1.2bedb28822107p-4, 0x1.921cd73760166p-10, 0x1.fff62159eede1p-4, + 0x1.a630903be55d4p-4, 0x1.21a799ce3ce3fp-4, 0x1.dfeae5a96262fp-4, -0x1.64c7df0acff9ep-5, + 0x1.04fb7d8a46e14p-5, -0x1.ef178d4fdf003p-4, -0x1.49a447eff4496p-4, -0x1.87c400b508886p-4, + -0x1.fe1caf9d7aae9p-4, 0x1.5f6cfd35084c6p-7, -0x1.01cfc8fe5d2c9p-4, 0x1.ba5aa924fefa3p-4, + 0x1.aa6c7fae0b0c5p-5, 0x1.d17e7964bbeecp-4, 0x1.f7599be7e979fp-4, 0x1.76dda564faa9cp-6, + 0x1.6e744404a707ep-4, -0x1.659194b45b5ecp-4, -0x1.455769b093781p-6, -0x1.f97f90a6fc9c9p-4, + -0x1.cc1f0d1dd4818p-4, -0x1.c124a63889fecp-5, -0x1.c08c4388d7c8ep-4, 0x1.edc19198655a1p-5, + -0x1.c37854835bfb6p-7, 0x1.fce15b35d457cp-4, 0x1.7f8eccde756e0p-4, 0x1.532828a81a692p-4, + 0x1.f22531aacccbap-4, -0x1.d934f758a5ddap-6, 0x1.7c3a8f3d2d30fp-5, -0x1.db65273251dd4p-4, + -0x1.1734d80d125aap-4, -0x1.ad2bc7c7e504fp-4, -0x1.ffa72ed681821p-4, -0x1.2d863a891ae06p-8, + -0x1.360589f8f4116p-4, 0x1.9777ef4f2d0cfp-4, 0x1.35410c4e8022bp-5, 0x1.e817ba74f4012p-4, + 0x1.e817ba74f4012p-4, 0x1.35410c4e8022bp-5, 0x1.9777ef4f2d0cfp-4, -0x1.360589f8f4116p-4, + -0x1.2d863a891ae06p-8, -0x1.ffa72ed681821p-4, -0x1.ad2bc7c7e504fp-4, -0x1.1734d80d125aap-4, + -0x1.db65273251dd4p-4, 0x1.7c3a8f3d2d30fp-5, -0x1.d934f758a5ddap-6, 0x1.f22531aacccbap-4, + 0x1.532828a81a692p-4, 0x1.7f8eccde756e0p-4, 0x1.fce15b35d457cp-4, -0x1.c37854835bfb6p-7, + 0x1.edc19198655a1p-5, -0x1.c08c4388d7c8ep-4, -0x1.c124a63889fecp-5, -0x1.cc1f0d1dd4818p-4, + -0x1.f97f90a6fc9c9p-4, -0x1.455769b093781p-6, -0x1.659194b45b5ecp-4, 0x1.6e744404a707ep-4, + 0x1.76dda564faa9cp-6, 0x1.f7599be7e979fp-4, 0x1.d17e7964bbeecp-4, 0x1.aa6c7fae0b0c5p-5, + 0x1.ba5aa924fefa3p-4, -0x1.01cfc8fe5d2c9p-4, 0x1.5f6cfd35084c6p-7, -0x1.fe1caf9d7aae9p-4, + -0x1.87c400b508886p-4, -0x1.49a447eff4496p-4, -0x1.ef178d4fdf003p-4, 0x1.04fb7d8a46e14p-5, + -0x1.64c7df0acff9ep-5, 0x1.dfeae5a96262fp-4, 0x1.21a799ce3ce3fp-4, 0x1.a630903be55d4p-4, + 0x1.fff62159eede1p-4, 0x1.921cd73760166p-10, 0x1.2bedb28822107p-4, -0x1.9ef43dc79f93bp-4, + -0x1.4d1e231184196p-5, -0x1.e426a32fcd84bp-4, -0x1.ebbd8cb1d6620p-4, -0x1.1d34454cf2e3ep-5, + -0x1.8fbcca2b35b9ep-4, 0x1.3fed9559e5528p-4, 0x1.f656f685e3a5cp-8, 0x1.ff09539e84eb0p-4, + 0x1.b3e4d5f7f6250p-4, 0x1.0c97062b2e602p-4, 0x1.d6961828d3ef0p-4, -0x1.9372a482bb58ep-5, + 0x1.a82a05a08a3e9p-6, -0x1.f4e602fa047f7p-4, -0x1.5c77be42cfda1p-4, -0x1.771e77c7fc1e4p-4, + -0x1.fb579813795b5p-4, 0x1.139f0776a3c3dp-6, -0x1.d797743dd130bp-5, 0x1.c678b390e1f46p-4, + -0x1.946de6758db72p-6, -0x1.83487a5a51dadp-4, -0x1.d028a050c4627p-8, 0x1.d40e9e91f3fdfp-4, + -0x1.ab81d51fc1e12p-6, -0x1.c6898d68ea1dep-5, -0x1.ba5936d6c85bfp-3, -0x1.53e86f5336c64p-8, + -0x1.00ba6ca9e9e54p-5, 0x1.a5d8a54600502p-4, 0x1.bba54764c1c81p-7, -0x1.d0088040e6648p-5, + -0x1.df4be550710bfp-6, -0x1.044ffdb05a124p-6, 0x1.8f255ad5985dfp-4, 0x1.3648fff0720d7p-7, + 0x1.0a04e626d9a0ap-6, 0x1.ce97131034d22p-4, -0x1.130e442b63022p-3, 0x1.619310f0cf705p-13, + -0x1.1fe6b123f2ac5p-3, -0x1.4fa016ca5aadep-4, -0x1.40119dd0127cep-8, -0x1.98759290becd7p-3, + -0x1.ba0f9bf55e048p-4, 0x1.127be861dc8c3p-3, 0x1.d9358568506fap-6, -0x1.42fffac0ca3cfp-6, + -0x1.4e442f949d28ap-5, 0x1.7d1349b7d7403p-4, -0x1.c361caa2613f0p-4, 0x1.b0d78b50650c4p-5, + 0x1.01af39f2bcff9p-4, 0x1.14d6cf831324cp-7, -0x1.fc10c2ef9974cp-6, -0x1.8a394cad176dbp-3, + 0x1.0684d5bc0e654p-4, -0x1.2423bd8c41cebp-4, -0x1.8e24da9358e7dp-5, -0x1.e99a53f040681p-8, + 0x1.0ccc87c47b221p-5, 0x1.5c2297af38a95p-5, 0x1.74d583ddc04fep-7, -0x1.d8b5bd13023b6p-6, + 0x1.46b4f9626e06fp-4, 0x1.5ee0cb4c7a12bp-5, -0x1.44a8885fbe3e3p-3, 0x1.94f64cc06a0f5p-5, + 0x1.5b1ee57d4b789p-5, 0x1.039cd05975d82p-2, -0x1.475a565ccaaddp-5, -0x1.6a8c9e0b13b61p-5, + -0x1.522215267fde0p-3, -0x1.a2be85ca915b5p-6, 0x1.00f1ecba70732p-4, -0x1.17c0a95f3aec6p-3, + -0x1.3a9336ce6a537p-6, 0x1.163fb4439d0fcp-7, -0x1.5d03c3e086277p-4, -0x1.9c03a6a90fff0p-9, + -0x1.d7690f44a584ep-7, -0x1.6ff4cfb1756ecp-5, 0x1.3b085d983c719p-5, -0x1.367f8455f5c63p-3, + -0x1.367f8455f5c63p-3, 0x1.3b085d983c719p-5, -0x1.6ff4cfb1756ecp-5, -0x1.d7690f44a584ep-7, + -0x1.9c03a6a90fff0p-9, -0x1.5d03c3e086277p-4, 0x1.163fb4439d0fcp-7, -0x1.3a9336ce6a537p-6, + -0x1.17c0a95f3aec6p-3, 0x1.00f1ecba70732p-4, -0x1.a2be85ca915b5p-6, -0x1.522215267fde0p-3, + -0x1.6a8c9e0b13b61p-5, -0x1.475a565ccaaddp-5, 0x1.039cd05975d82p-2, 0x1.5b1ee57d4b789p-5, + 0x1.94f64cc06a0f5p-5, -0x1.44a8885fbe3e3p-3, 0x1.5ee0cb4c7a12bp-5, 0x1.46b4f9626e06fp-4, + -0x1.d8b5bd13023b6p-6, 0x1.74d583ddc04fep-7, 0x1.5c2297af38a95p-5, 0x1.0ccc87c47b221p-5, + -0x1.e99a53f040681p-8, -0x1.8e24da9358e7dp-5, -0x1.2423bd8c41cebp-4, 0x1.0684d5bc0e654p-4, + -0x1.8a394cad176dbp-3, -0x1.fc10c2ef9974cp-6, 0x1.14d6cf831324cp-7, 0x1.01af39f2bcff9p-4, + 0x1.b0d78b50650c4p-5, -0x1.c361caa2613f0p-4, 0x1.7d1349b7d7403p-4, -0x1.4e442f949d28ap-5, + -0x1.42fffac0ca3cfp-6, 0x1.d9358568506fap-6, 0x1.127be861dc8c3p-3, -0x1.ba0f9bf55e048p-4, + -0x1.98759290becd7p-3, -0x1.40119dd0127cep-8, -0x1.4fa016ca5aadep-4, -0x1.1fe6b123f2ac5p-3, + 0x1.619310f0cf705p-13, -0x1.130e442b63022p-3, 0x1.ce97131034d22p-4, 0x1.0a04e626d9a0ap-6, + 0x1.3648fff0720d7p-7, 0x1.8f255ad5985dfp-4, -0x1.044ffdb05a124p-6, -0x1.df4be550710bfp-6, + -0x1.d0088040e6648p-5, 0x1.bba54764c1c81p-7, 0x1.a5d8a54600502p-4, -0x1.00ba6ca9e9e54p-5, + -0x1.53e86f5336c65p-8, -0x1.ba5936d6c85c2p-3, -0x1.c6898d68ea1e8p-5, -0x1.ab81d51fc1decp-6, + 0x1.d40e9e91f3fdbp-4, -0x1.d028a050c45e1p-8, -0x1.83487a4c3a202p-4, -0x1.946ddee19f89cp-6, + -0x1.d9659f9708ea0p-6, -0x1.824a4682389d3p-3, 0x1.fe2aa4980733dp-9, -0x1.3524c7277a5b0p-5, + -0x1.06169ce1adbdep-4, -0x1.a21de18b50adcp-4, 0x1.3470a6f46b483p-7, 0x1.bbfea5a30d0aap-4, + -0x1.de574b45c5b1bp-8, 0x1.ff3b6c1c2cd7dp-6, -0x1.91909e3ca5fecp-4, 0x1.3e48f5b328ed5p-3, + 0x1.0790d7d684accp-7, 0x1.597aa26177473p-3, 0x1.768318fb245c6p-5, -0x1.30f88d1425450p-5, + -0x1.67e8e2e35c21fp-4, 0x1.db65ee1a9ec59p-6, 0x1.72753689e9ee8p-9, 0x1.2629e28b96e53p-3, + -0x1.b2061ff932c52p-6, -0x1.18ff94468c7acp-6, 0x1.63e9bf7cd2e4bp-3, 0x1.894404df34c17p-6, + 0x1.ccfc6b8e4ec42p-6, -0x1.d98768c56ae71p-5, -0x1.9712357fd99d9p-5, 0x1.b110ba966b042p-3, + -0x1.4423569c37ef1p-3, -0x1.8e3619d6bb2d6p-5, 0x1.b127b58e53387p-6, 0x1.2c78603d4df02p-5, + -0x1.4d30072a2ccddp-6, -0x1.418ff1d510340p-4, 0x1.e29ce1663e805p-3, 0x1.58da95f2a03e2p-8, + -0x1.05d3ac4657d37p-5, -0x1.47a4c13b2ff71p-8, 0x1.b28ef7f5ecc81p-7, -0x1.67cf8b5f4e7b4p-5, + -0x1.5d7286b99b399p-5, 0x1.e0f08082339fcp-7, 0x1.ac35a19013467p-3, 0x1.701023a55a2f4p-8, + 0x1.b4d5025095444p-5, 0x1.5331ad71cc714p-4, -0x1.5574cb9a27d47p-4, -0x1.bebe17be4e6f2p-4, + 0x1.abee36819459bp-4, -0x1.de14498527ce4p-6, 0x1.09e65d6bf1791p-6, 0x1.5fe0617c4f6f8p-5, + 0x1.1e3eabd67df9dp-6, -0x1.01e4dfcd1b651p-4, -0x1.fbf3d9b4bd674p-5, -0x1.9b492c5648831p-7, + 0x1.1aa278ac057c2p-3, 0x1.5ab80d308a836p-5, 0x1.0c7bb90322bdbp-7, 0x1.0796a7fd9612ap-5, + -0x1.0119d95eb7e1fp-3, -0x1.931b5996573d0p-8, 0x1.55326684949c4p-3, 0x1.88828060894a2p-10, + 0x1.88828060894a2p-10, 0x1.55326684949c4p-3, -0x1.931b5996573d0p-8, -0x1.0119d95eb7e1fp-3, + 0x1.0796a7fd9612ap-5, 0x1.0c7bb90322bdbp-7, 0x1.5ab80d308a836p-5, 0x1.1aa278ac057c2p-3, + -0x1.9b492c5648831p-7, -0x1.fbf3d9b4bd674p-5, -0x1.01e4dfcd1b651p-4, 0x1.1e3eabd67df9dp-6, + 0x1.5fe0617c4f6f8p-5, 0x1.09e65d6bf1791p-6, -0x1.de14498527ce4p-6, 0x1.abee36819459bp-4, + -0x1.bebe17be4e6f2p-4, -0x1.5574cb9a27d47p-4, 0x1.5331ad71cc714p-4, 0x1.b4d5025095444p-5, + 0x1.701023a55a2f4p-8, 0x1.ac35a19013467p-3, 0x1.e0f08082339fcp-7, -0x1.5d7286b99b399p-5, + -0x1.67cf8b5f4e7b4p-5, 0x1.b28ef7f5ecc81p-7, -0x1.47a4c13b2ff71p-8, -0x1.05d3ac4657d37p-5, + 0x1.58da95f2a03e2p-8, 0x1.e29ce1663e805p-3, -0x1.418ff1d510340p-4, -0x1.4d30072a2ccddp-6, + 0x1.2c78603d4df02p-5, 0x1.b127b58e53387p-6, -0x1.8e3619d6bb2d6p-5, -0x1.4423569c37ef1p-3, + 0x1.b110ba966b042p-3, -0x1.9712357fd99d9p-5, -0x1.d98768c56ae71p-5, 0x1.ccfc6b8e4ec42p-6, + 0x1.894404df34c17p-6, 0x1.63e9bf7cd2e4bp-3, -0x1.18ff94468c7acp-6, -0x1.b2061ff932c52p-6, + 0x1.2629e28b96e53p-3, 0x1.72753689e9ee8p-9, 0x1.db65ee1a9ec59p-6, -0x1.67e8e2e35c21fp-4, + -0x1.30f88d1425450p-5, 0x1.768318fb245c6p-5, 0x1.597aa26177473p-3, 0x1.0790d7d684accp-7, + 0x1.3e48f5b328ed5p-3, -0x1.91909e3ca5fecp-4, 0x1.ff3b6c1c2cd7dp-6, -0x1.de574b45c5b1bp-8, + 0x1.bbfea5a30d0a6p-4, 0x1.3470a6f46b483p-7, -0x1.a21de18b50ae1p-4, -0x1.06169ce1adbdep-4, + -0x1.3524c7277a5b9p-5, 0x1.fe2aa4980721bp-9, -0x1.824a451451425p-3, -0x1.d9659fe8aeaf0p-6, + -0x1.edc195ed02ed7p-5, -0x1.c08c43b19eb0cp-4, 0x1.ff09534b6bee0p-4, 0x1.f656de6de9210p-8, + -0x1.2bedb1c51f7ecp-4, 0x1.9ef43d572afbdp-4, -0x1.7c3a94fac97aap-5, -0x1.db6527c6f6542p-4, + 0x1.f7599ac76af21p-4, 0x1.76dda0d6bb7a4p-6, -0x1.5c77bc7f5c00ap-4, 0x1.771e77840ba6bp-4, + -0x1.04fb8045079e1p-5, -0x1.ef178af568d1dp-4, 0x1.e817bccc57db2p-4, 0x1.35410b4213c93p-5, + -0x1.87c4030fdd596p-4, 0x1.49a449fd6778ep-4, -0x1.139f105d52217p-6, -0x1.fb57962ec0802p-4, + 0x1.d17e75084c77dp-4, 0x1.aa6c8447b320ap-5, -0x1.ad2bcad47e733p-4, 0x1.1734d5c29be62p-4, + -0x1.921d382bba58bp-10, -0x1.fff62283844b0p-4, 0x1.b3e4d1d7b02c9p-4, 0x1.0c9703bb6e1acp-4, + -0x1.cc1f0e72fc802p-4, 0x1.c1249cb4be4aap-5, 0x1.c378579f27891p-7, -0x1.fce161a826752p-4, + 0x1.8fbccc9279bd6p-4, 0x1.3fed9672b225cp-4, -0x1.e426a3688842fp-4, 0x1.4d1e2556893a3p-5, + 0x1.d93504115d7c9p-6, -0x1.f2252f04d6105p-4, 0x1.6591913ae2dd2p-4, 0x1.6e744383aee7bp-4, + -0x1.f4e604ddf3392p-4, 0x1.a82a0141a2414p-6, 0x1.64c7dd5fadf09p-5, -0x1.dfeae4f09bbeep-4, + 0x1.36058c130d9d6p-4, 0x1.9777ef0a4c03dp-4, -0x1.fe1caef872eb1p-4, 0x1.5f6d0912f3779p-7, + 0x1.d797761c6488fp-5, -0x1.c678b2f86f550p-4, 0x1.01cfc77824a45p-4, 0x1.ba5aa37915bc7p-4, + -0x1.ffa7303958920p-4, -0x1.2d865142d3ea7p-8, 0x1.21a7999220447p-4, -0x1.a63093139300ap-4, + 0x1.9372a6995e28bp-5, 0x1.d6961569c58acp-4, -0x1.f97f9361e9037p-4, -0x1.45576891339c9p-6, + 0x1.53282a184b2ccp-4, -0x1.7f8ecd91605efp-4, 0x1.1d3442895d177p-5, 0x1.ebbd8cab10af1p-4, + -0x1.ebbd8cab10af1p-4, -0x1.1d3442895d177p-5, 0x1.7f8ecd91605efp-4, -0x1.53282a184b2ccp-4, + 0x1.45576891339c9p-6, 0x1.f97f9361e9037p-4, -0x1.d6961569c58acp-4, -0x1.9372a6995e28bp-5, + 0x1.a63093139300ap-4, -0x1.21a7999220447p-4, 0x1.2d865142d3ea7p-8, 0x1.ffa7303958920p-4, + -0x1.ba5aa37915bc7p-4, -0x1.01cfc77824a45p-4, 0x1.c678b2f86f550p-4, -0x1.d797761c6488fp-5, + -0x1.5f6d0912f3779p-7, 0x1.fe1caef872eb1p-4, -0x1.9777ef0a4c03dp-4, -0x1.36058c130d9d6p-4, + 0x1.dfeae4f09bbeep-4, -0x1.64c7dd5fadf09p-5, -0x1.a82a0141a2414p-6, 0x1.f4e604ddf3392p-4, + -0x1.6e744383aee7bp-4, -0x1.6591913ae2dd2p-4, 0x1.f2252f04d6105p-4, -0x1.d93504115d7c9p-6, + -0x1.4d1e2556893a3p-5, 0x1.e426a3688842fp-4, -0x1.3fed9672b225cp-4, -0x1.8fbccc9279bd6p-4, + 0x1.fce161a826752p-4, -0x1.c378579f27891p-7, -0x1.c1249cb4be4aap-5, 0x1.cc1f0e72fc802p-4, + -0x1.0c9703bb6e1acp-4, -0x1.b3e4d1d7b02c9p-4, 0x1.fff62283844b0p-4, 0x1.921d382bba58bp-10, + -0x1.1734d5c29be62p-4, 0x1.ad2bcad47e733p-4, -0x1.aa6c8447b320ap-5, -0x1.d17e75084c77dp-4, + 0x1.fb57962ec0802p-4, 0x1.139f105d52217p-6, -0x1.49a449fd6778ep-4, 0x1.87c4030fdd596p-4, + -0x1.35410b4213c93p-5, -0x1.e817bccc57db2p-4, 0x1.ef178af568d1dp-4, 0x1.04fb8045079e1p-5, + -0x1.771e77840ba6bp-4, 0x1.5c77bc7f5c00ap-4, -0x1.76dda0d6bb7a4p-6, -0x1.f7599ac76af21p-4, + 0x1.db6527c6f6542p-4, 0x1.7c3a94fac97aap-5, -0x1.9ef43d572afbdp-4, 0x1.2bedb1c51f7ecp-4, + -0x1.f656de6de9210p-8, -0x1.ff09534b6bee0p-4, 0x1.c08c43b19eb1dp-4, 0x1.edc195ed02edcp-5, + 0x1.c08c43eec1c01p-4, -0x1.edc194b85c3c0p-5, 0x1.f656dcea03fd4p-8, -0x1.ff09548d7b229p-4, + -0x1.9ef43cd699c24p-4, -0x1.2bedb2112e0cfp-4, -0x1.db6528d11ae62p-4, 0x1.7c3a969fff3a6p-5, + -0x1.76dda123c242fp-6, 0x1.f7599ca08d08ap-4, 0x1.771e77dff3b7ap-4, 0x1.5c77bb449a5b0p-4, + 0x1.ef178b2501a8fp-4, -0x1.04fb7fd091194p-5, 0x1.35410be164340p-5, -0x1.e817bcf7bb131p-4, + -0x1.49a4494712751p-4, -0x1.87c4028259916p-4, -0x1.fb579507c4a16p-4, 0x1.139f1102e81b5p-6, + -0x1.aa6c83c201ac9p-5, 0x1.d17e7666bcd31p-4, 0x1.1734d534a8078p-4, 0x1.ad2bca035b90ap-4, + 0x1.fff62288bbb06p-4, -0x1.921d32ab0d4d0p-10, 0x1.0c9704612b6c3p-4, -0x1.b3e4d22ad46a1p-4, + -0x1.c12499cbc8ab1p-5, -0x1.cc1f0cdbfa179p-4, -0x1.fce163388fc3ep-4, -0x1.c37855f596dffp-7, + -0x1.3fed95900cd61p-4, 0x1.8fbccb9d26d42p-4, 0x1.4d1e249f56abep-5, 0x1.e426a355f720ep-4, + 0x1.f2252e63db560p-4, 0x1.d93503be8d33cp-6, 0x1.6e7443b21c880p-4, -0x1.6591917b62202p-4, + -0x1.a82a00fc0aa85p-6, -0x1.f4e602493d794p-4, -0x1.dfeae4f84fbbcp-4, -0x1.64c7dd830ed64p-5, + -0x1.9777ef9920dacp-4, 0x1.36058ae5af739p-4, 0x1.5f6d098acf856p-7, 0x1.fe1cafac0e313p-4, + 0x1.c678b4fcf9264p-4, 0x1.d797773f65eaep-5, 0x1.ba5aa4c55955fp-4, -0x1.01cfc78fda7cep-4, + 0x1.2d86526f42fa6p-8, -0x1.ffa72fed75ce7p-4, -0x1.a63091ae9e94cp-4, -0x1.21a79a5838517p-4, + -0x1.d696141fc4a35p-4, 0x1.9372a71245206p-5, -0x1.455767aea9444p-6, 0x1.f97f93a4f2447p-4, + 0x1.7f8ece297ff57p-4, 0x1.53282996adeccp-4, 0x1.ebbd8cf14b24bp-4, -0x1.1d3442ee1385fp-5, + 0x1.1d3442ee1385fp-5, -0x1.ebbd8cf14b24bp-4, -0x1.53282996adeccp-4, -0x1.7f8ece297ff57p-4, + -0x1.f97f93a4f2447p-4, 0x1.455767aea9444p-6, -0x1.9372a71245206p-5, 0x1.d696141fc4a35p-4, + 0x1.21a79a5838517p-4, 0x1.a63091ae9e94cp-4, 0x1.ffa72fed75ce7p-4, -0x1.2d86526f42fa6p-8, + 0x1.01cfc78fda7cep-4, -0x1.ba5aa4c55955fp-4, -0x1.d797773f65eaep-5, -0x1.c678b4fcf9264p-4, + -0x1.fe1cafac0e313p-4, -0x1.5f6d098acf856p-7, -0x1.36058ae5af739p-4, 0x1.9777ef9920dacp-4, + 0x1.64c7dd830ed64p-5, 0x1.dfeae4f84fbbcp-4, 0x1.f4e602493d794p-4, 0x1.a82a00fc0aa85p-6, + 0x1.6591917b62202p-4, -0x1.6e7443b21c880p-4, -0x1.d93503be8d33cp-6, -0x1.f2252e63db560p-4, + -0x1.e426a355f720ep-4, -0x1.4d1e249f56abep-5, -0x1.8fbccb9d26d42p-4, 0x1.3fed95900cd61p-4, + 0x1.c37855f596dffp-7, 0x1.fce163388fc3ep-4, 0x1.cc1f0cdbfa179p-4, 0x1.c12499cbc8ab1p-5, + 0x1.b3e4d22ad46a1p-4, -0x1.0c9704612b6c3p-4, 0x1.921d32ab0d4d0p-10, -0x1.fff62288bbb06p-4, + -0x1.ad2bca035b90ap-4, -0x1.1734d534a8078p-4, -0x1.d17e7666bcd31p-4, 0x1.aa6c83c201ac9p-5, + -0x1.139f1102e81b5p-6, 0x1.fb579507c4a16p-4, 0x1.87c4028259916p-4, 0x1.49a4494712751p-4, + 0x1.e817bcf7bb131p-4, -0x1.35410be164340p-5, 0x1.04fb7fd091194p-5, -0x1.ef178b2501a8fp-4, + -0x1.5c77bb449a5b0p-4, -0x1.771e77dff3b7ap-4, -0x1.f7599ca08d08ap-4, 0x1.76dda123c242fp-6, + -0x1.7c3a969fff3a6p-5, 0x1.db6528d11ae62p-4, 0x1.2bedb2112e0cfp-4, 0x1.9ef43cd699c24p-4, + 0x1.ff09548d7b229p-4, -0x1.f656dcea03fd4p-8, 0x1.edc194b85c3c1p-5, -0x1.c08c43eec1c0dp-4, + 0x1.8a083e313fc32p-8, -0x1.4a1f2b74d4f40p-4, 0x1.30d4e699ed5e9p-6, 0x1.7263736f518f0p-4, + -0x1.076c46ec37069p-4, 0x1.68de66b11495bp-5, 0x1.bf02da73d34f4p-3, -0x1.36041f1050fcfp-8, + 0x1.2b9cbad99c996p-8, 0x1.a9a59c5dd962ap-4, 0x1.571392c928ed2p-7, 0x1.2f2b680c8a3edp-5, + -0x1.116868e18dbf6p-2, 0x1.9ac90d3dad012p-9, 0x1.bf30096c18018p-6, 0x1.805e04619515ep-5, + -0x1.e03fc4ecbb789p-4, 0x1.1543302d4a7b6p-4, -0x1.c06c53d7e351fp-4, -0x1.04b0ce2682e3bp-5, + -0x1.18b6e2f1f277ap-4, -0x1.38dcf9aac0128p-6, 0x1.923674c0e83f7p-6, -0x1.298ab2aaa90b2p-3, + -0x1.a5d175c7bb966p-4, -0x1.47ba32d429429p-7, -0x1.cf23bb4fd0509p-4, -0x1.cd6df70e1306ap-5, + -0x1.f5d8bf2a20d5bp-4, -0x1.d7eadca46f482p-7, 0x1.14690bf2750e4p-4, 0x1.2275237cc1df8p-8, + -0x1.0355d63983667p-7, 0x1.e89513a2d2e84p-6, -0x1.4224f47525017p-5, -0x1.5f05b8aae5cb2p-4, + 0x1.4105a85dd52bep-4, 0x1.0aa8bc2ce5e66p-5, 0x1.366fbd2ebb547p-10, -0x1.08f27a3835c31p-4, + -0x1.f63cddfb38a89p-7, -0x1.88918f6a2710bp-4, 0x1.99603530ad8b6p-5, -0x1.03de710075c28p-5, + -0x1.0ca7a2a0b1660p-3, 0x1.4009230c39377p-4, -0x1.96ff96f04f872p-8, 0x1.fd2155bbc9b34p-6, + -0x1.d4fe43af572ebp-4, -0x1.25731de71aab8p-3, 0x1.357002853de4ep-7, -0x1.dfb75bb72a664p-4, + 0x1.6de2e7a7fd6acp-13, -0x1.278223233cf0fp-3, -0x1.4fb7da1f1b412p-3, -0x1.51d45ef4af471p-6, + -0x1.6a2dd707376bep-4, -0x1.06f5405d53ee1p-8, 0x1.31758f6c0a734p-10, 0x1.e022059758c08p-5, + 0x1.13b39a7387527p-5, 0x1.702ba1fc87ccep-4, -0x1.0532b5b70fe95p-2, 0x1.772ad1ff3b27ep-6, + -0x1.772ad1ff3b27ep-6, 0x1.0532b5b70fe95p-2, -0x1.702ba1fc87ccep-4, -0x1.13b39a7387527p-5, + -0x1.e022059758c08p-5, -0x1.31758f6c0a734p-10, 0x1.06f5405d53ee1p-8, 0x1.6a2dd707376bep-4, + 0x1.51d45ef4af471p-6, 0x1.4fb7da1f1b412p-3, 0x1.278223233cf0fp-3, -0x1.6de2e7a7fd6acp-13, + 0x1.dfb75bb72a664p-4, -0x1.357002853de4ep-7, 0x1.25731de71aab8p-3, 0x1.d4fe43af572ebp-4, + -0x1.fd2155bbc9b34p-6, 0x1.96ff96f04f872p-8, -0x1.4009230c39377p-4, 0x1.0ca7a2a0b1660p-3, + 0x1.03de710075c28p-5, -0x1.99603530ad8b6p-5, 0x1.88918f6a2710bp-4, 0x1.f63cddfb38a89p-7, + 0x1.08f27a3835c31p-4, -0x1.366fbd2ebb547p-10, -0x1.0aa8bc2ce5e66p-5, -0x1.4105a85dd52bep-4, + 0x1.5f05b8aae5cb2p-4, 0x1.4224f47525017p-5, -0x1.e89513a2d2e84p-6, 0x1.0355d63983667p-7, + -0x1.2275237cc1df8p-8, -0x1.14690bf2750e4p-4, 0x1.d7eadca46f482p-7, 0x1.f5d8bf2a20d5bp-4, + 0x1.cd6df70e1306ap-5, 0x1.cf23bb4fd0509p-4, 0x1.47ba32d429429p-7, 0x1.a5d175c7bb966p-4, + 0x1.298ab2aaa90b2p-3, -0x1.923674c0e83f7p-6, 0x1.38dcf9aac0128p-6, 0x1.18b6e2f1f277ap-4, + 0x1.04b0ce2682e3bp-5, 0x1.c06c53d7e351fp-4, -0x1.1543302d4a7b6p-4, 0x1.e03fc4ecbb789p-4, + -0x1.805e04619515ep-5, -0x1.bf30096c18018p-6, -0x1.9ac90d3dad012p-9, 0x1.116868e18dbf6p-2, + -0x1.2f2b680c8a3edp-5, -0x1.571392c928ed2p-7, -0x1.a9a59c5dd962ap-4, -0x1.2b9cbad99c996p-8, + 0x1.36041f1050fcfp-8, -0x1.bf02da73d34f4p-3, -0x1.68de66b11495bp-5, 0x1.076c46ec37077p-4, + -0x1.7263736f518f1p-4, -0x1.30d4e699ed5e1p-6, 0x1.4a1f2b752af1dp-4, -0x1.8a0850741d38dp-8, + -0x1.2ba23eba90b2fp-8, 0x1.6ee0572af6376p-4, -0x1.8e997d21f7ff9p-4, -0x1.dfec4099156e3p-7, + 0x1.8441db1f64c8bp-6, -0x1.681e60fdaec7dp-4, 0x1.ae6504f792a67p-5, 0x1.2eb5f7e1b41dcp-3, + -0x1.24dda13d8f263p-3, 0x1.933f789939e6fp-6, -0x1.fc80aa7de2171p-4, -0x1.229ba1f3ba8b7p-4, + 0x1.2c00565e2ae5ap-6, 0x1.8cc0cd90a5fe7p-5, -0x1.1f5fc5e5caa1bp-8, -0x1.0eadd5a22e558p-4, + -0x1.68a479cad98e0p-4, 0x1.0f11110f27b33p-4, 0x1.95c3a6035257bp-8, 0x1.e873730a0221ep-7, + -0x1.a47cc6d217d9dp-3, 0x1.05a9cfc728a71p-5, -0x1.78c28e16c8566p-3, -0x1.6a9cc95d0e701p-5, + 0x1.0346f798cef4cp-6, 0x1.ce4f185ea6e22p-10, -0x1.f018aefee9053p-6, -0x1.c223510f1d9d4p-6, + -0x1.4ce5ca5fba7d8p-3, 0x1.f650bf91ac0f2p-4, -0x1.1c1700fb7aa38p-8, 0x1.fe5f841af1670p-5, + 0x1.3a39368804e7cp-3, 0x1.37a627ebaaab8p-4, 0x1.9c89b28d17540p-6, 0x1.dd92877c3a7c8p-5, + -0x1.6039920832a5ep-5, 0x1.4f7941d259c08p-3, -0x1.3647282b1a7eap-5, -0x1.ca5e9b38ebc5bp-5, + -0x1.fd5aac5f78c07p-3, 0x1.964b085582021p-8, -0x1.50da806c73f82p-6, -0x1.14d60ccad0946p-7, + 0x1.9351f8e2e63f2p-4, -0x1.6a369b712d900p-4, 0x1.6952e6155a1cep-5, 0x1.d237177dad566p-10, + 0x1.4e5a42c48f751p-4, 0x1.d8bf13fe70827p-5, -0x1.b0c146b7c9b14p-6, 0x1.319afbacef230p-7, + -0x1.4c3cfc2ef0ccbp-3, -0x1.80c2063096334p-7, -0x1.10451002cd305p-5, -0x1.8e2ac9fca7d4fp-3, + -0x1.c7804c143d692p-7, -0x1.578a69a0b9bcdp-4, 0x1.605f47f6aa034p-5, -0x1.d972631464d27p-6, + -0x1.35fec7e235390p-5, -0x1.a9a25e810c9c6p-5, 0x1.03e26a0b0a3dcp-5, 0x1.333326591eeaap-3, + -0x1.333326591eeaap-3, -0x1.03e26a0b0a3dcp-5, 0x1.a9a25e810c9c6p-5, 0x1.35fec7e235390p-5, + 0x1.d972631464d27p-6, -0x1.605f47f6aa034p-5, 0x1.578a69a0b9bcdp-4, 0x1.c7804c143d692p-7, + 0x1.8e2ac9fca7d4fp-3, 0x1.10451002cd305p-5, 0x1.80c2063096334p-7, 0x1.4c3cfc2ef0ccbp-3, + -0x1.319afbacef230p-7, 0x1.b0c146b7c9b14p-6, -0x1.d8bf13fe70827p-5, -0x1.4e5a42c48f751p-4, + -0x1.d237177dad566p-10, -0x1.6952e6155a1cep-5, 0x1.6a369b712d900p-4, -0x1.9351f8e2e63f2p-4, + 0x1.14d60ccad0946p-7, 0x1.50da806c73f82p-6, -0x1.964b085582021p-8, 0x1.fd5aac5f78c07p-3, + 0x1.ca5e9b38ebc5bp-5, 0x1.3647282b1a7eap-5, -0x1.4f7941d259c08p-3, 0x1.6039920832a5ep-5, + -0x1.dd92877c3a7c8p-5, -0x1.9c89b28d17540p-6, -0x1.37a627ebaaab8p-4, -0x1.3a39368804e7cp-3, + -0x1.fe5f841af1670p-5, 0x1.1c1700fb7aa38p-8, -0x1.f650bf91ac0f2p-4, 0x1.4ce5ca5fba7d8p-3, + 0x1.c223510f1d9d4p-6, 0x1.f018aefee9053p-6, -0x1.ce4f185ea6e22p-10, -0x1.0346f798cef4cp-6, + 0x1.6a9cc95d0e701p-5, 0x1.78c28e16c8566p-3, -0x1.05a9cfc728a71p-5, 0x1.a47cc6d217d9dp-3, + -0x1.e873730a0221ep-7, -0x1.95c3a6035257bp-8, -0x1.0f11110f27b33p-4, 0x1.68a479cad98e0p-4, + 0x1.0eadd5a22e558p-4, 0x1.1f5fc5e5caa1bp-8, -0x1.8cc0cd90a5fe7p-5, -0x1.2c00565e2ae5ap-6, + 0x1.229ba1f3ba8b7p-4, 0x1.fc80aa7de2171p-4, -0x1.933f789939e6fp-6, 0x1.24dda13d8f263p-3, + -0x1.2eb5f7e1b41ddp-3, -0x1.ae6504f792a68p-5, 0x1.681e60fdaec7ep-4, -0x1.8441db1f64c88p-6, + 0x1.dfec4099156a5p-7, 0x1.8e997d21f7ff4p-4, -0x1.6ee056d9d375dp-4, 0x1.2ba23e9ea07b9p-8, + -0x1.01cfc8c4ad639p-4, -0x1.ba5aa55db7b66p-4, 0x1.fff62149a490ap-4, -0x1.921d39dbdf19fp-10, + -0x1.edc19543247a4p-5, 0x1.c08c428be0da9p-4, -0x1.0c9703a5823bfp-4, -0x1.b3e4d5310ddb1p-4, + 0x1.ffa72eec4d011p-4, -0x1.2d86611f9143ap-8, -0x1.d797777bf643cp-5, 0x1.c678b59131459p-4, + -0x1.1734d699fff2ep-4, -0x1.ad2bcb2659cf3p-4, 0x1.ff09597fc09bap-4, -0x1.f656aee2b8d3bp-8, + -0x1.c1249d6ef82cap-5, 0x1.cc1f0f8733f0dp-4, -0x1.21a79a9e06d62p-4, -0x1.a63092d074b6ap-4, + 0x1.fe1cb04cb6cf0p-4, -0x1.5f6cf8587ce7dp-7, -0x1.aa6c808ce5236p-5, 0x1.d17e753e803b7p-4, + -0x1.2bedb2af502a2p-4, -0x1.9ef43c210211fp-4, 0x1.fce1611844fddp-4, -0x1.c37858af3e913p-7, + -0x1.9372a7145deeap-5, 0x1.d69618cc82131p-4, -0x1.36058ad65f12fp-4, -0x1.9777eeb45b481p-4, + 0x1.fb5799aeed97ap-4, -0x1.139f0d0e6e21fp-6, -0x1.7c3a94b3375a8p-5, 0x1.db6526b9aa422p-4, + -0x1.3fed9412c7206p-4, -0x1.8fbccc48f5ca2p-4, 0x1.f97f922a97b9fp-4, -0x1.45575f91ab2f6p-6, + -0x1.64c7dc5d9f895p-5, 0x1.dfeae57fd8c03p-4, -0x1.49a44726f7528p-4, -0x1.87c40195752f9p-4, + 0x1.f759994429accp-4, -0x1.76dd998e24d49p-6, -0x1.4d1e255cb1b24p-5, 0x1.e426a5406b002p-4, + -0x1.53282966ef7ddp-4, -0x1.7f8ec9ca4ed2dp-4, 0x1.f4e60323c30a3p-4, -0x1.a829fee09df57p-6, + -0x1.35410e22db0d9p-5, 0x1.e817bbb733c69p-4, -0x1.5c77bb4aaf404p-4, -0x1.771e75448efbfp-4, + 0x1.f2252b454d66dp-4, -0x1.d935001507a79p-6, -0x1.1d34430eb6a79p-5, 0x1.ebbd8d5c09b0dp-4, + -0x1.659193e9389e9p-4, -0x1.6e7444457ffb2p-4, 0x1.ef17896a3bfcbp-4, -0x1.04fb7fcb96c35p-5, + -0x1.04fb7fcb96c35p-5, 0x1.ef17896a3bfcbp-4, -0x1.6e7444457ffb2p-4, -0x1.659193e9389e9p-4, + 0x1.ebbd8d5c09b0dp-4, -0x1.1d34430eb6a79p-5, -0x1.d935001507a79p-6, 0x1.f2252b454d66dp-4, + -0x1.771e75448efbfp-4, -0x1.5c77bb4aaf404p-4, 0x1.e817bbb733c69p-4, -0x1.35410e22db0d9p-5, + -0x1.a829fee09df57p-6, 0x1.f4e60323c30a3p-4, -0x1.7f8ec9ca4ed2dp-4, -0x1.53282966ef7ddp-4, + 0x1.e426a5406b002p-4, -0x1.4d1e255cb1b24p-5, -0x1.76dd998e24d49p-6, 0x1.f759994429accp-4, + -0x1.87c40195752f9p-4, -0x1.49a44726f7528p-4, 0x1.dfeae57fd8c03p-4, -0x1.64c7dc5d9f895p-5, + -0x1.45575f91ab2f6p-6, 0x1.f97f922a97b9fp-4, -0x1.8fbccc48f5ca2p-4, -0x1.3fed9412c7206p-4, + 0x1.db6526b9aa422p-4, -0x1.7c3a94b3375a8p-5, -0x1.139f0d0e6e21fp-6, 0x1.fb5799aeed97ap-4, + -0x1.9777eeb45b481p-4, -0x1.36058ad65f12fp-4, 0x1.d69618cc82131p-4, -0x1.9372a7145deeap-5, + -0x1.c37858af3e913p-7, 0x1.fce1611844fddp-4, -0x1.9ef43c210211fp-4, -0x1.2bedb2af502a2p-4, + 0x1.d17e753e803b7p-4, -0x1.aa6c808ce5236p-5, -0x1.5f6cf8587ce7dp-7, 0x1.fe1cb04cb6cf0p-4, + -0x1.a63092d074b6ap-4, -0x1.21a79a9e06d62p-4, 0x1.cc1f0f8733f0dp-4, -0x1.c1249d6ef82cap-5, + -0x1.f656aee2b8d3bp-8, 0x1.ff09597fc09bap-4, -0x1.ad2bcb2659cf3p-4, -0x1.1734d699fff2ep-4, + 0x1.c678b59131459p-4, -0x1.d797777bf643cp-5, -0x1.2d86611f9143ap-8, 0x1.ffa72eec4d011p-4, + -0x1.b3e4d5310ddb1p-4, -0x1.0c9703a5823bfp-4, 0x1.c08c428be0da9p-4, -0x1.edc19543247a4p-5, + -0x1.921d39dbdf19fp-10, 0x1.fff62149a490ap-4, -0x1.ba5aa55db7b47p-4, -0x1.01cfc8c4ad637p-4, + 0x1.ba5aa5bc2052cp-4, -0x1.01cfc7baa6e87p-4, -0x1.921d374a14a1cp-10, -0x1.fff621b2f50d0p-4, + -0x1.c08c429737a82p-4, -0x1.edc195edcf8d6p-5, -0x1.b3e4d64eee461p-4, 0x1.0c9703ab2380fp-4, + 0x1.2d866371b64b1p-8, 0x1.ffa72e53d3029p-4, 0x1.c678b38dd8fc3p-4, 0x1.d79779a2f4821p-5, + 0x1.ad2bcad2d2838p-4, -0x1.1734d6a3708e1p-4, -0x1.f656aec47c081p-8, -0x1.ff095873bc108p-4, + -0x1.cc1f0e08cd3b5p-4, -0x1.c1249b6bb87bep-5, -0x1.a6309238e0d81p-4, 0x1.21a79a128d6bfp-4, + 0x1.5f6cf9a6ea948p-7, 0x1.fe1cb0d12b0b1p-4, 0x1.d17e76a5d3164p-4, 0x1.aa6c81736568bp-5, + 0x1.9ef43c324ba78p-4, -0x1.2bedb31f5ee5ep-4, -0x1.c378577d745efp-7, -0x1.fce1601707b50p-4, + -0x1.d69617863acf6p-4, -0x1.9372a68106e8cp-5, -0x1.9777ef4909debp-4, 0x1.36058a4d1bf36p-4, + 0x1.139f0d05f206ep-6, 0x1.fb579839f735bp-4, 0x1.db6525f67a5acp-4, 0x1.7c3a9489f772ap-5, + 0x1.8fbccc2f214bcp-4, -0x1.3fed93e19a2b8p-4, -0x1.4557602158512p-6, -0x1.f97f925fc876cp-4, + -0x1.dfeae65ced989p-4, -0x1.64c7db8cfc794p-5, -0x1.87c4002fcaa15p-4, 0x1.49a4491a46f2bp-4, + 0x1.76dd9987bb7d4p-6, 0x1.f7599c1f6ce6fp-4, 0x1.e426a3143dd16p-4, 0x1.4d1e258126f9ap-5, + 0x1.7f8ec9ceaadc4p-4, -0x1.5328286c810b8p-4, -0x1.a82a00497e1b9p-6, -0x1.f4e602ab64426p-4, + -0x1.e817be1d3d858p-4, -0x1.35410e55210c3p-5, -0x1.771e74c4f5fafp-4, 0x1.5c77bc076307ep-4, + 0x1.d935008660e87p-6, 0x1.f2252e175e6b9p-4, 0x1.ebbd8c27b819fp-4, 0x1.1d344369c34d4p-5, + 0x1.6e7444b6d5ac6p-4, -0x1.6591948b48676p-4, -0x1.04fb8066dd49fp-5, -0x1.ef178a49eb61bp-4, + -0x1.ef178a49eb61bp-4, -0x1.04fb8066dd49fp-5, -0x1.6591948b48676p-4, 0x1.6e7444b6d5ac6p-4, + 0x1.1d344369c34d4p-5, 0x1.ebbd8c27b819fp-4, 0x1.f2252e175e6b9p-4, 0x1.d935008660e87p-6, + 0x1.5c77bc076307ep-4, -0x1.771e74c4f5fafp-4, -0x1.35410e55210c3p-5, -0x1.e817be1d3d858p-4, + -0x1.f4e602ab64426p-4, -0x1.a82a00497e1b9p-6, -0x1.5328286c810b8p-4, 0x1.7f8ec9ceaadc4p-4, + 0x1.4d1e258126f9ap-5, 0x1.e426a3143dd16p-4, 0x1.f7599c1f6ce6fp-4, 0x1.76dd9987bb7d4p-6, + 0x1.49a4491a46f2bp-4, -0x1.87c4002fcaa15p-4, -0x1.64c7db8cfc794p-5, -0x1.dfeae65ced989p-4, + -0x1.f97f925fc876cp-4, -0x1.4557602158512p-6, -0x1.3fed93e19a2b8p-4, 0x1.8fbccc2f214bcp-4, + 0x1.7c3a9489f772ap-5, 0x1.db6525f67a5acp-4, 0x1.fb579839f735bp-4, 0x1.139f0d05f206ep-6, + 0x1.36058a4d1bf36p-4, -0x1.9777ef4909debp-4, -0x1.9372a68106e8cp-5, -0x1.d69617863acf6p-4, + -0x1.fce1601707b50p-4, -0x1.c378577d745efp-7, -0x1.2bedb31f5ee5ep-4, 0x1.9ef43c324ba78p-4, + 0x1.aa6c81736568bp-5, 0x1.d17e76a5d3164p-4, 0x1.fe1cb0d12b0b1p-4, 0x1.5f6cf9a6ea948p-7, + 0x1.21a79a128d6bfp-4, -0x1.a6309238e0d81p-4, -0x1.c1249b6bb87bep-5, -0x1.cc1f0e08cd3b5p-4, + -0x1.ff095873bc108p-4, -0x1.f656aec47c081p-8, -0x1.1734d6a3708e1p-4, 0x1.ad2bcad2d2838p-4, + 0x1.d79779a2f4821p-5, 0x1.c678b38dd8fc3p-4, 0x1.ffa72e53d3029p-4, 0x1.2d866371b64b1p-8, + 0x1.0c9703ab2380fp-4, -0x1.b3e4d64eee461p-4, -0x1.edc195edcf8d6p-5, -0x1.c08c429737a82p-4, + -0x1.fff621b2f50d0p-4, -0x1.921d374a14a1cp-10, -0x1.01cfc7baa6e85p-4, 0x1.ba5aa5bc2051cp-4, + -0x1.94eb3210f5311p-4, -0x1.122b54aaaffe6p-4, 0x1.92bca73c55e6ap-7, -0x1.ebbfa98001467p-3, + 0x1.47db30bd5e093p-12, 0x1.4a729b7013a8cp-3, 0x1.003f1103b48d5p-3, 0x1.b451a2159a0f7p-4, + 0x1.55a7ce048ee33p-11, 0x1.4a1e4e003ddd6p-3, 0x1.6b3e673132dbcp-6, -0x1.6734a08eea572p-4, + 0x1.bb17e8568d03fp-8, -0x1.f4c63b864bf3ep-6, -0x1.05f040d000acfp-7, -0x1.742ea58ce2403p-5, + -0x1.93b2202108ae4p-3, -0x1.379b1551ac280p-4, -0x1.28a9842284f8fp-6, 0x1.06740cde02bd6p-5, + -0x1.afebd47d29a83p-10, -0x1.872222a25f292p-4, -0x1.6c6203c17431fp-3, -0x1.91d22a629f5f4p-6, + 0x1.cb1365cb68b09p-5, -0x1.b64f05a5969a8p-7, 0x1.eda560a78e050p-10, -0x1.0c61e3bccd3b9p-3, + -0x1.4eae9949b8b8cp-4, 0x1.83f1dbaf19532p-5, 0x1.1ab03da009cc6p-3, 0x1.28b863f0e39bep-5, + -0x1.a8b096bb60edcp-6, 0x1.7e14a7bbcd4b3p-3, -0x1.1a88a5849ec5fp-10, -0x1.f5a7c697c0ab6p-9, + -0x1.e5d3c1c613163p-5, -0x1.b5197f4e7e124p-5, 0x1.3a2a62e2cd4d5p-6, 0x1.0871d18d062cap-3, + 0x1.0935f4a879990p-3, -0x1.7d8a5e8d45092p-8, -0x1.a9f05738b93b2p-5, -0x1.c128de32fbd5cp-6, + -0x1.9574800579808p-6, -0x1.4c1262fa94e2cp-4, 0x1.f8a946026a558p-7, -0x1.f84a5c89cbbd2p-6, + 0x1.8e9019469f0abp-4, 0x1.0df699456b26bp-4, 0x1.b13e72a4d0e4dp-9, 0x1.17fe0a910c2dep-3, + 0x1.63cf50e305e24p-3, 0x1.551863375da60p-5, -0x1.c9bf78290afb4p-5, 0x1.1c35f964a5998p-5, + 0x1.a0f224483b771p-5, -0x1.f9fdb036c4230p-4, -0x1.9dd40abf84597p-5, -0x1.c4b224dc09546p-7, + 0x1.f25fd7886abbep-8, 0x1.e9fc55fddc2a1p-6, 0x1.1491377d5848ap-6, -0x1.324253d683b18p-3, + -0x1.324253d683b18p-3, 0x1.1491377d5848ap-6, 0x1.e9fc55fddc2a1p-6, 0x1.f25fd7886abbep-8, + -0x1.c4b224dc09546p-7, -0x1.9dd40abf84597p-5, -0x1.f9fdb036c4230p-4, 0x1.a0f224483b771p-5, + 0x1.1c35f964a5998p-5, -0x1.c9bf78290afb4p-5, 0x1.551863375da60p-5, 0x1.63cf50e305e24p-3, + 0x1.17fe0a910c2dep-3, 0x1.b13e72a4d0e4dp-9, 0x1.0df699456b26bp-4, 0x1.8e9019469f0abp-4, + -0x1.f84a5c89cbbd2p-6, 0x1.f8a946026a558p-7, -0x1.4c1262fa94e2cp-4, -0x1.9574800579808p-6, + -0x1.c128de32fbd5cp-6, -0x1.a9f05738b93b2p-5, -0x1.7d8a5e8d45092p-8, 0x1.0935f4a879990p-3, + 0x1.0871d18d062cap-3, 0x1.3a2a62e2cd4d5p-6, -0x1.b5197f4e7e124p-5, -0x1.e5d3c1c613163p-5, + -0x1.f5a7c697c0ab6p-9, -0x1.1a88a5849ec5fp-10, 0x1.7e14a7bbcd4b3p-3, -0x1.a8b096bb60edcp-6, + 0x1.28b863f0e39bep-5, 0x1.1ab03da009cc6p-3, 0x1.83f1dbaf19532p-5, -0x1.4eae9949b8b8cp-4, + -0x1.0c61e3bccd3b9p-3, 0x1.eda560a78e050p-10, -0x1.b64f05a5969a8p-7, 0x1.cb1365cb68b09p-5, + -0x1.91d22a629f5f4p-6, -0x1.6c6203c17431fp-3, -0x1.872222a25f292p-4, -0x1.afebd47d29a83p-10, + 0x1.06740cde02bd6p-5, -0x1.28a9842284f8fp-6, -0x1.379b1551ac280p-4, -0x1.93b2202108ae4p-3, + -0x1.742ea58ce2403p-5, -0x1.05f040d000acfp-7, -0x1.f4c63b864bf3ep-6, 0x1.bb17e8568d03fp-8, + -0x1.6734a08eea572p-4, 0x1.6b3e673132dbcp-6, 0x1.4a1e4e003ddd6p-3, 0x1.55a7ce048ee33p-11, + 0x1.b451a2159a0f7p-4, 0x1.003f1103b48d3p-3, 0x1.4a729b7013a8cp-3, 0x1.47db30bd5e320p-12, + -0x1.ebbfa98001460p-3, 0x1.92bca73c55ee4p-7, -0x1.122b54bf96376p-4, -0x1.94eb313e4c7e7p-4, + -0x1.850daca33ce5bp-14, 0x1.f4947819dab17p-4, -0x1.fdc273d58c81ep-3, -0x1.11fec345d569cp-5, + 0x1.2886bab65966dp-7, 0x1.4a02b3e84a6b9p-5, 0x1.109e9e46610fep-3, -0x1.9df3a313fd8c5p-4, + -0x1.212f878f66a4ap-5, 0x1.9cd90d8ff54c9p-6, -0x1.0afda0b43a695p-6, 0x1.0a8c83718f993p-3, + -0x1.871bfb9d97c49p-5, -0x1.dc9e1487a6986p-4, 0x1.7fe15ae5c2cf5p-3, -0x1.2740efb0b79c8p-9, + -0x1.e40aa543c656cp-5, 0x1.e911bb41a3376p-7, -0x1.f8f3fb8a7564cp-4, -0x1.c8220e3d7d546p-5, + -0x1.b93b1e5c08910p-4, -0x1.94b4e6d1d8544p-8, -0x1.f379acb0b9b82p-10, -0x1.ff7da9e221adbp-3, + -0x1.3e7e7f646cac6p-5, -0x1.f7a4fed7dcdd1p-7, 0x1.a90d87a3a2304p-4, -0x1.826fa0a31e37ap-5, + -0x1.b17ec7c3e5af9p-5, -0x1.034a110905c81p-4, -0x1.7f5b20774b573p-4, 0x1.5ef096147d504p-9, + 0x1.b006462eb54cfp-3, 0x1.4975bc697efc8p-6, -0x1.45825d383adc8p-10, 0x1.95a343bc08967p-5, + 0x1.2e101bbbc5eadp-4, 0x1.1fbbe01ce6b2ap-5, -0x1.5cf9a08f1be3fp-4, 0x1.4226803c5c415p-6, + 0x1.780806074ff70p-7, 0x1.18813984fd14fp-7, 0x1.3e78240f3440bp-7, -0x1.2236d03102e39p-4, + 0x1.e48230dd8d223p-5, -0x1.7d35213519956p-6, -0x1.20d14476ab1d0p-4, 0x1.11fb2e22ab6c0p-6, + -0x1.af8d041770787p-6, -0x1.de94c4d56d5c0p-7, 0x1.2cdf5bfd0400ep-5, 0x1.27832159655b0p-6, + 0x1.95b95b4a4a980p-7, -0x1.b23049c4f3506p-3, 0x1.27192a652669fp-6, -0x1.53fed362c6de0p-4, + -0x1.1768346669951p-4, -0x1.aab05365a638bp-6, -0x1.67745691cb710p-6, 0x1.db293fcd373d4p-4, + 0x1.c8b9236bf75cdp-4, 0x1.ed6a1fe30862cp-5, -0x1.5be871e933b7ap-3, -0x1.8d40d034b8b32p-6, + -0x1.8d40d034b8b32p-6, -0x1.5be871e933b7ap-3, 0x1.ed6a1fe30862cp-5, 0x1.c8b9236bf75cdp-4, + 0x1.db293fcd373d4p-4, -0x1.67745691cb710p-6, -0x1.aab05365a638bp-6, -0x1.1768346669951p-4, + -0x1.53fed362c6de0p-4, 0x1.27192a652669fp-6, -0x1.b23049c4f3506p-3, 0x1.95b95b4a4a980p-7, + 0x1.27832159655b0p-6, 0x1.2cdf5bfd0400ep-5, -0x1.de94c4d56d5c0p-7, -0x1.af8d041770787p-6, + 0x1.11fb2e22ab6c0p-6, -0x1.20d14476ab1d0p-4, -0x1.7d35213519956p-6, 0x1.e48230dd8d223p-5, + -0x1.2236d03102e39p-4, 0x1.3e78240f3440bp-7, 0x1.18813984fd14fp-7, 0x1.780806074ff70p-7, + 0x1.4226803c5c415p-6, -0x1.5cf9a08f1be3fp-4, 0x1.1fbbe01ce6b2ap-5, 0x1.2e101bbbc5eadp-4, + 0x1.95a343bc08967p-5, -0x1.45825d383adc8p-10, 0x1.4975bc697efc8p-6, 0x1.b006462eb54cfp-3, + 0x1.5ef096147d504p-9, -0x1.7f5b20774b573p-4, -0x1.034a110905c81p-4, -0x1.b17ec7c3e5af9p-5, + -0x1.826fa0a31e37ap-5, 0x1.a90d87a3a2304p-4, -0x1.f7a4fed7dcdd1p-7, -0x1.3e7e7f646cac6p-5, + -0x1.ff7da9e221adbp-3, -0x1.f379acb0b9b82p-10, -0x1.94b4e6d1d8544p-8, -0x1.b93b1e5c08910p-4, + -0x1.c8220e3d7d546p-5, -0x1.f8f3fb8a7564cp-4, 0x1.e911bb41a3376p-7, -0x1.e40aa543c656cp-5, + -0x1.2740efb0b79c8p-9, 0x1.7fe15ae5c2cf5p-3, -0x1.dc9e1487a6986p-4, -0x1.871bfb9d97c49p-5, + 0x1.0a8c83718f993p-3, -0x1.0afda0b43a695p-6, 0x1.9cd90d8ff54c9p-6, -0x1.212f878f66a4ap-5, + -0x1.9df3a313fd8c3p-4, 0x1.109e9e46610fep-3, 0x1.4a02b3e84a6a7p-5, 0x1.2886bab659658p-7, + -0x1.11fec345d5698p-5, -0x1.fdc273d58c81fp-3, 0x1.f4947ac9b9364p-4, -0x1.850ce0f76c775p-14, + -0x1.0c9705f92f3fbp-4, -0x1.b3e4d567fb091p-4, 0x1.fe1caf54dd206p-4, -0x1.5f6d0b03b4aedp-7, + -0x1.7c3a90b5ab824p-5, 0x1.db65280229123p-4, -0x1.532829bf1a525p-4, -0x1.7f8ecf22b3261p-4, + 0x1.ef178aa8df64fp-4, -0x1.04fb7f427a505p-5, -0x1.a82a0754dd63fp-6, 0x1.f4e60448beac9p-4, + -0x1.8fbcc8f2a4e7bp-4, -0x1.3fed967611f97p-4, 0x1.d17e77a627fe2p-4, -0x1.aa6c8374dfdb2p-5, + -0x1.2d8654f419718p-8, 0x1.ffa72f4200b32p-4, -0x1.c08c41544b4b8p-4, -0x1.edc1950ba3d64p-5, + 0x1.a6309347426b8p-4, -0x1.21a79829502d0p-4, 0x1.139f08ebf5f8fp-6, 0x1.fb57977f1de20p-4, + -0x1.e426a1b1380d4p-4, -0x1.4d1e21589f696p-5, 0x1.6e7445a1f2763p-4, -0x1.65918f9484aa8p-4, + 0x1.35410b7415426p-5, 0x1.e817b97ccb0b3p-4, -0x1.f97f925f2952dp-4, -0x1.45576732bb2b5p-6, + 0x1.2bedb51b2ae9bp-4, -0x1.9ef43ef80bf55p-4, 0x1.d797756fba9c1p-5, 0x1.c678b309dc630p-4, + -0x1.fff6238937530p-4, 0x1.921daf28ca8a4p-10, 0x1.c124a0c1e1235p-5, -0x1.cc1f0d518286bp-4, + 0x1.36058c8ffbfc6p-4, 0x1.9777f0a605ad8p-4, -0x1.f759997099ad5p-4, 0x1.76dd9df0037d0p-6, + 0x1.1d344437c71a4p-5, -0x1.ebbd8a7634690p-4, 0x1.771e76e92201bp-4, 0x1.5c77bcecc9e9ap-4, + -0x1.dfeae5561ac58p-4, 0x1.64c7e0b5fc8dep-5, 0x1.c3785eaeb6a7dp-7, -0x1.fce15ebc77dd8p-4, + 0x1.ad2bca583cd21p-4, 0x1.1734d88e55d87p-4, -0x1.ba5aa34851bffp-4, 0x1.01cfcafef67d4p-4, + -0x1.f656eb3bde6bap-8, -0x1.ff0953a7e8b98p-4, 0x1.d69618e2ac9e5p-4, 0x1.9372a86a3861bp-5, + -0x1.87c3ffb8b4d2cp-4, 0x1.49a4486f6795dp-4, -0x1.d934f99f71b93p-6, -0x1.f2253176c0b7fp-4, + 0x1.f2253176c0b7fp-4, 0x1.d934f99f71b93p-6, -0x1.49a4486f6795dp-4, 0x1.87c3ffb8b4d2cp-4, + -0x1.9372a86a3861bp-5, -0x1.d69618e2ac9e5p-4, 0x1.ff0953a7e8b98p-4, 0x1.f656eb3bde6bap-8, + -0x1.01cfcafef67d4p-4, 0x1.ba5aa34851bffp-4, -0x1.1734d88e55d87p-4, -0x1.ad2bca583cd21p-4, + 0x1.fce15ebc77dd8p-4, -0x1.c3785eaeb6a7dp-7, -0x1.64c7e0b5fc8dep-5, 0x1.dfeae5561ac58p-4, + -0x1.5c77bcecc9e9ap-4, -0x1.771e76e92201bp-4, 0x1.ebbd8a7634690p-4, -0x1.1d344437c71a4p-5, + -0x1.76dd9df0037d0p-6, 0x1.f759997099ad5p-4, -0x1.9777f0a605ad8p-4, -0x1.36058c8ffbfc6p-4, + 0x1.cc1f0d518286bp-4, -0x1.c124a0c1e1235p-5, -0x1.921daf28ca8a4p-10, 0x1.fff6238937530p-4, + -0x1.c678b309dc630p-4, -0x1.d797756fba9c1p-5, 0x1.9ef43ef80bf55p-4, -0x1.2bedb51b2ae9bp-4, + 0x1.45576732bb2b5p-6, 0x1.f97f925f2952dp-4, -0x1.e817b97ccb0b3p-4, -0x1.35410b7415426p-5, + 0x1.65918f9484aa8p-4, -0x1.6e7445a1f2763p-4, 0x1.4d1e21589f696p-5, 0x1.e426a1b1380d4p-4, + -0x1.fb57977f1de20p-4, -0x1.139f08ebf5f8fp-6, 0x1.21a79829502d0p-4, -0x1.a6309347426b8p-4, + 0x1.edc1950ba3d64p-5, 0x1.c08c41544b4b8p-4, -0x1.ffa72f4200b32p-4, 0x1.2d8654f419718p-8, + 0x1.aa6c8374dfdb2p-5, -0x1.d17e77a627fe2p-4, 0x1.3fed967611f97p-4, 0x1.8fbcc8f2a4e7bp-4, + -0x1.f4e60448beac9p-4, 0x1.a82a0754dd63fp-6, 0x1.04fb7f427a505p-5, -0x1.ef178aa8df64fp-4, + 0x1.7f8ecf22b3261p-4, 0x1.532829bf1a525p-4, -0x1.db65280229123p-4, 0x1.7c3a90b5ab824p-5, + 0x1.5f6d0b03b4aedp-7, -0x1.fe1caf54dd206p-4, 0x1.b3e4d567fb09cp-4, 0x1.0c9705f92f3fbp-4, + 0x1.b3e4d56a86f29p-4, -0x1.0c9705e8ff798p-4, -0x1.5f6d0b8f80a18p-7, -0x1.fe1caf148f676p-4, + -0x1.db65281649e3ep-4, -0x1.7c3a91f911b12p-5, -0x1.7f8ece27f4406p-4, 0x1.53282982334eep-4, + 0x1.04fb7f0b0c9e4p-5, 0x1.ef178c4eca94fp-4, 0x1.f4e603bb1e62ep-4, 0x1.a82a07046c755p-6, + 0x1.3fed96bcaa56ep-4, -0x1.8fbcca826f998p-4, -0x1.aa6c837fe2d09p-5, -0x1.d17e7790aa2b1p-4, + -0x1.ffa72e30382dbp-4, -0x1.2d8656dd8c431p-8, -0x1.edc194a3266d0p-5, 0x1.c08c3f6bb7f8ep-4, + 0x1.21a79852c8c8fp-4, 0x1.a630927be535ep-4, 0x1.fb57962a653dep-4, -0x1.139f0a79eb3b2p-6, + 0x1.4d1e20bd5468cp-5, -0x1.e426a271286b3p-4, -0x1.659191206ec5cp-4, -0x1.6e74467585ee3p-4, + -0x1.e817b7d59b23fp-4, 0x1.35410bd77e794p-5, -0x1.4557668d32f4fp-6, 0x1.f97f91b2a07b6p-4, + 0x1.9ef440e702479p-4, 0x1.2bedb57af5088p-4, 0x1.c678b4e142c16p-4, -0x1.d79773ed7b8cdp-5, + -0x1.921da40bed28cp-10, -0x1.fff62588f8d5dp-4, -0x1.cc1f0d8efe77fp-4, -0x1.c124a0eeee131p-5, + -0x1.9777f0358a09ep-4, 0x1.36058c562111fp-4, 0x1.76dd9dbee92cfp-6, 0x1.f7599745b7700p-4, + 0x1.ebbd8c236d338p-4, 0x1.1d34454b1f53bp-5, 0x1.5c77bc11dc0bdp-4, -0x1.771e768fc6572p-4, + -0x1.64c7e0425d899p-5, -0x1.dfeae576523a5p-4, -0x1.fce15f801fc95p-4, -0x1.c3785e33ffa2cp-7, + -0x1.1734d7ff97fcdp-4, 0x1.ad2bc9dea8f40p-4, 0x1.01cfca47763c0p-4, 0x1.ba5aa2de21dd3p-4, + 0x1.ff09534f0eb58p-4, -0x1.f656e9ab5473cp-8, 0x1.9372a7e1e9a41p-5, -0x1.d6961a6cc390bp-4, + -0x1.49a448b270975p-4, -0x1.87c4005c3870dp-4, -0x1.f2252fd44e2d4p-4, 0x1.d934fb455ea8bp-6, + -0x1.d934fb455ea8bp-6, 0x1.f2252fd44e2d4p-4, 0x1.87c4005c3870dp-4, 0x1.49a448b270975p-4, + 0x1.d6961a6cc390bp-4, -0x1.9372a7e1e9a41p-5, 0x1.f656e9ab5473cp-8, -0x1.ff09534f0eb58p-4, + -0x1.ba5aa2de21dd3p-4, -0x1.01cfca47763c0p-4, -0x1.ad2bc9dea8f40p-4, 0x1.1734d7ff97fcdp-4, + 0x1.c3785e33ffa2cp-7, 0x1.fce15f801fc95p-4, 0x1.dfeae576523a5p-4, 0x1.64c7e0425d899p-5, + 0x1.771e768fc6572p-4, -0x1.5c77bc11dc0bdp-4, -0x1.1d34454b1f53bp-5, -0x1.ebbd8c236d338p-4, + -0x1.f7599745b7700p-4, -0x1.76dd9dbee92cfp-6, -0x1.36058c562111fp-4, 0x1.9777f0358a09ep-4, + 0x1.c124a0eeee131p-5, 0x1.cc1f0d8efe77fp-4, 0x1.fff62588f8d5dp-4, 0x1.921da40bed28cp-10, + 0x1.d79773ed7b8cdp-5, -0x1.c678b4e142c16p-4, -0x1.2bedb57af5088p-4, -0x1.9ef440e702479p-4, + -0x1.f97f91b2a07b6p-4, 0x1.4557668d32f4fp-6, -0x1.35410bd77e794p-5, 0x1.e817b7d59b23fp-4, + 0x1.6e74467585ee3p-4, 0x1.659191206ec5cp-4, 0x1.e426a271286b3p-4, -0x1.4d1e20bd5468cp-5, + 0x1.139f0a79eb3b2p-6, -0x1.fb57962a653dep-4, -0x1.a630927be535ep-4, -0x1.21a79852c8c8fp-4, + -0x1.c08c3f6bb7f8ep-4, 0x1.edc194a3266d0p-5, 0x1.2d8656dd8c431p-8, 0x1.ffa72e30382dbp-4, + 0x1.d17e7790aa2b1p-4, 0x1.aa6c837fe2d09p-5, 0x1.8fbcca826f998p-4, -0x1.3fed96bcaa56ep-4, + -0x1.a82a07046c755p-6, -0x1.f4e603bb1e62ep-4, -0x1.ef178c4eca94fp-4, -0x1.04fb7f0b0c9e4p-5, + -0x1.53282982334eep-4, 0x1.7f8ece27f4406p-4, 0x1.7c3a91f911b12p-5, 0x1.db65281649e3ep-4, + 0x1.fe1caf148f676p-4, 0x1.5f6d0b8f80a18p-7, 0x1.0c9705e8ff798p-4, -0x1.b3e4d56a86f20p-4, + -0x1.5f8cd61db7b35p-4, -0x1.d3c3ba10bf132p-5, 0x1.2b6633301d376p-12, -0x1.0803b8f90cac3p-4, + 0x1.eabb00bb5c68ap-11, 0x1.5bf36562d2af4p-4, 0x1.0a82e17417a5fp-5, -0x1.7ae83f6ce7cefp-6, + 0x1.55cced000dfbfp-6, -0x1.33a837dfc547dp-5, 0x1.5722c09a9445bp-5, -0x1.5c3b7bf13d5e3p-6, + 0x1.6bb86fe49074ap-7, 0x1.6cd4422d9155ep-5, -0x1.4ac18fe7e9ee5p-12, -0x1.af9f4ac5ce3d8p-5, + -0x1.b97fd39b047bcp-4, 0x1.ec0567e7b5ea3p-8, 0x1.765e4d1584a5ep-6, 0x1.6714cdefc2abdp-3, + -0x1.04d8044ca83d7p-3, 0x1.7411ff4f51ae0p-8, 0x1.52fb892d1085ep-3, 0x1.04eba0311b5fcp-5, + -0x1.c7848e54bfe2dp-7, 0x1.fb56252a3ab16p-4, 0x1.588567f97d223p-5, 0x1.3baf79293a151p-5, + -0x1.4d761674097d8p-3, -0x1.16774ccabb039p-5, -0x1.2d56773fe850ap-7, 0x1.1189fbd0280b0p-4, + -0x1.34ac7ecc25d07p-3, -0x1.0d123da701f6fp-3, -0x1.aa9ad042cc5c7p-5, -0x1.a251ef48a7babp-7, + -0x1.254777f10b93ap-7, 0x1.1e9e96821483bp-8, -0x1.473131c228be7p-6, 0x1.c131c31a59cb8p-14, + 0x1.4f10b9022358ep-10, -0x1.76570913f3bf9p-5, -0x1.f6cc8493e0451p-7, 0x1.86e3dc5e3f148p-3, + -0x1.19a0378bf722ep-3, -0x1.b582a163c1a5dp-5, 0x1.84c096ee4f8fdp-5, 0x1.9302f479a783cp-4, + 0x1.3e1b4ece5cf46p-4, 0x1.5259e04a4c4f3p-3, 0x1.b41434747a49dp-3, -0x1.ee9d4d56b039ap-10, + -0x1.ff67f887f49f1p-6, -0x1.3e99b49f59b10p-5, 0x1.290681f913bcep-4, 0x1.5a31c6c95730cp-3, + 0x1.507e848485954p-3, -0x1.5e30ac6780914p-8, 0x1.ebc812c6e4d43p-9, 0x1.eac6ac51240a3p-5, + 0x1.545c5e342951fp-3, 0x1.0d52f98b66965p-4, -0x1.803da62fe4734p-3, -0x1.20e6321efcc84p-6, + 0x1.20e6321efcc84p-6, 0x1.803da62fe4734p-3, -0x1.0d52f98b66965p-4, -0x1.545c5e342951fp-3, + -0x1.eac6ac51240a3p-5, -0x1.ebc812c6e4d43p-9, 0x1.5e30ac6780914p-8, -0x1.507e848485954p-3, + -0x1.5a31c6c95730cp-3, -0x1.290681f913bcep-4, 0x1.3e99b49f59b10p-5, 0x1.ff67f887f49f1p-6, + 0x1.ee9d4d56b039ap-10, -0x1.b41434747a49dp-3, -0x1.5259e04a4c4f3p-3, -0x1.3e1b4ece5cf46p-4, + -0x1.9302f479a783cp-4, -0x1.84c096ee4f8fdp-5, 0x1.b582a163c1a5dp-5, 0x1.19a0378bf722ep-3, + -0x1.86e3dc5e3f148p-3, 0x1.f6cc8493e0451p-7, 0x1.76570913f3bf9p-5, -0x1.4f10b9022358ep-10, + -0x1.c131c31a59cb8p-14, 0x1.473131c228be7p-6, -0x1.1e9e96821483bp-8, 0x1.254777f10b93ap-7, + 0x1.a251ef48a7babp-7, 0x1.aa9ad042cc5c7p-5, 0x1.0d123da701f6fp-3, 0x1.34ac7ecc25d07p-3, + -0x1.1189fbd0280b0p-4, 0x1.2d56773fe850ap-7, 0x1.16774ccabb039p-5, 0x1.4d761674097d8p-3, + -0x1.3baf79293a151p-5, -0x1.588567f97d223p-5, -0x1.fb56252a3ab16p-4, 0x1.c7848e54bfe2dp-7, + -0x1.04eba0311b5fcp-5, -0x1.52fb892d1085ep-3, -0x1.7411ff4f51ae0p-8, 0x1.04d8044ca83d7p-3, + -0x1.6714cdefc2abdp-3, -0x1.765e4d1584a5ep-6, -0x1.ec0567e7b5ea3p-8, 0x1.b97fd39b047bcp-4, + 0x1.af9f4ac5ce3d8p-5, 0x1.4ac18fe7e9ee5p-12, -0x1.6cd4422d9155ep-5, -0x1.6bb86fe49074ap-7, + 0x1.5c3b7bf13d5e3p-6, -0x1.5722c09a9445bp-5, 0x1.33a837dfc547dp-5, -0x1.55cced000dfbfp-6, + 0x1.7ae83f6ce7cefp-6, -0x1.0a82e17417a6ep-5, -0x1.5bf36562d2af4p-4, -0x1.eabb00bb5c6fcp-11, + 0x1.0803b8f90cac3p-4, -0x1.2b6633301cd83p-12, 0x1.d3c3ba11c2eccp-5, 0x1.5f8cd5a530440p-4, + -0x1.1dd83ff47f2fep-5, -0x1.d113e2ca5dfe4p-7, 0x1.70bfb5559a56dp-4, 0x1.4054fb618749ap-6, + 0x1.d74bf942a624ep-5, -0x1.3578bbd6aecfap-3, -0x1.47eff701d8b87p-4, -0x1.549b3b5e08044p-3, + -0x1.d452bf4401a03p-4, -0x1.3dbd6e944789fp-5, -0x1.e3be0e6b9e5cap-6, 0x1.dc2d994da8b7bp-4, + 0x1.420c98a4fed5ep-3, -0x1.43c051afbdbf5p-5, -0x1.1ca11af5d1906p-7, -0x1.7b02191fdf5d6p-5, + 0x1.884fdb20a248cp-6, 0x1.f6640f71129abp-5, -0x1.dc3c389ec501cp-4, -0x1.b03bd118d31d4p-7, + 0x1.7e7b3212b0e4ap-8, -0x1.9efcf05254481p-5, -0x1.8f2bce4fe54abp-5, 0x1.680df76a7d563p-3, + 0x1.5b0e1bc91ab5fp-3, -0x1.3806df259698bp-5, 0x1.9bb400d97f1e9p-6, 0x1.c95d8e285b6c2p-4, + 0x1.e3183319476eap-6, 0x1.147bd08955a31p-3, -0x1.01012a83b4a03p-3, -0x1.99b18b870892ep-8, + 0x1.97185b74a798ap-6, 0x1.8e47ddc2c78d3p-4, -0x1.36014ae214b32p-7, -0x1.ab6eab5a53ba3p-3, + 0x1.b531091f48503p-3, 0x1.89e2521295d6ap-6, -0x1.37f005145a535p-5, 0x1.cd043dc5eb4f6p-4, + -0x1.46741f3ff5d4dp-7, -0x1.4739363f736d1p-4, 0x1.f534fa7dd652ap-5, -0x1.ac4099df8f203p-7, + -0x1.16638181fd69cp-5, 0x1.1a9095669d497p-6, 0x1.34cf571b66639p-4, 0x1.d8f78009815bdp-6, + -0x1.7ad5433607bd8p-3, 0x1.6fe39a24853cap-5, 0x1.8436b267438a1p-6, -0x1.c7e87afdc14d3p-5, + -0x1.3354667a6954bp-5, 0x1.7d6738a47a1aep-7, 0x1.05f5cc08b4242p-4, 0x1.6a8f33fd0332ap-4, + -0x1.8fa91998b4254p-7, 0x1.de3407ea96e1dp-4, 0x1.0b79681c6aadap-3, 0x1.29c4773a07c82p-6, + 0x1.0ef8438aa0546p-3, 0x1.e62e71613d6e8p-5, 0x1.50040edaef032p-5, -0x1.c473462001130p-6, + 0x1.c473462001130p-6, -0x1.50040edaef032p-5, -0x1.e62e71613d6e8p-5, -0x1.0ef8438aa0546p-3, + -0x1.29c4773a07c82p-6, -0x1.0b79681c6aadap-3, -0x1.de3407ea96e1dp-4, 0x1.8fa91998b4254p-7, + -0x1.6a8f33fd0332ap-4, -0x1.05f5cc08b4242p-4, -0x1.7d6738a47a1aep-7, 0x1.3354667a6954bp-5, + 0x1.c7e87afdc14d3p-5, -0x1.8436b267438a1p-6, -0x1.6fe39a24853cap-5, 0x1.7ad5433607bd8p-3, + -0x1.d8f78009815bdp-6, -0x1.34cf571b66639p-4, -0x1.1a9095669d497p-6, 0x1.16638181fd69cp-5, + 0x1.ac4099df8f203p-7, -0x1.f534fa7dd652ap-5, 0x1.4739363f736d1p-4, 0x1.46741f3ff5d4dp-7, + -0x1.cd043dc5eb4f6p-4, 0x1.37f005145a535p-5, -0x1.89e2521295d6ap-6, -0x1.b531091f48503p-3, + 0x1.ab6eab5a53ba3p-3, 0x1.36014ae214b32p-7, -0x1.8e47ddc2c78d3p-4, -0x1.97185b74a798ap-6, + 0x1.99b18b870892ep-8, 0x1.01012a83b4a03p-3, -0x1.147bd08955a31p-3, -0x1.e3183319476eap-6, + -0x1.c95d8e285b6c2p-4, -0x1.9bb400d97f1e9p-6, 0x1.3806df259698bp-5, -0x1.5b0e1bc91ab5fp-3, + -0x1.680df76a7d563p-3, 0x1.8f2bce4fe54abp-5, 0x1.9efcf05254481p-5, -0x1.7e7b3212b0e4ap-8, + 0x1.b03bd118d31d4p-7, 0x1.dc3c389ec501cp-4, -0x1.f6640f71129abp-5, -0x1.884fdb20a248cp-6, + 0x1.7b02191fdf5d6p-5, 0x1.1ca11af5d1906p-7, 0x1.43c051afbdbf5p-5, -0x1.420c98a4fed5ep-3, + -0x1.dc2d994da8b7bp-4, 0x1.e3be0e6b9e5cap-6, 0x1.3dbd6e944789fp-5, 0x1.d452bf4401a03p-4, + 0x1.549b3b5e08042p-3, 0x1.47eff701d8b86p-4, 0x1.3578bbd6aecfbp-3, -0x1.d74bf942a624bp-5, + -0x1.4054fb61874bap-6, -0x1.70bfb5559a56bp-4, 0x1.d113e5e366b94p-7, 0x1.1dd83f9bae3ccp-5, + -0x1.1734d5eb9e401p-4, -0x1.ad2bca42d33cbp-4, 0x1.f97f8f1767190p-4, -0x1.4557711496835p-6, + -0x1.04fb84c2ae3abp-5, 0x1.ef178a41522b2p-4, -0x1.8fbcccf21ba16p-4, -0x1.3fed93b08343cp-4, + 0x1.c678b21aa9e50p-4, -0x1.d797730a06fb1p-5, 0x1.f656f6648c21ap-8, 0x1.ff095a87d8677p-4, + -0x1.dfeae7a38d5cbp-4, -0x1.64c7df0b8bdafp-5, 0x1.65919334b38e4p-4, -0x1.6e74461c91c5fp-4, + 0x1.7c3a9468e7a81p-5, 0x1.db6526ae69bcap-4, -0x1.ffa72f6f5a834p-4, -0x1.2d864ab44e076p-8, + 0x1.c1249d8f1af6dp-5, -0x1.cc1f0f1443801p-4, 0x1.49a447a8e9183p-4, 0x1.87c3ff90fb384p-4, + -0x1.ebbd8bf9784f7p-4, 0x1.1d3443ae0cfa0p-5, 0x1.139f09ec79513p-6, -0x1.fb5793f599f2dp-4, + 0x1.b3e4d253bf547p-4, 0x1.0c97040c9c0cap-4, -0x1.a6308ecdca0a9p-4, 0x1.21a79a671ce48p-4, + -0x1.76dd9e5397327p-6, -0x1.f7599878e5210p-4, 0x1.f2253274c73a2p-4, 0x1.d93502db94fa6p-6, + -0x1.360589c6ee3e7p-4, 0x1.9777ee3e86028p-4, -0x1.edc19846e26b5p-5, -0x1.c08c429e09262p-4, + 0x1.fe1caff97f272p-4, -0x1.5f6cfdf26ed4fp-7, -0x1.4d1e22ca08b9dp-5, 0x1.e426a5df3e865p-4, + -0x1.771e77515faadp-4, -0x1.5c77c09913457p-4, 0x1.d6961728fd060p-4, -0x1.9372a1dadab8cp-5, + -0x1.921cd7353e1f2p-10, 0x1.fff61f0f2db47p-4, -0x1.d17e771075ba9p-4, -0x1.aa6c801ae2f52p-5, + 0x1.7f8ed0972eaafp-4, -0x1.532829a1682d7p-4, 0x1.35410c87d544ep-5, 0x1.e817bac52fe4ap-4, + -0x1.fce160bd806b7p-4, -0x1.c3786267a1efdp-7, 0x1.01cfc6fb60350p-4, -0x1.ba5aa5a7a1b19p-4, + 0x1.2bedb3a7a5b42p-4, 0x1.9ef440bcbb8a7p-4, -0x1.f4e6026ef937ap-4, 0x1.a82a01468c47cp-6, + 0x1.a82a01468c47cp-6, -0x1.f4e6026ef937ap-4, 0x1.9ef440bcbb8a7p-4, 0x1.2bedb3a7a5b42p-4, + -0x1.ba5aa5a7a1b19p-4, 0x1.01cfc6fb60350p-4, -0x1.c3786267a1efdp-7, -0x1.fce160bd806b7p-4, + 0x1.e817bac52fe4ap-4, 0x1.35410c87d544ep-5, -0x1.532829a1682d7p-4, 0x1.7f8ed0972eaafp-4, + -0x1.aa6c801ae2f52p-5, -0x1.d17e771075ba9p-4, 0x1.fff61f0f2db47p-4, -0x1.921cd7353e1f2p-10, + -0x1.9372a1dadab8cp-5, 0x1.d6961728fd060p-4, -0x1.5c77c09913457p-4, -0x1.771e77515faadp-4, + 0x1.e426a5df3e865p-4, -0x1.4d1e22ca08b9dp-5, -0x1.5f6cfdf26ed4fp-7, 0x1.fe1caff97f272p-4, + -0x1.c08c429e09262p-4, -0x1.edc19846e26b5p-5, 0x1.9777ee3e86028p-4, -0x1.360589c6ee3e7p-4, + 0x1.d93502db94fa6p-6, 0x1.f2253274c73a2p-4, -0x1.f7599878e5210p-4, -0x1.76dd9e5397327p-6, + 0x1.21a79a671ce48p-4, -0x1.a6308ecdca0a9p-4, 0x1.0c97040c9c0cap-4, 0x1.b3e4d253bf547p-4, + -0x1.fb5793f599f2dp-4, 0x1.139f09ec79513p-6, 0x1.1d3443ae0cfa0p-5, -0x1.ebbd8bf9784f7p-4, + 0x1.87c3ff90fb384p-4, 0x1.49a447a8e9183p-4, -0x1.cc1f0f1443801p-4, 0x1.c1249d8f1af6dp-5, + -0x1.2d864ab44e076p-8, -0x1.ffa72f6f5a834p-4, 0x1.db6526ae69bcap-4, 0x1.7c3a9468e7a81p-5, + -0x1.6e74461c91c5fp-4, 0x1.65919334b38e4p-4, -0x1.64c7df0b8bdafp-5, -0x1.dfeae7a38d5cbp-4, + 0x1.ff095a87d8677p-4, 0x1.f656f6648c21ap-8, -0x1.d797730a06fb1p-5, 0x1.c678b21aa9e50p-4, + -0x1.3fed93b08343cp-4, -0x1.8fbcccf21ba16p-4, 0x1.ef178a41522b2p-4, -0x1.04fb84c2ae3abp-5, + -0x1.4557711496835p-6, 0x1.f97f8f1767190p-4, -0x1.ad2bca42d33d5p-4, -0x1.1734d5eb9e404p-4, + 0x1.ad2bca61f7a7ap-4, -0x1.1734d5e7de224p-4, -0x1.45577189cf33ep-6, -0x1.f97f8e7cfdad8p-4, + -0x1.ef178a466990bp-4, -0x1.04fb857c3c51ep-5, -0x1.3fed92e5e7fdep-4, 0x1.8fbccb95d2d92p-4, + 0x1.d79772d689dddp-5, 0x1.c678b15013c6ep-4, 0x1.ff0959777bc19p-4, -0x1.f656f7ecf9764p-8, + 0x1.64c7deb8badb2p-5, -0x1.dfeae90fa0c7cp-4, -0x1.6e74462c76ff8p-4, -0x1.659192b2564e5p-4, + -0x1.db65267edb88fp-4, 0x1.7c3a94cc77766p-5, -0x1.2d86475fbea84p-8, 0x1.ffa72ed7edbf6p-4, + 0x1.cc1f0fca410a2p-4, 0x1.c1249ef65074bp-5, 0x1.87c3fefd78c26p-4, -0x1.49a448838c2c9p-4, + -0x1.1d34431235222p-5, -0x1.ebbd8d1b9cc8cp-4, -0x1.fb5795692d2afp-4, -0x1.139f09d289a2fp-6, + -0x1.0c9703f3a5a24p-4, 0x1.b3e4d432f007cp-4, 0x1.21a79aed246f9p-4, 0x1.a6308f6d9ffc9p-4, + 0x1.f75998dc882d8p-4, -0x1.76dd9df45f471p-6, 0x1.d93502190476ap-6, -0x1.f225321269bc9p-4, + -0x1.9777ee1e13d86p-4, -0x1.36058a6a4fcd3p-4, -0x1.c08c4361e465fp-4, 0x1.edc198b9ba01ap-5, + 0x1.5f6cfb943af0fp-7, 0x1.fe1caf01a0c85p-4, 0x1.e426a5a70d433p-4, 0x1.4d1e2324a8825p-5, + 0x1.5c77c03c4d28cp-4, -0x1.771e7778d1c84p-4, -0x1.9372a2bff240cp-5, -0x1.d69618ad3444dp-4, + -0x1.fff61e3b74092p-4, -0x1.921ce18ee51bep-10, -0x1.aa6c820deca75p-5, 0x1.d17e7721da0b5p-4, + 0x1.532828f6a74e4p-4, 0x1.7f8ecf9f56e62p-4, 0x1.e817b867c2a86p-4, -0x1.35410c588964dp-5, + 0x1.c378629927d3bp-7, -0x1.fce15f6d55ad0p-4, -0x1.ba5aa4de87986p-4, -0x1.01cfc797fdde4p-4, + -0x1.9ef4402c45196p-4, 0x1.2bedb32771066p-4, 0x1.a82a01ea25758p-6, 0x1.f4e604ff6b3f4p-4, + 0x1.f4e604ff6b3f4p-4, 0x1.a82a01ea25758p-6, 0x1.2bedb32771066p-4, -0x1.9ef4402c45196p-4, + -0x1.01cfc797fdde4p-4, -0x1.ba5aa4de87986p-4, -0x1.fce15f6d55ad0p-4, 0x1.c378629927d3bp-7, + -0x1.35410c588964dp-5, 0x1.e817b867c2a86p-4, 0x1.7f8ecf9f56e62p-4, 0x1.532828f6a74e4p-4, + 0x1.d17e7721da0b5p-4, -0x1.aa6c820deca75p-5, -0x1.921ce18ee51bep-10, -0x1.fff61e3b74092p-4, + -0x1.d69618ad3444dp-4, -0x1.9372a2bff240cp-5, -0x1.771e7778d1c84p-4, 0x1.5c77c03c4d28cp-4, + 0x1.4d1e2324a8825p-5, 0x1.e426a5a70d433p-4, 0x1.fe1caf01a0c85p-4, 0x1.5f6cfb943af0fp-7, + 0x1.edc198b9ba01ap-5, -0x1.c08c4361e465fp-4, -0x1.36058a6a4fcd3p-4, -0x1.9777ee1e13d86p-4, + -0x1.f225321269bc9p-4, 0x1.d93502190476ap-6, -0x1.76dd9df45f471p-6, 0x1.f75998dc882d8p-4, + 0x1.a6308f6d9ffc9p-4, 0x1.21a79aed246f9p-4, 0x1.b3e4d432f007cp-4, -0x1.0c9703f3a5a24p-4, + -0x1.139f09d289a2fp-6, -0x1.fb5795692d2afp-4, -0x1.ebbd8d1b9cc8cp-4, -0x1.1d34431235222p-5, + -0x1.49a448838c2c9p-4, 0x1.87c3fefd78c26p-4, 0x1.c1249ef65074bp-5, 0x1.cc1f0fca410a2p-4, + 0x1.ffa72ed7edbf6p-4, -0x1.2d86475fbea84p-8, 0x1.7c3a94cc77766p-5, -0x1.db65267edb88fp-4, + -0x1.659192b2564e5p-4, -0x1.6e74462c76ff8p-4, -0x1.dfeae90fa0c7cp-4, 0x1.64c7deb8badb2p-5, + -0x1.f656f7ecf9764p-8, 0x1.ff0959777bc19p-4, 0x1.c678b15013c6ep-4, 0x1.d79772d689dddp-5, + 0x1.8fbccb95d2d92p-4, -0x1.3fed92e5e7fdep-4, -0x1.04fb857c3c51ep-5, -0x1.ef178a466990bp-4, + -0x1.f97f8e7cfdad8p-4, -0x1.45577189cf33ep-6, -0x1.1734d5e7de223p-4, 0x1.ad2bca61f7a8ep-4, + -0x1.581fa0fd0552bp-5, -0x1.08548a4405c4dp-6, -0x1.564a9f0a9ca6bp-8, -0x1.c69d28bf1a9d8p-4, + -0x1.ffe2c822a50f3p-6, 0x1.8ac6b86f12df6p-6, -0x1.3ded1527db6f3p-4, 0x1.688b03091923ep-9, + -0x1.958ff17b6bb88p-6, 0x1.195aace9cc73bp-4, -0x1.7a493d36e52bep-3, -0x1.25429bc8d62d0p-11, + -0x1.f0174cf56ef61p-6, 0x1.53b1b4da439acp-3, 0x1.25e9e48fbfa45p-4, -0x1.f23db4ff55d7cp-6, + 0x1.9c4646f2c1fbfp-4, 0x1.d21b6ae3411bep-5, -0x1.1673a9bbdf8b5p-11, 0x1.9dc32cf6063b6p-3, + -0x1.e487a6c503bcfp-4, 0x1.338080c03ade0p-7, 0x1.5094aca42e303p-3, 0x1.7343f03ce5a3bp-5, + 0x1.81acfddb10465p-5, 0x1.ab8551e4f0a78p-3, 0x1.b3fe7f16fc949p-3, 0x1.9c9cbb9559e73p-6, + -0x1.13eff37ca1bf6p-7, -0x1.1a1b7f321d4e0p-7, -0x1.b124bdb4108b7p-6, 0x1.c20c921c40c2ap-7, + 0x1.23a2731d6e97fp-3, -0x1.fbeb0e488d214p-8, -0x1.b00d09712b072p-5, 0x1.6996147e4588dp-4, + 0x1.f71a29ea12b38p-4, 0x1.ee23d5c1421cfp-6, -0x1.21d0780c905e2p-4, 0x1.0121c1446610cp-5, + 0x1.81cf8dfb558bdp-6, 0x1.8fad79af6c955p-3, -0x1.1696bad2792bap-5, 0x1.daa7e9dc56c9bp-6, + -0x1.8a35656c96049p-4, 0x1.dbfddb9c31ebep-9, -0x1.c56c8366be4d8p-6, 0x1.1d092fa33a5f2p-4, + -0x1.d75ae74b80f4bp-5, -0x1.9bf7107c508b4p-6, 0x1.2346879ec0b5cp-3, 0x1.63209eb19c3e5p-4, + 0x1.37fea60205d0ap-4, 0x1.23293957fcffdp-6, 0x1.e761d6a8a9d89p-4, -0x1.dd532bb0a292bp-5, + 0x1.64b2a3039f81bp-9, -0x1.2a649b13aaa3cp-3, -0x1.045c5eb87a968p-4, 0x1.b67ef9f6a7793p-4, + -0x1.35008afa3932bp-5, 0x1.321053444d67dp-4, 0x1.e476a3ff878f1p-6, -0x1.31f77a6142adep-4, + -0x1.31f77a6142adep-4, 0x1.e476a3ff878f1p-6, 0x1.321053444d67dp-4, -0x1.35008afa3932bp-5, + 0x1.b67ef9f6a7793p-4, -0x1.045c5eb87a968p-4, -0x1.2a649b13aaa3cp-3, 0x1.64b2a3039f81bp-9, + -0x1.dd532bb0a292bp-5, 0x1.e761d6a8a9d89p-4, 0x1.23293957fcffdp-6, 0x1.37fea60205d0ap-4, + 0x1.63209eb19c3e5p-4, 0x1.2346879ec0b5cp-3, -0x1.9bf7107c508b4p-6, -0x1.d75ae74b80f4bp-5, + 0x1.1d092fa33a5f2p-4, -0x1.c56c8366be4d8p-6, 0x1.dbfddb9c31ebep-9, -0x1.8a35656c96049p-4, + 0x1.daa7e9dc56c9bp-6, -0x1.1696bad2792bap-5, 0x1.8fad79af6c955p-3, 0x1.81cf8dfb558bdp-6, + 0x1.0121c1446610cp-5, -0x1.21d0780c905e2p-4, 0x1.ee23d5c1421cfp-6, 0x1.f71a29ea12b38p-4, + 0x1.6996147e4588dp-4, -0x1.b00d09712b072p-5, -0x1.fbeb0e488d214p-8, 0x1.23a2731d6e97fp-3, + 0x1.c20c921c40c2ap-7, -0x1.b124bdb4108b7p-6, -0x1.1a1b7f321d4e0p-7, -0x1.13eff37ca1bf6p-7, + 0x1.9c9cbb9559e73p-6, 0x1.b3fe7f16fc949p-3, 0x1.ab8551e4f0a78p-3, 0x1.81acfddb10465p-5, + 0x1.7343f03ce5a3bp-5, 0x1.5094aca42e303p-3, 0x1.338080c03ade0p-7, -0x1.e487a6c503bcfp-4, + 0x1.9dc32cf6063b6p-3, -0x1.1673a9bbdf8b5p-11, 0x1.d21b6ae3411bep-5, 0x1.9c4646f2c1fbfp-4, + -0x1.f23db4ff55d7cp-6, 0x1.25e9e48fbfa45p-4, 0x1.53b1b4da439acp-3, -0x1.f0174cf56ef61p-6, + -0x1.25429bc8d62d0p-11, -0x1.7a493d36e52bep-3, 0x1.195aace9cc73bp-4, -0x1.958ff17b6bb88p-6, + 0x1.688b03091923cp-9, -0x1.3ded1527db6f7p-4, 0x1.8ac6b86f12df4p-6, -0x1.ffe2c822a50d4p-6, + -0x1.c69d28bf1a9ddp-4, -0x1.564a9f0a9ca75p-8, -0x1.08548a36f4330p-6, -0x1.581f9eac29bafp-5, + 0x1.4f176c9002c72p-5, 0x1.a9681368d5294p-5, 0x1.a382d246f1ab1p-5, -0x1.c58873045d376p-6, + -0x1.90a48dbedf5d8p-8, -0x1.34291624eebb7p-3, 0x1.f9fc8e2c2a0aep-10, -0x1.5d3f7a537d74dp-5, + -0x1.0756e58ee1e2bp-5, 0x1.f6260b4714df2p-6, -0x1.a7c7e242d6d2cp-5, -0x1.d607901e0e8dbp-4, + 0x1.368d88e8548aep-3, 0x1.38c38e59b2a04p-5, 0x1.b904d282ea33dp-6, -0x1.7dc69f85dfe21p-4, + 0x1.049273bddf37bp-5, -0x1.62f738c8b3e9ep-3, 0x1.19734c5d0c2edp-3, 0x1.825f75a01e0c5p-5, + 0x1.41f60d4009806p-5, 0x1.11097721ba127p-7, 0x1.1577be8f51dcbp-3, -0x1.d61b43ab61ab8p-5, + -0x1.fc65892aabdd4p-4, 0x1.edf68972c5189p-7, 0x1.4f8e4b3028844p-5, -0x1.1545509bfecc0p-3, + 0x1.c76f92ad2de03p-4, -0x1.72172dfce88dap-5, -0x1.f371198ac2af4p-4, -0x1.5260a35007391p-4, + 0x1.84b9f204e06e2p-6, -0x1.429f2c23c771dp-5, 0x1.e28d970f5a8d8p-6, 0x1.10356ac23ebaep-7, + -0x1.af853c013f941p-7, 0x1.59ff50c35a178p-6, -0x1.70e98181448acp-4, -0x1.359525c332c33p-3, + -0x1.62dae02d04eedp-3, 0x1.2fa0b66f1e37fp-5, -0x1.c719ea137676dp-6, -0x1.918cbec7607cap-6, + 0x1.10639ed67d466p-5, 0x1.937213dbb6975p-15, 0x1.eb7dbb95057d0p-6, -0x1.1a4eadc46e180p-7, + -0x1.39b29d284d0a7p-8, 0x1.bcfa05a666d95p-3, -0x1.d76d594b6b18fp-3, -0x1.a4a3f2ba0747fp-6, + -0x1.28b5ed05eefeap-6, -0x1.01e877c68e303p-4, 0x1.31b174ed3142ap-9, -0x1.b0c2fb2358215p-4, + 0x1.d672d485815dep-3, -0x1.9e181c8fc01fcp-5, 0x1.e1c24ef00dd13p-4, 0x1.c8387677d9199p-7, + -0x1.f1da190c05db2p-5, -0x1.6f74638cd0767p-4, -0x1.6d464c026f824p-5, -0x1.7362ae002e232p-11, + -0x1.7362ae002e232p-11, -0x1.6d464c026f824p-5, -0x1.6f74638cd0767p-4, -0x1.f1da190c05db2p-5, + 0x1.c8387677d9199p-7, 0x1.e1c24ef00dd13p-4, -0x1.9e181c8fc01fcp-5, 0x1.d672d485815dep-3, + -0x1.b0c2fb2358215p-4, 0x1.31b174ed3142ap-9, -0x1.01e877c68e303p-4, -0x1.28b5ed05eefeap-6, + -0x1.a4a3f2ba0747fp-6, -0x1.d76d594b6b18fp-3, 0x1.bcfa05a666d95p-3, -0x1.39b29d284d0a7p-8, + -0x1.1a4eadc46e180p-7, 0x1.eb7dbb95057d0p-6, 0x1.937213dbb6975p-15, 0x1.10639ed67d466p-5, + -0x1.918cbec7607cap-6, -0x1.c719ea137676dp-6, 0x1.2fa0b66f1e37fp-5, -0x1.62dae02d04eedp-3, + -0x1.359525c332c33p-3, -0x1.70e98181448acp-4, 0x1.59ff50c35a178p-6, -0x1.af853c013f941p-7, + 0x1.10356ac23ebaep-7, 0x1.e28d970f5a8d8p-6, -0x1.429f2c23c771dp-5, 0x1.84b9f204e06e2p-6, + -0x1.5260a35007391p-4, -0x1.f371198ac2af4p-4, -0x1.72172dfce88dap-5, 0x1.c76f92ad2de03p-4, + -0x1.1545509bfecc0p-3, 0x1.4f8e4b3028844p-5, 0x1.edf68972c5189p-7, -0x1.fc65892aabdd4p-4, + -0x1.d61b43ab61ab8p-5, 0x1.1577be8f51dcbp-3, 0x1.11097721ba127p-7, 0x1.41f60d4009806p-5, + 0x1.825f75a01e0c5p-5, 0x1.19734c5d0c2edp-3, -0x1.62f738c8b3e9ep-3, 0x1.049273bddf37bp-5, + -0x1.7dc69f85dfe21p-4, 0x1.b904d282ea33dp-6, 0x1.38c38e59b2a04p-5, 0x1.368d88e8548aep-3, + -0x1.d607901e0e8dbp-4, -0x1.a7c7e242d6d2cp-5, 0x1.f6260b4714df2p-6, -0x1.0756e58ee1e2bp-5, + -0x1.5d3f7a537d74cp-5, 0x1.f9fc8e2c2a0cep-10, -0x1.34291624eebbap-3, -0x1.90a48dbedf52cp-8, + -0x1.c58873045d37bp-6, 0x1.a382d246f1ab5p-5, 0x1.a96813247067bp-5, 0x1.4f176d4454f12p-5, + -0x1.21a79abee5e5bp-4, -0x1.a630916029d68p-4, 0x1.f2252fa175ff3p-4, -0x1.d934fafdd5befp-6, + -0x1.139f0f6deb742p-6, 0x1.fb5797e98d998p-4, -0x1.c08c41ee3c542p-4, -0x1.edc195735887ap-5, + 0x1.87c400f207d95p-4, -0x1.49a44a8a779efp-4, 0x1.4d1e21479563ep-5, 0x1.e426a5b19a9f2p-4, + -0x1.ffa72ebf4cb4ap-4, -0x1.2d864dc7a0f11p-8, 0x1.9372a90eaf70bp-5, -0x1.d69617e4d38e9p-4, + 0x1.6e7445621b0c7p-4, 0x1.6591926d2eb2cp-4, -0x1.d17e7747403abp-4, 0x1.aa6c826791da3p-5, + -0x1.f656e33ff3457p-8, -0x1.ff0955a72066fp-4, 0x1.e817b9a6e2a2cp-4, 0x1.35410c00cbd7cp-5, + -0x1.3fed93dd0a71cp-4, 0x1.8fbcc971ddf1ap-4, -0x1.01cfc82406d33p-4, -0x1.ba5aa5eae0111p-4, + 0x1.f97f91bb76705p-4, -0x1.4557716b2cfa9p-6, -0x1.a82a05e9bc012p-6, 0x1.f4e603792e9c2p-4, + -0x1.ad2bcc6bc8020p-4, -0x1.1734d68fcf6d6p-4, 0x1.9ef43f3edac69p-4, -0x1.2bedb0531424ep-4, + 0x1.04fb804ddd3e2p-5, 0x1.ef17890e507fcp-4, -0x1.fce1606f36351p-4, -0x1.c3786a0aa018dp-7, + 0x1.d797731c40a06p-5, -0x1.c678b4de70c72p-4, 0x1.53282571b0195p-4, 0x1.7f8ecd8014098p-4, + -0x1.dfeae5e754611p-4, 0x1.64c7df55c188bp-5, 0x1.921d4aa84a44ep-10, -0x1.fff6208080f53p-4, + 0x1.db652729f651ep-4, 0x1.7c3a94bc9577ep-5, -0x1.5c77bd484e8dap-4, 0x1.771e748d041bbp-4, + -0x1.c1249bdef5af3p-5, -0x1.cc1f106d45869p-4, 0x1.fe1caf65d1f73p-4, -0x1.5f6d062b38feep-7, + -0x1.1d34426108a4bp-5, 0x1.ebbd8d5f6d144p-4, -0x1.9777ef4893781p-4, -0x1.36058a3dcfd0dp-4, + 0x1.b3e4d301d22d3p-4, -0x1.0c9706cbd369dp-4, 0x1.76dd935c55569p-6, 0x1.f7599c66fede2p-4, + -0x1.f7599c66fede2p-4, -0x1.76dd935c55569p-6, 0x1.0c9706cbd369dp-4, -0x1.b3e4d301d22d3p-4, + 0x1.36058a3dcfd0dp-4, 0x1.9777ef4893781p-4, -0x1.ebbd8d5f6d144p-4, 0x1.1d34426108a4bp-5, + 0x1.5f6d062b38feep-7, -0x1.fe1caf65d1f73p-4, 0x1.cc1f106d45869p-4, 0x1.c1249bdef5af3p-5, + -0x1.771e748d041bbp-4, 0x1.5c77bd484e8dap-4, -0x1.7c3a94bc9577ep-5, -0x1.db652729f651ep-4, + 0x1.fff6208080f53p-4, -0x1.921d4aa84a44ep-10, -0x1.64c7df55c188bp-5, 0x1.dfeae5e754611p-4, + -0x1.7f8ecd8014098p-4, -0x1.53282571b0195p-4, 0x1.c678b4de70c72p-4, -0x1.d797731c40a06p-5, + 0x1.c3786a0aa018dp-7, 0x1.fce1606f36351p-4, -0x1.ef17890e507fcp-4, -0x1.04fb804ddd3e2p-5, + 0x1.2bedb0531424ep-4, -0x1.9ef43f3edac69p-4, 0x1.1734d68fcf6d6p-4, 0x1.ad2bcc6bc8020p-4, + -0x1.f4e603792e9c2p-4, 0x1.a82a05e9bc012p-6, 0x1.4557716b2cfa9p-6, -0x1.f97f91bb76705p-4, + 0x1.ba5aa5eae0111p-4, 0x1.01cfc82406d33p-4, -0x1.8fbcc971ddf1ap-4, 0x1.3fed93dd0a71cp-4, + -0x1.35410c00cbd7cp-5, -0x1.e817b9a6e2a2cp-4, 0x1.ff0955a72066fp-4, 0x1.f656e33ff3457p-8, + -0x1.aa6c826791da3p-5, 0x1.d17e7747403abp-4, -0x1.6591926d2eb2cp-4, -0x1.6e7445621b0c7p-4, + 0x1.d69617e4d38e9p-4, -0x1.9372a90eaf70bp-5, 0x1.2d864dc7a0f11p-8, 0x1.ffa72ebf4cb4ap-4, + -0x1.e426a5b19a9f2p-4, -0x1.4d1e21479563ep-5, 0x1.49a44a8a779efp-4, -0x1.87c400f207d95p-4, + 0x1.edc195735887ap-5, 0x1.c08c41ee3c542p-4, -0x1.fb5797e98d998p-4, 0x1.139f0f6deb742p-6, + 0x1.d934fafdd5befp-6, -0x1.f2252fa175ff3p-4, 0x1.a630916029d58p-4, 0x1.21a79abee5e58p-4, + 0x1.a6309204824ecp-4, -0x1.21a79a7f234bdp-4, -0x1.d934fc5c1e18ep-6, -0x1.f2253188594b9p-4, + -0x1.fb57989e45ad2p-4, -0x1.139f0f93e7f9bp-6, -0x1.edc1975fd2c99p-5, 0x1.c08c41e94a1dep-4, + 0x1.49a44a262f938p-4, 0x1.87c3ffc9e7ca5p-4, 0x1.e426a68e30485p-4, -0x1.4d1e214a849fep-5, + 0x1.2d864ba455b1fp-8, -0x1.ffa72f8450fb4p-4, -0x1.d69618ac39285p-4, -0x1.9372a8d989fadp-5, + -0x1.6591925837563p-4, 0x1.6e74466146c4ap-4, 0x1.aa6c81ae4e953p-5, 0x1.d17e77a36dc0ep-4, + 0x1.ff0955024451ep-4, -0x1.f656e41bce7d4p-8, 0x1.35410c4d30d83p-5, -0x1.e817b90111041p-4, + -0x1.8fbccaafb9ddfp-4, -0x1.3fed946e869a6p-4, -0x1.ba5aa5f524cbcp-4, 0x1.01cfc72999958p-4, + 0x1.4557710fd5c8fp-6, 0x1.f97f91eee43e1p-4, 0x1.f4e6035808d22p-4, 0x1.a82a040e31befp-6, + 0x1.1734d687381e7p-4, -0x1.ad2bcb4ac19f8p-4, -0x1.2bedb082e903dp-4, -0x1.9ef43db91bc0ap-4, + -0x1.ef1789743a4e7p-4, 0x1.04fb807868c24p-5, -0x1.c3786b8de9226p-7, 0x1.fce1600a76772p-4, + 0x1.c678b49e2396ep-4, 0x1.d79771ddd1eddp-5, 0x1.7f8ece18a5ecap-4, -0x1.5328266ea88d9p-4, + -0x1.64c7dff018fcfp-5, -0x1.dfeae63c1688fp-4, -0x1.fff6218488854p-4, -0x1.921d515560d54p-10, + -0x1.7c3a944866a4fp-5, 0x1.db652540c837dp-4, 0x1.771e73cc79b9fp-4, 0x1.5c77bba40b50ep-4, + 0x1.cc1f10b7e71fdp-4, -0x1.c1249c55c38fcp-5, -0x1.5f6d0627b8cdcp-7, -0x1.fe1caeef8e1dap-4, + -0x1.ebbd8b1cd18afp-4, -0x1.1d3441a11d4fep-5, -0x1.36058b0b228c5p-4, 0x1.9777ee35df550p-4, + 0x1.0c9705cc7edeap-4, 0x1.b3e4d59235a1ap-4, 0x1.f7599c095e8d1p-4, -0x1.76dd92796a840p-6, + 0x1.76dd92796a840p-6, -0x1.f7599c095e8d1p-4, -0x1.b3e4d59235a1ap-4, -0x1.0c9705cc7edeap-4, + -0x1.9777ee35df550p-4, 0x1.36058b0b228c5p-4, 0x1.1d3441a11d4fep-5, 0x1.ebbd8b1cd18afp-4, + 0x1.fe1caeef8e1dap-4, 0x1.5f6d0627b8cdcp-7, 0x1.c1249c55c38fcp-5, -0x1.cc1f10b7e71fdp-4, + -0x1.5c77bba40b50ep-4, -0x1.771e73cc79b9fp-4, -0x1.db652540c837dp-4, 0x1.7c3a944866a4fp-5, + 0x1.921d515560d54p-10, 0x1.fff6218488854p-4, 0x1.dfeae63c1688fp-4, 0x1.64c7dff018fcfp-5, + 0x1.5328266ea88d9p-4, -0x1.7f8ece18a5ecap-4, -0x1.d79771ddd1eddp-5, -0x1.c678b49e2396ep-4, + -0x1.fce1600a76772p-4, 0x1.c3786b8de9226p-7, -0x1.04fb807868c24p-5, 0x1.ef1789743a4e7p-4, + 0x1.9ef43db91bc0ap-4, 0x1.2bedb082e903dp-4, 0x1.ad2bcb4ac19f8p-4, -0x1.1734d687381e7p-4, + -0x1.a82a040e31befp-6, -0x1.f4e6035808d22p-4, -0x1.f97f91eee43e1p-4, -0x1.4557710fd5c8fp-6, + -0x1.01cfc72999958p-4, 0x1.ba5aa5f524cbcp-4, 0x1.3fed946e869a6p-4, 0x1.8fbccaafb9ddfp-4, + 0x1.e817b90111041p-4, -0x1.35410c4d30d83p-5, 0x1.f656e41bce7d4p-8, -0x1.ff0955024451ep-4, + -0x1.d17e77a36dc0ep-4, -0x1.aa6c81ae4e953p-5, -0x1.6e74466146c4ap-4, 0x1.6591925837563p-4, + 0x1.9372a8d989fadp-5, 0x1.d69618ac39285p-4, 0x1.ffa72f8450fb4p-4, -0x1.2d864ba455b1fp-8, + 0x1.4d1e214a849fep-5, -0x1.e426a68e30485p-4, -0x1.87c3ffc9e7ca5p-4, -0x1.49a44a262f938p-4, + -0x1.c08c41e94a1dep-4, 0x1.edc1975fd2c99p-5, 0x1.139f0f93e7f9bp-6, 0x1.fb57989e45ad2p-4, + 0x1.f2253188594b9p-4, 0x1.d934fc5c1e18ep-6, 0x1.21a79a7f234bdp-4, -0x1.a6309204824dap-4, + 0x1.c7173c7c3ff00p-4, 0x1.5d9b9bbcf20aep-8, 0x1.6b07a70939eb4p-5, 0x1.bd86190c89642p-3, + -0x1.b348f18d60f5fp-5, 0x1.959038579d8e2p-13, 0x1.315cc48fc0fefp-4, -0x1.44a94bb0441c7p-6, + 0x1.917877c76eb0ep-5, 0x1.2879510a3a527p-4, -0x1.7d09d5cd0fe3ep-4, -0x1.3a77b780af6dcp-5, + 0x1.44bf3470792b7p-6, 0x1.2cee53aa8ca57p-3, 0x1.084229daaaa74p-4, -0x1.993a1227c8e63p-6, + -0x1.cf78bd93fe27ap-5, -0x1.1a08e5f11bd33p-4, -0x1.98c90b430d1bfp-6, 0x1.9b281903deb97p-6, + -0x1.3f277c7b30573p-4, 0x1.3042dca64aa83p-7, 0x1.6207648870d85p-5, -0x1.2a367f7e66931p-3, + 0x1.91c15b6c3a0bdp-4, 0x1.9be489930d1d3p-6, -0x1.5d172da922c0fp-5, 0x1.0c8c0c2452a6ep-4, + -0x1.ef5c00a08c3c1p-6, 0x1.f9759dc4674c9p-4, 0x1.f643edf587399p-6, 0x1.131d376d3f22ep-5, + -0x1.0a13fc45c8f56p-3, -0x1.26bb9b7d27125p-4, 0x1.8dd2b1ec9896cp-6, -0x1.0f4fbe140d46dp-3, + -0x1.70883a2080bd0p-5, -0x1.46d492ac2d726p-7, 0x1.918fe2b58b64ep-6, 0x1.c71c1545f4aa9p-4, + -0x1.32cadd2e8d46ep-4, 0x1.e90a0d58c4abfp-5, -0x1.9922dbc8496d8p-7, -0x1.61169509980cap-6, + -0x1.f821d655ad74bp-5, 0x1.b4cc2c63ccfc3p-4, 0x1.e2c2bef5f16c2p-3, 0x1.1b41142b4469fp-6, + -0x1.e8885ae41529cp-8, 0x1.0169f665515d6p-3, 0x1.c0d70b8ea1755p-5, 0x1.0e29f150ace29p-3, + -0x1.0c25a3abdd362p-3, 0x1.330b1aa556395p-5, -0x1.464750245a6bbp-9, -0x1.b51e74ce8521ep-3, + -0x1.44061d8de7807p-4, 0x1.33f5b0c0ca698p-7, 0x1.10c10a786002bp-3, 0x1.0a18132285471p-7, + 0x1.521e4eac6b668p-4, -0x1.9e2313419cb77p-3, 0x1.3405ce14482a3p-6, -0x1.db72412e59d1ep-5, + 0x1.db72412e59d1ep-5, -0x1.3405ce14482a3p-6, 0x1.9e2313419cb77p-3, -0x1.521e4eac6b668p-4, + -0x1.0a18132285471p-7, -0x1.10c10a786002bp-3, -0x1.33f5b0c0ca698p-7, 0x1.44061d8de7807p-4, + 0x1.b51e74ce8521ep-3, 0x1.464750245a6bbp-9, -0x1.330b1aa556395p-5, 0x1.0c25a3abdd362p-3, + -0x1.0e29f150ace29p-3, -0x1.c0d70b8ea1755p-5, -0x1.0169f665515d6p-3, 0x1.e8885ae41529cp-8, + -0x1.1b41142b4469fp-6, -0x1.e2c2bef5f16c2p-3, -0x1.b4cc2c63ccfc3p-4, 0x1.f821d655ad74bp-5, + 0x1.61169509980cap-6, 0x1.9922dbc8496d8p-7, -0x1.e90a0d58c4abfp-5, 0x1.32cadd2e8d46ep-4, + -0x1.c71c1545f4aa9p-4, -0x1.918fe2b58b64ep-6, 0x1.46d492ac2d726p-7, 0x1.70883a2080bd0p-5, + 0x1.0f4fbe140d46dp-3, -0x1.8dd2b1ec9896cp-6, 0x1.26bb9b7d27125p-4, 0x1.0a13fc45c8f56p-3, + -0x1.131d376d3f22ep-5, -0x1.f643edf587399p-6, -0x1.f9759dc4674c9p-4, 0x1.ef5c00a08c3c1p-6, + -0x1.0c8c0c2452a6ep-4, 0x1.5d172da922c0fp-5, -0x1.9be489930d1d3p-6, -0x1.91c15b6c3a0bdp-4, + 0x1.2a367f7e66931p-3, -0x1.6207648870d85p-5, -0x1.3042dca64aa83p-7, 0x1.3f277c7b30573p-4, + -0x1.9b281903deb97p-6, 0x1.98c90b430d1bfp-6, 0x1.1a08e5f11bd33p-4, 0x1.cf78bd93fe27ap-5, + 0x1.993a1227c8e63p-6, -0x1.084229daaaa74p-4, -0x1.2cee53aa8ca57p-3, -0x1.44bf3470792b7p-6, + 0x1.3a77b780af6dcp-5, 0x1.7d09d5cd0fe3ep-4, -0x1.2879510a3a527p-4, -0x1.917877c76eb0ep-5, + 0x1.44a94bb0441c7p-6, -0x1.315cc48fc0feep-4, -0x1.959038579d270p-13, 0x1.b348f18d60f63p-5, + -0x1.bd86190c8963fp-3, -0x1.6b07a70939ea7p-5, -0x1.5d9b9afdad231p-8, -0x1.c7173c6c70cbap-4, + 0x1.5c4bb5dc94aecp-7, -0x1.1c1fe27d242d0p-3, 0x1.7e7570fe62a7bp-6, 0x1.8ccb647da4312p-9, + -0x1.eb86fd981787fp-8, -0x1.7984f71976a95p-4, -0x1.5bc50669e8ff3p-4, -0x1.73f1cfb4157fbp-5, + -0x1.1be520c9a466cp-5, 0x1.20a8b1218899ap-5, 0x1.c5cadee957853p-5, 0x1.792fe18f74a63p-3, + 0x1.2877e5dd5c5bep-3, -0x1.7a696aaf4e2c1p-7, -0x1.75b5b475554cep-7, -0x1.61412832030cbp-11, + 0x1.7c8c3b787f5ffp-3, -0x1.45c8ff7e1b5b5p-7, -0x1.61cc0cdea4cd6p-9, -0x1.8daff777943eep-7, + 0x1.1fea9f9a56d60p-8, 0x1.8362a6aa09127p-4, 0x1.8b855661f7d00p-3, -0x1.d16158e5f0d97p-9, + 0x1.eca652ec0a1e6p-5, 0x1.f545faa14caf1p-5, 0x1.06dd4be8f4e1cp-5, -0x1.eec14a1253af9p-6, + 0x1.69cad10d12496p-4, 0x1.b7a6201c80a8bp-7, 0x1.7c23f3a27deeep-5, 0x1.909d91da6529fp-5, + 0x1.4f77b83eb40c3p-4, 0x1.7404192f44c0dp-9, -0x1.cec214407f56dp-4, 0x1.3914b33a97516p-4, + -0x1.5f7bfda3ca81ap-6, 0x1.36d7f6b0f32bfp-2, 0x1.317f4b36c050ap-4, 0x1.3c486ece9744bp-7, + 0x1.aa7f8845b4223p-6, -0x1.a7830d92e7999p-6, -0x1.35898c69f9300p-6, 0x1.23d4bdb13a2eap-3, + 0x1.a5442e7624ceep-4, 0x1.7a56e30168a17p-5, -0x1.7b4479687275ep-6, 0x1.1f3050bc13a55p-3, + -0x1.a5ee8ea7d752fp-6, -0x1.18c36a0e86185p-5, 0x1.691c9642b9c8ap-5, -0x1.160faccefa3d1p-4, + -0x1.e8f7fea6faae7p-5, -0x1.0d846990db79ep-7, -0x1.0c1816cfcfbedp-4, 0x1.f0ea8cd1cc89fp-8, + -0x1.5d39f841438dap-8, -0x1.f7bc0d74da006p-4, 0x1.528e13525eaf6p-3, 0x1.29457cea9a779p-6, + 0x1.7e59616fb5297p-3, -0x1.e6509423cec44p-18, 0x1.ac73b22d7bcdbp-6, -0x1.4725a8f9fc228p-3, + 0x1.4725a8f9fc228p-3, -0x1.ac73b22d7bcdbp-6, 0x1.e6509423cec44p-18, -0x1.7e59616fb5297p-3, + -0x1.29457cea9a779p-6, -0x1.528e13525eaf6p-3, 0x1.f7bc0d74da006p-4, 0x1.5d39f841438dap-8, + -0x1.f0ea8cd1cc89fp-8, 0x1.0c1816cfcfbedp-4, 0x1.0d846990db79ep-7, 0x1.e8f7fea6faae7p-5, + 0x1.160faccefa3d1p-4, -0x1.691c9642b9c8ap-5, 0x1.18c36a0e86185p-5, 0x1.a5ee8ea7d752fp-6, + -0x1.1f3050bc13a55p-3, 0x1.7b4479687275ep-6, -0x1.7a56e30168a17p-5, -0x1.a5442e7624ceep-4, + -0x1.23d4bdb13a2eap-3, 0x1.35898c69f9300p-6, 0x1.a7830d92e7999p-6, -0x1.aa7f8845b4223p-6, + -0x1.3c486ece9744bp-7, -0x1.317f4b36c050ap-4, -0x1.36d7f6b0f32bfp-2, 0x1.5f7bfda3ca81ap-6, + -0x1.3914b33a97516p-4, 0x1.cec214407f56dp-4, -0x1.7404192f44c0dp-9, -0x1.4f77b83eb40c3p-4, + -0x1.909d91da6529fp-5, -0x1.7c23f3a27deeep-5, -0x1.b7a6201c80a8bp-7, -0x1.69cad10d12496p-4, + 0x1.eec14a1253af9p-6, -0x1.06dd4be8f4e1cp-5, -0x1.f545faa14caf1p-5, -0x1.eca652ec0a1e6p-5, + 0x1.d16158e5f0d97p-9, -0x1.8b855661f7d00p-3, -0x1.8362a6aa09127p-4, -0x1.1fea9f9a56d60p-8, + 0x1.8daff777943eep-7, 0x1.61cc0cdea4cd6p-9, 0x1.45c8ff7e1b5b5p-7, -0x1.7c8c3b787f5ffp-3, + 0x1.61412832030cbp-11, 0x1.75b5b475554cep-7, 0x1.7a696aaf4e2c1p-7, -0x1.2877e5dd5c5bep-3, + -0x1.792fe18f74a63p-3, -0x1.c5cadee957853p-5, -0x1.20a8b1218899ap-5, 0x1.1be520c9a466cp-5, + 0x1.73f1cfb415803p-5, 0x1.5bc50669e8ff5p-4, 0x1.7984f71976a8dp-4, 0x1.eb86fd98178b2p-8, + -0x1.8ccb647da42fep-9, -0x1.7e7570fe62a8bp-6, 0x1.1c1fe39feda04p-3, -0x1.5c4bb49489b7cp-7, + -0x1.2bedb2c656405p-4, -0x1.9ef43fbf89a1cp-4, 0x1.e817b62ce21c0p-4, -0x1.35410c8b6bccbp-5, + -0x1.921d2da18db6dp-10, 0x1.fff62126ea5c5p-4, -0x1.e426a54191891p-4, -0x1.4d1e23764d282p-5, + 0x1.36058a3281607p-4, -0x1.9777f011e46bep-4, 0x1.21a79bc5fb902p-4, 0x1.a6309112e469ap-4, + -0x1.ebbd8e46a4961p-4, 0x1.1d34432e2ca40p-5, 0x1.2d8685d2d712cp-8, -0x1.ffa731188b76cp-4, + 0x1.dfeae56b7bbafp-4, 0x1.64c7e0927ddb1p-5, -0x1.3fed90c5bd71fp-4, 0x1.8fbcca64f3ad8p-4, + -0x1.1734d55123e42p-4, -0x1.ad2bcdc23144fp-4, 0x1.ef17884134031p-4, -0x1.04fb835be6a58p-5, + -0x1.f656db0c271bap-8, 0x1.ff09565551cc0p-4, -0x1.db65290c55260p-4, -0x1.7c3a925e86251p-5, + 0x1.49a448e3dc976p-4, -0x1.87c3ff646154ap-4, 0x1.0c9705b743cc9p-4, 0x1.b3e4d008e9f04p-4, + -0x1.f2252f6c76fd7p-4, 0x1.d934fb731acd3p-6, 0x1.5f6d0ba650192p-7, -0x1.fe1cadb6df3c0p-4, + 0x1.d696147c68c3fp-4, 0x1.9372a80329f2ep-5, -0x1.53282bc026115p-4, 0x1.7f8ecf175b2c8p-4, + -0x1.01cfc8fcdb9b7p-4, -0x1.ba5aa3f6e8106p-4, 0x1.f4e605e0ebc21p-4, -0x1.a82a0bd82e8fdp-6, + -0x1.c378662a5ec0fp-7, 0x1.fce1619e450a2p-4, -0x1.d17e7703781f3p-4, -0x1.aa6c80fdd5f6bp-5, + 0x1.5c77b935a46c6p-4, -0x1.771e74d65dd36p-4, 0x1.edc19554d9dd9p-5, 0x1.c08c40a173aa0p-4, + -0x1.f7599c58b2fd1p-4, 0x1.76dd916bf8b38p-6, 0x1.139f0a532f5adp-6, -0x1.fb579958a33aap-4, + 0x1.cc1f1217e0f6fp-4, 0x1.c1249b08026ddp-5, -0x1.659191e801467p-4, 0x1.6e744596780c8p-4, + -0x1.d797753e2bf77p-5, -0x1.c678b2432cd3dp-4, 0x1.f97f94717c3a1p-4, -0x1.4557680b1a2e5p-6, + -0x1.4557680b1a2e5p-6, 0x1.f97f94717c3a1p-4, -0x1.c678b2432cd3dp-4, -0x1.d797753e2bf77p-5, + 0x1.6e744596780c8p-4, -0x1.659191e801467p-4, 0x1.c1249b08026ddp-5, 0x1.cc1f1217e0f6fp-4, + -0x1.fb579958a33aap-4, 0x1.139f0a532f5adp-6, 0x1.76dd916bf8b38p-6, -0x1.f7599c58b2fd1p-4, + 0x1.c08c40a173aa0p-4, 0x1.edc19554d9dd9p-5, -0x1.771e74d65dd36p-4, 0x1.5c77b935a46c6p-4, + -0x1.aa6c80fdd5f6bp-5, -0x1.d17e7703781f3p-4, 0x1.fce1619e450a2p-4, -0x1.c378662a5ec0fp-7, + -0x1.a82a0bd82e8fdp-6, 0x1.f4e605e0ebc21p-4, -0x1.ba5aa3f6e8106p-4, -0x1.01cfc8fcdb9b7p-4, + 0x1.7f8ecf175b2c8p-4, -0x1.53282bc026115p-4, 0x1.9372a80329f2ep-5, 0x1.d696147c68c3fp-4, + -0x1.fe1cadb6df3c0p-4, 0x1.5f6d0ba650192p-7, 0x1.d934fb731acd3p-6, -0x1.f2252f6c76fd7p-4, + 0x1.b3e4d008e9f04p-4, 0x1.0c9705b743cc9p-4, -0x1.87c3ff646154ap-4, 0x1.49a448e3dc976p-4, + -0x1.7c3a925e86251p-5, -0x1.db65290c55260p-4, 0x1.ff09565551cc0p-4, -0x1.f656db0c271bap-8, + -0x1.04fb835be6a58p-5, 0x1.ef17884134031p-4, -0x1.ad2bcdc23144fp-4, -0x1.1734d55123e42p-4, + 0x1.8fbcca64f3ad8p-4, -0x1.3fed90c5bd71fp-4, 0x1.64c7e0927ddb1p-5, 0x1.dfeae56b7bbafp-4, + -0x1.ffa731188b76cp-4, 0x1.2d8685d2d712cp-8, 0x1.1d34432e2ca40p-5, -0x1.ebbd8e46a4961p-4, + 0x1.a6309112e469ap-4, 0x1.21a79bc5fb902p-4, -0x1.9777f011e46bep-4, 0x1.36058a3281607p-4, + -0x1.4d1e23764d282p-5, -0x1.e426a54191891p-4, 0x1.fff62126ea5c5p-4, -0x1.921d2da18db6dp-10, + -0x1.35410c8b6bccbp-5, 0x1.e817b62ce21c0p-4, -0x1.9ef43fbf89a3fp-4, -0x1.2bedb2c656408p-4, + 0x1.9ef43f5d642c0p-4, -0x1.2bedb2e8f4855p-4, -0x1.35410bb372527p-5, -0x1.e817b60c7d43cp-4, + -0x1.fff621b198ed3p-4, -0x1.921d24b8ece10p-10, -0x1.4d1e24153f98ap-5, 0x1.e426a3ae122e3p-4, + 0x1.9777ef15a5767p-4, 0x1.36058a1cf9209p-4, 0x1.a6309007b672fp-4, -0x1.21a79cb74c686p-4, + -0x1.1d34430a409edp-5, -0x1.ebbd8da7a699ep-4, -0x1.ffa73213a72b9p-4, -0x1.2d868818e6da2p-8, + -0x1.64c7dfe945d6ep-5, 0x1.dfeae523fabc6p-4, 0x1.8fbcca9c07748p-4, 0x1.3fed9147a1a48p-4, + 0x1.ad2bcd21193e9p-4, -0x1.1734d510322d5p-4, -0x1.04fb83c3d4c4bp-5, -0x1.ef178847e6b58p-4, + -0x1.ff095630cc3c2p-4, -0x1.f656d9a654e4cp-8, -0x1.7c3a91d6a78d5p-5, 0x1.db6529493888fp-4, + 0x1.87c3feecc63c4p-4, 0x1.49a4491f0f7f0p-4, 0x1.b3e4d179cd917p-4, -0x1.0c97060c3e60ep-4, + -0x1.d934fb07a1141p-6, -0x1.f2253062c7b0dp-4, -0x1.fe1cad3a533b0p-4, -0x1.5f6d0be13f29ap-7, + -0x1.9372a886ef90dp-5, 0x1.d6961514b6477p-4, 0x1.7f8ecef3650f4p-4, 0x1.53282b906bccep-4, + 0x1.ba5aa5cf19d80p-4, -0x1.01cfc9b9ebd4ep-4, -0x1.a82a0c3321c03p-6, -0x1.f4e60621b5bccp-4, + -0x1.fce1605a90948p-4, -0x1.c378657ccdbefp-7, -0x1.aa6c819cead7fp-5, 0x1.d17e76664b096p-4, + 0x1.771e747d3bb16p-4, 0x1.5c77b7f8e97c1p-4, 0x1.c08c40d1cb9fep-4, -0x1.edc197aa554d5p-5, + -0x1.76dd92b6a71f8p-6, -0x1.f7599dc0bc2bfp-4, -0x1.fb579802bf195p-4, -0x1.139f09bb3a3cfp-6, + -0x1.c1249b4fd13cbp-5, 0x1.cc1f11a2e5293p-4, 0x1.6e74451da0b08p-4, 0x1.659190bf4e038p-4, + 0x1.c678b1c168e3cp-4, -0x1.d79775f5d05f2p-5, -0x1.4557678605694p-6, -0x1.f97f9697dc8a3p-4, + -0x1.f97f9697dc8a3p-4, -0x1.4557678605694p-6, -0x1.d79775f5d05f2p-5, 0x1.c678b1c168e3cp-4, + 0x1.659190bf4e038p-4, 0x1.6e74451da0b08p-4, 0x1.cc1f11a2e5293p-4, -0x1.c1249b4fd13cbp-5, + -0x1.139f09bb3a3cfp-6, -0x1.fb579802bf195p-4, -0x1.f7599dc0bc2bfp-4, -0x1.76dd92b6a71f8p-6, + -0x1.edc197aa554d5p-5, 0x1.c08c40d1cb9fep-4, 0x1.5c77b7f8e97c1p-4, 0x1.771e747d3bb16p-4, + 0x1.d17e76664b096p-4, -0x1.aa6c819cead7fp-5, -0x1.c378657ccdbefp-7, -0x1.fce1605a90948p-4, + -0x1.f4e60621b5bccp-4, -0x1.a82a0c3321c03p-6, -0x1.01cfc9b9ebd4ep-4, 0x1.ba5aa5cf19d80p-4, + 0x1.53282b906bccep-4, 0x1.7f8ecef3650f4p-4, 0x1.d6961514b6477p-4, -0x1.9372a886ef90dp-5, + -0x1.5f6d0be13f29ap-7, -0x1.fe1cad3a533b0p-4, -0x1.f2253062c7b0dp-4, -0x1.d934fb07a1141p-6, + -0x1.0c97060c3e60ep-4, 0x1.b3e4d179cd917p-4, 0x1.49a4491f0f7f0p-4, 0x1.87c3feecc63c4p-4, + 0x1.db6529493888fp-4, -0x1.7c3a91d6a78d5p-5, -0x1.f656d9a654e4cp-8, -0x1.ff095630cc3c2p-4, + -0x1.ef178847e6b58p-4, -0x1.04fb83c3d4c4bp-5, -0x1.1734d510322d5p-4, 0x1.ad2bcd21193e9p-4, + 0x1.3fed9147a1a48p-4, 0x1.8fbcca9c07748p-4, 0x1.dfeae523fabc6p-4, -0x1.64c7dfe945d6ep-5, + -0x1.2d868818e6da2p-8, -0x1.ffa73213a72b9p-4, -0x1.ebbd8da7a699ep-4, -0x1.1d34430a409edp-5, + -0x1.21a79cb74c686p-4, 0x1.a6309007b672fp-4, 0x1.36058a1cf9209p-4, 0x1.9777ef15a5767p-4, + 0x1.e426a3ae122e3p-4, -0x1.4d1e24153f98ap-5, -0x1.921d24b8ece10p-10, -0x1.fff621b198ed3p-4, + -0x1.e817b60c7d43cp-4, -0x1.35410bb372527p-5, -0x1.2bedb2e8f4855p-4, 0x1.9ef43f5d642ccp-4, + -0x1.3c8cd9d363e05p-3, -0x1.c8d7bb1eb0af6p-6, -0x1.456db37329e69p-4, -0x1.36a890a67ff84p-3, + -0x1.579dfbc20973ap-6, -0x1.ff1fe588fe510p-6, 0x1.6f6d994a7bc2fp-7, 0x1.e9cddf02a4db8p-3, + -0x1.5705d715da0c9p-6, 0x1.e17ff7952e4acp-6, 0x1.af3a42f80aebbp-3, 0x1.5a217a0f6baf8p-5, + -0x1.918a4d1699350p-7, 0x1.abc7b54ce3fa4p-4, 0x1.fe653ec1191bep-4, 0x1.078c357f78744p-5, + -0x1.716497c490b37p-4, 0x1.b66f17fbae969p-4, -0x1.080c431dd2826p-4, 0x1.89e582b5dd319p-5, + -0x1.cf65be0225030p-5, 0x1.ea8dec18ac062p-8, -0x1.54d6a0a9486aep-5, -0x1.5a1e3ef592b59p-4, + 0x1.155f84de0fc21p-4, -0x1.30d0841b21764p-5, 0x1.42c3f7850417ep-4, -0x1.2001ba9efa239p-3, + 0x1.45ae5d81d5ffcp-4, -0x1.f5b68fd306469p-4, -0x1.5bb48f31f0bc6p-12, -0x1.2fe394a36cb18p-4, + 0x1.81447d31c4008p-6, 0x1.5b67eeb67a058p-4, 0x1.0756d18c1b584p-6, 0x1.048f3cc1ba8b4p-6, + 0x1.0f971604ee09cp-7, 0x1.41de761ebf05cp-4, -0x1.9a4f69c204e76p-4, -0x1.57b62e18c714bp-3, + -0x1.5bf65c5313c54p-8, 0x1.7d03f0ebaa815p-4, 0x1.0e0483729c44ep-8, 0x1.68aaf7103c34fp-4, + -0x1.24af9dd7f9f13p-3, -0x1.8f06f25a884ebp-6, 0x1.30220574ee0cdp-6, 0x1.1a429ee9eeb57p-4, + 0x1.3a07cfed6a43ep-4, 0x1.c7d3ca76a3771p-5, 0x1.54d14815fdb5bp-4, 0x1.a053d22a04e36p-5, + 0x1.9286fdb1d6dcep-6, 0x1.7267aee40084ep-3, -0x1.734aaed8ddea3p-3, 0x1.7b50fabd48c35p-8, + 0x1.99677a107b1e3p-5, -0x1.73423320c7cd1p-4, -0x1.5453490a90681p-4, -0x1.9625d13c26993p-9, + 0x1.a3db87595768ap-4, 0x1.5811f4d132447p-6, -0x1.8d58f1056fcc2p-6, 0x1.40d1387cb19e1p-4, + 0x1.40d1387cb19e1p-4, -0x1.8d58f1056fcc2p-6, 0x1.5811f4d132447p-6, 0x1.a3db87595768ap-4, + -0x1.9625d13c26993p-9, -0x1.5453490a90681p-4, -0x1.73423320c7cd1p-4, 0x1.99677a107b1e3p-5, + 0x1.7b50fabd48c35p-8, -0x1.734aaed8ddea3p-3, 0x1.7267aee40084ep-3, 0x1.9286fdb1d6dcep-6, + 0x1.a053d22a04e36p-5, 0x1.54d14815fdb5bp-4, 0x1.c7d3ca76a3771p-5, 0x1.3a07cfed6a43ep-4, + 0x1.1a429ee9eeb57p-4, 0x1.30220574ee0cdp-6, -0x1.8f06f25a884ebp-6, -0x1.24af9dd7f9f13p-3, + 0x1.68aaf7103c34fp-4, 0x1.0e0483729c44ep-8, 0x1.7d03f0ebaa815p-4, -0x1.5bf65c5313c54p-8, + -0x1.57b62e18c714bp-3, -0x1.9a4f69c204e76p-4, 0x1.41de761ebf05cp-4, 0x1.0f971604ee09cp-7, + 0x1.048f3cc1ba8b4p-6, 0x1.0756d18c1b584p-6, 0x1.5b67eeb67a058p-4, 0x1.81447d31c4008p-6, + -0x1.2fe394a36cb18p-4, -0x1.5bb48f31f0bc6p-12, -0x1.f5b68fd306469p-4, 0x1.45ae5d81d5ffcp-4, + -0x1.2001ba9efa239p-3, 0x1.42c3f7850417ep-4, -0x1.30d0841b21764p-5, 0x1.155f84de0fc21p-4, + -0x1.5a1e3ef592b59p-4, -0x1.54d6a0a9486aep-5, 0x1.ea8dec18ac062p-8, -0x1.cf65be0225030p-5, + 0x1.89e582b5dd319p-5, -0x1.080c431dd2826p-4, 0x1.b66f17fbae969p-4, -0x1.716497c490b37p-4, + 0x1.078c357f78744p-5, 0x1.fe653ec1191bep-4, 0x1.abc7b54ce3fa4p-4, -0x1.918a4d1699350p-7, + 0x1.5a217a0f6baf8p-5, 0x1.af3a42f80aebbp-3, 0x1.e17ff7952e4acp-6, -0x1.5705d715da0c9p-6, + 0x1.e9cddf02a4db8p-3, 0x1.6f6d994a7bc34p-7, -0x1.ff1fe588fe516p-6, -0x1.579dfbc209740p-6, + -0x1.36a890a67ff86p-3, -0x1.456db37329e69p-4, -0x1.c8d7bb1a4cbfcp-6, -0x1.3c8cd9a34d3dep-3, + 0x1.4a695a24088eap-5, -0x1.96ceb97c8c361p-3, -0x1.d7b3200182f4dp-8, 0x1.5b5e3488403cap-5, + -0x1.b52c5f2ae3f15p-8, 0x1.15d904e349465p-3, -0x1.97126613593a0p-4, 0x1.8c8daaab5e1a0p-6, + -0x1.b593280a6e235p-5, -0x1.f6d2135e828b1p-4, -0x1.b91958cbb960fp-8, 0x1.6732f3364dc6bp-5, + -0x1.9959f4ba36341p-4, 0x1.cb1279fc85570p-6, -0x1.6eca9695ad56bp-8, -0x1.8a47fbeaf3bbcp-3, + 0x1.281cfc5b04b04p-9, 0x1.5dede0baf0394p-9, 0x1.bbdfc6cf28935p-4, -0x1.1be96fc57f252p-3, + -0x1.2d1fc63ea2289p-4, -0x1.a054e99a21fe4p-3, 0x1.e6d8d4d618574p-7, 0x1.3cfc86ba53912p-14, + 0x1.14a874020243dp-12, 0x1.ff0ac30aaedccp-5, 0x1.580854290720fp-4, -0x1.dad1f91a825b1p-5, + -0x1.91949f545f12dp-5, -0x1.684b2f44c0ee5p-5, -0x1.437580475a9c6p-4, -0x1.64544b5bf9deap-3, + -0x1.b0cfa5683b966p-6, 0x1.92e1316b38716p-8, 0x1.43ee30d163c96p-6, -0x1.9a95c61c9ee38p-4, + -0x1.382a531b2adebp-4, -0x1.1d3787f25f99ep-4, -0x1.0e564f7a2177fp-5, 0x1.24bbf72684cb0p-5, + -0x1.2740f81d03cd9p-4, 0x1.c24c91acfe3c2p-3, 0x1.c13090621f781p-6, -0x1.130d6b25d3fb8p-8, + 0x1.bc8c5378382e4p-6, 0x1.cab8e5620fb07p-5, 0x1.66f401454ddecp-5, 0x1.3bea05349fed2p-4, + -0x1.5d935a3525744p-6, 0x1.1aacfe17ac26fp-4, -0x1.2c9becdcdffaep-11, -0x1.73511965ef6fbp-3, + -0x1.70c277ff4d05bp-5, -0x1.00eaff5837975p-5, 0x1.b24a686303d04p-9, 0x1.a25311dfcac7fp-3, + 0x1.57b1f13631bb0p-7, 0x1.e9027e7c26bf3p-5, -0x1.e70f7624a51b9p-8, 0x1.0eec1624de96cp-4, + -0x1.8e0c78e50e1d2p-7, 0x1.c596d14f1ff74p-5, -0x1.a108d471b5e87p-3, -0x1.3883a90c082c6p-5, + -0x1.3883a90c082c6p-5, -0x1.a108d471b5e87p-3, 0x1.c596d14f1ff74p-5, -0x1.8e0c78e50e1d2p-7, + 0x1.0eec1624de96cp-4, -0x1.e70f7624a51b9p-8, 0x1.e9027e7c26bf3p-5, 0x1.57b1f13631bb0p-7, + 0x1.a25311dfcac7fp-3, 0x1.b24a686303d04p-9, -0x1.00eaff5837975p-5, -0x1.70c277ff4d05bp-5, + -0x1.73511965ef6fbp-3, -0x1.2c9becdcdffaep-11, 0x1.1aacfe17ac26fp-4, -0x1.5d935a3525744p-6, + 0x1.3bea05349fed2p-4, 0x1.66f401454ddecp-5, 0x1.cab8e5620fb07p-5, 0x1.bc8c5378382e4p-6, + -0x1.130d6b25d3fb8p-8, 0x1.c13090621f781p-6, 0x1.c24c91acfe3c2p-3, -0x1.2740f81d03cd9p-4, + 0x1.24bbf72684cb0p-5, -0x1.0e564f7a2177fp-5, -0x1.1d3787f25f99ep-4, -0x1.382a531b2adebp-4, + -0x1.9a95c61c9ee38p-4, 0x1.43ee30d163c96p-6, 0x1.92e1316b38716p-8, -0x1.b0cfa5683b966p-6, + -0x1.64544b5bf9deap-3, -0x1.437580475a9c6p-4, -0x1.684b2f44c0ee5p-5, -0x1.91949f545f12dp-5, + -0x1.dad1f91a825b1p-5, 0x1.580854290720fp-4, 0x1.ff0ac30aaedccp-5, 0x1.14a874020243dp-12, + 0x1.3cfc86ba53912p-14, 0x1.e6d8d4d618574p-7, -0x1.a054e99a21fe4p-3, -0x1.2d1fc63ea2289p-4, + -0x1.1be96fc57f252p-3, 0x1.bbdfc6cf28935p-4, 0x1.5dede0baf0394p-9, 0x1.281cfc5b04b04p-9, + -0x1.8a47fbeaf3bbcp-3, -0x1.6eca9695ad56bp-8, 0x1.cb1279fc85570p-6, -0x1.9959f4ba36341p-4, + 0x1.6732f3364dc6bp-5, -0x1.b91958cbb960fp-8, -0x1.f6d2135e828b1p-4, -0x1.b593280a6e235p-5, + 0x1.8c8daaab5e1a2p-6, -0x1.97126613593a0p-4, 0x1.15d904e349464p-3, -0x1.b52c5f2ae3f26p-8, + 0x1.5b5e3488403d0p-5, -0x1.d7b3200182f0fp-8, -0x1.96ceb9497b620p-3, 0x1.4a695a2de6383p-5, + -0x1.36058c9efab3bp-4, -0x1.9777f13227126p-4, 0x1.db65238056e45p-4, -0x1.7c3a905696873p-5, + 0x1.c3786f790a63cp-7, 0x1.fce15cfd07ec8p-4, -0x1.f97f913bead84p-4, -0x1.45576c34ef478p-6, + 0x1.aa6c7ec097fc4p-5, -0x1.d17e7416f7617p-4, 0x1.87c4011f98919p-4, 0x1.49a4485edc1d7p-4, + -0x1.a630949817f29p-4, 0x1.21a79a9fdc925p-4, -0x1.4d1e230f688f2p-5, -0x1.e426a65f8cac8p-4, + 0x1.ff095821c8d1bp-4, -0x1.f656fecf46752p-8, -0x1.a82a094e1b1f8p-6, 0x1.f4e601471def2p-4, + -0x1.c678b00ee23e7p-4, -0x1.d7977866c00bap-5, 0x1.5c77bdec5e5a5p-4, -0x1.771e75676f7e1p-4, + 0x1.0c9704b8b1004p-4, 0x1.b3e4d221dcea5p-4, -0x1.ebbd8c7f7ea05p-4, 0x1.1d344340209c6p-5, + -0x1.921cf934add70p-10, -0x1.fff620a077467p-4, 0x1.ef17892e1afafp-4, 0x1.04fb8088f13cdp-5, + -0x1.01cfc8eb5568ap-4, 0x1.ba5aa9b1e3eebp-4, -0x1.6591916955d4bp-4, -0x1.6e744533d54c3p-4, + 0x1.c08c4030c81b4p-4, -0x1.edc1978bdc2f6p-5, 0x1.d93501f5d53eep-6, 0x1.f2252feabae99p-4, + -0x1.ffa73159214e5p-4, -0x1.2d8643d2a2424p-8, 0x1.35410c93596d4p-5, -0x1.e817bca9e94e3p-4, + 0x1.ad2bc8633f4ecp-4, 0x1.1734d4f0a2307p-4, -0x1.7f8ecf22246a6p-4, 0x1.532829a1dafdbp-4, + -0x1.c1249e34da866p-5, -0x1.cc1f0f9d5488ap-4, 0x1.f7599a73d0d02p-4, -0x1.76dd9af2af8c5p-6, + -0x1.5f6d00f853350p-7, 0x1.fe1cb23d91338p-4, -0x1.dfeae71cd21ebp-4, -0x1.64c7db803ee24p-5, + 0x1.2bedb0d45e467p-4, -0x1.9ef4405ffbf75p-4, 0x1.3fed94feed496p-4, 0x1.8fbcc88031cafp-4, + -0x1.d69618f48bde6p-4, 0x1.9372a3baeb34bp-5, -0x1.139f08f28b49cp-6, -0x1.fb5798354fd88p-4, + 0x1.fb5798354fd88p-4, 0x1.139f08f28b49cp-6, -0x1.9372a3baeb34bp-5, 0x1.d69618f48bde6p-4, + -0x1.8fbcc88031cafp-4, -0x1.3fed94feed496p-4, 0x1.9ef4405ffbf75p-4, -0x1.2bedb0d45e467p-4, + 0x1.64c7db803ee24p-5, 0x1.dfeae71cd21ebp-4, -0x1.fe1cb23d91338p-4, 0x1.5f6d00f853350p-7, + 0x1.76dd9af2af8c5p-6, -0x1.f7599a73d0d02p-4, 0x1.cc1f0f9d5488ap-4, 0x1.c1249e34da866p-5, + -0x1.532829a1dafdbp-4, 0x1.7f8ecf22246a6p-4, -0x1.1734d4f0a2307p-4, -0x1.ad2bc8633f4ecp-4, + 0x1.e817bca9e94e3p-4, -0x1.35410c93596d4p-5, 0x1.2d8643d2a2424p-8, 0x1.ffa73159214e5p-4, + -0x1.f2252feabae99p-4, -0x1.d93501f5d53eep-6, 0x1.edc1978bdc2f6p-5, -0x1.c08c4030c81b4p-4, + 0x1.6e744533d54c3p-4, 0x1.6591916955d4bp-4, -0x1.ba5aa9b1e3eebp-4, 0x1.01cfc8eb5568ap-4, + -0x1.04fb8088f13cdp-5, -0x1.ef17892e1afafp-4, 0x1.fff620a077467p-4, 0x1.921cf934add70p-10, + -0x1.1d344340209c6p-5, 0x1.ebbd8c7f7ea05p-4, -0x1.b3e4d221dcea5p-4, -0x1.0c9704b8b1004p-4, + 0x1.771e75676f7e1p-4, -0x1.5c77bdec5e5a5p-4, 0x1.d7977866c00bap-5, 0x1.c678b00ee23e7p-4, + -0x1.f4e601471def2p-4, 0x1.a82a094e1b1f8p-6, 0x1.f656fecf46752p-8, -0x1.ff095821c8d1bp-4, + 0x1.e426a65f8cac8p-4, 0x1.4d1e230f688f2p-5, -0x1.21a79a9fdc925p-4, 0x1.a630949817f29p-4, + -0x1.49a4485edc1d7p-4, -0x1.87c4011f98919p-4, 0x1.d17e7416f7617p-4, -0x1.aa6c7ec097fc4p-5, + 0x1.45576c34ef478p-6, 0x1.f97f913bead84p-4, -0x1.fce15cfd07ec8p-4, -0x1.c3786f790a63cp-7, + 0x1.7c3a905696873p-5, -0x1.db65238056e45p-4, 0x1.9777f13227138p-4, 0x1.36058c9efab3ap-4, + 0x1.9777f120a8fa5p-4, -0x1.36058d042edb6p-4, -0x1.7c3a90aa8e97ap-5, -0x1.db6521dbb979dp-4, + -0x1.fce15d3894864p-4, 0x1.c3786f6380222p-7, -0x1.45576bbe6fe11p-6, 0x1.f97f9177902d7p-4, + 0x1.d17e76354f99cp-4, 0x1.aa6c7fa817702p-5, 0x1.49a44912e23d5p-4, -0x1.87c400f10c37fp-4, + -0x1.21a79ad92a275p-4, -0x1.a6309341dc10cp-4, -0x1.e426a62adc2e0p-4, 0x1.4d1e238df93ebp-5, + 0x1.f656fd084edc3p-8, 0x1.ff0957c53a771p-4, 0x1.f4e602c7cb1acp-4, 0x1.a82a091bc2a03p-6, + 0x1.d79778a903179p-5, -0x1.c678b24040bdbp-4, -0x1.771e750c16d67p-4, -0x1.5c77bc50a766ap-4, + -0x1.b3e4d2b4d2810p-4, 0x1.0c9704328cbccp-4, 0x1.1d344398b24b1p-5, 0x1.ebbd8c4e41129p-4, + 0x1.fff62060c8192p-4, -0x1.921cf5d5a19d3p-10, 0x1.04fb80f0f1c9cp-5, -0x1.ef1788947f0f6p-4, + -0x1.ba5aa7b81b1f4p-4, -0x1.01cfc8419f82fp-4, -0x1.6e7444e68093ap-4, 0x1.6591918421211p-4, + 0x1.edc1973496d59p-5, 0x1.c08c41e041f08p-4, 0x1.f2252f9335347p-4, -0x1.d93501c86b16ep-6, + 0x1.2d8643aaf39c4p-8, -0x1.ffa731c135e27p-4, -0x1.e817bd451b22ep-4, -0x1.35410c7c8b265p-5, + -0x1.1734d58fc7a16p-4, 0x1.ad2bc947d92f7p-4, 0x1.532828b54140ap-4, 0x1.7f8ecf88f5d0bp-4, + 0x1.cc1f0e3fcc6f2p-4, -0x1.c1249e3876e6dp-5, -0x1.76dd9a1f82550p-6, -0x1.f75998ade6067p-4, + -0x1.fe1cb13c1f147p-4, -0x1.5f6d01c25c236p-7, -0x1.64c7dc25fdfddp-5, 0x1.dfeae88c4fd5dp-4, + 0x1.9ef44050ab048p-4, 0x1.2bedb04faa09ap-4, 0x1.8fbcc7d6453bcp-4, -0x1.3fed9529467fap-4, + -0x1.9372a561d1edfp-5, -0x1.d696187fe1ba2p-4, -0x1.fb579973d9912p-4, 0x1.139f0949668e1p-6, + -0x1.139f0949668e1p-6, 0x1.fb579973d9912p-4, 0x1.d696187fe1ba2p-4, 0x1.9372a561d1edfp-5, + 0x1.3fed9529467fap-4, -0x1.8fbcc7d6453bcp-4, -0x1.2bedb04faa09ap-4, -0x1.9ef44050ab048p-4, + -0x1.dfeae88c4fd5dp-4, 0x1.64c7dc25fdfddp-5, 0x1.5f6d01c25c236p-7, 0x1.fe1cb13c1f147p-4, + 0x1.f75998ade6067p-4, 0x1.76dd9a1f82550p-6, 0x1.c1249e3876e6dp-5, -0x1.cc1f0e3fcc6f2p-4, + -0x1.7f8ecf88f5d0bp-4, -0x1.532828b54140ap-4, -0x1.ad2bc947d92f7p-4, 0x1.1734d58fc7a16p-4, + 0x1.35410c7c8b265p-5, 0x1.e817bd451b22ep-4, 0x1.ffa731c135e27p-4, -0x1.2d8643aaf39c4p-8, + 0x1.d93501c86b16ep-6, -0x1.f2252f9335347p-4, -0x1.c08c41e041f08p-4, -0x1.edc1973496d59p-5, + -0x1.6591918421211p-4, 0x1.6e7444e68093ap-4, 0x1.01cfc8419f82fp-4, 0x1.ba5aa7b81b1f4p-4, + 0x1.ef1788947f0f6p-4, -0x1.04fb80f0f1c9cp-5, 0x1.921cf5d5a19d3p-10, -0x1.fff62060c8192p-4, + -0x1.ebbd8c4e41129p-4, -0x1.1d344398b24b1p-5, -0x1.0c9704328cbccp-4, 0x1.b3e4d2b4d2810p-4, + 0x1.5c77bc50a766ap-4, 0x1.771e750c16d67p-4, 0x1.c678b24040bdbp-4, -0x1.d79778a903179p-5, + -0x1.a82a091bc2a03p-6, -0x1.f4e602c7cb1acp-4, -0x1.ff0957c53a771p-4, -0x1.f656fd084edc3p-8, + -0x1.4d1e238df93ebp-5, 0x1.e426a62adc2e0p-4, 0x1.a6309341dc10cp-4, 0x1.21a79ad92a275p-4, + 0x1.87c400f10c37fp-4, -0x1.49a44912e23d5p-4, -0x1.aa6c7fa817702p-5, -0x1.d17e76354f99cp-4, + -0x1.f97f9177902d7p-4, 0x1.45576bbe6fe11p-6, -0x1.c3786f6380222p-7, 0x1.fce15d3894864p-4, + 0x1.db6521dbb979dp-4, 0x1.7c3a90aa8e97ap-5, 0x1.36058d042edb5p-4, -0x1.9777f120a8f92p-4, + -0x1.684ab8186a970p-4, 0x1.ec7c90af03d62p-4, -0x1.b037124e05ea8p-5, -0x1.b8a71fbe22df8p-3, + -0x1.f20cff49f01aep-5, -0x1.ad3dcb36995ffp-6, -0x1.d64259bf88426p-7, -0x1.24054f5bf1ac8p-8, + -0x1.9a1aea09b90d6p-5, -0x1.0ab2c0f551ef9p-4, -0x1.dccdd99c169c8p-4, -0x1.b1e212af421d9p-4, + 0x1.3c10d7eb56bffp-4, 0x1.98ce376c357c4p-4, 0x1.74b2c580fab62p-3, -0x1.91411bf74d83bp-5, + -0x1.84c4990313782p-7, -0x1.35c1b94a6ad31p-4, -0x1.b56528d22252bp-6, -0x1.7e2b526968572p-5, + -0x1.3fc750bb4f7d3p-4, 0x1.6210ee5b62258p-7, 0x1.1bf3095743272p-7, -0x1.400800ccb0cc6p-4, + -0x1.9d83724c7f3a3p-5, 0x1.4379bfc507ca2p-4, -0x1.f4dc04ac3196cp-7, -0x1.183223dfd4f8dp-3, + 0x1.c63668fc66834p-4, 0x1.c65c88af5f30dp-8, -0x1.7d485c01a8155p-5, 0x1.8bdca824f7fa8p-6, + -0x1.f22a408be2456p-4, -0x1.7538ead184b1ep-4, -0x1.e0acf19fec744p-7, -0x1.c5979382da4e2p-5, + -0x1.17515c79ca56cp-5, -0x1.a141c0576d224p-4, -0x1.e972f7a1a4747p-6, -0x1.d921c41015483p-5, + 0x1.63638c6c517b9p-7, 0x1.b2858b20d4dd0p-4, 0x1.175fc8d86581dp-6, -0x1.c4a1703e4a283p-6, + 0x1.02347b56a2bc5p-3, 0x1.d592a6a02a1edp-4, -0x1.54eb66a89ecabp-6, -0x1.777c6f35805cdp-6, + 0x1.c8e05695a2b57p-4, -0x1.e34cfe27e8655p-5, -0x1.8c2bda980e79ep-6, -0x1.53f6087e061b7p-3, + 0x1.f9664163a64d5p-6, -0x1.f281832c82ad3p-6, -0x1.1bf6dcb1c153ap-5, -0x1.ead29f5ee4992p-3, + -0x1.3329e734f16d4p-4, 0x1.e96de8e6be469p-4, 0x1.7dda5b0d6de28p-3, -0x1.06bf8e322619cp-4, + 0x1.5f80bb0942d65p-7, -0x1.47572a8354dd2p-3, -0x1.e4c6541cc9b17p-5, 0x1.57e2c1224ba51p-7, + -0x1.57e2c1224ba51p-7, 0x1.e4c6541cc9b17p-5, 0x1.47572a8354dd2p-3, -0x1.5f80bb0942d65p-7, + 0x1.06bf8e322619cp-4, -0x1.7dda5b0d6de28p-3, -0x1.e96de8e6be469p-4, 0x1.3329e734f16d4p-4, + 0x1.ead29f5ee4992p-3, 0x1.1bf6dcb1c153ap-5, 0x1.f281832c82ad3p-6, -0x1.f9664163a64d5p-6, + 0x1.53f6087e061b7p-3, 0x1.8c2bda980e79ep-6, 0x1.e34cfe27e8655p-5, -0x1.c8e05695a2b57p-4, + 0x1.777c6f35805cdp-6, 0x1.54eb66a89ecabp-6, -0x1.d592a6a02a1edp-4, -0x1.02347b56a2bc5p-3, + 0x1.c4a1703e4a283p-6, -0x1.175fc8d86581dp-6, -0x1.b2858b20d4dd0p-4, -0x1.63638c6c517b9p-7, + 0x1.d921c41015483p-5, 0x1.e972f7a1a4747p-6, 0x1.a141c0576d224p-4, 0x1.17515c79ca56cp-5, + 0x1.c5979382da4e2p-5, 0x1.e0acf19fec744p-7, 0x1.7538ead184b1ep-4, 0x1.f22a408be2456p-4, + -0x1.8bdca824f7fa8p-6, 0x1.7d485c01a8155p-5, -0x1.c65c88af5f30dp-8, -0x1.c63668fc66834p-4, + 0x1.183223dfd4f8dp-3, 0x1.f4dc04ac3196cp-7, -0x1.4379bfc507ca2p-4, 0x1.9d83724c7f3a3p-5, + 0x1.400800ccb0cc6p-4, -0x1.1bf3095743272p-7, -0x1.6210ee5b62258p-7, 0x1.3fc750bb4f7d3p-4, + 0x1.7e2b526968572p-5, 0x1.b56528d22252bp-6, 0x1.35c1b94a6ad31p-4, 0x1.84c4990313782p-7, + 0x1.91411bf74d83bp-5, -0x1.74b2c580fab62p-3, -0x1.98ce376c357c4p-4, -0x1.3c10d7eb56bffp-4, + 0x1.b1e212af421d9p-4, 0x1.dccdd99c169c8p-4, 0x1.0ab2c0f551ef9p-4, 0x1.9a1aea09b90d6p-5, + 0x1.24054f5bf1acbp-8, 0x1.d64259bf8841fp-7, 0x1.ad3dcb3699609p-6, 0x1.f20cff49f01b6p-5, + 0x1.b8a71fbe22dfbp-3, 0x1.b037124e05ea0p-5, -0x1.ec7c90ca03883p-4, 0x1.684ab851c8b1bp-4, + 0x1.1153b492c0d3fp-4, -0x1.c12e7aa38bcf6p-4, 0x1.47f9ea51d49c1p-4, 0x1.c06ea1c854b89p-8, + 0x1.d9cd01ec35f87p-6, -0x1.ea90b3a4f93c2p-4, 0x1.32e42d98cba6bp-4, 0x1.6d5e447d2214cp-6, + 0x1.940b819daead4p-7, -0x1.59ff079afe4dbp-3, 0x1.9356266fe8b16p-6, 0x1.5cb588af85da2p-4, + 0x1.9329f3d138a75p-3, -0x1.3397d5d7a83e1p-7, -0x1.47ba58aad7d99p-5, 0x1.7444d330094aap-4, + -0x1.fd9e1b3ede632p-4, 0x1.88c0b10e8409ep-6, -0x1.30934d343e8e2p-9, -0x1.1ab8367db3f0bp-5, + -0x1.bde84d250d371p-7, 0x1.c6f3518482885p-4, -0x1.8509bf44de1a2p-5, -0x1.95cdc23c14a91p-5, + -0x1.a8de79a8215c1p-4, 0x1.3d8faff029f2ap-5, -0x1.54f7848f6e1b9p-6, 0x1.68663ef45aadfp-7, + -0x1.21038b8f7cec5p-6, -0x1.6edfeb2f6e5dfp-5, 0x1.8bd000ce98eaap-4, 0x1.60f5d2f81feadp-6, + 0x1.fe4c7ad739bdep-5, -0x1.2c563fb510ec6p-3, -0x1.112dd0304dfddp-7, -0x1.204678266e782p-4, + 0x1.b1de7c97baa01p-4, 0x1.54e840c1e33c2p-5, 0x1.8325c4f3e3050p-5, -0x1.d91002f3d2ff1p-3, + -0x1.67eddc8ee7e83p-5, -0x1.6f4192d90b997p-6, -0x1.3b4dd0ca80c20p-6, -0x1.b840b231093c7p-3, + 0x1.291df050c7d00p-3, 0x1.e8ecff1c6e039p-6, 0x1.9896d001de161p-4, -0x1.47a84e1984263p-4, + -0x1.7a607908aa445p-4, -0x1.2267b1e8885aep-6, -0x1.a577640653cecp-3, 0x1.22d716bb56a69p-4, + -0x1.8eb363dd7f839p-5, 0x1.3630155df546bp-4, -0x1.a80e388405ff4p-6, -0x1.ba205b7891272p-5, + 0x1.9f02ad38fed41p-5, 0x1.f11bf1d8167cep-4, -0x1.16136c9b5f3bbp-6, 0x1.eb58e578f4b8ep-4, + 0x1.4c7404597ee8fp-6, 0x1.80f4e0231bb19p-4, 0x1.a091b5975f68fp-9, -0x1.00973127c9b3bp-3, + 0x1.00973127c9b3bp-3, -0x1.a091b5975f68fp-9, -0x1.80f4e0231bb19p-4, -0x1.4c7404597ee8fp-6, + -0x1.eb58e578f4b8ep-4, 0x1.16136c9b5f3bbp-6, -0x1.f11bf1d8167cep-4, -0x1.9f02ad38fed41p-5, + 0x1.ba205b7891272p-5, 0x1.a80e388405ff4p-6, -0x1.3630155df546bp-4, 0x1.8eb363dd7f839p-5, + -0x1.22d716bb56a69p-4, 0x1.a577640653cecp-3, 0x1.2267b1e8885aep-6, 0x1.7a607908aa445p-4, + 0x1.47a84e1984263p-4, -0x1.9896d001de161p-4, -0x1.e8ecff1c6e039p-6, -0x1.291df050c7d00p-3, + 0x1.b840b231093c7p-3, 0x1.3b4dd0ca80c20p-6, 0x1.6f4192d90b997p-6, 0x1.67eddc8ee7e83p-5, + 0x1.d91002f3d2ff1p-3, -0x1.8325c4f3e3050p-5, -0x1.54e840c1e33c2p-5, -0x1.b1de7c97baa01p-4, + 0x1.204678266e782p-4, 0x1.112dd0304dfddp-7, 0x1.2c563fb510ec6p-3, -0x1.fe4c7ad739bdep-5, + -0x1.60f5d2f81feadp-6, -0x1.8bd000ce98eaap-4, 0x1.6edfeb2f6e5dfp-5, 0x1.21038b8f7cec5p-6, + -0x1.68663ef45aadfp-7, 0x1.54f7848f6e1b9p-6, -0x1.3d8faff029f2ap-5, 0x1.a8de79a8215c1p-4, + 0x1.95cdc23c14a91p-5, 0x1.8509bf44de1a2p-5, -0x1.c6f3518482885p-4, 0x1.bde84d250d371p-7, + 0x1.1ab8367db3f0bp-5, 0x1.30934d343e8e2p-9, -0x1.88c0b10e8409ep-6, 0x1.fd9e1b3ede632p-4, + -0x1.7444d330094aap-4, 0x1.47ba58aad7d99p-5, 0x1.3397d5d7a83e1p-7, -0x1.9329f3d138a75p-3, + -0x1.5cb588af85da2p-4, -0x1.9356266fe8b16p-6, 0x1.59ff079afe4dbp-3, -0x1.940b819daead4p-7, + -0x1.6d5e447d22144p-6, -0x1.32e42d98cba6dp-4, 0x1.ea90b3a4f93cep-4, -0x1.d9cd01ec35f96p-6, + -0x1.c06ea1c854b4bp-8, -0x1.47f9ea51d49c1p-4, 0x1.c12e797895b6bp-4, -0x1.1153b4be0da92p-4, + -0x1.3fed971287722p-4, -0x1.8fbcca117d095p-4, 0x1.cc1f0ec38e393p-4, -0x1.c124a207cc1c2p-5, + 0x1.d934ff2e8b38fp-6, 0x1.f225316a9901dp-4, -0x1.fff6217196678p-4, 0x1.921d2f1a04873p-10, + 0x1.a829fcbd830b7p-6, -0x1.f4e6040146ac9p-4, 0x1.d17e76ef39499p-4, 0x1.aa6c85ee71f6fp-5, + -0x1.360588d49f285p-4, 0x1.9777ee04e312ep-4, -0x1.49a448a2b9852p-4, -0x1.87c401f29ebebp-4, + 0x1.c678b266c62e4p-4, -0x1.d7977833e771ap-5, 0x1.04fb827c74d6dp-5, 0x1.ef17896bc449ep-4, + -0x1.ffa72f38688d9p-4, 0x1.2d8656218339bp-8, 0x1.76dda76708a63p-6, -0x1.f7599a7cdb02dp-4, + 0x1.d69614cde94d6p-4, 0x1.9372a7355aad9p-5, -0x1.2bedb328a8cf1p-4, 0x1.9ef43f1c89223p-4, + -0x1.53282d8b15ce9p-4, -0x1.7f8ecc17d61a1p-4, 0x1.c08c4222c94e9p-4, -0x1.edc1922415333p-5, + 0x1.1d3444e0ce216p-5, 0x1.ebbd8c88feb3cp-4, -0x1.ff095835becc3p-4, 0x1.f656ed57ee4a7p-8, + 0x1.45576b3ce744ap-6, -0x1.f97f91cbf72b6p-4, 0x1.db6525c35e026p-4, 0x1.7c3a94904908dp-5, + -0x1.21a796169bccfp-4, 0x1.a63094424e8f1p-4, -0x1.5c77ba0861cd0p-4, -0x1.771e74da97702p-4, + 0x1.ba5aa6d671593p-4, -0x1.01cfc6535a73dp-4, 0x1.354108c8359fdp-5, 0x1.e817bc79d15dbp-4, + -0x1.fe1cac8375836p-4, 0x1.5f6d02e3db9bap-7, 0x1.139f06411aed2p-6, -0x1.fb57962caa755p-4, + 0x1.dfeae667e4abcp-4, 0x1.64c7dbe31049dp-5, -0x1.1734d462f4154p-4, 0x1.ad2bcc5695d13p-4, + -0x1.6591924814ec2p-4, -0x1.6e7442b8bd288p-4, 0x1.b3e4d65f79322p-4, -0x1.0c970631b5c60p-4, + 0x1.4d1e258ac7f79p-5, 0x1.e426a46a04354p-4, -0x1.fce1620f42ff4p-4, 0x1.c3784f4e39739p-7, + 0x1.c3784f4e39739p-7, -0x1.fce1620f42ff4p-4, 0x1.e426a46a04354p-4, 0x1.4d1e258ac7f79p-5, + -0x1.0c970631b5c60p-4, 0x1.b3e4d65f79322p-4, -0x1.6e7442b8bd288p-4, -0x1.6591924814ec2p-4, + 0x1.ad2bcc5695d13p-4, -0x1.1734d462f4154p-4, 0x1.64c7dbe31049dp-5, 0x1.dfeae667e4abcp-4, + -0x1.fb57962caa755p-4, 0x1.139f06411aed2p-6, 0x1.5f6d02e3db9bap-7, -0x1.fe1cac8375836p-4, + 0x1.e817bc79d15dbp-4, 0x1.354108c8359fdp-5, -0x1.01cfc6535a73dp-4, 0x1.ba5aa6d671593p-4, + -0x1.771e74da97702p-4, -0x1.5c77ba0861cd0p-4, 0x1.a63094424e8f1p-4, -0x1.21a796169bccfp-4, + 0x1.7c3a94904908dp-5, 0x1.db6525c35e026p-4, -0x1.f97f91cbf72b6p-4, 0x1.45576b3ce744ap-6, + 0x1.f656ed57ee4a7p-8, -0x1.ff095835becc3p-4, 0x1.ebbd8c88feb3cp-4, 0x1.1d3444e0ce216p-5, + -0x1.edc1922415333p-5, 0x1.c08c4222c94e9p-4, -0x1.7f8ecc17d61a1p-4, -0x1.53282d8b15ce9p-4, + 0x1.9ef43f1c89223p-4, -0x1.2bedb328a8cf1p-4, 0x1.9372a7355aad9p-5, 0x1.d69614cde94d6p-4, + -0x1.f7599a7cdb02dp-4, 0x1.76dda76708a63p-6, 0x1.2d8656218339bp-8, -0x1.ffa72f38688d9p-4, + 0x1.ef17896bc449ep-4, 0x1.04fb827c74d6dp-5, -0x1.d7977833e771ap-5, 0x1.c678b266c62e4p-4, + -0x1.87c401f29ebebp-4, -0x1.49a448a2b9852p-4, 0x1.9777ee04e312ep-4, -0x1.360588d49f285p-4, + 0x1.aa6c85ee71f6fp-5, 0x1.d17e76ef39499p-4, -0x1.f4e6040146ac9p-4, 0x1.a829fcbd830b7p-6, + 0x1.921d2f1a04873p-10, -0x1.fff6217196678p-4, 0x1.f225316a9901dp-4, 0x1.d934ff2e8b38fp-6, + -0x1.c124a207cc1c2p-5, 0x1.cc1f0ec38e393p-4, -0x1.8fbcca117d08fp-4, -0x1.3fed971287722p-4, + 0x1.8fbccb52c51f8p-4, -0x1.3fed977f98533p-4, -0x1.c124a374cc32cp-5, -0x1.cc1f0ffd7639bp-4, + -0x1.f22531a354bbap-4, 0x1.d935003d3fdb5p-6, 0x1.921d27a193f9fp-10, 0x1.fff621b9211aap-4, + 0x1.f4e602703c731p-4, 0x1.a829fa81ee85fp-6, 0x1.aa6c853b05e0dp-5, -0x1.d17e78521b1aap-4, + -0x1.9777ee338c07bp-4, -0x1.360588e3a57ecp-4, -0x1.87c402acf1122p-4, 0x1.49a448e9260b1p-4, + 0x1.d797780767038p-5, 0x1.c678b2bcbefd4p-4, 0x1.ef178aa0208cap-4, -0x1.04fb82b530d4cp-5, + -0x1.2d8656d3abd61p-8, -0x1.ffa72f56ed5bep-4, -0x1.f7599aa095b86p-4, -0x1.76dda71216278p-6, + -0x1.9372a76775ad4p-5, 0x1.d696148ca9fb2p-4, 0x1.9ef43e57c7454p-4, 0x1.2bedb37631f30p-4, + 0x1.7f8ecc2e23f4ap-4, -0x1.53282cf96a6cdp-4, -0x1.edc1924652663p-5, -0x1.c08c406cf0bffp-4, + -0x1.ebbd8cb4271dfp-4, 0x1.1d3445d6dd534p-5, 0x1.f656eb5b7065dp-8, 0x1.ff0956ea675ccp-4, + 0x1.f97f9023dbc0ap-4, 0x1.45576bf81bbd0p-6, 0x1.7c3a964281ed7p-5, -0x1.db6526302fdd1p-4, + -0x1.a63092ebc2da7p-4, -0x1.21a7968231355p-4, -0x1.771e74c8b3de1p-4, 0x1.5c77b97c1ad35p-4, + 0x1.01cfc7b8dd0a0p-4, 0x1.ba5aa876b5cfdp-4, 0x1.e817bbb60fbe5p-4, -0x1.354107af7591cp-5, + -0x1.5f6d03b5f5008p-7, -0x1.fe1cad852d523p-4, -0x1.fb5796476e9c0p-4, -0x1.139f06dcf906cp-6, + -0x1.64c7dbda24b9bp-5, 0x1.dfeae56100145p-4, 0x1.ad2bcb84ff6dbp-4, 0x1.1734d4be80a67p-4, + 0x1.6e744233a484dp-4, -0x1.659193a7e2737p-4, -0x1.0c9705c43c8f0p-4, -0x1.b3e4d45e2ebbap-4, + -0x1.e426a615ab886p-4, 0x1.4d1e25e648033p-5, 0x1.c3784d8b12e84p-7, 0x1.fce16136ee17ap-4, + 0x1.fce16136ee17ap-4, 0x1.c3784d8b12e84p-7, 0x1.4d1e25e648033p-5, -0x1.e426a615ab886p-4, + -0x1.b3e4d45e2ebbap-4, -0x1.0c9705c43c8f0p-4, -0x1.659193a7e2737p-4, 0x1.6e744233a484dp-4, + 0x1.1734d4be80a67p-4, 0x1.ad2bcb84ff6dbp-4, 0x1.dfeae56100145p-4, -0x1.64c7dbda24b9bp-5, + -0x1.139f06dcf906cp-6, -0x1.fb5796476e9c0p-4, -0x1.fe1cad852d523p-4, -0x1.5f6d03b5f5008p-7, + -0x1.354107af7591cp-5, 0x1.e817bbb60fbe5p-4, 0x1.ba5aa876b5cfdp-4, 0x1.01cfc7b8dd0a0p-4, + 0x1.5c77b97c1ad35p-4, -0x1.771e74c8b3de1p-4, -0x1.21a7968231355p-4, -0x1.a63092ebc2da7p-4, + -0x1.db6526302fdd1p-4, 0x1.7c3a964281ed7p-5, 0x1.45576bf81bbd0p-6, 0x1.f97f9023dbc0ap-4, + 0x1.ff0956ea675ccp-4, 0x1.f656eb5b7065dp-8, 0x1.1d3445d6dd534p-5, -0x1.ebbd8cb4271dfp-4, + -0x1.c08c406cf0bffp-4, -0x1.edc1924652663p-5, -0x1.53282cf96a6cdp-4, 0x1.7f8ecc2e23f4ap-4, + 0x1.2bedb37631f30p-4, 0x1.9ef43e57c7454p-4, 0x1.d696148ca9fb2p-4, -0x1.9372a76775ad4p-5, + -0x1.76dda71216278p-6, -0x1.f7599aa095b86p-4, -0x1.ffa72f56ed5bep-4, -0x1.2d8656d3abd61p-8, + -0x1.04fb82b530d4cp-5, 0x1.ef178aa0208cap-4, 0x1.c678b2bcbefd4p-4, 0x1.d797780767038p-5, + 0x1.49a448e9260b1p-4, -0x1.87c402acf1122p-4, -0x1.360588e3a57ecp-4, -0x1.9777ee338c07bp-4, + -0x1.d17e78521b1aap-4, 0x1.aa6c853b05e0dp-5, 0x1.a829fa81ee85fp-6, 0x1.f4e602703c731p-4, + 0x1.fff621b9211aap-4, 0x1.921d27a193f9fp-10, 0x1.d935003d3fdb5p-6, -0x1.f22531a354bbap-4, + -0x1.cc1f0ffd7639bp-4, -0x1.c124a374cc32cp-5, -0x1.3fed977f98532p-4, 0x1.8fbccb52c5203p-4, + -0x1.edfdef6ec088cp-4, 0x1.a29d80573a7fbp-4, 0x1.be02f504a43fep-5, 0x1.653ceca05fd49p-3, + 0x1.ebeb4a8d20c9dp-4, -0x1.8c4948d4e4191p-5, 0x1.32e2734315dbbp-5, 0x1.87fdf97d19aadp-7, + 0x1.8bc827055bc46p-3, 0x1.1d2f367bf411cp-5, 0x1.77f9d865d6693p-5, 0x1.635de8afe4237p-3, + -0x1.aa8c781977fc6p-3, -0x1.14ed844938a28p-8, -0x1.af2a25145a9c6p-4, -0x1.3f5dffe49c5eep-8, + 0x1.27ccc584533dfp-8, 0x1.bdd9464485075p-5, -0x1.01bfcf315800ep-3, 0x1.be51bd71bf470p-6, + 0x1.c857c84e907d8p-7, 0x1.0019ac73ba3d1p-4, -0x1.6547a9996f44cp-3, 0x1.e104cabad7dcep-5, + 0x1.8b1549b8f7c0ep-6, 0x1.05209146911fdp-3, -0x1.a98e306bce20cp-8, 0x1.0e9e41c0641b7p-8, + -0x1.8d08ec8a3edeep-7, -0x1.ade492db5a9d9p-4, -0x1.d195a9d00dca9p-7, -0x1.af6109632358ap-4, + -0x1.0a6054db756d1p-5, -0x1.109795cb2de1fp-6, 0x1.262e3524c8abdp-5, 0x1.afc35548bbf65p-4, + 0x1.2af4af2c8e07ep-6, 0x1.5ba75ef48a87ap-8, -0x1.0aa24d2e0d667p-6, 0x1.fdb3ee0f60eb2p-4, + 0x1.5c90440230b57p-5, -0x1.42d0019b02665p-5, 0x1.847ba6fc74136p-8, 0x1.9728704c1c5b8p-8, + -0x1.050f3d98c027dp-3, -0x1.b5446a55e43fcp-3, -0x1.6bc3cb91c92e2p-7, -0x1.ac605a48cab49p-5, + 0x1.e5b9f063759a3p-6, 0x1.3af24f4e9cc20p-6, -0x1.b19e2db704693p-6, 0x1.ac3575cea7ae2p-5, + -0x1.03fb7e6ce7b84p-4, 0x1.1d9bdca914bcep-7, 0x1.f7c440c44e90fp-6, 0x1.80d710bad5312p-7, + 0x1.49f1036637804p-6, 0x1.40e86982fc84ap-7, -0x1.bcce2c790365dp-4, -0x1.bda793fc6cb1ap-3, + 0x1.5f16709808436p-3, -0x1.7df73cafa1358p-5, 0x1.0e3727969a0f3p-6, -0x1.5c25784f35792p-5, + -0x1.5c25784f35792p-5, 0x1.0e3727969a0f3p-6, -0x1.7df73cafa1358p-5, 0x1.5f16709808436p-3, + -0x1.bda793fc6cb1ap-3, -0x1.bcce2c790365dp-4, 0x1.40e86982fc84ap-7, 0x1.49f1036637804p-6, + 0x1.80d710bad5312p-7, 0x1.f7c440c44e90fp-6, 0x1.1d9bdca914bcep-7, -0x1.03fb7e6ce7b84p-4, + 0x1.ac3575cea7ae2p-5, -0x1.b19e2db704693p-6, 0x1.3af24f4e9cc20p-6, 0x1.e5b9f063759a3p-6, + -0x1.ac605a48cab49p-5, -0x1.6bc3cb91c92e2p-7, -0x1.b5446a55e43fcp-3, -0x1.050f3d98c027dp-3, + 0x1.9728704c1c5b8p-8, 0x1.847ba6fc74136p-8, -0x1.42d0019b02665p-5, 0x1.5c90440230b57p-5, + 0x1.fdb3ee0f60eb2p-4, -0x1.0aa24d2e0d667p-6, 0x1.5ba75ef48a87ap-8, 0x1.2af4af2c8e07ep-6, + 0x1.afc35548bbf65p-4, 0x1.262e3524c8abdp-5, -0x1.109795cb2de1fp-6, -0x1.0a6054db756d1p-5, + -0x1.af6109632358ap-4, -0x1.d195a9d00dca9p-7, -0x1.ade492db5a9d9p-4, -0x1.8d08ec8a3edeep-7, + 0x1.0e9e41c0641b7p-8, -0x1.a98e306bce20cp-8, 0x1.05209146911fdp-3, 0x1.8b1549b8f7c0ep-6, + 0x1.e104cabad7dcep-5, -0x1.6547a9996f44cp-3, 0x1.0019ac73ba3d1p-4, 0x1.c857c84e907d8p-7, + 0x1.be51bd71bf470p-6, -0x1.01bfcf315800ep-3, 0x1.bdd9464485075p-5, 0x1.27ccc584533dfp-8, + -0x1.3f5dffe49c5eep-8, -0x1.af2a25145a9c6p-4, -0x1.14ed844938a28p-8, -0x1.aa8c781977fc6p-3, + 0x1.635de8afe4237p-3, 0x1.77f9d865d6693p-5, 0x1.1d2f367bf411cp-5, 0x1.8bc827055bc46p-3, + 0x1.87fdf97d19aabp-7, 0x1.32e2734315dbep-5, -0x1.8c4948d4e4199p-5, 0x1.ebeb4a8d20c99p-4, + 0x1.653ceca05fd49p-3, 0x1.be02f504a440ap-5, 0x1.a29d802b6c741p-4, -0x1.edfdf02f249cfp-4, + 0x1.2f1ad5916c558p-4, -0x1.b6dd2c96b5bc9p-5, 0x1.4b110f25c0f9dp-3, -0x1.31caf98d50f3bp-4, + -0x1.7d8c683cfe1ebp-5, -0x1.325c129f02967p-6, 0x1.5685268bb385ep-3, -0x1.582f23819e7aep-5, + -0x1.2a94c207a33cfp-5, 0x1.1c1a8edfff970p-4, 0x1.2a5a088890bd6p-4, -0x1.610422f29b0fdp-6, + -0x1.4599b6c0deec6p-6, 0x1.6e18029b48e18p-4, -0x1.990fb456ac92ep-4, -0x1.f7a21cc2f0621p-5, + 0x1.27b29b62411f9p-3, 0x1.d7b1991770903p-5, 0x1.a418f05c4f2e4p-6, -0x1.a0fa66db6b2e9p-5, + -0x1.54fd600dbcbfcp-3, 0x1.2d7a5727715d6p-9, 0x1.e79f959a7bf8ep-10, -0x1.457c15e5b079ep-4, + 0x1.f78f63cd4c6c9p-5, -0x1.0e6353f655f70p-4, 0x1.5164e98488152p-5, 0x1.3900584b7641bp-11, + 0x1.d4ed97cc9372bp-4, -0x1.bc328cf1f2d7ap-7, 0x1.aa5b7930d82dfp-10, -0x1.ec0d8eaf8ce04p-4, + 0x1.8ba81be384486p-5, -0x1.8a6ec6e1b7c4cp-6, 0x1.9decca3ad5327p-3, -0x1.9b91effbfac51p-5, + -0x1.a2b5da779c34cp-6, 0x1.5ce7e466aa429p-5, -0x1.5fa3d6c13c1a9p-8, 0x1.3395a397d65b8p-4, + -0x1.1839d64cd8232p-3, -0x1.0667f1400b794p-3, 0x1.212ad5f74029bp-3, -0x1.06eddb92d3868p-4, + 0x1.05116a3393bb2p-3, -0x1.4dc63fdf39b61p-4, -0x1.d3cb6f7c3251fp-6, -0x1.182c2165e9248p-5, + 0x1.65df69fd7fbbap-4, 0x1.4b7c3ad2e4386p-5, -0x1.062370dd12b4cp-7, 0x1.4b265a6a7292cp-4, + -0x1.31b1d6a513cf1p-3, -0x1.ad4611d4f214cp-11, -0x1.e5f3eeb3acd58p-4, -0x1.b65d2796022cdp-3, + -0x1.d50a4f52f9ebbp-4, 0x1.b7cf8d1e6a9d3p-5, -0x1.4bce1e2f29fa9p-4, 0x1.595d038a2601fp-5, + -0x1.daec1d89b2c75p-7, 0x1.63b6e07b10863p-3, -0x1.db15bc2f7f246p-5, -0x1.435e0bc42de99p-8, + -0x1.435e0bc42de99p-8, -0x1.db15bc2f7f246p-5, 0x1.63b6e07b10863p-3, -0x1.daec1d89b2c75p-7, + 0x1.595d038a2601fp-5, -0x1.4bce1e2f29fa9p-4, 0x1.b7cf8d1e6a9d3p-5, -0x1.d50a4f52f9ebbp-4, + -0x1.b65d2796022cdp-3, -0x1.e5f3eeb3acd58p-4, -0x1.ad4611d4f214cp-11, -0x1.31b1d6a513cf1p-3, + 0x1.4b265a6a7292cp-4, -0x1.062370dd12b4cp-7, 0x1.4b7c3ad2e4386p-5, 0x1.65df69fd7fbbap-4, + -0x1.182c2165e9248p-5, -0x1.d3cb6f7c3251fp-6, -0x1.4dc63fdf39b61p-4, 0x1.05116a3393bb2p-3, + -0x1.06eddb92d3868p-4, 0x1.212ad5f74029bp-3, -0x1.0667f1400b794p-3, -0x1.1839d64cd8232p-3, + 0x1.3395a397d65b8p-4, -0x1.5fa3d6c13c1a9p-8, 0x1.5ce7e466aa429p-5, -0x1.a2b5da779c34cp-6, + -0x1.9b91effbfac51p-5, 0x1.9decca3ad5327p-3, -0x1.8a6ec6e1b7c4cp-6, 0x1.8ba81be384486p-5, + -0x1.ec0d8eaf8ce04p-4, 0x1.aa5b7930d82dfp-10, -0x1.bc328cf1f2d7ap-7, 0x1.d4ed97cc9372bp-4, + 0x1.3900584b7641bp-11, 0x1.5164e98488152p-5, -0x1.0e6353f655f70p-4, 0x1.f78f63cd4c6c9p-5, + -0x1.457c15e5b079ep-4, 0x1.e79f959a7bf8ep-10, 0x1.2d7a5727715d6p-9, -0x1.54fd600dbcbfcp-3, + -0x1.a0fa66db6b2e9p-5, 0x1.a418f05c4f2e4p-6, 0x1.d7b1991770903p-5, 0x1.27b29b62411f9p-3, + -0x1.f7a21cc2f0621p-5, -0x1.990fb456ac92ep-4, 0x1.6e18029b48e18p-4, -0x1.4599b6c0deec6p-6, + -0x1.610422f29b0fdp-6, 0x1.2a5a088890bd6p-4, 0x1.1c1a8edfff970p-4, -0x1.2a94c207a33cfp-5, + -0x1.582f23819e7b4p-5, 0x1.5685268bb3863p-3, -0x1.325c129f02971p-6, -0x1.7d8c683cfe1e7p-5, + -0x1.31caf98d50f3ep-4, 0x1.4b110f25c0f9cp-3, -0x1.b6dd3170bd502p-5, 0x1.2f1ad59ca0026p-4, + -0x1.49a44b667de8fp-4, -0x1.87c403497a448p-4, 0x1.ba5aa37d989dcp-4, -0x1.01cfc952d6e19p-4, + 0x1.64c7dfe5f701fp-5, 0x1.dfeae49b4059fp-4, -0x1.f7599cc97be26p-4, 0x1.76dd9d84dd203p-6, + -0x1.921d0d9ca9b17p-10, -0x1.fff621fee3981p-4, 0x1.f97f925e2e29ep-4, 0x1.4557758bec5d9p-6, + -0x1.4d1e22dc0f23bp-5, 0x1.e426a1b2127f8p-4, -0x1.c08c429bc3b47p-4, -0x1.edc1994bfda37p-5, + 0x1.3fed95807028cp-4, -0x1.8fbccafa5af4ap-4, 0x1.5328295eb1b61p-4, 0x1.7f8ecce919439p-4, + -0x1.b3e4d1f48fd5dp-4, 0x1.0c9704db6214dp-4, -0x1.7c3a8fe72034fp-5, -0x1.db6526e92feb3p-4, + 0x1.f4e604aac775ep-4, -0x1.a82a034f9951dp-6, 0x1.2d864da6e253cp-8, 0x1.ffa72e900de97p-4, + -0x1.fb5796d6907abp-4, -0x1.139f04d52ddb1p-6, 0x1.35410d47e1b9bp-5, -0x1.e817bab0441f2p-4, + 0x1.c678b33ed251ep-4, 0x1.d79778e696dadp-5, -0x1.36058aba84051p-4, 0x1.9777ed3223f08p-4, + -0x1.5c77bc1b53b11p-4, -0x1.771e77f1306dep-4, 0x1.ad2bc8d7eadf0p-4, -0x1.1734d4aba3b80p-4, + 0x1.9372aaf34eb39p-5, 0x1.d69618d31e343p-4, -0x1.f2252ee50d20ep-4, 0x1.d934fc7e00862p-6, + -0x1.f656f3a3f03d4p-8, -0x1.ff09554780affp-4, 0x1.fce160a7eaed5p-4, 0x1.c3785b48b4e61p-7, + -0x1.1d34422e18a2ep-5, 0x1.ebbd8cdfedf0cp-4, -0x1.cc1f0db103254p-4, -0x1.c124999f1bdf1p-5, + 0x1.2bedb157cf4b0p-4, -0x1.9ef4429228a2fp-4, 0x1.6591924a26647p-4, 0x1.6e74461aec049p-4, + -0x1.a6308efa37814p-4, 0x1.21a79b6f1dc4bp-4, -0x1.aa6c82176c27cp-5, -0x1.d17e766aa22abp-4, + 0x1.ef178a88d2dc5p-4, -0x1.04fb7cdfaa368p-5, 0x1.5f6d00e8baabfp-7, 0x1.fe1cb161ab584p-4, + -0x1.fe1cb161ab584p-4, -0x1.5f6d00e8baabfp-7, 0x1.04fb7cdfaa368p-5, -0x1.ef178a88d2dc5p-4, + 0x1.d17e766aa22abp-4, 0x1.aa6c82176c27cp-5, -0x1.21a79b6f1dc4bp-4, 0x1.a6308efa37814p-4, + -0x1.6e74461aec049p-4, -0x1.6591924a26647p-4, 0x1.9ef4429228a2fp-4, -0x1.2bedb157cf4b0p-4, + 0x1.c124999f1bdf1p-5, 0x1.cc1f0db103254p-4, -0x1.ebbd8cdfedf0cp-4, 0x1.1d34422e18a2ep-5, + -0x1.c3785b48b4e61p-7, -0x1.fce160a7eaed5p-4, 0x1.ff09554780affp-4, 0x1.f656f3a3f03d4p-8, + -0x1.d934fc7e00862p-6, 0x1.f2252ee50d20ep-4, -0x1.d69618d31e343p-4, -0x1.9372aaf34eb39p-5, + 0x1.1734d4aba3b80p-4, -0x1.ad2bc8d7eadf0p-4, 0x1.771e77f1306dep-4, 0x1.5c77bc1b53b11p-4, + -0x1.9777ed3223f08p-4, 0x1.36058aba84051p-4, -0x1.d79778e696dadp-5, -0x1.c678b33ed251ep-4, + 0x1.e817bab0441f2p-4, -0x1.35410d47e1b9bp-5, 0x1.139f04d52ddb1p-6, 0x1.fb5796d6907abp-4, + -0x1.ffa72e900de97p-4, -0x1.2d864da6e253cp-8, 0x1.a82a034f9951dp-6, -0x1.f4e604aac775ep-4, + 0x1.db6526e92feb3p-4, 0x1.7c3a8fe72034fp-5, -0x1.0c9704db6214dp-4, 0x1.b3e4d1f48fd5dp-4, + -0x1.7f8ecce919439p-4, -0x1.5328295eb1b61p-4, 0x1.8fbccafa5af4ap-4, -0x1.3fed95807028cp-4, + 0x1.edc1994bfda37p-5, 0x1.c08c429bc3b47p-4, -0x1.e426a1b2127f8p-4, 0x1.4d1e22dc0f23bp-5, + -0x1.4557758bec5d9p-6, -0x1.f97f925e2e29ep-4, 0x1.fff621fee3981p-4, 0x1.921d0d9ca9b17p-10, + -0x1.76dd9d84dd203p-6, 0x1.f7599cc97be26p-4, -0x1.dfeae49b4059fp-4, -0x1.64c7dfe5f701fp-5, + 0x1.01cfc952d6e19p-4, -0x1.ba5aa37d989dcp-4, 0x1.87c403497a453p-4, 0x1.49a44b667de90p-4, + 0x1.87c402e76887ep-4, -0x1.49a44a9cd8126p-4, -0x1.01cfc85539288p-4, -0x1.ba5aa29d42b8ap-4, + -0x1.dfeae5e8cf99bp-4, 0x1.64c7df1c28c44p-5, 0x1.76dd9ca914221p-6, 0x1.f7599c439437bp-4, + 0x1.fff6220f97d34p-4, -0x1.921d1004916afp-10, 0x1.4557758237357p-6, -0x1.f97f929dd70e4p-4, + -0x1.e426a2b9001ecp-4, -0x1.4d1e21effecbap-5, -0x1.edc19786cc39dp-5, 0x1.c08c433855dacp-4, + 0x1.8fbccc7250592p-4, 0x1.3fed941433006p-4, 0x1.7f8ecc9652eeap-4, -0x1.532828fb73a0fp-4, + -0x1.0c9704878b7a9p-4, -0x1.b3e4d05a988bep-4, -0x1.db652594412fap-4, 0x1.7c3a90d742c14p-5, + 0x1.a82a0116a30bfp-6, 0x1.f4e6046301ed6p-4, 0x1.ffa72d20c64d6p-4, -0x1.2d864dfa4e19ep-8, + 0x1.139f03c29f26fp-6, -0x1.fb57969e45648p-4, -0x1.e817bc49a06e8p-4, -0x1.35410d9b554c8p-5, + -0x1.d7977927aa0c1p-5, 0x1.c678b3ab7f990p-4, 0x1.9777ee4038579p-4, 0x1.36058a6065777p-4, + 0x1.771e77912cdbdp-4, -0x1.5c77bbdc0d7f5p-4, -0x1.1734d42e8300ap-4, -0x1.ad2bc9b8b2e85p-4, + -0x1.d6961884aaa76p-4, 0x1.9372aa2c6d66bp-5, 0x1.d934fdbb520aap-6, 0x1.f2252e8ef426cp-4, + 0x1.ff09553dd48a8p-4, -0x1.f656f41bb5535p-8, 0x1.c3785a27ec99dp-7, -0x1.fce15ff2f4e21p-4, + -0x1.ebbd8dc404036p-4, -0x1.1d34429530f41p-5, -0x1.c1249a1d3cb55p-5, 0x1.cc1f0ea548688p-4, + 0x1.9ef442bd36b4cp-4, 0x1.2bedb14e14be8p-4, 0x1.6e74468daf1bep-4, -0x1.6591935299cbap-4, + -0x1.21a79b78f6943p-4, -0x1.a630906abf3b1p-4, -0x1.d17e76a18fb42p-4, 0x1.aa6c7ff8c3c71p-5, + 0x1.04fb7cb45db50p-5, 0x1.ef17896d8dc72p-4, 0x1.fe1cb27ce2cd6p-4, -0x1.5f6cfebe50b2fp-7, + 0x1.5f6cfebe50b2fp-7, -0x1.fe1cb27ce2cd6p-4, -0x1.ef17896d8dc72p-4, -0x1.04fb7cb45db50p-5, + -0x1.aa6c7ff8c3c71p-5, 0x1.d17e76a18fb42p-4, 0x1.a630906abf3b1p-4, 0x1.21a79b78f6943p-4, + 0x1.6591935299cbap-4, -0x1.6e74468daf1bep-4, -0x1.2bedb14e14be8p-4, -0x1.9ef442bd36b4cp-4, + -0x1.cc1f0ea548688p-4, 0x1.c1249a1d3cb55p-5, 0x1.1d34429530f41p-5, 0x1.ebbd8dc404036p-4, + 0x1.fce15ff2f4e21p-4, -0x1.c3785a27ec99dp-7, 0x1.f656f41bb5535p-8, -0x1.ff09553dd48a8p-4, + -0x1.f2252e8ef426cp-4, -0x1.d934fdbb520aap-6, -0x1.9372aa2c6d66bp-5, 0x1.d6961884aaa76p-4, + 0x1.ad2bc9b8b2e85p-4, 0x1.1734d42e8300ap-4, 0x1.5c77bbdc0d7f5p-4, -0x1.771e77912cdbdp-4, + -0x1.36058a6065777p-4, -0x1.9777ee4038579p-4, -0x1.c678b3ab7f990p-4, 0x1.d7977927aa0c1p-5, + 0x1.35410d9b554c8p-5, 0x1.e817bc49a06e8p-4, 0x1.fb57969e45648p-4, -0x1.139f03c29f26fp-6, + 0x1.2d864dfa4e19ep-8, -0x1.ffa72d20c64d6p-4, -0x1.f4e6046301ed6p-4, -0x1.a82a0116a30bfp-6, + -0x1.7c3a90d742c14p-5, 0x1.db652594412fap-4, 0x1.b3e4d05a988bep-4, 0x1.0c9704878b7a9p-4, + 0x1.532828fb73a0fp-4, -0x1.7f8ecc9652eeap-4, -0x1.3fed941433006p-4, -0x1.8fbccc7250592p-4, + -0x1.c08c433855dacp-4, 0x1.edc19786cc39dp-5, 0x1.4d1e21effecbap-5, 0x1.e426a2b9001ecp-4, + 0x1.f97f929dd70e4p-4, -0x1.4557758237357p-6, 0x1.921d1004916afp-10, -0x1.fff6220f97d34p-4, + -0x1.f7599c439437bp-4, -0x1.76dd9ca914221p-6, -0x1.64c7df1c28c44p-5, 0x1.dfeae5e8cf99bp-4, + 0x1.ba5aa29d42b8ap-4, 0x1.01cfc85539288p-4, 0x1.49a44a9cd8127p-4, -0x1.87c402e768892p-4, + 0x1.c37d9825629c3p-6, -0x1.02db33c4e50edp-5, -0x1.52ae390eb132ap-4, -0x1.894a0df8d34d0p-3, + 0x1.2dd691ba4e88ep-7, 0x1.a45350a1eacaap-6, -0x1.30cabc9f5a7d6p-6, -0x1.6cb938ce2034cp-4, + 0x1.12ac323169ef1p-4, 0x1.68afde3396008p-8, 0x1.0b2a89809d7bfp-10, 0x1.f9cb2d538fc3fp-4, + 0x1.3352c5a2ab2d7p-3, -0x1.e731f138399bcp-6, -0x1.706ca913ac199p-4, -0x1.5dcafcda78b5cp-7, + -0x1.a126385724421p-3, 0x1.6ae1e6130ac8fp-5, -0x1.5aaca852e32ecp-5, 0x1.bd42f86c8857bp-5, + -0x1.781eff6f9eb06p-5, -0x1.544af5b811f09p-3, 0x1.6baeb23d309bbp-4, 0x1.872e7954e4edcp-6, + -0x1.d620249d5dce7p-8, -0x1.32e843934785ep-4, 0x1.8778de011fa21p-4, -0x1.299c80f57ce6ap-7, + 0x1.488dd69b889e8p-6, 0x1.47dceff8f0dc7p-4, 0x1.7365c0e472691p-6, -0x1.4b3b9ce7f34fap-9, + 0x1.17b35bf675fc6p-5, 0x1.576a10e54e937p-4, -0x1.aa1a9a1aaaae0p-4, 0x1.a5856d7a542a1p-4, + 0x1.35e822697afa3p-7, 0x1.47e20496a3864p-5, -0x1.a6854978e8f53p-5, 0x1.af112c7dc9530p-4, + 0x1.449508ff2a829p-5, -0x1.fe340fa9b82bdp-5, -0x1.5a4a7abd9dc1ep-5, 0x1.b5aace1d97254p-3, + 0x1.825e89cdc72a5p-4, 0x1.3abd557921c7bp-9, 0x1.0ea6a66094f85p-5, -0x1.e46f0b23fd163p-3, + -0x1.557e534bef387p-5, 0x1.bdc7b308d84d8p-10, 0x1.442cdc6885529p-5, -0x1.0a68c715bb7cbp-3, + -0x1.bee26ad7ad518p-4, 0x1.2a058b9c19c88p-7, 0x1.ce8cf50a76f9ep-3, 0x1.32ea49cf5ad61p-4, + 0x1.0b27705d043fbp-7, 0x1.d96a6dde9c51bp-7, 0x1.27e77e71c163bp-3, 0x1.e98cfe76169c8p-5, + 0x1.cc5cdc76a8fe4p-7, 0x1.8f6551592f116p-6, -0x1.5e13b481c8a9ap-4, 0x1.f249732767ef9p-10, + -0x1.f249732767ef9p-10, 0x1.5e13b481c8a9ap-4, -0x1.8f6551592f116p-6, -0x1.cc5cdc76a8fe4p-7, + -0x1.e98cfe76169c8p-5, -0x1.27e77e71c163bp-3, -0x1.d96a6dde9c51bp-7, -0x1.0b27705d043fbp-7, + -0x1.32ea49cf5ad61p-4, -0x1.ce8cf50a76f9ep-3, -0x1.2a058b9c19c88p-7, 0x1.bee26ad7ad518p-4, + 0x1.0a68c715bb7cbp-3, -0x1.442cdc6885529p-5, -0x1.bdc7b308d84d8p-10, 0x1.557e534bef387p-5, + 0x1.e46f0b23fd163p-3, -0x1.0ea6a66094f85p-5, -0x1.3abd557921c7bp-9, -0x1.825e89cdc72a5p-4, + -0x1.b5aace1d97254p-3, 0x1.5a4a7abd9dc1ep-5, 0x1.fe340fa9b82bdp-5, -0x1.449508ff2a829p-5, + -0x1.af112c7dc9530p-4, 0x1.a6854978e8f53p-5, -0x1.47e20496a3864p-5, -0x1.35e822697afa3p-7, + -0x1.a5856d7a542a1p-4, 0x1.aa1a9a1aaaae0p-4, -0x1.576a10e54e937p-4, -0x1.17b35bf675fc6p-5, + 0x1.4b3b9ce7f34fap-9, -0x1.7365c0e472691p-6, -0x1.47dceff8f0dc7p-4, -0x1.488dd69b889e8p-6, + 0x1.299c80f57ce6ap-7, -0x1.8778de011fa21p-4, 0x1.32e843934785ep-4, 0x1.d620249d5dce7p-8, + -0x1.872e7954e4edcp-6, -0x1.6baeb23d309bbp-4, 0x1.544af5b811f09p-3, 0x1.781eff6f9eb06p-5, + -0x1.bd42f86c8857bp-5, 0x1.5aaca852e32ecp-5, -0x1.6ae1e6130ac8fp-5, 0x1.a126385724421p-3, + 0x1.5dcafcda78b5cp-7, 0x1.706ca913ac199p-4, 0x1.e731f138399bcp-6, -0x1.3352c5a2ab2d7p-3, + -0x1.f9cb2d538fc3fp-4, -0x1.0b2a89809d7bfp-10, -0x1.68afde3396008p-8, -0x1.12ac323169ef1p-4, + 0x1.6cb938ce2034cp-4, 0x1.30cabc9f5a7d8p-6, -0x1.a45350a1eac99p-6, -0x1.2dd691ba4e887p-7, + 0x1.894a0df8d34d1p-3, 0x1.52ae390eb1323p-4, 0x1.02db339f36d57p-5, -0x1.c37d914ce764dp-6, + -0x1.31de853684c03p-5, -0x1.2681cf7f088d0p-6, -0x1.dd08baafdfaddp-5, -0x1.b3b2e438a6afbp-6, + 0x1.90fe7f1244663p-6, -0x1.67d5ddac25493p-5, 0x1.00b626a6a6c1fp-5, 0x1.f034665bbd8a5p-7, + -0x1.4dcc22788c314p-12, -0x1.f427dec2db729p-5, 0x1.07eb1e19e8336p-5, 0x1.54ca484b8158ap-5, + 0x1.ac0c71183cc30p-6, 0x1.48ea88bf5bf07p-4, -0x1.ec1ec04a6f7a6p-8, -0x1.a107dea5e845ep-4, + -0x1.67a133208bfc0p-6, 0x1.1bb0e898f0e31p-3, 0x1.b96b648bb546bp-4, 0x1.2fcb34bb01af8p-6, + -0x1.2798793669198p-3, -0x1.e88c4f4d441fdp-4, 0x1.80a0c490fd40cp-4, -0x1.0dce11ad073cep-3, + 0x1.1d60185f60f89p-4, -0x1.1bd4d86b1f29dp-4, -0x1.fcf1935aacdc1p-10, 0x1.27bf291abe0ebp-3, + -0x1.4334bc5372019p-3, -0x1.02459896daf29p-7, 0x1.5c118c153bbf8p-5, 0x1.57ce9a9d1087bp-3, + -0x1.3deed31a4426fp-4, -0x1.18e9862a67ea6p-4, 0x1.8f0cea44c5b02p-4, 0x1.65baa08747271p-5, + -0x1.9683ee625b84ap-4, -0x1.57b1cba971747p-3, -0x1.515effc783e91p-3, 0x1.f81027938cb0dp-4, + 0x1.9e910ac4143bep-4, 0x1.eb22e2ccfce88p-4, 0x1.3668d2f3198d7p-3, 0x1.a60d124a35912p-8, + 0x1.0e59d32d431b4p-7, -0x1.8ff9955ec5798p-5, -0x1.0d8269e91e38bp-2, -0x1.202da4a21ebadp-5, + 0x1.0430efcd7f30ep-5, -0x1.4d954e02a0285p-4, 0x1.2a003c4690907p-5, 0x1.d31b2bce237efp-7, + 0x1.55f6af47905d9p-4, -0x1.0ae64ea71920fp-4, -0x1.81f5467973990p-4, -0x1.237b537fc2dd6p-4, + 0x1.482eacdc088a1p-6, 0x1.38b85d113b068p-11, -0x1.6fe55a8acd954p-6, -0x1.1bacf42401d99p-4, + 0x1.21b601d00ae88p-4, 0x1.7ffbcbe1b9cbdp-8, 0x1.225163f037798p-8, -0x1.215fc130d435ap-3, + 0x1.215fc130d435ap-3, -0x1.225163f037798p-8, -0x1.7ffbcbe1b9cbdp-8, -0x1.21b601d00ae88p-4, + 0x1.1bacf42401d99p-4, 0x1.6fe55a8acd954p-6, -0x1.38b85d113b068p-11, -0x1.482eacdc088a1p-6, + 0x1.237b537fc2dd6p-4, 0x1.81f5467973990p-4, 0x1.0ae64ea71920fp-4, -0x1.55f6af47905d9p-4, + -0x1.d31b2bce237efp-7, -0x1.2a003c4690907p-5, 0x1.4d954e02a0285p-4, -0x1.0430efcd7f30ep-5, + 0x1.202da4a21ebadp-5, 0x1.0d8269e91e38bp-2, 0x1.8ff9955ec5798p-5, -0x1.0e59d32d431b4p-7, + -0x1.a60d124a35912p-8, -0x1.3668d2f3198d7p-3, -0x1.eb22e2ccfce88p-4, -0x1.9e910ac4143bep-4, + -0x1.f81027938cb0dp-4, 0x1.515effc783e91p-3, 0x1.57b1cba971747p-3, 0x1.9683ee625b84ap-4, + -0x1.65baa08747271p-5, -0x1.8f0cea44c5b02p-4, 0x1.18e9862a67ea6p-4, 0x1.3deed31a4426fp-4, + -0x1.57ce9a9d1087bp-3, -0x1.5c118c153bbf8p-5, 0x1.02459896daf29p-7, 0x1.4334bc5372019p-3, + -0x1.27bf291abe0ebp-3, 0x1.fcf1935aacdc1p-10, 0x1.1bd4d86b1f29dp-4, -0x1.1d60185f60f89p-4, + 0x1.0dce11ad073cep-3, -0x1.80a0c490fd40cp-4, 0x1.e88c4f4d441fdp-4, 0x1.2798793669198p-3, + -0x1.2fcb34bb01af8p-6, -0x1.b96b648bb546bp-4, -0x1.1bb0e898f0e31p-3, 0x1.67a133208bfc0p-6, + 0x1.a107dea5e845ep-4, 0x1.ec1ec04a6f7a6p-8, -0x1.48ea88bf5bf07p-4, -0x1.ac0c71183cc30p-6, + -0x1.54ca484b8158ap-5, -0x1.07eb1e19e8336p-5, 0x1.f427dec2db729p-5, 0x1.4dcc22788c314p-12, + -0x1.f034665bbd8a1p-7, -0x1.00b626a6a6c23p-5, 0x1.67d5ddac2548fp-5, -0x1.90fe7f124465fp-6, + 0x1.b3b2e438a6b26p-6, 0x1.dd08baafdfacfp-5, 0x1.2681d2fac4b01p-6, 0x1.31de861d16207p-5, + -0x1.53282a7d1092ap-4, -0x1.7f8ecd27850e4p-4, 0x1.a63091ac53e35p-4, -0x1.21a79a8ec2ee6p-4, + 0x1.d797768180572p-5, 0x1.c678b336f8d8ap-4, -0x1.dfeae8137cc3bp-4, 0x1.64c7dbc0f6177p-5, + -0x1.d93504ac3abbfp-6, -0x1.f22531ab89b24p-4, 0x1.fce160ce04d2dp-4, -0x1.c37846601fd14p-7, + -0x1.921d2daf35e15p-10, 0x1.fff6233135167p-4, -0x1.fb579968c2302p-4, -0x1.139f1ded9cf5dp-6, + 0x1.04fb82729823dp-5, -0x1.ef178aba45ef2p-4, 0x1.db6527c61cc94p-4, 0x1.7c3a940851c90p-5, + -0x1.edc19470a870cp-5, 0x1.c08c414240344p-4, -0x1.9ef43ce8a8ae2p-4, -0x1.2bedb0f70d177p-4, + 0x1.5c77b888b2af6p-4, -0x1.771e7551d813dp-4, 0x1.49a445f90cce7p-4, 0x1.87c401d529f20p-4, + -0x1.ad2bcc92831e9p-4, 0x1.1734d87650e19p-4, -0x1.c1249dff3e6c2p-5, -0x1.cc1f0bdcec929p-4, + 0x1.e426a5c3dfe8dp-4, -0x1.4d1e22835fd0dp-5, 0x1.a829ffd315d44p-6, 0x1.f4e603ee968cbp-4, + -0x1.fe1cb155f3b83p-4, 0x1.5f6d0274d886ap-7, 0x1.2d86754399378p-8, -0x1.ffa72e08fd61dp-4, + 0x1.f97f927737512p-4, 0x1.45575f74eefacp-6, -0x1.1d3443205253dp-5, 0x1.ebbd876c59090p-4, + -0x1.d6961597c3f91p-4, -0x1.9372a754d4753p-5, 0x1.01cfca73bab28p-4, -0x1.ba5aa3f717674p-4, + 0x1.9777ed7eeb65ap-4, 0x1.3605887129c65p-4, -0x1.6591938278cd6p-4, 0x1.6e74428ca8e4bp-4, + -0x1.3fed97333b554p-4, -0x1.8fbccd875271fp-4, 0x1.b3e4d3ddbe46ap-4, -0x1.0c97063fd6930p-4, + 0x1.aa6c842e5e458p-5, 0x1.d17e73c50dce4p-4, -0x1.e817ba01012d0p-4, 0x1.35410b82c7b0ep-5, + -0x1.76ddaa16b0046p-6, -0x1.f7599b3c88723p-4, 0x1.ff0959cb4f8f9p-4, -0x1.f656cb391b98dp-8, + -0x1.f656cb391b98dp-8, 0x1.ff0959cb4f8f9p-4, -0x1.f7599b3c88723p-4, -0x1.76ddaa16b0046p-6, + 0x1.35410b82c7b0ep-5, -0x1.e817ba01012d0p-4, 0x1.d17e73c50dce4p-4, 0x1.aa6c842e5e458p-5, + -0x1.0c97063fd6930p-4, 0x1.b3e4d3ddbe46ap-4, -0x1.8fbccd875271fp-4, -0x1.3fed97333b554p-4, + 0x1.6e74428ca8e4bp-4, -0x1.6591938278cd6p-4, 0x1.3605887129c65p-4, 0x1.9777ed7eeb65ap-4, + -0x1.ba5aa3f717674p-4, 0x1.01cfca73bab28p-4, -0x1.9372a754d4753p-5, -0x1.d6961597c3f91p-4, + 0x1.ebbd876c59090p-4, -0x1.1d3443205253dp-5, 0x1.45575f74eefacp-6, 0x1.f97f927737512p-4, + -0x1.ffa72e08fd61dp-4, 0x1.2d86754399378p-8, 0x1.5f6d0274d886ap-7, -0x1.fe1cb155f3b83p-4, + 0x1.f4e603ee968cbp-4, 0x1.a829ffd315d44p-6, -0x1.4d1e22835fd0dp-5, 0x1.e426a5c3dfe8dp-4, + -0x1.cc1f0bdcec929p-4, -0x1.c1249dff3e6c2p-5, 0x1.1734d87650e19p-4, -0x1.ad2bcc92831e9p-4, + 0x1.87c401d529f20p-4, 0x1.49a445f90cce7p-4, -0x1.771e7551d813dp-4, 0x1.5c77b888b2af6p-4, + -0x1.2bedb0f70d177p-4, -0x1.9ef43ce8a8ae2p-4, 0x1.c08c414240344p-4, -0x1.edc19470a870cp-5, + 0x1.7c3a940851c90p-5, 0x1.db6527c61cc94p-4, -0x1.ef178aba45ef2p-4, 0x1.04fb82729823dp-5, + -0x1.139f1ded9cf5dp-6, -0x1.fb579968c2302p-4, 0x1.fff6233135167p-4, -0x1.921d2daf35e15p-10, + -0x1.c37846601fd14p-7, 0x1.fce160ce04d2dp-4, -0x1.f22531ab89b24p-4, -0x1.d93504ac3abbfp-6, + 0x1.64c7dbc0f6177p-5, -0x1.dfeae8137cc3bp-4, 0x1.c678b336f8d8ap-4, 0x1.d797768180572p-5, + -0x1.21a79a8ec2ee6p-4, 0x1.a63091ac53e35p-4, -0x1.7f8ecd27850ddp-4, -0x1.53282a7d1092bp-4, + 0x1.7f8ecd4731600p-4, -0x1.53282a738e116p-4, -0x1.21a79aaf05bbcp-4, -0x1.a630915573d96p-4, + -0x1.c678b49e4e5b6p-4, 0x1.d797764e7da91p-5, 0x1.64c7db7a7547cp-5, 0x1.dfeae5c8906f7p-4, + 0x1.f22531b81bb25p-4, -0x1.d93506fb83248p-6, -0x1.c37846fd898c2p-7, -0x1.fce1603e3a20ep-4, + -0x1.fff6245377718p-4, -0x1.921d2925ed328p-10, -0x1.139f1de17bc53p-6, 0x1.fb5798289155fp-4, + 0x1.ef178c14dec01p-4, 0x1.04fb8226dc7cdp-5, 0x1.7c3a933bd5629p-5, -0x1.db65274a20f91p-4, + -0x1.c08c40f93fa7cp-4, -0x1.edc19536fabb6p-5, -0x1.2bedb0fd10af0p-4, 0x1.9ef43d6a14eabp-4, + 0x1.771e755c156d2p-4, 0x1.5c77b86336386p-4, 0x1.87c401ffee856p-4, -0x1.49a445c8bf7f4p-4, + -0x1.1734d95fd1230p-4, -0x1.ad2bcbf57caa8p-4, -0x1.cc1f0d5399decp-4, 0x1.c1249e99f0e93p-5, + 0x1.4d1e22ac80c67p-5, 0x1.e426a4956fc77p-4, 0x1.f4e6059345d27p-4, -0x1.a829fdfc18827p-6, + -0x1.5f6d03e67f3d0p-7, -0x1.fe1cb13d01d37p-4, -0x1.ffa72e0018d28p-4, -0x1.2d86759d5e5a4p-8, + -0x1.45575fc23126ap-6, 0x1.f97f91acd6387p-4, 0x1.ebbd877b91fc8p-4, 0x1.1d34434e7289ep-5, + 0x1.9372a6c78b2bfp-5, -0x1.d696160e6c262p-4, -0x1.ba5aa417af3b1p-4, -0x1.01cfcb23e02edp-4, + -0x1.360588909c1aap-4, 0x1.9777ee35f4e60p-4, 0x1.6e7442ed3f71bp-4, 0x1.659192835f3b0p-4, + 0x1.8fbccd65188f6p-4, -0x1.3fed968d5247ap-4, -0x1.0c9706a7a9d5dp-4, -0x1.b3e4d24fbbdd7p-4, + -0x1.d17e748d6a40cp-4, 0x1.aa6c862301e81p-5, 0x1.35410be3ca6d1p-5, 0x1.e817b8c4dd44cp-4, + 0x1.f7599c3f6ca13p-4, -0x1.76dda98b809cep-6, -0x1.f656ca990aedfp-8, -0x1.ff09590cb08efp-4, + -0x1.ff09590cb08efp-4, -0x1.f656ca990aedfp-8, -0x1.76dda98b809cep-6, 0x1.f7599c3f6ca13p-4, + 0x1.e817b8c4dd44cp-4, 0x1.35410be3ca6d1p-5, 0x1.aa6c862301e81p-5, -0x1.d17e748d6a40cp-4, + -0x1.b3e4d24fbbdd7p-4, -0x1.0c9706a7a9d5dp-4, -0x1.3fed968d5247ap-4, 0x1.8fbccd65188f6p-4, + 0x1.659192835f3b0p-4, 0x1.6e7442ed3f71bp-4, 0x1.9777ee35f4e60p-4, -0x1.360588909c1aap-4, + -0x1.01cfcb23e02edp-4, -0x1.ba5aa417af3b1p-4, -0x1.d696160e6c262p-4, 0x1.9372a6c78b2bfp-5, + 0x1.1d34434e7289ep-5, 0x1.ebbd877b91fc8p-4, 0x1.f97f91acd6387p-4, -0x1.45575fc23126ap-6, + -0x1.2d86759d5e5a4p-8, -0x1.ffa72e0018d28p-4, -0x1.fe1cb13d01d37p-4, -0x1.5f6d03e67f3d0p-7, + -0x1.a829fdfc18827p-6, 0x1.f4e6059345d27p-4, 0x1.e426a4956fc77p-4, 0x1.4d1e22ac80c67p-5, + 0x1.c1249e99f0e93p-5, -0x1.cc1f0d5399decp-4, -0x1.ad2bcbf57caa8p-4, -0x1.1734d95fd1230p-4, + -0x1.49a445c8bf7f4p-4, 0x1.87c401ffee856p-4, 0x1.5c77b86336386p-4, 0x1.771e755c156d2p-4, + 0x1.9ef43d6a14eabp-4, -0x1.2bedb0fd10af0p-4, -0x1.edc19536fabb6p-5, -0x1.c08c40f93fa7cp-4, + -0x1.db65274a20f91p-4, 0x1.7c3a933bd5629p-5, 0x1.04fb8226dc7cdp-5, 0x1.ef178c14dec01p-4, + 0x1.fb5798289155fp-4, -0x1.139f1de17bc53p-6, -0x1.921d2925ed328p-10, -0x1.fff6245377718p-4, + -0x1.fce1603e3a20ep-4, -0x1.c37846fd898c2p-7, -0x1.d93506fb83248p-6, 0x1.f22531b81bb25p-4, + 0x1.dfeae5c8906f7p-4, 0x1.64c7db7a7547cp-5, 0x1.d797764e7da91p-5, -0x1.c678b49e4e5b6p-4, + -0x1.a630915573d96p-4, -0x1.21a79aaf05bbcp-4, -0x1.53282a738e115p-4, 0x1.7f8ecd47315e6p-4, + 0x1.d6370a4e217dep-3, -0x1.02f8ab0097408p-9, -0x1.61b4f6a9cad67p-7, 0x1.496a75477e761p-6, + 0x1.90c21b95ce80dp-5, 0x1.48a2e223823fdp-5, 0x1.49d0d3ab9dad7p-8, 0x1.488b26299f207p-3, + -0x1.8d4a9377ddaa8p-3, -0x1.92ac93c00bf76p-6, 0x1.294877e10c7dep-6, -0x1.dbedc79cef0e1p-7, + 0x1.5f8fc436cec39p-3, -0x1.acd215ca68391p-8, -0x1.7ebe5463e6a74p-5, -0x1.325abedff7065p-6, + -0x1.b9b163359068fp-6, -0x1.1a6fc6b600ffap-9, 0x1.d8b3722bacc69p-6, 0x1.e50ee4aea2a97p-4, + 0x1.379b543780196p-4, 0x1.2ceccb42c2f2cp-4, 0x1.5768e901e1e1ap-6, -0x1.72d0e7dd41cc1p-5, + -0x1.addc3adde3de3p-5, -0x1.16029d4223162p-8, -0x1.c78fb63b2b87bp-4, -0x1.0efd48619db21p-4, + 0x1.f40dff288afebp-5, -0x1.5f1f65ff145cap-3, 0x1.40b9f97e4f780p-4, 0x1.ffb1323bdbf96p-5, + 0x1.5a421c1a7f343p-4, 0x1.8a2badd7e567ap-3, -0x1.99fc8530a436fp-6, -0x1.64a343f05f463p-4, + -0x1.4ac06ca05964ap-7, -0x1.7dda41a6cb4b8p-9, -0x1.70daa25c58992p-6, -0x1.106ceb96bf24bp-5, + 0x1.c51128257d67fp-7, 0x1.8f5a48c31f9b2p-3, 0x1.df10c76140a1dp-4, -0x1.b1c68360fd933p-6, + 0x1.a8ed48da28032p-6, 0x1.4c97b03881e7cp-4, 0x1.26dd4f851a94dp-6, -0x1.b9115226db427p-5, + -0x1.5802d837adffbp-6, -0x1.8465d9d35670fp-3, 0x1.f56784105832dp-6, 0x1.34f52e8d5cc37p-4, + -0x1.17528d8bc13a4p-3, -0x1.76fd56707bdffp-4, 0x1.b7f0a8bdcac43p-4, -0x1.2ab9c60ab3423p-3, + -0x1.7e4a2a79d6b35p-4, -0x1.45156b662eff7p-6, 0x1.c33b4311648bep-10, 0x1.0d1db0b4039fdp-7, + -0x1.29ad68be5acacp-3, -0x1.d368eddd89667p-5, 0x1.b3580427d6a21p-7, 0x1.66e0f02e15fcbp-6, + 0x1.66e0f02e15fcbp-6, 0x1.b3580427d6a21p-7, -0x1.d368eddd89667p-5, -0x1.29ad68be5acacp-3, + 0x1.0d1db0b4039fdp-7, 0x1.c33b4311648bep-10, -0x1.45156b662eff7p-6, -0x1.7e4a2a79d6b35p-4, + -0x1.2ab9c60ab3423p-3, 0x1.b7f0a8bdcac43p-4, -0x1.76fd56707bdffp-4, -0x1.17528d8bc13a4p-3, + 0x1.34f52e8d5cc37p-4, 0x1.f56784105832dp-6, -0x1.8465d9d35670fp-3, -0x1.5802d837adffbp-6, + -0x1.b9115226db427p-5, 0x1.26dd4f851a94dp-6, 0x1.4c97b03881e7cp-4, 0x1.a8ed48da28032p-6, + -0x1.b1c68360fd933p-6, 0x1.df10c76140a1dp-4, 0x1.8f5a48c31f9b2p-3, 0x1.c51128257d67fp-7, + -0x1.106ceb96bf24bp-5, -0x1.70daa25c58992p-6, -0x1.7dda41a6cb4b8p-9, -0x1.4ac06ca05964ap-7, + -0x1.64a343f05f463p-4, -0x1.99fc8530a436fp-6, 0x1.8a2badd7e567ap-3, 0x1.5a421c1a7f343p-4, + 0x1.ffb1323bdbf96p-5, 0x1.40b9f97e4f780p-4, -0x1.5f1f65ff145cap-3, 0x1.f40dff288afebp-5, + -0x1.0efd48619db21p-4, -0x1.c78fb63b2b87bp-4, -0x1.16029d4223162p-8, -0x1.addc3adde3de3p-5, + -0x1.72d0e7dd41cc1p-5, 0x1.5768e901e1e1ap-6, 0x1.2ceccb42c2f2cp-4, 0x1.379b543780196p-4, + 0x1.e50ee4aea2a97p-4, 0x1.d8b3722bacc69p-6, -0x1.1a6fc6b600ffap-9, -0x1.b9b163359068fp-6, + -0x1.325abedff7065p-6, -0x1.7ebe5463e6a74p-5, -0x1.acd215ca68391p-8, 0x1.5f8fc436cec39p-3, + -0x1.dbedc79cef0e1p-7, 0x1.294877e10c7dep-6, -0x1.92ac93c00bf76p-6, -0x1.8d4a9377ddaa8p-3, + 0x1.488b26299f207p-3, 0x1.49d0d3ab9da8bp-8, 0x1.48a2e223823fdp-5, 0x1.90c21b95ce821p-5, + 0x1.496a75477e771p-6, -0x1.61b4f6a9cacc6p-7, -0x1.02f8ae82abff4p-9, 0x1.d6370a6c02bcep-3, + 0x1.2a5839acf4549p-4, 0x1.9b46bb447e92dp-4, 0x1.49a59d8128c4fp-4, -0x1.c01d270527c62p-5, + -0x1.0530807d6898bp-4, -0x1.01b0c72852595p-2, -0x1.121f359ff71b4p-3, -0x1.194a03f6d786cp-5, + 0x1.5071e1283ee5ap-4, 0x1.ae4cf7b30d83cp-6, -0x1.6c5c5be1c3bf7p-5, -0x1.9356cb2037a93p-9, + -0x1.b51688f751654p-5, -0x1.a54d8db6be8dap-4, -0x1.66a5c271e54a9p-4, 0x1.1a8a0c74a0fd1p-8, + 0x1.0c5e3335922dcp-4, 0x1.08d9b1599b8a3p-4, 0x1.89ba9b8b21a78p-6, 0x1.50774eb2d1f92p-8, + -0x1.b7a4c13bb2ee6p-6, -0x1.d59f75f979aedp-4, -0x1.034b92a588a6cp-3, 0x1.d2fcd12a4cb29p-5, + -0x1.02651e0ebdde7p-4, -0x1.de33231c3c987p-4, -0x1.93dd63dcda6ccp-5, 0x1.421522cd6fbc3p-4, + -0x1.a66bce841e4f8p-7, 0x1.c5df3154fc469p-5, 0x1.4306143481647p-5, 0x1.39acbed428254p-3, + 0x1.02d84bf927c74p-3, -0x1.2191ff1292095p-5, -0x1.eb99c84081739p-11, -0x1.40925a5714235p-3, + -0x1.f26ffdab1743fp-6, -0x1.c160b741cb61cp-6, 0x1.6941081a750b3p-10, -0x1.8cc5055de3a6ap-4, + -0x1.20709e4339cacp-3, -0x1.7826abc74029fp-5, 0x1.991665e165b18p-6, -0x1.dc44893a3f586p-3, + -0x1.c35bf9f615759p-4, 0x1.964f154c4a492p-5, 0x1.3d3632a2fdf8ep-5, 0x1.71337e70c5d58p-6, + 0x1.a4716596b75abp-4, 0x1.38682e75a1de7p-6, -0x1.397ad42ebd3cep-4, 0x1.0dc8bb50648e6p-4, + 0x1.f2d7b04f86fadp-5, -0x1.21c631baa8f99p-3, 0x1.23fd5bdfb919fp-4, 0x1.47554ba4c598fp-8, + -0x1.1779ffb239995p-4, -0x1.9e3610aa65183p-4, -0x1.436b5ff117406p-3, -0x1.92af57a54ddffp-6, + 0x1.a9bae5964d342p-5, -0x1.e5a982204541fp-4, 0x1.72c322b749008p-4, -0x1.0d0cf3eb7934fp-7, + -0x1.0d0cf3eb7934fp-7, 0x1.72c322b749008p-4, -0x1.e5a982204541fp-4, 0x1.a9bae5964d342p-5, + -0x1.92af57a54ddffp-6, -0x1.436b5ff117406p-3, -0x1.9e3610aa65183p-4, -0x1.1779ffb239995p-4, + 0x1.47554ba4c598fp-8, 0x1.23fd5bdfb919fp-4, -0x1.21c631baa8f99p-3, 0x1.f2d7b04f86fadp-5, + 0x1.0dc8bb50648e6p-4, -0x1.397ad42ebd3cep-4, 0x1.38682e75a1de7p-6, 0x1.a4716596b75abp-4, + 0x1.71337e70c5d58p-6, 0x1.3d3632a2fdf8ep-5, 0x1.964f154c4a492p-5, -0x1.c35bf9f615759p-4, + -0x1.dc44893a3f586p-3, 0x1.991665e165b18p-6, -0x1.7826abc74029fp-5, -0x1.20709e4339cacp-3, + -0x1.8cc5055de3a6ap-4, 0x1.6941081a750b3p-10, -0x1.c160b741cb61cp-6, -0x1.f26ffdab1743fp-6, + -0x1.40925a5714235p-3, -0x1.eb99c84081739p-11, -0x1.2191ff1292095p-5, 0x1.02d84bf927c74p-3, + 0x1.39acbed428254p-3, 0x1.4306143481647p-5, 0x1.c5df3154fc469p-5, -0x1.a66bce841e4f8p-7, + 0x1.421522cd6fbc3p-4, -0x1.93dd63dcda6ccp-5, -0x1.de33231c3c987p-4, -0x1.02651e0ebdde7p-4, + 0x1.d2fcd12a4cb29p-5, -0x1.034b92a588a6cp-3, -0x1.d59f75f979aedp-4, -0x1.b7a4c13bb2ee6p-6, + 0x1.50774eb2d1f92p-8, 0x1.89ba9b8b21a78p-6, 0x1.08d9b1599b8a3p-4, 0x1.0c5e3335922dcp-4, + 0x1.1a8a0c74a0fd1p-8, -0x1.66a5c271e54a9p-4, -0x1.a54d8db6be8dap-4, -0x1.b51688f751654p-5, + -0x1.9356cb2037a93p-9, -0x1.6c5c5be1c3bf7p-5, 0x1.ae4cf7b30d83cp-6, 0x1.5071e1283ee5ap-4, + -0x1.194a03f6d7871p-5, -0x1.121f359ff71b4p-3, -0x1.01b0c72852598p-2, -0x1.0530807d68991p-4, + -0x1.c01d270527c7ap-5, 0x1.49a59d8128c45p-4, 0x1.9b46ba9364787p-4, 0x1.2a58397cbfea3p-4, + -0x1.5c77beea0ec92p-4, -0x1.771e77669fec4p-4, 0x1.8fbcc989c2d40p-4, -0x1.3fed939521d1fp-4, + 0x1.21a79ce6042e5p-4, 0x1.a63090d2a223dp-4, -0x1.ba5aa75b0887bp-4, 0x1.01cfc763fb280p-4, + -0x1.c1249fce97e5ep-5, -0x1.cc1f0fd5e5d7ap-4, 0x1.db6527e217b71p-4, -0x1.7c3a913ec3199p-5, + 0x1.3541105b89a81p-5, 0x1.e817bc0383e56p-4, -0x1.f225301e9d4e3p-4, 0x1.d934ff4027cabp-6, + -0x1.4557752cc9bc5p-6, -0x1.f97f94d2b7e80p-4, 0x1.fe1cb00a5688ap-4, -0x1.5f6cf50c44d57p-7, + 0x1.921d163f3bbc9p-10, 0x1.fff6218e00f27p-4, -0x1.ff0953ea68d73p-4, -0x1.f656f656384e1p-8, + 0x1.139f02b0a6960p-6, -0x1.fb5794c0fb6ddp-4, 0x1.f4e6013580413p-4, 0x1.a82a0cac59cc3p-6, + -0x1.1d3441a1cd60bp-5, 0x1.ebbd8986057abp-4, -0x1.dfeae7245934cp-4, -0x1.64c7e04584ad4p-5, + 0x1.aa6c839deceebp-5, -0x1.d17e78463356ap-4, 0x1.c08c4202e6b04p-4, 0x1.edc19abf90ceap-5, + -0x1.1734d3a40d580p-4, 0x1.ad2bcae3d355dp-4, -0x1.9777ef07937afp-4, -0x1.36058e8f0011dp-4, + 0x1.532827ee08e1cp-4, -0x1.7f8ecf78f2969p-4, 0x1.65918ec690ee0p-4, 0x1.6e7444e727184p-4, + -0x1.87c3fd9f5f3ebp-4, 0x1.49a447444a574p-4, -0x1.2bedb189b41cap-4, -0x1.9ef440bd220cap-4, + 0x1.b3e4d1d700650p-4, -0x1.0c970417cdedep-4, 0x1.d7976ee108abfp-5, 0x1.c678b407cfef4p-4, + -0x1.d69618e2f2b3fp-4, 0x1.9372a3fd35d0ap-5, -0x1.4d1e2420f5c3ep-5, -0x1.e426a5bf7e9c8p-4, + 0x1.ef17880cc29a3p-4, -0x1.04fb849b6ec94p-5, 0x1.76dd99dee7512p-6, 0x1.f7599d53b077ap-4, + -0x1.fce15f8c69fe2p-4, 0x1.c3784b66a4c9ep-7, -0x1.2d864b32357e3p-8, -0x1.ffa72f96e69c4p-4, + 0x1.ffa72f96e69c4p-4, 0x1.2d864b32357e3p-8, -0x1.c3784b66a4c9ep-7, 0x1.fce15f8c69fe2p-4, + -0x1.f7599d53b077ap-4, -0x1.76dd99dee7512p-6, 0x1.04fb849b6ec94p-5, -0x1.ef17880cc29a3p-4, + 0x1.e426a5bf7e9c8p-4, 0x1.4d1e2420f5c3ep-5, -0x1.9372a3fd35d0ap-5, 0x1.d69618e2f2b3fp-4, + -0x1.c678b407cfef4p-4, -0x1.d7976ee108abfp-5, 0x1.0c970417cdedep-4, -0x1.b3e4d1d700650p-4, + 0x1.9ef440bd220cap-4, 0x1.2bedb189b41cap-4, -0x1.49a447444a574p-4, 0x1.87c3fd9f5f3ebp-4, + -0x1.6e7444e727184p-4, -0x1.65918ec690ee0p-4, 0x1.7f8ecf78f2969p-4, -0x1.532827ee08e1cp-4, + 0x1.36058e8f0011dp-4, 0x1.9777ef07937afp-4, -0x1.ad2bcae3d355dp-4, 0x1.1734d3a40d580p-4, + -0x1.edc19abf90ceap-5, -0x1.c08c4202e6b04p-4, 0x1.d17e78463356ap-4, -0x1.aa6c839deceebp-5, + 0x1.64c7e04584ad4p-5, 0x1.dfeae7245934cp-4, -0x1.ebbd8986057abp-4, 0x1.1d3441a1cd60bp-5, + -0x1.a82a0cac59cc3p-6, -0x1.f4e6013580413p-4, 0x1.fb5794c0fb6ddp-4, -0x1.139f02b0a6960p-6, + 0x1.f656f656384e1p-8, 0x1.ff0953ea68d73p-4, -0x1.fff6218e00f27p-4, -0x1.921d163f3bbc9p-10, + 0x1.5f6cf50c44d57p-7, -0x1.fe1cb00a5688ap-4, 0x1.f97f94d2b7e80p-4, 0x1.4557752cc9bc5p-6, + -0x1.d934ff4027cabp-6, 0x1.f225301e9d4e3p-4, -0x1.e817bc0383e56p-4, -0x1.3541105b89a81p-5, + 0x1.7c3a913ec3199p-5, -0x1.db6527e217b71p-4, 0x1.cc1f0fd5e5d7ap-4, 0x1.c1249fce97e5ep-5, + -0x1.01cfc763fb280p-4, 0x1.ba5aa75b0887bp-4, -0x1.a63090d2a223dp-4, -0x1.21a79ce6042e5p-4, + 0x1.3fed939521d1fp-4, -0x1.8fbcc989c2d40p-4, 0x1.771e77669fec9p-4, 0x1.5c77beea0ec8fp-4, + 0x1.771e76c19b09bp-4, -0x1.5c77be68a3967p-4, -0x1.3fed936daf653p-4, -0x1.8fbcca75b1b87p-4, + -0x1.a6308f6dfe817p-4, 0x1.21a79cac720dfp-4, 0x1.01cfc7c9213f0p-4, 0x1.ba5aa76ed2a82p-4, + 0x1.cc1f0edf59fa9p-4, -0x1.c1249ff6d7330p-5, -0x1.7c3a9257b2981p-5, -0x1.db65292e11390p-4, + -0x1.e817bb689a4dcp-4, 0x1.354110807fac0p-5, 0x1.d934fe9f9045fp-6, 0x1.f225310f3c9e8p-4, + 0x1.f97f92b31a21cp-4, -0x1.4557759329affp-6, -0x1.5f6cf51f177bcp-7, -0x1.fe1cae9fcff5ap-4, + -0x1.fff6226dfcdb8p-4, 0x1.921d170c71197p-10, -0x1.f656f618813c3p-8, 0x1.ff095403b7593p-4, + 0x1.fb57937dec0ffp-4, 0x1.139f02d31ea9ap-6, 0x1.a82a0bf9a6f48p-6, -0x1.f4e6010165a27p-4, + -0x1.ebbd8ac151920p-4, -0x1.1d344123beb26p-5, -0x1.64c7e129c577dp-5, 0x1.dfeae56a19f8cp-4, + 0x1.d17e7735469f4p-4, 0x1.aa6c8334c18b9p-5, 0x1.edc19bbddb947p-5, -0x1.c08c42f2704fdp-4, + -0x1.ad2bc9935b89ep-4, -0x1.1734d41c5ac9dp-4, -0x1.36058ef01bec0p-4, 0x1.9777eff146dbap-4, + 0x1.7f8ed0c239b37p-4, 0x1.532827e91cae2p-4, 0x1.6e74449580a83p-4, -0x1.65918f8a4ae5ap-4, + -0x1.49a445debf708p-4, -0x1.87c3fee6a3568p-4, -0x1.9ef4413090f41p-4, 0x1.2bedb208ccbffp-4, + 0x1.0c97041ff3bb2p-4, 0x1.b3e4d267040fbp-4, 0x1.c678b3e35244dp-4, -0x1.d7976e8390968p-5, + -0x1.9372a4df076c5p-5, -0x1.d6961914d3106p-4, -0x1.e426a548aaddap-4, 0x1.4d1e22fbdc821p-5, + 0x1.04fb850f5d1f3p-5, 0x1.ef178931ef8e1p-4, 0x1.f7599c137dcafp-4, -0x1.76dd9b127637bp-6, + -0x1.c3784abc11bb3p-7, -0x1.fce160a75186bp-4, -0x1.ffa7310bb3dbdp-4, 0x1.2d864a2aa047bp-8, + -0x1.2d864a2aa047bp-8, 0x1.ffa7310bb3dbdp-4, 0x1.fce160a75186bp-4, 0x1.c3784abc11bb3p-7, + 0x1.76dd9b127637bp-6, -0x1.f7599c137dcafp-4, -0x1.ef178931ef8e1p-4, -0x1.04fb850f5d1f3p-5, + -0x1.4d1e22fbdc821p-5, 0x1.e426a548aaddap-4, 0x1.d6961914d3106p-4, 0x1.9372a4df076c5p-5, + 0x1.d7976e8390968p-5, -0x1.c678b3e35244dp-4, -0x1.b3e4d267040fbp-4, -0x1.0c97041ff3bb2p-4, + -0x1.2bedb208ccbffp-4, 0x1.9ef4413090f41p-4, 0x1.87c3fee6a3568p-4, 0x1.49a445debf708p-4, + 0x1.65918f8a4ae5ap-4, -0x1.6e74449580a83p-4, -0x1.532827e91cae2p-4, -0x1.7f8ed0c239b37p-4, + -0x1.9777eff146dbap-4, 0x1.36058ef01bec0p-4, 0x1.1734d41c5ac9dp-4, 0x1.ad2bc9935b89ep-4, + 0x1.c08c42f2704fdp-4, -0x1.edc19bbddb947p-5, -0x1.aa6c8334c18b9p-5, -0x1.d17e7735469f4p-4, + -0x1.dfeae56a19f8cp-4, 0x1.64c7e129c577dp-5, 0x1.1d344123beb26p-5, 0x1.ebbd8ac151920p-4, + 0x1.f4e6010165a27p-4, -0x1.a82a0bf9a6f48p-6, -0x1.139f02d31ea9ap-6, -0x1.fb57937dec0ffp-4, + -0x1.ff095403b7593p-4, 0x1.f656f618813c3p-8, -0x1.921d170c71197p-10, 0x1.fff6226dfcdb8p-4, + 0x1.fe1cae9fcff5ap-4, 0x1.5f6cf51f177bcp-7, 0x1.4557759329affp-6, -0x1.f97f92b31a21cp-4, + -0x1.f225310f3c9e8p-4, -0x1.d934fe9f9045fp-6, -0x1.354110807fac0p-5, 0x1.e817bb689a4dcp-4, + 0x1.db65292e11390p-4, 0x1.7c3a9257b2981p-5, 0x1.c1249ff6d7330p-5, -0x1.cc1f0edf59fa9p-4, + -0x1.ba5aa76ed2a82p-4, -0x1.01cfc7c9213f0p-4, -0x1.21a79cac720dfp-4, 0x1.a6308f6dfe817p-4, + 0x1.8fbcca75b1b87p-4, 0x1.3fed936daf653p-4, 0x1.5c77be68a3967p-4, -0x1.771e76c19b081p-4, + -0x1.1d109f1b9a82cp-3, 0x1.615ecb7cae504p-5, 0x1.4eb6b016a9163p-5, -0x1.720a8eb687cbap-7, + -0x1.46cc7f0e86ce8p-5, 0x1.05a8284a9aa95p-7, 0x1.aee48d97f984ep-6, -0x1.70fd78b9db8bap-4, + 0x1.c090b414b3a3dp-10, -0x1.c86ce9f5f678cp-6, 0x1.e3c370480229fp-7, 0x1.4989e9e08ed15p-5, + -0x1.d34527ecf193dp-3, -0x1.cbf5cb5b84880p-10, -0x1.bf87fb51afdd1p-7, -0x1.1f855c02d54b5p-4, + 0x1.f03b614dcaa2bp-4, 0x1.5149ad2873d78p-6, -0x1.f3146f0681809p-8, -0x1.362e8ffba8741p-2, + 0x1.5e657e848d74fp-3, -0x1.4f3935e6715d4p-8, -0x1.414c9d2a04194p-8, -0x1.779abb2d8a683p-6, + 0x1.944ee244b6af7p-6, -0x1.4aaa90c03085ap-7, 0x1.81765736898c3p-5, -0x1.63c508f8d9f24p-3, + 0x1.a2119541f564ap-4, -0x1.2f469032db965p-9, 0x1.024dc8e5d9f57p-8, 0x1.8b7da7577a267p-4, + 0x1.5f88b18bf90d5p-4, 0x1.7dbd7b5389aa2p-6, -0x1.4e34f480025a9p-4, 0x1.6223e2b78ff20p-3, + -0x1.d2b1a5118b49ep-4, -0x1.46d6f6bd70ae7p-5, 0x1.92ab82b166cd2p-4, 0x1.2b91cc22a5411p-4, + -0x1.d90da1a018358p-5, 0x1.871804fc35603p-6, 0x1.44f0b57e77abcp-5, 0x1.b1f57a3c09c71p-5, + -0x1.cae7ff5d5e6b6p-4, 0x1.445302e75cfe7p-3, 0x1.dec31f2d94888p-4, 0x1.da506f1941296p-5, + 0x1.472a976efe670p-8, -0x1.3b1913e239ecap-4, 0x1.2e0774fef6b93p-3, -0x1.f0dca0dce0363p-5, + -0x1.0451355ea09a7p-12, 0x1.85b186807699cp-4, 0x1.00912645dc4bep-7, 0x1.cc8aed2c46f99p-6, + -0x1.fa4fb4ef248dbp-6, -0x1.5ffc590480680p-3, 0x1.74a9e93e61368p-5, 0x1.fc4d31aa2a69bp-14, + 0x1.22ac7719399bbp-7, 0x1.0e488a8be0340p-4, 0x1.5b9b28b6a45e3p-5, 0x1.893ce4123f72ep-8, + -0x1.893ce4123f72ep-8, -0x1.5b9b28b6a45e3p-5, -0x1.0e488a8be0340p-4, -0x1.22ac7719399bbp-7, + -0x1.fc4d31aa2a69bp-14, -0x1.74a9e93e61368p-5, 0x1.5ffc590480680p-3, 0x1.fa4fb4ef248dbp-6, + -0x1.cc8aed2c46f99p-6, -0x1.00912645dc4bep-7, -0x1.85b186807699cp-4, 0x1.0451355ea09a7p-12, + 0x1.f0dca0dce0363p-5, -0x1.2e0774fef6b93p-3, 0x1.3b1913e239ecap-4, -0x1.472a976efe670p-8, + -0x1.da506f1941296p-5, -0x1.dec31f2d94888p-4, -0x1.445302e75cfe7p-3, 0x1.cae7ff5d5e6b6p-4, + -0x1.b1f57a3c09c71p-5, -0x1.44f0b57e77abcp-5, -0x1.871804fc35603p-6, 0x1.d90da1a018358p-5, + -0x1.2b91cc22a5411p-4, -0x1.92ab82b166cd2p-4, 0x1.46d6f6bd70ae7p-5, 0x1.d2b1a5118b49ep-4, + -0x1.6223e2b78ff20p-3, 0x1.4e34f480025a9p-4, -0x1.7dbd7b5389aa2p-6, -0x1.5f88b18bf90d5p-4, + -0x1.8b7da7577a267p-4, -0x1.024dc8e5d9f57p-8, 0x1.2f469032db965p-9, -0x1.a2119541f564ap-4, + 0x1.63c508f8d9f24p-3, -0x1.81765736898c3p-5, 0x1.4aaa90c03085ap-7, -0x1.944ee244b6af7p-6, + 0x1.779abb2d8a683p-6, 0x1.414c9d2a04194p-8, 0x1.4f3935e6715d4p-8, -0x1.5e657e848d74fp-3, + 0x1.362e8ffba8741p-2, 0x1.f3146f0681809p-8, -0x1.5149ad2873d78p-6, -0x1.f03b614dcaa2bp-4, + 0x1.1f855c02d54b5p-4, 0x1.bf87fb51afdd1p-7, 0x1.cbf5cb5b84880p-10, 0x1.d34527ecf193dp-3, + -0x1.4989e9e08ed15p-5, -0x1.e3c370480229fp-7, 0x1.c86ce9f5f678cp-6, -0x1.c090b414b3a3ep-10, + 0x1.70fd78b9db8bap-4, -0x1.aee48d97f983ep-6, -0x1.05a8284a9aa87p-7, 0x1.46cc7f0e86cd6p-5, + 0x1.720a8eb687cc4p-7, -0x1.4eb6b016a9163p-5, -0x1.615ecbd7339a9p-5, 0x1.1d109e9733ea7p-3, + -0x1.f91b95a3fc3a2p-5, -0x1.122100e6d7c77p-3, -0x1.b28a7175a3aaep-5, 0x1.aa28f559a4001p-4, + 0x1.8386afef2e10bp-4, 0x1.823a58b3cd707p-3, -0x1.b57a56fbe8027p-3, -0x1.64549bc85f7a8p-4, + 0x1.8228b189ea8c6p-4, -0x1.00617051b2acep-5, -0x1.24abd6275eb94p-7, 0x1.9ebd924a0bd3dp-5, + -0x1.e79ead761a3bcp-6, -0x1.8f6610ceb6477p-6, 0x1.2891e477ddb56p-5, -0x1.31864f505cd80p-6, + 0x1.146e9015855b1p-5, -0x1.977bc6381369fp-3, -0x1.021546a8e1c8cp-4, -0x1.1d4167aeee626p-5, + 0x1.a4457d74e52a0p-10, -0x1.0a77fafb05669p-6, 0x1.d1a7c639d2d3ep-5, -0x1.af1c9fd4c73c8p-7, + 0x1.4137dd6b78d81p-7, -0x1.e148f18cf9cebp-4, -0x1.e5f11eaf0e417p-3, -0x1.14e729e34d0a5p-5, + -0x1.3bea6dfee380cp-6, -0x1.7951915124f18p-4, -0x1.0213172442af1p-4, 0x1.28d89560fd05fp-6, + 0x1.39f9684aa6e90p-6, 0x1.05ac3cf8279adp-7, 0x1.142ef7beeb840p-5, -0x1.fd9d501a52a8dp-6, + 0x1.73f3d1b75b304p-4, 0x1.460514e221fd9p-5, 0x1.6cb5eb503b5f3p-4, 0x1.32b9720293e54p-5, + -0x1.6c9a4326c19b4p-6, 0x1.c4c3aa8ef48c4p-3, -0x1.df6c73bbc0920p-4, 0x1.158f1d1cd8e19p-5, + 0x1.00efa005baff7p-3, 0x1.b2a876d10dcc7p-4, 0x1.96ea53a5853d7p-6, -0x1.0ef572836cd1ep-5, + -0x1.1710afd97206fp-5, 0x1.e0b9c08478695p-4, -0x1.175de631c6276p-7, -0x1.e88621d66da4ep-6, + -0x1.267c16e82da07p-3, -0x1.80b207f92533dp-4, -0x1.1d3718181c322p-5, -0x1.5063dc00ffa04p-3, + -0x1.80fadc5483ecap-5, -0x1.7a1a20fc12b95p-6, -0x1.1c9e9bc5b2d30p-12, 0x1.1033b232552a6p-3, + -0x1.aa075127162a9p-6, -0x1.e869ec5f304f3p-7, -0x1.bea747556df89p-8, 0x1.65f705654de08p-4, + -0x1.65f705654de08p-4, 0x1.bea747556df89p-8, 0x1.e869ec5f304f3p-7, 0x1.aa075127162a9p-6, + -0x1.1033b232552a6p-3, 0x1.1c9e9bc5b2d30p-12, 0x1.7a1a20fc12b95p-6, 0x1.80fadc5483ecap-5, + 0x1.5063dc00ffa04p-3, 0x1.1d3718181c322p-5, 0x1.80b207f92533dp-4, 0x1.267c16e82da07p-3, + 0x1.e88621d66da4ep-6, 0x1.175de631c6276p-7, -0x1.e0b9c08478695p-4, 0x1.1710afd97206fp-5, + 0x1.0ef572836cd1ep-5, -0x1.96ea53a5853d7p-6, -0x1.b2a876d10dcc7p-4, -0x1.00efa005baff7p-3, + -0x1.158f1d1cd8e19p-5, 0x1.df6c73bbc0920p-4, -0x1.c4c3aa8ef48c4p-3, 0x1.6c9a4326c19b4p-6, + -0x1.32b9720293e54p-5, -0x1.6cb5eb503b5f3p-4, -0x1.460514e221fd9p-5, -0x1.73f3d1b75b304p-4, + 0x1.fd9d501a52a8dp-6, -0x1.142ef7beeb840p-5, -0x1.05ac3cf8279adp-7, -0x1.39f9684aa6e90p-6, + -0x1.28d89560fd05fp-6, 0x1.0213172442af1p-4, 0x1.7951915124f18p-4, 0x1.3bea6dfee380cp-6, + 0x1.14e729e34d0a5p-5, 0x1.e5f11eaf0e417p-3, 0x1.e148f18cf9cebp-4, -0x1.4137dd6b78d81p-7, + 0x1.af1c9fd4c73c8p-7, -0x1.d1a7c639d2d3ep-5, 0x1.0a77fafb05669p-6, -0x1.a4457d74e52a0p-10, + 0x1.1d4167aeee626p-5, 0x1.021546a8e1c8cp-4, 0x1.977bc6381369fp-3, -0x1.146e9015855b1p-5, + 0x1.31864f505cd80p-6, -0x1.2891e477ddb56p-5, 0x1.8f6610ceb6477p-6, 0x1.e79ead761a3bcp-6, + -0x1.9ebd924a0bd3dp-5, 0x1.24abd6275eb94p-7, 0x1.00617051b2acep-5, -0x1.8228b189ea8c6p-4, + 0x1.64549bc85f7a6p-4, 0x1.b57a56fbe8026p-3, -0x1.823a58b3cd707p-3, -0x1.8386afef2e10bp-4, + -0x1.aa28f559a4008p-4, 0x1.b28a7175a3ab7p-5, 0x1.122102312b822p-3, 0x1.f91b959508b62p-5, + -0x1.659197a6775e5p-4, -0x1.6e74430732228p-4, 0x1.771e75b69d090p-4, -0x1.5c77b9370af9ep-4, + 0x1.53282902f58a8p-4, 0x1.7f8eca4852e20p-4, -0x1.87c4027313976p-4, 0x1.49a44906ff66bp-4, + -0x1.3fed98dbad8edp-4, -0x1.8fbcc535c2350p-4, 0x1.9777f1f6e8f88p-4, -0x1.36058a5649746p-4, + 0x1.2bedb75cd1c65p-4, 0x1.9ef43f0b70abbp-4, -0x1.a63095d3aeacdp-4, 0x1.21a7966f08b10p-4, + -0x1.1734dbb993a8cp-4, -0x1.ad2bc744105adp-4, 0x1.b3e4d78615dfcp-4, -0x1.0c97026902aa1p-4, + 0x1.01cfcc3d5f321p-4, 0x1.ba5aa708a3af5p-4, -0x1.c08c4103e0de0p-4, 0x1.edc18e7156a44p-5, + -0x1.d7977cb7cc753p-5, -0x1.c678b15d6c499p-4, 0x1.cc1f0d3eb4631p-4, -0x1.c12491757b262p-5, + 0x1.aa6c8b8540045p-5, 0x1.d17e75b7a24ccp-4, -0x1.d69617be2e2a7p-4, 0x1.93729d45cebabp-5, + -0x1.7c3a9aa2d8729p-5, -0x1.db6526bb8ff3dp-4, 0x1.dfeaea51c8f0dp-4, -0x1.64c7d66ad1c26p-5, + 0x1.4d1e2a0813210p-5, 0x1.e426a2af6aeecp-4, -0x1.e817c01a4b104p-4, 0x1.3541060760100p-5, + -0x1.1d344d5a384aep-5, -0x1.ebbd89ea14f54p-4, 0x1.ef178b0529726p-4, -0x1.04fb7aca5f21cp-5, + 0x1.d935091e05c10p-6, 0x1.f2252e07e6f36p-4, -0x1.f4e604baade61p-4, 0x1.a829e80e0b9e2p-6, + -0x1.76ddad54af77fp-6, -0x1.f759976af98c4p-4, 0x1.f97f8fb35c0f7p-4, -0x1.4557580ec698ap-6, + 0x1.139f1c5b67f00p-6, 0x1.fb5796586cc2ep-4, -0x1.fce16161563a1p-4, 0x1.c37836b8d7b7bp-7, + -0x1.5f6d18834cc6bp-7, -0x1.fe1caef301807p-4, 0x1.ff095540cf63dp-4, -0x1.f656ae17f0083p-8, + 0x1.2d86b1b23cc00p-8, 0x1.ffa730102b74dp-4, -0x1.fff6221b53e9cp-4, 0x1.921bf857e5b5bp-10, + 0x1.921bf857e5b5bp-10, -0x1.fff6221b53e9cp-4, 0x1.ffa730102b74dp-4, 0x1.2d86b1b23cc00p-8, + -0x1.f656ae17f0083p-8, 0x1.ff095540cf63dp-4, -0x1.fe1caef301807p-4, -0x1.5f6d18834cc6bp-7, + 0x1.c37836b8d7b7bp-7, -0x1.fce16161563a1p-4, 0x1.fb5796586cc2ep-4, 0x1.139f1c5b67f00p-6, + -0x1.4557580ec698ap-6, 0x1.f97f8fb35c0f7p-4, -0x1.f759976af98c4p-4, -0x1.76ddad54af77fp-6, + 0x1.a829e80e0b9e2p-6, -0x1.f4e604baade61p-4, 0x1.f2252e07e6f36p-4, 0x1.d935091e05c10p-6, + -0x1.04fb7aca5f21cp-5, 0x1.ef178b0529726p-4, -0x1.ebbd89ea14f54p-4, -0x1.1d344d5a384aep-5, + 0x1.3541060760100p-5, -0x1.e817c01a4b104p-4, 0x1.e426a2af6aeecp-4, 0x1.4d1e2a0813210p-5, + -0x1.64c7d66ad1c26p-5, 0x1.dfeaea51c8f0dp-4, -0x1.db6526bb8ff3dp-4, -0x1.7c3a9aa2d8729p-5, + 0x1.93729d45cebabp-5, -0x1.d69617be2e2a7p-4, 0x1.d17e75b7a24ccp-4, 0x1.aa6c8b8540045p-5, + -0x1.c12491757b262p-5, 0x1.cc1f0d3eb4631p-4, -0x1.c678b15d6c499p-4, -0x1.d7977cb7cc753p-5, + 0x1.edc18e7156a44p-5, -0x1.c08c4103e0de0p-4, 0x1.ba5aa708a3af5p-4, 0x1.01cfcc3d5f321p-4, + -0x1.0c97026902aa1p-4, 0x1.b3e4d78615dfcp-4, -0x1.ad2bc744105adp-4, -0x1.1734dbb993a8cp-4, + 0x1.21a7966f08b10p-4, -0x1.a63095d3aeacdp-4, 0x1.9ef43f0b70abbp-4, 0x1.2bedb75cd1c65p-4, + -0x1.36058a5649746p-4, 0x1.9777f1f6e8f88p-4, -0x1.8fbcc535c2350p-4, -0x1.3fed98dbad8edp-4, + 0x1.49a44906ff66bp-4, -0x1.87c4027313976p-4, 0x1.7f8eca4852e20p-4, 0x1.53282902f58a8p-4, + -0x1.5c77b9370af9ep-4, 0x1.771e75b69d090p-4, -0x1.6e7443073221cp-4, -0x1.659197a6775e4p-4, + 0x1.6e74427d0036cp-4, -0x1.659196ffc0cf1p-4, -0x1.5c77b85925b9ap-4, -0x1.771e76198d92bp-4, + -0x1.7f8ec8960f04bp-4, 0x1.532829774a027p-4, 0x1.49a4494f66ae0p-4, 0x1.87c403e15bfdep-4, + 0x1.8fbcc5d651520p-4, -0x1.3fed9916e9eeep-4, -0x1.36058ac9eefd1p-4, -0x1.9777f27889169p-4, + -0x1.9ef43fe6af9d7p-4, 0x1.2bedb7ce1b220p-4, 0x1.21a796e38d542p-4, 0x1.a63096b8fe93dp-4, + 0x1.ad2bc859fe4cbp-4, -0x1.1734daea37e09p-4, -0x1.0c97024edf141p-4, -0x1.b3e4d5ed54e0dp-4, + -0x1.ba5aa67796242p-4, 0x1.01cfcafc979e5p-4, 0x1.edc18d5984f27p-5, 0x1.c08c4256a4adbp-4, + 0x1.c678b1c9af979p-4, -0x1.d7977c804bf63p-5, -0x1.c12490cd6f0f3p-5, -0x1.cc1f0cf185948p-4, + -0x1.d17e777e75146p-4, 0x1.aa6c8bb6086b8p-5, 0x1.93729ece3c7e3p-5, 0x1.d696169bc1d4cp-4, + 0x1.db65267d2a7dbp-4, -0x1.7c3a989df79e5p-5, -0x1.64c7d5f5d4d53p-5, -0x1.dfeaea6c8faadp-4, + -0x1.e426a339bcdbcp-4, 0x1.4d1e299b5e420p-5, 0x1.35410645e93e5p-5, 0x1.e817bdcdae3e5p-4, + 0x1.ebbd8ae2eb83fp-4, -0x1.1d344e3dabb41p-5, -0x1.04fb78f4854adp-5, -0x1.ef178a1174064p-4, + -0x1.f225304cf0e8fp-4, 0x1.d9350a00b1e9fp-6, 0x1.a829e64a8d1c0p-6, 0x1.f4e60434c87e7p-4, + 0x1.f759965cae5aap-4, -0x1.76ddade2b786ap-6, -0x1.455756a0ef092p-6, -0x1.f97f912376a50p-4, + -0x1.fb579833c15dfp-4, 0x1.139f1d4754ecfp-6, 0x1.c378350ea46b1p-7, 0x1.fce15fc6fdf00p-4, + 0x1.fe1cacd579c99p-4, -0x1.5f6d19b8794d1p-7, -0x1.f656ac68f0b73p-8, -0x1.ff0957789276cp-4, + -0x1.ffa72f1175ee7p-4, 0x1.2d86b509807e8p-8, 0x1.921becfd08dacp-10, 0x1.fff6210a21471p-4, + 0x1.fff6210a21471p-4, 0x1.921becfd08dacp-10, 0x1.2d86b509807e8p-8, -0x1.ffa72f1175ee7p-4, + -0x1.ff0957789276cp-4, -0x1.f656ac68f0b73p-8, -0x1.5f6d19b8794d1p-7, 0x1.fe1cacd579c99p-4, + 0x1.fce15fc6fdf00p-4, 0x1.c378350ea46b1p-7, 0x1.139f1d4754ecfp-6, -0x1.fb579833c15dfp-4, + -0x1.f97f912376a50p-4, -0x1.455756a0ef092p-6, -0x1.76ddade2b786ap-6, 0x1.f759965cae5aap-4, + 0x1.f4e60434c87e7p-4, 0x1.a829e64a8d1c0p-6, 0x1.d9350a00b1e9fp-6, -0x1.f225304cf0e8fp-4, + -0x1.ef178a1174064p-4, -0x1.04fb78f4854adp-5, -0x1.1d344e3dabb41p-5, 0x1.ebbd8ae2eb83fp-4, + 0x1.e817bdcdae3e5p-4, 0x1.35410645e93e5p-5, 0x1.4d1e299b5e420p-5, -0x1.e426a339bcdbcp-4, + -0x1.dfeaea6c8faadp-4, -0x1.64c7d5f5d4d53p-5, -0x1.7c3a989df79e5p-5, 0x1.db65267d2a7dbp-4, + 0x1.d696169bc1d4cp-4, 0x1.93729ece3c7e3p-5, 0x1.aa6c8bb6086b8p-5, -0x1.d17e777e75146p-4, + -0x1.cc1f0cf185948p-4, -0x1.c12490cd6f0f3p-5, -0x1.d7977c804bf63p-5, 0x1.c678b1c9af979p-4, + 0x1.c08c4256a4adbp-4, 0x1.edc18d5984f27p-5, 0x1.01cfcafc979e5p-4, -0x1.ba5aa67796242p-4, + -0x1.b3e4d5ed54e0dp-4, -0x1.0c97024edf141p-4, -0x1.1734daea37e09p-4, 0x1.ad2bc859fe4cbp-4, + 0x1.a63096b8fe93dp-4, 0x1.21a796e38d542p-4, 0x1.2bedb7ce1b220p-4, -0x1.9ef43fe6af9d7p-4, + -0x1.9777f27889169p-4, -0x1.36058ac9eefd1p-4, -0x1.3fed9916e9eeep-4, 0x1.8fbcc5d651520p-4, + 0x1.87c403e15bfdep-4, 0x1.49a4494f66ae0p-4, 0x1.532829774a027p-4, -0x1.7f8ec8960f04bp-4, + -0x1.771e76198d92bp-4, -0x1.5c77b85925b9ap-4, -0x1.659196ffc0cf2p-4, 0x1.6e74427d00357p-4, + 0x1.9593417011ba4p-4, -0x1.82e7c6658f729p-7, -0x1.f0e8314f1caf3p-5, -0x1.0aaa169edf5a7p-3, + -0x1.4997dd9d23566p-4, -0x1.34f308482692cp-5, -0x1.32405d269b9c7p-5, -0x1.526f9a85d0297p-3, + -0x1.01bc6fcb12012p-7, -0x1.4217dd0e2347ap-5, 0x1.5b76b44665f9fp-4, -0x1.c7c8f1fbaa71fp-4, + 0x1.955b3729e2181p-4, -0x1.14a709c1649ddp-3, -0x1.d70934d1c9e0ap-5, -0x1.1f09aea210e3fp-7, + -0x1.79dc466c37de5p-4, -0x1.1a7ec25afdc3dp-7, -0x1.27ac71a3ac374p-5, -0x1.466b5c8c5ae88p-5, + 0x1.0c0151d6cc5eap-4, 0x1.eb3a8aae90d4ep-6, 0x1.499fcf3350bcdp-6, -0x1.a8720c09c8c96p-7, + 0x1.6483dcb07f187p-4, 0x1.f292099787ca0p-4, 0x1.ac6d2b4ed0bd6p-5, -0x1.80e8368e967cbp-4, + 0x1.97b233c714ac7p-3, -0x1.017354c7f2a12p-4, -0x1.0b541ae708662p-5, 0x1.e9d42b940f9c0p-5, + -0x1.b384fdad74f5fp-5, -0x1.1a6911bf9718cp-4, 0x1.5f1dd5066e940p-5, 0x1.e54c19dfee8f5p-3, + 0x1.2da5b8e080771p-4, -0x1.81638c22ab735p-6, -0x1.db71dd7727dcep-5, 0x1.16221b2438d69p-3, + 0x1.b17d04662f12bp-5, -0x1.b4328eb573fccp-7, -0x1.4c92fd7448c05p-4, -0x1.e057678115ef3p-4, + 0x1.e3d76387e75c3p-5, -0x1.2373fc14ae68cp-4, 0x1.baaba189bf7d3p-5, -0x1.30e62ae2688fep-7, + 0x1.3a633940382a0p-5, -0x1.927eebc42eb15p-7, -0x1.c4bb6ec2b0132p-7, 0x1.bad9c5897b0c9p-3, + 0x1.f208bfc7b93bdp-5, -0x1.17491662aaa8bp-5, 0x1.cc6c299bcaf57p-7, 0x1.2c6e358ce5ba0p-4, + 0x1.68d4f892cdc49p-4, -0x1.0da6d61bb1449p-6, 0x1.5240ed69ddbcfp-7, 0x1.33d425b0fc6e9p-5, + -0x1.c3ac12a5e52b7p-3, -0x1.6e20666fcdabcp-8, -0x1.73e2fb6c8e857p-9, 0x1.80f2c2f7e85c6p-3, + 0x1.80f2c2f7e85c6p-3, -0x1.73e2fb6c8e857p-9, -0x1.6e20666fcdabcp-8, -0x1.c3ac12a5e52b7p-3, + 0x1.33d425b0fc6e9p-5, 0x1.5240ed69ddbcfp-7, -0x1.0da6d61bb1449p-6, 0x1.68d4f892cdc49p-4, + 0x1.2c6e358ce5ba0p-4, 0x1.cc6c299bcaf57p-7, -0x1.17491662aaa8bp-5, 0x1.f208bfc7b93bdp-5, + 0x1.bad9c5897b0c9p-3, -0x1.c4bb6ec2b0132p-7, -0x1.927eebc42eb15p-7, 0x1.3a633940382a0p-5, + -0x1.30e62ae2688fep-7, 0x1.baaba189bf7d3p-5, -0x1.2373fc14ae68cp-4, 0x1.e3d76387e75c3p-5, + -0x1.e057678115ef3p-4, -0x1.4c92fd7448c05p-4, -0x1.b4328eb573fccp-7, 0x1.b17d04662f12bp-5, + 0x1.16221b2438d69p-3, -0x1.db71dd7727dcep-5, -0x1.81638c22ab735p-6, 0x1.2da5b8e080771p-4, + 0x1.e54c19dfee8f5p-3, 0x1.5f1dd5066e940p-5, -0x1.1a6911bf9718cp-4, -0x1.b384fdad74f5fp-5, + 0x1.e9d42b940f9c0p-5, -0x1.0b541ae708662p-5, -0x1.017354c7f2a12p-4, 0x1.97b233c714ac7p-3, + -0x1.80e8368e967cbp-4, 0x1.ac6d2b4ed0bd6p-5, 0x1.f292099787ca0p-4, 0x1.6483dcb07f187p-4, + -0x1.a8720c09c8c96p-7, 0x1.499fcf3350bcdp-6, 0x1.eb3a8aae90d4ep-6, 0x1.0c0151d6cc5eap-4, + -0x1.466b5c8c5ae88p-5, -0x1.27ac71a3ac374p-5, -0x1.1a7ec25afdc3dp-7, -0x1.79dc466c37de5p-4, + -0x1.1f09aea210e3fp-7, -0x1.d70934d1c9e0ap-5, -0x1.14a709c1649ddp-3, 0x1.955b3729e2181p-4, + -0x1.c7c8f1fbaa71fp-4, 0x1.5b76b44665f9fp-4, -0x1.4217dd0e2347ap-5, -0x1.01bc6fcb12012p-7, + -0x1.526f9a85d0297p-3, -0x1.32405d269b9c8p-5, -0x1.34f3084826929p-5, -0x1.4997dd9d2355bp-4, + -0x1.0aaa169edf5a9p-3, -0x1.f0e8314f1caf1p-5, -0x1.82e7c67e8cd12p-7, 0x1.9593420523890p-4, + -0x1.c9be4b6501243p-4, 0x1.0aed83f7c759dp-4, -0x1.b1766298be688p-4, -0x1.30e6682fbbb7bp-3, + -0x1.221227c9da2cdp-4, 0x1.428c685dab529p-3, 0x1.5d05a3e414b3cp-8, 0x1.506f523e6ca27p-4, + 0x1.92d742e55b613p-5, -0x1.09d85a187a88dp-5, -0x1.cb98bcc95af53p-5, 0x1.890f32529e38ep-5, + 0x1.1e15c3f47ddaap-5, -0x1.cca6b99a957ecp-5, 0x1.77397cbcf9bd3p-6, -0x1.2e22fa6f159d5p-5, + 0x1.4fbfb246e62c3p-4, -0x1.bc224f2db9286p-7, 0x1.0ebbf3ac46787p-2, -0x1.7dc53695fc970p-4, + 0x1.8b624b84e8037p-4, 0x1.e051250e61d58p-5, 0x1.c625e88e9170dp-3, 0x1.679705918cd40p-4, + -0x1.0b1e59a853d39p-3, 0x1.1e8098e5ec9c1p-4, 0x1.627e335976f21p-10, -0x1.5db3d7bec9e01p-11, + 0x1.9fa9805f187a5p-9, -0x1.e6ab2d19c8f83p-4, 0x1.a190fb4593843p-5, -0x1.afaf209f6a341p-6, + -0x1.05c9ec234e728p-6, 0x1.3b1271cb59a6cp-6, 0x1.86868cbbdcda8p-3, -0x1.bbb84188df240p-7, + -0x1.01b7792198705p-5, -0x1.66525633f34f3p-5, -0x1.61e342aec8db8p-3, -0x1.71d3c8ff08ab9p-4, + -0x1.2f87fbde8c389p-6, 0x1.42668964d17a6p-5, -0x1.a250078f2376ap-7, -0x1.0c9cc2184433bp-4, + 0x1.232d3c65a3141p-4, -0x1.7c7474d95e866p-3, 0x1.37cf8c74e6338p-4, 0x1.3458783716d2dp-6, + -0x1.229a7a706c653p-6, -0x1.da0f305868764p-4, -0x1.58fb600d81493p-5, -0x1.730055c053563p-4, + -0x1.a3762f1ff1191p-6, -0x1.0a543ac140070p-3, -0x1.488c11fb525eap-4, -0x1.26fb5958d7a34p-6, + -0x1.5cd3bd4f05543p-9, -0x1.445ad22ed3e3ap-4, -0x1.f9670b25925abp-4, -0x1.782f885060c87p-8, + 0x1.5410fe66de640p-5, 0x1.4d5fac2f163d3p-9, 0x1.6b3c83ded20a8p-5, -0x1.0c78e61a6fcd1p-6, + -0x1.0c78e61a6fcd1p-6, 0x1.6b3c83ded20a8p-5, 0x1.4d5fac2f163d3p-9, 0x1.5410fe66de640p-5, + -0x1.782f885060c87p-8, -0x1.f9670b25925abp-4, -0x1.445ad22ed3e3ap-4, -0x1.5cd3bd4f05543p-9, + -0x1.26fb5958d7a34p-6, -0x1.488c11fb525eap-4, -0x1.0a543ac140070p-3, -0x1.a3762f1ff1191p-6, + -0x1.730055c053563p-4, -0x1.58fb600d81493p-5, -0x1.da0f305868764p-4, -0x1.229a7a706c653p-6, + 0x1.3458783716d2dp-6, 0x1.37cf8c74e6338p-4, -0x1.7c7474d95e866p-3, 0x1.232d3c65a3141p-4, + -0x1.0c9cc2184433bp-4, -0x1.a250078f2376ap-7, 0x1.42668964d17a6p-5, -0x1.2f87fbde8c389p-6, + -0x1.71d3c8ff08ab9p-4, -0x1.61e342aec8db8p-3, -0x1.66525633f34f3p-5, -0x1.01b7792198705p-5, + -0x1.bbb84188df240p-7, 0x1.86868cbbdcda8p-3, 0x1.3b1271cb59a6cp-6, -0x1.05c9ec234e728p-6, + -0x1.afaf209f6a341p-6, 0x1.a190fb4593843p-5, -0x1.e6ab2d19c8f83p-4, 0x1.9fa9805f187a5p-9, + -0x1.5db3d7bec9e01p-11, 0x1.627e335976f21p-10, 0x1.1e8098e5ec9c1p-4, -0x1.0b1e59a853d39p-3, + 0x1.679705918cd40p-4, 0x1.c625e88e9170dp-3, 0x1.e051250e61d58p-5, 0x1.8b624b84e8037p-4, + -0x1.7dc53695fc970p-4, 0x1.0ebbf3ac46787p-2, -0x1.bc224f2db9286p-7, 0x1.4fbfb246e62c3p-4, + -0x1.2e22fa6f159d5p-5, 0x1.77397cbcf9bd3p-6, -0x1.cca6b99a957ecp-5, 0x1.1e15c3f47ddaap-5, + 0x1.890f32529e38ep-5, -0x1.cb98bcc95af53p-5, -0x1.09d85a187a88dp-5, 0x1.92d742e55b613p-5, + 0x1.506f523e6ca26p-4, 0x1.5d05a3e414b5dp-8, 0x1.428c685dab52ap-3, -0x1.221227c9da2d2p-4, + -0x1.30e6682fbbb7ap-3, -0x1.b1766298be68cp-4, 0x1.0aed843cd75f1p-4, -0x1.c9be4b4705ebcp-4, + 0x1.6e7446c44f19ep-4, 0x1.6591922b22a1ap-4, -0x1.5c77ba951d129p-4, 0x1.771e760fceadfp-4, + -0x1.7f8ece4f9dde5p-4, -0x1.532829fd9c4cfp-4, 0x1.49a449cb12d80p-4, -0x1.87c402848c3b6p-4, + 0x1.8fbccaee3f400p-4, 0x1.3fed9679d5275p-4, -0x1.36058c06085d2p-4, 0x1.9777f15951ce9p-4, + -0x1.9ef43f1f3aecdp-4, -0x1.2bedb2419d110p-4, 0x1.21a79a825dfb1p-4, -0x1.a63091fa556dap-4, + 0x1.ad2bca03beabap-4, 0x1.1734d69ea1aafp-4, -0x1.0c9704b154bd4p-4, 0x1.b3e4d336208f3p-4, + -0x1.ba5aa4797e084p-4, -0x1.01cfc7b14e0cdp-4, 0x1.edc195014c9d2p-5, -0x1.c08c436310b8cp-4, + 0x1.c678b24bb1372p-4, 0x1.d797742cf93cap-5, -0x1.c1249c43e3c1ap-5, 0x1.cc1f0d88b4a8bp-4, + -0x1.d17e7994e6d8ap-4, -0x1.aa6c83a57c2a4p-5, 0x1.9372a528780dcp-5, -0x1.d69615b686ee2p-4, + 0x1.db6525b77d5c6p-4, 0x1.7c3a93a0ed1ebp-5, -0x1.64c7ddcb89ee5p-5, 0x1.dfeae534bc427p-4, + -0x1.e426a39288e18p-4, -0x1.4d1e262af8265p-5, 0x1.35410c933ba93p-5, -0x1.e817bba26bc76p-4, + 0x1.ebbd8b108c076p-4, 0x1.1d3441cd9d3e4p-5, -0x1.04fb80a9ba909p-5, 0x1.ef17891b5e4a8p-4, + -0x1.f2252ff6e77bfp-4, -0x1.d935050feb228p-6, 0x1.a82a047e1aba0p-6, -0x1.f4e60528c9e47p-4, + 0x1.f7599992b40a0p-4, 0x1.76dd9d01320edp-6, -0x1.45576c28b2cd4p-6, 0x1.f97f8f508667ap-4, + -0x1.fb57995af0f58p-4, -0x1.139f10c663287p-6, 0x1.c3785f15359c7p-7, -0x1.fce15f8d79dbcp-4, + 0x1.fe1cae83248e3p-4, 0x1.5f6cf0adc005bp-7, -0x1.f656df0f55f4cp-8, 0x1.ff0955e26f947p-4, + -0x1.ffa730a119739p-4, -0x1.2d865054b4d12p-8, 0x1.921d7e6fa2c57p-10, -0x1.fff62247308b0p-4, + 0x1.fff62247308b0p-4, -0x1.921d7e6fa2c57p-10, 0x1.2d865054b4d12p-8, 0x1.ffa730a119739p-4, + -0x1.ff0955e26f947p-4, 0x1.f656df0f55f4cp-8, -0x1.5f6cf0adc005bp-7, -0x1.fe1cae83248e3p-4, + 0x1.fce15f8d79dbcp-4, -0x1.c3785f15359c7p-7, 0x1.139f10c663287p-6, 0x1.fb57995af0f58p-4, + -0x1.f97f8f508667ap-4, 0x1.45576c28b2cd4p-6, -0x1.76dd9d01320edp-6, -0x1.f7599992b40a0p-4, + 0x1.f4e60528c9e47p-4, -0x1.a82a047e1aba0p-6, 0x1.d935050feb228p-6, 0x1.f2252ff6e77bfp-4, + -0x1.ef17891b5e4a8p-4, 0x1.04fb80a9ba909p-5, -0x1.1d3441cd9d3e4p-5, -0x1.ebbd8b108c076p-4, + 0x1.e817bba26bc76p-4, -0x1.35410c933ba93p-5, 0x1.4d1e262af8265p-5, 0x1.e426a39288e18p-4, + -0x1.dfeae534bc427p-4, 0x1.64c7ddcb89ee5p-5, -0x1.7c3a93a0ed1ebp-5, -0x1.db6525b77d5c6p-4, + 0x1.d69615b686ee2p-4, -0x1.9372a528780dcp-5, 0x1.aa6c83a57c2a4p-5, 0x1.d17e7994e6d8ap-4, + -0x1.cc1f0d88b4a8bp-4, 0x1.c1249c43e3c1ap-5, -0x1.d797742cf93cap-5, -0x1.c678b24bb1372p-4, + 0x1.c08c436310b8cp-4, -0x1.edc195014c9d2p-5, 0x1.01cfc7b14e0cdp-4, 0x1.ba5aa4797e084p-4, + -0x1.b3e4d336208f3p-4, 0x1.0c9704b154bd4p-4, -0x1.1734d69ea1aafp-4, -0x1.ad2bca03beabap-4, + 0x1.a63091fa556dap-4, -0x1.21a79a825dfb1p-4, 0x1.2bedb2419d110p-4, 0x1.9ef43f1f3aecdp-4, + -0x1.9777f15951ce9p-4, 0x1.36058c06085d2p-4, -0x1.3fed9679d5275p-4, -0x1.8fbccaee3f400p-4, + 0x1.87c402848c3b6p-4, -0x1.49a449cb12d80p-4, 0x1.532829fd9c4cfp-4, 0x1.7f8ece4f9dde5p-4, + -0x1.771e760fceadfp-4, 0x1.5c77ba951d129p-4, -0x1.6591922b22a3cp-4, -0x1.6e7446c44f1a4p-4, + -0x1.6591922b22a33p-4, 0x1.6e7446c44f1a3p-4, 0x1.771e760fceae2p-4, 0x1.5c77ba951d129p-4, + 0x1.532829fd9c4c9p-4, -0x1.7f8ece4f9dde9p-4, -0x1.87c402848c3b8p-4, -0x1.49a449cb12d82p-4, + -0x1.3fed9679d5273p-4, 0x1.8fbccaee3f402p-4, 0x1.9777f15951ceap-4, 0x1.36058c06085d5p-4, + 0x1.2bedb2419d10ep-4, -0x1.9ef43f1f3aeccp-4, -0x1.a63091fa556d9p-4, -0x1.21a79a825dfaep-4, + -0x1.1734d69ea1ab5p-4, 0x1.ad2bca03beabep-4, 0x1.b3e4d336208f3p-4, 0x1.0c9704b154bcfp-4, + 0x1.01cfc7b14e0cdp-4, -0x1.ba5aa4797e084p-4, -0x1.c08c436310b8ep-4, -0x1.edc195014c9ddp-5, + -0x1.d797742cf93d1p-5, 0x1.c678b24bb1376p-4, 0x1.cc1f0d88b4a8dp-4, 0x1.c1249c43e3c22p-5, + 0x1.aa6c83a57c2a8p-5, -0x1.d17e7994e6d8bp-4, -0x1.d69615b686ee1p-4, -0x1.9372a528780dfp-5, + -0x1.7c3a93a0ed1edp-5, 0x1.db6525b77d5c8p-4, 0x1.dfeae534bc428p-4, 0x1.64c7ddcb89eedp-5, + 0x1.4d1e262af8267p-5, -0x1.e426a39288e19p-4, -0x1.e817bba26bc74p-4, -0x1.35410c933ba9bp-5, + -0x1.1d3441cd9d3e7p-5, 0x1.ebbd8b108c076p-4, 0x1.ef17891b5e4a9p-4, 0x1.04fb80a9ba905p-5, + 0x1.d935050feb225p-6, -0x1.f2252ff6e77bep-4, -0x1.f4e60528c9e4ap-4, -0x1.a82a047e1abacp-6, + -0x1.76dd9d01320ecp-6, 0x1.f7599992b40a3p-4, 0x1.f97f8f508667bp-4, 0x1.45576c28b2ccfp-6, + 0x1.139f10c66327fp-6, -0x1.fb57995af0f59p-4, -0x1.fce15f8d79dbdp-4, -0x1.c3785f15359e1p-7, + -0x1.5f6cf0adc005ap-7, 0x1.fe1cae83248e3p-4, 0x1.ff0955e26f948p-4, 0x1.f656df0f55f14p-8, + 0x1.2d865054b4cd8p-8, -0x1.ffa730a11973ap-4, -0x1.fff62247308b0p-4, -0x1.921d7e6fa2c51p-10, + 0x1.921d7e6fa2c51p-10, 0x1.fff62247308b0p-4, 0x1.ffa730a11973ap-4, -0x1.2d865054b4cd8p-8, + -0x1.f656df0f55f14p-8, -0x1.ff0955e26f948p-4, -0x1.fe1cae83248e3p-4, 0x1.5f6cf0adc005ap-7, + 0x1.c3785f15359e1p-7, 0x1.fce15f8d79dbdp-4, 0x1.fb57995af0f59p-4, -0x1.139f10c66327fp-6, + -0x1.45576c28b2ccfp-6, -0x1.f97f8f508667bp-4, -0x1.f7599992b40a3p-4, 0x1.76dd9d01320ecp-6, + 0x1.a82a047e1abacp-6, 0x1.f4e60528c9e4ap-4, 0x1.f2252ff6e77bep-4, -0x1.d935050feb225p-6, + -0x1.04fb80a9ba905p-5, -0x1.ef17891b5e4a9p-4, -0x1.ebbd8b108c076p-4, 0x1.1d3441cd9d3e7p-5, + 0x1.35410c933ba9bp-5, 0x1.e817bba26bc74p-4, 0x1.e426a39288e19p-4, -0x1.4d1e262af8267p-5, + -0x1.64c7ddcb89eedp-5, -0x1.dfeae534bc428p-4, -0x1.db6525b77d5c8p-4, 0x1.7c3a93a0ed1edp-5, + 0x1.9372a528780dfp-5, 0x1.d69615b686ee1p-4, 0x1.d17e7994e6d8bp-4, -0x1.aa6c83a57c2a8p-5, + -0x1.c1249c43e3c22p-5, -0x1.cc1f0d88b4a8dp-4, -0x1.c678b24bb1376p-4, 0x1.d797742cf93d1p-5, + 0x1.edc195014c9ddp-5, 0x1.c08c436310b8ep-4, 0x1.ba5aa4797e084p-4, -0x1.01cfc7b14e0cdp-4, + -0x1.0c9704b154bcfp-4, -0x1.b3e4d336208f3p-4, -0x1.ad2bca03beabep-4, 0x1.1734d69ea1ab5p-4, + 0x1.21a79a825dfaep-4, 0x1.a63091fa556d9p-4, 0x1.9ef43f1f3aeccp-4, -0x1.2bedb2419d10ep-4, + -0x1.36058c06085d5p-4, -0x1.9777f15951ceap-4, -0x1.8fbccaee3f402p-4, 0x1.3fed9679d5273p-4, + 0x1.49a449cb12d82p-4, 0x1.87c402848c3b8p-4, 0x1.7f8ece4f9dde9p-4, -0x1.532829fd9c4c9p-4, + -0x1.5c77ba951d129p-4, -0x1.771e760fceae2p-4, -0x1.6e7446c44f1a4p-4, 0x1.6591922b22a3cp-4, + -0x1.5caecaacc501dp-4, 0x1.7616c5393cae3p-4, 0x1.2c28cc898b2dbp-5, 0x1.d6fd4d0b8dfd0p-4, + -0x1.0f4a4f5db900bp-4, 0x1.f98667758f05cp-5, 0x1.080bff5122ed8p-4, 0x1.a2c7d852638b9p-7, + -0x1.b2cdf48b504ecp-4, 0x1.3d0e6f70d8491p-5, 0x1.c4e91d8b055ecp-4, -0x1.65e8a225015f1p-4, + 0x1.c35f72b24df05p-5, -0x1.350df775c83aap-3, 0x1.1a7094450a92ep-5, -0x1.c811ea0c60925p-12, + -0x1.25d0e25f48990p-6, 0x1.d996d0f14d4e4p-6, -0x1.2ba91c4f656b6p-4, 0x1.083e6de776ac8p-4, + -0x1.5a8e2dbb0ef03p-9, -0x1.a4ab4396960edp-7, -0x1.4c4cc2fbb3fd9p-5, -0x1.3710471edf08cp-4, + 0x1.06a06a09775d7p-6, 0x1.33fb26c6726f5p-6, -0x1.1d53fcd59819cp-3, 0x1.df6ebe0881af3p-6, + 0x1.9b3a46fa5f24cp-4, -0x1.800ff3d55c1a0p-3, 0x1.2453c8ecc5d60p-3, -0x1.cdbc99d6714bdp-5, + 0x1.d37a0ac892692p-6, -0x1.86a5ed802a36ap-3, 0x1.9fca37f675a4cp-4, -0x1.12ce0a06a602fp-4, + -0x1.5de829e07f658p-5, 0x1.36e711c09b6afp-3, -0x1.8d6b4d1f6f540p-4, 0x1.5081c7b7b70d0p-5, + 0x1.082236d6fbff8p-3, -0x1.0a1752e607953p-2, 0x1.61c6ff2202591p-3, -0x1.e1ccf125d2c3fp-6, + 0x1.72d6b604fe25ep-6, 0x1.ff25ec3325055p-6, -0x1.7daae939b978cp-5, -0x1.72b132bf73747p-7, + -0x1.528f2983390b0p-5, 0x1.b280aa9cc9d91p-4, -0x1.bb25677be7aa5p-4, 0x1.412aa66fc7c31p-6, + 0x1.33225dbe07eb3p-5, -0x1.a5ada1579c0efp-4, 0x1.6f99cd3adeae3p-3, 0x1.17e85d8c912c9p-10, + -0x1.87b199fd14196p-8, -0x1.b7a7ad9a9b5b3p-4, -0x1.42a5debc5aae7p-7, -0x1.22554af8f7e8cp-6, + 0x1.15d1f37a19ef7p-6, -0x1.2666f908b983ap-6, -0x1.f71045702bf9fp-6, 0x1.36d4c7f92451ep-6, + -0x1.36d4c7f92451ep-6, 0x1.f71045702bf9fp-6, 0x1.2666f908b983ap-6, -0x1.15d1f37a19ef7p-6, + 0x1.22554af8f7e8cp-6, 0x1.42a5debc5aae7p-7, 0x1.b7a7ad9a9b5b3p-4, 0x1.87b199fd14196p-8, + -0x1.17e85d8c912c9p-10, -0x1.6f99cd3adeae3p-3, 0x1.a5ada1579c0efp-4, -0x1.33225dbe07eb3p-5, + -0x1.412aa66fc7c31p-6, 0x1.bb25677be7aa5p-4, -0x1.b280aa9cc9d91p-4, 0x1.528f2983390b0p-5, + 0x1.72b132bf73747p-7, 0x1.7daae939b978cp-5, -0x1.ff25ec3325055p-6, -0x1.72d6b604fe25ep-6, + 0x1.e1ccf125d2c3fp-6, -0x1.61c6ff2202591p-3, 0x1.0a1752e607953p-2, -0x1.082236d6fbff8p-3, + -0x1.5081c7b7b70d0p-5, 0x1.8d6b4d1f6f540p-4, -0x1.36e711c09b6afp-3, 0x1.5de829e07f658p-5, + 0x1.12ce0a06a602fp-4, -0x1.9fca37f675a4cp-4, 0x1.86a5ed802a36ap-3, -0x1.d37a0ac892692p-6, + 0x1.cdbc99d6714bdp-5, -0x1.2453c8ecc5d60p-3, 0x1.800ff3d55c1a0p-3, -0x1.9b3a46fa5f24cp-4, + -0x1.df6ebe0881af3p-6, 0x1.1d53fcd59819cp-3, -0x1.33fb26c6726f5p-6, -0x1.06a06a09775d7p-6, + 0x1.3710471edf08cp-4, 0x1.4c4cc2fbb3fd9p-5, 0x1.a4ab4396960edp-7, 0x1.5a8e2dbb0ef03p-9, + -0x1.083e6de776ac8p-4, 0x1.2ba91c4f656b6p-4, -0x1.d996d0f14d4e4p-6, 0x1.25d0e25f48990p-6, + 0x1.c811ea0c60925p-12, -0x1.1a7094450a92ep-5, 0x1.350df775c83aap-3, -0x1.c35f72b24df05p-5, + 0x1.65e8a225015f1p-4, -0x1.c4e91d8b055ecp-4, -0x1.3d0e6f70d8491p-5, 0x1.b2cdf48b504ecp-4, + -0x1.a2c7d852638bap-7, -0x1.080bff5122ed5p-4, -0x1.f98667758f05cp-5, 0x1.0f4a4f5db9011p-4, + -0x1.d6fd4d0b8dfd5p-4, -0x1.2c28cc898b2d2p-5, -0x1.7616c4ddc3168p-4, 0x1.5caec93b1dd20p-4, + 0x1.7616c44280abap-4, 0x1.5caec728734f0p-4, -0x1.d6fd4d0225114p-4, 0x1.2c28cd016518ap-5, + 0x1.f98666a9db6fbp-5, 0x1.0f4a4f11c589ep-4, -0x1.a2c7dafcadb27p-7, 0x1.080bff2b8050dp-4, + 0x1.3d0e6f1ba07c7p-5, 0x1.b2cdf49317f1cp-4, 0x1.65e8a21248e97p-4, 0x1.c4e91d9845c46p-4, + -0x1.350df797e8138p-3, -0x1.c35f72874c583p-5, 0x1.c8122be36cd97p-12, 0x1.1a7094cef8bbcp-5, + 0x1.d996cf75f4f10p-6, 0x1.25d0e3689dfcbp-6, -0x1.083e6dea62419p-4, -0x1.2ba91caed9903p-4, + -0x1.a4ab45fde865ep-7, 0x1.5a8e2d248971fp-9, 0x1.3710474091c14p-4, -0x1.4c4cc39db8be0p-5, + 0x1.33fb259acd5c3p-6, -0x1.06a06918941cfp-6, -0x1.df6ebe451c40ap-6, -0x1.1d53fccb6169ep-3, + -0x1.800ff3a9ad324p-3, -0x1.9b3a47179adcbp-4, 0x1.cdbc99fd92513p-5, 0x1.2453c8e8e8020p-3, + -0x1.86a5ed9af6d48p-3, -0x1.d37a0af914e0ap-6, 0x1.12ce0a05aa97ap-4, 0x1.9fca385fa8ebap-4, + 0x1.36e711c13f9d5p-3, 0x1.5de829cbe13c3p-5, -0x1.5081c7c0778f5p-5, -0x1.8d6b4d92e37e6p-4, + -0x1.0a1752f40e2e2p-2, -0x1.082236ea8d7dfp-3, 0x1.e1ccf16fcbcacp-6, 0x1.61c6ff26a0d20p-3, + 0x1.ff25ece112097p-6, -0x1.72d6b571a70bep-6, 0x1.72b131bf0e4b1p-7, -0x1.7daae9d3628dep-5, + 0x1.b280aa6c99cb0p-4, 0x1.528f296e1f154p-5, -0x1.412aa68668c39p-6, -0x1.bb256774790c5p-4, + -0x1.a5ada1db43ed7p-4, -0x1.33225ddbe1cc6p-5, -0x1.17e8571ca4afcp-10, 0x1.6f99cd17fc082p-3, + -0x1.b7a7ad9d7290fp-4, 0x1.87b197d96eba9p-8, 0x1.22554af81fc40p-6, -0x1.42a5e1282e49bp-7, + -0x1.2666fa0808185p-6, -0x1.15d1f34d7c75ap-6, -0x1.36d4c837524a0p-6, -0x1.f71045c1b8a7dp-6, + 0x1.f71045c1b8a7dp-6, 0x1.36d4c837524a0p-6, 0x1.15d1f34d7c75ap-6, 0x1.2666fa0808185p-6, + 0x1.42a5e1282e49bp-7, -0x1.22554af81fc40p-6, -0x1.87b197d96eba9p-8, 0x1.b7a7ad9d7290fp-4, + -0x1.6f99cd17fc082p-3, 0x1.17e8571ca4afcp-10, 0x1.33225ddbe1cc6p-5, 0x1.a5ada1db43ed7p-4, + 0x1.bb256774790c5p-4, 0x1.412aa68668c39p-6, -0x1.528f296e1f154p-5, -0x1.b280aa6c99cb0p-4, + 0x1.7daae9d3628dep-5, -0x1.72b131bf0e4b1p-7, 0x1.72d6b571a70bep-6, -0x1.ff25ece112097p-6, + -0x1.61c6ff26a0d20p-3, -0x1.e1ccf16fcbcacp-6, 0x1.082236ea8d7dfp-3, 0x1.0a1752f40e2e2p-2, + 0x1.8d6b4d92e37e6p-4, 0x1.5081c7c0778f5p-5, -0x1.5de829cbe13c3p-5, -0x1.36e711c13f9d5p-3, + -0x1.9fca385fa8ebap-4, -0x1.12ce0a05aa97ap-4, 0x1.d37a0af914e0ap-6, 0x1.86a5ed9af6d48p-3, + -0x1.2453c8e8e8020p-3, -0x1.cdbc99fd92513p-5, 0x1.9b3a47179adcbp-4, 0x1.800ff3a9ad324p-3, + 0x1.1d53fccb6169ep-3, 0x1.df6ebe451c40ap-6, 0x1.06a06918941cfp-6, -0x1.33fb259acd5c3p-6, + 0x1.4c4cc39db8be0p-5, -0x1.3710474091c14p-4, -0x1.5a8e2d248971fp-9, 0x1.a4ab45fde865ep-7, + 0x1.2ba91caed9903p-4, 0x1.083e6dea62419p-4, -0x1.25d0e3689dfcbp-6, -0x1.d996cf75f4f10p-6, + -0x1.1a7094cef8bbcp-5, -0x1.c8122be36cd97p-12, 0x1.c35f72874c583p-5, 0x1.350df797e8138p-3, + -0x1.c4e91d9845c46p-4, -0x1.65e8a21248e97p-4, -0x1.b2cdf49317f1cp-4, -0x1.3d0e6f1ba07c7p-5, + -0x1.080bff2b8050cp-4, 0x1.a2c7dafcadb1fp-7, -0x1.0f4a4f11c589dp-4, -0x1.f98666a9db6f5p-5, + -0x1.2c28cd016517bp-5, 0x1.d6fd4d0225115p-4, -0x1.5caec962e43e2p-4, -0x1.7616c4c3a7a9ep-4, + -0x1.5c77b989ff36fp-4, 0x1.771e77f3bcd78p-4, 0x1.8fbcc57281883p-4, 0x1.3fed956dc018bp-4, + 0x1.21a796d6663dfp-4, -0x1.a63095493012ap-4, -0x1.ba5aa45f83adfp-4, -0x1.01cfcb9a51ab5p-4, + -0x1.c1249536e8ea0p-5, 0x1.cc1f0f9a298d4p-4, 0x1.db6526c875be0p-4, 0x1.7c3a9955586bep-5, + 0x1.354109e28727ep-5, -0x1.e817bcec2b7b7p-4, -0x1.f2252dfc31595p-4, -0x1.d9351498e55ccp-6, + -0x1.455762d434b01p-6, 0x1.f97f92370bc94p-4, 0x1.fe1caed2bca83p-4, 0x1.5f6d0c5da8274p-7, + 0x1.921ce22f273b1p-10, -0x1.fff624b5bd27bp-4, -0x1.ff0954fe2959fp-4, 0x1.f656c8bccb828p-8, + 0x1.139f1dff3d3d1p-6, 0x1.fb57963c6b415p-4, 0x1.f4e60468c3156p-4, -0x1.a829fb361ef14p-6, + -0x1.1d344938109ccp-5, -0x1.ebbd89e692b60p-4, -0x1.dfeae44ea8aa0p-4, 0x1.64c7d60896f1fp-5, + 0x1.aa6c876e494ecp-5, 0x1.d17e75ccb2ba2p-4, 0x1.c08c435982bf3p-4, -0x1.edc18c8a7f85ap-5, + -0x1.1734d84a37ca0p-4, -0x1.ad2bc76a46502p-4, -0x1.9777f43cdd338p-4, 0x1.360587e358133p-4, + 0x1.53282b38a1910p-4, 0x1.7f8eca9070048p-4, 0x1.6591971158544p-4, -0x1.6e744352ec95ep-4, + -0x1.87c404b47232dp-4, -0x1.49a44acba35dcp-4, -0x1.2bedb5538a428p-4, 0x1.9ef43f3974ae1p-4, + 0x1.b3e4d16e5a54cp-4, 0x1.0c97016c0adebp-4, 0x1.d7977e4088c66p-5, -0x1.c678b17a9a53fp-4, + -0x1.d6961a1fb2d71p-4, -0x1.9372a6aeeb001p-5, -0x1.4d1e2a24645e1p-5, 0x1.e426a5826ce48p-4, + 0x1.ef1787dde1513p-4, 0x1.04fb74dfdb421p-5, 0x1.76ddad8e89ecep-6, -0x1.f7599a2c6a24fp-4, + -0x1.fce1611e1b26ep-4, -0x1.c3783313b2015p-7, -0x1.2d86982126e12p-8, 0x1.ffa72fe42316fp-4, + 0x1.ffa72fe42316fp-4, -0x1.2d86982126e12p-8, -0x1.c3783313b2015p-7, -0x1.fce1611e1b26ep-4, + -0x1.f7599a2c6a24fp-4, 0x1.76ddad8e89ecep-6, 0x1.04fb74dfdb421p-5, 0x1.ef1787dde1513p-4, + 0x1.e426a5826ce48p-4, -0x1.4d1e2a24645e1p-5, -0x1.9372a6aeeb001p-5, -0x1.d6961a1fb2d71p-4, + -0x1.c678b17a9a53fp-4, 0x1.d7977e4088c66p-5, 0x1.0c97016c0adebp-4, 0x1.b3e4d16e5a54cp-4, + 0x1.9ef43f3974ae1p-4, -0x1.2bedb5538a428p-4, -0x1.49a44acba35dcp-4, -0x1.87c404b47232dp-4, + -0x1.6e744352ec95ep-4, 0x1.6591971158544p-4, 0x1.7f8eca9070048p-4, 0x1.53282b38a1910p-4, + 0x1.360587e358133p-4, -0x1.9777f43cdd338p-4, -0x1.ad2bc76a46502p-4, -0x1.1734d84a37ca0p-4, + -0x1.edc18c8a7f85ap-5, 0x1.c08c435982bf3p-4, 0x1.d17e75ccb2ba2p-4, 0x1.aa6c876e494ecp-5, + 0x1.64c7d60896f1fp-5, -0x1.dfeae44ea8aa0p-4, -0x1.ebbd89e692b60p-4, -0x1.1d344938109ccp-5, + -0x1.a829fb361ef14p-6, 0x1.f4e60468c3156p-4, 0x1.fb57963c6b415p-4, 0x1.139f1dff3d3d1p-6, + 0x1.f656c8bccb828p-8, -0x1.ff0954fe2959fp-4, -0x1.fff624b5bd27bp-4, 0x1.921ce22f273b1p-10, + 0x1.5f6d0c5da8274p-7, 0x1.fe1caed2bca83p-4, 0x1.f97f92370bc94p-4, -0x1.455762d434b01p-6, + -0x1.d9351498e55ccp-6, -0x1.f2252dfc31595p-4, -0x1.e817bcec2b7b7p-4, 0x1.354109e28727ep-5, + 0x1.7c3a9955586bep-5, 0x1.db6526c875be0p-4, 0x1.cc1f0f9a298d4p-4, -0x1.c1249536e8ea0p-5, + -0x1.01cfcb9a51ab5p-4, -0x1.ba5aa45f83adfp-4, -0x1.a63095493012ap-4, 0x1.21a796d6663dfp-4, + 0x1.3fed956dc018bp-4, 0x1.8fbcc57281883p-4, 0x1.771e77f3bcd79p-4, -0x1.5c77b989ff36ap-4, + -0x1.771e787c4309bp-4, -0x1.5c77b8cd6caf0p-4, 0x1.3fed943be70ecp-4, -0x1.8fbcc637a3b06p-4, + 0x1.a6309373aa8f7p-4, 0x1.21a797684496bp-4, -0x1.01cfca676c2d8p-4, 0x1.ba5aa3e078b75p-4, + -0x1.cc1f0f7ee7185p-4, -0x1.c12494d569ea8p-5, 0x1.7c3a97607a5c9p-5, -0x1.db6526b2b6529p-4, + 0x1.e817bd8e08cd4p-4, 0x1.354108f2d52fep-5, -0x1.d93515e0b1acfp-6, 0x1.f225306a9d6c4p-4, + -0x1.f97f910c1adc8p-4, -0x1.455761d13b223p-6, 0x1.5f6d0d46d4df9p-7, -0x1.fe1cafb563cd4p-4, + 0x1.fff623d9a5ef7p-4, 0x1.921cd532cf9a5p-10, 0x1.f656c53f15be6p-8, 0x1.ff095481bb230p-4, + -0x1.fb5798412000cp-4, 0x1.139f1f0061634p-6, -0x1.a829fa184e596p-6, -0x1.f4e604091c8fbp-4, + 0x1.ebbd8b08a611cp-4, -0x1.1d3448a047647p-5, 0x1.64c7d5b56f363p-5, 0x1.dfeae46f3f703p-4, + -0x1.d17e77bbba73ep-4, 0x1.aa6c87a2e25ddp-5, -0x1.edc18b925799ap-5, -0x1.c08c44dcfca37p-4, + 0x1.ad2bc5ce6fd7bp-4, -0x1.1734d8e5637b8p-4, 0x1.360586f6d912cp-4, 0x1.9777f4e7337e5p-4, + -0x1.7f8ecbdd04c5ap-4, 0x1.53282a676c65ep-4, -0x1.6e7442eb38536p-4, -0x1.65919681955f8p-4, + 0x1.49a44b3d044e8p-4, -0x1.87c40376ada56p-4, 0x1.9ef43d65e6ecep-4, 0x1.2bedb4620b39dp-4, + -0x1.0c970164dcf41p-4, 0x1.b3e4d2a68fc1ap-4, -0x1.c678b20e88b05p-4, -0x1.d7977e3a48fddp-5, + 0x1.9372a5bcebd76p-5, -0x1.d696193069dabp-4, 0x1.e426a36f82048p-4, 0x1.4d1e2b3c5c276p-5, + -0x1.04fb7468d4adbp-5, 0x1.ef1789da1bdbfp-4, -0x1.f7599c305b9a8p-4, -0x1.76ddae2d8cdfep-6, + 0x1.c3783192c8d7ep-7, -0x1.fce15fab623e4p-4, 0x1.ffa72f0e65ba2p-4, 0x1.2d869ab265b56p-8, + 0x1.2d869ab265b56p-8, 0x1.ffa72f0e65ba2p-4, -0x1.fce15fab623e4p-4, 0x1.c3783192c8d7ep-7, + -0x1.76ddae2d8cdfep-6, -0x1.f7599c305b9a8p-4, 0x1.ef1789da1bdbfp-4, -0x1.04fb7468d4adbp-5, + 0x1.4d1e2b3c5c276p-5, 0x1.e426a36f82048p-4, -0x1.d696193069dabp-4, 0x1.9372a5bcebd76p-5, + -0x1.d7977e3a48fddp-5, -0x1.c678b20e88b05p-4, 0x1.b3e4d2a68fc1ap-4, -0x1.0c970164dcf41p-4, + 0x1.2bedb4620b39dp-4, 0x1.9ef43d65e6ecep-4, -0x1.87c40376ada56p-4, 0x1.49a44b3d044e8p-4, + -0x1.65919681955f8p-4, -0x1.6e7442eb38536p-4, 0x1.53282a676c65ep-4, -0x1.7f8ecbdd04c5ap-4, + 0x1.9777f4e7337e5p-4, 0x1.360586f6d912cp-4, -0x1.1734d8e5637b8p-4, 0x1.ad2bc5ce6fd7bp-4, + -0x1.c08c44dcfca37p-4, -0x1.edc18b925799ap-5, 0x1.aa6c87a2e25ddp-5, -0x1.d17e77bbba73ep-4, + 0x1.dfeae46f3f703p-4, 0x1.64c7d5b56f363p-5, -0x1.1d3448a047647p-5, 0x1.ebbd8b08a611cp-4, + -0x1.f4e604091c8fbp-4, -0x1.a829fa184e596p-6, 0x1.139f1f0061634p-6, -0x1.fb5798412000cp-4, + 0x1.ff095481bb230p-4, 0x1.f656c53f15be6p-8, 0x1.921cd532cf9a5p-10, 0x1.fff623d9a5ef7p-4, + -0x1.fe1cafb563cd4p-4, 0x1.5f6d0d46d4df9p-7, -0x1.455761d13b223p-6, -0x1.f97f910c1adc8p-4, + 0x1.f225306a9d6c4p-4, -0x1.d93515e0b1acfp-6, 0x1.354108f2d52fep-5, 0x1.e817bd8e08cd4p-4, + -0x1.db6526b2b6529p-4, 0x1.7c3a97607a5c9p-5, -0x1.c12494d569ea8p-5, -0x1.cc1f0f7ee7185p-4, + 0x1.ba5aa3e078b75p-4, -0x1.01cfca676c2d8p-4, 0x1.21a797684496bp-4, 0x1.a6309373aa8f7p-4, + -0x1.8fbcc637a3b06p-4, 0x1.3fed943be70ecp-4, -0x1.5c77b8cd6caf7p-4, -0x1.771e787c43099p-4, + -0x1.0e735aff58886p-3, 0x1.6affdce390a61p-6, -0x1.cbee5c6c8e0bbp-5, 0x1.05048c766eb06p-5, + -0x1.a9b932ebef3aep-4, -0x1.f574c10aa869cp-4, 0x1.873ea7ae21228p-5, 0x1.746455a79ee7bp-6, + -0x1.c853380a1c54ep-6, 0x1.2712279012ae4p-5, -0x1.0cd186f1b3444p-4, -0x1.b83e0f29ed0a7p-7, + 0x1.e6f7c1b433927p-5, -0x1.4f54ce0aff53ep-5, 0x1.fb42a25988424p-4, 0x1.09106c2682a0bp-5, + 0x1.ac120e1cf7309p-4, -0x1.5ce90786f7e7cp-8, -0x1.245f53e4444f7p-4, -0x1.f0f6caf82f006p-4, + 0x1.cafb7b91c565ep-5, -0x1.765a0b2ab3050p-7, -0x1.5348c1a3c26e6p-4, 0x1.f9759e657b39bp-5, + -0x1.1ec36807ca345p-5, -0x1.6d9c5adb1f1d0p-4, -0x1.f417c2a0c9349p-5, -0x1.d8125a72699adp-8, + -0x1.7aba4cf7b3338p-4, -0x1.2e88af0e1ada3p-8, 0x1.a5b2045a87c00p-6, -0x1.ef49ec5c66d80p-6, + -0x1.5a7614b333a5dp-3, -0x1.d1f3572eede7cp-4, -0x1.cb7b62c8e97b6p-4, -0x1.d07f59220695bp-4, + 0x1.1d5e6cbb43787p-4, -0x1.aea27e6a5fafdp-3, 0x1.bd09ea89a44d1p-7, 0x1.c6b780ecc4facp-4, + -0x1.15e6d0e7bd554p-7, -0x1.a6d5cc97450f9p-5, 0x1.2cb0710ebff88p-3, 0x1.22100c525a45fp-4, + -0x1.400ddc2a8366bp-4, 0x1.753011c8fc31ep-4, -0x1.3dc1560e44a39p-3, 0x1.20359882a8383p-3, + -0x1.8d9130c8aac85p-7, 0x1.6566ee6e198d1p-3, 0x1.f0399fc7d7c2fp-4, 0x1.61f469e038221p-4, + 0x1.5d3f5803ce709p-6, -0x1.46d64e90243eap-4, -0x1.5c7d491a45f12p-4, 0x1.cb5ac16b17de6p-8, + -0x1.3a20483b38abfp-4, -0x1.8b107edfb095ep-6, -0x1.f048811e4499fp-4, 0x1.51c273984a239p-4, + -0x1.0fd0715e93882p-4, 0x1.3a0d66fa3e067p-4, -0x1.6ec6136d0daadp-3, 0x1.cee79d59997e8p-9, + 0x1.cee79d59997e8p-9, -0x1.6ec6136d0daadp-3, 0x1.3a0d66fa3e067p-4, -0x1.0fd0715e93882p-4, + 0x1.51c273984a239p-4, -0x1.f048811e4499fp-4, -0x1.8b107edfb095ep-6, -0x1.3a20483b38abfp-4, + 0x1.cb5ac16b17de6p-8, -0x1.5c7d491a45f12p-4, -0x1.46d64e90243eap-4, 0x1.5d3f5803ce709p-6, + 0x1.61f469e038221p-4, 0x1.f0399fc7d7c2fp-4, 0x1.6566ee6e198d1p-3, -0x1.8d9130c8aac85p-7, + 0x1.20359882a8383p-3, -0x1.3dc1560e44a39p-3, 0x1.753011c8fc31ep-4, -0x1.400ddc2a8366bp-4, + 0x1.22100c525a45fp-4, 0x1.2cb0710ebff88p-3, -0x1.a6d5cc97450f9p-5, -0x1.15e6d0e7bd554p-7, + 0x1.c6b780ecc4facp-4, 0x1.bd09ea89a44d1p-7, -0x1.aea27e6a5fafdp-3, 0x1.1d5e6cbb43787p-4, + -0x1.d07f59220695bp-4, -0x1.cb7b62c8e97b6p-4, -0x1.d1f3572eede7cp-4, -0x1.5a7614b333a5dp-3, + -0x1.ef49ec5c66d80p-6, 0x1.a5b2045a87c00p-6, -0x1.2e88af0e1ada3p-8, -0x1.7aba4cf7b3338p-4, + -0x1.d8125a72699adp-8, -0x1.f417c2a0c9349p-5, -0x1.6d9c5adb1f1d0p-4, -0x1.1ec36807ca345p-5, + 0x1.f9759e657b39bp-5, -0x1.5348c1a3c26e6p-4, -0x1.765a0b2ab3050p-7, 0x1.cafb7b91c565ep-5, + -0x1.f0f6caf82f006p-4, -0x1.245f53e4444f7p-4, -0x1.5ce90786f7e7cp-8, 0x1.ac120e1cf7309p-4, + 0x1.09106c2682a0bp-5, 0x1.fb42a25988424p-4, -0x1.4f54ce0aff53ep-5, 0x1.e6f7c1b433927p-5, + -0x1.b83e0f29ed0a7p-7, -0x1.0cd186f1b3444p-4, 0x1.2712279012ae4p-5, -0x1.c853380a1c54ep-6, + 0x1.746455a79ee7dp-6, 0x1.873ea7ae2122ap-5, -0x1.f574c10aa8699p-4, -0x1.a9b932ebef3b1p-4, + 0x1.05048c766eaf4p-5, -0x1.cbee5c6c8e0c2p-5, 0x1.6affe14d22c43p-6, -0x1.0e735b46a047ep-3, + 0x1.4ef73e3ea4886p-6, 0x1.49a20904e29cdp-4, -0x1.8f66237a3a4cbp-5, -0x1.ef1e4947a0ce5p-5, + -0x1.2b1ac81526229p-4, 0x1.c2c68cd0b351fp-3, -0x1.3ab530e67f713p-5, 0x1.e73afccab8e10p-4, + 0x1.11bcdccf1d2a5p-7, -0x1.26d8d288e38fcp-4, -0x1.163622745268bp-5, -0x1.e15e4c9c8d574p-5, + -0x1.ec645bb2aa589p-5, 0x1.bd350ff11dad0p-6, -0x1.6b0e4433f72c0p-3, -0x1.84548a8f73df9p-9, + 0x1.7a2f290328342p-3, -0x1.f366aecffeebfp-6, 0x1.852c73f8c7ea4p-4, -0x1.4195611915893p-3, + 0x1.f6dbbc7f48e3fp-5, -0x1.296b21915caf0p-12, 0x1.a2918fa9ae119p-4, 0x1.01b37433ba8c1p-4, + -0x1.0a8311740918dp-4, 0x1.071beb0db936cp-3, 0x1.025e8332cf3cdp-4, -0x1.2f164fca78e33p-12, + -0x1.cc72d86161c33p-6, -0x1.27a0b7a37dde6p-4, 0x1.63b7bfa11007cp-5, -0x1.33dfb2da60290p-4, + -0x1.2db06b8c75e0ap-3, 0x1.178b9827f3bf1p-4, 0x1.c75be31151c32p-4, -0x1.1c73487514a20p-4, + -0x1.adbe7d3077698p-4, 0x1.03c11d5417a75p-3, 0x1.619315edd8bd3p-5, -0x1.16872418069e7p-7, + -0x1.c5b0dab33505dp-5, 0x1.2aa06d7838a0ap-4, 0x1.cd11f96908c56p-6, -0x1.02a6daecb1430p-4, + 0x1.17a40e6af4837p-5, 0x1.8b324d0ae09a7p-6, -0x1.09cd30349961cp-6, -0x1.0c3c1ad119311p-3, + 0x1.a020e5806655cp-7, -0x1.4083ea9fd19c4p-7, 0x1.ae79feadc0f20p-5, -0x1.8e0528b7fb195p-5, + 0x1.2d743da5f2c17p-4, 0x1.2db72610eada5p-6, -0x1.a1a15ea123601p-3, -0x1.bcf9c626386acp-7, + 0x1.6c4e2e9bad578p-4, -0x1.edcd2ca96ce3dp-6, -0x1.3f9c15955c43fp-3, -0x1.61a10b0c1c102p-4, + 0x1.1cdbced48114cp-5, 0x1.ffe87db1642bbp-5, -0x1.a8df709479dc2p-3, 0x1.234acbf6ca91ap-6, + 0x1.234acbf6ca91ap-6, -0x1.a8df709479dc2p-3, 0x1.ffe87db1642bbp-5, 0x1.1cdbced48114cp-5, + -0x1.61a10b0c1c102p-4, -0x1.3f9c15955c43fp-3, -0x1.edcd2ca96ce3dp-6, 0x1.6c4e2e9bad578p-4, + -0x1.bcf9c626386acp-7, -0x1.a1a15ea123601p-3, 0x1.2db72610eada5p-6, 0x1.2d743da5f2c17p-4, + -0x1.8e0528b7fb195p-5, 0x1.ae79feadc0f20p-5, -0x1.4083ea9fd19c4p-7, 0x1.a020e5806655cp-7, + -0x1.0c3c1ad119311p-3, -0x1.09cd30349961cp-6, 0x1.8b324d0ae09a7p-6, 0x1.17a40e6af4837p-5, + -0x1.02a6daecb1430p-4, 0x1.cd11f96908c56p-6, 0x1.2aa06d7838a0ap-4, -0x1.c5b0dab33505dp-5, + -0x1.16872418069e7p-7, 0x1.619315edd8bd3p-5, 0x1.03c11d5417a75p-3, -0x1.adbe7d3077698p-4, + -0x1.1c73487514a20p-4, 0x1.c75be31151c32p-4, 0x1.178b9827f3bf1p-4, -0x1.2db06b8c75e0ap-3, + -0x1.33dfb2da60290p-4, 0x1.63b7bfa11007cp-5, -0x1.27a0b7a37dde6p-4, -0x1.cc72d86161c33p-6, + -0x1.2f164fca78e33p-12, 0x1.025e8332cf3cdp-4, 0x1.071beb0db936cp-3, -0x1.0a8311740918dp-4, + 0x1.01b37433ba8c1p-4, 0x1.a2918fa9ae119p-4, -0x1.296b21915caf0p-12, 0x1.f6dbbc7f48e3fp-5, + -0x1.4195611915893p-3, 0x1.852c73f8c7ea4p-4, -0x1.f366aecffeebfp-6, 0x1.7a2f290328342p-3, + -0x1.84548a8f73df9p-9, -0x1.6b0e4433f72c0p-3, 0x1.bd350ff11dad0p-6, -0x1.ec645bb2aa589p-5, + -0x1.e15e4c9c8d574p-5, -0x1.163622745268bp-5, -0x1.26d8d288e38fcp-4, 0x1.11bcdccf1d2a5p-7, + 0x1.e73afccab8e10p-4, -0x1.3ab530e67f713p-5, 0x1.c2c68cd0b3520p-3, -0x1.2b1ac81526218p-4, + -0x1.ef1e4947a0cefp-5, -0x1.8f66237a3a4c0p-5, 0x1.49a20a41bf82cp-4, 0x1.4ef742c1a0067p-6, + -0x1.532829eaf2397p-4, 0x1.7f8ecfaef9b60p-4, 0x1.a630901dfd944p-4, 0x1.21a7992662313p-4, + 0x1.d79772c6b8101p-5, -0x1.c678b4119f1cap-4, -0x1.dfeae68f486f0p-4, -0x1.64c7e16910b9fp-5, + -0x1.d934fc0784336p-6, 0x1.f2252d284b212p-4, 0x1.fce15f1fdc461p-4, 0x1.c37861b223180p-7, + -0x1.921d45b840f4bp-10, -0x1.fff6212d18c06p-4, -0x1.fb57974d808a0p-4, 0x1.139f0c0e42abcp-6, + 0x1.04fb847ae2d08p-5, 0x1.ef178d10d2d11p-4, 0x1.db65250d2ac07p-4, -0x1.7c3a8cd474bc7p-5, + -0x1.edc19628f0019p-5, -0x1.c08c4159aeb58p-4, -0x1.9ef43e18dde59p-4, 0x1.2bedb0bb583edp-4, + 0x1.5c77bb0ec0e29p-4, 0x1.771e76a4232c6p-4, 0x1.49a44902c58a5p-4, -0x1.87c4026adfac1p-4, + -0x1.ad2bcb022da03p-4, -0x1.1734d598de357p-4, -0x1.c1249e0bd6684p-5, 0x1.cc1f0f3302860p-4, + 0x1.e426a5ad276b6p-4, 0x1.4d1e26a872be7p-5, 0x1.a82a042e12febp-6, -0x1.f4e6037b61b60p-4, + -0x1.fe1cafc302726p-4, -0x1.5f6ce7e82e3c7p-7, 0x1.2d865f04e6684p-8, 0x1.ffa72c791dbc3p-4, + 0x1.f97f8ed3a0ec1p-4, -0x1.455770f1adb83p-6, -0x1.1d34485732fcbp-5, -0x1.ebbd8c2cf6be9p-4, + -0x1.d6961846c87f7p-4, 0x1.9372aaa0bdb2cp-5, 0x1.01cfc692a4bd2p-4, 0x1.ba5aa76f23767p-4, + 0x1.9777ee4dde0a8p-4, -0x1.36058ac65a697p-4, -0x1.659190c3f42ddp-4, -0x1.6e74452d85307p-4, + -0x1.3fed96f457afap-4, 0x1.8fbccc82a09a4p-4, 0x1.b3e4d3ee2a183p-4, 0x1.0c97048c37771p-4, + 0x1.aa6c81f95339fp-5, -0x1.d17e7845b0b57p-4, -0x1.e817bb75e87cfp-4, -0x1.35410c0223212p-5, + -0x1.76dd9c3bf9bfbp-6, 0x1.f7599a5c875e2p-4, 0x1.ff095910b20c1p-4, 0x1.f65701e9dcecfp-8, + -0x1.f65701e9dcecfp-8, -0x1.ff095910b20c1p-4, -0x1.f7599a5c875e2p-4, 0x1.76dd9c3bf9bfbp-6, + 0x1.35410c0223212p-5, 0x1.e817bb75e87cfp-4, 0x1.d17e7845b0b57p-4, -0x1.aa6c81f95339fp-5, + -0x1.0c97048c37771p-4, -0x1.b3e4d3ee2a183p-4, -0x1.8fbccc82a09a4p-4, 0x1.3fed96f457afap-4, + 0x1.6e74452d85307p-4, 0x1.659190c3f42ddp-4, 0x1.36058ac65a697p-4, -0x1.9777ee4dde0a8p-4, + -0x1.ba5aa76f23767p-4, -0x1.01cfc692a4bd2p-4, -0x1.9372aaa0bdb2cp-5, 0x1.d6961846c87f7p-4, + 0x1.ebbd8c2cf6be9p-4, 0x1.1d34485732fcbp-5, 0x1.455770f1adb83p-6, -0x1.f97f8ed3a0ec1p-4, + -0x1.ffa72c791dbc3p-4, -0x1.2d865f04e6684p-8, 0x1.5f6ce7e82e3c7p-7, 0x1.fe1cafc302726p-4, + 0x1.f4e6037b61b60p-4, -0x1.a82a042e12febp-6, -0x1.4d1e26a872be7p-5, -0x1.e426a5ad276b6p-4, + -0x1.cc1f0f3302860p-4, 0x1.c1249e0bd6684p-5, 0x1.1734d598de357p-4, 0x1.ad2bcb022da03p-4, + 0x1.87c4026adfac1p-4, -0x1.49a44902c58a5p-4, -0x1.771e76a4232c6p-4, -0x1.5c77bb0ec0e29p-4, + -0x1.2bedb0bb583edp-4, 0x1.9ef43e18dde59p-4, 0x1.c08c4159aeb58p-4, 0x1.edc19628f0019p-5, + 0x1.7c3a8cd474bc7p-5, -0x1.db65250d2ac07p-4, -0x1.ef178d10d2d11p-4, -0x1.04fb847ae2d08p-5, + -0x1.139f0c0e42abcp-6, 0x1.fb57974d808a0p-4, 0x1.fff6212d18c06p-4, 0x1.921d45b840f4bp-10, + -0x1.c37861b223180p-7, -0x1.fce15f1fdc461p-4, -0x1.f2252d284b212p-4, 0x1.d934fc0784336p-6, + 0x1.64c7e16910b9fp-5, 0x1.dfeae68f486f0p-4, 0x1.c678b4119f1cap-4, -0x1.d79772c6b8101p-5, + -0x1.21a7992662313p-4, -0x1.a630901dfd944p-4, -0x1.7f8ecfaef9b5fp-4, 0x1.532829eaf2371p-4, + -0x1.7f8ecebdf3048p-4, -0x1.532829127069cp-4, 0x1.21a79937700f6p-4, -0x1.a6308f58bfa89p-4, + 0x1.c678b4acc739fp-4, 0x1.d7977347b52a0p-5, -0x1.64c7e018b34f7p-5, 0x1.dfeae58fc1790p-4, + -0x1.f2252be32bba5p-4, -0x1.d934fbdc79cb3p-6, 0x1.c378632d97e56p-7, -0x1.fce161059d9ddp-4, + 0x1.fff61ffeba9cap-4, -0x1.921d4bd7d0ef7p-10, 0x1.139f0b86904b6p-6, 0x1.fb5799dea30fcp-4, + -0x1.ef178c5f1208dp-4, 0x1.04fb83f980bf9p-5, -0x1.7c3a8e4232b5cp-5, -0x1.db65241a362bdp-4, + 0x1.c08c42f4cc71ap-4, -0x1.edc197c24fe93p-5, 0x1.2bedb1a403d2dp-4, 0x1.9ef43c3bc065dp-4, + -0x1.771e768967fddp-4, 0x1.5c77baf2ccc4cp-4, -0x1.87c401af3acb0p-4, -0x1.49a449b302738p-4, + 0x1.1734d52529d6bp-4, -0x1.ad2bca68c29afp-4, 0x1.cc1f0eed850f7p-4, 0x1.c1249ee71945cp-5, + -0x1.4d1e2620d86e8p-5, 0x1.e426a60064869p-4, -0x1.f4e6043625234p-4, -0x1.a82a03e01f97ap-6, + 0x1.5f6ce62778713p-7, -0x1.fe1caf2781f3cp-4, 0x1.ffa72bba0d2c4p-4, -0x1.2d865d7904771p-8, + 0x1.455770599b8bap-6, 0x1.f97f901604e16p-4, -0x1.ebbd8b7abe2bfp-4, 0x1.1d34489579fafp-5, + -0x1.9372a9aa4a37cp-5, -0x1.d696192ec45a4p-4, 0x1.ba5aa83e80b50p-4, -0x1.01cfc74f67133p-4, + 0x1.36058b7eabfd7p-4, 0x1.9777efd04a8aap-4, -0x1.6e74457c892d5p-4, 0x1.659190c3bc212p-4, + -0x1.8fbcce3cb3625p-4, -0x1.3fed97788aaa3p-4, 0x1.0c9705107dbf5p-4, -0x1.b3e4d26b1b708p-4, + 0x1.d17e77f8063d1p-4, 0x1.aa6c8219c2f2dp-5, -0x1.35410c7e86111p-5, 0x1.e817bb99e0cd5p-4, + -0x1.f75999c168463p-4, -0x1.76dd9b2088229p-6, 0x1.f65703a1ff5b1p-8, -0x1.ff09575d2a9fbp-4, + 0x1.ff09575d2a9fbp-4, -0x1.f65703a1ff5b1p-8, 0x1.76dd9b2088229p-6, 0x1.f75999c168463p-4, + -0x1.e817bb99e0cd5p-4, 0x1.35410c7e86111p-5, -0x1.aa6c8219c2f2dp-5, -0x1.d17e77f8063d1p-4, + 0x1.b3e4d26b1b708p-4, -0x1.0c9705107dbf5p-4, 0x1.3fed97788aaa3p-4, 0x1.8fbcce3cb3625p-4, + -0x1.659190c3bc212p-4, 0x1.6e74457c892d5p-4, -0x1.9777efd04a8aap-4, -0x1.36058b7eabfd7p-4, + 0x1.01cfc74f67133p-4, -0x1.ba5aa83e80b50p-4, 0x1.d696192ec45a4p-4, 0x1.9372a9aa4a37cp-5, + -0x1.1d34489579fafp-5, 0x1.ebbd8b7abe2bfp-4, -0x1.f97f901604e16p-4, -0x1.455770599b8bap-6, + 0x1.2d865d7904771p-8, -0x1.ffa72bba0d2c4p-4, 0x1.fe1caf2781f3cp-4, -0x1.5f6ce62778713p-7, + 0x1.a82a03e01f97ap-6, 0x1.f4e6043625234p-4, -0x1.e426a60064869p-4, 0x1.4d1e2620d86e8p-5, + -0x1.c1249ee71945cp-5, -0x1.cc1f0eed850f7p-4, 0x1.ad2bca68c29afp-4, -0x1.1734d52529d6bp-4, + 0x1.49a449b302738p-4, 0x1.87c401af3acb0p-4, -0x1.5c77baf2ccc4cp-4, 0x1.771e768967fddp-4, + -0x1.9ef43c3bc065dp-4, -0x1.2bedb1a403d2dp-4, 0x1.edc197c24fe93p-5, -0x1.c08c42f4cc71ap-4, + 0x1.db65241a362bdp-4, 0x1.7c3a8e4232b5cp-5, -0x1.04fb83f980bf9p-5, 0x1.ef178c5f1208dp-4, + -0x1.fb5799dea30fcp-4, -0x1.139f0b86904b6p-6, 0x1.921d4bd7d0ef7p-10, -0x1.fff61ffeba9cap-4, + 0x1.fce161059d9ddp-4, -0x1.c378632d97e56p-7, 0x1.d934fbdc79cb3p-6, 0x1.f2252be32bba5p-4, + -0x1.dfeae58fc1790p-4, 0x1.64c7e018b34f7p-5, -0x1.d7977347b52a0p-5, -0x1.c678b4acc739fp-4, + 0x1.a6308f58bfa89p-4, -0x1.21a79937700f6p-4, 0x1.53282912706a1p-4, 0x1.7f8ecebdf3046p-4, + -0x1.edfaac1b80b64p-6, -0x1.53ba3f837eaa3p-6, -0x1.d11dae518acd4p-5, 0x1.c149d77b2abf2p-7, + 0x1.3b293484b5fc2p-4, -0x1.e4ebc53d5dd34p-4, 0x1.50b0b1501a3f2p-6, 0x1.62553a2059176p-6, + -0x1.bc4ea52b5bf95p-4, 0x1.5f1d01817d899p-5, -0x1.040a9a7b2246ap-6, 0x1.feab69c3901a2p-4, + 0x1.6ce8a48d76d44p-6, -0x1.039926a2a817fp-6, -0x1.256bc9868b9ebp-6, -0x1.0c437a37e8786p-2, + 0x1.0778788a23685p-3, 0x1.79a6ea24c0d9ap-6, -0x1.87fb88551abc7p-7, -0x1.04aada36a829ep-3, + -0x1.8ef21ff225576p-3, 0x1.2f890f5163d73p-3, -0x1.337a117ae5cd1p-9, 0x1.ca7fc335c2ec5p-5, + 0x1.47fbab59e746ap-3, 0x1.b724220384733p-9, -0x1.232b9670399f4p-6, 0x1.1e46f1b59b691p-5, + 0x1.39b0cd35cb1b4p-5, -0x1.f21b09f7d776ep-5, -0x1.8e1ee44284c85p-5, -0x1.42a0cf72e9cc4p-5, + -0x1.1962d0dbe1e98p-6, 0x1.802f824221f91p-7, -0x1.c2e5c49dc7fcep-4, -0x1.caa15968ceca6p-6, + 0x1.a5150b1d96483p-7, -0x1.a8811a607a33cp-3, 0x1.f4e3ae765a6a0p-4, 0x1.c3097038c78abp-7, + 0x1.5ed6e5169e678p-8, -0x1.d1954916940c2p-6, -0x1.7a325946af0f2p-3, -0x1.0997fe00cde6dp-5, + -0x1.09b4ef7724db6p-7, 0x1.d46cd1b747390p-4, -0x1.212fec503771fp-3, 0x1.d37cfec8eaef9p-6, + -0x1.f4b18ff25a498p-5, 0x1.16da7bce40979p-6, 0x1.dc48b4fc08914p-9, 0x1.6239c9ba43dbcp-4, + 0x1.3e6ccb1c1709ep-3, 0x1.1fba67fa49e0cp-9, -0x1.2793f1eeb16e6p-6, -0x1.9bd320a7095e6p-3, + 0x1.1df963df13d5ep-6, 0x1.64d8078883579p-9, 0x1.f8f2c4f54d7cdp-6, 0x1.2cb3f2adce49bp-3, + 0x1.43272fc990b59p-5, -0x1.7ca021dfda3a4p-16, 0x1.5b64567c1dcadp-7, -0x1.8083744173c99p-7, + 0x1.8083744173c99p-7, -0x1.5b64567c1dcadp-7, 0x1.7ca021dfda3a4p-16, -0x1.43272fc990b59p-5, + -0x1.2cb3f2adce49bp-3, -0x1.f8f2c4f54d7cdp-6, -0x1.64d8078883579p-9, -0x1.1df963df13d5ep-6, + 0x1.9bd320a7095e6p-3, 0x1.2793f1eeb16e6p-6, -0x1.1fba67fa49e0cp-9, -0x1.3e6ccb1c1709ep-3, + -0x1.6239c9ba43dbcp-4, -0x1.dc48b4fc08914p-9, -0x1.16da7bce40979p-6, 0x1.f4b18ff25a498p-5, + -0x1.d37cfec8eaef9p-6, 0x1.212fec503771fp-3, -0x1.d46cd1b747390p-4, 0x1.09b4ef7724db6p-7, + 0x1.0997fe00cde6dp-5, 0x1.7a325946af0f2p-3, 0x1.d1954916940c2p-6, -0x1.5ed6e5169e678p-8, + -0x1.c3097038c78abp-7, -0x1.f4e3ae765a6a0p-4, 0x1.a8811a607a33cp-3, -0x1.a5150b1d96483p-7, + 0x1.caa15968ceca6p-6, 0x1.c2e5c49dc7fcep-4, -0x1.802f824221f91p-7, 0x1.1962d0dbe1e98p-6, + 0x1.42a0cf72e9cc4p-5, 0x1.8e1ee44284c85p-5, 0x1.f21b09f7d776ep-5, -0x1.39b0cd35cb1b4p-5, + -0x1.1e46f1b59b691p-5, 0x1.232b9670399f4p-6, -0x1.b724220384733p-9, -0x1.47fbab59e746ap-3, + -0x1.ca7fc335c2ec5p-5, 0x1.337a117ae5cd1p-9, -0x1.2f890f5163d73p-3, 0x1.8ef21ff225576p-3, + 0x1.04aada36a829ep-3, 0x1.87fb88551abc7p-7, -0x1.79a6ea24c0d9ap-6, -0x1.0778788a23685p-3, + 0x1.0c437a37e8786p-2, 0x1.256bc9868b9ebp-6, 0x1.039926a2a817fp-6, -0x1.6ce8a48d76d44p-6, + -0x1.feab69c3901a2p-4, 0x1.040a9a7b2246ap-6, -0x1.5f1d01817d899p-5, 0x1.bc4ea52b5bf95p-4, + -0x1.62553a2059175p-6, -0x1.50b0b1501a3ebp-6, 0x1.e4ebc53d5dd35p-4, -0x1.3b293484b5fc0p-4, + -0x1.c149d77b2ac42p-7, 0x1.d11dae518acd0p-5, 0x1.53ba44da20e0bp-6, 0x1.edfaabc9978e9p-6, + 0x1.972d9d3479a95p-10, 0x1.2f0502131d662p-6, 0x1.65c5269063d3dp-3, 0x1.1c1b3e5e048eep-4, + 0x1.2534ae068f8a2p-4, 0x1.af4560892b22ep-4, -0x1.a7900e8a2a8cbp-6, -0x1.81dc25ff67e7bp-4, + 0x1.1c4bec48bfea3p-5, 0x1.05235edafd55dp-3, -0x1.68f0d9993a312p-5, -0x1.b0762c7f95e8ep-6, + 0x1.e012c3fd994dbp-8, -0x1.cae6340db4ff9p-3, 0x1.d36aebbd69e8dp-5, 0x1.2cf3676fd8540p-5, + -0x1.80bf636c6f775p-8, 0x1.3adf2323e2c9cp-3, 0x1.c93130f640e11p-5, 0x1.03001155442c3p-3, + 0x1.79b574009e3aep-4, -0x1.69f3bce3f8e97p-6, -0x1.c97c2653bd0dbp-3, -0x1.2ca361dcf123ap-4, + -0x1.b18e6b4ca1e14p-6, 0x1.47751844eab7ep-4, 0x1.71b916bca664fp-12, -0x1.09961e82a67f2p-4, + 0x1.f2965edd5d65fp-7, 0x1.a8ea0999dc983p-6, 0x1.bc48005a4b3b2p-7, -0x1.b2b801522e0fap-6, + -0x1.1bd1ad98c408fp-6, 0x1.140e6d4dd67bbp-4, 0x1.de49e67550d20p-7, 0x1.3457bc4af4a1dp-3, + 0x1.1ec8bf3225f22p-3, 0x1.07963fac3bf37p-6, 0x1.5d8c5655d7268p-8, 0x1.2f289fe98ef03p-4, + -0x1.a4c3262e617f7p-4, 0x1.3611484ff88c1p-7, -0x1.1f16cfc76405dp-5, 0x1.cd6710c9bf504p-4, + -0x1.46d879276edc1p-4, -0x1.3d7911c45882cp-5, -0x1.787dd66df4755p-4, 0x1.5b116b5bf16abp-3, + -0x1.23be608c33e2ap-3, 0x1.6f3e7cafd2a45p-4, -0x1.f1eda82167fabp-6, -0x1.6c77a82100fc9p-7, + 0x1.0ede9a64c9487p-3, -0x1.0661097ad43b2p-5, -0x1.295e39a984035p-5, -0x1.30bb650731eb7p-3, + -0x1.ec59f4400709ap-6, 0x1.db6ad30bfbaa6p-5, 0x1.8aea5f446381bp-4, -0x1.17de9dc9ad2a3p-6, + -0x1.7b0b9ce5b7a2ep-6, -0x1.fa18c0792536fp-4, 0x1.1fa5a8cda6bafp-3, -0x1.3ae35ce56859ep-8, + 0x1.3ae35ce56859ep-8, -0x1.1fa5a8cda6bafp-3, 0x1.fa18c0792536fp-4, 0x1.7b0b9ce5b7a2ep-6, + 0x1.17de9dc9ad2a3p-6, -0x1.8aea5f446381bp-4, -0x1.db6ad30bfbaa6p-5, 0x1.ec59f4400709ap-6, + 0x1.30bb650731eb7p-3, 0x1.295e39a984035p-5, 0x1.0661097ad43b2p-5, -0x1.0ede9a64c9487p-3, + 0x1.6c77a82100fc9p-7, 0x1.f1eda82167fabp-6, -0x1.6f3e7cafd2a45p-4, 0x1.23be608c33e2ap-3, + -0x1.5b116b5bf16abp-3, 0x1.787dd66df4755p-4, 0x1.3d7911c45882cp-5, 0x1.46d879276edc1p-4, + -0x1.cd6710c9bf504p-4, 0x1.1f16cfc76405dp-5, -0x1.3611484ff88c1p-7, 0x1.a4c3262e617f7p-4, + -0x1.2f289fe98ef03p-4, -0x1.5d8c5655d7268p-8, -0x1.07963fac3bf37p-6, -0x1.1ec8bf3225f22p-3, + -0x1.3457bc4af4a1dp-3, -0x1.de49e67550d20p-7, -0x1.140e6d4dd67bbp-4, 0x1.1bd1ad98c408fp-6, + 0x1.b2b801522e0fap-6, -0x1.bc48005a4b3b2p-7, -0x1.a8ea0999dc983p-6, -0x1.f2965edd5d65fp-7, + 0x1.09961e82a67f2p-4, -0x1.71b916bca664fp-12, -0x1.47751844eab7ep-4, 0x1.b18e6b4ca1e14p-6, + 0x1.2ca361dcf123ap-4, 0x1.c97c2653bd0dbp-3, 0x1.69f3bce3f8e97p-6, -0x1.79b574009e3aep-4, + -0x1.03001155442c3p-3, -0x1.c93130f640e11p-5, -0x1.3adf2323e2c9cp-3, 0x1.80bf636c6f775p-8, + -0x1.2cf3676fd8540p-5, -0x1.d36aebbd69e8dp-5, 0x1.cae6340db4ff9p-3, -0x1.e012c3fd994dbp-8, + 0x1.b0762c7f95e8ep-6, 0x1.68f0d9993a312p-5, -0x1.05235edafd55dp-3, -0x1.1c4bec48bfea3p-5, + 0x1.81dc25ff67e7bp-4, 0x1.a7900e8a2a8c4p-6, -0x1.af4560892b22ep-4, -0x1.2534ae068f8abp-4, + -0x1.1c1b3e5e048ecp-4, -0x1.65c5269063d4dp-3, -0x1.2f0502a884f26p-6, -0x1.972e61d561cfdp-10, + -0x1.49a44a3497e57p-4, 0x1.87c401a50a0dep-4, 0x1.ba5aa97d88514p-4, 0x1.01cfc619880dbp-4, + 0x1.64c7e19748b49p-5, -0x1.dfeae7f15d53bp-4, -0x1.f7599defd6eb8p-4, -0x1.76dd98acb0297p-6, + -0x1.921cfc8007704p-10, 0x1.fff6205abb69ap-4, 0x1.f97f951724dfdp-4, -0x1.455770c1f0705p-6, + -0x1.4d1e20a955417p-5, -0x1.e426a3030ca46p-4, -0x1.c08c43d00aa66p-4, 0x1.edc19782ee259p-5, + 0x1.3fed943c31c7ep-4, 0x1.8fbccadc25a06p-4, 0x1.532828e3314f8p-4, -0x1.7f8ecd3c7fbd9p-4, + -0x1.b3e4d3ad86391p-4, -0x1.0c9703a5e644cp-4, -0x1.7c3a938f5057cp-5, 0x1.db6527c6bef57p-4, + 0x1.f4e603c9c066bp-4, 0x1.a82a08dcef3afp-6, 0x1.2d865215cf264p-8, -0x1.ffa72dfcb3c97p-4, + -0x1.fb57995aac0ccp-4, 0x1.139f18e2a176ep-6, 0x1.35410e9e777bep-5, 0x1.e817b9db1c98dp-4, + 0x1.c678b33d88661p-4, -0x1.d79770886ef77p-5, -0x1.36058caf46550p-4, -0x1.9777f00d96c11p-4, + -0x1.5c77bcc19a3bbp-4, 0x1.771e725e1390ep-4, 0x1.ad2bc9e072b1ap-4, 0x1.1734d83b1968cp-4, + 0x1.9372a4e902860p-5, -0x1.d69615737874fp-4, -0x1.f22531a349727p-4, -0x1.d934f8baf80fdp-6, + -0x1.f6571e5cc5467p-8, 0x1.ff0954375396cp-4, 0x1.fce15df391665p-4, -0x1.c37858897c517p-7, + -0x1.1d3442a7c6439p-5, -0x1.ebbd87670c446p-4, -0x1.cc1f0bb08518bp-4, 0x1.c124a10fe4916p-5, + 0x1.2bedb0bc83f45p-4, 0x1.9ef43fbf25e73p-4, 0x1.6591934ad1273p-4, -0x1.6e744566a3086p-4, + -0x1.a630917a5f959p-4, -0x1.21a79692702e1p-4, -0x1.aa6c7e3721da1p-5, 0x1.d17e794962101p-4, + 0x1.ef178a96bd927p-4, 0x1.04fb801737d2ap-5, 0x1.5f6d08e11efc7p-7, -0x1.fe1cb144fec53p-4, + -0x1.fe1cb144fec53p-4, 0x1.5f6d08e11efc7p-7, 0x1.04fb801737d2ap-5, 0x1.ef178a96bd927p-4, + 0x1.d17e794962101p-4, -0x1.aa6c7e3721da1p-5, -0x1.21a79692702e1p-4, -0x1.a630917a5f959p-4, + -0x1.6e744566a3086p-4, 0x1.6591934ad1273p-4, 0x1.9ef43fbf25e73p-4, 0x1.2bedb0bc83f45p-4, + 0x1.c124a10fe4916p-5, -0x1.cc1f0bb08518bp-4, -0x1.ebbd87670c446p-4, -0x1.1d3442a7c6439p-5, + -0x1.c37858897c517p-7, 0x1.fce15df391665p-4, 0x1.ff0954375396cp-4, -0x1.f6571e5cc5467p-8, + -0x1.d934f8baf80fdp-6, -0x1.f22531a349727p-4, -0x1.d69615737874fp-4, 0x1.9372a4e902860p-5, + 0x1.1734d83b1968cp-4, 0x1.ad2bc9e072b1ap-4, 0x1.771e725e1390ep-4, -0x1.5c77bcc19a3bbp-4, + -0x1.9777f00d96c11p-4, -0x1.36058caf46550p-4, -0x1.d79770886ef77p-5, 0x1.c678b33d88661p-4, + 0x1.e817b9db1c98dp-4, 0x1.35410e9e777bep-5, 0x1.139f18e2a176ep-6, -0x1.fb57995aac0ccp-4, + -0x1.ffa72dfcb3c97p-4, 0x1.2d865215cf264p-8, 0x1.a82a08dcef3afp-6, 0x1.f4e603c9c066bp-4, + 0x1.db6527c6bef57p-4, -0x1.7c3a938f5057cp-5, -0x1.0c9703a5e644cp-4, -0x1.b3e4d3ad86391p-4, + -0x1.7f8ecd3c7fbd9p-4, 0x1.532828e3314f8p-4, 0x1.8fbccadc25a06p-4, 0x1.3fed943c31c7ep-4, + 0x1.edc19782ee259p-5, -0x1.c08c43d00aa66p-4, -0x1.e426a3030ca46p-4, -0x1.4d1e20a955417p-5, + -0x1.455770c1f0705p-6, 0x1.f97f951724dfdp-4, 0x1.fff6205abb69ap-4, -0x1.921cfc8007704p-10, + -0x1.76dd98acb0297p-6, -0x1.f7599defd6eb8p-4, -0x1.dfeae7f15d53bp-4, 0x1.64c7e19748b49p-5, + 0x1.01cfc619880dbp-4, 0x1.ba5aa97d88514p-4, 0x1.87c401a50a0dep-4, -0x1.49a44a3497e4dp-4, + -0x1.87c401aba14b7p-4, -0x1.49a44a3c83ffep-4, 0x1.01cfc6559ddbep-4, -0x1.ba5aa9e7f6874p-4, + 0x1.dfeae8665af80p-4, 0x1.64c7e03644f8ep-5, -0x1.76dd998344406p-6, 0x1.f7599c15452c7p-4, + -0x1.fff62121ad483p-4, -0x1.921cfaeb11b7fp-10, -0x1.45576f71445cbp-6, -0x1.f97f94536f6b5p-4, + 0x1.e426a1724aa92p-4, -0x1.4d1e208744470p-5, 0x1.edc198664e788p-5, 0x1.c08c4392a5d24p-4, + -0x1.8fbcca6fb9a65p-4, 0x1.3fed94b1f96c4p-4, -0x1.7f8ecd3dbc104p-4, -0x1.53282897a6679p-4, + 0x1.0c9703cb8cdb6p-4, -0x1.b3e4d1f210921p-4, 0x1.db65272136c3bp-4, 0x1.7c3a928f48f38p-5, + -0x1.a82a07972cfdep-6, 0x1.f4e6024b46959p-4, -0x1.ffa72dc048c96p-4, -0x1.2d865241ae826p-8, + -0x1.139f18478f007p-6, -0x1.fb5797ebea840p-4, 0x1.e817b86e81402p-4, -0x1.35410db226687p-5, + 0x1.d7976faea9036p-5, 0x1.c678b47e0b69ap-4, -0x1.9777f0dbbb697p-4, 0x1.36058d038952fp-4, + -0x1.771e720c17026p-4, -0x1.5c77bcd24b2e1p-4, 0x1.1734d90337e18p-4, -0x1.ad2bcbcf6239ap-4, + 0x1.d69615bf8f08fp-4, 0x1.9372a4119fb8dp-5, -0x1.d934f9e249a83p-6, 0x1.f2253182fa22bp-4, + -0x1.ff0955c9092fdp-4, -0x1.f6571e5bf9ccap-8, -0x1.c3785795e6e44p-7, -0x1.fce15fedbd6a1p-4, + 0x1.ebbd874a6563bp-4, -0x1.1d3442aac01ecp-5, 0x1.c124a1b877a63p-5, 0x1.cc1f0cf833043p-4, + -0x1.9ef4404d66ed9p-4, 0x1.2bedb09f6f57ap-4, -0x1.6e7445e23e17fp-4, -0x1.6591922401ec5p-4, + 0x1.21a7964a04eb7p-4, -0x1.a63090f6fcac2p-4, 0x1.d17e7a589bb6fp-4, 0x1.aa6c7f82d376fp-5, + -0x1.04fb7f920b1a8p-5, 0x1.ef178bc09d0acp-4, -0x1.fe1cb0fccf580p-4, -0x1.5f6d091dc0e8bp-7, + -0x1.5f6d091dc0e8bp-7, -0x1.fe1cb0fccf580p-4, 0x1.ef178bc09d0acp-4, -0x1.04fb7f920b1a8p-5, + 0x1.aa6c7f82d376fp-5, 0x1.d17e7a589bb6fp-4, -0x1.a63090f6fcac2p-4, 0x1.21a7964a04eb7p-4, + -0x1.6591922401ec5p-4, -0x1.6e7445e23e17fp-4, 0x1.2bedb09f6f57ap-4, -0x1.9ef4404d66ed9p-4, + 0x1.cc1f0cf833043p-4, 0x1.c124a1b877a63p-5, -0x1.1d3442aac01ecp-5, 0x1.ebbd874a6563bp-4, + -0x1.fce15fedbd6a1p-4, -0x1.c3785795e6e44p-7, -0x1.f6571e5bf9ccap-8, -0x1.ff0955c9092fdp-4, + 0x1.f2253182fa22bp-4, -0x1.d934f9e249a83p-6, 0x1.9372a4119fb8dp-5, 0x1.d69615bf8f08fp-4, + -0x1.ad2bcbcf6239ap-4, 0x1.1734d90337e18p-4, -0x1.5c77bcd24b2e1p-4, -0x1.771e720c17026p-4, + 0x1.36058d038952fp-4, -0x1.9777f0dbbb697p-4, 0x1.c678b47e0b69ap-4, 0x1.d7976faea9036p-5, + -0x1.35410db226687p-5, 0x1.e817b86e81402p-4, -0x1.fb5797ebea840p-4, -0x1.139f18478f007p-6, + -0x1.2d865241ae826p-8, -0x1.ffa72dc048c96p-4, 0x1.f4e6024b46959p-4, -0x1.a82a07972cfdep-6, + 0x1.7c3a928f48f38p-5, 0x1.db65272136c3bp-4, -0x1.b3e4d1f210921p-4, 0x1.0c9703cb8cdb6p-4, + -0x1.53282897a6679p-4, -0x1.7f8ecd3dbc104p-4, 0x1.3fed94b1f96c4p-4, -0x1.8fbcca6fb9a65p-4, + 0x1.c08c4392a5d24p-4, 0x1.edc198664e788p-5, -0x1.4d1e208744470p-5, 0x1.e426a1724aa92p-4, + -0x1.f97f94536f6b5p-4, -0x1.45576f71445cbp-6, -0x1.921cfaeb11b7fp-10, -0x1.fff62121ad483p-4, + 0x1.f7599c15452c7p-4, -0x1.76dd998344406p-6, 0x1.64c7e03644f8ep-5, 0x1.dfeae8665af80p-4, + -0x1.ba5aa9e7f6874p-4, 0x1.01cfc6559ddbep-4, -0x1.49a44a3c83ff7p-4, -0x1.87c401aba14b6p-4, + -0x1.ebea67db7f6dcp-4, -0x1.2dd0a47dab56dp-5, 0x1.7ff4113955cacp-6, 0x1.b5d560bc35482p-5, + 0x1.0798d641eb987p-3, 0x1.5ac502698c744p-5, -0x1.0905f7ef6b391p-5, 0x1.0e6ebc1ab0b54p-3, + -0x1.921f7319a0101p-5, 0x1.412004be9ef98p-11, -0x1.f6eb19ef3a547p-6, -0x1.2d8bb3d1fd64ep-3, + 0x1.3fbec7ff2c01ap-3, -0x1.7d7f1c2c7241cp-5, 0x1.8aa2ecddc24bbp-7, -0x1.10aacbe1e87c4p-3, + -0x1.49a86b1ff6b3ap-3, 0x1.932a616ba1f2ep-6, -0x1.8c950ca6d9a2dp-3, 0x1.e6bc5142188d2p-5, + 0x1.0e6c6c814a304p-5, -0x1.924b2e0a5cba9p-4, -0x1.22df08020c457p-3, 0x1.1777d164ced0dp-6, + 0x1.d91d3d3755224p-7, -0x1.b4a0172f6d534p-5, -0x1.76d3945b25793p-5, 0x1.f2e86d5146127p-6, + -0x1.1c49cadcd8631p-5, 0x1.c82503fff680ap-5, -0x1.9edc3c07539aep-6, -0x1.272fd6bc400bap-9, + 0x1.cd8e466992996p-6, -0x1.4f1e394b0b064p-4, -0x1.839b30220be9bp-4, -0x1.219a232209679p-3, + -0x1.eee15602f0e28p-5, 0x1.a3480c21fe0a9p-5, -0x1.7e1a037e55d7ap-4, 0x1.6b2581eb539f2p-3, + 0x1.27b11d191e956p-3, 0x1.a7f8871b27cf2p-5, -0x1.946ea1de1a555p-8, -0x1.da243ad0129e2p-3, + 0x1.d4a985a332bc4p-4, -0x1.cf5cf836d6b9cp-8, 0x1.9e393cd689fc8p-8, 0x1.5d15eda10bea3p-4, + 0x1.5fff2d5103c10p-4, 0x1.2dae69bb08498p-5, -0x1.c7ed4f14bd3f6p-4, -0x1.c814ffe421d98p-4, + 0x1.3ffcb437ea143p-4, -0x1.81469c82302c5p-4, -0x1.c0675f62dca6dp-5, -0x1.cd9c6044279efp-6, + -0x1.0530c6093aad9p-5, 0x1.9adfb61cddc7bp-5, 0x1.b1a347fbf379fp-4, -0x1.3cbbf1356837ap-4, + -0x1.299de0d18862ep-4, -0x1.1a0b4c77289b1p-4, 0x1.0f2df1ef19cc3p-5, -0x1.cd6c5a4b4d590p-7, + -0x1.cd6c5a4b4d590p-7, 0x1.0f2df1ef19cc3p-5, -0x1.1a0b4c77289b1p-4, -0x1.299de0d18862ep-4, + -0x1.3cbbf1356837ap-4, 0x1.b1a347fbf379fp-4, 0x1.9adfb61cddc7bp-5, -0x1.0530c6093aad9p-5, + -0x1.cd9c6044279efp-6, -0x1.c0675f62dca6dp-5, -0x1.81469c82302c5p-4, 0x1.3ffcb437ea143p-4, + -0x1.c814ffe421d98p-4, -0x1.c7ed4f14bd3f6p-4, 0x1.2dae69bb08498p-5, 0x1.5fff2d5103c10p-4, + 0x1.5d15eda10bea3p-4, 0x1.9e393cd689fc8p-8, -0x1.cf5cf836d6b9cp-8, 0x1.d4a985a332bc4p-4, + -0x1.da243ad0129e2p-3, -0x1.946ea1de1a555p-8, 0x1.a7f8871b27cf2p-5, 0x1.27b11d191e956p-3, + 0x1.6b2581eb539f2p-3, -0x1.7e1a037e55d7ap-4, 0x1.a3480c21fe0a9p-5, -0x1.eee15602f0e28p-5, + -0x1.219a232209679p-3, -0x1.839b30220be9bp-4, -0x1.4f1e394b0b064p-4, 0x1.cd8e466992996p-6, + -0x1.272fd6bc400bap-9, -0x1.9edc3c07539aep-6, 0x1.c82503fff680ap-5, -0x1.1c49cadcd8631p-5, + 0x1.f2e86d5146127p-6, -0x1.76d3945b25793p-5, -0x1.b4a0172f6d534p-5, 0x1.d91d3d3755224p-7, + 0x1.1777d164ced0dp-6, -0x1.22df08020c457p-3, -0x1.924b2e0a5cba9p-4, 0x1.0e6c6c814a304p-5, + 0x1.e6bc5142188d2p-5, -0x1.8c950ca6d9a2dp-3, 0x1.932a616ba1f2ep-6, -0x1.49a86b1ff6b3ap-3, + -0x1.10aacbe1e87c4p-3, 0x1.8aa2ecddc24bbp-7, -0x1.7d7f1c2c7241cp-5, 0x1.3fbec7ff2c01ap-3, + -0x1.2d8bb3d1fd64ep-3, -0x1.f6eb19ef3a547p-6, 0x1.412004be9ef98p-11, -0x1.921f7319a0101p-5, + 0x1.0e6ebc1ab0b55p-3, -0x1.0905f7ef6b390p-5, 0x1.5ac502698c744p-5, 0x1.0798d641eb987p-3, + 0x1.b5d560bc35488p-5, 0x1.7ff4113955cb4p-6, -0x1.2dd0a34988a75p-5, -0x1.ebea67a8b758ep-4, + 0x1.81558f27398dbp-5, -0x1.edefee1e3219bp-4, 0x1.22455164c98acp-3, 0x1.ea22d194b5927p-8, + 0x1.001b1fcd9c71bp-4, 0x1.0542718b8a0adp-4, -0x1.ddc56f52b186ep-3, -0x1.70078f45b8ea4p-6, + -0x1.03d4c001aa21cp-9, -0x1.8916e7eb60010p-8, -0x1.fa5f937a4aba9p-6, 0x1.da77bb14cb215p-10, + -0x1.4d91aeac6fe86p-4, -0x1.f50621cdd617bp-4, -0x1.205fcf6fd9294p-4, -0x1.6d0f22140a10ep-6, + -0x1.9b3cb2e44dae0p-5, 0x1.9998b47a74cd6p-4, 0x1.62110ff9ccf23p-6, 0x1.8212e9eb92c7ap-5, + -0x1.42ef9858962c1p-3, 0x1.80e48e7733920p-6, -0x1.3eff171b5ca5dp-5, 0x1.331df375dbfd3p-4, + 0x1.51c8743f37c09p-5, -0x1.6f965d7634d66p-8, 0x1.03490d0f62052p-5, 0x1.a89a9d75a1adbp-3, + -0x1.17f61fa80d37cp-3, -0x1.24bd3e8b2fd29p-8, 0x1.a8c4d902f30f7p-5, 0x1.99d169bb21333p-3, + -0x1.bb58daccb6770p-3, 0x1.4263ac8afa7b5p-10, -0x1.0ad7f44ebed1bp-8, 0x1.09e15cfb2e46dp-5, + 0x1.2d00e1b48d479p-5, 0x1.0307c6168a9bfp-5, -0x1.450d003eff422p-9, -0x1.00d492f496491p-5, + -0x1.5136143234fe0p-6, 0x1.710bbd55c27fcp-4, -0x1.8ef6cce2c6ee3p-6, 0x1.88bffacfe6233p-5, + -0x1.3c2a76f2f4758p-5, -0x1.714e2e5ff44a2p-5, -0x1.de80c19b572b5p-5, -0x1.e88f6e21c6ce0p-5, + -0x1.157719acee79ep-8, 0x1.8d6502264efe2p-3, 0x1.557275eb06df1p-3, 0x1.a1b53b1bc9fe7p-6, + -0x1.1208598280f61p-5, -0x1.4b4b937f183c2p-3, 0x1.05cad8839cb51p-3, 0x1.398aa7ee1e2eep-6, + -0x1.874ec26ff3313p-4, -0x1.6e53871bc8761p-5, 0x1.9768daf7aa8f3p-5, -0x1.e283a45bc7ca3p-4, + -0x1.fa4ceb1f9ee4ep-8, 0x1.062303f2c5de2p-5, -0x1.014b6b64a1fcep-6, -0x1.2510947cd6f0cp-4, + -0x1.2510947cd6f0cp-4, -0x1.014b6b64a1fcep-6, 0x1.062303f2c5de2p-5, -0x1.fa4ceb1f9ee4ep-8, + -0x1.e283a45bc7ca3p-4, 0x1.9768daf7aa8f3p-5, -0x1.6e53871bc8761p-5, -0x1.874ec26ff3313p-4, + 0x1.398aa7ee1e2eep-6, 0x1.05cad8839cb51p-3, -0x1.4b4b937f183c2p-3, -0x1.1208598280f61p-5, + 0x1.a1b53b1bc9fe7p-6, 0x1.557275eb06df1p-3, 0x1.8d6502264efe2p-3, -0x1.157719acee79ep-8, + -0x1.e88f6e21c6ce0p-5, -0x1.de80c19b572b5p-5, -0x1.714e2e5ff44a2p-5, -0x1.3c2a76f2f4758p-5, + 0x1.88bffacfe6233p-5, -0x1.8ef6cce2c6ee3p-6, 0x1.710bbd55c27fcp-4, -0x1.5136143234fe0p-6, + -0x1.00d492f496491p-5, -0x1.450d003eff422p-9, 0x1.0307c6168a9bfp-5, 0x1.2d00e1b48d479p-5, + 0x1.09e15cfb2e46dp-5, -0x1.0ad7f44ebed1bp-8, 0x1.4263ac8afa7b5p-10, -0x1.bb58daccb6770p-3, + 0x1.99d169bb21333p-3, 0x1.a8c4d902f30f7p-5, -0x1.24bd3e8b2fd29p-8, -0x1.17f61fa80d37cp-3, + 0x1.a89a9d75a1adbp-3, 0x1.03490d0f62052p-5, -0x1.6f965d7634d66p-8, 0x1.51c8743f37c09p-5, + 0x1.331df375dbfd3p-4, -0x1.3eff171b5ca5dp-5, 0x1.80e48e7733920p-6, -0x1.42ef9858962c1p-3, + 0x1.8212e9eb92c7ap-5, 0x1.62110ff9ccf23p-6, 0x1.9998b47a74cd6p-4, -0x1.9b3cb2e44dae0p-5, + -0x1.6d0f22140a10ep-6, -0x1.205fcf6fd9294p-4, -0x1.f50621cdd617bp-4, -0x1.4d91aeac6fe86p-4, + 0x1.da77bb14cb215p-10, -0x1.fa5f937a4aba9p-6, -0x1.8916e7eb60010p-8, -0x1.03d4c001aa21cp-9, + -0x1.70078f45b8ea7p-6, -0x1.ddc56f52b186dp-3, 0x1.0542718b8a0acp-4, 0x1.001b1fcd9c71dp-4, + 0x1.ea22d194b5915p-8, 0x1.22455164c98adp-3, -0x1.edefee6fb4bc3p-4, 0x1.815591082e645p-5, + -0x1.3fed971a9ef28p-4, 0x1.8fbcca438a6f1p-4, 0x1.cc1f0d99da502p-4, 0x1.c1249ad68c395p-5, + 0x1.d934fe92ab941p-6, -0x1.f2252e551f838p-4, -0x1.fff621982be9ep-4, -0x1.921ce4dbfbf53p-10, + 0x1.a829fb13f119ep-6, 0x1.f4e60467bfaf4p-4, 0x1.d17e75cccdd1dp-4, -0x1.aa6c82eafd011p-5, + -0x1.360589fa6546cp-4, -0x1.9777eff6b1d41p-4, -0x1.49a44aa751d42p-4, 0x1.87c400ab7ed29p-4, + 0x1.c678b54d57b2bp-4, 0x1.d79776ea8ecaap-5, 0x1.04fb7e27786cdp-5, -0x1.ef178a4ccaf6ap-4, + -0x1.ffa72e217646fp-4, -0x1.2d8667d181c67p-8, 0x1.76dd9fb4387c1p-6, 0x1.f759998a439a9p-4, + 0x1.d69615fc9b84dp-4, -0x1.9372a40b7ff43p-5, -0x1.2bedb2fae3b42p-4, -0x1.9ef43c729aab8p-4, + -0x1.532829927f08ap-4, 0x1.7f8ecee5831cbp-4, 0x1.c08c428e04b4fp-4, 0x1.edc19515a1976p-5, + 0x1.1d3445e070147p-5, -0x1.ebbd8c4e50c1bp-4, -0x1.ff0954e8e8501p-4, -0x1.f656e92644d22p-8, + 0x1.45576690ae0b4p-6, 0x1.f97f94c3ad28bp-4, 0x1.db65264be83a0p-4, -0x1.7c3a90c5b6ad2p-5, + -0x1.21a79aae82d99p-4, -0x1.a63091b55e173p-4, -0x1.5c77bb5d902c2p-4, 0x1.771e755c8ef40p-4, + 0x1.ba5aa587ae7c3p-4, 0x1.01cfc9a9d9d27p-4, 0x1.35410a76e81c4p-5, -0x1.e817ba789c24fp-4, + -0x1.fe1cb0eb77f5bp-4, -0x1.5f6d05a9fd743p-7, 0x1.139f0b3135211p-6, 0x1.fb5796590a3edp-4, + 0x1.dfeae9dd710fdp-4, -0x1.64c7e1287cbb5p-5, -0x1.1734d7b01abefp-4, -0x1.ad2bcaddf0c4ap-4, + -0x1.65918fba16c3cp-4, 0x1.6e74455f0617ep-4, 0x1.b3e4d4a641736p-4, 0x1.0c97041ac1c70p-4, + 0x1.4d1e27dd24ddap-5, -0x1.e426a3d51de8cp-4, -0x1.fce16051ac315p-4, -0x1.c3785e0df4130p-7, + 0x1.c3785e0df4130p-7, 0x1.fce16051ac315p-4, 0x1.e426a3d51de8cp-4, -0x1.4d1e27dd24ddap-5, + -0x1.0c97041ac1c70p-4, -0x1.b3e4d4a641736p-4, -0x1.6e74455f0617ep-4, 0x1.65918fba16c3cp-4, + 0x1.ad2bcaddf0c4ap-4, 0x1.1734d7b01abefp-4, 0x1.64c7e1287cbb5p-5, -0x1.dfeae9dd710fdp-4, + -0x1.fb5796590a3edp-4, -0x1.139f0b3135211p-6, 0x1.5f6d05a9fd743p-7, 0x1.fe1cb0eb77f5bp-4, + 0x1.e817ba789c24fp-4, -0x1.35410a76e81c4p-5, -0x1.01cfc9a9d9d27p-4, -0x1.ba5aa587ae7c3p-4, + -0x1.771e755c8ef40p-4, 0x1.5c77bb5d902c2p-4, 0x1.a63091b55e173p-4, 0x1.21a79aae82d99p-4, + 0x1.7c3a90c5b6ad2p-5, -0x1.db65264be83a0p-4, -0x1.f97f94c3ad28bp-4, -0x1.45576690ae0b4p-6, + 0x1.f656e92644d22p-8, 0x1.ff0954e8e8501p-4, 0x1.ebbd8c4e50c1bp-4, -0x1.1d3445e070147p-5, + -0x1.edc19515a1976p-5, -0x1.c08c428e04b4fp-4, -0x1.7f8ecee5831cbp-4, 0x1.532829927f08ap-4, + 0x1.9ef43c729aab8p-4, 0x1.2bedb2fae3b42p-4, 0x1.9372a40b7ff43p-5, -0x1.d69615fc9b84dp-4, + -0x1.f759998a439a9p-4, -0x1.76dd9fb4387c1p-6, 0x1.2d8667d181c67p-8, 0x1.ffa72e217646fp-4, + 0x1.ef178a4ccaf6ap-4, -0x1.04fb7e27786cdp-5, -0x1.d79776ea8ecaap-5, -0x1.c678b54d57b2bp-4, + -0x1.87c400ab7ed29p-4, 0x1.49a44aa751d42p-4, 0x1.9777eff6b1d41p-4, 0x1.360589fa6546cp-4, + 0x1.aa6c82eafd011p-5, -0x1.d17e75cccdd1dp-4, -0x1.f4e60467bfaf4p-4, -0x1.a829fb13f119ep-6, + 0x1.921ce4dbfbf53p-10, 0x1.fff621982be9ep-4, 0x1.f2252e551f838p-4, -0x1.d934fe92ab941p-6, + -0x1.c1249ad68c395p-5, -0x1.cc1f0d99da502p-4, -0x1.8fbcca438a6f1p-4, 0x1.3fed971a9ef1bp-4, + -0x1.8fbccbf135e4dp-4, -0x1.3fed97a640752p-4, 0x1.c12498c6c92c4p-5, -0x1.cc1f0ef26d1abp-4, + 0x1.f2252e48ba435p-4, 0x1.d93500a97bf03p-6, -0x1.921cdf4020759p-10, 0x1.fff62208ab2f0p-4, + -0x1.f4e604926c9a8p-4, 0x1.a829fb1445bbdp-6, -0x1.aa6c84532e147p-5, -0x1.d17e765802989p-4, + 0x1.9777eebefe1e8p-4, -0x1.360589bf971e2p-4, 0x1.87c4005e26c00p-4, 0x1.49a44a01a91b4p-4, + -0x1.d7977775d42ecp-5, 0x1.c678b63cb47b7p-4, -0x1.ef1789963c259p-4, -0x1.04fb7e3453a46p-5, + 0x1.2d86693272a58p-8, -0x1.ffa72d1049778p-4, 0x1.f759992380f24p-4, -0x1.76dd9fa0f5bbdp-6, + 0x1.9372a2cbc8824p-5, 0x1.d69615c94e366p-4, -0x1.9ef43c5090ffbp-4, 0x1.2bedb36853aa2p-4, + -0x1.7f8ecf0dd3d74p-4, -0x1.5328298756a3bp-4, 0x1.edc1932895567p-5, -0x1.c08c438e2f068p-4, + 0x1.ebbd8d84c388bp-4, 0x1.1d34458656957p-5, -0x1.f656e7e8ebe2cp-8, 0x1.ff0955407c5dfp-4, + -0x1.f97f92c3b9445p-4, 0x1.45576677fea36p-6, -0x1.7c3a923a66fe6p-5, -0x1.db65254335209p-4, + 0x1.a63090d162aecp-4, -0x1.21a79ad2ec053p-4, 0x1.771e750f63df0p-4, 0x1.5c77bb46dd9f6p-4, + -0x1.01cfc8f8fae2fp-4, 0x1.ba5aa5264dd94p-4, -0x1.e817b97bf8966p-4, -0x1.3541092c419edp-5, + 0x1.5f6d04c9ed208p-7, -0x1.fe1cb262dff0ap-4, 0x1.fb57967acc8c5p-4, -0x1.139f0b41da27ep-6, + 0x1.64c7e22981444p-5, 0x1.dfeae9276318fp-4, -0x1.ad2bcc4633937p-4, 0x1.1734d7c64cd03p-4, + -0x1.6e7445feda559p-4, -0x1.65918f5c7d163p-4, 0x1.0c9703dcab1c3p-4, -0x1.b3e4d3b4dfa83p-4, + 0x1.e426a58087c29p-4, 0x1.4d1e27d8486f4p-5, -0x1.c3785d141a2ffp-7, 0x1.fce15fff2f893p-4, + -0x1.fce15fff2f893p-4, 0x1.c3785d141a2ffp-7, -0x1.4d1e27d8486f4p-5, -0x1.e426a58087c29p-4, + 0x1.b3e4d3b4dfa83p-4, -0x1.0c9703dcab1c3p-4, 0x1.65918f5c7d163p-4, 0x1.6e7445feda559p-4, + -0x1.1734d7c64cd03p-4, 0x1.ad2bcc4633937p-4, -0x1.dfeae9276318fp-4, -0x1.64c7e22981444p-5, + 0x1.139f0b41da27ep-6, -0x1.fb57967acc8c5p-4, 0x1.fe1cb262dff0ap-4, -0x1.5f6d04c9ed208p-7, + 0x1.3541092c419edp-5, 0x1.e817b97bf8966p-4, -0x1.ba5aa5264dd94p-4, 0x1.01cfc8f8fae2fp-4, + -0x1.5c77bb46dd9f6p-4, -0x1.771e750f63df0p-4, 0x1.21a79ad2ec053p-4, -0x1.a63090d162aecp-4, + 0x1.db65254335209p-4, 0x1.7c3a923a66fe6p-5, -0x1.45576677fea36p-6, 0x1.f97f92c3b9445p-4, + -0x1.ff0955407c5dfp-4, 0x1.f656e7e8ebe2cp-8, -0x1.1d34458656957p-5, -0x1.ebbd8d84c388bp-4, + 0x1.c08c438e2f068p-4, -0x1.edc1932895567p-5, 0x1.5328298756a3bp-4, 0x1.7f8ecf0dd3d74p-4, + -0x1.2bedb36853aa2p-4, 0x1.9ef43c5090ffbp-4, -0x1.d69615c94e366p-4, -0x1.9372a2cbc8824p-5, + 0x1.76dd9fa0f5bbdp-6, -0x1.f759992380f24p-4, 0x1.ffa72d1049778p-4, -0x1.2d86693272a58p-8, + 0x1.04fb7e3453a46p-5, 0x1.ef1789963c259p-4, -0x1.c678b63cb47b7p-4, 0x1.d7977775d42ecp-5, + -0x1.49a44a01a91b4p-4, -0x1.87c4005e26c00p-4, 0x1.360589bf971e2p-4, -0x1.9777eebefe1e8p-4, + 0x1.d17e765802989p-4, 0x1.aa6c84532e147p-5, -0x1.a829fb1445bbdp-6, 0x1.f4e604926c9a8p-4, + -0x1.fff62208ab2f0p-4, 0x1.921cdf4020759p-10, -0x1.d93500a97bf03p-6, -0x1.f2252e48ba435p-4, + 0x1.cc1f0ef26d1abp-4, -0x1.c12498c6c92c4p-5, 0x1.3fed97a640759p-4, 0x1.8fbccbf135e4dp-4, + 0x1.e9f66f47fbfcdp-3, -0x1.56ef0f96a77dep-6, 0x1.18a7d07ffd570p-4, 0x1.48e1152191467p-3, + -0x1.8daea9c0ce7aep-4, -0x1.1c51e20f0893fp-5, 0x1.99cc0fa97307ap-8, 0x1.df3478590549dp-6, + -0x1.46124ec7d5f9bp-3, -0x1.0160d7ed1d9adp-7, -0x1.5db986de4744ap-5, -0x1.6e17b857c4adap-4, + 0x1.4a1d203c13176p-3, -0x1.5be80f2bb96bfp-4, 0x1.e1078b8797d1fp-6, -0x1.6fa8227af2916p-11, + 0x1.9259959c1fda0p-5, -0x1.aa81dd0705e33p-3, 0x1.478245d248a1ap-7, 0x1.164dacd0ae946p-6, + 0x1.3e1a07d6ea780p-8, -0x1.cd671d3064e4ap-5, 0x1.02b0530427721p-3, 0x1.6ca451db909afp-6, + 0x1.1977eeba4a87bp-4, -0x1.b229b1c9fceafp-5, -0x1.1a94c160d5cd5p-3, 0x1.bbfdde918eed8p-8, + 0x1.57feca712f732p-4, 0x1.406c8928dfbb6p-4, 0x1.3c672d05976e5p-4, 0x1.93b6a7f5d28eep-5, + 0x1.09275c43a2f1cp-11, 0x1.7b5280c3b9883p-9, 0x1.de90db7a2ac66p-8, 0x1.e7c3f0af561f9p-5, + -0x1.cafc5cc44419bp-4, 0x1.8d683838a3477p-6, 0x1.ce18d0fb4d91ap-10, 0x1.1a9f2950493c7p-3, + -0x1.3cb0d14904c5cp-5, 0x1.0ddf855f3b1d7p-5, -0x1.382129a1e8696p-10, -0x1.9c49c4e8c0740p-5, + -0x1.21580a50bbc1ap-4, -0x1.737530821be17p-4, 0x1.234fca17dccdep-5, -0x1.10b9dfd26291fp-4, + 0x1.7f479eb750b3bp-6, 0x1.e63b7a7ae4a5cp-4, -0x1.dca5c21c83982p-4, 0x1.2fb801402bc65p-7, + 0x1.f885fd8e001fbp-9, -0x1.ff2328262f21dp-7, 0x1.65bb951928fffp-3, -0x1.45cde2f24aeefp-4, + -0x1.7fc7ea3c0b764p-3, -0x1.6489e8e453b92p-5, 0x1.809372e556ae3p-5, -0x1.406d3a8731db6p-4, + 0x1.cee8c40e85591p-5, -0x1.0bcb294376b6ep-7, 0x1.536d7f3fc6b6dp-6, 0x1.a7d11b8ce9ac2p-3, + -0x1.a7d11b8ce9ac2p-3, -0x1.536d7f3fc6b6dp-6, 0x1.0bcb294376b6ep-7, -0x1.cee8c40e85591p-5, + 0x1.406d3a8731db6p-4, -0x1.809372e556ae3p-5, 0x1.6489e8e453b92p-5, 0x1.7fc7ea3c0b764p-3, + 0x1.45cde2f24aeefp-4, -0x1.65bb951928fffp-3, 0x1.ff2328262f21dp-7, -0x1.f885fd8e001fbp-9, + -0x1.2fb801402bc65p-7, 0x1.dca5c21c83982p-4, -0x1.e63b7a7ae4a5cp-4, -0x1.7f479eb750b3bp-6, + 0x1.10b9dfd26291fp-4, -0x1.234fca17dccdep-5, 0x1.737530821be17p-4, 0x1.21580a50bbc1ap-4, + 0x1.9c49c4e8c0740p-5, 0x1.382129a1e8696p-10, -0x1.0ddf855f3b1d7p-5, 0x1.3cb0d14904c5cp-5, + -0x1.1a9f2950493c7p-3, -0x1.ce18d0fb4d91ap-10, -0x1.8d683838a3477p-6, 0x1.cafc5cc44419bp-4, + -0x1.e7c3f0af561f9p-5, -0x1.de90db7a2ac66p-8, -0x1.7b5280c3b9883p-9, -0x1.09275c43a2f1cp-11, + -0x1.93b6a7f5d28eep-5, -0x1.3c672d05976e5p-4, -0x1.406c8928dfbb6p-4, -0x1.57feca712f732p-4, + -0x1.bbfdde918eed8p-8, 0x1.1a94c160d5cd5p-3, 0x1.b229b1c9fceafp-5, -0x1.1977eeba4a87bp-4, + -0x1.6ca451db909afp-6, -0x1.02b0530427721p-3, 0x1.cd671d3064e4ap-5, -0x1.3e1a07d6ea780p-8, + -0x1.164dacd0ae946p-6, -0x1.478245d248a1ap-7, 0x1.aa81dd0705e33p-3, -0x1.9259959c1fda0p-5, + 0x1.6fa8227af2916p-11, -0x1.e1078b8797d1fp-6, 0x1.5be80f2bb96bfp-4, -0x1.4a1d203c13176p-3, + 0x1.6e17b857c4adap-4, 0x1.5db986de4744ap-5, 0x1.0160d7ed1d9adp-7, 0x1.46124ec7d5f9bp-3, + -0x1.df347859054a1p-6, -0x1.99cc0fa97307ap-8, 0x1.1c51e20f0893ap-5, 0x1.8daea9c0ce7aep-4, + -0x1.48e115219145cp-3, -0x1.18a7d07ffd573p-4, 0x1.56ef02edd2915p-6, -0x1.e9f66f4fe5b76p-3, + 0x1.88edd7e856426p-5, -0x1.3bbaf09828834p-3, -0x1.0de48f9efa3dcp-4, -0x1.788577bb8c710p-5, + -0x1.800ff9eb9a03ep-6, -0x1.79e03a1e07449p-6, -0x1.73058d3fdc082p-5, -0x1.1bf1873732989p-6, + 0x1.04f6b90f68794p-4, -0x1.1182e13bb4a41p-10, -0x1.22d770a91673bp-3, 0x1.73e7f62cd4100p-4, + 0x1.51fb751d63ea1p-4, -0x1.2b5e0e892f5bep-4, -0x1.186ffac98f6c7p-4, -0x1.7175b027cb624p-4, + -0x1.5fdc31d907327p-6, 0x1.7ec564201d135p-7, 0x1.7d0eaa07b7550p-5, -0x1.806e2c4774376p-5, + -0x1.08391bb40c47ap-3, 0x1.590321410a741p-6, -0x1.9ba2d3b5bb089p-8, 0x1.052347f0047c3p-4, + 0x1.5b11172b50e1ap-10, 0x1.df87d36cffe94p-10, -0x1.da451d88013ccp-9, 0x1.dc42cb65f6d5ap-4, + -0x1.c3306fbe7b3c0p-4, 0x1.31b40a0dc2f7ep-4, -0x1.669df6f162362p-5, 0x1.dd662bb991814p-5, + -0x1.84bc56fbfb526p-11, 0x1.8cb26e4c8e4a9p-4, -0x1.05182ead91b13p-5, -0x1.d4c3651bd48ffp-6, + 0x1.6dfabb7c814f1p-5, 0x1.fa56e4d956157p-3, 0x1.f53e7326d574bp-4, 0x1.38e3432ce277cp-4, + 0x1.07406ce65ff33p-7, -0x1.5d59479cf868cp-5, -0x1.6a45e8769db56p-4, 0x1.43c8a9e50fb93p-4, + 0x1.44d21ece023dbp-6, 0x1.83f190441ed7dp-11, 0x1.4747b76204d60p-4, 0x1.a12514d1b5713p-11, + 0x1.4e67c3f830c82p-3, -0x1.217047a53ed89p-6, 0x1.a1fbabbd9a335p-5, 0x1.2896fb885ab6ep-3, + 0x1.5c9b8e41adef5p-4, 0x1.79f92a17a98a1p-5, 0x1.da7770dbf6dd1p-6, 0x1.a40fcf4ba4e11p-4, + 0x1.21a910c0ecb5fp-4, -0x1.59b58a8692c1ap-4, 0x1.85cf32bc958d2p-3, -0x1.8e9bca18b0c5ep-4, + -0x1.f9ef2e03cb69cp-10, 0x1.bdcc93b110280p-5, 0x1.311c84e56ad4dp-2, -0x1.2644d47b25963p-4, + 0x1.2644d47b25963p-4, -0x1.311c84e56ad4dp-2, -0x1.bdcc93b110280p-5, 0x1.f9ef2e03cb69cp-10, + 0x1.8e9bca18b0c5ep-4, -0x1.85cf32bc958d2p-3, 0x1.59b58a8692c1ap-4, -0x1.21a910c0ecb5fp-4, + -0x1.a40fcf4ba4e11p-4, -0x1.da7770dbf6dd1p-6, -0x1.79f92a17a98a1p-5, -0x1.5c9b8e41adef5p-4, + -0x1.2896fb885ab6ep-3, -0x1.a1fbabbd9a335p-5, 0x1.217047a53ed89p-6, -0x1.4e67c3f830c82p-3, + -0x1.a12514d1b5713p-11, -0x1.4747b76204d60p-4, -0x1.83f190441ed7dp-11, -0x1.44d21ece023dbp-6, + -0x1.43c8a9e50fb93p-4, 0x1.6a45e8769db56p-4, 0x1.5d59479cf868cp-5, -0x1.07406ce65ff33p-7, + -0x1.38e3432ce277cp-4, -0x1.f53e7326d574bp-4, -0x1.fa56e4d956157p-3, -0x1.6dfabb7c814f1p-5, + 0x1.d4c3651bd48ffp-6, 0x1.05182ead91b13p-5, -0x1.8cb26e4c8e4a9p-4, 0x1.84bc56fbfb526p-11, + -0x1.dd662bb991814p-5, 0x1.669df6f162362p-5, -0x1.31b40a0dc2f7ep-4, 0x1.c3306fbe7b3c0p-4, + -0x1.dc42cb65f6d5ap-4, 0x1.da451d88013ccp-9, -0x1.df87d36cffe94p-10, -0x1.5b11172b50e1ap-10, + -0x1.052347f0047c3p-4, 0x1.9ba2d3b5bb089p-8, -0x1.590321410a741p-6, 0x1.08391bb40c47ap-3, + 0x1.806e2c4774376p-5, -0x1.7d0eaa07b7550p-5, -0x1.7ec564201d135p-7, 0x1.5fdc31d907327p-6, + 0x1.7175b027cb624p-4, 0x1.186ffac98f6c7p-4, 0x1.2b5e0e892f5bep-4, -0x1.51fb751d63ea1p-4, + -0x1.73e7f62cd4100p-4, 0x1.22d770a91673bp-3, 0x1.1182e13bb4a41p-10, -0x1.04f6b90f68794p-4, + 0x1.1bf187373298bp-6, 0x1.73058d3fdc082p-5, 0x1.79e03a1e07449p-6, 0x1.800ff9eb9a01dp-6, + 0x1.788577bb8c707p-5, 0x1.0de48f9efa3dbp-4, 0x1.3bbaf0dafeeeep-3, -0x1.88edd4f61bca3p-5, + -0x1.36058a36f3b7bp-4, 0x1.9777ed8e664d6p-4, 0x1.db65283cbb71ap-4, 0x1.7c3a93b868dacp-5, + 0x1.c378619182173p-7, -0x1.fce15efb73e5dp-4, -0x1.f97f916789b0ep-4, 0x1.45576c3ac56dfp-6, + 0x1.aa6c85155071ap-5, 0x1.d17e796ddb924p-4, 0x1.87c4017bda152p-4, -0x1.49a44b54634f6p-4, + -0x1.a63093cc62bf2p-4, -0x1.21a798d3e64f6p-4, -0x1.4d1e2a1e62d45p-5, 0x1.e426a42f5d830p-4, + 0x1.ff09552da073ap-4, 0x1.f656f1e802b00p-8, -0x1.a82a086b16c35p-6, -0x1.f4e6064c78c0fp-4, + -0x1.c678b23beac8dp-4, 0x1.d79774a76ca0ap-5, 0x1.5c77bcb8bc4c3p-4, 0x1.771e7463d423ap-4, + 0x1.0c9704ec371b9p-4, -0x1.b3e4d33b911c3p-4, -0x1.ebbd8c4958541p-4, -0x1.1d3444182e7c2p-5, + -0x1.921d01ef28901p-10, 0x1.fff623ca2d04dp-4, 0x1.ef1789019a122p-4, -0x1.04fb80383c6aep-5, + -0x1.01cfc89116859p-4, -0x1.ba5aa6b112fc0p-4, -0x1.659191d19c3a8p-4, 0x1.6e74455ec4792p-4, + 0x1.c08c41b35e876p-4, 0x1.edc197b66c647p-5, 0x1.d935005dab81cp-6, -0x1.f2252e7af7767p-4, + -0x1.ffa72c306a8a9p-4, 0x1.2d866128ec134p-8, 0x1.35410a81a05f1p-5, 0x1.e817b95e49dcap-4, + 0x1.ad2bcc3b50fd1p-4, -0x1.1734d3f07c04ap-4, -0x1.7f8ecc092fb44p-4, -0x1.53282a66507ecp-4, + -0x1.c1249ce4ba213p-5, 0x1.cc1f0b9dac024p-4, 0x1.f7599a32e61d1p-4, 0x1.76dda092f63f7p-6, + -0x1.5f6cf00eecbd3p-7, -0x1.fe1cb196a7a8dp-4, -0x1.dfeae5f903749p-4, 0x1.64c7e1962036cp-5, + 0x1.2bedb2b4c4b6fp-4, 0x1.9ef43c539093bp-4, 0x1.3fed95448ea1ep-4, -0x1.8fbcccab2aa6dp-4, + -0x1.d69619ba0b2b8p-4, -0x1.9372aa2e84099p-5, -0x1.139f10f638e9ap-6, 0x1.fb5795e681e1dp-4, + 0x1.fb5795e681e1dp-4, -0x1.139f10f638e9ap-6, -0x1.9372aa2e84099p-5, -0x1.d69619ba0b2b8p-4, + -0x1.8fbcccab2aa6dp-4, 0x1.3fed95448ea1ep-4, 0x1.9ef43c539093bp-4, 0x1.2bedb2b4c4b6fp-4, + 0x1.64c7e1962036cp-5, -0x1.dfeae5f903749p-4, -0x1.fe1cb196a7a8dp-4, -0x1.5f6cf00eecbd3p-7, + 0x1.76dda092f63f7p-6, 0x1.f7599a32e61d1p-4, 0x1.cc1f0b9dac024p-4, -0x1.c1249ce4ba213p-5, + -0x1.53282a66507ecp-4, -0x1.7f8ecc092fb44p-4, -0x1.1734d3f07c04ap-4, 0x1.ad2bcc3b50fd1p-4, + 0x1.e817b95e49dcap-4, 0x1.35410a81a05f1p-5, 0x1.2d866128ec134p-8, -0x1.ffa72c306a8a9p-4, + -0x1.f2252e7af7767p-4, 0x1.d935005dab81cp-6, 0x1.edc197b66c647p-5, 0x1.c08c41b35e876p-4, + 0x1.6e74455ec4792p-4, -0x1.659191d19c3a8p-4, -0x1.ba5aa6b112fc0p-4, -0x1.01cfc89116859p-4, + -0x1.04fb80383c6aep-5, 0x1.ef1789019a122p-4, 0x1.fff623ca2d04dp-4, -0x1.921d01ef28901p-10, + -0x1.1d3444182e7c2p-5, -0x1.ebbd8c4958541p-4, -0x1.b3e4d33b911c3p-4, 0x1.0c9704ec371b9p-4, + 0x1.771e7463d423ap-4, 0x1.5c77bcb8bc4c3p-4, 0x1.d79774a76ca0ap-5, -0x1.c678b23beac8dp-4, + -0x1.f4e6064c78c0fp-4, -0x1.a82a086b16c35p-6, 0x1.f656f1e802b00p-8, 0x1.ff09552da073ap-4, + 0x1.e426a42f5d830p-4, -0x1.4d1e2a1e62d45p-5, -0x1.21a798d3e64f6p-4, -0x1.a63093cc62bf2p-4, + -0x1.49a44b54634f6p-4, 0x1.87c4017bda152p-4, 0x1.d17e796ddb924p-4, 0x1.aa6c85155071ap-5, + 0x1.45576c3ac56dfp-6, -0x1.f97f916789b0ep-4, -0x1.fce15efb73e5dp-4, 0x1.c378619182173p-7, + 0x1.7c3a93b868dacp-5, 0x1.db65283cbb71ap-4, 0x1.9777ed8e664d6p-4, -0x1.36058a36f3b78p-4, + -0x1.9777ed9bd8c9fp-4, -0x1.36058a737e2dbp-4, 0x1.7c3a922b57d41p-5, -0x1.db6525fbb7cefp-4, + 0x1.fce15db032e25p-4, 0x1.c3786276c6121p-7, 0x1.45576d36f0f79p-6, 0x1.f97f8fa273ceap-4, + -0x1.d17e7820ab427p-4, 0x1.aa6c8426af48ap-5, -0x1.49a44a718a699p-4, -0x1.87c40214f7dabp-4, + 0x1.21a7981978ae6p-4, -0x1.a6309254b326ap-4, 0x1.e426a5c91e4a2p-4, 0x1.4d1e2af9634b0p-5, + -0x1.f656f11b93066p-8, 0x1.ff09565fe2b27p-4, -0x1.f4e604e6971f0p-4, 0x1.a82a07de0f339p-6, + -0x1.d79773e3d4f9ep-5, -0x1.c678b28449cd7p-4, 0x1.771e7430d267bp-4, -0x1.5c77bc839c06ap-4, + 0x1.b3e4d3b6897dfp-4, 0x1.0c970450bdbbcp-4, -0x1.1d3444d818eafp-5, 0x1.ebbd8c614033dp-4, + -0x1.fff62451ec6dap-4, -0x1.921d0015b9dc5p-10, -0x1.04fb8037ff756p-5, -0x1.ef178a17880c7p-4, + 0x1.ba5aa8453e8d3p-4, -0x1.01cfc8b69f9e8p-4, 0x1.6e74452ff3433p-4, 0x1.659193107668ep-4, + -0x1.edc198a5cf72cp-5, 0x1.c08c42e19e51cp-4, -0x1.f2252e4ec3191p-4, -0x1.d935015db42f2p-6, + -0x1.2d86611d03730p-8, -0x1.ffa72be1e0a65p-4, 0x1.e817b820f816cp-4, -0x1.35410b2eb10e2p-5, + 0x1.1734d42c89f0ep-4, 0x1.ad2bce562ddbap-4, -0x1.53282ad558d27p-4, 0x1.7f8ecc19a954fp-4, + -0x1.cc1f0c6118c6fp-4, -0x1.c1249daf74b52p-5, 0x1.76dda0ae80e41p-6, -0x1.f7599a30022f4p-4, + 0x1.fe1cb035f4fa8p-4, -0x1.5f6cf10f5ded8p-7, 0x1.64c7e0d722f8ep-5, 0x1.dfeae4d287cddp-4, + -0x1.9ef43e349db61p-4, 0x1.2bedb2e254375p-4, -0x1.8fbcce404c6cbp-4, -0x1.3fed95639c615p-4, + 0x1.9372a7d4c7bf5p-5, -0x1.d6961a00b77ccp-4, 0x1.fb5795e672b67p-4, 0x1.139f1145ca02ap-6, + 0x1.139f1145ca02ap-6, 0x1.fb5795e672b67p-4, -0x1.d6961a00b77ccp-4, 0x1.9372a7d4c7bf5p-5, + -0x1.3fed95639c615p-4, -0x1.8fbcce404c6cbp-4, 0x1.2bedb2e254375p-4, -0x1.9ef43e349db61p-4, + 0x1.dfeae4d287cddp-4, 0x1.64c7e0d722f8ep-5, -0x1.5f6cf10f5ded8p-7, 0x1.fe1cb035f4fa8p-4, + -0x1.f7599a30022f4p-4, 0x1.76dda0ae80e41p-6, -0x1.c1249daf74b52p-5, -0x1.cc1f0c6118c6fp-4, + 0x1.7f8ecc19a954fp-4, -0x1.53282ad558d27p-4, 0x1.ad2bce562ddbap-4, 0x1.1734d42c89f0ep-4, + -0x1.35410b2eb10e2p-5, 0x1.e817b820f816cp-4, -0x1.ffa72be1e0a65p-4, -0x1.2d86611d03730p-8, + -0x1.d935015db42f2p-6, -0x1.f2252e4ec3191p-4, 0x1.c08c42e19e51cp-4, -0x1.edc198a5cf72cp-5, + 0x1.659193107668ep-4, 0x1.6e74452ff3433p-4, -0x1.01cfc8b69f9e8p-4, 0x1.ba5aa8453e8d3p-4, + -0x1.ef178a17880c7p-4, -0x1.04fb8037ff756p-5, -0x1.921d0015b9dc5p-10, -0x1.fff62451ec6dap-4, + 0x1.ebbd8c614033dp-4, -0x1.1d3444d818eafp-5, 0x1.0c970450bdbbcp-4, 0x1.b3e4d3b6897dfp-4, + -0x1.5c77bc839c06ap-4, 0x1.771e7430d267bp-4, -0x1.c678b28449cd7p-4, -0x1.d79773e3d4f9ep-5, + 0x1.a82a07de0f339p-6, -0x1.f4e604e6971f0p-4, 0x1.ff09565fe2b27p-4, -0x1.f656f11b93066p-8, + 0x1.4d1e2af9634b0p-5, 0x1.e426a5c91e4a2p-4, -0x1.a6309254b326ap-4, 0x1.21a7981978ae6p-4, + -0x1.87c40214f7dabp-4, -0x1.49a44a718a699p-4, 0x1.aa6c8426af48ap-5, -0x1.d17e7820ab427p-4, + 0x1.f97f8fa273ceap-4, 0x1.45576d36f0f79p-6, 0x1.c3786276c6121p-7, 0x1.fce15db032e25p-4, + -0x1.db6525fbb7cefp-4, 0x1.7c3a922b57d41p-5, -0x1.36058a737e2c9p-4, -0x1.9777ed9bd8c9dp-4, + 0x1.c35e280b9d6c0p-3, -0x1.15a00e568014bp-8, -0x1.5419528344265p-6, 0x1.57182fa53cdcap-3, + -0x1.7a9a6ad3c5bc7p-6, 0x1.724094cde75e0p-6, 0x1.1a4e0014cd224p-7, -0x1.17157dafa8a60p-5, + 0x1.1d1b1cfbec92bp-4, -0x1.aae6217b9b5bcp-5, -0x1.24be2b0cb61f9p-8, 0x1.df0e1b0da5c5dp-4, + -0x1.c555d77e08402p-6, -0x1.af78a778e97eap-6, 0x1.5903b03d3cc1cp-3, 0x1.83e976fd0e028p-6, + 0x1.c0c8f6c3cd322p-9, 0x1.4b910ab70c2cap-3, -0x1.17bac341fb24dp-4, -0x1.3621397061fe3p-5, + 0x1.3e9808791a3d6p-5, 0x1.0004ec9188321p-4, -0x1.9204799587aa5p-6, -0x1.3b0b289e72775p-7, + 0x1.968d034c8d85bp-5, -0x1.7a21427c6c731p-8, 0x1.7a44b98231c31p-10, -0x1.4f455c0d36374p-5, + 0x1.a13336ce67f32p-7, 0x1.bb70b74447474p-7, 0x1.65eb35ed0c5eap-5, -0x1.cac838c6b951dp-4, + 0x1.9ce2ab81c9138p-3, 0x1.f2f6d1bbdbbebp-11, 0x1.268ae3ed017b1p-6, 0x1.90ea50eef098bp-9, + 0x1.10c5902d148e7p-4, -0x1.113d5387550eep-4, 0x1.65f86cccea0e0p-3, -0x1.9c623b7fea17dp-6, + -0x1.9025db3a9e0c4p-7, 0x1.5cf94a6f33be1p-5, -0x1.f5a0e4189a95ep-5, 0x1.8c4ce7fde183ap-8, + -0x1.729d239c483dcp-5, 0x1.fb059ddb1008fp-3, 0x1.2578ae43985d5p-7, 0x1.5f36654ea30edp-8, + -0x1.b8e29fe95a896p-4, 0x1.1765131ed3067p-10, 0x1.16de4a5afffdep-8, -0x1.a1bfdd0c7fe46p-4, + -0x1.b5c32b05957b4p-3, -0x1.0ef50438e0c37p-7, -0x1.0181cec4e156dp-4, -0x1.fb5c6ea1cca2bp-6, + -0x1.bb81a0a14e32ep-8, -0x1.4e2d9a7e494bdp-6, -0x1.49898a241614ap-3, -0x1.3ff7a62b5e34bp-4, + -0x1.d7ce2572ce113p-4, -0x1.83307b898ecafp-3, -0x1.45fe5fa7a3bc3p-4, 0x1.dca5788ddad87p-6, + 0x1.dca5788ddad87p-6, -0x1.45fe5fa7a3bc3p-4, -0x1.83307b898ecafp-3, -0x1.d7ce2572ce113p-4, + -0x1.3ff7a62b5e34bp-4, -0x1.49898a241614ap-3, -0x1.4e2d9a7e494bdp-6, -0x1.bb81a0a14e32ep-8, + -0x1.fb5c6ea1cca2bp-6, -0x1.0181cec4e156dp-4, -0x1.0ef50438e0c37p-7, -0x1.b5c32b05957b4p-3, + -0x1.a1bfdd0c7fe46p-4, 0x1.16de4a5afffdep-8, 0x1.1765131ed3067p-10, -0x1.b8e29fe95a896p-4, + 0x1.5f36654ea30edp-8, 0x1.2578ae43985d5p-7, 0x1.fb059ddb1008fp-3, -0x1.729d239c483dcp-5, + 0x1.8c4ce7fde183ap-8, -0x1.f5a0e4189a95ep-5, 0x1.5cf94a6f33be1p-5, -0x1.9025db3a9e0c4p-7, + -0x1.9c623b7fea17dp-6, 0x1.65f86cccea0e0p-3, -0x1.113d5387550eep-4, 0x1.10c5902d148e7p-4, + 0x1.90ea50eef098bp-9, 0x1.268ae3ed017b1p-6, 0x1.f2f6d1bbdbbebp-11, 0x1.9ce2ab81c9138p-3, + -0x1.cac838c6b951dp-4, 0x1.65eb35ed0c5eap-5, 0x1.bb70b74447474p-7, 0x1.a13336ce67f32p-7, + -0x1.4f455c0d36374p-5, 0x1.7a44b98231c31p-10, -0x1.7a21427c6c731p-8, 0x1.968d034c8d85bp-5, + -0x1.3b0b289e72775p-7, -0x1.9204799587aa5p-6, 0x1.0004ec9188321p-4, 0x1.3e9808791a3d6p-5, + -0x1.3621397061fe3p-5, -0x1.17bac341fb24dp-4, 0x1.4b910ab70c2cap-3, 0x1.c0c8f6c3cd322p-9, + 0x1.83e976fd0e028p-6, 0x1.5903b03d3cc1cp-3, -0x1.af78a778e97eap-6, -0x1.c555d77e08402p-6, + 0x1.df0e1b0da5c5dp-4, -0x1.24be2b0cb61f9p-8, -0x1.aae6217b9b5bcp-5, 0x1.1d1b1cfbec92bp-4, + -0x1.17157dafa8a5dp-5, 0x1.1a4e0014cd223p-7, 0x1.724094cde75d9p-6, -0x1.7a9a6ad3c5bc8p-6, + 0x1.57182fa53cdc9p-3, -0x1.5419528344264p-6, -0x1.15a008a1a7b53p-8, 0x1.c35e28111763cp-3, + -0x1.5ee2a1df2e770p-4, 0x1.2f5ed24805f24p-5, -0x1.fe044cb19e947p-4, -0x1.4bf80bf56e2f5p-7, + -0x1.ddc7df1b7a131p-6, 0x1.cc85464c314b5p-4, 0x1.51b02242e9764p-4, -0x1.f7153ec8a1265p-6, + 0x1.3f8a0e8cfba0cp-6, -0x1.3b32578d4a631p-5, 0x1.9881a47a45360p-6, 0x1.2bfdc42a415a7p-7, + 0x1.59c5f9824f20bp-3, -0x1.fd5da1e7fa375p-7, -0x1.9f748c824e260p-10, 0x1.e6e8fa1401a4dp-4, + 0x1.1dcf422129110p-4, -0x1.7f4108a6423cep-7, -0x1.c8ef3e8352ae4p-6, -0x1.4b3d5f7dd9928p-6, + -0x1.c6d74008f1187p-4, -0x1.86d6ee7d18856p-6, -0x1.c5185d23451cfp-6, -0x1.12bd27f262745p-9, + -0x1.5e662b9129d72p-4, 0x1.9967cd228f6f2p-5, 0x1.fbf687a151e0dp-5, -0x1.061eaf6b3e83fp-5, + 0x1.592f926df29eap-7, -0x1.5dfeed3306f87p-4, -0x1.2cfa3101e7f99p-4, -0x1.d1a458ae984f0p-5, + 0x1.7be394f200f2fp-6, -0x1.2b706454baebcp-4, -0x1.7aee2bda5c44cp-4, -0x1.35599f33dbd55p-3, + 0x1.adee7873398c9p-3, 0x1.bfaf570b5b67ap-6, 0x1.493862b219cb6p-5, -0x1.f459aa61c2566p-3, + -0x1.c2557cd041790p-7, -0x1.b54b021c18b75p-9, -0x1.30af3d077d7c9p-6, 0x1.6331cabbc99dcp-6, + -0x1.09314f744466cp-6, -0x1.5010ba2e9e763p-5, 0x1.16bf1bba74169p-10, 0x1.0d611dc2eae88p-5, + -0x1.d89e9a60eb76ap-7, -0x1.dcf3db258a41cp-8, 0x1.a36c6dbf35929p-7, -0x1.db345e4b24a9bp-8, + -0x1.13becb17e6c28p-5, -0x1.f49235a0b02f6p-4, 0x1.5467b06dff633p-3, -0x1.c7dcf4b56eefbp-4, + -0x1.0646aed1e46fep-4, 0x1.082f4f0ae95bep-4, -0x1.1559aad9ad896p-3, 0x1.b754eb45b4b10p-4, + 0x1.330bbdccb6672p-3, 0x1.05f94dd94abf7p-4, -0x1.34631a824df17p-8, 0x1.32c321859867ep-2, + 0x1.32c321859867ep-2, -0x1.34631a824df17p-8, 0x1.05f94dd94abf7p-4, 0x1.330bbdccb6672p-3, + 0x1.b754eb45b4b10p-4, -0x1.1559aad9ad896p-3, 0x1.082f4f0ae95bep-4, -0x1.0646aed1e46fep-4, + -0x1.c7dcf4b56eefbp-4, 0x1.5467b06dff633p-3, -0x1.f49235a0b02f6p-4, -0x1.13becb17e6c28p-5, + -0x1.db345e4b24a9bp-8, 0x1.a36c6dbf35929p-7, -0x1.dcf3db258a41cp-8, -0x1.d89e9a60eb76ap-7, + 0x1.0d611dc2eae88p-5, 0x1.16bf1bba74169p-10, -0x1.5010ba2e9e763p-5, -0x1.09314f744466cp-6, + 0x1.6331cabbc99dcp-6, -0x1.30af3d077d7c9p-6, -0x1.b54b021c18b75p-9, -0x1.c2557cd041790p-7, + -0x1.f459aa61c2566p-3, 0x1.493862b219cb6p-5, 0x1.bfaf570b5b67ap-6, 0x1.adee7873398c9p-3, + -0x1.35599f33dbd55p-3, -0x1.7aee2bda5c44cp-4, -0x1.2b706454baebcp-4, 0x1.7be394f200f2fp-6, + -0x1.d1a458ae984f0p-5, -0x1.2cfa3101e7f99p-4, -0x1.5dfeed3306f87p-4, 0x1.592f926df29eap-7, + -0x1.061eaf6b3e83fp-5, 0x1.fbf687a151e0dp-5, 0x1.9967cd228f6f2p-5, -0x1.5e662b9129d72p-4, + -0x1.12bd27f262745p-9, -0x1.c5185d23451cfp-6, -0x1.86d6ee7d18856p-6, -0x1.c6d74008f1187p-4, + -0x1.4b3d5f7dd9928p-6, -0x1.c8ef3e8352ae4p-6, -0x1.7f4108a6423cep-7, 0x1.1dcf422129110p-4, + 0x1.e6e8fa1401a4dp-4, -0x1.9f748c824e260p-10, -0x1.fd5da1e7fa375p-7, 0x1.59c5f9824f20bp-3, + 0x1.2bfdc42a415a7p-7, 0x1.9881a47a45360p-6, -0x1.3b32578d4a631p-5, 0x1.3f8a0e8cfba0cp-6, + -0x1.f7153ec8a1266p-6, 0x1.51b02242e9764p-4, 0x1.cc85464c314b5p-4, -0x1.ddc7df1b7a13cp-6, + -0x1.4bf80bf56e2f5p-7, -0x1.fe044cb19e94cp-4, 0x1.2f5ed2c2054fap-5, -0x1.5ee2a36115eaep-4, + -0x1.2bedb47344b35p-4, 0x1.9ef43ff81e7ccp-4, 0x1.e817bc1556fd6p-4, 0x1.35410858762cap-5, + -0x1.921d7be22f943p-10, -0x1.fff62011283abp-4, -0x1.e426a5dc866d3p-4, 0x1.4d1e2540b8e2fp-5, + 0x1.36058afcc6087p-4, 0x1.9777ee1020531p-4, 0x1.21a79a59e2f88p-4, -0x1.a630941a7e4b1p-4, + -0x1.ebbd8bfa52684p-4, -0x1.1d34442c9a508p-5, 0x1.2d8652a37eeb7p-8, 0x1.ffa730ca9020ep-4, + 0x1.dfeae691fb6d5p-4, -0x1.64c7db3586cc8p-5, -0x1.3fed949b0c394p-4, -0x1.8fbcc818c5d3cp-4, + -0x1.1734d73f62259p-4, 0x1.ad2bc7f288a27p-4, 0x1.ef1788a045fdcp-4, 0x1.04fb81afac34cp-5, + -0x1.f656ef212b21dp-8, -0x1.ff095242a7e9dp-4, -0x1.db6525a7ca396p-4, 0x1.7c3a9522f00a5p-5, + 0x1.49a4480ce9271p-4, 0x1.87c400a97595bp-4, 0x1.0c970478f6ac1p-4, -0x1.b3e4d44cb9ce5p-4, + -0x1.f225320e47831p-4, -0x1.d935068d02cbcp-6, 0x1.5f6d002b9dfa3p-7, 0x1.fe1cb1b015d1ep-4, + 0x1.d696186bb5459p-4, -0x1.9372a8b2a594ep-5, -0x1.53282a8ee5027p-4, -0x1.7f8ecebfbef57p-4, + -0x1.01cfc897b5eafp-4, 0x1.ba5aa69585326p-4, 0x1.f4e600b84c98cp-4, 0x1.a829fbbd68044p-6, + -0x1.c3784f6f94b56p-7, -0x1.fce161c43507ep-4, -0x1.d17e78e9cc824p-4, 0x1.aa6c862c3fcaap-5, + 0x1.5c77baecbafabp-4, 0x1.771e74f576565p-4, 0x1.edc1946d8014ap-5, -0x1.c08c3faced727p-4, + -0x1.f75999e985eacp-4, -0x1.76dda4fce8084p-6, 0x1.139f186b41327p-6, 0x1.fb5797a8a846fp-4, + 0x1.cc1f0c6f5eaedp-4, -0x1.c1249dcf46e8dp-5, -0x1.659193a7d3165p-4, -0x1.6e7444d6b308fp-4, + -0x1.d79777d340182p-5, 0x1.c678b241b584bp-4, 0x1.f97f935834055p-4, 0x1.4557700c50e85p-6, + -0x1.4557700c50e85p-6, -0x1.f97f935834055p-4, -0x1.c678b241b584bp-4, 0x1.d79777d340182p-5, + 0x1.6e7444d6b308fp-4, 0x1.659193a7d3165p-4, 0x1.c1249dcf46e8dp-5, -0x1.cc1f0c6f5eaedp-4, + -0x1.fb5797a8a846fp-4, -0x1.139f186b41327p-6, 0x1.76dda4fce8084p-6, 0x1.f75999e985eacp-4, + 0x1.c08c3faced727p-4, -0x1.edc1946d8014ap-5, -0x1.771e74f576565p-4, -0x1.5c77baecbafabp-4, + -0x1.aa6c862c3fcaap-5, 0x1.d17e78e9cc824p-4, 0x1.fce161c43507ep-4, 0x1.c3784f6f94b56p-7, + -0x1.a829fbbd68044p-6, -0x1.f4e600b84c98cp-4, -0x1.ba5aa69585326p-4, 0x1.01cfc897b5eafp-4, + 0x1.7f8ecebfbef57p-4, 0x1.53282a8ee5027p-4, 0x1.9372a8b2a594ep-5, -0x1.d696186bb5459p-4, + -0x1.fe1cb1b015d1ep-4, -0x1.5f6d002b9dfa3p-7, 0x1.d935068d02cbcp-6, 0x1.f225320e47831p-4, + 0x1.b3e4d44cb9ce5p-4, -0x1.0c970478f6ac1p-4, -0x1.87c400a97595bp-4, -0x1.49a4480ce9271p-4, + -0x1.7c3a9522f00a5p-5, 0x1.db6525a7ca396p-4, 0x1.ff095242a7e9dp-4, 0x1.f656ef212b21dp-8, + -0x1.04fb81afac34cp-5, -0x1.ef1788a045fdcp-4, -0x1.ad2bc7f288a27p-4, 0x1.1734d73f62259p-4, + 0x1.8fbcc818c5d3cp-4, 0x1.3fed949b0c394p-4, 0x1.64c7db3586cc8p-5, -0x1.dfeae691fb6d5p-4, + -0x1.ffa730ca9020ep-4, -0x1.2d8652a37eeb7p-8, 0x1.1d34442c9a508p-5, 0x1.ebbd8bfa52684p-4, + 0x1.a630941a7e4b1p-4, -0x1.21a79a59e2f88p-4, -0x1.9777ee1020531p-4, -0x1.36058afcc6087p-4, + -0x1.4d1e2540b8e2fp-5, 0x1.e426a5dc866d3p-4, 0x1.fff62011283abp-4, 0x1.921d7be22f943p-10, + -0x1.35410858762cap-5, -0x1.e817bc1556fd6p-4, -0x1.9ef43ff81e7cbp-4, 0x1.2bedb47344b4ap-4, + -0x1.9ef4401b8233ap-4, -0x1.2bedb4a5254b7p-4, 0x1.354107bee1887p-5, -0x1.e817b9cfc5735p-4, + 0x1.fff61fff36677p-4, -0x1.921d78e495c60p-10, 0x1.4d1e24c0657c9p-5, 0x1.e426a5d489f73p-4, + -0x1.9777edc4aa3fep-4, 0x1.360589d374decp-4, -0x1.a63092e79722bp-4, -0x1.21a79ab0a4725p-4, + 0x1.1d3444d3b4faap-5, -0x1.ebbd8c08c88e4p-4, 0x1.ffa731609101fp-4, -0x1.2d8651d415ae1p-8, + 0x1.64c7dc033e605p-5, 0x1.dfeae82ae6d8ap-4, -0x1.8fbcc7954a0c7p-4, 0x1.3fed94dea7f5fp-4, + -0x1.ad2bc8ffddb9cp-4, -0x1.1734d6df0b0c4p-4, 0x1.04fb8272c408dp-5, -0x1.ef178831da30dp-4, + 0x1.ff09544c0b89cp-4, -0x1.f656ee3c746bep-8, 0x1.7c3a94e423628p-5, 0x1.db65249b16d0ep-4, + -0x1.87c4009b2f5ddp-4, 0x1.49a448e1b56a3p-4, -0x1.b3e4d5682fbbap-4, -0x1.0c97040e816d4p-4, + 0x1.d935043cf5430p-6, -0x1.f22532481806dp-4, 0x1.fe1cb0dca2a03p-4, -0x1.5f6d00f2d2cffp-7, + 0x1.9372a84c7a2f1p-5, 0x1.d696181f71052p-4, -0x1.7f8ecf4bb7fb8p-4, 0x1.532829fab1071p-4, + -0x1.ba5aa759c7592p-4, -0x1.01cfc801589dep-4, 0x1.a829fcb03bd39p-6, -0x1.f4e60264e3647p-4, + 0x1.fce15ff87b2f3p-4, -0x1.c37850a08edf0p-7, 0x1.aa6c85706ba2bp-5, 0x1.d17e78fb11ff4p-4, + -0x1.771e74b8be2adp-4, 0x1.5c77ba882ba2ep-4, -0x1.c08c4182737c6p-4, -0x1.edc193e270f9ep-5, + 0x1.76dda472b8f05p-6, -0x1.f75998516a39fp-4, 0x1.fb5796028feebp-4, -0x1.139f184bc1d77p-6, + 0x1.c1249e02c99dap-5, 0x1.cc1f0dcd75c63p-4, -0x1.6e7444ad25de8p-4, 0x1.65919459cf25cp-4, + -0x1.c678b1f5adab1p-4, -0x1.d797783f667f9p-5, 0x1.4557705d448d5p-6, -0x1.f97f9427dceb8p-4, + 0x1.f97f9427dceb8p-4, -0x1.4557705d448d5p-6, 0x1.d797783f667f9p-5, 0x1.c678b1f5adab1p-4, + -0x1.65919459cf25cp-4, 0x1.6e7444ad25de8p-4, -0x1.cc1f0dcd75c63p-4, -0x1.c1249e02c99dap-5, + 0x1.139f184bc1d77p-6, -0x1.fb5796028feebp-4, 0x1.f75998516a39fp-4, -0x1.76dda472b8f05p-6, + 0x1.edc193e270f9ep-5, 0x1.c08c4182737c6p-4, -0x1.5c77ba882ba2ep-4, 0x1.771e74b8be2adp-4, + -0x1.d17e78fb11ff4p-4, -0x1.aa6c85706ba2bp-5, 0x1.c37850a08edf0p-7, -0x1.fce15ff87b2f3p-4, + 0x1.f4e60264e3647p-4, -0x1.a829fcb03bd39p-6, 0x1.01cfc801589dep-4, 0x1.ba5aa759c7592p-4, + -0x1.532829fab1071p-4, 0x1.7f8ecf4bb7fb8p-4, -0x1.d696181f71052p-4, -0x1.9372a84c7a2f1p-5, + 0x1.5f6d00f2d2cffp-7, -0x1.fe1cb0dca2a03p-4, 0x1.f22532481806dp-4, -0x1.d935043cf5430p-6, + 0x1.0c97040e816d4p-4, 0x1.b3e4d5682fbbap-4, -0x1.49a448e1b56a3p-4, 0x1.87c4009b2f5ddp-4, + -0x1.db65249b16d0ep-4, -0x1.7c3a94e423628p-5, 0x1.f656ee3c746bep-8, -0x1.ff09544c0b89cp-4, + 0x1.ef178831da30dp-4, -0x1.04fb8272c408dp-5, 0x1.1734d6df0b0c4p-4, 0x1.ad2bc8ffddb9cp-4, + -0x1.3fed94dea7f5fp-4, 0x1.8fbcc7954a0c7p-4, -0x1.dfeae82ae6d8ap-4, -0x1.64c7dc033e605p-5, + 0x1.2d8651d415ae1p-8, -0x1.ffa731609101fp-4, 0x1.ebbd8c08c88e4p-4, -0x1.1d3444d3b4faap-5, + 0x1.21a79ab0a4725p-4, 0x1.a63092e79722bp-4, -0x1.360589d374decp-4, 0x1.9777edc4aa3fep-4, + -0x1.e426a5d489f73p-4, -0x1.4d1e24c0657c9p-5, 0x1.921d78e495c60p-10, -0x1.fff61fff36677p-4, + 0x1.e817b9cfc5735p-4, -0x1.354107bee1887p-5, 0x1.2bedb4a5254d6p-4, 0x1.9ef4401b82340p-4, + 0x1.135203c15082ap-3, -0x1.d8f271bdbc0e3p-6, 0x1.0e9b957361d15p-6, 0x1.c4b34d1ba88ebp-6, + -0x1.3f1458b3146d2p-4, 0x1.c30be4ac3566cp-9, 0x1.9befcccc2c69ap-7, 0x1.72b50d0e2962ap-3, + 0x1.8274d4ba88404p-3, -0x1.67c1f1d5b2632p-3, -0x1.baae21092ddffp-4, -0x1.3996990660fc6p-4, + -0x1.d1eedf83c3bbdp-7, 0x1.9eb1e20ae4cfcp-4, 0x1.c842463fedca5p-4, 0x1.599a6c7ca2a18p-9, + -0x1.faf0127fb67e4p-6, 0x1.de4c1b22a55f5p-3, 0x1.3a200f3f09715p-3, -0x1.36967982b5876p-5, + 0x1.4eab225f1eb96p-4, -0x1.6e53ad7d3461fp-5, 0x1.d5078d07313c1p-12, -0x1.72b5815d8164ep-5, + 0x1.5b1728ee7ff32p-5, 0x1.1fe8cec0e6e3fp-9, -0x1.4e499183b4612p-5, -0x1.9fdcc3ea0bd3ep-4, + 0x1.27694800b3facp-4, 0x1.c4def1d2613fbp-4, -0x1.efe18ca4211bbp-5, 0x1.419abcf8ddff8p-4, + -0x1.e4dbaf2394f1ep-7, -0x1.0fd75876673d4p-3, 0x1.7de495ac56d67p-5, 0x1.17ce3062675aap-6, + 0x1.0b84f2460438bp-5, -0x1.03d3d4feb6298p-3, -0x1.8add73a32706ap-6, -0x1.90ad25e85fa09p-5, + -0x1.21ab9e2dc1875p-3, 0x1.cc6ea892c2aedp-5, 0x1.048d691edaa2ap-5, -0x1.68f46f23ee509p-5, + -0x1.7a2a0e043e1bcp-3, -0x1.589c6126c2a1ep-8, 0x1.30cf75b8a3540p-8, 0x1.ae56e528ddcaep-4, + -0x1.1954e2c6f7152p-5, 0x1.69c5b4934da83p-6, -0x1.aaf921d8d5ddbp-4, 0x1.4733e4d8735f2p-10, + -0x1.6e34f9133d6f0p-5, 0x1.0c6186e92f4f9p-3, -0x1.a27f79ef43996p-4, 0x1.9b1e5ed76d904p-8, + -0x1.e6dc96adb4f88p-5, 0x1.44ac6bcab55b9p-3, 0x1.13d580f6037fbp-6, -0x1.a101f599b1999p-4, + 0x1.1406341737ef6p-6, 0x1.6e0f4985d1c3ep-7, 0x1.5f0d75322d7fdp-6, -0x1.6b30027c6219cp-4, + 0x1.6b30027c6219cp-4, -0x1.5f0d75322d7fdp-6, -0x1.6e0f4985d1c3ep-7, -0x1.1406341737ef6p-6, + 0x1.a101f599b1999p-4, -0x1.13d580f6037fbp-6, -0x1.44ac6bcab55b9p-3, 0x1.e6dc96adb4f88p-5, + -0x1.9b1e5ed76d904p-8, 0x1.a27f79ef43996p-4, -0x1.0c6186e92f4f9p-3, 0x1.6e34f9133d6f0p-5, + -0x1.4733e4d8735f2p-10, 0x1.aaf921d8d5ddbp-4, -0x1.69c5b4934da83p-6, 0x1.1954e2c6f7152p-5, + -0x1.ae56e528ddcaep-4, -0x1.30cf75b8a3540p-8, 0x1.589c6126c2a1ep-8, 0x1.7a2a0e043e1bcp-3, + 0x1.68f46f23ee509p-5, -0x1.048d691edaa2ap-5, -0x1.cc6ea892c2aedp-5, 0x1.21ab9e2dc1875p-3, + 0x1.90ad25e85fa09p-5, 0x1.8add73a32706ap-6, 0x1.03d3d4feb6298p-3, -0x1.0b84f2460438bp-5, + -0x1.17ce3062675aap-6, -0x1.7de495ac56d67p-5, 0x1.0fd75876673d4p-3, 0x1.e4dbaf2394f1ep-7, + -0x1.419abcf8ddff8p-4, 0x1.efe18ca4211bbp-5, -0x1.c4def1d2613fbp-4, -0x1.27694800b3facp-4, + 0x1.9fdcc3ea0bd3ep-4, 0x1.4e499183b4612p-5, -0x1.1fe8cec0e6e3fp-9, -0x1.5b1728ee7ff32p-5, + 0x1.72b5815d8164ep-5, -0x1.d5078d07313c1p-12, 0x1.6e53ad7d3461fp-5, -0x1.4eab225f1eb96p-4, + 0x1.36967982b5876p-5, -0x1.3a200f3f09715p-3, -0x1.de4c1b22a55f5p-3, 0x1.faf0127fb67e4p-6, + -0x1.599a6c7ca2a18p-9, -0x1.c842463fedca5p-4, -0x1.9eb1e20ae4cfcp-4, 0x1.d1eedf83c3bbdp-7, + 0x1.3996990660fc6p-4, 0x1.baae21092ddffp-4, 0x1.67c1f1d5b2632p-3, -0x1.8274d4ba88404p-3, + -0x1.72b50d0e2962ap-3, -0x1.9befcccc2c69cp-7, -0x1.c30be4ac35632p-9, 0x1.3f1458b3146cap-4, + -0x1.c4b34d1ba890cp-6, -0x1.0e9b957361d14p-6, 0x1.d8f272af0dd52p-6, -0x1.135203c2dadd5p-3, + 0x1.08bdf1359a87cp-4, 0x1.16cdc64035ca9p-4, -0x1.1117eacdc98c9p-2, 0x1.af58b8592d862p-6, + -0x1.b9b544167cbccp-6, -0x1.091d27e308ea0p-6, 0x1.a07d2f7bf254cp-4, -0x1.18f69e218b961p-6, + -0x1.0427464985f8fp-4, 0x1.3d36d2dbd131bp-4, -0x1.2d37058103565p-5, 0x1.d59baa3111149p-3, + -0x1.107ad9aa14536p-5, 0x1.951a988cf8059p-6, 0x1.795ece41f2187p-5, 0x1.3965f4d790460p-6, + -0x1.181f0aa021dd3p-8, -0x1.5432bb36316dfp-5, 0x1.a65bf57808869p-5, -0x1.790d474771691p-4, + 0x1.266c8f106d86bp-4, 0x1.3293827d299b1p-3, 0x1.06d64ba4f21ddp-4, 0x1.8a9344ae9d7d8p-5, + 0x1.40f19834d8d5ap-7, -0x1.659de8e562ec9p-5, 0x1.b1584db28167dp-5, -0x1.7503b0f079578p-4, + 0x1.7aee9c26fffb1p-4, -0x1.e0d4660195be4p-8, -0x1.322103b460411p-3, -0x1.3b5302868db59p-3, + 0x1.1e9823283137fp-3, -0x1.d46493d86c214p-6, 0x1.c7578382d21d6p-6, 0x1.c75544e1d9ddep-5, + -0x1.455f1d4a25d89p-5, -0x1.9996d4a35f8f3p-8, 0x1.c756e0f9c885ep-7, 0x1.69a18a0877a55p-4, + 0x1.7c9a39b2b70b3p-8, -0x1.9e2d3e4438662p-5, -0x1.16e3795f3da53p-4, -0x1.8d489d57fe83fp-7, + -0x1.bc7b68ced47e0p-5, -0x1.5a5968c5ba7b8p-4, 0x1.3bbfc6ef5bee5p-5, 0x1.f01faf88b9aa2p-9, + 0x1.dac1ccccf35cep-6, 0x1.36e663bf21f00p-4, -0x1.0684e1ee1c746p-3, -0x1.4a22015712225p-4, + 0x1.d5cbacb9b80bcp-3, 0x1.4f560f7f1b4e8p-5, 0x1.0ae3875a67875p-8, 0x1.41f98efc99de7p-4, + 0x1.8ab3b36449936p-4, -0x1.1198b7289d5b7p-6, -0x1.1fbc30d78c426p-3, -0x1.9c91c99c181e3p-4, + -0x1.db4e5f205fdb7p-4, 0x1.41283ee056ea1p-3, 0x1.4df840f109b06p-5, -0x1.ba67de06f99f2p-5, + 0x1.ba67de06f99f2p-5, -0x1.4df840f109b06p-5, -0x1.41283ee056ea1p-3, 0x1.db4e5f205fdb7p-4, + 0x1.9c91c99c181e3p-4, 0x1.1fbc30d78c426p-3, 0x1.1198b7289d5b7p-6, -0x1.8ab3b36449936p-4, + -0x1.41f98efc99de7p-4, -0x1.0ae3875a67875p-8, -0x1.4f560f7f1b4e8p-5, -0x1.d5cbacb9b80bcp-3, + 0x1.4a22015712225p-4, 0x1.0684e1ee1c746p-3, -0x1.36e663bf21f00p-4, -0x1.dac1ccccf35cep-6, + -0x1.f01faf88b9aa2p-9, -0x1.3bbfc6ef5bee5p-5, 0x1.5a5968c5ba7b8p-4, 0x1.bc7b68ced47e0p-5, + 0x1.8d489d57fe83fp-7, 0x1.16e3795f3da53p-4, 0x1.9e2d3e4438662p-5, -0x1.7c9a39b2b70b3p-8, + -0x1.69a18a0877a55p-4, -0x1.c756e0f9c885ep-7, 0x1.9996d4a35f8f3p-8, 0x1.455f1d4a25d89p-5, + -0x1.c75544e1d9ddep-5, -0x1.c7578382d21d6p-6, 0x1.d46493d86c214p-6, -0x1.1e9823283137fp-3, + 0x1.3b5302868db59p-3, 0x1.322103b460411p-3, 0x1.e0d4660195be4p-8, -0x1.7aee9c26fffb1p-4, + 0x1.7503b0f079578p-4, -0x1.b1584db28167dp-5, 0x1.659de8e562ec9p-5, -0x1.40f19834d8d5ap-7, + -0x1.8a9344ae9d7d8p-5, -0x1.06d64ba4f21ddp-4, -0x1.3293827d299b1p-3, -0x1.266c8f106d86bp-4, + 0x1.790d474771691p-4, -0x1.a65bf57808869p-5, 0x1.5432bb36316dfp-5, 0x1.181f0aa021dd3p-8, + -0x1.3965f4d790460p-6, -0x1.795ece41f2187p-5, -0x1.951a988cf8059p-6, 0x1.107ad9aa14536p-5, + -0x1.d59baa3111149p-3, 0x1.2d37058103565p-5, -0x1.3d36d2dbd131bp-4, 0x1.0427464985f8fp-4, + 0x1.18f69e218b960p-6, -0x1.a07d2f7bf254cp-4, 0x1.091d27e308ea5p-6, 0x1.b9b544167cbe8p-6, + -0x1.af58b8592d869p-6, 0x1.1117eacdc98c7p-2, -0x1.16cdc63c40837p-4, -0x1.08bdf0aab3cc7p-4, + -0x1.21a79a3242346p-4, 0x1.a63093641045dp-4, 0x1.f2252c618314bp-4, 0x1.d934fddb1c68bp-6, + -0x1.139f0a3e81d7cp-6, -0x1.fb57964cae9cbp-4, -0x1.c08c42eca3fe0p-4, 0x1.edc194e26b0bap-5, + 0x1.87c401bc9349ap-4, 0x1.49a4489b003d8p-4, 0x1.4d1e24965af58p-5, -0x1.e426a78279265p-4, + -0x1.ffa730b183c75p-4, 0x1.2d8676532fac9p-8, 0x1.9372a4f93f8fdp-5, 0x1.d6961963c499fp-4, + 0x1.6e744546cd6b8p-4, -0x1.659191aa71feep-4, -0x1.d17e794398714p-4, -0x1.aa6c80b821d84p-5, + -0x1.f656da1bb4949p-8, 0x1.ff0955ef45677p-4, 0x1.e817b87271261p-4, -0x1.354108452c2f4p-5, + -0x1.3fed94801e390p-4, -0x1.8fbcca0f3f2edp-4, -0x1.01cfc62f77eddp-4, 0x1.ba5aa39204dcfp-4, + 0x1.f97f9405f25dcp-4, 0x1.455767a74519ep-6, -0x1.a829fb8e3208fp-6, -0x1.f4e602d948e20p-4, + -0x1.ad2bcac610ba8p-4, 0x1.1734d672fc71ep-4, 0x1.9ef43f671e991p-4, 0x1.2bedb53235b0bp-4, + 0x1.04fb81c4052b2p-5, -0x1.ef1787e00c230p-4, -0x1.fce1613914e23p-4, 0x1.c3785d9ef4ecbp-7, + 0x1.d79777903be02p-5, 0x1.c678af42bfcc0p-4, 0x1.53282b829daeap-4, -0x1.7f8ecec492160p-4, + -0x1.dfeae7b3528f4p-4, -0x1.64c7e03a7bd28p-5, 0x1.921ca9f9ecec7p-10, 0x1.fff620c040a9bp-4, + 0x1.db65235f8ce8fp-4, -0x1.7c3a9226329ddp-5, -0x1.5c77bb8e6feeep-4, -0x1.771e749104036p-4, + -0x1.c1249d43449b3p-5, 0x1.cc1f11bf596a3p-4, 0x1.fe1caff4a8c1cp-4, 0x1.5f6d03bde5bb1p-7, + -0x1.1d344305b7173p-5, -0x1.ebbd889f14416p-4, -0x1.9777efc56425fp-4, 0x1.360589ed50a5ap-4, + 0x1.b3e4d79964851p-4, 0x1.0c970579e7f30p-4, 0x1.76dda6581bd33p-6, -0x1.f7599bf1dcd51p-4, + -0x1.f7599bf1dcd51p-4, 0x1.76dda6581bd33p-6, 0x1.0c970579e7f30p-4, 0x1.b3e4d79964851p-4, + 0x1.360589ed50a5ap-4, -0x1.9777efc56425fp-4, -0x1.ebbd889f14416p-4, -0x1.1d344305b7173p-5, + 0x1.5f6d03bde5bb1p-7, 0x1.fe1caff4a8c1cp-4, 0x1.cc1f11bf596a3p-4, -0x1.c1249d43449b3p-5, + -0x1.771e749104036p-4, -0x1.5c77bb8e6feeep-4, -0x1.7c3a9226329ddp-5, 0x1.db65235f8ce8fp-4, + 0x1.fff620c040a9bp-4, 0x1.921ca9f9ecec7p-10, -0x1.64c7e03a7bd28p-5, -0x1.dfeae7b3528f4p-4, + -0x1.7f8ecec492160p-4, 0x1.53282b829daeap-4, 0x1.c678af42bfcc0p-4, 0x1.d79777903be02p-5, + 0x1.c3785d9ef4ecbp-7, -0x1.fce1613914e23p-4, -0x1.ef1787e00c230p-4, 0x1.04fb81c4052b2p-5, + 0x1.2bedb53235b0bp-4, 0x1.9ef43f671e991p-4, 0x1.1734d672fc71ep-4, -0x1.ad2bcac610ba8p-4, + -0x1.f4e602d948e20p-4, -0x1.a829fb8e3208fp-6, 0x1.455767a74519ep-6, 0x1.f97f9405f25dcp-4, + 0x1.ba5aa39204dcfp-4, -0x1.01cfc62f77eddp-4, -0x1.8fbcca0f3f2edp-4, -0x1.3fed94801e390p-4, + -0x1.354108452c2f4p-5, 0x1.e817b87271261p-4, 0x1.ff0955ef45677p-4, -0x1.f656da1bb4949p-8, + -0x1.aa6c80b821d84p-5, -0x1.d17e794398714p-4, -0x1.659191aa71feep-4, 0x1.6e744546cd6b8p-4, + 0x1.d6961963c499fp-4, 0x1.9372a4f93f8fdp-5, 0x1.2d8676532fac9p-8, -0x1.ffa730b183c75p-4, + -0x1.e426a78279265p-4, 0x1.4d1e24965af58p-5, 0x1.49a4489b003d8p-4, 0x1.87c401bc9349ap-4, + 0x1.edc194e26b0bap-5, -0x1.c08c42eca3fe0p-4, -0x1.fb57964cae9cbp-4, -0x1.139f0a3e81d7cp-6, + 0x1.d934fddb1c68bp-6, 0x1.f2252c618314bp-4, 0x1.a63093641045dp-4, -0x1.21a79a324232dp-4, + -0x1.a63092dcc658ap-4, -0x1.21a79967a2a4ap-4, 0x1.d934fe233621fp-6, -0x1.f2252cf9eac1ep-4, + 0x1.fb5797a211ea0p-4, -0x1.139f09c2ca390p-6, 0x1.edc1974cd0da3p-5, 0x1.c08c43af583d3p-4, + -0x1.49a448e58507fp-4, 0x1.87c40054171c5p-4, -0x1.e426a66f47cfap-4, -0x1.4d1e258334820p-5, + -0x1.2d8678f6cda64p-8, -0x1.ffa731c8426afp-4, 0x1.d69617f556fa0p-4, -0x1.9372a503c6305p-5, + 0x1.659193ad01656p-4, 0x1.6e7444df80909p-4, -0x1.aa6c817471d82p-5, 0x1.d17e793a2b6dbp-4, + -0x1.ff0955e6ae6b2p-4, -0x1.f656d89b9b358p-8, -0x1.3541083d41568p-5, -0x1.e817b8e2111e0p-4, + 0x1.8fbcca59ead4cp-4, -0x1.3fed94412ae29p-4, 0x1.ba5aa26b1d333p-4, 0x1.01cfc68181635p-4, + -0x1.455767269a260p-6, 0x1.f97f93365047bp-4, -0x1.f4e602bdbe2a5p-4, 0x1.a829fc0ab090ap-6, + -0x1.1734d68a59b7ep-4, -0x1.ad2bc9be89947p-4, 0x1.2bedb45fbd051p-4, -0x1.9ef43f1985df6p-4, + 0x1.ef1788027609cp-4, 0x1.04fb81ef2299bp-5, 0x1.c3785b8330756p-7, 0x1.fce160115b04cp-4, + -0x1.c678b16488e70p-4, 0x1.d79778e34dd1fp-5, -0x1.7f8eceb332e42p-4, -0x1.53282b67ccf02p-4, + 0x1.64c7df9e56870p-5, -0x1.dfeae7ff0337cp-4, 0x1.fff62166c08fap-4, -0x1.921ca22110755p-10, + 0x1.7c3a934e5527dp-5, 0x1.db6522c4dfff5p-4, -0x1.771e744e84143p-4, 0x1.5c77bc7305d62p-4, + -0x1.cc1f1164ccc82p-4, -0x1.c1249e2a1eb6fp-5, 0x1.5f6d0429fe9b0p-7, -0x1.fe1cb007fcb1cp-4, + 0x1.ebbd8a2a6ffb1p-4, -0x1.1d3442f7b4b7fp-5, 0x1.360589e5ef747p-4, 0x1.9777eee148440p-4, + -0x1.0c9705da9a7bdp-4, 0x1.b3e4d77e311a2p-4, -0x1.f7599a6c672b7p-4, -0x1.76dda71c9efd4p-6, + -0x1.76dda71c9efd4p-6, -0x1.f7599a6c672b7p-4, 0x1.b3e4d77e311a2p-4, -0x1.0c9705da9a7bdp-4, + 0x1.9777eee148440p-4, 0x1.360589e5ef747p-4, -0x1.1d3442f7b4b7fp-5, 0x1.ebbd8a2a6ffb1p-4, + -0x1.fe1cb007fcb1cp-4, 0x1.5f6d0429fe9b0p-7, -0x1.c1249e2a1eb6fp-5, -0x1.cc1f1164ccc82p-4, + 0x1.5c77bc7305d62p-4, -0x1.771e744e84143p-4, 0x1.db6522c4dfff5p-4, 0x1.7c3a934e5527dp-5, + -0x1.921ca22110755p-10, 0x1.fff62166c08fap-4, -0x1.dfeae7ff0337cp-4, 0x1.64c7df9e56870p-5, + -0x1.53282b67ccf02p-4, -0x1.7f8eceb332e42p-4, 0x1.d79778e34dd1fp-5, -0x1.c678b16488e70p-4, + 0x1.fce160115b04cp-4, 0x1.c3785b8330756p-7, 0x1.04fb81ef2299bp-5, 0x1.ef1788027609cp-4, + -0x1.9ef43f1985df6p-4, 0x1.2bedb45fbd051p-4, -0x1.ad2bc9be89947p-4, -0x1.1734d68a59b7ep-4, + 0x1.a829fc0ab090ap-6, -0x1.f4e602bdbe2a5p-4, 0x1.f97f93365047bp-4, -0x1.455767269a260p-6, + 0x1.01cfc68181635p-4, 0x1.ba5aa26b1d333p-4, -0x1.3fed94412ae29p-4, 0x1.8fbcca59ead4cp-4, + -0x1.e817b8e2111e0p-4, -0x1.3541083d41568p-5, -0x1.f656d89b9b358p-8, -0x1.ff0955e6ae6b2p-4, + 0x1.d17e793a2b6dbp-4, -0x1.aa6c817471d82p-5, 0x1.6e7444df80909p-4, 0x1.659193ad01656p-4, + -0x1.9372a503c6305p-5, 0x1.d69617f556fa0p-4, -0x1.ffa731c8426afp-4, -0x1.2d8678f6cda64p-8, + -0x1.4d1e258334820p-5, -0x1.e426a66f47cfap-4, 0x1.87c40054171c5p-4, -0x1.49a448e58507fp-4, + 0x1.c08c43af583d3p-4, 0x1.edc1974cd0da3p-5, -0x1.139f09c2ca390p-6, 0x1.fb5797a211ea0p-4, + -0x1.f2252cf9eac1ep-4, 0x1.d934fe233621fp-6, -0x1.21a79967a2a4bp-4, -0x1.a63092dcc6587p-4, + -0x1.127c386cc058dp-4, 0x1.35ce38d23006fp-4, -0x1.064ae35196bb6p-5, 0x1.fd22055cc0111p-6, + 0x1.1fb086f174f98p-5, 0x1.f8f428ec37f22p-9, 0x1.8ac94e283c868p-5, 0x1.c60eb974a7861p-7, + -0x1.021ea3fef498ap-3, -0x1.8ba5cfa3fb56ep-3, -0x1.3b6cf722bbbd3p-5, -0x1.2c411ceeb9a09p-4, + -0x1.82c91489990efp-6, -0x1.c2c3dfd3ecd57p-4, -0x1.af807acb9972bp-5, -0x1.71213bfd8db3ap-4, + 0x1.c665254675fe0p-4, 0x1.1d50516c0ddd1p-4, -0x1.3b50c77b5b31dp-10, 0x1.529c9951b4befp-17, + -0x1.7f9d97df80d5ep-5, 0x1.1d7cd1fe2e29ap-5, 0x1.9db0e6d2f495dp-7, 0x1.0cf93b2da7daep-4, + 0x1.a76c182812094p-5, -0x1.49e5976f43d8bp-7, -0x1.da0b5d9717842p-4, -0x1.b054522fb32f4p-6, + 0x1.d98772645ebc3p-7, -0x1.31a0ed0bfa2f3p-4, 0x1.fe971b557f5b5p-6, 0x1.0d011b7b1635bp-6, + 0x1.82f6921858460p-4, 0x1.d13bef69d5439p-5, -0x1.192cbbc17dfd9p-3, -0x1.3c7198593fce2p-3, + -0x1.f564532a1fd31p-4, -0x1.ce8b0ac121afbp-7, -0x1.e770cb9312154p-5, -0x1.7e5b173049c29p-3, + -0x1.07b8fc038e245p-3, 0x1.e4ecba9d56a1bp-5, -0x1.843a2c5641ed3p-4, -0x1.4ad4cb7f9f2f5p-3, + -0x1.b7352c268ac0dp-4, 0x1.8387dad96c260p-5, -0x1.9f71614d8271cp-5, 0x1.907269cce7350p-6, + 0x1.8000da5fc850ap-6, -0x1.1ae0dca103a9ap-4, 0x1.b115501eeb0c5p-4, -0x1.dca05f9954633p-5, + -0x1.2cdb521f0777fp-4, 0x1.05e2aa89fe45fp-5, 0x1.919c424993d3fp-6, -0x1.fa62693043fdbp-4, + 0x1.02ffae947772dp-2, 0x1.826580e02c1f5p-6, -0x1.56add1ed0eb68p-5, -0x1.ecab813cbe179p-10, + 0x1.5c2b496fa9a9bp-4, 0x1.1ffdc435cc51ep-3, 0x1.7f78531237d39p-3, -0x1.5703c470921c6p-6, + -0x1.5703c470921c6p-6, 0x1.7f78531237d39p-3, 0x1.1ffdc435cc51ep-3, 0x1.5c2b496fa9a9bp-4, + -0x1.ecab813cbe179p-10, -0x1.56add1ed0eb68p-5, 0x1.826580e02c1f5p-6, 0x1.02ffae947772dp-2, + -0x1.fa62693043fdbp-4, 0x1.919c424993d3fp-6, 0x1.05e2aa89fe45fp-5, -0x1.2cdb521f0777fp-4, + -0x1.dca05f9954633p-5, 0x1.b115501eeb0c5p-4, -0x1.1ae0dca103a9ap-4, 0x1.8000da5fc850ap-6, + 0x1.907269cce7350p-6, -0x1.9f71614d8271cp-5, 0x1.8387dad96c260p-5, -0x1.b7352c268ac0dp-4, + -0x1.4ad4cb7f9f2f5p-3, -0x1.843a2c5641ed3p-4, 0x1.e4ecba9d56a1bp-5, -0x1.07b8fc038e245p-3, + -0x1.7e5b173049c29p-3, -0x1.e770cb9312154p-5, -0x1.ce8b0ac121afbp-7, -0x1.f564532a1fd31p-4, + -0x1.3c7198593fce2p-3, -0x1.192cbbc17dfd9p-3, 0x1.d13bef69d5439p-5, 0x1.82f6921858460p-4, + 0x1.0d011b7b1635bp-6, 0x1.fe971b557f5b5p-6, -0x1.31a0ed0bfa2f3p-4, 0x1.d98772645ebc3p-7, + -0x1.b054522fb32f4p-6, -0x1.da0b5d9717842p-4, -0x1.49e5976f43d8bp-7, 0x1.a76c182812094p-5, + 0x1.0cf93b2da7daep-4, 0x1.9db0e6d2f495dp-7, 0x1.1d7cd1fe2e29ap-5, -0x1.7f9d97df80d5ep-5, + 0x1.529c9951b4befp-17, -0x1.3b50c77b5b31dp-10, 0x1.1d50516c0ddd1p-4, 0x1.c665254675fe0p-4, + -0x1.71213bfd8db3ap-4, -0x1.af807acb9972bp-5, -0x1.c2c3dfd3ecd57p-4, -0x1.82c91489990efp-6, + -0x1.2c411ceeb9a09p-4, -0x1.3b6cf722bbbd3p-5, -0x1.8ba5cfa3fb56ep-3, -0x1.021ea3fef498ap-3, + 0x1.c60eb974a7866p-7, 0x1.8ac94e283c868p-5, 0x1.f8f428ec37e91p-9, 0x1.1fb086f174fa0p-5, + 0x1.fd22055cc0101p-6, -0x1.064ae35196bafp-5, 0x1.35ce37e2fe8c0p-4, -0x1.127c3865fce96p-4, + 0x1.ded9bd4b9211ap-6, -0x1.0761847bfb47dp-3, -0x1.9df5ec47debf8p-4, 0x1.0d9f8d0b23172p-6, + -0x1.4dcc43ada71c2p-7, -0x1.c83a223e9a945p-4, -0x1.be6034a9d7246p-4, 0x1.16cc63b1942f6p-8, + -0x1.a6713363ea893p-4, 0x1.8330cdfd7c3e7p-4, 0x1.daaab506beb16p-5, -0x1.d5a53d15e9088p-5, + 0x1.31c6ecab9c822p-3, 0x1.4bcf06a1b4d00p-7, -0x1.cbbe6f15304e8p-5, -0x1.0aa66c89f82ecp-4, + -0x1.e97748d4ff4a0p-5, -0x1.c907742e838b6p-3, 0x1.6a139b05f201dp-7, -0x1.500c0b2566a3ap-4, + -0x1.4102ed2b0cc3ep-7, -0x1.ddcad90a7311ep-6, 0x1.446f026489ddep-3, 0x1.768886bc9aa0fp-5, + -0x1.73b41d22feb91p-4, -0x1.5a14568808844p-3, -0x1.2776459128a00p-6, -0x1.54da56bf30e40p-3, + -0x1.7d33f66823735p-3, 0x1.3b835e51e85b7p-8, 0x1.2d49ca622d7a5p-8, 0x1.b3367985171adp-4, + 0x1.e3498f3d6d99ap-5, -0x1.b0831f5de1c46p-8, -0x1.1ffc836a4e784p-3, -0x1.0aea731dbbe9ap-5, + -0x1.13ee69fe97d89p-8, -0x1.f26ef99e9a06bp-7, 0x1.aa23fc1191ff1p-6, 0x1.0a502701e6dafp-5, + -0x1.8a04024b2a5ebp-6, 0x1.5f9672e8287e3p-3, -0x1.7d02ddbeac599p-7, 0x1.8b4d2988f4067p-7, + -0x1.1e52634d7fcdcp-3, -0x1.312c0a3915f2ap-6, 0x1.4da51013d93e2p-7, -0x1.89a713ad196a9p-4, + -0x1.f33cc433302cbp-4, -0x1.472946149bffcp-5, -0x1.6e5425f65aa13p-3, -0x1.3974dd5208094p-4, + -0x1.78226d34b2667p-6, 0x1.c8d09bf2051dep-8, 0x1.c3ad36a024724p-5, 0x1.38c5dbb3c76d0p-7, + -0x1.0453245dd21fcp-9, -0x1.df00e462d438cp-4, 0x1.94e2fb8109d1fp-4, 0x1.443afcfb58efep-4, + -0x1.59ad906a51fbdp-4, 0x1.ac374fbbffb96p-4, -0x1.c115d7b34d0b9p-6, 0x1.7af59cbb41c87p-7, + 0x1.7af59cbb41c87p-7, -0x1.c115d7b34d0b9p-6, 0x1.ac374fbbffb96p-4, -0x1.59ad906a51fbdp-4, + 0x1.443afcfb58efep-4, 0x1.94e2fb8109d1fp-4, -0x1.df00e462d438cp-4, -0x1.0453245dd21fcp-9, + 0x1.38c5dbb3c76d0p-7, 0x1.c3ad36a024724p-5, 0x1.c8d09bf2051dep-8, -0x1.78226d34b2667p-6, + -0x1.3974dd5208094p-4, -0x1.6e5425f65aa13p-3, -0x1.472946149bffcp-5, -0x1.f33cc433302cbp-4, + -0x1.89a713ad196a9p-4, 0x1.4da51013d93e2p-7, -0x1.312c0a3915f2ap-6, -0x1.1e52634d7fcdcp-3, + 0x1.8b4d2988f4067p-7, -0x1.7d02ddbeac599p-7, 0x1.5f9672e8287e3p-3, -0x1.8a04024b2a5ebp-6, + 0x1.0a502701e6dafp-5, 0x1.aa23fc1191ff1p-6, -0x1.f26ef99e9a06bp-7, -0x1.13ee69fe97d89p-8, + -0x1.0aea731dbbe9ap-5, -0x1.1ffc836a4e784p-3, -0x1.b0831f5de1c46p-8, 0x1.e3498f3d6d99ap-5, + 0x1.b3367985171adp-4, 0x1.2d49ca622d7a5p-8, 0x1.3b835e51e85b7p-8, -0x1.7d33f66823735p-3, + -0x1.54da56bf30e40p-3, -0x1.2776459128a00p-6, -0x1.5a14568808844p-3, -0x1.73b41d22feb91p-4, + 0x1.768886bc9aa0fp-5, 0x1.446f026489ddep-3, -0x1.ddcad90a7311ep-6, -0x1.4102ed2b0cc3ep-7, + -0x1.500c0b2566a3ap-4, 0x1.6a139b05f201dp-7, -0x1.c907742e838b6p-3, -0x1.e97748d4ff4a0p-5, + -0x1.0aa66c89f82ecp-4, -0x1.cbbe6f15304e8p-5, 0x1.4bcf06a1b4d00p-7, 0x1.31c6ecab9c822p-3, + -0x1.d5a53d15e9088p-5, 0x1.daaab506beb16p-5, 0x1.8330cdfd7c3e7p-4, -0x1.a6713363ea893p-4, + 0x1.16cc63b1942efp-8, -0x1.be6034a9d7246p-4, -0x1.c83a223e9a944p-4, -0x1.4dcc43ada718ep-7, + 0x1.0d9f8d0b2317ep-6, -0x1.9df5ec47debffp-4, -0x1.07618467a49e0p-3, 0x1.ded9c5cc33008p-6, + -0x1.1734d6812522dp-4, 0x1.ad2bc9d46fb6ep-4, 0x1.f97f8f1593c98p-4, 0x1.4557649238190p-6, + -0x1.04fb8066cd7cdp-5, -0x1.ef178b9cedff6p-4, -0x1.8fbcc976d3030p-4, 0x1.3fed966d5f902p-4, + 0x1.c678b4e085e09p-4, 0x1.d797759d2e74ep-5, 0x1.f656e41e20da1p-8, -0x1.ff09583fe38a7p-4, + -0x1.dfeae3466f6ecp-4, 0x1.64c7dcce40960p-5, 0x1.659194fa552efp-4, 0x1.6e744560e77dcp-4, + 0x1.7c3a949e6fdd0p-5, -0x1.db65272a91f01p-4, -0x1.ffa7315969c81p-4, 0x1.2d866c3a6f0a3p-8, + 0x1.c1249951bb0dap-5, 0x1.cc1f0dc7a119cp-4, 0x1.49a44a921be39p-4, -0x1.87c400e8cca02p-4, + -0x1.ebbd8d5e8db82p-4, -0x1.1d3443923ddd6p-5, 0x1.139f0f32d7940p-6, 0x1.fb579547d2999p-4, + 0x1.b3e4d2f613758p-4, -0x1.0c9706d54b168p-4, -0x1.a63093eecfd0cp-4, -0x1.21a7982ce563ep-4, + -0x1.76dda2c990df1p-6, 0x1.f75999cd95428p-4, 0x1.f2252d01316a3p-4, -0x1.d934f8232df2ep-6, + -0x1.36058a46151d8p-4, -0x1.9777ef3fc5fb0p-4, -0x1.edc19587691dcp-5, 0x1.c08c447dd9e0fp-4, + 0x1.fe1caf6206bb6p-4, 0x1.5f6cfde1fea73p-7, -0x1.4d1e23c446af3p-5, -0x1.e426a312c6aa3p-4, + -0x1.771e771e4ea3fp-4, 0x1.5c77bab46b597p-4, 0x1.d69617da99034p-4, 0x1.9372a689faf3dp-5, + -0x1.921d0f8011c9cp-10, -0x1.fff62319d6a8dp-4, -0x1.d17e74a9e6ecep-4, 0x1.aa6c7faeacd2bp-5, + 0x1.7f8ecd81ea3d0p-4, 0x1.53282a9d33973p-4, 0x1.3541082e9a560p-5, -0x1.e817bc34e61f9p-4, + -0x1.fce16068a46cdp-4, 0x1.c37862a2d3566p-7, 0x1.01cfc96488c75p-4, 0x1.ba5aa5edb034ep-4, + 0x1.2bedb193f3d1dp-4, -0x1.9ef43f46eba75p-4, -0x1.f4e60371502aap-4, -0x1.a82a061d37bd6p-6, + 0x1.a82a061d37bd6p-6, 0x1.f4e60371502aap-4, 0x1.9ef43f46eba75p-4, -0x1.2bedb193f3d1dp-4, + -0x1.ba5aa5edb034ep-4, -0x1.01cfc96488c75p-4, -0x1.c37862a2d3566p-7, 0x1.fce16068a46cdp-4, + 0x1.e817bc34e61f9p-4, -0x1.3541082e9a560p-5, -0x1.53282a9d33973p-4, -0x1.7f8ecd81ea3d0p-4, + -0x1.aa6c7faeacd2bp-5, 0x1.d17e74a9e6ecep-4, 0x1.fff62319d6a8dp-4, 0x1.921d0f8011c9cp-10, + -0x1.9372a689faf3dp-5, -0x1.d69617da99034p-4, -0x1.5c77bab46b597p-4, 0x1.771e771e4ea3fp-4, + 0x1.e426a312c6aa3p-4, 0x1.4d1e23c446af3p-5, -0x1.5f6cfde1fea73p-7, -0x1.fe1caf6206bb6p-4, + -0x1.c08c447dd9e0fp-4, 0x1.edc19587691dcp-5, 0x1.9777ef3fc5fb0p-4, 0x1.36058a46151d8p-4, + 0x1.d934f8232df2ep-6, -0x1.f2252d01316a3p-4, -0x1.f75999cd95428p-4, 0x1.76dda2c990df1p-6, + 0x1.21a7982ce563ep-4, 0x1.a63093eecfd0cp-4, 0x1.0c9706d54b168p-4, -0x1.b3e4d2f613758p-4, + -0x1.fb579547d2999p-4, -0x1.139f0f32d7940p-6, 0x1.1d3443923ddd6p-5, 0x1.ebbd8d5e8db82p-4, + 0x1.87c400e8cca02p-4, -0x1.49a44a921be39p-4, -0x1.cc1f0dc7a119cp-4, -0x1.c1249951bb0dap-5, + -0x1.2d866c3a6f0a3p-8, 0x1.ffa7315969c81p-4, 0x1.db65272a91f01p-4, -0x1.7c3a949e6fdd0p-5, + -0x1.6e744560e77dcp-4, -0x1.659194fa552efp-4, -0x1.64c7dcce40960p-5, 0x1.dfeae3466f6ecp-4, + 0x1.ff09583fe38a7p-4, -0x1.f656e41e20da1p-8, -0x1.d797759d2e74ep-5, -0x1.c678b4e085e09p-4, + -0x1.3fed966d5f902p-4, 0x1.8fbcc976d3030p-4, 0x1.ef178b9cedff6p-4, 0x1.04fb8066cd7cdp-5, + -0x1.4557649238190p-6, -0x1.f97f8f1593c98p-4, -0x1.ad2bc9d46fb6ep-4, 0x1.1734d68125218p-4, + -0x1.ad2bcb543e32bp-4, -0x1.1734d6837488ep-4, 0x1.4557664878eaep-6, -0x1.f97f8edd1190dp-4, + 0x1.ef178cade3fb8p-4, -0x1.04fb80acd24a5p-5, 0x1.3fed960ad0959p-4, 0x1.8fbccacfe5d79p-4, + -0x1.d79774f70df9ep-5, 0x1.c678b4bd92ab0p-4, -0x1.ff0958537f65ep-4, -0x1.f656e57cc3b60p-8, + -0x1.64c7dcea752c4p-5, -0x1.dfeae337e806fp-4, 0x1.6e7444e29f789p-4, -0x1.659193f97d0d3p-4, + 0x1.db65255f63f56p-4, 0x1.7c3a94348c78fp-5, 0x1.2d866a5516446p-8, 0x1.ffa72fb442f4bp-4, + -0x1.cc1f0d9e1ccaap-4, 0x1.c1249965ca11ep-5, -0x1.87c4016e4b117p-4, -0x1.49a44a45dbf10p-4, + 0x1.1d34432442975p-5, -0x1.ebbd8b3a4e7b5p-4, 0x1.fb57957c1722cp-4, -0x1.139f0f4fa4881p-6, + 0x1.0c9705eafe518p-4, 0x1.b3e4d59c785b5p-4, -0x1.21a798ff5f380p-4, 0x1.a630952174b16p-4, + -0x1.f759990222aa0p-4, -0x1.76dda226d81cep-6, -0x1.d934f5eb591f3p-6, -0x1.f2252b5ad82d9p-4, + 0x1.9777efdbd327bp-4, -0x1.36058b2a7dddcp-4, 0x1.c08c45185e889p-4, 0x1.edc1979bbd1aap-5, + -0x1.5f6cfda7f0573p-7, 0x1.fe1caf09f6d01p-4, -0x1.e426a36ecfe13p-4, 0x1.4d1e2458d9553p-5, + -0x1.5c77ba253a2fdp-4, -0x1.771e7892a75a0p-4, 0x1.9372a77422434p-5, -0x1.d69618bad90b5p-4, + 0x1.fff621b37bb6fp-4, -0x1.921d16a83e083p-10, 0x1.aa6c7e767dd32p-5, 0x1.d17e748506f6bp-4, + -0x1.532829ab41da7p-4, 0x1.7f8ecc9a14ebep-4, -0x1.e817bc396bc03p-4, -0x1.35410947bd5c6p-5, + -0x1.c37862bf95ebdp-7, -0x1.fce16020c71c9p-4, 0x1.ba5aa614e094dp-4, -0x1.01cfca496f75fp-4, + 0x1.9ef4410033c5ep-4, 0x1.2bedb21f73055p-4, -0x1.a82a04733a4dcp-6, 0x1.f4e6036bf83f8p-4, + -0x1.f4e6036bf83f8p-4, 0x1.a82a04733a4dcp-6, -0x1.2bedb21f73055p-4, -0x1.9ef4410033c5ep-4, + 0x1.01cfca496f75fp-4, -0x1.ba5aa614e094dp-4, 0x1.fce16020c71c9p-4, 0x1.c37862bf95ebdp-7, + 0x1.35410947bd5c6p-5, 0x1.e817bc396bc03p-4, -0x1.7f8ecc9a14ebep-4, 0x1.532829ab41da7p-4, + -0x1.d17e748506f6bp-4, -0x1.aa6c7e767dd32p-5, 0x1.921d16a83e083p-10, -0x1.fff621b37bb6fp-4, + 0x1.d69618bad90b5p-4, -0x1.9372a77422434p-5, 0x1.771e7892a75a0p-4, 0x1.5c77ba253a2fdp-4, + -0x1.4d1e2458d9553p-5, 0x1.e426a36ecfe13p-4, -0x1.fe1caf09f6d01p-4, 0x1.5f6cfda7f0573p-7, + -0x1.edc1979bbd1aap-5, -0x1.c08c45185e889p-4, 0x1.36058b2a7dddcp-4, -0x1.9777efdbd327bp-4, + 0x1.f2252b5ad82d9p-4, 0x1.d934f5eb591f3p-6, 0x1.76dda226d81cep-6, 0x1.f759990222aa0p-4, + -0x1.a630952174b16p-4, 0x1.21a798ff5f380p-4, -0x1.b3e4d59c785b5p-4, -0x1.0c9705eafe518p-4, + 0x1.139f0f4fa4881p-6, -0x1.fb57957c1722cp-4, 0x1.ebbd8b3a4e7b5p-4, -0x1.1d34432442975p-5, + 0x1.49a44a45dbf10p-4, 0x1.87c4016e4b117p-4, -0x1.c1249965ca11ep-5, 0x1.cc1f0d9e1ccaap-4, + -0x1.ffa72fb442f4bp-4, -0x1.2d866a5516446p-8, -0x1.7c3a94348c78fp-5, -0x1.db65255f63f56p-4, + 0x1.659193f97d0d3p-4, -0x1.6e7444e29f789p-4, 0x1.dfeae337e806fp-4, 0x1.64c7dcea752c4p-5, + 0x1.f656e57cc3b60p-8, 0x1.ff0958537f65ep-4, -0x1.c678b4bd92ab0p-4, 0x1.d79774f70df9ep-5, + -0x1.8fbccacfe5d79p-4, -0x1.3fed960ad0959p-4, 0x1.04fb80acd24a5p-5, -0x1.ef178cade3fb8p-4, + 0x1.f97f8edd1190dp-4, -0x1.4557664878eaep-6, 0x1.1734d68374897p-4, 0x1.ad2bcb543e327p-4, + -0x1.1fe85836f94dap-3, -0x1.1cb116a3d8131p-3, 0x1.2a6374b695f00p-8, 0x1.b17d490cc469fp-3, + 0x1.24bcb769f4479p-4, -0x1.4e131734e6398p-9, 0x1.11cb121bbce2ap-12, 0x1.571d38a22c566p-4, + -0x1.8f6dc5c1efe0dp-7, 0x1.121d8fcb28d5bp-4, 0x1.245408b82223dp-10, 0x1.d61b17abc6052p-8, + 0x1.b1c2efb6e19e7p-6, 0x1.74b750ad7a801p-3, 0x1.e7895e9a47246p-4, 0x1.ba40036fd1aefp-4, + -0x1.db008fc15f534p-4, 0x1.f80557112b7fdp-8, -0x1.6b49c8842e86ap-12, -0x1.1706c4ec80716p-4, + -0x1.7a6dd4deeb284p-6, -0x1.33a65dcb7a710p-6, 0x1.bcc9d37ffe8c6p-4, 0x1.fa23c89adca90p-5, + -0x1.0a9149bd11180p-9, 0x1.313ab82979b60p-4, 0x1.ff7cd14c8537cp-5, -0x1.3ba52782174d3p-8, + -0x1.7b666a5aebd55p-4, 0x1.9cb15a5a3e814p-3, -0x1.a6e962c334c3fp-5, 0x1.a3462dff9856ap-3, + 0x1.221ae693a0568p-3, -0x1.c0f34be10c26ep-10, 0x1.be82feb9d8b77p-5, 0x1.84ab98f048978p-6, + -0x1.7adbb788e62a2p-5, -0x1.d39f4072dc491p-4, 0x1.4a0c232eecef3p-3, 0x1.06ee2a9cb7ccep-4, + 0x1.4a07101c653fbp-7, -0x1.92dbf92d68921p-3, -0x1.8fbc785a25ac0p-3, 0x1.35ccdc1c01bdcp-5, + 0x1.4e27de299054dp-4, -0x1.5a5f6e5875466p-5, -0x1.51629af4ab9b8p-8, -0x1.2771e647017fep-4, + 0x1.d3fd0121e12e6p-7, -0x1.6ee2da2473d94p-9, -0x1.5efee934a91edp-6, 0x1.4809ec1012cf3p-4, + 0x1.abbc31183b2f1p-4, 0x1.ef410dc25233fp-5, 0x1.694c91726f91ep-6, -0x1.8474701feda4dp-8, + 0x1.3ca01b87f936bp-9, 0x1.87c9a81e1f802p-4, -0x1.4a9c0964e7f1ap-5, -0x1.2015481366b97p-4, + -0x1.76fc880bc7c3ap-6, -0x1.082ac03747b6ep-7, 0x1.6e31a1d470b74p-5, -0x1.488080b71d70ap-6, + 0x1.488080b71d70ap-6, -0x1.6e31a1d470b74p-5, 0x1.082ac03747b6ep-7, 0x1.76fc880bc7c3ap-6, + 0x1.2015481366b97p-4, 0x1.4a9c0964e7f1ap-5, -0x1.87c9a81e1f802p-4, -0x1.3ca01b87f936bp-9, + 0x1.8474701feda4dp-8, -0x1.694c91726f91ep-6, -0x1.ef410dc25233fp-5, -0x1.abbc31183b2f1p-4, + -0x1.4809ec1012cf3p-4, 0x1.5efee934a91edp-6, 0x1.6ee2da2473d94p-9, -0x1.d3fd0121e12e6p-7, + 0x1.2771e647017fep-4, 0x1.51629af4ab9b8p-8, 0x1.5a5f6e5875466p-5, -0x1.4e27de299054dp-4, + -0x1.35ccdc1c01bdcp-5, 0x1.8fbc785a25ac0p-3, 0x1.92dbf92d68921p-3, -0x1.4a07101c653fbp-7, + -0x1.06ee2a9cb7ccep-4, -0x1.4a0c232eecef3p-3, 0x1.d39f4072dc491p-4, 0x1.7adbb788e62a2p-5, + -0x1.84ab98f048978p-6, -0x1.be82feb9d8b77p-5, 0x1.c0f34be10c26ep-10, -0x1.221ae693a0568p-3, + -0x1.a3462dff9856ap-3, 0x1.a6e962c334c3fp-5, -0x1.9cb15a5a3e814p-3, 0x1.7b666a5aebd55p-4, + 0x1.3ba52782174d3p-8, -0x1.ff7cd14c8537cp-5, -0x1.313ab82979b60p-4, 0x1.0a9149bd11180p-9, + -0x1.fa23c89adca90p-5, -0x1.bcc9d37ffe8c6p-4, 0x1.33a65dcb7a710p-6, 0x1.7a6dd4deeb284p-6, + 0x1.1706c4ec80716p-4, 0x1.6b49c8842e86ap-12, -0x1.f80557112b7fdp-8, 0x1.db008fc15f534p-4, + -0x1.ba40036fd1aefp-4, -0x1.e7895e9a47246p-4, -0x1.74b750ad7a801p-3, -0x1.b1c2efb6e19e7p-6, + -0x1.d61b17abc6052p-8, -0x1.245408b82223dp-10, -0x1.121d8fcb28d5bp-4, 0x1.8f6dc5c1efe0dp-7, + -0x1.571d38a22c566p-4, -0x1.11cb121bbce29p-12, 0x1.4e131734e642ap-9, -0x1.24bcb769f4471p-4, + -0x1.b17d490cc469bp-3, -0x1.2a6374b695edbp-8, 0x1.1cb1168fd6c43p-3, 0x1.1fe858241df56p-3, + -0x1.4a5adad11cc7dp-6, -0x1.f0f0d8951fc16p-8, -0x1.32197f51b53c4p-5, 0x1.15c1242841396p-4, + 0x1.a09c0a7bb01b1p-6, -0x1.3902626409795p-8, -0x1.5d5bcefbda3bfp-4, 0x1.7fee90acdeec1p-5, + 0x1.0c8d309727f31p-5, 0x1.958f309cec8d6p-4, 0x1.163ba6fbeb869p-6, -0x1.0149fdb433e13p-6, + -0x1.c5466ec31c093p-3, 0x1.09e66ae6ed19cp-4, -0x1.d040b87c88408p-4, -0x1.c910c82f4cda2p-3, + -0x1.7ccdec62a81b6p-4, 0x1.09391d89ca84cp-5, 0x1.6baf2f7ca9b14p-5, -0x1.7b3e79d5254bdp-5, + -0x1.6a1f12f3d7f72p-4, 0x1.bbe8aaebbc295p-4, 0x1.2b370d2a3741ep-9, -0x1.6c71c3d04564bp-3, + 0x1.30ae8b97d332ap-3, 0x1.170a15997850cp-8, 0x1.534921fa92ef2p-6, -0x1.0b90f9af68409p-2, + 0x1.9644db5b08ef3p-3, 0x1.22ff8d3cf687cp-7, -0x1.14d92630cfdf7p-4, -0x1.de722321a7cefp-5, + 0x1.749abbf2e7c3cp-4, 0x1.44753c8cc02fap-3, -0x1.6934160ec2341p-4, 0x1.d29575b72420ap-4, + -0x1.43d59c1d96f36p-8, -0x1.a40592ae5db5ap-5, -0x1.33e18f2d44e79p-6, -0x1.3364c178df567p-8, + -0x1.5194c32fb17f0p-4, -0x1.204fa62d3a3ebp-4, -0x1.2d001348ecd27p-5, -0x1.24e61f5c94c7dp-4, + -0x1.6bb0132853acfp-6, 0x1.28fdd29b68829p-5, -0x1.a54b641bbf1e1p-9, 0x1.f3e35b9b8f73dp-5, + -0x1.f79ef401b34c7p-6, 0x1.6830182700a26p-5, 0x1.e1f79aa9eb58bp-4, 0x1.57de8c1fcf938p-5, + -0x1.593b867be0c41p-5, 0x1.6b04feb0f9d79p-8, 0x1.253891b3a8828p-5, 0x1.eea755e198d32p-4, + 0x1.aa2a784ce15cbp-4, 0x1.359c248395ae1p-5, 0x1.8cb6f87a7b554p-7, 0x1.25ed1e343d8c9p-6, + -0x1.617608b488d46p-5, -0x1.11e812ffdd840p-3, -0x1.73d019429bae3p-5, 0x1.1fc165bc13db0p-5, + -0x1.1fc165bc13db0p-5, 0x1.73d019429bae3p-5, 0x1.11e812ffdd840p-3, 0x1.617608b488d46p-5, + -0x1.25ed1e343d8c9p-6, -0x1.8cb6f87a7b554p-7, -0x1.359c248395ae1p-5, -0x1.aa2a784ce15cbp-4, + -0x1.eea755e198d32p-4, -0x1.253891b3a8828p-5, -0x1.6b04feb0f9d79p-8, 0x1.593b867be0c41p-5, + -0x1.57de8c1fcf938p-5, -0x1.e1f79aa9eb58bp-4, -0x1.6830182700a26p-5, 0x1.f79ef401b34c7p-6, + -0x1.f3e35b9b8f73dp-5, 0x1.a54b641bbf1e1p-9, -0x1.28fdd29b68829p-5, 0x1.6bb0132853acfp-6, + 0x1.24e61f5c94c7dp-4, 0x1.2d001348ecd27p-5, 0x1.204fa62d3a3ebp-4, 0x1.5194c32fb17f0p-4, + 0x1.3364c178df567p-8, 0x1.33e18f2d44e79p-6, 0x1.a40592ae5db5ap-5, 0x1.43d59c1d96f36p-8, + -0x1.d29575b72420ap-4, 0x1.6934160ec2341p-4, -0x1.44753c8cc02fap-3, -0x1.749abbf2e7c3cp-4, + 0x1.de722321a7cefp-5, 0x1.14d92630cfdf7p-4, -0x1.22ff8d3cf687cp-7, -0x1.9644db5b08ef3p-3, + 0x1.0b90f9af68409p-2, -0x1.534921fa92ef2p-6, -0x1.170a15997850cp-8, -0x1.30ae8b97d332ap-3, + 0x1.6c71c3d04564bp-3, -0x1.2b370d2a3741ep-9, -0x1.bbe8aaebbc295p-4, 0x1.6a1f12f3d7f72p-4, + 0x1.7b3e79d5254bdp-5, -0x1.6baf2f7ca9b14p-5, -0x1.09391d89ca84cp-5, 0x1.7ccdec62a81b6p-4, + 0x1.c910c82f4cda2p-3, 0x1.d040b87c88408p-4, -0x1.09e66ae6ed19cp-4, 0x1.c5466ec31c093p-3, + 0x1.0149fdb433e13p-6, -0x1.163ba6fbeb869p-6, -0x1.958f309cec8d6p-4, -0x1.0c8d309727f31p-5, + -0x1.7fee90acdeec3p-5, 0x1.5d5bcefbda3bfp-4, 0x1.390262640979fp-8, -0x1.a09c0a7bb01a2p-6, + -0x1.15c1242841391p-4, 0x1.32197f51b53c4p-5, 0x1.f0f0d740623c5p-8, 0x1.4a5adb3f6ee67p-6, + -0x1.0c9706e640adfp-4, 0x1.b3e4d5181c48ep-4, 0x1.fe1cab1edaa32p-4, 0x1.5f6ceb015f89ep-7, + -0x1.7c3a91caafb1ep-5, -0x1.db652701edfd7p-4, -0x1.5328272601cb1p-4, 0x1.7f8ed0e6c2a77p-4, + 0x1.ef178a82bbdc0p-4, 0x1.04fb852aae5cap-5, -0x1.a82a1191fccb1p-6, -0x1.f4e6054b773dfp-4, + -0x1.8fbccd42d7615p-4, 0x1.3fed93c6138aap-4, 0x1.d17e776403697p-4, 0x1.aa6c87e399b50p-5, + -0x1.2d86286e57a5ep-8, -0x1.ffa72fbd0b6d9p-4, -0x1.c08c4034872f9p-4, 0x1.edc198cb8e658p-5, + 0x1.a630918ec246cp-4, 0x1.21a79bfa70063p-4, 0x1.139f05af3bbf5p-6, -0x1.fb5796d72033ap-4, + -0x1.e426a3a154e98p-4, 0x1.4d1e25512485dp-5, 0x1.6e7448ffa9896p-4, 0x1.659190bd366d5p-4, + 0x1.35410cf620acbp-5, -0x1.e817bb03f838cp-4, -0x1.f97f91f634478p-4, 0x1.45576de8be80ap-6, + 0x1.2bedb12453153p-4, 0x1.9ef4410e6d42cp-4, 0x1.d79775ad6e8e1p-5, -0x1.c678b26e0d78cp-4, + -0x1.fff61cc2a8cc3p-4, -0x1.921d9f5d0a2b5p-10, 0x1.c1249e0ae2a93p-5, 0x1.cc1f11e2e1b0cp-4, + 0x1.360588c3aeddcp-4, -0x1.9777ee670eb4dp-4, -0x1.f7599b62de029p-4, -0x1.76dd98dda1e37p-6, + 0x1.1d3441033ab54p-5, 0x1.ebbd8c4c4f565p-4, 0x1.771e74dda962bp-4, -0x1.5c77bbb848a6bp-4, + -0x1.dfeae2b5cadf4p-4, -0x1.64c7dceaf85edp-5, 0x1.c37863b658f8ap-7, 0x1.fce16105d626dp-4, + 0x1.ad2bcd2ded60ap-4, -0x1.1734d5f92a268p-4, -0x1.ba5aa88f8ddedp-4, -0x1.01cfc999bd84dp-4, + -0x1.f656d726319b5p-8, 0x1.ff09530fc7567p-4, 0x1.d69614c97e617p-4, -0x1.9372a4e9d3040p-5, + -0x1.87c4024ac7a23p-4, -0x1.49a44a88c423fp-4, -0x1.d934fd75af69cp-6, 0x1.f225302e69129p-4, + 0x1.f225302e69129p-4, -0x1.d934fd75af69cp-6, -0x1.49a44a88c423fp-4, -0x1.87c4024ac7a23p-4, + -0x1.9372a4e9d3040p-5, 0x1.d69614c97e617p-4, 0x1.ff09530fc7567p-4, -0x1.f656d726319b5p-8, + -0x1.01cfc999bd84dp-4, -0x1.ba5aa88f8ddedp-4, -0x1.1734d5f92a268p-4, 0x1.ad2bcd2ded60ap-4, + 0x1.fce16105d626dp-4, 0x1.c37863b658f8ap-7, -0x1.64c7dceaf85edp-5, -0x1.dfeae2b5cadf4p-4, + -0x1.5c77bbb848a6bp-4, 0x1.771e74dda962bp-4, 0x1.ebbd8c4c4f565p-4, 0x1.1d3441033ab54p-5, + -0x1.76dd98dda1e37p-6, -0x1.f7599b62de029p-4, -0x1.9777ee670eb4dp-4, 0x1.360588c3aeddcp-4, + 0x1.cc1f11e2e1b0cp-4, 0x1.c1249e0ae2a93p-5, -0x1.921d9f5d0a2b5p-10, -0x1.fff61cc2a8cc3p-4, + -0x1.c678b26e0d78cp-4, 0x1.d79775ad6e8e1p-5, 0x1.9ef4410e6d42cp-4, 0x1.2bedb12453153p-4, + 0x1.45576de8be80ap-6, -0x1.f97f91f634478p-4, -0x1.e817bb03f838cp-4, 0x1.35410cf620acbp-5, + 0x1.659190bd366d5p-4, 0x1.6e7448ffa9896p-4, 0x1.4d1e25512485dp-5, -0x1.e426a3a154e98p-4, + -0x1.fb5796d72033ap-4, 0x1.139f05af3bbf5p-6, 0x1.21a79bfa70063p-4, 0x1.a630918ec246cp-4, + 0x1.edc198cb8e658p-5, -0x1.c08c4034872f9p-4, -0x1.ffa72fbd0b6d9p-4, -0x1.2d86286e57a5ep-8, + 0x1.aa6c87e399b50p-5, 0x1.d17e776403697p-4, 0x1.3fed93c6138aap-4, -0x1.8fbccd42d7615p-4, + -0x1.f4e6054b773dfp-4, -0x1.a82a1191fccb1p-6, 0x1.04fb852aae5cap-5, 0x1.ef178a82bbdc0p-4, + 0x1.7f8ed0e6c2a77p-4, -0x1.5328272601cb1p-4, -0x1.db652701edfd7p-4, -0x1.7c3a91caafb1ep-5, + 0x1.5f6ceb015f89ep-7, 0x1.fe1cab1edaa32p-4, 0x1.b3e4d5181c48ep-4, -0x1.0c9706e640afbp-4, + -0x1.b3e4d471a1dd1p-4, -0x1.0c9705eb9b02ap-4, 0x1.5f6ce9e8d60fap-7, -0x1.fe1cac09002e6p-4, + 0x1.db6526d8b26cfp-4, -0x1.7c3a915da4d3fp-5, 0x1.7f8ecffa46e15p-4, 0x1.5328275e9e328p-4, + -0x1.04fb86058c363p-5, 0x1.ef178a83582a8p-4, -0x1.f4e605434739cp-4, 0x1.a82a132644a76p-6, + -0x1.3fed92edf2ecbp-4, -0x1.8fbccbf1440e6p-4, 0x1.aa6c887fba970p-5, -0x1.d17e777c81fe3p-4, + 0x1.ffa72f262ab3dp-4, -0x1.2d8623f5c449dp-8, 0x1.edc1995c88bc1p-5, 0x1.c08c404330656p-4, + -0x1.21a79ce6e01d3p-4, 0x1.a63092bd0badfp-4, -0x1.fb5795e8ba648p-4, -0x1.139f05eac4ff4p-6, + -0x1.4d1e249abef86p-5, -0x1.e426a2cf07fa2p-4, 0x1.659191225d023p-4, -0x1.6e7448279e7d0p-4, + 0x1.e817b8a1400eep-4, 0x1.35410ce7a9b75p-5, 0x1.45576f3be4d8ap-6, 0x1.f97f9205daad2p-4, + -0x1.9ef44087ff225p-4, 0x1.2bedb1883b45dp-4, -0x1.c678b1ab54dcap-4, -0x1.d79775f376845p-5, + 0x1.921dafae11871p-10, -0x1.fff61e8397e0cp-4, 0x1.cc1f132972be7p-4, -0x1.c1249c63ef78ap-5, + 0x1.9777ee3c190d7p-4, 0x1.3605891c7eebbp-4, -0x1.76dd98928de7ap-6, 0x1.f7599c4d20421p-4, + -0x1.ebbd8d732bfdcp-4, 0x1.1d34413853585p-5, -0x1.5c77bd4e431e0p-4, -0x1.771e75e9a315ep-4, + 0x1.64c7ddac62826p-5, -0x1.dfeae2e3e215ap-4, 0x1.fce15fb3ae5f4p-4, -0x1.c3786470ef33bp-7, + 0x1.1734d5e6e8a5dp-4, 0x1.ad2bce06e65cbp-4, -0x1.01cfc935491e6p-4, 0x1.ba5aa86afd446p-4, + -0x1.ff09535ef7b61p-4, -0x1.f656daf89324ap-8, -0x1.9372a4fe35723p-5, -0x1.d69615ae9784fp-4, + 0x1.49a44a7e6b39fp-4, -0x1.87c4024465407p-4, 0x1.f2252f4ffc8cap-4, 0x1.d934fe5433734p-6, + 0x1.d934fe5433734p-6, 0x1.f2252f4ffc8cap-4, -0x1.87c4024465407p-4, 0x1.49a44a7e6b39fp-4, + -0x1.d69615ae9784fp-4, -0x1.9372a4fe35723p-5, -0x1.f656daf89324ap-8, -0x1.ff09535ef7b61p-4, + 0x1.ba5aa86afd446p-4, -0x1.01cfc935491e6p-4, 0x1.ad2bce06e65cbp-4, 0x1.1734d5e6e8a5dp-4, + -0x1.c3786470ef33bp-7, 0x1.fce15fb3ae5f4p-4, -0x1.dfeae2e3e215ap-4, 0x1.64c7ddac62826p-5, + -0x1.771e75e9a315ep-4, -0x1.5c77bd4e431e0p-4, 0x1.1d34413853585p-5, -0x1.ebbd8d732bfdcp-4, + 0x1.f7599c4d20421p-4, -0x1.76dd98928de7ap-6, 0x1.3605891c7eebbp-4, 0x1.9777ee3c190d7p-4, + -0x1.c1249c63ef78ap-5, 0x1.cc1f132972be7p-4, -0x1.fff61e8397e0cp-4, 0x1.921dafae11871p-10, + -0x1.d79775f376845p-5, -0x1.c678b1ab54dcap-4, 0x1.2bedb1883b45dp-4, -0x1.9ef44087ff225p-4, + 0x1.f97f9205daad2p-4, 0x1.45576f3be4d8ap-6, 0x1.35410ce7a9b75p-5, 0x1.e817b8a1400eep-4, + -0x1.6e7448279e7d0p-4, 0x1.659191225d023p-4, -0x1.e426a2cf07fa2p-4, -0x1.4d1e249abef86p-5, + -0x1.139f05eac4ff4p-6, -0x1.fb5795e8ba648p-4, 0x1.a63092bd0badfp-4, -0x1.21a79ce6e01d3p-4, + 0x1.c08c404330656p-4, 0x1.edc1995c88bc1p-5, -0x1.2d8623f5c449dp-8, 0x1.ffa72f262ab3dp-4, + -0x1.d17e777c81fe3p-4, 0x1.aa6c887fba970p-5, -0x1.8fbccbf1440e6p-4, -0x1.3fed92edf2ecbp-4, + 0x1.a82a132644a76p-6, -0x1.f4e605434739cp-4, 0x1.ef178a83582a8p-4, -0x1.04fb86058c363p-5, + 0x1.5328275e9e328p-4, 0x1.7f8ecffa46e15p-4, -0x1.7c3a915da4d3fp-5, 0x1.db6526d8b26cfp-4, + -0x1.fe1cac09002e6p-4, 0x1.5f6ce9e8d60fap-7, -0x1.0c9705eb9b012p-4, -0x1.b3e4d471a1dd1p-4, + 0x1.6c3b8876c39e4p-3, 0x1.1d2fd927422e3p-6, 0x1.307c2508837a8p-8, 0x1.c8b0bb51e4134p-5, + 0x1.b964fb8d63717p-4, -0x1.71277e53455fep-7, 0x1.0a1bdc4bc3519p-6, -0x1.43669a94fa049p-7, + -0x1.38a1b2e6490f6p-6, -0x1.02dcdd1440a73p-8, -0x1.fce028b832b74p-5, 0x1.4e2456c39fb1ap-7, + 0x1.adf4b4a98e26ap-5, -0x1.a45da3f6ca3fbp-6, 0x1.b9656c7f5f26fp-6, 0x1.4bb523a9a5087p-5, + -0x1.2023dfc76447cp-3, 0x1.912c28d7160e6p-9, 0x1.8e8d839f1f53fp-9, 0x1.f76219288cd22p-6, + -0x1.8c9b9f27dffdfp-7, 0x1.468da7a83d9ecp-3, 0x1.9082fe5da7af7p-3, -0x1.8e3db15e7a0d0p-6, + 0x1.6620544dd3314p-5, 0x1.2f9e43b809796p-4, -0x1.5ec05281ff330p-12, -0x1.05cebeac48a8ap-4, + -0x1.2fb14d325af2fp-4, -0x1.52cf2b3029bd1p-5, 0x1.f5e5aafa0b5a0p-6, -0x1.040c7e2dddeb2p-3, + 0x1.4e2aa337f6c4dp-7, -0x1.cb240f5da0685p-7, 0x1.03a637ec2b7afp-5, -0x1.75e4f3ceeec6cp-4, + 0x1.eb47c1e262e1dp-8, 0x1.69594fb28f00ep-9, 0x1.e998548ff000ap-3, 0x1.b64110537709fp-5, + 0x1.cb1dc34bd35d6p-4, 0x1.5f111a6d531d8p-4, 0x1.55c283eb652edp-5, 0x1.cfb6beffa2d0ep-3, + -0x1.8ce481460e30dp-3, 0x1.48e3bcc8be8edp-5, -0x1.52a0a0e391c96p-3, -0x1.bf259d2fba2cap-5, + 0x1.39d7ad0898b5dp-5, 0x1.a3675660cf2bdp-4, -0x1.8f81630f4480ep-4, 0x1.a324048b64140p-7, + -0x1.85d01cdae8032p-9, -0x1.8430325eb717dp-6, -0x1.05efa3a113d67p-4, 0x1.ccf869b0a0bafp-4, + 0x1.4ea982cf7677ap-4, 0x1.180552d08db8dp-7, 0x1.81e0b9e7db82ap-6, 0x1.bcbee68290c93p-5, + 0x1.64fd6c86fab1ep-6, -0x1.3dd673e73ab07p-6, -0x1.e7dfdc31aa7aap-3, 0x1.b6d10c472e2d9p-5, + 0x1.b6d10c472e2d9p-5, -0x1.e7dfdc31aa7aap-3, -0x1.3dd673e73ab07p-6, 0x1.64fd6c86fab1ep-6, + 0x1.bcbee68290c93p-5, 0x1.81e0b9e7db82ap-6, 0x1.180552d08db8dp-7, 0x1.4ea982cf7677ap-4, + 0x1.ccf869b0a0bafp-4, -0x1.05efa3a113d67p-4, -0x1.8430325eb717dp-6, -0x1.85d01cdae8032p-9, + 0x1.a324048b64140p-7, -0x1.8f81630f4480ep-4, 0x1.a3675660cf2bdp-4, 0x1.39d7ad0898b5dp-5, + -0x1.bf259d2fba2cap-5, -0x1.52a0a0e391c96p-3, 0x1.48e3bcc8be8edp-5, -0x1.8ce481460e30dp-3, + 0x1.cfb6beffa2d0ep-3, 0x1.55c283eb652edp-5, 0x1.5f111a6d531d8p-4, 0x1.cb1dc34bd35d6p-4, + 0x1.b64110537709fp-5, 0x1.e998548ff000ap-3, 0x1.69594fb28f00ep-9, 0x1.eb47c1e262e1dp-8, + -0x1.75e4f3ceeec6cp-4, 0x1.03a637ec2b7afp-5, -0x1.cb240f5da0685p-7, 0x1.4e2aa337f6c4dp-7, + -0x1.040c7e2dddeb2p-3, 0x1.f5e5aafa0b5a0p-6, -0x1.52cf2b3029bd1p-5, -0x1.2fb14d325af2fp-4, + -0x1.05cebeac48a8ap-4, -0x1.5ec05281ff330p-12, 0x1.2f9e43b809796p-4, 0x1.6620544dd3314p-5, + -0x1.8e3db15e7a0d0p-6, 0x1.9082fe5da7af7p-3, 0x1.468da7a83d9ecp-3, -0x1.8c9b9f27dffdfp-7, + 0x1.f76219288cd22p-6, 0x1.8e8d839f1f53fp-9, 0x1.912c28d7160e6p-9, -0x1.2023dfc76447cp-3, + 0x1.4bb523a9a5087p-5, 0x1.b9656c7f5f26fp-6, -0x1.a45da3f6ca3fbp-6, 0x1.adf4b4a98e26ap-5, + 0x1.4e2456c39fb1ap-7, -0x1.fce028b832b74p-5, -0x1.02dcdd1440a73p-8, -0x1.38a1b2e6490f6p-6, + -0x1.43669a94fa04ap-7, 0x1.0a1bdc4bc3519p-6, -0x1.71277e5345608p-7, 0x1.b964fb8d63717p-4, + 0x1.c8b0bb51e412bp-5, 0x1.307c2508837a7p-8, 0x1.1d2fddad471bap-6, 0x1.6c3b8891cab67p-3, + 0x1.096614e85bd3dp-3, 0x1.09c991613a283p-5, -0x1.6ab00094d7d28p-6, 0x1.41321a8282350p-7, + 0x1.a6c2effc5723ep-5, 0x1.674844fab97abp-3, -0x1.0e8f8abe2e59ep-3, -0x1.8bcecf7867749p-6, + -0x1.446545917e3c9p-3, 0x1.127789b55ac8fp-7, -0x1.9d61a573aaf06p-6, -0x1.249e8014d6149p-3, + 0x1.e60c0a58a1841p-7, 0x1.fa13cd33465cfp-6, 0x1.0572d96aa3011p-2, 0x1.7ce496f90ca2ap-4, + 0x1.1565f7367f7bcp-7, 0x1.192b71761a0abp-3, 0x1.ef5081eb0ca14p-4, 0x1.7950eff2015c2p-4, + 0x1.27d9669d3f09dp-5, -0x1.31441a87aad90p-7, 0x1.23c9b6ccfd614p-7, 0x1.c502abe2c6b1ap-4, + -0x1.bc3232dd7d8b6p-3, -0x1.a8aa0938c41b4p-6, 0x1.366451e4af0b7p-8, 0x1.1e14c43301881p-4, + -0x1.028ecf8c46f5ep-6, 0x1.86b6038ff95cdp-4, -0x1.24001b6eea9a1p-3, 0x1.3ebe68312ab90p-6, + 0x1.0ee9eea626c13p-6, -0x1.a254faecb22e3p-4, 0x1.93eca58aee857p-6, 0x1.5163772e7890fp-6, + -0x1.ee5fcb1bb176fp-4, -0x1.11d8461edf3f8p-6, -0x1.00d7b8b68e49cp-7, 0x1.62f7b09911230p-4, + 0x1.64d034c58f2cep-10, 0x1.1329d4aeb6bf6p-11, -0x1.091a22b622429p-3, -0x1.d4c3d3be2eec2p-6, + -0x1.f4c7a947bb24dp-8, 0x1.11d5e71fd176bp-3, 0x1.92fdee076137cp-8, 0x1.6c382e19017acp-8, + 0x1.dac6045c546d4p-9, -0x1.3e69bbc50272ep-5, 0x1.85ad1d6418125p-6, -0x1.d445752fb3d0fp-3, + 0x1.738ea67a2b266p-5, 0x1.7d162e5cf62ddp-5, 0x1.f46c6d71ee40bp-5, -0x1.32a1468c26e5fp-5, + -0x1.c23409ef412f5p-9, -0x1.d6d7586eb1260p-5, -0x1.014b0b24c90a9p-4, 0x1.3d72e13a7f294p-7, + 0x1.38fd7b2d680fep-3, -0x1.60532c205da03p-5, -0x1.3cda9ee4ae8e2p-5, -0x1.bd2102f243456p-5, + -0x1.bd2102f243456p-5, -0x1.3cda9ee4ae8e2p-5, -0x1.60532c205da03p-5, 0x1.38fd7b2d680fep-3, + 0x1.3d72e13a7f294p-7, -0x1.014b0b24c90a9p-4, -0x1.d6d7586eb1260p-5, -0x1.c23409ef412f5p-9, + -0x1.32a1468c26e5fp-5, 0x1.f46c6d71ee40bp-5, 0x1.7d162e5cf62ddp-5, 0x1.738ea67a2b266p-5, + -0x1.d445752fb3d0fp-3, 0x1.85ad1d6418125p-6, -0x1.3e69bbc50272ep-5, 0x1.dac6045c546d4p-9, + 0x1.6c382e19017acp-8, 0x1.92fdee076137cp-8, 0x1.11d5e71fd176bp-3, -0x1.f4c7a947bb24dp-8, + -0x1.d4c3d3be2eec2p-6, -0x1.091a22b622429p-3, 0x1.1329d4aeb6bf6p-11, 0x1.64d034c58f2cep-10, + 0x1.62f7b09911230p-4, -0x1.00d7b8b68e49cp-7, -0x1.11d8461edf3f8p-6, -0x1.ee5fcb1bb176fp-4, + 0x1.5163772e7890fp-6, 0x1.93eca58aee857p-6, -0x1.a254faecb22e3p-4, 0x1.0ee9eea626c13p-6, + 0x1.3ebe68312ab90p-6, -0x1.24001b6eea9a1p-3, 0x1.86b6038ff95cdp-4, -0x1.028ecf8c46f5ep-6, + 0x1.1e14c43301881p-4, 0x1.366451e4af0b7p-8, -0x1.a8aa0938c41b4p-6, -0x1.bc3232dd7d8b6p-3, + 0x1.c502abe2c6b1ap-4, 0x1.23c9b6ccfd614p-7, -0x1.31441a87aad90p-7, 0x1.27d9669d3f09dp-5, + 0x1.7950eff2015c2p-4, 0x1.ef5081eb0ca14p-4, 0x1.192b71761a0abp-3, 0x1.1565f7367f7bcp-7, + 0x1.7ce496f90ca2ap-4, 0x1.0572d96aa3011p-2, 0x1.fa13cd33465cfp-6, 0x1.e60c0a58a1841p-7, + -0x1.249e8014d6149p-3, -0x1.9d61a573aaf06p-6, 0x1.127789b55ac8fp-7, -0x1.446545917e3c9p-3, + -0x1.8bcecf786774ap-6, -0x1.0e8f8abe2e59ep-3, 0x1.674844fab97abp-3, 0x1.a6c2effc57239p-5, + 0x1.41321a828234cp-7, -0x1.6ab00094d7d3ap-6, 0x1.09c9917b49419p-5, 0x1.0966144491c60p-3, + -0x1.01cfcb0bc067dp-4, 0x1.ba5aa86c430b5p-4, 0x1.fff61e6eacf11p-4, 0x1.921c6c627e1d8p-10, + -0x1.edc1979ad87bdp-5, -0x1.c08c416217801p-4, -0x1.0c970368ce47dp-4, 0x1.b3e4d575da4c5p-4, + 0x1.ffa72cb9f82e6p-4, 0x1.2d86557f0fbffp-8, -0x1.d7977588bc4f7p-5, -0x1.c678b3088cf75p-4, + -0x1.1734d89b60eabp-4, 0x1.ad2bca5d1aeb2p-4, 0x1.ff0958d1fe459p-4, 0x1.f656db5886048p-8, + -0x1.c1249b9aad775p-5, -0x1.cc1f0ff21df2bp-4, -0x1.21a79972476bap-4, 0x1.a6308e3308f8cp-4, + 0x1.fe1caf5f4e1d5p-4, 0x1.5f6d0b4d5fd02p-7, -0x1.aa6c86202ad2dp-5, -0x1.d17e752165bdcp-4, + -0x1.2bedb29936abcp-4, 0x1.9ef43ef888430p-4, 0x1.fce1615b6d01cp-4, 0x1.c37856c5653bbp-7, + -0x1.9372a341b8756p-5, -0x1.d69618f0393fbp-4, -0x1.360589fd4632ep-4, 0x1.9777f0b3f15b8p-4, + 0x1.fb57979085f51p-4, 0x1.139f1209e2a43p-6, -0x1.7c3a90cd5b201p-5, -0x1.db65256f210eep-4, + -0x1.3fed93f45350ap-4, 0x1.8fbcc8f635b7bp-4, 0x1.f97f926b87011p-4, 0x1.4557633cc5893p-6, + -0x1.64c7db8fd7ecep-5, -0x1.dfeae56ae9d96p-4, -0x1.49a4487046becp-4, 0x1.87c40255d243ep-4, + 0x1.f759997a16baap-4, 0x1.76dd9e18c3a56p-6, -0x1.4d1e269566433p-5, -0x1.e426a6d783b6fp-4, + -0x1.532829ccb8172p-4, 0x1.7f8ecc9661638p-4, 0x1.f4e601c27d427p-4, 0x1.a82a021f4cb75p-6, + -0x1.35410a2194bb4p-5, -0x1.e817bc1ce24e6p-4, -0x1.5c77ba5f1ee85p-4, 0x1.771e76f6f7c94p-4, + 0x1.f225317fbadfap-4, 0x1.d935017b56151p-6, -0x1.1d34444dea3c7p-5, -0x1.ebbd8d0a2c368p-4, + -0x1.659194c0aee60p-4, 0x1.6e744314f4c34p-4, 0x1.ef178ab5ce4fdp-4, 0x1.04fb7f382c257p-5, + -0x1.04fb7f382c257p-5, -0x1.ef178ab5ce4fdp-4, -0x1.6e744314f4c34p-4, 0x1.659194c0aee60p-4, + 0x1.ebbd8d0a2c368p-4, 0x1.1d34444dea3c7p-5, -0x1.d935017b56151p-6, -0x1.f225317fbadfap-4, + -0x1.771e76f6f7c94p-4, 0x1.5c77ba5f1ee85p-4, 0x1.e817bc1ce24e6p-4, 0x1.35410a2194bb4p-5, + -0x1.a82a021f4cb75p-6, -0x1.f4e601c27d427p-4, -0x1.7f8ecc9661638p-4, 0x1.532829ccb8172p-4, + 0x1.e426a6d783b6fp-4, 0x1.4d1e269566433p-5, -0x1.76dd9e18c3a56p-6, -0x1.f759997a16baap-4, + -0x1.87c40255d243ep-4, 0x1.49a4487046becp-4, 0x1.dfeae56ae9d96p-4, 0x1.64c7db8fd7ecep-5, + -0x1.4557633cc5893p-6, -0x1.f97f926b87011p-4, -0x1.8fbcc8f635b7bp-4, 0x1.3fed93f45350ap-4, + 0x1.db65256f210eep-4, 0x1.7c3a90cd5b201p-5, -0x1.139f1209e2a43p-6, -0x1.fb57979085f51p-4, + -0x1.9777f0b3f15b8p-4, 0x1.360589fd4632ep-4, 0x1.d69618f0393fbp-4, 0x1.9372a341b8756p-5, + -0x1.c37856c5653bbp-7, -0x1.fce1615b6d01cp-4, -0x1.9ef43ef888430p-4, 0x1.2bedb29936abcp-4, + 0x1.d17e752165bdcp-4, 0x1.aa6c86202ad2dp-5, -0x1.5f6d0b4d5fd02p-7, -0x1.fe1caf5f4e1d5p-4, + -0x1.a6308e3308f8cp-4, 0x1.21a79972476bap-4, 0x1.cc1f0ff21df2bp-4, 0x1.c1249b9aad775p-5, + -0x1.f656db5886048p-8, -0x1.ff0958d1fe459p-4, -0x1.ad2bca5d1aeb2p-4, 0x1.1734d89b60eabp-4, + 0x1.c678b3088cf75p-4, 0x1.d7977588bc4f7p-5, -0x1.2d86557f0fbffp-8, -0x1.ffa72cb9f82e6p-4, + -0x1.b3e4d575da4c5p-4, 0x1.0c970368ce47dp-4, 0x1.c08c416217801p-4, 0x1.edc1979ad87bdp-5, + -0x1.921c6c627e1d8p-10, -0x1.fff61e6eacf11p-4, -0x1.ba5aa86c430b5p-4, 0x1.01cfcb0bc066dp-4, + -0x1.ba5aa93e66990p-4, -0x1.01cfca4a7f5b4p-4, 0x1.921c605bb7233p-10, -0x1.fff61ed6567c5p-4, + 0x1.c08c3f63a3071p-4, -0x1.edc197cd8e6adp-5, 0x1.b3e4d56368085p-4, 0x1.0c97042ca4f42p-4, + -0x1.2d8657a5262f3p-8, 0x1.ffa72df1fe564p-4, -0x1.c678b195b9bc2p-4, 0x1.d79773f596153p-5, + -0x1.ad2bc9c9c04e2p-4, -0x1.1734d8019b156p-4, 0x1.f656d85df6ce7p-8, -0x1.ff0959b0e65bap-4, + 0x1.cc1f10d7238dep-4, -0x1.c1249a3d4865ep-5, 0x1.a6308f20f7d19p-4, 0x1.21a799ffbef10p-4, + -0x1.5f6d0bec8c94ap-7, 0x1.fe1caf03119abp-4, -0x1.d17e776201107p-4, 0x1.aa6c86c483d8dp-5, + -0x1.9ef43d97839bap-4, -0x1.2bedb24338d1bp-4, 0x1.c37853e08c189p-7, -0x1.fce15fa22ac3ap-4, + 0x1.d6961a62d213ep-4, -0x1.9372a4681b3e1p-5, 0x1.9777f03063c50p-4, 0x1.36058a992c3b8p-4, + -0x1.139f12efeb20cp-6, 0x1.fb57993c398c0p-4, -0x1.db6524b0fd79fp-4, 0x1.7c3a92052c94cp-5, + -0x1.8fbcca6d6e3d4p-4, -0x1.3fed951239b84p-4, 0x1.455762fc13d2ep-6, -0x1.f97f91a47c58fp-4, + 0x1.dfeae59c693e9p-4, -0x1.64c7db3b40e28p-5, 0x1.87c4021587da5p-4, 0x1.49a4489dd8e66p-4, + -0x1.76dd9de65a321p-6, 0x1.f75997332b5aep-4, -0x1.e426a5b2263fcp-4, 0x1.4d1e276dc29acp-5, + -0x1.7f8ecc6c31936p-4, -0x1.532829811f6ddp-4, 0x1.a82a036ecf157p-6, -0x1.f4e6005c929d2p-4, + 0x1.e817be3b5939cp-4, -0x1.35410a0c04502p-5, 0x1.771e768ca568cp-4, 0x1.5c77ba52b0726p-4, + -0x1.d935020f179fcp-6, 0x1.f2252fc14bf3cp-4, -0x1.ebbd8c1000d1cp-4, 0x1.1d34455b1cbeap-5, + -0x1.6e7444b63ceebp-4, -0x1.659194714f991p-4, 0x1.04fb7ee95caedp-5, -0x1.ef178c423d9fap-4, + 0x1.ef178c423d9fap-4, -0x1.04fb7ee95caedp-5, 0x1.659194714f991p-4, 0x1.6e7444b63ceebp-4, + -0x1.1d34455b1cbeap-5, 0x1.ebbd8c1000d1cp-4, -0x1.f2252fc14bf3cp-4, 0x1.d935020f179fcp-6, + -0x1.5c77ba52b0726p-4, -0x1.771e768ca568cp-4, 0x1.35410a0c04502p-5, -0x1.e817be3b5939cp-4, + 0x1.f4e6005c929d2p-4, -0x1.a82a036ecf157p-6, 0x1.532829811f6ddp-4, 0x1.7f8ecc6c31936p-4, + -0x1.4d1e276dc29acp-5, 0x1.e426a5b2263fcp-4, -0x1.f75997332b5aep-4, 0x1.76dd9de65a321p-6, + -0x1.49a4489dd8e66p-4, -0x1.87c4021587da5p-4, 0x1.64c7db3b40e28p-5, -0x1.dfeae59c693e9p-4, + 0x1.f97f91a47c58fp-4, -0x1.455762fc13d2ep-6, 0x1.3fed951239b84p-4, 0x1.8fbcca6d6e3d4p-4, + -0x1.7c3a92052c94cp-5, 0x1.db6524b0fd79fp-4, -0x1.fb57993c398c0p-4, 0x1.139f12efeb20cp-6, + -0x1.36058a992c3b8p-4, -0x1.9777f03063c50p-4, 0x1.9372a4681b3e1p-5, -0x1.d6961a62d213ep-4, + 0x1.fce15fa22ac3ap-4, -0x1.c37853e08c189p-7, 0x1.2bedb24338d1bp-4, 0x1.9ef43d97839bap-4, + -0x1.aa6c86c483d8dp-5, 0x1.d17e776201107p-4, -0x1.fe1caf03119abp-4, 0x1.5f6d0bec8c94ap-7, + -0x1.21a799ffbef10p-4, -0x1.a6308f20f7d19p-4, 0x1.c1249a3d4865ep-5, -0x1.cc1f10d7238dep-4, + 0x1.ff0959b0e65bap-4, -0x1.f656d85df6ce7p-8, 0x1.1734d8019b156p-4, 0x1.ad2bc9c9c04e2p-4, + -0x1.d79773f596153p-5, 0x1.c678b195b9bc2p-4, -0x1.ffa72df1fe564p-4, 0x1.2d8657a5262f3p-8, + -0x1.0c97042ca4f42p-4, -0x1.b3e4d56368085p-4, 0x1.edc197cd8e6adp-5, -0x1.c08c3f63a3071p-4, + 0x1.fff61ed6567c5p-4, -0x1.921c605bb7233p-10, 0x1.01cfca4a7f5b0p-4, 0x1.ba5aa93e6698fp-4, + -0x1.b1c9adcd781a4p-4, 0x1.37fc7c4db7bc8p-4, -0x1.137cf87903cddp-6, -0x1.af2d12def0617p-5, + -0x1.86089ad0411c7p-3, 0x1.3b8e5855da77bp-8, 0x1.3e2aeb6b01e8bp-4, -0x1.c962a4cc67118p-5, + -0x1.b2fc423102148p-7, 0x1.d73288b101ffcp-3, 0x1.04751eca9a3a3p-3, -0x1.cbadb7df848c2p-7, + -0x1.74ec7ee7cb6afp-6, 0x1.16aed3fcc761ap-5, -0x1.9d936b01b1361p-6, -0x1.07392d5aebdd6p-3, + -0x1.015fc12b48ccdp-4, 0x1.255507128371ep-4, 0x1.0748566d209d8p-5, -0x1.60c0e3bbaaee2p-4, + -0x1.505f7102f2ec7p-8, -0x1.46cc8b11e8ac2p-4, -0x1.fd4426827ada0p-4, 0x1.2d6239ffe0c09p-4, + 0x1.56e3e743645e9p-7, 0x1.974aa04270c97p-6, -0x1.5443eed0f4a8bp-6, 0x1.5df219aaeb58fp-3, + 0x1.aa2e097de6095p-5, -0x1.1769ccec3db0ep-7, -0x1.1e023458a3c74p-7, 0x1.83b5d2308cccbp-5, + -0x1.184dfc3191c86p-6, 0x1.1f127e3a052c9p-3, -0x1.c8291d230098ap-7, 0x1.6724eaa350b14p-4, + -0x1.f208e95fad26dp-6, -0x1.364676836355fp-7, -0x1.026e11e68c1e4p-7, 0x1.5157ecabce319p-4, + -0x1.b8e9b4e4dd5ffp-3, -0x1.2c382f1d9fe57p-9, -0x1.0211f45e3010fp-3, 0x1.3a13320b2f5c2p-3, + -0x1.42001f1f80a5bp-6, -0x1.af0705a9ee96dp-3, -0x1.faf7d3839c4b5p-5, -0x1.da105a47913e5p-7, + -0x1.927a3ce37164dp-6, -0x1.2016e02a98009p-6, 0x1.92c8124c4b4a3p-6, 0x1.9a6e3fff4c45cp-6, + 0x1.0d6ade56d4b70p-3, -0x1.08d5e07bb3ee4p-5, 0x1.7b459ca21a2a6p-4, -0x1.43773581f42e1p-5, + -0x1.5b222edf985f3p-10, -0x1.a716340783c1bp-3, -0x1.fa629b4f862bep-4, 0x1.cd163e95e500fp-5, + -0x1.81c03410d6b4ep-5, 0x1.d1a0a344f9455p-10, -0x1.0c58f4c74d0cfp-5, -0x1.b828b859d918bp-6, + 0x1.b828b859d918bp-6, 0x1.0c58f4c74d0cfp-5, -0x1.d1a0a344f9455p-10, 0x1.81c03410d6b4ep-5, + -0x1.cd163e95e500fp-5, 0x1.fa629b4f862bep-4, 0x1.a716340783c1bp-3, 0x1.5b222edf985f3p-10, + 0x1.43773581f42e1p-5, -0x1.7b459ca21a2a6p-4, 0x1.08d5e07bb3ee4p-5, -0x1.0d6ade56d4b70p-3, + -0x1.9a6e3fff4c45cp-6, -0x1.92c8124c4b4a3p-6, 0x1.2016e02a98009p-6, 0x1.927a3ce37164dp-6, + 0x1.da105a47913e5p-7, 0x1.faf7d3839c4b5p-5, 0x1.af0705a9ee96dp-3, 0x1.42001f1f80a5bp-6, + -0x1.3a13320b2f5c2p-3, 0x1.0211f45e3010fp-3, 0x1.2c382f1d9fe57p-9, 0x1.b8e9b4e4dd5ffp-3, + -0x1.5157ecabce319p-4, 0x1.026e11e68c1e4p-7, 0x1.364676836355fp-7, 0x1.f208e95fad26dp-6, + -0x1.6724eaa350b14p-4, 0x1.c8291d230098ap-7, -0x1.1f127e3a052c9p-3, 0x1.184dfc3191c86p-6, + -0x1.83b5d2308cccbp-5, 0x1.1e023458a3c74p-7, 0x1.1769ccec3db0ep-7, -0x1.aa2e097de6095p-5, + -0x1.5df219aaeb58fp-3, 0x1.5443eed0f4a8bp-6, -0x1.974aa04270c97p-6, -0x1.56e3e743645e9p-7, + -0x1.2d6239ffe0c09p-4, 0x1.fd4426827ada0p-4, 0x1.46cc8b11e8ac2p-4, 0x1.505f7102f2ec7p-8, + 0x1.60c0e3bbaaee2p-4, -0x1.0748566d209d8p-5, -0x1.255507128371ep-4, 0x1.015fc12b48ccdp-4, + 0x1.07392d5aebdd6p-3, 0x1.9d936b01b1361p-6, -0x1.16aed3fcc761ap-5, 0x1.74ec7ee7cb6afp-6, + 0x1.cbadb7df848c2p-7, -0x1.04751eca9a3a3p-3, -0x1.d73288b101ffcp-3, 0x1.b2fc423102148p-7, + 0x1.c962a4cc67119p-5, -0x1.3e2aeb6b01e8bp-4, -0x1.3b8e5855da7f2p-8, 0x1.86089ad0411cap-3, + 0x1.af2d12def0641p-5, 0x1.137cf87903cfcp-6, -0x1.37fc787e1b8ddp-4, 0x1.b1c9ae37a0580p-4, + 0x1.843554d62c87ep-4, -0x1.e3b94c5ca63c1p-5, 0x1.06e06391c5b20p-4, -0x1.8f892e2481846p-10, + -0x1.3f07a208eda36p-5, 0x1.babeb2e0f2025p-4, -0x1.99ca6cf1a8c5ap-5, -0x1.624b71a65de1cp-7, + -0x1.0d0a7b1366e16p-3, 0x1.18492a797fbb2p-6, -0x1.4c074bae63bd0p-7, 0x1.61816eada94cfp-4, + 0x1.e5f7133667156p-8, 0x1.eeb46bcd8676dp-5, -0x1.aef413d876338p-8, -0x1.d03f6663a820ep-8, + -0x1.543c510c03d29p-5, -0x1.b0e9f7c15f12bp-3, -0x1.e4231e6779087p-8, -0x1.49f0472ca85b1p-7, + -0x1.2ff8eb17fcf06p-4, -0x1.fd7542364c7f7p-9, 0x1.19b3cac46623ep-7, -0x1.0778a81cd41f3p-2, + -0x1.bc2103a08d77dp-5, -0x1.63cfc5b482133p-5, 0x1.6e367a580453fp-5, -0x1.de0c117f02552p-7, + -0x1.ec67f96ae3055p-8, 0x1.f5d5cffb93508p-4, 0x1.1faf644a66e4bp-4, 0x1.62c7c257e4776p-4, + 0x1.36d208ad1b876p-3, -0x1.142cc0df55d20p-8, -0x1.fd5daa3cc744bp-5, 0x1.cea4ac61d28fdp-3, + -0x1.b355c7a586b5fp-6, 0x1.7810ec9dd06cdp-3, -0x1.cf3d80067a3adp-4, -0x1.9cf33f9b4412ep-6, + -0x1.70f069f59e7eep-5, -0x1.1d6fd0ffcfec8p-3, 0x1.52d32c6da0530p-5, 0x1.36b3f46b2098fp-4, + 0x1.43449eadff1aap-4, -0x1.05c86492e558cp-10, -0x1.8f6ceda418c2dp-5, -0x1.9f5865a0ad5adp-5, + 0x1.2fa80c8be4a8dp-4, -0x1.45aa3f34c606ap-4, -0x1.84315972f670fp-3, 0x1.6d70665aaa56dp-6, + 0x1.1a805fdccf7b4p-5, 0x1.49526f905fdcdp-5, -0x1.a38ce47cef762p-5, -0x1.2cdef41133ce4p-4, + -0x1.30eabd2459c9bp-7, 0x1.fff3d0faf22cdp-8, -0x1.ef3447476e6d6p-6, 0x1.8a3907f5abb2bp-3, + 0x1.a23367c1a938fp-6, 0x1.10dc36aa0e488p-4, 0x1.0ecf193252ce4p-3, -0x1.861060940c73fp-7, + 0x1.861060940c73fp-7, -0x1.0ecf193252ce4p-3, -0x1.10dc36aa0e488p-4, -0x1.a23367c1a938fp-6, + -0x1.8a3907f5abb2bp-3, 0x1.ef3447476e6d6p-6, -0x1.fff3d0faf22cdp-8, 0x1.30eabd2459c9bp-7, + 0x1.2cdef41133ce4p-4, 0x1.a38ce47cef762p-5, -0x1.49526f905fdcdp-5, -0x1.1a805fdccf7b4p-5, + -0x1.6d70665aaa56dp-6, 0x1.84315972f670fp-3, 0x1.45aa3f34c606ap-4, -0x1.2fa80c8be4a8dp-4, + 0x1.9f5865a0ad5adp-5, 0x1.8f6ceda418c2dp-5, 0x1.05c86492e558cp-10, -0x1.43449eadff1aap-4, + -0x1.36b3f46b2098fp-4, -0x1.52d32c6da0530p-5, 0x1.1d6fd0ffcfec8p-3, 0x1.70f069f59e7eep-5, + 0x1.9cf33f9b4412ep-6, 0x1.cf3d80067a3adp-4, -0x1.7810ec9dd06cdp-3, 0x1.b355c7a586b5fp-6, + -0x1.cea4ac61d28fdp-3, 0x1.fd5daa3cc744bp-5, 0x1.142cc0df55d20p-8, -0x1.36d208ad1b876p-3, + -0x1.62c7c257e4776p-4, -0x1.1faf644a66e4bp-4, -0x1.f5d5cffb93508p-4, 0x1.ec67f96ae3055p-8, + 0x1.de0c117f02552p-7, -0x1.6e367a580453fp-5, 0x1.63cfc5b482133p-5, 0x1.bc2103a08d77dp-5, + 0x1.0778a81cd41f3p-2, -0x1.19b3cac46623ep-7, 0x1.fd7542364c7f7p-9, 0x1.2ff8eb17fcf06p-4, + 0x1.49f0472ca85b1p-7, 0x1.e4231e6779087p-8, 0x1.b0e9f7c15f12bp-3, 0x1.543c510c03d29p-5, + 0x1.d03f6663a820ep-8, 0x1.aef413d876338p-8, -0x1.eeb46bcd8676dp-5, -0x1.e5f7133667156p-8, + -0x1.61816eada94cfp-4, 0x1.4c074bae63bd0p-7, -0x1.18492a797fbb2p-6, 0x1.0d0a7b1366e16p-3, + 0x1.624b71a65de1cp-7, 0x1.99ca6cf1a8c5ap-5, -0x1.babeb2e0f2025p-4, 0x1.3f07a208eda37p-5, + 0x1.8f892e248181dp-10, -0x1.06e06391c5b1dp-4, 0x1.e3b94c5bc1314p-5, -0x1.843554ddedc94p-4, + -0x1.edc1958233d20p-5, 0x1.c08c42a9ad883p-4, 0x1.ff09572208d8bp-4, -0x1.f657108f43f78p-8, + -0x1.2bedb2bcc9b35p-4, -0x1.9ef4415de5094p-4, -0x1.7c3a922f7e4a0p-5, 0x1.db6526e4e96b0p-4, + 0x1.f759996f2cd89p-4, -0x1.76dd9c05f3f6fp-6, -0x1.5c77bb7078b75p-4, -0x1.771e7559d0456p-4, + -0x1.04fb7ffa3338dp-5, 0x1.ef17898757fd4p-4, 0x1.e817bbd31fc16p-4, -0x1.35410bcb2d2bdp-5, + -0x1.87c401ac8a92bp-4, -0x1.49a449d92bb91p-4, -0x1.139f0cf043b1bp-6, 0x1.fb57975377751p-4, + 0x1.d17e756218d05p-4, -0x1.aa6c83210d773p-5, -0x1.ad2bc8c654952p-4, -0x1.1734d6a56fb4cp-4, + -0x1.921d3d4a39f4ap-10, 0x1.fff6216b51c55p-4, 0x1.b3e4d54d45ca6p-4, -0x1.0c9703c66c48fp-4, + -0x1.cc1f123409143p-4, -0x1.c1249b1d7858ap-5, 0x1.c37860e54b400p-7, 0x1.fce15eb9bda99p-4, + 0x1.8fbccc7174f50p-4, -0x1.3fed942242206p-4, -0x1.e426a56bc33dbp-4, -0x1.4d1e22d4bcc93p-5, + 0x1.d934f0c54c420p-6, 0x1.f2252dfe04adap-4, 0x1.659193fc98b2cp-4, -0x1.6e74446c48c94p-4, + -0x1.f4e605cf8a0f7p-4, -0x1.a829fca8fbba6p-6, 0x1.64c7dc932d30fp-5, 0x1.dfeae5a1f1b83p-4, + 0x1.36058c40b1e75p-4, -0x1.9777ec4374176p-4, -0x1.fe1cb076fc84cp-4, -0x1.5f6d09d7a986fp-7, + 0x1.d7977276c498cp-5, 0x1.c678b0a8408cdp-4, 0x1.01cfc64090764p-4, -0x1.ba5aa5844881ap-4, + -0x1.ffa72f160cbfap-4, 0x1.2d86409542158p-8, 0x1.21a79ac04932fp-4, 0x1.a63090612f957p-4, + 0x1.9372a23985dc2p-5, -0x1.d696165fc31c6p-4, -0x1.f97f92514247ep-4, 0x1.4557780e32077p-6, + 0x1.5328297c218d2p-4, 0x1.7f8ed19329f25p-4, 0x1.1d3444531febcp-5, -0x1.ebbd8d8760479p-4, + -0x1.ebbd8d8760479p-4, 0x1.1d3444531febcp-5, 0x1.7f8ed19329f25p-4, 0x1.5328297c218d2p-4, + 0x1.4557780e32077p-6, -0x1.f97f92514247ep-4, -0x1.d696165fc31c6p-4, 0x1.9372a23985dc2p-5, + 0x1.a63090612f957p-4, 0x1.21a79ac04932fp-4, 0x1.2d86409542158p-8, -0x1.ffa72f160cbfap-4, + -0x1.ba5aa5844881ap-4, 0x1.01cfc64090764p-4, 0x1.c678b0a8408cdp-4, 0x1.d7977276c498cp-5, + -0x1.5f6d09d7a986fp-7, -0x1.fe1cb076fc84cp-4, -0x1.9777ec4374176p-4, 0x1.36058c40b1e75p-4, + 0x1.dfeae5a1f1b83p-4, 0x1.64c7dc932d30fp-5, -0x1.a829fca8fbba6p-6, -0x1.f4e605cf8a0f7p-4, + -0x1.6e74446c48c94p-4, 0x1.659193fc98b2cp-4, 0x1.f2252dfe04adap-4, 0x1.d934f0c54c420p-6, + -0x1.4d1e22d4bcc93p-5, -0x1.e426a56bc33dbp-4, -0x1.3fed942242206p-4, 0x1.8fbccc7174f50p-4, + 0x1.fce15eb9bda99p-4, 0x1.c37860e54b400p-7, -0x1.c1249b1d7858ap-5, -0x1.cc1f123409143p-4, + -0x1.0c9703c66c48fp-4, 0x1.b3e4d54d45ca6p-4, 0x1.fff6216b51c55p-4, -0x1.921d3d4a39f4ap-10, + -0x1.1734d6a56fb4cp-4, -0x1.ad2bc8c654952p-4, -0x1.aa6c83210d773p-5, 0x1.d17e756218d05p-4, + 0x1.fb57975377751p-4, -0x1.139f0cf043b1bp-6, -0x1.49a449d92bb91p-4, -0x1.87c401ac8a92bp-4, + -0x1.35410bcb2d2bdp-5, 0x1.e817bbd31fc16p-4, 0x1.ef17898757fd4p-4, -0x1.04fb7ffa3338dp-5, + -0x1.771e7559d0456p-4, -0x1.5c77bb7078b75p-4, -0x1.76dd9c05f3f6fp-6, 0x1.f759996f2cd89p-4, + 0x1.db6526e4e96b0p-4, -0x1.7c3a922f7e4a0p-5, -0x1.9ef4415de5094p-4, -0x1.2bedb2bcc9b35p-4, + -0x1.f657108f43f78p-8, 0x1.ff09572208d8bp-4, 0x1.c08c42a9ad882p-4, -0x1.edc1958233d4ap-5, + -0x1.c08c428d9131ep-4, -0x1.edc1964a1de98p-5, -0x1.f657117e85425p-8, -0x1.ff09583e4a43bp-4, + 0x1.9ef441308d437p-4, -0x1.2bedb30e44adcp-4, 0x1.db6525ff8121bp-4, 0x1.7c3a92b3c5dc6p-5, + 0x1.76dd9caa03573p-6, 0x1.f7599c2465d1ep-4, -0x1.771e74b6d6940p-4, 0x1.5c77bc180d301p-4, + -0x1.ef178a1035643p-4, -0x1.04fb809192b24p-5, -0x1.35410cd0ee6a1p-5, -0x1.e817babacae01p-4, + 0x1.49a44ada04afdp-4, -0x1.87c4002280ea8p-4, 0x1.fb57980c5b629p-4, 0x1.139f0caffd5f9p-6, + 0x1.aa6c82fcba3a3p-5, 0x1.d17e73848a546p-4, -0x1.1734d691b0e8dp-4, 0x1.ad2bc92f5ca32p-4, + -0x1.fff6217e92629p-4, -0x1.921d3cbf52b94p-10, -0x1.0c9703be3d04dp-4, -0x1.b3e4d64454a0cp-4, + 0x1.c1249b5eb3d86p-5, -0x1.cc1f115cee8c9p-4, 0x1.fce15fe4120c7p-4, -0x1.c3785ee57721cp-7, + 0x1.3fed93d12feccp-4, 0x1.8fbccc3d8ac9dp-4, -0x1.4d1e22147f092p-5, 0x1.e426a31c47f1fp-4, + -0x1.f2252e1d60fdap-4, 0x1.d934ef625471fp-6, -0x1.6e7444c6c94aep-4, -0x1.6591947c5c06ep-4, + 0x1.a829fd2a1fd5fp-6, -0x1.f4e60604a385dp-4, 0x1.dfeae65641fd3p-4, -0x1.64c7dbb696697p-5, + 0x1.9777ebfc2540cp-4, 0x1.36058c0d7b420p-4, -0x1.5f6d0837a474cp-7, 0x1.fe1cb0d4081a1p-4, + -0x1.c678b03bf9639p-4, 0x1.d79772f50cf0bp-5, -0x1.ba5aa5c7f9055p-4, -0x1.01cfc5f81cbc4p-4, + -0x1.2d86408a86a46p-8, -0x1.ffa72e559f29fp-4, 0x1.a630907d28d5ep-4, -0x1.21a79a251be4fp-4, + 0x1.d6961749727eep-4, 0x1.9372a34d1dce3p-5, 0x1.4557780560095p-6, 0x1.f97f925d4c84dp-4, + -0x1.7f8ed07eb6fb0p-4, 0x1.53282a23fbd61p-4, -0x1.ebbd8c2ec09e7p-4, -0x1.1d3444f09875bp-5, + -0x1.1d3444f09875bp-5, -0x1.ebbd8c2ec09e7p-4, 0x1.53282a23fbd61p-4, -0x1.7f8ed07eb6fb0p-4, + 0x1.f97f925d4c84dp-4, 0x1.4557780560095p-6, 0x1.9372a34d1dce3p-5, 0x1.d6961749727eep-4, + -0x1.21a79a251be4fp-4, 0x1.a630907d28d5ep-4, -0x1.ffa72e559f29fp-4, -0x1.2d86408a86a46p-8, + -0x1.01cfc5f81cbc4p-4, -0x1.ba5aa5c7f9055p-4, 0x1.d79772f50cf0bp-5, -0x1.c678b03bf9639p-4, + 0x1.fe1cb0d4081a1p-4, -0x1.5f6d0837a474cp-7, 0x1.36058c0d7b420p-4, 0x1.9777ebfc2540cp-4, + -0x1.64c7dbb696697p-5, 0x1.dfeae65641fd3p-4, -0x1.f4e60604a385dp-4, 0x1.a829fd2a1fd5fp-6, + -0x1.6591947c5c06ep-4, -0x1.6e7444c6c94aep-4, 0x1.d934ef625471fp-6, -0x1.f2252e1d60fdap-4, + 0x1.e426a31c47f1fp-4, -0x1.4d1e22147f092p-5, 0x1.8fbccc3d8ac9dp-4, 0x1.3fed93d12feccp-4, + -0x1.c3785ee57721cp-7, 0x1.fce15fe4120c7p-4, -0x1.cc1f115cee8c9p-4, 0x1.c1249b5eb3d86p-5, + -0x1.b3e4d64454a0cp-4, -0x1.0c9703be3d04dp-4, -0x1.921d3cbf52b94p-10, -0x1.fff6217e92629p-4, + 0x1.ad2bc92f5ca32p-4, -0x1.1734d691b0e8dp-4, 0x1.d17e73848a546p-4, 0x1.aa6c82fcba3a3p-5, + 0x1.139f0caffd5f9p-6, 0x1.fb57980c5b629p-4, -0x1.87c4002280ea8p-4, 0x1.49a44ada04afdp-4, + -0x1.e817babacae01p-4, -0x1.35410cd0ee6a1p-5, -0x1.04fb809192b24p-5, -0x1.ef178a1035643p-4, + 0x1.5c77bc180d301p-4, -0x1.771e74b6d6940p-4, 0x1.f7599c2465d1ep-4, 0x1.76dd9caa03573p-6, + 0x1.7c3a92b3c5dc6p-5, 0x1.db6525ff8121bp-4, -0x1.2bedb30e44adcp-4, 0x1.9ef441308d437p-4, + -0x1.ff09583e4a43bp-4, -0x1.f657117e85425p-8, -0x1.edc1964a1de9ep-5, -0x1.c08c428d91321p-4, + -0x1.2cf4ec21f9851p-5, -0x1.f2bf54e9f8997p-6, -0x1.30210bab7b48fp-7, 0x1.edaa7a0a3b908p-3, + -0x1.e649853b3e500p-5, -0x1.2d65d6a48c081p-5, 0x1.9dba66f754479p-5, 0x1.2f2567e737b23p-8, + 0x1.24b6ea29fdb0ap-6, -0x1.31871fa3f5e15p-5, -0x1.5a62c9a4d1fa9p-4, 0x1.2d1e7e2691009p-4, + 0x1.123808988ff8dp-3, -0x1.d591ca5b81fe1p-8, 0x1.f91756ec017c2p-7, 0x1.2b308a1d33abdp-3, + 0x1.2e1a3019ce33dp-7, -0x1.525bede67c966p-4, -0x1.446a179245b7bp-4, -0x1.ba2f452dafd76p-6, + -0x1.3073b11f33266p-6, 0x1.7a7b89ab0a6a3p-3, -0x1.aee4f2b0fce06p-5, 0x1.62efbe44be76dp-5, + 0x1.15028037c88d1p-5, -0x1.69c94f1731816p-8, -0x1.25aac846cc83cp-3, 0x1.ac44010a1c5eep-4, + -0x1.bc462bd56ae54p-5, -0x1.07ac1cca2265ap-2, -0x1.1c108367a557dp-3, -0x1.2077de1e8d0bdp-6, + 0x1.35d03217be34dp-4, -0x1.9eb041c8b5b2bp-7, -0x1.aa6c249d78365p-5, 0x1.0801d860e88a6p-4, + 0x1.4739440e72cc4p-4, 0x1.4f81bac7b321bp-5, -0x1.d7d34a004bf78p-5, 0x1.570cda24ce642p-7, + -0x1.0bbe0f6202215p-5, 0x1.88ed3c4bf7cccp-4, -0x1.964c87fdaffddp-4, -0x1.1ea9eb19028a3p-5, + 0x1.ea7bb4448dbfbp-5, 0x1.5002130243f15p-4, -0x1.07e89c48c31c0p-7, -0x1.abf2f9a366539p-5, + -0x1.2150cd2d9305bp-4, 0x1.4ed51924d60f2p-4, 0x1.ddca7ce54c98ep-5, -0x1.33e671f5e08bdp-4, + 0x1.5f537fbbbee63p-8, -0x1.c2d68cfeaa8e3p-3, 0x1.af638e3acfb69p-5, -0x1.23bd116f941abp-4, + -0x1.ae871666c391ep-3, -0x1.4af178af70a13p-6, 0x1.047b7c2219872p-6, -0x1.7316ccd6ca18ap-4, + 0x1.70bf99b864b49p-10, 0x1.f4c603d3079ebp-4, 0x1.199c1bbd191ecp-11, 0x1.d50f8a45df5a7p-10, + 0x1.d50f8a45df5a7p-10, 0x1.199c1bbd191ecp-11, 0x1.f4c603d3079ebp-4, 0x1.70bf99b864b49p-10, + -0x1.7316ccd6ca18ap-4, 0x1.047b7c2219872p-6, -0x1.4af178af70a13p-6, -0x1.ae871666c391ep-3, + -0x1.23bd116f941abp-4, 0x1.af638e3acfb69p-5, -0x1.c2d68cfeaa8e3p-3, 0x1.5f537fbbbee63p-8, + -0x1.33e671f5e08bdp-4, 0x1.ddca7ce54c98ep-5, 0x1.4ed51924d60f2p-4, -0x1.2150cd2d9305bp-4, + -0x1.abf2f9a366539p-5, -0x1.07e89c48c31c0p-7, 0x1.5002130243f15p-4, 0x1.ea7bb4448dbfbp-5, + -0x1.1ea9eb19028a3p-5, -0x1.964c87fdaffddp-4, 0x1.88ed3c4bf7cccp-4, -0x1.0bbe0f6202215p-5, + 0x1.570cda24ce642p-7, -0x1.d7d34a004bf78p-5, 0x1.4f81bac7b321bp-5, 0x1.4739440e72cc4p-4, + 0x1.0801d860e88a6p-4, -0x1.aa6c249d78365p-5, -0x1.9eb041c8b5b2bp-7, 0x1.35d03217be34dp-4, + -0x1.2077de1e8d0bdp-6, -0x1.1c108367a557dp-3, -0x1.07ac1cca2265ap-2, -0x1.bc462bd56ae54p-5, + 0x1.ac44010a1c5eep-4, -0x1.25aac846cc83cp-3, -0x1.69c94f1731816p-8, 0x1.15028037c88d1p-5, + 0x1.62efbe44be76dp-5, -0x1.aee4f2b0fce06p-5, 0x1.7a7b89ab0a6a3p-3, -0x1.3073b11f33266p-6, + -0x1.ba2f452dafd76p-6, -0x1.446a179245b7bp-4, -0x1.525bede67c966p-4, 0x1.2e1a3019ce33dp-7, + 0x1.2b308a1d33abdp-3, 0x1.f91756ec017c2p-7, -0x1.d591ca5b81fe1p-8, 0x1.123808988ff8dp-3, + 0x1.2d1e7e2691009p-4, -0x1.5a62c9a4d1fa9p-4, -0x1.31871fa3f5e15p-5, 0x1.24b6ea29fdb0ap-6, + 0x1.2f2567e737b20p-8, 0x1.9dba66f754479p-5, -0x1.2d65d6a48c06cp-5, -0x1.e649853b3e502p-5, + 0x1.edaa7a0a3b90bp-3, -0x1.30210bab7b4b8p-7, -0x1.f2bf57950d269p-6, -0x1.2cf4ec277b618p-5, + 0x1.c9bc4427ef374p-6, 0x1.1479567c48731p-6, -0x1.2bb90bd8a494fp-4, -0x1.54aec0d6b2143p-5, + -0x1.1745880f8d126p-5, -0x1.5663b192c1ce7p-3, 0x1.2dd4549608d09p-5, 0x1.4132f18120747p-5, + 0x1.a7af3395fa379p-5, 0x1.cdfa8876bebdep-7, 0x1.b03d64da11ef4p-5, -0x1.97435874d2042p-4, + -0x1.2f0284610457fp-6, 0x1.50e5fd82cf639p-3, 0x1.c7560060e7743p-4, 0x1.a58d4f6e56823p-6, + -0x1.1399f08ea7907p-4, 0x1.25187bee8d20ep-3, -0x1.0a4d5955fd5d5p-9, -0x1.51e725e3cc0b9p-5, + 0x1.39cb8ad280e99p-4, -0x1.2b8a67f4a3a7ep-5, -0x1.5157dea0028d9p-6, -0x1.9ee797f8f50fep-5, + -0x1.03406ed3df9d0p-7, 0x1.2ce9308408d93p-4, 0x1.17f9a01fb1893p-3, 0x1.11514b2c1dbd4p-3, + 0x1.80bfc43727820p-4, -0x1.81730e893e866p-5, 0x1.d22973406da7ep-10, -0x1.5908b63a15591p-3, + -0x1.28e611df54819p-4, 0x1.9c8c19c14829ap-4, -0x1.06ada73b3687fp-10, -0x1.80356dab18848p-5, + -0x1.03d89982cad54p-5, -0x1.aaa25d96a4afdp-3, -0x1.04a14e356ec01p-3, 0x1.3d8f2f8d74f96p-4, + -0x1.2f20b6dccd4a5p-2, -0x1.f113197e3f807p-6, 0x1.3043eb2594106p-7, 0x1.9dac988acea4bp-10, + 0x1.721ad68b36517p-5, 0x1.626ecb27670fdp-4, 0x1.1e8dbaa8ae171p-3, -0x1.3219f7af4cefep-6, + -0x1.c4ba7291019e2p-5, -0x1.24a6a38fa765cp-5, 0x1.2fc60bf9a4d66p-4, -0x1.26ff8574f75ebp-6, + 0x1.cbd3acbac0b6bp-5, 0x1.6407027c86f74p-6, 0x1.f6b8fec77391ep-4, -0x1.3ba33e3ca0966p-6, + -0x1.1e58d4d2cafe6p-6, -0x1.8ebf27d53caffp-8, 0x1.ceb25113591c4p-4, -0x1.abddfcfec537ep-8, + -0x1.338b7444a6040p-3, 0x1.2376b56a19357p-4, -0x1.a917f2be6588ap-8, -0x1.d7d338581c07fp-4, + -0x1.d7d338581c07fp-4, -0x1.a917f2be6588ap-8, 0x1.2376b56a19357p-4, -0x1.338b7444a6040p-3, + -0x1.abddfcfec537ep-8, 0x1.ceb25113591c4p-4, -0x1.8ebf27d53caffp-8, -0x1.1e58d4d2cafe6p-6, + -0x1.3ba33e3ca0966p-6, 0x1.f6b8fec77391ep-4, 0x1.6407027c86f74p-6, 0x1.cbd3acbac0b6bp-5, + -0x1.26ff8574f75ebp-6, 0x1.2fc60bf9a4d66p-4, -0x1.24a6a38fa765cp-5, -0x1.c4ba7291019e2p-5, + -0x1.3219f7af4cefep-6, 0x1.1e8dbaa8ae171p-3, 0x1.626ecb27670fdp-4, 0x1.721ad68b36517p-5, + 0x1.9dac988acea4bp-10, 0x1.3043eb2594106p-7, -0x1.f113197e3f807p-6, -0x1.2f20b6dccd4a5p-2, + 0x1.3d8f2f8d74f96p-4, -0x1.04a14e356ec01p-3, -0x1.aaa25d96a4afdp-3, -0x1.03d89982cad54p-5, + -0x1.80356dab18848p-5, -0x1.06ada73b3687fp-10, 0x1.9c8c19c14829ap-4, -0x1.28e611df54819p-4, + -0x1.5908b63a15591p-3, 0x1.d22973406da7ep-10, -0x1.81730e893e866p-5, 0x1.80bfc43727820p-4, + 0x1.11514b2c1dbd4p-3, 0x1.17f9a01fb1893p-3, 0x1.2ce9308408d93p-4, -0x1.03406ed3df9d0p-7, + -0x1.9ee797f8f50fep-5, -0x1.5157dea0028d9p-6, -0x1.2b8a67f4a3a7ep-5, 0x1.39cb8ad280e99p-4, + -0x1.51e725e3cc0b9p-5, -0x1.0a4d5955fd5d5p-9, 0x1.25187bee8d20ep-3, -0x1.1399f08ea7907p-4, + 0x1.a58d4f6e56823p-6, 0x1.c7560060e7743p-4, 0x1.50e5fd82cf639p-3, -0x1.2f0284610457fp-6, + -0x1.97435874d2042p-4, 0x1.b03d64da11ef4p-5, 0x1.cdfa8876bebdep-7, 0x1.a7af3395fa379p-5, + 0x1.4132f18120748p-5, 0x1.2dd4549608d09p-5, -0x1.5663b192c1ce8p-3, -0x1.1745880f8d11cp-5, + -0x1.54aec0d6b2145p-5, -0x1.2bb90bd8a4950p-4, 0x1.147956bb7d55bp-6, 0x1.c9bc460f915d0p-6, + 0x1.d797764f309c1p-5, -0x1.c678b366aae93p-4, -0x1.fb57969f18f26p-4, 0x1.139f10286e5d1p-6, + 0x1.5c77bcde9783cp-4, 0x1.771e7534d19c4p-4, 0x1.a82a0493481aap-6, -0x1.f4e605434619ap-4, + -0x1.d69618444dc00p-4, 0x1.9372a72390881p-5, 0x1.b3e4d22624ea7p-4, 0x1.0c970691b13d2p-4, + -0x1.f656d1780e2abp-8, -0x1.ff0953b707619p-4, -0x1.8fbcccf9a29bcp-4, 0x1.3fed96a11c9cbp-4, + 0x1.ebbd8d2379d45p-4, 0x1.1d3443d47a2a8p-5, -0x1.4d1e22e3bd216p-5, -0x1.e426a150e013dp-4, + -0x1.2bedb0aa1e360p-4, 0x1.9ef43b3bb1970p-4, 0x1.fff622f0b4c76p-4, 0x1.921d0068ab87cp-10, + -0x1.21a799e75eae6p-4, -0x1.a63090d92668cp-4, -0x1.64c7db5c267f9p-5, 0x1.dfeae54d748b7p-4, + 0x1.ef178b5824a5cp-4, -0x1.04fb85c0b11a4p-5, -0x1.87c400ccba1dfp-4, -0x1.49a44a5986bf0p-4, + -0x1.5f6d087d32e1bp-7, 0x1.fe1cb1f06f01bp-4, 0x1.ba5aa66e656edp-4, -0x1.01cfc3cde7715p-4, + -0x1.d17e77f894152p-4, -0x1.aa6c846f9e302p-5, 0x1.76dd9baae50eap-6, 0x1.f7599b30c0ae6p-4, + 0x1.6591917330a17p-4, -0x1.6e7443e5cbeb5p-4, -0x1.f97f91411f4d7p-4, -0x1.45576946433abp-6, + 0x1.c1249d4790239p-5, 0x1.cc1f115182833p-4, 0x1.edc1968819b56p-5, -0x1.c08c4403fae56p-4, + -0x1.fce15f899b727p-4, 0x1.c378607984b7bp-7, 0x1.532827c355097p-4, 0x1.7f8ecb7161a9dp-4, + 0x1.d934f765dd53dp-6, -0x1.f22531f70da3bp-4, -0x1.db6525aed843ep-4, 0x1.7c3a9514067ecp-5, + 0x1.ad2bcb3fb4d62p-4, 0x1.1734d4a263030p-4, -0x1.2d866028485cfp-8, -0x1.ffa72e26e2fcfp-4, + -0x1.9777ef506334bp-4, 0x1.360589e70e593p-4, 0x1.e817bd2c3fbebp-4, 0x1.35410e3ed224ep-5, + -0x1.35410e3ed224ep-5, -0x1.e817bd2c3fbebp-4, -0x1.360589e70e593p-4, 0x1.9777ef506334bp-4, + 0x1.ffa72e26e2fcfp-4, 0x1.2d866028485cfp-8, -0x1.1734d4a263030p-4, -0x1.ad2bcb3fb4d62p-4, + -0x1.7c3a9514067ecp-5, 0x1.db6525aed843ep-4, 0x1.f22531f70da3bp-4, -0x1.d934f765dd53dp-6, + -0x1.7f8ecb7161a9dp-4, -0x1.532827c355097p-4, -0x1.c378607984b7bp-7, 0x1.fce15f899b727p-4, + 0x1.c08c4403fae56p-4, -0x1.edc1968819b56p-5, -0x1.cc1f115182833p-4, -0x1.c1249d4790239p-5, + 0x1.45576946433abp-6, 0x1.f97f91411f4d7p-4, 0x1.6e7443e5cbeb5p-4, -0x1.6591917330a17p-4, + -0x1.f7599b30c0ae6p-4, -0x1.76dd9baae50eap-6, 0x1.aa6c846f9e302p-5, 0x1.d17e77f894152p-4, + 0x1.01cfc3cde7715p-4, -0x1.ba5aa66e656edp-4, -0x1.fe1cb1f06f01bp-4, 0x1.5f6d087d32e1bp-7, + 0x1.49a44a5986bf0p-4, 0x1.87c400ccba1dfp-4, 0x1.04fb85c0b11a4p-5, -0x1.ef178b5824a5cp-4, + -0x1.dfeae54d748b7p-4, 0x1.64c7db5c267f9p-5, 0x1.a63090d92668cp-4, 0x1.21a799e75eae6p-4, + -0x1.921d0068ab87cp-10, -0x1.fff622f0b4c76p-4, -0x1.9ef43b3bb1970p-4, 0x1.2bedb0aa1e360p-4, + 0x1.e426a150e013dp-4, 0x1.4d1e22e3bd216p-5, -0x1.1d3443d47a2a8p-5, -0x1.ebbd8d2379d45p-4, + -0x1.3fed96a11c9cbp-4, 0x1.8fbcccf9a29bcp-4, 0x1.ff0953b707619p-4, 0x1.f656d1780e2abp-8, + -0x1.0c970691b13d2p-4, -0x1.b3e4d22624ea7p-4, -0x1.9372a72390881p-5, 0x1.d69618444dc00p-4, + 0x1.f4e605434619ap-4, -0x1.a82a0493481aap-6, -0x1.771e7534d19c4p-4, -0x1.5c77bcde9783cp-4, + -0x1.139f10286e5d1p-6, 0x1.fb57969f18f26p-4, 0x1.c678b366aae94p-4, -0x1.d797764f30996p-5, + -0x1.c678b5a657c5cp-4, -0x1.d7977781a28cep-5, -0x1.139f109b66925p-6, -0x1.fb5795b264eebp-4, + 0x1.771e74ce2a840p-4, -0x1.5c77bbd8ea278p-4, 0x1.f4e602e12cb73p-4, 0x1.a82a041450f07p-6, + 0x1.9372a7ee194e6p-5, 0x1.d696180988d55p-4, -0x1.0c9706b08aa8cp-4, 0x1.b3e4d29e4f476p-4, + -0x1.ff09552fc7c74p-4, 0x1.f656cf8b6ae38p-8, -0x1.3fed95d193131p-4, -0x1.8fbccc3cce4adp-4, + 0x1.1d3444a115694p-5, -0x1.ebbd8dd76707cp-4, 0x1.e426a0d01b4ddp-4, -0x1.4d1e22f942e9ep-5, + 0x1.9ef43bde61a8ap-4, 0x1.2bedb096a9d2bp-4, -0x1.921d000f88e10p-10, 0x1.fff6232db7389p-4, + -0x1.a630904ac5574p-4, 0x1.21a79addfa90cp-4, -0x1.dfeae582979bap-4, -0x1.64c7dc9d6feb3p-5, + -0x1.04fb85ba5a712p-5, -0x1.ef178bb8bdf47p-4, 0x1.49a449d6e0182p-4, -0x1.87c3ff96468d0p-4, + 0x1.fe1cb3b9ee37cp-4, 0x1.5f6d087911f7fp-7, 0x1.01cfc4343949cp-4, 0x1.ba5aa56ce5651p-4, + -0x1.aa6c83f38ad74p-5, 0x1.d17e774787a43p-4, -0x1.f75999e7877c0p-4, 0x1.76dd9bc17d5c9p-6, + -0x1.6e74444a93051p-4, -0x1.659191cc3db25p-4, 0x1.455768d7d4b92p-6, -0x1.f97f90dc00344p-4, + 0x1.cc1f10c030526p-4, -0x1.c1249ab46791dp-5, 0x1.c08c446863f67p-4, 0x1.edc195ad3666ap-5, + 0x1.c3785f141aef9p-7, 0x1.fce1607312e1ep-4, -0x1.7f8eccf4db3fcp-4, 0x1.5328282a10edap-4, + -0x1.f2253274e929fp-4, -0x1.d934f9282456ap-6, -0x1.7c3a950c959c8p-5, -0x1.db65264aa6944p-4, + 0x1.1734d3b216983p-4, -0x1.ad2bcaa8aa618p-4, 0x1.ffa72d3001192p-4, -0x1.2d8660b7ad490p-8, + 0x1.360589babd787p-4, 0x1.9777efff7b58fp-4, -0x1.35410e5635384p-5, 0x1.e817bd86e950ap-4, + -0x1.e817bd86e950ap-4, 0x1.35410e5635384p-5, -0x1.9777efff7b58fp-4, -0x1.360589babd787p-4, + 0x1.2d8660b7ad490p-8, -0x1.ffa72d3001192p-4, 0x1.ad2bcaa8aa618p-4, -0x1.1734d3b216983p-4, + 0x1.db65264aa6944p-4, 0x1.7c3a950c959c8p-5, 0x1.d934f9282456ap-6, 0x1.f2253274e929fp-4, + -0x1.5328282a10edap-4, 0x1.7f8eccf4db3fcp-4, -0x1.fce1607312e1ep-4, -0x1.c3785f141aef9p-7, + -0x1.edc195ad3666ap-5, -0x1.c08c446863f67p-4, 0x1.c1249ab46791dp-5, -0x1.cc1f10c030526p-4, + 0x1.f97f90dc00344p-4, -0x1.455768d7d4b92p-6, 0x1.659191cc3db25p-4, 0x1.6e74444a93051p-4, + -0x1.76dd9bc17d5c9p-6, 0x1.f75999e7877c0p-4, -0x1.d17e774787a43p-4, 0x1.aa6c83f38ad74p-5, + -0x1.ba5aa56ce5651p-4, -0x1.01cfc4343949cp-4, -0x1.5f6d087911f7fp-7, -0x1.fe1cb3b9ee37cp-4, + 0x1.87c3ff96468d0p-4, -0x1.49a449d6e0182p-4, 0x1.ef178bb8bdf47p-4, 0x1.04fb85ba5a712p-5, + 0x1.64c7dc9d6feb3p-5, 0x1.dfeae582979bap-4, -0x1.21a79addfa90cp-4, 0x1.a630904ac5574p-4, + -0x1.fff6232db7389p-4, 0x1.921d000f88e10p-10, -0x1.2bedb096a9d2bp-4, -0x1.9ef43bde61a8ap-4, + 0x1.4d1e22f942e9ep-5, -0x1.e426a0d01b4ddp-4, 0x1.ebbd8dd76707cp-4, -0x1.1d3444a115694p-5, + 0x1.8fbccc3cce4adp-4, 0x1.3fed95d193131p-4, -0x1.f656cf8b6ae38p-8, 0x1.ff09552fc7c74p-4, + -0x1.b3e4d29e4f476p-4, 0x1.0c9706b08aa8cp-4, -0x1.d696180988d55p-4, -0x1.9372a7ee194e6p-5, + -0x1.a82a041450f07p-6, -0x1.f4e602e12cb73p-4, 0x1.5c77bbd8ea278p-4, -0x1.771e74ce2a840p-4, + 0x1.fb5795b264eebp-4, 0x1.139f109b66925p-6, 0x1.d7977781a2851p-5, 0x1.c678b5a657c54p-4, + 0x1.4c1e54886e9fcp-3, 0x1.1441f0f7a3604p-3, 0x1.4cbdec7022520p-7, -0x1.f36d5e7e53955p-5, + 0x1.21428fef55a70p-6, 0x1.2274f1bc33495p-6, 0x1.d3a1612e2169ep-5, 0x1.3dd96d5a607cep-7, + -0x1.9709eacdee9a0p-5, 0x1.b815c63b628eep-6, 0x1.7383e14e2f467p-9, 0x1.1b014c88496fap-5, + 0x1.05f545a7cd02fp-3, -0x1.93958bb4f7d65p-10, -0x1.161e4b2b3da76p-7, 0x1.80af8fe1e9f26p-6, + -0x1.2963deb05af33p-6, -0x1.2c2544fb8ea1fp-5, 0x1.ab9bf95138092p-3, 0x1.6079ba1b0d827p-6, + 0x1.69eda55cb22dbp-3, -0x1.4a763712b7a45p-5, 0x1.15914713b2a8ap-6, -0x1.1f552e1881d8ap-3, + 0x1.11f5db256f05fp-6, -0x1.f30986c975c3dp-6, 0x1.43ef25f414a17p-4, 0x1.1ac646a2b0163p-8, + -0x1.b58872dd8ff5ep-6, 0x1.291269dca26f7p-2, 0x1.0abcbd8addcf5p-4, -0x1.b906dde29a7c2p-4, + -0x1.6abaf2a1704ecp-5, 0x1.a1dd748cb958bp-7, -0x1.0497d1ad8796ep-5, -0x1.36e6a49db30dep-5, + -0x1.2ce9df26a09b1p-4, 0x1.009b4c16a3036p-2, -0x1.58153790d7c0ep-4, 0x1.c372a16794bcbp-6, + 0x1.779f4b179476cp-5, -0x1.9d90436305a97p-5, -0x1.22b57525808a2p-5, -0x1.aa5923fcb66dep-5, + -0x1.31f7b634d8ea4p-5, -0x1.2a2ecbb221c1bp-4, -0x1.1d0dceb464a8bp-6, 0x1.3135aac204019p-5, + 0x1.21b0d8aa23507p-16, -0x1.2e10a3afb8291p-4, 0x1.608c40ce968dap-3, 0x1.56632c74436d0p-4, + 0x1.3bddc72511769p-11, 0x1.1bec0dbf0425bp-6, -0x1.f43d9d2b90797p-8, -0x1.498c28cd9785fp-4, + 0x1.4cfe238b2378ap-5, 0x1.8100d157f4b7fp-3, 0x1.0370cdbf5a1efp-3, -0x1.e7bc32328bf83p-8, + 0x1.3042fc1432271p-5, 0x1.c5f43be00e7c7p-4, 0x1.11abd3e18c044p-6, -0x1.3ee7342c959e4p-4, + 0x1.3ee7342c959e4p-4, -0x1.11abd3e18c044p-6, -0x1.c5f43be00e7c7p-4, -0x1.3042fc1432271p-5, + 0x1.e7bc32328bf83p-8, -0x1.0370cdbf5a1efp-3, -0x1.8100d157f4b7fp-3, -0x1.4cfe238b2378ap-5, + 0x1.498c28cd9785fp-4, 0x1.f43d9d2b90797p-8, -0x1.1bec0dbf0425bp-6, -0x1.3bddc72511769p-11, + -0x1.56632c74436d0p-4, -0x1.608c40ce968dap-3, 0x1.2e10a3afb8291p-4, -0x1.21b0d8aa23507p-16, + -0x1.3135aac204019p-5, 0x1.1d0dceb464a8bp-6, 0x1.2a2ecbb221c1bp-4, 0x1.31f7b634d8ea4p-5, + 0x1.aa5923fcb66dep-5, 0x1.22b57525808a2p-5, 0x1.9d90436305a97p-5, -0x1.779f4b179476cp-5, + -0x1.c372a16794bcbp-6, 0x1.58153790d7c0ep-4, -0x1.009b4c16a3036p-2, 0x1.2ce9df26a09b1p-4, + 0x1.36e6a49db30dep-5, 0x1.0497d1ad8796ep-5, -0x1.a1dd748cb958bp-7, 0x1.6abaf2a1704ecp-5, + 0x1.b906dde29a7c2p-4, -0x1.0abcbd8addcf5p-4, -0x1.291269dca26f7p-2, 0x1.b58872dd8ff5ep-6, + -0x1.1ac646a2b0163p-8, -0x1.43ef25f414a17p-4, 0x1.f30986c975c3dp-6, -0x1.11f5db256f05fp-6, + 0x1.1f552e1881d8ap-3, -0x1.15914713b2a8ap-6, 0x1.4a763712b7a45p-5, -0x1.69eda55cb22dbp-3, + -0x1.6079ba1b0d827p-6, -0x1.ab9bf95138092p-3, 0x1.2c2544fb8ea1fp-5, 0x1.2963deb05af33p-6, + -0x1.80af8fe1e9f26p-6, 0x1.161e4b2b3da76p-7, 0x1.93958bb4f7d65p-10, -0x1.05f545a7cd02fp-3, + -0x1.1b014c88496fap-5, -0x1.7383e14e2f467p-9, -0x1.b815c63b628eep-6, 0x1.9709eacdee9a0p-5, + -0x1.3dd96d5a607cdp-7, -0x1.d3a1612e2169ep-5, -0x1.2274f1bc3348ep-6, -0x1.21428fef55a6fp-6, + 0x1.f36d5e7e5390fp-5, -0x1.4cbdec7022539p-7, -0x1.1441eff458828p-3, -0x1.4c1e545f089ffp-3, + -0x1.52190d4dc9d45p-5, -0x1.c0e6229acbf34p-5, -0x1.0568c5ffaf5d9p-5, 0x1.ac4519d07fc13p-7, + -0x1.0210b627819cdp-3, -0x1.678477fe6073dp-3, 0x1.46ae64470e301p-6, 0x1.02b104e130e32p-2, + 0x1.2292af80ad367p-3, 0x1.108c59b61bc9ap-5, 0x1.c65fc05b50938p-5, -0x1.99038366880d0p-5, + 0x1.d1a8cae2c9b88p-7, -0x1.05e29aeae4a5ap-3, 0x1.43900e952d292p-3, -0x1.ae95d74a5e75ap-5, + 0x1.a8fee23d6fed2p-3, 0x1.54b909af190b2p-7, 0x1.571c935b9b7b1p-5, 0x1.c6068df1bfc65p-5, + 0x1.3383664a0127fp-5, 0x1.71521830ac474p-3, 0x1.8a83b3b80f05dp-6, -0x1.53357eed7bc7bp-6, + -0x1.489a13da25398p-5, 0x1.910d175b1b397p-4, -0x1.94c1079869f27p-5, 0x1.00c2977772d3fp-6, + 0x1.1e6939625ff8bp-4, 0x1.69a23bd3b1f7dp-6, 0x1.96b9739f8a439p-10, 0x1.01c27b2e5514fp-4, + -0x1.9d0c18c377659p-8, 0x1.503e074ee70e1p-3, 0x1.820ab7ac3b995p-4, -0x1.74f35b74263fcp-4, + 0x1.2dd2151704120p-6, 0x1.c698cecfa013bp-5, -0x1.4b8d0fcf46cc1p-7, -0x1.7d47f74906d89p-3, + 0x1.2b2befa737e0ap-4, -0x1.2cb2d54bede98p-4, 0x1.626c3cc4cb6a6p-6, 0x1.60126fe8da30cp-5, + -0x1.01675d1b60162p-3, -0x1.28bedcc873092p-4, -0x1.7285bf32ee8abp-7, -0x1.dde734be3aec0p-4, + 0x1.e3a371049e768p-9, 0x1.ddd83aeaacb22p-11, -0x1.1189649501123p-7, 0x1.aa94d4a84e63fp-5, + 0x1.01371afaba986p-6, 0x1.1e6ce9bd5a113p-4, -0x1.5246c3ad7f8e7p-4, -0x1.c4eff632ae96fp-6, + -0x1.79637c66d8a05p-3, 0x1.5ecc674add2e1p-5, 0x1.912ec918d0370p-7, -0x1.bbe009c6fa7a5p-4, + -0x1.b9cd5bd10a351p-4, -0x1.7b2d21dba8d6fp-9, 0x1.e59f4c9a08c2fp-6, 0x1.e397addd7cbddp-8, + -0x1.e397addd7cbddp-8, -0x1.e59f4c9a08c2fp-6, 0x1.7b2d21dba8d6fp-9, 0x1.b9cd5bd10a351p-4, + 0x1.bbe009c6fa7a5p-4, -0x1.912ec918d0370p-7, -0x1.5ecc674add2e1p-5, 0x1.79637c66d8a05p-3, + 0x1.c4eff632ae96fp-6, 0x1.5246c3ad7f8e7p-4, -0x1.1e6ce9bd5a113p-4, -0x1.01371afaba986p-6, + -0x1.aa94d4a84e63fp-5, 0x1.1189649501123p-7, -0x1.ddd83aeaacb22p-11, -0x1.e3a371049e768p-9, + 0x1.dde734be3aec0p-4, 0x1.7285bf32ee8abp-7, 0x1.28bedcc873092p-4, 0x1.01675d1b60162p-3, + -0x1.60126fe8da30cp-5, -0x1.626c3cc4cb6a6p-6, 0x1.2cb2d54bede98p-4, -0x1.2b2befa737e0ap-4, + 0x1.7d47f74906d89p-3, 0x1.4b8d0fcf46cc1p-7, -0x1.c698cecfa013bp-5, -0x1.2dd2151704120p-6, + 0x1.74f35b74263fcp-4, -0x1.820ab7ac3b995p-4, -0x1.503e074ee70e1p-3, 0x1.9d0c18c377659p-8, + -0x1.01c27b2e5514fp-4, -0x1.96b9739f8a439p-10, -0x1.69a23bd3b1f7dp-6, -0x1.1e6939625ff8bp-4, + -0x1.00c2977772d3fp-6, 0x1.94c1079869f27p-5, -0x1.910d175b1b397p-4, 0x1.489a13da25398p-5, + 0x1.53357eed7bc7bp-6, -0x1.8a83b3b80f05dp-6, -0x1.71521830ac474p-3, -0x1.3383664a0127fp-5, + -0x1.c6068df1bfc65p-5, -0x1.571c935b9b7b1p-5, -0x1.54b909af190b2p-7, -0x1.a8fee23d6fed2p-3, + 0x1.ae95d74a5e75ap-5, -0x1.43900e952d292p-3, 0x1.05e29aeae4a5ap-3, -0x1.d1a8cae2c9b88p-7, + 0x1.99038366880d0p-5, -0x1.c65fc05b50938p-5, -0x1.108c59b61bc9ap-5, -0x1.2292af80ad367p-3, + -0x1.02b104e130e32p-2, -0x1.46ae64470e301p-6, 0x1.678477fe6073dp-3, 0x1.0210b627819ccp-3, + -0x1.ac4519d07fc33p-7, 0x1.0568c5ffaf5cdp-5, 0x1.c0e62316e6b50p-5, 0x1.52190d441d19fp-5, + 0x1.c1249f2b7d577p-5, -0x1.cc1f112c954abp-4, -0x1.f4e6018933536p-4, 0x1.a82a0bdf3aeb2p-6, + 0x1.87c4004e03fdep-4, 0x1.49a44b5c80932p-4, 0x1.2d864fe034855p-8, -0x1.ffa72dba5cc2ep-4, + -0x1.9ef440f40d961p-4, 0x1.2bedb229888d1p-4, 0x1.ebbd8f82aa377p-4, 0x1.1d344826b415dp-5, + -0x1.7c3a929201a6fp-5, -0x1.db65299d4449cp-4, -0x1.01cfcc3fbe689p-4, 0x1.ba5aa6fc0d618p-4, + 0x1.fb5797c018f2dp-4, -0x1.139f0846f090ep-6, -0x1.6e74464b38388p-4, -0x1.6591913bebee6p-4, + -0x1.c378681196325p-7, 0x1.fce160954cdc4p-4, 0x1.b3e4d34800d68p-4, -0x1.0c9705b5205b1p-4, + -0x1.dfeae35cb88c8p-4, -0x1.64c7dce473d1dp-5, 0x1.354107e8c8e66p-5, 0x1.e817b80066b7ep-4, + 0x1.21a79aa612127p-4, -0x1.a63092cd77391p-4, -0x1.ff0954eb909f3p-4, 0x1.f656f12b6564bp-8, + 0x1.5328284a4e847p-4, 0x1.7f8ecef832900p-4, 0x1.76dda0de61f45p-6, -0x1.f7599d04525efp-4, + -0x1.c678b41428e2fp-4, 0x1.d7977509875afp-5, 0x1.d17e757b63fafp-4, 0x1.aa6c81ab64455p-5, + -0x1.d935005e4112dp-6, -0x1.f2252ddbca709p-4, -0x1.3fed94b3f3a1ep-4, 0x1.8fbcc7285c3a2p-4, + 0x1.fff621990592bp-4, 0x1.921dc3de31badp-10, -0x1.36058bc1322c2p-4, -0x1.9777f16189aadp-4, + -0x1.04fb7ebd973bep-5, 0x1.ef17863485df2p-4, 0x1.d6961343900c4p-4, -0x1.9372a3c1fd798p-5, + -0x1.c08c420c60ec1p-4, -0x1.edc19bb2d10adp-5, 0x1.45577379c545ep-6, 0x1.f97f91fcb32adp-4, + 0x1.5c77bb5c54b84p-4, -0x1.771e73bb2e62ep-4, -0x1.fe1cb05e7250fp-4, -0x1.5f6cf6af4f187p-7, + 0x1.1734d86b13c61p-4, 0x1.ad2bcbee07a14p-4, 0x1.4d1e23e2e56dfp-5, -0x1.e426a53579926p-4, + -0x1.e426a53579926p-4, 0x1.4d1e23e2e56dfp-5, 0x1.ad2bcbee07a14p-4, 0x1.1734d86b13c61p-4, + -0x1.5f6cf6af4f187p-7, -0x1.fe1cb05e7250fp-4, -0x1.771e73bb2e62ep-4, 0x1.5c77bb5c54b84p-4, + 0x1.f97f91fcb32adp-4, 0x1.45577379c545ep-6, -0x1.edc19bb2d10adp-5, -0x1.c08c420c60ec1p-4, + -0x1.9372a3c1fd798p-5, 0x1.d6961343900c4p-4, 0x1.ef17863485df2p-4, -0x1.04fb7ebd973bep-5, + -0x1.9777f16189aadp-4, -0x1.36058bc1322c2p-4, 0x1.921dc3de31badp-10, 0x1.fff621990592bp-4, + 0x1.8fbcc7285c3a2p-4, -0x1.3fed94b3f3a1ep-4, -0x1.f2252ddbca709p-4, -0x1.d935005e4112dp-6, + 0x1.aa6c81ab64455p-5, 0x1.d17e757b63fafp-4, 0x1.d7977509875afp-5, -0x1.c678b41428e2fp-4, + -0x1.f7599d04525efp-4, 0x1.76dda0de61f45p-6, 0x1.7f8ecef832900p-4, 0x1.5328284a4e847p-4, + 0x1.f656f12b6564bp-8, -0x1.ff0954eb909f3p-4, -0x1.a63092cd77391p-4, 0x1.21a79aa612127p-4, + 0x1.e817b80066b7ep-4, 0x1.354107e8c8e66p-5, -0x1.64c7dce473d1dp-5, -0x1.dfeae35cb88c8p-4, + -0x1.0c9705b5205b1p-4, 0x1.b3e4d34800d68p-4, 0x1.fce160954cdc4p-4, -0x1.c378681196325p-7, + -0x1.6591913bebee6p-4, -0x1.6e74464b38388p-4, -0x1.139f0846f090ep-6, 0x1.fb5797c018f2dp-4, + 0x1.ba5aa6fc0d618p-4, -0x1.01cfcc3fbe689p-4, -0x1.db65299d4449cp-4, -0x1.7c3a929201a6fp-5, + 0x1.1d344826b415dp-5, 0x1.ebbd8f82aa377p-4, 0x1.2bedb229888d1p-4, -0x1.9ef440f40d961p-4, + -0x1.ffa72dba5cc2ep-4, 0x1.2d864fe034855p-8, 0x1.49a44b5c80932p-4, 0x1.87c4004e03fdep-4, + 0x1.a82a0bdf3aeb2p-6, -0x1.f4e6018933536p-4, -0x1.cc1f112c954abp-4, 0x1.c1249f2b7d56ep-5, + -0x1.cc1f10ce350f3p-4, -0x1.c1249ef3fcd68p-5, -0x1.a82a0d6f784b6p-6, -0x1.f4e602eb857c9p-4, + 0x1.49a44ce1302eep-4, -0x1.87c400fb7da78p-4, 0x1.ffa72ef626b75p-4, 0x1.2d864ead197dfp-8, + 0x1.2bedb2d3ea9c8p-4, 0x1.9ef440f3ce03fp-4, -0x1.1d3447bb36df1p-5, 0x1.ebbd8cfa3e273p-4, + -0x1.db65273889d50p-4, 0x1.7c3a91900b9d3p-5, -0x1.ba5aa5e729055p-4, -0x1.01cfccbcbb748p-4, + -0x1.139f0899af6e3p-6, -0x1.fb57982c1c4e5p-4, 0x1.65918fd047062p-4, -0x1.6e7445a6d4e3ap-4, + 0x1.fce1620822883p-4, 0x1.c37867afceac7p-7, 0x1.0c97060290a91p-4, 0x1.b3e4d2c5b2518p-4, + -0x1.64c7dcca9d37fp-5, 0x1.dfeae5a3362f1p-4, -0x1.e817b77511ba8p-4, 0x1.3541084f31b3fp-5, + -0x1.a6309257d93dap-4, -0x1.21a799a8debefp-4, -0x1.f656f25cfa61cp-8, -0x1.ff0953c4e09c9p-4, + 0x1.7f8ece8441048p-4, -0x1.532828f24a13ap-4, 0x1.f7599bfcf2d90p-4, 0x1.76dd9fa594893p-6, + 0x1.d79774d76ed02p-5, 0x1.c678b38f91017p-4, -0x1.aa6c81e5ba137p-5, 0x1.d17e75f3b7f98p-4, + -0x1.f2252e48b8cacp-4, 0x1.d934ff6ae24bfp-6, -0x1.8fbcc843d9895p-4, -0x1.3fed93cde1a09p-4, + 0x1.921dc64651453p-10, -0x1.fff6217cfaafep-4, 0x1.9777ef940bf46p-4, -0x1.36058bae030eep-4, + 0x1.ef17869b8b4a5p-4, 0x1.04fb7ed06b7fap-5, 0x1.9372a41f3e810p-5, 0x1.d69614b52f8e3p-4, + -0x1.edc19b9b427d0p-5, 0x1.c08c4389c51cbp-4, -0x1.f97f90d3af180p-4, 0x1.455774e9e6b8ep-6, + -0x1.771e747f09ef9p-4, -0x1.5c77ba96e097ep-4, 0x1.5f6cf6d016a09p-7, -0x1.fe1cafb9a8034p-4, + 0x1.ad2bcd0b5a9efp-4, -0x1.1734d8596174bp-4, 0x1.e426a6ad3c2d5p-4, 0x1.4d1e23a9daf61p-5, + 0x1.4d1e23a9daf61p-5, 0x1.e426a6ad3c2d5p-4, -0x1.1734d8596174bp-4, 0x1.ad2bcd0b5a9efp-4, + -0x1.fe1cafb9a8034p-4, 0x1.5f6cf6d016a09p-7, -0x1.5c77ba96e097ep-4, -0x1.771e747f09ef9p-4, + 0x1.455774e9e6b8ep-6, -0x1.f97f90d3af180p-4, 0x1.c08c4389c51cbp-4, -0x1.edc19b9b427d0p-5, + 0x1.d69614b52f8e3p-4, 0x1.9372a41f3e810p-5, 0x1.04fb7ed06b7fap-5, 0x1.ef17869b8b4a5p-4, + -0x1.36058bae030eep-4, 0x1.9777ef940bf46p-4, -0x1.fff6217cfaafep-4, 0x1.921dc64651453p-10, + -0x1.3fed93cde1a09p-4, -0x1.8fbcc843d9895p-4, 0x1.d934ff6ae24bfp-6, -0x1.f2252e48b8cacp-4, + 0x1.d17e75f3b7f98p-4, -0x1.aa6c81e5ba137p-5, 0x1.c678b38f91017p-4, 0x1.d79774d76ed02p-5, + 0x1.76dd9fa594893p-6, 0x1.f7599bfcf2d90p-4, -0x1.532828f24a13ap-4, 0x1.7f8ece8441048p-4, + -0x1.ff0953c4e09c9p-4, -0x1.f656f25cfa61cp-8, -0x1.21a799a8debefp-4, -0x1.a6309257d93dap-4, + 0x1.3541084f31b3fp-5, -0x1.e817b77511ba8p-4, 0x1.dfeae5a3362f1p-4, -0x1.64c7dcca9d37fp-5, + 0x1.b3e4d2c5b2518p-4, 0x1.0c97060290a91p-4, 0x1.c37867afceac7p-7, 0x1.fce1620822883p-4, + -0x1.6e7445a6d4e3ap-4, 0x1.65918fd047062p-4, -0x1.fb57982c1c4e5p-4, -0x1.139f0899af6e3p-6, + -0x1.01cfccbcbb748p-4, -0x1.ba5aa5e729055p-4, 0x1.7c3a91900b9d3p-5, -0x1.db65273889d50p-4, + 0x1.ebbd8cfa3e273p-4, -0x1.1d3447bb36df1p-5, 0x1.9ef440f3ce03fp-4, 0x1.2bedb2d3ea9c8p-4, + 0x1.2d864ead197dfp-8, 0x1.ffa72ef626b75p-4, -0x1.87c400fb7da78p-4, 0x1.49a44ce1302eep-4, + -0x1.f4e602eb857c9p-4, -0x1.a82a0d6f784b6p-6, -0x1.c1249ef3fcd36p-5, -0x1.cc1f10ce350f9p-4, + -0x1.8a57a4e3c48dap-4, 0x1.3264842587724p-7, -0x1.5aa4623644b69p-10, -0x1.653854414af68p-5, + 0x1.4cb4192413674p-4, -0x1.b31f0f1edfcfbp-6, -0x1.f144e1ab78002p-4, -0x1.94355eedca28bp-6, + 0x1.133a699763c44p-4, 0x1.58813c4c55ec4p-3, 0x1.b28f4600d378ep-5, -0x1.a453a5b5bb051p-3, + 0x1.5f7eb3c2bf031p-3, -0x1.294d00ca147b3p-4, 0x1.49736c10c91c7p-3, 0x1.7a5e3abff5e52p-7, + 0x1.6d89e03db2c35p-9, -0x1.773a2dad844ffp-4, -0x1.87b092856272ep-5, 0x1.18da43f9522f7p-5, + 0x1.751542f4e70b2p-4, 0x1.82f77bf7f9f86p-13, -0x1.131f90842e6c2p-5, -0x1.a7fdd2c7356f2p-7, + -0x1.3142ad0c6a46bp-5, 0x1.f11d3ce4abce8p-3, 0x1.c40d4a885fec4p-3, 0x1.ca3f6a32bb5fdp-7, + 0x1.7017ef39bfb00p-5, 0x1.4225f964ac08fp-3, -0x1.3e00e4a880c28p-6, 0x1.0b5db754a83afp-13, + 0x1.75a058714afc7p-5, -0x1.a1ea28861ee61p-6, 0x1.630d26eadac02p-6, -0x1.97ab3cb3a7e35p-6, + -0x1.f6de694bb613fp-4, 0x1.60f236c1f0969p-9, 0x1.0c16604810f23p-11, 0x1.660b46a1d1e0cp-7, + -0x1.a91b0d5fc34c8p-4, -0x1.0fccdfe67bc92p-6, -0x1.d64c2b951ca89p-4, 0x1.492d22fc8459cp-8, + 0x1.333f9b566212ap-7, -0x1.764107cf11acap-3, 0x1.23a971e1802fbp-6, 0x1.419e2206d15e1p-3, + -0x1.120896be95aabp-6, 0x1.926296521143cp-5, -0x1.1a2603aafc0fbp-5, 0x1.ca3108f55fcdcp-4, + -0x1.3d5f6fc0502b3p-10, 0x1.c51c89b908eedp-4, 0x1.053aa340bcb58p-4, 0x1.fe7214a654959p-7, + -0x1.ac306b1e16bbfp-5, -0x1.12d148852b2c3p-5, -0x1.f2efd7524d723p-6, -0x1.2905e15e6f1fep-5, + -0x1.98c36ae4fc1cap-4, 0x1.93b0ddf748729p-5, -0x1.02e4e11540719p-3, -0x1.a0ee28604b354p-6, + -0x1.a0ee28604b354p-6, -0x1.02e4e11540719p-3, 0x1.93b0ddf748729p-5, -0x1.98c36ae4fc1cap-4, + -0x1.2905e15e6f1fep-5, -0x1.f2efd7524d723p-6, -0x1.12d148852b2c3p-5, -0x1.ac306b1e16bbfp-5, + 0x1.fe7214a654959p-7, 0x1.053aa340bcb58p-4, 0x1.c51c89b908eedp-4, -0x1.3d5f6fc0502b3p-10, + 0x1.ca3108f55fcdcp-4, -0x1.1a2603aafc0fbp-5, 0x1.926296521143cp-5, -0x1.120896be95aabp-6, + 0x1.419e2206d15e1p-3, 0x1.23a971e1802fbp-6, -0x1.764107cf11acap-3, 0x1.333f9b566212ap-7, + 0x1.492d22fc8459cp-8, -0x1.d64c2b951ca89p-4, -0x1.0fccdfe67bc92p-6, -0x1.a91b0d5fc34c8p-4, + 0x1.660b46a1d1e0cp-7, 0x1.0c16604810f23p-11, 0x1.60f236c1f0969p-9, -0x1.f6de694bb613fp-4, + -0x1.97ab3cb3a7e35p-6, 0x1.630d26eadac02p-6, -0x1.a1ea28861ee61p-6, 0x1.75a058714afc7p-5, + 0x1.0b5db754a83afp-13, -0x1.3e00e4a880c28p-6, 0x1.4225f964ac08fp-3, 0x1.7017ef39bfb00p-5, + 0x1.ca3f6a32bb5fdp-7, 0x1.c40d4a885fec4p-3, 0x1.f11d3ce4abce8p-3, -0x1.3142ad0c6a46bp-5, + -0x1.a7fdd2c7356f2p-7, -0x1.131f90842e6c2p-5, 0x1.82f77bf7f9f86p-13, 0x1.751542f4e70b2p-4, + 0x1.18da43f9522f7p-5, -0x1.87b092856272ep-5, -0x1.773a2dad844ffp-4, 0x1.6d89e03db2c35p-9, + 0x1.7a5e3abff5e52p-7, 0x1.49736c10c91c7p-3, -0x1.294d00ca147b3p-4, 0x1.5f7eb3c2bf031p-3, + -0x1.a453a5b5bb051p-3, 0x1.b28f4600d378ep-5, 0x1.58813c4c55ec4p-3, 0x1.133a699763c44p-4, + -0x1.94355eedca28bp-6, -0x1.f144e1ab78002p-4, -0x1.b31f0f1edfcf3p-6, 0x1.4cb4192413674p-4, + -0x1.653854414af56p-5, -0x1.5aa4623644b26p-10, 0x1.326490255ed0ap-7, -0x1.8a57a4a9eb63dp-4, + -0x1.b69e7b9d41062p-7, -0x1.214f6679086c0p-4, 0x1.23ed0527d3ad5p-3, 0x1.04e3a174d8a0ep-6, + -0x1.0ee8d14c13d5ep-7, -0x1.1abd9816d6e06p-5, -0x1.022efcb976d2ap-5, 0x1.94763cd116004p-3, + -0x1.cb9de331fc26bp-4, 0x1.ea87f0973f49ep-5, 0x1.8a9810ff5174dp-3, -0x1.5d37d2a48145bp-5, + 0x1.a26bfddd2cc1cp-5, -0x1.51e86ee30c870p-4, -0x1.0ffc6621158c7p-5, 0x1.4024e1c3a9157p-8, + 0x1.fb20ada315ec2p-8, -0x1.c8e2415c5135fp-6, 0x1.398111fc7dc61p-5, -0x1.924b60d667d8ap-5, + -0x1.4375088d3c4e0p-9, 0x1.f40f91c97b9dbp-5, 0x1.5b3cb1de4fb45p-3, 0x1.e05efda08a5cbp-4, + 0x1.d3f9cc2fc0e0cp-4, 0x1.6eaf8c588c798p-7, -0x1.fc1286a2b40ccp-7, -0x1.26e7467a7e22bp-4, + 0x1.1c80e2ee04a48p-7, -0x1.284264c867f0cp-7, -0x1.69d1cb3ba11e3p-3, 0x1.67202ccc4988bp-7, + 0x1.4dcd895bdad11p-7, 0x1.1301d514f74d0p-4, 0x1.0082d209edb80p-7, -0x1.efd4821087840p-5, + 0x1.48262c95f7b26p-3, -0x1.738c772fc094ep-5, 0x1.12c9c664d8cf0p-3, -0x1.5347fff84f7dap-4, + -0x1.19ef387b80015p-5, -0x1.5bd8e04e3c902p-5, -0x1.7574c9ef5040ep-4, -0x1.ec4230821b658p-4, + 0x1.75614f711f03ap-3, -0x1.56453950e9295p-7, 0x1.76891fce2cb3cp-6, -0x1.8fbc0fedcbcf4p-4, + -0x1.14aac4f61457dp-5, 0x1.862c2c23a588dp-6, -0x1.421bf91746c3ap-3, 0x1.5a6226bebae4ep-5, + 0x1.c9302c7f2dd10p-7, -0x1.1cd5a694850a0p-4, -0x1.222ca4a0a5fafp-6, -0x1.9863433c59604p-3, + 0x1.1c6f3c6e3bae7p-5, 0x1.cbfd3e20ce0d5p-5, -0x1.7ba181b756ba3p-4, 0x1.57aa56db977bap-6, + -0x1.241296ad2975dp-4, -0x1.982106c415d6fp-4, -0x1.cb9fa30e203fep-6, 0x1.78048b797abacp-3, + 0x1.78048b797abacp-3, -0x1.cb9fa30e203fep-6, -0x1.982106c415d6fp-4, -0x1.241296ad2975dp-4, + 0x1.57aa56db977bap-6, -0x1.7ba181b756ba3p-4, 0x1.cbfd3e20ce0d5p-5, 0x1.1c6f3c6e3bae7p-5, + -0x1.9863433c59604p-3, -0x1.222ca4a0a5fafp-6, -0x1.1cd5a694850a0p-4, 0x1.c9302c7f2dd10p-7, + 0x1.5a6226bebae4ep-5, -0x1.421bf91746c3ap-3, 0x1.862c2c23a588dp-6, -0x1.14aac4f61457dp-5, + -0x1.8fbc0fedcbcf4p-4, 0x1.76891fce2cb3cp-6, -0x1.56453950e9295p-7, 0x1.75614f711f03ap-3, + -0x1.ec4230821b658p-4, -0x1.7574c9ef5040ep-4, -0x1.5bd8e04e3c902p-5, -0x1.19ef387b80015p-5, + -0x1.5347fff84f7dap-4, 0x1.12c9c664d8cf0p-3, -0x1.738c772fc094ep-5, 0x1.48262c95f7b26p-3, + -0x1.efd4821087840p-5, 0x1.0082d209edb80p-7, 0x1.1301d514f74d0p-4, 0x1.4dcd895bdad11p-7, + 0x1.67202ccc4988bp-7, -0x1.69d1cb3ba11e3p-3, -0x1.284264c867f0cp-7, 0x1.1c80e2ee04a48p-7, + -0x1.26e7467a7e22bp-4, -0x1.fc1286a2b40ccp-7, 0x1.6eaf8c588c798p-7, 0x1.d3f9cc2fc0e0cp-4, + 0x1.e05efda08a5cbp-4, 0x1.5b3cb1de4fb45p-3, 0x1.f40f91c97b9dbp-5, -0x1.4375088d3c4e0p-9, + -0x1.924b60d667d8ap-5, 0x1.398111fc7dc61p-5, -0x1.c8e2415c5135fp-6, 0x1.fb20ada315ec2p-8, + 0x1.4024e1c3a9157p-8, -0x1.0ffc6621158c7p-5, -0x1.51e86ee30c870p-4, 0x1.a26bfddd2cc1cp-5, + -0x1.5d37d2a48145bp-5, 0x1.8a9810ff5174dp-3, 0x1.ea87f0973f49ep-5, -0x1.cb9de331fc26bp-4, + 0x1.94763cd116004p-3, -0x1.022efcb976d2ap-5, -0x1.1abd9816d6e06p-5, -0x1.0ee8d14c13d4ep-7, + 0x1.04e3a174d8a28p-6, 0x1.23ed0527d3ad5p-3, -0x1.214f66372caf1p-4, -0x1.b69e888d744aap-7, + 0x1.aa6c813b5ebcbp-5, -0x1.d17e77fef9349p-4, -0x1.ebbd8d3b043bep-4, 0x1.1d343fe2daf85p-5, + 0x1.ad2bcae4093d8p-4, 0x1.1734d3ea16099p-4, -0x1.139f0c93801e5p-6, -0x1.fb5795b08ed8fp-4, + -0x1.53282826204bbp-4, 0x1.7f8ecdd83096cp-4, 0x1.fff6222de5843p-4, 0x1.921d8928ab6dbp-10, + -0x1.49a44a5f26385p-4, -0x1.87c3fff5ffd5fp-4, -0x1.455771127689ap-6, 0x1.f97f938b3029dp-4, + 0x1.b3e4d48d1f140p-4, -0x1.0c97048b3c4f3p-4, -0x1.e817b9afc3370p-4, -0x1.35410e5ae4addp-5, + 0x1.9372a7730e6f8p-5, 0x1.d69618c88ab9ap-4, 0x1.c124a05c5eda6p-5, -0x1.cc1f0cb793360p-4, + -0x1.ef17885eca08ep-4, 0x1.04fb8013c6d11p-5, 0x1.a6309087bc442p-4, 0x1.21a79a2859aa5p-4, + -0x1.c3785a2f334a3p-7, -0x1.fce15d9ef3c23p-4, -0x1.5c77bd6fa22c8p-4, 0x1.771e77ad3c273p-4, + 0x1.ffa72fd170e63p-4, 0x1.2d864e9ea3d66p-8, -0x1.3fed93dd6fd3cp-4, -0x1.8fbccd7ff2871p-4, + -0x1.76dd96e60b534p-6, 0x1.f7599cf8bdcbdp-4, 0x1.ba5aa89b39257p-4, -0x1.01cfc602423a3p-4, + -0x1.e426a5d439c61p-4, -0x1.4d1e22973f7e0p-5, 0x1.7c3a94005e82ap-5, 0x1.db6525e0e9131p-4, + 0x1.d797741f240dep-5, -0x1.c678b267bc9e3p-4, -0x1.f2253154320a6p-4, 0x1.d934f90f007f0p-6, + 0x1.9ef43f3ed2de1p-4, 0x1.2bedb09141184p-4, -0x1.5f6ce6e2a2584p-7, -0x1.fe1cafac82557p-4, + -0x1.659191c014680p-4, 0x1.6e7444355b910p-4, 0x1.ff0954ff98a73p-4, 0x1.f656e1d4f6f03p-8, + -0x1.36058ae3be17dp-4, -0x1.9777ed57b27a9p-4, -0x1.a82a0db957735p-6, 0x1.f4e60402272c6p-4, + 0x1.c08c43ba4322bp-4, -0x1.edc191f6ffc8cp-5, -0x1.dfeae6adfe556p-4, -0x1.64c7df1f71bf8p-5, + 0x1.64c7df1f71bf8p-5, 0x1.dfeae6adfe556p-4, 0x1.edc191f6ffc8cp-5, -0x1.c08c43ba4322bp-4, + -0x1.f4e60402272c6p-4, 0x1.a82a0db957735p-6, 0x1.9777ed57b27a9p-4, 0x1.36058ae3be17dp-4, + -0x1.f656e1d4f6f03p-8, -0x1.ff0954ff98a73p-4, -0x1.6e7444355b910p-4, 0x1.659191c014680p-4, + 0x1.fe1cafac82557p-4, 0x1.5f6ce6e2a2584p-7, -0x1.2bedb09141184p-4, -0x1.9ef43f3ed2de1p-4, + -0x1.d934f90f007f0p-6, 0x1.f2253154320a6p-4, 0x1.c678b267bc9e3p-4, -0x1.d797741f240dep-5, + -0x1.db6525e0e9131p-4, -0x1.7c3a94005e82ap-5, 0x1.4d1e22973f7e0p-5, 0x1.e426a5d439c61p-4, + 0x1.01cfc602423a3p-4, -0x1.ba5aa89b39257p-4, -0x1.f7599cf8bdcbdp-4, 0x1.76dd96e60b534p-6, + 0x1.8fbccd7ff2871p-4, 0x1.3fed93dd6fd3cp-4, -0x1.2d864e9ea3d66p-8, -0x1.ffa72fd170e63p-4, + -0x1.771e77ad3c273p-4, 0x1.5c77bd6fa22c8p-4, 0x1.fce15d9ef3c23p-4, 0x1.c3785a2f334a3p-7, + -0x1.21a79a2859aa5p-4, -0x1.a6309087bc442p-4, -0x1.04fb8013c6d11p-5, 0x1.ef17885eca08ep-4, + 0x1.cc1f0cb793360p-4, -0x1.c124a05c5eda6p-5, -0x1.d69618c88ab9ap-4, -0x1.9372a7730e6f8p-5, + 0x1.35410e5ae4addp-5, 0x1.e817b9afc3370p-4, 0x1.0c97048b3c4f3p-4, -0x1.b3e4d48d1f140p-4, + -0x1.f97f938b3029dp-4, 0x1.455771127689ap-6, 0x1.87c3fff5ffd5fp-4, 0x1.49a44a5f26385p-4, + -0x1.921d8928ab6dbp-10, -0x1.fff6222de5843p-4, -0x1.7f8ecdd83096cp-4, 0x1.53282826204bbp-4, + 0x1.fb5795b08ed8fp-4, 0x1.139f0c93801e5p-6, -0x1.1734d3ea16099p-4, -0x1.ad2bcae4093d8p-4, + -0x1.1d343fe2daf85p-5, 0x1.ebbd8d3b043bep-4, 0x1.d17e77fef934ap-4, -0x1.aa6c813b5eb8bp-5, + -0x1.d17e76f831199p-4, -0x1.aa6c819c50811p-5, -0x1.1d343fd7b4aa4p-5, -0x1.ebbd8c6ad5141p-4, + 0x1.1734d48dcdf4ep-4, -0x1.ad2bca91c1854p-4, 0x1.fb579725866c4p-4, -0x1.139f0b2e89682p-6, + 0x1.7f8ecf3f26675p-4, 0x1.532828e8ad619p-4, -0x1.921d8ec0baae4p-10, 0x1.fff6232569c42p-4, + -0x1.87c4000dacaedp-4, 0x1.49a44b00fae50p-4, -0x1.f97f93beb0325p-4, -0x1.455771625c66cp-6, + -0x1.0c9704af25147p-4, -0x1.b3e4d5009b1a4p-4, 0x1.35410e16e9929p-5, -0x1.e817b7ef3c303p-4, + 0x1.d696180df6c1ep-4, -0x1.9372a7493d1cbp-5, 0x1.cc1f0be09458dp-4, 0x1.c124a0c635391p-5, + 0x1.04fb80b33233ap-5, 0x1.ef17870cbedd2p-4, -0x1.21a79b4fa8995p-4, 0x1.a6308fbe03980p-4, + -0x1.fce15ddfd30dep-4, 0x1.c3785a54ddda7p-7, -0x1.771e7663a46afp-4, -0x1.5c77bc64598f1p-4, + 0x1.2d864c8123234p-8, -0x1.ffa730e31b35fp-4, 0x1.8fbccc1be4c14p-4, -0x1.3fed949af4f06p-4, + 0x1.f7599d45e53e5p-4, 0x1.76dd950faeb01p-6, 0x1.01cfc5e9f35d9p-4, 0x1.ba5aa8ab46938p-4, + -0x1.4d1e21dc8c39ap-5, 0x1.e426a55627944p-4, -0x1.db6525b40bcabp-4, 0x1.7c3a9494322b8p-5, + -0x1.c678b20c55ed7p-4, -0x1.d79773e98712ep-5, -0x1.d934f86a3c886p-6, -0x1.f22531bda2a41p-4, + 0x1.2bedb09bb1f9ap-4, -0x1.9ef43edcb6e8ep-4, 0x1.fe1cb1aef058ap-4, -0x1.5f6ce692471dbp-7, + 0x1.6e744493f25b1p-4, 0x1.659192a709a88p-4, -0x1.f656e4e4ca61ep-8, 0x1.ff09538fd7807p-4, + -0x1.9777ee996941ap-4, 0x1.36058a07b4d13p-4, -0x1.f4e6060bf7facp-4, -0x1.a82a0d2b3bb69p-6, + -0x1.edc18fc1f2541p-5, -0x1.c08c42f607d07p-4, 0x1.64c7df6bd6653p-5, -0x1.dfeae654c6851p-4, + 0x1.dfeae654c6851p-4, -0x1.64c7df6bd6653p-5, 0x1.c08c42f607d07p-4, 0x1.edc18fc1f2541p-5, + 0x1.a82a0d2b3bb69p-6, 0x1.f4e6060bf7facp-4, -0x1.36058a07b4d13p-4, 0x1.9777ee996941ap-4, + -0x1.ff09538fd7807p-4, 0x1.f656e4e4ca61ep-8, -0x1.659192a709a88p-4, -0x1.6e744493f25b1p-4, + 0x1.5f6ce692471dbp-7, -0x1.fe1cb1aef058ap-4, 0x1.9ef43edcb6e8ep-4, -0x1.2bedb09bb1f9ap-4, + 0x1.f22531bda2a41p-4, 0x1.d934f86a3c886p-6, 0x1.d79773e98712ep-5, 0x1.c678b20c55ed7p-4, + -0x1.7c3a9494322b8p-5, 0x1.db6525b40bcabp-4, -0x1.e426a55627944p-4, 0x1.4d1e21dc8c39ap-5, + -0x1.ba5aa8ab46938p-4, -0x1.01cfc5e9f35d9p-4, -0x1.76dd950faeb01p-6, -0x1.f7599d45e53e5p-4, + 0x1.3fed949af4f06p-4, -0x1.8fbccc1be4c14p-4, 0x1.ffa730e31b35fp-4, -0x1.2d864c8123234p-8, + 0x1.5c77bc64598f1p-4, 0x1.771e7663a46afp-4, -0x1.c3785a54ddda7p-7, 0x1.fce15ddfd30dep-4, + -0x1.a6308fbe03980p-4, 0x1.21a79b4fa8995p-4, -0x1.ef17870cbedd2p-4, -0x1.04fb80b33233ap-5, + -0x1.c124a0c635391p-5, -0x1.cc1f0be09458dp-4, 0x1.9372a7493d1cbp-5, -0x1.d696180df6c1ep-4, + 0x1.e817b7ef3c303p-4, -0x1.35410e16e9929p-5, 0x1.b3e4d5009b1a4p-4, 0x1.0c9704af25147p-4, + 0x1.455771625c66cp-6, 0x1.f97f93beb0325p-4, -0x1.49a44b00fae50p-4, 0x1.87c4000dacaedp-4, + -0x1.fff6232569c42p-4, 0x1.921d8ec0baae4p-10, -0x1.532828e8ad619p-4, -0x1.7f8ecf3f26675p-4, + 0x1.139f0b2e89682p-6, -0x1.fb579725866c4p-4, 0x1.ad2bca91c1854p-4, -0x1.1734d48dcdf4ep-4, + 0x1.ebbd8c6ad5141p-4, 0x1.1d343fd7b4aa4p-5, 0x1.aa6c819c507e9p-5, 0x1.d17e76f831197p-4, + -0x1.2b83fa627b644p-4, 0x1.dd26e5a173651p-6, 0x1.06b8a03ad386ap-8, 0x1.b6bf1a3b599bap-4, + -0x1.2e95aae5630cfp-4, 0x1.bf7ba2ff29a37p-4, -0x1.d52f6cac5b46cp-4, -0x1.aa0171799953bp-6, + -0x1.41456cf072aebp-4, -0x1.04a0ba9135390p-4, 0x1.d97971827d596p-10, -0x1.253fb136858d3p-4, + 0x1.026b86b6e650ep-5, -0x1.a2b2490a0546ep-4, -0x1.6581399d280e9p-3, 0x1.da1e2978a76b8p-7, + -0x1.5b709c6720e72p-5, -0x1.21f254a071a34p-6, 0x1.4710dd83fcbb4p-7, -0x1.3e8749f106034p-3, + -0x1.065be458b63eep-4, 0x1.37ce119f895b4p-6, 0x1.eadfed15f4971p-4, 0x1.30a19dc9e9b8ap-6, + 0x1.c701047096fa7p-7, 0x1.01e6c7270df83p-2, 0x1.b3199894797f8p-5, 0x1.83ac1ab8e1034p-3, + -0x1.74e763eb93529p-3, -0x1.7875234135263p-6, 0x1.14bcaf9e8a78fp-4, 0x1.dc5865fd96f34p-9, + 0x1.940f22f2c3732p-7, 0x1.056205693932bp-5, 0x1.c34a14230b1c9p-4, 0x1.281bd0b4c8538p-6, + -0x1.489a1abf7c968p-3, 0x1.2d5ec780d4137p-8, -0x1.c240e1d0e43f5p-7, 0x1.5d8b51069ab89p-4, + -0x1.0e12eb00b8bd3p-6, -0x1.011d2f23c5545p-8, 0x1.70014e15ab3d5p-10, -0x1.f67b8c739a033p-6, + -0x1.087cfbb550b4dp-3, 0x1.6ce0c5d4e4a41p-5, -0x1.20c4ffa9c9d16p-7, 0x1.94c94ed4acae9p-4, + -0x1.8badaf40b6ab1p-4, 0x1.7cfc1b75eba91p-4, -0x1.1cf97692cfd65p-4, -0x1.4a0b1f1cee839p-7, + 0x1.438d02742649dp-5, -0x1.ac0fa5f0e86dfp-8, 0x1.b3e600ccffe0ep-7, 0x1.6f25f3ebe57a4p-3, + 0x1.be4d8b9bacaf2p-4, -0x1.895cab9b9988ep-6, 0x1.aec3bb3352aa3p-3, -0x1.0a90c6d7007dfp-8, + -0x1.8c52737303db9p-4, 0x1.28fcdce866c25p-4, -0x1.1800c34f3ab71p-5, -0x1.48f44f6017c2dp-5, + 0x1.48f44f6017c2dp-5, 0x1.1800c34f3ab71p-5, -0x1.28fcdce866c25p-4, 0x1.8c52737303db9p-4, + 0x1.0a90c6d7007dfp-8, -0x1.aec3bb3352aa3p-3, 0x1.895cab9b9988ep-6, -0x1.be4d8b9bacaf2p-4, + -0x1.6f25f3ebe57a4p-3, -0x1.b3e600ccffe0ep-7, 0x1.ac0fa5f0e86dfp-8, -0x1.438d02742649dp-5, + 0x1.4a0b1f1cee839p-7, 0x1.1cf97692cfd65p-4, -0x1.7cfc1b75eba91p-4, 0x1.8badaf40b6ab1p-4, + -0x1.94c94ed4acae9p-4, 0x1.20c4ffa9c9d16p-7, -0x1.6ce0c5d4e4a41p-5, 0x1.087cfbb550b4dp-3, + 0x1.f67b8c739a033p-6, -0x1.70014e15ab3d5p-10, 0x1.011d2f23c5545p-8, 0x1.0e12eb00b8bd3p-6, + -0x1.5d8b51069ab89p-4, 0x1.c240e1d0e43f5p-7, -0x1.2d5ec780d4137p-8, 0x1.489a1abf7c968p-3, + -0x1.281bd0b4c8538p-6, -0x1.c34a14230b1c9p-4, -0x1.056205693932bp-5, -0x1.940f22f2c3732p-7, + -0x1.dc5865fd96f34p-9, -0x1.14bcaf9e8a78fp-4, 0x1.7875234135263p-6, 0x1.74e763eb93529p-3, + -0x1.83ac1ab8e1034p-3, -0x1.b3199894797f8p-5, -0x1.01e6c7270df83p-2, -0x1.c701047096fa7p-7, + -0x1.30a19dc9e9b8ap-6, -0x1.eadfed15f4971p-4, -0x1.37ce119f895b4p-6, 0x1.065be458b63eep-4, + 0x1.3e8749f106034p-3, -0x1.4710dd83fcbb4p-7, 0x1.21f254a071a34p-6, 0x1.5b709c6720e72p-5, + -0x1.da1e2978a76b8p-7, 0x1.6581399d280e9p-3, 0x1.a2b2490a0546ep-4, -0x1.026b86b6e650ep-5, + 0x1.253fb136858d3p-4, -0x1.d97971827d596p-10, 0x1.04a0ba9135390p-4, 0x1.41456cf072aebp-4, + 0x1.aa0171799953bp-6, 0x1.d52f6cac5b46cp-4, -0x1.bf7ba2ff29a3dp-4, 0x1.2e95aae5630c5p-4, + -0x1.b6bf1a3b599bbp-4, -0x1.06b8a03ad38b1p-8, -0x1.dd26e7889eefdp-6, 0x1.2b83fa4d86f49p-4, + 0x1.76c95b4ab33e3p-4, -0x1.b1dd0c3cae755p-4, 0x1.936d514c2871bp-3, -0x1.3e13b5a314cfcp-4, + -0x1.e7377d24f2e42p-7, 0x1.eef5d002ab2f8p-5, 0x1.68a8e54eac679p-4, -0x1.a08940bd8988fp-5, + -0x1.dcfb3d776aab8p-5, 0x1.58b778df5f0e6p-5, -0x1.892631de1f314p-4, 0x1.ec01911688603p-6, + 0x1.12d96d8baa0ccp-5, -0x1.0f2645ad378f8p-4, 0x1.e1dc9bbe65c97p-7, 0x1.90d623b76e069p-3, + 0x1.3b678f81ac68dp-5, 0x1.370148e765959p-9, -0x1.81a659bc6009dp-12, 0x1.68606fb83a03ap-7, + -0x1.ee7e50c9850edp-6, -0x1.8e2f30b4a865bp-3, -0x1.ab9130c9fa231p-6, -0x1.bbe34164a9d19p-4, + 0x1.b440cbfc9784cp-5, 0x1.0cc84aaae1082p-7, -0x1.e56963cc9ba52p-10, 0x1.efa9fa7379910p-5, + 0x1.2ce62cc840a8bp-6, -0x1.6567bc0c73f40p-3, 0x1.89af3844ae9f6p-3, -0x1.29f5e1313eb13p-3, + 0x1.e48a22799de46p-5, -0x1.a79a8917f66c1p-6, -0x1.6e2d8f1bb4767p-6, 0x1.7e87c357b8697p-4, + 0x1.f8224370c2a65p-5, 0x1.d09051045e00dp-6, -0x1.961cb15a7f4c0p-4, 0x1.9ace185be614ap-7, + -0x1.f0d982724c04ep-3, 0x1.dd9d0f5275619p-6, -0x1.f70506f01e5f5p-5, -0x1.1b0ded59fd411p-5, + -0x1.39d08aab2ff48p-4, 0x1.72b3b30fb402fp-5, 0x1.8294f320b3e84p-3, -0x1.e9bc17df38c39p-6, + -0x1.7e22437a13b29p-4, -0x1.8fd7b3e8f226dp-4, 0x1.1eb4b92cd0910p-5, -0x1.160b0b42ba4aap-3, + -0x1.8beae81d155d2p-4, 0x1.a7d45c231dbacp-5, -0x1.0f9e7a43c599ep-6, -0x1.7bfa60698f04fp-6, + 0x1.9d2ab64dd220cp-6, -0x1.8ad74a2df290dp-5, -0x1.85485e6ee408fp-5, 0x1.075cdd1122775p-3, + -0x1.9b6ae8310898ep-5, 0x1.0c608b8c184cbp-5, 0x1.92473607dda99p-6, 0x1.22c61759c4d1ap-7, + -0x1.22c61759c4d1ap-7, -0x1.92473607dda99p-6, -0x1.0c608b8c184cbp-5, 0x1.9b6ae8310898ep-5, + -0x1.075cdd1122775p-3, 0x1.85485e6ee408fp-5, 0x1.8ad74a2df290dp-5, -0x1.9d2ab64dd220cp-6, + 0x1.7bfa60698f04fp-6, 0x1.0f9e7a43c599ep-6, -0x1.a7d45c231dbacp-5, 0x1.8beae81d155d2p-4, + 0x1.160b0b42ba4aap-3, -0x1.1eb4b92cd0910p-5, 0x1.8fd7b3e8f226dp-4, 0x1.7e22437a13b29p-4, + 0x1.e9bc17df38c39p-6, -0x1.8294f320b3e84p-3, -0x1.72b3b30fb402fp-5, 0x1.39d08aab2ff48p-4, + 0x1.1b0ded59fd411p-5, 0x1.f70506f01e5f5p-5, -0x1.dd9d0f5275619p-6, 0x1.f0d982724c04ep-3, + -0x1.9ace185be614ap-7, 0x1.961cb15a7f4c0p-4, -0x1.d09051045e00dp-6, -0x1.f8224370c2a65p-5, + -0x1.7e87c357b8697p-4, 0x1.6e2d8f1bb4767p-6, 0x1.a79a8917f66c1p-6, -0x1.e48a22799de46p-5, + 0x1.29f5e1313eb13p-3, -0x1.89af3844ae9f6p-3, 0x1.6567bc0c73f40p-3, -0x1.2ce62cc840a8bp-6, + -0x1.efa9fa7379910p-5, 0x1.e56963cc9ba52p-10, -0x1.0cc84aaae1082p-7, -0x1.b440cbfc9784cp-5, + 0x1.bbe34164a9d19p-4, 0x1.ab9130c9fa231p-6, 0x1.8e2f30b4a865bp-3, 0x1.ee7e50c9850edp-6, + -0x1.68606fb83a03ap-7, 0x1.81a659bc6009dp-12, -0x1.370148e765959p-9, -0x1.3b678f81ac68dp-5, + -0x1.90d623b76e069p-3, -0x1.e1dc9bbe65c97p-7, 0x1.0f2645ad378f8p-4, -0x1.12d96d8baa0ccp-5, + -0x1.ec01911688603p-6, 0x1.892631de1f314p-4, -0x1.58b778df5f0e6p-5, 0x1.dcfb3d776aab8p-5, + 0x1.a08940bd8988fp-5, -0x1.68a8e54eac67ap-4, -0x1.eef5d002ab2f5p-5, 0x1.e7377d24f2e0fp-7, + 0x1.3e13b5a314cfcp-4, -0x1.936d514c2871dp-3, 0x1.b1dd0c5adfccdp-4, -0x1.76c95e09b73e0p-4, + 0x1.9372a6ac580c2p-5, -0x1.d69617a77d586p-4, -0x1.dfeae3227fe85p-4, 0x1.64c7ddce0299bp-5, + 0x1.cc1f0d2e39301p-4, 0x1.c1249ec40cc20p-5, -0x1.35410c262b39ap-5, -0x1.e817bc9045b20p-4, + -0x1.edc193c2d0bc7p-5, 0x1.c08c3f0e54012p-4, 0x1.ef178ccd98e2fp-4, -0x1.04fb8430ce531p-5, + -0x1.b3e4d5a1bfd4fp-4, -0x1.0c9706579c228p-4, 0x1.a829fdff8a81cp-6, 0x1.f4e604e8def4bp-4, + 0x1.21a798b18ddd5p-4, -0x1.a63095254010dp-4, -0x1.f97f8f7277f89p-4, 0x1.455773f0ff95fp-6, + 0x1.9777eeeb70ad9p-4, 0x1.36058ccce7db6p-4, -0x1.c3785966bd589p-7, -0x1.fce15f4187911p-4, + -0x1.49a44b3ce0b67p-4, 0x1.87c3feda6598ep-4, 0x1.ff0951e01cd46p-4, -0x1.f656e295e6fc4p-8, + -0x1.771e77bc9768bp-4, -0x1.5c77bd2d0e618p-4, 0x1.921d4801e4bb9p-10, 0x1.fff620d61382bp-4, + 0x1.6e74463869f70p-4, -0x1.659194607a51ap-4, -0x1.ffa7305d14554p-4, -0x1.2d866dd6c0d8ep-8, + 0x1.532828e1057fap-4, 0x1.7f8eccfc0a078p-4, 0x1.5f6d074e4844ep-7, -0x1.fe1cb1ed21104p-4, + -0x1.8fbcc794b8917p-4, 0x1.3fed9656aab69p-4, 0x1.fb5797d90ef3bp-4, 0x1.139f0bd8028cfp-6, + -0x1.2bedb2048cea6p-4, -0x1.9ef4406afcbf4p-4, -0x1.76dda3b072523p-6, 0x1.f75997d71f2e9p-4, + 0x1.ad2bc77e49bd9p-4, -0x1.1734d7facf0f2p-4, -0x1.f2252d6edd522p-4, -0x1.d934fa8220811p-6, + 0x1.01cfc9b2edde7p-4, 0x1.ba5aa8ba8c722p-4, 0x1.1d34435193692p-5, -0x1.ebbd8b296d07bp-4, + -0x1.c678b325531b9p-4, 0x1.d79774bfa1016p-5, 0x1.e426a46cfaa46p-4, 0x1.4d1e20c9d62b2p-5, + -0x1.aa6c87a553a26p-5, -0x1.d17e790bcbbbdp-4, -0x1.7c3a96a946d18p-5, 0x1.db65261d8ec2fp-4, + 0x1.db65261d8ec2fp-4, -0x1.7c3a96a946d18p-5, -0x1.d17e790bcbbbdp-4, -0x1.aa6c87a553a26p-5, + 0x1.4d1e20c9d62b2p-5, 0x1.e426a46cfaa46p-4, 0x1.d79774bfa1016p-5, -0x1.c678b325531b9p-4, + -0x1.ebbd8b296d07bp-4, 0x1.1d34435193692p-5, 0x1.ba5aa8ba8c722p-4, 0x1.01cfc9b2edde7p-4, + -0x1.d934fa8220811p-6, -0x1.f2252d6edd522p-4, -0x1.1734d7facf0f2p-4, 0x1.ad2bc77e49bd9p-4, + 0x1.f75997d71f2e9p-4, -0x1.76dda3b072523p-6, -0x1.9ef4406afcbf4p-4, -0x1.2bedb2048cea6p-4, + 0x1.139f0bd8028cfp-6, 0x1.fb5797d90ef3bp-4, 0x1.3fed9656aab69p-4, -0x1.8fbcc794b8917p-4, + -0x1.fe1cb1ed21104p-4, 0x1.5f6d074e4844ep-7, 0x1.7f8eccfc0a078p-4, 0x1.532828e1057fap-4, + -0x1.2d866dd6c0d8ep-8, -0x1.ffa7305d14554p-4, -0x1.659194607a51ap-4, 0x1.6e74463869f70p-4, + 0x1.fff620d61382bp-4, 0x1.921d4801e4bb9p-10, -0x1.5c77bd2d0e618p-4, -0x1.771e77bc9768bp-4, + -0x1.f656e295e6fc4p-8, 0x1.ff0951e01cd46p-4, 0x1.87c3feda6598ep-4, -0x1.49a44b3ce0b67p-4, + -0x1.fce15f4187911p-4, -0x1.c3785966bd589p-7, 0x1.36058ccce7db6p-4, 0x1.9777eeeb70ad9p-4, + 0x1.455773f0ff95fp-6, -0x1.f97f8f7277f89p-4, -0x1.a63095254010dp-4, 0x1.21a798b18ddd5p-4, + 0x1.f4e604e8def4bp-4, 0x1.a829fdff8a81cp-6, -0x1.0c9706579c228p-4, -0x1.b3e4d5a1bfd4fp-4, + -0x1.04fb8430ce531p-5, 0x1.ef178ccd98e2fp-4, 0x1.c08c3f0e54012p-4, -0x1.edc193c2d0bc7p-5, + -0x1.e817bc9045b20p-4, -0x1.35410c262b39ap-5, 0x1.c1249ec40cc20p-5, 0x1.cc1f0d2e39301p-4, + 0x1.64c7ddce0299bp-5, -0x1.dfeae3227fe85p-4, -0x1.d69617a77d586p-4, 0x1.9372a6ac58097p-5, + -0x1.d69616fd527fcp-4, -0x1.9372a6fca6903p-5, -0x1.64c7dede42effp-5, -0x1.dfeae46565d3fp-4, + 0x1.c1249dbf23a63p-5, -0x1.cc1f0b0f18353p-4, 0x1.e817bc94d8013p-4, -0x1.35410c7a46554p-5, + 0x1.c08c3f9e9ccbbp-4, 0x1.edc1946aea530p-5, 0x1.04fb852e35562p-5, 0x1.ef178b719d4aep-4, + -0x1.0c970614eaa82p-4, 0x1.b3e4d5f25d566p-4, -0x1.f4e603882383ap-4, 0x1.a829fe926086dp-6, + -0x1.a63094567b03dp-4, -0x1.21a797dda126fp-4, -0x1.455775bd564c5p-6, -0x1.f97f90cee95c3p-4, + 0x1.36058bdbeae23p-4, -0x1.9777f067cac6bp-4, 0x1.fce15e9d88c0ap-4, -0x1.c3785a3c88c27p-7, + 0x1.87c3ff99142b5p-4, 0x1.49a44aa9c91b7p-4, 0x1.f656e48b1430fp-8, 0x1.ff0951a15678dp-4, + -0x1.5c77bbccc29b1p-4, 0x1.771e780131584p-4, -0x1.fff62024de6e0p-4, 0x1.921d515708128p-10, + -0x1.659194a297580p-4, -0x1.6e7446aef05eep-4, 0x1.2d866bbbc9439p-8, -0x1.ffa731a6ca6fap-4, + 0x1.7f8ecccdc8115p-4, -0x1.532827ea15b48p-4, 0x1.fe1cb278a3df7p-4, 0x1.5f6d059c5aef5p-7, + 0x1.3fed958e8e54bp-4, 0x1.8fbcc7d5a03e9p-4, -0x1.139f0ba54cd7ep-6, 0x1.fb57980e53cc2p-4, + -0x1.9ef43fe854a49p-4, 0x1.2bedb161a56c1p-4, -0x1.f75998da411fbp-4, -0x1.76dda22724fd4p-6, + -0x1.1734d8a40c178p-4, -0x1.ad2bc895e5b91p-4, 0x1.d934f9d307a52p-6, -0x1.f2252f0ab90b5p-4, + 0x1.ba5aa78213b73p-4, -0x1.01cfc95a9938cp-4, 0x1.ebbd8cc7e2866p-4, 0x1.1d34440182823p-5, + 0x1.d79776dd406f2p-5, 0x1.c678b2989c603p-4, -0x1.4d1e2161a7884p-5, 0x1.e426a5010c0c4p-4, + -0x1.d17e7795e003ap-4, 0x1.aa6c87426eb9ap-5, -0x1.db65262b7625fp-4, -0x1.7c3a970607c78p-5, + -0x1.7c3a970607c78p-5, -0x1.db65262b7625fp-4, 0x1.aa6c87426eb9ap-5, -0x1.d17e7795e003ap-4, + 0x1.e426a5010c0c4p-4, -0x1.4d1e2161a7884p-5, 0x1.c678b2989c603p-4, 0x1.d79776dd406f2p-5, + 0x1.1d34440182823p-5, 0x1.ebbd8cc7e2866p-4, -0x1.01cfc95a9938cp-4, 0x1.ba5aa78213b73p-4, + -0x1.f2252f0ab90b5p-4, 0x1.d934f9d307a52p-6, -0x1.ad2bc895e5b91p-4, -0x1.1734d8a40c178p-4, + -0x1.76dda22724fd4p-6, -0x1.f75998da411fbp-4, 0x1.2bedb161a56c1p-4, -0x1.9ef43fe854a49p-4, + 0x1.fb57980e53cc2p-4, -0x1.139f0ba54cd7ep-6, 0x1.8fbcc7d5a03e9p-4, 0x1.3fed958e8e54bp-4, + 0x1.5f6d059c5aef5p-7, 0x1.fe1cb278a3df7p-4, -0x1.532827ea15b48p-4, 0x1.7f8ecccdc8115p-4, + -0x1.ffa731a6ca6fap-4, 0x1.2d866bbbc9439p-8, -0x1.6e7446aef05eep-4, -0x1.659194a297580p-4, + 0x1.921d515708128p-10, -0x1.fff62024de6e0p-4, 0x1.771e780131584p-4, -0x1.5c77bbccc29b1p-4, + 0x1.ff0951a15678dp-4, 0x1.f656e48b1430fp-8, 0x1.49a44aa9c91b7p-4, 0x1.87c3ff99142b5p-4, + -0x1.c3785a3c88c27p-7, 0x1.fce15e9d88c0ap-4, -0x1.9777f067cac6bp-4, 0x1.36058bdbeae23p-4, + -0x1.f97f90cee95c3p-4, -0x1.455775bd564c5p-6, -0x1.21a797dda126fp-4, -0x1.a63094567b03dp-4, + 0x1.a829fe926086dp-6, -0x1.f4e603882383ap-4, 0x1.b3e4d5f25d566p-4, -0x1.0c970614eaa82p-4, + 0x1.ef178b719d4aep-4, 0x1.04fb852e35562p-5, 0x1.edc1946aea530p-5, 0x1.c08c3f9e9ccbbp-4, + -0x1.35410c7a46554p-5, 0x1.e817bc94d8013p-4, -0x1.cc1f0b0f18353p-4, 0x1.c1249dbf23a63p-5, + -0x1.dfeae46565d3fp-4, -0x1.64c7dede42effp-5, -0x1.9372a6fca68d0p-5, -0x1.d69616fd527f6p-4, + 0x1.c12c39e785920p-3, -0x1.22ecb21606b35p-5, -0x1.1536a326ea03cp-4, -0x1.729ba99411349p-7, + 0x1.8a3d1c6e1dd08p-7, -0x1.76cc476bfca3dp-6, 0x1.fab9dec802558p-4, 0x1.24b202b58967dp-5, + 0x1.74fba553a0f77p-4, 0x1.08c364ef380f2p-7, 0x1.ba9c568554f54p-7, -0x1.15627c2997678p-6, + 0x1.75f20919642fcp-4, 0x1.f71ce185d2a14p-4, -0x1.8936fe0f6b1aep-6, -0x1.4d7ea412bfbcap-6, + -0x1.4a75364c1f8ebp-6, 0x1.bac800b875af4p-5, -0x1.2078c70493226p-5, 0x1.104472abbe7b4p-4, + 0x1.983cc2bb4d874p-7, -0x1.c18e5a37c0918p-5, 0x1.6d3b3c41ff8b8p-5, 0x1.d1c0fe9b2e8c8p-9, + -0x1.2187aa0f7fd1bp-6, 0x1.1f2e58d72d77dp-4, 0x1.d5f8091c218ebp-7, -0x1.9b46246b259e9p-6, + 0x1.a090000aa60fap-4, 0x1.1606022d57e12p-3, 0x1.12672871ee8a3p-3, 0x1.b2f109b194962p-8, + -0x1.ae2e4b2a98a66p-5, -0x1.a7465b7390087p-6, -0x1.08b4aeb6793c9p-9, -0x1.13f503a9b48c0p-3, + 0x1.7676dcbe9f5bdp-3, -0x1.9f008ec7f809ap-5, -0x1.34490b203de7ap-3, -0x1.7d661d70b1065p-6, + -0x1.918ee21edf810p-7, 0x1.dc33b48b6252fp-9, -0x1.9c373b2eaa3b5p-9, -0x1.434bfee799bbep-4, + 0x1.a007d450e4bcbp-3, -0x1.99e3a54c45599p-4, -0x1.fa8290d92e873p-4, 0x1.b2ddd2ebad8a9p-8, + -0x1.be4cdb7e0c40cp-5, 0x1.000804e41697bp-3, -0x1.12bc5d1944dd3p-4, -0x1.399f8412cfb31p-4, + -0x1.737deee8e345ap-4, 0x1.2ca1927792efdp-3, 0x1.64c1e40dbf15bp-3, 0x1.42125f3fa235bp-5, + 0x1.b839f0a5d5189p-5, 0x1.6f0ea7bae8a87p-3, 0x1.0afffc572dffap-11, -0x1.8c15483c89635p-5, + -0x1.d91b4458a5b90p-8, -0x1.8d022789098cep-4, 0x1.86793b85c200fp-3, 0x1.e6491739fcfbep-6, + 0x1.e6491739fcfbep-6, 0x1.86793b85c200fp-3, -0x1.8d022789098cep-4, -0x1.d91b4458a5b90p-8, + -0x1.8c15483c89635p-5, 0x1.0afffc572dffap-11, 0x1.6f0ea7bae8a87p-3, 0x1.b839f0a5d5189p-5, + 0x1.42125f3fa235bp-5, 0x1.64c1e40dbf15bp-3, 0x1.2ca1927792efdp-3, -0x1.737deee8e345ap-4, + -0x1.399f8412cfb31p-4, -0x1.12bc5d1944dd3p-4, 0x1.000804e41697bp-3, -0x1.be4cdb7e0c40cp-5, + 0x1.b2ddd2ebad8a9p-8, -0x1.fa8290d92e873p-4, -0x1.99e3a54c45599p-4, 0x1.a007d450e4bcbp-3, + -0x1.434bfee799bbep-4, -0x1.9c373b2eaa3b5p-9, 0x1.dc33b48b6252fp-9, -0x1.918ee21edf810p-7, + -0x1.7d661d70b1065p-6, -0x1.34490b203de7ap-3, -0x1.9f008ec7f809ap-5, 0x1.7676dcbe9f5bdp-3, + -0x1.13f503a9b48c0p-3, -0x1.08b4aeb6793c9p-9, -0x1.a7465b7390087p-6, -0x1.ae2e4b2a98a66p-5, + 0x1.b2f109b194962p-8, 0x1.12672871ee8a3p-3, 0x1.1606022d57e12p-3, 0x1.a090000aa60fap-4, + -0x1.9b46246b259e9p-6, 0x1.d5f8091c218ebp-7, 0x1.1f2e58d72d77dp-4, -0x1.2187aa0f7fd1bp-6, + 0x1.d1c0fe9b2e8c8p-9, 0x1.6d3b3c41ff8b8p-5, -0x1.c18e5a37c0918p-5, 0x1.983cc2bb4d874p-7, + 0x1.104472abbe7b4p-4, -0x1.2078c70493226p-5, 0x1.bac800b875af4p-5, -0x1.4a75364c1f8ebp-6, + -0x1.4d7ea412bfbcap-6, -0x1.8936fe0f6b1aep-6, 0x1.f71ce185d2a14p-4, 0x1.75f20919642fcp-4, + -0x1.15627c2997678p-6, 0x1.ba9c568554f54p-7, 0x1.08c364ef380f2p-7, 0x1.74fba553a0f77p-4, + 0x1.24b202b58967dp-5, 0x1.fab9dec802558p-4, -0x1.76cc476bfca28p-6, 0x1.8a3d1c6e1dcf6p-7, + -0x1.729ba99411397p-7, -0x1.1536a326ea03ep-4, -0x1.22ecaf0e30e02p-5, 0x1.c12c3a074a585p-3, + -0x1.c4dba2807f273p-6, -0x1.62dc8045be645p-10, 0x1.188db8c25ebafp-2, -0x1.fb087ccc2bf39p-5, + 0x1.af9081388cc7cp-3, 0x1.df63d9130438ep-5, 0x1.8f05fdd439edcp-6, -0x1.02400f65eba7fp-4, + 0x1.afc4bf8f17bcdp-4, -0x1.77d56564e7a5bp-6, 0x1.2cef2a0e5c2f1p-7, 0x1.45a4a0e5de538p-4, + -0x1.01e65829e2f0ap-4, 0x1.f70d93499b060p-5, -0x1.3352ec00e2969p-4, 0x1.04f9b93204a5ap-5, + 0x1.d5114e073598ep-5, -0x1.d0fe4390a4d21p-5, -0x1.210abc4dddb44p-6, -0x1.95b7f43297a8bp-5, + -0x1.a5c729647cadfp-3, 0x1.d46cda7ccfbf2p-5, 0x1.5d6ddb6373d90p-5, -0x1.ba44b90404787p-3, + -0x1.ca39fb1a3ac0cp-5, -0x1.ced9c1e7bc150p-3, 0x1.99ba06e93634ap-5, 0x1.a8c0043b140e6p-6, + 0x1.abfa31683d8d0p-4, -0x1.dde0dae67a345p-4, -0x1.04c84741808fdp-5, 0x1.73a8842b97efdp-4, + -0x1.6d8002202c08ap-7, 0x1.448a4714cd640p-6, -0x1.dd8dfc2d4e58dp-4, -0x1.26279b74047f1p-5, + 0x1.35250579f1b0ap-3, 0x1.b8030d6602fa1p-5, 0x1.6f454b04a2066p-6, -0x1.2f458f768bae1p-6, + 0x1.36a9b205a88a6p-3, -0x1.20c999ae019bcp-6, 0x1.0632e3147d094p-7, 0x1.51792a45f20f1p-5, + 0x1.2364bf5dbd32dp-4, 0x1.d066b5d014138p-4, -0x1.056166a4b4185p-6, -0x1.58a25aa322d3ap-8, + -0x1.3e85eaf824315p-7, -0x1.a34cbf861e6b3p-8, -0x1.e9db3386c485fp-7, 0x1.952b52d954498p-5, + -0x1.c752ca4224dd0p-6, 0x1.3e5a2d8d65292p-3, -0x1.0f6498f174b5cp-5, 0x1.b0720bcda97a4p-5, + 0x1.30a4a4a5b11d9p-5, -0x1.72717ac50243cp-4, -0x1.0e41ade13d5e5p-5, -0x1.7b6f607032c3bp-4, + -0x1.d25e023ac3a4cp-6, -0x1.c93f68dc94fabp-10, 0x1.ca72d9001e7c1p-5, -0x1.fcabc5c5aa978p-6, + -0x1.fcabc5c5aa978p-6, 0x1.ca72d9001e7c1p-5, -0x1.c93f68dc94fabp-10, -0x1.d25e023ac3a4cp-6, + -0x1.7b6f607032c3bp-4, -0x1.0e41ade13d5e5p-5, -0x1.72717ac50243cp-4, 0x1.30a4a4a5b11d9p-5, + 0x1.b0720bcda97a4p-5, -0x1.0f6498f174b5cp-5, 0x1.3e5a2d8d65292p-3, -0x1.c752ca4224dd0p-6, + 0x1.952b52d954498p-5, -0x1.e9db3386c485fp-7, -0x1.a34cbf861e6b3p-8, -0x1.3e85eaf824315p-7, + -0x1.58a25aa322d3ap-8, -0x1.056166a4b4185p-6, 0x1.d066b5d014138p-4, 0x1.2364bf5dbd32dp-4, + 0x1.51792a45f20f1p-5, 0x1.0632e3147d094p-7, -0x1.20c999ae019bcp-6, 0x1.36a9b205a88a6p-3, + -0x1.2f458f768bae1p-6, 0x1.6f454b04a2066p-6, 0x1.b8030d6602fa1p-5, 0x1.35250579f1b0ap-3, + -0x1.26279b74047f1p-5, -0x1.dd8dfc2d4e58dp-4, 0x1.448a4714cd640p-6, -0x1.6d8002202c08ap-7, + 0x1.73a8842b97efdp-4, -0x1.04c84741808fdp-5, -0x1.dde0dae67a345p-4, 0x1.abfa31683d8d0p-4, + 0x1.a8c0043b140e6p-6, 0x1.99ba06e93634ap-5, -0x1.ced9c1e7bc150p-3, -0x1.ca39fb1a3ac0cp-5, + -0x1.ba44b90404787p-3, 0x1.5d6ddb6373d90p-5, 0x1.d46cda7ccfbf2p-5, -0x1.a5c729647cadfp-3, + -0x1.95b7f43297a8bp-5, -0x1.210abc4dddb44p-6, -0x1.d0fe4390a4d21p-5, 0x1.d5114e073598ep-5, + 0x1.04f9b93204a5ap-5, -0x1.3352ec00e2969p-4, 0x1.f70d93499b060p-5, -0x1.01e65829e2f0ap-4, + 0x1.45a4a0e5de538p-4, 0x1.2cef2a0e5c2f1p-7, -0x1.77d56564e7a5bp-6, 0x1.afc4bf8f17bcdp-4, + -0x1.02400f65eba7fp-4, 0x1.8f05fdd439edep-6, 0x1.df63d9130438ep-5, 0x1.af9081388cc7cp-3, + -0x1.fb087ccc2bf3dp-5, 0x1.188db8c25ebb0p-2, -0x1.62dc72e2fbb6cp-10, -0x1.c4dba08fe77e8p-6, + 0x1.7c3a93b93b3e2p-5, -0x1.db65266c2e5e0p-4, -0x1.d17e75192dbbep-4, 0x1.aa6c832d91689p-5, + 0x1.e426a2d22b7b8p-4, 0x1.4d1e25bd8fd7ep-5, -0x1.d797739bc0f45p-5, -0x1.c678b3b748ad8p-4, + -0x1.1d3444894fb07p-5, 0x1.ebbd8c8d38358p-4, 0x1.ba5aa6d29868dp-4, -0x1.01cfc84fb994dp-4, + -0x1.f2252f6791ff0p-4, -0x1.d934fdc9ec58fp-6, 0x1.1734d66ffd7a3p-4, 0x1.ad2bc8d9394c2p-4, + 0x1.76dd9d0447ee7p-6, -0x1.f7599bc79b5a8p-4, -0x1.9ef43dcf2f24ap-4, 0x1.2bedb2458444bp-4, + 0x1.fb5797f45d4e8p-4, 0x1.139f0eca7eabbp-6, -0x1.3fed94d6d1147p-4, -0x1.8fbccbe051edcp-4, + -0x1.5f6cffafadda2p-7, 0x1.fe1caec9c195fp-4, 0x1.7f8eccbbbeb06p-4, -0x1.53282830a4e66p-4, + -0x1.ffa72fbaf068bp-4, -0x1.2d86504cbf96cp-8, 0x1.65919276251d4p-4, 0x1.6e74439d092c3p-4, + -0x1.921cc3a01ef59p-10, -0x1.fff6229ea5d25p-4, -0x1.5c77bd4b65bd0p-4, 0x1.771e73787247dp-4, + 0x1.ff095644e0912p-4, -0x1.f656e0b87867ap-8, -0x1.87c400eaed0ffp-4, -0x1.49a448f13e46ap-4, + 0x1.c378622e7eeabp-7, 0x1.fce1609666adfp-4, 0x1.36058a52a4807p-4, -0x1.9777ede261dcep-4, + -0x1.f97f92460a8bep-4, 0x1.455768cf00db5p-6, 0x1.a6308f99fc4e1p-4, 0x1.21a79b24ba970p-4, + -0x1.a82a051ea5a8bp-6, -0x1.f4e6058680c50p-4, -0x1.0c9704fed4b5ep-4, 0x1.b3e4d3a907dcap-4, + 0x1.ef178cd882b68p-4, -0x1.04fb822bbab92p-5, -0x1.c08c4289b669ap-4, -0x1.edc193b3a3dcbp-5, + 0x1.35410d458b191p-5, 0x1.e817ba7d39170p-4, 0x1.c1249beffc590p-5, -0x1.cc1f0e40925c1p-4, + -0x1.dfeae7a718c70p-4, 0x1.64c7dc924af4ap-5, 0x1.d69619b7ec942p-4, 0x1.9372a6185234fp-5, + -0x1.9372a6185234fp-5, -0x1.d69619b7ec942p-4, -0x1.64c7dc924af4ap-5, 0x1.dfeae7a718c70p-4, + 0x1.cc1f0e40925c1p-4, -0x1.c1249beffc590p-5, -0x1.e817ba7d39170p-4, -0x1.35410d458b191p-5, + 0x1.edc193b3a3dcbp-5, 0x1.c08c4289b669ap-4, 0x1.04fb822bbab92p-5, -0x1.ef178cd882b68p-4, + -0x1.b3e4d3a907dcap-4, 0x1.0c9704fed4b5ep-4, 0x1.f4e6058680c50p-4, 0x1.a82a051ea5a8bp-6, + -0x1.21a79b24ba970p-4, -0x1.a6308f99fc4e1p-4, -0x1.455768cf00db5p-6, 0x1.f97f92460a8bep-4, + 0x1.9777ede261dcep-4, -0x1.36058a52a4807p-4, -0x1.fce1609666adfp-4, -0x1.c378622e7eeabp-7, + 0x1.49a448f13e46ap-4, 0x1.87c400eaed0ffp-4, 0x1.f656e0b87867ap-8, -0x1.ff095644e0912p-4, + -0x1.771e73787247dp-4, 0x1.5c77bd4b65bd0p-4, 0x1.fff6229ea5d25p-4, 0x1.921cc3a01ef59p-10, + -0x1.6e74439d092c3p-4, -0x1.65919276251d4p-4, 0x1.2d86504cbf96cp-8, 0x1.ffa72fbaf068bp-4, + 0x1.53282830a4e66p-4, -0x1.7f8eccbbbeb06p-4, -0x1.fe1caec9c195fp-4, 0x1.5f6cffafadda2p-7, + 0x1.8fbccbe051edcp-4, 0x1.3fed94d6d1147p-4, -0x1.139f0eca7eabbp-6, -0x1.fb5797f45d4e8p-4, + -0x1.2bedb2458444bp-4, 0x1.9ef43dcf2f24ap-4, 0x1.f7599bc79b5a8p-4, -0x1.76dd9d0447ee7p-6, + -0x1.ad2bc8d9394c2p-4, -0x1.1734d66ffd7a3p-4, 0x1.d934fdc9ec58fp-6, 0x1.f2252f6791ff0p-4, + 0x1.01cfc84fb994dp-4, -0x1.ba5aa6d29868dp-4, -0x1.ebbd8c8d38358p-4, 0x1.1d3444894fb07p-5, + 0x1.c678b3b748ad8p-4, 0x1.d797739bc0f45p-5, -0x1.4d1e25bd8fd7ep-5, -0x1.e426a2d22b7b8p-4, + -0x1.aa6c832d91689p-5, 0x1.d17e75192dbbep-4, 0x1.db65266c2e5dfp-4, -0x1.7c3a93b93b404p-5, + -0x1.db652726d1a80p-4, -0x1.7c3a9309e3d30p-5, -0x1.aa6c83065506fp-5, -0x1.d17e74bee65c0p-4, + 0x1.4d1e245f8b719p-5, -0x1.e426a4850d155p-4, 0x1.c678b22c81cd9p-4, -0x1.d797742ba22bap-5, + 0x1.ebbd8d3835e1ap-4, 0x1.1d3444efac4c8p-5, 0x1.01cfc81499c01p-4, 0x1.ba5aa7766cf71p-4, + -0x1.d934fe8ee6bb4p-6, 0x1.f2252f75b3423p-4, -0x1.ad2bc847988b8p-4, 0x1.1734d5dc6fb4ep-4, + -0x1.f7599b21909a5p-4, -0x1.76dd9b9386e61p-6, -0x1.2bedb2a4b4601p-4, -0x1.9ef43f3a37567p-4, + 0x1.139f0d9295ce3p-6, -0x1.fb5797f188000p-4, 0x1.8fbccbab642dcp-4, -0x1.3fed94a26c3d3p-4, + 0x1.fe1cae60e262fp-4, 0x1.5f6d00609da9dp-7, 0x1.53282848b25bep-4, 0x1.7f8ecc15feb29p-4, + -0x1.2d864fc5ada9cp-8, 0x1.ffa72d9b61262p-4, -0x1.6e7444a4a2992p-4, 0x1.6591923728721p-4, + -0x1.fff621b8c7797p-4, 0x1.921cc6805fc83p-10, -0x1.771e744d0ad3cp-4, -0x1.5c77bce1338dcp-4, + -0x1.f656e20cba8a6p-8, -0x1.ff09573b62712p-4, 0x1.49a448d9878dap-4, -0x1.87c400d1129d3p-4, + 0x1.fce161feaf39cp-4, -0x1.c37861c4f58bep-7, 0x1.9777eebaa3587p-4, 0x1.36058acf23669p-4, + 0x1.455768c0ea3b7p-6, 0x1.f97f9275d0469p-4, -0x1.21a79b66d0cf7p-4, 0x1.a63090dbbcb44p-4, + -0x1.f4e603a14368dp-4, 0x1.a82a04f1902cbp-6, -0x1.b3e4d313738efp-4, -0x1.0c9703e24bab2p-4, + -0x1.04fb828351eacp-5, -0x1.ef178db4908f3p-4, 0x1.edc191e2a7ef8p-5, -0x1.c08c4318b68e5p-4, + 0x1.e817ba2e9f579p-4, -0x1.35410d651034dp-5, 0x1.cc1f0ef202621p-4, 0x1.c1249b6b024edp-5, + 0x1.64c7dd06b4ea9p-5, 0x1.dfeae7d9e6904p-4, -0x1.9372a67f28403p-5, 0x1.d6961856ec775p-4, + -0x1.d6961856ec775p-4, 0x1.9372a67f28403p-5, -0x1.dfeae7d9e6904p-4, -0x1.64c7dd06b4ea9p-5, + -0x1.c1249b6b024edp-5, -0x1.cc1f0ef202621p-4, 0x1.35410d651034dp-5, -0x1.e817ba2e9f579p-4, + 0x1.c08c4318b68e5p-4, -0x1.edc191e2a7ef8p-5, 0x1.ef178db4908f3p-4, 0x1.04fb828351eacp-5, + 0x1.0c9703e24bab2p-4, 0x1.b3e4d313738efp-4, -0x1.a82a04f1902cbp-6, 0x1.f4e603a14368dp-4, + -0x1.a63090dbbcb44p-4, 0x1.21a79b66d0cf7p-4, -0x1.f97f9275d0469p-4, -0x1.455768c0ea3b7p-6, + -0x1.36058acf23669p-4, -0x1.9777eebaa3587p-4, 0x1.c37861c4f58bep-7, -0x1.fce161feaf39cp-4, + 0x1.87c400d1129d3p-4, -0x1.49a448d9878dap-4, 0x1.ff09573b62712p-4, 0x1.f656e20cba8a6p-8, + 0x1.5c77bce1338dcp-4, 0x1.771e744d0ad3cp-4, -0x1.921cc6805fc83p-10, 0x1.fff621b8c7797p-4, + -0x1.6591923728721p-4, 0x1.6e7444a4a2992p-4, -0x1.ffa72d9b61262p-4, 0x1.2d864fc5ada9cp-8, + -0x1.7f8ecc15feb29p-4, -0x1.53282848b25bep-4, -0x1.5f6d00609da9dp-7, -0x1.fe1cae60e262fp-4, + 0x1.3fed94a26c3d3p-4, -0x1.8fbccbab642dcp-4, 0x1.fb5797f188000p-4, -0x1.139f0d9295ce3p-6, + 0x1.9ef43f3a37567p-4, 0x1.2bedb2a4b4601p-4, 0x1.76dd9b9386e61p-6, 0x1.f7599b21909a5p-4, + -0x1.1734d5dc6fb4ep-4, 0x1.ad2bc847988b8p-4, -0x1.f2252f75b3423p-4, 0x1.d934fe8ee6bb4p-6, + -0x1.ba5aa7766cf71p-4, -0x1.01cfc81499c01p-4, -0x1.1d3444efac4c8p-5, -0x1.ebbd8d3835e1ap-4, + 0x1.d797742ba22bap-5, -0x1.c678b22c81cd9p-4, 0x1.e426a4850d155p-4, -0x1.4d1e245f8b719p-5, + 0x1.d17e74bee65c0p-4, 0x1.aa6c83065506fp-5, 0x1.7c3a9309e3d16p-5, 0x1.db652726d1a82p-4, + 0x1.030ec2a508761p-4, -0x1.6bab9cbe4b752p-7, 0x1.11faa191ea31cp-5, -0x1.e8f2f2b1c863ep-5, + -0x1.2ff00cc7efd42p-7, -0x1.2d55ed4248c6ap-3, -0x1.0a1ea08d7dd93p-4, 0x1.15616726b9fc1p-4, + -0x1.3c521c0e119bcp-4, 0x1.3609212ce6f52p-4, 0x1.907ec67c36326p-5, 0x1.c2549cc78de91p-3, + -0x1.9297789f56a67p-6, 0x1.b5b7586cb4c9dp-4, 0x1.6c502c62944e4p-5, -0x1.016587de036bcp-4, + -0x1.1a88a57f6516dp-4, -0x1.a556e10fbc093p-7, 0x1.3795e9f63be1cp-5, 0x1.d4664fc0b0f1ap-5, + -0x1.0ae01882bebe6p-6, -0x1.411a49b9a83f3p-4, 0x1.27859df016f7cp-4, -0x1.923e787f4d31ep-5, + -0x1.921e89e013626p-3, -0x1.d144067119aa8p-10, 0x1.f11efd71635dbp-4, -0x1.0a71803092b05p-9, + -0x1.4f460a9bf81e7p-9, -0x1.1aeb04e90e051p-2, 0x1.b194e312098f5p-5, 0x1.596f365408fd4p-6, + 0x1.fcc1da02339d7p-4, 0x1.6eaa75647d62fp-8, 0x1.86bc8a862f2a7p-6, 0x1.6dd40a88fd98ep-6, + 0x1.e0b953b065d54p-9, -0x1.acbe97ba0637cp-7, 0x1.ef6a88141ae5fp-6, 0x1.6b8beb0927609p-4, + 0x1.77be0293431aap-4, -0x1.4f49dbcffc55dp-7, 0x1.6af87dc7120ddp-4, 0x1.c9a21382056aep-4, + -0x1.9c15cd57008b6p-11, -0x1.212e61c012ed6p-4, -0x1.58e2aac08877ep-4, 0x1.00eaf24546ee8p-3, + 0x1.3c98689f532e9p-7, 0x1.c7a5fcd763f28p-9, 0x1.402e4d7ae90aap-4, 0x1.89817ac9f0053p-4, + -0x1.818d2d4eeb665p-7, -0x1.18a857b01f547p-6, -0x1.0fe7fe129b78cp-3, -0x1.bd8c679441ba2p-4, + -0x1.66c416fde12d3p-3, -0x1.f5cd711892281p-6, -0x1.1a75f077e0581p-4, 0x1.cc33ac9dc1a9bp-5, + 0x1.dd4d9121f2e40p-5, 0x1.c295494503d7bp-3, 0x1.ebcfd145c0460p-5, -0x1.24c6b17379dbbp-5, + 0x1.24c6b17379dbbp-5, -0x1.ebcfd145c0460p-5, -0x1.c295494503d7bp-3, -0x1.dd4d9121f2e40p-5, + -0x1.cc33ac9dc1a9bp-5, 0x1.1a75f077e0581p-4, 0x1.f5cd711892281p-6, 0x1.66c416fde12d3p-3, + 0x1.bd8c679441ba2p-4, 0x1.0fe7fe129b78cp-3, 0x1.18a857b01f547p-6, 0x1.818d2d4eeb665p-7, + -0x1.89817ac9f0053p-4, -0x1.402e4d7ae90aap-4, -0x1.c7a5fcd763f28p-9, -0x1.3c98689f532e9p-7, + -0x1.00eaf24546ee8p-3, 0x1.58e2aac08877ep-4, 0x1.212e61c012ed6p-4, 0x1.9c15cd57008b6p-11, + -0x1.c9a21382056aep-4, -0x1.6af87dc7120ddp-4, 0x1.4f49dbcffc55dp-7, -0x1.77be0293431aap-4, + -0x1.6b8beb0927609p-4, -0x1.ef6a88141ae5fp-6, 0x1.acbe97ba0637cp-7, -0x1.e0b953b065d54p-9, + -0x1.6dd40a88fd98ep-6, -0x1.86bc8a862f2a7p-6, -0x1.6eaa75647d62fp-8, -0x1.fcc1da02339d7p-4, + -0x1.596f365408fd4p-6, -0x1.b194e312098f5p-5, 0x1.1aeb04e90e051p-2, 0x1.4f460a9bf81e7p-9, + 0x1.0a71803092b05p-9, -0x1.f11efd71635dbp-4, 0x1.d144067119aa8p-10, 0x1.921e89e013626p-3, + 0x1.923e787f4d31ep-5, -0x1.27859df016f7cp-4, 0x1.411a49b9a83f3p-4, 0x1.0ae01882bebe6p-6, + -0x1.d4664fc0b0f1ap-5, -0x1.3795e9f63be1cp-5, 0x1.a556e10fbc093p-7, 0x1.1a88a57f6516dp-4, + 0x1.016587de036bcp-4, -0x1.6c502c62944e4p-5, -0x1.b5b7586cb4c9dp-4, 0x1.9297789f56a67p-6, + -0x1.c2549cc78de91p-3, -0x1.907ec67c36326p-5, -0x1.3609212ce6f52p-4, 0x1.3c521c0e119bcp-4, + -0x1.15616726b9fc1p-4, 0x1.0a1ea08d7dd93p-4, 0x1.2d55ed4248c66p-3, 0x1.2ff00cc7efd31p-7, + 0x1.e8f2f2b1c863ep-5, -0x1.11faa191ea323p-5, 0x1.6baba1344da88p-7, -0x1.030ec29b281bep-4, + 0x1.1e9d3ff60dd81p-4, 0x1.8fcf2869b54a7p-8, -0x1.3157e1a8732e8p-3, -0x1.dc9725d97eadap-6, + 0x1.9e18eae900c3bp-4, 0x1.38112a5bf2af3p-4, -0x1.a68c468d6f6a6p-5, -0x1.79e4122e3e5abp-10, + -0x1.16e3c1149edaep-5, 0x1.790350b702d14p-5, -0x1.4c2cd461e2708p-5, 0x1.f26d599414be4p-6, + 0x1.548120d310f33p-6, -0x1.af776faa107dap-7, -0x1.6a5099ed7c79fp-4, -0x1.47d8963aaa1eep-6, + 0x1.a8c82f605de4bp-6, -0x1.5c886b27478b6p-5, 0x1.c68cf9bb2e6c5p-4, 0x1.49cef569dd5e8p-4, + -0x1.93b8b9005e1efp-5, 0x1.58a6e4a47ec70p-6, -0x1.6d08d3203bef3p-4, -0x1.1a38fe3b42327p-4, + 0x1.6f8ef8edfd8ffp-7, -0x1.f02d56e0da09fp-4, 0x1.0cd60d471cbc4p-4, 0x1.6cfc8a9d751a6p-5, + -0x1.4b7d66c61c65ap-3, -0x1.1e4f827d6e291p-8, -0x1.5840e85d2df92p-5, -0x1.0a980c0989b04p-2, + 0x1.075bbf580eb1fp-6, 0x1.133c8a0d8a205p-6, -0x1.c3d0e6e224962p-4, -0x1.dd50eb2873a88p-5, + -0x1.7d09d5831b629p-4, 0x1.c5f0cc1027f6fp-7, -0x1.834ef0c70f292p-4, -0x1.252f3d08df969p-3, + -0x1.1a14d3954c6f2p-7, -0x1.2041ff0891bb5p-6, -0x1.6f052eb871f61p-5, 0x1.1ddbb7b678779p-5, + 0x1.3da5f5dd38b71p-5, -0x1.c768ec7f7eb0ap-6, -0x1.ad285bd43cb58p-3, 0x1.ac8106d6db521p-4, + 0x1.efd8f6794a867p-8, 0x1.578569100fd7dp-4, -0x1.57c6517baa8e3p-4, -0x1.650dcf464d2cap-6, + 0x1.0e890b4574ce3p-3, 0x1.86bb5621ff658p-4, -0x1.0f2a815b35790p-5, 0x1.a0dfae0896c8cp-5, + -0x1.7de78916bc5c7p-7, -0x1.08f41c9e6838ep-3, 0x1.6c2f49e4b6d69p-4, 0x1.69542656d35e2p-3, + -0x1.0ac1a83100880p-2, 0x1.71b2e9b976027p-7, -0x1.6ca1b48a5554bp-6, -0x1.8671dd373b9b0p-6, + 0x1.8671dd373b9b0p-6, 0x1.6ca1b48a5554bp-6, -0x1.71b2e9b976027p-7, 0x1.0ac1a83100880p-2, + -0x1.69542656d35e2p-3, -0x1.6c2f49e4b6d69p-4, 0x1.08f41c9e6838ep-3, 0x1.7de78916bc5c7p-7, + -0x1.a0dfae0896c8cp-5, 0x1.0f2a815b35790p-5, -0x1.86bb5621ff658p-4, -0x1.0e890b4574ce3p-3, + 0x1.650dcf464d2cap-6, 0x1.57c6517baa8e3p-4, -0x1.578569100fd7dp-4, -0x1.efd8f6794a867p-8, + -0x1.ac8106d6db521p-4, 0x1.ad285bd43cb58p-3, 0x1.c768ec7f7eb0ap-6, -0x1.3da5f5dd38b71p-5, + -0x1.1ddbb7b678779p-5, 0x1.6f052eb871f61p-5, 0x1.2041ff0891bb5p-6, 0x1.1a14d3954c6f2p-7, + 0x1.252f3d08df969p-3, 0x1.834ef0c70f292p-4, -0x1.c5f0cc1027f6fp-7, 0x1.7d09d5831b629p-4, + 0x1.dd50eb2873a88p-5, 0x1.c3d0e6e224962p-4, -0x1.133c8a0d8a205p-6, -0x1.075bbf580eb1fp-6, + 0x1.0a980c0989b04p-2, 0x1.5840e85d2df92p-5, 0x1.1e4f827d6e291p-8, 0x1.4b7d66c61c65ap-3, + -0x1.6cfc8a9d751a6p-5, -0x1.0cd60d471cbc4p-4, 0x1.f02d56e0da09fp-4, -0x1.6f8ef8edfd8ffp-7, + 0x1.1a38fe3b42327p-4, 0x1.6d08d3203bef3p-4, -0x1.58a6e4a47ec70p-6, 0x1.93b8b9005e1efp-5, + -0x1.49cef569dd5e8p-4, -0x1.c68cf9bb2e6c5p-4, 0x1.5c886b27478b6p-5, -0x1.a8c82f605de4bp-6, + 0x1.47d8963aaa1eep-6, 0x1.6a5099ed7c79fp-4, 0x1.af776faa107dap-7, -0x1.548120d310f33p-6, + -0x1.f26d599414be4p-6, 0x1.4c2cd461e2708p-5, -0x1.790350b702d14p-5, 0x1.16e3c1149edaep-5, + 0x1.79e4122e3e5a6p-10, 0x1.a68c468d6f6a6p-5, -0x1.38112a5bf2af1p-4, -0x1.9e18eae900c40p-4, + 0x1.dc9725d97eacfp-6, 0x1.3157e1a8732dep-3, -0x1.8fcf28c8398f6p-8, -0x1.1e9d423666295p-4, + 0x1.64c7df7460decp-5, -0x1.dfeae7979d69ep-4, -0x1.c08c3e89ac90ep-4, 0x1.edc193c9eae91p-5, + 0x1.f4e6043a05182p-4, 0x1.a82a0316f4cccp-6, -0x1.36058c209c9c9p-4, -0x1.9777efb85615dp-4, + -0x1.f656eed75c719p-8, 0x1.ff09557dbb4a7p-4, 0x1.659193a5408e0p-4, -0x1.6e74483dfdc5cp-4, + -0x1.fe1cb0cb7f724p-4, 0x1.5f6cf7d39854fp-7, 0x1.9ef43c851403cp-4, 0x1.2bedb6445bb2dp-4, + -0x1.d934f7d48f1b9p-6, -0x1.f2252eccb04c3p-4, -0x1.d7976f7734e1fp-5, 0x1.c678b2dcf7a98p-4, + 0x1.db6526b1283afp-4, -0x1.7c3a8f6622cf3p-5, -0x1.e426a274713aep-4, -0x1.4d1e2392332f3p-5, + 0x1.01cfc7c9b9df8p-4, 0x1.ba5aa493fc61cp-4, 0x1.76dd9c145df36p-6, -0x1.f7599c3e63fdap-4, + -0x1.8fbcc9ca99219p-4, 0x1.3fed967689beap-4, 0x1.ffa72e9912d68p-4, 0x1.2d86520bef7f2p-8, + -0x1.771e75b6d05c2p-4, -0x1.5c77bc01eb422p-4, 0x1.c378565601113p-7, 0x1.fce15dd7ac521p-4, + 0x1.21a799e99847cp-4, -0x1.a6309058befdep-4, -0x1.ef178c854055ap-4, 0x1.04fb8032fef5bp-5, + 0x1.cc1f0d9f67439p-4, 0x1.c1249a8826f36p-5, -0x1.9372a75e17ab5p-5, -0x1.d69619a3d6c88p-4, + -0x1.354111c9d4f7cp-5, 0x1.e817bd884c61ep-4, 0x1.b3e4d4c93a03dp-4, -0x1.0c970528570d6p-4, + -0x1.f97f90629ac50p-4, -0x1.4557697b9dd93p-6, 0x1.49a448d1d439fp-4, 0x1.87c3ff17546c6p-4, + 0x1.921d77fc72a1ap-10, -0x1.fff623b9def37p-4, -0x1.5328291e39e9dp-4, 0x1.7f8ecf286c5d7p-4, + 0x1.fb5794d238330p-4, -0x1.139f1884b6ff5p-6, -0x1.ad2bca80b8c41p-4, -0x1.1734d84ef468ep-4, + 0x1.1d34461383eb7p-5, 0x1.ebbd8b2c5075ap-4, 0x1.aa6c86067e33cp-5, -0x1.d17e77702bcf2p-4, + -0x1.d17e77702bcf2p-4, 0x1.aa6c86067e33cp-5, 0x1.ebbd8b2c5075ap-4, 0x1.1d34461383eb7p-5, + -0x1.1734d84ef468ep-4, -0x1.ad2bca80b8c41p-4, -0x1.139f1884b6ff5p-6, 0x1.fb5794d238330p-4, + 0x1.7f8ecf286c5d7p-4, -0x1.5328291e39e9dp-4, -0x1.fff623b9def37p-4, 0x1.921d77fc72a1ap-10, + 0x1.87c3ff17546c6p-4, 0x1.49a448d1d439fp-4, -0x1.4557697b9dd93p-6, -0x1.f97f90629ac50p-4, + -0x1.0c970528570d6p-4, 0x1.b3e4d4c93a03dp-4, 0x1.e817bd884c61ep-4, -0x1.354111c9d4f7cp-5, + -0x1.d69619a3d6c88p-4, -0x1.9372a75e17ab5p-5, 0x1.c1249a8826f36p-5, 0x1.cc1f0d9f67439p-4, + 0x1.04fb8032fef5bp-5, -0x1.ef178c854055ap-4, -0x1.a6309058befdep-4, 0x1.21a799e99847cp-4, + 0x1.fce15dd7ac521p-4, 0x1.c378565601113p-7, -0x1.5c77bc01eb422p-4, -0x1.771e75b6d05c2p-4, + 0x1.2d86520bef7f2p-8, 0x1.ffa72e9912d68p-4, 0x1.3fed967689beap-4, -0x1.8fbcc9ca99219p-4, + -0x1.f7599c3e63fdap-4, 0x1.76dd9c145df36p-6, 0x1.ba5aa493fc61cp-4, 0x1.01cfc7c9b9df8p-4, + -0x1.4d1e2392332f3p-5, -0x1.e426a274713aep-4, -0x1.7c3a8f6622cf3p-5, 0x1.db6526b1283afp-4, + 0x1.c678b2dcf7a98p-4, -0x1.d7976f7734e1fp-5, -0x1.f2252eccb04c3p-4, -0x1.d934f7d48f1b9p-6, + 0x1.2bedb6445bb2dp-4, 0x1.9ef43c851403cp-4, 0x1.5f6cf7d39854fp-7, -0x1.fe1cb0cb7f724p-4, + -0x1.6e74483dfdc5cp-4, 0x1.659193a5408e0p-4, 0x1.ff09557dbb4a7p-4, -0x1.f656eed75c719p-8, + -0x1.9777efb85615dp-4, -0x1.36058c209c9c9p-4, 0x1.a82a0316f4cccp-6, 0x1.f4e6043a05182p-4, + 0x1.edc193c9eae91p-5, -0x1.c08c3e89ac90ep-4, -0x1.dfeae7979d69ep-4, 0x1.64c7df7460e41p-5, + 0x1.dfeae6fc7ee20p-4, 0x1.64c7df33d3cdcp-5, 0x1.edc1943691c20p-5, 0x1.c08c3f716978fp-4, + -0x1.a82a030c63775p-6, 0x1.f4e602b8eaeb0p-4, -0x1.9777f02e25086p-4, 0x1.36058afb56cf7p-4, + -0x1.ff09549ddd854p-4, -0x1.f656eda83b831p-8, -0x1.6e7447916ac0dp-4, -0x1.65919413090efp-4, + -0x1.5f6cf980fb542p-7, -0x1.fe1cb25583397p-4, 0x1.2bedb57f57804p-4, -0x1.9ef43dcd9bb4cp-4, + 0x1.f22530e32fd28p-4, -0x1.d934f842f5c16p-6, 0x1.c678b411768f8p-4, 0x1.d7976f5f3d081p-5, + 0x1.7c3a8ff63958dp-5, 0x1.db6526cd611b7p-4, -0x1.4d1e23db19226p-5, 0x1.e426a437efb17p-4, + -0x1.ba5aa5c64a806p-4, 0x1.01cfc73ea870ap-4, -0x1.f7599aa1c2047p-4, -0x1.76dd9c8c49a33p-6, + -0x1.3fed96a5a003dp-4, -0x1.8fbcc8f759fcfp-4, 0x1.2d8653b2454c0p-8, -0x1.ffa72dc669b8dp-4, + 0x1.5c77bbce3bb27p-4, -0x1.771e7615aeb8ap-4, 0x1.fce15df488d22p-4, -0x1.c37854e769800p-7, + 0x1.a6308ff04aa8fp-4, 0x1.21a7996d5c348p-4, 0x1.04fb7f49794b4p-5, 0x1.ef178cde7e5c5p-4, + -0x1.c12499189b6b9p-5, 0x1.cc1f0cb02d963p-4, -0x1.d696194ac6f1dp-4, 0x1.9372a79bd085cp-5, + -0x1.e817bd171d48cp-4, -0x1.3541113bfd8b6p-5, -0x1.0c970610fefacp-4, -0x1.b3e4d438b3fbfp-4, + 0x1.455768556da2ep-6, -0x1.f97f902c1ca04p-4, 0x1.87c3ffdb567afp-4, -0x1.49a44970349cdp-4, + 0x1.fff62403c932dp-4, 0x1.921d7189d5e72p-10, 0x1.7f8eceed19614p-4, 0x1.532829639a1bep-4, + 0x1.139f1962f4720p-6, 0x1.fb5793dfe3a43p-4, -0x1.1734d711fc4b2p-4, 0x1.ad2bcac9ea665p-4, + -0x1.ebbd8a769a250p-4, 0x1.1d3446a0473b0p-5, -0x1.d17e780ae4575p-4, -0x1.aa6c8638cded7p-5, + -0x1.aa6c8638cded7p-5, -0x1.d17e780ae4575p-4, 0x1.1d3446a0473b0p-5, -0x1.ebbd8a769a250p-4, + 0x1.ad2bcac9ea665p-4, -0x1.1734d711fc4b2p-4, 0x1.fb5793dfe3a43p-4, 0x1.139f1962f4720p-6, + 0x1.532829639a1bep-4, 0x1.7f8eceed19614p-4, 0x1.921d7189d5e72p-10, 0x1.fff62403c932dp-4, + -0x1.49a44970349cdp-4, 0x1.87c3ffdb567afp-4, -0x1.f97f902c1ca04p-4, 0x1.455768556da2ep-6, + -0x1.b3e4d438b3fbfp-4, -0x1.0c970610fefacp-4, -0x1.3541113bfd8b6p-5, -0x1.e817bd171d48cp-4, + 0x1.9372a79bd085cp-5, -0x1.d696194ac6f1dp-4, 0x1.cc1f0cb02d963p-4, -0x1.c12499189b6b9p-5, + 0x1.ef178cde7e5c5p-4, 0x1.04fb7f49794b4p-5, 0x1.21a7996d5c348p-4, 0x1.a6308ff04aa8fp-4, + -0x1.c37854e769800p-7, 0x1.fce15df488d22p-4, -0x1.771e7615aeb8ap-4, 0x1.5c77bbce3bb27p-4, + -0x1.ffa72dc669b8dp-4, 0x1.2d8653b2454c0p-8, -0x1.8fbcc8f759fcfp-4, -0x1.3fed96a5a003dp-4, + -0x1.76dd9c8c49a33p-6, -0x1.f7599aa1c2047p-4, 0x1.01cfc73ea870ap-4, -0x1.ba5aa5c64a806p-4, + 0x1.e426a437efb17p-4, -0x1.4d1e23db19226p-5, 0x1.db6526cd611b7p-4, 0x1.7c3a8ff63958dp-5, + 0x1.d7976f5f3d081p-5, 0x1.c678b411768f8p-4, -0x1.d934f842f5c16p-6, 0x1.f22530e32fd28p-4, + -0x1.9ef43dcd9bb4cp-4, 0x1.2bedb57f57804p-4, -0x1.fe1cb25583397p-4, -0x1.5f6cf980fb542p-7, + -0x1.65919413090efp-4, -0x1.6e7447916ac0dp-4, -0x1.f656eda83b831p-8, -0x1.ff09549ddd854p-4, + 0x1.36058afb56cf7p-4, -0x1.9777f02e25086p-4, 0x1.f4e602b8eaeb0p-4, -0x1.a82a030c63775p-6, + 0x1.c08c3f716978fp-4, 0x1.edc1943691c20p-5, 0x1.64c7df33d3c9dp-5, 0x1.dfeae6fc7ee20p-4, + -0x1.c7466461fe8adp-10, 0x1.30aafbdee6778p-4, -0x1.a1a0d448dc81bp-4, 0x1.053ffb8c12b53p-3, + 0x1.0ddc1deebe8b8p-6, 0x1.989563dc2ed37p-3, 0x1.87b7de5b2c877p-3, 0x1.ae7c560193e9fp-7, + -0x1.d7800c35073ffp-5, -0x1.46364fe85d47fp-8, -0x1.bee35b8f7fb2ep-7, 0x1.67628b963ca49p-3, + 0x1.f07932dbac577p-7, 0x1.b38244f77d840p-7, -0x1.2108e4129ff2ep-7, 0x1.a938598c7c294p-6, + -0x1.20e9d9abe34e4p-2, 0x1.ee9bdfc2bfa08p-6, -0x1.5cc8f1b8eea06p-3, 0x1.ae3b930d07e4fp-5, + 0x1.36861d7c6def2p-5, 0x1.4bb7b6cad86a0p-4, -0x1.92a619c935743p-5, -0x1.0ed0b8b9192edp-6, + 0x1.2c3b91d1ddfbap-11, 0x1.3327158c73365p-3, -0x1.4878f10b56d4dp-4, -0x1.0d0ec956e4a59p-6, + 0x1.b07985c056dadp-5, 0x1.0e38c84e81c6ep-6, -0x1.0619a0f472258p-6, 0x1.fdfc1291cbb4cp-5, + 0x1.8dc6ec83071bbp-4, 0x1.73edf1b073f30p-6, -0x1.01dc66a69eec8p-4, -0x1.b4a1b14113bdep-7, + -0x1.6534eaa8e1affp-7, 0x1.dad13478e175cp-5, 0x1.d3ac6fd8a4a9ep-6, -0x1.2b5750ee3c583p-3, + 0x1.9ec0edae4f811p-7, -0x1.6175536db1a04p-8, -0x1.2e3652ebbe8bbp-3, -0x1.34d76f3613839p-5, + -0x1.3c81d53592a9cp-3, -0x1.bef7148c34d5dp-5, -0x1.d9b7d27596e3dp-6, 0x1.4ca9bcf65cda0p-3, + 0x1.dea63feec8dc1p-10, -0x1.e8000ff018d68p-6, -0x1.ad4dcfbd0eca1p-5, -0x1.45cbc1db99baap-4, + 0x1.9796307d09a64p-5, 0x1.2395f52a60fd9p-7, -0x1.8ad183684ba19p-5, 0x1.4030e4b3d6735p-3, + -0x1.8c9f0358aa65ap-6, 0x1.46fa4ba246256p-4, -0x1.6c341cb8f259fp-4, 0x1.4a6afe9c89c23p-6, + -0x1.8afc3423cc7fdp-5, -0x1.bd37b7f29fc41p-5, 0x1.1ad9c4da2ec9fp-3, 0x1.4b39c4574ea9ep-8, + 0x1.4b39c4574ea9ep-8, 0x1.1ad9c4da2ec9fp-3, -0x1.bd37b7f29fc41p-5, -0x1.8afc3423cc7fdp-5, + 0x1.4a6afe9c89c23p-6, -0x1.6c341cb8f259fp-4, 0x1.46fa4ba246256p-4, -0x1.8c9f0358aa65ap-6, + 0x1.4030e4b3d6735p-3, -0x1.8ad183684ba19p-5, 0x1.2395f52a60fd9p-7, 0x1.9796307d09a64p-5, + -0x1.45cbc1db99baap-4, -0x1.ad4dcfbd0eca1p-5, -0x1.e8000ff018d68p-6, 0x1.dea63feec8dc1p-10, + 0x1.4ca9bcf65cda0p-3, -0x1.d9b7d27596e3dp-6, -0x1.bef7148c34d5dp-5, -0x1.3c81d53592a9cp-3, + -0x1.34d76f3613839p-5, -0x1.2e3652ebbe8bbp-3, -0x1.6175536db1a04p-8, 0x1.9ec0edae4f811p-7, + -0x1.2b5750ee3c583p-3, 0x1.d3ac6fd8a4a9ep-6, 0x1.dad13478e175cp-5, -0x1.6534eaa8e1affp-7, + -0x1.b4a1b14113bdep-7, -0x1.01dc66a69eec8p-4, 0x1.73edf1b073f30p-6, 0x1.8dc6ec83071bbp-4, + 0x1.fdfc1291cbb4cp-5, -0x1.0619a0f472258p-6, 0x1.0e38c84e81c6ep-6, 0x1.b07985c056dadp-5, + -0x1.0d0ec956e4a59p-6, -0x1.4878f10b56d4dp-4, 0x1.3327158c73365p-3, 0x1.2c3b91d1ddfbap-11, + -0x1.0ed0b8b9192edp-6, -0x1.92a619c935743p-5, 0x1.4bb7b6cad86a0p-4, 0x1.36861d7c6def2p-5, + 0x1.ae3b930d07e4fp-5, -0x1.5cc8f1b8eea06p-3, 0x1.ee9bdfc2bfa08p-6, -0x1.20e9d9abe34e4p-2, + 0x1.a938598c7c294p-6, -0x1.2108e4129ff2ep-7, 0x1.b38244f77d840p-7, 0x1.f07932dbac577p-7, + 0x1.67628b963ca49p-3, -0x1.bee35b8f7fb2ep-7, -0x1.46364fe85d47fp-8, -0x1.d7800c35073ffp-5, + 0x1.ae7c560193e9fp-7, 0x1.87b7de5b2c877p-3, 0x1.989563dc2ed39p-3, 0x1.0ddc1deebe8b6p-6, + 0x1.053ffb8c12b51p-3, -0x1.a1a0d448dc81fp-4, 0x1.30aafb9a22e21p-4, -0x1.c7465c3ea1dd1p-10, + 0x1.fc43b5c2b1b1bp-5, -0x1.644e9fab90e9ap-5, 0x1.65b3bdf572de5p-5, 0x1.ffc7b19560907p-7, + 0x1.ab87f0d9e9da8p-5, 0x1.3e63bde9f1b1cp-5, -0x1.c687e4dc29320p-4, 0x1.a8bf2c1636d9cp-6, + -0x1.76319a130880ep-5, -0x1.cd88e7476dc7bp-7, -0x1.b653ef5967e8fp-5, -0x1.37ae312464c69p-4, + 0x1.3089eaa8f6a65p-3, -0x1.59097632f360fp-5, -0x1.ec2a510b76a46p-5, 0x1.7e76dccb869d1p-4, + -0x1.2a26e015513c8p-7, -0x1.41cc377acd359p-7, -0x1.281384ba1593cp-4, 0x1.1ddea93ed492ep-4, + -0x1.b5dfac203bb2bp-3, 0x1.62d882945245ap-5, 0x1.8b41913fb2376p-3, 0x1.0de3d3af22201p-5, + 0x1.7fb4a707d9167p-5, -0x1.38e1b04077260p-3, -0x1.7d0621366122ep-5, -0x1.fbc14fa84fef9p-5, + 0x1.11b96397d25bfp-6, 0x1.04e1e93d9f6bcp-3, 0x1.b074bfef24b55p-6, -0x1.f5598328aa5c7p-7, + 0x1.d3e2eecc41ebap-4, -0x1.cdb5b821354f7p-8, 0x1.8b5db5dbcba41p-6, 0x1.fc5ede9282a23p-5, + 0x1.a80c4af2564b5p-5, -0x1.2a3878218fd42p-3, -0x1.308de8310735ep-3, 0x1.3a26ef4f79107p-6, + 0x1.21997eae313f6p-4, 0x1.9fe1118c5e57bp-5, -0x1.1ce557177e769p-4, -0x1.84054baf65788p-6, + -0x1.cb4640721921bp-4, 0x1.b32a8f11036d8p-5, 0x1.19eff86724846p-3, 0x1.1672c0496947dp-3, + -0x1.8f4375daa16f4p-3, -0x1.71ad1b0a2d62dp-6, 0x1.c650a59f35d17p-8, -0x1.da934f7c364b1p-5, + 0x1.4e39e1212543fp-5, 0x1.8c4bfbb8e2779p-4, 0x1.98956948dc386p-4, -0x1.638215910a602p-6, + -0x1.1aedfb3b309ecp-3, 0x1.9bc9265f31cd3p-5, 0x1.c97d6a6fc61bbp-3, -0x1.2d6d040a326a2p-4, + -0x1.2e78a0aa7e07dp-4, 0x1.f8fc3dc7c6b64p-7, 0x1.5364a143c8bf6p-4, -0x1.853d644a651dfp-9, + -0x1.853d644a651dfp-9, 0x1.5364a143c8bf6p-4, 0x1.f8fc3dc7c6b64p-7, -0x1.2e78a0aa7e07dp-4, + -0x1.2d6d040a326a2p-4, 0x1.c97d6a6fc61bbp-3, 0x1.9bc9265f31cd3p-5, -0x1.1aedfb3b309ecp-3, + -0x1.638215910a602p-6, 0x1.98956948dc386p-4, 0x1.8c4bfbb8e2779p-4, 0x1.4e39e1212543fp-5, + -0x1.da934f7c364b1p-5, 0x1.c650a59f35d17p-8, -0x1.71ad1b0a2d62dp-6, -0x1.8f4375daa16f4p-3, + 0x1.1672c0496947dp-3, 0x1.19eff86724846p-3, 0x1.b32a8f11036d8p-5, -0x1.cb4640721921bp-4, + -0x1.84054baf65788p-6, -0x1.1ce557177e769p-4, 0x1.9fe1118c5e57bp-5, 0x1.21997eae313f6p-4, + 0x1.3a26ef4f79107p-6, -0x1.308de8310735ep-3, -0x1.2a3878218fd42p-3, 0x1.a80c4af2564b5p-5, + 0x1.fc5ede9282a23p-5, 0x1.8b5db5dbcba41p-6, -0x1.cdb5b821354f7p-8, 0x1.d3e2eecc41ebap-4, + -0x1.f5598328aa5c7p-7, 0x1.b074bfef24b55p-6, 0x1.04e1e93d9f6bcp-3, 0x1.11b96397d25bfp-6, + -0x1.fbc14fa84fef9p-5, -0x1.7d0621366122ep-5, -0x1.38e1b04077260p-3, 0x1.7fb4a707d9167p-5, + 0x1.0de3d3af22201p-5, 0x1.8b41913fb2376p-3, 0x1.62d882945245ap-5, -0x1.b5dfac203bb2bp-3, + 0x1.1ddea93ed492ep-4, -0x1.281384ba1593cp-4, -0x1.41cc377acd359p-7, -0x1.2a26e015513c8p-7, + 0x1.7e76dccb869d1p-4, -0x1.ec2a510b76a46p-5, -0x1.59097632f360fp-5, 0x1.3089eaa8f6a65p-3, + -0x1.37ae312464c69p-4, -0x1.b653ef5967e8fp-5, -0x1.cd88e7476dc7bp-7, -0x1.76319a130880ep-5, + 0x1.a8bf2c1636d9cp-6, -0x1.c687e4dc2931fp-4, 0x1.3e63bde9f1b1fp-5, 0x1.ab87f0d9e9dacp-5, + 0x1.ffc7b1956091dp-7, 0x1.65b3bdf572e05p-5, -0x1.644e9fca7b188p-5, 0x1.fc43b2feb5319p-5, + 0x1.4d1e2552cfb57p-5, -0x1.e426a61c57811p-4, -0x1.ad2bc9142c63fp-4, 0x1.1734d459b1061p-4, + 0x1.fe1cb0041891bp-4, 0x1.5f6cff52be676p-7, -0x1.771e74868a902p-4, -0x1.5c77ba79a2568p-4, + 0x1.45576d8dd2bc2p-6, 0x1.f97f91dd6dfa0p-4, 0x1.edc194e9f7866p-5, -0x1.c08c40622d22dp-4, + -0x1.d69616bc2f2eep-4, 0x1.9372a8955432cp-5, 0x1.ef1789ed9a275p-4, 0x1.04fb803a963bep-5, + -0x1.36058c53c748bp-4, -0x1.9777f02303485p-4, -0x1.921d831fdb654p-10, 0x1.fff61f2b7c679p-4, + 0x1.3fed94ba281c0p-4, -0x1.8fbcc7e2ee96fp-4, -0x1.f2252f86b6fdap-4, 0x1.d934ffa2ba066p-6, + 0x1.d17e7486ae2dbp-4, 0x1.aa6c81893b499p-5, -0x1.d797737f5e781p-5, -0x1.c678b37c705cbp-4, + -0x1.76dd9f5d6366bp-6, 0x1.f7599bfba2152p-4, 0x1.7f8ecf610c06cp-4, -0x1.532829ef512e1p-4, + -0x1.ff09569263ec7p-4, 0x1.f656e21b07cecp-8, 0x1.a63091ea3cf50p-4, 0x1.21a799f9a8018p-4, + -0x1.35410cc0b02d2p-5, -0x1.e817baae153b8p-4, -0x1.64c7d9031eac7p-5, 0x1.dfeae48ba6c07p-4, + 0x1.b3e4d4806727cp-4, -0x1.0c97040d950b4p-4, -0x1.fce15ff20e360p-4, -0x1.c378585a147a7p-7, + 0x1.6e7443c874408p-4, 0x1.659193732b009p-4, -0x1.139f0c9a9964dp-6, -0x1.fb57996b64af2p-4, + -0x1.01cfc835e618cp-4, 0x1.ba5aa450e946ep-4, 0x1.db652796781f1p-4, -0x1.7c3a91b040864p-5, + -0x1.ebbd8e3a6cbe4p-4, -0x1.1d3445d279249p-5, 0x1.2bedb4fa9b664p-4, 0x1.9ef43f6cb9217p-4, + 0x1.2d864f8ba2ddfp-8, -0x1.ffa72f3989093p-4, -0x1.49a449c6248c2p-4, 0x1.87c3ffd991616p-4, + 0x1.f4e60573b280cp-4, -0x1.a829fc06cde53p-6, -0x1.cc1f11c3fd21cp-4, -0x1.c124a17560fe8p-5, + 0x1.c124a17560fe8p-5, 0x1.cc1f11c3fd21cp-4, 0x1.a829fc06cde53p-6, -0x1.f4e60573b280cp-4, + -0x1.87c3ffd991616p-4, 0x1.49a449c6248c2p-4, 0x1.ffa72f3989093p-4, -0x1.2d864f8ba2ddfp-8, + -0x1.9ef43f6cb9217p-4, -0x1.2bedb4fa9b664p-4, 0x1.1d3445d279249p-5, 0x1.ebbd8e3a6cbe4p-4, + 0x1.7c3a91b040864p-5, -0x1.db652796781f1p-4, -0x1.ba5aa450e946ep-4, 0x1.01cfc835e618cp-4, + 0x1.fb57996b64af2p-4, 0x1.139f0c9a9964dp-6, -0x1.659193732b009p-4, -0x1.6e7443c874408p-4, + 0x1.c378585a147a7p-7, 0x1.fce15ff20e360p-4, 0x1.0c97040d950b4p-4, -0x1.b3e4d4806727cp-4, + -0x1.dfeae48ba6c07p-4, 0x1.64c7d9031eac7p-5, 0x1.e817baae153b8p-4, 0x1.35410cc0b02d2p-5, + -0x1.21a799f9a8018p-4, -0x1.a63091ea3cf50p-4, -0x1.f656e21b07cecp-8, 0x1.ff09569263ec7p-4, + 0x1.532829ef512e1p-4, -0x1.7f8ecf610c06cp-4, -0x1.f7599bfba2152p-4, 0x1.76dd9f5d6366bp-6, + 0x1.c678b37c705cbp-4, 0x1.d797737f5e781p-5, -0x1.aa6c81893b499p-5, -0x1.d17e7486ae2dbp-4, + -0x1.d934ffa2ba066p-6, 0x1.f2252f86b6fdap-4, 0x1.8fbcc7e2ee96fp-4, -0x1.3fed94ba281c0p-4, + -0x1.fff61f2b7c679p-4, 0x1.921d831fdb654p-10, 0x1.9777f02303485p-4, 0x1.36058c53c748bp-4, + -0x1.04fb803a963bep-5, -0x1.ef1789ed9a275p-4, -0x1.9372a8955432cp-5, 0x1.d69616bc2f2eep-4, + 0x1.c08c40622d22dp-4, -0x1.edc194e9f7866p-5, -0x1.f97f91dd6dfa0p-4, -0x1.45576d8dd2bc2p-6, + 0x1.5c77ba79a2568p-4, 0x1.771e74868a902p-4, -0x1.5f6cff52be676p-7, -0x1.fe1cb0041891bp-4, + -0x1.1734d459b1061p-4, 0x1.ad2bc9142c63fp-4, 0x1.e426a61c57811p-4, -0x1.4d1e2552cfb26p-5, + 0x1.e426a5ffabc98p-4, 0x1.4d1e263865b54p-5, 0x1.1734d451e72fcp-4, 0x1.ad2bc82e9cea6p-4, + -0x1.5f6cffbae0a89p-7, 0x1.fe1cb0fcbd9e2p-4, -0x1.5c77bb1007a46p-4, 0x1.771e7445b3450p-4, + -0x1.f97f9184f5795p-4, 0x1.45576cd1f4300p-6, -0x1.c08c40d1182bcp-4, -0x1.edc195f12d7b6p-5, + -0x1.9372a89c3def9p-5, -0x1.d6961663340ddp-4, 0x1.04fb7ffc778b5p-5, -0x1.ef1789cead7c2p-4, + 0x1.9777f095d7c5fp-4, -0x1.36058c6153be7p-4, 0x1.fff61d95c06fcp-4, 0x1.921d8870fcb1ep-10, + 0x1.8fbcc8f4aea81p-4, 0x1.3fed953f42801p-4, 0x1.d93500da52ae5p-6, 0x1.f22530368eaacp-4, + -0x1.aa6c81af24335p-5, 0x1.d17e7495717efp-4, -0x1.c678b335bbd89p-4, 0x1.d7977435d226cp-5, + -0x1.f7599a6667361p-4, -0x1.76dd9e72b0b32p-6, -0x1.53282aef1b22cp-4, -0x1.7f8ece0b3f03fp-4, + -0x1.f656e1f5c64c7p-8, -0x1.ff095787ee6f4p-4, 0x1.21a79b1f2bc7cp-4, -0x1.a63092ce25233p-4, + 0x1.e817b9ece0b67p-4, -0x1.35410c947c07dp-5, 0x1.dfeae4e996edcp-4, 0x1.64c7d8a031220p-5, + 0x1.0c97051c27785p-4, 0x1.b3e4d4bc5417fp-4, -0x1.c378593df463fp-7, 0x1.fce1606221d85p-4, + -0x1.659194d5c7fa2p-4, 0x1.6e74450f1c68ap-4, -0x1.fb57982ca4cebp-4, 0x1.139f0c04721fap-6, + -0x1.ba5aa424295abp-4, -0x1.01cfc77d09523p-4, -0x1.7c3a9236a1277p-5, -0x1.db6526dfc41bep-4, + 0x1.1d34463ef0388p-5, -0x1.ebbd8e9e96fb1p-4, 0x1.9ef43f6cd08e9p-4, -0x1.2bedb4eef99d1p-4, + 0x1.ffa72e60b8c8bp-4, 0x1.2d864e67644a8p-8, 0x1.87c400932e4acp-4, 0x1.49a44b2bd31fep-4, + 0x1.a829fce5ca687p-6, 0x1.f4e60376261b7p-4, -0x1.c124a108e8a4fp-5, 0x1.cc1f1107db986p-4, + -0x1.cc1f1107db986p-4, 0x1.c124a108e8a4fp-5, -0x1.f4e60376261b7p-4, -0x1.a829fce5ca687p-6, + -0x1.49a44b2bd31fep-4, -0x1.87c400932e4acp-4, -0x1.2d864e67644a8p-8, -0x1.ffa72e60b8c8bp-4, + 0x1.2bedb4eef99d1p-4, -0x1.9ef43f6cd08e9p-4, 0x1.ebbd8e9e96fb1p-4, -0x1.1d34463ef0388p-5, + 0x1.db6526dfc41bep-4, 0x1.7c3a9236a1277p-5, 0x1.01cfc77d09523p-4, 0x1.ba5aa424295abp-4, + -0x1.139f0c04721fap-6, 0x1.fb57982ca4cebp-4, -0x1.6e74450f1c68ap-4, 0x1.659194d5c7fa2p-4, + -0x1.fce1606221d85p-4, 0x1.c378593df463fp-7, -0x1.b3e4d4bc5417fp-4, -0x1.0c97051c27785p-4, + -0x1.64c7d8a031220p-5, -0x1.dfeae4e996edcp-4, 0x1.35410c947c07dp-5, -0x1.e817b9ece0b67p-4, + 0x1.a63092ce25233p-4, -0x1.21a79b1f2bc7cp-4, 0x1.ff095787ee6f4p-4, 0x1.f656e1f5c64c7p-8, + 0x1.7f8ece0b3f03fp-4, 0x1.53282aef1b22cp-4, 0x1.76dd9e72b0b32p-6, 0x1.f7599a6667361p-4, + -0x1.d7977435d226cp-5, 0x1.c678b335bbd89p-4, -0x1.d17e7495717efp-4, 0x1.aa6c81af24335p-5, + -0x1.f22530368eaacp-4, -0x1.d93500da52ae5p-6, -0x1.3fed953f42801p-4, -0x1.8fbcc8f4aea81p-4, + -0x1.921d8870fcb1ep-10, -0x1.fff61d95c06fcp-4, 0x1.36058c6153be7p-4, -0x1.9777f095d7c5fp-4, + 0x1.ef1789cead7c2p-4, -0x1.04fb7ffc778b5p-5, 0x1.d6961663340ddp-4, 0x1.9372a89c3def9p-5, + 0x1.edc195f12d7b6p-5, 0x1.c08c40d1182bcp-4, -0x1.45576cd1f4300p-6, 0x1.f97f9184f5795p-4, + -0x1.771e7445b3450p-4, 0x1.5c77bb1007a46p-4, -0x1.fe1cb0fcbd9e2p-4, 0x1.5f6cffbae0a89p-7, + -0x1.ad2bc82e9cea6p-4, -0x1.1734d451e72fcp-4, -0x1.4d1e263865b19p-5, -0x1.e426a5ffabc94p-4, + -0x1.735ecb8e4c20fp-4, 0x1.7437e69acc1ffp-5, -0x1.a5e2621f822d8p-6, -0x1.62ee2d427506cp-4, + 0x1.bf2a6efd5fe3bp-7, -0x1.8afe34ae89b6ep-6, -0x1.383208aff57b3p-3, 0x1.1f66a46e60dfap-8, + -0x1.014ea253fc620p-5, -0x1.6b60e128b30bcp-6, -0x1.c91513cfa220dp-6, -0x1.5061d7c7ddd06p-5, + -0x1.c98c0a269d8f2p-7, -0x1.c4af68a4534b3p-7, -0x1.71f4b22598da5p-6, 0x1.b706ebda4505dp-4, + -0x1.07938dc7a5af3p-3, 0x1.2ab0248ae890dp-4, -0x1.1bb3dbc6f1095p-5, -0x1.3e182ce577056p-10, + -0x1.fabb016e64ff5p-6, -0x1.260f02910986bp-5, 0x1.4946e5123a31dp-8, 0x1.2f1a208b88accp-3, + -0x1.9fd4109fa34d0p-9, 0x1.de6a89be8f40bp-5, 0x1.47559fb08832dp-4, 0x1.320af48a9abbbp-5, + -0x1.b7b9ebdc759c3p-6, -0x1.821ad88a9db64p-5, -0x1.bd77b6a0a9320p-4, 0x1.ae2436187ff3cp-5, + 0x1.02c0d45da765bp-6, -0x1.cc9d8619dc8a0p-3, 0x1.f948756f0e344p-6, -0x1.d9f51019a9b54p-5, + -0x1.63e50c94ce606p-3, 0x1.2043e3f866ea4p-4, 0x1.dc1eda645cc3dp-4, -0x1.c63a112c67b0bp-6, + 0x1.97a70d41e40fdp-5, 0x1.dd1244e278041p-7, 0x1.06c2e0bc4b70ep-7, -0x1.a03d48b024f24p-4, + -0x1.e0cc381c18fdep-4, 0x1.9ac329d9fac24p-4, 0x1.b7b49b218f182p-3, 0x1.1f5cf1706e57dp-6, + 0x1.e497c36c5f273p-5, 0x1.1937acd0712eep-3, 0x1.c3ec07285eae9p-5, -0x1.ea57ffcd8bc9ep-10, + 0x1.47b251e3fdf9ap-8, 0x1.3322683603a8fp-3, 0x1.a0e8c8bdd9c3ap-4, -0x1.6ac8bfc00bbd2p-4, + 0x1.a0254abd597c4p-6, 0x1.0e453fbea437bp-10, -0x1.7a177c26fbd89p-5, 0x1.b24ec4693c108p-3, + -0x1.adbca65165753p-7, -0x1.33d312af9122fp-3, -0x1.d43a84e2fce80p-5, 0x1.8c318dfd4937dp-3, + -0x1.8c318dfd4937dp-3, 0x1.d43a84e2fce80p-5, 0x1.33d312af9122fp-3, 0x1.adbca65165753p-7, + -0x1.b24ec4693c108p-3, 0x1.7a177c26fbd89p-5, -0x1.0e453fbea437bp-10, -0x1.a0254abd597c4p-6, + 0x1.6ac8bfc00bbd2p-4, -0x1.a0e8c8bdd9c3ap-4, -0x1.3322683603a8fp-3, -0x1.47b251e3fdf9ap-8, + 0x1.ea57ffcd8bc9ep-10, -0x1.c3ec07285eae9p-5, -0x1.1937acd0712eep-3, -0x1.e497c36c5f273p-5, + -0x1.1f5cf1706e57dp-6, -0x1.b7b49b218f182p-3, -0x1.9ac329d9fac24p-4, 0x1.e0cc381c18fdep-4, + 0x1.a03d48b024f24p-4, -0x1.06c2e0bc4b70ep-7, -0x1.dd1244e278041p-7, -0x1.97a70d41e40fdp-5, + 0x1.c63a112c67b0bp-6, -0x1.dc1eda645cc3dp-4, -0x1.2043e3f866ea4p-4, 0x1.63e50c94ce606p-3, + 0x1.d9f51019a9b54p-5, -0x1.f948756f0e344p-6, 0x1.cc9d8619dc8a0p-3, -0x1.02c0d45da765bp-6, + -0x1.ae2436187ff3cp-5, 0x1.bd77b6a0a9320p-4, 0x1.821ad88a9db64p-5, 0x1.b7b9ebdc759c3p-6, + -0x1.320af48a9abbbp-5, -0x1.47559fb08832dp-4, -0x1.de6a89be8f40bp-5, 0x1.9fd4109fa34d0p-9, + -0x1.2f1a208b88accp-3, -0x1.4946e5123a31dp-8, 0x1.260f02910986bp-5, 0x1.fabb016e64ff5p-6, + 0x1.3e182ce577056p-10, 0x1.1bb3dbc6f1095p-5, -0x1.2ab0248ae890dp-4, 0x1.07938dc7a5af3p-3, + -0x1.b706ebda4505dp-4, 0x1.71f4b22598da5p-6, 0x1.c4af68a4534b3p-7, 0x1.c98c0a269d8f2p-7, + 0x1.5061d7c7ddd06p-5, 0x1.c91513cfa220dp-6, 0x1.6b60e128b30bcp-6, 0x1.014ea253fc620p-5, + -0x1.1f66a46e60dfap-8, 0x1.383208aff57b3p-3, 0x1.8afe34ae89b6ep-6, -0x1.bf2a6efd5fe49p-7, + 0x1.62ee2d4275068p-4, 0x1.a5e2621f822d5p-6, -0x1.7437e80dc20aep-5, 0x1.735ecb99e3a7fp-4, + 0x1.e3075b6d7cfefp-5, -0x1.1d8bcec6a562ep-3, -0x1.4a3bed14ada6cp-4, -0x1.d233c72f691ddp-5, + 0x1.0c3e503636ba7p-5, 0x1.1072045965e25p-6, 0x1.09bd8b53a142ep-4, 0x1.08cf5b5736315p-4, + -0x1.2aaff6dc20a39p-6, -0x1.baa74605a3672p-3, -0x1.77b7ca3cf1681p-5, 0x1.661a6134d0f00p-5, + -0x1.2a6eec8fab7d2p-3, -0x1.626c5247037c5p-5, 0x1.67df16937235cp-3, 0x1.82f1cf49ac4e6p-5, + -0x1.3f56c75c9b992p-4, -0x1.8a107144ab2fep-6, -0x1.34e01cf534140p-8, -0x1.54fb305f8f6acp-5, + -0x1.bc6bbe86d67cfp-11, -0x1.fd720e49a6ee3p-4, -0x1.a9f06afd94609p-6, 0x1.35743fa479e77p-5, + 0x1.16de369a824dcp-3, 0x1.e3beba2c4f336p-4, 0x1.cb1e7eac8e57ep-7, 0x1.14aa4232f2e63p-2, + 0x1.9172bb32f2c78p-5, -0x1.ef2baab2264f2p-4, -0x1.f894d4d516281p-4, -0x1.4dd36ae6b9f6dp-5, + 0x1.7a0fdb0dc5870p-4, 0x1.468cae412a94cp-6, 0x1.b2a048c06d821p-5, 0x1.3151905bfe574p-4, + -0x1.46575715e925cp-7, 0x1.a6e6edaac9866p-5, 0x1.c189699856ccep-7, -0x1.baea77b2d8f5fp-4, + -0x1.6d37f36b71116p-3, -0x1.4d6a8bb96fe20p-6, -0x1.b69d76a89cff0p-4, 0x1.f20fdd6ecf7cbp-7, + 0x1.322ffaab709e8p-3, 0x1.e1fcaadf030dap-4, 0x1.8520738be3eb1p-9, 0x1.ed206273852d3p-5, + -0x1.0d4bb4758e0eap-5, -0x1.4dca91e59d3c5p-5, -0x1.3ce8fa0b83b8ep-4, -0x1.64ed120e41ba7p-5, + -0x1.863fae6202a26p-4, -0x1.6042bf2a9aff2p-5, -0x1.c9e0e3804644bp-4, -0x1.c701775fd6accp-4, + -0x1.040f0ec94af55p-7, -0x1.8d26d6925a275p-4, -0x1.41be7d3bbb66dp-4, -0x1.36a5e7cecb07dp-5, + 0x1.ee43e481c6a0dp-5, 0x1.c58c9e64e6532p-6, 0x1.052633674f0a0p-5, -0x1.02641f25984d9p-6, + 0x1.02641f25984d9p-6, -0x1.052633674f0a0p-5, -0x1.c58c9e64e6532p-6, -0x1.ee43e481c6a0dp-5, + 0x1.36a5e7cecb07dp-5, 0x1.41be7d3bbb66dp-4, 0x1.8d26d6925a275p-4, 0x1.040f0ec94af55p-7, + 0x1.c701775fd6accp-4, 0x1.c9e0e3804644bp-4, 0x1.6042bf2a9aff2p-5, 0x1.863fae6202a26p-4, + 0x1.64ed120e41ba7p-5, 0x1.3ce8fa0b83b8ep-4, 0x1.4dca91e59d3c5p-5, 0x1.0d4bb4758e0eap-5, + -0x1.ed206273852d3p-5, -0x1.8520738be3eb1p-9, -0x1.e1fcaadf030dap-4, -0x1.322ffaab709e8p-3, + -0x1.f20fdd6ecf7cbp-7, 0x1.b69d76a89cff0p-4, 0x1.4d6a8bb96fe20p-6, 0x1.6d37f36b71116p-3, + 0x1.baea77b2d8f5fp-4, -0x1.c189699856ccep-7, -0x1.a6e6edaac9866p-5, 0x1.46575715e925cp-7, + -0x1.3151905bfe574p-4, -0x1.b2a048c06d821p-5, -0x1.468cae412a94cp-6, -0x1.7a0fdb0dc5870p-4, + 0x1.4dd36ae6b9f6dp-5, 0x1.f894d4d516281p-4, 0x1.ef2baab2264f2p-4, -0x1.9172bb32f2c78p-5, + -0x1.14aa4232f2e63p-2, -0x1.cb1e7eac8e57ep-7, -0x1.e3beba2c4f336p-4, -0x1.16de369a824dcp-3, + -0x1.35743fa479e77p-5, 0x1.a9f06afd94609p-6, 0x1.fd720e49a6ee3p-4, 0x1.bc6bbe86d67cfp-11, + 0x1.54fb305f8f6acp-5, 0x1.34e01cf534140p-8, 0x1.8a107144ab2fep-6, 0x1.3f56c75c9b992p-4, + -0x1.82f1cf49ac4e6p-5, -0x1.67df16937235cp-3, 0x1.626c5247037c5p-5, 0x1.2a6eec8fab7d2p-3, + -0x1.661a6134d0f00p-5, 0x1.77b7ca3cf1681p-5, 0x1.baa74605a3672p-3, 0x1.2aaff6dc20a39p-6, + -0x1.08cf5b5736315p-4, -0x1.09bd8b53a142ep-4, -0x1.1072045965e25p-6, -0x1.0c3e503636bb1p-5, + 0x1.d233c72f691e2p-5, 0x1.4a3bed14ada9bp-4, 0x1.1d8bcecc5008fp-3, -0x1.e3075c52c0a6ap-5, + 0x1.35410e0fd95fep-5, -0x1.e817bd2229b76p-4, -0x1.9777ed3f94535p-4, 0x1.36058d10d6231p-4, + 0x1.ffa730c6193ffp-4, -0x1.2d864099369c0p-8, -0x1.ad2bc99bd53c5p-4, -0x1.1734d62fa442dp-4, + 0x1.7c3a93b4b5a8fp-5, 0x1.db6523f277b12p-4, 0x1.d934fc972af43p-6, -0x1.f2253290079d3p-4, + -0x1.7f8ecd5b76218p-4, 0x1.5328274838c34p-4, 0x1.fce15fc99d3d9p-4, -0x1.c3785c2d88c47p-7, + -0x1.c08c420793edfp-4, -0x1.edc1955a7c7c3p-5, 0x1.c124a15b80e1ep-5, 0x1.cc1f0dc3f33b8p-4, + 0x1.45577148873e4p-6, -0x1.f97f93c9327f8p-4, -0x1.659192ae60532p-4, 0x1.6e7443b696837p-4, + 0x1.f759982a824e9p-4, -0x1.76dd9bb61fbe4p-6, -0x1.d17e780181019p-4, -0x1.aa6c81b9db22bp-5, + 0x1.01cfc86ddecffp-4, 0x1.ba5aa70e76133p-4, 0x1.5f6cf92e6f81ep-7, -0x1.fe1caffb29b1ap-4, + -0x1.49a44979aeda3p-4, 0x1.87c4010afb44ep-4, 0x1.ef178a081bcaep-4, -0x1.04fb82e3ac8e1p-5, + -0x1.dfeae5260c4ffp-4, -0x1.64c7e1e66cad2p-5, 0x1.21a797fe7d711p-4, 0x1.a63093bcc38ffp-4, + 0x1.921cbe6158133p-10, -0x1.fff620065526bp-4, -0x1.2bedb2f6fd100p-4, 0x1.9ef43fad37320p-4, + 0x1.e426a522e0b7ep-4, -0x1.4d1e1c324605ep-5, -0x1.ebbd8d76d9f72p-4, -0x1.1d344508afcffp-5, + 0x1.3fed952ca6190p-4, 0x1.8fbcc81e0e8dap-4, -0x1.f656f8f2d390ap-8, -0x1.ff0954ad74106p-4, + -0x1.0c9705e6899aep-4, 0x1.b3e4d50380c5cp-4, 0x1.d69616dd2e647p-4, -0x1.9372a8f84052ep-5, + -0x1.f4e5ffcb7945dp-4, -0x1.a829fb9df07afp-6, 0x1.5c77bef49a9a5p-4, 0x1.771e73a17746fp-4, + -0x1.139f1069ce221p-6, -0x1.fb5799279e67fp-4, -0x1.d79778e24e5d5p-5, 0x1.c678b401bacb2p-4, + 0x1.c678b401bacb2p-4, -0x1.d79778e24e5d5p-5, -0x1.fb5799279e67fp-4, -0x1.139f1069ce221p-6, + 0x1.771e73a17746fp-4, 0x1.5c77bef49a9a5p-4, -0x1.a829fb9df07afp-6, -0x1.f4e5ffcb7945dp-4, + -0x1.9372a8f84052ep-5, 0x1.d69616dd2e647p-4, 0x1.b3e4d50380c5cp-4, -0x1.0c9705e6899aep-4, + -0x1.ff0954ad74106p-4, -0x1.f656f8f2d390ap-8, 0x1.8fbcc81e0e8dap-4, 0x1.3fed952ca6190p-4, + -0x1.1d344508afcffp-5, -0x1.ebbd8d76d9f72p-4, -0x1.4d1e1c324605ep-5, 0x1.e426a522e0b7ep-4, + 0x1.9ef43fad37320p-4, -0x1.2bedb2f6fd100p-4, -0x1.fff620065526bp-4, 0x1.921cbe6158133p-10, + 0x1.a63093bcc38ffp-4, 0x1.21a797fe7d711p-4, -0x1.64c7e1e66cad2p-5, -0x1.dfeae5260c4ffp-4, + -0x1.04fb82e3ac8e1p-5, 0x1.ef178a081bcaep-4, 0x1.87c4010afb44ep-4, -0x1.49a44979aeda3p-4, + -0x1.fe1caffb29b1ap-4, 0x1.5f6cf92e6f81ep-7, 0x1.ba5aa70e76133p-4, 0x1.01cfc86ddecffp-4, + -0x1.aa6c81b9db22bp-5, -0x1.d17e780181019p-4, -0x1.76dd9bb61fbe4p-6, 0x1.f759982a824e9p-4, + 0x1.6e7443b696837p-4, -0x1.659192ae60532p-4, -0x1.f97f93c9327f8p-4, 0x1.45577148873e4p-6, + 0x1.cc1f0dc3f33b8p-4, 0x1.c124a15b80e1ep-5, -0x1.edc1955a7c7c3p-5, -0x1.c08c420793edfp-4, + -0x1.c3785c2d88c47p-7, 0x1.fce15fc99d3d9p-4, 0x1.5328274838c34p-4, -0x1.7f8ecd5b76218p-4, + -0x1.f2253290079d3p-4, 0x1.d934fc972af43p-6, 0x1.db6523f277b12p-4, 0x1.7c3a93b4b5a8fp-5, + -0x1.1734d62fa442dp-4, -0x1.ad2bc99bd53c5p-4, -0x1.2d864099369c0p-8, 0x1.ffa730c6193ffp-4, + 0x1.36058d10d6231p-4, -0x1.9777ed3f94535p-4, -0x1.e817bd2229b76p-4, 0x1.35410e0fd95e1p-5, + 0x1.e817bc5a562afp-4, 0x1.35410ea1ba420p-5, 0x1.36058bad30df7p-4, 0x1.9777ec3332185p-4, + 0x1.2d86426ea2b92p-8, 0x1.ffa72ff53d0c7p-4, -0x1.1734d64501c7fp-4, 0x1.ad2bcb3b017e0p-4, + -0x1.db6524402cf85p-4, 0x1.7c3a9216833f6p-5, -0x1.f22533349e47fp-4, -0x1.d934fdc3eabc0p-6, + -0x1.532826d7f3956p-4, -0x1.7f8ecd2970f1cp-4, -0x1.c3785bb229b2bp-7, -0x1.fce1606d27e7fp-4, + 0x1.edc194e8f3bfap-5, -0x1.c08c4351fa413p-4, 0x1.cc1f0d7660353p-4, -0x1.c124a09c21888p-5, + 0x1.f97f92c99f165p-4, 0x1.45576fe3b796dp-6, 0x1.6e7444a2b9df0p-4, 0x1.659192db005adp-4, + 0x1.76dd9d38832c7p-6, 0x1.f75998522df9bp-4, -0x1.aa6c8332ec5c0p-5, 0x1.d17e76d6347d3p-4, + -0x1.ba5aa74d275a8p-4, 0x1.01cfc902f8816p-4, -0x1.fe1caf8aa29f4p-4, -0x1.5f6cf9aff8a92p-7, + -0x1.87c400396e652p-4, -0x1.49a44b3ec4fa4p-4, -0x1.04fb81b6e0c59p-5, -0x1.ef178ba5d387fp-4, + 0x1.64c7e2dd14afep-5, -0x1.dfeae4e366606p-4, 0x1.a63092fc9f39cp-4, -0x1.21a799116b520p-4, + 0x1.fff621259d02ap-4, 0x1.921cbb273ab6cp-10, 0x1.9ef43ecd7f40dp-4, 0x1.2bedb2e006313p-4, + 0x1.4d1e1d38193e9p-5, 0x1.e426a40b976f7p-4, -0x1.1d34456f67c85p-5, 0x1.ebbd8c11decefp-4, + -0x1.8fbcc81ee0b57p-4, 0x1.3fed941b0f96bp-4, -0x1.ff0954ee87733p-4, 0x1.f656f7ce32094p-8, + -0x1.b3e4d40578a1fp-4, -0x1.0c9706d4b58b4p-4, -0x1.9372a849208cfp-5, -0x1.d696174fe347cp-4, + 0x1.a829fcf60031bp-6, -0x1.f4e600db00b22p-4, 0x1.771e741130db4p-4, -0x1.5c77bdcd20b9ep-4, + 0x1.fb5799b563c55p-4, -0x1.139f1103e4dddp-6, 0x1.c678b4295f00dp-4, 0x1.d7977956b0df2p-5, + 0x1.d7977956b0df2p-5, 0x1.c678b4295f00dp-4, -0x1.139f1103e4dddp-6, 0x1.fb5799b563c55p-4, + -0x1.5c77bdcd20b9ep-4, 0x1.771e741130db4p-4, -0x1.f4e600db00b22p-4, 0x1.a829fcf60031bp-6, + -0x1.d696174fe347cp-4, -0x1.9372a849208cfp-5, -0x1.0c9706d4b58b4p-4, -0x1.b3e4d40578a1fp-4, + 0x1.f656f7ce32094p-8, -0x1.ff0954ee87733p-4, 0x1.3fed941b0f96bp-4, -0x1.8fbcc81ee0b57p-4, + 0x1.ebbd8c11decefp-4, -0x1.1d34456f67c85p-5, 0x1.e426a40b976f7p-4, 0x1.4d1e1d38193e9p-5, + 0x1.2bedb2e006313p-4, 0x1.9ef43ecd7f40dp-4, 0x1.921cbb273ab6cp-10, 0x1.fff621259d02ap-4, + -0x1.21a799116b520p-4, 0x1.a63092fc9f39cp-4, -0x1.dfeae4e366606p-4, 0x1.64c7e2dd14afep-5, + -0x1.ef178ba5d387fp-4, -0x1.04fb81b6e0c59p-5, -0x1.49a44b3ec4fa4p-4, -0x1.87c400396e652p-4, + -0x1.5f6cf9aff8a92p-7, -0x1.fe1caf8aa29f4p-4, 0x1.01cfc902f8816p-4, -0x1.ba5aa74d275a8p-4, + 0x1.d17e76d6347d3p-4, -0x1.aa6c8332ec5c0p-5, 0x1.f75998522df9bp-4, 0x1.76dd9d38832c7p-6, + 0x1.659192db005adp-4, 0x1.6e7444a2b9df0p-4, 0x1.45576fe3b796dp-6, 0x1.f97f92c99f165p-4, + -0x1.c124a09c21888p-5, 0x1.cc1f0d7660353p-4, -0x1.c08c4351fa413p-4, 0x1.edc194e8f3bfap-5, + -0x1.fce1606d27e7fp-4, -0x1.c3785bb229b2bp-7, -0x1.7f8ecd2970f1cp-4, -0x1.532826d7f3956p-4, + -0x1.d934fdc3eabc0p-6, -0x1.f22533349e47fp-4, 0x1.7c3a9216833f6p-5, -0x1.db6524402cf85p-4, + 0x1.ad2bcb3b017e0p-4, -0x1.1734d64501c7fp-4, 0x1.ffa72ff53d0c7p-4, 0x1.2d86426ea2b92p-8, + 0x1.9777ec3332185p-4, 0x1.36058bad30df7p-4, 0x1.35410ea1ba44fp-5, 0x1.e817bc5a562b1p-4, + 0x1.9349a2f027470p-4, 0x1.dc5cb98384636p-5, 0x1.09c814f99bc0dp-4, -0x1.331d2944c9914p-5, + -0x1.2468b2be895f5p-7, 0x1.cf025e022f3bap-3, -0x1.036547870ea9fp-5, 0x1.9c15c530721efp-5, + 0x1.6cdf7ef37eaaap-7, -0x1.40efba6700544p-9, 0x1.4d8df6c37e36fp-4, -0x1.12e2ddb4c79b6p-9, + 0x1.a0995223d5cc3p-5, -0x1.6d998845c9074p-5, -0x1.24ec4050970d4p-7, 0x1.d43ee4df1fda1p-6, + -0x1.a76adc4222522p-5, 0x1.15111f0cc948fp-3, -0x1.2ce5739f90298p-4, 0x1.617b4b45f17adp-7, + 0x1.1075668666377p-4, -0x1.6e870e1ad54b4p-10, -0x1.b33d67be64da5p-5, 0x1.c3fc6a7b54eb9p-4, + 0x1.0380da831076bp-5, 0x1.9f69f55c852e0p-5, 0x1.9e09354059fb5p-4, 0x1.56e0fa812c7cdp-3, + -0x1.4bc8ff9f8174dp-5, -0x1.4848edaf10b0dp-4, 0x1.1fe39332debeap-2, 0x1.0940620bbd7e5p-5, + 0x1.380f07dfda70dp-4, 0x1.d101fecedba8fp-5, -0x1.bdbeb2b329b6ap-6, 0x1.8788df03301dep-5, + 0x1.94653286e401ap-5, 0x1.2eb8faffa0711p-4, -0x1.05755067bd153p-5, 0x1.344d1777a0b77p-3, + 0x1.b4a994833f2e1p-5, 0x1.dfbd49ea7b3e4p-8, 0x1.2d551f5e511ffp-6, -0x1.1a2c338cdbdbfp-3, + 0x1.27cf5b9b02bacp-5, 0x1.a9876e1ad4e45p-6, 0x1.1a8438f4a4f1fp-5, 0x1.7d354cb942a49p-5, + 0x1.7d3742685c3fcp-4, 0x1.f7b941d7054d7p-3, -0x1.cc72df3e3e75bp-4, -0x1.82346a36f8ed5p-8, + -0x1.75829f35a3c59p-5, 0x1.31c0e73fbe9b2p-5, 0x1.485beb7db5f5ap-7, -0x1.4a00053998997p-4, + -0x1.a39fd21c53afbp-5, 0x1.464162db255f7p-3, 0x1.8bd059e25415ap-3, 0x1.65a142af44adbp-5, + 0x1.0fdb5f07c53a1p-5, 0x1.1df85a5a1516ep-6, -0x1.ad28cf39e9d85p-5, -0x1.0223881dba7f6p-4, + -0x1.0223881dba7f6p-4, -0x1.ad28cf39e9d85p-5, 0x1.1df85a5a1516ep-6, 0x1.0fdb5f07c53a1p-5, + 0x1.65a142af44adbp-5, 0x1.8bd059e25415ap-3, 0x1.464162db255f7p-3, -0x1.a39fd21c53afbp-5, + -0x1.4a00053998997p-4, 0x1.485beb7db5f5ap-7, 0x1.31c0e73fbe9b2p-5, -0x1.75829f35a3c59p-5, + -0x1.82346a36f8ed5p-8, -0x1.cc72df3e3e75bp-4, 0x1.f7b941d7054d7p-3, 0x1.7d3742685c3fcp-4, + 0x1.7d354cb942a49p-5, 0x1.1a8438f4a4f1fp-5, 0x1.a9876e1ad4e45p-6, 0x1.27cf5b9b02bacp-5, + -0x1.1a2c338cdbdbfp-3, 0x1.2d551f5e511ffp-6, 0x1.dfbd49ea7b3e4p-8, 0x1.b4a994833f2e1p-5, + 0x1.344d1777a0b77p-3, -0x1.05755067bd153p-5, 0x1.2eb8faffa0711p-4, 0x1.94653286e401ap-5, + 0x1.8788df03301dep-5, -0x1.bdbeb2b329b6ap-6, 0x1.d101fecedba8fp-5, 0x1.380f07dfda70dp-4, + 0x1.0940620bbd7e5p-5, 0x1.1fe39332debeap-2, -0x1.4848edaf10b0dp-4, -0x1.4bc8ff9f8174dp-5, + 0x1.56e0fa812c7cdp-3, 0x1.9e09354059fb5p-4, 0x1.9f69f55c852e0p-5, 0x1.0380da831076bp-5, + 0x1.c3fc6a7b54eb9p-4, -0x1.b33d67be64da5p-5, -0x1.6e870e1ad54b4p-10, 0x1.1075668666377p-4, + 0x1.617b4b45f17adp-7, -0x1.2ce5739f90298p-4, 0x1.15111f0cc948fp-3, -0x1.a76adc4222522p-5, + 0x1.d43ee4df1fda1p-6, -0x1.24ec4050970d4p-7, -0x1.6d998845c9074p-5, 0x1.a0995223d5cc3p-5, + -0x1.12e2ddb4c79b6p-9, 0x1.4d8df6c37e36fp-4, -0x1.40efba6700544p-9, 0x1.6cdf7ef37eaaap-7, + 0x1.9c15c530721eep-5, -0x1.036547870eaa0p-5, 0x1.cf025e022f3bbp-3, -0x1.2468b2be8960cp-7, + -0x1.331d2944c9915p-5, 0x1.09c814f99bc0ap-4, 0x1.dc5cbc0f7e17cp-5, 0x1.9349a319734dfp-4, + -0x1.38b6bda7389bfp-7, 0x1.9a4546142662bp-5, -0x1.194af21562fffp-4, -0x1.95e5e4d149359p-7, + -0x1.1be40488ea24cp-4, 0x1.7649a83185520p-6, 0x1.2285fb7d437e3p-3, 0x1.dbaf8711807bdp-6, + 0x1.411878add2d25p-4, -0x1.63eee2bd6aabap-3, -0x1.781a3e2df5355p-6, -0x1.d525b57dcc289p-4, + -0x1.569020fa8c09ep-4, 0x1.acdb812db6bfbp-8, -0x1.2d40de3d0313bp-2, -0x1.4c8bed7c6bd8dp-11, + -0x1.099af85e20911p-8, 0x1.0a87594a4ca90p-5, 0x1.0f1a840522a33p-5, 0x1.392df078fee88p-4, + 0x1.9b17baa05bf5bp-6, 0x1.a1b9bcefa1313p-5, -0x1.f019a9b1c4619p-5, -0x1.316bbc75d8729p-3, + -0x1.6ddd9e01a095ap-5, 0x1.7ccf40671d310p-5, -0x1.bbdaa11318265p-3, 0x1.98064e8280375p-6, + -0x1.cefa8e19783c2p-5, 0x1.a0a86a4f14792p-4, 0x1.0a5d77d58870ep-7, -0x1.21a9b64adbb75p-3, + 0x1.afa3772a8e55dp-3, 0x1.71f508249b533p-4, -0x1.0eb7cac7da273p-4, -0x1.15c1658b20e79p-4, + -0x1.9e888db38ed91p-3, 0x1.cb8d183f68315p-5, 0x1.1ac53ecde1c9dp-5, 0x1.497f17362cbabp-4, + 0x1.6d3bc70ee4491p-7, -0x1.a3c96170a5e68p-5, 0x1.5f0f74084d5f4p-5, 0x1.42da61f9f6139p-5, + 0x1.ab27e8887493cp-4, 0x1.afce2544fed4dp-6, -0x1.069d351752961p-3, -0x1.0302aa2319517p-4, + -0x1.41a16e93a8225p-7, -0x1.9e2a844c0f632p-7, -0x1.315d287d592a6p-7, 0x1.fbce3b21d4b63p-5, + -0x1.be8b7521cfdf3p-7, -0x1.e046eae26d4dbp-6, -0x1.3ef1b819a6a25p-6, -0x1.4d99ddac73349p-9, + 0x1.be2ba881051d6p-6, 0x1.1ef085187770ep-4, 0x1.6c0b53b67e932p-4, -0x1.11dbf89cddce0p-3, + 0x1.3fefa25233532p-7, 0x1.a68304465216dp-4, -0x1.1734f3b346d75p-13, 0x1.e82f1275bce67p-6, + 0x1.e82f1275bce67p-6, -0x1.1734f3b346d75p-13, 0x1.a68304465216dp-4, 0x1.3fefa25233532p-7, + -0x1.11dbf89cddce0p-3, 0x1.6c0b53b67e932p-4, 0x1.1ef085187770ep-4, 0x1.be2ba881051d6p-6, + -0x1.4d99ddac73349p-9, -0x1.3ef1b819a6a25p-6, -0x1.e046eae26d4dbp-6, -0x1.be8b7521cfdf3p-7, + 0x1.fbce3b21d4b63p-5, -0x1.315d287d592a6p-7, -0x1.9e2a844c0f632p-7, -0x1.41a16e93a8225p-7, + -0x1.0302aa2319517p-4, -0x1.069d351752961p-3, 0x1.afce2544fed4dp-6, 0x1.ab27e8887493cp-4, + 0x1.42da61f9f6139p-5, 0x1.5f0f74084d5f4p-5, -0x1.a3c96170a5e68p-5, 0x1.6d3bc70ee4491p-7, + 0x1.497f17362cbabp-4, 0x1.1ac53ecde1c9dp-5, 0x1.cb8d183f68315p-5, -0x1.9e888db38ed91p-3, + -0x1.15c1658b20e79p-4, -0x1.0eb7cac7da273p-4, 0x1.71f508249b533p-4, 0x1.afa3772a8e55dp-3, + -0x1.21a9b64adbb75p-3, 0x1.0a5d77d58870ep-7, 0x1.a0a86a4f14792p-4, -0x1.cefa8e19783c2p-5, + 0x1.98064e8280375p-6, -0x1.bbdaa11318265p-3, 0x1.7ccf40671d310p-5, -0x1.6ddd9e01a095ap-5, + -0x1.316bbc75d8729p-3, -0x1.f019a9b1c4619p-5, 0x1.a1b9bcefa1313p-5, 0x1.9b17baa05bf5bp-6, + 0x1.392df078fee88p-4, 0x1.0f1a840522a33p-5, 0x1.0a87594a4ca90p-5, -0x1.099af85e20911p-8, + -0x1.4c8bed7c6bd8dp-11, -0x1.2d40de3d0313bp-2, 0x1.acdb812db6bfbp-8, -0x1.569020fa8c09ep-4, + -0x1.d525b57dcc289p-4, -0x1.781a3e2df5355p-6, -0x1.63eee2bd6aabap-3, 0x1.411878add2d25p-4, + 0x1.dbaf8711807bdp-6, 0x1.2285fb7d437e3p-3, 0x1.7649a83185521p-6, -0x1.1be40488ea24dp-4, + -0x1.95e5e4d149347p-7, -0x1.194af21562ff7p-4, 0x1.9a45461cdab35p-5, -0x1.38b6b781b2917p-7, + 0x1.1d34449e56a5bp-5, -0x1.ebbd8b2924455p-4, -0x1.7f8ecbf0831aep-4, 0x1.532827db73497p-4, + 0x1.f97f92939eaf8p-4, -0x1.45576c88cd6b0p-6, -0x1.d69616f8c24d6p-4, -0x1.9372a8ddf8b44p-5, + 0x1.21a79a67c380ep-4, 0x1.a630924504bfcp-4, -0x1.2d8648cef00c2p-8, -0x1.ffa7301f34f9ap-4, + -0x1.01cfc7c12500cp-4, 0x1.ba5aa7492c5a8p-4, 0x1.c678b3ddbfaa5p-4, -0x1.d7977750ca724p-5, + -0x1.fe1cb120a2dc3p-4, -0x1.5f6cfb5be78afp-7, 0x1.9777edf17c505p-4, 0x1.36058d0256c57p-4, + -0x1.64c7dc2a223c8p-5, -0x1.dfeae70c3720fp-4, -0x1.a82a0433139bep-6, 0x1.f4e60418060d8p-4, + 0x1.65918f4050d56p-4, -0x1.6e7445ea26cdfp-4, -0x1.f2252eee36b44p-4, 0x1.d934fd0718e5bp-6, + 0x1.e426a5496b727p-4, 0x1.4d1e21db09b44p-5, -0x1.3fed9469767e9p-4, -0x1.8fbccb325f5e2p-4, + 0x1.c3785ee3d0934p-7, 0x1.fce161fa03c27p-4, 0x1.c124a3261756bp-5, -0x1.cc1f0c1a6d690p-4, + -0x1.b3e4d44282d92p-4, 0x1.0c9703db7444fp-4, 0x1.fff621645fbc5p-4, 0x1.921d3c0567c7fp-10, + -0x1.ad2bcb0b73d63p-4, -0x1.1734d428f5f8ap-4, 0x1.aa6c7e4a3140ap-5, 0x1.d17e7546a801ep-4, + 0x1.139f0bb97dad9p-6, -0x1.fb5797776c6aep-4, -0x1.49a44b7b9faecp-4, 0x1.87c400b5cf042p-4, + 0x1.e817b937d11b4p-4, -0x1.35410cc750643p-5, -0x1.ef178866d7814p-4, -0x1.04fb805be0139p-5, + 0x1.5c77bde6b482ap-4, 0x1.771e76ce6db22p-4, -0x1.76dd9cf290823p-6, -0x1.f7599b852640ap-4, + -0x1.7c3a8d26fe2acp-5, 0x1.db6526ddeb523p-4, 0x1.9ef43e5aa5b64p-4, -0x1.2bedb1d4a32c8p-4, + -0x1.ff0957393440cp-4, 0x1.f656dfec51151p-8, 0x1.c08c42e8eebfcp-4, 0x1.edc197ba94b73p-5, + -0x1.edc197ba94b73p-5, -0x1.c08c42e8eebfcp-4, -0x1.f656dfec51151p-8, 0x1.ff0957393440cp-4, + 0x1.2bedb1d4a32c8p-4, -0x1.9ef43e5aa5b64p-4, -0x1.db6526ddeb523p-4, 0x1.7c3a8d26fe2acp-5, + 0x1.f7599b852640ap-4, 0x1.76dd9cf290823p-6, -0x1.771e76ce6db22p-4, -0x1.5c77bde6b482ap-4, + 0x1.04fb805be0139p-5, 0x1.ef178866d7814p-4, 0x1.35410cc750643p-5, -0x1.e817b937d11b4p-4, + -0x1.87c400b5cf042p-4, 0x1.49a44b7b9faecp-4, 0x1.fb5797776c6aep-4, -0x1.139f0bb97dad9p-6, + -0x1.d17e7546a801ep-4, -0x1.aa6c7e4a3140ap-5, 0x1.1734d428f5f8ap-4, 0x1.ad2bcb0b73d63p-4, + -0x1.921d3c0567c7fp-10, -0x1.fff621645fbc5p-4, -0x1.0c9703db7444fp-4, 0x1.b3e4d44282d92p-4, + 0x1.cc1f0c1a6d690p-4, -0x1.c124a3261756bp-5, -0x1.fce161fa03c27p-4, -0x1.c3785ee3d0934p-7, + 0x1.8fbccb325f5e2p-4, 0x1.3fed9469767e9p-4, -0x1.4d1e21db09b44p-5, -0x1.e426a5496b727p-4, + -0x1.d934fd0718e5bp-6, 0x1.f2252eee36b44p-4, 0x1.6e7445ea26cdfp-4, -0x1.65918f4050d56p-4, + -0x1.f4e60418060d8p-4, 0x1.a82a0433139bep-6, 0x1.dfeae70c3720fp-4, 0x1.64c7dc2a223c8p-5, + -0x1.36058d0256c57p-4, -0x1.9777edf17c505p-4, 0x1.5f6cfb5be78afp-7, 0x1.fe1cb120a2dc3p-4, + 0x1.d7977750ca724p-5, -0x1.c678b3ddbfaa5p-4, -0x1.ba5aa7492c5a8p-4, 0x1.01cfc7c12500cp-4, + 0x1.ffa7301f34f9ap-4, 0x1.2d8648cef00c2p-8, -0x1.a630924504bfcp-4, -0x1.21a79a67c380ep-4, + 0x1.9372a8ddf8b44p-5, 0x1.d69616f8c24d6p-4, 0x1.45576c88cd6b0p-6, -0x1.f97f92939eaf8p-4, + -0x1.532827db73497p-4, 0x1.7f8ecbf0831aep-4, 0x1.ebbd8b2924455p-4, -0x1.1d34449e56a5dp-5, + 0x1.ebbd8b4f41a6dp-4, 0x1.1d344430a8b89p-5, 0x1.532827bc87619p-4, 0x1.7f8ecc40e7adep-4, + 0x1.45576b84c7da1p-6, 0x1.f97f92660daf1p-4, -0x1.9372a8c054ffdp-5, 0x1.d69617a547288p-4, + -0x1.a63091c87fe1dp-4, 0x1.21a799912023dp-4, -0x1.ffa72f3ee1838p-4, 0x1.2d86496e5b381p-8, + -0x1.ba5aa63e82a06p-4, -0x1.01cfc7e2402d0p-4, -0x1.d79775525840dp-5, -0x1.c678b4c8c505fp-4, + 0x1.5f6cfd2927bfep-7, -0x1.fe1cb0c94d9c6p-4, 0x1.36058c0348e34p-4, -0x1.9777ee91382acp-4, + 0x1.dfeae6c39324bp-4, -0x1.64c7dca88749ap-5, 0x1.f4e603673eea4p-4, 0x1.a82a02bd5044fp-6, + 0x1.6e74457052049p-4, 0x1.6591906fa1455p-4, 0x1.d934fd1d25bcdp-6, 0x1.f2252df858822p-4, + -0x1.4d1e219af29adp-5, 0x1.e426a6b8c33a5p-4, -0x1.8fbccc69501d8p-4, 0x1.3fed94b202648p-4, + -0x1.fce161d9bb59ep-4, 0x1.c3785fc9a71a7p-7, -0x1.cc1f0c0bd0d1fp-4, -0x1.c124a1939f4ebp-5, + -0x1.0c9703a4a3346p-4, -0x1.b3e4d40da70b2p-4, 0x1.921d3936b63acp-10, -0x1.fff621fb1fd0cp-4, + 0x1.1734d378c4b31p-4, -0x1.ad2bca4c1b008p-4, 0x1.d17e7608984a1p-4, -0x1.aa6c7e07ab0d1p-5, + 0x1.fb579881789d1p-4, 0x1.139f0c65056dep-6, 0x1.87c40088011a5p-4, 0x1.49a44c406f059p-4, + 0x1.35410b29ecddfp-5, 0x1.e817b96b0ce1ap-4, -0x1.04fb7fa34965ep-5, 0x1.ef1787becfa6ep-4, + -0x1.771e7682600d4p-4, 0x1.5c77be36294f7p-4, -0x1.f7599c948d83dp-4, 0x1.76dd9c1c43ad9p-6, + -0x1.db65269cbcb71p-4, -0x1.7c3a8b97ef573p-5, -0x1.2bedb2126d31bp-4, -0x1.9ef43eabee82bp-4, + -0x1.f656dd95b5249p-8, -0x1.ff09581180077p-4, 0x1.edc197fbfc21bp-5, -0x1.c08c41effb4ffp-4, + 0x1.c08c41effb4ffp-4, -0x1.edc197fbfc21bp-5, 0x1.ff09581180077p-4, 0x1.f656dd95b5249p-8, + 0x1.9ef43eabee82bp-4, 0x1.2bedb2126d31bp-4, 0x1.7c3a8b97ef573p-5, 0x1.db65269cbcb71p-4, + -0x1.76dd9c1c43ad9p-6, 0x1.f7599c948d83dp-4, -0x1.5c77be36294f7p-4, 0x1.771e7682600d4p-4, + -0x1.ef1787becfa6ep-4, 0x1.04fb7fa34965ep-5, -0x1.e817b96b0ce1ap-4, -0x1.35410b29ecddfp-5, + -0x1.49a44c406f059p-4, -0x1.87c40088011a5p-4, -0x1.139f0c65056dep-6, -0x1.fb579881789d1p-4, + 0x1.aa6c7e07ab0d1p-5, -0x1.d17e7608984a1p-4, 0x1.ad2bca4c1b008p-4, -0x1.1734d378c4b31p-4, + 0x1.fff621fb1fd0cp-4, -0x1.921d3936b63acp-10, 0x1.b3e4d40da70b2p-4, 0x1.0c9703a4a3346p-4, + 0x1.c124a1939f4ebp-5, 0x1.cc1f0c0bd0d1fp-4, -0x1.c3785fc9a71a7p-7, 0x1.fce161d9bb59ep-4, + -0x1.3fed94b202648p-4, 0x1.8fbccc69501d8p-4, -0x1.e426a6b8c33a5p-4, 0x1.4d1e219af29adp-5, + -0x1.f2252df858822p-4, -0x1.d934fd1d25bcdp-6, -0x1.6591906fa1455p-4, -0x1.6e74457052049p-4, + -0x1.a82a02bd5044fp-6, -0x1.f4e603673eea4p-4, 0x1.64c7dca88749ap-5, -0x1.dfeae6c39324bp-4, + 0x1.9777ee91382acp-4, -0x1.36058c0348e34p-4, 0x1.fe1cb0c94d9c6p-4, -0x1.5f6cfd2927bfep-7, + 0x1.c678b4c8c505fp-4, 0x1.d79775525840dp-5, 0x1.01cfc7e2402d0p-4, 0x1.ba5aa63e82a06p-4, + -0x1.2d86496e5b381p-8, 0x1.ffa72f3ee1838p-4, -0x1.21a799912023dp-4, 0x1.a63091c87fe1dp-4, + -0x1.d69617a547288p-4, 0x1.9372a8c054ffdp-5, -0x1.f97f92660daf1p-4, -0x1.45576b84c7da1p-6, + -0x1.7f8ecc40e7adep-4, -0x1.532827bc87619p-4, -0x1.1d344430a8b7fp-5, -0x1.ebbd8b4f41a6ap-4, + 0x1.1f894e2585242p-3, 0x1.757740848cebdp-5, 0x1.67bddf249ee52p-4, -0x1.3daf722fb60edp-5, + -0x1.971904bd892fep-6, 0x1.bbd7fe5184954p-4, -0x1.acca9493e05b4p-8, 0x1.fbdf2d11fc3f7p-6, + -0x1.17dbb5f7e3c86p-3, 0x1.85678a067658ep-4, -0x1.d5081d437129ap-7, 0x1.2531c700191f6p-10, + -0x1.6d5edc94fb963p-4, 0x1.5ba2f6b6b53a8p-6, -0x1.1b00ca210b2d2p-6, 0x1.49b54c0ee6e59p-5, + -0x1.661f982acb07bp-7, 0x1.fe9749b86d4f9p-4, 0x1.da9b7451ba95dp-4, 0x1.c52368acfb956p-4, + -0x1.a5f84780d406bp-3, 0x1.35ad4708153b8p-10, 0x1.6db3312ddb5dep-5, 0x1.a16a65ded33acp-9, + 0x1.902b68e67c2a3p-3, -0x1.26c8864a86d55p-8, -0x1.e8ba678720d0cp-7, 0x1.fd300756f93b8p-8, + 0x1.d27df445ea833p-7, -0x1.f2d2f4480012fp-5, 0x1.eecab88d59878p-7, -0x1.3b1a46dcdddb9p-3, + -0x1.84c2de34325c5p-4, 0x1.ebbeae330e979p-8, 0x1.e9e1e04de3afdp-4, -0x1.89b81952d4168p-5, + 0x1.dadbc77f22ddep-8, -0x1.8ffbf8fba19c3p-4, 0x1.25d04ef8445e9p-8, -0x1.20024eec6b262p-3, + 0x1.ae5542eeb3580p-4, 0x1.91dfd54af883ap-7, -0x1.5493dd748e8a1p-4, -0x1.25489ab3ed0f8p-4, + -0x1.0996ca5e603bep-4, 0x1.0cee260a0ca1ap-6, 0x1.5fae3a2c17e11p-5, 0x1.3b857ebc8622cp-4, + 0x1.c3faf0c20b133p-4, 0x1.e330f9e9140d0p-4, 0x1.b3974c3f26703p-9, 0x1.41e34b9c815c0p-5, + 0x1.07f3a2531b36cp-3, -0x1.bedec8039f852p-5, 0x1.b1c48ebab4519p-3, 0x1.1e06d6e6496c8p-5, + 0x1.46431bd4d5c17p-3, -0x1.35ef9c594de75p-6, -0x1.1ed7208b53dcap-6, 0x1.44e9ceeb45479p-3, + -0x1.eb6bd826711dap-7, 0x1.0402d41a1dbd8p-3, -0x1.56905ce6c0b1bp-5, -0x1.c385c6c09f2eap-4, + 0x1.c385c6c09f2eap-4, 0x1.56905ce6c0b1bp-5, -0x1.0402d41a1dbd8p-3, 0x1.eb6bd826711dap-7, + -0x1.44e9ceeb45479p-3, 0x1.1ed7208b53dcap-6, 0x1.35ef9c594de75p-6, -0x1.46431bd4d5c17p-3, + -0x1.1e06d6e6496c8p-5, -0x1.b1c48ebab4519p-3, 0x1.bedec8039f852p-5, -0x1.07f3a2531b36cp-3, + -0x1.41e34b9c815c0p-5, -0x1.b3974c3f26703p-9, -0x1.e330f9e9140d0p-4, -0x1.c3faf0c20b133p-4, + -0x1.3b857ebc8622cp-4, -0x1.5fae3a2c17e11p-5, -0x1.0cee260a0ca1ap-6, 0x1.0996ca5e603bep-4, + 0x1.25489ab3ed0f8p-4, 0x1.5493dd748e8a1p-4, -0x1.91dfd54af883ap-7, -0x1.ae5542eeb3580p-4, + 0x1.20024eec6b262p-3, -0x1.25d04ef8445e9p-8, 0x1.8ffbf8fba19c3p-4, -0x1.dadbc77f22ddep-8, + 0x1.89b81952d4168p-5, -0x1.e9e1e04de3afdp-4, -0x1.ebbeae330e979p-8, 0x1.84c2de34325c5p-4, + 0x1.3b1a46dcdddb9p-3, -0x1.eecab88d59878p-7, 0x1.f2d2f4480012fp-5, -0x1.d27df445ea833p-7, + -0x1.fd300756f93b8p-8, 0x1.e8ba678720d0cp-7, 0x1.26c8864a86d55p-8, -0x1.902b68e67c2a3p-3, + -0x1.a16a65ded33acp-9, -0x1.6db3312ddb5dep-5, -0x1.35ad4708153b8p-10, 0x1.a5f84780d406bp-3, + -0x1.c52368acfb956p-4, -0x1.da9b7451ba95dp-4, -0x1.fe9749b86d4f9p-4, 0x1.661f982acb07bp-7, + -0x1.49b54c0ee6e59p-5, 0x1.1b00ca210b2d2p-6, -0x1.5ba2f6b6b53a8p-6, 0x1.6d5edc94fb963p-4, + -0x1.2531c700191f6p-10, 0x1.d5081d437129ap-7, -0x1.85678a067658ep-4, 0x1.17dbb5f7e3c86p-3, + -0x1.fbdf2d11fc3f7p-6, 0x1.acca9493e05b2p-8, -0x1.bbd7fe518495ap-4, 0x1.971904bd89308p-6, + 0x1.3daf722fb60f5p-5, -0x1.67bddf249ee4ap-4, -0x1.75774143a62f8p-5, -0x1.1f894e218f29ep-3, + 0x1.4297d149eedafp-4, 0x1.8565e40563803p-4, -0x1.0c89eea979296p-6, 0x1.a76da2bd9a626p-6, + 0x1.d1192a9e18561p-3, 0x1.9ae4707a40fffp-6, 0x1.760b9f571a127p-6, -0x1.81ebf31f96778p-5, + 0x1.67b27a65b2c5ep-4, -0x1.be4b2f292722dp-4, -0x1.5b16be0bb54b4p-6, 0x1.5f5b46265ee1bp-4, + -0x1.a11de5df895bap-5, 0x1.e643f13df39eap-5, 0x1.f9a8ee4637f2ep-5, 0x1.fd0d35539d6b3p-7, + 0x1.beed37f44d197p-6, 0x1.20d32f019dd21p-5, -0x1.e3d8179fb2f2ap-6, 0x1.7c00a02a7739cp-3, + -0x1.6d4aef77d15e2p-4, -0x1.e8b9832931897p-5, -0x1.189712904a9b6p-5, 0x1.eb8e81726dda2p-7, + -0x1.8c97529f1db0fp-5, 0x1.05f2cc4e1acffp-5, -0x1.423815e6a9b7fp-4, 0x1.41cb4e5e7b073p-5, + -0x1.afdfd53cbf016p-3, -0x1.067d8d637404ep-5, -0x1.539b7c8ae1fc2p-9, 0x1.9b349dc93d5eep-3, + -0x1.c35c878d084ffp-5, 0x1.42dc046c8039dp-4, 0x1.c3e1e673d4d42p-4, -0x1.609058712d683p-4, + 0x1.671e0113d67fdp-3, -0x1.c73e6068f73c4p-6, -0x1.7dcbc7aa2f1fcp-4, -0x1.9820a250373cfp-5, + -0x1.b84370a0675c8p-3, 0x1.7ceca3d848aa8p-5, 0x1.c79d919dab2dfp-7, 0x1.e901a849305d6p-6, + 0x1.d0d5d01b4920fp-12, 0x1.9d8af52da30cfp-5, 0x1.a5653997bcdabp-4, 0x1.f0e83f843e87dp-5, + -0x1.503e80c1212a8p-6, -0x1.195d839321c66p-8, -0x1.faba8c48f085bp-4, -0x1.3f805daf4c59cp-11, + -0x1.90f6793421ab3p-4, 0x1.fac8046796ba4p-6, 0x1.c9f5d8df61b25p-6, 0x1.3c9c743959a42p-3, + -0x1.19a36b1cdc46bp-4, 0x1.3493ae1ffad2fp-3, -0x1.ef24c3f6b88e4p-8, 0x1.5160c6970801cp-6, + 0x1.fe488a153251ap-4, 0x1.8478e00b0d4d2p-6, 0x1.e0b2ae42b2439p-5, -0x1.6eb75752a139ep-4, + 0x1.6eb75752a139ep-4, -0x1.e0b2ae42b2439p-5, -0x1.8478e00b0d4d2p-6, -0x1.fe488a153251ap-4, + -0x1.5160c6970801cp-6, 0x1.ef24c3f6b88e4p-8, -0x1.3493ae1ffad2fp-3, 0x1.19a36b1cdc46bp-4, + -0x1.3c9c743959a42p-3, -0x1.c9f5d8df61b25p-6, -0x1.fac8046796ba4p-6, 0x1.90f6793421ab3p-4, + 0x1.3f805daf4c59cp-11, 0x1.faba8c48f085bp-4, 0x1.195d839321c66p-8, 0x1.503e80c1212a8p-6, + -0x1.f0e83f843e87dp-5, -0x1.a5653997bcdabp-4, -0x1.9d8af52da30cfp-5, -0x1.d0d5d01b4920fp-12, + -0x1.e901a849305d6p-6, -0x1.c79d919dab2dfp-7, -0x1.7ceca3d848aa8p-5, 0x1.b84370a0675c8p-3, + 0x1.9820a250373cfp-5, 0x1.7dcbc7aa2f1fcp-4, 0x1.c73e6068f73c4p-6, -0x1.671e0113d67fdp-3, + 0x1.609058712d683p-4, -0x1.c3e1e673d4d42p-4, -0x1.42dc046c8039dp-4, 0x1.c35c878d084ffp-5, + -0x1.9b349dc93d5eep-3, 0x1.539b7c8ae1fc2p-9, 0x1.067d8d637404ep-5, 0x1.afdfd53cbf016p-3, + -0x1.41cb4e5e7b073p-5, 0x1.423815e6a9b7fp-4, -0x1.05f2cc4e1acffp-5, 0x1.8c97529f1db0fp-5, + -0x1.eb8e81726dda2p-7, 0x1.189712904a9b6p-5, 0x1.e8b9832931897p-5, 0x1.6d4aef77d15e2p-4, + -0x1.7c00a02a7739cp-3, 0x1.e3d8179fb2f2ap-6, -0x1.20d32f019dd21p-5, -0x1.beed37f44d197p-6, + -0x1.fd0d35539d6b3p-7, -0x1.f9a8ee4637f2ep-5, -0x1.e643f13df39eap-5, 0x1.a11de5df895bap-5, + -0x1.5f5b46265ee1bp-4, 0x1.5b16be0bb54b4p-6, 0x1.be4b2f292722dp-4, -0x1.67b27a65b2c5ep-4, + 0x1.81ebf31f96778p-5, -0x1.760b9f571a125p-6, -0x1.9ae4707a41006p-6, -0x1.d1192a9e18565p-3, + -0x1.a76da2bd9a620p-6, 0x1.0c89eea9792c3p-6, -0x1.8565e41de060cp-4, -0x1.4297d180b2fe4p-4, + 0x1.04fb803e1e63cp-5, -0x1.ef178acc6ac0ep-4, -0x1.65919232926d2p-4, 0x1.6e7445eff9f16p-4, + 0x1.ebbd8bbf0a51ap-4, -0x1.1d34402d0fab3p-5, -0x1.f22530e9cc991p-4, -0x1.d934fb773f599p-6, + 0x1.771e788f07b48p-4, 0x1.5c77bb092e4b7p-4, -0x1.35410be3c9736p-5, -0x1.e817bc6bb73b7p-4, + -0x1.a82a0087cf8d8p-6, 0x1.f4e603ffdbb2bp-4, 0x1.53282cc7cbcc4p-4, -0x1.7f8ecc1a7087cp-4, + -0x1.e426a54a85e4dp-4, 0x1.4d1e2082a07f5p-5, 0x1.f7599a7c8e057p-4, 0x1.76dd99566c183p-6, + -0x1.87c3ff9fe07ebp-4, -0x1.49a449efe527cp-4, 0x1.64c7e0d12e5ecp-5, 0x1.dfeae49fc3b08p-4, + 0x1.45576d1b69918p-6, -0x1.f97f8fe26fdabp-4, -0x1.3fed94632d0f4p-4, 0x1.8fbccab52d47cp-4, + 0x1.db6526d806b68p-4, -0x1.7c3a95eca6680p-5, -0x1.fb57975f5fea2p-4, -0x1.139f0a404fe61p-6, + 0x1.9777f13749fcbp-4, 0x1.36058b646aa33p-4, -0x1.9372a4ea634c5p-5, -0x1.d6961888a142dp-4, + -0x1.c37870a7c6ea5p-7, 0x1.fce15fa212d61p-4, 0x1.2bedb20e0176ep-4, -0x1.9ef43df55e8e1p-4, + -0x1.d17e7952cfb2bp-4, 0x1.aa6c848350222p-5, 0x1.fe1cacaa10eb9p-4, 0x1.5f6d0923ca496p-7, + -0x1.a6308f18ee9b9p-4, -0x1.21a79bf4d1745p-4, 0x1.c1249c3944fe2p-5, 0x1.cc1f0dbf7cca0p-4, + 0x1.f656e8a05a762p-8, -0x1.ff09535ad2c12p-4, -0x1.1734d5d06332fp-4, 0x1.ad2bc76104d40p-4, + 0x1.c678b49383375p-4, -0x1.d79775d4ef8dcp-5, -0x1.ffa72fce4827bp-4, -0x1.2d86301c0db23p-8, + 0x1.b3e4d35087e22p-4, 0x1.0c970197e5138p-4, -0x1.edc1980d49929p-5, -0x1.c08c43225daa8p-4, + -0x1.921d1efad9896p-10, 0x1.fff6252bbc877p-4, 0x1.01cfc8bb32330p-4, -0x1.ba5aa68d9920fp-4, + -0x1.ba5aa68d9920fp-4, 0x1.01cfc8bb32330p-4, 0x1.fff6252bbc877p-4, -0x1.921d1efad9896p-10, + -0x1.c08c43225daa8p-4, -0x1.edc1980d49929p-5, 0x1.0c970197e5138p-4, 0x1.b3e4d35087e22p-4, + -0x1.2d86301c0db23p-8, -0x1.ffa72fce4827bp-4, -0x1.d79775d4ef8dcp-5, 0x1.c678b49383375p-4, + 0x1.ad2bc76104d40p-4, -0x1.1734d5d06332fp-4, -0x1.ff09535ad2c12p-4, 0x1.f656e8a05a762p-8, + 0x1.cc1f0dbf7cca0p-4, 0x1.c1249c3944fe2p-5, -0x1.21a79bf4d1745p-4, -0x1.a6308f18ee9b9p-4, + 0x1.5f6d0923ca496p-7, 0x1.fe1cacaa10eb9p-4, 0x1.aa6c848350222p-5, -0x1.d17e7952cfb2bp-4, + -0x1.9ef43df55e8e1p-4, 0x1.2bedb20e0176ep-4, 0x1.fce15fa212d61p-4, -0x1.c37870a7c6ea5p-7, + -0x1.d6961888a142dp-4, -0x1.9372a4ea634c5p-5, 0x1.36058b646aa33p-4, 0x1.9777f13749fcbp-4, + -0x1.139f0a404fe61p-6, -0x1.fb57975f5fea2p-4, -0x1.7c3a95eca6680p-5, 0x1.db6526d806b68p-4, + 0x1.8fbccab52d47cp-4, -0x1.3fed94632d0f4p-4, -0x1.f97f8fe26fdabp-4, 0x1.45576d1b69918p-6, + 0x1.dfeae49fc3b08p-4, 0x1.64c7e0d12e5ecp-5, -0x1.49a449efe527cp-4, -0x1.87c3ff9fe07ebp-4, + 0x1.76dd99566c183p-6, 0x1.f7599a7c8e057p-4, 0x1.4d1e2082a07f5p-5, -0x1.e426a54a85e4dp-4, + -0x1.7f8ecc1a7087cp-4, 0x1.53282cc7cbcc4p-4, 0x1.f4e603ffdbb2bp-4, -0x1.a82a0087cf8d8p-6, + -0x1.e817bc6bb73b7p-4, -0x1.35410be3c9736p-5, 0x1.5c77bb092e4b7p-4, 0x1.771e788f07b48p-4, + -0x1.d934fb773f599p-6, -0x1.f22530e9cc991p-4, -0x1.1d34402d0fab3p-5, 0x1.ebbd8bbf0a51ap-4, + 0x1.6e7445eff9f16p-4, -0x1.65919232926d2p-4, -0x1.ef178acc6ac0ep-4, 0x1.04fb803e1e62ap-5, + 0x1.ef178a1a3b937p-4, 0x1.04fb7fdbb2b3bp-5, 0x1.6e7446e7a6d2bp-4, 0x1.659192b5ae54fp-4, + 0x1.1d34411f5a4efp-5, 0x1.ebbd8d4a7feeap-4, -0x1.d934fd0860bd1p-6, 0x1.f22530b826709p-4, + -0x1.5c77bc8e80ebap-4, 0x1.771e77e9c5c73p-4, -0x1.e817bc9e6a219p-4, 0x1.35410b30c4d00p-5, + -0x1.f4e60462b0a9fp-4, -0x1.a829ff5a266fdp-6, -0x1.7f8ecc1396c0bp-4, -0x1.53282bb553f3bp-4, + -0x1.4d1e200035d06p-5, -0x1.e426a47a98abfp-4, 0x1.76dd993486dd8p-6, -0x1.f75999743c7c5p-4, + 0x1.49a449a0c2017p-4, -0x1.87c4003ac2c8fp-4, 0x1.dfeae47ce504dp-4, -0x1.64c7dfef736afp-5, + 0x1.f97f90d040f30p-4, 0x1.45576c92b78f8p-6, 0x1.8fbccad061a65p-4, 0x1.3fed943dc1c96p-4, + 0x1.7c3a9665446d2p-5, 0x1.db6526acfd00dp-4, -0x1.139f0a5c9f5a8p-6, 0x1.fb579726cfdd1p-4, + -0x1.36058baf7c766p-4, 0x1.9777f0783f629p-4, -0x1.d696191b61c03p-4, 0x1.9372a4310ffdfp-5, + -0x1.fce15fe54e0b0p-4, -0x1.c3786f8435ce7p-7, -0x1.9ef43e5515779p-4, -0x1.2bedb26d420cap-4, + -0x1.aa6c84ee2e886p-5, -0x1.d17e77f0de2c4p-4, 0x1.5f6d094f44510p-7, -0x1.fe1cac586c8eap-4, + 0x1.21a79cc4af37dp-4, -0x1.a630901536dfcp-4, 0x1.cc1f0e80f94b3p-4, -0x1.c1249c509f1aep-5, + 0x1.ff0952189e898p-4, 0x1.f656e75be0ce1p-8, 0x1.ad2bc8b811d7bp-4, 0x1.1734d5dafda29p-4, + 0x1.d797766c1e9c5p-5, 0x1.c678b3b5ef86ep-4, -0x1.2d8630c936a61p-8, 0x1.ffa73027f6348p-4, + -0x1.0c97020b6c2d1p-4, 0x1.b3e4d1edb9cf8p-4, -0x1.c08c42fdbac38p-4, 0x1.edc197eef45f2p-5, + -0x1.fff6252a98bdep-4, -0x1.921d1d7b27b13p-10, -0x1.ba5aa634a7607p-4, -0x1.01cfc84ef37f9p-4, + -0x1.01cfc84ef37f9p-4, -0x1.ba5aa634a7607p-4, -0x1.921d1d7b27b13p-10, -0x1.fff6252a98bdep-4, + 0x1.edc197eef45f2p-5, -0x1.c08c42fdbac38p-4, 0x1.b3e4d1edb9cf8p-4, -0x1.0c97020b6c2d1p-4, + 0x1.ffa73027f6348p-4, -0x1.2d8630c936a61p-8, 0x1.c678b3b5ef86ep-4, 0x1.d797766c1e9c5p-5, + 0x1.1734d5dafda29p-4, 0x1.ad2bc8b811d7bp-4, 0x1.f656e75be0ce1p-8, 0x1.ff0952189e898p-4, + -0x1.c1249c509f1aep-5, 0x1.cc1f0e80f94b3p-4, -0x1.a630901536dfcp-4, 0x1.21a79cc4af37dp-4, + -0x1.fe1cac586c8eap-4, 0x1.5f6d094f44510p-7, -0x1.d17e77f0de2c4p-4, -0x1.aa6c84ee2e886p-5, + -0x1.2bedb26d420cap-4, -0x1.9ef43e5515779p-4, -0x1.c3786f8435ce7p-7, -0x1.fce15fe54e0b0p-4, + 0x1.9372a4310ffdfp-5, -0x1.d696191b61c03p-4, 0x1.9777f0783f629p-4, -0x1.36058baf7c766p-4, + 0x1.fb579726cfdd1p-4, -0x1.139f0a5c9f5a8p-6, 0x1.db6526acfd00dp-4, 0x1.7c3a9665446d2p-5, + 0x1.3fed943dc1c96p-4, 0x1.8fbccad061a65p-4, 0x1.45576c92b78f8p-6, 0x1.f97f90d040f30p-4, + -0x1.64c7dfef736afp-5, 0x1.dfeae47ce504dp-4, -0x1.87c4003ac2c8fp-4, 0x1.49a449a0c2017p-4, + -0x1.f75999743c7c5p-4, 0x1.76dd993486dd8p-6, -0x1.e426a47a98abfp-4, -0x1.4d1e200035d06p-5, + -0x1.53282bb553f3bp-4, -0x1.7f8ecc1396c0bp-4, -0x1.a829ff5a266fdp-6, -0x1.f4e60462b0a9fp-4, + 0x1.35410b30c4d00p-5, -0x1.e817bc9e6a219p-4, 0x1.771e77e9c5c73p-4, -0x1.5c77bc8e80ebap-4, + 0x1.f22530b826709p-4, -0x1.d934fd0860bd1p-6, 0x1.ebbd8d4a7feeap-4, 0x1.1d34411f5a4efp-5, + 0x1.659192b5ae54fp-4, 0x1.6e7446e7a6d2bp-4, 0x1.04fb7fdbb2b25p-5, 0x1.ef178a1a3b935p-4, + -0x1.0e3d0ca854477p-3, 0x1.079e39ecfa64dp-5, -0x1.bcecff773c0bbp-7, 0x1.43701908042c0p-3, + -0x1.6d8981d84bba8p-5, 0x1.6770b865f7961p-6, -0x1.b931de2fe9e77p-7, 0x1.9bc33b009c277p-6, + 0x1.447b4f086bf3fp-4, 0x1.aa7ac70132ef5p-5, -0x1.a95feff5d52e3p-4, 0x1.12d4fbb99e356p-6, + 0x1.5fb3227043762p-4, -0x1.2dafd6f9777b9p-5, -0x1.1fbb0bef96ef2p-3, -0x1.df9ceaf799256p-9, + 0x1.5017756e6b264p-5, 0x1.770bff2cf4502p-4, -0x1.e4f0297de3e95p-13, 0x1.9e1055ffb2ed5p-4, + -0x1.cccf307e35d63p-3, -0x1.d0d5e07e1f46bp-4, 0x1.5b9feca124150p-4, -0x1.579652aff7b98p-4, + 0x1.9b615fc55b43ap-3, 0x1.b22e91a6fefaap-6, -0x1.58dc89119141ep-7, -0x1.65fd5ff7f326dp-5, + 0x1.08ae92a8b663ap-5, -0x1.59b03f9476366p-4, 0x1.a65f5452e0944p-5, 0x1.b654acba350dbp-4, + 0x1.8ed624144228ap-4, -0x1.7243b1ab9e4f2p-4, -0x1.d2172223db9e0p-6, -0x1.64c833e130bb2p-9, + 0x1.3566e0f8f4839p-3, -0x1.837ed519ad58ap-5, 0x1.e3c7f1dabe1dcp-4, -0x1.90ed55eec1187p-5, + -0x1.7ddb0a2973cfap-6, 0x1.7739bb34c15cbp-6, -0x1.7dfde6d42a4f6p-5, -0x1.6c3ffd5128ff6p-7, + 0x1.9517418fa9bf0p-5, 0x1.acd4e1213ff71p-3, 0x1.ae17efdfe5ea0p-4, -0x1.36b9784c9a059p-7, + 0x1.6ac6bfa0107c6p-5, 0x1.1d38f7db03934p-5, 0x1.3713915b9a746p-3, 0x1.080503a6c9cc8p-4, + 0x1.69181d098b5fep-6, -0x1.a9a2635352f99p-6, 0x1.59273fa05d509p-5, -0x1.46b0466698898p-6, + 0x1.ee5fa29140debp-7, -0x1.a9ab040f451edp-3, -0x1.647c22e4a90c0p-3, -0x1.0d88717258160p-4, + -0x1.302fa4ecd9c00p-4, -0x1.825272060beffp-5, -0x1.7c1b261fcf81bp-7, 0x1.f0b8b8794cd37p-6, + 0x1.f0b8b8794cd37p-6, -0x1.7c1b261fcf81bp-7, -0x1.825272060beffp-5, -0x1.302fa4ecd9c00p-4, + -0x1.0d88717258160p-4, -0x1.647c22e4a90c0p-3, -0x1.a9ab040f451edp-3, 0x1.ee5fa29140debp-7, + -0x1.46b0466698898p-6, 0x1.59273fa05d509p-5, -0x1.a9a2635352f99p-6, 0x1.69181d098b5fep-6, + 0x1.080503a6c9cc8p-4, 0x1.3713915b9a746p-3, 0x1.1d38f7db03934p-5, 0x1.6ac6bfa0107c6p-5, + -0x1.36b9784c9a059p-7, 0x1.ae17efdfe5ea0p-4, 0x1.acd4e1213ff71p-3, 0x1.9517418fa9bf0p-5, + -0x1.6c3ffd5128ff6p-7, -0x1.7dfde6d42a4f6p-5, 0x1.7739bb34c15cbp-6, -0x1.7ddb0a2973cfap-6, + -0x1.90ed55eec1187p-5, 0x1.e3c7f1dabe1dcp-4, -0x1.837ed519ad58ap-5, 0x1.3566e0f8f4839p-3, + -0x1.64c833e130bb2p-9, -0x1.d2172223db9e0p-6, -0x1.7243b1ab9e4f2p-4, 0x1.8ed624144228ap-4, + 0x1.b654acba350dbp-4, 0x1.a65f5452e0944p-5, -0x1.59b03f9476366p-4, 0x1.08ae92a8b663ap-5, + -0x1.65fd5ff7f326dp-5, -0x1.58dc89119141ep-7, 0x1.b22e91a6fefaap-6, 0x1.9b615fc55b43ap-3, + -0x1.579652aff7b98p-4, 0x1.5b9feca124150p-4, -0x1.d0d5e07e1f46bp-4, -0x1.cccf307e35d63p-3, + 0x1.9e1055ffb2ed5p-4, -0x1.e4f0297de3e95p-13, 0x1.770bff2cf4502p-4, 0x1.5017756e6b264p-5, + -0x1.df9ceaf799256p-9, -0x1.1fbb0bef96ef2p-3, -0x1.2dafd6f9777b9p-5, 0x1.5fb3227043762p-4, + 0x1.12d4fbb99e356p-6, -0x1.a95feff5d52e3p-4, 0x1.aa7ac70132ef5p-5, 0x1.447b4f086bf3fp-4, + 0x1.9bc33b009c277p-6, -0x1.b931de2fe9e77p-7, 0x1.6770b865f796dp-6, -0x1.6d8981d84bba9p-5, + 0x1.43701908042c8p-3, -0x1.bcecff773c0d3p-7, 0x1.079e3db5432cap-5, -0x1.0e3d0c8c718d5p-3, + -0x1.fce7f03ba5bb6p-11, 0x1.5af78dfe9bb5cp-5, 0x1.47a47bf1ebf7dp-5, -0x1.1ee7b437948b2p-6, + 0x1.fac9464f3f372p-7, 0x1.db88f65343b9fp-6, -0x1.67b16a88f2791p-4, 0x1.80f1c302e6bd3p-6, + -0x1.0699d600d5037p-7, -0x1.532e6e87b5df1p-4, 0x1.cee6be63f1369p-6, 0x1.8ee056381bc26p-4, + -0x1.7b39d83c80fbcp-6, -0x1.aac736fb0fe5bp-3, -0x1.7908803b62c75p-5, 0x1.1069fc1c17c43p-5, + -0x1.551fb6b99a0c5p-3, 0x1.3bfc569a9a406p-5, 0x1.d9c85665aa947p-5, 0x1.c3b67968e4c39p-6, + 0x1.72d12d872d103p-4, 0x1.91ceffffffe2cp-4, 0x1.b22103591549cp-6, 0x1.0156e561fa941p-3, + 0x1.39ec6d15717c8p-5, 0x1.76000afb232e5p-3, -0x1.842e54492bc93p-7, 0x1.ab9130aaad5c4p-6, + 0x1.ab5c6819b231ap-4, 0x1.11881b9d40fd6p-4, -0x1.acfd786988f86p-3, 0x1.e8750ea1f2e0dp-6, + 0x1.4822cd3af4a4ep-3, -0x1.056f9a6942f3cp-5, -0x1.1541a13319779p-4, -0x1.954403141ebbcp-4, + 0x1.791fb9de81f65p-8, -0x1.94c8fc2b42201p-9, -0x1.ac7ed7bc33bcdp-5, -0x1.4970822ce52b6p-7, + -0x1.0bd7db84dd1b2p-7, -0x1.a8238f5440fecp-9, -0x1.4d1b48546c53fp-5, 0x1.f0154dd042808p-8, + 0x1.3bd0bd0feaadcp-3, 0x1.51b6fd1cfac56p-5, -0x1.5a52ca1dab2c8p-5, 0x1.d4eaceb38f47dp-8, + 0x1.b63d16ea31628p-8, -0x1.4be619faf562ap-4, 0x1.8b14d3f45249bp-6, -0x1.ee1aafa164f6ep-3, + -0x1.1dd81abc52b2cp-5, 0x1.6a96387b9ac77p-5, 0x1.30397d7a6505cp-3, 0x1.e8edef5e6182ep-8, + 0x1.82f821ca3048cp-3, -0x1.80dcedc693094p-4, -0x1.a5f5a94fcd72fp-7, 0x1.7c0647c0ae020p-15, + -0x1.2a83e71610343p-7, 0x1.bb1da052fed80p-3, 0x1.b521d1de1c0c7p-5, -0x1.00ee635c732dbp-5, + -0x1.00ee635c732dbp-5, 0x1.b521d1de1c0c7p-5, 0x1.bb1da052fed80p-3, -0x1.2a83e71610343p-7, + 0x1.7c0647c0ae020p-15, -0x1.a5f5a94fcd72fp-7, -0x1.80dcedc693094p-4, 0x1.82f821ca3048cp-3, + 0x1.e8edef5e6182ep-8, 0x1.30397d7a6505cp-3, 0x1.6a96387b9ac77p-5, -0x1.1dd81abc52b2cp-5, + -0x1.ee1aafa164f6ep-3, 0x1.8b14d3f45249bp-6, -0x1.4be619faf562ap-4, 0x1.b63d16ea31628p-8, + 0x1.d4eaceb38f47dp-8, -0x1.5a52ca1dab2c8p-5, 0x1.51b6fd1cfac56p-5, 0x1.3bd0bd0feaadcp-3, + 0x1.f0154dd042808p-8, -0x1.4d1b48546c53fp-5, -0x1.a8238f5440fecp-9, -0x1.0bd7db84dd1b2p-7, + -0x1.4970822ce52b6p-7, -0x1.ac7ed7bc33bcdp-5, -0x1.94c8fc2b42201p-9, 0x1.791fb9de81f65p-8, + -0x1.954403141ebbcp-4, -0x1.1541a13319779p-4, -0x1.056f9a6942f3cp-5, 0x1.4822cd3af4a4ep-3, + 0x1.e8750ea1f2e0dp-6, -0x1.acfd786988f86p-3, 0x1.11881b9d40fd6p-4, 0x1.ab5c6819b231ap-4, + 0x1.ab9130aaad5c4p-6, -0x1.842e54492bc93p-7, 0x1.76000afb232e5p-3, 0x1.39ec6d15717c8p-5, + 0x1.0156e561fa941p-3, 0x1.b22103591549cp-6, 0x1.91ceffffffe2cp-4, 0x1.72d12d872d103p-4, + 0x1.c3b67968e4c39p-6, 0x1.d9c85665aa947p-5, 0x1.3bfc569a9a406p-5, -0x1.551fb6b99a0c5p-3, + 0x1.1069fc1c17c43p-5, -0x1.7908803b62c75p-5, -0x1.aac736fb0fe5bp-3, -0x1.7b39d83c80fbcp-6, + 0x1.8ee056381bc26p-4, 0x1.cee6be63f1369p-6, -0x1.532e6e87b5df1p-4, -0x1.0699d600d5037p-7, + 0x1.80f1c302e6bd3p-6, -0x1.67b16a88f2791p-4, 0x1.db88f65343ba5p-6, 0x1.fac9464f3f37ep-7, + -0x1.1ee7b437948aap-6, 0x1.47a47bf1ebf74p-5, 0x1.5af78e63f5398p-5, -0x1.fce854a3612d6p-11, + 0x1.d934fdb4be20ap-6, -0x1.f22530fcbbb53p-4, -0x1.49a4493d1f6d8p-4, 0x1.87c40176756f7p-4, + 0x1.d69616d74a519p-4, -0x1.9372a6ecf8066p-5, -0x1.ff095695f20ebp-4, -0x1.f656ed12a3c9fp-8, + 0x1.ba5aa6117f34dp-4, 0x1.01cfc864b357ep-4, -0x1.1734d66e2c935p-4, -0x1.ad2bcbc2817dep-4, + 0x1.c3785e2dda60dp-7, 0x1.fce15f8350254p-4, 0x1.64c7dfba06509p-5, -0x1.dfeae6f34b9adp-4, + -0x1.771e75d69d7cfp-4, 0x1.5c77bc4a21d74p-4, 0x1.ebbd8bc65de1dp-4, -0x1.1d3442b30d5a6p-5, + -0x1.f7599a6680c02p-4, -0x1.76dda1019a398p-6, 0x1.9777eef90409cp-4, 0x1.36058bd5b0aafp-4, + -0x1.c1249b131b1f3p-5, -0x1.cc1f0c4737e0bp-4, -0x1.921d3827dbc33p-10, 0x1.fff622c235339p-4, + 0x1.d79776add121cp-5, -0x1.c678b2b12f220p-4, -0x1.9ef44039d2856p-4, 0x1.2bedb1d37c24bp-4, + 0x1.f97f92cdeaad2p-4, -0x1.4557697d852b6p-6, -0x1.e817b9a6dab4dp-4, -0x1.35410ae866038p-5, + 0x1.6e7444d006059p-4, 0x1.6591923d598a6p-4, -0x1.4d1e219a177a9p-5, -0x1.e426a5d45cc6dp-4, + -0x1.139f0c97a1990p-6, 0x1.fb5797c5319dfp-4, 0x1.21a7981c09ca9p-4, -0x1.a63090f17bfcep-4, + -0x1.c08c4208cbfecp-4, 0x1.edc18f8191e4ap-5, 0x1.ffa73009ddec6p-4, -0x1.2d865a2f96257p-8, + -0x1.d17e72bbc5b6cp-4, -0x1.aa6c7fcb3ae68p-5, 0x1.3fed94c61c077p-4, 0x1.8fbcc95b1d6edp-4, + -0x1.a829ff64f48b2p-6, -0x1.f4e6071a30950p-4, -0x1.04fb7f6e7f6f4p-5, 0x1.ef178ad4ee568p-4, + 0x1.5328274d7d3c5p-4, -0x1.7f8eccf5a4cf3p-4, -0x1.db65288e9bbcdp-4, 0x1.7c3a96009fc8fp-5, + 0x1.fe1cb08e13b56p-4, 0x1.5f6d0be06def8p-7, -0x1.b3e4d522724dcp-4, -0x1.0c9704183eb5fp-4, + 0x1.0c9704183eb5fp-4, 0x1.b3e4d522724dcp-4, -0x1.5f6d0be06def8p-7, -0x1.fe1cb08e13b56p-4, + -0x1.7c3a96009fc8fp-5, 0x1.db65288e9bbcdp-4, 0x1.7f8eccf5a4cf3p-4, -0x1.5328274d7d3c5p-4, + -0x1.ef178ad4ee568p-4, 0x1.04fb7f6e7f6f4p-5, 0x1.f4e6071a30950p-4, 0x1.a829ff64f48b2p-6, + -0x1.8fbcc95b1d6edp-4, -0x1.3fed94c61c077p-4, 0x1.aa6c7fcb3ae68p-5, 0x1.d17e72bbc5b6cp-4, + 0x1.2d865a2f96257p-8, -0x1.ffa73009ddec6p-4, -0x1.edc18f8191e4ap-5, 0x1.c08c4208cbfecp-4, + 0x1.a63090f17bfcep-4, -0x1.21a7981c09ca9p-4, -0x1.fb5797c5319dfp-4, 0x1.139f0c97a1990p-6, + 0x1.e426a5d45cc6dp-4, 0x1.4d1e219a177a9p-5, -0x1.6591923d598a6p-4, -0x1.6e7444d006059p-4, + 0x1.35410ae866038p-5, 0x1.e817b9a6dab4dp-4, 0x1.4557697d852b6p-6, -0x1.f97f92cdeaad2p-4, + -0x1.2bedb1d37c24bp-4, 0x1.9ef44039d2856p-4, 0x1.c678b2b12f220p-4, -0x1.d79776add121cp-5, + -0x1.fff622c235339p-4, 0x1.921d3827dbc33p-10, 0x1.cc1f0c4737e0bp-4, 0x1.c1249b131b1f3p-5, + -0x1.36058bd5b0aafp-4, -0x1.9777eef90409cp-4, 0x1.76dda1019a398p-6, 0x1.f7599a6680c02p-4, + 0x1.1d3442b30d5a6p-5, -0x1.ebbd8bc65de1dp-4, -0x1.5c77bc4a21d74p-4, 0x1.771e75d69d7cfp-4, + 0x1.dfeae6f34b9adp-4, -0x1.64c7dfba06509p-5, -0x1.fce15f8350254p-4, -0x1.c3785e2dda60dp-7, + 0x1.ad2bcbc2817dep-4, 0x1.1734d66e2c935p-4, -0x1.01cfc864b357ep-4, -0x1.ba5aa6117f34dp-4, + 0x1.f656ed12a3c9fp-8, 0x1.ff095695f20ebp-4, 0x1.9372a6ecf8066p-5, -0x1.d69616d74a519p-4, + -0x1.87c40176756f7p-4, 0x1.49a4493d1f6d8p-4, 0x1.f22530fcbbb53p-4, -0x1.d934fdb4be1e3p-6, + 0x1.f2253017be1c2p-4, 0x1.d934ff24a36cap-6, 0x1.87c402d7258f7p-4, 0x1.49a449c87e5c6p-4, + 0x1.9372a823aacc3p-5, 0x1.d696174fd9321p-4, -0x1.f656ea8aae2b2p-8, 0x1.ff09554b5a590p-4, + -0x1.01cfc80b3012cp-4, 0x1.ba5aa4fef0e8ap-4, -0x1.ad2bccc19db52p-4, 0x1.1734d6ade5ef9p-4, + -0x1.fce15f94dda85p-4, 0x1.c3785ded47421p-7, -0x1.dfeae6d794d2bp-4, -0x1.64c7def737332p-5, + -0x1.5c77bca8c307fp-4, -0x1.771e765cafc22p-4, -0x1.1d344343031c5p-5, -0x1.ebbd8b4afcc4cp-4, + 0x1.76dda0855fbb1p-6, -0x1.f7599a209c8b9p-4, 0x1.36058bc332636p-4, -0x1.9777ef72897b7p-4, + 0x1.cc1f0c403884dp-4, -0x1.c1249ba95a9d9p-5, 0x1.fff6221ad2f68p-4, 0x1.921d2d6e1ff1dp-10, + 0x1.c678b1d13d779p-4, 0x1.d797772f117dep-5, 0x1.2bedb28e5f138p-4, 0x1.9ef44012dc578p-4, + 0x1.455768277f59bp-6, 0x1.f97f941eceb56p-4, -0x1.35410c528e519p-5, 0x1.e817b9b70d587p-4, + -0x1.659191aed89c3p-4, 0x1.6e74463143800p-4, -0x1.e426a57a57c04p-4, 0x1.4d1e22411444ap-5, + -0x1.fb5798a44f81ap-4, -0x1.139f0d0d56cc9p-6, -0x1.a6308fbaff4fdp-4, -0x1.21a7985a028ecp-4, + -0x1.edc18f5749834p-5, -0x1.c08c41cb1321cp-4, -0x1.2d865d9abb8eap-8, -0x1.ffa730eb13b65p-4, + 0x1.aa6c814c79d55p-5, -0x1.d17e74a273fd0p-4, 0x1.8fbcc956f59d8p-4, -0x1.3fed9361d3ec0p-4, + 0x1.f4e60699af80cp-4, -0x1.a829ff7040527p-6, 0x1.ef1789a31b196p-4, 0x1.04fb7f8180f9ep-5, + 0x1.7f8ecd49354fdp-4, 0x1.53282846f04d0p-4, 0x1.7c3a9679c140bp-5, 0x1.db65281b3756ap-4, + -0x1.5f6d0def6c3b0p-7, 0x1.fe1cb060f823ap-4, -0x1.0c9703db68029p-4, 0x1.b3e4d37569d8fp-4, + -0x1.b3e4d37569d8fp-4, 0x1.0c9703db68029p-4, -0x1.fe1cb060f823ap-4, 0x1.5f6d0def6c3b0p-7, + -0x1.db65281b3756ap-4, -0x1.7c3a9679c140bp-5, -0x1.53282846f04d0p-4, -0x1.7f8ecd49354fdp-4, + -0x1.04fb7f8180f9ep-5, -0x1.ef1789a31b196p-4, 0x1.a829ff7040527p-6, -0x1.f4e60699af80cp-4, + 0x1.3fed9361d3ec0p-4, -0x1.8fbcc956f59d8p-4, 0x1.d17e74a273fd0p-4, -0x1.aa6c814c79d55p-5, + 0x1.ffa730eb13b65p-4, 0x1.2d865d9abb8eap-8, 0x1.c08c41cb1321cp-4, 0x1.edc18f5749834p-5, + 0x1.21a7985a028ecp-4, 0x1.a6308fbaff4fdp-4, 0x1.139f0d0d56cc9p-6, 0x1.fb5798a44f81ap-4, + -0x1.4d1e22411444ap-5, 0x1.e426a57a57c04p-4, -0x1.6e74463143800p-4, 0x1.659191aed89c3p-4, + -0x1.e817b9b70d587p-4, 0x1.35410c528e519p-5, -0x1.f97f941eceb56p-4, -0x1.455768277f59bp-6, + -0x1.9ef44012dc578p-4, -0x1.2bedb28e5f138p-4, -0x1.d797772f117dep-5, -0x1.c678b1d13d779p-4, + -0x1.921d2d6e1ff1dp-10, -0x1.fff6221ad2f68p-4, 0x1.c1249ba95a9d9p-5, -0x1.cc1f0c403884dp-4, + 0x1.9777ef72897b7p-4, -0x1.36058bc332636p-4, 0x1.f7599a209c8b9p-4, -0x1.76dda0855fbb1p-6, + 0x1.ebbd8b4afcc4cp-4, 0x1.1d344343031c5p-5, 0x1.771e765cafc22p-4, 0x1.5c77bca8c307fp-4, + 0x1.64c7def737332p-5, 0x1.dfeae6d794d2bp-4, -0x1.c3785ded47421p-7, 0x1.fce15f94dda85p-4, + -0x1.1734d6ade5ef9p-4, 0x1.ad2bccc19db52p-4, -0x1.ba5aa4fef0e8ap-4, 0x1.01cfc80b3012cp-4, + -0x1.ff09554b5a590p-4, 0x1.f656ea8aae2b2p-8, -0x1.d696174fd9321p-4, -0x1.9372a823aacc3p-5, + -0x1.49a449c87e5c6p-4, -0x1.87c402d7258f7p-4, -0x1.d934ff24a36fbp-6, -0x1.f2253017be1c2p-4, + -0x1.05a76bbcf61f6p-3, 0x1.b5de83457a6f2p-7, -0x1.18eab8dc80d04p-4, 0x1.2bdee085f529fp-4, + 0x1.55fc1ca763f0bp-6, 0x1.62cf4d9eb8143p-4, -0x1.ae4feff653f34p-7, -0x1.6432312a52af5p-4, + -0x1.44aee06556a18p-4, 0x1.1ee5f365c5d1ep-4, 0x1.a3ba65d7f12f5p-6, 0x1.f04591d81184dp-5, + -0x1.206dbc81d96adp-2, -0x1.06ea8e4197557p-7, 0x1.1679191018db6p-4, -0x1.1a811681c3f9fp-7, + 0x1.c461bea1ea252p-4, 0x1.11cbd28b63aaep-4, 0x1.a4929e5f616b0p-4, 0x1.65e2523fdd36ap-9, + -0x1.0a3e043e6e5dfp-11, -0x1.ea0e84820e3efp-6, 0x1.1543fe089cc7bp-7, -0x1.7728468d58d87p-4, + 0x1.6461267008b40p-7, 0x1.6d3e19aa98812p-4, 0x1.3e942a80eeabfp-4, 0x1.2affba642645bp-7, + 0x1.d2f618d4913e3p-6, -0x1.1403f5c1e533ep-4, -0x1.6db0ab1b9a42ap-8, -0x1.659c85e105debp-4, + 0x1.1cf6a4818ec50p-6, -0x1.402ffd1f56f0ep-3, -0x1.9eb7f7ac81ad5p-9, -0x1.c22f5fdb30190p-6, + -0x1.58ce75adbf2d8p-3, 0x1.edc2707b470d8p-6, -0x1.fa17d111db11fp-7, -0x1.274522b737069p-6, + -0x1.292c6f3314f54p-4, 0x1.61e4c9112d32dp-6, 0x1.864d5248f0d4bp-4, 0x1.38e3c3a661af8p-4, + -0x1.b40e895602009p-6, -0x1.d9da1aabcb8a3p-5, 0x1.ed4286a64dda7p-7, 0x1.4ffe32ff1eab0p-5, + -0x1.54b2c41965592p-4, 0x1.2e2646a1eaaccp-7, 0x1.43c991a1d9fafp-3, -0x1.d0eeae06ba6b4p-6, + -0x1.1fa9e25182543p-4, -0x1.2253d6222095ep-9, 0x1.881b740dc2e12p-3, -0x1.9c0a30aa3e2f1p-5, + 0x1.ebb3c3c7f80aep-5, -0x1.b2ba9ab117a00p-4, 0x1.9798c9d47ab7dp-5, -0x1.5ed7c38b68943p-4, + -0x1.672a84896146bp-7, -0x1.3c1113f88c9b4p-2, -0x1.fb924981fdba6p-5, 0x1.b902b2dd12977p-4, + -0x1.b902b2dd12977p-4, 0x1.fb924981fdba6p-5, 0x1.3c1113f88c9b4p-2, 0x1.672a84896146bp-7, + 0x1.5ed7c38b68943p-4, -0x1.9798c9d47ab7dp-5, 0x1.b2ba9ab117a00p-4, -0x1.ebb3c3c7f80aep-5, + 0x1.9c0a30aa3e2f1p-5, -0x1.881b740dc2e12p-3, 0x1.2253d6222095ep-9, 0x1.1fa9e25182543p-4, + 0x1.d0eeae06ba6b4p-6, -0x1.43c991a1d9fafp-3, -0x1.2e2646a1eaaccp-7, 0x1.54b2c41965592p-4, + -0x1.4ffe32ff1eab0p-5, -0x1.ed4286a64dda7p-7, 0x1.d9da1aabcb8a3p-5, 0x1.b40e895602009p-6, + -0x1.38e3c3a661af8p-4, -0x1.864d5248f0d4bp-4, -0x1.61e4c9112d32dp-6, 0x1.292c6f3314f54p-4, + 0x1.274522b737069p-6, 0x1.fa17d111db11fp-7, -0x1.edc2707b470d8p-6, 0x1.58ce75adbf2d8p-3, + 0x1.c22f5fdb30190p-6, 0x1.9eb7f7ac81ad5p-9, 0x1.402ffd1f56f0ep-3, -0x1.1cf6a4818ec50p-6, + 0x1.659c85e105debp-4, 0x1.6db0ab1b9a42ap-8, 0x1.1403f5c1e533ep-4, -0x1.d2f618d4913e3p-6, + -0x1.2affba642645bp-7, -0x1.3e942a80eeabfp-4, -0x1.6d3e19aa98812p-4, -0x1.6461267008b40p-7, + 0x1.7728468d58d87p-4, -0x1.1543fe089cc7bp-7, 0x1.ea0e84820e3efp-6, 0x1.0a3e043e6e5dfp-11, + -0x1.65e2523fdd36ap-9, -0x1.a4929e5f616b0p-4, -0x1.11cbd28b63aaep-4, -0x1.c461bea1ea252p-4, + 0x1.1a811681c3f9fp-7, -0x1.1679191018db6p-4, 0x1.06ea8e4197557p-7, 0x1.206dbc81d96adp-2, + -0x1.f04591d81184dp-5, -0x1.a3ba65d7f12f5p-6, -0x1.1ee5f365c5d1ep-4, 0x1.44aee06556a18p-4, + 0x1.6432312a52af5p-4, 0x1.ae4feff653f34p-7, -0x1.62cf4d9eb8140p-4, -0x1.55fc1ca763f0ap-6, + -0x1.2bdee085f52aep-4, 0x1.18eab8dc80d02p-4, -0x1.b5de7c1925645p-7, 0x1.05a76bc2c313bp-3, + -0x1.8ae58df122681p-5, -0x1.9ebd06bc88d69p-4, 0x1.506bd4f846a17p-4, -0x1.a450b79c13ec9p-4, + -0x1.0024b2ea390bdp-7, 0x1.eb1b33dd0c099p-5, 0x1.afeddee7c365bp-6, -0x1.a0a7baaa583dcp-9, + -0x1.46e765c567882p-5, 0x1.95bb3c2daa4d3p-4, 0x1.26933e4b48254p-5, -0x1.02075c98abe2ap-8, + 0x1.42daf06ad588bp-6, -0x1.661a9f30cb8a7p-3, 0x1.3b67da141c6c1p-7, -0x1.1771b861a29cbp-3, + 0x1.0f1b73bf2fd08p-3, 0x1.81da6638730bep-4, -0x1.8579f4d7f921cp-3, -0x1.172ed9de9bfb2p-6, + -0x1.ca4e0a3286ebap-3, 0x1.2025387e42693p-7, -0x1.b2bbd5d7dd6fbp-5, 0x1.f13e3edd6a606p-6, + 0x1.c97d267393affp-4, 0x1.b09f172ef4dd3p-4, -0x1.920880f16abe3p-7, 0x1.1022800b13f7ap-7, + -0x1.62d2518fd3611p-5, -0x1.53659ccc9e425p-7, 0x1.d974c02ffa730p-5, -0x1.2428ff84ff146p-4, + -0x1.ce02b0fdab32cp-5, -0x1.61bbb41c8e454p-6, 0x1.bcc813603f466p-6, 0x1.947ac6b3ead68p-6, + -0x1.256ab38087aa2p-4, 0x1.672076f985a1ep-5, 0x1.b06ccf6516850p-6, 0x1.792ae9b7d73c3p-8, + 0x1.414f6690d430ep-6, 0x1.adda4c917506ep-6, -0x1.74666b8b37b9fp-5, -0x1.41e28aac1e8d3p-3, + 0x1.814a61c411ec6p-3, -0x1.8265236caf7b8p-5, 0x1.c4b1056cca3e4p-4, 0x1.f466495d6de1dp-8, + 0x1.231967f6c596dp-4, 0x1.bc4ba25195b47p-7, 0x1.df193e2989afep-5, -0x1.9c1b05b26ef2fp-4, + -0x1.28bafc4f486a8p-5, -0x1.0675f5ccea225p-3, 0x1.9da318a0c43adp-9, 0x1.2436cb97e0508p-3, + -0x1.c60749ce4666fp-5, 0x1.291645312e49ap-3, -0x1.10413688c8f05p-3, -0x1.8b8aec8262c5cp-5, + 0x1.6754d69925e51p-3, -0x1.21fac26d30fbcp-6, -0x1.319c66a39d6a4p-3, -0x1.63279f0f6315fp-4, + 0x1.63279f0f6315fp-4, 0x1.319c66a39d6a4p-3, 0x1.21fac26d30fbcp-6, -0x1.6754d69925e51p-3, + 0x1.8b8aec8262c5cp-5, 0x1.10413688c8f05p-3, -0x1.291645312e49ap-3, 0x1.c60749ce4666fp-5, + -0x1.2436cb97e0508p-3, -0x1.9da318a0c43adp-9, 0x1.0675f5ccea225p-3, 0x1.28bafc4f486a8p-5, + 0x1.9c1b05b26ef2fp-4, -0x1.df193e2989afep-5, -0x1.bc4ba25195b47p-7, -0x1.231967f6c596dp-4, + -0x1.f466495d6de1dp-8, -0x1.c4b1056cca3e4p-4, 0x1.8265236caf7b8p-5, -0x1.814a61c411ec6p-3, + 0x1.41e28aac1e8d3p-3, 0x1.74666b8b37b9fp-5, -0x1.adda4c917506ep-6, -0x1.414f6690d430ep-6, + -0x1.792ae9b7d73c3p-8, -0x1.b06ccf6516850p-6, -0x1.672076f985a1ep-5, 0x1.256ab38087aa2p-4, + -0x1.947ac6b3ead68p-6, -0x1.bcc813603f466p-6, 0x1.61bbb41c8e454p-6, 0x1.ce02b0fdab32cp-5, + 0x1.2428ff84ff146p-4, -0x1.d974c02ffa730p-5, 0x1.53659ccc9e425p-7, 0x1.62d2518fd3611p-5, + -0x1.1022800b13f7ap-7, 0x1.920880f16abe3p-7, -0x1.b09f172ef4dd3p-4, -0x1.c97d267393affp-4, + -0x1.f13e3edd6a606p-6, 0x1.b2bbd5d7dd6fbp-5, -0x1.2025387e42693p-7, 0x1.ca4e0a3286ebap-3, + 0x1.172ed9de9bfb2p-6, 0x1.8579f4d7f921cp-3, -0x1.81da6638730bep-4, -0x1.0f1b73bf2fd08p-3, + 0x1.1771b861a29cbp-3, -0x1.3b67da141c6c1p-7, 0x1.661a9f30cb8a7p-3, -0x1.42daf06ad588bp-6, + 0x1.02075c98abe2ap-8, -0x1.26933e4b48254p-5, -0x1.95bb3c2daa4d3p-4, 0x1.46e765c567882p-5, + 0x1.a0a7baaa583dcp-9, -0x1.afeddee7c3657p-6, -0x1.eb1b33dd0c099p-5, 0x1.0024b2ea390a6p-7, + 0x1.a450b79c13ecep-4, -0x1.506bd4f846a1bp-4, 0x1.9ebd06b450697p-4, 0x1.8ae5908462631p-5, + 0x1.a82a0372be5e1p-6, -0x1.f4e605b825eb3p-4, -0x1.2bedb0135f173p-4, 0x1.9ef43ee961aa7p-4, + 0x1.ba5aa7dcbee4dp-4, -0x1.01cfc6609c395p-4, -0x1.fce160746119cp-4, 0x1.c3785f83bf900p-7, + 0x1.e817b95446565p-4, 0x1.35410da6db1a4p-5, -0x1.7f8ed0ef6fb45p-4, -0x1.532828dad95edp-4, + 0x1.aa6c855e6b8ddp-5, 0x1.d17e787224cd4p-4, -0x1.921d2786f4fc2p-10, -0x1.fff6237a5d818p-4, + -0x1.9372a494c2cfcp-5, 0x1.d696161818dedp-4, 0x1.771e7666bd966p-4, -0x1.5c77bc05819f5p-4, + -0x1.e426a61ee9d25p-4, 0x1.4d1e25b463648p-5, 0x1.fe1cae4891ddap-4, 0x1.5f6cfb359f1f6p-7, + -0x1.c08c42ef83e6bp-4, -0x1.edc195a4d7ae8p-5, 0x1.3605898ed1d7dp-4, 0x1.9777ec4e581d6p-4, + -0x1.d934fe4721e26p-6, -0x1.f2252d780b1d6p-4, -0x1.76dd9b8a143b8p-6, 0x1.f7599a1c6f7d9p-4, + 0x1.21a7991c0aa6cp-4, -0x1.a63093e34ac97p-4, -0x1.b3e4d5228e8c5p-4, 0x1.0c9705440d292p-4, + 0x1.fb5794c56702ap-4, -0x1.139f08cd17300p-6, -0x1.ebbd8f31a6c1dp-4, -0x1.1d34442685450p-5, + 0x1.87c4002486e06p-4, 0x1.49a44870316bap-4, -0x1.c1249e77004b7p-5, -0x1.cc1f0f858a21bp-4, + 0x1.2d8637678e99ep-8, 0x1.ffa7311b81a93p-4, 0x1.7c3a956f6b496p-5, -0x1.db6525b65ad96p-4, + -0x1.6e7442c09e1cep-4, 0x1.659190b4ce8d3p-4, 0x1.dfeae40dad11ap-4, -0x1.64c7dec06bad3p-5, + -0x1.ff09583b2c3b9p-4, -0x1.f656fb77f99c6p-8, 0x1.c678b4129ba94p-4, 0x1.d79770442c6cap-5, + -0x1.3fed944d54932p-4, -0x1.8fbcc82ed4a1bp-4, 0x1.04fb80b368932p-5, 0x1.ef1788264a18fp-4, + 0x1.455769f50e5b6p-6, -0x1.f97f94f0c3160p-4, -0x1.1734d86c09e11p-4, 0x1.ad2bc996279fep-4, + 0x1.ad2bc996279fep-4, -0x1.1734d86c09e11p-4, -0x1.f97f94f0c3160p-4, 0x1.455769f50e5b6p-6, + 0x1.ef1788264a18fp-4, 0x1.04fb80b368932p-5, -0x1.8fbcc82ed4a1bp-4, -0x1.3fed944d54932p-4, + 0x1.d79770442c6cap-5, 0x1.c678b4129ba94p-4, -0x1.f656fb77f99c6p-8, -0x1.ff09583b2c3b9p-4, + -0x1.64c7dec06bad3p-5, 0x1.dfeae40dad11ap-4, 0x1.659190b4ce8d3p-4, -0x1.6e7442c09e1cep-4, + -0x1.db6525b65ad96p-4, 0x1.7c3a956f6b496p-5, 0x1.ffa7311b81a93p-4, 0x1.2d8637678e99ep-8, + -0x1.cc1f0f858a21bp-4, -0x1.c1249e77004b7p-5, 0x1.49a44870316bap-4, 0x1.87c4002486e06p-4, + -0x1.1d34442685450p-5, -0x1.ebbd8f31a6c1dp-4, -0x1.139f08cd17300p-6, 0x1.fb5794c56702ap-4, + 0x1.0c9705440d292p-4, -0x1.b3e4d5228e8c5p-4, -0x1.a63093e34ac97p-4, 0x1.21a7991c0aa6cp-4, + 0x1.f7599a1c6f7d9p-4, -0x1.76dd9b8a143b8p-6, -0x1.f2252d780b1d6p-4, -0x1.d934fe4721e26p-6, + 0x1.9777ec4e581d6p-4, 0x1.3605898ed1d7dp-4, -0x1.edc195a4d7ae8p-5, -0x1.c08c42ef83e6bp-4, + 0x1.5f6cfb359f1f6p-7, 0x1.fe1cae4891ddap-4, 0x1.4d1e25b463648p-5, -0x1.e426a61ee9d25p-4, + -0x1.5c77bc05819f5p-4, 0x1.771e7666bd966p-4, 0x1.d696161818dedp-4, -0x1.9372a494c2cfcp-5, + -0x1.fff6237a5d818p-4, -0x1.921d2786f4fc2p-10, 0x1.d17e787224cd4p-4, 0x1.aa6c855e6b8ddp-5, + -0x1.532828dad95edp-4, -0x1.7f8ed0ef6fb45p-4, 0x1.35410da6db1a4p-5, 0x1.e817b95446565p-4, + 0x1.c3785f83bf900p-7, -0x1.fce160746119cp-4, -0x1.01cfc6609c395p-4, 0x1.ba5aa7dcbee4dp-4, + 0x1.9ef43ee961aa7p-4, -0x1.2bedb0135f173p-4, -0x1.f4e605b825eb3p-4, 0x1.a82a0372be59fp-6, + 0x1.f4e6057726142p-4, 0x1.a82a049e72aedp-6, 0x1.9ef43eb2bca89p-4, 0x1.2bedb131cd1e4p-4, + 0x1.01cfc68d42ddfp-4, 0x1.ba5aa6338eeb6p-4, 0x1.c378607af7a41p-7, 0x1.fce161e5f88a6p-4, + -0x1.35410ccff69d6p-5, 0x1.e817b9c5e8effp-4, -0x1.532827d3b505ap-4, 0x1.7f8ed10c63d26p-4, + -0x1.d17e791b1c746p-4, 0x1.aa6c84b7f996ep-5, -0x1.fff6235ea3540p-4, 0x1.921d3026db4f0p-10, + -0x1.d69616c475df4p-4, -0x1.9372a4feb1a6bp-5, -0x1.5c77bd23bddc4p-4, -0x1.771e766cd7d76p-4, + -0x1.4d1e249b0923ap-5, -0x1.e426a599865aap-4, 0x1.5f6cfb2fe68b9p-7, -0x1.fe1cad527adb2p-4, + 0x1.edc195a8b15ddp-5, -0x1.c08c424336dc8p-4, 0x1.9777eda83ef31p-4, -0x1.3605895039e74p-4, + 0x1.f2252cfce2842p-4, -0x1.d934fd97f8dc4p-6, 0x1.f759994541a39p-4, 0x1.76dd9ca99047cp-6, + 0x1.a630928d883bcp-4, 0x1.21a79811a4e4fp-4, 0x1.0c9704b5a0f51p-4, 0x1.b3e4d51e09558p-4, + 0x1.139f07d0f4153p-6, 0x1.fb579527cb615p-4, -0x1.1d34437ca31b2p-5, 0x1.ebbd8f3363829p-4, + -0x1.49a448585dc08p-4, 0x1.87c3ffd73b92ep-4, -0x1.cc1f0e63d2ae4p-4, 0x1.c124a00a22180p-5, + -0x1.ffa731706fdbep-4, 0x1.2d86354061fa6p-8, -0x1.db6525691d811p-4, -0x1.7c3a950fc9a1ep-5, + -0x1.6591917d7d4f9p-4, -0x1.6e7442892e62fp-4, -0x1.64c7dfc054fa0p-5, -0x1.dfeae50f91f65p-4, + 0x1.f656fc411ea9ap-8, -0x1.ff09592e5aadbp-4, 0x1.d79770d7d08a7p-5, -0x1.c678b353dc712p-4, + 0x1.8fbcc9189907dp-4, -0x1.3fed9410e27cep-4, 0x1.ef1789064c49ep-4, -0x1.04fb817b6b317p-5, + 0x1.f97f9558f2905p-4, 0x1.4557697894c16p-6, 0x1.ad2bc90127ca4p-4, 0x1.1734d874e7f2cp-4, + 0x1.1734d874e7f2cp-4, 0x1.ad2bc90127ca4p-4, 0x1.4557697894c16p-6, 0x1.f97f9558f2905p-4, + -0x1.04fb817b6b317p-5, 0x1.ef1789064c49ep-4, -0x1.3fed9410e27cep-4, 0x1.8fbcc9189907dp-4, + -0x1.c678b353dc712p-4, 0x1.d79770d7d08a7p-5, -0x1.ff09592e5aadbp-4, 0x1.f656fc411ea9ap-8, + -0x1.dfeae50f91f65p-4, -0x1.64c7dfc054fa0p-5, -0x1.6e7442892e62fp-4, -0x1.6591917d7d4f9p-4, + -0x1.7c3a950fc9a1ep-5, -0x1.db6525691d811p-4, 0x1.2d86354061fa6p-8, -0x1.ffa731706fdbep-4, + 0x1.c124a00a22180p-5, -0x1.cc1f0e63d2ae4p-4, 0x1.87c3ffd73b92ep-4, -0x1.49a448585dc08p-4, + 0x1.ebbd8f3363829p-4, -0x1.1d34437ca31b2p-5, 0x1.fb579527cb615p-4, 0x1.139f07d0f4153p-6, + 0x1.b3e4d51e09558p-4, 0x1.0c9704b5a0f51p-4, 0x1.21a79811a4e4fp-4, 0x1.a630928d883bcp-4, + 0x1.76dd9ca99047cp-6, 0x1.f759994541a39p-4, -0x1.d934fd97f8dc4p-6, 0x1.f2252cfce2842p-4, + -0x1.3605895039e74p-4, 0x1.9777eda83ef31p-4, -0x1.c08c424336dc8p-4, 0x1.edc195a8b15ddp-5, + -0x1.fe1cad527adb2p-4, 0x1.5f6cfb2fe68b9p-7, -0x1.e426a599865aap-4, -0x1.4d1e249b0923ap-5, + -0x1.771e766cd7d76p-4, -0x1.5c77bd23bddc4p-4, -0x1.9372a4feb1a6bp-5, -0x1.d69616c475df4p-4, + 0x1.921d3026db4f0p-10, -0x1.fff6235ea3540p-4, 0x1.aa6c84b7f996ep-5, -0x1.d17e791b1c746p-4, + 0x1.7f8ed10c63d26p-4, -0x1.532827d3b505ap-4, 0x1.e817b9c5e8effp-4, -0x1.35410ccff69d6p-5, + 0x1.fce161e5f88a6p-4, 0x1.c378607af7a41p-7, 0x1.ba5aa6338eeb6p-4, 0x1.01cfc68d42ddfp-4, + 0x1.2bedb131cd1e4p-4, 0x1.9ef43eb2bca89p-4, 0x1.a82a049e72b20p-6, 0x1.f4e6057726147p-4, + 0x1.311e070040df2p-3, -0x1.ff1c6da74b114p-8, -0x1.a5b9a9c9e0298p-6, 0x1.0c7cbaada5dadp-5, + -0x1.2362b95935ab3p-8, -0x1.a1a2cd48acea3p-5, 0x1.3da8b02632299p-9, -0x1.3df25da6f1b55p-4, + 0x1.8ef60db277eb3p-5, -0x1.14598c261ffbap-4, 0x1.5aae16a675621p-4, -0x1.d00970a4a874fp-4, + 0x1.45143dd27ee9bp-4, 0x1.68deb799f9b61p-5, -0x1.970284534793bp-3, -0x1.a0ccb0103e7e8p-9, + 0x1.bb6b7beb5a14fp-5, -0x1.b83622ab633fbp-7, 0x1.c5df6975a1005p-5, 0x1.a3c0df822b3a6p-4, + -0x1.06bb4f8a58873p-4, -0x1.3d686175b270fp-3, 0x1.9f92f1316d59fp-10, -0x1.b9c4cb2989d1dp-3, + -0x1.6838251c64bb7p-6, 0x1.570f392fee3bfp-3, 0x1.58ef3f918bd6dp-5, -0x1.6d0f1eca7762ep-4, + -0x1.0267e1f2e0a5fp-2, 0x1.28deaa62ee40ap-5, -0x1.d0a4c668ebc1fp-4, 0x1.4a9c511f07a94p-12, + -0x1.7e6ebc0b8a14bp-7, -0x1.83357c3aaa5b8p-4, 0x1.d6763cdf90038p-6, 0x1.6ab158dd9b9b5p-4, + 0x1.0b3290c947de7p-6, 0x1.9be39b889e401p-3, 0x1.1c50dd50412f7p-6, 0x1.10ce8cb008c2dp-4, + -0x1.312ce5772d4d1p-5, -0x1.1ddbd854c754dp-5, 0x1.f321d91b4faefp-4, 0x1.7b154fb95396bp-6, + -0x1.5904f89180cc0p-5, 0x1.4c2fce639cd0dp-8, -0x1.0378f010575bfp-4, -0x1.8bd4f88642afdp-5, + -0x1.a2015f6f602f2p-6, 0x1.025447b21dbfdp-3, -0x1.fb74e1bb31c0ep-5, 0x1.6e89e10954f23p-4, + -0x1.8049151881906p-8, -0x1.b81f306b44b40p-3, -0x1.58e894f26bb73p-6, 0x1.ced2bfafccb47p-6, + -0x1.2b33ea3e9b3fap-5, 0x1.5e63f15d7fd1fp-4, 0x1.aa3ab925f7c21p-5, 0x1.090ec0472dfdfp-5, + -0x1.acf8b104eb31fp-7, -0x1.ba1d5136ce397p-6, 0x1.474556073c5f9p-6, -0x1.45b065f499861p-4, + -0x1.45b065f499861p-4, 0x1.474556073c5f9p-6, -0x1.ba1d5136ce397p-6, -0x1.acf8b104eb31fp-7, + 0x1.090ec0472dfdfp-5, 0x1.aa3ab925f7c21p-5, 0x1.5e63f15d7fd1fp-4, -0x1.2b33ea3e9b3fap-5, + 0x1.ced2bfafccb47p-6, -0x1.58e894f26bb73p-6, -0x1.b81f306b44b40p-3, -0x1.8049151881906p-8, + 0x1.6e89e10954f23p-4, -0x1.fb74e1bb31c0ep-5, 0x1.025447b21dbfdp-3, -0x1.a2015f6f602f2p-6, + -0x1.8bd4f88642afdp-5, -0x1.0378f010575bfp-4, 0x1.4c2fce639cd0dp-8, -0x1.5904f89180cc0p-5, + 0x1.7b154fb95396bp-6, 0x1.f321d91b4faefp-4, -0x1.1ddbd854c754dp-5, -0x1.312ce5772d4d1p-5, + 0x1.10ce8cb008c2dp-4, 0x1.1c50dd50412f7p-6, 0x1.9be39b889e401p-3, 0x1.0b3290c947de7p-6, + 0x1.6ab158dd9b9b5p-4, 0x1.d6763cdf90038p-6, -0x1.83357c3aaa5b8p-4, -0x1.7e6ebc0b8a14bp-7, + 0x1.4a9c511f07a94p-12, -0x1.d0a4c668ebc1fp-4, 0x1.28deaa62ee40ap-5, -0x1.0267e1f2e0a5fp-2, + -0x1.6d0f1eca7762ep-4, 0x1.58ef3f918bd6dp-5, 0x1.570f392fee3bfp-3, -0x1.6838251c64bb7p-6, + -0x1.b9c4cb2989d1dp-3, 0x1.9f92f1316d59fp-10, -0x1.3d686175b270fp-3, -0x1.06bb4f8a58873p-4, + 0x1.a3c0df822b3a6p-4, 0x1.c5df6975a1005p-5, -0x1.b83622ab633fbp-7, 0x1.bb6b7beb5a14fp-5, + -0x1.a0ccb0103e7e8p-9, -0x1.970284534793bp-3, 0x1.68deb799f9b61p-5, 0x1.45143dd27ee9bp-4, + -0x1.d00970a4a874fp-4, 0x1.5aae16a675621p-4, -0x1.14598c261ffbap-4, 0x1.8ef60db277eb3p-5, + -0x1.3df25da6f1b55p-4, 0x1.3da8b02632297p-9, -0x1.a1a2cd48ace95p-5, -0x1.2362b95935abbp-8, + 0x1.0c7cbaada5dbcp-5, -0x1.a5b9a9c9e0291p-6, -0x1.ff1c7bcd7d666p-8, 0x1.311e06eeb4333p-3, + -0x1.d16795fd5b97fp-9, -0x1.4efce7a7e52e4p-7, -0x1.2502b02a07777p-3, -0x1.9b0a38912a220p-11, + -0x1.b3aa37f537e99p-3, -0x1.b0180e91bd90fp-5, -0x1.9db7f0af478dbp-3, -0x1.dda44abbfe2eep-8, + 0x1.8d04ba8b3ca98p-7, -0x1.2aca7013103b6p-5, -0x1.045877ca41bccp-4, 0x1.23281537cd1a3p-7, + -0x1.7f18163dd8102p-5, 0x1.c8f1f0562176ep-6, -0x1.3a67409d3e98ap-5, -0x1.3552083eddaf6p-6, + -0x1.65e5cae06b979p-5, 0x1.a162d8d7d8e73p-3, -0x1.f929f5bcdbcdep-6, -0x1.4767be4371992p-4, + 0x1.695426bd08cfep-4, -0x1.2a3fc064d82cbp-4, -0x1.fee8854841ac2p-4, -0x1.c512b7b45bc4bp-6, + -0x1.147ef87e7a189p-4, 0x1.41ab3d01c8ed0p-4, -0x1.8ae637b97e466p-4, 0x1.780771c28acf8p-5, + 0x1.41de6e3b18f81p-7, 0x1.50c83a37a275cp-6, -0x1.cc601a39cd48fp-6, -0x1.b97a4536128adp-3, + -0x1.3e7915c3dd372p-6, 0x1.013651286997dp-2, 0x1.2ad59a22ec12cp-3, -0x1.289651f3e8916p-8, + -0x1.988dd5ea13b77p-6, 0x1.699c5952364c9p-5, -0x1.e914d8c37efbfp-4, -0x1.e8400bff2f497p-6, + 0x1.0f6fe46f178f3p-3, 0x1.28601c5e4b01ap-3, -0x1.531eb86378f97p-7, 0x1.0ce34e0758db8p-3, + -0x1.ed1830d8ece64p-6, 0x1.fc93a9159e695p-5, -0x1.c6b5f00276eb0p-4, -0x1.5753933477a2bp-5, + 0x1.30bd4fbcf0bb0p-4, -0x1.ff68c9cea5c69p-5, -0x1.934d1d8e65c1bp-6, -0x1.db045568e8930p-6, + -0x1.9d53931e8d03cp-7, -0x1.e85edf1568f66p-6, -0x1.c6e5ae9a92a6ap-5, 0x1.8fd1a910ad52bp-5, + -0x1.bf0402d6f4f9ep-5, -0x1.19054a29df396p-5, 0x1.1ef3123d97d60p-6, 0x1.451d112b5bf0bp-3, + -0x1.ecdc1856cae0ap-7, 0x1.e862c6801ca40p-7, -0x1.1b46d2636e70ep-4, 0x1.81c4e31cbb8aep-6, + 0x1.81c4e31cbb8aep-6, -0x1.1b46d2636e70ep-4, 0x1.e862c6801ca40p-7, -0x1.ecdc1856cae0ap-7, + 0x1.451d112b5bf0bp-3, 0x1.1ef3123d97d60p-6, -0x1.19054a29df396p-5, -0x1.bf0402d6f4f9ep-5, + 0x1.8fd1a910ad52bp-5, -0x1.c6e5ae9a92a6ap-5, -0x1.e85edf1568f66p-6, -0x1.9d53931e8d03cp-7, + -0x1.db045568e8930p-6, -0x1.934d1d8e65c1bp-6, -0x1.ff68c9cea5c69p-5, 0x1.30bd4fbcf0bb0p-4, + -0x1.5753933477a2bp-5, -0x1.c6b5f00276eb0p-4, 0x1.fc93a9159e695p-5, -0x1.ed1830d8ece64p-6, + 0x1.0ce34e0758db8p-3, -0x1.531eb86378f97p-7, 0x1.28601c5e4b01ap-3, 0x1.0f6fe46f178f3p-3, + -0x1.e8400bff2f497p-6, -0x1.e914d8c37efbfp-4, 0x1.699c5952364c9p-5, -0x1.988dd5ea13b77p-6, + -0x1.289651f3e8916p-8, 0x1.2ad59a22ec12cp-3, 0x1.013651286997dp-2, -0x1.3e7915c3dd372p-6, + -0x1.b97a4536128adp-3, -0x1.cc601a39cd48fp-6, 0x1.50c83a37a275cp-6, 0x1.41de6e3b18f81p-7, + 0x1.780771c28acf8p-5, -0x1.8ae637b97e466p-4, 0x1.41ab3d01c8ed0p-4, -0x1.147ef87e7a189p-4, + -0x1.c512b7b45bc4bp-6, -0x1.fee8854841ac2p-4, -0x1.2a3fc064d82cbp-4, 0x1.695426bd08cfep-4, + -0x1.4767be4371992p-4, -0x1.f929f5bcdbcdep-6, 0x1.a162d8d7d8e73p-3, -0x1.65e5cae06b979p-5, + -0x1.3552083eddaf6p-6, -0x1.3a67409d3e98ap-5, 0x1.c8f1f0562176ep-6, -0x1.7f18163dd8102p-5, + 0x1.23281537cd1a3p-7, -0x1.045877ca41bccp-4, -0x1.2aca7013103b6p-5, 0x1.8d04ba8b3ca98p-7, + -0x1.dda44abbfe2efp-8, -0x1.9db7f0af478dap-3, -0x1.b0180e91bd90ep-5, -0x1.b3aa37f537e98p-3, + -0x1.9b0a38912a162p-11, -0x1.2502b02a07771p-3, -0x1.4efce858a53ddp-7, -0x1.d16713fc640abp-9, + 0x1.76dd9ffb86cd8p-6, -0x1.f7599bc9fc416p-4, -0x1.0c9704413ff0ep-4, 0x1.b3e4d26b55279p-4, + 0x1.9777efeb8dc38p-4, -0x1.360589d6c54f6p-4, -0x1.ebbd8d87336fdp-4, 0x1.1d3444fd9b973p-5, + 0x1.fe1caeb1b6ff0p-4, 0x1.5f6d04094ad99p-7, -0x1.cc1f10833107dp-4, -0x1.c1249d93aa4fap-5, + 0x1.5c77bb9d6e7f4p-4, 0x1.771e752a4383bp-4, -0x1.7c3a9466f54f3p-5, -0x1.db65262e0bbd0p-4, + 0x1.921cfa925d9acp-10, 0x1.fff62460976fap-4, 0x1.64c7dd99917afp-5, -0x1.dfeae7e720a23p-4, + -0x1.532829f024c69p-4, 0x1.7f8eca2710365p-4, 0x1.c678b31debaeap-4, -0x1.d797753c7b966p-5, + -0x1.fce160403c23bp-4, 0x1.c3785c2a94fcdp-7, 0x1.ef17888737f58p-4, 0x1.04fb80ae3187ep-5, + -0x1.9ef440503a726p-4, -0x1.2bedb2ddcef24p-4, 0x1.1734d7212f2c8p-4, 0x1.ad2bc94de11b3p-4, + -0x1.a82a029d42014p-6, -0x1.f4e6062c3090dp-4, -0x1.45576df69f6f3p-6, 0x1.f97f92116543ep-4, + 0x1.01cfc8f32f3c1p-4, -0x1.ba5aa6fd9d094p-4, -0x1.8fbcc9f6d771fp-4, 0x1.3fed95bcb7bc2p-4, + 0x1.e817b81186971p-4, -0x1.35410bb149c6dp-5, -0x1.ff095437913e2p-4, -0x1.f656debf46addp-8, + 0x1.d17e76e4a14a6p-4, 0x1.aa6c864a8abfbp-5, -0x1.65919298abf0ep-4, -0x1.6e744608adacfp-4, + 0x1.9372a718e46c6p-5, 0x1.d69618450d7d7p-4, -0x1.2d86521092f29p-8, -0x1.ffa72d35770ddp-4, + -0x1.4d1e27baa56eep-5, 0x1.e426a44fb898cp-4, 0x1.49a447cfafa6fp-4, -0x1.87c400a6af24bp-4, + -0x1.c08c4041b1b50p-4, 0x1.edc1955465e5dp-5, 0x1.fb579843d900dp-4, -0x1.139f10b506819p-6, + -0x1.f2252fe158642p-4, -0x1.d935007f80309p-6, 0x1.a63090d00bc69p-4, 0x1.21a79b0bbc926p-4, + -0x1.21a79b0bbc926p-4, -0x1.a63090d00bc69p-4, 0x1.d935007f80309p-6, 0x1.f2252fe158642p-4, + 0x1.139f10b506819p-6, -0x1.fb579843d900dp-4, -0x1.edc1955465e5dp-5, 0x1.c08c4041b1b50p-4, + 0x1.87c400a6af24bp-4, -0x1.49a447cfafa6fp-4, -0x1.e426a44fb898cp-4, 0x1.4d1e27baa56eep-5, + 0x1.ffa72d35770ddp-4, 0x1.2d86521092f29p-8, -0x1.d69618450d7d7p-4, -0x1.9372a718e46c6p-5, + 0x1.6e744608adacfp-4, 0x1.65919298abf0ep-4, -0x1.aa6c864a8abfbp-5, -0x1.d17e76e4a14a6p-4, + 0x1.f656debf46addp-8, 0x1.ff095437913e2p-4, 0x1.35410bb149c6dp-5, -0x1.e817b81186971p-4, + -0x1.3fed95bcb7bc2p-4, 0x1.8fbcc9f6d771fp-4, 0x1.ba5aa6fd9d094p-4, -0x1.01cfc8f32f3c1p-4, + -0x1.f97f92116543ep-4, 0x1.45576df69f6f3p-6, 0x1.f4e6062c3090dp-4, 0x1.a82a029d42014p-6, + -0x1.ad2bc94de11b3p-4, -0x1.1734d7212f2c8p-4, 0x1.2bedb2ddcef24p-4, 0x1.9ef440503a726p-4, + -0x1.04fb80ae3187ep-5, -0x1.ef17888737f58p-4, -0x1.c3785c2a94fcdp-7, 0x1.fce160403c23bp-4, + 0x1.d797753c7b966p-5, -0x1.c678b31debaeap-4, -0x1.7f8eca2710365p-4, 0x1.532829f024c69p-4, + 0x1.dfeae7e720a23p-4, -0x1.64c7dd99917afp-5, -0x1.fff62460976fap-4, -0x1.921cfa925d9acp-10, + 0x1.db65262e0bbd0p-4, 0x1.7c3a9466f54f3p-5, -0x1.771e752a4383bp-4, -0x1.5c77bb9d6e7f4p-4, + 0x1.c1249d93aa4fap-5, 0x1.cc1f10833107dp-4, -0x1.5f6d04094ad99p-7, -0x1.fe1caeb1b6ff0p-4, + -0x1.1d3444fd9b973p-5, 0x1.ebbd8d87336fdp-4, 0x1.360589d6c54f6p-4, -0x1.9777efeb8dc38p-4, + -0x1.b3e4d26b55279p-4, 0x1.0c9704413ff0ep-4, 0x1.f7599bc9fc415p-4, -0x1.76dd9ffb86d1ep-6, + 0x1.f7599a72b9261p-4, 0x1.76dd9f8c9c052p-6, 0x1.b3e4d2e735ef5p-4, 0x1.0c9704e7b083ap-4, + 0x1.36058a3021d8dp-4, 0x1.9777f0c3b8425p-4, 0x1.1d344488c19adp-5, 0x1.ebbd8d63feb73p-4, + -0x1.5f6d056945dd0p-7, 0x1.fe1cb05c33d2ep-4, -0x1.c1249c666cc4ap-5, 0x1.cc1f10fcc2284p-4, + -0x1.771e752193a8bp-4, 0x1.5c77bb4d7f1aep-4, -0x1.db65260226f79p-4, 0x1.7c3a96000192cp-5, + -0x1.fff6232ed9aedp-4, 0x1.921cf2e202290p-10, -0x1.dfeae6dcf1b50p-4, -0x1.64c7dc1111c44p-5, + -0x1.7f8eca46ec533p-4, -0x1.5328286a53269p-4, -0x1.d797752da1590p-5, -0x1.c678b24f10548p-4, + -0x1.c3785c1a3bc6dp-7, -0x1.fce15f1785e1bp-4, 0x1.04fb8095af7e7p-5, -0x1.ef1789bbdbaaep-4, + 0x1.2bedb25fc5d28p-4, -0x1.9ef440e3d926dp-4, 0x1.ad2bc9b1198a5p-4, -0x1.1734d699cd022p-4, + 0x1.f4e6064bbe214p-4, -0x1.a82a01677350bp-6, 0x1.f97f90ebcaf7fp-4, 0x1.45576d98f05e9p-6, + 0x1.ba5aa6a49da23p-4, 0x1.01cfc8d0a97dep-4, 0x1.3fed95e6639c5p-4, 0x1.8fbccaf126b0ap-4, + 0x1.35410c593f14fp-5, 0x1.e817b88890befp-4, -0x1.f656dd25b50ddp-8, 0x1.ff095502ad6c1p-4, + -0x1.aa6c84adb694dp-5, 0x1.d17e76a5f63c3p-4, -0x1.6e74469db2372p-4, 0x1.659193322ad73p-4, + -0x1.d696179805583p-4, 0x1.9372a7710f510p-5, -0x1.ffa72e08531a2p-4, 0x1.2d8653e1f2f09p-8, + -0x1.e426a53d995e3p-4, -0x1.4d1e26f2b8b73p-5, -0x1.87c400dae164ap-4, -0x1.49a448afd326bp-4, + -0x1.edc194d744fb1p-5, -0x1.c08c41302ec76p-4, -0x1.139f120ccf57dp-6, -0x1.fb5797e454609p-4, + 0x1.d934ffeb6fa00p-6, -0x1.f2252f0edf072p-4, 0x1.21a799e8a8accp-4, -0x1.a6309141954adp-4, + 0x1.a6309141954adp-4, -0x1.21a799e8a8accp-4, 0x1.f2252f0edf072p-4, -0x1.d934ffeb6fa00p-6, + 0x1.fb5797e454609p-4, 0x1.139f120ccf57dp-6, 0x1.c08c41302ec76p-4, 0x1.edc194d744fb1p-5, + 0x1.49a448afd326bp-4, 0x1.87c400dae164ap-4, 0x1.4d1e26f2b8b73p-5, 0x1.e426a53d995e3p-4, + -0x1.2d8653e1f2f09p-8, 0x1.ffa72e08531a2p-4, -0x1.9372a7710f510p-5, 0x1.d696179805583p-4, + -0x1.659193322ad73p-4, 0x1.6e74469db2372p-4, -0x1.d17e76a5f63c3p-4, 0x1.aa6c84adb694dp-5, + -0x1.ff095502ad6c1p-4, 0x1.f656dd25b50ddp-8, -0x1.e817b88890befp-4, -0x1.35410c593f14fp-5, + -0x1.8fbccaf126b0ap-4, -0x1.3fed95e6639c5p-4, -0x1.01cfc8d0a97dep-4, -0x1.ba5aa6a49da23p-4, + -0x1.45576d98f05e9p-6, -0x1.f97f90ebcaf7fp-4, 0x1.a82a01677350bp-6, -0x1.f4e6064bbe214p-4, + 0x1.1734d699cd022p-4, -0x1.ad2bc9b1198a5p-4, 0x1.9ef440e3d926dp-4, -0x1.2bedb25fc5d28p-4, + 0x1.ef1789bbdbaaep-4, -0x1.04fb8095af7e7p-5, 0x1.fce15f1785e1bp-4, 0x1.c3785c1a3bc6dp-7, + 0x1.c678b24f10548p-4, 0x1.d797752da1590p-5, 0x1.5328286a53269p-4, 0x1.7f8eca46ec533p-4, + 0x1.64c7dc1111c44p-5, 0x1.dfeae6dcf1b50p-4, -0x1.921cf2e202290p-10, 0x1.fff6232ed9aedp-4, + -0x1.7c3a96000192cp-5, 0x1.db65260226f79p-4, -0x1.5c77bb4d7f1aep-4, 0x1.771e752193a8bp-4, + -0x1.cc1f10fcc2284p-4, 0x1.c1249c666cc4ap-5, -0x1.fe1cb05c33d2ep-4, 0x1.5f6d056945dd0p-7, + -0x1.ebbd8d63feb73p-4, -0x1.1d344488c19adp-5, -0x1.9777f0c3b8425p-4, -0x1.36058a3021d8dp-4, + -0x1.0c9704e7b083ap-4, -0x1.b3e4d2e735ef5p-4, -0x1.76dd9f8c9c09dp-6, -0x1.f7599a72b9268p-4, + 0x1.cf7e1bd811ea8p-5, 0x1.e28cf90c2d596p-7, -0x1.1b53cb3c81ec5p-4, -0x1.07c0f0694c242p-4, + 0x1.13a41482e7a43p-5, 0x1.326a4a4da7193p-8, 0x1.a534e97181c3ap-5, -0x1.bf8a82988aa5fp-3, + -0x1.9301b435153f6p-9, 0x1.90ede41cd58b2p-7, 0x1.9d54af37d86c0p-7, 0x1.9fcaf3ff77999p-4, + 0x1.0ef8b2d362335p-3, -0x1.025b38e50a6d7p-7, 0x1.a565ddcd9a57fp-4, -0x1.4181165ab11d3p-4, + -0x1.ffb43758e526ep-4, -0x1.00b97549645f6p-7, -0x1.3547097df3744p-4, 0x1.e5fab536de5b1p-6, + 0x1.4a07b442bde89p-5, -0x1.7a8a99a3c4ea0p-5, 0x1.86d5e542a39dep-4, -0x1.5b03bcb243e23p-4, + 0x1.76a25ef2d43d9p-6, -0x1.ec9bebc4d99aap-3, 0x1.8a7a442125627p-6, 0x1.ba076e48cf9d0p-7, + 0x1.c8efb632ad8eap-5, -0x1.85f62ffda517fp-4, -0x1.5f5b17a945ac4p-4, 0x1.c8e1c57e96bd3p-8, + -0x1.abc8d450ce484p-6, 0x1.7669dbcfdde81p-9, -0x1.c4cceb22e62f9p-6, -0x1.174c2a0abc31cp-6, + 0x1.e8d9955654b2ep-4, -0x1.b7706b9be3ecfp-8, -0x1.6000c5f5385b4p-4, -0x1.1c6ece1dedfd8p-3, + -0x1.d3e5edeb7f8a1p-5, -0x1.96126edb219c0p-4, 0x1.3750be7f6f2c0p-7, 0x1.484bc4fe06fe1p-3, + -0x1.f2bea41d92014p-8, 0x1.369fe99996d2dp-3, -0x1.dad8b81938697p-5, -0x1.5fe12c85a2b71p-4, + 0x1.91f2ea5bce6e7p-7, -0x1.971e5c67513a8p-6, 0x1.24e0dfd6a784ep-4, 0x1.a389dbfa8884fp-7, + -0x1.781e9ad872539p-3, 0x1.05bf90a7cb087p-8, -0x1.3ef9f69495957p-5, -0x1.8152e4156632ap-7, + 0x1.b079017ae87abp-4, 0x1.0ab8d7502b853p-4, -0x1.b3c5790947582p-9, 0x1.17b9c8f697317p-3, + -0x1.7e8db0e4cc489p-7, 0x1.d3c9fe08a566dp-3, 0x1.17ed5fb6d3e7fp-3, -0x1.7499d011a55d4p-4, + 0x1.7499d011a55d4p-4, -0x1.17ed5fb6d3e7fp-3, -0x1.d3c9fe08a566dp-3, 0x1.7e8db0e4cc489p-7, + -0x1.17b9c8f697317p-3, 0x1.b3c5790947582p-9, -0x1.0ab8d7502b853p-4, -0x1.b079017ae87abp-4, + 0x1.8152e4156632ap-7, 0x1.3ef9f69495957p-5, -0x1.05bf90a7cb087p-8, 0x1.781e9ad872539p-3, + -0x1.a389dbfa8884fp-7, -0x1.24e0dfd6a784ep-4, 0x1.971e5c67513a8p-6, -0x1.91f2ea5bce6e7p-7, + 0x1.5fe12c85a2b71p-4, 0x1.dad8b81938697p-5, -0x1.369fe99996d2dp-3, 0x1.f2bea41d92014p-8, + -0x1.484bc4fe06fe1p-3, -0x1.3750be7f6f2c0p-7, 0x1.96126edb219c0p-4, 0x1.d3e5edeb7f8a1p-5, + 0x1.1c6ece1dedfd8p-3, 0x1.6000c5f5385b4p-4, 0x1.b7706b9be3ecfp-8, -0x1.e8d9955654b2ep-4, + 0x1.174c2a0abc31cp-6, 0x1.c4cceb22e62f9p-6, -0x1.7669dbcfdde81p-9, 0x1.abc8d450ce484p-6, + -0x1.c8e1c57e96bd3p-8, 0x1.5f5b17a945ac4p-4, 0x1.85f62ffda517fp-4, -0x1.c8efb632ad8eap-5, + -0x1.ba076e48cf9d0p-7, -0x1.8a7a442125627p-6, 0x1.ec9bebc4d99aap-3, -0x1.76a25ef2d43d9p-6, + 0x1.5b03bcb243e23p-4, -0x1.86d5e542a39dep-4, 0x1.7a8a99a3c4ea0p-5, -0x1.4a07b442bde89p-5, + -0x1.e5fab536de5b1p-6, 0x1.3547097df3744p-4, 0x1.00b97549645f6p-7, 0x1.ffb43758e526ep-4, + 0x1.4181165ab11d3p-4, -0x1.a565ddcd9a57fp-4, 0x1.025b38e50a6d7p-7, -0x1.0ef8b2d362335p-3, + -0x1.9fcaf3ff77999p-4, -0x1.9d54af37d86c0p-7, -0x1.90ede41cd58b2p-7, 0x1.9301b435153f6p-9, + 0x1.bf8a82988aa5fp-3, -0x1.a534e97181c3ap-5, -0x1.326a4a4da71adp-8, -0x1.13a41482e7a40p-5, + 0x1.07c0f0694c24bp-4, 0x1.1b53cb3c81ec1p-4, -0x1.e28cf57ab0a71p-7, -0x1.cf7e1bd7160dep-5, + 0x1.29879f8455c04p-6, -0x1.377cf26ab9411p-3, 0x1.1ae95c05bb8afp-4, 0x1.33d3da5185e2ap-6, + -0x1.3c7bccb5888c3p-4, 0x1.b36da1f144894p-4, -0x1.101def015cca3p-4, -0x1.540dc23bdc405p-6, + -0x1.7caf696f1aca7p-5, -0x1.8f515f4d3d060p-7, -0x1.4e827f444ef19p-5, -0x1.36cf25882eb41p-4, + 0x1.ccafac43eeabdp-5, -0x1.39da769dc7a57p-4, 0x1.717b9503df79ep-4, 0x1.b7f694fbea300p-7, + 0x1.f5ef6add45851p-8, 0x1.8a6d9541cf276p-4, 0x1.63a3ac86ba6a0p-5, -0x1.de0d7209988a7p-6, + -0x1.22fe7059ec0c0p-3, -0x1.7afab47f8b633p-4, 0x1.ca2384e55cc4cp-4, 0x1.24a7c2087ba58p-4, + -0x1.1fbd4a1109920p-3, -0x1.e76b4b542336cp-10, -0x1.e9eb05a013c77p-3, 0x1.ecac490caa78cp-5, + 0x1.8a0cda46f246dp-4, -0x1.f8e08ee90fb82p-5, 0x1.3619fa6deccbap-4, 0x1.82fe9870e8cf7p-4, + 0x1.8404e0b74b512p-6, 0x1.a3a032bf1b947p-5, -0x1.09764c0c0018cp-6, 0x1.1943a4c521594p-4, + 0x1.24460f2ad44d9p-4, -0x1.6e52ba5aff60dp-4, 0x1.9fe8fc79f823fp-3, 0x1.0c5a7fa605c21p-4, + -0x1.062d7762b4878p-2, 0x1.a18a63c7166e6p-9, 0x1.b150fd775c2cbp-5, -0x1.fd8d01e60f9e7p-8, + -0x1.1d6e05cb9e75bp-4, -0x1.04ba171fc9b69p-5, 0x1.8ab83650570b2p-5, 0x1.a9dc7db17587dp-4, + 0x1.4b2b5be2fec78p-5, 0x1.bbe61026cdeb9p-3, 0x1.ff6554211b793p-6, -0x1.1a22dbcbce618p-10, + -0x1.22174480f33c1p-5, 0x1.7144633ab627bp-5, -0x1.656f73019f1a8p-4, 0x1.46080a3a8132ap-4, + 0x1.da187030fc4ecp-4, -0x1.e51312a89eb42p-5, 0x1.417cb6e11ab6ap-4, 0x1.9ab1b022bc1cep-6, + -0x1.72e0c7e32325ap-6, 0x1.bdd2075c4097ep-7, 0x1.3e43697f7c1fbp-4, 0x1.03ccd0a70c2b0p-4, + -0x1.03ccd0a70c2b0p-4, -0x1.3e43697f7c1fbp-4, -0x1.bdd2075c4097ep-7, 0x1.72e0c7e32325ap-6, + -0x1.9ab1b022bc1cep-6, -0x1.417cb6e11ab6ap-4, 0x1.e51312a89eb42p-5, -0x1.da187030fc4ecp-4, + -0x1.46080a3a8132ap-4, 0x1.656f73019f1a8p-4, -0x1.7144633ab627bp-5, 0x1.22174480f33c1p-5, + 0x1.1a22dbcbce618p-10, -0x1.ff6554211b793p-6, -0x1.bbe61026cdeb9p-3, -0x1.4b2b5be2fec78p-5, + -0x1.a9dc7db17587dp-4, -0x1.8ab83650570b2p-5, 0x1.04ba171fc9b69p-5, 0x1.1d6e05cb9e75bp-4, + 0x1.fd8d01e60f9e7p-8, -0x1.b150fd775c2cbp-5, -0x1.a18a63c7166e6p-9, 0x1.062d7762b4878p-2, + -0x1.0c5a7fa605c21p-4, -0x1.9fe8fc79f823fp-3, 0x1.6e52ba5aff60dp-4, -0x1.24460f2ad44d9p-4, + -0x1.1943a4c521594p-4, 0x1.09764c0c0018cp-6, -0x1.a3a032bf1b947p-5, -0x1.8404e0b74b512p-6, + -0x1.82fe9870e8cf7p-4, -0x1.3619fa6deccbap-4, 0x1.f8e08ee90fb82p-5, -0x1.8a0cda46f246dp-4, + -0x1.ecac490caa78cp-5, 0x1.e9eb05a013c77p-3, 0x1.e76b4b542336cp-10, 0x1.1fbd4a1109920p-3, + -0x1.24a7c2087ba58p-4, -0x1.ca2384e55cc4cp-4, 0x1.7afab47f8b633p-4, 0x1.22fe7059ec0c0p-3, + 0x1.de0d7209988a7p-6, -0x1.63a3ac86ba6a0p-5, -0x1.8a6d9541cf276p-4, -0x1.f5ef6add45851p-8, + -0x1.b7f694fbea300p-7, -0x1.717b9503df79ep-4, 0x1.39da769dc7a57p-4, -0x1.ccafac43eeabdp-5, + 0x1.36cf25882eb41p-4, 0x1.4e827f444ef19p-5, 0x1.8f515f4d3d060p-7, 0x1.7caf696f1aca7p-5, + 0x1.540dc23bdc405p-6, 0x1.101def015cca4p-4, -0x1.b36da1f144893p-4, 0x1.3c7bccb5888c0p-4, + -0x1.33d3da5185e23p-6, -0x1.1ae95c05bb8bcp-4, 0x1.377cf26e19de8p-3, -0x1.298798e77af32p-6, + 0x1.45576a72fc6c6p-6, -0x1.f97f942da32edp-4, -0x1.d797723bc0851p-5, 0x1.c678b00344184p-4, + 0x1.6e74453415929p-4, -0x1.659192faba609p-4, -0x1.cc1f10b8a6e77p-4, 0x1.c124a107e864dp-5, + 0x1.fb5796ea1b3eap-4, -0x1.139f0e48ab87cp-6, -0x1.f7599b92556ebp-4, -0x1.76dd956683c81p-6, + 0x1.c08c4118b8dbcp-4, 0x1.edc1984fe0a56p-5, -0x1.5c77ba5231578p-4, -0x1.771e77ba2debdp-4, + 0x1.aa6c8109a7f4fp-5, 0x1.d17e76d9cdac0p-4, -0x1.c3786c8306cb3p-7, -0x1.fce15f36e2740p-4, + -0x1.a82a08d3422c0p-6, 0x1.f4e60488f88a1p-4, 0x1.01cfc85739250p-4, -0x1.ba5aa6f1bb646p-4, + -0x1.7f8ecf1081b42p-4, 0x1.532829896dca8p-4, 0x1.d696171003c1fp-4, -0x1.9372aa1698055p-5, + -0x1.fe1cad4dee519p-4, 0x1.5f6d007d84c0cp-7, 0x1.f2252dad9ce3ep-4, 0x1.d934fb61fcf88p-6, + -0x1.b3e4d509757d9p-4, -0x1.0c97043b24236p-4, 0x1.49a4480d351e9p-4, 0x1.87c40295909f7p-4, + -0x1.7c3a8b6dd151cp-5, -0x1.db6523b2cde76p-4, 0x1.f656cd6e34be2p-8, 0x1.ff0958dbb8917p-4, + 0x1.04fb7dffde635p-5, -0x1.ef178accd40f4p-4, -0x1.1734d88ee1c5ep-4, 0x1.ad2bcd1ecd012p-4, + 0x1.8fbcc9bbfb12ap-4, -0x1.3fed94c89c8cdp-4, -0x1.dfeae6a123501p-4, 0x1.64c7dba1b9d0cp-5, + 0x1.ffa72ba27798ep-4, -0x1.2d8657d3dbbd0p-8, -0x1.ebbd8b0d3ee9dp-4, -0x1.1d3444156ad34p-5, + 0x1.a63093311bf94p-4, 0x1.21a79bdfc40cbp-4, -0x1.36058c7a5178dp-4, -0x1.9777f10d81269p-4, + 0x1.4d1e28ae40ab9p-5, 0x1.e426a5374bd5ep-4, -0x1.921d01da9ada0p-10, -0x1.fff620d46b002p-4, + -0x1.35410815db7e5p-5, 0x1.e817b9eb524a1p-4, 0x1.2bedb18cc7b43p-4, -0x1.9ef43e431b5fap-4, + -0x1.9ef43e431b5fap-4, 0x1.2bedb18cc7b43p-4, 0x1.e817b9eb524a1p-4, -0x1.35410815db7e5p-5, + -0x1.fff620d46b002p-4, -0x1.921d01da9ada0p-10, 0x1.e426a5374bd5ep-4, 0x1.4d1e28ae40ab9p-5, + -0x1.9777f10d81269p-4, -0x1.36058c7a5178dp-4, 0x1.21a79bdfc40cbp-4, 0x1.a63093311bf94p-4, + -0x1.1d3444156ad34p-5, -0x1.ebbd8b0d3ee9dp-4, -0x1.2d8657d3dbbd0p-8, 0x1.ffa72ba27798ep-4, + 0x1.64c7dba1b9d0cp-5, -0x1.dfeae6a123501p-4, -0x1.3fed94c89c8cdp-4, 0x1.8fbcc9bbfb12ap-4, + 0x1.ad2bcd1ecd012p-4, -0x1.1734d88ee1c5ep-4, -0x1.ef178accd40f4p-4, 0x1.04fb7dffde635p-5, + 0x1.ff0958dbb8917p-4, 0x1.f656cd6e34be2p-8, -0x1.db6523b2cde76p-4, -0x1.7c3a8b6dd151cp-5, + 0x1.87c40295909f7p-4, 0x1.49a4480d351e9p-4, -0x1.0c97043b24236p-4, -0x1.b3e4d509757d9p-4, + 0x1.d934fb61fcf88p-6, 0x1.f2252dad9ce3ep-4, 0x1.5f6d007d84c0cp-7, -0x1.fe1cad4dee519p-4, + -0x1.9372aa1698055p-5, 0x1.d696171003c1fp-4, 0x1.532829896dca8p-4, -0x1.7f8ecf1081b42p-4, + -0x1.ba5aa6f1bb646p-4, 0x1.01cfc85739250p-4, 0x1.f4e60488f88a1p-4, -0x1.a82a08d3422c0p-6, + -0x1.fce15f36e2740p-4, -0x1.c3786c8306cb3p-7, 0x1.d17e76d9cdac0p-4, 0x1.aa6c8109a7f4fp-5, + -0x1.771e77ba2debdp-4, -0x1.5c77ba5231578p-4, 0x1.edc1984fe0a56p-5, 0x1.c08c4118b8dbcp-4, + -0x1.76dd956683c81p-6, -0x1.f7599b92556ebp-4, -0x1.139f0e48ab87cp-6, 0x1.fb5796ea1b3eap-4, + 0x1.c124a107e864dp-5, -0x1.cc1f10b8a6e77p-4, -0x1.659192faba609p-4, 0x1.6e74453415929p-4, + 0x1.c678b00344184p-4, -0x1.d797723bc0851p-5, -0x1.f97f942da32edp-4, 0x1.45576a72fc75fp-6, + 0x1.f97f94e5cf345p-4, 0x1.455769efcc9ffp-6, 0x1.c678b12d3841fp-4, 0x1.d79771d37e573p-5, + 0x1.65919197907b8p-4, 0x1.6e744505f6824p-4, 0x1.c124a10965b70p-5, 0x1.cc1f107ccececp-4, + 0x1.139f0e67828fep-6, 0x1.fb57978492496p-4, -0x1.76dd95660280fp-6, 0x1.f7599c3237414p-4, + -0x1.edc197bf30391p-5, 0x1.c08c428d2427ap-4, -0x1.771e7807ee0bep-4, 0x1.5c77b9afffe24p-4, + -0x1.d17e76b51035bp-4, 0x1.aa6c804b53addp-5, -0x1.fce15e2ef1cc4p-4, 0x1.c3786c21ec106p-7, + -0x1.f4e604b450ffcp-4, -0x1.a82a07e3fed72p-6, -0x1.ba5aa5b765157p-4, -0x1.01cfc80122ca0p-4, + -0x1.53282a46a3f7dp-4, -0x1.7f8ecf1cbc9b9p-4, -0x1.9372a9ab096d0p-5, -0x1.d696186a47df5p-4, + -0x1.5f6cff896ed3cp-7, -0x1.fe1cae1f5274ep-4, 0x1.d934fba56c13bp-6, -0x1.f2252dc502587p-4, + 0x1.0c9704178201ep-4, -0x1.b3e4d4d252a44p-4, 0x1.87c4015ce4e1dp-4, -0x1.49a44854ad46ap-4, + 0x1.db6524bfd6e20p-4, -0x1.7c3a8ba6e3510p-5, 0x1.ff095952dafc9p-4, -0x1.f656cdc2819f6p-8, + 0x1.ef17899e160d6p-4, 0x1.04fb7eb4de0fdp-5, 0x1.ad2bcbfe1429dp-4, 0x1.1734d82ae7c59p-4, + 0x1.3fed93d538b95p-4, 0x1.8fbcc982f8c08p-4, 0x1.64c7dbd9f6a13p-5, 0x1.dfeae5fd20620p-4, + 0x1.2d86582394183p-8, 0x1.ffa72d7dfa11bp-4, -0x1.1d34444926c8ap-5, 0x1.ebbd8aa1c2aaap-4, + -0x1.21a79c0a19bf6p-4, 0x1.a630943648376p-4, -0x1.9777f0231a52dp-4, 0x1.36058cc41c86bp-4, + -0x1.e426a41ede5b1p-4, 0x1.4d1e288142936p-5, -0x1.fff6200d50807p-4, 0x1.921d02dc808f8p-10, + -0x1.e817b9d637e52p-4, -0x1.3541076e64f6bp-5, -0x1.9ef43e3f0db09p-4, -0x1.2bedb2955d065p-4, + -0x1.2bedb2955d065p-4, -0x1.9ef43e3f0db09p-4, -0x1.3541076e64f6bp-5, -0x1.e817b9d637e52p-4, + 0x1.921d02dc808f8p-10, -0x1.fff6200d50807p-4, 0x1.4d1e288142936p-5, -0x1.e426a41ede5b1p-4, + 0x1.36058cc41c86bp-4, -0x1.9777f0231a52dp-4, 0x1.a630943648376p-4, -0x1.21a79c0a19bf6p-4, + 0x1.ebbd8aa1c2aaap-4, -0x1.1d34444926c8ap-5, 0x1.ffa72d7dfa11bp-4, 0x1.2d86582394183p-8, + 0x1.dfeae5fd20620p-4, 0x1.64c7dbd9f6a13p-5, 0x1.8fbcc982f8c08p-4, 0x1.3fed93d538b95p-4, + 0x1.1734d82ae7c59p-4, 0x1.ad2bcbfe1429dp-4, 0x1.04fb7eb4de0fdp-5, 0x1.ef17899e160d6p-4, + -0x1.f656cdc2819f6p-8, 0x1.ff095952dafc9p-4, -0x1.7c3a8ba6e3510p-5, 0x1.db6524bfd6e20p-4, + -0x1.49a44854ad46ap-4, 0x1.87c4015ce4e1dp-4, -0x1.b3e4d4d252a44p-4, 0x1.0c9704178201ep-4, + -0x1.f2252dc502587p-4, 0x1.d934fba56c13bp-6, -0x1.fe1cae1f5274ep-4, -0x1.5f6cff896ed3cp-7, + -0x1.d696186a47df5p-4, -0x1.9372a9ab096d0p-5, -0x1.7f8ecf1cbc9b9p-4, -0x1.53282a46a3f7dp-4, + -0x1.01cfc80122ca0p-4, -0x1.ba5aa5b765157p-4, -0x1.a82a07e3fed72p-6, -0x1.f4e604b450ffcp-4, + 0x1.c3786c21ec106p-7, -0x1.fce15e2ef1cc4p-4, 0x1.aa6c804b53addp-5, -0x1.d17e76b51035bp-4, + 0x1.5c77b9afffe24p-4, -0x1.771e7807ee0bep-4, 0x1.c08c428d2427ap-4, -0x1.edc197bf30391p-5, + 0x1.f7599c3237414p-4, -0x1.76dd95660280fp-6, 0x1.fb57978492496p-4, 0x1.139f0e67828fep-6, + 0x1.cc1f107ccececp-4, 0x1.c124a10965b70p-5, 0x1.6e744505f6824p-4, 0x1.65919197907b8p-4, + 0x1.d79771d37e573p-5, 0x1.c678b12d3841fp-4, 0x1.455769efcc9c6p-6, 0x1.f97f94e5cf347p-4, + -0x1.06e7468f03c68p-4, 0x1.78a571b6bc37bp-6, 0x1.0984cfc30011ep-4, -0x1.09ca2d9425127p-4, + -0x1.70720650c04cfp-5, -0x1.27f084577ca7ap-5, -0x1.5b333b213bc97p-4, 0x1.40f3eefb37dbfp-7, + -0x1.b26745d7ca2cfp-6, 0x1.179b781926bfap-6, -0x1.37c8a4f7248dep-6, 0x1.5abcf88418b34p-3, + 0x1.8459fce6dbf76p-4, 0x1.be6369267aa05p-6, 0x1.811cb48dbca96p-5, 0x1.005d6808d1ec0p-4, + 0x1.997db73f62bd2p-4, -0x1.098f234284dfep-7, 0x1.22276f5aa9738p-2, -0x1.a41b941b22600p-7, + -0x1.a8ff2de71ba7ap-3, -0x1.74f0f2f1af31bp-5, 0x1.83a985778be79p-5, -0x1.ed73001ea1c44p-5, + -0x1.1e6bfdc7d8122p-5, 0x1.d5a8a4d11eac4p-4, -0x1.0b5cb90a86fc5p-4, -0x1.7ce8d39bd35bfp-3, + 0x1.b77ecfdd68f54p-8, -0x1.332e9c6c14a7ep-4, -0x1.b27004366570cp-6, -0x1.9f8594bedb9f9p-8, + 0x1.de059d8fd7356p-4, -0x1.88adccfdc8554p-7, 0x1.154d5413aa161p-7, 0x1.0afb443c53b5ep-5, + -0x1.efd99c9957fbfp-5, -0x1.cc808934feb03p-4, -0x1.24376c2aac2f3p-4, -0x1.34f7542d9fa06p-7, + -0x1.21a88b3e2ee04p-3, 0x1.a3b23a4373580p-7, 0x1.33d32eb9e7c41p-3, 0x1.72064e7c44861p-7, + -0x1.3a6e4b53ae3dep-5, 0x1.2af4f36fae9e3p-4, 0x1.07c2303361247p-4, 0x1.060c23af2f2a7p-3, + -0x1.f6845c522dcc8p-8, 0x1.1765e09937efbp-4, 0x1.fc519a96a71e5p-5, 0x1.200413ed7df25p-4, + 0x1.82f6aeb588dbfp-4, 0x1.b99a027a48776p-4, -0x1.c37d98abd1a3ep-6, 0x1.a06f81ff05cb9p-12, + 0x1.cf44c05be62b5p-3, -0x1.ce6df0438e94bp-4, 0x1.c2a99c2d9b43ep-4, 0x1.6fabaa120ba9dp-8, + -0x1.62389d284c721p-5, -0x1.a97fa8abad110p-7, 0x1.8c5675c535076p-4, 0x1.58cbbbb9c4d7ap-6, + 0x1.58cbbbb9c4d7ap-6, 0x1.8c5675c535076p-4, -0x1.a97fa8abad110p-7, -0x1.62389d284c721p-5, + 0x1.6fabaa120ba9dp-8, 0x1.c2a99c2d9b43ep-4, -0x1.ce6df0438e94bp-4, 0x1.cf44c05be62b5p-3, + 0x1.a06f81ff05cb9p-12, -0x1.c37d98abd1a3ep-6, 0x1.b99a027a48776p-4, 0x1.82f6aeb588dbfp-4, + 0x1.200413ed7df25p-4, 0x1.fc519a96a71e5p-5, 0x1.1765e09937efbp-4, -0x1.f6845c522dcc8p-8, + 0x1.060c23af2f2a7p-3, 0x1.07c2303361247p-4, 0x1.2af4f36fae9e3p-4, -0x1.3a6e4b53ae3dep-5, + 0x1.72064e7c44861p-7, 0x1.33d32eb9e7c41p-3, 0x1.a3b23a4373580p-7, -0x1.21a88b3e2ee04p-3, + -0x1.34f7542d9fa06p-7, -0x1.24376c2aac2f3p-4, -0x1.cc808934feb03p-4, -0x1.efd99c9957fbfp-5, + 0x1.0afb443c53b5ep-5, 0x1.154d5413aa161p-7, -0x1.88adccfdc8554p-7, 0x1.de059d8fd7356p-4, + -0x1.9f8594bedb9f9p-8, -0x1.b27004366570cp-6, -0x1.332e9c6c14a7ep-4, 0x1.b77ecfdd68f54p-8, + -0x1.7ce8d39bd35bfp-3, -0x1.0b5cb90a86fc5p-4, 0x1.d5a8a4d11eac4p-4, -0x1.1e6bfdc7d8122p-5, + -0x1.ed73001ea1c44p-5, 0x1.83a985778be79p-5, -0x1.74f0f2f1af31bp-5, -0x1.a8ff2de71ba7ap-3, + -0x1.a41b941b22600p-7, 0x1.22276f5aa9738p-2, -0x1.098f234284dfep-7, 0x1.997db73f62bd2p-4, + 0x1.005d6808d1ec0p-4, 0x1.811cb48dbca96p-5, 0x1.be6369267aa05p-6, 0x1.8459fce6dbf76p-4, + 0x1.5abcf88418b34p-3, -0x1.37c8a4f7248dep-6, 0x1.179b781926bfap-6, -0x1.b26745d7ca2cfp-6, + 0x1.40f3eefb37dbfp-7, -0x1.5b333b213bc97p-4, -0x1.27f084577ca8ap-5, -0x1.70720650c04d0p-5, + -0x1.09ca2d9425119p-4, 0x1.0984cfc30011bp-4, 0x1.78a5774ffefc8p-6, -0x1.06e746e8016cep-4, + -0x1.46d7a4b43f7dap-6, 0x1.2e8448f4733e5p-5, -0x1.5d8176332772fp-5, -0x1.5eaefa3ce3d93p-5, + 0x1.6c2e03434b2b2p-4, -0x1.74ace0af9497cp-3, -0x1.2b3d0497093c5p-8, 0x1.9653dd852a74dp-5, + 0x1.6f7953bb0ae70p-4, -0x1.cd2ceb9212a3bp-7, 0x1.15954fe4c1303p-3, 0x1.ad02144080892p-5, + -0x1.4511af8b1bce4p-3, 0x1.0d21c97810ed4p-7, 0x1.d243bd8d92217p-5, 0x1.d5db741e11b86p-5, + 0x1.6954cc1ced373p-7, 0x1.c70c6a74f001ap-5, 0x1.d408124616fabp-5, -0x1.607b2e9724ceap-3, + -0x1.dff66ec775b6dp-5, -0x1.66944a1325f06p-4, -0x1.a744c151afb2dp-7, 0x1.691824bd7bf23p-5, + -0x1.2cc16a4a930d4p-3, -0x1.e82b42fd9d3a5p-4, -0x1.b20ae97ec4b36p-4, -0x1.317f47f2db402p-7, + 0x1.fe1d28ea3886bp-3, 0x1.e069613e3b056p-8, -0x1.9ee4fccf5a5aep-5, -0x1.24134df772027p-5, + 0x1.80cce4f460f27p-7, 0x1.d0492cf77aef3p-10, -0x1.f484d674b3f02p-10, 0x1.cf51786383033p-5, + 0x1.84450039fdb2cp-5, 0x1.be71f8e23cbe2p-3, -0x1.776734bd60efdp-6, 0x1.515bf9b1bf364p-4, + -0x1.6b108dd81894ep-4, -0x1.6d2e80a19c00ep-5, 0x1.c6053d313fadcp-5, 0x1.0819330ecc2a8p-4, + -0x1.af0c85094941bp-4, -0x1.1c2cfec10a31fp-3, -0x1.c50c28d73f0b8p-4, 0x1.930917cd9f3d6p-8, + -0x1.0a6daca274773p-4, -0x1.d07eb188c807fp-9, -0x1.6dcaa707b5362p-3, 0x1.ca5353e2d5a29p-6, + 0x1.a03d8206d27c6p-6, -0x1.ebf8ca07d71fdp-6, -0x1.107ef11459fb7p-5, -0x1.0e72fb74e6ccdp-3, + 0x1.0d487c8a795f0p-4, 0x1.4db829b1ed1c9p-3, 0x1.fc381c6dcee6ap-6, 0x1.2a32693c1504dp-5, + -0x1.6748f586b22e3p-6, 0x1.ee4a50786115dp-9, -0x1.01fa9335fa592p-3, -0x1.00f8e50d3f00ep-5, + -0x1.00f8e50d3f00ep-5, -0x1.01fa9335fa592p-3, 0x1.ee4a50786115dp-9, -0x1.6748f586b22e3p-6, + 0x1.2a32693c1504dp-5, 0x1.fc381c6dcee6ap-6, 0x1.4db829b1ed1c9p-3, 0x1.0d487c8a795f0p-4, + -0x1.0e72fb74e6ccdp-3, -0x1.107ef11459fb7p-5, -0x1.ebf8ca07d71fdp-6, 0x1.a03d8206d27c6p-6, + 0x1.ca5353e2d5a29p-6, -0x1.6dcaa707b5362p-3, -0x1.d07eb188c807fp-9, -0x1.0a6daca274773p-4, + 0x1.930917cd9f3d6p-8, -0x1.c50c28d73f0b8p-4, -0x1.1c2cfec10a31fp-3, -0x1.af0c85094941bp-4, + 0x1.0819330ecc2a8p-4, 0x1.c6053d313fadcp-5, -0x1.6d2e80a19c00ep-5, -0x1.6b108dd81894ep-4, + 0x1.515bf9b1bf364p-4, -0x1.776734bd60efdp-6, 0x1.be71f8e23cbe2p-3, 0x1.84450039fdb2cp-5, + 0x1.cf51786383033p-5, -0x1.f484d674b3f02p-10, 0x1.d0492cf77aef3p-10, 0x1.80cce4f460f27p-7, + -0x1.24134df772027p-5, -0x1.9ee4fccf5a5aep-5, 0x1.e069613e3b056p-8, 0x1.fe1d28ea3886bp-3, + -0x1.317f47f2db402p-7, -0x1.b20ae97ec4b36p-4, -0x1.e82b42fd9d3a5p-4, -0x1.2cc16a4a930d4p-3, + 0x1.691824bd7bf23p-5, -0x1.a744c151afb2dp-7, -0x1.66944a1325f06p-4, -0x1.dff66ec775b6dp-5, + -0x1.607b2e9724ceap-3, 0x1.d408124616fabp-5, 0x1.c70c6a74f001ap-5, 0x1.6954cc1ced373p-7, + 0x1.d5db741e11b86p-5, 0x1.d243bd8d92217p-5, 0x1.0d21c97810ed4p-7, -0x1.4511af8b1bce4p-3, + 0x1.ad02144080892p-5, 0x1.15954fe4c1303p-3, -0x1.cd2ceb9212a3bp-7, 0x1.6f7953bb0ae70p-4, + 0x1.9653dd852a74dp-5, -0x1.2b3d0497093c5p-8, -0x1.74ace0af9497dp-3, 0x1.6c2e03434b2b6p-4, + -0x1.5eaefa3ce3d8fp-5, -0x1.5d81763327732p-5, 0x1.2e8449663411dp-5, -0x1.46d798be37e73p-6, + 0x1.139f0c49fa666p-6, -0x1.fb5799ba6001cp-4, -0x1.9372a3d27e140p-5, 0x1.d6961473c2564p-4, + 0x1.3fed922fbcd70p-4, -0x1.8fbccaf2a48c8p-4, -0x1.9ef43f6762a7bp-4, 0x1.2bedb0c26eb77p-4, + 0x1.dfeae4a86a953p-4, -0x1.64c7dd7136963p-5, -0x1.fe1caff93874dp-4, 0x1.5f6cf9964612ep-7, + 0x1.f7599c551eaacp-4, 0x1.76dd9c2c514a2p-6, -0x1.cc1f0dd89e036p-4, -0x1.c124a18a97edcp-5, + 0x1.7f8ecf9c56eadp-4, 0x1.53282a6d04965p-4, -0x1.1734d296ef4bbp-4, -0x1.ad2bc9cf5c434p-4, + 0x1.35410c9d565f8p-5, 0x1.e817ba191ba78p-4, -0x1.2d8656673ef11p-8, -0x1.ffa72d2ad8987p-4, + -0x1.d934fd1ac77d6p-6, 0x1.f2252fcfd3269p-4, 0x1.edc19305cf0d0p-5, -0x1.c08c43aad937cp-4, + -0x1.65919268f83b6p-4, 0x1.6e744791783f6p-4, 0x1.ba5aa7481eb37p-4, -0x1.01cfc83faf88cp-4, + -0x1.ef178d181fa1ap-4, 0x1.04fb82ee4537bp-5, 0x1.fff620a97bdd7p-4, 0x1.921d67f33f548p-10, + -0x1.ebbd8da2fd06dp-4, -0x1.1d3440bf0aa10p-5, 0x1.b3e4d51359695p-4, 0x1.0c9704783bc2ap-4, + -0x1.5c77bcd9d59b6p-4, -0x1.771e754a5a8e7p-4, 0x1.d79777b90f167p-5, 0x1.c678b308fcd37p-4, + -0x1.a82a068317ed6p-6, -0x1.f4e5ffbf6df65p-4, -0x1.f656f2be811b6p-8, 0x1.ff0956a6dd5eap-4, + 0x1.4d1e23dcdfbe0p-5, -0x1.e426a282f361ep-4, -0x1.21a79a26c98afp-4, 0x1.a6308f923472ap-4, + 0x1.87c4025d3a38ap-4, -0x1.49a44ba692099p-4, -0x1.d17e76bf26b8dp-4, 0x1.aa6c836f2a62fp-5, + 0x1.f97f91e46ccb6p-4, -0x1.45576df11df95p-6, -0x1.fce15ef07517ep-4, -0x1.c378610bcd665p-7, + 0x1.db65284236eddp-4, 0x1.7c3a943c383b7p-5, -0x1.9777ef34acde2p-4, -0x1.36058d370ed58p-4, + 0x1.36058d370ed58p-4, 0x1.9777ef34acde2p-4, -0x1.7c3a943c383b7p-5, -0x1.db65284236eddp-4, + 0x1.c378610bcd665p-7, 0x1.fce15ef07517ep-4, 0x1.45576df11df95p-6, -0x1.f97f91e46ccb6p-4, + -0x1.aa6c836f2a62fp-5, 0x1.d17e76bf26b8dp-4, 0x1.49a44ba692099p-4, -0x1.87c4025d3a38ap-4, + -0x1.a6308f923472ap-4, 0x1.21a79a26c98afp-4, 0x1.e426a282f361ep-4, -0x1.4d1e23dcdfbe0p-5, + -0x1.ff0956a6dd5eap-4, 0x1.f656f2be811b6p-8, 0x1.f4e5ffbf6df65p-4, 0x1.a82a068317ed6p-6, + -0x1.c678b308fcd37p-4, -0x1.d79777b90f167p-5, 0x1.771e754a5a8e7p-4, 0x1.5c77bcd9d59b6p-4, + -0x1.0c9704783bc2ap-4, -0x1.b3e4d51359695p-4, 0x1.1d3440bf0aa10p-5, 0x1.ebbd8da2fd06dp-4, + -0x1.921d67f33f548p-10, -0x1.fff620a97bdd7p-4, -0x1.04fb82ee4537bp-5, 0x1.ef178d181fa1ap-4, + 0x1.01cfc83faf88cp-4, -0x1.ba5aa7481eb37p-4, -0x1.6e744791783f6p-4, 0x1.65919268f83b6p-4, + 0x1.c08c43aad937cp-4, -0x1.edc19305cf0d0p-5, -0x1.f2252fcfd3269p-4, 0x1.d934fd1ac77d6p-6, + 0x1.ffa72d2ad8987p-4, 0x1.2d8656673ef11p-8, -0x1.e817ba191ba78p-4, -0x1.35410c9d565f8p-5, + 0x1.ad2bc9cf5c434p-4, 0x1.1734d296ef4bbp-4, -0x1.53282a6d04965p-4, -0x1.7f8ecf9c56eadp-4, + 0x1.c124a18a97edcp-5, 0x1.cc1f0dd89e036p-4, -0x1.76dd9c2c514a2p-6, -0x1.f7599c551eaacp-4, + -0x1.5f6cf9964612ep-7, 0x1.fe1caff93874dp-4, 0x1.64c7dd7136963p-5, -0x1.dfeae4a86a953p-4, + -0x1.2bedb0c26eb77p-4, 0x1.9ef43f6762a7bp-4, 0x1.8fbccaf2a48c8p-4, -0x1.3fed922fbcd70p-4, + -0x1.d6961473c2564p-4, 0x1.9372a3d27e140p-5, 0x1.fb5799ba6001cp-4, -0x1.139f0c49fa67ep-6, + 0x1.fb57994d35b0bp-4, 0x1.139f0b59fa2a1p-6, 0x1.d69613acb75afp-4, 0x1.9372a38470b01p-5, + 0x1.8fbcca1a21152p-4, 0x1.3fed92cdb21a2p-4, 0x1.2bedb02d8b88dp-4, 0x1.9ef43eddbaab6p-4, + 0x1.64c7dc45e094ap-5, 0x1.dfeae52891d9dp-4, 0x1.5f6cf7ace5b75p-7, 0x1.fe1caf9b73a44p-4, + -0x1.76dd9c18a0ad4p-6, 0x1.f7599decc9dc0p-4, -0x1.c124a07c58cb2p-5, 0x1.cc1f0ec21c7dbp-4, + -0x1.53282ab8f42c2p-4, 0x1.7f8ece3017d72p-4, -0x1.ad2bcbb0d5da4p-4, 0x1.1734d25643a24p-4, + -0x1.e817bb2775061p-4, 0x1.35410dfdacd21p-5, -0x1.ffa72d90f8e7cp-4, 0x1.2d86542d900abp-8, + -0x1.f2252f0106ed0p-4, -0x1.d934fc6fa0cb4p-6, -0x1.c08c42b0cd30dp-4, -0x1.edc192e922c39p-5, + -0x1.6e74466cd2c14p-4, -0x1.659192fb6dc63p-4, -0x1.01cfc8b04b8dfp-4, -0x1.ba5aa692d5a93p-4, + -0x1.04fb82862fa2bp-5, -0x1.ef178c3c51edcp-4, 0x1.921d723f2aca9p-10, -0x1.fff6214d2d21ap-4, + 0x1.1d343f8f3691fp-5, -0x1.ebbd8d4faf931p-4, 0x1.0c97053590a9ap-4, -0x1.b3e4d3f36ebdfp-4, + 0x1.771e74e480f5cp-4, -0x1.5c77bc6094af5p-4, 0x1.c678b2aa8076bp-4, -0x1.d79777a612f34p-5, + 0x1.f4e60072b6a45p-4, -0x1.a82a082c1fd83p-6, 0x1.ff095691d1919p-4, 0x1.f656f538227b6p-8, + 0x1.e426a27dc59f1p-4, 0x1.4d1e23e2fffc5p-5, 0x1.a6309018dc6fcp-4, 0x1.21a79aa9bc509p-4, + 0x1.49a44a89e452ep-4, 0x1.87c40339f5135p-4, 0x1.aa6c822a1d4d4p-5, 0x1.d17e761c94b52p-4, + 0x1.45576f7b16b12p-6, 0x1.f97f92dc53c5cp-4, -0x1.c37863763a0f0p-7, 0x1.fce15f663bd32p-4, + -0x1.7c3a9465b7507p-5, 0x1.db65299cdd426p-4, -0x1.36058d644253dp-4, 0x1.9777ee7b96a5bp-4, + -0x1.9777ee7b96a5bp-4, 0x1.36058d644253dp-4, -0x1.db65299cdd426p-4, 0x1.7c3a9465b7507p-5, + -0x1.fce15f663bd32p-4, 0x1.c37863763a0f0p-7, -0x1.f97f92dc53c5cp-4, -0x1.45576f7b16b12p-6, + -0x1.d17e761c94b52p-4, -0x1.aa6c822a1d4d4p-5, -0x1.87c40339f5135p-4, -0x1.49a44a89e452ep-4, + -0x1.21a79aa9bc509p-4, -0x1.a6309018dc6fcp-4, -0x1.4d1e23e2fffc5p-5, -0x1.e426a27dc59f1p-4, + -0x1.f656f538227b6p-8, -0x1.ff095691d1919p-4, 0x1.a82a082c1fd83p-6, -0x1.f4e60072b6a45p-4, + 0x1.d79777a612f34p-5, -0x1.c678b2aa8076bp-4, 0x1.5c77bc6094af5p-4, -0x1.771e74e480f5cp-4, + 0x1.b3e4d3f36ebdfp-4, -0x1.0c97053590a9ap-4, 0x1.ebbd8d4faf931p-4, -0x1.1d343f8f3691fp-5, + 0x1.fff6214d2d21ap-4, -0x1.921d723f2aca9p-10, 0x1.ef178c3c51edcp-4, 0x1.04fb82862fa2bp-5, + 0x1.ba5aa692d5a93p-4, 0x1.01cfc8b04b8dfp-4, 0x1.659192fb6dc63p-4, 0x1.6e74466cd2c14p-4, + 0x1.edc192e922c39p-5, 0x1.c08c42b0cd30dp-4, 0x1.d934fc6fa0cb4p-6, 0x1.f2252f0106ed0p-4, + -0x1.2d86542d900abp-8, 0x1.ffa72d90f8e7cp-4, -0x1.35410dfdacd21p-5, 0x1.e817bb2775061p-4, + -0x1.1734d25643a24p-4, 0x1.ad2bcbb0d5da4p-4, -0x1.7f8ece3017d72p-4, 0x1.53282ab8f42c2p-4, + -0x1.cc1f0ec21c7dbp-4, 0x1.c124a07c58cb2p-5, -0x1.f7599decc9dc0p-4, 0x1.76dd9c18a0ad4p-6, + -0x1.fe1caf9b73a44p-4, -0x1.5f6cf7ace5b75p-7, -0x1.dfeae52891d9dp-4, -0x1.64c7dc45e094ap-5, + -0x1.9ef43eddbaab6p-4, -0x1.2bedb02d8b88dp-4, -0x1.3fed92cdb21a2p-4, -0x1.8fbcca1a21152p-4, + -0x1.9372a38470b01p-5, -0x1.d69613acb75afp-4, -0x1.139f0b59fa294p-6, -0x1.fb57994d35b0dp-4, + -0x1.2ec7f4f6b2f8ep-3, 0x1.dfaed517315c6p-8, 0x1.63ffbfed1a7aap-7, 0x1.0d92c868796e9p-4, + -0x1.60c97ed5b3130p-4, 0x1.93110924ca6a1p-4, 0x1.dacd107abd64fp-6, 0x1.d356c9b0efc83p-5, + -0x1.f7b1309769cbfp-7, 0x1.80e1d0b427d85p-3, -0x1.80202e6363bb9p-6, -0x1.39e70bd60a62bp-6, + 0x1.40a8b4dbae4aap-7, -0x1.09ba2ab97fc78p-4, 0x1.3189357695c19p-6, 0x1.56ee97d7564d2p-3, + -0x1.f2e570213b635p-4, -0x1.1fed838fc2411p-3, -0x1.92f4efbd232a2p-4, 0x1.bf2cb1c51965ep-4, + 0x1.e32a13dd7c981p-4, 0x1.566fb47f4b401p-6, -0x1.cbc3ca2c3be09p-4, -0x1.616db65203129p-7, + -0x1.b8b25b45787d9p-6, 0x1.61a5b3c14eaccp-5, 0x1.a051e412d6962p-3, -0x1.485c9682b8f91p-4, + 0x1.b29321d0f4264p-4, -0x1.bdbce3b5cd67dp-4, 0x1.d33b43f079901p-5, -0x1.41e88bea3db1cp-4, + -0x1.dd6398f2d80b0p-6, 0x1.772fbcc74308bp-3, 0x1.ea07f69764aeap-8, -0x1.20d9da11ee2fbp-4, + -0x1.b7bf4ca3bdfbfp-6, 0x1.4aecae9c68d11p-10, -0x1.554489164090dp-5, -0x1.8ec9a43fa7f92p-4, + 0x1.e8401409f569bp-5, -0x1.de4c9f3a35242p-9, -0x1.393f5b7e82e3fp-3, 0x1.feb7ae0271f22p-8, + -0x1.d057a77213570p-5, -0x1.51403fa75bdb3p-6, 0x1.134c94f2f755bp-3, 0x1.fc5497493019dp-9, + 0x1.d6b8c9624f6d3p-4, 0x1.2976ec27440e6p-7, -0x1.3825c382a7d52p-3, -0x1.d1b1154d4a4e8p-4, + 0x1.0d90f62351ce4p-4, -0x1.52130c3493318p-12, -0x1.15211c80a8ab5p-4, 0x1.e7b7ef17367dap-8, + 0x1.a53583e25fe5cp-7, -0x1.18d07c4601d45p-3, -0x1.52ab81a9ab928p-6, -0x1.09b2ca106a7ecp-3, + -0x1.2addf36a3c85fp-5, 0x1.1c10a11dab5dbp-4, -0x1.04a62d68583b6p-3, 0x1.f8315dd223fa4p-8, + -0x1.f8315dd223fa4p-8, 0x1.04a62d68583b6p-3, -0x1.1c10a11dab5dbp-4, 0x1.2addf36a3c85fp-5, + 0x1.09b2ca106a7ecp-3, 0x1.52ab81a9ab928p-6, 0x1.18d07c4601d45p-3, -0x1.a53583e25fe5cp-7, + -0x1.e7b7ef17367dap-8, 0x1.15211c80a8ab5p-4, 0x1.52130c3493318p-12, -0x1.0d90f62351ce4p-4, + 0x1.d1b1154d4a4e8p-4, 0x1.3825c382a7d52p-3, -0x1.2976ec27440e6p-7, -0x1.d6b8c9624f6d3p-4, + -0x1.fc5497493019dp-9, -0x1.134c94f2f755bp-3, 0x1.51403fa75bdb3p-6, 0x1.d057a77213570p-5, + -0x1.feb7ae0271f22p-8, 0x1.393f5b7e82e3fp-3, 0x1.de4c9f3a35242p-9, -0x1.e8401409f569bp-5, + 0x1.8ec9a43fa7f92p-4, 0x1.554489164090dp-5, -0x1.4aecae9c68d11p-10, 0x1.b7bf4ca3bdfbfp-6, + 0x1.20d9da11ee2fbp-4, -0x1.ea07f69764aeap-8, -0x1.772fbcc74308bp-3, 0x1.dd6398f2d80b0p-6, + 0x1.41e88bea3db1cp-4, -0x1.d33b43f079901p-5, 0x1.bdbce3b5cd67dp-4, -0x1.b29321d0f4264p-4, + 0x1.485c9682b8f91p-4, -0x1.a051e412d6962p-3, -0x1.61a5b3c14eaccp-5, 0x1.b8b25b45787d9p-6, + 0x1.616db65203129p-7, 0x1.cbc3ca2c3be09p-4, -0x1.566fb47f4b401p-6, -0x1.e32a13dd7c981p-4, + -0x1.bf2cb1c51965ep-4, 0x1.92f4efbd232a2p-4, 0x1.1fed838fc2411p-3, 0x1.f2e570213b635p-4, + -0x1.56ee97d7564d2p-3, -0x1.3189357695c19p-6, 0x1.09ba2ab97fc78p-4, -0x1.40a8b4dbae4aap-7, + 0x1.39e70bd60a62bp-6, 0x1.80202e6363bb9p-6, -0x1.80e1d0b427d85p-3, 0x1.f7b1309769cbfp-7, + -0x1.d356c9b0efc83p-5, -0x1.dacd107abd64fp-6, -0x1.93110924ca69dp-4, 0x1.60c97ed5b3133p-4, + -0x1.0d92c868796e6p-4, -0x1.63ffbfed1a7a5p-7, -0x1.dfaed5043ed67p-8, 0x1.2ec7f4eefbdbap-3, + -0x1.3205bd320fc2fp-7, 0x1.be311e9a61445p-4, 0x1.4799e15e720b2p-5, 0x1.059780194d963p-4, + -0x1.d522dc7cb50f9p-8, -0x1.81bc1f7b95d9fp-7, 0x1.382ffd9fa5d63p-4, 0x1.22554a119b6aep-5, + 0x1.bcfdd0274ecd2p-5, 0x1.6701686a169b2p-8, 0x1.cd66b2e18e1c9p-3, -0x1.a0c640c440d1fp-7, + 0x1.267e0eecd6b8cp-6, -0x1.87ae73a924f5cp-6, -0x1.3cd2de85d5ba9p-3, 0x1.81740f95f88bep-5, + -0x1.d70b062167532p-5, 0x1.e801c1d0d1a45p-7, 0x1.b67e41c4f68b8p-7, 0x1.00095ce1d27f1p-5, + 0x1.f1a2b76ad4b79p-6, -0x1.0a08683467b32p-8, 0x1.ed4d2133c980fp-8, -0x1.a3bc07c0a0b2ap-4, + 0x1.037bd386c345ep-4, -0x1.99e5d63834f29p-5, 0x1.43b84fcf67775p-6, 0x1.f219601d7d8e7p-3, + 0x1.853632c3bbe81p-6, -0x1.c7dc1daf1d5a1p-4, -0x1.3b53b92d3a808p-3, -0x1.c8a0b2e7423d5p-5, + -0x1.5d5ec91ee28d1p-4, -0x1.586a1b310a390p-6, -0x1.1dad24be47b66p-5, 0x1.cf6791b938ba0p-7, + 0x1.575bd8d2b8f3fp-3, 0x1.d73fb5202e719p-5, -0x1.de86ba9d90d36p-7, 0x1.8133f3dc9f932p-4, + -0x1.57d79faeb3e66p-5, 0x1.43f2f1b955bdfp-3, 0x1.a86f421c69edbp-7, -0x1.40ac5b0d2b57cp-4, + -0x1.1b385db0025adp-5, -0x1.8a72e015d84b3p-5, -0x1.52820ca075d34p-6, 0x1.3f04c6089e1a3p-3, + -0x1.5fc362b5aca40p-6, -0x1.e4fff5516672ap-6, -0x1.0c31251e02279p-5, 0x1.0ba7b2b1e0098p-3, + 0x1.9f83949f5211ap-4, 0x1.30ea181c0b5efp-5, -0x1.13e2c2dcb72ccp-4, -0x1.dd5ed564c8f9dp-4, + 0x1.db14cdc8ca2dcp-3, -0x1.d51dc8364b9e6p-5, -0x1.2238529f8fc83p-3, -0x1.7214254f6294ep-5, + 0x1.0fcc9a9c86a0ep-3, 0x1.675c20b4d6be7p-7, 0x1.eca723a23df66p-5, 0x1.b5e04855dd99bp-4, + -0x1.b5e04855dd99bp-4, -0x1.eca723a23df66p-5, -0x1.675c20b4d6be7p-7, -0x1.0fcc9a9c86a0ep-3, + 0x1.7214254f6294ep-5, 0x1.2238529f8fc83p-3, 0x1.d51dc8364b9e6p-5, -0x1.db14cdc8ca2dcp-3, + 0x1.dd5ed564c8f9dp-4, 0x1.13e2c2dcb72ccp-4, -0x1.30ea181c0b5efp-5, -0x1.9f83949f5211ap-4, + -0x1.0ba7b2b1e0098p-3, 0x1.0c31251e02279p-5, 0x1.e4fff5516672ap-6, 0x1.5fc362b5aca40p-6, + -0x1.3f04c6089e1a3p-3, 0x1.52820ca075d34p-6, 0x1.8a72e015d84b3p-5, 0x1.1b385db0025adp-5, + 0x1.40ac5b0d2b57cp-4, -0x1.a86f421c69edbp-7, -0x1.43f2f1b955bdfp-3, 0x1.57d79faeb3e66p-5, + -0x1.8133f3dc9f932p-4, 0x1.de86ba9d90d36p-7, -0x1.d73fb5202e719p-5, -0x1.575bd8d2b8f3fp-3, + -0x1.cf6791b938ba0p-7, 0x1.1dad24be47b66p-5, 0x1.586a1b310a390p-6, 0x1.5d5ec91ee28d1p-4, + 0x1.c8a0b2e7423d5p-5, 0x1.3b53b92d3a808p-3, 0x1.c7dc1daf1d5a1p-4, -0x1.853632c3bbe81p-6, + -0x1.f219601d7d8e7p-3, -0x1.43b84fcf67775p-6, 0x1.99e5d63834f29p-5, -0x1.037bd386c345ep-4, + 0x1.a3bc07c0a0b2ap-4, -0x1.ed4d2133c980fp-8, 0x1.0a08683467b32p-8, -0x1.f1a2b76ad4b79p-6, + -0x1.00095ce1d27f1p-5, -0x1.b67e41c4f68b8p-7, -0x1.e801c1d0d1a45p-7, 0x1.d70b062167532p-5, + -0x1.81740f95f88bep-5, 0x1.3cd2de85d5ba9p-3, 0x1.87ae73a924f5cp-6, -0x1.267e0eecd6b8cp-6, + 0x1.a0c640c440d1fp-7, -0x1.cd66b2e18e1c9p-3, -0x1.6701686a169b2p-8, -0x1.bcfdd0274ecd2p-5, + -0x1.22554a119b6aep-5, -0x1.382ffd9fa5d63p-4, 0x1.81bc1f7b95da0p-7, 0x1.d522dc7cb50ecp-8, + -0x1.059780194d968p-4, -0x1.4799e15e720bbp-5, -0x1.be311e99860bcp-4, 0x1.3205ce730b142p-7, + 0x1.c3785eced0dd9p-7, -0x1.fce15f3c05134p-4, -0x1.4d1e21c569a44p-5, 0x1.e426a5b09a7b3p-4, + 0x1.0c9705ea66cd3p-4, -0x1.b3e4d2b63eb80p-4, -0x1.6591944934f67p-4, 0x1.6e7446770a839p-4, + 0x1.ad2bc800d8ff7p-4, -0x1.1734d58262c45p-4, -0x1.dfeae6fc4b0e6p-4, 0x1.64c7dd2e65fcfp-5, + 0x1.fb5795a9ec3e6p-4, -0x1.139f0bc824564p-6, -0x1.fe1cb13e74922p-4, -0x1.5f6d0322b6166p-7, + 0x1.e817bb364a4a6p-4, 0x1.35410bbbb6850p-5, -0x1.ba5aa44e2a30fp-4, -0x1.01cfc7eead507p-4, + 0x1.771e75483b1f3p-4, 0x1.5c77bb4895a01p-4, -0x1.21a799e88e04dp-4, -0x1.a63092c9ef39fp-4, + 0x1.7c3a9251e9c2dp-5, 0x1.db6526397fa1ep-4, -0x1.45576aa140b64p-6, -0x1.f97f941b1787ap-4, + -0x1.f656c4dea2dcap-8, 0x1.ff0957f15f8a9p-4, 0x1.1d34420683f82p-5, -0x1.ebbd8c3b2839bp-4, + -0x1.edc194fe68124p-5, 0x1.c08c432d1ba39p-4, 0x1.53282a5c35244p-4, -0x1.7f8ed05df22c9p-4, + -0x1.9ef43f70cbcdcp-4, 0x1.2bedafefce47bp-4, 0x1.d696189c62d00p-4, -0x1.9372a26dc03b1p-5, + -0x1.f7599a1ddadd8p-4, 0x1.76dda7033fd9fp-6, 0x1.ffa72daa2fe20p-4, 0x1.2d865edb57ea5p-8, + -0x1.ef17892ffbda8p-4, -0x1.04fb87cede4b7p-5, 0x1.c678b15881767p-4, 0x1.d79775cac92e3p-5, + -0x1.87c3ffef00761p-4, -0x1.49a447854b9b0p-4, 0x1.36058a1813828p-4, 0x1.9777ecf3fe5b9p-4, + -0x1.aa6c807f6e6c5p-5, -0x1.d17e781b3fa79p-4, 0x1.a82a06b32cc66p-6, 0x1.f4e603704d947p-4, + 0x1.921ca259bb5adp-10, -0x1.fff621f4fc31ep-4, -0x1.d934f7a236619p-6, 0x1.f22530a34aaf7p-4, + 0x1.c1249e427915ap-5, -0x1.cc1f116327ce4p-4, -0x1.3fed96dc73d16p-4, 0x1.8fbcc8c75128bp-4, + 0x1.8fbcc8c75128bp-4, -0x1.3fed96dc73d16p-4, -0x1.cc1f116327ce4p-4, 0x1.c1249e427915ap-5, + 0x1.f22530a34aaf7p-4, -0x1.d934f7a236619p-6, -0x1.fff621f4fc31ep-4, 0x1.921ca259bb5adp-10, + 0x1.f4e603704d947p-4, 0x1.a82a06b32cc66p-6, -0x1.d17e781b3fa79p-4, -0x1.aa6c807f6e6c5p-5, + 0x1.9777ecf3fe5b9p-4, 0x1.36058a1813828p-4, -0x1.49a447854b9b0p-4, -0x1.87c3ffef00761p-4, + 0x1.d79775cac92e3p-5, 0x1.c678b15881767p-4, -0x1.04fb87cede4b7p-5, -0x1.ef17892ffbda8p-4, + 0x1.2d865edb57ea5p-8, 0x1.ffa72daa2fe20p-4, 0x1.76dda7033fd9fp-6, -0x1.f7599a1ddadd8p-4, + -0x1.9372a26dc03b1p-5, 0x1.d696189c62d00p-4, 0x1.2bedafefce47bp-4, -0x1.9ef43f70cbcdcp-4, + -0x1.7f8ed05df22c9p-4, 0x1.53282a5c35244p-4, 0x1.c08c432d1ba39p-4, -0x1.edc194fe68124p-5, + -0x1.ebbd8c3b2839bp-4, 0x1.1d34420683f82p-5, 0x1.ff0957f15f8a9p-4, -0x1.f656c4dea2dcap-8, + -0x1.f97f941b1787ap-4, -0x1.45576aa140b64p-6, 0x1.db6526397fa1ep-4, 0x1.7c3a9251e9c2dp-5, + -0x1.a63092c9ef39fp-4, -0x1.21a799e88e04dp-4, 0x1.5c77bb4895a01p-4, 0x1.771e75483b1f3p-4, + -0x1.01cfc7eead507p-4, -0x1.ba5aa44e2a30fp-4, 0x1.35410bbbb6850p-5, 0x1.e817bb364a4a6p-4, + -0x1.5f6d0322b6166p-7, -0x1.fe1cb13e74922p-4, -0x1.139f0bc824564p-6, 0x1.fb5795a9ec3e6p-4, + 0x1.64c7dd2e65fcfp-5, -0x1.dfeae6fc4b0e6p-4, -0x1.1734d58262c45p-4, 0x1.ad2bc800d8ff7p-4, + 0x1.6e7446770a839p-4, -0x1.6591944934f67p-4, -0x1.b3e4d2b63eb80p-4, 0x1.0c9705ea66cd3p-4, + 0x1.e426a5b09a7b3p-4, -0x1.4d1e21c569a44p-5, -0x1.fce15f3c05135p-4, 0x1.c3785eced0dc2p-7, + 0x1.fce15f68b5129p-4, 0x1.c3785e34e9a2cp-7, 0x1.e426a6548f693p-4, 0x1.4d1e208563b77p-5, + 0x1.b3e4d3b49aa0ap-4, 0x1.0c97063f7743fp-4, 0x1.6e7445eab81dcp-4, 0x1.659193df4677ap-4, + 0x1.1734d5c6acebbp-4, 0x1.ad2bc860c0befp-4, 0x1.64c7dd6326580p-5, 0x1.dfeae7d4ae077p-4, + 0x1.139f0b70f4becp-6, 0x1.fb5796a1c235cp-4, -0x1.5f6d0264f5e04p-7, 0x1.fe1cb1b9f31a0p-4, + -0x1.35410b8f69f15p-5, 0x1.e817bb8e487bap-4, -0x1.01cfc72cd93eap-4, 0x1.ba5aa57e922f1p-4, + -0x1.5c77bb556a4f4p-4, 0x1.771e7554cce06p-4, -0x1.a6309380f248ap-4, 0x1.21a79967778edp-4, + -0x1.db6524f03a8cbp-4, 0x1.7c3a935ee44dbp-5, -0x1.f97f933a927f5p-4, 0x1.455769fa45063p-6, + -0x1.ff0957ce4195bp-4, -0x1.f656c5e48d3e8p-8, -0x1.ebbd8b3bb4ec9p-4, -0x1.1d34418e62908p-5, + -0x1.c08c4411d3011p-4, -0x1.edc1959d26bedp-5, -0x1.7f8ecfa1afa18p-4, -0x1.532829dc2109cp-4, + -0x1.2bedaef219650p-4, -0x1.9ef43fb702d87p-4, -0x1.9372a314ed3ecp-5, -0x1.d6961921c63cfp-4, + -0x1.76dda7cd298c4p-6, -0x1.f7599a0dd4922p-4, 0x1.2d865dad7c56ap-8, -0x1.ffa72ca3c2a12p-4, + 0x1.04fb87b51f461p-5, -0x1.ef178a113fd37p-4, 0x1.d797753b90a46p-5, -0x1.c678b20240b3bp-4, + 0x1.49a4478eedddap-4, -0x1.87c3feafda4ccp-4, 0x1.9777ed029c5ccp-4, -0x1.360589a6bf789p-4, + 0x1.d17e76d7099c9p-4, -0x1.aa6c808ba2933p-5, 0x1.f4e60379b3489p-4, -0x1.a82a060c9848fp-6, + 0x1.fff620b42ccf9p-4, 0x1.921ca63e7cb01p-10, 0x1.f22530a47b36bp-4, 0x1.d934f6dcf3506p-6, + 0x1.cc1f117fb1da0p-4, 0x1.c1249e1c0ca65p-5, 0x1.8fbcc944bb35ep-4, 0x1.3fed97fb97056p-4, + 0x1.3fed97fb97056p-4, 0x1.8fbcc944bb35ep-4, 0x1.c1249e1c0ca65p-5, 0x1.cc1f117fb1da0p-4, + 0x1.d934f6dcf3506p-6, 0x1.f22530a47b36bp-4, 0x1.921ca63e7cb01p-10, 0x1.fff620b42ccf9p-4, + -0x1.a82a060c9848fp-6, 0x1.f4e60379b3489p-4, -0x1.aa6c808ba2933p-5, 0x1.d17e76d7099c9p-4, + -0x1.360589a6bf789p-4, 0x1.9777ed029c5ccp-4, -0x1.87c3feafda4ccp-4, 0x1.49a4478eedddap-4, + -0x1.c678b20240b3bp-4, 0x1.d797753b90a46p-5, -0x1.ef178a113fd37p-4, 0x1.04fb87b51f461p-5, + -0x1.ffa72ca3c2a12p-4, 0x1.2d865dad7c56ap-8, -0x1.f7599a0dd4922p-4, -0x1.76dda7cd298c4p-6, + -0x1.d6961921c63cfp-4, -0x1.9372a314ed3ecp-5, -0x1.9ef43fb702d87p-4, -0x1.2bedaef219650p-4, + -0x1.532829dc2109cp-4, -0x1.7f8ecfa1afa18p-4, -0x1.edc1959d26bedp-5, -0x1.c08c4411d3011p-4, + -0x1.1d34418e62908p-5, -0x1.ebbd8b3bb4ec9p-4, -0x1.f656c5e48d3e8p-8, -0x1.ff0957ce4195bp-4, + 0x1.455769fa45063p-6, -0x1.f97f933a927f5p-4, 0x1.7c3a935ee44dbp-5, -0x1.db6524f03a8cbp-4, + 0x1.21a79967778edp-4, -0x1.a6309380f248ap-4, 0x1.771e7554cce06p-4, -0x1.5c77bb556a4f4p-4, + 0x1.ba5aa57e922f1p-4, -0x1.01cfc72cd93eap-4, 0x1.e817bb8e487bap-4, -0x1.35410b8f69f15p-5, + 0x1.fe1cb1b9f31a0p-4, -0x1.5f6d0264f5e04p-7, 0x1.fb5796a1c235cp-4, 0x1.139f0b70f4becp-6, + 0x1.dfeae7d4ae077p-4, 0x1.64c7dd6326580p-5, 0x1.ad2bc860c0befp-4, 0x1.1734d5c6acebbp-4, + 0x1.659193df4677ap-4, 0x1.6e7445eab81dcp-4, 0x1.0c97063f7743fp-4, 0x1.b3e4d3b49aa0ap-4, + 0x1.4d1e208563b77p-5, 0x1.e426a6548f693p-4, 0x1.c3785e34e9bbdp-7, 0x1.fce15f68b512cp-4, + 0x1.75f792a7d4752p-3, -0x1.1ca3974f3e93cp-6, -0x1.7d8b147024e44p-5, -0x1.21e24149797dcp-6, + -0x1.ecd248c850732p-5, 0x1.0dff91ab64926p-5, 0x1.6cd9c1de57a1ap-3, 0x1.40c0e810cbe5fp-3, + -0x1.7f5a55d3c4e1fp-4, -0x1.3b575e56d1cabp-4, 0x1.4d4b4bca0f705p-7, -0x1.073f1f7243ccap-3, + 0x1.b9e5e5284b8eap-10, -0x1.1acc67304f234p-6, -0x1.d3b7736b6f882p-11, 0x1.e6518f4458249p-5, + 0x1.e2fb7d6f2e5d1p-5, 0x1.3757c5ba35f20p-4, 0x1.e584bbf8a60a8p-6, 0x1.35c12a01267aap-3, + 0x1.074feddc212c4p-3, -0x1.23a8535225dacp-6, -0x1.eafbe110ee807p-3, -0x1.9227f8fc73114p-5, + -0x1.70566a83490b1p-6, -0x1.319930934716dp-8, -0x1.c820dd99ef6ebp-4, 0x1.fd752266fda12p-6, + 0x1.bd9ea74e94122p-4, -0x1.25d590e92d205p-7, 0x1.6f68abc6995d0p-3, -0x1.237e8c488f298p-5, + 0x1.5d6ac3321ea6bp-4, -0x1.06d72c6f1ae4dp-4, 0x1.ef43f178e3e4dp-9, -0x1.b020918457fccp-6, + -0x1.767e7688690b1p-7, -0x1.231db553731c0p-3, 0x1.d4ecda1dd03fbp-5, -0x1.db727533eeab9p-4, + -0x1.f194bdfd42db6p-7, -0x1.8f5f4548ceeefp-4, -0x1.cb47cbee3e30fp-9, -0x1.e2aeae84724e6p-8, + 0x1.ecb3bb944f9f4p-7, 0x1.b71bc37f34410p-4, -0x1.1b185cd93dd96p-5, 0x1.41881a258acb5p-4, + -0x1.73247acffc495p-4, 0x1.06d8f7eeaeb2fp-4, -0x1.fa4c418de6971p-6, -0x1.8876ed00d6fb0p-4, + -0x1.5c8dbff50314bp-4, 0x1.2628f76b7d61bp-6, -0x1.0c4d713b0fe53p-5, -0x1.d93b1f7b533e3p-5, + 0x1.5afa7b5e2df1ep-5, 0x1.ea36cfdc683e2p-8, 0x1.040acd0a70e7fp-4, -0x1.92bc2b73bdf71p-6, + -0x1.bb11e28dd65bbp-3, -0x1.b01b18ff8aeb0p-6, -0x1.34fe7682ffd4ep-3, 0x1.8f5a46df14f97p-4, + 0x1.8f5a46df14f97p-4, -0x1.34fe7682ffd4ep-3, -0x1.b01b18ff8aeb0p-6, -0x1.bb11e28dd65bbp-3, + -0x1.92bc2b73bdf71p-6, 0x1.040acd0a70e7fp-4, 0x1.ea36cfdc683e2p-8, 0x1.5afa7b5e2df1ep-5, + -0x1.d93b1f7b533e3p-5, -0x1.0c4d713b0fe53p-5, 0x1.2628f76b7d61bp-6, -0x1.5c8dbff50314bp-4, + -0x1.8876ed00d6fb0p-4, -0x1.fa4c418de6971p-6, 0x1.06d8f7eeaeb2fp-4, -0x1.73247acffc495p-4, + 0x1.41881a258acb5p-4, -0x1.1b185cd93dd96p-5, 0x1.b71bc37f34410p-4, 0x1.ecb3bb944f9f4p-7, + -0x1.e2aeae84724e6p-8, -0x1.cb47cbee3e30fp-9, -0x1.8f5f4548ceeefp-4, -0x1.f194bdfd42db6p-7, + -0x1.db727533eeab9p-4, 0x1.d4ecda1dd03fbp-5, -0x1.231db553731c0p-3, -0x1.767e7688690b1p-7, + -0x1.b020918457fccp-6, 0x1.ef43f178e3e4dp-9, -0x1.06d72c6f1ae4dp-4, 0x1.5d6ac3321ea6bp-4, + -0x1.237e8c488f298p-5, 0x1.6f68abc6995d0p-3, -0x1.25d590e92d205p-7, 0x1.bd9ea74e94122p-4, + 0x1.fd752266fda12p-6, -0x1.c820dd99ef6ebp-4, -0x1.319930934716dp-8, -0x1.70566a83490b1p-6, + -0x1.9227f8fc73114p-5, -0x1.eafbe110ee807p-3, -0x1.23a8535225dacp-6, 0x1.074feddc212c4p-3, + 0x1.35c12a01267aap-3, 0x1.e584bbf8a60a8p-6, 0x1.3757c5ba35f20p-4, 0x1.e2fb7d6f2e5d1p-5, + 0x1.e6518f4458249p-5, -0x1.d3b7736b6f882p-11, -0x1.1acc67304f234p-6, 0x1.b9e5e5284b8eap-10, + -0x1.073f1f7243ccap-3, 0x1.4d4b4bca0f705p-7, -0x1.3b575e56d1cabp-4, -0x1.7f5a55d3c4e1fp-4, + 0x1.40c0e810cbe5fp-3, 0x1.6cd9c1de57a1ap-3, 0x1.0dff91ab6491fp-5, -0x1.ecd248c850734p-5, + -0x1.21e24149797c4p-6, -0x1.7d8b147024e4ap-5, -0x1.1ca394114c87ep-6, 0x1.75f792a0fe29fp-3, + -0x1.2a9b391dd7355p-5, -0x1.0fd99999844b5p-3, 0x1.3681cbafbbea2p-5, -0x1.507808f810b8ap-4, + 0x1.5af44a2a48bf4p-6, -0x1.ed8bc0622d3a8p-3, 0x1.cb1999a87cfa0p-4, -0x1.bebe668e4a487p-4, + -0x1.af1b225b861bdp-3, 0x1.278240844adfbp-5, -0x1.e940126208b78p-4, 0x1.9c6f2a6a416c5p-5, + -0x1.74459176267c6p-4, 0x1.e05fcb08a26cbp-7, 0x1.1159828bb1bf8p-4, 0x1.cdb0bfd62ec2ap-8, + 0x1.92ffcd401c59ep-4, -0x1.38185763a3b84p-8, -0x1.a1b649ac1a6acp-3, -0x1.cb030a2f94e7bp-5, + -0x1.a14dde66515d9p-4, 0x1.6004d5cff75ddp-5, 0x1.977fb1bf3414ap-7, -0x1.38d8acb3a8e6fp-7, + 0x1.71da4c19f0191p-4, -0x1.0cfa67509da8dp-3, 0x1.c3f2f74ced246p-7, 0x1.6bff770937288p-10, + -0x1.12567d225906dp-6, -0x1.cb8f0cb58b226p-5, -0x1.0d0282b26a4e0p-5, 0x1.963386254a45ap-3, + 0x1.3d707a31051b6p-6, -0x1.3bc0cc501f5d5p-4, -0x1.28f8e104e5bcep-3, 0x1.baeefafdfcd8cp-4, + -0x1.4c1d4632160cdp-6, -0x1.3bcb9a791bb3ep-5, 0x1.eff6b7facb3d6p-4, -0x1.4c3dfdca86794p-5, + 0x1.3193f60beb926p-8, 0x1.ceff53e9f2acdp-6, -0x1.3092e0dff712ep-3, -0x1.5381b48bd8c26p-6, + -0x1.2ddb2aa2d0c67p-3, -0x1.0d611f745478dp-7, 0x1.4cc10d0ae3e5ap-4, -0x1.105a3988afc9ep-6, + -0x1.a022f5e27ef95p-13, 0x1.947dfed3525dep-6, 0x1.ec7b9cf66f74fp-7, -0x1.440aae88b90d5p-5, + 0x1.2a850e2d2e7b9p-4, -0x1.78610b5e6afcbp-4, -0x1.246697fea8ca4p-6, 0x1.cccbb45d0b23ap-8, + 0x1.6b1882cebf583p-7, -0x1.d948a8754b666p-5, 0x1.bfbe2ac214716p-7, 0x1.b92b6e79639abp-4, + -0x1.532d577ac67c0p-4, -0x1.fc8ea918d5ec0p-8, -0x1.2da8d41ad9d9cp-6, 0x1.61bc64e9fc0eep-3, + 0x1.61bc64e9fc0eep-3, -0x1.2da8d41ad9d9cp-6, -0x1.fc8ea918d5ec0p-8, -0x1.532d577ac67c0p-4, + 0x1.b92b6e79639abp-4, 0x1.bfbe2ac214716p-7, -0x1.d948a8754b666p-5, 0x1.6b1882cebf583p-7, + 0x1.cccbb45d0b23ap-8, -0x1.246697fea8ca4p-6, -0x1.78610b5e6afcbp-4, 0x1.2a850e2d2e7b9p-4, + -0x1.440aae88b90d5p-5, 0x1.ec7b9cf66f74fp-7, 0x1.947dfed3525dep-6, -0x1.a022f5e27ef95p-13, + -0x1.105a3988afc9ep-6, 0x1.4cc10d0ae3e5ap-4, -0x1.0d611f745478dp-7, -0x1.2ddb2aa2d0c67p-3, + -0x1.5381b48bd8c26p-6, -0x1.3092e0dff712ep-3, 0x1.ceff53e9f2acdp-6, 0x1.3193f60beb926p-8, + -0x1.4c3dfdca86794p-5, 0x1.eff6b7facb3d6p-4, -0x1.3bcb9a791bb3ep-5, -0x1.4c1d4632160cdp-6, + 0x1.baeefafdfcd8cp-4, -0x1.28f8e104e5bcep-3, -0x1.3bc0cc501f5d5p-4, 0x1.3d707a31051b6p-6, + 0x1.963386254a45ap-3, -0x1.0d0282b26a4e0p-5, -0x1.cb8f0cb58b226p-5, -0x1.12567d225906dp-6, + 0x1.6bff770937288p-10, 0x1.c3f2f74ced246p-7, -0x1.0cfa67509da8dp-3, 0x1.71da4c19f0191p-4, + -0x1.38d8acb3a8e6fp-7, 0x1.977fb1bf3414ap-7, 0x1.6004d5cff75ddp-5, -0x1.a14dde66515d9p-4, + -0x1.cb030a2f94e7bp-5, -0x1.a1b649ac1a6acp-3, -0x1.38185763a3b84p-8, 0x1.92ffcd401c59ep-4, + 0x1.cdb0bfd62ec2ap-8, 0x1.1159828bb1bf8p-4, 0x1.e05fcb08a26cbp-7, -0x1.74459176267c6p-4, + 0x1.9c6f2a6a416c5p-5, -0x1.e940126208b78p-4, 0x1.278240844adfbp-5, -0x1.af1b225b861bdp-3, + -0x1.bebe668e4a487p-4, 0x1.cb1999a87cf9ep-4, -0x1.ed8bc0622d3a8p-3, 0x1.5af44a2a48c0bp-6, + -0x1.507808f810b94p-4, 0x1.3681cbafbbe9fp-5, -0x1.0fd999a7d000dp-3, -0x1.2a9b36b990aadp-5, + 0x1.5f6d01b24e796p-7, -0x1.fe1cb28b60744p-4, -0x1.04fb7ee16ea6ap-5, 0x1.ef1788a14bf88p-4, + 0x1.aa6c80f0b3396p-5, -0x1.d17e77422fadfp-4, -0x1.21a79a94f9944p-4, 0x1.a630922f7bebep-4, + 0x1.659192b42cebcp-4, -0x1.6e74463bb721ep-4, -0x1.9ef43e8aa29b8p-4, 0x1.2bedb0d1991ecp-4, + 0x1.cc1f0f1ac1f16p-4, -0x1.c12498c05ce4bp-5, -0x1.ebbd8d094a217p-4, 0x1.1d344529e0704p-5, + 0x1.fce160f1aa02cp-4, -0x1.c3785bbff28c4p-7, -0x1.ff0954c15249fp-4, -0x1.f656ee1c235dep-8, + 0x1.f2252e5454f51p-4, 0x1.d934fdb176873p-6, -0x1.d69616e012f0ep-4, -0x1.9372a67edf669p-5, + 0x1.ad2bc9a6e10b5p-4, 0x1.1734d747dd2a5p-4, -0x1.771e74892da68p-4, -0x1.5c77bac99616ep-4, + 0x1.36058affb5046p-4, 0x1.9777ed2199832p-4, -0x1.d797798273a40p-5, -0x1.c678b461a64b3p-4, + 0x1.35410e239a89cp-5, 0x1.e817bcbe5dbf5p-4, -0x1.139f02b376ef0p-6, -0x1.fb5795faec6eap-4, + -0x1.2d865df203714p-8, 0x1.ffa73012ad3aep-4, 0x1.a82a04b298f66p-6, -0x1.f4e603fb64a6dp-4, + -0x1.7c3a910f66328p-5, 0x1.db65266319b9ap-4, 0x1.0c9704e657a32p-4, -0x1.b3e4d423b1dcap-4, + -0x1.532827f2846d8p-4, 0x1.7f8ed04c9deeep-4, 0x1.8fbccafdc5014p-4, -0x1.3fed95c394135p-4, + -0x1.c08c43c028407p-4, 0x1.edc194801d679p-5, 0x1.e426a2713ffc1p-4, -0x1.4d1e2271b66b8p-5, + -0x1.f97f936f87096p-4, 0x1.4557700e6b368p-6, 0x1.fff6214389c31p-4, 0x1.921d456f99266p-10, + -0x1.f75998cd9d947p-4, -0x1.76dd951ef32dcp-6, 0x1.dfeae4ed75bb0p-4, 0x1.64c7dd02ebf30p-5, + -0x1.ba5aa61075e3ap-4, -0x1.01cfc8c46772ap-4, 0x1.87c402304f954p-4, 0x1.49a44b6ab0f6dp-4, + -0x1.49a44b6ab0f6dp-4, -0x1.87c402304f954p-4, 0x1.01cfc8c46772ap-4, 0x1.ba5aa61075e3ap-4, + -0x1.64c7dd02ebf30p-5, -0x1.dfeae4ed75bb0p-4, 0x1.76dd951ef32dcp-6, 0x1.f75998cd9d947p-4, + -0x1.921d456f99266p-10, -0x1.fff6214389c31p-4, -0x1.4557700e6b368p-6, 0x1.f97f936f87096p-4, + 0x1.4d1e2271b66b8p-5, -0x1.e426a2713ffc1p-4, -0x1.edc194801d679p-5, 0x1.c08c43c028407p-4, + 0x1.3fed95c394135p-4, -0x1.8fbccafdc5014p-4, -0x1.7f8ed04c9deeep-4, 0x1.532827f2846d8p-4, + 0x1.b3e4d423b1dcap-4, -0x1.0c9704e657a32p-4, -0x1.db65266319b9ap-4, 0x1.7c3a910f66328p-5, + 0x1.f4e603fb64a6dp-4, -0x1.a82a04b298f66p-6, -0x1.ffa73012ad3aep-4, 0x1.2d865df203714p-8, + 0x1.fb5795faec6eap-4, 0x1.139f02b376ef0p-6, -0x1.e817bcbe5dbf5p-4, -0x1.35410e239a89cp-5, + 0x1.c678b461a64b3p-4, 0x1.d797798273a40p-5, -0x1.9777ed2199832p-4, -0x1.36058affb5046p-4, + 0x1.5c77bac99616ep-4, 0x1.771e74892da68p-4, -0x1.1734d747dd2a5p-4, -0x1.ad2bc9a6e10b5p-4, + 0x1.9372a67edf669p-5, 0x1.d69616e012f0ep-4, -0x1.d934fdb176873p-6, -0x1.f2252e5454f51p-4, + 0x1.f656ee1c235dep-8, 0x1.ff0954c15249fp-4, 0x1.c3785bbff28c4p-7, -0x1.fce160f1aa02cp-4, + -0x1.1d344529e0704p-5, 0x1.ebbd8d094a217p-4, 0x1.c12498c05ce4bp-5, -0x1.cc1f0f1ac1f16p-4, + -0x1.2bedb0d1991ecp-4, 0x1.9ef43e8aa29b8p-4, 0x1.6e74463bb721ep-4, -0x1.659192b42cebcp-4, + -0x1.a630922f7bebep-4, 0x1.21a79a94f9944p-4, 0x1.d17e77422fadfp-4, -0x1.aa6c80f0b3396p-5, + -0x1.ef1788a14bf88p-4, 0x1.04fb7ee16ea6ap-5, 0x1.fe1cb28b60744p-4, -0x1.5f6d01b24e77fp-7, + 0x1.fe1cb25b080e7p-4, 0x1.5f6d01f3718a6p-7, 0x1.ef1788d335b24p-4, 0x1.04fb7ea34efe3p-5, + 0x1.d17e77c6b2d96p-4, 0x1.aa6c80a89bfa9p-5, 0x1.a63092fdc7698p-4, 0x1.21a79af2483e7p-4, + 0x1.6e7446b8d839dp-4, 0x1.659193351e129p-4, 0x1.2bedb0a05b010p-4, 0x1.9ef43efd00ee8p-4, + 0x1.c124998024282p-5, 0x1.cc1f0fca302a7p-4, 0x1.1d34441b1bd6fp-5, 0x1.ebbd8cb173bb4p-4, + 0x1.c3785ce40784ap-7, 0x1.fce1619454b36p-4, -0x1.f656efcd61cf3p-8, 0x1.ff0955053d89ap-4, + -0x1.d934fd4817ec4p-6, 0x1.f2252ca56ee25p-4, -0x1.9372a7381f362p-5, 0x1.d696170acfd29p-4, + -0x1.1734d659d5485p-4, 0x1.ad2bc84bd4182p-4, -0x1.5c77bb081948dp-4, 0x1.771e758c23d69p-4, + -0x1.9777ed12e9396p-4, 0x1.36058b13cb3bep-4, -0x1.c678b52811b26p-4, 0x1.d79778755928cp-5, + -0x1.e817bd863e345p-4, 0x1.35410d0196be0p-5, -0x1.fb5795bcec4eap-4, 0x1.139f028010d59p-6, + -0x1.ffa72f490c4a6p-4, -0x1.2d865c27ede0dp-8, -0x1.f4e6035d4aecbp-4, -0x1.a82a064849375p-6, + -0x1.db6527a216515p-4, -0x1.7c3a90e216bbfp-5, -0x1.b3e4d22b4377ap-4, -0x1.0c970492ab9bep-4, + -0x1.7f8ecee05750ap-4, -0x1.53282901ce09cp-4, -0x1.3fed977fa6439p-4, -0x1.8fbccb125fb1bp-4, + -0x1.edc1961c449d7p-5, -0x1.c08c443b67b2ep-4, -0x1.4d1e22dcdb868p-5, -0x1.e426a0d8b46b6p-4, + -0x1.4557721bce693p-6, -0x1.f97f93c6da53bp-4, 0x1.921d4bd3026bep-10, -0x1.fff62140d79cep-4, + 0x1.76dd9460baee0p-6, -0x1.f759992f71435p-4, 0x1.64c7dd79ed87ep-5, -0x1.dfeae5c0bb2adp-4, + 0x1.01cfc89d1c5e8p-4, -0x1.ba5aa5096b023p-4, 0x1.49a44b2916af6p-4, -0x1.87c40149c2a7ep-4, + 0x1.87c40149c2a7ep-4, -0x1.49a44b2916af6p-4, 0x1.ba5aa5096b023p-4, -0x1.01cfc89d1c5e8p-4, + 0x1.dfeae5c0bb2adp-4, -0x1.64c7dd79ed87ep-5, 0x1.f759992f71435p-4, -0x1.76dd9460baee0p-6, + 0x1.fff62140d79cep-4, -0x1.921d4bd3026bep-10, 0x1.f97f93c6da53bp-4, 0x1.4557721bce693p-6, + 0x1.e426a0d8b46b6p-4, 0x1.4d1e22dcdb868p-5, 0x1.c08c443b67b2ep-4, 0x1.edc1961c449d7p-5, + 0x1.8fbccb125fb1bp-4, 0x1.3fed977fa6439p-4, 0x1.53282901ce09cp-4, 0x1.7f8ecee05750ap-4, + 0x1.0c970492ab9bep-4, 0x1.b3e4d22b4377ap-4, 0x1.7c3a90e216bbfp-5, 0x1.db6527a216515p-4, + 0x1.a82a064849375p-6, 0x1.f4e6035d4aecbp-4, 0x1.2d865c27ede0dp-8, 0x1.ffa72f490c4a6p-4, + -0x1.139f028010d59p-6, 0x1.fb5795bcec4eap-4, -0x1.35410d0196be0p-5, 0x1.e817bd863e345p-4, + -0x1.d79778755928cp-5, 0x1.c678b52811b26p-4, -0x1.36058b13cb3bep-4, 0x1.9777ed12e9396p-4, + -0x1.771e758c23d69p-4, 0x1.5c77bb081948dp-4, -0x1.ad2bc84bd4182p-4, 0x1.1734d659d5485p-4, + -0x1.d696170acfd29p-4, 0x1.9372a7381f362p-5, -0x1.f2252ca56ee25p-4, 0x1.d934fd4817ec4p-6, + -0x1.ff0955053d89ap-4, 0x1.f656efcd61cf3p-8, -0x1.fce1619454b36p-4, -0x1.c3785ce40784ap-7, + -0x1.ebbd8cb173bb4p-4, -0x1.1d34441b1bd6fp-5, -0x1.cc1f0fca302a7p-4, -0x1.c124998024282p-5, + -0x1.9ef43efd00ee8p-4, -0x1.2bedb0a05b010p-4, -0x1.659193351e129p-4, -0x1.6e7446b8d839dp-4, + -0x1.21a79af2483e7p-4, -0x1.a63092fdc7698p-4, -0x1.aa6c80a89bfa9p-5, -0x1.d17e77c6b2d96p-4, + -0x1.04fb7ea34efe3p-5, -0x1.ef1788d335b24p-4, -0x1.5f6d01f371758p-7, -0x1.fe1cb25b080e3p-4, + 0x1.4503b19f062edp-4, -0x1.5176462048d86p-8, 0x1.4789fed5065a8p-3, 0x1.c2834c47ebc84p-7, + -0x1.9e02d5c57b70bp-3, 0x1.13d9b548abeb4p-4, -0x1.e764de3d058a2p-3, -0x1.cddc69494d33ap-4, + 0x1.2f2fbed373244p-3, 0x1.d368632fa147fp-6, -0x1.5e7b347c0ee53p-6, 0x1.6f5dece457d2ep-5, + -0x1.9cf566987b3a5p-5, -0x1.57d40aa13f7a3p-5, 0x1.af1dab7154cdcp-6, -0x1.13c1ca36ca11bp-3, + -0x1.d06fdcd0e4085p-9, -0x1.084e6fdfac908p-3, -0x1.ad739d38b5ebep-8, 0x1.24178fd393621p-4, + -0x1.ae6b40689ca7fp-9, 0x1.21de7b0b9a62bp-4, -0x1.b752f5a9b12a0p-6, 0x1.d29717fa287dep-3, + -0x1.c86cd5436fd62p-5, -0x1.97e17bf6c5a76p-4, 0x1.7b133c5cdf359p-11, -0x1.08ce7fb3aeaeep-8, + 0x1.a19667f30a641p-4, 0x1.f8832c643e581p-8, 0x1.0020080c747cbp-3, -0x1.afa8167323c43p-5, + -0x1.795a5897f85cep-6, 0x1.510b4018b2295p-5, 0x1.f50dcce9dd569p-4, 0x1.093230dfe617dp-7, + -0x1.864c0ff9318a6p-6, 0x1.0bd88877a3d8cp-8, -0x1.a84be4a734d49p-5, 0x1.3da090fb8efccp-5, + -0x1.73c1714824f53p-3, -0x1.8d944de45aed7p-6, 0x1.161cf52cdef06p-4, 0x1.4bf78751e6f9ep-5, + -0x1.afd4d593b7c5ep-5, 0x1.6bcd5b75c16e4p-5, 0x1.c390748668539p-4, -0x1.dc3b5ca88af68p-4, + -0x1.e1d865ca0a66ep-6, -0x1.dcd7f403d54d6p-5, 0x1.4c1c59615c635p-4, -0x1.1b62793a61fadp-5, + 0x1.0e37fc8dadca2p-5, -0x1.3c7ae69af028cp-3, -0x1.fc254328932a6p-10, 0x1.27ba9395d6925p-6, + 0x1.8bccc1905efdcp-7, 0x1.756b195377141p-7, -0x1.b3e5a50a9d366p-7, -0x1.b015d5e5f7e30p-4, + 0x1.141732e209182p-4, 0x1.46995f0a53e79p-3, 0x1.8626650bae241p-5, 0x1.9bba72c73db50p-4, + -0x1.9bba72c73db50p-4, -0x1.8626650bae241p-5, -0x1.46995f0a53e79p-3, -0x1.141732e209182p-4, + 0x1.b015d5e5f7e30p-4, 0x1.b3e5a50a9d366p-7, -0x1.756b195377141p-7, -0x1.8bccc1905efdcp-7, + -0x1.27ba9395d6925p-6, 0x1.fc254328932a6p-10, 0x1.3c7ae69af028cp-3, -0x1.0e37fc8dadca2p-5, + 0x1.1b62793a61fadp-5, -0x1.4c1c59615c635p-4, 0x1.dcd7f403d54d6p-5, 0x1.e1d865ca0a66ep-6, + 0x1.dc3b5ca88af68p-4, -0x1.c390748668539p-4, -0x1.6bcd5b75c16e4p-5, 0x1.afd4d593b7c5ep-5, + -0x1.4bf78751e6f9ep-5, -0x1.161cf52cdef06p-4, 0x1.8d944de45aed7p-6, 0x1.73c1714824f53p-3, + -0x1.3da090fb8efccp-5, 0x1.a84be4a734d49p-5, -0x1.0bd88877a3d8cp-8, 0x1.864c0ff9318a6p-6, + -0x1.093230dfe617dp-7, -0x1.f50dcce9dd569p-4, -0x1.510b4018b2295p-5, 0x1.795a5897f85cep-6, + 0x1.afa8167323c43p-5, -0x1.0020080c747cbp-3, -0x1.f8832c643e581p-8, -0x1.a19667f30a641p-4, + 0x1.08ce7fb3aeaeep-8, -0x1.7b133c5cdf359p-11, 0x1.97e17bf6c5a76p-4, 0x1.c86cd5436fd62p-5, + -0x1.d29717fa287dep-3, 0x1.b752f5a9b12a0p-6, -0x1.21de7b0b9a62bp-4, 0x1.ae6b40689ca7fp-9, + -0x1.24178fd393621p-4, 0x1.ad739d38b5ebep-8, 0x1.084e6fdfac908p-3, 0x1.d06fdcd0e4085p-9, + 0x1.13c1ca36ca11bp-3, -0x1.af1dab7154cdcp-6, 0x1.57d40aa13f7a3p-5, 0x1.9cf566987b3a5p-5, + -0x1.6f5dece457d2ep-5, 0x1.5e7b347c0ee53p-6, -0x1.d368632fa147fp-6, -0x1.2f2fbed373244p-3, + 0x1.cddc69494d33ap-4, 0x1.e764de3d058a2p-3, -0x1.13d9b548abeb3p-4, 0x1.9e02d5c57b709p-3, + -0x1.c2834c47ebcb5p-7, -0x1.4789fed5065aap-3, 0x1.517643071142bp-8, -0x1.4503b1bfea736p-4, + 0x1.45042fbf0f471p-9, -0x1.23f97cfe42a4cp-4, 0x1.e38f2ba6a857bp-10, -0x1.824936ec1d6d0p-3, + 0x1.ba002800ba20bp-6, -0x1.f242fd5515700p-4, 0x1.6a215fecc27d0p-4, -0x1.e6fddb619f272p-4, + 0x1.fb9b0072c4824p-5, 0x1.946b202458d88p-4, 0x1.ea8ba59dc419ap-8, 0x1.11e16a360d288p-5, + -0x1.4ad87a51ebaf8p-4, 0x1.062f46a67fb3ep-4, -0x1.f17f5af140538p-8, 0x1.14df989dfee13p-5, + -0x1.5100bbb523009p-4, 0x1.8b0b0568459b8p-6, -0x1.1f1cd7200990dp-4, 0x1.8d8e33e55bb18p-7, + 0x1.2c5d78af96f8ep-2, 0x1.06de36ed694bfp-5, 0x1.09aea3005a32bp-3, 0x1.4d66cb685b575p-5, + -0x1.8faeda7f89256p-7, 0x1.42ac66c8b285dp-6, 0x1.c7ceef645108fp-4, -0x1.10c4be27d5743p-6, + 0x1.eff695fe16bf7p-6, -0x1.dde5171adea83p-6, -0x1.718e1ec00cbeap-6, 0x1.3555a61e4d7e6p-5, + 0x1.f6fe0c4069031p-6, -0x1.43850e7741c9ap-3, -0x1.43c490bd86088p-6, 0x1.c2fdaf68713b4p-6, + -0x1.eed5bcc0c378bp-8, 0x1.35a5e560d390fp-3, -0x1.a9abb402596ebp-6, -0x1.6969508944829p-9, + -0x1.23684b4bac980p-6, -0x1.b54bd25e819b2p-3, 0x1.1abb435738846p-5, -0x1.36b7f9b393749p-4, + 0x1.69f1084cfe763p-5, 0x1.cc5ecac00da6cp-4, -0x1.37d5afd986b04p-4, 0x1.0b99153c6bdadp-3, + -0x1.fba7407dea759p-10, -0x1.01a972a36341cp-6, 0x1.db3d9453f7ca4p-3, 0x1.cf2af77e51150p-6, + -0x1.f759704e1c3c6p-6, -0x1.d35bfb3818323p-6, 0x1.a8446725dfc5ap-5, -0x1.0eb3ee0787427p-7, + -0x1.1bdcf83567955p-5, -0x1.fa3e730d236d0p-8, -0x1.0928f2c6f4519p-3, -0x1.30a136511d5d9p-6, + -0x1.75828ab81657fp-6, -0x1.2d696a8156b1ap-5, 0x1.8ff0b0c9c3cf9p-3, 0x1.4ec08ec15dc2cp-5, + -0x1.4ec08ec15dc2cp-5, -0x1.8ff0b0c9c3cf9p-3, 0x1.2d696a8156b1ap-5, 0x1.75828ab81657fp-6, + 0x1.30a136511d5d9p-6, 0x1.0928f2c6f4519p-3, 0x1.fa3e730d236d0p-8, 0x1.1bdcf83567955p-5, + 0x1.0eb3ee0787427p-7, -0x1.a8446725dfc5ap-5, 0x1.d35bfb3818323p-6, 0x1.f759704e1c3c6p-6, + -0x1.cf2af77e51150p-6, -0x1.db3d9453f7ca4p-3, 0x1.01a972a36341cp-6, 0x1.fba7407dea759p-10, + -0x1.0b99153c6bdadp-3, 0x1.37d5afd986b04p-4, -0x1.cc5ecac00da6cp-4, -0x1.69f1084cfe763p-5, + 0x1.36b7f9b393749p-4, -0x1.1abb435738846p-5, 0x1.b54bd25e819b2p-3, 0x1.23684b4bac980p-6, + 0x1.6969508944829p-9, 0x1.a9abb402596ebp-6, -0x1.35a5e560d390fp-3, 0x1.eed5bcc0c378bp-8, + -0x1.c2fdaf68713b4p-6, 0x1.43c490bd86088p-6, 0x1.43850e7741c9ap-3, -0x1.f6fe0c4069031p-6, + -0x1.3555a61e4d7e6p-5, 0x1.718e1ec00cbeap-6, 0x1.dde5171adea83p-6, -0x1.eff695fe16bf7p-6, + 0x1.10c4be27d5743p-6, -0x1.c7ceef645108fp-4, -0x1.42ac66c8b285dp-6, 0x1.8faeda7f89256p-7, + -0x1.4d66cb685b575p-5, -0x1.09aea3005a32bp-3, -0x1.06de36ed694bfp-5, -0x1.2c5d78af96f8ep-2, + -0x1.8d8e33e55bb18p-7, 0x1.1f1cd7200990dp-4, -0x1.8b0b0568459b8p-6, 0x1.5100bbb523009p-4, + -0x1.14df989dfee13p-5, 0x1.f17f5af140538p-8, -0x1.062f46a67fb3ep-4, 0x1.4ad87a51ebaf8p-4, + -0x1.11e16a360d288p-5, -0x1.ea8ba59dc419ap-8, -0x1.946b202458d88p-4, -0x1.fb9b0072c4824p-5, + 0x1.e6fddb619f272p-4, -0x1.6a215fecc27cfp-4, 0x1.f242fd5515700p-4, -0x1.ba002800ba1fbp-6, + 0x1.824936ec1d6cfp-3, -0x1.e38f2ba6a86acp-10, 0x1.23f97d0021e88p-4, -0x1.45041b9c63829p-9, + 0x1.f656eea020d8ep-8, -0x1.ff0956d5f48bcp-4, -0x1.76dd92d115337p-6, 0x1.f759986b875f1p-4, + 0x1.35410e85907e6p-5, -0x1.e817bbc0aaab5p-4, -0x1.aa6c8066ad818p-5, 0x1.d17e76ab9b87ep-4, + 0x1.0c9704ea50ba7p-4, -0x1.b3e4d44020f18p-4, -0x1.3fed97afb375ap-4, 0x1.8fbccb9288f84p-4, + 0x1.6e7446b5d4f8ap-4, -0x1.6591920da80bap-4, -0x1.9777f11a42c2ep-4, 0x1.360589660c1a0p-4, + 0x1.ba5aa7678cbd7p-4, -0x1.01cfc6ebb65acp-4, -0x1.d69616bdc8ebfp-4, 0x1.9372aa29ea9f2p-5, + 0x1.ebbd8d743607bp-4, -0x1.1d3440a70652ap-5, -0x1.f97f90c8940efp-4, 0x1.45576e524fb99p-6, + 0x1.ffa72c94d9b4fp-4, -0x1.2d865487a87b5p-8, -0x1.fe1cac81467d2p-4, -0x1.5f6d03882a907p-7, + 0x1.f4e605e29ca49p-4, 0x1.a82a0642732b9p-6, -0x1.e426a3f1624d2p-4, -0x1.4d1e206c66016p-5, + 0x1.cc1f0e8603f0ep-4, 0x1.c124a025878bep-5, -0x1.ad2bcc086d287p-4, -0x1.1734d6a7843aep-4, + 0x1.87c401419e300p-4, 0x1.49a449ab008e9p-4, -0x1.5c77bd1fbc5f0p-4, -0x1.771e73f963e3dp-4, + 0x1.2bedb26250e2fp-4, 0x1.9ef43c32edca9p-4, -0x1.edc19225fedc0p-5, -0x1.c08c3e90d2ba0p-4, + 0x1.7c3a8d2443f01p-5, 0x1.db652750b5452p-4, -0x1.04fb8048a544fp-5, -0x1.ef178c4327450p-4, + 0x1.139f0d0c87f69p-6, 0x1.fb5795da1cbd8p-4, -0x1.921cfa1987dbfp-10, -0x1.fff621f7751d8p-4, + -0x1.c3786b2fd766ap-7, 0x1.fce1613af0447p-4, 0x1.d934f41450094p-6, -0x1.f22530184c948p-4, + -0x1.64c7db480d406p-5, 0x1.dfeae5932547fp-4, 0x1.d79775f182deep-5, -0x1.c678b3df69270p-4, + -0x1.21a79a940409bp-4, 0x1.a6309579659e9p-4, 0x1.53282a2727633p-4, -0x1.7f8ecf0c7dd5ep-4, + -0x1.7f8ecf0c7dd5ep-4, 0x1.53282a2727633p-4, 0x1.a6309579659e9p-4, -0x1.21a79a940409bp-4, + -0x1.c678b3df69270p-4, 0x1.d79775f182deep-5, 0x1.dfeae5932547fp-4, -0x1.64c7db480d406p-5, + -0x1.f22530184c948p-4, 0x1.d934f41450094p-6, 0x1.fce1613af0447p-4, -0x1.c3786b2fd766ap-7, + -0x1.fff621f7751d8p-4, -0x1.921cfa1987dbfp-10, 0x1.fb5795da1cbd8p-4, 0x1.139f0d0c87f69p-6, + -0x1.ef178c4327450p-4, -0x1.04fb8048a544fp-5, 0x1.db652750b5452p-4, 0x1.7c3a8d2443f01p-5, + -0x1.c08c3e90d2ba0p-4, -0x1.edc19225fedc0p-5, 0x1.9ef43c32edca9p-4, 0x1.2bedb26250e2fp-4, + -0x1.771e73f963e3dp-4, -0x1.5c77bd1fbc5f0p-4, 0x1.49a449ab008e9p-4, 0x1.87c401419e300p-4, + -0x1.1734d6a7843aep-4, -0x1.ad2bcc086d287p-4, 0x1.c124a025878bep-5, 0x1.cc1f0e8603f0ep-4, + -0x1.4d1e206c66016p-5, -0x1.e426a3f1624d2p-4, 0x1.a82a0642732b9p-6, 0x1.f4e605e29ca49p-4, + -0x1.5f6d03882a907p-7, -0x1.fe1cac81467d2p-4, -0x1.2d865487a87b5p-8, 0x1.ffa72c94d9b4fp-4, + 0x1.45576e524fb99p-6, -0x1.f97f90c8940efp-4, -0x1.1d3440a70652ap-5, 0x1.ebbd8d743607bp-4, + 0x1.9372aa29ea9f2p-5, -0x1.d69616bdc8ebfp-4, -0x1.01cfc6ebb65acp-4, 0x1.ba5aa7678cbd7p-4, + 0x1.360589660c1a0p-4, -0x1.9777f11a42c2ep-4, -0x1.6591920da80bap-4, 0x1.6e7446b5d4f8ap-4, + 0x1.8fbccb9288f84p-4, -0x1.3fed97afb375ap-4, -0x1.b3e4d44020f18p-4, 0x1.0c9704ea50ba7p-4, + 0x1.d17e76ab9b87ep-4, -0x1.aa6c8066ad818p-5, -0x1.e817bbc0aaab5p-4, 0x1.35410e85907e6p-5, + 0x1.f759986b875f1p-4, -0x1.76dd92d115337p-6, -0x1.ff0956d5f48bcp-4, 0x1.f656eea020be9p-8, + 0x1.ff0956b319950p-4, 0x1.f656edc41dfc1p-8, 0x1.f75999b5661cap-4, 0x1.76dd922d0ca41p-6, + 0x1.e817b9eaf42cep-4, 0x1.35410eff18935p-5, 0x1.d17e776681bcdp-4, 0x1.aa6c817394e4ep-5, + 0x1.b3e4d572f172dp-4, 0x1.0c9704ec59b0fp-4, 0x1.8fbccb6bd36e5p-4, 0x1.3fed98af1b004p-4, + 0x1.659192509c899p-4, 0x1.6e74466452927p-4, 0x1.3605883eaed83p-4, 0x1.9777efd677a23p-4, + 0x1.01cfc664a89b0p-4, 0x1.ba5aa777d8c89p-4, 0x1.9372a82e34d29p-5, 0x1.d69615f2a79c4p-4, + 0x1.1d3440336254cp-5, 0x1.ebbd8d719f01cp-4, 0x1.45576ea51d7a1p-6, 0x1.f97f91cf1a3cfp-4, + 0x1.2d8653f48b009p-8, 0x1.ffa72cfe0d376p-4, -0x1.5f6d0188aab79p-7, 0x1.fe1cad78b9d01p-4, + -0x1.a82a0597b9861p-6, 0x1.f4e605f351ee0p-4, -0x1.4d1e204f99157p-5, 0x1.e426a34dc6c2ep-4, + -0x1.c124a2042f7ebp-5, 0x1.cc1f0f71ffcf9p-4, -0x1.1734d662e39aap-4, 0x1.ad2bcb3c15529p-4, + -0x1.49a44a90056d7p-4, 0x1.87c3ffbadc7d7p-4, -0x1.771e74fa06abap-4, 0x1.5c77bc924bbadp-4, + -0x1.9ef43ceaf7989p-4, 0x1.2bedb2fa40610p-4, -0x1.c08c3f97ea444p-4, 0x1.edc1918dc1facp-5, + -0x1.db6527f0d5b15p-4, 0x1.7c3a8d0a5b397p-5, -0x1.ef178ad097310p-4, 0x1.04fb80e0ee702p-5, + -0x1.fb579446215bfp-4, 0x1.139f0c0518cbcp-6, -0x1.fff6215e1c5f2p-4, 0x1.921cfd1e989f7p-10, + -0x1.fce1616a747d3p-4, -0x1.c3786b963d31fp-7, -0x1.f22531eeb3d27p-4, -0x1.d934f470a1638p-6, + -0x1.dfeae4a27cc9cp-4, -0x1.64c7da494c150p-5, -0x1.c678b3128330cp-4, -0x1.d797753889cfep-5, + -0x1.a63094fdde2c9p-4, -0x1.21a79b51e8eb7p-4, -0x1.7f8ecebf2cc1dp-4, -0x1.53282b4b85cd4p-4, + -0x1.53282b4b85cd4p-4, -0x1.7f8ecebf2cc1dp-4, -0x1.21a79b51e8eb7p-4, -0x1.a63094fdde2c9p-4, + -0x1.d797753889cfep-5, -0x1.c678b3128330cp-4, -0x1.64c7da494c150p-5, -0x1.dfeae4a27cc9cp-4, + -0x1.d934f470a1638p-6, -0x1.f22531eeb3d27p-4, -0x1.c3786b963d31fp-7, -0x1.fce1616a747d3p-4, + 0x1.921cfd1e989f7p-10, -0x1.fff6215e1c5f2p-4, 0x1.139f0c0518cbcp-6, -0x1.fb579446215bfp-4, + 0x1.04fb80e0ee702p-5, -0x1.ef178ad097310p-4, 0x1.7c3a8d0a5b397p-5, -0x1.db6527f0d5b15p-4, + 0x1.edc1918dc1facp-5, -0x1.c08c3f97ea444p-4, 0x1.2bedb2fa40610p-4, -0x1.9ef43ceaf7989p-4, + 0x1.5c77bc924bbadp-4, -0x1.771e74fa06abap-4, 0x1.87c3ffbadc7d7p-4, -0x1.49a44a90056d7p-4, + 0x1.ad2bcb3c15529p-4, -0x1.1734d662e39aap-4, 0x1.cc1f0f71ffcf9p-4, -0x1.c124a2042f7ebp-5, + 0x1.e426a34dc6c2ep-4, -0x1.4d1e204f99157p-5, 0x1.f4e605f351ee0p-4, -0x1.a82a0597b9861p-6, + 0x1.fe1cad78b9d01p-4, -0x1.5f6d0188aab79p-7, 0x1.ffa72cfe0d376p-4, 0x1.2d8653f48b009p-8, + 0x1.f97f91cf1a3cfp-4, 0x1.45576ea51d7a1p-6, 0x1.ebbd8d719f01cp-4, 0x1.1d3440336254cp-5, + 0x1.d69615f2a79c4p-4, 0x1.9372a82e34d29p-5, 0x1.ba5aa777d8c89p-4, 0x1.01cfc664a89b0p-4, + 0x1.9777efd677a23p-4, 0x1.3605883eaed83p-4, 0x1.6e74466452927p-4, 0x1.659192509c899p-4, + 0x1.3fed98af1b004p-4, 0x1.8fbccb6bd36e5p-4, 0x1.0c9704ec59b0fp-4, 0x1.b3e4d572f172dp-4, + 0x1.aa6c817394e4ep-5, 0x1.d17e776681bcdp-4, 0x1.35410eff18935p-5, 0x1.e817b9eaf42cep-4, + 0x1.76dd922d0ca41p-6, 0x1.f75999b5661cap-4, 0x1.f656edc41e1bcp-8, 0x1.ff0956b319956p-4, + 0x1.eda560b88d067p-5, 0x1.c381df39433ddp-9, 0x1.1a90c33806837p-4, -0x1.6a9963bd81174p-9, + -0x1.e54c1ea7ad65cp-6, -0x1.19797dc256d95p-7, 0x1.043a9be49d57ep-3, -0x1.8201c23e46f72p-5, + -0x1.0e33af1be3920p-5, -0x1.f084e77f1fe51p-5, 0x1.2e88b21f41e2ep-6, 0x1.228c598e77f7fp-4, + -0x1.93d54037f89fbp-6, 0x1.29542076db576p-6, -0x1.0bc40c6755e93p-5, -0x1.5a0896c14231cp-7, + -0x1.808b4b3a6f99ap-4, -0x1.552139cbcd2f8p-4, -0x1.ba6e0b7862be1p-6, -0x1.c2abbda4afb8cp-5, + -0x1.c696789feed97p-6, -0x1.e523c6075c38ap-3, 0x1.3452dd290fb70p-5, -0x1.dc991410d0d14p-5, + 0x1.7c2eb07769eafp-9, 0x1.eb432d16678a0p-3, -0x1.9729e17ac4eecp-9, -0x1.676cd069c8569p-3, + -0x1.cb81534eb0f40p-7, 0x1.c77b6725d8bfap-4, -0x1.e33b2480c897ap-5, 0x1.633b0f23e3a24p-3, + -0x1.96afb08ae13aap-5, -0x1.6e4e56e41a76ap-5, 0x1.3ef38a357f595p-4, 0x1.d8e66a398c69cp-5, + 0x1.ad56c36459c28p-7, -0x1.1fe7454633c80p-7, 0x1.56981047297b2p-4, 0x1.4bbaee05d8e35p-6, + 0x1.b03c002f4f9bep-3, -0x1.644f2054ef1b6p-5, -0x1.b447cbd1d2fc6p-4, -0x1.71b1206f822f2p-4, + 0x1.373d394ae06eap-4, -0x1.af3922ad8c3afp-7, -0x1.13c2529d3c48bp-3, -0x1.2c6c8662f0e73p-5, + 0x1.3c766f1e6c2aep-7, -0x1.f95aee91fd4fcp-11, 0x1.76a0b4ede8c49p-3, -0x1.3e3e7d6c61678p-9, + -0x1.21405b82c0bb4p-3, -0x1.0a52711742e5bp-11, -0x1.a4d528e40293ap-4, 0x1.44bfa2d0f9435p-5, + 0x1.ea5c632adc7adp-5, -0x1.7dd187cb373b6p-5, -0x1.a453c64bb07bap-5, -0x1.10889d6d2aecap-4, + -0x1.8e390c5f81a73p-3, -0x1.97ba97fffaf0ap-7, 0x1.0e869302967f7p-4, 0x1.a7c9b20e133a5p-4, + 0x1.a7c9b20e133a5p-4, 0x1.0e869302967f7p-4, -0x1.97ba97fffaf0ap-7, -0x1.8e390c5f81a73p-3, + -0x1.10889d6d2aecap-4, -0x1.a453c64bb07bap-5, -0x1.7dd187cb373b6p-5, 0x1.ea5c632adc7adp-5, + 0x1.44bfa2d0f9435p-5, -0x1.a4d528e40293ap-4, -0x1.0a52711742e5bp-11, -0x1.21405b82c0bb4p-3, + -0x1.3e3e7d6c61678p-9, 0x1.76a0b4ede8c49p-3, -0x1.f95aee91fd4fcp-11, 0x1.3c766f1e6c2aep-7, + -0x1.2c6c8662f0e73p-5, -0x1.13c2529d3c48bp-3, -0x1.af3922ad8c3afp-7, 0x1.373d394ae06eap-4, + -0x1.71b1206f822f2p-4, -0x1.b447cbd1d2fc6p-4, -0x1.644f2054ef1b6p-5, 0x1.b03c002f4f9bep-3, + 0x1.4bbaee05d8e35p-6, 0x1.56981047297b2p-4, -0x1.1fe7454633c80p-7, 0x1.ad56c36459c28p-7, + 0x1.d8e66a398c69cp-5, 0x1.3ef38a357f595p-4, -0x1.6e4e56e41a76ap-5, -0x1.96afb08ae13aap-5, + 0x1.633b0f23e3a24p-3, -0x1.e33b2480c897ap-5, 0x1.c77b6725d8bfap-4, -0x1.cb81534eb0f40p-7, + -0x1.676cd069c8569p-3, -0x1.9729e17ac4eecp-9, 0x1.eb432d16678a0p-3, 0x1.7c2eb07769eafp-9, + -0x1.dc991410d0d14p-5, 0x1.3452dd290fb70p-5, -0x1.e523c6075c38ap-3, -0x1.c696789feed97p-6, + -0x1.c2abbda4afb8cp-5, -0x1.ba6e0b7862be1p-6, -0x1.552139cbcd2f8p-4, -0x1.808b4b3a6f99ap-4, + -0x1.5a0896c14231cp-7, -0x1.0bc40c6755e93p-5, 0x1.29542076db576p-6, -0x1.93d54037f89fbp-6, + 0x1.228c598e77f7fp-4, 0x1.2e88b21f41e2ep-6, -0x1.f084e77f1fe51p-5, -0x1.0e33af1be3920p-5, + -0x1.8201c23e46f72p-5, 0x1.043a9be49d57ep-3, -0x1.19797dc256da8p-7, -0x1.e54c1ea7ad65ap-6, + -0x1.6a9963bd81090p-9, 0x1.1a90c33806833p-4, 0x1.c381f683ce9efp-9, 0x1.eda560a327b94p-5, + 0x1.257729c4fdb02p-11, 0x1.92b9d031cea6dp-3, 0x1.ae4481d06f297p-8, -0x1.80214d7b02a76p-7, + -0x1.557fdf5ad513bp-6, 0x1.1d29ced944c11p-4, 0x1.e24015ea6d80ep-6, 0x1.3f9e5ce716208p-6, + 0x1.6187321e4c385p-4, -0x1.7022cbd01f0f7p-5, 0x1.f147df855884bp-3, 0x1.aae175cd81e51p-4, + -0x1.805ad827ddc12p-9, 0x1.4cc8c18243e29p-5, -0x1.b0379de0ec31bp-7, 0x1.0ec4acc0484a9p-3, + -0x1.213a36e58208ap-4, -0x1.de3df3dee667dp-4, 0x1.82efa8afdf8b5p-5, 0x1.afe7e15480692p-5, + 0x1.032a1cafcac74p-3, 0x1.14c4312a2ccb4p-7, -0x1.01916a4acc98dp-4, -0x1.821dd52944d4cp-5, + -0x1.00876d5ba1791p-2, -0x1.a40d4521f0e19p-6, 0x1.6e515bab5ec7cp-6, -0x1.3368d8d54b966p-6, + 0x1.370aa257d13b9p-3, 0x1.c34973b808254p-6, -0x1.6386a670075b0p-6, 0x1.6fc49278dde8bp-8, + -0x1.996fd97d3e341p-5, -0x1.7ccabba15ffc0p-5, -0x1.5aeed7a89395ap-4, -0x1.fc58e26e31a75p-6, + 0x1.e7742cdc206ddp-4, -0x1.57028bf911925p-3, 0x1.b5ea159e409cap-7, 0x1.ec682ee471449p-4, + -0x1.0953d0d83c150p-4, -0x1.473a3419b124bp-3, 0x1.ae3827ff2b182p-6, -0x1.9e27cf3aeb7cap-8, + 0x1.37df6ea04ac14p-5, 0x1.5f675eae7cafep-8, 0x1.6854c44842c98p-4, -0x1.7f986e6ac9d5ap-6, + 0x1.035ef88118a01p-7, 0x1.542170af71569p-3, 0x1.6e58cc6e5c9a8p-7, -0x1.87bb7ba9a3d14p-3, + 0x1.199812aca7e1fp-7, -0x1.df02eb568ca86p-7, -0x1.da34a3263dccbp-7, 0x1.1d46c1052af2ap-3, + -0x1.9da0bde5ee041p-5, 0x1.2b47f68657e65p-4, 0x1.b07d376985ca6p-6, -0x1.b48a4d2a0131fp-5, + 0x1.98fab9a2b653bp-6, 0x1.bae77cfe75d12p-4, -0x1.dbcd64583c0dfp-5, -0x1.1e5b41ca79583p-6, + -0x1.1e5b41ca79583p-6, -0x1.dbcd64583c0dfp-5, 0x1.bae77cfe75d12p-4, 0x1.98fab9a2b653bp-6, + -0x1.b48a4d2a0131fp-5, 0x1.b07d376985ca6p-6, 0x1.2b47f68657e65p-4, -0x1.9da0bde5ee041p-5, + 0x1.1d46c1052af2ap-3, -0x1.da34a3263dccbp-7, -0x1.df02eb568ca86p-7, 0x1.199812aca7e1fp-7, + -0x1.87bb7ba9a3d14p-3, 0x1.6e58cc6e5c9a8p-7, 0x1.542170af71569p-3, 0x1.035ef88118a01p-7, + -0x1.7f986e6ac9d5ap-6, 0x1.6854c44842c98p-4, 0x1.5f675eae7cafep-8, 0x1.37df6ea04ac14p-5, + -0x1.9e27cf3aeb7cap-8, 0x1.ae3827ff2b182p-6, -0x1.473a3419b124bp-3, -0x1.0953d0d83c150p-4, + 0x1.ec682ee471449p-4, 0x1.b5ea159e409cap-7, -0x1.57028bf911925p-3, 0x1.e7742cdc206ddp-4, + -0x1.fc58e26e31a75p-6, -0x1.5aeed7a89395ap-4, -0x1.7ccabba15ffc0p-5, -0x1.996fd97d3e341p-5, + 0x1.6fc49278dde8bp-8, -0x1.6386a670075b0p-6, 0x1.c34973b808254p-6, 0x1.370aa257d13b9p-3, + -0x1.3368d8d54b966p-6, 0x1.6e515bab5ec7cp-6, -0x1.a40d4521f0e19p-6, -0x1.00876d5ba1791p-2, + -0x1.821dd52944d4cp-5, -0x1.01916a4acc98dp-4, 0x1.14c4312a2ccb4p-7, 0x1.032a1cafcac74p-3, + 0x1.afe7e15480692p-5, 0x1.82efa8afdf8b5p-5, -0x1.de3df3dee667dp-4, -0x1.213a36e58208ap-4, + 0x1.0ec4acc0484a9p-3, -0x1.b0379de0ec31bp-7, 0x1.4cc8c18243e29p-5, -0x1.805ad827ddc12p-9, + 0x1.aae175cd81e51p-4, 0x1.f147df855884bp-3, -0x1.7022cbd01f0f7p-5, 0x1.6187321e4c385p-4, + 0x1.3f9e5ce716208p-6, 0x1.e24015ea6d7f5p-6, 0x1.1d29ced944c12p-4, -0x1.557fdf5ad5123p-6, + -0x1.80214d7b02a71p-7, 0x1.ae4481d06f157p-8, 0x1.92b9d02f98fb3p-3, 0x1.2576765e03095p-11, + 0x1.2d86586620187p-8, -0x1.ffa730c403a7fp-4, -0x1.c3785fe6a8e9ap-7, 0x1.fce15f6f95d8ep-4, + 0x1.76dd97a39cc0ep-6, -0x1.f7599a2c89767p-4, -0x1.04fb81c672a0bp-5, 0x1.ef178b2444fd3p-4, + 0x1.4d1e24c5ffd69p-5, -0x1.e426a4e2b2f1ep-4, -0x1.9372a81010fe8p-5, 0x1.d69618bf1aaf6p-4, + 0x1.d797776185f7fp-5, -0x1.c678b3abdde67p-4, -0x1.0c9704a477420p-4, 0x1.b3e4d51245c81p-4, + 0x1.2bedb4d70cbe6p-4, -0x1.9ef43fa0cae1ap-4, -0x1.49a44b22966acp-4, 0x1.87c3ffdf10c6ep-4, + 0x1.659191eed63e0p-4, -0x1.6e74461fd5b6ep-4, -0x1.7f8eceacf641bp-4, 0x1.532827e702211p-4, + 0x1.9777eca187063p-4, -0x1.36058a19d7bcdp-4, -0x1.ad2bc9af1afe4p-4, 0x1.1734d45519fd1p-4, + 0x1.c08c403ac3a27p-4, -0x1.edc190beb847ep-5, -0x1.d17e78c664a8bp-4, 0x1.aa6c84aa8f94ep-5, + 0x1.dfeae7fe17643p-4, -0x1.64c7dec508b58p-5, -0x1.ebbd8db463b1dp-4, 0x1.1d34429096cc1p-5, + 0x1.f4e6031b3f6eap-4, -0x1.a82a080d7be4cp-6, -0x1.fb579939a6975p-4, 0x1.139f08ee4bbd9p-6, + 0x1.ff09569d73de4p-4, -0x1.f656ebec061cep-8, -0x1.fff61f0689a9cp-4, -0x1.921cbee6324efp-10, + 0x1.fe1caef720dacp-4, 0x1.5f6d0bfa3dcc4p-7, -0x1.f97f923fcddb4p-4, -0x1.45576bd142c9ap-6, + 0x1.f2252d2265359p-4, 0x1.d934fc2a301c5p-6, -0x1.e817b80d1065ap-4, -0x1.35410f4c15566p-5, + 0x1.db65256a3b7d3p-4, 0x1.7c3a963b53438p-5, -0x1.cc1f0f352da99p-4, -0x1.c124995e7db7ap-5, + 0x1.ba5aa64ccc414p-4, 0x1.01cfc836dcb2fp-4, -0x1.a63091cf6924dp-4, -0x1.21a79a83366f2p-4, + 0x1.8fbcc7118aa68p-4, 0x1.3fed98c543bfap-4, -0x1.771e7729b8f56p-4, -0x1.5c77bc76eb3ddp-4, + 0x1.5c77bc76eb3ddp-4, 0x1.771e7729b8f56p-4, -0x1.3fed98c543bfap-4, -0x1.8fbcc7118aa68p-4, + 0x1.21a79a83366f2p-4, 0x1.a63091cf6924dp-4, -0x1.01cfc836dcb2fp-4, -0x1.ba5aa64ccc414p-4, + 0x1.c124995e7db7ap-5, 0x1.cc1f0f352da99p-4, -0x1.7c3a963b53438p-5, -0x1.db65256a3b7d3p-4, + 0x1.35410f4c15566p-5, 0x1.e817b80d1065ap-4, -0x1.d934fc2a301c5p-6, -0x1.f2252d2265359p-4, + 0x1.45576bd142c9ap-6, 0x1.f97f923fcddb4p-4, -0x1.5f6d0bfa3dcc4p-7, -0x1.fe1caef720dacp-4, + 0x1.921cbee6324efp-10, 0x1.fff61f0689a9cp-4, 0x1.f656ebec061cep-8, -0x1.ff09569d73de4p-4, + -0x1.139f08ee4bbd9p-6, 0x1.fb579939a6975p-4, 0x1.a82a080d7be4cp-6, -0x1.f4e6031b3f6eap-4, + -0x1.1d34429096cc1p-5, 0x1.ebbd8db463b1dp-4, 0x1.64c7dec508b58p-5, -0x1.dfeae7fe17643p-4, + -0x1.aa6c84aa8f94ep-5, 0x1.d17e78c664a8bp-4, 0x1.edc190beb847ep-5, -0x1.c08c403ac3a27p-4, + -0x1.1734d45519fd1p-4, 0x1.ad2bc9af1afe4p-4, 0x1.36058a19d7bcdp-4, -0x1.9777eca187063p-4, + -0x1.532827e702211p-4, 0x1.7f8eceacf641bp-4, 0x1.6e74461fd5b6ep-4, -0x1.659191eed63e0p-4, + -0x1.87c3ffdf10c6ep-4, 0x1.49a44b22966acp-4, 0x1.9ef43fa0cae1ap-4, -0x1.2bedb4d70cbe6p-4, + -0x1.b3e4d51245c81p-4, 0x1.0c9704a477420p-4, 0x1.c678b3abdde67p-4, -0x1.d797776185f7fp-5, + -0x1.d69618bf1aaf6p-4, 0x1.9372a81010fe8p-5, 0x1.e426a4e2b2f1ep-4, -0x1.4d1e24c5ffd69p-5, + -0x1.ef178b2444fd3p-4, 0x1.04fb81c672a0bp-5, 0x1.f7599a2c89767p-4, -0x1.76dd97a39cc0ep-6, + -0x1.fce15f6f95d8ep-4, 0x1.c3785fe6a8e9ap-7, 0x1.ffa730c403a7fp-4, -0x1.2d86586620334p-8, + 0x1.ffa730b2e8cd7p-4, 0x1.2d86594513e0cp-8, 0x1.fce15f92ad851p-4, 0x1.c3785fca84da6p-7, + 0x1.f7599b1fd7b36p-4, 0x1.76dd98cb2facfp-6, 0x1.ef1789a91552bp-4, 0x1.04fb8285192a9p-5, + 0x1.e426a58ffbff1p-4, 0x1.4d1e25069e6e8p-5, 0x1.d696193e0229fp-4, 0x1.9372a865cdf38p-5, + 0x1.c678b5182dc66p-4, 0x1.d797772937fedp-5, 0x1.b3e4d48cfacc3p-4, 0x1.0c97044f6a336p-4, + 0x1.9ef43fc003203p-4, 0x1.2bedb4d452389p-4, 0x1.87c40108be7bap-4, 0x1.49a44a4cba3a3p-4, + 0x1.6e7445f893a63p-4, 0x1.659191d43e1f7p-4, 0x1.5328284a924a9p-4, 0x1.7f8ecd94af21dp-4, + 0x1.36058a9368ec6p-4, 0x1.9777ecc0f6f9dp-4, 0x1.1734d43b330edp-4, 0x1.ad2bc9d0d848fp-4, + 0x1.edc1907257be0p-5, 0x1.c08c3fd0b5375p-4, 0x1.aa6c851ee587bp-5, 0x1.d17e7906d5226p-4, + 0x1.64c7de35ee7bcp-5, 0x1.dfeae79158264p-4, 0x1.1d344266fd32ap-5, 0x1.ebbd8e2640abcp-4, + 0x1.a82a0803d5aabp-6, 0x1.f4e601a143d06p-4, 0x1.139f0851db958p-6, 0x1.fb57984e2f09cp-4, + 0x1.f656ebe1d45f6p-8, 0x1.ff0957535b8a7p-4, -0x1.921cbb8d102b0p-10, 0x1.fff61e9a47ce0p-4, + -0x1.5f6d0ce067ef9p-7, 0x1.fe1cae89eab54p-4, -0x1.45576bf90ebf3p-6, 0x1.f97f92b41b10dp-4, + -0x1.d934fbde54ca3p-6, 0x1.f2252ca662470p-4, -0x1.354110bb93eafp-5, 0x1.e817b99ee58d3p-4, + -0x1.7c3a95b20f7e6p-5, 0x1.db6525943cd2ap-4, -0x1.c1249abbb881dp-5, 0x1.cc1f0f4f795adp-4, + -0x1.01cfc7f2fa47ap-4, 0x1.ba5aa57c4e9f8p-4, -0x1.21a79a02c4396p-4, 0x1.a630926d0393ap-4, + -0x1.3fed981af94cep-4, 0x1.8fbcc68667387p-4, -0x1.5c77bcd833334p-4, 0x1.771e77550a377p-4, + -0x1.771e77550a377p-4, 0x1.5c77bcd833334p-4, -0x1.8fbcc68667387p-4, 0x1.3fed981af94cep-4, + -0x1.a630926d0393ap-4, 0x1.21a79a02c4396p-4, -0x1.ba5aa57c4e9f8p-4, 0x1.01cfc7f2fa47ap-4, + -0x1.cc1f0f4f795adp-4, 0x1.c1249abbb881dp-5, -0x1.db6525943cd2ap-4, 0x1.7c3a95b20f7e6p-5, + -0x1.e817b99ee58d3p-4, 0x1.354110bb93eafp-5, -0x1.f2252ca662470p-4, 0x1.d934fbde54ca3p-6, + -0x1.f97f92b41b10dp-4, 0x1.45576bf90ebf3p-6, -0x1.fe1cae89eab54p-4, 0x1.5f6d0ce067ef9p-7, + -0x1.fff61e9a47ce0p-4, 0x1.921cbb8d102b0p-10, -0x1.ff0957535b8a7p-4, -0x1.f656ebe1d45f6p-8, + -0x1.fb57984e2f09cp-4, -0x1.139f0851db958p-6, -0x1.f4e601a143d06p-4, -0x1.a82a0803d5aabp-6, + -0x1.ebbd8e2640abcp-4, -0x1.1d344266fd32ap-5, -0x1.dfeae79158264p-4, -0x1.64c7de35ee7bcp-5, + -0x1.d17e7906d5226p-4, -0x1.aa6c851ee587bp-5, -0x1.c08c3fd0b5375p-4, -0x1.edc1907257be0p-5, + -0x1.ad2bc9d0d848fp-4, -0x1.1734d43b330edp-4, -0x1.9777ecc0f6f9dp-4, -0x1.36058a9368ec6p-4, + -0x1.7f8ecd94af21dp-4, -0x1.5328284a924a9p-4, -0x1.659191d43e1f7p-4, -0x1.6e7445f893a63p-4, + -0x1.49a44a4cba3a3p-4, -0x1.87c40108be7bap-4, -0x1.2bedb4d452389p-4, -0x1.9ef43fc003203p-4, + -0x1.0c97044f6a336p-4, -0x1.b3e4d48cfacc3p-4, -0x1.d797772937fedp-5, -0x1.c678b5182dc66p-4, + -0x1.9372a865cdf38p-5, -0x1.d696193e0229fp-4, -0x1.4d1e25069e6e8p-5, -0x1.e426a58ffbff1p-4, + -0x1.04fb8285192a9p-5, -0x1.ef1789a91552bp-4, -0x1.76dd98cb2facfp-6, -0x1.f7599b1fd7b36p-4, + -0x1.c3785fca84da6p-7, -0x1.fce15f92ad851p-4, -0x1.2d86594513ee6p-8, -0x1.ffa730b2e8cd9p-4, + 0x1.9fd0ec48ee8afp-3, -0x1.b7c79e0eea43dp-8, -0x1.606d54b837f73p-4, 0x1.d35a34c1a50b8p-7, + 0x1.8d8f39604ae43p-4, -0x1.6741efb271125p-7, -0x1.227330f01b36ap-9, 0x1.0bc41996d8cccp-6, + 0x1.31c2e6f1fec5ap-5, 0x1.6a4f07a143ed7p-6, -0x1.a4dde34d1c604p-7, 0x1.6d2fb341f6a35p-5, + -0x1.0059dd4cb3f39p-5, -0x1.5cb23ab9223a0p-5, 0x1.97d970820b836p-3, -0x1.a5383885d872fp-4, + 0x1.a270448fdf651p-12, 0x1.ddff64c2cdea7p-7, -0x1.69adda3b89edcp-7, 0x1.269478ed49212p-4, + -0x1.000272c2e445ep-5, -0x1.f16d3151754a4p-5, -0x1.215a585d31efcp-3, 0x1.ac9d136736258p-5, + 0x1.0a4d42eeaeec0p-4, 0x1.7601915b2deacp-3, 0x1.4e7e2746b936fp-10, -0x1.e43bd7fd2d6f5p-4, + 0x1.c1df09ff7ba23p-4, 0x1.a1fccd310f862p-4, 0x1.1d1ed4f9068d6p-4, -0x1.03c4f8d71fd01p-3, + 0x1.6f206fbb19e67p-6, 0x1.a105e2fa226fcp-9, 0x1.9c90ccab8314bp-7, -0x1.6967e7b9a5c25p-5, + -0x1.c3650cd1a1050p-6, 0x1.7ada2f8da5cb8p-5, -0x1.21e330400fb23p-6, 0x1.e4b7f0c47ae32p-6, + 0x1.17b9d648a65a1p-6, -0x1.0100188600528p-3, -0x1.2c3dce394b0d8p-8, -0x1.b0ac568bdd635p-3, + -0x1.d2232fc45b457p-8, 0x1.1deffd83ddcb6p-3, 0x1.01262325d286dp-8, -0x1.f9ba626c221b7p-3, + -0x1.24c9122d464d5p-8, 0x1.a35fdb3a62bbfp-8, -0x1.fad371fbbfa9fp-6, -0x1.7a29a6a753012p-5, + 0x1.0976009af5625p-7, 0x1.22e94e6a42dc3p-6, -0x1.22cee1648803bp-4, -0x1.1e3bddbc3506fp-4, + 0x1.93c856cd16363p-6, 0x1.e81566543d876p-5, -0x1.0b829f9888b5ap-5, 0x1.ac8b6f5b7ae52p-3, + 0x1.59430c97a2eb9p-6, -0x1.b3f814389d915p-3, 0x1.ced14e6bd048ep-7, 0x1.fdff996b81f3bp-8, + -0x1.fdff996b81f3bp-8, -0x1.ced14e6bd048ep-7, 0x1.b3f814389d915p-3, -0x1.59430c97a2eb9p-6, + -0x1.ac8b6f5b7ae52p-3, 0x1.0b829f9888b5ap-5, -0x1.e81566543d876p-5, -0x1.93c856cd16363p-6, + 0x1.1e3bddbc3506fp-4, 0x1.22cee1648803bp-4, -0x1.22e94e6a42dc3p-6, -0x1.0976009af5625p-7, + 0x1.7a29a6a753012p-5, 0x1.fad371fbbfa9fp-6, -0x1.a35fdb3a62bbfp-8, 0x1.24c9122d464d5p-8, + 0x1.f9ba626c221b7p-3, -0x1.01262325d286dp-8, -0x1.1deffd83ddcb6p-3, 0x1.d2232fc45b457p-8, + 0x1.b0ac568bdd635p-3, 0x1.2c3dce394b0d8p-8, 0x1.0100188600528p-3, -0x1.17b9d648a65a1p-6, + -0x1.e4b7f0c47ae32p-6, 0x1.21e330400fb23p-6, -0x1.7ada2f8da5cb8p-5, 0x1.c3650cd1a1050p-6, + 0x1.6967e7b9a5c25p-5, -0x1.9c90ccab8314bp-7, -0x1.a105e2fa226fcp-9, -0x1.6f206fbb19e67p-6, + 0x1.03c4f8d71fd01p-3, -0x1.1d1ed4f9068d6p-4, -0x1.a1fccd310f862p-4, -0x1.c1df09ff7ba23p-4, + 0x1.e43bd7fd2d6f5p-4, -0x1.4e7e2746b936fp-10, -0x1.7601915b2deacp-3, -0x1.0a4d42eeaeec0p-4, + -0x1.ac9d136736258p-5, 0x1.215a585d31efcp-3, 0x1.f16d3151754a4p-5, 0x1.000272c2e445ep-5, + -0x1.269478ed49212p-4, 0x1.69adda3b89edcp-7, -0x1.ddff64c2cdea7p-7, -0x1.a270448fdf651p-12, + 0x1.a5383885d872fp-4, -0x1.97d970820b836p-3, 0x1.5cb23ab9223a0p-5, 0x1.0059dd4cb3f39p-5, + -0x1.6d2fb341f6a35p-5, 0x1.a4dde34d1c604p-7, -0x1.6a4f07a143ed7p-6, -0x1.31c2e6f1fec5ap-5, + -0x1.0bc41996d8cccp-6, 0x1.227330f01b36ap-9, 0x1.6741efb27111ep-7, -0x1.8d8f39604ae44p-4, + -0x1.d35a34c1a50eap-7, 0x1.606d54b837f73p-4, 0x1.b7c7b60570372p-8, -0x1.9fd0ec29d8366p-3, + -0x1.3ce06aae700e2p-6, -0x1.cf33aea034213p-7, 0x1.b04a67c2e2abbp-8, -0x1.21660a867508cp-2, + 0x1.163ee8a7407dap-5, -0x1.8bbaf6f4d21cbp-6, -0x1.a58e86df468c0p-6, -0x1.0447af27f8468p-2, + -0x1.737480f9ad143p-5, 0x1.80ad8d5d175c4p-4, 0x1.e27a540a4fbfbp-9, 0x1.e0c0689684a18p-5, + 0x1.b4ecfa18f6738p-9, -0x1.68e18f3fea5d6p-4, 0x1.f1ef0db16610ep-8, -0x1.b1a966f95d967p-5, + -0x1.7ac2dcb38db70p-4, 0x1.41b9326af4326p-3, 0x1.1b2a9e72cc1dep-6, 0x1.49457716fdf09p-3, + 0x1.338df76861a31p-4, -0x1.a4fa305f6abdep-4, -0x1.fda0ee7e2bdf1p-7, 0x1.1b63dc125f3acp-3, + 0x1.bc0aaa2efdb82p-5, -0x1.24d105d7f1c97p-8, -0x1.af993f4101711p-5, -0x1.ea808a12053dfp-6, + 0x1.c0ada588f3f50p-7, -0x1.3d58bb18534c6p-4, 0x1.db5da24f063c3p-6, 0x1.0592029936723p-5, + -0x1.b71d0d1c5fec1p-4, 0x1.4cf0904845d14p-5, -0x1.3834ede522e27p-3, 0x1.0c1d54222281fp-5, + 0x1.7fcccc1422653p-6, -0x1.7ea5629cd4e53p-6, 0x1.b03ec2704910ap-5, -0x1.ef05cde808bbcp-6, + 0x1.6beeb5aa5bb4ep-3, 0x1.d447f695a9d98p-6, 0x1.057e3b07602dcp-5, 0x1.4e3bc89c9c1a1p-5, + -0x1.04a4abadff4aep-2, -0x1.dd22fefe6a6d4p-7, -0x1.119bfd12a6647p-3, 0x1.e0941dac636cbp-7, + 0x1.df617c22ce488p-6, 0x1.03dff36007573p-5, -0x1.e1aed8e037f76p-4, -0x1.1b79968db0694p-5, + 0x1.6a08f84de2af3p-6, -0x1.0f01c295448edp-11, 0x1.dadb5e0876071p-4, -0x1.a5bc58b1c426cp-8, + 0x1.96a76b3116e4dp-4, 0x1.7e9f8824925f8p-5, -0x1.bf33bb75f37c7p-5, -0x1.2f8cd389cdf52p-4, + 0x1.6ed33b24b4f13p-7, -0x1.ce239f24da43cp-7, 0x1.8bf221c6f1ff0p-5, 0x1.e2904d81e95c5p-5, + -0x1.e2904d81e95c5p-5, -0x1.8bf221c6f1ff0p-5, 0x1.ce239f24da43cp-7, -0x1.6ed33b24b4f13p-7, + 0x1.2f8cd389cdf52p-4, 0x1.bf33bb75f37c7p-5, -0x1.7e9f8824925f8p-5, -0x1.96a76b3116e4dp-4, + 0x1.a5bc58b1c426cp-8, -0x1.dadb5e0876071p-4, 0x1.0f01c295448edp-11, -0x1.6a08f84de2af3p-6, + 0x1.1b79968db0694p-5, 0x1.e1aed8e037f76p-4, -0x1.03dff36007573p-5, -0x1.df617c22ce488p-6, + -0x1.e0941dac636cbp-7, 0x1.119bfd12a6647p-3, 0x1.dd22fefe6a6d4p-7, 0x1.04a4abadff4aep-2, + -0x1.4e3bc89c9c1a1p-5, -0x1.057e3b07602dcp-5, -0x1.d447f695a9d98p-6, -0x1.6beeb5aa5bb4ep-3, + 0x1.ef05cde808bbcp-6, -0x1.b03ec2704910ap-5, 0x1.7ea5629cd4e53p-6, -0x1.7fcccc1422653p-6, + -0x1.0c1d54222281fp-5, 0x1.3834ede522e27p-3, -0x1.4cf0904845d14p-5, 0x1.b71d0d1c5fec1p-4, + -0x1.0592029936723p-5, -0x1.db5da24f063c3p-6, 0x1.3d58bb18534c6p-4, -0x1.c0ada588f3f50p-7, + 0x1.ea808a12053dfp-6, 0x1.af993f4101711p-5, 0x1.24d105d7f1c97p-8, -0x1.bc0aaa2efdb82p-5, + -0x1.1b63dc125f3acp-3, 0x1.fda0ee7e2bdf1p-7, 0x1.a4fa305f6abdep-4, -0x1.338df76861a31p-4, + -0x1.49457716fdf09p-3, -0x1.1b2a9e72cc1dep-6, -0x1.41b9326af4326p-3, 0x1.7ac2dcb38db70p-4, + 0x1.b1a966f95d967p-5, -0x1.f1ef0db16610ep-8, 0x1.68e18f3fea5d6p-4, -0x1.b4ecfa18f6738p-9, + -0x1.e0c0689684a18p-5, -0x1.e27a540a4fbfbp-9, -0x1.80ad8d5d175c4p-4, 0x1.737480f9ad143p-5, + 0x1.0447af27f8468p-2, 0x1.a58e86df468bfp-6, 0x1.8bbaf6f4d21c0p-6, -0x1.163ee8a7407dap-5, + 0x1.21660a867508cp-2, -0x1.b04a67c2e2ad0p-8, 0x1.cf33aca5f37b5p-7, 0x1.3ce06a2db083dp-6, + 0x1.921d2a22794b3p-10, -0x1.fff622cd23717p-4, -0x1.2d863fe59fcc5p-8, 0x1.ffa72f3ecc670p-4, + 0x1.f657028dc303bp-8, -0x1.ff09519332712p-4, -0x1.5f6cfcb1e5395p-7, 0x1.fe1cb18ed39c9p-4, + 0x1.c3785f012d77cp-7, -0x1.fce15f9430f29p-4, -0x1.139f05b6193cap-6, 0x1.fb5798a7ad5b1p-4, + 0x1.45576dcaa4be3p-6, -0x1.f97f94e81b99cp-4, -0x1.76dda057805dcp-6, 0x1.f7599d11d9985p-4, + 0x1.a82a00dabfc51p-6, -0x1.f4e60308b41f7p-4, -0x1.d934f35940795p-6, 0x1.f22530643c13cp-4, + 0x1.04fb84ff90821p-5, -0x1.ef178c1bca0e3p-4, -0x1.1d3441c25e95bp-5, 0x1.ebbd8b6bd79f6p-4, + 0x1.35410bbd049cap-5, -0x1.e817bad12a397p-4, -0x1.4d1e21e4d5e61p-5, 0x1.e426a25fd3250p-4, + 0x1.64c7db5c650e0p-5, -0x1.dfeae5df955b4p-4, -0x1.7c3a8fc6dc1a6p-5, 0x1.db6527314fc9fp-4, + 0x1.9372a7b8004a8p-5, -0x1.d69615e51be8ap-4, -0x1.aa6c844119155p-5, 0x1.d17e795652423p-4, + 0x1.c1249c09c35a6p-5, -0x1.cc1f0cbf3457bp-4, -0x1.d797759361166p-5, 0x1.c678b3af81b0fp-4, + 0x1.edc1959246be8p-5, -0x1.c08c42fd41b09p-4, -0x1.01cfc85af07a6p-4, 0x1.ba5aa7b72bc52p-4, + 0x1.0c970889d0149p-4, -0x1.b3e4d2d8b0456p-4, -0x1.1734d5b3fccd1p-4, 0x1.ad2bc8d479e08p-4, + 0x1.21a7966f69587p-4, -0x1.a6308d5eabd57p-4, -0x1.2bedb00dce523p-4, 0x1.9ef43eac98e1fp-4, + 0x1.36058b84a0603p-4, -0x1.9777f0db901d3p-4, -0x1.3fed93fc0dc0fp-4, 0x1.8fbccb961ca97p-4, + 0x1.49a449d6ef2ffp-4, -0x1.87c3fefe4d549p-4, -0x1.5328277b4c520p-4, 0x1.7f8eceebed530p-4, + 0x1.5c77bda7bc072p-4, -0x1.771e797c8c3cep-4, -0x1.65919294ea34cp-4, 0x1.6e7444f7fabf6p-4, + 0x1.6e7444f7fabf6p-4, -0x1.65919294ea34cp-4, -0x1.771e797c8c3cep-4, 0x1.5c77bda7bc072p-4, + 0x1.7f8eceebed530p-4, -0x1.5328277b4c520p-4, -0x1.87c3fefe4d549p-4, 0x1.49a449d6ef2ffp-4, + 0x1.8fbccb961ca97p-4, -0x1.3fed93fc0dc0fp-4, -0x1.9777f0db901d3p-4, 0x1.36058b84a0603p-4, + 0x1.9ef43eac98e1fp-4, -0x1.2bedb00dce523p-4, -0x1.a6308d5eabd57p-4, 0x1.21a7966f69587p-4, + 0x1.ad2bc8d479e08p-4, -0x1.1734d5b3fccd1p-4, -0x1.b3e4d2d8b0456p-4, 0x1.0c970889d0149p-4, + 0x1.ba5aa7b72bc52p-4, -0x1.01cfc85af07a6p-4, -0x1.c08c42fd41b09p-4, 0x1.edc1959246be8p-5, + 0x1.c678b3af81b0fp-4, -0x1.d797759361166p-5, -0x1.cc1f0cbf3457bp-4, 0x1.c1249c09c35a6p-5, + 0x1.d17e795652423p-4, -0x1.aa6c844119155p-5, -0x1.d69615e51be8ap-4, 0x1.9372a7b8004a8p-5, + 0x1.db6527314fc9fp-4, -0x1.7c3a8fc6dc1a6p-5, -0x1.dfeae5df955b4p-4, 0x1.64c7db5c650e0p-5, + 0x1.e426a25fd3250p-4, -0x1.4d1e21e4d5e61p-5, -0x1.e817bad12a397p-4, 0x1.35410bbd049cap-5, + 0x1.ebbd8b6bd79f6p-4, -0x1.1d3441c25e95bp-5, -0x1.ef178c1bca0e3p-4, 0x1.04fb84ff90821p-5, + 0x1.f22530643c13cp-4, -0x1.d934f35940795p-6, -0x1.f4e60308b41f7p-4, 0x1.a82a00dabfc51p-6, + 0x1.f7599d11d9985p-4, -0x1.76dda057805dcp-6, -0x1.f97f94e81b99cp-4, 0x1.45576dcaa4be3p-6, + 0x1.fb5798a7ad5b1p-4, -0x1.139f05b6193cap-6, -0x1.fce15f9430f29p-4, 0x1.c3785f012d77cp-7, + 0x1.fe1cb18ed39c9p-4, -0x1.5f6cfcb1e5395p-7, -0x1.ff09519332712p-4, 0x1.f657028dc303bp-8, + 0x1.ffa72f3ecc670p-4, -0x1.2d863fe59fcc5p-8, -0x1.fff622cd23717p-4, 0x1.921d2a22798bbp-10, + 0x1.fff62261dad1dp-4, 0x1.921d34cabf15ap-10, 0x1.ffa72f3151772p-4, 0x1.2d863bcf0acc5p-8, + 0x1.ff095266cb4b7p-4, 0x1.f65705e19eb06p-8, 0x1.fe1cb02862b1ep-4, 0x1.5f6cfb16faab4p-7, + 0x1.fce15e6c8ceacp-4, 0x1.c3786010d40bbp-7, 0x1.fb5798efa1da1p-4, 0x1.139f0552c4cfap-6, + 0x1.f97f940e23751p-4, 0x1.45576fa8673aap-6, 0x1.f7599c396fcd5p-4, 0x1.76dd9ff20a8aap-6, + 0x1.f4e602b07ebf2p-4, 0x1.a82a015c7fba9p-6, 0x1.f2252fd763853p-4, 0x1.d934f4206a675p-6, + 0x1.ef178c48331f8p-4, 0x1.04fb8556c9e01p-5, 0x1.ebbd8b7c9d1ffp-4, 0x1.1d34425d5b255p-5, + 0x1.e817ba161c5a9p-4, 0x1.35410d1583e1bp-5, 0x1.e426a1c9b959ap-4, 0x1.4d1e21be07840p-5, + 0x1.dfeae6940d93fp-4, 0x1.64c7dac9f71b9p-5, 0x1.db6527101590ep-4, 0x1.7c3a90548e47ep-5, + 0x1.d696164bb3ed7p-4, 0x1.9372a65721e14p-5, 0x1.d17e79e141d48p-4, 0x1.aa6c84eccabe1p-5, + 0x1.cc1f0d103a0f6p-4, 0x1.c1249d387b5ffp-5, 0x1.c678b53bfc8b6p-4, 0x1.d7977685e1f01p-5, + 0x1.c08c427eb3eb1p-4, 0x1.edc1953affd94p-5, 0x1.ba5aa6a8093c8p-4, 0x1.01cfc8a038d02p-4, + 0x1.b3e4d2e84f48ep-4, 0x1.0c9708d5a4c6bp-4, 0x1.ad2bc9ee35593p-4, 0x1.1734d68a022b5p-4, + 0x1.a6308ec1a22f1p-4, 0x1.21a7967c3f788p-4, 0x1.9ef43e63e1a97p-4, 0x1.2bedb07308b36p-4, + 0x1.9777f0a4a8d61p-4, 0x1.36058c8d9b935p-4, 0x1.8fbccad44e6d3p-4, 0x1.3fed94ba9679fp-4, + 0x1.87c3fefc62b13p-4, 0x1.49a44aa3f9547p-4, 0x1.7f8ece436747fp-4, 0x1.5328282d690b3p-4, + 0x1.771e785ae9189p-4, 0x1.5c77bd81c2f38p-4, 0x1.6e744589a2447p-4, 0x1.6591926d7b71dp-4, + 0x1.6591926d7b71dp-4, 0x1.6e744589a2447p-4, 0x1.5c77bd81c2f38p-4, 0x1.771e785ae9189p-4, + 0x1.5328282d690b3p-4, 0x1.7f8ece436747fp-4, 0x1.49a44aa3f9547p-4, 0x1.87c3fefc62b13p-4, + 0x1.3fed94ba9679fp-4, 0x1.8fbccad44e6d3p-4, 0x1.36058c8d9b935p-4, 0x1.9777f0a4a8d61p-4, + 0x1.2bedb07308b36p-4, 0x1.9ef43e63e1a97p-4, 0x1.21a7967c3f788p-4, 0x1.a6308ec1a22f1p-4, + 0x1.1734d68a022b5p-4, 0x1.ad2bc9ee35593p-4, 0x1.0c9708d5a4c6bp-4, 0x1.b3e4d2e84f48ep-4, + 0x1.01cfc8a038d02p-4, 0x1.ba5aa6a8093c8p-4, 0x1.edc1953affd94p-5, 0x1.c08c427eb3eb1p-4, + 0x1.d7977685e1f01p-5, 0x1.c678b53bfc8b6p-4, 0x1.c1249d387b5ffp-5, 0x1.cc1f0d103a0f6p-4, + 0x1.aa6c84eccabe1p-5, 0x1.d17e79e141d48p-4, 0x1.9372a65721e14p-5, 0x1.d696164bb3ed7p-4, + 0x1.7c3a90548e47ep-5, 0x1.db6527101590ep-4, 0x1.64c7dac9f71b9p-5, 0x1.dfeae6940d93fp-4, + 0x1.4d1e21be07840p-5, 0x1.e426a1c9b959ap-4, 0x1.35410d1583e1bp-5, 0x1.e817ba161c5a9p-4, + 0x1.1d34425d5b255p-5, 0x1.ebbd8b7c9d1ffp-4, 0x1.04fb8556c9e01p-5, 0x1.ef178c48331f8p-4, + 0x1.d934f4206a675p-6, 0x1.f2252fd763853p-4, 0x1.a82a015c7fba9p-6, 0x1.f4e602b07ebf2p-4, + 0x1.76dd9ff20a8aap-6, 0x1.f7599c396fcd5p-4, 0x1.45576fa8673aap-6, 0x1.f97f940e23751p-4, + 0x1.139f0552c4cfap-6, 0x1.fb5798efa1da1p-4, 0x1.c3786010d40bbp-7, 0x1.fce15e6c8ceacp-4, + 0x1.5f6cfb16faab4p-7, 0x1.fe1cb02862b1ep-4, 0x1.f65705e19eb06p-8, 0x1.ff095266cb4b7p-4, + 0x1.2d863bcf0acc5p-8, 0x1.ffa72f3151772p-4, 0x1.921d34cabe876p-10, 0x1.fff62261dad1ap-4, + -0x1.23d1d60df2e15p-3, 0x1.a04ed42b10310p-8, 0x1.7110575dc1186p-7, -0x1.e6a4a177499f2p-8, + -0x1.fd59dc38b2e13p-5, -0x1.f07676ebe9a5ep-9, 0x1.91fb308729974p-7, -0x1.b459038501478p-11, + 0x1.3381557898d92p-4, 0x1.903aec8d3db1bp-7, 0x1.dfbcb524ab89dp-6, -0x1.d4ef27e413d62p-6, + 0x1.021597a47816ep-3, 0x1.e187646de6efcp-7, 0x1.2f443c4765520p-3, 0x1.09d72e8081b9ep-6, + -0x1.5653937d7c72ep-3, -0x1.46e79b4be7b9dp-5, 0x1.626b78ad4e598p-6, 0x1.4eea8953f3826p-6, + -0x1.b7f91ec2629b0p-6, 0x1.969a0d8aed73ap-8, -0x1.604aba9f9f033p-3, -0x1.097036fc1b9dbp-5, + -0x1.42070eb0ebf7bp-3, 0x1.d751fc26d72e7p-7, -0x1.6f60c49eb1bffp-9, 0x1.d8e84d5e6358ap-6, + 0x1.1eaa5aecf4f33p-4, -0x1.79c1ed323ff3dp-5, 0x1.cab5659efda77p-3, 0x1.1b5d7b0066fcbp-4, + -0x1.8c6cc94e8cb1bp-3, -0x1.a08883b974e77p-6, -0x1.53903eca79c68p-5, -0x1.f74385c93b851p-5, + -0x1.b8ba23c3a0747p-6, -0x1.08d2fe33802d2p-4, -0x1.66507539216e9p-3, 0x1.5a88c7e746216p-5, + 0x1.cf49b757c21f3p-3, 0x1.1b2e32dfad8dcp-3, 0x1.22c030b82ecbfp-3, -0x1.7ea1e4a3eba38p-5, + 0x1.0964126d2b9bap-5, 0x1.82b3a68cc14c5p-5, -0x1.72d7a82ca10f7p-13, -0x1.2feec27d910cap-5, + 0x1.48e8d6a677ac6p-4, -0x1.dfafe29e0b4d0p-7, -0x1.1e179f3061a71p-3, -0x1.59298c154b496p-5, + 0x1.6c609c46c9e8cp-3, -0x1.3277664af302fp-5, -0x1.0a1ebef2a9400p-4, -0x1.c9efefd7b469bp-6, + 0x1.9efb9f6a10025p-4, 0x1.26146777a508dp-4, 0x1.56d94c0fbff18p-8, -0x1.698cf7f390465p-5, + -0x1.cb9edf8571682p-4, 0x1.2bf87fbe204a1p-4, -0x1.7865b79927347p-8, 0x1.7d6eda43ba218p-6, + 0x1.7d6eda43ba218p-6, -0x1.7865b79927347p-8, 0x1.2bf87fbe204a1p-4, -0x1.cb9edf8571682p-4, + -0x1.698cf7f390465p-5, 0x1.56d94c0fbff18p-8, 0x1.26146777a508dp-4, 0x1.9efb9f6a10025p-4, + -0x1.c9efefd7b469bp-6, -0x1.0a1ebef2a9400p-4, -0x1.3277664af302fp-5, 0x1.6c609c46c9e8cp-3, + -0x1.59298c154b496p-5, -0x1.1e179f3061a71p-3, -0x1.dfafe29e0b4d0p-7, 0x1.48e8d6a677ac6p-4, + -0x1.2feec27d910cap-5, -0x1.72d7a82ca10f7p-13, 0x1.82b3a68cc14c5p-5, 0x1.0964126d2b9bap-5, + -0x1.7ea1e4a3eba38p-5, 0x1.22c030b82ecbfp-3, 0x1.1b2e32dfad8dcp-3, 0x1.cf49b757c21f3p-3, + 0x1.5a88c7e746216p-5, -0x1.66507539216e9p-3, -0x1.08d2fe33802d2p-4, -0x1.b8ba23c3a0747p-6, + -0x1.f74385c93b851p-5, -0x1.53903eca79c68p-5, -0x1.a08883b974e77p-6, -0x1.8c6cc94e8cb1bp-3, + 0x1.1b5d7b0066fcbp-4, 0x1.cab5659efda77p-3, -0x1.79c1ed323ff3dp-5, 0x1.1eaa5aecf4f33p-4, + 0x1.d8e84d5e6358ap-6, -0x1.6f60c49eb1bffp-9, 0x1.d751fc26d72e7p-7, -0x1.42070eb0ebf7bp-3, + -0x1.097036fc1b9dbp-5, -0x1.604aba9f9f033p-3, 0x1.969a0d8aed73ap-8, -0x1.b7f91ec2629b0p-6, + 0x1.4eea8953f3826p-6, 0x1.626b78ad4e598p-6, -0x1.46e79b4be7b9dp-5, -0x1.5653937d7c72ep-3, + 0x1.09d72e8081b9ep-6, 0x1.2f443c4765520p-3, 0x1.e187646de6efcp-7, 0x1.021597a47816ep-3, + -0x1.d4ef27e413d62p-6, 0x1.dfbcb524ab89dp-6, 0x1.903aec8d3db1bp-7, 0x1.3381557898d92p-4, + -0x1.b459038501478p-11, 0x1.91fb308729974p-7, -0x1.f07676ebe9b22p-9, -0x1.fd59dc38b2e11p-5, + -0x1.e6a4a177499e8p-8, 0x1.7110575dc11b8p-7, 0x1.a04effd83473ep-8, -0x1.23d1d5ff553c2p-3, + 0x1.ea4a2054522cbp-5, -0x1.91aa24f24daa5p-9, 0x1.ec2754862088dp-6, -0x1.aa17ec92dafaep-3, + 0x1.a5181b052de58p-5, -0x1.32b23a6f77f9ep-4, 0x1.684ccd857c9b0p-5, 0x1.152b6c4bc585ap-8, + 0x1.b7810d033ab4cp-8, 0x1.d409318bbd9dep-4, 0x1.69fafacc708bfp-6, -0x1.68a10b3ceecccp-5, + 0x1.b31d43585eddap-5, -0x1.34b956b4c3520p-5, 0x1.b3e0955f705b1p-7, -0x1.6898109736af2p-5, + 0x1.3b24b27a6d9bep-4, 0x1.3b0c95fe6ab8bp-4, -0x1.60870bceae277p-6, -0x1.0d3b05cbb461dp-3, + 0x1.7de8b32e8af47p-7, -0x1.6ee40f47e92b3p-3, -0x1.849a5658be5bbp-11, -0x1.adc23c50e7f59p-5, + 0x1.0504186ac1d06p-3, -0x1.28e2582be349ap-4, 0x1.1f3ff90178b10p-7, 0x1.04a9376290715p-3, + -0x1.f466eaf9b92a1p-5, -0x1.d7760f3d64cc5p-3, -0x1.39ef980fa6a26p-4, -0x1.10c6301b83d91p-3, + 0x1.91f2eaef10d64p-6, -0x1.3ab43d591c080p-4, 0x1.e43290b6bdd33p-9, -0x1.415ccf89366dap-3, + 0x1.992ca3a6f755ep-4, -0x1.3797a09d77659p-7, 0x1.fc4776b1e0996p-7, 0x1.727f32ab699a2p-3, + -0x1.d8c65040f9b0fp-4, -0x1.614418239ac06p-5, -0x1.8afe7e771d112p-7, -0x1.0ed5c8ea1c059p-3, + -0x1.73655be98d193p-5, 0x1.f36bd7b695ccep-5, -0x1.840ed03770760p-4, -0x1.bb4745f6a0d12p-5, + 0x1.0be4b328de1afp-4, -0x1.679137152f324p-3, -0x1.5c3296341c640p-6, -0x1.a07b50da5e1b8p-6, + 0x1.403666109fd34p-4, 0x1.028a11f0baa2dp-4, -0x1.df23e98077e63p-5, -0x1.5000779f5dee2p-4, + 0x1.23bcb8ec241d3p-3, 0x1.21c7c1329bcd8p-4, -0x1.9f77e1baa2484p-5, 0x1.b79bd1667231fp-7, + -0x1.754ff72455876p-4, 0x1.1dd437a1954f5p-3, -0x1.67c30495d8a05p-6, -0x1.54909298a69f0p-8, + -0x1.54909298a69f0p-8, -0x1.67c30495d8a05p-6, 0x1.1dd437a1954f5p-3, -0x1.754ff72455876p-4, + 0x1.b79bd1667231fp-7, -0x1.9f77e1baa2484p-5, 0x1.21c7c1329bcd8p-4, 0x1.23bcb8ec241d3p-3, + -0x1.5000779f5dee2p-4, -0x1.df23e98077e63p-5, 0x1.028a11f0baa2dp-4, 0x1.403666109fd34p-4, + -0x1.a07b50da5e1b8p-6, -0x1.5c3296341c640p-6, -0x1.679137152f324p-3, 0x1.0be4b328de1afp-4, + -0x1.bb4745f6a0d12p-5, -0x1.840ed03770760p-4, 0x1.f36bd7b695ccep-5, -0x1.73655be98d193p-5, + -0x1.0ed5c8ea1c059p-3, -0x1.8afe7e771d112p-7, -0x1.614418239ac06p-5, -0x1.d8c65040f9b0fp-4, + 0x1.727f32ab699a2p-3, 0x1.fc4776b1e0996p-7, -0x1.3797a09d77659p-7, 0x1.992ca3a6f755ep-4, + -0x1.415ccf89366dap-3, 0x1.e43290b6bdd33p-9, -0x1.3ab43d591c080p-4, 0x1.91f2eaef10d64p-6, + -0x1.10c6301b83d91p-3, -0x1.39ef980fa6a26p-4, -0x1.d7760f3d64cc5p-3, -0x1.f466eaf9b92a1p-5, + 0x1.04a9376290715p-3, 0x1.1f3ff90178b10p-7, -0x1.28e2582be349ap-4, 0x1.0504186ac1d06p-3, + -0x1.adc23c50e7f59p-5, -0x1.849a5658be5bbp-11, -0x1.6ee40f47e92b3p-3, 0x1.7de8b32e8af47p-7, + -0x1.0d3b05cbb461dp-3, -0x1.60870bceae277p-6, 0x1.3b0c95fe6ab8bp-4, 0x1.3b24b27a6d9bep-4, + -0x1.6898109736af2p-5, 0x1.b3e0955f705b1p-7, -0x1.34b956b4c3520p-5, 0x1.b31d43585eddap-5, + -0x1.68a10b3ceecccp-5, 0x1.69fafacc708bfp-6, 0x1.d409318bbd9dep-4, 0x1.b7810d033ab4cp-8, + 0x1.152b6c4bc585ap-8, 0x1.684ccd857c9afp-5, -0x1.32b23a6f77f9dp-4, 0x1.a5181b052de5ep-5, + -0x1.aa17ec92dafafp-3, 0x1.ec27548620894p-6, -0x1.91aa37d82caa1p-9, 0x1.ea4a1f1af02f3p-5, +}; + +// qmf_synthesis_taps: 64x10x4 float64, sha256 cd7756d060d51fbf +const double qmf_synthesis_taps[2560] = { + -0x1.b813996d9c4d5p-55, -0x1.05aefdbb11307p-50, -0x1.d6b1ae7990e4dp-60, 0x1.adeb89b837de4p-57, + -0x1.576e83f91d644p-5, -0x1.2b6b9c672dd6cp-32, -0x1.79f785a36d7fap-31, 0x1.4b5594e20cd41p-33, + 0x1.314a992d8c80dp-37, -0x1.b2e41c11925c4p-3, -0x1.adb579c4959a6p-32, 0x1.07f3796d8b110p-27, + -0x1.202aca17bed7ap+0, -0x1.a6fd9f037f95bp-28, -0x1.5c7d59a1df253p-25, -0x1.4cf2a477788d3p-34, + 0x1.e0dbeb56e573ap-27, -0x1.71d3aa1de6fedp+2, 0x1.f94f40b2e55a7p-37, -0x1.36636f4ac0cbbp-32, + -0x1.b51d3825f5be8p+3, -0x1.73eec1db9cdfbp-27, 0x1.cbc5e658b1fc1p-28, 0x1.96736914a45a2p-37, + -0x1.e0dbeb56e573ap-27, 0x1.71d3aa1de6fedp+2, -0x1.f94f40b2e65e4p-37, 0x1.36636f4ac14a2p-32, + -0x1.202aca17bed7ap+0, -0x1.a6fd9f037f95bp-28, -0x1.5c7d59a1df255p-25, -0x1.4cf2a47778902p-34, + -0x1.314a992d8c80dp-37, 0x1.b2e41c11925c5p-3, 0x1.adb579c5d83f1p-32, -0x1.07f3796c2b68fp-27, + -0x1.576e83f91d652p-5, -0x1.2b6b9df9ed294p-32, -0x1.79f785aa700cbp-31, 0x1.4b5594dd75090p-33, + -0x1.9333ebe777273p-37, 0x1.21af23dff19c9p-7, 0x1.5b4f968ce4a4fp-36, 0x1.8e6dfed3c972bp-39, + -0x1.6d4dc1cfdfacap-5, -0x1.e8fa7f64cf47ep-35, 0x1.32c9efb3a6535p-33, -0x1.e77c3447d396fp-31, + 0x1.cf5a8fedb799bp-32, -0x1.d78bfba82d3c3p-3, -0x1.54753ea7c1a67p-32, -0x1.2ba9a344dccfbp-30, + -0x1.1a7c83c39055ap+0, 0x1.51faca5f3a537p-29, 0x1.bc5dcee03051fp-30, -0x1.0a7e13455ae11p-25, + 0x1.d41681230167bp-27, -0x1.7d510f80b8e57p+2, -0x1.95b931a4cc109p-24, -0x1.58f6e2c521024p-33, + -0x1.b50765ddf0591p+3, -0x1.5ab24212a8597p-27, -0x1.9a113cccbad23p-34, 0x1.6812b2c9fd06dp-28, + -0x1.51ca7ccc457eap-27, 0x1.666425cef342fp+2, -0x1.afa2e4a3e1963p-24, -0x1.c85209ed4d1afp-33, + -0x1.2533d5cba2cd3p+0, -0x1.46da9fe3a42a0p-30, -0x1.f00169fd1803bp-32, -0x1.17778abc86f78p-25, + -0x1.85dda43b55264p-31, 0x1.8f472fa32b33ep-3, -0x1.5da3111280a87p-31, -0x1.0ad0d4943faedp-33, + -0x1.42c5dbcae2b0bp-5, -0x1.27f307336cf10p-35, -0x1.adf44325edce2p-41, -0x1.5997d9aeb7547p-31, + -0x1.5cdf8514f313ep-35, 0x1.268763b5aab08p-7, 0x1.7786dc22d0079p-34, 0x1.34a779ef946a5p-36, + -0x1.82430d93f5080p-5, -0x1.d483bf40dde09p-34, 0x1.6bea66d2cc2dap-34, -0x1.3280a9aa7f474p-31, + 0x1.17075f5f9a5b7p-30, -0x1.fd3b9f6e5fa15p-3, 0x1.c2427656925c7p-31, 0x1.9a6916018d6bfp-33, + -0x1.14491397debfdp+0, -0x1.6cb11bcbd7d29p-29, 0x1.93e225ddbde9ep-28, -0x1.d7698c4ab93edp-26, + 0x1.f4fa7f069377ep-26, -0x1.88d79d9d05f84p+2, 0x1.7cfdf1d842220p-24, 0x1.43889bb276d34p-30, + -0x1.b4c9cb8802597p+3, -0x1.8cdfefa1a4161p-26, -0x1.55a1c755dffc6p-31, 0x1.815a5c6579037p-28, + -0x1.bf3b1d285dfabp-26, 0x1.5b015586db19bp+2, 0x1.af53c672bda2fp-24, 0x1.6f0a9313ba28cp-30, + -0x1.29afd7b6fb35fp+0, -0x1.156eebbc7af11p-29, 0x1.f8fdd49063701p-30, -0x1.5a4b57dcffbeap-25, + -0x1.dbe600e65213ep-31, 0x1.6cc23f82d81e2p-3, 0x1.27efbf9f96c61p-30, 0x1.7f3ae12d29e77p-33, + -0x1.2db117a9f706ep-5, -0x1.df02b608c977ep-33, -0x1.d494f0d0af202p-36, -0x1.56152eee2b7ddp-31, + -0x1.3cd5e744ad3d7p-37, 0x1.036475a2db234p-7, 0x1.8a6592bec2a38p-37, -0x1.5bbfd67137ff8p-37, + -0x1.97f7934b46cacp-5, -0x1.645c757bf30adp-33, -0x1.873e3f53e549cp-33, -0x1.790197a9d28a7p-31, + -0x1.47b79415333f9p-30, -0x1.1225119fcf8bcp-2, 0x1.29cba4fe59d7fp-35, -0x1.705ef5cd15664p-30, + -0x1.0d63dd8cef728p+0, -0x1.b999552cfa78ep-30, 0x1.6fe074e9b54d8p-29, -0x1.27b4f72f12df3p-25, + 0x1.4c3f3dbe85f23p-26, -0x1.9466373b1a80bp+2, 0x1.81875cb465629p-24, -0x1.ce8ca6cc73242p-31, + -0x1.b4614767d3feap+3, -0x1.1c450f4e82c77p-26, 0x1.231a6bf8bd3d3p-31, 0x1.7b4cca58eb849p-28, + -0x1.5703dfbbb0b22p-26, 0x1.4fadc784659a1p+2, 0x1.d068d0f497de3p-24, -0x1.294a164115a98p-30, + -0x1.2da1c3b5f1cf9p+0, 0x1.8044e9696d7bcp-31, -0x1.24474dd9ed65bp-27, -0x1.1c59e6a406963p-25, + 0x1.132a061afb715p-31, 0x1.4b72f37f2880dp-3, 0x1.b31bb9b3ecb96p-32, -0x1.0f1dcca317fa6p-36, + -0x1.194d1f9d828bdp-5, -0x1.daf81d4082d68p-35, -0x1.816d544543333p-33, -0x1.956e46b4bc09fp-33, + -0x1.a28b60472934bp-35, 0x1.ff346782346fap-8, 0x1.fa1ba0b5934f9p-42, -0x1.6fe9eb05bb279p-36, + -0x1.ad1fe9d0a9944p-5, -0x1.ac960231aede1p-33, 0x1.f0440b53f301fp-33, 0x1.670f5323b20f2p-30, + 0x1.21de72ed963d0p-29, -0x1.25fbcfbfe4f3ap-2, -0x1.b155b800f094fp-32, 0x1.68946442ff019p-32, + -0x1.05eaa5bed9658p+0, -0x1.3bd2a20fe26dap-33, 0x1.bf1411475ace7p-30, 0x1.061157ccdb8b4p-25, + 0x1.639dc3be1cdedp-25, -0x1.9ffb37988be79p+2, 0x1.94569d9fab063p-24, -0x1.8339907123623p-31, + -0x1.b3d01b9046bf5p+3, -0x1.86ac363fd78b6p-26, -0x1.cf12bc9ef38cbp-32, -0x1.750a5b24f2da0p-28, + -0x1.353e50e33a421p-27, 0x1.446e87c5025b3p+2, 0x1.032e8d63b0c70p-23, -0x1.ea260e2b03a46p-31, + -0x1.3103b7c0150c0p+0, -0x1.3e52e249fef94p-28, 0x1.d3fe5b340b91cp-29, 0x1.33531aff99c4fp-25, + -0x1.0ad1bed29ede3p-31, 0x1.2b413daeb5361p-3, -0x1.9d60283112956p-33, 0x1.0d70c3eb13907p-32, + -0x1.040fd1c3e7c52p-5, -0x1.88cc1554d7b26p-33, 0x1.996bcc3c8613ap-34, 0x1.723aafcf9f9e9p-31, + -0x1.5adb8b0bf3274p-36, 0x1.00935a92001a2p-7, 0x1.88d0349ca51b5p-36, -0x1.21fa47cfb2dc1p-35, + -0x1.c32294b999a79p-5, 0x1.143134ed8761ap-33, 0x1.04c11b7bb2a11p-33, -0x1.370b7cb13107ap-31, + -0x1.b6e8ed2608078p-31, -0x1.3a5d229598aabp-2, -0x1.696a42d281826p-30, 0x1.40bdbeaab0106p-32, + -0x1.fb941ec7aae19p-1, 0x1.2a4eb9a8a39a6p-29, 0x1.34bb54ade4388p-29, -0x1.e74af434cee12p-27, + -0x1.0c722eb3e984ep-28, -0x1.ab9764b310d7fp+2, 0x1.5881c8f17511ep-24, -0x1.88d897b3528a6p-31, + -0x1.b3166eba137c9p+3, 0x1.415a2a52af1d6p-29, 0x1.33b1bb738a452p-32, 0x1.317cd7af75849p-28, + 0x1.af2594c6cfe30p-31, 0x1.3940708cf7d01p+2, 0x1.d5d931672e525p-24, -0x1.082dda7071c1bp-30, + -0x1.33d87c982aa34p+0, -0x1.aec2ccbb168d9p-29, -0x1.58e801f6abec4p-28, -0x1.4b0747c595288p-25, + -0x1.a192d48b54e6dp-36, 0x1.0c09545ba182cp-3, 0x1.f4e95323a7f67p-32, 0x1.4a3ce508ba850p-33, + -0x1.e0fd20cc6a3bfp-6, -0x1.b5ecaf7849627p-36, -0x1.acfeceee19329p-34, -0x1.7bc357210fd5bp-32, + -0x1.53bd096620543p-36, 0x1.084751b8cca1ep-7, 0x1.716bc75f2a7adp-34, 0x1.3513a522fe732p-37, + -0x1.d7f7b197c2572p-5, -0x1.2bad1653fac20p-32, 0x1.b7daefe52df28p-35, -0x1.a3b19d1f86693p-31, + 0x1.78a9c29a4c825p-30, -0x1.4f1ad9b5ce6d6p-2, -0x1.a5687d6b7176ep-31, -0x1.a872c0707127dp-32, + -0x1.ea049f3ad02b2p-1, -0x1.4e7e362e0273fp-29, -0x1.04e2c02796b34p-30, -0x1.7253f501815b5p-26, + 0x1.4e8275589365dp-26, -0x1.b734b3a3e9dcep+2, 0x1.6ec4d06e6178ap-24, 0x1.a0bb7bdc570d8p-31, + -0x1.b23131a11414bp+3, -0x1.67baafbef7489p-27, -0x1.b7bc39675628fp-32, 0x1.65e740a1b716bp-28, + -0x1.98eaee4ba4741p-29, 0x1.2e2743bffde3cp+2, 0x1.0a7418616676bp-23, 0x1.24be76dc102b9p-30, + -0x1.36314393d533bp+0, -0x1.abb103f8753d6p-29, 0x1.66e0f02e65cd9p-28, -0x1.62527eeaef996p-25, + -0x1.17b13c6e6f302p-31, 0x1.dbe51f599af43p-4, -0x1.e9528c8f4d45fp-35, 0x1.c30020079968fp-32, + -0x1.ba2fc989f622ap-6, -0x1.9805ff5e0e0d8p-33, 0x1.4fefd335d5da9p-33, -0x1.f7698041718cdp-32, + -0x1.273cfa3687b6bp-37, 0x1.1205c2020c2dap-7, 0x1.1437333a7cec5p-34, 0x1.85a9056096707p-37, + -0x1.ece1d3fd73fb3p-5, -0x1.1c1a32a56e658p-32, 0x1.229c3f491e81ep-34, -0x1.014426ee5cd39p-30, + 0x1.2330cad56ca96p-33, -0x1.644c7ff379f77p-2, -0x1.a3bde1ff8c8d2p-31, -0x1.09492bf873c4ap-30, + -0x1.d72a43e193140p-1, -0x1.ceb7f6ca52d1dp-30, 0x1.c0081606ab4fep-29, -0x1.609ff65bd8f22p-26, + 0x1.a7f1c2ebccfe3p-26, -0x1.c2d24df879445p+2, 0x1.09e7a84dbf71ep-24, -0x1.203c26ce2cc2dp-31, + -0x1.b1248829c358fp+3, -0x1.1958b1be2f8d7p-26, 0x1.38a5b4dd4f437p-33, 0x1.787e932a0d83bp-28, + -0x1.8276208744127p-27, 0x1.23252810beaa1p+2, 0x1.9b79e821fb72bp-24, -0x1.e93255f4112f4p-31, + -0x1.380319f9cc2c6p+0, -0x1.9d282a5842e9dp-30, -0x1.15e31525115d7p-28, -0x1.850d8fd56a9c1p-25, + -0x1.24eeff1a0362ep-32, 0x1.a211b605cbc81p-4, 0x1.f39136798c952p-34, 0x1.9802496cb93ebp-33, + -0x1.94d5b1ddc6a88p-6, -0x1.77cfdc1a64f40p-35, 0x1.81096c2b875f5p-37, -0x1.0d447ba102895p-31, + 0x1.f8a28b2ca843cp-35, 0x1.1e9aff4d53b67p-7, 0x1.ef2108ab2ec6dp-35, -0x1.651192e50219cp-36, + -0x1.00f3277443dadp-4, 0x1.d209690fb7936p-32, -0x1.baafff77d23a8p-34, 0x1.2d823bbb71a89p-30, + -0x1.304c97dc2c8b2p-29, -0x1.79f24517db54ap-2, -0x1.0f1e905490d65p-29, 0x1.b8c1c8a82ffadp-34, + -0x1.c2efd5086c2a5p-1, 0x1.5c101279dc5c7p-28, 0x1.f1c23c0687cfep-30, 0x1.0beb323734f38p-26, + -0x1.136ed4cae5bd6p-25, -0x1.ce7022ee01f43p+2, 0x1.231035dd9053bp-24, -0x1.68cc0d5307e0fp-31, + -0x1.afef751fb1ed9p+3, 0x1.a8809e3488ebep-26, -0x1.98d0a6372d357p-32, -0x1.7115bb60c9d83p-28, + 0x1.d2beff0cc36fap-26, 0x1.183b3762bf20ap+2, 0x1.df8e1091cc4d3p-24, -0x1.26e20ee5737f2p-30, + -0x1.395d61494a9edp+0, 0x1.7a20ba69d9002p-27, 0x1.81478de7f2b7bp-29, 0x1.9bd016b06ff1cp-25, + 0x1.388253b969e8dp-32, 0x1.6aa86f3aeebd4p-4, 0x1.12e6668afa584p-31, -0x1.79f4ce07f8a82p-34, + -0x1.6c720f23f1be6p-6, 0x1.74f6812305d35p-33, -0x1.e9df3b772856ep-35, 0x1.9a9392c677cd6p-32, + 0x1.1d0a58e6c9290p-36, 0x1.29ae2d2a41ccep-7, 0x1.6edf444d38b73p-34, 0x1.27f6a76f6bd97p-36, + -0x1.0b842d40009cdp-4, 0x1.1f98bafed7f48p-33, -0x1.550e4332fdb80p-32, -0x1.ad06a0edac189p-30, + -0x1.959d2b719547dp-30, -0x1.900888dfe7c9bp-2, -0x1.517c7e5e590b2p-31, -0x1.5866080246c35p-29, + -0x1.ad566ea120b67p-1, 0x1.86c1455296ef2p-29, -0x1.79b5829136660p-28, -0x1.5b72d822b1096p-26, + -0x1.3c6a42a885f38p-25, -0x1.da0a86b163316p+2, 0x1.308ea165f3a81p-24, -0x1.5bf6ea435bc20p-31, + -0x1.ae9188c061384p+3, 0x1.b31c95be586c4p-26, 0x1.3c5cd182087a1p-31, 0x1.4762779b0b1d9p-28, + 0x1.371c665089c44p-26, 0x1.0d6b7b2d5e851p+2, 0x1.0bca63e95464cp-23, -0x1.731a38ef92204p-30, + -0x1.3a3f42f96a39dp+0, 0x1.6bef16b2455c4p-28, -0x1.5cacbee196d85p-29, -0x1.49252da1f0366p-25, + 0x1.7d031f53e3651p-32, 0x1.357a5d26d3a96p-4, 0x1.1039dcf059f0fp-31, 0x1.d5228745b96d9p-33, + -0x1.49b8c0f95b9a4p-6, 0x1.66d4fb6f27001p-36, 0x1.8de104d018351p-36, -0x1.16b86b2ae1d64p-32, + 0x1.16fca039fd416p-34, 0x1.33ce4b8df09d8p-7, 0x1.9e32ff6fd3ab9p-34, -0x1.ae20b840defebp-36, + -0x1.14fbadb99a9a7p-4, 0x1.41fc49353f691p-32, -0x1.4a1b776d82486p-33, -0x1.92ab242dfc309p-30, + -0x1.3a327531faeb8p-29, -0x1.a680f7a887579p-2, -0x1.14d9a5af6314ep-28, -0x1.acb281014ca34p-31, + -0x1.964e43a2f0aa9p-1, 0x1.9c1d55dd74124p-28, -0x1.92c9243e79163p-30, -0x1.2439c29102656p-26, + -0x1.eabe3a0c076fdp-25, -0x1.e5a08f9d95777p+2, 0x1.d4b71dc8d9128p-25, -0x1.5ea391e408d89p-31, + -0x1.ad0aa19413b49p+3, 0x1.46fc4c9d38d66p-25, 0x1.9669174dd72a1p-32, 0x1.5a2fbe3c77f72p-28, + 0x1.6f1b8bd067366p-26, 0x1.02b629c491d2ep+2, 0x1.b61bc8b7d65cbp-24, -0x1.5f6fd8224b9b6p-30, + -0x1.3aaac1883d29bp+0, 0x1.3dfd770e9c7c4p-28, -0x1.a6c3792567a95p-29, -0x1.78f87f4676902p-25, + 0x1.6c771a9eda81ap-32, 0x1.02381db648d50p-4, 0x1.2eacdab546aacp-31, 0x1.eea8a0a776770p-34, + -0x1.26ea83c523ba8p-6, 0x1.04c0afbd9ddd0p-33, -0x1.ce4a2d6b7800ep-34, -0x1.88aeb2df9abd4p-33, + 0x1.1d5d1b41f93c3p-36, 0x1.41885773bfd5ap-7, 0x1.09173fb4e6586p-34, 0x1.72d650b32c66fp-35, + -0x1.1e97f9723a4efp-4, 0x1.13364fe068714p-33, 0x1.4471af0dd8fafp-32, -0x1.a698e817f5fd3p-31, + 0x1.3974f372e74cap-31, -0x1.bd6a1b43650dbp-2, -0x1.3ca410e9cc150p-29, -0x1.00feec9259c2cp-32, + -0x1.7dfee349c9179p-1, -0x1.6b3fe58ea0ef4p-32, 0x1.fff0584a67e26p-30, -0x1.0982e287de1aep-26, + -0x1.bf964c85165e8p-27, -0x1.f12d8b268b4d8p+2, 0x1.a20f5cc5b80e9p-25, 0x1.66c576a2fe07ap-30, + -0x1.ab5cf931ad22dp+3, 0x1.1ccd8a78cd8f9p-29, -0x1.8f34f42fd5ae7p-31, 0x1.45887069d26d3p-28, + -0x1.567df15774b65p-26, 0x1.f03bdd3865e92p+1, 0x1.a1bafb5e1addap-24, 0x1.63f655d378cf4p-29, + -0x1.3aa4e163f0660p+0, -0x1.a6c4ce207f25ep-29, 0x1.cf546dffdc5abp-28, -0x1.692c6e186e3fdp-25, + -0x1.3b9e20ecffbcdp-34, 0x1.a28ff91946b62p-5, 0x1.1196d88d8e767p-32, -0x1.353a808991b89p-34, + -0x1.0327bd9a22b8ap-6, 0x1.687de2b61d360p-36, 0x1.c31fd6c685df4p-35, -0x1.53c67a3f61e21p-33, + 0x1.9d77601f7ca25p-35, 0x1.4af4d9e73545ap-7, 0x1.ec3a64a9f5f88p-34, 0x1.1fdffa212541ep-35, + -0x1.28498ba951859p-4, 0x1.20bda3788a288p-34, 0x1.48acc7a760a12p-34, -0x1.7438441d57384p-30, + -0x1.d6e41128fb310p-29, -0x1.d4b35de295ff1p-2, -0x1.69a8150d85aa7p-28, -0x1.209809adc7b7fp-30, + -0x1.64299fd9f98b9p-1, 0x1.246c08f4b2c2ap-29, 0x1.4d10a6333e5fap-30, -0x1.487036067b4c1p-26, + -0x1.8d9ac054dfd83p-25, -0x1.fcb17dbe6188cp+2, 0x1.7e329bfd77ca2p-25, 0x1.8783c61843076p-31, + -0x1.a98671a098ad2p+3, 0x1.193f0460799aep-25, -0x1.d090a4a415eb1p-32, 0x1.3045698546619p-28, + 0x1.3c4744cd4db33p-26, 0x1.db4709cb82eabp+1, 0x1.9644fc16f4556p-24, 0x1.7f609bf37896ap-30, + -0x1.3a3395d651a76p+0, 0x1.b1785ba18dc8cp-31, 0x1.0b15fc9648d32p-28, -0x1.3e4a75748d0c6p-25, + 0x1.e087ccb9959fcp-34, 0x1.4568a9b317814p-5, 0x1.229258a61a080p-32, 0x1.81ba7c6c75e5cp-36, + -0x1.c35491bac2222p-7, 0x1.5a06cbf663b87p-34, -0x1.76d26f26c9677p-47, -0x1.1b4c64f61b3c1p-32, + -0x1.c64122156582bp-35, 0x1.56e6dd2e8f787p-7, 0x1.7b24e92e95230p-34, -0x1.09a5252c228eep-35, + -0x1.3170a93d78101p-4, 0x1.ee0737357b689p-33, -0x1.0af63750e76bep-33, 0x1.09b39be13dcfbp-30, + 0x1.56c8f77b9f9bap-30, -0x1.ec57f30950538p-2, -0x1.427dc0fcb8d63p-27, 0x1.907c2957b66afp-31, + -0x1.48dfe747361cbp-1, -0x1.9d9bb6b210d6bp-30, 0x1.29608a63d8c1bp-31, 0x1.1848db37d1f92p-26, + 0x1.0e467f5e63c6fp-27, -0x1.04162f776de90p+3, 0x1.4fce9beb48028p-25, -0x1.1ada79fdf52d6p-30, + -0x1.a78a5d181320ap+3, -0x1.e035eadbaf2a5p-28, -0x1.4ebce5e0b3fcfp-31, -0x1.236235fb6f122p-28, + -0x1.2a6f887911c81p-27, 0x1.c695b91d1751bp+1, 0x1.7aca7ea3a92dfp-24, -0x1.363da57675b9ap-29, + -0x1.39573d820405ap+0, -0x1.b3b674a47977bp-30, 0x1.b172e61ae0855p-28, 0x1.3fcbd34a41a12p-25, + -0x1.384aedc0e4d4fp-35, 0x1.d8e4d902215bep-6, 0x1.0ac246a2246a3p-32, 0x1.1abab64793dd2p-33, + -0x1.8703ed5afcc5fp-7, -0x1.550c22486e542p-36, 0x1.82cc2d6704314p-36, 0x1.74a1d8c7ce735p-33, + -0x1.368e1b541b13fp-35, 0x1.63589f465c9dap-7, 0x1.2681188777b58p-33, -0x1.1e33ad639a1bep-36, + -0x1.3a217d7213faep-4, -0x1.c809be3090dc2p-33, -0x1.1521ce89213dbp-35, 0x1.f9fe38ddf550dp-30, + 0x1.8b7a2205625aep-32, -0x1.020ffb9373eebp-1, -0x1.7a6246f8c0845p-28, -0x1.11686b153e3b9p-32, + -0x1.2c2b71a03211fp-1, -0x1.53ddeca6ac2cfp-29, 0x1.435049ebfa2c7p-28, 0x1.9dfa2c05a7589p-27, + 0x1.5f48d4e1bdbf8p-25, -0x1.09ca8da6f7686p+3, 0x1.3bcd5ca126b26p-25, 0x1.c5ddb2d044ca2p-31, + -0x1.a565c16a10d11p+3, -0x1.092c65f27a434p-25, 0x1.7d94366ab049fp-32, -0x1.3cec21f5c967ep-28, + -0x1.75dc184e0d64dp-26, 0x1.b21f353193e8cp+1, 0x1.7f2d4d046955dp-24, 0x1.10c7bd135d029p-29, + -0x1.381cb387eef51p+0, -0x1.3fdefc1d2406bp-28, -0x1.9cfd30fdac67cp-28, 0x1.791e3a5e3cdbfp-25, + -0x1.68b1d0762c77ep-34, 0x1.2f40719d4ed7bp-6, 0x1.35a5609b0a4f9p-32, 0x1.42d316da9abfap-35, + -0x1.471f7d88e90d7p-7, -0x1.59f62abc2955bp-36, 0x1.d42f936bebd52p-34, 0x1.7d1c3c5c5f288p-33, + -0x1.48d484c30138cp-35, 0x1.6bf0c60e50e81p-7, 0x1.9987bf365573fp-33, -0x1.716f2bcd2c619p-35, + -0x1.420738194b813p-4, -0x1.7eb3a53fe98cfp-31, -0x1.0a999236cd95dp-35, -0x1.a8fd996ac30f2p-31, + 0x1.414c554f8c213p-30, -0x1.0e227211561d9p-1, -0x1.780e745609527p-27, -0x1.406232f81e90bp-32, + -0x1.0dfec20f5acbbp-1, -0x1.5e0b852722a8ep-30, 0x1.607df023320f3p-31, -0x1.6d1df1c1b07d7p-27, + 0x1.28031baab5e17p-25, -0x1.0f798826b27b4p+3, 0x1.92667e6ad74dbp-25, -0x1.ad52f8a7d5bd3p-32, + -0x1.a31c9a1f1f201p+3, -0x1.86339dd5180abp-26, 0x1.32c84aad534c0p-32, 0x1.4098ba433d533p-28, + -0x1.d5956d1730e47p-29, 0x1.9df3b8016ba67p+1, 0x1.040ff6eb53212p-23, -0x1.269388c30bd8dp-30, + -0x1.367aefff6433dp+0, -0x1.496c8daeca8f7p-28, -0x1.c4285b5b3ec0ap-29, -0x1.88a3a68b5e951p-25, + -0x1.1e09b56a0c01ap-34, 0x1.1e7c56054f7bfp-7, 0x1.3a43fc99670bcp-33, -0x1.51353973dc7aap-37, + -0x1.0bc636160881ep-7, -0x1.3d3873fc40c45p-35, -0x1.3dd3e8a75aef9p-37, -0x1.67889ea6f292bp-33, + -0x1.dc792da9bb2eep-35, 0x1.7745835cd8ffep-7, 0x1.983fe09c9831cp-34, -0x1.b60675439592ep-35, + -0x1.4a41756b794e0p-4, 0x1.cff7554aa3a45p-33, 0x1.1f5623812264cp-31, 0x1.b8879e483cb80p-33, + 0x1.9a7abc90705f9p-30, -0x1.1a503f64c52e5p-1, -0x1.8a5cd3596bb73p-29, 0x1.8eb6b952ebd50p-30, + -0x1.dc7c6d3fc8e1fp-2, -0x1.68bdad01b6871p-29, 0x1.2851d85f89d3dp-29, 0x1.ba6d472e9168bp-28, + 0x1.49012fd4490fcp-29, -0x1.151f6b55a74d8p+3, 0x1.0069a4e08711fp-25, -0x1.2471bbb545592p-30, + -0x1.a0ace5284530ep+3, -0x1.84d61be94244ap-34, -0x1.701b1bea978aep-31, -0x1.070e72284f8c2p-28, + 0x1.78db829e60f06p-28, 0x1.8a074344beb6bp+1, 0x1.6676e8d062487p-24, -0x1.779f270e80e1cp-29, + -0x1.347c2b90501bcp+0, -0x1.08519d4c9a8fcp-29, 0x1.b596906608fe1p-28, 0x1.4dd6edcd65be3p-25, + 0x1.4fccaef0612fap-40, -0x1.cf2080f58b90ep-12, -0x1.467bd4fac6f99p-38, -0x1.618df56fcb8cfp-40, + -0x1.a6369d54331b4p-8, -0x1.100df74d69af7p-36, 0x1.12f9eea825cb5p-37, 0x1.8ecf785b61e87p-34, + 0x1.08457e366a4d3p-34, 0x1.7c5f8a433db91p-7, 0x1.53ac3416eb0eep-33, 0x1.1688cab3fba29p-34, + -0x1.50e73a437df71p-4, 0x1.2ca0d69544b9ap-32, -0x1.de21255fd3327p-36, 0x1.bba188bf01086p-30, + -0x1.79da19e12bca3p-29, -0x1.26aa0c2af9246p-1, -0x1.90e9ed01adca7p-28, -0x1.17b28b072b870p-29, + -0x1.9a1a9a26eb638p-2, 0x1.632f256368ba6p-30, -0x1.c0faae2669014p-31, 0x1.13745ed836538p-27, + -0x1.9e8fc99fb2f67p-25, -0x1.1abaa21e43da0p+3, 0x1.27940e64fc8aap-25, 0x1.0c01bc9f6b3c7p-32, + -0x1.9e170a2538142p+3, 0x1.1d9632ca9d4a6p-25, 0x1.14a0394068873p-33, -0x1.2861199a62952p-28, + 0x1.14de5d8cc8ef5p-28, 0x1.7668e43320f63p+1, 0x1.b97791a3d3285p-24, 0x1.710bfc483b946p-32, + -0x1.3228143a13bdfp+0, 0x1.02cfd4983046fp-27, -0x1.2a7535464f814p-30, 0x1.78d92bab5ac93p-25, + -0x1.18dd1fbdcb095p-36, -0x1.31c75420336c4p-7, -0x1.41ca1754af8cep-33, 0x1.f4783c0ce1f2fp-37, + -0x1.3547e037ba7cap-8, 0x1.d95181c5bd8d5p-36, 0x1.83f36f1f08933p-43, 0x1.78d60ef5f8e82p-34, + 0x1.19cbf4caa6d7dp-36, 0x1.861ea208b43cfp-7, 0x1.aceef0c6f394bp-33, 0x1.046841ac3ce3fp-37, + -0x1.57cf3be010828p-4, 0x1.b8e7d94d8c120p-32, 0x1.8dbeceda41b3dp-35, 0x1.98edabeb552b4p-31, + 0x1.7b783d76dcbacp-31, -0x1.330bf40ece48ep-1, -0x1.d497491bbe984p-28, -0x1.70074759f56d1p-29, + -0x1.54c84bf61981cp-2, 0x1.09ea9cb3e4b41p-30, -0x1.6a8ef7685b465p-33, 0x1.a1d434a76393ap-28, + -0x1.9f99de3434103p-27, -0x1.204be1f2782dcp+3, 0x1.dc48d95c1bb8fp-26, -0x1.d2b0e465ae250p-33, + -0x1.9b5d9bfb9432ep+3, 0x1.4400fb58e466ep-27, -0x1.f8547825836a0p-33, -0x1.05be0ecd6b02ap-28, + 0x1.2a445af32479ep-28, 0x1.63157bce98e1cp+1, 0x1.7c5b5d92f5ef6p-24, -0x1.5c971039c198fp-30, + -0x1.2f83ddf2dc532p+0, -0x1.c5ead80c4b57ep-31, 0x1.5bb03e4e3d756p-29, 0x1.53a2b0c582760p-25, + 0x1.38658bb0362dcp-34, -0x1.1dcc4a30829b4p-6, -0x1.664b11970af37p-32, -0x1.cd72f1b7edbcfp-39, + -0x1.ac73a40859dd4p-9, 0x1.a47477c754fb0p-38, 0x1.6d9dbcc012b3ap-39, 0x1.d92ef698247b3p-35, + 0x1.ee9d64c062e23p-34, 0x1.88b919e1d1a22p-7, 0x1.38d2d01c2c3d5p-32, -0x1.49ff118e0c6c2p-37, + -0x1.5e6e980d25ec0p-4, 0x1.d427bc9a5a76dp-31, -0x1.3173722440899p-32, -0x1.ac77c180e12b2p-30, + -0x1.f18f387d72884p-28, -0x1.3f882fd66c1dfp-1, -0x1.4abd8710303aap-27, 0x1.898c67f8623a2p-29, + -0x1.0c35480e7b3b0p-2, 0x1.902a7331bfaa6p-30, -0x1.035151bcd7ec2p-30, -0x1.412927b56f04ep-28, + -0x1.bb0dc34e72e5dp-24, -0x1.25cffbd2f02bap+3, 0x1.ea7399ef6c11dp-26, -0x1.63cf3d94cbc50p-31, + -0x1.987f59f7309b2p+3, 0x1.50ae8bc9413d5p-24, 0x1.e0c6709554cd1p-32, 0x1.15fb024165b8cp-28, + 0x1.7fe7092f9ae72p-26, 0x1.50117fbe4b429p+1, 0x1.a2eeca24127bcp-24, -0x1.b31ff2df644c9p-30, + -0x1.2c7da7f478ba9p+0, 0x1.0d490a50dc910p-27, -0x1.36eeeda485364p-28, -0x1.6ff6427123d0ep-25, + -0x1.209131696e6f6p-32, -0x1.9dc93614a3960p-6, -0x1.f1703c9f297dep-32, -0x1.1cafcb239bc73p-35, + -0x1.cb047dff0ec24p-10, 0x1.bbe861486bfcbp-37, -0x1.aad3eb89114f8p-40, -0x1.2595b4c40858ap-36, + -0x1.0afdd18a57c58p-36, 0x1.92b99ffc6e199p-7, 0x1.69b01f0bb122cp-33, -0x1.2afaa27b4a436p-34, + -0x1.632f1a21edc05p-4, 0x1.01863d577815ep-31, 0x1.e3c71c101df9ap-33, 0x1.b4d940afb2cbap-30, + -0x1.92f7caf6a4a7cp-29, -0x1.4c0fe243213c9p-1, -0x1.3d2b4b4aba794p-27, 0x1.54842e1224899p-28, + -0x1.816e06214e136p-3, -0x1.6af15657463f1p-34, 0x1.8eda36eb39609p-32, 0x1.68445b2064601p-29, + -0x1.e2415f08f1122p-25, -0x1.2b48de32eb878p+3, 0x1.8302d598dbe98p-26, -0x1.2402c923a93c4p-32, + -0x1.957d901e98af9p+3, 0x1.73ab343e23063p-25, -0x1.0968eba0ad5ddp-34, -0x1.1a58013796a4fp-28, + 0x1.21231c456831dp-27, 0x1.3d5c09f5ebfd3p+1, 0x1.628a09e604c13p-24, 0x1.471abfbdcc08bp-32, + -0x1.293d5624b6484p+0, -0x1.ac31332a90e9dp-32, 0x1.40b623fc3e138p-31, 0x1.7c8024c43d188p-25, + -0x1.6759d37eb3492p-33, -0x1.09bcd7f92cbcdp-5, -0x1.11139c793fabbp-30, 0x1.d7c22cceeb018p-33, + -0x1.c4d0f22b19681p-13, 0x1.89662983fd0e4p-41, -0x1.3c292dced3820p-42, 0x1.30193a2459cc5p-38, + -0x1.49dcd839897a9p-34, 0x1.950129b0fbd39p-7, 0x1.9d6267bfeff6ep-33, -0x1.d2b37e0816310p-39, + -0x1.67a2b7ad893dep-4, -0x1.785b1ef3538a6p-31, -0x1.90a034c6ecb22p-31, 0x1.1727901257422p-29, + 0x1.63bafeb5787c2p-28, -0x1.5898818c1c80dp-1, -0x1.68599c033d6b8p-27, 0x1.149b5abb7d24ep-29, + -0x1.c85f433a1db59p-4, -0x1.0291866f32954p-30, -0x1.8db888fe5fba6p-34, 0x1.147751ae03c4bp-29, + 0x1.4abef48051ea7p-25, -0x1.30b28f869f93fp+3, 0x1.863fab7a8504fp-26, 0x1.475fd2f4cfb17p-31, + -0x1.92590199145b2p+3, -0x1.0e3f98125a402p-25, 0x1.236908696efe1p-31, -0x1.1bc64782a5fa7p-28, + -0x1.c07dd3af03c1bp-27, 0x1.2af5cdad90580p+1, 0x1.80b57f046dab7p-24, 0x1.9d72000690342p-29, + -0x1.25af2dd0e12bep+0, -0x1.2375cc481cceep-28, -0x1.8acbae56a6759p-28, 0x1.81c1f432b1e45p-25, + 0x1.d6d59102d051bp-34, -0x1.413d03af46b06p-5, -0x1.55b78423b5e38p-31, 0x1.2adab8045d656p-35, + 0x1.02edc5a3a686ep-10, 0x1.174abcb31404dp-37, 0x1.b94b07ba2a55ep-38, -0x1.6d54f2abb99eep-36, + 0x1.fef1addd7f014p-34, 0x1.9abe9f8571ad1p-7, 0x1.576615d7b3122p-32, 0x1.dcd235987a56cp-35, + -0x1.6b90cd9a18ec7p-4, 0x1.21e4e294175f5p-30, -0x1.9e8834e148302p-34, 0x1.927ac431898d3p-30, + -0x1.5b502eaa355ffp-28, -0x1.6540477516c36p-1, -0x1.c0be1b9108c3cp-27, -0x1.b6dd343589d1fp-29, + -0x1.031259b0f12dep-5, 0x1.97b711de06fa7p-32, 0x1.c597a633438d2p-34, 0x1.36448cbfcab7dp-31, + -0x1.19bc73e77940ap-23, -0x1.360e5d8ca4fc7p+3, 0x1.41835636081b8p-26, 0x1.3af2a21b3df7ep-37, + -0x1.8f1149a88ac23p+3, 0x1.c2b8c73de0290p-24, -0x1.1d07c502a292bp-34, -0x1.2d062ad528b7bp-28, + 0x1.9765b33af0f39p-26, 0x1.18e4cfd767ad9p+1, 0x1.50f24af0bda06p-24, -0x1.0d4da4755641fp-30, + -0x1.21d83fb8f486ap+0, 0x1.103de6f37455bp-26, 0x1.8ae9601e6edc6p-31, 0x1.9d5675664da12p-25, + -0x1.428ff55c7106ap-31, -0x1.74db79aaed39cp-5, -0x1.3e15671523fdfp-30, -0x1.81d5b01ea51e9p-33, + 0x1.2f53fbbd888fep-9, -0x1.04f51adfc87e5p-35, -0x1.5d818d47ae977p-38, -0x1.d67801ac21fd9p-36, + 0x1.b1d4ffab9c2efp-34, 0x1.97e3a469c3452p-7, 0x1.1c4044b7315b4p-32, -0x1.22caa5d3ab79fp-39, + -0x1.6e986e18140bfp-4, 0x1.290d40f15ae28p-30, 0x1.8783e635dde15p-34, -0x1.5b6e4b780e733p-30, + -0x1.3d331a74a925ep-27, -0x1.71dbfc66480d1p-1, -0x1.bc015e1cc80f0p-27, 0x1.5f6b056d8ee58p-29, + 0x1.a491c250007f2p-5, -0x1.7c6aba009feefp-31, -0x1.37b6d5169c6bcp-32, 0x1.b88d75653fc8ep-31, + -0x1.5011705dc74c9p-23, -0x1.3b58b01f3bffcp+3, 0x1.c09650893e490p-27, 0x1.367f1a3f04b46p-30, + -0x1.8ba9925226ecdp+3, 0x1.17725f6eed39ep-23, -0x1.9b24ad2c4fc01p-31, 0x1.03a3aaa459984p-28, + 0x1.339c6bd40b029p-25, 0x1.072b281edf7d3p+1, 0x1.f247b8d6cdc0ep-25, 0x1.b1da487e9ae19p-28, + -0x1.1dbfd626ddfecp+0, 0x1.9d4a22d2d19f6p-27, 0x1.1bf36798358e2p-27, -0x1.665219003d56dp-25, + -0x1.7fb79caf31de2p-31, -0x1.a4a280546089bp-5, -0x1.2b0f1872ef98cp-30, 0x1.29e6aa743be5cp-35, + 0x1.b80da0293ea23p-9, -0x1.4c9e07a41cdb6p-35, -0x1.d64d87b9afde1p-39, 0x1.bb4cd5e0e00b5p-35, + -0x1.a919849560e3fp-34, 0x1.992303ccb848ap-7, 0x1.27db5b3cbbea3p-32, 0x1.dff94de6dabe3p-39, + -0x1.707295ef1c221p-4, -0x1.63ba03e59a957p-32, -0x1.6be99d9af09bfp-33, -0x1.a0c7b40f19c75p-30, + 0x1.90a4b4b28cf21p-29, -0x1.7e7013f03d2eep-1, -0x1.0272de2641394p-26, 0x1.65ccf095a66adp-31, + 0x1.18dc39db4bdf5p-3, 0x1.49844fde58c39p-34, 0x1.337fb3a5520abp-31, 0x1.ab7ee8810d850p-29, + 0x1.534abb20b59c0p-24, -0x1.40935bd58faedp+3, 0x1.e4c05737f8d05p-27, -0x1.49c9bef080cc9p-32, + -0x1.881fc7b80a77bp+3, -0x1.19e911405e054p-24, 0x1.148c11c659222p-32, 0x1.cbffa7c689762p-29, + -0x1.027248bd84827p-27, 0x1.eb8d4bbe9d154p+0, 0x1.22d5666174b96p-24, -0x1.6998fc7e50120p-30, + -0x1.1969c3e8f8d21p+0, -0x1.caf1bdc3e126fp-29, -0x1.75e3487d4939dp-29, -0x1.3c150b1028f2bp-25, + 0x1.77a1ee711f6a1p-34, -0x1.d002dfa68194cp-5, -0x1.64f969cf79beap-30, -0x1.173801fed0aedp-33, + 0x1.2fc53fd497693p-8, 0x1.cfac4d5b2715ep-37, 0x1.0340c1c593c16p-37, 0x1.1b9ed0ad26313p-34, + -0x1.287e11cc0cfe0p-34, 0x1.990546dc52f6ep-7, 0x1.d927459034647p-33, 0x1.e911f8260cb4fp-36, + -0x1.71fc1907065e5p-4, -0x1.d48201b2f7b3fp-31, 0x1.5f97eb8977051p-31, 0x1.09af5101e7075p-30, + 0x1.22c85dffe6660p-27, -0x1.8afd78fe79255p-1, -0x1.39e4dbac9d274p-26, 0x1.8fa0199368a90p-29, + 0x1.cef9a6fb030e6p-3, 0x1.a9a0214a93e4ap-30, 0x1.3d8314221aad8p-32, -0x1.ccda0b2948241p-30, + 0x1.25b7fcb795317p-23, -0x1.45bbbd3d1787cp+3, 0x1.b2a7659354f08p-27, -0x1.ca3a6702130e8p-33, + -0x1.84756122cce53p+3, -0x1.ee40e73ea474dp-24, -0x1.25d914b8912b2p-33, -0x1.a3b746b51b37ap-29, + -0x1.9d93c0e49ef94p-28, 0x1.c973c8f58459dp+0, 0x1.136b2a9b57f28p-24, 0x1.153b8008aa975p-34, + -0x1.14ebb34bf4859p+0, -0x1.8275f8fb75dbcp-27, 0x1.9e13aa5072fb9p-30, 0x1.22adb924570d7p-25, + 0x1.20d72bbeb7f54p-31, -0x1.f80e4ac82156fp-5, -0x1.6ae33b1d8d097p-30, -0x1.439dea51a78c1p-33, + 0x1.6f1ff92d2af17p-8, 0x1.bb006ec58da29p-35, -0x1.bec0460b5dbebp-36, -0x1.0ad6315bc870ep-34, + 0x1.8e63d9b5fbe6bp-38, 0x1.96bdced483da1p-7, 0x1.33fc25ea1c6f1p-32, -0x1.6c2a0d4a6a712p-37, + -0x1.718d5ec67a820p-4, 0x1.07ffaf574b168p-33, -0x1.c0250a71f0992p-32, -0x1.36beb0c741178p-29, + -0x1.c3b91a265080cp-29, -0x1.97755908a7060p-1, -0x1.89a53a895c12dp-27, -0x1.1240f0538d769p-28, + 0x1.45c5132cf8068p-2, -0x1.6042cd970e6cdp-32, 0x1.4fe7b425a41bdp-30, 0x1.267e6b0c97fadp-27, + -0x1.f6e1694f0d057p-25, -0x1.4ad1272f6b149p+3, 0x1.52bc45a3f9bcdp-27, -0x1.593ec3d69cb2ap-31, + -0x1.80ac30da8ec09p+3, 0x1.bdedd9d7ed087p-25, 0x1.b4a2b83aee963p-31, 0x1.a46a9580b1773p-29, + 0x1.e7a44400caa1ep-27, 0x1.a8122ab62e5d4p+0, 0x1.e09ff1f5bb040p-25, -0x1.90fb60381a418p-28, + -0x1.101ffb27a5675p+0, 0x1.d185eff7ef6f9p-28, -0x1.26da044a002f6p-27, -0x1.1175896901ec3p-25, + -0x1.08dfccdb977e2p-32, -0x1.0e58c549c9009p-4, -0x1.cc20907446c9fp-30, 0x1.2a70c2e10f42dp-35, + 0x1.ad6792f56bd38p-8, -0x1.3cd7acb8c338bp-36, 0x1.94962590500d1p-36, 0x1.f112441e3bde8p-34, + -0x1.d3188ef175fc6p-34, 0x1.9012c6e9aa58ap-7, 0x1.b18f955a1be08p-33, 0x1.11aa0bf908fd9p-36, + -0x1.70bedeed02a3ap-4, -0x1.112030d696e76p-30, -0x1.46d7d6d3e14c7p-35, -0x1.7daf9a017f243p-30, + 0x1.1e578b371169bp-27, -0x1.a3e2d0ba22037p-1, -0x1.ddcdd94336795p-27, -0x1.86da79c3072a6p-28, + 0x1.a7145eb489f56p-2, 0x1.cc773e4d4a617p-29, 0x1.7f0b93c037b03p-30, 0x1.6532ee57b66d4p-28, + 0x1.01bd0c2b11366p-23, -0x1.4fd254fdd604fp+3, 0x1.3b8d79d786275p-27, -0x1.858187ee13239p-32, + -0x1.7cc3fcf36e6e2p+3, -0x1.c6d2890454721p-24, 0x1.64dabcc994357p-31, 0x1.9c52f1b6bb40fp-29, + -0x1.9885326e699f1p-28, 0x1.8762eeece70f9p+0, 0x1.dcc7dd0a73970p-25, -0x1.78e60090d4d79p-28, + -0x1.0b290f3624125p+0, -0x1.cbd3874dcfc6cp-27, -0x1.d677c83eee6c3p-28, -0x1.131e075e976a7p-25, + 0x1.50efdad8407cfp-31, -0x1.1f0f535430218p-4, -0x1.be08d104847cdp-30, -0x1.6797c6d0c4832p-35, + 0x1.e3021ab6fc373p-8, 0x1.24cb9a4c03aa4p-34, -0x1.72f09d8fd616ep-43, 0x1.87f312fb8715dp-34, + -0x1.a94e9b0f39ad3p-35, 0x1.8ac9f6862ada8p-7, 0x1.753ffc71e2a00p-32, 0x1.80912ae09393ep-35, + -0x1.6e755eaf0cffcp-4, -0x1.1f9466f719407p-31, -0x1.2eb77807f1fb0p-31, 0x1.15ea142d41a58p-30, + 0x1.93a23c0d1887dp-28, -0x1.b03c2e5d1cdb6p-1, -0x1.71cfe30ee16ccp-26, -0x1.7e61626107d53p-28, + 0x1.05c28f1aaa8d8p-1, 0x1.ac1c992509880p-29, 0x1.37faaa66079afp-28, -0x1.8774faf2a9bddp-27, + 0x1.1ef38c91689b2p-24, -0x1.54be3f0e413dap+3, 0x1.373576e8e01c9p-27, 0x1.9b5628dc94a3dp-31, + -0x1.78bd8caeaf06fp+3, -0x1.07a27abc482a3p-24, 0x1.6b7f6ab7c4f76p-31, -0x1.05d922b8646f9p-28, + -0x1.078e04edcae84p-27, 0x1.677186bb6e8fbp+0, 0x1.de2c8c08c7012p-25, 0x1.3f58acbfcd821p-29, + -0x1.060711223d6f1p+0, -0x1.81dfe8359b91cp-29, -0x1.6b77b73cb2094p-28, 0x1.46d5431c7add9p-25, + 0x1.90fb395f54e00p-32, -0x1.2db983021cb37p-4, -0x1.9334e68ff534dp-30, -0x1.91507c9bad747p-34, + 0x1.0dc6b30a6b1b8p-7, 0x1.3bee661eb2203p-34, 0x1.b75a4b79bf26ep-35, -0x1.02a26832050e3p-33, + -0x1.9e61597a0db1ap-33, 0x1.7fbebf56d2006p-7, 0x1.06dd2f30c09e6p-32, -0x1.d7973b9356326p-35, + -0x1.6b1919608f703p-4, -0x1.6c71927c3643cp-30, 0x1.36d84841d70aep-35, 0x1.14a78ab14c962p-29, + 0x1.97fe62dde7808p-27, -0x1.bc60972b09027p-1, -0x1.3944ce5a354f3p-26, 0x1.a83de1a583b4dp-30, + 0x1.39920f51566e3p-1, 0x1.df48d7c75fc48p-28, -0x1.c0dd83f391cfdp-29, -0x1.b0bfadbc1a8b6p-27, + 0x1.e009e900747b5p-24, -0x1.59952f607fa6dp+3, 0x1.ddd688f5aa53dp-28, -0x1.1d796b0439f98p-30, + -0x1.749af96c5cdf2p+3, -0x1.c37a67c695ddap-24, -0x1.1334cbb11e961p-30, -0x1.02fadefe2bfe3p-28, + -0x1.26e80d0e8f0e9p-26, 0x1.483e090df001bp+0, 0x1.8c295f73dc388p-25, -0x1.08331eab57ad0p-27, + -0x1.00c2cd684e9e2p+0, -0x1.7a9246bd548bcp-27, 0x1.4ab9acbfe70b0p-27, 0x1.34388cd9c9387p-25, + 0x1.0fd6f8109a1fdp-30, -0x1.3b4a4b31093c3p-4, -0x1.d21ca0c31d390p-30, 0x1.d7b264bd28745p-33, + 0x1.23be795758f83p-7, 0x1.d8856665a0439p-34, -0x1.ffbf9869a2833p-35, -0x1.9dd8fd4602eaap-33, + -0x1.684a2f8b5570cp-33, 0x1.7a4b59d44c259p-7, 0x1.4bef9501ca36cp-32, 0x1.468a685cc6099p-34, + -0x1.66d599e0c7bc1p-4, -0x1.8d7be108a6a17p-31, -0x1.22cd110d17f23p-34, 0x1.08ff94802835bp-29, + 0x1.b4db8eb6fcb52p-28, -0x1.c86fc7e853607p-1, -0x1.a88172f65b831p-26, -0x1.4d70a130deb25p-28, + 0x1.6ed7e5e45fa49p-1, 0x1.0d1831131ec8ep-27, 0x1.119ff74846e35p-28, -0x1.884ac1812af28p-26, + 0x1.07a69b44a857cp-23, -0x1.5e54181077d76p+3, 0x1.a13b526ab607dp-28, 0x1.ee678bf56e00bp-32, + -0x1.705b41a3af465p+3, -0x1.f5bbecf3edcb2p-24, 0x1.ba7c1bedaca9ep-32, -0x1.03436876692adp-28, + -0x1.947833e899f06p-27, 0x1.29c187df09969p+0, 0x1.47471e8d872f2p-25, 0x1.16abc252693b8p-31, + -0x1.f68adfd33bf72p-1, -0x1.ca54f55a7fa56p-27, -0x1.f0bda5d3f40c4p-30, 0x1.d6ca9d8e60fa1p-26, + 0x1.55f0822bce66ap-31, -0x1.46a11dbb6f765p-4, -0x1.a9b88d0462deap-30, -0x1.7157798034c23p-34, + 0x1.37bf75dc96da4p-7, 0x1.e1cfc44a62aabp-34, 0x1.0955aecb88015p-37, -0x1.c03e5c8222431p-33, + -0x1.7aba71ebbff26p-30, 0x1.6ab2fbf63257ep-7, 0x1.0af347d03033dp-32, -0x1.09e7ef7e9dd3ep-35, + -0x1.60d6cffb76be6p-4, -0x1.6a9fb187dd436p-27, -0x1.65e938a9ff51dp-33, 0x1.92763eb0186c9p-30, + 0x1.f2dc19b415a10p-24, -0x1.d444a80e73de8p-1, -0x1.900fd86dabe72p-26, -0x1.79c02bbcb31f0p-28, + 0x1.a5ba41f7fd1f3p-1, 0x1.bbfc5b9bdf7bbp-24, 0x1.173eb40149987p-30, -0x1.cac3402c5610dp-27, + 0x1.7e1c68493f065p-20, -0x1.62fbec10dcd1ep+3, 0x1.5cbf588de41b6p-28, -0x1.714e0387dcd72p-32, + -0x1.6c0075ccf2615p+3, -0x1.75c6af8573ab0p-20, -0x1.b21bea27b637fp-32, -0x1.dc63478ee0b6ep-29, + -0x1.23e250a8c97aep-23, 0x1.0c0bd8144fe12p+0, 0x1.1dcba0ee0e5dfp-25, -0x1.1ea4a2e9dabdfp-27, + -0x1.eb630a1970bfbp-1, -0x1.021fde7d916bbp-23, 0x1.7e7477a2d54acp-28, 0x1.fa9d80e9c2cd3p-26, + 0x1.55876e817aa97p-27, -0x1.50bd282ce4fc6p-4, -0x1.0caddf02b094bp-29, 0x1.e64ec8711cce9p-33, + 0x1.4c7b720a3c254p-7, 0x1.4d0957ef51b75p-30, -0x1.b55e99bde955ap-35, -0x1.105f179d54556p-32, + 0x1.7d7c075bb6a18p-54, -0x1.5cac5bc3ca99ap-7, 0x1.27f67aeb7be01p-32, 0x1.71acd267fabacp-34, + 0x1.597a5d9f0357fp-4, -0x1.035592930ef0cp-33, 0x1.2e9e8a0805482p-31, -0x1.f6910975c2b90p-30, + -0x1.0117d1ac2251dp-28, 0x1.dffb6ba9d3ea4p-1, -0x1.c3ec346bd12d8p-26, -0x1.d266ccf744479p-29, + -0x1.de2be1716d4e8p-1, 0x1.53b42b2753ccdp-30, -0x1.542bc50445297p-28, 0x1.9bb9e2de4816dp-26, + 0x1.f280f5e695584p-27, 0x1.678bd9a86de73p+3, 0x1.20ad832bd5c53p-28, 0x1.802cc2a426a83p-31, + 0x1.678bd9a86de73p+3, -0x1.f280f621f2716p-27, -0x1.802cc2d072ac9p-31, 0x1.20ad830403a0ep-28, + -0x1.53b42efb649aep-30, -0x1.de2be1716d4e8p-1, 0x1.9bb9e304e37ecp-26, 0x1.542bc53a51c19p-28, + 0x1.dffb6ba9d3ea7p-1, 0x1.0117d649b51d9p-28, 0x1.d266cde7d7d36p-29, -0x1.c3ec341b0a8d6p-26, + 0x1.03559059ee50cp-33, 0x1.597a5d9f0359ep-4, -0x1.f691098782fc9p-30, -0x1.2e9e8a0ee2e33p-31, + -0x1.5cac5bc3cac57p-7, -0x1.cf80163f4f804p-63, -0x1.71acd25f86a0dp-34, 0x1.27f67b5fca761p-32, + -0x1.4c7b720faa638p-7, -0x1.2b0381480a5a1p-30, 0x1.575ca9229f07ep-33, -0x1.5258e836f0274p-33, + 0x1.34f40233abee0p-27, -0x1.50bd27fb781b7p-4, 0x1.b1abf817763dcp-30, 0x1.24fcb5bfdb303p-30, + 0x1.eb630a1de1cd2p-1, 0x1.b28ad00b9b552p-24, -0x1.89b3bc688b350p-26, 0x1.61fa16fb698dfp-26, + -0x1.df4a5b3f0ffdap-24, 0x1.0c0bd8096814ap+0, -0x1.b5ed693f5c9a4p-26, -0x1.6b80921ccc865p-26, + 0x1.6c0075f0da921p+3, 0x1.3d21d542d44e3p-20, 0x1.a5010f28b5b23p-29, -0x1.65039dcfa6d2bp-29, + 0x1.4434b315fcb7bp-20, -0x1.62fbec175f0b8p+3, -0x1.d86eb3116ccf4p-29, -0x1.7adee75d6de7fp-29, + -0x1.a5ba41fb8cca3p-1, -0x1.6b1fe7edea17cp-24, 0x1.09f0c93055485p-26, -0x1.93817b7c04ebep-27, + 0x1.a920b6c04f363p-24, -0x1.d444a825e264fp-1, 0x1.a8ee99f7d9673p-27, 0x1.3935996932bb1p-27, + 0x1.60d6cffc09d8cp-4, 0x1.33d96334fd0d8p-27, -0x1.3976b813dbfd3p-30, 0x1.3b6b58f7b41b7p-30, + -0x1.48accfdedde33p-30, 0x1.6ab2fc1c81891p-7, -0x1.d5a1debc2e7adp-34, -0x1.0484775176615p-33, + -0x1.37bf75cd7f8f9p-7, -0x1.81843518e5c13p-32, 0x1.e70dd707be3cap-35, 0x1.bb1629fe4a40cp-33, + 0x1.5b7b553c7bb8dp-29, -0x1.46a11dc86f949p-4, -0x1.f6c7d437c8ad7p-30, 0x1.29ac5c523aa0cp-33, + 0x1.f68adfbbe10bep-1, 0x1.3a53981748864p-25, -0x1.897febb29450bp-29, -0x1.ecb93d73b77bep-26, + -0x1.7198a5cabf9d5p-25, 0x1.29c187f405d6dp+0, 0x1.952d959ecfe7fp-25, -0x1.d396fd5252211p-29, + 0x1.705b41e40e132p+3, 0x1.903454149ee3ep-22, 0x1.252a39136e39cp-31, 0x1.de181f0daaff1p-29, + 0x1.a26fe443607fcp-22, -0x1.5e5417bdf8daap+3, 0x1.cc9603838d327p-28, -0x1.81585ae10c8e8p-32, + -0x1.6ed7e5b19fefdp-1, -0x1.7fb972d7063edp-26, 0x1.3e518d54cd75ep-28, 0x1.1976c2ac90ca5p-26, + 0x1.f51b3fca5c44ap-26, -0x1.c86fc7dad8b9fp-1, -0x1.61e9d598f5061p-26, -0x1.41bdce3f81cc4p-33, + 0x1.66d599eb7c946p-4, 0x1.861ac6ceb975bp-29, -0x1.bcb24c226ca7ap-34, -0x1.dbb9bd4e667e3p-30, + -0x1.ca2c9b51feb5ap-32, 0x1.7a4b59d72ac5ep-7, 0x1.21c95621a9cd5p-32, 0x1.c42b17ec8ce0ap-35, + -0x1.23be79ade6616p-7, -0x1.f3815ac78d289p-35, 0x1.1531dae151cb3p-35, 0x1.42c3db17cb683p-32, + 0x1.c43c6d7899fcap-33, -0x1.3b4a4ba075973p-4, -0x1.1af9fe68367b4p-30, 0x1.a704ee2d30f5cp-32, + 0x1.00c2cda2266e7p+0, 0x1.21f5616cd7233p-28, -0x1.25bf24a642896p-27, -0x1.27133ad2a2e95p-25, + -0x1.0e434c53907ddp-28, 0x1.483e09888c3e0p+0, 0x1.805bf0ddd0667p-25, -0x1.336fc4165115bp-28, + 0x1.749af97b8639fp+3, 0x1.ed44b25a50c70p-26, 0x1.313e6e94aedabp-30, 0x1.fa0ab0dc6e6d7p-29, + 0x1.070c9a77bc4c3p-25, -0x1.59952f8eaab35p+3, 0x1.ec536ffde863ap-28, -0x1.445a5f5a73f01p-30, + -0x1.39920fac20e41p-1, -0x1.25e6480adedcep-29, 0x1.e266e7d0c519bp-28, 0x1.ce8f7f04c7e05p-27, + 0x1.478d15fe9b35fp-28, -0x1.bc60975bad68ep-1, -0x1.8a3d2f4b8d80ep-26, 0x1.142eefb76a1f2p-27, + 0x1.6b191979dfb2ap-4, 0x1.16141361aa967p-31, -0x1.5c035fc0aed68p-31, -0x1.09a0c4d9c5037p-29, + -0x1.01593aebe8272p-36, 0x1.7fbebf7c5c16ap-7, 0x1.7ab6ba72b2996p-33, -0x1.7197b5fb92ad2p-34, + -0x1.0dc6b32a40165p-7, 0x1.15f4aa26eff43p-33, 0x1.eaf7c82cbda6ap-35, 0x1.3d806be85226cp-33, + -0x1.7bdd6797648b9p-30, -0x1.2db983466b4dep-4, -0x1.b5b5010549397p-30, 0x1.82504e8cbf6fbp-33, + 0x1.06071138eb8dcp+0, -0x1.4ccb8ae7a8b90p-26, -0x1.c1f8a63ae203dp-28, -0x1.3ed42c3d86c5fp-25, + 0x1.c44d84aa4016bp-26, 0x1.677187045939ep+0, 0x1.ca8a4a6aeda79p-25, -0x1.e2fd85aa09b59p-30, + 0x1.78bd8cfc10a75p+3, -0x1.5798fc9656873p-23, 0x1.605d1f777a410p-31, 0x1.f302fdc42b5c0p-29, + -0x1.7675cf159c012p-23, -0x1.54be3f1313d98p+3, 0x1.3744cf5ba790cp-27, -0x1.927775d53632fp-31, + -0x1.05c28f50ecc69p-1, 0x1.f81e03757a07ep-28, 0x1.b3de2b0c4a8e0p-30, 0x1.3680b0ecedc7dp-27, + -0x1.14c5dba4db535p-26, -0x1.b03c2e9da8344p-1, -0x1.b357e387c7b49p-26, 0x1.b0a0971d6f5b3p-28, + 0x1.6e755f02dba2fp-4, -0x1.a22466ba3da65p-30, -0x1.91c0c6182ea41p-32, -0x1.9bc874669448dp-30, + 0x1.a8c488c11fe3ep-33, 0x1.8ac9f6c9ada2dp-7, 0x1.caf8481d1f997p-33, -0x1.977b63c7bce7ep-35, + -0x1.e3021b2190909p-8, 0x1.9cfebc036a289p-39, 0x1.d2182c82e2631p-37, -0x1.22d20839eefa0p-33, + -0x1.98912fe772312p-33, -0x1.1f0f53728a99ap-4, 0x1.8ad3129404c34p-30, -0x1.903be404ade68p-34, + 0x1.0b290f90e1b0bp+0, 0x1.6d1643248660bp-29, -0x1.9a05a2cfc9ab5p-29, 0x1.28276e5ff37c4p-25, + 0x1.a4e05e916e23ep-28, 0x1.8762ef2335c4ep+0, -0x1.d2c1ed92c4276p-25, -0x1.9c4ea36a9dd37p-29, + 0x1.7cc3fd352c42ap+3, -0x1.8c721838e6aa4p-29, 0x1.aafb3937ab72ap-32, -0x1.b0e4e326ed57dp-29, + -0x1.444589650fee9p-29, -0x1.4fd25549c45e1p+3, -0x1.4b48e1406acdep-27, -0x1.209210bf9cb43p-32, + -0x1.a7145f09aee4fp-2, 0x1.b323fc40ecb94p-31, 0x1.e62c351a72cc5p-29, -0x1.c7f2f4e90e797p-29, + 0x1.798f83300072dp-29, -0x1.a3e2d13d161a9p-1, 0x1.792cf5c4319bep-26, -0x1.31f969af5128fp-29, + 0x1.70bedf36fdfe5p-4, -0x1.2bf1c58875d03p-34, -0x1.17d45212afa04p-31, 0x1.82fc8fe8d0d30p-30, + -0x1.067e81cb78cd9p-35, 0x1.9012c76d065a2p-7, -0x1.5b61b3c389008p-32, 0x1.0f931fad34a6ep-38, + -0x1.ad67937ab82e7p-8, 0x1.e24754e8000f3p-36, 0x1.3198bcc33d17cp-35, -0x1.663d30e45706dp-34, + -0x1.3d147e20cfc2cp-32, -0x1.0e58c5b276336p-4, 0x1.d74a0416ed2ebp-30, 0x1.7385f9bdb1924p-35, + 0x1.101ffb8e46ee3p+0, -0x1.009faff76d400p-28, -0x1.81862e8564367p-27, 0x1.0b9d2e6281c42p-25, + 0x1.81adeaf9d7778p-28, 0x1.a8122b34e802bp+0, -0x1.0fea85d44fdaap-24, -0x1.5dbbd29fe083bp-28, + 0x1.80ac3145d09d9p+3, -0x1.1e61bf218d289p-25, 0x1.24d5b29ec533fp-30, -0x1.93bf32ea3538fp-29, + -0x1.4725a6224490dp-25, -0x1.4ad1276d80424p+3, -0x1.7bb5ed46fe92ap-27, -0x1.22665e3dbbb69p-30, + -0x1.45c5138cc7330p-2, -0x1.045d90962f7acp-36, 0x1.5cf005f31aecfp-29, -0x1.c03edd9641d2ep-28, + -0x1.29a1ca7745c6bp-29, -0x1.97755940fdd14p-1, 0x1.8f8486ae33d0dp-27, 0x1.adb5d53999bb8p-29, + 0x1.718d5f317cc6dp-4, -0x1.37807cc42d160p-32, -0x1.b32bc84d93727p-31, 0x1.70f0e1d32b491p-30, + -0x1.66b0f1dd3b9c5p-35, 0x1.96bdcf4e6c7a9p-7, -0x1.637f57f64d949p-32, -0x1.a4e05f8fe9381p-36, + -0x1.6f1ff950ea63ap-8, -0x1.14715b5499600p-34, 0x1.0790db91ae62cp-37, -0x1.9dfa718652317p-34, + 0x1.1500946b28ae5p-31, -0x1.f80e4b1646fc7p-5, 0x1.1bdb2b91a2592p-30, -0x1.91a91aee7cc41p-33, + 0x1.14ebb359a507fp+0, 0x1.4697257174dcep-27, 0x1.ef2a0548a00a7p-29, 0x1.30988ac26fb1cp-25, + -0x1.bc381c754ae11p-27, 0x1.c973c8ff019a3p+0, -0x1.ef7b2b15940eep-25, 0x1.2e4e0e7a321c5p-30, + 0x1.8475617143ee8p+3, 0x1.122926f72387fp-23, -0x1.63b58a939664ep-32, -0x1.ba8c03e1c091fp-29, + 0x1.431b0d5781300p-23, -0x1.45bbbd6e29540p+3, -0x1.88f355097ccd4p-27, 0x1.f9cf5bd7dacecp-32, + -0x1.cef9a71a1623ep-3, -0x1.8982df19614aap-29, -0x1.073ff70b85639p-34, -0x1.6438ba9e784dap-29, + 0x1.101ed70bd3e8ap-27, -0x1.8afd7924ab583p-1, 0x1.27a0d6a723ad8p-26, -0x1.e2043a91f3a4fp-29, + 0x1.71fc19314d990p-4, 0x1.a7e0969e38f85p-31, 0x1.9304a770b4ec4p-33, 0x1.b6bf16710154bp-30, + -0x1.5a6b91d33bf4fp-34, 0x1.9905474472218p-7, -0x1.d4079074920f1p-34, 0x1.c98410a693d44p-35, + -0x1.2fc53fb7edf92p-8, -0x1.abddcec4a27d4p-35, 0x1.3ba820c2aa5dap-35, -0x1.b2f8ba2f3b4fep-34, + 0x1.41f8eac666d1ep-31, -0x1.d002dfacc88a1p-5, 0x1.92902101fb03ap-30, 0x1.11cf7ae116e21p-32, + 0x1.1969c3eee283bp+0, 0x1.8b49c8699fcc0p-27, -0x1.2628740457c11p-27, 0x1.ef9607a855126p-26, + -0x1.49fb37de3ffd8p-26, 0x1.eb8d4bb7c724bp+0, -0x1.2dc77c5504d7dp-24, -0x1.2c6ae379b63d4p-29, + 0x1.881fc7bbddfdbp+3, 0x1.6e91309b1595dp-24, 0x1.b1b31abfc4827p-31, -0x1.6960c1e518769p-29, + 0x1.b311f1a1d0128p-24, -0x1.40935bc5c2ebep+3, -0x1.010af121aca80p-26, -0x1.9dbb1846577d6p-31, + -0x1.18dc39c70b2cbp-3, -0x1.c0d2bfc019ff8p-31, 0x1.9fe8120272882p-30, -0x1.7cbee9f8748dap-29, + 0x1.3fe7a5a0b035dp-27, -0x1.7e7013c9dd2aap-1, 0x1.5664737ef7225p-26, 0x1.321468fe8473cp-28, + 0x1.707295ba8a012p-4, 0x1.8f6173e8cf413p-31, -0x1.279e5db09ebe2p-31, 0x1.8a7027bd7507bp-30, + -0x1.54b2dcb737102p-33, 0x1.992303d9d7cd5p-7, -0x1.39f462680d2f9p-32, -0x1.952d0ec8dc0e2p-34, + -0x1.b80da013476bbp-9, 0x1.c80aee3c5c1c7p-35, 0x1.20152fd3d344dp-37, -0x1.d0a9e0b1837b5p-35, + -0x1.0697941ff307fp-30, -0x1.a4a280400b8c0p-5, 0x1.b103af37be844p-31, 0x1.5861c9b5d8251p-33, + 0x1.1dbfd5fe2e63cp+0, -0x1.543064bdefddbp-26, -0x1.25b3b5891839ap-29, 0x1.6c1b4d87cb3c9p-25, + 0x1.7971198af4ce5p-25, 0x1.072b28176904ap+1, -0x1.388b3f4487c4cp-24, -0x1.1cd9496ff65c6p-31, + 0x1.8ba9921700da7p+3, -0x1.7eae40bb37a2bp-23, 0x1.ac039c245f8f7p-33, -0x1.077b8813bd8d7p-28, + -0x1.cfb0e5fb167f6p-23, -0x1.3b58afee80756p+3, -0x1.179cddccd70d1p-26, -0x1.7c6ca00647a4dp-32, + -0x1.a491c2221cbe6p-5, 0x1.de2fdca300064p-31, 0x1.bffd1c8681dc0p-36, -0x1.49df775c9ebb9p-31, + -0x1.6089b3228d4c8p-27, -0x1.71dbfc30512ccp-1, 0x1.fe66d438f79cdp-27, 0x1.bc4adb7cd89a8p-29, + 0x1.6e986e236e1f5p-4, -0x1.bf9b8fcd486fdp-30, -0x1.ea840564bcd08p-33, 0x1.8397030db09dbp-31, + 0x1.7499c3f715827p-33, 0x1.97e3a3f04655fp-7, -0x1.067f9ff33bf7dp-32, -0x1.7e19d1efcb99ep-34, + -0x1.2f53fbb667fb9p-9, 0x1.e798eaaf8f03ep-36, 0x1.167c8c7973324p-39, -0x1.ffc97c5a6ed02p-36, + -0x1.85c62f4b08802p-31, -0x1.74db79acdd812p-5, 0x1.15e86e98a3e23p-30, -0x1.a4162e5fc5cb6p-32, + 0x1.21d83f980c9c2p+0, -0x1.b35e0e4add797p-27, -0x1.cf307b28282b0p-33, 0x1.933b1fa637bb6p-25, + 0x1.83312537bb32ep-26, 0x1.18e4cfcbdf54fp+1, -0x1.48804d5ea865ap-24, -0x1.b63927b6b32d0p-31, + 0x1.8f1149a01ed29p+3, -0x1.f803083284ae3p-24, 0x1.5db6e3ea3c43fp-36, -0x1.25d260c206495p-28, + -0x1.3b6706e162273p-23, -0x1.360e5d97c67a7p+3, -0x1.3ca22be5ac0d5p-26, 0x1.d8fa4cdcd41fcp-35, + 0x1.031259b0d71c4p-5, -0x1.84df74c622a08p-32, -0x1.07362c325f20fp-35, 0x1.39bd08b128618p-31, + -0x1.06b3098587a5ep-27, -0x1.6540477c8316dp-1, 0x1.07091111d0844p-26, -0x1.bbbc1e6127c51p-29, + 0x1.6b90cd804f8bcp-4, -0x1.14adda489a954p-30, -0x1.a400f3da1e88dp-34, 0x1.df91ce49ef418p-30, + 0x1.3d0b8834892fap-33, 0x1.9abe9f612b607p-7, -0x1.1f4cc2a71767bp-32, 0x1.45bf5dafe4551p-37, + -0x1.02edc58dd875dp-10, -0x1.6150c250ce5b0p-39, 0x1.ebf062b77a0b9p-41, 0x1.fa76368952cd3p-37, + 0x1.6e9af9141c293p-34, -0x1.413d036c57c5ap-5, -0x1.4f0a05677c130p-31, 0x1.37dbf03537851p-33, + 0x1.25af2da33f37cp+0, 0x1.4a7b1e69b727ep-30, -0x1.5869e11c3e39cp-28, -0x1.52af3c8944e07p-25, + 0x1.d9d2440a4e5f2p-31, 0x1.2af5cd66b9e3bp+1, 0x1.667736838378cp-24, -0x1.e1f7c14fb8ddep-30, + 0x1.92590178e32b1p+3, 0x1.a45b0dfd1ed66p-27, 0x1.f9e0a50103a9fp-32, 0x1.f213f2e7b7359p-29, + 0x1.1981fdb95bee0p-26, -0x1.30b28f8a9fba4p+3, 0x1.709d252e42e0bp-26, -0x1.5c6382562b4a6p-31, + 0x1.c85f43032f71ep-4, 0x1.f5d0d8ce75ab3p-32, -0x1.39d90aa948450p-32, -0x1.08532a84dd4e6p-29, + 0x1.0092ac4699c69p-29, -0x1.5898814b5553bp-1, -0x1.dcb8f16301d8bp-27, 0x1.8ac73a985ab06p-29, + 0x1.67a2b74b5e36bp-4, 0x1.c166cbb7d1e0ep-33, -0x1.5b1f08d046645p-35, -0x1.75f89839afccbp-30, + -0x1.622006060b009p-37, 0x1.9501298060ffap-7, 0x1.40c7eb1c98517p-32, -0x1.4c7735c071a1fp-38, + -0x1.c4d0f1ad6adf8p-13, -0x1.2be596f046742p-42, -0x1.15efed1c1e5a3p-41, -0x1.045e6275c3407p-38, + 0x1.8fab10462540bp-33, -0x1.09bcd7c40e95fp-5, -0x1.f966a333c93c9p-31, -0x1.2f4c9eb7733f6p-37, + -0x1.293d55c96f2f1p+0, 0x1.0a2348b2c32f9p-32, 0x1.87893199a4de1p-28, -0x1.5e3dfea35aaaap-25, + -0x1.c6ccf84db9007p-27, 0x1.3d5c09cdd0f07p+1, 0x1.6de120c598856p-24, 0x1.75016d212c7abp-29, + -0x1.957d8fc829a97p+3, -0x1.5c3294abbd613p-30, -0x1.1eb066428033fp-31, 0x1.040cfa83d0ff5p-28, + -0x1.04b14f1fcad5bp-29, -0x1.2b48ddce05e09p+3, 0x1.91e71b0b577c2p-26, 0x1.63b6b7453858fp-31, + -0x1.816e05c04c007p-3, 0x1.5bb5d61a8b1e8p-32, -0x1.4c535d3143704p-34, -0x1.6f8407d4f965dp-29, + 0x1.14d0c80d2dd9cp-30, -0x1.4c0fe1cddcf2ep-1, -0x1.8ff263e615c67p-27, 0x1.1f241dd921506p-30, + -0x1.632f19b46753ep-4, -0x1.49f1bfaa644fcp-32, 0x1.59907cf107fbdp-34, -0x1.539a45140aaa0p-30, + 0x1.08875967551c6p-37, 0x1.92b99fa39b510p-7, 0x1.c3551af09654dp-33, -0x1.2120877307328p-36, + -0x1.cb047dae0a113p-10, 0x1.dc7d5538460e1p-38, -0x1.beda48bd96994p-38, 0x1.31cad2e575f6ap-35, + -0x1.c648c3a0c9a56p-35, -0x1.9dc935cb3e73bp-6, 0x1.4fff78fe1b3cep-32, -0x1.f1e4a1c4b8906p-37, + -0x1.2c7da7cb9810cp+0, 0x1.04ad2b431f3d9p-28, -0x1.c336439d3069dp-28, 0x1.7170907262bd4p-25, + 0x1.c1904a108f16bp-29, 0x1.50117f7702451p+1, -0x1.85585bf29e7c9p-24, -0x1.d0b1e0a61dbf7p-29, + -0x1.987f59ab21a64p+3, -0x1.7aae52c0b87e8p-26, 0x1.5b03974af1a0ep-31, -0x1.191245a1e1360p-28, + 0x1.0aea69e72a12ap-25, -0x1.25cffbc2eb58ap+3, -0x1.cb914d22179a2p-26, -0x1.aa55e032f90e7p-31, + -0x1.0c3547c5587ecp-2, -0x1.5f5be60aa9d9dp-35, -0x1.53f2968dd80cdp-30, 0x1.a2d96a18e6f95p-28, + 0x1.c07918f540784p-32, -0x1.3f882fa53cc2fp-1, 0x1.a20d3db62189fp-27, -0x1.8295ab58360d6p-29, + -0x1.5e6e97dc9d871p-4, -0x1.754ed6ae10bd8p-32, -0x1.57c29b56de078p-32, 0x1.ac0d57e4d6ff6p-30, + 0x1.30c255dc001d7p-37, 0x1.88b919b87507dp-7, -0x1.e10dfc9ec28abp-33, 0x1.86e001481dc38p-34, + -0x1.ac73a38a1f7e5p-9, 0x1.c47ee68c1bf78p-37, -0x1.4fc5172002de0p-36, -0x1.504a6cd357c3dp-35, + -0x1.6495bb57a6dc4p-34, -0x1.1dcc49c50a6aap-6, -0x1.3d275a51158ccp-32, 0x1.35b37e4dd2654p-35, + -0x1.2f83ddd0ef30cp+0, 0x1.6ca7a1c2a1879p-27, -0x1.2779bdd90a906p-27, -0x1.4fae20f1b8813p-25, + 0x1.e7f01ffbe7cc3p-27, 0x1.63157b96b90f2p+1, 0x1.d471ed4307cb7p-24, -0x1.7c609f749251dp-29, + -0x1.9b5d9b5c13352p+3, 0x1.7a4e83fdb6ca8p-25, 0x1.d5e4f4d6b2c7ep-31, 0x1.0755ea8bb1b37p-28, + -0x1.004685c405ad3p-24, -0x1.204be1a6852b1p+3, 0x1.25615b8d15a9ap-25, -0x1.1a372f100beb6p-30, + -0x1.54c84b9e69174p-2, 0x1.67a26baf65640p-29, -0x1.3fe612617cfbap-29, -0x1.23b21107de455p-27, + -0x1.32a273f94b06cp-28, -0x1.330bf3add43dbp-1, -0x1.25e789dd9b6fcp-27, 0x1.6813aceceab7cp-29, + -0x1.57cf3ba37a577p-4, 0x1.0534087e33684p-31, -0x1.ca4a0d2947e71p-33, -0x1.56bc27bad9959p-30, + 0x1.018f613a9b4c4p-34, 0x1.861ea1b40a8d9p-7, 0x1.1ad21ff6fa546p-33, -0x1.1731a5d0772b9p-35, + -0x1.3547dfea2c909p-8, -0x1.42ae6431439a8p-35, -0x1.a13f7b66b0890p-39, 0x1.4777e0f276007p-34, + 0x1.066f2738f2f57p-34, -0x1.31c753df1dc5dp-7, 0x1.4425718db5f9fp-33, -0x1.c9dcc7406621ap-37, + -0x1.322813a1e0067p+0, -0x1.bb923c1567c17p-27, -0x1.60b3a20eb45a5p-30, 0x1.466e3bbf990d9p-25, + -0x1.4d5338226fe17p-26, 0x1.7668e3c06b064p+1, -0x1.8155923dd277ap-24, -0x1.b87bfdbb5a61ap-31, + -0x1.9e1709e2e7764p+3, -0x1.cbe8ca5481bbbp-25, 0x1.0301618526563p-33, -0x1.fc0de9f9c7fb4p-29, + 0x1.3c05a88c1c752p-24, -0x1.1abaa1f674e8bp+3, -0x1.02b1e032cb200p-25, -0x1.a0a0c4a47c7e9p-36, + -0x1.9a1a99d3caebep-2, -0x1.4c812e579d392p-28, -0x1.2205bb9d7cd06p-34, 0x1.8a000c2f3254fp-28, + 0x1.9827e4c2e842bp-28, -0x1.26aa0bc7cef76p-1, 0x1.b3d147af557e9p-28, -0x1.fda9385c85614p-29, + -0x1.50e739f42c96ap-4, -0x1.9959f6236ecb0p-31, 0x1.ebf79df3dcf2fp-32, 0x1.3190c4632d3a5p-30, + -0x1.11f5ebafbd32bp-34, 0x1.7c5f89d7aed05p-7, -0x1.2a48dd6954d48p-33, 0x1.b3c72b6da8228p-37, + -0x1.a6369d225d9f7p-8, 0x1.0cffc3bef1748p-36, -0x1.4aa6536a07e36p-38, 0x1.2a20dc331554cp-34, + -0x1.799f4b8dc5b02p-39, -0x1.cf208115634a0p-12, 0x1.524e19b930e76p-38, -0x1.e7c5176e83761p-42, + -0x1.347c2b886ffcap+0, 0x1.a3daf6a0f31b0p-28, 0x1.a2f28a100b996p-30, 0x1.0d337b79854dcp-25, + 0x1.6a723bb3595a2p-28, 0x1.8a074373aa0d6p+1, -0x1.8aeaefd7300c1p-24, 0x1.1eefebad961d6p-31, + -0x1.a0ace5341d513p+3, 0x1.46a3ce10b724ap-26, -0x1.2bb4c21c93efdp-33, -0x1.abf54c4147452p-29, + -0x1.d9ea5e94b9c5fp-26, -0x1.151f6b6e99d96p+3, -0x1.1d45a5582b4cap-25, 0x1.3cebd598b71a0p-33, + -0x1.dc7c6d475feecp-2, 0x1.cc3be0e08da02p-29, -0x1.2c18dfae3105ep-33, 0x1.9006a48107fc7p-28, + -0x1.586b0b5e791a2p-29, -0x1.1a503f8ef0715p-1, 0x1.1b7d8ec1d1eb4p-27, 0x1.656b9784c2684p-31, + -0x1.4a417576bff27p-4, 0x1.222168bda0d17p-32, 0x1.5aa3ecca61d9bp-36, 0x1.e98af81fd5111p-31, + 0x1.e6ab0f787f94cp-35, 0x1.7745834248926p-7, -0x1.405ba411ff082p-33, -0x1.91ba6cfb489a5p-37, + -0x1.0bc6364c11531p-7, -0x1.c73335ee94958p-35, -0x1.ac1cbfdb1da37p-35, 0x1.743506bafd8c3p-33, + 0x1.bdcfdd6716d05p-35, -0x1.1e7c56648af62p-7, -0x1.0b857aa70a664p-33, -0x1.11022e54e1d6dp-34, + -0x1.367af04819bd2p+0, -0x1.047b0459ccdddp-26, -0x1.2c84ac27682b8p-27, 0x1.6cf5f67c641cap-25, + 0x1.adbbb31bf312ep-27, -0x1.9df3b848b2963p+1, -0x1.af3378c313b45p-24, -0x1.f8dcdee89c9b6p-29, + -0x1.a31c9a529cc1ep+3, -0x1.571a00a910705p-25, 0x1.0c65eeac5f661p-30, -0x1.2e57f1f45391ep-28, + -0x1.faddeb0800e78p-25, 0x1.0f79884fb36c8p+3, -0x1.4cd0bc3c4558dp-25, -0x1.802585ee0ce38p-30, + -0x1.0dfec238d0516p-1, -0x1.eb352f5e01dcdp-30, -0x1.141b31b8af575p-28, 0x1.85b321a630132p-27, + -0x1.7d46e3bc30d5dp-29, 0x1.0e22723e57f14p-1, 0x1.050a5f8901c05p-27, -0x1.9c6082b10cf3cp-35, + -0x1.4207383cc29d0p-4, -0x1.0d29ecc287a12p-31, -0x1.b01090c800aedp-31, 0x1.89695537dfd52p-30, + 0x1.15042ae72f8cep-34, -0x1.6bf0c65e775a8p-7, -0x1.a32fda05250f5p-33, -0x1.8cdaafb211669p-35, + -0x1.471f7d91d5db5p-7, -0x1.890fa3c887d92p-35, -0x1.36d7a5743a2bcp-34, -0x1.c0b1fcebd78f2p-35, + 0x1.2477d0224accap-35, -0x1.2f4071a87fd1fp-6, 0x1.c9e8ebc30f54ap-33, -0x1.257a71ee00386p-34, + -0x1.381cb3aa1ffc7p+0, -0x1.eb24e8a3f830dp-29, -0x1.1112694eb142ep-29, -0x1.5cdf97f76c5e9p-25, + 0x1.bf0b0a00240a5p-27, -0x1.b21f354a959e4p+1, 0x1.a185ab35e4a64p-24, -0x1.2b5e2fd3811fbp-30, + -0x1.a565c1540dd92p+3, -0x1.78c5983b2867fp-26, 0x1.c2b5f43e53716p-32, 0x1.1f97b75353457p-28, + -0x1.025196bc7fec9p-25, 0x1.09ca8d9eb7e85p+3, 0x1.590871ed0fffep-25, -0x1.09222397dd798p-31, + -0x1.2c2b71b6f6c5fp-1, -0x1.244d1c0126741p-29, -0x1.58b24063e5bbdp-28, -0x1.42ff4f34b0b71p-27, + -0x1.204af56c24e32p-30, 0x1.020ffb9b0362bp-1, -0x1.0b3da2a808d59p-27, 0x1.52547e75f4e0fp-31, + -0x1.3a217d84759d3p-4, -0x1.a5a4f8f9ef48cp-32, -0x1.ebddad2c1acf1p-32, -0x1.29fc4158a5c37p-30, + 0x1.5b62b574767dcp-35, -0x1.63589f5fe0589p-7, 0x1.02f9f5eed7403p-33, -0x1.e00f261ae027ap-35, + -0x1.8703ed6a073dcp-7, 0x1.6ad6143cad121p-37, -0x1.655e2fdfd4a16p-35, 0x1.746d3c30daae7p-33, + 0x1.f64f2be1c2157p-37, -0x1.d8e4d920bd1efp-6, -0x1.0eb4bb94656b3p-32, 0x1.a8a50b244b720p-34, + -0x1.39573d714e074p+0, -0x1.f7af890b81ecbp-29, -0x1.c5f51f8739000p-30, 0x1.4c602148dc9ddp-25, + 0x1.6fbfe23b0c2d3p-28, -0x1.c695b935205a8p+1, -0x1.5d47792e2f177p-24, -0x1.4dca64e9e29bdp-31, + -0x1.a78a5d3549ee2p+3, -0x1.b61309484da3dp-27, 0x1.ee5feb90d436dp-34, -0x1.1a2ead187f9eep-28, + -0x1.492bdc64b4b20p-26, 0x1.04162fa0de035p+3, -0x1.32b12e37f26bbp-25, -0x1.eb5d0fd03da4ap-33, + -0x1.48dfe777ee291p-1, -0x1.09bce823c45e4p-28, 0x1.dd8d0ab7cfdd1p-31, 0x1.71d3a48e53dbdp-27, + -0x1.198fd75ffae46p-29, 0x1.ec57f331a5deep-2, 0x1.86cae396d7248p-29, -0x1.81edca43bcaf4p-31, + -0x1.3170a9838e3c3p-4, -0x1.6454c776597e8p-36, -0x1.5fff783573482p-32, 0x1.0dfda836ed9a7p-30, + 0x1.c10f122f3343bp-35, -0x1.56e6dd5804759p-7, -0x1.9bf5b4231b192p-34, -0x1.8aa5bfbbf6074p-37, + -0x1.c35491ebe852cp-7, 0x1.ebcf878d5f66cp-36, -0x1.dd71d3b696085p-36, 0x1.7e9f15b44fe4cp-33, + -0x1.196cf5cfe7d1fp-34, -0x1.4568a9ca3d509p-5, -0x1.288ef3fb2c924p-31, -0x1.347e53aa3f550p-33, + -0x1.3a3395f0b3068p+0, -0x1.8183eb10e5015p-29, -0x1.14f57bbedd86bp-27, 0x1.2d3e1341097fcp-25, + -0x1.6f607b4803cc4p-27, -0x1.db4709e3450b7p+1, -0x1.aff8a9eb1170dp-24, -0x1.6bdf9ab307846p-29, + -0x1.a98671e126ed3p+3, 0x1.543ccfee23e44p-26, 0x1.f62615e82f852p-31, -0x1.0d51c8f050738p-28, + 0x1.dc5521f5100afp-26, 0x1.fcb17dee8dd18p+2, -0x1.95cc950a070ebp-25, -0x1.5b631a994536dp-30, + -0x1.64299ff68f49bp-1, 0x1.77972da4776c6p-31, -0x1.b929603274a4ap-29, 0x1.bcff5d94441c4p-27, + 0x1.679ef7e5f183bp-31, 0x1.d4b35dea02a78p-2, 0x1.2ebe6da5b01fap-28, 0x1.f7837fe682868p-32, + -0x1.28498be1adcb2p-4, -0x1.60c58182c524cp-34, -0x1.2c052c585b0efp-32, 0x1.d16efd4aab711p-31, + 0x1.55b31a3eda1d9p-37, -0x1.4af4da00c5c26p-7, -0x1.1c2b7ab7197bfp-33, 0x1.3dc5ebadde093p-34, + -0x1.0327bdd88c74dp-6, -0x1.efc8c11591c9bp-36, -0x1.f4a3058de0182p-43, 0x1.0e8a0c6327695p-32, + 0x1.5d68980c6f01bp-33, -0x1.a28ff97255a99p-5, 0x1.25c9c0b9e4e32p-32, 0x1.2c3c626ff715ep-32, + -0x1.3aa4e19f4f0c2p+0, -0x1.f84fddccb7d99p-31, -0x1.088bbd5831714p-27, 0x1.745d0fb3ff458p-25, + 0x1.3a1113bf3d079p-25, -0x1.f03bdd9962d42p+1, 0x1.81e965a031c8ep-24, 0x1.18854926f87bcp-29, + -0x1.ab5cf9c55b8abp+3, -0x1.445cd14afa6a7p-27, 0x1.cd4d81554a2a2p-32, -0x1.5ae618862acebp-28, + 0x1.11aec037aa36bp-29, 0x1.f12d8baf2cd64p+2, 0x1.8274a692e4a88p-25, 0x1.3436046d61caap-30, + -0x1.7dfee394fe52fp-1, 0x1.7a2b28c4f1db9p-32, 0x1.616814ab4838dp-28, 0x1.437f9ff3f90d0p-26, + -0x1.a6a44131074e3p-30, 0x1.bd6a1b8fdc572p-2, -0x1.6813aed9a4789p-29, -0x1.eeed2bc9224a6p-30, + -0x1.1e97f9d8bfaa5p-4, -0x1.d416c55c1d99ep-34, 0x1.68c7dbfe96a51p-32, 0x1.4ef4070392696p-30, + 0x1.04081ff24245ep-34, -0x1.418857c9ef79dp-7, 0x1.38601df9a26eep-33, 0x1.aee4ebb794dc4p-35, + -0x1.26ea842698688p-6, 0x1.652906419b807p-33, -0x1.3721e5f302cb6p-38, 0x1.620262eb76b07p-33, + -0x1.a695cd8e39cd0p-32, -0x1.02381e02fac9ep-4, -0x1.bf8f9b863409ap-32, 0x1.f762acf0a228bp-33, + -0x1.3aaac1ff7bc74p+0, 0x1.8c402c0e8a69fp-28, 0x1.1bcb713f12db3p-30, 0x1.414975a519451p-25, + -0x1.f3dab03dc143ap-26, -0x1.02b62a12df038p+2, -0x1.a07564fbf4846p-24, 0x1.0a62c24d1e800p-31, + -0x1.ad0aa214dbe6dp+3, 0x1.a1df06ed5bb0ep-25, -0x1.469074f214135p-33, -0x1.40a7afc4e6590p-28, + 0x1.353f9c8070d73p-24, 0x1.e5a08fed69c2ap+2, -0x1.bc9a0a69fbb9fp-25, 0x1.fea442c4ea9c9p-33, + -0x1.964e441106533p-1, 0x1.f26a774f99581p-28, 0x1.ed5b1efd3ec5dp-31, 0x1.64cd569f35b6dp-26, + 0x1.710c80645f565p-29, 0x1.a680f807b304dp-2, 0x1.f1a183484d853p-30, 0x1.197fcde304335p-31, + -0x1.14fbae0424fbbp-4, 0x1.30399805ead23p-32, 0x1.43f3db567888dp-33, 0x1.a358ea81864bep-30, + -0x1.46b30535b0199p-34, -0x1.33ce4c13d38fbp-7, -0x1.097f3a552fcf3p-33, 0x1.a3d61bb0b5e65p-37, + -0x1.49b8c136444bep-6, 0x1.e6a16f707b1b5p-33, -0x1.903d93ce58788p-35, -0x1.75fb06ea2fb07p-33, + -0x1.0cbfc1be49b93p-31, -0x1.357a5d551c2d3p-4, 0x1.4bb84e42acf76p-31, -0x1.2e11b9e11b37ep-33, + -0x1.3a3f435a4f97bp+0, 0x1.54e76925b1036p-27, 0x1.3b004d7364723p-29, -0x1.538a854e41661p-25, + -0x1.16d2fa460f5c2p-25, -0x1.0d6b7b5bbffcap+2, 0x1.18823af732caap-23, 0x1.47eee7116a575p-30, + -0x1.ae918901f1919p+3, 0x1.3da5144cc448cp-25, -0x1.2c34d420c2f7dp-31, 0x1.4299f778dd194p-28, + 0x1.b3923f12336f5p-25, 0x1.da0a86f534e89p+2, 0x1.3fc7807d6c7f2p-24, 0x1.2e7c412ea4c7bp-31, + -0x1.ad566ee0b5955p-1, 0x1.27ddb5c806521p-28, 0x1.73da740363a8cp-28, -0x1.2ab1ee7c00f82p-26, + 0x1.856a0e36ed2eep-29, 0x1.9008891630738p-2, -0x1.10fba784ac701p-28, 0x1.493a9fec815cfp-29, + -0x1.0b842d6cf7d5cp-4, 0x1.344689780b060p-32, -0x1.50392348a9f0ep-35, -0x1.014423dc5a836p-30, + -0x1.d121aad9e93ddp-35, -0x1.29ae2d86124ddp-7, 0x1.6abcc786eeda5p-34, -0x1.3071f080c5663p-34, + -0x1.6c720f0108442p-6, 0x1.434011db5baadp-33, -0x1.d11214292c4e7p-34, 0x1.f94cf2ac2e73ep-32, + -0x1.c4a8ac42898a5p-34, -0x1.6aa86f0f3b85ap-4, -0x1.9e1c9985878ccp-32, -0x1.2f9bf66bf74a5p-33, + -0x1.395d610e73d8dp+0, 0x1.2634226c027acp-27, -0x1.b71973110fa00p-29, 0x1.363c48c669f8bp-25, + -0x1.28e88da9f9576p-25, -0x1.183b3763462acp+2, -0x1.07d02786f37afp-23, -0x1.2a328f8024687p-31, + -0x1.afef74fb75008p+3, 0x1.258ff372cf08ap-25, 0x1.e89b63f323661p-33, -0x1.2614085ab343bp-28, + 0x1.82433c23b34b8p-25, 0x1.ce7022ba86a55p+2, -0x1.40102ecfb8a28p-24, -0x1.ce13d236d714fp-32, + -0x1.c2efd4eb48e59p-1, 0x1.86355562dd0e3p-28, 0x1.1e577b0c87519p-30, 0x1.0726ef2add85dp-26, + 0x1.943f97abf1af7p-30, 0x1.79f2451a66628p-2, 0x1.823a115be3c34p-30, 0x1.e392a58db0302p-30, + -0x1.00f3275d9abecp-4, 0x1.0005cd5b5cf1fp-31, -0x1.e93649e4eae14p-35, 0x1.d31b010faf645p-31, + -0x1.6c5612fd7bf45p-35, -0x1.1e9aff37f0e4dp-7, -0x1.119aedeeac0fbp-33, -0x1.00db5f48885cep-38, + -0x1.94d5b19008ce4p-6, 0x1.4175a227830fbp-34, -0x1.56cf192a8a7c9p-34, 0x1.60af68cecca43p-31, + -0x1.2a317123dad57p-32, -0x1.a211b5950b078p-4, 0x1.321080abcc0f0p-37, 0x1.b63b10bb3f420p-35, + -0x1.380319cc2bc64p+0, 0x1.8159f8b5a10ccp-28, -0x1.95655bd6394dfp-28, 0x1.5c9178dbb709fp-25, + -0x1.73982f3e9b6eap-27, -0x1.232527dd9f6e2p+2, -0x1.a841aba3c007cp-24, -0x1.53bf324393288p-29, + -0x1.b12487f15b984p+3, 0x1.9a1ee9a4e4317p-28, 0x1.cd7a5e48a7f0fp-31, -0x1.64b1fb2a4e3dap-28, + 0x1.84bfe7b023d78p-28, 0x1.c2d24da5a36f0p+2, -0x1.11ef945d7e7b1p-24, -0x1.b5ae897a6cbf8p-30, + -0x1.d72a439e468bcp-1, 0x1.b3796408a3a86p-30, -0x1.36848145b47bbp-28, 0x1.82e67e28e8bd0p-26, + -0x1.31874687defb2p-37, 0x1.644c7f9f52a54p-2, -0x1.1205b2f2260a3p-32, -0x1.30b0f1861e5f1p-34, + -0x1.ece1d3d029892p-5, -0x1.2ff0cefe19b15p-34, -0x1.b64b9521c908dp-33, 0x1.168e8a231bfc6p-30, + -0x1.64645ee2137b6p-36, -0x1.1205c1e2e9bd1p-7, -0x1.b7237fd4b7d92p-37, 0x1.5286225347139p-37, + -0x1.ba2fc8ff35c7dp-6, -0x1.ba853ce038c86p-33, -0x1.6603512014062p-35, -0x1.90a2e63a094d3p-32, + 0x1.4b35b1cf4c3e8p-30, -0x1.dbe51f34967fcp-4, 0x1.46af16d819883p-31, -0x1.a7d6be5b4eaa6p-32, + -0x1.36314364328b0p+0, -0x1.50911992bb0fdp-27, 0x1.172ef49a17375p-29, -0x1.8fa6173e8dbf0p-25, + 0x1.122fd740d8cf5p-25, -0x1.2e274369331efp+2, 0x1.0e07f2940e242p-23, 0x1.212e89f9b91b0p-32, + -0x1.b2313142138e1p+3, -0x1.6162a27b8718fp-25, -0x1.0c94235c34effp-37, 0x1.74479b6fe8942p-28, + -0x1.09b0681731960p-24, 0x1.b734b34135d03p+2, 0x1.741e87eb9a740p-24, 0x1.a90b7de292831p-33, + -0x1.ea049efe7fb23p-1, -0x1.be6427c3ddff6p-28, -0x1.51e95c6b3b9b6p-29, -0x1.3264a31b1a89cp-26, + -0x1.93e23a0fc1101p-29, 0x1.4f1ad97157046p-2, -0x1.68fad99d1c9fap-29, -0x1.b2ffcc3b62393p-32, + -0x1.d7f7b12b9f5a4p-5, -0x1.216787ae2af74p-31, -0x1.12373e328c1edp-34, -0x1.fa8d8d38ed5f4p-31, + 0x1.829b7d59daf04p-35, -0x1.084751723c952p-7, 0x1.12dbc15ba691ap-34, 0x1.2b97b618791a9p-37, + -0x1.e0fd2092224d9p-6, 0x1.d507016ee341ep-37, -0x1.7ec22142fe021p-36, -0x1.f046d4ccaedeap-32, + -0x1.43d17498adb67p-33, -0x1.0c09544a804d4p-3, -0x1.573f5cc3071abp-31, -0x1.e3345a5170699p-33, + -0x1.33d87c6e60492p+0, 0x1.b976d222c5143p-28, -0x1.85be02993a3b2p-28, -0x1.3e6bbb86eb0d3p-25, + -0x1.2fab8f155c550p-27, -0x1.3940706c232b3p+2, 0x1.02d32156b7c51p-23, -0x1.31e1265d7c47fp-30, + -0x1.b3166e95ae38bp+3, 0x1.ef6738058cdb2p-27, 0x1.04d628efe59bcp-31, 0x1.28a5e2d6b6319p-28, + 0x1.a64b10cb54d3bp-26, 0x1.ab9764856c8dfp+2, 0x1.7b2dcfe6d09f4p-24, -0x1.c6b35bee93572p-31, + -0x1.fb941e81113e3p-1, 0x1.232002e12b6a5p-28, 0x1.ab2b8b599722cp-32, -0x1.e754d7171b094p-27, + 0x1.a04ebfeca165ep-30, 0x1.3a5d2249b8d5cp-2, -0x1.3488826bb2579p-36, 0x1.6bde3a5dfd070p-33, + -0x1.c322945a49a26p-5, 0x1.23b453053fd03p-33, -0x1.3348c2a38d868p-32, -0x1.ac81257f749e6p-31, + -0x1.106cbe1bd0283p-39, -0x1.00935a654e707p-7, 0x1.b14fe67ac6e00p-36, 0x1.e6a09a71661aep-36, + -0x1.040fd14a43e5cp-5, -0x1.22d44917ca7bbp-33, -0x1.8d681e9fdf44ep-35, 0x1.03ed76c5fab49p-31, + 0x1.151788a59f9ecp-31, -0x1.2b413d166bba2p-3, -0x1.832807a2a31b6p-31, 0x1.1182586accec4p-31, + -0x1.3103b7494d3c6p+0, -0x1.f75fc96aa229cp-28, 0x1.4a484976b28b6p-32, 0x1.76ffc8a24ad58p-25, + 0x1.74d71af1442e6p-26, -0x1.446e872873a70p+2, -0x1.0047ae00d9d30p-23, 0x1.01bfe2ee1f27fp-32, + -0x1.b3d01abe0883cp+3, -0x1.aeb9e0f4750a8p-26, -0x1.586e01990edc3p-33, -0x1.665fa6212ce45p-28, + -0x1.3bbcef608de70p-25, 0x1.9ffb36d49a694p+2, -0x1.8fe15d50da444p-24, 0x1.a37ff8e3634dbp-33, + -0x1.05eaa554c20fep+0, 0x1.1fdeee07d74fbp-30, 0x1.dc20052f6cb1bp-30, 0x1.3e0a41d4eba3cp-26, + -0x1.e71e23d2c8cedp-32, 0x1.25fbcf3a44a9ep-2, 0x1.49dddf4e19cdep-32, 0x1.438228ecec2c2p-34, + -0x1.ad1fe90cb28d3p-5, -0x1.7fcb3e0e7c8c5p-33, 0x1.7af4f824b5d9fp-34, 0x1.1ff74858c61bap-30, + 0x1.35adc35d933d7p-35, -0x1.ff34669e9bcb7p-8, -0x1.6423a08d324e6p-36, 0x1.85c8f75645910p-41, + -0x1.194d1f4d9735fp-5, 0x1.7c55d8f5a143fp-34, -0x1.554493b0d82bap-34, 0x1.26e4c4415dd03p-32, + -0x1.93b68f05ee440p-31, -0x1.4b72f337bdebap-3, -0x1.a9392094a3dffp-31, 0x1.ac878e98b4c8cp-32, + -0x1.2da1c35839858p+0, 0x1.4a826d8782f68p-28, 0x1.020213f6e0912p-29, 0x1.e0280b40afbabp-26, + -0x1.3997a187a1755p-27, -0x1.4fadc73fee4dcp+2, -0x1.0082f026e15a0p-23, 0x1.2ca27465d3527p-32, + -0x1.b46146eef64dfp+3, 0x1.16ab912f250f6p-27, -0x1.6db5025f2243ap-33, -0x1.49a90513bc7cdp-28, + 0x1.8a72b5ed79126p-27, 0x1.94663707fee80p+2, -0x1.a9cec0dbeb0f0p-24, 0x1.e33fd0ee33256p-33, + -0x1.0d63dd6f745c3p+0, 0x1.2d3b0355d7accp-28, 0x1.015d0a63b757bp-34, 0x1.08eae8418121cp-25, + 0x1.74f5979dc118dp-30, 0x1.1225117495b61p-2, -0x1.6e6fba21bd128p-31, 0x1.be90b7cb8151ep-32, + -0x1.97f792fc74a37p-5, 0x1.61edfb975211ap-33, -0x1.01c9711d6505bp-34, 0x1.165fef99685f4p-31, + -0x1.df9e2c4d59a47p-36, -0x1.036475748bee1p-7, 0x1.697f36135dcaep-42, 0x1.1d757a656313ap-36, + -0x1.2db117b33c33cp-5, 0x1.dd9eee7128119p-34, -0x1.61d3d387b312fp-33, -0x1.34009031df46dp-32, + -0x1.42ae9f0e961b5p-32, -0x1.6cc23f81417f3p-3, 0x1.3b47d4f7d2117p-31, -0x1.c09bcd0bdc1eep-31, + -0x1.29afd79330ce1p+0, 0x1.ef532366829c5p-29, -0x1.eb835e6de88a9p-29, -0x1.b6e1512570224p-26, + -0x1.fa43fc6fd30adp-27, -0x1.5b01557d3419bp+2, 0x1.e20d85a0c71ffp-24, -0x1.67cc2e119e351p-30, + -0x1.b4c9cb793beb4p+3, 0x1.504918f56ccc0p-27, 0x1.9536b34ab60c5p-31, 0x1.405e0f8f34d40p-28, + 0x1.4ae431eb5a45fp-27, 0x1.88d79d6fa62e5p+2, 0x1.a9a2d5ec36148p-24, -0x1.4d4419abad4a7p-30, + -0x1.1449139332786p+0, 0x1.4a2ddc7bbe2adp-30, -0x1.7742967963adbp-28, -0x1.0ddea9a1a5a33p-25, + 0x1.045069d818532p-33, 0x1.fd3b9f5486496p-3, 0x1.7dc574f0dc373p-30, 0x1.b9c718db8a4b3p-31, + -0x1.82430d9b5385dp-5, -0x1.6d7c20bb4b869p-36, -0x1.0dffae43f6990p-34, -0x1.0402762517299p-32, + 0x1.18002cadd3928p-36, -0x1.268763a6fa7aap-7, -0x1.188aacd31463fp-34, 0x1.1d3532b869b89p-36, + -0x1.42c5db5a87b49p-5, 0x1.14e4785c46fdep-33, -0x1.87b38ee794c7bp-32, -0x1.ebded662179c6p-32, + -0x1.0da8972d94af4p-30, -0x1.8f472f5d9c944p-3, 0x1.87f7ef599fbd1p-31, -0x1.92e2c5d53d0d2p-32, + -0x1.2533d5a983f93p+0, 0x1.86652a7b2dd11p-27, -0x1.e81364f870505p-28, -0x1.ec2e24af6cff4p-26, + -0x1.73a561d55196fp-25, -0x1.66642569f525cp+2, 0x1.a39ad4323f182p-24, -0x1.abdc068f698dbp-29, + -0x1.b50765708bc88p+3, 0x1.5650353eecaddp-25, 0x1.63d44d0a1efccp-30, 0x1.8f5770f205649p-28, + 0x1.dadc137483e9cp-25, 0x1.7d510f6b651ddp+2, 0x1.8a74b07ab7588p-24, -0x1.94ba63622c8fdp-29, + -0x1.1a7c838062e37p+0, 0x1.cba5b010a0158p-27, -0x1.285a686c5d6e4p-27, -0x1.69dffcbb17e04p-25, + 0x1.bf3002c10cc5dp-31, 0x1.d78bfb417d797p-3, 0x1.1b6b77ac79c6bp-33, 0x1.8622c1b6ef76fp-33, + -0x1.6d4dc16db9769p-5, 0x1.c059292d2bc93p-35, -0x1.45134930d8a85p-32, -0x1.294f225bf0847p-30, + -0x1.a399fa422f496p-35, -0x1.21af2398bff6dp-7, -0x1.107653e51a805p-34, -0x1.6c0e1182c0d95p-37, +}; + +// hybrid_synthesis_indices: 154x4 int16, sha256 f5beb3220e4530fc +const std::int16_t hybrid_synthesis_indices[616] = { + 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, + 0, 0, 1, 1, 0, 1, 2, 0, 0, 0, + 2, 1, 0, 1, 3, 0, 0, 0, 3, 1, + 0, 1, 4, 0, 0, 0, 4, 1, 0, 1, + 5, 0, 1, 0, 5, 1, 1, 1, 6, 0, + 0, 0, 6, 1, 0, 1, 7, 0, 0, 0, + 7, 1, 0, 1, 8, 0, 1, 0, 8, 1, + 1, 1, 9, 0, 0, 0, 9, 1, 0, 1, + 10, 0, 1, 0, 10, 1, 1, 1, 11, 0, + 2, 0, 11, 1, 2, 1, 12, 0, 1, 0, + 12, 1, 1, 1, 13, 0, 2, 0, 13, 1, + 2, 1, 14, 0, 2, 0, 14, 1, 2, 1, + 15, 0, 2, 0, 15, 1, 2, 1, 16, 0, + 3, 0, 16, 1, 3, 1, 17, 0, 4, 0, + 17, 1, 4, 1, 18, 0, 5, 0, 18, 1, + 5, 1, 19, 0, 6, 0, 19, 1, 6, 1, + 20, 0, 7, 0, 20, 1, 7, 1, 21, 0, + 8, 0, 21, 1, 8, 1, 22, 0, 9, 0, + 22, 1, 9, 1, 23, 0, 10, 0, 23, 1, + 10, 1, 24, 0, 11, 0, 24, 1, 11, 1, + 25, 0, 12, 0, 25, 1, 12, 1, 26, 0, + 13, 0, 26, 1, 13, 1, 27, 0, 14, 0, + 27, 1, 14, 1, 28, 0, 15, 0, 28, 1, + 15, 1, 29, 0, 16, 0, 29, 1, 16, 1, + 30, 0, 17, 0, 30, 1, 17, 1, 31, 0, + 18, 0, 31, 1, 18, 1, 32, 0, 19, 0, + 32, 1, 19, 1, 33, 0, 20, 0, 33, 1, + 20, 1, 34, 0, 21, 0, 34, 1, 21, 1, + 35, 0, 22, 0, 35, 1, 22, 1, 36, 0, + 23, 0, 36, 1, 23, 1, 37, 0, 24, 0, + 37, 1, 24, 1, 38, 0, 25, 0, 38, 1, + 25, 1, 39, 0, 26, 0, 39, 1, 26, 1, + 40, 0, 27, 0, 40, 1, 27, 1, 41, 0, + 28, 0, 41, 1, 28, 1, 42, 0, 29, 0, + 42, 1, 29, 1, 43, 0, 30, 0, 43, 1, + 30, 1, 44, 0, 31, 0, 44, 1, 31, 1, + 45, 0, 32, 0, 45, 1, 32, 1, 46, 0, + 33, 0, 46, 1, 33, 1, 47, 0, 34, 0, + 47, 1, 34, 1, 48, 0, 35, 0, 48, 1, + 35, 1, 49, 0, 36, 0, 49, 1, 36, 1, + 50, 0, 37, 0, 50, 1, 37, 1, 51, 0, + 38, 0, 51, 1, 38, 1, 52, 0, 39, 0, + 52, 1, 39, 1, 53, 0, 40, 0, 53, 1, + 40, 1, 54, 0, 41, 0, 54, 1, 41, 1, + 55, 0, 42, 0, 55, 1, 42, 1, 56, 0, + 43, 0, 56, 1, 43, 1, 57, 0, 44, 0, + 57, 1, 44, 1, 58, 0, 45, 0, 58, 1, + 45, 1, 59, 0, 46, 0, 59, 1, 46, 1, + 60, 0, 47, 0, 60, 1, 47, 1, 61, 0, + 48, 0, 61, 1, 48, 1, 62, 0, 49, 0, + 62, 1, 49, 1, 63, 0, 50, 0, 63, 1, + 50, 1, 64, 0, 51, 0, 64, 1, 51, 1, + 65, 0, 52, 0, 65, 1, 52, 1, 66, 0, + 53, 0, 66, 1, 53, 1, 67, 0, 54, 0, + 67, 1, 54, 1, 68, 0, 55, 0, 68, 1, + 55, 1, 69, 0, 56, 0, 69, 1, 56, 1, + 70, 0, 57, 0, 70, 1, 57, 1, 71, 0, + 58, 0, 71, 1, 58, 1, 72, 0, 59, 0, + 72, 1, 59, 1, 73, 0, 60, 0, 73, 1, + 60, 1, 74, 0, 61, 0, 74, 1, 61, 1, + 75, 0, 62, 0, 75, 1, 62, 1, 76, 0, + 63, 0, 76, 1, 63, 1, +}; + +} // namespace + +// Same field-for-field result the file loader produces for the same values. +const Kernels& builtin_kernels() { + static const Kernels kernels = [] { + Kernels value; + value.qmf_analysis.assign(qmf_analysis_coefficients, + qmf_analysis_coefficients + kQmfAnalysisCount); + value.hybrid_low.assign(hybrid_analysis_low_kernel, + hybrid_analysis_low_kernel + kHybridLowCount); + value.hybrid_indices.assign(hybrid_synthesis_indices, + hybrid_synthesis_indices + kHybridIndexCount); + value.hybrid_values.assign(hybrid_synthesis_values, + hybrid_synthesis_values + kHybridValueCount); + value.qmf_basis.assign(qmf_synthesis_basis, + qmf_synthesis_basis + kQmfBasisCount); + value.qmf_taps.assign(qmf_synthesis_taps, + qmf_synthesis_taps + kQmfTapsCount); + value.hybrid_count = static_cast(value.hybrid_values.size()); + return value; + }(); + return kernels; +} + +} // namespace joc::hrtf diff --git a/src/hrtf/public_filterbank.cpp b/src/hrtf/public_filterbank.cpp new file mode 100644 index 0000000..286e9ed --- /dev/null +++ b/src/hrtf/public_filterbank.cpp @@ -0,0 +1,610 @@ +#include "hrtf/public_filterbank.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "foundation/fft.h" +#include "simd/simd.h" + +namespace joc::hrtf { + +namespace { + +constexpr double kPi = 3.14159265358979323846; +constexpr std::size_t kQmfLength = dsp::kQmfFftSize; +constexpr int kQmfTaps = 10; +constexpr int kSynthesisRank = 4; +constexpr int kSynthesisTaps = 10; + +// ----------------------------------------------------------- filterbank ----- + +// One shared forward plan for the 128-point QMF transform. The analysis bank runs +// it 2 * slots * channels times per chunk, so the twiddle recurrence is built once +// instead of being re-derived inside every butterfly. +const dsp::FftPlan& qmf_fft_plan() { + static const dsp::FftPlan plan(dsp::kQmfFftSize, false); + return plan; +} + +// Public 64-band complex QMF analysis (public_filterbank.QmfAnalysis). +class QmfAnalysis { +public: + static_assert(static_cast(kQmfBands) == simd::kQmfAnalysisBands, + "the dispatched accumulate is written for this band count"); + QmfAnalysis(const Kernels& kernels, std::size_t channels) + : channels_(channels), coefficients_(kernels.qmf_analysis) { + history_.assign(9u * channels_ * kQmfBands, 0.0); + // The polyphase MAC consumes one coefficient per band, so the shipped + // [band][tap] layout makes its inner loop a stride-10 gather. Transposing + // once here turns that into a contiguous AXPY. The coefficient values and + // the accumulation order are untouched, so the sums are bit-identical. + coefficients_by_lag_.resize(static_cast(kQmfTaps) * kQmfBands); + for (int band = 0; band < kQmfBands; ++band) { + for (int tap = 0; tap < kQmfTaps; ++tap) { + coefficients_by_lag_[static_cast(tap) * kQmfBands + + static_cast(band)] = + coefficients_[static_cast(band) * kQmfTaps + + static_cast(tap)]; + } + } + premultiply_.resize(kQmfBands); + post_.resize(kQmfBands); + even_post_.resize(kQmfBands); + for (int band = 0; band < kQmfBands; ++band) { + const double phase = static_cast(band); + premultiply_[static_cast(band)] = + std::polar(1.0, -kPi * phase / 128.0); + post_[static_cast(band)] = + std::polar(1.0, -3.0 * (phase + 0.5) * kPi / 128.0); + even_post_[static_cast(band)] = + Complex(0.0, band % 2 == 0 ? 1.0 : -1.0); + } + } + + void reset() { std::fill(history_.begin(), history_.end(), 0.0); } + + // samples: [slots*64, channels]; output: [slots, channels, 64] complex. + void process(const std::vector& samples, std::size_t slots, + std::vector* output) { + const std::size_t joined_slots = 9u + slots; + const std::size_t history_size = 9u * channels_ * kQmfBands; + const std::size_t joined_size = joined_slots * channels_ * kQmfBands; + // The joined window is filled completely -- the history lands in its first + // 9 * channels * 64 entries and the new samples in the rest -- so it is a + // reusable scratch buffer rather than a fresh zero-filled allocation. The + // history tail is taken by index instead of from end(), because the buffer may + // be longer than the window this call uses. + if (joined_.size() < joined_size) { + joined_.resize(joined_size); + } + std::copy(history_.begin(), history_.end(), joined_.begin()); + std::copy(samples.begin(), samples.begin() + static_cast(slots * channels_ * kQmfBands), + joined_.begin() + static_cast(history_size)); + + // The two polyphase accumulators are read before they are written, so their + // zero fill is load-bearing and stays; only the per-call allocation goes. + const std::size_t accumulator_size = slots * channels_ * kQmfBands; + if (even_.size() < accumulator_size) { + even_.resize(accumulator_size); + } + if (odd_.size() < accumulator_size) { + odd_.resize(accumulator_size); + } + std::fill(even_.begin(), even_.begin() + static_cast(accumulator_size), 0.0); + std::fill(odd_.begin(), odd_.begin() + static_cast(accumulator_size), 0.0); + // The ten lags are ten accumulate passes over the same 64 bands with one + // shared coefficient row; the bands are independent accumulations of a + // single product each, so they are what the dispatched kernel puts in its + // lanes, and every band keeps the caller's own multiply-then-add. + // + // Slots are processed in blocks, with the lag loop inside: one lag pass + // touches every source row once, so running the ten passes over the whole + // chunk re-reads the joined window ten times -- at 1536 slots that is + // hundreds of megabytes per chunk and the loop ends up bound by memory, not + // by arithmetic. A block's ten lag passes instead slide over a window of + // (block + 9) rows that stays in the second-level cache. Lags still run in + // ascending order inside a block, which is the order each output's sum is + // formed in, so nothing about the arithmetic changes. + constexpr std::size_t kSlotBlock = 32; + for (std::size_t first = 0u; first < slots; first += kSlotBlock) { + const std::size_t block = std::min(kSlotBlock, slots - first); + for (int lag = 0; lag < kQmfTaps; ++lag) { + std::vector& target = (lag % 2 == 0) ? even_ : odd_; + const double* row = + coefficients_by_lag_.data() + static_cast(lag) * kQmfBands; + const std::size_t source_slot = 9u - static_cast(lag) + first; + simd::qmf_analysis_taps( + target.data() + first * channels_ * kQmfBands, + joined_.data() + source_slot * channels_ * kQmfBands, row, + block * channels_); + } + } + std::copy(joined_.begin() + static_cast(joined_size - history_size), + joined_.begin() + static_cast(joined_size), history_.begin()); + + // Every output element is assigned below, so the size is all that has to be + // established; a resize of an already correctly sized buffer touches nothing. + output->resize(slots * channels_ * kQmfBands); + std::array even_spectrum{}; + std::array odd_spectrum{}; + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (std::size_t channel = 0u; channel < channels_; ++channel) { + const double* even_values = even_.data() + (slot * channels_ + channel) * kQmfBands; + const double* odd_values = odd_.data() + (slot * channels_ + channel) * kQmfBands; + transform(even_values, &even_spectrum); + transform(odd_values, &odd_spectrum); + Complex* destination = + output->data() + (slot * channels_ + channel) * kQmfBands; + for (int band = 0; band < kQmfBands; ++band) { + destination[band] = odd_spectrum[static_cast(band)] + + even_spectrum[static_cast(band)] * + even_post_[static_cast(band)]; + } + } + } + } + +private: + void transform(const double* values, std::array* spectrum) { + for (int band = 0; band < kQmfBands; ++band) { + (*spectrum)[static_cast(band)] = + Complex(values[band], 0.0) * premultiply_[static_cast(band)]; + } + for (int index = kQmfBands; index < dsp::kQmfFftSize; ++index) { + (*spectrum)[static_cast(index)] = Complex(0.0, 0.0); + } + dsp::fft_radix2(spectrum, qmf_fft_plan()); + for (int band = 0; band < kQmfBands; ++band) { + (*spectrum)[static_cast(band)] *= post_[static_cast(band)]; + } + } + + std::size_t channels_; + std::vector coefficients_; // [64][10] + std::vector coefficients_by_lag_; // [10][64], the same values transposed + std::vector history_; // [9][channels][64] + std::vector joined_; // scratch, [9 + slots][channels][64] + std::vector even_; // scratch, [slots][channels][64], zeroed per call + std::vector odd_; // scratch, [slots][channels][64], zeroed per call + std::vector premultiply_; + std::vector post_; + std::vector even_post_; +}; + +// Sparse 64-QMF to 77-hybrid analysis (public_filterbank.HybridAnalysis). +class HybridAnalysis { +public: + HybridAnalysis(const Kernels& kernels, std::size_t channels) + : channels_(channels), low_kernel_(kernels.hybrid_low) { + history_.assign(12u * channels_ * 3u * 2u, 0.0); + high_history_.assign(6u * channels_ * 61u, Complex(0.0, 0.0)); + // The dispatched join walks one term at a time and adds its 32 weights to + // 32 outputs, so the shipped [tap][band][component] table is regrouped to + // the term order the caller accumulates in. Same weights, same order. + const std::size_t outputs = simd::kHybridOutputs; + low_by_term_.resize(simd::kHybridTerms * outputs); + for (int lag = 0; lag < 13; ++lag) { + for (int point = 0; point < 3; ++point) { + for (int input = 0; input < 2; ++input) { + const std::size_t term = + (static_cast(lag) * 3u + static_cast(point)) * 2u + + static_cast(input); + const std::size_t source = (static_cast(point) * 2u + + static_cast(input)) * 13u + + static_cast(lag); + for (std::size_t output = 0u; output < outputs; ++output) { + low_by_term_[term * outputs + output] = + low_kernel_[source * outputs + output]; + } + } + } + } + low_values_.resize(simd::kHybridJoinBlock * simd::kHybridTerms); + low_out_.resize(simd::kHybridJoinBlock * outputs); + } + + void reset() { + std::fill(history_.begin(), history_.end(), 0.0); + std::fill(high_history_.begin(), high_history_.end(), Complex(0.0, 0.0)); + } + + // qmf: [slots, channels, 64]; output: [slots, channels, 77] complex. + void process(const std::vector& qmf, std::size_t slots, + std::vector* output) { + const std::size_t joined_slots = 12u + slots; + const std::size_t history_size = 12u * channels_ * 6u; + const std::size_t joined_size = joined_slots * channels_ * 3u * 2u; + // Both the joined window and the pending high-band history are written in full + // before they are read, so they are reused scratch buffers; the history tail is + // taken by index because the buffer can be longer than this call's window. + if (joined_.size() < joined_size) { + joined_.resize(joined_size); + } + std::copy(history_.begin(), history_.end(), joined_.begin()); + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (std::size_t channel = 0u; channel < channels_; ++channel) { + const Complex* source = qmf.data() + (slot * channels_ + channel) * kQmfBands; + double* destination = + joined_.data() + ((12u + slot) * channels_ + channel) * 6u; + for (int band = 0; band < 3; ++band) { + destination[static_cast(band) * 2u] = source[band].real(); + destination[static_cast(band) * 2u + 1u] = source[band].imag(); + } + } + } + // The low bands are accumulated in a register block and written straight into + // the output, and the high bands are written by the pass below; between them + // every one of the 77 bands is assigned, so only the size has to be set. + output->resize(slots * channels_ * kHybridBands); + // The thirteen taps are summed in a per-output register block and the low + // bands are written straight into the output. Keeping a separate low plane + // and then copying it into the output re-streams tens of megabytes per chunk + // for nothing, and only the first kHybridLow bands are ever touched. The + // join itself is dispatched (see src/simd/simd.h): the 32 outputs of a + // row are 32 independent accumulations over the same 78 terms, which is what + // shares a vector. Every lane keeps the caller's term order -- lag, then + // point, then input -- and its two roundings, and skips exactly the terms + // this loop skips. Rows are staged in blocks so the gathered values do not + // spill out of the first-level cache. + const std::size_t hybrid_rows = slots * channels_; + const std::size_t block = simd::kHybridJoinBlock; + const std::size_t terms = simd::kHybridTerms; + for (std::size_t first = 0u; first < hybrid_rows; first += block) { + const std::size_t count = std::min(block, hybrid_rows - first); + for (std::size_t index = 0u; index < count; ++index) { + const std::size_t row = first + index; + const std::size_t slot = row / channels_; + const std::size_t channel = row % channels_; + double* staged = low_values_.data() + index * terms; + for (int lag = 0; lag < 13; ++lag) { + const std::size_t source_slot = 12u - static_cast(lag) + slot; + const double* source = + joined_.data() + (source_slot * channels_ + channel) * 6u; + for (int point = 0; point < 3; ++point) { + for (int input = 0; input < 2; ++input) { + staged[(static_cast(lag) * 3u + + static_cast(point)) * 2u + + static_cast(input)] = + source[static_cast(point) * 2u + + static_cast(input)]; + } + } + } + } + simd::hybrid_low_join(low_values_.data(), low_by_term_.data(), + low_out_.data(), count); + for (std::size_t index = 0u; index < count; ++index) { + Complex* destination = output->data() + (first + index) * kHybridBands; + const double* values = low_out_.data() + index * simd::kHybridOutputs; + for (int band = 0; band < kHybridLow; ++band) { + destination[band] = Complex(values[static_cast(band) * 2u], + values[static_cast(band) * 2u + 1u]); + } + } + } + std::copy(joined_.begin() + static_cast(joined_size - history_size), + joined_.begin() + static_cast(joined_size), history_.begin()); + + // The high bands pass through unchanged but delayed by the six slots of + // history the reference concatenates in front of them. Only the last six + // entries of that concatenation survive into high_history_, so a six-entry + // register replaces the (6 + slots) plane and its full copy. Note the + // output reads the concatenation at index `slot`, not `6 + slot`, so the + // first six output slots come from the history: that offset is part of the + // current output and is preserved verbatim. + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (std::size_t channel = 0u; channel < channels_; ++channel) { + Complex* destination = output->data() + + (slot * channels_ + channel) * kHybridBands + kHybridLow; + if (slot < 6u) { + const Complex* source = + high_history_.data() + (slot * channels_ + channel) * 61u; + for (int band = 0; band < 61; ++band) { + destination[band] = source[band]; + } + } else { + const Complex* source = + qmf.data() + ((slot - 6u) * channels_ + channel) * kQmfBands; + for (int band = 3; band < kQmfBands; ++band) { + destination[static_cast(band - 3)] = source[band]; + } + } + } + } + // Every entry of the pending high-band history is written here, so it is a + // reusable scratch buffer; the copy into the live history is kept as it was. + if (next_high_history_.size() < 6u * channels_ * 61u) { + next_high_history_.resize(6u * channels_ * 61u); + } + for (std::size_t entry = 0u; entry < 6u; ++entry) { + const std::size_t combined = slots + entry; + for (std::size_t channel = 0u; channel < channels_; ++channel) { + Complex* destination = + next_high_history_.data() + (entry * channels_ + channel) * 61u; + if (combined < 6u) { + const Complex* source = + high_history_.data() + (combined * channels_ + channel) * 61u; + for (int band = 0; band < 61; ++band) { + destination[band] = source[band]; + } + } else { + const Complex* source = + qmf.data() + ((combined - 6u) * channels_ + channel) * kQmfBands; + for (int band = 3; band < kQmfBands; ++band) { + destination[static_cast(band - 3)] = source[band]; + } + } + } + } + std::copy(next_high_history_.begin(), next_high_history_.end(), high_history_.begin()); + } + +private: + std::size_t channels_; + std::vector low_kernel_; // [3][2][13][16][2] + std::vector low_by_term_; // [78][32], the same weights in the caller's term order + std::vector low_values_; // scratch, [block][78] + std::vector low_out_; // scratch, [block][32] + std::vector history_; // [12][channels][3][2] + std::vector high_history_; // [6][channels][61] + std::vector joined_; // scratch, [12 + slots][channels][3][2] + std::vector next_high_history_; // scratch, [6][channels][61] +}; + +// Instantaneous sparse 77-hybrid to 64-QMF synthesis map. +class HybridSynthesis { +public: + explicit HybridSynthesis(const Kernels& kernels) { + const std::size_t rows = kernels.hybrid_indices.size() / 4u; + mapping_.reserve(rows); + for (std::size_t index = 0u; index < rows; ++index) { + Entry entry; + for (int field = 0; field < 4; ++field) { + entry.index[static_cast(field)] = + kernels.hybrid_indices[index * 4u + static_cast(field)]; + } + entry.gain = kernels.hybrid_values[index]; + mapping_.push_back(entry); + } + } + + // hybrid: [slots, channels, 77]; output: [slots, channels, 64] complex. + // The sparse map moves a real or imaginary part of one band into a real or + // imaginary part of another, so the two components are accumulated apart. + void process(const std::vector& hybrid, std::size_t slots, std::size_t channels, + std::vector* output) const { + const std::size_t rows = slots * channels; + std::vector real(rows * kQmfBands, 0.0); + std::vector imaginary(rows * kQmfBands, 0.0); + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (std::size_t channel = 0u; channel < channels; ++channel) { + const std::size_t row = slot * channels + channel; + const Complex* source = hybrid.data() + row * kHybridBands; + for (const Entry& entry : mapping_) { + const double value = entry.index[1] == 0u ? source[entry.index[0]].real() + : source[entry.index[0]].imag(); + if (value == 0.0) { + continue; + } + double* destination = + (entry.index[3] == 0u ? real.data() : imaginary.data()) + row * kQmfBands; + destination[entry.index[2]] += value * entry.gain; + } + } + } + // Every output element is assigned from the two accumulators below, so the + // zero fill that `assign` performed was dead; only the size is needed. + output->resize(rows * kQmfBands); + for (std::size_t index = 0u; index < output->size(); ++index) { + (*output)[index] = Complex(real[index], imaginary[index]); + } + } + +private: + struct Entry { + std::size_t index[4] = {0u, 0u, 0u, 0u}; + double gain = 0.0; + }; + std::vector mapping_; +}; + +// Rank-4 64-band synthesis. +class QmfSynthesis { +public: + QmfSynthesis(const Kernels& kernels, std::size_t channels) + : channels_(channels), basis_(kernels.qmf_basis), taps_(kernels.qmf_taps) { + history_.assign(9u * channels_ * kQmfBands * kSynthesisRank, 0.0); + // The dispatched basis kernel reads the four ranks of one (band, tap) as + // one vector, so the shipped [band][rank][tap] table is reordered once + // here. The weights are the same doubles, only their order differs. + const std::size_t bands = static_cast(kQmfBands); + const std::size_t ranks = static_cast(kSynthesisRank); + const std::size_t taps = dsp::kQmfFftSize; + basis_by_tap_.resize(bands * taps * ranks); + for (std::size_t band = 0u; band < bands; ++band) { + for (std::size_t tap = 0u; tap < taps; ++tap) { + for (std::size_t rank = 0u; rank < ranks; ++rank) { + basis_by_tap_[(band * taps + tap) * ranks + rank] = + basis_[(band * ranks + rank) * taps + tap]; + } + } + } + } + + void reset() { std::fill(history_.begin(), history_.end(), 0.0); } + + // qmf: [slots, channels, 64]; output: [slots*64, channels] real. + void process(const std::vector& qmf, std::size_t slots, std::vector* output) { + const std::size_t rows = slots * channels_; + // [row][band][component] staging for the basis application. Both staging + // planes and the joined window are reusable scratch: every element of each is + // written before it is read, so the buffers are sized once and kept instead of + // being allocated and zero-filled on every call. + const std::size_t flat_size = rows * dsp::kQmfFftSize; + if (flat_.size() < flat_size) { + flat_.resize(flat_size); + } + for (std::size_t row = 0u; row < rows; ++row) { + for (int band = 0; band < kQmfBands; ++band) { + flat_[row * dsp::kQmfFftSize + static_cast(band) * 2u] = + qmf[row * kQmfBands + static_cast(band)].real(); + flat_[row * dsp::kQmfFftSize + static_cast(band) * 2u + 1u] = + qmf[row * kQmfBands + static_cast(band)].imag(); + } + } + // The sums are written straight into the joined window: the destination index + // is known up front, the summation order is untouched, and the application + // itself is dispatched -- the four ranks of a band are four independent dot + // products over the same 128 values, so they share a vector while every lane + // keeps the tap order and the two roundings of `sum +=`. + const std::size_t history_size = 9u * channels_ * kQmfBands * kSynthesisRank; + const std::size_t joined_size = history_size + rows * kQmfBands * kSynthesisRank; + if (joined_.size() < joined_size) { + joined_.resize(joined_size); + } + std::copy(history_.begin(), history_.end(), joined_.begin()); + simd::qmf_synthesis_basis(flat_.data(), basis_by_tap_.data(), + joined_.data() + history_size, rows); + std::copy(joined_.begin() + static_cast(joined_size - history_size), + joined_.begin() + static_cast(joined_size), history_.begin()); + + output->assign(rows * kQmfBands, 0.0); + for (int lag = 0; lag < kSynthesisTaps; ++lag) { + for (std::size_t slot = 0u; slot < slots; ++slot) { + const std::size_t source_slot = 9u - static_cast(lag) + slot; + for (std::size_t channel = 0u; channel < channels_; ++channel) { + const double* source = + joined_.data() + + (source_slot * channels_ + channel) * kQmfBands * kSynthesisRank; + double* destination = + output->data() + (slot * channels_ + channel) * kQmfBands; + for (int band = 0; band < kQmfBands; ++band) { + double sum = 0.0; + for (int rank = 0; rank < kSynthesisRank; ++rank) { + sum += source[static_cast(band) * kSynthesisRank + + static_cast(rank)] * + taps_[(static_cast(band) * kSynthesisTaps + + static_cast(lag)) * kSynthesisRank + + static_cast(rank)]; + } + destination[band] += sum; + } + } + } + } + } + +private: + std::size_t channels_; + std::vector basis_; // [64][4][128] + std::vector basis_by_tap_; // [64][128][4], the same weights transposed + std::vector taps_; // [64][10][4] + std::vector history_; // [9][channels][64][4] + std::vector flat_; // scratch, [rows][128], fully written per call + std::vector joined_; // scratch, [9 + slots][channels][64][4] +}; + +// public_filterbank.PublicAnalysis77.process: [N, channels] -> [N/64, channels, 77]. +void analysis_77(const std::vector& samples, std::size_t slots, + std::size_t channels, QmfAnalysis& qmf, + HybridAnalysis& hybrid_analysis, std::vector* hybrid) { + std::vector hops(slots * channels * kQmfHop, 0.0); + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (std::size_t channel = 0u; channel < channels; ++channel) { + for (int index = 0; index < kQmfHop; ++index) { + hops[(slot * channels + channel) * kQmfHop + static_cast(index)] = + samples[(slot * kQmfHop + static_cast(index)) * channels + channel]; + } + } + } + std::vector qmf_bands; + qmf.process(hops, slots, &qmf_bands); + hybrid_analysis.process(qmf_bands, slots, hybrid); +} + +// public_filterbank.PublicSynthesis77.process: [slots, channels, 77] -> [slots*64, channels]. +void synthesis_77(const std::vector& hybrid, std::size_t slots, + std::size_t channels, const HybridSynthesis& synthesis, + QmfSynthesis& qmf, std::vector* time) { + std::vector qmf_bands; + synthesis.process(hybrid, slots, channels, &qmf_bands); + std::vector samples; + qmf.process(qmf_bands, slots, &samples); + // The reference transposes (slots, channels, 64) to sample-major output. + time->assign(samples.size(), 0.0); + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (std::size_t channel = 0u; channel < channels; ++channel) { + for (int band = 0; band < kQmfBands; ++band) { + (*time)[(slot * kQmfHop + static_cast(band)) * channels + channel] = + samples[(slot * channels + channel) * kQmfBands + static_cast(band)]; + } + } + } +} + +} // namespace + +struct PublicFilterbank::Impl { + Impl(const Kernels& kernels, std::size_t channels) + : channels(channels), qmf(kernels, channels), hybrid_analysis(kernels, channels), + hybrid_synthesis(kernels), qmf_synthesis(kernels, channels) {} + + std::size_t channels; + QmfAnalysis qmf; + HybridAnalysis hybrid_analysis; + HybridSynthesis hybrid_synthesis; + QmfSynthesis qmf_synthesis; +}; + +PublicFilterbank::PublicFilterbank(const Kernels& kernels, std::size_t channels) + : impl_(std::make_unique(kernels, channels)) {} + +PublicFilterbank::~PublicFilterbank() = default; + +void PublicFilterbank::reset() { + impl_->qmf.reset(); + impl_->hybrid_analysis.reset(); + impl_->qmf_synthesis.reset(); +} + +void PublicFilterbank::analyze_full_rate(const std::vector& samples, std::size_t slots, + std::vector* hybrid) { + analysis_77(samples, slots, impl_->channels, impl_->qmf, impl_->hybrid_analysis, hybrid); +} + +void PublicFilterbank::synthesize_full_rate(const std::vector& hybrid, std::size_t slots, + std::vector* time) { + synthesis_77(hybrid, slots, impl_->channels, impl_->hybrid_synthesis, impl_->qmf_synthesis, + time); +} + +void PublicFilterbank::analyze_qmf(const std::vector& hops, std::size_t slots, + std::vector* qmf) { + impl_->qmf.process(hops, slots, qmf); +} + +void PublicFilterbank::analyze_hybrid(const std::vector& qmf, std::size_t slots, + std::vector* hybrid) { + impl_->hybrid_analysis.process(qmf, slots, hybrid); +} + +void PublicFilterbank::synthesize_hybrid(const std::vector& hybrid, std::size_t slots, + std::vector* qmf) { + impl_->hybrid_synthesis.process(hybrid, slots, impl_->channels, qmf); +} + +void PublicFilterbank::synthesize_qmf(const std::vector& qmf, std::size_t slots, + std::vector* time) { + impl_->qmf_synthesis.process(qmf, slots, time); +} + +} // namespace joc::hrtf + + diff --git a/src/hrtf/public_filterbank.h b/src/hrtf/public_filterbank.h new file mode 100644 index 0000000..4da85e9 --- /dev/null +++ b/src/hrtf/public_filterbank.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include +#include + +#include "hrtf/jochrtf.h" + +// Public 64-QMF / 77-hybrid filterbank, shared by the SOFA field compiler and the +// Rosella renderer (upstream public_filterbank.py and rosella_filterbank.py are +// the same bank). Everything is float64/complex128, as the reference computes it, +// and the stateful half-steps are exposed because Rosella drives them directly. +namespace joc::hrtf { + +inline constexpr int kQmfBands = 64; +inline constexpr int kQmfHop = 64; +inline constexpr int kHybridLow = 16; +inline constexpr int kHybridBandCount = 77; +inline constexpr int kLatencySamples = 961; + +using Complex = std::complex; + +class PublicFilterbank { +public: + PublicFilterbank(const Kernels& kernels, std::size_t channels); + ~PublicFilterbank(); + PublicFilterbank(const PublicFilterbank&) = delete; + PublicFilterbank& operator=(const PublicFilterbank&) = delete; + + void reset(); + + // Full-rate [slots*64, channels] -> hybrid [slots, channels, 77]. + void analyze_full_rate(const std::vector& samples, std::size_t slots, + std::vector* hybrid); + // Hybrid [slots, channels, 77] -> full-rate [slots*64, channels]. + void synthesize_full_rate(const std::vector& hybrid, std::size_t slots, + std::vector* time); + + // The stateful half-steps, in the order the reference runs them. + void analyze_qmf(const std::vector& hops, std::size_t slots, + std::vector* qmf); + void analyze_hybrid(const std::vector& qmf, std::size_t slots, + std::vector* hybrid); + void synthesize_hybrid(const std::vector& hybrid, std::size_t slots, + std::vector* qmf); + void synthesize_qmf(const std::vector& qmf, std::size_t slots, + std::vector* time); + +private: + struct Impl; + std::unique_ptr impl_; +}; + +} // namespace joc::hrtf diff --git a/src/hrtf/rosella_model.cpp b/src/hrtf/rosella_model.cpp new file mode 100644 index 0000000..35dce9f --- /dev/null +++ b/src/hrtf/rosella_model.cpp @@ -0,0 +1,535 @@ +#include "hrtf/rosella_model.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "foundation/fs_utf8.h" +#include "foundation/mini_json.h" +#include "foundation/sha256.h" + +namespace joc::hrtf { + +namespace { + +// The model's fixed-point lane scale: every stored value is a Q15 integer. +constexpr float kQ15 = 1.0f / 32768.0f; + +Status model_fail(joc_error code, const std::string& message) { + return Status::fail(code, stage::kRender, message); +} + +float q15(std::int32_t value) { return static_cast(value) * kQ15; } + +float q15_exp(std::int32_t value, int exponent) { + return q15(value) * static_cast(std::ldexp(1.0, exponent)); +} + +std::uint16_t low16(std::int32_t value) { + return static_cast(static_cast(value) & 0xFFFFu); +} + +std::string trim(const std::string& text) { + const std::size_t begin = text.find_first_not_of(" \t\r\n"); + const std::size_t end = text.find_last_not_of(" \t\r\n"); + return begin == std::string::npos ? std::string() : text.substr(begin, end - begin + 1u); +} + +// The lane array is read straight out of the JSON text: it is one flat list of +// integers, and building a 15691-node DOM for it would only cost time. +bool parse_int_array(const std::string& raw, std::vector* out, std::string* error) { + out->clear(); + const char* cursor = raw.c_str(); + const char* end = cursor + raw.size(); + while (cursor < end && *cursor != '[') { + ++cursor; + } + if (cursor == end) { + *error = "rosella_coefficients must be a JSON array"; + return false; + } + ++cursor; + while (cursor < end) { + while (cursor < end && (*cursor == ' ' || *cursor == '\t' || *cursor == '\r' || + *cursor == '\n' || *cursor == ',')) { + ++cursor; + } + if (cursor >= end) { + break; + } + if (*cursor == ']') { + return true; + } + const bool negative = *cursor == '-'; + if (negative) { + ++cursor; + } + if (cursor >= end || *cursor < '0' || *cursor > '9') { + *error = "rosella_coefficients contains a non-integer value"; + return false; + } + long long value = 0; + while (cursor < end && *cursor >= '0' && *cursor <= '9') { + value = value * 10 + (*cursor - '0'); + if (value > (1ll << 40)) { + *error = "rosella_coefficients value is out of range"; + return false; + } + ++cursor; + } + // A fractional part or an exponent means the value is not an exact integer. + if (cursor < end && (*cursor == '.' || *cursor == 'e' || *cursor == 'E')) { + *error = "rosella_coefficients contains a non-integer value"; + return false; + } + if (negative) { + value = -value; + } + if (value < -(1ll << 31) || value > (1ll << 31) - 1) { + *error = "rosella_coefficients value is outside signed int32"; + return false; + } + out->push_back(static_cast(value)); + } + *error = "rosella_coefficients array is truncated"; + return false; +} + +struct RpHeader { + std::uint16_t stored_checksum = 0; + std::uint16_t computed_checksum = 0; + bool checksum_valid = false; + bool table_a_present = false; + bool table_b_present = false; + bool table_c_present = false; + int table_a_dimension = 0; + int table_a_option = 0; + int table_a_extra = 0; + int table_b_dimension = 0; + int table_b_extra = 0; + int table_b_groups = 0; + int table_c_dimension = 0; + std::size_t active_lanes = 0; +}; + +Status inspect_rp(const std::vector& lanes, RpHeader* out) { + if (lanes.size() < 5u) { + return model_fail(JOC_ERR_HRTF_FORMAT, "Rosella rp must contain whole int32 lanes"); + } + if (low16(lanes[0]) != 0x7072u) { + return model_fail(JOC_ERR_HRTF_FORMAT, "bad Rosella rp magic"); + } + out->stored_checksum = low16(lanes[1]); + out->table_a_present = low16(lanes[2]) != 0u; + out->table_b_present = low16(lanes[3]) != 0u; + out->table_c_present = low16(lanes[4]) != 0u; + std::size_t index = 5u; + if (out->table_a_present) { + out->table_a_dimension = low16(lanes[index]); + out->table_a_option = low16(lanes[index + 1u]); + out->table_a_extra = low16(lanes[index + 2u]); + index += 5u; + } else { + out->table_a_dimension = 77; + } + if (out->table_b_present) { + if (!out->table_a_present) { + return model_fail(JOC_ERR_HRTF_FORMAT, + "Rosella rp table B cannot be present without table A"); + } + out->table_b_dimension = low16(lanes[index]); + out->table_b_extra = low16(lanes[index + 1u]); + out->table_b_groups = low16(lanes[index + 2u]); + index += 3u; + } + if (out->table_c_present) { + out->table_c_dimension = low16(lanes[index]); + index += 1u; + } + const long long payload_words = + static_cast(index) - 2 + + (out->table_b_present ? (out->table_b_dimension + 380 * out->table_b_groups + + out->table_b_extra + 79) + : 0) + + (out->table_a_present ? (171 * out->table_a_extra + 79 + + 2 * (out->table_a_option + 14 * out->table_a_dimension)) + : 0) + + 11 + (out->table_c_present ? (314 * out->table_c_dimension + 1) : 0); + if (payload_words < 0) { + return model_fail(JOC_ERR_HRTF_FORMAT, "malformed Rosella rp header"); + } + out->active_lanes = static_cast(2 + payload_words); + if (lanes.size() < out->active_lanes) { + return model_fail(JOC_ERR_HRTF_FORMAT, "Rosella rp is truncated"); + } + std::uint32_t computed = 0xA569u; + for (std::size_t lane = 2u; lane < out->active_lanes; ++lane) { + computed ^= low16(lanes[lane]); + } + out->computed_checksum = static_cast(computed & 0xFFFFu); + out->checksum_valid = out->computed_checksum == out->stored_checksum; + return Status::success(); +} + +// _unpack_field: the serialized 154-per-direction field lanes to the padded grid. +void unpack_field(const std::int32_t* serialized, int directions, int exponent, + std::vector* padded) { + padded->assign(static_cast(160 * directions), 0.0f); + const int stride8 = 8 * directions; + const int stride2 = 2 * directions; + for (int source = 0; source < 154 * directions; ++source) { + const int group4 = (source % stride8) / stride2; + const int destination = (group4 & 3) + 4 * (source % stride2 + + 2 * directions * (source / stride8 + + (group4 >> 2))); + (*padded)[static_cast(destination)] = + q15_exp(serialized[source], exponent); + } +} + +// _unpack_table_a_grid: the serialized table-A rows to the padded lane grid. +void unpack_table_a_grid(const std::int32_t* serialized, int dimension, int serialized_rows, + int padded_rows, int lane_group, std::vector* padded) { + padded->assign(static_cast(padded_rows) * static_cast(dimension), + 0.0f); + const int group_width = lane_group * 4; + for (int source = 0; source < serialized_rows * dimension; ++source) { + const int remainder = source % group_width; + const int destination = (remainder / lane_group) + + 4 * (remainder % lane_group + + group_width / 4 * (source / group_width)); + (*padded)[static_cast(destination)] = q15(serialized[source]); + } +} + +void unpack_table_a_extra(const std::int32_t* serialized, std::vector* padded) { + padded->assign(160u, 0.0f); + for (int source = 0; source < 154; ++source) { + const int remainder = source & 7; + const int destination = (remainder >> 1) + 4 * ((source & 1) + 2 * (source >> 3)); + (*padded)[static_cast(destination)] = q15(serialized[source]); + } +} + +} // namespace + +std::string RosellaModel::summary() const { + std::string name = capture.name.empty() ? std::string("unnamed") : capture.name; + return "Rosella personalized_headphone '" + name + "' (" + + (room_model.empty() ? std::string("unknown room") : room_model) + "), " + + std::to_string(table_a_dimension) + " HQMF / 77 hybrid @ " + + std::to_string(sample_rate) + " Hz"; +} + +Status load_personalized_headphone(const std::string& path, RosellaModel* out) { + if (out == nullptr) { + return model_fail(JOC_ERR_INVALID_ARGUMENT, "null Rosella model destination"); + } + if (!fs_utf8::exists(path)) { + return model_fail(JOC_ERR_HRTF_NOT_FOUND, "personalized headphone model not found: " + path); + } + std::ifstream stream = fs_utf8::open_input(path); + if (!stream.good()) { + return model_fail(JOC_ERR_IO, "cannot open " + path); + } + std::string text((std::istreambuf_iterator(stream)), std::istreambuf_iterator()); + if (text.empty()) { + return model_fail(JOC_ERR_HRTF_FORMAT, "empty personalized headphone model: " + path); + } + // The checksum is taken over the coefficient lanes, exactly as upstream hashes + // the int32 image of the array. + const std::size_t first = text.find_first_not_of(" \t\r\n"); + if (first == std::string::npos || text[first] != '{') { + return model_fail(JOC_ERR_NOT_SUPPORTED, + "raw rp models are not supported; use a .personalized_headphone JSON"); + } + std::vector root; + std::string error; + if (!json::parse_object(text, &root, &error)) { + return model_fail(JOC_ERR_HRTF_FORMAT, "invalid personalized headphone JSON: " + error); + } + const json::Member* personalized = json::find(root, "personalized_hrtf"); + if (personalized == nullptr) { + return model_fail(JOC_ERR_HRTF_FORMAT, "personalized_hrtf is missing"); + } + std::vector inner; + if (!json::parse_object(personalized->raw, &inner, &error)) { + return model_fail(JOC_ERR_HRTF_FORMAT, "invalid personalized_hrtf object: " + error); + } + const json::Member* virtualizer = json::find(inner, "virtualizer_parameters"); + if (virtualizer == nullptr) { + return model_fail(JOC_ERR_HRTF_FORMAT, "virtualizer_parameters is missing"); + } + std::vector parameters; + if (!json::parse_object(virtualizer->raw, ¶meters, &error)) { + return model_fail(JOC_ERR_HRTF_FORMAT, "invalid virtualizer_parameters: " + error); + } + const json::Member* coefficient_member = json::find(parameters, "rosella_coefficients"); + if (coefficient_member == nullptr) { + return model_fail(JOC_ERR_HRTF_FORMAT, "rosella_coefficients is missing"); + } + RosellaModel model; + model.source_path = path; + if (const json::Member* member = json::find(parameters, "rosella_coefficients_version")) { + json::as_string(*member, &model.coefficient_version); + } + if (const json::Member* member = json::find(parameters, "room_model")) { + json::as_string(*member, &model.room_model); + } + if (const json::Member* capture = json::find(inner, "phrtf_capture_metadata")) { + std::vector fields; + if (json::parse_object(capture->raw, &fields, &error)) { + const std::pair mapping[] = { + {"capture_submission_date", &model.capture.capture_submission_date}, + {"capture_type", &model.capture.capture_type}, + {"label", &model.capture.label}, + {"name", &model.capture.name}, + {"phrtf_algorithm_version", &model.capture.algorithm_version}, + {"phrtf_creation_date", &model.capture.creation_date}, + {"uuid", &model.capture.uuid}, + {"version", &model.capture.version}, + }; + for (const auto& entry : mapping) { + if (const json::Member* member = json::find(fields, entry.first)) { + json::as_string(*member, entry.second); + } + } + } + } + std::vector lanes; + if (!parse_int_array(coefficient_member->raw, &lanes, &error)) { + return model_fail(JOC_ERR_HRTF_FORMAT, error); + } + { + crypto::Sha256 hash; + hash.update(lanes.data(), lanes.size() * sizeof(std::int32_t)); + model.coefficient_sha256 = hash.finish_hex(); + } + + RpHeader header; + Status status = inspect_rp(lanes, &header); + if (!status.ok()) { + return status; + } + if (!header.checksum_valid || header.active_lanes != lanes.size()) { + return model_fail(JOC_ERR_HRTF_FORMAT, + "invalid or non-active Rosella rp coefficient sequence"); + } + if (!header.table_a_present || !header.table_b_present || header.table_c_present) { + return model_fail(JOC_ERR_NOT_SUPPORTED, + "the renderer requires table A+B and no table C"); + } + if (header.table_a_dimension != 64 || header.table_a_option != 3) { + return model_fail(JOC_ERR_NOT_SUPPORTED, + "the renderer requires the observed 64-channel HQMF layout"); + } + if (header.table_b_dimension != 20 || header.table_b_groups != 36) { + return model_fail(JOC_ERR_NOT_SUPPORTED, + "the renderer requires 20 hybrid groups and 36 direction terms"); + } + + const std::int32_t* values = lanes.data(); + const std::size_t total = lanes.size(); + std::size_t position = 13u; + const int extra = header.table_a_extra; + model.table_a_dimension = header.table_a_dimension; + model.table_a_option = header.table_a_option; + model.table_a_extra = extra; + model.table_a_header_field = low16(values[8]); + model.table_a_header_25 = low16(values[9]); + model.table_a_control = low16(values[position]); + model.field_exponent = values[position]; + position += 1u; + const int option_count = header.table_a_option; + model.table_a_option_ids.resize(static_cast(option_count)); + for (int index = 0; index < option_count; ++index) { + model.table_a_option_ids[static_cast(index)] = + low16(values[position + static_cast(index)]); + } + position += static_cast(option_count); + model.table_a_option_values.resize(static_cast(option_count)); + for (int index = 0; index < option_count; ++index) { + model.table_a_option_values[static_cast(index)] = + q15(values[position + static_cast(index)]); + } + position += static_cast(option_count); + model.table_a_scalar = q15(values[position]); + position += 1u; + const int dimension = header.table_a_dimension; + unpack_table_a_grid(values + position, dimension, 16, 20, 16, + &model.table_a_filter_16x64_padded); + position += static_cast(16 * dimension); + for (int index = 0; index < 4; ++index) { + model.table_a_four_integers[static_cast(index)] = + low16(values[position + static_cast(index)]); + } + position += 4u; + model.table_a_integer = low16(values[position]); + position += 1u; + unpack_table_a_grid(values + position, dimension, 8, 10, 8, + &model.table_a_filter_8x64_padded); + position += static_cast(8 * dimension); + model.table_a_vector16.resize(16u); + for (int index = 0; index < 16; ++index) { + model.table_a_vector16[static_cast(index)] = + q15(values[position + static_cast(index)]); + } + position += 16u; + unpack_table_a_grid(values + position, dimension, 4, 5, 4, + &model.table_a_filter_4x64_padded); + position += static_cast(4 * dimension); + model.table_a_extra_indices.resize(static_cast(extra)); + for (int index = 0; index < extra; ++index) { + model.table_a_extra_indices[static_cast(index)] = + low16(values[position + static_cast(index)]); + } + position += static_cast(extra); + model.table_a_extra_fields_padded.assign(static_cast(extra) * 160u, 0.0f); + std::vector unpacked; + for (int index = 0; index < extra; ++index) { + unpack_table_a_extra(values + position, &unpacked); + std::copy(unpacked.begin(), unpacked.end(), + model.table_a_extra_fields_padded.begin() + static_cast(index) * 160); + position += 154u; + } + model.table_a_extra_vectors.assign(static_cast(extra) * 16u, 0.0f); + for (int index = 0; index < extra; ++index) { + for (int lane = 0; lane < 16; ++lane) { + model.table_a_extra_vectors[static_cast(index) * 16u + + static_cast(lane)] = + q15(values[position + static_cast(lane)]); + } + position += 16u; + } + const std::size_t table_b_start = position; + if (table_b_start != 13u + 1821u + static_cast(171 * extra)) { + return model_fail(JOC_ERR_HRTF_FORMAT, "Rosella table-A parser lost its place"); + } + + model.sample_rate = 2 * low16(values[position]); + position += 1u; + model.matrix_exponent = values[position]; + position += 1u; + const std::size_t matrix_count = 36u * 36u; + model.matrix_left.resize(matrix_count); + model.matrix_right.resize(matrix_count); + for (std::size_t index = 0; index < matrix_count; ++index) { + model.matrix_left[index] = q15_exp(values[position + index], model.matrix_exponent); + } + position += matrix_count; + for (std::size_t index = 0; index < matrix_count; ++index) { + model.matrix_right[index] = q15_exp(values[position + index], model.matrix_exponent); + } + position += matrix_count; + model.vector_left.resize(36u); + model.vector_right.resize(36u); + for (int index = 0; index < 36; ++index) { + model.vector_left[static_cast(index)] = + q15_exp(values[position + static_cast(index)], model.matrix_exponent); + } + position += 36u; + for (int index = 0; index < 36; ++index) { + model.vector_right[static_cast(index)] = + q15_exp(values[position + static_cast(index)], model.matrix_exponent); + } + position += 36u; + + const std::size_t serialized_count = 154u * 36u; + unpack_field(values + position, 36, model.field_exponent, &model.field_left_padded); + bool odd_zero = true; + for (std::size_t index = 1u; index < serialized_count; index += 2u) { + const float value = q15_exp(values[position + index], model.field_exponent); + if (std::abs(value) > 1.0e-6f) { + odd_zero = false; + break; + } + } + model.field_left_odd_serialized_zero = odd_zero; + position += serialized_count; + unpack_field(values + position, 36, model.field_exponent, &model.field_right_padded); + position += serialized_count; + + model.hybrid_flags.resize(20u); + int active_hybrid = 0; + for (int index = 0; index < 20; ++index) { + model.hybrid_flags[static_cast(index)] = + low16(values[position + static_cast(index)]); + if (model.hybrid_flags[static_cast(index)] == 1) { + ++active_hybrid; + } + } + position += 20u; + if (active_hybrid != header.table_b_extra) { + return model_fail(JOC_ERR_HRTF_FORMAT, "hybrid value count does not match the header"); + } + model.hybrid_values.resize(static_cast(active_hybrid)); + for (int index = 0; index < active_hybrid; ++index) { + model.hybrid_values[static_cast(index)] = + q15(values[position + static_cast(index)]); + } + position += static_cast(active_hybrid); + model.model_scalars.resize(5u); + for (int index = 0; index < 5; ++index) { + model.model_scalars[static_cast(index)] = + q15(values[position + static_cast(index)]); + } + position += 5u; + const std::size_t expected_tail = + table_b_start + static_cast(header.table_b_dimension + + 380 * header.table_b_groups + + header.table_b_extra + 79); + if (position != expected_tail) { + return model_fail(JOC_ERR_HRTF_FORMAT, "Rosella table-B parser lost its place"); + } + + model.header_float_scalars[0] = q15(values[position]); + model.header_float_scalars[1] = q15(values[position + 1u]) * 16.0f; + model.header_integer_fields[0] = values[position + 2u]; + model.header_integer_fields[1] = low16(values[position + 3u]); + position += 4u; + for (int profile = 0; profile < 4; ++profile) { + RosellaDistanceProfile parsed; + for (int index = 0; index < 6; ++index) { + parsed.bounds[static_cast(index)] = + q15(values[position + static_cast(index)]); + } + position += 6u; + parsed.distance_scale_m = + q15_exp(values[position], values[position + 1u]); + position += 2u; + parsed.inverse_distance_per_m = q15(values[position]); + parsed.axis_scales_internal[0] = q15(values[position + 1u]); + parsed.axis_scales_internal[1] = q15(values[position + 2u]); + parsed.axis_scales_internal[2] = q15(values[position + 3u]); + parsed.minimum_normalized_radius = q15(values[position + 4u]); + position += 5u; + model.profiles[static_cast(profile)] = parsed; + } + model.profile_tail.resize(8u); + for (int index = 0; index < 8; ++index) { + model.profile_tail[static_cast(index)] = + q15(values[position + static_cast(index)]); + } + position += 8u; + for (int index = 0; index < 3; ++index) { + model.post_fields[static_cast(index)] = + values[position + static_cast(index)]; + } + position += 3u; + if (position != total) { + return model_fail(JOC_ERR_HRTF_FORMAT, "unparsed Rosella coefficient lanes"); + } + if (model.sample_rate != 48000) { + return model_fail(JOC_ERR_HRTF_FORMAT, + "Rosella model sample rate must be 48000, got " + + std::to_string(model.sample_rate)); + } + *out = std::move(model); + return Status::success(); +} + +} // namespace joc::hrtf diff --git a/src/hrtf/rosella_model.h b/src/hrtf/rosella_model.h new file mode 100644 index 0000000..9df1369 --- /dev/null +++ b/src/hrtf/rosella_model.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include +#include +#include + +#include "foundation/status.h" + +// Parser for the Dolby ".personalized_headphone" model (upstream rosella_model.py). +// The file is JSON whose virtualizer_parameters carry the raw "rp" coefficient +// lanes; everything the renderer needs is unpacked here, in the same float32 +// arithmetic the reference uses, because those values are part of the model. +namespace joc::hrtf { + +struct RosellaDistanceProfile { + std::array bounds{}; + float distance_scale_m = 0.0f; + float inverse_distance_per_m = 0.0f; + std::array axis_scales_internal{}; + float minimum_normalized_radius = 0.0f; +}; + +struct RosellaCaptureMetadata { + std::string capture_submission_date; + std::string capture_type; + std::string label; + std::string name; + std::string algorithm_version; + std::string creation_date; + std::string uuid; + std::string version; +}; + +struct RosellaModel { + std::string source_path; + std::string coefficient_sha256; + std::string coefficient_version; + std::string room_model; + RosellaCaptureMetadata capture; + + int table_a_dimension = 0; + int table_a_option = 0; + int table_a_extra = 0; + int table_a_header_field = 0; + int table_a_header_25 = 0; + int table_a_control = 0; + std::vector table_a_option_ids; + std::vector table_a_option_values; + float table_a_scalar = 0.0f; + std::vector table_a_filter_16x64_padded; + std::array table_a_four_integers{}; + int table_a_integer = 0; + std::vector table_a_filter_8x64_padded; + std::vector table_a_vector16; + std::vector table_a_filter_4x64_padded; + std::vector table_a_extra_indices; + std::vector table_a_extra_fields_padded; + std::vector table_a_extra_vectors; + + int sample_rate = 0; + int matrix_exponent = 0; + int field_exponent = 0; + std::vector matrix_left; + std::vector matrix_right; + std::vector vector_left; + std::vector vector_right; + std::vector field_left_padded; + std::vector field_right_padded; + bool field_left_odd_serialized_zero = false; + std::vector hybrid_flags; + std::vector hybrid_values; + std::vector model_scalars; + std::array header_float_scalars{}; + std::array header_integer_fields{}; + std::array profiles{}; + std::vector profile_tail; + std::array post_fields{}; + + // One line for reports and logs: the capture name and room model are the + // model's own strings, followed by the table layout and sample rate, e.g. + // "Rosella personalized_headphone '' (), HQMF / 77 hybrid @ Hz". + std::string summary() const; +}; + +Status load_personalized_headphone(const std::string& path, RosellaModel* out); + +} // namespace joc::hrtf diff --git a/src/hrtf/rosella_renderer.cpp b/src/hrtf/rosella_renderer.cpp new file mode 100644 index 0000000..8a08839 --- /dev/null +++ b/src/hrtf/rosella_renderer.cpp @@ -0,0 +1,1358 @@ +#include "hrtf/rosella_renderer.h" + +#include "simd/simd.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "foundation/fft.h" +#include "hrtf/public_filterbank.h" + +namespace joc::hrtf { + +namespace { + +constexpr int kSourceChannels = 16; +constexpr int kOutputChannels = 2; +constexpr int kDirectionTerms = 36; +constexpr int kBlockSamples = 512; +constexpr int kFrameSamples = 1536; +constexpr int kRoomBands = 64; +constexpr double kPi = 3.14159265358979323846; +constexpr double kRoomInputGain = 0.70710677; +constexpr double kCentreEqual = 0.9998489618301392; +constexpr double kCentreAlternate = 0.7070000171661377; + +// The fixed sixteen-band low-pass a special (LFE) source is rendered through; the +// constants are the float32 bit patterns of rosella_direct._SPECIAL_LFE_LOW_16. +constexpr std::uint32_t kSpecialLfeLowBits[16] = { + 0x402695EAu, 0x3FE75979u, 0x3F28CAAAu, 0xBCE1FB2Eu, 0xBDD8AF65u, 0xBD8F426Eu, + 0x3D996821u, 0xBC16B3A0u, 0x3B64BAF1u, 0xBC81ECFDu, 0xBA3D892Fu, 0x3AF6A9F0u, + 0xB9DD1C5Fu, 0x380A193Fu, 0x38052059u, 0x351BCB34u}; + +Status render_fail(joc_error code, const std::string& message) { + return Status::fail(code, stage::kRender, message); +} + +std::vector special_lfe_low() { + std::vector values(kHybridBands, 0.0); + for (int index = 0; index < 16; ++index) { + float narrowed = 0.0f; + const std::uint32_t bits = kSpecialLfeLowBits[index]; + std::memcpy(&narrowed, &bits, sizeof(float)); + values[static_cast(index)] = static_cast(narrowed); + } + return values; +} + +// rosella_model.direction_basis: the observed 36-term basis. The operation order is +// part of the model, so the intermediates are named after the reference's. +void direction_basis(double x, double y, double z, double* out) { + const double yz = y * z; + const double x2 = x * x; + const double y2 = y * y; + const double x2m02 = x2 - 0.2; + const double xy = x * y; + out[0] = 1.0; + out[1] = x; + out[2] = y; + out[3] = z; + out[4] = x2 - (1.0 / 3.0); + out[5] = xy; + out[6] = x * z; + out[7] = y2 - (1.0 / 3.0); + out[8] = yz; + out[9] = (x2 - 0.6) * x; + out[10] = x2m02 * y; + out[11] = x2m02 * z; + out[12] = (y2 - 0.2) * x; + out[13] = yz * x; + out[14] = (y2 - 0.6) * y; + out[15] = (y2 - 0.2) * z; + out[16] = x2 * x2 - 0.2; + out[17] = xy * x2; + out[18] = (x * z) * x2; + out[19] = y2 * x2 - (1.0 / 15.0); + out[20] = yz * x2; + out[21] = x * y2 * y; + out[22] = x * y2 * z; + out[23] = y2 * y2 - 0.2; + const double x4 = x2 * x2; + const double x2y2 = y2 * x2; + const double y4 = y2 * y2; + out[24] = yz * y2; + out[25] = (x4 - (3.0 / 7.0)) * x; + out[26] = (x4 - (3.0 / 35.0)) * y; + out[27] = (x4 - (3.0 / 35.0)) * z; + out[28] = (x2y2 - (3.0 / 35.0)) * x; + out[29] = (x2 * z) * xy; + out[30] = (x2y2 - (3.0 / 35.0)) * y; + out[31] = (x2y2 - (1.0 / 35.0)) * z; + out[32] = (y4 - (3.0 / 35.0)) * x; + out[33] = (y2 * z) * xy; + out[34] = (y4 - (3.0 / 7.0)) * y; + out[35] = (y4 - (3.0 / 35.0)) * z; +} + +// rosella_direct._logical_field: the padded lane grid as [77][36][2] float64. +void logical_field(const std::vector& padded, std::vector* out) { + out->assign(static_cast(kHybridBands) * kDirectionTerms * 2u, 0.0); + for (int band = 0; band < kHybridBands; ++band) { + const int block = band / 4; + const int lane = band % 4; + for (int term = 0; term < kDirectionTerms; ++term) { + for (int component = 0; component < 2; ++component) { + const std::size_t source = + static_cast(lane + 4 * (term * 2 + component + 72 * block)); + (*out)[(static_cast(band) * kDirectionTerms + + static_cast(term)) * 2u + + static_cast(component)] = + source < padded.size() ? static_cast(padded[source]) : 0.0; + } + } + } +} + +// rosella_direct._round_away_from_zero. +double round_away_from_zero(double value) { + return value >= 0.0 ? std::floor(value + 0.5) : std::ceil(value - 0.5); +} + +// rosella_direct._q15_position: ADM coordinates on the Rosella metadata grid. +void q15_position(const double position[3], int encoded[3]) { + const double raw[3] = { + std::min(std::max((position[0] + 1.0) * 0.5, 0.0), 1.0), + std::min(std::max((1.0 - position[1]) * 0.5, 0.0), 1.0), + std::min(std::max(position[2], -1.0), 1.0), + }; + for (int axis = 0; axis < 3; ++axis) { + encoded[axis] = static_cast( + std::min(round_away_from_zero(raw[axis] * 32768.0), 32767.0)); + } +} + +struct ProfileGeometry { + double direction[3] = {1.0, 0.0, 0.0}; + double radius = 0.0; + double clamped = 0.0; + double alpha = 0.0; +}; + +// rosella_direct._profile_geometry. +ProfileGeometry profile_geometry(const RosellaModel& model, const double position[3], + int profile_index) { + const RosellaDistanceProfile& profile = model.profiles[static_cast(profile_index)]; + int encoded[3] = {0, 0, 0}; + q15_position(position, encoded); + const double q_front = 1.0 - 2.0 * static_cast(encoded[1]) / 32768.0; + const double q_x = 2.0 * static_cast(encoded[0]) / 32768.0 - 1.0; + const double q_vertical = static_cast(encoded[2]) / 32768.0; + double mapped_front = q_front; + double mapped_lateral = -q_x; + double mapped_vertical = q_vertical; + if (model.header_integer_fields[0] != 0) { + if (q_x == 0.0 && q_front == 0.0) { + mapped_front = 0.0; + mapped_lateral = 0.0; + mapped_vertical = q_vertical; + } else { + const double horizontal_max = std::max(std::abs(q_x), std::abs(q_front)); + const double horizontal_norm = (q_x / horizontal_max) * (q_x / horizontal_max) + + (q_front / horizontal_max) * (q_front / horizontal_max); + double vertical_norm = 1.0; + if (q_vertical != 0.0) { + const double smaller = std::min(std::abs(q_vertical), horizontal_max); + const double larger = std::max(std::abs(q_vertical), horizontal_max); + vertical_norm = 1.0 + (smaller / larger) * (smaller / larger); + } + const double horizontal_factor = 1.0 / std::sqrt(horizontal_norm * vertical_norm); + const double vertical_factor = 1.0 / std::sqrt(vertical_norm); + mapped_front = q_front * horizontal_factor; + mapped_lateral = -q_x * horizontal_factor; + mapped_vertical = q_vertical * vertical_factor; + } + } + double scaled[3] = {mapped_front * static_cast(profile.axis_scales_internal[2]), + mapped_lateral * static_cast(profile.axis_scales_internal[0]), + mapped_vertical * static_cast(profile.axis_scales_internal[1])}; + double ray = 1.0; + for (int axis = 0; axis < 3; ++axis) { + const double value = scaled[axis]; + const double lower = static_cast(profile.bounds[static_cast(axis) * 2u]); + const double upper = + static_cast(profile.bounds[static_cast(axis) * 2u + 1u]); + if (value < lower) { + ray = std::min(ray, lower / value); + } else if (value > upper) { + ray = std::min(ray, upper / value); + } + } + if (ray < 1.0) { + scaled[0] *= ray; + scaled[1] *= ray; + scaled[2] *= ray; + } + ProfileGeometry result; + result.radius = std::sqrt(scaled[0] * scaled[0] + scaled[1] * scaled[1] + + scaled[2] * scaled[2]); + result.clamped = std::max(result.radius, static_cast(profile.minimum_normalized_radius)); + result.alpha = result.radius / result.clamped; + if (result.radius > 1.0e-30) { + for (int axis = 0; axis < 3; ++axis) { + result.direction[axis] = scaled[axis] / result.radius; + } + } + return result; +} + +struct EarGeometry { + double basis_minus[kDirectionTerms] = {}; + double basis_plus[kDirectionTerms] = {}; + double path_minus = 0.0; + double path_plus = 0.0; +}; + +// rosella_direct._ear_geometry. +EarGeometry ear_geometry(const RosellaModel& model, const RosellaDistanceProfile& profile, + const double direction[3], double clamped, double offset, + double correction) { + const double x = direction[0]; + const double y = direction[1]; + const double z = direction[2]; + const double inverse_distance = static_cast(profile.inverse_distance_per_m); + const double ear = offset * inverse_distance / clamped; + const double y_minus = y - ear; + const double y_plus = y + ear; + const double common = x * x + z * z; + const double length_minus = std::sqrt(y_minus * y_minus + common); + const double length_plus = std::sqrt(y_plus * y_plus + common); + EarGeometry result; + direction_basis(x / length_minus, y_minus / length_minus, z / length_minus, + result.basis_minus); + direction_basis(x / length_plus, y_plus / length_plus, z / length_plus, result.basis_plus); + result.path_minus = length_minus * clamped; + result.path_plus = length_plus * clamped; + if (correction != 0.0) { + const double multiplier = 2.0 * correction * inverse_distance; + double left = 0.0; + double right = 0.0; + for (int term = 0; term < kDirectionTerms; ++term) { + left += static_cast(model.vector_left[static_cast(term)]) * + result.basis_minus[term]; + right += static_cast(model.vector_right[static_cast(term)]) * + result.basis_plus[term]; + } + result.path_minus += std::max(left, 0.0) * multiplier; + result.path_plus += std::max(right, 0.0) * multiplier; + } + return result; +} + +// rosella_direct._phase_groups. +void phase_groups(const RosellaModel& model, double delay_samples, Complex* out) { + // The reference starts from np.ones(77) and only rewrites the flagged bands. + std::fill(out, out + kHybridBands, Complex(1.0, 0.0)); + Complex current(1.0, 0.0); + Complex step(1.0, 0.0); + std::size_t value_index = 0u; + for (std::size_t band = 0u; band < model.hybrid_flags.size() && band < kHybridBands; ++band) { + const int flag = model.hybrid_flags[band]; + if (flag != 2) { + if (flag == 1) { + const double angle = + static_cast(model.hybrid_values[value_index]) * delay_samples; + ++value_index; + step = Complex(std::cos(angle), std::sin(angle)); + } + current *= step; + } + out[band] = current; + } +} + +struct DirectResult { + Complex gains[2][kHybridBands] = {}; + double room_send = 0.0; + double physical_radius_m = 0.0; + double normalized_radius = 0.0; + double clamped_radius = 0.0; + double delay_samples = 0.0; + int delayed_ear = -1; +}; + +// rosella_direct.special_lfe_direct. +const DirectResult& special_lfe_direct() { + static const DirectResult result = [] { + DirectResult direct; + const std::vector low = special_lfe_low(); + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kHybridBands; ++band) { + direct.gains[ear][band] = Complex(low[static_cast(band)], 0.0); + } + } + return direct; + }(); + return result; +} + +// rosella_direct.direct_and_room_send. +DirectResult direct_and_room_send(const RosellaModel& model, + const std::vector& field_left, + const std::vector& field_right, const double position[3], + int profile_index) { + const RosellaDistanceProfile& profile = + model.profiles[static_cast(profile_index)]; + const ProfileGeometry geometry = profile_geometry(model, position, profile_index); + + const EarGeometry delay_ears = + ear_geometry(model, profile, geometry.direction, geometry.clamped, + static_cast(model.model_scalars[1]), + static_cast(model.model_scalars[2])); + const double delay = std::abs(delay_ears.path_plus - delay_ears.path_minus) * + static_cast(profile.distance_scale_m) * + (static_cast(model.sample_rate) / 343.3) * geometry.alpha; + int delayed_ear = -1; + if (delay_ears.path_minus > delay_ears.path_plus) { + delayed_ear = 0; + } else if (delay_ears.path_plus > delay_ears.path_minus) { + delayed_ear = 1; + } + + const EarGeometry weight_ears = + ear_geometry(model, profile, geometry.direction, geometry.clamped, + static_cast(model.model_scalars[3]), + static_cast(model.model_scalars[4])); + const double weight_norm = + std::sqrt(weight_ears.path_minus * weight_ears.path_minus + + weight_ears.path_plus * weight_ears.path_plus); + const double weight_left = weight_ears.path_plus / weight_norm; + const double weight_right = weight_ears.path_minus / weight_norm; + + const double final_offset = static_cast(model.model_scalars[0]); + double basis_minus[kDirectionTerms] = {}; + double basis_plus[kDirectionTerms] = {}; + if (final_offset == 0.0) { + direction_basis(geometry.direction[0], geometry.direction[1], geometry.direction[2], + basis_minus); + std::copy(basis_minus, basis_minus + kDirectionTerms, basis_plus); + } else { + const double x = geometry.direction[0]; + const double y = geometry.direction[1]; + const double z = geometry.direction[2]; + const double ear = + final_offset * static_cast(profile.inverse_distance_per_m) / geometry.clamped; + const double y_minus = y - ear; + const double y_plus = y + ear; + const double common_length = x * x + z * z; + const double length_minus = std::sqrt(y_minus * y_minus + common_length); + const double length_plus = std::sqrt(y_plus * y_plus + common_length); + direction_basis(x / length_minus, y_minus / length_minus, z / length_minus, basis_minus); + direction_basis(x / length_plus, y_plus / length_plus, z / length_plus, basis_plus); + } + + DirectResult result; + Complex left[kHybridBands] = {}; + Complex right[kHybridBands] = {}; + for (int band = 0; band < kHybridBands; ++band) { + double left_real = 0.0; + double left_imag = 0.0; + double right_real = 0.0; + double right_imag = 0.0; + for (int term = 0; term < kDirectionTerms; ++term) { + const std::size_t index = + (static_cast(band) * kDirectionTerms + static_cast(term)) * + 2u; + left_real += field_left[index] * basis_minus[term]; + left_imag += field_left[index + 1u] * basis_minus[term]; + right_real += field_right[index] * basis_plus[term]; + right_imag += field_right[index + 1u] * basis_plus[term]; + } + left[band] = Complex(left_real, left_imag); + right[band] = Complex(right_real, right_imag); + } + if (delayed_ear >= 0) { + Complex phase[kHybridBands]; + phase_groups(model, delay, phase); + Complex* target = delayed_ear == 0 ? left : right; + for (int band = 0; band < kHybridBands; ++band) { + target[band] *= phase[band]; + } + } + + const double effective_radius = + geometry.radius * static_cast(model.header_float_scalars[0]) * + static_cast(profile.distance_scale_m); + double common = 1.0; + double room_send = 0.0; + if (profile_index == static_cast(RosellaProfile::Far) || + profile_index == static_cast(RosellaProfile::Mid)) { + common = 1.0 / std::sqrt(1.0 + static_cast(model.header_float_scalars[1]) * + effective_radius * effective_radius); + room_send = effective_radius * common; + } + + Complex left_term0[kHybridBands]; + Complex right_term0[kHybridBands]; + for (int band = 0; band < kHybridBands; ++band) { + const std::size_t index = static_cast(band) * kDirectionTerms * 2u; + left_term0[band] = Complex(field_left[index], field_left[index + 1u]); + right_term0[band] = Complex(field_right[index], field_right[index + 1u]); + } + const bool weights_are_default_equal = + static_cast(model.model_scalars[3]) == 0.0 && + static_cast(model.model_scalars[4]) == 0.0; + double centre_left = 0.0; + double centre_right = 0.0; + double right_direction_weight = weight_right; + if (weights_are_default_equal) { + centre_left = weight_left * (1.0 - geometry.alpha) * kCentreEqual; + centre_right = centre_left; + right_direction_weight = weight_left; + } else { + centre_left = (1.0 - geometry.alpha) * kCentreAlternate; + centre_right = centre_left; + } + for (int band = 0; band < kHybridBands; ++band) { + result.gains[0][band] = + common * (left[band] * (weight_left * geometry.alpha) + left_term0[band] * centre_left); + result.gains[1][band] = common * (right[band] * (right_direction_weight * geometry.alpha) + + right_term0[band] * centre_right); + } + result.room_send = room_send; + result.physical_radius_m = static_cast(profile.distance_scale_m) * geometry.radius; + result.normalized_radius = geometry.radius; + result.clamped_radius = geometry.clamped; + result.delay_samples = delay; + result.delayed_ear = delayed_ear; + return result; +} + +// rosella_room._RosellaRoomState: the recursive table-A room model. +class RoomState { +public: + explicit RoomState(const RosellaModel& model) : model_(model) { + bands_ = std::min(64, model.table_a_dimension); + delays_ = model.table_a_four_integers; + capacity_ = 0; + for (const int delay : delays_) { + capacity_ = std::max(capacity_, delay); + } + // The vectors are stored column-major (numpy's order="F"). + matrix_.assign(16u, 0.0); + for (int row = 0; row < 4; ++row) { + for (int column = 0; column < 4; ++column) { + matrix_[static_cast(row) + 4u * static_cast(column)] = + static_cast(model.table_a_vector16[static_cast(row) + + 4u * static_cast(column)]); + } + } + const std::vector& f8 = model.table_a_filter_8x64_padded; + const std::vector& f4 = model.table_a_filter_4x64_padded; + const std::vector& f16 = model.table_a_filter_16x64_padded; + feedback_real_.assign(static_cast(bands_) * 4u, 0.0); + feedback_imag_.assign(static_cast(bands_) * 4u, 0.0); + output_tap_.assign(static_cast(bands_) * 4u, 0.0); + left_real_.assign(static_cast(bands_) * 4u, 0.0); + left_imag_.assign(static_cast(bands_) * 4u, 0.0); + right_real_.assign(static_cast(bands_) * 4u, 0.0); + right_imag_.assign(static_cast(bands_) * 4u, 0.0); + for (int band = 0; band < bands_; ++band) { + const int group = band / 4; + const int lane = band % 4; + for (int tap = 0; tap < 4; ++tap) { + const std::size_t target = static_cast(band) * 4u + + static_cast(tap); + const std::size_t g8 = ((static_cast(group) * 4u + + static_cast(tap)) * 2u) * + 4u + + static_cast(lane); + feedback_real_[target] = static_cast(f8[g8]); + feedback_imag_[target] = static_cast(f8[g8 + 4u]); + output_tap_[target] = static_cast( + f4[(static_cast(group) * 4u + static_cast(tap)) * 4u + + static_cast(lane)]); + const std::size_t g16 = ((static_cast(group) * 4u + + static_cast(tap)) * 4u) * + 4u; + left_real_[target] = static_cast(f16[g16 + static_cast(lane)]); + left_imag_[target] = + static_cast(f16[g16 + 4u + static_cast(lane)]); + right_real_[target] = + static_cast(f16[g16 + 8u + static_cast(lane)]); + right_imag_[target] = + static_cast(f16[g16 + 12u + static_cast(lane)]); + } + } + allpass_gain_.resize(model.table_a_option_values.size()); + for (std::size_t index = 0u; index < model.table_a_option_values.size(); ++index) { + allpass_gain_[index] = static_cast(model.table_a_option_values[index]); + } + allpass_delay_ = model.table_a_option_ids; + for (const int delay : allpass_delay_) { + allpass_real_.emplace_back(static_cast(delay) * + static_cast(bands_), + 0.0); + allpass_imag_.emplace_back(static_cast(delay) * + static_cast(bands_), + 0.0); + } + allpass_position_.assign(allpass_real_.size(), 0); + memory_real_.assign(static_cast(capacity_) * static_cast(bands_) * 4u, + 0.0); + memory_imag_.assign(memory_real_.size(), 0.0); + extra_matrices_.resize(model.table_a_extra_indices.size()); + for (std::size_t index = 0u; index < extra_matrices_.size(); ++index) { + extra_matrices_[index].assign(16u, 0.0); + for (int row = 0; row < 4; ++row) { + for (int column = 0; column < 4; ++column) { + extra_matrices_[index][static_cast(row) + + 4u * static_cast(column)] = + static_cast( + model.table_a_extra_vectors[index * 16u + static_cast(row) + + 4u * static_cast(column)]); + } + } + } + } + + void reset() { + for (std::vector& value : allpass_real_) { + std::fill(value.begin(), value.end(), 0.0); + } + for (std::vector& value : allpass_imag_) { + std::fill(value.begin(), value.end(), 0.0); + } + std::fill(allpass_position_.begin(), allpass_position_.end(), 0); + std::fill(memory_real_.begin(), memory_real_.end(), 0.0); + std::fill(memory_imag_.begin(), memory_imag_.end(), 0.0); + position_ = 0; + } + + Status process_slot(const Complex* room_send, Complex* output) { + if (static_cast(model_.table_a_scalar) >= 0.5) { + return render_fail(JOC_ERR_NOT_SUPPORTED, "alternate Rosella table-A room mode"); + } + const std::size_t bands = static_cast(bands_); + std::vector input_real(bands, 0.0); + std::vector input_imag(bands, 0.0); + for (std::size_t band = 0u; band < bands; ++band) { + input_real[band] = room_send[band].real() * kRoomInputGain; + input_imag[band] = room_send[band].imag() * kRoomInputGain; + } + for (std::size_t index = 0u; index < allpass_gain_.size(); ++index) { + const std::size_t delay = static_cast(allpass_delay_[index]); + const std::size_t position = static_cast(allpass_position_[index]); + const double gain = allpass_gain_[index]; + for (std::size_t band = 0u; band < bands; ++band) { + const std::size_t cell = position * bands + band; + const double previous_real = allpass_real_[index][cell]; + const double previous_imag = allpass_imag_[index][cell]; + const double residual_real = input_real[band] - previous_real * gain; + const double residual_imag = input_imag[band] - previous_imag * gain; + input_real[band] = residual_real * gain + previous_real; + input_imag[band] = residual_imag * gain + previous_imag; + allpass_real_[index][cell] = residual_real; + allpass_imag_[index][cell] = residual_imag; + } + allpass_position_[index] = static_cast((position + 1u) % delay); + } + + std::vector branch_real(bands * 4u, 0.0); + std::vector branch_imag(bands * 4u, 0.0); + std::vector delayed_real(bands * 4u, 0.0); + std::vector delayed_imag(bands * 4u, 0.0); + for (int branch = 0; branch < 4; ++branch) { + const std::size_t slot = + static_cast((position_ - delays_[static_cast(branch)] + + capacity_) % + capacity_); + for (std::size_t band = 0u; band < bands; ++band) { + const std::size_t source = (slot * bands + band) * 4u + static_cast(branch); + delayed_real[band * 4u + static_cast(branch)] = memory_real_[source]; + delayed_imag[band * 4u + static_cast(branch)] = memory_imag_[source]; + } + } + for (std::size_t band = 0u; band < bands; ++band) { + for (int row = 0; row < 4; ++row) { + double real = input_real[band]; + double imag = input_imag[band]; + for (int column = 0; column < 4; ++column) { + const double coefficient = + matrix_[static_cast(row) + 4u * static_cast(column)]; + real += delayed_real[band * 4u + static_cast(column)] * coefficient; + imag += delayed_imag[band * 4u + static_cast(column)] * coefficient; + } + branch_real[band * 4u + static_cast(row)] = real; + branch_imag[band * 4u + static_cast(row)] = imag; + } + } + + const std::size_t tap_slot = static_cast( + (position_ - model_.table_a_integer + capacity_) % capacity_); + std::vector tap_real(bands * 4u, 0.0); + std::vector tap_imag(bands * 4u, 0.0); + for (std::size_t band = 0u; band < bands; ++band) { + for (int lane = 0; lane < 4; ++lane) { + const std::size_t source = (tap_slot * bands + band) * 4u + static_cast(lane); + tap_real[band * 4u + static_cast(lane)] = memory_real_[source]; + tap_imag[band * 4u + static_cast(lane)] = memory_imag_[source]; + } + } + for (std::size_t cell = 0u; cell < branch_real.size(); ++cell) { + const double real = branch_real[cell]; + const double imag = branch_imag[cell]; + memory_real_[(static_cast(position_) * bands) * 4u + cell] = + real * feedback_real_[cell] - imag * feedback_imag_[cell]; + memory_imag_[(static_cast(position_) * bands) * 4u + cell] = + imag * feedback_real_[cell] + real * feedback_imag_[cell]; + } + position_ = (position_ + 1) % capacity_; + + std::vector extra_real(bands * 4u, 0.0); + std::vector extra_imag(bands * 4u, 0.0); + for (std::size_t index = 0u; index < model_.table_a_extra_indices.size(); ++index) { + const std::size_t delay = + static_cast(model_.table_a_extra_indices[index]); + const std::size_t slot = static_cast( + (position_ - static_cast(delay) - 1 + capacity_ * 2) % capacity_); + for (std::size_t band = 0u; band < bands; ++band) { + for (int row = 0; row < 4; ++row) { + double mixed_real = 0.0; + double mixed_imag = 0.0; + for (int column = 0; column < 4; ++column) { + const std::size_t source = + (slot * bands + band) * 4u + static_cast(column); + const double coefficient = + extra_matrices_[index][static_cast(row) + + 4u * static_cast(column)]; + mixed_real += memory_real_[source] * coefficient; + mixed_imag += memory_imag_[source] * coefficient; + } + const int group = static_cast(band) / 4; + const int lane = static_cast(band) % 4; + const std::size_t field = + (index * 20u + static_cast(group)) * 2u * 4u; + const double coefficient_real = static_cast( + model_.table_a_extra_fields_padded[field + static_cast(lane)]); + const double coefficient_imag = static_cast( + model_.table_a_extra_fields_padded[field + 4u + static_cast(lane)]); + const std::size_t target = band * 4u + static_cast(row); + extra_real[target] += + mixed_real * coefficient_real - mixed_imag * coefficient_imag; + extra_imag[target] += + mixed_imag * coefficient_real + mixed_real * coefficient_imag; + } + } + } + + for (std::size_t band = 0u; band < bands; ++band) { + double left_real = 0.0; + double left_imag = 0.0; + double right_real = 0.0; + double right_imag = 0.0; + for (int lane = 0; lane < 4; ++lane) { + const std::size_t cell = band * 4u + static_cast(lane); + const double real = tap_real[cell] * output_tap_[cell] + extra_real[cell]; + const double imag = tap_imag[cell] * output_tap_[cell] + extra_imag[cell]; + left_real += left_real_[cell] * real - left_imag_[cell] * imag; + left_imag += left_imag_[cell] * real + left_real_[cell] * imag; + right_real += right_real_[cell] * real - right_imag_[cell] * imag; + right_imag += right_imag_[cell] * real + right_real_[cell] * imag; + } + output[band] = Complex(left_real, left_imag); + output[kHybridBands + band] = Complex(right_real, right_imag); + } + return Status::success(); + } + +private: + const RosellaModel& model_; + int bands_ = 0; + std::array delays_{}; + int capacity_ = 0; + std::vector matrix_; + std::vector feedback_real_; + std::vector feedback_imag_; + std::vector output_tap_; + std::vector left_real_; + std::vector left_imag_; + std::vector right_real_; + std::vector right_imag_; + std::vector allpass_gain_; + std::vector allpass_delay_; + std::vector> allpass_real_; + std::vector> allpass_imag_; + std::vector allpass_position_; + std::vector memory_real_; + std::vector memory_imag_; + int position_ = 0; + std::vector> extra_matrices_; +}; + +// rosella_room.RosellaRoomFir: the room FIR plus its overlap-add convolution. +class RoomFir { +public: + RoomFir(const RosellaModel& model, int impulse_slots) : length_(impulse_slots) { + RoomState reference(model); + kernel_.assign(static_cast(length_) * 2u * kRoomBands, Complex(0.0, 0.0)); + Complex slot_output[2 * kHybridBands]; + for (int slot = 0; slot < length_; ++slot) { + Complex impulse[kHybridBands]; + for (int band = 0; band < kHybridBands; ++band) { + impulse[band] = Complex(slot == 0 && band < kRoomBands ? 1.0 : 0.0, 0.0); + } + const Status status = reference.process_slot(impulse, slot_output); + if (!status.ok()) { + return; + } + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kRoomBands; ++band) { + kernel_[(static_cast(slot) * 2u + static_cast(ear)) * + kRoomBands + + static_cast(band)] = + slot_output[ear * kHybridBands + band]; + } + } + } + tail_.assign(static_cast(length_ - 1) * 2u * kRoomBands, Complex(0.0, 0.0)); + valid_ = true; + } + + bool valid() const { return valid_; } + + void reset() { + std::fill(tail_.begin(), tail_.end(), Complex(0.0, 0.0)); + fft_cache_size_ = 0u; + forward_plan_.reset(); + inverse_plan_.reset(); + } + + // rosella_room.RosellaRoomFir.process_chunk. + Status process_chunk(const std::vector& values, std::size_t slots, + std::vector* output) { + output->assign(slots * 2u * kHybridBands, Complex(0.0, 0.0)); + if (slots == 0u) { + return Status::success(); + } + const std::size_t needed = slots + static_cast(length_) - 1u; + std::size_t fft_size = 1u; + while (fft_size < needed) { + fft_size <<= 1u; + } + if (fft_size != fft_cache_size_) { + kernel_fft_.assign(fft_size * 2u * kRoomBands, Complex(0.0, 0.0)); + // The room transforms a fixed length for the whole chunk, so the radix-2 + // twiddle recurrences are materialised once here rather than re-derived + // inside every butterfly of every one of the 3 * kRoomBands transforms. + forward_plan_ = std::make_unique(fft_size, false); + inverse_plan_ = std::make_unique(fft_size, true); + line_.assign(fft_size, Complex(0.0, 0.0)); + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kRoomBands; ++band) { + for (int slot = 0; slot < length_; ++slot) { + line_[static_cast(slot)] = + kernel_[(static_cast(slot) * 2u + + static_cast(ear)) * + kRoomBands + + static_cast(band)]; + } + std::fill(line_.begin() + length_, line_.end(), Complex(0.0, 0.0)); + dsp::fft_radix2(&line_, *forward_plan_); + for (std::size_t index = 0u; index < fft_size; ++index) { + // Band-major, so that the spectrum multiply below reads both + // of its operands as runs instead of striding through them + // one complex per cache line. Same values, same places. + kernel_fft_[(static_cast(ear) * kRoomBands + + static_cast(band)) * + fft_size + + index] = line_[index]; + } + } + } + fft_cache_size_ = fft_size; + } + // input_fft_ and block_ are indexed linearly and every entry of each is written + // before it is read (the per-band forward transform fills input_fft_ column by + // column, and the inverse transform fills block_ entry by entry), so their zero + // fills were dead. The line buffer, by contrast, is handed to fft_radix2, + // which transforms exactly data->size() entries -- it therefore has to keep the + // exact length and the exact initialisation it had as a local. + if (line_.size() != fft_size) { + line_.assign(fft_size, Complex(0.0, 0.0)); + } + const std::size_t input_fft_size = fft_size * kRoomBands; + if (input_fft_.size() < input_fft_size) { + input_fft_.resize(input_fft_size); + } + for (int band = 0; band < kRoomBands; ++band) { + for (std::size_t slot = 0u; slot < slots; ++slot) { + line_[slot] = values[slot * kHybridBands + static_cast(band)]; + } + std::fill(line_.begin() + static_cast(slots), line_.end(), + Complex(0.0, 0.0)); + dsp::fft_radix2(&line_, *forward_plan_); + for (std::size_t index = 0u; index < fft_size; ++index) { + // Band-major, matching kernel_fft_, so that the spectrum multiply + // reads both operands as runs. + input_fft_[static_cast(band) * fft_size + index] = line_[index]; + } + } + const std::size_t block_size = needed * 2u * kRoomBands; + if (block_.size() < block_size) { + block_.resize(block_size); + } + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kRoomBands; ++band) { + // Both planes are band-major now, so this is one contiguous complex + // product per (ear, band) and the dispatched kernel puts neighbouring + // complexes in its lanes; each product keeps the caller's four + // multiplies and two roundings. + simd::complex_multiply( + reinterpret_cast(line_.data()), + reinterpret_cast( + input_fft_.data() + static_cast(band) * fft_size), + reinterpret_cast( + kernel_fft_.data() + + (static_cast(ear) * kRoomBands + + static_cast(band)) * + fft_size), + fft_size); + dsp::fft_radix2(&line_, *inverse_plan_); + for (std::size_t slot = 0u; slot < needed; ++slot) { + block_[(slot * 2u + static_cast(ear)) * kRoomBands + + static_cast(band)] = line_[slot]; + } + } + } + const std::size_t tail_length = static_cast(length_ - 1); + for (std::size_t index = 0u; index < tail_length * 2u * kRoomBands; ++index) { + block_[index] += tail_[index]; + } + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kRoomBands; ++band) { + (*output)[slot * 2u * kHybridBands + static_cast(ear) * kHybridBands + + static_cast(band)] = + block_[(slot * 2u + static_cast(ear)) * kRoomBands + + static_cast(band)]; + } + } + } + for (std::size_t index = 0u; index < tail_length * 2u * kRoomBands; ++index) { + tail_[index] = block_[slots * 2u * kRoomBands + index]; + } + return Status::success(); + } + +private: + int length_ = 0; + bool valid_ = false; + std::vector kernel_; + std::vector tail_; + std::vector kernel_fft_; + std::size_t fft_cache_size_ = 0u; + std::vector line_; // scratch, exactly fft_size entries + std::vector input_fft_; // scratch, [fft_size][kRoomBands], fully written + std::vector block_; // scratch, [needed][2][kRoomBands], fully written + std::unique_ptr forward_plan_; + std::unique_ptr inverse_plan_; +}; + +// rosella_core.RosellaRenderer: per-source direct gains plus the room send. +class Core { +public: + Status configure(const RosellaModel& model, const std::vector& field_left, + const std::vector& field_right, int room_impulse_slots) { + model_ = &model; + field_left_ = &field_left; + field_right_ = &field_right; + room_ = std::make_unique(model, room_impulse_slots); + if (!room_->valid()) { + return render_fail(JOC_ERR_NOT_SUPPORTED, "alternate Rosella table-A room mode"); + } + gains_.assign(static_cast(kSourceChannels) * 2u * kHybridBands, + Complex(0.0, 0.0)); + room_sends_.assign(kSourceChannels, 0.0); + keys_.assign(kSourceChannels, Key{}); + for (int source = 0; source < kSourceChannels; ++source) { + const double position[3] = {0.0, 1.0, 0.0}; + Status status = set_source(source, position, + static_cast(RosellaProfile::Mid), false); + if (!status.ok()) { + return status; + } + } + return Status::success(); + } + + void reset() { room_->reset(); } + + Status set_source(int source, const double position[3], int profile, bool special_lfe) { + const int effective_profile = special_lfe ? 0 : profile; + Key key; + key.special_lfe = special_lfe; + key.profile = effective_profile; + key.position[0] = position[0]; + key.position[1] = position[1]; + key.position[2] = position[2]; + if (keys_[static_cast(source)].equals(key)) { + return Status::success(); + } + DirectResult result; + if (special_lfe) { + result = special_lfe_direct(); + } else { + result = direct_and_room_send(*model_, *field_left_, *field_right_, position, + effective_profile); + } + for (int ear = 0; ear < 2; ++ear) { + for (int band = 0; band < kHybridBands; ++band) { + gains_[(static_cast(source) * 2u + static_cast(ear)) * + kHybridBands + + static_cast(band)] = result.gains[ear][band]; + } + } + room_sends_[static_cast(source)] = result.room_send; + keys_[static_cast(source)] = key; + return Status::success(); + } + + // rosella_core.RosellaRenderer.direct_and_send_static: the sources are summed in + // reverse index order, which is part of the reference's arithmetic. + void direct_and_send_static(const std::vector& hybrid, std::size_t slots, + std::vector* direct, std::vector* room_send) { + direct->assign(slots * 2u * kHybridBands, Complex(0.0, 0.0)); + room_send->assign(slots * kHybridBands, Complex(0.0, 0.0)); + for (int source = kSourceChannels - 1; source >= 0; --source) { + const std::size_t base = static_cast(source) * kHybridBands; + for (std::size_t slot = 0u; slot < slots; ++slot) { + const std::size_t input = slot * kSourceChannels * kHybridBands + base; + const std::size_t room_target = slot * kHybridBands; + for (int band = 0; band < kHybridBands; ++band) { + const Complex value = hybrid[input + static_cast(band)]; + for (int ear = 0; ear < 2; ++ear) { + (*direct)[slot * 2u * kHybridBands + + static_cast(ear) * kHybridBands + + static_cast(band)] += + value * gains_[(static_cast(source) * 2u + + static_cast(ear)) * + kHybridBands + + static_cast(band)]; + } + (*room_send)[room_target + static_cast(band)] += + value * room_sends_[static_cast(source)]; + } + } + } + } + + Status process_chunk(const std::vector& hybrid, std::size_t slots, + std::vector* output) { + std::vector direct; + std::vector room_send; + direct_and_send_static(hybrid, slots, &direct, &room_send); + std::vector room; + const Status status = room_->process_chunk(room_send, slots, &room); + if (!status.ok()) { + return status; + } + for (std::size_t index = 0u; index < direct.size(); ++index) { + direct[index] += room[index]; + } + *output = std::move(direct); + return Status::success(); + } + + Status room_process(const std::vector& room_send, std::size_t slots, + std::vector* output) { + return room_->process_chunk(room_send, slots, output); + } + +private: + struct Key { + bool special_lfe = false; + int profile = 0; + double position[3] = {0.0, 1.0, 0.0}; + bool equals(const Key& other) const { + return special_lfe == other.special_lfe && profile == other.profile && + position[0] == other.position[0] && position[1] == other.position[1] && + position[2] == other.position[2]; + } + }; + + const RosellaModel* model_ = nullptr; + const std::vector* field_left_ = nullptr; + const std::vector* field_right_ = nullptr; + std::unique_ptr room_; + std::vector gains_; + std::vector room_sends_; + std::vector keys_; +}; + +} // namespace + +struct RosellaRuntime::Impl { + RosellaModel model; + RosellaRenderOptions options; + std::vector field_left; + std::vector field_right; + Core core; + std::unique_ptr analysis_bank; + std::unique_ptr synthesis_bank; + timeline::OamdPositionTimeline timeline{timeline::kTimelineObjects}; + + std::vector buffer; // [chunk_samples][16] + std::size_t buffer_used = 0; + std::vector output; + std::uint64_t input_samples = 0; + std::uint64_t processed_input_samples = 0; + std::uint64_t raw_output_samples = 0; + std::uint64_t metadata_block_updates = 0; + bool open = false; + bool finished = false; + + std::size_t chunk_samples() const { + return static_cast(options.chunk_frames) * kFrameSamples; + } + + // rosella_binaural_renderer._process_samples. + Status process_samples(const double* values, std::size_t count) { + const std::size_t blocks = count / kBlockSamples; + const std::size_t slots = blocks * (kBlockSamples / kQmfHop); + // Every plane below is written in full before it is read, so they live as + // reusable buffers rather than as per-chunk allocations: the chunk geometry is + // constant, which turns each one into a no-op size check after the first chunk. + const std::size_t hops_size = slots * kSourceChannels * kQmfHop; + if (hops_.size() < hops_size) { + hops_.resize(hops_size); + } + for (std::size_t block = 0u; block < blocks; ++block) { + for (std::size_t hop = 0u; hop < kBlockSamples / kQmfHop; ++hop) { + for (std::size_t channel = 0u; channel < kSourceChannels; ++channel) { + for (int index = 0; index < kQmfHop; ++index) { + hops_[((block * (kBlockSamples / kQmfHop) + hop) * kSourceChannels + + channel) * + kQmfHop + + static_cast(index)] = + values[(block * kBlockSamples + hop * kQmfHop + + static_cast(index)) * + kSourceChannels + + channel]; + } + } + } + } + analysis_bank->analyze_qmf(hops_, slots, &qmf_); + analysis_bank->analyze_hybrid(qmf_, slots, &hybrid_); + + if (rendered_.size() < slots * 2u * kHybridBands) { + rendered_.resize(slots * 2u * kHybridBands); + } + if (room_sends_buffer_.size() != slots * kHybridBands) { + room_sends_buffer_.resize(slots * kHybridBands); + } + for (std::size_t block = 0u; block < blocks; ++block) { + const std::size_t first_slot = block * (kBlockSamples / kQmfHop); + const std::size_t block_slots = kBlockSamples / kQmfHop; + const std::int64_t sample = + static_cast(processed_input_samples) + + static_cast(block * kBlockSamples); + Status status = set_block_parameters(sample); + if (!status.ok()) { + return status; + } + std::vector block_hybrid( + hybrid_.begin() + static_cast(first_slot * kSourceChannels * + kHybridBands), + hybrid_.begin() + static_cast((first_slot + block_slots) * + kSourceChannels * kHybridBands)); + std::vector direct; + std::vector room_send; + core.direct_and_send_static(block_hybrid, block_slots, &direct, &room_send); + std::copy(direct.begin(), direct.end(), + rendered_.begin() + static_cast(first_slot * 2u * kHybridBands)); + std::copy(room_send.begin(), room_send.end(), + room_sends_buffer_.begin() + + static_cast(first_slot * kHybridBands)); + } + // The room runs once for the whole chunk, as the reference does. Its output + // keeps a zero fill of its own: only the first kRoomBands of each ear are + // written, and the caller adds the whole 77-band slot back into `rendered`. + Status status = core.room_process(room_sends_buffer_, slots, &room_out_); + if (!status.ok()) { + return status; + } + for (std::size_t index = 0u; index < rendered_.size(); ++index) { + rendered_[index] += room_out_[index]; + } + synthesis_bank->synthesize_hybrid(rendered_, slots, &qmf_out_); + // The synthesis bank returns [slots, ears, 64]; the reference transposes it to + // sample-major stereo before the latency skip. + synthesis_bank->synthesize_qmf(qmf_out_, slots, &bands_); + const std::size_t produced = blocks * kBlockSamples; + if (time_.size() != produced * kOutputChannels) { + time_.resize(produced * kOutputChannels); + } + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (std::size_t channel = 0u; channel < kOutputChannels; ++channel) { + for (int band = 0; band < kQmfHop; ++band) { + time_[(slot * kQmfHop + static_cast(band)) * kOutputChannels + + channel] = + bands_[(slot * kOutputChannels + channel) * kQmfHop + + static_cast(band)]; + } + } + } + for (std::size_t sample = 0u; sample < produced; ++sample) { + for (std::size_t channel = 0u; channel < kOutputChannels; ++channel) { + time_[sample * kOutputChannels + channel] *= options.output_gain; + } + } + append_output(time_.data(), produced); + processed_input_samples += count; + return Status::success(); + } + + // rosella_binaural_renderer._set_block_parameters. + Status set_block_parameters(std::int64_t sample) { + double positions[timeline::kTimelineObjects][3] = {}; + Status status = timeline.positions_at(sample, positions); + if (!status.ok()) { + return status; + } + const double lfe[3] = {0.0, 1.0, 0.0}; + status = core.set_source(0, lfe, static_cast(RosellaProfile::Mid), true); + if (!status.ok()) { + return status; + } + for (int object = 0; object < timeline::kTimelineObjects; ++object) { + status = core.set_source(object + 1, positions[object], + static_cast(options.profile), false); + if (!status.ok()) { + return status; + } + } + return Status::success(); + } + + // The reference drops the first 961 samples of the raw stream (the filterbank's + // latency) and returns everything after that. + void append_output(const double* stereo, std::size_t count) { + const std::int64_t remaining = static_cast(kLatencySamples) - + static_cast(raw_output_samples); + const std::size_t skip = static_cast( + std::max(0, std::min(static_cast(count), + remaining))); + raw_output_samples += count; + for (std::size_t sample = skip; sample < count; ++sample) { + output.push_back(stereo[sample * kOutputChannels]); + output.push_back(stereo[sample * kOutputChannels + 1u]); + } + } + + // Per-chunk scratch. Every one of these planes is written in full before it is + // read, so they are sized once and reused instead of being allocated per chunk. + std::vector hops_; // [slots][kSourceChannels][64] + std::vector qmf_; // [slots][kSourceChannels][64] + std::vector hybrid_; // [slots][kSourceChannels][77] + std::vector rendered_; // [slots][2][77] + std::vector room_out_; // [slots][2][77], partially written (see above) + std::vector qmf_out_; // [slots][2][64] + std::vector bands_; // [slots][2][64] + std::vector time_; // [produced][2] + std::vector room_sends_buffer_; +}; + +RosellaRuntime::RosellaRuntime() : impl_(std::make_unique()) {} +RosellaRuntime::~RosellaRuntime() = default; + +Status RosellaRuntime::open(const RosellaModel& model, const RosellaRenderOptions& options) { + if (impl_->open) { + return render_fail(JOC_ERR_STATE, "Rosella runtime is already open"); + } + if (options.chunk_frames <= 0) { + return render_fail(JOC_ERR_INVALID_ARGUMENT, "chunk_frames must be positive"); + } + if (options.room_impulse_slots <= 0) { + return render_fail(JOC_ERR_INVALID_ARGUMENT, "room_impulse_slots must be positive"); + } + if (!(options.tail_seconds >= 0.0)) { + return render_fail(JOC_ERR_INVALID_ARGUMENT, "tail_seconds must be non-negative"); + } + if (!std::isfinite(options.output_gain)) { + return render_fail(JOC_ERR_INVALID_ARGUMENT, "output_gain must be finite"); + } + if (options.object_delay_samples < 0) { + return render_fail(JOC_ERR_INVALID_ARGUMENT, "object_delay_samples must be non-negative"); + } + impl_->model = model; + impl_->options = options; + logical_field(impl_->model.field_left_padded, &impl_->field_left); + logical_field(impl_->model.field_right_padded, &impl_->field_right); + // The core and the room keep references, so they must point at this runtime's + // own copy of the model rather than at the caller's. + Status status = impl_->core.configure(impl_->model, impl_->field_left, impl_->field_right, + options.room_impulse_slots); + if (!status.ok()) { + return status; + } + // The analysis bank runs sixteen sources, the synthesis bank two output ears. + impl_->analysis_bank = std::make_unique(builtin_kernels(), kSourceChannels); + impl_->synthesis_bank = std::make_unique(builtin_kernels(), kOutputChannels); + impl_->buffer.assign(impl_->chunk_samples() * kSourceChannels, 0.0); + impl_->room_sends_buffer_.assign( + (impl_->chunk_samples() / kQmfHop) * kHybridBands, Complex(0.0, 0.0)); + impl_->buffer_used = 0; + impl_->output.clear(); + impl_->input_samples = 0u; + impl_->processed_input_samples = 0u; + impl_->raw_output_samples = 0u; + impl_->metadata_block_updates = 0u; + impl_->finished = false; + impl_->open = true; + return Status::success(); +} + +Status RosellaRuntime::submit_frame(const float* objects16_planar, const oamd::OamdUpdate* update, + std::int64_t frame_index, std::int64_t outer_sample_offset, + std::int64_t object_delay_samples) { + // The timeline is addressed by the number of samples submitted so far, exactly as + // the reference addresses it, rather than by the caller's frame index. + (void)frame_index; + if (!impl_->open) { + return render_fail(JOC_ERR_STATE, "Rosella runtime is not open"); + } + if (impl_->finished) { + return render_fail(JOC_ERR_STATE, "Rosella runtime is already finished"); + } + if (objects16_planar == nullptr) { + return render_fail(JOC_ERR_INVALID_ARGUMENT, "null frame"); + } + if (update != nullptr) { + const Status submitted = impl_->timeline.submit_update( + *update, static_cast(impl_->input_samples), outer_sample_offset, + object_delay_samples, static_cast(impl_->processed_input_samples)); + if (!submitted.ok()) { + return submitted; + } + ++impl_->metadata_block_updates; + } + const std::size_t chunk = impl_->chunk_samples(); + std::size_t offset = 0u; + while (offset < kFrameSamples) { + const std::size_t room = chunk - impl_->buffer_used; + const std::size_t count = std::min(room, kFrameSamples - offset); + for (std::size_t sample = 0u; sample < count; ++sample) { + double* row = impl_->buffer.data() + (impl_->buffer_used + sample) * kSourceChannels; + for (std::size_t channel = 0u; channel < kSourceChannels; ++channel) { + row[channel] = static_cast( + objects16_planar[channel * kFrameSamples + offset + sample]); + } + } + impl_->buffer_used += count; + offset += count; + if (impl_->buffer_used == chunk) { + const Status status = impl_->process_samples(impl_->buffer.data(), chunk); + if (!status.ok()) { + return status; + } + impl_->buffer_used = 0u; + } + } + impl_->input_samples += kFrameSamples; + return Status::success(); +} + +Status RosellaRuntime::finish(std::uint32_t flush_samples, std::vector* out) { + if (!impl_->open) { + return render_fail(JOC_ERR_STATE, "Rosella runtime is not open"); + } + if (out != nullptr) { + out->clear(); + } + if (impl_->finished) { + return Status::success(); + } + // Only the flush tail is returned: the caller has already taken the program. + const std::size_t program_end = impl_->output.size(); + if (impl_->buffer_used != 0u) { + const Status status = impl_->process_samples(impl_->buffer.data(), impl_->buffer_used); + if (!status.ok()) { + return status; + } + impl_->buffer_used = 0u; + } + const std::size_t chunk = impl_->chunk_samples(); + std::vector silence; + std::uint32_t remaining = flush_samples; + while (remaining > 0u) { + const std::size_t count = std::min(remaining, chunk); + silence.assign(count * kSourceChannels, 0.0); + const Status status = impl_->process_samples(silence.data(), count); + if (!status.ok()) { + return status; + } + remaining -= static_cast(count); + } + impl_->finished = true; + if (out != nullptr) { + out->assign(impl_->output.begin() + static_cast(program_end), + impl_->output.end()); + } + return Status::success(); +} + +std::uint32_t RosellaRuntime::finish_capacity(double tail_seconds) const { + const double samples = tail_seconds * 48000.0 + static_cast(kLatencySamples) + + static_cast(kBlockSamples); + const double blocks = std::ceil(samples / static_cast(kBlockSamples)); + return static_cast(blocks) * kBlockSamples; +} + +Status RosellaRuntime::reset() { + if (!impl_->open) { + return render_fail(JOC_ERR_STATE, "Rosella runtime is not open"); + } + impl_->core.reset(); + impl_->analysis_bank->reset(); + impl_->synthesis_bank->reset(); + impl_->buffer_used = 0u; + impl_->output.clear(); + impl_->input_samples = 0u; + impl_->processed_input_samples = 0u; + impl_->raw_output_samples = 0u; + impl_->metadata_block_updates = 0u; + impl_->finished = false; + impl_->timeline = timeline::OamdPositionTimeline(timeline::kTimelineObjects); + return Status::success(); +} + +const std::vector& RosellaRuntime::output() const { return impl_->output; } + +void RosellaRuntime::take_output(std::vector* out) { + if (out == nullptr) { + return; + } + // Replace semantics, exactly like SofaBinauralRuntime::take_output: the caller's + // previous contents are discarded, and the internal buffer is emptied afterwards + // because the swap leaves it holding whatever the caller had. + out->swap(impl_->output); + impl_->output.clear(); +} + +std::uint64_t RosellaRuntime::input_samples() const { return impl_->input_samples; } +std::uint64_t RosellaRuntime::processed_input_samples() const { + return impl_->processed_input_samples; +} +std::uint64_t RosellaRuntime::metadata_block_updates() const { + return impl_->metadata_block_updates; +} +const timeline::OamdPositionTimeline& RosellaRuntime::timeline() const { return impl_->timeline; } + +} // namespace joc::hrtf diff --git a/src/hrtf/rosella_renderer.h b/src/hrtf/rosella_renderer.h new file mode 100644 index 0000000..7922df7 --- /dev/null +++ b/src/hrtf/rosella_renderer.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include +#include +#include + +#include "foundation/status.h" +#include "hrtf/rosella_model.h" +#include "oamd/oamd_parser.h" +#include "timeline/position_timeline.h" + +// Rosella ".personalized_headphone" binaural renderer (upstream rosella_core.py, +// rosella_direct.py, rosella_room.py and rosella_binaural_renderer.py). It takes +// the same pipeline slot as the SOFA runtime: sixteen object channels per frame in, +// interleaved stereo out, with the OAMD timeline driving the per-block parameters. +namespace joc::hrtf { + +// rosella_direct.BINAURAL_PROFILE_NAMES. +enum class RosellaProfile : std::int32_t { Near = 1, Far = 2, Mid = 3 }; + +struct RosellaRenderOptions { + RosellaProfile profile = RosellaProfile::Mid; + std::int64_t object_delay_samples = 1473; + double tail_seconds = 5.0; + double output_gain = 1.0; + int chunk_frames = 64; + int room_impulse_slots = 4096; +}; + +class RosellaRuntime { +public: + RosellaRuntime(); + ~RosellaRuntime(); + RosellaRuntime(const RosellaRuntime&) = delete; + RosellaRuntime& operator=(const RosellaRuntime&) = delete; + + Status open(const RosellaModel& model, const RosellaRenderOptions& options); + + // objects16_planar is channel-major: channel * 1536 + sample. + Status submit_frame(const float* objects16_planar, const oamd::OamdUpdate* update, + std::int64_t frame_index, std::int64_t outer_sample_offset, + std::int64_t object_delay_samples); + + // Drains the flush tail: the pending partial chunk plus flush_samples of silence. + Status finish(std::uint32_t flush_samples, std::vector* out); + std::uint32_t finish_capacity(double tail_seconds) const; + + Status reset(); + + const std::vector& output() const; + void take_output(std::vector* out); + + std::uint64_t input_samples() const; + std::uint64_t processed_input_samples() const; + std::uint64_t metadata_block_updates() const; + const timeline::OamdPositionTimeline& timeline() const; + +private: + struct Impl; + std::unique_ptr impl_; +}; + +} // namespace joc::hrtf diff --git a/src/hrtf/sofa.cpp b/src/hrtf/sofa.cpp new file mode 100644 index 0000000..c05c0ac --- /dev/null +++ b/src/hrtf/sofa.cpp @@ -0,0 +1,255 @@ +#include "hrtf/sofa.h" + +#include +#include +#include +#include +#include +#include + +#include "foundation/fs_utf8.h" +#include "foundation/sha256.h" +#include "io/hdf5.h" + +namespace joc::hrtf { + +namespace { + +Status sofa_fail(joc_error code, const std::string& message) { + return Status::fail(code, stage::kRender, message); +} + +std::string format_number(double value) { + if (std::isfinite(value) && value == std::floor(value) && std::fabs(value) < 1.0e15) { + return std::to_string(static_cast(value)); + } + char buffer[32]; + std::snprintf(buffer, sizeof(buffer), "%.6g", value); + return std::string(buffer); +} + +// Every array is checked against the element count the convention prescribes, so +// a file whose shape disagrees with its metadata is rejected instead of silently +// producing a shifted impulse response. +Status read_doubles(const io::Hdf5File& file, const std::string& path, std::uint64_t expected, + std::vector* out) { + if (!file.has_dataset(path)) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, "SOFA file has no " + path + " dataset"); + } + const Status status = file.read_dataset_double(path, out); + if (!status.ok()) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, "SOFA dataset " + path + ": " + status.message()); + } + if (out->size() != expected) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, + "SOFA dataset " + path + " holds " + std::to_string(out->size()) + + " values, expected " + std::to_string(expected)); + } + return Status::success(); +} + +Status read_text(const io::Hdf5File& file, const std::string& name, bool required, + std::string* out) { + io::Hdf5Attribute attribute; + const Status status = file.attribute("", name, &attribute); + if (!status.ok()) { + if (required) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, + "SOFA file has no root attribute " + name + ": " + status.message()); + } + return Status::success(); + } + *out = attribute.text; + return Status::success(); +} + +// SHA-256 of the whole file: the compiled-cache key is derived from it, so the +// digest is taken over the exact bytes the parse consumed. +std::string file_digest(const std::string& path) { + std::ifstream stream = fs_utf8::open_input(path); + if (!stream.good()) { + return std::string(); + } + crypto::Sha256 hash; + std::vector buffer(1u << 20); + while (stream.good()) { + stream.read(buffer.data(), static_cast(buffer.size())); + const std::streamsize count = stream.gcount(); + if (count > 0) { + hash.update(buffer.data(), static_cast(count)); + } + } + return hash.finish_hex(); +} + +// The coordinate declaration of one dataset, when the file carries it. +void read_coordinates(const io::Hdf5File& file, const std::string& dataset, + SofaCoordinate* out) { + io::Hdf5Attribute attribute; + if (file.attribute(dataset, "Type", &attribute).ok()) { + out->type = attribute.text; + } + if (file.attribute(dataset, "Units", &attribute).ok()) { + out->units = attribute.text; + } +} + +} // namespace + +std::string SofaHrir::summary() const { + return "SOFA " + sofa_conventions + ", " + std::to_string(ir_count) + " IRs x " + + std::to_string(ir_length) + " taps @ " + format_number(sample_rate) + " Hz"; +} + +Status load_sofa(const std::string& path, SofaHrir* out) { + if (out == nullptr) { + return sofa_fail(JOC_ERR_INVALID_ARGUMENT, "null SOFA destination"); + } + if (!fs_utf8::exists(path)) { + return sofa_fail(JOC_ERR_HRTF_NOT_FOUND, "SOFA file not found: " + path); + } + io::Hdf5File file; + Status status = file.open(path); + if (!status.ok()) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, "SOFA file " + path + ": " + status.message()); + } + + SofaHrir sofa; + sofa.source_path = path; + sofa.source_sha256 = file_digest(path); + for (char& character : sofa.source_sha256) { + character = static_cast(std::toupper(static_cast(character))); + } + status = read_text(file, "Conventions", true, &sofa.conventions); + if (!status.ok()) { + return status; + } + status = read_text(file, "SOFAConventions", true, &sofa.sofa_conventions); + if (!status.ok()) { + return status; + } + if (sofa.conventions != "SOFA" || sofa.sofa_conventions != "SimpleFreeFieldHRIR") { + return sofa_fail(JOC_ERR_HRTF_UNSUPPORTED_CONVENTION, + "SOFA conventions " + sofa.conventions + "/" + sofa.sofa_conventions + + " are not SimpleFreeFieldHRIR"); + } + status = read_text(file, "SOFAConventionsVersion", false, &sofa.convention_version); + if (!status.ok()) { + return status; + } + status = read_text(file, "Version", false, &sofa.version); + if (!status.ok()) { + return status; + } + status = read_text(file, "DataType", false, &sofa.data_type); + if (!status.ok()) { + return status; + } + status = read_text(file, "RoomType", false, &sofa.room_type); + if (!status.ok()) { + return status; + } + status = read_text(file, "Title", false, &sofa.title); + if (!status.ok()) { + return status; + } + status = read_text(file, "DatabaseName", false, &sofa.database_name); + if (!status.ok()) { + return status; + } + status = read_text(file, "ListenerShortName", false, &sofa.listener_short_name); + if (!status.ok()) { + return status; + } + status = read_text(file, "Comment", false, &sofa.comment); + if (!status.ok()) { + return status; + } + + io::Hdf5DatasetInfo info; + status = file.dataset_info("Data.IR", &info); + if (!status.ok()) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, + "SOFA file has no usable Data.IR dataset: " + status.message()); + } + if (info.shape.size() != 3u || info.shape[1] != 2u || info.shape[0] == 0u || + info.shape[2] == 0u) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, "SOFA Data.IR is not shaped (M, 2, N)"); + } + if (info.shape[0] > 0xFFFFFFFFull || info.shape[2] > 0xFFFFFFFFull) { + return sofa_fail(JOC_ERR_HRTF_FORMAT, "SOFA Data.IR is larger than this reader accepts"); + } + sofa.ir_count = static_cast(info.shape[0]); + sofa.ir_length = static_cast(info.shape[2]); + const std::uint64_t taps = static_cast(sofa.ir_count) * 2u * sofa.ir_length; + status = read_doubles(file, "Data.IR", taps, &sofa.ir); + if (!status.ok()) { + return status; + } + + std::vector scalar; + status = read_doubles(file, "Data.SamplingRate", 1u, &scalar); + if (!status.ok()) { + return status; + } + sofa.sample_rate = scalar[0]; + io::Hdf5Attribute attribute; + if (file.attribute("Data.SamplingRate", "Units", &attribute).ok()) { + sofa.sampling_rate_units = attribute.text; + } + + // Data.Delay is optional in the wild; absent means "no delay was measured". + if (file.has_dataset("Data.Delay")) { + std::vector delay; + status = read_doubles(file, "Data.Delay", 2u, &delay); + if (!status.ok()) { + return status; + } + sofa.delay[0] = delay[0]; + sofa.delay[1] = delay[1]; + } + + const std::uint64_t measurements = sofa.ir_count; + status = read_doubles(file, "SourcePosition", measurements * 3u, &sofa.source_position); + if (!status.ok()) { + return status; + } + read_coordinates(file, "SourcePosition", &sofa.source_position_coordinates); + + std::vector vector; + status = read_doubles(file, "ListenerPosition", 3u, &vector); + if (!status.ok()) { + return status; + } + std::copy(vector.begin(), vector.end(), sofa.listener_position); + read_coordinates(file, "ListenerPosition", &sofa.listener_position_coordinates); + status = read_doubles(file, "ListenerView", 3u, &vector); + if (!status.ok()) { + return status; + } + std::copy(vector.begin(), vector.end(), sofa.listener_view); + read_coordinates(file, "ListenerView", &sofa.listener_view_coordinates); + status = read_doubles(file, "ListenerUp", 3u, &vector); + if (!status.ok()) { + return status; + } + std::copy(vector.begin(), vector.end(), sofa.listener_up); + read_coordinates(file, "ListenerUp", &sofa.listener_up_coordinates); + status = read_doubles(file, "EmitterPosition", 3u, &vector); + if (!status.ok()) { + return status; + } + std::copy(vector.begin(), vector.end(), sofa.emitter_position); + read_coordinates(file, "EmitterPosition", &sofa.emitter_position_coordinates); + status = read_doubles(file, "ReceiverPosition", 6u, &vector); + if (!status.ok()) { + return status; + } + std::copy(vector.begin(), vector.end(), sofa.receiver_position); + read_coordinates(file, "ReceiverPosition", &sofa.receiver_position_coordinates); + + *out = std::move(sofa); + return Status::success(); +} + +} // namespace joc::hrtf diff --git a/src/hrtf/sofa.h b/src/hrtf/sofa.h new file mode 100644 index 0000000..101b033 --- /dev/null +++ b/src/hrtf/sofa.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include + +#include "foundation/status.h" + +namespace joc::hrtf { + +// Coordinate declaration of one SOFA variable: Type ("spherical"/"cartesian") and +// Units. Empty when the file does not declare them (ListenerUp inherits). +struct SofaCoordinate { + std::string type; + std::string units; +}; + +// SOFA SimpleFreeFieldHRIR as this project consumes it: the impulse responses, +// the measurement geometry and the metadata needed to report what was loaded. +// All angles are degrees, all distances metres, exactly as the file stores them. +struct SofaHrir { + double sample_rate = 0.0; + std::uint32_t ir_count = 0; // M: number of measurements + std::uint32_t ir_length = 0; // N: taps per impulse response + std::vector ir; // C order [M][2][N] + double delay[2] = {0.0, 0.0}; + std::vector source_position; // M*3 + double listener_position[3] = {0.0, 0.0, 0.0}; + double listener_view[3] = {1.0, 0.0, 0.0}; + double listener_up[3] = {0.0, 0.0, 1.0}; + double emitter_position[3] = {0.0, 0.0, 0.0}; + double receiver_position[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + std::string conventions; + std::string sofa_conventions; + std::string convention_version; + std::string version; + std::string data_type; + std::string room_type; + std::string title; + std::string database_name; + std::string listener_short_name; + std::string comment; + std::string sampling_rate_units; + SofaCoordinate source_position_coordinates; + SofaCoordinate listener_position_coordinates; + SofaCoordinate listener_view_coordinates; + SofaCoordinate listener_up_coordinates; + SofaCoordinate emitter_position_coordinates; + SofaCoordinate receiver_position_coordinates; + // Identity of the file itself, needed for the compiled-cache key. + std::string source_path; + std::string source_sha256; + + // One line for reports and logs: + // "SOFA SimpleFreeFieldHRIR, IRs x taps @ Hz". + std::string summary() const; +}; + +Status load_sofa(const std::string& path, SofaHrir* out); + +} // namespace joc::hrtf diff --git a/src/hrtf/sofa_cache.cpp b/src/hrtf/sofa_cache.cpp new file mode 100644 index 0000000..f49b92f --- /dev/null +++ b/src/hrtf/sofa_cache.cpp @@ -0,0 +1,237 @@ +#include "hrtf/sofa_cache.h" + +#include +#include +#include +#include +#include +#include + +#include "foundation/fs_utf8.h" +#include "hrtf/sofa.h" + +namespace joc::hrtf { + +namespace { + +namespace fs = std::filesystem; + +// Small process-local cache: the reference keeps the last eight compiled fields. +constexpr std::size_t kMemoryCacheEntries = 8; + +struct MemoryEntry { + std::string key; + Field field; +}; + +std::mutex& memory_mutex() { + static std::mutex mutex; + return mutex; +} + +std::list& memory_cache() { + static std::list cache; + return cache; +} + +bool memory_cache_get(const std::string& key, Field* out) { + std::lock_guard lock(memory_mutex()); + std::list& cache = memory_cache(); + for (auto entry = cache.begin(); entry != cache.end(); ++entry) { + if (entry->key == key) { + *out = entry->field; + cache.splice(cache.begin(), cache, entry); + return true; + } + } + return false; +} + +void memory_cache_put(const std::string& key, const Field& field) { + std::lock_guard lock(memory_mutex()); + std::list& cache = memory_cache(); + for (auto entry = cache.begin(); entry != cache.end(); ++entry) { + if (entry->key == key) { + entry->field = field; + cache.splice(cache.begin(), cache, entry); + return; + } + } + cache.push_front(MemoryEntry{key, field}); + while (cache.size() > kMemoryCacheEntries) { + cache.pop_back(); + } +} + +Status cache_fail(joc_error code, const std::string& message) { + return Status::fail(code, stage::kRender, message); +} + +std::string upper(std::string text) { + std::transform(text.begin(), text.end(), text.begin(), [](unsigned char value) { + return static_cast(std::toupper(value)); + }); + return text; +} + +} // namespace + +Status parse_cache_policy(const std::string& text, CachePolicy* out) { + if (out == nullptr) { + return cache_fail(JOC_ERR_INVALID_ARGUMENT, "null cache policy"); + } + if (text == "none") { + *out = CachePolicy::None; + return Status::success(); + } + if (text == "memory") { + *out = CachePolicy::Memory; + return Status::success(); + } + if (text == "disk") { + *out = CachePolicy::Disk; + return Status::success(); + } + return cache_fail(JOC_ERR_INVALID_CONFIG, "cache_policy must be none, memory, or disk"); +} + +Status validate_jochrtf(const std::string& path, const std::string& source_sha256, + const std::string& cache_key, Field* out) { + Field field; + const Status status = load_jochrtf(path, &field); + if (!status.ok()) { + return status; + } + if (!source_sha256.empty() && field.source_sha256 != upper(source_sha256)) { + return cache_fail(JOC_ERR_HRTF_HASH, "compiled HRTF source hash mismatch"); + } + if (!cache_key.empty() && field.cache_key != upper(cache_key)) { + return cache_fail(JOC_ERR_HRTF_HASH, "compiled HRTF configuration hash mismatch"); + } + if (out != nullptr) { + *out = std::move(field); + } + return Status::success(); +} + +Status save_jochrtf_atomic(const Field& field, const std::string& path) { + if (path.empty()) { + return cache_fail(JOC_ERR_INVALID_ARGUMENT, "empty compiled HRTF cache path"); + } + const fs::path target = fs_utf8::to_path(path); + std::error_code error; + if (target.has_parent_path()) { + fs::create_directories(target.parent_path(), error); + if (error) { + return cache_fail(JOC_ERR_OUTPUT_OPEN, + "cannot create " + fs_utf8::from_path(target.parent_path())); + } + } + const std::string temporary = path + ".tmp"; + Status status = write_jochrtf(field, temporary); + if (!status.ok()) { + return status; + } + // The rename is what makes a half-written cache impossible to observe. + fs::rename(fs_utf8::to_path(temporary), target, error); + if (error) { + fs::remove(fs_utf8::to_path(temporary), error); + return cache_fail(JOC_ERR_OUTPUT_WRITE, "cannot replace " + path); + } + return Status::success(); +} + +Status load_or_compile_sofa_field(const SofaFieldRequest& request, Field* out, + std::string* cache_path) { + if (out == nullptr) { + return cache_fail(JOC_ERR_INVALID_ARGUMENT, "null compiled HRTF destination"); + } + if (request.sofa_path.empty()) { + return cache_fail(JOC_ERR_INVALID_ARGUMENT, "no SOFA path for the compiled HRTF field"); + } + if (request.policy == CachePolicy::Disk && request.cache_dir.empty()) { + return cache_fail(JOC_ERR_INVALID_CONFIG, "the disk cache policy needs a cache directory"); + } + SofaHrir sofa; + Status status = load_sofa(request.sofa_path, &sofa); + if (!status.ok()) { + return status; + } + CanonicalHrtf canonical; + status = canonicalize_sofa(sofa, &canonical); + if (!status.ok()) { + return status; + } + // The key depends on the shell that the radius selects, exactly as upstream. + double actual_radius = request.options.shell_radius_m; + (void)canonical_shell_indices(canonical, request.options.shell_radius_m, &actual_radius); + const std::string key = compiled_hrtf_cache_key( + canonical.source_sha256, canonical.sample_rate_hz, actual_radius, request.options.order, + request.options.projection_ridge, request.options.sh_ridge); + if (cache_path != nullptr) { + cache_path->clear(); + } + + std::string target; + if (request.policy == CachePolicy::Disk) { + target = request.cache_dir; + if (!target.empty() && target.back() != '/' && target.back() != '\\') { + target += "/"; + } + target += cache_file_name(canonical.source_path.empty() + ? std::string() + : canonical.source_path, + key); + if (fs_utf8::exists(target)) { + Field cached_field; + const Status cached = + validate_jochrtf(target, canonical.source_sha256, key, &cached_field); + if (cached.ok()) { + memory_cache_put(key, cached_field); + *out = std::move(cached_field); + if (cache_path != nullptr) { + *cache_path = target; + } + return Status::success(); + } + } + } + Field field; + if (request.policy != CachePolicy::None && memory_cache_get(key, &field)) { + // A memory hit still materialises the disk cache the caller asked for. + if (request.policy == CachePolicy::Disk) { + status = save_jochrtf_atomic(field, target); + if (!status.ok()) { + return status; + } + if (cache_path != nullptr) { + *cache_path = target; + } + } + *out = std::move(field); + return Status::success(); + } + status = compile_canonical_field(canonical, request.options, &field); + if (!status.ok()) { + return status; + } + if (field.cache_key != key) { + return cache_fail(JOC_ERR_INTERNAL, "internal compiled HRTF cache-key mismatch"); + } + if (request.policy == CachePolicy::Disk) { + status = save_jochrtf_atomic(field, target); + if (!status.ok()) { + return status; + } + if (cache_path != nullptr) { + *cache_path = target; + } + } + if (request.policy != CachePolicy::None) { + memory_cache_put(key, field); + } + *out = std::move(field); + return Status::success(); +} + +} // namespace joc::hrtf diff --git a/src/hrtf/sofa_cache.h b/src/hrtf/sofa_cache.h new file mode 100644 index 0000000..08f0bc3 --- /dev/null +++ b/src/hrtf/sofa_cache.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include "foundation/status.h" +#include "hrtf/jochrtf.h" +#include "hrtf/sofa_field.h" + +// Compiled-field cache: the .jochrtf is an internal artifact, so the caller only +// names the SOFA file and the policy. "memory" keeps the compiled field in this +// process, "disk" additionally reuses (and writes) /..jochrtf. +namespace joc::hrtf { + +enum class CachePolicy { None, Memory, Disk }; + +struct SofaFieldRequest { + std::string sofa_path; + CompileOptions options; + CachePolicy policy = CachePolicy::Memory; + std::string cache_dir; // required for the disk policy +}; + +// Parses "none"/"memory"/"disk"; anything else is rejected. +Status parse_cache_policy(const std::string& text, CachePolicy* out); + +// Returns the compiled field, reusing a valid cache when the policy allows it. +// `cache_path` (optional) receives the cache file that was read or written. +Status load_or_compile_sofa_field(const SofaFieldRequest& request, Field* out, + std::string* cache_path); + +// Writes the field to `path` through a temporary file and an atomic rename. +Status save_jochrtf_atomic(const Field& field, const std::string& path); + +// Verifies that a cache file belongs to `source_sha256` and `cache_key`. +Status validate_jochrtf(const std::string& path, const std::string& source_sha256, + const std::string& cache_key, Field* out); + +} // namespace joc::hrtf diff --git a/src/hrtf/sofa_field.cpp b/src/hrtf/sofa_field.cpp new file mode 100644 index 0000000..d22523b --- /dev/null +++ b/src/hrtf/sofa_field.cpp @@ -0,0 +1,1843 @@ +#include "hrtf/sofa_field.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "foundation/fft.h" +#include "foundation/sha256.h" +#include "hrtf/public_filterbank.h" +#include "io/npy_writer.h" + +namespace joc::hrtf { + +namespace { + +using Complex = std::complex; + +constexpr double kPi = 3.14159265358979323846; +constexpr int kParameterCount = 2 * kHybridBands; +constexpr std::int32_t kFilterbankFormatVersion = 1; +constexpr int kQmfBands = 64; + +// Hybrid-band centre frequencies of the public analysis bank at 48 kHz +// (public_filterbank._BAND_CENTER_FREQUENCIES_HZ; part of the cache contract). +const double kBandCenters[kHybridBands] = { + 53.19564095937407, 26.3876219849709, 140.9074183269806, 98.55238901464415, + 234.09258166297573, 344.8745321543293, 321.80435900819805, 401.38762185365727, + 476.19239745597804, 473.552388917001, 648.8076026837931, 719.8745321201852, + 780.1254679168173, 851.1923973714038, 1023.8076024849751, 1155.125467695814, + 1293.0325067063661, 1668.032511377253, 2043.0325074138086, 2456.967490229666, + 2831.96748495363, 3206.967488172826, 3581.9675052705525, 3918.0325089666067, + 4331.967500201844, 4706.967500350216, 5043.032510771545, 5456.9674914391635, + 5831.967490225267, 6168.0324885741875, 6543.032508972284, 6956.96748844665, + 7293.032503259869, 7668.032503551393, 8043.032504806491, 8418.032498852166, + 8793.032502508235, 9206.967488589786, 9543.032511549152, 9956.967486913867, + 10293.032513008677, 10668.032507835102, 11043.032513641429, 11456.967482937946, + 11793.032513984212, 12206.967486015788, 12543.032517062376, 12956.96748635822, + 13331.967492165066, 13706.967486991198, 14043.032513086031, 14456.967488451, + 14793.032511410214, 15206.967497492202, 15581.967501147887, 15956.967495193188, + 16331.96749644876, 16706.967496740173, 17043.03251155318, 17456.96749102773, + 17831.967511425748, 18168.032509774734, 18543.032508560515, 18956.967489228293, + 19293.032499649784, 19668.032499798002, 20081.967491033392, 20418.0324947296, + 20793.032511827063, 21168.032515046092, 21543.032509770488, 21956.967492586176, + 22331.96748862257, 22706.967493293465, 23043.03251375972, 23418.03251061199, + 23831.96749768645, +}; + +Status field_fail(joc_error code, const std::string& message) { + return Status::fail(code, stage::kRender, message); +} + +double dot3(const double* a, const double* b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +void cross3(const double* a, const double* b, double* out) { + out[0] = a[1] * b[2] - a[2] * b[1]; + out[1] = a[2] * b[0] - a[0] * b[2]; + out[2] = a[0] * b[1] - a[1] * b[0]; +} + +bool normalize3(double* value) { + const double length = std::sqrt(dot3(value, value)); + if (!std::isfinite(length) || length <= 1.0e-15) { + return false; + } + value[0] /= length; + value[1] /= length; + value[2] /= length; + return true; +} + +// Python's round-half-even, used for the reference's shell and direction keys. +double round_half_even(double value, int digits) { + const double scale = std::pow(10.0, digits); + const double scaled = value * scale; + const double lower = std::floor(scaled); + const double fraction = scaled - lower; + double rounded = lower; + if (fraction > 0.5 || (fraction == 0.5 && std::fmod(lower, 2.0) != 0.0)) { + rounded = lower + 1.0; + } + return rounded / scale; +} + +// numpy.percentile with linear interpolation. +double percentile(std::vector values, double percent) { + if (values.empty()) { + return 0.0; + } + std::sort(values.begin(), values.end()); + const double position = (static_cast(values.size()) - 1.0) * percent / 100.0; + const std::size_t lower = static_cast(std::floor(position)); + const std::size_t upper = static_cast(std::ceil(position)); + if (lower == upper || upper >= values.size()) { + return values[std::min(lower, values.size() - 1u)]; + } + const double fraction = position - static_cast(lower); + return values[lower] * (1.0 - fraction) + values[upper] * fraction; +} + + +// Port of sofa_canonical.shift_signal_fft: positive shift delays, negative advances. +std::vector shift_signal_fft(const std::vector& values, double shift) { + const std::size_t count = values.size(); + std::vector result(count, 0.0); + if (std::abs(shift) < 1.0e-12) { + return values; + } + const std::size_t guard = + std::max(128u, static_cast(std::ceil(std::abs(shift))) + 64u); + const std::size_t fft_size = dsp::next_fast_len(count + 2u * guard); + std::vector spectrum(fft_size, Complex(0.0, 0.0)); + for (std::size_t index = 0u; index < count; ++index) { + spectrum[guard + index] = Complex(values[index], 0.0); + } + std::vector transformed; + dsp::fft_any(spectrum, false, &transformed); + const std::size_t half = fft_size / 2u; + for (std::size_t bin = 0u; bin <= half; ++bin) { + const double angle = -2.0 * kPi * static_cast(bin) * shift / + static_cast(fft_size); + transformed[bin] *= std::polar(1.0, angle); + } + for (std::size_t bin = half + 1u; bin < fft_size; ++bin) { + const double angle = -2.0 * kPi * static_cast(bin - fft_size) * shift / + static_cast(fft_size); + transformed[bin] *= std::polar(1.0, angle); + } + std::vector restored; + dsp::fft_any(transformed, true, &restored); + for (std::size_t index = 0u; index < count; ++index) { + result[index] = restored[guard + index].real(); + } + return result; +} + +// public_filterbank.hybrid_gain_synthesis_dictionary for one FIR length. +std::vector hybrid_gain_synthesis_dictionary(std::size_t sample_count, + const Kernels& kernels) { + const std::size_t total = + ((kLatencySamples + sample_count + 512u + kQmfHop - 1u) / kQmfHop) * kQmfHop; + const std::size_t slots = total / kQmfHop; + std::vector impulse(total, 0.0); + impulse[0] = 1.0; + PublicFilterbank analysis_bank(kernels, 1u); + std::vector base; + analysis_bank.analyze_full_rate(impulse, slots, &base); + + std::vector hybrid(slots * kParameterCount * kHybridBands, Complex(0.0, 0.0)); + for (std::size_t slot = 0u; slot < slots; ++slot) { + for (int band = 0; band < kHybridBands; ++band) { + const Complex value = base[slot * kHybridBands + static_cast(band)]; + hybrid[(slot * kParameterCount + static_cast(2 * band)) * kHybridBands + + static_cast(band)] = value; + hybrid[(slot * kParameterCount + static_cast(2 * band + 1)) * kHybridBands + + static_cast(band)] = Complex(0.0, 1.0) * value; + } + } + PublicFilterbank synthesis_bank(kernels, kParameterCount); + std::vector rendered; + synthesis_bank.synthesize_full_rate(hybrid, slots, &rendered); + std::vector dictionary(sample_count * kParameterCount, 0.0); + for (std::size_t tap = 0u; tap < sample_count; ++tap) { + for (int parameter = 0; parameter < kParameterCount; ++parameter) { + dictionary[tap * kParameterCount + static_cast(parameter)] = + rendered[(kLatencySamples + tap) * kParameterCount + static_cast(parameter)]; + } + } + return dictionary; +} + + +// -------------------------------------------------------- linear algebra ---- + +// LU with partial pivoting, complex (mirrors the LAPACK zgesv path the reference +// takes when the ridge system is cast to complex for a complex right-hand side). +bool lu_solve_complex(std::vector* matrix, int order, std::vector* rhs, + int columns) { + std::vector pivot(static_cast(order)); + for (int step = 0; step < order; ++step) { + int best = step; + double best_magnitude = std::abs((*matrix)[static_cast(step) * order + step]); + for (int row = step + 1; row < order; ++row) { + const double magnitude = + std::abs((*matrix)[static_cast(row) * order + step]); + if (magnitude > best_magnitude) { + best_magnitude = magnitude; + best = row; + } + } + pivot[static_cast(step)] = best; + if (best != step) { + for (int column = 0; column < order; ++column) { + std::swap((*matrix)[static_cast(step) * order + column], + (*matrix)[static_cast(best) * order + column]); + } + } + const Complex diagonal = (*matrix)[static_cast(step) * order + step]; + if (std::abs(diagonal) <= 1.0e-300) { + return false; + } + for (int row = step + 1; row < order; ++row) { + const Complex factor = + (*matrix)[static_cast(row) * order + step] / diagonal; + (*matrix)[static_cast(row) * order + step] = factor; + for (int column = step + 1; column < order; ++column) { + (*matrix)[static_cast(row) * order + column] -= + factor * (*matrix)[static_cast(step) * order + column]; + } + } + } + for (int column = 0; column < columns; ++column) { + for (int step = 0; step < order; ++step) { + const int source = pivot[static_cast(step)]; + if (source != step) { + std::swap((*rhs)[static_cast(step) * columns + column], + (*rhs)[static_cast(source) * columns + column]); + } + } + for (int row = 1; row < order; ++row) { + Complex sum = (*rhs)[static_cast(row) * columns + column]; + for (int column2 = 0; column2 < row; ++column2) { + sum -= (*matrix)[static_cast(row) * order + column2] * + (*rhs)[static_cast(column2) * columns + column]; + } + (*rhs)[static_cast(row) * columns + column] = sum; + } + for (int row = order - 1; row >= 0; --row) { + Complex sum = (*rhs)[static_cast(row) * columns + column]; + for (int column2 = row + 1; column2 < order; ++column2) { + sum -= (*matrix)[static_cast(row) * order + column2] * + (*rhs)[static_cast(column2) * columns + column]; + } + (*rhs)[static_cast(row) * columns + column] = + sum / (*matrix)[static_cast(row) * order + row]; + } + } + return true; +} + +// LU with partial pivoting, real (the LAPACK dgesv path). +bool lu_solve_real(std::vector* matrix, int order, std::vector* rhs, int columns) { + std::vector pivot(static_cast(order)); + for (int step = 0; step < order; ++step) { + int best = step; + double best_magnitude = std::abs((*matrix)[static_cast(step) * order + step]); + for (int row = step + 1; row < order; ++row) { + const double magnitude = std::abs((*matrix)[static_cast(row) * order + step]); + if (magnitude > best_magnitude) { + best_magnitude = magnitude; + best = row; + } + } + pivot[static_cast(step)] = best; + if (best != step) { + for (int column = 0; column < order; ++column) { + std::swap((*matrix)[static_cast(step) * order + column], + (*matrix)[static_cast(best) * order + column]); + } + } + const double diagonal = (*matrix)[static_cast(step) * order + step]; + if (std::abs(diagonal) <= 1.0e-300) { + return false; + } + for (int row = step + 1; row < order; ++row) { + const double factor = (*matrix)[static_cast(row) * order + step] / diagonal; + (*matrix)[static_cast(row) * order + step] = factor; + for (int column = step + 1; column < order; ++column) { + (*matrix)[static_cast(row) * order + column] -= + factor * (*matrix)[static_cast(step) * order + column]; + } + } + } + for (int column = 0; column < columns; ++column) { + for (int step = 0; step < order; ++step) { + const int source = pivot[static_cast(step)]; + if (source != step) { + std::swap((*rhs)[static_cast(step) * columns + column], + (*rhs)[static_cast(source) * columns + column]); + } + } + for (int row = 1; row < order; ++row) { + double sum = (*rhs)[static_cast(row) * columns + column]; + for (int column2 = 0; column2 < row; ++column2) { + sum -= (*matrix)[static_cast(row) * order + column2] * + (*rhs)[static_cast(column2) * columns + column]; + } + (*rhs)[static_cast(row) * columns + column] = sum; + } + for (int row = order - 1; row >= 0; --row) { + double sum = (*rhs)[static_cast(row) * columns + column]; + for (int column2 = row + 1; column2 < order; ++column2) { + sum -= (*matrix)[static_cast(row) * order + column2] * + (*rhs)[static_cast(column2) * columns + column]; + } + (*rhs)[static_cast(row) * columns + column] = + sum / (*matrix)[static_cast(row) * order + row]; + } + } + return true; +} + +// ---------------------------------------------------- spherical harmonics --- + +// P_degree^order(x) with the Condon-Shortley phase (spherical_harmonics.py). +double associated_legendre(int order, int degree, double x) { + double p_mm = 1.0; + if (order != 0) { + double double_factorial = 1.0; + for (int value = 1; value < 2 * order; value += 2) { + double_factorial *= static_cast(value); + } + p_mm = (order % 2 == 0 ? 1.0 : -1.0) * double_factorial * + std::pow(std::max(0.0, 1.0 - x * x), 0.5 * static_cast(order)); + } + if (degree == order) { + return p_mm; + } + double previous_previous = p_mm; + double previous = x * static_cast(2 * order + 1) * p_mm; + if (degree == order + 1) { + return previous; + } + for (int current = order + 2; current <= degree; ++current) { + const double value = + (static_cast(2 * current - 1) * x * previous - + static_cast(current + order - 1) * previous_previous) / + static_cast(current - order); + previous_previous = previous; + previous = value; + } + return previous; +} + +double factorial(int value) { + double result = 1.0; + for (int index = 2; index <= value; ++index) { + result *= static_cast(index); + } + return result; +} + +// [M, (order+1)^2] orthonormal real harmonics in ACN order. +void real_spherical_harmonics(const std::vector& directions, std::size_t count, int order, + std::vector* basis) { + const std::size_t terms = static_cast((order + 1) * (order + 1)); + basis->assign(count * terms, 0.0); + for (std::size_t point = 0u; point < count; ++point) { + double unit[3] = {directions[point * 3u], directions[point * 3u + 1u], + directions[point * 3u + 2u]}; + if (!normalize3(unit)) { + unit[0] = 1.0; + unit[1] = 0.0; + unit[2] = 0.0; + } + const double azimuth = std::atan2(unit[1], unit[0]); + const double cos_colatitude = std::min(1.0, std::max(-1.0, unit[2])); + std::size_t column = 0u; + for (int degree = 0; degree <= order; ++degree) { + for (int m = -degree; m <= degree; ++m) { + const int absolute = std::abs(m); + const double normalization = + std::sqrt((2.0 * static_cast(degree) + 1.0) / (4.0 * kPi) * + factorial(degree - absolute) / factorial(degree + absolute)); + const double legendre = associated_legendre(absolute, degree, cos_colatitude); + double value = 0.0; + if (m < 0) { + value = std::sqrt(2.0) * normalization * legendre * + std::sin(static_cast(absolute) * azimuth); + } else if (m > 0) { + value = std::sqrt(2.0) * normalization * legendre * + std::cos(static_cast(m) * azimuth); + } else { + value = normalization * legendre; + } + (*basis)[point * terms + column] = value; + ++column; + } + } + } +} + +// Area weights of an irregular full-sphere grid (spherical_harmonics.py). +// +// The Voronoi cell of p_i is the intersection of the hemispheres +// dot(x, p_i - p_j) >= 0. Projected gnomonicly onto the tangent plane at p_i +// that intersection is a convex polygon of half-planes, so the cell can be +// clipped directly without building a convex hull: this has no triangulation +// ambiguity on cocircular grids (latitude rings) and reproduces the reference's +// spherical Voronoi areas to roundoff. The spherical area is the solid-angle fan +// from p_i over the cell's corners. +std::vector spherical_voronoi_weights(const std::vector& directions, + std::size_t count) { + std::vector weights(count, 1.0 / static_cast(count)); + if (count < 4u) { + return weights; + } + constexpr double kBox = 4.0; // a cap of ~76 degrees: far larger than any cell + std::vector areas(count, 0.0); + std::vector> polygon; + std::vector> clipped; + for (std::size_t point = 0u; point < count; ++point) { + double p[3] = {directions[point * 3u], directions[point * 3u + 1u], + directions[point * 3u + 2u]}; + if (!normalize3(p)) { + return weights; + } + double helper[3] = {0.0, 0.0, 1.0}; + if (std::abs(p[2]) >= 0.9) { + helper[0] = 1.0; + helper[2] = 0.0; + } + double east[3]; + double north[3]; + cross3(helper, p, east); + if (!normalize3(east)) { + return weights; + } + cross3(p, east, north); + + polygon.clear(); + polygon.emplace_back(-kBox, -kBox); + polygon.emplace_back(kBox, -kBox); + polygon.emplace_back(kBox, kBox); + polygon.emplace_back(-kBox, kBox); + for (std::size_t other = 0u; other < count && polygon.size() >= 3u; ++other) { + if (other == point) { + continue; + } + const double* q = directions.data() + other * 3u; + const double cosine = dot3(p, q); + const double a = dot3(east, q); + const double b = dot3(north, q); + clipped.clear(); + for (std::size_t index = 0u; index < polygon.size(); ++index) { + const std::pair& current = polygon[index]; + const std::pair& next = polygon[(index + 1u) % polygon.size()]; + const double value = (1.0 - cosine) - current.first * a - current.second * b; + const double next_value = (1.0 - cosine) - next.first * a - next.second * b; + if (value >= 0.0) { + clipped.push_back(current); + } + if ((value >= 0.0) != (next_value >= 0.0)) { + const double fraction = value / (value - next_value); + clipped.emplace_back(current.first + fraction * (next.first - current.first), + current.second + fraction * (next.second - current.second)); + } + } + polygon.swap(clipped); + } + if (polygon.size() < 3u) { + return weights; // a cell that does not close: keep the uniform fallback + } + double area = 0.0; + for (std::size_t index = 0u; index < polygon.size(); ++index) { + const std::pair& current = polygon[index]; + const std::pair& next = polygon[(index + 1u) % polygon.size()]; + double first[3] = {p[0] + current.first * east[0] + current.second * north[0], + p[1] + current.first * east[1] + current.second * north[1], + p[2] + current.first * east[2] + current.second * north[2]}; + double second[3] = {p[0] + next.first * east[0] + next.second * north[0], + p[1] + next.first * east[1] + next.second * north[1], + p[2] + next.first * east[2] + next.second * north[2]}; + if (!normalize3(first) || !normalize3(second)) { + return weights; + } + double cross[3]; + cross3(first, second, cross); + const double determinant = dot3(p, cross); + const double denominator = + 1.0 + dot3(p, first) + dot3(first, second) + dot3(second, p); + area += std::abs(2.0 * std::atan2(determinant, denominator)); + } + if (!std::isfinite(area) || area <= 0.0) { + return weights; + } + areas[point] = area; + } + double sum = 0.0; + for (const double area : areas) { + sum += area; + } + if (!(sum > 0.0) || !std::isfinite(sum)) { + return weights; + } + for (std::size_t point = 0u; point < count; ++point) { + weights[point] = areas[point] / sum; + } + return weights; +} +// ---------------------------------------------------------- coordinates ----- + +double length_factor(const std::string& token, bool* found) { + static const std::pair kTable[] = { + {"m", 1.0}, {"metre", 1.0}, {"metres", 1.0}, {"meter", 1.0}, + {"meters", 1.0}, {"cm", 1.0e-2}, {"centimetre", 1.0e-2}, {"centimetres", 1.0e-2}, + {"centimeter", 1.0e-2}, {"centimeters", 1.0e-2}, {"mm", 1.0e-3}, {"millimetre", 1.0e-3}, + {"millimetres", 1.0e-3}, {"millimeter", 1.0e-3}, {"millimeters", 1.0e-3}, + }; + for (const auto& entry : kTable) { + if (token == entry.first) { + *found = true; + return entry.second; + } + } + *found = false; + return 0.0; +} + +bool angle_in_radians(const std::string& token, double value, double* out) { + if (token == "degree" || token == "degrees") { + *out = value * (kPi / 180.0); + return true; + } + if (token == "radian" || token == "radians") { + *out = value; + return true; + } + return false; +} + +std::vector split_units(const std::string& units) { + std::vector tokens; + std::string current; + for (const char character : units) { + if (character == ',') { + const std::size_t begin = current.find_first_not_of(" \t"); + const std::size_t end = current.find_last_not_of(" \t"); + if (begin != std::string::npos) { + std::string token = current.substr(begin, end - begin + 1u); + std::transform(token.begin(), token.end(), token.begin(), + [](unsigned char value) { + return static_cast(std::tolower(value)); + }); + tokens.push_back(token); + } + current.clear(); + } else { + current.push_back(character); + } + } + const std::size_t begin = current.find_first_not_of(" \t"); + const std::size_t end = current.find_last_not_of(" \t"); + if (begin != std::string::npos) { + std::string token = current.substr(begin, end - begin + 1u); + std::transform(token.begin(), token.end(), token.begin(), [](unsigned char value) { + return static_cast(std::tolower(value)); + }); + tokens.push_back(token); + } + return tokens; +} + +std::string lowered(const std::string& text) { + std::string result = text; + const std::size_t begin = result.find_first_not_of(" \t"); + const std::size_t end = result.find_last_not_of(" \t"); + result = begin == std::string::npos ? std::string() : result.substr(begin, end - begin + 1u); + std::transform(result.begin(), result.end(), result.begin(), [](unsigned char value) { + return static_cast(std::tolower(value)); + }); + return result; +} + +// coordinates_to_cartesian_m: spherical or Cartesian rows to metres, in place. +Status convert_coordinates(const std::vector& values, std::size_t rows, + const std::string& type, const std::string& units, + const std::string& variable, std::vector* out) { + if (values.size() != rows * 3u) { + return field_fail(JOC_ERR_HRTF_FORMAT, variable + " must contain finite C=3 coordinates"); + } + for (const double value : values) { + if (!std::isfinite(value)) { + return field_fail(JOC_ERR_HRTF_FORMAT, + variable + " must contain finite C=3 coordinates"); + } + } + const std::string kind = lowered(type); + const std::vector tokens = split_units(units); + out->assign(values.size(), 0.0); + if (kind == "cartesian") { + double factors[3] = {0.0, 0.0, 0.0}; + if (tokens.size() == 1u) { + bool found = false; + const double factor = length_factor(tokens[0], &found); + if (!found) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "unsupported Cartesian units for " + variable + ": " + units); + } + factors[0] = factors[1] = factors[2] = factor; + } else if (tokens.size() == 3u) { + for (int axis = 0; axis < 3; ++axis) { + bool found = false; + factors[axis] = length_factor(tokens[static_cast(axis)], &found); + if (!found) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "unsupported Cartesian units for " + variable + ": " + units); + } + } + } else { + return field_fail(JOC_ERR_HRTF_FORMAT, + "unsupported Cartesian units for " + variable + ": " + units); + } + for (std::size_t row = 0u; row < rows; ++row) { + for (int axis = 0; axis < 3; ++axis) { + (*out)[row * 3u + static_cast(axis)] = + values[row * 3u + static_cast(axis)] * factors[axis]; + } + } + return Status::success(); + } + if (kind != "spherical" || tokens.size() != 3u) { + return field_fail(JOC_ERR_HRTF_FORMAT, "unsupported coordinates for " + variable + + ": Type=" + type + ", Units=" + units); + } + bool radius_found = false; + const double radius_factor = length_factor(tokens[2], &radius_found); + if (!radius_found) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "unsupported spherical radius unit for " + variable + ": " + units); + } + for (std::size_t row = 0u; row < rows; ++row) { + double azimuth = 0.0; + double elevation = 0.0; + if (!angle_in_radians(tokens[0], values[row * 3u], &azimuth) || + !angle_in_radians(tokens[1], values[row * 3u + 1u], &elevation)) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "unsupported spherical angle units for " + variable + ": " + units); + } + const double radius = values[row * 3u + 2u] * radius_factor; + if (radius < 0.0) { + return field_fail(JOC_ERR_HRTF_FORMAT, + variable + " contains a negative spherical radius"); + } + const double horizontal = std::cos(elevation); + (*out)[row * 3u] = radius * horizontal * std::cos(azimuth); + (*out)[row * 3u + 1u] = radius * horizontal * std::sin(azimuth); + (*out)[row * 3u + 2u] = radius * std::sin(elevation); + } + return Status::success(); +} + +// ------------------------------------------------------------- JSON --------- + +std::string json_escape(const std::string& text) { + std::string out = "\""; + for (const char character : text) { + const unsigned char value = static_cast(character); + switch (character) { + case '"': out += "\\\""; break; + case '\\': out += "\\\\"; break; + case '\n': out += "\\n"; break; + case '\r': out += "\\r"; break; + case '\t': out += "\\t"; break; + case '\b': out += "\\b"; break; + case '\f': out += "\\f"; break; + default: + if (value < 0x20u) { + char buffer[8]; + std::snprintf(buffer, sizeof(buffer), "\\u%04x", value); + out += buffer; + } else { + out.push_back(character); + } + break; + } + } + out += "\""; + return out; +} + +std::string json_number(double value) { return io::python_float_repr(value); } + +// Python's float.hex(), the representation json.dumps uses for the cache-key +// payload, so the key matches the reference byte for byte. +std::string python_hex(double value) { + if (std::isnan(value)) { + return "nan"; + } + if (std::isinf(value)) { + return value > 0.0 ? "inf" : "-inf"; + } + if (value == 0.0) { + return std::signbit(value) ? "-0x0.0p+0" : "0x0.0p+0"; + } + std::uint64_t bits = 0u; + std::memcpy(&bits, &value, sizeof(bits)); + const bool negative = (bits >> 63u) != 0u; + const int exponent = static_cast((bits >> 52u) & 0x7FFu); + const std::uint64_t mantissa = bits & 0xFFFFFFFFFFFFFull; + char buffer[40]; + if (exponent == 0) { + std::snprintf(buffer, sizeof(buffer), "%s0x0.%013llxp-1022", negative ? "-" : "", + static_cast(mantissa)); + } else { + std::snprintf(buffer, sizeof(buffer), "%s0x1.%013llxp%+d", negative ? "-" : "", + static_cast(mantissa), exponent - 1023); + } + return buffer; +} + +using JsonMembers = std::vector>; + +std::string json_object(JsonMembers members) { + std::sort(members.begin(), members.end(), + [](const std::pair& left, + const std::pair& right) { + return left.first < right.first; + }); + std::string out = "{"; + for (std::size_t index = 0u; index < members.size(); ++index) { + if (index != 0u) { + out += ","; + } + out += json_escape(members[index].first) + ":" + members[index].second; + } + out += "}"; + return out; +} + +std::string json_array(const std::vector& values) { + std::string out = "["; + for (std::size_t index = 0u; index < values.size(); ++index) { + if (index != 0u) { + out += ","; + } + out += values[index]; + } + out += "]"; + return out; +} + +// ------------------------------------------------------- cache contract ----- + +std::string sha256_hex_upper(const void* data, std::size_t size) { + crypto::Sha256 hash; + hash.update(data, size); + std::string digest = hash.finish_hex(); + std::transform(digest.begin(), digest.end(), digest.begin(), [](unsigned char value) { + return static_cast(std::toupper(value)); + }); + return digest; +} + +std::string to_upper(std::string text) { + std::transform(text.begin(), text.end(), text.begin(), [](unsigned char value) { + return static_cast(std::toupper(value)); + }); + return text; +} + +// filterbank_fingerprint(): stable identifiers of the embedded public tables. +std::string filterbank_fingerprint_json() { + const Kernels& kernels = builtin_kernels(); + auto hash_float32 = [](const std::vector& values) { + std::vector narrowed(values.size()); + for (std::size_t index = 0u; index < values.size(); ++index) { + narrowed[index] = static_cast(values[index]); + } + return sha256_hex_upper(narrowed.data(), narrowed.size() * sizeof(float)); + }; + auto hash_float64 = [](const std::vector& values) { + return sha256_hex_upper(values.data(), values.size() * sizeof(double)); + }; + const std::string band_centers_sha = + sha256_hex_upper(kBandCenters, static_cast(kHybridBands) * sizeof(double)); + const JsonMembers arrays = { + // The fingerprint also covers the archive's format_version member. + {"format_version", + json_escape(sha256_hex_upper(&kFilterbankFormatVersion, sizeof(kFilterbankFormatVersion)))}, + {"hybrid_analysis_low_kernel", json_escape(hash_float32(kernels.hybrid_low))}, + {"hybrid_synthesis_indices", + json_escape(sha256_hex_upper(kernels.hybrid_indices.data(), + kernels.hybrid_indices.size() * sizeof(std::int16_t)))}, + {"hybrid_synthesis_values", json_escape(hash_float32(kernels.hybrid_values))}, + {"qmf_analysis_coefficients", json_escape(hash_float32(kernels.qmf_analysis))}, + {"qmf_synthesis_basis", json_escape(hash_float64(kernels.qmf_basis))}, + {"qmf_synthesis_taps", json_escape(hash_float64(kernels.qmf_taps))}, + }; + return json_object({ + {"archive_sha256", json_escape(kFilterbankArchiveSha256)}, + {"array_sha256", json_object(arrays)}, + {"band_centers_sha256", json_escape(band_centers_sha)}, + {"table_version", json_escape(kFilterbankTableVersion)}, + }); +} + +} // namespace + +std::vector hybrid_gain_synthesis_dictionary_for_check(std::size_t sample_count) { + return hybrid_gain_synthesis_dictionary(sample_count, builtin_kernels()); +} + +std::vector analysis_impulse_for_check(std::size_t total_samples) { + const std::size_t slots = total_samples / kQmfHop; + std::vector impulse(total_samples, 0.0); + impulse[0] = 1.0; + PublicFilterbank bank(builtin_kernels(), 1u); + std::vector base; + bank.analyze_full_rate(impulse, slots, &base); + std::vector out(base.size() * 2u, 0.0); + for (std::size_t index = 0u; index < base.size(); ++index) { + out[index * 2u] = base[index].real(); + out[index * 2u + 1u] = base[index].imag(); + } + return out; +} + +const std::vector& hybrid_band_center_frequencies_hz() { + static const std::vector centers(kBandCenters, kBandCenters + kHybridBands); + return centers; +} + +std::string compiled_hrtf_cache_key(const std::string& source_sha256, double sample_rate_hz, + double shell_radius_m, int order, double projection_ridge, + double sh_ridge) { + const std::string payload = json_object({ + {"compiler_version", json_escape(kCompilerVersion)}, + {"filterbank", filterbank_fingerprint_json()}, + {"order", std::to_string(order)}, + {"phase_policy_version", json_escape(kPhasePolicyVersion)}, + {"projection_ridge", json_escape(python_hex(projection_ridge))}, + {"sh_convention", json_escape(kShConvention)}, + {"shell_radius_m", json_escape(python_hex(shell_radius_m))}, + {"source_sha256", json_escape(to_upper(source_sha256))}, + {"spherical_harmonic_ridge", json_escape(python_hex(sh_ridge))}, + {"target_sample_rate_hz", json_escape(python_hex(sample_rate_hz))}, + }); + const std::string encoded = std::string("JOC-HRTF-CACHE-KEY-V1\0", 22u) + payload; + return to_upper(sha256_hex_upper(encoded.data(), encoded.size())); +} + +std::string field_payload_sha256(const Field& field) { + crypto::Sha256 hash; + const char prefix[] = "JOC-HRTF-CACHE-PAYLOAD-V1"; + hash.update(prefix, sizeof(prefix) - 1u); + const std::uint8_t zero = 0u; + hash.update(&zero, 1u); + auto feed = [&](const char* name, const char* dtype, const std::string& shape, + const void* data, std::size_t size) { + const std::string name_text(name); + const std::string dtype_text(dtype); + hash.update(name_text.data(), name_text.size()); + hash.update(&zero, 1u); + hash.update(dtype_text.data(), dtype_text.size()); + hash.update(&zero, 1u); + hash.update(shape.data(), shape.size()); + hash.update(&zero, 1u); + hash.update(data, size); + }; + feed("band_center_frequencies_hz", "= 'A' && character <= 'Z') || + (character >= 'a' && character <= 'z') || + (character >= '0' && character <= '9') || character == '.' || + character == '_' || character == '-'; + safe.push_back(allowed ? character : '_'); + } + const std::size_t begin = safe.find_first_not_of("._"); + const std::size_t end = safe.find_last_not_of("._"); + safe = begin == std::string::npos ? std::string() : safe.substr(begin, end - begin + 1u); + if (safe.empty()) { + safe = "hrtf"; + } + return safe + "." + cache_key.substr(0u, 20u) + ".jochrtf"; +} + +Status write_jochrtf(const Field& field, const std::string& path) { + if (field.metadata_json.empty() || field.payload_sha256.empty()) { + return field_fail(JOC_ERR_INVALID_ARGUMENT, + "compiled HRTF field has no metadata to write"); + } + std::vector members; + auto add_real = [&](const char* name, const std::vector& values, + std::vector shape) { + io::NpyMember member; + member.name = name; + member.descr = "& basis, std::size_t count, int terms, + const std::vector& weights, double ridge, + std::vector* system, std::vector* weighted_basis) { + weighted_basis->assign(count * static_cast(terms), 0.0); + for (std::size_t row = 0u; row < count; ++row) { + for (int term = 0; term < terms; ++term) { + (*weighted_basis)[row * static_cast(terms) + static_cast(term)] = + basis[row * static_cast(terms) + static_cast(term)] * + weights[row]; + } + } + system->assign(static_cast(terms) * static_cast(terms), 0.0); + for (std::size_t row = 0u; row < count; ++row) { + for (int left = 0; left < terms; ++left) { + const double value = + basis[row * static_cast(terms) + static_cast(left)]; + if (value == 0.0) { + continue; + } + for (int right = 0; right < terms; ++right) { + (*system)[static_cast(left) * static_cast(terms) + + static_cast(right)] += + value * (*weighted_basis)[row * static_cast(terms) + + static_cast(right)]; + } + } + } + double trace = 0.0; + for (int term = 0; term < terms; ++term) { + trace += (*system)[static_cast(term) * static_cast(terms) + + static_cast(term)]; + } + const double scale = trace / static_cast(terms); + for (int term = 0; term < terms; ++term) { + (*system)[static_cast(term) * static_cast(terms) + + static_cast(term)] += ridge * scale; + } +} + +// fit_real_spherical_harmonics for complex targets: [terms, columns]. +std::vector fit_complex(const std::vector& basis, std::size_t count, int terms, + const std::vector& weights, double ridge, + const std::vector& values, std::size_t columns) { + std::vector system; + std::vector weighted_basis; + normal_system(basis, count, terms, weights, ridge, &system, &weighted_basis); + std::vector matrix(system.size()); + for (std::size_t index = 0u; index < system.size(); ++index) { + matrix[index] = Complex(system[index], 0.0); + } + std::vector right(static_cast(terms) * columns, Complex(0.0, 0.0)); + for (std::size_t row = 0u; row < count; ++row) { + for (int term = 0; term < terms; ++term) { + const double basis_value = + basis[row * static_cast(terms) + static_cast(term)]; + if (basis_value == 0.0) { + continue; + } + for (std::size_t column = 0u; column < columns; ++column) { + right[static_cast(term) * columns + column] += + basis_value * weights[row] * values[row * columns + column]; + } + } + } + lu_solve_complex(&matrix, terms, &right, static_cast(columns)); + return right; +} + +// fit_real_spherical_harmonics for real targets: [terms, columns]. +std::vector fit_real(const std::vector& basis, std::size_t count, int terms, + const std::vector& weights, double ridge, + const std::vector& values, std::size_t columns) { + std::vector system; + std::vector weighted_basis; + normal_system(basis, count, terms, weights, ridge, &system, &weighted_basis); + std::vector right(static_cast(terms) * columns, 0.0); + for (std::size_t row = 0u; row < count; ++row) { + for (int term = 0; term < terms; ++term) { + const double basis_value = + basis[row * static_cast(terms) + static_cast(term)]; + if (basis_value == 0.0) { + continue; + } + for (std::size_t column = 0u; column < columns; ++column) { + right[static_cast(term) * columns + column] += + basis_value * weights[row] * values[row * columns + column]; + } + } + } + lu_solve_real(&system, terms, &right, static_cast(columns)); + return right; +} + +// --------------------------------------------------------- time alignment --- + +// sofa_canonical._subsample_peak: parabolic peak of |values|. +double subsample_peak(const std::vector& values) { + std::size_t index = 0u; + double magnitude = -1.0; + for (std::size_t position = 0u; position < values.size(); ++position) { + const double current = std::abs(values[position]); + if (current > magnitude) { + magnitude = current; + index = position; + } + } + if (index == 0u || index + 1u >= values.size()) { + return static_cast(index); + } + const double previous = std::abs(values[index - 1u]); + const double current = std::abs(values[index]); + const double next = std::abs(values[index + 1u]); + const double denominator = previous - 2.0 * current + next; + double correction = 0.0; + if (std::abs(denominator) >= 1.0e-30) { + correction = 0.5 * (previous - next) / denominator; + } + correction = std::min(0.5, std::max(-0.5, correction)); + return static_cast(index) + correction; +} + +struct AlignedHrtf { + std::vector aligned; // [M,2,N] + std::vector runtime_delay; // [M,2] + std::vector embedded_removed; // [M,2] + std::string delay_source; +}; + +// sofa_canonical.time_align_hrtf: separate exactly one delay representation. +AlignedHrtf time_align_hrtf(const CanonicalHrtf& canonical) { + AlignedHrtf result; + const std::size_t measurements = canonical.measurements; + const std::size_t taps = canonical.taps; + result.aligned = canonical.hrir; + result.runtime_delay.assign(measurements * 2u, 0.0); + result.embedded_removed.assign(measurements * 2u, 0.0); + double maximum = 0.0; + for (const double value : canonical.delay_samples) { + maximum = std::max(maximum, std::abs(value)); + } + if (maximum > 1.0e-12) { + result.runtime_delay = canonical.delay_samples; + result.delay_source = "Data.Delay (external; applied once at render time)"; + return result; + } + std::size_t used_peak = 0u; + std::size_t retained = 0u; + std::vector ear(taps, 0.0); + // hrir[measurement][channel] as a tap range. + auto ear_range = [&](std::size_t measurement, int channel) { + const std::size_t first = (measurement * 2u + static_cast(channel)) * taps; + return std::make_pair(canonical.hrir.begin() + static_cast(first), + canonical.hrir.begin() + static_cast(first + taps)); + }; + for (std::size_t measurement = 0u; measurement < measurements; ++measurement) { + double peaks[2] = {0.0, 0.0}; + for (int channel = 0; channel < 2; ++channel) { + const auto range = ear_range(measurement, channel); + std::copy(range.first, range.second, ear.begin()); + peaks[channel] = subsample_peak(ear); + } + if (std::max(peaks[0], peaks[1]) > 2.0) { + ++used_peak; + } else { + peaks[0] = 0.0; + peaks[1] = 0.0; + ++retained; + } + for (int channel = 0; channel < 2; ++channel) { + const std::size_t ear_index = measurement * 2u + static_cast(channel); + result.runtime_delay[ear_index] = peaks[channel]; + result.embedded_removed[ear_index] = peaks[channel]; + if (peaks[channel] != 0.0) { + const auto range = ear_range(measurement, channel); + std::copy(range.first, range.second, ear.begin()); + const std::vector shifted = shift_signal_fft(ear, -peaks[channel]); + std::copy(shifted.begin(), shifted.end(), + result.aligned.begin() + static_cast(ear_index * taps)); + } + } + } + result.delay_source = "embedded Data.IR arrival separation: peak=" + + std::to_string(used_peak) + + ", zero-origin embedded phase retained=" + std::to_string(retained) + + "; positive onset restored once at render time"; + return result; +} + +// ------------------------------------------------------------- pipeline ----- + +// canonical.shell_indices: the measurements on the shell nearest to radius_m. +} // namespace + +std::vector canonical_shell_indices(const CanonicalHrtf& canonical, double radius_m, + double* actual_radius_m) { + std::vector shells; + for (const double radius : canonical.measurement_radius_m) { + const double rounded = round_half_even(radius, 9); + if (std::find(shells.begin(), shells.end(), rounded) == shells.end()) { + shells.push_back(rounded); + } + } + std::sort(shells.begin(), shells.end()); + double shell = shells.empty() ? radius_m : shells.front(); + double best = std::numeric_limits::infinity(); + for (const double candidate : shells) { + const double distance = std::abs(candidate - radius_m); + if (distance < best) { + best = distance; + shell = candidate; + } + } + std::vector indices; + double total = 0.0; + for (std::size_t index = 0u; index < canonical.measurement_radius_m.size(); ++index) { + if (std::abs(canonical.measurement_radius_m[index] - shell) <= 5.0e-7) { + indices.push_back(index); + total += canonical.measurement_radius_m[index]; + } + } + *actual_radius_m = indices.empty() ? shell : total / static_cast(indices.size()); + return indices; +} + +namespace { + +// _group_coincident: merge measurements that share a direction (keys are the +// directions rounded to ten decimals, grouped in sorted key order). +void group_coincident(const std::vector& directions, std::size_t count, + const std::vector& gains, std::size_t columns, + const std::vector& delays, std::vector* out_directions, + std::vector* out_gains, std::vector* out_delays) { + struct Key { + double value[3]; + std::size_t first; + }; + std::vector keys(count); + for (std::size_t index = 0u; index < count; ++index) { + for (int axis = 0; axis < 3; ++axis) { + keys[index].value[axis] = + round_half_even(directions[index * 3u + static_cast(axis)], 10); + } + keys[index].first = index; + } + std::sort(keys.begin(), keys.end(), [](const Key& left, const Key& right) { + for (int axis = 0; axis < 3; ++axis) { + if (left.value[axis] != right.value[axis]) { + return left.value[axis] < right.value[axis]; + } + } + return left.first < right.first; + }); + std::vector unique; + std::vector group_of(count, 0u); + for (const Key& key : keys) { + if (unique.empty() || unique.back().value[0] != key.value[0] || + unique.back().value[1] != key.value[1] || unique.back().value[2] != key.value[2]) { + unique.push_back(key); + } else if (key.first < unique.back().first) { + unique.back().first = key.first; + } + group_of[key.first] = unique.size() - 1u; + } + const std::size_t groups = unique.size(); + out_directions->assign(groups * 3u, 0.0); + out_gains->assign(groups * columns, Complex(0.0, 0.0)); + out_delays->assign(groups * 2u, 0.0); + std::vector counts(groups, 0.0); + for (std::size_t index = 0u; index < count; ++index) { + const std::size_t group = group_of[index]; + ++counts[group]; + for (int axis = 0; axis < 3; ++axis) { + (*out_directions)[group * 3u + static_cast(axis)] += + directions[index * 3u + static_cast(axis)]; + } + for (std::size_t column = 0u; column < columns; ++column) { + (*out_gains)[group * columns + column] += gains[index * columns + column]; + } + for (std::size_t ear = 0u; ear < 2u; ++ear) { + (*out_delays)[group * 2u + ear] += delays[index * 2u + ear]; + } + } + for (std::size_t group = 0u; group < groups; ++group) { + for (std::size_t column = 0u; column < columns; ++column) { + (*out_gains)[group * columns + column] /= counts[group]; + } + for (std::size_t ear = 0u; ear < 2u; ++ear) { + (*out_delays)[group * 2u + ear] /= counts[group]; + } + } +} + +std::string basename_of(const std::string& path) { + const std::size_t slash = path.find_last_of("/\\"); + return slash == std::string::npos ? path : path.substr(slash + 1u); +} + +// sofa_canonical._processing_label: the non-empty identifying attributes. +std::string processing_label(const SofaHrir& sofa) { + std::vector parts; + const std::string candidates[4] = {sofa.database_name, sofa.title, sofa.listener_short_name, + sofa.comment}; + for (const std::string& value : candidates) { + const std::size_t begin = value.find_first_not_of(" \t"); + const std::size_t end = value.find_last_not_of(" \t"); + if (begin == std::string::npos) { + continue; + } + const std::string trimmed = value.substr(begin, end - begin + 1u); + if (std::find(parts.begin(), parts.end(), trimmed) == parts.end()) { + parts.push_back(trimmed); + } + } + std::string label; + for (std::size_t index = 0u; index < parts.size(); ++index) { + if (index != 0u) { + label += " | "; + } + label += parts[index]; + } + return label; +} + +double minimum_of(const std::vector& values) { + double result = std::numeric_limits::infinity(); + for (const double value : values) { + result = std::min(result, value); + } + return values.empty() ? 0.0 : result; +} + +double maximum_of(const std::vector& values) { + double result = -std::numeric_limits::infinity(); + for (const double value : values) { + result = std::max(result, value); + } + return values.empty() ? 0.0 : result; +} + +} // namespace + +Status canonicalize_sofa(const SofaHrir& sofa, CanonicalHrtf* out) { + if (out == nullptr) { + return field_fail(JOC_ERR_INVALID_ARGUMENT, "null canonical HRTF destination"); + } + if (sofa.conventions != "SOFA") { + return field_fail(JOC_ERR_HRTF_UNSUPPORTED_CONVENTION, "Conventions must be SOFA"); + } + if (sofa.sofa_conventions != "SimpleFreeFieldHRIR") { + return field_fail(JOC_ERR_HRTF_UNSUPPORTED_CONVENTION, + "unsupported SOFAConventions=" + sofa.sofa_conventions + + "; convert explicitly first"); + } + if (sofa.convention_version != "0.4" && sofa.convention_version != "1.0" && + sofa.convention_version != "1.1") { + return field_fail(JOC_ERR_HRTF_UNSUPPORTED_CONVENTION, + "unsupported SimpleFreeFieldHRIR version " + sofa.convention_version); + } + if (sofa.data_type != "FIR") { + return field_fail(JOC_ERR_HRTF_FORMAT, "DataType must be FIR"); + } + const std::string room_type = lowered(sofa.room_type); + if (room_type != "free field" && room_type != "free-field" && room_type != "anechoic" && + room_type != "hemi-anechoic") { + return field_fail(JOC_ERR_HRTF_FORMAT, + "RoomType must explicitly be free-field, got " + sofa.room_type); + } + const std::size_t measurements = sofa.ir_count; + const std::size_t taps = sofa.ir_length; + if (measurements == 0u || taps == 0u || sofa.ir.size() != measurements * 2u * taps) { + return field_fail(JOC_ERR_HRTF_FORMAT, "Data.IR must have shape [M,R=2,N]"); + } + for (const double value : sofa.ir) { + if (!std::isfinite(value)) { + return field_fail(JOC_ERR_HRTF_FORMAT, "Data.IR contains non-finite values"); + } + } + if (!std::isfinite(sofa.sample_rate) || sofa.sample_rate <= 0.0) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "Data.SamplingRate must contain one positive finite value"); + } + const std::string rate_units = lowered(sofa.sampling_rate_units); + if (rate_units != "hertz" && rate_units != "hz") { + return field_fail(JOC_ERR_HRTF_FORMAT, + "Data.SamplingRate Units must be hertz, got " + sofa.sampling_rate_units); + } + std::vector delay(2u, 0.0); + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const double value = sofa.delay[ear]; + if (!std::isfinite(value)) { + return field_fail(JOC_ERR_HRTF_FORMAT, "Data.Delay must be finite"); + } + if (value < -1.0e-9) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "negative Data.Delay is outside the supported causal contract"); + } + delay[ear] = std::max(0.0, value); + } + + const std::vector emitter_values(sofa.emitter_position, + sofa.emitter_position + 3); + std::vector emitter; + Status status = convert_coordinates(emitter_values, 1u, sofa.emitter_position_coordinates.type, + sofa.emitter_position_coordinates.units, "EmitterPosition", + &emitter); + if (!status.ok()) { + return status; + } + for (const double value : emitter) { + if (std::abs(value) > 1.0e-9) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "non-zero EmitterPosition needs a separate source-pose adapter"); + } + } + + const std::vector position_values(sofa.listener_position, + sofa.listener_position + 3); + const std::vector view_values(sofa.listener_view, sofa.listener_view + 3); + const std::vector up_values(sofa.listener_up, sofa.listener_up + 3); + std::vector listener_position; + std::vector listener_view; + std::vector listener_up_raw; + status = convert_coordinates(position_values, 1u, sofa.listener_position_coordinates.type, + sofa.listener_position_coordinates.units, "ListenerPosition", + &listener_position); + if (!status.ok()) { + return status; + } + status = convert_coordinates(view_values, 1u, sofa.listener_view_coordinates.type, + sofa.listener_view_coordinates.units, "ListenerView", &listener_view); + if (!status.ok()) { + return status; + } + // ListenerUp inherits ListenerView's Type/Units when it declares none. + const std::string up_type = sofa.listener_up_coordinates.type.empty() ? sofa.listener_view_coordinates.type + : sofa.listener_up_coordinates.type; + const std::string up_units = sofa.listener_up_coordinates.units.empty() + ? sofa.listener_view_coordinates.units + : sofa.listener_up_coordinates.units; + status = convert_coordinates(up_values, 1u, up_type, up_units, "ListenerUp", &listener_up_raw); + if (!status.ok()) { + return status; + } + double forward[3] = {listener_view[0], listener_view[1], listener_view[2]}; + if (!normalize3(forward)) { + return field_fail(JOC_ERR_HRTF_FORMAT, "ListenerView must be non-zero"); + } + double left[3]; + cross3(listener_up_raw.data(), forward, left); + if (!normalize3(left)) { + return field_fail(JOC_ERR_HRTF_FORMAT, "ListenerUp must not be parallel to ListenerView"); + } + double up[3]; + cross3(forward, left, up); + + std::vector source_world; + status = convert_coordinates(sofa.source_position, measurements, sofa.source_position_coordinates.type, + sofa.source_position_coordinates.units, "SourcePosition", + &source_world); + if (!status.ok()) { + return status; + } + if (source_world.size() != measurements * 3u) { + return field_fail(JOC_ERR_HRTF_FORMAT, "SourcePosition must have shape [M,C=3]"); + } + std::vector source_local(measurements * 3u, 0.0); + std::vector radii(measurements, 0.0); + for (std::size_t row = 0u; row < measurements; ++row) { + const double relative[3] = {source_world[row * 3u] - listener_position[0], + source_world[row * 3u + 1u] - listener_position[1], + source_world[row * 3u + 2u] - listener_position[2]}; + source_local[row * 3u] = dot3(relative, forward); + source_local[row * 3u + 1u] = dot3(relative, left); + source_local[row * 3u + 2u] = dot3(relative, up); + radii[row] = std::sqrt(source_local[row * 3u] * source_local[row * 3u] + + source_local[row * 3u + 1u] * source_local[row * 3u + 1u] + + source_local[row * 3u + 2u] * source_local[row * 3u + 2u]); + if (!std::isfinite(radii[row]) || radii[row] <= 1.0e-8) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "every source measurement must have a positive radius"); + } + } + + // ReceiverPosition is [R=2,C=3,I]; the two receivers are converted separately + // so their units are validated the same way as every other coordinate row. + std::vector receiver_cartesian(6u, 0.0); + for (std::size_t receiver = 0u; receiver < 2u; ++receiver) { + const std::vector row(sofa.receiver_position + receiver * 3u, + sofa.receiver_position + receiver * 3u + 3u); + std::vector converted; + status = convert_coordinates(row, 1u, sofa.receiver_position_coordinates.type, + sofa.receiver_position_coordinates.units, "ReceiverPosition", + &converted); + if (!status.ok()) { + return status; + } + for (int axis = 0; axis < 3; ++axis) { + receiver_cartesian[receiver * 3u + static_cast(axis)] = + converted[static_cast(axis)]; + } + } + int left_index = 0; + int right_index = 1; + const double lateral = receiver_cartesian[1] - receiver_cartesian[4]; + if (lateral <= 1.0e-5) { + if (lateral >= -1.0e-5) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "ReceiverPosition does not identify one consistently-left and one " + "consistently-right receiver"); + } + left_index = 1; + right_index = 0; + } + + CanonicalHrtf canonical; + canonical.source_path = sofa.source_path; + canonical.source_sha256 = to_upper(sofa.source_sha256); + canonical.convention = sofa.sofa_conventions; + canonical.convention_version = sofa.convention_version; + canonical.processing_label = processing_label(sofa); + canonical.sample_rate_hz = sofa.sample_rate; + canonical.measurements = static_cast(measurements); + canonical.taps = static_cast(taps); + canonical.left_receiver_index = left_index; + canonical.right_receiver_index = right_index; + canonical.source_position_cartesian_m = source_local; + canonical.unit_directions.resize(measurements * 3u, 0.0); + for (std::size_t row = 0u; row < measurements; ++row) { + for (int axis = 0; axis < 3; ++axis) { + canonical.unit_directions[row * 3u + static_cast(axis)] = + source_local[row * 3u + static_cast(axis)] / radii[row]; + } + } + canonical.measurement_radius_m = radii; + canonical.hrir.assign(measurements * 2u * taps, 0.0); + canonical.delay_samples.assign(measurements * 2u, 0.0); + for (std::size_t row = 0u; row < measurements; ++row) { + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const std::size_t source_ear = ear == 0u ? static_cast(left_index) + : static_cast(right_index); + std::copy(sofa.ir.begin() + + static_cast((row * 2u + source_ear) * taps), + sofa.ir.begin() + + static_cast((row * 2u + source_ear + 1u) * taps), + canonical.hrir.begin() + static_cast((row * 2u + ear) * taps)); + canonical.delay_samples[row * 2u + ear] = delay[source_ear]; + } + } + *out = std::move(canonical); + return Status::success(); +} + +Status compile_canonical_field(const CanonicalHrtf& canonical, const CompileOptions& options, + Field* out) { + if (out == nullptr) { + return field_fail(JOC_ERR_INVALID_ARGUMENT, "null field destination"); + } + if (options.order != kFieldOrder) { + return field_fail(JOC_ERR_HRTF_FORMAT, "the runtime HRTF field is fixed at fifth order"); + } + if (!std::isfinite(canonical.sample_rate_hz) || + std::abs(canonical.sample_rate_hz - kFieldSampleRateHz) > 1.0e-9) { + return field_fail(JOC_ERR_HRTF_FORMAT, "SOFA HRTF fields must be compiled at 48 kHz"); + } + if (!std::isfinite(options.shell_radius_m) || options.shell_radius_m <= 0.0) { + return field_fail(JOC_ERR_HRTF_FORMAT, "shell_radius_m must be positive and finite"); + } + if (!std::isfinite(options.projection_ridge) || options.projection_ridge < 0.0 || + !std::isfinite(options.sh_ridge) || options.sh_ridge < 0.0) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "compiler ridge values must be finite and non-negative"); + } + if (canonical.measurements == 0u || canonical.taps == 0u) { + return field_fail(JOC_ERR_HRTF_FORMAT, "canonical HRTF is empty"); + } + const std::size_t terms = static_cast(kFieldTerms); + const std::size_t gains_per_direction = static_cast(kParameterCount); + const std::size_t columns = static_cast(kParameterCount); + + const AlignedHrtf aligned = time_align_hrtf(canonical); + double shell_radius = options.shell_radius_m; + const std::vector indices = + canonical_shell_indices(canonical, options.shell_radius_m, &shell_radius); + if (indices.size() < terms) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "fifth-order SH needs at least 36 measurements on one shell, got " + + std::to_string(indices.size())); + } + const std::size_t selected = indices.size(); + + // Project the selected HRIRs onto the public analysis/gain/synthesis dictionary. + const Kernels& kernels = builtin_kernels(); + const std::vector dictionary = hybrid_gain_synthesis_dictionary(canonical.taps, kernels); + std::vector system(columns * columns, 0.0); + for (std::size_t left = 0u; left < columns; ++left) { + for (std::size_t right = 0u; right < columns; ++right) { + double sum = 0.0; + for (std::size_t tap = 0u; tap < canonical.taps; ++tap) { + sum += dictionary[tap * columns + left] * dictionary[tap * columns + right]; + } + system[left * columns + right] = sum; + } + } + double trace = 0.0; + for (std::size_t parameter = 0u; parameter < columns; ++parameter) { + trace += system[parameter * columns + parameter]; + } + const double scale = trace / static_cast(columns); + for (std::size_t parameter = 0u; parameter < columns; ++parameter) { + system[parameter * columns + parameter] += options.projection_ridge * scale; + } + + // target[tap][measurement*2 + ear], the reference's reshape(-1, N).T. + const std::size_t target_columns = selected * 2u; + std::vector target(canonical.taps * target_columns, 0.0); + for (std::size_t row = 0u; row < selected; ++row) { + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const std::size_t column = row * 2u + ear; + for (std::size_t tap = 0u; tap < canonical.taps; ++tap) { + target[tap * target_columns + column] = + canonical.hrir[(indices[row] * 2u + ear) * canonical.taps + tap]; + } + } + } + std::vector parameters(columns * target_columns, 0.0); + for (std::size_t tap = 0u; tap < canonical.taps; ++tap) { + for (std::size_t parameter = 0u; parameter < columns; ++parameter) { + const double value = dictionary[tap * columns + parameter]; + if (value == 0.0) { + continue; + } + for (std::size_t column = 0u; column < target_columns; ++column) { + parameters[parameter * target_columns + column] += + value * target[tap * target_columns + column]; + } + } + } + if (!lu_solve_real(&system, static_cast(columns), ¶meters, + static_cast(target_columns))) { + return field_fail(JOC_ERR_HRTF_FORMAT, "HRTF projection system is singular"); + } + + // Hybrid gains [measurement][ear*77 + band] with the known embedded delay + // removed exactly once (parameters[parameter][measurement*2 + ear]). + std::vector selected_removed(selected * 2u, 0.0); + std::vector gains_by_direction(selected * gains_per_direction, Complex(0.0, 0.0)); + for (std::size_t row = 0u; row < selected; ++row) { + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const std::size_t column = row * 2u + ear; + const double removed = aligned.embedded_removed[indices[row] * 2u + ear]; + selected_removed[column] = removed; + for (int band = 0; band < kHybridBands; ++band) { + const double real = parameters[static_cast(2 * band) * target_columns + column]; + const double imaginary = + parameters[static_cast(2 * band + 1) * target_columns + column]; + const double removal = + 2.0 * kPi * removed * kBandCenters[band] / canonical.sample_rate_hz; + gains_by_direction[row * gains_per_direction + ear * kHybridBands + + static_cast(band)] = + Complex(real, imaginary) * std::polar(1.0, removal); + } + } + } + std::vector signal_to_noise(target_columns, 0.0); + double maximum_gain = 0.0; + for (const Complex value : gains_by_direction) { + maximum_gain = std::max(maximum_gain, std::abs(value)); + } + for (std::size_t column = 0u; column < target_columns; ++column) { + double reference_energy = 0.0; + double error_energy = 0.0; + for (std::size_t tap = 0u; tap < canonical.taps; ++tap) { + double reconstructed = 0.0; + for (std::size_t parameter = 0u; parameter < columns; ++parameter) { + reconstructed += dictionary[tap * columns + parameter] * + parameters[parameter * target_columns + column]; + } + const double value = target[tap * target_columns + column]; + reference_energy += value * value; + const double error = value - reconstructed; + error_energy += error * error; + } + signal_to_noise[column] = + 10.0 * std::log10(std::max(reference_energy, 1.0e-300) / + std::max(error_energy, 1.0e-300)); + } + + std::vector directions; + std::vector gains; + std::vector runtime_delay; + std::vector selected_directions(selected * 3u, 0.0); + std::vector selected_delays(selected * 2u, 0.0); + for (std::size_t row = 0u; row < selected; ++row) { + for (int axis = 0; axis < 3; ++axis) { + selected_directions[row * 3u + static_cast(axis)] = + canonical.unit_directions[indices[row] * 3u + static_cast(axis)]; + } + for (std::size_t ear = 0u; ear < 2u; ++ear) { + selected_delays[row * 2u + ear] = aligned.runtime_delay[indices[row] * 2u + ear]; + } + } + group_coincident(selected_directions, selected, gains_by_direction, gains_per_direction, + selected_delays, &directions, &gains, &runtime_delay); + const std::size_t unique = directions.size() / 3u; + if (unique < terms) { + return field_fail(JOC_ERR_HRTF_FORMAT, + "coincident-direction merging left fewer than 36 directions"); + } + + std::vector basis; + real_spherical_harmonics(directions, unique, options.order, &basis); + const std::vector weights = spherical_voronoi_weights(directions, unique); + const std::vector coefficients = fit_complex( + basis, unique, kFieldTerms, weights, options.sh_ridge, gains, gains_per_direction); + const std::vector delay_coefficients = + fit_real(basis, unique, kFieldTerms, weights, options.sh_ridge, runtime_delay, 2u); + + // Reconstruction error of the reported fit. + std::vector relative_error; + std::vector magnitude_error_db; + std::vector delay_error; + relative_error.reserve(unique * kHybridBands); + magnitude_error_db.reserve(unique * kHybridBands); + delay_error.reserve(unique * 2u); + for (std::size_t row = 0u; row < unique; ++row) { + for (std::size_t ear = 0u; ear < 2u; ++ear) { + double reconstructed_delay = 0.0; + for (std::size_t term = 0u; term < terms; ++term) { + reconstructed_delay += basis[row * terms + term] * delay_coefficients[term * 2u + ear]; + } + const double reference_delay = runtime_delay[row * 2u + ear]; + delay_error.push_back(reconstructed_delay - reference_delay); + for (int band = 0; band < kHybridBands; ++band) { + Complex reconstructed_aligned(0.0, 0.0); + for (std::size_t term = 0u; term < terms; ++term) { + reconstructed_aligned += + basis[row * terms + term] * + coefficients[term * gains_per_direction + ear * kHybridBands + + static_cast(band)]; + } + const Complex reference = + gains[row * gains_per_direction + ear * kHybridBands + + static_cast(band)] * + std::polar(1.0, -2.0 * kPi * reference_delay * kBandCenters[band] / + canonical.sample_rate_hz); + const Complex reconstructed = + reconstructed_aligned * + std::polar(1.0, -2.0 * kPi * reconstructed_delay * kBandCenters[band] / + canonical.sample_rate_hz); + const double magnitude_reference = std::max(std::abs(reference), 1.0e-12); + relative_error.push_back(std::abs(reconstructed - reference) / magnitude_reference); + magnitude_error_db.push_back( + std::abs(20.0 * std::log10(std::max(std::abs(reconstructed), 1.0e-12)) - + 20.0 * std::log10(magnitude_reference))); + } + } + } + double delay_square_sum = 0.0; + double delay_maximum = 0.0; + for (const double value : delay_error) { + delay_square_sum += value * value; + delay_maximum = std::max(delay_maximum, std::abs(value)); + } + + // Delay bounds per ear, and the four arrays the cache stores. + std::vector delay_bounds(4u, 0.0); + for (std::size_t ear = 0u; ear < 2u; ++ear) { + double minimum = std::numeric_limits::infinity(); + double maximum = -std::numeric_limits::infinity(); + for (std::size_t row = 0u; row < unique; ++row) { + minimum = std::min(minimum, runtime_delay[row * 2u + ear]); + maximum = std::max(maximum, runtime_delay[row * 2u + ear]); + } + delay_bounds[ear * 2u] = minimum; + delay_bounds[ear * 2u + 1u] = maximum; + } + std::vector flat_coefficients(terms * 2u * kHybridBands * 2u, 0.0); + for (std::size_t term = 0u; term < terms; ++term) { + for (std::size_t ear = 0u; ear < 2u; ++ear) { + for (int band = 0; band < kHybridBands; ++band) { + const Complex value = + coefficients[term * gains_per_direction + ear * kHybridBands + + static_cast(band)]; + const std::size_t offset = + ((term * 2u + ear) * kHybridBands + static_cast(band)) * 2u; + flat_coefficients[offset] = value.real(); + flat_coefficients[offset + 1u] = value.imag(); + } + } + } + + Field field; + field.source_sha256 = to_upper(canonical.source_sha256); + field.source_display_name = basename_of(canonical.source_path); + field.measurement_radius_m = shell_radius; + field.order = options.order; + field.projection_ridge = options.projection_ridge; + field.spherical_harmonic_ridge = options.sh_ridge; + field.compiler_version = kCompilerVersion; + field.phase_policy_version = kPhasePolicyVersion; + field.sh_convention = kShConvention; + field.filterbank_json = filterbank_fingerprint_json(); + field.delay_source = aligned.delay_source; + field.band_centers_hz.assign(kBandCenters, kBandCenters + kHybridBands); + field.coefficients = std::move(flat_coefficients); + field.delay_coefficients = std::move(delay_coefficients); + field.delay_bounds = std::move(delay_bounds); + field.cache_key = compiled_hrtf_cache_key(field.source_sha256, canonical.sample_rate_hz, + shell_radius, options.order, + options.projection_ridge, options.sh_ridge); + field.fit_report_json = json_object({ + {"complex_relative_error_median", json_number(percentile(relative_error, 50.0))}, + {"complex_relative_error_p95", json_number(percentile(relative_error, 95.0))}, + {"delay_error_samples_max", json_number(delay_maximum)}, + {"delay_error_samples_rms", + json_number(std::sqrt(delay_square_sum / static_cast(delay_error.size())))}, + {"delay_source", json_escape(aligned.delay_source)}, + {"format", json_escape("SOFA FIR -> public 64-QMF/77-hybrid -> ACN/N3D real SH")}, + {"input_measurements", std::to_string(selected)}, + {"magnitude_error_db_median", json_number(percentile(magnitude_error_db, 50.0))}, + {"magnitude_error_db_p95", json_number(percentile(magnitude_error_db, 95.0))}, + {"order", std::to_string(options.order)}, + {"phase_policy_version", json_escape(kPhasePolicyVersion)}, + {"precision", json_escape("float64/complex128")}, + {"projection", + json_object({ + {"dictionary_shape", + json_array({std::to_string(canonical.taps), std::to_string(kParameterCount)})}, + {"embedded_delay_samples_max", json_number(maximum_of(selected_removed))}, + {"embedded_delay_samples_min", json_number(minimum_of(selected_removed))}, + {"fir_reconstruction_snr_db_median", json_number(percentile(signal_to_noise, 50.0))}, + {"fir_reconstruction_snr_db_min", json_number(minimum_of(signal_to_noise))}, + {"fir_reconstruction_snr_db_p05", json_number(percentile(signal_to_noise, 5.0))}, + {"maximum_absolute_hybrid_gain", json_number(maximum_gain)}, + {"method", json_escape("regularized public analysis/gain/synthesis dictionary")}, + {"precision", json_escape("float64/complex128")}, + {"real_parameters", std::to_string(kParameterCount)}, + {"ridge", json_number(options.projection_ridge)}, + })}, + {"shell_radius_m", json_number(shell_radius)}, + {"spherical_harmonic_ridge", json_number(options.sh_ridge)}, + {"terms", std::to_string(kFieldTerms)}, + {"unique_directions", std::to_string(unique)}, + }); + field.payload_sha256 = field_payload_sha256(field); + field.metadata_json = json_object({ + {"cache_key", json_escape(field.cache_key)}, + {"cache_key_version", "1"}, + {"cache_schema", json_escape(std::string(kCacheSchema))}, + {"compiler_version", json_escape(field.compiler_version)}, + {"delay_source", json_escape(field.delay_source)}, + {"filterbank", field.filterbank_json}, + {"fit_report", field.fit_report_json}, + {"format_version", std::to_string(kFormatVersion)}, + {"magic", json_escape(std::string(kMagic))}, + {"measurement_radius_m", json_number(field.measurement_radius_m)}, + {"order", std::to_string(field.order)}, + {"payload_sha256", json_escape(field.payload_sha256)}, + {"phase_policy_version", json_escape(field.phase_policy_version)}, + {"projection_ridge", json_number(field.projection_ridge)}, + {"sample_rate_hz", json_number(canonical.sample_rate_hz)}, + {"sh_convention", json_escape(field.sh_convention)}, + {"source_display_name", json_escape(field.source_display_name)}, + {"source_sha256", json_escape(field.source_sha256)}, + {"spherical_harmonic_ridge", json_number(field.spherical_harmonic_ridge)}, + }); + *out = std::move(field); + return Status::success(); +} + +void shell_directions_and_weights_for_check(const SofaHrir& sofa, double radius_m, + std::vector* directions, + std::vector* weights) { + CanonicalHrtf canonical; + if (!canonicalize_sofa(sofa, &canonical).ok()) { + return; + } + double actual = radius_m; + const std::vector indices = canonical_shell_indices(canonical, radius_m, &actual); + directions->assign(indices.size() * 3u, 0.0); + for (std::size_t row = 0u; row < indices.size(); ++row) { + for (int axis = 0; axis < 3; ++axis) { + (*directions)[row * 3u + static_cast(axis)] = + canonical.unit_directions[indices[row] * 3u + static_cast(axis)]; + } + } + *weights = spherical_voronoi_weights(*directions, indices.size()); +} +Status compile_sofa_field(const SofaHrir& sofa, const CompileOptions& options, Field* out) { + CanonicalHrtf canonical; + const Status status = canonicalize_sofa(sofa, &canonical); + if (!status.ok()) { + return status; + } + return compile_canonical_field(canonical, options, out); +} + +} // namespace joc::hrtf diff --git a/src/hrtf/sofa_field.h b/src/hrtf/sofa_field.h new file mode 100644 index 0000000..bb80fba --- /dev/null +++ b/src/hrtf/sofa_field.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include +#include + +#include "foundation/status.h" +#include "hrtf/jochrtf.h" +#include "hrtf/sofa.h" + +// SOFA SimpleFreeFieldHRIR -> compiled directional field, ported from the +// reference chain (sofa_canonical.py + sofa_hrtf_field.py + the public +// filterbank): the measurement shell is selected, one delay representation is +// separated, the FIRs are projected onto the 64-QMF/77-hybrid filterbank and the +// result is fitted with fifth-order ACN/N3D real spherical harmonics. +namespace joc::hrtf { + +inline constexpr int kFieldOrder = 5; +inline constexpr int kFieldTerms = 36; +inline constexpr double kFieldSampleRateHz = 48000.0; +inline constexpr double kDefaultShellRadiusM = 1.0; +inline constexpr double kDefaultProjectionRidge = 1.0e-3; +inline constexpr double kDefaultSphericalHarmonicRidge = 1.0e-5; +inline constexpr const char* kCompilerVersion = "joc-sofa-compiler-v1"; +inline constexpr const char* kPhasePolicyVersion = "sofa-delay-exactly-once-v1"; +inline constexpr const char* kShConvention = "ACN/N3D real"; +inline constexpr const char* kFilterbankTableVersion = "joc-public-64qmf-77hybrid-v1"; +// SHA-256 of the standard filterbank archive the embedded tables came from. It +// participates in the cache key, so it is part of the file-format contract. +inline constexpr const char* kFilterbankArchiveSha256 = + "C05BEF4D26E96ECBD4694E2572F05DA400255C777BA5047300B9D3B1F81081CD"; + +struct CompileOptions { + double shell_radius_m = kDefaultShellRadiusM; + int order = kFieldOrder; + double projection_ridge = kDefaultProjectionRidge; + double sh_ridge = kDefaultSphericalHarmonicRidge; +}; + +// Canonical HRIR set: Data.IR and Data.Delay stay separate, the listener frame is +// applied to the source positions and the ears are ordered left/right. +struct CanonicalHrtf { + std::string source_path; + std::string source_sha256; + std::string convention; + std::string convention_version; + std::string processing_label; + double sample_rate_hz = 0.0; + std::uint32_t measurements = 0; + std::uint32_t taps = 0; + int left_receiver_index = 0; + int right_receiver_index = 1; + std::vector source_position_cartesian_m; // [M,3] listener-local + std::vector unit_directions; // [M,3] + std::vector measurement_radius_m; // [M] + std::vector hrir; // [M,2,N] canonical L/R + std::vector delay_samples; // [M,2], not applied +}; + +// Port of load_simple_free_field_hrir(): strict SimpleFreeFieldHRIR import. +Status canonicalize_sofa(const SofaHrir& sofa, CanonicalHrtf* out); + +// Compiles the canonical set into the runtime field (port of SofaHrtfField.fit). +Status compile_sofa_field(const SofaHrir& sofa, const CompileOptions& options, Field* out); + +// The measurements on the shell nearest to radius_m; actual_radius_m receives the +// mean radius of that shell (upstream CanonicalHrtf.shell_indices). +std::vector canonical_shell_indices(const CanonicalHrtf& canonical, double radius_m, + double* actual_radius_m); + +// Compiles an already canonicalized set (used by tests and the cache layer). +Status compile_canonical_field(const CanonicalHrtf& canonical, const CompileOptions& options, + Field* out); + +// Configuration hash that names the cache file (upstream compiled_hrtf_cache_key). +std::string compiled_hrtf_cache_key(const std::string& source_sha256, double sample_rate_hz, + double shell_radius_m, int order, double projection_ridge, + double sh_ridge); + +// Payload hash over the four arrays (upstream _payload_sha256). +std::string field_payload_sha256(const Field& field); + +// "..jochrtf", the upstream cache file name. +std::string cache_file_name(const std::string& display_name, const std::string& cache_key); + +// Serializes the field as a .jochrtf cache the upstream loader also accepts. +Status write_jochrtf(const Field& field, const std::string& path); + +// The analysis/gain/synthesis dictionary the projection solves against (dev check). +std::vector hybrid_gain_synthesis_dictionary_for_check(std::size_t sample_count); + +// Shell directions and their spherical Voronoi weights (dev check). +void shell_directions_and_weights_for_check(const SofaHrir& sofa, double radius_m, + std::vector* directions, + std::vector* weights); + +// PublicAnalysis77 on a unit impulse, interleaved complex (dev check). +std::vector analysis_impulse_for_check(std::size_t total_samples); + +// The 77 hybrid-band centre frequencies at 48 kHz. +const std::vector& hybrid_band_center_frequencies_hz(); + +} // namespace joc::hrtf diff --git a/src/io/adm_writer.cpp b/src/io/adm_writer.cpp new file mode 100644 index 0000000..5988821 --- /dev/null +++ b/src/io/adm_writer.cpp @@ -0,0 +1,241 @@ +#include "io/adm_writer.h" +#include "foundation/fs_utf8.h" + +#include +#include + +#include "io/wav_writer.h" // pack_int24 (shared int24 quantisation) + +namespace joc::io { + +namespace { + +constexpr long kDs64BodyOffset = 20; +constexpr long kDataSizeOffset = 76; + +void put_u16(std::string* out, std::uint16_t value) { + char buffer[2]; + std::memcpy(buffer, &value, 2); + out->append(buffer, 2); +} + +void put_u32(std::string* out, std::uint32_t value) { + char buffer[4]; + std::memcpy(buffer, &value, 4); + out->append(buffer, 4); +} + +void put_u64(std::string* out, std::uint64_t value) { + char buffer[8]; + std::memcpy(buffer, &value, 8); + out->append(buffer, 8); +} + +} // namespace + +AdmBwfWriter::~AdmBwfWriter() { abort(); } + +Status AdmBwfWriter::open(const std::string& path, std::size_t block_samples) { + if (block_samples < JOC_FRAME_SAMPLES) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, + "ADM block size must hold at least one E-AC-3 frame"); + } + path_ = path; + block_samples_ = block_samples; + used_ = 0; + frames_ = 0; + finalized_ = false; + buffer_.assign(block_samples * kChannels, 0.0f); + + file_ = fs_utf8::fopen(path, "wb+"); + if (file_ == nullptr) { + std::error_code ignored; + const std::filesystem::path parent = std::filesystem::path(path).parent_path(); + if (!parent.empty()) { + std::filesystem::create_directories(parent, ignored); + } + file_ = fs_utf8::fopen(path, "wb+"); + } + if (file_ == nullptr) { + return Status::fail(JOC_ERR_OUTPUT_OPEN, stage::kOutput, "cannot open " + path); + } + std::string header; + header.append("RF64", 4); + put_u32(&header, 0xFFFFFFFFu); + header.append("WAVE", 4); + if (std::fwrite(header.data(), 1, header.size(), file_) != header.size()) { + abort(); + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "cannot write " + path); + } + Status status = write_chunk("ds64", std::string(28, '\0')); + if (!status.ok()) { + abort(); + return status; + } + std::string fmt; + put_u16(&fmt, 1); + put_u16(&fmt, static_cast(kChannels)); + put_u32(&fmt, kRate); + put_u32(&fmt, kRate * kChannels * 3u); + put_u16(&fmt, static_cast(kChannels * 3u)); + put_u16(&fmt, 24); + status = write_chunk("fmt ", fmt); + if (!status.ok()) { + abort(); + return status; + } + status = write_chunk("data", std::string()); + if (!status.ok()) { + abort(); + return status; + } + return Status::success(); +} + +Status AdmBwfWriter::write_chunk(const char id[4], const std::string& body) { + std::string header; + header.append(id, 4); + put_u32(&header, static_cast(body.size())); + if (std::fwrite(header.data(), 1, header.size(), file_) != header.size()) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "chunk header write failed"); + } + if (!body.empty() && + std::fwrite(body.data(), 1, body.size(), file_) != body.size()) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "chunk body write failed"); + } + if ((body.size() & 1u) != 0u) { + const char pad = '\0'; + if (std::fwrite(&pad, 1, 1, file_) != 1) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "chunk padding write failed"); + } + } + return Status::success(); +} + +Status AdmBwfWriter::flush() { + if (used_ == 0) { + return Status::success(); + } + if (file_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kOutput, "ADM writer is not open"); + } + packed_.clear(); + pack_int24(buffer_.data(), used_, kChannels, &packed_); + if (std::fwrite(packed_.data(), 1, packed_.size(), file_) != packed_.size()) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "audio write failed for " + path_); + } + used_ = 0; + return Status::success(); +} + +Status AdmBwfWriter::write_objects16(const float* planar16) { + if (file_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kOutput, "ADM writer is not open"); + } + if (planar16 == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, "null frame"); + } + std::size_t source = 0; + while (source < JOC_FRAME_SAMPLES) { + const std::size_t available = block_samples_ - used_; + const std::size_t count = + std::min(available, static_cast(JOC_FRAME_SAMPLES) - source); + float* target = buffer_.data() + used_ * kChannels; + std::memset(target, 0, count * kChannels * sizeof(float)); + for (std::size_t sample = 0; sample < count; ++sample) { + float* row = target + sample * kChannels; + row[3] = planar16[0u * JOC_FRAME_SAMPLES + source + sample]; + for (std::size_t object = 0; object < 15u; ++object) { + row[10u + object] = + planar16[(object + 1u) * JOC_FRAME_SAMPLES + source + sample]; + } + } + used_ += count; + source += count; + if (used_ == block_samples_) { + const Status status = flush(); + if (!status.ok()) { + return status; + } + } + } + frames_ += JOC_FRAME_SAMPLES; + return Status::success(); +} + +Status AdmBwfWriter::finalize(const std::string& axml, const std::string& chna, + const std::string& dbmd) { + if (file_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kOutput, "ADM writer is not open"); + } + if (finalized_) { + return Status::fail(JOC_ERR_STATE, stage::kOutput, "ADM writer already finalized"); + } + Status status = flush(); + if (!status.ok()) { + return status; + } + status = write_chunk("axml", axml); + if (!status.ok()) { + return status; + } + status = write_chunk("chna", chna); + if (!status.ok()) { + return status; + } + status = write_chunk("dbmd", dbmd); + if (!status.ok()) { + return status; + } + + if (std::fseek(file_, 0, SEEK_END) != 0) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "seek failed for " + path_); + } + const long long total = std::ftell(file_); + if (total < 0) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "tell failed for " + path_); + } + const std::uint64_t data_len = frames_ * kChannels * 3u; + const std::uint32_t data_field = + data_len <= 0xFFFFFFFFull ? static_cast(data_len) : 0xFFFFFFFFu; + + if (std::fseek(file_, kDataSizeOffset, SEEK_SET) != 0) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "seek failed for " + path_); + } + char buffer[4]; + std::memcpy(buffer, &data_field, 4); + if (std::fwrite(buffer, 1, 4, file_) != 4) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "data size patch failed"); + } + + std::string ds64; + put_u64(&ds64, static_cast(total) - 8u); + put_u64(&ds64, data_len); + put_u64(&ds64, frames_); + put_u32(&ds64, 0); + if (std::fseek(file_, kDs64BodyOffset, SEEK_SET) != 0) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "seek failed for " + path_); + } + if (std::fwrite(ds64.data(), 1, ds64.size(), file_) != ds64.size()) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "ds64 patch failed"); + } + finalized_ = true; + if (std::fclose(file_) != 0) { + file_ = nullptr; + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "close failed for " + path_); + } + file_ = nullptr; + return Status::success(); +} + +void AdmBwfWriter::abort() { + if (file_ != nullptr) { + std::fclose(file_); + file_ = nullptr; + } + if (!finalized_ && !path_.empty()) { + fs_utf8::remove(path_); + } +} + +} // namespace joc::io diff --git a/src/io/adm_writer.h b/src/io/adm_writer.h new file mode 100644 index 0000000..9a41699 --- /dev/null +++ b/src/io/adm_writer.h @@ -0,0 +1,52 @@ + +#pragma once + +#include +#include +#include +#include + +#include "foundation/status.h" +#include "joc_core.h" + +namespace joc::io { + +class AdmBwfWriter { +public: + static constexpr std::uint32_t kChannels = 25; + static constexpr std::uint32_t kRate = 48000; + static constexpr std::size_t kDefaultBlockSamples = 131072; + + AdmBwfWriter() = default; + ~AdmBwfWriter(); + + AdmBwfWriter(const AdmBwfWriter&) = delete; + AdmBwfWriter& operator=(const AdmBwfWriter&) = delete; + + Status open(const std::string& path, std::size_t block_samples = kDefaultBlockSamples); + + Status write_objects16(const float* planar16); + + Status finalize(const std::string& axml, const std::string& chna, const std::string& dbmd); + + // Closes and removes a file that was never finalized (plan 28.3: abort must + void abort(); + + std::uint64_t frames() const { return frames_; } + bool open_ok() const { return file_ != nullptr; } + +private: + Status write_chunk(const char id[4], const std::string& body); + Status flush(); + + std::FILE* file_ = nullptr; + std::string path_; + std::size_t block_samples_ = kDefaultBlockSamples; + std::size_t used_ = 0; + std::uint64_t frames_ = 0; + std::vector buffer_; + std::string packed_; + bool finalized_ = false; +}; + +} // namespace joc::io diff --git a/src/io/hdf5.cpp b/src/io/hdf5.cpp new file mode 100644 index 0000000..12cfc3d --- /dev/null +++ b/src/io/hdf5.cpp @@ -0,0 +1,1430 @@ +#include "io/hdf5.h" + +#include +#include +#include +#include +#include +#include + +#include "foundation/fs_utf8.h" + +namespace joc::io { + +namespace { + +// Object header message ids of the HDF5 file format specification (version 3): +// 0x02 points at the dense link heap, 0x06 is one link, 0x10 continues the +// header in another block and 0x15 points at the dense attribute heap. +constexpr std::uint8_t kMsgNil = 0x00; +constexpr std::uint8_t kMsgDataspace = 0x01; +constexpr std::uint8_t kMsgLinkInfo = 0x02; +constexpr std::uint8_t kMsgDatatype = 0x03; +constexpr std::uint8_t kMsgLink = 0x06; +constexpr std::uint8_t kMsgLayout = 0x08; +constexpr std::uint8_t kMsgAttribute = 0x0C; +constexpr std::uint8_t kMsgContinuation = 0x10; +constexpr std::uint8_t kMsgAttributeInfo = 0x15; + +constexpr std::uint64_t kUndefinedAddress = 0xFFFFFFFFFFFFFFFFull; +constexpr std::uint64_t kMaxReadSize = 1ull << 32; // a dataset larger than this is refused +constexpr int kMaxNesting = 32; + +Status fail(joc_error code, const std::string& message) { + return Status::fail(code, stage::kRender, message); +} + +std::uint64_t read_le(const std::uint8_t* data, std::size_t size) { + std::uint64_t value = 0; + for (std::size_t i = 0; i < size; ++i) { + value |= static_cast(data[i]) << (8u * i); + } + return value; +} + +std::uint64_t align_to_8(std::uint64_t value) { return (value + 7u) & ~std::uint64_t{7u}; } + +void swap_element_bytes(std::uint8_t* data, std::uint64_t size) { + for (std::uint64_t i = 0; i < size / 2; ++i) { + const std::uint8_t head = data[i]; + data[i] = data[size - 1 - i]; + data[size - 1 - i] = head; + } +} + +struct Message { + std::uint8_t type = kMsgNil; + std::uint64_t body = 0; // absolute file offset of the message body + std::uint64_t size = 0; +}; + +struct LinkEntry { + std::string name; + std::uint64_t address = kUndefinedAddress; +}; + +struct AttributeEntry { + std::string name; + std::uint64_t body = 0; + std::uint64_t size = 0; +}; + +// Fractal heap header fields this reader needs; the free-space accounting is +// deliberately not modelled because objects are enumerated from the blocks. +struct FractalHeap { + std::uint64_t id_length = 0; + std::uint32_t max_object = 0; + std::uint64_t object_count = 0; + std::uint64_t huge_count = 0; + std::uint64_t tiny_count = 0; + std::uint16_t width = 0; + std::uint64_t start_block = 0; + std::uint64_t max_direct_block = 0; + std::uint8_t offset_width = 0; + std::uint16_t current_rows = 0; + std::uint64_t root_block = kUndefinedAddress; +}; + +struct Layout { + bool compact = false; + std::uint64_t address = kUndefinedAddress; + std::uint64_t size = 0; + std::uint64_t inline_offset = 0; +}; + +enum class HeapObjectKind { Link, Attribute }; + +bool is_string_type(Hdf5Type type) { return type == Hdf5Type::String; } + +std::string trim_nul(std::string text) { + while (!text.empty() && text.back() == '\0') { + text.pop_back(); + } + return text; +} + +// Attribute names are stored with their NUL terminator included in the name size. +std::string attribute_name(const std::uint8_t* data, std::size_t size) { + const std::size_t length = std::string(reinterpret_cast(data), size).find('\0'); + return std::string(reinterpret_cast(data), + length == std::string::npos ? size : length); +} + +} // namespace + +std::uint64_t Hdf5DatasetInfo::element_count() const { + std::uint64_t count = 1; + for (const std::uint64_t dimension : shape) { + count *= dimension; + } + return count; +} + +struct Hdf5File::Impl { + std::string file_path; + mutable std::ifstream stream; + bool opened = false; + std::uint64_t file_size = 0; + std::uint8_t offset_size = 8; + std::uint8_t length_size = 8; + std::uint64_t root_object = kUndefinedAddress; + + // Parsed metadata is cached by file address / path: the file itself is only + // read again when a dataset's payload is requested. + mutable std::map> headers; + mutable std::map> link_cache; + mutable std::map object_cache; + + Status read_at(std::uint64_t offset, std::uint64_t size, std::vector* out) const { + if (out == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "HDF5 read without a destination buffer"); + } + out->clear(); + if (size == 0) { + return Status::success(); + } + if (offset > file_size || size > file_size - offset) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 structure runs past the end of " + file_path + + " (offset " + std::to_string(offset) + ", size " + + std::to_string(size) + ")"); + } + stream.clear(); + stream.seekg(static_cast(offset), std::ios::beg); + if (!stream.good()) { + return fail(JOC_ERR_IO, "cannot seek in " + file_path); + } + out->resize(static_cast(size)); + stream.read(reinterpret_cast(out->data()), static_cast(size)); + if (stream.gcount() != static_cast(size)) { + return fail(JOC_ERR_IO, "short read in " + file_path); + } + return Status::success(); + } + + Status read_u64(std::uint64_t offset, std::uint8_t size, std::uint64_t* out) const { + std::vector buffer; + const Status status = read_at(offset, size, &buffer); + if (!status.ok()) { + return status; + } + *out = read_le(buffer.data(), buffer.size()); + return Status::success(); + } + + Status parse_messages(const std::uint8_t* data, std::size_t size, std::uint64_t base, + bool creation_order, std::vector* out, int depth) const { + std::size_t position = 0; + while (position + 4u <= size) { + const std::uint8_t type = data[position]; + const std::uint64_t body_size = read_le(data + position + 1, 2); + const std::size_t header_size = 4u + (creation_order ? 2u : 0u); + if (position + header_size > size) { + // A chunk may end with fewer bytes than a message header needs: + // that leftover is padding, not a message. + break; + } + const std::uint64_t body = position + header_size; + if (body + body_size > size) { + return fail(JOC_ERR_INPUT_FORMAT, + "HDF5 object header message overruns its chunk in " + file_path); + } + if (type == kMsgNil) { + if (body_size == 0) { + break; + } + position = static_cast(body + body_size); + continue; + } + if (type == kMsgContinuation) { + if (depth >= kMaxNesting) { + return fail(JOC_ERR_INPUT_FORMAT, + "HDF5 object header continuation nesting in " + file_path); + } + if (body_size < offset_size + length_size) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 continuation message in " + file_path); + } + const std::uint64_t next = read_le(data + body, offset_size); + const std::uint64_t length = read_le(data + body + offset_size, length_size); + std::vector block; + const Status status = read_at(next, length, &block); + if (!status.ok()) { + return status; + } + std::size_t start = 0; + std::size_t stop = block.size(); + if (block.size() >= 8u && std::memcmp(block.data(), "OCHK", 4) == 0) { + // A continuation block is "OCHK", the messages, then its own + // checksum, which must not be walked as a message header. + start = 4; + stop = block.size() - 4; + } + const Status nested = parse_messages(block.data() + start, stop - start, + next + start, creation_order, out, depth + 1); + if (!nested.ok()) { + return nested; + } + } else { + Message message; + message.type = type; + message.body = base + body; + message.size = body_size; + out->push_back(message); + } + position = static_cast(body + body_size); + } + return Status::success(); + } + + Status object_messages(std::uint64_t address, std::vector* out) const { + const auto cached = headers.find(address); + if (cached != headers.end()) { + *out = cached->second; + return Status::success(); + } + std::vector prefix; + Status status = read_at(address, 8, &prefix); + if (!status.ok()) { + return status; + } + if (std::memcmp(prefix.data(), "OHDR", 4) != 0) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 object header signature missing in " + file_path); + } + if (prefix[4] != 2u) { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 object header version " + std::to_string(prefix[4]) + + " is not supported"); + } + const std::uint8_t flags = prefix[5]; + std::uint64_t position = address + 6; + if ((flags & 0x20u) != 0u) { + position += 16; // access/modification/change/birth times + } + if ((flags & 0x10u) != 0u) { + position += 4; // attribute storage phase change values + } + const std::size_t width = std::size_t{1} << (flags & 0x03u); + std::vector size_field; + status = read_at(position, width, &size_field); + if (!status.ok()) { + return status; + } + const std::uint64_t chunk_size = read_le(size_field.data(), width); + position += width; + std::vector chunk; + status = read_at(position, chunk_size, &chunk); + if (!status.ok()) { + return status; + } + std::vector messages; + // A header that tracks attribute creation order stores a two byte + // creation order in every message header. + status = parse_messages(chunk.data(), chunk.size(), position, (flags & 0x04u) != 0u, + &messages, 0); + if (!status.ok()) { + return status; + } + headers[address] = messages; + *out = messages; + return Status::success(); + } + + Status parse_datatype(const std::uint8_t* data, std::size_t size, Hdf5TypeInfo* out) const { + if (size < 8u) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 datatype message in " + file_path); + } + const std::uint8_t version_class = data[0]; + const std::uint8_t datatype_class = static_cast(version_class & 0x0Fu); + const std::uint8_t bits = data[1]; + const std::uint32_t element_size = static_cast(read_le(data + 4, 4)); + Hdf5TypeInfo info; + info.size = element_size; + info.big_endian = (bits & 0x01u) != 0u; + switch (datatype_class) { + case 0: // fixed point + info.is_signed = (bits & 0x08u) != 0u; + switch (element_size) { + case 1: info.type = info.is_signed ? Hdf5Type::Int8 : Hdf5Type::UInt8; break; + case 2: info.type = info.is_signed ? Hdf5Type::Int16 : Hdf5Type::UInt16; break; + case 4: info.type = info.is_signed ? Hdf5Type::Int32 : Hdf5Type::UInt32; break; + case 8: info.type = info.is_signed ? Hdf5Type::Int64 : Hdf5Type::UInt64; break; + default: + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 integer of " + std::to_string(element_size) + + " bytes is not supported"); + } + break; + case 1: // floating point + if (element_size == 4u) { + info.type = Hdf5Type::Float32; + } else if (element_size == 8u) { + info.type = Hdf5Type::Float64; + } else { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 float of " + std::to_string(element_size) + + " bytes is not supported"); + } + break; + case 3: // fixed length string + info.type = Hdf5Type::String; + break; + default: + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 datatype class " + std::to_string(datatype_class) + + " (compound, variable length or reference) is not supported"); + } + *out = info; + return Status::success(); + } + + Status parse_dataspace(const std::uint8_t* data, std::size_t size, + std::vector* out) const { + if (size < 4u) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 dataspace message in " + file_path); + } + const std::uint8_t version = data[0]; + const std::uint8_t rank = data[1]; + const std::uint8_t flags = data[2]; + if (version != 1u && version != 2u) { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 dataspace version " + std::to_string(version) + " is not supported"); + } + // Version 1 aligns the dimension sizes on an eight byte boundary, so its + // four byte preamble is padded; version 2 writes them immediately. + const std::uint64_t start = (version == 1u) ? 8u : 4u; + const std::uint64_t needed = start + static_cast(rank) * length_size; + if (needed > size) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 dataspace dimensions in " + file_path); + } + std::vector shape; + shape.reserve(rank); + for (std::uint8_t index = 0; index < rank; ++index) { + shape.push_back(read_le(data + start + static_cast(index) * length_size, + length_size)); + } + (void)flags; // maximum dimensions and permutation indexes are not needed + *out = std::move(shape); + return Status::success(); + } + + Status parse_layout(const std::uint8_t* data, std::size_t size, Layout* out) const { + if (size < 2u) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 data layout message in " + file_path); + } + const std::uint8_t version = data[0]; + const std::uint8_t storage_class = data[1]; + if (version == 3u || version == 4u) { + switch (storage_class) { + case 0: { // compact: the data follows the two byte size field + if (size < 4u) { + return fail(JOC_ERR_INPUT_FORMAT, + "truncated HDF5 compact layout in " + file_path); + } + out->compact = true; + out->size = read_le(data + 2, 2); + out->inline_offset = 4; + return Status::success(); + } + case 1: { // contiguous: address then allocated size + if (size < 2u + offset_size + length_size) { + return fail(JOC_ERR_INPUT_FORMAT, + "truncated HDF5 contiguous layout in " + file_path); + } + out->compact = false; + out->address = read_le(data + 2, offset_size); + out->size = read_le(data + 2 + offset_size, length_size); + return Status::success(); + } + case 2: + return fail(JOC_ERR_NOT_SUPPORTED, "chunked datasets are not supported"); + default: + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 data layout class " + std::to_string(storage_class) + + " is not supported"); + } + } + if (version == 1u || version == 2u) { + // The older layouts only describe contiguous storage in a form this + // reader can follow. + if (storage_class != 1u || size < 2u + offset_size) { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 data layout version " + std::to_string(version) + + " is not supported"); + } + out->compact = false; + out->address = read_le(data + 2, offset_size); + out->size = 0; // derived from the dataspace and datatype + return Status::success(); + } + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 data layout version " + std::to_string(version) + " is not supported"); + } + + Status read_fractal_heap(std::uint64_t address, FractalHeap* out) const { + std::vector data; + // The header ends with the root block address and the current row count, + // 142 bytes in total for eight byte offsets and lengths. + Status status = read_at(address, 144, &data); + if (!status.ok()) { + return status; + } + if (std::memcmp(data.data(), "FRHP", 4) != 0) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 fractal heap header missing in " + file_path); + } + std::size_t position = 4; + const std::uint8_t version = data[position++]; + if (version != 0u) { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 fractal heap version " + std::to_string(version) + " is not supported"); + } + out->id_length = read_le(data.data() + position, 2); + position += 2; + const std::uint64_t filter_length = read_le(data.data() + position, 2); + position += 2; + if (filter_length != 0u) { + return fail(JOC_ERR_NOT_SUPPORTED, "filtered HDF5 fractal heaps are not supported"); + } + position += 1; // flags + out->max_object = static_cast(read_le(data.data() + position, 4)); + position += 4; + position += static_cast(length_size); // next huge object id + position += static_cast(offset_size); // huge object B-tree + position += static_cast(length_size); // free space in managed blocks + position += static_cast(offset_size); // free space B-tree + position += static_cast(length_size); // managed space + position += static_cast(length_size); // allocated managed space + position += static_cast(length_size); // direct block iterator offset + out->object_count = read_le(data.data() + position, length_size); + position += static_cast(length_size); + position += static_cast(length_size); // size of huge objects + out->huge_count = read_le(data.data() + position, length_size); + position += static_cast(length_size); + position += static_cast(length_size); // size of tiny objects + out->tiny_count = read_le(data.data() + position, length_size); + position += static_cast(length_size); + out->width = static_cast(read_le(data.data() + position, 2)); + position += 2; + out->start_block = read_le(data.data() + position, length_size); + position += static_cast(length_size); + out->max_direct_block = read_le(data.data() + position, length_size); + position += static_cast(length_size); + const std::uint64_t max_heap_bits = read_le(data.data() + position, 2); + position += 2; + position += 2; // starting number of rows in the root indirect block + out->root_block = read_le(data.data() + position, offset_size); + position += static_cast(offset_size); + out->current_rows = static_cast(read_le(data.data() + position, 2)); + out->offset_width = static_cast((max_heap_bits + 7u) / 8u); + if (out->offset_width == 0u) { + out->offset_width = 1; + } + if (out->id_length == 0u || out->start_block == 0u) { + return fail(JOC_ERR_INPUT_FORMAT, "malformed HDF5 fractal heap header in " + file_path); + } + return Status::success(); + } + + // Size of one heap object at `offset`, used to step from object to object. + // Free space is zero filled, so the first byte that does not describe a + // well formed message ends the enumeration. + Status object_extent(HeapObjectKind kind, std::uint64_t offset, std::uint64_t limit, + std::uint64_t* size, bool* valid) const { + *valid = false; + *size = 0; + std::vector data; + const std::uint64_t available = (limit > offset) ? (limit - offset) : 0; + const std::uint64_t wanted = std::min(available, 8); + if (wanted < 4u) { + return Status::success(); + } + const Status status = read_at(offset, wanted, &data); + if (!status.ok()) { + return status; + } + if (kind == HeapObjectKind::Link) { + if (data[0] != 1u) { + return Status::success(); + } + const std::uint8_t flags = data[1]; + std::uint64_t position = 2; + if ((flags & 0x08u) != 0u) { + position += 1; + } + if ((flags & 0x04u) != 0u) { + position += 8; + } + if ((flags & 0x10u) != 0u) { + position += 1; + } + const std::uint64_t name_size_field = 1ull << (flags & 0x03u); + std::vector header; + const Status head_status = read_at(offset, position + name_size_field, &header); + if (!head_status.ok()) { + return head_status; + } + const std::uint64_t name_length = read_le(header.data() + position, name_size_field); + const std::uint64_t total = position + name_size_field + name_length + offset_size; + if (name_length == 0u || name_length > 4096u || total > available) { + return Status::success(); + } + *size = total; + *valid = true; + return Status::success(); + } + if (data[0] < 1u || data[0] > 3u) { + return Status::success(); + } + std::vector header; + const Status head_status = read_at(offset, std::min(available, 8), &header); + if (!head_status.ok()) { + return head_status; + } + if (header.size() < 8u) { + return Status::success(); + } + const std::uint64_t name_size = read_le(header.data() + 2, 2); + const std::uint64_t datatype_size = read_le(header.data() + 4, 2); + const std::uint64_t dataspace_size = read_le(header.data() + 6, 2); + // Version 1 pads the attribute name to eight bytes, versions 2 and 3 + // write it (and, for version 3, a character set byte) unpadded. The + // datatype and dataspace messages are always padded to eight bytes. + const std::uint64_t name_offset = (data[0] == 3u) ? 9u : 8u; + const std::uint64_t name_field = + (data[0] == 1u) ? align_to_8(name_size) : name_size; + const std::uint64_t datatype_offset = name_offset + name_field; + const std::uint64_t dataspace_offset = datatype_offset + align_to_8(datatype_size); + const std::uint64_t data_offset = dataspace_offset + align_to_8(dataspace_size); + if (name_size == 0u || name_size > 4096u || data_offset > available || + datatype_size < 8u || dataspace_size < 4u) { + return Status::success(); + } + std::vector tail; + const Status tail_status = read_at(offset + datatype_offset, datatype_size, &tail); + if (!tail_status.ok()) { + return tail_status; + } + const std::uint64_t element_size = read_le(tail.data() + 4, 4); + std::vector space; + const Status space_status = read_at(offset + dataspace_offset, dataspace_size, &space); + if (!space_status.ok()) { + return space_status; + } + std::vector shape; + const Status shape_status = parse_dataspace(space.data(), space.size(), &shape); + if (!shape_status.ok()) { + return Status::success(); + } + std::uint64_t count = 1; + for (const std::uint64_t dimension : shape) { + if (dimension != 0u && count > kMaxReadSize / dimension) { + return Status::success(); + } + count *= dimension; + } + if (count != 0u && element_size > kMaxReadSize / count) { + return Status::success(); + } + const std::uint64_t total = data_offset + count * element_size; + if (total > available) { + return Status::success(); + } + *size = total; + *valid = true; + return Status::success(); + } + + Status scan_direct_block(const FractalHeap& heap, std::uint64_t address, int row, + HeapObjectKind kind, std::vector* out) const { + std::vector prefix; + Status status = read_at(address, 4 + 1 + offset_size, &prefix); + if (!status.ok()) { + return status; + } + if (std::memcmp(prefix.data(), "FHDB", 4) != 0) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 fractal heap direct block missing in " + file_path); + } + if (prefix[4] != 0u) { + return fail(JOC_ERR_NOT_SUPPORTED, "unsupported HDF5 fractal heap block version"); + } + const std::uint64_t block_size = + std::min(heap.start_block << row, heap.max_direct_block); + if (block_size == 0u || address + block_size < address) { + return fail(JOC_ERR_INPUT_FORMAT, "malformed HDF5 fractal heap block in " + file_path); + } + const std::uint64_t end = + std::min(address + block_size, file_size); + std::uint64_t position = address + 4 + 1 + offset_size + heap.offset_width + 4; + while (position < end) { + std::uint64_t object_size = 0; + bool valid = false; + status = object_extent(kind, position, end, &object_size, &valid); + if (!status.ok()) { + return status; + } + if (!valid || object_size == 0u) { + break; + } + Message object; + object.type = kMsgNil; // heap objects carry no message type + object.body = position; + object.size = object_size; + out->push_back(object); + position += object_size; + } + return Status::success(); + } + + Status collect_blocks(const FractalHeap& heap, std::uint64_t block, int row, int depth, + std::vector>* out) const { + if (block == kUndefinedAddress || depth > kMaxNesting) { + return Status::success(); + } + std::vector signature; + Status status = read_at(block, 4, &signature); + if (!status.ok()) { + return status; + } + if (std::memcmp(signature.data(), "FHDB", 4) == 0) { + out->emplace_back(block, row); + return Status::success(); + } + if (std::memcmp(signature.data(), "FHIB", 4) != 0) { + return fail(JOC_ERR_INPUT_FORMAT, "unknown HDF5 fractal heap block in " + file_path); + } + // Indirect block: version, heap header address, block offset, then one + // address per child block, two per row more than the row above. + const std::uint64_t header = 4 + 1 + offset_size + heap.offset_width; + const int rows = (depth == 0) ? static_cast(heap.current_rows) : kMaxNesting - 1; + std::uint64_t position = block + header; + for (int current = 0; current <= rows; ++current) { + const int children = 1 << std::min(current, 20); + bool any = false; + for (int index = 0; index < children; ++index) { + std::uint64_t child = kUndefinedAddress; + status = read_u64(position, offset_size, &child); + if (!status.ok()) { + return status; + } + position += offset_size; + if (child != kUndefinedAddress) { + any = true; + status = collect_blocks(heap, child, current, depth + 1, out); + if (!status.ok()) { + return status; + } + } + } + if (!any) { + break; + } + } + return Status::success(); + } + + Status heap_objects(std::uint64_t heap_address, HeapObjectKind kind, + std::vector* out) const { + FractalHeap heap; + Status status = read_fractal_heap(heap_address, &heap); + if (!status.ok()) { + return status; + } + if (heap.huge_count != 0u) { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 heap object is stored as a huge object and is not supported"); + } + std::vector> blocks; + status = collect_blocks(heap, heap.root_block, 0, 0, &blocks); + if (!status.ok()) { + return status; + } + for (const std::pair& block : blocks) { + status = scan_direct_block(heap, block.first, block.second, kind, out); + if (!status.ok()) { + return status; + } + } + return Status::success(); + } + + Status parse_link(const std::uint8_t* data, std::size_t size, LinkEntry* out) const { + if (size < 2u || data[0] != 1u) { + return fail(JOC_ERR_INPUT_FORMAT, "malformed HDF5 link message in " + file_path); + } + const std::uint8_t flags = data[1]; + std::uint64_t position = 2; + std::uint8_t link_type = 0; + if ((flags & 0x08u) != 0u) { + if (position + 1u > size) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 link message in " + file_path); + } + link_type = data[position]; + position += 1; + } + if ((flags & 0x04u) != 0u) { + position += 8; + } + if ((flags & 0x10u) != 0u) { + position += 1; + } + const std::uint64_t name_size_field = 1ull << (flags & 0x03u); + if (position + name_size_field > size) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 link name in " + file_path); + } + const std::uint64_t name_length = read_le(data + position, name_size_field); + position += name_size_field; + if (position + name_length + offset_size > size) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 link message in " + file_path); + } + const std::string name(reinterpret_cast(data + position), + static_cast(name_length)); + position += name_length; + if (link_type != 0u) { + return fail(JOC_ERR_NOT_SUPPORTED, + std::string(link_type == 1u ? "soft" : "external") + + " HDF5 link '" + name + "' is not supported"); + } + out->name = name; + out->address = read_le(data + position, offset_size); + return Status::success(); + } + + Status links_of(const std::string& group_path, std::vector* out) const { + const auto cached = link_cache.find(group_path); + if (cached != link_cache.end()) { + *out = cached->second; + return Status::success(); + } + std::uint64_t address = kUndefinedAddress; + Status status = object_address(group_path, &address); + if (!status.ok()) { + return status; + } + std::vector messages; + status = object_messages(address, &messages); + if (!status.ok()) { + return status; + } + std::vector links; + for (const Message& message : messages) { + if (message.type == kMsgLink) { + std::vector body; + status = read_at(message.body, message.size, &body); + if (!status.ok()) { + return status; + } + LinkEntry entry; + status = parse_link(body.data(), body.size(), &entry); + if (!status.ok()) { + return status; + } + links.push_back(std::move(entry)); + } else if (message.type == kMsgLinkInfo) { + std::vector body; + status = read_at(message.body, message.size, &body); + if (!status.ok()) { + return status; + } + if (body.size() < 2u) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 link info message in " + file_path); + } + const std::uint8_t flags = body[1]; + std::uint64_t position = 2; + if ((flags & 0x01u) != 0u) { + position += static_cast(length_size); // maximum creation index + } + if (position + offset_size > body.size()) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 link info message in " + file_path); + } + const std::uint64_t heap_address = read_le(body.data() + position, offset_size); + if (heap_address == kUndefinedAddress) { + // No dense storage: this group keeps its links compact. + continue; + } + std::vector objects; + status = heap_objects(heap_address, HeapObjectKind::Link, &objects); + if (!status.ok()) { + return status; + } + for (const Message& object : objects) { + std::vector link_body; + status = read_at(object.body, object.size, &link_body); + if (!status.ok()) { + return status; + } + LinkEntry entry; + status = parse_link(link_body.data(), link_body.size(), &entry); + if (!status.ok()) { + return status; + } + links.push_back(std::move(entry)); + } + } + } + link_cache[group_path] = links; + *out = links; + return Status::success(); + } + + Status object_address(const std::string& path, std::uint64_t* out) const { + if (path.empty() || path == "/") { + *out = root_object; + return Status::success(); + } + const auto cached = object_cache.find(path); + if (cached != object_cache.end()) { + *out = cached->second; + return Status::success(); + } + std::uint64_t current = root_object; + std::string prefix; + // A leading slash is the HDF5 spelling of "from the root group". + std::size_t start = path[0] == '/' ? 1u : 0u; + while (true) { + const std::size_t slash = path.find('/', start); + const std::string component = + path.substr(start, slash == std::string::npos ? std::string::npos : slash - start); + if (component.empty()) { + return fail(JOC_ERR_INVALID_ARGUMENT, "empty link name in HDF5 path " + path); + } + std::vector entries; + const Status status = links_of(prefix, &entries); + if (!status.ok()) { + return status; + } + const LinkEntry* found = nullptr; + for (const LinkEntry& entry : entries) { + if (entry.name == component) { + found = &entry; + break; + } + } + if (found == nullptr) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 object not found: " + path); + } + current = found->address; + if (slash == std::string::npos) { + break; + } + prefix = prefix.empty() ? component : prefix + "/" + component; + start = slash + 1; + } + object_cache[path] = current; + *out = current; + return Status::success(); + } + + Status attribute_entries(const std::string& object_path, + std::vector* out) const { + std::uint64_t address = kUndefinedAddress; + Status status = object_address(object_path, &address); + if (!status.ok()) { + return status; + } + std::vector messages; + status = object_messages(address, &messages); + if (!status.ok()) { + return status; + } + std::vector entries; + for (const Message& message : messages) { + if (message.type == kMsgAttribute) { + std::vector body; + status = read_at(message.body, std::min(message.size, 8), &body); + if (!status.ok()) { + return status; + } + if (body.size() < 8u || body[0] < 1u || body[0] > 3u) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 attribute message in " + file_path); + } + const std::uint64_t name_size = read_le(body.data() + 2, 2); + const std::uint64_t name_offset = (body[0] == 3u) ? 9u : 8u; + if (name_size == 0u || name_offset + name_size > message.size) { + return fail(JOC_ERR_INPUT_FORMAT, "malformed HDF5 attribute name in " + file_path); + } + std::vector name; + status = read_at(message.body + name_offset, name_size, &name); + if (!status.ok()) { + return status; + } + AttributeEntry entry; + entry.name = attribute_name(name.data(), name.size()); + entry.body = message.body; + entry.size = message.size; + entries.push_back(std::move(entry)); + } else if (message.type == kMsgAttributeInfo) { + std::vector body; + status = read_at(message.body, message.size, &body); + if (!status.ok()) { + return status; + } + if (body.size() < 2u) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 attribute info message in " + file_path); + } + const std::uint8_t flags = body[1]; + std::uint64_t position = 2; + if ((flags & 0x01u) != 0u) { + position += 2; // maximum creation index + } + if (position + offset_size > body.size()) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 attribute info message in " + file_path); + } + const std::uint64_t heap_address = read_le(body.data() + position, offset_size); + if (heap_address == kUndefinedAddress) { + // No dense storage: this object keeps its attributes compact. + continue; + } + std::vector objects; + status = heap_objects(heap_address, HeapObjectKind::Attribute, &objects); + if (!status.ok()) { + return status; + } + for (const Message& object : objects) { + std::vector head; + status = read_at(object.body, std::min(object.size, 8), &head); + if (!status.ok()) { + return status; + } + if (head.size() < 8u || head[0] < 1u || head[0] > 3u) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 attribute in the dense storage of " + file_path); + } + const std::uint64_t name_size = read_le(head.data() + 2, 2); + const std::uint64_t name_offset = (head[0] == 3u) ? 9u : 8u; + if (name_size == 0u || name_offset + name_size > object.size) { + return fail(JOC_ERR_INPUT_FORMAT, + "malformed HDF5 attribute name in " + file_path); + } + std::vector name; + status = read_at(object.body + name_offset, name_size, &name); + if (!status.ok()) { + return status; + } + AttributeEntry entry; + entry.name = attribute_name(name.data(), name.size()); + entry.body = object.body; + entry.size = object.size; + entries.push_back(std::move(entry)); + } + } + } + *out = std::move(entries); + return Status::success(); + } + + Status decode_attribute(std::uint64_t body_offset, std::uint64_t body_size, + Hdf5Attribute* out) const { + if (body_size > kMaxReadSize) { + return fail(JOC_ERR_NOT_SUPPORTED, "HDF5 attribute is too large to read"); + } + std::vector body; + Status status = read_at(body_offset, body_size, &body); + if (!status.ok()) { + return status; + } + if (body.size() < 8u || body[0] < 1u || body[0] > 3u) { + return fail(JOC_ERR_INPUT_FORMAT, "malformed HDF5 attribute message in " + file_path); + } + const std::uint8_t version = body[0]; + const std::uint64_t name_size = read_le(body.data() + 2, 2); + const std::uint64_t datatype_size = read_le(body.data() + 4, 2); + const std::uint64_t dataspace_size = read_le(body.data() + 6, 2); + const std::uint64_t name_offset = (version == 3u) ? 9u : 8u; + const std::uint64_t name_field = (version == 1u) ? align_to_8(name_size) : name_size; + const std::uint64_t datatype_offset = name_offset + name_field; + const std::uint64_t dataspace_offset = datatype_offset + align_to_8(datatype_size); + const std::uint64_t data_offset = dataspace_offset + align_to_8(dataspace_size); + if (name_size == 0u || datatype_size < 8u || dataspace_size < 4u || + data_offset > body.size()) { + return fail(JOC_ERR_INPUT_FORMAT, "malformed HDF5 attribute message in " + file_path); + } + Hdf5Attribute attribute; + status = parse_datatype(body.data() + datatype_offset, + static_cast(datatype_size), &attribute.type); + if (!status.ok()) { + return status; + } + status = parse_dataspace(body.data() + dataspace_offset, + static_cast(dataspace_size), &attribute.shape); + if (!status.ok()) { + return status; + } + std::uint64_t count = 1; + for (const std::uint64_t dimension : attribute.shape) { + count *= dimension; + } + const std::uint64_t bytes = count * attribute.type.size; + if (bytes > body.size() - data_offset) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated HDF5 attribute data in " + file_path); + } + attribute.raw.assign(body.begin() + static_cast(data_offset), + body.begin() + static_cast(data_offset + bytes)); + if (attribute.type.big_endian && !is_string_type(attribute.type.type)) { + for (std::uint64_t index = 0; index < count; ++index) { + swap_element_bytes(attribute.raw.data() + index * attribute.type.size, + attribute.type.size); + } + attribute.type.big_endian = false; + } + if (is_string_type(attribute.type.type)) { + attribute.text.assign(reinterpret_cast(attribute.raw.data()), + attribute.raw.size()); + attribute.text = trim_nul(std::move(attribute.text)); + } + *out = std::move(attribute); + return Status::success(); + } + + Status dataset_parts(const std::string& path, Hdf5DatasetInfo* info, Layout* layout) const { + std::uint64_t address = kUndefinedAddress; + Status status = object_address(path, &address); + if (!status.ok()) { + return status; + } + std::vector messages; + status = object_messages(address, &messages); + if (!status.ok()) { + return status; + } + bool have_dataspace = false; + bool have_datatype = false; + bool have_layout = false; + for (const Message& message : messages) { + if (message.type == kMsgDataspace || message.type == kMsgDatatype || + message.type == kMsgLayout) { + std::vector body; + status = read_at(message.body, message.size, &body); + if (!status.ok()) { + return status; + } + if (message.type == kMsgDataspace) { + status = parse_dataspace(body.data(), body.size(), &info->shape); + have_dataspace = status.ok(); + } else if (message.type == kMsgDatatype) { + status = parse_datatype(body.data(), body.size(), &info->type); + have_datatype = status.ok(); + } else { + status = parse_layout(body.data(), body.size(), layout); + if (status.ok() && layout->compact) { + layout->inline_offset += message.body; + } + have_layout = status.ok(); + } + if (!status.ok()) { + return status; + } + } + } + if (!have_dataspace || !have_datatype) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 object is not a dataset: " + path); + } + if (!have_layout) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 dataset has no data layout message: " + path); + } + return Status::success(); + } + + // Reads exactly one dataset: the payload of every other object stays on disk. + Status read_dataset(const std::string& path, Hdf5DatasetInfo* info, + std::vector* raw) const { + Layout layout; + Status status = dataset_parts(path, info, &layout); + if (!status.ok()) { + return status; + } + const std::uint64_t count = info->element_count(); + if (count > kMaxReadSize || info->type.size == 0u || + (count != 0u && info->type.size > kMaxReadSize / count)) { + return fail(JOC_ERR_NOT_SUPPORTED, "HDF5 dataset is too large to read: " + path); + } + const std::uint64_t bytes = count * info->type.size; + std::vector data; + if (bytes == 0u) { + // An empty dataset has no payload to fetch, allocated or not. + *raw = std::move(data); + return Status::success(); + } + if (layout.compact) { + if (layout.size < bytes) { + return fail(JOC_ERR_INPUT_FORMAT, "truncated compact HDF5 dataset: " + path); + } + status = read_at(layout.inline_offset, bytes, &data); + } else { + if (layout.address == kUndefinedAddress) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 dataset storage is not allocated: " + path); + } + if (layout.size != 0u && layout.size < bytes) { + return fail(JOC_ERR_INPUT_FORMAT, + "HDF5 dataset storage is shorter than its shape: " + path); + } + status = read_at(layout.address, bytes, &data); + } + if (!status.ok()) { + return status; + } + if (info->type.big_endian && !is_string_type(info->type.type)) { + for (std::uint64_t index = 0; index < count; ++index) { + swap_element_bytes(data.data() + index * info->type.size, info->type.size); + } + info->type.big_endian = false; + } + *raw = std::move(data); + return Status::success(); + } +}; + +Hdf5File::Hdf5File() : impl_(std::make_unique()) {} +Hdf5File::~Hdf5File() = default; +Hdf5File::Hdf5File(Hdf5File&&) noexcept = default; +Hdf5File& Hdf5File::operator=(Hdf5File&&) noexcept = default; + +Status Hdf5File::open(const std::string& path) { + if (impl_ == nullptr) { + return fail(JOC_ERR_STATE, "HDF5 reader is not constructed"); + } + if (!fs_utf8::exists(path)) { + return fail(JOC_ERR_INPUT_NOT_FOUND, "HDF5 file not found: " + path); + } + std::error_code error; + const std::uintmax_t size = fs_utf8::file_size(path, error); + if (error) { + return fail(JOC_ERR_IO, "cannot query the size of " + path); + } + impl_->stream = fs_utf8::open_input(path); + if (!impl_->stream.good()) { + return fail(JOC_ERR_IO, "cannot open " + path); + } + impl_->file_path = path; + impl_->file_size = static_cast(size); + impl_->opened = false; + impl_->headers.clear(); + impl_->link_cache.clear(); + impl_->object_cache.clear(); + + std::vector signature; + Status status = impl_->read_at(0, 8, &signature); + if (!status.ok()) { + return status; + } + static const std::uint8_t kMagic[8] = {0x89u, 'H', 'D', 'F', '\r', '\n', 0x1Au, '\n'}; + if (std::memcmp(signature.data(), kMagic, 8) != 0) { + return fail(JOC_ERR_INPUT_FORMAT, "not an HDF5 file: " + path); + } + std::vector superblock; + status = impl_->read_at(0, 64, &superblock); + if (!status.ok()) { + return status; + } + const std::uint8_t version = superblock[8]; + if (version > 1u) { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 superblock version " + std::to_string(version) + " is not supported"); + } + impl_->offset_size = superblock[13]; + impl_->length_size = superblock[14]; + if (impl_->offset_size == 0u || impl_->offset_size > 8u || impl_->length_size == 0u || + impl_->length_size > 8u) { + return fail(JOC_ERR_INPUT_FORMAT, "malformed HDF5 superblock in " + path); + } + const std::uint64_t root_entry = 56; + status = impl_->read_u64(root_entry + impl_->offset_size, impl_->offset_size, + &impl_->root_object); + if (!status.ok()) { + return status; + } + if (impl_->root_object == kUndefinedAddress) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 root group address is undefined in " + path); + } + std::vector root_prefix; + status = impl_->read_at(impl_->root_object, 4, &root_prefix); + if (!status.ok()) { + return status; + } + if (std::memcmp(root_prefix.data(), "OHDR", 4) != 0) { + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 root group does not use a version 2 object header in " + path); + } + impl_->opened = true; + return Status::success(); +} + +bool Hdf5File::is_open() const { return impl_ != nullptr && impl_->opened; } + +Status Hdf5File::links(const std::string& group_path, std::vector* names) const { + if (names == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "null name list"); + } + if (!is_open()) { + return fail(JOC_ERR_STATE, "HDF5 reader is not open"); + } + std::vector entries; + const Status status = impl_->links_of(group_path, &entries); + if (!status.ok()) { + return status; + } + names->clear(); + names->reserve(entries.size()); + for (const LinkEntry& entry : entries) { + names->push_back(entry.name); + } + return Status::success(); +} + +bool Hdf5File::has_dataset(const std::string& path) const { + if (!is_open()) { + return false; + } + std::uint64_t address = kUndefinedAddress; + if (!impl_->object_address(path, &address).ok()) { + return false; + } + std::vector messages; + if (!impl_->object_messages(address, &messages).ok()) { + return false; + } + // A dataset is the object that carries both a dataspace and a datatype, + // whatever its storage class turns out to be. + bool dataspace = false; + bool datatype = false; + for (const Message& message : messages) { + dataspace = dataspace || message.type == kMsgDataspace; + datatype = datatype || message.type == kMsgDatatype; + } + return dataspace && datatype; +} + +Status Hdf5File::dataset_info(const std::string& path, Hdf5DatasetInfo* out) const { + if (out == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "null dataset info"); + } + if (!is_open()) { + return fail(JOC_ERR_STATE, "HDF5 reader is not open"); + } + Layout layout; + Hdf5DatasetInfo info; + const Status status = impl_->dataset_parts(path, &info, &layout); + if (!status.ok()) { + return status; + } + *out = std::move(info); + return Status::success(); +} + +Status Hdf5File::read_dataset_raw(const std::string& path, std::vector* out) const { + if (out == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "null dataset buffer"); + } + if (!is_open()) { + return fail(JOC_ERR_STATE, "HDF5 reader is not open"); + } + Hdf5DatasetInfo info; + return impl_->read_dataset(path, &info, out); +} + +Status Hdf5File::read_dataset_double(const std::string& path, std::vector* out) const { + if (out == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "null dataset buffer"); + } + if (!is_open()) { + return fail(JOC_ERR_STATE, "HDF5 reader is not open"); + } + Hdf5DatasetInfo info; + std::vector raw; + const Status status = impl_->read_dataset(path, &info, &raw); + if (!status.ok()) { + return status; + } + const std::uint64_t count = info.element_count(); + out->clear(); + out->resize(static_cast(count)); + for (std::uint64_t index = 0; index < count; ++index) { + const std::uint8_t* element = raw.data() + index * info.type.size; + double value = 0.0; + switch (info.type.type) { + case Hdf5Type::Float64: { + std::memcpy(&value, element, sizeof(double)); + break; + } + case Hdf5Type::Float32: { + float narrow = 0.0f; + std::memcpy(&narrow, element, sizeof(float)); + value = static_cast(narrow); + break; + } + case Hdf5Type::Int8: { + value = static_cast(static_cast(element[0])); + break; + } + case Hdf5Type::UInt8: { + value = static_cast(element[0]); + break; + } + case Hdf5Type::Int16: { + std::int16_t narrow = 0; + std::memcpy(&narrow, element, sizeof(narrow)); + value = static_cast(narrow); + break; + } + case Hdf5Type::UInt16: { + std::uint16_t narrow = 0; + std::memcpy(&narrow, element, sizeof(narrow)); + value = static_cast(narrow); + break; + } + case Hdf5Type::Int32: { + std::int32_t narrow = 0; + std::memcpy(&narrow, element, sizeof(narrow)); + value = static_cast(narrow); + break; + } + case Hdf5Type::UInt32: { + std::uint32_t narrow = 0; + std::memcpy(&narrow, element, sizeof(narrow)); + value = static_cast(narrow); + break; + } + case Hdf5Type::Int64: { + std::int64_t narrow = 0; + std::memcpy(&narrow, element, sizeof(narrow)); + value = static_cast(narrow); + break; + } + case Hdf5Type::UInt64: { + std::uint64_t narrow = 0; + std::memcpy(&narrow, element, sizeof(narrow)); + value = static_cast(narrow); + break; + } + default: + return fail(JOC_ERR_NOT_SUPPORTED, + "HDF5 dataset is not numeric and cannot be read as double: " + path); + } + (*out)[static_cast(index)] = value; + } + return Status::success(); +} + +Status Hdf5File::attribute_names(const std::string& object_path, + std::vector* names) const { + if (names == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "null name list"); + } + if (!is_open()) { + return fail(JOC_ERR_STATE, "HDF5 reader is not open"); + } + std::vector entries; + const Status status = impl_->attribute_entries(object_path, &entries); + if (!status.ok()) { + return status; + } + names->clear(); + names->reserve(entries.size()); + for (const AttributeEntry& entry : entries) { + names->push_back(entry.name); + } + return Status::success(); +} + +Status Hdf5File::attribute(const std::string& object_path, const std::string& name, + Hdf5Attribute* out) const { + if (out == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "null attribute"); + } + if (!is_open()) { + return fail(JOC_ERR_STATE, "HDF5 reader is not open"); + } + std::vector entries; + Status status = impl_->attribute_entries(object_path, &entries); + if (!status.ok()) { + return status; + } + for (const AttributeEntry& entry : entries) { + if (entry.name == name) { + return impl_->decode_attribute(entry.body, entry.size, out); + } + } + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 attribute not found: " + name); +} + +Status Hdf5File::attribute_text(const std::string& object_path, const std::string& name, + std::string* out) const { + if (out == nullptr) { + return fail(JOC_ERR_INVALID_ARGUMENT, "null text"); + } + Hdf5Attribute attribute; + Status status = this->attribute(object_path, name, &attribute); + if (!status.ok()) { + return status; + } + if (!is_string_type(attribute.type.type)) { + return fail(JOC_ERR_INPUT_FORMAT, "HDF5 attribute is not a string: " + name); + } + *out = attribute.text; + return Status::success(); +} + +} // namespace joc::io diff --git a/src/io/hdf5.h b/src/io/hdf5.h new file mode 100644 index 0000000..2a936c6 --- /dev/null +++ b/src/io/hdf5.h @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include +#include + +#include "foundation/status.h" + +// Read-only subset of the HDF5 file format, sized for the SOFA files this +// project consumes: superblock v0, version 2 object headers, fractal-heap link +// and attribute storage, compact and contiguous datasets. The file is opened +// lazily: only the requested dataset's bytes are read into memory, everything +// else (superblock, object headers, heap blocks) is fetched on demand and the +// metadata that was parsed is cached by file address. +// +// Paths are HDF5 link paths ("Data.IR" is a single link name here, "Group/Set" +// walks two links); the empty path names the root group. Byte order is +// normalized on read, so callers never see the file's own endianness. +namespace joc::io { + +enum class Hdf5Type { + Unknown, + Int8, + Int16, + Int32, + Int64, + UInt8, + UInt16, + UInt32, + UInt64, + Float32, + Float64, + String, +}; + +struct Hdf5TypeInfo { + Hdf5Type type = Hdf5Type::Unknown; + std::uint32_t size = 0; // bytes per element as stored in the file + bool big_endian = false; + bool is_signed = false; +}; + +struct Hdf5DatasetInfo { + std::vector shape; + Hdf5TypeInfo type; + + std::uint64_t element_count() const; +}; + +struct Hdf5Attribute { + Hdf5TypeInfo type; + std::vector shape; + std::vector raw; // C order, host byte order + std::string text; // decoded for fixed-length string attributes +}; + +class Hdf5File { +public: + Hdf5File(); + ~Hdf5File(); + Hdf5File(Hdf5File&&) noexcept; + Hdf5File& operator=(Hdf5File&&) noexcept; + Hdf5File(const Hdf5File&) = delete; + Hdf5File& operator=(const Hdf5File&) = delete; + + Status open(const std::string& path); + bool is_open() const; + + // Names of the links of a group ("" is the root group). + Status links(const std::string& group_path, std::vector* names) const; + + bool has_dataset(const std::string& path) const; + Status dataset_info(const std::string& path, Hdf5DatasetInfo* out) const; + Status read_dataset_raw(const std::string& path, std::vector* out) const; + Status read_dataset_double(const std::string& path, std::vector* out) const; + + Status attribute_names(const std::string& object_path, std::vector* names) const; + Status attribute(const std::string& object_path, const std::string& name, Hdf5Attribute* out) const; + Status attribute_text(const std::string& object_path, const std::string& name, std::string* out) const; + +private: + struct Impl; + std::unique_ptr impl_; +}; + +} // namespace joc::io diff --git a/src/io/inflate.cpp b/src/io/inflate.cpp new file mode 100644 index 0000000..cc051e0 --- /dev/null +++ b/src/io/inflate.cpp @@ -0,0 +1,276 @@ +#include "io/inflate.h" + +#include + +namespace joc::io { + +namespace { + +class LsbBitReader { +public: + LsbBitReader(const std::uint8_t* data, std::size_t size) : data_(data), size_(size) {} + + bool ok() const { return ok_; } + std::size_t byte_position() const { return position_ >> 3; } + + std::uint32_t bits(unsigned count) { + std::uint32_t value = 0; + for (unsigned i = 0; i < count; ++i) { + if ((position_ >> 3) >= size_) { + ok_ = false; + return value; + } + const std::uint32_t bit = (data_[position_ >> 3] >> (position_ & 7u)) & 1u; + value |= bit << i; + ++position_; + } + return value; + } + + void align_to_byte() { position_ = (position_ + 7u) & ~static_cast(7u); } + + void skip_bytes(std::size_t count) { position_ += count * 8u; } + +private: + const std::uint8_t* data_; + std::size_t size_; + std::size_t position_ = 0; + bool ok_ = true; +}; + +struct Huffman { + std::uint16_t counts[16] = {}; + std::uint16_t symbols[288] = {}; + int max_length = 0; + + bool build(const std::uint8_t* lengths, int count) { + for (int i = 0; i < 16; ++i) { + counts[i] = 0; + } + for (int i = 0; i < count; ++i) { + counts[lengths[i]]++; + } + counts[0] = 0; + std::uint16_t offsets[16] = {}; + std::uint16_t total = 0; + for (int length = 1; length < 16; ++length) { + offsets[length] = total; + total = static_cast(total + counts[length]); + } + if (total == 0) { + return false; + } + for (int symbol = 0; symbol < count; ++symbol) { + const std::uint8_t length = lengths[symbol]; + if (length != 0) { + symbols[offsets[length]++] = static_cast(symbol); + } + } + max_length = 15; + while (max_length > 0 && counts[max_length] == 0) { + --max_length; + } + return max_length != 0; + } + + int decode(LsbBitReader* reader) const { + int code = 0; + int first = 0; + int index = 0; + for (int length = 1; length <= max_length; ++length) { + code |= static_cast(reader->bits(1)); + if (!reader->ok()) { + return -1; + } + const int count = counts[length]; + if (code - first < count) { + return symbols[index + (code - first)]; + } + index += count; + first = (first + count) << 1; + code <<= 1; + } + return -1; + } +}; + +constexpr std::uint16_t kLengthBase[29] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, + 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, + 195, 227, 258}; +constexpr std::uint8_t kLengthExtra[29] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, + 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; +constexpr std::uint16_t kDistanceBase[30] = {1, 2, 3, 4, 5, 7, 9, 13, + 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, + 4097, 6145, 8193, 12289, 16385, 24577}; +constexpr std::uint8_t kDistanceExtra[30] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, + 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; +constexpr std::uint8_t kCodeLengthOrder[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, + 14, 1, 15}; + +bool inflate_block_data(LsbBitReader* reader, const Huffman& literal, const Huffman& distance, + std::vector* out) { + for (;;) { + const int symbol = literal.decode(reader); + if (symbol < 0) { + return false; + } + if (symbol < 256) { + out->push_back(static_cast(symbol)); + continue; + } + if (symbol == 256) { + return true; + } + const int length_index = symbol - 257; + if (length_index >= 29) { + return false; + } + const std::uint32_t length = + kLengthBase[length_index] + reader->bits(kLengthExtra[length_index]); + const int distance_symbol = distance.decode(reader); + if (distance_symbol < 0 || distance_symbol >= 30) { + return false; + } + const std::uint32_t distance_value = + kDistanceBase[distance_symbol] + reader->bits(kDistanceExtra[distance_symbol]); + if (!reader->ok() || distance_value == 0 || distance_value > out->size()) { + return false; + } + const std::size_t start = out->size() - distance_value; + for (std::uint32_t i = 0; i < length; ++i) { + out->push_back((*out)[start + i]); + } + } +} + +bool inflate_fixed(LsbBitReader* reader, std::vector* out) { + std::uint8_t lengths[288]; + for (int i = 0; i < 144; ++i) { lengths[i] = 8; } + for (int i = 144; i < 256; ++i) { lengths[i] = 9; } + for (int i = 256; i < 280; ++i) { lengths[i] = 7; } + for (int i = 280; i < 288; ++i) { lengths[i] = 8; } + Huffman literal; + if (!literal.build(lengths, 288)) { + return false; + } + std::uint8_t distance_lengths[30]; + for (int i = 0; i < 30; ++i) { distance_lengths[i] = 5; } + Huffman distance; + if (!distance.build(distance_lengths, 30)) { + return false; + } + return inflate_block_data(reader, literal, distance, out); +} + +bool inflate_dynamic(LsbBitReader* reader, std::vector* out) { + const int literal_count = static_cast(reader->bits(5)) + 257; + const int distance_count = static_cast(reader->bits(5)) + 1; + const int code_length_count = static_cast(reader->bits(4)) + 4; + if (!reader->ok() || literal_count > 286 || distance_count > 30) { + return false; + } + std::uint8_t code_lengths[19] = {}; + for (int i = 0; i < code_length_count; ++i) { + code_lengths[kCodeLengthOrder[i]] = static_cast(reader->bits(3)); + } + if (!reader->ok()) { + return false; + } + Huffman code_length_tree; + if (!code_length_tree.build(code_lengths, 19)) { + return false; + } + std::uint8_t lengths[288 + 30] = {}; + const int total = literal_count + distance_count; + int index = 0; + while (index < total) { + const int symbol = code_length_tree.decode(reader); + if (symbol < 0) { + return false; + } + if (symbol < 16) { + lengths[index++] = static_cast(symbol); + continue; + } + int repeat = 0; + std::uint8_t value = 0; + if (symbol == 16) { + if (index == 0) { + return false; + } + value = lengths[index - 1]; + repeat = 3 + static_cast(reader->bits(2)); + } else if (symbol == 17) { + repeat = 3 + static_cast(reader->bits(3)); + } else { + repeat = 11 + static_cast(reader->bits(7)); + } + if (!reader->ok() || index + repeat > total) { + return false; + } + for (int i = 0; i < repeat; ++i) { + lengths[index++] = value; + } + } + Huffman literal; + if (!literal.build(lengths, literal_count)) { + return false; + } + Huffman distance; + if (!distance.build(lengths + literal_count, distance_count)) { + return false; + } + return inflate_block_data(reader, literal, distance, out); +} + +} // namespace + +bool inflate_raw(const std::uint8_t* data, std::size_t size, std::vector* out) { + if (data == nullptr || out == nullptr) { + return false; + } + out->clear(); + LsbBitReader reader(data, size); + for (;;) { + const std::uint32_t final_block = reader.bits(1); + const std::uint32_t type = reader.bits(2); + if (!reader.ok()) { + return false; + } + if (type == 0) { + reader.align_to_byte(); + const std::size_t position = reader.byte_position(); + if (position + 4 > size) { + return false; + } + const std::uint16_t length = static_cast(data[position] | (data[position + 1] << 8)); + const std::uint16_t complement = + static_cast(data[position + 2] | (data[position + 3] << 8)); + if (static_cast(length ^ 0xFFFFu) != complement) { + return false; + } + if (position + 4 + length > size) { + return false; + } + out->insert(out->end(), data + position + 4, data + position + 4 + length); + reader.skip_bytes(4u + length); + } else if (type == 1) { + if (!inflate_fixed(&reader, out)) { + return false; + } + } else if (type == 2) { + if (!inflate_dynamic(&reader, out)) { + return false; + } + } else { + return false; + } + if (final_block != 0u) { + break; + } + } + return true; +} + +} // namespace joc::io diff --git a/src/io/inflate.h b/src/io/inflate.h new file mode 100644 index 0000000..3a77dc5 --- /dev/null +++ b/src/io/inflate.h @@ -0,0 +1,12 @@ + +#pragma once + +#include +#include +#include + +namespace joc::io { + +bool inflate_raw(const std::uint8_t* data, std::size_t size, std::vector* out); + +} // namespace joc::io diff --git a/src/io/npy.cpp b/src/io/npy.cpp new file mode 100644 index 0000000..f2a4ac4 --- /dev/null +++ b/src/io/npy.cpp @@ -0,0 +1,420 @@ +#include "io/npy.h" + +#include + +namespace joc::io { + +namespace { + +std::uint16_t read_u16(const std::uint8_t* p) { return static_cast(p[0] | (p[1] << 8)); } +std::uint32_t read_u32(const std::uint8_t* p) { + return static_cast(p[0]) | (static_cast(p[1]) << 8) | + (static_cast(p[2]) << 16) | (static_cast(p[3]) << 24); +} + +NpyType classify(const std::string& descr) { + if (descr == " 2 && descr[0] == '<' && descr[1] == 'U') { + return NpyType::Unicode; + } + if (descr.size() > 2 && descr[0] == '=' && descr[1] == 'U') { + return NpyType::Unicode; + } + return NpyType::Unknown; +} + +std::size_t unicode_length(const std::string& descr) { + std::size_t index = 0; + while (index < descr.size() && (descr[index] == '<' || descr[index] == '=')) { + ++index; + } + if (index >= descr.size() || descr[index] != 'U') { + return 0; + } + ++index; + std::size_t value = 0; + bool any = false; + while (index < descr.size() && descr[index] >= '0' && descr[index] <= '9') { + value = value * 10 + static_cast(descr[index] - '0'); + ++index; + any = true; + } + return any ? value : 0; +} + +bool is_big_endian(const std::string& descr) { return !descr.empty() && descr[0] == '>'; } + +bool header_value(const std::string& header, const std::string& key, std::string* out) { + const std::string needle = "'" + key + "'"; + const std::size_t position = header.find(needle); + if (position == std::string::npos) { + return false; + } + const std::size_t colon = header.find(':', position + needle.size()); + if (colon == std::string::npos) { + return false; + } + std::size_t start = colon + 1; + while (start < header.size() && (header[start] == ' ' || header[start] == '\t')) { + ++start; + } + *out = header.substr(start); + return true; +} + +} // namespace + +std::size_t NpyArray::element_count() const { + std::size_t count = 1; + for (const std::int64_t dimension : shape) { + count *= static_cast(dimension < 0 ? 0 : dimension); + } + return count; +} + +std::size_t NpyArray::element_size() const { + switch (type) { + case NpyType::Float64: return 8; + case NpyType::Float32: return 4; + case NpyType::Int64: return 8; + case NpyType::Int32: return 4; + case NpyType::Int16: return 2; + case NpyType::UInt8: return 1; + case NpyType::Complex128: return 16; + case NpyType::Unicode: return item_bytes; + default: return 0; + } +} + +bool parse_npy(const std::uint8_t* data, std::size_t size, NpyArray* out, std::string* error) { + if (data == nullptr || out == nullptr) { + return false; + } + const std::uint8_t magic[6] = {0x93u, 'N', 'U', 'M', 'P', 'Y'}; + if (size < 10u || std::memcmp(data, magic, 6) != 0) { + if (error != nullptr) { *error = "not a .npy image"; } + return false; + } + const std::uint8_t major = data[6]; + std::size_t header_length = 0; + std::size_t header_offset = 0; + if (major == 1u) { + header_length = read_u16(data + 8); + header_offset = 10; + } else if (major == 2u || major == 3u) { + if (size < 12u) { + if (error != nullptr) { *error = "truncated .npy v2 header"; } + return false; + } + header_length = read_u32(data + 8); + header_offset = 12; + } else { + if (error != nullptr) { *error = "unsupported .npy version " + std::to_string(major); } + return false; + } + if (header_offset + header_length > size) { + if (error != nullptr) { *error = "truncated .npy header"; } + return false; + } + const std::string header(reinterpret_cast(data + header_offset), header_length); + + out->descr.clear(); + std::string value; + if (!header_value(header, "descr", &value)) { + if (error != nullptr) { *error = ".npy header without descr"; } + return false; + } + const std::size_t first_quote = value.find('\''); + const std::size_t second_quote = + first_quote == std::string::npos ? std::string::npos : value.find('\'', first_quote + 1); + if (first_quote == std::string::npos || second_quote == std::string::npos) { + if (error != nullptr) { *error = ".npy descr is not a quoted string"; } + return false; + } + out->descr = value.substr(first_quote + 1, second_quote - first_quote - 1); + out->type = classify(out->descr); + if (out->type == NpyType::Unknown) { + if (error != nullptr) { *error = "unsupported .npy dtype " + out->descr; } + return false; + } + out->item_bytes = 0; + if (out->type == NpyType::Unicode) { + const std::size_t length = unicode_length(out->descr); + if (length == 0) { + if (error != nullptr) { *error = "malformed unicode .npy dtype " + out->descr; } + return false; + } + out->item_bytes = length * 4u; + } + + out->fortran_order = header.find("'fortran_order': True") != std::string::npos; + + if (!header_value(header, "shape", &value)) { + if (error != nullptr) { *error = ".npy header without shape"; } + return false; + } + out->shape.clear(); + for (std::size_t i = 0; i < value.size(); ++i) { + if (value[i] >= '0' && value[i] <= '9') { + long long dimension = 0; + while (i < value.size() && value[i] >= '0' && value[i] <= '9') { + dimension = dimension * 10 + (value[i] - '0'); + ++i; + } + out->shape.push_back(dimension); + } else if (value[i] == ')') { + break; + } + } + + const std::size_t expected = out->element_count() * out->element_size(); + if (header_offset + header_length + expected > size) { + if (error != nullptr) { + *error = ".npy payload truncated (need " + std::to_string(expected) + " bytes)"; + } + return false; + } + out->data = data + header_offset + header_length; + out->data_bytes = expected; + return true; +} + +bool npy_shape_is(const NpyArray& array, const std::vector& expected) { + return array.shape == expected; +} + +namespace { + +template +void load_le(const std::uint8_t* source, std::size_t count, bool swap, std::vector* out) { + out->resize(count); + std::memcpy(out->data(), source, count * sizeof(T)); + if (swap) { + std::uint8_t* bytes = reinterpret_cast(out->data()); + for (std::size_t i = 0; i < count; ++i) { + for (std::size_t b = 0; b < sizeof(T) / 2; ++b) { + const std::uint8_t temporary = bytes[i * sizeof(T) + b]; + bytes[i * sizeof(T) + b] = bytes[i * sizeof(T) + sizeof(T) - 1 - b]; + bytes[i * sizeof(T) + sizeof(T) - 1 - b] = temporary; + } + } + } +} + +} // namespace + +bool npy_to_double(const NpyArray& array, std::vector* out, std::string* error) { + const bool swap = is_big_endian(array.descr); + const std::size_t count = array.element_count(); + switch (array.type) { + case NpyType::Float64: + load_le(array.data, count, swap, out); + return true; + case NpyType::Complex128: + load_le(array.data, count * 2u, swap, out); + return true; + case NpyType::Float32: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + case NpyType::Int64: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + case NpyType::Int32: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + case NpyType::Int16: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + case NpyType::UInt8: { + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(array.data[i]); + } + return true; + } + default: + if (error != nullptr) { *error = "cannot convert " + array.descr + " to double"; } + return false; + } +} + +bool npy_to_int16(const NpyArray& array, std::vector* out, std::string* error) { + const bool swap = is_big_endian(array.descr); + const std::size_t count = array.element_count(); + switch (array.type) { + case NpyType::Int16: + load_le(array.data, count, swap, out); + return true; + case NpyType::Int32: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + case NpyType::Int64: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + default: + if (error != nullptr) { *error = "cannot convert " + array.descr + " to int16"; } + return false; + } +} + +bool npy_to_int32(const NpyArray& array, std::vector* out, std::string* error) { + const bool swap = is_big_endian(array.descr); + const std::size_t count = array.element_count(); + switch (array.type) { + case NpyType::Int32: + load_le(array.data, count, swap, out); + return true; + case NpyType::Int64: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + case NpyType::Int16: { + std::vector values; + load_le(array.data, count, swap, &values); + out->resize(count); + for (std::size_t i = 0; i < count; ++i) { + (*out)[i] = static_cast(values[i]); + } + return true; + } + default: + if (error != nullptr) { *error = "cannot convert " + array.descr + " to int32"; } + return false; + } +} + +bool npy_to_uint8(const NpyArray& array, std::vector* out, std::string* error) { + if (array.type != NpyType::UInt8) { + if (error != nullptr) { *error = "cannot convert " + array.descr + " to uint8"; } + return false; + } + out->assign(array.data, array.data + array.element_count()); + return true; +} + +bool npy_unicode_to_utf8(const NpyArray& array, std::string* out, std::string* error) { + if (array.type != NpyType::Unicode) { + if (error != nullptr) { *error = "not a unicode .npy member: " + array.descr; } + return false; + } + if (array.shape.size() != 0) { + if (error != nullptr) { *error = "unicode .npy member must be a scalar"; } + return false; + } + out->clear(); + const std::size_t count = array.item_bytes / 4u; + for (std::size_t i = 0; i < count; ++i) { + const std::uint8_t* p = array.data + i * 4u; + const std::uint32_t code = static_cast(p[0]) | (static_cast(p[1]) << 8) | + (static_cast(p[2]) << 16) | + (static_cast(p[3]) << 24); + if (code == 0u) { + break; + } + if (code < 0x80u) { + out->push_back(static_cast(code)); + } else if (code < 0x800u) { + out->push_back(static_cast(0xC0u | (code >> 6))); + out->push_back(static_cast(0x80u | (code & 0x3Fu))); + } else if (code < 0x10000u) { + out->push_back(static_cast(0xE0u | (code >> 12))); + out->push_back(static_cast(0x80u | ((code >> 6) & 0x3Fu))); + out->push_back(static_cast(0x80u | (code & 0x3Fu))); + } else { + out->push_back(static_cast(0xF0u | (code >> 18))); + out->push_back(static_cast(0x80u | ((code >> 12) & 0x3Fu))); + out->push_back(static_cast(0x80u | ((code >> 6) & 0x3Fu))); + out->push_back(static_cast(0x80u | (code & 0x3Fu))); + } + } + return true; +} + +bool npy_to_c_order(const NpyArray& array, std::vector* out, std::string* error) { + const std::size_t element = array.element_size(); + if (element == 0) { + if (error != nullptr) { *error = "unsupported element size for " + array.descr; } + return false; + } + if (!array.fortran_order) { + out->assign(array.data, array.data + array.data_bytes); + return true; + } + const std::size_t dimensions = array.shape.size(); + if (dimensions == 0) { + out->assign(array.data, array.data + element); + return true; + } + // Source (Fortran) strides in elements; destination is C order. + std::vector source_stride(dimensions, 1); + std::size_t running = 1; + for (std::size_t d = 0; d < dimensions; ++d) { + source_stride[d] = running; + running *= static_cast(array.shape[d]); + } + out->assign(array.data_bytes, 0); + std::vector index(dimensions, 0); + const std::size_t total = array.element_count(); + for (std::size_t linear = 0; linear < total; ++linear) { + std::size_t remainder = linear; + for (std::size_t d = dimensions; d-- > 0;) { + index[d] = remainder % static_cast(array.shape[d]); + remainder /= static_cast(array.shape[d]); + } + std::size_t source = 0; + for (std::size_t d = 0; d < dimensions; ++d) { + source += index[d] * source_stride[d]; + } + std::memcpy(out->data() + linear * element, array.data + source * element, element); + } + return true; +} + +} // namespace joc::io diff --git a/src/io/npy.h b/src/io/npy.h new file mode 100644 index 0000000..9246442 --- /dev/null +++ b/src/io/npy.h @@ -0,0 +1,42 @@ + +#pragma once + +#include +#include +#include + +namespace joc::io { + +enum class NpyType { Unknown, Float64, Float32, Int64, Int32, Int16, UInt8, Complex128, Unicode }; + +struct NpyArray { + std::string descr; + NpyType type = NpyType::Unknown; + bool fortran_order = false; + std::vector shape; + const std::uint8_t* data = nullptr; + std::size_t data_bytes = 0; + std::size_t item_bytes = 0; // bytes per element as stored + + std::size_t element_count() const; + std::size_t element_size() const; // bytes per element in the file +}; + +// Parses the header of one `.npy` image. `data` must outlive the NpyArray. +bool parse_npy(const std::uint8_t* data, std::size_t size, NpyArray* out, std::string* error); + +bool npy_to_double(const NpyArray& array, std::vector* out, std::string* error); +bool npy_to_int16(const NpyArray& array, std::vector* out, std::string* error); +bool npy_to_int32(const NpyArray& array, std::vector* out, std::string* error); +bool npy_to_uint8(const NpyArray& array, std::vector* out, std::string* error); + +bool npy_unicode_to_utf8(const NpyArray& array, std::string* out, std::string* error); + +// Materializes the array in C order as raw element bytes. Fortran-order members +// hybrid synthesis table as [count][4] row-major while the shipped table stores it +// Fortran-order, so passing the file bytes straight through would transpose it. +bool npy_to_c_order(const NpyArray& array, std::vector* out, std::string* error); + +bool npy_shape_is(const NpyArray& array, const std::vector& expected); + +} // namespace joc::io diff --git a/src/io/npy_writer.cpp b/src/io/npy_writer.cpp new file mode 100644 index 0000000..78434fe --- /dev/null +++ b/src/io/npy_writer.cpp @@ -0,0 +1,263 @@ +#include "io/npy_writer.h" + +#include +#include +#include +#include +#include +#include + +#include "foundation/fs_utf8.h" +#include "io/zip_reader.h" + +namespace joc::io { + +namespace { + +constexpr std::size_t kNpyHeaderAlignment = 64; + +void append_u16(std::vector* out, std::uint16_t value) { + out->push_back(static_cast(value & 0xFFu)); + out->push_back(static_cast((value >> 8) & 0xFFu)); +} + +void append_u32(std::vector* out, std::uint32_t value) { + for (int index = 0; index < 4; ++index) { + out->push_back(static_cast((value >> (8 * index)) & 0xFFu)); + } +} + +void append_bytes(std::vector* out, const void* data, std::size_t size) { + const std::uint8_t* bytes = static_cast(data); + out->insert(out->end(), bytes, bytes + size); +} + +std::string shape_literal(const std::vector& shape) { + if (shape.empty()) { + return "()"; + } + std::string text = "("; + for (std::size_t index = 0; index < shape.size(); ++index) { + if (index != 0u) { + text += ", "; + } + text += std::to_string(shape[index]); + } + if (shape.size() == 1u) { + text += ","; + } + text += ")"; + return text; +} + +} // namespace + +std::vector npy_image(const std::string& descr, + const std::vector& shape, + const std::vector& data) { + std::string header = "{'descr': '" + descr + "', 'fortran_order': False, 'shape': " + + shape_literal(shape) + ", }"; + // NumPy pads the header so that the payload starts on a 64-byte boundary. + const std::size_t preamble = 10u; // magic, version, two byte header length + std::size_t total = preamble + header.size() + 1u; + const std::size_t padding = (kNpyHeaderAlignment - (total % kNpyHeaderAlignment)) % + kNpyHeaderAlignment; + header.append(padding, ' '); + header.push_back('\n'); + + std::vector out; + out.reserve(preamble + header.size() + data.size()); + static const std::uint8_t kMagic[6] = {0x93u, 'N', 'U', 'M', 'P', 'Y'}; + append_bytes(&out, kMagic, sizeof(kMagic)); + out.push_back(1u); // major + out.push_back(0u); // minor + append_u16(&out, static_cast(header.size())); + append_bytes(&out, header.data(), header.size()); + append_bytes(&out, data.data(), data.size()); + return out; +} + +std::vector zip_bytes(const std::vector& members) { + std::vector out; + struct Entry { + std::string name; + std::uint32_t crc = 0; + std::uint32_t size = 0; + std::uint32_t offset = 0; + }; + std::vector entries; + entries.reserve(members.size()); + + for (const NpyMember& member : members) { + const std::string name = member.name + ".npy"; + const std::vector payload = npy_image(member.descr, member.shape, member.data); + Entry entry; + entry.name = name; + entry.crc = crc32_of(payload.data(), payload.size()); + entry.size = static_cast(payload.size()); + entry.offset = static_cast(out.size()); + entries.push_back(entry); + + append_u32(&out, 0x04034B50u); // local file header + append_u16(&out, 20u); // version needed + append_u16(&out, 0u); // flags + append_u16(&out, 0u); // method: stored + append_u16(&out, 0u); // time + append_u16(&out, 0x2821u); // date: 2000-01-01, fixed for reproducibility + append_u32(&out, entry.crc); + append_u32(&out, entry.size); + append_u32(&out, entry.size); + append_u16(&out, static_cast(name.size())); + append_u16(&out, 0u); // extra length + append_bytes(&out, name.data(), name.size()); + append_bytes(&out, payload.data(), payload.size()); + } + + const std::uint32_t directory_offset = static_cast(out.size()); + for (const Entry& entry : entries) { + append_u32(&out, 0x02014B50u); // central directory header + append_u16(&out, 20u); // version made by + append_u16(&out, 20u); // version needed + append_u16(&out, 0u); // flags + append_u16(&out, 0u); // method: stored + append_u16(&out, 0u); // time + append_u16(&out, 0x2821u); // date + append_u32(&out, entry.crc); + append_u32(&out, entry.size); + append_u32(&out, entry.size); + append_u16(&out, static_cast(entry.name.size())); + append_u16(&out, 0u); // extra + append_u16(&out, 0u); // comment + append_u16(&out, 0u); // disk + append_u16(&out, 0u); // internal attributes + append_u32(&out, 0u); // external attributes + append_u32(&out, entry.offset); + append_bytes(&out, entry.name.data(), entry.name.size()); + } + const std::uint32_t directory_size = static_cast(out.size()) - directory_offset; + + append_u32(&out, 0x06054B50u); // end of central directory + append_u16(&out, 0u); + append_u16(&out, 0u); + append_u16(&out, static_cast(entries.size())); + append_u16(&out, static_cast(entries.size())); + append_u32(&out, directory_size); + append_u32(&out, directory_offset); + append_u16(&out, 0u); + return out; +} + +bool write_zip(const std::string& path, const std::vector& members, + std::string* error) { + const std::vector bytes = zip_bytes(members); + std::FILE* stream = fs_utf8::fopen(path, "wb"); + if (stream == nullptr) { + if (error != nullptr) { + *error = "cannot open " + path + " for writing"; + } + return false; + } + const std::size_t written = std::fwrite(bytes.data(), 1, bytes.size(), stream); + const bool flushed = std::fclose(stream) == 0; + if (written != bytes.size() || !flushed) { + if (error != nullptr) { + *error = "short write to " + path; + } + return false; + } + return true; +} + +std::vector utf8_to_utf32le(const std::string& text) { + std::vector out; + out.reserve(text.size() * 4u); + std::size_t index = 0; + while (index < text.size()) { + const std::uint8_t lead = static_cast(text[index]); + std::uint32_t code = 0; + std::size_t extra = 0; + if (lead < 0x80u) { + code = lead; + } else if ((lead & 0xE0u) == 0xC0u) { + code = lead & 0x1Fu; + extra = 1; + } else if ((lead & 0xF0u) == 0xE0u) { + code = lead & 0x0Fu; + extra = 2; + } else if ((lead & 0xF8u) == 0xF0u) { + code = lead & 0x07u; + extra = 3; + } else { + code = 0xFFFDu; // invalid lead byte: substitute rather than fail + extra = 0; + } + ++index; + for (std::size_t count = 0; count < extra && index < text.size(); ++count) { + code = (code << 6) | (static_cast(text[index]) & 0x3Fu); + ++index; + } + for (int byte = 0; byte < 4; ++byte) { + out.push_back(static_cast((code >> (8 * byte)) & 0xFFu)); + } + } + return out; +} + +std::string python_float_repr(double value) { + if (std::isnan(value)) { + return "NaN"; + } + if (std::isinf(value)) { + return value > 0.0 ? "Infinity" : "-Infinity"; + } + // to_chars gives the shortest round-trip digits; Python's repr uses the same + // digits but its own notation, so the digits are re-laid-out here. + std::array buffer{}; + const std::to_chars_result converted = + std::to_chars(buffer.data(), buffer.data() + buffer.size(), value); + std::string text(buffer.data(), converted.ptr); + const bool negative = !text.empty() && text[0] == '-'; + const std::string body = negative ? text.substr(1) : text; + const std::size_t exponent_at = body.find_first_of("eE"); + std::string digits = body; + int exponent = 0; + if (exponent_at != std::string::npos) { + digits = body.substr(0, exponent_at); + exponent = std::atoi(body.c_str() + exponent_at + 1); + } + const std::size_t point = digits.find('.'); + std::string mantissa = digits; + if (point != std::string::npos) { + mantissa = digits.substr(0, point) + digits.substr(point + 1); + exponent += static_cast(point) - 1; + } else { + exponent += static_cast(digits.size()) - 1; + } + while (mantissa.size() > 1u && mantissa.back() == '0') { + mantissa.pop_back(); + } + // Python switches to exponent notation below 1e-4 and at 1e16 and above. + std::string result; + if (exponent < -4 || exponent >= 16) { + result = mantissa.substr(0, 1); + if (mantissa.size() > 1u) { + result += "." + mantissa.substr(1); + } + char tail[16]; + std::snprintf(tail, sizeof(tail), "e%+03d", exponent); + result += tail; + } else if (exponent >= 0) { + if (static_cast(exponent) + 1u >= mantissa.size()) { + result = mantissa + std::string(static_cast(exponent) + 1u - mantissa.size(), '0'); + result += ".0"; + } else { + result = mantissa.substr(0, static_cast(exponent) + 1u) + "." + + mantissa.substr(static_cast(exponent) + 1u); + } + } else { + result = "0." + std::string(static_cast(-exponent - 1), '0') + mantissa; + } + return negative ? "-" + result : result; +} + +} // namespace joc::io diff --git a/src/io/npy_writer.h b/src/io/npy_writer.h new file mode 100644 index 0000000..f2e9075 --- /dev/null +++ b/src/io/npy_writer.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace joc::io { + +// NPY 1.0 images and a minimal ZIP container, used to write the compiled HRTF +// cache in exactly the layout the reader (and NumPy) expects. Only what the +// cache needs is implemented: little-endian C-order arrays and stored members. +struct NpyMember { + std::string name; // archive member name, without the .npy suffix + std::string descr; // NumPy dtype string, e.g. " shape; + std::vector data; // C order payload in the dtype's byte order +}; + +// Serializes one array as an NPY 1.0 image (magic, header, 64-byte aligned). +std::vector npy_image(const std::string& descr, + const std::vector& shape, + const std::vector& data); + +// Writes a ZIP archive with stored (uncompressed) members. The upstream reader +// accepts stored members, and compression would need a deflate encoder. +bool write_zip(const std::string& path, const std::vector& members, + std::string* error); + +// Serializes the archive in memory (same layout as write_zip). +std::vector zip_bytes(const std::vector& members); + +// UTF-8 text as the payload of a NumPy Unicode scalar string (''). +std::vector utf8_to_utf32le(const std::string& text); + +// Python's repr() for a double: shortest round-trip digits with Python's +// exponent rules, which is what json.dumps emits for the cache metadata. +std::string python_float_repr(double value); + +} // namespace joc::io diff --git a/src/io/process.cpp b/src/io/process.cpp new file mode 100644 index 0000000..583f58a --- /dev/null +++ b/src/io/process.cpp @@ -0,0 +1,186 @@ +#include "io/process.h" +#include "foundation/fs_utf8.h" + +#include +#include +#include +#include + +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#else +#include +#endif + +namespace joc::io { + +namespace { + +std::string quote_argument(const std::string& argument) { + if (!argument.empty() && argument.find_first_of(" \t\"") == std::string::npos) { + return argument; + } + std::string quoted = "\""; + unsigned backslashes = 0; + for (const char c : argument) { + if (c == '\\') { + ++backslashes; + continue; + } + if (c == '"') { + quoted.append(backslashes * 2 + 1, '\\'); + quoted.push_back('"'); + backslashes = 0; + continue; + } + quoted.append(backslashes, '\\'); + backslashes = 0; + quoted.push_back(c); + } + quoted.append(backslashes * 2, '\\'); + quoted.push_back('"'); + return quoted; +} + +std::string tail_of(const std::string& text, std::size_t limit) { + if (text.size() <= limit) { + return text; + } + return text.substr(text.size() - limit); +} + +} // namespace + +Status run_process(const std::vector& argv, ProcessResult* out) { + if (out == nullptr || argv.empty()) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, "empty command"); + } + out->output.clear(); + out->exit_code = 0; + + const std::filesystem::path log_path = + std::filesystem::temp_directory_path() / + ("joc_process_" + std::to_string(std::random_device{}()) + ".log"); + + auto read_log = [&]() { +#if defined(_WIN32) + return; // the Windows branch reads the handle it opened +#else + std::ifstream log = fs_utf8::open_input(fs_utf8::from_path(log_path)); + if (log) { + std::string text((std::istreambuf_iterator(log)), + std::istreambuf_iterator()); + out->output = tail_of(text, 4096); + } +#endif + }; + +#if defined(_WIN32) + std::string command; + for (std::size_t i = 0; i < argv.size(); ++i) { + if (i != 0) { + command.push_back(' '); + } + command += quote_argument(argv[i]); + } + auto widen = [](const std::string& text) { + if (text.empty()) { + return std::wstring(); + } + const int size = MultiByteToWideChar(CP_UTF8, 0, text.c_str(), + static_cast(text.size()), nullptr, 0); + std::wstring wide(static_cast(size), L'\0'); + MultiByteToWideChar(CP_UTF8, 0, text.c_str(), static_cast(text.size()), wide.data(), + size); + return wide; + }; + const std::wstring wide_command = widen(command); + const std::wstring wide_log = widen(fs_utf8::from_path(log_path)); + + SECURITY_ATTRIBUTES attributes{}; + attributes.nLength = sizeof(attributes); + attributes.bInheritHandle = TRUE; + // DELETE access plus FILE_FLAG_DELETE_ON_CLOSE means the log disappears when + // the last handle goes away - including when this process is killed, which + // would otherwise leave joc_process_*.log litter in the temp directory. + HANDLE log_handle = CreateFileW( + wide_log.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &attributes, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, nullptr); + if (log_handle == INVALID_HANDLE_VALUE) { + return Status::fail(JOC_ERR_IO, stage::kOutput, "cannot create the process log file"); + } + + // A delete-on-close file cannot be reopened by name (it is delete-pending), so + // the child's output is read back through the handle it wrote to. + auto read_log_handle = [&]() { + LARGE_INTEGER start{}; + start.QuadPart = 0; + if (!SetFilePointerEx(log_handle, start, nullptr, FILE_BEGIN)) { + return; + } + std::string text; + char buffer[1024]; + DWORD count = 0; + while (ReadFile(log_handle, buffer, sizeof(buffer), &count, nullptr) && count > 0) { + text.append(buffer, count); + } + out->output = tail_of(text, 4096); + }; + + STARTUPINFOW startup{}; + startup.cb = sizeof(startup); + startup.dwFlags = STARTF_USESTDHANDLES; + startup.hStdOutput = log_handle; + startup.hStdError = log_handle; + startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + PROCESS_INFORMATION process{}; + + std::vector mutable_command(wide_command.begin(), wide_command.end()); + mutable_command.push_back(L'\0'); + const BOOL started = CreateProcessW(nullptr, mutable_command.data(), nullptr, nullptr, TRUE, + CREATE_NO_WINDOW, nullptr, nullptr, &startup, &process); + if (!started) { + CloseHandle(log_handle); // delete-on-close removes the file + return Status::fail(JOC_ERR_LIBRARY_MISSING, stage::kOutput, + "cannot start " + argv[0] + " (is it on PATH?)"); + } + WaitForSingleObject(process.hProcess, INFINITE); + DWORD exit_code = 0; + GetExitCodeProcess(process.hProcess, &exit_code); + CloseHandle(process.hThread); + CloseHandle(process.hProcess); + // Read the log before the delete-on-close handle goes away. + read_log_handle(); + CloseHandle(log_handle); + out->exit_code = static_cast(exit_code); +#else + std::string command; + for (std::size_t i = 0; i < argv.size(); ++i) { + if (i != 0) { + command.push_back(' '); + } + command += quote_argument(argv[i]); + } + command += " > " + quote_argument(fs_utf8::from_path(log_path)) + " 2>&1"; + const int status = std::system(command.c_str()); + // system() reports a wait status, not the child's exit code. + out->exit_code = status == -1 ? 127u + : WIFEXITED(status) ? static_cast(WEXITSTATUS(status)) + : 128u; + read_log(); + std::error_code ignored; + std::filesystem::remove(log_path, ignored); +#endif + + if (out->exit_code != 0) { + return Status::fail(JOC_ERR_INPUT_FORMAT, stage::kOutput, + argv[0] + " failed with exit code " + std::to_string(out->exit_code) + + (out->output.empty() ? "" : ": " + tail_of(out->output, 400))); + } + return Status::success(); +} + +} // namespace joc::io diff --git a/src/io/process.h b/src/io/process.h new file mode 100644 index 0000000..fd6af45 --- /dev/null +++ b/src/io/process.h @@ -0,0 +1,19 @@ + +#pragma once + +#include +#include +#include + +#include "foundation/status.h" + +namespace joc::io { + +struct ProcessResult { + std::uint32_t exit_code = 0; + std::string output; +}; + +Status run_process(const std::vector& argv, ProcessResult* out); + +} // namespace joc::io diff --git a/src/io/wav_writer.cpp b/src/io/wav_writer.cpp new file mode 100644 index 0000000..cccf85c --- /dev/null +++ b/src/io/wav_writer.cpp @@ -0,0 +1,242 @@ +#include "io/wav_writer.h" +#include "foundation/fs_utf8.h" + +#include +#include +#include +#include +#include + +namespace joc::io { + +namespace { + +constexpr std::uint16_t kWaveFormatPcm = 0x0001; +constexpr std::uint16_t kWaveFormatIeeeFloat = 0x0003; +constexpr std::uint16_t kWaveFormatExtensible = 0xFFFE; +constexpr std::uint8_t kPcmGuid[16] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; +constexpr std::uint8_t kFloatGuid[16] = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}; + +void put_u16(std::string* out, std::uint16_t value) { + char buffer[2]; + std::memcpy(buffer, &value, 2); + out->append(buffer, 2); +} + +void put_u32(std::string* out, std::uint32_t value) { + char buffer[4]; + std::memcpy(buffer, &value, 4); + out->append(buffer, 4); +} + +void put_u64(std::string* out, std::uint64_t value) { + char buffer[8]; + std::memcpy(buffer, &value, 8); + out->append(buffer, 8); +} + +// Port of speaker_wav._fmt_chunk. +std::string fmt_chunk(std::uint32_t channels, std::uint32_t rate, SampleFormat format, WavInfo* info) { + std::uint16_t simple_tag = 0; + const std::uint8_t* guid = nullptr; + if (format == SampleFormat::Float32) { + info->bits_per_sample = 32; + info->bytes_per_sample = 4; + simple_tag = kWaveFormatIeeeFloat; + guid = kFloatGuid; + } else { + info->bits_per_sample = 24; + info->bytes_per_sample = 3; + simple_tag = kWaveFormatPcm; + guid = kPcmGuid; + } + const std::uint32_t block_align = channels * info->bytes_per_sample; + const std::uint32_t byte_rate = rate * block_align; + info->block_align = block_align; + + std::string body; + if (channels <= 2) { + put_u16(&body, simple_tag); + put_u16(&body, static_cast(channels)); + put_u32(&body, rate); + put_u32(&body, byte_rate); + put_u16(&body, static_cast(block_align)); + put_u16(&body, static_cast(info->bits_per_sample)); + } else { + put_u16(&body, kWaveFormatExtensible); + put_u16(&body, static_cast(channels)); + put_u32(&body, rate); + put_u32(&body, byte_rate); + put_u16(&body, static_cast(block_align)); + put_u16(&body, static_cast(info->bits_per_sample)); + put_u16(&body, 22); + put_u16(&body, static_cast(info->bits_per_sample)); + put_u32(&body, 0); + body.append(reinterpret_cast(guid), 16); + } + return body; +} + +// int32 conversion identical to NumPy's float32 -> int32 cast after clipping. +std::int32_t to_int32(const float value) { + if (!std::isfinite(value)) { + return std::numeric_limits::min(); + } + return static_cast(value); +} + +} // namespace + +void pack_int24(const float* interleaved, std::size_t frames, std::size_t channels, + std::string* out) { + const std::size_t count = frames * channels; + out->resize(count * 3); + char* target = out->data(); + for (std::size_t i = 0; i < count; ++i) { + float value = interleaved[i]; + if (value > 1.0f) { + value = 1.0f; + } else if (value < -1.0f) { + value = -1.0f; + } + const std::int32_t scaled = to_int32(value * 8388607.0f); + const std::uint32_t bits = static_cast(scaled); + target[i * 3 + 0] = static_cast(bits & 0xFFu); + target[i * 3 + 1] = static_cast((bits >> 8) & 0xFFu); + target[i * 3 + 2] = static_cast((bits >> 16) & 0xFFu); + } +} + +WavWriter::~WavWriter() { + if (file_ != nullptr) { + std::fclose(file_); + file_ = nullptr; + } +} + +Status WavWriter::open(const std::string& path, std::uint32_t channels, std::uint32_t rate, + SampleFormat format, std::uint64_t total_frames) { + if (channels == 0 || rate == 0) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, + "WAV writer needs a positive channel count and rate"); + } + path_ = path; + channels_ = channels; + total_frames_ = total_frames; + frames_written_ = 0; + finalized_ = false; + info_ = WavInfo{}; + info_.format = format; + + const std::string fmt = fmt_chunk(channels, rate, format, &info_); + const std::uint64_t data_size = total_frames * info_.block_align; + info_.data_bytes = data_size; + const std::uint64_t riff_file_size = 12u + 8u + fmt.size() + 8u + data_size; + const bool rf64 = (riff_file_size - 8u) > 0xFFFFFFFFull; + info_.rf64 = rf64; + + std::string header; + if (rf64) { + const std::uint64_t file_size = 12u + 36u + 8u + fmt.size() + 8u + data_size; + header.append("RF64", 4); + put_u32(&header, 0xFFFFFFFFu); + header.append("WAVE", 4); + header.append("ds64", 4); + put_u32(&header, 28); + put_u64(&header, file_size - 8u); + put_u64(&header, data_size); + put_u64(&header, total_frames); + put_u32(&header, 0); + } else { + header.append("RIFF", 4); + put_u32(&header, static_cast(riff_file_size - 8u)); + header.append("WAVE", 4); + } + header.append("fmt ", 4); + put_u32(&header, static_cast(fmt.size())); + header.append(fmt); + header.append("data", 4); + put_u32(&header, rf64 ? 0xFFFFFFFFu : static_cast(data_size)); + + file_ = fs_utf8::fopen(path, "wb"); + if (file_ == nullptr) { + // The reference creates the parent directory itself. + std::error_code ignored; + const std::filesystem::path parent = std::filesystem::path(path).parent_path(); + if (!parent.empty()) { + std::filesystem::create_directories(parent, ignored); + } + file_ = fs_utf8::fopen(path, "wb"); + } + if (file_ == nullptr) { + return Status::fail(JOC_ERR_OUTPUT_OPEN, stage::kOutput, "cannot open " + path); + } + if (std::fwrite(header.data(), 1, header.size(), file_) != header.size()) { + std::fclose(file_); + file_ = nullptr; + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "cannot write header to " + path); + } + return Status::success(); +} + +Status WavWriter::write(const double* interleaved, std::size_t frames) { + if (file_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kOutput, "WAV writer is not open"); + } + if (frames == 0) { + return Status::success(); + } + if (frames_written_ + frames > total_frames_) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, + "WAV writer received more frames than the header declared (declared " + + std::to_string(total_frames_) + ", written " + + std::to_string(frames_written_) + ", requested " + + std::to_string(frames) + ")"); + } + const std::size_t count = frames * channels_; + if (info_.format == SampleFormat::Float32) { + std::vector converted(count); + for (std::size_t i = 0; i < count; ++i) { + converted[i] = static_cast(interleaved[i]); + } + if (std::fwrite(converted.data(), sizeof(float), count, file_) != count) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "write failed for " + path_); + } + } else { + std::vector converted(count); + for (std::size_t i = 0; i < count; ++i) { + converted[i] = static_cast(interleaved[i]); + } + std::string packed; + pack_int24(converted.data(), frames, channels_, &packed); + if (std::fwrite(packed.data(), 1, packed.size(), file_) != packed.size()) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "write failed for " + path_); + } + } + frames_written_ += frames; + return Status::success(); +} + +Status WavWriter::finalize() { + if (file_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kOutput, "WAV writer is not open"); + } + if (frames_written_ != total_frames_) { + std::fclose(file_); + file_ = nullptr; + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, + "WAV writer wrote " + std::to_string(frames_written_) + " of " + + std::to_string(total_frames_) + " frames"); + } + const int result = std::fclose(file_); + file_ = nullptr; + finalized_ = true; + if (result != 0) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "close failed for " + path_); + } + return Status::success(); +} + +} // namespace joc::io diff --git a/src/io/wav_writer.h b/src/io/wav_writer.h new file mode 100644 index 0000000..5cbc9b7 --- /dev/null +++ b/src/io/wav_writer.h @@ -0,0 +1,61 @@ +// Port of src/speaker_wav.py. + +#pragma once + +#include +#include +#include + +#include "foundation/status.h" +#include "joc_core.h" + +namespace joc::io { + +enum class SampleFormat { Float32, Int24 }; + +struct WavInfo { + SampleFormat format = SampleFormat::Float32; + std::uint32_t bits_per_sample = 32; + std::uint32_t bytes_per_sample = 4; + std::uint32_t block_align = 0; + std::uint64_t data_bytes = 0; + bool rf64 = false; +}; + +// int24 packing shared by the WAV and ADM writers: +// trunc(clip(v, -1, 1) * 8388607.0f) with the low three bytes written LE. +// NaN follows NumPy's float->int cast (INT32_MIN) so that the C++ conversion is +// never undefined; the reference passes it through unguarded (plan TD-3.11). +void pack_int24(const float* interleaved, std::size_t frames, std::size_t channels, + std::string* out); + +class WavWriter { +public: + WavWriter() = default; + ~WavWriter(); + + WavWriter(const WavWriter&) = delete; + WavWriter& operator=(const WavWriter&) = delete; + + // `total_frames` must be known up front: the header depends on it. + Status open(const std::string& path, std::uint32_t channels, std::uint32_t rate, + SampleFormat format, std::uint64_t total_frames); + + Status write(const double* interleaved, std::size_t frames); + + Status finalize(); + + const WavInfo& info() const { return info_; } + std::uint64_t frames_written() const { return frames_written_; } + +private: + std::FILE* file_ = nullptr; + std::string path_; + WavInfo info_; + std::uint32_t channels_ = 0; + std::uint64_t total_frames_ = 0; + std::uint64_t frames_written_ = 0; + bool finalized_ = false; +}; + +} // namespace joc::io diff --git a/src/io/zip_reader.cpp b/src/io/zip_reader.cpp new file mode 100644 index 0000000..b2bfb52 --- /dev/null +++ b/src/io/zip_reader.cpp @@ -0,0 +1,215 @@ +#include "io/zip_reader.h" +#include "foundation/fs_utf8.h" + +#include +#include + +#include "io/inflate.h" + +namespace joc::io { + +namespace { + +constexpr std::uint32_t kLocalHeaderSignature = 0x04034b50u; +constexpr std::uint32_t kCentralHeaderSignature = 0x02014b50u; +constexpr std::uint32_t kEndOfCentralDirectory = 0x06054b50u; + +std::uint16_t read_u16(const std::uint8_t* p) { + return static_cast(p[0] | (p[1] << 8)); +} + +std::uint32_t read_u32(const std::uint8_t* p) { + return static_cast(p[0]) | (static_cast(p[1]) << 8) | + (static_cast(p[2]) << 16) | (static_cast(p[3]) << 24); +} + +} // namespace + +std::uint32_t crc32_of(const std::uint8_t* data, std::size_t size) { + static std::uint32_t table[256]; + static bool ready = false; + if (!ready) { + for (std::uint32_t i = 0; i < 256; ++i) { + std::uint32_t value = i; + for (int bit = 0; bit < 8; ++bit) { + value = (value & 1u) ? (0xEDB88320u ^ (value >> 1)) : (value >> 1); + } + table[i] = value; + } + ready = true; + } + std::uint32_t crc = 0xFFFFFFFFu; + for (std::size_t i = 0; i < size; ++i) { + crc = table[(crc ^ data[i]) & 0xFFu] ^ (crc >> 8); + } + return crc ^ 0xFFFFFFFFu; +} + +bool ZipArchive::open(const std::string& path, std::string* error) { + entries_.clear(); + data_.clear(); + std::FILE* file = fs_utf8::fopen(path, "rb"); + if (file == nullptr) { + if (error != nullptr) { + *error = "cannot open " + path; + } + return false; + } + std::fseek(file, 0, SEEK_END); + const long long size = std::ftell(file); + std::fseek(file, 0, SEEK_SET); + if (size <= 0) { + std::fclose(file); + if (error != nullptr) { + *error = "empty file " + path; + } + return false; + } + data_.resize(static_cast(size)); + const std::size_t got = std::fread(data_.data(), 1, data_.size(), file); + std::fclose(file); + if (got != data_.size()) { + if (error != nullptr) { + *error = "short read on " + path; + } + return false; + } + + std::size_t eocd = std::string::npos; + const std::size_t scan_start = data_.size() > 65557u ? data_.size() - 65557u : 0u; + for (std::size_t i = data_.size(); i-- > scan_start;) { + if (i + 4u <= data_.size() && read_u32(&data_[i]) == kEndOfCentralDirectory) { + eocd = i; + break; + } + if (i == 0) { + break; + } + } + if (eocd == std::string::npos || eocd + 22u > data_.size()) { + if (error != nullptr) { + *error = "not a zip archive (no end-of-central-directory)"; + } + return false; + } + const std::uint16_t entry_count = read_u16(&data_[eocd + 10]); + const std::uint32_t directory_offset = read_u32(&data_[eocd + 16]); + if (directory_offset >= data_.size()) { + if (error != nullptr) { + *error = "central directory offset out of range"; + } + return false; + } + std::size_t cursor = directory_offset; + for (std::uint16_t index = 0; index < entry_count; ++index) { + if (cursor + 46u > data_.size() || read_u32(&data_[cursor]) != kCentralHeaderSignature) { + if (error != nullptr) { + *error = "malformed central directory entry " + std::to_string(index); + } + return false; + } + ZipEntry entry; + entry.method = read_u16(&data_[cursor + 10]); + entry.crc32 = read_u32(&data_[cursor + 16]); + entry.compressed_size = read_u32(&data_[cursor + 20]); + entry.uncompressed_size = read_u32(&data_[cursor + 24]); + const std::uint16_t name_length = read_u16(&data_[cursor + 28]); + const std::uint16_t extra_length = read_u16(&data_[cursor + 30]); + const std::uint16_t comment_length = read_u16(&data_[cursor + 32]); + entry.local_header_offset = read_u32(&data_[cursor + 42]); + if (entry.compressed_size == 0xFFFFFFFFu || entry.uncompressed_size == 0xFFFFFFFFu || + entry.local_header_offset == 0xFFFFFFFFu) { + if (error != nullptr) { + *error = "zip64 archives are not supported"; + } + return false; + } + if (cursor + 46u + name_length > data_.size()) { + if (error != nullptr) { + *error = "member name out of range"; + } + return false; + } + entry.name.assign(reinterpret_cast(&data_[cursor + 46]), name_length); + entries_.push_back(std::move(entry)); + cursor += 46u + name_length + extra_length + comment_length; + } + return true; +} + +const ZipEntry* ZipArchive::find(const std::string& name) const { + for (const ZipEntry& entry : entries_) { + if (entry.name == name) { + return &entry; + } + } + return nullptr; +} + +bool ZipArchive::extract(const ZipEntry& entry, std::vector* out, + std::string* error) const { + if (out == nullptr) { + return false; + } + const std::size_t offset = entry.local_header_offset; + if (offset + 30u > data_.size() || read_u32(&data_[offset]) != kLocalHeaderSignature) { + if (error != nullptr) { + *error = "bad local header for " + entry.name; + } + return false; + } + const std::uint16_t name_length = read_u16(&data_[offset + 26]); + const std::uint16_t extra_length = read_u16(&data_[offset + 28]); + const std::size_t start = offset + 30u + name_length + extra_length; + if (start + entry.compressed_size > data_.size()) { + if (error != nullptr) { + *error = "member data out of range for " + entry.name; + } + return false; + } + if (entry.method == 0u) { + out->assign(data_.begin() + static_cast(start), + data_.begin() + static_cast(start + entry.compressed_size)); + } else if (entry.method == 8u) { + if (!inflate_raw(&data_[start], entry.compressed_size, out)) { + if (error != nullptr) { + *error = "deflate error in " + entry.name; + } + return false; + } + } else { + if (error != nullptr) { + *error = "unsupported compression method " + std::to_string(entry.method) + " for " + + entry.name; + } + return false; + } + if (entry.uncompressed_size != 0u && out->size() != entry.uncompressed_size) { + if (error != nullptr) { + *error = "size mismatch for " + entry.name + " (" + std::to_string(out->size()) + + " vs " + std::to_string(entry.uncompressed_size) + ")"; + } + return false; + } + if (entry.crc32 != 0u && crc32_of(out->data(), out->size()) != entry.crc32) { + if (error != nullptr) { + *error = "CRC mismatch for " + entry.name; + } + return false; + } + return true; +} + +bool ZipArchive::read_member(const std::string& name, std::vector* out, + std::string* error) const { + const ZipEntry* entry = find(name); + if (entry == nullptr) { + if (error != nullptr) { + *error = "member not found: " + name; + } + return false; + } + return extract(*entry, out, error); +} + +} // namespace joc::io diff --git a/src/io/zip_reader.h b/src/io/zip_reader.h new file mode 100644 index 0000000..9c032a6 --- /dev/null +++ b/src/io/zip_reader.h @@ -0,0 +1,38 @@ + +#pragma once + +#include +#include +#include + +namespace joc::io { + +struct ZipEntry { + std::string name; + std::uint16_t method = 0; + std::uint32_t crc32 = 0; + std::uint32_t compressed_size = 0; + std::uint32_t uncompressed_size = 0; + std::uint32_t local_header_offset = 0; +}; + +class ZipArchive { +public: + bool open(const std::string& path, std::string* error); + + const std::vector& entries() const { return entries_; } + + const ZipEntry* find(const std::string& name) const; + + bool extract(const ZipEntry& entry, std::vector* out, std::string* error) const; + + bool read_member(const std::string& name, std::vector* out, std::string* error) const; + +private: + std::vector data_; + std::vector entries_; +}; + +std::uint32_t crc32_of(const std::uint8_t* data, std::size_t size); + +} // namespace joc::io diff --git a/src/joc_bitstream/joc_huffman_tables.h b/src/joc_bitstream/joc_huffman_tables.h new file mode 100644 index 0000000..c3911a6 --- /dev/null +++ b/src/joc_bitstream/joc_huffman_tables.h @@ -0,0 +1,89 @@ +#pragma once + +// JOC Huffman trees required by the bitstream parser. + +static const int joc_huff_code_coarse_generic[][2] = +{ + { -1, 1}, { 2, -2}, { -96, 3}, { 4, -3}, { -95, 5}, { 6, 7}, { -4, -94}, { 8, 9}, { -5, -93}, { 10, 11}, + { -6, -92}, { 12, 13}, { -7, -91}, { 14, 15}, { 16, -90}, { -8, 17}, { 18, -89}, { -9, 19}, { 20, 21}, { -88, -10}, + { 22, 23}, { -11, -87}, { 24, 25}, { 26, -86}, { -12, 27}, { 28, -85}, { -13, 29}, { 30, 31}, { 32, -84}, { -14, 33}, + { 34, -15}, { -83, 35}, { 36, 37}, { -16, 38}, { -17, -82}, { 39, 40}, { 41, -81}, { 42, 43}, { 44, 45}, { 46, 47}, + { 48, 49}, { 50, 51}, { 52, -18}, { -78, 53}, { -19, 54}, { 55, 56}, { 57, 58}, { -22, 59}, { 60, 61}, { 62, 63}, + { 64, 65}, { 66, 67}, { 68, -20}, { -21, -79}, { -80, -25}, { 69, 70}, { -26, 71}, { 72, 73}, { 74, 75}, { 76, 77}, + { 78, 79}, { 80, 81}, { 82, 83}, { 84, 85}, { 86, 87}, { 88, 89}, { 90, 91}, { 92, 93}, { 94, -23}, { -74, -75}, + { -72, -73}, { -76, -77}, { -34, -35}, { -32, -33}, { -38, -39}, { -36, -37}, { -30, -31}, { -28, -29}, { -50, -51}, { -48, -49}, + { -54, -55}, { -52, -53}, { -42, -43}, { -40, -41}, { -46, -47}, { -44, -45}, { -66, -67}, { -64, -65}, { -70, -71}, { -68, -69}, + { -58, -59}, { -56, -57}, { -62, -63}, { -60, -61}, { -24, -27} +}; + +static const int joc_huff_code_fine_generic[][2] = +{ + { -1, 1}, { 2, 3}, { -2,-192}, { 4, 5}, { 6, -3}, {-191, 7}, { 8, 9}, { -4,-190}, { 10, 11}, { -5,-189}, + { 12, 13}, { -6, 14}, {-188, 15}, { 16, -7}, {-187, 17}, { 18, -8}, {-186, 19}, { 20, -9}, {-185, 21}, { 22, -10}, + {-184, 23}, { 24, -11}, { 25,-183}, { 26, 27}, { -12,-182}, { 28, 29}, { -13,-181}, { 30, 31}, {-180, -14}, { 32, 33}, + { 34,-179}, { -15, 35}, { 36,-178}, { -16, 37}, { 38,-177}, { 39, -17}, { 40, 41}, {-176, 42}, { -18, 43}, { -19, 44}, + {-175, 45}, { 46,-174}, { -20, 47}, {-173, 48}, { 49, -21}, { 50, 51}, { 52, -22}, { 53, 54}, {-172, 55}, {-171, -23}, + { 56, 57}, { 58,-170}, { 59, -24}, { -25, 60}, {-169, 61}, { 62, 63}, { 64, 65}, { 66, 67}, {-168, 68}, { -26, 69}, + {-167, -27}, { 70,-166}, {-165, 71}, { -29, 72}, { 73, 74}, { -30, 75}, { 76, 77}, { 78, 79}, { 80, -28}, { 81, 82}, + { 83,-163}, { -31, -33}, {-164,-161}, { 84, 85}, { 86, 87}, { 88, 89}, { 90, 91}, { 92, 93}, { 94, 95}, { 96, 97}, + { 98, 99}, { -32,-162}, { 100, 101}, { 102, 103}, { 104, 105}, { 106, 107}, { 108, 109}, { 110, 111}, {-160, 112}, { -36, -38}, + { 113, 114}, { 115, 116}, { 117, 118}, { 119, 120}, { 121, 122}, { 123, 124}, { 125, 126}, { 127, 128}, { 129, 130}, { 131, 132}, + { 133, -35}, {-158, 134}, {-155,-156}, { -37, -42}, { 135, 136}, { 137, 138}, { 139, 140}, { 141, 142}, { 143, 144}, { 145, 146}, + { 147, 148}, { 149, 150}, { 151, 152}, { 153, 154}, { 155, 156}, { 157, 158}, { 159, 160}, { 161, 162}, { 163, 164}, { 165, 166}, + { 167, 168}, { 169, 170}, { 171, 172}, { 173, 174}, { 175, 176}, { 177, 178}, { 179, 180}, { 181, 182}, { 183, 184}, {-157, 185}, + { -45, -48}, { 186, 187}, { 188, 189}, { -34, -41}, { 190, -39}, { -60, -61}, { -58, -59}, { -64, -65}, { -62, -63}, { -52, -53}, + { -50, -51}, { -56, -57}, { -54, -55}, { -76, -77}, { -74, -75}, { -80, -81}, { -78, -79}, { -68, -69}, { -66, -67}, { -72, -73}, + { -70, -71}, { -47, -49}, { -44, -46}, {-124,-125}, {-122,-123}, {-128,-129}, {-126,-127}, {-116,-117}, {-114,-115}, {-120,-121}, + {-118,-119}, {-140,-141}, {-138,-139}, {-144,-145}, {-142,-143}, {-132,-133}, {-130,-131}, {-136,-137}, {-134,-135}, { -92, -93}, + { -90, -91}, { -96, -97}, { -94, -95}, { -84, -85}, { -82, -83}, { -88, -89}, { -86, -87}, {-108,-109}, {-106,-107}, {-112,-113}, + {-110,-111}, {-100,-101}, { -98, -99}, {-104,-105}, {-102,-103}, {-154,-159}, {-148,-149}, {-146,-147}, {-152,-153}, {-150,-151}, + { -40, -43} +}; + +static const int joc_huff_code_coarse_coeff_sparse[][2] = +{ + { -1, 1}, { 2, 3}, { -2, -96}, { 4, 5}, { 6, -95}, { -3, 7}, { 8, 9}, { -4, 10}, { -94, 11}, { 12, -5}, + { -93, 13}, { 14, 15}, { -6, -92}, { 16, 17}, { 18, -7}, { -91, 19}, { 20, -8}, { -90, 21}, { 22, 23}, { -9, -89}, + { 24, 25}, { 26, -10}, { -88, 27}, { 28, 29}, { 30, -11}, { -87, 31}, { 32, 33}, { 34, 35}, { -12, -86}, { 36, 37}, + { 38, -13}, { 39, -85}, { 40, 41}, { 42, 43}, { -14, -84}, { 44, 45}, { 46, 47}, { -83, -15}, { 48, 49}, { 50, -16}, + { 51, 52}, { -82, 53}, { 54, -81}, { 55, 56}, { -17, 57}, { 58, -80}, { 59, 60}, { -18, 61}, { 62, 63}, { -79, 64}, + { -19, -78}, { 65, 66}, { 67, 68}, { 69, -20}, { -77, -21}, { 70, 71}, { 72, 73}, { 74, -76}, { 75, -22}, { 76, 77}, + { -75, 78}, { 79, 80}, { -54, -74}, { -73, 81}, { -23, 82}, { -50, -24}, { -55, -25}, { 83, -47}, { -49, -44}, { -71, 84}, + { -48, -51}, { 85, -72}, { -26, -53}, { -70, -27}, { 86, -45}, { 87, 88}, { -68, 89}, { -29, -43}, { 90, -30}, { -46, -69}, + { 91, -28}, { -52, -31}, { 92, -32}, { 93, -64}, { -67, 94}, { -36, -33}, { -63, -37}, { -65, -61}, { -66, -59}, { -34, -38}, + { -41, -42}, { -35, -60}, { -39, -57}, { -56, -40}, { -62, -58} +}; + +static const int joc_huff_code_fine_coeff_sparse[][2] = +{ + { 1, -1}, { 2, 3}, { 4, -2}, {-192, 5}, { 6, 7}, { 8, -3}, {-191, 9}, { 10, 11}, { 12,-190}, { -4, 13}, + { 14, 15}, {-189, -5}, { 16, 17}, { 18, -6}, {-188, 19}, { 20, 21}, { -7,-187}, { 22, 23}, { -8, 24}, {-186, 25}, + { -9, 26}, { 27,-185}, { 28, -10}, { 29, 30}, {-184, 31}, { -11, 32}, { 33,-183}, { 34, -12}, { 35,-182}, { 36, 37}, + { 38, -13}, {-181, 39}, { 40, -14}, { 41,-180}, { 42, 43}, {-179, -15}, { 44, -16}, { 45,-178}, { 46, 47}, { 48, 49}, + { 50,-177}, { -17, 51}, { -18, 52}, {-176, 53}, { 54, 55}, {-175, -19}, { 56, 57}, { 58, -20}, { 59,-174}, { 60, 61}, + { -21, 62}, { 63,-173}, { 64, 65}, { 66,-172}, { 67, 68}, { -22, 69}, { 70, 71}, { -23, 72}, {-171, 73}, { 74, 75}, + { 76, -24}, { 77,-170}, { -25, 78}, { 79, 80}, { 81,-169}, { 82, 83}, { 84, -26}, { 85,-168}, { 86, 87}, { 88, 89}, + {-167, 90}, { -27, 91}, { 92, -28}, { 93,-166}, { 94, -29}, { 95, 96}, { 97, 98}, {-165, 99}, { 100, -30}, {-164, 101}, + { 102, 103}, { 104, 105}, {-163, 106}, { -31, 107}, { -32, 108}, { 109, 110}, {-161, 111}, {-160,-162}, { 112, -34}, { -33, 113}, + { 114, 115}, { 116, 117}, { 118, 119}, { 120,-159}, { 121, 122}, { 123,-158}, { 124, 125}, { -36,-155}, { 126, 127}, { -35, 128}, + { 129, 130}, {-157, 131}, {-156, 132}, { -37, 133}, { 134, 135}, {-154, -38}, { 136, 137}, { -39, -41}, { 138,-153}, { 139, -40}, + {-149, 140}, { 141, 142}, { 143, 144}, {-151, 145}, { 146, 147}, { 148, -42}, { -43, 149}, { 150, 151}, {-152, 152}, { -46, -98}, + { 153, 154}, { 155,-147}, { 156, 157}, { 158,-107}, { 159, 160}, {-145,-150}, { -96, 161}, { 162, -45}, {-146, 163}, { 164, -97}, + {-108,-105}, {-148,-106}, { -44, 165}, { -94,-141}, { -99, 166}, { -89, 167}, { -50, -95}, {-100, -48}, {-144, 168}, { 169, 170}, + { -51,-142}, { -90, -91}, { -47, -49}, { 171, -53}, { -93,-143}, {-137,-138}, { -55,-101}, { 172, 173}, { -54, -86}, { -88, -87}, + {-103, 174}, { 175, -61}, {-109, 176}, { 177, 178}, { -52,-139}, { -57,-140}, { 179, 180}, { -56,-136}, { -58,-102}, { 181, 182}, + { -60,-135}, { 183,-104}, {-128,-134}, { -92, 184}, { -59, -62}, { 185, 186}, { -71,-133}, { 187,-127}, {-126, 188}, { -63, -64}, + { -85,-132}, { 189, -66}, {-121,-125}, { 190, -68}, { -74, -75}, { -70, -73}, { -81, -65}, {-118,-131}, { -72,-110}, {-119,-120}, + { -76, -84}, {-122,-130}, { -83,-117}, { -69, -78}, { -80, -82}, {-123,-124}, { -67,-116}, {-129, -77}, {-113,-114}, {-112,-115}, + { -79,-111} +}; + +static const int joc_huff_code_5ch_pos_index_sparse[][2] = +{ + { -1, 1}, { 2, 3}, { -4, -3}, { -2, -5} +}; + +static const int joc_huff_code_7ch_pos_index_sparse[][2] = +{ + { -1, 1}, { 2, 3}, { 4, 5}, { -4, -3}, { -2, -5}, { -6, -7} +}; diff --git a/src/joc_bitstream/joc_parser.cpp b/src/joc_bitstream/joc_parser.cpp new file mode 100644 index 0000000..18c8055 --- /dev/null +++ b/src/joc_bitstream/joc_parser.cpp @@ -0,0 +1,415 @@ +#include "joc_bitstream/joc_parser.h" + +#include +#include +#include +#include + +#include "foundation/bit_reader.h" +#include "joc_huffman_tables.h" + +namespace joc::joc { + +namespace { + +struct NumChannelsEntry { + std::uint32_t config; + std::int16_t channels; +}; +constexpr NumChannelsEntry kNumChannels[] = { + {0u, 5}, {1u, 7}, {2u, 7}, {3u, 5}, {4u, 7}, +}; + +struct NumBandsEntry { + std::uint32_t index; + std::int16_t bands; +}; +constexpr NumBandsEntry kNumBands[] = { + {0u, 1}, {1u, 3}, {2u, 5}, {3u, 7}, {4u, 9}, {5u, 12}, {6u, 15}, {7u, 23}, +}; + +// Floored modulo: Python's % operator semantics, so that the ported +inline std::int64_t floored_mod(std::int64_t value, std::int64_t modulus) { + const std::int64_t remainder = value % modulus; + return remainder < 0 ? remainder + modulus : remainder; +} + +enum class SymbolKind { Mtx, Idx, Vec }; + +struct Tree { + const int (*nodes)[2] = nullptr; + int count = 0; +}; + +Tree select_tree(std::uint32_t quant_idx, SymbolKind kind, int n_channels) { + Tree tree; + switch (kind) { + case SymbolKind::Idx: + if (n_channels == 5) { + tree.nodes = joc_huff_code_5ch_pos_index_sparse; + tree.count = static_cast(sizeof(joc_huff_code_5ch_pos_index_sparse) / + sizeof(joc_huff_code_5ch_pos_index_sparse[0])); + } else { + tree.nodes = joc_huff_code_7ch_pos_index_sparse; + tree.count = static_cast(sizeof(joc_huff_code_7ch_pos_index_sparse) / + sizeof(joc_huff_code_7ch_pos_index_sparse[0])); + } + break; + case SymbolKind::Vec: + if (quant_idx == 0u) { + tree.nodes = joc_huff_code_coarse_coeff_sparse; + tree.count = static_cast(sizeof(joc_huff_code_coarse_coeff_sparse) / + sizeof(joc_huff_code_coarse_coeff_sparse[0])); + } else { + tree.nodes = joc_huff_code_fine_coeff_sparse; + tree.count = static_cast(sizeof(joc_huff_code_fine_coeff_sparse) / + sizeof(joc_huff_code_fine_coeff_sparse[0])); + } + break; + case SymbolKind::Mtx: + default: + if (quant_idx == 0u) { + tree.nodes = joc_huff_code_coarse_generic; + tree.count = static_cast(sizeof(joc_huff_code_coarse_generic) / + sizeof(joc_huff_code_coarse_generic[0])); + } else { + tree.nodes = joc_huff_code_fine_generic; + tree.count = static_cast(sizeof(joc_huff_code_fine_generic) / + sizeof(joc_huff_code_fine_generic[0])); + } + break; + } + return tree; +} + +// infinite loop (plan 40.4 BL-6). +bool huff_decode(const Tree& tree, bits::BitReader& reader, std::int16_t* out_value) { + int node = 0; + int steps = 0; + while (node >= 0) { + if (node >= tree.count || steps > tree.count) { + reader.fail(JOC_ERR_JOC_SYNTAX, "Huffman tree walk left the valid node range"); + return false; + } + ++steps; + const std::uint32_t bit = reader.read(1); + if (reader.failed()) { + return false; + } + node = tree.nodes[node][bit]; + } + *out_value = static_cast(-node - 1); + return true; +} + +Status syntax_fail(const std::string& message) { + return Status::fail(JOC_ERR_JOC_SYNTAX, stage::kJoc, message); +} + +Status truncated_fail(const bits::BitReader& reader) { + if (reader.error() == JOC_ERR_JOC_SYNTAX) { + return syntax_fail(reader.error_message()); + } + return Status::fail(JOC_ERR_BITSTREAM_TRUNCATED, stage::kJoc, + std::string("JOC bitstream truncated: ") + reader.error_message()); +} + +void reconstruct_dense(const ObjectSymbols& symbols, std::uint32_t dp, int n_channels, std::int64_t nquant, + std::int64_t offset, + std::int64_t q[JOC_MAX_DPOINTS][JOC_MAX_CORE_CHANNELS][JOC_MAX_PARAMETER_BANDS]) { + for (int ch = 0; ch < n_channels; ++ch) { + q[dp][ch][0] = + floored_mod(offset + static_cast(symbols.mtx[dp][ch][0]), nquant); + for (int pb = 1; pb < symbols.n_bands; ++pb) { + q[dp][ch][pb] = floored_mod( + q[dp][ch][pb - 1] + static_cast(symbols.mtx[dp][ch][pb]), nquant); + } + } +} + +// across parameter bands and is deliberately NOT reset when the active channel +Status reconstruct_sparse( + const ObjectSymbols& symbols, std::uint32_t dp, int n_channels, std::int64_t nquant, std::int64_t offset, + std::int64_t q[JOC_MAX_DPOINTS][JOC_MAX_CORE_CHANNELS][JOC_MAX_PARAMETER_BANDS]) { + if (n_channels != 5 && n_channels != 7) { + return Status::fail(JOC_ERR_JOC_UNSUPPORTED_VARIANT, stage::kJoc, + "sparse JOC requires 5 or 7 core channels, got " + + std::to_string(n_channels)); + } + const int initial_channel = symbols.idx[dp][0]; + if (initial_channel < 0 || initial_channel >= n_channels) { + return syntax_fail("sparse JOC initial channel " + std::to_string(initial_channel) + + " out of range for " + std::to_string(n_channels) + " channels"); + } + // Non-active entries take nquant/2, which dequantizes to exactly zero. + for (int ch = 0; ch < n_channels; ++ch) { + for (int pb = 0; pb < symbols.n_bands; ++pb) { + q[dp][ch][pb] = nquant / 2; + } + } + int active = initial_channel; + std::int64_t coefficient = offset; + for (int pb = 0; pb < symbols.n_bands; ++pb) { + if (pb != 0) { + active = static_cast( + floored_mod(static_cast(active) + symbols.idx[dp][pb], n_channels)); + } + coefficient = floored_mod(coefficient + static_cast(symbols.vec[dp][pb]), nquant); + q[dp][active][pb] = coefficient; + } + return Status::success(); +} + +} // namespace + +std::int16_t num_channels_for_config(std::uint32_t dmx_config_idx) { + for (const NumChannelsEntry& entry : kNumChannels) { + if (entry.config == dmx_config_idx) { + return entry.channels; + } + } + return -1; +} + +std::int16_t num_bands_for_index(std::uint32_t num_bands_idx) { + for (const NumBandsEntry& entry : kNumBands) { + if (entry.index == num_bands_idx) { + return entry.bands; + } + } + return -1; +} + +Status parse_id14(const std::uint8_t* payload, std::size_t payload_size, joc_frame_params* out, + FrameSymbols* symbols) { + if (payload == nullptr || out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kJoc, "null payload or output"); + } + std::memset(out, 0, sizeof(*out)); + out->struct_size = sizeof(joc_frame_params); + out->struct_version = JOC_FRAME_PARAMS_VERSION; + // capture is purely additive and never changes the parse result. + FrameSymbols local_symbols{}; + FrameSymbols& capture = (symbols != nullptr) ? *symbols : local_symbols; + std::memset(&capture, 0, sizeof(capture)); + + bits::BitReader reader(payload, payload_size); + + out->dmx_config_idx = static_cast(reader.read(3)); + out->num_objects_bits = static_cast(reader.read(6)); + out->ext_config_idx = static_cast(reader.read(3)); + + const std::uint32_t n_objects = static_cast(out->num_objects_bits) + 1u; + const std::int16_t n_channels = num_channels_for_config(out->dmx_config_idx); + if (n_channels < 0) { + return syntax_fail("unknown JOC downmix configuration " + + std::to_string(out->dmx_config_idx)); + } + out->n_channels = static_cast(n_channels); + if (n_objects > JOC_MAX_OBJECTS) { + // The reference implementation has no check here and fails later inside + // NumPy; the port reports it explicitly (plan 28.2). + return Status::fail(JOC_ERR_JOC_UNSUPPORTED_VARIANT, stage::kJoc, + "JOC frame declares " + std::to_string(n_objects) + + " objects, the ABI supports at most " + + std::to_string(static_cast(JOC_MAX_OBJECTS))); + } + out->n_objects = static_cast(n_objects); + + out->clipgain_x_bits = static_cast(reader.read(3)); + out->clipgain_y_bits = static_cast(reader.read(5)); + out->seq_count = reader.read(10); + // clipgain = 1 + (y/32) * 2^(x-4). The reference multiplies by an exact + // exactly for the whole legal range. + out->clipgain = 1.0 + static_cast(out->clipgain_y_bits) / 32.0 * + std::ldexp(1.0, static_cast(out->clipgain_x_bits) - 4); + + for (std::uint32_t obj = 0; obj < n_objects; ++obj) { + joc_object_params& info = out->objects[obj]; + info.present = static_cast(reader.read(1)); + if (info.present == 0u) { + continue; + } + info.num_bands_idx = static_cast(reader.read(3)); + const std::int16_t bands = num_bands_for_index(info.num_bands_idx); + if (bands < 0) { + return syntax_fail("unknown JOC num_bands index " + + std::to_string(info.num_bands_idx)); + } + info.n_bands = static_cast(bands); + info.sparse = static_cast(reader.read(1)); + info.quant_idx = static_cast(reader.read(1)); + info.slope_idx = static_cast(reader.read(1)); + info.num_dpoints_bits = static_cast(reader.read(1)); + info.n_dpoints = static_cast(info.num_dpoints_bits + 1u); + if (info.slope_idx == 1u) { + for (std::uint32_t dp = 0; dp < info.n_dpoints; ++dp) { + info.offset_ts[dp] = static_cast(reader.read(5) + 1u); + } + } + } + if (reader.failed()) { + return truncated_fail(reader); + } + + for (std::uint32_t obj = 0; obj < n_objects; ++obj) { + const joc_object_params& info = out->objects[obj]; + if (info.present == 0u) { + continue; + } + ObjectSymbols* symbol = &capture.objects[obj]; + symbol->present = 1; + symbol->sparse = info.sparse; + symbol->n_bands = info.n_bands; + symbol->n_dpoints = info.n_dpoints; + symbol->n_channels = out->n_channels; + for (std::uint32_t dp = 0; dp < info.n_dpoints; ++dp) { + if (info.sparse == 1u) { + const Tree idx_tree = select_tree(info.quant_idx, SymbolKind::Idx, n_channels); + const std::uint32_t first = reader.read(3); + if (reader.failed()) { + return truncated_fail(reader); + } + symbol->idx[dp][0] = static_cast(first); + for (int pb = 1; pb < info.n_bands; ++pb) { + std::int16_t value = 0; + if (!huff_decode(idx_tree, reader, &value)) { + return truncated_fail(reader); + } + symbol->idx[dp][pb] = static_cast(value); + } + const Tree vec_tree = select_tree(info.quant_idx, SymbolKind::Vec, n_channels); + for (int pb = 0; pb < info.n_bands; ++pb) { + std::int16_t value = 0; + if (!huff_decode(vec_tree, reader, &value)) { + return truncated_fail(reader); + } + symbol->vec[dp][pb] = value; + } + } else { + const Tree mtx_tree = select_tree(info.quant_idx, SymbolKind::Mtx, n_channels); + for (int ch = 0; ch < n_channels; ++ch) { + for (int pb = 0; pb < info.n_bands; ++pb) { + std::int16_t value = 0; + if (!huff_decode(mtx_tree, reader, &value)) { + return truncated_fail(reader); + } + symbol->mtx[dp][ch][pb] = value; + } + } + } + } + } + + out->data_end_bits = static_cast(reader.position()); + out->trailing_bits = static_cast(payload_size * 8u - reader.position()); + const std::size_t tail_offset = reader.position() / 8u; + if (tail_offset < payload_size) { + const std::size_t tail_bytes = std::min(8u, payload_size - tail_offset); + std::memcpy(out->tail_bytes, payload + tail_offset, tail_bytes); + } + + for (std::uint32_t obj = 0; obj < n_objects; ++obj) { + const joc_object_params& info = out->objects[obj]; + if (info.present == 0u) { + continue; + } + std::uint32_t mask_bit = 1u << obj; + out->present_mask |= mask_bit; + + const std::int64_t nquant = (info.quant_idx == 0u) ? 96 : 192; + std::int64_t q[JOC_MAX_DPOINTS][JOC_MAX_CORE_CHANNELS][JOC_MAX_PARAMETER_BANDS] = {}; + ObjectSymbols* symbol = &capture.objects[obj]; + + for (std::uint32_t dp = 0; dp < info.n_dpoints; ++dp) { + if (info.sparse == 1u) { + const std::int64_t offset = (info.quant_idx == 0u) ? 50 : 100; + const Status status = + reconstruct_sparse(*symbol, dp, n_channels, nquant, offset, q); + if (!status.ok()) { + return status; + } + } else { + const std::int64_t offset = (info.quant_idx == 0u) ? 48 : 96; + reconstruct_dense(*symbol, dp, n_channels, nquant, offset, q); + } + } + + // Operand order and types are kept identical to the reference so the + // result is bit-exact, not merely close. + const double nquant_half = static_cast(nquant) / 2.0; + const double denominator = 4096.0 * static_cast(1 + static_cast(info.quant_idx)); + for (std::uint32_t dp = 0; dp < info.n_dpoints; ++dp) { + for (int ch = 0; ch < n_channels; ++ch) { + for (int pb = 0; pb < info.n_bands; ++pb) { + const double value = static_cast(q[dp][ch][pb]) - nquant_half; + out->objects[obj].dq[dp][ch][pb] = value * 820.0 / denominator; + } + } + } + for (std::uint32_t dp = 0; dp < info.n_dpoints; ++dp) { + for (int ch = 0; ch < n_channels; ++ch) { + for (int pb = 0; pb < info.n_bands; ++pb) { + symbol->q[dp][ch][pb] = q[dp][ch][pb]; + } + } + } + } + + capture.n_objects = out->n_objects; + capture.n_channels = out->n_channels; + return Status::success(); +} + +Status parse_eac3_frame(const std::uint8_t* frame, std::size_t frame_size, joc_frame_params* out, + emdf::Container* container, FrameSymbols* symbols) { + if (frame == nullptr || out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kJoc, "null frame or output"); + } + emdf::Container local; + const Status status = emdf::find_joc_emdf(frame, frame_size, &local); + if (!status.ok()) { + return status; + } + if (container != nullptr) { + *container = local; + } + const emdf::Payload* payload = local.find(emdf::kIdJoc); + if (payload == nullptr) { + return Status::fail(JOC_ERR_EMDF_TRANSPORT, stage::kEmdf, + "EMDF container has no ID14 (JOC) payload"); + } + std::vector bytes; + const Status extract = emdf::extract_payload_bytes(frame, frame_size, *payload, &bytes); + if (!extract.ok()) { + return extract; + } + return parse_id14(bytes.data(), bytes.size(), out, symbols); +} + +Status check_id14_padding(const std::uint8_t* payload, std::size_t payload_size, + std::uint32_t* out_trailing_bits) { + joc_frame_params params; + FrameSymbols symbols; + const Status status = parse_id14(payload, payload_size, ¶ms, &symbols); + if (!status.ok()) { + return status; + } + if (out_trailing_bits != nullptr) { + *out_trailing_bits = params.trailing_bits; + } + if (params.trailing_bits > 7u) { + return Status::fail(JOC_ERR_BITSTREAM_PADDING, stage::kJoc, + "more than 7 bits left after joc_data (" + + std::to_string(params.trailing_bits) + ")"); + } + for (std::size_t bit = params.data_end_bits; bit < payload_size * 8u; ++bit) { + if (((payload[bit >> 3] >> (7u - (bit & 7u))) & 1u) != 0u) { + return Status::fail(JOC_ERR_BITSTREAM_PADDING, stage::kJoc, + "non-zero trailing padding bit at " + std::to_string(bit)); + } + } + return Status::success(); +} + +} // namespace joc::joc diff --git a/src/joc_bitstream/joc_parser.h b/src/joc_bitstream/joc_parser.h new file mode 100644 index 0000000..606f5d0 --- /dev/null +++ b/src/joc_bitstream/joc_parser.h @@ -0,0 +1,46 @@ +// Port of src/joc_decode.py. + +#pragma once + +#include +#include +#include + +#include "joc_core.h" +#include "emdf/emdf_parser.h" +#include "foundation/status.h" + +namespace joc::joc { + +struct ObjectSymbols { + std::uint8_t present = 0; + std::uint8_t sparse = 0; + std::uint8_t n_bands = 0; + std::uint8_t n_dpoints = 0; + std::uint8_t n_channels = 0; + std::int64_t q[JOC_MAX_DPOINTS][JOC_MAX_CORE_CHANNELS][JOC_MAX_PARAMETER_BANDS] = {}; + std::int16_t mtx[JOC_MAX_DPOINTS][JOC_MAX_CORE_CHANNELS][JOC_MAX_PARAMETER_BANDS] = {}; + std::uint8_t idx[JOC_MAX_DPOINTS][JOC_MAX_PARAMETER_BANDS] = {}; + std::int16_t vec[JOC_MAX_DPOINTS][JOC_MAX_PARAMETER_BANDS] = {}; +}; + +struct FrameSymbols { + std::uint8_t n_objects = 0; + std::uint8_t n_channels = 0; + ObjectSymbols objects[JOC_MAX_OBJECTS]; +}; + +Status parse_id14(const std::uint8_t* payload, std::size_t payload_size, joc_frame_params* out, + FrameSymbols* symbols); + +Status parse_eac3_frame(const std::uint8_t* frame, std::size_t frame_size, joc_frame_params* out, + emdf::Container* container, FrameSymbols* symbols); + +Status check_id14_padding(const std::uint8_t* payload, std::size_t payload_size, + std::uint32_t* out_trailing_bits); + +std::int16_t num_channels_for_config(std::uint32_t dmx_config_idx); + +std::int16_t num_bands_for_index(std::uint32_t num_bands_idx); + +} // namespace joc::joc diff --git a/src/joc_core/eac3joc_core.cpp b/src/joc_core/eac3joc_core.cpp new file mode 100644 index 0000000..9ea832d --- /dev/null +++ b/src/joc_core/eac3joc_core.cpp @@ -0,0 +1,735 @@ +#define EJOC_BUILD_DLL +#include "eac3joc_core.h" +#include "qmf_tables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ejoc { + +struct Complex { + double re; + double im; +}; + +inline Complex mul(const Complex a, const Complex b) noexcept { + return {a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re}; +} + +inline double clamp_unit(double value) noexcept { + return value < -1.0 ? -1.0 : (value > 1.0 ? 1.0 : value); +} + +constexpr double kPi = 3.141592653589793238462643383279502884; +constexpr int kLfeDelay = 1217; +constexpr int kMaxBands = EJOC_MAX_PARAMETER_BANDS; + +const uint8_t* parameter_band_map(const int bands) noexcept { + using namespace tables; + switch (bands) { + case 1: return kPbMap1; + case 3: return kPbMap3; + case 5: return kPbMap5; + case 7: return kPbMap7; + case 9: return kPbMap9; + case 12: return kPbMap12; + case 15: return kPbMap15; + case 23: return kPbMap23; + default: return nullptr; + } +} + +class Renderer final { +public: + Renderer() noexcept { + initialize_tables(); + reset(); + } + + ~Renderer() noexcept { + stop_workers(); + } + + int reset() noexcept { + std::memset(analysis_fifo_, 0, sizeof(analysis_fifo_)); + std::memset(analysis_delay_, 0, sizeof(analysis_delay_)); + std::memset(surround_delay_, 0, sizeof(surround_delay_)); + std::memset(surround_history_, 0, sizeof(surround_history_)); + std::memset(lfe_delay_, 0, sizeof(lfe_delay_)); + std::memset(matrix_previous_, 0, sizeof(matrix_previous_)); + std::memset(synthesis_state_, 0, sizeof(synthesis_state_)); + std::memset(x_, 0, sizeof(x_)); + std::memset(z_, 0, sizeof(z_)); + analysis_phase_ = 0.0625f; + error_[0] = '\0'; + return 0; + } + + int set_threads(uint32_t total_threads) noexcept { + if (total_threads < 1) { + total_threads = 1; + } + if (total_threads > EJOC_MAX_OBJECTS) { + total_threads = EJOC_MAX_OBJECTS; + } + stop_workers(); + job_count_ = 0; + next_job_.store(0, std::memory_order_relaxed); + if (total_threads == 1) { + return 0; + } + try { + stop_.store(false, std::memory_order_relaxed); + pool_ready_.store(false, std::memory_order_relaxed); + work_barrier_ = std::make_unique>(static_cast(total_threads)); + workers_.reserve(total_threads - 1); + for (uint32_t index = 1; index < total_threads; ++index) { + workers_.emplace_back([this]() noexcept { worker_loop(); }); + } + pool_ready_.store(true, std::memory_order_release); + // Startup rendezvous: ensure every worker has entered the two-phase + // barrier loop before set_threads returns, so an immediate destroy + // cannot race a worker that exits before reaching the barrier. + work_barrier_->arrive_and_wait(); + work_barrier_->arrive_and_wait(); + } catch (...) { + stop_.store(true, std::memory_order_release); + pool_ready_.store(true, std::memory_order_release); + for (std::thread& worker : workers_) { + if (worker.joinable()) { + worker.join(); + } + } + workers_.clear(); + work_barrier_.reset(); + stop_.store(false, std::memory_order_relaxed); + return fail("failed to create native worker threads"); + } + return 0; + } + + uint32_t thread_count() const noexcept { + return static_cast(workers_.size() + 1); + } + + const char* error() const noexcept { + return error_[0] ? error_ : ""; + } + + int process( + const float* bed5, + const float* lfe, + const uint32_t object_mask, + const uint8_t* n_bands, + const uint8_t* n_dpoints, + const uint8_t* slope_idx, + const uint8_t* offset_ts, + const double* dq, + const double clipgain, + const float phase_new, + const float output_scale, + float* output16) noexcept { + + error_[0] = '\0'; + if (!bed5 || !n_bands || !n_dpoints || !slope_idx || !offset_ts || !dq || !output16) { + return fail("null pointer passed to ejoc_renderer_process"); + } + if (object_mask & ~((1u << EJOC_MAX_OBJECTS) - 1u)) { + return fail("object_mask contains an object index above 14"); + } + if (!std::isfinite(clipgain) || !std::isfinite(phase_new) || !std::isfinite(output_scale)) { + return fail("clipgain, phase_new, and output_scale must be finite"); + } + for (int object = 0; object < EJOC_MAX_OBJECTS; ++object) { + if ((object_mask & (1u << object)) == 0) { + continue; + } + if (!parameter_band_map(n_bands[object])) { + return fail("unsupported parameter-band count"); + } + if (n_dpoints[object] < 1 || n_dpoints[object] > 2) { + return fail("n_dpoints must be 1 or 2"); + } + if (slope_idx[object] > 1) { + return fail("slope_idx must be 0 or 1"); + } + } + + std::memset(output16, 0, sizeof(float) * EJOC_OUTPUT_CHANNELS * EJOC_FRAME_SAMPLES); + analysis(bed5, phase_new); + render_lfe(lfe, output_scale, output16); + process_objects(object_mask, n_bands, n_dpoints, slope_idx, offset_ts, + dq, clipgain, output_scale, output16); + return 0; + } + +private: + void initialize_tables() noexcept { + for (int i = 0; i < 64; ++i) { + int value = i; + int reversed = 0; + for (int bit = 0; bit < 6; ++bit) { + reversed = (reversed << 1) | (value & 1); + value >>= 1; + } + bit_reverse_[i] = static_cast(reversed); + const double theta = kPi * static_cast(i) / 128.0; + rotation_sin_[i] = 0.5 * std::sin(theta); + rotation_cos_[i] = 0.5 * std::cos(theta); + } + for (int i = 0; i < 32; ++i) { + const double angle = -2.0 * kPi * static_cast(i) / 64.0; + fft_twiddle_[i] = {std::cos(angle), std::sin(angle)}; + } + } + + int fail(const char* message) noexcept { + std::snprintf(error_, sizeof(error_), "%s", message); + return -1; + } + + void fft64(Complex* values) const noexcept { + for (int i = 0; i < 64; ++i) { + const int j = bit_reverse_[i]; + if (j > i) { + const Complex temp = values[i]; + values[i] = values[j]; + values[j] = temp; + } + } + for (int length = 2; length <= 64; length <<= 1) { + const int half = length >> 1; + const int twiddle_step = 64 / length; + for (int base = 0; base < 64; base += length) { + for (int j = 0; j < half; ++j) { + const Complex even = values[base + j]; + const Complex odd = mul(values[base + j + half], fft_twiddle_[j * twiddle_step]); + values[base + j] = {even.re + odd.re, even.im + odd.im}; + values[base + j + half] = {even.re - odd.re, even.im - odd.im}; + } + } + } + } + + void analysis_slot(const int channel, const float* ring, const int timeslot) noexcept { + double v36[64]; + double v40[64]; + Complex frequency[64]; + + for (int sample = 0; sample < 64; ++sample) { + v36[sample] = + analysis_fifo_[channel][0][sample] * tables::kAnalysisWindow[8 * 64 + sample] + + analysis_fifo_[channel][2][sample] * tables::kAnalysisWindow[6 * 64 + sample] + + analysis_fifo_[channel][4][sample] * tables::kAnalysisWindow[4 * 64 + sample] + + analysis_fifo_[channel][6][sample] * tables::kAnalysisWindow[2 * 64 + sample] + + analysis_fifo_[channel][8][sample] * tables::kAnalysisWindow[0 * 64 + sample]; + v40[sample] = + analysis_fifo_[channel][1][sample] * tables::kAnalysisWindow[7 * 64 + sample] + + analysis_fifo_[channel][3][sample] * tables::kAnalysisWindow[5 * 64 + sample] + + analysis_fifo_[channel][5][sample] * tables::kAnalysisWindow[3 * 64 + sample] + + analysis_fifo_[channel][7][sample] * tables::kAnalysisWindow[1 * 64 + sample] + + static_cast(ring[sample]) * tables::kAnalysisWindow[9 * 64 + sample]; + } + + for (int k = 0; k < 64; ++k) { + const int source = 63 - k; + const double re = v40[source]; + const double im = v36[source]; + const double a = rotation_sin_[k]; + const double b = rotation_cos_[k]; + frequency[k] = {im * a - re * b, im * b + re * a}; + } + fft64(frequency); + constexpr double scale = 1.0 / 64.0; + for (int k = 0; k < 32; ++k) { + x_[channel][2 * k][timeslot] = {frequency[k].re * scale, -frequency[k].im * scale}; + x_[channel][2 * k + 1][timeslot] = { + frequency[63 - k].re * scale, + frequency[63 - k].im * scale}; + } + + for (int history = 8; history > 0; --history) { + std::memcpy(analysis_fifo_[channel][history], analysis_fifo_[channel][history - 1], + sizeof(analysis_fifo_[channel][history])); + } + for (int sample = 0; sample < 64; ++sample) { + analysis_fifo_[channel][0][sample] = static_cast(ring[sample]); + } + } + + void surround_post() noexcept { + static constexpr double kDcA[21] = { + -.0006242550443857908, -.0019234686624258757, -.0042654648423194885, + -.008168308064341545, -.014327201060950756, -.023759860545396805, + -.03757232800126076, -.05577569454908371, -.07568276673555374, + -.09172472357749939, -.5979374051094055, -.09172472357749939, + -.07568276673555374, -.05577569454908371, -.03757232800126076, + -.023759860545396805, -.014327201060950756, -.008168308064341545, + -.0042654648423194885, -.0019234686624258757, -.0006242550443857908, + }; + static constexpr double kDcB[21] = { + .0013996040215715766, .003839150769636035, .007512642536312342, + .012419373728334904, .018367428332567215, .0249701626598835, + .03167900815606117, .03785000368952751, .04283412545919418, + .04607561603188515, .047200120985507965, .04607561603188515, + .04283412545919418, .03785000368952751, .03167900815606117, + .0249701626598835, .018367428332567215, .012419373728334904, + .007512642536312342, .003839150769636035, .0013996040215715766, + }; + + for (int surround = 0; surround < 2; ++surround) { + const int channel = surround + 3; + for (int group = 0; group < 24; group += 4) { + Complex current[4][64]; + Complex dc_buffer[24]; + for (int slot = 0; slot < 4; ++slot) { + for (int band = 0; band < 64; ++band) { + current[slot][band] = x_[channel][band][group + slot]; + const Complex delayed = surround_delay_[surround][slot][band]; + x_[channel][band][group + slot] = {delayed.im, -delayed.re}; + } + } + + for (int i = 0; i < 20; ++i) { + dc_buffer[i] = surround_history_[surround][i]; + } + for (int i = 0; i < 4; ++i) { + dc_buffer[20 + i] = current[i][0]; + } + for (int slot = 0; slot < 4; ++slot) { + Complex sum{0.0, 0.0}; + for (int tap = 0; tap < 21; ++tap) { + const Complex sample = dc_buffer[slot + tap]; + const double cr = kDcB[tap]; + const double ci = kDcA[tap]; + sum.re += sample.re * cr - sample.im * ci; + sum.im += sample.re * ci + sample.im * cr; + } + x_[channel][0][group + slot] = {2.0 * sum.re, 2.0 * sum.im}; + } + for (int i = 0; i < 20; ++i) { + surround_history_[surround][i] = dc_buffer[i + 4]; + } + + std::memmove(&surround_delay_[surround][0][0], + &surround_delay_[surround][4][0], + sizeof(Complex) * 6 * 64); + for (int slot = 0; slot < 4; ++slot) { + std::memcpy(surround_delay_[surround][6 + slot], current[slot], + sizeof(Complex) * 64); + } + } + } + } + + void analysis_channel(const int channel) noexcept { + const float* bed5 = job_bed5_; + const float phase_old = job_phase_old_; + const float phase_new = job_phase_new_; + const bool ramp_phase = phase_old != phase_new; + const float phase_step = static_cast((phase_new - phase_old) / 256.0f); + float scaled[64]; + float delayed[64]; + + for (int timeslot = 0; timeslot < 24; ++timeslot) { + for (int sample = 0; sample < 64; ++sample) { + const int frame_sample = timeslot * 64 + sample; + float gain = phase_new; + if (ramp_phase && frame_sample < 256) { + const float product = static_cast(static_cast(frame_sample) * phase_step); + gain = static_cast(phase_old + product); + } + scaled[sample] = static_cast(bed5[channel * 1536 + frame_sample] * gain); + } + const float* analysis_input = scaled; + if (channel < 3) { + std::memcpy(delayed, analysis_delay_[channel][0], sizeof(delayed)); + std::memmove(&analysis_delay_[channel][0][0], + &analysis_delay_[channel][1][0], + sizeof(float) * 9 * 64); + std::memcpy(analysis_delay_[channel][9], scaled, sizeof(scaled)); + analysis_input = delayed; + } + analysis_slot(channel, analysis_input, timeslot); + } + } + + void analysis(const float* bed5, const float phase_new) noexcept { + job_bed5_ = bed5; + job_phase_old_ = analysis_phase_; + job_phase_new_ = phase_new; + job_kind_ = JobKind::Analysis; + job_count_ = 5; + for (int channel = 0; channel < 5; ++channel) { + job_objects_[channel] = channel; + } + dispatch_jobs(); + analysis_phase_ = phase_new; + surround_post(); + } + + static std::size_t dq_index(const int object, const int point, const int channel, const int band) noexcept { + return static_cast((((object * 2 + point) * 5 + channel) * kMaxBands) + band); + } + + void matrix_object( + const int object, + const uint8_t* n_bands, + const uint8_t* n_dpoints, + const uint8_t* slope_idx, + const uint8_t* offset_ts, + const double* dq) noexcept { + + std::memset(z_[object], 0, sizeof(z_[object])); + const int bands = n_bands[object]; + const int points = n_dpoints[object]; + const int slope = slope_idx[object]; + const uint8_t* pb_map = parameter_band_map(bands); + + for (int channel = 0; channel < 5; ++channel) { + for (int subband = 0; subband < 64; ++subband) { + const int parameter_band = pb_map[subband]; + const double previous = matrix_previous_[object][channel][subband]; + const double target0 = dq[dq_index(object, 0, channel, parameter_band)]; + const double target1 = points == 2 + ? dq[dq_index(object, 1, channel, parameter_band)] + : target0; + double last = previous; + + for (int timeslot = 0; timeslot < 24; ++timeslot) { + double coefficient; + if (slope == 0) { + if (points == 1) { + const double alpha = static_cast(timeslot + 1) / 24.0; + coefficient = previous * (1.0 - alpha) + target0 * alpha; + } else if (timeslot < 12) { + const double alpha = static_cast(timeslot + 1) / 12.0; + coefficient = previous * (1.0 - alpha) + target0 * alpha; + } else { + const double alpha = static_cast(timeslot - 11) / 12.0; + coefficient = target0 * (1.0 - alpha) + target1 * alpha; + } + } else if (points == 1) { + coefficient = timeslot < offset_ts[object * 2] ? previous : target0; + } else { + coefficient = timeslot < offset_ts[object * 2] ? previous : target0; + if (timeslot >= offset_ts[object * 2 + 1]) { + coefficient = target1; + } + } + z_[object][subband][timeslot].re += x_[channel][subband][timeslot].re * coefficient; + z_[object][subband][timeslot].im += x_[channel][subband][timeslot].im * coefficient; + last = coefficient; + } + matrix_previous_[object][channel][subband] = last; + } + } + } + + void qmf5_step(double* state, const double* rotated, double* output) noexcept { + for (int block = 0; block < 16; ++block) { + for (int lane = 0; lane < 4; ++lane) { + const int sample = block * 4 + lane; + const int state_base = block * 36 + lane; + const double even = rotated[block * 8 + lane * 2]; + const double odd = rotated[block * 8 + lane * 2 + 1]; + output[sample] = 2.0 * ( + tables::kQmf5Window[sample] * even + state[state_base]); + + state[state_base] = tables::kQmf5Window[1 * 64 + sample] * odd + state[state_base + 4]; + for (int slot = 0; slot < 7; ++slot) { + const double alternating = (slot & 1) == 0 ? even : odd; + state[state_base + (slot + 1) * 4] = + tables::kQmf5Window[(slot + 2) * 64 + sample] * alternating + + state[state_base + (slot + 2) * 4]; + } + state[state_base + 8 * 4] = tables::kQmf5Window[9 * 64 + sample] * odd; + } + } + } + + void synthesis_object( + const int object, + const double clipgain, + const float output_scale, + float* output16) noexcept { + + Complex frequency[64]; + double rotated[128]; + double pcm64[64]; + double* state = synthesis_state_[object]; + float* destination = output16 + (object + 1) * 1536; + for (int timeslot = 0; timeslot < 24; ++timeslot) { + for (int k = 0; k < 32; ++k) { + const Complex even = z_[object][2 * k][timeslot]; + const Complex odd = z_[object][2 * k + 1][timeslot]; + frequency[k] = {even.re, -even.im}; + frequency[63 - k] = {odd.re, odd.im}; + } + fft64(frequency); + for (int k = 0; k < 64; ++k) { + const double re = frequency[k].re; + const double im = frequency[k].im; + const double sin_component = rotation_sin_[k]; + const double cos_component = rotation_cos_[k]; + rotated[2 * k] = 2.0 * (re * cos_component + im * sin_component); + rotated[2 * k + 1] = 2.0 * (im * cos_component - re * sin_component); + } + qmf5_step(state, rotated, pcm64); + for (int sample = 0; sample < 64; ++sample) { + const double clipped = clamp_unit(16.0 * pcm64[sample]); + const float value = static_cast(clipped * clipgain); + destination[timeslot * 64 + sample] = static_cast(value * output_scale); + } + } + } + + void process_one_object(const int object) noexcept { + matrix_object(object, job_n_bands_, job_n_dpoints_, job_slope_idx_, + job_offset_ts_, job_dq_); + synthesis_object(object, job_clipgain_, job_output_scale_, job_output16_); + } + + void execute_job_loop() noexcept { + while (true) { + const int index = next_job_.fetch_add(1, std::memory_order_relaxed); + if (index >= job_count_) { + break; + } + const int item = job_objects_[index]; + if (job_kind_ == JobKind::Analysis) { + analysis_channel(item); + } else { + process_one_object(item); + } + } + } + + void dispatch_jobs() noexcept { + if (workers_.empty() || job_count_ == 1) { + next_job_.store(0, std::memory_order_relaxed); + execute_job_loop(); + return; + } + next_job_.store(0, std::memory_order_relaxed); + work_barrier_->arrive_and_wait(); + execute_job_loop(); + work_barrier_->arrive_and_wait(); + } + + void worker_loop() noexcept { + while (!pool_ready_.load(std::memory_order_acquire)) { + std::this_thread::yield(); + } + if (stop_.load(std::memory_order_acquire)) { + return; + } + while (true) { + work_barrier_->arrive_and_wait(); + if (stop_.load(std::memory_order_acquire)) { + return; + } + execute_job_loop(); + work_barrier_->arrive_and_wait(); + } + } + + void stop_workers() noexcept { + if (workers_.empty()) { + work_barrier_.reset(); + stop_.store(false, std::memory_order_relaxed); + pool_ready_.store(false, std::memory_order_relaxed); + return; + } + stop_.store(true, std::memory_order_release); + work_barrier_->arrive_and_wait(); + for (std::thread& worker : workers_) { + if (worker.joinable()) { + worker.join(); + } + } + workers_.clear(); + work_barrier_.reset(); + stop_.store(false, std::memory_order_relaxed); + pool_ready_.store(false, std::memory_order_relaxed); + } + + void process_objects( + const uint32_t object_mask, + const uint8_t* n_bands, + const uint8_t* n_dpoints, + const uint8_t* slope_idx, + const uint8_t* offset_ts, + const double* dq, + const double clipgain, + const float output_scale, + float* output16) noexcept { + + int count = 0; + for (int object = 0; object < EJOC_MAX_OBJECTS; ++object) { + if (object_mask & (1u << object)) { + job_objects_[count++] = object; + } + } + if (count == 0) { + return; + } + job_kind_ = JobKind::Objects; + job_count_ = count; + job_n_bands_ = n_bands; + job_n_dpoints_ = n_dpoints; + job_slope_idx_ = slope_idx; + job_offset_ts_ = offset_ts; + job_dq_ = dq; + job_clipgain_ = clipgain; + job_output_scale_ = output_scale; + job_output16_ = output16; + + dispatch_jobs(); + } + + void render_lfe(const float* lfe, const float output_scale, float* output16) noexcept { + if (!lfe) { + return; + } + for (int sample = 0; sample < kLfeDelay; ++sample) { + const float value = static_cast(clamp_unit(lfe_delay_[sample])); + output16[sample] = static_cast(value * output_scale); + } + for (int sample = kLfeDelay; sample < 1536; ++sample) { + const float value = static_cast(clamp_unit(static_cast(lfe[sample - kLfeDelay]))); + output16[sample] = static_cast(value * output_scale); + } + for (int sample = 0; sample < kLfeDelay; ++sample) { + lfe_delay_[sample] = static_cast(lfe[sample + (1536 - kLfeDelay)]); + } + } + + enum class JobKind : uint8_t { Analysis, Objects }; + + std::vector workers_; + std::unique_ptr> work_barrier_; + std::atomic stop_{false}; + std::atomic pool_ready_{false}; + std::atomic next_job_{0}; + int job_objects_[EJOC_MAX_OBJECTS]{}; + int job_count_ = 0; + JobKind job_kind_ = JobKind::Objects; + const float* job_bed5_ = nullptr; + float job_phase_old_ = 0.0625f; + float job_phase_new_ = 0.0625f; + const uint8_t* job_n_bands_ = nullptr; + const uint8_t* job_n_dpoints_ = nullptr; + const uint8_t* job_slope_idx_ = nullptr; + const uint8_t* job_offset_ts_ = nullptr; + const double* job_dq_ = nullptr; + double job_clipgain_ = 1.0; + float job_output_scale_ = 1.0f; + float* job_output16_ = nullptr; + + alignas(64) double analysis_fifo_[5][9][64]; + alignas(64) float analysis_delay_[3][10][64]; + float analysis_phase_; + alignas(64) Complex surround_delay_[2][10][64]; + alignas(64) Complex surround_history_[2][20]; + alignas(64) double lfe_delay_[kLfeDelay]; + alignas(64) double matrix_previous_[15][5][64]; + alignas(64) double synthesis_state_[15][640]; + alignas(64) Complex x_[5][64][24]; + alignas(64) Complex z_[15][64][24]; + + uint8_t bit_reverse_[64]; + Complex fft_twiddle_[32]; + double rotation_sin_[64]; + double rotation_cos_[64]; + char error_[256]; +}; + +} // namespace ejoc + +extern "C" { + +uint32_t EJOC_CALL ejoc_abi_version(void) { + return EJOC_ABI_VERSION; +} + +const char* EJOC_CALL ejoc_build_info(void) { +#if defined(_MSC_VER) + return "eac3joc-core abi=1 compiler=MSVC fft=fixed64 speaker=double binaural=double crt=static-by-build"; +#elif defined(__clang__) + return "eac3joc-core abi=1 compiler=Clang fft=fixed64 speaker=double binaural=double"; +#elif defined(__GNUC__) + return "eac3joc-core abi=1 compiler=GCC fft=fixed64 speaker=double binaural=double"; +#else + return "eac3joc-core abi=1 compiler=unknown fft=fixed64 speaker=double binaural=double"; +#endif +} + +ejoc_renderer_handle EJOC_CALL ejoc_renderer_create(void) { + return new (std::nothrow) ejoc::Renderer(); +} + +void EJOC_CALL ejoc_renderer_destroy(ejoc_renderer_handle handle) { + delete static_cast(handle); +} + +int EJOC_CALL ejoc_renderer_reset(ejoc_renderer_handle handle) { + if (!handle) { + return -1; + } + return static_cast(handle)->reset(); +} + +int EJOC_CALL ejoc_renderer_set_threads(ejoc_renderer_handle handle, uint32_t total_threads) { + if (!handle) { + return -1; + } + return static_cast(handle)->set_threads(total_threads); +} + +uint32_t EJOC_CALL ejoc_renderer_thread_count(ejoc_renderer_handle handle) { + if (!handle) { + return 0; + } + return static_cast(handle)->thread_count(); +} + +const char* EJOC_CALL ejoc_renderer_last_error(ejoc_renderer_handle handle) { + if (!handle) { + return "null renderer handle"; + } + return static_cast(handle)->error(); +} + +int EJOC_CALL ejoc_renderer_process( + ejoc_renderer_handle handle, + const float* bed5_planar, + const float* lfe, + const uint32_t object_mask, + const uint8_t* n_bands, + const uint8_t* n_dpoints, + const uint8_t* slope_idx, + const uint8_t* offset_ts, + const double* dq, + const double clipgain, + const float phase_new, + const float output_scale, + float* output16_planar) { + if (!handle) { + return -1; + } + return static_cast(handle)->process( + bed5_planar, lfe, object_mask, n_bands, n_dpoints, slope_idx, + offset_ts, dq, clipgain, phase_new, output_scale, output16_planar); +} + +} // extern "C" diff --git a/src/joc_core/objects16.cpp b/src/joc_core/objects16.cpp new file mode 100644 index 0000000..83b6026 --- /dev/null +++ b/src/joc_core/objects16.cpp @@ -0,0 +1,70 @@ +#include "joc_core/objects16.h" + +#include + +namespace joc::joc { + +Status rebuild_objects16(ejoc_renderer_handle handle, const joc_frame_params& params, + const float* bed5_planar, const float* lfe, float gain, + std::vector* out16, std::string* error) { + if (handle == nullptr || bed5_planar == nullptr || out16 == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kDsp, "null argument"); + } + if (params.n_channels != JOC_CORE_CHANNELS) { + if (error != nullptr) { + *error = "the reused JOC kernel requires 5 core channels, frame declares " + + std::to_string(static_cast(params.n_channels)); + } + return Status::fail(JOC_ERR_JOC_UNSUPPORTED_VARIANT, stage::kDsp, *error); + } + + std::vector dq(static_cast(JOC_MAX_OBJECTS) * JOC_MAX_DPOINTS * + JOC_CORE_CHANNELS * JOC_MAX_PARAMETER_BANDS, + 0.0); + std::uint8_t n_bands[JOC_MAX_OBJECTS] = {}; + std::uint8_t n_dpoints[JOC_MAX_OBJECTS] = {}; + std::uint8_t slope_idx[JOC_MAX_OBJECTS] = {}; + std::uint8_t offset_ts[JOC_MAX_OBJECTS * JOC_MAX_DPOINTS] = {}; + for (unsigned obj = 0; obj < JOC_MAX_OBJECTS; ++obj) { + const joc_object_params& object = params.objects[obj]; + if (object.present == 0) { + continue; + } + n_bands[obj] = object.n_bands; + n_dpoints[obj] = object.n_dpoints; + slope_idx[obj] = object.slope_idx; + for (unsigned dp = 0; dp < JOC_MAX_DPOINTS; ++dp) { + offset_ts[obj * JOC_MAX_DPOINTS + dp] = object.offset_ts[dp]; + } + for (unsigned dp = 0; dp < object.n_dpoints; ++dp) { + for (unsigned ch = 0; ch < JOC_CORE_CHANNELS; ++ch) { + for (unsigned pb = 0; pb < object.n_bands; ++pb) { + const std::size_t index = + ((static_cast(obj) * JOC_MAX_DPOINTS + dp) * JOC_CORE_CHANNELS + + ch) * + JOC_MAX_PARAMETER_BANDS + + pb; + dq[index] = object.dq[dp][ch][pb]; + } + } + } + } + + out16->assign(static_cast(JOC_OUTPUT_CHANNELS) * JOC_FRAME_SAMPLES, 0.0f); + const int result = ejoc_renderer_process( + handle, bed5_planar, lfe, params.present_mask, n_bands, n_dpoints, slope_idx, offset_ts, + dq.data(), params.clipgain, 0.0625f, gain, out16->data()); + if (result != 0) { + const char* detail = ejoc_renderer_last_error(handle); + const std::string message = + "ejoc_renderer_process failed (" + std::to_string(result) + "): " + + (detail != nullptr ? detail : "unknown"); + if (error != nullptr) { + *error = message; + } + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kDsp, message); + } + return Status::success(); +} + +} // namespace joc::joc diff --git a/src/joc_core/objects16.h b/src/joc_core/objects16.h new file mode 100644 index 0000000..06a693d --- /dev/null +++ b/src/joc_core/objects16.h @@ -0,0 +1,18 @@ + +#pragma once + +#include +#include + +#include "eac3joc_core.h" +#include "foundation/status.h" +#include "joc_core.h" + +namespace joc::joc { + +// [16][1536] planar float32. The kernel requires exactly 5 core channels. +Status rebuild_objects16(ejoc_renderer_handle handle, const joc_frame_params& params, + const float* bed5_planar, const float* lfe, float gain, + std::vector* out16, std::string* error); + +} // namespace joc::joc diff --git a/src/joc_core/qmf_tables.h b/src/joc_core/qmf_tables.h new file mode 100644 index 0000000..e63f0e3 --- /dev/null +++ b/src/joc_core/qmf_tables.h @@ -0,0 +1,388 @@ +#pragma once + +#include + +// Generated table data; do not hand-edit. +namespace ejoc::tables { +inline constexpr double kAnalysisWindow[640] = { + 0.00019903187057934701, 0.00024947625934146345, 0.00030217695166356862, 0.00035484600812196732, + 0.0004058915947098285, 0.00045464080176316202, 0.00050126801943406463, 0.00054649583762511611, + 0.00059120741207152605, 0.0006361178238876164, 0.00068160606315359473, 0.00072772568091750145, + 0.00077434181002900004, 0.00082129903603345156, 0.00086853635730221868, 0.00091610715026035905, + 0.00096411682898178697, 0.0010126305278390646, 0.0010616052895784378, 0.0011108826147392392, + 0.0011602368904277682, 0.0012094489065930247, 0.0012583627831190825, 0.0013069023843854666, + 0.0013550462899729609, 0.0014027846045792103, 0.0014500867109745741, 0.0014968989416956902, + 0.0015431707724928856, 0.0015888890484347939, 0.0016340982401743531, 0.0016788924112915993, + 0.0017233812250196934, 0.0017676511779427528, 0.0018117419676855206, 0.0018556505674496293, + 0.0018993609119206667, 0.0019428766099736094, 0.0019862416666001081, 0.0020295341964811087, + 0.0020728406962007284, 0.0021162291523069143, 0.0021597379818558693, 0.0022033930290490389, + 0.0022472396958619356, 0.0022913739085197449, 0.0023359460756182671, 0.0023811329156160355, + 0.0024270866997539997, 0.0024738919455558062, 0.0025215502828359604, 0.0025700139813125134, + 0.0026192441582679749, 0.0026692659594118595, 0.002720177173614502, 0.0027720888610929251, + 0.0028250094037503004, 0.0028787164483219385, 0.0029326770454645157, 0.0029860674403607845, + 0.0030379060190171003, 0.0030872693751007318, 0.0031335193198174238, 0.0031764607410877943, + 0.0032163741998374462, 0.0032539025414735079, 0.0032898378558456898, 0.0033248732797801495, + 0.003359407652169466, 0.0033934540115296841, 0.0034266682341694832, 0.0034584659151732922, + 0.0034881711471825838, 0.0035151413176208735, 0.0035388274118304253, 0.0035587677266448736, + 0.0035745392087846994, 0.0035856980830430984, 0.0035917432978749275, 0.0035921167582273483, + 0.0035862282384186983, 0.0035734928678721189, 0.0035533567424863577, 0.0035253004170954227, + 0.0034888240043073893, 0.003443423192948103, 0.0033885682933032513, 0.0033236993476748466, + 0.0032482317183166742, 0.0031615688931196928, 0.0030631136614829302, 0.0029522709082812071, + 0.0028284420259296894, 0.0026910160668194294, 0.0025393660180270672, 0.0023728485684841871, + 0.0021908141206949949, 0.0019926181994378567, 0.0017776311142370105, 0.0015452421503141522, + 0.001294855959713459, 0.0010258855763822794, 0.00073774566408246756, 0.00042984966421499848, + 0.00010161137470277026, -0.00024754938203841448, -0.00061819725669920444, -0.0010108760325238109, + -0.001426108181476593, -0.0018643926596269011, -0.0023262077011168003, -0.002812013728544116, + -0.0033222525380551815, -0.003857344388961792, -0.0044176783412694931, -0.0050036045722663403, + -0.0056154225021600723, -0.0062533821910619736, -0.0069176913239061832, -0.0076085370965301991, + -0.008326113224029541, -0.0090706516057252884, -0.0098424339666962624, -0.010641784407198429, + -0.011469035409390926, -0.012324465438723564, -0.013208229094743729, -0.014120301231741905, + 0.015060451813042164, 0.016028247773647308, 0.017023105174303055, 0.018044359982013702, + 0.019091326743364334, 0.020163353532552719, 0.021259821951389313, 0.022380130365490913, + 0.02352365106344223, 0.024689681828022003, 0.025877414271235466, 0.027085918933153152, + 0.028314167633652687, 0.029561035335063934, 0.030825328081846237, 0.032105788588523865, + 0.033401083201169968, 0.034709792584180832, 0.036030396819114685, 0.037361271679401398, + 0.03870067372918129, 0.040046781301498413, 0.041397668421268463, 0.042751342058181763, + 0.044105727225542068, 0.045458663254976273, 0.046807888895273209, 0.048151064664125443, + 0.049485750496387482, 0.050809424370527267, 0.05211947113275528, 0.053413204848766327, + 0.054687850177288055, 0.055940557271242142, 0.057168368250131607, 0.058368254452943802, + 0.059537097811698914, 0.06067170575261116, 0.061768818646669388, 0.062825113534927368, + 0.063837200403213501, 0.064801648259162903, 0.065714947879314423, 0.066573545336723328, + 0.067373812198638916, 0.068112112581729889, 0.068784743547439575, 0.069387979805469513, + 0.069918066263198853, 0.070371203124523163, 0.070743560791015625, 0.071031264960765839, + 0.071230456233024597, 0.071337237954139709, 0.071347743272781372, 0.071258097887039185, + 0.07106444239616394, 0.070762887597084045, 0.070349536836147308, 0.069820456206798553, + 0.069171726703643799, 0.068399444222450256, 0.067499779164791107, 0.066468983888626099, + 0.065303429961204529, 0.063999593257904053, 0.062554046511650085, 0.060963429510593414, + 0.059224434196949005, 0.057333782315254211, 0.055288247764110565, 0.05308464914560318, + 0.050719890743494034, 0.04819098487496376, 0.045495055615901947, 0.042629346251487732, + 0.039591230452060699, 0.036378197371959686, 0.032987859100103378, 0.029417969286441803, + 0.025666400790214539, 0.0217311792075634, 0.017610486596822739, 0.013302664272487164, + 0.0088062174618244171, 0.0041198157705366611, -0.00075770384864881635, -0.0058273370377719402, + -0.011089906096458435, -0.016546055674552917, -0.022196246311068535, -0.028040755540132523, + -0.034079667180776596, -0.040312871336936951, -0.046740073710680008, -0.053360763937234879, + -0.06017424538731575, -0.0671796053647995, -0.074375726282596588, -0.081761270761489868, + -0.089334696531295776, -0.097094230353832245, -0.10503791272640228, -0.1131635457277298, + -0.12146873027086258, -0.12995083630084991, -0.13860704004764557, -0.1474342942237854, + -0.15642932057380676, -0.1655886322259903, -0.17490856349468231, -0.18438516557216644, + -0.19401434063911438, -0.20379173755645752, -0.21371282637119293, -0.22377283871173859, + -0.23396681249141693, -0.24428960680961609, -0.25473582744598389, -0.26529994606971741, + -0.27597621083259583, -0.2867586612701416, -0.29764124751091003, -0.30861768126487732, + -0.31968152523040771, -0.33082622289657593, -0.34204500913619995, -0.35333094000816345, + 0.36467701196670532, 0.37607598304748535, 0.38752046227455139, 0.39900293946266174, + 0.41051584482192993, 0.42205137014389038, 0.4336017370223999, 0.44515895843505859, + 0.45671501755714417, 0.46826183795928955, 0.47979119420051575, 0.49129492044448853, + 0.50276464223861694, 0.51419198513031006, 0.52556860446929932, 0.53688603639602661, + 0.54813587665557861, 0.55930960178375244, 0.57039880752563477, 0.58139497041702271, + 0.59228962659835815, 0.60307443141937256, 0.61374092102050781, 0.62428075075149536, + 0.63468557596206665, 0.64494723081588745, 0.65505754947662354, 0.66500836610794067, + 0.67479169368743896, 0.68439966440200806, 0.69382447004318237, 0.70305842161178589, + 0.71209394931793213, 0.72092366218566895, 0.72954028844833374, 0.73793661594390869, + 0.74610573053359985, 0.75404083728790283, 0.76173526048660278, 0.76918256282806396, + 0.77637648582458496, 0.78331100940704346, 0.78998017311096191, 0.79637837409973145, + 0.80250018835067749, 0.80834043025970459, 0.81389403343200684, 0.81915634870529175, + 0.82412278652191162, 0.82878917455673218, 0.83315145969390869, 0.83720588684082031, + 0.84094899892807007, 0.84437751770019531, 0.84748858213424683, 0.85027939081192017, + 0.85274755954742432, 0.85489106178283691, 0.85670793056488037, 0.8581966757774353, + 0.85935592651367188, 0.86018466949462891, 0.86068224906921387, 0.86084812879562378, + 0.86068224906921387, 0.86018466949462891, 0.85935592651367188, 0.8581966757774353, + 0.85670793056488037, 0.85489106178283691, 0.85274755954742432, 0.85027939081192017, + 0.84748858213424683, 0.84437751770019531, 0.84094899892807007, 0.83720588684082031, + 0.83315145969390869, 0.82878917455673218, 0.82412278652191162, 0.81915634870529175, + 0.81389403343200684, 0.80834043025970459, 0.80250018835067749, 0.79637837409973145, + 0.78998017311096191, 0.78331100940704346, 0.77637648582458496, 0.76918256282806396, + 0.76173526048660278, 0.75404083728790283, 0.74610573053359985, 0.73793661594390869, + 0.72954028844833374, 0.72092366218566895, 0.71209394931793213, 0.70305842161178589, + 0.69382447004318237, 0.68439966440200806, 0.67479169368743896, 0.66500836610794067, + 0.65505754947662354, 0.64494723081588745, 0.63468557596206665, 0.62428075075149536, + 0.61374092102050781, 0.60307443141937256, 0.59228962659835815, 0.58139497041702271, + 0.57039880752563477, 0.55930960178375244, 0.54813587665557861, 0.53688603639602661, + 0.52556860446929932, 0.51419198513031006, 0.50276464223861694, 0.49129492044448853, + 0.47979119420051575, 0.46826183795928955, 0.45671501755714417, 0.44515895843505859, + 0.4336017370223999, 0.42205137014389038, 0.41051584482192993, 0.39900293946266174, + 0.38752046227455139, 0.37607598304748535, 0.36467701196670532, 0.35333094000816345, + -0.34204500913619995, -0.33082622289657593, -0.31968152523040771, -0.30861768126487732, + -0.29764124751091003, -0.2867586612701416, -0.27597621083259583, -0.26529994606971741, + -0.25473582744598389, -0.24428960680961609, -0.23396681249141693, -0.22377283871173859, + -0.21371282637119293, -0.20379173755645752, -0.19401434063911438, -0.18438516557216644, + -0.17490856349468231, -0.1655886322259903, -0.15642932057380676, -0.1474342942237854, + -0.13860704004764557, -0.12995083630084991, -0.12146873027086258, -0.1131635457277298, + -0.10503791272640228, -0.097094230353832245, -0.089334696531295776, -0.081761270761489868, + -0.074375726282596588, -0.0671796053647995, -0.06017424538731575, -0.053360763937234879, + -0.046740073710680008, -0.040312871336936951, -0.034079667180776596, -0.028040755540132523, + -0.022196246311068535, -0.016546055674552917, -0.011089906096458435, -0.0058273370377719402, + -0.00075770384864881635, 0.0041198157705366611, 0.0088062174618244171, 0.013302664272487164, + 0.017610486596822739, 0.0217311792075634, 0.025666400790214539, 0.029417969286441803, + 0.032987859100103378, 0.036378197371959686, 0.039591230452060699, 0.042629346251487732, + 0.045495055615901947, 0.04819098487496376, 0.050719890743494034, 0.05308464914560318, + 0.055288247764110565, 0.057333782315254211, 0.059224434196949005, 0.060963429510593414, + 0.062554046511650085, 0.063999593257904053, 0.065303429961204529, 0.066468983888626099, + 0.067499779164791107, 0.068399444222450256, 0.069171726703643799, 0.069820456206798553, + 0.070349536836147308, 0.070762887597084045, 0.07106444239616394, 0.071258097887039185, + 0.071347743272781372, 0.071337237954139709, 0.071230456233024597, 0.071031264960765839, + 0.070743560791015625, 0.070371203124523163, 0.069918066263198853, 0.069387979805469513, + 0.068784743547439575, 0.068112112581729889, 0.067373812198638916, 0.066573545336723328, + 0.065714947879314423, 0.064801648259162903, 0.063837200403213501, 0.062825113534927368, + 0.061768818646669388, 0.06067170575261116, 0.059537097811698914, 0.058368254452943802, + 0.057168368250131607, 0.055940557271242142, 0.054687850177288055, 0.053413204848766327, + 0.05211947113275528, 0.050809424370527267, 0.049485750496387482, 0.048151064664125443, + 0.046807888895273209, 0.045458663254976273, 0.044105727225542068, 0.042751342058181763, + 0.041397668421268463, 0.040046781301498413, 0.03870067372918129, 0.037361271679401398, + 0.036030396819114685, 0.034709792584180832, 0.033401083201169968, 0.032105788588523865, + 0.030825328081846237, 0.029561035335063934, 0.028314167633652687, 0.027085918933153152, + 0.025877414271235466, 0.024689681828022003, 0.02352365106344223, 0.022380130365490913, + 0.021259821951389313, 0.020163353532552719, 0.019091326743364334, 0.018044359982013702, + 0.017023105174303055, 0.016028247773647308, 0.015060451813042164, 0.014120301231741905, + -0.013208229094743729, -0.012324465438723564, -0.011469035409390926, -0.010641784407198429, + -0.0098424339666962624, -0.0090706516057252884, -0.008326113224029541, -0.0076085370965301991, + -0.0069176913239061832, -0.0062533821910619736, -0.0056154225021600723, -0.0050036045722663403, + -0.0044176783412694931, -0.003857344388961792, -0.0033222525380551815, -0.002812013728544116, + -0.0023262077011168003, -0.0018643926596269011, -0.001426108181476593, -0.0010108760325238109, + -0.00061819725669920444, -0.00024754938203841448, 0.00010161137470277026, 0.00042984966421499848, + 0.00073774566408246756, 0.0010258855763822794, 0.001294855959713459, 0.0015452421503141522, + 0.0017776311142370105, 0.0019926181994378567, 0.0021908141206949949, 0.0023728485684841871, + 0.0025393660180270672, 0.0026910160668194294, 0.0028284420259296894, 0.0029522709082812071, + 0.0030631136614829302, 0.0031615688931196928, 0.0032482317183166742, 0.0033236993476748466, + 0.0033885682933032513, 0.003443423192948103, 0.0034888240043073893, 0.0035253004170954227, + 0.0035533567424863577, 0.0035734928678721189, 0.0035862282384186983, 0.0035921167582273483, + 0.0035917432978749275, 0.0035856980830430984, 0.0035745392087846994, 0.0035587677266448736, + 0.0035388274118304253, 0.0035151413176208735, 0.0034881711471825838, 0.0034584659151732922, + 0.0034266682341694832, 0.0033934540115296841, 0.003359407652169466, 0.0033248732797801495, + 0.0032898378558456898, 0.0032539025414735079, 0.0032163741998374462, 0.0031764607410877943, + 0.0031335193198174238, 0.0030872693751007318, 0.0030379060190171003, 0.0029860674403607845, + 0.0029326770454645157, 0.0028787164483219385, 0.0028250094037503004, 0.0027720888610929251, + 0.002720177173614502, 0.0026692659594118595, 0.0026192441582679749, 0.0025700139813125134, + 0.0025215502828359604, 0.0024738919455558062, 0.0024270866997539997, 0.0023811329156160355, + 0.0023359460756182671, 0.0022913739085197449, 0.0022472396958619356, 0.0022033930290490389, + 0.0021597379818558693, 0.0021162291523069143, 0.0020728406962007284, 0.0020295341964811087, + 0.0019862416666001081, 0.0019428766099736094, 0.0018993609119206667, 0.0018556505674496293, + 0.0018117419676855206, 0.0017676511779427528, 0.0017233812250196934, 0.0016788924112915993, + 0.0016340982401743531, 0.0015888890484347939, 0.0015431707724928856, 0.0014968989416956902, + 0.0014500867109745741, 0.0014027846045792103, 0.0013550462899729609, 0.0013069023843854666, + 0.0012583627831190825, 0.0012094489065930247, 0.0011602368904277682, 0.0011108826147392392, + 0.0010616052895784378, 0.0010126305278390646, 0.00096411682898178697, 0.00091610715026035905, + 0.00086853635730221868, 0.00082129903603345156, 0.00077434181002900004, 0.00072772568091750145, + 0.00068160606315359473, 0.0006361178238876164, 0.00059120741207152605, 0.00054649583762511611, + 0.00050126801943406463, 0.00045464080176316202, 0.0004058915947098285, 0.00035484600812196732, + 0.00030217695166356862, 0.00024947625934146345, 0.00019903187057934701, 0, +}; + +inline constexpr double kQmf5Window[640] = { + 0, 0.00019903187057934701, 0.00024947625934146345, 0.00030217695166356862, + 0.00035484600812196732, 0.0004058915947098285, 0.00045464080176316202, 0.00050126801943406463, + 0.00054649583762511611, 0.00059120741207152605, 0.0006361178238876164, 0.00068160606315359473, + 0.00072772568091750145, 0.00077434181002900004, 0.00082129903603345156, 0.00086853635730221868, + 0.00091610715026035905, 0.00096411682898178697, 0.0010126305278390646, 0.0010616052895784378, + 0.0011108826147392392, 0.0011602368904277682, 0.0012094489065930247, 0.0012583627831190825, + 0.0013069023843854666, 0.0013550462899729609, 0.0014027846045792103, 0.0014500867109745741, + 0.0014968989416956902, 0.0015431707724928856, 0.0015888890484347939, 0.0016340982401743531, + 0.0016788924112915993, 0.0017233812250196934, 0.0017676511779427528, 0.0018117419676855206, + 0.0018556505674496293, 0.0018993609119206667, 0.0019428766099736094, 0.0019862416666001081, + 0.0020295341964811087, 0.0020728406962007284, 0.0021162291523069143, 0.0021597379818558693, + 0.0022033930290490389, 0.0022472396958619356, 0.0022913739085197449, 0.0023359460756182671, + 0.0023811329156160355, 0.0024270866997539997, 0.0024738919455558062, 0.0025215502828359604, + 0.0025700139813125134, 0.0026192441582679749, 0.0026692659594118595, 0.002720177173614502, + 0.0027720888610929251, 0.0028250094037503004, 0.0028787164483219385, 0.0029326770454645157, + 0.0029860674403607845, 0.0030379060190171003, 0.0030872693751007318, 0.0031335193198174238, + 0.0031764607410877943, 0.0032163741998374462, 0.0032539025414735079, 0.0032898378558456898, + 0.0033248732797801495, 0.003359407652169466, 0.0033934540115296841, 0.0034266682341694832, + 0.0034584659151732922, 0.0034881711471825838, 0.0035151413176208735, 0.0035388274118304253, + 0.0035587677266448736, 0.0035745392087846994, 0.0035856980830430984, 0.0035917432978749275, + 0.0035921167582273483, 0.0035862282384186983, 0.0035734928678721189, 0.0035533567424863577, + 0.0035253004170954227, 0.0034888240043073893, 0.003443423192948103, 0.0033885682933032513, + 0.0033236993476748466, 0.0032482317183166742, 0.0031615688931196928, 0.0030631136614829302, + 0.0029522709082812071, 0.0028284420259296894, 0.0026910160668194294, 0.0025393660180270672, + 0.0023728485684841871, 0.0021908141206949949, 0.0019926181994378567, 0.0017776311142370105, + 0.0015452421503141522, 0.001294855959713459, 0.0010258855763822794, 0.00073774566408246756, + 0.00042984966421499848, 0.00010161137470277026, -0.00024754938203841448, -0.00061819725669920444, + -0.0010108760325238109, -0.001426108181476593, -0.0018643926596269011, -0.0023262077011168003, + -0.002812013728544116, -0.0033222525380551815, -0.003857344388961792, -0.0044176783412694931, + -0.0050036045722663403, -0.0056154225021600723, -0.0062533821910619736, -0.0069176913239061832, + -0.0076085370965301991, -0.008326113224029541, -0.0090706516057252884, -0.0098424339666962624, + -0.010641784407198429, -0.011469035409390926, -0.012324465438723564, -0.013208229094743729, + 0.014120301231741905, 0.015060451813042164, 0.016028247773647308, 0.017023105174303055, + 0.018044359982013702, 0.019091326743364334, 0.020163353532552719, 0.021259821951389313, + 0.022380130365490913, 0.02352365106344223, 0.024689681828022003, 0.025877414271235466, + 0.027085918933153152, 0.028314167633652687, 0.029561035335063934, 0.030825328081846237, + 0.032105788588523865, 0.033401083201169968, 0.034709792584180832, 0.036030396819114685, + 0.037361271679401398, 0.03870067372918129, 0.040046781301498413, 0.041397668421268463, + 0.042751342058181763, 0.044105727225542068, 0.045458663254976273, 0.046807888895273209, + 0.048151064664125443, 0.049485750496387482, 0.050809424370527267, 0.05211947113275528, + 0.053413204848766327, 0.054687850177288055, 0.055940557271242142, 0.057168368250131607, + 0.058368254452943802, 0.059537097811698914, 0.06067170575261116, 0.061768818646669388, + 0.062825113534927368, 0.063837200403213501, 0.064801648259162903, 0.065714947879314423, + 0.066573545336723328, 0.067373812198638916, 0.068112112581729889, 0.068784743547439575, + 0.069387979805469513, 0.069918066263198853, 0.070371203124523163, 0.070743560791015625, + 0.071031264960765839, 0.071230456233024597, 0.071337237954139709, 0.071347743272781372, + 0.071258097887039185, 0.07106444239616394, 0.070762887597084045, 0.070349536836147308, + 0.069820456206798553, 0.069171726703643799, 0.068399444222450256, 0.067499779164791107, + 0.066468983888626099, 0.065303429961204529, 0.063999593257904053, 0.062554046511650085, + 0.060963429510593414, 0.059224434196949005, 0.057333782315254211, 0.055288247764110565, + 0.05308464914560318, 0.050719890743494034, 0.04819098487496376, 0.045495055615901947, + 0.042629346251487732, 0.039591230452060699, 0.036378197371959686, 0.032987859100103378, + 0.029417969286441803, 0.025666400790214539, 0.0217311792075634, 0.017610486596822739, + 0.013302664272487164, 0.0088062174618244171, 0.0041198157705366611, -0.00075770384864881635, + -0.0058273370377719402, -0.011089906096458435, -0.016546055674552917, -0.022196246311068535, + -0.028040755540132523, -0.034079667180776596, -0.040312871336936951, -0.046740073710680008, + -0.053360763937234879, -0.06017424538731575, -0.0671796053647995, -0.074375726282596588, + -0.081761270761489868, -0.089334696531295776, -0.097094230353832245, -0.10503791272640228, + -0.1131635457277298, -0.12146873027086258, -0.12995083630084991, -0.13860704004764557, + -0.1474342942237854, -0.15642932057380676, -0.1655886322259903, -0.17490856349468231, + -0.18438516557216644, -0.19401434063911438, -0.20379173755645752, -0.21371282637119293, + -0.22377283871173859, -0.23396681249141693, -0.24428960680961609, -0.25473582744598389, + -0.26529994606971741, -0.27597621083259583, -0.2867586612701416, -0.29764124751091003, + -0.30861768126487732, -0.31968152523040771, -0.33082622289657593, -0.34204500913619995, + 0.35333094000816345, 0.36467701196670532, 0.37607598304748535, 0.38752046227455139, + 0.39900293946266174, 0.41051584482192993, 0.42205137014389038, 0.4336017370223999, + 0.44515895843505859, 0.45671501755714417, 0.46826183795928955, 0.47979119420051575, + 0.49129492044448853, 0.50276464223861694, 0.51419198513031006, 0.52556860446929932, + 0.53688603639602661, 0.54813587665557861, 0.55930960178375244, 0.57039880752563477, + 0.58139497041702271, 0.59228962659835815, 0.60307443141937256, 0.61374092102050781, + 0.62428075075149536, 0.63468557596206665, 0.64494723081588745, 0.65505754947662354, + 0.66500836610794067, 0.67479169368743896, 0.68439966440200806, 0.69382447004318237, + 0.70305842161178589, 0.71209394931793213, 0.72092366218566895, 0.72954028844833374, + 0.73793661594390869, 0.74610573053359985, 0.75404083728790283, 0.76173526048660278, + 0.76918256282806396, 0.77637648582458496, 0.78331100940704346, 0.78998017311096191, + 0.79637837409973145, 0.80250018835067749, 0.80834043025970459, 0.81389403343200684, + 0.81915634870529175, 0.82412278652191162, 0.82878917455673218, 0.83315145969390869, + 0.83720588684082031, 0.84094899892807007, 0.84437751770019531, 0.84748858213424683, + 0.85027939081192017, 0.85274755954742432, 0.85489106178283691, 0.85670793056488037, + 0.8581966757774353, 0.85935592651367188, 0.86018466949462891, 0.86068224906921387, + 0.86084812879562378, 0.86068224906921387, 0.86018466949462891, 0.85935592651367188, + 0.8581966757774353, 0.85670793056488037, 0.85489106178283691, 0.85274755954742432, + 0.85027939081192017, 0.84748858213424683, 0.84437751770019531, 0.84094899892807007, + 0.83720588684082031, 0.83315145969390869, 0.82878917455673218, 0.82412278652191162, + 0.81915634870529175, 0.81389403343200684, 0.80834043025970459, 0.80250018835067749, + 0.79637837409973145, 0.78998017311096191, 0.78331100940704346, 0.77637648582458496, + 0.76918256282806396, 0.76173526048660278, 0.75404083728790283, 0.74610573053359985, + 0.73793661594390869, 0.72954028844833374, 0.72092366218566895, 0.71209394931793213, + 0.70305842161178589, 0.69382447004318237, 0.68439966440200806, 0.67479169368743896, + 0.66500836610794067, 0.65505754947662354, 0.64494723081588745, 0.63468557596206665, + 0.62428075075149536, 0.61374092102050781, 0.60307443141937256, 0.59228962659835815, + 0.58139497041702271, 0.57039880752563477, 0.55930960178375244, 0.54813587665557861, + 0.53688603639602661, 0.52556860446929932, 0.51419198513031006, 0.50276464223861694, + 0.49129492044448853, 0.47979119420051575, 0.46826183795928955, 0.45671501755714417, + 0.44515895843505859, 0.4336017370223999, 0.42205137014389038, 0.41051584482192993, + 0.39900293946266174, 0.38752046227455139, 0.37607598304748535, 0.36467701196670532, + -0.35333094000816345, -0.34204500913619995, -0.33082622289657593, -0.31968152523040771, + -0.30861768126487732, -0.29764124751091003, -0.2867586612701416, -0.27597621083259583, + -0.26529994606971741, -0.25473582744598389, -0.24428960680961609, -0.23396681249141693, + -0.22377283871173859, -0.21371282637119293, -0.20379173755645752, -0.19401434063911438, + -0.18438516557216644, -0.17490856349468231, -0.1655886322259903, -0.15642932057380676, + -0.1474342942237854, -0.13860704004764557, -0.12995083630084991, -0.12146873027086258, + -0.1131635457277298, -0.10503791272640228, -0.097094230353832245, -0.089334696531295776, + -0.081761270761489868, -0.074375726282596588, -0.0671796053647995, -0.06017424538731575, + -0.053360763937234879, -0.046740073710680008, -0.040312871336936951, -0.034079667180776596, + -0.028040755540132523, -0.022196246311068535, -0.016546055674552917, -0.011089906096458435, + -0.0058273370377719402, -0.00075770384864881635, 0.0041198157705366611, 0.0088062174618244171, + 0.013302664272487164, 0.017610486596822739, 0.0217311792075634, 0.025666400790214539, + 0.029417969286441803, 0.032987859100103378, 0.036378197371959686, 0.039591230452060699, + 0.042629346251487732, 0.045495055615901947, 0.04819098487496376, 0.050719890743494034, + 0.05308464914560318, 0.055288247764110565, 0.057333782315254211, 0.059224434196949005, + 0.060963429510593414, 0.062554046511650085, 0.063999593257904053, 0.065303429961204529, + 0.066468983888626099, 0.067499779164791107, 0.068399444222450256, 0.069171726703643799, + 0.069820456206798553, 0.070349536836147308, 0.070762887597084045, 0.07106444239616394, + 0.071258097887039185, 0.071347743272781372, 0.071337237954139709, 0.071230456233024597, + 0.071031264960765839, 0.070743560791015625, 0.070371203124523163, 0.069918066263198853, + 0.069387979805469513, 0.068784743547439575, 0.068112112581729889, 0.067373812198638916, + 0.066573545336723328, 0.065714947879314423, 0.064801648259162903, 0.063837200403213501, + 0.062825113534927368, 0.061768818646669388, 0.06067170575261116, 0.059537097811698914, + 0.058368254452943802, 0.057168368250131607, 0.055940557271242142, 0.054687850177288055, + 0.053413204848766327, 0.05211947113275528, 0.050809424370527267, 0.049485750496387482, + 0.048151064664125443, 0.046807888895273209, 0.045458663254976273, 0.044105727225542068, + 0.042751342058181763, 0.041397668421268463, 0.040046781301498413, 0.03870067372918129, + 0.037361271679401398, 0.036030396819114685, 0.034709792584180832, 0.033401083201169968, + 0.032105788588523865, 0.030825328081846237, 0.029561035335063934, 0.028314167633652687, + 0.027085918933153152, 0.025877414271235466, 0.024689681828022003, 0.02352365106344223, + 0.022380130365490913, 0.021259821951389313, 0.020163353532552719, 0.019091326743364334, + 0.018044359982013702, 0.017023105174303055, 0.016028247773647308, 0.015060451813042164, + -0.014120301231741905, -0.013208229094743729, -0.012324465438723564, -0.011469035409390926, + -0.010641784407198429, -0.0098424339666962624, -0.0090706516057252884, -0.008326113224029541, + -0.0076085370965301991, -0.0069176913239061832, -0.0062533821910619736, -0.0056154225021600723, + -0.0050036045722663403, -0.0044176783412694931, -0.003857344388961792, -0.0033222525380551815, + -0.002812013728544116, -0.0023262077011168003, -0.0018643926596269011, -0.001426108181476593, + -0.0010108760325238109, -0.00061819725669920444, -0.00024754938203841448, 0.00010161137470277026, + 0.00042984966421499848, 0.00073774566408246756, 0.0010258855763822794, 0.001294855959713459, + 0.0015452421503141522, 0.0017776311142370105, 0.0019926181994378567, 0.0021908141206949949, + 0.0023728485684841871, 0.0025393660180270672, 0.0026910160668194294, 0.0028284420259296894, + 0.0029522709082812071, 0.0030631136614829302, 0.0031615688931196928, 0.0032482317183166742, + 0.0033236993476748466, 0.0033885682933032513, 0.003443423192948103, 0.0034888240043073893, + 0.0035253004170954227, 0.0035533567424863577, 0.0035734928678721189, 0.0035862282384186983, + 0.0035921167582273483, 0.0035917432978749275, 0.0035856980830430984, 0.0035745392087846994, + 0.0035587677266448736, 0.0035388274118304253, 0.0035151413176208735, 0.0034881711471825838, + 0.0034584659151732922, 0.0034266682341694832, 0.0033934540115296841, 0.003359407652169466, + 0.0033248732797801495, 0.0032898378558456898, 0.0032539025414735079, 0.0032163741998374462, + 0.0031764607410877943, 0.0031335193198174238, 0.0030872693751007318, 0.0030379060190171003, + 0.0029860674403607845, 0.0029326770454645157, 0.0028787164483219385, 0.0028250094037503004, + 0.0027720888610929251, 0.002720177173614502, 0.0026692659594118595, 0.0026192441582679749, + 0.0025700139813125134, 0.0025215502828359604, 0.0024738919455558062, 0.0024270866997539997, + 0.0023811329156160355, 0.0023359460756182671, 0.0022913739085197449, 0.0022472396958619356, + 0.0022033930290490389, 0.0021597379818558693, 0.0021162291523069143, 0.0020728406962007284, + 0.0020295341964811087, 0.0019862416666001081, 0.0019428766099736094, 0.0018993609119206667, + 0.0018556505674496293, 0.0018117419676855206, 0.0017676511779427528, 0.0017233812250196934, + 0.0016788924112915993, 0.0016340982401743531, 0.0015888890484347939, 0.0015431707724928856, + 0.0014968989416956902, 0.0014500867109745741, 0.0014027846045792103, 0.0013550462899729609, + 0.0013069023843854666, 0.0012583627831190825, 0.0012094489065930247, 0.0011602368904277682, + 0.0011108826147392392, 0.0010616052895784378, 0.0010126305278390646, 0.00096411682898178697, + 0.00091610715026035905, 0.00086853635730221868, 0.00082129903603345156, 0.00077434181002900004, + 0.00072772568091750145, 0.00068160606315359473, 0.0006361178238876164, 0.00059120741207152605, + 0.00054649583762511611, 0.00050126801943406463, 0.00045464080176316202, 0.0004058915947098285, + 0.00035484600812196732, 0.00030217695166356862, 0.00024947625934146345, 0.00019903187057934701, +}; + +inline constexpr uint8_t kPbMap1[64] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +inline constexpr uint8_t kPbMap3[64] = { + 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +}; + +inline constexpr uint8_t kPbMap5[64] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +}; + +inline constexpr uint8_t kPbMap7[64] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +}; + +inline constexpr uint8_t kPbMap9[64] = { + 0, 1, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, +}; + +inline constexpr uint8_t kPbMap12[64] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +}; + +inline constexpr uint8_t kPbMap15[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +}; + +inline constexpr uint8_t kPbMap23[64] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, + 19, 19, 19, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, +}; +} // namespace ejoc::tables diff --git a/src/oamd/oamd_parser.cpp b/src/oamd/oamd_parser.cpp new file mode 100644 index 0000000..750dffa --- /dev/null +++ b/src/oamd/oamd_parser.cpp @@ -0,0 +1,500 @@ +#include "oamd/oamd_parser.h" + +#include +#include + +#include "foundation/bit_reader.h" + +namespace joc::oamd { + +namespace { + +constexpr int kSampleOffsetIndex[4] = {8, 16, 18, 24}; +constexpr int kRampDurations[3] = {0, 512, 1536}; +constexpr int kRampDurationIndex[16] = {32, 64, 128, 256, 320, 480, + 1000, 1001, 1024, 1600, 1601, 1602, + 1920, 2000, 2002, 2048}; +constexpr std::uint32_t kObjectElementId = 1; +constexpr int kIsfObjectCounts[6] = {4, 8, 10, 14, 15, 30}; +constexpr int kStandardBedChannelCount[10] = {2, 1, 1, 2, 2, 2, 2, 2, 2, 1}; + +Status variant(const std::string& name, const std::string& message) { + return Status::fail(JOC_ERR_OAMD_UNSUPPORTED_VARIANT, stage::kOamd, + name + ": " + message); +} + +Status syntax(const std::string& message) { + return Status::fail(JOC_ERR_OAMD_SYNTAX, stage::kOamd, message); +} + +bool variable_bits_max(bits::BitReader& reader, unsigned width, unsigned max_groups, + std::uint32_t* out_value) { + std::uint32_t value = reader.read(width); + if (reader.failed()) { + return false; + } + std::uint32_t more = reader.read(1); + if (reader.failed()) { + return false; + } + unsigned num_group = 1; + if (max_groups > num_group) { + if (more != 0u) { + value = (value + 1u) << width; + } + while (more != 0u) { + value += reader.read(width); + more = reader.read(1); + if (reader.failed()) { + return false; + } + if (num_group >= max_groups) { + break; + } + if (more != 0u) { + value = (value + 1u) << width; + num_group += 1; + } + } + } + *out_value = value; + return true; +} + +struct ProgramInfo { + bool dynamic_object_only = false; + bool lfe_present = false; + std::uint32_t num_bed_objects = 0; + std::uint32_t num_isf_objects = 0; + std::int32_t num_dynamic_objects = -1; + std::vector bed_assignments; +}; + +Status parse_program_assignment(bits::BitReader& reader, ProgramInfo* program) { + program->dynamic_object_only = reader.read(1) != 0u; + if (reader.failed()) { + return syntax("program_assignment truncated"); + } + if (program->dynamic_object_only) { + program->lfe_present = reader.read(1) != 0u; + if (reader.failed()) { + return syntax("program_assignment truncated"); + } + program->num_bed_objects = program->lfe_present ? 1u : 0u; + return Status::success(); + } + + const std::uint32_t mask = reader.read(4); + if (reader.failed()) { + return syntax("program_assignment truncated"); + } + if ((mask & 0x1u) != 0u) { + reader.read(1); + const std::uint32_t multi = reader.read(1); + if (reader.failed()) { + return syntax("program_assignment truncated"); + } + std::uint32_t instances = 1; + if (multi != 0u) { + instances = reader.read(3) + 2u; + } + for (std::uint32_t instance = 0; instance < instances; ++instance) { + BedAssignment assignment; + if (reader.read(1) != 0u) { + assignment.lfe_only = true; + assignment.mask = 0; + program->bed_assignments.push_back(assignment); + program->num_bed_objects += 1; + continue; + } + if (reader.read(1) != 0u) { + assignment.standard = true; + assignment.mask = reader.read(10); + for (int bit = 0; bit < 10; ++bit) { + if (((assignment.mask >> bit) & 1u) != 0u) { + program->num_bed_objects += + static_cast(kStandardBedChannelCount[bit]); + } + } + } else { + assignment.standard = false; + assignment.mask = reader.read(17); + for (int bit = 0; bit < 17; ++bit) { + if (((assignment.mask >> bit) & 1u) != 0u) { + program->num_bed_objects += 1; + } + } + } + program->bed_assignments.push_back(assignment); + if (reader.failed()) { + return syntax("program_assignment truncated"); + } + } + } + if ((mask & 0x2u) != 0u) { + const std::uint32_t isf_idx = reader.read(3); + if (reader.failed()) { + return syntax("program_assignment truncated"); + } + program->num_isf_objects = + (isf_idx < 6u) ? static_cast(kIsfObjectCounts[isf_idx]) : 0u; + } + if ((mask & 0x4u) != 0u) { + std::uint32_t count = reader.read(5); + if (count == 0x1Fu) { + count += reader.read(7); + } + if (reader.failed()) { + return syntax("program_assignment truncated"); + } + program->num_dynamic_objects = static_cast(count + 1u); + } + if ((mask & 0x8u) != 0u) { + const std::uint32_t reserved_bytes = reader.read(4) + 1u; + if (!reader.skip(static_cast(reserved_bytes) * 8u)) { + return syntax("program_assignment reserved data truncated"); + } + } + return Status::success(); +} + +Status parse_object_info_block(bits::BitReader& reader, int object_index, bool in_bed_or_isf, + int* position_x, int* position_y, int* position_z, bool* has_position) { + *has_position = false; + const bool not_active = reader.read(1) != 0u; + if (reader.failed()) { + return syntax("object_info_block truncated"); + } + const std::uint32_t basic_status = not_active ? 0u : 1u; + if (basic_status == 1u) { + const std::uint32_t gain_idx = reader.read(2); + if (gain_idx == 2u) { + reader.read(6); + } + const bool default_priority = reader.read(1) != 0u; + if (!default_priority) { + reader.read(5); + } + if (reader.failed()) { + return syntax("object_info_block truncated"); + } + } + const std::uint32_t render_status = (not_active || in_bed_or_isf) ? 0u : 1u; + if (render_status == 1u) { + const int x = static_cast(reader.read(6)); + const int y = static_cast(reader.read(6)); + const int z_sign = static_cast(reader.read(1)); + const int z = static_cast(reader.read(4)); + if (reader.failed()) { + return syntax("object_info_block truncated"); + } + *position_x = x; + *position_y = y; + *position_z = z_sign != 0 ? z : -z; + *has_position = true; + if (reader.read(1) != 0u) { + if (reader.read(1) == 0u) { + reader.read(4); + } + } + reader.read(3); + reader.read(1); + const std::uint32_t size_idx = reader.read(2); + if (size_idx == 1u) { + reader.read(5); + } else if (size_idx == 2u) { + reader.read(15); + } + if (reader.read(1) != 0u) { + reader.read(3); + reader.read(2); + } + reader.read(1); + if (reader.failed()) { + return syntax("object_info_block truncated"); + } + } + if (reader.read(1) != 0u) { + const std::uint32_t additional_bytes = reader.read(4) + 1u; + if (!reader.skip(static_cast(additional_bytes) * 8u)) { + return syntax("object_info_block additional table truncated"); + } + } + (void)object_index; + return Status::success(); +} + +struct ObjectElementInfo { + std::uint32_t sample_offset_code = 0; + std::uint32_t sample_offset = 0; + std::uint32_t block_count = 0; + std::uint32_t block_offset_samples = 0; + std::uint32_t ramp_duration_samples = 0; + bool reserved_data_not_present = false; +}; + +Status parse_object_element(bits::BitReader& reader, std::uint32_t object_count, + std::uint32_t bed_isf_objects, ObjectElementInfo* out, OamdUpdate* update) { + out->sample_offset_code = reader.read(2); + if (reader.failed()) { + return syntax("object_element truncated"); + } + switch (out->sample_offset_code) { + case 0: out->sample_offset = 0; break; + case 1: { + const std::uint32_t index = reader.read(2); + if (reader.failed()) { + return syntax("object_element truncated"); + } + out->sample_offset = static_cast(kSampleOffsetIndex[index & 3u]); + break; + } + case 2: out->sample_offset = reader.read(5); break; + default: + return variant("md_sample_offset_mode", + "MD sample-offset mode " + + std::to_string(out->sample_offset_code) + + " is not covered by the 16-slot model"); + } + out->block_count = reader.read(3) + 1u; + if (reader.failed()) { + return syntax("object_element truncated"); + } + for (std::uint32_t block = 0; block < out->block_count; ++block) { + const std::uint32_t block_offset_factor = reader.read(6); + const std::uint32_t ramp_code = reader.read(2); + std::uint32_t ramp_duration = 0; + if (ramp_code == 3u) { + if (reader.read(1) != 0u) { + const std::uint32_t index = reader.read(4); + if (reader.failed()) { + return syntax("object_element truncated"); + } + ramp_duration = static_cast(kRampDurationIndex[index & 15u]); + } else { + ramp_duration = reader.read(11); + } + } else { + ramp_duration = static_cast(kRampDurations[ramp_code]); + } + if (reader.failed()) { + return syntax("object_element truncated"); + } + if (block == 0) { + out->block_offset_samples = out->sample_offset + block_offset_factor * 32u; + out->ramp_duration_samples = ramp_duration; + } + } + out->reserved_data_not_present = reader.read(1) != 0u; + if (!out->reserved_data_not_present) { + reader.read(5); + } + if (reader.failed()) { + return syntax("object_element truncated"); + } + + for (std::uint32_t index = 0; index < object_count; ++index) { + int x = 0; + int y = 0; + int z = 0; + bool has_position = false; + const bool in_bed_or_isf = index < bed_isf_objects; + const Status status = + parse_object_info_block(reader, static_cast(index), in_bed_or_isf, &x, &y, &z, + &has_position); + if (!status.ok()) { + return status; + } + if (!has_position || index >= static_cast(kMaxSlots)) { + continue; + } + update->slots[index].q1 = + (x >= 0 && x <= kNQ12) ? static_cast(q_of(x, kNQ12)) : static_cast(-1); + update->slots[index].q2 = + (y >= 0 && y <= kNQ12) ? static_cast(q_of(y, kNQ12)) : static_cast(-1); + if (z >= 0 && z <= kNQ3) { + update->slots[index].q3 = static_cast(q_of(z, kNQ3)); + } else if (z < 0) { + update->slots[index].q3 = 0; + } else { + update->slots[index].q3 = static_cast(-1); + } + } + return Status::success(); +} + +} // namespace + +int q_of(int k, int n) { + const double value = std::floor(32768.0 * static_cast(k) / static_cast(n) + 0.5); + const int quantised = static_cast(value); + return quantised > 32767 ? 32767 : quantised; +} + +Status parse_id11(const std::uint8_t* payload, std::size_t payload_size, OamdUpdate* out) { + return parse_id11_verbose(payload, payload_size, out, nullptr); +} + +Status parse_id11_verbose(const std::uint8_t* payload, std::size_t payload_size, OamdUpdate* out, + ParseTrace* trace) { + if (payload == nullptr || out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOamd, "null payload or output"); + } + if (payload_size == 0) { + return variant("header_truncated", "OAMD payload is empty"); + } + *out = OamdUpdate{}; + + bits::BitReader reader(payload, payload_size); + std::uint32_t version = reader.read(2); + if (reader.failed()) { + return variant("header_truncated", "OAMD payload cannot hold the 2-bit version"); + } + if (version == 3u) { + version += reader.read(3); + if (reader.failed()) { + return syntax("OAMD version extension truncated"); + } + } + std::uint32_t object_count_bits = reader.read(5); + if (object_count_bits == 0x1Fu) { + object_count_bits += reader.read(7); + } + if (reader.failed()) { + return syntax("OAMD object count truncated"); + } + const std::uint32_t object_count = object_count_bits + 1u; + + ProgramInfo program; + Status status = parse_program_assignment(reader, &program); + if (!status.ok()) { + return status; + } + const std::uint32_t alternate_present = reader.read(1); + if (reader.failed()) { + return syntax("OAMD alternate data flag truncated"); + } + + std::uint32_t element_count = reader.read(4); + if (element_count == 0xFu) { + element_count += reader.read(5); + } + if (reader.failed()) { + return syntax("OAMD element count truncated"); + } + if (element_count == 0u) { + return variant("missing_object_element", "OAMD declares no element"); + } + const std::uint32_t bed_isf_objects = program.num_bed_objects + program.num_isf_objects; + + bool have_object_element = false; + ObjectElementInfo object_element; + for (std::uint32_t ordinal = 0; ordinal < element_count; ++ordinal) { + const std::size_t header_start = reader.position(); + const std::uint32_t element_id = reader.read(4); + std::uint32_t size_field = 0; + if (!variable_bits_max(reader, 4, 4, &size_field)) { + return syntax("OAMD element header truncated at ordinal " + std::to_string(ordinal)); + } + const std::uint32_t size_bytes = size_field + 1u; + const std::size_t region_start = reader.position(); + const std::size_t region_end = region_start + static_cast(size_bytes) * 8u; + if (region_end > reader.limit()) { + return variant("element_bounds", + "element " + std::to_string(ordinal) + " (id " + + std::to_string(element_id) + ") declares " + + std::to_string(size_bytes) + + " bytes, beyond the payload (header at bit " + + std::to_string(header_start) + ")"); + } + if (alternate_present != 0u) { + reader.read(4); + } + reader.read(1); + if (reader.failed()) { + return syntax("OAMD element control fields truncated at ordinal " + + std::to_string(ordinal)); + } + + if (element_id == kObjectElementId) { + if (have_object_element) { + return variant("multiple_object_elements", "OAMD contains several object elements"); + } + have_object_element = true; + const Status parsed = parse_object_element(reader, object_count, bed_isf_objects, + &object_element, out); + if (!parsed.ok()) { + return parsed; + } + if (trace != nullptr) { + trace->parsed_end_bit = static_cast(reader.position()); + } + if (reader.position() < region_end) { + reader.set_limit_bits(reader.limit()); + reader.skip(region_end - reader.position()); + } + } else { + if (!reader.skip(region_end - reader.position())) { + return syntax("OAMD element skip past payload end"); + } + } + if (reader.failed()) { + return syntax("OAMD element parse failed at ordinal " + std::to_string(ordinal)); + } + } + + if (!have_object_element) { + return variant("missing_object_element", "OAMD has no object element"); + } + + // Trailing padding must be zero over the whole remainder. + { + bits::BitReader tail(payload, payload_size); + tail.reset(payload, payload_size, reader.position()); + while (tail.remaining_bits() > 0) { + const std::size_t chunk = + tail.remaining_bits() > 32u ? 32u : tail.remaining_bits(); + if (tail.read(static_cast(chunk)) != 0u) { + return Status::fail(JOC_ERR_BITSTREAM_PADDING, stage::kOamd, + "OAMD payload padding is not zero (from bit " + + std::to_string(reader.position()) + ")"); + } + } + } + + if (version != 0u) { + return variant("oamd_version", + "OAMD syntax version " + std::to_string(version) + " is not covered"); + } + if (object_count > static_cast(kMaxSlots)) { + return variant("object_count", "OAMD object count " + std::to_string(object_count) + + " exceeds the 16-slot model"); + } + if (object_element.block_count != 1u) { + return variant("multiple_position_blocks", + "OAMD frame carries " + std::to_string(object_element.block_count) + + " position blocks; a single frame_update cannot express that"); + } + + out->block_offset_samples = object_element.block_offset_samples; + out->ramp_duration_samples = object_element.ramp_duration_samples; + out->object_count = object_count; + out->dynamic_object_only = program.dynamic_object_only; + out->lfe_present = program.lfe_present; + out->num_bed_objects = program.num_bed_objects; + out->num_isf_objects = program.num_isf_objects; + out->num_dynamic_objects = program.num_dynamic_objects; + + if (trace != nullptr) { + trace->bed_assignments = program.bed_assignments; + trace->element_count = element_count; + trace->object_element_count = have_object_element ? 1u : 0u; + trace->sample_offset_code = object_element.sample_offset_code; + trace->sample_offset = object_element.sample_offset; + trace->block_count = object_element.block_count; + trace->reserved_data_not_present = object_element.reserved_data_not_present; + } + return Status::success(); +} + +} // namespace joc::oamd diff --git a/src/oamd/oamd_parser.h b/src/oamd/oamd_parser.h new file mode 100644 index 0000000..814ad87 --- /dev/null +++ b/src/oamd/oamd_parser.h @@ -0,0 +1,103 @@ +// Port of src/oamd_bits.py. + +#pragma once + +#include +#include +#include + +#include "foundation/status.h" +#include "joc_core.h" + +namespace joc::oamd { + +inline constexpr int kMaxSlots = 16; +inline constexpr int kObjects = 15; +inline constexpr int kAxes = 3; +inline constexpr int kNQ12 = 62; +inline constexpr int kNQ3 = 15; +inline constexpr int kQ15Scale = 32768; + +// (the reference's None), i.e. hold the previous position. +struct SlotUpdate { + std::int16_t q1 = -1; + std::int16_t q2 = -1; + std::int16_t q3 = -1; +}; + +struct OamdUpdate { + SlotUpdate slots[kMaxSlots]; + std::uint32_t block_offset_samples = 0; + std::uint32_t ramp_duration_samples = 0; + std::uint32_t object_count = 0; + bool dynamic_object_only = false; + bool lfe_present = false; + std::uint32_t num_bed_objects = 0; + std::uint32_t num_isf_objects = 0; + std::int32_t num_dynamic_objects = -1; +}; + +class OamdState { +public: + OamdState() { reset(); } + + void reset() { + for (int slot = 0; slot < kMaxSlots; ++slot) { + for (int axis = 0; axis < kAxes; ++axis) { + q_[slot][axis] = 0; + } + } + q_[0][0] = 16384; + q_[0][1] = 16384; + } + + void apply(const OamdUpdate& update) { + for (int slot = 0; slot < kMaxSlots; ++slot) { + const SlotUpdate& value = update.slots[slot]; + if (value.q1 >= 0) { q_[slot][0] = value.q1; } + if (value.q2 >= 0) { q_[slot][1] = value.q2; } + if (value.q3 >= 0) { q_[slot][2] = value.q3; } + } + } + + std::int16_t q(int slot, int axis) const { return q_[slot][axis]; } + + // Objects 1..15 as q15 triples, the layout the speaker renderer consumes. + void object_positions_q15(std::uint16_t out[kObjects][kAxes]) const { + for (int object = 0; object < kObjects; ++object) { + for (int axis = 0; axis < kAxes; ++axis) { + out[object][axis] = static_cast(q_[object + 1][axis]); + } + } + } + +private: + std::int16_t q_[kMaxSlots][kAxes] = {}; +}; + +// q_of(k, n) = min(32767, floor(32768 k / n + 0.5)), the reference's quantiser. +int q_of(int k, int n); + +Status parse_id11(const std::uint8_t* payload, std::size_t payload_size, OamdUpdate* out); + +struct BedAssignment { + bool lfe_only = false; + bool standard = false; + std::uint32_t mask = 0; +}; + +struct ParseTrace { + std::vector bed_assignments; + std::uint32_t element_count = 0; + std::uint32_t object_element_count = 0; + std::uint32_t sample_offset_code = 0; + std::uint32_t sample_offset = 0; + std::uint32_t block_count = 0; + std::uint32_t parsed_end_bit = 0; + bool reserved_data_not_present = false; +}; + +Status parse_id11_verbose(const std::uint8_t* payload, std::size_t payload_size, OamdUpdate* out, + ParseTrace* trace); + +} // namespace joc::oamd diff --git a/src/simd/cpu_probe.cpp b/src/simd/cpu_probe.cpp new file mode 100644 index 0000000..90cec52 --- /dev/null +++ b/src/simd/cpu_probe.cpp @@ -0,0 +1,101 @@ +// CPU feature probe; see cpu_probe.h. +// +// Nothing here is ISA-specific code: the x86 path uses CPUID / XGETBV (MSVC) or +// the compiler's own runtime probe (GCC/Clang, so no inline assembly), and the +// AArch64 path reads the aux vector. That is what lets this unit stay baseline +// and run before the dispatcher has decided anything. + +#include "simd/cpu_probe.h" + +#if defined(_M_X64) +#include +#include +#elif defined(__x86_64__) +#include +#endif + +#if defined(__linux__) && (defined(__aarch64__) || defined(_M_ARM64)) +#include +#endif + +namespace joc::simd { +namespace { + +// ------------------------------------------------------------------- x86-64 -- +#if defined(_M_X64) || defined(__x86_64__) + +#if defined(_M_X64) + +// CPUID tells us what the silicon can do; XCR0 tells us whether the OS saves the +// state the wider registers need. Both have to agree, or the first AVX +// instruction after a context switch corrupts another thread's registers. +CpuFeatures probe_x86() noexcept { + CpuFeatures features; + int regs[4] = {0, 0, 0, 0}; + __cpuid(regs, 0); + const int max_leaf = regs[0]; + __cpuid(regs, 1); + features.sse2 = (regs[3] & (1 << 26)) != 0; + const bool osxsave = (regs[2] & (1 << 27)) != 0; + const bool avx = (regs[2] & (1 << 28)) != 0; + if (!osxsave || !avx || max_leaf < 7) { + return features; + } + const unsigned long long xcr0 = _xgetbv(0); + const bool ymm_state = (xcr0 & 0x06ull) == 0x06ull; // XMM + YMM saved + const bool zmm_state = (xcr0 & 0xe6ull) == 0xe6ull; // + opmask / ZMM / hi16 + if (!ymm_state) { + return features; + } + __cpuidex(regs, 7, 0); + features.avx2 = (regs[1] & (1 << 5)) != 0; + features.avx512 = zmm_state && (regs[1] & (1 << 16)) != 0; // AVX512F + return features; +} + +#else // GCC/Clang on x86-64 + +// The compiler runtime performs the same CPUID + XGETBV probe (libgcc's cpuinfo +// checks XCR0 before it reports AVX), which keeps this file free of inline +// assembly. +CpuFeatures probe_x86() noexcept { + CpuFeatures features; + features.sse2 = __builtin_cpu_supports("sse2") != 0; + features.avx2 = __builtin_cpu_supports("avx2") != 0; + features.avx512 = __builtin_cpu_supports("avx512f") != 0; + return features; +} + +#endif + +CpuFeatures probe() noexcept { return probe_x86(); } + +// ----------------------------------------------------------------- AArch64 -- +#elif defined(__aarch64__) || defined(_M_ARM64) + +CpuFeatures probe() noexcept { + CpuFeatures features; +#if defined(__linux__) + // ASIMD is architectural for AArch64; the aux vector only confirms it. + features.neon = (getauxval(AT_HWCAP) & (1u << 1)) != 0u; +#else + features.neon = true; +#endif + return features; +} + +// ------------------------------------------------------------ anything else -- +#else + +CpuFeatures probe() noexcept { return CpuFeatures{}; } + +#endif + +} // namespace + +const CpuFeatures& cpu_features() noexcept { + static const CpuFeatures features = probe(); + return features; +} + +} // namespace joc::simd diff --git a/src/simd/cpu_probe.h b/src/simd/cpu_probe.h new file mode 100644 index 0000000..68e3002 --- /dev/null +++ b/src/simd/cpu_probe.h @@ -0,0 +1,30 @@ +#pragma once + +// "Can this CPU and this operating system actually execute ISA X?" +// +// Its own unit and free of policy: it reads CPUID / XGETBV / HWCAP, caches the +// answer, and knows nothing about JOC_SIMD, the kernel table or which +// implementation is preferred. This is the one place that can fault the process +// if it is wrong, so it stays small enough to review on its own. +// +// Compiled with the baseline ISA like every other non-intrinsic unit (see +// CMakeLists.txt): it runs before any ISA unit is reached, so it must not execute +// a wide instruction itself. + +namespace joc::simd { + +// One flag per ISA the dispatcher can ask about. A flag means "usable here": +// both the silicon and the OS state-management agree, not merely that CPUID +// advertises the feature. +struct CpuFeatures { + bool sse2 = false; + bool avx2 = false; + bool avx512 = false; + bool neon = false; +}; + +// Probed once, on first use. Never throws and never reads the environment (the +// JOC_SIMD override is the dispatcher's business). +const CpuFeatures& cpu_features() noexcept; + +} // namespace joc::simd diff --git a/src/simd/dispatch.cpp b/src/simd/dispatch.cpp new file mode 100644 index 0000000..5cfa709 --- /dev/null +++ b/src/simd/dispatch.cpp @@ -0,0 +1,293 @@ +// Kernel dispatch: CPU features in, kernel table out. +// +// This file holds policy only -- which ISA is asked for, which ladder is walked, +// which slot ends up with which implementation. The question "can this machine +// run ISA X at all" belongs to cpu_probe.cpp, and the implementations themselves +// belong to the one ISA unit per ISA (kernels_scalar.cpp / kernels_intrin_*.cpp). +// +// JOC_SIMD=auto|scalar|sse2|avx2|avx512|neon. A forced ISA that this build or +// this machine cannot provide is reported on stderr and then ignored -- forcing a +// path the CPU lacks would fault instead of verifying anything. +// +// This unit is compiled with the baseline ISA: it runs before anything else in +// any binary that links the kernels, so it must not execute an ISA-specific +// instruction itself. + +#include "simd/simd.h" + +#include "simd/cpu_probe.h" + +#include +#include +#include + +// Which ISA units the build system put into this binary. An ISA that was not +// compiled in has no entry point to reference at all. +#if !defined(JOC_SIMD_HAVE_SSE2) +#define JOC_SIMD_HAVE_SSE2 0 +#endif +#if !defined(JOC_SIMD_HAVE_AVX2) +#define JOC_SIMD_HAVE_AVX2 0 +#endif +#if !defined(JOC_SIMD_HAVE_AVX512) +#define JOC_SIMD_HAVE_AVX512 0 +#endif +#if !defined(JOC_SIMD_HAVE_NEON) +#define JOC_SIMD_HAVE_NEON 0 +#endif + +namespace joc::simd { + +// Implemented by the per-ISA units; referenced only when compiled in. The file +// name carries the ISA (FLAC's `*_intrin_.c` convention), and the CMake list +// gives exactly those units their wider /arch or -m flag. +const Kernels& kernels_scalar() noexcept; +#if JOC_SIMD_HAVE_AVX2 +const Kernels& kernels_intrin_avx2() noexcept; +#endif +#if JOC_SIMD_HAVE_AVX512 +const Kernels& kernels_intrin_avx512() noexcept; +#endif +#if JOC_SIMD_HAVE_NEON +const Kernels& kernels_intrin_neon() noexcept; +#endif + +namespace { + +constexpr std::size_t kKernelCount = static_cast(Kernel::count); + +// The probe itself lives in cpu_probe.cpp; all this file needs from it is the +// cached answer, turned into the two questions the ladder asks: "was it compiled +// into this binary" (JOC_SIMD_HAVE_*) and "can this machine run it". + +struct Resolution { + Kernels kernels; + Isa active[kKernelCount] = {}; + Isa selected = Isa::scalar; + bool forced = false; +}; + +int isa_rank(Isa isa) noexcept { + switch (isa) { + case Isa::scalar: return 0; + case Isa::sse2: return 1; + case Isa::neon: return 1; + case Isa::avx2: return 2; + case Isa::avx512: return 3; + } + return 0; +} + +bool isa_compiled(Isa isa) noexcept { + switch (isa) { + case Isa::scalar: return true; + // The x86-64 baseline *is* SSE2: the baseline units are compiled for it + // and there is no separate unit, because a 128-bit SSE2 register is + // exactly the register a scalar double already uses -- SSE2 cannot widen + // a double-precision operation, so "sse2" selects the reference kernels. + case Isa::sse2: return JOC_SIMD_HAVE_SSE2 != 0; + case Isa::avx2: return JOC_SIMD_HAVE_AVX2 != 0; + case Isa::avx512: return JOC_SIMD_HAVE_AVX512 != 0; + case Isa::neon: return JOC_SIMD_HAVE_NEON != 0; + } + return false; +} + +const Kernels& kernels_of(Isa isa) noexcept { + switch (isa) { + case Isa::scalar: + case Isa::sse2: return kernels_scalar(); +#if JOC_SIMD_HAVE_AVX2 + case Isa::avx2: return kernels_intrin_avx2(); +#endif +#if JOC_SIMD_HAVE_AVX512 + case Isa::avx512: return kernels_intrin_avx512(); +#endif +#if JOC_SIMD_HAVE_NEON + case Isa::neon: return kernels_intrin_neon(); +#endif + default: break; + } + return kernels_scalar(); +} + +bool parse_isa(const char* text, Isa* out) noexcept { + struct Entry { + const char* name; + Isa isa; + }; + static const Entry kEntries[] = { + {"scalar", Isa::scalar}, {"sse2", Isa::sse2}, {"avx2", Isa::avx2}, + {"avx512", Isa::avx512}, {"neon", Isa::neon}, + }; + for (const Entry& entry : kEntries) { + if (std::strcmp(text, entry.name) == 0) { + *out = entry.isa; + return true; + } + } + return false; +} + +Resolution resolve() noexcept { + Resolution resolution; + Isa best = Isa::scalar; + bool forced = false; + + if (const char* requested = std::getenv("JOC_SIMD"); + requested != nullptr && requested[0] != '\0' && std::strcmp(requested, "auto") != 0) { + Isa wanted = Isa::scalar; + if (!parse_isa(requested, &wanted)) { + std::fprintf(stderr, + "joc: JOC_SIMD=%s is not one of auto|scalar|sse2|avx2|avx512|neon; " + "using auto\n", + requested); + } else if (!isa_compiled(wanted)) { + std::fprintf(stderr, "joc: JOC_SIMD=%s is not part of this build; using auto\n", + requested); + } else if (!isa_supported(wanted)) { + std::fprintf(stderr, "joc: JOC_SIMD=%s is not supported by this CPU or OS; using auto\n", + requested); + } else { + best = wanted; + forced = true; + } + } + + if (!forced) { + // Widest runnable ISA, in descending order. + static const Isa kLadder[] = {Isa::avx512, Isa::avx2, Isa::sse2, Isa::neon}; + for (const Isa candidate : kLadder) { + if (isa_compiled(candidate) && isa_supported(candidate)) { + best = candidate; + break; + } + } + } + resolution.selected = best; + resolution.forced = forced; + + // Per kernel: widest compiled + runnable implementation at or below the + // selected ISA, falling back to the scalar reference, which is always there. + static const Isa kCandidates[] = {Isa::avx512, Isa::avx2, Isa::sse2, Isa::neon, Isa::scalar}; + for (std::size_t index = 0u; index < kKernelCount; ++index) { + const Kernel kernel = static_cast(index); + resolution.active[index] = Isa::scalar; + for (const Isa candidate : kCandidates) { + if (isa_rank(candidate) > isa_rank(best) || !isa_compiled(candidate) + || !isa_supported(candidate)) { + continue; + } + const Kernels& set = kernels_of(candidate); + bool resolved = false; + switch (kernel) { + case Kernel::fft_butterflies: + if (set.fft_butterflies != nullptr) { + resolution.kernels.fft_butterflies = set.fft_butterflies; + resolved = true; + } + break; + case Kernel::qmf_synthesis_basis: + if (set.qmf_synthesis_basis != nullptr) { + resolution.kernels.qmf_synthesis_basis = set.qmf_synthesis_basis; + resolved = true; + } + break; + case Kernel::hybrid_low_join: + if (set.hybrid_low_join != nullptr) { + resolution.kernels.hybrid_low_join = set.hybrid_low_join; + resolved = true; + } + break; + case Kernel::render_hybrid_path: + if (set.render_hybrid_path != nullptr) { + resolution.kernels.render_hybrid_path = set.render_hybrid_path; + resolved = true; + } + break; + case Kernel::complex_axpy: + if (set.complex_axpy != nullptr) { + resolution.kernels.complex_axpy = set.complex_axpy; + resolved = true; + } + break; + case Kernel::qmf_analysis_taps: + if (set.qmf_analysis_taps != nullptr) { + resolution.kernels.qmf_analysis_taps = set.qmf_analysis_taps; + resolved = true; + } + break; + case Kernel::complex_multiply: + if (set.complex_multiply != nullptr) { + resolution.kernels.complex_multiply = set.complex_multiply; + resolved = true; + } + break; + case Kernel::count: break; + } + if (resolved) { + resolution.active[index] = candidate; + break; + } + } + } + + if (std::getenv("JOC_SIMD_LOG") != nullptr) { + std::fprintf(stderr, "joc: simd selected=%s forced=%d\n", isa_name(resolution.selected), + resolution.forced ? 1 : 0); + for (std::size_t index = 0u; index < kKernelCount; ++index) { + std::fprintf(stderr, "joc: simd kernel[%u]=%s\n", static_cast(index), + isa_name(resolution.active[index])); + } + } + return resolution; +} + +const Resolution& resolution() noexcept { + static const Resolution resolved = resolve(); + return resolved; +} + +} // namespace + +const char* isa_name(Isa isa) noexcept { + switch (isa) { + case Isa::scalar: return "scalar"; + case Isa::sse2: return "sse2"; + case Isa::avx2: return "avx2"; + case Isa::avx512: return "avx512"; + case Isa::neon: return "neon"; + } + return "?"; +} + +bool isa_supported(Isa isa) noexcept { + const CpuFeatures& cpu = cpu_features(); + switch (isa) { + case Isa::scalar: + return true; + case Isa::sse2: + return cpu.sse2; + case Isa::avx2: + return cpu.avx2; + case Isa::avx512: + return cpu.avx512; + case Isa::neon: + return cpu.neon; + } + return false; +} + +Isa selected_isa() noexcept { return resolution().selected; } + +Isa active_isa(Kernel kernel) noexcept { + const std::size_t index = static_cast(kernel); + if (index >= kKernelCount) { + return Isa::scalar; + } + return resolution().active[index]; +} + +const Kernels& kernels() noexcept { return resolution().kernels; } + +} // namespace joc::simd diff --git a/src/simd/kernels_intrin_avx2.cpp b/src/simd/kernels_intrin_avx2.cpp new file mode 100644 index 0000000..8934a40 --- /dev/null +++ b/src/simd/kernels_intrin_avx2.cpp @@ -0,0 +1,321 @@ +// AVX2 implementation of the dispatched kernels. Compiled with /arch:AVX2 (or +// -mavx2) and only ever called after the dispatcher has confirmed that this CPU +// and the OS state it saves can execute AVX2 code. +// +// CMake gives exactly the `kernels_intrin_*.cpp` units a wider flag, so no +// baseline unit can inherit one by accident. +// +// Nothing in this file may have dynamic initialisation: it is linked into the +// same image as the baseline code and would run before the dispatcher. + +#include "simd/simd.h" + +#include + +#include + +namespace joc::simd { +namespace { + +// Two interleaved complexes per vector. +// +// The scalar kernel computes, for one butterfly, +// odd.re = o.re * w.re - o.im * w.im +// odd.im = o.re * w.im + o.im * w.re +// with separate multiplies and one rounding per operation. In a 256-bit vector +// the even element of every 128-bit half is a real part, so duplicating the even +// elements of the twiddle broadcasts w.re onto both components of a complex and +// permuting the odd data elements in lines up `o.im`, `o.re` against `w.im`. +// addsub then subtracts on the real lanes and adds on the imaginary ones, which +// is the same two roundings: `o.im * w.re + o.re * w.im` is the scalar's +// `o.re * w.im + o.im * w.re` with the summands exchanged, and floating-point +// addition is commutative. +inline __m256d mul_pair(__m256d odd, __m256d twiddle) noexcept { + const __m256d real = _mm256_mul_pd(odd, _mm256_movedup_pd(twiddle)); + const __m256d cross = _mm256_mul_pd(_mm256_permute_pd(odd, 0x05), _mm256_permute_pd(twiddle, 0x0f)); + return _mm256_addsub_pd(real, cross); +} + +// The radix-2 DIT cascade over a bit-reversed buffer of any power-of-two size at +// or above kMinVectorFftSize. +// +// Stage s pairs element (start + offset) with (start + offset + 2^s) for every +// group of 2^(s+1) elements, and the butterflies of a stage are mutually +// independent: none of them reads a slot another one writes. They are therefore +// free to share a vector, and each one still accumulates nothing -- every output +// is a single add or subtract of two products, in lanes whose operations are +// independent of each other. +// +// Stage 0 is the one case whose group holds a single butterfly, so the pair is +// packed from two neighbouring groups instead: their factors are identical +// (offset is always 0), and a permute2f128 moves the even and odd halves into +// two vector registers. +void fft_butterflies_avx2(double* data, std::size_t size, const double* twiddle, + const std::size_t* stage_begin) noexcept { + { + const auto* pair = reinterpret_cast(twiddle + 2u * stage_begin[0]); + const __m256d factor = _mm256_broadcast_pd(pair); + for (std::size_t index = 0u; index < 2u * size; index += 8u) { + const __m256d low = _mm256_loadu_pd(data + index); + const __m256d high = _mm256_loadu_pd(data + index + 4u); + const __m256d even = _mm256_permute2f128_pd(low, high, 0x20); + const __m256d odd = _mm256_permute2f128_pd(low, high, 0x31); + const __m256d rotated = mul_pair(odd, factor); + const __m256d sum = _mm256_add_pd(even, rotated); + const __m256d difference = _mm256_sub_pd(even, rotated); + _mm256_storeu_pd(data + index, _mm256_permute2f128_pd(sum, difference, 0x20)); + _mm256_storeu_pd(data + index + 4u, _mm256_permute2f128_pd(sum, difference, 0x31)); + } + } + + std::size_t stage = 1u; + for (std::size_t half = 2u; half < size; half <<= 1u, ++stage) { + const std::size_t length = half << 1u; + const double* table = twiddle + 2u * stage_begin[stage]; + for (std::size_t start = 0u; start < size; start += length) { + for (std::size_t offset = 0u; offset < half; offset += 2u) { + const std::size_t even_index = (start + offset) * 2u; + const std::size_t odd_index = even_index + half * 2u; + const std::size_t factor_index = offset * 2u; + const __m256d even = _mm256_loadu_pd(data + even_index); + const __m256d odd = _mm256_loadu_pd(data + odd_index); + const __m256d factor = _mm256_loadu_pd(table + factor_index); + const __m256d rotated = mul_pair(odd, factor); + _mm256_storeu_pd(data + even_index, _mm256_add_pd(even, rotated)); + _mm256_storeu_pd(data + odd_index, _mm256_sub_pd(even, rotated)); + } + } + } +} + +// QMF synthesis basis, four ranks of one band per vector. +// +// The four ranks are four dot products over the same 128 taps, so they are four +// independent accumulators and nothing has to be reassociated to fill a vector. +// Each lane performs exactly the caller's `sum += values[tap] * weight`, in tap +// order, with a separate multiply and add, and the rank-minor table makes the +// four weights one contiguous load. +// +// A band's chain is 128 dependent adds, so the loop is latency-bound long before +// it is throughput-bound; the cure is more independent chains, not a shorter +// chain (that would reassociate). `Rows` output rows share one weight load and +// run their chains side by side -- the caller's rows are consecutive output +// channels, which do read the same weights. +template +void synthesize_rows(const double* values, const double* basis, double* out) noexcept { + constexpr std::size_t kRanks = kSynthesisRanks; + constexpr std::size_t kTaps = kSynthesisTaps; + constexpr std::size_t kRowOut = kSynthesisBands * kRanks; + for (std::size_t band = 0u; band < kSynthesisBands; ++band) { + const double* table = basis + band * kTaps * kRanks; + __m256d sum[Rows]; + for (int row = 0; row < Rows; ++row) { + sum[row] = _mm256_setzero_pd(); + } + for (std::size_t tap = 0u; tap < kTaps; ++tap) { + const __m256d weight = _mm256_loadu_pd(table + tap * kRanks); + for (int row = 0; row < Rows; ++row) { + sum[row] = _mm256_add_pd( + sum[row], + _mm256_mul_pd(_mm256_broadcast_sd(values + row * kTaps + tap), weight)); + } + } + for (int row = 0; row < Rows; ++row) { + _mm256_storeu_pd(out + row * kRowOut + band * kRanks, sum[row]); + } + } +} + +void qmf_synthesis_basis_avx2(const double* values, const double* basis, double* out, + std::size_t rows) noexcept { + constexpr std::size_t kTaps = kSynthesisTaps; + constexpr std::size_t kRowOut = kSynthesisBands * kSynthesisRanks; + std::size_t row = 0u; + for (; row + 4u <= rows; row += 4u) { + synthesize_rows<4>(values + row * kTaps, basis, out + row * kRowOut); + } + for (; row < rows; ++row) { + synthesize_rows<1>(values + row * kTaps, basis, out + row * kRowOut); + } +} + +// Hybrid analysis low join, one term against all 32 outputs. +// +// The 32 outputs of a row are independent accumulations over the same 78 terms, +// so they are what fills the four vectors: one broadcast of the term's value, +// then a multiply and an add per vector. Every lane keeps the term order and the +// two roundings of the caller's `out += value * weight`. Terms that are exactly +// zero are skipped, which is what the caller does and what leaves its sums +// unchanged (a lane's running sum is never a negative zero). +void hybrid_low_join_avx2(const double* values, const double* kernel, double* out, + std::size_t rows) noexcept { + constexpr std::size_t kTerms = kHybridTerms; + constexpr std::size_t kOutputs = kHybridOutputs; + static_assert(kOutputs == 32u, "eight 256-bit accumulators cover one row's outputs"); + for (std::size_t row = 0u; row < rows; ++row) { + const double* source = values + row * kTerms; + double* destination = out + row * kOutputs; + __m256d sum0 = _mm256_setzero_pd(); + __m256d sum1 = _mm256_setzero_pd(); + __m256d sum2 = _mm256_setzero_pd(); + __m256d sum3 = _mm256_setzero_pd(); + __m256d sum4 = _mm256_setzero_pd(); + __m256d sum5 = _mm256_setzero_pd(); + __m256d sum6 = _mm256_setzero_pd(); + __m256d sum7 = _mm256_setzero_pd(); + for (std::size_t term = 0u; term < kTerms; ++term) { + const double value = source[term]; + if (value == 0.0) { + continue; + } + const double* weights = kernel + term * kOutputs; + const __m256d factor = _mm256_broadcast_sd(&value); + sum0 = _mm256_add_pd(sum0, _mm256_mul_pd(factor, _mm256_loadu_pd(weights))); + sum1 = _mm256_add_pd(sum1, _mm256_mul_pd(factor, _mm256_loadu_pd(weights + 4u))); + sum2 = _mm256_add_pd(sum2, _mm256_mul_pd(factor, _mm256_loadu_pd(weights + 8u))); + sum3 = _mm256_add_pd(sum3, _mm256_mul_pd(factor, _mm256_loadu_pd(weights + 12u))); + sum4 = _mm256_add_pd(sum4, _mm256_mul_pd(factor, _mm256_loadu_pd(weights + 16u))); + sum5 = _mm256_add_pd(sum5, _mm256_mul_pd(factor, _mm256_loadu_pd(weights + 20u))); + sum6 = _mm256_add_pd(sum6, _mm256_mul_pd(factor, _mm256_loadu_pd(weights + 24u))); + sum7 = _mm256_add_pd(sum7, _mm256_mul_pd(factor, _mm256_loadu_pd(weights + 28u))); + } + _mm256_storeu_pd(destination, sum0); + _mm256_storeu_pd(destination + 4u, sum1); + _mm256_storeu_pd(destination + 8u, sum2); + _mm256_storeu_pd(destination + 12u, sum3); + _mm256_storeu_pd(destination + 16u, sum4); + _mm256_storeu_pd(destination + 20u, sum5); + _mm256_storeu_pd(destination + 24u, sum6); + _mm256_storeu_pd(destination + 28u, sum7); + } +} + +// One rendered path, two bands per vector. +// +// A band's real and imaginary parts are adjacent, so a vector holds two whole +// bands and the cross terms are one swap away -- the same shape the FFT kernel +// uses. Two products are needed per component here (`h * t` and `h * swapped(t)`), +// each scaled on its own, and the real part is their difference while the +// imaginary part is their sum: addsub produces both pairings and a blend keeps +// one lane of each. Bands are independent accumulations into independent +// outputs, so this is still nothing but cross-band parallelism. +void render_hybrid_path_avx2(double* out, const double* transfer, const double* history0, + const double* history1, double scale) noexcept { + const __m256d factor = _mm256_set1_pd(scale); + const double* histories[2] = {history0, history1}; + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const double* source = histories[ear]; + const double* taps = transfer + ear * kPathBands * 2u; + double* destination = out + ear * kPathBands * 2u; + std::size_t band = 0u; + for (; band + 2u <= kPathBands; band += 2u) { + const __m256d history = _mm256_loadu_pd(source + band * 2u); + const __m256d tap = _mm256_loadu_pd(taps + band * 2u); + const __m256d product = _mm256_mul_pd(_mm256_mul_pd(history, tap), factor); + const __m256d crossed = _mm256_mul_pd( + _mm256_mul_pd(history, _mm256_permute_pd(tap, 0x05)), factor); + const __m256d difference = + _mm256_addsub_pd(product, _mm256_permute_pd(product, 0x05)); + const __m256d sum = _mm256_add_pd(crossed, _mm256_permute_pd(crossed, 0x05)); + // `difference` carries the real parts in lanes 0 and 2, `sum` the + // imaginary ones in lanes 1 and 3 (four elements, so the blend takes a + // four-bit selector). + const __m256d result = _mm256_blend_pd(difference, sum, 0xa); + _mm256_storeu_pd(destination + band * 2u, + _mm256_add_pd(_mm256_loadu_pd(destination + band * 2u), result)); + } + for (; band < kPathBands; ++band) { + const double source_real = source[band * 2u]; + const double source_imag = source[band * 2u + 1u]; + const double tap_real = taps[band * 2u]; + const double tap_imag = taps[band * 2u + 1u]; + destination[band * 2u] += + source_real * tap_real * scale - source_imag * tap_imag * scale; + destination[band * 2u + 1u] += + source_real * tap_imag * scale + source_imag * tap_real * scale; + } + } +} + +// Scalar times a run of interleaved complexes, accumulated in place. The elements +// are independent, so two complexes (one 256-bit vector) go together and each +// component keeps the caller's own multiply-then-add. +void complex_axpy_avx2(double* out, const double* field, double scale, + std::size_t count) noexcept { + const __m256d factor = _mm256_set1_pd(scale); + std::size_t index = 0u; + for (; index + 2u <= count; index += 2u) { + const std::size_t offset = index * 2u; + _mm256_storeu_pd(out + offset, + _mm256_add_pd(_mm256_loadu_pd(out + offset), + _mm256_mul_pd(_mm256_loadu_pd(field + offset), factor))); + } + for (; index < count; ++index) { + out[index * 2u] += field[index * 2u] * scale; + out[index * 2u + 1u] += field[index * 2u + 1u] * scale; + } +} + +// QMF analysis polyphase accumulate: the 64 bands of a row are 64 independent +// accumulations of one product each, and the coefficient row is reused by every +// row, so the rows stream past a first-level-cache-resident set of coefficients. +void qmf_analysis_taps_avx2(double* out, const double* source, const double* coefficients, + std::size_t rows) noexcept { + for (std::size_t row = 0u; row < rows; ++row) { + double* destination = out + row * kQmfAnalysisBands; + const double* values = source + row * kQmfAnalysisBands; + for (std::size_t band = 0u; band < kQmfAnalysisBands; band += 4u) { + _mm256_storeu_pd(destination + band, + _mm256_add_pd(_mm256_loadu_pd(destination + band), + _mm256_mul_pd(_mm256_loadu_pd(values + band), + _mm256_loadu_pd(coefficients + band)))); + } + } +} + +// Element-wise complex product of two runs, two complexes per vector. Both +// operands take part in every lane, so both products of the scalar formula are +// formed and addsub pairs the real difference with the imaginary sum: the same +// four multiplies and the same two roundings per component as `a * b`. +void complex_multiply_avx2(double* out, const double* left, const double* right, + std::size_t count) noexcept { + std::size_t index = 0u; + for (; index + 2u <= count; index += 2u) { + const std::size_t offset = index * 2u; + const __m256d first = _mm256_loadu_pd(left + offset); + const __m256d second = _mm256_loadu_pd(right + offset); + // (re*re, im*im) and (im*re, re*im): the first gives the real difference, + // the second the imaginary sum. + const __m256d product = _mm256_mul_pd(first, second); + const __m256d crossed = _mm256_mul_pd(_mm256_permute_pd(first, 0x05), second); + const __m256d difference = + _mm256_addsub_pd(product, _mm256_permute_pd(product, 0x05)); + const __m256d total = _mm256_add_pd(crossed, _mm256_permute_pd(crossed, 0x05)); + _mm256_storeu_pd(out + offset, _mm256_blend_pd(difference, total, 0xa)); + } + for (; index < count; ++index) { + const std::size_t offset = index * 2u; + const double left_real = left[offset]; + const double left_imag = left[offset + 1u]; + const double right_real = right[offset]; + const double right_imag = right[offset + 1u]; + out[offset] = left_real * right_real - left_imag * right_imag; + out[offset + 1u] = left_real * right_imag + left_imag * right_real; + } +} + +const Kernels kAvx2{ + &fft_butterflies_avx2, + &qmf_synthesis_basis_avx2, + &hybrid_low_join_avx2, + &render_hybrid_path_avx2, + &complex_axpy_avx2, + &qmf_analysis_taps_avx2, + &complex_multiply_avx2, +}; + +} // namespace + +const Kernels& kernels_intrin_avx2() noexcept { return kAvx2; } + +} // namespace joc::simd diff --git a/src/simd/kernels_intrin_avx512.cpp b/src/simd/kernels_intrin_avx512.cpp new file mode 100644 index 0000000..c40f351 --- /dev/null +++ b/src/simd/kernels_intrin_avx512.cpp @@ -0,0 +1,272 @@ +// AVX-512F implementation of the dispatched kernels. Compiled with /arch:AVX512 +// (or -mavx512f) and only ever called after the dispatcher has confirmed AVX-512F +// *and* that the OS saves the opmask/ZMM state. +// +// CMake gives exactly the `kernels_intrin_*.cpp` units a wider flag, so no +// baseline unit can inherit one by accident. +// +// Nothing in this file may have dynamic initialisation: it is linked into the +// same image as the baseline code and would run before the dispatcher. + +#include "simd/simd.h" + +#include + +#include + +namespace joc::simd { +namespace { + +// Four interleaved complexes per vector: a 512-bit register is four 128-bit +// lanes, each holding one (re, im) pair, so the AVX2 argument applies one lane +// wider -- movedup/permute broadcast the twiddle components inside every lane. +// AVX-512 never widened VADDSUBPD to 512 bits, so the real lanes take the +// difference and the imaginary ones the sum through merge masking: that is still +// one exact subtract and one exact add per output, with the same two roundings +// per component and no reassociation. +inline __m512d mul_quad(__m512d odd, __m512d twiddle) noexcept { + const __m512d real = _mm512_mul_pd(odd, _mm512_movedup_pd(twiddle)); + const __m512d cross = + _mm512_mul_pd(_mm512_permute_pd(odd, 0x55), _mm512_permute_pd(twiddle, 0xff)); + const __m512d upper = _mm512_mask_add_pd(real, 0xaa, real, cross); + return _mm512_mask_sub_pd(upper, 0x55, real, cross); +} + +// Stages 0 and 1 hold fewer than four complexes in a group, so their butterflies +// are packed from neighbouring groups instead; the factor depends only on the +// offset inside a group, so one broadcast serves every packed lane. +// +// VSHUFF64X2 takes a two-bit selector per output lane, but its first two output +// lanes can only name lanes of its first operand and its last two only lanes of +// its second (verified against the instruction). These are the immediates the +// packings need, written as the four lane selections they spell out. +constexpr int kHalvesEven = 0x88; // (low.l0, low.l2, high.l0, high.l2) = x0,x2,x4,x6 +constexpr int kHalvesOdd = 0xdd; // (low.l1, low.l3, high.l1, high.l3) = x1,x3,x5,x7 +constexpr int kGroupsEven = 0x44; // (low.l0, low.l1, high.l0, high.l1) +constexpr int kGroupsOdd = 0xee; // (low.l2, low.l3, high.l2, high.l3) +constexpr int kSwapMiddle = 0xd8; // (a.l0, a.l2, a.l1, a.l3) + +void pack_halves(double* buffer, __m512d factor) noexcept { + const __m512d low = _mm512_loadu_pd(buffer); + const __m512d high = _mm512_loadu_pd(buffer + 8u); + const __m512d even = _mm512_shuffle_f64x2(low, high, kHalvesEven); + const __m512d odd = _mm512_shuffle_f64x2(low, high, kHalvesOdd); + const __m512d rotated = mul_quad(odd, factor); + const __m512d sum = _mm512_add_pd(even, rotated); + const __m512d difference = _mm512_sub_pd(even, rotated); + // `sum` holds the results for the even positions of the four packed groups and + // `difference` those for the odd ones, and the buffer wants them interleaved + // again. One shuffle cannot do that, so each store pairs the two halves and + // then swaps the two middle lanes of the pair. + const __m512d pairs_low = _mm512_shuffle_f64x2(sum, difference, kGroupsEven); + const __m512d pairs_high = _mm512_shuffle_f64x2(sum, difference, kGroupsOdd); + _mm512_storeu_pd(buffer, _mm512_shuffle_f64x2(pairs_low, pairs_low, kSwapMiddle)); + _mm512_storeu_pd(buffer + 8u, _mm512_shuffle_f64x2(pairs_high, pairs_high, kSwapMiddle)); +} + +void pack_groups(double* buffer, __m512d factor) noexcept { + const __m512d low = _mm512_loadu_pd(buffer); + const __m512d high = _mm512_loadu_pd(buffer + 8u); + const __m512d even = _mm512_shuffle_f64x2(low, high, kGroupsEven); + const __m512d odd = _mm512_shuffle_f64x2(low, high, kGroupsOdd); + const __m512d rotated = mul_quad(odd, factor); + const __m512d sum = _mm512_add_pd(even, rotated); + const __m512d difference = _mm512_sub_pd(even, rotated); + _mm512_storeu_pd(buffer, _mm512_shuffle_f64x2(sum, difference, kGroupsEven)); + _mm512_storeu_pd(buffer + 8u, _mm512_shuffle_f64x2(sum, difference, kGroupsOdd)); +} + +void fft_butterflies_avx512(double* buffer, std::size_t size, const double* twiddle, + const std::size_t* stage_begin) noexcept { + // Stage 0: length 2, one butterfly per group, one factor for all of them. + { + const __m128d pair = _mm_loadu_pd(twiddle + 2u * stage_begin[0]); + const __m512d factor = _mm512_broadcast_f64x4(_mm256_broadcast_pd(&pair)); + for (std::size_t index = 0u; index < 2u * size; index += 16u) { + pack_halves(buffer + index, factor); + } + } + + // Stage 1: length 4, two butterflies per group and two factors. + { + const __m512d factor = + _mm512_broadcast_f64x4(_mm256_loadu_pd(twiddle + 2u * stage_begin[1])); + for (std::size_t index = 0u; index < 2u * size; index += 16u) { + pack_groups(buffer + index, factor); + } + } + + std::size_t stage = 2u; + for (std::size_t half = 4u; half < size; half <<= 1u, ++stage) { + const std::size_t length = half << 1u; + const double* table = twiddle + 2u * stage_begin[stage]; + for (std::size_t start = 0u; start < size; start += length) { + for (std::size_t offset = 0u; offset < half; offset += 4u) { + const std::size_t even_index = (start + offset) * 2u; + const std::size_t odd_index = even_index + half * 2u; + const std::size_t factor_index = offset * 2u; + const __m512d even = _mm512_loadu_pd(buffer + even_index); + const __m512d odd = _mm512_loadu_pd(buffer + odd_index); + const __m512d factor = _mm512_loadu_pd(table + factor_index); + const __m512d rotated = mul_quad(odd, factor); + _mm512_storeu_pd(buffer + even_index, _mm512_add_pd(even, rotated)); + _mm512_storeu_pd(buffer + odd_index, _mm512_sub_pd(even, rotated)); + } + } + } +} + +// Scalar times a run of interleaved complexes: four complexes (eight doubles) per +// vector, every element an independent accumulation. +void complex_axpy_avx512(double* out, const double* field, double scale, + std::size_t count) noexcept { + const __m512d factor = _mm512_set1_pd(scale); + std::size_t index = 0u; + for (; index + 4u <= count; index += 4u) { + const std::size_t offset = index * 2u; + _mm512_storeu_pd(out + offset, + _mm512_add_pd(_mm512_loadu_pd(out + offset), + _mm512_mul_pd(_mm512_loadu_pd(field + offset), factor))); + } + for (; index < count; ++index) { + out[index * 2u] += field[index * 2u] * scale; + out[index * 2u + 1u] += field[index * 2u + 1u] * scale; + } +} + +// QMF analysis polyphase accumulate, eight bands per vector. +void qmf_analysis_taps_avx512(double* out, const double* source, const double* coefficients, + std::size_t rows) noexcept { + for (std::size_t row = 0u; row < rows; ++row) { + double* destination = out + row * kQmfAnalysisBands; + const double* values = source + row * kQmfAnalysisBands; + for (std::size_t band = 0u; band < kQmfAnalysisBands; band += 8u) { + _mm512_storeu_pd(destination + band, + _mm512_add_pd(_mm512_loadu_pd(destination + band), + _mm512_mul_pd(_mm512_loadu_pd(values + band), + _mm512_loadu_pd(coefficients + band)))); + } + } +} + +// Hybrid analysis low join: 32 outputs are exactly four 512-bit vectors, so one +// broadcast of the term's value feeds four multiplies and four adds. +void hybrid_low_join_avx512(const double* values, const double* kernel, double* out, + std::size_t rows) noexcept { + constexpr std::size_t kTerms = kHybridTerms; + constexpr std::size_t kOutputs = kHybridOutputs; + static_assert(kOutputs == 32u, "four 512-bit accumulators cover one row"); + for (std::size_t row = 0u; row < rows; ++row) { + const double* source = values + row * kTerms; + double* destination = out + row * kOutputs; + __m512d sum0 = _mm512_setzero_pd(); + __m512d sum1 = _mm512_setzero_pd(); + __m512d sum2 = _mm512_setzero_pd(); + __m512d sum3 = _mm512_setzero_pd(); + for (std::size_t term = 0u; term < kTerms; ++term) { + const double value = source[term]; + if (value == 0.0) { + continue; + } + const double* weights = kernel + term * kOutputs; + const __m512d factor = _mm512_set1_pd(value); + sum0 = _mm512_add_pd(sum0, _mm512_mul_pd(factor, _mm512_loadu_pd(weights))); + sum1 = _mm512_add_pd(sum1, _mm512_mul_pd(factor, _mm512_loadu_pd(weights + 8u))); + sum2 = _mm512_add_pd(sum2, _mm512_mul_pd(factor, _mm512_loadu_pd(weights + 16u))); + sum3 = _mm512_add_pd(sum3, _mm512_mul_pd(factor, _mm512_loadu_pd(weights + 24u))); + } + _mm512_storeu_pd(destination, sum0); + _mm512_storeu_pd(destination + 8u, sum1); + _mm512_storeu_pd(destination + 16u, sum2); + _mm512_storeu_pd(destination + 24u, sum3); + } +} + +// One rendered path, four bands per vector. AVX-512 has no 512-bit addsub, so the +// two pairings are built with merge masking -- still one exact subtract and one +// exact add per output, and the same separate scale multiply per product. +void render_hybrid_path_avx512(double* out, const double* transfer, const double* history0, + const double* history1, double scale) noexcept { + const __m512d factor = _mm512_set1_pd(scale); + const double* histories[2] = {history0, history1}; + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const double* source = histories[ear]; + const double* taps = transfer + ear * kPathBands * 2u; + double* destination = out + ear * kPathBands * 2u; + std::size_t band = 0u; + for (; band + 4u <= kPathBands; band += 4u) { + const __m512d history = _mm512_loadu_pd(source + band * 2u); + const __m512d tap = _mm512_loadu_pd(taps + band * 2u); + const __m512d product = _mm512_mul_pd( + _mm512_mul_pd(history, tap), factor); + const __m512d crossed = _mm512_mul_pd( + _mm512_mul_pd(history, _mm512_permute_pd(tap, 0x55)), factor); + const __m512d swapped_product = _mm512_permute_pd(product, 0x55); + const __m512d swapped_crossed = _mm512_permute_pd(crossed, 0x55); + // The real component is the difference of the two products and sits in + // the even element of each complex, the imaginary one is the sum of the + // crossed pair and sits in the odd element -- so the subtract is masked + // to the even lanes and the blend keeps the sum on the odd ones. + const __m512d difference = + _mm512_mask_sub_pd(product, 0x55, product, swapped_product); + const __m512d total = _mm512_add_pd(crossed, swapped_crossed); + const __m512d result = _mm512_mask_blend_pd(0xaa, difference, total); + _mm512_storeu_pd(destination + band * 2u, + _mm512_add_pd(_mm512_loadu_pd(destination + band * 2u), result)); + } + for (; band < kPathBands; ++band) { + const double source_real = source[band * 2u]; + const double source_imag = source[band * 2u + 1u]; + const double tap_real = taps[band * 2u]; + const double tap_imag = taps[band * 2u + 1u]; + destination[band * 2u] += + source_real * tap_real * scale - source_imag * tap_imag * scale; + destination[band * 2u + 1u] += + source_real * tap_imag * scale + source_imag * tap_real * scale; + } + } +} + +// Element-wise complex product, four complexes per vector. AVX-512 has no 512-bit +// addsub, so the real difference is masked into the even lanes and the imaginary +// sum into the odd ones. +void complex_multiply_avx512(double* out, const double* left, const double* right, + std::size_t count) noexcept { + std::size_t index = 0u; + for (; index + 4u <= count; index += 4u) { + const std::size_t offset = index * 2u; + const __m512d first = _mm512_loadu_pd(left + offset); + const __m512d second = _mm512_loadu_pd(right + offset); + const __m512d product = _mm512_mul_pd(first, second); + const __m512d crossed = _mm512_mul_pd(_mm512_permute_pd(first, 0x55), second); + const __m512d difference = + _mm512_mask_sub_pd(product, 0x55, product, _mm512_permute_pd(product, 0x55)); + const __m512d total = _mm512_add_pd(crossed, _mm512_permute_pd(crossed, 0x55)); + _mm512_storeu_pd(out + offset, _mm512_mask_blend_pd(0xaa, difference, total)); + } + for (; index < count; ++index) { + const std::size_t offset = index * 2u; + const double left_real = left[offset]; + const double left_imag = left[offset + 1u]; + const double right_real = right[offset]; + const double right_imag = right[offset + 1u]; + out[offset] = left_real * right_real - left_imag * right_imag; + out[offset + 1u] = left_real * right_imag + left_imag * right_real; + } +} + +const Kernels kAvx512{ + &fft_butterflies_avx512, + nullptr, // qmf_synthesis_basis: four ranks do not fill a 512-bit vector + &hybrid_low_join_avx512, + &render_hybrid_path_avx512, + &complex_axpy_avx512, + &qmf_analysis_taps_avx512, + &complex_multiply_avx512, +}; + +} // namespace + +const Kernels& kernels_intrin_avx512() noexcept { return kAvx512; } + +} // namespace joc::simd diff --git a/src/simd/kernels_intrin_neon.cpp b/src/simd/kernels_intrin_neon.cpp new file mode 100644 index 0000000..a523901 --- /dev/null +++ b/src/simd/kernels_intrin_neon.cpp @@ -0,0 +1,311 @@ +// AArch64 NEON (ASIMD) implementation of the dispatched kernels. +// +// CMake gives exactly the `kernels_intrin_*.cpp` units their ISA flag, so no +// baseline unit can inherit one by accident. +// +// Unlike the x86 units this one needs no feature probe -- ASIMD is architectural +// for AArch64 -- but it is still only reached through the dispatcher, so +// JOC_SIMD=scalar, sse2 or neon all stay available on the same binary. +// +// A NEON register holds two doubles, so a vector carries two lanes where an AVX2 +// vector carries four. The lanes are the same independent work items as in the +// AVX2 unit, and each lane performs exactly the scalar reference's operations in +// the scalar reference's order: separate multiplies and adds, never a fused +// multiply-add, and never a reassociated sum. +// +// Nothing in this file may have dynamic initialisation (it is linked into the +// same image as the baseline code and would run before the dispatcher). +// +// NOTE: the unit tests do not exercise this unit. It is built by the AArch64 CI +// job, and its bit-exactness is argued from the shared kernel contract (simd.h) +// rather than measured here. + +#include "simd/simd.h" + +#include + +#include + +#include "foundation/fft.h" + +namespace joc::simd { +namespace { + +constexpr std::size_t kFftSize = dsp::kQmfFftSize; +static_assert(kFftSize == 128u, "the QMF transform is the 128-point case"); + +// ------------------------------------------------------------ radix-2 FFT ---- +// +// Two butterflies per iteration, held as separate real/imaginary vectors: vld2q +// loads two interleaved complexes and deinterleaves them, vst2q puts them back. +// `sum = even + odd * w` and `difference = even - odd * w` are then two add/sub +// pairs, and the complex product is four multiplies and two add/subs, which is +// what the scalar kernel writes. +inline float64x2x2_t complex_mul(float64x2_t odd_real, float64x2_t odd_imag, + float64x2_t weight_real, float64x2_t weight_imag) { + float64x2x2_t result; + result.val[0] = vsubq_f64(vmulq_f64(odd_real, weight_real), vmulq_f64(odd_imag, weight_imag)); + result.val[1] = vaddq_f64(vmulq_f64(odd_real, weight_imag), vmulq_f64(odd_imag, weight_real)); + return result; +} + +// Stages 0 and 1 hold fewer than two complexes per group, so their butterflies are +// packed from neighbouring groups; the factor depends only on the offset inside a +// group, so the two lanes share it. +void fft_butterflies_neon(double* buffer, std::size_t size, const double* twiddle, + const std::size_t* stage_begin) noexcept { + // Stage 0: length 2, one butterfly per group. The two lanes take the two + // halves of two neighbouring groups, which the transposes select. + { + const double* table = twiddle + 2u * stage_begin[0]; + const float64x2_t weight_real = vdupq_n_f64(table[0]); + const float64x2_t weight_imag = vdupq_n_f64(table[1]); + for (std::size_t index = 0u; index < 2u * size; index += 8u) { + const float64x2_t first = vld1q_f64(buffer + index); + const float64x2_t second = vld1q_f64(buffer + index + 2u); + const float64x2_t third = vld1q_f64(buffer + index + 4u); + const float64x2_t fourth = vld1q_f64(buffer + index + 6u); + const float64x2_t even_real = vtrn1q_f64(first, third); + const float64x2_t even_imag = vtrn2q_f64(first, third); + const float64x2_t odd_real = vtrn1q_f64(second, fourth); + const float64x2_t odd_imag = vtrn2q_f64(second, fourth); + const float64x2x2_t rotated = + complex_mul(odd_real, odd_imag, weight_real, weight_imag); + const float64x2_t sum_real = vaddq_f64(even_real, rotated.val[0]); + const float64x2_t sum_imag = vaddq_f64(even_imag, rotated.val[1]); + const float64x2_t difference_real = vsubq_f64(even_real, rotated.val[0]); + const float64x2_t difference_imag = vsubq_f64(even_imag, rotated.val[1]); + // sum.* are the two groups' even-position results and difference.* their + // odd-position ones; a transpose of the two component vectors puts each + // complex back together, in the order the groups appear. + vst1q_f64(buffer + index, vtrn1q_f64(sum_real, sum_imag)); + vst1q_f64(buffer + index + 2u, vtrn1q_f64(difference_real, difference_imag)); + vst1q_f64(buffer + index + 4u, vtrn2q_f64(sum_real, sum_imag)); + vst1q_f64(buffer + index + 6u, vtrn2q_f64(difference_real, difference_imag)); + } + } + + std::size_t stage = 1u; + for (std::size_t half = 2u; half < size; half <<= 1u, ++stage) { + const std::size_t length = half << 1u; + const double* table = twiddle + 2u * stage_begin[stage]; + for (std::size_t start = 0u; start < size; start += length) { + for (std::size_t offset = 0u; offset < half; offset += 2u) { + double* even_values = buffer + (start + offset) * 2u; + double* odd_values = even_values + half * 2u; + const float64x2x2_t even = vld2q_f64(even_values); + const float64x2x2_t odd = vld2q_f64(odd_values); + const float64x2x2_t weight = vld2q_f64(table + offset * 2u); + const float64x2x2_t rotated = + complex_mul(odd.val[0], odd.val[1], weight.val[0], weight.val[1]); + float64x2x2_t sum; + float64x2x2_t difference; + sum.val[0] = vaddq_f64(even.val[0], rotated.val[0]); + sum.val[1] = vaddq_f64(even.val[1], rotated.val[1]); + difference.val[0] = vsubq_f64(even.val[0], rotated.val[0]); + difference.val[1] = vsubq_f64(even.val[1], rotated.val[1]); + vst2q_f64(even_values, sum); + vst2q_f64(odd_values, difference); + } + } + } +} + +// --------------------------------------------------- QMF synthesis basis ----- +// +// The four ranks of a band are four independent dot products over the same row, so +// two registers carry four lanes. `Rows` rows run side by side because a band's +// chain is 128 dependent adds: the cure is more independent chains, not a shorter +// chain. +template +void synthesize_rows_neon(const double* values, const double* basis, double* out) noexcept { + constexpr std::size_t kRanks = kSynthesisRanks; + constexpr std::size_t kTaps = kSynthesisTaps; + constexpr std::size_t kRowOut = kSynthesisBands * kRanks; + for (std::size_t band = 0u; band < kSynthesisBands; ++band) { + const double* table = basis + band * kTaps * kRanks; + float64x2_t low[Rows]; + float64x2_t high[Rows]; + for (int row = 0; row < Rows; ++row) { + low[row] = vdupq_n_f64(0.0); + high[row] = vdupq_n_f64(0.0); + } + for (std::size_t tap = 0u; tap < kTaps; ++tap) { + const float64x2_t weight_low = vld1q_f64(table + tap * kRanks); + const float64x2_t weight_high = vld1q_f64(table + tap * kRanks + 2u); + for (int row = 0; row < Rows; ++row) { + const float64x2_t factor = vdupq_n_f64(values[row * kTaps + tap]); + low[row] = vaddq_f64(low[row], vmulq_f64(factor, weight_low)); + high[row] = vaddq_f64(high[row], vmulq_f64(factor, weight_high)); + } + } + for (int row = 0; row < Rows; ++row) { + vst1q_f64(out + row * kRowOut + band * kRanks, low[row]); + vst1q_f64(out + row * kRowOut + band * kRanks + 2u, high[row]); + } + } +} + +void qmf_synthesis_basis_neon(const double* values, const double* basis, double* out, + std::size_t rows) noexcept { + constexpr std::size_t kTaps = kSynthesisTaps; + constexpr std::size_t kRowOut = kSynthesisBands * kSynthesisRanks; + std::size_t row = 0u; + for (; row + 4u <= rows; row += 4u) { + synthesize_rows_neon<4>(values + row * kTaps, basis, out + row * kRowOut); + } + for (; row < rows; ++row) { + synthesize_rows_neon<1>(values + row * kTaps, basis, out + row * kRowOut); + } +} + +// ------------------------------------------------------ Hybrid low join ----- +// +// One term against all 32 outputs, two outputs per register: the outputs are +// independent accumulations over the same terms, which is what the lanes carry. +void hybrid_low_join_neon(const double* values, const double* kernel, double* out, + std::size_t rows) noexcept { + constexpr std::size_t kTerms = kHybridTerms; + constexpr std::size_t kOutputs = kHybridOutputs; + static_assert(kOutputs == 32u, "sixteen 128-bit accumulators cover one row"); + for (std::size_t row = 0u; row < rows; ++row) { + const double* source = values + row * kTerms; + double* destination = out + row * kOutputs; + float64x2_t partial[16]; + for (int chunk = 0; chunk < 16; ++chunk) { + partial[chunk] = vdupq_n_f64(0.0); + } + for (std::size_t term = 0u; term < kTerms; ++term) { + const double value = source[term]; + if (value == 0.0) { + continue; + } + const double* weights = kernel + term * kOutputs; + const float64x2_t factor = vdupq_n_f64(value); + for (int chunk = 0; chunk < 16; ++chunk) { + partial[chunk] = vaddq_f64( + partial[chunk], vmulq_f64(factor, vld1q_f64(weights + chunk * 2))); + } + } + for (int chunk = 0; chunk < 16; ++chunk) { + vst1q_f64(destination + chunk * 2, partial[chunk]); + } + } +} + +// --------------------------------------------------- Rendered hybrid path --- +// +// Two bands per iteration, real and imaginary held apart and reloaded from memory +// in the caller's own layout: `out += h * t * scale` for the real part and +// `out += h * swapped(t) * scale` for the imaginary one, with the scale applied to +// each product separately. +void render_hybrid_path_neon(double* out, const double* transfer, const double* history0, + const double* history1, double scale) noexcept { + const float64x2_t factor = vdupq_n_f64(scale); + const double* histories[2] = {history0, history1}; + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const double* source = histories[ear]; + const double* taps = transfer + ear * kPathBands * 2u; + double* destination = out + ear * kPathBands * 2u; + std::size_t band = 0u; + for (; band + 2u <= kPathBands; band += 2u) { + const float64x2x2_t history = vld2q_f64(source + band * 2u); + const float64x2x2_t tap = vld2q_f64(taps + band * 2u); + float64x2x2_t output = vld2q_f64(destination + band * 2u); + // The caller scales each product on its own before combining, so the + // scale is a separate multiply of every product -- not a multiply of the + // difference and the sum, which would round differently. + const float64x2_t real = vsubq_f64( + vmulq_f64(vmulq_f64(history.val[0], tap.val[0]), factor), + vmulq_f64(vmulq_f64(history.val[1], tap.val[1]), factor)); + const float64x2_t imaginary = vaddq_f64( + vmulq_f64(vmulq_f64(history.val[0], tap.val[1]), factor), + vmulq_f64(vmulq_f64(history.val[1], tap.val[0]), factor)); + output.val[0] = vaddq_f64(output.val[0], real); + output.val[1] = vaddq_f64(output.val[1], imaginary); + vst2q_f64(destination + band * 2u, output); + } + for (; band < kPathBands; ++band) { + const double source_real = source[band * 2u]; + const double source_imag = source[band * 2u + 1u]; + const double tap_real = taps[band * 2u]; + const double tap_imag = taps[band * 2u + 1u]; + destination[band * 2u] += + source_real * tap_real * scale - source_imag * tap_imag * scale; + destination[band * 2u + 1u] += + source_real * tap_imag * scale + source_imag * tap_real * scale; + } + } +} + +// Scalar times a run of interleaved complexes, two complexes per iteration. +void complex_axpy_neon(double* out, const double* field, double scale, + std::size_t count) noexcept { + const float64x2_t factor = vdupq_n_f64(scale); + std::size_t index = 0u; + for (; index + 2u <= count; index += 2u) { + const float64x2_t values = vld1q_f64(field + index * 2u); + const float64x2_t accumulated = vld1q_f64(out + index * 2u); + vst1q_f64(out + index * 2u, vaddq_f64(accumulated, vmulq_f64(values, factor))); + } + for (; index < count; ++index) { + out[index * 2u] += field[index * 2u] * scale; + out[index * 2u + 1u] += field[index * 2u + 1u] * scale; + } +} + +// QMF analysis polyphase accumulate, two bands per iteration. +void qmf_analysis_taps_neon(double* out, const double* source, const double* coefficients, + std::size_t rows) noexcept { + for (std::size_t row = 0u; row < rows; ++row) { + double* destination = out + row * kQmfAnalysisBands; + const double* values = source + row * kQmfAnalysisBands; + for (std::size_t band = 0u; band < kQmfAnalysisBands; band += 2u) { + vst1q_f64(destination + band, + vaddq_f64(vld1q_f64(destination + band), + vmulq_f64(vld1q_f64(values + band), + vld1q_f64(coefficients + band)))); + } + } +} + +// Element-wise complex product of two runs, two complexes per iteration. +void complex_multiply_neon(double* out, const double* left, const double* right, + std::size_t count) noexcept { + std::size_t index = 0u; + for (; index + 2u <= count; index += 2u) { + const float64x2x2_t first = vld2q_f64(left + index * 2u); + const float64x2x2_t second = vld2q_f64(right + index * 2u); + float64x2x2_t result; + result.val[0] = vsubq_f64(vmulq_f64(first.val[0], second.val[0]), + vmulq_f64(first.val[1], second.val[1])); + result.val[1] = vaddq_f64(vmulq_f64(first.val[0], second.val[1]), + vmulq_f64(first.val[1], second.val[0])); + vst2q_f64(out + index * 2u, result); + } + for (; index < count; ++index) { + const std::size_t offset = index * 2u; + const double left_real = left[offset]; + const double left_imag = left[offset + 1u]; + const double right_real = right[offset]; + const double right_imag = right[offset + 1u]; + out[offset] = left_real * right_real - left_imag * right_imag; + out[offset + 1u] = left_real * right_imag + left_imag * right_real; + } +} + +const Kernels kNeon{ + &fft_butterflies_neon, + &qmf_synthesis_basis_neon, + &hybrid_low_join_neon, + &render_hybrid_path_neon, + &complex_axpy_neon, + &qmf_analysis_taps_neon, + &complex_multiply_neon, +}; + +} // namespace + +const Kernels& kernels_intrin_neon() noexcept { return kNeon; } + +} // namespace joc::simd diff --git a/src/simd/kernels_scalar.cpp b/src/simd/kernels_scalar.cpp new file mode 100644 index 0000000..cdf689e --- /dev/null +++ b/src/simd/kernels_scalar.cpp @@ -0,0 +1,156 @@ +// Scalar reference implementations of the dispatched DSP kernels. +// +// This unit is compiled with the baseline ISA of the target (no /arch flag on +// MSVC, no -m flag elsewhere) and is the ground truth every vector path is +// compared against: JOC_SIMD=scalar selects exactly these functions, and their +// output must be bit-identical to any ISA path's. +// +// The arithmetic below is deliberately written with std::complex, which +// on MSVC expands to the plain `re * rr - im * ri` / `re * ri + im * rr` pair +// (no helper call, no scaling trick), so the vector paths have an unambiguous +// two-roundings-per-component target to reproduce. + +#include "simd/simd.h" + +#include + +#include "foundation/fft.h" + +namespace joc::simd { +namespace { + +using Complex = dsp::Complex; + +// Exactly the stage loop of FftPlan::apply, over a table this kernel does not own, +// for any power-of-two size. The bit-reversal permutation stays with the caller: +// both call sites already write their input in permuted order. +void fft_butterflies_scalar(double* raw_data, std::size_t size, const double* raw_twiddle, + const std::size_t* stage_begin) noexcept { + auto* data = reinterpret_cast(raw_data); + const auto* twiddle = reinterpret_cast(raw_twiddle); + std::size_t stage = 0u; + for (std::size_t length = 2u; length <= size; length <<= 1u, ++stage) { + const Complex* table = twiddle + stage_begin[stage]; + for (std::size_t start = 0u; start < size; start += length) { + for (std::size_t offset = 0u; offset < length / 2u; ++offset) { + const Complex even = data[start + offset]; + const Complex odd = data[start + offset + length / 2u] * table[offset]; + data[start + offset] = even + odd; + data[start + offset + length / 2u] = even - odd; + } + } + } +} + +// The reference for the synthesis basis: one accumulator per output, taps in +// increasing order, one rounding per multiply and per add. This is the shape +// both callers write, with the basis rows reordered rank-minor -- the products +// and their order are the caller's. +void qmf_synthesis_basis_scalar(const double* values, const double* basis, double* out, + std::size_t rows) noexcept { + for (std::size_t row = 0u; row < rows; ++row) { + const double* source = values + row * kSynthesisTaps; + double* destination = out + row * kSynthesisBands * kSynthesisRanks; + for (std::size_t band = 0u; band < kSynthesisBands; ++band) { + const double* table = basis + band * kSynthesisTaps * kSynthesisRanks; + for (std::size_t rank = 0u; rank < kSynthesisRanks; ++rank) { + double sum = 0.0; + for (std::size_t tap = 0u; tap < kSynthesisTaps; ++tap) { + sum += source[tap] * table[tap * kSynthesisRanks + rank]; + } + destination[band * kSynthesisRanks + rank] = sum; + } + } + } +} + +// The reference for the hybrid low join: one accumulator per output, terms in the +// caller's order, one rounding per multiply and per add, zero terms skipped. +void hybrid_low_join_scalar(const double* values, const double* kernel, double* out, + std::size_t rows) noexcept { + for (std::size_t row = 0u; row < rows; ++row) { + const double* source = values + row * kHybridTerms; + double* destination = out + row * kHybridOutputs; + for (std::size_t output = 0u; output < kHybridOutputs; ++output) { + destination[output] = 0.0; + } + for (std::size_t term = 0u; term < kHybridTerms; ++term) { + const double value = source[term]; + if (value == 0.0) { + continue; + } + const double* weights = kernel + term * kHybridOutputs; + for (std::size_t output = 0u; output < kHybridOutputs; ++output) { + destination[output] += value * weights[output]; + } + } + } +} + +// The reference for one rendered path: each band of each ear accumulates its own +// value, in the caller's order, with the scale applied to each product. +void render_hybrid_path_scalar(double* out, const double* transfer, const double* history0, + const double* history1, double scale) noexcept { + const double* histories[2] = {history0, history1}; + for (std::size_t ear = 0u; ear < 2u; ++ear) { + const double* source = histories[ear]; + const double* taps = transfer + ear * kPathBands * 2u; + double* destination = out + ear * kPathBands * 2u; + for (std::size_t band = 0u; band < kPathBands; ++band) { + const double source_real = source[band * 2u]; + const double source_imag = source[band * 2u + 1u]; + const double tap_real = taps[band * 2u]; + const double tap_imag = taps[band * 2u + 1u]; + destination[band * 2u] += + source_real * tap_real * scale - source_imag * tap_imag * scale; + destination[band * 2u + 1u] += + source_real * tap_imag * scale + source_imag * tap_real * scale; + } + } +} + +// Neighbouring complexes and neighbouring bands are independent outputs, so the +// references for the two accumulates are plain element-wise loops. +void complex_axpy_scalar(double* out, const double* field, double scale, + std::size_t count) noexcept { + for (std::size_t index = 0u; index < count * 2u; ++index) { + out[index] += field[index] * scale; + } +} + +void qmf_analysis_taps_scalar(double* out, const double* source, const double* coefficients, + std::size_t rows) noexcept { + for (std::size_t row = 0u; row < rows; ++row) { + double* destination = out + row * kQmfAnalysisBands; + const double* values = source + row * kQmfAnalysisBands; + for (std::size_t band = 0u; band < kQmfAnalysisBands; ++band) { + destination[band] += values[band] * coefficients[band]; + } + } +} + +void complex_multiply_scalar(double* out, const double* left, const double* right, + std::size_t count) noexcept { + auto* destination = reinterpret_cast(out); + const auto* first = reinterpret_cast(left); + const auto* second = reinterpret_cast(right); + for (std::size_t index = 0u; index < count; ++index) { + destination[index] = first[index] * second[index]; + } +} + +const Kernels kScalar{ + &fft_butterflies_scalar, + &qmf_synthesis_basis_scalar, + &hybrid_low_join_scalar, + &render_hybrid_path_scalar, + &complex_axpy_scalar, + &qmf_analysis_taps_scalar, + &complex_multiply_scalar, +}; + +} // namespace + +const Kernels& kernels_scalar() noexcept { return kScalar; } + +} // namespace joc::simd diff --git a/src/simd/simd.h b/src/simd/simd.h new file mode 100644 index 0000000..61b10d0 --- /dev/null +++ b/src/simd/simd.h @@ -0,0 +1,209 @@ +#pragma once + +#include + +// Runtime-dispatched SIMD kernels for the DSP core. +// +// Module layout (the ISA lives in the file name, never in a subdirectory): +// +// simd.h this contract -- the only header a caller includes +// cpu_probe.{h,cpp} "can this CPU and OS run ISA X", no policy +// dispatch.cpp JOC_SIMD + the ladder + the kernel table +// kernels_scalar.cpp the reference implementation, Isa::scalar +// kernels_intrin_avx2.cpp /arch:AVX2 -mavx2 -- exactly the +// kernels_intrin_avx512.cpp /arch:AVX512 -mavx512f -- `kernels_intrin_*` +// kernels_intrin_neon.cpp AArch64 default -- units get a wider flag +// +// The scalar reference in kernels_scalar.cpp fixes both the data layout and the +// arithmetic: a vector path may only compute *independent* outputs in parallel +// lanes. It may never reassociate an accumulation, contract a multiply into an +// FMA, or change the order in which one output's terms are summed, so every ISA +// path reproduces the scalar bits exactly and JOC_SIMD=scalar is a valid +// reference for any of them. Kernel-level layout changes (AoS -> SoA inside a +// kernel, for instance) are fine as long as each individual output value is +// still produced by the same sequence of roundings. +// +// MSVC has no function-level ISA attribute, so each ISA lives in its own +// translation unit compiled with its own /arch (or -m) flag and the dispatcher +// picks one at run time: CPUID + XGETBV on x86-64, the architectural AArch64 +// baseline (NEON/ASIMD needs no probing) elsewhere. +// +// The ISA units are linked into the same binaries as the baseline code, so they +// must stay free of objects with dynamic initialisation: a global constructor +// would execute ISA-specific instructions before the dispatcher has had a chance +// to look at the CPU. Constant tables are fine -- they live in .rdata. +namespace joc::simd { + +enum class Isa { + scalar = 0, + sse2, + avx2, + avx512, + neon, +}; + +// One entry per dispatched kernel. +enum class Kernel { + // Power-of-two radix-2 DIT butterfly cascade, in place, over `size` interleaved + // (re, im) pairs already in bit-reversed order. `twiddle` is the caller's own + // factor table, read as interleaved pairs: stage s (length 2^(s+1)) takes its + // 2^s factors starting at stage_begin[s], a *complex* index into `twiddle`. + fft_butterflies = 0, + // QMF synthesis basis application, see kSynthesis* below. + qmf_synthesis_basis, + // Hybrid analysis low join, see kHybrid* below. + hybrid_low_join, + // Hybrid-domain path rendering, see kPathBands below. + render_hybrid_path, + // Scalar-times-vector accumulate over interleaved complexes. + complex_axpy, + // QMF analysis polyphase accumulate, see kQmfAnalysisBands below. + qmf_analysis_taps, + // Element-wise complex product of two whole runs. + complex_multiply, + count, +}; + +// Both filterbanks apply the same map: for every output row and every one of the +// 64 bands, four ranks each accumulate 128 taps. +inline constexpr std::size_t kSynthesisBands = 64; +inline constexpr std::size_t kSynthesisRanks = 4; +inline constexpr std::size_t kSynthesisTaps = 128; + +// ... and both derive the same 16 low hybrid bands from 78 terms: 3 parents x 2 +// components x 13 lags. +inline constexpr std::size_t kHybridTerms = 78; +inline constexpr std::size_t kHybridOutputs = 32; +// Rows the callers stage at a time: enough to keep the kernel busy, small enough +// that the staged values stay in the first-level cache. +inline constexpr std::size_t kHybridJoinBlock = 32; + +// Bands in one ear of a rendered path (the SOFA renderer's 77-band hybrid domain). +inline constexpr std::size_t kPathBands = 77; + +// The cascade packs whole groups into a vector, so it needs at least one full +// packing: a size of 8 covers a 512-bit stage. Smaller transforms are rare enough +// (and short enough) that the caller's portable loop is the right answer there. +inline constexpr std::size_t kMinVectorFftSize = 8; + +// Bands in one QMF analysis row (the polyphase accumulator of both filterbanks). +inline constexpr std::size_t kQmfAnalysisBands = 64; + +const char* isa_name(Isa isa) noexcept; + +// Whether this CPU *and* the OS state it has to save can execute the ISA. The +// answer never changes, so it is computed once. +bool isa_supported(Isa isa) noexcept; + +// The ISA the dispatcher settled on, after applying a JOC_SIMD override. This +// is the widest ISA considered, not necessarily the one that serves every +// kernel: active_isa() answers that per kernel. +Isa selected_isa() noexcept; + +// Which ISA actually implements `kernel` after the per-kernel fallback. +Isa active_isa(Kernel kernel) noexcept; + +// The dispatched kernels; a slot is never null. +struct Kernels { + void (*fft_butterflies)(double* data, std::size_t size, const double* twiddle, + const std::size_t* stage_begin) noexcept = nullptr; + + // values: [rows][kSynthesisTaps] real/imaginary of the 64 bands of one row. + // basis: the same weights the caller holds, reordered rank-minor, so that + // (band, tap) addresses its kSynthesisRanks weights contiguously: + // basis[(band * kSynthesisTaps + tap) * kSynthesisRanks + rank]. + // out: [rows][kSynthesisBands][kSynthesisRanks], rank-minor as well. + // + // Each of the four ranks is an independent dot product over the row, so the + // four of them are what shares a vector; every lane keeps the tap order and + // the two roundings of the caller's `sum += values[tap] * weight`. + void (*qmf_synthesis_basis)(const double* values, const double* basis, double* out, + std::size_t rows) noexcept = nullptr; + + // Hybrid analysis low join. Every output row accumulates kHybridTerms values + // into kHybridOutputs outputs (16 bands x a real/imaginary pair, component + // minor): + // out[row][output] = sum over term of values[row][term] * kernel[term][output] + // values is [rows][kHybridTerms] in the caller's own term order and kernel is + // the caller's taps regrouped to that same order, so that one term's 32 + // weights are contiguous. Terms whose value is exactly zero are skipped, as + // both callers do: adding a zero product to a lane can only leave it alone + // (no lane's running sum can be a negative zero, since it starts at +0 and + // sums without ever producing one). + void (*hybrid_low_join)(const double* values, const double* kernel, double* out, + std::size_t rows) noexcept = nullptr; + + // One rendered path. For each ear e and band b, with the ear's history sample + // h and the path's transfer t: + // out[e][b].re += h.re * t[e][b].re * scale - h.im * t[e][b].im * scale + // out[e][b].im += h.re * t[e][b].im * scale + h.im * t[e][b].re * scale + // `history0` and `history1` are the two ears' [kPathBands] interleaved complex + // rows (they come from different places in the history ring); `transfer` and + // `out` are [2][kPathBands] interleaved complexes. The scale multiplies each + // product separately, exactly as the caller writes it, so the bands -- which + // are independent accumulations into independent outputs -- are what the lanes + // carry. + void (*render_hybrid_path)(double* out, const double* transfer, const double* history0, + const double* history1, double scale) noexcept = nullptr; + + // `count` interleaved complexes, accumulated in place: + // out[i] += field[i] * scale + // Every element is an independent accumulation of one product, so the lanes + // carry neighbouring elements and each one keeps the caller's multiply-then-add. + void (*complex_axpy)(double* out, const double* field, double scale, + std::size_t count) noexcept = nullptr; + + // QMF analysis polyphase accumulate: `rows` rows of kQmfAnalysisBands bands, + // out[row][band] += source[row][band] * coefficients[band] + // Neighbouring bands are neighbouring outputs, so they are what fills a vector; + // each band accumulates its own product once, in the caller's order. + void (*qmf_analysis_taps)(double* out, const double* source, const double* coefficients, + std::size_t rows) noexcept = nullptr; + + // `count` interleaved complexes, multiplied element by element: + // out[i] = left[i] * right[i] + // with the caller's `re * re - im * im` and `re * im + im * re`, two roundings + // per component. Neighbouring complexes are independent products. + void (*complex_multiply)(double* out, const double* left, const double* right, + std::size_t count) noexcept = nullptr; +}; + +const Kernels& kernels() noexcept; + +// Convenience wrappers. +inline void fft_butterflies(double* data, std::size_t size, const double* twiddle, + const std::size_t* stage_begin) noexcept { + kernels().fft_butterflies(data, size, twiddle, stage_begin); +} + +inline void qmf_synthesis_basis(const double* values, const double* basis, double* out, + std::size_t rows) noexcept { + kernels().qmf_synthesis_basis(values, basis, out, rows); +} + +inline void hybrid_low_join(const double* values, const double* kernel, double* out, + std::size_t rows) noexcept { + kernels().hybrid_low_join(values, kernel, out, rows); +} + +inline void render_hybrid_path(double* out, const double* transfer, const double* history0, + const double* history1, double scale) noexcept { + kernels().render_hybrid_path(out, transfer, history0, history1, scale); +} + +inline void complex_axpy(double* out, const double* field, double scale, + std::size_t count) noexcept { + kernels().complex_axpy(out, field, scale, count); +} + +inline void qmf_analysis_taps(double* out, const double* source, const double* coefficients, + std::size_t rows) noexcept { + kernels().qmf_analysis_taps(out, source, coefficients, rows); +} + +inline void complex_multiply(double* out, const double* left, const double* right, + std::size_t count) noexcept { + kernels().complex_multiply(out, left, right, count); +} + +} // namespace joc::simd diff --git a/src/speaker/speaker_layout_lookup.cpp b/src/speaker/speaker_layout_lookup.cpp new file mode 100644 index 0000000..eb41ad1 --- /dev/null +++ b/src/speaker/speaker_layout_lookup.cpp @@ -0,0 +1,71 @@ +#include "speaker/speaker_layout_lookup.h" + +#include + +namespace joc::speaker { + +namespace { + +struct FrozenLayout { + const char* name; + std::uint32_t out_ch_config; + std::uint32_t speaker_bitfield; +}; + +constexpr FrozenLayout kLayouts[kLayoutCount] = { + {"2.0", 0, 1}, + {"3.1", 3, 7}, + {"5.1", 7, 15}, + {"7.1", 11, 31}, + {"5.1.2", 13, 1039}, + {"5.1.4", 14, 2575}, + {"7.1.2", 15, 1055}, + {"7.1.4", 16, 2591}, + {"9.1.4", 19, 2719}, + {"9.1.6", 20, 3743}, +}; + +void fill(const FrozenLayout& source, LayoutInfo* out) { + out->name = source.name; + out->out_ch_config = source.out_ch_config; + out->speaker_bitfield = source.speaker_bitfield; + out->channel_count = ejoc_speaker_layout_channel_count(source.speaker_bitfield); +} + +} // namespace + +bool layout_at(int index, LayoutInfo* out) { + if (out == nullptr || index < 0 || index >= kLayoutCount) { + return false; + } + fill(kLayouts[index], out); + return true; +} + +bool layout_by_name(const char* name, LayoutInfo* out) { + if (name == nullptr || out == nullptr) { + return false; + } + for (int index = 0; index < kLayoutCount; ++index) { + if (std::strcmp(name, kLayouts[index].name) == 0) { + fill(kLayouts[index], out); + return true; + } + } + return false; +} + +bool layout_by_bitfield(std::uint32_t bitfield, LayoutInfo* out) { + if (out == nullptr) { + return false; + } + for (int index = 0; index < kLayoutCount; ++index) { + if (kLayouts[index].speaker_bitfield == bitfield) { + fill(kLayouts[index], out); + return true; + } + } + return false; +} + +} // namespace joc::speaker diff --git a/src/speaker/speaker_layout_lookup.h b/src/speaker/speaker_layout_lookup.h new file mode 100644 index 0000000..0416d9d --- /dev/null +++ b/src/speaker/speaker_layout_lookup.h @@ -0,0 +1,28 @@ + +#pragma once + +#include + +#include "eac3joc_core.h" +#include "joc_core.h" + +namespace joc::speaker { + +inline constexpr int kLayoutCount = 10; + +struct LayoutInfo { + const char* name = ""; + std::uint32_t out_ch_config = 0; + std::uint32_t speaker_bitfield = 0; + std::uint32_t channel_count = 0; +}; + +// All ten layouts in the reference's order (2.0, 3.1, 5.1, 7.1, 5.1.2, 5.1.4, +bool layout_at(int index, LayoutInfo* out); + +// False when the name is unknown (case-sensitive, exactly as the reference CLI). +bool layout_by_name(const char* name, LayoutInfo* out); + +bool layout_by_bitfield(std::uint32_t bitfield, LayoutInfo* out); + +} // namespace joc::speaker diff --git a/src/speaker/speaker_layouts.h b/src/speaker/speaker_layouts.h new file mode 100644 index 0000000..cbd7f89 --- /dev/null +++ b/src/speaker/speaker_layouts.h @@ -0,0 +1,534 @@ +#pragma once + +#include +#include +#include + +namespace ejoc::speaker_tables { + +inline constexpr std::size_t kMaxPoints = 15; +inline constexpr std::size_t kMaxGroups = 4; +inline constexpr std::size_t kMaxGroupSize = 3; +inline constexpr std::size_t kMaxChannels = 16; + +struct SpeakerPoint { + std::array coordinate_q15{}; + std::uint8_t speaker_id{}; +}; + +struct AxisGroup { + std::uint8_t size{}; + std::array indices{}; +}; + +struct RegionGeometry { + std::uint8_t point_count{}; + std::uint8_t mode{}; + std::uint8_t axis0_group_count{}; + std::uint8_t axis1_group_count{}; + std::array points{}; + std::array axis0_groups{}; + std::array axis1_groups{}; +}; + +struct LayoutGeometry { + std::uint32_t speaker_bitfield{}; + std::uint8_t out_ch_config{}; + std::uint8_t channel_count{}; + std::array standard_from_internal{}; + std::array regions{}; +}; + +inline constexpr std::array kLayouts{{ + LayoutGeometry{ + 0x1u, 0, 2, + {{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0x7u, 3, 4, + {{0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 1, 1, 1, 0, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0xFu, 7, 6, + {{0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 5, 2, 2, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 2, 2, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 2, 2, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 2, 2, 0, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 2, 1, 1, 0, + {{SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0x1Fu, 11, 8, + {{0, 1, 2, 3, 6, 7, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 7, 2, 3, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 2, 2, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 2, 2, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 2, 2, 0, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 4, 2, 2, 0, + {{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0x40Fu, 13, 8, + {{0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 7, 3, 2, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 3, 2, 1, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 3, 1, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 4, 3, 1, 1, + {{SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 6}, SpeakerPoint{{24840, 16384, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0xA0Fu, 14, 10, + {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 9, 3, 2, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 9, 3, 2, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 9, 3, 2, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 2, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 1, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 6, 3, 1, 2, + {{SpeakerPoint{{0, 32767, 0}, 4}, SpeakerPoint{{32767, 32767, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{{7928, 24840, 32767}, 8}, SpeakerPoint{{24840, 24840, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {2, 3, 0}}, AxisGroup{2, {4, 5, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 3, 1, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 6}, SpeakerPoint{{24840, 7928, 32767}, 7}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0x41Fu, 15, 10, + {{0, 1, 2, 3, 6, 7, 4, 5, 8, 9, 0, 0, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 9, 3, 3, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}}}, + {{AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 3, 2, 1, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 3, 1, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 6, 3, 2, 1, + {{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 16384, 32767}, 8}, SpeakerPoint{{24840, 16384, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {4, 5, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 3, 1, 1, 0, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0xA1Fu, 16, 12, + {{0, 1, 2, 3, 6, 7, 4, 5, 8, 9, 10, 11, 0, 0, 0, 0}}, + {{ + RegionGeometry{ + 11, 3, 3, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}}}, + {{AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 9, 3, 2, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 9, 3, 2, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 2, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 1, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 8, 3, 2, 2, + {{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{{7928, 24840, 32767}, 10}, SpeakerPoint{{24840, 24840, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {4, 5, 0}}, AxisGroup{2, {6, 7, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 5, 3, 1, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 8}, SpeakerPoint{{24840, 7928, 32767}, 9}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0xA9Fu, 19, 14, + {{0, 1, 2, 3, 6, 7, 4, 5, 10, 11, 12, 13, 8, 9, 0, 0}}, + {{ + RegionGeometry{ + 13, 3, 4, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}}}, + {{AxisGroup{2, {9, 10, 0}}, AxisGroup{2, {11, 12, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 11, 3, 3, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}}}, + {{AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 9, 3, 2, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 2, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 1, 2, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 8, 3, 2, 2, + {{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 24840, 32767}, 12}, SpeakerPoint{{24840, 24840, 32767}, 13}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {4, 5, 0}}, AxisGroup{2, {6, 7, 0}}, AxisGroup{}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + }, + LayoutGeometry{ + 0xE9Fu, 20, 16, + {{0, 1, 2, 3, 6, 7, 4, 5, 10, 11, 14, 15, 12, 13, 8, 9}}, + {{ + RegionGeometry{ + 15, 3, 4, 3, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}}}, + {{AxisGroup{2, {9, 10, 0}}, AxisGroup{2, {11, 12, 0}}, AxisGroup{2, {13, 14, 0}}, AxisGroup{}}} + }, + RegionGeometry{ + 13, 3, 3, 3, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}}}, + {{AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{2, {11, 12, 0}}, AxisGroup{}}} + }, + RegionGeometry{ + 11, 3, 2, 3, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{2, {9, 10, 0}}, AxisGroup{}}} + }, + RegionGeometry{ + 9, 3, 2, 3, + {{SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{1, {0, 0, 0}}, AxisGroup{2, {1, 2, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}}} + }, + RegionGeometry{ + 9, 3, 1, 3, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {3, 4, 0}}, AxisGroup{2, {5, 6, 0}}, AxisGroup{2, {7, 8, 0}}, AxisGroup{}}} + }, + RegionGeometry{ + 10, 3, 2, 3, + {{SpeakerPoint{{0, 16384, 0}, 4}, SpeakerPoint{{32767, 16384, 0}, 5}, SpeakerPoint{{0, 32767, 0}, 6}, SpeakerPoint{{32767, 32767, 0}, 7}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{{7928, 16384, 32767}, 12}, SpeakerPoint{{24840, 16384, 32767}, 13}, SpeakerPoint{{7928, 24840, 32767}, 14}, SpeakerPoint{{24840, 24840, 32767}, 15}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{2, {0, 1, 0}}, AxisGroup{2, {2, 3, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {4, 5, 0}}, AxisGroup{2, {6, 7, 0}}, AxisGroup{2, {8, 9, 0}}, AxisGroup{}}} + }, + RegionGeometry{ + 7, 3, 2, 1, + {{SpeakerPoint{{0, 0, 0}, 0}, SpeakerPoint{{32767, 0, 0}, 1}, SpeakerPoint{{16384, 0, 0}, 2}, SpeakerPoint{{0, 5285, 0}, 8}, SpeakerPoint{{32767, 5285, 0}, 9}, SpeakerPoint{{7928, 7928, 32767}, 10}, SpeakerPoint{{24840, 7928, 32767}, 11}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}, SpeakerPoint{}}}, + {{AxisGroup{3, {0, 2, 1}}, AxisGroup{2, {3, 4, 0}}, AxisGroup{}, AxisGroup{}}}, + {{AxisGroup{2, {5, 6, 0}}, AxisGroup{}, AxisGroup{}, AxisGroup{}}} + } + }} + } +}}; + +inline constexpr const LayoutGeometry* find_layout(const std::uint32_t speaker_bitfield) noexcept { + for (const auto& layout : kLayouts) { + if (layout.speaker_bitfield == speaker_bitfield) { + return &layout; + } + } + return nullptr; +} + +} // namespace ejoc::speaker_tables diff --git a/src/speaker/speaker_renderer.cpp b/src/speaker/speaker_renderer.cpp new file mode 100644 index 0000000..385cce5 --- /dev/null +++ b/src/speaker/speaker_renderer.cpp @@ -0,0 +1,495 @@ +#define EJOC_BUILD_DLL +#include "eac3joc_core.h" +#include "speaker_layouts.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace ejoc::speaker { + +using speaker_tables::AxisGroup; +using speaker_tables::LayoutGeometry; +using speaker_tables::RegionGeometry; + +constexpr double kPi = 3.141592653589793238462643383279502884; +constexpr double kQ15Scale = 32768.0; +constexpr double kQ15Max = 32767.0 / kQ15Scale; +constexpr double kGainSnapThreshold = 1.0e-4; +constexpr std::size_t kObjects = EJOC_MAX_OBJECTS; +constexpr std::size_t kChannels = EJOC_OUTPUT_CHANNELS; +constexpr std::size_t kBlock = EJOC_SPEAKER_BLOCK_SAMPLES; + +using PointGains = std::array; +using ChannelGains = std::array; +using ObjectChannelGains = std::array; +using RemainingCounts = std::array, kObjects>; + +inline double clamp(const double value, const double low, const double high) noexcept { + return value < low ? low : (value > high ? high : value); +} + +inline double coordinate(const RegionGeometry& region, const std::size_t point, + const std::size_t component) noexcept { + return static_cast(region.points[point].coordinate_q15[component]) / kQ15Scale; +} + +std::uint64_t expand_speaker_bitfield(const std::uint32_t compact) noexcept { + constexpr std::array expansions{{ + 0x00000003ULL, 0x00000004ULL, 0x00000008ULL, 0x00000030ULL, + 0x000000C0ULL, 0x00000100ULL, 0x00000600ULL, 0x00001800ULL, + 0x00006000ULL, 0x00018000ULL, 0x00060000ULL, 0x00180000ULL, + 0x00600000ULL, 0x01800000ULL, 0x06000000ULL, 0x18000000ULL, + 0x60000000ULL, 0x080000000ULL, 0x600000000ULL, 0x800000000ULL, + 0x1000000000ULL, 0x2000000000ULL, + }}; + std::uint64_t expanded = 0; + for (std::size_t bit_index = 0; bit_index < expansions.size(); ++bit_index) { + if ((compact & (1u << bit_index)) != 0) { + expanded |= expansions[bit_index]; + } + } + return expanded; +} + +inline int bit(const std::uint64_t value, const unsigned index) noexcept { + return static_cast((value >> index) & 1ULL); +} + +double layout_attenuation_db(const std::uint32_t compact) noexcept { + const std::uint64_t expanded = expand_speaker_bitfield(compact); + const int height_channels = 2 * ( + bit(expanded, 13) + bit(expanded, 15) + bit(expanded, 17) + + bit(expanded, 19) + bit(expanded, 21)); + const int floor_channels = bit(expanded, 8) + 2 * ( + bit(expanded, 31) + bit(expanded, 4) + bit(expanded, 6) + + bit(expanded, 11) + bit(expanded, 25) + bit(expanded, 27) + + bit(expanded, 29) + bit(expanded, 33)); + const double height_factor = std::min(static_cast(height_channels) / 4.0, 1.0); + const double floor_factor = std::min(static_cast(floor_channels) / 4.0, 1.0); + return -std::max(4.5 - 1.5 * height_factor - 3.0 * floor_factor, 0.0); +} + +int floor_y_exponent(const std::uint32_t compact) noexcept { + const std::uint32_t low = static_cast(expand_speaker_bitfield(compact)); + return ((low & 0x130u) != 0 && (low & 0x18C0u) == 0) ? 1 : 0; +} + +inline void equal_power_pair(const double position, double& lower, double& upper) noexcept { + const double angle = (kPi * 0.5) * position; + lower = std::cos(angle); + upper = std::sin(angle); +} + +void axis0_gains(const RegionGeometry& region, + const std::array& groups, + const std::uint8_t group_count, + const double value, + PointGains& output) noexcept { + output.fill(0.0); + for (std::size_t row = 0; row < group_count; ++row) { + const auto& group = groups[row]; + if (group.size == 0) { + continue; + } + const std::size_t first = group.indices[0]; + const std::size_t last = group.indices[group.size - 1]; + const double first_value = coordinate(region, first, 0); + const double last_value = coordinate(region, last, 0); + if (value <= first_value) { + output[first] = 1.0; + continue; + } + if (value >= last_value) { + output[last] = 1.0; + continue; + } + for (std::size_t index = 0; index + 1 < group.size; ++index) { + const std::size_t lower_index = group.indices[index]; + const std::size_t upper_index = group.indices[index + 1]; + const double lower_value = coordinate(region, lower_index, 0); + const double upper_value = coordinate(region, upper_index, 0); + if (value > lower_value && value <= upper_value) { + const double position = (value - lower_value) / (upper_value - lower_value); + equal_power_pair(position, output[lower_index], output[upper_index]); + break; + } + } + } +} + +void axis1_gains(const RegionGeometry& region, + const std::array& groups, + const std::uint8_t group_count, + const double value, + PointGains& output) noexcept { + output.fill(0.0); + if (group_count == 0) { + return; + } + const auto& first_group = groups[0]; + const auto& last_group = groups[group_count - 1]; + const double first_value = coordinate(region, first_group.indices[0], 1); + const double last_value = coordinate(region, last_group.indices[0], 1); + if (value <= first_value) { + for (std::size_t index = 0; index < first_group.size; ++index) { + output[first_group.indices[index]] = 1.0; + } + return; + } + if (value > last_value) { + for (std::size_t index = 0; index < last_group.size; ++index) { + output[last_group.indices[index]] = 1.0; + } + return; + } + for (std::size_t row = 0; row + 1 < group_count; ++row) { + const auto& lower_group = groups[row]; + const auto& upper_group = groups[row + 1]; + const double lower_value = coordinate(region, lower_group.indices[0], 1); + const double upper_value = coordinate(region, upper_group.indices[0], 1); + if (value >= lower_value && value <= upper_value) { + const double position = (value - lower_value) / (upper_value - lower_value); + double lower_gain = 0.0; + double upper_gain = 0.0; + equal_power_pair(position, lower_gain, upper_gain); + for (std::size_t index = 0; index < lower_group.size; ++index) { + output[lower_group.indices[index]] = lower_gain; + } + for (std::size_t index = 0; index < upper_group.size; ++index) { + output[upper_group.indices[index]] = upper_gain; + } + return; + } + } +} + +void plane_gains(const RegionGeometry& region, + const std::array& groups, + const std::uint8_t group_count, + const double u, + const double v, + const std::uint8_t mode, + PointGains& output) noexcept { + axis0_gains(region, groups, group_count, u, output); + if (mode >= 2) { + PointGains vertical{}; + axis1_gains(region, groups, group_count, v, vertical); + for (std::size_t point = 0; point < region.point_count; ++point) { + output[point] *= vertical[point]; + } + } +} + +class Renderer { +public: + explicit Renderer(const LayoutGeometry* layout) noexcept : layout_(layout) { + for (std::size_t standard = 0; standard < layout_->channel_count; ++standard) { + standard_index_for_internal_[layout_->standard_from_internal[standard]] = + static_cast(standard); + } + attenuation_db_ = layout_attenuation_db(layout_->speaker_bitfield); + floor_y_exponent_ = floor_y_exponent(layout_->speaker_bitfield); + reset_state(); + } + + int reset() noexcept { + reset_state(); + error_[0] = '\0'; + return 0; + } + + const char* last_error() const noexcept { + return error_[0] ? error_.data() : ""; + } + + int process(const float* input, + const std::uint32_t sample_count, + const std::uint32_t metadata_count, + const std::uint32_t* metadata_offsets, + const std::uint32_t* ramp_durations, + const std::uint16_t* positions_q15, + const std::uint8_t* region_indices, + const std::uint8_t* height_enabled, + const double* object_gains, + double* output) noexcept { + error_[0] = '\0'; + if (!input || !output) { + return fail("null PCM pointer passed to ejoc_speaker_renderer_process"); + } + if ((sample_count % kBlock) != 0) { + return fail("sample_count must be a multiple of 32"); + } + if (metadata_count && (!metadata_offsets || !ramp_durations || !positions_q15)) { + return fail("metadata arrays are null while metadata_count is nonzero"); + } + if (!validate_metadata(sample_count, metadata_count, metadata_offsets, + positions_q15, region_indices, object_gains)) { + return -1; + } + + std::fill(output, output + static_cast(sample_count) * layout_->channel_count, 0.0); + const bool has_lfe = (layout_->speaker_bitfield & 0x4u) != 0; + const std::size_t total_blocks = sample_count / kBlock; + std::size_t event = 0; + for (std::size_t block = 0; block < total_blocks; ++block) { + while (event < metadata_count && aligned_block(metadata_offsets[event]) == block) { + apply_event(event, ramp_durations, positions_q15, region_indices, + height_enabled, object_gains); + ++event; + } + mix_block(input, output, block, has_lfe); + } + while (event < metadata_count && aligned_block(metadata_offsets[event]) == total_blocks) { + apply_event(event, ramp_durations, positions_q15, region_indices, + height_enabled, object_gains); + ++event; + } + if (event != metadata_count) { + return fail("metadata alignment produced an event outside this process call"); + } + return 0; + } + +private: + void reset_state() noexcept { + for (auto& row : current_) row.fill(0.0); + for (auto& row : target_) row.fill(0.0); + for (auto& row : step_) row.fill(0.0); + for (auto& row : remaining_) row.fill(0); + } + + int fail(const char* message) noexcept { + std::snprintf(error_.data(), error_.size(), "%s", message); + return -1; + } + + bool validate_metadata(const std::uint32_t sample_count, + const std::uint32_t metadata_count, + const std::uint32_t* metadata_offsets, + const std::uint16_t* positions_q15, + const std::uint8_t* region_indices, + const double* object_gains) noexcept { + for (std::size_t event = 0; event < metadata_count; ++event) { + if (metadata_offsets[event] > sample_count) { + fail("metadata offset exceeds sample_count"); + return false; + } + if (event && metadata_offsets[event] < metadata_offsets[event - 1]) { + fail("metadata offsets must be nondecreasing"); + return false; + } + for (std::size_t object = 0; object < kObjects; ++object) { + const std::size_t object_event = event * kObjects + object; + if (region_indices && region_indices[object_event] >= 7) { + fail("region index is above 6"); + return false; + } + if (object_gains && !std::isfinite(object_gains[object_event])) { + fail("object gain is not finite"); + return false; + } + const std::size_t coordinate_base = object_event * EJOC_SPEAKER_COORDINATES; + for (std::size_t component = 0; component < EJOC_SPEAKER_COORDINATES; ++component) { + if (positions_q15[coordinate_base + component] > 32767u) { + fail("Q15 object coordinate is above 32767"); + return false; + } + } + } + } + return true; + } + + static std::size_t aligned_block(const std::uint32_t sample) noexcept { + return (static_cast(sample) + kBlock / 2 - 1) / kBlock; + } + + static std::uint32_t ramp_blocks(const std::uint32_t duration) noexcept { + return static_cast( + (static_cast(duration) + kBlock / 2 - 1) / kBlock); + } + + void render_point(const std::uint16_t* position, + const std::uint8_t region_index, + const bool enable_height, + const double object_gain, + ChannelGains& output) const noexcept { + output.fill(0.0); + const auto& region = layout_->regions[region_index]; + const double u = static_cast(position[0]) / kQ15Scale; + const double v = static_cast(position[1]) / kQ15Scale; + const double w = static_cast(position[2]) / kQ15Scale; + const double floor_v = clamp(std::ldexp(v, floor_y_exponent_), 0.0, 1.0); + PointGains floor{}; + plane_gains(region, region.axis0_groups, region.axis0_group_count, + u, floor_v, region.mode, floor); + PointGains point = floor; + if (region.mode == 3) { + PointGains height{}; + plane_gains(region, region.axis1_groups, region.axis1_group_count, + u, v, 3, height); + const double z = enable_height ? clamp(w, 0.0, kQ15Max) : 0.0; + if (z >= kQ15Max) { + point = height; + } else if (z > 0.0) { + double floor_weight = 0.0; + double height_weight = 0.0; + equal_power_pair(z, floor_weight, height_weight); + for (std::size_t index = 0; index < region.point_count; ++index) { + point[index] = floor[index] * floor_weight + height[index] * height_weight; + } + } + } + const double y_term = clamp(v / 0.6, 0.0, 1.0); + const double z_term = clamp((w - 0.2) / 0.8, 0.0, 1.0); + const double amount = clamp(y_term + z_term, 0.0, 1.0); + const double gain = std::pow(10.0, attenuation_db_ * amount / 20.0) * object_gain; + for (std::size_t index = 0; index < region.point_count; ++index) { + output[region.points[index].speaker_id] = point[index] * gain; + } + } + + void apply_event(const std::size_t event, + const std::uint32_t* ramp_durations, + const std::uint16_t* positions_q15, + const std::uint8_t* region_indices, + const std::uint8_t* height_enabled, + const double* object_gains) noexcept { + const std::uint32_t blocks = ramp_blocks(ramp_durations[event]); + for (std::size_t object = 0; object < kObjects; ++object) { + const std::size_t object_event = event * kObjects + object; + const auto* position = positions_q15 + object_event * EJOC_SPEAKER_COORDINATES; + const std::uint8_t region = region_indices ? region_indices[object_event] : 0; + const bool height = !height_enabled || height_enabled[object_event] != 0; + const double object_gain = object_gains ? object_gains[object_event] : 1.0; + ChannelGains next{}; + render_point(position, region, height, object_gain, next); + for (std::size_t channel = 0; channel < layout_->channel_count; ++channel) { + const double difference = next[channel] - current_[object][channel]; + target_[object][channel] = next[channel]; + if (std::abs(difference) >= kGainSnapThreshold && blocks != 0) { + step_[object][channel] = difference / static_cast(blocks); + remaining_[object][channel] = blocks; + } else { + current_[object][channel] = next[channel]; + step_[object][channel] = 0.0; + remaining_[object][channel] = 0; + } + } + } + } + + void mix_block(const float* input, double* output, const std::size_t block, + const bool has_lfe) noexcept { + const std::size_t start = block * kBlock; + if (has_lfe) { + for (std::size_t sample = 0; sample < kBlock; ++sample) { + output[(start + sample) * layout_->channel_count + 3] = + static_cast(input[(start + sample) * EJOC_OUTPUT_CHANNELS]); + } + } + for (std::size_t object = 0; object < kObjects; ++object) { + for (std::size_t internal = 0; internal < layout_->channel_count; ++internal) { + const bool active = remaining_[object][internal] != 0; + const double fixed_gain = target_[object][internal]; + if (!active && fixed_gain == 0.0) { + continue; + } + const std::size_t standard = standard_index_for_internal_[internal]; + for (std::size_t sample = 0; sample < kBlock; ++sample) { + const double gain = active + ? current_[object][internal] + + (static_cast(sample) / static_cast(kBlock)) * + step_[object][internal] + : fixed_gain; + output[(start + sample) * layout_->channel_count + standard] += + static_cast( + input[(start + sample) * EJOC_OUTPUT_CHANNELS + object + 1]) * gain; + } + if (active) { + current_[object][internal] += step_[object][internal]; + --remaining_[object][internal]; + if (remaining_[object][internal] == 0) { + current_[object][internal] = target_[object][internal]; + } + } else { + current_[object][internal] = target_[object][internal]; + } + } + } + } + + const LayoutGeometry* layout_; + double attenuation_db_{}; + int floor_y_exponent_{}; + ObjectChannelGains current_{}; + ObjectChannelGains target_{}; + ObjectChannelGains step_{}; + RemainingCounts remaining_{}; + std::array standard_index_for_internal_{}; + std::array error_{}; +}; + +} // namespace ejoc::speaker + +extern "C" { + +uint32_t EJOC_CALL ejoc_speaker_layout_channel_count(const uint32_t speaker_bitfield) { + const auto* layout = ejoc::speaker_tables::find_layout(speaker_bitfield); + return layout ? layout->channel_count : 0; +} + +ejoc_speaker_renderer_handle EJOC_CALL ejoc_speaker_renderer_create( + const uint32_t speaker_bitfield) { + const auto* layout = ejoc::speaker_tables::find_layout(speaker_bitfield); + if (!layout) { + return nullptr; + } + return new (std::nothrow) ejoc::speaker::Renderer(layout); +} + +void EJOC_CALL ejoc_speaker_renderer_destroy(ejoc_speaker_renderer_handle handle) { + delete static_cast(handle); +} + +int EJOC_CALL ejoc_speaker_renderer_reset(ejoc_speaker_renderer_handle handle) { + if (!handle) { + return -1; + } + return static_cast(handle)->reset(); +} + +const char* EJOC_CALL ejoc_speaker_renderer_last_error(ejoc_speaker_renderer_handle handle) { + if (!handle) { + return "speaker renderer handle is null"; + } + return static_cast(handle)->last_error(); +} + +int EJOC_CALL ejoc_speaker_renderer_process( + ejoc_speaker_renderer_handle handle, + const float* objects16_interleaved, + const uint32_t sample_count, + const uint32_t metadata_count, + const uint32_t* metadata_offsets, + const uint32_t* ramp_durations, + const uint16_t* positions_q15, + const uint8_t* region_indices, + const uint8_t* height_enabled, + const double* object_gains, + double* output_interleaved) { + if (!handle) { + return -1; + } + return static_cast(handle)->process( + objects16_interleaved, sample_count, metadata_count, + metadata_offsets, ramp_durations, positions_q15, + region_indices, height_enabled, object_gains, output_interleaved); +} + +} // extern "C" diff --git a/src/speaker/speaker_step.cpp b/src/speaker/speaker_step.cpp new file mode 100644 index 0000000..58f99a7 --- /dev/null +++ b/src/speaker/speaker_step.cpp @@ -0,0 +1,62 @@ +#include "speaker/speaker_step.h" + +#include + +namespace joc::speaker { + +Status step(SpeakerStep* context, const std::vector& objects16_planar, + const oamd::OamdUpdate* update, std::string* error) { + if (context == nullptr || context->handle == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kRender, "speaker renderer is not open"); + } + if (objects16_planar.size() != + static_cast(JOC_OUTPUT_CHANNELS) * JOC_FRAME_SAMPLES) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kRender, + "objects16 must be [16][1536]"); + } + context->interleaved.assign(static_cast(JOC_FRAME_SAMPLES) * JOC_OUTPUT_CHANNELS, + 0.0f); + for (std::size_t n = 0; n < JOC_FRAME_SAMPLES; ++n) { + for (std::size_t c = 0; c < JOC_OUTPUT_CHANNELS; ++c) { + context->interleaved[n * JOC_OUTPUT_CHANNELS + c] = + objects16_planar[c * JOC_FRAME_SAMPLES + n]; + } + } + context->output.assign( + static_cast(JOC_FRAME_SAMPLES) * context->layout.channel_count, 0.0); + + context->last_had_payload = update != nullptr; + std::uint32_t ramp = 0; + if (update != nullptr) { + context->state.apply(*update); + ramp = update->ramp_duration_samples; + context->last_block_offset = update->block_offset_samples; + context->last_ramp_duration = update->ramp_duration_samples; + context->last_object_count = update->object_count; + } + + std::uint16_t positions[oamd::kObjects][3] = {}; + context->state.object_positions_q15(positions); + // A frame without OAMD must not touch the gains at all (no event), otherwise a + // pending ramp would snap - matching the reference exactly. + const std::uint32_t event_count = context->last_had_payload ? 1u : 0u; + const std::uint32_t offset = context->metadata_offset; + const int result = ejoc_speaker_renderer_process( + context->handle, context->interleaved.data(), JOC_FRAME_SAMPLES, event_count, + event_count != 0u ? &offset : nullptr, event_count != 0u ? &ramp : nullptr, + event_count != 0u ? &positions[0][0] : nullptr, nullptr, nullptr, nullptr, + context->output.data()); + if (result != 0) { + const char* message = ejoc_speaker_renderer_last_error(context->handle); + const std::string text = + "ejoc_speaker_renderer_process failed (" + std::to_string(result) + "): " + + (message != nullptr ? message : "unknown"); + if (error != nullptr) { + *error = text; + } + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, text); + } + return Status::success(); +} + +} // namespace joc::speaker diff --git a/src/speaker/speaker_step.h b/src/speaker/speaker_step.h new file mode 100644 index 0000000..26ed6ce --- /dev/null +++ b/src/speaker/speaker_step.h @@ -0,0 +1,31 @@ + +#pragma once + +#include +#include +#include + +#include "eac3joc_core.h" +#include "foundation/status.h" +#include "oamd/oamd_parser.h" +#include "speaker/speaker_layout_lookup.h" + +namespace joc::speaker { + +struct SpeakerStep { + ejoc_speaker_renderer_handle handle = nullptr; + LayoutInfo layout{}; + oamd::OamdState state; + std::uint32_t metadata_offset = 1473; + std::vector interleaved; + std::vector output; + std::uint32_t last_block_offset = 0; + std::uint32_t last_ramp_duration = 0; + std::uint32_t last_object_count = 0; + bool last_had_payload = false; +}; + +Status step(SpeakerStep* context, const std::vector& objects16_planar, + const oamd::OamdUpdate* update, std::string* error); + +} // namespace joc::speaker diff --git a/src/stream/stream.cpp b/src/stream/stream.cpp new file mode 100644 index 0000000..37f8c79 --- /dev/null +++ b/src/stream/stream.cpp @@ -0,0 +1,348 @@ +#include "stream/stream.h" + +#include +#include +#include + +#include "adm/adm_metadata.h" +#include "foundation/status.h" +#include "hrtf/jochrtf.h" +#include "joc_bitstream/joc_parser.h" +#include "joc_core/objects16.h" + +namespace joc::stream { + +namespace { + +constexpr std::size_t kFrameSamples = JOC_FRAME_SAMPLES; +constexpr std::size_t kBedChannels = 6; +constexpr int kCoreChannels[5] = {0, 1, 2, 4, 5}; +constexpr int kLfeChannel = 3; + +} // namespace + +Stream::~Stream() { + if (rebuilder_ != nullptr) { + ejoc_renderer_destroy(rebuilder_); + rebuilder_ = nullptr; + } + if (speaker_.handle != nullptr) { + ejoc_speaker_renderer_destroy(speaker_.handle); + speaker_.handle = nullptr; + } +} + +void Stream::reset_state() { + reader_ = eac3::FrameReader(); + metadata_.clear(); + bed_pending_.clear(); + objects16_.clear(); + output_.clear(); + read_offset_ = 0; + info_ = Info(); + info_.output_channels = output_channels_; + if (rebuilder_ != nullptr) { + ejoc_renderer_reset(rebuilder_); + } + if (speaker_.handle != nullptr) { + ejoc_speaker_renderer_reset(speaker_.handle); + speaker_.state.reset(); + speaker_.output.clear(); + speaker_.last_had_payload = false; + } + if (binaural_ready_) { + binaural_.reset(); + } +} + +Status Stream::create(const Config& config) { + if (rebuilder_ != nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kRender, "stream already created"); + } + config_ = config; + if (config_.input > JOC_STREAM_IN_PCM_OBJECTS16 || + config_.output > JOC_STREAM_OUT_BINAURAL) { + return Status::fail(JOC_ERR_INVALID_CONFIG, stage::kRender, "unknown stream kind"); + } + if (config_.input == JOC_STREAM_IN_PCM_OBJECTS16 && + config_.output == JOC_STREAM_OUT_PCM_OBJECTS16) { + return Status::fail(JOC_ERR_INVALID_CONFIG, stage::kRender, + "objects16 input with objects16 output would do nothing"); + } + gain_ = static_cast(std::pow(10.0, config_.gain_db / 20.0)); + + if (config_.input == JOC_STREAM_IN_EAC3) { + rebuilder_ = ejoc_renderer_create(); + if (rebuilder_ == nullptr) { + return Status::fail(JOC_ERR_OUT_OF_MEMORY, stage::kDsp, "cannot create the JOC kernel"); + } + if (config_.native_threads != 0u) { + ejoc_renderer_set_threads(rebuilder_, config_.native_threads); + } + } + + if (config_.output == JOC_STREAM_OUT_SPEAKER) { + speaker_enabled_ = true; + if (!speaker::layout_by_name(config_.layout.c_str(), &speaker_.layout)) { + return Status::fail(JOC_ERR_LAYOUT_UNSUPPORTED, stage::kRender, + "unknown speaker layout: " + config_.layout); + } + speaker_.metadata_offset = config_.metadata_offset; + speaker_.handle = ejoc_speaker_renderer_create(speaker_.layout.speaker_bitfield); + if (speaker_.handle == nullptr) { + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kRender, + "cannot create the speaker renderer"); + } + output_channels_ = speaker_.layout.channel_count; + } else if (config_.output == JOC_STREAM_OUT_BINAURAL) { + binaural_enabled_ = true; + hrtf::Field field; + hrtf::Kernels kernels; + Status status = hrtf::load_jochrtf(config_.hrtf_path, &field); + if (status.ok()) { + status = config_.kernels_path.empty() + ? (kernels = hrtf::builtin_kernels(), Status::success()) + : hrtf::load_kernels(config_.kernels_path, &kernels); + } + binaural::Profile profile = binaural::Profile::Mid; + if (status.ok() && config_.binaural_mode == JOC_BINAURAL_NEAR) { + profile = binaural::Profile::Near; + } else if (status.ok() && config_.binaural_mode == JOC_BINAURAL_FAR) { + profile = binaural::Profile::Far; + } + if (status.ok()) { + status = binaural_.open(field, kernels, profile); + } + if (!status.ok()) { + return status; + } + binaural_ready_ = true; + output_channels_ = 2; + } else { + output_channels_ = JOC_OUTPUT_CHANNELS; + } + reset_state(); + return Status::success(); +} + +Status Stream::push_eac3(const std::uint8_t* data, std::size_t size, std::size_t* consumed) { + if (rebuilder_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kEmdf, "stream is not an E-AC-3 input"); + } + if (consumed != nullptr) { + *consumed = size; + } + if (data != nullptr && size != 0u) { + reader_.push(data, size); + info_.bytes_in += size; + } + for (;;) { + eac3::Frame frame; + const eac3::FrameReader::Next state = reader_.next(&frame); + if (state == eac3::FrameReader::Next::End) { + break; + } + if (state == eac3::FrameReader::Next::Fail) { + return Status::fail(reader_.error(), stage::kEac3, reader_.error_message()); + } + FrameMetadata entry; + emdf::Container container; + const Status parsed = + joc::parse_eac3_frame(frame.data, frame.size, &entry.params, &container, nullptr); + if (!parsed.ok()) { + return parsed; + } + if (const emdf::Payload* payload = container.find(emdf::kIdOamd)) { + std::vector bytes; + const Status extracted = + emdf::extract_payload_bytes(frame.data, frame.size, *payload, &bytes); + if (!extracted.ok()) { + return extracted; + } + const Status oamd = oamd::parse_id11(bytes.data(), bytes.size(), &entry.update); + if (!oamd.ok()) { + return oamd; + } + entry.has_update = true; + entry.outer_offset = static_cast(payload->sample_offset); + } + metadata_.push_back(entry); + } + return process_ready_frames(); +} + +Status Stream::push_bed(const float* interleaved6, std::size_t samples, std::size_t* consumed) { + if (rebuilder_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kDsp, "stream is not an E-AC-3 input"); + } + if (consumed != nullptr) { + *consumed = samples; + } + if (interleaved6 != nullptr && samples != 0u) { + bed_pending_.insert(bed_pending_.end(), interleaved6, + interleaved6 + samples * kBedChannels); + } + return process_ready_frames(); +} + +Status Stream::push_objects16(const float* planar16, std::size_t samples, std::size_t* consumed) { + if (consumed != nullptr) { + *consumed = samples; + } + if (planar16 == nullptr || samples == 0u) { + return Status::success(); + } + // Rendered immediately: the host has already done the JOC rebuild. + for (std::size_t offset = 0; offset < samples; offset += kFrameSamples) { + const std::size_t count = std::min(kFrameSamples, samples - offset); + std::vector frame(static_cast(JOC_OUTPUT_CHANNELS) * kFrameSamples, + 0.0f); + for (std::size_t channel = 0; channel < JOC_OUTPUT_CHANNELS; ++channel) { + std::memcpy(frame.data() + channel * kFrameSamples, + planar16 + channel * samples + offset, count * sizeof(float)); + } + ++info_.frames_in; + info_.samples_in += count; + const Status rendered = render_objects16(frame); + if (!rendered.ok()) { + return rendered; + } + if (count != kFrameSamples) { + break; // a partial frame is dropped; the host should push whole frames + } + } + return Status::success(); +} + +Status Stream::process_ready_frames() { + while (bed_pending_.size() / kBedChannels >= kFrameSamples && !metadata_.empty()) { + const FrameMetadata entry = metadata_.front(); + metadata_.pop_front(); + + std::vector bed5(static_cast(JOC_CORE_CHANNELS) * kFrameSamples, 0.0f); + std::vector lfe(kFrameSamples, 0.0f); + for (std::size_t sample = 0; sample < kFrameSamples; ++sample) { + for (std::size_t channel = 0; channel < JOC_CORE_CHANNELS; ++channel) { + bed5[channel * kFrameSamples + sample] = + bed_pending_[sample * kBedChannels + kCoreChannels[channel]]; + } + lfe[sample] = bed_pending_[sample * kBedChannels + kLfeChannel]; + } + bed_pending_.erase(bed_pending_.begin(), + bed_pending_.begin() + static_cast(kFrameSamples * + kBedChannels)); + + std::string error; + const Status rebuilt = joc::rebuild_objects16(rebuilder_, entry.params, bed5.data(), + lfe.data(), gain_, &objects16_, &error); + if (!rebuilt.ok()) { + return Status::fail(rebuilt.code(), stage::kDsp, error); + } + pending_metadata_ = entry; + const Status rendered = render_objects16(objects16_); + if (!rendered.ok()) { + return rendered; + } + ++info_.frames_in; + info_.samples_in += kFrameSamples; + } + return Status::success(); +} + +Status Stream::render_objects16(const std::vector& objects16) { + if (config_.output == JOC_STREAM_OUT_PCM_OBJECTS16) { + output_.insert(output_.end(), objects16.begin(), objects16.end()); + info_.frames_out++; + info_.samples_out += kFrameSamples; + return Status::success(); + } + if (speaker_enabled_) { + std::string error; + const Status stepped = + speaker::step(&speaker_, objects16, pending_metadata_.has_update + ? &pending_metadata_.update + : nullptr, + &error); + if (!stepped.ok()) { + return Status::fail(stepped.code(), stage::kRender, error); + } + for (const double value : speaker_.output) { + output_.push_back(static_cast(value)); + } + info_.frames_out++; + info_.samples_out += kFrameSamples; + return Status::success(); + } + + const Status submitted = + binaural_.submit_frame(objects16.data(), + pending_metadata_.has_update ? &pending_metadata_.update : nullptr, + static_cast(info_.frames_out), + pending_metadata_.outer_offset, + static_cast(config_.object_delay_samples)); + if (!submitted.ok()) { + return submitted; + } + std::vector produced; + binaural_.take_output(&produced); + for (const double value : produced) { + output_.push_back(static_cast(value)); + } + info_.frames_out++; + info_.samples_out += produced.size() / 2u; + return Status::success(); +} + +Status Stream::pull(float* destination, std::size_t capacity_samples, std::size_t* produced) { + if (produced != nullptr) { + *produced = 0; + } + if (destination == nullptr || produced == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, "null pull buffer"); + } + const std::size_t available = buffered_samples(); + const std::size_t count = std::min(capacity_samples, available); + if (count != 0u) { + std::memcpy(destination, output_.data() + read_offset_, + count * output_channels_ * sizeof(float)); + read_offset_ += count * output_channels_; + if (read_offset_ == output_.size()) { + output_.clear(); + read_offset_ = 0; + } else if (read_offset_ > (1u << 20)) { + output_.erase(output_.begin(), + output_.begin() + static_cast(read_offset_)); + read_offset_ = 0; + } + } + *produced = static_cast(count); + return Status::success(); +} + +Status Stream::flush() { + if (binaural_ready_) { + std::vector tail; + const Status drained = + binaural_.finish(binaural_.finish_capacity(config_.tail_seconds), &tail); + if (!drained.ok()) { + return drained; + } + for (const double value : tail) { + output_.push_back(static_cast(value)); + } + info_.samples_out += tail.size() / 2u; + } + info_.ended = 1; + return Status::success(); +} + +Status Stream::reset() { + if (rebuilder_ == nullptr && !speaker_enabled_ && !binaural_ready_ && + config_.input != JOC_STREAM_IN_PCM_OBJECTS16) { + return Status::fail(JOC_ERR_STATE, stage::kRender, "stream is not created"); + } + reset_state(); + return Status::success(); +} + +} // namespace joc::stream diff --git a/src/stream/stream.h b/src/stream/stream.h new file mode 100644 index 0000000..b765e3e --- /dev/null +++ b/src/stream/stream.h @@ -0,0 +1,101 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "binaural/binaural_runtime.h" +#include "eac3_transport/eac3_reader.h" +#include "foundation/status.h" +#include "joc_core.h" +#include "joc_stream.h" +#include "oamd/oamd_parser.h" +#include "speaker/speaker_step.h" + +namespace joc::stream { + +struct Config { + std::uint32_t input = JOC_STREAM_IN_EAC3; + std::uint32_t output = JOC_STREAM_OUT_PCM_OBJECTS16; + std::string layout; + std::uint32_t metadata_offset = 1473; + std::uint32_t binaural_mode = JOC_BINAURAL_MID; + std::string hrtf_path; + std::string kernels_path; + double tail_seconds = 5.0; + std::uint32_t object_delay_samples = 1473; + double gain_db = 0.0; + std::uint32_t native_threads = 0; +}; + +struct Info { + std::uint64_t frames_in = 0; + std::uint64_t frames_out = 0; + std::uint64_t samples_in = 0; + std::uint64_t samples_out = 0; + std::uint64_t bytes_in = 0; + std::uint64_t oamd_payloads = 0; + std::uint64_t oamd_transitions = 0; + std::uint32_t output_channels = 0; + std::uint32_t ended = 0; +}; + +// One frame's metadata, queued while the matching core PCM arrives. +struct FrameMetadata { + joc_frame_params params{}; + oamd::OamdUpdate update{}; + bool has_update = false; + std::int64_t outer_offset = 0; +}; + +class Stream { +public: + Stream() = default; + ~Stream(); + + Stream(const Stream&) = delete; + Stream& operator=(const Stream&) = delete; + + Status create(const Config& config); + Status push_eac3(const std::uint8_t* data, std::size_t size, std::size_t* consumed); + Status push_bed(const float* interleaved6, std::size_t samples, std::size_t* consumed); + Status push_objects16(const float* planar16, std::size_t samples, std::size_t* consumed); + Status pull(float* destination, std::size_t capacity_samples, std::size_t* produced); + Status flush(); + Status reset(); + + const Info& info() const { return info_; } + // Per-channel sample count, not the interleaved float count. + std::size_t buffered_samples() const { + return output_channels_ != 0u ? (output_.size() - read_offset_) / output_channels_ : 0u; + } + +private: + Status process_ready_frames(); + Status render_objects16(const std::vector& objects16); + void reset_state(); + + Config config_; + Info info_; + eac3::FrameReader reader_; + std::deque metadata_; + FrameMetadata pending_metadata_; + std::vector bed_pending_; + std::vector frame_copy_; + std::vector objects16_; + std::vector output_; + std::size_t read_offset_ = 0; + std::uint32_t output_channels_ = 0; + + ejoc_renderer_handle rebuilder_ = nullptr; + speaker::SpeakerStep speaker_; + binaural::SofaBinauralRuntime binaural_; + bool speaker_enabled_ = false; + bool binaural_enabled_ = false; + bool binaural_ready_ = false; + float gain_ = 1.0f; +}; + +} // namespace joc::stream diff --git a/src/task/task.cpp b/src/task/task.cpp new file mode 100644 index 0000000..e81eb9f --- /dev/null +++ b/src/task/task.cpp @@ -0,0 +1,1943 @@ +#include "task/task.h" +#include "foundation/fs_utf8.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "adm/adm_metadata.h" +#include "adm/adm_tracks.h" +#include "binaural/binaural_runtime.h" +#include "eac3_transport/eac3_reader.h" +#include "emdf/emdf_parser.h" +#include "foundation/sha256.h" +#include "hrtf/jochrtf.h" +#include "hrtf/rosella_model.h" +#include "hrtf/rosella_renderer.h" +#include "hrtf/sofa_cache.h" +#include "io/adm_writer.h" +#include "io/process.h" +#include "io/wav_writer.h" +#include "joc_bitstream/joc_parser.h" +#include "joc_core/objects16.h" +#include "oamd/oamd_parser.h" +#include "speaker/speaker_step.h" +#include "telemetry/event_bus.h" + +namespace joc::task { + +namespace { + +namespace fs = std::filesystem; +using Clock = std::chrono::steady_clock; + +constexpr std::size_t kBedFrameBytes = static_cast(JOC_FRAME_SAMPLES) * 6u * 4u; +constexpr std::size_t kReadChunk = 1u << 20; +constexpr double kDefaultTailThreshold = 1.0e-8; +constexpr int kCoreChannels[5] = {0, 1, 2, 4, 5}; +constexpr int kLfeChannel = 3; + +std::string lower(std::string text) { + for (char& c : text) { + if (c >= 'A' && c <= 'Z') { + c = static_cast(c - 'A' + 'a'); + } + } + return text; +} + +bool ends_with(const std::string& text, const char* suffix) { + const std::size_t length = std::strlen(suffix); + return text.size() >= length && text.compare(text.size() - length, length, suffix) == 0; +} + +std::string fmt(const char* format, ...) { + char buffer[512]; + va_list args; + va_start(args, format); + std::vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + return std::string(buffer); +} + +struct Settings { + std::string input_path; std::string ffmpeg_path = "ffmpeg"; + std::string bed_path; + std::string work_dir; + std::string output_path; + std::string layout; + std::string hrtf_path; + std::string kernels_path; + std::string hrtf_sofa_path; + std::string personalized_headphone_path; + std::string hrtf_cache_dir; + std::uint32_t hrtf_cache_policy = JOC_HRTF_CACHE_MEMORY; + double hrtf_radius_m = 1.0; + std::uint32_t operation = JOC_OP_ADM_BWF; + std::uint32_t output_format = JOC_FORMAT_FLOAT32; + std::uint32_t adm_binaural_mode = JOC_BINAURAL_MID; + std::uint32_t trajectory_mode = JOC_TRAJECTORY_COMPACT; + std::uint32_t object_delay_samples = 1473; + std::uint32_t speaker_metadata_offset = 1473; + std::uint32_t binaural_mode = JOC_BINAURAL_MID; + std::uint32_t progress_interval = 1000; + std::uint32_t native_threads = 0; + std::uint32_t flags = 0; + std::uint32_t clip_action = JOC_CLIP_ASK; + std::uint32_t print_metadata = 0; + std::string metadata_json_path; + bool metadata_only = false; + double gain_db = 0.0; + double tail_seconds = 5.0; + double tail_threshold = kDefaultTailThreshold; + double drc_scale = 0.0; + std::int32_t target_level = 0; + std::uint64_t duration_frames = 0; + const joc_cancel_token* cancel = nullptr; +}; + +Settings normalise(const joc_task_config& raw) { + Settings cfg; + if (raw.input_path != nullptr) { cfg.input_path = raw.input_path; } + if (raw.ffmpeg_path != nullptr && raw.ffmpeg_path[0] != '\0') { cfg.ffmpeg_path = raw.ffmpeg_path; } + if (raw.bed_path != nullptr) { cfg.bed_path = raw.bed_path; } + if (raw.work_dir != nullptr) { cfg.work_dir = raw.work_dir; } + if (raw.output_path != nullptr) { cfg.output_path = raw.output_path; } + if (raw.speaker_layout_name != nullptr) { cfg.layout = raw.speaker_layout_name; } + if (raw.hrtf_path != nullptr) { cfg.hrtf_path = raw.hrtf_path; } + if (raw.hrtf_sofa_path != nullptr) { cfg.hrtf_sofa_path = raw.hrtf_sofa_path; } + if (raw.personalized_headphone_path != nullptr) { + cfg.personalized_headphone_path = raw.personalized_headphone_path; + } + if (raw.hrtf_cache_dir != nullptr) { cfg.hrtf_cache_dir = raw.hrtf_cache_dir; } + cfg.hrtf_cache_policy = raw.hrtf_cache_policy; + cfg.hrtf_radius_m = raw.hrtf_radius_m; + if (raw.kernels_path != nullptr) { cfg.kernels_path = raw.kernels_path; } + cfg.operation = raw.operation; + cfg.output_format = raw.output_format; + cfg.flags = raw.flags; + cfg.clip_action = raw.clip_action; + cfg.print_metadata = raw.print_metadata; + cfg.metadata_only = (raw.flags & JOC_TASK_F_METADATA_ONLY) != 0u; + if (raw.metadata_json_path != nullptr) { cfg.metadata_json_path = raw.metadata_json_path; } + cfg.gain_db = raw.gain_db; + cfg.drc_scale = raw.eac3_drc_scale; + cfg.target_level = raw.eac3_target_level; + cfg.duration_frames = raw.duration_frames; + cfg.cancel = raw.cancel; + // config still produces the reference behaviour (plan 26.1). + if (raw.object_delay_samples != 0u) { cfg.object_delay_samples = raw.object_delay_samples; } + if (raw.speaker_metadata_offset != 0u) { + cfg.speaker_metadata_offset = raw.speaker_metadata_offset; + } + if (raw.progress_interval_frames != 0u) { cfg.progress_interval = raw.progress_interval_frames; } + if (raw.binaural_tail_seconds > 0.0) { cfg.tail_seconds = raw.binaural_tail_seconds; } + if (raw.binaural_tail_threshold > 0.0) { cfg.tail_threshold = raw.binaural_tail_threshold; } + if (raw.native_threads != 0u) { cfg.native_threads = raw.native_threads; } + if (raw.operation == JOC_OP_BINAURAL) { + cfg.binaural_mode = raw.binaural_mode != 0u ? raw.binaural_mode : JOC_BINAURAL_MID; + cfg.adm_binaural_mode = raw.adm_binaural_mode; + } else { + cfg.binaural_mode = raw.binaural_mode != 0u ? raw.binaural_mode : JOC_BINAURAL_MID; + cfg.adm_binaural_mode = + raw.adm_binaural_mode != 0u ? raw.adm_binaural_mode : JOC_BINAURAL_MID; + } + if (raw.trajectory_mode != 0u) { cfg.trajectory_mode = raw.trajectory_mode; } + return cfg; +} + +void add_issue(std::vector* issues, joc_error code, std::uint32_t severity, + const char* field, const std::string& message) { + if (issues == nullptr) { + return; + } + joc_validation_issue issue{}; + issue.code = code; + issue.severity = severity; + std::snprintf(issue.field, sizeof(issue.field), "%s", field); + std::snprintf(issue.message, sizeof(issue.message), "%s", message.c_str()); + issues->push_back(issue); +} + +bool cancelled(const Settings& cfg) { + return cfg.cancel != nullptr && joc_cancel_token_is_requested(cfg.cancel) != 0; +} + +std::string create_temp_dir(const Settings& cfg) { const fs::path base = cfg.work_dir.empty() ? fs::temp_directory_path() + : fs_utf8::to_path(cfg.work_dir); + const fs::path target = base / fmt("joc_task_%u", static_cast(std::random_device{}())); + std::error_code error; + fs::create_directories(target, error); + return fs_utf8::from_path(target); +} + +std::uint64_t count_frames(const std::string& path) { + std::ifstream input = fs_utf8::open_input(path); + if (!input) { + return 0; + } + ::joc::eac3::FrameReader reader; + std::vector chunk(kReadChunk); + std::uint64_t frames = 0; + bool done = false; + while (!done) { + input.read(chunk.data(), static_cast(chunk.size())); + const std::streamsize got = input.gcount(); + if (got > 0) { + reader.push(reinterpret_cast(chunk.data()), + static_cast(got)); + } else { + reader.finish(); + done = true; + } + for (;;) { + ::joc::eac3::Frame frame; + const ::joc::eac3::FrameReader::Next state = reader.next(&frame); + if (state == ::joc::eac3::FrameReader::Next::Ok) { + ++frames; + continue; + } + if (state == ::joc::eac3::FrameReader::Next::Fail) { + return frames; + } + break; + } + } + return frames; +} + +bool stdin_is_interactive() { +#ifdef _WIN32 + return _isatty(_fileno(stdin)) != 0; +#else + return isatty(fileno(stdin)) != 0; +#endif +} + +// Rendered PCM is spooled to a float32 file so the output format can be decided +// once the peak is known, which is what makes --clip-action possible; the +// reference CLI spools for the same reason. +class PcmSpool { +public: + ~PcmSpool() { close(); } + + Status open(const std::string& path, std::uint32_t channels, bool trim, double threshold) { + path_ = path; + channels_ = channels; + trim_ = trim; + threshold_ = threshold; + // A spool left behind by a killed run would otherwise be appended to by the + // "wb+" open below; only this exact path is ever removed. + if (fs_utf8::exists(path)) { + std::error_code ignored; + std::filesystem::remove(fs_utf8::to_path(path), ignored); + } + file_ = fs_utf8::fopen_spool(path); + if (file_ == nullptr) { + return Status::fail(JOC_ERR_OUTPUT_OPEN, stage::kOutput, "cannot open " + path); + } + return Status::success(); + } + + // The declared sample budget; write() refuses to grow past it. + void set_limit(std::uint64_t frames) { limit_frames_ = frames; } + + Status write(const float* interleaved, std::size_t frames) { + if (frames == 0u || file_ == nullptr) { + return Status::success(); + } + // The declared budget is a hard stop: a renderer that overproduces must fail + // here, not after writing an unbounded spool. + if (limit_frames_ != 0u && position_ + frames > limit_frames_) { + return Status::fail(JOC_ERR_RENDER_FAILED, stage::kOutput, + "binaural output exceeded its declared budget: " + + std::to_string(position_ + frames) + " > " + + std::to_string(limit_frames_) + " samples"); + } + for (std::size_t index = 0; index < frames; ++index) { + double per_sample = 0.0; + for (std::uint32_t channel = 0; channel < channels_; ++channel) { + const double value = + std::abs(static_cast(interleaved[index * channels_ + channel])); + per_sample = std::max(per_sample, value); + } + peak_ = std::max(peak_, per_sample); + if (per_sample > 1.0) { + ++clipped_; + } + if (trim_ && per_sample > threshold_) { + last_above_ = position_ + index; + any_above_ = true; + } + } + const std::size_t count = frames * channels_; + if (std::fwrite(interleaved, sizeof(float), count, file_) != count) { + return Status::fail(JOC_ERR_OUTPUT_WRITE, stage::kOutput, "cannot write the PCM spool"); + } + position_ += frames; + return Status::success(); + } + + // Trailing near-silence is dropped, but never below `minimum` frames. + std::uint64_t kept(std::uint64_t minimum) const { + if (!trim_) { + return position_; + } + const std::uint64_t last = any_above_ ? last_above_ + 1u : 0u; + return std::min(position_, std::max(minimum, last)); + } + + // `report` is called with (frames written so far, total) so a long finalize is + // visibly alive instead of looking hung. + Status copy_to(io::WavWriter* writer, std::uint64_t keep, + const std::function& report = {}) { + if (file_ == nullptr) { + return Status::fail(JOC_ERR_STATE, stage::kOutput, "the PCM spool is closed"); + } + std::fflush(file_); + if (std::fseek(file_, 0, SEEK_SET) != 0) { + return Status::fail(JOC_ERR_IO, stage::kOutput, "cannot rewind the PCM spool"); + } + constexpr std::size_t kBlockFrames = 4096; + std::vector block(kBlockFrames * channels_); + std::vector converted(kBlockFrames * channels_); + std::uint64_t remaining = keep; + while (remaining > 0u) { + const std::size_t frames = + static_cast(std::min(remaining, kBlockFrames)); + const std::size_t count = frames * channels_; + if (std::fread(block.data(), sizeof(float), count, file_) != count) { + return Status::fail(JOC_ERR_IO, stage::kOutput, "cannot read the PCM spool"); + } + for (std::size_t index = 0; index < count; ++index) { + converted[index] = static_cast(block[index]); + } + const Status written = writer->write(converted.data(), frames); + if (!written.ok()) { + return written; + } + remaining -= frames; + if (report) { + report(keep - remaining, keep); + } + } + return Status::success(); + } + + double peak() const { return peak_; } + std::uint64_t clipped() const { return clipped_; } + std::uint64_t position() const { return position_; } + + void close() { + if (file_ != nullptr) { + std::fclose(file_); + file_ = nullptr; + fs_utf8::remove(path_); + } + } + +private: + std::FILE* file_ = nullptr; + std::string path_; + std::uint32_t channels_ = 0; + bool trim_ = false; + double threshold_ = kDefaultTailThreshold; + double peak_ = 0.0; + std::uint64_t clipped_ = 0; + std::uint64_t position_ = 0; + std::uint64_t last_above_ = 0; + std::uint64_t limit_frames_ = 0; + bool any_above_ = false; +}; + +// Mirrors the reference CLI's choose_pcm_output_format. +Status decide_output_format(const Settings& cfg, telemetry::EventBus* bus, double peak, + std::uint64_t clipped, std::uint32_t* actual) { + *actual = cfg.output_format; + if (cfg.output_format != JOC_FORMAT_PCM24 || clipped == 0u) { + return Status::success(); + } + const std::string notice = + fmt("[clip] int24 将发生削波:peak=%.9g,超出 [-1,1] 的样本值=%llu", peak, + static_cast(clipped)); + std::fprintf(stderr, "%s\n", notice.c_str()); + bus->warning(notice); + std::uint32_t action = cfg.clip_action; + if (action == JOC_CLIP_ASK) { + if (!stdin_is_interactive()) { + return Status::fail(JOC_ERR_OUTPUT_CLIP_ABORT, stage::kOutput, + "检测到 int24 削波,但当前不是交互终端;请使用 " + "--clip-action continue、--clip-action float32 或 " + "--clip-action abort"); + } + for (;;) { + std::fputs("继续写 int24 并截断 [i] / 改为 float32 [f,默认] / 取消 [a]:", stderr); + std::fflush(stderr); + char line[64] = {0}; + if (std::fgets(line, sizeof(line), stdin) == nullptr) { + return Status::fail(JOC_ERR_OUTPUT_CLIP_ABORT, stage::kOutput, + "用户因 int24 削波取消输出"); + } + std::string answer(line); + while (!answer.empty() && (answer.back() == '\n' || answer.back() == '\r' || + answer.back() == ' ')) { + answer.pop_back(); + } + for (char& character : answer) { + character = static_cast(std::tolower(static_cast(character))); + } + if (answer.empty() || answer == "f" || answer == "float" || answer == "float32") { + action = JOC_CLIP_FLOAT32; + break; + } + if (answer == "i" || answer == "int" || answer == "int24" || answer == "c" || + answer == "continue") { + action = JOC_CLIP_CONTINUE; + break; + } + if (answer == "a" || answer == "abort" || answer == "q" || answer == "quit" || + answer == "n" || answer == "no") { + action = JOC_CLIP_ABORT; + break; + } + std::fputs("请输入 i、f 或 a。\n", stderr); + } + } + if (action == JOC_CLIP_CONTINUE) { + std::fputs("[clip] 将继续写 int24,超范围值会截断到 [-1,1]。\n", stdout); + *actual = JOC_FORMAT_PCM24; + return Status::success(); + } + if (action == JOC_CLIP_FLOAT32) { + std::fputs("[clip] 已切换为 float32 WAV,不执行截断。\n", stdout); + *actual = JOC_FORMAT_FLOAT32; + return Status::success(); + } + if (action == JOC_CLIP_ABORT) { + return Status::fail(JOC_ERR_OUTPUT_CLIP_ABORT, stage::kOutput, + "用户因 int24 削波取消输出"); + } + return Status::fail(JOC_ERR_INVALID_CONFIG, stage::kOutput, "unknown clip action"); +} + +std::string json_escape(const std::string& text) { + std::string out; + out.reserve(text.size() + 8u); + for (const char character : text) { + switch (character) { + case '"': out += "\\\""; break; + case '\\': out += "\\\\"; break; + case '\n': out += "\\n"; break; + case '\r': out += "\\r"; break; + case '\t': out += "\\t"; break; + default: + if (static_cast(character) < 0x20u) { + out += fmt("\\u%04x", static_cast(character)); + } else { + out.push_back(character); + } + } + } + return out; +} + +// Parses the bitstream without decoding or rendering: --metadata-only and the +// diagnostic metadata reports. +Status report_metadata(const Settings& cfg, telemetry::EventBus* bus, const std::string& eac3_path, + std::uint64_t total_frames) { + std::ifstream input = fs_utf8::open_input(eac3_path); + if (!input) { + return Status::fail(JOC_ERR_INPUT_NOT_FOUND, stage::kEac3, + "cannot open the E-AC-3 stream: " + eac3_path); + } + ::joc::eac3::FrameReader reader; + std::vector chunk(kReadChunk); + std::vector rows; + std::uint64_t frames = 0; + std::uint64_t oamd_payloads = 0; + std::uint64_t objects_total = 0; + std::uint32_t objects_min = 0xFFFFFFFFu; + std::uint32_t objects_max = 0u; + double clipgain_min = 0.0; + double clipgain_max = 0.0; + bool stream_done = false; + Status failure = Status::success(); + while (!stream_done && frames < total_frames) { + input.read(chunk.data(), static_cast(chunk.size())); + const std::streamsize got = input.gcount(); + if (got > 0) { + reader.push(reinterpret_cast(chunk.data()), + static_cast(got)); + } else { + reader.finish(); + stream_done = true; + } + for (;;) { + ::joc::eac3::Frame frame; + const ::joc::eac3::FrameReader::Next state = reader.next(&frame); + if (state == ::joc::eac3::FrameReader::Next::End) { + break; + } + if (state == ::joc::eac3::FrameReader::Next::Fail) { + return Status::fail(reader.error(), stage::kEac3, reader.error_message()); + } + if (frames >= total_frames) { + stream_done = true; + break; + } + joc_frame_params params{}; + ::joc::emdf::Container container; + const Status parsed = ::joc::joc::parse_eac3_frame(frame.data, frame.size, ¶ms, + &container, nullptr); + if (!parsed.ok()) { + return Status::fail(parsed.code(), parsed.stage(), + "frame " + std::to_string(frames) + ": " + parsed.message()); + } + std::uint32_t oamd_objects = 0; + std::uint32_t oamd_updates = 0; + if (const ::joc::emdf::Payload* payload = container.find(::joc::emdf::kIdOamd)) { + std::vector bytes; + const Status extracted = + ::joc::emdf::extract_payload_bytes(frame.data, frame.size, *payload, &bytes); + if (!extracted.ok()) { + return Status::fail(extracted.code(), extracted.stage(), extracted.message()); + } + ::joc::oamd::OamdUpdate update; + const Status oamd = ::joc::oamd::parse_id11(bytes.data(), bytes.size(), &update); + if (!oamd.ok()) { + return Status::fail(oamd.code(), oamd.stage(), + "frame " + std::to_string(frames) + ": " + oamd.message()); + } + ++oamd_payloads; + oamd_updates = update.object_count; + oamd_objects = update.object_count; + } + objects_total += params.n_objects; + objects_min = std::min(objects_min, static_cast(params.n_objects)); + objects_max = std::max(objects_max, static_cast(params.n_objects)); + if (frames == 0u) { + clipgain_min = params.clipgain; + clipgain_max = params.clipgain; + } else { + clipgain_min = std::min(clipgain_min, params.clipgain); + clipgain_max = std::max(clipgain_max, params.clipgain); + } + if (cfg.print_metadata >= 2u) { + rows.push_back(fmt("frame %6llu: bytes=%5u containers=%u objects=%u clipgain=%.9g " + "oamd=%s(%u updates)", + static_cast(frames), frame.size, + static_cast(container.payload_count), + static_cast(params.n_objects), params.clipgain, + oamd_objects != 0u ? "yes" : "no", oamd_updates)); + } + ++frames; + } + } + if (cfg.print_metadata >= 2u) { + for (const std::string& row : rows) { + std::printf("%s\n", row.c_str()); + } + } + const double mean_objects = frames != 0u + ? static_cast(objects_total) / static_cast(frames) + : 0.0; + if (cfg.print_metadata >= 1u) { + std::printf("metadata summary: frames=%llu objects(min/mean/max)=%u/%.3f/%u " + "clipgain=%.9g..%.9g oamd_payloads=%llu\n", + static_cast(frames), + objects_min == 0xFFFFFFFFu ? 0u : objects_min, mean_objects, objects_max, + clipgain_min, clipgain_max, + static_cast(oamd_payloads)); + } + if (!cfg.metadata_json_path.empty()) { + std::string json = fmt( + "{\n \"input\": \"%s\",\n \"frames\": %llu,\n \"objects_min\": %u,\n" + " \"objects_mean\": %.6f,\n \"objects_max\": %u,\n \"clipgain_min\": %.9g,\n" + " \"clipgain_max\": %.9g,\n \"oamd_payloads\": %llu\n}\n", + json_escape(cfg.input_path).c_str(), static_cast(frames), + objects_min == 0xFFFFFFFFu ? 0u : objects_min, mean_objects, objects_max, + clipgain_min, clipgain_max, static_cast(oamd_payloads)); + std::ofstream output = fs_utf8::open_output(cfg.metadata_json_path); + if (!output) { + return Status::fail(JOC_ERR_OUTPUT_OPEN, stage::kOutput, + "cannot write " + cfg.metadata_json_path); + } + output << json; + } + bus->emit(JOC_EV_METADATA_INDEXED, JOC_STAGE_METADATA, JOC_LOG_INFO, + fmt("metadata: %llu frames, oamd payloads %llu", + static_cast(frames), + static_cast(oamd_payloads))); + std::fflush(stdout); + return failure; +} + +class BedSource { +public: + bool open(const std::string& path) { + file_.open(path, std::ios::binary); + return static_cast(file_); + } + + bool read_frame(std::uint64_t index, std::vector* bed5, std::vector* lfe) { + bed5->assign(static_cast(JOC_CORE_CHANNELS) * JOC_FRAME_SAMPLES, 0.0f); + lfe->assign(JOC_FRAME_SAMPLES, 0.0f); + file_.clear(); + file_.seekg(static_cast(index * kBedFrameBytes), std::ios::beg); + std::vector interleaved(static_cast(JOC_FRAME_SAMPLES) * 6u); + file_.read(reinterpret_cast(interleaved.data()), + static_cast(interleaved.size() * sizeof(float))); + if (file_.gcount() != static_cast(interleaved.size() * sizeof(float))) { + return false; + } + for (std::size_t n = 0; n < JOC_FRAME_SAMPLES; ++n) { + for (std::size_t c = 0; c < JOC_CORE_CHANNELS; ++c) { + (*bed5)[c * JOC_FRAME_SAMPLES + n] = interleaved[n * 6u + kCoreChannels[c]]; + } + (*lfe)[n] = interleaved[n * 6u + kLfeChannel]; + } + return true; + } + +private: + std::ifstream file_; +}; + +// --------------------------------------------------------------------------- +// Overlapped frame pipeline +// +// The frame loop used to run its three stages back to back on the calling +// thread: read + decode + JOC rebuild, then the DSP, then the write. Only the +// DSP is long, so the other two were pure waiting time on the critical path. +// The same three stages now run on three threads and hand frames over through +// two small bounded rings: +// +// producer thread : E-AC-3 read -> core PCM read -> JOC rebuild (t_render) +// calling thread : speaker / binaural DSP, events, progress (t_render_dsp) +// writer thread : spool / ADM BWF / objects16 intermediate (t_write) +// +// No stage work changed. The DSP still consumes frames in strictly increasing +// order on one thread, the writer still writes them in that order, and every +// stage sees the same input it saw before, so the produced bytes are the bytes +// the serial loop produced. What did change is the order of the stages in time +// -- and therefore the error handling, which now has to arbitrate between +// stages that fail at different moments. The rule is the serial loop's rule: +// the failure of the lowest frame index wins, ties broken by stage order. +// --------------------------------------------------------------------------- + +// Frames in flight in the bitstream ring. The DSP does not consume at a +// constant rate: the Rosella runtime renders in 64-frame chunks, so one frame in +// 64 costs ~115 ms while the other 63 are nearly free. A ring smaller than a +// chunk starves the DSP during the cheap frames -- measured: with 3 slots the +// overlap collapsed to zero (the producer had to rebuild every frame on demand +// at 0.41 ms against a DSP that wanted them at 0.04 ms). One chunk of slack +// lets the bitstream stage do its work inside the render burst instead. This is +// the only unbounded-looking number here: 64 x 98 KB ~ 6.3 MB, independent of +// the length of the file. +constexpr std::size_t kBitstreamRingDepth = 64; + +// The output stage is neither bursty nor slow (it is a buffered write per +// frame), so its ring only has to cover the writer's scheduling latency. +constexpr std::size_t kOutputRingDepth = 4; + +// One frame on its way from the bitstream stage to the DSP. +struct JocJob { + std::uint64_t index = 0; + std::vector objects16; // channel-major, 16 x 1536 + oamd::OamdUpdate update; + bool has_update = false; + std::int64_t outer_offset = 0; + unsigned objects = 0; // for the per-frame trace event + double clipgain = 0.0; +}; + +// One rendered frame on its way to disk. It owns everything the writer needs, +// so the DSP thread can move on while the writer is still on this frame. +struct OutputJob { + std::uint64_t index = 0; + std::vector dsp; // interleaved render, the spool payload + std::size_t dsp_frames = 0; + std::vector objects16; // only when the ADM writer or --keep-raw needs it + oamd::OamdUpdate update; + bool has_update = false; + std::int64_t outer_offset = 0; +}; + +// One producer, one consumer, fixed capacity. Payloads are handed over by +// swapping, so both sides keep a buffer and the steady state allocates nothing. +// The producer blocks while the ring is full, which is what makes the buffering +// bounded; the consumer blocks while it is empty. +template +class FrameRing { +public: + explicit FrameRing(std::size_t capacity) : slots_(capacity == 0u ? 1u : capacity) {} + + FrameRing(const FrameRing&) = delete; + FrameRing& operator=(const FrameRing&) = delete; + + // Producer side. False once the peer stopped (failure, cancellation or the + // normal end), in which case the payload is left untouched. + bool push(Payload* payload) { + std::unique_lock lock(mutex_); + has_space_.wait(lock, [this] { return count_ < slots_.size() || closed_; }); + if (closed_) { + return false; + } + std::swap(slots_[(head_ + count_) % slots_.size()], *payload); + ++count_; + has_item_.notify_one(); + return true; + } + + // Consumer side. False once the producer closed the ring and it drained, + // or once the ring was aborted. + bool pop(Payload* payload) { + std::unique_lock lock(mutex_); + has_item_.wait(lock, [this] { return count_ != 0u || closed_; }); + if (count_ == 0u || aborted_) { + return false; + } + std::swap(slots_[head_], *payload); + head_ = (head_ + 1u) % slots_.size(); + --count_; + has_space_.notify_one(); + return true; + } + + // Normal end: drain what is queued, then stop. + void close() { + std::lock_guard lock(mutex_); + closed_ = true; + has_item_.notify_all(); + has_space_.notify_all(); + } + + // Failure or cancellation: stop now and drop what is queued, so a peer + // blocked in push() or pop() is released immediately. + void abort() { + std::lock_guard lock(mutex_); + closed_ = true; + aborted_ = true; + has_item_.notify_all(); + has_space_.notify_all(); + } + +private: + std::mutex mutex_; + std::condition_variable has_item_; + std::condition_variable has_space_; + std::vector slots_; + std::size_t head_ = 0; + std::size_t count_ = 0; + bool closed_ = false; + bool aborted_ = false; +}; + +// The order the serial loop would have met two failures at the same frame. +enum class StageRank : int { kJoc = 0, kDsp = 1, kWrite = 2 }; + +struct StageFailure { + bool valid = false; + std::uint64_t frame = 0; + int rank = 0; + joc_error code = JOC_OK; + std::string stage_text; + std::string message; +}; + +// Where each stage leaves the failure that stopped it. The serial loop always +// reported the failure of the lowest frame index, so that is the one recorded +// and the one every thread reports, whichever stage happens to notice first. +class FailureBoard { +public: + void record(std::uint64_t frame, StageRank rank, joc_error code, + const std::string& stage_text, const std::string& message) { + std::lock_guard lock(mutex_); + if (failure_.valid && + (failure_.frame < frame || + (failure_.frame == frame && failure_.rank <= static_cast(rank)))) { + return; + } + failure_.valid = true; + failure_.frame = frame; + failure_.rank = static_cast(rank); + failure_.code = code; + failure_.stage_text = stage_text; + failure_.message = message; + } + + // The earliest failure recorded so far, if there is one. + bool earliest(StageFailure* out) const { + std::lock_guard lock(mutex_); + if (!failure_.valid) { + return false; + } + *out = failure_; + return true; + } + + // True when a stage already failed on a frame the caller has not reached. + // The serial loop would have stopped there, so the caller stops too. + bool before(std::uint64_t frame, StageFailure* out) const { + std::lock_guard lock(mutex_); + if (!failure_.valid || failure_.frame >= frame) { + return false; + } + *out = failure_; + return true; + } + +private: + mutable std::mutex mutex_; + StageFailure failure_; +}; + +// The stop flag every stage polls between frames. A plain bool behind a mutex +// rather than an atomic: the stages touch it once per frame, so the lock costs +// nothing next to a frame of DSP. +class StopFlag { +public: + void request() { + std::lock_guard lock(mutex_); + stop_ = true; + } + + bool requested() const { + std::lock_guard lock(mutex_); + return stop_; + } + +private: + mutable std::mutex mutex_; + bool stop_ = false; +}; + +// The serial loop emitted its progress line after that frame's write, so a +// progress boundary waits for the writer to reach the frame first: the line -- +// and any write failure hiding behind it -- is then exactly the serial one. +// The wait costs one handoff every `progress_interval` frames. +class WriteProgress { +public: + void complete(std::uint64_t frame) { + std::lock_guard lock(mutex_); + completed_ = std::max(completed_, frame + 1u); + cv_.notify_all(); + } + + // The writer is done: nobody will complete another frame. + void finish() { + std::lock_guard lock(mutex_); + finished_ = true; + cv_.notify_all(); + } + + void wait_for(std::uint64_t frame) { + std::unique_lock lock(mutex_); + cv_.wait(lock, [this, frame] { return finished_ || completed_ > frame; }); + } + +private: + std::mutex mutex_; + std::condition_variable cv_; + std::uint64_t completed_ = 0; // frames written so far + bool finished_ = false; +}; + +// Wakes and joins both stage threads. It is declared after every resource the +// threads touch, so on every exit path -- normal end, early return, failure, +// cancellation or an exception out of the frame loop -- the threads are joined +// before those resources are destroyed. Without it, a throwing exit would +// destroy a joinable std::thread and terminate. +class StageJoiner { +public: + StageJoiner(FrameRing* joc_ring, FrameRing* output_ring, StopFlag* stop, + std::thread* producer, std::thread* writer) + : joc_ring_(joc_ring), output_ring_(output_ring), stop_(stop), producer_(producer), + writer_(writer) {} + + ~StageJoiner() { shutdown(true); } + + StageJoiner(const StageJoiner&) = delete; + StageJoiner& operator=(const StageJoiner&) = delete; + + // `discard` drops whatever is still queued (failure, cancellation); without + // it the writer drains the ring first, which is what the normal end wants. + void shutdown(bool discard) { + stop_->request(); + if (discard) { + joc_ring_->abort(); + output_ring_->abort(); + } else { + joc_ring_->close(); + output_ring_->close(); + } + if (producer_->joinable()) { + producer_->join(); + } + if (writer_->joinable()) { + writer_->join(); + } + } + +private: + FrameRing* joc_ring_; + FrameRing* output_ring_; + StopFlag* stop_; + std::thread* producer_; + std::thread* writer_; +}; + +} // namespace + +Status validate(const joc_task_config& raw, std::vector* issues, + std::uint32_t* error_count) { + const Settings cfg = normalise(raw); + std::uint32_t errors = 0; + auto fail = [&](joc_error code, const char* field, const std::string& message) { + add_issue(issues, code, 2u, field, message); + ++errors; + }; + auto warn = [&](joc_error code, const char* field, const std::string& message) { + add_issue(issues, code, 1u, field, message); + }; + + if (cfg.input_path.empty()) { + fail(JOC_ERR_INVALID_CONFIG, "input_path", "an input path is required"); + } else if (!fs_utf8::exists(cfg.input_path)) { + fail(JOC_ERR_INPUT_NOT_FOUND, "input_path", "input not found: " + cfg.input_path); + } + if (cfg.output_path.empty()) { + fail(JOC_ERR_INVALID_CONFIG, "output_path", "an output path is required"); + } + if (cfg.operation > JOC_OP_BINAURAL) { + fail(JOC_ERR_INVALID_CONFIG, "operation", "operation must be ADM_BWF, SPEAKER or BINAURAL"); + } + if (cfg.output_format > JOC_FORMAT_PCM24) { + fail(JOC_ERR_INVALID_CONFIG, "output_format", "output_format must be FLOAT32 or PCM24"); + } + if (cfg.clip_action > JOC_CLIP_ABORT) { + fail(JOC_ERR_INVALID_CONFIG, "clip_action", "clip_action must be ask/continue/float32/abort"); + } + if (!std::isfinite(cfg.tail_threshold) || cfg.tail_threshold < 0.0) { + fail(JOC_ERR_INVALID_CONFIG, "binaural_tail_threshold", + "binaural_tail_threshold must be a finite non-negative value"); + } + if (cfg.operation == JOC_OP_ADM_BWF) { + // ADM BWF is inherently 24-bit and this mode has no format option, so a + // float32 request is simply unused: not a warning, just the mode's nature. + if (cfg.output_format > JOC_FORMAT_PCM24) { + fail(JOC_ERR_INVALID_CONFIG, "output_format", + "output_format must be FLOAT32 or PCM24"); + } + } + if (cfg.operation == JOC_OP_SPEAKER) { + ::joc::speaker::LayoutInfo layout; + if (cfg.layout.empty()) { + fail(JOC_ERR_INVALID_CONFIG, "speaker_layout_name", + "a speaker layout is required for the speaker operation"); + } else if (!::joc::speaker::layout_by_name(cfg.layout.c_str(), &layout)) { + fail(JOC_ERR_LAYOUT_UNSUPPORTED, "speaker_layout_name", + "unknown speaker layout: " + cfg.layout); + } + } + if (cfg.operation == JOC_OP_BINAURAL) { + if (cfg.hrtf_path.empty() && cfg.hrtf_sofa_path.empty() && + cfg.personalized_headphone_path.empty()) { + fail(JOC_ERR_INVALID_CONFIG, "hrtf_path", + "a SOFA input, a Rosella model or a compiled HRTF (.jochrtf) is required for the " + "binaural operation"); + } else if (!cfg.personalized_headphone_path.empty() && + !fs_utf8::exists(cfg.personalized_headphone_path)) { + fail(JOC_ERR_HRTF_NOT_FOUND, "personalized_headphone_path", + "personalized headphone model not found: " + cfg.personalized_headphone_path); + } else if (!cfg.hrtf_sofa_path.empty() && !fs_utf8::exists(cfg.hrtf_sofa_path)) { + fail(JOC_ERR_HRTF_NOT_FOUND, "hrtf_sofa_path", + "SOFA HRTF not found: " + cfg.hrtf_sofa_path); + } else if (cfg.hrtf_sofa_path.empty() && cfg.personalized_headphone_path.empty() && + !fs_utf8::exists(cfg.hrtf_path)) { + fail(JOC_ERR_HRTF_NOT_FOUND, "hrtf_path", "HRTF cache not found: " + cfg.hrtf_path); + } + if (!cfg.hrtf_sofa_path.empty()) { + if (cfg.hrtf_cache_policy > JOC_HRTF_CACHE_DISK) { + fail(JOC_ERR_INVALID_CONFIG, "hrtf_cache_policy", + "hrtf_cache_policy must be none, memory or disk"); + } + if (cfg.hrtf_cache_policy == JOC_HRTF_CACHE_DISK && cfg.hrtf_cache_dir.empty()) { + fail(JOC_ERR_INVALID_CONFIG, "hrtf_cache_dir", + "the disk cache policy needs a cache directory"); + } + if (!std::isfinite(cfg.hrtf_radius_m) || cfg.hrtf_radius_m <= 0.0) { + fail(JOC_ERR_INVALID_CONFIG, "hrtf_radius_m", + "hrtf_radius_m must be positive and finite"); + } + } + // The filterbank tables are compiled in; a path is only a verification override. + if (!cfg.kernels_path.empty() && !fs_utf8::exists(cfg.kernels_path)) { + fail(JOC_ERR_HRTF_NOT_FOUND, "kernels_path", + "kernel tables not found: " + cfg.kernels_path); + } + if (cfg.binaural_mode == JOC_BINAURAL_OFF) { + fail(JOC_ERR_INVALID_CONFIG, "binaural_mode", + "binaural_mode off is only meaningful for ADM output"); + } + } + if (cfg.operation == JOC_OP_ADM_BWF) { + if (cfg.adm_binaural_mode > 4u) { + fail(JOC_ERR_INVALID_CONFIG, "adm_binaural_mode", + "adm binaural mode must be off/near/far/mid/unspecified"); + } + if (cfg.trajectory_mode > JOC_TRAJECTORY_DENSE64) { + fail(JOC_ERR_INVALID_CONFIG, "trajectory_mode", + "trajectory mode must be compact or dense64"); + } + } + if (!std::isfinite(cfg.gain_db) || cfg.gain_db < -200.0 || cfg.gain_db > 200.0) { + fail(JOC_ERR_INVALID_CONFIG, "gain_db", "gain_db must be a finite value in [-200, 200]"); + } + if (cfg.native_threads > 15u) { + warn(JOC_ERR_INVALID_CONFIG, "native_threads", + "native_threads is clamped to the 15 JOC objects"); + } + if (cfg.bed_path.empty() && !fs_utf8::exists(cfg.ffmpeg_path)) { + warn(JOC_ERR_LIBRARY_MISSING, "ffmpeg_path", + "bed PCM is not supplied, so ffmpeg must be reachable: " + cfg.ffmpeg_path); + } + if (error_count != nullptr) { + *error_count = errors; + } + return errors == 0 ? Status::success() + : Status::fail(JOC_ERR_INVALID_CONFIG, stage::kOutput, + std::to_string(errors) + " configuration error(s)"); +} + +Status run(const joc_task_config& raw, const joc_event_sink* sink, joc_task_result* out) { + const Settings cfg = normalise(raw); + const auto started = Clock::now(); + telemetry::EventBus bus(sink); + bus.emit(JOC_EV_TASK_STARTED, JOC_STAGE_INPUT, JOC_LOG_INFO, "task started"); + + if (out != nullptr) { + std::memset(out, 0, sizeof(*out)); + out->struct_size = sizeof(joc_task_result); + out->struct_version = JOC_TASK_RESULT_VERSION; + } + + std::vector issues; + std::uint32_t error_count = 0; + const Status validated = validate(raw, &issues, &error_count); + for (const joc_validation_issue& issue : issues) { + if (issue.severity >= 2u) { + bus.error(issue.code, issue.field, issue.message); + } else { + bus.warning(std::string(issue.field) + ": " + issue.message); + } + } + auto finalize_with_error = [&](joc_error code, const std::string& stage_text, + const std::string& message) -> Status { + bus.error(code, stage_text, message); + if (out != nullptr) { + out->status = JOC_TASK_FAILED; + out->error_code = static_cast(code); + std::snprintf(out->error_stage, sizeof(out->error_stage), "%s", stage_text.c_str()); + std::snprintf(out->error_message, sizeof(out->error_message), "%s", message.c_str()); + out->t_total = std::chrono::duration(Clock::now() - started).count(); + } + bus.emit(JOC_EV_TASK_FAILED, JOC_STAGE_DONE, JOC_LOG_ERROR, message, code); + return Status::fail(code, stage_text, message); + }; + if (!validated.ok()) { + return finalize_with_error(JOC_ERR_INVALID_CONFIG, "config", + issues.empty() ? validated.message() : issues.front().message); + } + + const auto decode_started = Clock::now(); + std::string temp_dir; + std::string eac3_path = cfg.input_path; + const std::string lowered = lower(cfg.input_path); + if (!ends_with(lowered, ".eac3") && !ends_with(lowered, ".ec3")) { + temp_dir = create_temp_dir(cfg); + eac3_path = temp_dir + "\\input.eac3"; + bus.stage(JOC_STAGE_INPUT, "extracting the E-AC-3 elementary stream"); + const io::ProcessResult extracted = [&] { + io::ProcessResult result; + run_process({cfg.ffmpeg_path, "-hide_banner", "-loglevel", "error", "-y", "-i", + cfg.input_path, "-map", "0:a:0", "-vn", "-c:a", "copy", "-f", "eac3", + eac3_path}, + &result); + return result; + }(); + if (!fs_utf8::exists(eac3_path)) { + return finalize_with_error(JOC_ERR_INPUT_FORMAT, "input", + "ffmpeg could not extract E-AC-3: " + + (extracted.output.empty() ? "no output" + : extracted.output)); + } + } + + std::string bed_path = cfg.bed_path; + if (bed_path.empty() && !cfg.metadata_only) { + if (temp_dir.empty()) { + temp_dir = create_temp_dir(cfg); + } + bed_path = temp_dir + "\\core51_f32le.raw"; + bus.stage(JOC_STAGE_DECODE, "decoding the 5.1 core PCM with ffmpeg"); + std::vector argv = {cfg.ffmpeg_path, "-hide_banner", "-loglevel", "error", "-y", + "-i", eac3_path}; + argv.insert(argv.end(), {"-map", "0:a:0", "-vn", "-ac", "6", "-ar", "48000", + "-c:a", "pcm_f32le", "-f", "f32le", bed_path}); + argv.insert(argv.begin() + 4, {"-drc_scale", fmt("%.10g", cfg.drc_scale)}); + if (cfg.target_level != 0) { + argv.insert(argv.begin() + 4, {"-target_level", std::to_string(cfg.target_level)}); + } + io::ProcessResult decoded; + const Status status = io::run_process(argv, &decoded); + if (!status.ok()) { + return finalize_with_error(JOC_ERR_INPUT_FORMAT, "decode", + "ffmpeg could not decode the core PCM: " + decoded.output); + } + } + if (!bed_path.empty() && !fs_utf8::exists(bed_path)) { + return finalize_with_error(JOC_ERR_INPUT_NOT_FOUND, "bed_path", + "core PCM not found: " + bed_path); + } + const double t_decode = std::chrono::duration(Clock::now() - decode_started).count(); + + std::uint64_t total_frames = count_frames(eac3_path); + if (total_frames == 0u) { + return finalize_with_error(JOC_ERR_INPUT_FORMAT, "input", "no E-AC-3 frames found"); + } + if (cfg.duration_frames != 0u && cfg.duration_frames < total_frames) { + total_frames = cfg.duration_frames; + } + bus.set_totals(total_frames, total_frames * static_cast(JOC_FRAME_SAMPLES)); + bus.emit(JOC_EV_INPUT_OPENED, JOC_STAGE_INPUT, JOC_LOG_INFO, "input: " + cfg.input_path); + bus.emit(JOC_EV_METADATA_INDEXED, JOC_STAGE_METADATA, JOC_LOG_INFO, + fmt("%llu frames, %.2f s", static_cast(total_frames), + static_cast(total_frames) * + static_cast(JOC_FRAME_SAMPLES) / 48000.0)); + + if (cfg.metadata_only || cfg.print_metadata != 0u || !cfg.metadata_json_path.empty()) { + const Status reported = report_metadata(cfg, &bus, eac3_path, total_frames); + if (!reported.ok()) { + return finalize_with_error(reported.code(), reported.stage(), reported.message()); + } + } + if (cfg.metadata_only) { + if (out != nullptr) { + out->status = JOC_TASK_OK; + out->input_frames = total_frames; + out->duration_sec = static_cast(total_frames) * + static_cast(JOC_FRAME_SAMPLES) / 48000.0; + out->t_decode_bed = t_decode; + out->t_total = std::chrono::duration(Clock::now() - started).count(); + } + if (!temp_dir.empty()) { + std::error_code ignored; + fs::remove_all(fs_utf8::to_path(temp_dir), ignored); + } + bus.emit(JOC_EV_TASK_COMPLETED, JOC_STAGE_DONE, JOC_LOG_INFO, + fmt("metadata only: %llu frames", + static_cast(total_frames))); + return Status::success(); + } + + const float gain = static_cast(std::pow(10.0, cfg.gain_db / 20.0)); + ejoc_renderer_handle rebuilder = ejoc_renderer_create(); + if (rebuilder == nullptr) { + return finalize_with_error(JOC_ERR_OUT_OF_MEMORY, "joc", "cannot create the JOC kernel"); + } + struct KernelGuard { + ejoc_renderer_handle handle; + ~KernelGuard() { ejoc_renderer_destroy(handle); } + } guard{rebuilder}; + if (cfg.native_threads != 0u) { + ejoc_renderer_set_threads(rebuilder, cfg.native_threads); + } + + ::joc::speaker::SpeakerStep speaker; + const bool speaker_enabled = cfg.operation == JOC_OP_SPEAKER; + if (speaker_enabled) { + if (!::joc::speaker::layout_by_name(cfg.layout.c_str(), &speaker.layout)) { + return finalize_with_error(JOC_ERR_LAYOUT_UNSUPPORTED, "speaker_layout_name", + "unknown speaker layout: " + cfg.layout); + } + speaker.metadata_offset = cfg.speaker_metadata_offset; + speaker.handle = ejoc_speaker_renderer_create(speaker.layout.speaker_bitfield); + if (speaker.handle == nullptr) { + return finalize_with_error(JOC_ERR_RENDER_FAILED, "render", + "cannot create the speaker renderer"); + } + bus.emit(JOC_EV_RENDERER_INITIALIZED, JOC_STAGE_RENDER, JOC_LOG_INFO, + fmt("speaker renderer: %s, %u channels", speaker.layout.name, + speaker.layout.channel_count)); + } + + ::joc::binaural::SofaBinauralRuntime binaural; + ::joc::hrtf::RosellaRuntime rosella; + const bool binaural_enabled = cfg.operation == JOC_OP_BINAURAL; + const bool rosella_enabled = !cfg.personalized_headphone_path.empty(); + if (binaural_enabled) { + if (rosella_enabled) { + ::joc::hrtf::RosellaModel model; + Status status = + ::joc::hrtf::load_personalized_headphone(cfg.personalized_headphone_path, &model); + ::joc::hrtf::RosellaRenderOptions render_options; + if (cfg.binaural_mode == JOC_BINAURAL_NEAR) { + render_options.profile = ::joc::hrtf::RosellaProfile::Near; + } else if (cfg.binaural_mode == JOC_BINAURAL_FAR) { + render_options.profile = ::joc::hrtf::RosellaProfile::Far; + } + render_options.object_delay_samples = cfg.object_delay_samples; + render_options.tail_seconds = cfg.tail_seconds; + render_options.output_gain = std::pow(10.0, cfg.gain_db / 20.0); + if (status.ok()) { + status = rosella.open(model, render_options); + } + if (status.ok()) { + bus.emit(JOC_EV_HRTF_LOADED, JOC_STAGE_RENDER, JOC_LOG_INFO, model.summary()); + bus.emit(JOC_EV_RENDERER_INITIALIZED, JOC_STAGE_RENDER, JOC_LOG_INFO, + "Rosella binaural runtime ready (the first 961 samples are the " + "filterbank latency)"); + } + if (!status.ok()) { + return finalize_with_error(status.code(), "render", + "binaural setup failed: " + status.message()); + } + } + if (!rosella_enabled) { + ::joc::hrtf::Field field; + ::joc::hrtf::Kernels kernels; + ::joc::binaural::Profile profile = ::joc::binaural::Profile::Mid; + Status status = Status::success(); + if (!cfg.hrtf_sofa_path.empty()) { + // The .jochrtf is an internal cache: the SOFA is the user-facing input. + ::joc::hrtf::SofaFieldRequest request; + request.sofa_path = cfg.hrtf_sofa_path; + request.options.shell_radius_m = cfg.hrtf_radius_m; + request.cache_dir = cfg.hrtf_cache_dir; + switch (cfg.hrtf_cache_policy) { + case JOC_HRTF_CACHE_NONE: request.policy = ::joc::hrtf::CachePolicy::None; break; + case JOC_HRTF_CACHE_DISK: request.policy = ::joc::hrtf::CachePolicy::Disk; break; + default: request.policy = ::joc::hrtf::CachePolicy::Memory; break; + } + std::string cache_path; + status = ::joc::hrtf::load_or_compile_sofa_field(request, &field, &cache_path); + if (status.ok()) { + bus.emit(JOC_EV_HRTF_LOADED, JOC_STAGE_RENDER, JOC_LOG_INFO, + "SOFA HRTF compiled: " + field.source_sha256.substr(0, 16) + + (cache_path.empty() ? std::string() : " -> " + cache_path)); + } + } else { + status = ::joc::hrtf::load_jochrtf(cfg.hrtf_path, &field); + if (status.ok()) { + bus.emit(JOC_EV_HRTF_LOADED, JOC_STAGE_RENDER, JOC_LOG_INFO, + "compiled HRTF: " + field.source_sha256.substr(0, 16)); + } + } + if (status.ok()) { + status = cfg.kernels_path.empty() + ? (kernels = ::joc::hrtf::builtin_kernels(), Status::success()) + : ::joc::hrtf::load_kernels(cfg.kernels_path, &kernels); + } + if (status.ok() && cfg.binaural_mode == JOC_BINAURAL_NEAR) { + profile = ::joc::binaural::Profile::Near; + } else if (status.ok() && cfg.binaural_mode == JOC_BINAURAL_FAR) { + profile = ::joc::binaural::Profile::Far; + } + if (status.ok()) { + status = binaural.open(field, kernels, profile); + } + if (!status.ok()) { + return finalize_with_error(status.code(), "render", + "binaural setup failed: " + status.message()); + } + bus.emit(JOC_EV_RENDERER_INITIALIZED, JOC_STAGE_RENDER, JOC_LOG_INFO, + "binaural runtime ready (the first 961 samples are the kernel latency)"); + } + } + + ::joc::io::AdmBwfWriter adm_writer; + ::joc::adm::TrajectoryBuilder trajectory(48000, 64, cfg.object_delay_samples); + const bool adm_enabled = cfg.operation == JOC_OP_ADM_BWF; + if (adm_enabled) { + const Status status = adm_writer.open(cfg.output_path); + if (!status.ok()) { + return finalize_with_error(status.code(), "output", status.message()); + } + } + + PcmSpool spool; + ::joc::io::WavWriter wav_writer; + std::uint32_t wav_channels = 0; + bool wav_output = speaker_enabled || binaural_enabled; + if (wav_output) { + wav_channels = binaural_enabled ? 2u : static_cast(speaker.layout.channel_count); + const Status status = spool.open(cfg.output_path + ".spool.f32", wav_channels, + binaural_enabled, cfg.tail_threshold); + if (!status.ok()) { + return finalize_with_error(status.code(), "output", status.message()); + } + bus.emit(JOC_EV_OUTPUT_OPENED, JOC_STAGE_OUTPUT, JOC_LOG_INFO, "output: " + cfg.output_path); + bus.emit(JOC_EV_OUTPUT_FORMAT_DECIDED, JOC_STAGE_OUTPUT, JOC_LOG_INFO, + cfg.output_format == JOC_FORMAT_PCM24 ? "int24 (clip policy applies)" + : "float32"); + } else { + bus.emit(JOC_EV_OUTPUT_OPENED, JOC_STAGE_OUTPUT, JOC_LOG_INFO, + "output: " + cfg.output_path + " (25-channel RF64 ADM BWF)"); + } + + std::ofstream raw_objects; + if ((cfg.flags & JOC_TASK_F_KEEP_INTERMEDIATE) != 0u) { + raw_objects = fs_utf8::open_output(cfg.output_path + ".objects16.f32le"); + if (!raw_objects) { + return finalize_with_error(JOC_ERR_OUTPUT_OPEN, "output", + "cannot write the objects16 intermediate"); + } + } + + BedSource bed; + if (!bed.open(bed_path)) { + return finalize_with_error(JOC_ERR_INPUT_NOT_FOUND, "bed_path", + "cannot open the core PCM: " + bed_path); + } + std::ifstream input = fs_utf8::open_input(eac3_path); + if (!input) { + return finalize_with_error(JOC_ERR_INPUT_NOT_FOUND, "input", + "cannot open the E-AC-3 stream: " + eac3_path); + } + + double dsp_seconds = 0.0; + double write_seconds = 0.0; // the writer thread's own write time + double write_setup_seconds = 0.0; // the caller's share of the same stage + double joc_seconds = 0.0; // the bitstream stage's own time + std::uint64_t written_samples = 0; + std::uint64_t file_bytes = 0; + std::uint32_t output_format_actual = cfg.output_format; + double peak = 0.0; + std::uint64_t over_unity = 0; + std::uint64_t processed = 0; + ::joc::eac3::FrameReader reader; + std::vector chunk(kReadChunk); + std::vector bed5; + std::vector lfe; + std::vector objects16; + + FrameRing joc_ring(kBitstreamRingDepth); + FrameRing output_ring(kOutputRingDepth); + StopFlag stop; + FailureBoard failures; + WriteProgress write_progress; + std::thread producer; + std::thread writer; + StageJoiner joiner(&joc_ring, &output_ring, &stop, &producer, &writer); + + // ---- stage 1: the bitstream, on its own thread ------------------------ // + // The serial loop's read/decode/JOC section, verbatim apart from its error + // paths: it records failures instead of returning, because the calling + // thread owns the return value, the result struct and the event sink. + producer = std::thread([&]() { + std::uint64_t produced = 0; + bool stream_done = false; + double seconds = 0.0; + JocJob job; + try { + while (!stream_done && !stop.requested()) { + auto stage_started = Clock::now(); + input.read(chunk.data(), static_cast(chunk.size())); + const std::streamsize got = input.gcount(); + if (got > 0) { + reader.push(reinterpret_cast(chunk.data()), + static_cast(got)); + } else { + reader.finish(); + stream_done = true; + } + for (;;) { + ::joc::eac3::Frame frame; + const ::joc::eac3::FrameReader::Next state = reader.next(&frame); + if (state == ::joc::eac3::FrameReader::Next::End) { + break; + } + if (state == ::joc::eac3::FrameReader::Next::Fail) { + failures.record(produced, StageRank::kJoc, reader.error(), "eac3_transport", + reader.error_message()); + stream_done = true; + break; + } + if (produced >= total_frames) { + stream_done = true; + break; + } + if (!bed.read_frame(produced, &bed5, &lfe)) { + failures.record(produced, StageRank::kJoc, JOC_ERR_INPUT_FORMAT, "bed_path", + "core PCM ended before frame " + std::to_string(produced)); + stream_done = true; + break; + } + joc_frame_params params{}; + ::joc::emdf::Container container; + const Status parsed = ::joc::joc::parse_eac3_frame(frame.data, frame.size, + ¶ms, &container, nullptr); + if (!parsed.ok()) { + failures.record(produced, StageRank::kJoc, parsed.code(), parsed.stage(), + "frame " + std::to_string(produced) + ": " + + parsed.message()); + stream_done = true; + break; + } + job.update = ::joc::oamd::OamdUpdate{}; + job.has_update = false; + job.outer_offset = 0; + if (const ::joc::emdf::Payload* payload = container.find(::joc::emdf::kIdOamd)) { + std::vector bytes; + const Status extracted = ::joc::emdf::extract_payload_bytes( + frame.data, frame.size, *payload, &bytes); + if (!extracted.ok()) { + failures.record(produced, StageRank::kJoc, extracted.code(), + extracted.stage(), extracted.message()); + stream_done = true; + break; + } + const Status oamd = + ::joc::oamd::parse_id11(bytes.data(), bytes.size(), &job.update); + if (!oamd.ok()) { + failures.record(produced, StageRank::kJoc, oamd.code(), oamd.stage(), + "frame " + std::to_string(produced) + ": " + + oamd.message()); + stream_done = true; + break; + } + job.has_update = true; + job.outer_offset = static_cast(payload->sample_offset); + } + std::string dsp_error; + const Status rebuilt = ::joc::joc::rebuild_objects16( + rebuilder, params, bed5.data(), lfe.data(), gain, &objects16, &dsp_error); + if (!rebuilt.ok()) { + failures.record(produced, StageRank::kJoc, rebuilt.code(), "joc", + "frame " + std::to_string(produced) + ": " + dsp_error); + stream_done = true; + break; + } + job.index = produced; + job.objects = params.n_objects; + job.clipgain = params.clipgain; + job.objects16.swap(objects16); + // The clock stops before the handoff, so the stage's number is + // its own work (including the chunk read) and never the time it + // spent waiting for the DSP to make room in the ring. + seconds += std::chrono::duration(Clock::now() - stage_started).count(); + if (!joc_ring.push(&job)) { + stream_done = true; + break; + } + ++produced; + stage_started = Clock::now(); + } + } + } catch (...) { + // On the calling thread this would have propagated out of run(); on a + // stage thread it has to become a failure, or the thread terminates. + failures.record(produced, StageRank::kJoc, JOC_ERR_OUT_OF_MEMORY, "joc", + "the bitstream stage ran out of memory at frame " + + std::to_string(produced)); + } + joc_seconds = seconds; + joc_ring.close(); + }); + + // ---- stage 3: the output, on its own thread --------------------------- // + // The serial loop's write section, verbatim apart from its error paths. + writer = std::thread([&]() { + OutputJob job; + std::vector interleaved; + double seconds = 0.0; + try { + while (output_ring.pop(&job)) { + const auto write_started = Clock::now(); + Status status = Status::success(); + if (raw_objects.is_open() && !job.objects16.empty()) { + // 16 objects, interleaved per sample, exactly like the reference + // intermediate (frame_count, 1536, 16) float32. + interleaved.resize(static_cast(JOC_OUTPUT_CHANNELS) * + JOC_FRAME_SAMPLES); + for (std::size_t sample = 0; sample < JOC_FRAME_SAMPLES; ++sample) { + for (std::size_t channel = 0; channel < JOC_OUTPUT_CHANNELS; ++channel) { + interleaved[sample * JOC_OUTPUT_CHANNELS + channel] = + job.objects16[channel * JOC_FRAME_SAMPLES + sample]; + } + } + raw_objects.write(reinterpret_cast(interleaved.data()), + static_cast(interleaved.size() * + sizeof(float))); + } + if (adm_enabled && !job.objects16.empty()) { + trajectory.submit_frame(static_cast(job.index), + job.has_update ? &job.update : nullptr, + job.outer_offset); + status = adm_writer.write_objects16(job.objects16.data()); + } else if (speaker_enabled && !job.dsp.empty()) { + interleaved.resize(job.dsp.size()); + for (std::size_t index = 0; index < job.dsp.size(); ++index) { + interleaved[index] = static_cast(job.dsp[index]); + } + status = spool.write(interleaved.data(), JOC_FRAME_SAMPLES); + } else if (binaural_enabled && !job.dsp.empty()) { + interleaved.resize(job.dsp.size()); + for (std::size_t index = 0; index < job.dsp.size(); ++index) { + interleaved[index] = static_cast(job.dsp[index]); + } + status = spool.write(interleaved.data(), job.dsp.size() / 2u); + } + seconds += std::chrono::duration(Clock::now() - write_started).count(); + if (!status.ok()) { + failures.record(job.index, StageRank::kWrite, status.code(), status.stage(), + status.message()); + break; + } + write_progress.complete(job.index); + } + } catch (...) { + failures.record(job.index, StageRank::kWrite, JOC_ERR_OUT_OF_MEMORY, "output", + "the output stage ran out of memory at frame " + + std::to_string(job.index)); + } + write_seconds = seconds; + write_progress.finish(); + // Released whether the writer finished or failed, so the calling thread + // can never be left waiting for a frame that will not be written. + output_ring.abort(); + }); + + // ---- stage 2: the DSP, on the calling thread -------------------------- // + JocJob frame; + OutputJob pending; + StageFailure pending_failure; + bool failed = false; + for (;;) { + if (!joc_ring.pop(&frame)) { + // The producer finished the stream -- or failed, which the shutdown + // below and the failure board decide. + break; + } + // A stage that already failed on an earlier frame stops the run here, + // which is where the serial loop would have stopped. + if (failures.before(frame.index, &pending_failure)) { + failed = true; + break; + } + if (cancelled(cfg)) { + // Stop and join both stages before the ADM writer is aborted, so + // nothing can still be writing when the abort runs. + joiner.shutdown(true); + if (adm_enabled) { + adm_writer.abort(); + } + if (out != nullptr) { + out->status = JOC_TASK_CANCELLED; + out->error_code = static_cast(JOC_ERR_CANCELLED); + out->input_frames = processed; + out->t_total = std::chrono::duration(Clock::now() - started).count(); + } + bus.emit(JOC_EV_TASK_CANCELLED, JOC_STAGE_DONE, JOC_LOG_WARNING, + "cancelled at frame " + std::to_string(processed), JOC_ERR_CANCELLED); + return Status::fail(JOC_ERR_CANCELLED, stage::kOutput, "task cancelled"); + } + + // The bitstream stage already rebuilt this frame. The trace event stays + // here, on the thread that owns the event sink, in the same place it had + // in the serial loop: after the rebuild, before the DSP. + bus.emit(JOC_EV_JOC_FRAME_STATS, JOC_STAGE_JOC, JOC_LOG_TRACE, + fmt("frame %llu objects=%u clipgain=%.6f", + static_cast(frame.index), + static_cast(frame.objects), frame.clipgain)); + + // The DSP and the output write are timed apart: the DSP dominates the + // frame loop, so charging it to the write made that number meaningless. + double frame_dsp_seconds = 0.0; + if (!adm_enabled) { + // ADM has no DSP stage (objects16 goes straight into the BWF), so it + // must not be charged any DSP time at all. + const auto dsp_started = Clock::now(); + if (speaker_enabled) { + std::string speaker_error; + const Status stepped = ::joc::speaker::step( + &speaker, frame.objects16, frame.has_update ? &frame.update : nullptr, + &speaker_error); + if (!stepped.ok()) { + failures.record(frame.index, StageRank::kDsp, stepped.code(), "render", + "frame " + std::to_string(frame.index) + ": " + speaker_error); + failed = true; + } + } else { + const Status submitted = + rosella_enabled + ? rosella.submit_frame(frame.objects16.data(), + frame.has_update ? &frame.update : nullptr, + static_cast(frame.index), + frame.outer_offset, + static_cast(cfg.object_delay_samples)) + : binaural.submit_frame(frame.objects16.data(), + frame.has_update ? &frame.update : nullptr, + static_cast(frame.index), + frame.outer_offset, + static_cast( + cfg.object_delay_samples)); + if (!submitted.ok()) { + failures.record(frame.index, StageRank::kDsp, submitted.code(), "render", + "frame " + std::to_string(frame.index) + ": " + + submitted.message()); + failed = true; + } + } + frame_dsp_seconds = std::chrono::duration(Clock::now() - dsp_started).count(); + dsp_seconds += frame_dsp_seconds; + } + if (failed) { + break; + } + + // Hand the rendered frame to the writer. The job owns its payload, so the + // DSP can start the next frame while this one is still being written; the + // bounded ring is what limits how far ahead that can run. + const auto write_started = Clock::now(); + pending.index = frame.index; + pending.objects16.clear(); + pending.dsp.clear(); + pending.dsp_frames = 0; + pending.has_update = false; + pending.outer_offset = 0; + if (adm_enabled) { + // objects16 goes straight into the BWF, so the writer owns it now. + pending.objects16.swap(frame.objects16); + pending.update = frame.update; + pending.has_update = frame.has_update; + pending.outer_offset = frame.outer_offset; + } else { + if (raw_objects.is_open()) { + // --keep-raw interleaves objects16 for every operation. + pending.objects16.swap(frame.objects16); + } + if (speaker_enabled) { + pending.dsp = speaker.output; + pending.dsp_frames = JOC_FRAME_SAMPLES; + } else { + if (rosella_enabled) { + rosella.take_output(&pending.dsp); + } else { + binaural.take_output(&pending.dsp); + } + pending.dsp_frames = pending.dsp.size() / 2u; + } + } + // The spool accounting is known as soon as the frame is rendered, so the + // progress line reports exactly what the serial loop reported without + // waiting for the write itself. + const std::uint64_t frame_samples = + (adm_enabled || speaker_enabled) ? static_cast(JOC_FRAME_SAMPLES) + : static_cast(pending.dsp_frames); + write_setup_seconds += + std::chrono::duration(Clock::now() - write_started).count(); + if (!output_ring.push(&pending)) { + // The writer stopped; it recorded the failure that stopped it. + failures.earliest(&pending_failure); + failed = true; + break; + } + written_samples += frame_samples; + + ++processed; + if (cfg.progress_interval != 0u && processed % cfg.progress_interval == 0u) { + // The serial loop printed this line after that frame's write, so wait + // for the writer to reach the frame first: the line, and any write + // failure hiding behind it, is then exactly the serial one. One + // handoff per progress interval, so the overlap is not given back. + write_progress.wait_for(processed - 1u); + if (failures.before(processed, &pending_failure)) { + failed = true; + break; + } + bus.progress(processed, processed * static_cast(JOC_FRAME_SAMPLES), + written_samples, file_bytes, + static_cast(written_samples) / 48000.0); + bus.emit(JOC_EV_OAMD_STATS, JOC_STAGE_METADATA, JOC_LOG_DEBUG, + fmt("oamd payloads=%llu transitions=%llu", + static_cast(binaural_enabled + ? binaural.timeline().payload_count() + : 0ull), + static_cast(binaural_enabled + ? binaural.timeline() + .transition_count() + : 0ull))); + } + } + + if (failed) { + // The calling thread stopped the run -- its own failure, or one an + // earlier frame's stage already recorded. Stop both stages and drop + // whatever is still queued; the board holds the earliest failure, which + // is the one the serial loop would have reported. + joiner.shutdown(true); + StageFailure reported = pending_failure; + if (!failures.earliest(&reported) && !reported.valid) { + // Unreachable: a stage always records before it stops. A lost error + // would be worse than a synthetic one, so the code stays non-zero. + reported.valid = true; + reported.code = JOC_ERR_INTERNAL; + reported.stage_text = "output"; + reported.message = "the render pipeline stopped without reporting a failure"; + } + return finalize_with_error(reported.code, reported.stage_text, reported.message); + } + // Normal end: the producer closed its ring, so let the writer drain the last + // frames and join it. Every in-loop write is finished before the finalize + // (tail flush, spool -> WAV, SHA-256, report) looks at the output. + joiner.shutdown(false); + StageFailure recorded; + if (failures.earliest(&recorded)) { + return finalize_with_error(recorded.code, recorded.stage_text, recorded.message); + } + + // The stages overlap now, so t_render can no longer be "the frame loop minus + // the renderer and the disk": that difference is whatever the DSP left over, + // not the JOC stage's time. The fields keep their meaning and are measured + // where the work happens -- t_render is the bitstream stage's own time (read + // + decode + JOC rebuild, with no waiting for the other stages), and t_write + // is the output stage's own time: the writer thread's writes plus the + // caller's assembly of the jobs it writes. + const double t_render = joc_seconds; + write_seconds += write_setup_seconds; + + // The finalize (tail drain, spool -> WAV conversion, writer finalize) is disk + // work, so it is added to the file-write total rather than left untimed. + const auto finalize_started = Clock::now(); + bus.stage(JOC_STAGE_OUTPUT, "finalizing the output"); + std::string failure; + if (adm_enabled) { + std::vector<::joc::adm::Track> tracks; + const Status built = trajectory.build( + static_cast(processed) * static_cast(JOC_FRAME_SAMPLES), + cfg.trajectory_mode == JOC_TRAJECTORY_DENSE64 ? ::joc::adm::TrajectoryMode::Dense64 + : ::joc::adm::TrajectoryMode::Compact, + &tracks); + if (!built.ok()) { + failure = built.message(); + } else { + const double duration_sec = + static_cast(processed) * static_cast(JOC_FRAME_SAMPLES) / 48000.0; + const std::string axml = ::joc::adm::build_axml(tracks, duration_sec, 48000); + const std::string chna = ::joc::adm::build_chna(); + std::string dbmd; + const ::joc::adm::BinauralMode mode = + static_cast<::joc::adm::BinauralMode>(cfg.adm_binaural_mode); + const Status dbmd_status = + ::joc::adm::build_dbmd(::joc::io::AdmBwfWriter::kChannels, mode, &dbmd); + if (!dbmd_status.ok()) { + failure = dbmd_status.message(); + } else { + const Status finalized = adm_writer.finalize(axml, chna, dbmd); + if (!finalized.ok()) { + failure = finalized.message(); + } else if (out != nullptr) { + out->oamd_payloads = 0; + for (const ::joc::adm::Track& track : tracks) { + out->oamd_transitions += track.blocks.size(); + } + } + } + } + if (!failure.empty()) { + adm_writer.abort(); + return finalize_with_error(JOC_ERR_OUTPUT_WRITE, "output", failure); + } + written_samples = processed * static_cast(JOC_FRAME_SAMPLES); + output_format_actual = JOC_FORMAT_PCM24; + } else { + const std::uint64_t program_samples = written_samples; + if (binaural_enabled) { + std::vector tail; + const Status drained_tail = + rosella_enabled + ? rosella.finish(rosella.finish_capacity(cfg.tail_seconds), &tail) + : binaural.finish(binaural.finish_capacity(cfg.tail_seconds), &tail); + if (!drained_tail.ok()) { + return finalize_with_error(drained_tail.code(), "output", + drained_tail.message()); + } + const std::size_t samples = tail.size() / 2u; + std::vector interleaved(tail.size()); + for (std::size_t index = 0; index < tail.size(); ++index) { + interleaved[index] = static_cast(tail[index]); + } + bus.emit(JOC_EV_OUTPUT_STATS, JOC_STAGE_OUTPUT, JOC_LOG_INFO, + fmt("binaural: %llu programme samples + %llu tail samples = %llu total", + static_cast(program_samples), + static_cast(samples), + static_cast(program_samples + samples))); + const Status written = spool.write(interleaved.data(), samples); + if (!written.ok()) { + return finalize_with_error(written.code(), "output", written.message()); + } + } + // The spool holds float32; the final format is decided now that the peak + // is known, then the requested WAV is written from it. + const std::uint64_t keep = spool.kept(program_samples); + std::uint32_t actual_format = cfg.output_format; + const Status decided = + decide_output_format(cfg, &bus, spool.peak(), spool.clipped(), &actual_format); + if (!decided.ok()) { + return finalize_with_error(decided.code(), decided.stage(), decided.message()); + } + if (keep != spool.position()) { + bus.emit(JOC_EV_OUTPUT_STATS, JOC_STAGE_OUTPUT, JOC_LOG_INFO, + fmt("tail trimmed: %llu -> %llu samples (threshold %.3g)", + static_cast(spool.position()), + static_cast(keep), cfg.tail_threshold)); + } + const io::SampleFormat format = actual_format == JOC_FORMAT_PCM24 + ? io::SampleFormat::Int24 + : io::SampleFormat::Float32; + Status status = wav_writer.open(cfg.output_path, wav_channels, 48000, format, keep); + if (status.ok()) { + // Report on the same cadence as the render loop, so one knob + // (`--progress-every`, default 1000 frames) governs both. The frame + // field stays in E-AC-3 frames so the frontend's "frame/total" keeps + // its meaning (and stays monotone). + const std::uint64_t quantum = + static_cast(cfg.progress_interval) * JOC_FRAME_SAMPLES; + std::uint64_t last_reported = 0u; + status = spool.copy_to(&wav_writer, keep, [&](std::uint64_t done, std::uint64_t total) { + if (quantum == 0u || (done != total && done < last_reported + quantum)) { + return; + } + last_reported = done; + const std::uint64_t frames = + std::min(processed, done / JOC_FRAME_SAMPLES); + bus.progress(frames, done, done, 0u, static_cast(done) / 48000.0); + }); + } + if (status.ok()) { + status = wav_writer.finalize(); + } + if (!status.ok()) { + return finalize_with_error(status.code(), "output", status.message()); + } + written_samples = keep; + peak = spool.peak(); + over_unity = spool.clipped(); + output_format_actual = actual_format; + } + spool.close(); + if (raw_objects.is_open()) { + raw_objects.close(); + bus.emit(JOC_EV_OUTPUT_STATS, JOC_STAGE_OUTPUT, JOC_LOG_INFO, + "objects16 intermediate: " + cfg.output_path + ".objects16.f32le"); + } + const double finalize_seconds = + std::chrono::duration(Clock::now() - finalize_started).count(); + + std::error_code size_error; + file_bytes = fs_utf8::file_size(cfg.output_path, size_error); + std::string digest; + if ((cfg.flags & JOC_TASK_F_SKIP_SHA256) == 0u) { + std::ifstream output = fs_utf8::open_input(cfg.output_path); + if (output) { + crypto::Sha256 hash; + std::vector block(1u << 20); + for (;;) { + output.read(block.data(), static_cast(block.size())); + const std::streamsize count = output.gcount(); + if (count <= 0) { + break; + } + hash.update(block.data(), static_cast(count)); + } + digest = hash.finish_hex(); + } + } + if (out != nullptr) { + out->status = JOC_TASK_OK; + out->error_code = 0; + out->input_frames = processed; + out->output_samples = written_samples; + out->duration_sec = static_cast(processed) * static_cast(JOC_FRAME_SAMPLES) / 48000.0; + out->output_format_actual = output_format_actual; + out->output_peak = peak; + out->output_over_unity_values = over_unity; + out->output_file_bytes = file_bytes; + std::snprintf(out->output_sha256, sizeof(out->output_sha256), "%s", digest.c_str()); + out->oamd_payloads = binaural_enabled ? binaural.timeline().payload_count() : out->oamd_payloads; + out->oamd_transitions = + binaural_enabled ? binaural.timeline().transition_count() : out->oamd_transitions; + out->t_decode_bed = t_decode; + out->t_render = t_render; + out->t_write = write_seconds; + out->t_render_dsp = dsp_seconds; + out->t_write_file = write_seconds + finalize_seconds; + out->t_total = std::chrono::duration(Clock::now() - started).count(); + } + if (speaker.handle != nullptr) { + ejoc_speaker_renderer_destroy(speaker.handle); + speaker.handle = nullptr; + } + if (!temp_dir.empty()) { + std::error_code ignored; + fs::remove_all(fs_utf8::to_path(temp_dir), ignored); + } + bus.emit(JOC_EV_OUTPUT_FINALIZED, JOC_STAGE_OUTPUT, JOC_LOG_INFO, + fmt("%s (%llu bytes, sha256 %s)", cfg.output_path.c_str(), + static_cast(file_bytes), + digest.empty() ? "skipped" : digest.substr(0, 16).c_str())); + bus.emit(JOC_EV_TASK_COMPLETED, JOC_STAGE_DONE, JOC_LOG_INFO, + fmt("done: %llu frames, %llu output samples, %.2f s wall clock", + static_cast(processed), + static_cast(written_samples), + std::chrono::duration(Clock::now() - started).count())); + return Status::success(); +} + +Status result_to_json(const joc_task_result& result, std::string* out) { + if (out == nullptr) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOutput, "null output"); + } + *out = fmt( + "{\"status\":%u,\"error_code\":%u,\"error_stage\":\"%s\",\"error_message\":\"%s\"," + "\"input_frames\":%llu,\"output_samples\":%llu,\"duration_sec\":%.6f," + "\"output_format_actual\":%u,\"output_peak\":%.9g,\"output_over_unity_values\":%llu," + "\"output_file_bytes\":%llu,\"output_sha256\":\"%s\",\"oamd_payloads\":%llu," + "\"oamd_transitions\":%llu,\"t_decode_bed\":%.6f,\"t_render\":%.6f,\"t_write\":%.6f," + "\"t_render_dsp\":%.6f,\"t_write_file\":%.6f,\"t_total\":%.6f}", + result.status, result.error_code, result.error_stage, result.error_message, + static_cast(result.input_frames), + static_cast(result.output_samples), result.duration_sec, + result.output_format_actual, result.output_peak, + static_cast(result.output_over_unity_values), + static_cast(result.output_file_bytes), result.output_sha256, + static_cast(result.oamd_payloads), + static_cast(result.oamd_transitions), result.t_decode_bed, + result.t_render, result.t_write, result.t_render_dsp, result.t_write_file, + result.t_total); + return Status::success(); +} + +} // namespace joc::task diff --git a/src/task/task.h b/src/task/task.h new file mode 100644 index 0000000..ab6fb5f --- /dev/null +++ b/src/task/task.h @@ -0,0 +1,21 @@ + +#pragma once + +#include +#include + +#include "foundation/status.h" +#include "joc_core.h" + +namespace joc::task { + +Status validate(const joc_task_config& raw, std::vector* issues, + std::uint32_t* error_count); + +// Runs the task on the calling thread. Never throws; failures come back as the +Status run(const joc_task_config& raw, const joc_event_sink* sink, joc_task_result* out); + +// Serialises the stable subset of the result (plan 22.2 / 33.5). +Status result_to_json(const joc_task_result& result, std::string* out); + +} // namespace joc::task diff --git a/src/telemetry/event_bus.cpp b/src/telemetry/event_bus.cpp new file mode 100644 index 0000000..63a5f41 --- /dev/null +++ b/src/telemetry/event_bus.cpp @@ -0,0 +1,111 @@ +#include "telemetry/event_bus.h" + +#include +#include + +namespace joc::telemetry { + +// The event must stay a trivially copyable POD with no pointers: that is what +// makes "an event can never carry audio" a compile-time property. +static_assert(std::is_trivially_copyable_v, "joc_event must be a POD"); +static_assert(sizeof(joc_event) <= 512, "joc_event must stay small"); + +const char* stage_name(joc_stage stage) { + switch (stage) { + case JOC_STAGE_IDLE: return "idle"; + case JOC_STAGE_INPUT: return "input"; + case JOC_STAGE_METADATA: return "metadata"; + case JOC_STAGE_DECODE: return "decode"; + case JOC_STAGE_JOC: return "joc"; + case JOC_STAGE_RENDER: return "render"; + case JOC_STAGE_OUTPUT: return "output"; + case JOC_STAGE_DONE: return "done"; + default: return "unknown"; + } +} + +EventBus::EventBus(const joc_event_sink* sink) { + if (sink != nullptr && sink->callback != nullptr) { + sink_ = *sink; + has_sink_ = true; + } +} + +void EventBus::set_totals(std::uint64_t total_frames, std::uint64_t total_samples) { + total_frames_ = total_frames; + total_samples_ = total_samples; +} + +double EventBus::elapsed_seconds() const { + return std::chrono::duration(std::chrono::steady_clock::now() - started_).count(); +} + +void EventBus::publish(joc_event* event) { + if (!has_sink_) { + return; + } + if (sink_.min_type != 0u && event->type < sink_.min_type) { + return; + } + if (sink_.max_type != 0u && event->type > sink_.max_type) { + return; + } + sink_.callback(sink_.user, event); +} + +void EventBus::emit(std::uint32_t type, joc_stage stage, std::uint32_t log_level, + const std::string& message, joc_error code) { + joc_event event{}; + event.struct_size = sizeof(joc_event); + event.type = type; + event.sequence = ++sequence_; + event.timestamp_us = static_cast(elapsed_seconds() * 1e6); + event.total_frames = total_frames_; + event.total_samples = total_samples_; + event.stage = static_cast(stage); + event.backend = backend_; + event.progress = total_frames_ != 0u + ? static_cast(event.current_frame) / + static_cast(total_frames_) + : -1.0; + event.elapsed_seconds = elapsed_seconds(); + event.error_code = code; + event.log_level = log_level; + std::snprintf(event.stage_name, sizeof(event.stage_name), "%s", stage_name(stage)); + std::snprintf(event.message, sizeof(event.message), "%s", message.c_str()); + publish(&event); +} + +void EventBus::progress(std::uint64_t frame, std::uint64_t sample, std::uint64_t output_samples, + std::uint64_t output_bytes, double output_seconds) { + joc_event event{}; + event.struct_size = sizeof(joc_event); + event.type = JOC_EV_PROGRESS; + event.sequence = ++sequence_; + event.timestamp_us = static_cast(elapsed_seconds() * 1e6); + event.current_frame = frame; + event.total_frames = total_frames_; + event.current_sample = sample; + event.total_samples = total_samples_; + event.stage = static_cast(stage_); + event.backend = backend_; + event.progress = total_frames_ != 0u + ? static_cast(frame) / static_cast(total_frames_) + : -1.0; + event.elapsed_seconds = elapsed_seconds(); + const double audio_seconds = static_cast(sample) / 48000.0; + event.realtime_factor = event.elapsed_seconds > 0.0 ? audio_seconds / event.elapsed_seconds + : 0.0; + event.output_samples = output_samples; + event.output_bytes = output_bytes; + event.output_duration_seconds = output_seconds; + std::snprintf(event.stage_name, sizeof(event.stage_name), "%s", stage_name(stage_)); + publish(&event); +} + +void EventBus::stage(joc_stage stage, const std::string& message) { + stage_ = stage; + emit(JOC_EV_STAGE_CHANGED, stage, JOC_LOG_INFO, message); +} + +} // namespace joc::telemetry diff --git a/src/telemetry/event_bus.h b/src/telemetry/event_bus.h new file mode 100644 index 0000000..e7a1df5 --- /dev/null +++ b/src/telemetry/event_bus.h @@ -0,0 +1,62 @@ + +#pragma once + +#include +#include +#include + +#include "joc_core.h" + +namespace joc::telemetry { + +const char* stage_name(joc_stage stage); + +class EventBus { +public: + EventBus() = default; + explicit EventBus(const joc_event_sink* sink); + + void set_totals(std::uint64_t total_frames, std::uint64_t total_samples); + void set_backend(std::uint32_t backend) { backend_ = backend; } + + // Generic emit; `message` is truncated into the 256-byte field. + void emit(std::uint32_t type, joc_stage stage, std::uint32_t log_level, const std::string& message, + joc_error code = JOC_OK); + + void progress(std::uint64_t frame, std::uint64_t sample, std::uint64_t output_samples, std::uint64_t output_bytes, + double output_seconds); + void stage(joc_stage stage, const std::string& message = std::string()); + void info(const std::string& message) { emit(JOC_EV_LOG, stage_, JOC_LOG_INFO, message); } + void warning(const std::string& message) + { + ++warning_count_; + emit(JOC_EV_WARNING, stage_, JOC_LOG_WARNING, message); + } + void error(joc_error code, const std::string& stage_text, const std::string& message) + { + ++error_count_; + emit(JOC_EV_ERROR, stage_, JOC_LOG_ERROR, + (stage_text.empty() ? message : stage_text + ": " + message), code); + } + + std::uint64_t sequence() const { return sequence_; } + std::uint32_t warning_count() const { return warning_count_; } + std::uint32_t error_count() const { return error_count_; } + double elapsed_seconds() const; + +private: + void publish(joc_event* event); + + joc_event_sink sink_{}; + bool has_sink_ = false; + std::chrono::steady_clock::time_point started_ = std::chrono::steady_clock::now(); + std::uint64_t sequence_ = 0; + std::uint64_t total_frames_ = 0; + std::uint64_t total_samples_ = 0; + std::uint32_t backend_ = 0; + std::uint32_t warning_count_ = 0; + std::uint32_t error_count_ = 0; + joc_stage stage_ = JOC_STAGE_IDLE; +}; + +} // namespace joc::telemetry diff --git a/src/timeline/position_timeline.cpp b/src/timeline/position_timeline.cpp new file mode 100644 index 0000000..84a4ec4 --- /dev/null +++ b/src/timeline/position_timeline.cpp @@ -0,0 +1,187 @@ +#include "timeline/position_timeline.h" + +#include + +#include "foundation/geometry.h" + +namespace joc::timeline { + +namespace { + +Status timeline_fail(joc_error code, const std::string& message) { + return Status::fail(code, stage::kOamd, message); +} + +} // namespace + +void ObjectPositionTrack::set_initial(const double position[3]) { + for (int i = 0; i < 3; ++i) { + initial_[i] = position[i]; + last_target_[i] = position[i]; + } +} + +Status ObjectPositionTrack::append(std::int64_t start_sample, std::int64_t duration_samples, + const double target[3], int object_index) { + if (start_sample < 0 || duration_samples < 0) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOamd, + "position transition timing must be non-negative"); + } + if (!transitions_.empty()) { + const PositionTransition& previous = transitions_.back(); + if (start_sample < previous.end_sample()) { + return timeline_fail( + JOC_ERR_OAMD_UNSUPPORTED_VARIANT, + "overlapping_binaural_position_ramps: object " + std::to_string(object_index) + + " has a new position update at sample " + std::to_string(start_sample) + + " before the previous ramp ends at " + std::to_string(previous.end_sample())); + } + if (start_sample == previous.start_sample && previous.duration_samples == 0) { + PositionTransition replacement; + replacement.start_sample = start_sample; + replacement.duration_samples = duration_samples; + std::memcpy(replacement.origin, previous.origin, sizeof(replacement.origin)); + std::memcpy(replacement.target, target, sizeof(replacement.target)); + transitions_.back() = replacement; + std::memcpy(last_target_, target, sizeof(last_target_)); + return Status::success(); + } + } + PositionTransition transition; + transition.start_sample = start_sample; + transition.duration_samples = duration_samples; + std::memcpy(transition.origin, last_target_, sizeof(transition.origin)); + std::memcpy(transition.target, target, sizeof(transition.target)); + transitions_.push_back(transition); + std::memcpy(last_target_, target, sizeof(last_target_)); + return Status::success(); +} + +Status ObjectPositionTrack::position_at(std::int64_t sample, double out[3]) { + if (sample < last_query_sample_) { + return Status::fail(JOC_ERR_STATE, stage::kOamd, + "binaural metadata positions must be queried monotonically"); + } + last_query_sample_ = sample; + while (cursor_ < transitions_.size()) { + const PositionTransition& transition = transitions_[cursor_]; + if (sample < transition.end_sample()) { + break; + } + std::memcpy(initial_, transition.target, sizeof(initial_)); + ++cursor_; + } + if (cursor_ >= transitions_.size()) { + std::memcpy(out, initial_, sizeof(initial_)); + return Status::success(); + } + const PositionTransition& transition = transitions_[cursor_]; + if (sample < transition.start_sample) { + std::memcpy(out, initial_, sizeof(initial_)); + return Status::success(); + } + if (transition.duration_samples == 0) { + std::memcpy(out, transition.target, sizeof(transition.target)); + return Status::success(); + } + const double amount = + static_cast(sample - transition.start_sample) / + static_cast(transition.duration_samples); + for (int i = 0; i < 3; ++i) { + out[i] = transition.origin[i] + (transition.target[i] - transition.origin[i]) * amount; + } + return Status::success(); +} + +OamdPositionTimeline::OamdPositionTimeline(int object_count) : object_count_(object_count) { + if (object_count != kTimelineObjects) { + object_count_ = kTimelineObjects; + } +} + +Status OamdPositionTimeline::submit_update(const oamd::OamdUpdate& update, + std::int64_t frame_start_sample, + std::int64_t outer_sample_offset, + std::int64_t object_delay_samples, + std::int64_t processed_sample) { + if (frame_start_sample < 0 || outer_sample_offset < 0 || object_delay_samples < 0) { + return Status::fail(JOC_ERR_INVALID_ARGUMENT, stage::kOamd, + "OAMD frame, outer offset and object delay must be non-negative"); + } + state_.apply(update); + + double targets[kTimelineObjects][3] = {}; + for (int index = 0; index < kTimelineObjects; ++index) { + geometry::q_to_adm_xyz(state_.q(index + 1, 0), state_.q(index + 1, 1), + state_.q(index + 1, 2), &targets[index][0], &targets[index][1], + &targets[index][2]); + } + + const std::int64_t coded_event = + frame_start_sample + outer_sample_offset + + static_cast(update.block_offset_samples); + if (coded_event < last_coded_event_sample_) { + return timeline_fail(JOC_ERR_OAMD_UNSUPPORTED_VARIANT, + "non_monotonic_binaural_updates: event sample " + + std::to_string(coded_event) + " follows " + + std::to_string(last_coded_event_sample_)); + } + last_coded_event_sample_ = coded_event; + + if (!initialized_) { + if (processed_sample > 0) { + return timeline_fail(JOC_ERR_OAMD_UNSUPPORTED_VARIANT, + "late_initial_binaural_state: the first OAMD state arrived after " + "sample " + std::to_string(processed_sample) + + " had been processed, so sample 0 cannot be backfilled"); + } + for (int index = 0; index < kTimelineObjects; ++index) { + tracks_[index].set_initial(targets[index]); + std::memcpy(previous_targets_[index], targets[index], sizeof(targets[index])); + has_previous_[index] = true; + } + initialized_ = true; + ++payload_count_; + return Status::success(); + } + + const std::int64_t ramp_duration = static_cast(update.ramp_duration_samples); + const std::int64_t effective_ramp = + ramp_duration - kOamdUpdateQuantumSamples > 0 ? ramp_duration - kOamdUpdateQuantumSamples + : 0; + std::int64_t transition_start = coded_event + object_delay_samples; + if (effective_ramp != 0) { + transition_start += kOamdUpdateQuantumSamples; + } + for (int index = 0; index < kTimelineObjects; ++index) { + const bool changed = !has_previous_[index] || + std::memcmp(previous_targets_[index], targets[index], + sizeof(targets[index])) != 0; + if (!changed) { + continue; + } + const Status status = tracks_[index].append(transition_start, effective_ramp, + targets[index], index + 1); + if (!status.ok()) { + return status; + } + std::memcpy(previous_targets_[index], targets[index], sizeof(targets[index])); + has_previous_[index] = true; + ++transition_count_; + } + ++payload_count_; + return Status::success(); +} + +Status OamdPositionTimeline::positions_at(std::int64_t sample, + double positions[kTimelineObjects][3]) { + for (int index = 0; index < kTimelineObjects; ++index) { + const Status status = tracks_[index].position_at(sample, positions[index]); + if (!status.ok()) { + return status; + } + } + return Status::success(); +} + +} // namespace joc::timeline diff --git a/src/timeline/position_timeline.h b/src/timeline/position_timeline.h new file mode 100644 index 0000000..fd137c1 --- /dev/null +++ b/src/timeline/position_timeline.h @@ -0,0 +1,71 @@ +// Port of src/binaural_metadata.py. + +#pragma once + +#include +#include + +#include "foundation/status.h" +#include "oamd/oamd_parser.h" + +namespace joc::timeline { + +inline constexpr std::int64_t kOamdUpdateQuantumSamples = 64; +inline constexpr int kTimelineObjects = 15; + +struct PositionTransition { + std::int64_t start_sample = 0; + std::int64_t duration_samples = 0; + double origin[3] = {}; + double target[3] = {}; + std::int64_t end_sample() const { return start_sample + duration_samples; } +}; + +class ObjectPositionTrack { +public: + void set_initial(const double position[3]); + Status append(std::int64_t start_sample, std::int64_t duration_samples, const double target[3], + int object_index); + // Monotonic queries only; out receives the interpolated position. + Status position_at(std::int64_t sample, double out[3]); + + const std::vector& transitions() const { return transitions_; } + +private: + double initial_[3] = {}; + double last_target_[3] = {}; + std::vector transitions_; + std::size_t cursor_ = 0; + std::int64_t last_query_sample_ = -1; +}; + +class OamdPositionTimeline { +public: + explicit OamdPositionTimeline(int object_count = kTimelineObjects); + + Status submit_update(const oamd::OamdUpdate& update, std::int64_t frame_start_sample, + std::int64_t outer_sample_offset, std::int64_t object_delay_samples, + std::int64_t processed_sample); + + // positions[15][3]; queries must be monotonically increasing. + Status positions_at(std::int64_t sample, double positions[kTimelineObjects][3]); + + std::uint64_t payload_count() const { return payload_count_; } + std::uint64_t transition_count() const { return transition_count_; } + bool initialized() const { return initialized_; } + + const ObjectPositionTrack& track(int index) const { return tracks_[index]; } + +private: + int object_count_; + oamd::OamdState state_; + ObjectPositionTrack tracks_[kTimelineObjects]; + bool initialized_ = false; + double previous_targets_[kTimelineObjects][3] = {}; + bool has_previous_[kTimelineObjects] = {}; + std::uint64_t payload_count_ = 0; + std::uint64_t transition_count_ = 0; + std::int64_t last_coded_event_sample_ = -1; +}; + +} // namespace joc::timeline diff --git a/tests/test_core.cpp b/tests/test_core.cpp new file mode 100644 index 0000000..e5458a3 --- /dev/null +++ b/tests/test_core.cpp @@ -0,0 +1,733 @@ +// Unit tests for the engine's self-contained parts: no test data files, no +// reference implementation, no external framework. Run with `ctest` or directly. +#include +#include +#include +#include +#include +#include +#include +#include + +#include "adm/adm_metadata.h" +#include "eac3_transport/eac3_reader.h" +#include "foundation/bit_reader.h" +#include "foundation/fs_utf8.h" +#include "foundation/geometry.h" +#include "hrtf/jochrtf.h" +#include "hrtf/sofa.h" +#include "hrtf/sofa_cache.h" +#include "hrtf/rosella_model.h" +#include "hrtf/rosella_renderer.h" +#include "hrtf/sofa_field.h" +#include "foundation/mini_json.h" +#include "foundation/sha256.h" +#include "io/inflate.h" +#include "io/hdf5.h" +#include "io/npy_writer.h" +#include "io/npy.h" +#include "io/process.h" +#include "io/wav_writer.h" +#include "io/zip_reader.h" +#include "oamd/oamd_parser.h" + +namespace { + +int g_failures = 0; +int g_checks = 0; + +void check(bool condition, const char* expression, const char* file, int line) { + ++g_checks; + if (!condition) { + ++g_failures; + std::printf("FAIL %s:%d %s\n", file, line, expression); + } +} + +#define CHECK(expression) check((expression), #expression, __FILE__, __LINE__) + +void test_sha256() { + CHECK(joc::crypto::sha256_hex("", 0) == + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + CHECK(joc::crypto::sha256_hex("abc", 3) == + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + const char* two_block = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + CHECK(joc::crypto::sha256_hex(two_block, std::strlen(two_block)) == + "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); + std::vector million(1000000, 'a'); + CHECK(joc::crypto::sha256_hex(million.data(), million.size()) == + "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); + // Incremental updates must equal a single-shot hash. + joc::crypto::Sha256 incremental; + incremental.update("ab", 2); + incremental.update("c", 1); + CHECK(incremental.finish_hex() == joc::crypto::sha256_hex("abc", 3)); +} + +void test_crc32_and_inflate() { + CHECK(joc::io::crc32_of(reinterpret_cast("123456789"), 9) == 0xCBF43926u); + // One stored DEFLATE block: BFINAL=1, BTYPE=00, LEN=3, NLEN=~LEN, "abc". + const std::uint8_t stored[] = {0x01, 0x03, 0x00, 0xFC, 0xFF, 'a', 'b', 'c'}; + std::vector out; + CHECK(joc::io::inflate_raw(stored, sizeof(stored), &out)); + CHECK(out.size() == 3 && std::memcmp(out.data(), "abc", 3) == 0); + const std::uint8_t truncated[] = {0x01, 0x10, 0x00, 0xEF, 0xFF, 'a'}; + CHECK(!joc::io::inflate_raw(truncated, sizeof(truncated), &out)); +} + +void test_bit_reader() { + const std::uint8_t data[] = {0xB2, 0x5D}; // 1011 0010 0101 1101 + joc::bits::BitReader reader(data, sizeof(data)); + CHECK(reader.read(3) == 0x5); + CHECK(reader.read(5) == 0x12); + CHECK(reader.read(8) == 0x5D); + CHECK(reader.position() == 16); + CHECK(!reader.failed()); + + joc::bits::BitReader short_read(data, 1); + CHECK(short_read.read(9) == 0); + CHECK(short_read.failed()); + CHECK(short_read.error() == JOC_ERR_BITSTREAM_TRUNCATED); + CHECK(short_read.position() == 0); + + joc::bits::BitReader limited(data, sizeof(data)); + limited.set_limit_bits(4); + CHECK(limited.read(4) == 0xB); + CHECK(limited.read(1) == 0 && limited.failed()); +} + +// Writes MSB-first bits; used only to build test vectors. +class BitWriter { +public: + void write(std::uint32_t value, unsigned count) { + for (unsigned i = count; i-- > 0;) { + const std::uint8_t bit = static_cast((value >> i) & 1u); + if (used_ == 0) { + bytes_.push_back(0); + } + bytes_.back() |= static_cast(bit << (7u - used_)); + used_ = (used_ + 1u) % 8u; + } + } + const std::vector& bytes() const { return bytes_; } + +private: + std::vector bytes_; + unsigned used_ = 0; +}; + +void test_variable_bits() { + // 300 with width 8 is two groups: 0 (continue) then 44 (stop). + BitWriter writer; + writer.write(0, 8); + writer.write(1, 1); + writer.write(44, 8); + writer.write(0, 1); + joc::bits::BitReader reader(writer.bytes().data(), writer.bytes().size()); + std::uint32_t value = 0; + CHECK(joc::bits::variable_bits(reader, 8, 8, &value)); + CHECK(value == 300); + + // Eight continuation groups exceed the limit and must fail, not loop. + BitWriter endless; + for (int group = 0; group < 8; ++group) { + endless.write(0, 8); + endless.write(1, 1); + } + joc::bits::BitReader endless_reader(endless.bytes().data(), endless.bytes().size()); + CHECK(!joc::bits::variable_bits(endless_reader, 8, 8, &value)); + CHECK(endless_reader.error() == JOC_ERR_EMDF_SYNTAX); +} + +void test_eac3_frame_bytes() { + std::vector frame(3072, 0); + frame[0] = 0x0B; + frame[1] = 0x77; + frame[2] = 0x05; + frame[3] = 0xFF; // frmsiz words = 1536 -> 3072 bytes + std::size_t size = 0; + CHECK(joc::eac3::FrameReader::frame_bytes(frame.data(), frame.size(), 0, &size) == JOC_OK); + CHECK(size == 3072); + CHECK(joc::eac3::FrameReader::frame_bytes(frame.data(), 100, 0, &size) == + JOC_ERR_BITSTREAM_TRUNCATED); + frame[1] = 0x78; + CHECK(joc::eac3::FrameReader::frame_bytes(frame.data(), frame.size(), 0, &size) == + JOC_ERR_EAC3_SYNCFRAME); +} + +void test_mini_json() { + const std::string text = R"({"a":1,"b":"x\ny","c":{"d":true},"e":-2.5})"; + std::vector members; + std::string error; + CHECK(joc::json::parse_object(text, &members, &error)); + double number = 0.0; + CHECK(joc::json::as_number(*joc::json::find(members, "a"), &number) && number == 1.0); + CHECK(joc::json::as_number(*joc::json::find(members, "e"), &number) && number == -2.5); + std::string value; + CHECK(joc::json::as_string(*joc::json::find(members, "b"), &value) && value == "x\ny"); + CHECK(joc::json::find(members, "c")->raw == R"({"d":true})"); + std::vector duplicate; + CHECK(!joc::json::parse_object(R"({"a":1,"a":2})", &duplicate, &error)); + CHECK(!joc::json::parse_object("[1,2]", &duplicate, &error)); +} + +void test_npy() { + // Build a minimal image; + const char magic[6] = {'\x93', 'N', 'U', 'M', 'P', 'Y'}; + image.insert(image.end(), magic, magic + 6); + image.push_back(1); + image.push_back(0); + image.push_back(static_cast(header.size() & 0xFFu)); + image.push_back(static_cast(header.size() >> 8)); + image.insert(image.end(), header.begin(), header.end()); + const double values[2] = {1.5, -0.25}; + const std::uint8_t* raw = reinterpret_cast(values); + image.insert(image.end(), raw, raw + sizeof(values)); + + joc::io::NpyArray array; + std::string error; + CHECK(joc::io::parse_npy(image.data(), image.size(), &array, &error)); + CHECK(array.descr == " loaded; + CHECK(joc::io::npy_to_double(array, &loaded, &error)); + CHECK(loaded.size() == 2 && loaded[0] == 1.5 && loaded[1] == -0.25); +} + +void test_oamd_and_adm_helpers() { + CHECK(joc::oamd::q_of(0, 62) == 0); + CHECK(joc::oamd::q_of(62, 62) == 32767); + CHECK(joc::oamd::q_of(31, 62) == 16384); + CHECK(joc::oamd::q_of(15, 15) == 32767); + + CHECK(joc::adm::ts(0.0) == "00:00:00.00000"); + CHECK(joc::adm::ts(1.5) == "00:00:01.50000"); + CHECK(joc::adm::ts(3661.25) == "01:01:01.25000"); + // 0.999999 s rounds to the next second, not to 100000 microseconds. + CHECK(joc::adm::ts(0.999999) == "00:00:01.00000"); + + double x = 0.0; + double y = 0.0; + double z = 0.0; + joc::geometry::q_to_adm_xyz(0, 32767, 0, &x, &y, &z); + CHECK(x == -1.0 && y == -1.0 && z == 0.0); + joc::geometry::q_to_adm_xyz(32767, 0, 0, &x, &y, &z); + CHECK(x == 1.0 && y == 1.0 && z == 0.0); +} + +void test_int24_packing() { + // Interleaved (L,R) for two frames: 0.0, +1.0, -1.0, +2.0 (clips). + const float values[4] = {0.0f, 1.0f, -1.0f, 2.0f}; + std::string packed; + joc::io::pack_int24(values, 2, 2, &packed); + CHECK(packed.size() == 12); + auto byte = [&](std::size_t index) { + return static_cast(packed[index]); + }; + CHECK(byte(0) == 0x00 && byte(1) == 0x00 && byte(2) == 0x00); // 0.0 + CHECK(byte(3) == 0xFF && byte(4) == 0xFF && byte(5) == 0x7F); // +1.0 + CHECK(byte(6) == 0x01 && byte(7) == 0x00 && byte(8) == 0x80); // -1.0 + CHECK(byte(9) == 0xFF && byte(10) == 0xFF && byte(11) == 0x7F); // +2.0 clips +} + +void test_utf8_paths() { + // Non-ASCII paths must survive the OS boundary on every platform: this is the + // regression guard for the ANSI-code-page bug class (a Japanese path used to + // reach ffmpeg as mojibake on Windows). + const std::string directory = joc::fs_utf8::temp_directory(); + CHECK(!directory.empty()); + const std::string path = joc::fs_utf8::from_path( + joc::fs_utf8::to_path(directory) / joc::fs_utf8::to_path("joc_テスト_須田景凪_测试.bin")); + CHECK(joc::fs_utf8::from_path(joc::fs_utf8::to_path(path)) == path); + + std::FILE* file = joc::fs_utf8::fopen(path, "wb"); + CHECK(file != nullptr); + if (file != nullptr) { + const char payload[] = "joc-utf8"; + CHECK(std::fwrite(payload, 1, sizeof(payload) - 1u, file) == sizeof(payload) - 1u); + std::fclose(file); + } + CHECK(joc::fs_utf8::exists(path)); + std::error_code error; + CHECK(joc::fs_utf8::file_size(path, error) == sizeof("joc-utf8") - 1u); + + std::ifstream input = joc::fs_utf8::open_input(path); + CHECK(input.good()); + std::string content(sizeof("joc-utf8") - 1u, '\0'); + input.read(content.data(), static_cast(content.size())); + CHECK(content == "joc-utf8"); + input.close(); + + std::ofstream output = joc::fs_utf8::open_output(path + ".copy"); + CHECK(output.good()); + output << content; + output.close(); + CHECK(joc::fs_utf8::exists(path + ".copy")); + + CHECK(joc::fs_utf8::remove(path) == 0); + CHECK(joc::fs_utf8::remove(path + ".copy") == 0); + CHECK(!joc::fs_utf8::exists(path)); +} + +void test_process_runner() { + // The ffmpeg boundary must surface both the exit code and the child's stderr. +#if defined(_WIN32) + const std::vector command = {"cmd.exe", "/c", "echo boom 1>&2 & exit 3"}; +#else + const std::vector command = {"/bin/sh", "-c", "echo boom 1>&2; exit 3"}; +#endif + joc::io::ProcessResult result; + const joc::Status status = joc::io::run_process(command, &result); + CHECK(!status.ok()); + CHECK(result.exit_code == 3u); + CHECK(result.output.find("boom") != std::string::npos); +} + +void test_npy_and_zip_writers() { + using joc::io::NpyMember; + // Python's repr, which is what json.dumps writes into the cache metadata. + CHECK(joc::io::python_float_repr(48000.0) == "48000.0"); + CHECK(joc::io::python_float_repr(1.0) == "1.0"); + CHECK(joc::io::python_float_repr(0.001) == "0.001"); + CHECK(joc::io::python_float_repr(1.0e-5) == "1e-05"); + CHECK(joc::io::python_float_repr(1.5) == "1.5"); + CHECK(joc::io::python_float_repr(-2.25) == "-2.25"); + CHECK(joc::io::python_float_repr(1.0e16) == "1e+16"); + CHECK(joc::io::python_float_repr(1234567890123456.0) == "1234567890123456.0"); + + // An NPY image must round-trip through the reader that loads the cache. + const std::vector values = {1.5, -2.25, 3.75, 4.0, 0.5, 0.25}; + std::vector payload(values.size() * sizeof(double)); + std::memcpy(payload.data(), values.data(), payload.size()); + const std::vector image = joc::io::npy_image(" restored; + CHECK(joc::io::npy_to_double(array, &restored, &error)); + CHECK(restored.size() == values.size()); + bool same = restored.size() == values.size(); + for (std::size_t index = 0; index < restored.size() && same; ++index) { + same = restored[index] == values[index]; + } + CHECK(same); + + // A Unicode scalar string member, as the cache stores its metadata. + const std::string text = "{\"k\":\"v\"}"; + const std::vector unicode = joc::io::utf8_to_utf32le(text); + CHECK(unicode.size() == text.size() * 4u); + CHECK(unicode[0] == static_cast('{') && unicode[1] == 0u && + unicode[3] == 0u); + const std::vector text_image = + joc::io::npy_image(" members; + NpyMember member; + member.name = "band_center_frequencies_hz"; + member.descr = " read_back; + CHECK(archive.read_member("band_center_frequencies_hz.npy", &read_back, &error)); + CHECK(read_back.size() == image.size()); + CHECK(read_back.size() == image.size() && + std::memcmp(read_back.data(), image.data(), image.size()) == 0); + CHECK(joc::fs_utf8::remove(path) == 0); +} + +// --------------------------------------------------------------------------- +// HRTF import and compile path. +// +// Everything below builds its input in memory, so the suite reads no external +// files; the parts that need one are exercised through their error paths. +// --------------------------------------------------------------------------- + +constexpr double kPi = 3.14159265358979323846; + +// A SimpleFreeFieldHRIR set with `measurements` directions on one 1 m shell and +// `taps` decaying taps per ear. The values are closed-form placeholders; what +// the canonicaliser and the spherical-harmonic fit actually read is the +// geometry and the shape. +joc::hrtf::SofaHrir synthetic_sofa(std::uint32_t measurements, std::uint32_t taps) { + joc::hrtf::SofaHrir sofa; + sofa.sample_rate = 48000.0; + sofa.sampling_rate_units = "hertz"; + sofa.ir_count = measurements; + sofa.ir_length = taps; + sofa.conventions = "SOFA"; + sofa.sofa_conventions = "SimpleFreeFieldHRIR"; + sofa.convention_version = "1.0"; + sofa.version = "1.0"; + sofa.data_type = "FIR"; + sofa.room_type = "free field"; + sofa.receiver_position[0] = 0.0; + sofa.receiver_position[1] = 0.09; + sofa.receiver_position[2] = 0.0; + sofa.receiver_position[3] = 0.0; + sofa.receiver_position[4] = -0.09; + sofa.receiver_position[5] = 0.0; + sofa.source_position_coordinates.type = "spherical"; + sofa.source_position_coordinates.units = "degree, degree, metre"; + sofa.emitter_position_coordinates.type = "cartesian"; + sofa.emitter_position_coordinates.units = "metre"; + sofa.listener_position_coordinates.type = "cartesian"; + sofa.listener_position_coordinates.units = "metre"; + sofa.listener_view_coordinates.type = "cartesian"; + sofa.listener_view_coordinates.units = "metre"; + sofa.receiver_position_coordinates.type = "cartesian"; + sofa.receiver_position_coordinates.units = "metre"; + sofa.source_sha256 = std::string(64u, '0'); + sofa.source_position.assign(static_cast(measurements) * 3u, 0.0); + sofa.ir.assign(static_cast(measurements) * 2u * taps, 0.0); + for (std::uint32_t index = 0; index < measurements; ++index) { + // Fibonacci sphere: an even spread over the whole sphere, every point at + // one metre, so the set is a single shell. + const double unit = (static_cast(index) + 0.5) / static_cast(measurements); + const double elevation = std::asin(2.0 * unit - 1.0); + const double azimuth = + 2.0 * kPi * std::fmod(static_cast(index) * 0.6180339887498949, 1.0); + sofa.source_position[index * 3u + 0u] = azimuth * 180.0 / kPi; + sofa.source_position[index * 3u + 1u] = elevation * 180.0 / kPi; + sofa.source_position[index * 3u + 2u] = 1.0; + for (std::uint32_t ear = 0; ear < 2u; ++ear) { + for (std::uint32_t tap = 0; tap < taps; ++tap) { + const double decay = + std::exp(-4.0 * static_cast(tap) / static_cast(taps)); + const double phase = 0.2 * static_cast(tap) + + 0.05 * static_cast(index) + + 1.5 * static_cast(ear) + elevation; + sofa.ir[(static_cast(index) * 2u + ear) * taps + tap] = + decay * std::sin(phase); + } + } + } + return sofa; +} + +void test_sofa_canonicalize() { + const joc::hrtf::SofaHrir sofa = synthetic_sofa(64u, 64u); + + joc::hrtf::CanonicalHrtf canonical; + const joc::Status status = joc::hrtf::canonicalize_sofa(sofa, &canonical); + CHECK(status.ok()); + if (!status.ok()) { + std::printf(" canonicalize_sofa failed: %s\n", status.message().c_str()); + return; + } + CHECK(canonical.measurements == 64u && canonical.taps == 64u); + CHECK(canonical.sample_rate_hz == 48000.0); + CHECK(canonical.hrir.size() == 64u * 2u * 64u); + CHECK(canonical.delay_samples.size() == 64u * 2u); + CHECK(canonical.unit_directions.size() == 64u * 3u); + CHECK(canonical.source_position_cartesian_m.size() == 64u * 3u); + CHECK(canonical.left_receiver_index != canonical.right_receiver_index); + CHECK(canonical.left_receiver_index >= 0 && canonical.left_receiver_index < 2); + CHECK(canonical.right_receiver_index >= 0 && canonical.right_receiver_index < 2); + bool unit_length = canonical.unit_directions.size() == 64u * 3u; + bool one_shell = canonical.measurement_radius_m.size() == 64u; + for (std::size_t index = 0u; index < 64u; ++index) { + const double x = canonical.unit_directions[index * 3u + 0u]; + const double y = canonical.unit_directions[index * 3u + 1u]; + const double z = canonical.unit_directions[index * 3u + 2u]; + unit_length = unit_length && std::abs(x * x + y * y + z * z - 1.0) < 1.0e-9; + one_shell = one_shell && std::abs(canonical.measurement_radius_m[index] - 1.0) < 1.0e-9; + } + CHECK(unit_length); + CHECK(one_shell); + + // The shell the compile step selects, and the radius it reports for it. + double actual_radius = 0.0; + const std::vector shell = + joc::hrtf::canonical_shell_indices(canonical, 0.5, &actual_radius); + CHECK(shell.size() == 64u); + CHECK(std::abs(actual_radius - 1.0) < 1.0e-9); + + // The import is strict: each of these is a rejection, never a silent repair. + joc::hrtf::CanonicalHrtf rejected; + joc::hrtf::SofaHrir broken = sofa; + broken.conventions = "not-sofa"; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.sofa_conventions = "SimpleFreeFieldHRTF"; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.convention_version = "9.9"; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.data_type = "FLOAT"; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.room_type = ""; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.sampling_rate_units = "furlongs"; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.sample_rate = 0.0; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.ir[0] = std::numeric_limits::quiet_NaN(); + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.delay[1] = -1.0; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.emitter_position[0] = 0.5; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.listener_view[0] = broken.listener_view[1] = broken.listener_view[2] = 0.0; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.listener_up[0] = 1.0; // parallel to ListenerView + broken.listener_up[1] = 0.0; + broken.listener_up[2] = 0.0; + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.source_position[2] = -1.0; // a negative spherical radius + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); + broken = sofa; + broken.ir.resize(7u); + CHECK(!joc::hrtf::canonicalize_sofa(broken, &rejected).ok()); +} + +void test_sofa_compile_and_cache() { + const joc::hrtf::SofaHrir sofa = synthetic_sofa(64u, 64u); + const joc::hrtf::CompileOptions options = joc::hrtf::CompileOptions(); + joc::hrtf::Field field; + + // The runtime field is fixed at fifth order and at 48 kHz. + joc::hrtf::CompileOptions wrong_order = options; + wrong_order.order = 3; + CHECK(!joc::hrtf::compile_sofa_field(sofa, wrong_order, &field).ok()); + joc::hrtf::SofaHrir wrong_rate = sofa; + wrong_rate.sample_rate = 44100.0; + CHECK(!joc::hrtf::compile_sofa_field(wrong_rate, options, &field).ok()); + + const joc::Status status = joc::hrtf::compile_sofa_field(sofa, options, &field); + CHECK(status.ok()); + if (!status.ok()) { + std::printf(" compile_sofa_field failed: %s\n", status.message().c_str()); + return; + } + CHECK(field.order == 5); + CHECK(field.measurement_radius_m == 1.0); + CHECK(field.band_centers_hz.size() == 77u); + CHECK(field.coefficients.size() == 36u * 2u * 77u * 2u); + CHECK(field.delay_coefficients.size() == 36u * 2u); + CHECK(field.delay_bounds.size() == 4u); + CHECK(!field.cache_key.empty() && !field.payload_sha256.empty()); + CHECK(!field.metadata_json.empty() && !field.delay_source.empty()); + bool finite = true; + for (const double value : field.coefficients) { + finite = finite && std::isfinite(value); + } + for (const double value : field.delay_coefficients) { + finite = finite && std::isfinite(value); + } + CHECK(finite); + // The payload digest is a pure function of the compiled arrays. + CHECK(joc::hrtf::field_payload_sha256(field) == field.payload_sha256); + + // The cache round-trips through the shipped writer and loader. + const std::string cache_path = joc::fs_utf8::temp_directory() + "/joc_test_cache.jochrtf"; + CHECK(joc::hrtf::write_jochrtf(field, cache_path).ok()); + joc::hrtf::Field reloaded; + const joc::Status loaded = joc::hrtf::load_jochrtf(cache_path, &reloaded); + CHECK(loaded.ok()); + if (loaded.ok()) { + CHECK(reloaded.cache_key == field.cache_key); + CHECK(reloaded.source_sha256 == field.source_sha256); + CHECK(reloaded.order == field.order); + CHECK(reloaded.measurement_radius_m == field.measurement_radius_m); + CHECK(reloaded.band_centers_hz == field.band_centers_hz); + CHECK(reloaded.coefficients == field.coefficients); + CHECK(reloaded.delay_coefficients == field.delay_coefficients); + CHECK(reloaded.delay_bounds == field.delay_bounds); + CHECK(reloaded.payload_sha256 == field.payload_sha256); + } + // A cache is trusted only after its key and payload verify; a damaged one is + // rejected instead of being used. + CHECK(joc::hrtf::validate_jochrtf(cache_path, field.source_sha256, field.cache_key, nullptr) + .ok()); + CHECK(!joc::hrtf::validate_jochrtf(cache_path, field.source_sha256, "00", nullptr).ok()); + CHECK(joc::fs_utf8::remove(cache_path) == 0); + + const std::string poisoned = joc::fs_utf8::temp_directory() + "/joc_test_poisoned.jochrtf"; + CHECK(joc::io::write_zip(poisoned, {}, nullptr)); + CHECK(!joc::hrtf::validate_jochrtf(poisoned, field.source_sha256, field.cache_key, nullptr) + .ok()); + CHECK(!joc::hrtf::load_jochrtf(poisoned, &reloaded).ok()); + CHECK(joc::fs_utf8::remove(poisoned) == 0); +} + +void test_sofa_reader_errors() { + // No SOFA file is needed to check that the reader answers correctly: a path + // that does not exist and a file that is not HDF5 are distinct, reported + // errors rather than a partially filled structure. + joc::hrtf::SofaHrir sofa; + const std::string missing = joc::fs_utf8::temp_directory() + "/joc_absent.sofa"; + const joc::Status absent = joc::hrtf::load_sofa(missing, &sofa); + CHECK(!absent.ok()); + CHECK(!absent.message().empty()); + CHECK(!joc::hrtf::load_sofa(std::string(), &sofa).ok()); + CHECK(!joc::hrtf::load_sofa(missing, nullptr).ok()); + + const std::string garbage = joc::fs_utf8::temp_directory() + "/joc_garbage.sofa"; + { + std::ofstream stream = joc::fs_utf8::open_output(garbage); + stream << "this is not an HDF5 container"; + } + const joc::Status malformed = joc::hrtf::load_sofa(garbage, &sofa); + CHECK(!malformed.ok()); + CHECK(!malformed.message().empty()); + CHECK(joc::fs_utf8::remove(garbage) == 0); +} + +void test_hrtf_cache_policy() { + // The policy parser and the miss path of the cache layer, neither of which + // needs a SOFA file. + joc::hrtf::CachePolicy policy = joc::hrtf::CachePolicy::None; + CHECK(joc::hrtf::parse_cache_policy("none", &policy).ok() && + policy == joc::hrtf::CachePolicy::None); + CHECK(joc::hrtf::parse_cache_policy("memory", &policy).ok() && + policy == joc::hrtf::CachePolicy::Memory); + CHECK(joc::hrtf::parse_cache_policy("disk", &policy).ok() && + policy == joc::hrtf::CachePolicy::Disk); + CHECK(!joc::hrtf::parse_cache_policy("sometimes", &policy).ok()); + + joc::hrtf::SofaFieldRequest request; + request.sofa_path = joc::fs_utf8::temp_directory() + "/joc_absent.sofa"; + request.policy = joc::hrtf::CachePolicy::Disk; + request.cache_dir = joc::fs_utf8::temp_directory() + "/joc_absent_cache"; + joc::hrtf::Field field; + std::string written = "sentinel"; + CHECK(!joc::hrtf::load_or_compile_sofa_field(request, &field, &written).ok()); +} + +void test_rosella_model_errors() { + // A real model is proprietary user data and is not part of this repository. + // What can be checked without one is that every malformed input is reported + // instead of being half-loaded. + joc::hrtf::RosellaModel model; + const std::string missing = joc::fs_utf8::temp_directory() + "/joc_absent.headphone"; + CHECK(!joc::hrtf::load_personalized_headphone(missing, &model).ok()); + CHECK(!joc::hrtf::load_personalized_headphone(missing, nullptr).ok()); + + const std::string raw = joc::fs_utf8::temp_directory() + "/joc_raw.headphone"; + { + std::ofstream stream = joc::fs_utf8::open_output(raw); + stream << "rp binary model, not JSON"; + } + const joc::Status raw_status = joc::hrtf::load_personalized_headphone(raw, &model); + CHECK(!raw_status.ok()); + CHECK(raw_status.message().find("JSON") != std::string::npos); + CHECK(joc::fs_utf8::remove(raw) == 0); + + const std::string empty = joc::fs_utf8::temp_directory() + "/joc_empty.headphone"; + { + std::ofstream stream = joc::fs_utf8::open_output(empty); + stream << "{}"; + } + CHECK(!joc::hrtf::load_personalized_headphone(empty, &model).ok()); + CHECK(joc::fs_utf8::remove(empty) == 0); + + const std::string no_coefficients = joc::fs_utf8::temp_directory() + "/joc_no_coeff.headphone"; + { + std::ofstream stream = joc::fs_utf8::open_output(no_coefficients); + stream << "{\"personalized_hrtf\":{\"virtualizer_parameters\":{}}}"; + } + const joc::Status status = + joc::hrtf::load_personalized_headphone(no_coefficients, &model); + CHECK(!status.ok()); + CHECK(status.message().find("rosella_coefficients") != std::string::npos); + CHECK(joc::fs_utf8::remove(no_coefficients) == 0); +} + +void test_builtin_kernel_tables() { + // The filterbank tables are compiled in, and their content must stay identical + // to the standard-defined archive the file loader accepts. The hashes below are + // the SHA-256 of each member's C-order bytes. + const joc::hrtf::Kernels& kernels = joc::hrtf::builtin_kernels(); + CHECK(kernels.qmf_analysis.size() == 640); + CHECK(kernels.hybrid_low.size() == 2496); + CHECK(kernels.hybrid_indices.size() == 616); + CHECK(kernels.hybrid_values.size() == 154); + CHECK(kernels.qmf_basis.size() == 32768); + CHECK(kernels.qmf_taps.size() == 2560); + CHECK(kernels.hybrid_count == 154); + + auto hash_floats = [](const std::vector& values, bool narrow) { + joc::crypto::Sha256 hash; + if (narrow) { + std::vector raw(values.size()); + for (std::size_t i = 0; i < values.size(); ++i) { + raw[i] = static_cast(values[i]); + } + hash.update(raw.data(), raw.size() * sizeof(float)); + } else { + hash.update(values.data(), values.size() * sizeof(double)); + } + return hash.finish_hex(); + }; + CHECK(hash_floats(kernels.qmf_analysis, true) == + "aeff6c7117d41664b9c4bf03bbf563f5319ec1b8c551f171adbb90cf19d9d306"); + CHECK(hash_floats(kernels.hybrid_low, true) == + "d00d36133b81ba699a7630c4df1be203fa1b7e371e595eaaebbe8957db322627"); + CHECK(hash_floats(kernels.hybrid_values, true) == + "99409fdd9d20d1d7c2be16bbc1e2159c8042487227c72160850745164c9cee7f"); + CHECK(hash_floats(kernels.qmf_basis, false) == + "a0c4a55385f6d6c7c92d7615c83ad5fbda51046d9ef785cac0b9ac9a760dc527"); + CHECK(hash_floats(kernels.qmf_taps, false) == + "cd7756d060d51fbf02f44c1ce53cb6225b221099505c94c3f58d3bee6f428150"); + joc::crypto::Sha256 indices; + indices.update(kernels.hybrid_indices.data(), + kernels.hybrid_indices.size() * sizeof(std::int16_t)); + CHECK(indices.finish_hex() == + "f5beb3220e4530fcf28e7f4da7f07e821074265d118c911d61a590e00753a573"); +} + +} // namespace + +int main() { + test_sha256(); + test_crc32_and_inflate(); + test_bit_reader(); + test_variable_bits(); + test_eac3_frame_bytes(); + test_mini_json(); + test_npy(); + test_oamd_and_adm_helpers(); + test_int24_packing(); + test_utf8_paths(); + test_process_runner(); + test_builtin_kernel_tables(); + test_npy_and_zip_writers(); + test_sofa_canonicalize(); + test_sofa_compile_and_cache(); + test_sofa_reader_errors(); + test_hrtf_cache_policy(); + test_rosella_model_errors(); + std::printf("%d checks, %d failure(s)\n", g_checks, g_failures); + return g_failures == 0 ? 0 : 1; +} diff --git a/tests/test_headers.c b/tests/test_headers.c new file mode 100644 index 0000000..5183f7c --- /dev/null +++ b/tests/test_headers.c @@ -0,0 +1,22 @@ +/* The public headers must stay valid C: this translation unit is compiled as C + * and never linked, so it fails the build if a header stops being C-compatible. */ +#include "joc_core.h" +#include "joc_stream.h" + +int joc_header_c_probe(void) { + joc_task_config task = {0}; + joc_stream_config stream = {0}; + joc_event_sink sink = {0}; + joc_event event = {0}; + joc_task_result result = {0}; + joc_emdf_info emdf = {0}; + joc_frame_params params = {0}; + (void)task; + (void)stream; + (void)sink; + (void)event; + (void)result; + (void)emdf; + (void)params; + return (int)JOC_FRAME_SAMPLES + (int)JOC_STREAM_IN_CORE_PCM; +} diff --git a/tests/test_headers.cpp b/tests/test_headers.cpp new file mode 100644 index 0000000..c4c362f --- /dev/null +++ b/tests/test_headers.cpp @@ -0,0 +1,31 @@ +// The same headers under C++: aggregate initialisation, enum values and the +// function declarations must all be usable from a C++ translation unit. +#include "joc_core.h" +#include "joc_stream.h" + +namespace { + +int probe() { + joc_task_config task{}; + task.struct_size = sizeof(task); + task.operation = JOC_OP_BINAURAL; + task.binaural_mode = JOC_BINAURAL_MID; + joc_stream_config stream{}; + stream.struct_size = sizeof(stream); + stream.input = JOC_STREAM_IN_CORE_PCM; + stream.output = JOC_STREAM_OUT_SPEAKER; + joc_stream_buffer buffer{}; + buffer.struct_size = sizeof(buffer); + joc_stream_status_info status{}; + status.struct_size = sizeof(status); + joc_error (*create)(const joc_stream_config*, joc_stream**) = &joc_stream_create; + joc_error (*execute)(const joc_task_config*, const joc_event_sink*, joc_task_result*) = + &joc_task_execute; + return static_cast(task.operation) + static_cast(stream.output) + + static_cast(JOC_TIMESLOTS) + (create != nullptr ? 1 : 0) + + (execute != nullptr ? 1 : 0); +} + +} // namespace + +int joc_header_cpp_probe() { return probe(); }