From 4d75fbac93b7b0ea1c4884a85d9b135f3a72d0fc Mon Sep 17 00:00:00 2001 From: ImmanuelSegol <3ditds@gmail.com> Date: Wed, 14 Feb 2024 22:28:17 +0000 Subject: [PATCH 01/21] issue with init_optimized_poseidon_constants --- .../c++/multi-gpu-poseidon/CMakeLists.txt | 25 ++++ examples/c++/multi-gpu-poseidon/README.md | 2 + examples/c++/multi-gpu-poseidon/compile.sh | 9 ++ examples/c++/multi-gpu-poseidon/example.cu | 119 ++++++++++++++++++ examples/c++/multi-gpu-poseidon/run.sh | 2 + 5 files changed, 157 insertions(+) create mode 100644 examples/c++/multi-gpu-poseidon/CMakeLists.txt create mode 100644 examples/c++/multi-gpu-poseidon/README.md create mode 100755 examples/c++/multi-gpu-poseidon/compile.sh create mode 100644 examples/c++/multi-gpu-poseidon/example.cu create mode 100755 examples/c++/multi-gpu-poseidon/run.sh diff --git a/examples/c++/multi-gpu-poseidon/CMakeLists.txt b/examples/c++/multi-gpu-poseidon/CMakeLists.txt new file mode 100644 index 000000000..424b3e9bc --- /dev/null +++ b/examples/c++/multi-gpu-poseidon/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.18) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CUDA_STANDARD 17) +set(CMAKE_CUDA_STANDARD_REQUIRED TRUE) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) +if (${CMAKE_VERSION} VERSION_LESS "3.24.0") + set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH}) +else() + set(CMAKE_CUDA_ARCHITECTURES native) # on 3.24+, on earlier it is ignored, and the target is not passed +endif () +project(icicle LANGUAGES CUDA CXX) + +set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr") +set(CMAKE_CUDA_FLAGS_RELEASE "") +set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -g -G -O0") +# change the path to your Icicle location +include_directories("../../../icicle") +add_executable( + example + example.cu +) +find_library(NVML_LIBRARY nvidia-ml PATHS /usr/local/cuda/targets/x86_64-linux/lib/stubs/ ) +target_link_libraries(example ${NVML_LIBRARY}) +set_target_properties(example PROPERTIES CUDA_SEPARABLE_COMPILATION ON) + diff --git a/examples/c++/multi-gpu-poseidon/README.md b/examples/c++/multi-gpu-poseidon/README.md new file mode 100644 index 000000000..28ecc8a53 --- /dev/null +++ b/examples/c++/multi-gpu-poseidon/README.md @@ -0,0 +1,2 @@ +# Muliple GPU on a single host + diff --git a/examples/c++/multi-gpu-poseidon/compile.sh b/examples/c++/multi-gpu-poseidon/compile.sh new file mode 100755 index 000000000..36c1ddac1 --- /dev/null +++ b/examples/c++/multi-gpu-poseidon/compile.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Exit immediately on error +set -e + +rm -rf build +mkdir -p build +cmake -S . -B build +cmake --build build diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu new file mode 100644 index 000000000..91d35416e --- /dev/null +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -0,0 +1,119 @@ +#include +#include +#include + +// select the curve (only 2 available so far) +#define CURVE_ID 2 +#include "appUtils/poseidon/poseidon.cu" + +using namespace poseidon; +using namespace curve_config; + +void setCudaDevice(const unsigned device_id) { + // Example function to set the CUDA device + std::cout << "Setting CUDA device to " << device_id << std::endl; + // cudaSetDevice(device_id); +} + +// function that a thread will execute +void processData(const device_context::DeviceContext ctx, const std::vector& inputData, std::vector& outputData) { + // Simulate some processing + PoseidonConstants column_constants; + int size_col = 11; + // init_optimized_poseidon_constants(ctx, &column_constants); + init_optimized_poseidon_constants(size_col, ctx, &column_constants); + PoseidonConfig column_config = default_poseidon_config(size_col+1); + column_config.are_inputs_on_device = true; + column_config.are_outputs_on_device = true; + + for (int num : inputData) { + outputData.push_back(num * 2); // Example operation + } +} + +void checkCudaError(cudaError_t error) { + if (error != cudaSuccess) { + std::cerr << "CUDA error: " << cudaGetErrorString(error) << std::endl; + // Handle the error, e.g., exit the program or throw an exception. + } +} + +int main() { + const uint32_t size_col=11; + const unsigned size_partition = 1024; // size_row / nof_partitions; + // layers is allocated only for one partition, need to resuse for different partitions + const uint32_t size_layers = size_col * size_partition; // size_col * size_row + // Input data for each thread + std::vector inputData1 = {1, 2, 3, 4}; + std::vector inputData2 = {5, 6, 7, 8}; + + // Output data for each thread + std::vector outputData1, outputData2; + + + // Multiple devices are supported by device context + + // setCudaDevice(device_id); + cudaStream_t stream0, stream1; + cudaError_t err; + err = cudaStreamCreate(&stream0); + checkCudaError(err); + err = cudaStreamCreate(&stream1); + checkCudaError(err); + + device_context::DeviceContext ctx0 = device_context::DeviceContext{ + (cudaStream_t&)stream0, // SP: simulate different device as stream + 0, // device_id + 0, // mempool + }; + device_context::DeviceContext ctx1 = device_context::DeviceContext{ + (cudaStream_t&)stream1, // SP: simulate different device as stream + 0, // device_id + 0, // mempool + }; + + // Allocate and initialize memory for the layers + scalar_t* layers0 = static_cast(malloc(size_layers * sizeof(scalar_t))); + if (layers0 == nullptr) { + std::cerr << "Memory allocation for 'layers' failed." << std::endl; + } + scalar_t s = scalar_t::zero(); + for (unsigned i = 0; i < size_col*size_partition ; i++) { + layers0[i] = s; + s = s + scalar_t::one(); + } + scalar_t* layers1 = static_cast(malloc(size_layers * sizeof(scalar_t))); + if (layers1 == nullptr) { + std::cerr << "Memory allocation for 'layers' failed." << std::endl; + } + s = scalar_t::zero() + scalar_t::one(); + for (unsigned i = 0; i < size_col*size_partition ; i++) { + layers1[i] = s; + s = s + scalar_t::one(); + } + + + + // Start threads + std::thread thread1(processData, ctx0, std::ref(inputData1), std::ref(outputData1)); + std::thread thread2(processData, ctx1, std::ref(inputData2), std::ref(outputData2)); + + // Wait for the threads to finish + thread1.join(); + thread2.join(); + + // Process the output data (example: print the data) + std::cout << "Output Data from Thread 1: "; + for (int num : outputData1) { + std::cout << num << " "; + } + std::cout << std::endl; + + std::cout << "Output Data from Thread 2: "; + for (int num : outputData2) { + std::cout << num << " "; + } + std::cout << std::endl; + + return 0; +} diff --git a/examples/c++/multi-gpu-poseidon/run.sh b/examples/c++/multi-gpu-poseidon/run.sh new file mode 100755 index 000000000..6e3fc976d --- /dev/null +++ b/examples/c++/multi-gpu-poseidon/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +./build/example From 481f144dc80dabadb9cc7c7192bce0f94347ebd8 Mon Sep 17 00:00:00 2001 From: ImmanuelSegol <3ditds@gmail.com> Date: Thu, 15 Feb 2024 15:11:20 +0000 Subject: [PATCH 02/21] debug --- examples/c++/multi-gpu-poseidon/example.cu | 57 ++++++++++------------ icicle/appUtils/poseidon/poseidon.cuh | 1 + 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu index 91d35416e..953952922 100644 --- a/examples/c++/multi-gpu-poseidon/example.cu +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -16,11 +16,9 @@ void setCudaDevice(const unsigned device_id) { } // function that a thread will execute -void processData(const device_context::DeviceContext ctx, const std::vector& inputData, std::vector& outputData) { - // Simulate some processing +void processData(device_context::DeviceContext ctx, const std::vector& inputData, std::vector& outputData) { PoseidonConstants column_constants; int size_col = 11; - // init_optimized_poseidon_constants(ctx, &column_constants); init_optimized_poseidon_constants(size_col, ctx, &column_constants); PoseidonConfig column_config = default_poseidon_config(size_col+1); column_config.are_inputs_on_device = true; @@ -61,36 +59,33 @@ int main() { err = cudaStreamCreate(&stream1); checkCudaError(err); - device_context::DeviceContext ctx0 = device_context::DeviceContext{ - (cudaStream_t&)stream0, // SP: simulate different device as stream - 0, // device_id - 0, // mempool - }; - device_context::DeviceContext ctx1 = device_context::DeviceContext{ - (cudaStream_t&)stream1, // SP: simulate different device as stream - 0, // device_id - 0, // mempool - }; + device_context::DeviceContext ctx0 = device_context::get_default_device_context(); + ctx0.device_id=0; + device_context::DeviceContext ctx1 = device_context::get_default_device_context(); + ctx1.device_id=1; + + + // Allocate and initialize memory for the layers - scalar_t* layers0 = static_cast(malloc(size_layers * sizeof(scalar_t))); - if (layers0 == nullptr) { - std::cerr << "Memory allocation for 'layers' failed." << std::endl; - } - scalar_t s = scalar_t::zero(); - for (unsigned i = 0; i < size_col*size_partition ; i++) { - layers0[i] = s; - s = s + scalar_t::one(); - } - scalar_t* layers1 = static_cast(malloc(size_layers * sizeof(scalar_t))); - if (layers1 == nullptr) { - std::cerr << "Memory allocation for 'layers' failed." << std::endl; - } - s = scalar_t::zero() + scalar_t::one(); - for (unsigned i = 0; i < size_col*size_partition ; i++) { - layers1[i] = s; - s = s + scalar_t::one(); - } + // scalar_t* layers0 = static_cast(malloc(size_layers * sizeof(scalar_t))); + // if (layers0 == nullptr) { + // std::cerr << "Memory allocation for 'layers' failed." << std::endl; + // } + // scalar_t s = scalar_t::zero(); + // for (unsigned i = 0; i < size_col*size_partition ; i++) { + // layers0[i] = s; + // s = s + scalar_t::one(); + // } + // scalar_t* layers1 = static_cast(malloc(size_layers * sizeof(scalar_t))); + // if (layers1 == nullptr) { + // std::cerr << "Memory allocation for 'layers' failed." << std::endl; + // } + // s = scalar_t::zero() + scalar_t::one(); + // for (unsigned i = 0; i < size_col*size_partition ; i++) { + // layers1[i] = s; + // s = s + scalar_t::one(); + // } diff --git a/icicle/appUtils/poseidon/poseidon.cuh b/icicle/appUtils/poseidon/poseidon.cuh index 5541405f3..b51dfc366 100644 --- a/icicle/appUtils/poseidon/poseidon.cuh +++ b/icicle/appUtils/poseidon/poseidon.cuh @@ -119,6 +119,7 @@ namespace poseidon { /** * Loads pre-calculated optimized constants, moves them to the device */ + // Stas: I have an issue with the number of argumnets template cudaError_t init_optimized_poseidon_constants(device_context::DeviceContext& ctx, PoseidonConstants* constants); From 29675bb40d27ffa91f436b10e96a487dcb4ac281 Mon Sep 17 00:00:00 2001 From: ImmanuelSegol <3ditds@gmail.com> Date: Thu, 15 Feb 2024 16:45:33 +0000 Subject: [PATCH 03/21] executes without errors --- examples/c++/multi-gpu-poseidon/example.cu | 117 ++++++++------------- 1 file changed, 44 insertions(+), 73 deletions(-) diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu index 953952922..e0a3790de 100644 --- a/examples/c++/multi-gpu-poseidon/example.cu +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -2,33 +2,13 @@ #include #include -// select the curve (only 2 available so far) +// select the curve #define CURVE_ID 2 #include "appUtils/poseidon/poseidon.cu" using namespace poseidon; using namespace curve_config; -void setCudaDevice(const unsigned device_id) { - // Example function to set the CUDA device - std::cout << "Setting CUDA device to " << device_id << std::endl; - // cudaSetDevice(device_id); -} - -// function that a thread will execute -void processData(device_context::DeviceContext ctx, const std::vector& inputData, std::vector& outputData) { - PoseidonConstants column_constants; - int size_col = 11; - init_optimized_poseidon_constants(size_col, ctx, &column_constants); - PoseidonConfig column_config = default_poseidon_config(size_col+1); - column_config.are_inputs_on_device = true; - column_config.are_outputs_on_device = true; - - for (int num : inputData) { - outputData.push_back(num * 2); // Example operation - } -} - void checkCudaError(cudaError_t error) { if (error != cudaSuccess) { std::cerr << "CUDA error: " << cudaGetErrorString(error) << std::endl; @@ -36,78 +16,69 @@ void checkCudaError(cudaError_t error) { } } +// these global varibales go into template calls +const int size_col = 11; + +// this function executes the Poseidon thread +void threadPoseidon(device_context::DeviceContext ctx, unsigned size_partition, scalar_t * layers, scalar_t * column_hashes) { + PoseidonConstants column_constants; + init_optimized_poseidon_constants(size_col, ctx, &column_constants); + PoseidonConfig column_config = default_poseidon_config(size_col+1); + cudaError_t err = poseidon_hash(layers, column_hashes, (size_t) size_partition, column_constants, column_config); + checkCudaError(err); +} + int main() { const uint32_t size_col=11; - const unsigned size_partition = 1024; // size_row / nof_partitions; + const unsigned size_row = (1<<30); + const unsigned nof_partitions = 64; + const unsigned size_partition = size_row / nof_partitions; // layers is allocated only for one partition, need to resuse for different partitions const uint32_t size_layers = size_col * size_partition; // size_col * size_row - // Input data for each thread - std::vector inputData1 = {1, 2, 3, 4}; - std::vector inputData2 = {5, 6, 7, 8}; - - // Output data for each thread - std::vector outputData1, outputData2; - - - // Multiple devices are supported by device context - - // setCudaDevice(device_id); - cudaStream_t stream0, stream1; - cudaError_t err; - err = cudaStreamCreate(&stream0); - checkCudaError(err); - err = cudaStreamCreate(&stream1); - checkCudaError(err); + + // Key: multiple devices are supported by device context device_context::DeviceContext ctx0 = device_context::get_default_device_context(); ctx0.device_id=0; device_context::DeviceContext ctx1 = device_context::get_default_device_context(); ctx1.device_id=1; - - + // Allocate and initialize memory for the layers and hashes + scalar_t* layers0 = static_cast(malloc(size_layers * sizeof(scalar_t))); + if (layers0 == nullptr) { + std::cerr << "Memory allocation for 'layers' failed." << std::endl; + } + scalar_t s = scalar_t::zero(); + for (unsigned i = 0; i < size_col*size_partition ; i++) { + layers0[i] = s; + s = s + scalar_t::one(); + } + scalar_t* layers1 = static_cast(malloc(size_layers * sizeof(scalar_t))); + if (layers1 == nullptr) { + std::cerr << "Memory allocation for 'layers' failed." << std::endl; + } + s = scalar_t::zero() + scalar_t::one(); + for (unsigned i = 0; i < size_col*size_partition ; i++) { + layers1[i] = s; + s = s + scalar_t::one(); + } - // Allocate and initialize memory for the layers - // scalar_t* layers0 = static_cast(malloc(size_layers * sizeof(scalar_t))); - // if (layers0 == nullptr) { - // std::cerr << "Memory allocation for 'layers' failed." << std::endl; - // } - // scalar_t s = scalar_t::zero(); - // for (unsigned i = 0; i < size_col*size_partition ; i++) { - // layers0[i] = s; - // s = s + scalar_t::one(); - // } - // scalar_t* layers1 = static_cast(malloc(size_layers * sizeof(scalar_t))); - // if (layers1 == nullptr) { - // std::cerr << "Memory allocation for 'layers' failed." << std::endl; - // } - // s = scalar_t::zero() + scalar_t::one(); - // for (unsigned i = 0; i < size_col*size_partition ; i++) { - // layers1[i] = s; - // s = s + scalar_t::one(); - // } - - + scalar_t* column_hash0 = static_cast(malloc(size_partition * sizeof(scalar_t))); + scalar_t* column_hash1 = static_cast(malloc(size_partition * sizeof(scalar_t))); // Start threads - std::thread thread1(processData, ctx0, std::ref(inputData1), std::ref(outputData1)); - std::thread thread2(processData, ctx1, std::ref(inputData2), std::ref(outputData2)); + std::thread thread0(threadPoseidon, ctx0, size_partition, layers0, column_hash0); + std::thread thread1(threadPoseidon, ctx1, size_partition, layers1, column_hash1); // Wait for the threads to finish + thread0.join(); thread1.join(); - thread2.join(); // Process the output data (example: print the data) - std::cout << "Output Data from Thread 1: "; - for (int num : outputData1) { - std::cout << num << " "; - } + std::cout << "Output Data from Thread 0: "; std::cout << std::endl; - std::cout << "Output Data from Thread 2: "; - for (int num : outputData2) { - std::cout << num << " "; - } + std::cout << "Output Data from Thread 1: "; std::cout << std::endl; return 0; From 418c3d844b3f9942d54662f96a727b79a918e0a2 Mon Sep 17 00:00:00 2001 From: Stas Polonsky Date: Thu, 15 Feb 2024 22:10:15 +0000 Subject: [PATCH 04/21] completed example --- examples/c++/multi-gpu-poseidon/example.cu | 93 ++++++++++++++++------ 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu index e0a3790de..a6865958a 100644 --- a/examples/c++/multi-gpu-poseidon/example.cu +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -1,6 +1,8 @@ #include #include -#include +#include + +#include // select the curve #define CURVE_ID 2 @@ -16,26 +18,53 @@ void checkCudaError(cudaError_t error) { } } -// these global varibales go into template calls +// these global constants go into template calls const int size_col = 11; // this function executes the Poseidon thread -void threadPoseidon(device_context::DeviceContext ctx, unsigned size_partition, scalar_t * layers, scalar_t * column_hashes) { - PoseidonConstants column_constants; - init_optimized_poseidon_constants(size_col, ctx, &column_constants); - PoseidonConfig column_config = default_poseidon_config(size_col+1); - cudaError_t err = poseidon_hash(layers, column_hashes, (size_t) size_partition, column_constants, column_config); +void threadPoseidon(device_context::DeviceContext ctx, unsigned size_partition, scalar_t * layers, scalar_t * column_hashes, PoseidonConstants * constants) { + PoseidonConfig column_config = { + ctx, // ctx + false, // are_inputes_on_device + false, // are_outputs_on_device + false, // input_is_a_state + false, // aligned + false, // loop_state + false, // is_async + }; + cudaError_t err = poseidon_hash(layers, column_hashes, (size_t) size_partition, *constants, column_config); checkCudaError(err); } +using FpMilliseconds = std::chrono::duration; +#define START_TIMER(timer) auto timer##_start = std::chrono::high_resolution_clock::now(); +#define END_TIMER(timer, msg) printf("%s: %.0f ms\n", msg, FpMilliseconds(std::chrono::high_resolution_clock::now() - timer##_start).count()); + + +#define CHECK_ALLOC(ptr) if ((ptr) == nullptr) { \ + std::cerr << "Memory allocation for '" #ptr "' failed." << std::endl; \ + exit(EXIT_FAILURE); \ +} + int main() { - const uint32_t size_col=11; - const unsigned size_row = (1<<30); + const unsigned size_row = (1<<26); const unsigned nof_partitions = 64; const unsigned size_partition = size_row / nof_partitions; // layers is allocated only for one partition, need to resuse for different partitions - const uint32_t size_layers = size_col * size_partition; // size_col * size_row + const uint32_t size_layers = size_col * size_partition; + nvmlInit(); + unsigned int deviceCount; + nvmlDeviceGetCount(&deviceCount); + std::cout << "Available GPUs: " << deviceCount << std::endl; + for (unsigned int i = 0; i < deviceCount; ++i) { + nvmlDevice_t device; + char name[NVML_DEVICE_NAME_BUFFER_SIZE]; + nvmlDeviceGetHandleByIndex(i, &device); + nvmlDeviceGetName(device, name, NVML_DEVICE_NAME_BUFFER_SIZE); + std::cout << "Device ID: " << i << ", Type: " << name << std::endl; + } + // Key: multiple devices are supported by device context device_context::DeviceContext ctx0 = device_context::get_default_device_context(); @@ -43,20 +72,16 @@ int main() { device_context::DeviceContext ctx1 = device_context::get_default_device_context(); ctx1.device_id=1; - // Allocate and initialize memory for the layers and hashes + std::cout << "Allocate and initialize the memory for layers and hashes" << std::endl; scalar_t* layers0 = static_cast(malloc(size_layers * sizeof(scalar_t))); - if (layers0 == nullptr) { - std::cerr << "Memory allocation for 'layers' failed." << std::endl; - } + CHECK_ALLOC(layers0); scalar_t s = scalar_t::zero(); for (unsigned i = 0; i < size_col*size_partition ; i++) { layers0[i] = s; s = s + scalar_t::one(); } scalar_t* layers1 = static_cast(malloc(size_layers * sizeof(scalar_t))); - if (layers1 == nullptr) { - std::cerr << "Memory allocation for 'layers' failed." << std::endl; - } + CHECK_ALLOC(layers1); s = scalar_t::zero() + scalar_t::one(); for (unsigned i = 0; i < size_col*size_partition ; i++) { layers1[i] = s; @@ -64,22 +89,40 @@ int main() { } scalar_t* column_hash0 = static_cast(malloc(size_partition * sizeof(scalar_t))); + CHECK_ALLOC(column_hash0); scalar_t* column_hash1 = static_cast(malloc(size_partition * sizeof(scalar_t))); + CHECK_ALLOC(column_hash1); + + PoseidonConstants column_constants0, column_constants1; + init_optimized_poseidon_constants(size_col, ctx0, &column_constants0); + init_optimized_poseidon_constants(size_col, ctx1, &column_constants1); - // Start threads - std::thread thread0(threadPoseidon, ctx0, size_partition, layers0, column_hash0); - std::thread thread1(threadPoseidon, ctx1, size_partition, layers1, column_hash1); + std::cout << "Parallel execution of Poseidon threads" << std::endl; + START_TIMER(parallel); + std::thread thread0(threadPoseidon, ctx0, size_partition, layers0, column_hash0, &column_constants0); + std::thread thread1(threadPoseidon, ctx1, size_partition, layers1, column_hash1, &column_constants1); // Wait for the threads to finish thread0.join(); thread1.join(); - - // Process the output data (example: print the data) + END_TIMER(parallel,"2 GPUs"); std::cout << "Output Data from Thread 0: "; - std::cout << std::endl; - + std::cout << column_hash0[0] << std::endl; std::cout << "Output Data from Thread 1: "; - std::cout << std::endl; + std::cout << column_hash1[0] << std::endl; + + std::cout << "Sequential execution of Poseidon threads" << std::endl; + START_TIMER(sequential); + std::thread thread2(threadPoseidon, ctx0, size_partition, layers0, column_hash0, &column_constants0); + thread2.join(); + std::thread thread3(threadPoseidon, ctx0, size_partition, layers1, column_hash1, &column_constants0); + thread3.join(); + END_TIMER(sequential,"1 GPU"); + std::cout << "Output Data from Thread 2: "; + std::cout << column_hash0[0] << std::endl; + std::cout << "Output Data from Thread 3: "; + std::cout << column_hash1[0] << std::endl; + nvmlShutdown(); return 0; } From 8dd52306dc9fc45cea00650ef4fe123a126a03ce Mon Sep 17 00:00:00 2001 From: Stas Polonsky Date: Thu, 15 Feb 2024 23:07:33 +0000 Subject: [PATCH 05/21] update README --- examples/c++/multi-gpu-poseidon/README.md | 51 ++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/examples/c++/multi-gpu-poseidon/README.md b/examples/c++/multi-gpu-poseidon/README.md index 28ecc8a53..4fbae3338 100644 --- a/examples/c++/multi-gpu-poseidon/README.md +++ b/examples/c++/multi-gpu-poseidon/README.md @@ -1,2 +1,51 @@ -# Muliple GPU on a single host +# Icicle example: using muliple GPU to hash large dataset + +## Best-Practices + +This example builds on [single GPU Poseidon example](../poseidon/README.md) so we recommend to run it first. + +## Key-Takeaway + +Use `device_context::DeviceContext` variable to select GPU to use. +Use C++ threads to compute `Icicle` primitives on different GPUs in parallel. + +## Concise Usage Explanation + +1. Include c++ threads + +```c++ +#include +``` + +2. Define a __thread function__. Importantly, device context `ctx` will hold the GPU id. + +```c++ +void threadPoseidon(device_context::DeviceContext ctx, ...) {...} +``` + +3. Initialize device contexts for different GPUs + +```c++ +device_context::DeviceContext ctx0 = device_context::get_default_device_context(); +ctx0.device_id=0; +device_context::DeviceContext ctx1 = device_context::get_default_device_context(); +ctx1.device_id=1; +``` +4. Finally, spawn the threads and wait for their completion + +```c++ +std::thread thread0(threadPoseidon, ctx0, ...); +std::thread thread1(threadPoseidon, ctx1, ...); +thread0.join(); +thread1.join(); +``` + +## What's in the example + +This is a **toy** example executing the first step of the Filecoin's Pre-Commit 2 phase: compute $2^{30}$ Poseison hashes for each column of $11 \times 2^{30}$ matrix. + +1. Define the size of the example: $2^{30}$ won't fit on a typical machine, so we partition the problem into `nof_partitions` +2. Hash two partitions in parallel on two GPUs +3. Hash two partitions in series on one GPU +4. Compare execution times From 319358427fc8b707d53c5266ee758997da1f4d6e Mon Sep 17 00:00:00 2001 From: Stas Polonsky Date: Fri, 16 Feb 2024 16:35:04 +0000 Subject: [PATCH 06/21] cudaSetDevice in the thread function --- examples/c++/multi-gpu-poseidon/example.cu | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu index a6865958a..2db13629b 100644 --- a/examples/c++/multi-gpu-poseidon/example.cu +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -7,6 +7,7 @@ // select the curve #define CURVE_ID 2 #include "appUtils/poseidon/poseidon.cu" +#include "utils/error_handler.cuh" using namespace poseidon; using namespace curve_config; @@ -23,6 +24,12 @@ const int size_col = 11; // this function executes the Poseidon thread void threadPoseidon(device_context::DeviceContext ctx, unsigned size_partition, scalar_t * layers, scalar_t * column_hashes, PoseidonConstants * constants) { + cudaError_t err_result = CHK_STICKY(cudaSetDevice(ctx.device_id)); + if (err_result != cudaSuccess) { + std::cerr << "CUDA error: " << cudaGetErrorString(err_result) << std::endl; + return; + } + // CHK_IF_RETURN(); I can't use it in a standard thread function PoseidonConfig column_config = { ctx, // ctx false, // are_inputes_on_device @@ -30,7 +37,7 @@ void threadPoseidon(device_context::DeviceContext ctx, unsigned size_partition, false, // input_is_a_state false, // aligned false, // loop_state - false, // is_async + true, // is_async }; cudaError_t err = poseidon_hash(layers, column_hashes, (size_t) size_partition, *constants, column_config); checkCudaError(err); From 6681be549acfc9bcc8f4bb4ccfdc390519d45317 Mon Sep 17 00:00:00 2001 From: Stas Polonsky Date: Fri, 16 Feb 2024 19:43:58 +0000 Subject: [PATCH 07/21] fixed on-device memory issue --- examples/c++/multi-gpu-poseidon/example.cu | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu index 2db13629b..2d4bfbdfc 100644 --- a/examples/c++/multi-gpu-poseidon/example.cu +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -37,7 +37,7 @@ void threadPoseidon(device_context::DeviceContext ctx, unsigned size_partition, false, // input_is_a_state false, // aligned false, // loop_state - true, // is_async + false, // is_async }; cudaError_t err = poseidon_hash(layers, column_hashes, (size_t) size_partition, *constants, column_config); checkCudaError(err); @@ -102,6 +102,11 @@ int main() { PoseidonConstants column_constants0, column_constants1; init_optimized_poseidon_constants(size_col, ctx0, &column_constants0); + cudaError_t err_result = CHK_STICKY(cudaSetDevice(ctx1.device_id)); + if (err_result != cudaSuccess) { + std::cerr << "CUDA error: " << cudaGetErrorString(err_result) << std::endl; + return; + } init_optimized_poseidon_constants(size_col, ctx1, &column_constants1); std::cout << "Parallel execution of Poseidon threads" << std::endl; From 518a3ad9b65d494371c30aeecc8f191eaae74d80 Mon Sep 17 00:00:00 2001 From: Stas Polonsky Date: Sat, 17 Feb 2024 00:18:21 +0000 Subject: [PATCH 08/21] ready for PR --- examples/c++/multi-gpu-poseidon/example.cu | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu index 2d4bfbdfc..6e5d1d56a 100644 --- a/examples/c++/multi-gpu-poseidon/example.cu +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -54,7 +54,7 @@ using FpMilliseconds = std::chrono::duration Date: Sun, 18 Feb 2024 18:40:01 -0500 Subject: [PATCH 09/21] updates example compares Radix2 and MixedRadix NTTs --- examples/c++/ntt/README.md | 12 +++++++++--- examples/c++/ntt/example.cu | 37 +++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/examples/c++/ntt/README.md b/examples/c++/ntt/README.md index 5e27640b8..47103e55f 100644 --- a/examples/c++/ntt/README.md +++ b/examples/c++/ntt/README.md @@ -16,10 +16,11 @@ We recommend to run our examples in [ZK-containers](../../ZK-containers.md) to s // Include NTT template #include "appUtils/ntt/ntt.cu" using namespace curve_config; +using namespace ntt; // Configure NTT -ntt::NTTConfig config=ntt::DefaultNTTConfig(); +NTTConfig config=DefaultNTTConfig(); // Call NTT -ntt::NTT(input, ntt_size, ntt::NTTDir::kForward, config, output); +NTT(input, ntt_size, NTTDir::kForward, config, output); ``` ## Running the example @@ -28,5 +29,10 @@ ntt::NTT(input, ntt_size, ntt::NTTDir::kForward, config, output); - compile with `./compile.sh` - run with `./run.sh` +## What's in the example - +1. Define the size of the example +2. Initialize input +3. Run Radix2 NTT +4. Run MexedRadix NTT +5. Validate the data output diff --git a/examples/c++/ntt/example.cu b/examples/c++/ntt/example.cu index b72cc5554..6ae7f7bbe 100644 --- a/examples/c++/ntt/example.cu +++ b/examples/c++/ntt/example.cu @@ -7,6 +7,7 @@ #include "appUtils/ntt/ntt.cu" #include "appUtils/ntt/kernel_ntt.cu" using namespace curve_config; +using namespace ntt; // Operate on scalars typedef scalar_t S; @@ -58,11 +59,16 @@ int validate_output(const unsigned ntt_size, const unsigned nof_ntts, E* element return nof_errors; } +using FpMilliseconds = std::chrono::duration; +#define START_TIMER(timer) auto timer##_start = std::chrono::high_resolution_clock::now(); +#define END_TIMER(timer, msg) printf("%s: %.0f ms\n", msg, FpMilliseconds(std::chrono::high_resolution_clock::now() - timer##_start).count()); + + int main(int argc, char* argv[]) { std::cout << "Icicle Examples: Number Theoretical Transform (NTT)" << std::endl; std::cout << "Example parameters" << std::endl; - const unsigned log_ntt_size = 20; + const unsigned log_ntt_size = 26; std::cout << "Log2(NTT size): " << log_ntt_size << std::endl; const unsigned ntt_size = 1 << log_ntt_size; std::cout << "NTT size: " << ntt_size << std::endl; @@ -78,24 +84,27 @@ int main(int argc, char* argv[]) output = (E*)malloc(sizeof(E) * batch_size); std::cout << "Running NTT with on-host data" << std::endl; - cudaStream_t stream; - cudaStreamCreate(&stream); // Create a device context auto ctx = device_context::get_default_device_context(); - // the next line is valid only for CURVE_ID 1 (will add support for other curves soon) - S rou = S{{0x53337857, 0x53422da9, 0xdbed349f, 0xac616632, 0x6d1e303, 0x27508aba, 0xa0ed063, 0x26125da1}}; - ntt::InitDomain(rou, ctx); + const S basic_root = S::omega(log_ntt_size /*NTT_LOG_SIZE*/); + InitDomain(basic_root, ctx); // Create an NTTConfig instance - ntt::NTTConfig config = ntt::DefaultNTTConfig(); + NTTConfig config = DefaultNTTConfig(); + config.ntt_algorithm = NttAlgorithm::MixedRadix; config.batch_size = nof_ntts; - config.ctx.stream = stream; - auto begin0 = std::chrono::high_resolution_clock::now(); - cudaError_t err = ntt::NTT(input, ntt_size, ntt::NTTDir::kForward, config, output); - auto end0 = std::chrono::high_resolution_clock::now(); - auto elapsed0 = std::chrono::duration_cast(end0 - begin0); - printf("On-device runtime: %.3f seconds\n", elapsed0.count() * 1e-9); + START_TIMER(MixedRadix); + cudaError_t err = NTT(input, ntt_size, NTTDir::kForward, config, output); + END_TIMER(MixedRadix, "MixedRadix NTT"); + + config.ntt_algorithm = NttAlgorithm::Radix2; + START_TIMER(Radix2); + err = NTT(input, ntt_size, NTTDir::kForward, config, output); + END_TIMER(Radix2, "Radix2 NTT"); + + std::cout << "Validating output" << std::endl; validate_output(ntt_size, nof_ntts, output); - cudaStreamDestroy(stream); + + std::cout << "Cleaning-up memory" << std::endl; free(input); free(output); return 0; From 4664cfded5daf393ff201038c84dfa73f2fa2c38 Mon Sep 17 00:00:00 2001 From: stas Date: Mon, 19 Feb 2024 15:59:49 -0500 Subject: [PATCH 10/21] complied with reviewer's comments --- examples/c++/ntt/README.md | 2 +- examples/c++/ntt/example.cu | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/c++/ntt/README.md b/examples/c++/ntt/README.md index 47103e55f..28e8dd451 100644 --- a/examples/c++/ntt/README.md +++ b/examples/c++/ntt/README.md @@ -34,5 +34,5 @@ NTT(input, ntt_size, NTTDir::kForward, config, output); 1. Define the size of the example 2. Initialize input 3. Run Radix2 NTT -4. Run MexedRadix NTT +4. Run MixedRadix NTT 5. Validate the data output diff --git a/examples/c++/ntt/example.cu b/examples/c++/ntt/example.cu index 6ae7f7bbe..a01a54f90 100644 --- a/examples/c++/ntt/example.cu +++ b/examples/c++/ntt/example.cu @@ -68,7 +68,7 @@ int main(int argc, char* argv[]) { std::cout << "Icicle Examples: Number Theoretical Transform (NTT)" << std::endl; std::cout << "Example parameters" << std::endl; - const unsigned log_ntt_size = 26; + const unsigned log_ntt_size = 20; std::cout << "Log2(NTT size): " << log_ntt_size << std::endl; const unsigned ntt_size = 1 << log_ntt_size; std::cout << "NTT size: " << ntt_size << std::endl; @@ -96,6 +96,9 @@ int main(int argc, char* argv[]) cudaError_t err = NTT(input, ntt_size, NTTDir::kForward, config, output); END_TIMER(MixedRadix, "MixedRadix NTT"); + std::cout << "Validating output" << std::endl; + validate_output(ntt_size, nof_ntts, output); + config.ntt_algorithm = NttAlgorithm::Radix2; START_TIMER(Radix2); err = NTT(input, ntt_size, NTTDir::kForward, config, output); From b1af193f6fc72e3a089f92bf92fbb9fe048277c9 Mon Sep 17 00:00:00 2001 From: stas Date: Tue, 20 Feb 2024 19:14:25 -0500 Subject: [PATCH 11/21] fixed spelling --- examples/c++/multi-gpu-poseidon/README.md | 3 ++- examples/c++/multi-gpu-poseidon/example.cu | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/c++/multi-gpu-poseidon/README.md b/examples/c++/multi-gpu-poseidon/README.md index 4fbae3338..5fb110fe6 100644 --- a/examples/c++/multi-gpu-poseidon/README.md +++ b/examples/c++/multi-gpu-poseidon/README.md @@ -1,4 +1,4 @@ -# Icicle example: using muliple GPU to hash large dataset +# Icicle example: using multiple GPU to hash large dataset ## Best-Practices @@ -31,6 +31,7 @@ ctx0.device_id=0; device_context::DeviceContext ctx1 = device_context::get_default_device_context(); ctx1.device_id=1; ``` + 4. Finally, spawn the threads and wait for their completion ```c++ diff --git a/examples/c++/multi-gpu-poseidon/example.cu b/examples/c++/multi-gpu-poseidon/example.cu index 6e5d1d56a..edb12f9b1 100644 --- a/examples/c++/multi-gpu-poseidon/example.cu +++ b/examples/c++/multi-gpu-poseidon/example.cu @@ -57,7 +57,7 @@ int main() { const unsigned size_row = (1<<30); const unsigned nof_partitions = 64; const unsigned size_partition = size_row / nof_partitions; - // layers is allocated only for one partition, need to resuse for different partitions + // layers is allocated only for one partition, need to reuse for different partitions const uint32_t size_layers = size_col * size_partition; nvmlInit(); From 82d1ff47695d0b585d32f2932977efbf753e8e00 Mon Sep 17 00:00:00 2001 From: stas Date: Tue, 20 Feb 2024 20:40:45 -0500 Subject: [PATCH 12/21] fixed spelling in poseidon.cuh --- icicle/appUtils/poseidon/poseidon.cuh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icicle/appUtils/poseidon/poseidon.cuh b/icicle/appUtils/poseidon/poseidon.cuh index 18fcf77e8..6eb439567 100644 --- a/icicle/appUtils/poseidon/poseidon.cuh +++ b/icicle/appUtils/poseidon/poseidon.cuh @@ -119,7 +119,7 @@ namespace poseidon { /** * Loads pre-calculated optimized constants, moves them to the device */ - // Stas: I have an issue with the number of argumnets + // Stas: I have an issue with the number of arguments template cudaError_t init_optimized_poseidon_constants(int arity, device_context::DeviceContext& ctx, PoseidonConstants* constants); From c046fd17c6744a80f6be3dbda5abacc33b93fd10 Mon Sep 17 00:00:00 2001 From: stas Date: Tue, 20 Feb 2024 20:43:59 -0500 Subject: [PATCH 13/21] removed my comments from poseidon.cuh --- icicle/appUtils/poseidon/poseidon.cuh | 1 - 1 file changed, 1 deletion(-) diff --git a/icicle/appUtils/poseidon/poseidon.cuh b/icicle/appUtils/poseidon/poseidon.cuh index 6eb439567..b139dc9a3 100644 --- a/icicle/appUtils/poseidon/poseidon.cuh +++ b/icicle/appUtils/poseidon/poseidon.cuh @@ -119,7 +119,6 @@ namespace poseidon { /** * Loads pre-calculated optimized constants, moves them to the device */ - // Stas: I have an issue with the number of arguments template cudaError_t init_optimized_poseidon_constants(int arity, device_context::DeviceContext& ctx, PoseidonConstants* constants); From f9755980f0152745f5e35e03d21051ae3d534ae1 Mon Sep 17 00:00:00 2001 From: ChickenLover Date: Wed, 21 Feb 2024 21:17:10 +0700 Subject: [PATCH 14/21] add vector operations bindings to Rust (#384) * add vector operations bindings to Rust --- icicle/utils/vec_ops.cu | 154 ++++-------- icicle/utils/vec_ops.cuh | 60 ++++- wrappers/rust/icicle-core/src/lib.rs | 1 + wrappers/rust/icicle-core/src/vec_ops/mod.rs | 231 ++++++++++++++++++ .../rust/icicle-core/src/vec_ops/tests.rs | 27 ++ .../icicle-curves/icicle-bls12-377/src/lib.rs | 1 + .../icicle-bls12-377/src/vec_ops/mod.rs | 24 ++ .../icicle-curves/icicle-bls12-381/src/lib.rs | 1 + .../icicle-bls12-381/src/vec_ops/mod.rs | 20 ++ .../icicle-curves/icicle-bn254/src/lib.rs | 1 + .../icicle-bn254/src/vec_ops/mod.rs | 20 ++ .../icicle-curves/icicle-bw6-761/src/lib.rs | 1 + .../icicle-bw6-761/src/vec_ops/mod.rs | 8 + 13 files changed, 437 insertions(+), 112 deletions(-) create mode 100644 wrappers/rust/icicle-core/src/vec_ops/mod.rs create mode 100644 wrappers/rust/icicle-core/src/vec_ops/tests.rs create mode 100644 wrappers/rust/icicle-curves/icicle-bls12-377/src/vec_ops/mod.rs create mode 100644 wrappers/rust/icicle-curves/icicle-bls12-381/src/vec_ops/mod.rs create mode 100644 wrappers/rust/icicle-curves/icicle-bn254/src/vec_ops/mod.rs create mode 100644 wrappers/rust/icicle-curves/icicle-bw6-761/src/vec_ops/mod.rs diff --git a/icicle/utils/vec_ops.cu b/icicle/utils/vec_ops.cu index 55295d08b..c3e9d8ed3 100644 --- a/icicle/utils/vec_ops.cu +++ b/icicle/utils/vec_ops.cu @@ -1,9 +1,11 @@ #include #include +#include "vec_ops.cuh" #include "../curves/curve_config.cuh" #include "device_context.cuh" #include "mont.cuh" +#include "utils/utils.h" namespace vec_ops { @@ -11,8 +13,8 @@ namespace vec_ops { #define MAX_THREADS_PER_BLOCK 256 - template - __global__ void MulKernel(S* scalar_vec, E* element_vec, int n, E* result) + template + __global__ void MulKernel(E* scalar_vec, E* element_vec, int n, E* result) { int tid = blockDim.x * blockIdx.x + threadIdx.x; if (tid < n) { result[tid] = scalar_vec[tid] * element_vec[tid]; } @@ -31,12 +33,10 @@ namespace vec_ops { int tid = blockIdx.x * blockDim.x + threadIdx.x; if (tid < n) { result[tid] = element_vec1[tid] - element_vec2[tid]; } } - } // namespace - template - cudaError_t - Mul(S* vec_a, E* vec_b, int n, bool is_on_device, bool is_montgomery, device_context::DeviceContext ctx, E* result) + template + cudaError_t VecOp(E* vec_a, E* vec_b, int n, VecOpsConfig& config, E* result) { CHK_INIT_IF_RETURN(); @@ -44,103 +44,61 @@ namespace vec_ops { int num_threads = MAX_THREADS_PER_BLOCK; int num_blocks = (n + num_threads - 1) / num_threads; - S* d_vec_a; - E *d_vec_b, *d_result; - if (!is_on_device) { - // Allocate memory on the device for the input vectors and the output vector - CHK_IF_RETURN(cudaMallocAsync(&d_vec_a, n * sizeof(S), ctx.stream)); - CHK_IF_RETURN(cudaMallocAsync(&d_vec_b, n * sizeof(E), ctx.stream)); - CHK_IF_RETURN(cudaMallocAsync(&d_result, n * sizeof(E), ctx.stream)); - - // Copy the input vectors and the modulus from the host to the device - CHK_IF_RETURN(cudaMemcpyAsync(d_vec_a, vec_a, n * sizeof(S), cudaMemcpyHostToDevice, ctx.stream)); - CHK_IF_RETURN(cudaMemcpyAsync(d_vec_b, vec_b, n * sizeof(E), cudaMemcpyHostToDevice, ctx.stream)); + E *d_vec_a, *d_vec_b, *d_result; + if (!config.is_a_on_device) { + CHK_IF_RETURN(cudaMallocAsync(&d_vec_a, n * sizeof(E), config.ctx.stream)); + CHK_IF_RETURN(cudaMemcpyAsync(d_vec_a, vec_a, n * sizeof(E), cudaMemcpyHostToDevice, config.ctx.stream)); + } else { + d_vec_a = vec_a; } - E* d_res = is_on_device ? result : d_result; - // Call the kernel to perform element-wise modular multiplication - MulKernel<<>>( - is_on_device ? vec_a : d_vec_a, is_on_device ? vec_b : d_vec_b, n, d_res); - if (is_montgomery) CHK_IF_RETURN(mont::FromMontgomery(d_res, n, ctx.stream, d_res)); - - if (!is_on_device) { - CHK_IF_RETURN(cudaMemcpyAsync(result, d_result, n * sizeof(E), cudaMemcpyDeviceToHost, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_vec_a, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_vec_b, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_result, ctx.stream)); + if (!config.is_b_on_device) { + CHK_IF_RETURN(cudaMallocAsync(&d_vec_b, n * sizeof(E), config.ctx.stream)); + CHK_IF_RETURN(cudaMemcpyAsync(d_vec_b, vec_b, n * sizeof(E), cudaMemcpyHostToDevice, config.ctx.stream)); + } else { + d_vec_b = vec_b; } - return CHK_STICKY(cudaStreamSynchronize(ctx.stream)); - } - - template - cudaError_t Add(E* vec_a, E* vec_b, int n, bool is_on_device, device_context::DeviceContext ctx, E* result) - { - CHK_INIT_IF_RETURN(); + if (!config.is_result_on_device) { + CHK_IF_RETURN(cudaMallocAsync(&d_result, n * sizeof(E), config.ctx.stream)); + } else { + d_result = result; + } - // Set the grid and block dimensions - int num_threads = MAX_THREADS_PER_BLOCK; - int num_blocks = (n + num_threads - 1) / num_threads; + // Call the kernel to perform element-wise operation + Kernel<<>>(d_vec_a, d_vec_b, n, d_result); + if (config.is_result_montgomery_form) CHK_IF_RETURN(mont::FromMontgomery(d_result, n, config.ctx.stream, d_result)); - E *d_vec_a, *d_vec_b, *d_result; - if (!is_on_device) { - // Allocate memory on the device for the input vectors and the output vector - CHK_IF_RETURN(cudaMallocAsync(&d_vec_a, n * sizeof(E), ctx.stream)); - CHK_IF_RETURN(cudaMallocAsync(&d_vec_b, n * sizeof(E), ctx.stream)); - CHK_IF_RETURN(cudaMallocAsync(&d_result, n * sizeof(E), ctx.stream)); - - // Copy the input vectors from the host to the device - CHK_IF_RETURN(cudaMemcpyAsync(d_vec_a, vec_a, n * sizeof(E), cudaMemcpyHostToDevice, ctx.stream)); - CHK_IF_RETURN(cudaMemcpyAsync(d_vec_b, vec_b, n * sizeof(E), cudaMemcpyHostToDevice, ctx.stream)); - } + if (!config.is_a_on_device) { CHK_IF_RETURN(cudaFreeAsync(d_vec_a, config.ctx.stream)); } - // Call the kernel to perform element-wise addition - AddKernel<<>>( - is_on_device ? vec_a : d_vec_a, is_on_device ? vec_b : d_vec_b, n, is_on_device ? result : d_result); + if (!config.is_b_on_device) { CHK_IF_RETURN(cudaFreeAsync(d_vec_b, config.ctx.stream)); } - if (!is_on_device) { - CHK_IF_RETURN(cudaMemcpyAsync(result, d_result, n * sizeof(E), cudaMemcpyDeviceToHost, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_vec_a, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_vec_b, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_result, ctx.stream)); + if (!config.is_result_on_device) { + CHK_IF_RETURN(cudaMemcpyAsync(result, d_result, n * sizeof(E), cudaMemcpyDeviceToHost, config.ctx.stream)); + CHK_IF_RETURN(cudaFreeAsync(d_result, config.ctx.stream)); } - return CHK_STICKY(cudaStreamSynchronize(ctx.stream)); + if (!config.is_async) return CHK_STICKY(cudaStreamSynchronize(config.ctx.stream)); + + return CHK_LAST(); } template - cudaError_t Sub(E* vec_a, E* vec_b, int n, bool is_on_device, device_context::DeviceContext ctx, E* result) + cudaError_t Mul(E* vec_a, E* vec_b, int n, VecOpsConfig& config, E* result) { - CHK_INIT_IF_RETURN(); - - // Set the grid and block dimensions - int num_threads = MAX_THREADS_PER_BLOCK; - int num_blocks = (n + num_threads - 1) / num_threads; - - E *d_vec_a, *d_vec_b, *d_result; - if (!is_on_device) { - // Allocate memory on the device for the input vectors and the output vector - CHK_IF_RETURN(cudaMallocAsync(&d_vec_a, n * sizeof(E), ctx.stream)); - CHK_IF_RETURN(cudaMallocAsync(&d_vec_b, n * sizeof(E), ctx.stream)); - CHK_IF_RETURN(cudaMallocAsync(&d_result, n * sizeof(E), ctx.stream)); - - // Copy the input vectors from the host to the device - CHK_IF_RETURN(cudaMemcpyAsync(d_vec_a, vec_a, n * sizeof(E), cudaMemcpyHostToDevice, ctx.stream)); - CHK_IF_RETURN(cudaMemcpyAsync(d_vec_b, vec_b, n * sizeof(E), cudaMemcpyHostToDevice, ctx.stream)); - } - - // Call the kernel to perform element-wise subtraction - SubKernel<<>>( - is_on_device ? vec_a : d_vec_a, is_on_device ? vec_b : d_vec_b, n, is_on_device ? result : d_result); + return VecOp(vec_a, vec_b, n, config, result); + } - if (!is_on_device) { - CHK_IF_RETURN(cudaMemcpyAsync(result, d_result, n * sizeof(E), cudaMemcpyDeviceToHost, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_vec_a, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_vec_b, ctx.stream)); - CHK_IF_RETURN(cudaFreeAsync(d_result, ctx.stream)); - } + template + cudaError_t Add(E* vec_a, E* vec_b, int n, VecOpsConfig& config, E* result) + { + return VecOp(vec_a, vec_b, n, config, result); + } - return CHK_STICKY(cudaStreamSynchronize(ctx.stream)); + template + cudaError_t Sub(E* vec_a, E* vec_b, int n, VecOpsConfig& config, E* result) + { + return VecOp(vec_a, vec_b, n, config, result); } /** @@ -148,16 +106,14 @@ namespace vec_ops { * `S` and `E` being the [scalar field](@ref scalar_t) of the curve given by `-DCURVE` env variable during build. * @return `cudaSuccess` if the execution was successful and an error code otherwise. */ - extern "C" cudaError_t MulCuda( + extern "C" cudaError_t CONCAT_EXPAND(CURVE, MulCuda)( curve_config::scalar_t* vec_a, curve_config::scalar_t* vec_b, int n, - bool is_on_device, - bool is_montgomery, - device_context::DeviceContext ctx, + VecOpsConfig& config, curve_config::scalar_t* result) { - return Mul(vec_a, vec_b, n, is_on_device, is_montgomery, ctx, result); + return Mul(vec_a, vec_b, n, config, result); } /** @@ -165,15 +121,14 @@ namespace vec_ops { * `E` being the [scalar field](@ref scalar_t) of the curve given by `-DCURVE` env variable during build. * @return `cudaSuccess` if the execution was successful and an error code otherwise. */ - extern "C" cudaError_t AddCuda( + extern "C" cudaError_t CONCAT_EXPAND(CURVE, AddCuda)( curve_config::scalar_t* vec_a, curve_config::scalar_t* vec_b, int n, - bool is_on_device, - device_context::DeviceContext ctx, + VecOpsConfig& config, curve_config::scalar_t* result) { - return Add(vec_a, vec_b, n, is_on_device, ctx, result); + return Add(vec_a, vec_b, n, config, result); } /** @@ -181,15 +136,14 @@ namespace vec_ops { * `E` being the [scalar field](@ref scalar_t) of the curve given by `-DCURVE` env variable during build. * @return `cudaSuccess` if the execution was successful and an error code otherwise. */ - extern "C" cudaError_t SubCuda( + extern "C" cudaError_t CONCAT_EXPAND(CURVE, SubCuda)( curve_config::scalar_t* vec_a, curve_config::scalar_t* vec_b, int n, - bool is_on_device, - device_context::DeviceContext ctx, + VecOpsConfig& config, curve_config::scalar_t* result) { - return Sub(vec_a, vec_b, n, is_on_device, ctx, result); + return Sub(vec_a, vec_b, n, config, result); } } // namespace vec_ops \ No newline at end of file diff --git a/icicle/utils/vec_ops.cuh b/icicle/utils/vec_ops.cuh index 3b7ce6efd..fe1d349ca 100644 --- a/icicle/utils/vec_ops.cuh +++ b/icicle/utils/vec_ops.cuh @@ -10,31 +10,68 @@ */ namespace vec_ops { + /** + * @struct VecOpsConfig + * Struct that encodes NTT parameters to be passed into the [NTT](@ref NTT) function. + */ + template + struct VecOpsConfig { + device_context::DeviceContext ctx; /**< Details related to the device such as its id and stream. */ + + bool is_a_on_device; /**< True if `a` is on device and false if it is not. Default value: false. */ + + bool is_b_on_device; /**< True if `b` is on device and false if it is not. Default value: false. */ + + bool is_result_on_device; /**< If true, output is preserved on device, otherwise on host. Default value: false. */ + + bool is_result_montgomery_form; /**< True if `result` vector should be in Montgomery form and false otherwise. + * Default value: false. */ + + bool is_async; /**< Whether to run the vector operations asynchronously. If set to `true`, the function will be + * non-blocking and you'd need to synchronize it explicitly by running + * `cudaStreamSynchronize` or `cudaDeviceSynchronize`. If set to false, the + * function will block the current CPU thread. */ + }; + + /** + * A function that returns the default value of [VecOpsConfig](@ref VecOpsConfig). + * @return Default value of [VecOpsConfig](@ref VecOpsConfig). + */ + template + VecOpsConfig DefaultVecOpsConfig() + { + device_context::DeviceContext ctx = device_context::get_default_device_context(); + VecOpsConfig config = { + ctx, // ctx + false, // is_a_on_device + false, // is_b_on_device + false, // is_result_on_device + false, // is_result_montgomery_form + false, // is_async + }; + return config; + } + /** * A function that multiplies two vectors element-wise. * @param vec_a First input vector. * @param vec_b Second input vector. * @param n Size of vectors `vec_a` and `vec_b`. - * @param is_on_device If true, inputs and outputs are on device, if false - on the host. - * @param is_montgomery If true, inputs are expected to be in Montgomery form and results are returned in Montgomery - * form. If false - inputs and outputs are non-Montgomery. - * @param ctx [DeviceContext](@ref device_context::DeviceContext) used in this method. + * @param config Configuration of the operation. * @param result Resulting vector - element-wise product of `vec_a` and `vec_b`, can be the same pointer as `vec_b`. * @tparam S The type of scalars `vec_a`. * @tparam E The type of elements `vec_b` and `result`. Often (but not always) `E=S`. * @return `cudaSuccess` if the execution was successful and an error code otherwise. */ template - cudaError_t - Mul(S* vec_a, E* vec_b, int n, bool is_on_device, bool is_montgomery, device_context::DeviceContext ctx, E* result); + cudaError_t Mul(S* vec_a, E* vec_b, int n, VecOpsConfig& config, E* result); /** * A function that adds two vectors element-wise. * @param vec_a First input vector. * @param vec_b Second input vector. * @param n Size of vectors `vec_a` and `vec_b`. - * @param is_on_device If true, inputs and outputs are on device, if false - on the host. - * @param ctx [DeviceContext](@ref device_context::DeviceContext) used in this method. + * @param config Configuration of the operation. * @param result Resulting vector - element-wise sum of `vec_a` and `vec_b`, can be the same pointer as `vec_a` or * `vec_b`. If inputs are in Montgomery form, the result is too, and vice versa: non-Montgomery inputs produce * non-Montgomery result. @@ -42,15 +79,14 @@ namespace vec_ops { * @return `cudaSuccess` if the execution was successful and an error code otherwise. */ template - cudaError_t Add(E* vec_a, E* vec_b, int n, bool is_on_device, device_context::DeviceContext ctx, E* result); + cudaError_t Add(E* vec_a, E* vec_b, int n, VecOpsConfig& config, E* result); /** * A function that subtracts two vectors element-wise. * @param vec_a First input vector. * @param vec_b Second input vector. * @param n Size of vectors `vec_a` and `vec_b`. - * @param is_on_device If true, inputs and outputs are on device, if false - on the host. - * @param ctx [DeviceContext](@ref device_context::DeviceContext) used in this method. + * @param config Configuration of the operation. * @param result Resulting vector - element-wise difference of `vec_a` and `vec_b`, can be the same pointer as `vec_a` * or `vec_b`. If inputs are in Montgomery form, the result is too, and vice versa: non-Montgomery inputs produce * non-Montgomery result. @@ -58,7 +94,7 @@ namespace vec_ops { * @return `cudaSuccess` if the execution was successful and an error code otherwise. */ template - cudaError_t Sub(E* vec_a, E* vec_b, int n, bool is_on_device, device_context::DeviceContext ctx, E* result); + cudaError_t Sub(E* vec_a, E* vec_b, int n, VecOpsConfig& config, E* result); } // namespace vec_ops diff --git a/wrappers/rust/icicle-core/src/lib.rs b/wrappers/rust/icicle-core/src/lib.rs index 713ca901d..d60f86f07 100644 --- a/wrappers/rust/icicle-core/src/lib.rs +++ b/wrappers/rust/icicle-core/src/lib.rs @@ -9,6 +9,7 @@ pub mod poseidon; pub mod tests; pub mod traits; pub mod tree; +pub mod vec_ops; pub trait SNARKCurve: curve::Curve + msm::MSM where diff --git a/wrappers/rust/icicle-core/src/vec_ops/mod.rs b/wrappers/rust/icicle-core/src/vec_ops/mod.rs new file mode 100644 index 000000000..7e2593293 --- /dev/null +++ b/wrappers/rust/icicle-core/src/vec_ops/mod.rs @@ -0,0 +1,231 @@ +use icicle_cuda_runtime::{ + device_context::{DeviceContext, DEFAULT_DEVICE_ID}, + memory::HostOrDeviceSlice, +}; + +use crate::{error::IcicleResult, traits::FieldImpl}; + +pub mod tests; + +/// Struct that encodes VecOps parameters. +#[repr(C)] +#[derive(Debug, Clone)] +pub struct VecOpsConfig<'a> { + /// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext). + pub ctx: DeviceContext<'a>, + is_a_on_device: bool, + is_b_on_device: bool, + is_result_on_device: bool, + is_result_montgomery_form: bool, + /// Whether to run the vector operations asynchronously. If set to `true`, the functions will be non-blocking and you'd need to synchronize + /// it explicitly by running `stream.synchronize()`. If set to false, the functions will block the current CPU thread. + pub is_async: bool, +} + +impl<'a> Default for VecOpsConfig<'a> { + fn default() -> Self { + Self::default_for_device(DEFAULT_DEVICE_ID) + } +} + +impl<'a> VecOpsConfig<'a> { + pub fn default_for_device(device_id: usize) -> Self { + VecOpsConfig { + ctx: DeviceContext::default_for_device(device_id), + is_a_on_device: false, + is_b_on_device: false, + is_result_on_device: false, + is_result_montgomery_form: false, + is_async: false, + } + } +} + +#[doc(hidden)] +pub trait VecOps { + fn add( + a: &HostOrDeviceSlice, + b: &HostOrDeviceSlice, + result: &mut HostOrDeviceSlice, + cfg: &VecOpsConfig, + ) -> IcicleResult<()>; + + fn sub( + a: &HostOrDeviceSlice, + b: &HostOrDeviceSlice, + result: &mut HostOrDeviceSlice, + cfg: &VecOpsConfig, + ) -> IcicleResult<()>; + + fn mul( + a: &HostOrDeviceSlice, + b: &HostOrDeviceSlice, + result: &mut HostOrDeviceSlice, + cfg: &VecOpsConfig, + ) -> IcicleResult<()>; +} + +fn check_vec_ops_args(a: &HostOrDeviceSlice, b: &HostOrDeviceSlice, result: &mut HostOrDeviceSlice) { + if a.len() != b.len() || a.len() != result.len() { + panic!( + "left, right and output lengths {}; {}; {} do not match", + a.len(), + b.len(), + result.len() + ); + } +} + +pub fn add_scalars( + a: &HostOrDeviceSlice, + b: &HostOrDeviceSlice, + result: &mut HostOrDeviceSlice, + cfg: &VecOpsConfig, +) -> IcicleResult<()> +where + F: FieldImpl, + ::Config: VecOps, +{ + check_vec_ops_args(a, b, result); + <::Config as VecOps>::add(a, b, result, cfg) +} + +pub fn sub_scalars( + a: &HostOrDeviceSlice, + b: &HostOrDeviceSlice, + result: &mut HostOrDeviceSlice, + cfg: &VecOpsConfig, +) -> IcicleResult<()> +where + F: FieldImpl, + ::Config: VecOps, +{ + check_vec_ops_args(a, b, result); + <::Config as VecOps>::sub(a, b, result, cfg) +} + +pub fn mul_scalars( + a: &HostOrDeviceSlice, + b: &HostOrDeviceSlice, + result: &mut HostOrDeviceSlice, + cfg: &VecOpsConfig, +) -> IcicleResult<()> +where + F: FieldImpl, + ::Config: VecOps, +{ + check_vec_ops_args(a, b, result); + <::Config as VecOps>::mul(a, b, result, cfg) +} + +#[macro_export] +macro_rules! impl_vec_ops_field { + ( + $field_prefix:literal, + $field_prefix_ident:ident, + $field:ident, + $field_config:ident + ) => { + mod $field_prefix_ident { + use crate::vec_ops::{$field, CudaError, DeviceContext, HostOrDeviceSlice}; + use icicle_core::vec_ops::VecOpsConfig; + + extern "C" { + #[link_name = concat!($field_prefix, "AddCuda")] + pub(crate) fn add_scalars_cuda( + a: *const $field, + b: *const $field, + size: u32, + cfg: *const VecOpsConfig, + result: *mut $field, + ) -> CudaError; + + #[link_name = concat!($field_prefix, "SubCuda")] + pub(crate) fn sub_scalars_cuda( + a: *const $field, + b: *const $field, + size: u32, + cfg: *const VecOpsConfig, + result: *mut $field, + ) -> CudaError; + + #[link_name = concat!($field_prefix, "MulCuda")] + pub(crate) fn mul_scalars_cuda( + a: *const $field, + b: *const $field, + size: u32, + cfg: *const VecOpsConfig, + result: *mut $field, + ) -> CudaError; + } + } + + impl VecOps<$field> for $field_config { + fn add( + a: &HostOrDeviceSlice<$field>, + b: &HostOrDeviceSlice<$field>, + result: &mut HostOrDeviceSlice<$field>, + cfg: &VecOpsConfig, + ) -> IcicleResult<()> { + unsafe { + $field_prefix_ident::add_scalars_cuda( + a.as_ptr(), + b.as_ptr(), + a.len() as u32, + cfg as *const _ as *const VecOpsConfig, + result.as_mut_ptr(), + ) + .wrap() + } + } + + fn sub( + a: &HostOrDeviceSlice<$field>, + b: &HostOrDeviceSlice<$field>, + result: &mut HostOrDeviceSlice<$field>, + cfg: &VecOpsConfig, + ) -> IcicleResult<()> { + unsafe { + $field_prefix_ident::sub_scalars_cuda( + a.as_ptr(), + b.as_ptr(), + a.len() as u32, + cfg as *const _ as *const VecOpsConfig, + result.as_mut_ptr(), + ) + .wrap() + } + } + + fn mul( + a: &HostOrDeviceSlice<$field>, + b: &HostOrDeviceSlice<$field>, + result: &mut HostOrDeviceSlice<$field>, + cfg: &VecOpsConfig, + ) -> IcicleResult<()> { + unsafe { + $field_prefix_ident::mul_scalars_cuda( + a.as_ptr(), + b.as_ptr(), + a.len() as u32, + cfg as *const _ as *const VecOpsConfig, + result.as_mut_ptr(), + ) + .wrap() + } + } + } + }; +} + +#[macro_export] +macro_rules! impl_vec_add_tests { + ( + $field:ident + ) => { + #[test] + pub fn test_vec_add_scalars() { + check_vec_ops_scalars::<$field>() + } + }; +} diff --git a/wrappers/rust/icicle-core/src/vec_ops/tests.rs b/wrappers/rust/icicle-core/src/vec_ops/tests.rs new file mode 100644 index 000000000..b7a483f0c --- /dev/null +++ b/wrappers/rust/icicle-core/src/vec_ops/tests.rs @@ -0,0 +1,27 @@ +use crate::traits::GenerateRandom; +use crate::vec_ops::{add_scalars, mul_scalars, sub_scalars, FieldImpl, HostOrDeviceSlice, VecOps, VecOpsConfig}; + +pub fn check_vec_ops_scalars() +where + ::Config: VecOps + GenerateRandom, +{ + let test_size = 1 << 14; + + let a = HostOrDeviceSlice::on_host(F::Config::generate_random(test_size)); + let b = HostOrDeviceSlice::on_host(F::Config::generate_random(test_size)); + let ones = HostOrDeviceSlice::on_host(vec![F::one(); test_size]); + let mut result = HostOrDeviceSlice::on_host(vec![F::zero(); test_size]); + let mut result2 = HostOrDeviceSlice::on_host(vec![F::zero(); test_size]); + let mut result3 = HostOrDeviceSlice::on_host(vec![F::zero(); test_size]); + + let cfg = VecOpsConfig::default(); + add_scalars(&a, &b, &mut result, &cfg).unwrap(); + + sub_scalars(&result, &b, &mut result2, &cfg).unwrap(); + + assert_eq!(a[0..1][0], result2[0..1][0]); + + mul_scalars(&a, &ones, &mut result3, &cfg).unwrap(); + + assert_eq!(a[0..1][0], result3[0..1][0]); +} diff --git a/wrappers/rust/icicle-curves/icicle-bls12-377/src/lib.rs b/wrappers/rust/icicle-curves/icicle-bls12-377/src/lib.rs index 009326772..2bda6aec3 100644 --- a/wrappers/rust/icicle-curves/icicle-bls12-377/src/lib.rs +++ b/wrappers/rust/icicle-curves/icicle-bls12-377/src/lib.rs @@ -3,5 +3,6 @@ pub mod msm; pub mod ntt; pub mod poseidon; pub mod tree; +pub mod vec_ops; impl icicle_core::SNARKCurve for curve::CurveCfg {} diff --git a/wrappers/rust/icicle-curves/icicle-bls12-377/src/vec_ops/mod.rs b/wrappers/rust/icicle-curves/icicle-bls12-377/src/vec_ops/mod.rs new file mode 100644 index 000000000..e41b3f17c --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-bls12-377/src/vec_ops/mod.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "bw6-761")] +use crate::curve::{BaseCfg, BaseField}; +use crate::curve::{ScalarCfg, ScalarField}; + +use icicle_core::error::IcicleResult; +use icicle_core::impl_vec_ops_field; +use icicle_core::traits::IcicleResultWrap; +use icicle_core::vec_ops::{VecOps, VecOpsConfig}; +use icicle_cuda_runtime::device_context::DeviceContext; +use icicle_cuda_runtime::error::CudaError; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +impl_vec_ops_field!("bls12_377", bls12_377, ScalarField, ScalarCfg); +#[cfg(feature = "bw6-761")] +impl_vec_ops_field!("bw6_761", bw6_761, BaseField, BaseCfg); + +#[cfg(test)] +pub(crate) mod tests { + use crate::curve::ScalarField; + use icicle_core::impl_vec_add_tests; + use icicle_core::vec_ops::tests::*; + + impl_vec_add_tests!(ScalarField); +} diff --git a/wrappers/rust/icicle-curves/icicle-bls12-381/src/lib.rs b/wrappers/rust/icicle-curves/icicle-bls12-381/src/lib.rs index 009326772..2bda6aec3 100644 --- a/wrappers/rust/icicle-curves/icicle-bls12-381/src/lib.rs +++ b/wrappers/rust/icicle-curves/icicle-bls12-381/src/lib.rs @@ -3,5 +3,6 @@ pub mod msm; pub mod ntt; pub mod poseidon; pub mod tree; +pub mod vec_ops; impl icicle_core::SNARKCurve for curve::CurveCfg {} diff --git a/wrappers/rust/icicle-curves/icicle-bls12-381/src/vec_ops/mod.rs b/wrappers/rust/icicle-curves/icicle-bls12-381/src/vec_ops/mod.rs new file mode 100644 index 000000000..01cff3db7 --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-bls12-381/src/vec_ops/mod.rs @@ -0,0 +1,20 @@ +use crate::curve::{ScalarCfg, ScalarField}; + +use icicle_core::error::IcicleResult; +use icicle_core::impl_vec_ops_field; +use icicle_core::traits::IcicleResultWrap; +use icicle_core::vec_ops::{VecOps, VecOpsConfig}; +use icicle_cuda_runtime::device_context::DeviceContext; +use icicle_cuda_runtime::error::CudaError; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +impl_vec_ops_field!("bls12_381", bls12_381, ScalarField, ScalarCfg); + +#[cfg(test)] +pub(crate) mod tests { + use crate::curve::ScalarField; + use icicle_core::impl_vec_add_tests; + use icicle_core::vec_ops::tests::*; + + impl_vec_add_tests!(ScalarField); +} diff --git a/wrappers/rust/icicle-curves/icicle-bn254/src/lib.rs b/wrappers/rust/icicle-curves/icicle-bn254/src/lib.rs index 009326772..2bda6aec3 100644 --- a/wrappers/rust/icicle-curves/icicle-bn254/src/lib.rs +++ b/wrappers/rust/icicle-curves/icicle-bn254/src/lib.rs @@ -3,5 +3,6 @@ pub mod msm; pub mod ntt; pub mod poseidon; pub mod tree; +pub mod vec_ops; impl icicle_core::SNARKCurve for curve::CurveCfg {} diff --git a/wrappers/rust/icicle-curves/icicle-bn254/src/vec_ops/mod.rs b/wrappers/rust/icicle-curves/icicle-bn254/src/vec_ops/mod.rs new file mode 100644 index 000000000..9447aa8dc --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-bn254/src/vec_ops/mod.rs @@ -0,0 +1,20 @@ +use crate::curve::{ScalarCfg, ScalarField}; + +use icicle_core::error::IcicleResult; +use icicle_core::impl_vec_ops_field; +use icicle_core::traits::IcicleResultWrap; +use icicle_core::vec_ops::{VecOps, VecOpsConfig}; +use icicle_cuda_runtime::device_context::DeviceContext; +use icicle_cuda_runtime::error::CudaError; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +impl_vec_ops_field!("bn254", bn254, ScalarField, ScalarCfg); + +#[cfg(test)] +pub(crate) mod tests { + use crate::curve::ScalarField; + use icicle_core::impl_vec_add_tests; + use icicle_core::vec_ops::tests::*; + + impl_vec_add_tests!(ScalarField); +} diff --git a/wrappers/rust/icicle-curves/icicle-bw6-761/src/lib.rs b/wrappers/rust/icicle-curves/icicle-bw6-761/src/lib.rs index 009326772..2bda6aec3 100644 --- a/wrappers/rust/icicle-curves/icicle-bw6-761/src/lib.rs +++ b/wrappers/rust/icicle-curves/icicle-bw6-761/src/lib.rs @@ -3,5 +3,6 @@ pub mod msm; pub mod ntt; pub mod poseidon; pub mod tree; +pub mod vec_ops; impl icicle_core::SNARKCurve for curve::CurveCfg {} diff --git a/wrappers/rust/icicle-curves/icicle-bw6-761/src/vec_ops/mod.rs b/wrappers/rust/icicle-curves/icicle-bw6-761/src/vec_ops/mod.rs new file mode 100644 index 000000000..cb3ad9782 --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-bw6-761/src/vec_ops/mod.rs @@ -0,0 +1,8 @@ +#[cfg(test)] +pub(crate) mod tests { + use crate::curve::ScalarField; + use icicle_core::impl_vec_add_tests; + use icicle_core::vec_ops::tests::*; + + impl_vec_add_tests!(ScalarField); +} From 965bf757f9c9ffe8b7ba5f5b4df7049494c3e8d3 Mon Sep 17 00:00:00 2001 From: ChickenLover Date: Wed, 21 Feb 2024 22:30:40 +0700 Subject: [PATCH 15/21] update examples with new vec ops (#388) --- examples/c++/multiply/example.cu | 12 ++++++------ examples/c++/polynomial_multiplication/example.cu | 10 +++++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/examples/c++/multiply/example.cu b/examples/c++/multiply/example.cu index 5589a2d05..64cd52977 100644 --- a/examples/c++/multiply/example.cu +++ b/examples/c++/multiply/example.cu @@ -10,15 +10,15 @@ using namespace curve_config; -// select scalar or point field -//typedef scalar_t T; -typedef point_field_t T; +typedef scalar_t T; int vector_mult(T* vec_b, T* vec_a, T* vec_result, size_t n_elments, device_context::DeviceContext ctx) { - const bool is_on_device = true; - const bool is_montgomery = false; - cudaError_t err = vec_ops::Mul(vec_a, vec_b, n_elments, is_on_device, is_montgomery, ctx, vec_result); + vec_ops::VecOpsConfig config = vec_ops::DefaultVecOpsConfig(); + config.is_a_on_device = true; + config.is_b_on_device = true; + config.is_result_on_device = true; + cudaError_t err = vec_ops::Mul(vec_a, vec_b, n_elments, config, vec_result); if (err != cudaSuccess) { std::cerr << "Failed to multiply vectors - " << cudaGetErrorString(err) << std::endl; return 0; diff --git a/examples/c++/polynomial_multiplication/example.cu b/examples/c++/polynomial_multiplication/example.cu index ada721123..bc39f0c24 100644 --- a/examples/c++/polynomial_multiplication/example.cu +++ b/examples/c++/polynomial_multiplication/example.cu @@ -84,8 +84,16 @@ int main(int argc, char** argv) // (4) multiply A,B CHK_IF_RETURN(cudaMallocAsync(&MulGpu, sizeof(test_data) * NTT_SIZE, ntt_config.ctx.stream)); + vec_ops::VecOpsConfig config { + ntt_config.ctx, + true, // is_a_on_device + true, // is_b_on_device + true, // is_result_on_device + false, // is_montgomery + false // is_async + }; CHK_IF_RETURN( - vec_ops::Mul(GpuA, GpuB, NTT_SIZE, true /*=is_on_device*/, false /*=is_montgomery*/, ntt_config.ctx, MulGpu)); + vec_ops::Mul(GpuA, GpuB, NTT_SIZE, config, MulGpu)); // (5) INTT (in place) ntt_config.are_inputs_on_device = true; From 4b221e96658ae08130bc9dc5b4134f7f57eb555c Mon Sep 17 00:00:00 2001 From: nonam3e <71525212+nonam3e@users.noreply.github.com> Date: Wed, 21 Feb 2024 23:20:28 +0700 Subject: [PATCH 16/21] Grumpkin curve implementation (#379) --- icicle/CMakeLists.txt | 12 +- icicle/appUtils/poseidon/constants.cu | 3 + .../poseidon/constants/generate_parameters.py | 6 +- .../poseidon/constants/grumpkin_poseidon.h | 10806 ++++++++++++++++ icicle/curves/curve_config.cuh | 4 + icicle/curves/grumpkin_params.cuh | 22 + wrappers/rust/Cargo.toml | 1 + .../icicle-core/tests/grumpkin_constants.bin | Bin 0 -> 12096 bytes .../icicle-curves/icicle-grumpkin/Cargo.toml | 28 + .../icicle-curves/icicle-grumpkin/build.rs | 19 + .../icicle-grumpkin/src/curve.rs | 39 + .../icicle-curves/icicle-grumpkin/src/lib.rs | 5 + .../icicle-grumpkin/src/msm/mod.rs | 21 + .../icicle-grumpkin/src/poseidon/mod.rs | 22 + .../icicle-grumpkin/src/tree/mod.rs | 21 + .../icicle-grumpkin/src/vec_ops/mod.rs | 20 + 16 files changed, 11023 insertions(+), 6 deletions(-) create mode 100644 icicle/appUtils/poseidon/constants/grumpkin_poseidon.h create mode 100644 icicle/curves/grumpkin_params.cuh create mode 100644 wrappers/rust/icicle-core/tests/grumpkin_constants.bin create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/Cargo.toml create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/build.rs create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/src/curve.rs create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/src/lib.rs create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/src/msm/mod.rs create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/src/poseidon/mod.rs create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/src/tree/mod.rs create mode 100644 wrappers/rust/icicle-curves/icicle-grumpkin/src/vec_ops/mod.rs diff --git a/icicle/CMakeLists.txt b/icicle/CMakeLists.txt index 6e6e3f31c..6e8910639 100644 --- a/icicle/CMakeLists.txt +++ b/icicle/CMakeLists.txt @@ -68,8 +68,9 @@ include_directories("${CMAKE_SOURCE_DIR}") # when adding a new curve/field, append its name to the end of this list -set(SUPPORTED_CURVES bn254;bls12_381;bls12_377;bw6_761) -set(SUPPORTED_CURVES_WITH_POSEIDON bn254;bls12_381;bls12_377;bw6_761) +set(SUPPORTED_CURVES bn254;bls12_381;bls12_377;bw6_761;grumpkin) +set(SUPPORTED_CURVES_WITH_POSEIDON bn254;bls12_381;bls12_377;bw6_761;grumpkin) +SET(SUPPORTED_CURVES_WITHOUT_NTT grumpkin) set(IS_CURVE_SUPPORTED FALSE) set(I 0) @@ -100,6 +101,11 @@ if (NOT BUILD_TESTS) list(APPEND ICICLE_SOURCES appUtils/tree/merkle.cu) endif() + if (NOT CURVE IN_LIST SUPPORTED_CURVES_WITHOUT_NTT) + list(APPEND ICICLE_SOURCES appUtils/ntt/ntt.cu) + list(APPEND ICICLE_SOURCES appUtils/ntt/kernel_ntt.cu) + endif() + add_library( icicle utils/vec_ops.cu @@ -107,8 +113,6 @@ if (NOT BUILD_TESTS) primitives/field.cu primitives/projective.cu appUtils/msm/msm.cu - appUtils/ntt/ntt.cu - appUtils/ntt/kernel_ntt.cu ${ICICLE_SOURCES} ) set_target_properties(icicle PROPERTIES OUTPUT_NAME "ingo_${CURVE}") diff --git a/icicle/appUtils/poseidon/constants.cu b/icicle/appUtils/poseidon/constants.cu index d8cd4be6a..8cbd5c10c 100644 --- a/icicle/appUtils/poseidon/constants.cu +++ b/icicle/appUtils/poseidon/constants.cu @@ -13,6 +13,9 @@ using namespace poseidon_constants_bls12_377; #elif CURVE_ID == BW6_761 #include "appUtils/poseidon/constants/bw6_761_poseidon.h" using namespace poseidon_constants_bw6_761; +#elif CURVE_ID == GRUMPKIN +#include "appUtils/poseidon/constants/grumpkin_poseidon.h" +using namespace poseidon_constants_grumpkin; #endif namespace poseidon { diff --git a/icicle/appUtils/poseidon/constants/generate_parameters.py b/icicle/appUtils/poseidon/constants/generate_parameters.py index 4d2f79399..915f307d8 100755 --- a/icicle/appUtils/poseidon/constants/generate_parameters.py +++ b/icicle/appUtils/poseidon/constants/generate_parameters.py @@ -9,7 +9,8 @@ # Modify these arity = 11 -p = 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001 # bls12-381 +p = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 # grumpkin +# p = 0x73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001 # bls12-381 # p = 0x12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001 # bls12-377 # p = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 # bn254 # p = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001 # bw6-761 @@ -31,10 +32,11 @@ # F.primitive_element() # # primitive_element = None -primitive_element = 7 # bls12-381 +# primitive_element = 7 # bls12-381 # primitive_element = 22 # bls12-377 # primitive_element = 5 # bn254 # primitive_element = 15 # bw6-761 +primitive_element = 3 # grumpkin # currently we only support alpha 5, if you need alpha other than 5 - feal free to reach out alpha = 5 diff --git a/icicle/appUtils/poseidon/constants/grumpkin_poseidon.h b/icicle/appUtils/poseidon/constants/grumpkin_poseidon.h new file mode 100644 index 000000000..32c55ccb8 --- /dev/null +++ b/icicle/appUtils/poseidon/constants/grumpkin_poseidon.h @@ -0,0 +1,10806 @@ +#pragma once +#ifndef GRUMPKIN_POSEIDON_H +#define GRUMPKIN_POSEIDON_H + +namespace poseidon_constants_grumpkin { + /** + * This inner namespace contains optimized constants for running Poseidon. + * These constants were generated using an algorithm defined at + * https://spec.filecoin.io/algorithms/crypto/poseidon/ + * The number in the name corresponds to the arity of hash function + * Each array contains: + * RoundConstants | MDSMatrix | Non-sparse matrix | Sparse matrices + */ + + int partial_rounds_2 = 56; + + int partial_rounds_4 = 56; + + int partial_rounds_8 = 57; + + int partial_rounds_11 = 57; + + unsigned char poseidon_constants_2[] = { + 0x31, 0x2a, 0xfd, 0xbb, 0x33, 0xfa, 0x28, 0xd8, 0xb9, 0x3b, 0x37, 0x56, + 0xca, 0x07, 0x07, 0x22, 0xb4, 0xc2, 0x89, 0x50, 0x50, 0xc1, 0x51, 0x59, + 0x0d, 0xe6, 0xec, 0xb8, 0x46, 0x23, 0x51, 0x21, 0xc8, 0x88, 0xa5, 0x3d, + 0x75, 0x06, 0x36, 0x19, 0x10, 0x48, 0x3b, 0xfc, 0xd7, 0xe0, 0x91, 0x42, + 0xba, 0xbe, 0xbb, 0x99, 0xe1, 0x48, 0xc5, 0x92, 0x3e, 0xe8, 0x69, 0x2c, + 0x25, 0x40, 0x3a, 0x2b, 0x64, 0xd4, 0xc0, 0xc1, 0xe8, 0x80, 0xbe, 0x12, + 0x3e, 0x84, 0x54, 0x29, 0xbd, 0x10, 0xfb, 0x96, 0x45, 0x73, 0x75, 0x44, + 0xea, 0x82, 0xc0, 0x87, 0x41, 0x3c, 0x30, 0x3f, 0x8e, 0x77, 0x1a, 0x2a, + 0x68, 0x36, 0x15, 0x10, 0x26, 0x5c, 0xec, 0xaf, 0x74, 0x58, 0xeb, 0x5f, + 0xbd, 0x33, 0x03, 0x08, 0x0a, 0x70, 0x26, 0x37, 0x9e, 0xc7, 0x07, 0x0d, + 0x5b, 0x15, 0x6a, 0x14, 0xa2, 0xb4, 0xdb, 0x03, 0x78, 0x4b, 0xf4, 0xf3, + 0xe2, 0x61, 0x26, 0x4b, 0xd2, 0x31, 0x7a, 0x80, 0xc3, 0x56, 0x8a, 0x2c, + 0x8a, 0xe8, 0x2f, 0x20, 0xf1, 0x3e, 0x52, 0x52, 0xa6, 0x63, 0xc7, 0x44, + 0x4f, 0x82, 0x24, 0x10, 0xc9, 0xfb, 0xf5, 0x90, 0xbb, 0x9e, 0x84, 0x83, + 0xc5, 0x28, 0x0c, 0xf4, 0xa0, 0xad, 0x94, 0xe1, 0x19, 0x16, 0x98, 0x22, + 0x36, 0x30, 0x40, 0xef, 0xa1, 0x45, 0x49, 0xb1, 0xdf, 0x64, 0xda, 0x0f, + 0xfa, 0x61, 0x87, 0x99, 0xbd, 0xa7, 0xc1, 0x06, 0x04, 0x24, 0xfd, 0x6e, + 0x91, 0x0c, 0xc4, 0x68, 0x63, 0x5a, 0xfc, 0x40, 0xbe, 0xbb, 0xe4, 0x11, + 0xec, 0x50, 0x4f, 0x61, 0xdd, 0x17, 0x68, 0x07, 0x4d, 0x61, 0x35, 0xbb, + 0x2a, 0x8b, 0x22, 0x6c, 0xe0, 0xe6, 0xbf, 0xc9, 0x91, 0x50, 0x63, 0xfe, + 0xfa, 0x12, 0x9d, 0xb4, 0x8c, 0x2e, 0x14, 0x8a, 0x49, 0x2d, 0x81, 0xc1, + 0x26, 0x0a, 0xe1, 0x29, 0xe6, 0x21, 0x39, 0x95, 0x15, 0x54, 0xc8, 0xca, + 0xaf, 0x7f, 0x7e, 0xcb, 0xb6, 0xa3, 0x88, 0xf8, 0x1f, 0x8c, 0x3a, 0x62, + 0x93, 0x84, 0x86, 0xbe, 0xac, 0xa8, 0x88, 0xdc, 0xe6, 0x93, 0xa4, 0x20, + 0x11, 0x44, 0xa4, 0x9e, 0xeb, 0x8a, 0xfb, 0x26, 0x97, 0xa1, 0x03, 0x20, + 0x70, 0x55, 0xce, 0x18, 0x4c, 0x26, 0xd0, 0x2e, 0xd5, 0x90, 0x6f, 0x33, + 0x7c, 0xf4, 0xe8, 0x7a, 0x78, 0x5e, 0xe1, 0x15, 0xc8, 0x19, 0xfa, 0x64, + 0xea, 0xa0, 0xc9, 0x36, 0x36, 0x94, 0x2f, 0xcc, 0x69, 0xce, 0x2a, 0xd0, + 0xff, 0x4d, 0x8a, 0xf7, 0x59, 0x21, 0x9f, 0x57, 0x71, 0x45, 0x9c, 0xba, + 0xbf, 0xd9, 0xc2, 0x24, 0x18, 0x9d, 0x9f, 0xb9, 0x3b, 0x16, 0x8d, 0xc7, + 0x5f, 0x76, 0x39, 0x39, 0x43, 0x75, 0xd5, 0xe2, 0x2f, 0x12, 0x44, 0x5e, + 0xf8, 0x9b, 0x06, 0x00, 0x1f, 0xec, 0x63, 0x23, 0x5d, 0xf5, 0xd3, 0x0f, + 0x28, 0x23, 0xc3, 0xcc, 0xaa, 0xa3, 0xcb, 0xbd, 0x50, 0x95, 0x6f, 0x90, + 0xba, 0x7d, 0x3e, 0x79, 0x21, 0x3c, 0x40, 0xcb, 0x5c, 0x27, 0x2c, 0xc1, + 0x44, 0x76, 0x54, 0xd7, 0xb8, 0xe0, 0x01, 0x10, 0x87, 0x10, 0x97, 0xc8, + 0xde, 0x69, 0x1a, 0x51, 0x84, 0x64, 0x4b, 0x11, 0xf2, 0xc6, 0x2d, 0xd8, + 0x98, 0xce, 0xc4, 0x9e, 0xd6, 0x69, 0x62, 0xf8, 0x4e, 0x70, 0x5a, 0x0c, + 0x22, 0x83, 0x42, 0x1a, 0xdb, 0x71, 0x4a, 0xf6, 0x59, 0x2c, 0x75, 0xef, + 0x73, 0x54, 0x0d, 0xdf, 0x32, 0x74, 0x70, 0xb2, 0x74, 0x9d, 0x8b, 0x6e, + 0x4a, 0xb9, 0xeb, 0x3e, 0x29, 0x02, 0xe9, 0xc1, 0x14, 0xec, 0xe3, 0x19, + 0x29, 0x39, 0xc8, 0x93, 0xcd, 0x9d, 0x40, 0x63, 0xe1, 0x5a, 0x5a, 0xb5, + 0x7d, 0x9c, 0x26, 0x0b, 0x20, 0x01, 0xff, 0xdc, 0xaa, 0xc4, 0x6e, 0x8f, + 0x1a, 0xc6, 0x72, 0xff, 0x6c, 0x51, 0x08, 0x06, 0x21, 0xb6, 0x6f, 0xa1, + 0xdb, 0x9c, 0x64, 0xfc, 0x95, 0x40, 0xe4, 0x22, 0xfe, 0x2b, 0xe7, 0x87, + 0x70, 0x34, 0x3f, 0x7c, 0x02, 0xa0, 0xd4, 0xa9, 0x50, 0x5b, 0x05, 0xb4, + 0x3f, 0xb1, 0xee, 0x26, 0xf8, 0xdc, 0x47, 0x89, 0xec, 0xdc, 0x83, 0xd4, + 0xb0, 0xf1, 0x89, 0x31, 0xe8, 0x65, 0x1a, 0xc1, 0x3b, 0x9b, 0x60, 0x1e, + 0x9a, 0x3d, 0xa2, 0xa9, 0xf1, 0xf5, 0x5c, 0x26, 0xd0, 0xd1, 0x39, 0x2a, + 0xef, 0x4b, 0xf1, 0x19, 0xff, 0xb9, 0x95, 0x8a, 0xc7, 0x29, 0xc0, 0xdc, + 0x45, 0xea, 0xa4, 0x49, 0x01, 0x79, 0xca, 0xf9, 0x40, 0x93, 0x94, 0x5c, + 0xc5, 0x85, 0xc2, 0xbb, 0xa9, 0x36, 0x7c, 0x2a, 0xce, 0xf0, 0x53, 0x36, + 0x80, 0xab, 0x71, 0xd3, 0xf9, 0x98, 0x26, 0x8f, 0xb1, 0x32, 0x91, 0x22, + 0xea, 0x3c, 0x4a, 0x61, 0x09, 0x98, 0xa6, 0xd7, 0x70, 0x99, 0xd8, 0xe8, + 0xad, 0xed, 0x8e, 0x06, 0xbf, 0xcf, 0x71, 0x55, 0xa3, 0x8f, 0xc9, 0x6c, + 0xca, 0xca, 0xa3, 0x80, 0xd7, 0x65, 0x3d, 0xeb, 0x21, 0x0c, 0xa6, 0xb3, + 0x5c, 0x97, 0xa0, 0x43, 0xb8, 0xe8, 0x55, 0x20, 0x53, 0xd2, 0x9a, 0x2f, + 0xe7, 0x94, 0xcf, 0x39, 0x5e, 0x26, 0x76, 0x8e, 0xc2, 0xb0, 0x88, 0x85, + 0xde, 0xa0, 0xbd, 0xaa, 0x6a, 0xca, 0x2a, 0x3a, 0x4b, 0xc9, 0x16, 0x99, + 0x30, 0x26, 0xd7, 0x6c, 0xf5, 0x1b, 0x93, 0x0a, 0xdd, 0x91, 0xce, 0x2e, + 0x70, 0x00, 0xeb, 0x9b, 0xfe, 0xd3, 0x12, 0x1f, 0xe0, 0xc1, 0xd6, 0x0b, + 0x0c, 0x74, 0x2c, 0xac, 0x96, 0xc7, 0x85, 0x68, 0x77, 0x6f, 0x8d, 0x10, + 0x37, 0xd9, 0x5a, 0x12, 0x08, 0x57, 0x2a, 0x07, 0xda, 0x3b, 0x50, 0xdf, + 0xa7, 0xe8, 0x6c, 0x13, 0x3c, 0x36, 0x2b, 0x2c, 0x09, 0xe0, 0xfa, 0xcc, + 0x92, 0xe2, 0x86, 0x69, 0x22, 0xfb, 0x95, 0x8d, 0xb4, 0xb6, 0xe9, 0x0a, + 0xbf, 0xe0, 0x49, 0x02, 0x81, 0xe4, 0xf9, 0x33, 0xda, 0x41, 0x1c, 0xee, + 0x66, 0x8b, 0x9a, 0x92, 0x6e, 0xa3, 0x6f, 0x2c, 0x9c, 0xfe, 0x2b, 0x5f, + 0x73, 0x1f, 0x82, 0xb1, 0x51, 0xdd, 0x17, 0x13, 0xfb, 0x24, 0xd1, 0x80, + 0x5f, 0xad, 0xc5, 0xcf, 0x64, 0xcc, 0xa8, 0x27, 0x75, 0x93, 0x70, 0xf5, + 0xfe, 0xa0, 0x4c, 0x55, 0x47, 0x85, 0x4f, 0xfd, 0x70, 0x01, 0xd3, 0xc8, + 0xf9, 0x10, 0x1a, 0x26, 0x43, 0xb9, 0xb6, 0x42, 0xf8, 0x0a, 0xde, 0x68, + 0xe3, 0x6b, 0xc4, 0x49, 0xf9, 0x49, 0x1c, 0x52, 0x68, 0x09, 0xad, 0xbb, + 0x19, 0x31, 0x24, 0xde, 0x84, 0x4b, 0x4b, 0x24, 0x40, 0x27, 0x43, 0x2d, + 0xb4, 0x9c, 0x8d, 0xfa, 0xeb, 0x37, 0xee, 0x26, 0xf3, 0x06, 0xdb, 0xdc, + 0xd8, 0xcb, 0x76, 0x9e, 0x76, 0x25, 0xe2, 0x27, 0xe7, 0x21, 0xc8, 0x60, + 0x53, 0x62, 0x28, 0x32, 0x13, 0xd9, 0xac, 0x10, 0x00, 0x29, 0x3f, 0xcb, + 0x70, 0x65, 0x15, 0x4d, 0x7d, 0x8c, 0xdf, 0x0a, 0xe8, 0x06, 0xef, 0xa8, + 0xcc, 0xda, 0xf9, 0xe9, 0x0f, 0x95, 0xea, 0x72, 0x99, 0x41, 0x0b, 0x81, + 0x26, 0x01, 0xf1, 0x00, 0x25, 0xc0, 0xc1, 0x85, 0xcf, 0xd0, 0x5f, 0xf0, + 0x2c, 0x8b, 0x6f, 0xae, 0xfb, 0xc6, 0x44, 0x6c, 0xe1, 0x84, 0x2f, 0x75, + 0x29, 0x4c, 0xa0, 0x58, 0x76, 0xfe, 0xba, 0xbe, 0x1c, 0x3a, 0x43, 0x06, + 0xfe, 0xe3, 0x9f, 0xbe, 0x42, 0xab, 0xbc, 0x0b, 0x27, 0x8e, 0x79, 0xef, + 0x6e, 0x27, 0xce, 0xe9, 0x16, 0xa4, 0xab, 0x89, 0x29, 0x57, 0x6c, 0x4a, + 0xeb, 0x65, 0xab, 0xa0, 0xb4, 0xe9, 0xa0, 0x0a, 0x7c, 0x9d, 0x20, 0x10, + 0xaa, 0x96, 0x37, 0x18, 0x64, 0x42, 0x05, 0x78, 0x3d, 0x86, 0xf8, 0x51, + 0xcd, 0xb8, 0xc4, 0x55, 0x26, 0x27, 0xd5, 0xb1, 0x02, 0xed, 0xe7, 0x8c, + 0x1f, 0xfa, 0xde, 0x2d, 0x92, 0xe1, 0x03, 0x8a, 0x2a, 0xa5, 0xf3, 0xa2, + 0x4f, 0x0b, 0xda, 0x46, 0x58, 0x33, 0x92, 0x86, 0xc8, 0x2a, 0xf1, 0x9a, + 0x77, 0xa9, 0x5a, 0xe9, 0x9b, 0xa3, 0x9c, 0xb1, 0xbe, 0x7b, 0xe7, 0x07, + 0xae, 0xbc, 0xdc, 0xae, 0xb5, 0xab, 0xfe, 0xde, 0x68, 0xef, 0xa1, 0x6e, + 0x35, 0x21, 0x99, 0x7d, 0x71, 0x4f, 0x61, 0xbf, 0xbf, 0xd3, 0x81, 0x1a, + 0x96, 0x29, 0x14, 0x6b, 0xe1, 0x6f, 0x39, 0x1d, 0x3a, 0x19, 0x09, 0x1c, + 0x89, 0x81, 0x48, 0x4c, 0x7e, 0xd2, 0xc5, 0xb9, 0x27, 0xa5, 0xdf, 0x68, + 0x83, 0x2d, 0x97, 0x6c, 0xa3, 0x1c, 0xa4, 0xd5, 0x4d, 0x32, 0x09, 0xd6, + 0xda, 0xd1, 0x74, 0x22, 0xd6, 0xb0, 0x72, 0x1b, 0x05, 0x7b, 0x5a, 0x5b, + 0x5d, 0x3f, 0x51, 0x9e, 0xae, 0xd1, 0x17, 0xc6, 0x88, 0x1e, 0x17, 0x1a, + 0xb4, 0x8b, 0x10, 0xcc, 0xd7, 0x55, 0x4b, 0x68, 0x8d, 0x65, 0xbe, 0x2e, + 0x2d, 0x59, 0x11, 0x44, 0x03, 0xb7, 0xa2, 0x9e, 0xf2, 0x3a, 0xa1, 0x1a, + 0xd1, 0x39, 0xed, 0xb2, 0x60, 0x93, 0x84, 0x88, 0x75, 0x73, 0x2a, 0xd0, + 0x6a, 0x6c, 0xa1, 0x65, 0x5e, 0xb3, 0x24, 0x21, 0xda, 0xef, 0x6a, 0xc4, + 0x20, 0xe1, 0xfa, 0xe9, 0xe8, 0xa6, 0x4b, 0x7d, 0x29, 0xc3, 0x72, 0xe3, + 0x82, 0x5f, 0xd5, 0x23, 0xc0, 0x4f, 0x81, 0x11, 0xd0, 0x51, 0xb5, 0xbc, + 0xd2, 0xb8, 0x2b, 0x06, 0x60, 0x54, 0xc9, 0x75, 0x60, 0xcf, 0x1f, 0xaf, + 0x75, 0xd3, 0xb7, 0x9a, 0xe9, 0xad, 0x75, 0xac, 0xec, 0xfb, 0x3b, 0x59, + 0xcf, 0xbe, 0x37, 0x3b, 0x60, 0x06, 0xaf, 0x0e, 0x91, 0x51, 0xd9, 0x1a, + 0xf0, 0xfa, 0xc9, 0xed, 0xa9, 0x68, 0xb0, 0xea, 0x84, 0xca, 0xe8, 0x5c, + 0xf3, 0x96, 0xc6, 0x26, 0xac, 0xe6, 0xc7, 0x82, 0xfb, 0x2e, 0xa5, 0xa4, + 0xe2, 0x86, 0xe8, 0x3a, 0x89, 0x22, 0x1d, 0x20, 0x45, 0x1c, 0xb8, 0x4f, + 0x49, 0x40, 0xd2, 0xcb, 0x78, 0xd3, 0x7a, 0x6d, 0x9b, 0x14, 0x19, 0xe2, + 0xd2, 0xd6, 0x8a, 0x06, 0x7c, 0x85, 0xe3, 0xf4, 0xe7, 0x7b, 0x1c, 0x0e, + 0x92, 0x26, 0x3e, 0x1a, 0x63, 0xea, 0x75, 0xff, 0x3a, 0xb7, 0x2b, 0x63, + 0x80, 0x74, 0xc0, 0x16, 0x41, 0xb4, 0x4c, 0xe2, 0x8c, 0xa2, 0x02, 0xc3, + 0x85, 0x2e, 0x6d, 0xff, 0xaa, 0x42, 0x2c, 0xa4, 0xba, 0xf7, 0xce, 0x1d, + 0x3b, 0x97, 0xb9, 0xd9, 0xd8, 0xea, 0xb7, 0xab, 0x1a, 0x49, 0xe5, 0xd8, + 0x88, 0x1e, 0x13, 0x95, 0xe5, 0x96, 0x47, 0xb4, 0x05, 0x0d, 0xba, 0xb5, + 0x53, 0xe4, 0x87, 0x78, 0xf8, 0x76, 0x27, 0x2e, 0x82, 0x52, 0xff, 0xc0, + 0x22, 0x99, 0x77, 0xe0, 0x7c, 0xc2, 0x1b, 0x47, 0x74, 0x13, 0x26, 0x94, + 0x35, 0x70, 0x24, 0x97, 0x34, 0x20, 0x07, 0x9d, 0x86, 0xa7, 0x25, 0xa8, + 0x59, 0x2d, 0x43, 0x14, 0x8d, 0x99, 0x53, 0xc1, 0x02, 0xb2, 0x89, 0x6c, + 0x6f, 0xeb, 0x08, 0xf1, 0xa9, 0xfd, 0x1e, 0xd8, 0x57, 0xe3, 0x4a, 0xce, + 0x54, 0x2a, 0xf7, 0xcc, 0xfa, 0x1c, 0x1b, 0x96, 0x4d, 0x3d, 0xb4, 0x2c, + 0xae, 0x9f, 0x6e, 0x48, 0x3c, 0x1e, 0x6a, 0xc4, 0x76, 0x53, 0x96, 0x7e, + 0x43, 0xc5, 0xd5, 0xaa, 0x13, 0x78, 0x53, 0x6c, 0x4a, 0xb7, 0xc8, 0xd2, + 0x35, 0xc8, 0x05, 0xaa, 0xa8, 0x79, 0xa6, 0x18, 0x4b, 0xee, 0xb0, 0xe8, + 0x81, 0xa3, 0x5a, 0xec, 0xe2, 0x33, 0xf5, 0x65, 0xc8, 0x66, 0x10, 0x59, + 0xb2, 0xf5, 0x23, 0x4b, 0x7a, 0x04, 0x1f, 0xd6, 0xed, 0x6c, 0xd5, 0x02, + 0xed, 0x83, 0x01, 0x0e, 0x47, 0x69, 0x4e, 0x14, 0x36, 0xa8, 0x06, 0xc0, + 0xed, 0xea, 0xd0, 0x7c, 0x75, 0x3f, 0x3c, 0x68, 0xe0, 0x92, 0xdb, 0x70, + 0x1b, 0x66, 0x81, 0x9d, 0xc2, 0xdf, 0x73, 0x68, 0xb0, 0xc8, 0xd8, 0x1f, + 0x65, 0x1e, 0x2d, 0xf2, 0xdc, 0x45, 0x3a, 0x8b, 0xd1, 0x48, 0xd2, 0x84, + 0x2b, 0xc1, 0xdc, 0x27, 0x1f, 0x45, 0xe1, 0x78, 0x79, 0x3d, 0x26, 0xe4, + 0x04, 0xbb, 0xd5, 0x3b, 0x2b, 0xe6, 0x9c, 0x19, 0x0d, 0xaa, 0x00, 0x4b, + 0xa7, 0xee, 0xcf, 0x05, 0x63, 0xcd, 0x83, 0x94, 0x4d, 0x28, 0x41, 0xb4, + 0x34, 0x39, 0x6c, 0x69, 0x48, 0x7f, 0xa7, 0xc0, 0x5c, 0xc5, 0xf4, 0x47, + 0xca, 0x5e, 0x05, 0x01, 0x8f, 0xb0, 0x31, 0xe3, 0x07, 0xbb, 0xe4, 0xba, + 0xb7, 0x86, 0x55, 0xa8, 0x9e, 0x73, 0x0c, 0xac, 0x18, 0x9a, 0x64, 0x79, + 0xbf, 0x1f, 0xdd, 0x56, 0xca, 0x71, 0xdf, 0xa4, 0xac, 0x26, 0xec, 0x1c, + 0x52, 0xd2, 0xa8, 0xcc, 0xe6, 0x9b, 0x66, 0x26, 0xba, 0xb2, 0xc3, 0xd5, + 0x78, 0xc6, 0x25, 0x4b, 0xa1, 0x18, 0xfd, 0x65, 0x5b, 0x36, 0x97, 0x30, + 0x97, 0xe5, 0x1a, 0xa3, 0xc5, 0xaa, 0x84, 0x15, 0xcf, 0x7d, 0x36, 0xab, + 0xa4, 0xcd, 0x25, 0x8e, 0xc1, 0x03, 0x1e, 0xd2, 0xa5, 0xd8, 0x64, 0x54, + 0x14, 0x1a, 0xda, 0xc9, 0xe8, 0xa2, 0x97, 0x82, 0x22, 0x36, 0xe9, 0x30, + 0xbf, 0xa2, 0x65, 0x1a, 0x7d, 0x7b, 0x44, 0x77, 0xae, 0xd5, 0xc6, 0x21, + 0x14, 0xa2, 0xad, 0xbc, 0x7e, 0xa9, 0x8f, 0xf8, 0x62, 0x23, 0x7e, 0x65, + 0xb8, 0x79, 0xa2, 0xe8, 0x80, 0xad, 0xc1, 0xe3, 0xb5, 0x73, 0xa5, 0x17, + 0xff, 0xca, 0x3f, 0xaa, 0x13, 0x4d, 0xe1, 0x30, 0xaa, 0x83, 0xd6, 0x01, + 0xd9, 0xe9, 0x40, 0x72, 0xd8, 0xbb, 0xf9, 0xd9, 0x9b, 0xf8, 0x7a, 0xc5, + 0x12, 0x43, 0xe2, 0xe1, 0x81, 0x58, 0x51, 0x04, 0x99, 0x39, 0xfa, 0x27, + 0xb4, 0x27, 0xdb, 0xed, 0xff, 0x7d, 0x32, 0x37, 0x30, 0xa7, 0x9d, 0x35, + 0xcb, 0xcc, 0xc8, 0x1e, 0xc8, 0x0a, 0xe6, 0xc0, 0x72, 0xce, 0x4e, 0x63, + 0xf1, 0x87, 0x76, 0x29, 0xbb, 0xfa, 0x00, 0x3e, 0xa5, 0x48, 0x98, 0xc4, + 0xc3, 0xb1, 0x9f, 0x60, 0xe0, 0x4e, 0xc4, 0x12, 0x39, 0x3d, 0x13, 0x6a, + 0x03, 0x90, 0xfc, 0x1e, 0xc6, 0x40, 0x99, 0x91, 0x82, 0x2a, 0xae, 0x25, + 0xbf, 0xef, 0xe9, 0x0d, 0x88, 0x36, 0xcc, 0x51, 0xb4, 0x78, 0x5c, 0x31, + 0x57, 0x64, 0x7b, 0x40, 0x30, 0xdb, 0x04, 0x6c, 0x69, 0xba, 0x90, 0x67, + 0x61, 0x93, 0x43, 0xff, 0xe0, 0x0a, 0x2b, 0x10, 0x8f, 0x71, 0x13, 0xbc, + 0x8d, 0x8a, 0x33, 0x2c, 0xa9, 0x6b, 0x22, 0x58, 0xb9, 0x2c, 0x99, 0xf3, + 0x98, 0x53, 0x3e, 0xe3, 0x32, 0x20, 0xc4, 0x1f, 0x3c, 0x72, 0x0b, 0x48, + 0x5e, 0xe3, 0xc9, 0x17, 0x97, 0x6b, 0x05, 0xf4, 0xf4, 0x64, 0x01, 0xe7, + 0x7e, 0x18, 0x93, 0x3d, 0xca, 0x1e, 0xad, 0xcc, 0x35, 0x4d, 0x37, 0x97, + 0x24, 0x34, 0x1c, 0xe5, 0x48, 0x16, 0x86, 0x83, 0xf3, 0x81, 0xce, 0x0f, + 0xae, 0x51, 0xe0, 0x4c, 0x82, 0x27, 0xcd, 0xb5, 0xdc, 0x48, 0xe9, 0x13, + 0xc6, 0x21, 0x45, 0xb0, 0xa0, 0x3d, 0xb5, 0x6e, 0x59, 0xd4, 0xfc, 0xea, + 0x04, 0xe3, 0x02, 0x2f, 0x5b, 0x20, 0x7e, 0x21, 0x48, 0x55, 0x0f, 0x43, + 0xf1, 0x2f, 0x79, 0x76, 0xfa, 0xac, 0xc5, 0xc1, 0xcb, 0x56, 0xea, 0x57, + 0xe2, 0x75, 0x7b, 0xe2, 0x5a, 0xc8, 0xf6, 0x79, 0x84, 0x32, 0x8a, 0xe5, + 0xd5, 0x48, 0x99, 0x2f, 0x0f, 0x88, 0x1b, 0x00, 0xb4, 0x1f, 0x51, 0x91, + 0x12, 0x78, 0x0e, 0x85, 0x30, 0xfe, 0xcf, 0xd7, 0xd6, 0x6f, 0x3a, 0xe3, + 0x48, 0x36, 0x3a, 0xd2, 0x74, 0x01, 0x1e, 0x4c, 0x7d, 0x49, 0x40, 0x30, + 0x62, 0xb9, 0x89, 0x92, 0x5e, 0x1a, 0xf7, 0xfd, 0xe8, 0x9f, 0x6c, 0x47, + 0x80, 0xac, 0x5d, 0x47, 0xca, 0x1b, 0x41, 0xef, 0x4a, 0x59, 0xe2, 0xaf, + 0x18, 0x91, 0x16, 0x95, 0x97, 0xfd, 0xa6, 0x02, 0x1e, 0xe5, 0x15, 0x0d, + 0xfc, 0xed, 0x82, 0x68, 0x0f, 0x58, 0xbe, 0xaa, 0x8e, 0xba, 0xa9, 0x60, + 0x0a, 0x1b, 0x29, 0x6e, 0xc6, 0x1b, 0x88, 0xfd, 0x29, 0x41, 0xbb, 0xcf, + 0xee, 0x1f, 0xdc, 0x14, 0x41, 0xb2, 0x36, 0xec, 0x3c, 0x22, 0xf7, 0x97, + 0xf2, 0xa8, 0x18, 0x69, 0xd9, 0xb4, 0xbd, 0x0c, 0xc1, 0x28, 0x0a, 0x46, + 0xd0, 0xd5, 0x3d, 0x01, 0x20, 0x82, 0xdd, 0x26, 0x5a, 0x59, 0xce, 0x18, + 0x34, 0x28, 0xbe, 0x87, 0x27, 0x11, 0x2e, 0x5b, 0x4a, 0x0e, 0x29, 0x73, + 0xa0, 0x94, 0xdc, 0xb8, 0x4f, 0xf2, 0x66, 0x0d, 0x12, 0x09, 0xa6, 0x5b, + 0x01, 0x75, 0x98, 0xfc, 0x6c, 0xc7, 0x10, 0x2c, 0xaa, 0x52, 0xfb, 0x6d, + 0x5f, 0xae, 0xd0, 0x0d, 0x4b, 0xd7, 0x21, 0x98, 0xea, 0x25, 0xb0, 0x5b, + 0xa5, 0x0e, 0x75, 0xad, 0x68, 0x62, 0x37, 0x70, 0x96, 0xd1, 0xf2, 0x75, + 0xde, 0x9e, 0x50, 0x04, 0x5b, 0xdb, 0x88, 0xf8, 0xc8, 0x72, 0x54, 0x39, + 0xfc, 0x3f, 0xf0, 0x80, 0x76, 0xaa, 0x44, 0xe0, 0x8a, 0x01, 0x15, 0xc4, + 0xaa, 0x63, 0x67, 0x8d, 0xd8, 0xff, 0x8f, 0xd9, 0xf4, 0xcc, 0xd4, 0x10, + 0x54, 0xa6, 0x29, 0x21, 0xd5, 0xd0, 0xba, 0x37, 0x8c, 0xdb, 0xad, 0x16, + 0x48, 0xc5, 0xe4, 0x6e, 0xf1, 0xe8, 0x7b, 0x51, 0xc6, 0x18, 0x33, 0x7c, + 0x3d, 0x49, 0xe3, 0xbf, 0x7c, 0xda, 0x55, 0x02, 0x69, 0x40, 0x23, 0x98, + 0xd0, 0xae, 0x27, 0x9a, 0xb3, 0xc9, 0x9a, 0x66, 0xb7, 0x89, 0x63, 0x8c, + 0x0c, 0xe6, 0x73, 0x9a, 0xed, 0xcf, 0xaa, 0x4f, 0x88, 0xbd, 0x75, 0xdb, + 0xc3, 0xb9, 0x3e, 0x1f, 0xe4, 0x8f, 0xe1, 0x9c, 0x24, 0x20, 0x12, 0x98, + 0xb9, 0x20, 0x06, 0xe1, 0x04, 0x19, 0x7b, 0x86, 0x3b, 0xfc, 0xfe, 0x7a, + 0xb1, 0x25, 0x7d, 0x20, 0x18, 0x5b, 0xa5, 0x57, 0xfd, 0x72, 0xbc, 0x2c, + 0x46, 0x38, 0xb6, 0x7c, 0xea, 0x5d, 0xb5, 0xbc, 0xa7, 0xb2, 0x90, 0xf8, + 0x80, 0xff, 0x22, 0x5f, 0xf6, 0xee, 0x99, 0x78, 0x86, 0xfb, 0xe0, 0xc9, + 0x64, 0xb6, 0xc5, 0xc4, 0x89, 0xfd, 0x84, 0x01, 0xd5, 0x44, 0x45, 0x54, + 0x0e, 0x1b, 0xfe, 0x04, 0x23, 0xa1, 0x2c, 0xd3, 0x36, 0x0b, 0xb7, 0x00, + 0x3f, 0x39, 0xf6, 0x98, 0xac, 0xe0, 0x78, 0x38, 0xb3, 0xff, 0x1e, 0x61, + 0x87, 0xd0, 0x0c, 0x1a, 0x85, 0x6f, 0x7c, 0x9f, 0xfd, 0xf3, 0x1a, 0x4b, + 0x92, 0x97, 0xbb, 0x01, 0x9a, 0x32, 0x83, 0x18, 0x58, 0x1e, 0xfb, 0xa4, + 0x52, 0xe1, 0xd0, 0xa1, 0xe6, 0x6e, 0x89, 0x25, 0x74, 0x91, 0x1f, 0x29, + 0xce, 0xfa, 0xf8, 0xe8, 0x37, 0xf9, 0xee, 0x3b, 0x0c, 0x84, 0x1d, 0x2f, + 0xd6, 0x99, 0x1e, 0x60, 0x19, 0x63, 0xcd, 0x99, 0xa5, 0x92, 0x6f, 0xef, + 0x4e, 0x5a, 0xf4, 0xa1, 0x02, 0x8d, 0xc5, 0x02, 0x40, 0xa9, 0x7d, 0xf7, + 0x40, 0x01, 0xe4, 0xd3, 0x9f, 0x4c, 0x24, 0x42, 0x60, 0x9d, 0x69, 0x55, + 0x06, 0x42, 0x08, 0xa3, 0x9f, 0xe3, 0xd8, 0xe7, 0xfe, 0x46, 0xa1, 0x5d, + 0x67, 0x98, 0x97, 0x25, 0xc2, 0x3e, 0xfd, 0x76, 0xc3, 0x88, 0x13, 0xf9, + 0x46, 0x2a, 0x1c, 0xaf, 0x72, 0x35, 0x5f, 0x1d, 0x2d, 0xfa, 0x52, 0xe1, + 0x18, 0x0c, 0x57, 0x50, 0x06, 0x39, 0x1e, 0xdd, 0xb3, 0xab, 0xc9, 0x0f, + 0x67, 0x47, 0x79, 0xe8, 0x02, 0x74, 0x81, 0xc8, 0x8d, 0x4b, 0xb5, 0x59, + 0x85, 0xb1, 0xab, 0x99, 0xec, 0x5c, 0x69, 0xe7, 0xf0, 0x4a, 0x04, 0xf5, + 0xd6, 0xf0, 0xa8, 0x6a, 0xfb, 0x5e, 0x8f, 0x0d, 0x3b, 0x7c, 0xf4, 0xb8, + 0x21, 0xbd, 0x88, 0x11, 0xff, 0x43, 0x6b, 0x05, 0xdb, 0xfc, 0x81, 0x17, + 0x5a, 0xa0, 0xfc, 0x10, 0x47, 0x55, 0xb9, 0x1f, 0x00, 0x76, 0x32, 0xf6, + 0xde, 0x81, 0x59, 0x24, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x52, 0x3f, 0x1f, 0xb6, 0x05, 0x23, 0x08, 0x4f, 0xa3, 0x72, 0x1c, 0x5a, + 0xa4, 0x5a, 0xe0, 0x65, 0x17, 0x56, 0x60, 0xa0, 0x6d, 0x11, 0x14, 0x6e, + 0x0a, 0x68, 0x4c, 0xb8, 0x9c, 0x13, 0x19, 0x0c, 0x5e, 0xfe, 0x4a, 0xe8, + 0x40, 0x87, 0x13, 0x24, 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, + 0xd1, 0x01, 0xb4, 0x4d, 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, + 0xde, 0xfb, 0x08, 0x1d, 0x52, 0x3f, 0x1f, 0xb6, 0x05, 0x23, 0x08, 0x4f, + 0xa3, 0x72, 0x1c, 0x5a, 0xa4, 0x5a, 0xe0, 0x65, 0x17, 0x56, 0x60, 0xa0, + 0x6d, 0x11, 0x14, 0x6e, 0x0a, 0x68, 0x4c, 0xb8, 0x9c, 0x13, 0x19, 0x0c, + 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, 0xbb, 0xac, 0xaa, 0x3e, + 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, 0x3a, 0x90, 0x96, 0x6e, + 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, 0x66, 0x28, 0x68, 0xb4, + 0xbd, 0x74, 0x70, 0x07, 0xcb, 0x28, 0xb4, 0x81, 0xce, 0xd8, 0xeb, 0xa8, + 0xf8, 0x1e, 0x41, 0xc1, 0xc2, 0xe4, 0x42, 0xc4, 0x22, 0xb0, 0xfe, 0x10, + 0xb5, 0x96, 0x53, 0x28, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x66, 0x28, 0x68, 0xb4, 0xbd, 0x74, 0x70, 0x07, 0xcb, 0x28, 0xb4, 0x81, + 0xce, 0xd8, 0xeb, 0xa8, 0xf8, 0x1e, 0x41, 0xc1, 0xc2, 0xe4, 0x42, 0xc4, + 0x22, 0xb0, 0xfe, 0x10, 0xb5, 0x96, 0x53, 0x28, 0xbb, 0x90, 0x90, 0x32, + 0x56, 0xe2, 0xa4, 0xb4, 0x50, 0x98, 0x65, 0xa9, 0x77, 0x61, 0x25, 0x7b, + 0x35, 0xa0, 0xb7, 0xb7, 0x43, 0x03, 0x77, 0xb2, 0xce, 0xed, 0x40, 0xa5, + 0x41, 0x08, 0xa7, 0x1b, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x74, 0x44, 0x87, 0xac, 0xd4, 0xfb, 0x9c, 0xe8, 0x07, 0xd3, 0x36, 0x46, + 0xdb, 0x8c, 0x8f, 0x39, 0xed, 0xf2, 0xc6, 0x2f, 0xc7, 0xf9, 0x0e, 0x94, + 0xd7, 0xb8, 0xfc, 0x0a, 0xb9, 0x93, 0x5d, 0x2e, 0x04, 0xc1, 0x02, 0x69, + 0x31, 0xf1, 0x2f, 0xea, 0xb7, 0xc4, 0xc1, 0xd4, 0x07, 0x9d, 0x21, 0x4b, + 0xc2, 0x16, 0x6c, 0x2e, 0x2c, 0xe2, 0xe5, 0x6f, 0x0b, 0x01, 0x36, 0x79, + 0xd2, 0x4b, 0xc8, 0x19, 0x52, 0x3f, 0x1f, 0xb6, 0x05, 0x23, 0x08, 0x4f, + 0xa3, 0x72, 0x1c, 0x5a, 0xa4, 0x5a, 0xe0, 0x65, 0x17, 0x56, 0x60, 0xa0, + 0x6d, 0x11, 0x14, 0x6e, 0x0a, 0x68, 0x4c, 0xb8, 0x9c, 0x13, 0x19, 0x0c, + 0xef, 0x57, 0xd7, 0xc5, 0xe3, 0x87, 0xa9, 0xcc, 0x9a, 0xbe, 0x4f, 0x39, + 0xa5, 0x1b, 0x0d, 0x38, 0x89, 0x35, 0xd2, 0x9e, 0xba, 0xfb, 0x0d, 0x54, + 0x90, 0x9e, 0x84, 0xab, 0xda, 0x5e, 0x42, 0x06, 0x2f, 0xa3, 0xdd, 0x47, + 0x42, 0xcb, 0x38, 0x28, 0xfa, 0xde, 0xaf, 0x59, 0xc1, 0x40, 0xa5, 0x9d, + 0x7c, 0xb3, 0xf9, 0x59, 0xe1, 0xf3, 0x70, 0xfb, 0xc5, 0xf0, 0x19, 0x91, + 0xfc, 0x10, 0xdd, 0x27, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x2f, 0xa3, 0xdd, 0x47, 0x42, 0xcb, 0x38, 0x28, 0xfa, 0xde, 0xaf, 0x59, + 0xc1, 0x40, 0xa5, 0x9d, 0x7c, 0xb3, 0xf9, 0x59, 0xe1, 0xf3, 0x70, 0xfb, + 0xc5, 0xf0, 0x19, 0x91, 0xfc, 0x10, 0xdd, 0x27, 0x05, 0x08, 0x2a, 0x97, + 0x02, 0x8d, 0xb5, 0xa9, 0x1b, 0xce, 0xa9, 0xa2, 0xc7, 0x12, 0xfa, 0x4d, + 0x36, 0x5e, 0xd5, 0x63, 0x45, 0xcd, 0xc3, 0x86, 0xca, 0x8f, 0x2b, 0xf5, + 0x88, 0x3b, 0x8a, 0x1c, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x45, 0xec, 0x79, 0x18, 0x9f, 0x8f, 0xcb, 0xf1, 0xc2, 0x41, 0xcb, 0xcb, + 0x6f, 0x49, 0x53, 0xb8, 0x42, 0xe9, 0x53, 0xfa, 0x5b, 0x5e, 0xac, 0x99, + 0x47, 0xff, 0xef, 0xb3, 0x01, 0x0d, 0x5e, 0x22, 0xae, 0xd6, 0xce, 0xa0, + 0x62, 0x2a, 0x07, 0x63, 0x1e, 0xf0, 0xf5, 0x8a, 0x1c, 0x67, 0xdf, 0x27, + 0xa1, 0x63, 0x7a, 0xf7, 0xd1, 0xae, 0xd9, 0x6c, 0x08, 0x78, 0x5a, 0x77, + 0x9a, 0x65, 0x52, 0x1e, 0xa4, 0x6f, 0x8e, 0x6d, 0xa6, 0x61, 0x6c, 0x5b, + 0x97, 0x89, 0xed, 0x5c, 0xac, 0x3f, 0x07, 0x55, 0x7b, 0x6d, 0xe7, 0x28, + 0x09, 0xc1, 0x23, 0x1d, 0x6b, 0x92, 0xc3, 0x83, 0x87, 0x48, 0xfb, 0x1b, + 0x5d, 0x22, 0x76, 0x80, 0x28, 0x82, 0xef, 0x72, 0x84, 0x8b, 0x8c, 0x2b, + 0xe4, 0xeb, 0x33, 0x64, 0x27, 0x41, 0x0d, 0x66, 0xdc, 0xfc, 0x03, 0xef, + 0x55, 0x51, 0xd6, 0x3d, 0x75, 0xfd, 0xa7, 0x02, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0xcb, 0xfc, 0xdb, 0x67, 0xc0, 0x16, 0x0a, 0x77, + 0xb0, 0xf8, 0xdd, 0x84, 0xba, 0x18, 0xf2, 0xcc, 0x2d, 0xd4, 0x58, 0xe4, + 0x1c, 0xa5, 0x83, 0xa1, 0x1d, 0x27, 0x58, 0xe9, 0x48, 0xc7, 0x0e, 0x1c, + 0x65, 0x51, 0x89, 0x7c, 0xa3, 0x5b, 0x02, 0x06, 0x6f, 0x0a, 0xdc, 0xc3, + 0x86, 0x60, 0x37, 0x4d, 0xcb, 0xa5, 0x10, 0x6f, 0xcd, 0x9f, 0x11, 0x19, + 0x5d, 0xf3, 0xee, 0x00, 0x40, 0xbb, 0x09, 0x19, 0x82, 0x49, 0x53, 0xda, + 0x95, 0x8b, 0x09, 0x64, 0x04, 0x81, 0xd5, 0x14, 0xc4, 0xf7, 0xfe, 0x23, + 0xc5, 0xc6, 0x5d, 0x81, 0x0e, 0x40, 0x05, 0x2f, 0xd4, 0xab, 0xde, 0xfd, + 0xd2, 0xe3, 0xd4, 0x1a, 0xf8, 0x18, 0x2d, 0xea, 0xfb, 0x1e, 0x97, 0x82, + 0xcd, 0xeb, 0x7f, 0xb3, 0x8e, 0xee, 0xc2, 0xcd, 0x16, 0x9b, 0xc5, 0x89, + 0x6f, 0xf8, 0x75, 0x22, 0x53, 0x86, 0x79, 0xc9, 0xb5, 0x18, 0x8d, 0x13, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x93, 0x83, 0x8a, 0xfb, + 0x2e, 0x93, 0x72, 0xc4, 0xf9, 0xab, 0x6a, 0xb8, 0xbc, 0xf0, 0xd7, 0xeb, + 0x93, 0xe0, 0xc3, 0xa2, 0x3c, 0x7b, 0xd7, 0x6c, 0x19, 0x8b, 0xfb, 0x0b, + 0x11, 0x56, 0x4d, 0x18, 0xb4, 0x1d, 0x17, 0x3a, 0x96, 0x18, 0xbb, 0x99, + 0x65, 0x37, 0x8c, 0x5c, 0x76, 0x54, 0x3f, 0xa1, 0x9f, 0x36, 0x5d, 0xdd, + 0xe7, 0x60, 0x2d, 0xf0, 0x37, 0x96, 0xd5, 0xf3, 0xdc, 0x01, 0x7e, 0x02, + 0x16, 0x5a, 0xbb, 0x92, 0x77, 0x11, 0xf7, 0xec, 0xc7, 0x34, 0xf6, 0xb0, + 0xdb, 0xb0, 0x4a, 0x3c, 0xca, 0xb4, 0xc3, 0xdc, 0xb8, 0x6e, 0x87, 0xb6, + 0xb6, 0xde, 0x29, 0xea, 0xf2, 0xa0, 0x75, 0x2e, 0xa5, 0x1e, 0x65, 0x1b, + 0x64, 0x34, 0xd6, 0x02, 0xf9, 0x26, 0x73, 0xb9, 0x24, 0xd4, 0x50, 0xe5, + 0x36, 0xca, 0x2b, 0x16, 0x97, 0x17, 0x86, 0x26, 0x39, 0xa8, 0xdf, 0x44, + 0x99, 0x08, 0x22, 0x12, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x0a, 0xbf, 0x69, 0xc4, 0xbe, 0xe7, 0x6b, 0x5b, 0x4e, 0xfd, 0x39, 0xf5, + 0x2e, 0xb4, 0xf2, 0xe6, 0x22, 0x8b, 0xe2, 0x68, 0x48, 0xf6, 0x33, 0x08, + 0xaa, 0x3f, 0x56, 0x10, 0x50, 0x22, 0x37, 0x2f, 0xbe, 0xa4, 0x9b, 0x14, + 0xb7, 0x01, 0x35, 0xc8, 0x30, 0xe0, 0xbe, 0xd1, 0x00, 0x8c, 0x18, 0xbd, + 0x8b, 0xcf, 0xb1, 0x3e, 0xb0, 0xbf, 0x7e, 0xf7, 0x1e, 0xd5, 0x1c, 0xfa, + 0x72, 0x06, 0x36, 0x21, 0x0c, 0x34, 0xe3, 0x34, 0x91, 0xdd, 0x0d, 0x36, + 0x72, 0xc4, 0xde, 0xf2, 0xf3, 0x32, 0xb1, 0xa6, 0xcc, 0xca, 0x30, 0x7c, + 0x07, 0xe7, 0xc0, 0x0f, 0x45, 0xca, 0xbf, 0x75, 0xe3, 0x4e, 0xf5, 0x05, + 0x54, 0x1e, 0x95, 0xee, 0x17, 0x58, 0xea, 0xc5, 0xb3, 0x84, 0x64, 0x73, + 0x47, 0xb5, 0xe4, 0x30, 0xa0, 0x07, 0x22, 0x5d, 0x13, 0xce, 0xc3, 0xf2, + 0xf9, 0x77, 0xc0, 0xb6, 0x12, 0x88, 0x53, 0x27, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x76, 0xd1, 0xcf, 0x20, 0x9c, 0x89, 0x1c, 0xb6, + 0x59, 0x83, 0xe0, 0xa6, 0x91, 0xe4, 0xce, 0x7a, 0x52, 0x92, 0xcb, 0x4a, + 0x45, 0xfa, 0xc4, 0x5e, 0x76, 0xf2, 0xe8, 0x73, 0x03, 0xa4, 0x8f, 0x25, + 0xd3, 0xc3, 0x0f, 0x0f, 0x4a, 0xca, 0xeb, 0x19, 0xe8, 0xf3, 0x50, 0x18, + 0xfa, 0xad, 0xe2, 0x26, 0x23, 0x9a, 0x63, 0xa0, 0x44, 0x5c, 0xe2, 0x80, + 0x0a, 0xe9, 0x56, 0x66, 0x37, 0x42, 0x01, 0x08, 0xdb, 0x21, 0x2d, 0x7a, + 0xc3, 0x0f, 0x75, 0xa6, 0x09, 0x29, 0x68, 0xe6, 0x8b, 0x25, 0x4e, 0x47, + 0xf6, 0xc4, 0xac, 0x4c, 0x9a, 0xf8, 0xbb, 0x35, 0xce, 0x05, 0xda, 0xf2, + 0x71, 0x81, 0x57, 0x18, 0x7a, 0x0d, 0x81, 0xf1, 0x8e, 0x8e, 0xad, 0xac, + 0x12, 0xa5, 0x16, 0xbd, 0x1d, 0x8d, 0xca, 0x0b, 0xbc, 0xb4, 0x89, 0xc1, + 0x05, 0xde, 0xb0, 0xe4, 0x61, 0xd0, 0xa0, 0xb9, 0xf4, 0xaf, 0x40, 0x2d, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0xd2, 0x7d, 0x1f, 0x46, + 0xa2, 0xc9, 0x89, 0x73, 0x3c, 0xcd, 0x69, 0x19, 0xe4, 0x82, 0x75, 0x91, + 0x68, 0x9a, 0x4e, 0x14, 0x71, 0x94, 0x6c, 0xc4, 0x53, 0x27, 0x77, 0x5c, + 0x4a, 0xba, 0x3b, 0x07, 0x40, 0x07, 0x24, 0xf0, 0x9e, 0x8c, 0x23, 0x2d, + 0x46, 0x1d, 0x39, 0x43, 0xd3, 0x38, 0x80, 0x51, 0x21, 0x66, 0xe7, 0x29, + 0xf4, 0x93, 0xf6, 0xdc, 0x8e, 0xfd, 0xe5, 0xc9, 0xc7, 0xdf, 0x3a, 0x15, + 0x4e, 0x9f, 0x9f, 0x6f, 0xa5, 0x25, 0x6a, 0x49, 0xf2, 0x4f, 0xc7, 0x23, + 0x2e, 0xc4, 0x60, 0x32, 0xa9, 0xd1, 0x12, 0xc6, 0x56, 0x89, 0x51, 0x80, + 0xf6, 0x75, 0xed, 0xb9, 0xef, 0x28, 0xff, 0x07, 0x64, 0xe0, 0x8a, 0x92, + 0xc1, 0x42, 0x4a, 0xe6, 0xbe, 0xf8, 0x0f, 0x17, 0xac, 0xfe, 0x8f, 0x2d, + 0x8e, 0x77, 0x25, 0xda, 0x69, 0x38, 0x25, 0x71, 0x05, 0x08, 0x41, 0x28, + 0x17, 0x2f, 0xf5, 0x00, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x9b, 0xf6, 0x01, 0xc9, 0x6a, 0xad, 0x5f, 0xed, 0x52, 0x05, 0xf4, 0xce, + 0x63, 0x30, 0xa5, 0x16, 0xca, 0xc2, 0xe1, 0x7a, 0xd7, 0x0a, 0x80, 0x87, + 0xb0, 0x89, 0x75, 0x6e, 0x4a, 0x24, 0x05, 0x22, 0xd4, 0x25, 0x26, 0x84, + 0x4c, 0xeb, 0x94, 0xee, 0xd6, 0x69, 0xab, 0xc1, 0xc7, 0xd9, 0xd1, 0x63, + 0xcc, 0xd9, 0x4d, 0x2f, 0x30, 0x3c, 0x10, 0x67, 0x5a, 0xe6, 0xf3, 0x34, + 0xe6, 0x7f, 0x05, 0x30, 0xe1, 0x34, 0x1b, 0x22, 0x4d, 0x07, 0x8a, 0xd6, + 0xf7, 0x61, 0xed, 0x09, 0x13, 0x9f, 0x47, 0x40, 0x32, 0xb7, 0xdd, 0xac, + 0x5b, 0x7b, 0xf5, 0x68, 0xc8, 0xb8, 0xc5, 0xb7, 0x57, 0x7e, 0x7c, 0x1c, + 0xc6, 0xe2, 0x69, 0x0e, 0x84, 0x3f, 0xd7, 0x83, 0xb7, 0x03, 0x8f, 0x97, + 0x97, 0x40, 0x88, 0x47, 0x21, 0x0e, 0x9a, 0x6e, 0x67, 0x0a, 0x29, 0xb7, + 0x09, 0xe6, 0x09, 0x7f, 0x9b, 0xf7, 0xcb, 0x0d, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x6d, 0x04, 0x4b, 0x4f, 0xd5, 0x38, 0x70, 0x8a, + 0xd6, 0xb4, 0x22, 0x41, 0xb5, 0x69, 0x2a, 0x15, 0x64, 0xed, 0x86, 0x31, + 0x44, 0x1d, 0x69, 0x4e, 0x21, 0xf5, 0x0c, 0x41, 0xb5, 0xbe, 0xce, 0x0e, + 0x72, 0x8f, 0xa0, 0x19, 0x40, 0x4a, 0x32, 0x81, 0x38, 0xaf, 0xa2, 0xda, + 0xad, 0xe8, 0x7f, 0xb2, 0x83, 0x52, 0x83, 0x18, 0xde, 0x7a, 0x90, 0xfd, + 0x20, 0x97, 0x22, 0xc4, 0xfc, 0x5f, 0xe6, 0x16, 0x06, 0xa5, 0xcf, 0x41, + 0xcd, 0xdb, 0xa1, 0xe4, 0x57, 0x70, 0x25, 0xe3, 0xe7, 0xb6, 0x55, 0x4b, + 0x37, 0x57, 0x47, 0x8c, 0xd1, 0xac, 0x83, 0x6e, 0x72, 0x71, 0xfc, 0x89, + 0x7a, 0x9f, 0x31, 0x04, 0xc2, 0x4c, 0x4d, 0x2f, 0x5c, 0xfd, 0x44, 0x01, + 0x08, 0x70, 0x2a, 0x43, 0x24, 0xbd, 0xa8, 0x75, 0x8c, 0x94, 0x0b, 0x60, + 0xaf, 0x35, 0x55, 0xa3, 0xa3, 0x65, 0xa1, 0x0b, 0x72, 0x08, 0x08, 0x0b, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0xff, 0x49, 0xe3, 0xb2, + 0xdf, 0xe4, 0xe9, 0xf6, 0x2c, 0x1a, 0x0f, 0xfe, 0xcd, 0xc5, 0x8d, 0x88, + 0x5d, 0x53, 0x29, 0xa0, 0xda, 0xb3, 0xa3, 0x49, 0x33, 0x48, 0xb5, 0xb0, + 0x33, 0xf8, 0x43, 0x2a, 0x1c, 0x6a, 0x01, 0x78, 0x6d, 0x2b, 0xd6, 0x45, + 0xbd, 0xcc, 0xa3, 0x84, 0x9e, 0xc4, 0xe5, 0x9d, 0x14, 0xc2, 0x7b, 0x6a, + 0xc3, 0x0f, 0x95, 0x74, 0x60, 0xa8, 0xa1, 0x9b, 0x9e, 0xfd, 0xcd, 0x0d, + 0x3b, 0xb7, 0xb3, 0x60, 0xa5, 0xc5, 0x68, 0x77, 0x70, 0x33, 0x2e, 0x14, + 0x0b, 0x30, 0x88, 0xfb, 0xb8, 0xdb, 0x55, 0x8a, 0x00, 0x76, 0x08, 0x7b, + 0x9a, 0x09, 0x80, 0x82, 0x6a, 0x51, 0x3b, 0x23, 0x3b, 0x9a, 0xb7, 0x98, + 0xe3, 0xc0, 0x2d, 0x8a, 0x43, 0x44, 0xba, 0xdf, 0x52, 0xe9, 0x12, 0xf1, + 0xa5, 0x38, 0x2c, 0xbe, 0xef, 0x75, 0xa2, 0x0b, 0xdb, 0x96, 0x3b, 0xf3, + 0x3d, 0x8a, 0xeb, 0x0b, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x43, 0x7d, 0x2c, 0xdb, 0x83, 0xe4, 0x45, 0x08, 0x61, 0xf8, 0x6d, 0x2e, + 0xe4, 0xe1, 0x6d, 0xa5, 0x4c, 0xc3, 0x72, 0xc3, 0x8c, 0xd3, 0x7b, 0x05, + 0x2b, 0x84, 0x4a, 0x86, 0x9f, 0x50, 0x1c, 0x1e, 0x39, 0xc6, 0xcd, 0xa9, + 0xc6, 0xd9, 0x07, 0x07, 0xd6, 0xdf, 0xc1, 0x77, 0xf2, 0x15, 0x23, 0x05, + 0xfe, 0xc5, 0x27, 0x7c, 0xda, 0x30, 0x10, 0x7a, 0x5e, 0xa6, 0x15, 0xdf, + 0x71, 0x39, 0xdd, 0x07, 0x2d, 0x28, 0x2e, 0xe9, 0x87, 0x82, 0x17, 0x0e, + 0x17, 0xaa, 0x92, 0x6e, 0xef, 0x7e, 0x4e, 0x59, 0x0f, 0xc1, 0x2d, 0x4d, + 0x65, 0xb6, 0xe8, 0x15, 0x0f, 0x94, 0xd4, 0xbc, 0x9e, 0xa2, 0x89, 0x0f, + 0xeb, 0x8b, 0xbd, 0xf5, 0x7f, 0x8a, 0xa9, 0x70, 0x6e, 0x00, 0xe8, 0xcd, + 0x2d, 0x26, 0xe7, 0xd3, 0xdf, 0xee, 0x13, 0xc2, 0x6d, 0x13, 0x84, 0x0b, + 0xbb, 0x8d, 0x44, 0x6e, 0x72, 0x2e, 0xdb, 0x08, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x55, 0x8f, 0xe2, 0xd7, 0x55, 0x81, 0xb2, 0x62, + 0x55, 0xf7, 0x97, 0x7e, 0x74, 0x45, 0x42, 0xeb, 0xde, 0x28, 0xe6, 0x0c, + 0x2d, 0x9b, 0x95, 0x9b, 0xf7, 0xb2, 0x9c, 0xd8, 0xd8, 0x24, 0xf2, 0x08, + 0x97, 0x7f, 0xcb, 0xff, 0x5d, 0xe4, 0xd9, 0xcb, 0xaf, 0x6f, 0x5d, 0xc5, + 0x7b, 0xb7, 0x94, 0xe3, 0x84, 0x2d, 0x96, 0x66, 0x3e, 0x9b, 0xa3, 0x1a, + 0x83, 0x28, 0x31, 0xcb, 0x66, 0xcc, 0x1e, 0x15, 0x99, 0xac, 0xb0, 0x4d, + 0xe6, 0xc4, 0x09, 0x07, 0x22, 0x35, 0x5d, 0x16, 0xfc, 0x05, 0xf9, 0xb8, + 0x3c, 0x3c, 0x38, 0x73, 0xa5, 0x22, 0x53, 0x47, 0x13, 0xf4, 0x8c, 0x9a, + 0x37, 0x6b, 0x88, 0x11, 0x84, 0x8a, 0x76, 0x39, 0x6f, 0x4c, 0x67, 0x82, + 0xf0, 0x4d, 0xd8, 0xf5, 0x2c, 0x9d, 0x44, 0x5a, 0xc8, 0x5d, 0x34, 0xdd, + 0xa0, 0x7e, 0x03, 0x34, 0x55, 0xd3, 0x5d, 0xff, 0x4c, 0x10, 0x79, 0x21, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0xc7, 0x1e, 0x40, 0xf3, + 0xcb, 0xa2, 0x8b, 0x1f, 0x92, 0x12, 0xe3, 0x23, 0xd7, 0xa8, 0xef, 0x15, + 0xa4, 0xf5, 0xe5, 0x65, 0xb0, 0x43, 0xff, 0xd2, 0xde, 0x2d, 0xe7, 0x0a, + 0x0c, 0xdd, 0x68, 0x2a, 0xe1, 0x47, 0x51, 0x87, 0x95, 0xc8, 0x5d, 0x00, + 0x77, 0x3d, 0x75, 0xc0, 0xef, 0x90, 0x5a, 0x2c, 0xb2, 0x73, 0x0e, 0x08, + 0x34, 0x3c, 0x3f, 0x1d, 0x53, 0xfe, 0x64, 0x0e, 0x9a, 0xa5, 0x2e, 0x11, + 0xc3, 0xde, 0x87, 0xfc, 0xeb, 0x11, 0x6e, 0x00, 0x52, 0x83, 0x1a, 0x1a, + 0x60, 0xfe, 0xc1, 0xf2, 0xf4, 0x61, 0x82, 0x88, 0x1e, 0x8b, 0xfc, 0xcc, + 0xdc, 0xee, 0xd7, 0x70, 0x48, 0xd6, 0x58, 0x2e, 0x40, 0xcf, 0xe9, 0xf5, + 0xd1, 0x17, 0x36, 0x93, 0xc5, 0x98, 0xe7, 0xac, 0xcd, 0x03, 0xb9, 0x1f, + 0x95, 0x13, 0xe7, 0xa7, 0xc3, 0x8a, 0x83, 0x22, 0x16, 0x80, 0xbc, 0x63, + 0x34, 0x10, 0xde, 0x0a, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x13, 0xbd, 0x6b, 0x8f, 0x61, 0x1a, 0xf5, 0x99, 0x4d, 0x93, 0x35, 0x83, + 0x55, 0xc0, 0x5c, 0x38, 0xc6, 0xee, 0x1a, 0x5e, 0x44, 0x3b, 0x60, 0xd8, + 0xcf, 0xe7, 0x86, 0x65, 0x5d, 0xa6, 0x81, 0x06, 0xdc, 0xca, 0x9d, 0x3e, + 0x5c, 0xbb, 0x85, 0x38, 0xd8, 0x3d, 0x4a, 0x42, 0xf7, 0x9b, 0x32, 0xac, + 0xcf, 0xa6, 0x4a, 0x28, 0xa1, 0xde, 0xb4, 0xe7, 0x8a, 0x3a, 0x56, 0xc8, + 0x8d, 0xed, 0x05, 0x24, 0xf1, 0xf2, 0xb4, 0x20, 0x8a, 0xa8, 0x20, 0x2f, + 0x9f, 0x1c, 0x19, 0x85, 0xda, 0xb3, 0x70, 0xb0, 0x33, 0xaa, 0xf6, 0x03, + 0xdb, 0xf2, 0x77, 0xd2, 0xb8, 0xac, 0xf7, 0x91, 0xdd, 0x11, 0x53, 0x0b, + 0x41, 0xbc, 0x7e, 0x89, 0x09, 0x18, 0x64, 0x9d, 0x37, 0x63, 0xae, 0xf2, + 0xfc, 0x6f, 0x4a, 0xe7, 0xde, 0xf8, 0xc5, 0xa6, 0xec, 0xf5, 0xc9, 0x37, + 0x4b, 0xdc, 0x87, 0x29, 0x37, 0x9b, 0x88, 0x16, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x67, 0xa4, 0x2e, 0xf5, 0x9a, 0xed, 0xed, 0xea, + 0xc9, 0x78, 0x22, 0xe0, 0x5a, 0xaf, 0x3d, 0x8f, 0x4d, 0xd5, 0x89, 0x00, + 0xe9, 0x5d, 0xaf, 0xac, 0x95, 0xde, 0xe7, 0x31, 0xc7, 0x70, 0xa9, 0x1a, + 0xea, 0x9c, 0x3c, 0x29, 0xc5, 0x51, 0xd5, 0x6a, 0xc0, 0x8b, 0xfe, 0x61, + 0xa9, 0xed, 0x81, 0xeb, 0xb9, 0x38, 0x31, 0x9f, 0xc1, 0xfc, 0x31, 0x6b, + 0x8a, 0x5d, 0xd5, 0x51, 0x52, 0x57, 0xd1, 0x19, 0xaa, 0xcb, 0x9b, 0x90, + 0x4b, 0x6e, 0xf9, 0x2d, 0x33, 0x0b, 0x7f, 0x5b, 0xf5, 0xe7, 0x7d, 0x78, + 0xf7, 0xd9, 0x54, 0x4f, 0xca, 0x45, 0x3a, 0x8a, 0x60, 0xc5, 0x8d, 0xd3, + 0xab, 0x65, 0x4a, 0x10, 0x6e, 0xbf, 0x1e, 0x03, 0x03, 0x32, 0x18, 0x4d, + 0xa6, 0x62, 0xd6, 0xf6, 0x1d, 0x65, 0x72, 0xb2, 0x28, 0xe4, 0x2d, 0x84, + 0xd0, 0x58, 0x16, 0x4f, 0x59, 0x9f, 0x62, 0x53, 0x07, 0x4c, 0xaf, 0x09, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0xa2, 0xd4, 0xf9, 0xc8, + 0xae, 0x45, 0x75, 0xeb, 0x3f, 0xfc, 0x5b, 0xf0, 0x36, 0x53, 0xf7, 0xd4, + 0x83, 0x1a, 0xf9, 0xef, 0x5f, 0x34, 0x78, 0x45, 0xf9, 0x99, 0x7c, 0xf5, + 0x1b, 0xa5, 0xa2, 0x09, 0x11, 0xb0, 0x5a, 0x95, 0x3e, 0x87, 0xf9, 0xd6, + 0x11, 0x5b, 0xf9, 0x94, 0x35, 0xe5, 0x26, 0x6a, 0x14, 0x4c, 0x3a, 0x33, + 0xd0, 0xaf, 0xc5, 0xae, 0x90, 0xe2, 0x1b, 0x7a, 0x21, 0xad, 0x3d, 0x27, + 0x4e, 0x5c, 0x88, 0xe5, 0x0d, 0xad, 0x3e, 0xdb, 0xa2, 0xb5, 0x76, 0x81, + 0xb6, 0xa7, 0x96, 0xaf, 0x09, 0xe2, 0xeb, 0x3e, 0x5e, 0x50, 0xff, 0x5a, + 0xaf, 0xcd, 0x4a, 0x83, 0xba, 0x9a, 0x75, 0x1b, 0xa7, 0x25, 0xb8, 0x34, + 0xda, 0x3e, 0xe0, 0x1b, 0x4e, 0x89, 0x27, 0x7e, 0x27, 0x00, 0xf1, 0x3e, + 0xbc, 0x0a, 0x2e, 0xa9, 0x45, 0xe5, 0xc7, 0x94, 0x24, 0x16, 0xdb, 0x03, + 0xaf, 0xdf, 0xc1, 0x23, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x0b, 0x4f, 0xbb, 0x13, 0xfd, 0x61, 0x62, 0xd7, 0x4d, 0x0d, 0xa8, 0x05, + 0x43, 0x0e, 0x5f, 0x5d, 0x19, 0xad, 0xf3, 0x23, 0x91, 0xb9, 0xfa, 0xd3, + 0x5e, 0x50, 0xa5, 0xcf, 0xf7, 0xc2, 0xa9, 0x20, 0xd9, 0x35, 0x0b, 0x15, + 0xd0, 0x21, 0xcb, 0x35, 0x47, 0xe7, 0x04, 0x4a, 0x6a, 0xa3, 0x10, 0x2c, + 0x2f, 0x5b, 0x3e, 0x54, 0xa2, 0x3e, 0x7a, 0x93, 0xa3, 0xfe, 0x7f, 0x51, + 0x06, 0xcd, 0xbb, 0x12, 0xd4, 0x70, 0x2f, 0xcf, 0x97, 0xab, 0xfb, 0xf8, + 0x39, 0xce, 0x09, 0x93, 0x99, 0x46, 0x88, 0xc9, 0x21, 0xc4, 0x5e, 0xc7, + 0x9e, 0x23, 0x79, 0xd0, 0x16, 0x3e, 0x58, 0xa7, 0xce, 0xd9, 0xcf, 0x2e, + 0xd3, 0x0e, 0xb3, 0xf2, 0x6a, 0x3f, 0xcf, 0xda, 0x54, 0x26, 0xc2, 0xa5, + 0x1b, 0xaf, 0xc7, 0x44, 0xdd, 0x04, 0xf9, 0x06, 0x7f, 0x84, 0x53, 0x92, + 0x3e, 0x27, 0x50, 0x28, 0x37, 0xbb, 0x1e, 0x02, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x90, 0xf4, 0xd3, 0x13, 0x2b, 0x8d, 0xdf, 0x1d, + 0x6e, 0x33, 0x02, 0x55, 0xca, 0xef, 0xe7, 0x49, 0x6e, 0xd3, 0xa6, 0x9a, + 0xdd, 0x42, 0x37, 0xbf, 0xd6, 0x3d, 0x29, 0x4a, 0xa4, 0x5a, 0xc1, 0x2e, + 0x9b, 0xfa, 0xad, 0x95, 0x51, 0x51, 0x9f, 0xb6, 0xbb, 0x16, 0xdf, 0x22, + 0x97, 0xf5, 0x83, 0x41, 0x76, 0x8b, 0xf8, 0x4c, 0x27, 0xa1, 0x2f, 0x99, + 0x2b, 0x94, 0xee, 0x55, 0x6d, 0x92, 0x88, 0x29, 0x7e, 0xea, 0x66, 0xe6, + 0x5f, 0xe2, 0x18, 0x0e, 0xad, 0xcc, 0xbb, 0x80, 0x26, 0xba, 0x1b, 0x39, + 0x4a, 0x4e, 0x7f, 0x7f, 0x85, 0xb2, 0x3d, 0x79, 0xfc, 0xdb, 0x80, 0x54, + 0x76, 0x50, 0xad, 0x2c, 0x53, 0xfc, 0x92, 0x29, 0xf8, 0x47, 0x19, 0x7a, + 0x73, 0x44, 0xdc, 0x4a, 0xdc, 0xcc, 0x57, 0x9b, 0xa7, 0x84, 0xe7, 0xf3, + 0x62, 0xc3, 0x5b, 0xfb, 0x54, 0x72, 0xed, 0x2e, 0x62, 0xc3, 0x5e, 0x2b, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x27, 0x8e, 0x65, 0xa9, + 0x4f, 0x24, 0x66, 0x1e, 0x16, 0x3e, 0x1a, 0xc8, 0x5d, 0x70, 0x37, 0x35, + 0x6d, 0x74, 0x57, 0x27, 0xa9, 0x07, 0x9c, 0x71, 0x94, 0x1d, 0x3c, 0x20, + 0xb0, 0x22, 0x6f, 0x0b, 0xa6, 0x6a, 0xe6, 0x49, 0xa2, 0x55, 0x6b, 0x58, + 0xc1, 0x28, 0x5b, 0xb4, 0xb3, 0xb5, 0x39, 0xa5, 0xb0, 0xbd, 0x8e, 0x49, + 0xef, 0x9f, 0xe4, 0x43, 0x42, 0x30, 0x79, 0xe3, 0xd9, 0x96, 0xa3, 0x14, + 0xe3, 0xa5, 0x04, 0x59, 0xe9, 0xb7, 0xae, 0x27, 0xa4, 0xf5, 0x94, 0x7d, + 0x6d, 0x69, 0x19, 0x56, 0x1b, 0x2b, 0x37, 0x34, 0x17, 0x82, 0x51, 0x9d, + 0x8e, 0x47, 0x48, 0x27, 0xfb, 0x58, 0x23, 0x2f, 0xbf, 0x5a, 0x21, 0xb5, + 0xd9, 0x2e, 0x88, 0x58, 0x9c, 0xf4, 0xfd, 0x70, 0xa8, 0x0d, 0x03, 0xb9, + 0xc4, 0xa8, 0xce, 0xd2, 0xcb, 0x72, 0xff, 0xa7, 0x7e, 0xb1, 0x05, 0x9b, + 0xab, 0xd3, 0xf6, 0x2e, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0xab, 0xe8, 0xd2, 0x2c, 0x3e, 0x2c, 0xe0, 0xb0, 0x88, 0xbe, 0x7c, 0xa1, + 0x05, 0x6f, 0x26, 0xb1, 0x9a, 0xd7, 0x18, 0x59, 0x96, 0x1a, 0x40, 0xab, + 0xb3, 0xd8, 0x2e, 0xd1, 0x27, 0x3c, 0x4f, 0x1c, 0xd2, 0xc4, 0x15, 0x4f, + 0x66, 0xb6, 0x3f, 0x49, 0xab, 0x41, 0xc8, 0xe3, 0x23, 0x2b, 0x6a, 0xdf, + 0x57, 0xbb, 0x01, 0xb9, 0x34, 0x70, 0xf0, 0xb7, 0xcf, 0x58, 0xbe, 0x3d, + 0x9e, 0x4a, 0x39, 0x0f, 0xf9, 0xe3, 0x10, 0x88, 0x12, 0xc0, 0xd2, 0x16, + 0x2b, 0x01, 0x4e, 0x71, 0x48, 0xff, 0x05, 0xef, 0x72, 0xe0, 0xea, 0x74, + 0xca, 0x32, 0xdb, 0xae, 0x1a, 0xdb, 0xc5, 0xf6, 0xd5, 0xd0, 0xbd, 0x19, + 0xb6, 0xac, 0x7d, 0x73, 0x51, 0x5d, 0xa5, 0x33, 0x2d, 0xa3, 0x03, 0xe4, + 0x45, 0x4f, 0xf0, 0xd1, 0x99, 0xf6, 0xf6, 0x71, 0x16, 0x65, 0x0d, 0x86, + 0x2b, 0xff, 0x8e, 0x30, 0xf3, 0x1c, 0x4d, 0x00, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x5b, 0x02, 0x94, 0x24, 0x41, 0x5b, 0x75, 0x91, + 0x05, 0xb6, 0x8e, 0x22, 0xe6, 0x8a, 0x2a, 0x39, 0x1a, 0xae, 0x5a, 0x4a, + 0x77, 0xe9, 0x64, 0x00, 0xf4, 0x66, 0xac, 0xcb, 0xf6, 0xe1, 0x6c, 0x0b, + 0xf3, 0x53, 0xc0, 0x37, 0x9d, 0x54, 0x86, 0xdb, 0xdc, 0x8a, 0x8f, 0x21, + 0x5a, 0x67, 0xe2, 0x7b, 0xc4, 0x6c, 0xa0, 0x94, 0xce, 0x27, 0xc5, 0xae, + 0x5a, 0x7f, 0xfc, 0xec, 0xbe, 0xdc, 0xc8, 0x1c, 0xb6, 0x9d, 0xe3, 0x70, + 0xd3, 0x0f, 0x95, 0x9a, 0x5b, 0x97, 0x14, 0x46, 0x36, 0x56, 0x91, 0x37, + 0x44, 0x14, 0x11, 0x2b, 0xed, 0x30, 0xa9, 0x4d, 0xbd, 0xed, 0x97, 0xfd, + 0xc4, 0x48, 0x60, 0x15, 0xaf, 0xd2, 0x0c, 0xf0, 0xe1, 0x0a, 0x03, 0x30, + 0x63, 0x7e, 0xee, 0xca, 0x6b, 0xd4, 0xbf, 0x46, 0xb7, 0xf1, 0x83, 0x6d, + 0x26, 0x12, 0x2e, 0x70, 0x0b, 0xe5, 0xf9, 0x02, 0xaf, 0x33, 0xb1, 0x29, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x99, 0xaf, 0x1e, 0x02, + 0x96, 0x31, 0x20, 0x3e, 0xe2, 0x96, 0x44, 0x2a, 0xbf, 0x7e, 0x2a, 0x60, + 0x59, 0xd5, 0x64, 0x9b, 0xe3, 0xce, 0xa7, 0xbe, 0x57, 0xb1, 0xcd, 0xa2, + 0xd0, 0x7f, 0xd3, 0x18, 0x65, 0xe1, 0xf9, 0xf0, 0x1d, 0xf5, 0xff, 0x0d, + 0x62, 0x50, 0xd8, 0x4d, 0x75, 0x69, 0x5b, 0x33, 0x13, 0xb7, 0x47, 0x80, + 0x5f, 0xd3, 0xc8, 0xa2, 0xfd, 0xda, 0x8f, 0x9b, 0x33, 0xf9, 0xc6, 0x0b, + 0xb4, 0xfa, 0x52, 0xb7, 0x6e, 0x04, 0x48, 0x43, 0x51, 0x73, 0x2d, 0x6c, + 0xac, 0xd3, 0x64, 0x66, 0xe9, 0x2c, 0x4f, 0x0b, 0xf4, 0x49, 0x27, 0x05, + 0x58, 0x16, 0x9b, 0x97, 0xb7, 0x06, 0x4e, 0x1c, 0x94, 0x56, 0x5d, 0xd5, + 0xe4, 0xdf, 0xf3, 0x54, 0x15, 0x24, 0xc2, 0xae, 0x27, 0xc3, 0xec, 0xac, + 0x1e, 0x83, 0x38, 0xbf, 0xdf, 0xf6, 0xad, 0x71, 0xc3, 0xdd, 0x52, 0xd3, + 0x09, 0x2f, 0xdd, 0x10, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x3f, 0xbe, 0xfe, 0x1d, 0xd5, 0x14, 0xfb, 0xda, 0x06, 0xe4, 0x78, 0x4d, + 0xdb, 0xca, 0xe9, 0x96, 0xd6, 0x53, 0xa5, 0x97, 0x23, 0x39, 0x7b, 0xf5, + 0x47, 0xeb, 0x74, 0xad, 0xf1, 0x68, 0xcd, 0x28, 0x85, 0x4e, 0x9e, 0xfe, + 0xbf, 0xf0, 0xca, 0x76, 0x2a, 0x7a, 0x08, 0x29, 0xa3, 0xa3, 0x0b, 0xa5, + 0x66, 0x53, 0x86, 0x54, 0x12, 0x97, 0x44, 0x41, 0x27, 0x3c, 0x0a, 0x8b, + 0xb9, 0x31, 0xb6, 0x1b, 0x48, 0x98, 0x27, 0xd0, 0x46, 0xf1, 0x83, 0x1a, + 0xfc, 0x29, 0x7a, 0xa6, 0x81, 0x6c, 0x7f, 0x34, 0x3f, 0xf9, 0x24, 0xe7, + 0x3c, 0xc5, 0xe2, 0x54, 0x59, 0xc6, 0xdd, 0x18, 0xab, 0x54, 0xe2, 0x04, + 0x04, 0x30, 0x63, 0x17, 0xa6, 0x75, 0x90, 0xe3, 0x32, 0x68, 0xd3, 0xf9, + 0x11, 0x74, 0x8d, 0x88, 0xe5, 0xa7, 0xde, 0x2a, 0xb9, 0x27, 0x4e, 0x98, + 0x0d, 0x7e, 0x54, 0x53, 0x39, 0xd3, 0xd3, 0x2f, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x5f, 0x4d, 0x52, 0xe4, 0xde, 0x4f, 0x2a, 0x4b, + 0xb4, 0x92, 0x07, 0x0f, 0x94, 0xc4, 0x56, 0x96, 0x0c, 0x8a, 0xdd, 0xb8, + 0x01, 0xbf, 0xf7, 0x10, 0xe9, 0xc6, 0x51, 0x85, 0xc5, 0xd7, 0x7c, 0x01, + 0xbd, 0x92, 0x93, 0x44, 0x7a, 0x83, 0x44, 0x37, 0x83, 0x0a, 0x81, 0x17, + 0x19, 0x93, 0xab, 0xd6, 0x31, 0xfb, 0xc3, 0x46, 0x2c, 0x5d, 0xc9, 0x92, + 0xcb, 0x7f, 0x97, 0x1a, 0x9c, 0x7a, 0x4d, 0x07, 0x0a, 0xaa, 0x3d, 0xd9, + 0x7f, 0x1c, 0x6d, 0x98, 0x56, 0x60, 0xee, 0xa2, 0x55, 0x2c, 0x9c, 0x57, + 0x9d, 0x1b, 0x59, 0x79, 0x61, 0xd6, 0xe9, 0x8a, 0x9f, 0xee, 0x74, 0x43, + 0x8a, 0x7c, 0xd2, 0x1d, 0xeb, 0xc2, 0x53, 0x4e, 0x26, 0xab, 0x1b, 0xf1, + 0x0d, 0x86, 0xfd, 0xbe, 0x67, 0xc0, 0xf5, 0x02, 0x1c, 0x75, 0x27, 0xc1, + 0x7b, 0x7d, 0xbb, 0xdb, 0x1b, 0x5b, 0x3e, 0xf2, 0x35, 0xe8, 0xe8, 0x29, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x43, 0xbf, 0x19, 0x87, + 0x5c, 0x56, 0x04, 0xf5, 0x04, 0xea, 0x06, 0x6f, 0x92, 0x87, 0xd5, 0x7b, + 0x83, 0xf5, 0x6b, 0x58, 0x28, 0x45, 0xda, 0x1b, 0xc0, 0xf5, 0xd2, 0xeb, + 0x4b, 0x56, 0xd7, 0x29, 0xf9, 0x3e, 0x9e, 0xfd, 0xfe, 0x1c, 0xa1, 0xfb, + 0x9b, 0x97, 0xcc, 0x27, 0x71, 0x03, 0x3d, 0x34, 0x44, 0x73, 0xb8, 0xac, + 0x55, 0x25, 0xab, 0xe1, 0xde, 0x9b, 0x9d, 0x0a, 0x09, 0xb2, 0x7c, 0x19, + 0xf3, 0xe8, 0x4f, 0x89, 0xce, 0x7e, 0x0c, 0x11, 0x9f, 0xf2, 0x32, 0xdb, + 0x6f, 0xe5, 0x1b, 0x31, 0x9c, 0xdb, 0x28, 0xcb, 0xa2, 0x22, 0xe1, 0x8a, + 0xe5, 0x76, 0xd4, 0x2b, 0xd3, 0xd6, 0xc2, 0x02, 0xb8, 0x52, 0xe7, 0x7a, + 0xfa, 0xf0, 0x8a, 0xa2, 0x23, 0x4e, 0xe7, 0x72, 0xe4, 0x65, 0x50, 0xf7, + 0x54, 0x40, 0x48, 0x13, 0x20, 0xb3, 0x25, 0xfd, 0x34, 0xe2, 0x66, 0xb6, + 0x31, 0x74, 0x1f, 0x28, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0xbe, 0xf4, 0x9a, 0x05, 0xfb, 0x81, 0x27, 0x94, 0x20, 0xa9, 0x7b, 0x5a, + 0x69, 0x37, 0x28, 0x39, 0xe2, 0x88, 0x05, 0x55, 0xe4, 0x78, 0x14, 0x35, + 0x47, 0x7d, 0xda, 0x2d, 0x1c, 0x8c, 0x74, 0x11, 0xbe, 0xbb, 0x67, 0xcf, + 0xe5, 0x0c, 0x23, 0x8f, 0x66, 0xda, 0x3c, 0x5d, 0xc6, 0x61, 0x04, 0x14, + 0x2a, 0x94, 0xcd, 0x54, 0x8a, 0xe9, 0x3d, 0x34, 0x49, 0xb5, 0xd9, 0x0a, + 0x63, 0xaf, 0x3e, 0x00, 0x68, 0x31, 0x80, 0x6a, 0x62, 0x3a, 0xa9, 0x2b, + 0x17, 0x41, 0xfa, 0xc6, 0x66, 0x02, 0x92, 0xb6, 0x14, 0x40, 0x52, 0xfe, + 0x11, 0x13, 0xcc, 0x10, 0xa8, 0xa4, 0xc8, 0x74, 0x4b, 0xfd, 0x73, 0x07, + 0x6e, 0x6b, 0x76, 0x98, 0xa6, 0xef, 0x99, 0xfb, 0x75, 0xd0, 0xc6, 0x54, + 0xcb, 0x7f, 0x2c, 0x2b, 0xdb, 0x85, 0x93, 0x2c, 0x4d, 0x8a, 0xf8, 0x26, + 0xec, 0x83, 0xfe, 0x2e, 0xc1, 0x17, 0x56, 0x2e, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0xd1, 0x79, 0x15, 0xc7, 0x83, 0x29, 0x01, 0xc5, + 0xfa, 0x52, 0xbf, 0xa0, 0x45, 0x8a, 0x3c, 0x29, 0xd1, 0x3d, 0x79, 0xdb, + 0x2f, 0x0e, 0xb7, 0x87, 0x11, 0xb3, 0x41, 0x18, 0xc4, 0x7a, 0xe3, 0x16, + 0x5c, 0x2b, 0x41, 0x94, 0xc9, 0xcd, 0x3a, 0x67, 0x50, 0xd6, 0x54, 0x11, + 0x2d, 0xd5, 0x2b, 0x05, 0x58, 0xcc, 0x42, 0x5d, 0x00, 0x26, 0xf6, 0x62, + 0x57, 0x33, 0x84, 0xc1, 0x25, 0xcb, 0xa3, 0x00, 0x26, 0xc3, 0xf2, 0xf5, + 0x10, 0xae, 0xd5, 0x2c, 0x81, 0x6f, 0x36, 0x5a, 0x4d, 0x4a, 0x1f, 0xee, + 0x63, 0x50, 0xbb, 0x46, 0x64, 0x57, 0x2b, 0x1e, 0xcf, 0x6a, 0x06, 0xa0, + 0xaa, 0xee, 0x1b, 0x1f, 0x48, 0x6f, 0xdb, 0xd1, 0xb2, 0x30, 0x44, 0x00, + 0x61, 0x3c, 0xf7, 0x5d, 0xb3, 0x3d, 0xe1, 0xa2, 0xb5, 0x66, 0xa7, 0x08, + 0xec, 0xda, 0x07, 0xd4, 0xb2, 0xa8, 0xa0, 0x7d, 0xed, 0xdc, 0x19, 0x2e, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x72, 0x05, 0x06, 0x1f, + 0x5a, 0x02, 0x08, 0xab, 0x39, 0xc3, 0x64, 0x2f, 0x5d, 0xb2, 0x13, 0xd2, + 0xe4, 0x0c, 0x8a, 0x88, 0x94, 0x8e, 0x3b, 0x8c, 0xbc, 0xa1, 0x35, 0xe3, + 0x2a, 0xdb, 0x5c, 0x0e, 0x8b, 0xc3, 0x75, 0x06, 0x6b, 0x65, 0x77, 0x59, + 0x89, 0x06, 0x02, 0x80, 0xe2, 0x31, 0x51, 0xc3, 0xce, 0xc9, 0x2d, 0x0b, + 0x0d, 0xe2, 0xcc, 0xe7, 0x52, 0x78, 0x41, 0x07, 0x8f, 0xf8, 0xb5, 0x20, + 0x3b, 0x06, 0x30, 0xaa, 0xd2, 0xf4, 0x1c, 0x45, 0x26, 0x20, 0x3f, 0x07, + 0x88, 0x03, 0x34, 0x1f, 0x57, 0x9c, 0x54, 0xa2, 0x7b, 0x02, 0xaf, 0x7a, + 0xc9, 0xe4, 0x32, 0x3c, 0x4c, 0xa1, 0xba, 0x1f, 0x95, 0x93, 0x99, 0x07, + 0xbe, 0xb0, 0x7d, 0xd2, 0x97, 0xe3, 0x0b, 0xa8, 0x78, 0x13, 0xf9, 0xdb, + 0x6f, 0xea, 0x13, 0x61, 0x3b, 0x38, 0x41, 0x5f, 0x05, 0xc1, 0x87, 0x07, + 0xb2, 0x84, 0x67, 0x03, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x00, 0x00, 0x00, 0x30, 0xc2, 0x35, 0xb2, 0xc0, 0xe8, 0x0e, 0x8a, 0xaf, + 0x28, 0x09, 0x1e, 0x7e, 0x9e, 0x37, 0x96, 0x87, 0x92, 0x36, 0x29, 0xd7, + 0x70, 0xd5, 0x84, 0xef, 0xb7, 0x50, 0x42, 0x00, 0xdb, 0x65, 0x7f, 0x96, + 0x2b, 0xfd, 0x56, 0xb8, 0xd4, 0x98, 0x1c, 0xdc, 0xf9, 0x6c, 0x2d, 0x09, + 0xc2, 0x47, 0x48, 0x4f, 0x23, 0xec, 0xa4, 0x59, 0x33, 0x8f, 0x0e, 0x0d, + 0xa1, 0x02, 0x5f, 0x09, 0xb1, 0x69, 0x7f, 0x53, 0x0c, 0xcb, 0x28, 0xbc, + 0x8a, 0x69, 0xd9, 0x38, 0x2a, 0xa2, 0x2e, 0x89, 0xd7, 0x0f, 0x1d, 0x66, + 0xca, 0x91, 0x41, 0xf7, 0x78, 0x16, 0x75, 0x8b, 0x57, 0xff, 0xf2, 0x0b, + 0x8e, 0xe3, 0x5e, 0x5a, 0xf5, 0xd0, 0x3a, 0xb1, 0x42, 0x9c, 0x42, 0x6f, + 0x58, 0x39, 0x2e, 0xf5, 0x83, 0xf2, 0xd3, 0x1a, 0x95, 0xfe, 0x43, 0x86, + 0x91, 0x67, 0x25, 0x97, 0x8f, 0x14, 0xd3, 0x01, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0x00, 0x24, 0x7a, 0x63, 0x86, 0x07, + 0x09, 0xeb, 0x71, 0x66, 0xa4, 0x43, 0x09, 0xeb, 0xbc, 0x2d, 0x8c, 0x2c, + 0xae, 0xeb, 0x7e, 0xde, 0xbf, 0x45, 0x0a, 0x22, 0x91, 0x27, 0x00, 0x00, + 0x91, 0x31, 0x7e, 0x2b, 0x15, 0xf7, 0x0b, 0x2c, 0x28, 0x12, 0x19, 0xe6, + 0x52, 0xa3, 0x61, 0x0b, 0xc7, 0x76, 0xf9, 0x2e, 0x61, 0x40, 0x09, 0x5d, + 0xca, 0x62, 0xa8, 0x36, 0xf1, 0xcc, 0x08, 0x1d, 0xfc, 0x07, 0x2c, 0x22, + 0x30, 0xa8, 0xdb, 0x75, 0xfa, 0x8a, 0x39, 0x04, 0xb2, 0xfe, 0xab, 0x06, + 0x24, 0xc6, 0x61, 0x94, 0x55, 0xde, 0x09, 0xcb, 0xcf, 0x51, 0xaa, 0x66, + 0x9c, 0xa3, 0x99, 0x19, 0x83, 0xd7, 0xe1, 0xd3, 0x3e, 0xa9, 0xe6, 0x35, + 0x91, 0x43, 0x56, 0x6e, 0xd7, 0x52, 0xfc, 0x43, 0xcf, 0x92, 0x85, 0x65, + 0x66, 0xb8, 0xa0, 0x4c, 0x07, 0x6b, 0x1b, 0x36, 0xd4, 0xf4, 0x4b, 0x1f, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0x00, 0xac, + 0x99, 0x37, 0xb3, 0x60, 0xfa, 0x50, 0xcb, 0x16, 0x8f, 0x95, 0x6b, 0xcc, + 0x70, 0x69, 0x74, 0x2e, 0x07, 0xd5, 0x81, 0x98, 0xee, 0x16, 0x88, 0x9b, + 0x17, 0x00, 0x00, 0x00, 0x6c, 0x97, 0xfd, 0xef, 0x76, 0xf9, 0x96, 0x38, + 0x72, 0x3a, 0x80, 0xb9, 0xf6, 0xbd, 0xdf, 0x4b, 0x60, 0x02, 0x7f, 0x21, + 0xe4, 0x49, 0xee, 0xaf, 0xda, 0xf9, 0x6d, 0xb4, 0x0c, 0xa5, 0xb6, 0x26, + 0x19, 0x64, 0xb7, 0xe3, 0xf6, 0xdb, 0x71, 0x48, 0x9b, 0xbb, 0xeb, 0x2f, + 0xbc, 0x31, 0xad, 0x2f, 0x4c, 0x0a, 0xe4, 0xca, 0x67, 0x3a, 0xf4, 0x6b, + 0xcc, 0x60, 0x36, 0xde, 0x49, 0xc4, 0xc8, 0x13, 0x17, 0x23, 0x4b, 0x69, + 0xcf, 0xb9, 0x62, 0x66, 0x59, 0x27, 0x0b, 0x57, 0x11, 0x63, 0x82, 0x44, + 0xd4, 0x5f, 0x83, 0x6a, 0x3c, 0x3f, 0x1f, 0x28, 0x6b, 0x56, 0x63, 0x2e, + 0xb6, 0x29, 0xc1, 0x2a, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x00, 0x00, 0x00, 0xa5, 0xd1, 0xee, 0x7c, 0xd0, 0xba, 0xcb, 0x9d, 0x26, + 0x7f, 0xd1, 0xed, 0xba, 0xb3, 0x89, 0xf0, 0x52, 0xc2, 0x4f, 0x0c, 0xf0, + 0x23, 0xdd, 0x15, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xcb, 0xfe, 0x08, + 0x2b, 0xa4, 0xb6, 0x7e, 0xe8, 0xdb, 0x9d, 0x5a, 0x52, 0xc6, 0xd0, 0x3f, + 0xf8, 0x1e, 0x32, 0x5c, 0xb1, 0x2f, 0x73, 0x36, 0xe5, 0x3c, 0x5f, 0x49, + 0x94, 0x52, 0x5b, 0x13, 0xc6, 0x67, 0xfe, 0x73, 0x72, 0x87, 0x4f, 0x41, + 0xa3, 0x3f, 0x62, 0xfc, 0xb5, 0x53, 0x70, 0x9b, 0x63, 0x4a, 0x29, 0xf1, + 0x43, 0xb1, 0x35, 0xa1, 0x15, 0x3e, 0x75, 0xb6, 0xc0, 0x1e, 0x98, 0x02, + 0x6a, 0xe0, 0x1f, 0xd7, 0x81, 0x0b, 0x7e, 0x6a, 0x97, 0x3b, 0x27, 0xe3, + 0x72, 0x1b, 0x86, 0xd7, 0xbb, 0xf0, 0x8a, 0x9d, 0x5f, 0x4d, 0xc5, 0x05, + 0xa1, 0x93, 0xd0, 0xbe, 0xb5, 0x5d, 0x2a, 0x26, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0x00, 0x83, 0x1e, 0x97, 0x8a, 0xf6, + 0x06, 0xe2, 0xcb, 0xfe, 0xa5, 0x10, 0x1f, 0x59, 0x8b, 0xd6, 0x2f, 0x75, + 0xeb, 0x3d, 0xff, 0xdf, 0x6e, 0x67, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdb, 0x65, 0xff, 0x4d, 0x69, 0x9c, 0xf6, 0x9e, 0x5a, 0xa1, 0xa2, 0xf7, + 0x84, 0x91, 0x3f, 0x13, 0x61, 0x40, 0xa3, 0x76, 0x7e, 0xf9, 0x1d, 0xca, + 0x32, 0xf5, 0xff, 0x2c, 0x4a, 0xa9, 0xad, 0x09, 0x88, 0x37, 0xe5, 0x02, + 0xe3, 0x29, 0x5b, 0x34, 0xa5, 0x4a, 0x3d, 0xc4, 0x52, 0x48, 0xd5, 0xd1, + 0xfa, 0xac, 0xe0, 0x3f, 0x8d, 0xa6, 0xd1, 0xee, 0x8a, 0x26, 0x94, 0xfd, + 0x6a, 0x8e, 0x54, 0x01, 0x0f, 0xc5, 0x62, 0x79, 0x3c, 0xe3, 0x0f, 0x55, + 0xf6, 0x7f, 0xe7, 0x46, 0x97, 0x81, 0x55, 0xfa, 0xd4, 0x66, 0x6a, 0xa7, + 0x12, 0xd4, 0x89, 0xcd, 0x49, 0x66, 0xe4, 0xa9, 0xe7, 0xb6, 0xa5, 0x17, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0x40, 0xe4, + 0x16, 0xab, 0x32, 0x30, 0xf2, 0x5a, 0x04, 0x1d, 0x4c, 0x5c, 0xea, 0xfe, + 0x39, 0xbb, 0xe4, 0x26, 0x4f, 0x5e, 0x35, 0xa6, 0x03, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x31, 0x7e, 0x90, 0xb9, 0xc8, 0x03, 0x19, + 0xf1, 0xce, 0x9e, 0x8f, 0x75, 0xd4, 0xbf, 0x0c, 0xf9, 0x40, 0xac, 0xfa, + 0x39, 0xb1, 0xdc, 0x00, 0x8d, 0xc0, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x80, 0x5a, 0xfe, 0x55, 0xc1, 0xac, 0x86, 0x0d, 0x28, 0x0e, 0xc1, 0xcc, + 0xc3, 0x57, 0x5d, 0x2f, 0x7a, 0x19, 0x35, 0x28, 0xe1, 0xd3, 0x13, 0xdf, + 0x1d, 0x81, 0xce, 0x23, 0x2b, 0x21, 0xea, 0x0f, 0xc1, 0xab, 0x12, 0x2c, + 0xde, 0x4c, 0xfb, 0x4d, 0x6a, 0x28, 0x99, 0x15, 0x90, 0x88, 0x10, 0x0d, + 0x20, 0xf1, 0x51, 0x36, 0x15, 0x46, 0x02, 0x2f, 0x9d, 0xdf, 0x9e, 0x4d, + 0xc6, 0x5d, 0xeb, 0x11, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x00, 0x00, 0xc0, 0x5a, 0x43, 0x4f, 0x54, 0x90, 0x5b, 0x8f, 0x29, 0xf1, + 0xbe, 0xb3, 0x8e, 0xbf, 0x2b, 0x63, 0x9b, 0xa4, 0x6d, 0x29, 0xe3, 0xfd, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x97, 0x5d, 0x98, + 0xeb, 0x47, 0xe3, 0x8b, 0x66, 0xbd, 0xab, 0xd1, 0x23, 0x0c, 0xe8, 0x30, + 0x76, 0x1e, 0x9b, 0xfa, 0xe0, 0x9d, 0x18, 0x07, 0x51, 0xb3, 0x27, 0xb4, + 0x28, 0xa5, 0xb6, 0x26, 0xf3, 0x89, 0xcd, 0x60, 0x62, 0xcf, 0xf6, 0x00, + 0x71, 0xd5, 0x8c, 0x00, 0x45, 0x98, 0xac, 0xd4, 0x90, 0xac, 0xb7, 0x52, + 0x75, 0xa9, 0x08, 0xf8, 0x28, 0x3d, 0x8e, 0x37, 0x30, 0x38, 0xfe, 0x14, + 0x54, 0x16, 0x03, 0x8c, 0xf6, 0xd1, 0xd8, 0x07, 0x8c, 0x2e, 0xbb, 0x81, + 0x95, 0x71, 0x92, 0xcd, 0x8b, 0x2c, 0xfa, 0x58, 0x12, 0xa5, 0x72, 0x00, + 0x50, 0x30, 0x57, 0xec, 0x0b, 0xbf, 0x39, 0x0c, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0xd0, 0xb0, 0xb1, 0x11, 0x5d, 0x5f, + 0x5d, 0xc3, 0x95, 0x1a, 0x6e, 0xc2, 0xfe, 0xd5, 0xed, 0x59, 0xd2, 0x9f, + 0x2b, 0xf7, 0xc8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb6, 0xcb, 0xbe, 0xe2, 0x51, 0x33, 0x50, 0x43, 0xc6, 0x29, 0xcc, 0x57, + 0x85, 0x56, 0xb9, 0x33, 0x45, 0xf7, 0x91, 0x39, 0x91, 0xbd, 0x9b, 0x47, + 0xaa, 0xd9, 0x13, 0x5a, 0x94, 0x52, 0x5b, 0x13, 0x05, 0xf2, 0xc7, 0x11, + 0xb2, 0xe6, 0x7f, 0x5e, 0xcb, 0x1c, 0x5d, 0xc4, 0xac, 0x7b, 0x96, 0x1b, + 0x03, 0x2a, 0x4b, 0x86, 0x9e, 0xee, 0x34, 0x08, 0x1b, 0xbb, 0xa4, 0x32, + 0xe7, 0x20, 0x95, 0x01, 0x1e, 0x85, 0x1a, 0x18, 0x7e, 0xe2, 0x87, 0x82, + 0x97, 0xe2, 0x2c, 0xad, 0x78, 0x8e, 0xba, 0x78, 0x0c, 0xf5, 0xbd, 0xe5, + 0xc7, 0x1b, 0x87, 0x22, 0xb5, 0xe7, 0x92, 0xb4, 0xbf, 0x8c, 0x46, 0x1b, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0x30, 0x32, + 0x38, 0x7a, 0x48, 0x1a, 0x77, 0x0f, 0x63, 0xf3, 0x88, 0x03, 0x96, 0xed, + 0xc5, 0x2c, 0x20, 0xd4, 0xa5, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xdb, 0x65, 0x37, 0xb8, 0xf5, 0x48, 0x4a, 0xae, + 0xa7, 0xcf, 0x21, 0xef, 0x6a, 0x17, 0x82, 0xb4, 0xb2, 0x6f, 0x8d, 0xc1, + 0x60, 0x97, 0xdb, 0x24, 0xd5, 0xec, 0x09, 0x2d, 0x4a, 0xa9, 0xad, 0x09, + 0x3f, 0xc5, 0x00, 0x4a, 0xda, 0x3f, 0xd4, 0xe8, 0x0c, 0xc7, 0xe0, 0x1c, + 0xab, 0x20, 0xe6, 0x3c, 0x44, 0x87, 0x1e, 0x21, 0x0b, 0xc3, 0xd1, 0xcd, + 0xd5, 0x2e, 0x39, 0xe2, 0x02, 0x4e, 0x42, 0x19, 0xfd, 0xf0, 0x2c, 0xfa, + 0x00, 0xd6, 0xad, 0x43, 0xd6, 0x9d, 0xcb, 0x4f, 0x63, 0x98, 0xf3, 0x50, + 0x5f, 0x28, 0x1f, 0xb2, 0x7d, 0xd7, 0x3e, 0x0f, 0x21, 0x24, 0x4f, 0x74, + 0x79, 0x30, 0x38, 0x08, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x00, 0x00, 0x64, 0x7f, 0x44, 0x75, 0xc4, 0x97, 0x37, 0x63, 0x51, 0x19, + 0x64, 0xd6, 0x26, 0x62, 0xe4, 0x5c, 0xc4, 0xac, 0xa2, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x31, 0x0e, 0x49, + 0x6a, 0x93, 0xbb, 0x45, 0x2d, 0x20, 0x07, 0x6e, 0xc8, 0x7d, 0x32, 0xe7, + 0xe9, 0x49, 0x57, 0x5e, 0x79, 0x8f, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, + 0xde, 0xfb, 0x08, 0x1d, 0xac, 0x9e, 0x5b, 0xc3, 0x81, 0x9b, 0x43, 0x91, + 0x50, 0x97, 0x3c, 0x2f, 0xe7, 0xd1, 0xa9, 0x16, 0x96, 0xf8, 0x99, 0xd4, + 0x5d, 0x93, 0xc0, 0x73, 0xc2, 0x01, 0x0b, 0xa2, 0x5e, 0x50, 0xcd, 0x0d, + 0xf3, 0xb4, 0x51, 0x38, 0xe0, 0xf1, 0x86, 0x5d, 0x4a, 0x19, 0xd4, 0x31, + 0x73, 0x19, 0xe2, 0x61, 0x58, 0xe8, 0x7a, 0x10, 0x5e, 0x5f, 0xcc, 0x68, + 0x13, 0x10, 0xfc, 0xda, 0x41, 0x41, 0x2c, 0x09, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0xac, 0xba, 0x36, 0xd5, 0x4b, 0x79, + 0xf3, 0x04, 0xf5, 0x8c, 0x51, 0xd7, 0x9c, 0xc4, 0x42, 0x49, 0x0f, 0x61, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6c, 0x97, 0xd3, 0x1b, 0xb7, 0x4f, 0x34, 0xce, 0x00, 0x32, 0x35, 0x09, + 0x4c, 0x20, 0x6a, 0x91, 0x59, 0x65, 0x7d, 0xf4, 0xf7, 0x6a, 0x73, 0x93, + 0x54, 0xb3, 0x27, 0xb4, 0x28, 0xa5, 0xb6, 0x26, 0x8d, 0x3f, 0x06, 0xdc, + 0x53, 0xe8, 0x70, 0xd5, 0x93, 0xf1, 0xb9, 0xd9, 0xce, 0x21, 0x5f, 0x21, + 0x02, 0x65, 0xe1, 0x66, 0xf8, 0x63, 0x4e, 0x80, 0x02, 0x2b, 0xd6, 0x9f, + 0x94, 0x9b, 0xbf, 0x19, 0xb7, 0xd2, 0x9e, 0x2d, 0x6e, 0xa5, 0x07, 0xf5, + 0x48, 0x0e, 0xdc, 0x9a, 0x22, 0x47, 0xd5, 0x74, 0xa2, 0x48, 0x40, 0x66, + 0xe4, 0x87, 0x48, 0x91, 0xb6, 0x83, 0x9d, 0x12, 0x08, 0x4b, 0x3c, 0x2a, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x00, 0x00, 0xb5, 0x26, + 0x62, 0x47, 0xcf, 0x65, 0x84, 0xa1, 0x99, 0xdc, 0x4d, 0x33, 0x06, 0x56, + 0x18, 0xe9, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xb6, 0xcb, 0x6a, 0xff, 0xb5, 0x07, 0x85, 0x6d, + 0x69, 0xe6, 0x8d, 0x30, 0xce, 0xfd, 0xbb, 0xda, 0xbe, 0xa7, 0x88, 0x33, + 0x7c, 0xb5, 0xb9, 0x49, 0xaa, 0xd9, 0x13, 0x5a, 0x94, 0x52, 0x5b, 0x13, + 0x6e, 0xe5, 0x12, 0xb3, 0x6f, 0xce, 0x4d, 0xbe, 0xa5, 0xc4, 0x57, 0xf5, + 0x09, 0x0d, 0x6c, 0xb4, 0x67, 0xd0, 0x35, 0xfa, 0x08, 0xc8, 0x36, 0x65, + 0x56, 0x40, 0x6f, 0x86, 0x5e, 0xcf, 0xbe, 0x17, 0x86, 0x70, 0x7c, 0x16, + 0x07, 0x2a, 0x2d, 0xbf, 0xf6, 0x70, 0x14, 0xc6, 0x09, 0x55, 0x4f, 0xb7, + 0xaf, 0x5c, 0xd1, 0x9f, 0x11, 0x5a, 0x3a, 0x01, 0x10, 0xce, 0x6e, 0x34, + 0x90, 0x23, 0xdb, 0x09, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x00, 0x00, 0x03, 0xc6, 0x05, 0x53, 0x9b, 0xa2, 0x22, 0xa8, 0x0c, 0xfa, + 0x63, 0x9c, 0xc2, 0x5e, 0x8d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xe5, 0x26, 0xdc, + 0x7c, 0x3f, 0x7d, 0xbb, 0x94, 0xcc, 0xe8, 0x4c, 0x45, 0x0b, 0xd9, 0x2a, + 0x4b, 0x82, 0xe6, 0x19, 0xbe, 0xda, 0xdc, 0x24, 0xd5, 0xec, 0x09, 0x2d, + 0x4a, 0xa9, 0xad, 0x09, 0xf1, 0x7d, 0x3c, 0x69, 0xb5, 0x0c, 0xf0, 0x69, + 0x4d, 0xff, 0xf0, 0xa8, 0x6c, 0xad, 0x25, 0xdb, 0x52, 0xf8, 0x5b, 0x10, + 0xc6, 0x82, 0x8a, 0xc2, 0x48, 0x0c, 0x9b, 0xed, 0xf9, 0xd7, 0xc4, 0x1a, + 0x18, 0x02, 0x62, 0x36, 0xfd, 0x7b, 0x3e, 0x4b, 0x9e, 0x07, 0x3d, 0xf1, + 0xfc, 0xa8, 0xbe, 0x37, 0xe9, 0x3a, 0x38, 0x60, 0x0e, 0xbb, 0xce, 0x9e, + 0x5b, 0x99, 0xe4, 0x13, 0xbf, 0xd5, 0x90, 0x0d, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x00, 0x40, 0x58, 0x89, 0xea, 0xfc, 0xd4, 0xce, + 0xe7, 0xab, 0x47, 0x2a, 0x12, 0x95, 0x93, 0x9d, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x91, 0x31, 0xbb, 0x60, 0x01, 0xaa, 0xd0, 0x7c, 0x9c, 0x94, 0x70, 0x76, + 0x61, 0x4c, 0x03, 0x4e, 0xb9, 0x01, 0xb4, 0x4d, 0x3a, 0x90, 0x96, 0x6e, + 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, 0xac, 0x42, 0x9b, 0x8e, + 0x45, 0x56, 0x71, 0x5e, 0x83, 0x9c, 0x9b, 0x93, 0x30, 0xaa, 0xde, 0xaf, + 0x52, 0x78, 0x54, 0x56, 0xf4, 0x9c, 0x43, 0xb7, 0x7b, 0xcf, 0xbd, 0x8f, + 0x09, 0x43, 0xec, 0x21, 0xb0, 0x42, 0x50, 0x1b, 0x8c, 0xcc, 0x70, 0xf8, + 0xb1, 0x77, 0xd4, 0xa6, 0xfb, 0x3b, 0x07, 0x54, 0x6c, 0x2a, 0x26, 0x91, + 0x78, 0x62, 0x4d, 0xdc, 0xff, 0xa9, 0xc1, 0x22, 0xb7, 0x55, 0x1f, 0x17, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x00, 0xc0, 0x8a, 0x2f, + 0x82, 0xda, 0x05, 0x96, 0x7e, 0x40, 0x9e, 0xef, 0x9e, 0xdb, 0x4c, 0x0c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6c, 0xf7, 0xd1, 0x5d, 0x68, 0x20, 0x7d, 0xae, + 0x15, 0xa4, 0xc2, 0x6e, 0xe0, 0xef, 0xd0, 0x9d, 0x17, 0xad, 0x9a, 0x67, + 0xf8, 0x6a, 0x73, 0x93, 0x54, 0xb3, 0x27, 0xb4, 0x28, 0xa5, 0xb6, 0x26, + 0xa1, 0x70, 0x1f, 0xb9, 0xbe, 0x2f, 0xfb, 0xbb, 0x95, 0x14, 0x03, 0xbc, + 0x85, 0x0d, 0xfd, 0xee, 0x22, 0x2c, 0x74, 0xfc, 0x12, 0xc6, 0x38, 0x24, + 0x07, 0xcb, 0xbf, 0x90, 0x46, 0x29, 0x9f, 0x28, 0xa5, 0xaa, 0xd3, 0xbc, + 0x44, 0x5b, 0x7f, 0x6d, 0x52, 0xcc, 0x7f, 0x27, 0x35, 0xad, 0x1d, 0x6d, + 0xad, 0x60, 0xeb, 0xb8, 0x7f, 0x88, 0x2d, 0xf7, 0xc6, 0x08, 0x2b, 0x0d, + 0x8c, 0xa8, 0x9d, 0x09, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x00, 0xd0, 0x69, 0x1e, 0xe4, 0x15, 0x78, 0x19, 0x0a, 0xda, 0x1f, 0xdf, + 0xc2, 0x56, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x8b, 0x46, 0xd9, + 0x98, 0x32, 0xdf, 0x73, 0xba, 0x06, 0x2c, 0x7a, 0xfc, 0x0f, 0x2b, 0xd6, + 0x8b, 0x56, 0xcd, 0x33, 0x7c, 0xb5, 0xb9, 0x49, 0xaa, 0xd9, 0x13, 0x5a, + 0x94, 0x52, 0x5b, 0x13, 0x9f, 0x5e, 0x41, 0x17, 0xfd, 0x0d, 0x49, 0xc0, + 0x87, 0x9f, 0xe1, 0x52, 0x84, 0x0c, 0x7b, 0x05, 0x73, 0x1a, 0x87, 0xac, + 0xde, 0x9d, 0x63, 0x3a, 0x0b, 0x5c, 0x6c, 0x17, 0xd1, 0x5b, 0xdf, 0x11, + 0x93, 0x3c, 0x93, 0x6a, 0x8b, 0x2c, 0x76, 0x69, 0x60, 0xba, 0xb9, 0x77, + 0xc1, 0x46, 0xd5, 0x86, 0x7d, 0xcc, 0x91, 0x2f, 0xb1, 0x77, 0x12, 0x0a, + 0xb2, 0x8c, 0xa6, 0xf0, 0xf7, 0xf8, 0x64, 0x26, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x00, 0x30, 0x32, 0x71, 0x23, 0x2e, 0xdd, 0x8b, + 0xf5, 0xda, 0xc1, 0xf5, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xdb, 0x9d, 0xf0, 0xbc, 0xa6, 0x4f, 0xe9, 0x7e, 0x30, 0xff, 0xe4, 0x9a, + 0xeb, 0xdc, 0x19, 0xeb, 0x45, 0xab, 0xe6, 0x19, 0xbe, 0xda, 0xdc, 0x24, + 0xd5, 0xec, 0x09, 0x2d, 0x4a, 0xa9, 0xad, 0x09, 0x39, 0xc4, 0x7e, 0x56, + 0x9a, 0x90, 0x44, 0x69, 0x15, 0x32, 0x2e, 0x45, 0xb4, 0xcd, 0x9f, 0x05, + 0xd4, 0xb6, 0x6c, 0x61, 0x39, 0x52, 0x90, 0x82, 0x4e, 0x7e, 0x25, 0xe8, + 0xf3, 0x46, 0xcb, 0x29, 0x70, 0x4e, 0xbf, 0xa9, 0xbc, 0x9c, 0xe3, 0x6c, + 0x3d, 0x12, 0x84, 0x17, 0x9a, 0x98, 0x54, 0x07, 0x9c, 0x7c, 0x0d, 0x95, + 0xc7, 0x18, 0x35, 0x2e, 0x2a, 0xaa, 0x68, 0x5b, 0xcc, 0x5f, 0x5e, 0x12, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x00, 0xa4, 0xd8, 0x1d, + 0xa2, 0x5e, 0xa7, 0x37, 0x70, 0xad, 0xd1, 0x9c, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x41, 0x78, 0xa3, 0xe1, 0x13, 0x6b, 0xb3, + 0xc9, 0xc2, 0x6f, 0x25, 0x54, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x67, 0x6c, 0x95, 0x25, 0x10, 0x0f, 0xf6, 0x13, 0x4a, 0xe9, 0xcd, 0xc0, + 0xbf, 0x3b, 0x0d, 0x8e, 0xaa, 0x71, 0x7b, 0x4a, 0x28, 0x10, 0x67, 0xe6, + 0x60, 0x4c, 0xf7, 0x44, 0x34, 0x52, 0x20, 0x24, 0x58, 0x55, 0x51, 0xde, + 0xc8, 0xba, 0xbe, 0x08, 0x59, 0xea, 0x56, 0x7c, 0xa7, 0x46, 0xa9, 0x7f, + 0x1b, 0x5f, 0x8c, 0x4f, 0xb4, 0x5c, 0xd8, 0x4c, 0x22, 0xb3, 0xf1, 0x32, + 0xad, 0x73, 0xd8, 0x0d, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x00, 0xac, 0x7f, 0x7a, 0x7f, 0xcc, 0x6b, 0x89, 0xc3, 0x0c, 0x8f, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xcd, 0xdd, 0x30, + 0x33, 0x58, 0x3c, 0x66, 0x14, 0xf4, 0xb4, 0x51, 0x74, 0x88, 0x67, 0xac, + 0x17, 0xad, 0x9a, 0x67, 0xf8, 0x6a, 0x73, 0x93, 0x54, 0xb3, 0x27, 0xb4, + 0x28, 0xa5, 0xb6, 0x26, 0xb6, 0xff, 0x36, 0x7a, 0xf9, 0xdf, 0x24, 0x7b, + 0x39, 0x3e, 0x97, 0x60, 0x67, 0x3f, 0x09, 0x5d, 0x4f, 0x5c, 0x42, 0xae, + 0xa9, 0x29, 0xc7, 0xaf, 0xef, 0x75, 0x44, 0x9b, 0x77, 0x3b, 0x2c, 0x0e, + 0xb5, 0x2e, 0xfd, 0xe4, 0x11, 0x06, 0xb6, 0x32, 0xc5, 0x91, 0x6d, 0xea, + 0xd9, 0xeb, 0xbe, 0x71, 0x3c, 0xb8, 0xdc, 0x34, 0x0a, 0x26, 0x17, 0xd7, + 0x20, 0xdc, 0x89, 0x58, 0xc2, 0x7b, 0xdc, 0x0f, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x00, 0xc5, 0x1c, 0xd9, 0xfc, 0x35, 0x0a, 0xad, + 0x17, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb6, 0x57, 0x03, 0x0a, 0x60, 0x81, 0x8b, 0x6d, 0x70, 0x03, 0xc6, 0x29, + 0x3a, 0xc4, 0x33, 0xd6, 0x8b, 0x56, 0xcd, 0x33, 0x7c, 0xb5, 0xb9, 0x49, + 0xaa, 0xd9, 0x13, 0x5a, 0x94, 0x52, 0x5b, 0x13, 0x35, 0x4d, 0x48, 0x77, + 0x40, 0xce, 0xc5, 0xfa, 0x07, 0xa0, 0x04, 0x8c, 0x95, 0x2f, 0x7b, 0x2b, + 0x6f, 0xa4, 0x30, 0xc3, 0x0d, 0xb8, 0x60, 0x64, 0x5c, 0xfc, 0x57, 0x7f, + 0x4d, 0x80, 0xe5, 0x2a, 0x0d, 0x70, 0xdb, 0x65, 0x17, 0xc1, 0x42, 0xf8, + 0x60, 0xd5, 0x74, 0xf6, 0xc7, 0x69, 0xbc, 0x38, 0xb8, 0x62, 0x39, 0x77, + 0xe2, 0x8c, 0xd3, 0x6a, 0x49, 0xce, 0x79, 0x50, 0xc5, 0x9b, 0x86, 0x04, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0x00, 0x83, 0x86, 0xfc, + 0xaf, 0x41, 0xb9, 0x0e, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5b, 0x45, 0xe0, 0x99, 0x59, 0xe6, 0x81, 0x90, + 0x40, 0x8e, 0xe3, 0x14, 0x1d, 0xe2, 0x19, 0xeb, 0x45, 0xab, 0xe6, 0x19, + 0xbe, 0xda, 0xdc, 0x24, 0xd5, 0xec, 0x09, 0x2d, 0x4a, 0xa9, 0xad, 0x09, + 0x0d, 0xd9, 0xf6, 0xc4, 0xba, 0x8f, 0xa6, 0x06, 0x61, 0x81, 0xa0, 0x91, + 0x2a, 0xd2, 0xc9, 0xc4, 0x3a, 0xa8, 0xe5, 0x1f, 0xcf, 0xfd, 0xe1, 0xde, + 0x15, 0x42, 0x00, 0x40, 0x41, 0xd6, 0x7b, 0x2c, 0x87, 0x3b, 0x48, 0x42, + 0xb2, 0x14, 0x2c, 0xf4, 0xd5, 0xbc, 0xaa, 0x3f, 0xbf, 0xf2, 0xd1, 0xa5, + 0xbd, 0x8d, 0xf1, 0xb3, 0xd7, 0x16, 0x04, 0x2c, 0x0b, 0x07, 0x53, 0x24, + 0xce, 0x09, 0x1c, 0x14, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x40, 0x0c, 0xab, 0x80, 0x53, 0x26, 0xc2, 0x54, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x36, 0xd3, 0xfe, + 0xaa, 0x2c, 0x8d, 0xbf, 0xba, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, + 0xd1, 0x01, 0xb4, 0x4d, 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, + 0xde, 0xfb, 0x08, 0x1d, 0xc4, 0x9c, 0x3a, 0x28, 0x22, 0x66, 0x09, 0x0f, + 0xae, 0x59, 0x20, 0x58, 0xbe, 0x2c, 0x40, 0x2e, 0x3c, 0x17, 0xeb, 0x5b, + 0x15, 0x7b, 0x16, 0x73, 0x80, 0xe3, 0xf3, 0x96, 0xc6, 0xb3, 0x82, 0x09, + 0xe9, 0x99, 0x10, 0xf0, 0x34, 0x2c, 0x13, 0xce, 0x1e, 0x2c, 0xf7, 0x85, + 0xe4, 0x99, 0x1a, 0x79, 0x03, 0x3f, 0x5b, 0xfd, 0xdf, 0x84, 0x8c, 0x92, + 0x8f, 0x67, 0xc5, 0x8b, 0x55, 0x2b, 0xe3, 0x20, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0xc0, 0xfa, 0x49, 0xea, 0x2a, 0x92, 0x32, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcc, 0x01, 0x57, 0x0b, 0x4f, 0x0f, 0xde, 0x2f, 0xa4, 0x3b, 0x8e, 0x53, + 0x74, 0x88, 0x67, 0xac, 0x17, 0xad, 0x9a, 0x67, 0xf8, 0x6a, 0x73, 0x93, + 0x54, 0xb3, 0x27, 0xb4, 0x28, 0xa5, 0xb6, 0x26, 0xa2, 0xd2, 0x52, 0xb0, + 0x3a, 0xa6, 0x9c, 0xe4, 0xb2, 0x50, 0xfe, 0x21, 0xb8, 0x2d, 0xe6, 0x17, + 0xf3, 0xec, 0x03, 0x6f, 0x45, 0xf4, 0x66, 0x76, 0x24, 0x94, 0x7c, 0x7c, + 0xec, 0xf3, 0xdd, 0x1f, 0xcd, 0x47, 0x47, 0x39, 0x94, 0x24, 0xc3, 0x38, + 0x5f, 0xcc, 0x6e, 0xf3, 0x89, 0x15, 0x54, 0xed, 0xe3, 0x70, 0xcb, 0xbc, + 0x00, 0xb4, 0x6e, 0xf9, 0xef, 0x9c, 0x3f, 0x48, 0x6a, 0xa7, 0xdb, 0x2f, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0xd0, 0xb2, 0x9d, 0x4f, + 0x2c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x76, 0xb5, 0x0b, 0xc8, 0x0c, 0xe1, 0x0c, 0x18, + 0xd2, 0x1d, 0xc7, 0x29, 0x3a, 0xc4, 0x33, 0xd6, 0x8b, 0x56, 0xcd, 0x33, + 0x7c, 0xb5, 0xb9, 0x49, 0xaa, 0xd9, 0x13, 0x5a, 0x94, 0x52, 0x5b, 0x13, + 0xb4, 0x3e, 0xb4, 0x19, 0xb5, 0x1f, 0x82, 0x51, 0x53, 0x4d, 0xee, 0xed, + 0x6c, 0xf1, 0x5d, 0x62, 0xdb, 0x10, 0x59, 0xb7, 0x60, 0x9a, 0xcc, 0x6f, + 0x73, 0xbb, 0xdb, 0x6e, 0x7b, 0xc1, 0x23, 0x29, 0x66, 0x10, 0x85, 0xb8, + 0xf2, 0x73, 0x9b, 0x81, 0x4c, 0xf2, 0x8d, 0xdd, 0x44, 0xe8, 0x57, 0xea, + 0xbc, 0xc8, 0x76, 0x21, 0x59, 0xdb, 0x06, 0x36, 0x63, 0x24, 0x1a, 0x3d, + 0x44, 0xff, 0x0c, 0x2d, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0x30, 0xc2, 0xb2, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x86, 0x1b, 0x9e, + 0x55, 0x82, 0x06, 0x0c, 0xe9, 0x8e, 0xe3, 0x14, 0x1d, 0xe2, 0x19, 0xeb, + 0x45, 0xab, 0xe6, 0x19, 0xbe, 0xda, 0xdc, 0x24, 0xd5, 0xec, 0x09, 0x2d, + 0x4a, 0xa9, 0xad, 0x09, 0xd1, 0x2d, 0x93, 0x12, 0x11, 0xb6, 0x70, 0x17, + 0x8c, 0xa1, 0x3a, 0x18, 0x86, 0x1e, 0xae, 0x60, 0x01, 0x07, 0xe9, 0x37, + 0x8b, 0x52, 0xb8, 0x3f, 0xca, 0xda, 0x63, 0xa6, 0x1b, 0xd2, 0x53, 0x19, + 0x38, 0x4d, 0xc9, 0x31, 0x5f, 0x7b, 0x29, 0x91, 0x11, 0xc6, 0x5a, 0x11, + 0xa0, 0x48, 0x29, 0xd9, 0x86, 0x71, 0x92, 0x35, 0x7a, 0x08, 0x5a, 0x27, + 0xd7, 0x03, 0xa1, 0xf2, 0xc9, 0x66, 0x85, 0x03, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0xe4, 0xc5, 0xbd, 0x0a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x21, 0xb8, 0x8d, 0xdb, 0x40, 0x87, 0x13, 0x24, 0xbb, 0xac, 0xaa, 0x3e, + 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, 0x3a, 0x90, 0x96, 0x6e, + 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, 0x62, 0xb3, 0x45, 0x42, + 0xf4, 0x20, 0x4e, 0x15, 0x0f, 0x65, 0x17, 0xfa, 0xac, 0x6a, 0x21, 0xad, + 0xd5, 0xdf, 0x4e, 0xe8, 0x07, 0xd8, 0x49, 0x5d, 0x00, 0xe3, 0x01, 0x59, + 0xc7, 0x82, 0xf1, 0x2c, 0x32, 0x73, 0x57, 0x92, 0xe9, 0x6f, 0x12, 0x46, + 0x21, 0x3f, 0x27, 0xbe, 0xd2, 0xbf, 0x50, 0xe8, 0x3e, 0xc3, 0x7b, 0x69, + 0xaf, 0xaf, 0x45, 0xb4, 0xe0, 0xdc, 0x6b, 0x46, 0x65, 0x05, 0x9b, 0x14, + 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, + 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, + 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, 0xac, 0x68, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x5c, 0xe0, 0xab, 0x09, 0x1a, 0x30, + 0xa4, 0x3b, 0x8e, 0x53, 0x74, 0x88, 0x67, 0xac, 0x17, 0xad, 0x9a, 0x67, + 0xf8, 0x6a, 0x73, 0x93, 0x54, 0xb3, 0x27, 0xb4, 0x28, 0xa5, 0xb6, 0x26, + 0x89, 0x73, 0xad, 0x6f, 0x45, 0x3b, 0x05, 0x6a, 0xd4, 0x58, 0x07, 0x72, + 0x03, 0x99, 0x54, 0x97, 0x7c, 0xa4, 0x07, 0xdc, 0xc5, 0xcf, 0x9c, 0x46, + 0x61, 0x3f, 0xeb, 0x14, 0x89, 0xee, 0x79, 0x24, 0x3c, 0x4f, 0xdf, 0x1b, + 0x68, 0x49, 0x3f, 0x2b, 0xee, 0xde, 0x8e, 0xee, 0x89, 0xf3, 0x8f, 0xbe, + 0xd0, 0xf4, 0x96, 0xc9, 0xeb, 0xb0, 0x9d, 0x49, 0x3c, 0x45, 0xb0, 0xb7, + 0xa7, 0xff, 0xf6, 0x0c, 0x85, 0x53, 0x53, 0x90, 0x64, 0x5d, 0xc0, 0xd2, + 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, 0x93, 0xe5, 0x00, 0x01, + 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, 0xf7, 0xde, 0x42, 0x20, + 0xd5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xfa, 0x31, 0xf0, + 0xd5, 0x04, 0x0d, 0x18, 0xd2, 0x1d, 0xc7, 0x29, 0x3a, 0xc4, 0x33, 0xd6, + 0x8b, 0x56, 0xcd, 0x33, 0x7c, 0xb5, 0xb9, 0x49, 0xaa, 0xd9, 0x13, 0x5a, + 0x94, 0x52, 0x5b, 0x13, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xeb, 0x40, 0xf7, 0xc7, 0xa4, 0x6f, 0x93, 0xf9, 0x67, 0x94, 0x0f, 0x6b, + 0xa3, 0x18, 0x4f, 0x4d, 0x8c, 0x78, 0x4e, 0xfb, 0xab, 0x7f, 0x20, 0x0f, + 0x61, 0x18, 0x2e, 0xb5, 0x7b, 0xdf, 0xc5, 0x0a, 0x85, 0x53, 0x53, 0x90, + 0x64, 0x5d, 0xc0, 0xd2, 0x08, 0x87, 0xf6, 0x9a, 0x0b, 0x47, 0x56, 0xba, + 0x93, 0xe5, 0x00, 0x01, 0xcf, 0x83, 0x35, 0xd0, 0x1b, 0xc0, 0xcb, 0x40, + 0xf7, 0xde, 0x42, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0x7e, 0x57, 0x64, 0x76, 0xc8, 0x16, 0xaa, 0x2f, 0x74, 0x1c, 0xc9, + 0x65, 0x97, 0xda, 0xb6, 0x74, 0x57, 0xa7, 0x5a, 0x99, 0xfd, 0x04, 0x01, + 0xea, 0xbc, 0xa2, 0x9d, 0x83, 0xd0, 0xdf, 0x21, 0x52, 0x3f, 0x1f, 0xb6, + 0x05, 0x23, 0x08, 0x4f, 0xa3, 0x72, 0x1c, 0x5a, 0xa4, 0x5a, 0xe0, 0x65, + 0x17, 0x56, 0x60, 0xa0, 0x6d, 0x11, 0x14, 0x6e, 0x0a, 0x68, 0x4c, 0xb8, + 0x9c, 0x13, 0x19, 0x0c, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d + }; + unsigned char poseidon_constants_4[] = { + 0x51, 0xc5, 0xc0, 0xa5, 0xa2, 0x2d, 0xb2, 0x3b, 0x29, 0xfc, 0x61, 0x9b, + 0x16, 0x3e, 0x9d, 0xab, 0x79, 0xa3, 0xea, 0x87, 0xfc, 0x95, 0x76, 0x26, + 0x56, 0xc3, 0x9e, 0x46, 0xb0, 0x20, 0x7a, 0x16, 0x50, 0x5f, 0x2a, 0x87, + 0x5d, 0x9f, 0x80, 0xf0, 0x46, 0x35, 0x5d, 0xb4, 0xac, 0xbd, 0x7f, 0x74, + 0x5b, 0xa2, 0x70, 0x00, 0xb4, 0x89, 0x6e, 0x38, 0x7b, 0xe7, 0x97, 0x47, + 0x98, 0x8b, 0x34, 0x1f, 0xd0, 0xfd, 0x4b, 0x3e, 0x2d, 0x02, 0xac, 0x15, + 0xc9, 0x70, 0x1c, 0x54, 0x6f, 0xc4, 0xd7, 0x08, 0xf6, 0xe4, 0x89, 0x2f, + 0x7b, 0x77, 0xe3, 0xde, 0xd6, 0x7d, 0xdd, 0x73, 0x33, 0xa6, 0x60, 0x03, + 0x74, 0xf3, 0x25, 0x26, 0x8b, 0x50, 0x31, 0x56, 0x1f, 0x5a, 0xb6, 0xb6, + 0xe1, 0xc2, 0x6e, 0x1e, 0xba, 0xd7, 0x12, 0x84, 0x9e, 0x5c, 0xbc, 0x67, + 0xb5, 0xf1, 0xff, 0x8d, 0x96, 0x4c, 0x57, 0x02, 0xd0, 0xb1, 0x66, 0x4e, + 0x6b, 0xdc, 0x92, 0x9c, 0xfb, 0x29, 0xbc, 0xe5, 0xbc, 0xb9, 0xea, 0xef, + 0x7b, 0x94, 0xe5, 0x6f, 0x47, 0xb4, 0x46, 0x1e, 0xd5, 0x3d, 0xab, 0xe2, + 0xfc, 0xbd, 0xc1, 0x24, 0xa5, 0x67, 0x20, 0xa3, 0x16, 0x95, 0x31, 0xdf, + 0xf7, 0xbd, 0x7e, 0xd2, 0x33, 0xf3, 0xe5, 0x1e, 0xb4, 0x90, 0xc7, 0xa7, + 0x17, 0x75, 0xcb, 0x03, 0x78, 0x60, 0xa7, 0xf2, 0xcf, 0x40, 0x8a, 0x05, + 0x44, 0x0c, 0xd5, 0x98, 0x3c, 0x0f, 0x96, 0xb8, 0x2b, 0xc8, 0x05, 0xd4, + 0x2a, 0x9c, 0xf9, 0xc1, 0xae, 0x53, 0x6a, 0x36, 0x6e, 0x3c, 0xe2, 0xa7, + 0x6c, 0x25, 0x79, 0x6f, 0x88, 0xa9, 0x30, 0x07, 0x95, 0xaf, 0x27, 0x4f, + 0x2a, 0x3b, 0x8b, 0x0a, 0x60, 0x65, 0x35, 0xac, 0x74, 0x14, 0xfb, 0x07, + 0xdc, 0x53, 0x50, 0x74, 0x95, 0xdb, 0x2c, 0x0e, 0xb9, 0xf2, 0xf3, 0x89, + 0x59, 0x1b, 0x61, 0x0e, 0xfa, 0xbe, 0xe7, 0x7a, 0xfc, 0x29, 0xf0, 0xc5, + 0x46, 0x9f, 0x27, 0x67, 0xe3, 0xc0, 0x22, 0xdd, 0x70, 0x95, 0x8d, 0x04, + 0x1d, 0x61, 0xad, 0x16, 0x1e, 0xd6, 0xd6, 0x92, 0x7b, 0xf5, 0xd2, 0x15, + 0x6a, 0xeb, 0x08, 0xe7, 0xc8, 0x0b, 0x50, 0xb2, 0xb9, 0xcc, 0x6b, 0xf0, + 0xa3, 0x6a, 0x5c, 0xb7, 0x5a, 0x39, 0x92, 0xd1, 0x5e, 0xde, 0xe8, 0x40, + 0x75, 0xfa, 0xcf, 0xba, 0xe5, 0x41, 0x49, 0x11, 0xfd, 0x07, 0xf5, 0x3c, + 0xed, 0xf2, 0xd3, 0x03, 0xf4, 0xa1, 0x95, 0x88, 0x5e, 0xf4, 0x36, 0x03, + 0xbf, 0x1a, 0x22, 0xf4, 0x84, 0x88, 0xd9, 0xc5, 0xd2, 0xab, 0x60, 0xe5, + 0x78, 0xf2, 0x52, 0x1d, 0x7e, 0x40, 0x64, 0x5b, 0x16, 0x71, 0xf5, 0x01, + 0x76, 0x0f, 0x58, 0xaa, 0x79, 0x13, 0x8e, 0x3d, 0xce, 0x84, 0xa9, 0x2b, + 0x4b, 0x86, 0x13, 0x97, 0xd5, 0x30, 0xf1, 0xb0, 0x2f, 0x5e, 0x59, 0x2b, + 0x1c, 0x82, 0x8a, 0x58, 0x56, 0xe0, 0x53, 0x7d, 0x31, 0x02, 0x86, 0x81, + 0x94, 0x35, 0xe9, 0x2b, 0xdc, 0x8e, 0x5b, 0x3a, 0xdc, 0xd2, 0x56, 0x0b, + 0xa5, 0x86, 0x45, 0x3a, 0xd3, 0x40, 0x48, 0x2e, 0x9d, 0x98, 0x7d, 0x97, + 0x2b, 0xce, 0x87, 0xbc, 0x82, 0x2e, 0xab, 0x2c, 0x55, 0x5d, 0xac, 0xc2, + 0xb0, 0x39, 0xea, 0x71, 0xa3, 0x31, 0x6c, 0x15, 0x43, 0xfc, 0x30, 0x54, + 0x04, 0x8a, 0x3b, 0x25, 0x4b, 0x67, 0x62, 0x77, 0xc0, 0xd8, 0xed, 0xa7, + 0x9c, 0xc1, 0xaa, 0xad, 0x98, 0x8f, 0xc7, 0x54, 0x17, 0xf5, 0xd9, 0xcd, + 0x7d, 0xd9, 0x60, 0xd4, 0x68, 0x47, 0xb4, 0xa7, 0x1c, 0x49, 0x3b, 0x1b, + 0x7c, 0xc8, 0xe7, 0x44, 0xbe, 0x4b, 0x23, 0xee, 0xf8, 0xa3, 0xe3, 0xe5, + 0x5e, 0x53, 0x6f, 0xbf, 0xab, 0xc1, 0x3c, 0x12, 0xf8, 0x82, 0x25, 0xfd, + 0x40, 0xec, 0x5b, 0x69, 0x1a, 0x0e, 0x67, 0x0a, 0x3c, 0x2b, 0x9e, 0x45, + 0x3c, 0x03, 0xea, 0xc7, 0x77, 0xaf, 0xb9, 0x9f, 0x4a, 0xee, 0x5a, 0x3a, + 0xc4, 0x0c, 0x3c, 0x32, 0x00, 0x83, 0x64, 0x61, 0xdd, 0x9c, 0x44, 0xd9, + 0xaa, 0xf7, 0x02, 0x0b, 0x7b, 0xc7, 0x73, 0x63, 0xff, 0x90, 0x03, 0x9b, + 0x33, 0x01, 0x13, 0xda, 0xd7, 0x09, 0xc9, 0xde, 0xf4, 0xae, 0x5b, 0xa8, + 0x7f, 0x4a, 0x93, 0xe6, 0x66, 0x46, 0xbd, 0xd1, 0xd0, 0xc4, 0xfc, 0x2e, + 0xd0, 0x97, 0x9c, 0xed, 0x93, 0x2e, 0x36, 0x38, 0xf6, 0x1f, 0x42, 0x54, + 0xb7, 0x32, 0x0f, 0x16, 0xbe, 0xa8, 0x75, 0x39, 0xcb, 0xd8, 0xee, 0xac, + 0x84, 0x33, 0x95, 0x2c, 0xcd, 0xb5, 0xa0, 0x23, 0x3b, 0xc4, 0x7b, 0xcf, + 0x15, 0x8b, 0x00, 0x68, 0x73, 0x2f, 0x5c, 0xe7, 0x1f, 0x08, 0xd9, 0x77, + 0x85, 0x09, 0x1d, 0x42, 0x96, 0x9c, 0xbc, 0x93, 0xe9, 0x52, 0x89, 0xd8, + 0x05, 0x43, 0x28, 0x22, 0xaa, 0xd7, 0x8d, 0x91, 0x7e, 0x56, 0x1e, 0x42, + 0x81, 0xac, 0x26, 0x91, 0xf0, 0xd8, 0x92, 0x8a, 0xa1, 0x7b, 0x59, 0x0b, + 0xee, 0xa4, 0xb4, 0x9a, 0x87, 0xa8, 0xc5, 0x74, 0xf4, 0x36, 0x41, 0x22, + 0xe6, 0xcd, 0x86, 0xd1, 0x29, 0xdf, 0xee, 0xf2, 0xa3, 0x46, 0xab, 0xa3, + 0x88, 0x0d, 0xfa, 0x1b, 0x12, 0x4b, 0x91, 0x8b, 0xdb, 0x58, 0x35, 0xe4, + 0x4a, 0xd9, 0x7b, 0x43, 0x84, 0xe8, 0x19, 0x19, 0x12, 0x5d, 0x79, 0x0e, + 0xa6, 0x2b, 0xbb, 0xc5, 0x86, 0x13, 0xb3, 0x11, 0x5d, 0x5a, 0x32, 0x4e, + 0x1c, 0x70, 0xd9, 0xca, 0x53, 0xde, 0xab, 0xc2, 0x9f, 0x71, 0xfa, 0x6b, + 0x1f, 0xa5, 0x61, 0x19, 0x54, 0x39, 0x69, 0xd4, 0x51, 0x15, 0xe9, 0x05, + 0xfa, 0x84, 0x50, 0xee, 0xdc, 0xcb, 0x9c, 0xd6, 0xcb, 0x14, 0x6b, 0x17, + 0x91, 0xc4, 0xa3, 0x2e, 0x24, 0x84, 0x1f, 0xda, 0x34, 0x8f, 0x5b, 0x16, + 0x89, 0x2f, 0x58, 0xd9, 0x08, 0x6e, 0x89, 0x0a, 0x0d, 0x2f, 0x53, 0x19, + 0x3c, 0x39, 0x07, 0xb9, 0xbc, 0x2b, 0x2f, 0xba, 0x77, 0x83, 0x62, 0x61, + 0xbc, 0xc3, 0xb9, 0x83, 0x3b, 0x98, 0xda, 0x0c, 0x5d, 0x63, 0xa5, 0xad, + 0xdd, 0x77, 0xb5, 0x7b, 0xe2, 0xba, 0x81, 0x92, 0x1a, 0xc9, 0xec, 0x7e, + 0x3d, 0x17, 0xfa, 0x4e, 0xc4, 0x4a, 0x41, 0x9d, 0x5e, 0xad, 0x86, 0x5e, + 0x5a, 0x1e, 0xb2, 0x06, 0x36, 0xf3, 0xcd, 0x4f, 0x4e, 0xcd, 0xd0, 0x99, + 0xd1, 0x3e, 0x1a, 0x25, 0x5f, 0x8f, 0x93, 0x23, 0x12, 0x2d, 0xee, 0x80, + 0x3a, 0x56, 0xc9, 0xb7, 0x61, 0xea, 0x49, 0x13, 0xee, 0xc0, 0x56, 0x0d, + 0xde, 0x0b, 0x4d, 0x7c, 0x56, 0x46, 0xd6, 0xf3, 0x8d, 0x48, 0x3f, 0x36, + 0x2b, 0xdd, 0x3c, 0x6c, 0x4b, 0xe9, 0xae, 0x53, 0xb8, 0x29, 0xca, 0xb6, + 0x4a, 0x78, 0x7a, 0xf7, 0xbb, 0x0a, 0x2e, 0x0e, 0x0b, 0x7f, 0x01, 0xbe, + 0x15, 0xbe, 0x87, 0x0b, 0xad, 0x63, 0xc0, 0x53, 0x57, 0xe7, 0x4b, 0x0f, + 0xc0, 0x5a, 0xb1, 0x40, 0x4d, 0xd2, 0x5f, 0x5a, 0x93, 0xf5, 0x38, 0x57, + 0xa9, 0xbb, 0x87, 0x2b, 0x24, 0x29, 0xa4, 0x63, 0xee, 0x16, 0x6e, 0xcf, + 0x41, 0x4c, 0x57, 0xe5, 0x3a, 0x5b, 0x49, 0x4c, 0xca, 0x6b, 0x37, 0x97, + 0xb5, 0x90, 0x64, 0x3f, 0x6c, 0xf7, 0x23, 0x94, 0x54, 0x15, 0x71, 0x1c, + 0x62, 0xaf, 0x04, 0x0a, 0x9d, 0x0f, 0xfd, 0x35, 0xf2, 0xfa, 0x44, 0x7e, + 0xa4, 0x01, 0x2d, 0xd3, 0xf9, 0xe0, 0x98, 0x36, 0x6e, 0x29, 0xd0, 0x7e, + 0x07, 0xe0, 0xaf, 0xe1, 0x98, 0x19, 0xa7, 0x26, 0x0b, 0x16, 0x59, 0x42, + 0xd5, 0x65, 0x5b, 0x17, 0xd4, 0x83, 0xb5, 0x02, 0x66, 0xe8, 0x5c, 0x9d, + 0x8e, 0x66, 0x1e, 0x5c, 0x91, 0xf9, 0xf6, 0xd0, 0x8b, 0x94, 0x2a, 0x73, + 0x5c, 0x9b, 0x9c, 0x23, 0xe1, 0x92, 0x19, 0xe4, 0x19, 0xc1, 0xa4, 0x06, + 0x88, 0x13, 0xc2, 0xc0, 0xd9, 0x59, 0x9b, 0xa1, 0xe4, 0xd1, 0xb6, 0xf8, + 0x3d, 0x4d, 0xc0, 0x26, 0x05, 0xa9, 0xc1, 0x95, 0x08, 0x4a, 0x28, 0x27, + 0xff, 0xf3, 0x39, 0xed, 0x08, 0x98, 0x6d, 0xc7, 0xfe, 0x92, 0x23, 0x2b, + 0xa8, 0x85, 0x4e, 0x20, 0xab, 0x83, 0x61, 0x2e, 0x01, 0x41, 0xb1, 0xd2, + 0xe2, 0x58, 0x9b, 0xe7, 0x29, 0xd1, 0xf4, 0x15, 0x74, 0x94, 0x55, 0x78, + 0xc4, 0xd1, 0xad, 0x9b, 0xd9, 0xa6, 0x8d, 0x85, 0x74, 0xf6, 0x46, 0x56, + 0x57, 0x62, 0x3c, 0xe6, 0xb4, 0xc4, 0x8c, 0x49, 0x6d, 0x0a, 0x1c, 0xdc, + 0xce, 0x2e, 0xff, 0x19, 0x62, 0xc6, 0x4c, 0xc9, 0x7c, 0x36, 0xea, 0x10, + 0x78, 0xd1, 0x6b, 0xb8, 0xb0, 0x01, 0xe3, 0xe3, 0xee, 0x2a, 0x6f, 0x3b, + 0xdc, 0xcc, 0x92, 0xa1, 0x65, 0x6f, 0xd1, 0x53, 0xe8, 0xb3, 0xf3, 0x08, + 0x07, 0xb5, 0x55, 0x9d, 0x15, 0xd8, 0x65, 0x2e, 0xe5, 0x13, 0xd2, 0x88, + 0x78, 0x07, 0x7f, 0x79, 0xb2, 0x4d, 0x63, 0xce, 0x0d, 0x84, 0x53, 0xf5, + 0xe0, 0xfa, 0xee, 0x52, 0x7a, 0xfd, 0x0f, 0x27, 0x74, 0x7e, 0xff, 0x78, + 0x19, 0x41, 0x8b, 0xc5, 0x96, 0xde, 0x20, 0x27, 0xed, 0xe9, 0xe8, 0x15, + 0x77, 0xf9, 0x43, 0x76, 0x03, 0xe2, 0xab, 0xb4, 0x4c, 0x5a, 0x7d, 0x01, + 0x4e, 0xb6, 0x2b, 0x27, 0xd5, 0x24, 0x0d, 0x9a, 0xb4, 0x15, 0x4c, 0xcd, + 0x38, 0x1f, 0x4e, 0xc5, 0x28, 0xf7, 0xeb, 0x01, 0x6b, 0xce, 0xea, 0x21, + 0xb0, 0xfd, 0xce, 0x3d, 0xf9, 0x7d, 0x2c, 0x37, 0x24, 0x0a, 0x8c, 0x04, + 0x03, 0x21, 0x90, 0x61, 0x02, 0xba, 0xa7, 0x35, 0x26, 0x4d, 0xb8, 0xf6, + 0x85, 0x7d, 0x17, 0xe5, 0x66, 0x1a, 0xe5, 0x07, 0xd4, 0xd3, 0xd4, 0x41, + 0xfa, 0xb7, 0xa8, 0x0b, 0xef, 0x94, 0x72, 0x0d, 0x64, 0xd7, 0xd4, 0xb0, + 0x23, 0xf9, 0x29, 0x94, 0xd5, 0xf0, 0xda, 0x51, 0x79, 0x49, 0xd7, 0x23, + 0x7e, 0x27, 0x46, 0x8f, 0x09, 0xce, 0x66, 0x4d, 0xbe, 0x23, 0xef, 0x4d, + 0xf2, 0x3d, 0xfb, 0x0b, 0x6c, 0x44, 0x7f, 0x90, 0x51, 0xc1, 0x3d, 0x84, + 0xbe, 0x7e, 0xc1, 0xa0, 0x5c, 0x76, 0xbc, 0x20, 0x66, 0xbe, 0x69, 0xa7, + 0x39, 0xa6, 0xd8, 0xe2, 0x74, 0xf9, 0x4b, 0x35, 0x9c, 0xea, 0x65, 0x25, + 0xbd, 0xf5, 0x0a, 0xaa, 0x58, 0xfa, 0x0f, 0x1d, 0x06, 0x2e, 0x38, 0x10, + 0xff, 0x6a, 0xcf, 0xeb, 0xd8, 0xec, 0xc6, 0x7a, 0xc9, 0x12, 0xc6, 0xba, + 0x5c, 0x14, 0x84, 0x45, 0xe3, 0x50, 0x86, 0x03, 0xaf, 0xff, 0x53, 0xda, + 0x2e, 0x79, 0x6d, 0x87, 0x7b, 0x45, 0x94, 0x7e, 0x10, 0x1f, 0xa8, 0x8e, + 0x5e, 0xf6, 0x8d, 0xab, 0xcc, 0xf6, 0xb4, 0xcd, 0xd2, 0x9d, 0x19, 0x3c, + 0x12, 0x4a, 0x47, 0x0f, 0x57, 0x23, 0x17, 0x14, 0xd4, 0xef, 0xe2, 0x97, + 0x94, 0xa1, 0xb4, 0x0d, 0x5f, 0x42, 0x52, 0x3b, 0x3a, 0x94, 0x10, 0xbc, + 0xc8, 0xa9, 0xc9, 0x24, 0xc8, 0xbe, 0x89, 0xab, 0x82, 0xec, 0x96, 0x18, + 0xfc, 0x17, 0xff, 0x43, 0x7a, 0x39, 0xb4, 0x1c, 0x25, 0xb7, 0xd8, 0x30, + 0xdd, 0x08, 0xc9, 0xc6, 0xa7, 0x21, 0x1f, 0x9d, 0x07, 0xd2, 0x43, 0x6e, + 0x42, 0xa4, 0x56, 0x01, 0x63, 0x24, 0x60, 0x16, 0xb4, 0x15, 0xda, 0xf6, + 0x0d, 0x6f, 0x5c, 0x8d, 0x23, 0x42, 0x85, 0xd9, 0x79, 0xc8, 0x8a, 0xb3, + 0x5a, 0x21, 0xc8, 0x07, 0x82, 0xfc, 0xef, 0x1b, 0xbb, 0x79, 0x81, 0x7f, + 0x69, 0xd7, 0xbf, 0x22, 0xba, 0x5c, 0xfe, 0x09, 0xc6, 0x96, 0x62, 0x4d, + 0xcc, 0x3e, 0x19, 0xc4, 0x64, 0xa6, 0xa5, 0xa6, 0x6a, 0x35, 0xd3, 0xf4, + 0x33, 0x4f, 0x0e, 0x7c, 0x85, 0x36, 0xee, 0x62, 0x37, 0x47, 0x50, 0x0d, + 0xfd, 0xe9, 0x57, 0x19, 0xb6, 0x51, 0xa7, 0xa1, 0x89, 0x8b, 0x25, 0x2b, + 0x74, 0x19, 0x50, 0x77, 0xfd, 0x1f, 0xe1, 0xd9, 0xd2, 0x98, 0x85, 0x61, + 0x1e, 0x24, 0x95, 0x49, 0x9e, 0xdc, 0x18, 0x26, 0xf6, 0x6b, 0xf2, 0x5c, + 0x67, 0xbd, 0x99, 0x71, 0x22, 0x37, 0xb4, 0x19, 0xf7, 0xa1, 0x06, 0x70, + 0x36, 0xc7, 0x00, 0x9a, 0xdb, 0xdf, 0x0e, 0x7f, 0xb4, 0x3d, 0x95, 0xe7, + 0xdf, 0xfd, 0x95, 0x0d, 0x27, 0x38, 0x3d, 0x17, 0x94, 0x33, 0x66, 0x07, + 0x9f, 0xaa, 0x6f, 0xf3, 0x50, 0x4e, 0x45, 0xc2, 0xac, 0xa3, 0xb9, 0x98, + 0xa4, 0x2c, 0xb9, 0x50, 0xa3, 0xd9, 0x41, 0x77, 0xa3, 0xb0, 0x58, 0x0b, + 0xd9, 0x63, 0x1d, 0xd9, 0x07, 0x99, 0xf7, 0x36, 0x87, 0x73, 0x6f, 0x14, + 0x18, 0xe9, 0x31, 0x08, 0xae, 0x93, 0xb6, 0xdb, 0x64, 0xe1, 0x04, 0x5b, + 0x70, 0x08, 0x34, 0xbd, 0x19, 0x96, 0x02, 0x22, 0xf3, 0x9b, 0x5c, 0x03, + 0xaf, 0x3f, 0x3d, 0xaf, 0x9f, 0x6d, 0x43, 0xcc, 0xec, 0x40, 0x3a, 0x48, + 0x91, 0x18, 0x5b, 0x8d, 0x65, 0x8c, 0xfb, 0x38, 0xe1, 0x51, 0xcb, 0x68, + 0x23, 0xa2, 0x6e, 0x00, 0xd9, 0xec, 0x72, 0xf6, 0x2d, 0x31, 0x5c, 0xa2, + 0x8b, 0xa1, 0xe7, 0x03, 0x3a, 0xd8, 0xaf, 0x77, 0x5a, 0xf3, 0xa3, 0xef, + 0x44, 0x2d, 0xb1, 0xf4, 0x2d, 0xc6, 0xfb, 0xd4, 0x97, 0x7f, 0x25, 0x2b, + 0x29, 0xa8, 0x1d, 0x4e, 0x66, 0x69, 0xdf, 0x3c, 0x4c, 0xd2, 0x83, 0x3e, + 0xba, 0xe2, 0x14, 0x8b, 0xbb, 0xfa, 0x2b, 0x8a, 0x3f, 0xde, 0xa6, 0x8b, + 0x4f, 0x2e, 0x77, 0x70, 0x94, 0x98, 0x81, 0x02, 0xd3, 0x38, 0x9c, 0x23, + 0x9a, 0x9f, 0x2c, 0x30, 0x43, 0x62, 0xb7, 0x0f, 0x11, 0x65, 0xc4, 0x17, + 0x4e, 0x17, 0x73, 0xf6, 0xe3, 0x5f, 0x5f, 0x6a, 0x01, 0x42, 0x73, 0x35, + 0x92, 0xd4, 0x44, 0x17, 0xba, 0xfb, 0xf2, 0x83, 0x68, 0x3f, 0xd3, 0x28, + 0xab, 0x26, 0x6f, 0x42, 0x74, 0x77, 0xb9, 0x69, 0x78, 0xe4, 0x1f, 0x39, + 0xdc, 0x06, 0x13, 0xdc, 0xed, 0xa0, 0x12, 0x98, 0x43, 0x2c, 0x67, 0x2c, + 0x91, 0xa1, 0x66, 0x38, 0x59, 0x62, 0x55, 0xa3, 0xdd, 0x60, 0x34, 0x72, + 0xc2, 0x80, 0xa7, 0x1e, 0x7f, 0x11, 0xf0, 0xed, 0x4b, 0xf6, 0xae, 0xfb, + 0x53, 0x51, 0xdd, 0x51, 0x09, 0x68, 0x7f, 0x1a, 0x23, 0xbf, 0x82, 0xd9, + 0x36, 0xf8, 0x8f, 0x4a, 0xd8, 0x13, 0x40, 0x4f, 0x0b, 0x4d, 0x05, 0x50, + 0x5e, 0xb4, 0x9b, 0x01, 0x84, 0x29, 0x73, 0xd5, 0x2b, 0x5e, 0xb9, 0x8d, + 0xe5, 0xc6, 0x2f, 0x28, 0x9f, 0xeb, 0x43, 0xff, 0x29, 0x40, 0x0d, 0x57, + 0x2c, 0xff, 0xe8, 0x3f, 0xa5, 0x54, 0xbe, 0x98, 0x54, 0x0e, 0xb3, 0x0c, + 0x71, 0x3b, 0xe8, 0x69, 0x93, 0x2a, 0xae, 0x68, 0xf2, 0x9b, 0x06, 0x09, + 0x93, 0xae, 0x31, 0x71, 0xad, 0xa4, 0xb3, 0x3e, 0x66, 0x79, 0x69, 0x33, + 0xda, 0x32, 0x60, 0xd8, 0x3b, 0x7e, 0x4c, 0x38, 0xf1, 0x77, 0x23, 0xa0, + 0x94, 0x75, 0x85, 0xf5, 0x79, 0x9f, 0x39, 0x12, 0x7f, 0xe6, 0x49, 0xbb, + 0x3b, 0xf0, 0x25, 0x16, 0x3a, 0x52, 0xa6, 0xb8, 0x58, 0x54, 0x1a, 0x0b, + 0x16, 0x58, 0xd6, 0x50, 0x40, 0xd4, 0xc8, 0xa6, 0xd9, 0x42, 0x84, 0xbf, + 0x73, 0x32, 0x4d, 0x0e, 0x55, 0x2c, 0xcb, 0x4a, 0xa7, 0x2c, 0xdf, 0xf8, + 0x2f, 0x2b, 0x80, 0x1c, 0x63, 0x3b, 0xd5, 0x42, 0xf4, 0xb1, 0xac, 0xef, + 0x32, 0xf1, 0xf6, 0x4b, 0x9b, 0xd0, 0x26, 0x45, 0x0f, 0xb7, 0x9b, 0x28, + 0x0d, 0x86, 0x69, 0x38, 0xf3, 0xd6, 0xca, 0xc8, 0xb9, 0x9a, 0xef, 0x5a, + 0xc1, 0xd3, 0x89, 0xd4, 0x50, 0xd8, 0xd6, 0x38, 0x8d, 0x32, 0xd1, 0x66, + 0x80, 0xcb, 0x2a, 0xb5, 0x1c, 0x2d, 0x23, 0x0f, 0xd8, 0x0b, 0x2d, 0x14, + 0xa5, 0x18, 0xfe, 0x25, 0x69, 0xb9, 0xe6, 0x66, 0x4e, 0x3d, 0xde, 0x33, + 0x0a, 0xd6, 0xdb, 0xcc, 0xad, 0x7b, 0xda, 0xc6, 0xbe, 0xb3, 0x42, 0xc3, + 0xa8, 0xb0, 0x9f, 0x08, 0x4c, 0x74, 0x63, 0x3e, 0x80, 0x69, 0x0d, 0x34, + 0x52, 0x16, 0x37, 0x87, 0x8d, 0x81, 0x24, 0x98, 0xd1, 0x38, 0x0d, 0x1f, + 0x97, 0xbf, 0x76, 0xb1, 0xb8, 0xef, 0x77, 0x4f, 0xda, 0x07, 0x2f, 0x11, + 0xec, 0x6a, 0x3d, 0x68, 0x57, 0xef, 0x62, 0x58, 0xbd, 0x40, 0x95, 0x52, + 0x4a, 0x24, 0xf1, 0x2c, 0xc2, 0xcb, 0xd6, 0x04, 0xf5, 0x69, 0xb4, 0x82, + 0xbd, 0x75, 0x11, 0xb7, 0xdf, 0x32, 0x34, 0x0e, 0xa3, 0xa7, 0xbd, 0xa1, + 0x9a, 0x58, 0xc5, 0xc1, 0xbc, 0x05, 0xa0, 0x4c, 0xc1, 0x41, 0x2a, 0xbf, + 0xe1, 0x4c, 0x78, 0xde, 0xbd, 0x73, 0xc1, 0x7e, 0x29, 0x75, 0xcd, 0xd2, + 0xe1, 0x09, 0x6e, 0x2a, 0x0c, 0x98, 0x1e, 0x76, 0x8b, 0x19, 0xd7, 0xab, + 0x1f, 0x27, 0x65, 0x33, 0x6a, 0x55, 0x56, 0xe3, 0xec, 0x5b, 0x93, 0x33, + 0x5a, 0xbf, 0xf0, 0xf3, 0x79, 0x84, 0x9c, 0x6d, 0xd6, 0x17, 0x7d, 0x00, + 0x2b, 0x47, 0x68, 0xd4, 0x9c, 0x8d, 0x3a, 0x4d, 0x12, 0x19, 0x97, 0x07, + 0x40, 0x59, 0x39, 0x86, 0xb3, 0x46, 0xcf, 0xad, 0x7a, 0x3b, 0x80, 0x2d, + 0xd6, 0xf4, 0x5e, 0x18, 0x20, 0x11, 0x16, 0x19, 0x5e, 0xc1, 0x34, 0xde, + 0x2a, 0xde, 0x39, 0x5e, 0x33, 0x99, 0xbf, 0xe5, 0xa6, 0xb7, 0x0a, 0xaf, + 0x98, 0x7e, 0x7d, 0x04, 0x2f, 0x81, 0xa9, 0x25, 0xae, 0x7d, 0x40, 0xd5, + 0xcd, 0x72, 0x1c, 0x21, 0x32, 0x8a, 0x5a, 0xfb, 0x02, 0x92, 0x28, 0xeb, + 0xf2, 0x5c, 0x81, 0x58, 0x0c, 0x53, 0x9a, 0x25, 0xce, 0x8c, 0x9b, 0x50, + 0x8e, 0x49, 0x28, 0x4b, 0x8d, 0xe3, 0x4a, 0xfa, 0xf2, 0x84, 0xf4, 0x1a, + 0xc8, 0xb5, 0x17, 0x8e, 0x6e, 0x45, 0xc0, 0x11, 0xd6, 0xcc, 0x34, 0x19, + 0xb1, 0xee, 0xc5, 0xc8, 0x9e, 0x0d, 0x38, 0xcb, 0x24, 0xf4, 0x8b, 0x1b, + 0x44, 0x22, 0x1c, 0xb6, 0xcc, 0xee, 0x8e, 0x2e, 0x1d, 0x1c, 0xaa, 0x2c, + 0x49, 0x43, 0xad, 0x59, 0x77, 0x99, 0xd7, 0xdf, 0x55, 0xc6, 0xcc, 0xa5, + 0x8c, 0xef, 0x03, 0x09, 0x5b, 0xaf, 0xc6, 0x32, 0x99, 0xb8, 0xe3, 0xdc, + 0xca, 0x44, 0x03, 0x1a, 0x4f, 0x15, 0x02, 0xeb, 0x41, 0x2c, 0xc3, 0xd6, + 0x92, 0xaf, 0x2c, 0x99, 0xa2, 0x97, 0x9d, 0xfe, 0xc5, 0xd2, 0xb8, 0x20, + 0x48, 0x17, 0xed, 0xa5, 0x49, 0xf8, 0xee, 0x22, 0xf8, 0x06, 0x0a, 0x09, + 0xdf, 0x72, 0xcb, 0x77, 0x18, 0x02, 0x3a, 0x81, 0x07, 0xb6, 0x0c, 0x3f, + 0xdc, 0x66, 0x18, 0x09, 0x93, 0xcb, 0x4e, 0x9f, 0x84, 0x9e, 0xae, 0xab, + 0x6c, 0xaf, 0x8e, 0xd5, 0xcf, 0x6c, 0xa9, 0x29, 0x63, 0x5d, 0xde, 0xe7, + 0x37, 0x69, 0xa4, 0xf5, 0x21, 0xfc, 0x4c, 0x59, 0x85, 0x8f, 0x68, 0x66, + 0x6f, 0xe5, 0x3a, 0x48, 0x33, 0xcb, 0xe8, 0x1e, 0xfb, 0x19, 0x95, 0x8d, + 0x56, 0x0a, 0x1c, 0x12, 0xee, 0xf1, 0x04, 0x87, 0x8c, 0xb6, 0x5f, 0x69, + 0xdf, 0xac, 0xca, 0xb4, 0x8e, 0x0c, 0x21, 0x1f, 0xa5, 0x9d, 0x04, 0xf6, + 0x49, 0x4f, 0xf5, 0x00, 0x52, 0x7c, 0x45, 0x54, 0xc9, 0xc8, 0xb4, 0x29, + 0xad, 0xa8, 0xa0, 0xee, 0x76, 0x15, 0x8a, 0xac, 0x49, 0x74, 0xab, 0x36, + 0x1c, 0x43, 0x23, 0x89, 0x54, 0xf0, 0x47, 0x03, 0xca, 0x75, 0x89, 0x99, + 0xe4, 0x08, 0xba, 0x27, 0xee, 0x62, 0xbd, 0x13, 0xd4, 0xf9, 0xaf, 0xe1, + 0xab, 0x9b, 0xff, 0x56, 0xb9, 0x17, 0xe5, 0x19, 0xa8, 0xf4, 0x3f, 0x64, + 0xec, 0xd4, 0x48, 0x6b, 0x94, 0x35, 0xd2, 0x5c, 0x1a, 0x7d, 0xc3, 0xb1, + 0x90, 0xbe, 0x48, 0x0d, 0x52, 0xc1, 0x16, 0xd9, 0xbc, 0x8d, 0x7a, 0x09, + 0xe4, 0xd6, 0xaf, 0x40, 0xe3, 0x57, 0xdd, 0x53, 0x1b, 0x76, 0x80, 0xfa, + 0x02, 0x1e, 0x63, 0x10, 0x5b, 0xdc, 0xf1, 0x70, 0x9c, 0x9b, 0x25, 0x1d, + 0xdf, 0x47, 0x12, 0xde, 0xfb, 0x2c, 0x56, 0x34, 0xae, 0x95, 0x96, 0xee, + 0xec, 0x78, 0x1e, 0x2a, 0x6e, 0x1d, 0xe6, 0x66, 0x24, 0xb9, 0xa2, 0x6e, + 0x42, 0x92, 0xbc, 0x01, 0x30, 0xd7, 0x4a, 0x03, 0xe9, 0x7a, 0x56, 0x61, + 0x08, 0x46, 0x5d, 0xa5, 0x40, 0xdc, 0x00, 0xb4, 0x3b, 0x21, 0xc5, 0xb8, + 0x9c, 0xf7, 0xf7, 0x82, 0x1f, 0xee, 0x60, 0x0e, 0x83, 0x96, 0xe3, 0x44, + 0x6f, 0x85, 0x56, 0x30, 0xc6, 0x81, 0x5a, 0x0a, 0x41, 0x63, 0x29, 0xb2, + 0x80, 0x53, 0xff, 0x3d, 0x20, 0xdf, 0x27, 0xb2, 0x74, 0x3f, 0x75, 0x28, + 0x8f, 0x25, 0xd4, 0x4b, 0xd7, 0x27, 0x7b, 0x86, 0xb7, 0xad, 0x64, 0x15, + 0x41, 0xc4, 0xa0, 0x57, 0xb3, 0xe5, 0xf7, 0x22, 0xd4, 0x35, 0xc1, 0xb5, + 0x8b, 0x39, 0xb6, 0x50, 0x20, 0x75, 0x13, 0x2a, 0x05, 0x84, 0xd4, 0xbe, + 0xe4, 0xd3, 0xb8, 0x12, 0xec, 0xc2, 0x3e, 0x0b, 0x95, 0x44, 0x26, 0x2e, + 0xe9, 0x14, 0x15, 0xbf, 0xa0, 0xdb, 0xad, 0xad, 0xdd, 0x73, 0x71, 0x87, + 0x9c, 0x09, 0x82, 0x42, 0xf3, 0xf7, 0x76, 0x15, 0x90, 0xc4, 0x5a, 0x0f, + 0x01, 0xad, 0x0c, 0x0a, 0x0c, 0x73, 0x45, 0x95, 0x2f, 0x71, 0xc3, 0x1b, + 0x3b, 0x46, 0x29, 0xf9, 0xbc, 0x78, 0x66, 0x07, 0x51, 0x8c, 0xe4, 0xc9, + 0xb5, 0x0e, 0x30, 0xe0, 0x33, 0xe4, 0x01, 0x9f, 0x97, 0xf8, 0xc8, 0x2d, + 0x38, 0x98, 0x42, 0x0e, 0x98, 0xd6, 0xf1, 0xdd, 0xc4, 0xa3, 0x29, 0xe2, + 0x08, 0xab, 0x8a, 0x6e, 0xb2, 0xe9, 0x51, 0xce, 0x4b, 0xfc, 0x91, 0x93, + 0xb0, 0xe2, 0xc6, 0x56, 0x65, 0xc5, 0x63, 0x25, 0x25, 0x8d, 0x36, 0xf7, + 0x3c, 0xca, 0x09, 0xda, 0xb7, 0x46, 0x8c, 0x65, 0x38, 0xa2, 0x90, 0x5a, + 0x05, 0x3d, 0xf3, 0x22, 0x1e, 0xd6, 0x2f, 0xb7, 0x0b, 0x53, 0x02, 0x73, + 0x29, 0xda, 0x29, 0x12, 0x2b, 0xbc, 0x71, 0x26, 0xdd, 0x6f, 0x11, 0x12, + 0xa2, 0xc4, 0x9b, 0x4a, 0x58, 0xd7, 0x0c, 0x0f, 0x1c, 0x67, 0x14, 0x7f, + 0xc0, 0x7b, 0xb7, 0xd0, 0x70, 0xc0, 0x9e, 0x8a, 0xe3, 0x28, 0xf7, 0x29, + 0xe0, 0x0b, 0xb5, 0x25, 0xb5, 0x73, 0x2d, 0xb7, 0x65, 0x18, 0x2f, 0x67, + 0xf7, 0xf6, 0xb6, 0x48, 0x0b, 0x2e, 0x91, 0x68, 0xd0, 0x58, 0xb0, 0xb7, + 0x22, 0x4e, 0xfc, 0x3d, 0x91, 0x48, 0x93, 0x01, 0x28, 0xc0, 0xfa, 0x29, + 0x96, 0x46, 0x53, 0xdc, 0x1c, 0x7b, 0x03, 0x8d, 0xf5, 0x39, 0x48, 0x6e, + 0xd0, 0x90, 0x55, 0x77, 0xdd, 0xd4, 0x8b, 0xa8, 0x06, 0xde, 0xcb, 0xff, + 0xb4, 0x04, 0x1f, 0x04, 0x25, 0xac, 0x27, 0x3b, 0x65, 0x0c, 0x02, 0x6e, + 0x26, 0x74, 0xad, 0xeb, 0x2f, 0xd7, 0xb3, 0x75, 0xfd, 0xe2, 0x4c, 0xa6, + 0x87, 0xcf, 0xc1, 0x20, 0x32, 0x58, 0x6d, 0x1c, 0x01, 0x30, 0xd2, 0x10, + 0xfa, 0x9a, 0xac, 0x9a, 0xf0, 0x36, 0x58, 0x3d, 0xd1, 0x28, 0x78, 0xd5, + 0x50, 0x26, 0xcd, 0x75, 0xc6, 0x8f, 0x76, 0x3f, 0x57, 0x7c, 0x6e, 0xbd, + 0xd7, 0xbc, 0x29, 0x6a, 0x3c, 0x61, 0x7e, 0x00, 0xde, 0xd9, 0xfa, 0x8a, + 0xee, 0x2c, 0x96, 0xb8, 0x4b, 0xec, 0x0b, 0xee, 0x98, 0x37, 0xd8, 0x13, + 0x2c, 0xda, 0x30, 0x0d, 0xa6, 0x1d, 0x5e, 0x37, 0xfc, 0x56, 0x00, 0x59, + 0xc1, 0x8b, 0x2e, 0x2e, 0x1f, 0x93, 0xaf, 0xa1, 0x96, 0xe1, 0x3e, 0x35, + 0x3a, 0x4b, 0xcd, 0x96, 0xfe, 0x5a, 0x30, 0xfd, 0x81, 0x91, 0x88, 0xcc, + 0x1a, 0x15, 0x49, 0x47, 0x26, 0x53, 0xe2, 0xd3, 0xd1, 0x27, 0x25, 0x10, + 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, 0xbb, 0xac, 0xaa, 0x3e, + 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, 0x3a, 0x90, 0x96, 0x6e, + 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, 0x66, 0x28, 0x68, 0xb4, + 0xbd, 0x74, 0x70, 0x07, 0xcb, 0x28, 0xb4, 0x81, 0xce, 0xd8, 0xeb, 0xa8, + 0xf8, 0x1e, 0x41, 0xc1, 0xc2, 0xe4, 0x42, 0xc4, 0x22, 0xb0, 0xfe, 0x10, + 0xb5, 0x96, 0x53, 0x28, 0xbb, 0x90, 0x90, 0x32, 0x56, 0xe2, 0xa4, 0xb4, + 0x50, 0x98, 0x65, 0xa9, 0x77, 0x61, 0x25, 0x7b, 0x35, 0xa0, 0xb7, 0xb7, + 0x43, 0x03, 0x77, 0xb2, 0xce, 0xed, 0x40, 0xa5, 0x41, 0x08, 0xa7, 0x1b, + 0xa9, 0x9f, 0x0f, 0xdb, 0x82, 0x11, 0x84, 0xa7, 0x51, 0x39, 0x0e, 0x2d, + 0x52, 0x2d, 0xf0, 0xb2, 0x0b, 0x2b, 0x30, 0xd0, 0xb6, 0x08, 0x0a, 0x37, + 0x05, 0x34, 0x26, 0x5c, 0xce, 0x89, 0x0c, 0x06, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x66, 0x28, 0x68, 0xb4, 0xbd, 0x74, 0x70, 0x07, + 0xcb, 0x28, 0xb4, 0x81, 0xce, 0xd8, 0xeb, 0xa8, 0xf8, 0x1e, 0x41, 0xc1, + 0xc2, 0xe4, 0x42, 0xc4, 0x22, 0xb0, 0xfe, 0x10, 0xb5, 0x96, 0x53, 0x28, + 0xbb, 0x90, 0x90, 0x32, 0x56, 0xe2, 0xa4, 0xb4, 0x50, 0x98, 0x65, 0xa9, + 0x77, 0x61, 0x25, 0x7b, 0x35, 0xa0, 0xb7, 0xb7, 0x43, 0x03, 0x77, 0xb2, + 0xce, 0xed, 0x40, 0xa5, 0x41, 0x08, 0xa7, 0x1b, 0xa9, 0x9f, 0x0f, 0xdb, + 0x82, 0x11, 0x84, 0xa7, 0x51, 0x39, 0x0e, 0x2d, 0x52, 0x2d, 0xf0, 0xb2, + 0x0b, 0x2b, 0x30, 0xd0, 0xb6, 0x08, 0x0a, 0x37, 0x05, 0x34, 0x26, 0x5c, + 0xce, 0x89, 0x0c, 0x06, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x2f, 0x7f, 0x25, 0x74, 0xa0, 0xc3, 0x09, 0x92, 0x5d, 0x56, 0x55, 0x9f, + 0x2b, 0xd3, 0xa6, 0xe0, 0xe8, 0x00, 0xda, 0x26, 0x1d, 0x48, 0x4b, 0xb7, + 0x3f, 0xe3, 0x8e, 0x43, 0xef, 0x7d, 0x84, 0x0e, 0xbb, 0x90, 0x90, 0x32, + 0x56, 0xe2, 0xa4, 0xb4, 0x50, 0x98, 0x65, 0xa9, 0x77, 0x61, 0x25, 0x7b, + 0x35, 0xa0, 0xb7, 0xb7, 0x43, 0x03, 0x77, 0xb2, 0xce, 0xed, 0x40, 0xa5, + 0x41, 0x08, 0xa7, 0x1b, 0xa9, 0x9f, 0x0f, 0xdb, 0x82, 0x11, 0x84, 0xa7, + 0x51, 0x39, 0x0e, 0x2d, 0x52, 0x2d, 0xf0, 0xb2, 0x0b, 0x2b, 0x30, 0xd0, + 0xb6, 0x08, 0x0a, 0x37, 0x05, 0x34, 0x26, 0x5c, 0xce, 0x89, 0x0c, 0x06, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x2f, 0x7f, 0x25, 0x74, + 0xa0, 0xc3, 0x09, 0x92, 0x5d, 0x56, 0x55, 0x9f, 0x2b, 0xd3, 0xa6, 0xe0, + 0xe8, 0x00, 0xda, 0x26, 0x1d, 0x48, 0x4b, 0xb7, 0x3f, 0xe3, 0x8e, 0x43, + 0xef, 0x7d, 0x84, 0x0e, 0xd8, 0x5c, 0x0b, 0x88, 0xd3, 0x69, 0xd4, 0x79, + 0x98, 0xcc, 0xdb, 0x7d, 0x24, 0xdb, 0x68, 0x99, 0x65, 0x7c, 0xf4, 0xc5, + 0xca, 0xd7, 0x35, 0xe2, 0x60, 0x54, 0x4a, 0x5a, 0xad, 0x35, 0x66, 0x04, + 0xa9, 0x9f, 0x0f, 0xdb, 0x82, 0x11, 0x84, 0xa7, 0x51, 0x39, 0x0e, 0x2d, + 0x52, 0x2d, 0xf0, 0xb2, 0x0b, 0x2b, 0x30, 0xd0, 0xb6, 0x08, 0x0a, 0x37, + 0x05, 0x34, 0x26, 0x5c, 0xce, 0x89, 0x0c, 0x06, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x2f, 0x7f, 0x25, 0x74, 0xa0, 0xc3, 0x09, 0x92, + 0x5d, 0x56, 0x55, 0x9f, 0x2b, 0xd3, 0xa6, 0xe0, 0xe8, 0x00, 0xda, 0x26, + 0x1d, 0x48, 0x4b, 0xb7, 0x3f, 0xe3, 0x8e, 0x43, 0xef, 0x7d, 0x84, 0x0e, + 0xd8, 0x5c, 0x0b, 0x88, 0xd3, 0x69, 0xd4, 0x79, 0x98, 0xcc, 0xdb, 0x7d, + 0x24, 0xdb, 0x68, 0x99, 0x65, 0x7c, 0xf4, 0xc5, 0xca, 0xd7, 0x35, 0xe2, + 0x60, 0x54, 0x4a, 0x5a, 0xad, 0x35, 0x66, 0x04, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x2f, 0x7f, 0x25, 0x74, 0xa0, 0xc3, 0x09, 0x92, 0x5d, 0x56, 0x55, 0x9f, + 0x2b, 0xd3, 0xa6, 0xe0, 0xe8, 0x00, 0xda, 0x26, 0x1d, 0x48, 0x4b, 0xb7, + 0x3f, 0xe3, 0x8e, 0x43, 0xef, 0x7d, 0x84, 0x0e, 0xd8, 0x5c, 0x0b, 0x88, + 0xd3, 0x69, 0xd4, 0x79, 0x98, 0xcc, 0xdb, 0x7d, 0x24, 0xdb, 0x68, 0x99, + 0x65, 0x7c, 0xf4, 0xc5, 0xca, 0xd7, 0x35, 0xe2, 0x60, 0x54, 0x4a, 0x5a, + 0xad, 0x35, 0x66, 0x04, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x69, 0xc2, 0x9a, 0x16, 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, + 0xd4, 0xc4, 0x63, 0x29, 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, + 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, 0x5e, 0xfe, 0x4a, 0xe8, + 0x40, 0x87, 0x13, 0x24, 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, + 0xd1, 0x01, 0xb4, 0x4d, 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, + 0xde, 0xfb, 0x08, 0x1d, 0x95, 0x92, 0xcb, 0xa8, 0x81, 0x5e, 0x60, 0xfc, + 0xdf, 0x92, 0x0c, 0xb4, 0x50, 0x7e, 0x39, 0x41, 0x69, 0x82, 0x68, 0x04, + 0x97, 0xa3, 0x5c, 0xb5, 0xd8, 0x1b, 0xb7, 0x1e, 0x97, 0xc1, 0x96, 0x0d, + 0xdf, 0xa1, 0x92, 0xbe, 0xe6, 0xad, 0xf7, 0xaf, 0x77, 0x27, 0x6d, 0x89, + 0x7f, 0xf6, 0xf2, 0xa8, 0xa8, 0x1d, 0x6a, 0xe4, 0x0a, 0x48, 0x95, 0xe4, + 0x6e, 0xd3, 0x01, 0x85, 0xcd, 0xc3, 0x21, 0x00, 0x5b, 0xd0, 0xc4, 0xf4, + 0xbe, 0xd0, 0x53, 0x73, 0x11, 0xee, 0xdc, 0x38, 0xb1, 0x9f, 0x1c, 0x60, + 0xfa, 0x74, 0x3b, 0x03, 0x8d, 0x37, 0xc6, 0x63, 0xed, 0x78, 0x93, 0xa1, + 0x9e, 0x47, 0xfa, 0x16, 0x18, 0x00, 0x84, 0xba, 0x3b, 0x22, 0x40, 0x71, + 0xa9, 0x78, 0xdb, 0xc1, 0x70, 0xd0, 0xe3, 0xb6, 0x0e, 0x15, 0x1e, 0x2f, + 0x74, 0xa3, 0xb2, 0x46, 0x54, 0x3c, 0x36, 0x06, 0x0b, 0x30, 0xd2, 0x03, + 0x66, 0x28, 0x68, 0xb4, 0xbd, 0x74, 0x70, 0x07, 0xcb, 0x28, 0xb4, 0x81, + 0xce, 0xd8, 0xeb, 0xa8, 0xf8, 0x1e, 0x41, 0xc1, 0xc2, 0xe4, 0x42, 0xc4, + 0x22, 0xb0, 0xfe, 0x10, 0xb5, 0x96, 0x53, 0x28, 0xc3, 0x56, 0xa6, 0xa5, + 0x9f, 0xd8, 0xc5, 0x92, 0x6e, 0x5e, 0xd5, 0x96, 0x6b, 0xa7, 0xa3, 0x14, + 0x91, 0xa7, 0x5d, 0x59, 0x68, 0xa6, 0x38, 0x1c, 0x2a, 0x3e, 0x51, 0xa7, + 0x53, 0x6d, 0x0a, 0x09, 0x45, 0xaa, 0xa1, 0x57, 0xec, 0xdc, 0x82, 0x1a, + 0x05, 0xde, 0xac, 0x84, 0x7d, 0x05, 0xdb, 0xc9, 0x41, 0x33, 0x95, 0x5e, + 0x88, 0x66, 0x06, 0x6d, 0x36, 0xd8, 0xea, 0xd5, 0xf9, 0xe3, 0xc4, 0x1b, + 0x26, 0x43, 0xe7, 0x4e, 0x1d, 0x56, 0x60, 0xbc, 0xf8, 0x50, 0x68, 0x5e, + 0x2a, 0xc4, 0xed, 0x9a, 0x18, 0x66, 0x0f, 0x7b, 0x78, 0x64, 0xa3, 0x6b, + 0x3e, 0xa2, 0x4b, 0x31, 0x2a, 0x92, 0x6b, 0x2c, 0xf9, 0xb6, 0xc6, 0x38, + 0xcd, 0xb1, 0x60, 0xa8, 0x44, 0xf4, 0xde, 0xbb, 0xe2, 0x2c, 0xc1, 0x4c, + 0xd7, 0x4e, 0x43, 0xf5, 0x33, 0x2b, 0x11, 0x1d, 0x81, 0x6f, 0x20, 0xf3, + 0xfe, 0xb4, 0x0d, 0x16, 0xbb, 0x90, 0x90, 0x32, 0x56, 0xe2, 0xa4, 0xb4, + 0x50, 0x98, 0x65, 0xa9, 0x77, 0x61, 0x25, 0x7b, 0x35, 0xa0, 0xb7, 0xb7, + 0x43, 0x03, 0x77, 0xb2, 0xce, 0xed, 0x40, 0xa5, 0x41, 0x08, 0xa7, 0x1b, + 0x45, 0xaa, 0xa1, 0x57, 0xec, 0xdc, 0x82, 0x1a, 0x05, 0xde, 0xac, 0x84, + 0x7d, 0x05, 0xdb, 0xc9, 0x41, 0x33, 0x95, 0x5e, 0x88, 0x66, 0x06, 0x6d, + 0x36, 0xd8, 0xea, 0xd5, 0xf9, 0xe3, 0xc4, 0x1b, 0xe8, 0x3e, 0x94, 0xc3, + 0x96, 0x20, 0xd8, 0xac, 0x5d, 0x51, 0xa1, 0x12, 0x3f, 0xd4, 0x10, 0xf4, + 0x69, 0x29, 0xe7, 0xd0, 0x7f, 0xf8, 0xb0, 0x15, 0x26, 0x9e, 0x88, 0x08, + 0x88, 0xdf, 0x15, 0x13, 0x4b, 0x6a, 0xed, 0x5c, 0xd5, 0xdd, 0x76, 0x01, + 0x24, 0xfe, 0x70, 0x98, 0x6e, 0x66, 0xfc, 0xac, 0xa8, 0x15, 0x77, 0xad, + 0x0f, 0x46, 0x8f, 0x9f, 0xba, 0xc6, 0x01, 0x92, 0xa9, 0xed, 0xc4, 0x09, + 0xee, 0x64, 0x91, 0x0c, 0x34, 0x57, 0xc3, 0xf0, 0x16, 0xee, 0xa3, 0x09, + 0xe1, 0x9d, 0x17, 0x14, 0xc0, 0x0a, 0xe2, 0xf0, 0xa8, 0xab, 0x39, 0x60, + 0x66, 0x51, 0xf2, 0x19, 0xd2, 0x7f, 0xa1, 0x11, 0xa9, 0x9f, 0x0f, 0xdb, + 0x82, 0x11, 0x84, 0xa7, 0x51, 0x39, 0x0e, 0x2d, 0x52, 0x2d, 0xf0, 0xb2, + 0x0b, 0x2b, 0x30, 0xd0, 0xb6, 0x08, 0x0a, 0x37, 0x05, 0x34, 0x26, 0x5c, + 0xce, 0x89, 0x0c, 0x06, 0x26, 0x43, 0xe7, 0x4e, 0x1d, 0x56, 0x60, 0xbc, + 0xf8, 0x50, 0x68, 0x5e, 0x2a, 0xc4, 0xed, 0x9a, 0x18, 0x66, 0x0f, 0x7b, + 0x78, 0x64, 0xa3, 0x6b, 0x3e, 0xa2, 0x4b, 0x31, 0x2a, 0x92, 0x6b, 0x2c, + 0x4b, 0x6a, 0xed, 0x5c, 0xd5, 0xdd, 0x76, 0x01, 0x24, 0xfe, 0x70, 0x98, + 0x6e, 0x66, 0xfc, 0xac, 0xa8, 0x15, 0x77, 0xad, 0x0f, 0x46, 0x8f, 0x9f, + 0xba, 0xc6, 0x01, 0x92, 0xa9, 0xed, 0xc4, 0x09, 0x18, 0x85, 0x04, 0x10, + 0x6b, 0x71, 0x08, 0x76, 0x9e, 0x36, 0xdd, 0x42, 0xdd, 0x29, 0x5e, 0x00, + 0x36, 0xe4, 0x49, 0x7d, 0xa0, 0x04, 0x56, 0x51, 0xd9, 0x48, 0xcf, 0x4f, + 0xd0, 0x63, 0x74, 0x09, 0xcb, 0xdd, 0xba, 0x75, 0x69, 0x1f, 0x0f, 0x88, + 0xc5, 0x3b, 0x7d, 0xc9, 0x42, 0x48, 0x21, 0x8d, 0x38, 0xc0, 0xf9, 0xf4, + 0x14, 0x09, 0x54, 0x11, 0x1c, 0xb1, 0x64, 0xef, 0xdd, 0xe3, 0xac, 0x19, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xf9, 0xb6, 0xc6, 0x38, + 0xcd, 0xb1, 0x60, 0xa8, 0x44, 0xf4, 0xde, 0xbb, 0xe2, 0x2c, 0xc1, 0x4c, + 0xd7, 0x4e, 0x43, 0xf5, 0x33, 0x2b, 0x11, 0x1d, 0x81, 0x6f, 0x20, 0xf3, + 0xfe, 0xb4, 0x0d, 0x16, 0xee, 0x64, 0x91, 0x0c, 0x34, 0x57, 0xc3, 0xf0, + 0x16, 0xee, 0xa3, 0x09, 0xe1, 0x9d, 0x17, 0x14, 0xc0, 0x0a, 0xe2, 0xf0, + 0xa8, 0xab, 0x39, 0x60, 0x66, 0x51, 0xf2, 0x19, 0xd2, 0x7f, 0xa1, 0x11, + 0xcb, 0xdd, 0xba, 0x75, 0x69, 0x1f, 0x0f, 0x88, 0xc5, 0x3b, 0x7d, 0xc9, + 0x42, 0x48, 0x21, 0x8d, 0x38, 0xc0, 0xf9, 0xf4, 0x14, 0x09, 0x54, 0x11, + 0x1c, 0xb1, 0x64, 0xef, 0xdd, 0xe3, 0xac, 0x19, 0xd9, 0x27, 0xd7, 0x14, + 0x05, 0x18, 0xda, 0x45, 0xe9, 0x35, 0xda, 0x05, 0xce, 0x4b, 0x1d, 0x4c, + 0xc5, 0x75, 0x1f, 0x65, 0x49, 0xc8, 0x5e, 0x53, 0x53, 0xd5, 0x8b, 0xf1, + 0xcd, 0xae, 0x0c, 0x15, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x5d, 0x49, 0x40, 0xdc, 0xfc, 0x7c, 0x51, 0x7c, 0x67, 0xc9, 0x58, 0x81, + 0x5a, 0xdb, 0x5d, 0x8d, 0x04, 0xf3, 0xad, 0x38, 0xa7, 0x55, 0xd3, 0xf1, + 0x06, 0xa1, 0x3c, 0xa8, 0xba, 0x06, 0x54, 0x02, 0xec, 0x3b, 0x83, 0x31, + 0x69, 0xbb, 0x79, 0xb1, 0xf8, 0x03, 0x1f, 0x3c, 0x7b, 0xe2, 0x6b, 0x67, + 0x3c, 0xea, 0x7c, 0x0c, 0x6c, 0xe8, 0x9e, 0x88, 0xfb, 0x92, 0xcb, 0x99, + 0x83, 0x20, 0x30, 0x01, 0x30, 0xcc, 0xf3, 0xe1, 0x48, 0x89, 0xec, 0x4b, + 0x58, 0x40, 0xf6, 0x05, 0x41, 0xb0, 0x65, 0x23, 0x0c, 0x5a, 0xfb, 0xa9, + 0x88, 0x0d, 0x74, 0xb0, 0xf7, 0x46, 0x7d, 0xd6, 0xd8, 0xc9, 0x7b, 0x0d, + 0x83, 0x12, 0xab, 0xc6, 0xc2, 0xe2, 0xae, 0x75, 0x6b, 0xaf, 0x0b, 0xcf, + 0xa8, 0xa4, 0x83, 0x50, 0x23, 0x54, 0x68, 0x25, 0xd8, 0xf5, 0xca, 0x76, + 0xf3, 0x7d, 0x9e, 0x9a, 0x75, 0x43, 0xb1, 0x27, 0xc5, 0x5c, 0x84, 0xfe, + 0xcb, 0x8d, 0x64, 0x28, 0x3d, 0xca, 0x7b, 0xf7, 0x81, 0x6b, 0xf0, 0x28, + 0xc0, 0x83, 0x84, 0x0c, 0xcf, 0xe2, 0x40, 0xde, 0xd7, 0xea, 0xd3, 0xed, + 0x32, 0xc4, 0xbd, 0x2c, 0xbf, 0x5b, 0xc9, 0xe6, 0xd1, 0x2f, 0x09, 0xb5, + 0x48, 0x1e, 0x89, 0xe1, 0x3f, 0x25, 0x18, 0x89, 0x4f, 0xa6, 0x4b, 0x17, + 0x22, 0xef, 0xe1, 0xec, 0xde, 0xf3, 0xfd, 0xfd, 0xf5, 0x98, 0x28, 0x11, + 0xe6, 0x9d, 0x98, 0xdd, 0x5a, 0x32, 0x97, 0x4f, 0x73, 0x48, 0xc5, 0x42, + 0x24, 0x77, 0x4d, 0xa6, 0xaa, 0xda, 0x0b, 0xf0, 0x4e, 0x7d, 0xbf, 0xf7, + 0x20, 0x88, 0x3b, 0xcb, 0xc6, 0x67, 0x91, 0x18, 0x84, 0x2b, 0x27, 0x13, + 0x40, 0x28, 0x8e, 0xc8, 0x76, 0x4c, 0x71, 0x9b, 0xa0, 0x92, 0xe8, 0x4e, + 0x76, 0xf1, 0x03, 0xbb, 0x9d, 0xed, 0xb0, 0x8f, 0xb1, 0x7a, 0x81, 0xb1, + 0x1f, 0x8b, 0xcd, 0x17, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x81, 0x17, 0xfa, 0x10, 0x03, 0x20, 0x33, 0x80, 0x24, 0x39, 0x85, 0xd1, + 0x22, 0xe0, 0xcd, 0xa1, 0x5d, 0x8a, 0x2f, 0x73, 0x9c, 0x37, 0xce, 0xfa, + 0xd0, 0xd4, 0x1f, 0xea, 0x1a, 0x26, 0x1a, 0x06, 0x60, 0xd3, 0xa4, 0x1a, + 0x01, 0x9b, 0x9e, 0x31, 0x83, 0xd3, 0x02, 0x4d, 0x94, 0x9e, 0x93, 0xdc, + 0xdf, 0x13, 0xaa, 0xbf, 0x23, 0xbf, 0xc7, 0xfa, 0xe6, 0xf9, 0xd4, 0xfb, + 0xc4, 0xb7, 0x2c, 0x2a, 0x4c, 0x51, 0xb6, 0x96, 0xda, 0x91, 0x15, 0x6f, + 0x5a, 0x15, 0xc1, 0x1c, 0xbf, 0xd8, 0x6e, 0xaf, 0x60, 0xab, 0xd9, 0x5b, + 0xe2, 0xfc, 0xca, 0x50, 0xed, 0x8c, 0xd2, 0xfb, 0xe3, 0x23, 0xf0, 0x29, + 0xbc, 0x12, 0x99, 0xa4, 0x7e, 0xf5, 0x08, 0xce, 0xde, 0x04, 0xef, 0x19, + 0x46, 0x0a, 0xa2, 0x74, 0xac, 0x2b, 0xd0, 0xbb, 0xfa, 0x01, 0xbc, 0x14, + 0xa4, 0x59, 0xda, 0x94, 0x07, 0x42, 0x6a, 0x29, 0xf8, 0x3c, 0x50, 0x86, + 0x20, 0x03, 0x4a, 0x6c, 0xd3, 0x77, 0x6c, 0x22, 0x69, 0x49, 0x6f, 0xa6, + 0xf5, 0xdb, 0x3c, 0x98, 0xee, 0xaf, 0xca, 0xc4, 0x89, 0x2f, 0x94, 0xf2, + 0x38, 0x44, 0x96, 0x2e, 0x34, 0xbb, 0x3a, 0xab, 0xd4, 0x80, 0x17, 0x9d, + 0xe6, 0x7b, 0x02, 0x3c, 0xc5, 0x45, 0x36, 0x56, 0x96, 0x37, 0x1f, 0x85, + 0x0f, 0xa5, 0x88, 0x44, 0x68, 0x26, 0xb6, 0xb9, 0xf9, 0x53, 0xb1, 0x13, + 0x77, 0x6a, 0xc9, 0x5b, 0x10, 0xc5, 0x5c, 0xf1, 0xbc, 0xf4, 0x80, 0xec, + 0x26, 0x7a, 0xe2, 0x4c, 0x5f, 0x8e, 0x84, 0x9a, 0xbe, 0x79, 0xaa, 0x4f, + 0x17, 0x8b, 0x0f, 0xd6, 0x6c, 0x3a, 0x03, 0x22, 0x5d, 0x5c, 0xf6, 0xab, + 0xd1, 0xe7, 0x73, 0xd2, 0xe1, 0xad, 0x7c, 0x29, 0x34, 0xac, 0x5e, 0x39, + 0xbc, 0x2b, 0xaf, 0xd5, 0x47, 0x19, 0x08, 0xe3, 0x1e, 0xa6, 0x93, 0x16, + 0x76, 0x62, 0x07, 0x19, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xbe, 0x62, 0x0e, 0x23, 0x47, 0x25, 0x3a, 0x00, 0x67, 0xcb, 0xfa, 0xb5, + 0xde, 0x8a, 0x07, 0x6b, 0x63, 0x40, 0xb4, 0xf5, 0x25, 0xba, 0xaf, 0x56, + 0x1a, 0x37, 0x2c, 0x71, 0x0d, 0x44, 0x16, 0x17, 0x0b, 0xe7, 0x14, 0x36, + 0xdf, 0x10, 0x3e, 0xda, 0xae, 0x79, 0x8f, 0xf0, 0x25, 0x4b, 0xbc, 0xfa, + 0xf3, 0x4b, 0xbf, 0x92, 0x81, 0xbc, 0x7c, 0x66, 0xff, 0x98, 0x18, 0xc8, + 0xbf, 0x77, 0xe4, 0x11, 0xf8, 0x04, 0xda, 0xe9, 0x66, 0xed, 0x42, 0xea, + 0xde, 0xa7, 0xd3, 0xe5, 0x06, 0xeb, 0x1e, 0xac, 0xbe, 0x8c, 0x07, 0x07, + 0xa8, 0xa5, 0x36, 0xd0, 0x42, 0x10, 0xa5, 0x8f, 0xbc, 0xed, 0xcb, 0x01, + 0xdc, 0xde, 0x99, 0xf9, 0xe5, 0x2a, 0x1b, 0x6f, 0x3b, 0xd9, 0xe8, 0x3f, + 0x0c, 0xb3, 0x22, 0x73, 0x72, 0xe8, 0xb2, 0x1c, 0xda, 0x4b, 0x8f, 0xc2, + 0x10, 0x25, 0x20, 0xb5, 0x7e, 0x49, 0xa9, 0x2f, 0x93, 0x97, 0x81, 0x61, + 0x50, 0xaf, 0xe5, 0xb9, 0x48, 0x7a, 0x88, 0x5d, 0x77, 0x9c, 0x4d, 0x21, + 0xe0, 0x1c, 0xf3, 0xfb, 0xb6, 0x41, 0x14, 0x53, 0x3f, 0xa2, 0x2e, 0xd7, + 0xc8, 0xbe, 0x2d, 0x1c, 0xda, 0xb3, 0x02, 0x84, 0x70, 0xde, 0xb1, 0x9d, + 0x6b, 0xd6, 0xff, 0x9c, 0xb2, 0x84, 0x30, 0x66, 0x78, 0x00, 0x22, 0x9e, + 0x49, 0x60, 0xc7, 0x8d, 0xa6, 0xf2, 0xb6, 0x54, 0x9b, 0xaa, 0xc0, 0x00, + 0x5c, 0x1b, 0xa4, 0x1e, 0x0b, 0xcd, 0x8a, 0xef, 0xca, 0xf7, 0xcb, 0x7e, + 0xea, 0xd4, 0x80, 0xc7, 0x8b, 0xf5, 0x87, 0x9a, 0x2b, 0xbb, 0xa6, 0xf1, + 0xa3, 0xa4, 0x28, 0xaf, 0x2c, 0xf4, 0xfb, 0x12, 0xf1, 0xc0, 0x9e, 0x0c, + 0x15, 0x08, 0xb6, 0x0c, 0xc9, 0x98, 0xc7, 0x6f, 0x4d, 0x63, 0x8b, 0x09, + 0x93, 0xf0, 0xcd, 0x96, 0x33, 0xfc, 0xf2, 0x16, 0x22, 0x64, 0x5b, 0x56, + 0x5f, 0x86, 0xc5, 0x03, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x85, 0xf1, 0xa6, 0x32, 0x5a, 0x8c, 0x07, 0x0e, 0x37, 0x97, 0xd9, 0x78, + 0xf6, 0xb0, 0xbc, 0xd3, 0xea, 0x35, 0x4a, 0x72, 0xb1, 0x36, 0x62, 0xfa, + 0xbe, 0x53, 0x57, 0xfe, 0xf8, 0xa5, 0x60, 0x02, 0xa1, 0x0e, 0x58, 0xe2, + 0xac, 0xbf, 0x6d, 0xce, 0x0e, 0xbb, 0xf1, 0xdb, 0xd4, 0xf0, 0xcb, 0x37, + 0x3b, 0x46, 0x8c, 0x8a, 0x07, 0x97, 0xc0, 0xa4, 0x7d, 0xa6, 0x98, 0xba, + 0xc9, 0x62, 0x9c, 0x23, 0x77, 0xb3, 0xb4, 0x7c, 0xee, 0x62, 0xbb, 0xef, + 0x4b, 0xcf, 0xf3, 0x5d, 0xcd, 0x20, 0x00, 0x10, 0xbb, 0xab, 0x78, 0x87, + 0x43, 0xa7, 0x09, 0x64, 0x10, 0x98, 0x65, 0xc6, 0x2f, 0x56, 0x10, 0x03, + 0x3a, 0x1d, 0xdf, 0x78, 0xf7, 0x31, 0xf7, 0x87, 0xb7, 0xf2, 0xcb, 0x2b, + 0x17, 0x11, 0x50, 0xc7, 0xc8, 0x3c, 0x54, 0xe4, 0x56, 0xcb, 0x5c, 0x87, + 0xc6, 0xce, 0x97, 0xf2, 0x69, 0x37, 0x56, 0x02, 0x2d, 0x36, 0x33, 0x70, + 0x5d, 0x80, 0xca, 0x1e, 0x67, 0x21, 0x6c, 0xfb, 0x3a, 0x2c, 0x37, 0xa3, + 0x21, 0xc2, 0xd6, 0x63, 0x96, 0xfa, 0xcd, 0xcc, 0xa9, 0xff, 0xcd, 0x86, + 0x21, 0x7a, 0x4d, 0x1e, 0x4a, 0xb5, 0xb7, 0xff, 0xc0, 0xa4, 0x98, 0x9a, + 0x72, 0x0e, 0x91, 0x04, 0xad, 0x13, 0xf2, 0x84, 0x80, 0x59, 0x5b, 0xea, + 0xe4, 0x70, 0x1e, 0x26, 0xbb, 0x6b, 0xa0, 0x01, 0x22, 0xe6, 0xe3, 0x13, + 0x43, 0x49, 0x0c, 0x7b, 0x8d, 0x73, 0xe1, 0xa5, 0xdd, 0xe4, 0x70, 0xb2, + 0x10, 0x9b, 0x9e, 0x1c, 0x2a, 0x7b, 0x6b, 0x0b, 0xd6, 0x2c, 0x16, 0x79, + 0x3e, 0x45, 0x52, 0x92, 0x34, 0x53, 0x41, 0x19, 0x79, 0x3b, 0x10, 0xa2, + 0x9b, 0xf7, 0x0d, 0xbe, 0x5a, 0x24, 0x1b, 0xc0, 0x63, 0x97, 0x89, 0x2c, + 0x13, 0xe3, 0x85, 0xa3, 0x4e, 0xb8, 0x0c, 0x03, 0x3e, 0x2e, 0xf7, 0x80, + 0x0e, 0x61, 0x6b, 0x19, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xdc, 0xaf, 0xe0, 0x74, 0xd4, 0x82, 0x85, 0x8f, 0x85, 0x19, 0x0b, 0xe4, + 0xa7, 0xff, 0xb0, 0xe2, 0xc1, 0xa2, 0x9e, 0x49, 0xbb, 0x80, 0x5a, 0x79, + 0xeb, 0x32, 0x80, 0x1f, 0xfa, 0x4b, 0xb1, 0x1f, 0x6b, 0x44, 0x4b, 0x00, + 0xad, 0x49, 0x3e, 0xf1, 0x55, 0x16, 0x87, 0xcc, 0xbf, 0xc1, 0x76, 0xa1, + 0x36, 0x5b, 0xa7, 0x61, 0xcb, 0xe3, 0x59, 0x93, 0xed, 0x44, 0x2c, 0x42, + 0x85, 0x07, 0xaf, 0x26, 0xfa, 0xe5, 0xc8, 0x49, 0x25, 0xcf, 0xde, 0xf0, + 0xe4, 0xfc, 0xa4, 0x43, 0x37, 0xc4, 0x1b, 0x71, 0xa4, 0xf5, 0xad, 0x2a, + 0xb1, 0x08, 0x09, 0x07, 0x33, 0xa7, 0x7b, 0xaa, 0x27, 0x0e, 0xe1, 0x0d, + 0xc4, 0x4d, 0x57, 0x43, 0x8c, 0x7b, 0x5a, 0xc2, 0x18, 0x09, 0x6c, 0xad, + 0xe3, 0x02, 0x94, 0xdf, 0x84, 0x55, 0xb1, 0x86, 0xe0, 0xec, 0x01, 0x07, + 0x56, 0xf5, 0xfb, 0x36, 0x05, 0x61, 0x85, 0x03, 0x95, 0x66, 0x18, 0xd1, + 0xef, 0xd4, 0x35, 0x06, 0xc0, 0xe1, 0xfa, 0x3d, 0x9b, 0x26, 0x60, 0xa6, + 0xf2, 0xdb, 0x23, 0xce, 0x51, 0xc4, 0x8e, 0xfd, 0x51, 0x6d, 0xf3, 0xe4, + 0x5e, 0x5f, 0xa5, 0x17, 0xcd, 0xad, 0x76, 0x97, 0xd7, 0x61, 0x50, 0x66, + 0xba, 0x85, 0x84, 0x6e, 0xe4, 0x48, 0xd1, 0x27, 0xe7, 0xc5, 0x62, 0x1d, + 0x67, 0x3c, 0x13, 0x08, 0x22, 0x47, 0x07, 0x68, 0x8f, 0x08, 0xc6, 0x16, + 0xa8, 0x9f, 0x27, 0xda, 0x45, 0x94, 0x18, 0x78, 0x9d, 0x3b, 0x11, 0xa4, + 0x05, 0xbd, 0xb3, 0x8b, 0xe9, 0xee, 0x3f, 0xca, 0x47, 0xe8, 0xd1, 0x14, + 0x31, 0x6f, 0x30, 0x19, 0xda, 0xe0, 0xff, 0x26, 0x4c, 0x12, 0x65, 0xce, + 0x2a, 0x20, 0x4e, 0xc4, 0xe7, 0x04, 0x91, 0x51, 0x27, 0xac, 0x74, 0xd4, + 0x0b, 0xe0, 0x19, 0xb6, 0xa2, 0x83, 0x4a, 0x90, 0x89, 0xee, 0x7b, 0x2e, + 0xee, 0x20, 0xae, 0x08, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xb2, 0xfd, 0xea, 0x95, 0x3c, 0x2a, 0xac, 0xdc, 0x8d, 0xa8, 0x2f, 0x9c, + 0xd6, 0x99, 0xa6, 0xa5, 0x22, 0x7c, 0x9c, 0xc5, 0x2e, 0x52, 0xd3, 0x96, + 0xa6, 0xc8, 0xae, 0x61, 0x14, 0xfc, 0x65, 0x21, 0xc2, 0x3e, 0x50, 0xc2, + 0x68, 0xef, 0x8b, 0x49, 0xe1, 0x72, 0x79, 0x8f, 0xf5, 0x6f, 0xfe, 0x4d, + 0x2b, 0xfb, 0xff, 0xda, 0xaa, 0xdf, 0x53, 0x18, 0x66, 0xad, 0x08, 0xe3, + 0x30, 0x8d, 0xe4, 0x20, 0xae, 0xfe, 0x1a, 0x7b, 0x60, 0x29, 0x92, 0xb2, + 0x84, 0xab, 0x8b, 0xa3, 0xd9, 0x2c, 0xf0, 0x11, 0x0c, 0x45, 0xae, 0x68, + 0x83, 0x74, 0x96, 0x1e, 0x94, 0x6b, 0x2d, 0x15, 0xb9, 0x23, 0xd1, 0x1d, + 0x75, 0xfc, 0xa4, 0x51, 0x89, 0xdc, 0x3b, 0x00, 0x4a, 0x6c, 0x64, 0x50, + 0x03, 0x2b, 0x9d, 0x7e, 0xaf, 0x62, 0xaf, 0x90, 0xc6, 0xa7, 0xaa, 0x4e, + 0x08, 0x15, 0x74, 0x34, 0x2a, 0xa2, 0xd5, 0x19, 0xa8, 0x8c, 0xae, 0x69, + 0x97, 0x9a, 0x4d, 0x01, 0x14, 0x8b, 0xbd, 0x47, 0x78, 0xd6, 0xe6, 0xe3, + 0x44, 0x6b, 0xcc, 0x77, 0x50, 0x87, 0x10, 0x77, 0x5f, 0xcd, 0x2c, 0x97, + 0x18, 0x7c, 0x81, 0x19, 0x05, 0xeb, 0xe9, 0xb8, 0x6d, 0x8c, 0x50, 0x30, + 0xa8, 0x0f, 0x1a, 0x89, 0x0c, 0x49, 0xa8, 0xa1, 0x14, 0xad, 0x26, 0xb9, + 0xfc, 0x58, 0xb3, 0xc4, 0x93, 0x2c, 0xd6, 0x80, 0x99, 0xcb, 0x53, 0x16, + 0x8c, 0x77, 0xd4, 0xb3, 0xf1, 0xe1, 0x0b, 0x28, 0x94, 0x48, 0xcb, 0x45, + 0xf4, 0x01, 0x94, 0xab, 0x10, 0xc4, 0x98, 0x81, 0xf4, 0x5f, 0x3b, 0xb3, + 0x86, 0x4a, 0x5a, 0x90, 0xe8, 0xd6, 0xcc, 0x19, 0xd8, 0xcf, 0x63, 0x41, + 0x6f, 0x8c, 0x84, 0x7a, 0xea, 0x20, 0x35, 0x3b, 0x88, 0x48, 0xd1, 0x85, + 0x51, 0xb0, 0xa4, 0x26, 0xf8, 0xa9, 0x40, 0x65, 0xfb, 0x72, 0x6e, 0x6c, + 0x87, 0x11, 0x59, 0x19, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x07, 0xe4, 0xac, 0x6a, 0x3e, 0xa1, 0x6e, 0xf4, 0xa3, 0x09, 0x33, 0x73, + 0xfc, 0x51, 0x7b, 0xaf, 0x84, 0x17, 0xe9, 0xaa, 0xe2, 0x6e, 0x5c, 0x44, + 0xc0, 0x2f, 0x30, 0x35, 0x0a, 0x16, 0xe6, 0x0b, 0x26, 0x08, 0xd8, 0xbf, + 0x16, 0xf4, 0x0e, 0x71, 0xc3, 0x55, 0x18, 0x54, 0x91, 0xe1, 0x89, 0xf2, + 0x49, 0x93, 0x21, 0x0f, 0x4c, 0x20, 0x15, 0x38, 0xed, 0x51, 0x2c, 0x27, + 0x59, 0x9e, 0xe3, 0x17, 0x0d, 0x62, 0x5d, 0x8f, 0x2a, 0xf3, 0x7b, 0x95, + 0xf1, 0xd8, 0x5c, 0xad, 0x7a, 0xd7, 0xf5, 0x0a, 0xb6, 0xd3, 0x8d, 0x9c, + 0x51, 0xe6, 0xa9, 0x13, 0xb6, 0xdf, 0xed, 0xe0, 0x96, 0xd4, 0x4c, 0x2e, + 0x4e, 0x44, 0xd7, 0xe0, 0x3a, 0x0a, 0x11, 0x18, 0x75, 0x09, 0x42, 0x9c, + 0xb5, 0xb7, 0xfd, 0x25, 0xc5, 0x86, 0x2a, 0xda, 0x12, 0x06, 0x71, 0x9e, + 0x74, 0x03, 0x15, 0x66, 0x19, 0xc7, 0x0a, 0x1d, 0xdf, 0x8a, 0xb0, 0xf0, + 0xda, 0x4f, 0x90, 0x64, 0x24, 0x7c, 0x03, 0xbc, 0x2d, 0xdb, 0xbb, 0xf5, + 0x30, 0xaf, 0x8c, 0x81, 0x5e, 0x71, 0x3a, 0x0d, 0x70, 0x9c, 0x82, 0x31, + 0xb4, 0x0b, 0x87, 0x2b, 0xdf, 0xe4, 0xf7, 0x08, 0x03, 0x41, 0x47, 0x4a, + 0xf8, 0xaf, 0x69, 0x3d, 0x3f, 0xdc, 0x72, 0x90, 0x40, 0xbf, 0x82, 0x98, + 0x6f, 0xef, 0x2e, 0xfe, 0xe1, 0xc7, 0xc6, 0x22, 0xbf, 0x41, 0x62, 0x22, + 0xea, 0xb6, 0x83, 0x93, 0x35, 0x5e, 0x6a, 0xca, 0xc4, 0xf6, 0xa9, 0x5f, + 0x04, 0xc7, 0xf9, 0x72, 0x45, 0x40, 0xfc, 0xbf, 0x5e, 0x8f, 0xf3, 0x73, + 0x2f, 0xde, 0xff, 0xdb, 0x05, 0x76, 0x96, 0x26, 0xb9, 0xde, 0xd1, 0xad, + 0xa8, 0x6d, 0xae, 0x93, 0x5b, 0x77, 0x68, 0x28, 0xe2, 0x33, 0x81, 0x8e, + 0x44, 0x3b, 0xb8, 0xf8, 0xb5, 0x27, 0x6a, 0x9b, 0xe8, 0x4b, 0x3c, 0x1f, + 0xdc, 0xb5, 0x6f, 0x05, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x30, 0x8b, 0xc7, 0xea, 0x8a, 0x0f, 0x44, 0x2c, 0x7d, 0xc7, 0xd3, 0x71, + 0xd0, 0x3c, 0xe1, 0x97, 0x0b, 0x6c, 0xbd, 0x53, 0xc8, 0x9f, 0x68, 0x6a, + 0x0e, 0x36, 0x72, 0xb6, 0x7e, 0x6b, 0x65, 0x07, 0x86, 0xca, 0xef, 0x64, + 0xd2, 0x75, 0x40, 0xa2, 0x57, 0x01, 0x88, 0xff, 0x0e, 0x00, 0xbb, 0xf0, + 0x29, 0x5f, 0xd9, 0x86, 0x70, 0xb1, 0x29, 0x54, 0xf2, 0x3a, 0x49, 0x54, + 0x6b, 0x80, 0xe3, 0x17, 0x8f, 0x59, 0xfa, 0xba, 0x68, 0xed, 0x45, 0x4b, + 0xbf, 0x41, 0x3f, 0x0c, 0x07, 0xe3, 0x16, 0x09, 0x6d, 0xd5, 0x45, 0x8d, + 0x29, 0x89, 0x42, 0x53, 0x99, 0x81, 0x1a, 0x82, 0xba, 0xe8, 0xe1, 0x24, + 0xdc, 0x4b, 0xb2, 0x50, 0x5c, 0x59, 0x56, 0x95, 0x48, 0x15, 0x1f, 0xb7, + 0x08, 0x6b, 0x55, 0xa8, 0x0a, 0x7a, 0x34, 0x99, 0xd4, 0x38, 0x0a, 0x82, + 0xe1, 0xea, 0xd8, 0xa2, 0x0e, 0x8a, 0x14, 0x21, 0xd8, 0x93, 0x3c, 0x77, + 0x58, 0x68, 0x57, 0xd6, 0x88, 0x3e, 0x49, 0x85, 0x86, 0xfb, 0x0e, 0xaa, + 0x94, 0xa8, 0xe4, 0x1e, 0xc7, 0x0f, 0xb9, 0x7d, 0xea, 0xc4, 0x7e, 0xfb, + 0x5a, 0x2a, 0x9c, 0x18, 0x87, 0xe0, 0xec, 0xbc, 0x8e, 0x61, 0xbb, 0x95, + 0xf5, 0x56, 0xba, 0x0b, 0x04, 0xfd, 0xfc, 0xa5, 0x0b, 0x8d, 0xc6, 0x1f, + 0x92, 0x53, 0xba, 0x46, 0xd9, 0xd4, 0xe8, 0x4a, 0x46, 0x6f, 0xfe, 0x0d, + 0x26, 0xbe, 0xae, 0xd7, 0x90, 0x93, 0x72, 0x78, 0x62, 0x73, 0xce, 0xd1, + 0x67, 0xda, 0x1a, 0xc1, 0xe4, 0x57, 0x14, 0xcf, 0x5b, 0xf4, 0x04, 0xfe, + 0xe5, 0xbc, 0xd8, 0x6b, 0x00, 0x5b, 0xe7, 0x1b, 0xd0, 0x71, 0xb2, 0xeb, + 0xec, 0x4e, 0xb4, 0x64, 0xd4, 0xc8, 0x8d, 0xd8, 0x43, 0xc4, 0x8f, 0x68, + 0x76, 0x25, 0x38, 0x63, 0xac, 0xd7, 0x16, 0xfe, 0x89, 0xcf, 0x0d, 0x35, + 0x8f, 0xc4, 0x70, 0x17, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x1d, 0xa9, 0x8f, 0x3a, 0xdf, 0x65, 0x2e, 0x9f, 0x42, 0xf7, 0xe5, 0x69, + 0xc1, 0x60, 0xdf, 0x76, 0x6d, 0xd6, 0x56, 0x49, 0xf9, 0x49, 0x33, 0xa5, + 0x90, 0xb2, 0x4f, 0xb0, 0xa9, 0x0e, 0x2e, 0x0b, 0xe0, 0x47, 0xcc, 0xc5, + 0xb2, 0xd9, 0x5e, 0x0f, 0xc7, 0x9b, 0x5f, 0xca, 0xa4, 0xb1, 0xdd, 0x2f, + 0x2e, 0xa6, 0xd2, 0x02, 0x09, 0x5e, 0x9a, 0x9f, 0x92, 0x21, 0xec, 0x99, + 0xd5, 0xe0, 0x6d, 0x0e, 0x93, 0xbc, 0x5c, 0xb1, 0xdc, 0x5e, 0x61, 0x5a, + 0xa7, 0x18, 0xae, 0x36, 0x78, 0x49, 0x78, 0x22, 0xb7, 0xd4, 0x56, 0xde, + 0x74, 0x7f, 0x47, 0x3a, 0xfe, 0x33, 0x66, 0x8d, 0x88, 0x12, 0x6a, 0x1f, + 0xb9, 0x59, 0x48, 0x56, 0xfa, 0xa3, 0x22, 0xe0, 0xd9, 0x0a, 0xee, 0xd3, + 0x5f, 0x49, 0xbb, 0xaa, 0x16, 0x29, 0x4a, 0x55, 0x23, 0xda, 0x16, 0x7b, + 0xf6, 0x25, 0xcb, 0x1b, 0xee, 0x43, 0x53, 0x0c, 0xa2, 0xe5, 0x36, 0xef, + 0x40, 0x3b, 0xfc, 0xb7, 0xaa, 0x8e, 0x35, 0xc9, 0xdd, 0x21, 0x9e, 0xa2, + 0x0e, 0x68, 0x74, 0x2d, 0x3c, 0x33, 0x80, 0x7d, 0xb5, 0xb2, 0xcb, 0x2c, + 0x9b, 0xc2, 0xcb, 0x2a, 0x47, 0xf6, 0x88, 0x5b, 0x2e, 0x98, 0xde, 0x80, + 0x95, 0xdf, 0xee, 0x02, 0x5a, 0x5b, 0x92, 0x6e, 0x29, 0x8b, 0x99, 0x31, + 0x90, 0x36, 0x98, 0x0c, 0xaf, 0x5b, 0xdf, 0x9e, 0xee, 0xee, 0x47, 0x2a, + 0xf8, 0xfc, 0xf0, 0x10, 0x3e, 0x38, 0x21, 0x67, 0xc3, 0x1b, 0xd4, 0xd2, + 0x08, 0xa7, 0x5c, 0x9c, 0x2d, 0x13, 0xe2, 0x22, 0xbc, 0x69, 0x54, 0xbc, + 0x47, 0x78, 0x51, 0x10, 0xd2, 0x14, 0xc6, 0x2e, 0x2a, 0x91, 0xa1, 0xff, + 0x50, 0x7e, 0x11, 0xbc, 0xe3, 0x24, 0xcb, 0x2d, 0x90, 0xe8, 0x98, 0x9e, + 0x6c, 0x19, 0xce, 0x84, 0xb5, 0x8c, 0x48, 0xd8, 0xec, 0x61, 0xcf, 0x90, + 0x27, 0xf9, 0x56, 0x16, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x82, 0xb1, 0xb5, 0x40, 0x0e, 0x74, 0xb0, 0xcd, 0x51, 0xef, 0x86, 0xb9, + 0x79, 0x94, 0xc6, 0x19, 0xb0, 0x58, 0xd6, 0xe8, 0x85, 0x5c, 0x27, 0x7e, + 0x73, 0x8b, 0xfa, 0xc4, 0xe7, 0xc1, 0x40, 0x19, 0xef, 0x3d, 0x34, 0x58, + 0xe0, 0xa1, 0x18, 0xb9, 0xa2, 0x55, 0x78, 0xf9, 0x7b, 0xcc, 0xa2, 0x99, + 0x54, 0x90, 0xa1, 0x20, 0xcd, 0x8a, 0x2e, 0xeb, 0x38, 0xc5, 0xa6, 0x44, + 0x8a, 0x63, 0x2d, 0x13, 0xa0, 0xa8, 0x39, 0xd0, 0xb2, 0x6d, 0x6b, 0x90, + 0x88, 0x33, 0xd6, 0x4f, 0xc3, 0x9a, 0x44, 0xa5, 0x2e, 0xcb, 0xc1, 0x0b, + 0x8e, 0xfb, 0xcd, 0x23, 0xc2, 0xc5, 0x0f, 0x88, 0x16, 0xe0, 0xa4, 0x2b, + 0xcd, 0x3c, 0xea, 0x9a, 0xe8, 0xb6, 0x53, 0x88, 0x6d, 0x30, 0x7d, 0xcd, + 0x5f, 0x6b, 0xdd, 0xcc, 0x6b, 0xc7, 0xbd, 0x26, 0x69, 0x27, 0xfb, 0x1d, + 0x6f, 0xb7, 0x87, 0xaa, 0x9e, 0x82, 0x97, 0x07, 0x37, 0x94, 0xda, 0x96, + 0xf3, 0x9a, 0xba, 0xa9, 0xce, 0xea, 0xa3, 0x25, 0x31, 0xbf, 0xbe, 0x59, + 0x5c, 0x91, 0xe2, 0x21, 0xef, 0x79, 0x6b, 0x77, 0x3a, 0xef, 0x47, 0x30, + 0x0d, 0x59, 0x84, 0x28, 0x7d, 0x33, 0x19, 0x27, 0x1f, 0x12, 0xe6, 0x6a, + 0x90, 0x68, 0x52, 0x90, 0x74, 0xb8, 0x42, 0x0e, 0x02, 0x95, 0x83, 0x3f, + 0x24, 0xd6, 0x77, 0x2b, 0x88, 0x81, 0x47, 0xfd, 0xa9, 0x18, 0x02, 0x1a, + 0x8f, 0x8e, 0x09, 0xdf, 0x32, 0x23, 0xee, 0x96, 0x6b, 0xee, 0xb6, 0x49, + 0xaa, 0x46, 0x10, 0x50, 0x8a, 0xee, 0x3f, 0x71, 0x22, 0x22, 0x62, 0x50, + 0x20, 0xb6, 0x95, 0x4a, 0x9a, 0x54, 0xbc, 0x2a, 0xba, 0xb7, 0x43, 0xb8, + 0xdd, 0x1c, 0xb9, 0x25, 0xaf, 0xb8, 0x56, 0x4e, 0xe8, 0x43, 0x68, 0x13, + 0x35, 0x67, 0xdc, 0x18, 0x54, 0xe9, 0xbd, 0x85, 0x16, 0xc9, 0xf0, 0xda, + 0x93, 0x2b, 0x42, 0x23, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xdd, 0x22, 0x39, 0x02, 0x44, 0xe5, 0xc1, 0x08, 0x0e, 0x04, 0x9a, 0x6b, + 0x8d, 0x10, 0xfe, 0x8b, 0xdd, 0x4c, 0xc3, 0x3e, 0x6c, 0x64, 0x72, 0xfe, + 0xed, 0xf4, 0xb5, 0xd8, 0x82, 0x2a, 0x42, 0x04, 0xf6, 0xaf, 0xc5, 0xd8, + 0xfb, 0xe1, 0x6e, 0x98, 0x72, 0x62, 0xf8, 0x7c, 0x32, 0x75, 0x5e, 0x90, + 0x86, 0x60, 0x32, 0xc7, 0x46, 0xb1, 0x8d, 0x62, 0x70, 0xc5, 0x9e, 0x72, + 0xb1, 0x14, 0xb8, 0x1b, 0xe4, 0xb3, 0xcf, 0xb2, 0x2f, 0xc5, 0x71, 0x2e, + 0xef, 0xbb, 0xbf, 0xcb, 0x01, 0x88, 0xcb, 0x93, 0x92, 0x54, 0xcd, 0x55, + 0xd4, 0x19, 0x68, 0xa4, 0x47, 0x8b, 0x3d, 0xf5, 0xe5, 0x29, 0x93, 0x24, + 0x58, 0x8c, 0x55, 0x8c, 0x33, 0x0d, 0x07, 0x6e, 0xe6, 0x67, 0x8d, 0x55, + 0x7c, 0xf9, 0x83, 0x5c, 0x25, 0xd7, 0xb9, 0xe7, 0xdd, 0x4d, 0xf7, 0xa5, + 0x0d, 0x74, 0x3d, 0x10, 0x1a, 0x35, 0x96, 0x04, 0x3d, 0x45, 0x5d, 0x9a, + 0xde, 0x3b, 0x8f, 0xeb, 0xcb, 0xe0, 0x86, 0x24, 0x4c, 0x54, 0xd9, 0xa6, + 0x3d, 0xc1, 0x22, 0x49, 0x47, 0xc6, 0x61, 0xd8, 0x31, 0xc9, 0xb9, 0x90, + 0xb8, 0x7a, 0xbb, 0x18, 0xf6, 0xb7, 0xbf, 0x34, 0xc9, 0xd9, 0xee, 0x7f, + 0xd8, 0xe5, 0x19, 0x73, 0xb3, 0x26, 0xea, 0x5a, 0x12, 0x87, 0x84, 0x1e, + 0x2c, 0x8e, 0xa4, 0x06, 0xbf, 0x32, 0x4c, 0x6b, 0x7c, 0xeb, 0x12, 0x29, + 0x65, 0x27, 0x34, 0xf1, 0x9a, 0x89, 0xa8, 0xcb, 0x01, 0x78, 0x1a, 0x38, + 0x69, 0x93, 0xfa, 0x7a, 0x3b, 0x88, 0xe4, 0x65, 0x71, 0xad, 0xaf, 0x5e, + 0x7d, 0x16, 0x24, 0xeb, 0x1d, 0x97, 0x9a, 0x17, 0xc1, 0x41, 0x22, 0x14, + 0x33, 0xa7, 0x12, 0x47, 0xe9, 0xde, 0x69, 0x6e, 0x41, 0xcd, 0xc1, 0xe4, + 0xa9, 0x97, 0xf9, 0x36, 0x46, 0xa5, 0x4e, 0x59, 0x56, 0x45, 0x44, 0xb3, + 0x13, 0x07, 0x85, 0x0b, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x4c, 0x52, 0x8b, 0x62, 0xfb, 0xae, 0x6b, 0x85, 0xff, 0x4b, 0x33, 0xb9, + 0x15, 0x48, 0xbf, 0x88, 0x22, 0x9b, 0x5b, 0x46, 0x98, 0x82, 0x68, 0x68, + 0x1d, 0x68, 0xc2, 0xb8, 0x7b, 0xf8, 0x10, 0x1d, 0xc6, 0x8d, 0x6a, 0x16, + 0x6d, 0x2a, 0x50, 0xa7, 0x8a, 0x3d, 0x41, 0x03, 0x8b, 0xc7, 0x06, 0x80, + 0xdb, 0x37, 0xc1, 0xaa, 0x4f, 0xb9, 0xa3, 0xc5, 0xaa, 0xff, 0x37, 0x67, + 0x19, 0x30, 0x0e, 0x0f, 0xe3, 0x05, 0x3c, 0x69, 0xdd, 0x29, 0x7c, 0x17, + 0xb7, 0x6f, 0x41, 0x66, 0xb3, 0x72, 0x95, 0x1c, 0xdd, 0x07, 0xb5, 0x54, + 0xd3, 0xd0, 0xc8, 0x6e, 0x72, 0xe1, 0x76, 0xb6, 0x87, 0x9b, 0x37, 0x11, + 0x5b, 0xea, 0x69, 0x52, 0x5e, 0x54, 0xa3, 0xcb, 0x3b, 0xad, 0x22, 0x3a, + 0x41, 0x81, 0x3d, 0xc1, 0x11, 0xb8, 0x7c, 0xf6, 0x5f, 0x73, 0x02, 0x6e, + 0xd4, 0xc9, 0x43, 0x7b, 0xdb, 0x4f, 0x78, 0x2e, 0xf7, 0xd2, 0xa8, 0x35, + 0xdd, 0x2c, 0x65, 0xcf, 0xc1, 0x0f, 0x48, 0xaf, 0x53, 0x20, 0x6a, 0x12, + 0x39, 0xad, 0xc1, 0x97, 0x81, 0x02, 0x8e, 0xe9, 0xd6, 0xd7, 0x90, 0x91, + 0xdb, 0xc4, 0x2e, 0x2a, 0x02, 0xbc, 0xb0, 0xa2, 0x85, 0x38, 0x05, 0x99, + 0x5c, 0xac, 0x71, 0xd2, 0x02, 0x04, 0xbe, 0xb1, 0x7a, 0x3c, 0x50, 0x0e, + 0xd0, 0x96, 0x2a, 0x09, 0x35, 0x84, 0xc5, 0x83, 0x25, 0x33, 0x82, 0x2f, + 0x23, 0x9d, 0x9f, 0x10, 0x22, 0x60, 0x50, 0x7d, 0x6c, 0x5b, 0x2a, 0xa9, + 0x5a, 0x83, 0x46, 0x02, 0x7a, 0x11, 0x55, 0x9c, 0x88, 0x3b, 0x33, 0xed, + 0x6a, 0x60, 0x5d, 0x9b, 0xc7, 0xb0, 0x9b, 0x06, 0xf5, 0x62, 0x18, 0xd7, + 0x57, 0x8c, 0x26, 0x2e, 0x73, 0x61, 0xd6, 0x4e, 0xeb, 0x48, 0x06, 0x46, + 0xb0, 0x93, 0x1a, 0x16, 0xa5, 0xa3, 0x80, 0x3f, 0x6c, 0xca, 0x86, 0xba, + 0x25, 0x86, 0x05, 0x11, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x4e, 0x15, 0x99, 0x98, 0x7a, 0xa8, 0x8f, 0x4b, 0x65, 0x29, 0x69, 0xf4, + 0xc3, 0xe6, 0x23, 0xeb, 0x1f, 0xe9, 0xd9, 0xdd, 0xd1, 0x49, 0x04, 0xea, + 0xb3, 0xe7, 0x94, 0x85, 0x99, 0xc6, 0x22, 0x25, 0x5b, 0xe1, 0x7a, 0x6a, + 0x72, 0x36, 0x5a, 0x58, 0x13, 0x32, 0x7f, 0xa5, 0x83, 0x29, 0x90, 0x17, + 0x03, 0xa4, 0xc6, 0x02, 0x1b, 0xe1, 0x96, 0x3e, 0x4d, 0xc5, 0x91, 0x62, + 0x0b, 0x9d, 0x00, 0x2c, 0x91, 0x73, 0xf9, 0x28, 0xdd, 0x1e, 0x2f, 0x6c, + 0x67, 0x13, 0xde, 0xa7, 0x8f, 0xfd, 0x30, 0x12, 0xbb, 0x88, 0x4f, 0x24, + 0x07, 0x63, 0xc7, 0xc7, 0x0c, 0x97, 0x42, 0xe1, 0xb6, 0x24, 0x89, 0x20, + 0x14, 0xc1, 0xcd, 0xc8, 0x5f, 0xb5, 0x3b, 0x66, 0x4d, 0x69, 0x8b, 0x5b, + 0xbd, 0x2f, 0xeb, 0xc7, 0x14, 0xab, 0x95, 0xdd, 0x08, 0x55, 0xfe, 0xfe, + 0x06, 0x52, 0xda, 0x17, 0xf5, 0x54, 0x04, 0x25, 0xfa, 0x42, 0xc1, 0xc1, + 0x37, 0x50, 0x84, 0x04, 0x15, 0x23, 0x5b, 0x51, 0x5a, 0x4f, 0x25, 0xd9, + 0x82, 0xd5, 0xac, 0x6a, 0xee, 0xae, 0xed, 0x5b, 0x9b, 0x12, 0x6a, 0x36, + 0xc7, 0x98, 0xd3, 0x1a, 0xfe, 0x8b, 0x8e, 0x9e, 0xcd, 0xaa, 0xda, 0x63, + 0x83, 0x07, 0x80, 0xed, 0x11, 0xc0, 0x82, 0xa3, 0xc9, 0xa2, 0x1c, 0x67, + 0x81, 0xe9, 0x7f, 0x67, 0xaa, 0xfb, 0x4d, 0x35, 0x67, 0x45, 0xb0, 0x2b, + 0xcb, 0x53, 0xf9, 0x18, 0xe3, 0x86, 0xde, 0xba, 0x31, 0xb5, 0x3a, 0xa4, + 0x83, 0x11, 0x93, 0x57, 0x31, 0x58, 0x55, 0xbf, 0x60, 0x70, 0x69, 0xa2, + 0x41, 0x9d, 0x52, 0xfa, 0x2c, 0xba, 0xb0, 0x0e, 0x29, 0xf6, 0xe5, 0x1c, + 0x92, 0xcf, 0x92, 0xf1, 0x09, 0x07, 0xe3, 0xee, 0xad, 0xf3, 0x69, 0x4c, + 0x7b, 0x20, 0x01, 0xc0, 0x04, 0xc4, 0x90, 0x39, 0x5f, 0xce, 0x3f, 0x18, + 0x13, 0x83, 0xbf, 0x1c, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xa4, 0xfb, 0x94, 0x68, 0xe0, 0xde, 0xe5, 0x93, 0xcb, 0x1a, 0xf0, 0x98, + 0x79, 0x9a, 0x64, 0xd3, 0x76, 0xe1, 0xae, 0x47, 0x45, 0x8e, 0xfc, 0xe6, + 0x0d, 0x28, 0x1c, 0xd0, 0xa1, 0x6d, 0x0f, 0x15, 0x0f, 0x87, 0x4c, 0xc5, + 0x44, 0xa5, 0x0e, 0x4f, 0x6e, 0xca, 0xd8, 0x90, 0xa2, 0x82, 0x42, 0xb2, + 0x63, 0x27, 0x58, 0x60, 0xfc, 0x91, 0x56, 0x12, 0x83, 0x83, 0x4e, 0x2d, + 0xf2, 0x27, 0x5f, 0x05, 0x56, 0xa0, 0xc0, 0x4e, 0x64, 0x09, 0x39, 0xfa, + 0x77, 0xd7, 0x6d, 0x85, 0x1c, 0x7a, 0xc6, 0x44, 0x8c, 0xa0, 0x4f, 0x58, + 0xa7, 0x59, 0x64, 0xda, 0x29, 0xda, 0x27, 0x18, 0xb3, 0x73, 0x8b, 0x1a, + 0x9c, 0x14, 0x58, 0xca, 0xc2, 0x94, 0x13, 0xcb, 0xde, 0x81, 0x6d, 0x6a, + 0x49, 0x98, 0xc2, 0xeb, 0x1e, 0x96, 0xe7, 0xfa, 0x1b, 0x93, 0xf5, 0x40, + 0x0e, 0x5e, 0x46, 0x64, 0x4e, 0xea, 0x67, 0x22, 0xf8, 0x46, 0xbe, 0x4d, + 0x27, 0x08, 0x5b, 0xf1, 0x27, 0xba, 0x94, 0x2b, 0xef, 0x77, 0xb1, 0xcb, + 0xab, 0x2e, 0x9b, 0x99, 0x67, 0xd0, 0x69, 0x1b, 0xcd, 0xac, 0x05, 0xbc, + 0xe9, 0x58, 0xc3, 0x07, 0xbd, 0x70, 0x54, 0x78, 0x01, 0xed, 0x85, 0xfa, + 0x04, 0x36, 0x49, 0xf5, 0xd0, 0x0c, 0x65, 0x89, 0xca, 0x7f, 0x64, 0xe8, + 0xb3, 0x70, 0x96, 0xed, 0x00, 0xdf, 0x35, 0xe6, 0xce, 0x0e, 0x65, 0x00, + 0xc4, 0x01, 0x0a, 0x02, 0x41, 0x61, 0x3a, 0x4a, 0x6f, 0xb5, 0xd8, 0xf1, + 0xe2, 0x90, 0xf7, 0xa5, 0xc9, 0xf5, 0x57, 0xcd, 0xb0, 0x36, 0x84, 0x24, + 0x47, 0x78, 0xc0, 0x5a, 0xac, 0xf6, 0x3f, 0x22, 0xf3, 0xc5, 0x06, 0x28, + 0x36, 0xda, 0x28, 0xe9, 0xc2, 0x01, 0x8c, 0x65, 0xb8, 0x15, 0xae, 0xad, + 0xd8, 0x83, 0x0d, 0x87, 0x3a, 0xea, 0x11, 0x0a, 0x72, 0x31, 0xdd, 0x26, + 0x19, 0xda, 0xdf, 0x13, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x72, 0x2c, 0xde, 0xdf, 0x47, 0xaa, 0x0f, 0x9a, 0xe2, 0xd5, 0x67, 0x0e, + 0x07, 0x1d, 0x80, 0x6c, 0x30, 0x1a, 0x83, 0x3f, 0x22, 0x85, 0xca, 0x2c, + 0x6d, 0xbd, 0xcc, 0x0a, 0x98, 0xa7, 0xd9, 0x0f, 0xb8, 0xf2, 0x10, 0x40, + 0xd1, 0x5a, 0x7b, 0x23, 0x6e, 0xa1, 0xaf, 0x3a, 0xaa, 0xc2, 0x05, 0x6c, + 0x5f, 0xac, 0xdb, 0xc0, 0xe7, 0x91, 0xe8, 0x4f, 0xb9, 0xfd, 0x3d, 0xb3, + 0xef, 0xd9, 0x54, 0x0a, 0x94, 0x2f, 0x3a, 0x81, 0x66, 0x9d, 0x04, 0x7c, + 0x76, 0x69, 0x58, 0x19, 0x5e, 0x6b, 0x44, 0x14, 0xdd, 0x9c, 0x68, 0xa2, + 0xe8, 0xc5, 0xe6, 0x9b, 0x19, 0x44, 0x75, 0xee, 0x9d, 0xc4, 0xad, 0x00, + 0x17, 0x1e, 0x81, 0x2e, 0x20, 0x15, 0x44, 0x8e, 0xf8, 0xbf, 0x98, 0xd0, + 0x03, 0x9c, 0x66, 0x5e, 0x40, 0x6e, 0x9f, 0xc0, 0x29, 0xb1, 0xf9, 0xeb, + 0x17, 0x31, 0x44, 0x81, 0x84, 0xb6, 0x5b, 0x2e, 0x5f, 0xb7, 0xe5, 0x4b, + 0xcf, 0xa4, 0x81, 0xcf, 0xf3, 0xf2, 0xaa, 0x98, 0xca, 0x4c, 0xf7, 0x45, + 0xa7, 0xef, 0xf7, 0x02, 0x1d, 0x5e, 0xcc, 0xe3, 0xee, 0xa9, 0x83, 0x24, + 0xde, 0x7d, 0x81, 0x10, 0x44, 0xc3, 0xac, 0xb2, 0xd5, 0x1e, 0x8c, 0xbe, + 0xbb, 0x9f, 0x11, 0xfa, 0xdb, 0x42, 0xda, 0x42, 0xeb, 0xb3, 0x36, 0xe4, + 0x9b, 0x6d, 0x67, 0x63, 0x95, 0x88, 0x2a, 0x8c, 0x50, 0x0c, 0x6f, 0x23, + 0x47, 0xdb, 0x1a, 0x14, 0xcc, 0x88, 0x89, 0x08, 0x4b, 0xc6, 0xeb, 0x46, + 0x75, 0x38, 0x05, 0xac, 0x34, 0xdd, 0xd0, 0xc4, 0x73, 0x9f, 0x33, 0xd9, + 0x5c, 0x97, 0x19, 0xc6, 0xbd, 0x1c, 0xc7, 0x03, 0x14, 0xe2, 0xc8, 0x54, + 0xa7, 0x5d, 0xa0, 0x56, 0x3d, 0xf1, 0xaf, 0xeb, 0xc6, 0x65, 0xd9, 0xe2, + 0x1b, 0xd8, 0xe9, 0xbc, 0x9b, 0x57, 0x99, 0xb6, 0x83, 0x1d, 0xaf, 0xfa, + 0xd0, 0x06, 0x33, 0x2b, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xf0, 0xa9, 0xa9, 0xd9, 0xad, 0x64, 0x8c, 0x40, 0x8a, 0x7f, 0x24, 0xca, + 0x51, 0xb6, 0x6a, 0xe1, 0x09, 0x42, 0xa4, 0x30, 0x18, 0x2a, 0x79, 0x6f, + 0x36, 0x94, 0x54, 0xda, 0x8e, 0x36, 0xc2, 0x28, 0xd1, 0x8f, 0x35, 0x75, + 0xde, 0x1e, 0xa2, 0x70, 0x1e, 0x22, 0x4e, 0xb6, 0xad, 0x3e, 0xcf, 0x54, + 0x58, 0xb6, 0x67, 0x00, 0xb8, 0xcf, 0x4a, 0xb5, 0x7f, 0x72, 0xde, 0xe2, + 0xde, 0x4e, 0xef, 0x00, 0xc0, 0x84, 0x98, 0xa3, 0xd0, 0x43, 0xbb, 0xee, + 0x48, 0xf2, 0xe3, 0xe8, 0x4f, 0x37, 0xa7, 0x09, 0xd6, 0x10, 0xd7, 0xe9, + 0xe1, 0x7a, 0x8a, 0xf1, 0x5f, 0x7e, 0xfc, 0x26, 0x05, 0xe1, 0xca, 0x06, + 0xa6, 0x08, 0x6e, 0x66, 0xd3, 0xaa, 0x9d, 0x63, 0x96, 0x81, 0x30, 0xcb, + 0x11, 0x3a, 0x8e, 0x29, 0x1e, 0xde, 0x0c, 0xda, 0x37, 0x26, 0xda, 0x70, + 0x30, 0x3e, 0xbe, 0xc5, 0x47, 0x52, 0xc2, 0x18, 0xfb, 0x9b, 0x64, 0x9c, + 0xfd, 0x30, 0x63, 0xc0, 0x8a, 0x37, 0x9f, 0x61, 0x86, 0xe7, 0xe3, 0x2c, + 0x91, 0x58, 0xd2, 0xe2, 0xf4, 0x6c, 0xe9, 0x20, 0x8b, 0xf5, 0xb0, 0x24, + 0x27, 0x28, 0xed, 0x29, 0xcb, 0x81, 0x65, 0x5e, 0x6f, 0xe1, 0xc2, 0x82, + 0xfe, 0xca, 0xf1, 0xd5, 0x77, 0x44, 0xdb, 0xbe, 0x74, 0xd7, 0xee, 0xd7, + 0xdd, 0xbc, 0xe7, 0x8a, 0x39, 0x31, 0x7c, 0x59, 0x89, 0x6c, 0x84, 0x07, + 0xaa, 0x39, 0xef, 0xa5, 0x2b, 0x6c, 0x54, 0x73, 0xc7, 0x0d, 0x46, 0x4d, + 0x19, 0x36, 0x1a, 0xf0, 0x80, 0xa1, 0x3a, 0xdf, 0x4d, 0xa5, 0x29, 0xdd, + 0x1e, 0xbc, 0xca, 0x4b, 0x3e, 0xfa, 0x6a, 0x13, 0xf1, 0x47, 0xd0, 0x7b, + 0x79, 0x5d, 0x4d, 0x7e, 0x92, 0x30, 0x2c, 0x54, 0xdc, 0xf8, 0x05, 0x79, + 0x89, 0xef, 0xa2, 0x78, 0x67, 0xb2, 0x96, 0x45, 0x19, 0xd3, 0x3a, 0x5e, + 0xe8, 0x9d, 0x19, 0x04, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xab, 0xa0, 0xcd, 0xba, 0x7a, 0x07, 0x6f, 0x7e, 0xbf, 0xce, 0x9b, 0x30, + 0x21, 0x9f, 0x28, 0xe8, 0x09, 0xe4, 0xdf, 0x32, 0x5b, 0x0d, 0x34, 0x71, + 0xa1, 0xf0, 0x92, 0xe4, 0xc6, 0xd4, 0xcb, 0x29, 0xc1, 0x49, 0x6e, 0xf4, + 0x96, 0xd5, 0x67, 0x7b, 0x4f, 0x7b, 0x21, 0x39, 0x9b, 0x76, 0x46, 0x5c, + 0xf5, 0xdc, 0x11, 0xd3, 0x43, 0x07, 0xe8, 0x75, 0xd6, 0x6e, 0x76, 0xc6, + 0x66, 0x0a, 0x0a, 0x0c, 0x6e, 0x8f, 0x7c, 0x1c, 0x2b, 0xad, 0x6e, 0x48, + 0x69, 0x81, 0x4c, 0x7f, 0xcc, 0xa6, 0x2a, 0xb0, 0x3b, 0xfc, 0xd8, 0x2f, + 0xc5, 0x45, 0xd4, 0x0d, 0x2d, 0xb6, 0xe9, 0xd6, 0x7f, 0x6a, 0x3b, 0x20, + 0x0a, 0x57, 0x41, 0xde, 0xfa, 0x9b, 0x52, 0x5b, 0x6a, 0x0b, 0x42, 0x0d, + 0x3b, 0x72, 0x40, 0xb1, 0xa3, 0x66, 0x77, 0xcc, 0x00, 0xd6, 0x81, 0x2f, + 0xc2, 0xfa, 0xe2, 0x10, 0x32, 0x24, 0x71, 0x29, 0xbf, 0xb0, 0x8f, 0x33, + 0x5a, 0x67, 0x95, 0xd2, 0x8c, 0x2a, 0x3f, 0x78, 0xa7, 0xc7, 0x0e, 0x1a, + 0x92, 0x29, 0x38, 0xa4, 0x45, 0x46, 0x0d, 0x30, 0xba, 0x10, 0x0b, 0x35, + 0x28, 0xb0, 0x63, 0x0c, 0xe2, 0x5b, 0xc0, 0xbf, 0x42, 0x52, 0xab, 0x86, + 0xc6, 0xfd, 0xb2, 0x69, 0x1c, 0xc7, 0x47, 0x68, 0x61, 0x3c, 0xcb, 0x49, + 0x13, 0x37, 0x3d, 0x6e, 0x49, 0x8e, 0xd2, 0x65, 0x44, 0x7a, 0x07, 0x2f, + 0x2d, 0x09, 0x9e, 0x23, 0x30, 0x20, 0x30, 0xe8, 0x04, 0xac, 0x2b, 0x17, + 0xf5, 0xe5, 0x3b, 0x3b, 0xee, 0x59, 0x46, 0xea, 0xa7, 0x07, 0x16, 0xdf, + 0x0b, 0xf8, 0xb2, 0x5e, 0xf3, 0x23, 0xb9, 0x1a, 0x56, 0x94, 0xb7, 0xc6, + 0x86, 0x86, 0xea, 0x13, 0xb4, 0xe6, 0xaf, 0xf3, 0xdb, 0x13, 0x6d, 0x59, + 0x83, 0xe2, 0xd3, 0x7f, 0x88, 0x60, 0x0b, 0x3e, 0x63, 0xfc, 0x4f, 0x7d, + 0xb6, 0xe4, 0x0b, 0x14, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xd9, 0xc3, 0x56, 0x5c, 0x96, 0x57, 0xbf, 0x1a, 0x8f, 0x7a, 0xcd, 0x95, + 0xdf, 0xd9, 0x3e, 0xc0, 0x2c, 0x9c, 0xd1, 0xf5, 0xf5, 0x9f, 0xd7, 0x7b, + 0x36, 0x07, 0xce, 0x3a, 0xaa, 0x03, 0x18, 0x17, 0x51, 0x11, 0x2f, 0x89, + 0xcb, 0x42, 0x10, 0x78, 0x4a, 0x66, 0xc3, 0x5f, 0x9b, 0x52, 0x3c, 0x2c, + 0x27, 0x90, 0x28, 0x66, 0xf0, 0xf9, 0xcf, 0xa7, 0x71, 0xb7, 0x07, 0x68, + 0x74, 0x0f, 0xa4, 0x26, 0x95, 0x66, 0x9c, 0xed, 0x50, 0xf2, 0xc3, 0xdf, + 0x67, 0xa4, 0x9a, 0x94, 0x7b, 0xb9, 0x61, 0xd8, 0x31, 0x49, 0x0a, 0x69, + 0x3c, 0x84, 0x80, 0xc9, 0x55, 0x39, 0x73, 0xed, 0x1f, 0x9c, 0xa3, 0x14, + 0xbc, 0xb6, 0x92, 0x36, 0x20, 0x1b, 0x6c, 0xab, 0xcd, 0x36, 0x21, 0x0b, + 0xf6, 0xaa, 0x6e, 0xd6, 0x17, 0x99, 0xde, 0xbb, 0xff, 0x44, 0x14, 0x59, + 0xf5, 0xce, 0x76, 0x61, 0xdc, 0x8e, 0x31, 0x0e, 0xec, 0xb2, 0x01, 0xf9, + 0x60, 0x20, 0x98, 0x4a, 0x47, 0x86, 0x3d, 0xea, 0xcd, 0x65, 0x1e, 0xb3, + 0x3a, 0x68, 0x43, 0x5c, 0x28, 0x47, 0xbc, 0xff, 0x38, 0x92, 0xe2, 0x9c, + 0x48, 0x40, 0x7d, 0x2b, 0x4f, 0xd2, 0xb7, 0x3b, 0x1f, 0xa5, 0x5d, 0x44, + 0x73, 0x69, 0x10, 0x8d, 0x38, 0xfb, 0x93, 0x3f, 0xdb, 0x96, 0x55, 0xa9, + 0xa0, 0xe6, 0xfa, 0xa9, 0x3b, 0xe0, 0xca, 0xdf, 0x90, 0xe9, 0xdc, 0x03, + 0x82, 0x1c, 0x37, 0xf3, 0xa2, 0x2c, 0x57, 0xf4, 0x1e, 0x5c, 0x94, 0x70, + 0xcf, 0xff, 0xdd, 0x58, 0x31, 0x34, 0x02, 0x38, 0x9f, 0xd9, 0x03, 0x28, + 0xdf, 0xbb, 0x47, 0x2d, 0x93, 0xf3, 0xdf, 0x05, 0x1f, 0x5a, 0x31, 0x7e, + 0x10, 0xea, 0xbb, 0xec, 0x90, 0x5f, 0xb2, 0xb6, 0x20, 0x3b, 0x87, 0xe6, + 0x3f, 0x1e, 0xa0, 0x8c, 0x35, 0xe0, 0xf0, 0xbf, 0x92, 0x25, 0xf8, 0xd9, + 0x33, 0x7b, 0x89, 0x2a, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x91, 0x34, 0x30, 0x8f, 0x7a, 0x5b, 0xf6, 0x69, 0x57, 0x41, 0x58, 0x55, + 0x14, 0x3c, 0xe2, 0x71, 0xa8, 0x3f, 0x6f, 0xac, 0x0f, 0x3b, 0xc8, 0xef, + 0x73, 0xb4, 0xd4, 0x8b, 0xe4, 0xb2, 0xc5, 0x2e, 0x1e, 0x4d, 0x35, 0x45, + 0x17, 0x8b, 0x07, 0x3f, 0x2f, 0xa5, 0xfe, 0x48, 0x1a, 0x80, 0xfa, 0x49, + 0x86, 0xf5, 0x2c, 0x56, 0x03, 0x00, 0x78, 0x5c, 0xcf, 0x47, 0x15, 0xb6, + 0xf1, 0x4b, 0x25, 0x1d, 0x8e, 0x7a, 0x42, 0xf6, 0x88, 0xfc, 0xe1, 0x43, + 0x04, 0x26, 0x2a, 0x14, 0xdf, 0x93, 0xd2, 0x0c, 0xc2, 0xd4, 0x49, 0x07, + 0xc4, 0x8c, 0xde, 0x84, 0x2a, 0x9a, 0x30, 0x1c, 0x37, 0x56, 0xa3, 0x16, + 0x7f, 0xac, 0x43, 0x01, 0x64, 0xb2, 0x16, 0xa0, 0x87, 0x9e, 0x4e, 0x80, + 0xb0, 0xba, 0x6b, 0x1a, 0x8e, 0xc7, 0xdf, 0xb9, 0xda, 0x0a, 0x93, 0xf1, + 0x90, 0xdd, 0x0f, 0x5d, 0xe9, 0x2c, 0xa3, 0x27, 0x6e, 0xdc, 0x5d, 0x97, + 0x77, 0xa5, 0x0e, 0x9b, 0x98, 0x24, 0xc4, 0xe9, 0x06, 0xbe, 0xc4, 0xe5, + 0xc6, 0xf0, 0x1d, 0x93, 0x87, 0x2c, 0x92, 0x1e, 0xed, 0x71, 0xfa, 0xec, + 0x9a, 0xb3, 0x5a, 0x27, 0x09, 0x7a, 0x0e, 0x92, 0x9e, 0x61, 0x85, 0xcf, + 0x59, 0x49, 0xd5, 0x77, 0x02, 0x7e, 0x67, 0xa0, 0xe4, 0x30, 0x40, 0xdf, + 0xe0, 0xb8, 0x03, 0xa9, 0x19, 0x89, 0xd7, 0x31, 0x7b, 0x9c, 0x26, 0x19, + 0x6e, 0x1d, 0x1a, 0x85, 0xa9, 0xdb, 0x0c, 0x4d, 0x52, 0x72, 0x37, 0xd6, + 0xbf, 0x6d, 0xe8, 0xa9, 0xdc, 0xa0, 0x2b, 0x45, 0x7b, 0x1e, 0xbc, 0xb5, + 0x4b, 0x25, 0xaf, 0x2a, 0x8f, 0x64, 0xe6, 0x0d, 0xb7, 0x66, 0xe3, 0x27, + 0xda, 0x7c, 0x86, 0xce, 0xc9, 0x23, 0x92, 0x89, 0x9d, 0x85, 0x7d, 0xd9, + 0xf4, 0x06, 0xd2, 0x75, 0xec, 0x2c, 0xc7, 0x37, 0xca, 0x60, 0x06, 0xe7, + 0xb8, 0xbb, 0xa8, 0x15, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x2f, 0x4c, 0xb0, 0x84, 0xf8, 0x86, 0x5a, 0xd0, 0xca, 0xc7, 0x56, 0x61, + 0xc9, 0xa3, 0xe5, 0xbd, 0x2d, 0xd8, 0xc4, 0x03, 0x6c, 0x99, 0x2a, 0xb3, + 0x0d, 0x8e, 0xa2, 0x58, 0xc0, 0x9a, 0x15, 0x09, 0x07, 0x19, 0x95, 0x34, + 0x4d, 0x5d, 0x76, 0x0a, 0x28, 0x05, 0xee, 0xbd, 0xa7, 0x97, 0xba, 0xb9, + 0x28, 0x3f, 0xb3, 0xa5, 0x68, 0xcc, 0xa3, 0x89, 0x98, 0x9c, 0x85, 0x65, + 0x93, 0xe6, 0x0c, 0x2d, 0xe9, 0x4b, 0xea, 0x25, 0x0d, 0xb7, 0x1e, 0x83, + 0x33, 0x8a, 0xe0, 0xf1, 0x78, 0x1b, 0xf5, 0x2b, 0xb0, 0x9c, 0x7d, 0xd6, + 0x71, 0x33, 0xeb, 0x21, 0x4b, 0xa9, 0x25, 0x38, 0x89, 0xaa, 0x7c, 0x14, + 0xb8, 0xae, 0x7e, 0x5e, 0x0f, 0x16, 0x81, 0xa4, 0x3b, 0x6d, 0x56, 0x12, + 0x71, 0x99, 0xa3, 0x5b, 0x9c, 0x72, 0xf1, 0x05, 0xd7, 0xcf, 0x4d, 0x66, + 0x10, 0xe5, 0x4a, 0xcb, 0x67, 0xea, 0xd6, 0x01, 0xac, 0x1f, 0xa4, 0x82, + 0x59, 0x29, 0xa3, 0x41, 0x05, 0x25, 0x9a, 0x4c, 0xe0, 0xc2, 0x20, 0x76, + 0x64, 0x34, 0x3a, 0xed, 0x97, 0x27, 0x62, 0xa1, 0xf4, 0xf4, 0xde, 0x45, + 0x36, 0x27, 0x3e, 0x1a, 0x49, 0x4c, 0x16, 0xb3, 0x4e, 0xe1, 0x32, 0x2f, + 0xba, 0xc0, 0x68, 0x61, 0x83, 0x61, 0x0d, 0x34, 0xe2, 0xf4, 0x21, 0x5a, + 0xe1, 0x94, 0xd5, 0xa8, 0x27, 0x93, 0xae, 0x61, 0xc1, 0xcd, 0xef, 0x28, + 0x5d, 0x24, 0x37, 0x5b, 0x19, 0x5d, 0xd8, 0xf2, 0xd0, 0x97, 0xb0, 0xb3, + 0x72, 0xa1, 0x22, 0x3d, 0x62, 0xf1, 0xc3, 0x79, 0x09, 0x40, 0x93, 0xbc, + 0xa4, 0x42, 0x93, 0x1c, 0x44, 0x97, 0x13, 0x23, 0xb4, 0x99, 0xaf, 0x53, + 0x1e, 0x04, 0x5d, 0x33, 0xf8, 0xc9, 0x9b, 0xb7, 0x1a, 0x51, 0x07, 0xf1, + 0xc3, 0xd6, 0xb2, 0xab, 0x28, 0xbe, 0xbb, 0x56, 0x68, 0x40, 0x1c, 0x0e, + 0x5c, 0xb8, 0xf7, 0x25, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x3b, 0xb6, 0x6c, 0x8b, 0x8a, 0xae, 0x76, 0xb7, 0xea, 0x0b, 0x68, 0x3a, + 0xc6, 0xfa, 0xe4, 0x13, 0xbb, 0x45, 0xf5, 0x46, 0x3f, 0xcf, 0xa7, 0x48, + 0x26, 0x2f, 0xf6, 0x3c, 0x6a, 0x4d, 0xad, 0x24, 0x9a, 0x11, 0x94, 0x2c, + 0xc9, 0x3d, 0x07, 0xe9, 0xde, 0x47, 0x1d, 0xea, 0x8c, 0x2c, 0x5f, 0x2f, + 0x6c, 0x8c, 0xf2, 0xd1, 0x8d, 0x69, 0x98, 0xe3, 0xa6, 0xf3, 0x3b, 0x45, + 0x1c, 0xd5, 0x9e, 0x2f, 0xdf, 0x6e, 0xe8, 0xbb, 0xbe, 0x02, 0x0b, 0x02, + 0xdf, 0xfd, 0x67, 0x6b, 0xd4, 0x84, 0x6c, 0x2d, 0xca, 0x87, 0x92, 0xf9, + 0x22, 0x12, 0x4e, 0x42, 0x92, 0x88, 0x7e, 0x2b, 0xc4, 0x5b, 0x7c, 0x21, + 0x46, 0xa7, 0x86, 0xa4, 0x8d, 0x33, 0x31, 0xc4, 0x10, 0x30, 0xc7, 0x11, + 0xac, 0x3c, 0x3d, 0xf3, 0xea, 0xe8, 0xa6, 0x97, 0xf5, 0x04, 0x2a, 0x63, + 0xa5, 0x61, 0x67, 0x68, 0xf5, 0x3d, 0x34, 0x06, 0x84, 0x1f, 0x5d, 0xab, + 0xa2, 0xf6, 0xa8, 0x68, 0x20, 0x53, 0x84, 0xd8, 0xb6, 0xae, 0xff, 0x1d, + 0x8b, 0xac, 0xc4, 0x30, 0x1d, 0xf0, 0x38, 0x9b, 0xe3, 0xa0, 0x35, 0x50, + 0xb2, 0x87, 0x7d, 0x19, 0xe8, 0xe3, 0xc2, 0x05, 0x6c, 0xd5, 0xd9, 0xc5, + 0x5a, 0xe3, 0xa1, 0xfc, 0xf1, 0x5f, 0xa7, 0x84, 0xbd, 0x7b, 0xa5, 0x1c, + 0x8b, 0xb4, 0x0d, 0x59, 0xc7, 0xa3, 0x06, 0x18, 0xf7, 0x6e, 0x51, 0x25, + 0x30, 0x11, 0xe7, 0x79, 0xbb, 0xcc, 0x23, 0xc8, 0xd8, 0x59, 0x20, 0x7e, + 0x6f, 0x31, 0x31, 0x87, 0x8d, 0x60, 0x5a, 0xcb, 0x77, 0xaf, 0x74, 0x38, + 0x72, 0xda, 0x67, 0x2b, 0x30, 0x78, 0x37, 0x28, 0x16, 0x45, 0x71, 0xf8, + 0x47, 0x93, 0x5a, 0xe2, 0x28, 0x45, 0x58, 0x61, 0xd0, 0x31, 0x41, 0x6a, + 0xc0, 0x92, 0xa1, 0xb7, 0x10, 0x4c, 0x8e, 0xcd, 0xaa, 0x5b, 0x10, 0xa9, + 0x00, 0x22, 0x37, 0x1e, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x67, 0xd5, 0x4f, 0x45, 0xfb, 0x1b, 0x77, 0xc9, 0xbd, 0x07, 0xab, 0x79, + 0x5a, 0x34, 0x20, 0x91, 0xb9, 0xbc, 0x9f, 0xb5, 0xbf, 0xf2, 0x73, 0xda, + 0x69, 0xfe, 0xa5, 0xaf, 0x21, 0xe8, 0x86, 0x2e, 0x60, 0xe6, 0xf6, 0x5d, + 0xb8, 0x72, 0x30, 0x54, 0x2d, 0x01, 0xf3, 0x92, 0x87, 0x8d, 0x75, 0xf8, + 0x6a, 0xbd, 0x84, 0xb7, 0xa6, 0x64, 0x9d, 0x8c, 0x2c, 0xed, 0x12, 0xa3, + 0x30, 0x56, 0x1e, 0x1a, 0x85, 0xcf, 0xd9, 0x08, 0x7f, 0xa0, 0x13, 0x55, + 0x2a, 0x91, 0xc7, 0x6a, 0x31, 0x3f, 0x9e, 0x9f, 0x21, 0x24, 0xce, 0x58, + 0xd8, 0x9e, 0x47, 0xf8, 0x2d, 0x74, 0xab, 0xa4, 0x61, 0xf2, 0xc2, 0x2e, + 0xd6, 0x8d, 0x18, 0x0c, 0x07, 0x9a, 0x1f, 0x8e, 0x61, 0x18, 0x41, 0x1b, + 0x7f, 0xd2, 0x4a, 0xe9, 0xa7, 0x1b, 0x09, 0xe2, 0x21, 0x4f, 0xfb, 0x48, + 0x79, 0x6b, 0x04, 0xc7, 0x0a, 0xed, 0x5b, 0x19, 0x17, 0xc9, 0x3c, 0x7b, + 0x84, 0x4c, 0x25, 0x33, 0xd0, 0xcc, 0x7b, 0x9e, 0x80, 0xd9, 0x15, 0xdf, + 0x47, 0xda, 0x70, 0x1a, 0x57, 0xba, 0x46, 0x82, 0xeb, 0x54, 0x0a, 0x1e, + 0x87, 0xe9, 0x0e, 0x2d, 0x03, 0x06, 0x38, 0x16, 0x58, 0x7e, 0xf6, 0x84, + 0x3a, 0x72, 0x4a, 0xf8, 0x5e, 0xf4, 0xef, 0xd4, 0x44, 0x56, 0xea, 0x39, + 0xe7, 0x83, 0x10, 0xd7, 0x40, 0x1a, 0x8e, 0x4b, 0x44, 0x37, 0xcf, 0x0c, + 0xf2, 0x7e, 0x51, 0x3f, 0xa9, 0x1a, 0x82, 0x64, 0xf3, 0x41, 0x2e, 0x86, + 0x0a, 0xd6, 0x38, 0x32, 0xb3, 0x52, 0x2a, 0x89, 0x34, 0xa3, 0x87, 0x67, + 0xa8, 0xeb, 0x4e, 0x5f, 0x8f, 0x76, 0x9e, 0x0a, 0xa7, 0xf8, 0x77, 0x90, + 0xfb, 0x39, 0x99, 0xf8, 0x03, 0x98, 0x08, 0x11, 0xaa, 0xe5, 0x47, 0x03, + 0x69, 0x57, 0x59, 0xff, 0x80, 0xbc, 0x33, 0x78, 0x14, 0x1c, 0xbd, 0x30, + 0x41, 0x90, 0x23, 0x08, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x63, 0xc7, 0xfc, 0xc0, 0x38, 0x7f, 0x8b, 0x2c, 0x74, 0xa8, 0x15, 0x9b, + 0xda, 0xfb, 0xcf, 0x40, 0x77, 0x9b, 0x3f, 0x20, 0xe4, 0xb5, 0x32, 0x94, + 0x43, 0x75, 0xd6, 0xfe, 0x2c, 0xcf, 0x08, 0x0d, 0x21, 0xd3, 0x1f, 0xf6, + 0xf7, 0xdd, 0x55, 0xea, 0x39, 0x9e, 0x8b, 0x14, 0x1b, 0xfd, 0xbf, 0xcb, + 0x9b, 0x43, 0x6e, 0xb4, 0x8c, 0x50, 0x79, 0x01, 0xd1, 0x1a, 0xe4, 0xd4, + 0x2c, 0x5e, 0x01, 0x28, 0x49, 0x4f, 0x35, 0x2c, 0x1b, 0x66, 0xdd, 0x58, + 0xf8, 0x09, 0xe4, 0xfb, 0xfc, 0xa6, 0x7d, 0x86, 0xab, 0xfa, 0x2d, 0x68, + 0x3c, 0x9f, 0xfa, 0x92, 0xac, 0x4c, 0x05, 0xdb, 0xd9, 0x19, 0x39, 0x04, + 0x0b, 0xb1, 0x82, 0xed, 0x05, 0x89, 0x0d, 0xd6, 0xae, 0x90, 0xce, 0xb1, + 0xb4, 0x03, 0x8d, 0xcd, 0x48, 0x49, 0xba, 0x2a, 0x47, 0x36, 0x5f, 0x08, + 0x13, 0x61, 0xc5, 0xd7, 0xd6, 0x38, 0x41, 0x30, 0x83, 0xcb, 0x46, 0x67, + 0xb3, 0x24, 0xea, 0x00, 0xbf, 0x62, 0xd6, 0xcd, 0x00, 0xa4, 0xf1, 0x98, + 0xfd, 0x3d, 0x6a, 0x79, 0xb1, 0xb2, 0x49, 0xca, 0x94, 0x14, 0x8f, 0x37, + 0xc8, 0x0f, 0x11, 0x24, 0xe8, 0x9e, 0xc6, 0x03, 0x77, 0xcc, 0xed, 0xc7, + 0x10, 0x05, 0xe3, 0xb5, 0x5e, 0xa1, 0x78, 0x94, 0x00, 0xb3, 0x5e, 0xed, + 0x4c, 0xf4, 0xa4, 0xf8, 0xe2, 0xdd, 0x71, 0xb6, 0x19, 0x2a, 0x03, 0x24, + 0x76, 0xb5, 0x6c, 0xda, 0xf7, 0x6b, 0x74, 0x3a, 0xf6, 0xef, 0x2c, 0xf4, + 0x64, 0x77, 0x5b, 0x9d, 0x80, 0xf0, 0x02, 0x0c, 0x32, 0x4f, 0xa4, 0xa9, + 0xc5, 0xbd, 0x60, 0x9a, 0x33, 0xf1, 0x2d, 0x0f, 0xa4, 0x7b, 0xf4, 0x93, + 0x04, 0x00, 0x56, 0x6f, 0x96, 0xe9, 0xa1, 0x34, 0x8c, 0xc1, 0x5f, 0x41, + 0x10, 0xf3, 0x53, 0x85, 0x73, 0x48, 0xe1, 0x04, 0x44, 0x36, 0xbc, 0x6c, + 0x77, 0x68, 0xae, 0x28, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x87, 0xb0, 0x14, 0x1f, 0x67, 0xee, 0x27, 0xc1, 0xa7, 0x02, 0x2c, 0xa5, + 0x8c, 0x99, 0x0b, 0x01, 0xb5, 0xf8, 0x5d, 0xed, 0xe0, 0xd0, 0xf3, 0x96, + 0xa7, 0xc5, 0x18, 0xe5, 0x37, 0x6b, 0x37, 0x0b, 0x94, 0x6c, 0xf7, 0xd4, + 0x36, 0x9e, 0xed, 0xdc, 0xe8, 0xd4, 0x90, 0x49, 0x08, 0x8c, 0x55, 0x6d, + 0x02, 0x7c, 0xb8, 0xf0, 0x88, 0xa0, 0xcd, 0x0e, 0xc4, 0xbf, 0x9c, 0x9a, + 0x70, 0x89, 0x57, 0x1a, 0xe9, 0x54, 0x68, 0xf9, 0xf8, 0xcc, 0xf4, 0xb6, + 0x40, 0xa3, 0x71, 0x24, 0x12, 0xc6, 0x18, 0x19, 0x5b, 0xb4, 0xa3, 0xc5, + 0x33, 0x2d, 0xd2, 0xeb, 0x04, 0x21, 0x11, 0x94, 0x82, 0xee, 0x34, 0x27, + 0x8e, 0xac, 0x2f, 0x79, 0x30, 0x51, 0x88, 0x3d, 0x52, 0xb4, 0x2a, 0x67, + 0x00, 0x51, 0xce, 0xdc, 0x57, 0x55, 0xd4, 0x80, 0x6c, 0xac, 0x99, 0xc2, + 0x83, 0x2c, 0x82, 0xc1, 0xcd, 0xb4, 0xa7, 0x01, 0x3d, 0x3e, 0x9e, 0xce, + 0x9e, 0x3c, 0x38, 0xc9, 0x81, 0xdf, 0xde, 0x6c, 0x1c, 0xe8, 0xba, 0xa2, + 0x99, 0x0a, 0x25, 0x18, 0xcd, 0x74, 0xad, 0xce, 0xa8, 0xa3, 0xb4, 0xa7, + 0xaa, 0x61, 0x59, 0x18, 0xc3, 0x8b, 0x6a, 0x1c, 0xdc, 0x8d, 0x33, 0x0e, + 0x94, 0x40, 0x89, 0x3e, 0xc1, 0xa7, 0xa5, 0x44, 0x6f, 0xf9, 0xbc, 0x86, + 0x7b, 0x10, 0xe9, 0x0b, 0x54, 0x95, 0xc1, 0xe0, 0x26, 0x6d, 0xfc, 0x2f, + 0x86, 0x1f, 0x57, 0x09, 0xba, 0xd7, 0x78, 0x38, 0x78, 0x1f, 0x10, 0xba, + 0x29, 0x73, 0x93, 0xdc, 0x6a, 0x8f, 0xd9, 0xea, 0xc8, 0xd1, 0x9b, 0xf2, + 0x17, 0x75, 0x7e, 0xfd, 0x2a, 0x1f, 0x79, 0x04, 0x66, 0xa6, 0x53, 0xcc, + 0x14, 0xb3, 0x17, 0x5a, 0xcf, 0xf6, 0xb4, 0x49, 0xd2, 0x72, 0xcf, 0x9e, + 0x25, 0xd1, 0x2d, 0xe3, 0xf7, 0x5a, 0x2b, 0xd4, 0x14, 0xb8, 0x81, 0x41, + 0x38, 0x90, 0x02, 0x12, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x4d, 0xac, 0x5d, 0xd6, 0xf4, 0x68, 0xc1, 0x65, 0xa4, 0x85, 0x3b, 0x81, + 0xe7, 0xb3, 0xfb, 0x53, 0x63, 0x02, 0x0e, 0x82, 0xdf, 0xe8, 0x1b, 0xac, + 0xe8, 0xad, 0x6e, 0xf8, 0x18, 0xcc, 0x8b, 0x1a, 0x63, 0xe0, 0xad, 0x65, + 0xd1, 0x0d, 0xb1, 0xef, 0x77, 0x3e, 0x2c, 0x91, 0x17, 0x4a, 0x35, 0x88, + 0xb5, 0x18, 0x8c, 0xa3, 0x44, 0x75, 0x8b, 0xe1, 0xdf, 0xa6, 0x36, 0xda, + 0xca, 0xc5, 0xc4, 0x03, 0x5d, 0x90, 0xdd, 0x6d, 0xec, 0x44, 0xbf, 0x32, + 0x50, 0xab, 0x2e, 0x84, 0x7e, 0x21, 0x47, 0xfd, 0xd0, 0x5f, 0x80, 0x4b, + 0xf4, 0x4e, 0xa7, 0x18, 0x8d, 0xe8, 0xbb, 0xeb, 0xc7, 0xd7, 0x2a, 0x13, + 0xad, 0xc7, 0xb0, 0x16, 0x58, 0x1e, 0x30, 0x54, 0x84, 0x4b, 0xff, 0x50, + 0x12, 0x9f, 0x6f, 0xc0, 0x5f, 0xa6, 0xc9, 0xf3, 0x74, 0xf2, 0x2f, 0x0d, + 0xd0, 0x81, 0xdd, 0xf5, 0x05, 0x61, 0x80, 0x29, 0xe1, 0x8a, 0x47, 0x98, + 0x36, 0x0c, 0xd6, 0x27, 0x32, 0x83, 0xf3, 0xf4, 0x1b, 0x6d, 0xcd, 0x1d, + 0x30, 0x75, 0xed, 0x29, 0x9a, 0x3b, 0x0b, 0x55, 0x55, 0xc5, 0x79, 0x33, + 0x83, 0xde, 0x70, 0x2b, 0x30, 0xa8, 0x64, 0x49, 0x1c, 0xa1, 0x3b, 0xc9, + 0x33, 0x7c, 0x64, 0x02, 0x5c, 0xbd, 0xf1, 0x51, 0x56, 0x47, 0x85, 0x1c, + 0x10, 0x54, 0xb0, 0xdb, 0xe1, 0x61, 0x77, 0x9f, 0x28, 0xf9, 0xf1, 0x1e, + 0x1e, 0xcc, 0x52, 0xbc, 0x5c, 0x05, 0xfb, 0x01, 0x94, 0x71, 0x58, 0x4e, + 0xf2, 0x21, 0x27, 0xc5, 0xce, 0x02, 0x20, 0x11, 0xdf, 0x94, 0x26, 0x75, + 0xff, 0x80, 0x22, 0x3d, 0x88, 0x7f, 0x55, 0x21, 0x4a, 0xfc, 0xa3, 0xf6, + 0x50, 0xba, 0x07, 0x2c, 0x3d, 0xf0, 0x30, 0x2c, 0x06, 0x79, 0xdc, 0x8a, + 0xe8, 0x29, 0x42, 0x4f, 0xfa, 0x4b, 0x74, 0x57, 0x5f, 0xac, 0xfe, 0xb8, + 0x94, 0xac, 0x00, 0x0c, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xa7, 0x15, 0xc9, 0x9d, 0x11, 0x5f, 0x4c, 0x2a, 0x0f, 0x86, 0x9d, 0x20, + 0x1a, 0x4f, 0xa9, 0x32, 0x43, 0x05, 0xac, 0x3c, 0x36, 0x08, 0x9f, 0x2f, + 0xe1, 0x55, 0x8e, 0x38, 0xe2, 0xbf, 0x3e, 0x11, 0x24, 0x69, 0xdf, 0x2e, + 0x3a, 0x2f, 0x54, 0x49, 0x17, 0x4b, 0x8a, 0xa2, 0xf4, 0xcf, 0xa2, 0x5c, + 0x8d, 0x2b, 0xaf, 0x0e, 0xe7, 0x20, 0xe5, 0x53, 0x77, 0xa4, 0xa2, 0x40, + 0x2e, 0x34, 0x52, 0x23, 0x77, 0x4e, 0xd4, 0x8b, 0x11, 0x6f, 0x9c, 0x9e, + 0x57, 0xa4, 0x29, 0x57, 0xf0, 0xe6, 0x8f, 0x7a, 0x98, 0xbb, 0xd5, 0x3a, + 0x00, 0x64, 0x90, 0x2b, 0xb5, 0x32, 0x52, 0xf1, 0xba, 0xfc, 0xff, 0x0c, + 0xd6, 0xd5, 0x8f, 0xc6, 0x8f, 0x04, 0x91, 0x9f, 0xc2, 0x47, 0x8b, 0x2b, + 0x90, 0xdd, 0x85, 0x23, 0x82, 0x3b, 0x7c, 0x77, 0x3d, 0x32, 0x4e, 0x8a, + 0xf5, 0x03, 0xef, 0xd9, 0xae, 0x1c, 0xbc, 0x15, 0x62, 0x5c, 0x4a, 0x41, + 0x21, 0xaf, 0x1e, 0x8f, 0x98, 0xe0, 0x96, 0x7b, 0x09, 0x9a, 0x65, 0xe3, + 0x42, 0x9e, 0xa7, 0xd3, 0x47, 0x39, 0x0c, 0xa5, 0xfc, 0x51, 0x83, 0x75, + 0xe8, 0x0e, 0x2d, 0x07, 0xce, 0x42, 0xd7, 0x39, 0xe0, 0xd1, 0xe6, 0x80, + 0x5d, 0x93, 0x1a, 0xfb, 0xb0, 0x19, 0x0f, 0x1d, 0xbf, 0x48, 0xa9, 0x0d, + 0xb0, 0x88, 0x77, 0x9e, 0x7b, 0x7d, 0x47, 0x97, 0xdb, 0xe5, 0x64, 0x23, + 0xb3, 0x7c, 0x7e, 0xda, 0x40, 0x17, 0x02, 0xba, 0x7a, 0xfe, 0x75, 0xf8, + 0xe2, 0xeb, 0x9e, 0x52, 0xe6, 0xcc, 0x1c, 0x1e, 0x39, 0xa4, 0xf2, 0x2f, + 0x35, 0xf5, 0x55, 0x2c, 0x7f, 0xe4, 0x33, 0x04, 0x5f, 0x26, 0xa5, 0x2b, + 0x3d, 0x6e, 0x10, 0x78, 0x3e, 0x91, 0xa0, 0xe4, 0xd4, 0x76, 0x42, 0xb3, + 0xd6, 0xac, 0xec, 0x28, 0xb3, 0x40, 0xe2, 0xda, 0x86, 0x30, 0xe9, 0x93, + 0xa7, 0x41, 0xdf, 0x2e, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x20, 0x55, 0x77, 0x6d, 0xde, 0xaf, 0xbc, 0xb7, 0xdf, 0xd6, 0x6e, 0x17, + 0x28, 0x55, 0x65, 0x7d, 0xf6, 0x12, 0x8b, 0x77, 0xfb, 0xc6, 0xe9, 0x8c, + 0xaf, 0xdf, 0x42, 0xac, 0x8e, 0x2e, 0xeb, 0x25, 0x2e, 0x3c, 0x63, 0x79, + 0x17, 0x2d, 0x3f, 0x30, 0x0a, 0x05, 0x3d, 0x9c, 0xf7, 0xb3, 0xbd, 0x33, + 0xf1, 0x47, 0xaf, 0xa1, 0x1b, 0x4f, 0x5d, 0x36, 0xbb, 0x5b, 0x41, 0xa3, + 0xeb, 0x56, 0x5f, 0x0b, 0x84, 0xc2, 0x9e, 0xe2, 0xe0, 0xa8, 0xd6, 0x87, + 0x72, 0xdc, 0x57, 0x70, 0x91, 0x19, 0x4b, 0x62, 0xac, 0x99, 0x14, 0xfa, + 0xbc, 0x6d, 0xef, 0x11, 0xfa, 0x9a, 0x30, 0xcd, 0x88, 0xb6, 0xc9, 0x22, + 0xee, 0xa8, 0x4d, 0xb5, 0xc7, 0xe6, 0x16, 0x45, 0x26, 0xd7, 0x3c, 0x49, + 0x02, 0xd8, 0xf7, 0x78, 0x8d, 0xfb, 0xb1, 0xee, 0x63, 0x17, 0x36, 0x1e, + 0xb4, 0x7c, 0x95, 0x13, 0x4d, 0x5d, 0x6c, 0x0f, 0xc1, 0xff, 0xed, 0xd5, + 0xf1, 0xe8, 0x50, 0x58, 0xa6, 0x90, 0x63, 0x7a, 0xce, 0xf6, 0x68, 0xb8, + 0x67, 0x21, 0xdd, 0x62, 0x5c, 0xb5, 0x61, 0x97, 0x9f, 0x56, 0xce, 0xf3, + 0xf8, 0xf5, 0x96, 0x0e, 0x95, 0xe9, 0x4e, 0x84, 0x8b, 0xdd, 0x1f, 0xa3, + 0x04, 0x26, 0xdf, 0x4c, 0xe8, 0xa4, 0x89, 0x2e, 0x7a, 0x4d, 0x3a, 0xd6, + 0x04, 0x3c, 0x2c, 0x11, 0x2d, 0xb7, 0x07, 0x51, 0x03, 0xa8, 0x86, 0x02, + 0xa5, 0xbf, 0x55, 0x09, 0x6b, 0xd8, 0xff, 0xd3, 0x8d, 0x3b, 0xc0, 0xd7, + 0xe9, 0x4f, 0x0f, 0x7b, 0x58, 0x4e, 0x50, 0x91, 0x62, 0xad, 0xef, 0x38, + 0x2b, 0xd5, 0xe0, 0x34, 0xbd, 0x8a, 0x44, 0x1d, 0x56, 0x4d, 0xfb, 0x86, + 0x9e, 0x7a, 0x8d, 0xaa, 0x8b, 0xb7, 0x6c, 0x1b, 0xb8, 0x82, 0xf3, 0xb1, + 0xdf, 0x5c, 0x27, 0x7e, 0xbb, 0xc1, 0x68, 0xc5, 0xd3, 0xe1, 0xd4, 0x70, + 0xb2, 0x51, 0xc0, 0x07, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x76, 0x50, 0x06, 0x5c, 0x90, 0x54, 0x44, 0xd9, 0x1b, 0x2b, 0xdf, 0xfc, + 0xe0, 0xa9, 0x1b, 0x0c, 0x13, 0x70, 0xca, 0xe2, 0x36, 0x86, 0x8c, 0x35, + 0x9b, 0x9f, 0x4e, 0x45, 0x92, 0xef, 0xec, 0x2f, 0xad, 0x08, 0x2b, 0x8a, + 0x30, 0x5e, 0xf8, 0x5b, 0x79, 0x76, 0x35, 0xa5, 0x61, 0x25, 0x2d, 0x35, + 0xf2, 0x2e, 0x5c, 0xea, 0x71, 0x4b, 0x53, 0x30, 0x11, 0xf6, 0xf2, 0x90, + 0xf1, 0xcb, 0x59, 0x0c, 0xdb, 0x7b, 0x7d, 0xa0, 0x14, 0x45, 0xb3, 0x5f, + 0x86, 0xe1, 0x6f, 0xdd, 0xba, 0x50, 0xb8, 0xee, 0x33, 0x05, 0xfb, 0xe9, + 0xae, 0x91, 0xbd, 0x39, 0x9e, 0xef, 0x45, 0xaf, 0x11, 0x1b, 0xba, 0x0a, + 0x7d, 0x81, 0x69, 0x26, 0x0a, 0xaf, 0xd0, 0xf7, 0xc8, 0xdd, 0x14, 0xe0, + 0x05, 0x43, 0x82, 0x60, 0x48, 0x84, 0x69, 0x90, 0xd3, 0x85, 0x75, 0xb8, + 0xf4, 0x01, 0x57, 0x30, 0x4f, 0xee, 0x33, 0x00, 0x5e, 0x3e, 0xfd, 0xb6, + 0xe0, 0x21, 0x10, 0x2c, 0x89, 0xdb, 0x30, 0x8b, 0x57, 0x0f, 0x15, 0xef, + 0xbc, 0xdd, 0xca, 0x14, 0x07, 0xf7, 0xdc, 0xfc, 0x4a, 0xc9, 0x94, 0x0b, + 0xfb, 0x87, 0xaa, 0x14, 0x28, 0xa6, 0x14, 0xf5, 0x6e, 0x27, 0x0c, 0x94, + 0xc3, 0xec, 0xbd, 0x63, 0x0b, 0x10, 0x05, 0xab, 0x85, 0x28, 0x01, 0xb1, + 0x55, 0x62, 0x33, 0x9f, 0x2c, 0x84, 0xb3, 0xed, 0xae, 0x0d, 0x9a, 0x2b, + 0x54, 0xfe, 0x7d, 0x39, 0x04, 0x91, 0xa6, 0x6d, 0x7f, 0xce, 0xed, 0x38, + 0x44, 0x9e, 0x4c, 0x00, 0xb3, 0xa8, 0x60, 0x4c, 0x22, 0x80, 0x67, 0x5d, + 0xd8, 0x80, 0x3a, 0xab, 0xd1, 0x77, 0x60, 0x22, 0x0a, 0x84, 0x9d, 0xc2, + 0xe8, 0x7d, 0xa6, 0x8a, 0x33, 0xd1, 0xb8, 0xae, 0xaf, 0xe9, 0x29, 0x35, + 0xd2, 0xf0, 0x3e, 0xbb, 0xaa, 0xcf, 0xa1, 0xad, 0x09, 0x39, 0x7b, 0x40, + 0x18, 0x09, 0xb8, 0x2e, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x75, 0xb8, 0x08, 0x0f, 0x3c, 0xb0, 0xae, 0x40, 0xf8, 0x18, 0xe8, 0x97, + 0x9e, 0x8a, 0x98, 0xc8, 0x20, 0xe6, 0x69, 0x59, 0xf7, 0x64, 0xc2, 0xe7, + 0x57, 0x1c, 0x79, 0x6f, 0xcc, 0xb6, 0xb2, 0x24, 0x1a, 0xd3, 0x14, 0xaf, + 0x8b, 0x90, 0xeb, 0x60, 0x86, 0x0e, 0x2c, 0xa2, 0x3e, 0xe2, 0x9d, 0x99, + 0xbd, 0x83, 0x37, 0xa8, 0xd8, 0x2b, 0x77, 0x38, 0x3a, 0x17, 0x56, 0xa0, + 0x83, 0x71, 0x20, 0x27, 0xde, 0x2d, 0x8c, 0x59, 0xbb, 0x5b, 0x29, 0xfb, + 0x25, 0x34, 0x63, 0x39, 0xf5, 0x20, 0x14, 0x61, 0xbc, 0xc7, 0x5e, 0x6f, + 0x4c, 0xc5, 0x5f, 0x5d, 0x68, 0x0e, 0x61, 0xa1, 0xd5, 0xaf, 0x87, 0x14, + 0x0b, 0x61, 0x06, 0x2b, 0x4f, 0x7c, 0x8e, 0x85, 0xd9, 0xa8, 0xaf, 0x89, + 0xed, 0xe9, 0xd7, 0x9d, 0xc0, 0xfe, 0x0e, 0x50, 0xa6, 0xf4, 0x1c, 0xcd, + 0x7e, 0xa9, 0x61, 0xec, 0x55, 0x35, 0x1e, 0x11, 0xe4, 0x2e, 0x5f, 0xd6, + 0xd8, 0xc3, 0xdb, 0xa7, 0xcf, 0x61, 0x53, 0xda, 0x30, 0xa9, 0x06, 0x4c, + 0x71, 0x2b, 0x16, 0x60, 0xef, 0x9a, 0xc7, 0xe0, 0xed, 0x8b, 0xfc, 0x38, + 0x32, 0x65, 0xfa, 0x02, 0x98, 0xc0, 0x21, 0xde, 0x9c, 0xa4, 0x8a, 0xc6, + 0x70, 0xac, 0x16, 0x66, 0x79, 0xf5, 0x9c, 0x48, 0x7d, 0x96, 0x41, 0x28, + 0x74, 0xf4, 0x9c, 0xcc, 0x4e, 0x4e, 0xf4, 0xc9, 0x35, 0x63, 0xb8, 0x02, + 0x7d, 0xb4, 0x6b, 0x3b, 0x40, 0x72, 0x73, 0x9e, 0x61, 0x1b, 0x78, 0x0c, + 0x0b, 0x59, 0x30, 0xb4, 0x83, 0x0e, 0x7b, 0x0e, 0x48, 0xb1, 0xab, 0x56, + 0xda, 0xc5, 0x6c, 0x7c, 0xcc, 0x8e, 0x22, 0x25, 0xec, 0x76, 0xe8, 0xe2, + 0x93, 0xae, 0x05, 0x6f, 0xc8, 0xdd, 0x2c, 0x56, 0x85, 0x3d, 0xab, 0x97, + 0xe5, 0xca, 0x1f, 0x21, 0x4f, 0xf1, 0x84, 0x33, 0xda, 0xd2, 0x72, 0x40, + 0x15, 0x9a, 0xfd, 0x28, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x85, 0x71, 0x69, 0xe8, 0x81, 0x43, 0x3a, 0x62, 0x66, 0x1f, 0x09, 0xbf, + 0xbc, 0xd0, 0xb3, 0x02, 0x5d, 0xb8, 0x18, 0x7f, 0x23, 0x29, 0xca, 0xf8, + 0xe1, 0x02, 0x5c, 0x06, 0x3b, 0x6c, 0x9f, 0x10, 0x6a, 0xae, 0x5e, 0x2f, + 0xbd, 0x10, 0xab, 0x17, 0x24, 0x39, 0x72, 0x96, 0xf6, 0x54, 0x70, 0x26, + 0x55, 0x1f, 0x72, 0xfb, 0xbe, 0x36, 0x3d, 0x41, 0xd6, 0x7f, 0xe6, 0x3d, + 0xae, 0xd9, 0x13, 0x11, 0xd8, 0xa4, 0x42, 0xb9, 0x86, 0xb2, 0x2d, 0x25, + 0xdf, 0xe8, 0xb7, 0x54, 0x1c, 0x8d, 0x83, 0xf5, 0x1f, 0x28, 0x8c, 0x2e, + 0x0c, 0x68, 0x24, 0x47, 0xbc, 0xae, 0x4a, 0x86, 0x7a, 0x69, 0x82, 0x1a, + 0x05, 0xfd, 0x6e, 0xa4, 0x04, 0xa1, 0xfd, 0xf7, 0xda, 0x4f, 0xdb, 0x08, + 0x70, 0xc9, 0x5a, 0xff, 0xf5, 0xa4, 0x7b, 0xd8, 0xbc, 0x4a, 0x6c, 0x1a, + 0xb6, 0x21, 0xe4, 0x12, 0xa5, 0x0d, 0x42, 0x1f, 0x39, 0xc9, 0x22, 0xc8, + 0x0f, 0x93, 0x47, 0xdd, 0x05, 0x6b, 0xfe, 0x13, 0x1d, 0x32, 0xbd, 0x47, + 0x86, 0xef, 0x25, 0x76, 0x29, 0x1f, 0x95, 0x90, 0x81, 0x89, 0xef, 0x60, + 0x0b, 0xe3, 0x2c, 0x0c, 0x25, 0x9f, 0xa2, 0x3f, 0xf3, 0xa7, 0x88, 0xf5, + 0x41, 0x90, 0xb2, 0x03, 0x79, 0x80, 0x57, 0x0c, 0xe1, 0xa9, 0x50, 0x2c, + 0x1e, 0xa4, 0xd1, 0xea, 0xe6, 0x84, 0x16, 0x84, 0x88, 0x4e, 0x99, 0x13, + 0x9d, 0xb5, 0xba, 0xa3, 0x7d, 0x7d, 0x2a, 0xeb, 0xec, 0xdf, 0xe4, 0xa7, + 0x0b, 0x3b, 0xde, 0x8a, 0x38, 0x0b, 0x43, 0x6f, 0x0d, 0xc2, 0x41, 0xf6, + 0x05, 0x6a, 0x8b, 0xf7, 0x46, 0xbe, 0xb8, 0x2b, 0xda, 0xf9, 0x9f, 0xac, + 0xdd, 0xc7, 0x64, 0x6c, 0x44, 0x5d, 0x42, 0xfa, 0x77, 0x24, 0xca, 0x7d, + 0xc2, 0x9d, 0xcf, 0x7c, 0x69, 0x87, 0x7a, 0xd5, 0x18, 0x26, 0x19, 0x65, + 0xcb, 0x74, 0x36, 0x21, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x3e, 0xaf, 0xf0, 0x1a, 0x06, 0xc0, 0xe6, 0xbc, 0xcc, 0xa4, 0x27, 0xdf, + 0x0c, 0x40, 0x64, 0x57, 0xb5, 0x25, 0xcd, 0xb9, 0xdc, 0x9b, 0x15, 0x3b, + 0x1e, 0x24, 0xb6, 0x0d, 0x0a, 0x26, 0xab, 0x1d, 0xe5, 0x74, 0x49, 0xb8, + 0xa4, 0x36, 0x81, 0xf4, 0x27, 0xc8, 0x79, 0xa0, 0x62, 0x37, 0x95, 0x83, + 0xa2, 0xd0, 0x10, 0x85, 0x04, 0x8d, 0x16, 0xb8, 0x99, 0x6d, 0x70, 0xf8, + 0x11, 0x98, 0x1e, 0x00, 0x16, 0xb8, 0x85, 0x65, 0x8e, 0x82, 0xd7, 0x99, + 0x52, 0xc6, 0x86, 0xf5, 0xe0, 0x91, 0xcc, 0xb5, 0x57, 0x32, 0xfc, 0xda, + 0xca, 0x2c, 0x5d, 0x3c, 0x07, 0x3f, 0xa8, 0x07, 0xcc, 0x30, 0x77, 0x05, + 0x67, 0x44, 0xb4, 0x9b, 0xd1, 0x60, 0xa1, 0x01, 0x59, 0x9d, 0x5d, 0x21, + 0x03, 0xf8, 0x1a, 0xc8, 0x2c, 0x51, 0x84, 0x46, 0x27, 0x47, 0xdd, 0x6c, + 0xd0, 0xb9, 0xe9, 0x81, 0x6d, 0x9f, 0x86, 0x13, 0x8d, 0x6a, 0xe9, 0x99, + 0xcd, 0x98, 0x6a, 0xf6, 0xe3, 0xb9, 0x06, 0x89, 0xa2, 0x4f, 0xc7, 0xfa, + 0x7d, 0x77, 0x45, 0x7d, 0x8c, 0x34, 0xce, 0x0d, 0xb3, 0x21, 0x10, 0xbf, + 0x99, 0x90, 0x49, 0x10, 0x04, 0xa6, 0xba, 0xfe, 0x28, 0xa9, 0xae, 0x2d, + 0xa9, 0x9a, 0x44, 0xec, 0xd5, 0x1e, 0x42, 0xb0, 0x28, 0x66, 0x16, 0x61, + 0xad, 0x99, 0xe9, 0xd7, 0xc7, 0x57, 0x8e, 0x76, 0x8d, 0x38, 0x24, 0x08, + 0xcb, 0xd2, 0x02, 0x98, 0x00, 0x9a, 0x6e, 0xca, 0x52, 0x08, 0x2a, 0x1d, + 0x5b, 0xb6, 0x88, 0xfd, 0xfd, 0xa1, 0x22, 0x2c, 0xef, 0x6d, 0xd6, 0x40, + 0xa2, 0x76, 0x75, 0x5e, 0x80, 0xa4, 0xe0, 0x2b, 0xd3, 0x85, 0x93, 0x4a, + 0xee, 0x3b, 0x72, 0x44, 0xec, 0xdf, 0x76, 0x7e, 0x02, 0x17, 0xad, 0x52, + 0xc6, 0x55, 0xb5, 0xde, 0x65, 0x91, 0x50, 0x21, 0xea, 0xa5, 0x9e, 0xff, + 0xb7, 0x0b, 0x5e, 0x0a, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x0a, 0x91, 0x2a, 0x0a, 0x6a, 0x98, 0xb3, 0xb5, 0xb8, 0xb5, 0x0e, 0xdc, + 0x15, 0xd3, 0x45, 0x39, 0x62, 0x7b, 0xe3, 0x65, 0xbb, 0xf7, 0x80, 0x9d, + 0x83, 0xf1, 0xcc, 0xe3, 0x2d, 0x2b, 0xe7, 0x25, 0x9f, 0xe0, 0xfa, 0x31, + 0x3d, 0xc4, 0xe0, 0x6d, 0xee, 0x19, 0x8c, 0x7b, 0x15, 0xc2, 0xe3, 0x1f, + 0x3b, 0x05, 0x14, 0xf7, 0x3e, 0x11, 0x52, 0xb3, 0xbc, 0x1e, 0x44, 0x70, + 0xa7, 0xbb, 0x23, 0x1d, 0x6e, 0x96, 0x8d, 0x99, 0xb3, 0x85, 0x4e, 0x98, + 0xe5, 0x7c, 0xe8, 0x90, 0xee, 0x24, 0xe1, 0xda, 0xcf, 0x9b, 0x72, 0x74, + 0x83, 0x53, 0x07, 0x20, 0xae, 0x28, 0xc9, 0x90, 0x4c, 0x43, 0x26, 0x0a, + 0xca, 0xfc, 0x87, 0xd5, 0xce, 0x09, 0x23, 0x6e, 0xe6, 0xae, 0x13, 0x5c, + 0xe2, 0x89, 0x2f, 0xbd, 0xb6, 0x78, 0x0b, 0x85, 0x47, 0xab, 0x04, 0xaf, + 0xd3, 0x5e, 0xad, 0xcd, 0x4f, 0x0c, 0xed, 0x10, 0x79, 0x2f, 0x68, 0x89, + 0x8a, 0x13, 0x8c, 0xa7, 0xfb, 0x59, 0x00, 0x36, 0xb4, 0x03, 0xcf, 0x25, + 0xe0, 0xd6, 0x6f, 0x22, 0xf9, 0x92, 0x1d, 0x32, 0x2d, 0x22, 0x8a, 0x5b, + 0xd4, 0x5a, 0x5c, 0x0c, 0x80, 0x5d, 0xf4, 0x1d, 0x76, 0xe4, 0x09, 0x93, + 0x9d, 0x99, 0xa5, 0xce, 0x21, 0xfa, 0x4e, 0xd0, 0x19, 0xa7, 0x29, 0x6d, + 0x73, 0xfa, 0x13, 0x67, 0x9d, 0xe8, 0x38, 0x6e, 0x93, 0xbb, 0xaa, 0x0c, + 0x85, 0x16, 0x5d, 0x64, 0x8a, 0xd6, 0x2a, 0x44, 0x1d, 0xbc, 0x29, 0x16, + 0x6f, 0xa4, 0xf7, 0xc0, 0x4a, 0x14, 0x5d, 0xdc, 0x28, 0x2e, 0xb5, 0x67, + 0x87, 0x7a, 0x93, 0xb5, 0x07, 0x41, 0x6d, 0x1f, 0x93, 0x1b, 0x0d, 0x94, + 0x35, 0x91, 0x6d, 0x89, 0x51, 0x84, 0xe4, 0xa8, 0x5a, 0xc7, 0x1a, 0x74, + 0x59, 0xd5, 0x6b, 0xaa, 0x54, 0x53, 0x83, 0xc1, 0xf8, 0xd4, 0xab, 0x1a, + 0xd8, 0x89, 0x33, 0x09, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x09, 0xc2, 0x50, 0x35, 0x59, 0x65, 0x64, 0x07, 0xd8, 0x59, 0xa0, 0x7d, + 0xba, 0xed, 0x97, 0x71, 0x3f, 0xaf, 0x25, 0x09, 0x1e, 0x66, 0xdf, 0xaa, + 0x1e, 0xb4, 0xa9, 0xc1, 0x77, 0x35, 0x2d, 0x1f, 0x99, 0x41, 0x1b, 0xed, + 0x67, 0x99, 0x1a, 0xb1, 0xa1, 0xe8, 0xc5, 0xb3, 0xc3, 0x1e, 0x2e, 0x2b, + 0x77, 0x84, 0x79, 0x9c, 0x30, 0x92, 0x5e, 0x55, 0x86, 0x38, 0x48, 0x40, + 0x22, 0xb6, 0x50, 0x01, 0x8b, 0x29, 0x32, 0x59, 0x6e, 0x16, 0x33, 0x2b, + 0x2f, 0x6c, 0x97, 0x23, 0xf9, 0xbd, 0x5f, 0x64, 0x99, 0x76, 0x50, 0x4e, + 0x61, 0x0f, 0xeb, 0x29, 0xf7, 0x98, 0x3b, 0x20, 0x4d, 0xe1, 0x37, 0x0b, + 0x75, 0x35, 0x64, 0x64, 0x37, 0xbf, 0x4b, 0xcd, 0xc1, 0x17, 0xb6, 0x1c, + 0x8e, 0x84, 0x61, 0x25, 0x62, 0x47, 0x24, 0x84, 0x8f, 0x85, 0xdd, 0xa8, + 0x56, 0xc4, 0x31, 0x14, 0x8d, 0x8c, 0xae, 0x0c, 0x8d, 0xb7, 0x92, 0x22, + 0xb4, 0xd3, 0xc3, 0x8d, 0x76, 0xef, 0x7c, 0x56, 0x55, 0x22, 0x2c, 0x51, + 0xd0, 0xba, 0xbe, 0x4c, 0xd6, 0x22, 0xe5, 0x0d, 0xb7, 0x54, 0x53, 0x23, + 0xce, 0x5f, 0xc2, 0x06, 0xf1, 0xbb, 0x02, 0xa3, 0xb9, 0xc8, 0x8d, 0xd9, + 0x4a, 0x3b, 0x35, 0x57, 0x8f, 0x9e, 0xaa, 0xbc, 0x9b, 0xfc, 0x0c, 0xb5, + 0x56, 0xd1, 0xae, 0x61, 0x00, 0x55, 0x2c, 0x6a, 0x0c, 0xc5, 0xa5, 0x0a, + 0x6c, 0x72, 0xd1, 0x18, 0xbf, 0x47, 0xf9, 0xd1, 0x57, 0x89, 0x87, 0x0a, + 0x27, 0xc4, 0xf2, 0x5f, 0x20, 0x3b, 0x6c, 0x01, 0xe9, 0x86, 0x83, 0x8c, + 0x5a, 0x9f, 0x89, 0x4c, 0xce, 0x6a, 0xe6, 0x02, 0xb9, 0xad, 0x73, 0x1b, + 0x4b, 0x7a, 0x27, 0xaf, 0xdf, 0x30, 0xf6, 0x5c, 0xe6, 0x1f, 0x02, 0xd9, + 0x89, 0x09, 0xb2, 0x8f, 0x03, 0x39, 0xd3, 0x84, 0xfb, 0xc8, 0x01, 0x9f, + 0x3f, 0x00, 0x3c, 0x27, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x5d, 0x2a, 0xde, 0x71, 0x74, 0x40, 0x82, 0xe9, 0xd5, 0x00, 0xb3, 0xdf, + 0x41, 0x6b, 0xd9, 0x21, 0x5c, 0xf0, 0x15, 0xf4, 0xdc, 0xf5, 0xa4, 0x33, + 0x7f, 0x9b, 0x78, 0x5d, 0xc5, 0x81, 0x89, 0x21, 0x53, 0xaf, 0xc1, 0x80, + 0xf3, 0x83, 0xca, 0xf3, 0xf9, 0x01, 0xd7, 0x53, 0xbe, 0xbb, 0x47, 0xeb, + 0x05, 0x93, 0x77, 0x55, 0x74, 0xfe, 0xbc, 0x34, 0x0d, 0xc7, 0x31, 0x84, + 0x58, 0x9c, 0xc0, 0x2d, 0x0b, 0x5b, 0x57, 0xb8, 0x33, 0xfe, 0x14, 0x6c, + 0x54, 0x75, 0x0e, 0x37, 0x93, 0xe0, 0x96, 0x7d, 0x28, 0x6e, 0xd1, 0xf7, + 0x16, 0x93, 0x28, 0xfa, 0x8c, 0x0a, 0xc9, 0xb0, 0xc7, 0x1a, 0x3e, 0x0a, + 0xc5, 0x0e, 0x98, 0x41, 0xb8, 0xd9, 0x33, 0x9d, 0x04, 0xf5, 0x52, 0x73, + 0x91, 0x3a, 0xd5, 0x0f, 0x10, 0x00, 0x8c, 0x2b, 0x33, 0x2f, 0x6e, 0x78, + 0x64, 0xd7, 0x36, 0x28, 0x1d, 0x05, 0xd4, 0x10, 0x36, 0xbb, 0x22, 0x0a, + 0x85, 0xab, 0xc1, 0x6f, 0x19, 0x4b, 0xda, 0x35, 0xa5, 0xe6, 0x6c, 0x72, + 0x01, 0xa3, 0xff, 0x6f, 0xe2, 0x52, 0xbf, 0x8c, 0x61, 0xc5, 0xeb, 0xb6, + 0x3c, 0x46, 0x41, 0x19, 0xae, 0x95, 0x36, 0xed, 0x38, 0xec, 0x3e, 0xf1, + 0xd7, 0x67, 0x83, 0x4d, 0x68, 0x18, 0x58, 0x16, 0xfe, 0xf6, 0x7c, 0xb2, + 0x86, 0xdb, 0xe9, 0x46, 0x25, 0x03, 0xa8, 0x59, 0x7e, 0xaa, 0xa9, 0x0a, + 0xf0, 0x0f, 0xf5, 0xa0, 0x14, 0xc6, 0x74, 0x4b, 0x4f, 0xb0, 0xb0, 0x6b, + 0x24, 0x81, 0x90, 0x8f, 0x14, 0x72, 0x22, 0x09, 0x50, 0xe5, 0x78, 0x31, + 0x36, 0x65, 0x65, 0x9b, 0x66, 0x84, 0x74, 0x01, 0x14, 0x50, 0x09, 0x8f, + 0x57, 0x31, 0xdc, 0x49, 0x6e, 0x54, 0xb7, 0x6c, 0x1d, 0xfa, 0xe4, 0xb3, + 0x4e, 0xa5, 0xe0, 0x00, 0x6a, 0xd3, 0x80, 0x83, 0xd0, 0x55, 0x88, 0x1c, + 0xb4, 0x87, 0xd2, 0x00, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x70, 0x37, 0xad, 0x8c, 0x55, 0x7e, 0x4b, 0xde, 0x16, 0xd4, 0xec, 0x8d, + 0x50, 0xd4, 0x6a, 0xe6, 0x46, 0x96, 0x51, 0x64, 0x9d, 0x31, 0xc9, 0x51, + 0xfb, 0x76, 0x5d, 0x55, 0xf9, 0xa5, 0xb1, 0x29, 0xbd, 0x3f, 0x05, 0xa4, + 0xfa, 0x78, 0x81, 0x01, 0x3c, 0xb6, 0x82, 0x49, 0x45, 0x02, 0xc3, 0x76, + 0xc0, 0x37, 0x26, 0xa0, 0x4a, 0xe1, 0x04, 0xc1, 0x12, 0xd9, 0x97, 0x54, + 0x51, 0xcf, 0xe8, 0x14, 0xb2, 0x92, 0xf9, 0x3e, 0x81, 0xd8, 0x68, 0x2f, + 0x01, 0xe5, 0x50, 0x6d, 0x60, 0x9c, 0x05, 0x62, 0xb0, 0xa0, 0xd5, 0x86, + 0xc6, 0x22, 0x5f, 0xb5, 0xb7, 0xb7, 0xd2, 0x2e, 0x0a, 0xd3, 0xb3, 0x13, + 0x36, 0xbc, 0x90, 0xa4, 0xe4, 0xbb, 0x49, 0xd9, 0xba, 0x44, 0x84, 0xce, + 0xd7, 0x04, 0x34, 0x6a, 0x9e, 0xd5, 0xe9, 0x7d, 0x95, 0xb9, 0x2d, 0x63, + 0xe5, 0x08, 0xcd, 0xa4, 0x44, 0x1e, 0xe1, 0x2b, 0x7f, 0x0b, 0x2c, 0xa5, + 0xf7, 0x4e, 0xe7, 0x47, 0x74, 0x72, 0x42, 0x41, 0xb9, 0x50, 0x33, 0x2d, + 0x9e, 0x66, 0x74, 0x0b, 0x70, 0x83, 0xbf, 0x57, 0xdd, 0x17, 0xde, 0x67, + 0x1c, 0xef, 0x33, 0x2c, 0x41, 0x78, 0x09, 0x9a, 0x12, 0x22, 0xb2, 0xea, + 0xe6, 0x92, 0x74, 0xe5, 0x13, 0x59, 0x2c, 0x5a, 0x4f, 0x16, 0x76, 0xc4, + 0x2a, 0x21, 0xb8, 0x32, 0x59, 0xbb, 0x90, 0xb0, 0x50, 0x89, 0x3c, 0x1a, + 0x0d, 0xa6, 0x19, 0x98, 0xc4, 0xb4, 0x82, 0x98, 0x71, 0x0d, 0x8b, 0x2e, + 0x30, 0xd9, 0xca, 0x2b, 0xff, 0x45, 0xa1, 0x39, 0x28, 0x89, 0x56, 0x92, + 0x88, 0x92, 0x4b, 0xbb, 0x45, 0x22, 0x8b, 0x1a, 0x81, 0xf1, 0x77, 0x2d, + 0xd5, 0x02, 0xcd, 0xae, 0xb9, 0x33, 0x51, 0x99, 0x77, 0x44, 0xb4, 0x5c, + 0x83, 0x92, 0x93, 0x88, 0xb7, 0x88, 0x44, 0xcc, 0x9d, 0xf1, 0x79, 0x43, + 0x6b, 0xa8, 0x7a, 0x07, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x04, 0x2b, 0xc9, 0x66, 0x2e, 0x8d, 0x3e, 0xa9, 0xdd, 0xba, 0x64, 0x55, + 0x7a, 0xa2, 0x4c, 0x38, 0xb8, 0xdc, 0x9a, 0xdd, 0xc1, 0xb7, 0x42, 0xfe, + 0x15, 0xa2, 0xb6, 0xad, 0x40, 0x5a, 0x5b, 0x10, 0x62, 0x6d, 0xea, 0x41, + 0x31, 0x65, 0xfc, 0xaf, 0x40, 0xdb, 0x2f, 0xa7, 0x6f, 0x88, 0xd1, 0x6d, + 0x01, 0xda, 0x49, 0x6f, 0x0e, 0x6c, 0x67, 0xdd, 0xdc, 0xc1, 0x64, 0x98, + 0x98, 0x52, 0xb6, 0x0c, 0x13, 0x28, 0x09, 0x41, 0xf3, 0x8c, 0x63, 0x73, + 0x74, 0x29, 0x8a, 0xec, 0xef, 0x52, 0xba, 0xc5, 0x6d, 0x75, 0x94, 0x71, + 0x09, 0x08, 0x07, 0xf9, 0xe2, 0x00, 0x8b, 0x98, 0xf4, 0x5b, 0x10, 0x2b, + 0xef, 0x80, 0x7e, 0x35, 0xb1, 0x56, 0x77, 0x43, 0x80, 0x29, 0x74, 0x8b, + 0x87, 0x91, 0x88, 0x7d, 0xb9, 0xc7, 0xa8, 0xef, 0xbf, 0xd2, 0x95, 0x65, + 0x4c, 0x62, 0xfb, 0xe8, 0x4f, 0x20, 0x32, 0x07, 0xee, 0x49, 0xf6, 0x73, + 0x44, 0xd5, 0xa0, 0x72, 0x09, 0x06, 0x39, 0x47, 0x9b, 0x9b, 0x47, 0xea, + 0xe4, 0xf8, 0xca, 0x0c, 0x3a, 0x94, 0xd6, 0x80, 0x51, 0xbe, 0x55, 0x9c, + 0xe1, 0x2f, 0xf4, 0x0b, 0x3a, 0x1f, 0x1d, 0x9d, 0x2b, 0x7a, 0xcb, 0xe0, + 0x37, 0x82, 0x4a, 0xb2, 0x29, 0xc8, 0xfe, 0x56, 0x2f, 0xf1, 0x30, 0x15, + 0x38, 0x28, 0xae, 0x4e, 0x4a, 0x4e, 0xe5, 0x5e, 0xd2, 0xb3, 0xd9, 0x0d, + 0xf6, 0x09, 0x45, 0x10, 0xa2, 0x1c, 0x6c, 0xdd, 0xd9, 0x41, 0xf8, 0x4d, + 0x7f, 0xe3, 0xd2, 0xb6, 0x8f, 0x8c, 0x60, 0xf1, 0xea, 0xfc, 0xcf, 0x3b, + 0x39, 0x27, 0xa2, 0xc1, 0x39, 0xc9, 0xb2, 0x1f, 0xfc, 0xdd, 0x91, 0x7b, + 0x69, 0xb3, 0x0f, 0x34, 0x55, 0xc0, 0xa6, 0x8d, 0x98, 0xd7, 0xb1, 0x2d, + 0x57, 0xfa, 0x86, 0x6c, 0xc8, 0x8c, 0x2d, 0x79, 0x07, 0x7a, 0xcb, 0xa6, + 0xad, 0xd3, 0xed, 0x11, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xc9, 0x40, 0x0a, 0xca, 0x69, 0xdd, 0x58, 0xd5, 0x8c, 0x38, 0x43, 0x39, + 0x34, 0x63, 0xe5, 0x6b, 0x27, 0x72, 0x3b, 0xe7, 0x40, 0xdc, 0x35, 0x47, + 0x49, 0xcc, 0x7f, 0x44, 0xe5, 0x1c, 0x10, 0x18, 0x54, 0x5c, 0x26, 0x8d, + 0xa2, 0xba, 0x62, 0x6a, 0xfa, 0x41, 0xda, 0xb2, 0x83, 0x4e, 0x25, 0x79, + 0x02, 0xea, 0xf3, 0xef, 0xbc, 0x16, 0xb7, 0x2b, 0x6f, 0x6d, 0x59, 0x1e, + 0xec, 0xc9, 0xb1, 0x00, 0x2c, 0x76, 0x9b, 0x7d, 0x5b, 0x73, 0x4d, 0x5a, + 0x89, 0xf8, 0x24, 0x08, 0xd1, 0x7c, 0x14, 0x82, 0xc4, 0x53, 0xf0, 0xd2, + 0xbe, 0x7c, 0x97, 0xda, 0xa9, 0x74, 0xd1, 0x9c, 0xb0, 0x9b, 0x79, 0x10, + 0xea, 0x93, 0x04, 0x63, 0xf6, 0xd8, 0xd2, 0x2d, 0x07, 0xa1, 0x3d, 0xbf, + 0xc1, 0x34, 0x59, 0xb9, 0xbe, 0x56, 0x42, 0x57, 0xf3, 0xb2, 0x06, 0x31, + 0x10, 0x1b, 0x92, 0xa2, 0x2c, 0xa3, 0xa9, 0x10, 0x74, 0xfd, 0x3a, 0xb8, + 0x87, 0x2c, 0xa0, 0xee, 0xde, 0xbb, 0x9a, 0x5b, 0x66, 0xb0, 0x0a, 0xd8, + 0x99, 0xd4, 0x56, 0xd0, 0x33, 0x0d, 0xa6, 0x0e, 0xa4, 0x01, 0x93, 0x33, + 0xd1, 0x68, 0x11, 0x00, 0x38, 0x3a, 0xff, 0x26, 0xdf, 0x18, 0x55, 0x4b, + 0x69, 0xda, 0x4c, 0x32, 0xe5, 0xda, 0x3f, 0x1f, 0x0d, 0x83, 0x49, 0xc1, + 0x9e, 0xc1, 0xd1, 0x20, 0xce, 0x3a, 0x9c, 0x3d, 0x7e, 0xe5, 0xba, 0x17, + 0xb7, 0x00, 0x9e, 0xa9, 0x87, 0x87, 0x9d, 0xc7, 0x14, 0x2f, 0xe4, 0x3e, + 0xdd, 0x06, 0x7a, 0x3c, 0x3d, 0x19, 0xa3, 0x66, 0x78, 0x1c, 0x2a, 0xa3, + 0x66, 0x82, 0x58, 0x9a, 0x9c, 0x43, 0x0a, 0x01, 0xd3, 0xd1, 0xc6, 0x23, + 0x42, 0x3d, 0x6e, 0xc3, 0x45, 0x90, 0x71, 0x6e, 0x60, 0x82, 0x86, 0x31, + 0x6b, 0xec, 0x89, 0xcf, 0x46, 0x36, 0xd5, 0xbb, 0x45, 0x79, 0x6e, 0x0c, + 0x2a, 0xcb, 0xe5, 0x04, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xe0, 0xf8, 0xd0, 0x87, 0xc5, 0xe9, 0x0d, 0x40, 0x80, 0x5d, 0xeb, 0x82, + 0x9d, 0x24, 0xa5, 0xec, 0xeb, 0x03, 0x96, 0x9e, 0x80, 0x2c, 0x35, 0x7b, + 0x23, 0xc3, 0xfc, 0xdc, 0x55, 0x31, 0xb4, 0x0d, 0xa0, 0x22, 0x94, 0x45, + 0x23, 0x7e, 0x22, 0xe6, 0x47, 0x8b, 0xe0, 0xcc, 0xea, 0x89, 0xbf, 0x6b, + 0x03, 0x9a, 0x85, 0x36, 0xe5, 0x2b, 0x6f, 0x38, 0x51, 0x5f, 0x88, 0xc7, + 0x0b, 0xd2, 0xff, 0x21, 0x47, 0xaf, 0x5f, 0x07, 0x46, 0x6c, 0xe7, 0x80, + 0x25, 0xd3, 0x93, 0x16, 0x1a, 0xe5, 0xed, 0xf5, 0xbf, 0x2a, 0xbc, 0x2f, + 0x09, 0xc9, 0x7c, 0x88, 0xe2, 0x0d, 0x8b, 0xe8, 0x90, 0x95, 0xaa, 0x17, + 0x5a, 0xa3, 0x2e, 0x7b, 0x6b, 0x11, 0xec, 0x28, 0x8f, 0xfb, 0x53, 0x74, + 0xb1, 0xe0, 0x5c, 0x81, 0x4e, 0x01, 0xca, 0xd5, 0x91, 0xf7, 0x20, 0xad, + 0xa8, 0x17, 0x49, 0x92, 0x60, 0x92, 0xe2, 0x23, 0xc6, 0x78, 0x25, 0x64, + 0x66, 0x1f, 0x59, 0x8e, 0x09, 0xab, 0x5e, 0x38, 0xeb, 0x71, 0xd5, 0xb8, + 0xb1, 0xcb, 0xa7, 0x36, 0xc4, 0x05, 0xa4, 0x3d, 0xdd, 0x63, 0x7a, 0x59, + 0xae, 0xc0, 0x67, 0x01, 0x10, 0x02, 0x16, 0x16, 0xf5, 0x85, 0x9e, 0x1a, + 0xdc, 0xca, 0x71, 0xad, 0x0c, 0x0d, 0x5d, 0x37, 0xf7, 0xe5, 0x3d, 0xb6, + 0x48, 0xe8, 0x73, 0x22, 0x7d, 0xaa, 0xcd, 0xeb, 0x84, 0x9c, 0x89, 0x27, + 0x18, 0x89, 0x67, 0x62, 0xeb, 0xe5, 0xa6, 0xdf, 0x79, 0xaa, 0x75, 0x86, + 0x49, 0xbd, 0xa7, 0xcd, 0x74, 0xeb, 0xbc, 0xb2, 0x97, 0xd6, 0xb8, 0xa7, + 0xdd, 0x53, 0x81, 0x99, 0xfb, 0x91, 0x18, 0x21, 0x5e, 0xca, 0x93, 0x07, + 0xfc, 0x8e, 0x92, 0x2b, 0x91, 0xc7, 0x85, 0xe5, 0x31, 0x14, 0x88, 0xfc, + 0xff, 0xb9, 0x05, 0x6c, 0x60, 0xe1, 0x60, 0x26, 0x54, 0x2b, 0xf2, 0x38, + 0xdf, 0x80, 0x21, 0x2e, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x96, 0x5f, 0x01, 0x57, 0x0f, 0x42, 0xe0, 0x2f, 0x08, 0x9b, 0xbb, 0xd5, + 0x10, 0x0d, 0xcc, 0x7e, 0x72, 0xd2, 0xc0, 0xca, 0x2c, 0xce, 0xe9, 0x1a, + 0xe5, 0x84, 0xcb, 0xf4, 0x16, 0xa3, 0xbb, 0x0c, 0x4a, 0x6d, 0x89, 0x1f, + 0xf8, 0x60, 0x23, 0xa1, 0x4f, 0x42, 0x6a, 0x98, 0xb1, 0xb6, 0xde, 0x05, + 0x3a, 0x39, 0x28, 0x5c, 0xdc, 0x3d, 0x8d, 0x16, 0xbc, 0x03, 0x07, 0x75, + 0x58, 0x63, 0x90, 0x25, 0x9f, 0x61, 0x7b, 0xc7, 0xb6, 0xca, 0x85, 0x0b, + 0xe4, 0x89, 0x17, 0xfb, 0x62, 0x34, 0xd7, 0x9a, 0x3c, 0xb9, 0x25, 0x8e, + 0x9a, 0x61, 0xf9, 0x86, 0x63, 0x4e, 0x87, 0xc7, 0xa9, 0x6b, 0x61, 0x21, + 0x82, 0x3f, 0x23, 0xee, 0x11, 0x89, 0xe2, 0x7e, 0x6d, 0x8a, 0x2c, 0x00, + 0x73, 0x87, 0x43, 0xed, 0x2d, 0x74, 0x1a, 0xb6, 0xaa, 0x0f, 0x83, 0x99, + 0xff, 0x68, 0xca, 0xf1, 0xfd, 0x4a, 0xf7, 0x06, 0xfa, 0x3b, 0x92, 0xff, + 0x8e, 0x1b, 0x06, 0x28, 0x7a, 0xe5, 0xde, 0x5b, 0x13, 0xf1, 0x88, 0x79, + 0x2d, 0xc6, 0x3a, 0xae, 0xf3, 0x4e, 0x8a, 0xe0, 0x99, 0xa9, 0x4d, 0xd2, + 0x73, 0x54, 0xb0, 0x0a, 0x64, 0xa8, 0x86, 0x58, 0x0e, 0xa8, 0x7d, 0xa6, + 0xa3, 0x81, 0x58, 0x10, 0x59, 0x88, 0x31, 0x4b, 0xbe, 0x77, 0x92, 0x21, + 0x47, 0x84, 0x88, 0x0f, 0x3b, 0xf5, 0x9a, 0x9d, 0xfe, 0xe6, 0x53, 0x14, + 0x19, 0x10, 0xf7, 0x33, 0x64, 0x3e, 0x5c, 0x14, 0xc2, 0x76, 0xc0, 0x59, + 0xf2, 0xa8, 0xaf, 0x01, 0xc0, 0x8c, 0x96, 0x1b, 0x84, 0x00, 0xa8, 0xb4, + 0x12, 0x7f, 0x1f, 0x6b, 0xf6, 0x47, 0x18, 0x19, 0x2a, 0x66, 0xb2, 0xef, + 0x0a, 0xb8, 0x7e, 0x3f, 0x25, 0xea, 0x6f, 0x63, 0x7a, 0xcb, 0xea, 0x12, + 0x32, 0x3f, 0xa0, 0xd0, 0x3e, 0x02, 0x38, 0x9c, 0x9a, 0xbf, 0x5e, 0xe9, + 0x09, 0xee, 0x6e, 0x26, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x0a, 0x4a, 0xc5, 0xe7, 0x11, 0xaf, 0xd5, 0x33, 0x92, 0xd5, 0xbc, 0xc5, + 0xbf, 0x61, 0x7e, 0x2d, 0x3e, 0x36, 0x73, 0x2c, 0x3b, 0x37, 0x01, 0x8c, + 0xf4, 0x46, 0x84, 0x22, 0xd9, 0xe1, 0x2e, 0x0f, 0x55, 0x3d, 0xf0, 0x8f, + 0xfc, 0x7e, 0x10, 0x88, 0x3e, 0x07, 0x71, 0x06, 0x7f, 0x16, 0x26, 0x5e, + 0xe8, 0x2f, 0x8b, 0x3f, 0x60, 0x24, 0x76, 0x1c, 0x47, 0xd7, 0x02, 0x97, + 0x53, 0xcd, 0x8e, 0x1d, 0xc5, 0xd3, 0x3c, 0xd8, 0xc8, 0xbe, 0x15, 0xfa, + 0x20, 0xb7, 0xc7, 0xba, 0xc2, 0xe1, 0x3b, 0x7c, 0x3d, 0x88, 0xc4, 0xe7, + 0x73, 0x5c, 0xe3, 0x3f, 0x54, 0x25, 0x52, 0xe8, 0xb2, 0xa1, 0xdd, 0x0b, + 0xbc, 0x8c, 0x07, 0x0f, 0x2a, 0xeb, 0x2c, 0x78, 0x42, 0xd6, 0x9b, 0x1a, + 0x0e, 0x98, 0xc1, 0x45, 0xaf, 0x4e, 0xd3, 0x73, 0xca, 0xc8, 0x1f, 0x2c, + 0x58, 0xdd, 0x98, 0xde, 0x1c, 0xe3, 0xb6, 0x1d, 0x7a, 0x0c, 0x29, 0xbb, + 0xce, 0xb2, 0xa0, 0x68, 0x59, 0x2a, 0xcf, 0xe6, 0xb9, 0x18, 0x76, 0x37, + 0x5a, 0xd6, 0x1a, 0xf1, 0x63, 0x19, 0xb2, 0x7c, 0xcd, 0x9c, 0xb7, 0x87, + 0xf1, 0x39, 0x7c, 0x26, 0xc0, 0x76, 0xbb, 0x8d, 0x46, 0xf2, 0x7c, 0x78, + 0x64, 0x4c, 0x31, 0xbd, 0x91, 0x7c, 0x75, 0x3a, 0xdc, 0x5e, 0xe8, 0x3e, + 0xa2, 0x1d, 0xdb, 0xfc, 0xad, 0xe6, 0x38, 0xb8, 0xfc, 0x2d, 0x08, 0x17, + 0x25, 0xa6, 0x48, 0x5e, 0x6d, 0x22, 0x41, 0xb9, 0x72, 0x3a, 0x74, 0xb3, + 0xa3, 0xff, 0x06, 0x61, 0xdc, 0x3e, 0x1a, 0xa2, 0x50, 0xc4, 0xa1, 0x64, + 0x38, 0x2f, 0x2a, 0xba, 0x0f, 0x04, 0xaa, 0x05, 0x58, 0xc6, 0xbe, 0x32, + 0xd2, 0xd6, 0xe1, 0xbf, 0x58, 0x3c, 0x4d, 0x4e, 0x69, 0x00, 0xf8, 0x02, + 0xbc, 0x7e, 0xbb, 0xff, 0x53, 0x9b, 0x23, 0xe2, 0x89, 0xfe, 0x79, 0xc7, + 0x4a, 0xda, 0xa6, 0x1e, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x3c, 0x60, 0xe5, 0x42, 0x30, 0xbc, 0x95, 0x79, 0xa1, 0x06, 0xe5, 0x08, + 0x12, 0xd8, 0x29, 0xcf, 0x43, 0x42, 0x67, 0x63, 0xec, 0xd4, 0x12, 0xc2, + 0xf4, 0xea, 0x2d, 0xb6, 0x54, 0xfb, 0xbe, 0x0c, 0xd0, 0x2d, 0x98, 0xde, + 0xa6, 0x42, 0xb5, 0x34, 0xdd, 0x82, 0x8b, 0xe2, 0x32, 0xb8, 0xb3, 0x41, + 0xb6, 0xc3, 0x50, 0xc9, 0x35, 0xf4, 0xa6, 0xf5, 0xfb, 0xcc, 0xa0, 0xdf, + 0xf0, 0x2f, 0x6d, 0x10, 0x37, 0x05, 0xb2, 0x59, 0x75, 0x95, 0x6a, 0x35, + 0x9a, 0x0e, 0x9b, 0x52, 0x51, 0x35, 0xd6, 0xa9, 0xd1, 0xcf, 0xf7, 0xfe, + 0x11, 0x68, 0x71, 0xed, 0xa0, 0x92, 0x11, 0x72, 0xaa, 0xbf, 0x0f, 0x19, + 0x67, 0xcf, 0x3f, 0x32, 0x14, 0xda, 0xbb, 0x37, 0x90, 0x06, 0x75, 0x02, + 0x3e, 0x4f, 0x2e, 0x14, 0x4f, 0xef, 0x47, 0x54, 0x8b, 0x15, 0x7b, 0x03, + 0x38, 0x18, 0x91, 0xa2, 0xf6, 0x05, 0x1f, 0x09, 0x7a, 0xce, 0xdf, 0xd4, + 0x43, 0xae, 0xad, 0x58, 0xd2, 0xca, 0x1e, 0xc6, 0x9c, 0xce, 0x1e, 0xb6, + 0xa3, 0x7c, 0x7c, 0x06, 0x54, 0x3a, 0x39, 0x17, 0xaa, 0xfa, 0x49, 0x91, + 0xef, 0x9d, 0x60, 0x27, 0xed, 0x55, 0x50, 0xe0, 0xf9, 0xc6, 0xa0, 0xd1, + 0xb2, 0x01, 0x8d, 0x4e, 0x6a, 0xeb, 0x0b, 0x99, 0x6d, 0x01, 0xd7, 0x5c, + 0x11, 0xfc, 0x0b, 0x56, 0x09, 0xd3, 0x9b, 0x96, 0x7b, 0xfe, 0xd4, 0x03, + 0xe8, 0xb5, 0xad, 0x7e, 0x70, 0xf3, 0x08, 0x43, 0xe1, 0xc2, 0x53, 0x09, + 0xb6, 0x09, 0xe3, 0x0a, 0xc5, 0x45, 0x98, 0x58, 0x78, 0xf5, 0x85, 0x39, + 0xdb, 0x42, 0xe4, 0x4a, 0x5e, 0x1a, 0xb7, 0x0e, 0x80, 0xb6, 0xd0, 0x1c, + 0xf6, 0x22, 0x7f, 0xc7, 0xec, 0xda, 0xb5, 0xfa, 0xc0, 0xa4, 0xab, 0x40, + 0x8f, 0xf1, 0x71, 0xc3, 0x9e, 0x54, 0xa5, 0xb7, 0x99, 0x68, 0x26, 0x58, + 0x6b, 0xb4, 0xce, 0x26, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x8d, 0x2f, 0x6a, 0x8e, 0x80, 0x85, 0x36, 0x45, 0xe7, 0x1f, 0x6f, 0x8b, + 0x42, 0x66, 0x5b, 0x4f, 0xc4, 0xea, 0xac, 0x15, 0x7d, 0x6f, 0xdc, 0xb1, + 0x3c, 0x11, 0x21, 0x3b, 0x20, 0xce, 0x7a, 0x11, 0xdf, 0x8f, 0x71, 0x28, + 0xa3, 0x17, 0x10, 0x28, 0x7d, 0xa3, 0xd3, 0xee, 0xfb, 0x6e, 0x44, 0x7b, + 0x6f, 0xc3, 0xcd, 0xa1, 0x8e, 0x2e, 0x51, 0x5c, 0xee, 0x22, 0xcb, 0x4e, + 0xa4, 0x66, 0xe2, 0x16, 0x57, 0xff, 0xad, 0x8a, 0xdc, 0x61, 0x5b, 0xad, + 0x3c, 0xea, 0x69, 0x02, 0x13, 0x1d, 0x77, 0x11, 0x04, 0x24, 0x60, 0x90, + 0x4b, 0xcc, 0xc6, 0xb5, 0x2b, 0x08, 0x5c, 0x91, 0x5c, 0x4a, 0x09, 0x0c, + 0xb3, 0xae, 0x29, 0xb8, 0x00, 0x8b, 0x6d, 0xe3, 0xf2, 0xdb, 0x63, 0x5f, + 0xca, 0x79, 0x3c, 0x32, 0x68, 0x3a, 0xa9, 0x87, 0x9c, 0x7d, 0x34, 0xe4, + 0x7a, 0x55, 0xa9, 0x8b, 0x69, 0x74, 0x94, 0x0c, 0xaf, 0xe3, 0xe4, 0x8f, + 0x52, 0x6e, 0xa4, 0xa2, 0xf0, 0x21, 0xee, 0x4f, 0xb5, 0x88, 0x97, 0x61, + 0xdc, 0x44, 0xe7, 0x3a, 0xdf, 0xbc, 0xc4, 0x35, 0xb4, 0x33, 0xbc, 0x2e, + 0x90, 0x26, 0x53, 0x12, 0x3c, 0x56, 0x0a, 0x7a, 0x24, 0x96, 0xc5, 0x6b, + 0xef, 0xc6, 0x13, 0x8d, 0x44, 0xb0, 0x26, 0x47, 0x78, 0x9b, 0xc2, 0x0a, + 0xb7, 0xb3, 0xfc, 0x19, 0xa1, 0x81, 0x7f, 0x99, 0x0b, 0x42, 0x1e, 0x17, + 0x46, 0x5b, 0x9e, 0x1d, 0xae, 0xd0, 0xcf, 0x57, 0x45, 0x16, 0xfa, 0x47, + 0x10, 0xc6, 0xa5, 0xf0, 0x99, 0x7c, 0x86, 0x40, 0x30, 0xed, 0x57, 0xce, + 0x56, 0x97, 0xad, 0xa7, 0x80, 0xc2, 0xc4, 0x0f, 0x4b, 0x63, 0x39, 0xb1, + 0x82, 0xd2, 0xd2, 0x64, 0x40, 0xf7, 0xc0, 0x03, 0x38, 0xa1, 0xda, 0x7c, + 0x38, 0x83, 0x5c, 0x70, 0xad, 0x85, 0xec, 0x25, 0x58, 0x69, 0xfd, 0x99, + 0xdd, 0x61, 0xc8, 0x07, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6f, 0x66, 0x3f, 0x43, 0x68, 0x55, 0x74, 0x6c, 0x5d, 0xae, 0x4a, 0x91, + 0xfb, 0xdb, 0x64, 0x94, 0x4b, 0x45, 0xc5, 0x71, 0x27, 0xe4, 0x07, 0xd0, + 0xb5, 0xa6, 0x9e, 0x89, 0x12, 0x5d, 0xec, 0x29, 0x43, 0x64, 0x03, 0xa0, + 0xb9, 0xef, 0x3b, 0xa3, 0x42, 0xad, 0xf0, 0x07, 0x80, 0x3c, 0xe5, 0xd4, + 0x9c, 0x06, 0x06, 0xf3, 0x6a, 0xd5, 0xb7, 0x73, 0x28, 0x57, 0x40, 0x9d, + 0x10, 0x25, 0x1f, 0x00, 0xf9, 0xd5, 0xb9, 0x62, 0x28, 0x7a, 0x19, 0xfe, + 0x6d, 0x26, 0xd5, 0xce, 0x7a, 0x71, 0xa2, 0xff, 0xf5, 0x7a, 0xf9, 0x15, + 0x8e, 0xa5, 0x1e, 0x12, 0x4e, 0x6f, 0xf0, 0x45, 0x88, 0x9e, 0x6d, 0x09, + 0x7e, 0x20, 0x72, 0xdc, 0x53, 0xc6, 0x4c, 0x3c, 0x0a, 0xa6, 0x11, 0x92, + 0x6b, 0x44, 0x1a, 0x4e, 0x98, 0x67, 0x92, 0x57, 0x79, 0xb2, 0x9e, 0x05, + 0xee, 0x1e, 0x2a, 0x6b, 0x7c, 0xaa, 0x5f, 0x0d, 0x71, 0x71, 0x4d, 0x90, + 0x5b, 0x38, 0x76, 0xc1, 0x13, 0xaf, 0xda, 0xe1, 0xcc, 0x9e, 0xba, 0x7f, + 0xa3, 0x92, 0x57, 0xe3, 0xa3, 0xca, 0x8e, 0x0f, 0xfa, 0xd8, 0x51, 0xb1, + 0x89, 0x6a, 0xae, 0x2f, 0x3f, 0xe7, 0xc0, 0x71, 0x96, 0xb7, 0x79, 0x51, + 0x0f, 0xff, 0x76, 0xb2, 0xf3, 0xf9, 0xc9, 0x99, 0x7c, 0x9d, 0x20, 0xfe, + 0xdf, 0x43, 0xbe, 0x40, 0x57, 0x66, 0xc9, 0x1b, 0x8c, 0x8a, 0xfb, 0x10, + 0xf0, 0xf5, 0x5f, 0xcd, 0xf4, 0x26, 0x10, 0x44, 0xcc, 0x43, 0x7f, 0x0b, + 0x18, 0xa2, 0x05, 0xe6, 0xa3, 0x89, 0x91, 0x9b, 0x44, 0xe3, 0xf1, 0x9d, + 0x76, 0x7c, 0x6f, 0xd7, 0xfb, 0xcb, 0x4e, 0x09, 0x54, 0x06, 0x51, 0x59, + 0xec, 0xa9, 0xfd, 0x6a, 0x7c, 0x85, 0x0e, 0x13, 0x1c, 0x4c, 0x35, 0xa9, + 0xbe, 0xf3, 0xf6, 0x36, 0xc6, 0x0e, 0x51, 0x61, 0xe8, 0x1b, 0xe6, 0xae, + 0xb0, 0x34, 0xd5, 0x1c, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xdb, 0xff, 0xa3, 0x9d, 0x82, 0xe0, 0xfd, 0x3d, 0x98, 0x49, 0x10, 0xa3, + 0x39, 0x44, 0xdf, 0x59, 0xb5, 0xad, 0x9a, 0x91, 0x31, 0x5e, 0x9e, 0x06, + 0x1d, 0xfc, 0x9f, 0xf4, 0x5c, 0xe6, 0x0b, 0x2e, 0xeb, 0x1c, 0x86, 0x42, + 0xfa, 0xb8, 0xae, 0xc6, 0xb8, 0x38, 0x4e, 0x88, 0xe8, 0x33, 0x2b, 0x45, + 0x58, 0x6b, 0x07, 0x3f, 0xd7, 0x4d, 0x0f, 0x2c, 0x60, 0x0b, 0xf3, 0x08, + 0xb0, 0xe5, 0x2f, 0x2e, 0x58, 0xac, 0x24, 0x0c, 0x82, 0x18, 0x43, 0x43, + 0x11, 0x59, 0x46, 0xfc, 0xcd, 0x7a, 0x81, 0xb3, 0x0c, 0xf6, 0x64, 0x95, + 0x24, 0xde, 0x94, 0xb1, 0x6b, 0x2b, 0xcd, 0x13, 0xa9, 0x6e, 0x66, 0x2b, + 0x38, 0xb9, 0x3a, 0x7a, 0x53, 0x1c, 0xb8, 0xd5, 0x0f, 0xad, 0xc7, 0x31, + 0xe4, 0x88, 0x57, 0xd7, 0xe8, 0x7e, 0x43, 0xd3, 0xbc, 0xbd, 0xab, 0x91, + 0x5c, 0x33, 0x94, 0xee, 0xb3, 0x01, 0xf6, 0x23, 0x26, 0x4c, 0xf5, 0xa1, + 0x50, 0x2a, 0xc8, 0xbf, 0xe5, 0x2c, 0x89, 0x37, 0x4b, 0xf5, 0xde, 0x1d, + 0x2a, 0x59, 0x24, 0x42, 0x9d, 0x65, 0x99, 0xbd, 0xf0, 0x24, 0xa6, 0x14, + 0x7a, 0x17, 0x33, 0x0d, 0xaa, 0x2e, 0xa7, 0xdb, 0x37, 0x79, 0xd7, 0x96, + 0x1e, 0x38, 0x47, 0x6e, 0x36, 0xef, 0x50, 0xd2, 0x16, 0xc7, 0x3b, 0x9b, + 0xfc, 0xb4, 0x2b, 0xbb, 0x93, 0x05, 0x75, 0x79, 0x4b, 0xd7, 0x0e, 0x14, + 0x25, 0x1c, 0xae, 0xfe, 0x08, 0xe4, 0xf4, 0x1a, 0xd3, 0xfa, 0x30, 0xce, + 0x16, 0x4c, 0xb1, 0x6a, 0xce, 0xbb, 0x43, 0x4a, 0x1b, 0x93, 0x3f, 0xc2, + 0x61, 0xcb, 0x81, 0xd4, 0xb3, 0xf5, 0x56, 0x1f, 0x4d, 0x61, 0x60, 0x50, + 0x54, 0xe3, 0xca, 0x91, 0xa8, 0x07, 0xba, 0x75, 0x41, 0x53, 0x9c, 0x94, + 0xc3, 0x37, 0x9f, 0xb2, 0x0c, 0x8a, 0xce, 0xcc, 0x44, 0x0c, 0xa6, 0xcc, + 0xe6, 0x71, 0x14, 0x0c, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0x54, 0x54, 0x67, 0xca, 0x3d, 0x80, 0xd6, 0x2c, 0xb4, 0x1a, 0xe3, + 0x0d, 0x90, 0xc7, 0x76, 0xd2, 0x27, 0x36, 0x26, 0x65, 0xea, 0x03, 0x80, + 0x1c, 0x40, 0x3a, 0x51, 0x55, 0xc4, 0x68, 0x11, 0x43, 0xda, 0xc7, 0x99, + 0x15, 0xc8, 0xc4, 0xa9, 0x77, 0xd7, 0xc3, 0x16, 0x4b, 0xd8, 0x45, 0x5b, + 0x78, 0x57, 0x37, 0xca, 0xde, 0x34, 0x13, 0xd2, 0xa7, 0xf8, 0x2c, 0xb1, + 0x22, 0xf6, 0x54, 0x0f, 0x04, 0x23, 0xd5, 0xed, 0x7d, 0xe9, 0xb3, 0xe3, + 0xf1, 0x77, 0xc6, 0xcf, 0x4f, 0x16, 0x52, 0xb8, 0x10, 0xd1, 0xee, 0xce, + 0x44, 0x7d, 0xd4, 0xcb, 0x2e, 0x66, 0x4d, 0xb0, 0x38, 0xe7, 0x01, 0x23, + 0xb7, 0xed, 0x48, 0x34, 0xc3, 0xdf, 0x7d, 0xe6, 0x88, 0xeb, 0x5a, 0x7f, + 0x0f, 0x35, 0x68, 0xc7, 0x8c, 0xe1, 0x9d, 0xee, 0xdf, 0x66, 0x2d, 0xbb, + 0x9f, 0x4a, 0xe6, 0xd0, 0x23, 0xc4, 0xdc, 0x20, 0x85, 0xcc, 0x9d, 0xa6, + 0xb7, 0x7c, 0x87, 0xcb, 0x93, 0xc5, 0xd9, 0x38, 0xb0, 0xa7, 0xb8, 0xb1, + 0x5c, 0x87, 0xdc, 0xa3, 0x4a, 0x85, 0xde, 0xea, 0x16, 0xff, 0x1a, 0x96, + 0x89, 0x7b, 0x20, 0x21, 0xfa, 0x7d, 0xf1, 0x8f, 0x4e, 0x77, 0x6b, 0x81, + 0x90, 0x6a, 0xe0, 0x2c, 0xb5, 0x62, 0xf1, 0xcd, 0xdf, 0xa1, 0x9d, 0x04, + 0x9e, 0x37, 0x4f, 0x08, 0x98, 0xcf, 0x43, 0x92, 0x32, 0x47, 0x9d, 0x13, + 0x0c, 0xf0, 0x41, 0x9a, 0xdb, 0xac, 0x1f, 0xe4, 0x1b, 0x7f, 0x28, 0xa8, + 0xdb, 0x61, 0x0a, 0x27, 0x71, 0x74, 0x42, 0x3d, 0x47, 0xb5, 0xef, 0x0f, + 0x37, 0x87, 0xc5, 0x88, 0x62, 0x37, 0x28, 0x0e, 0x0a, 0x69, 0x7d, 0x2a, + 0x98, 0x0d, 0xb5, 0xd6, 0x92, 0x01, 0x5e, 0x7d, 0xbb, 0xe5, 0x4b, 0x06, + 0x8d, 0x82, 0x5d, 0x58, 0x4e, 0xe9, 0x36, 0x96, 0x7f, 0xaa, 0x4f, 0x7c, + 0xd5, 0xc1, 0xce, 0x2c, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0x54, 0x94, 0x01, 0xf2, 0x2c, 0xd6, 0x27, 0x81, 0x19, 0xdd, 0xf2, + 0x28, 0x8a, 0xaa, 0x9a, 0xbc, 0xd4, 0x6a, 0x36, 0x9a, 0x16, 0xc2, 0xd4, + 0x2a, 0x6d, 0x31, 0x6b, 0x7f, 0x6f, 0x21, 0x10, 0x82, 0x91, 0x3a, 0x76, + 0xf3, 0x54, 0x65, 0x38, 0x57, 0x5c, 0x96, 0x5c, 0xd6, 0x07, 0xef, 0x7c, + 0xce, 0x7c, 0xf9, 0x1a, 0xd1, 0xf1, 0x98, 0xac, 0xf8, 0x14, 0x0d, 0xc9, + 0x10, 0x84, 0xd3, 0x0d, 0x86, 0xb4, 0xaf, 0xa3, 0xe1, 0x84, 0x93, 0x21, + 0x1f, 0x1c, 0xca, 0xfe, 0x83, 0x9c, 0x64, 0xcc, 0xdd, 0xdf, 0xf6, 0x9d, + 0x61, 0xac, 0xf7, 0x1d, 0x92, 0xc6, 0x12, 0x48, 0x78, 0x8c, 0x7a, 0x29, + 0xf6, 0xa4, 0x73, 0x74, 0xc0, 0xa7, 0x5f, 0x65, 0xa3, 0x35, 0x86, 0x58, + 0x25, 0x69, 0x02, 0x92, 0xe0, 0xf1, 0xcd, 0x97, 0xdc, 0xfc, 0x15, 0xd9, + 0x7b, 0xe9, 0x3a, 0xe8, 0xc9, 0x4f, 0x30, 0x1d, 0x1d, 0x98, 0x3e, 0xba, + 0x46, 0xf0, 0x49, 0x28, 0xb3, 0xf0, 0xbe, 0xb0, 0x27, 0x07, 0x8e, 0xae, + 0x13, 0x7f, 0xf9, 0x7e, 0x8e, 0x2a, 0xcb, 0x49, 0x06, 0x52, 0x3a, 0x56, + 0x48, 0x93, 0xdd, 0x18, 0x45, 0x0d, 0x49, 0xb6, 0xc9, 0xaf, 0x5a, 0x32, + 0xfc, 0x45, 0xd3, 0x55, 0xde, 0xe7, 0x74, 0x2a, 0xc3, 0x9c, 0xe0, 0x8e, + 0xe0, 0x34, 0x9a, 0x05, 0xe3, 0x20, 0x1d, 0xee, 0xac, 0xad, 0x63, 0x0a, + 0x40, 0x0d, 0x82, 0x42, 0x11, 0x2e, 0x36, 0xc2, 0x6e, 0x63, 0xb3, 0x2e, + 0x94, 0xf0, 0xcc, 0x70, 0xaf, 0x4e, 0xb8, 0x09, 0xb4, 0x73, 0x74, 0xf9, + 0xda, 0xb8, 0x03, 0x67, 0x1f, 0x46, 0x9f, 0x2c, 0xf0, 0x2d, 0xaa, 0xc3, + 0x16, 0x02, 0x4a, 0x56, 0x5c, 0x64, 0xbf, 0x8c, 0xd3, 0xf5, 0x83, 0xc7, + 0xcb, 0x24, 0xbb, 0x08, 0xf4, 0xa2, 0x31, 0xae, 0xb8, 0xec, 0x13, 0xce, + 0xcb, 0xf4, 0xcd, 0x27, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0x54, 0xdc, 0x5f, 0xc2, 0x8d, 0xf2, 0x50, 0xf3, 0x80, 0xda, 0xcd, + 0x88, 0xea, 0x0f, 0x08, 0xcf, 0xd4, 0xb3, 0x57, 0x44, 0x6d, 0xd9, 0x13, + 0x4d, 0xeb, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x86, 0xb4, 0xdf, 0x3d, + 0x0c, 0xa3, 0xb1, 0x22, 0x9b, 0x46, 0x3a, 0x31, 0x0f, 0x82, 0xe5, 0x97, + 0x61, 0xce, 0xc7, 0x66, 0x94, 0x5a, 0x14, 0xc9, 0x25, 0x35, 0xe1, 0x77, + 0x62, 0x8c, 0x7a, 0x29, 0x82, 0x91, 0x6c, 0x6b, 0x22, 0x64, 0x75, 0xc0, + 0xb0, 0xca, 0x54, 0x12, 0xd4, 0x62, 0xd0, 0x6e, 0x05, 0x2c, 0x32, 0x1a, + 0x9e, 0x95, 0x13, 0xdf, 0x98, 0xb7, 0xa0, 0xd2, 0x20, 0x84, 0xd3, 0x0d, + 0x74, 0x13, 0xd1, 0xee, 0xfd, 0x0d, 0xdc, 0x7d, 0xe6, 0xe7, 0xde, 0xdd, + 0x29, 0xb8, 0x89, 0xb6, 0x9f, 0x93, 0x8b, 0x3c, 0x70, 0x25, 0xa4, 0xec, + 0xd7, 0xf5, 0x23, 0xb1, 0xb2, 0xcb, 0x5c, 0x0f, 0xba, 0xc9, 0x3d, 0x6d, + 0xbf, 0x4d, 0x3e, 0xf9, 0x28, 0x11, 0x27, 0xd0, 0x7c, 0x42, 0x95, 0x16, + 0xea, 0x3e, 0x98, 0xbb, 0x6f, 0x61, 0xae, 0xc5, 0xb7, 0xef, 0x65, 0x8d, + 0xdd, 0xa4, 0x6d, 0x02, 0xb4, 0xa4, 0xa3, 0xce, 0x06, 0x14, 0xea, 0xc3, + 0xde, 0x73, 0x5f, 0x27, 0xc0, 0x2d, 0x88, 0x11, 0x5b, 0xf1, 0x4c, 0x45, + 0x5d, 0x99, 0x3c, 0xd0, 0x0a, 0xe9, 0x89, 0xb5, 0x40, 0x66, 0xa4, 0x2e, + 0x4c, 0x24, 0xe9, 0x7f, 0xe8, 0x1f, 0x30, 0x0f, 0xfb, 0x03, 0x40, 0x6f, + 0xbb, 0xe3, 0xd1, 0x29, 0x8a, 0x0e, 0x2c, 0x45, 0xb8, 0xde, 0x4f, 0x4d, + 0xf2, 0x48, 0xd5, 0x49, 0xbc, 0x5f, 0xf3, 0x08, 0xc2, 0x88, 0x9c, 0xaa, + 0xfa, 0x9d, 0xce, 0xa5, 0xed, 0xef, 0x5e, 0xe6, 0x4c, 0x5c, 0x67, 0xf4, + 0x6e, 0xc7, 0x36, 0x28, 0xfe, 0xb3, 0x20, 0x45, 0x0f, 0x11, 0xa0, 0xfb, + 0x43, 0x76, 0x27, 0x1b, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0x54, 0xa0, 0x49, 0x66, 0x53, 0xf1, 0xc8, 0x43, 0x53, 0x41, 0x9e, + 0x14, 0xbf, 0xe3, 0xa0, 0xa5, 0x77, 0xfa, 0xec, 0xe8, 0x1c, 0x3c, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0xc5, 0x6b, 0xf8, 0xd3, + 0x2b, 0x20, 0x3a, 0x02, 0x61, 0xdd, 0x3c, 0xf4, 0x16, 0xac, 0x68, 0xe0, + 0x78, 0x76, 0x1a, 0x13, 0xe5, 0xb3, 0x87, 0x5e, 0x42, 0x29, 0x91, 0x0e, + 0x52, 0xca, 0x90, 0x22, 0xc1, 0x48, 0x0f, 0xe9, 0xd8, 0x2e, 0x36, 0xa5, + 0x58, 0xda, 0x5a, 0xcf, 0x7d, 0xd7, 0x89, 0x04, 0x98, 0xf5, 0x9c, 0xf4, + 0xc0, 0x9e, 0x5d, 0xad, 0x73, 0x3b, 0x50, 0x69, 0x10, 0xc2, 0xe9, 0x06, + 0xf2, 0x01, 0xfc, 0x0d, 0x5b, 0x7e, 0xbf, 0xe2, 0xae, 0x0e, 0xf3, 0x4a, + 0xcd, 0x42, 0xd9, 0xd7, 0x0e, 0x16, 0xd5, 0xa1, 0x07, 0xa9, 0x95, 0x09, + 0x6f, 0x9b, 0x83, 0xde, 0x91, 0x47, 0x89, 0x01, 0x1c, 0x0c, 0x6b, 0x81, + 0xc2, 0x9e, 0xd9, 0x27, 0x42, 0x34, 0xfc, 0xef, 0xad, 0x88, 0x63, 0xa1, + 0xa6, 0x56, 0x74, 0x19, 0x6f, 0x9b, 0x5b, 0xc7, 0x40, 0x9c, 0x09, 0x9e, + 0xb0, 0x2e, 0xb5, 0x28, 0xf9, 0x49, 0xf1, 0x3e, 0x70, 0xdc, 0xa8, 0xf1, + 0x35, 0x16, 0x64, 0x57, 0xda, 0x59, 0x7e, 0xf1, 0x67, 0xba, 0xb7, 0xce, + 0x58, 0x78, 0x2f, 0xfc, 0xb3, 0xba, 0xa6, 0xa5, 0xfd, 0x32, 0x25, 0x18, + 0xbf, 0x65, 0xc0, 0xf5, 0x9e, 0xe0, 0x22, 0x08, 0x6c, 0x71, 0x0f, 0xf7, + 0x78, 0x8e, 0xfe, 0x2a, 0xa0, 0x08, 0xf0, 0x89, 0xe2, 0xaf, 0xf1, 0x79, + 0xf4, 0xb8, 0xf3, 0x38, 0x35, 0xb4, 0x21, 0x1c, 0xaa, 0x3d, 0xfa, 0xb0, + 0x48, 0xd9, 0x94, 0xc6, 0x01, 0x95, 0x9d, 0xc3, 0xf9, 0x51, 0xd9, 0xa6, + 0xac, 0xf0, 0xca, 0x1a, 0x6a, 0xf8, 0x69, 0xa2, 0x9b, 0xc3, 0x41, 0x7e, + 0xfb, 0x9a, 0xe9, 0x2b, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0xd4, 0x20, 0xbb, 0xd1, 0x13, 0x55, 0xfa, 0x9b, 0x2a, 0x0a, 0xbc, + 0xe9, 0xc0, 0x78, 0x15, 0x6c, 0x50, 0x6d, 0xe3, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x86, 0xb4, 0x1c, 0x59, + 0x74, 0x2c, 0xf3, 0xf7, 0x2e, 0xdb, 0x90, 0x79, 0xd4, 0x95, 0x29, 0x88, + 0x9b, 0x69, 0x36, 0xf1, 0xe3, 0x84, 0xb2, 0x0b, 0xb6, 0x64, 0xe1, 0x77, + 0x62, 0x8c, 0x7a, 0x29, 0x82, 0xb1, 0xa2, 0x7d, 0x1f, 0x5a, 0xdb, 0xb0, + 0x3e, 0x3c, 0x25, 0x64, 0xb1, 0xc1, 0x0d, 0x29, 0x9e, 0x1e, 0xe5, 0x14, + 0xa4, 0x81, 0x3b, 0x59, 0xe7, 0x76, 0xa0, 0xd2, 0x20, 0x84, 0xd3, 0x0d, + 0xf6, 0xa4, 0xc4, 0x8e, 0xd7, 0xcc, 0x90, 0x59, 0x26, 0x3f, 0xb9, 0x99, + 0x12, 0xe2, 0x62, 0x8a, 0xdb, 0x19, 0x84, 0xd5, 0x1b, 0x2e, 0x61, 0xbc, + 0x3d, 0x89, 0xc4, 0x83, 0xd3, 0x4f, 0x30, 0x1d, 0x38, 0xc9, 0xec, 0xe4, + 0xbb, 0xda, 0x0c, 0x8c, 0x54, 0x40, 0x2b, 0x95, 0xcf, 0xb8, 0x16, 0xdc, + 0xe8, 0x69, 0x82, 0xea, 0x59, 0x02, 0xfe, 0xb1, 0x5e, 0x06, 0xf5, 0xa6, + 0xcd, 0xf7, 0x3a, 0x02, 0xad, 0x46, 0xbc, 0xb8, 0x02, 0x37, 0xaa, 0xc8, + 0x86, 0x20, 0x6c, 0x1f, 0x20, 0x79, 0xa7, 0x4d, 0x32, 0xf2, 0xf7, 0x77, + 0x2d, 0xd0, 0x01, 0xc7, 0x9c, 0xd7, 0x2e, 0x13, 0x38, 0xc2, 0xda, 0x27, + 0x85, 0x4b, 0xd0, 0x64, 0x13, 0xf6, 0x79, 0x05, 0x90, 0xc3, 0x89, 0x4b, + 0xf4, 0x58, 0x9e, 0x47, 0xac, 0x2d, 0x91, 0x98, 0x41, 0x5a, 0x4a, 0x96, + 0x19, 0xe0, 0xd3, 0x87, 0x03, 0x1b, 0x91, 0x17, 0x24, 0x9c, 0xf9, 0x39, + 0x67, 0x25, 0x57, 0x81, 0xeb, 0x7f, 0x75, 0xec, 0x87, 0x3a, 0xa2, 0x5e, + 0xe4, 0xb9, 0xcc, 0x7d, 0x18, 0xf3, 0xdb, 0x95, 0xcd, 0xe0, 0xb2, 0xff, + 0xc6, 0x25, 0x65, 0x02, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0x14, 0x4f, 0x66, 0x98, 0x05, 0x8e, 0xbd, 0xaa, 0xe9, 0x63, 0x4d, + 0xbe, 0xfd, 0x4e, 0x41, 0xef, 0x73, 0x80, 0x80, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x82, 0xf1, 0x84, 0x6d, + 0xd5, 0x4f, 0x90, 0xf5, 0x67, 0xe8, 0x26, 0x42, 0xc6, 0xf3, 0xd0, 0xf6, + 0x41, 0xcb, 0xdb, 0xdb, 0xa1, 0x81, 0x3b, 0x59, 0xe7, 0x76, 0xa0, 0xd2, + 0x20, 0x84, 0xd3, 0x0d, 0x00, 0x20, 0x52, 0x55, 0xdc, 0x8d, 0x28, 0x12, + 0x70, 0x0b, 0x08, 0x78, 0x60, 0xe7, 0xe5, 0xa3, 0x97, 0x06, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb7, 0x85, 0x79, 0xa7, 0x9e, 0x8b, 0x26, 0xa1, 0xab, 0x59, 0x7b, 0xb2, + 0xcc, 0x64, 0x58, 0x9e, 0x25, 0x47, 0x13, 0xbe, 0xed, 0xee, 0xfe, 0x68, + 0xb1, 0xc4, 0x14, 0xed, 0xe3, 0x11, 0x1a, 0x24, 0xff, 0x1c, 0xbd, 0x5d, + 0x31, 0x7f, 0xd4, 0x98, 0x12, 0xe8, 0x24, 0x10, 0xdc, 0x56, 0xf6, 0xcd, + 0x42, 0xe8, 0x4e, 0x03, 0x22, 0xa8, 0x01, 0x80, 0x99, 0x9c, 0x79, 0xff, + 0x74, 0xcd, 0x3a, 0x21, 0x23, 0x10, 0xb7, 0xec, 0x76, 0x32, 0x23, 0x00, + 0x81, 0xbe, 0x7f, 0x39, 0xa4, 0x44, 0x51, 0xf4, 0x55, 0x6c, 0x3a, 0x36, + 0x8a, 0x97, 0x48, 0xd1, 0x80, 0xee, 0x94, 0x0c, 0x40, 0x01, 0xc7, 0x1e, + 0x9f, 0x3f, 0x9c, 0xf8, 0xd9, 0x84, 0x9e, 0xbc, 0x08, 0xf4, 0x1b, 0xff, + 0x13, 0xb5, 0x44, 0x77, 0xc6, 0x64, 0x66, 0x15, 0xf6, 0xfb, 0x68, 0x8e, + 0xb2, 0x3f, 0x15, 0xca, 0x29, 0x0c, 0x37, 0x06, 0xb0, 0xac, 0xe8, 0x16, + 0x72, 0x80, 0x52, 0xe9, 0x72, 0xd1, 0x96, 0xf1, 0xe8, 0x94, 0xa4, 0xb8, + 0x1c, 0x5b, 0x2d, 0x19, 0xe6, 0x30, 0xdb, 0xcf, 0x45, 0xca, 0xc7, 0x84, + 0x8c, 0xe2, 0x8d, 0x2f, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0xdc, 0x56, 0xd8, 0x65, 0x6f, 0xf0, 0x3b, 0xb9, 0xda, 0xef, 0x7e, + 0xa8, 0x89, 0x2e, 0xdd, 0xc9, 0x72, 0x80, 0x80, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x86, 0x04, 0xc9, 0x15, + 0x3c, 0xee, 0x2c, 0xf2, 0xb1, 0x63, 0x4d, 0xd1, 0x52, 0xb2, 0xa9, 0x38, + 0x50, 0x70, 0x93, 0x93, 0xe5, 0x84, 0xb2, 0x0b, 0xb6, 0x64, 0xe1, 0x77, + 0x62, 0x8c, 0x7a, 0x29, 0x00, 0xf2, 0xcf, 0xbb, 0x62, 0x39, 0x78, 0x06, + 0x2e, 0x9b, 0x62, 0x26, 0x2e, 0x8d, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf6, 0x74, 0x98, 0xde, 0x95, 0xea, 0xf3, 0x67, 0x0b, 0x5c, 0xab, 0xd5, + 0x7a, 0x11, 0x2d, 0x90, 0xff, 0x61, 0x25, 0xd0, 0x1c, 0x2e, 0x61, 0xbc, + 0x3d, 0x89, 0xc4, 0x83, 0xd3, 0x4f, 0x30, 0x1d, 0x0f, 0xb8, 0x91, 0xe7, + 0xec, 0x3c, 0x93, 0xf8, 0xca, 0x0c, 0x7b, 0x87, 0x2a, 0x11, 0x5a, 0xf7, + 0xfd, 0x37, 0x06, 0x2e, 0xa9, 0x10, 0xea, 0x5c, 0xc4, 0x2f, 0x69, 0xe2, + 0x7f, 0x54, 0x5c, 0x20, 0xd0, 0x85, 0x54, 0xc0, 0xd5, 0x76, 0xce, 0x18, + 0xcb, 0x7e, 0x48, 0x7c, 0xa4, 0x06, 0xd1, 0x62, 0x22, 0x4b, 0x7a, 0xaa, + 0x72, 0xe9, 0x66, 0x8f, 0xbd, 0x06, 0x83, 0x8b, 0x71, 0xeb, 0xd0, 0x1b, + 0xbe, 0xdd, 0xf1, 0x11, 0x0e, 0xbd, 0x54, 0xad, 0xed, 0xb8, 0x6c, 0x13, + 0xfd, 0x53, 0x3d, 0x56, 0x33, 0x2b, 0xb3, 0x01, 0x4c, 0xc4, 0x1e, 0x75, + 0x67, 0xbb, 0x78, 0xe2, 0xee, 0x65, 0x6b, 0x27, 0x42, 0xcd, 0xba, 0x24, + 0xff, 0x75, 0x27, 0x91, 0x5f, 0x19, 0xdd, 0x67, 0x4a, 0xae, 0x4f, 0x9c, + 0x4c, 0x66, 0x06, 0xec, 0x49, 0xfb, 0xaa, 0x32, 0x2c, 0xee, 0x76, 0x43, + 0x09, 0x82, 0x77, 0x0f, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x6d, 0xe0, 0x54, 0x7e, 0x57, 0x52, 0x35, 0xfc, 0x55, 0xe6, 0x8f, 0xd7, + 0x85, 0x23, 0x2b, 0xdd, 0xc9, 0x72, 0x80, 0x80, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x86, 0xaa, 0x39, 0x1c, + 0xfc, 0xa9, 0x15, 0xd3, 0x69, 0xa9, 0x76, 0x53, 0x33, 0x12, 0xb8, 0x38, + 0x50, 0x70, 0x93, 0x93, 0xe5, 0x84, 0xb2, 0x0b, 0xb6, 0x64, 0xe1, 0x77, + 0x62, 0x8c, 0x7a, 0x29, 0x43, 0x7c, 0x17, 0x51, 0xb2, 0xad, 0x83, 0xe1, + 0xc8, 0x7d, 0x08, 0xf9, 0x19, 0x09, 0x5c, 0x1c, 0x28, 0xb8, 0xc9, 0xc9, + 0x72, 0x42, 0xd9, 0x05, 0x5b, 0xb2, 0xf0, 0x3b, 0x31, 0x46, 0xbd, 0x14, + 0xf8, 0x53, 0xea, 0x97, 0x64, 0x5a, 0xcc, 0x4b, 0xf9, 0x40, 0x69, 0x0a, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x71, 0x78, 0x9d, 0x98, + 0xb2, 0x8c, 0x97, 0x5e, 0xd0, 0x38, 0x07, 0x76, 0x05, 0x62, 0x61, 0x0e, + 0x54, 0x2d, 0x91, 0x1e, 0xda, 0xfb, 0x76, 0xa5, 0x98, 0x34, 0x3b, 0x41, + 0x01, 0xab, 0x11, 0x1d, 0x52, 0xd9, 0xd0, 0x4b, 0x0e, 0xf4, 0x6e, 0x05, + 0x9d, 0x6b, 0xfd, 0x96, 0xf7, 0xda, 0xbe, 0xfd, 0x8b, 0xd4, 0xa2, 0xbf, + 0x80, 0x83, 0xa6, 0xae, 0x7f, 0x25, 0xd8, 0xbb, 0x8f, 0xf4, 0xe0, 0x1e, + 0x40, 0x4b, 0x32, 0x7a, 0x68, 0xe9, 0x6f, 0x46, 0x10, 0x4b, 0x7b, 0xc4, + 0xcf, 0x2a, 0x37, 0xeb, 0xa4, 0x8a, 0x03, 0x28, 0x11, 0x41, 0x7e, 0x33, + 0x1e, 0x63, 0x79, 0x19, 0x9e, 0x52, 0xfc, 0x16, 0x81, 0xd5, 0x8d, 0x75, + 0x52, 0xf0, 0x09, 0xc8, 0x55, 0x25, 0xc6, 0x3e, 0x8d, 0x30, 0xea, 0x57, + 0x76, 0xfb, 0xf2, 0x70, 0x6a, 0xc1, 0x2f, 0xee, 0x73, 0x2c, 0x3b, 0xbf, + 0xd8, 0x3b, 0xb3, 0x0b, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xed, 0x88, 0x9f, 0x0c, 0xab, 0xb1, 0xfd, 0x4e, 0xa2, 0x43, 0x7b, 0xcd, + 0x85, 0x23, 0x2b, 0xdd, 0xc9, 0x72, 0x80, 0x80, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x04, 0xa0, 0x92, 0xa0, + 0x22, 0xb9, 0xd9, 0x44, 0xd2, 0x97, 0x65, 0xa9, 0x77, 0x61, 0x25, 0x7b, + 0x35, 0xa0, 0xb7, 0xb7, 0x43, 0x03, 0x77, 0xb2, 0xce, 0xed, 0x40, 0xa5, + 0x41, 0x08, 0xa7, 0x1b, 0xe1, 0x46, 0x69, 0x8d, 0xe3, 0xfc, 0x2a, 0x26, + 0xc0, 0x66, 0x59, 0xea, 0x5d, 0x58, 0xc9, 0x5e, 0x0d, 0xe8, 0xed, 0xed, + 0xd0, 0xc0, 0x9d, 0xac, 0x73, 0x3b, 0x50, 0x69, 0x10, 0xc2, 0xe9, 0x06, + 0x78, 0xe7, 0x08, 0x5c, 0xdc, 0x28, 0xae, 0xaf, 0x6a, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xce, 0x5e, 0xca, 0x19, + 0x69, 0x37, 0x5d, 0xcf, 0x56, 0x8e, 0x71, 0xf0, 0x7b, 0x73, 0x3b, 0x29, + 0x71, 0x38, 0x0c, 0x5a, 0x96, 0x2f, 0xf1, 0xd0, 0xa2, 0xad, 0xaa, 0x14, + 0x3d, 0xb9, 0x89, 0x2d, 0x4f, 0x3b, 0x93, 0x09, 0xd0, 0x2f, 0x69, 0xae, + 0x70, 0xe3, 0xb2, 0x10, 0x3f, 0x1b, 0x44, 0x75, 0xc2, 0x4a, 0x8b, 0x91, + 0xe9, 0xd6, 0x4d, 0xab, 0xee, 0x39, 0x14, 0xce, 0x19, 0x8f, 0x26, 0x28, + 0x5c, 0x9a, 0x4c, 0xb2, 0x34, 0x43, 0x56, 0x8e, 0x6d, 0x90, 0xd5, 0xbb, + 0x88, 0xef, 0xa6, 0xdf, 0x4f, 0xe2, 0x1d, 0x9d, 0xf9, 0x7c, 0xf5, 0x5d, + 0xf6, 0xc7, 0x1b, 0x8b, 0x0a, 0x6b, 0xb8, 0x07, 0xdd, 0x4d, 0x8c, 0x27, + 0x89, 0x27, 0x3e, 0xe7, 0x64, 0xa4, 0x30, 0xcd, 0x51, 0xdd, 0x7f, 0xfc, + 0xdd, 0xff, 0xad, 0x97, 0xe3, 0x4b, 0xa8, 0x39, 0x02, 0x63, 0x3c, 0x57, + 0x50, 0x92, 0x32, 0x13, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0x2d, 0x3f, 0xe0, 0x84, 0x5d, 0x87, 0x60, 0x69, 0x84, 0x43, 0x7b, 0xcd, + 0x85, 0x23, 0x2b, 0xdd, 0xc9, 0x72, 0x80, 0x80, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0xa7, 0xeb, 0x44, 0x7d, + 0x1a, 0x15, 0x1f, 0x3c, 0x8d, 0xca, 0x71, 0x68, 0x91, 0x6a, 0x81, 0x97, + 0x5d, 0x58, 0x81, 0x81, 0xb6, 0x45, 0x50, 0xb8, 0x29, 0xa0, 0x31, 0xe1, + 0x72, 0x4e, 0x64, 0x30, 0xe1, 0x42, 0xc7, 0x20, 0x9e, 0x36, 0x2b, 0x2d, + 0x14, 0x66, 0x59, 0xea, 0x5d, 0x58, 0xc9, 0x5e, 0x0d, 0xe8, 0xed, 0xed, + 0xd0, 0xc0, 0x9d, 0xac, 0x73, 0x3b, 0x50, 0x69, 0x10, 0xc2, 0xe9, 0x06, + 0x4d, 0xad, 0x60, 0x93, 0x76, 0x47, 0xd9, 0xe6, 0x79, 0x2c, 0xe7, 0x64, + 0xa0, 0x55, 0x6c, 0x31, 0xf2, 0x79, 0x37, 0xe2, 0x4b, 0x6d, 0xc3, 0x0f, + 0xca, 0x4d, 0x74, 0x1a, 0xc3, 0x8d, 0x46, 0x16, 0xe1, 0xb7, 0xb3, 0x16, + 0x2b, 0x11, 0x18, 0xab, 0xc4, 0x63, 0xb7, 0x82, 0x94, 0xe6, 0x9b, 0x1a, + 0xe8, 0x64, 0xf0, 0x6d, 0x67, 0x8e, 0x47, 0xb5, 0xc9, 0x75, 0xa2, 0x2f, + 0x33, 0xce, 0x73, 0x19, 0x2e, 0x27, 0x31, 0x49, 0x87, 0x5c, 0x97, 0x4c, + 0xc2, 0xf1, 0x86, 0x83, 0x0e, 0xe2, 0x15, 0x33, 0xa8, 0x44, 0x88, 0x08, + 0x76, 0x33, 0xa0, 0x69, 0x3b, 0x9f, 0x9e, 0xca, 0x2f, 0x56, 0x80, 0x2e, + 0x0d, 0x3d, 0xc3, 0x9f, 0xed, 0xce, 0x89, 0xb3, 0x31, 0x4f, 0x39, 0x30, + 0xf8, 0x26, 0xa2, 0x3b, 0x8d, 0x14, 0x22, 0x82, 0x1c, 0x2c, 0xe3, 0xed, + 0x6b, 0xc8, 0x92, 0x8e, 0x48, 0x4b, 0x2a, 0x10, 0x00, 0x01, 0x5b, 0xdb, + 0xf9, 0x4a, 0x1c, 0x22, 0x28, 0x78, 0xec, 0xc0, 0x3e, 0x94, 0x59, 0x85, + 0x7e, 0xc9, 0x62, 0x22, 0xe7, 0x8d, 0xa3, 0xaf, 0xd9, 0x2f, 0x84, 0xc6, + 0x59, 0xfd, 0x40, 0x0c, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xb5, 0x5a, 0x31, 0x49, 0xb2, 0x2e, 0x60, 0x69, 0x84, 0x43, 0x7b, 0xcd, + 0x85, 0x23, 0x2b, 0xdd, 0xc9, 0x72, 0x80, 0x80, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x56, 0x95, 0x7f, 0x47, + 0x81, 0x53, 0xf7, 0x0e, 0x79, 0x64, 0x18, 0x7e, 0x33, 0x12, 0xb8, 0x38, + 0x50, 0x70, 0x93, 0x93, 0xe5, 0x84, 0xb2, 0x0b, 0xb6, 0x64, 0xe1, 0x77, + 0x62, 0x8c, 0x7a, 0x29, 0x52, 0x1f, 0xe8, 0x05, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x5f, 0xdc, 0xdb, 0x45, 0x99, 0x2c, 0x41, 0xa2, 0xf8, 0x99, 0x39, + 0x5c, 0x06, 0xff, 0xee, 0x0c, 0x4a, 0x13, 0xbe, 0xed, 0xee, 0xfe, 0x68, + 0xb1, 0xc4, 0x14, 0xed, 0xe3, 0x11, 0x1a, 0x24, 0x37, 0xa9, 0x42, 0x40, + 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, 0xa2, 0x05, 0x45, 0xc8, + 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, 0xe3, 0xcc, 0x6f, 0xcd, + 0xc5, 0x18, 0xcf, 0x19, 0x8d, 0xee, 0x63, 0xf5, 0xcf, 0x94, 0x1b, 0xd8, + 0x12, 0x4f, 0xf4, 0x06, 0xfb, 0xc5, 0x00, 0xd5, 0xef, 0x20, 0x15, 0x46, + 0x0f, 0x64, 0x9c, 0x6e, 0x28, 0x33, 0x33, 0x0c, 0xad, 0xf5, 0x87, 0x18, + 0x30, 0x78, 0x36, 0xf9, 0xeb, 0xaa, 0xab, 0x46, 0x5b, 0x96, 0x09, 0xfe, + 0x4a, 0x44, 0x29, 0x58, 0x7a, 0xf4, 0x3d, 0xa9, 0x26, 0xca, 0xb5, 0x90, + 0xc1, 0xc0, 0x59, 0xf9, 0x99, 0x38, 0xa6, 0x0b, 0xb6, 0x9a, 0x08, 0x90, + 0xa2, 0x00, 0x7b, 0x51, 0xdb, 0x4f, 0x07, 0x88, 0xb1, 0x19, 0x38, 0x0b, + 0xb9, 0x60, 0x33, 0x02, 0xc5, 0x5f, 0x04, 0x20, 0x7d, 0xf5, 0x1a, 0xbf, + 0x69, 0xc8, 0x52, 0x08, 0x5e, 0xfe, 0x4a, 0xe8, 0x40, 0x87, 0x13, 0x24, + 0xbb, 0xac, 0xaa, 0x3e, 0x57, 0xa6, 0x4d, 0xc1, 0xd1, 0x01, 0xb4, 0x4d, + 0x3a, 0x90, 0x96, 0x6e, 0x7f, 0xc6, 0x1d, 0x87, 0xde, 0xfb, 0x08, 0x1d, + 0xc9, 0xa9, 0x29, 0x48, 0xb2, 0x2e, 0x60, 0x69, 0x84, 0x43, 0x7b, 0xcd, + 0x85, 0x23, 0x2b, 0xdd, 0xc9, 0x72, 0x80, 0x80, 0xe7, 0xc1, 0x1a, 0xe8, + 0x0d, 0xe0, 0x65, 0xa0, 0x7b, 0x6f, 0x21, 0x10, 0x1f, 0x24, 0xa4, 0x8c, + 0x95, 0x38, 0x29, 0x2d, 0x14, 0x66, 0x59, 0xea, 0x5d, 0x58, 0xc9, 0x5e, + 0x0d, 0xe8, 0xed, 0xed, 0xd0, 0xc0, 0x9d, 0xac, 0x73, 0x3b, 0x50, 0x69, + 0x10, 0xc2, 0xe9, 0x06, 0x28, 0xd9, 0xd8, 0x4b, 0x81, 0x53, 0xf7, 0x0e, + 0x79, 0x64, 0x18, 0x7e, 0x33, 0x12, 0xb8, 0x38, 0x50, 0x70, 0x93, 0x93, + 0xe5, 0x84, 0xb2, 0x0b, 0xb6, 0x64, 0xe1, 0x77, 0x62, 0x8c, 0x7a, 0x29, + 0xd9, 0x21, 0x37, 0x72, 0x3a, 0x53, 0x1c, 0xa3, 0x5b, 0x13, 0x61, 0x85, + 0x13, 0x51, 0x3e, 0x23, 0xde, 0x9d, 0x52, 0x7d, 0x12, 0xcc, 0xd6, 0x8c, + 0x9c, 0xf4, 0x7b, 0x7c, 0xaa, 0xea, 0xe7, 0x0b, 0x66, 0x28, 0x68, 0xb4, + 0xbd, 0x74, 0x70, 0x07, 0xcb, 0x28, 0xb4, 0x81, 0xce, 0xd8, 0xeb, 0xa8, + 0xf8, 0x1e, 0x41, 0xc1, 0xc2, 0xe4, 0x42, 0xc4, 0x22, 0xb0, 0xfe, 0x10, + 0xb5, 0x96, 0x53, 0x28, 0xbb, 0x90, 0x90, 0x32, 0x56, 0xe2, 0xa4, 0xb4, + 0x50, 0x98, 0x65, 0xa9, 0x77, 0x61, 0x25, 0x7b, 0x35, 0xa0, 0xb7, 0xb7, + 0x43, 0x03, 0x77, 0xb2, 0xce, 0xed, 0x40, 0xa5, 0x41, 0x08, 0xa7, 0x1b, + 0xa9, 0x9f, 0x0f, 0xdb, 0x82, 0x11, 0x84, 0xa7, 0x51, 0x39, 0x0e, 0x2d, + 0x52, 0x2d, 0xf0, 0xb2, 0x0b, 0x2b, 0x30, 0xd0, 0xb6, 0x08, 0x0a, 0x37, + 0x05, 0x34, 0x26, 0x5c, 0xce, 0x89, 0x0c, 0x06, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b + }; + unsigned char poseidon_constants_8[] = { + 0x39, 0xec, 0xbc, 0x40, 0x49, 0x50, 0x75, 0xa1, 0xf3, 0x58, 0x2e, 0xd3, + 0x78, 0x63, 0xfa, 0xb4, 0x80, 0x9d, 0xe8, 0xc8, 0x52, 0x5b, 0xa7, 0x25, + 0x2b, 0x02, 0x84, 0x0c, 0x48, 0x9b, 0xcd, 0x0c, 0x0a, 0x20, 0x79, 0x37, + 0x8b, 0x6b, 0x82, 0x99, 0x3b, 0x75, 0xba, 0xac, 0x8e, 0xd0, 0x73, 0x11, + 0x15, 0xe7, 0x5d, 0x3a, 0x17, 0x14, 0x3d, 0xa2, 0x09, 0x75, 0x0e, 0x9a, + 0x64, 0xcb, 0xf7, 0x11, 0x29, 0x32, 0x0c, 0x75, 0x43, 0x8a, 0xe0, 0xfa, + 0x32, 0xd3, 0x48, 0x26, 0xb7, 0xbe, 0x86, 0xf1, 0x9c, 0x7f, 0x24, 0x22, + 0x06, 0x97, 0x2a, 0xa2, 0x89, 0xb0, 0x9a, 0xba, 0x43, 0xf6, 0xcf, 0x0e, + 0x49, 0x31, 0x20, 0xb9, 0x9e, 0x27, 0x86, 0x43, 0x32, 0x31, 0x5b, 0x05, + 0x26, 0x97, 0x2f, 0x49, 0xc1, 0x65, 0x66, 0x96, 0x73, 0x73, 0x92, 0xa2, + 0x23, 0xb9, 0x43, 0x5e, 0x68, 0x90, 0x00, 0x0a, 0x24, 0xdb, 0xc8, 0x59, + 0xdf, 0xac, 0x3a, 0x82, 0x71, 0x45, 0xfa, 0x97, 0x11, 0x78, 0xcd, 0x4f, + 0x84, 0xa5, 0x3f, 0x05, 0x7e, 0x50, 0x0c, 0xf1, 0x22, 0x8f, 0x2b, 0x91, + 0xe3, 0xe1, 0x5f, 0x01, 0x84, 0x60, 0xdb, 0x7c, 0xf5, 0x7a, 0x7b, 0xab, + 0xb9, 0xf4, 0xa2, 0x05, 0xae, 0x60, 0x67, 0x33, 0xa5, 0x31, 0x39, 0xb5, + 0xb7, 0xe1, 0xe2, 0x12, 0x1e, 0xd5, 0x51, 0x68, 0xaf, 0x65, 0xb5, 0x26, + 0xa1, 0x2a, 0x43, 0xdf, 0x11, 0xc1, 0x67, 0xda, 0xd3, 0xd4, 0xb0, 0xd7, + 0xa9, 0x20, 0x17, 0x1b, 0xb2, 0xd4, 0xbb, 0xb8, 0x8e, 0xc4, 0x6b, 0x05, + 0xaa, 0x9e, 0x61, 0xdf, 0x40, 0x72, 0x99, 0x28, 0x64, 0xe9, 0x8d, 0xf6, + 0x59, 0xa3, 0x4e, 0xdd, 0xb6, 0xc4, 0x8e, 0x1d, 0x5f, 0xad, 0x30, 0x35, + 0x55, 0x6e, 0x66, 0xd6, 0x29, 0xc6, 0x55, 0x29, 0x4b, 0xfc, 0xac, 0x39, + 0x4f, 0x33, 0xe9, 0x21, 0xca, 0x73, 0x65, 0xfb, 0x3b, 0xa8, 0x1e, 0x55, + 0x48, 0x2c, 0xc0, 0xf3, 0x36, 0x69, 0x0f, 0x66, 0x49, 0x08, 0x91, 0xee, + 0x05, 0x9a, 0x67, 0xb4, 0x16, 0xa4, 0xaf, 0xab, 0xd6, 0x67, 0x92, 0x24, + 0x55, 0xcb, 0x10, 0xff, 0x07, 0x14, 0x2c, 0x4f, 0x59, 0xc3, 0x96, 0x5d, + 0xe3, 0x58, 0x89, 0x0c, 0x2b, 0x6e, 0x8b, 0x41, 0xfd, 0x07, 0x3c, 0x6d, + 0xaf, 0xea, 0xd9, 0x2f, 0x5a, 0x3d, 0x30, 0x21, 0x5c, 0x14, 0xb8, 0xa1, + 0x87, 0x5a, 0xfd, 0x40, 0xa9, 0x29, 0x59, 0xf3, 0x45, 0x62, 0x42, 0x4a, + 0x68, 0x0b, 0x90, 0x91, 0xc2, 0x41, 0x8c, 0xb9, 0x8a, 0x7a, 0x0c, 0x58, + 0xdf, 0x36, 0x42, 0x1f, 0x52, 0xf2, 0x5f, 0x91, 0x42, 0x89, 0xee, 0x47, + 0xc9, 0x3d, 0xbb, 0x48, 0x98, 0x84, 0x75, 0x6a, 0x87, 0x9c, 0x45, 0x7c, + 0xdc, 0x09, 0x6b, 0x9b, 0xbb, 0x51, 0x1c, 0x30, 0xcd, 0xc7, 0xaa, 0x01, + 0x38, 0xcc, 0x0d, 0x0f, 0xec, 0x4c, 0x35, 0xe6, 0x2c, 0xf0, 0xea, 0x74, + 0x6c, 0x96, 0x2d, 0xcd, 0x37, 0x40, 0x4d, 0xe0, 0x51, 0xba, 0xa4, 0x19, + 0xeb, 0xeb, 0x3f, 0xbd, 0x47, 0x17, 0x52, 0x1f, 0x6d, 0x98, 0x9e, 0x45, + 0xec, 0x93, 0x8f, 0xc5, 0x40, 0xb6, 0x86, 0xda, 0xac, 0x3a, 0xa8, 0x21, + 0xae, 0xb4, 0xc8, 0x88, 0xd9, 0xd8, 0x1f, 0xc8, 0xe3, 0xd3, 0x9d, 0xa9, + 0x23, 0x56, 0x24, 0x29, 0x50, 0xfd, 0x63, 0x9c, 0x44, 0x75, 0x03, 0x27, + 0x8a, 0x5a, 0xd8, 0xaa, 0x5c, 0xfa, 0x18, 0x73, 0x81, 0x49, 0x29, 0x08, + 0xf8, 0x38, 0x05, 0x6c, 0xcc, 0xf1, 0xdc, 0x3b, 0xad, 0x67, 0x7d, 0x2b, + 0x9e, 0xf4, 0xcc, 0x16, 0xec, 0x63, 0x67, 0x9c, 0x0c, 0x44, 0xfb, 0x40, + 0x84, 0xe7, 0x45, 0xeb, 0x4f, 0xd5, 0xfc, 0xb2, 0xeb, 0x23, 0x46, 0x00, + 0xc7, 0x54, 0xb6, 0xfb, 0x61, 0x00, 0xae, 0x03, 0xd6, 0x4e, 0x16, 0x8d, + 0x99, 0x79, 0x55, 0x01, 0xdc, 0x96, 0x63, 0x37, 0xee, 0x11, 0x57, 0xb7, + 0x4a, 0xd1, 0x75, 0x65, 0xaa, 0xfb, 0x01, 0x4c, 0x42, 0x03, 0x0b, 0xa3, + 0x50, 0x8a, 0x85, 0x11, 0x3e, 0xae, 0xbc, 0xb7, 0x9f, 0x85, 0x2b, 0xe7, + 0x27, 0xdf, 0x01, 0x02, 0x6d, 0x42, 0x0f, 0x33, 0x2f, 0xb8, 0x5e, 0x0b, + 0x34, 0x83, 0x85, 0xe9, 0x42, 0x92, 0x1a, 0x6c, 0xc4, 0xa2, 0xf5, 0x1e, + 0x2b, 0xbb, 0x37, 0x7e, 0xa3, 0x51, 0xd0, 0xdd, 0x1a, 0x90, 0x0a, 0x90, + 0xec, 0xb2, 0x13, 0xb8, 0xdb, 0x41, 0x66, 0xfd, 0x65, 0x97, 0xe6, 0x95, + 0x22, 0x5e, 0x26, 0x45, 0x60, 0x12, 0x9f, 0x1f, 0xd3, 0x3a, 0x25, 0x07, + 0xcc, 0xef, 0x39, 0x65, 0xef, 0xf4, 0xd9, 0x97, 0x0d, 0xf8, 0x13, 0x2d, + 0x4b, 0x96, 0x9b, 0xe7, 0x09, 0x21, 0x07, 0x6f, 0x7b, 0x8b, 0xfd, 0xbd, + 0x28, 0xcc, 0x16, 0x08, 0xf2, 0x8d, 0x32, 0xc1, 0x18, 0xa1, 0x12, 0x11, + 0x28, 0x9b, 0xca, 0x8b, 0xdc, 0x88, 0xb0, 0xf8, 0x36, 0x58, 0xd5, 0xc4, + 0x92, 0xd1, 0x50, 0x60, 0x83, 0x37, 0x8d, 0x9c, 0x26, 0x83, 0x60, 0x1c, + 0x73, 0xf7, 0x33, 0x54, 0xc1, 0x04, 0x2e, 0x44, 0x0f, 0x94, 0xdf, 0xe2, + 0xeb, 0x77, 0xc8, 0x86, 0x54, 0x1c, 0xe5, 0x46, 0xf2, 0xb8, 0xb0, 0x05, + 0x79, 0x32, 0x12, 0xab, 0x96, 0x2b, 0xf9, 0x2d, 0x99, 0xb1, 0x39, 0x26, + 0xa0, 0x7f, 0x2e, 0x79, 0xad, 0x45, 0xf2, 0x89, 0x14, 0x6c, 0x36, 0xb7, + 0x39, 0xe4, 0xfc, 0x0c, 0x1b, 0x4a, 0x2e, 0xa5, 0xe8, 0xb6, 0x76, 0x26, + 0x13, 0xd5, 0xd4, 0x08, 0x85, 0x9a, 0xd2, 0xfe, 0xca, 0x6c, 0xd0, 0xbf, + 0x19, 0x44, 0x41, 0x2e, 0x3f, 0xec, 0x40, 0xe1, 0x25, 0xcd, 0x98, 0xeb, + 0x8c, 0x9e, 0x0f, 0x44, 0xa0, 0xa7, 0x56, 0x40, 0x28, 0x50, 0x4d, 0x02, + 0x2c, 0xe2, 0xb3, 0x24, 0x81, 0x8d, 0xbe, 0xd1, 0x8a, 0xba, 0x73, 0x2e, + 0x21, 0xb7, 0x68, 0xe2, 0xbe, 0xfe, 0x7d, 0x08, 0xe4, 0x61, 0x2d, 0xca, + 0x03, 0x6b, 0x5c, 0x21, 0x4b, 0x97, 0x40, 0x2f, 0x5f, 0x14, 0xb0, 0xb9, + 0x8f, 0xe8, 0x43, 0x0d, 0x26, 0x5a, 0x15, 0x04, 0x74, 0x17, 0xa1, 0x47, + 0x90, 0xec, 0x69, 0xa1, 0x6d, 0x49, 0x45, 0x86, 0x98, 0x57, 0x61, 0xbb, + 0x3a, 0x67, 0x54, 0x29, 0x3b, 0xb2, 0xc7, 0xe0, 0x53, 0x4b, 0x8c, 0x24, + 0xa6, 0xf4, 0x5c, 0x2d, 0xcf, 0x5e, 0x8f, 0xd6, 0x3c, 0x21, 0x3a, 0x9c, + 0x1d, 0xb0, 0x81, 0x7d, 0x61, 0xe3, 0xb0, 0xf8, 0x1f, 0xe7, 0xbb, 0x00, + 0x26, 0x5d, 0x12, 0xc0, 0x68, 0x1e, 0x87, 0x71, 0x4a, 0x2b, 0x99, 0x76, + 0xb8, 0x7d, 0xdb, 0xd7, 0x48, 0x8a, 0x28, 0x72, 0x61, 0xd9, 0xcd, 0x8c, + 0x1b, 0x61, 0x11, 0x96, 0xa9, 0xd7, 0x00, 0x13, 0x47, 0x66, 0x74, 0x35, + 0x0f, 0xdd, 0x2d, 0x28, 0xf6, 0xe9, 0x8e, 0xdc, 0xdb, 0xb4, 0x7f, 0x16, + 0x27, 0x50, 0x30, 0x67, 0x2e, 0xba, 0xbd, 0x9e, 0x11, 0x96, 0x8a, 0x8b, + 0x2f, 0x0b, 0x0c, 0x09, 0x5f, 0x52, 0xf2, 0x4f, 0xda, 0x2f, 0xa4, 0xe2, + 0x96, 0x3d, 0x30, 0xce, 0xa7, 0xb6, 0x23, 0xd6, 0xcf, 0xcc, 0xe9, 0x7b, + 0x83, 0x68, 0x51, 0x60, 0xad, 0x0d, 0x89, 0x60, 0xdb, 0x17, 0x5a, 0x02, + 0xf2, 0x4d, 0xdb, 0x0c, 0xa8, 0x5a, 0x44, 0x4b, 0x7b, 0x09, 0xad, 0xde, + 0xc4, 0x70, 0x3a, 0x31, 0xcb, 0x5c, 0xed, 0x20, 0x6d, 0x0e, 0x26, 0x19, + 0x9c, 0xe1, 0xbb, 0xbf, 0xb7, 0x70, 0x4f, 0x10, 0x45, 0x03, 0x83, 0xaa, + 0xb3, 0x96, 0x59, 0x36, 0x68, 0xb6, 0xe0, 0xf7, 0xca, 0x50, 0x53, 0x9c, + 0x0c, 0x8b, 0x0e, 0x9b, 0x8a, 0x9e, 0x5a, 0x22, 0xa4, 0x7a, 0x64, 0x67, + 0xa2, 0x3d, 0x71, 0x16, 0x32, 0xca, 0xf3, 0x96, 0xe8, 0x46, 0xd2, 0x83, + 0x1a, 0x5b, 0x74, 0x20, 0x82, 0x4c, 0x30, 0x5b, 0x1c, 0x33, 0xd5, 0x48, + 0xf3, 0xde, 0x2d, 0x85, 0x5e, 0x53, 0x8c, 0x4d, 0xe0, 0x5c, 0xfe, 0x16, + 0xbd, 0xbc, 0xe3, 0xe8, 0x64, 0x91, 0x2b, 0xf7, 0x7d, 0x4c, 0x16, 0x56, + 0x21, 0x42, 0xf3, 0x65, 0x02, 0x19, 0x42, 0x5e, 0x54, 0x77, 0x30, 0x66, + 0xaa, 0x3c, 0xa4, 0x2b, 0x70, 0x37, 0x8e, 0x04, 0x2a, 0x7b, 0xc6, 0x75, + 0xdb, 0x57, 0xb9, 0xdd, 0xef, 0x5e, 0x80, 0xe2, 0xf6, 0xf5, 0x8f, 0xcf, + 0x76, 0x28, 0xd7, 0xaf, 0xfa, 0x34, 0x53, 0x3a, 0x04, 0x53, 0x71, 0xb7, + 0x0e, 0xfd, 0x94, 0x0f, 0x11, 0x58, 0x37, 0xee, 0x09, 0x17, 0xd2, 0x5f, + 0x59, 0x2b, 0xb4, 0x0c, 0x70, 0x8d, 0x7c, 0x62, 0xa3, 0x33, 0x92, 0xd7, + 0x85, 0x92, 0xb5, 0xe9, 0xcf, 0x99, 0x69, 0x71, 0x37, 0x14, 0xa3, 0x0b, + 0xd3, 0xdc, 0x71, 0xfe, 0xb8, 0xe6, 0x33, 0xee, 0xab, 0xdb, 0xbd, 0x79, + 0x4a, 0x08, 0x3c, 0x0f, 0xb8, 0xfa, 0x78, 0xe4, 0xe0, 0x74, 0x8f, 0xb6, + 0xe0, 0x70, 0x02, 0xe4, 0xeb, 0xa2, 0xea, 0x2d, 0x56, 0x15, 0x23, 0x29, + 0x56, 0x22, 0x44, 0x2e, 0x84, 0xbe, 0xbb, 0xcd, 0x24, 0x0b, 0x00, 0x0c, + 0xdb, 0xd7, 0x40, 0x25, 0x7d, 0x33, 0xb7, 0x9c, 0x98, 0x67, 0x5e, 0xdf, + 0xfa, 0x6e, 0x15, 0x1a, 0x6d, 0xf0, 0x01, 0xe4, 0xe2, 0xdf, 0x92, 0x77, + 0xd3, 0xd0, 0x44, 0xcc, 0x1e, 0x01, 0x5b, 0x82, 0x0e, 0x58, 0x3e, 0x01, + 0x7e, 0x49, 0x19, 0x5d, 0x19, 0xc5, 0x27, 0x4f, 0x08, 0xf1, 0x8b, 0x2e, + 0x4a, 0x59, 0xeb, 0x2c, 0x7f, 0x2b, 0x5c, 0x96, 0x38, 0x6a, 0xc2, 0x47, + 0x40, 0xe3, 0x03, 0x01, 0xd0, 0xa1, 0x51, 0x81, 0x60, 0x9c, 0x65, 0x99, + 0xd7, 0x9a, 0x8f, 0x9a, 0xe7, 0x0c, 0x94, 0x0e, 0x5b, 0x51, 0x41, 0x62, + 0x77, 0x10, 0x4c, 0x42, 0x6e, 0x75, 0x31, 0x61, 0x34, 0x32, 0x64, 0x3f, + 0x32, 0x3b, 0xf7, 0x15, 0x01, 0xfa, 0xd3, 0x23, 0x90, 0x24, 0xbe, 0x9b, + 0xc3, 0x37, 0x88, 0x19, 0xcd, 0x6a, 0x09, 0xec, 0x2e, 0x5d, 0x27, 0xfb, + 0x4b, 0x80, 0x72, 0x73, 0x60, 0xdd, 0xdb, 0xed, 0x50, 0x8d, 0x4c, 0x11, + 0x52, 0x5d, 0xcb, 0x52, 0xdc, 0x5c, 0x5f, 0xc3, 0x8a, 0x0f, 0x3e, 0x26, + 0x8e, 0x4a, 0xf5, 0x2e, 0xca, 0xbc, 0x8f, 0x58, 0x2d, 0xc8, 0x51, 0xc2, + 0xf0, 0x4f, 0xbf, 0x59, 0xb3, 0x89, 0x26, 0x5b, 0xfa, 0x2c, 0x78, 0x86, + 0x8c, 0x58, 0xb9, 0xf4, 0xb9, 0x6f, 0xc0, 0x1f, 0x44, 0xc5, 0x1f, 0xf6, + 0xa8, 0x53, 0xb2, 0x38, 0x21, 0xca, 0x11, 0x7b, 0x23, 0x0c, 0xe8, 0x98, + 0x01, 0xbc, 0xdb, 0x3c, 0xb0, 0x0c, 0xb5, 0x04, 0x5e, 0x26, 0xfc, 0x2a, + 0xdb, 0xf3, 0x4e, 0x1d, 0x81, 0xf4, 0x8c, 0x2e, 0xb4, 0x7c, 0xb4, 0x7c, + 0x2d, 0xe9, 0x81, 0xbf, 0x1e, 0xa2, 0xff, 0x58, 0x92, 0xea, 0xc5, 0x0e, + 0x38, 0xeb, 0x97, 0x41, 0x8f, 0xf6, 0x47, 0x76, 0x0b, 0xae, 0x8c, 0x25, + 0x42, 0xc8, 0x5c, 0x72, 0xad, 0xa7, 0x1b, 0x1a, 0x32, 0xba, 0xcd, 0xeb, + 0x99, 0xea, 0xe6, 0x96, 0x69, 0xfe, 0x65, 0xb6, 0x23, 0xa1, 0xf0, 0x3b, + 0x67, 0x4f, 0x35, 0x16, 0x63, 0xae, 0x78, 0x0b, 0x19, 0x0d, 0x79, 0x83, + 0xdc, 0x29, 0xd5, 0x07, 0xb9, 0x66, 0x13, 0x02, 0x59, 0xb7, 0x17, 0x8c, + 0xdf, 0x59, 0x39, 0x6a, 0xeb, 0x01, 0x38, 0x24, 0x43, 0xfd, 0x94, 0x0c, + 0x4c, 0x87, 0xa0, 0x19, 0x6e, 0xcd, 0x55, 0xf9, 0x7c, 0x8b, 0x46, 0x17, + 0xc4, 0x8e, 0x50, 0xe3, 0xf8, 0x2e, 0x74, 0xf4, 0x8b, 0xf9, 0x3e, 0x88, + 0x5c, 0xfa, 0x9c, 0x21, 0x9c, 0x44, 0xb3, 0x07, 0xf7, 0x68, 0x07, 0x2a, + 0x88, 0xfb, 0x02, 0x1c, 0x8b, 0x33, 0x7a, 0x8a, 0x72, 0x68, 0x1e, 0x55, + 0x32, 0x8f, 0xc3, 0xec, 0xcc, 0xa4, 0xc6, 0xca, 0xe4, 0xe2, 0x57, 0x85, + 0x63, 0xc1, 0xec, 0xcb, 0xbc, 0x6f, 0x1d, 0x15, 0x94, 0xf1, 0xa1, 0xec, + 0x01, 0x72, 0xcc, 0xed, 0x99, 0xb1, 0xaa, 0x44, 0x72, 0xa7, 0xef, 0xed, + 0x0b, 0x40, 0x2f, 0x5f, 0xe5, 0x9a, 0x2d, 0x4d, 0x72, 0x85, 0xd2, 0xba, + 0x9c, 0x6a, 0x70, 0x1e, 0x0e, 0x2a, 0x06, 0x73, 0x55, 0xc9, 0x09, 0x54, + 0xee, 0xcb, 0x13, 0xe6, 0x1c, 0xb9, 0x2e, 0xb6, 0x6e, 0x7c, 0xa4, 0x31, + 0xa1, 0x30, 0x07, 0x17, 0xaa, 0x65, 0x91, 0x6a, 0xd7, 0x4b, 0xfe, 0x06, + 0x06, 0xb2, 0xac, 0xe8, 0xe6, 0x8b, 0x23, 0xc6, 0x02, 0x1b, 0xad, 0xb4, + 0x2e, 0xdb, 0x82, 0x5d, 0x94, 0xb9, 0x77, 0x19, 0x79, 0xd2, 0x7b, 0x8c, + 0x2c, 0x8c, 0xe8, 0x9c, 0xe0, 0x95, 0x64, 0x2f, 0x7e, 0x08, 0x20, 0x19, + 0xba, 0x3b, 0x31, 0x16, 0x10, 0xfb, 0x1c, 0x60, 0xf5, 0xb7, 0x78, 0xc2, + 0xc3, 0x12, 0x28, 0xb9, 0xb6, 0x16, 0xf8, 0xd9, 0x91, 0xa0, 0xb8, 0xfc, + 0x19, 0x6d, 0x6f, 0x16, 0x8c, 0x98, 0x6b, 0x8b, 0xd5, 0xb1, 0xaa, 0x7e, + 0xe0, 0x47, 0x53, 0x8c, 0x69, 0x66, 0x51, 0x7f, 0x65, 0xde, 0x8b, 0x3e, + 0x43, 0xff, 0xe8, 0x34, 0x89, 0xf7, 0x0f, 0xaf, 0x1e, 0x11, 0x59, 0x00, + 0x8e, 0x31, 0x59, 0x56, 0x32, 0xd1, 0x40, 0xb4, 0x65, 0xb1, 0xe5, 0x5c, + 0x1f, 0x31, 0x25, 0xea, 0xe0, 0x3c, 0x36, 0x47, 0xbc, 0x48, 0x98, 0x63, + 0x18, 0x52, 0x0c, 0xaa, 0x76, 0x18, 0x36, 0x27, 0x53, 0x96, 0x3a, 0xe0, + 0x50, 0x21, 0x9f, 0x5d, 0x7d, 0x9b, 0x5e, 0xdd, 0xca, 0xed, 0xa0, 0x65, + 0xbb, 0xea, 0x20, 0xc1, 0xe3, 0xff, 0x0c, 0x29, 0xbb, 0x77, 0xf7, 0xbe, + 0x71, 0xbe, 0xd8, 0x29, 0xab, 0xfc, 0x7e, 0x79, 0x67, 0xc0, 0xc1, 0x72, + 0xa8, 0xc9, 0x9a, 0x9e, 0xe1, 0xb9, 0x29, 0x74, 0x67, 0xc0, 0xc1, 0xae, + 0xef, 0x69, 0x99, 0x30, 0xd7, 0xc6, 0xfd, 0xb5, 0x77, 0xc5, 0x83, 0x03, + 0x03, 0x7d, 0x2f, 0xf8, 0x06, 0x01, 0xbc, 0x14, 0xfa, 0x8d, 0x06, 0xaf, + 0x68, 0x8f, 0x0a, 0x28, 0xca, 0x62, 0x47, 0xdf, 0x34, 0xa0, 0xa7, 0xdb, + 0xe7, 0x83, 0x86, 0x28, 0x54, 0xed, 0xf4, 0x02, 0x79, 0xa9, 0x1e, 0x39, + 0x83, 0x4f, 0x53, 0x75, 0x38, 0x15, 0xb3, 0x2e, 0xcc, 0x8a, 0xff, 0x67, + 0x17, 0xe6, 0x14, 0x88, 0x87, 0xcf, 0x2f, 0xf7, 0xe3, 0x91, 0x21, 0xa4, + 0x0a, 0x73, 0x3c, 0x1b, 0xfb, 0xb4, 0x06, 0xfe, 0x8f, 0xf7, 0xec, 0x90, + 0x8a, 0x86, 0xe2, 0x70, 0xa3, 0xd8, 0xe7, 0x15, 0xf8, 0x8e, 0xc3, 0x2b, + 0xd6, 0xb7, 0xd6, 0x34, 0x71, 0x53, 0x6a, 0x40, 0x79, 0x14, 0x34, 0x23, + 0xc2, 0x95, 0xb0, 0x55, 0xb8, 0xc9, 0xf8, 0x14, 0xe5, 0x26, 0xe9, 0xa8, + 0xfe, 0x53, 0x87, 0x65, 0x92, 0x6c, 0x32, 0x4f, 0x4f, 0x81, 0x2d, 0xdc, + 0xcc, 0x65, 0x2f, 0xfa, 0x71, 0x0c, 0xe5, 0x17, 0x23, 0x5f, 0x87, 0x3c, + 0x46, 0x05, 0x11, 0x6f, 0xaf, 0x24, 0x70, 0xf0, 0x25, 0x83, 0x04, 0xc7, + 0xfe, 0x06, 0x48, 0xd9, 0xfc, 0xa2, 0x37, 0x8b, 0xc7, 0x86, 0x0a, 0x6b, + 0x6f, 0x8c, 0x93, 0x15, 0x67, 0xd0, 0x5c, 0xc3, 0x36, 0xb7, 0x7c, 0x57, + 0xa5, 0x8f, 0x73, 0xb4, 0xfa, 0x3d, 0xf6, 0x04, 0x5f, 0xde, 0x9f, 0xd2, + 0x9e, 0xe3, 0xfa, 0x41, 0x5d, 0xc2, 0x30, 0x6a, 0x30, 0x8a, 0x74, 0x26, + 0xcb, 0xa1, 0x86, 0xb9, 0x31, 0x35, 0x04, 0x8f, 0x63, 0x9b, 0xc0, 0x02, + 0x08, 0x50, 0xa3, 0xf2, 0x3b, 0xa3, 0x3e, 0x2f, 0x24, 0x38, 0x10, 0xbb, + 0xc2, 0x50, 0x00, 0xaf, 0x05, 0xe5, 0x4e, 0x0e, 0x33, 0x4b, 0xd7, 0xfa, + 0x45, 0x10, 0x00, 0xff, 0xe5, 0x64, 0xf9, 0xa7, 0x83, 0xbd, 0x87, 0x66, + 0xa5, 0x2d, 0xe1, 0x9d, 0x2d, 0x26, 0x92, 0xe6, 0xcc, 0xb1, 0x75, 0xdf, + 0x95, 0x7b, 0x49, 0x0a, 0xb4, 0x0a, 0x8d, 0x7b, 0x35, 0x6e, 0x10, 0xbf, + 0x9a, 0x4a, 0x61, 0x44, 0x54, 0xfc, 0x18, 0xf5, 0x87, 0x55, 0xf0, 0x8f, + 0xa8, 0x27, 0x18, 0xa4, 0xbf, 0x0a, 0x01, 0x65, 0x0c, 0xac, 0x4a, 0x20, + 0x14, 0x93, 0xd5, 0xf6, 0x12, 0x2c, 0x09, 0xa5, 0xe6, 0x6d, 0x47, 0x68, + 0x71, 0x65, 0x9e, 0x9a, 0xbd, 0xd9, 0xcf, 0xf3, 0xbf, 0xb9, 0x10, 0xa9, + 0xd2, 0x14, 0x22, 0x20, 0x56, 0x74, 0xce, 0x04, 0xa7, 0x35, 0xbb, 0xfe, + 0x3c, 0x8b, 0x0f, 0xbe, 0x4b, 0x87, 0x7a, 0xb3, 0xc9, 0x47, 0x67, 0x68, + 0xe2, 0x0a, 0x26, 0x59, 0x67, 0x56, 0x33, 0xcd, 0x0e, 0x5b, 0xa2, 0x56, + 0xb2, 0xe5, 0xa1, 0x03, 0x7e, 0xbe, 0xa3, 0xc3, 0x20, 0xc3, 0x13, 0xfd, + 0xf4, 0x4d, 0x6c, 0x3b, 0xa2, 0xeb, 0x1c, 0x4b, 0x24, 0x66, 0x44, 0x56, + 0xaf, 0x11, 0xcd, 0x0a, 0x02, 0xc6, 0x93, 0x70, 0x55, 0xae, 0x65, 0x02, + 0x37, 0xda, 0xf7, 0xef, 0xa6, 0x8a, 0xd4, 0x1f, 0x8f, 0xac, 0x64, 0x03, + 0x32, 0x63, 0x62, 0x54, 0x5c, 0x12, 0x5a, 0xc2, 0x99, 0x75, 0xa3, 0x03, + 0x35, 0xaa, 0xbc, 0xf3, 0xde, 0x33, 0x7b, 0x20, 0x6f, 0x6c, 0x45, 0x4e, + 0x80, 0x9e, 0x1c, 0x17, 0x9b, 0x95, 0x37, 0x4e, 0xc4, 0x56, 0x8b, 0xc2, + 0xf6, 0x5e, 0x4a, 0x65, 0x51, 0x3c, 0x61, 0x8a, 0xe8, 0xa9, 0x84, 0x4f, + 0x45, 0xbe, 0x8d, 0x26, 0x74, 0xaf, 0x20, 0xeb, 0xbf, 0xfb, 0x1d, 0x1e, + 0x42, 0x5d, 0x8a, 0x06, 0xc2, 0xe3, 0x19, 0xe8, 0x97, 0xd8, 0x80, 0x4a, + 0xc6, 0x34, 0x2f, 0xd8, 0x8e, 0x59, 0xc0, 0xac, 0x67, 0x74, 0xc4, 0x0c, + 0xb3, 0x05, 0xb7, 0xf1, 0xf7, 0x95, 0xa1, 0xd0, 0x4b, 0xeb, 0xde, 0x0d, + 0x65, 0x61, 0x2b, 0x1b, 0xd7, 0x39, 0xa3, 0x75, 0x13, 0xca, 0x05, 0x41, + 0x7a, 0xad, 0x52, 0xd1, 0x7c, 0x29, 0x3c, 0x27, 0x74, 0xe3, 0x84, 0xfc, + 0xee, 0x06, 0x35, 0xa8, 0xa4, 0x92, 0x42, 0x7f, 0x78, 0x2a, 0x67, 0x70, + 0x7d, 0x29, 0xff, 0x29, 0x17, 0x87, 0x42, 0x72, 0x4f, 0xcb, 0xc1, 0xfb, + 0x76, 0x2f, 0x6a, 0x26, 0xbb, 0x0f, 0x4e, 0x25, 0xd6, 0x23, 0x5a, 0xe8, + 0xa2, 0xee, 0x26, 0x5b, 0x40, 0xd1, 0xa4, 0xdc, 0x17, 0x31, 0x85, 0xe5, + 0xf0, 0x8c, 0x27, 0xf1, 0xcd, 0x5b, 0x14, 0x6e, 0x6a, 0x3c, 0xbe, 0x2a, + 0x41, 0xe9, 0x1f, 0x29, 0x34, 0xd8, 0x7f, 0xc5, 0xcd, 0xdf, 0x57, 0x3b, + 0xbd, 0xf9, 0xc5, 0x13, 0xbb, 0xdd, 0xfb, 0x04, 0x4b, 0xb4, 0xfd, 0xe5, + 0xe3, 0x54, 0xd8, 0x9f, 0xe8, 0x4b, 0xed, 0x1a, 0xc2, 0x69, 0x33, 0xab, + 0x60, 0x48, 0x60, 0x32, 0xf9, 0x6b, 0x25, 0x29, 0x78, 0x32, 0x3e, 0x11, + 0xf9, 0xfe, 0xcd, 0x92, 0xf0, 0x3e, 0x57, 0xdc, 0xf2, 0x42, 0x76, 0xd2, + 0xf7, 0xb4, 0x31, 0x0a, 0xe2, 0xde, 0x96, 0xff, 0xeb, 0xa2, 0x09, 0xa3, + 0x6f, 0x70, 0x9a, 0x1f, 0x43, 0x69, 0x23, 0xb1, 0x72, 0x5f, 0xd6, 0x65, + 0xc5, 0x45, 0xc4, 0xed, 0xa6, 0xcc, 0x4b, 0x83, 0x09, 0x65, 0xa4, 0x0b, + 0xab, 0xdf, 0x88, 0x46, 0xa3, 0x1c, 0x3f, 0x5a, 0x0e, 0x36, 0xf7, 0x90, + 0x77, 0xaa, 0x2b, 0x12, 0xf8, 0x59, 0x4f, 0x48, 0x37, 0x34, 0x9d, 0x08, + 0x68, 0x80, 0x0d, 0xd3, 0x01, 0x85, 0x7f, 0x2a, 0xfa, 0xfa, 0xe3, 0x58, + 0x9b, 0x66, 0x79, 0xbc, 0xea, 0xd6, 0xc5, 0x85, 0x48, 0xd3, 0xa8, 0x80, + 0x8a, 0xf7, 0xf4, 0x6b, 0xc1, 0x93, 0x68, 0xba, 0xf5, 0x73, 0x90, 0xc2, + 0x91, 0xd0, 0x63, 0x0b, 0xf6, 0x5c, 0x22, 0xc9, 0x6f, 0xe5, 0xab, 0x42, + 0x0e, 0x71, 0xa5, 0x2e, 0xbc, 0xa5, 0x1e, 0x66, 0xaf, 0xf6, 0xd4, 0xc0, + 0x31, 0xcb, 0x40, 0xd7, 0x40, 0xf4, 0x2e, 0xec, 0x5f, 0xa1, 0x70, 0x05, + 0x8e, 0x90, 0xaa, 0x40, 0x1e, 0x9c, 0x16, 0xc0, 0xf4, 0x15, 0x58, 0x69, + 0xbf, 0x6f, 0x55, 0x86, 0xbc, 0x2b, 0x32, 0xb4, 0xd4, 0xb3, 0x43, 0x1e, + 0x8b, 0x17, 0x5f, 0xc7, 0x4c, 0x49, 0x7f, 0x10, 0xdc, 0xb1, 0x17, 0xda, + 0xea, 0x56, 0x6e, 0x1d, 0xa7, 0x63, 0x46, 0xdc, 0xc4, 0x8b, 0x1d, 0x3b, + 0xe3, 0x50, 0xfc, 0x0c, 0xc9, 0x5b, 0xbf, 0x8b, 0x7c, 0x47, 0xd2, 0x32, + 0xe9, 0x6d, 0xb9, 0x03, 0xc2, 0x81, 0xd6, 0xd7, 0x86, 0x13, 0xbd, 0xbf, + 0xb8, 0x7e, 0x9b, 0x84, 0x5e, 0x6b, 0x34, 0x64, 0x51, 0xdf, 0x39, 0x39, + 0x18, 0x95, 0xd0, 0xf0, 0x1c, 0x8a, 0x04, 0xcf, 0xb9, 0xfd, 0xbc, 0x28, + 0xd4, 0xb4, 0x99, 0x14, 0x6b, 0xb1, 0xe8, 0xef, 0xb1, 0x74, 0xc6, 0xef, + 0x99, 0xd5, 0xbb, 0xd4, 0x9e, 0x5e, 0x8e, 0x31, 0xcf, 0x5c, 0x31, 0xab, + 0x47, 0x0c, 0x2e, 0x66, 0xfa, 0xb6, 0x64, 0x16, 0xab, 0xe4, 0xcf, 0x1e, + 0x5a, 0xdc, 0xa7, 0x85, 0x89, 0xa2, 0xdf, 0x68, 0xc9, 0xff, 0x71, 0xa7, + 0x0d, 0x0c, 0xba, 0xa1, 0x30, 0xc4, 0x6b, 0x5c, 0x96, 0x4f, 0x19, 0xaa, + 0x8d, 0x19, 0xeb, 0x2a, 0x30, 0xc3, 0x5b, 0x50, 0xbb, 0x5f, 0xec, 0xc8, + 0xdc, 0x48, 0xef, 0xb3, 0x9d, 0xe5, 0xc7, 0xd5, 0x1f, 0x9e, 0xb6, 0x15, + 0x07, 0x6b, 0x47, 0xd1, 0xe3, 0x3c, 0x7f, 0x51, 0xee, 0x4e, 0x7e, 0x11, + 0x8b, 0xb9, 0x75, 0x90, 0x94, 0xd8, 0x92, 0x5a, 0xbd, 0xa4, 0xc0, 0xb8, + 0xfc, 0x02, 0xd1, 0xcd, 0xf1, 0x1f, 0x28, 0x16, 0x66, 0xc9, 0xe8, 0x5a, + 0x4a, 0x7d, 0xd8, 0xbf, 0x37, 0x5d, 0x43, 0x12, 0x1c, 0x57, 0xda, 0xe1, + 0x4d, 0x29, 0x9d, 0xf7, 0x9c, 0xc3, 0x53, 0x37, 0x7c, 0x1d, 0xe0, 0x14, + 0x3d, 0x92, 0xf1, 0x06, 0x64, 0x08, 0x49, 0xeb, 0xfe, 0x20, 0xed, 0x2a, + 0x34, 0x43, 0xfa, 0x24, 0x8d, 0x09, 0x4f, 0xaa, 0x0f, 0x99, 0xde, 0x6e, + 0x36, 0x89, 0x08, 0x55, 0x59, 0x28, 0xf5, 0x05, 0x1f, 0x28, 0x6f, 0x54, + 0xd3, 0x2f, 0x74, 0x58, 0x6b, 0x99, 0x89, 0xd9, 0x21, 0xe8, 0xdc, 0x04, + 0x1a, 0x89, 0x22, 0x08, 0xf5, 0x00, 0xc5, 0x95, 0x94, 0x5e, 0xae, 0x13, + 0x85, 0x79, 0x77, 0xa6, 0x03, 0x60, 0xdb, 0xa9, 0xdf, 0xcb, 0x7a, 0x9f, + 0x3d, 0xbb, 0x56, 0x97, 0xfc, 0xc3, 0xb3, 0x08, 0x59, 0xb5, 0xf6, 0x98, + 0xd5, 0x64, 0x54, 0x96, 0x38, 0x01, 0x9b, 0xa5, 0xba, 0x88, 0xfd, 0xe6, + 0x47, 0x48, 0x20, 0x49, 0x35, 0x74, 0xbd, 0x30, 0x1d, 0x62, 0x9f, 0xbc, + 0x8e, 0x25, 0x6b, 0x09, 0xc0, 0xfe, 0xbc, 0x28, 0x0a, 0xbe, 0x76, 0x11, + 0x7b, 0x8b, 0xfa, 0xac, 0x09, 0x35, 0x3d, 0x96, 0x1b, 0x15, 0x35, 0xe8, + 0xa5, 0x3d, 0xae, 0x8f, 0x11, 0x0c, 0x2b, 0x1e, 0x01, 0xf9, 0x9a, 0x11, + 0x7d, 0xa6, 0xe0, 0xa6, 0x89, 0x31, 0xb6, 0xa8, 0xf0, 0x1d, 0x7a, 0x66, + 0xd9, 0xad, 0x7e, 0x44, 0xcf, 0xc5, 0x5b, 0xf7, 0x65, 0xe9, 0x56, 0x2e, + 0xe5, 0x6d, 0x10, 0x69, 0x1d, 0x94, 0x52, 0x28, 0x30, 0x32, 0x78, 0x99, + 0xfb, 0x8f, 0xf6, 0xef, 0xd7, 0x75, 0x09, 0x4e, 0xa3, 0x51, 0x8f, 0xf7, + 0x2e, 0x4f, 0x01, 0x6f, 0x02, 0x61, 0xd6, 0xfb, 0xc9, 0x77, 0x50, 0xc6, + 0xb7, 0x41, 0xe9, 0x2f, 0x41, 0x9b, 0x04, 0x7c, 0x08, 0xe0, 0xc8, 0x75, + 0x98, 0x0d, 0x88, 0xa4, 0xd9, 0xb6, 0xe1, 0x59, 0xa0, 0x37, 0x9e, 0x5c, + 0xdc, 0xbf, 0x6e, 0xb8, 0xb6, 0x29, 0xd7, 0x61, 0xb0, 0xc7, 0x50, 0x20, + 0x0e, 0x06, 0x21, 0x6d, 0xa2, 0x85, 0xa5, 0x83, 0x55, 0xd7, 0x73, 0x42, + 0x52, 0xe5, 0x67, 0x4c, 0xde, 0xb1, 0x3b, 0x46, 0x99, 0x5d, 0xe1, 0xe9, + 0xd2, 0x9a, 0x02, 0x40, 0x9a, 0x5c, 0xdd, 0x22, 0x48, 0x1a, 0x3f, 0x30, + 0x8d, 0x2c, 0x43, 0xd8, 0xfe, 0x79, 0xe1, 0x66, 0x16, 0xb4, 0xc8, 0x30, + 0xd1, 0xb0, 0xe9, 0xb4, 0x56, 0x0d, 0x01, 0xcd, 0xe0, 0x16, 0x8b, 0x1f, + 0x57, 0x1d, 0x73, 0x1f, 0xa0, 0x97, 0xaa, 0x4f, 0xb1, 0x35, 0xc0, 0x5e, + 0xc6, 0x73, 0x2a, 0x90, 0xce, 0x2f, 0x60, 0x43, 0xce, 0x3d, 0x47, 0xa4, + 0x9a, 0x6a, 0x6d, 0x0b, 0xb8, 0xaf, 0x7d, 0x35, 0x0a, 0x60, 0xd8, 0x20, + 0xa6, 0x06, 0x69, 0x2c, 0xb0, 0xa3, 0x4a, 0xc8, 0xa8, 0x6b, 0x79, 0x06, + 0x1b, 0xd5, 0x2a, 0x09, 0x46, 0x6e, 0x52, 0x84, 0x29, 0xa7, 0xcb, 0xf8, + 0x38, 0x87, 0xb7, 0x8f, 0x5f, 0x2b, 0x00, 0x06, 0xd5, 0x91, 0x70, 0x7d, + 0x9f, 0x54, 0x8d, 0xf8, 0xcb, 0x39, 0xac, 0x4f, 0x78, 0x50, 0xf1, 0xc8, + 0xd0, 0x23, 0x80, 0xb9, 0x1c, 0x22, 0x99, 0x8a, 0x0c, 0xb4, 0x96, 0x57, + 0x48, 0x12, 0x21, 0x1b, 0xf0, 0x43, 0x1c, 0xea, 0xa9, 0x4c, 0xc8, 0x14, + 0x37, 0xa7, 0xae, 0x19, 0x8a, 0x72, 0x4b, 0x59, 0xb5, 0xdc, 0x9e, 0xc6, + 0x3f, 0x99, 0x39, 0xe6, 0x6e, 0xad, 0x84, 0x70, 0x5c, 0xe7, 0x5f, 0x1b, + 0xa8, 0xe7, 0x90, 0x2e, 0xdd, 0x70, 0x15, 0x4c, 0xa6, 0x2e, 0x45, 0xad, + 0x96, 0x51, 0x04, 0x99, 0x19, 0x83, 0xe9, 0x9a, 0x94, 0x75, 0xc3, 0x6d, + 0x10, 0x80, 0x2d, 0x1a, 0x01, 0x23, 0x0d, 0x1e, 0xcd, 0x17, 0xd4, 0x88, + 0xe1, 0xa4, 0x87, 0xab, 0x98, 0xea, 0xf8, 0x3a, 0x1a, 0x85, 0x6b, 0xbe, + 0xa1, 0x60, 0x8b, 0x72, 0xca, 0xf0, 0xde, 0xbd, 0x74, 0x80, 0x71, 0x1e, + 0x95, 0x6a, 0x1e, 0x1c, 0x9d, 0xe9, 0x26, 0x68, 0xe8, 0x77, 0x5c, 0x58, + 0x5a, 0xa7, 0x9c, 0xda, 0x54, 0xea, 0xce, 0xa0, 0xb0, 0xff, 0x99, 0x59, + 0xcd, 0xf6, 0x11, 0xe2, 0xfc, 0x3f, 0xee, 0x57, 0x8c, 0x15, 0x26, 0x04, + 0xdc, 0x6f, 0xaa, 0xe8, 0x32, 0x1f, 0x35, 0xce, 0xc2, 0x09, 0x4f, 0x26, + 0x15, 0x76, 0x85, 0x2b, 0xa4, 0x24, 0x3a, 0xe3, 0xc4, 0x32, 0xb5, 0xcf, + 0x55, 0xc9, 0x27, 0xfc, 0x90, 0x3f, 0xea, 0x2f, 0xc3, 0x86, 0x48, 0xd8, + 0x2d, 0x55, 0xed, 0xfd, 0x28, 0x07, 0xb1, 0x10, 0xfb, 0xc7, 0x19, 0x02, + 0x1a, 0xd7, 0x85, 0x63, 0x78, 0x48, 0x03, 0x0d, 0xaf, 0x52, 0xae, 0xe7, + 0x58, 0x13, 0x31, 0x11, 0x00, 0x3f, 0x6e, 0x87, 0xb7, 0xc1, 0xda, 0x23, + 0x93, 0x56, 0x13, 0x8a, 0xa6, 0x81, 0x66, 0xa6, 0xe4, 0xc0, 0xa8, 0x2e, + 0xcb, 0x3d, 0xfe, 0x2d, 0x03, 0xb8, 0xe1, 0x43, 0x4c, 0xb3, 0x28, 0x03, + 0x4e, 0xac, 0xd4, 0x77, 0x30, 0x5e, 0x7c, 0x15, 0xf8, 0x55, 0xe0, 0x8e, + 0x7a, 0xb8, 0x52, 0x77, 0x3b, 0x07, 0xab, 0x2a, 0x42, 0xa0, 0xaf, 0x8a, + 0x24, 0xa9, 0x6c, 0x42, 0x2d, 0xdd, 0xb6, 0x18, 0x1f, 0xb2, 0x6a, 0x1c, + 0x44, 0x23, 0xb4, 0xb1, 0x00, 0x17, 0xc3, 0x66, 0x80, 0xce, 0x96, 0xd6, + 0xbf, 0x8c, 0xb4, 0xb0, 0x8c, 0x8a, 0xbc, 0x57, 0x91, 0xeb, 0x25, 0x85, + 0xde, 0x30, 0x43, 0x1a, 0xd3, 0x5b, 0x17, 0x55, 0x3a, 0xbd, 0x01, 0x7e, + 0x8f, 0xd4, 0x30, 0xc1, 0x0c, 0x57, 0x9c, 0x7b, 0x86, 0xe2, 0x6d, 0xcc, + 0xba, 0xce, 0xa6, 0xe3, 0x32, 0x05, 0x39, 0xc4, 0x4b, 0xb4, 0xb0, 0x18, + 0x96, 0x1c, 0x1b, 0x9c, 0x2c, 0x83, 0x9a, 0x26, 0x5b, 0x8d, 0x1e, 0x1f, + 0x00, 0x19, 0x31, 0x75, 0x32, 0xe7, 0x4e, 0xfd, 0x2d, 0xbe, 0x85, 0x4e, + 0xb1, 0xe7, 0xad, 0xba, 0x66, 0xfd, 0xcf, 0x0e, 0xa9, 0x99, 0xf3, 0x25, + 0x2b, 0xbd, 0xe5, 0x0e, 0x59, 0xcb, 0x93, 0x96, 0x2a, 0x9d, 0xf6, 0xf2, + 0x2e, 0x37, 0x79, 0x13, 0xbc, 0xd1, 0x57, 0xe0, 0x2f, 0x5b, 0x77, 0xb3, + 0xea, 0xdd, 0xd7, 0x04, 0x5b, 0xcf, 0x0f, 0x46, 0xfd, 0xc9, 0x02, 0x80, + 0x3b, 0xd1, 0xfc, 0x44, 0x0b, 0xfd, 0x47, 0xb1, 0x75, 0x82, 0x93, 0x4c, + 0xb6, 0x6f, 0x58, 0x98, 0x44, 0x72, 0x7d, 0xae, 0xeb, 0xb9, 0x55, 0x07, + 0x23, 0xd0, 0x3f, 0x88, 0x9c, 0xce, 0x68, 0xa9, 0x31, 0x19, 0xa1, 0xba, + 0xe4, 0x5a, 0xb8, 0xa5, 0x57, 0xee, 0x89, 0xe4, 0xbe, 0xf3, 0xbb, 0xa9, + 0xc0, 0xb9, 0x9c, 0x5d, 0xc5, 0xd4, 0x67, 0x28, 0x85, 0x9f, 0xea, 0xe4, + 0x50, 0xde, 0xdf, 0x34, 0x2d, 0xb1, 0x9a, 0x60, 0x7f, 0xd6, 0x18, 0x3a, + 0x85, 0x33, 0xba, 0xc9, 0x13, 0xa2, 0xc5, 0xab, 0xc0, 0x3e, 0x96, 0xd7, + 0x2e, 0xe1, 0x99, 0x2e, 0x33, 0xf9, 0xdd, 0x60, 0xc7, 0xa3, 0xfc, 0xf1, + 0x6f, 0x22, 0xc6, 0x50, 0x45, 0xdc, 0x8b, 0x39, 0x76, 0xe2, 0x25, 0xe4, + 0xa2, 0x84, 0x75, 0xdb, 0x74, 0x71, 0x4f, 0x4d, 0xd4, 0x31, 0x38, 0x1c, + 0x59, 0x8f, 0x30, 0xd6, 0x03, 0xd6, 0x6d, 0xb5, 0xd7, 0xf2, 0x33, 0xd4, + 0x4f, 0x06, 0x0f, 0xef, 0x53, 0x5e, 0x3b, 0x8d, 0xd9, 0x82, 0x57, 0x2e, + 0x33, 0xa8, 0x67, 0xe4, 0xf2, 0x2f, 0xfb, 0x2e, 0x56, 0xea, 0xdb, 0x2b, + 0x5f, 0x56, 0x75, 0x34, 0x2c, 0x6b, 0x1d, 0xf3, 0x4d, 0x90, 0x1b, 0x0c, + 0xad, 0x00, 0xbc, 0x32, 0xc8, 0x52, 0x9f, 0xab, 0x10, 0x1a, 0x65, 0x44, + 0x77, 0x1c, 0xe9, 0x24, 0x2b, 0x6f, 0x5b, 0xf1, 0x7c, 0x05, 0x65, 0xfd, + 0x06, 0x4d, 0x17, 0x07, 0x72, 0xeb, 0x63, 0x09, 0x33, 0x0e, 0x21, 0xd3, + 0x93, 0x58, 0x73, 0xe2, 0xb6, 0x15, 0x2c, 0x2d, 0x26, 0xd6, 0x80, 0x11, + 0x6a, 0x86, 0xb5, 0xd1, 0xf5, 0x58, 0xba, 0xda, 0x47, 0x85, 0xe9, 0xc7, + 0xb7, 0x3d, 0x1c, 0x38, 0xf7, 0x7d, 0xcb, 0x22, 0x59, 0x8a, 0x36, 0xa6, + 0x88, 0x81, 0x50, 0xd5, 0xd3, 0xa3, 0xbf, 0x15, 0xca, 0x53, 0x4b, 0xf2, + 0xe8, 0xdd, 0x57, 0xfc, 0x7b, 0xcd, 0x72, 0xac, 0x20, 0x51, 0xfb, 0xcf, + 0xcc, 0xce, 0x39, 0x1b, 0x3e, 0x63, 0xc4, 0x8a, 0x04, 0x4e, 0x60, 0xb6, + 0x4f, 0xc5, 0x84, 0x2f, 0x5b, 0xfe, 0xf7, 0x06, 0xe7, 0xc9, 0x81, 0x9b, + 0x83, 0x4e, 0x87, 0x5c, 0x29, 0x91, 0xe0, 0x3e, 0x6a, 0x35, 0xeb, 0xdd, + 0x5f, 0xfd, 0x2e, 0x76, 0x29, 0x18, 0x92, 0x13, 0x5e, 0xd7, 0x5f, 0x0e, + 0x70, 0x6a, 0x4b, 0xd7, 0xcb, 0xb6, 0x2b, 0xd6, 0xa2, 0x08, 0xee, 0x53, + 0x17, 0xc3, 0x90, 0x71, 0xca, 0xdd, 0x05, 0x2d, 0x81, 0x3e, 0x0d, 0xd1, + 0x60, 0x6e, 0xce, 0xf2, 0x65, 0xb1, 0xe3, 0x0d, 0x7c, 0xfc, 0xf0, 0x99, + 0x41, 0xe5, 0x17, 0xd1, 0x9b, 0xc3, 0x55, 0xe8, 0xed, 0x6d, 0x0b, 0x6b, + 0x10, 0x58, 0x0c, 0x71, 0xda, 0xce, 0x13, 0x59, 0xe2, 0x06, 0x52, 0x2b, + 0xd8, 0x3e, 0x89, 0x05, 0x06, 0xb0, 0x66, 0x8d, 0xd4, 0xc8, 0xb0, 0x07, + 0xcc, 0xed, 0xc2, 0xd3, 0x6f, 0x08, 0xf8, 0x14, 0x83, 0x41, 0x5f, 0xc3, + 0x8a, 0xc7, 0xda, 0x80, 0xcd, 0x52, 0xdb, 0xf4, 0xe7, 0x3e, 0x3d, 0x19, + 0x61, 0xd3, 0x3f, 0x11, 0xfe, 0x92, 0xa1, 0xa5, 0x12, 0xa2, 0x47, 0xf7, + 0x04, 0x7a, 0xf8, 0x2c, 0x95, 0xc3, 0x4e, 0xc6, 0x6e, 0x4c, 0x35, 0xbc, + 0x7a, 0x9f, 0x4c, 0x32, 0x4c, 0xa1, 0x93, 0x15, 0x79, 0x1f, 0x94, 0x10, + 0x6e, 0x46, 0x6e, 0xe8, 0x19, 0xd3, 0x1c, 0xf2, 0x28, 0xad, 0xc7, 0x4f, + 0xa7, 0x74, 0x8b, 0x19, 0x43, 0xc3, 0x87, 0xf0, 0x89, 0x7c, 0x21, 0xdc, + 0x2b, 0x58, 0x86, 0x08, 0xd9, 0x6d, 0x41, 0xcb, 0xa6, 0x1f, 0xcf, 0x43, + 0xf8, 0xf9, 0x9a, 0xd7, 0xd6, 0xc2, 0x93, 0x73, 0x2e, 0xc2, 0xa1, 0x9c, + 0xd6, 0xf4, 0x2b, 0x7d, 0x75, 0x37, 0xe3, 0x5c, 0x02, 0xb3, 0x25, 0x2c, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x2f, 0x7f, 0x25, 0x74, + 0xa0, 0xc3, 0x09, 0x92, 0x5d, 0x56, 0x55, 0x9f, 0x2b, 0xd3, 0xa6, 0xe0, + 0xe8, 0x00, 0xda, 0x26, 0x1d, 0x48, 0x4b, 0xb7, 0x3f, 0xe3, 0x8e, 0x43, + 0xef, 0x7d, 0x84, 0x0e, 0xd8, 0x5c, 0x0b, 0x88, 0xd3, 0x69, 0xd4, 0x79, + 0x98, 0xcc, 0xdb, 0x7d, 0x24, 0xdb, 0x68, 0x99, 0x65, 0x7c, 0xf4, 0xc5, + 0xca, 0xd7, 0x35, 0xe2, 0x60, 0x54, 0x4a, 0x5a, 0xad, 0x35, 0x66, 0x04, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x69, 0xc2, 0x9a, 0x16, + 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, 0xd4, 0xc4, 0x63, 0x29, + 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, 0x75, 0x6c, 0x06, 0x46, + 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, + 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, + 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, + 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, + 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, + 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, + 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, + 0x2f, 0x7f, 0x25, 0x74, 0xa0, 0xc3, 0x09, 0x92, 0x5d, 0x56, 0x55, 0x9f, + 0x2b, 0xd3, 0xa6, 0xe0, 0xe8, 0x00, 0xda, 0x26, 0x1d, 0x48, 0x4b, 0xb7, + 0x3f, 0xe3, 0x8e, 0x43, 0xef, 0x7d, 0x84, 0x0e, 0xd8, 0x5c, 0x0b, 0x88, + 0xd3, 0x69, 0xd4, 0x79, 0x98, 0xcc, 0xdb, 0x7d, 0x24, 0xdb, 0x68, 0x99, + 0x65, 0x7c, 0xf4, 0xc5, 0xca, 0xd7, 0x35, 0xe2, 0x60, 0x54, 0x4a, 0x5a, + 0xad, 0x35, 0x66, 0x04, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x69, 0xc2, 0x9a, 0x16, 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, + 0xd4, 0xc4, 0x63, 0x29, 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, + 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, + 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, + 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, + 0x5a, 0xab, 0x05, 0x26, 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, + 0x6d, 0xd2, 0x5e, 0xe2, 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, + 0xa5, 0x9c, 0xf7, 0x0c, 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, + 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, + 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, + 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, + 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, + 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, + 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, + 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, + 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, + 0xd8, 0x5c, 0x0b, 0x88, 0xd3, 0x69, 0xd4, 0x79, 0x98, 0xcc, 0xdb, 0x7d, + 0x24, 0xdb, 0x68, 0x99, 0x65, 0x7c, 0xf4, 0xc5, 0xca, 0xd7, 0x35, 0xe2, + 0x60, 0x54, 0x4a, 0x5a, 0xad, 0x35, 0x66, 0x04, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x69, 0xc2, 0x9a, 0x16, 0x15, 0xd0, 0x6c, 0xfc, + 0x5a, 0xe2, 0xf2, 0xfd, 0xd4, 0xc4, 0x63, 0x29, 0xa5, 0x8c, 0xed, 0x9e, + 0x1e, 0x8f, 0xac, 0x47, 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, + 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, + 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, + 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, 0x37, 0xa9, 0x42, 0x40, + 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, 0xa2, 0x05, 0x45, 0xc8, + 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, 0xe3, 0xcc, 0x6f, 0xcd, + 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, + 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, + 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, + 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, + 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, + 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, + 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, + 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, + 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, + 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, + 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x69, 0xc2, 0x9a, 0x16, + 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, 0xd4, 0xc4, 0x63, 0x29, + 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, 0x75, 0x6c, 0x06, 0x46, + 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, + 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, + 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, + 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, + 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, + 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, + 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, + 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, + 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, + 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, + 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, + 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, + 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, + 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, + 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, + 0x69, 0xc2, 0x9a, 0x16, 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, + 0xd4, 0xc4, 0x63, 0x29, 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, + 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, + 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, + 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, + 0x5a, 0xab, 0x05, 0x26, 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, + 0x6d, 0xd2, 0x5e, 0xe2, 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, + 0xa5, 0x9c, 0xf7, 0x0c, 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, + 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, + 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, + 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, + 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, + 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, + 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, + 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, + 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, + 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, + 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, + 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, + 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, + 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, + 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, + 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, + 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, + 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, + 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, + 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, 0x37, 0xa9, 0x42, 0x40, + 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, 0xa2, 0x05, 0x45, 0xc8, + 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, 0xe3, 0xcc, 0x6f, 0xcd, + 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, + 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, + 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, + 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, + 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, + 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, + 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, + 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, + 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, + 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, + 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, + 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, + 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, + 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, + 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, + 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, + 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, + 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, + 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, + 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, + 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, + 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, + 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, + 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, + 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, + 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, + 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, + 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, + 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, + 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, + 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, + 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, + 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, + 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, + 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, + 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, + 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, + 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, + 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, + 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, + 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, + 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, + 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, + 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, + 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, + 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, + 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, + 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, + 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, + 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, + 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, + 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, + 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, + 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, + 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, + 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, + 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, + 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, + 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, + 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, + 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, + 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, + 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, + 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, + 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, + 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, + 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, + 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, + 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, + 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, + 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, + 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, + 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, + 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, + 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, + 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, + 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, + 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, + 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, + 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, + 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, + 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, + 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, + 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, + 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, + 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, + 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xe8, 0x0f, 0x83, 0x02, + 0x34, 0xf2, 0x99, 0x3f, 0xfe, 0xac, 0xb3, 0x29, 0xc7, 0xbe, 0x07, 0xb3, + 0x25, 0x5b, 0x34, 0xb4, 0xf7, 0x24, 0x88, 0x8b, 0x59, 0x2b, 0x6c, 0x75, + 0x4f, 0x96, 0x18, 0x25, 0x23, 0xde, 0x6d, 0x42, 0x36, 0x8a, 0x34, 0x2e, + 0x6d, 0x25, 0x5b, 0xbb, 0xad, 0x94, 0x53, 0xf4, 0xdc, 0x87, 0x86, 0x45, + 0x93, 0xb7, 0xe4, 0x09, 0x8b, 0x27, 0x14, 0xb0, 0xdf, 0x6f, 0xd6, 0x23, + 0x81, 0x58, 0x1a, 0x2f, 0x32, 0x0b, 0x8b, 0xe9, 0x84, 0x8b, 0x2e, 0xd2, + 0x5f, 0xab, 0x61, 0x8d, 0x04, 0xf3, 0x98, 0x53, 0xa3, 0xde, 0x26, 0xba, + 0xba, 0x8b, 0xe4, 0x49, 0xcb, 0x94, 0xd0, 0x0d, 0xb0, 0x24, 0x58, 0x41, + 0x8d, 0xd2, 0x25, 0xac, 0x46, 0xd0, 0xff, 0x08, 0x43, 0xdd, 0xbf, 0x15, + 0xd4, 0x1a, 0x2f, 0x0f, 0xbd, 0xe5, 0x14, 0xc4, 0x07, 0xfb, 0xde, 0xfb, + 0x89, 0xed, 0x19, 0x06, 0xd5, 0x30, 0xd9, 0x1c, 0x88, 0x30, 0xd6, 0x3c, + 0x7a, 0x1c, 0x03, 0x3c, 0xd6, 0xa6, 0x20, 0x1b, 0x22, 0xdc, 0x97, 0xcc, + 0x5e, 0xa3, 0x2e, 0xff, 0x5d, 0xf4, 0xf0, 0xb5, 0x32, 0xd8, 0xf1, 0x0d, + 0x13, 0xf4, 0xe6, 0xda, 0xb7, 0x1a, 0x90, 0x79, 0xdc, 0xbb, 0x6a, 0xfb, + 0xb6, 0xfb, 0xb8, 0xe1, 0x86, 0x4f, 0xfa, 0x57, 0xec, 0xcf, 0xab, 0x76, + 0xbf, 0x65, 0x21, 0xef, 0x7a, 0x5e, 0x45, 0x1c, 0xfb, 0x3a, 0x63, 0x98, + 0xa7, 0x94, 0x18, 0x4f, 0xf4, 0x7a, 0xe5, 0xab, 0xf2, 0x84, 0x34, 0xfc, + 0xa1, 0x15, 0x13, 0x44, 0xfa, 0x0c, 0xc9, 0x3e, 0x14, 0x82, 0xd3, 0x7f, + 0x1e, 0x9c, 0xb1, 0x25, 0x1c, 0x9e, 0x00, 0x8d, 0xfc, 0x9c, 0x3e, 0x84, + 0x0f, 0x6b, 0xaa, 0xd5, 0xe7, 0x36, 0xf2, 0x94, 0xd8, 0x55, 0x2f, 0x11, + 0x23, 0xaf, 0x87, 0x07, 0xe6, 0x9a, 0x2a, 0x53, 0xa3, 0x09, 0x0d, 0x07, + 0x2f, 0x7f, 0x25, 0x74, 0xa0, 0xc3, 0x09, 0x92, 0x5d, 0x56, 0x55, 0x9f, + 0x2b, 0xd3, 0xa6, 0xe0, 0xe8, 0x00, 0xda, 0x26, 0x1d, 0x48, 0x4b, 0xb7, + 0x3f, 0xe3, 0x8e, 0x43, 0xef, 0x7d, 0x84, 0x0e, 0x32, 0x1a, 0xdd, 0xe6, + 0x67, 0x3a, 0x06, 0x0c, 0x93, 0x3a, 0xb9, 0xdf, 0x01, 0xc0, 0x2f, 0x12, + 0x98, 0xc3, 0xf3, 0xa1, 0x5c, 0xb3, 0x45, 0x53, 0x00, 0xe5, 0xfb, 0x15, + 0x62, 0x05, 0x1a, 0x13, 0x79, 0xd7, 0xdb, 0xf5, 0x83, 0x9b, 0xa9, 0xa7, + 0xf9, 0xe4, 0x08, 0x06, 0x56, 0xaf, 0x3a, 0x60, 0xfc, 0x9b, 0x2a, 0x50, + 0xf2, 0x3d, 0x5a, 0x6e, 0x30, 0x39, 0xb5, 0x44, 0x2c, 0xc2, 0x9c, 0x18, + 0xe6, 0x7c, 0x77, 0x4b, 0x5f, 0xec, 0x92, 0x42, 0xf8, 0x8a, 0xac, 0x3c, + 0x58, 0x05, 0xe2, 0x9b, 0xa4, 0x5e, 0xec, 0x81, 0x4e, 0x4e, 0xa8, 0x94, + 0xcc, 0x04, 0x32, 0xa9, 0x49, 0xb2, 0x50, 0x0f, 0x34, 0xae, 0x0b, 0xd6, + 0xfd, 0xec, 0xe1, 0x47, 0xa5, 0xe6, 0x97, 0x44, 0x60, 0x2c, 0xca, 0x32, + 0x82, 0xef, 0x97, 0x39, 0x07, 0xdf, 0x29, 0xb2, 0x95, 0x8c, 0x65, 0xff, + 0x26, 0x3a, 0xa7, 0x2f, 0xf9, 0xfd, 0x98, 0x34, 0x9f, 0xae, 0x9b, 0x1b, + 0x46, 0xeb, 0xa6, 0x0c, 0xbc, 0xfb, 0x1b, 0xc8, 0x7f, 0x4c, 0xf5, 0x2b, + 0xda, 0x87, 0xf1, 0x8e, 0xd3, 0x60, 0xcf, 0x94, 0xfd, 0x10, 0x0c, 0x10, + 0x2f, 0x00, 0xc7, 0xf5, 0x24, 0x55, 0xcc, 0xcf, 0x1a, 0xdb, 0x03, 0x89, + 0x0f, 0xb7, 0x68, 0x34, 0x55, 0x42, 0x67, 0x56, 0x00, 0xd0, 0x44, 0xea, + 0xc0, 0x2a, 0x10, 0xf6, 0x79, 0x73, 0x42, 0x28, 0x7d, 0x7b, 0x58, 0xa1, + 0x66, 0x91, 0xef, 0x5b, 0x17, 0xdf, 0xe4, 0xa0, 0x77, 0x90, 0x78, 0x63, + 0x00, 0x7e, 0xb1, 0x30, 0x1e, 0xac, 0xb0, 0x17, 0x55, 0x0f, 0xc5, 0x37, + 0x06, 0x22, 0x1e, 0x2c, 0xff, 0x38, 0x5a, 0xf5, 0x56, 0xcf, 0x19, 0x3b, + 0xc9, 0x79, 0x35, 0xda, 0x21, 0xc5, 0x51, 0xc3, 0x86, 0xc1, 0x7d, 0x79, + 0xa7, 0x80, 0x48, 0x4b, 0x63, 0x95, 0xa5, 0x3f, 0x1b, 0xc4, 0x7a, 0x1d, + 0xd8, 0x5c, 0x0b, 0x88, 0xd3, 0x69, 0xd4, 0x79, 0x98, 0xcc, 0xdb, 0x7d, + 0x24, 0xdb, 0x68, 0x99, 0x65, 0x7c, 0xf4, 0xc5, 0xca, 0xd7, 0x35, 0xe2, + 0x60, 0x54, 0x4a, 0x5a, 0xad, 0x35, 0x66, 0x04, 0x79, 0xd7, 0xdb, 0xf5, + 0x83, 0x9b, 0xa9, 0xa7, 0xf9, 0xe4, 0x08, 0x06, 0x56, 0xaf, 0x3a, 0x60, + 0xfc, 0x9b, 0x2a, 0x50, 0xf2, 0x3d, 0x5a, 0x6e, 0x30, 0x39, 0xb5, 0x44, + 0x2c, 0xc2, 0x9c, 0x18, 0xda, 0xa7, 0xdc, 0xa8, 0xe4, 0xd7, 0x97, 0xd8, + 0x2a, 0x1f, 0x7a, 0x4f, 0x31, 0x86, 0x57, 0xed, 0x18, 0xef, 0x98, 0xef, + 0xd4, 0x16, 0x73, 0xe7, 0x30, 0xb2, 0xf1, 0x4d, 0xdd, 0x45, 0xfa, 0x13, + 0xd0, 0xde, 0xac, 0xb2, 0xac, 0x99, 0x66, 0x8b, 0x79, 0xe0, 0xb8, 0x10, + 0x81, 0xcd, 0xcd, 0xd7, 0xbc, 0x09, 0x26, 0x70, 0x64, 0x3e, 0xd1, 0x37, + 0x80, 0x70, 0x55, 0x4a, 0xc7, 0x45, 0x0a, 0x30, 0xf9, 0x22, 0x91, 0x2b, + 0x36, 0x2d, 0x05, 0xac, 0xb9, 0x79, 0x06, 0xb9, 0xa3, 0x1e, 0xc3, 0x68, + 0x3a, 0x1e, 0x23, 0x5a, 0x99, 0x7d, 0x67, 0xca, 0xac, 0x90, 0x92, 0xb1, + 0x90, 0x05, 0xb1, 0x04, 0x39, 0xc5, 0xc3, 0x82, 0x28, 0x05, 0xbf, 0xbf, + 0x9e, 0xa6, 0x95, 0xf8, 0x0f, 0x5e, 0x0c, 0xdd, 0x1b, 0xd6, 0xdb, 0x1c, + 0x2f, 0x57, 0xc3, 0x14, 0xeb, 0xc8, 0xe5, 0xaf, 0xa8, 0x68, 0x05, 0x25, + 0xe9, 0x7a, 0xcf, 0x0a, 0x1d, 0x67, 0x42, 0xdd, 0x82, 0xc0, 0xb2, 0xcd, + 0xf0, 0xe6, 0xd9, 0x0e, 0x0f, 0x41, 0x03, 0x8d, 0xc4, 0xe1, 0x64, 0x78, + 0x95, 0x1f, 0x27, 0xbf, 0x2c, 0x3a, 0xde, 0x22, 0x44, 0x12, 0x95, 0xf4, + 0xc9, 0x91, 0xc2, 0x3f, 0x63, 0x32, 0x9c, 0x9a, 0x77, 0x7e, 0x11, 0x8f, + 0x53, 0xe2, 0x65, 0x4b, 0x8f, 0xa4, 0x10, 0xff, 0x68, 0x23, 0xc1, 0xd2, + 0x34, 0xf8, 0xdb, 0x29, 0x50, 0x84, 0x80, 0x95, 0xcc, 0x2d, 0x7e, 0x1f, + 0x6e, 0x4e, 0x3e, 0x2c, 0x2b, 0x9f, 0x2e, 0x83, 0x01, 0x3c, 0xb3, 0x31, + 0x7c, 0x13, 0x29, 0x01, 0x67, 0xf2, 0x6e, 0xd7, 0x13, 0x86, 0x17, 0x08, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xe6, 0x7c, 0x77, 0x4b, + 0x5f, 0xec, 0x92, 0x42, 0xf8, 0x8a, 0xac, 0x3c, 0x58, 0x05, 0xe2, 0x9b, + 0xa4, 0x5e, 0xec, 0x81, 0x4e, 0x4e, 0xa8, 0x94, 0xcc, 0x04, 0x32, 0xa9, + 0x49, 0xb2, 0x50, 0x0f, 0xd0, 0xde, 0xac, 0xb2, 0xac, 0x99, 0x66, 0x8b, + 0x79, 0xe0, 0xb8, 0x10, 0x81, 0xcd, 0xcd, 0xd7, 0xbc, 0x09, 0x26, 0x70, + 0x64, 0x3e, 0xd1, 0x37, 0x80, 0x70, 0x55, 0x4a, 0xc7, 0x45, 0x0a, 0x30, + 0x17, 0x10, 0xb8, 0xd2, 0x62, 0xfc, 0xa5, 0x94, 0xf5, 0xd3, 0x62, 0xdc, + 0x5e, 0x02, 0xc1, 0x36, 0x77, 0x47, 0xb3, 0xd6, 0x85, 0x7b, 0x50, 0x39, + 0x0d, 0x85, 0xa0, 0x02, 0x6a, 0xf8, 0xa6, 0x20, 0x2a, 0x90, 0x56, 0x36, + 0xde, 0x2d, 0xa5, 0xdd, 0x78, 0x3a, 0x0b, 0x44, 0x74, 0x09, 0x04, 0xd5, + 0x95, 0x9d, 0x6e, 0x6a, 0xcc, 0x85, 0x22, 0xa8, 0x2a, 0x0a, 0xf6, 0x60, + 0x50, 0x9f, 0x36, 0x1c, 0xba, 0x0d, 0xde, 0x91, 0xc4, 0x04, 0x38, 0x9f, + 0xff, 0xd6, 0x5c, 0xde, 0x87, 0x98, 0x52, 0xca, 0x43, 0x08, 0x2e, 0x80, + 0xc0, 0xa5, 0xed, 0xf5, 0x30, 0x6c, 0xd2, 0x83, 0x43, 0xb0, 0xf1, 0x0e, + 0x2e, 0x09, 0xa3, 0x12, 0xf7, 0xb3, 0x16, 0xa9, 0xf9, 0x48, 0x09, 0xd0, + 0xc3, 0x7f, 0x27, 0x61, 0x99, 0x98, 0xb9, 0xa1, 0xb2, 0x91, 0x73, 0x43, + 0x09, 0x60, 0x7a, 0x76, 0x19, 0xca, 0xc5, 0x2d, 0xa4, 0x3e, 0x90, 0x27, + 0x82, 0xe7, 0x5f, 0xa1, 0xdd, 0x91, 0x8b, 0x41, 0x5f, 0x6c, 0xef, 0xde, + 0x04, 0x87, 0xcf, 0x9c, 0x46, 0x02, 0x09, 0xa0, 0x86, 0xd5, 0xfe, 0x65, + 0xfb, 0x21, 0x82, 0x18, 0x89, 0x5a, 0xb6, 0x85, 0xe7, 0xcb, 0x33, 0x75, + 0x07, 0x94, 0xed, 0xf0, 0xcb, 0x05, 0x95, 0x72, 0x71, 0x2b, 0x17, 0xab, + 0x72, 0xfc, 0xf9, 0x8f, 0x98, 0x8b, 0x43, 0x7b, 0xda, 0x5b, 0x72, 0x0e, + 0x69, 0xc2, 0x9a, 0x16, 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, + 0xd4, 0xc4, 0x63, 0x29, 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, + 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, 0x34, 0xae, 0x0b, 0xd6, + 0xfd, 0xec, 0xe1, 0x47, 0xa5, 0xe6, 0x97, 0x44, 0x60, 0x2c, 0xca, 0x32, + 0x82, 0xef, 0x97, 0x39, 0x07, 0xdf, 0x29, 0xb2, 0x95, 0x8c, 0x65, 0xff, + 0x26, 0x3a, 0xa7, 0x2f, 0xf9, 0x22, 0x91, 0x2b, 0x36, 0x2d, 0x05, 0xac, + 0xb9, 0x79, 0x06, 0xb9, 0xa3, 0x1e, 0xc3, 0x68, 0x3a, 0x1e, 0x23, 0x5a, + 0x99, 0x7d, 0x67, 0xca, 0xac, 0x90, 0x92, 0xb1, 0x90, 0x05, 0xb1, 0x04, + 0x2a, 0x90, 0x56, 0x36, 0xde, 0x2d, 0xa5, 0xdd, 0x78, 0x3a, 0x0b, 0x44, + 0x74, 0x09, 0x04, 0xd5, 0x95, 0x9d, 0x6e, 0x6a, 0xcc, 0x85, 0x22, 0xa8, + 0x2a, 0x0a, 0xf6, 0x60, 0x50, 0x9f, 0x36, 0x1c, 0x3d, 0x63, 0x69, 0x40, + 0x19, 0xa8, 0x54, 0x93, 0xaa, 0xd5, 0x4c, 0x4f, 0x72, 0xd4, 0x14, 0xb9, + 0x05, 0x24, 0xd9, 0x96, 0x39, 0x17, 0x95, 0x70, 0xf5, 0x35, 0xf0, 0x02, + 0xfa, 0x9c, 0xcb, 0x06, 0xde, 0xea, 0x98, 0x0d, 0xb8, 0xf4, 0x48, 0x4d, + 0x55, 0xec, 0x18, 0x2a, 0xa5, 0xed, 0x12, 0xb5, 0x66, 0x28, 0xc6, 0x08, + 0x55, 0x60, 0x58, 0xf6, 0x23, 0x7e, 0x26, 0xd1, 0xc0, 0x22, 0x5e, 0x1e, + 0x71, 0x1a, 0xb9, 0xbb, 0xce, 0x73, 0xf1, 0x08, 0xf1, 0x22, 0xd3, 0x8b, + 0x6f, 0xa6, 0x39, 0x75, 0xf6, 0x71, 0xfb, 0xc4, 0xff, 0xf2, 0x7b, 0x7f, + 0x5d, 0x29, 0xaa, 0x7e, 0x99, 0xa2, 0xf5, 0x07, 0x85, 0x75, 0x9c, 0xf4, + 0x22, 0xb7, 0x62, 0xee, 0xf7, 0xe8, 0xaf, 0x05, 0x7a, 0xe1, 0x1d, 0x15, + 0x87, 0xca, 0xde, 0xfb, 0xce, 0xca, 0xbd, 0x68, 0xea, 0x39, 0x26, 0xda, + 0x4d, 0x48, 0xbb, 0x0e, 0x03, 0xbb, 0xf7, 0xd3, 0x00, 0x71, 0xf5, 0x75, + 0x6b, 0x2a, 0x4e, 0x3e, 0xf5, 0xad, 0x7b, 0x61, 0x89, 0x51, 0x71, 0xbe, + 0x9f, 0xd0, 0xd8, 0xac, 0xfe, 0xec, 0xf6, 0x1e, 0x03, 0x95, 0x96, 0x1b, + 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, + 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, + 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, 0xf9, 0xfd, 0x98, 0x34, + 0x9f, 0xae, 0x9b, 0x1b, 0x46, 0xeb, 0xa6, 0x0c, 0xbc, 0xfb, 0x1b, 0xc8, + 0x7f, 0x4c, 0xf5, 0x2b, 0xda, 0x87, 0xf1, 0x8e, 0xd3, 0x60, 0xcf, 0x94, + 0xfd, 0x10, 0x0c, 0x10, 0x39, 0xc5, 0xc3, 0x82, 0x28, 0x05, 0xbf, 0xbf, + 0x9e, 0xa6, 0x95, 0xf8, 0x0f, 0x5e, 0x0c, 0xdd, 0x1b, 0xd6, 0xdb, 0x1c, + 0x2f, 0x57, 0xc3, 0x14, 0xeb, 0xc8, 0xe5, 0xaf, 0xa8, 0x68, 0x05, 0x25, + 0xba, 0x0d, 0xde, 0x91, 0xc4, 0x04, 0x38, 0x9f, 0xff, 0xd6, 0x5c, 0xde, + 0x87, 0x98, 0x52, 0xca, 0x43, 0x08, 0x2e, 0x80, 0xc0, 0xa5, 0xed, 0xf5, + 0x30, 0x6c, 0xd2, 0x83, 0x43, 0xb0, 0xf1, 0x0e, 0xde, 0xea, 0x98, 0x0d, + 0xb8, 0xf4, 0x48, 0x4d, 0x55, 0xec, 0x18, 0x2a, 0xa5, 0xed, 0x12, 0xb5, + 0x66, 0x28, 0xc6, 0x08, 0x55, 0x60, 0x58, 0xf6, 0x23, 0x7e, 0x26, 0xd1, + 0xc0, 0x22, 0x5e, 0x1e, 0x4f, 0x96, 0x18, 0x12, 0x4e, 0x4a, 0x60, 0x12, + 0x58, 0x9d, 0xbf, 0x6a, 0x68, 0xd4, 0x97, 0xba, 0x0c, 0x85, 0xd4, 0x59, + 0x82, 0x31, 0xb2, 0x51, 0xb7, 0x80, 0xda, 0xdd, 0x62, 0x5e, 0x85, 0x17, + 0x1c, 0x11, 0xc6, 0x45, 0x61, 0x8a, 0x25, 0x39, 0xc0, 0xee, 0x1f, 0xa6, + 0xb8, 0x2e, 0x1c, 0xd9, 0xb3, 0x59, 0xf8, 0x53, 0x49, 0xbc, 0x5a, 0xc8, + 0x9c, 0xcb, 0x51, 0xa0, 0xe9, 0xc6, 0xb1, 0x14, 0xe7, 0x3c, 0x90, 0x33, + 0xd3, 0x8d, 0x9c, 0x51, 0xa3, 0x8b, 0x16, 0x64, 0x6d, 0xf9, 0x94, 0xd4, + 0xfa, 0xb6, 0x34, 0x1b, 0x55, 0x51, 0x46, 0x44, 0xb3, 0x53, 0x6a, 0x06, + 0xef, 0x2e, 0x20, 0x24, 0x30, 0x62, 0x1b, 0x5b, 0x16, 0x40, 0xef, 0x96, + 0xbc, 0xcb, 0x65, 0x68, 0x13, 0x01, 0x21, 0x88, 0xc1, 0x84, 0xf3, 0x4b, + 0x62, 0xbd, 0x6b, 0x28, 0x26, 0xd5, 0xc6, 0xca, 0x7a, 0xa3, 0xc8, 0x0f, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x2f, 0x00, 0xc7, 0xf5, + 0x24, 0x55, 0xcc, 0xcf, 0x1a, 0xdb, 0x03, 0x89, 0x0f, 0xb7, 0x68, 0x34, + 0x55, 0x42, 0x67, 0x56, 0x00, 0xd0, 0x44, 0xea, 0xc0, 0x2a, 0x10, 0xf6, + 0x79, 0x73, 0x42, 0x28, 0xe9, 0x7a, 0xcf, 0x0a, 0x1d, 0x67, 0x42, 0xdd, + 0x82, 0xc0, 0xb2, 0xcd, 0xf0, 0xe6, 0xd9, 0x0e, 0x0f, 0x41, 0x03, 0x8d, + 0xc4, 0xe1, 0x64, 0x78, 0x95, 0x1f, 0x27, 0xbf, 0x2c, 0x3a, 0xde, 0x22, + 0x2e, 0x09, 0xa3, 0x12, 0xf7, 0xb3, 0x16, 0xa9, 0xf9, 0x48, 0x09, 0xd0, + 0xc3, 0x7f, 0x27, 0x61, 0x99, 0x98, 0xb9, 0xa1, 0xb2, 0x91, 0x73, 0x43, + 0x09, 0x60, 0x7a, 0x76, 0x19, 0xca, 0xc5, 0x2d, 0x71, 0x1a, 0xb9, 0xbb, + 0xce, 0x73, 0xf1, 0x08, 0xf1, 0x22, 0xd3, 0x8b, 0x6f, 0xa6, 0x39, 0x75, + 0xf6, 0x71, 0xfb, 0xc4, 0xff, 0xf2, 0x7b, 0x7f, 0x5d, 0x29, 0xaa, 0x7e, + 0x99, 0xa2, 0xf5, 0x07, 0x1c, 0x11, 0xc6, 0x45, 0x61, 0x8a, 0x25, 0x39, + 0xc0, 0xee, 0x1f, 0xa6, 0xb8, 0x2e, 0x1c, 0xd9, 0xb3, 0x59, 0xf8, 0x53, + 0x49, 0xbc, 0x5a, 0xc8, 0x9c, 0xcb, 0x51, 0xa0, 0xe9, 0xc6, 0xb1, 0x14, + 0xb9, 0xde, 0x70, 0x3f, 0x37, 0x0e, 0x7e, 0xdd, 0x42, 0x5a, 0x85, 0x71, + 0xd8, 0x8e, 0x60, 0x30, 0x09, 0xcc, 0xc1, 0xe3, 0x62, 0xa4, 0x1e, 0xab, + 0x1c, 0x59, 0x6b, 0x4d, 0xca, 0x4e, 0x21, 0x07, 0x4c, 0x92, 0x5a, 0x94, + 0xa7, 0x83, 0x3c, 0xf4, 0x1a, 0x29, 0x73, 0xe6, 0x6c, 0x80, 0xec, 0x94, + 0xc0, 0x29, 0xd1, 0x7e, 0xc2, 0xe3, 0x37, 0x07, 0x87, 0x0e, 0x6e, 0xad, + 0x12, 0xbb, 0x56, 0x10, 0x10, 0xe7, 0x36, 0x52, 0xf5, 0x44, 0xfc, 0xb9, + 0x2f, 0x7c, 0x4e, 0x73, 0x10, 0x62, 0xfd, 0xbb, 0x60, 0xd5, 0x3a, 0x8d, + 0x31, 0xc2, 0xb6, 0xaf, 0x73, 0xe4, 0xee, 0xd9, 0xc7, 0x11, 0x08, 0x01, + 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, + 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, + 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, 0x7d, 0x7b, 0x58, 0xa1, + 0x66, 0x91, 0xef, 0x5b, 0x17, 0xdf, 0xe4, 0xa0, 0x77, 0x90, 0x78, 0x63, + 0x00, 0x7e, 0xb1, 0x30, 0x1e, 0xac, 0xb0, 0x17, 0x55, 0x0f, 0xc5, 0x37, + 0x06, 0x22, 0x1e, 0x2c, 0x44, 0x12, 0x95, 0xf4, 0xc9, 0x91, 0xc2, 0x3f, + 0x63, 0x32, 0x9c, 0x9a, 0x77, 0x7e, 0x11, 0x8f, 0x53, 0xe2, 0x65, 0x4b, + 0x8f, 0xa4, 0x10, 0xff, 0x68, 0x23, 0xc1, 0xd2, 0x34, 0xf8, 0xdb, 0x29, + 0xa4, 0x3e, 0x90, 0x27, 0x82, 0xe7, 0x5f, 0xa1, 0xdd, 0x91, 0x8b, 0x41, + 0x5f, 0x6c, 0xef, 0xde, 0x04, 0x87, 0xcf, 0x9c, 0x46, 0x02, 0x09, 0xa0, + 0x86, 0xd5, 0xfe, 0x65, 0xfb, 0x21, 0x82, 0x18, 0x85, 0x75, 0x9c, 0xf4, + 0x22, 0xb7, 0x62, 0xee, 0xf7, 0xe8, 0xaf, 0x05, 0x7a, 0xe1, 0x1d, 0x15, + 0x87, 0xca, 0xde, 0xfb, 0xce, 0xca, 0xbd, 0x68, 0xea, 0x39, 0x26, 0xda, + 0x4d, 0x48, 0xbb, 0x0e, 0xe7, 0x3c, 0x90, 0x33, 0xd3, 0x8d, 0x9c, 0x51, + 0xa3, 0x8b, 0x16, 0x64, 0x6d, 0xf9, 0x94, 0xd4, 0xfa, 0xb6, 0x34, 0x1b, + 0x55, 0x51, 0x46, 0x44, 0xb3, 0x53, 0x6a, 0x06, 0xef, 0x2e, 0x20, 0x24, + 0x4c, 0x92, 0x5a, 0x94, 0xa7, 0x83, 0x3c, 0xf4, 0x1a, 0x29, 0x73, 0xe6, + 0x6c, 0x80, 0xec, 0x94, 0xc0, 0x29, 0xd1, 0x7e, 0xc2, 0xe3, 0x37, 0x07, + 0x87, 0x0e, 0x6e, 0xad, 0x12, 0xbb, 0x56, 0x10, 0x83, 0x24, 0xac, 0xfa, + 0xfc, 0x14, 0x5b, 0x74, 0xb9, 0xcf, 0x8d, 0x2a, 0xb3, 0x08, 0x7b, 0x89, + 0x97, 0xc3, 0xfc, 0x27, 0x9a, 0x3d, 0xe8, 0x22, 0xd1, 0xf3, 0x95, 0x30, + 0x7e, 0x8f, 0x63, 0x09, 0x20, 0xef, 0x10, 0x38, 0xdc, 0x3c, 0x61, 0x41, + 0x5f, 0x42, 0x73, 0x1a, 0xb5, 0xeb, 0xad, 0xcd, 0x71, 0x64, 0x83, 0x23, + 0xd4, 0x18, 0xec, 0x93, 0x2b, 0x26, 0x0b, 0x5c, 0xaf, 0xf6, 0x76, 0x2f, + 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, + 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, + 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, 0xff, 0x38, 0x5a, 0xf5, + 0x56, 0xcf, 0x19, 0x3b, 0xc9, 0x79, 0x35, 0xda, 0x21, 0xc5, 0x51, 0xc3, + 0x86, 0xc1, 0x7d, 0x79, 0xa7, 0x80, 0x48, 0x4b, 0x63, 0x95, 0xa5, 0x3f, + 0x1b, 0xc4, 0x7a, 0x1d, 0x50, 0x84, 0x80, 0x95, 0xcc, 0x2d, 0x7e, 0x1f, + 0x6e, 0x4e, 0x3e, 0x2c, 0x2b, 0x9f, 0x2e, 0x83, 0x01, 0x3c, 0xb3, 0x31, + 0x7c, 0x13, 0x29, 0x01, 0x67, 0xf2, 0x6e, 0xd7, 0x13, 0x86, 0x17, 0x08, + 0x89, 0x5a, 0xb6, 0x85, 0xe7, 0xcb, 0x33, 0x75, 0x07, 0x94, 0xed, 0xf0, + 0xcb, 0x05, 0x95, 0x72, 0x71, 0x2b, 0x17, 0xab, 0x72, 0xfc, 0xf9, 0x8f, + 0x98, 0x8b, 0x43, 0x7b, 0xda, 0x5b, 0x72, 0x0e, 0x03, 0xbb, 0xf7, 0xd3, + 0x00, 0x71, 0xf5, 0x75, 0x6b, 0x2a, 0x4e, 0x3e, 0xf5, 0xad, 0x7b, 0x61, + 0x89, 0x51, 0x71, 0xbe, 0x9f, 0xd0, 0xd8, 0xac, 0xfe, 0xec, 0xf6, 0x1e, + 0x03, 0x95, 0x96, 0x1b, 0x30, 0x62, 0x1b, 0x5b, 0x16, 0x40, 0xef, 0x96, + 0xbc, 0xcb, 0x65, 0x68, 0x13, 0x01, 0x21, 0x88, 0xc1, 0x84, 0xf3, 0x4b, + 0x62, 0xbd, 0x6b, 0x28, 0x26, 0xd5, 0xc6, 0xca, 0x7a, 0xa3, 0xc8, 0x0f, + 0x10, 0xe7, 0x36, 0x52, 0xf5, 0x44, 0xfc, 0xb9, 0x2f, 0x7c, 0x4e, 0x73, + 0x10, 0x62, 0xfd, 0xbb, 0x60, 0xd5, 0x3a, 0x8d, 0x31, 0xc2, 0xb6, 0xaf, + 0x73, 0xe4, 0xee, 0xd9, 0xc7, 0x11, 0x08, 0x01, 0x20, 0xef, 0x10, 0x38, + 0xdc, 0x3c, 0x61, 0x41, 0x5f, 0x42, 0x73, 0x1a, 0xb5, 0xeb, 0xad, 0xcd, + 0x71, 0x64, 0x83, 0x23, 0xd4, 0x18, 0xec, 0x93, 0x2b, 0x26, 0x0b, 0x5c, + 0xaf, 0xf6, 0x76, 0x2f, 0x9a, 0xc4, 0x1b, 0x5a, 0x45, 0x34, 0x22, 0x6c, + 0x67, 0x75, 0x23, 0xe9, 0xb3, 0x42, 0x58, 0xfb, 0xb4, 0x1f, 0x42, 0x25, + 0x7f, 0xb5, 0x1a, 0x7a, 0x57, 0x55, 0x89, 0x99, 0x6b, 0x36, 0x76, 0x22, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x27, 0xd3, 0xd4, 0x04, + 0xb2, 0xc7, 0x99, 0xb4, 0xc1, 0x96, 0xf3, 0xa7, 0x20, 0xcf, 0xd7, 0x4c, + 0x42, 0xa5, 0xbd, 0x13, 0xeb, 0xaf, 0x7a, 0x90, 0x16, 0x71, 0x32, 0xa8, + 0x26, 0x9b, 0x39, 0x10, 0x0e, 0xe1, 0x98, 0xec, 0xc2, 0xb8, 0xb3, 0x83, + 0x77, 0x9e, 0xec, 0xa5, 0x8f, 0xf9, 0x08, 0xc1, 0xbf, 0xec, 0x17, 0xf3, + 0xf9, 0xe4, 0x30, 0x17, 0x38, 0x43, 0x30, 0xfa, 0xbd, 0xe5, 0x2d, 0x1b, + 0xbf, 0xcb, 0x6b, 0xc8, 0x47, 0xd1, 0x1f, 0xdf, 0x53, 0xf5, 0x39, 0x4b, + 0x0e, 0xbf, 0x62, 0xe2, 0x36, 0x3b, 0x3d, 0xbf, 0xf3, 0xc8, 0xb2, 0x52, + 0x50, 0xdd, 0xf5, 0x66, 0x10, 0xa8, 0xef, 0x1e, 0x52, 0xa0, 0x64, 0xc8, + 0xbb, 0x33, 0x5f, 0x81, 0x44, 0x8c, 0xde, 0xde, 0x3b, 0x44, 0xa5, 0x67, + 0x9a, 0xa2, 0xdc, 0x6e, 0x14, 0xe0, 0x42, 0x0e, 0xc3, 0x01, 0xcf, 0x9c, + 0xdf, 0x71, 0xf1, 0x24, 0xd3, 0x13, 0x04, 0xfe, 0xc3, 0xbb, 0xd2, 0x5c, + 0x0a, 0x86, 0x86, 0x2d, 0x6c, 0x54, 0x9e, 0xb5, 0x2e, 0x67, 0xa5, 0xcb, + 0x16, 0xcf, 0x1a, 0x96, 0x3a, 0x34, 0xf4, 0x89, 0x39, 0xe0, 0xb0, 0x06, + 0xf0, 0x9f, 0x4a, 0x8a, 0xc5, 0x4f, 0x8c, 0x60, 0xbc, 0x8a, 0x3c, 0x0a, + 0x54, 0x32, 0x3a, 0x72, 0x91, 0xeb, 0xc0, 0x86, 0x20, 0x4e, 0x0a, 0x6a, + 0xd2, 0xdd, 0x8e, 0x9a, 0x4f, 0x16, 0xfe, 0x0d, 0x4e, 0x7a, 0x01, 0xe1, + 0x08, 0x1a, 0x51, 0x8c, 0x4a, 0x32, 0x67, 0xab, 0x18, 0x49, 0xac, 0x7d, + 0x14, 0xe0, 0xaa, 0x25, 0x1b, 0x59, 0x1e, 0x72, 0x2a, 0xf5, 0xd3, 0x19, + 0x8a, 0x5f, 0x6d, 0x2c, 0xc8, 0x32, 0xe4, 0xab, 0xdb, 0xeb, 0x8e, 0xb0, + 0xe0, 0x99, 0x48, 0x45, 0x7b, 0x8e, 0x41, 0xaa, 0x76, 0x1f, 0x99, 0xf5, + 0xd8, 0x3f, 0xe0, 0x15, 0x08, 0xd9, 0x04, 0x0f, 0xb3, 0x42, 0x55, 0x2e, + 0x76, 0x1a, 0xf7, 0x88, 0xa8, 0x8a, 0x26, 0x7a, 0xe6, 0x68, 0x6c, 0xc9, + 0x85, 0x4d, 0x02, 0x64, 0xfc, 0xf0, 0x55, 0xb2, 0x91, 0xd8, 0xe7, 0x67, + 0x42, 0x6f, 0x65, 0x4f, 0xec, 0xdb, 0x94, 0x05, 0x3a, 0xff, 0xfe, 0xfc, + 0x81, 0xd8, 0x40, 0x5f, 0xa5, 0x76, 0xf2, 0x66, 0x3d, 0xe3, 0x0a, 0x93, + 0x67, 0x07, 0x09, 0xf2, 0xf2, 0x70, 0xf3, 0x62, 0x2e, 0xc1, 0xea, 0xf1, + 0x5c, 0x43, 0x40, 0x0a, 0xf2, 0x4e, 0xf1, 0x2f, 0x13, 0x22, 0x54, 0xf0, + 0x99, 0x1b, 0xe6, 0x26, 0x37, 0x43, 0xac, 0xd6, 0x63, 0x4d, 0x14, 0xc8, + 0xd4, 0xf6, 0x30, 0x9f, 0xdc, 0x72, 0x9d, 0xb4, 0x6d, 0xa0, 0x77, 0x2b, + 0xfe, 0x82, 0x69, 0xeb, 0xd8, 0x86, 0xc2, 0x44, 0xc7, 0xa4, 0xd7, 0xa5, + 0x8b, 0x41, 0x53, 0x28, 0xfa, 0x4a, 0xf3, 0x88, 0x25, 0xdf, 0x75, 0x43, + 0x29, 0x2e, 0xc1, 0xe6, 0x4e, 0x6f, 0xb1, 0x2b, 0xda, 0x00, 0x92, 0x63, + 0xf7, 0xc1, 0x5f, 0x5e, 0x1a, 0x3a, 0x53, 0xb5, 0x87, 0x91, 0x0e, 0xf0, + 0x9e, 0xd5, 0x09, 0x5b, 0x07, 0x46, 0x01, 0xb1, 0x25, 0x36, 0xd0, 0x00, + 0xc1, 0xd2, 0x99, 0x2b, 0x22, 0x6e, 0x48, 0xa0, 0x12, 0xa8, 0x35, 0x3c, + 0xd5, 0xda, 0x40, 0xc6, 0x54, 0x53, 0xc5, 0xd5, 0x5b, 0x5c, 0x54, 0x74, + 0x00, 0x95, 0xcc, 0xfc, 0xf7, 0xde, 0x61, 0x9d, 0x38, 0x4c, 0x9c, 0x05, + 0x55, 0x94, 0x15, 0x1e, 0xf2, 0xd2, 0x4e, 0xbe, 0xd1, 0xef, 0x38, 0x3e, + 0x84, 0xcb, 0x3b, 0x30, 0x29, 0x25, 0x54, 0xd5, 0xe2, 0xd4, 0xf1, 0x79, + 0x2a, 0xe1, 0x47, 0xff, 0xfa, 0x1c, 0x8d, 0x11, 0x3d, 0x16, 0xd5, 0xcc, + 0x82, 0x89, 0xb7, 0x50, 0x5f, 0xc2, 0x7f, 0xc8, 0xab, 0xa9, 0xa4, 0xdc, + 0x0c, 0x18, 0x36, 0xf2, 0x30, 0x58, 0x82, 0x5d, 0xbc, 0xa1, 0x49, 0x43, + 0x9e, 0x26, 0x72, 0x24, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x10, 0x63, 0x7a, 0xda, 0x0a, 0x64, 0x03, 0x3a, 0xe2, 0x30, 0x20, 0x7e, + 0x56, 0x94, 0x81, 0x0b, 0x8e, 0x8b, 0x27, 0x38, 0xa2, 0x92, 0x43, 0x82, + 0xaf, 0x40, 0x3c, 0x94, 0xf9, 0xd6, 0x4a, 0x1e, 0xfa, 0xfa, 0x62, 0x5c, + 0xd6, 0xf3, 0x22, 0xbe, 0x37, 0xfb, 0x8d, 0xd8, 0x9d, 0xe2, 0x2c, 0x11, + 0x88, 0x01, 0x71, 0x7f, 0x8a, 0x59, 0xd5, 0x62, 0x6f, 0x70, 0x52, 0x62, + 0x29, 0x44, 0x05, 0x1a, 0x4c, 0x60, 0xb4, 0xde, 0x91, 0x47, 0xd4, 0x80, + 0x2e, 0xe8, 0xdb, 0xbc, 0x00, 0xf6, 0x72, 0x84, 0x23, 0xeb, 0x3b, 0xfe, + 0xa7, 0x63, 0xcd, 0xe5, 0x6e, 0xb4, 0x0e, 0x74, 0xcb, 0xc3, 0xec, 0x03, + 0x41, 0xec, 0x1e, 0x15, 0x18, 0x49, 0x12, 0xcb, 0x77, 0x1b, 0xf7, 0xd6, + 0xc7, 0x03, 0x06, 0x37, 0x7e, 0x35, 0x58, 0x33, 0xb1, 0xb2, 0x51, 0x53, + 0x8f, 0xa2, 0xc6, 0xe9, 0x71, 0xe3, 0x21, 0x2b, 0x3d, 0xf5, 0x58, 0x49, + 0x56, 0x6c, 0xa4, 0x9a, 0x7a, 0xdd, 0xf1, 0x2e, 0x5c, 0x83, 0x12, 0xee, + 0x1e, 0xfa, 0xf7, 0xa5, 0x1a, 0xfd, 0xe4, 0x39, 0xa1, 0x44, 0xf4, 0x6a, + 0x77, 0xd8, 0x99, 0x02, 0x38, 0xad, 0x0f, 0xdf, 0xba, 0xca, 0xe5, 0xf0, + 0x55, 0x3a, 0xbe, 0xc0, 0xf9, 0x30, 0x7f, 0x9d, 0xa2, 0x97, 0x7c, 0x74, + 0x1d, 0x91, 0x2a, 0x16, 0x7b, 0x0d, 0x19, 0x8b, 0x29, 0xd1, 0x65, 0x02, + 0x08, 0x4e, 0x31, 0xe3, 0xb9, 0xf5, 0x7a, 0x57, 0x59, 0x9b, 0x6d, 0x38, + 0xa8, 0x40, 0x39, 0x8e, 0x32, 0x2a, 0xcc, 0x4a, 0x97, 0xf0, 0x3a, 0x3b, + 0xb0, 0xf6, 0x81, 0x7f, 0x3e, 0xfb, 0x3f, 0x00, 0xc7, 0x46, 0xd5, 0xf6, + 0x30, 0x45, 0x91, 0x84, 0x87, 0xae, 0xcb, 0x47, 0xf2, 0x0f, 0x14, 0x30, + 0x58, 0x84, 0x36, 0x76, 0x1a, 0xf1, 0x53, 0xde, 0x5f, 0xbe, 0x6e, 0x53, + 0xc7, 0x46, 0x3b, 0x06, 0xa7, 0x3c, 0xed, 0x44, 0x2a, 0x82, 0xe5, 0xfc, + 0x71, 0x52, 0xeb, 0xe7, 0x6c, 0xcd, 0x60, 0x39, 0x78, 0x59, 0x39, 0xae, + 0x8b, 0xa6, 0x38, 0x52, 0x42, 0xcb, 0x89, 0xf8, 0xc3, 0x83, 0x75, 0x07, + 0x21, 0x0b, 0xf3, 0x74, 0x66, 0xf7, 0xf8, 0x6f, 0xbf, 0x11, 0xe3, 0x01, + 0xd5, 0xb3, 0xd8, 0xda, 0xea, 0x35, 0x8e, 0x97, 0x5e, 0xe5, 0x5b, 0x24, + 0x34, 0x36, 0x92, 0x34, 0xaa, 0x66, 0x79, 0x28, 0x95, 0x61, 0x82, 0xc5, + 0x29, 0x02, 0x82, 0x7a, 0xc9, 0xbe, 0xd1, 0x94, 0x3a, 0x75, 0xe4, 0xdf, + 0x37, 0x23, 0xa5, 0xf7, 0x4c, 0x03, 0x17, 0xdc, 0x75, 0x39, 0x18, 0x86, + 0x49, 0xc3, 0xd8, 0x15, 0x67, 0xc2, 0x42, 0x61, 0x1b, 0x51, 0x9e, 0xbb, + 0xe5, 0xe8, 0x4a, 0x26, 0xdb, 0x26, 0xaa, 0x03, 0xb4, 0x32, 0x97, 0x25, + 0xff, 0xd2, 0x29, 0x54, 0x1d, 0xc9, 0xa5, 0x85, 0x78, 0x40, 0x13, 0x0b, + 0x5c, 0xd6, 0x44, 0x57, 0x6e, 0x25, 0x66, 0x9c, 0x69, 0x16, 0x89, 0x84, + 0x05, 0x47, 0xc3, 0x0a, 0xea, 0x5b, 0x83, 0x76, 0x4d, 0x61, 0xcf, 0x88, + 0xce, 0x63, 0x98, 0x8f, 0x5c, 0x6d, 0x52, 0x18, 0x98, 0x76, 0xb7, 0x09, + 0x33, 0x9f, 0xa7, 0xbe, 0x9f, 0x60, 0x6f, 0x21, 0x61, 0x13, 0x86, 0xbe, + 0xac, 0x95, 0x46, 0x9e, 0x64, 0xcb, 0xe6, 0xff, 0xc7, 0x82, 0x4d, 0x60, + 0x40, 0x1b, 0xc8, 0x2b, 0x6e, 0xe8, 0xb1, 0x81, 0xc0, 0xaa, 0xca, 0x55, + 0xa1, 0xff, 0xfc, 0xdf, 0x0e, 0xc6, 0x0f, 0x4b, 0x65, 0x2a, 0x9f, 0xb6, + 0x9c, 0x10, 0x6d, 0x0a, 0xb5, 0x29, 0x5c, 0x29, 0x8c, 0x6e, 0xf0, 0x04, + 0x7c, 0x7e, 0x0e, 0xd2, 0x8a, 0x70, 0xcd, 0x9e, 0x4a, 0x8e, 0x0c, 0x78, + 0x61, 0x73, 0xa5, 0x46, 0x90, 0xe5, 0xb8, 0xe3, 0xc1, 0xa9, 0x05, 0x32, + 0x9a, 0x82, 0x2a, 0x98, 0xc0, 0x23, 0x1c, 0x08, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x31, 0x5f, 0xd0, 0xbb, 0x8f, 0xa9, 0x33, 0x12, + 0xf8, 0x57, 0x74, 0x58, 0xfd, 0x36, 0x21, 0xa4, 0x60, 0x4a, 0x00, 0x83, + 0xf7, 0xa9, 0xd6, 0xe9, 0x5b, 0xa8, 0x6a, 0xdc, 0xbd, 0x12, 0x5e, 0x2e, + 0x6c, 0x53, 0xe4, 0x20, 0x67, 0x75, 0xc0, 0xf0, 0xb8, 0xd5, 0xe1, 0x28, + 0xf6, 0x91, 0x7e, 0x4c, 0xb2, 0xc8, 0xc9, 0x8d, 0x46, 0x27, 0x5b, 0xea, + 0x52, 0x6e, 0xae, 0x51, 0x7f, 0x11, 0x28, 0x1b, 0x26, 0x1d, 0xf4, 0x09, + 0x79, 0x9e, 0x75, 0x08, 0x95, 0xf2, 0x09, 0x9f, 0x79, 0x4f, 0x5a, 0xdc, + 0xad, 0xc2, 0x61, 0x95, 0x85, 0xbe, 0x83, 0x63, 0x51, 0xd6, 0xc0, 0xfe, + 0xf1, 0x03, 0xd6, 0x2d, 0x85, 0x3a, 0x10, 0x0c, 0x88, 0x74, 0xa2, 0x0a, + 0x03, 0x5c, 0xd2, 0xd7, 0x21, 0x5c, 0x35, 0x24, 0x17, 0x69, 0xcf, 0xb8, + 0x3e, 0xb4, 0x7b, 0x61, 0x0d, 0x69, 0x67, 0xf2, 0xda, 0x44, 0x1f, 0x2d, + 0x09, 0x7d, 0x44, 0x42, 0x7b, 0x46, 0xe9, 0x8e, 0x41, 0xbd, 0xab, 0xea, + 0x9e, 0x2d, 0x6f, 0x94, 0x1c, 0x1d, 0xc2, 0x0d, 0x52, 0x25, 0x2d, 0x3a, + 0x2c, 0xf7, 0x41, 0x79, 0x0b, 0x16, 0xe1, 0x09, 0x8f, 0x36, 0xe6, 0x54, + 0xbf, 0x29, 0xcc, 0xa4, 0x75, 0xbf, 0xd0, 0x18, 0x66, 0xfc, 0xd3, 0xac, + 0x2f, 0x33, 0x09, 0x44, 0x01, 0x78, 0x39, 0x88, 0x20, 0x97, 0x2d, 0x15, + 0xa5, 0x0a, 0xad, 0x0a, 0x72, 0x98, 0xc4, 0x32, 0x6a, 0x22, 0x97, 0x2e, + 0x4b, 0xfd, 0x34, 0x35, 0xff, 0xb1, 0xd4, 0x0d, 0xfd, 0x11, 0xb5, 0x9f, + 0x41, 0x9e, 0xc1, 0x15, 0x87, 0x91, 0xa2, 0xac, 0x5a, 0xb7, 0x63, 0x2b, + 0x4c, 0x2f, 0x7d, 0x96, 0xbf, 0xfa, 0xa2, 0xe1, 0x91, 0xba, 0xd6, 0xb5, + 0x90, 0xd8, 0xd9, 0xce, 0x48, 0x1c, 0xdd, 0xc2, 0xc8, 0x03, 0x6d, 0xc1, + 0x37, 0xd5, 0x3b, 0x0b, 0x20, 0xb5, 0xc7, 0x10, 0x0d, 0xc0, 0xef, 0x83, + 0x58, 0x6b, 0x58, 0xb1, 0xee, 0x35, 0x61, 0x87, 0x08, 0xb1, 0x99, 0x95, + 0x2b, 0x24, 0xf3, 0x0e, 0x9e, 0xb8, 0xc3, 0xd4, 0x34, 0x8d, 0xfb, 0x84, + 0x72, 0x04, 0x74, 0x17, 0x4f, 0x2e, 0xc5, 0xc6, 0xc6, 0x55, 0x7d, 0x32, + 0x3f, 0xba, 0x14, 0x39, 0x8c, 0xdb, 0x25, 0x2a, 0x0a, 0x87, 0x71, 0xb1, + 0x08, 0xab, 0xfa, 0x95, 0x44, 0x44, 0x2c, 0x87, 0x32, 0xbc, 0x15, 0x17, + 0x6f, 0x90, 0xab, 0x38, 0xcb, 0x93, 0x5c, 0xbd, 0x9b, 0xe7, 0xe6, 0x9c, + 0x6a, 0x59, 0x84, 0xe6, 0x75, 0x1f, 0xb0, 0x07, 0x0b, 0x4b, 0x7c, 0xb5, + 0xd9, 0x1f, 0x50, 0xbd, 0xb4, 0x2f, 0xd3, 0x05, 0x74, 0x17, 0xe2, 0x4a, + 0x2c, 0x67, 0x02, 0xa2, 0x49, 0x38, 0x7c, 0xec, 0x05, 0xcf, 0x01, 0x48, + 0xc7, 0x53, 0x18, 0x4a, 0x76, 0x43, 0x05, 0x72, 0x39, 0x73, 0xec, 0xe8, + 0x3c, 0x31, 0x1d, 0x12, 0xc9, 0x23, 0xe7, 0xe3, 0x87, 0x6b, 0x87, 0xf2, + 0x8a, 0x65, 0x88, 0xf6, 0x09, 0xcf, 0xea, 0xa4, 0x70, 0x91, 0xa5, 0xb1, + 0x67, 0xe7, 0xe0, 0xbc, 0x1b, 0x08, 0x19, 0x59, 0x45, 0xd2, 0x62, 0x2e, + 0x63, 0x41, 0x85, 0x92, 0x3c, 0x43, 0x8b, 0x33, 0x54, 0x40, 0xb0, 0x62, + 0x9d, 0xc4, 0x69, 0x61, 0xac, 0x65, 0xcc, 0x33, 0x52, 0xfa, 0x26, 0x6f, + 0x3f, 0xea, 0xff, 0xad, 0x99, 0xe5, 0x03, 0x03, 0x15, 0xf1, 0xfe, 0x1c, + 0xf5, 0xa0, 0x6e, 0xed, 0x28, 0x06, 0xe5, 0x0a, 0xe5, 0x19, 0x8f, 0xb4, + 0x86, 0xa6, 0x62, 0xb7, 0x8d, 0x72, 0xbe, 0x19, 0x06, 0xe5, 0xba, 0xd0, + 0xbe, 0xb5, 0x59, 0x18, 0x73, 0x09, 0x27, 0x51, 0xa4, 0x25, 0xfc, 0xae, + 0x3d, 0x66, 0x26, 0x17, 0xfc, 0x3f, 0x43, 0xaf, 0xb3, 0x8b, 0xf4, 0x3b, + 0x7e, 0xcb, 0x7e, 0xa2, 0x5d, 0xb7, 0xb9, 0x15, 0xea, 0x63, 0x50, 0x2c, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xde, 0x14, 0x97, 0x4a, + 0xb8, 0x66, 0x38, 0x24, 0xb5, 0xd5, 0x35, 0x08, 0xba, 0x4c, 0x90, 0x9f, + 0x3c, 0xac, 0x85, 0xff, 0x9b, 0xc9, 0x15, 0x8b, 0xc8, 0x13, 0xda, 0xa2, + 0x85, 0x49, 0xcb, 0x06, 0xbe, 0xb0, 0xc5, 0x6e, 0xee, 0xaa, 0xc5, 0xed, + 0xdc, 0xf7, 0xc0, 0x25, 0x0a, 0xfa, 0x22, 0xeb, 0xff, 0xed, 0x14, 0xd9, + 0xad, 0x72, 0x74, 0xd4, 0xbe, 0x0c, 0x12, 0x4a, 0xdc, 0xe7, 0x01, 0x09, + 0x28, 0x58, 0xe7, 0xfb, 0xa4, 0x8a, 0x43, 0x1d, 0x7c, 0x11, 0x7c, 0x53, + 0x83, 0xe0, 0x3d, 0x2d, 0x0a, 0x12, 0xfe, 0x20, 0xaa, 0x64, 0x9e, 0x44, + 0xdf, 0x1f, 0x4d, 0xe5, 0x75, 0x28, 0xda, 0x07, 0xec, 0x73, 0xc5, 0xe6, + 0x96, 0xc6, 0xf9, 0xc9, 0x5f, 0xbe, 0x5e, 0xe2, 0x12, 0x79, 0x60, 0x04, + 0x51, 0x1f, 0xcd, 0x4f, 0x87, 0x4e, 0x39, 0x63, 0x05, 0x86, 0xdd, 0x67, + 0xf7, 0x06, 0x95, 0x27, 0x39, 0x6e, 0x9b, 0xfe, 0xc0, 0xd4, 0x01, 0x37, + 0x3f, 0x96, 0x6f, 0xe5, 0x8e, 0x99, 0xbf, 0x49, 0xac, 0xbf, 0x89, 0x5f, + 0x56, 0x99, 0xd2, 0xc9, 0x86, 0x83, 0x73, 0xdc, 0xba, 0x99, 0x19, 0x01, + 0xf6, 0xa7, 0x82, 0xc7, 0x19, 0x2f, 0x63, 0xf1, 0x63, 0xa9, 0x1d, 0x05, + 0x99, 0xa1, 0x63, 0x55, 0x99, 0x15, 0x0d, 0x66, 0x73, 0x35, 0xba, 0xc2, + 0x58, 0xdc, 0xd3, 0x02, 0x8f, 0x73, 0xc3, 0x04, 0xae, 0x88, 0xf2, 0x61, + 0x0b, 0x20, 0x91, 0xb2, 0xb3, 0x13, 0x91, 0x00, 0x6b, 0x12, 0x2f, 0x10, + 0xe5, 0xb8, 0x78, 0x8c, 0x23, 0xdd, 0xfd, 0x5a, 0xf3, 0xce, 0x8f, 0x0b, + 0x3f, 0xf4, 0xc5, 0x22, 0x04, 0x6d, 0x3f, 0xcf, 0x66, 0x2c, 0x27, 0x71, + 0x84, 0x48, 0x99, 0x98, 0x33, 0x00, 0x78, 0xc5, 0xf0, 0xb3, 0x7f, 0xea, + 0x3a, 0x7b, 0xb1, 0x9a, 0x3c, 0x1f, 0x7e, 0xc9, 0x9e, 0x9a, 0xcc, 0x22, + 0xf2, 0x5b, 0xcd, 0x79, 0x20, 0xf9, 0x2c, 0xf5, 0x8c, 0x95, 0x47, 0x53, + 0x7e, 0x9a, 0x87, 0xf4, 0x1e, 0x5f, 0xc9, 0x22, 0x32, 0xcc, 0xb5, 0xc8, + 0x4f, 0xbf, 0xb0, 0x63, 0x1b, 0x6e, 0x9b, 0x01, 0x08, 0x1e, 0x08, 0x40, + 0xf9, 0x8f, 0xb4, 0xc4, 0xa2, 0x88, 0xdd, 0xc9, 0x69, 0x4e, 0xeb, 0xbe, + 0xe6, 0xfd, 0x26, 0x37, 0xe7, 0x62, 0xe4, 0x41, 0xd5, 0x97, 0x1c, 0x70, + 0x4b, 0xd7, 0x16, 0x1d, 0x67, 0x72, 0x0b, 0x8a, 0x9a, 0xd4, 0xd9, 0xb3, + 0xd0, 0x3f, 0xd8, 0xd2, 0xe9, 0x0e, 0xf9, 0xe9, 0x43, 0x7c, 0x46, 0x9f, + 0x6f, 0x1f, 0x70, 0x59, 0x0f, 0x8e, 0xbb, 0x94, 0x1a, 0x01, 0xbd, 0x29, + 0x0b, 0xb6, 0x2b, 0x44, 0xfe, 0xac, 0x93, 0x1f, 0x02, 0x9c, 0x12, 0x97, + 0xc7, 0x6d, 0x97, 0xce, 0x98, 0x9e, 0x9d, 0x4a, 0x76, 0x7e, 0x98, 0x23, + 0x2f, 0xc1, 0xc6, 0x83, 0x9b, 0x2b, 0x13, 0x0c, 0x6b, 0x15, 0x0a, 0x33, + 0xed, 0x3f, 0x41, 0x26, 0x99, 0x96, 0x77, 0xa5, 0x80, 0x2d, 0xb7, 0x1a, + 0x04, 0x61, 0xee, 0xc6, 0x14, 0x58, 0xcd, 0x37, 0xe0, 0x6c, 0xd6, 0xa3, + 0xab, 0xd6, 0xe6, 0x24, 0xfb, 0x08, 0x0b, 0x02, 0x58, 0x53, 0xe5, 0xd0, + 0x24, 0x6c, 0xec, 0x1c, 0x5e, 0xd6, 0xbb, 0x3e, 0x34, 0x91, 0x62, 0xf7, + 0xca, 0x30, 0x25, 0x79, 0x3a, 0x6b, 0xa1, 0x88, 0x47, 0x58, 0x8b, 0x22, + 0xf5, 0xb0, 0x82, 0xc7, 0x93, 0xfe, 0x5d, 0x91, 0x16, 0xe9, 0x84, 0x1a, + 0x3f, 0xb8, 0xf2, 0x13, 0x80, 0x9b, 0x26, 0xfe, 0x89, 0x62, 0x91, 0x9d, + 0x41, 0x89, 0x5f, 0xe7, 0xa2, 0x60, 0xc8, 0x28, 0x6e, 0xc8, 0x4b, 0x19, + 0x3e, 0xa6, 0x89, 0x7c, 0xe9, 0xa2, 0x6c, 0x85, 0xd2, 0xda, 0x9d, 0xc3, + 0xe5, 0xcf, 0x27, 0xf1, 0x32, 0x22, 0xe3, 0xc1, 0x77, 0xc3, 0xc6, 0x08, + 0x58, 0xa4, 0xd6, 0x24, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0xf5, 0x76, 0x73, 0x5b, 0xcf, 0x89, 0xc7, 0x76, 0xfb, 0x47, 0x9c, 0xcf, + 0x6b, 0xc8, 0x32, 0x27, 0x3f, 0x63, 0x09, 0x71, 0x6d, 0x50, 0x9a, 0x23, + 0x1a, 0x16, 0x0f, 0xf3, 0x17, 0xfc, 0xb3, 0x0d, 0x68, 0x1b, 0x5a, 0x05, + 0xd0, 0x20, 0xbb, 0x29, 0x19, 0xa2, 0x76, 0x5b, 0xe0, 0x23, 0x0c, 0x51, + 0x3e, 0xa1, 0x59, 0xee, 0x0f, 0xe0, 0x1b, 0x3a, 0xee, 0xcd, 0x8b, 0x83, + 0x08, 0xce, 0xea, 0x10, 0xae, 0x72, 0xc9, 0x10, 0xd0, 0x41, 0xf9, 0x55, + 0x29, 0x8f, 0x56, 0x66, 0xde, 0xdd, 0xfb, 0x86, 0xfe, 0xb7, 0x54, 0xbe, + 0xcc, 0x73, 0x91, 0x4c, 0xf0, 0x31, 0xd0, 0x92, 0x2f, 0xde, 0x2d, 0x2d, + 0x64, 0x4b, 0x18, 0x6d, 0xdb, 0xe8, 0xb0, 0x61, 0x3f, 0x4d, 0xf3, 0x52, + 0x7e, 0x69, 0x16, 0x77, 0x6e, 0xe3, 0x09, 0x79, 0xb3, 0x0f, 0x27, 0x2b, + 0xf7, 0xa5, 0x68, 0xe5, 0xb5, 0xdb, 0xf3, 0x1b, 0x63, 0x9a, 0xb4, 0xd5, + 0xb2, 0xbc, 0xf1, 0xbe, 0xda, 0x5f, 0x16, 0xf2, 0xee, 0x88, 0x85, 0x1f, + 0x33, 0x76, 0xc1, 0x49, 0x1d, 0x64, 0x2d, 0xb5, 0xf8, 0x5f, 0xb6, 0x7b, + 0xf0, 0x73, 0x02, 0x2c, 0x00, 0x89, 0x2e, 0xc8, 0x7a, 0x6b, 0x61, 0x7d, + 0x35, 0x61, 0x24, 0x5d, 0x60, 0x4f, 0x0c, 0x00, 0xb5, 0xbb, 0xa2, 0x26, + 0x6c, 0xb7, 0x14, 0xf0, 0x93, 0x0f, 0xc6, 0x63, 0x55, 0xfd, 0xa9, 0x00, + 0x29, 0xff, 0xab, 0x71, 0x87, 0xfd, 0x32, 0x0e, 0xc0, 0x1d, 0xd0, 0x1e, + 0xf9, 0x58, 0xe8, 0x1b, 0x9d, 0x44, 0xcc, 0x55, 0xc0, 0x85, 0x8b, 0x5c, + 0xbc, 0x83, 0x63, 0xc2, 0xf8, 0x3f, 0x05, 0x07, 0x7f, 0x1e, 0x96, 0xd7, + 0x49, 0xbc, 0xe4, 0xf0, 0x6d, 0xdc, 0xd2, 0xf9, 0x2c, 0x6d, 0x1c, 0x07, + 0xf4, 0x49, 0xe7, 0x88, 0x45, 0xd2, 0xb4, 0xca, 0x79, 0xe1, 0x5f, 0x75, + 0xae, 0xf0, 0xd6, 0x03, 0x03, 0x78, 0x1b, 0x2a, 0x4c, 0x90, 0x7b, 0x60, + 0xbf, 0xdc, 0x9d, 0x3c, 0xba, 0x0d, 0xf3, 0x3e, 0x63, 0x30, 0xe4, 0x4e, + 0x3d, 0x9c, 0xff, 0x38, 0xc4, 0x95, 0x97, 0x44, 0x0a, 0x27, 0x24, 0x0e, + 0xde, 0x93, 0x49, 0x3a, 0x77, 0x63, 0x0d, 0x69, 0x57, 0x7e, 0x16, 0xc2, + 0xd6, 0x8d, 0xab, 0xff, 0x56, 0x9d, 0xfe, 0x69, 0xb3, 0xb9, 0x8d, 0x6e, + 0xb7, 0x6b, 0x8c, 0x3a, 0x13, 0xd0, 0x0f, 0x2e, 0xf1, 0x15, 0x51, 0x7d, + 0x7e, 0xe0, 0x50, 0x2e, 0xd3, 0x8f, 0x26, 0x58, 0x9d, 0x07, 0x24, 0x4b, + 0xbf, 0x54, 0x90, 0x6a, 0x84, 0x8d, 0xdf, 0xb5, 0x0e, 0xb7, 0xb3, 0x08, + 0x37, 0x2d, 0x3a, 0x04, 0x4a, 0xfd, 0x4f, 0xdf, 0x0c, 0x1b, 0x9d, 0x62, + 0x50, 0x8c, 0xc8, 0x02, 0x50, 0x49, 0xca, 0x2c, 0xa7, 0x8d, 0x21, 0x39, + 0x53, 0x34, 0x41, 0x50, 0x73, 0xf8, 0xf7, 0xa1, 0x0a, 0x40, 0x7e, 0x1a, + 0x36, 0x10, 0x7e, 0xf8, 0xd1, 0x7b, 0x1c, 0x95, 0x0b, 0xfc, 0xb9, 0xc6, + 0x96, 0xae, 0x7d, 0xcd, 0x60, 0xeb, 0x60, 0x52, 0xfe, 0x4b, 0xd0, 0xe7, + 0x26, 0x55, 0xa2, 0x89, 0x36, 0xe6, 0x60, 0x29, 0x9f, 0x12, 0xb2, 0x58, + 0xba, 0x79, 0x39, 0xe7, 0x3f, 0x8c, 0xb1, 0x5a, 0xd7, 0x65, 0xb1, 0x9a, + 0x7a, 0x68, 0x69, 0x1c, 0x7c, 0x68, 0x6e, 0x4d, 0x3f, 0x42, 0x7f, 0xe4, + 0x3c, 0xa6, 0x03, 0x1e, 0x1a, 0x15, 0x02, 0x2c, 0x23, 0x21, 0xb2, 0x91, + 0x47, 0xd1, 0x6a, 0x13, 0xe3, 0x56, 0x01, 0x7c, 0xc3, 0xd5, 0x80, 0x51, + 0x60, 0xce, 0x10, 0xa6, 0xb8, 0x8d, 0x75, 0xef, 0x60, 0x21, 0xe7, 0x20, + 0x16, 0xb6, 0x84, 0x64, 0x51, 0x88, 0xf7, 0x40, 0xbf, 0xd6, 0x0a, 0xc9, + 0x49, 0xf4, 0x90, 0xe0, 0x3e, 0xa2, 0x21, 0x10, 0x09, 0x8d, 0x53, 0x96, + 0xb0, 0xb5, 0xce, 0xb5, 0x2e, 0x2c, 0xfe, 0x10, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x5a, 0x25, 0xd7, 0x64, 0xe8, 0x4b, 0xc0, 0x2a, + 0x41, 0x83, 0x30, 0xc2, 0x20, 0xc4, 0x74, 0xa1, 0x7d, 0x89, 0x8b, 0x55, + 0x0a, 0x4d, 0xb7, 0x6f, 0x0a, 0xa0, 0x8f, 0xa7, 0x21, 0x3b, 0x7f, 0x0e, + 0x85, 0x50, 0x1e, 0xba, 0x44, 0x43, 0x1d, 0x65, 0x4f, 0xd3, 0xec, 0xb8, + 0x28, 0xf7, 0xf5, 0x18, 0xde, 0x48, 0x10, 0x04, 0x0d, 0xdd, 0x37, 0xb0, + 0x48, 0xe5, 0xd2, 0xe9, 0x22, 0x50, 0xe2, 0x0f, 0x4a, 0x41, 0x4b, 0x40, + 0xbe, 0xb2, 0x77, 0x3e, 0xa1, 0x91, 0x75, 0xf7, 0x19, 0xa2, 0xe6, 0x29, + 0x97, 0x11, 0xdf, 0x27, 0xc8, 0x25, 0x4f, 0xff, 0xd8, 0x22, 0xe4, 0xee, + 0x13, 0xc8, 0x19, 0x04, 0x78, 0x87, 0xee, 0xf4, 0xab, 0xab, 0xaa, 0x2c, + 0xeb, 0xc4, 0xdf, 0xb3, 0x3f, 0x69, 0xcf, 0xe0, 0x5b, 0xfa, 0x1c, 0x97, + 0x8e, 0xb8, 0x34, 0xea, 0x1e, 0xcf, 0x17, 0x17, 0xbb, 0xa9, 0x85, 0x19, + 0xd4, 0xce, 0x4d, 0xec, 0xd6, 0xcb, 0x26, 0xee, 0xfc, 0xaa, 0xb5, 0x13, + 0xf5, 0xb6, 0x86, 0x22, 0x98, 0xad, 0x13, 0xfd, 0xf3, 0xa6, 0x91, 0x2b, + 0x17, 0x58, 0x13, 0x3d, 0x38, 0x03, 0xa3, 0x14, 0x9a, 0x8c, 0xcc, 0xcd, + 0x5c, 0x23, 0xed, 0xbc, 0x43, 0xa9, 0xeb, 0x79, 0x4c, 0xf0, 0x12, 0x85, + 0x46, 0xa0, 0x16, 0x6e, 0x59, 0xad, 0xbe, 0x00, 0xe3, 0xca, 0x24, 0x60, + 0x57, 0x46, 0x6d, 0x26, 0x4f, 0x61, 0x0d, 0x42, 0x8a, 0xb1, 0x3b, 0xd4, + 0xe0, 0x7f, 0xb8, 0xd1, 0x93, 0xb4, 0x8d, 0x4b, 0x4b, 0x19, 0x4f, 0x87, + 0x54, 0x52, 0x94, 0x99, 0x44, 0x82, 0xee, 0xda, 0x30, 0x0a, 0x54, 0x0a, + 0xc0, 0x8c, 0x75, 0xe5, 0x95, 0x11, 0xe2, 0x4c, 0x8e, 0xac, 0x89, 0x0b, + 0x99, 0x56, 0xa7, 0x3e, 0xf4, 0x5e, 0x68, 0x36, 0xbd, 0xa4, 0xf7, 0x0f, + 0x77, 0xce, 0x05, 0x7e, 0x93, 0x8f, 0xff, 0x18, 0x93, 0x2a, 0x53, 0x8f, + 0x63, 0x6e, 0xcf, 0x06, 0x44, 0x24, 0xe9, 0x1f, 0xe0, 0x8d, 0xa9, 0x6a, + 0x5c, 0x80, 0x07, 0x68, 0x0d, 0x69, 0x79, 0xa4, 0xa6, 0xdc, 0xeb, 0x5f, + 0xe9, 0xc0, 0x7c, 0x18, 0xed, 0xa5, 0xce, 0xcd, 0xf4, 0x6b, 0xad, 0x9e, + 0xce, 0x36, 0xe4, 0x0f, 0xfa, 0x5b, 0xa3, 0x92, 0xbd, 0x0a, 0xc3, 0x06, + 0xe0, 0x5f, 0x3c, 0xdf, 0xad, 0x94, 0xd2, 0x74, 0xbd, 0x88, 0xe9, 0x01, + 0xde, 0x06, 0xdb, 0x88, 0x22, 0x8e, 0x39, 0x38, 0x68, 0x53, 0x02, 0x8b, + 0xa3, 0x12, 0x5f, 0x0e, 0xee, 0x23, 0x3a, 0x81, 0x5f, 0x8b, 0x35, 0x74, + 0xa0, 0x31, 0x2a, 0xe6, 0xac, 0xa3, 0xd6, 0x24, 0xd3, 0x65, 0x34, 0xc6, + 0x1c, 0x91, 0x8b, 0xd1, 0xaf, 0x8e, 0x0b, 0x71, 0x34, 0xc4, 0x05, 0x32, + 0x0d, 0x1e, 0x54, 0xb3, 0x06, 0xb0, 0x93, 0xe5, 0x8b, 0x82, 0x63, 0x6b, + 0x41, 0x41, 0x6f, 0x23, 0x8b, 0xe3, 0xa6, 0xfc, 0x85, 0xb0, 0x01, 0x24, + 0xe2, 0x3f, 0x20, 0xe3, 0xa9, 0xc2, 0xd5, 0x27, 0xf8, 0x2e, 0xfd, 0x80, + 0xd5, 0xa3, 0x3c, 0xea, 0x40, 0x02, 0x8d, 0x39, 0x92, 0x78, 0x48, 0x11, + 0x42, 0xb7, 0x4b, 0xd2, 0x27, 0xb2, 0xa4, 0x96, 0xd5, 0x57, 0x72, 0x82, + 0x27, 0xcb, 0xaa, 0x84, 0x3c, 0xb7, 0x30, 0xdd, 0xca, 0xdf, 0x1d, 0x56, + 0x5a, 0x3b, 0x82, 0xdf, 0x4d, 0xcf, 0xae, 0x12, 0xb4, 0x5f, 0xe6, 0x66, + 0xd4, 0xdf, 0x42, 0xc6, 0xb3, 0x4e, 0xb9, 0x6b, 0x65, 0x03, 0x70, 0xac, + 0x74, 0xec, 0xd5, 0xb7, 0x01, 0xc3, 0x20, 0xd1, 0x8b, 0x7f, 0x93, 0xf0, + 0x9b, 0xf8, 0xd8, 0x03, 0x4e, 0xd7, 0x9f, 0x96, 0x66, 0xab, 0xb9, 0xc1, + 0xea, 0x20, 0xf0, 0x38, 0x66, 0x99, 0x01, 0x98, 0xd8, 0x20, 0xc0, 0x14, + 0x91, 0x56, 0xa1, 0x6e, 0x16, 0xc7, 0x6d, 0x26, 0x2b, 0xb4, 0x67, 0x15, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xfe, 0xd0, 0xa1, 0xe8, + 0xa6, 0xab, 0xf0, 0x42, 0x5a, 0x2a, 0x3a, 0x04, 0xac, 0x3b, 0x3d, 0x4b, + 0xf0, 0x2e, 0xfb, 0xc3, 0x19, 0xec, 0xcf, 0x7e, 0xd8, 0xd9, 0xa1, 0xb6, + 0xc7, 0xeb, 0x5c, 0x1d, 0xd8, 0x26, 0x4b, 0xb9, 0x43, 0x58, 0xbe, 0x85, + 0x7f, 0x40, 0x08, 0xdb, 0x71, 0x3a, 0x3a, 0x8b, 0xb2, 0xe5, 0x88, 0xc1, + 0x1f, 0xce, 0x53, 0x34, 0x30, 0x82, 0xf1, 0x7f, 0x8e, 0x6b, 0xe6, 0x23, + 0x7e, 0xb0, 0xb4, 0x56, 0xa2, 0x7b, 0x5f, 0xeb, 0x73, 0xcf, 0x1f, 0x22, + 0x99, 0x94, 0x95, 0x7d, 0xf4, 0x80, 0x64, 0x19, 0xe8, 0x3c, 0x7f, 0xde, + 0xbc, 0x43, 0xf7, 0xa6, 0x64, 0x1e, 0x9c, 0x27, 0x1a, 0x72, 0x6e, 0x98, + 0x67, 0x6b, 0x3b, 0xe7, 0xef, 0xd7, 0xc4, 0x38, 0xe6, 0xc5, 0x0e, 0xa1, + 0x61, 0x8e, 0xed, 0xb3, 0x71, 0xcd, 0x9f, 0x09, 0xdf, 0x07, 0x82, 0x78, + 0xbb, 0xa8, 0x19, 0x2a, 0xe6, 0x3f, 0xf5, 0xc9, 0x3a, 0xcf, 0x57, 0x22, + 0x5a, 0x21, 0xe0, 0x1e, 0x72, 0x4c, 0x1f, 0x0d, 0x22, 0x6f, 0x4a, 0x6d, + 0xd8, 0x8d, 0x9f, 0x8a, 0xb1, 0x98, 0x17, 0x73, 0x30, 0xa4, 0xba, 0x2d, + 0x5b, 0xf7, 0x04, 0x0a, 0xef, 0x1c, 0xbc, 0x9f, 0x7d, 0x19, 0xe2, 0x3e, + 0xa6, 0xd6, 0x1b, 0xb7, 0x4a, 0xfe, 0xcd, 0x4a, 0x24, 0x89, 0x0d, 0x12, + 0x30, 0x48, 0xf0, 0x67, 0x26, 0x23, 0x35, 0x23, 0x32, 0x05, 0x92, 0xed, + 0x73, 0xc9, 0xe2, 0x2b, 0x91, 0x62, 0x80, 0xd1, 0x71, 0x0b, 0x20, 0x3e, + 0xfd, 0x1b, 0xb7, 0x81, 0x7e, 0x2d, 0xd0, 0x5f, 0x81, 0xe9, 0xa0, 0x89, + 0x93, 0x32, 0x56, 0x30, 0xc8, 0xf4, 0xc5, 0x68, 0x65, 0xb9, 0xdb, 0x4a, + 0xc8, 0x06, 0xad, 0x7e, 0x9f, 0x0f, 0xca, 0xaf, 0xfb, 0x16, 0x18, 0xb1, + 0x12, 0xd5, 0xdf, 0x22, 0x63, 0xa6, 0xf2, 0xc6, 0x19, 0xf5, 0x7c, 0x1e, + 0x8a, 0xb9, 0x75, 0xc7, 0x6a, 0x52, 0x57, 0x17, 0x27, 0x59, 0x6e, 0x4b, + 0x73, 0x13, 0x70, 0xc4, 0x35, 0xa5, 0x7a, 0xfe, 0x6c, 0x4f, 0xef, 0xed, + 0x65, 0x83, 0x46, 0x09, 0xd0, 0x1a, 0x5b, 0x2b, 0xd4, 0x8c, 0xa1, 0x53, + 0x31, 0x91, 0x08, 0x1e, 0x39, 0x8f, 0xef, 0x9d, 0xa4, 0x37, 0xef, 0xb9, + 0xa1, 0xec, 0x24, 0xcf, 0xc6, 0xaa, 0xe1, 0x73, 0xca, 0xeb, 0xd5, 0x25, + 0x84, 0xb1, 0xf8, 0x0f, 0xaf, 0xda, 0x37, 0x76, 0x60, 0xbf, 0x80, 0x6d, + 0x6d, 0x76, 0x69, 0x2c, 0xf1, 0xe8, 0x0d, 0x79, 0xcb, 0xe5, 0x6b, 0x9e, + 0x7f, 0x96, 0xde, 0x69, 0xb3, 0x7c, 0x7c, 0x39, 0x59, 0x31, 0x08, 0x30, + 0x5d, 0x6c, 0x08, 0x5c, 0x8d, 0x77, 0xd4, 0xa3, 0xc2, 0x10, 0x03, 0x73, + 0x47, 0x29, 0xdb, 0xba, 0x58, 0xc0, 0x11, 0xab, 0x4e, 0x32, 0xa0, 0xd6, + 0x0c, 0x40, 0x33, 0x53, 0xbf, 0x89, 0x71, 0x05, 0x0c, 0xa0, 0x3d, 0x19, + 0x71, 0xac, 0x85, 0x30, 0x50, 0xea, 0x47, 0x4c, 0x48, 0x59, 0xc1, 0x27, + 0xb1, 0x2d, 0x3b, 0x30, 0xff, 0xc0, 0x0f, 0x9c, 0x79, 0x67, 0x55, 0x11, + 0x3c, 0x44, 0xa4, 0x2d, 0x01, 0x38, 0xae, 0x90, 0x63, 0x98, 0x80, 0x60, + 0xeb, 0xa4, 0x27, 0xc0, 0xc9, 0xee, 0x18, 0x63, 0xc8, 0xc9, 0xb9, 0x1c, + 0x0f, 0xd9, 0xe7, 0xb7, 0x46, 0x65, 0xb8, 0xcb, 0x46, 0xf9, 0x4e, 0x0b, + 0x8b, 0x95, 0xc7, 0xa9, 0x26, 0xde, 0xb8, 0xab, 0xea, 0x87, 0x12, 0x2d, + 0xeb, 0x2c, 0xdb, 0xc7, 0xfd, 0x31, 0x0b, 0x67, 0x36, 0x2c, 0x1e, 0x1e, + 0xff, 0x3d, 0x80, 0x57, 0xf3, 0x61, 0x41, 0x1a, 0x3a, 0x49, 0xff, 0x10, + 0xcc, 0xa9, 0x63, 0xb4, 0x18, 0x18, 0x8b, 0xe0, 0x89, 0x21, 0x82, 0xfe, + 0xaf, 0x12, 0x59, 0x75, 0x2c, 0x14, 0x0b, 0x1e, 0xd9, 0xff, 0x1e, 0x92, + 0x26, 0x81, 0x66, 0x1a, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0xb6, 0x65, 0xc8, 0x20, 0xde, 0x26, 0x57, 0xee, 0x95, 0x89, 0x20, 0xed, + 0xe6, 0xfd, 0x84, 0x65, 0xab, 0x3f, 0xea, 0x3d, 0x22, 0x5b, 0xa3, 0x99, + 0x3b, 0x35, 0x5e, 0xc3, 0x72, 0xce, 0x6a, 0x1b, 0x11, 0xbc, 0xf3, 0xd3, + 0x9c, 0x08, 0x29, 0x21, 0xe7, 0x05, 0x7b, 0x05, 0xf3, 0x19, 0x61, 0x5a, + 0xb3, 0xa4, 0x4c, 0x60, 0x2d, 0x2c, 0x46, 0x4b, 0x7d, 0xbb, 0x31, 0x5b, + 0x71, 0x55, 0xfe, 0x0a, 0x16, 0x73, 0x24, 0x82, 0xcd, 0xec, 0x15, 0x50, + 0xfd, 0x80, 0x2f, 0x84, 0xee, 0x60, 0x40, 0x3b, 0x82, 0x2f, 0x38, 0xbd, + 0xe1, 0x91, 0x70, 0x53, 0x5f, 0x27, 0x47, 0xed, 0xfa, 0xe3, 0x61, 0x20, + 0x9b, 0xff, 0xf4, 0xd5, 0x5b, 0x62, 0x6d, 0xab, 0x1d, 0x8d, 0xa4, 0x18, + 0x14, 0x0d, 0x98, 0xdb, 0xec, 0xab, 0x00, 0xc5, 0x32, 0xe1, 0xa1, 0xd2, + 0x5e, 0x43, 0x01, 0x8d, 0xcf, 0xf6, 0xfb, 0x06, 0x16, 0xb9, 0xf7, 0xba, + 0xbb, 0x76, 0x2d, 0x28, 0xb3, 0x12, 0x64, 0xb0, 0xac, 0x2a, 0xfb, 0xf6, + 0xc8, 0x12, 0xd5, 0x88, 0x09, 0xe6, 0x09, 0x34, 0x3e, 0x60, 0xf3, 0xc1, + 0x50, 0x83, 0x74, 0x0e, 0x17, 0xeb, 0xec, 0x37, 0x30, 0x85, 0x23, 0x25, + 0xc2, 0x14, 0x81, 0x4f, 0x17, 0xd3, 0x65, 0xba, 0xce, 0x73, 0x59, 0x3c, + 0x5c, 0xda, 0x61, 0x6b, 0xdb, 0x9b, 0x4a, 0x84, 0x02, 0x22, 0x56, 0x1e, + 0x76, 0x85, 0x5f, 0x8e, 0x75, 0xe2, 0xbb, 0xb6, 0x42, 0xfb, 0xbd, 0x5f, + 0x9a, 0x15, 0x8e, 0xd6, 0x44, 0x95, 0x15, 0x24, 0x5c, 0x47, 0x68, 0xa6, + 0x49, 0x12, 0x86, 0xba, 0x70, 0x00, 0x49, 0x19, 0x93, 0x04, 0x19, 0xc4, + 0xd3, 0xa5, 0xb5, 0x95, 0xe1, 0x9c, 0xd1, 0x84, 0xe2, 0x31, 0x2e, 0x78, + 0xba, 0xd0, 0x0d, 0x84, 0xec, 0xcb, 0x94, 0xde, 0x26, 0x6c, 0xbc, 0x57, + 0xf1, 0x68, 0xbf, 0x01, 0xff, 0x31, 0x64, 0xe6, 0xb2, 0xcb, 0xc7, 0xeb, + 0x36, 0x7a, 0x16, 0xc8, 0xd5, 0xa9, 0x67, 0x33, 0x63, 0x9d, 0x07, 0xa0, + 0xbf, 0x36, 0x40, 0x75, 0xb9, 0x79, 0xb3, 0xaf, 0xe0, 0x91, 0x68, 0x1b, + 0xf4, 0x79, 0x3a, 0x34, 0xdb, 0x77, 0x65, 0xd8, 0xd0, 0x9e, 0x4e, 0x24, + 0x22, 0x22, 0x9a, 0x39, 0x67, 0x76, 0x31, 0x6b, 0x92, 0x48, 0x17, 0xb6, + 0x8f, 0x77, 0xc2, 0x4e, 0xf7, 0x82, 0x97, 0x04, 0x39, 0xee, 0x44, 0x33, + 0x2c, 0xcc, 0x10, 0xb4, 0xc5, 0x89, 0x9f, 0x06, 0x6f, 0x8b, 0x22, 0xff, + 0xed, 0x85, 0x7e, 0x8c, 0x5c, 0xac, 0xed, 0xd3, 0xf3, 0x33, 0xa8, 0xd4, + 0xd6, 0x2f, 0x13, 0x0c, 0x79, 0x04, 0xc7, 0x34, 0x22, 0x8d, 0x81, 0x99, + 0xad, 0x84, 0x0b, 0x76, 0xd6, 0x2b, 0x31, 0x52, 0xe8, 0xd5, 0x3a, 0xc8, + 0xcc, 0x2a, 0x68, 0x67, 0xeb, 0x7c, 0x92, 0x3e, 0x8a, 0x2a, 0xde, 0x26, + 0x82, 0x79, 0x34, 0x3a, 0xd2, 0x79, 0xb1, 0xe0, 0xaa, 0x8b, 0x49, 0x89, + 0x51, 0x84, 0xbb, 0x31, 0xf9, 0x00, 0xde, 0x80, 0xb5, 0xab, 0x6a, 0x49, + 0xf8, 0xec, 0xa9, 0x38, 0x4d, 0x97, 0x90, 0x28, 0x91, 0xaa, 0xba, 0x4c, + 0x7f, 0xc3, 0x55, 0xf9, 0x1a, 0x26, 0xf3, 0x65, 0x15, 0x5f, 0x30, 0x02, + 0xbe, 0x3d, 0x80, 0xa1, 0xed, 0xa8, 0xe2, 0x59, 0x03, 0x81, 0x12, 0xa3, + 0x43, 0xce, 0x28, 0x1d, 0x99, 0xc7, 0x8b, 0x5b, 0x59, 0x72, 0x80, 0xe4, + 0xf9, 0x29, 0xc9, 0x81, 0xf6, 0x1b, 0x4e, 0x21, 0x79, 0xd1, 0x40, 0x85, + 0xcf, 0x69, 0xe8, 0x15, 0xcd, 0x51, 0xef, 0x7e, 0xae, 0x10, 0x9f, 0x0d, + 0xc0, 0xc0, 0xcc, 0x2a, 0x10, 0xb2, 0x39, 0x62, 0x6e, 0xd7, 0x13, 0x28, + 0x33, 0x75, 0xf1, 0xcd, 0xd3, 0x21, 0x6c, 0x0a, 0x95, 0x57, 0xa3, 0x16, + 0x2a, 0xbb, 0xd5, 0xd9, 0x6b, 0xfa, 0xb1, 0x11, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x13, 0x48, 0xb3, 0xac, 0x3e, 0x38, 0xb9, 0xf5, + 0xf2, 0x07, 0x26, 0x6f, 0x5d, 0x15, 0x60, 0xa4, 0xab, 0x4d, 0xe8, 0x1e, + 0x79, 0xcc, 0x73, 0x5e, 0x11, 0x67, 0xd0, 0x2b, 0x35, 0xd8, 0x7f, 0x29, + 0xe1, 0x71, 0x3a, 0xfa, 0x7c, 0x58, 0x02, 0xe1, 0x07, 0xb8, 0x34, 0x52, + 0x63, 0x92, 0x97, 0x86, 0xa3, 0x90, 0xca, 0xfd, 0x78, 0xf7, 0x99, 0x6b, + 0x50, 0xf7, 0xe4, 0x0c, 0x03, 0x6d, 0xb5, 0x29, 0x6e, 0xb0, 0x28, 0xb5, + 0x6c, 0x82, 0x11, 0x73, 0xff, 0xa4, 0xe4, 0x55, 0x2e, 0x5a, 0xeb, 0x30, + 0x71, 0x3c, 0xd8, 0x73, 0x47, 0xe4, 0xcb, 0xad, 0x70, 0x7e, 0x0d, 0xd0, + 0xfd, 0xa4, 0x2a, 0x26, 0x05, 0x9f, 0x52, 0x9f, 0xbf, 0x0d, 0x0c, 0xa2, + 0xc5, 0xb8, 0xfd, 0xef, 0x1c, 0xd4, 0xc6, 0xa7, 0x95, 0x91, 0x27, 0x1f, + 0xa8, 0x90, 0x9c, 0xec, 0x42, 0xa3, 0x90, 0x03, 0x6d, 0x09, 0x66, 0x28, + 0x45, 0x30, 0xe2, 0x47, 0x23, 0xe5, 0x81, 0xb0, 0xa8, 0xe0, 0x99, 0xd0, + 0xaf, 0x8f, 0xa3, 0xd6, 0x83, 0x9a, 0x23, 0x4e, 0x3f, 0xf3, 0x87, 0x61, + 0x84, 0x56, 0xa8, 0x50, 0x06, 0x3d, 0xfa, 0x01, 0x11, 0xfc, 0x67, 0x31, + 0x73, 0x7a, 0xa2, 0xdb, 0x7a, 0xa6, 0xe7, 0xdb, 0xed, 0x09, 0xa1, 0x3e, + 0x33, 0x68, 0x3f, 0x77, 0xf5, 0x67, 0x92, 0x21, 0x3f, 0x1c, 0x62, 0x7f, + 0x0f, 0xb8, 0x0a, 0x2d, 0xb3, 0xb1, 0xa5, 0xa4, 0xc1, 0x83, 0x8f, 0xc4, + 0x1e, 0xf5, 0x60, 0xc8, 0xf0, 0xba, 0x2f, 0x49, 0x8e, 0x59, 0xcc, 0x74, + 0x43, 0x62, 0x27, 0xdf, 0xfe, 0xbf, 0x1b, 0xef, 0x99, 0x89, 0xbb, 0x28, + 0xb1, 0x71, 0x95, 0x67, 0x8a, 0xa5, 0x88, 0xe2, 0x0b, 0xc9, 0x43, 0x2e, + 0x47, 0x0d, 0x1a, 0x27, 0x3a, 0x7b, 0x4d, 0x28, 0x33, 0xe0, 0x1d, 0x0a, + 0x0d, 0xa2, 0x95, 0x84, 0x6e, 0x31, 0x29, 0x27, 0x28, 0x5d, 0x39, 0x7c, + 0x09, 0xc0, 0xa4, 0xa5, 0xf4, 0xca, 0x89, 0x60, 0x70, 0xc2, 0x5a, 0x95, + 0xd7, 0x8f, 0x50, 0x03, 0x62, 0x28, 0x57, 0x99, 0x65, 0xae, 0x26, 0x90, + 0x17, 0x0d, 0x15, 0x27, 0x47, 0x77, 0x01, 0xbd, 0x04, 0xf3, 0xf2, 0x2b, + 0xac, 0x88, 0x12, 0x63, 0x24, 0x36, 0xcb, 0x5f, 0xe5, 0xc4, 0x43, 0x22, + 0xa2, 0x90, 0x27, 0x36, 0xa4, 0xf9, 0x71, 0xb1, 0x9c, 0x97, 0xd1, 0x06, + 0x88, 0x65, 0xad, 0x3f, 0x17, 0x45, 0xf7, 0x69, 0xc1, 0xce, 0x30, 0x30, + 0xc4, 0xde, 0x89, 0x3a, 0x2f, 0xab, 0x3c, 0x61, 0x05, 0xae, 0x98, 0x46, + 0x1f, 0x17, 0x15, 0x26, 0xe8, 0x14, 0xc1, 0x1e, 0x51, 0x66, 0x7b, 0xff, + 0x3b, 0xaa, 0xe5, 0x00, 0x32, 0x4c, 0x45, 0xae, 0x8f, 0xe7, 0x1d, 0xdc, + 0xc4, 0x2f, 0x78, 0x62, 0xcb, 0x32, 0xed, 0xa7, 0xcc, 0x6d, 0x3f, 0x85, + 0x9c, 0xf0, 0x9c, 0x2d, 0x20, 0x5c, 0x3f, 0xc7, 0xc6, 0x3e, 0xf8, 0x76, + 0x24, 0xc7, 0x3d, 0xbc, 0x2d, 0x2a, 0x25, 0x3f, 0x35, 0xaa, 0xfa, 0xf1, + 0xa7, 0xad, 0x46, 0x9f, 0x79, 0x9a, 0x12, 0x0f, 0x7b, 0xf6, 0xd0, 0x2e, + 0xdb, 0x7b, 0x58, 0xe9, 0x27, 0x01, 0x78, 0xed, 0x7a, 0x79, 0x7d, 0x08, + 0xe4, 0x33, 0xd3, 0xc5, 0x00, 0xdd, 0xfd, 0xc5, 0xcb, 0xd1, 0xd0, 0x98, + 0x31, 0xc9, 0x5a, 0x57, 0xca, 0x6e, 0x26, 0x13, 0x5a, 0xd4, 0xdb, 0x77, + 0xe1, 0xd5, 0xaa, 0x3a, 0xb2, 0x84, 0x1e, 0xd4, 0x97, 0x22, 0xfe, 0xe4, + 0x51, 0x5a, 0x8e, 0x29, 0x54, 0xce, 0xc5, 0x18, 0x73, 0xdb, 0xb2, 0xd0, + 0xa7, 0x72, 0x33, 0x10, 0xa4, 0x9c, 0xe3, 0xfb, 0xaa, 0xab, 0x3c, 0xd5, + 0x73, 0x7f, 0x66, 0xd3, 0x71, 0x65, 0x00, 0xf4, 0x6d, 0x45, 0x13, 0xbe, + 0x9c, 0xc4, 0x46, 0x5b, 0xdd, 0xeb, 0xf2, 0xb1, 0xb1, 0xe2, 0xcc, 0x18, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x48, 0x89, 0xba, 0x74, + 0xb6, 0x49, 0xc0, 0xcc, 0x93, 0xdc, 0x6c, 0x76, 0x88, 0xdc, 0x57, 0x22, + 0x5f, 0xf8, 0x83, 0x0c, 0xb2, 0x85, 0x99, 0x85, 0x9c, 0xcb, 0x34, 0x20, + 0x1f, 0xe1, 0x7b, 0x29, 0xf5, 0x35, 0x45, 0xed, 0x98, 0xdb, 0x77, 0xcc, + 0x0c, 0x61, 0xd7, 0xc8, 0x6a, 0xc7, 0x6d, 0x1d, 0x3f, 0x32, 0xe0, 0x82, + 0x63, 0xfe, 0xcc, 0xaa, 0x49, 0xe1, 0x98, 0xcd, 0x7a, 0x2b, 0x09, 0x0f, + 0xa0, 0xf0, 0xf8, 0x70, 0x40, 0x60, 0xc3, 0x50, 0xae, 0x37, 0xbb, 0x98, + 0x2f, 0xb4, 0xe1, 0x38, 0xe7, 0xc1, 0xd1, 0x65, 0xb8, 0x09, 0x56, 0x1d, + 0xa1, 0xfc, 0xb9, 0x46, 0xb9, 0x29, 0xee, 0x22, 0x33, 0x57, 0x77, 0x9d, + 0x2e, 0x43, 0xf6, 0x50, 0x74, 0x6f, 0x14, 0x09, 0x6c, 0x9a, 0x3f, 0xad, + 0xd0, 0x31, 0x07, 0xd1, 0x4f, 0xf6, 0x83, 0xc7, 0x1f, 0xca, 0x5d, 0xbf, + 0xef, 0x00, 0x73, 0x07, 0xd4, 0x00, 0x9e, 0x5a, 0x95, 0x4c, 0x90, 0x6f, + 0x52, 0x34, 0x93, 0xdf, 0x59, 0xe7, 0xfd, 0x7f, 0x90, 0x52, 0xf9, 0xfb, + 0x1c, 0x24, 0x19, 0xfe, 0x3c, 0x89, 0xda, 0xbf, 0x62, 0x5e, 0x46, 0x11, + 0x2e, 0xf7, 0x0a, 0xda, 0xf1, 0x74, 0x26, 0x0c, 0x9d, 0xcf, 0xf0, 0xd7, + 0xf3, 0x70, 0xbc, 0xd6, 0x98, 0x64, 0x8e, 0xde, 0x49, 0x90, 0xf3, 0x5a, + 0xe0, 0x76, 0x0a, 0x15, 0xd0, 0xa8, 0x72, 0x0c, 0x5d, 0x9f, 0x70, 0xad, + 0x12, 0x04, 0x31, 0x83, 0x57, 0x1c, 0x32, 0x4a, 0xd9, 0xd2, 0x5d, 0xb6, + 0xba, 0x1b, 0x00, 0xd0, 0xd9, 0x24, 0x15, 0xdc, 0x0d, 0xde, 0xac, 0xbb, + 0x53, 0x55, 0xb4, 0x04, 0xfd, 0xac, 0x7e, 0x59, 0x97, 0x4e, 0x21, 0x30, + 0x6b, 0x6e, 0x5f, 0x80, 0x50, 0x4f, 0xd4, 0x95, 0x5e, 0x80, 0xba, 0x09, + 0x1d, 0xe5, 0xaf, 0x7d, 0xc0, 0xee, 0x57, 0xda, 0x34, 0x58, 0xb8, 0x09, + 0x79, 0xf0, 0x6b, 0x21, 0x40, 0x2f, 0x00, 0xae, 0x4b, 0xcd, 0x44, 0xe8, + 0x39, 0x6c, 0x07, 0x76, 0x96, 0x62, 0x5d, 0xab, 0x45, 0x7d, 0xe2, 0xdc, + 0x4c, 0xf1, 0xe8, 0x72, 0xbd, 0xa3, 0xf1, 0x2b, 0xbc, 0x49, 0x9e, 0xad, + 0x92, 0x43, 0xbc, 0x7a, 0xe3, 0xcf, 0x17, 0x10, 0xf3, 0x43, 0x84, 0xd3, + 0xf5, 0x32, 0x91, 0x86, 0xdb, 0xfd, 0x21, 0x40, 0x08, 0x1b, 0x90, 0x52, + 0x00, 0xb0, 0xca, 0x0c, 0x0e, 0x98, 0xe4, 0xed, 0x0d, 0x67, 0xf6, 0x65, + 0x89, 0x89, 0x71, 0xe7, 0x04, 0xf1, 0x1e, 0x48, 0x15, 0x66, 0xad, 0xb8, + 0xfe, 0x6b, 0x71, 0x05, 0xa2, 0xe2, 0x8e, 0x39, 0x38, 0xaa, 0x11, 0x0d, + 0x87, 0x78, 0xdc, 0x01, 0x73, 0xcc, 0xcf, 0x3e, 0xe4, 0xe1, 0x52, 0xc2, + 0x47, 0xfa, 0x88, 0x26, 0xf5, 0x5f, 0x72, 0x91, 0x3d, 0x89, 0xa9, 0x24, + 0x55, 0xc6, 0xd0, 0x8e, 0x2c, 0xe0, 0x9f, 0x22, 0xcd, 0x99, 0x3f, 0x12, + 0x2e, 0x0a, 0x6a, 0xe6, 0x1f, 0xe3, 0x10, 0xa0, 0x5b, 0x84, 0x32, 0xfd, + 0x6c, 0x9f, 0xf2, 0x3e, 0x55, 0x38, 0x82, 0x6e, 0x39, 0x20, 0xf1, 0xc8, + 0xff, 0xf4, 0x06, 0x1c, 0x61, 0x44, 0x8f, 0x4b, 0xf6, 0x3a, 0xa2, 0xdb, + 0x3b, 0x77, 0xaa, 0xec, 0xcf, 0xa0, 0x94, 0xe6, 0xd2, 0xa0, 0x58, 0x5f, + 0x40, 0xbc, 0xa3, 0x0d, 0xd1, 0x8f, 0x6e, 0x09, 0x02, 0x2d, 0xab, 0x2f, + 0x3f, 0x3d, 0x38, 0xe5, 0x15, 0x9b, 0xad, 0x08, 0xac, 0x83, 0x3e, 0xe1, + 0xc1, 0xf4, 0x3a, 0xb2, 0x32, 0x49, 0xa3, 0x86, 0xf9, 0xc5, 0x77, 0x1c, + 0x51, 0x41, 0xdf, 0x87, 0x4c, 0x15, 0xec, 0x0d, 0x0a, 0xd3, 0x8c, 0x1a, + 0xd9, 0xfb, 0x4a, 0xca, 0x07, 0xcb, 0x23, 0x78, 0x46, 0xc4, 0x03, 0xbd, + 0xa7, 0x52, 0xee, 0xca, 0x3e, 0xed, 0xf8, 0x80, 0xf6, 0x40, 0x76, 0xc7, + 0x76, 0x00, 0x84, 0x28, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x02, 0x86, 0x44, 0xdf, 0x10, 0xb1, 0xff, 0xac, 0xda, 0x70, 0x56, 0xaf, + 0xda, 0x22, 0xfd, 0x6e, 0x62, 0x46, 0x03, 0x73, 0xa0, 0x04, 0x71, 0xbe, + 0xa4, 0xa2, 0x35, 0x9f, 0x0a, 0xe6, 0x86, 0x04, 0xc6, 0x15, 0x2a, 0xf9, + 0x19, 0x94, 0x9a, 0x36, 0x81, 0xa4, 0xf7, 0xc8, 0x97, 0xdd, 0x83, 0xf1, + 0x35, 0x6b, 0x72, 0x74, 0xb0, 0x2c, 0x70, 0x33, 0xa8, 0xd9, 0xd3, 0xf1, + 0x91, 0x4b, 0x7c, 0x2f, 0xd5, 0x19, 0xd8, 0x7b, 0xa0, 0x47, 0x89, 0xe1, + 0x21, 0x9c, 0x38, 0xda, 0xeb, 0xb0, 0xcb, 0x76, 0xb7, 0xda, 0xf3, 0x4a, + 0x8f, 0x36, 0xe6, 0x95, 0x4a, 0xe3, 0xdc, 0x62, 0x1c, 0xfd, 0x05, 0x2e, + 0xc1, 0x9c, 0x53, 0x6b, 0x82, 0x29, 0x13, 0x95, 0x7e, 0xcd, 0x5b, 0x6a, + 0x32, 0xdb, 0x8a, 0xe0, 0xf5, 0xab, 0x6b, 0xf2, 0xbc, 0x46, 0xc4, 0xfb, + 0xae, 0x5b, 0x00, 0xae, 0x9d, 0x8d, 0x59, 0x0d, 0x21, 0x0f, 0xd4, 0x38, + 0x6b, 0x4d, 0x64, 0xd2, 0x60, 0x87, 0xdd, 0x19, 0x73, 0x9d, 0x20, 0xc3, + 0xaa, 0x78, 0xf7, 0x3d, 0x16, 0xb5, 0xdd, 0xa7, 0x2f, 0x48, 0x7d, 0x87, + 0x1e, 0x1a, 0xf9, 0x2a, 0x7d, 0xf2, 0xe2, 0xad, 0x90, 0x24, 0x39, 0xdd, + 0xde, 0x59, 0x2a, 0x7b, 0x66, 0x45, 0xbf, 0xab, 0x7d, 0x1e, 0x9d, 0x1e, + 0x06, 0x32, 0xf9, 0xc2, 0x10, 0x46, 0x2c, 0x75, 0xd4, 0x85, 0x25, 0x2f, + 0x08, 0x82, 0xa5, 0x3e, 0x77, 0xb7, 0xfa, 0xe6, 0x0c, 0xaa, 0x41, 0xb9, + 0x0f, 0x27, 0xd1, 0x85, 0x23, 0xa7, 0x13, 0x36, 0x52, 0xf3, 0x5f, 0x9b, + 0x6f, 0x8f, 0x82, 0x46, 0xdb, 0x90, 0x4c, 0x1e, 0x4d, 0x9e, 0x0d, 0x31, + 0x1d, 0xd5, 0xcc, 0xb5, 0x4c, 0xbe, 0x0f, 0x03, 0xbd, 0xf8, 0x6f, 0xb1, + 0x29, 0x73, 0x97, 0xac, 0x17, 0xd2, 0x31, 0xfb, 0x4a, 0xd1, 0x32, 0xaa, + 0x39, 0x13, 0x9c, 0x01, 0x3b, 0x78, 0xb5, 0x16, 0x6a, 0x17, 0x28, 0x56, + 0x46, 0x10, 0x3a, 0x19, 0x4c, 0x6f, 0x85, 0xfa, 0x73, 0xbd, 0x84, 0x96, + 0xf7, 0xd5, 0xa2, 0x0b, 0x9a, 0xc9, 0x2f, 0xa0, 0xac, 0xf6, 0xdf, 0x23, + 0xb2, 0x32, 0xf3, 0xa3, 0xcb, 0x66, 0x8b, 0xd1, 0xa8, 0x55, 0x10, 0xea, + 0x4a, 0x21, 0xb6, 0x92, 0x16, 0x81, 0x1a, 0x7c, 0xae, 0x24, 0x59, 0xf8, + 0x73, 0x5e, 0x62, 0x46, 0x9c, 0x0d, 0x02, 0x17, 0xf8, 0x74, 0x86, 0xb1, + 0x72, 0x7e, 0x98, 0xb6, 0x59, 0x08, 0x38, 0x4d, 0xa7, 0x6a, 0x0c, 0x08, + 0x1c, 0x0a, 0xc7, 0xc9, 0xf0, 0xea, 0x01, 0xb7, 0x4c, 0x7d, 0x48, 0x6c, + 0x26, 0x89, 0x6f, 0x0e, 0x29, 0x44, 0x45, 0x4b, 0x09, 0x37, 0xf9, 0x9a, + 0x63, 0xd0, 0xd7, 0xff, 0xe7, 0x2b, 0x80, 0xb0, 0xe8, 0xc9, 0x51, 0xb7, + 0x99, 0xf6, 0x57, 0x23, 0xbb, 0xe5, 0xa0, 0x70, 0x6d, 0xe0, 0xb8, 0x07, + 0xd4, 0x8b, 0x9e, 0x7b, 0x21, 0xa8, 0xc7, 0x57, 0x84, 0x80, 0xf4, 0x9c, + 0x74, 0x5f, 0x85, 0xd5, 0x08, 0x44, 0x1f, 0x94, 0x65, 0x57, 0x1a, 0xab, + 0xec, 0x29, 0x78, 0x9b, 0x12, 0x56, 0x3f, 0x25, 0x4c, 0xfe, 0x13, 0xa6, + 0xf5, 0xcb, 0x5e, 0x1e, 0xb2, 0xd9, 0xcf, 0xfe, 0xb7, 0xc4, 0x58, 0x4d, + 0x6b, 0xf9, 0x07, 0xe5, 0xda, 0xa5, 0xf2, 0xa1, 0x71, 0x30, 0x5a, 0x29, + 0xc7, 0xfc, 0x26, 0x0e, 0x62, 0x42, 0x9e, 0x76, 0x3c, 0x65, 0x02, 0x09, + 0xfc, 0xe3, 0x0e, 0x5c, 0xb1, 0xbd, 0x4e, 0x43, 0x65, 0xa2, 0xa0, 0x8e, + 0xca, 0xdd, 0x36, 0xc3, 0x45, 0x5a, 0x0b, 0x90, 0x83, 0xfd, 0xaf, 0x03, + 0xb9, 0x76, 0x2d, 0xda, 0x1b, 0xab, 0xed, 0xdd, 0xae, 0x6e, 0x93, 0x45, + 0x6d, 0x3a, 0x2b, 0x59, 0x3a, 0x91, 0x99, 0x5c, 0x3c, 0xc7, 0x51, 0xe9, + 0x8e, 0x65, 0x62, 0x52, 0x33, 0xe0, 0x8f, 0x10, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0xe5, 0x28, 0x80, 0x7d, 0x69, 0xf4, 0xeb, 0xce, + 0x57, 0x66, 0xc6, 0x39, 0xaa, 0x59, 0x52, 0x24, 0xf8, 0x5e, 0xef, 0x0e, + 0x69, 0xd4, 0x7c, 0xab, 0x4e, 0x69, 0x9f, 0xdd, 0xb5, 0x69, 0x58, 0x2e, + 0x02, 0x41, 0xe1, 0x66, 0x05, 0x37, 0x8b, 0xef, 0x58, 0x1f, 0xb6, 0x78, + 0xca, 0x9d, 0x7d, 0x0e, 0xfd, 0x00, 0x26, 0x86, 0x2c, 0xe0, 0x40, 0xd6, + 0x55, 0xfa, 0x14, 0xc4, 0x5d, 0x3e, 0xc9, 0x2c, 0x40, 0xd6, 0xa7, 0x27, + 0xb3, 0xc1, 0x4f, 0xfa, 0x9c, 0xe7, 0xe6, 0x0a, 0x2d, 0x31, 0xa2, 0x94, + 0x85, 0xfd, 0x0c, 0x5c, 0x7c, 0xad, 0x9f, 0xf5, 0x25, 0xd6, 0x02, 0x4f, + 0x02, 0xc6, 0x3b, 0x1f, 0xcf, 0xa6, 0x29, 0x04, 0xce, 0xa2, 0xc5, 0xc5, + 0xc6, 0x7f, 0x34, 0x8f, 0x48, 0x8c, 0xd8, 0x82, 0xdc, 0x48, 0x2c, 0xde, + 0xaf, 0xcc, 0x2b, 0xe6, 0xa3, 0xd6, 0xf0, 0xca, 0x13, 0x82, 0xa6, 0x2f, + 0xfc, 0x67, 0xfb, 0x6b, 0x6c, 0xed, 0x14, 0xa1, 0x3a, 0x73, 0xc2, 0xf6, + 0xcc, 0xe4, 0xc1, 0xb8, 0xb6, 0xd9, 0x6b, 0xfc, 0x90, 0x20, 0x82, 0x15, + 0xcd, 0x14, 0xf3, 0xdd, 0x59, 0xae, 0x4c, 0x25, 0x5c, 0x8b, 0x10, 0x5c, + 0x74, 0x63, 0xe5, 0xb7, 0x84, 0xf9, 0x49, 0x36, 0x97, 0xf8, 0xc2, 0x56, + 0xcf, 0x1f, 0x43, 0x7b, 0x29, 0x42, 0x76, 0x0c, 0xe6, 0xa7, 0x23, 0x4b, + 0x6d, 0xf7, 0x40, 0x06, 0x5f, 0x3d, 0x46, 0x0f, 0x9a, 0x86, 0x53, 0xa4, + 0xe1, 0x5f, 0xad, 0xeb, 0xf3, 0xfa, 0xb5, 0x9d, 0x17, 0x96, 0x2c, 0x28, + 0x12, 0xfa, 0xa3, 0xda, 0x47, 0x5e, 0x4a, 0x7e, 0x89, 0x32, 0xaa, 0x29, + 0x1a, 0xf5, 0x5e, 0x24, 0x4a, 0x78, 0xb4, 0xc1, 0xfa, 0x74, 0xf7, 0xc5, + 0x45, 0x5d, 0xe7, 0x1f, 0xce, 0x47, 0x67, 0xaf, 0x4a, 0x0f, 0x8c, 0xe3, + 0x76, 0x36, 0xd3, 0xd8, 0xe0, 0xd5, 0xfa, 0x1e, 0xaa, 0xd7, 0x98, 0x8d, + 0xba, 0x0e, 0x6f, 0xdf, 0x42, 0x60, 0xee, 0x31, 0xc8, 0xa7, 0x47, 0x62, + 0x80, 0x93, 0xe2, 0xf6, 0x1c, 0x96, 0xd8, 0xee, 0x14, 0xf5, 0x9c, 0x37, + 0x83, 0x56, 0x86, 0x01, 0xc3, 0x6e, 0x61, 0x2c, 0xf4, 0xee, 0xc8, 0xef, + 0x59, 0xbb, 0x4b, 0xd2, 0x5b, 0x6a, 0xe9, 0x4c, 0x0a, 0xef, 0xba, 0xfe, + 0x13, 0xbb, 0xf7, 0x60, 0xde, 0xe1, 0xa2, 0x8f, 0x85, 0xb2, 0x8f, 0x11, + 0x11, 0x9e, 0x6d, 0x30, 0x15, 0x70, 0xe4, 0x07, 0xc7, 0x87, 0xd1, 0x89, + 0xb9, 0x0a, 0x64, 0x84, 0x23, 0xa3, 0x19, 0x2c, 0x45, 0x49, 0x1e, 0xb3, + 0x1e, 0x10, 0xde, 0x46, 0x72, 0x1b, 0x04, 0x29, 0x13, 0xc9, 0x7f, 0x8a, + 0xf6, 0x5a, 0x61, 0x58, 0x0c, 0xcb, 0xf5, 0xff, 0xb6, 0x57, 0x1f, 0x77, + 0x4c, 0x43, 0xc9, 0x9c, 0x9b, 0x48, 0x24, 0xc3, 0x7c, 0x5b, 0xe6, 0xcd, + 0xc7, 0x2e, 0xc1, 0x07, 0x7b, 0xee, 0x7d, 0x2c, 0xe1, 0xd8, 0x27, 0x65, + 0xe3, 0xf7, 0x63, 0x9d, 0xa4, 0xf6, 0x3d, 0xee, 0x0e, 0x8d, 0x6c, 0x68, + 0x9a, 0xf3, 0x93, 0x11, 0xcf, 0xc5, 0x80, 0xb0, 0xc3, 0xde, 0x34, 0x11, + 0x84, 0xad, 0x8c, 0xbe, 0x26, 0xcf, 0x3d, 0x7f, 0x8c, 0x41, 0xda, 0x44, + 0x6e, 0xab, 0x4c, 0xdc, 0xb9, 0x2f, 0x97, 0x80, 0x80, 0x76, 0x0a, 0x2a, + 0x21, 0x0f, 0xfd, 0x95, 0x1f, 0x87, 0x1a, 0x11, 0x3e, 0x1c, 0x42, 0x41, + 0xd4, 0x3d, 0xa2, 0xc8, 0xb5, 0xd8, 0xc2, 0xa1, 0xf4, 0x95, 0xdd, 0x72, + 0x99, 0xfa, 0x33, 0x95, 0x8d, 0x73, 0x21, 0x0f, 0x86, 0x36, 0x83, 0x56, + 0x84, 0xf3, 0xe5, 0x1c, 0x07, 0x76, 0x8e, 0x67, 0x4a, 0xc0, 0x62, 0xed, + 0xbd, 0x32, 0xa6, 0xdb, 0x30, 0x40, 0xa7, 0xdc, 0xa4, 0xb7, 0x7f, 0x3f, + 0xe1, 0xd2, 0xca, 0xa4, 0x1c, 0x03, 0xa9, 0xca, 0x25, 0x2f, 0xfc, 0x08, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xbd, 0x5e, 0xd3, 0x7f, + 0xd2, 0x9d, 0xc2, 0x45, 0xe5, 0x9c, 0xc1, 0x69, 0x79, 0x45, 0xce, 0x3c, + 0x68, 0x90, 0xe5, 0x2d, 0xcc, 0xf8, 0x1f, 0x58, 0xb2, 0xc6, 0x69, 0x93, + 0x3e, 0xd7, 0x28, 0x2b, 0xd1, 0x95, 0x34, 0xb2, 0x14, 0x48, 0xcb, 0x15, + 0xce, 0x44, 0xa5, 0x34, 0x73, 0x21, 0x26, 0x9d, 0xa6, 0x5c, 0xca, 0x2c, + 0xfa, 0x7f, 0x02, 0xc6, 0xa5, 0xa5, 0x6f, 0xbd, 0x48, 0x2b, 0x46, 0x16, + 0x85, 0x5a, 0x5c, 0xde, 0x28, 0x73, 0xfe, 0xd1, 0x84, 0x51, 0x1e, 0xe2, + 0x2c, 0x07, 0x70, 0xd2, 0xb7, 0xde, 0xa5, 0xe4, 0x53, 0x20, 0x2c, 0x62, + 0x67, 0x23, 0xe8, 0x7e, 0x1b, 0x2b, 0xfd, 0x2a, 0xa3, 0x13, 0x5c, 0xf6, + 0x7d, 0x59, 0x51, 0x2b, 0xe3, 0x99, 0x1b, 0x09, 0xc8, 0xb1, 0xc5, 0x40, + 0xaf, 0x09, 0xd3, 0xdc, 0xf7, 0x91, 0x43, 0x50, 0x25, 0x89, 0x60, 0xa8, + 0xac, 0x87, 0xf4, 0x13, 0xdb, 0x6e, 0xb4, 0xe2, 0xf6, 0x85, 0xd5, 0x0d, + 0x64, 0x3b, 0xcd, 0x1d, 0xb8, 0xfc, 0xfe, 0x4a, 0xa7, 0x5f, 0xf1, 0xb9, + 0x11, 0x1a, 0x60, 0x50, 0xa5, 0xad, 0x9b, 0x17, 0x00, 0x39, 0xab, 0x22, + 0x5e, 0x8e, 0x45, 0xff, 0x5e, 0x89, 0xce, 0xea, 0x19, 0x11, 0xb7, 0x6e, + 0xb8, 0x8d, 0xe0, 0x3b, 0x2c, 0x86, 0xdb, 0x48, 0x60, 0x68, 0x8b, 0x5c, + 0xfb, 0x3d, 0xd1, 0xa1, 0xc6, 0xb8, 0xe9, 0x17, 0xb5, 0x53, 0x7d, 0x0c, + 0xac, 0x3c, 0xa4, 0x1f, 0x09, 0x77, 0xad, 0x8e, 0xcf, 0xd8, 0x9a, 0x2c, + 0x29, 0xc7, 0x49, 0xcb, 0xa8, 0x9f, 0xb4, 0x19, 0x1c, 0x00, 0x99, 0x9c, + 0x29, 0x46, 0xa1, 0x23, 0xd2, 0x03, 0xe4, 0x99, 0x95, 0xc7, 0xda, 0x20, + 0xaa, 0x8b, 0x55, 0x6e, 0x8d, 0xab, 0x57, 0x39, 0x48, 0x86, 0x1a, 0xc8, + 0xa2, 0x41, 0x7c, 0xf1, 0x82, 0xea, 0x6a, 0x50, 0xd4, 0x17, 0x2f, 0x27, + 0x30, 0x14, 0x64, 0x5e, 0x8f, 0xac, 0x61, 0x6d, 0xcc, 0x02, 0x51, 0x0b, + 0x89, 0x78, 0x69, 0xf9, 0x74, 0x2a, 0x75, 0x26, 0x84, 0x1f, 0x6b, 0x14, + 0xec, 0x87, 0x08, 0x56, 0xf6, 0xf1, 0xac, 0x0f, 0xa2, 0x74, 0x00, 0xb9, + 0x0f, 0x7e, 0xf2, 0x5c, 0x9e, 0x9e, 0xcf, 0xec, 0x43, 0xa4, 0x17, 0x3f, + 0xd6, 0xe9, 0x54, 0x60, 0x99, 0x8d, 0x65, 0x63, 0x88, 0x68, 0x55, 0xd4, + 0x66, 0x99, 0x1a, 0x2c, 0x43, 0xde, 0xb8, 0xf3, 0xf3, 0x94, 0x72, 0x5b, + 0x88, 0x64, 0x1d, 0x1c, 0xf5, 0xde, 0xd2, 0xd2, 0xa1, 0x07, 0xe8, 0x46, + 0xc1, 0x3b, 0x89, 0xb6, 0xee, 0x1e, 0xf6, 0x0a, 0xf1, 0xdb, 0x43, 0x28, + 0xe9, 0xce, 0xd9, 0x8d, 0x09, 0x12, 0x11, 0x36, 0xcd, 0x7e, 0xf6, 0xde, + 0xa0, 0x8e, 0x43, 0xdd, 0xae, 0x62, 0x1e, 0xd7, 0xa1, 0xa4, 0xca, 0x2f, + 0x98, 0x38, 0x43, 0x44, 0xe4, 0x18, 0x31, 0x1b, 0x19, 0x2c, 0xb0, 0xd5, + 0xed, 0x75, 0xcc, 0xa2, 0x3b, 0x0a, 0xc3, 0xec, 0xfd, 0xc2, 0x23, 0x9a, + 0xdf, 0x66, 0x26, 0x43, 0x25, 0x5b, 0x13, 0xfe, 0x79, 0xa7, 0x5b, 0x77, + 0xcd, 0x75, 0x06, 0x2e, 0x72, 0x1c, 0x12, 0xa1, 0xa4, 0x51, 0xcf, 0x0c, + 0x80, 0xfe, 0xe7, 0x65, 0xf4, 0xaa, 0x3d, 0xf7, 0xe9, 0x9d, 0xdc, 0x96, + 0x75, 0xc2, 0xe0, 0x56, 0x78, 0xb2, 0xd4, 0x0f, 0xb3, 0x34, 0x3d, 0x1e, + 0x0a, 0xe5, 0x9a, 0x3e, 0x4b, 0x05, 0xfb, 0x99, 0x3d, 0xef, 0xd8, 0xdb, + 0xc3, 0x12, 0x26, 0xdc, 0xfc, 0x03, 0x38, 0xe4, 0xa0, 0x67, 0xe3, 0x25, + 0xd8, 0x40, 0x96, 0xbc, 0x77, 0x05, 0x9a, 0x1f, 0x8f, 0x94, 0x92, 0xd3, + 0xca, 0xa8, 0x77, 0x35, 0xf8, 0x3e, 0xc2, 0x5a, 0xb0, 0x3f, 0x63, 0xff, + 0x9e, 0xf5, 0xf3, 0x24, 0x6c, 0x89, 0x8f, 0xfe, 0x0b, 0x8b, 0x79, 0x88, + 0x9a, 0x3c, 0xae, 0x27, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x65, 0xd9, 0x5b, 0x9d, 0xf5, 0x8d, 0x23, 0x2f, 0x43, 0x08, 0x78, 0xa7, + 0xd8, 0xa4, 0x46, 0x49, 0x7c, 0x22, 0xc9, 0xd5, 0x09, 0xa3, 0x20, 0xd1, + 0xca, 0x15, 0x4f, 0xba, 0x51, 0x59, 0x52, 0x09, 0x45, 0xcf, 0x47, 0x95, + 0x36, 0xa8, 0x0b, 0x6a, 0x0f, 0x3a, 0x7b, 0xa9, 0x2d, 0x30, 0x5a, 0xaa, + 0x3a, 0xd7, 0x5a, 0xe7, 0x82, 0xee, 0x36, 0xbf, 0x16, 0xf9, 0x09, 0xd4, + 0x3e, 0xd4, 0x7d, 0x07, 0xcf, 0x1d, 0xf4, 0x9f, 0x89, 0x12, 0x29, 0xe9, + 0x80, 0x31, 0x0b, 0x99, 0x5d, 0xc9, 0xaf, 0xf3, 0x83, 0xa9, 0xf0, 0x74, + 0xb9, 0x8f, 0x8d, 0x48, 0x9b, 0x86, 0x79, 0xb8, 0xe1, 0x56, 0x19, 0x01, + 0xa7, 0xbb, 0x13, 0xb8, 0x24, 0xa4, 0x11, 0x8f, 0x4b, 0xfc, 0x4a, 0x7d, + 0x1b, 0x07, 0x19, 0xe8, 0xac, 0x32, 0x6f, 0xe2, 0xc1, 0x06, 0x96, 0xa2, + 0x79, 0x4b, 0xab, 0x6c, 0x7a, 0x21, 0x8b, 0x0d, 0xd7, 0x2f, 0xe3, 0xd2, + 0x0f, 0x69, 0x5c, 0x67, 0x12, 0x8d, 0x69, 0x76, 0x1e, 0x01, 0x80, 0x8f, + 0xa3, 0xd2, 0x5e, 0x7b, 0xf6, 0x65, 0xbe, 0x3f, 0x80, 0x0b, 0xa2, 0x88, + 0x90, 0x2e, 0x0d, 0x14, 0x97, 0xf9, 0xad, 0x1c, 0xf6, 0xa3, 0xf4, 0xab, + 0x69, 0xe1, 0xdc, 0x9b, 0x38, 0x1b, 0x34, 0x4c, 0x81, 0x56, 0x63, 0xd6, + 0x7b, 0x92, 0xab, 0xab, 0xf0, 0x8a, 0xc6, 0x2a, 0x0b, 0xc7, 0xf9, 0x1a, + 0xee, 0x6c, 0xe8, 0xda, 0x23, 0xfc, 0x70, 0x9a, 0xa0, 0x35, 0xca, 0x16, + 0x00, 0xdc, 0x15, 0x28, 0x8e, 0x26, 0x7d, 0x71, 0xc6, 0x88, 0x5a, 0x2f, + 0xe6, 0xb5, 0x9b, 0xed, 0x1e, 0xed, 0xed, 0x07, 0x44, 0x1a, 0x8c, 0xd1, + 0x29, 0x1e, 0x70, 0x06, 0x7e, 0x58, 0x4e, 0x9f, 0x8c, 0xd1, 0x7e, 0x30, + 0x45, 0x4e, 0x7c, 0xbc, 0xbb, 0xed, 0xa9, 0x2e, 0xa3, 0x01, 0xee, 0xa2, + 0xa6, 0xb4, 0x3a, 0x22, 0x5e, 0xdc, 0x24, 0x43, 0x4a, 0x10, 0xf5, 0x6e, + 0x84, 0xce, 0x24, 0x00, 0x78, 0x90, 0xec, 0x6c, 0xb1, 0xb8, 0xc3, 0x69, + 0x3b, 0x0d, 0xa7, 0xdd, 0x5d, 0x3d, 0x15, 0x85, 0x69, 0xc5, 0x8d, 0x26, + 0x9b, 0x97, 0xab, 0x63, 0xb5, 0xcb, 0x0a, 0x84, 0x2f, 0x43, 0x88, 0x05, + 0x15, 0xe4, 0x1a, 0xe9, 0x02, 0x27, 0x62, 0x84, 0xcd, 0xa8, 0xb1, 0xf4, + 0xe9, 0xf0, 0xe7, 0x6d, 0xe8, 0xe0, 0x23, 0x19, 0xdf, 0xa3, 0xa7, 0x99, + 0x97, 0x97, 0x2f, 0xde, 0x46, 0x87, 0xa7, 0x15, 0x9e, 0xa7, 0xa0, 0x84, + 0x5d, 0xa3, 0x9d, 0xce, 0x91, 0x57, 0xff, 0x4a, 0x9b, 0x72, 0x98, 0x3e, + 0x0d, 0xbe, 0x06, 0x28, 0xc0, 0x3f, 0x74, 0x35, 0xff, 0xa8, 0x20, 0x00, + 0xf2, 0xd9, 0x2a, 0x73, 0x79, 0xf7, 0x78, 0x32, 0xf1, 0x59, 0x9a, 0xae, + 0x31, 0xa1, 0x12, 0xca, 0xe3, 0x7f, 0x38, 0x27, 0x10, 0xfc, 0x3d, 0x20, + 0x49, 0xa5, 0xbe, 0xb5, 0xb0, 0x3c, 0x0a, 0xc7, 0x8d, 0x23, 0xc4, 0xb8, + 0xa5, 0xeb, 0x15, 0x6f, 0x3d, 0x79, 0x7b, 0x53, 0xcb, 0x15, 0x81, 0x80, + 0xf4, 0x6a, 0xe4, 0xc5, 0x29, 0x28, 0xe5, 0x08, 0x38, 0x50, 0xde, 0xab, + 0xec, 0x4a, 0xdb, 0xcf, 0x7e, 0x35, 0xfc, 0x16, 0xb7, 0xb9, 0xdc, 0x21, + 0xd3, 0x96, 0xad, 0x0b, 0xfe, 0x58, 0xc9, 0x94, 0x30, 0x38, 0xc0, 0x98, + 0xf4, 0x1c, 0xde, 0x16, 0x11, 0x6a, 0x97, 0xcc, 0x9a, 0xcd, 0x67, 0x20, + 0x9a, 0xe9, 0x3e, 0x1c, 0xc4, 0x0d, 0xcf, 0xfa, 0x1b, 0x7e, 0x9f, 0xb3, + 0x53, 0x2e, 0x77, 0xec, 0xd7, 0x9f, 0x92, 0xdb, 0x0e, 0xcf, 0x19, 0x1e, + 0xae, 0x8d, 0x47, 0x56, 0xfb, 0x2d, 0x07, 0x19, 0xcc, 0xde, 0x0d, 0x02, + 0x02, 0xfe, 0x36, 0x6d, 0x1a, 0x07, 0xcb, 0x3a, 0x5f, 0x87, 0x93, 0x99, + 0x1c, 0xeb, 0xef, 0x9b, 0xc0, 0xf6, 0x49, 0x22, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x94, 0xee, 0x69, 0xf7, 0x89, 0xea, 0x7a, 0xe8, + 0xbf, 0x79, 0x6d, 0x34, 0x8e, 0x56, 0x0e, 0x37, 0x8c, 0x86, 0xba, 0xde, + 0xe4, 0x17, 0x25, 0xfc, 0xe5, 0x70, 0x5d, 0x8b, 0x9b, 0x27, 0xa2, 0x26, + 0xa7, 0xc6, 0x5b, 0xcf, 0x97, 0x60, 0xc4, 0xd5, 0xb7, 0x55, 0x87, 0x68, + 0x22, 0x60, 0xdb, 0x5c, 0xdd, 0xbc, 0x60, 0x07, 0x3f, 0xf6, 0x6b, 0xfe, + 0x8d, 0x43, 0xbc, 0x0b, 0x18, 0x6c, 0x8d, 0x24, 0xcf, 0x37, 0x95, 0xcc, + 0xf9, 0x11, 0xab, 0x9a, 0x51, 0x7e, 0x7f, 0x3c, 0x69, 0x41, 0xa0, 0xa6, + 0xda, 0x19, 0x92, 0x18, 0x2c, 0x5b, 0xea, 0xbb, 0x4a, 0x12, 0x05, 0x74, + 0xef, 0xf3, 0xcf, 0x28, 0xc3, 0xff, 0x61, 0x67, 0x82, 0x01, 0x5e, 0x4a, + 0xce, 0x39, 0x00, 0x72, 0x89, 0xf4, 0x11, 0xf0, 0x47, 0x60, 0x5f, 0x85, + 0x30, 0x96, 0x0c, 0x15, 0x10, 0x05, 0x4c, 0x41, 0x30, 0x06, 0x69, 0x09, + 0xc5, 0x66, 0x70, 0xa6, 0xaf, 0x99, 0x5e, 0x00, 0x7d, 0x32, 0x54, 0xae, + 0x4c, 0xc2, 0xdb, 0x9f, 0x22, 0x06, 0x59, 0x11, 0x71, 0x5e, 0xdb, 0x66, + 0x88, 0xf3, 0x76, 0x6b, 0x39, 0x6e, 0x89, 0x1a, 0x4a, 0x80, 0x36, 0x3a, + 0x21, 0xf6, 0xe8, 0xa0, 0xbc, 0xba, 0xaa, 0x86, 0x89, 0x48, 0x35, 0x05, + 0x65, 0x34, 0xc3, 0xc7, 0x2b, 0x2c, 0xac, 0xe4, 0xca, 0x32, 0xb1, 0xb3, + 0x48, 0x00, 0xc0, 0x0c, 0xfd, 0x6f, 0x77, 0x36, 0x95, 0x4a, 0xb3, 0x79, + 0x6f, 0xf6, 0x1c, 0x4f, 0x23, 0x02, 0xa1, 0xe1, 0xd6, 0xfb, 0x20, 0xea, + 0xd9, 0xdb, 0x62, 0x75, 0x88, 0xc0, 0x5e, 0x1e, 0x42, 0x53, 0xdd, 0x23, + 0x89, 0x48, 0xfa, 0xf3, 0x27, 0x4a, 0x31, 0x9a, 0x2e, 0x6d, 0xe7, 0x6b, + 0x77, 0x65, 0x7b, 0x90, 0xf9, 0xb7, 0xef, 0x0f, 0x03, 0xed, 0xc4, 0xb0, + 0xed, 0x9b, 0x8b, 0x09, 0x2b, 0xaf, 0x18, 0x0b, 0x06, 0xec, 0x56, 0x0d, + 0xc5, 0xa8, 0x91, 0x6e, 0x12, 0xfb, 0x7f, 0x6c, 0xde, 0x05, 0xdd, 0xeb, + 0xcb, 0x33, 0x04, 0xfc, 0xd0, 0x5a, 0x20, 0xb2, 0x78, 0x30, 0xff, 0x67, + 0xd2, 0x24, 0x94, 0x03, 0x8b, 0x9c, 0x2c, 0x46, 0xbc, 0xef, 0xf8, 0x01, + 0x86, 0x09, 0x90, 0x74, 0xd4, 0x0d, 0xb6, 0xb1, 0xe0, 0xd9, 0xb2, 0xee, + 0x0b, 0xbe, 0x13, 0xb0, 0x5a, 0xda, 0x0e, 0xd7, 0x4d, 0x74, 0x1a, 0x19, + 0x87, 0xcc, 0xa2, 0xb0, 0xd2, 0x11, 0xf8, 0xa2, 0xce, 0xe0, 0xb6, 0x4b, + 0x88, 0xd3, 0x70, 0xae, 0xba, 0x8b, 0xb1, 0xb1, 0x73, 0x6d, 0xb6, 0xfd, + 0x34, 0xef, 0x68, 0x92, 0x89, 0x38, 0xe1, 0x08, 0x0a, 0x39, 0x58, 0x98, + 0x04, 0x96, 0xb3, 0x6e, 0x07, 0xd2, 0x2a, 0x3b, 0xe2, 0xb3, 0xdf, 0x7a, + 0x8d, 0xbb, 0x0e, 0x0c, 0xca, 0x6c, 0xf5, 0xcd, 0x93, 0x6a, 0xa7, 0x8d, + 0x42, 0x68, 0x6d, 0x26, 0x5d, 0x79, 0x50, 0x07, 0x77, 0x30, 0x79, 0x61, + 0xfc, 0xf3, 0x41, 0xcb, 0xde, 0x22, 0x21, 0x5a, 0x37, 0x17, 0x93, 0x26, + 0xe8, 0x7e, 0xc3, 0x22, 0x80, 0x4a, 0xe3, 0x82, 0xe0, 0x29, 0x90, 0x25, + 0x64, 0xb8, 0x23, 0x49, 0x6d, 0x0c, 0xc2, 0xa4, 0x36, 0xd9, 0x5e, 0x6a, + 0xb8, 0x30, 0x71, 0x53, 0xf5, 0xae, 0xfe, 0x51, 0xa6, 0x8c, 0xd8, 0x10, + 0x95, 0x22, 0x1a, 0x88, 0x2f, 0xd1, 0x6d, 0x1c, 0xba, 0x8d, 0xd4, 0x5c, + 0xfa, 0x52, 0x9c, 0x6b, 0xf5, 0x9d, 0xe3, 0x62, 0x53, 0xf4, 0x70, 0x50, + 0xfb, 0x17, 0xbf, 0x78, 0x95, 0x24, 0xcc, 0x78, 0xf4, 0xf3, 0xed, 0xfd, + 0x7d, 0xab, 0x2c, 0x09, 0x6b, 0x2b, 0xba, 0x3a, 0x7d, 0xc8, 0x2f, 0x7a, + 0x01, 0xba, 0x69, 0xc6, 0xb3, 0x4e, 0xcf, 0xb9, 0x68, 0x65, 0x37, 0x80, + 0x6d, 0x4a, 0x99, 0x3d, 0x82, 0x3a, 0x30, 0xf3, 0xb0, 0xd6, 0x08, 0x0f, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x69, 0x19, 0x44, 0xb0, + 0x23, 0x07, 0x50, 0x58, 0x2f, 0xc3, 0x8b, 0x32, 0x09, 0xbc, 0xb9, 0xc9, + 0x83, 0xab, 0x03, 0xd0, 0x11, 0x24, 0xed, 0x50, 0x4b, 0x34, 0x38, 0xec, + 0xab, 0xcb, 0xb5, 0x1d, 0x9d, 0x84, 0xc2, 0xc9, 0xbb, 0x2d, 0xea, 0x31, + 0x75, 0xa3, 0x95, 0xd1, 0x86, 0xdd, 0x3d, 0xd1, 0x68, 0x49, 0xf0, 0xa5, + 0x6e, 0xc0, 0x50, 0x88, 0xfb, 0x7c, 0x4f, 0x34, 0x66, 0x47, 0x1b, 0x19, + 0x34, 0xa5, 0xe7, 0x50, 0xfc, 0x06, 0x3e, 0x1e, 0xdc, 0xed, 0x8c, 0xa0, + 0xfc, 0xae, 0x9d, 0xfa, 0x7d, 0x5b, 0xea, 0x70, 0x5a, 0xaa, 0xbf, 0x0c, + 0x6f, 0x61, 0x09, 0x33, 0x9f, 0x22, 0x21, 0x04, 0x12, 0x3e, 0x38, 0x2c, + 0x79, 0x01, 0x4e, 0x5d, 0x56, 0xd7, 0xdb, 0x4f, 0xf9, 0x53, 0x5b, 0x78, + 0x02, 0x4f, 0xf2, 0x20, 0x24, 0x4f, 0x4f, 0xc0, 0xef, 0xdc, 0xeb, 0x46, + 0xb4, 0x8d, 0x9d, 0x12, 0x39, 0xa8, 0x97, 0xd1, 0x3f, 0xd2, 0x22, 0x44, + 0x29, 0x0a, 0xca, 0xb6, 0xd2, 0x63, 0xd3, 0xee, 0x1e, 0x58, 0x73, 0x3b, + 0xbd, 0x2d, 0x1f, 0xb3, 0x6d, 0x39, 0x55, 0x5b, 0xda, 0x5e, 0xfc, 0x23, + 0xe8, 0x3f, 0x1d, 0x80, 0x4d, 0xfa, 0x5a, 0x33, 0xac, 0x83, 0x06, 0xa4, + 0xe9, 0x59, 0x19, 0xa5, 0xcf, 0xb5, 0xa6, 0x64, 0xa8, 0x5a, 0x6d, 0xa0, + 0x41, 0xa7, 0x8b, 0xd5, 0x51, 0x03, 0x4a, 0x1e, 0x2d, 0x61, 0x8a, 0x31, + 0xc3, 0x90, 0x90, 0xf7, 0xe7, 0x40, 0x83, 0x6b, 0x62, 0x58, 0x71, 0x9f, + 0xdc, 0x72, 0x38, 0x91, 0xd8, 0x79, 0xa6, 0xe0, 0x03, 0x51, 0x3c, 0x5b, + 0xd7, 0xd1, 0x4a, 0x0a, 0x61, 0x02, 0xad, 0xf9, 0xf2, 0xba, 0xda, 0x2b, + 0xeb, 0x6c, 0x4d, 0x4d, 0xbb, 0x03, 0x17, 0xcc, 0x3d, 0x26, 0x1a, 0xf7, + 0x3a, 0xa4, 0x37, 0x41, 0xa5, 0xd5, 0xd6, 0x85, 0xc9, 0x31, 0xe4, 0x12, + 0x6c, 0x95, 0x42, 0xcd, 0x15, 0xe3, 0x85, 0xaa, 0x71, 0xcc, 0xc1, 0x4b, + 0xeb, 0x96, 0xbc, 0x68, 0x67, 0xc0, 0xbe, 0xd5, 0x54, 0x74, 0x5c, 0xf6, + 0xc9, 0x8c, 0xa5, 0x85, 0xe6, 0xcc, 0x7f, 0x14, 0x2f, 0x36, 0x1b, 0xa5, + 0xda, 0x08, 0x6f, 0x96, 0xc7, 0xd5, 0xa6, 0x6e, 0xf3, 0x89, 0x1a, 0xde, + 0x80, 0x12, 0x43, 0x37, 0x31, 0x6f, 0x94, 0x49, 0x72, 0xaf, 0x1b, 0x30, + 0x24, 0x70, 0x77, 0x2a, 0x63, 0x9f, 0xcd, 0xcb, 0xb9, 0x52, 0x7d, 0x65, + 0xb5, 0xc0, 0xcd, 0x81, 0x61, 0x7a, 0x88, 0xe5, 0x2b, 0x85, 0xf5, 0xfc, + 0xf7, 0x6c, 0x98, 0xed, 0x97, 0x3f, 0x4b, 0x77, 0xec, 0x7b, 0xc3, 0x08, + 0xbf, 0xc5, 0x05, 0x5d, 0x32, 0x71, 0x49, 0x1e, 0xc0, 0x10, 0xf5, 0x5f, + 0x13, 0x4c, 0x3f, 0x35, 0x1c, 0x7a, 0x8a, 0x49, 0x6a, 0x74, 0xc3, 0xde, + 0x1d, 0xf2, 0x0e, 0x88, 0xad, 0xc9, 0x4a, 0x19, 0xad, 0x7c, 0x70, 0x44, + 0xf2, 0x21, 0x23, 0x7e, 0xd4, 0x04, 0x38, 0xd1, 0xb3, 0x2f, 0xdd, 0x73, + 0xa7, 0x19, 0x02, 0xf8, 0xbb, 0x0b, 0xed, 0x51, 0x73, 0xf3, 0x11, 0xde, + 0x11, 0x74, 0xd7, 0x2d, 0xf1, 0xae, 0x2f, 0xdb, 0xd9, 0xa4, 0xee, 0x62, + 0xc4, 0xda, 0xa5, 0xc6, 0xb0, 0x0d, 0x4a, 0x0d, 0x59, 0xbf, 0xe1, 0xf1, + 0x7b, 0x9b, 0xef, 0x4f, 0xa9, 0xb7, 0x00, 0x6d, 0xf7, 0xe9, 0x6d, 0x10, + 0xc5, 0xd7, 0x00, 0x62, 0x45, 0x96, 0x8c, 0xbd, 0x70, 0x4a, 0x6b, 0xbd, + 0xe3, 0xe2, 0x83, 0x9b, 0x82, 0x99, 0x48, 0x18, 0xf9, 0x64, 0xa0, 0x66, + 0xe2, 0xa6, 0x6b, 0xbf, 0x92, 0x6f, 0x90, 0x27, 0x9d, 0xa6, 0xb6, 0xdf, + 0xea, 0x53, 0x3c, 0x01, 0x24, 0x2a, 0x32, 0x05, 0x6c, 0xbe, 0x60, 0x68, + 0xb6, 0x4a, 0x07, 0xcd, 0x00, 0xa3, 0x11, 0xb5, 0x40, 0x05, 0x60, 0xab, + 0xa8, 0xa8, 0xe6, 0x23, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x39, 0xf1, 0x01, 0xc5, 0x17, 0xf3, 0x36, 0xb4, 0x3c, 0x95, 0x0a, 0xb4, + 0x44, 0xe3, 0x75, 0x90, 0xab, 0xda, 0xdc, 0x13, 0x26, 0x8b, 0x2a, 0xb0, + 0x33, 0xb2, 0xdc, 0xe8, 0xd7, 0xbe, 0x9e, 0x0e, 0xf4, 0xb2, 0x8d, 0x04, + 0xf9, 0x64, 0xbb, 0xc1, 0xb9, 0x60, 0xa0, 0xd9, 0xba, 0x14, 0xe3, 0x54, + 0x57, 0x21, 0x86, 0xae, 0xc0, 0x25, 0x96, 0xb8, 0x88, 0x4d, 0x6b, 0x2d, + 0xfb, 0xb3, 0x5a, 0x28, 0x32, 0x37, 0xcf, 0x17, 0x04, 0x84, 0x47, 0x7e, + 0xdb, 0xce, 0x8d, 0x62, 0x38, 0x11, 0xf0, 0xa0, 0xd2, 0x83, 0x10, 0x6f, + 0x4f, 0x80, 0x33, 0x01, 0x76, 0xea, 0xed, 0xdc, 0xbf, 0x79, 0x90, 0x2b, + 0x99, 0x28, 0x6e, 0xd2, 0xbd, 0x4a, 0x67, 0x06, 0xeb, 0xc3, 0x42, 0x77, + 0xe7, 0xec, 0x21, 0xa1, 0x27, 0x63, 0x95, 0xca, 0x2e, 0x90, 0xf7, 0x11, + 0x05, 0xeb, 0x92, 0x6d, 0x39, 0xe3, 0x2f, 0x1e, 0x7e, 0xcb, 0x24, 0x26, + 0x34, 0x14, 0x00, 0xba, 0xe8, 0x42, 0x3f, 0x88, 0x6c, 0x24, 0xdb, 0xc2, + 0x6b, 0x9b, 0x98, 0x0e, 0x8e, 0x23, 0x5b, 0xc3, 0xdf, 0xb5, 0x1f, 0x2f, + 0x39, 0xea, 0xba, 0x14, 0xe6, 0xd2, 0x6c, 0xa2, 0x4a, 0x9c, 0xcf, 0xd5, + 0xca, 0x9f, 0xdf, 0xb6, 0x71, 0x46, 0xf6, 0xdc, 0x67, 0x14, 0xd4, 0x76, + 0x0b, 0x3d, 0xcc, 0xc3, 0x0f, 0x5a, 0xc3, 0x9e, 0xc3, 0xa6, 0xe5, 0x14, + 0x33, 0x62, 0xb8, 0x7c, 0xdd, 0x37, 0x0d, 0x02, 0x47, 0x61, 0x29, 0x5b, + 0x3c, 0x64, 0xfa, 0x47, 0x2c, 0x36, 0xf8, 0xab, 0xf6, 0xbd, 0xfc, 0x0c, + 0x99, 0xb2, 0x99, 0xf1, 0xf2, 0x75, 0xb1, 0x1f, 0x49, 0xf9, 0xa2, 0x06, + 0xd5, 0x4c, 0x1f, 0x5e, 0x34, 0x92, 0xd0, 0x60, 0xe8, 0x36, 0xae, 0x78, + 0x35, 0x5f, 0x5c, 0x0f, 0x9e, 0xf9, 0x60, 0xd8, 0x56, 0xf9, 0xef, 0x6b, + 0xc6, 0x44, 0x40, 0x0f, 0xff, 0x97, 0xaf, 0x96, 0xbb, 0xc1, 0x1a, 0xe9, + 0x4b, 0x26, 0x4f, 0xb3, 0x1a, 0x21, 0x23, 0xb1, 0x39, 0x3f, 0xd0, 0xe1, + 0x20, 0x8d, 0xce, 0x9b, 0x6e, 0xe8, 0xe2, 0xad, 0xb2, 0xb8, 0xe8, 0x0d, + 0x27, 0xc9, 0x1b, 0x4d, 0x0e, 0x15, 0x5b, 0x67, 0x44, 0xa7, 0x70, 0x2d, + 0x6d, 0x0f, 0x0d, 0xef, 0x48, 0xce, 0x49, 0x8f, 0xc3, 0x25, 0xad, 0xcd, + 0x2c, 0x38, 0x56, 0xce, 0xff, 0x50, 0x59, 0x2f, 0xee, 0xf6, 0xf6, 0xd0, + 0xe6, 0xf7, 0x52, 0x41, 0xea, 0x73, 0xa4, 0xd2, 0xba, 0x57, 0xc6, 0xf3, + 0x41, 0xbc, 0x52, 0xf1, 0x98, 0x10, 0x68, 0x65, 0x4e, 0xf0, 0x99, 0x37, + 0xc0, 0xc0, 0xb7, 0x12, 0x41, 0xf6, 0xeb, 0xfd, 0x84, 0x53, 0xc3, 0x69, + 0x38, 0x3b, 0x0e, 0xfa, 0xe8, 0xc1, 0x50, 0x0e, 0x01, 0x8d, 0xe7, 0xd2, + 0x10, 0x2d, 0x69, 0x25, 0x77, 0x6b, 0x71, 0xe2, 0x6c, 0x0c, 0x64, 0x16, + 0x74, 0x3b, 0x74, 0x89, 0xff, 0xa9, 0x46, 0x4c, 0xca, 0xc0, 0x25, 0x3d, + 0x6d, 0x75, 0xcd, 0x9d, 0x90, 0x22, 0x94, 0x66, 0xb0, 0xbe, 0xc3, 0x68, + 0xe7, 0x6f, 0x86, 0x86, 0x64, 0x12, 0xa5, 0x13, 0xa0, 0xbb, 0x80, 0x25, + 0x96, 0x0d, 0x41, 0x98, 0x84, 0xaa, 0xec, 0x17, 0xce, 0x21, 0xdd, 0xf6, + 0xb3, 0x42, 0xf2, 0x27, 0x13, 0xf6, 0x8f, 0x59, 0x27, 0xde, 0x1c, 0xbf, + 0xb5, 0x6b, 0x5e, 0x24, 0x00, 0xf7, 0x18, 0xb0, 0xe0, 0x93, 0x7c, 0xf2, + 0xcb, 0x8f, 0x93, 0xf1, 0x8c, 0x19, 0xd9, 0x72, 0x23, 0x64, 0x9f, 0xb6, + 0x3a, 0x58, 0x62, 0xf3, 0x0e, 0xf2, 0xbd, 0x2b, 0xe5, 0x0f, 0x95, 0x1c, + 0x9a, 0x70, 0x6d, 0x17, 0x14, 0x2e, 0x16, 0x2f, 0x55, 0x30, 0xdb, 0x53, + 0x33, 0x6d, 0xbc, 0xdc, 0xe2, 0x4d, 0x04, 0xdd, 0x0b, 0xdc, 0x08, 0x8a, + 0xde, 0x98, 0xb3, 0xcc, 0x09, 0x93, 0xc9, 0x05, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x11, 0x0e, 0x2c, 0xcc, 0x7f, 0x6f, 0x51, 0x14, + 0x51, 0x6d, 0x0b, 0x69, 0xe1, 0x7f, 0x1f, 0x86, 0x5c, 0x61, 0xcd, 0x3e, + 0xac, 0xc5, 0x7c, 0xc3, 0xf5, 0xdc, 0x27, 0x35, 0xe9, 0xdf, 0x2c, 0x29, + 0x93, 0xa2, 0x60, 0xb4, 0x22, 0xf7, 0xbf, 0xc6, 0x4b, 0x58, 0x4f, 0xce, + 0x7a, 0xe8, 0x26, 0x0c, 0xae, 0xb4, 0x8c, 0x56, 0x3b, 0x6c, 0x79, 0x19, + 0xd6, 0x14, 0xa2, 0x54, 0xc6, 0x18, 0x1d, 0x26, 0x1e, 0x84, 0x16, 0x8e, + 0x26, 0xee, 0x31, 0xcc, 0xf5, 0x8f, 0xbd, 0x10, 0x79, 0x02, 0xf2, 0xcd, + 0x87, 0xbf, 0xe1, 0x2e, 0x6a, 0x8a, 0x89, 0x27, 0xf8, 0x0c, 0x2e, 0x26, + 0x30, 0x6d, 0xa5, 0x2c, 0x06, 0xea, 0xc9, 0x39, 0x4a, 0x78, 0xb7, 0x5b, + 0x44, 0xe6, 0x35, 0xbe, 0x8d, 0x63, 0x36, 0x72, 0xd8, 0xe0, 0x60, 0x70, + 0xa4, 0x9c, 0xb6, 0xd8, 0xe7, 0xfe, 0x3c, 0x50, 0xf1, 0x7d, 0xdc, 0x0c, + 0x60, 0xe9, 0x5f, 0x29, 0xe9, 0x64, 0xef, 0x88, 0xad, 0x74, 0x84, 0xee, + 0x93, 0x76, 0x29, 0x8c, 0x16, 0xa6, 0x23, 0xfa, 0x1d, 0x9e, 0xa5, 0xdc, + 0xf6, 0x88, 0x09, 0x46, 0x0e, 0xb1, 0x97, 0x12, 0x7c, 0x3d, 0x7e, 0x65, + 0x09, 0xc7, 0x24, 0x3f, 0x1a, 0xfa, 0xab, 0xa3, 0x12, 0xa4, 0x93, 0x54, + 0x90, 0x0d, 0x3b, 0x82, 0x79, 0x24, 0x14, 0x36, 0x96, 0x08, 0x13, 0x95, + 0x45, 0x28, 0x92, 0x15, 0x47, 0xd3, 0x91, 0x67, 0xf7, 0xfb, 0x42, 0xb7, + 0x88, 0x2a, 0xb2, 0xa0, 0xe1, 0x56, 0xb4, 0xe0, 0x3d, 0x72, 0xe1, 0xfd, + 0x35, 0xa6, 0x6c, 0x80, 0x8f, 0x12, 0x6f, 0x0a, 0x13, 0x1e, 0x60, 0x16, + 0xe3, 0x66, 0xf7, 0xa5, 0xde, 0x79, 0x68, 0x70, 0x5b, 0x33, 0x43, 0xcc, + 0xd7, 0x4b, 0xa7, 0xca, 0x28, 0x08, 0xe5, 0x4f, 0xae, 0x80, 0x56, 0x97, + 0xc4, 0x7e, 0x00, 0x8f, 0x3e, 0x1e, 0x23, 0x14, 0x97, 0xa7, 0xca, 0xe5, + 0x1e, 0x12, 0xa2, 0xf9, 0x61, 0xcf, 0x25, 0xfd, 0x97, 0x71, 0x72, 0x4a, + 0xa3, 0x91, 0xcc, 0x30, 0x7d, 0x2b, 0xbe, 0x6d, 0xbb, 0xdd, 0x96, 0x06, + 0x69, 0x38, 0x0b, 0x21, 0x5c, 0x53, 0xb3, 0xc3, 0x99, 0x42, 0x1e, 0xae, + 0x94, 0x8c, 0x95, 0xc4, 0x76, 0x02, 0xb5, 0xd6, 0xef, 0x77, 0x5f, 0xcf, + 0x36, 0xd4, 0xec, 0x38, 0x95, 0xe8, 0xfc, 0x3d, 0x47, 0x4d, 0x94, 0x09, + 0xba, 0x64, 0xce, 0x93, 0xfd, 0xfd, 0x82, 0x67, 0x89, 0xf9, 0xa4, 0x8c, + 0x3a, 0xdd, 0xdd, 0xab, 0x97, 0x12, 0x6e, 0x05, 0x90, 0x90, 0xad, 0x6a, + 0xf1, 0x67, 0x42, 0x3b, 0xdf, 0x8c, 0xd9, 0x13, 0x72, 0x2a, 0x99, 0xb1, + 0x5f, 0x9b, 0x2f, 0x20, 0x4e, 0x6a, 0x78, 0xb2, 0xf2, 0xb0, 0x31, 0xdc, + 0x5c, 0x0a, 0x99, 0x6e, 0x41, 0x20, 0x75, 0x23, 0xd5, 0xb9, 0x57, 0xf4, + 0x54, 0xa9, 0x69, 0x00, 0xbe, 0xb4, 0x18, 0xf7, 0x4a, 0x79, 0x24, 0xcc, + 0xb8, 0x6f, 0xf7, 0x26, 0x4d, 0x37, 0x55, 0xea, 0x0a, 0x46, 0x7e, 0xc3, + 0x99, 0xcb, 0x9e, 0x55, 0xda, 0x6d, 0xd6, 0x30, 0x77, 0xe9, 0x28, 0x26, + 0x2a, 0xbc, 0x04, 0x5c, 0x03, 0xa0, 0xda, 0xe6, 0x72, 0x18, 0xad, 0x14, + 0xdc, 0xf7, 0x5f, 0x9f, 0x2e, 0x70, 0xce, 0xe9, 0x22, 0x94, 0xab, 0x36, + 0x72, 0x59, 0xc7, 0xec, 0x23, 0x34, 0xe4, 0x21, 0x97, 0xbb, 0xc4, 0xe6, + 0x5d, 0xc3, 0x8a, 0x41, 0xc3, 0x0c, 0xfb, 0x5c, 0x26, 0x48, 0x39, 0x35, + 0xfa, 0x1e, 0x6f, 0xf1, 0xb8, 0x40, 0x18, 0x16, 0x6c, 0x34, 0x4f, 0xa9, + 0xeb, 0x36, 0xff, 0x03, 0x9f, 0x04, 0xdd, 0x9d, 0xdb, 0xce, 0x37, 0x07, + 0x92, 0xa1, 0xc3, 0xaf, 0x02, 0xdd, 0xf1, 0xa1, 0x3b, 0x59, 0x79, 0x2a, + 0x4f, 0xb7, 0xe7, 0xd4, 0x5d, 0xe3, 0x57, 0x61, 0x22, 0x4f, 0x78, 0x27, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x09, 0x89, 0xe2, 0x00, + 0x90, 0xfc, 0x0f, 0x6d, 0x8e, 0xb4, 0x50, 0x2a, 0x2e, 0x82, 0x6c, 0x8d, + 0x24, 0x3f, 0xb1, 0xb5, 0x05, 0x55, 0x29, 0xd5, 0x53, 0x5c, 0xc9, 0xb8, + 0x3a, 0x97, 0x27, 0x1e, 0x97, 0x6d, 0xd8, 0x8f, 0x37, 0x71, 0x91, 0xc4, + 0xf9, 0xf7, 0x5e, 0x9b, 0x7b, 0x3c, 0xa3, 0xca, 0x75, 0xe6, 0x64, 0xd0, + 0x4f, 0x6d, 0x2d, 0x46, 0x64, 0x8d, 0xbb, 0xe7, 0x57, 0x36, 0x9e, 0x0a, + 0xab, 0x3e, 0x12, 0x39, 0x30, 0x6f, 0x26, 0x23, 0x12, 0xfa, 0xcf, 0xdd, + 0xcb, 0x42, 0x0e, 0x9e, 0x27, 0x21, 0x3e, 0x89, 0xbb, 0xab, 0x8b, 0x95, + 0x07, 0x1b, 0x93, 0x8c, 0x2b, 0x48, 0xf2, 0x04, 0xa3, 0x38, 0x62, 0x36, + 0x05, 0xc6, 0x05, 0x97, 0xa6, 0x55, 0x07, 0xcd, 0x7a, 0x65, 0xbb, 0xe4, + 0xc2, 0xd9, 0x75, 0x1c, 0x8b, 0x75, 0x54, 0x06, 0x2f, 0x65, 0x24, 0x4f, + 0x6e, 0x2d, 0x12, 0x16, 0x61, 0xed, 0x59, 0xa0, 0xab, 0x76, 0xa8, 0xb8, + 0x9d, 0x8d, 0x32, 0xd1, 0x4c, 0x40, 0xa9, 0x5b, 0x83, 0x50, 0xe4, 0xf3, + 0x0e, 0x7c, 0xc0, 0x4b, 0xb9, 0xe6, 0x02, 0x09, 0x36, 0x76, 0xa9, 0x16, + 0x1c, 0x3e, 0x7c, 0xbc, 0xdb, 0x6d, 0x7c, 0x84, 0x45, 0x40, 0xf5, 0xcd, + 0x43, 0xff, 0xb2, 0x10, 0xe8, 0xd9, 0xcf, 0x8a, 0xb7, 0x49, 0x42, 0xf2, + 0x37, 0x1e, 0x5c, 0xf3, 0xf0, 0xee, 0xcd, 0x17, 0xa9, 0x17, 0xdc, 0xc4, + 0x8d, 0xe1, 0x24, 0xd6, 0xd4, 0x07, 0xbd, 0xba, 0x29, 0xe7, 0x5e, 0x38, + 0x40, 0x6a, 0x5d, 0x5f, 0x1c, 0x7f, 0x5b, 0x1f, 0xa3, 0x0a, 0x88, 0x48, + 0xe0, 0xd0, 0xc5, 0x25, 0x3d, 0x4a, 0x31, 0x39, 0x09, 0x97, 0x5a, 0xb9, + 0xf4, 0xb5, 0x03, 0x1b, 0x11, 0x9f, 0x03, 0xe3, 0x97, 0x6b, 0xd5, 0x55, + 0xf4, 0xf3, 0x29, 0xd8, 0x4e, 0x9a, 0xd2, 0x65, 0x7a, 0xe8, 0x67, 0x26, + 0x58, 0x6e, 0x3e, 0x1d, 0x13, 0xc4, 0x57, 0x37, 0x4b, 0xfa, 0xed, 0xf3, + 0xc4, 0x04, 0x35, 0x82, 0x04, 0x12, 0x62, 0xa1, 0xe6, 0xbb, 0x0e, 0xd1, + 0xd4, 0xed, 0xd7, 0x6e, 0x22, 0xc5, 0xa4, 0x0d, 0x01, 0xa4, 0x24, 0x97, + 0xa7, 0x78, 0x33, 0x18, 0xf4, 0x3f, 0x4b, 0x04, 0x38, 0xdd, 0x25, 0x66, + 0xb8, 0x39, 0x61, 0x1c, 0xe3, 0x12, 0xa2, 0x45, 0x5e, 0xe4, 0xaa, 0x56, + 0xdb, 0xbe, 0xbb, 0x24, 0xda, 0x64, 0x47, 0x42, 0x60, 0xc7, 0x5d, 0x96, + 0x08, 0xd8, 0xaa, 0xce, 0x02, 0x5c, 0xf5, 0x08, 0xcd, 0xde, 0x2b, 0xc7, + 0x81, 0xdb, 0x82, 0xea, 0x4f, 0x21, 0x39, 0x62, 0x0d, 0x0e, 0xe9, 0x2b, + 0xc6, 0x6f, 0xfe, 0x28, 0x73, 0xdf, 0x0e, 0xa3, 0xeb, 0x19, 0x3e, 0x28, + 0xcb, 0xb6, 0x83, 0x84, 0x04, 0x79, 0x31, 0xcf, 0x64, 0x17, 0x2a, 0xe2, + 0xc1, 0xfc, 0xa3, 0x62, 0x12, 0x42, 0xb0, 0x28, 0xf0, 0xfb, 0x37, 0xa0, + 0x12, 0x53, 0xf1, 0x34, 0xff, 0xfc, 0xa4, 0x7d, 0xf9, 0x6a, 0x8a, 0x39, + 0xa3, 0x00, 0x79, 0x0e, 0xe3, 0xe8, 0xa4, 0x52, 0x6c, 0x07, 0x53, 0xe9, + 0x44, 0x23, 0x5f, 0x01, 0x01, 0x34, 0xf9, 0xfd, 0x55, 0xff, 0x46, 0x9d, + 0x2c, 0xe1, 0xeb, 0xcf, 0xc8, 0x9b, 0xcf, 0x33, 0xc3, 0x8d, 0x6b, 0x8f, + 0x14, 0x78, 0x96, 0xf8, 0xe5, 0xbf, 0xa4, 0x45, 0x09, 0x6d, 0xb3, 0x0b, + 0x17, 0x7b, 0xcd, 0x53, 0x21, 0xe9, 0x38, 0xa0, 0xba, 0x6e, 0x30, 0x5c, + 0x3c, 0x1f, 0x9d, 0xe2, 0xb0, 0xce, 0x8a, 0xd2, 0xcb, 0xfe, 0xd3, 0x5e, + 0xc5, 0x2a, 0x76, 0xea, 0x13, 0xdd, 0x4f, 0x15, 0x98, 0xfe, 0x1b, 0x88, + 0x6e, 0x74, 0xdc, 0x68, 0x0e, 0xf4, 0xca, 0xea, 0xfe, 0x8d, 0xeb, 0x34, + 0xcd, 0xe1, 0x27, 0x11, 0xa3, 0x1b, 0x97, 0x54, 0xf1, 0xb4, 0x20, 0x46, + 0xc0, 0x3b, 0xab, 0x0e, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x80, 0x2f, 0x36, 0x7b, 0x98, 0x38, 0x32, 0x08, 0x1f, 0xcb, 0x1c, 0x98, + 0xbd, 0xa4, 0xc6, 0xde, 0x4c, 0xfc, 0x16, 0xad, 0x9e, 0x9b, 0x39, 0xf9, + 0x4e, 0xb4, 0xbe, 0xec, 0xbb, 0x7c, 0x25, 0x18, 0x00, 0xb6, 0x5e, 0x51, + 0x63, 0x51, 0x99, 0x1a, 0x52, 0xd9, 0xe5, 0x2f, 0xc4, 0xe1, 0xa8, 0x79, + 0x2a, 0xb9, 0x9e, 0x9e, 0xd5, 0x06, 0x88, 0xca, 0x0b, 0xab, 0x5b, 0x98, + 0xe3, 0xb2, 0x4a, 0x18, 0x26, 0x74, 0xd1, 0x4d, 0x36, 0xb5, 0x7d, 0x2c, + 0xbd, 0x06, 0x5b, 0x84, 0x4d, 0xf5, 0x9e, 0x2f, 0x97, 0xa8, 0x11, 0xd6, + 0x55, 0x9a, 0x02, 0x30, 0x0e, 0x66, 0x4c, 0x01, 0xb5, 0x96, 0xb9, 0x2a, + 0xe5, 0x76, 0x39, 0x05, 0x1d, 0x9a, 0x67, 0x7b, 0x57, 0xec, 0x44, 0x71, + 0x6c, 0xb5, 0x0d, 0x47, 0xb9, 0x99, 0x2b, 0x17, 0x67, 0xc7, 0x8b, 0x71, + 0xa1, 0x3d, 0xc6, 0xb6, 0x97, 0x54, 0xfd, 0x22, 0xf5, 0x53, 0x9d, 0x85, + 0x15, 0xb1, 0xd7, 0xda, 0x3f, 0x75, 0x28, 0xf0, 0xe0, 0xdb, 0xaa, 0xd4, + 0x02, 0x38, 0x1e, 0x6a, 0x7c, 0x32, 0xa6, 0xa7, 0x02, 0x72, 0x25, 0x17, + 0x3e, 0x67, 0x7e, 0x1b, 0xd1, 0xf4, 0x77, 0x13, 0xff, 0xc9, 0x4f, 0xe9, + 0x67, 0x90, 0xb3, 0xb1, 0x11, 0xd1, 0xff, 0xeb, 0xe3, 0x35, 0xbf, 0x96, + 0xd6, 0x10, 0xee, 0x1b, 0x70, 0x7f, 0x3e, 0xd4, 0x2f, 0x01, 0xaa, 0x03, + 0x99, 0x37, 0x1b, 0x50, 0xd3, 0x4a, 0x0c, 0xa0, 0x59, 0xc0, 0x2d, 0xb7, + 0xb6, 0x3b, 0xf6, 0x8f, 0x99, 0xa3, 0xde, 0x3f, 0x35, 0xe4, 0x16, 0x38, + 0xe5, 0x37, 0xcd, 0xb2, 0x7a, 0x79, 0x46, 0x02, 0xda, 0x89, 0x71, 0x51, + 0x38, 0x77, 0xdc, 0xde, 0x06, 0x06, 0x01, 0xf0, 0x7d, 0x91, 0x1b, 0xfc, + 0x9d, 0xbd, 0x39, 0x81, 0x88, 0xfa, 0xfc, 0x20, 0x39, 0x68, 0x6d, 0x7e, + 0x15, 0xaf, 0x98, 0x08, 0xdc, 0xa6, 0x3e, 0xd4, 0x70, 0x77, 0xfd, 0xf5, + 0x47, 0x17, 0xb7, 0x18, 0x33, 0xff, 0xf5, 0xcd, 0xb8, 0x9f, 0x67, 0x69, + 0xf3, 0xa6, 0x22, 0xd1, 0xd3, 0x70, 0x2e, 0xde, 0x2d, 0x6f, 0x7a, 0x10, + 0x83, 0xda, 0x77, 0x49, 0xf8, 0x05, 0x68, 0xbc, 0xe1, 0x21, 0x75, 0x81, + 0xda, 0x4a, 0xa1, 0x50, 0x8a, 0x6d, 0x2f, 0x3f, 0xf4, 0xf1, 0x2e, 0x5c, + 0x31, 0xa4, 0x66, 0x66, 0xd4, 0x5a, 0xcb, 0x1b, 0xfa, 0x38, 0x0d, 0xd6, + 0x87, 0xba, 0x4e, 0x3c, 0x14, 0xb8, 0xe7, 0xc1, 0x15, 0x0f, 0xeb, 0x7d, + 0x54, 0xb2, 0x0a, 0xfc, 0x24, 0xda, 0x22, 0xbb, 0x48, 0x6c, 0x5a, 0xce, + 0xf0, 0x7e, 0xea, 0x00, 0xe6, 0x2f, 0xf9, 0x0c, 0xe9, 0x47, 0x00, 0x6a, + 0x87, 0x6d, 0xf0, 0xec, 0x03, 0x60, 0x6b, 0xbb, 0x0e, 0xdb, 0x3d, 0xed, + 0x70, 0x6b, 0xf1, 0xc1, 0x60, 0xb7, 0x3d, 0x59, 0x65, 0xc4, 0xca, 0x0d, + 0x09, 0xa4, 0x68, 0x4a, 0x46, 0xac, 0x64, 0x63, 0xcd, 0x76, 0xa1, 0x65, + 0xf0, 0x10, 0xe2, 0xc0, 0x8e, 0xbd, 0x6c, 0x01, 0xba, 0x29, 0xca, 0x7e, + 0x3d, 0x15, 0x6f, 0x82, 0xf1, 0x00, 0x4e, 0x2b, 0x00, 0x06, 0xa9, 0x27, + 0x0f, 0x92, 0x6b, 0xab, 0x2d, 0x1b, 0x8e, 0x5b, 0x49, 0x9d, 0x7b, 0x01, + 0x84, 0xad, 0x8d, 0xfe, 0x2d, 0x9e, 0x11, 0x94, 0xe1, 0x66, 0xce, 0xc7, + 0x4c, 0x65, 0x8c, 0x09, 0x12, 0x0a, 0xbe, 0x8f, 0x7a, 0x19, 0xe1, 0xb5, + 0xdf, 0x29, 0xa1, 0xe8, 0x20, 0xbd, 0xa6, 0x6f, 0x15, 0x26, 0x60, 0x64, + 0x2f, 0xa7, 0xa2, 0xf8, 0xd7, 0xe9, 0x52, 0x19, 0xc6, 0x7f, 0x31, 0x2d, + 0xe5, 0xa1, 0x9a, 0x41, 0x5f, 0x89, 0xdd, 0x1d, 0x07, 0x6a, 0x24, 0x80, + 0x6c, 0x26, 0x56, 0xb2, 0xf1, 0x3d, 0x5d, 0x7c, 0x83, 0x73, 0x7d, 0x1a, + 0x1f, 0xac, 0x5c, 0xc8, 0x3e, 0xa6, 0xed, 0x1c, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0xca, 0xbf, 0x39, 0xcb, 0x4a, 0x28, 0xf5, 0xdb, + 0x11, 0x1a, 0x52, 0x92, 0x63, 0xe4, 0x20, 0x57, 0x6b, 0xff, 0xd7, 0xb6, + 0xf4, 0xad, 0x43, 0x3c, 0x89, 0xc9, 0xbe, 0x67, 0xf2, 0x33, 0x48, 0x09, + 0x0b, 0x03, 0xd1, 0x14, 0x09, 0x42, 0xd7, 0xd4, 0x22, 0x2b, 0x56, 0x73, + 0xa9, 0x15, 0xc9, 0x24, 0xb2, 0x83, 0xa7, 0x1e, 0x7f, 0x4b, 0x92, 0x6f, + 0x66, 0xd6, 0x6f, 0xdb, 0x12, 0x4f, 0x41, 0x10, 0x99, 0x26, 0xfb, 0x11, + 0xf7, 0x7c, 0xdc, 0xd2, 0x23, 0xf9, 0x6e, 0xc5, 0x7e, 0x68, 0x3b, 0xb8, + 0x5f, 0xdc, 0x79, 0x15, 0xf6, 0x06, 0x46, 0x56, 0x69, 0x15, 0x15, 0x0c, + 0x7f, 0x17, 0x07, 0x19, 0xeb, 0x75, 0x30, 0x90, 0x03, 0xc4, 0xbb, 0x62, + 0x0c, 0xaa, 0x07, 0xf5, 0x14, 0x43, 0xd7, 0xfa, 0xdc, 0xca, 0x1a, 0xc3, + 0xdf, 0x6d, 0x3e, 0x3e, 0xd2, 0xe6, 0x59, 0xb8, 0x4f, 0x81, 0x5c, 0x1f, + 0x64, 0xa7, 0x20, 0xd6, 0xc5, 0x3b, 0xf2, 0x08, 0x6c, 0x7f, 0x3f, 0x0e, + 0x65, 0x03, 0xe5, 0x21, 0xd6, 0xc9, 0xf2, 0xbd, 0x62, 0xda, 0xd8, 0xee, + 0x00, 0x9e, 0x5d, 0x95, 0x34, 0xb4, 0x23, 0x12, 0x95, 0x6b, 0x8a, 0x1f, + 0xc9, 0x96, 0xa9, 0x74, 0xef, 0x28, 0xf4, 0x00, 0x6e, 0x59, 0x22, 0x95, + 0x9a, 0x3f, 0x79, 0x39, 0xaa, 0x2d, 0x3a, 0x3f, 0x7f, 0x60, 0x62, 0xeb, + 0xe2, 0xcf, 0xc1, 0x2a, 0xdd, 0xb3, 0x9b, 0x28, 0x47, 0xa0, 0x38, 0xb5, + 0x2e, 0x6f, 0x74, 0x72, 0x61, 0x0a, 0x5e, 0x25, 0xcd, 0xd7, 0xb3, 0x70, + 0x5f, 0x5f, 0x58, 0xe4, 0x57, 0x13, 0x8f, 0x8a, 0xc5, 0x40, 0xc5, 0x05, + 0xf7, 0x7f, 0xe2, 0xda, 0x5f, 0x64, 0x68, 0xb4, 0x65, 0xf8, 0x09, 0x81, + 0xc6, 0xea, 0xa1, 0x09, 0xa7, 0xd2, 0xa7, 0x8e, 0x44, 0x72, 0xe4, 0x4b, + 0x69, 0x03, 0x81, 0x91, 0x45, 0x32, 0x8e, 0x1b, 0x30, 0x7c, 0x3c, 0x02, + 0xd5, 0xaf, 0xd1, 0x0e, 0x16, 0x6a, 0x08, 0x28, 0xb8, 0x60, 0x08, 0xac, + 0x85, 0x2c, 0x73, 0xa8, 0x3e, 0x12, 0xb0, 0x23, 0x3c, 0xba, 0xf4, 0x49, + 0x27, 0x2e, 0x18, 0x08, 0xed, 0x3d, 0x1a, 0xf6, 0xe0, 0x06, 0x75, 0x9b, + 0x0e, 0x59, 0xb5, 0x56, 0x7e, 0x26, 0xb5, 0xcc, 0x00, 0x4a, 0x0f, 0x8f, + 0xff, 0x9e, 0x7c, 0xec, 0xe8, 0x7a, 0xa8, 0x54, 0xab, 0x17, 0x97, 0x20, + 0xcd, 0x23, 0xf3, 0x6c, 0x3c, 0x7d, 0x2e, 0xfc, 0x44, 0x96, 0x4c, 0x5a, + 0x07, 0x13, 0x6b, 0xc1, 0x1d, 0x2a, 0x45, 0x5d, 0xb7, 0x20, 0xd8, 0xd2, + 0xd0, 0x48, 0x77, 0x8c, 0x29, 0x33, 0x51, 0x11, 0xc4, 0x1f, 0xe0, 0x7f, + 0x6b, 0x70, 0x19, 0xed, 0x8c, 0x7c, 0x12, 0x5d, 0x43, 0xbc, 0x0e, 0xbc, + 0x95, 0x57, 0xf2, 0xa9, 0x13, 0x5f, 0xe9, 0x26, 0x92, 0xbd, 0xb4, 0x25, + 0x21, 0xb5, 0x4e, 0x2a, 0xdd, 0x36, 0x7f, 0xc2, 0x57, 0x78, 0xf1, 0xb0, + 0xd6, 0x9b, 0x5e, 0xe2, 0x4d, 0x7b, 0x07, 0x4a, 0x73, 0xa8, 0x80, 0x4a, + 0xa5, 0x89, 0x66, 0x51, 0xb0, 0x58, 0x07, 0x4e, 0x42, 0xbb, 0x2b, 0x2f, + 0x18, 0xd7, 0x29, 0x1b, 0xd6, 0xdc, 0x00, 0xcf, 0xcb, 0x4b, 0x98, 0x0f, + 0x53, 0x1a, 0xb9, 0x36, 0xa8, 0xa7, 0xb3, 0x6f, 0xe8, 0x48, 0x51, 0x00, + 0x89, 0xec, 0x7e, 0x6c, 0x1d, 0x39, 0x5a, 0x0d, 0xb8, 0xd8, 0x7f, 0xce, + 0xaf, 0xf5, 0xc6, 0xf8, 0xce, 0xb2, 0x7f, 0x14, 0x7a, 0x90, 0x60, 0x10, + 0x87, 0x94, 0x51, 0x51, 0xab, 0xcf, 0xd2, 0x8e, 0x10, 0xf8, 0x20, 0xd0, + 0xf2, 0xe0, 0x32, 0x24, 0x30, 0x73, 0x3b, 0xaf, 0xc6, 0xb1, 0xe7, 0x63, + 0x0c, 0xbc, 0x39, 0xb9, 0x2d, 0x1c, 0xcd, 0x52, 0x96, 0x01, 0x59, 0xe6, + 0x3f, 0x02, 0xca, 0x91, 0xdd, 0x4d, 0x9f, 0xe5, 0xc0, 0x58, 0x8a, 0x1d, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x13, 0x93, 0x89, 0x04, + 0x1b, 0x0c, 0xdb, 0x9f, 0xde, 0x1b, 0x39, 0x82, 0x5d, 0x27, 0x85, 0x08, + 0xa8, 0xbd, 0x28, 0x4c, 0xf1, 0xea, 0x86, 0x9d, 0x00, 0xf4, 0xda, 0x69, + 0x5d, 0xb4, 0xaf, 0x1c, 0x31, 0x1e, 0x64, 0xa2, 0x3a, 0x9d, 0x79, 0x50, + 0x8a, 0xf1, 0x1a, 0x90, 0x5e, 0xf8, 0xb6, 0xe1, 0x5e, 0x98, 0x66, 0xf2, + 0x8c, 0x5b, 0x88, 0x2e, 0x68, 0x17, 0x0a, 0x57, 0xc1, 0xff, 0xe9, 0x18, + 0x90, 0x1d, 0xc3, 0x94, 0x01, 0x74, 0x1f, 0x5e, 0x1b, 0x81, 0x95, 0xb5, + 0x20, 0xd2, 0x4e, 0x8c, 0x02, 0x84, 0x09, 0xa5, 0x26, 0xa0, 0x97, 0xbb, + 0x0a, 0x6b, 0x6e, 0x71, 0xfa, 0x30, 0x81, 0x2a, 0x30, 0xd2, 0x9e, 0x8f, + 0x29, 0xfd, 0xa5, 0xf6, 0xf2, 0x12, 0xef, 0x15, 0x98, 0x15, 0xc4, 0xf2, + 0x5c, 0xc7, 0xf0, 0xd4, 0x4c, 0x85, 0x6f, 0x3e, 0xc4, 0x1a, 0xd3, 0x29, + 0x97, 0x51, 0xa7, 0x0f, 0xcf, 0xb5, 0x18, 0xc2, 0xa6, 0x5c, 0xb9, 0xa6, + 0x0f, 0x55, 0x1b, 0xf7, 0x88, 0xba, 0x2d, 0x52, 0x89, 0x51, 0xbf, 0x95, + 0xa1, 0xcd, 0xc9, 0xac, 0xfd, 0xfa, 0x45, 0x73, 0x39, 0x42, 0x11, 0x02, + 0x10, 0xf4, 0x93, 0x29, 0x78, 0x58, 0x62, 0x49, 0x88, 0xfe, 0xc1, 0x17, + 0x2e, 0x0a, 0x08, 0x94, 0xce, 0x0a, 0x4e, 0xae, 0x78, 0xdf, 0x63, 0x28, + 0x1b, 0xd0, 0x27, 0xfc, 0xd2, 0xde, 0x54, 0x2e, 0x63, 0x07, 0x9f, 0x06, + 0xce, 0x5c, 0xbd, 0x3b, 0xb6, 0x73, 0x5f, 0x42, 0x6b, 0xb3, 0x44, 0xa0, + 0x48, 0xe8, 0x52, 0x9e, 0x81, 0xef, 0xe0, 0x10, 0x0f, 0x06, 0x0d, 0x82, + 0x9d, 0xba, 0x2a, 0x18, 0xc7, 0xab, 0x40, 0x24, 0xa7, 0xbf, 0xb6, 0x12, + 0xa9, 0x21, 0xab, 0xde, 0xf2, 0x18, 0x85, 0x63, 0xbb, 0x97, 0x6d, 0x2e, + 0x2d, 0x6a, 0xb9, 0x53, 0xe6, 0x49, 0xb6, 0xc0, 0xe6, 0x39, 0x77, 0x01, + 0x03, 0x31, 0x1a, 0x57, 0x94, 0x1f, 0x96, 0x74, 0xdb, 0xc7, 0xde, 0xe8, + 0x63, 0xc4, 0xed, 0xcd, 0xc1, 0x63, 0xcf, 0x06, 0xb2, 0xc5, 0x73, 0x64, + 0xa9, 0x2d, 0x4f, 0x7b, 0x2d, 0x9d, 0xaf, 0x13, 0x20, 0x0c, 0x81, 0xdc, + 0x67, 0x1c, 0x46, 0x2b, 0x95, 0xb5, 0x1b, 0x35, 0x1a, 0xb8, 0xb5, 0xe2, + 0xd9, 0xa5, 0xad, 0x36, 0x0c, 0x80, 0x48, 0x8b, 0xf4, 0xd0, 0xeb, 0xae, + 0xcd, 0x7d, 0x1e, 0x2c, 0xbc, 0x60, 0x7c, 0x17, 0x81, 0xf9, 0xb4, 0x7a, + 0x3c, 0x84, 0x34, 0x3f, 0x60, 0x1f, 0x5c, 0xfc, 0xa3, 0x79, 0x5f, 0xcc, + 0xcb, 0x0f, 0xd0, 0x2f, 0x98, 0x8b, 0x31, 0xde, 0xac, 0x26, 0x52, 0x0b, + 0xbf, 0xc7, 0xab, 0x00, 0x7f, 0x77, 0x1f, 0xf2, 0x0d, 0x0d, 0x3c, 0x0b, + 0x20, 0x97, 0x34, 0x6c, 0xae, 0xf0, 0x30, 0x4b, 0x22, 0x6d, 0x94, 0xfe, + 0x29, 0x78, 0x52, 0x3b, 0xbe, 0x2e, 0x13, 0x08, 0xf8, 0x4d, 0x20, 0x4b, + 0x06, 0x9d, 0x31, 0x22, 0xb1, 0xf1, 0xbc, 0x8e, 0x62, 0x13, 0x39, 0x25, + 0x72, 0x6f, 0x89, 0xc8, 0x2f, 0x93, 0xf7, 0x8c, 0xbf, 0xb3, 0x65, 0x76, + 0xe1, 0x3e, 0x1f, 0x0b, 0x1a, 0x9f, 0xd0, 0xd0, 0x11, 0x50, 0x20, 0xa6, + 0xe5, 0x11, 0x4c, 0xf4, 0x09, 0x8b, 0xae, 0xc2, 0x93, 0x41, 0x30, 0x7c, + 0xf8, 0x6e, 0x4b, 0x56, 0x5d, 0xeb, 0xad, 0x07, 0x9d, 0x94, 0x5e, 0x08, + 0x0e, 0xff, 0xaa, 0x1f, 0x7e, 0x09, 0xc9, 0x8d, 0x2f, 0x8b, 0xa8, 0x3f, + 0x2d, 0xf4, 0x19, 0x3a, 0xab, 0xdb, 0x88, 0x01, 0xaf, 0x03, 0x65, 0xb5, + 0x03, 0x96, 0x21, 0x88, 0xe8, 0xad, 0xf1, 0x0f, 0x3d, 0xd0, 0xfe, 0xd7, + 0x20, 0x2d, 0x96, 0xfb, 0xb2, 0x1b, 0xa9, 0xdc, 0xb8, 0x6c, 0x66, 0xa9, + 0xac, 0xbe, 0x61, 0x79, 0x06, 0x2f, 0x4d, 0xc5, 0x22, 0xfa, 0x08, 0xa7, + 0x1e, 0xe0, 0x87, 0x1b, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x56, 0x25, 0x0d, 0x38, 0xc1, 0x94, 0x42, 0xfd, 0x09, 0xea, 0x1e, 0xf3, + 0x25, 0xe1, 0xa6, 0x6e, 0xc0, 0x2d, 0xce, 0x07, 0x05, 0x66, 0x6f, 0x13, + 0xb9, 0x34, 0xd4, 0x8d, 0xe1, 0x58, 0x62, 0x1b, 0x25, 0x1b, 0xed, 0x27, + 0x46, 0xed, 0x93, 0x4f, 0x56, 0xa5, 0xe1, 0x5f, 0xa2, 0xa3, 0x3a, 0x9c, + 0x4a, 0x95, 0x8b, 0x0d, 0xa7, 0x7b, 0x77, 0xe8, 0x00, 0x0b, 0x0d, 0x51, + 0xf5, 0x60, 0x34, 0x1d, 0xd6, 0x22, 0x2b, 0x56, 0x95, 0xe2, 0xf9, 0x30, + 0x5c, 0x43, 0x57, 0x47, 0xdf, 0x0b, 0xbd, 0xbb, 0x18, 0x0a, 0x85, 0x55, + 0x4c, 0xe5, 0x1b, 0x67, 0x14, 0xc0, 0x5d, 0x0d, 0xcb, 0x28, 0x0c, 0x1c, + 0x89, 0xbb, 0x3e, 0xc1, 0x2a, 0x4c, 0x2e, 0xdd, 0xa6, 0x7e, 0xd4, 0x32, + 0x2a, 0x91, 0x1b, 0x15, 0xe8, 0x53, 0x17, 0x27, 0x41, 0x59, 0xfe, 0xdc, + 0x8c, 0xc1, 0x9a, 0xff, 0x71, 0x2b, 0x45, 0x1d, 0xc3, 0x40, 0x9a, 0xb8, + 0x47, 0x59, 0x1a, 0x6e, 0x32, 0xa4, 0xf1, 0x60, 0xe7, 0x92, 0xc9, 0x46, + 0x49, 0x0d, 0xc3, 0xb2, 0xa6, 0x12, 0xf0, 0xab, 0x1a, 0x66, 0x50, 0x89, + 0x3f, 0xd0, 0x92, 0x1a, 0x64, 0xfb, 0x17, 0xa4, 0x5a, 0xf1, 0x8c, 0xe3, + 0xb4, 0xb7, 0x04, 0x44, 0x75, 0x44, 0xda, 0xf5, 0x1f, 0xc5, 0xa0, 0xdb, + 0x70, 0x8a, 0x5b, 0x2e, 0x80, 0x15, 0xf9, 0xc0, 0xc4, 0xa3, 0xef, 0x2d, + 0xeb, 0x83, 0x00, 0xd1, 0x1f, 0x29, 0xcd, 0x49, 0x19, 0xdc, 0xae, 0x75, + 0x67, 0x6c, 0x5b, 0xf4, 0x20, 0x18, 0x79, 0xc9, 0x2a, 0x6a, 0xac, 0x9c, + 0x96, 0xff, 0xc4, 0xdb, 0x4d, 0x8e, 0x75, 0x0d, 0x5a, 0x11, 0x32, 0x93, + 0xe8, 0x5f, 0x06, 0x0d, 0xcc, 0xef, 0x71, 0x85, 0xbf, 0xa1, 0x02, 0x3d, + 0x59, 0x23, 0xfb, 0xcc, 0x27, 0x39, 0x97, 0x26, 0x35, 0xe3, 0xe1, 0x0d, + 0xc2, 0xed, 0x87, 0x1f, 0x67, 0xbc, 0xea, 0x99, 0x21, 0x89, 0xc1, 0xf5, + 0x7d, 0x2f, 0x07, 0x04, 0x68, 0xa6, 0x53, 0x43, 0x20, 0x2f, 0xa6, 0xb4, + 0x19, 0x02, 0x2d, 0x36, 0x5b, 0xba, 0x11, 0x2f, 0x46, 0x1d, 0xfc, 0x16, + 0x5f, 0x05, 0xda, 0x0d, 0x3b, 0xfd, 0x48, 0xb1, 0x4c, 0xb3, 0xc4, 0x0f, + 0xa1, 0x46, 0x00, 0x17, 0xb8, 0x33, 0x8d, 0x0a, 0x3d, 0x74, 0xaf, 0xcb, + 0xae, 0x70, 0x05, 0x35, 0xde, 0xb8, 0x89, 0x24, 0xc0, 0x4e, 0xfc, 0x78, + 0x90, 0xaa, 0xaa, 0xaf, 0x39, 0x00, 0xa1, 0x65, 0x9b, 0x61, 0x8e, 0xea, + 0xd2, 0x0e, 0xfd, 0x6f, 0xf6, 0xe3, 0x02, 0x5f, 0xc8, 0x94, 0x54, 0xbd, + 0x57, 0x00, 0x35, 0x15, 0xe8, 0x1b, 0x00, 0x6a, 0x12, 0x76, 0x10, 0x73, + 0xb6, 0xe1, 0x9a, 0x6b, 0xa4, 0x20, 0xe6, 0x70, 0x1f, 0x0e, 0x53, 0xe5, + 0x01, 0xa0, 0xb0, 0x43, 0x73, 0x63, 0x79, 0xcf, 0x07, 0xf3, 0x12, 0x02, + 0xf9, 0x15, 0xaf, 0xad, 0x4d, 0x9d, 0xdc, 0x35, 0xd6, 0x41, 0x66, 0xf6, + 0x86, 0xd8, 0x49, 0x5a, 0x8a, 0x6a, 0xf8, 0x54, 0x2a, 0x83, 0xcf, 0xfc, + 0x48, 0xb4, 0x07, 0xc0, 0x4b, 0x63, 0xd3, 0x27, 0x94, 0x2c, 0x75, 0x15, + 0x80, 0x3a, 0x50, 0xe1, 0x50, 0x26, 0xa5, 0x11, 0x04, 0xdb, 0x47, 0x21, + 0xb8, 0x89, 0xa1, 0xb6, 0x77, 0x59, 0x79, 0xd2, 0xb8, 0xba, 0xd8, 0x4c, + 0x5c, 0x7e, 0xd2, 0x27, 0x3e, 0xee, 0xa3, 0x7f, 0x00, 0xf5, 0x1a, 0x22, + 0x32, 0xf9, 0xce, 0xcb, 0xb1, 0x32, 0x11, 0x36, 0x5b, 0x5c, 0xa1, 0xda, + 0x3f, 0x66, 0x64, 0x29, 0x1b, 0x85, 0xaf, 0xa6, 0x82, 0xaf, 0xb8, 0x2e, + 0xdf, 0x9a, 0x92, 0x33, 0xd0, 0xa3, 0xdb, 0x25, 0xbd, 0x38, 0x9c, 0x6a, + 0xaa, 0x52, 0xf2, 0x7b, 0x0b, 0xff, 0x36, 0x66, 0xc4, 0x5e, 0xa4, 0x35, + 0x41, 0xae, 0xda, 0x2f, 0x93, 0x7e, 0x62, 0x07, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x03, 0x51, 0x69, 0xfc, 0xe2, 0x70, 0x31, 0x76, + 0x87, 0xc7, 0x6d, 0x60, 0xc2, 0x47, 0x2c, 0x80, 0x15, 0x6b, 0x83, 0x5e, + 0xb4, 0x50, 0x22, 0x83, 0x6f, 0xeb, 0xe6, 0x70, 0xa3, 0x19, 0x4c, 0x0e, + 0xa3, 0xa1, 0x62, 0x66, 0xdf, 0x5c, 0x3f, 0xee, 0xcc, 0x84, 0xc2, 0xae, + 0x00, 0x77, 0x28, 0x83, 0x42, 0xb1, 0x54, 0xfc, 0x39, 0x48, 0x46, 0xac, + 0xf5, 0x8b, 0x29, 0x4c, 0xbf, 0x00, 0x52, 0x25, 0xc1, 0xd2, 0x90, 0x4c, + 0xf1, 0x21, 0x9e, 0x6e, 0xf0, 0xe5, 0x09, 0xf3, 0xbf, 0x6e, 0x75, 0xe7, + 0x38, 0x38, 0xb7, 0x2e, 0xaa, 0x73, 0x61, 0x9e, 0x2b, 0x8b, 0x36, 0xb8, + 0xaf, 0xec, 0x70, 0x0d, 0x35, 0x2b, 0x9e, 0x52, 0x48, 0x80, 0x64, 0x96, + 0xcf, 0xf0, 0xa1, 0x66, 0xe8, 0x53, 0xb7, 0xcf, 0x7d, 0x84, 0x3e, 0xfd, + 0x37, 0x0a, 0xa6, 0x57, 0xd9, 0xd6, 0xb6, 0x22, 0xfe, 0xec, 0xef, 0x00, + 0xdb, 0xcf, 0x7f, 0x07, 0x80, 0x64, 0x08, 0x58, 0xbb, 0x04, 0x67, 0x0a, + 0xb8, 0x7a, 0x83, 0xa9, 0xc3, 0x2e, 0xce, 0xb8, 0x27, 0x7c, 0x4e, 0xe5, + 0x32, 0x32, 0x14, 0x0a, 0xa0, 0xd5, 0xab, 0x2a, 0x30, 0x43, 0xd9, 0x22, + 0x94, 0x06, 0xed, 0xbb, 0xd7, 0xdf, 0x40, 0x19, 0x34, 0x99, 0x49, 0x14, + 0xe9, 0xd4, 0x80, 0x24, 0xa7, 0x4d, 0xdb, 0x1f, 0x89, 0x99, 0x59, 0xcc, + 0xb2, 0x01, 0x18, 0x16, 0x6c, 0x5c, 0x24, 0x59, 0x5c, 0xab, 0xcd, 0x42, + 0x06, 0x57, 0x52, 0xec, 0x2e, 0x99, 0x61, 0x93, 0x69, 0xb3, 0xcf, 0x49, + 0xf7, 0x61, 0xaa, 0x55, 0xad, 0x1e, 0x29, 0x93, 0x79, 0x99, 0x92, 0x06, + 0x8f, 0x0d, 0xff, 0xeb, 0x3f, 0x91, 0xc2, 0x16, 0x2f, 0x31, 0xb3, 0xe1, + 0x9c, 0xd6, 0x87, 0x87, 0xc5, 0x5a, 0xdc, 0x17, 0x16, 0xcd, 0x67, 0xc1, + 0x41, 0x15, 0xae, 0x12, 0xeb, 0xf0, 0x51, 0x21, 0x5f, 0x96, 0x55, 0x61, + 0xb1, 0x4a, 0xe6, 0x50, 0xc2, 0x61, 0x47, 0xbf, 0x1d, 0x7a, 0xe4, 0x13, + 0x20, 0x83, 0xd9, 0xbd, 0x0e, 0xe6, 0x3b, 0xe3, 0x72, 0x62, 0xca, 0xce, + 0xa7, 0xc7, 0x21, 0x21, 0x75, 0xed, 0xc9, 0x21, 0xc3, 0xfa, 0x7e, 0xdd, + 0x90, 0x88, 0x41, 0x91, 0x48, 0x48, 0xae, 0x36, 0x16, 0x5f, 0x8a, 0x67, + 0xd5, 0xf6, 0x05, 0xe0, 0xd6, 0xbd, 0x6b, 0x44, 0xf3, 0x9a, 0xea, 0x0b, + 0xd6, 0x95, 0x6b, 0x57, 0x3a, 0xa0, 0xf4, 0x36, 0x95, 0x0e, 0x66, 0x65, + 0xe4, 0xff, 0x5e, 0x15, 0x4c, 0x7d, 0xfd, 0x60, 0x83, 0xb6, 0xc3, 0x5b, + 0x1f, 0x59, 0x81, 0xc1, 0xc6, 0x92, 0xef, 0x2d, 0x3d, 0x8f, 0x11, 0xf1, + 0xaa, 0xaa, 0x3d, 0x0d, 0xda, 0xdd, 0x50, 0xc1, 0x0f, 0x59, 0x0f, 0x9e, + 0x2e, 0x81, 0x36, 0x52, 0x53, 0x26, 0x83, 0x56, 0xe8, 0x3b, 0xb3, 0xd3, + 0x19, 0xd8, 0xbd, 0x0f, 0xbf, 0x5b, 0xc8, 0xb3, 0x69, 0x64, 0x8f, 0x15, + 0x09, 0xf7, 0x95, 0x32, 0xe6, 0x3c, 0xbd, 0x0a, 0xe5, 0xea, 0xab, 0x2e, + 0x32, 0x7f, 0xeb, 0x1f, 0x1c, 0x04, 0xc9, 0x5d, 0x07, 0x5f, 0x08, 0x1c, + 0x73, 0xed, 0x1b, 0x9a, 0x98, 0xad, 0xe5, 0x04, 0xea, 0x6e, 0x06, 0xeb, + 0x58, 0x15, 0x5e, 0x45, 0xa8, 0x57, 0x07, 0x89, 0xd1, 0x22, 0x45, 0x90, + 0x24, 0xe1, 0xf9, 0x7f, 0x2c, 0xd3, 0x37, 0x07, 0x1d, 0x95, 0xae, 0xf8, + 0x26, 0x09, 0x0f, 0xe2, 0x4a, 0xfd, 0xcb, 0x93, 0x25, 0xde, 0x6a, 0x1a, + 0x0a, 0xbf, 0x52, 0x7d, 0x35, 0x11, 0x99, 0xf6, 0x2f, 0xe5, 0xa8, 0xd1, + 0x2b, 0x91, 0x03, 0x23, 0xe9, 0x51, 0x15, 0x23, 0x88, 0xfd, 0xe9, 0x1d, + 0x6b, 0xcd, 0x3c, 0x26, 0x8d, 0xcc, 0x33, 0xc1, 0xa4, 0x2f, 0xa8, 0xee, + 0x4e, 0xd0, 0xba, 0x70, 0x44, 0xa9, 0xb4, 0xdb, 0x36, 0x6a, 0xdc, 0x15, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xdf, 0xf8, 0xb6, 0x37, + 0x83, 0x15, 0x18, 0xc7, 0x32, 0xb0, 0xda, 0xea, 0x4c, 0x31, 0x77, 0x20, + 0xca, 0xc7, 0x41, 0xd3, 0xd7, 0x88, 0xa4, 0x7c, 0x59, 0xe2, 0xa2, 0x71, + 0x91, 0xe0, 0xd0, 0x2c, 0x90, 0x2d, 0x4d, 0xae, 0xe3, 0x91, 0x0f, 0x7e, + 0x0d, 0x6f, 0xbd, 0xfb, 0x90, 0xe5, 0x74, 0x90, 0x18, 0x4c, 0x67, 0xf3, + 0x7a, 0x38, 0x1c, 0x27, 0x0a, 0xea, 0x4f, 0xba, 0x15, 0xb1, 0x7a, 0x27, + 0x02, 0x7f, 0xa2, 0x4a, 0x28, 0x59, 0xb4, 0x91, 0x67, 0xe1, 0xf3, 0x1e, + 0xd9, 0x0a, 0xa9, 0x0f, 0x18, 0xca, 0xf8, 0xa9, 0xdc, 0x02, 0x19, 0xd8, + 0x0e, 0xc6, 0x26, 0x09, 0x29, 0x82, 0xc7, 0x1e, 0xee, 0x51, 0xd8, 0x32, + 0x60, 0x78, 0x00, 0x6b, 0x0d, 0x37, 0x8d, 0x03, 0x34, 0x04, 0x16, 0x40, + 0x47, 0xd3, 0x1e, 0xaa, 0x1c, 0x68, 0x7a, 0x15, 0x18, 0x3b, 0xc7, 0x12, + 0x55, 0x40, 0xe7, 0x11, 0xa4, 0x82, 0x33, 0xc6, 0xa1, 0x85, 0xdf, 0x5c, + 0x78, 0xee, 0xe8, 0x0e, 0x75, 0x6a, 0xc4, 0x6e, 0x6f, 0xa5, 0xb7, 0x81, + 0xe4, 0xe3, 0xd4, 0x85, 0x1e, 0xe1, 0xf5, 0xae, 0xb7, 0xa2, 0x32, 0x05, + 0xc8, 0xc5, 0x5d, 0x21, 0xf2, 0x05, 0x11, 0x67, 0x4c, 0x84, 0xce, 0x4c, + 0xa7, 0xa8, 0xe6, 0xc9, 0x6f, 0x1f, 0x25, 0x66, 0xd9, 0xed, 0xc0, 0x68, + 0x22, 0xb4, 0xe7, 0xaf, 0x4c, 0x51, 0x1d, 0x08, 0xbe, 0x30, 0x00, 0xe8, + 0xb2, 0x9a, 0x46, 0x0b, 0x46, 0x6b, 0x96, 0xd8, 0xab, 0x9e, 0x7f, 0xd9, + 0xa7, 0xf9, 0x69, 0xb6, 0x49, 0x07, 0x6b, 0x4f, 0x7f, 0x96, 0xa7, 0x54, + 0xc0, 0x96, 0x0e, 0x12, 0x21, 0x3b, 0x5f, 0xd2, 0xa6, 0x11, 0x04, 0xbf, + 0xe1, 0x71, 0x19, 0x2f, 0x50, 0xf1, 0x38, 0x04, 0x6a, 0x50, 0x97, 0x5f, + 0x66, 0xd3, 0xae, 0xe7, 0x8e, 0x27, 0xc5, 0x30, 0x87, 0x2a, 0x6f, 0x08, + 0xad, 0x81, 0x5d, 0x62, 0x6f, 0xb1, 0xfe, 0x21, 0xc6, 0x84, 0x7b, 0xcf, + 0xea, 0x88, 0x29, 0x11, 0x22, 0xb2, 0xae, 0xb6, 0x54, 0x21, 0x7d, 0x0f, + 0x60, 0xe0, 0x6b, 0xac, 0xa4, 0x8e, 0x67, 0x02, 0xf5, 0x58, 0x98, 0x73, + 0x0f, 0x14, 0x0e, 0xd7, 0x99, 0x88, 0xc2, 0x0a, 0xc6, 0xd5, 0xb2, 0x6f, + 0x9a, 0xcc, 0x55, 0xa4, 0x21, 0xdc, 0xd9, 0xfc, 0xb0, 0xba, 0xed, 0xce, + 0x2b, 0x53, 0x56, 0x1d, 0x03, 0xdb, 0x32, 0x73, 0x0b, 0x6e, 0xe4, 0x69, + 0xbf, 0xc6, 0x43, 0x66, 0x11, 0x82, 0x32, 0xe1, 0xd3, 0xb4, 0xa8, 0xf7, + 0xa2, 0xb4, 0xb6, 0x92, 0x13, 0x7e, 0x1f, 0x25, 0x4b, 0x07, 0x37, 0x27, + 0x3b, 0x38, 0x1a, 0xda, 0x7b, 0xe4, 0x0d, 0xfe, 0x08, 0x8d, 0xc0, 0x03, + 0x16, 0x5c, 0x11, 0x66, 0xe9, 0xdd, 0x5a, 0x66, 0xd8, 0xc4, 0x3c, 0xc8, + 0x84, 0xe1, 0xf8, 0x9d, 0xae, 0x17, 0x04, 0x0a, 0xe1, 0xbf, 0x1b, 0x91, + 0x89, 0x7f, 0xf5, 0xce, 0x46, 0x0d, 0x42, 0x20, 0x4e, 0x0f, 0xc1, 0x05, + 0x42, 0xff, 0x14, 0x43, 0x17, 0x82, 0x68, 0x64, 0x8b, 0xb2, 0x94, 0x03, + 0x4a, 0xdd, 0x8e, 0x00, 0x93, 0x7a, 0xf8, 0x11, 0xe8, 0x46, 0x59, 0x04, + 0x4b, 0x84, 0xc0, 0xbf, 0xce, 0xe5, 0x2b, 0x85, 0xb3, 0x82, 0x26, 0x16, + 0x06, 0x2d, 0x2d, 0xd9, 0x02, 0xa7, 0xe8, 0x24, 0x34, 0xb1, 0x62, 0x03, + 0x0e, 0x73, 0xf6, 0x7c, 0xac, 0x9f, 0x49, 0xd8, 0x44, 0x66, 0x06, 0x90, + 0xe7, 0x10, 0xdd, 0xf0, 0xc7, 0x01, 0xc0, 0x75, 0x89, 0x48, 0xe0, 0x39, + 0x7c, 0xf5, 0x87, 0x2d, 0x32, 0x97, 0x1b, 0x12, 0xbd, 0xc4, 0xe2, 0x70, + 0xe5, 0x3a, 0xf0, 0x53, 0xe7, 0x5f, 0x1b, 0xc8, 0x06, 0x21, 0xd2, 0xa3, + 0x18, 0xc4, 0x13, 0x55, 0x72, 0x21, 0x3a, 0xcc, 0xf1, 0xcc, 0x13, 0x34, + 0xba, 0xca, 0xbc, 0x0c, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0xb4, 0xde, 0x0a, 0xb2, 0x1a, 0x1a, 0x64, 0xee, 0xbe, 0x75, 0xc7, 0xc6, + 0xcf, 0xa8, 0x60, 0xa6, 0x5e, 0x24, 0x82, 0xe4, 0x95, 0x8d, 0x98, 0xb1, + 0xe5, 0x74, 0xe5, 0xd2, 0x0b, 0x7d, 0x3c, 0x25, 0x5f, 0x32, 0xde, 0x49, + 0x1c, 0x7a, 0x26, 0xaf, 0x23, 0x8a, 0xae, 0x96, 0x3d, 0x99, 0x4d, 0x45, + 0xdd, 0x4f, 0x53, 0x90, 0xa6, 0xee, 0x70, 0x88, 0x3d, 0xe5, 0xeb, 0xa2, + 0x89, 0xc4, 0xdd, 0x20, 0xc9, 0x9b, 0x59, 0x2e, 0x78, 0x3c, 0xe9, 0x98, + 0xd5, 0x78, 0x69, 0x4c, 0xcd, 0xdd, 0x3f, 0x86, 0xd7, 0x4b, 0xbb, 0x2e, + 0x5f, 0xb5, 0xba, 0xbf, 0x97, 0xfb, 0xc8, 0x9c, 0x0a, 0x54, 0x59, 0x2f, + 0x04, 0x13, 0x4d, 0x64, 0x86, 0x85, 0x9b, 0x12, 0xe1, 0x77, 0xa2, 0x0b, + 0x51, 0x53, 0x0c, 0x57, 0x46, 0xb2, 0x03, 0x16, 0xc2, 0x41, 0x2c, 0xae, + 0x6c, 0xa7, 0xee, 0x57, 0x69, 0xc5, 0x44, 0x08, 0x29, 0x3c, 0x30, 0xb7, + 0x7d, 0xfe, 0x7c, 0x3f, 0xc4, 0x94, 0xde, 0xb0, 0xbc, 0x24, 0xa7, 0x4b, + 0x1f, 0xab, 0xdf, 0xad, 0xff, 0x7a, 0xfe, 0x2f, 0xc2, 0xde, 0x93, 0x56, + 0x9f, 0x7a, 0xe5, 0x08, 0xf4, 0x3e, 0xec, 0x57, 0x70, 0x86, 0x3f, 0x2d, + 0x34, 0x85, 0xd1, 0x54, 0x03, 0xef, 0xdf, 0xd5, 0x0e, 0x1a, 0x87, 0xaa, + 0xd0, 0x5b, 0xb3, 0x8a, 0x48, 0xd8, 0x30, 0x23, 0x8f, 0xea, 0xc8, 0x0e, + 0xb2, 0x0c, 0x20, 0xef, 0x48, 0x29, 0x96, 0x8b, 0x47, 0x74, 0x6a, 0x38, + 0xed, 0x5f, 0x60, 0xc4, 0x5f, 0x1f, 0x47, 0x67, 0x37, 0x4e, 0x12, 0x3f, + 0xe8, 0x22, 0xbd, 0x2d, 0xb2, 0x21, 0xda, 0x1b, 0x21, 0x65, 0x8b, 0xac, + 0xfa, 0xac, 0x00, 0x07, 0x94, 0xb0, 0x2c, 0x12, 0x75, 0xf5, 0x13, 0x83, + 0xdd, 0xa0, 0xc9, 0x68, 0xb9, 0xad, 0xcc, 0xc0, 0x6e, 0x87, 0x60, 0x31, + 0xff, 0xb8, 0x6f, 0x0e, 0xcf, 0xad, 0xbe, 0x01, 0x61, 0x01, 0x40, 0x1a, + 0x50, 0xf7, 0x2f, 0x8b, 0x2b, 0xf0, 0x14, 0x94, 0x68, 0x18, 0xf9, 0xa4, + 0xf9, 0x8f, 0xc2, 0xf1, 0x97, 0xc0, 0x30, 0x00, 0x62, 0x0c, 0x1e, 0x1f, + 0x7f, 0x82, 0x78, 0x1a, 0x81, 0x71, 0xd6, 0x0a, 0x67, 0x79, 0xb6, 0x12, + 0xc9, 0xd9, 0x01, 0xe1, 0x11, 0xb1, 0x64, 0x23, 0xaf, 0x3b, 0xd7, 0x16, + 0x87, 0x65, 0xb5, 0x9b, 0x72, 0xf7, 0xa0, 0x1c, 0x80, 0x35, 0x69, 0xe0, + 0x6f, 0x45, 0x0a, 0x44, 0x75, 0x0a, 0xde, 0x53, 0x02, 0xb4, 0x34, 0xb4, + 0x4b, 0x55, 0xc9, 0xa5, 0xbe, 0xb5, 0x8b, 0x7a, 0x41, 0x47, 0x5b, 0x5c, + 0x10, 0x06, 0xa1, 0x07, 0xa9, 0xd5, 0xc8, 0xdd, 0xa5, 0x65, 0xba, 0xc8, + 0x1f, 0x68, 0xdb, 0x3d, 0x5d, 0xb8, 0xa5, 0x3b, 0xe2, 0x9f, 0x92, 0x84, + 0x26, 0xe3, 0x6d, 0xb4, 0x66, 0x92, 0x85, 0x3c, 0x71, 0xa4, 0xc5, 0x22, + 0x70, 0xcd, 0xab, 0xd6, 0x44, 0x21, 0x72, 0xbc, 0xf6, 0x5b, 0x49, 0x55, + 0x2f, 0x05, 0xe7, 0x8f, 0x5b, 0xee, 0x0f, 0x58, 0xcc, 0x4f, 0xf8, 0x28, + 0x67, 0xc1, 0x63, 0x70, 0x24, 0x81, 0xa5, 0x19, 0x8a, 0x0f, 0x43, 0x23, + 0xc9, 0x22, 0x8d, 0xee, 0x19, 0xbb, 0xb2, 0x94, 0xa7, 0x09, 0xdb, 0xb7, + 0xab, 0x41, 0x5b, 0xf1, 0x9a, 0x44, 0xb9, 0xa7, 0x77, 0xf1, 0x73, 0x3b, + 0xd5, 0x7b, 0x1c, 0x06, 0x3e, 0xd3, 0x5f, 0xce, 0xc1, 0xec, 0xf1, 0x9a, + 0x4d, 0x55, 0xaf, 0xd2, 0x54, 0x52, 0x84, 0x13, 0xe4, 0x6b, 0xc6, 0x04, + 0x41, 0x07, 0x60, 0x2f, 0xf9, 0x78, 0xbd, 0x77, 0x1e, 0x95, 0x0c, 0x06, + 0xb8, 0xe0, 0x70, 0x49, 0x92, 0x1e, 0x4c, 0x7d, 0x57, 0xad, 0xe5, 0x93, + 0x87, 0xea, 0xcb, 0x78, 0x8e, 0xad, 0xba, 0x2b, 0xc8, 0xdd, 0x2c, 0xc7, + 0xa7, 0xce, 0x8e, 0x23, 0xb9, 0x23, 0xaa, 0x24, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x4f, 0x07, 0x98, 0x1d, 0x5f, 0x86, 0xfe, 0x90, + 0x57, 0x79, 0xa0, 0x08, 0x4b, 0xed, 0x3d, 0xf7, 0x47, 0x2c, 0x64, 0xbf, + 0x06, 0x69, 0x1e, 0xba, 0x6f, 0xd4, 0x86, 0x9e, 0x1e, 0xb0, 0x52, 0x30, + 0x5a, 0x0c, 0x7a, 0x36, 0xf1, 0x1a, 0x57, 0x4b, 0x8d, 0x9f, 0x07, 0x8c, + 0x76, 0x9b, 0x45, 0xe1, 0x27, 0x08, 0xab, 0x4e, 0xed, 0x59, 0xae, 0xb3, + 0x2d, 0xec, 0x18, 0x23, 0xf2, 0x39, 0xbd, 0x18, 0x5b, 0x76, 0x20, 0x48, + 0xa4, 0x3d, 0xd4, 0x9b, 0x1d, 0x32, 0xfe, 0x20, 0xad, 0xa9, 0x1c, 0x78, + 0x08, 0xeb, 0xb2, 0x32, 0x14, 0xde, 0x56, 0x66, 0xba, 0x4c, 0x6e, 0x54, + 0xa7, 0x66, 0x8d, 0x26, 0xdc, 0x7b, 0x05, 0x10, 0xf1, 0xa4, 0x73, 0xc3, + 0x25, 0xd2, 0x8c, 0x61, 0x16, 0xfd, 0x58, 0x5d, 0x38, 0x2a, 0xd3, 0xc0, + 0xbb, 0xb5, 0x08, 0xd8, 0xa8, 0xea, 0x30, 0x41, 0xd3, 0x32, 0xb3, 0x16, + 0x0e, 0x9f, 0x8a, 0x5b, 0xeb, 0x58, 0x69, 0x49, 0xd3, 0xf6, 0xcd, 0xc1, + 0x59, 0xfe, 0x0b, 0xe4, 0x21, 0x75, 0x9b, 0xdc, 0xec, 0xb0, 0x5a, 0x21, + 0xa8, 0xb5, 0xc9, 0x90, 0x6e, 0xe4, 0xe0, 0x0f, 0x38, 0x38, 0xd7, 0x3b, + 0x87, 0x13, 0x26, 0xa9, 0x30, 0x08, 0x3d, 0x8c, 0x6f, 0x36, 0xd9, 0xf5, + 0x54, 0x99, 0xff, 0xb3, 0x21, 0xda, 0x55, 0x2d, 0xb2, 0x1f, 0x95, 0x1e, + 0xe1, 0x57, 0x1e, 0x0e, 0xbf, 0xe5, 0xde, 0x49, 0x02, 0x78, 0x34, 0x95, + 0xa6, 0xe7, 0x35, 0x4c, 0x83, 0x8d, 0xb2, 0x47, 0x62, 0x08, 0x96, 0x00, + 0x80, 0x16, 0x6e, 0x85, 0x23, 0x2a, 0x8f, 0xac, 0x63, 0x5a, 0xc1, 0x10, + 0x25, 0x39, 0x13, 0xfd, 0x1a, 0x94, 0x49, 0xd1, 0x15, 0x66, 0xe4, 0x9b, + 0xc1, 0x75, 0x30, 0x6d, 0x7a, 0xf5, 0xde, 0x7b, 0xbf, 0x1e, 0xf8, 0x1c, + 0xc1, 0xec, 0x0d, 0x1e, 0x43, 0x1e, 0x0a, 0x0c, 0xa9, 0x7f, 0x01, 0xd9, + 0x26, 0xf1, 0xde, 0x53, 0xbc, 0xf2, 0x87, 0xfc, 0xae, 0xa7, 0x30, 0xfc, + 0x5d, 0xfd, 0x40, 0x15, 0x3b, 0xda, 0x6c, 0x11, 0x3a, 0x0b, 0xd9, 0x4a, + 0xd8, 0x57, 0x40, 0x17, 0xe7, 0x6f, 0x36, 0x3a, 0x81, 0xb5, 0x22, 0x71, + 0x86, 0x1f, 0x68, 0x59, 0xb6, 0x11, 0x12, 0x81, 0xe3, 0x89, 0xe2, 0xb0, + 0x43, 0xbd, 0x99, 0x8e, 0xd8, 0x58, 0x58, 0x7f, 0x36, 0x19, 0x1c, 0x04, + 0x90, 0xea, 0x6f, 0xf6, 0x58, 0x61, 0xab, 0xaf, 0x4d, 0x01, 0xa1, 0xf0, + 0xf5, 0xcc, 0x34, 0xc8, 0x3b, 0xff, 0xbb, 0x5b, 0xba, 0x30, 0x83, 0x46, + 0x4b, 0x47, 0xb2, 0x4d, 0x2e, 0xf3, 0xc9, 0x16, 0x55, 0x12, 0x0c, 0x95, + 0x04, 0x74, 0x31, 0x8f, 0x50, 0x27, 0xf0, 0xaa, 0x3d, 0x82, 0x61, 0xcd, + 0x00, 0xe1, 0x5d, 0x6c, 0xbf, 0xd4, 0x24, 0x50, 0x2f, 0x56, 0x2d, 0x60, + 0x0f, 0x5a, 0x6a, 0x12, 0xff, 0x93, 0xfc, 0x83, 0xb1, 0x65, 0x12, 0x8f, + 0x67, 0xc8, 0x17, 0xab, 0x28, 0x85, 0xb6, 0x23, 0x62, 0xb6, 0x42, 0xda, + 0xa0, 0x95, 0x93, 0x97, 0x13, 0xfb, 0xe0, 0xca, 0x18, 0x1a, 0xe5, 0x2a, + 0x84, 0xfa, 0xdf, 0x22, 0xe0, 0xd4, 0x88, 0x22, 0x32, 0x7a, 0x84, 0xba, + 0x33, 0x19, 0xc1, 0x27, 0xae, 0x48, 0xfd, 0xd1, 0x65, 0x9d, 0x64, 0x71, + 0x89, 0x82, 0x91, 0x12, 0x27, 0xd1, 0x9d, 0x23, 0xd9, 0x83, 0x81, 0x4b, + 0x93, 0x59, 0xb9, 0xb3, 0x7b, 0xb6, 0x9e, 0x07, 0x1b, 0xfd, 0xfb, 0x43, + 0xff, 0xfb, 0xd4, 0xcd, 0x84, 0xd5, 0x18, 0x6a, 0xbe, 0xd4, 0xf1, 0x00, + 0xff, 0xb7, 0xa2, 0x17, 0xa6, 0x6f, 0xa9, 0x23, 0x8a, 0x89, 0x2e, 0x76, + 0xac, 0x26, 0x69, 0x54, 0x10, 0xd8, 0xdb, 0xdb, 0x3e, 0x4e, 0xc2, 0x66, + 0x3f, 0xd0, 0x4b, 0x22, 0x6a, 0x34, 0xfb, 0x49, 0x88, 0x34, 0x08, 0x19, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xb6, 0x92, 0xc5, 0xd0, + 0x1d, 0xad, 0xab, 0xdf, 0x51, 0x7c, 0x63, 0x64, 0x94, 0x29, 0xd2, 0x9a, + 0xfe, 0xbc, 0x93, 0x3b, 0xb5, 0xe9, 0xab, 0x91, 0x49, 0x08, 0x54, 0x30, + 0xcb, 0xc1, 0xfd, 0x1b, 0x80, 0x5b, 0x32, 0xf8, 0x26, 0xa6, 0xff, 0x42, + 0x1d, 0x15, 0x56, 0x72, 0xb3, 0x5e, 0x54, 0x91, 0xdd, 0x38, 0xa0, 0xe2, + 0xb0, 0x5b, 0x6f, 0xa9, 0x3c, 0x71, 0xe2, 0x4e, 0xd4, 0xc1, 0x40, 0x27, + 0xe6, 0xf5, 0x55, 0x4a, 0xae, 0xce, 0x8f, 0x3d, 0xc1, 0xd2, 0x88, 0xb9, + 0xc9, 0xbc, 0xe9, 0x06, 0x74, 0x08, 0x8a, 0xce, 0xaf, 0xd1, 0xcf, 0x8c, + 0xa1, 0xab, 0xd0, 0x5f, 0x22, 0xfc, 0xb4, 0x27, 0xa2, 0x7c, 0x26, 0xc0, + 0x7c, 0xbe, 0x1b, 0x85, 0x2c, 0xaf, 0xe2, 0x87, 0xd8, 0x75, 0x5f, 0x2c, + 0xd4, 0x00, 0xac, 0xc6, 0x40, 0xe9, 0x32, 0x12, 0xaa, 0x26, 0x6e, 0x8d, + 0x5c, 0xf8, 0xc3, 0x08, 0xd7, 0xa6, 0xe8, 0xfb, 0x7d, 0x53, 0x9a, 0x47, + 0xb5, 0x62, 0xd7, 0x3c, 0x97, 0x17, 0x5c, 0xea, 0x68, 0x97, 0x06, 0x9b, + 0x99, 0x94, 0x7a, 0xb4, 0xce, 0xd7, 0xd1, 0xff, 0x44, 0x33, 0x4b, 0x10, + 0x96, 0x6e, 0x08, 0xf6, 0x66, 0x2c, 0xcb, 0x71, 0xa3, 0x68, 0x29, 0xe2, + 0x11, 0xb0, 0xc1, 0xe9, 0x94, 0xd2, 0x57, 0x3c, 0x37, 0x83, 0xe9, 0x11, + 0xd6, 0x81, 0xa2, 0x0e, 0x7f, 0xda, 0x21, 0x07, 0x9c, 0x21, 0x69, 0x44, + 0x5b, 0xaa, 0x3b, 0x4e, 0xe0, 0x47, 0x07, 0xaa, 0x87, 0xcd, 0x4c, 0xc9, + 0x7c, 0x6e, 0xb3, 0x3c, 0x31, 0x3c, 0x11, 0x90, 0x40, 0x27, 0x9c, 0x9a, + 0xed, 0xf9, 0x40, 0x20, 0x9c, 0x85, 0xdb, 0xc7, 0xbf, 0xa5, 0x07, 0xf4, + 0x22, 0xbc, 0x98, 0x9c, 0x25, 0x30, 0x19, 0xbf, 0xdd, 0x48, 0xd6, 0x52, + 0x51, 0xf4, 0xe7, 0x8e, 0xf6, 0x6e, 0x1f, 0x3c, 0x24, 0x20, 0x11, 0x1c, + 0xb6, 0x32, 0x75, 0xfc, 0x77, 0x96, 0x4e, 0x6c, 0x94, 0xcb, 0x08, 0x69, + 0xc6, 0xa7, 0x08, 0x20, 0xe5, 0xa7, 0x57, 0x08, 0x82, 0xaf, 0x46, 0x40, + 0x41, 0x3f, 0x78, 0x96, 0x90, 0x92, 0xbd, 0x04, 0xc7, 0xbd, 0x6d, 0x6c, + 0xb6, 0xfd, 0xcf, 0xab, 0xc7, 0xdc, 0x7b, 0xee, 0xfd, 0x7d, 0x7e, 0x41, + 0xb5, 0x58, 0x1e, 0x60, 0x7d, 0xb4, 0x49, 0xb5, 0xff, 0x46, 0x7b, 0x13, + 0xa2, 0xd9, 0x91, 0x21, 0x54, 0x28, 0xa5, 0xb0, 0x85, 0xc3, 0xba, 0xd0, + 0x96, 0xe5, 0x1a, 0x08, 0xf5, 0xce, 0x32, 0x14, 0x53, 0x45, 0x4b, 0x6a, + 0x94, 0x9e, 0x43, 0xab, 0x45, 0xa4, 0xe7, 0xc2, 0x0b, 0xb3, 0x33, 0x10, + 0x1d, 0x4c, 0x8f, 0xd9, 0x88, 0x71, 0x83, 0x27, 0x45, 0xfa, 0x2d, 0xd4, + 0x46, 0x6c, 0x9f, 0xb4, 0xdb, 0xed, 0xdf, 0x49, 0x35, 0xd7, 0x66, 0x62, + 0x54, 0x88, 0x59, 0xe3, 0xb5, 0x65, 0xf2, 0x01, 0x0d, 0xdc, 0x43, 0xdd, + 0x62, 0x8d, 0x5b, 0xb7, 0x18, 0x1d, 0xe0, 0xf3, 0xa2, 0xbf, 0x35, 0xcb, + 0xb3, 0x5d, 0x0a, 0x81, 0x8a, 0x8f, 0x28, 0xfd, 0xb3, 0xb2, 0x12, 0x64, + 0x3b, 0x3a, 0xa2, 0x17, 0x4b, 0xab, 0xbd, 0x40, 0xcf, 0x24, 0xbb, 0x3c, + 0xe5, 0x9a, 0xda, 0x30, 0x55, 0x15, 0x57, 0xe0, 0xcc, 0xcf, 0xa1, 0x4c, + 0x97, 0xa4, 0x55, 0xe2, 0x1e, 0x8a, 0x5d, 0xda, 0x40, 0xe4, 0x27, 0x1c, + 0x04, 0x02, 0xb1, 0xd7, 0x7c, 0x32, 0xba, 0x05, 0xdd, 0x1f, 0x45, 0xd8, + 0xde, 0xc0, 0x12, 0xc4, 0xae, 0x61, 0xda, 0xff, 0x4b, 0x87, 0x26, 0xb9, + 0xb0, 0x94, 0x2a, 0x74, 0x86, 0x7c, 0x3f, 0x0d, 0x2a, 0x56, 0xff, 0x45, + 0x4f, 0xb5, 0x14, 0x73, 0xa1, 0x49, 0x93, 0x08, 0x6c, 0xd8, 0xc7, 0xc2, + 0x0e, 0x05, 0xcc, 0xbc, 0x6a, 0xf4, 0x32, 0xd1, 0x24, 0xca, 0x5a, 0x62, + 0xfc, 0xb0, 0x10, 0x25, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x8a, 0x87, 0xc7, 0x1a, 0x5f, 0x7b, 0xf4, 0xc4, 0x76, 0x3b, 0x99, 0x42, + 0x3e, 0x68, 0xc3, 0x90, 0x1d, 0x10, 0x6f, 0xfa, 0x77, 0x89, 0xa5, 0xc2, + 0xca, 0x07, 0x32, 0xef, 0x75, 0x9a, 0x6c, 0x00, 0xc9, 0xba, 0x56, 0x46, + 0x93, 0x55, 0xf0, 0x06, 0xb2, 0x12, 0x9d, 0x59, 0x76, 0x7e, 0x3f, 0x7d, + 0x05, 0x31, 0xf7, 0x5f, 0x77, 0xf1, 0x0f, 0xb9, 0xf4, 0xef, 0x18, 0x4e, + 0x33, 0xd2, 0x0a, 0x2f, 0x23, 0x71, 0x98, 0x1f, 0x07, 0x56, 0x26, 0x63, + 0xb9, 0x35, 0x7c, 0x78, 0x17, 0x00, 0xae, 0x7f, 0x90, 0x45, 0x95, 0xf5, + 0x83, 0xb4, 0x34, 0x2d, 0x1c, 0x78, 0xa0, 0x48, 0xbe, 0x66, 0x6e, 0x23, + 0x7d, 0x98, 0x18, 0xbd, 0x7e, 0xf3, 0xb8, 0xdf, 0xb8, 0xd5, 0x84, 0xdb, + 0x99, 0xa8, 0x1b, 0xff, 0x73, 0x8c, 0x65, 0x1f, 0x59, 0x73, 0xe8, 0x4f, + 0x66, 0xe3, 0xc7, 0x27, 0xc8, 0xe1, 0x4d, 0x06, 0xd0, 0x27, 0x25, 0xfa, + 0x1b, 0x92, 0xdb, 0x61, 0xb5, 0x56, 0xd2, 0xda, 0xc5, 0xda, 0x1e, 0x6f, + 0xa0, 0xe5, 0x74, 0x14, 0x4c, 0x43, 0x96, 0x54, 0xbd, 0xcc, 0x07, 0xd9, + 0x4b, 0xf8, 0x0a, 0x10, 0x88, 0x14, 0x81, 0xff, 0x5f, 0xcf, 0x3d, 0x7e, + 0x01, 0xb7, 0x9a, 0x0a, 0x69, 0x59, 0xe9, 0x62, 0x0c, 0xd8, 0xc3, 0x26, + 0x8e, 0x96, 0xa5, 0x2c, 0x1b, 0x68, 0x36, 0x09, 0x0b, 0x94, 0xfb, 0x07, + 0x15, 0x5f, 0xe0, 0x6a, 0xf8, 0x85, 0xb1, 0xd8, 0x29, 0xd0, 0xcd, 0x72, + 0xad, 0x52, 0xb6, 0x67, 0x5e, 0x2e, 0xb8, 0x0b, 0x0b, 0x0a, 0xd5, 0x6d, + 0x38, 0x25, 0xe4, 0x9e, 0x43, 0xc2, 0x40, 0x08, 0x0a, 0x93, 0x67, 0x64, + 0x01, 0xda, 0x7d, 0xd8, 0x1f, 0x16, 0x69, 0xc1, 0x12, 0xc2, 0x5b, 0xfe, + 0x7a, 0xe6, 0x90, 0x0a, 0x41, 0xbd, 0x3b, 0xd6, 0x51, 0x63, 0x81, 0xd6, + 0xab, 0xc1, 0xf5, 0x1a, 0xcf, 0x0c, 0x68, 0x80, 0x62, 0x01, 0x17, 0x94, + 0x6d, 0x2a, 0x6c, 0xc4, 0x7e, 0x7a, 0x0d, 0x27, 0xf0, 0xdb, 0x51, 0xd2, + 0x62, 0x6c, 0x33, 0x57, 0x4e, 0xe3, 0xbd, 0xa3, 0x4b, 0xb0, 0x5f, 0x0d, + 0xd3, 0x1b, 0x17, 0x0b, 0xf4, 0x10, 0xe7, 0xf2, 0x43, 0x3d, 0x0e, 0x29, + 0xa3, 0x31, 0x14, 0xc5, 0xa6, 0xc0, 0xf3, 0x38, 0x19, 0xda, 0x08, 0x5e, + 0x19, 0x40, 0x57, 0x4c, 0x8d, 0xc7, 0x79, 0x10, 0xa5, 0x49, 0x4c, 0xce, + 0x75, 0x54, 0xd7, 0x45, 0x29, 0xd9, 0x0e, 0xcd, 0xe5, 0x57, 0xbe, 0x9a, + 0x18, 0xe0, 0x95, 0x1e, 0xd8, 0x7f, 0xac, 0xc0, 0xd0, 0x2a, 0xa5, 0x94, + 0x6d, 0xfc, 0xa8, 0x2e, 0xc1, 0xcd, 0xa0, 0xea, 0x61, 0x90, 0x20, 0xca, + 0x0c, 0x0b, 0x14, 0xbe, 0xba, 0xd9, 0x4a, 0x3e, 0x0c, 0xec, 0xf3, 0xf7, + 0xb4, 0xc0, 0x7f, 0x0e, 0x7b, 0x93, 0xc7, 0x63, 0xfd, 0x95, 0x63, 0x06, + 0xef, 0xbd, 0x17, 0x2a, 0xce, 0x23, 0xf7, 0x88, 0xf1, 0x39, 0xc0, 0xb2, + 0x1d, 0xf8, 0xf6, 0x3d, 0x27, 0x9d, 0x0f, 0x5d, 0x56, 0x97, 0x64, 0xf8, + 0x52, 0x7c, 0x19, 0x7e, 0x9f, 0x48, 0xe3, 0x03, 0x2a, 0x13, 0xa1, 0x00, + 0x6b, 0x0f, 0xda, 0xc2, 0x37, 0xb3, 0x42, 0xd0, 0x47, 0x43, 0x41, 0xdd, + 0xd5, 0xb2, 0xd2, 0x41, 0xda, 0xac, 0x23, 0x95, 0xb8, 0x61, 0x2c, 0x67, + 0x8e, 0xb5, 0x82, 0x1d, 0xc5, 0x50, 0x78, 0x87, 0xfe, 0x50, 0x40, 0xde, + 0xeb, 0x82, 0x37, 0xb7, 0x9b, 0x84, 0xb6, 0x4e, 0x70, 0xc8, 0xea, 0x5a, + 0xaa, 0x7f, 0xca, 0x02, 0x04, 0x4c, 0xbb, 0xd4, 0x99, 0x9b, 0x79, 0x1a, + 0x4e, 0x2a, 0x67, 0x61, 0xbc, 0x35, 0x67, 0xc5, 0xb0, 0x06, 0xf6, 0x9f, + 0xeb, 0xf2, 0xcc, 0xd7, 0xf0, 0x8a, 0x2d, 0x95, 0x83, 0xe4, 0x7b, 0x9f, + 0x18, 0x58, 0xd5, 0x7e, 0xb6, 0xf0, 0x55, 0x12, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0xef, 0x24, 0x33, 0x99, 0x88, 0x8b, 0xe6, 0x43, + 0x81, 0xc7, 0x94, 0x6d, 0x12, 0xf0, 0xcd, 0xc1, 0x08, 0x2b, 0x0f, 0x7e, + 0xf8, 0xef, 0x48, 0x2a, 0x92, 0xc5, 0x45, 0x6b, 0xe8, 0x15, 0x42, 0x20, + 0x8c, 0x75, 0xa0, 0x53, 0x9c, 0x7e, 0x08, 0xa1, 0x89, 0x4c, 0xca, 0xef, + 0x49, 0xde, 0x54, 0x62, 0x73, 0x95, 0x4c, 0x4b, 0x75, 0xb1, 0x41, 0x7a, + 0x79, 0x63, 0xe9, 0xb6, 0x4e, 0x90, 0xf4, 0x29, 0x86, 0x8a, 0xff, 0x6a, + 0xc1, 0x1c, 0x00, 0xc7, 0xbf, 0x70, 0x3c, 0xba, 0x65, 0x5d, 0xe1, 0x82, + 0x41, 0xd5, 0xae, 0x77, 0x36, 0x2d, 0xde, 0xce, 0x9a, 0xae, 0xa0, 0xac, + 0x1a, 0x4e, 0x67, 0x2f, 0x99, 0xef, 0x5b, 0xca, 0x30, 0x04, 0x98, 0x3c, + 0x53, 0x15, 0x72, 0xb4, 0xaa, 0xd3, 0xbb, 0xdf, 0xbd, 0x3f, 0xc5, 0xd3, + 0x33, 0x60, 0x95, 0x79, 0x47, 0xc1, 0x0d, 0x07, 0x0f, 0xd4, 0xa3, 0x09, + 0x67, 0x29, 0x29, 0xba, 0xdf, 0x33, 0x4e, 0xf9, 0x73, 0xb5, 0x1c, 0xdb, + 0x37, 0xac, 0xc2, 0xf5, 0xb7, 0x5d, 0xdb, 0xe1, 0x3e, 0x4b, 0x08, 0xac, + 0x31, 0x69, 0x86, 0x96, 0x87, 0x05, 0x55, 0x2e, 0x02, 0x9b, 0x73, 0xb8, + 0x9e, 0x9a, 0xec, 0x4a, 0x4c, 0xe5, 0xc6, 0x88, 0xf6, 0xc9, 0x1d, 0x66, + 0xfd, 0xe3, 0xaf, 0xb6, 0x6f, 0x03, 0xa6, 0x11, 0xdc, 0x1d, 0x58, 0x4d, + 0x56, 0xa6, 0x36, 0x19, 0x4a, 0x4a, 0x0a, 0x0f, 0xf9, 0x25, 0x75, 0xa8, + 0xe5, 0xf5, 0xd8, 0x24, 0x43, 0xd6, 0x7b, 0xc9, 0x23, 0xd3, 0x8b, 0x2d, + 0xbc, 0x0d, 0xd7, 0xe5, 0xa9, 0xa3, 0x53, 0xe8, 0xc3, 0x80, 0x6d, 0x03, + 0x65, 0xe6, 0xe4, 0x76, 0x8c, 0x1b, 0x06, 0x10, 0xf5, 0x81, 0xcb, 0xc2, + 0x15, 0x2a, 0x58, 0x59, 0xfe, 0x1f, 0xd0, 0xfe, 0xd5, 0x58, 0xce, 0xd5, + 0x55, 0x8c, 0x5f, 0x2c, 0xb6, 0x56, 0x43, 0x15, 0x26, 0x46, 0x85, 0xcb, + 0xf4, 0x0e, 0x12, 0x4a, 0xb1, 0x98, 0x0c, 0x0f, 0x6e, 0xcd, 0x47, 0x6e, + 0x95, 0x2e, 0x44, 0xc1, 0x0b, 0xa9, 0x5a, 0x0d, 0x32, 0xed, 0x39, 0x50, + 0xf3, 0x45, 0x91, 0x1a, 0xb0, 0x0e, 0x9f, 0xa7, 0xc9, 0xcf, 0xe9, 0x41, + 0x95, 0xeb, 0xd4, 0xd5, 0x83, 0xb5, 0xa5, 0x7f, 0xf4, 0x83, 0x44, 0xc6, + 0x66, 0x07, 0x5f, 0x0c, 0xf0, 0x6e, 0x74, 0x81, 0x0c, 0xe3, 0x6a, 0x2f, + 0x12, 0x30, 0x69, 0x6a, 0xbe, 0x5c, 0x67, 0xdb, 0x67, 0x44, 0x32, 0x02, + 0x45, 0x95, 0xd8, 0xf0, 0x48, 0xb3, 0x2a, 0x1d, 0xd2, 0x49, 0x32, 0x76, + 0x3d, 0xca, 0xd3, 0xd7, 0xf5, 0x7d, 0x0b, 0x13, 0x74, 0x70, 0xcb, 0x0d, + 0xf7, 0x9c, 0x86, 0xec, 0xd6, 0x91, 0xdf, 0x14, 0xd2, 0xe2, 0x39, 0x24, + 0x23, 0x77, 0x9d, 0xdf, 0xff, 0xad, 0x23, 0x49, 0xbf, 0xf7, 0xbd, 0x94, + 0x54, 0xf1, 0x9a, 0x03, 0xe7, 0x33, 0x64, 0x4a, 0x26, 0xa9, 0x26, 0x1d, + 0x7d, 0xf1, 0x1f, 0x01, 0x89, 0x2d, 0xd1, 0xf4, 0xb3, 0x86, 0x4e, 0x8d, + 0x46, 0x28, 0x62, 0x0c, 0x54, 0x4b, 0x76, 0x12, 0xc0, 0x16, 0x71, 0x2f, + 0xa0, 0x23, 0xb4, 0x9a, 0xd6, 0xba, 0xab, 0xcc, 0xff, 0x02, 0x55, 0x79, + 0x3f, 0x5a, 0xcf, 0x16, 0x93, 0xff, 0xca, 0x49, 0xf5, 0x0f, 0x04, 0x01, + 0xe5, 0xa2, 0xda, 0xab, 0xe0, 0xe1, 0x7f, 0x21, 0x09, 0x1e, 0xed, 0xc2, + 0x6a, 0x49, 0x9c, 0xf3, 0x13, 0x20, 0xfc, 0xa3, 0x50, 0xd3, 0x42, 0x51, + 0x36, 0x79, 0x28, 0xb1, 0xfc, 0xaf, 0x1d, 0xe7, 0x90, 0xbd, 0x94, 0xb8, + 0xa4, 0x89, 0x25, 0x10, 0xb5, 0x88, 0x38, 0x79, 0x35, 0x55, 0x31, 0xa2, + 0x7d, 0x03, 0x66, 0x29, 0xcd, 0xd0, 0x30, 0xd6, 0x11, 0x2b, 0xdd, 0x42, + 0x17, 0x6c, 0x10, 0x51, 0xa6, 0x32, 0x77, 0x01, 0xad, 0x33, 0xbb, 0x09, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x26, 0x5d, 0xf4, 0x31, + 0xeb, 0x90, 0xa8, 0x5c, 0x2a, 0x4f, 0x7a, 0xdc, 0xce, 0x6b, 0xbc, 0x9d, + 0x78, 0xf1, 0x95, 0x07, 0xce, 0x57, 0xd0, 0xb4, 0x93, 0x1f, 0x41, 0x61, + 0xf6, 0x99, 0xa6, 0x27, 0x7b, 0xbc, 0xb8, 0x81, 0x50, 0x68, 0x5c, 0x65, + 0x2d, 0x5f, 0x91, 0xb9, 0x2e, 0x00, 0x46, 0xc6, 0xcb, 0x42, 0xd1, 0x6f, + 0x26, 0x2a, 0xf7, 0xae, 0x3b, 0x8b, 0x4d, 0xd9, 0x96, 0xe4, 0xe7, 0x21, + 0x29, 0xa8, 0xbe, 0xb5, 0x82, 0x74, 0x1a, 0x79, 0x7e, 0xb3, 0x42, 0xcc, + 0xc4, 0x46, 0x06, 0xf0, 0xb0, 0x3b, 0x42, 0xa7, 0x75, 0x56, 0x8f, 0xdd, + 0x88, 0x50, 0xa9, 0xda, 0xd4, 0xd0, 0x30, 0x07, 0xda, 0x00, 0x92, 0x1e, + 0xa9, 0x17, 0x1f, 0x83, 0x48, 0xc4, 0xdb, 0x0b, 0x4e, 0x58, 0x9a, 0xbe, + 0xf8, 0x14, 0xcb, 0xe5, 0x54, 0x1c, 0x30, 0xfb, 0xcd, 0xc2, 0xad, 0x7c, + 0x8e, 0xf3, 0x51, 0x0d, 0x76, 0x6f, 0xbd, 0x65, 0x9e, 0xf3, 0x55, 0x6d, + 0xe5, 0xcd, 0xd7, 0x40, 0xfe, 0x95, 0x85, 0x04, 0xf2, 0x97, 0x88, 0xd4, + 0x8e, 0x16, 0x7c, 0x7b, 0x62, 0x89, 0xb0, 0xd7, 0xb5, 0x93, 0x5f, 0x0c, + 0x20, 0x0e, 0x15, 0x62, 0xbb, 0xe6, 0x4c, 0xe2, 0xd0, 0xa5, 0x00, 0x54, + 0x98, 0xb3, 0xf5, 0x60, 0x20, 0x6c, 0x63, 0xa8, 0x5a, 0x8f, 0xa9, 0x0a, + 0x38, 0x7b, 0xfe, 0x53, 0xce, 0xe5, 0x32, 0x03, 0x61, 0xcd, 0xac, 0x3b, + 0xa7, 0x23, 0xff, 0xca, 0xe8, 0xde, 0xa2, 0x8e, 0x8e, 0x59, 0xf9, 0xfd, + 0xb8, 0x1d, 0x29, 0x54, 0xae, 0x7a, 0x85, 0x7a, 0x11, 0x68, 0xfa, 0x4d, + 0xaf, 0x1d, 0x3d, 0x0b, 0x28, 0xfc, 0xe6, 0xb4, 0xaa, 0xba, 0xbf, 0x83, + 0x38, 0x94, 0x5a, 0xb0, 0x2a, 0x15, 0xe8, 0x9c, 0xd4, 0x71, 0x05, 0x52, + 0x26, 0xe7, 0xc7, 0xe3, 0xc4, 0x77, 0x9c, 0x91, 0x09, 0xf7, 0xed, 0x0f, + 0x8b, 0x63, 0x88, 0x9c, 0x35, 0x3a, 0x9f, 0xa5, 0x42, 0x50, 0x82, 0xd1, + 0xdf, 0xab, 0x7a, 0x1e, 0x2a, 0xd6, 0xb8, 0x10, 0x28, 0x3f, 0x70, 0xe7, + 0x88, 0xb5, 0x28, 0xc3, 0x88, 0x25, 0xc7, 0x11, 0xe3, 0x8c, 0xe0, 0x36, + 0x57, 0xf8, 0x7f, 0x0f, 0x22, 0xe7, 0x6a, 0x66, 0x3c, 0x04, 0x70, 0xe8, + 0xa6, 0xa8, 0x21, 0x20, 0x98, 0xd4, 0x2d, 0x9c, 0x4c, 0x91, 0x8a, 0x51, + 0x43, 0xfa, 0xbf, 0x14, 0x16, 0x73, 0xef, 0x8a, 0x72, 0xf2, 0x22, 0xc0, + 0x79, 0x04, 0xc8, 0x10, 0xad, 0x64, 0x92, 0xfa, 0x13, 0xe3, 0x9b, 0x83, + 0xa1, 0x7c, 0x0d, 0x33, 0x53, 0x6e, 0xbf, 0x08, 0xe1, 0x43, 0xbb, 0x19, + 0xea, 0x59, 0xa9, 0xb7, 0x4a, 0xdc, 0xe8, 0x18, 0x2e, 0xb7, 0xa9, 0xe4, + 0x81, 0x25, 0xf3, 0x1f, 0x3a, 0x65, 0xa8, 0xd2, 0x5e, 0x84, 0x4e, 0x61, + 0x0b, 0x6e, 0xd1, 0xb3, 0x1c, 0x78, 0x77, 0x0c, 0xf2, 0x8c, 0xbc, 0x8d, + 0x17, 0x05, 0xed, 0x58, 0xcc, 0xce, 0x22, 0x1e, 0x15, 0x11, 0x3d, 0x1a, + 0x41, 0x4d, 0x3a, 0xfe, 0x78, 0x45, 0x0f, 0x37, 0xa2, 0x06, 0xcc, 0x6f, + 0x33, 0xbd, 0x5e, 0x07, 0x31, 0x60, 0x36, 0xe7, 0x17, 0x8b, 0x91, 0x82, + 0xc5, 0xc8, 0x72, 0xfe, 0xf3, 0xd8, 0xea, 0xaa, 0xc3, 0xcc, 0x4a, 0xcb, + 0x3c, 0xb4, 0xbd, 0xf8, 0x66, 0x37, 0xda, 0xa1, 0xf8, 0xee, 0x10, 0x30, + 0x45, 0x31, 0xf4, 0xff, 0x40, 0x6f, 0xb5, 0xc5, 0xe6, 0x79, 0x72, 0x62, + 0x08, 0xd5, 0xc6, 0xf7, 0xf4, 0x5e, 0x68, 0xe2, 0xf9, 0x6f, 0x73, 0xbd, + 0x04, 0x60, 0xba, 0xf6, 0x6c, 0x39, 0x1f, 0x1e, 0xed, 0x36, 0x39, 0x75, + 0x8f, 0x84, 0x2f, 0x5d, 0x86, 0xe4, 0x23, 0x23, 0xbc, 0xec, 0xbc, 0x5a, + 0x88, 0x3b, 0x3d, 0x8e, 0x76, 0x74, 0x38, 0x9d, 0xfe, 0x5f, 0x6d, 0x6b, + 0x55, 0x7d, 0xee, 0x1f, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0xc1, 0xa3, 0x1f, 0x8d, 0x34, 0x95, 0xe6, 0x76, 0x87, 0xaf, 0x37, 0x97, + 0x76, 0x6c, 0x97, 0x49, 0xd4, 0x80, 0xba, 0x81, 0xc2, 0xf2, 0xd9, 0x7f, + 0x97, 0x22, 0x8b, 0x2d, 0x75, 0x44, 0x55, 0x2b, 0x89, 0x21, 0x38, 0x41, + 0x28, 0xac, 0x40, 0x71, 0xb0, 0xf8, 0xb1, 0x44, 0xeb, 0x2f, 0x84, 0x3e, + 0x90, 0x96, 0xb6, 0xbf, 0xa1, 0x20, 0xb8, 0x51, 0xc7, 0xe3, 0xa3, 0xa7, + 0x6f, 0x2e, 0xc9, 0x11, 0xda, 0x0b, 0xbe, 0x22, 0xd2, 0x15, 0x31, 0x65, + 0xbe, 0xfc, 0xca, 0x9a, 0x13, 0x7d, 0xf8, 0x05, 0x97, 0xf3, 0x7c, 0x46, + 0x7c, 0x57, 0x8b, 0xae, 0x20, 0xab, 0xaa, 0x56, 0x3d, 0x6e, 0x6e, 0x1a, + 0x92, 0x79, 0x76, 0x7d, 0x2f, 0x4b, 0x5b, 0x8a, 0x76, 0xba, 0x40, 0x6c, + 0xa2, 0xb0, 0x1f, 0x05, 0x35, 0x21, 0x02, 0x12, 0x52, 0xfa, 0xe9, 0xa9, + 0x7d, 0xca, 0x5d, 0x01, 0xac, 0x00, 0xf1, 0x08, 0xa8, 0x9c, 0xbe, 0xac, + 0x75, 0xd4, 0xbc, 0x90, 0x6e, 0xba, 0xc7, 0x62, 0x96, 0xa5, 0x64, 0x0c, + 0x25, 0x9d, 0x5a, 0x5d, 0x2b, 0x08, 0xa4, 0x59, 0xb0, 0xf5, 0x59, 0x16, + 0x6f, 0xce, 0xa3, 0x1b, 0xc9, 0x4e, 0x20, 0x9d, 0x94, 0x7e, 0xd6, 0xdc, + 0x67, 0xd8, 0xd7, 0xd3, 0x7a, 0x30, 0x6b, 0xe1, 0xf8, 0x08, 0x2b, 0xce, + 0x30, 0x4a, 0x77, 0xca, 0xe5, 0x8f, 0x7c, 0x0a, 0x2b, 0x15, 0xbf, 0x2a, + 0x6b, 0x82, 0x66, 0xfc, 0x8f, 0x76, 0x75, 0x0f, 0x06, 0x61, 0x4b, 0x8d, + 0x45, 0x2e, 0xe1, 0xf5, 0xcc, 0x83, 0xd8, 0x74, 0x9d, 0x39, 0x1b, 0xec, + 0xb6, 0x25, 0x55, 0x29, 0x8e, 0x0b, 0x72, 0x2a, 0x7a, 0x16, 0x22, 0x3b, + 0x5f, 0xaa, 0x7b, 0xb8, 0xce, 0xf9, 0xa4, 0x71, 0x9f, 0x8e, 0x79, 0x49, + 0x66, 0x8e, 0x86, 0x42, 0x49, 0x5e, 0x51, 0xae, 0xff, 0xcc, 0x9c, 0x4b, + 0x3d, 0x5b, 0x45, 0x08, 0x39, 0xc0, 0xec, 0xe7, 0xcc, 0xf7, 0x88, 0xb9, + 0x2c, 0x70, 0x78, 0x2f, 0x4b, 0xe9, 0x29, 0xce, 0x47, 0x21, 0x93, 0x9d, + 0x97, 0xbf, 0x70, 0xe2, 0x53, 0x2c, 0xec, 0x16, 0x94, 0xeb, 0xd1, 0x0f, + 0x7d, 0x9e, 0x84, 0xa9, 0x2e, 0xb7, 0xfe, 0x27, 0x91, 0xbf, 0x3b, 0x50, + 0x44, 0x51, 0xfa, 0x40, 0x8e, 0xf6, 0x1f, 0xa3, 0x30, 0x6d, 0x80, 0x78, + 0x1b, 0xfe, 0x5b, 0x66, 0x1d, 0x7c, 0x72, 0x02, 0x5c, 0xf5, 0x95, 0x4b, + 0xcd, 0x4a, 0x2b, 0x11, 0x24, 0x11, 0xe9, 0x84, 0xe9, 0x12, 0xeb, 0x87, + 0xe3, 0x4f, 0x45, 0x90, 0xa2, 0x46, 0x76, 0x5a, 0x13, 0x2f, 0x2b, 0xbb, + 0x28, 0x8a, 0x92, 0x00, 0xba, 0x4d, 0xff, 0xa7, 0x16, 0x89, 0x3f, 0x02, + 0x8c, 0x7e, 0x20, 0xde, 0x74, 0xe5, 0x9a, 0xdf, 0x52, 0xf4, 0x8b, 0x99, + 0xe2, 0xe6, 0xf1, 0xe7, 0x63, 0xd1, 0xbb, 0xf3, 0x8e, 0xd5, 0xe4, 0x27, + 0x58, 0xd7, 0xd0, 0xb4, 0x65, 0xce, 0x87, 0xf6, 0xfa, 0x2b, 0xb5, 0x3b, + 0xf7, 0x73, 0x95, 0x59, 0x3c, 0xe7, 0x71, 0xd3, 0x81, 0x4e, 0x31, 0xbe, + 0xce, 0xdd, 0x26, 0x25, 0x13, 0x93, 0x88, 0x28, 0x83, 0xaf, 0x33, 0x00, + 0x36, 0x04, 0x7a, 0x9a, 0xea, 0x7b, 0x9d, 0x69, 0x41, 0x90, 0x15, 0x9a, + 0x29, 0xef, 0xd2, 0x07, 0xbc, 0xd1, 0x14, 0x35, 0x40, 0x06, 0xf3, 0x59, + 0x8f, 0x95, 0x7b, 0x2b, 0xca, 0xa5, 0x5d, 0x30, 0xa9, 0x05, 0x15, 0xde, + 0x44, 0x93, 0x21, 0x96, 0xaa, 0xaf, 0x16, 0x38, 0x2f, 0x61, 0x27, 0x2d, + 0xd0, 0x2d, 0xa0, 0x5b, 0x0a, 0x66, 0x7b, 0x4b, 0xc2, 0x7d, 0x1b, 0x02, + 0x2b, 0xd5, 0x0b, 0x90, 0x93, 0x86, 0x7d, 0x8e, 0xd8, 0xae, 0x7a, 0x22, + 0x59, 0x65, 0x7c, 0xea, 0x68, 0xba, 0xad, 0x36, 0xa6, 0x0d, 0x3a, 0x34, + 0xac, 0xbb, 0x33, 0x0a, 0xcd, 0x52, 0x14, 0x28, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x3f, 0x3e, 0x00, 0xb3, 0xba, 0x7d, 0x7b, 0xa1, + 0x5f, 0x1a, 0xde, 0x8b, 0xf1, 0x90, 0xa0, 0x8b, 0x93, 0xb5, 0x5f, 0x22, + 0x77, 0x51, 0x93, 0xf8, 0x93, 0xdd, 0x74, 0x70, 0x7f, 0xd4, 0x8c, 0x2b, + 0x39, 0xd6, 0xe9, 0xe6, 0xf9, 0x6f, 0xcc, 0x93, 0xde, 0x2a, 0x98, 0xe1, + 0x5d, 0xb5, 0x04, 0xc4, 0xc0, 0x81, 0xc6, 0xe4, 0xd4, 0x8c, 0xbf, 0x01, + 0xa0, 0x97, 0x4b, 0xc1, 0x9f, 0xb5, 0x17, 0x18, 0x17, 0x10, 0x2b, 0x9a, + 0x3b, 0x22, 0x5e, 0x06, 0x2f, 0xf6, 0x78, 0x86, 0x4b, 0x4f, 0xb8, 0x35, + 0x13, 0x53, 0x75, 0x98, 0xc3, 0x28, 0x89, 0xc1, 0x90, 0x02, 0x92, 0xc1, + 0x46, 0x46, 0x45, 0x15, 0x2f, 0xa2, 0x49, 0x3b, 0x7b, 0x85, 0xab, 0x85, + 0x23, 0x52, 0xe5, 0xd9, 0xda, 0x89, 0xa6, 0xc6, 0x34, 0x1d, 0x2b, 0x9a, + 0xe1, 0xa1, 0x5d, 0xab, 0x02, 0xe9, 0x98, 0x8d, 0x96, 0x94, 0xcb, 0x22, + 0xeb, 0x4a, 0x89, 0x9e, 0xf7, 0x47, 0x3a, 0x85, 0xbd, 0x41, 0x4a, 0x08, + 0x10, 0x70, 0xde, 0x1f, 0x6b, 0x67, 0x74, 0x2d, 0x87, 0xe8, 0xf4, 0x4f, + 0x28, 0x2f, 0x95, 0x4e, 0xe5, 0xf0, 0xd8, 0x03, 0x4e, 0x87, 0x38, 0xbd, + 0x36, 0x4e, 0xc6, 0x5a, 0x8e, 0x01, 0x4d, 0x0e, 0x27, 0x40, 0xf2, 0x8c, + 0x68, 0xe4, 0x30, 0xbb, 0x1f, 0x46, 0x51, 0xb8, 0xb9, 0x9f, 0xcc, 0x4f, + 0xe2, 0x88, 0x76, 0x27, 0xfc, 0xb7, 0x6e, 0x86, 0xb0, 0xa1, 0x59, 0xf8, + 0x63, 0xa9, 0x2f, 0xec, 0xb0, 0xae, 0x13, 0x76, 0xb6, 0x90, 0xc6, 0xc1, + 0xa5, 0x06, 0xf9, 0xe8, 0xa9, 0xaf, 0xf9, 0x9b, 0x64, 0xc8, 0x86, 0x2b, + 0x0a, 0x0d, 0xf0, 0x1e, 0x41, 0xd1, 0xe0, 0xca, 0x24, 0x1e, 0x56, 0x0a, + 0x45, 0xab, 0x29, 0x37, 0x00, 0x20, 0xce, 0xc0, 0x83, 0x72, 0x97, 0x9c, + 0x89, 0x2b, 0x63, 0xa0, 0xb9, 0x18, 0x6f, 0x2b, 0xb8, 0x70, 0x45, 0xf2, + 0x87, 0x3d, 0x8c, 0x1c, 0x82, 0x2a, 0xc8, 0x83, 0xfb, 0xd8, 0x38, 0x33, + 0x12, 0xb2, 0x57, 0xd3, 0xd3, 0xfa, 0x2a, 0x4a, 0xd3, 0x67, 0x5a, 0x60, + 0x74, 0x6e, 0xa4, 0x29, 0x26, 0xd7, 0x59, 0x26, 0x75, 0xec, 0x00, 0x07, + 0xc3, 0x00, 0x91, 0x6a, 0xc0, 0xb4, 0xb4, 0x80, 0x09, 0x50, 0x74, 0x1f, + 0x8e, 0x18, 0x9f, 0xac, 0x68, 0x0a, 0x4c, 0x21, 0x79, 0x4b, 0x48, 0x0b, + 0xe9, 0xc9, 0x73, 0x58, 0xbd, 0xa1, 0x9e, 0x0f, 0xf4, 0xb3, 0xcc, 0xbe, + 0xa1, 0xd1, 0x3b, 0x72, 0xbb, 0xba, 0x88, 0xa1, 0x4a, 0xd6, 0xc7, 0x85, + 0xcc, 0xe0, 0x3d, 0xf3, 0xe0, 0x15, 0xc8, 0x0a, 0x23, 0x5f, 0xa7, 0x45, + 0x54, 0x1c, 0x9f, 0x89, 0x53, 0xa5, 0xfb, 0x02, 0x81, 0x1a, 0xa8, 0x24, + 0x0d, 0x94, 0xa8, 0x3f, 0xb9, 0xef, 0x7b, 0x03, 0x86, 0x62, 0xab, 0x8f, + 0x5c, 0x08, 0x80, 0x16, 0x39, 0x3c, 0xdd, 0x18, 0x7a, 0xde, 0x9f, 0x76, + 0xd4, 0x44, 0x92, 0xc7, 0x91, 0xc2, 0x15, 0x00, 0x03, 0x88, 0x70, 0xe4, + 0x0b, 0xd1, 0xe5, 0xf9, 0xc8, 0x71, 0x33, 0xb5, 0x33, 0x3a, 0x73, 0x28, + 0x15, 0xf3, 0x50, 0xae, 0x75, 0xb2, 0x41, 0xf9, 0x27, 0x3e, 0xc4, 0x3d, + 0x7d, 0xe3, 0xd9, 0xb0, 0x4d, 0x56, 0x5d, 0x60, 0x2c, 0x6e, 0x41, 0x76, + 0x5b, 0xc9, 0x03, 0x1e, 0xfc, 0x78, 0x24, 0x1e, 0x1f, 0xfa, 0x94, 0x05, + 0x8b, 0x97, 0xf6, 0xbf, 0x3c, 0x85, 0x82, 0xda, 0x2c, 0xf0, 0xff, 0xc8, + 0x3a, 0xda, 0x89, 0x56, 0x4d, 0x63, 0x0e, 0x10, 0xbb, 0xaa, 0xab, 0xee, + 0xa8, 0xd4, 0xb1, 0x14, 0x5c, 0x25, 0x0a, 0x60, 0xd3, 0x57, 0x6c, 0xdb, + 0x23, 0x7f, 0x79, 0xce, 0xfd, 0x65, 0x70, 0x99, 0xd9, 0x4f, 0x1e, 0xd5, + 0xbc, 0x8d, 0x74, 0x07, 0x6e, 0x48, 0x51, 0xf7, 0x61, 0x7c, 0x26, 0x06, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x99, 0x4e, 0x08, 0x5e, + 0x32, 0x0f, 0x05, 0x70, 0x6d, 0x9f, 0x81, 0xc1, 0xbe, 0x79, 0xb7, 0x0c, + 0x85, 0x04, 0x84, 0x03, 0xac, 0xab, 0x76, 0x03, 0x80, 0x33, 0x53, 0x93, + 0x1d, 0x2f, 0x14, 0x0b, 0x07, 0x76, 0x75, 0x54, 0x40, 0x43, 0x16, 0x0f, + 0x7d, 0xe3, 0x4b, 0xc8, 0x69, 0xaa, 0xac, 0xe4, 0x7a, 0xa0, 0xe4, 0xc6, + 0x98, 0xd1, 0xb7, 0x57, 0x7f, 0x49, 0x3c, 0xed, 0xd6, 0xef, 0xd3, 0x11, + 0xb5, 0x62, 0xaf, 0x50, 0xef, 0x7c, 0x48, 0xf5, 0x66, 0xe6, 0xc8, 0xa9, + 0x43, 0xfc, 0x76, 0x75, 0x8e, 0x61, 0x54, 0x99, 0x85, 0x41, 0x55, 0x14, + 0xb6, 0x6d, 0x3a, 0x1a, 0x76, 0xd9, 0x0c, 0x19, 0x60, 0x06, 0xac, 0x66, + 0xb1, 0x39, 0xe6, 0x67, 0x1d, 0xff, 0x71, 0xb7, 0xd4, 0x27, 0xc5, 0x0c, + 0x1c, 0x08, 0x42, 0x2e, 0xb7, 0x6c, 0xdd, 0xfb, 0xbf, 0xeb, 0xbe, 0x7b, + 0x9b, 0x88, 0x4b, 0x0a, 0x34, 0xe7, 0xc4, 0x98, 0x85, 0x60, 0x0d, 0x30, + 0x59, 0x61, 0xdf, 0x0e, 0x2e, 0xc7, 0x2a, 0xad, 0xa8, 0x83, 0x98, 0xd0, + 0x7b, 0x49, 0x0b, 0x6e, 0xe3, 0x84, 0xec, 0x67, 0xf0, 0x20, 0x69, 0x0e, + 0x57, 0xf2, 0x7c, 0x38, 0x98, 0x32, 0x7b, 0x70, 0xea, 0x59, 0xf9, 0x97, + 0x1f, 0x5e, 0x6a, 0xbb, 0x2f, 0x4c, 0x93, 0xf3, 0x48, 0x76, 0x20, 0x0d, + 0x15, 0x27, 0xf7, 0xf4, 0x28, 0x33, 0x33, 0x03, 0x39, 0x29, 0xb1, 0x8f, + 0x17, 0xea, 0xf2, 0xf9, 0xf0, 0x88, 0xcf, 0xee, 0x46, 0xeb, 0x3c, 0x19, + 0xcc, 0x3f, 0x6d, 0x91, 0xb5, 0x22, 0xe8, 0x9f, 0xcc, 0x55, 0x15, 0x36, + 0xfa, 0x7d, 0x65, 0x1a, 0xd5, 0x16, 0x07, 0x1e, 0xbd, 0x5e, 0x1d, 0x97, + 0x09, 0x5c, 0x08, 0x4d, 0xcc, 0x50, 0x0b, 0x7b, 0x11, 0x0d, 0xb5, 0x73, + 0x59, 0x5a, 0xd7, 0xdb, 0xd0, 0xbf, 0xae, 0x16, 0xf9, 0x89, 0xf5, 0x0c, + 0x9b, 0xf4, 0xdf, 0x7b, 0xc8, 0xe6, 0x4e, 0x64, 0xb5, 0xa7, 0xcf, 0xc2, + 0xa6, 0x6c, 0x9d, 0x67, 0xdf, 0x8e, 0x43, 0x93, 0x8c, 0xe7, 0xfd, 0xe4, + 0xda, 0x8b, 0xfa, 0x06, 0x31, 0xc5, 0x46, 0x1d, 0xdd, 0x1b, 0x71, 0xc9, + 0xda, 0x9e, 0x54, 0x2d, 0xf0, 0x00, 0x91, 0xb1, 0x2f, 0x40, 0x17, 0xb7, + 0x37, 0xbf, 0x04, 0xb6, 0x36, 0x9f, 0xd6, 0x10, 0xc1, 0xa7, 0xd0, 0xba, + 0xf2, 0xcf, 0xa7, 0x0c, 0xe9, 0x0a, 0x1c, 0x32, 0xc1, 0xdf, 0x20, 0x4e, + 0x80, 0x73, 0x27, 0xa9, 0xbc, 0xb1, 0x1c, 0x18, 0x9f, 0x5a, 0xd1, 0x4d, + 0x4c, 0x13, 0x5c, 0xdb, 0xac, 0x80, 0x75, 0x04, 0x0d, 0x40, 0xd6, 0x0d, + 0x56, 0x90, 0x64, 0x9b, 0x7b, 0x06, 0x45, 0xfa, 0x36, 0xf6, 0xe2, 0x2f, + 0xf0, 0xfa, 0xca, 0xd6, 0x95, 0x32, 0x60, 0x0b, 0x83, 0xcd, 0xb2, 0x0f, + 0xeb, 0x07, 0x4d, 0x3a, 0x13, 0xf4, 0xff, 0x20, 0xc1, 0x9e, 0xbd, 0x93, + 0x47, 0x6b, 0x91, 0x67, 0x3d, 0xeb, 0x3b, 0x6e, 0x75, 0xea, 0x52, 0x22, + 0x50, 0x38, 0xc4, 0x62, 0xbd, 0x8b, 0xee, 0x5b, 0xfb, 0x7b, 0x22, 0x86, + 0x4d, 0x64, 0x8b, 0x1d, 0xf0, 0xf3, 0xb6, 0xc2, 0x1f, 0xd1, 0x86, 0xbc, + 0x18, 0x9c, 0x53, 0x1e, 0xa1, 0xa2, 0x1e, 0x21, 0x96, 0xff, 0x5f, 0x98, + 0x70, 0xeb, 0x6f, 0x47, 0xb4, 0x34, 0xf4, 0xf0, 0x40, 0x25, 0xad, 0x13, + 0xb8, 0xae, 0xeb, 0xa8, 0xf4, 0x96, 0x93, 0xa9, 0x69, 0xd6, 0x2f, 0x39, + 0xd6, 0x88, 0x91, 0x6b, 0xf5, 0x98, 0x28, 0x9b, 0x00, 0xde, 0xfd, 0x5c, + 0x9f, 0x8c, 0xd5, 0x73, 0x88, 0x1b, 0x93, 0x1b, 0xf4, 0xcb, 0x74, 0xd6, + 0x5e, 0xbb, 0x32, 0x6a, 0x11, 0x39, 0x3d, 0x3b, 0x4c, 0x90, 0x94, 0xf8, + 0x84, 0x2f, 0x94, 0x20, 0x2c, 0xe1, 0x6a, 0x2a, 0x8d, 0x25, 0x0e, 0xd0, + 0xb5, 0xda, 0x1f, 0x22, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0xda, 0xa7, 0x99, 0x72, 0xa4, 0x00, 0x63, 0x4e, 0x4a, 0x61, 0x48, 0xc7, + 0xb9, 0x78, 0x9f, 0x82, 0x4c, 0x38, 0x30, 0xc9, 0x10, 0x28, 0x68, 0x2a, + 0x13, 0xc1, 0xbf, 0x6e, 0x2d, 0x30, 0xe3, 0x08, 0xe2, 0x11, 0x4e, 0x37, + 0xab, 0xbc, 0x7b, 0x8f, 0x50, 0x6e, 0xaf, 0xa3, 0x2b, 0xf5, 0x0b, 0xcd, + 0x6a, 0x6c, 0xa7, 0x4e, 0x52, 0xfe, 0xef, 0x21, 0x60, 0x0b, 0xa2, 0x68, + 0xd1, 0x3c, 0x1a, 0x2c, 0xb8, 0x42, 0x62, 0xaf, 0xa6, 0xdc, 0xcd, 0x80, + 0xc6, 0x08, 0x45, 0x24, 0xcb, 0x8c, 0xa5, 0xb7, 0x9b, 0x37, 0x8f, 0x97, + 0xfd, 0x39, 0x8d, 0x86, 0x57, 0x0c, 0xd0, 0xf3, 0x1f, 0x2c, 0x76, 0x2a, + 0xcc, 0x8a, 0xcc, 0x95, 0xff, 0x27, 0x7e, 0x2f, 0x45, 0x85, 0x9a, 0xb5, + 0x89, 0xfd, 0x19, 0x2b, 0xc4, 0xeb, 0x22, 0x37, 0x91, 0x46, 0x2c, 0xfa, + 0xae, 0x76, 0x63, 0xb7, 0xf0, 0x80, 0xed, 0x16, 0x54, 0x21, 0x48, 0xb8, + 0x89, 0x92, 0x0b, 0x57, 0x3c, 0xe7, 0x25, 0x96, 0x45, 0x7a, 0x1e, 0x49, + 0xbf, 0x18, 0x75, 0xb5, 0x9d, 0x54, 0x85, 0x12, 0x7a, 0x48, 0x4d, 0x6c, + 0x14, 0x07, 0x87, 0x0d, 0x08, 0xaf, 0x81, 0xf0, 0x0c, 0x91, 0x13, 0xa6, + 0xd1, 0x54, 0x8d, 0x7f, 0x38, 0x3b, 0xd6, 0x2f, 0x69, 0x24, 0xa5, 0x18, + 0xd9, 0xab, 0x44, 0x0f, 0x18, 0xe0, 0xfa, 0x3c, 0x40, 0x0e, 0xdc, 0x28, + 0xfd, 0xb5, 0x79, 0xe1, 0x52, 0x48, 0x5b, 0x1b, 0x0d, 0x3f, 0x71, 0x0a, + 0x6d, 0xb4, 0x9e, 0x61, 0xe5, 0x3e, 0x1e, 0x14, 0xe9, 0x60, 0xce, 0xef, + 0xc1, 0x0e, 0x1b, 0x95, 0xd6, 0x6a, 0xae, 0x1a, 0x36, 0xdc, 0x15, 0xb2, + 0x16, 0x9c, 0xe2, 0x8e, 0xbf, 0xae, 0x14, 0xcc, 0x42, 0x52, 0x8b, 0x37, + 0xd0, 0x44, 0xf3, 0x22, 0xf1, 0x99, 0xe2, 0xa8, 0x24, 0x73, 0x16, 0xb5, + 0x5c, 0xe7, 0x89, 0x13, 0x41, 0xdc, 0x48, 0xb9, 0xd9, 0x5d, 0x92, 0x25, + 0xb1, 0x62, 0x82, 0x99, 0x5b, 0x14, 0x7c, 0x4a, 0xde, 0x0e, 0x54, 0x0c, + 0x81, 0x37, 0x48, 0xad, 0xc9, 0x59, 0x68, 0xef, 0x7b, 0x9c, 0x0f, 0x20, + 0x4f, 0x4a, 0xb0, 0x23, 0x41, 0xc9, 0x6f, 0x27, 0xde, 0xe8, 0x19, 0x12, + 0xb8, 0x80, 0x0e, 0x18, 0x68, 0xa2, 0xa8, 0x50, 0xcc, 0xfa, 0x6b, 0x5e, + 0xb0, 0x9c, 0xd6, 0x52, 0xbf, 0x1c, 0xeb, 0x07, 0x1f, 0x5e, 0x02, 0x1b, + 0x12, 0x81, 0x66, 0x64, 0xce, 0xc7, 0x93, 0xe7, 0x2b, 0x02, 0x19, 0x73, + 0x9f, 0x92, 0x1a, 0x58, 0xd5, 0xd2, 0x4a, 0xe9, 0x7f, 0xe6, 0x2e, 0x85, + 0xa6, 0x5c, 0x01, 0x2a, 0xed, 0xbb, 0x99, 0x91, 0xc0, 0xd7, 0x73, 0x59, + 0x12, 0xe3, 0xaa, 0x45, 0x7e, 0x46, 0x84, 0xc0, 0xee, 0xe5, 0x90, 0xc4, + 0x54, 0x97, 0x2f, 0x41, 0xda, 0xab, 0x4d, 0xc7, 0x2a, 0xfe, 0x18, 0x2c, + 0xaa, 0x54, 0x6c, 0x43, 0x87, 0xd0, 0x4e, 0x4e, 0xd1, 0x42, 0xc3, 0x3f, + 0xb2, 0x24, 0x6e, 0xbd, 0xa7, 0x4f, 0x18, 0x7a, 0x72, 0x24, 0x90, 0x75, + 0x81, 0x56, 0x8c, 0x7c, 0x29, 0x95, 0x51, 0x25, 0x6e, 0x76, 0xab, 0x6f, + 0x22, 0xba, 0x87, 0x5a, 0x97, 0xd7, 0xbf, 0xcf, 0x63, 0x76, 0x44, 0x85, + 0x73, 0x51, 0xf6, 0x91, 0xd9, 0x1a, 0x65, 0x8d, 0x36, 0x7b, 0xcd, 0xb6, + 0x14, 0x1c, 0x6f, 0x08, 0xb4, 0x39, 0x7e, 0xc4, 0x77, 0xf0, 0x12, 0x98, + 0x59, 0x31, 0x85, 0x20, 0x10, 0x74, 0x11, 0x72, 0x5c, 0x47, 0x24, 0x59, + 0x10, 0x19, 0x17, 0xb6, 0x1c, 0x37, 0x52, 0x35, 0xbf, 0xcc, 0xdf, 0x05, + 0xb7, 0x82, 0x07, 0x5e, 0x66, 0xb5, 0x57, 0x00, 0xa1, 0xb8, 0xba, 0xc0, + 0xf5, 0xaa, 0x06, 0x69, 0x5e, 0x13, 0xfc, 0xd0, 0xc4, 0x01, 0x0a, 0x0a, + 0x1c, 0xcd, 0x7f, 0xac, 0x5c, 0xa6, 0xc9, 0x16, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x61, 0xdb, 0xc0, 0xf5, 0x33, 0x93, 0xd4, 0xed, + 0x7b, 0xda, 0xbe, 0x4f, 0x2e, 0xfb, 0xf6, 0xc1, 0x54, 0x9f, 0xfd, 0xe0, + 0x2a, 0xc4, 0x2d, 0x7d, 0x28, 0xb1, 0x30, 0x4d, 0x6e, 0xe0, 0xdc, 0x1a, + 0xba, 0xeb, 0x8b, 0xf5, 0x14, 0x4f, 0x6f, 0x7e, 0x33, 0xa5, 0x0b, 0x5b, + 0x7a, 0x30, 0xba, 0xdb, 0x2f, 0x48, 0x59, 0xf9, 0xf5, 0x38, 0xe2, 0xc3, + 0x66, 0x7e, 0x6c, 0xc3, 0xf1, 0x60, 0xe2, 0x17, 0xd6, 0x2b, 0x89, 0xb8, + 0xdc, 0x33, 0x0f, 0x02, 0xaf, 0xb0, 0x41, 0x09, 0x80, 0x96, 0x12, 0x77, + 0x70, 0x99, 0xf7, 0x50, 0xf7, 0xc6, 0x1a, 0xcd, 0x97, 0x54, 0x3d, 0xef, + 0x52, 0x2d, 0x5c, 0x2b, 0x88, 0xbb, 0x62, 0x2d, 0x40, 0xcd, 0xcf, 0x8f, + 0x79, 0x37, 0x1b, 0x5d, 0xc2, 0xc7, 0xd6, 0x90, 0x3d, 0x5f, 0x3c, 0xab, + 0x3a, 0xc2, 0xdc, 0x4d, 0xf8, 0xb0, 0xaa, 0xea, 0x5a, 0x1d, 0xad, 0x2d, + 0x55, 0x28, 0xc0, 0xce, 0x79, 0x75, 0x25, 0xa7, 0xc1, 0x5c, 0xd7, 0x43, + 0x71, 0x84, 0x8a, 0xaf, 0x9b, 0x66, 0x43, 0xfb, 0x36, 0xf5, 0x9f, 0x5b, + 0xc6, 0x81, 0x36, 0x1a, 0x42, 0xf8, 0xa6, 0x1f, 0xda, 0x3c, 0xb7, 0x38, + 0x2c, 0xc4, 0x1c, 0x71, 0xe0, 0xc4, 0xe8, 0x17, 0x06, 0xa9, 0xc9, 0x32, + 0xc0, 0x7b, 0xcd, 0x1f, 0x2c, 0xd1, 0xa3, 0xfb, 0xfd, 0x02, 0xfa, 0x98, + 0xd1, 0x4d, 0x99, 0x04, 0x91, 0x98, 0x97, 0x46, 0xd5, 0x80, 0x8c, 0x7c, + 0xd0, 0xdd, 0x39, 0x59, 0xeb, 0x1a, 0xb7, 0xe9, 0x5d, 0x0d, 0x6c, 0x14, + 0xe8, 0x52, 0xa6, 0xb2, 0x1b, 0xb7, 0x14, 0xb6, 0x51, 0xe6, 0xe9, 0x15, + 0x06, 0xf7, 0xa9, 0x0a, 0x0a, 0x80, 0xda, 0x65, 0xc4, 0x66, 0x8f, 0x39, + 0x2e, 0x82, 0x32, 0xdd, 0x3a, 0xe7, 0x39, 0x77, 0xa2, 0x52, 0x9a, 0x5b, + 0x29, 0x1a, 0x44, 0x01, 0xa6, 0xd0, 0x7f, 0x29, 0x4d, 0x23, 0x90, 0x33, + 0x6a, 0x88, 0xa1, 0xe5, 0x44, 0xfd, 0x25, 0xd0, 0x4c, 0xf9, 0x29, 0x71, + 0x05, 0x4e, 0x0b, 0xce, 0x6e, 0x15, 0x6a, 0xbf, 0x30, 0xbc, 0xa9, 0x75, + 0x5b, 0xfc, 0x94, 0x03, 0xe0, 0x6d, 0xb6, 0xd3, 0xc3, 0x74, 0x08, 0xd9, + 0x04, 0x69, 0xcc, 0x83, 0x5c, 0x47, 0xf9, 0x92, 0x04, 0xf6, 0x97, 0x3c, + 0x60, 0x11, 0x82, 0x6b, 0x87, 0x69, 0x84, 0xc1, 0xd0, 0x30, 0xaf, 0x16, + 0xa1, 0xd1, 0x33, 0xcb, 0x81, 0x98, 0x75, 0xc9, 0x39, 0x4a, 0x97, 0xbb, + 0xe9, 0x0b, 0xf0, 0xdd, 0x7a, 0xd7, 0x4e, 0x3b, 0xc2, 0xab, 0x09, 0xe8, + 0x9a, 0x55, 0xc8, 0xcc, 0x7e, 0x47, 0xb0, 0x14, 0x5c, 0xd4, 0x0a, 0xc2, + 0x60, 0x0b, 0x99, 0x08, 0xdd, 0x21, 0xaf, 0x1c, 0x96, 0x36, 0x16, 0x77, + 0x1b, 0x05, 0xb2, 0xc1, 0x48, 0x2b, 0xc1, 0x40, 0xd2, 0xcf, 0xfe, 0xf7, + 0x6d, 0x68, 0x6d, 0x12, 0x94, 0x10, 0xd8, 0xc9, 0x30, 0x6e, 0x9a, 0x10, + 0xfe, 0x99, 0xff, 0x93, 0x20, 0x42, 0x6c, 0xa6, 0x7e, 0x47, 0xa1, 0x2c, + 0xec, 0x5e, 0xff, 0x9d, 0x6a, 0x7b, 0x06, 0x18, 0xdb, 0x44, 0x43, 0x19, + 0x46, 0x7d, 0xe1, 0xa0, 0x0c, 0x13, 0x6b, 0xe6, 0x84, 0x15, 0x11, 0x01, + 0x0c, 0x05, 0x56, 0xe8, 0xab, 0x10, 0x9d, 0x5c, 0xce, 0x2a, 0xeb, 0x59, + 0x1b, 0x83, 0x59, 0x8d, 0x1f, 0x17, 0x97, 0x20, 0x94, 0xae, 0xeb, 0xaa, + 0x04, 0x7a, 0x90, 0x33, 0x04, 0xd1, 0x10, 0x48, 0x1d, 0x5b, 0x47, 0x0e, + 0x7c, 0x03, 0x10, 0x29, 0x82, 0x18, 0xff, 0x6b, 0x2a, 0x11, 0x17, 0x96, + 0x04, 0xb8, 0x30, 0x1f, 0x0d, 0xa9, 0x61, 0x07, 0xe5, 0xe8, 0xf9, 0x5c, + 0x11, 0x8a, 0x68, 0x3f, 0x98, 0x18, 0x8f, 0x36, 0x38, 0x03, 0x3e, 0x9c, + 0x22, 0x4b, 0x36, 0x17, 0x12, 0xf0, 0xaf, 0x27, 0x16, 0x54, 0x66, 0x28, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xd5, 0xea, 0x9d, 0xf8, + 0x29, 0x0c, 0x5c, 0x9d, 0x33, 0x2c, 0x80, 0x92, 0x31, 0xbd, 0x00, 0xd7, + 0xef, 0x98, 0x27, 0x25, 0x8f, 0x8e, 0x80, 0xc3, 0x39, 0xd2, 0xe8, 0x6a, + 0x9d, 0x6b, 0x0e, 0x1c, 0x24, 0xae, 0x60, 0xce, 0x92, 0x89, 0x58, 0x7b, + 0x7f, 0x78, 0xbb, 0xff, 0x71, 0x75, 0xbf, 0x2f, 0x78, 0x74, 0xaa, 0xb1, + 0x33, 0x27, 0x25, 0xbf, 0xa5, 0xcd, 0x65, 0xae, 0xbe, 0xa1, 0xbc, 0x28, + 0x5a, 0x36, 0x06, 0x24, 0xe0, 0x09, 0x9a, 0x7b, 0x70, 0x01, 0x4a, 0x1c, + 0x2f, 0xa8, 0xd0, 0x6e, 0x42, 0xbf, 0x82, 0x02, 0x1d, 0x1a, 0xe5, 0x1c, + 0x20, 0x64, 0x74, 0xc1, 0xd5, 0xec, 0xa8, 0x26, 0xa1, 0x06, 0x59, 0x3b, + 0xfb, 0xe1, 0xc6, 0x24, 0xac, 0x55, 0xfa, 0x73, 0xc2, 0x3c, 0x77, 0xa4, + 0x37, 0xb6, 0xbd, 0x80, 0x2d, 0x8a, 0x4b, 0xa4, 0x04, 0x1b, 0x29, 0xe8, + 0xb4, 0x62, 0xba, 0x1a, 0xc1, 0x6f, 0x5e, 0x42, 0x1b, 0x03, 0x00, 0x4c, + 0x5e, 0x95, 0x4d, 0xca, 0xa4, 0x31, 0xa0, 0x77, 0xca, 0xe8, 0xc3, 0x57, + 0xdd, 0xb9, 0x5e, 0x70, 0x20, 0xfd, 0x63, 0xeb, 0xe0, 0x98, 0xad, 0x2b, + 0xcb, 0x74, 0x23, 0x12, 0x88, 0x59, 0x94, 0x5b, 0x85, 0xe8, 0x85, 0xb9, + 0xbc, 0x12, 0x91, 0xc2, 0x4d, 0x04, 0x06, 0xb7, 0x9a, 0x7e, 0x3b, 0x98, + 0xa4, 0xca, 0x4d, 0x9b, 0x5b, 0x5a, 0x5b, 0x19, 0xec, 0x25, 0x76, 0x36, + 0xbb, 0xee, 0xc5, 0x53, 0x7a, 0x6d, 0x7e, 0x9b, 0xca, 0x44, 0x64, 0xfb, + 0x55, 0xf1, 0x2f, 0x8e, 0xc7, 0xdf, 0x27, 0xee, 0x9d, 0x29, 0xbd, 0x9a, + 0x6b, 0x9a, 0x62, 0x05, 0x92, 0x17, 0xcb, 0xbc, 0x4a, 0xef, 0x32, 0xb1, + 0x8a, 0xa1, 0xab, 0x9b, 0xec, 0xaf, 0xd1, 0xa4, 0x1e, 0xb8, 0x45, 0xbe, + 0x16, 0x94, 0x67, 0x83, 0xa0, 0x8f, 0xe0, 0x7c, 0xdd, 0x27, 0x8d, 0x04, + 0xf0, 0x03, 0x01, 0x48, 0x9c, 0xc5, 0x5b, 0x2e, 0xed, 0xf1, 0xa8, 0xf3, + 0xe0, 0xa3, 0x9e, 0x14, 0xe0, 0xe2, 0x80, 0x53, 0xd7, 0xb7, 0xdf, 0xba, + 0xef, 0xa2, 0xbe, 0x8f, 0x79, 0x3a, 0xa6, 0x13, 0x38, 0xb3, 0x7b, 0x9a, + 0x54, 0x0f, 0x4b, 0x99, 0xd5, 0xdd, 0x22, 0x69, 0x2f, 0xda, 0x09, 0xd0, + 0x79, 0x1c, 0xac, 0xc9, 0xd2, 0x34, 0xeb, 0x04, 0xa6, 0x2a, 0x9e, 0x53, + 0x63, 0xee, 0xa5, 0x21, 0xd2, 0xfb, 0xde, 0xa2, 0x0f, 0xbf, 0x4e, 0xe6, + 0xba, 0x81, 0x3e, 0xfb, 0xdb, 0x7b, 0x2f, 0xcd, 0x97, 0x35, 0xf4, 0xef, + 0x84, 0xbf, 0xf9, 0xba, 0xc2, 0x6f, 0x06, 0x92, 0xe5, 0x5d, 0x82, 0x0f, + 0xe7, 0x60, 0x9c, 0x9d, 0xe8, 0xde, 0x4e, 0x33, 0x22, 0xb4, 0xe8, 0x88, + 0x94, 0x85, 0xd6, 0x2e, 0x56, 0xb6, 0xf4, 0x37, 0x70, 0xe3, 0xa3, 0x52, + 0xd7, 0xd5, 0x74, 0x67, 0x43, 0x90, 0x4e, 0x04, 0x00, 0xbd, 0xaa, 0xd2, + 0xf4, 0x06, 0x6f, 0xbe, 0x28, 0x10, 0x37, 0x08, 0x9d, 0x62, 0xe5, 0x75, + 0xb2, 0x8a, 0xcd, 0x3b, 0x69, 0x94, 0x7e, 0x27, 0xcd, 0xd5, 0xca, 0xb0, + 0x9f, 0x06, 0xcb, 0x20, 0x07, 0x2d, 0xe9, 0xa8, 0xa3, 0x57, 0x16, 0x88, + 0x80, 0x95, 0x4c, 0xb5, 0x3f, 0xc3, 0x9d, 0x8b, 0x76, 0xda, 0xf0, 0xf4, + 0x7c, 0x80, 0xc6, 0x19, 0x04, 0xe4, 0x27, 0x54, 0xc1, 0x6b, 0x29, 0x17, + 0x2f, 0x84, 0x94, 0xc0, 0x95, 0x61, 0xa0, 0xa3, 0x76, 0x19, 0x68, 0x24, + 0xcb, 0x6f, 0x0c, 0xc2, 0x76, 0xcd, 0x63, 0x54, 0x47, 0xec, 0x6b, 0xe1, + 0x77, 0x94, 0x78, 0x03, 0x89, 0x5d, 0x4d, 0x07, 0x2e, 0x36, 0x34, 0x9a, + 0xb4, 0x28, 0x63, 0xc6, 0xc3, 0x7c, 0x43, 0x3b, 0x8d, 0xe3, 0x6e, 0x1f, + 0x5c, 0x7d, 0xa9, 0xb4, 0x44, 0x2d, 0x60, 0x7d, 0x70, 0xc3, 0x94, 0x8b, + 0x8e, 0x2e, 0x96, 0x2b, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x1d, 0x8e, 0xfa, 0x0d, 0xd2, 0x89, 0xac, 0x32, 0xf7, 0xb7, 0x32, 0x23, + 0x0e, 0x03, 0xd7, 0x47, 0xf4, 0x82, 0x72, 0xa8, 0x7d, 0xd6, 0xfe, 0x2c, + 0xd2, 0x45, 0xee, 0x7a, 0xb1, 0x9d, 0xe3, 0x17, 0x68, 0xc3, 0x5d, 0x6a, + 0x5b, 0x5f, 0x14, 0x93, 0x9d, 0x2c, 0xcd, 0x61, 0xc6, 0x39, 0x48, 0x10, + 0xf3, 0x43, 0xb6, 0xa4, 0xca, 0x34, 0xe8, 0x39, 0x79, 0xb4, 0xde, 0xa1, + 0x81, 0xa3, 0xb9, 0x2d, 0x91, 0x59, 0x21, 0x22, 0x82, 0xed, 0x69, 0xe1, + 0x2a, 0x3d, 0x10, 0x9d, 0x81, 0xe7, 0x24, 0x7f, 0xda, 0xac, 0x55, 0xa3, + 0xf3, 0x09, 0xfd, 0x91, 0x3a, 0xab, 0xd4, 0x11, 0x62, 0x1f, 0xbd, 0x2d, + 0xff, 0x6d, 0x8a, 0x74, 0x43, 0x99, 0x8e, 0x3c, 0x32, 0xce, 0x9b, 0xa3, + 0x3f, 0x81, 0xbe, 0x0b, 0x87, 0x66, 0x0f, 0xed, 0x10, 0xe1, 0x99, 0x5a, + 0xf4, 0xc2, 0x8a, 0xc8, 0xb8, 0x99, 0x5a, 0x2d, 0x88, 0xf8, 0x0b, 0x76, + 0x40, 0x6c, 0xef, 0xff, 0xcd, 0x3a, 0x5b, 0xe6, 0xe6, 0xac, 0x44, 0x1c, + 0xc5, 0xd3, 0xba, 0xe5, 0xde, 0xd3, 0x57, 0x93, 0xb1, 0xba, 0xad, 0x04, + 0xde, 0x76, 0x54, 0x14, 0xfe, 0x5d, 0x52, 0xcd, 0xbf, 0x8d, 0xfb, 0x32, + 0x0c, 0x97, 0xfc, 0x08, 0xf0, 0xab, 0x01, 0x1a, 0xa3, 0x0f, 0xb3, 0x8a, + 0x35, 0xa9, 0xb6, 0xc9, 0xf9, 0xcf, 0x55, 0x43, 0x77, 0x2a, 0xdf, 0x17, + 0x2c, 0xff, 0x09, 0xbf, 0x64, 0x22, 0xf8, 0x0e, 0x48, 0xf0, 0x8d, 0x92, + 0xea, 0x2d, 0x81, 0xc4, 0x30, 0x4d, 0xd6, 0x42, 0x99, 0x7a, 0xd2, 0xbc, + 0xa7, 0x6e, 0xbb, 0x0f, 0x2a, 0xd0, 0x29, 0x15, 0xfe, 0xb3, 0x03, 0x96, + 0xe0, 0xdb, 0x1f, 0x33, 0x05, 0x80, 0x94, 0x8b, 0xb4, 0xeb, 0x4a, 0xd3, + 0x8f, 0x60, 0xd9, 0xa2, 0x27, 0x66, 0x35, 0xa4, 0x93, 0x8f, 0xee, 0xfb, + 0x9b, 0xda, 0xc4, 0x1d, 0xca, 0xd0, 0x24, 0x0b, 0x9f, 0x57, 0x8a, 0x51, + 0x99, 0xb5, 0x98, 0x20, 0x38, 0x57, 0x53, 0xf4, 0x10, 0x38, 0x6f, 0xa8, + 0x9a, 0x0f, 0x7e, 0x71, 0x21, 0x58, 0x36, 0xac, 0x2c, 0xde, 0x85, 0x1a, + 0x71, 0xd0, 0x1d, 0x56, 0xf0, 0x2c, 0x85, 0x37, 0x02, 0xe3, 0x7a, 0xc8, + 0x51, 0x0d, 0x2c, 0x58, 0x19, 0x63, 0x95, 0x68, 0xba, 0xa9, 0x7b, 0x82, + 0x09, 0x10, 0xa9, 0xd5, 0x58, 0x6a, 0xba, 0x25, 0xd1, 0xce, 0x91, 0xa7, + 0xd4, 0xc2, 0xbc, 0x63, 0x49, 0x09, 0x41, 0x76, 0xcb, 0xb7, 0xae, 0xc4, + 0x17, 0x2a, 0x98, 0xb6, 0x13, 0xfb, 0x4c, 0x45, 0x98, 0xd3, 0x4c, 0xe0, + 0xbd, 0x9f, 0xab, 0x02, 0xe9, 0xd1, 0x87, 0xb0, 0x22, 0x86, 0x8f, 0xd8, + 0x20, 0x71, 0x83, 0xbb, 0xe4, 0x4e, 0x8a, 0x0e, 0x95, 0xf9, 0xed, 0xdf, + 0x72, 0x99, 0x00, 0x73, 0x41, 0xb0, 0xb9, 0x80, 0x0e, 0xa2, 0x3c, 0x1f, + 0xb1, 0x9c, 0x05, 0x7a, 0x5f, 0x2b, 0xc8, 0xab, 0xca, 0x6a, 0xfa, 0x4b, + 0x2a, 0x5b, 0xa0, 0x34, 0x57, 0x5a, 0x5e, 0x42, 0xfe, 0x97, 0x17, 0x40, + 0xef, 0x17, 0xd2, 0x28, 0xe0, 0xf1, 0xc4, 0x1a, 0x7b, 0x7b, 0x92, 0x6a, + 0x92, 0x5a, 0x38, 0xa7, 0xcf, 0xcd, 0x55, 0x94, 0x00, 0x20, 0x54, 0x6f, + 0x56, 0xe3, 0x73, 0xcc, 0xd5, 0xbd, 0x32, 0x77, 0xb5, 0x34, 0x11, 0xdd, + 0xcd, 0xb2, 0xef, 0x0f, 0x3a, 0x0a, 0x75, 0xde, 0x0b, 0x96, 0x1c, 0xab, + 0x64, 0x17, 0xee, 0x01, 0x38, 0xfb, 0xa9, 0x5e, 0x83, 0x20, 0x5c, 0x14, + 0xe4, 0x63, 0x2e, 0x14, 0xa5, 0xb0, 0x1a, 0xa0, 0x7c, 0xd1, 0xd0, 0x17, + 0xa4, 0xff, 0xad, 0x9c, 0xf5, 0x4d, 0x1d, 0xab, 0xd9, 0xd7, 0xa4, 0x7c, + 0xe1, 0xdb, 0x12, 0x58, 0x34, 0xe0, 0x96, 0x7c, 0x6d, 0xc9, 0x2c, 0x0b, + 0xb1, 0xde, 0x50, 0xb7, 0x9c, 0x05, 0x76, 0x18, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x10, 0x7e, 0xa6, 0x9a, 0x51, 0xa9, 0x41, 0x43, + 0x24, 0x81, 0xdb, 0x04, 0x2e, 0xcc, 0xc5, 0xc3, 0xf8, 0xaa, 0x9c, 0xda, + 0x34, 0x8f, 0x6d, 0xa3, 0x57, 0xf0, 0x01, 0x89, 0x65, 0x3c, 0x52, 0x10, + 0xde, 0x8a, 0x44, 0xca, 0xb7, 0xcd, 0xe0, 0xee, 0x66, 0x4b, 0x45, 0xfd, + 0x0d, 0x30, 0x24, 0x11, 0x1b, 0x01, 0xb0, 0x6d, 0xd1, 0xf5, 0x4e, 0x38, + 0x39, 0x26, 0x40, 0xaf, 0x1c, 0xec, 0xca, 0x2a, 0xaf, 0x39, 0xb0, 0xa8, + 0x7c, 0xee, 0x15, 0xf1, 0x9c, 0xef, 0x0d, 0xb0, 0x95, 0x7b, 0xde, 0xbe, + 0xc6, 0xbf, 0xc4, 0x7e, 0x68, 0xe0, 0xc7, 0xba, 0xd2, 0xcb, 0x2d, 0x6f, + 0xb5, 0xd2, 0x77, 0x1f, 0x59, 0x30, 0x0c, 0xd8, 0x91, 0x0d, 0x33, 0xc6, + 0xaf, 0xcc, 0xfa, 0xfc, 0x5e, 0x83, 0x0b, 0x23, 0x28, 0xc4, 0x2a, 0x8e, + 0xb0, 0xef, 0x90, 0xa3, 0x40, 0x02, 0x27, 0x80, 0x83, 0xda, 0x3e, 0x02, + 0xae, 0x8d, 0x5a, 0x3e, 0x91, 0xa9, 0x47, 0x31, 0x19, 0x33, 0x87, 0x32, + 0xa3, 0x49, 0xeb, 0x4b, 0xc5, 0xea, 0xc3, 0x1a, 0x78, 0x85, 0xb8, 0x84, + 0x13, 0x9b, 0xa9, 0x72, 0xf5, 0xe3, 0x87, 0x1d, 0x72, 0x5c, 0xac, 0x02, + 0x28, 0x4d, 0x83, 0xec, 0x24, 0x0d, 0xab, 0x74, 0xd6, 0x02, 0x14, 0x7b, + 0x9b, 0x7e, 0xda, 0x16, 0x24, 0x03, 0x31, 0x4e, 0xed, 0xaf, 0xd1, 0xfe, + 0x75, 0x28, 0x5d, 0x0f, 0x71, 0xcd, 0xf8, 0x0e, 0x0d, 0x07, 0xc7, 0xec, + 0x49, 0xe7, 0xc1, 0x6d, 0xf9, 0x13, 0x3c, 0x43, 0xca, 0x87, 0x09, 0xab, + 0x5e, 0xd2, 0x65, 0x47, 0x50, 0xb6, 0x9c, 0x27, 0x5f, 0xf3, 0xcd, 0x12, + 0x51, 0x5f, 0xba, 0xa9, 0x8e, 0xf2, 0x0d, 0x86, 0x73, 0x76, 0x50, 0x36, + 0xfa, 0x65, 0x3e, 0xa4, 0x1e, 0x2f, 0x40, 0x75, 0xf9, 0xf4, 0xfa, 0xf2, + 0x8f, 0xa9, 0xd9, 0x70, 0x79, 0x8f, 0x01, 0x1a, 0x07, 0x58, 0xee, 0x31, + 0x2d, 0x86, 0x09, 0xf7, 0x55, 0x6e, 0xdf, 0x74, 0x74, 0x60, 0xd4, 0x26, + 0x12, 0x6b, 0x28, 0xd1, 0x53, 0x6b, 0x8f, 0x22, 0x29, 0xf2, 0xd6, 0x29, + 0x1c, 0xb6, 0x3a, 0x09, 0x28, 0x6c, 0x3f, 0x32, 0xdb, 0x62, 0xe2, 0x56, + 0x69, 0xde, 0x23, 0x0c, 0x15, 0xb8, 0x17, 0x83, 0x1d, 0x1a, 0x61, 0xcb, + 0xd6, 0xe9, 0x9c, 0xa7, 0x88, 0xaa, 0xd2, 0x4a, 0xc4, 0x3e, 0xc0, 0x2f, + 0xf1, 0x5b, 0xfa, 0x8b, 0x9e, 0xae, 0x36, 0x50, 0x8c, 0x67, 0x68, 0x2f, + 0xda, 0xd8, 0x90, 0x28, 0x00, 0x76, 0x89, 0xe4, 0xe4, 0x3a, 0xea, 0xbc, + 0xc5, 0xa2, 0xd3, 0xf0, 0x4f, 0x45, 0x08, 0x16, 0x5c, 0x8f, 0x14, 0xb9, + 0x10, 0xa2, 0x2d, 0x33, 0x4a, 0xb0, 0xad, 0x22, 0xaa, 0x6b, 0xce, 0xf1, + 0xbf, 0x26, 0x34, 0xd4, 0xe4, 0x29, 0xe3, 0xb2, 0x81, 0x44, 0x4b, 0x75, + 0xb4, 0x72, 0x8b, 0x24, 0xab, 0xaa, 0x48, 0xce, 0x64, 0x21, 0xa3, 0xe5, + 0x58, 0xfe, 0xbd, 0x8d, 0x45, 0x03, 0x7f, 0x4c, 0x42, 0xa4, 0x6d, 0xc4, + 0x6f, 0x46, 0x02, 0xb5, 0xe8, 0x7e, 0xd0, 0x0a, 0x92, 0x78, 0x58, 0x00, + 0x85, 0x2e, 0x9f, 0x65, 0xa1, 0x8f, 0x65, 0x14, 0x9e, 0x9a, 0xc5, 0x8d, + 0xb2, 0x16, 0x7b, 0xef, 0x69, 0x95, 0x63, 0x94, 0x3c, 0xd4, 0xa4, 0x13, + 0xa2, 0xa9, 0xb3, 0xa3, 0x27, 0x58, 0x98, 0x1c, 0x2e, 0x4d, 0x0e, 0xe9, + 0x70, 0xac, 0x9d, 0x4a, 0x86, 0xed, 0x0d, 0x93, 0xcb, 0x7a, 0xa4, 0x23, + 0x7d, 0x17, 0x3f, 0xb1, 0x1b, 0xc2, 0x7f, 0x02, 0x51, 0x74, 0xd0, 0xb3, + 0x1b, 0xd7, 0xa9, 0x28, 0x9f, 0x6c, 0xb3, 0xad, 0x96, 0x28, 0xa1, 0xa5, + 0x5e, 0x1c, 0x15, 0xd3, 0x05, 0x76, 0x91, 0x62, 0xc5, 0xf3, 0xe9, 0x42, + 0x17, 0xbd, 0x0d, 0x37, 0x9e, 0x8a, 0x39, 0x37, 0x04, 0x48, 0x28, 0x1f, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x4e, 0xff, 0xa5, 0x71, + 0x1d, 0x44, 0x5e, 0x60, 0xf5, 0xff, 0x71, 0x7f, 0xe6, 0x35, 0x00, 0xbe, + 0x91, 0xbd, 0x08, 0x30, 0x52, 0x7c, 0x68, 0x41, 0x8c, 0x41, 0x31, 0xa3, + 0x4a, 0x78, 0x78, 0x07, 0x67, 0x60, 0x87, 0xee, 0xe7, 0xcb, 0xf4, 0xe5, + 0x3b, 0xe1, 0x60, 0xef, 0x57, 0xf3, 0x67, 0xc1, 0xcd, 0x95, 0x84, 0xbb, + 0x00, 0x9a, 0xa6, 0xeb, 0xc1, 0x0b, 0xa7, 0x25, 0xc9, 0x6b, 0x9b, 0x14, + 0x1f, 0x43, 0xe8, 0x70, 0x89, 0x65, 0x25, 0xd8, 0xa9, 0x54, 0xb1, 0x88, + 0xf4, 0x8d, 0xaa, 0x0d, 0x8e, 0xa5, 0xa3, 0xbc, 0x4d, 0xd4, 0x8f, 0x24, + 0xf0, 0x95, 0x9a, 0xb2, 0xbc, 0xf6, 0xd4, 0x20, 0xd5, 0x12, 0x94, 0x67, + 0x98, 0x1a, 0x3d, 0x1b, 0xfe, 0x2c, 0xef, 0xfc, 0x02, 0x00, 0x52, 0xd0, + 0x44, 0x8d, 0xfa, 0x7b, 0xe5, 0xb7, 0xa8, 0xba, 0xa2, 0x38, 0xb7, 0xd0, + 0xd5, 0x45, 0xca, 0x1e, 0x68, 0xe4, 0x04, 0xd0, 0x19, 0x72, 0x9e, 0x08, + 0x65, 0xe8, 0xe4, 0x04, 0xbd, 0xc0, 0x49, 0xda, 0x6f, 0x31, 0xa1, 0x6d, + 0xfa, 0x0a, 0x37, 0xf0, 0xc8, 0x92, 0xab, 0x8b, 0x52, 0xba, 0xb1, 0x1a, + 0x42, 0x36, 0x16, 0x56, 0x48, 0x2d, 0x63, 0xe9, 0xf5, 0x6f, 0x77, 0xc6, + 0xc3, 0x06, 0x82, 0x0a, 0xf8, 0x38, 0x52, 0x4b, 0x5e, 0x40, 0x93, 0x8c, + 0xf2, 0x89, 0x59, 0xa1, 0x57, 0xd4, 0x3a, 0x1c, 0xc0, 0x4a, 0x66, 0x23, + 0x60, 0x6e, 0x57, 0xa5, 0x3b, 0xee, 0x74, 0x71, 0x65, 0x3b, 0xa0, 0x4a, + 0x39, 0x12, 0x3b, 0x44, 0xd4, 0x19, 0x78, 0x83, 0x66, 0xd8, 0xc3, 0xa4, + 0x07, 0xe8, 0xcd, 0x04, 0x14, 0x2f, 0xe8, 0x93, 0xef, 0xc3, 0x7d, 0x52, + 0x21, 0x30, 0xf1, 0x22, 0x42, 0x6b, 0x98, 0xf8, 0x40, 0x27, 0x4a, 0x40, + 0xbf, 0xfe, 0x74, 0x86, 0x7b, 0xb9, 0xaf, 0x01, 0x82, 0x09, 0x7e, 0x01, + 0x0d, 0xd2, 0x67, 0x88, 0x92, 0x83, 0xf4, 0x01, 0xad, 0x76, 0x00, 0x76, + 0xb1, 0xaa, 0x78, 0xfc, 0xad, 0x5f, 0x4e, 0x1c, 0x8b, 0x6a, 0x2d, 0x48, + 0xfa, 0x34, 0xed, 0xc6, 0x98, 0xed, 0xcf, 0x2f, 0xa0, 0xb7, 0xb4, 0x88, + 0xb2, 0xd5, 0x5c, 0xbd, 0xfd, 0x54, 0x2d, 0xec, 0x46, 0xb2, 0x8a, 0x1a, + 0x54, 0x29, 0x28, 0x5e, 0x11, 0xaf, 0x9d, 0xf7, 0x63, 0x44, 0xcc, 0xa9, + 0xb2, 0xca, 0x18, 0x30, 0xb2, 0x83, 0x1d, 0xb0, 0x4c, 0xe3, 0x9e, 0x81, + 0xd0, 0x15, 0x9c, 0xa0, 0x26, 0x26, 0x66, 0x55, 0xd5, 0xcc, 0x0f, 0x5e, + 0xf2, 0x95, 0x3b, 0x2a, 0x82, 0x2a, 0xb1, 0x35, 0x30, 0x9e, 0x88, 0x2b, + 0x3b, 0xce, 0x66, 0x2b, 0x8d, 0x2d, 0x8c, 0xf0, 0xe5, 0xe8, 0x1f, 0x51, + 0x62, 0x15, 0x37, 0xe5, 0xc4, 0x0f, 0x4c, 0xc2, 0xde, 0xae, 0x0e, 0x82, + 0xac, 0xe5, 0xcb, 0xdf, 0x7d, 0x67, 0x25, 0x2f, 0x8e, 0x85, 0x3b, 0xeb, + 0x8f, 0xbc, 0xc7, 0x07, 0x46, 0xd0, 0x19, 0x73, 0xf1, 0x2d, 0x2f, 0x10, + 0x4c, 0xb1, 0x1f, 0xc1, 0x8b, 0x2c, 0x1a, 0x82, 0xce, 0x54, 0xaa, 0x81, + 0x94, 0x58, 0x8e, 0x20, 0x18, 0x38, 0x2c, 0xfa, 0xa0, 0xd3, 0x75, 0xb8, + 0x60, 0x25, 0x0b, 0x62, 0x4a, 0x3a, 0x4d, 0x14, 0xd3, 0xfc, 0x9d, 0x0d, + 0x07, 0x22, 0x60, 0xb3, 0x80, 0xeb, 0x28, 0x4f, 0x3d, 0xe6, 0x36, 0x01, + 0x7e, 0x06, 0xa2, 0xff, 0x92, 0x05, 0xda, 0x39, 0xbc, 0xb1, 0xc1, 0x8d, + 0xb7, 0xfe, 0xa5, 0x65, 0x42, 0x44, 0xba, 0x53, 0xa3, 0xfe, 0x4f, 0x80, + 0x54, 0x50, 0xaa, 0x89, 0x99, 0xf7, 0x9e, 0x2f, 0x11, 0x63, 0xe7, 0x82, + 0x37, 0x95, 0x0b, 0x86, 0xda, 0xb4, 0x27, 0xc2, 0xe6, 0xd4, 0xba, 0x92, + 0xac, 0xf8, 0x6b, 0x79, 0xdf, 0xdb, 0x30, 0xc3, 0x3e, 0xcd, 0x48, 0x2f, + 0x15, 0xcd, 0x61, 0x06, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x91, 0x55, 0xfa, 0xd5, 0x52, 0x11, 0xba, 0x5a, 0xc9, 0x5b, 0x2e, 0x7b, + 0x48, 0xa6, 0xde, 0xdc, 0x01, 0x5c, 0x5b, 0xb5, 0x9a, 0x0f, 0x67, 0x78, + 0xeb, 0x83, 0x80, 0xfe, 0xea, 0x4c, 0x6b, 0x16, 0x16, 0xef, 0xdd, 0x72, + 0x3c, 0x65, 0x71, 0x11, 0x85, 0x0c, 0x2f, 0xa7, 0x30, 0x63, 0xdb, 0xe8, + 0x9a, 0x4f, 0xb6, 0x7d, 0xe7, 0xa2, 0x41, 0xfa, 0xe3, 0x53, 0xfe, 0xb4, + 0x43, 0x05, 0x5c, 0x0f, 0x0f, 0xe3, 0x40, 0x47, 0xa9, 0xdd, 0x6a, 0x3e, + 0x08, 0x0f, 0xd3, 0x70, 0xce, 0x22, 0x30, 0x46, 0x45, 0x94, 0x12, 0x3c, + 0x4b, 0x1c, 0x6d, 0xfc, 0xc2, 0xbc, 0x54, 0x5b, 0x86, 0x49, 0x8c, 0x13, + 0x1d, 0xd8, 0x6c, 0xe2, 0xbb, 0x66, 0x70, 0x7a, 0x5d, 0xf4, 0x2e, 0xd4, + 0x22, 0x65, 0xfb, 0x73, 0x36, 0x0f, 0x19, 0x33, 0x7e, 0xa2, 0x05, 0xdd, + 0xc3, 0xfa, 0xcb, 0x8d, 0x2c, 0x0d, 0x34, 0x08, 0x58, 0x26, 0xeb, 0xc3, + 0xa8, 0x20, 0x39, 0xab, 0x15, 0x26, 0x20, 0xd8, 0x5b, 0x5e, 0xf0, 0x8b, + 0xbc, 0xa7, 0x73, 0xfd, 0xf3, 0xf7, 0xef, 0xf0, 0xb1, 0xbe, 0xa8, 0xe3, + 0x8b, 0x21, 0x78, 0x15, 0x7d, 0x6e, 0xa8, 0xfa, 0x18, 0x2e, 0x5d, 0x09, + 0xa0, 0xf4, 0x70, 0xde, 0x87, 0xd6, 0xa2, 0xf4, 0xfb, 0xa2, 0x07, 0x8d, + 0x5a, 0x83, 0x0a, 0x52, 0xd4, 0xae, 0x7b, 0xa5, 0x51, 0x4b, 0x62, 0x05, + 0x33, 0x93, 0x2e, 0x13, 0x6a, 0x55, 0xcd, 0x49, 0x7f, 0x22, 0x6e, 0x7a, + 0x07, 0xda, 0x64, 0x33, 0xe3, 0x6d, 0xee, 0xbd, 0xf9, 0xa6, 0xec, 0xbb, + 0xcd, 0xa0, 0xbc, 0x47, 0xbe, 0x09, 0x0f, 0x16, 0xee, 0x15, 0xd6, 0xb5, + 0xce, 0x71, 0x7b, 0xe9, 0x67, 0x3c, 0x0e, 0xa2, 0x82, 0x7e, 0x95, 0xc9, + 0xe7, 0x3d, 0xc8, 0x78, 0x59, 0x71, 0xbe, 0x45, 0xf9, 0x4d, 0x9b, 0xf3, + 0xde, 0x12, 0x17, 0x00, 0x55, 0x4c, 0xa1, 0xe4, 0x4f, 0xe6, 0xbb, 0xca, + 0x64, 0xf4, 0x16, 0x2c, 0x59, 0x64, 0x54, 0x44, 0x42, 0x16, 0xa8, 0xbf, + 0x8c, 0x68, 0xcf, 0x55, 0xfa, 0xae, 0x03, 0x6e, 0x15, 0xa8, 0x0a, 0x0c, + 0xf3, 0x38, 0x58, 0xa6, 0xcc, 0x62, 0x07, 0x48, 0x4d, 0x3c, 0xe1, 0xe8, + 0x48, 0x50, 0x33, 0x01, 0x3b, 0xfb, 0x90, 0x9e, 0x3a, 0x26, 0x95, 0x4a, + 0x19, 0x0c, 0xd6, 0x03, 0x0c, 0xd2, 0x81, 0x1a, 0xce, 0x02, 0x4c, 0xcd, + 0x54, 0x7c, 0xb1, 0x29, 0xfb, 0xff, 0x6e, 0xf7, 0xae, 0xe6, 0xdf, 0x98, + 0x26, 0x43, 0x46, 0x0e, 0x02, 0xa5, 0x22, 0xbe, 0x88, 0x0e, 0xb0, 0xd9, + 0x45, 0x99, 0x37, 0x0e, 0xb7, 0x15, 0xab, 0xfa, 0x7c, 0x00, 0x6b, 0x64, + 0xaf, 0x0a, 0x07, 0x81, 0x29, 0xb4, 0x41, 0x42, 0x18, 0x40, 0x62, 0x15, + 0xad, 0xa6, 0x67, 0xd5, 0x40, 0x98, 0xe8, 0x5f, 0xfa, 0xc2, 0xc1, 0x18, + 0x40, 0xf3, 0x84, 0x9a, 0x82, 0x43, 0x02, 0xad, 0xf5, 0x48, 0x52, 0xaa, + 0x3f, 0xa9, 0x80, 0xeb, 0x2f, 0xf6, 0xcf, 0xc0, 0x0b, 0xe3, 0xa5, 0xa6, + 0x08, 0x47, 0x96, 0x6e, 0x3f, 0x7a, 0x6b, 0x1d, 0x3a, 0x68, 0xdd, 0xe1, + 0x26, 0xb9, 0xdc, 0x94, 0x80, 0xdd, 0x90, 0x6e, 0x75, 0xe9, 0xed, 0x46, + 0x87, 0x49, 0xae, 0xac, 0xe2, 0x5b, 0x31, 0x35, 0x60, 0x83, 0x36, 0x7a, + 0xce, 0x7c, 0x54, 0x29, 0xc5, 0x5b, 0x01, 0x20, 0xc1, 0xcf, 0x1c, 0xe3, + 0xe1, 0xc2, 0x62, 0xba, 0x94, 0x41, 0xfb, 0x25, 0x15, 0x4b, 0xb2, 0x00, + 0x40, 0x78, 0xec, 0x97, 0x33, 0xf8, 0xfd, 0x04, 0xa3, 0x93, 0x80, 0x24, + 0x61, 0xe4, 0x21, 0x3d, 0xef, 0x59, 0x14, 0x5c, 0x7f, 0xe0, 0xc7, 0x53, + 0x3f, 0xd7, 0x5f, 0x3c, 0x4e, 0x5c, 0x33, 0x06, 0x80, 0x3d, 0x69, 0xb8, + 0x17, 0x0d, 0xfc, 0xa5, 0x91, 0x4e, 0x97, 0x1f, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x3c, 0x5e, 0xc3, 0x0f, 0x9f, 0xb6, 0x7b, 0xa2, + 0x11, 0x17, 0xd5, 0xc1, 0xce, 0x6c, 0x62, 0xd2, 0x75, 0x15, 0x7f, 0x90, + 0xff, 0x11, 0xb5, 0xba, 0x79, 0xe8, 0xc0, 0x0c, 0xfc, 0x4f, 0x4f, 0x08, + 0xc8, 0x5f, 0xeb, 0xa4, 0x5d, 0x56, 0xfc, 0x91, 0x07, 0x2e, 0x8f, 0x21, + 0x4b, 0x40, 0xab, 0xeb, 0xa5, 0x23, 0xe9, 0x58, 0x44, 0xc0, 0x85, 0x77, + 0x4d, 0x52, 0xf8, 0xe9, 0x5b, 0x8d, 0x0d, 0x15, 0xa9, 0x9a, 0xe5, 0x70, + 0xd6, 0xe8, 0xbd, 0x76, 0x12, 0x29, 0xb1, 0xa6, 0x9c, 0x19, 0x20, 0x67, + 0x98, 0x63, 0x9e, 0xee, 0xec, 0xe4, 0xa7, 0x73, 0xf8, 0xbf, 0xd1, 0x1a, + 0x7a, 0xba, 0x4a, 0x04, 0x99, 0x24, 0xf6, 0x72, 0x2e, 0x8a, 0xb8, 0x8c, + 0x79, 0x3f, 0x64, 0x19, 0xbc, 0xb8, 0x36, 0x70, 0x19, 0xaf, 0x71, 0x9e, + 0x77, 0xf4, 0xa4, 0x61, 0x6b, 0xec, 0x8d, 0x7c, 0xa3, 0xa7, 0x9d, 0x16, + 0x06, 0x3a, 0x1e, 0xf4, 0x50, 0xe5, 0xf7, 0xca, 0xad, 0x0b, 0x8f, 0xe3, + 0x24, 0x28, 0x9a, 0xac, 0xc4, 0xb8, 0x94, 0x0f, 0x2a, 0xfd, 0x45, 0xaa, + 0x15, 0x00, 0xc1, 0x54, 0x7d, 0xe0, 0xc2, 0x2c, 0x52, 0x4f, 0x6c, 0x72, + 0xc8, 0x24, 0x6e, 0x6d, 0x8d, 0xa7, 0x18, 0x42, 0xe2, 0x91, 0x1b, 0x82, + 0xd3, 0x27, 0xfd, 0x79, 0x0b, 0x97, 0x19, 0xe4, 0x28, 0x63, 0x85, 0x99, + 0xb7, 0xe3, 0xc3, 0x29, 0xe7, 0x7e, 0xd6, 0xb9, 0x34, 0x55, 0x1e, 0xe7, + 0x5c, 0xde, 0x63, 0xdd, 0x88, 0xf3, 0xf4, 0x65, 0xba, 0x8b, 0xf5, 0x70, + 0xfc, 0x92, 0x87, 0x59, 0xa2, 0x76, 0x7f, 0x62, 0xff, 0x80, 0x20, 0x10, + 0x10, 0x16, 0x46, 0x0b, 0xd6, 0xd7, 0x0a, 0xe1, 0xd0, 0x70, 0xce, 0x95, + 0xa7, 0xc9, 0x87, 0x41, 0xe1, 0xea, 0x31, 0x08, 0x94, 0xa2, 0x8c, 0x9a, + 0x5d, 0x2b, 0x1b, 0x5b, 0x79, 0x89, 0x59, 0x04, 0x3b, 0x6f, 0x3b, 0x80, + 0x88, 0xf6, 0xa8, 0x62, 0x4a, 0xcb, 0xfc, 0xe7, 0xb1, 0x2e, 0x7c, 0x4b, + 0x21, 0xf9, 0x5e, 0x80, 0x5e, 0x1b, 0x37, 0xb7, 0x60, 0x02, 0x24, 0xd3, + 0xd3, 0xa1, 0x8b, 0x05, 0xcc, 0x11, 0xc7, 0xe3, 0x7a, 0x2d, 0xf9, 0x2f, + 0x06, 0x21, 0x4e, 0x4a, 0x86, 0x87, 0xbc, 0x92, 0x7f, 0xb7, 0xc9, 0x29, + 0xd8, 0x24, 0x83, 0x71, 0xb7, 0xbf, 0x87, 0x83, 0xf7, 0xc8, 0x04, 0x15, + 0xeb, 0x20, 0x35, 0x88, 0x01, 0x86, 0x94, 0x1c, 0xd0, 0x41, 0xd8, 0xf1, + 0x55, 0x71, 0x61, 0x86, 0xfd, 0x1d, 0x88, 0x51, 0x99, 0xb7, 0xb7, 0x43, + 0x9e, 0x5d, 0x2f, 0xa6, 0x47, 0x33, 0x3b, 0x2d, 0x5b, 0x6c, 0x44, 0x37, + 0xcd, 0x8e, 0xc3, 0xa0, 0xa1, 0x14, 0x08, 0x72, 0x4d, 0x58, 0xed, 0xec, + 0x40, 0x94, 0x82, 0x19, 0x1a, 0x19, 0xd1, 0xc2, 0xeb, 0x70, 0xcc, 0xe9, + 0x16, 0x8d, 0x15, 0x22, 0xc2, 0x2f, 0x19, 0x3d, 0x10, 0x62, 0x41, 0x23, + 0x82, 0x60, 0x98, 0xe6, 0xcf, 0x51, 0xe2, 0xdd, 0x9d, 0x36, 0xec, 0xa2, + 0x21, 0xfa, 0xa8, 0x45, 0x39, 0x94, 0x69, 0xae, 0xf4, 0x35, 0x30, 0x29, + 0x3f, 0x90, 0x52, 0xed, 0x2e, 0x7b, 0x08, 0xf2, 0x40, 0xa8, 0xc9, 0x54, + 0x0a, 0x24, 0xf9, 0xc5, 0x09, 0x24, 0xf5, 0x8d, 0xbe, 0xd6, 0x17, 0x5b, + 0xe9, 0x5a, 0xc5, 0x10, 0x01, 0x6b, 0x7d, 0x2f, 0x82, 0xef, 0x1b, 0x30, + 0x74, 0xe6, 0x68, 0xdc, 0x31, 0x21, 0xd0, 0xc8, 0xae, 0x36, 0x6d, 0xa0, + 0xbf, 0xc7, 0x83, 0x45, 0x29, 0x36, 0x16, 0x00, 0xb0, 0x54, 0x28, 0xfb, + 0x2a, 0x38, 0x2f, 0x26, 0x92, 0x9e, 0x44, 0xa6, 0x40, 0x56, 0x1b, 0xc2, + 0x0d, 0x69, 0x80, 0x68, 0xad, 0xd7, 0x0e, 0x2b, 0x43, 0xe3, 0x68, 0x67, + 0x39, 0x26, 0xcd, 0x52, 0x64, 0xe8, 0xc9, 0x5f, 0x15, 0x21, 0x8c, 0x24, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xa9, 0xf6, 0xa9, 0xf7, + 0x6c, 0x94, 0x63, 0x04, 0xeb, 0x87, 0xeb, 0xd4, 0x50, 0xfb, 0xa9, 0xa4, + 0xb6, 0x04, 0x6b, 0xb4, 0x3d, 0x82, 0x45, 0x33, 0x24, 0xa3, 0x37, 0xb3, + 0xff, 0x06, 0x1c, 0x23, 0x24, 0x08, 0x47, 0xad, 0x75, 0x7c, 0xb5, 0x86, + 0x67, 0x75, 0xc7, 0x26, 0x8b, 0xe6, 0xaf, 0x88, 0x0b, 0xd7, 0x4b, 0x81, + 0x65, 0x6a, 0xed, 0x5c, 0xfe, 0x7c, 0x2c, 0x7c, 0x31, 0xfe, 0x4e, 0x23, + 0x96, 0xc7, 0x82, 0xf6, 0xc2, 0x15, 0x50, 0x6e, 0xa1, 0x3e, 0x2a, 0xf7, + 0x8a, 0x43, 0x7c, 0xf5, 0x03, 0x13, 0x03, 0x70, 0xde, 0x95, 0xa9, 0xc3, + 0x58, 0x2f, 0x93, 0x6a, 0xa2, 0x78, 0x11, 0x1c, 0x8a, 0x7c, 0xc8, 0x99, + 0x70, 0x2d, 0xe6, 0x14, 0xc8, 0xf9, 0xb6, 0x59, 0x54, 0xd0, 0x1a, 0x0f, + 0x03, 0x75, 0xef, 0x7e, 0x7e, 0x24, 0xff, 0xf2, 0x7e, 0xa1, 0xb0, 0x0d, + 0x30, 0x01, 0xd1, 0x0a, 0xa6, 0xe5, 0xc9, 0xc9, 0x89, 0x05, 0x1a, 0x6f, + 0xc0, 0xd6, 0x73, 0xac, 0xd1, 0x06, 0x86, 0x57, 0xe3, 0x68, 0x30, 0x62, + 0x57, 0xd9, 0x01, 0x83, 0x77, 0xe4, 0xdf, 0xe9, 0x34, 0x11, 0x5f, 0x01, + 0xc3, 0x81, 0x6d, 0xa2, 0x02, 0x3a, 0x00, 0xcf, 0x3d, 0x6e, 0x88, 0xb2, + 0x16, 0x25, 0x3b, 0xe8, 0x20, 0x92, 0x53, 0xbb, 0x6c, 0x5c, 0x9e, 0xea, + 0x5a, 0xc6, 0xfb, 0x33, 0x63, 0x7f, 0x29, 0x11, 0x18, 0xc0, 0x4f, 0xf4, + 0x3d, 0x12, 0xcd, 0x40, 0xec, 0xbf, 0xbe, 0x58, 0xe9, 0x99, 0x4f, 0x11, + 0xeb, 0xa3, 0xc8, 0x7d, 0x5d, 0xa1, 0x13, 0x71, 0xeb, 0x7b, 0x95, 0x47, + 0x95, 0xf2, 0x83, 0x04, 0x9a, 0x04, 0xc6, 0x5a, 0x16, 0x42, 0x8a, 0xa8, + 0xd2, 0xf6, 0xeb, 0xa3, 0xe3, 0xe3, 0x77, 0x6d, 0x1c, 0x7a, 0x59, 0xa2, + 0x32, 0xd3, 0x2e, 0xe3, 0xb8, 0xf7, 0xb7, 0x13, 0x10, 0x10, 0xd4, 0x16, + 0x43, 0xce, 0x35, 0xf7, 0xc3, 0xef, 0x76, 0x83, 0x54, 0x56, 0xc0, 0x5f, + 0x69, 0x35, 0x99, 0x18, 0x6f, 0x90, 0x9a, 0x6b, 0x5b, 0xf2, 0xc0, 0x2c, + 0x8f, 0xe0, 0x78, 0x1f, 0x23, 0x4c, 0x21, 0x1f, 0xd9, 0xa4, 0x18, 0x7e, + 0x7d, 0x37, 0x30, 0x00, 0xd3, 0xe3, 0xfc, 0x72, 0xb6, 0x57, 0xd1, 0x22, + 0x8b, 0x47, 0x93, 0xaf, 0x62, 0x7f, 0xec, 0xcc, 0xae, 0x47, 0xbe, 0x23, + 0xde, 0x92, 0xfb, 0x26, 0x15, 0x97, 0xda, 0xf0, 0x3b, 0x07, 0x8a, 0xbf, + 0x0f, 0xc1, 0xb2, 0x4c, 0xd8, 0xaf, 0xd5, 0x02, 0x0a, 0xc4, 0x96, 0xa6, + 0xee, 0xdc, 0xd6, 0x0e, 0x46, 0xe9, 0x2d, 0x53, 0x7b, 0x84, 0x04, 0x26, + 0x7a, 0xac, 0xee, 0x34, 0xd9, 0xac, 0x98, 0xa3, 0x72, 0xf9, 0xba, 0x2d, + 0x03, 0xad, 0x65, 0x59, 0x52, 0xb0, 0x39, 0x16, 0xe7, 0x36, 0x6b, 0xb3, + 0xac, 0x29, 0xe9, 0x80, 0xa6, 0xd1, 0x3f, 0x17, 0xdf, 0x3d, 0xfe, 0x33, + 0xe8, 0x7b, 0xf9, 0xea, 0x18, 0xc5, 0x5b, 0x9b, 0x18, 0x90, 0x29, 0x97, + 0xc4, 0xa1, 0x56, 0x69, 0x51, 0x82, 0x21, 0x4b, 0xe7, 0x59, 0x35, 0x51, + 0xe0, 0xec, 0x8c, 0x29, 0xae, 0xbf, 0x47, 0x71, 0xef, 0xc0, 0xc0, 0xc0, + 0x77, 0x69, 0x18, 0x77, 0x12, 0x89, 0x39, 0x65, 0x61, 0x96, 0xa3, 0x71, + 0x12, 0xa0, 0x84, 0xf7, 0x71, 0x4a, 0xc4, 0x45, 0x20, 0x1a, 0x3b, 0x22, + 0x95, 0x96, 0x2c, 0xb2, 0x7a, 0x45, 0xca, 0x81, 0x86, 0x29, 0x51, 0x82, + 0x01, 0x76, 0xef, 0x55, 0x7c, 0x7b, 0xc3, 0x53, 0x96, 0x3b, 0x18, 0x86, + 0x95, 0xb5, 0x16, 0x93, 0x6f, 0xf0, 0xc9, 0x25, 0x60, 0x42, 0x7d, 0x2b, + 0x2b, 0xab, 0x0d, 0xef, 0xfc, 0xc6, 0x44, 0xa4, 0xd6, 0x59, 0x0c, 0x33, + 0x9d, 0x91, 0xef, 0x4b, 0x7c, 0xc4, 0xab, 0x44, 0x4e, 0xe2, 0xe5, 0x26, + 0x4e, 0xb0, 0xd6, 0x1c, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0xed, 0x77, 0x96, 0x9f, 0x97, 0x4a, 0x9f, 0x90, 0xa4, 0xcc, 0xc9, 0xdd, + 0x32, 0x07, 0xe6, 0xd6, 0x57, 0x54, 0x9e, 0xde, 0xed, 0xcf, 0x47, 0x40, + 0x7e, 0x05, 0x6b, 0xb1, 0xcb, 0x1d, 0x43, 0x06, 0xd1, 0x98, 0xef, 0xd0, + 0x7e, 0xac, 0x59, 0x6a, 0x5b, 0xd5, 0x8a, 0x25, 0xd2, 0xda, 0x20, 0x9a, + 0x10, 0xac, 0xf3, 0x0f, 0x8d, 0x26, 0x3e, 0x24, 0x2a, 0x09, 0x69, 0x91, + 0x7a, 0xed, 0xfe, 0x06, 0x5c, 0xf3, 0xf7, 0xf5, 0xc9, 0x05, 0x48, 0x3d, + 0xb7, 0xba, 0xdd, 0xab, 0x9d, 0xa1, 0xaa, 0x2a, 0xd1, 0xee, 0xd9, 0x88, + 0x40, 0x22, 0xb3, 0x23, 0x7d, 0x00, 0xa2, 0x30, 0x3b, 0x41, 0x6c, 0x24, + 0x2c, 0x3e, 0x16, 0xb1, 0x86, 0x6f, 0x1d, 0x63, 0xc5, 0x65, 0xa3, 0x6f, + 0x94, 0x74, 0x90, 0xbf, 0xa8, 0xb0, 0xa9, 0xd2, 0x7d, 0xf4, 0x59, 0xc1, + 0x87, 0xea, 0xcf, 0xec, 0xda, 0xc8, 0x07, 0x03, 0x9e, 0x70, 0xd4, 0x88, + 0x19, 0x03, 0x4b, 0xa9, 0xca, 0x1e, 0x90, 0x21, 0x67, 0x8e, 0x54, 0xde, + 0xc3, 0x68, 0x2c, 0x52, 0x62, 0x51, 0x4c, 0xf9, 0xb6, 0x2b, 0x76, 0x1b, + 0xcc, 0x0d, 0x83, 0x1e, 0x52, 0xad, 0xc1, 0xd5, 0xff, 0xc5, 0xc4, 0xb5, + 0xcd, 0x42, 0xae, 0xc2, 0x65, 0xae, 0x59, 0x57, 0x3b, 0xe9, 0x72, 0xc5, + 0xbb, 0xc2, 0x1b, 0x76, 0x4a, 0x3b, 0x00, 0x62, 0x4c, 0x23, 0xb3, 0x22, + 0xab, 0xb5, 0x7d, 0x8c, 0x01, 0xc5, 0xef, 0xbf, 0x14, 0x62, 0xc5, 0xd9, + 0x13, 0x76, 0x1e, 0xe4, 0x97, 0xbc, 0xd5, 0xf7, 0xc2, 0x65, 0x8c, 0x1d, + 0xa7, 0x81, 0xa6, 0xc1, 0x71, 0xa7, 0xa2, 0x2d, 0x6a, 0x5b, 0x28, 0x84, + 0x6a, 0xfc, 0x4f, 0x55, 0xf0, 0x38, 0x64, 0x40, 0x75, 0xac, 0x2f, 0xd8, + 0x66, 0x16, 0xb2, 0xc8, 0x67, 0x1c, 0x45, 0x62, 0xf7, 0x26, 0x25, 0x8a, + 0x0f, 0x4c, 0xb1, 0x18, 0xbd, 0x6c, 0x35, 0x71, 0x4a, 0xe6, 0x0e, 0x81, + 0x49, 0x48, 0x6e, 0x4a, 0x8a, 0x87, 0xfa, 0x47, 0x76, 0x59, 0xb8, 0x43, + 0x32, 0x3c, 0x3f, 0xa7, 0x7a, 0xa4, 0x29, 0xa4, 0x68, 0x3c, 0x9e, 0x01, + 0x62, 0xfe, 0x9d, 0x5c, 0xa2, 0x51, 0xbd, 0x6b, 0x2d, 0x75, 0xcb, 0x29, + 0x41, 0x90, 0x36, 0x10, 0x79, 0xfd, 0x22, 0x44, 0xd4, 0x1d, 0x14, 0xd7, + 0xa5, 0xd9, 0xdd, 0x28, 0xb7, 0xfe, 0x12, 0x1b, 0xe0, 0xcf, 0xc2, 0xa7, + 0x97, 0xeb, 0xd2, 0x1a, 0x81, 0x07, 0x1b, 0xb3, 0xc5, 0xb7, 0xa3, 0x25, + 0xec, 0xba, 0x5c, 0x99, 0xf6, 0x63, 0xd6, 0x60, 0x76, 0x86, 0xd5, 0xeb, + 0x9c, 0xc1, 0x38, 0x0a, 0x4d, 0xf7, 0x01, 0x0d, 0x5b, 0x30, 0x7e, 0x1b, + 0xe1, 0xd4, 0x56, 0x85, 0xfd, 0x5c, 0x1d, 0x62, 0x2d, 0xd7, 0x12, 0x44, + 0xd3, 0x17, 0x79, 0xac, 0x9e, 0xad, 0x5b, 0x3f, 0x2a, 0x21, 0xe6, 0x2d, + 0x55, 0x83, 0x42, 0x4c, 0x3f, 0x2d, 0xca, 0xf4, 0x3c, 0xb1, 0xb5, 0xfe, + 0x37, 0xd6, 0xf0, 0x13, 0x7a, 0x98, 0xc3, 0xed, 0xb3, 0x6a, 0x9f, 0xdd, + 0x6d, 0x7c, 0xf3, 0x11, 0x9c, 0x96, 0x50, 0x0c, 0x70, 0x0a, 0x06, 0x8b, + 0x06, 0x29, 0xe5, 0xc7, 0xe2, 0x22, 0xad, 0xf5, 0x94, 0xd2, 0x57, 0x3e, + 0x2f, 0xa6, 0x2c, 0x8f, 0x33, 0x6b, 0xe9, 0x46, 0xfc, 0x69, 0xc9, 0x29, + 0x4d, 0x41, 0xb2, 0x24, 0xe6, 0xd3, 0xba, 0xab, 0xd2, 0x19, 0xe7, 0x24, + 0x82, 0xf2, 0x07, 0x32, 0x8f, 0x6d, 0xa4, 0x84, 0x12, 0xf6, 0xa0, 0xe3, + 0x5d, 0x50, 0x14, 0x23, 0x25, 0x3d, 0x56, 0x76, 0x4b, 0xf5, 0xc1, 0x21, + 0x4e, 0x6f, 0x6a, 0xd5, 0x86, 0x43, 0x10, 0x8e, 0xa2, 0x18, 0xca, 0xf6, + 0xac, 0x8d, 0x69, 0x38, 0x91, 0x04, 0xd3, 0x8b, 0x1c, 0x6b, 0xec, 0x05, + 0x1a, 0x4b, 0xb6, 0x82, 0x41, 0xbe, 0x05, 0x0d, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0xe5, 0x35, 0xfa, 0x11, 0x45, 0x61, 0x56, 0xf8, + 0x53, 0x3a, 0x5a, 0x44, 0xa2, 0x82, 0x55, 0x09, 0x5e, 0xed, 0x8d, 0x89, + 0x7a, 0xa0, 0x33, 0x5f, 0x5b, 0x46, 0x79, 0x19, 0xb4, 0x35, 0xe5, 0x05, + 0x8c, 0x34, 0xad, 0x9d, 0x91, 0x17, 0x72, 0x38, 0x35, 0x6b, 0x3f, 0x3b, + 0x23, 0x0a, 0xa8, 0x1d, 0xd7, 0x6a, 0xf0, 0xd5, 0x2c, 0x2f, 0xdc, 0x70, + 0x8f, 0xbf, 0x6c, 0x09, 0xfa, 0x84, 0x78, 0x14, 0xba, 0x4e, 0xf0, 0xfa, + 0xbf, 0x72, 0x56, 0xa1, 0x1b, 0xc8, 0xf9, 0xf8, 0xb4, 0x90, 0xfc, 0xd7, + 0x0a, 0x1d, 0x85, 0xa7, 0x9f, 0x96, 0xb1, 0x31, 0xfa, 0x66, 0x36, 0xa4, + 0x10, 0x54, 0x3b, 0x1a, 0xd1, 0x70, 0x79, 0xea, 0x9f, 0x00, 0x9a, 0xe2, + 0x57, 0x48, 0xe3, 0x1c, 0x80, 0x91, 0x37, 0x73, 0x06, 0xde, 0xce, 0x35, + 0xe7, 0x53, 0x55, 0x8f, 0x09, 0xe4, 0x45, 0x61, 0x86, 0xe2, 0x9a, 0x03, + 0x1f, 0x52, 0x1d, 0xa6, 0xe2, 0x8f, 0x10, 0xec, 0x43, 0x8c, 0x71, 0x75, + 0x2c, 0x93, 0x8a, 0x7b, 0x9c, 0x10, 0xa5, 0x3f, 0x27, 0x4f, 0x84, 0xc0, + 0x25, 0xfb, 0xef, 0x14, 0x59, 0xb4, 0xab, 0x0c, 0xfe, 0xe3, 0x0d, 0xee, + 0x0e, 0xb4, 0xe1, 0x17, 0x13, 0xcb, 0x8d, 0xfb, 0x6a, 0x47, 0x11, 0xa1, + 0x85, 0x04, 0xf4, 0xd1, 0x92, 0x02, 0xc8, 0x6a, 0x62, 0x95, 0xb1, 0x66, + 0x09, 0xb3, 0x50, 0x23, 0x81, 0x96, 0xcc, 0x0f, 0x8c, 0x1f, 0x7c, 0x4c, + 0x9f, 0x62, 0x61, 0x0c, 0x92, 0x74, 0xe0, 0x06, 0x28, 0xa6, 0x8d, 0xfa, + 0x19, 0xd3, 0x64, 0x6a, 0xbd, 0x1a, 0x4f, 0x70, 0x84, 0xed, 0xd4, 0x01, + 0xda, 0x8b, 0xcf, 0xd3, 0x7d, 0x48, 0xbe, 0x49, 0xc7, 0x9e, 0x7f, 0xa5, + 0xc8, 0x58, 0x87, 0xa8, 0x58, 0xe2, 0x6a, 0xdb, 0x5e, 0xbe, 0xb1, 0x39, + 0x11, 0xf6, 0xa3, 0xdb, 0x4d, 0xbc, 0x57, 0x0d, 0x30, 0xd4, 0xc9, 0x26, + 0xad, 0xe7, 0x94, 0xdc, 0xbc, 0x84, 0x43, 0x43, 0x4f, 0x31, 0x7b, 0x90, + 0x08, 0x3d, 0xe8, 0xfb, 0xc7, 0xda, 0xda, 0x1e, 0x24, 0x45, 0xf2, 0xf7, + 0x77, 0x36, 0x14, 0x26, 0xfe, 0xd3, 0x6e, 0x93, 0x90, 0x0a, 0x6b, 0x3e, + 0xed, 0x7a, 0x6d, 0xfb, 0x7a, 0xe1, 0xdc, 0xdb, 0x16, 0x76, 0x83, 0xe8, + 0xa9, 0xf9, 0x79, 0x0e, 0x8a, 0xf7, 0xde, 0x3a, 0xe5, 0x8f, 0x80, 0x27, + 0xf0, 0xe6, 0xda, 0xff, 0x8f, 0x53, 0x5a, 0x45, 0x76, 0x37, 0x89, 0x32, + 0xf5, 0xc2, 0x1a, 0x23, 0xe9, 0x4d, 0x6b, 0x01, 0xea, 0xc8, 0x23, 0x6b, + 0x9e, 0x6f, 0x43, 0xc5, 0x4b, 0x9a, 0x80, 0x03, 0xfe, 0x3c, 0x49, 0x41, + 0x66, 0x41, 0x86, 0x3f, 0x5c, 0x07, 0x48, 0xaa, 0xe9, 0x71, 0xa6, 0x61, + 0xa4, 0x95, 0x11, 0xc1, 0x63, 0x2e, 0x18, 0xe4, 0x6a, 0x35, 0x0e, 0x46, + 0x7d, 0xc5, 0x2f, 0x11, 0x5c, 0xf9, 0xf2, 0x81, 0x61, 0x46, 0xd4, 0x62, + 0x56, 0xf4, 0xf8, 0xeb, 0x27, 0x56, 0x45, 0x49, 0x77, 0x03, 0x09, 0x15, + 0x3c, 0x32, 0x85, 0x14, 0xa1, 0xe8, 0x6d, 0x5a, 0xe5, 0xf1, 0x68, 0x1c, + 0xcf, 0x86, 0xd6, 0xc9, 0xd0, 0xf7, 0xd6, 0x28, 0x3c, 0x63, 0xa0, 0x6c, + 0xa9, 0xdb, 0xa7, 0xeb, 0xbf, 0x32, 0x8b, 0xef, 0x56, 0x9b, 0xbf, 0x81, + 0xf4, 0x61, 0x16, 0x98, 0xcb, 0x77, 0x27, 0x0e, 0xd6, 0xaa, 0x5c, 0x34, + 0x1e, 0x19, 0xf7, 0xa6, 0x68, 0x46, 0x16, 0xd2, 0xee, 0x0e, 0x41, 0x9a, + 0xeb, 0x18, 0x07, 0x4d, 0x88, 0x34, 0xcf, 0x5a, 0x4d, 0x38, 0xb1, 0x91, + 0x60, 0xc3, 0x90, 0x26, 0x5d, 0x5c, 0x29, 0x07, 0x58, 0xb6, 0x14, 0xfc, + 0x35, 0xc5, 0x0e, 0x2e, 0xaa, 0xec, 0x70, 0x62, 0x51, 0x80, 0x6a, 0x9c, + 0xd9, 0x28, 0x43, 0x91, 0xa2, 0x0b, 0xcc, 0x40, 0x81, 0x84, 0xee, 0x03, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x27, 0xc9, 0xa3, 0xad, + 0xab, 0x24, 0x8c, 0x8c, 0xca, 0xcd, 0x9a, 0x9f, 0x9c, 0xd4, 0x1c, 0x73, + 0xee, 0x6c, 0xc7, 0x9b, 0xdc, 0x64, 0x70, 0x37, 0x03, 0x04, 0x1c, 0x6b, + 0xe3, 0x52, 0x77, 0x10, 0x61, 0xe1, 0xd1, 0x0c, 0xfa, 0xb9, 0xa0, 0x7d, + 0xe1, 0xda, 0xeb, 0x45, 0x9a, 0x82, 0x39, 0x45, 0x22, 0x62, 0x7c, 0x67, + 0xbd, 0x06, 0x8c, 0x19, 0x6d, 0xbb, 0x54, 0x2e, 0x65, 0xfd, 0xfe, 0x09, + 0x26, 0xc5, 0x7d, 0x2d, 0x45, 0x49, 0xe9, 0x56, 0x61, 0xd0, 0x8e, 0x87, + 0x5c, 0x1b, 0x5b, 0xc6, 0x18, 0x2b, 0x58, 0xce, 0xf8, 0x9a, 0xd5, 0xed, + 0xd5, 0x65, 0x8b, 0x60, 0x4b, 0xdf, 0x8f, 0x2b, 0x5c, 0xb0, 0x60, 0x73, + 0xba, 0xab, 0x17, 0xa8, 0xb4, 0x80, 0x89, 0x04, 0x35, 0x01, 0x66, 0x97, + 0xab, 0x29, 0x98, 0x98, 0x77, 0xb1, 0x62, 0x86, 0xce, 0xfe, 0xfa, 0xb5, + 0xbf, 0x29, 0x4d, 0x08, 0x28, 0xac, 0x5a, 0x29, 0x27, 0xca, 0xad, 0x80, + 0xbe, 0x47, 0xa3, 0xcb, 0xeb, 0x71, 0x71, 0x1e, 0x89, 0x3d, 0x63, 0xf9, + 0x1a, 0x32, 0x6f, 0x8b, 0xb0, 0x1b, 0x08, 0x08, 0x64, 0x58, 0xf7, 0x1e, + 0x70, 0x64, 0xb3, 0x01, 0xd6, 0xd4, 0xfa, 0x61, 0xa8, 0x66, 0x33, 0x7d, + 0x05, 0x4e, 0x53, 0xae, 0xe8, 0xae, 0x37, 0x05, 0x8e, 0x47, 0x70, 0xc5, + 0x51, 0x06, 0xea, 0x17, 0x99, 0x5b, 0xe9, 0x24, 0x31, 0x49, 0xa0, 0xc0, + 0xa2, 0xb7, 0x80, 0x2f, 0x93, 0xc2, 0xf9, 0x3a, 0x87, 0xb3, 0xe4, 0xd1, + 0x5e, 0x7c, 0x6d, 0xe8, 0x3f, 0x09, 0xee, 0xd5, 0x05, 0xca, 0x4b, 0x43, + 0x2c, 0x24, 0x8d, 0x0b, 0xb1, 0x13, 0x78, 0xcf, 0x25, 0x8c, 0x48, 0x6a, + 0x96, 0x47, 0x46, 0xaa, 0x7a, 0x41, 0xf2, 0x57, 0x44, 0xe8, 0xea, 0x3e, + 0xdc, 0xe9, 0x7c, 0xa1, 0x4c, 0x85, 0x12, 0x92, 0xe3, 0x3a, 0xc8, 0x06, + 0x95, 0xb8, 0xb6, 0x00, 0xeb, 0xdb, 0xe0, 0x5e, 0x84, 0x6b, 0xad, 0x67, + 0x5a, 0xc4, 0x51, 0x8d, 0x7b, 0x8d, 0x87, 0x0c, 0x5e, 0xd6, 0xf2, 0x47, + 0xc3, 0xf0, 0xaf, 0x56, 0xa5, 0x51, 0xd3, 0x26, 0xf2, 0x4c, 0x30, 0x8a, + 0x3f, 0x95, 0x12, 0x06, 0x11, 0xef, 0xbf, 0xd6, 0x0a, 0x68, 0xe9, 0xb1, + 0x6d, 0x64, 0x04, 0x45, 0x1f, 0x3c, 0x8b, 0x1d, 0xa7, 0xa9, 0x29, 0x32, + 0x71, 0x9e, 0x41, 0x09, 0xc2, 0xf4, 0xc5, 0x99, 0x83, 0xd9, 0xe5, 0x59, + 0x64, 0x52, 0xb6, 0xbd, 0x99, 0x70, 0x53, 0x76, 0xf6, 0xa3, 0xf9, 0x1f, + 0xb3, 0xb0, 0x74, 0x65, 0x1a, 0x23, 0x4d, 0x5f, 0x40, 0x6c, 0x9a, 0x13, + 0x2b, 0x96, 0xf6, 0x1e, 0x01, 0xa0, 0xf5, 0x24, 0xca, 0x00, 0x8c, 0x38, + 0xd1, 0xf0, 0xcd, 0xe4, 0x30, 0xb5, 0x71, 0x99, 0x35, 0x84, 0x68, 0x21, + 0x70, 0x82, 0xc6, 0xe0, 0x52, 0x7c, 0x48, 0x29, 0xa8, 0x01, 0x3e, 0x9a, + 0x3b, 0xb1, 0x2d, 0x86, 0xda, 0x30, 0xc0, 0x28, 0x26, 0xa0, 0xbb, 0xcf, + 0xf7, 0x91, 0x13, 0x2e, 0x2f, 0xfb, 0x65, 0x5e, 0xe5, 0x72, 0x17, 0x03, + 0x6d, 0x26, 0x9f, 0x0b, 0xaa, 0xa4, 0x6c, 0xeb, 0xc0, 0xd4, 0x9d, 0x96, + 0x60, 0x48, 0x3f, 0x6b, 0x37, 0x82, 0x89, 0xdc, 0xb5, 0x2b, 0x3d, 0xda, + 0xdc, 0xc8, 0x78, 0xc2, 0xb1, 0xe0, 0xaa, 0xd5, 0x3f, 0xad, 0x77, 0x19, + 0x9e, 0x4c, 0xe0, 0x52, 0x89, 0x3b, 0xa2, 0x6d, 0x72, 0x3d, 0x5e, 0x4f, + 0x3d, 0xe7, 0xe0, 0xff, 0xe9, 0x7b, 0x36, 0x45, 0xad, 0x4b, 0xc8, 0x2d, + 0xdc, 0x2f, 0x87, 0x5e, 0x20, 0x6b, 0x10, 0x12, 0x9a, 0x99, 0x06, 0xc0, + 0x64, 0x86, 0xa2, 0xd8, 0xc6, 0x4d, 0x1c, 0x21, 0x14, 0x32, 0xfd, 0xbb, + 0x37, 0xda, 0xb8, 0xe1, 0x59, 0x30, 0xfb, 0x71, 0x8d, 0xcc, 0x53, 0xe3, + 0xee, 0x7b, 0xe3, 0x03, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x7e, 0x95, 0x9c, 0x17, 0x3c, 0x12, 0xc7, 0x3e, 0x26, 0xd4, 0x81, 0x2b, + 0xfd, 0x6d, 0xff, 0x99, 0x07, 0xff, 0x5f, 0x14, 0xaa, 0xd6, 0x6a, 0xe5, + 0x4c, 0xac, 0x59, 0xd4, 0x9a, 0x7c, 0xa8, 0x06, 0x02, 0xf8, 0x19, 0x64, + 0x77, 0x41, 0x61, 0x5f, 0x46, 0xa4, 0x90, 0xd4, 0x8a, 0x90, 0xc9, 0x44, + 0xc0, 0xf1, 0xf6, 0x35, 0xcf, 0xaa, 0xb6, 0x49, 0x44, 0xb1, 0x41, 0xa4, + 0xe5, 0xa8, 0x20, 0x00, 0xe3, 0x7c, 0xc5, 0xaa, 0x07, 0x4d, 0x5a, 0x6d, + 0x11, 0xaa, 0x38, 0xb2, 0xf7, 0xfe, 0xb9, 0xc6, 0x50, 0x05, 0x19, 0x02, + 0x28, 0x38, 0xcc, 0xa3, 0xe3, 0x9e, 0x2d, 0xd2, 0xa4, 0xbf, 0xa0, 0x27, + 0xd6, 0xc4, 0xd1, 0xe6, 0x6c, 0x97, 0x93, 0x08, 0xc3, 0x8a, 0x2b, 0xcd, + 0x6c, 0xd6, 0x11, 0xd7, 0xe0, 0xfd, 0x61, 0xec, 0x9d, 0x94, 0xee, 0xcd, + 0x54, 0xd2, 0xdc, 0xda, 0x46, 0x44, 0x65, 0x03, 0x23, 0xdb, 0xd0, 0xb3, + 0xd0, 0x74, 0x66, 0xa0, 0x36, 0xcd, 0x78, 0x8b, 0x23, 0xcb, 0x33, 0xc2, + 0xdc, 0x94, 0xe2, 0x0b, 0x96, 0xc7, 0x0a, 0xcb, 0x05, 0xf5, 0xd3, 0xb7, + 0x36, 0x99, 0xe5, 0x1d, 0x8d, 0x9d, 0xfc, 0xbd, 0x59, 0x33, 0xea, 0x23, + 0xa1, 0x65, 0x1a, 0xe7, 0x9f, 0xad, 0x0f, 0x61, 0x8e, 0x4c, 0x97, 0x9f, + 0x57, 0xb2, 0x78, 0x8e, 0xee, 0x54, 0x7a, 0x25, 0x81, 0x1e, 0xf8, 0x04, + 0xab, 0x49, 0x75, 0x81, 0x0d, 0x26, 0x1f, 0x6d, 0xa3, 0xf9, 0x0a, 0x1c, + 0xbb, 0x10, 0xf5, 0xcb, 0xd7, 0x52, 0xb6, 0x5b, 0x7e, 0x7a, 0xcf, 0x76, + 0x51, 0x5f, 0x4d, 0x32, 0x57, 0x20, 0xa4, 0x19, 0x91, 0x38, 0x3e, 0xae, + 0x2f, 0x0f, 0x38, 0xd2, 0x89, 0x6e, 0xb7, 0x3d, 0xd3, 0x7d, 0xfd, 0xb6, + 0xc9, 0x35, 0x9e, 0x22, 0xff, 0x58, 0x54, 0x0f, 0x5d, 0xf1, 0xab, 0x61, + 0x73, 0xcb, 0xad, 0x29, 0x46, 0x4a, 0xaf, 0x9c, 0x32, 0x8b, 0x4d, 0x70, + 0x92, 0xcf, 0x0a, 0x64, 0x22, 0xfc, 0x4d, 0x7e, 0xc0, 0x20, 0x28, 0x79, + 0x29, 0x2a, 0xbe, 0x61, 0x0f, 0x10, 0xca, 0x1d, 0x59, 0xb1, 0x7f, 0x11, + 0xc2, 0xc2, 0xe1, 0x25, 0xa6, 0x23, 0x11, 0x25, 0x54, 0x77, 0x90, 0x49, + 0xa8, 0x00, 0xcd, 0xce, 0xc7, 0x01, 0x19, 0x44, 0xb7, 0xa1, 0x05, 0xa7, + 0xac, 0x67, 0x6d, 0x9f, 0xaa, 0x53, 0xfa, 0x0d, 0xb1, 0x91, 0x40, 0x15, + 0xe0, 0x0d, 0x3d, 0x3d, 0x07, 0x9f, 0x40, 0x55, 0xed, 0xc2, 0x0d, 0x5e, + 0x80, 0x1c, 0xca, 0xf1, 0xe1, 0x0b, 0x69, 0x26, 0x02, 0xd4, 0x1b, 0x41, + 0xbe, 0x4b, 0x1c, 0x26, 0x83, 0xcb, 0x57, 0x99, 0xcb, 0x78, 0xfa, 0xf8, + 0xe0, 0xab, 0xda, 0xfe, 0x29, 0xc9, 0x4c, 0xf7, 0x61, 0x8f, 0xd0, 0xba, + 0x98, 0x12, 0x02, 0x85, 0xbb, 0x0b, 0xbf, 0x2d, 0xde, 0x9b, 0x32, 0x09, + 0x35, 0x9d, 0x1b, 0xae, 0xed, 0x03, 0xa8, 0xe7, 0x92, 0x53, 0xd4, 0x22, + 0xee, 0x93, 0xdc, 0x0c, 0x89, 0xbe, 0xd4, 0x47, 0x19, 0xed, 0x43, 0xed, + 0xfd, 0x32, 0xec, 0xb0, 0x69, 0xb5, 0x3f, 0x06, 0xf8, 0x1b, 0x58, 0xfe, + 0x3e, 0xb0, 0xda, 0x6e, 0xee, 0x11, 0x83, 0x3d, 0x79, 0x02, 0x13, 0x10, + 0x31, 0x9c, 0x4b, 0x96, 0x9c, 0x4a, 0x24, 0xd7, 0xae, 0xe8, 0x92, 0x7e, + 0x98, 0xbc, 0x86, 0x02, 0x02, 0x3d, 0xae, 0xc5, 0x2d, 0x71, 0x3f, 0x9a, + 0xfe, 0xfc, 0xaa, 0x7b, 0xf4, 0x21, 0xe6, 0xb1, 0x58, 0xc6, 0x37, 0x48, + 0xd1, 0xc3, 0xaf, 0xb8, 0xc5, 0x92, 0x9f, 0xeb, 0xff, 0xb7, 0x01, 0x2e, + 0xea, 0xcf, 0x89, 0x2f, 0x1e, 0xc4, 0xb3, 0xe6, 0x65, 0x01, 0x56, 0x2d, + 0xbc, 0x22, 0x76, 0xc2, 0xef, 0x79, 0x9a, 0x6c, 0x55, 0x69, 0x01, 0x19, + 0xc6, 0x39, 0x57, 0xe1, 0x4e, 0x7a, 0xf0, 0x0c, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x3d, 0xfc, 0x45, 0x0e, 0x15, 0x74, 0xd5, 0x4a, + 0x4b, 0xd0, 0xab, 0x93, 0xf7, 0xca, 0x6a, 0xd2, 0x0f, 0x71, 0x68, 0x9e, + 0x13, 0x7b, 0xfd, 0x16, 0xc7, 0x46, 0x0b, 0x52, 0xd4, 0x5c, 0x36, 0x1e, + 0x21, 0xf9, 0x04, 0xaa, 0x94, 0xc9, 0xcd, 0xd6, 0x50, 0x5f, 0xfe, 0x7a, + 0x29, 0x2e, 0xc0, 0x65, 0xba, 0x92, 0x3a, 0xca, 0xbf, 0xe2, 0x4f, 0xe3, + 0x21, 0xc2, 0xc4, 0x4e, 0xdd, 0x0f, 0xf4, 0x17, 0x46, 0x7e, 0x4e, 0x00, + 0xd9, 0xfc, 0x2c, 0x7f, 0x67, 0xa4, 0xa7, 0x82, 0xe6, 0x74, 0xb9, 0xab, + 0x75, 0x38, 0xc6, 0x1f, 0x91, 0x31, 0x97, 0x76, 0x90, 0x96, 0x83, 0x3e, + 0xf9, 0x6e, 0xf9, 0x1c, 0x1c, 0x7b, 0x8b, 0x2c, 0xbc, 0x9f, 0x5d, 0x08, + 0xcd, 0xf2, 0x52, 0x98, 0xc2, 0x4d, 0x6d, 0x5b, 0x18, 0x31, 0x58, 0x4b, + 0xbd, 0x32, 0x7f, 0xa8, 0xb2, 0x54, 0x7f, 0xfd, 0xfc, 0xc6, 0x41, 0x10, + 0x42, 0xec, 0xf6, 0x69, 0x87, 0xea, 0x60, 0x11, 0x29, 0x32, 0x8c, 0xcb, + 0xea, 0x7a, 0xa4, 0xde, 0x9d, 0x35, 0xfa, 0x02, 0x35, 0x86, 0xd0, 0x59, + 0x83, 0xcb, 0xec, 0x3d, 0x5a, 0x2c, 0xd0, 0x05, 0x66, 0x4d, 0x77, 0xb2, + 0x41, 0x40, 0xe8, 0xd0, 0x78, 0x4c, 0x16, 0xfe, 0xd5, 0x41, 0x30, 0xd9, + 0x0f, 0x14, 0x2d, 0xd2, 0x1e, 0xae, 0x3d, 0xea, 0x59, 0xd3, 0xf3, 0x69, + 0xd6, 0x40, 0x49, 0x0e, 0xc5, 0x6d, 0x7d, 0x88, 0xdf, 0x42, 0xf0, 0xae, + 0xde, 0x11, 0xc7, 0xc1, 0x14, 0x93, 0xe4, 0x33, 0xbf, 0x70, 0x47, 0x57, + 0x88, 0x8b, 0xef, 0x0c, 0xaf, 0xe9, 0xd6, 0x67, 0x2e, 0x3d, 0xeb, 0x01, + 0x44, 0xdb, 0xa4, 0x63, 0xf7, 0xdb, 0xf3, 0x2b, 0x58, 0xa3, 0x13, 0x8d, + 0x30, 0x1b, 0xef, 0x89, 0xa9, 0x2b, 0x19, 0x9c, 0xd7, 0x05, 0x03, 0x88, + 0xb0, 0x41, 0x12, 0x04, 0xf6, 0xfe, 0x90, 0x16, 0x52, 0x94, 0x0e, 0xba, + 0xbd, 0x20, 0xb4, 0x97, 0x9d, 0x20, 0xc1, 0xe6, 0xa6, 0x3b, 0x2b, 0x6f, + 0x3a, 0x1c, 0x99, 0xb1, 0xd8, 0x58, 0xe3, 0xd0, 0x50, 0x9e, 0x5e, 0xb5, + 0x47, 0x5a, 0x2b, 0x19, 0x36, 0x1a, 0xfd, 0xd5, 0xb9, 0xfe, 0x33, 0xb4, + 0x38, 0x8c, 0xa8, 0x89, 0xcd, 0x8a, 0xaa, 0x3e, 0xdd, 0x44, 0x10, 0xa7, + 0x0a, 0xbf, 0x12, 0xcd, 0x24, 0x57, 0xbc, 0x8d, 0xae, 0x18, 0x53, 0x2d, + 0xab, 0x5e, 0x23, 0x89, 0xb0, 0x1e, 0x71, 0xf4, 0xec, 0x7f, 0x6c, 0xad, + 0x59, 0xec, 0xb5, 0xd2, 0xed, 0xd4, 0x8b, 0x52, 0xf6, 0xcf, 0xd7, 0x78, + 0xb4, 0x62, 0x3d, 0x48, 0x1e, 0x5e, 0xdd, 0x09, 0xb1, 0xd3, 0x93, 0xf3, + 0x06, 0x12, 0x4d, 0xf0, 0x06, 0xec, 0xc6, 0xac, 0x14, 0xf1, 0xda, 0x0e, + 0xc1, 0xe6, 0xf7, 0x63, 0x2a, 0xa5, 0x92, 0xe1, 0x23, 0xc3, 0xc8, 0xd7, + 0x4e, 0x87, 0x59, 0x19, 0x42, 0x98, 0x11, 0xde, 0x48, 0x1d, 0xad, 0x57, + 0x5f, 0x87, 0x82, 0x8b, 0x8f, 0xf5, 0x18, 0x3f, 0x8b, 0x25, 0x15, 0x06, + 0x64, 0x0b, 0x18, 0xf9, 0xe5, 0x3f, 0x75, 0xb9, 0xfd, 0xa6, 0x9d, 0x20, + 0x44, 0xd8, 0x94, 0x4c, 0x18, 0x47, 0x1d, 0xdc, 0x01, 0x29, 0xe4, 0x01, + 0x7c, 0xfa, 0x1b, 0xe2, 0xef, 0x58, 0xd7, 0x56, 0x2b, 0x2d, 0x8b, 0x2c, + 0x98, 0xec, 0x00, 0x84, 0xc1, 0xb1, 0x15, 0x2d, 0x17, 0x1b, 0x60, 0x65, + 0xac, 0x53, 0x44, 0x7a, 0xaf, 0x8b, 0xf6, 0x61, 0x4d, 0x78, 0x06, 0xc8, + 0x0e, 0x3d, 0x09, 0x36, 0xe0, 0x43, 0x32, 0x0f, 0xb0, 0xa7, 0xe9, 0x86, + 0x3a, 0x46, 0xcd, 0x0b, 0x0b, 0x2e, 0x2b, 0xdc, 0x2d, 0xd1, 0xd9, 0x98, + 0x3b, 0x42, 0x09, 0xb1, 0xa5, 0x9d, 0xca, 0xd0, 0xdb, 0x6b, 0x02, 0xb5, + 0x5d, 0xbe, 0x85, 0x61, 0xaa, 0x67, 0x4e, 0xf9, 0x5a, 0x9c, 0x0a, 0x2c, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0xa8, 0x9d, 0xb6, 0xf5, + 0x8e, 0xcf, 0x7e, 0x1e, 0x82, 0x31, 0x3c, 0xeb, 0x99, 0x14, 0xe7, 0x4a, + 0xb2, 0xaa, 0x2a, 0x15, 0x59, 0x51, 0xb0, 0x6d, 0xa3, 0xe9, 0xd6, 0xb6, + 0x9a, 0xf9, 0x76, 0x04, 0x06, 0x3a, 0x53, 0xe6, 0xa4, 0xd2, 0x91, 0x8b, + 0x64, 0xe2, 0xe1, 0x9f, 0x78, 0x08, 0x2b, 0x34, 0xeb, 0xac, 0x72, 0x90, + 0x72, 0x75, 0x45, 0x25, 0xe4, 0x80, 0xeb, 0xce, 0x7d, 0x61, 0x38, 0x01, + 0x9e, 0x2e, 0xc1, 0xf7, 0x10, 0xca, 0xe1, 0x8c, 0x2d, 0x07, 0x99, 0xd1, + 0xfc, 0x27, 0xc1, 0x05, 0x52, 0x42, 0xe9, 0x21, 0x1c, 0x6d, 0x7b, 0x65, + 0x38, 0xd1, 0x8d, 0x83, 0xec, 0x2d, 0x6c, 0x2a, 0x29, 0xfb, 0x34, 0x61, + 0x9f, 0xbd, 0x11, 0x71, 0xf0, 0xe6, 0xcf, 0x99, 0x64, 0x7b, 0xf5, 0x8c, + 0x69, 0x9a, 0xa1, 0x12, 0xeb, 0x38, 0x5b, 0x00, 0xab, 0x9f, 0x12, 0x81, + 0xcf, 0x62, 0xc4, 0x2c, 0xba, 0x41, 0x06, 0x1f, 0x44, 0x87, 0x92, 0x74, + 0xe8, 0x76, 0x42, 0xc5, 0x83, 0xb2, 0x70, 0x05, 0x29, 0xde, 0x2a, 0xc5, + 0x18, 0x7e, 0x6f, 0x7d, 0x3e, 0x01, 0xcc, 0xa5, 0xdc, 0xf6, 0x40, 0x26, + 0xe8, 0x1c, 0xf7, 0xab, 0x8c, 0x49, 0x8f, 0xcb, 0x1d, 0xe9, 0xbd, 0x4c, + 0x43, 0x3a, 0xe6, 0xbf, 0x4a, 0x65, 0x7c, 0x91, 0xff, 0xc2, 0x3a, 0x2f, + 0x80, 0x81, 0x12, 0x89, 0x7d, 0x81, 0xab, 0x2d, 0x61, 0x1d, 0xce, 0x52, + 0x03, 0xfb, 0xb6, 0x10, 0x39, 0x22, 0xd3, 0x91, 0xe0, 0xbc, 0x96, 0x10, + 0x0a, 0xd6, 0x5f, 0x0e, 0xda, 0xec, 0x35, 0xd4, 0xdf, 0x23, 0xe8, 0x4a, + 0x13, 0xa9, 0xc5, 0x2d, 0x60, 0x7e, 0x24, 0x89, 0x2d, 0x74, 0x07, 0x16, + 0x65, 0xf1, 0x90, 0xd8, 0xe6, 0xc0, 0x61, 0xb1, 0x11, 0xa3, 0x05, 0x34, + 0x30, 0x29, 0xd5, 0x1d, 0x3c, 0x30, 0x87, 0x11, 0x5f, 0x0b, 0x8f, 0x15, + 0x1c, 0x0f, 0x9c, 0x2d, 0x04, 0xbb, 0xbd, 0xd2, 0x1c, 0xb5, 0x6d, 0x64, + 0xdd, 0x6f, 0x26, 0x16, 0x25, 0x91, 0xcf, 0x39, 0x97, 0x35, 0x83, 0x80, + 0xe6, 0xd3, 0x2a, 0x08, 0x02, 0xdb, 0x8e, 0x26, 0xd4, 0xa8, 0xdd, 0xf3, + 0x7c, 0xf0, 0x60, 0x9e, 0x84, 0xfb, 0x4e, 0x69, 0x7f, 0x12, 0x77, 0x8b, + 0xb8, 0x12, 0xe6, 0x09, 0xa1, 0x35, 0x5f, 0x01, 0x49, 0x2d, 0x49, 0xb6, + 0xc4, 0x70, 0x0b, 0x2a, 0x71, 0xe2, 0x58, 0xb7, 0xf4, 0xaf, 0x37, 0x53, + 0x4f, 0xc7, 0x78, 0xe3, 0x79, 0xe4, 0xb5, 0x8f, 0xec, 0x18, 0x44, 0x84, + 0xf9, 0x89, 0x42, 0x8e, 0x37, 0x85, 0x4d, 0x17, 0xf2, 0x8a, 0xa2, 0x04, + 0x34, 0x83, 0xc0, 0xea, 0x67, 0x08, 0x38, 0x6d, 0x1e, 0x31, 0xdd, 0x44, + 0xf1, 0xb0, 0x44, 0x2e, 0x07, 0x3a, 0x6d, 0x36, 0xf1, 0x49, 0xef, 0x31, + 0x99, 0x5f, 0xae, 0xfc, 0x09, 0x99, 0x81, 0x0f, 0xb0, 0xbf, 0x65, 0xf4, + 0xe2, 0x2f, 0xf5, 0xd6, 0x6a, 0xf6, 0x38, 0xad, 0x21, 0x86, 0x9e, 0x3a, + 0x98, 0x6f, 0x63, 0x03, 0x87, 0x2f, 0xb4, 0x27, 0xb7, 0xaa, 0xbd, 0x96, + 0xcc, 0x81, 0x95, 0x05, 0xd3, 0x98, 0x6e, 0xfe, 0x7e, 0x84, 0x87, 0x82, + 0x7b, 0x61, 0x06, 0xeb, 0xac, 0x4d, 0x4a, 0x5a, 0x6c, 0xfa, 0xe0, 0x31, + 0x97, 0x34, 0xe8, 0x8a, 0x1a, 0x8f, 0xa5, 0x1d, 0x3e, 0x6a, 0xc2, 0x23, + 0x54, 0xc9, 0x4f, 0x8f, 0x4e, 0x02, 0x70, 0x01, 0xf7, 0xed, 0x01, 0x28, + 0x93, 0xdb, 0x1c, 0x0a, 0x36, 0x9c, 0x44, 0x51, 0x96, 0x71, 0x6d, 0xa6, + 0xd3, 0x4c, 0xd5, 0x2a, 0xf3, 0x08, 0x81, 0x18, 0xe4, 0xe2, 0xe7, 0x8e, + 0x2c, 0x94, 0xd8, 0x45, 0x65, 0x15, 0x45, 0xf1, 0x3a, 0x22, 0xa0, 0xd0, + 0xfd, 0x2f, 0xc3, 0xf2, 0x3f, 0x58, 0xd6, 0xaa, 0x42, 0x94, 0x39, 0x86, + 0x26, 0x73, 0x5d, 0x22, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x6c, 0x48, 0x4a, 0x32, 0x96, 0x51, 0x73, 0x98, 0x52, 0x91, 0x67, 0xbf, + 0xdd, 0xcd, 0x14, 0x94, 0x18, 0xa9, 0x12, 0x09, 0x9b, 0xa1, 0x80, 0x67, + 0x09, 0x03, 0xe4, 0x6d, 0x9b, 0xac, 0x27, 0x00, 0xb2, 0x7d, 0xa4, 0x87, + 0x37, 0x87, 0x95, 0x6b, 0xd2, 0x65, 0x51, 0x4f, 0x7d, 0x3c, 0x78, 0x2c, + 0x1b, 0x83, 0xe7, 0x5b, 0x9f, 0x6b, 0x98, 0xe4, 0xb2, 0xfa, 0xa9, 0x2c, + 0x2e, 0xf4, 0xd6, 0x06, 0x10, 0x8f, 0x5e, 0xaf, 0x7d, 0x10, 0xdf, 0xe2, + 0x7e, 0x71, 0xd5, 0x13, 0xfb, 0x61, 0x3d, 0xaf, 0xad, 0x62, 0x82, 0xda, + 0x87, 0x80, 0xb6, 0xe4, 0x19, 0xee, 0x6e, 0x7a, 0x18, 0x55, 0x08, 0x2c, + 0x55, 0x16, 0x4d, 0x46, 0x79, 0x6b, 0x5f, 0x1a, 0x07, 0x22, 0x7d, 0xcd, + 0xcd, 0xe6, 0xd7, 0x80, 0x38, 0x59, 0xf6, 0x4f, 0xf2, 0x73, 0x15, 0xc0, + 0xb4, 0x61, 0x64, 0x69, 0xec, 0x4a, 0xb3, 0x26, 0x82, 0xbe, 0x28, 0x56, + 0xc0, 0x16, 0x88, 0x87, 0x31, 0x64, 0x9e, 0x48, 0xe3, 0x10, 0xbc, 0xaf, + 0x80, 0x7a, 0xf3, 0x43, 0x92, 0x32, 0x94, 0x3f, 0x87, 0x81, 0x14, 0x62, + 0xb5, 0x6a, 0x6a, 0x08, 0x56, 0x8a, 0x15, 0x8b, 0xf4, 0xd0, 0x85, 0xf2, + 0xc3, 0x0a, 0x4f, 0x3c, 0x82, 0xf7, 0xae, 0x1d, 0x9d, 0x17, 0xa3, 0xf7, + 0xa0, 0xd1, 0xc9, 0x34, 0xaf, 0x26, 0x56, 0xd2, 0xc0, 0xda, 0x39, 0x26, + 0x61, 0x08, 0x4e, 0xff, 0x21, 0x8a, 0x36, 0xf8, 0x20, 0x68, 0x4b, 0xb9, + 0x27, 0xbd, 0x38, 0xa7, 0x33, 0x80, 0x62, 0x54, 0x1a, 0xb1, 0xa5, 0xf2, + 0x8b, 0x7c, 0x17, 0x32, 0x23, 0xb8, 0x09, 0x12, 0xb8, 0xb5, 0x63, 0xce, + 0x5e, 0xff, 0x27, 0x4d, 0xc0, 0xe3, 0xb8, 0x19, 0x88, 0xc8, 0xb4, 0x7e, + 0x34, 0x1d, 0x8f, 0x96, 0x27, 0xeb, 0x4f, 0xc2, 0x73, 0x62, 0xa8, 0x27, + 0x19, 0x96, 0xaf, 0x01, 0x98, 0xdb, 0x77, 0x38, 0xab, 0x4e, 0xaf, 0xf1, + 0x91, 0x05, 0x81, 0xc4, 0xe1, 0x91, 0x37, 0xc5, 0xaf, 0xde, 0x3a, 0x7e, + 0x6d, 0xeb, 0x84, 0x19, 0xf0, 0x81, 0x71, 0x4c, 0x3d, 0xa0, 0x46, 0x08, + 0xef, 0xb6, 0x01, 0x3c, 0xa8, 0x95, 0x23, 0x89, 0xfb, 0x5a, 0xcf, 0x23, + 0xc3, 0xb9, 0xb3, 0x52, 0xa9, 0x2a, 0xb4, 0x21, 0x11, 0x49, 0x18, 0x78, + 0x61, 0x48, 0x8a, 0x58, 0x92, 0xd9, 0x0b, 0x2d, 0x39, 0x75, 0x25, 0x09, + 0xd0, 0x8d, 0x00, 0x1e, 0x02, 0x32, 0xe9, 0x81, 0x51, 0xd9, 0x10, 0xf0, + 0xe0, 0xad, 0x4a, 0x19, 0x66, 0xc1, 0x71, 0xfc, 0x31, 0xec, 0x86, 0x44, + 0x58, 0x05, 0xc6, 0x1d, 0x6a, 0xd8, 0xad, 0x4a, 0x31, 0x8a, 0xdc, 0x7e, + 0xc4, 0x79, 0x4a, 0xf7, 0x99, 0x1d, 0x41, 0x7b, 0x4d, 0x0d, 0x98, 0x95, + 0xca, 0x94, 0xfd, 0xf6, 0xc0, 0xc6, 0xf8, 0x16, 0x30, 0xf4, 0xbb, 0x18, + 0x3c, 0x5f, 0x25, 0x0f, 0x37, 0x94, 0x41, 0x6d, 0x6d, 0x88, 0xa6, 0xed, + 0x40, 0x0c, 0xad, 0xca, 0x1c, 0x5d, 0x86, 0x6f, 0x02, 0xa2, 0x8b, 0x23, + 0x9e, 0xb5, 0x52, 0x77, 0x27, 0x5d, 0x28, 0x2f, 0x05, 0xee, 0xa9, 0x21, + 0xc0, 0x05, 0x78, 0xd2, 0x0d, 0x59, 0x43, 0x77, 0x9b, 0xd9, 0x6d, 0x42, + 0x88, 0x89, 0x39, 0x07, 0x9c, 0xfa, 0xd7, 0xfe, 0x16, 0x43, 0xfa, 0xa2, + 0x28, 0xce, 0xa5, 0x27, 0xfa, 0x46, 0x4b, 0xe0, 0x15, 0x8e, 0x39, 0xe0, + 0xb0, 0x2b, 0x4d, 0x20, 0xdc, 0x64, 0x02, 0x2e, 0x76, 0xa0, 0xc1, 0x52, + 0xf0, 0xae, 0x17, 0x60, 0xfb, 0xf5, 0x93, 0xac, 0x0c, 0x73, 0x3a, 0x2a, + 0x7a, 0x02, 0xab, 0x20, 0x7d, 0x1b, 0x92, 0x2b, 0x9c, 0xa4, 0xd4, 0xd4, + 0x3e, 0xa0, 0x42, 0xea, 0xcf, 0x42, 0x42, 0xb2, 0x5a, 0x3b, 0x72, 0x6b, + 0x1f, 0x92, 0xb0, 0xf5, 0xd3, 0x9d, 0x53, 0x04, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0xc2, 0xb7, 0xe1, 0x52, 0xf9, 0xfb, 0xe2, 0x6f, + 0x9d, 0xf9, 0x59, 0xa2, 0x97, 0xe6, 0xdd, 0x17, 0xd3, 0x1e, 0x83, 0x9b, + 0x63, 0xdc, 0x1f, 0x85, 0x89, 0x0f, 0xa2, 0x55, 0x22, 0xa5, 0xee, 0x1c, + 0x4d, 0xe0, 0xea, 0xee, 0x16, 0xd7, 0x71, 0x49, 0x13, 0x53, 0x9f, 0x5b, + 0x55, 0x7c, 0x55, 0xba, 0x90, 0xb3, 0x71, 0x43, 0x9c, 0xf7, 0xf0, 0xdc, + 0xa2, 0x8c, 0x5c, 0xc3, 0x88, 0x79, 0x7b, 0x1c, 0x3a, 0xd8, 0x80, 0x4d, + 0x13, 0x03, 0xcf, 0xce, 0x9e, 0x60, 0xe6, 0x67, 0x41, 0x32, 0xf5, 0xa9, + 0x41, 0x74, 0xbc, 0xcf, 0xb2, 0xa3, 0xcc, 0x41, 0x16, 0x04, 0x25, 0x92, + 0x1f, 0x2b, 0xb0, 0x03, 0x51, 0x26, 0x6e, 0x2e, 0xac, 0xa9, 0x8f, 0x49, + 0x5a, 0x0f, 0xb6, 0x0d, 0xe2, 0x1e, 0xb9, 0x13, 0x46, 0xc1, 0xb5, 0xfb, + 0x8d, 0x67, 0xda, 0x1a, 0xad, 0x9c, 0xf3, 0x4a, 0xfd, 0x81, 0x31, 0x0e, + 0x53, 0x07, 0x40, 0x1d, 0x5a, 0x96, 0xeb, 0x7b, 0x26, 0x1b, 0x9a, 0xe6, + 0x1c, 0xf1, 0x19, 0xa7, 0x90, 0x9a, 0x48, 0x85, 0x3d, 0x4a, 0x3b, 0x2e, + 0x7e, 0xcf, 0x97, 0xcb, 0xc2, 0xbd, 0x71, 0x05, 0xa6, 0x28, 0xe4, 0xcb, + 0x9a, 0xb4, 0x9c, 0xf1, 0xdb, 0x81, 0x9c, 0x5d, 0x6f, 0xea, 0x72, 0x8d, + 0x01, 0xc9, 0x4f, 0x6b, 0xa0, 0xa4, 0xec, 0x6d, 0xba, 0x0c, 0x2d, 0xcb, + 0x8d, 0x75, 0x0b, 0x1b, 0xb4, 0x33, 0x3a, 0x6b, 0xf5, 0xd3, 0x3c, 0x84, + 0xc0, 0x9e, 0x35, 0x16, 0xff, 0x74, 0x54, 0xe9, 0xaa, 0x3b, 0xb0, 0x04, + 0xc9, 0x02, 0xe8, 0x38, 0xfd, 0xdd, 0x49, 0xdc, 0xd1, 0x27, 0x09, 0x1e, + 0x55, 0xd6, 0x18, 0x99, 0x9a, 0xfa, 0xa9, 0xf5, 0x94, 0x2f, 0xd8, 0x17, + 0xb6, 0x1d, 0x6d, 0xa0, 0x90, 0x2b, 0x2f, 0x47, 0xe3, 0x12, 0xc2, 0xd8, + 0x03, 0xdf, 0x47, 0x3d, 0x89, 0x93, 0xbc, 0x26, 0xd5, 0x7b, 0x66, 0x4c, + 0x33, 0x57, 0x48, 0xe8, 0x78, 0xd9, 0x19, 0xc2, 0xe4, 0x17, 0xe3, 0x09, + 0xf7, 0x9b, 0x0c, 0x2c, 0x27, 0x35, 0x9f, 0x65, 0x6a, 0xa8, 0x3d, 0x75, + 0x59, 0x61, 0xae, 0x01, 0x3a, 0x19, 0x1f, 0x90, 0x23, 0x05, 0x07, 0x14, + 0x3f, 0x25, 0x59, 0x4d, 0x7e, 0xbe, 0x13, 0x42, 0x70, 0x97, 0xf3, 0xc5, + 0xb8, 0xdd, 0xd0, 0x1c, 0x1a, 0x85, 0x33, 0xd4, 0x38, 0x6b, 0xfc, 0x1d, + 0x6e, 0xfd, 0xae, 0x8e, 0x13, 0xd3, 0x7c, 0x83, 0x8e, 0xcb, 0x20, 0xeb, + 0xd0, 0x04, 0x84, 0xb9, 0xb1, 0xcf, 0x06, 0x85, 0xff, 0xd4, 0x29, 0xad, + 0xa8, 0x35, 0x01, 0xba, 0x2b, 0xc4, 0x77, 0x10, 0x23, 0xd0, 0xc0, 0xba, + 0xdc, 0xf8, 0xee, 0x2d, 0xd3, 0xf2, 0x29, 0x6c, 0xa3, 0x95, 0xfb, 0xbb, + 0x21, 0x26, 0xdd, 0x80, 0x3c, 0x55, 0x0c, 0xcd, 0xe5, 0xb4, 0x01, 0x2e, + 0x24, 0xef, 0x3b, 0x00, 0xfd, 0x81, 0xb8, 0x8b, 0x9e, 0xa1, 0x67, 0x52, + 0xf5, 0x0e, 0x04, 0xb6, 0x3f, 0x69, 0x33, 0xef, 0xb8, 0xd1, 0x43, 0x3b, + 0xfb, 0x1d, 0xd5, 0x2f, 0x11, 0x20, 0x44, 0x68, 0x12, 0x88, 0x26, 0x18, + 0xd2, 0x24, 0x30, 0x0f, 0x43, 0xe1, 0x4e, 0xaa, 0x9b, 0x02, 0x90, 0x38, + 0xc0, 0x1b, 0x2d, 0xa9, 0x54, 0x7a, 0x9f, 0xef, 0xba, 0x94, 0x66, 0xb1, + 0xc6, 0x6a, 0xf7, 0xcf, 0x11, 0x27, 0x54, 0x07, 0x98, 0xd9, 0x77, 0x7d, + 0xec, 0x1f, 0x4f, 0x4d, 0x5e, 0x24, 0xdc, 0x3c, 0xff, 0xa3, 0xac, 0x0b, + 0x1d, 0xd5, 0xc0, 0x4b, 0xd0, 0x16, 0xc0, 0xdc, 0x2c, 0xff, 0x43, 0x79, + 0x24, 0xd4, 0x1b, 0x0f, 0x9b, 0x47, 0xa6, 0x61, 0xda, 0xff, 0xb3, 0x74, + 0x7e, 0x60, 0xe7, 0x18, 0x09, 0xb8, 0xf8, 0x22, 0xd0, 0x50, 0x1a, 0xec, + 0x11, 0x16, 0x08, 0x88, 0x15, 0x11, 0x08, 0x9a, 0x37, 0x00, 0x0e, 0x01, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x00, 0x00, 0x66, 0xeb, + 0x22, 0x02, 0x75, 0xc8, 0x14, 0xfc, 0xf9, 0x17, 0x6d, 0xf6, 0x8a, 0xa1, + 0x40, 0x89, 0xd4, 0xd5, 0xe5, 0x83, 0x1e, 0xeb, 0x1f, 0xa9, 0xf1, 0xae, + 0x3e, 0xc5, 0xd0, 0x09, 0x36, 0x84, 0xd4, 0xe2, 0x90, 0x12, 0x93, 0x0e, + 0xa7, 0xfb, 0x4a, 0x37, 0x5d, 0x7f, 0x4e, 0x43, 0x3b, 0xdf, 0x45, 0x62, + 0xb6, 0xbc, 0x4b, 0xd4, 0x8b, 0x88, 0x42, 0xcd, 0x6e, 0x03, 0xa6, 0x14, + 0x3a, 0x1b, 0xaf, 0xf8, 0x57, 0x8b, 0x33, 0xb4, 0x6a, 0x31, 0x00, 0x8e, + 0x21, 0xfd, 0x9c, 0x37, 0xe9, 0x2d, 0x41, 0x04, 0x3d, 0x3f, 0xda, 0x41, + 0xec, 0x15, 0xca, 0x81, 0x48, 0xc9, 0x47, 0x28, 0xa0, 0x24, 0x8b, 0x7f, + 0x30, 0xdd, 0x5f, 0x4b, 0x81, 0xbc, 0x4c, 0x0a, 0xbb, 0xbb, 0x47, 0x1f, + 0x1f, 0x28, 0x8d, 0x93, 0x4e, 0x30, 0x6b, 0x3d, 0x06, 0x02, 0x32, 0xd7, + 0xde, 0xac, 0x05, 0x14, 0x45, 0xe3, 0x0b, 0xad, 0x39, 0xbd, 0xd6, 0x45, + 0xb8, 0x78, 0xf6, 0x98, 0x9d, 0x5c, 0x7f, 0xc3, 0x96, 0x06, 0x79, 0xce, + 0x43, 0x63, 0x9c, 0xed, 0x17, 0x1d, 0x49, 0x4a, 0x44, 0xd5, 0xea, 0x2e, + 0xfc, 0x9d, 0xf7, 0xc7, 0xa8, 0x17, 0x6d, 0x71, 0xea, 0xee, 0xe2, 0x3a, + 0x1b, 0xb1, 0xd6, 0x25, 0xda, 0xb7, 0x26, 0x23, 0x51, 0xa6, 0x1a, 0x30, + 0x7e, 0xf8, 0x8b, 0x1f, 0xcf, 0x54, 0x4a, 0x05, 0xbe, 0x31, 0x83, 0x1c, + 0xf3, 0x70, 0x7b, 0xbe, 0xb5, 0x27, 0x7e, 0x9a, 0x25, 0x85, 0x8a, 0x5d, + 0x8a, 0x5e, 0x01, 0x47, 0x82, 0x71, 0xad, 0xb9, 0xf4, 0x9e, 0x51, 0x72, + 0xa6, 0x85, 0xcb, 0x1e, 0x74, 0xa5, 0x93, 0x26, 0x74, 0x09, 0x58, 0x61, + 0x28, 0x6a, 0xd6, 0xf7, 0x8e, 0x2e, 0x03, 0x20, 0xa7, 0x8e, 0x2d, 0xf7, + 0x27, 0xce, 0xe6, 0xe6, 0x0d, 0x1f, 0x47, 0xf6, 0x0a, 0xb8, 0x58, 0x2b, + 0xfd, 0x06, 0x29, 0xd1, 0x45, 0x78, 0xf7, 0xbe, 0xb3, 0x53, 0x77, 0x2d, + 0xe3, 0x4c, 0x2f, 0x47, 0x4b, 0xf1, 0xb2, 0x09, 0x43, 0xca, 0xa1, 0x0a, + 0x2b, 0x00, 0x0b, 0xf1, 0x26, 0x6d, 0xaf, 0x12, 0x83, 0x32, 0xf2, 0xe5, + 0x9a, 0x9c, 0x7e, 0x80, 0x33, 0x54, 0xc2, 0x29, 0x8e, 0x38, 0xbb, 0xf5, + 0x3c, 0xfc, 0xed, 0xd5, 0x87, 0x80, 0xd7, 0xfc, 0xba, 0x2d, 0x9f, 0xd2, + 0xfd, 0xb3, 0x55, 0x2b, 0xea, 0x23, 0xdf, 0xe7, 0x9a, 0xc9, 0xd0, 0xd9, + 0x60, 0xf3, 0x2b, 0xd2, 0xdd, 0x7f, 0x47, 0xa7, 0x7d, 0x93, 0x5d, 0x47, + 0x9b, 0x7d, 0xa2, 0xb9, 0x9f, 0x90, 0x35, 0xff, 0xad, 0x50, 0x69, 0x25, + 0xc9, 0x66, 0xa1, 0x87, 0x38, 0x52, 0x3c, 0xf6, 0x57, 0x71, 0x4c, 0x42, + 0xa1, 0xd2, 0x1d, 0xf7, 0xd6, 0xd7, 0x07, 0x10, 0x88, 0x5d, 0x8c, 0x68, + 0x99, 0x8e, 0xd0, 0xf0, 0x58, 0x87, 0xc1, 0x06, 0x71, 0xc8, 0x7b, 0x1c, + 0xd7, 0x8d, 0xec, 0x2b, 0xfa, 0x40, 0xb9, 0x5d, 0x4f, 0x0f, 0xb4, 0xcd, + 0x32, 0x49, 0x83, 0x8c, 0x39, 0x6d, 0xcf, 0xbc, 0x79, 0x29, 0x04, 0x6f, + 0x8a, 0x84, 0xd0, 0x02, 0x6c, 0x48, 0xc9, 0x06, 0x71, 0x94, 0x88, 0x45, + 0xbe, 0xa7, 0xbe, 0x49, 0x37, 0x91, 0xa2, 0xbb, 0xae, 0xca, 0x72, 0x3c, + 0xa9, 0x39, 0x77, 0x3b, 0xc3, 0xfa, 0xa6, 0xaa, 0x83, 0x27, 0x60, 0x2a, + 0x67, 0xb9, 0xf5, 0x94, 0xe7, 0x72, 0xf9, 0xe0, 0x11, 0x57, 0xc8, 0x1e, + 0x7b, 0xc6, 0x2a, 0xb1, 0x8b, 0x5e, 0xcf, 0x49, 0x4b, 0x4d, 0x16, 0x14, + 0xc4, 0x80, 0x89, 0x5c, 0x6e, 0x8c, 0xd0, 0x2b, 0xfa, 0x9a, 0x3c, 0xbc, + 0x64, 0xcf, 0xf8, 0xe2, 0x86, 0x5b, 0x14, 0x90, 0x39, 0x65, 0x15, 0x7f, + 0x32, 0xc1, 0xc6, 0xe4, 0x0d, 0xda, 0x52, 0xb3, 0x6e, 0xeb, 0x2a, 0x3a, + 0x3e, 0xcb, 0x63, 0x1f, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x00, 0x80, 0x94, 0xa1, 0xb6, 0x10, 0xb3, 0x5e, 0xf4, 0x62, 0xb6, 0x24, + 0x09, 0x0b, 0xf6, 0x0a, 0x25, 0x18, 0xcb, 0x76, 0x03, 0x06, 0xb0, 0x19, + 0xa7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x9a, 0xa1, 0x17, + 0xa2, 0x71, 0xdf, 0x6b, 0xea, 0xa1, 0xb0, 0xde, 0x6a, 0x1a, 0x28, 0xf7, + 0xf3, 0xdb, 0x5d, 0xe2, 0x38, 0x66, 0xb5, 0x7a, 0x51, 0xd9, 0x9c, 0x2c, + 0x18, 0xe3, 0x97, 0x27, 0x9f, 0xf3, 0x9e, 0xda, 0x0c, 0x48, 0xab, 0xb4, + 0x1c, 0x32, 0xb2, 0x1b, 0x32, 0x22, 0x8a, 0xb8, 0xdd, 0x1c, 0xcb, 0xee, + 0x73, 0x66, 0xe9, 0x18, 0xce, 0x8a, 0xdf, 0x0e, 0x08, 0xa1, 0x32, 0x0d, + 0x3a, 0x31, 0x69, 0xfb, 0xbe, 0x24, 0xe8, 0x58, 0x12, 0x76, 0x4b, 0x2e, + 0x73, 0x22, 0x4d, 0xc6, 0xf9, 0x84, 0xa2, 0x63, 0x05, 0x95, 0x92, 0xc8, + 0x48, 0x5b, 0x70, 0x91, 0xc0, 0xf0, 0xde, 0x23, 0xe9, 0x1c, 0x36, 0xfd, + 0xfd, 0xb5, 0x5a, 0xb1, 0x9f, 0xb4, 0x08, 0x80, 0x74, 0x4e, 0xd6, 0x18, + 0xcf, 0xdf, 0x7e, 0x69, 0x44, 0xe2, 0x32, 0x41, 0xef, 0xb3, 0x83, 0xd1, + 0x06, 0xd7, 0x2a, 0x0b, 0xbb, 0x96, 0xc7, 0xb8, 0xef, 0x44, 0x56, 0x2c, + 0x7b, 0x55, 0x89, 0x5d, 0x3d, 0x23, 0x3b, 0xe1, 0x37, 0x74, 0x83, 0x9c, + 0xa2, 0x4a, 0xfa, 0xdd, 0xf3, 0xfb, 0x82, 0x74, 0x14, 0x85, 0x80, 0x21, + 0x2f, 0xf0, 0xe3, 0xe8, 0x54, 0x13, 0x35, 0x0b, 0x1e, 0x02, 0x3b, 0xe6, + 0x82, 0xf3, 0x3e, 0x6c, 0x38, 0x4b, 0xe7, 0xf3, 0x5a, 0xac, 0xb0, 0xfe, + 0x22, 0xe2, 0xd8, 0x07, 0xb6, 0xbb, 0x9c, 0x12, 0xdd, 0x07, 0x57, 0x63, + 0xbe, 0x7f, 0xdd, 0x20, 0x12, 0xb6, 0x78, 0xe2, 0xf4, 0x9e, 0x2d, 0x3f, + 0x9a, 0x2b, 0x33, 0x81, 0xaf, 0x85, 0x1d, 0x28, 0xbe, 0x24, 0x56, 0x22, + 0x5a, 0x2e, 0x4e, 0x18, 0xd2, 0x0f, 0xdc, 0xb2, 0x7b, 0x31, 0xd1, 0x2a, + 0x78, 0xde, 0xad, 0x2c, 0xcd, 0x58, 0xbe, 0xdb, 0x53, 0x33, 0x8a, 0x5e, + 0x04, 0xdb, 0xf6, 0xab, 0x30, 0x0b, 0x03, 0xa7, 0x23, 0xbf, 0x63, 0x1c, + 0x10, 0xe1, 0xbf, 0x32, 0xcf, 0xc3, 0x58, 0xff, 0xf2, 0xe6, 0x1b, 0x37, + 0x64, 0x8b, 0x17, 0x09, 0x2f, 0x1b, 0x54, 0x35, 0xd0, 0xed, 0xd8, 0xa7, + 0x14, 0xd8, 0xbb, 0x81, 0xc7, 0x97, 0x07, 0x0d, 0x03, 0x1c, 0x9f, 0xab, + 0x7d, 0xa9, 0x7a, 0x43, 0xf3, 0x7a, 0xab, 0xc6, 0xc6, 0x0b, 0x1d, 0xbb, + 0xa8, 0x58, 0xdd, 0xe7, 0xc6, 0xf8, 0x0e, 0xfc, 0x66, 0x69, 0x4a, 0xdc, + 0x9a, 0x08, 0x79, 0x2e, 0x05, 0x4d, 0x53, 0xcc, 0x3f, 0xa1, 0x32, 0x99, + 0x03, 0x6e, 0x24, 0x23, 0x59, 0x87, 0x25, 0xa3, 0x52, 0x1f, 0x38, 0x61, + 0xba, 0xa8, 0x7c, 0xfb, 0xfc, 0x44, 0xf0, 0x18, 0x95, 0x10, 0x90, 0x1d, + 0x2c, 0x81, 0x27, 0xdd, 0x3a, 0x51, 0x99, 0xbc, 0x3a, 0x67, 0x68, 0xc7, + 0x3b, 0x5e, 0x12, 0xd5, 0xed, 0x9e, 0x1b, 0x3b, 0xbe, 0xac, 0x3a, 0xca, + 0xa2, 0x45, 0x65, 0xb5, 0x61, 0xd4, 0x4a, 0x09, 0xdc, 0x28, 0x76, 0x98, + 0x60, 0x97, 0xaa, 0x5a, 0x76, 0x14, 0x99, 0x6c, 0x0c, 0x29, 0x18, 0x2e, + 0xb6, 0x23, 0xa8, 0xf0, 0x67, 0xe8, 0x41, 0x4f, 0x17, 0xc6, 0x85, 0x64, + 0xb8, 0xb6, 0x29, 0x28, 0x7f, 0x35, 0xaa, 0x20, 0xe5, 0x8f, 0x34, 0x86, + 0x54, 0x27, 0x1d, 0xe5, 0x8a, 0x11, 0xad, 0x1b, 0x52, 0x96, 0xc7, 0x6b, + 0x80, 0x68, 0xb0, 0x36, 0x6d, 0x50, 0x0e, 0x42, 0x1b, 0xc1, 0xc7, 0x1c, + 0xe6, 0x8f, 0x27, 0x40, 0xac, 0xee, 0xac, 0x66, 0xda, 0xbe, 0x4c, 0xa6, + 0x94, 0xb2, 0x3d, 0xa5, 0x0f, 0x35, 0x8e, 0x06, 0xc4, 0x9c, 0xe1, 0xf6, + 0x8e, 0x4b, 0x41, 0x89, 0xc9, 0x43, 0xc7, 0x0f, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x00, 0x58, 0xa6, 0xab, 0xd0, 0x6b, 0x7c, 0x98, + 0x75, 0x5c, 0x91, 0xe2, 0x76, 0x7a, 0x43, 0x17, 0x8c, 0x88, 0xb7, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x66, 0x36, 0xd6, 0x72, 0x9f, 0xd6, 0x56, 0x50, 0x01, 0xc6, 0xc5, + 0x80, 0x8c, 0xb6, 0xda, 0x22, 0xc3, 0xa4, 0xd5, 0xf5, 0x36, 0x0d, 0x6b, + 0xe4, 0xa5, 0x73, 0xc3, 0x62, 0x0c, 0xff, 0x15, 0x09, 0x7a, 0x69, 0x99, + 0x87, 0xcf, 0xf1, 0x77, 0x63, 0x06, 0xa4, 0xb2, 0x36, 0xcf, 0xad, 0x7c, + 0x1f, 0x0e, 0x10, 0x04, 0xf6, 0x36, 0x0d, 0x6b, 0xe4, 0xa5, 0x73, 0xc3, + 0x62, 0x0c, 0xff, 0x15, 0x6d, 0x07, 0xb7, 0x49, 0x94, 0xf4, 0xa9, 0xa5, + 0x6c, 0x86, 0xb4, 0x11, 0xdb, 0xbb, 0x5e, 0xb6, 0xdc, 0xec, 0x35, 0xaf, + 0xb7, 0x9f, 0x75, 0x80, 0xcb, 0xfc, 0x95, 0x25, 0xc6, 0xfd, 0x01, 0x2d, + 0x2f, 0x78, 0x8a, 0x9c, 0x18, 0x79, 0x03, 0x8b, 0xf9, 0xea, 0xdf, 0x16, + 0xe4, 0xf2, 0xd8, 0x6e, 0x24, 0xa8, 0xf7, 0xfd, 0xf7, 0x90, 0x32, 0x33, + 0x86, 0x02, 0xd8, 0x07, 0xb6, 0xbb, 0x9c, 0x12, 0x5e, 0x70, 0x43, 0xd3, + 0x3c, 0x1c, 0x48, 0xfd, 0xa0, 0x67, 0xcb, 0xc1, 0x71, 0xb2, 0x96, 0x02, + 0x5c, 0x75, 0xea, 0x5a, 0xee, 0x21, 0x65, 0x66, 0x0c, 0x05, 0xb0, 0x0f, + 0x6c, 0x77, 0x39, 0x25, 0xa4, 0x04, 0x8a, 0xc3, 0xfd, 0x11, 0x47, 0x5a, + 0x93, 0x39, 0x6e, 0x64, 0xf3, 0x0e, 0x54, 0x95, 0x2d, 0x81, 0x5c, 0xdb, + 0x1e, 0x8f, 0xac, 0x47, 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, + 0xeb, 0x0d, 0x82, 0xe3, 0x60, 0xce, 0x7d, 0x67, 0xf8, 0x72, 0x35, 0x8f, + 0x16, 0x6f, 0x2a, 0x05, 0xf1, 0xf3, 0xf7, 0x65, 0x6d, 0x53, 0x2e, 0xc9, + 0x01, 0x02, 0x35, 0xac, 0x2a, 0x69, 0x01, 0x25, 0x4b, 0x37, 0x69, 0x41, + 0x3c, 0x02, 0x91, 0x62, 0xd3, 0x99, 0xe9, 0xec, 0x7f, 0x3f, 0x2e, 0x3d, + 0x59, 0xe5, 0x95, 0xd9, 0xd0, 0x7d, 0x82, 0xd9, 0xa6, 0xc3, 0xdb, 0x0f, + 0x9e, 0x5f, 0xee, 0x2c, 0x13, 0x3f, 0x4f, 0x65, 0x25, 0xa2, 0x93, 0xbf, + 0xfe, 0x2a, 0xda, 0xa9, 0xc5, 0x1a, 0xf9, 0x20, 0xa4, 0x31, 0xb0, 0x52, + 0x04, 0x66, 0x89, 0x0a, 0xf8, 0xb1, 0x91, 0x7f, 0xda, 0x09, 0x53, 0x10, + 0xc4, 0xa4, 0x80, 0x48, 0x58, 0x19, 0x69, 0xbe, 0x9d, 0xbf, 0xc2, 0x68, + 0xf5, 0x89, 0x5d, 0xc7, 0xdc, 0xcf, 0xad, 0x54, 0x65, 0x95, 0x34, 0xea, + 0x60, 0x97, 0x77, 0x91, 0xb4, 0x51, 0x1f, 0x2c, 0xc6, 0x45, 0x4c, 0x0c, + 0x6c, 0x64, 0x01, 0xf9, 0xff, 0x16, 0x2a, 0x9d, 0x4b, 0xe7, 0x65, 0x14, + 0x8f, 0xd2, 0x88, 0x72, 0xb1, 0x75, 0xeb, 0xf8, 0xf5, 0x5e, 0x2b, 0x7f, + 0xe1, 0x8f, 0x38, 0x01, 0xba, 0x30, 0x63, 0x41, 0x48, 0x85, 0x20, 0x13, + 0x7b, 0x3a, 0x2b, 0x84, 0xc6, 0x84, 0x7e, 0x40, 0x08, 0xde, 0x07, 0xc4, + 0x7c, 0x20, 0xb5, 0x67, 0x94, 0xf2, 0x77, 0xd8, 0xf1, 0xb9, 0x94, 0x01, + 0xe4, 0x58, 0xc7, 0x66, 0x5b, 0xff, 0x53, 0x5d, 0xc0, 0xac, 0xe2, 0x25, + 0x34, 0xa9, 0x0f, 0x29, 0xce, 0xf8, 0xab, 0x9d, 0xbe, 0x07, 0x05, 0x60, + 0x89, 0x7e, 0x1c, 0x41, 0x4e, 0xb5, 0x3c, 0x10, 0xf3, 0x7b, 0x13, 0xa1, + 0xf0, 0x81, 0x6b, 0x41, 0xe1, 0xfa, 0x7a, 0x8e, 0x73, 0x23, 0xef, 0xd6, + 0xec, 0xb4, 0x50, 0x72, 0x4a, 0x2b, 0x2b, 0xa1, 0xd7, 0xde, 0x0f, 0x17, + 0xd1, 0xee, 0x03, 0x0d, 0x76, 0x85, 0x2b, 0x84, 0xb5, 0xae, 0x4d, 0x68, + 0xc1, 0xb7, 0x45, 0xad, 0xe8, 0x80, 0xe4, 0x7d, 0x3d, 0x52, 0x51, 0xb1, + 0x18, 0x55, 0x18, 0x05, 0x43, 0x02, 0x80, 0x68, 0x25, 0x79, 0x39, 0x30, + 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, + 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, + 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, 0x00, 0x02, 0x48, 0xa6, + 0x29, 0xa2, 0x89, 0xff, 0x60, 0xc3, 0x15, 0x9a, 0x31, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6a, 0xb3, 0x63, 0x82, 0xa1, 0xe0, 0xb1, 0xae, + 0xdc, 0x6c, 0x0a, 0x64, 0x16, 0xb4, 0xd1, 0x32, 0xcb, 0xf8, 0xe8, 0x8b, + 0x95, 0xaf, 0x6b, 0xc4, 0xc1, 0xa8, 0x94, 0xb4, 0x5a, 0x6b, 0xcc, 0x08, + 0x35, 0x63, 0x3b, 0xb1, 0xbf, 0x23, 0xdc, 0x59, 0xeb, 0x8b, 0x13, 0x7b, + 0x7d, 0xe5, 0x68, 0x99, 0x65, 0x7c, 0xf4, 0xc5, 0xca, 0xd7, 0x35, 0xe2, + 0x60, 0x54, 0x4a, 0x5a, 0xad, 0x35, 0x66, 0x04, 0xa7, 0xb9, 0xbc, 0x96, + 0x41, 0x93, 0x9d, 0x1d, 0x64, 0x0d, 0x5e, 0x01, 0xbd, 0xf9, 0xcd, 0xe2, + 0x8a, 0x4d, 0x76, 0x4b, 0x88, 0x32, 0x2e, 0x9f, 0x62, 0x95, 0x3f, 0xef, + 0x16, 0x19, 0x90, 0x25, 0xd2, 0xd3, 0x6a, 0x64, 0x89, 0x20, 0x11, 0xc1, + 0xd4, 0x2d, 0x48, 0x1f, 0xa0, 0x09, 0xb2, 0x94, 0x52, 0xc6, 0x76, 0x4f, + 0x8f, 0x47, 0xd6, 0xa3, 0x3a, 0x36, 0x03, 0xa3, 0x0d, 0xae, 0x55, 0x16, + 0x18, 0x28, 0x35, 0x86, 0xd7, 0x67, 0xb0, 0x2d, 0xf3, 0x10, 0xce, 0x84, + 0x9a, 0x0b, 0xed, 0x70, 0xc3, 0x5d, 0x9e, 0x14, 0xbf, 0xb4, 0x1d, 0x85, + 0xa3, 0x9d, 0x59, 0xd9, 0xbc, 0x92, 0xc7, 0x1d, 0xbb, 0xdb, 0x35, 0xa5, + 0x0d, 0xb4, 0xd0, 0x06, 0x11, 0xbc, 0x74, 0xe9, 0xf4, 0xe3, 0x0a, 0xdf, + 0x7b, 0x29, 0x32, 0xf7, 0x56, 0x6b, 0xc1, 0xf5, 0x57, 0xd1, 0x84, 0x74, + 0x14, 0x85, 0x80, 0x21, 0x8c, 0xb0, 0xc5, 0x91, 0xbb, 0xda, 0xe3, 0x98, + 0x27, 0x0c, 0x79, 0x16, 0x2a, 0xd4, 0x4d, 0x07, 0xff, 0x45, 0x84, 0x94, + 0x32, 0x0a, 0xb5, 0x1b, 0x7e, 0x6d, 0x4c, 0xfd, 0x31, 0x01, 0xe2, 0x07, + 0xe3, 0x4c, 0x5f, 0x93, 0x60, 0xfe, 0x2f, 0xd4, 0x34, 0x01, 0xd5, 0x4f, + 0x5c, 0x5a, 0xf5, 0x20, 0xf9, 0x29, 0x58, 0xf0, 0xd9, 0xa3, 0x1f, 0x2e, + 0xee, 0xb9, 0x68, 0x20, 0x46, 0x8f, 0x25, 0x16, 0xaf, 0xcd, 0x76, 0xfb, + 0x24, 0xb9, 0xf0, 0xa3, 0xfd, 0x1c, 0x13, 0x74, 0x67, 0xa1, 0x3c, 0x2b, + 0xd5, 0x42, 0xe8, 0x9a, 0x4c, 0xc8, 0x97, 0x5f, 0x9c, 0x56, 0xb2, 0xdd, + 0x9a, 0x37, 0x29, 0x10, 0xaf, 0xdd, 0x6f, 0xea, 0x07, 0x6d, 0x5c, 0x40, + 0xfc, 0x51, 0x93, 0xf2, 0x72, 0x9e, 0xa7, 0x74, 0xb7, 0xe4, 0x77, 0x0f, + 0x3a, 0x3e, 0xd7, 0x81, 0xc5, 0xac, 0x6d, 0x66, 0x3c, 0x66, 0x5d, 0x23, + 0x8e, 0x0d, 0xb6, 0x4c, 0xa0, 0x69, 0x23, 0x6b, 0xba, 0xc7, 0xc1, 0x0d, + 0xf3, 0x91, 0x02, 0xc4, 0x7e, 0xc7, 0x1d, 0x51, 0x80, 0xcc, 0x30, 0xde, + 0xa7, 0x57, 0xf7, 0x4a, 0xb5, 0x05, 0x42, 0x1b, 0xc4, 0xe6, 0x0b, 0x2e, + 0x38, 0xdc, 0xf4, 0xc9, 0x8f, 0x66, 0x71, 0xae, 0xf3, 0x21, 0xaf, 0xfe, + 0xc2, 0x56, 0xc6, 0xca, 0xff, 0x9c, 0x6b, 0xff, 0x6c, 0xa3, 0xfa, 0x06, + 0xce, 0x5b, 0x52, 0x0e, 0x01, 0x1c, 0x6e, 0x24, 0x43, 0x36, 0xfe, 0x05, + 0x2c, 0xc1, 0x87, 0xdd, 0xc1, 0xc1, 0x94, 0x9f, 0xf9, 0x63, 0x76, 0xf8, + 0xe8, 0x5f, 0x90, 0x2b, 0xcb, 0x78, 0xfa, 0xbf, 0x4c, 0x3c, 0xf1, 0x09, + 0x34, 0x48, 0x73, 0xfe, 0x8e, 0xe4, 0xac, 0xea, 0x6d, 0xfa, 0x59, 0xdd, + 0xc7, 0xbc, 0xc0, 0x99, 0xf5, 0x5b, 0x1a, 0x72, 0xb7, 0x8c, 0xe8, 0x00, + 0x41, 0xaa, 0x61, 0x57, 0x20, 0xb0, 0x29, 0x05, 0x96, 0x64, 0xd9, 0x86, + 0x3c, 0xa4, 0xdd, 0x84, 0x55, 0x9f, 0x37, 0xa5, 0x02, 0xc2, 0xad, 0x1c, + 0x78, 0xc6, 0xd7, 0x87, 0x5e, 0xc9, 0xed, 0x74, 0xc9, 0xe4, 0x8d, 0xde, + 0x9a, 0xeb, 0x23, 0x26, 0xb1, 0xc4, 0x19, 0x6b, 0xdb, 0xd1, 0x55, 0x6e, + 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, 0x1a, 0x32, 0x01, 0xac, + 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, 0xf4, 0xd3, 0x03, 0x2b, + 0x60, 0x15, 0xe6, 0xf2, 0x9e, 0x6e, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x62, 0x9a, 0x58, + 0xde, 0x26, 0x3c, 0x79, 0x98, 0xcc, 0xdb, 0x7d, 0x24, 0xdb, 0x68, 0x99, + 0x65, 0x7c, 0xf4, 0xc5, 0xca, 0xd7, 0x35, 0xe2, 0x60, 0x54, 0x4a, 0x5a, + 0xad, 0x35, 0x66, 0x04, 0xa2, 0xee, 0x03, 0x47, 0x7a, 0xb3, 0x18, 0xc5, + 0xf4, 0xfd, 0x95, 0xea, 0x6c, 0x8f, 0x18, 0xfe, 0xf7, 0xdb, 0x8c, 0xbb, + 0xeb, 0x6d, 0x1a, 0xd6, 0xc8, 0x4b, 0xe7, 0x86, 0xc5, 0x18, 0xfe, 0x2b, + 0x9a, 0xef, 0xec, 0x2f, 0x4e, 0x38, 0x85, 0x1b, 0xff, 0x75, 0xd0, 0x60, + 0x08, 0x0b, 0x78, 0xd8, 0x61, 0x73, 0xe3, 0x70, 0xfe, 0xa5, 0xda, 0x37, + 0x5e, 0xa3, 0x9b, 0xbb, 0xac, 0x50, 0x62, 0x03, 0xdb, 0xf5, 0x03, 0x8e, + 0xc7, 0x8b, 0xea, 0x47, 0xc4, 0x29, 0x76, 0xbe, 0x9f, 0xd3, 0x0a, 0xdf, + 0x7b, 0x29, 0x32, 0xf7, 0x56, 0x6b, 0xc1, 0xf5, 0x57, 0xd1, 0x84, 0x74, + 0x14, 0x85, 0x80, 0x21, 0x6f, 0x38, 0xad, 0xc4, 0x42, 0x5b, 0x3f, 0x35, + 0xfb, 0x88, 0x7a, 0x14, 0xae, 0x3c, 0x94, 0x26, 0x9a, 0xfa, 0xe2, 0x6c, + 0xf7, 0x90, 0x32, 0x33, 0x86, 0x02, 0xd8, 0x07, 0xb6, 0xbb, 0x9c, 0x12, + 0x59, 0xfc, 0x6d, 0xf1, 0xf8, 0x70, 0x53, 0xc2, 0x5f, 0x59, 0x78, 0xe9, + 0x26, 0x88, 0xcf, 0x02, 0x0b, 0x92, 0x0a, 0x32, 0x27, 0xfe, 0x79, 0x14, + 0xef, 0x69, 0x2e, 0x3e, 0x65, 0xa0, 0x0e, 0x1a, 0xe9, 0x8d, 0x49, 0x7a, + 0xd3, 0x99, 0x19, 0xbd, 0x26, 0x8c, 0x69, 0xd0, 0x36, 0x70, 0xaa, 0xac, + 0xee, 0x34, 0x51, 0x93, 0x21, 0xc4, 0x9e, 0x9f, 0xc4, 0x5d, 0x42, 0xb0, + 0x5f, 0x67, 0x2e, 0x19, 0x7a, 0x1b, 0xd7, 0x2a, 0xbe, 0x20, 0xef, 0xf8, + 0x48, 0x8c, 0x94, 0x41, 0x17, 0x59, 0x83, 0x85, 0x0a, 0x14, 0x9a, 0x11, + 0x19, 0x13, 0xa5, 0x08, 0x42, 0x33, 0xf5, 0x88, 0x2e, 0xbb, 0x34, 0x11, + 0xe3, 0xff, 0xf4, 0xbc, 0x7b, 0x6f, 0x78, 0x31, 0x43, 0x9f, 0xd1, 0xa2, + 0x40, 0x3b, 0x94, 0x60, 0xe8, 0x1a, 0x87, 0x46, 0x1d, 0xbd, 0xb3, 0xcf, + 0x1c, 0x72, 0xad, 0x75, 0x1b, 0x6e, 0x6f, 0x04, 0xc4, 0x9a, 0x97, 0x1f, + 0x38, 0x03, 0x47, 0xfd, 0xda, 0xc7, 0x29, 0xf1, 0x0e, 0xb3, 0xd9, 0x02, + 0x77, 0x98, 0xd6, 0x5e, 0x0a, 0x3b, 0xc9, 0xe8, 0x4d, 0xbe, 0x49, 0x61, + 0x17, 0x4a, 0x74, 0x1f, 0x86, 0x59, 0x4d, 0xe6, 0x35, 0x8a, 0xa2, 0x84, + 0x9a, 0x53, 0x18, 0xae, 0x30, 0xa1, 0xb8, 0x8f, 0x09, 0x40, 0xb7, 0x49, + 0xe2, 0x0d, 0x88, 0x49, 0xa3, 0xa0, 0x4d, 0xec, 0xc1, 0xb3, 0x52, 0x10, + 0x89, 0x4c, 0xf1, 0xde, 0xa0, 0x88, 0x00, 0xf6, 0xe8, 0xd1, 0xdf, 0x66, + 0xd7, 0xe5, 0x19, 0xff, 0xd8, 0x72, 0x19, 0x60, 0xd3, 0xfc, 0x14, 0x62, + 0xab, 0xec, 0x0e, 0xdb, 0x1b, 0x13, 0x39, 0x14, 0xe8, 0xfd, 0xa8, 0x79, + 0x03, 0x25, 0xe4, 0x08, 0x4b, 0xdb, 0xfd, 0x49, 0x6e, 0x31, 0xe9, 0x60, + 0xb8, 0x34, 0x58, 0xe0, 0xd0, 0xf2, 0x1e, 0x17, 0x2d, 0x8e, 0xd8, 0xbc, + 0x32, 0x06, 0xa6, 0x2c, 0xfc, 0x63, 0xfc, 0x6d, 0xcb, 0x08, 0x72, 0xb8, + 0xaa, 0xa1, 0xf1, 0x65, 0x11, 0xb2, 0xe2, 0x31, 0xad, 0xab, 0x55, 0x5a, + 0x31, 0x63, 0x8d, 0x3f, 0xfb, 0x04, 0x63, 0x35, 0xda, 0x50, 0x59, 0x1e, + 0x58, 0x41, 0x2b, 0xc2, 0xfd, 0x22, 0x1f, 0x4a, 0x62, 0xaf, 0x1e, 0x21, + 0x50, 0xd3, 0x6a, 0xd8, 0x69, 0xfb, 0x30, 0x19, 0x04, 0xb2, 0x40, 0x7e, + 0xa0, 0x15, 0x68, 0x46, 0xba, 0x4d, 0x66, 0x2d, 0xb1, 0xc4, 0x19, 0x6b, + 0xdb, 0xd1, 0x55, 0x6e, 0xb6, 0x5e, 0xf3, 0x23, 0xba, 0x5e, 0xc8, 0x4d, + 0x1a, 0x32, 0x01, 0xac, 0xbe, 0xaf, 0x9c, 0x15, 0x25, 0x00, 0x65, 0x56, + 0xf4, 0xd3, 0x03, 0x2b, 0x83, 0xff, 0x18, 0xf8, 0x6a, 0x82, 0x06, 0x0c, + 0xe9, 0x8e, 0xe3, 0x14, 0x1d, 0xe2, 0x19, 0xeb, 0x45, 0xab, 0xe6, 0x19, + 0xbe, 0xda, 0xdc, 0x24, 0xd5, 0xec, 0x09, 0x2d, 0x4a, 0xa9, 0xad, 0x09, + 0x2d, 0x2c, 0x5d, 0x28, 0x60, 0xfd, 0x00, 0xe7, 0x7b, 0x5a, 0x0a, 0x08, + 0xf8, 0x04, 0x8f, 0x83, 0xa7, 0x95, 0xa1, 0xbd, 0x7e, 0xe9, 0x1f, 0x72, + 0x1a, 0xe7, 0xc7, 0x4a, 0x5a, 0xeb, 0x12, 0x24, 0xd2, 0xba, 0x16, 0x10, + 0xa7, 0xd3, 0xa8, 0xf3, 0x30, 0x99, 0xb7, 0xfb, 0x48, 0xb6, 0xd1, 0x32, + 0xcb, 0xf8, 0xe8, 0x8b, 0x95, 0xaf, 0x6b, 0xc4, 0xc1, 0xa8, 0x94, 0xb4, + 0x5a, 0x6b, 0xcc, 0x08, 0x8e, 0x5c, 0xb6, 0x27, 0x55, 0x97, 0x20, 0xe6, + 0x2a, 0xd3, 0x6a, 0xa1, 0x83, 0x03, 0x1a, 0x1e, 0x78, 0x20, 0x21, 0xa2, + 0x8a, 0x39, 0x66, 0x4b, 0x55, 0x20, 0xd6, 0xd5, 0x13, 0xa0, 0x7c, 0x20, + 0x37, 0x29, 0x6b, 0xc9, 0x08, 0xac, 0x82, 0x3e, 0xfb, 0x88, 0x7a, 0x14, + 0xae, 0x3c, 0x94, 0x26, 0x9a, 0xfa, 0xe2, 0x6c, 0xf7, 0x90, 0x32, 0x33, + 0x86, 0x02, 0xd8, 0x07, 0xb6, 0xbb, 0x9c, 0x12, 0xc7, 0x98, 0x61, 0x3d, + 0xe2, 0x28, 0xf7, 0xd5, 0x31, 0x77, 0x3f, 0x13, 0x61, 0x4c, 0x03, 0xd9, + 0x96, 0xe8, 0xd7, 0x65, 0xa3, 0xb3, 0x33, 0x5e, 0x99, 0x43, 0x42, 0x98, + 0xf9, 0xf2, 0x69, 0x2d, 0x41, 0x4f, 0x8b, 0xaa, 0xd0, 0xd0, 0xf1, 0x58, + 0x3b, 0x65, 0x4a, 0xea, 0x04, 0xd3, 0xda, 0x8b, 0x62, 0xf3, 0x11, 0x8c, + 0xb4, 0x91, 0xce, 0xf7, 0x8c, 0x3e, 0x92, 0x88, 0x8d, 0x7b, 0x30, 0x08, + 0x85, 0x67, 0xb9, 0x83, 0x4f, 0x52, 0xbb, 0x9c, 0x81, 0x20, 0x52, 0x90, + 0x1a, 0x7c, 0x81, 0x30, 0x49, 0x95, 0x82, 0x08, 0x46, 0x71, 0x6d, 0x88, + 0x3b, 0xb7, 0x1d, 0xf9, 0xa2, 0x62, 0xd6, 0x28, 0x2f, 0x7f, 0x25, 0x74, + 0xa0, 0xc3, 0x09, 0x92, 0x5d, 0x56, 0x55, 0x9f, 0x2b, 0xd3, 0xa6, 0xe0, + 0xe8, 0x00, 0xda, 0x26, 0x1d, 0x48, 0x4b, 0xb7, 0x3f, 0xe3, 0x8e, 0x43, + 0xef, 0x7d, 0x84, 0x0e, 0xd8, 0x5c, 0x0b, 0x88, 0xd3, 0x69, 0xd4, 0x79, + 0x98, 0xcc, 0xdb, 0x7d, 0x24, 0xdb, 0x68, 0x99, 0x65, 0x7c, 0xf4, 0xc5, + 0xca, 0xd7, 0x35, 0xe2, 0x60, 0x54, 0x4a, 0x5a, 0xad, 0x35, 0x66, 0x04, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x69, 0xc2, 0x9a, 0x16, + 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, 0xd4, 0xc4, 0x63, 0x29, + 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, 0x75, 0x6c, 0x06, 0x46, + 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, + 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, + 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, + 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, + 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, + 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, + 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b + }; + unsigned char poseidon_constants_11[] = { + 0xe4, 0xbc, 0x89, 0xd0, 0x6b, 0x09, 0xde, 0xe6, 0x7d, 0xb7, 0x3a, 0x0f, + 0x8e, 0xf1, 0x06, 0xd5, 0xe0, 0x02, 0x89, 0xf3, 0xc5, 0xbf, 0x99, 0x73, + 0x04, 0xb5, 0x48, 0xe6, 0x76, 0x95, 0x6c, 0x1f, 0xa9, 0x8c, 0xf0, 0xc8, + 0x24, 0xe9, 0x8b, 0x25, 0xb2, 0xe8, 0xed, 0xb7, 0x4d, 0xf0, 0xfd, 0x68, + 0x47, 0xa7, 0xa5, 0x43, 0xe2, 0x93, 0x19, 0xd7, 0xeb, 0x3d, 0xdf, 0x28, + 0x70, 0xba, 0xde, 0x06, 0x5a, 0x03, 0xc1, 0x44, 0x7d, 0xd2, 0x7b, 0x88, + 0x8a, 0x35, 0xa3, 0x94, 0xe8, 0x80, 0x72, 0x42, 0x2a, 0x08, 0x3f, 0x03, + 0xc6, 0x83, 0x45, 0x91, 0xc1, 0x65, 0xda, 0x8d, 0x56, 0xff, 0xf5, 0x29, + 0xcf, 0x13, 0xc3, 0x54, 0x65, 0xee, 0xd3, 0xe8, 0x39, 0xe9, 0x31, 0x4a, + 0x96, 0xf9, 0x7d, 0xab, 0x40, 0x62, 0x60, 0x72, 0x56, 0x4e, 0x57, 0xb3, + 0x04, 0x20, 0x2a, 0x48, 0x9e, 0x76, 0x26, 0x07, 0x1a, 0x82, 0xa6, 0xa3, + 0x7a, 0x99, 0xba, 0x22, 0x9f, 0x35, 0x12, 0xb0, 0x92, 0x49, 0xc1, 0x17, + 0xb2, 0xb3, 0xb7, 0x61, 0xe1, 0x20, 0x37, 0x1f, 0x18, 0x6d, 0x45, 0xb0, + 0x24, 0xc5, 0xbf, 0x17, 0xb7, 0x72, 0x7f, 0x67, 0x81, 0x0c, 0x50, 0x0d, + 0x7a, 0x46, 0xcd, 0xf9, 0x48, 0x35, 0x43, 0xb4, 0x05, 0x41, 0xeb, 0xf0, + 0x9b, 0x2d, 0x19, 0xc1, 0x76, 0x27, 0x6f, 0x57, 0x6f, 0x3f, 0x32, 0x14, + 0x45, 0xe7, 0x1c, 0x75, 0x80, 0x2a, 0xb1, 0x47, 0x1e, 0x64, 0x97, 0xe5, + 0x63, 0x80, 0x9f, 0x95, 0xfc, 0x4c, 0x72, 0x8a, 0x86, 0x3a, 0xf9, 0xb6, + 0x53, 0x8d, 0x9d, 0x75, 0xf0, 0x67, 0xd1, 0x2e, 0x95, 0xf9, 0xd2, 0xce, + 0xb3, 0xd0, 0x26, 0x6e, 0x48, 0x27, 0xd2, 0xb9, 0xc9, 0x3f, 0xd7, 0x7a, + 0x81, 0xf4, 0x03, 0xba, 0x05, 0xfc, 0xac, 0x47, 0xf6, 0xb7, 0x92, 0x60, + 0xa4, 0x0a, 0x0c, 0x2f, 0x30, 0x2b, 0x2f, 0xfd, 0x32, 0xee, 0xbd, 0x81, + 0x8a, 0x85, 0x5f, 0x64, 0x77, 0x0d, 0xbb, 0x19, 0xeb, 0xbd, 0xe9, 0xc9, + 0x45, 0xe2, 0xa7, 0x56, 0x1e, 0x11, 0xc4, 0x32, 0x4d, 0xd5, 0x14, 0x1f, + 0x14, 0xb0, 0xc7, 0x7a, 0xfd, 0xb3, 0x81, 0x1e, 0xe1, 0x2c, 0x4e, 0x9c, + 0xd2, 0x4c, 0xad, 0x24, 0x52, 0x7e, 0xcf, 0x9b, 0x04, 0xe5, 0x2f, 0xea, + 0x77, 0x54, 0x75, 0xcf, 0x8b, 0x13, 0x59, 0x17, 0xf9, 0x94, 0x82, 0xdf, + 0x26, 0x90, 0x9b, 0x2a, 0x9b, 0xc9, 0x3c, 0xe2, 0x16, 0x97, 0x54, 0xf6, + 0x7d, 0xa9, 0x03, 0x42, 0x88, 0xe8, 0xcc, 0xf9, 0xbc, 0xf5, 0x40, 0x64, + 0x12, 0xa2, 0x8c, 0x1f, 0x04, 0x04, 0x1d, 0x4f, 0x68, 0xf2, 0x20, 0xab, + 0x03, 0x9a, 0xd9, 0x8f, 0x93, 0xe0, 0x17, 0x04, 0xbc, 0x2c, 0xce, 0x02, + 0xe5, 0x08, 0x65, 0xe0, 0x0d, 0xc2, 0x6c, 0xc2, 0xfd, 0xe0, 0xad, 0x1b, + 0xf3, 0xfc, 0x9c, 0x5a, 0x20, 0x7e, 0xa8, 0xad, 0x26, 0x27, 0x0b, 0x6a, + 0x37, 0x82, 0x74, 0x0b, 0x12, 0xc0, 0x9b, 0xf7, 0x11, 0xd5, 0x6b, 0x3a, + 0x01, 0x3b, 0x54, 0x9e, 0xb2, 0xa3, 0xed, 0x1e, 0x19, 0x4d, 0x7c, 0x47, + 0x79, 0x6e, 0x52, 0x42, 0xfe, 0xf2, 0xcb, 0xd5, 0xd1, 0x8a, 0x4a, 0x28, + 0xa0, 0x16, 0xa2, 0x30, 0xac, 0xf5, 0x66, 0x2d, 0x4a, 0xcf, 0x38, 0xab, + 0x6f, 0xf7, 0x22, 0x0a, 0xba, 0x3d, 0xaa, 0xd1, 0x4a, 0xa6, 0x69, 0xa2, + 0x69, 0x11, 0x2c, 0xdb, 0xad, 0x6f, 0x5d, 0x7a, 0xab, 0x21, 0xf3, 0x88, + 0x19, 0xf1, 0x93, 0xae, 0x3a, 0x5a, 0x6c, 0xd5, 0x47, 0x32, 0x2a, 0x0d, + 0x4e, 0x21, 0x48, 0xcb, 0xa1, 0x92, 0x72, 0xb4, 0xaa, 0x02, 0x0e, 0x09, + 0xc7, 0x31, 0x3b, 0x2e, 0xe8, 0x15, 0xd7, 0x28, 0x29, 0x16, 0x4f, 0xc7, + 0x84, 0xd8, 0x7e, 0xc7, 0xbd, 0xdc, 0x1f, 0x12, 0xcf, 0x0b, 0x68, 0xa0, + 0x81, 0x07, 0xf5, 0xd8, 0x85, 0x42, 0x27, 0xa0, 0x40, 0xfe, 0x2c, 0x7a, + 0x6b, 0x92, 0xbc, 0x07, 0xe6, 0x2f, 0x0d, 0xe4, 0xaf, 0xe6, 0xe1, 0x18, + 0x2e, 0xe4, 0x61, 0x1f, 0x95, 0x4a, 0xca, 0xff, 0xe6, 0x66, 0x1f, 0x51, + 0xe4, 0xa1, 0xb3, 0x73, 0x1e, 0xd2, 0x09, 0x4c, 0xbd, 0x06, 0xce, 0xdc, + 0x35, 0xd9, 0x8a, 0xf0, 0xd1, 0xf6, 0x5f, 0x01, 0x57, 0xf5, 0x34, 0x12, + 0x1f, 0x25, 0x70, 0x72, 0x3d, 0x0d, 0x58, 0xa4, 0xe8, 0x00, 0x07, 0x95, + 0xb0, 0xd8, 0x3b, 0x7a, 0xc7, 0x20, 0x5e, 0xc1, 0xf0, 0xaf, 0x7a, 0xf6, + 0x21, 0xc1, 0x9f, 0x5d, 0x18, 0x4c, 0x2f, 0x2e, 0xc6, 0x53, 0x9d, 0x93, + 0xa8, 0x2c, 0x49, 0x8d, 0xf0, 0xd1, 0x8f, 0x2f, 0xd6, 0x2b, 0x2a, 0x45, + 0x3f, 0xfd, 0xdf, 0xa9, 0xaa, 0x11, 0xaa, 0xd3, 0xc5, 0x0e, 0x33, 0x6e, + 0x74, 0x43, 0xcf, 0x19, 0x60, 0xaa, 0xab, 0x3f, 0xd8, 0x88, 0x7f, 0x22, + 0xe6, 0x23, 0x4e, 0x9d, 0xd5, 0x45, 0x7c, 0xe0, 0xde, 0x26, 0xb9, 0x9a, + 0xa6, 0x0a, 0x48, 0x73, 0xaf, 0x4c, 0x10, 0xf8, 0x3a, 0x0f, 0x5a, 0x15, + 0xe8, 0x44, 0x54, 0x70, 0xad, 0x5f, 0xe6, 0xbf, 0x30, 0x5c, 0xfa, 0x26, + 0x97, 0x9a, 0x6e, 0x8b, 0xa5, 0x2a, 0x9c, 0x7d, 0x91, 0x6e, 0x8c, 0x5d, + 0x8f, 0xcf, 0x72, 0x22, 0x65, 0xa0, 0x9d, 0x1e, 0xc1, 0xd9, 0x6c, 0x58, + 0xbc, 0x58, 0x80, 0x0d, 0x88, 0x3b, 0xa9, 0x3b, 0xa6, 0xde, 0xf7, 0x1c, + 0x6f, 0x09, 0x12, 0x38, 0x9c, 0x3d, 0x75, 0x75, 0xb4, 0xc1, 0xe7, 0x19, + 0xc0, 0x5f, 0x49, 0x15, 0xac, 0x27, 0xac, 0xcf, 0xb8, 0x9d, 0xe6, 0xbc, + 0x82, 0x18, 0x9a, 0x59, 0x52, 0xdd, 0x17, 0xed, 0xac, 0x6a, 0xf9, 0xf0, + 0xee, 0xc3, 0x65, 0x5c, 0x08, 0x41, 0x1d, 0xa8, 0x7d, 0x33, 0x79, 0x09, + 0xc0, 0x7b, 0x3c, 0xdd, 0xfa, 0xa9, 0xb5, 0xac, 0xde, 0xcd, 0x8d, 0x87, + 0xa2, 0x41, 0xd2, 0xce, 0xba, 0xab, 0xbd, 0x72, 0x07, 0x0e, 0xf2, 0xff, + 0xe1, 0x30, 0xd9, 0x62, 0x96, 0xac, 0xae, 0x29, 0x9a, 0x18, 0x25, 0xad, + 0x6d, 0xb1, 0x58, 0xc5, 0xb3, 0xf1, 0xf9, 0x89, 0xd6, 0x85, 0x16, 0xdf, + 0xd5, 0x14, 0xf3, 0x4a, 0x76, 0x29, 0xb8, 0x01, 0x69, 0xe3, 0x14, 0x56, + 0x24, 0xe7, 0x7b, 0x0e, 0x49, 0x4f, 0xdf, 0xf0, 0x12, 0xa3, 0x4f, 0x6a, + 0xcc, 0xfe, 0xa5, 0xee, 0xc8, 0xdb, 0xc5, 0xe6, 0x3e, 0x71, 0x8c, 0xe3, + 0xc1, 0xd3, 0x53, 0xa8, 0x97, 0xee, 0x1b, 0xde, 0xe6, 0xb9, 0x76, 0x19, + 0x39, 0x5a, 0x6d, 0xa7, 0x56, 0x9e, 0xc6, 0x0d, 0xd0, 0xac, 0xe4, 0x10, + 0x26, 0x03, 0x54, 0x56, 0x46, 0x69, 0x36, 0x08, 0xe2, 0xff, 0x3c, 0x8c, + 0xe2, 0x0f, 0x75, 0x0a, 0x68, 0xcd, 0xa2, 0x07, 0xa5, 0x50, 0xe2, 0x68, + 0xb9, 0xeb, 0x87, 0x3d, 0xaa, 0x2d, 0xf7, 0x42, 0x17, 0x60, 0xb1, 0xf9, + 0xad, 0x63, 0xca, 0xd5, 0x0b, 0x4b, 0x11, 0xe7, 0x22, 0x1f, 0x53, 0x8d, + 0xff, 0x12, 0xf6, 0x19, 0xbd, 0x3a, 0xd5, 0xe6, 0x3e, 0xf7, 0x6a, 0xc0, + 0xd3, 0xb9, 0xf9, 0x74, 0xb6, 0x92, 0x16, 0x04, 0xd5, 0x85, 0x3f, 0xd3, + 0xfa, 0x3e, 0xe1, 0x90, 0xf8, 0x82, 0x57, 0x25, 0x24, 0x80, 0x13, 0x11, + 0xc7, 0x48, 0x67, 0x94, 0xe3, 0x88, 0x0d, 0xf5, 0x64, 0xcc, 0xca, 0x4e, + 0xbe, 0x49, 0x35, 0x47, 0x47, 0x08, 0x62, 0x90, 0x50, 0xf7, 0xd9, 0x44, + 0x7e, 0x32, 0x1d, 0x9f, 0xc1, 0xa5, 0xdf, 0x16, 0x89, 0x61, 0xb5, 0xe0, + 0x03, 0x5b, 0x6c, 0x09, 0x4c, 0xbc, 0xe3, 0x53, 0x15, 0xb4, 0xe0, 0x43, + 0x92, 0x11, 0xc0, 0x37, 0x72, 0x92, 0x78, 0x11, 0x43, 0x1c, 0x24, 0x62, + 0x95, 0xad, 0xfc, 0x14, 0x97, 0x60, 0x68, 0x41, 0x39, 0x1e, 0xcf, 0xe6, + 0xd0, 0x7d, 0x5f, 0x65, 0x25, 0x04, 0xf8, 0xdb, 0x22, 0xe7, 0x79, 0x54, + 0xa4, 0xd3, 0xad, 0xbc, 0x70, 0xe1, 0x3d, 0x8a, 0x1b, 0x38, 0x8e, 0x16, + 0xed, 0x87, 0xe7, 0xaa, 0x88, 0x1e, 0x40, 0x4c, 0x86, 0xf9, 0x1c, 0x35, + 0xa0, 0x26, 0x3f, 0x72, 0xde, 0xf4, 0x0f, 0x0f, 0x8e, 0xe0, 0x8c, 0x17, + 0x47, 0x97, 0x1d, 0x85, 0x00, 0x5d, 0x39, 0x24, 0x68, 0xf3, 0x73, 0x35, + 0xbc, 0xdd, 0xea, 0x4d, 0x1a, 0xe6, 0x6c, 0x00, 0x09, 0xc2, 0xfb, 0xb2, + 0x36, 0xb1, 0xa2, 0x89, 0x3d, 0x68, 0x4e, 0x98, 0x7a, 0xec, 0x1b, 0xb7, + 0x36, 0x08, 0x1b, 0x09, 0x67, 0x3d, 0x21, 0x5e, 0x19, 0x81, 0xad, 0x69, + 0x5e, 0xf9, 0x56, 0xe6, 0x6a, 0xa4, 0xd2, 0x55, 0x1d, 0x26, 0xe4, 0xd4, + 0xee, 0xbc, 0x91, 0x1c, 0xde, 0x86, 0xc5, 0x3e, 0xe7, 0x9d, 0x55, 0x23, + 0xa1, 0x4f, 0x6d, 0xc0, 0x10, 0x99, 0xd1, 0xcb, 0x28, 0xbc, 0x1b, 0x1f, + 0x12, 0x51, 0x1f, 0xe8, 0x7e, 0xa3, 0x91, 0x1b, 0xfb, 0x11, 0x9c, 0x2a, + 0x72, 0x07, 0xd4, 0x0c, 0xcf, 0x0c, 0x82, 0x2c, 0x82, 0xba, 0x2e, 0x51, + 0x37, 0x6e, 0x7c, 0xd9, 0x9f, 0xf4, 0xc9, 0xfd, 0x0c, 0xc3, 0x55, 0x71, + 0x45, 0xdd, 0x9e, 0x64, 0x9e, 0x27, 0x35, 0xca, 0x8a, 0xbd, 0xa9, 0xe5, + 0x2c, 0x13, 0xef, 0x17, 0xd7, 0x61, 0xbd, 0x15, 0x20, 0x67, 0x28, 0x72, + 0xad, 0xc2, 0xca, 0x5d, 0xcd, 0x02, 0x5c, 0xab, 0x90, 0x75, 0xec, 0x87, + 0x1d, 0x83, 0x82, 0x3c, 0x12, 0xee, 0x96, 0x39, 0x16, 0x58, 0x33, 0x25, + 0x2d, 0xdf, 0x64, 0x9b, 0xa5, 0x5d, 0xd4, 0xda, 0x82, 0x14, 0x2a, 0xe5, + 0x40, 0xf7, 0xa3, 0x2b, 0xe4, 0xf1, 0xf6, 0x92, 0x6d, 0x7c, 0x1a, 0x38, + 0xd8, 0x50, 0xc8, 0xc0, 0xc4, 0xac, 0x3b, 0x28, 0xf8, 0x4d, 0x66, 0xc4, + 0x5f, 0xd4, 0xd7, 0x4e, 0x44, 0x9b, 0x34, 0xcd, 0xd3, 0x23, 0x4e, 0x98, + 0x91, 0xf0, 0x58, 0xf6, 0x96, 0x22, 0xb8, 0x69, 0x90, 0xdb, 0x8f, 0x3a, + 0x42, 0xdc, 0x87, 0x29, 0x18, 0x45, 0xd7, 0xb0, 0x5f, 0x14, 0x0b, 0x9c, + 0xa2, 0xfb, 0x84, 0xfe, 0x9a, 0x40, 0x07, 0xa2, 0x0e, 0xbf, 0xcc, 0x53, + 0x92, 0x72, 0x48, 0xc4, 0xde, 0x76, 0x27, 0x67, 0xa1, 0x5a, 0x04, 0x21, + 0xcc, 0x07, 0xe1, 0xb9, 0x11, 0xe1, 0xba, 0x48, 0xa4, 0x08, 0xbd, 0x1a, + 0x42, 0x9a, 0x7c, 0x5b, 0x74, 0x72, 0x3f, 0x34, 0x99, 0xc6, 0xf6, 0x51, + 0xca, 0x59, 0x16, 0x22, 0x82, 0x9d, 0x11, 0x23, 0xc5, 0x7d, 0x7f, 0x18, + 0x99, 0x43, 0x47, 0xcc, 0xad, 0xdd, 0x7e, 0xfd, 0xe2, 0xac, 0x24, 0x66, + 0xd1, 0xde, 0xaa, 0x47, 0xb5, 0xc8, 0x67, 0xf9, 0xdc, 0x79, 0x3d, 0xed, + 0xac, 0x98, 0x3e, 0x0e, 0x48, 0xf3, 0x8f, 0xa8, 0x32, 0xdc, 0xd6, 0xee, + 0xc9, 0xc3, 0x9c, 0x73, 0x87, 0x0b, 0x7f, 0xc8, 0xa3, 0xdb, 0x84, 0x36, + 0x68, 0x49, 0x8b, 0x04, 0xd4, 0x59, 0x76, 0x18, 0x3f, 0x32, 0xa1, 0x09, + 0xd6, 0xdb, 0x98, 0xb3, 0xce, 0x0a, 0xba, 0x1c, 0xe9, 0x70, 0x8d, 0x88, + 0xb1, 0xf2, 0x4a, 0x8d, 0xa2, 0x14, 0x26, 0x4d, 0x2e, 0x97, 0xfd, 0xad, + 0x57, 0x1b, 0x26, 0xe5, 0xc3, 0x66, 0x1a, 0x0d, 0x3f, 0xef, 0x56, 0x16, + 0xab, 0x59, 0x0c, 0xf9, 0xd0, 0x00, 0xbf, 0xaa, 0x00, 0x04, 0xe7, 0x27, + 0x5d, 0x9b, 0x82, 0xee, 0xcf, 0x6b, 0x1e, 0x86, 0xe4, 0x38, 0x47, 0xf7, + 0xad, 0x03, 0x3f, 0x0b, 0xd1, 0xda, 0x27, 0x30, 0x2a, 0xe6, 0xf5, 0xbe, + 0x73, 0xfb, 0x8d, 0x20, 0xa3, 0xaa, 0xe2, 0x52, 0x49, 0xd4, 0xa3, 0xfb, + 0x5a, 0x33, 0xe9, 0xc9, 0x9e, 0x3c, 0x27, 0x82, 0x41, 0x79, 0x4d, 0x00, + 0x27, 0x1a, 0x87, 0x8e, 0xf9, 0x1d, 0x48, 0x6d, 0x05, 0xf5, 0xe9, 0x77, + 0x95, 0x47, 0xb4, 0x49, 0x1d, 0x6d, 0x83, 0xa4, 0x80, 0x72, 0x85, 0x6f, + 0x1e, 0x92, 0xbf, 0x38, 0x3f, 0xbc, 0xb4, 0x15, 0x06, 0x42, 0x21, 0xa5, + 0x06, 0x0d, 0xa7, 0x01, 0xe9, 0xfe, 0xcc, 0x43, 0xaa, 0xae, 0x87, 0x65, + 0x10, 0x9e, 0x57, 0xd0, 0x95, 0xed, 0x25, 0x2f, 0xd5, 0x37, 0x57, 0x37, + 0xf2, 0x58, 0x6f, 0x25, 0x31, 0x8d, 0x64, 0xce, 0x1f, 0xab, 0x1d, 0xc6, + 0xb2, 0xa6, 0x06, 0xd1, 0xed, 0x2e, 0xef, 0x8d, 0x21, 0x44, 0xb6, 0x02, + 0xe1, 0xb2, 0xd9, 0xaf, 0xd2, 0xd2, 0x5e, 0x22, 0xb1, 0x2e, 0x2a, 0x05, + 0xe2, 0x50, 0xb7, 0x9d, 0x17, 0x7c, 0xd0, 0xc5, 0xa4, 0xce, 0x7a, 0x73, + 0xe2, 0x01, 0xa0, 0x96, 0x04, 0x21, 0xaa, 0x22, 0xc6, 0x26, 0x6b, 0xf0, + 0x19, 0x86, 0xd1, 0xad, 0x0f, 0xf9, 0x8f, 0x22, 0x99, 0x00, 0x80, 0xd5, + 0x92, 0x66, 0xf9, 0x5e, 0xf3, 0xf8, 0x95, 0xb3, 0x22, 0x82, 0x97, 0x2f, + 0xe3, 0x2a, 0xb1, 0x3e, 0xda, 0xd3, 0x20, 0xb7, 0x30, 0x44, 0xcb, 0xf2, + 0xb4, 0x73, 0x14, 0x2a, 0xea, 0x0b, 0x79, 0xfe, 0x49, 0x90, 0x43, 0x27, + 0x2e, 0x08, 0x58, 0xbd, 0x19, 0x1a, 0x91, 0x16, 0x36, 0x0b, 0x75, 0xda, + 0x2b, 0xe9, 0x2b, 0xe4, 0x0c, 0xdc, 0xab, 0xc0, 0xea, 0x67, 0x05, 0x0e, + 0x9a, 0xd3, 0xaf, 0x71, 0xb7, 0xb8, 0x2d, 0xbb, 0xab, 0xda, 0xd1, 0x33, + 0x2d, 0xd8, 0x4b, 0xcb, 0x4f, 0x7a, 0x65, 0xab, 0xa4, 0x3d, 0x90, 0xdc, + 0x8c, 0x89, 0x01, 0xbf, 0x09, 0x3a, 0xb9, 0x17, 0x10, 0xca, 0x90, 0x43, + 0xb9, 0xd1, 0xbe, 0x62, 0xa3, 0x4a, 0xe9, 0x87, 0x30, 0x04, 0xb6, 0x25, + 0x36, 0xdb, 0x6f, 0xc5, 0x8e, 0xd3, 0x3b, 0xe8, 0xc1, 0x1a, 0x35, 0xa9, + 0x01, 0xfe, 0xa5, 0x07, 0x05, 0x0d, 0xa9, 0x8f, 0x45, 0x28, 0x0c, 0x47, + 0x62, 0xb5, 0x60, 0x28, 0x2b, 0x3e, 0x64, 0xec, 0x4b, 0x8f, 0x11, 0xa2, + 0x8f, 0x86, 0x4b, 0xa5, 0xae, 0xd7, 0xb3, 0x8a, 0x5d, 0x79, 0xa4, 0x1a, + 0x76, 0x7c, 0xaa, 0x8a, 0x35, 0x36, 0xa0, 0xcf, 0x79, 0x40, 0x87, 0x05, + 0x0c, 0xda, 0xe6, 0x33, 0x87, 0xf5, 0x65, 0x9b, 0x38, 0x83, 0xa3, 0xed, + 0x1e, 0x2f, 0x9a, 0x0c, 0xd3, 0x2b, 0x70, 0x0b, 0x3f, 0xb6, 0xe7, 0x50, + 0x19, 0x62, 0x9b, 0x1f, 0xab, 0x25, 0xaf, 0x74, 0x82, 0x03, 0x9d, 0x3d, + 0x13, 0x30, 0x3e, 0xeb, 0xca, 0xda, 0xed, 0x07, 0xe3, 0x15, 0xca, 0x2b, + 0x95, 0x35, 0x8d, 0x1b, 0x9b, 0x16, 0x4e, 0x7c, 0x79, 0xb1, 0x01, 0x3a, + 0xa2, 0xb0, 0xe3, 0xa7, 0xad, 0xd9, 0x7c, 0xe8, 0xf7, 0x9f, 0xce, 0xb3, + 0x34, 0x75, 0x57, 0xca, 0x20, 0x65, 0x71, 0x54, 0xee, 0xe0, 0x13, 0x1d, + 0x87, 0x3a, 0xee, 0x3f, 0x06, 0xc4, 0xc1, 0x90, 0xfd, 0x02, 0x49, 0x51, + 0x6e, 0x02, 0xda, 0xa8, 0x54, 0x73, 0x0d, 0x25, 0x39, 0x85, 0x6e, 0xdb, + 0x8d, 0x18, 0x2e, 0x67, 0xbe, 0xec, 0xba, 0x07, 0x0f, 0x32, 0x9a, 0x74, + 0x23, 0x4a, 0x14, 0x97, 0xe3, 0x8f, 0xe5, 0x8b, 0x23, 0x89, 0x89, 0xd4, + 0x4f, 0x34, 0x60, 0xa7, 0xa1, 0xdd, 0x27, 0x6e, 0xbd, 0x94, 0xf2, 0xd5, + 0x46, 0xf1, 0x77, 0x06, 0x7b, 0x40, 0xdb, 0xe0, 0x6e, 0x61, 0xec, 0x64, + 0xb7, 0x99, 0x76, 0x83, 0x8d, 0x55, 0xe5, 0xda, 0x83, 0xc7, 0xca, 0xa6, + 0x77, 0x41, 0xb8, 0xa1, 0x98, 0x0d, 0x3f, 0x6c, 0x2f, 0xc6, 0x40, 0x07, + 0xaf, 0x82, 0x35, 0x11, 0x8e, 0x6a, 0x06, 0x48, 0x55, 0xd3, 0x84, 0x8a, + 0xe0, 0x6d, 0x36, 0xab, 0xc3, 0x44, 0x3b, 0x49, 0x79, 0x9d, 0x7e, 0x77, + 0xf1, 0xee, 0x71, 0x3b, 0x45, 0xd5, 0x3f, 0x21, 0x87, 0x33, 0xde, 0xba, + 0x22, 0x4b, 0x4e, 0x5c, 0x99, 0xb3, 0x20, 0x5c, 0xa2, 0x99, 0xc2, 0x79, + 0x2e, 0xd1, 0x6d, 0xc9, 0x97, 0xfa, 0xc5, 0x69, 0xe2, 0xf7, 0xd1, 0x2c, + 0x3d, 0x12, 0x85, 0x2d, 0x29, 0x55, 0x70, 0xb0, 0xa0, 0x1a, 0x97, 0x8e, + 0x86, 0x89, 0x66, 0x33, 0xfe, 0x4b, 0xb8, 0x71, 0x3d, 0x43, 0xff, 0x06, + 0x95, 0x2a, 0x40, 0x54, 0x89, 0x41, 0x50, 0x7c, 0xf3, 0xb1, 0x13, 0x20, + 0x88, 0x89, 0x24, 0x3a, 0x11, 0x30, 0xd2, 0x49, 0xc3, 0x6a, 0xca, 0x1e, + 0xd7, 0xcc, 0x77, 0x9c, 0xa7, 0x92, 0x44, 0xbf, 0x21, 0x7d, 0x53, 0x17, + 0xa9, 0x7b, 0x1f, 0x6c, 0x7a, 0x94, 0x11, 0x06, 0x0c, 0x7f, 0xeb, 0x8d, + 0x9e, 0xef, 0x67, 0x38, 0x8a, 0xe5, 0x22, 0x7a, 0x49, 0xf9, 0x51, 0x98, + 0xc0, 0xfa, 0x67, 0xba, 0x7a, 0x49, 0xcd, 0x2f, 0xf5, 0xd2, 0x7c, 0x3c, + 0xb5, 0xdf, 0xf8, 0x28, 0xbb, 0x42, 0x81, 0xe1, 0x24, 0x45, 0xc6, 0x81, + 0x67, 0x57, 0xa0, 0x11, 0x57, 0xbb, 0x51, 0x29, 0xc5, 0x6f, 0x87, 0x84, + 0x3f, 0xb3, 0x72, 0x40, 0xfb, 0xe1, 0x71, 0x8a, 0x2c, 0x62, 0x36, 0x29, + 0xf5, 0x7e, 0x63, 0x58, 0xfd, 0x7e, 0xa0, 0xa2, 0x13, 0x61, 0xfb, 0xe2, + 0x9e, 0x06, 0x2c, 0xaf, 0x2a, 0x40, 0x90, 0x9e, 0x42, 0x2b, 0xc7, 0x52, + 0x51, 0x32, 0xf5, 0x14, 0x4d, 0x9b, 0x7b, 0x0c, 0xb7, 0x75, 0x54, 0x85, + 0xce, 0x24, 0xc6, 0xfb, 0x73, 0xab, 0x97, 0x9c, 0x25, 0x42, 0x18, 0x3e, + 0x9f, 0x33, 0xe8, 0x57, 0x37, 0xdc, 0xaf, 0x5d, 0xc5, 0x2f, 0x4d, 0x66, + 0xaf, 0x35, 0xe7, 0x01, 0x70, 0x6f, 0x49, 0xbd, 0xbf, 0x4b, 0x18, 0xcd, + 0x60, 0x11, 0xe4, 0xd6, 0xa9, 0x04, 0x1f, 0x03, 0x47, 0xc0, 0xeb, 0x85, + 0x00, 0x04, 0xe8, 0x76, 0x87, 0xd0, 0x15, 0x74, 0xb3, 0xaa, 0x9a, 0x21, + 0x87, 0xba, 0xc2, 0xa4, 0x84, 0xd4, 0x4a, 0x6b, 0x9a, 0xbf, 0x68, 0xd4, + 0x12, 0xea, 0x9e, 0x06, 0xda, 0x88, 0xad, 0xeb, 0xc6, 0xd7, 0x5e, 0xd3, + 0x5b, 0x6b, 0x80, 0xb2, 0xd0, 0xbe, 0x27, 0x30, 0x9f, 0x53, 0xd6, 0x8b, + 0x11, 0x65, 0x07, 0xc0, 0x55, 0x03, 0x8e, 0xb1, 0xc6, 0xf2, 0x13, 0x73, + 0x4a, 0x45, 0xb5, 0x99, 0xbc, 0xcc, 0xb4, 0xd7, 0x24, 0x87, 0xe3, 0x16, + 0xb7, 0x6f, 0xd8, 0x1d, 0x82, 0x73, 0x6b, 0x81, 0x4f, 0x45, 0xbc, 0x8b, + 0x6d, 0x2c, 0xd0, 0xc4, 0xb1, 0x26, 0xe4, 0x27, 0xf9, 0xdc, 0x92, 0xc6, + 0x3b, 0x47, 0xd3, 0x88, 0xd5, 0x0c, 0x68, 0x87, 0x5b, 0x9d, 0x6c, 0x15, + 0xdb, 0x95, 0x7a, 0x98, 0x08, 0xe3, 0xb6, 0x95, 0x05, 0xcb, 0x46, 0x41, + 0x18, 0x2f, 0xb9, 0x13, 0xf8, 0x67, 0xc1, 0xfd, 0x83, 0x72, 0x65, 0xfe, + 0xc8, 0x7c, 0x76, 0xbb, 0x52, 0x0f, 0x63, 0x1a, 0xdc, 0x2c, 0xc8, 0x7b, + 0x3e, 0xb6, 0x7e, 0x28, 0xdb, 0xf4, 0x21, 0x75, 0x27, 0xd7, 0x1e, 0xf2, + 0x9e, 0x92, 0xf4, 0x78, 0xb3, 0x2b, 0xcc, 0x86, 0x4e, 0xac, 0xb8, 0xfc, + 0x69, 0x1e, 0x17, 0x17, 0x28, 0xc3, 0x62, 0x65, 0x0a, 0x49, 0xa6, 0x1b, + 0xdd, 0x5e, 0xce, 0x7a, 0x23, 0x25, 0xba, 0x3d, 0x88, 0x62, 0x42, 0x71, + 0x49, 0xb9, 0xda, 0x22, 0x68, 0xa0, 0x02, 0xec, 0x7b, 0xd2, 0x29, 0x20, + 0x29, 0xed, 0xd9, 0x6a, 0x8c, 0xae, 0x72, 0x61, 0xcf, 0xae, 0x75, 0x8f, + 0x1d, 0x5e, 0x21, 0xeb, 0xab, 0x0b, 0xc2, 0xfe, 0x07, 0x98, 0x2a, 0x7f, + 0xce, 0x39, 0xea, 0x6f, 0x88, 0xc4, 0xbd, 0x23, 0x2a, 0x3f, 0xfe, 0x5e, + 0x89, 0x13, 0x41, 0x7d, 0xc9, 0x64, 0x17, 0x8c, 0xe6, 0x02, 0xf8, 0x3a, + 0x20, 0xfd, 0x32, 0x7a, 0x1b, 0xc7, 0xaf, 0x14, 0xf2, 0xc9, 0xea, 0x92, + 0xdb, 0x89, 0x41, 0x03, 0x4c, 0x08, 0xc5, 0x89, 0x7c, 0x7d, 0x80, 0x8f, + 0x43, 0x29, 0x0e, 0xd8, 0xc9, 0x53, 0x05, 0x24, 0x73, 0x59, 0x90, 0xb9, + 0xef, 0x07, 0x70, 0x4f, 0xdf, 0xd8, 0x6c, 0xfc, 0x39, 0x4b, 0xf7, 0x1e, + 0xa5, 0xf9, 0x0b, 0x17, 0x66, 0x12, 0xf5, 0x5a, 0x5b, 0x39, 0x77, 0x01, + 0xdc, 0x9b, 0xa0, 0xd2, 0xef, 0x2a, 0x74, 0x49, 0x33, 0x7f, 0x8b, 0x7c, + 0x13, 0xde, 0x47, 0x27, 0x67, 0x23, 0x42, 0x1b, 0xa4, 0xbb, 0x82, 0x31, + 0x9c, 0xf8, 0x4e, 0x98, 0x26, 0x80, 0x27, 0xdc, 0x64, 0x49, 0x35, 0xf2, + 0x45, 0x10, 0x46, 0x0c, 0xbb, 0x2b, 0x93, 0x27, 0x55, 0xdf, 0x71, 0x26, + 0x7d, 0xeb, 0x92, 0x17, 0x50, 0xae, 0x0d, 0x5b, 0x96, 0x58, 0x9b, 0xed, + 0xaa, 0xd0, 0xc2, 0x53, 0xe8, 0xf3, 0x73, 0x91, 0xa0, 0x0f, 0x99, 0x45, + 0x32, 0x4f, 0x08, 0x4a, 0xc4, 0x69, 0xe8, 0x31, 0x53, 0xf6, 0xfa, 0x01, + 0x89, 0x22, 0x7f, 0x13, 0x79, 0x6a, 0x12, 0xa8, 0xef, 0x65, 0xa7, 0x30, + 0xfc, 0x12, 0x57, 0x15, 0x20, 0xab, 0xd0, 0xee, 0xb6, 0xa4, 0xe1, 0x80, + 0xa4, 0xad, 0x69, 0x9b, 0xa1, 0xea, 0xcb, 0x13, 0x8d, 0x65, 0xa9, 0x00, + 0x75, 0x0e, 0x81, 0x43, 0x0e, 0x9f, 0x99, 0x72, 0x3e, 0x47, 0xe2, 0x28, + 0x07, 0x3c, 0xcf, 0x64, 0x08, 0xb3, 0x7c, 0x12, 0xb1, 0x98, 0xf0, 0xc0, + 0x2a, 0xbd, 0x7a, 0x09, 0x15, 0x76, 0x69, 0x83, 0xe8, 0x29, 0x35, 0x28, + 0xbd, 0xc1, 0x91, 0xa5, 0xb8, 0x90, 0xc9, 0xc1, 0x2f, 0x02, 0x3a, 0xaa, + 0xb6, 0xdf, 0xa3, 0xcf, 0x13, 0x32, 0xc2, 0xc1, 0x8b, 0x78, 0xc1, 0x1f, + 0x49, 0x84, 0xa8, 0x17, 0x7e, 0xe4, 0x1d, 0xe3, 0xb0, 0x9a, 0x67, 0xb9, + 0xa0, 0x16, 0x0b, 0x0f, 0x0b, 0xa5, 0xc2, 0x52, 0x4c, 0xc3, 0xd2, 0x47, + 0xbf, 0x3e, 0x27, 0x65, 0x19, 0x1d, 0xdf, 0x29, 0xc2, 0xbf, 0xd7, 0x47, + 0x64, 0xd6, 0xba, 0x36, 0xed, 0xb8, 0xc3, 0x12, 0x72, 0x16, 0x79, 0x94, + 0x58, 0x87, 0xb2, 0x93, 0x58, 0xf8, 0x45, 0xcc, 0x60, 0x74, 0x30, 0x10, + 0x1e, 0xc7, 0x6a, 0x08, 0x99, 0x5b, 0x60, 0x2c, 0x6f, 0xa7, 0xbf, 0x91, + 0xc7, 0xca, 0xce, 0x01, 0x5f, 0x15, 0xb0, 0x86, 0x3e, 0xc9, 0x04, 0xe6, + 0x7e, 0x66, 0xa9, 0xce, 0x9e, 0xfc, 0xa9, 0x62, 0xcf, 0x7b, 0x99, 0x0b, + 0x60, 0xb5, 0xfd, 0x64, 0xc7, 0xf1, 0x43, 0x48, 0x51, 0xec, 0xb5, 0x4a, + 0x20, 0x48, 0x23, 0xf8, 0xfe, 0xdf, 0xeb, 0x0e, 0x0d, 0x99, 0x08, 0x50, + 0xbf, 0xe6, 0x16, 0x9f, 0x4f, 0xe8, 0xbf, 0x1f, 0x8b, 0xe1, 0xed, 0xd4, + 0x0b, 0x3c, 0x37, 0x87, 0x4e, 0x52, 0x3f, 0xd1, 0x49, 0x4f, 0x0e, 0x6b, + 0x7c, 0xba, 0xb1, 0xae, 0xf5, 0x39, 0xbd, 0xf1, 0xe9, 0x83, 0x43, 0xa5, + 0xee, 0x88, 0x2c, 0x1c, 0xee, 0x30, 0xe1, 0xf8, 0xa4, 0xc4, 0x26, 0xea, + 0x97, 0x9b, 0x7d, 0xf5, 0x3f, 0xc1, 0x96, 0xfe, 0x3b, 0x97, 0xce, 0x27, + 0xce, 0xd3, 0x09, 0x6c, 0xfe, 0x7e, 0x27, 0x4d, 0x03, 0x53, 0x8a, 0x0a, + 0xa2, 0xc1, 0xdd, 0xb5, 0x0e, 0x38, 0x1e, 0xb8, 0xe6, 0xb4, 0x00, 0x19, + 0x18, 0x32, 0x0c, 0x5e, 0x11, 0x94, 0xa4, 0xe6, 0xec, 0xda, 0x9f, 0x14, + 0x43, 0xa3, 0x42, 0x50, 0x69, 0xb9, 0x82, 0x03, 0x8e, 0xe9, 0x57, 0xc6, + 0x25, 0x5b, 0x4c, 0xe4, 0x6a, 0x1d, 0x2b, 0xc2, 0xf5, 0xd7, 0xde, 0xd7, + 0x9d, 0xb0, 0x51, 0x18, 0xe1, 0x07, 0x61, 0xde, 0xcf, 0x17, 0x4c, 0x0d, + 0x50, 0x5b, 0x1a, 0x1a, 0x1b, 0x6b, 0x7f, 0x1c, 0x8c, 0x3e, 0x85, 0x3e, + 0x5b, 0x6c, 0xf6, 0xf1, 0x1e, 0x94, 0x2a, 0xf2, 0xfa, 0x45, 0x3e, 0xd9, + 0x82, 0xd6, 0x9c, 0x2e, 0x55, 0x19, 0x4a, 0x33, 0xb6, 0xfc, 0x54, 0x25, + 0x0a, 0x1a, 0xd1, 0x42, 0xf7, 0x7a, 0xa3, 0x20, 0xcf, 0x26, 0xbc, 0x08, + 0xec, 0xd6, 0x36, 0xd6, 0x8c, 0x62, 0x58, 0x90, 0x3e, 0x03, 0x7a, 0x75, + 0x26, 0xa6, 0xce, 0x56, 0x8d, 0x9b, 0x48, 0x26, 0x19, 0x3c, 0xe6, 0x62, + 0x36, 0x0a, 0xf1, 0x4c, 0x82, 0x04, 0x2f, 0x92, 0x23, 0x95, 0xcc, 0x5a, + 0xf4, 0xd0, 0xa1, 0xd2, 0xd1, 0xde, 0x50, 0x45, 0xdf, 0x54, 0xc1, 0x48, + 0x03, 0xd9, 0x84, 0x0a, 0x09, 0x42, 0xd8, 0xb2, 0xb2, 0x7a, 0x6d, 0xbc, + 0x02, 0x80, 0x5c, 0x6b, 0x73, 0x49, 0x5d, 0x2a, 0x1b, 0x6e, 0x72, 0xc9, + 0x3e, 0x53, 0xca, 0xa2, 0xa1, 0x44, 0x17, 0x96, 0x80, 0x65, 0x18, 0x0c, + 0x43, 0x4b, 0x77, 0xdc, 0x4e, 0x4a, 0x8b, 0xd5, 0x89, 0x8e, 0x59, 0xf1, + 0x61, 0x15, 0xff, 0xe0, 0xc0, 0x9f, 0x9f, 0xde, 0x56, 0x58, 0x2c, 0xd4, + 0x1a, 0xda, 0x25, 0x84, 0xde, 0x62, 0x92, 0x29, 0x8d, 0xec, 0x14, 0x17, + 0x5b, 0xc6, 0x21, 0xf7, 0x97, 0x1c, 0xc1, 0xba, 0xcc, 0x75, 0xe2, 0x0a, + 0x47, 0x5e, 0x94, 0xdb, 0x7b, 0x8a, 0x50, 0x5e, 0x33, 0x00, 0x65, 0x45, + 0x4e, 0xef, 0x07, 0x13, 0x6d, 0xf6, 0xf1, 0xee, 0x39, 0x7b, 0x65, 0x48, + 0x23, 0x7e, 0x07, 0xc0, 0x3b, 0x67, 0xb4, 0x7f, 0x30, 0x98, 0x09, 0x39, + 0xd3, 0x23, 0xbf, 0x80, 0x8e, 0xa0, 0x4d, 0xfd, 0x53, 0x8b, 0x06, 0x19, + 0xd9, 0xd6, 0xc4, 0x88, 0x6c, 0x87, 0xed, 0x0c, 0x54, 0xd2, 0x8e, 0xb4, + 0x25, 0xf0, 0xa2, 0xee, 0x3c, 0x0e, 0x14, 0x1e, 0xe4, 0x10, 0x01, 0x2a, + 0xef, 0x15, 0x74, 0xd5, 0x1b, 0xc3, 0x4b, 0x1d, 0x35, 0x5e, 0xc3, 0x46, + 0xbe, 0xfe, 0x88, 0xba, 0xc5, 0x0c, 0x48, 0x37, 0xe1, 0xd7, 0xb7, 0x4c, + 0x6f, 0xa3, 0xd9, 0xc3, 0x35, 0x8e, 0xde, 0x20, 0x0b, 0xbf, 0xe4, 0xf2, + 0x74, 0xef, 0x9f, 0x21, 0xfb, 0xca, 0x58, 0x95, 0xd5, 0x56, 0x88, 0xca, + 0xda, 0xc4, 0xce, 0x65, 0x0e, 0xe6, 0x50, 0x65, 0x48, 0x59, 0xeb, 0x93, + 0xad, 0x10, 0x9b, 0xd1, 0xd2, 0xbd, 0x9a, 0xc8, 0xbd, 0x81, 0xc1, 0x16, + 0x70, 0xaa, 0x4f, 0x3b, 0x22, 0x09, 0xc1, 0x8e, 0x14, 0xbe, 0xc8, 0x35, + 0xb4, 0x70, 0x11, 0x06, 0x24, 0xb6, 0x8d, 0x74, 0xd8, 0xbc, 0xfc, 0xbc, + 0x3a, 0x66, 0xf0, 0xc7, 0x3c, 0x3d, 0xa4, 0x02, 0x06, 0x02, 0x12, 0xa3, + 0xf2, 0xf3, 0x2f, 0x60, 0x32, 0x08, 0xa6, 0xbb, 0x61, 0x5d, 0xc6, 0xf8, + 0x63, 0x8f, 0xac, 0xe2, 0x27, 0x89, 0xba, 0x22, 0x92, 0x95, 0x18, 0xec, + 0xb3, 0x3f, 0xbb, 0x00, 0xc5, 0x1a, 0x50, 0x4c, 0x6e, 0xc7, 0xad, 0xd7, + 0x87, 0xda, 0x1f, 0xe9, 0x86, 0x58, 0x8f, 0x94, 0x4b, 0x69, 0x5e, 0x68, + 0xe0, 0xb1, 0x26, 0xb4, 0x94, 0xae, 0x9e, 0xd1, 0x9c, 0xe6, 0x36, 0x2e, + 0x21, 0xa1, 0xe3, 0x87, 0x43, 0xcf, 0xaa, 0x0e, 0xc4, 0xe7, 0x83, 0x2a, + 0xfa, 0xf2, 0x59, 0xe3, 0x1a, 0xb6, 0x3a, 0xc0, 0x5d, 0x2f, 0x54, 0xaa, + 0xee, 0x09, 0x62, 0x0b, 0x97, 0x09, 0x01, 0x29, 0xca, 0x51, 0xab, 0xdb, + 0x81, 0xe5, 0xe5, 0x91, 0x89, 0x02, 0x5e, 0xc3, 0x9c, 0x8a, 0xe2, 0x8e, + 0xde, 0x7e, 0x6e, 0x05, 0x2c, 0xe2, 0xec, 0xa4, 0x4f, 0x3c, 0x41, 0xfc, + 0xaf, 0x74, 0x4a, 0x1f, 0xa1, 0x06, 0x68, 0x94, 0x17, 0xf9, 0xa6, 0x79, + 0x61, 0xe3, 0x29, 0xa1, 0x57, 0x86, 0x07, 0x85, 0x90, 0xe4, 0x6f, 0x79, + 0xcf, 0x45, 0x6b, 0x11, 0x77, 0xce, 0x68, 0x18, 0x84, 0xf3, 0xb7, 0x2f, + 0x55, 0xc8, 0x6d, 0x8a, 0x1e, 0x69, 0x6d, 0xfb, 0x05, 0xea, 0x5b, 0x06, + 0x53, 0xec, 0x42, 0x1b, 0xfb, 0x3c, 0xc3, 0x5f, 0x66, 0x55, 0x8a, 0xc8, + 0xbb, 0x4c, 0x9d, 0x3e, 0xba, 0xa0, 0xda, 0x0c, 0xe9, 0x7c, 0x33, 0x06, + 0x8f, 0x78, 0xe6, 0xf2, 0xb7, 0x44, 0x15, 0xdc, 0xd8, 0x80, 0x20, 0xe7, + 0x84, 0xee, 0x9a, 0xa0, 0xdf, 0x19, 0x02, 0xbf, 0xf9, 0x0d, 0x21, 0xc0, + 0x64, 0x54, 0xef, 0x21, 0x2f, 0xb9, 0xc4, 0xab, 0x65, 0xc9, 0x6a, 0x1d, + 0x24, 0x35, 0xb9, 0x09, 0xaa, 0x41, 0x99, 0xf3, 0x0a, 0xe5, 0x8b, 0xfd, + 0x09, 0x5b, 0xa7, 0xab, 0x63, 0x54, 0x8f, 0x81, 0x1c, 0x1a, 0x42, 0x18, + 0x7f, 0xc0, 0x0b, 0xa2, 0x3d, 0x28, 0x78, 0x51, 0x22, 0xc5, 0x07, 0x4c, + 0x5b, 0x95, 0x64, 0x04, 0x00, 0x3c, 0x4b, 0x29, 0x68, 0x6c, 0x6a, 0x01, + 0x73, 0xf8, 0xb1, 0x41, 0xff, 0xe3, 0x86, 0x2c, 0x1d, 0x72, 0x3d, 0x37, + 0x14, 0x98, 0x9f, 0x35, 0x0e, 0xeb, 0xda, 0x0d, 0x44, 0x58, 0x2f, 0x52, + 0x68, 0x85, 0x11, 0xf1, 0x33, 0xe4, 0x3d, 0x52, 0x1a, 0xa9, 0x57, 0xdc, + 0x62, 0x94, 0xb7, 0x0f, 0xf2, 0x84, 0x8a, 0xd8, 0xcb, 0xe2, 0xb7, 0x52, + 0x1a, 0x6a, 0x92, 0xf4, 0xc0, 0x4b, 0x59, 0x9f, 0x4d, 0xa9, 0x83, 0xdd, + 0x78, 0x98, 0xfb, 0xec, 0x2c, 0x39, 0x64, 0x77, 0x85, 0x33, 0x6b, 0x28, + 0x56, 0xd5, 0xf6, 0x75, 0x0a, 0x01, 0x05, 0xf2, 0x65, 0x55, 0xe3, 0x4f, + 0x4a, 0x46, 0x05, 0xb8, 0x62, 0xd5, 0xce, 0x28, 0x26, 0x7a, 0xed, 0x8c, + 0x4f, 0xcc, 0x4e, 0x6b, 0x92, 0x17, 0xc7, 0x28, 0x0f, 0x9a, 0xdc, 0x69, + 0x3b, 0x95, 0x68, 0x5c, 0xa7, 0xeb, 0xe4, 0xcf, 0x9c, 0x96, 0x68, 0x81, + 0x1d, 0xcd, 0x60, 0x48, 0x87, 0xb3, 0xf4, 0x6c, 0x2e, 0xda, 0x61, 0x08, + 0xa2, 0xf3, 0x58, 0x20, 0xcc, 0xb8, 0x37, 0x49, 0x19, 0xe7, 0x6d, 0x61, + 0x75, 0xba, 0xee, 0xe1, 0xfa, 0x89, 0xde, 0xf4, 0x0e, 0xfc, 0xef, 0x8a, + 0x8d, 0x40, 0x9e, 0x12, 0x90, 0x3e, 0xe8, 0xd3, 0x25, 0x48, 0x6a, 0x23, + 0xd0, 0x84, 0xdc, 0x73, 0xe5, 0x34, 0xcb, 0x0b, 0x26, 0xff, 0xff, 0x0f, + 0x82, 0x1f, 0x69, 0xf8, 0x38, 0x90, 0xa4, 0x3a, 0x9f, 0x01, 0xc8, 0x89, + 0x71, 0xb0, 0xcc, 0xa2, 0x73, 0x0b, 0x0f, 0x04, 0x0b, 0x42, 0xc7, 0xa4, + 0x69, 0xa2, 0x6b, 0x2e, 0x54, 0x38, 0x66, 0xb4, 0xf3, 0x53, 0xb3, 0x24, + 0x95, 0x9e, 0xc4, 0x7d, 0x16, 0x23, 0x85, 0x52, 0x38, 0xd9, 0xee, 0xa1, + 0x7a, 0x81, 0x50, 0x09, 0x0c, 0x10, 0x86, 0x5f, 0xfe, 0x16, 0xbd, 0xb3, + 0x7a, 0x24, 0xce, 0xaa, 0xc3, 0x3d, 0xf8, 0x26, 0x38, 0xc6, 0x50, 0x15, + 0x68, 0xf4, 0x0d, 0xf4, 0x68, 0x69, 0xaf, 0xe3, 0x93, 0xc3, 0xd0, 0x0d, + 0x91, 0x7b, 0x89, 0xf4, 0xb5, 0xc9, 0x14, 0x58, 0x55, 0x53, 0x7f, 0xcf, + 0x44, 0xf6, 0x0f, 0x2c, 0xc7, 0x47, 0xe7, 0x0a, 0xed, 0x92, 0x48, 0x75, + 0x99, 0x63, 0xd1, 0x54, 0x27, 0x7d, 0x46, 0x1a, 0x30, 0xb4, 0xf1, 0x71, + 0x46, 0x5a, 0x8f, 0x5c, 0xdc, 0xc1, 0x08, 0xa8, 0x32, 0x3b, 0x33, 0x47, + 0xce, 0x5c, 0x1c, 0x3a, 0x99, 0x45, 0x62, 0xa1, 0xde, 0x64, 0x21, 0xa9, + 0xb5, 0xa2, 0x18, 0x27, 0x06, 0x6b, 0x2b, 0x8b, 0x4c, 0x0f, 0xbc, 0x7a, + 0x8a, 0x5d, 0xfc, 0x3f, 0x50, 0xc6, 0xc5, 0x6a, 0x90, 0xcb, 0x8d, 0xb9, + 0x09, 0xb4, 0xae, 0x3b, 0xc3, 0x6d, 0x92, 0x05, 0xd6, 0xc3, 0x72, 0x06, + 0x5d, 0x06, 0x48, 0xf3, 0xd0, 0x08, 0x89, 0x8a, 0xbe, 0xe3, 0x28, 0x5b, + 0xf7, 0xe2, 0xfc, 0x52, 0x85, 0xb4, 0xb4, 0x4b, 0xb2, 0x63, 0x2d, 0xf4, + 0xbd, 0x31, 0x90, 0x6c, 0xa7, 0xf8, 0x10, 0x29, 0x9c, 0x9c, 0x18, 0x46, + 0x52, 0x8b, 0x39, 0xb6, 0xf0, 0x08, 0x63, 0x70, 0x2f, 0xb7, 0x47, 0x79, + 0xac, 0xb9, 0x07, 0xd7, 0x49, 0x2b, 0xe4, 0x81, 0xb9, 0x22, 0x11, 0x10, + 0xff, 0xa7, 0x6c, 0x15, 0x82, 0x0a, 0xb7, 0xe0, 0xdb, 0x37, 0xf5, 0xbc, + 0x54, 0x14, 0x97, 0x35, 0x25, 0x01, 0xe6, 0x14, 0xef, 0x18, 0xfe, 0x06, + 0xd6, 0x5f, 0x23, 0xdb, 0x87, 0x14, 0x8c, 0xe5, 0x53, 0xe6, 0x9b, 0x1b, + 0x63, 0xa7, 0xa4, 0xdb, 0xe7, 0x16, 0xd0, 0xce, 0x7a, 0x87, 0x4f, 0xad, + 0xac, 0x60, 0x96, 0x96, 0xb2, 0x6d, 0x6b, 0xda, 0x32, 0xb0, 0xc0, 0x01, + 0xe7, 0x79, 0x7f, 0xe7, 0x65, 0x07, 0xe0, 0x12, 0x8d, 0xc3, 0x0b, 0x70, + 0x0b, 0x0a, 0xb8, 0x60, 0xcb, 0xbb, 0x87, 0x2d, 0xba, 0x3d, 0x7c, 0xf6, + 0xfd, 0xc8, 0x10, 0x4d, 0x34, 0x0d, 0x01, 0xc9, 0xf3, 0x32, 0x0b, 0x97, + 0x5d, 0x78, 0x87, 0x1d, 0xce, 0xa1, 0x01, 0x14, 0xdf, 0xcc, 0x0d, 0x62, + 0x36, 0x8f, 0x9e, 0x31, 0xb7, 0x46, 0xbe, 0x5a, 0x1a, 0xf9, 0x21, 0x60, + 0x14, 0x04, 0x7c, 0x69, 0x37, 0xf8, 0xc6, 0xa7, 0x3a, 0x66, 0x62, 0x22, + 0x55, 0xe8, 0x92, 0x06, 0xdf, 0x00, 0x64, 0xb8, 0x9f, 0xb3, 0x66, 0x03, + 0x70, 0x3a, 0x7c, 0x88, 0x35, 0x3b, 0x5c, 0x53, 0xb0, 0x12, 0x52, 0xd5, + 0xfc, 0xcb, 0x55, 0x34, 0xb7, 0xa4, 0xe5, 0x22, 0x5e, 0x1b, 0x2a, 0x7d, + 0xff, 0xfd, 0x50, 0x46, 0x5d, 0xda, 0x1e, 0x91, 0xf5, 0xf7, 0x3e, 0x56, + 0x6a, 0xf0, 0xb5, 0xfc, 0xeb, 0x28, 0x13, 0x23, 0x46, 0xeb, 0x4f, 0x33, + 0x27, 0x8b, 0x3d, 0x0d, 0x4a, 0x5a, 0x4e, 0x05, 0xd1, 0x3b, 0xe2, 0x94, + 0x6f, 0x25, 0x64, 0x26, 0xd5, 0x00, 0xce, 0x68, 0x8a, 0x26, 0x8d, 0xd4, + 0x6f, 0x71, 0x4a, 0xab, 0x9c, 0x14, 0xf9, 0x83, 0xe8, 0x52, 0x19, 0x04, + 0xea, 0x9a, 0x18, 0x51, 0x5f, 0xbc, 0xeb, 0x30, 0x5d, 0xf1, 0x16, 0xe3, + 0x97, 0x6c, 0x95, 0x68, 0x2b, 0xf3, 0x3a, 0x78, 0x86, 0xea, 0xf1, 0xa0, + 0x7e, 0xdb, 0xdc, 0x93, 0xc3, 0x70, 0x2a, 0x2d, 0x9e, 0xe5, 0x90, 0x6a, + 0x38, 0x72, 0x88, 0xfb, 0x3b, 0x0f, 0x6c, 0xa6, 0x5d, 0xbd, 0x75, 0x36, + 0x7e, 0x20, 0x58, 0x58, 0x10, 0xe1, 0xad, 0xc0, 0x9d, 0x96, 0xda, 0x70, + 0xd3, 0x3e, 0xa4, 0x1b, 0x6e, 0x71, 0xcb, 0xd8, 0xc2, 0xfd, 0x93, 0xae, + 0xd0, 0x33, 0x99, 0x12, 0xb5, 0x55, 0x40, 0xdd, 0x21, 0xfb, 0x90, 0xbc, + 0xd7, 0x2f, 0xea, 0xbd, 0x47, 0x49, 0xdc, 0x21, 0x6c, 0x62, 0x66, 0x21, + 0x1a, 0x85, 0xb6, 0xca, 0x3a, 0x05, 0xb8, 0x79, 0x6c, 0x8c, 0x60, 0xb3, + 0x8c, 0xcb, 0x01, 0xe0, 0x73, 0xef, 0xc3, 0x59, 0x9a, 0xb5, 0xc4, 0x53, + 0xa9, 0x57, 0xfa, 0x0f, 0xa9, 0x74, 0xef, 0x00, 0xc8, 0x19, 0xdc, 0xe7, + 0x6a, 0xcd, 0x09, 0xd6, 0xf6, 0x98, 0xcb, 0x9a, 0x50, 0x13, 0x09, 0x39, + 0xe2, 0xc4, 0x28, 0x56, 0x26, 0x22, 0x46, 0xb0, 0xe6, 0xfa, 0x2e, 0xd8, + 0xcd, 0x7c, 0x2e, 0x0a, 0x16, 0x83, 0xd9, 0xcc, 0xbd, 0x64, 0x54, 0x64, + 0x47, 0x8f, 0x3d, 0x98, 0xd9, 0x28, 0xeb, 0xe2, 0x82, 0x27, 0x91, 0x95, + 0xb5, 0x83, 0x34, 0x72, 0x6f, 0xdb, 0xc5, 0x42, 0x6b, 0xb4, 0x83, 0x25, + 0xe5, 0xd1, 0xfb, 0x24, 0xaa, 0xf9, 0xe6, 0xaa, 0xb7, 0x7f, 0xf6, 0xf1, + 0x6c, 0x02, 0x7e, 0xe9, 0xc8, 0x04, 0x1b, 0xf5, 0x32, 0x42, 0xf5, 0x19, + 0x86, 0x40, 0xaf, 0xca, 0xe5, 0x4d, 0xdd, 0x24, 0xea, 0xee, 0xd8, 0xae, + 0xb9, 0x24, 0x25, 0x21, 0xef, 0x38, 0xed, 0x2d, 0xf3, 0x5f, 0x12, 0xbf, + 0x09, 0x1c, 0x16, 0x4b, 0xee, 0xe6, 0x6d, 0x57, 0x81, 0xbd, 0x83, 0xb0, + 0x0e, 0x70, 0xa5, 0x14, 0xa0, 0xac, 0x9f, 0xb0, 0x18, 0x60, 0xa4, 0xb7, + 0xab, 0x9b, 0xb4, 0xbd, 0xd3, 0x0c, 0x13, 0xa9, 0x93, 0x41, 0xc8, 0x52, + 0xd7, 0xf3, 0x2e, 0xef, 0xbf, 0x6a, 0x54, 0x68, 0xd1, 0x62, 0x57, 0x29, + 0x3a, 0xfd, 0x9d, 0xea, 0x75, 0x2e, 0xbb, 0xbf, 0x40, 0x5f, 0x1d, 0x02, + 0xb4, 0x88, 0x90, 0x41, 0x55, 0xda, 0x11, 0xa6, 0xcc, 0x19, 0x61, 0xcd, + 0x4c, 0x7c, 0xdc, 0x70, 0xb7, 0x4e, 0x87, 0x00, 0x7c, 0xa9, 0x6d, 0x45, + 0x3e, 0x26, 0xaf, 0xe1, 0x64, 0x46, 0x81, 0x18, 0x76, 0xd6, 0x47, 0xb9, + 0xd2, 0xaf, 0xdf, 0x71, 0x64, 0x47, 0xc8, 0xd3, 0xe3, 0x81, 0x21, 0x05, + 0x07, 0xae, 0xc7, 0x0e, 0xc8, 0x60, 0x81, 0xf3, 0x4a, 0x64, 0xa0, 0x81, + 0x75, 0xc6, 0xbb, 0x0a, 0xc0, 0xa2, 0x92, 0xe4, 0x9b, 0x58, 0x79, 0x4e, + 0x22, 0xc8, 0xe2, 0xde, 0x96, 0xb7, 0xc6, 0x36, 0x53, 0x2d, 0xf0, 0x1d, + 0x70, 0xdb, 0x70, 0x61, 0x53, 0x13, 0x50, 0x30, 0xfc, 0xca, 0xc1, 0x80, + 0x0b, 0x49, 0x31, 0xb9, 0x51, 0xc7, 0x31, 0x3a, 0x7a, 0xe9, 0xdf, 0x3d, + 0xa2, 0xb0, 0x01, 0xc9, 0xfb, 0x0a, 0x92, 0x1e, 0x31, 0x9d, 0x6b, 0x51, + 0x07, 0x63, 0x56, 0x6e, 0x6d, 0x45, 0x99, 0x63, 0x23, 0x26, 0x41, 0x4c, + 0xeb, 0xc1, 0xc6, 0x85, 0x8a, 0x4a, 0x37, 0xb3, 0x49, 0xce, 0x9d, 0x17, + 0x29, 0x0f, 0x4b, 0x22, 0x2d, 0xd4, 0xb1, 0x8b, 0xef, 0x07, 0x17, 0xea, + 0x5d, 0x14, 0x0a, 0x0c, 0xaa, 0x5e, 0xcf, 0xf6, 0x66, 0xb1, 0x20, 0x18, + 0x8c, 0x78, 0xd6, 0xa4, 0x7f, 0xb5, 0xee, 0x39, 0x13, 0x97, 0x26, 0x0d, + 0x8c, 0x38, 0x33, 0xa1, 0xbe, 0x89, 0xb7, 0xb7, 0xfd, 0x87, 0x7d, 0x49, + 0x8e, 0xcd, 0xbe, 0x10, 0x6a, 0x17, 0xe0, 0xa7, 0xa4, 0x56, 0xa3, 0xc0, + 0x2b, 0x20, 0x18, 0x11, 0x03, 0x5b, 0xce, 0x21, 0x09, 0x0a, 0x50, 0x6d, + 0x31, 0x00, 0x90, 0x33, 0x3b, 0x47, 0x75, 0xaf, 0x2d, 0x1c, 0x2c, 0xb4, + 0x03, 0x3d, 0x9e, 0xf7, 0xd7, 0x28, 0x19, 0xe2, 0x90, 0x16, 0x05, 0x21, + 0x88, 0x1d, 0xd7, 0x29, 0xa2, 0x44, 0xcb, 0x27, 0xda, 0xe4, 0xee, 0x6e, + 0x06, 0x09, 0x41, 0x09, 0xa6, 0x67, 0xf3, 0xc9, 0x68, 0xb4, 0xed, 0x26, + 0x7b, 0x4d, 0x1d, 0x9d, 0xd1, 0x3c, 0x9a, 0xe3, 0x2c, 0xcc, 0x12, 0x14, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x69, 0xc2, 0x9a, 0x16, + 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, 0xd4, 0xc4, 0x63, 0x29, + 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, 0x75, 0x6c, 0x06, 0x46, + 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, + 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, + 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, + 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, + 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, + 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, + 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, + 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, + 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, + 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, + 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, + 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, + 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, + 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, + 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, + 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, + 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, + 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, + 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, + 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, + 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, + 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, + 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, + 0x69, 0xc2, 0x9a, 0x16, 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, + 0xd4, 0xc4, 0x63, 0x29, 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, + 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, + 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, + 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, + 0x5a, 0xab, 0x05, 0x26, 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, + 0x6d, 0xd2, 0x5e, 0xe2, 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, + 0xa5, 0x9c, 0xf7, 0x0c, 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, + 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, + 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, + 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, + 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, + 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, + 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, + 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, + 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, + 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, + 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, + 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, + 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, + 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, + 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, + 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, + 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, + 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, + 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, + 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, + 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, + 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, + 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, + 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, + 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, + 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, + 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, + 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, 0x37, 0xa9, 0x42, 0x40, + 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, 0xa2, 0x05, 0x45, 0xc8, + 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, 0xe3, 0xcc, 0x6f, 0xcd, + 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, + 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, + 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, + 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, + 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, + 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, + 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, + 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, + 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, + 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, + 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, + 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, + 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, + 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, + 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, + 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, + 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, + 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, + 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, + 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, + 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, + 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, + 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, + 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, + 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, + 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, + 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, + 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, + 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, + 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, + 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, + 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, + 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, + 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, + 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, + 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, + 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, + 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, + 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, + 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, + 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, + 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, + 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, + 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, + 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, + 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, + 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, + 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, + 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, + 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, + 0x73, 0x81, 0x9d, 0x6d, 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, + 0xf6, 0x99, 0xbd, 0x42, 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, + 0xc6, 0x98, 0xce, 0x05, 0xd8, 0xdf, 0x8b, 0xf7, 0x15, 0xae, 0x46, 0x1c, + 0x74, 0x56, 0x32, 0x33, 0xb3, 0x97, 0x72, 0x60, 0x81, 0x72, 0x37, 0x90, + 0x6a, 0x6a, 0xfe, 0x7f, 0x4f, 0x06, 0x9c, 0x13, 0x47, 0xd5, 0x87, 0x2e, + 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, + 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, + 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, + 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, + 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, + 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, + 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, + 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, + 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, + 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, + 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, + 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, + 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, + 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, + 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, + 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, + 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, + 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, + 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, + 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, + 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, + 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, + 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, + 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, + 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, 0x25, 0xbc, 0xbb, 0x3f, + 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, 0xa5, 0xe9, 0xea, 0xe2, + 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, 0xd8, 0xdf, 0x8b, 0xf7, + 0x15, 0xae, 0x46, 0x1c, 0x74, 0x56, 0x32, 0x33, 0xb3, 0x97, 0x72, 0x60, + 0x81, 0x72, 0x37, 0x90, 0x6a, 0x6a, 0xfe, 0x7f, 0x4f, 0x06, 0x9c, 0x13, + 0x47, 0xd5, 0x87, 0x2e, 0xa8, 0x40, 0x32, 0xc1, 0x50, 0x1f, 0xd2, 0x38, + 0xc1, 0x0d, 0x77, 0xd9, 0xc3, 0xed, 0x6d, 0x4c, 0x7d, 0x83, 0x2b, 0x0f, + 0x27, 0xa7, 0xf9, 0x99, 0x6f, 0x35, 0x32, 0xbd, 0x77, 0x0b, 0x78, 0x1e, + 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, + 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, + 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, 0xfc, 0x60, 0xcb, 0x21, + 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, 0xa5, 0xe4, 0xa4, 0xf2, + 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, 0x27, 0x50, 0xcb, 0x9b, + 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, + 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, + 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, + 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, + 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, + 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, + 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, + 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, + 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, + 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, + 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, + 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, + 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, + 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, + 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, + 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, + 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, + 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, + 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, + 0xd8, 0xdf, 0x8b, 0xf7, 0x15, 0xae, 0x46, 0x1c, 0x74, 0x56, 0x32, 0x33, + 0xb3, 0x97, 0x72, 0x60, 0x81, 0x72, 0x37, 0x90, 0x6a, 0x6a, 0xfe, 0x7f, + 0x4f, 0x06, 0x9c, 0x13, 0x47, 0xd5, 0x87, 0x2e, 0xa8, 0x40, 0x32, 0xc1, + 0x50, 0x1f, 0xd2, 0x38, 0xc1, 0x0d, 0x77, 0xd9, 0xc3, 0xed, 0x6d, 0x4c, + 0x7d, 0x83, 0x2b, 0x0f, 0x27, 0xa7, 0xf9, 0x99, 0x6f, 0x35, 0x32, 0xbd, + 0x77, 0x0b, 0x78, 0x1e, 0x24, 0xe2, 0x01, 0xaf, 0xa6, 0xa1, 0x41, 0x1a, + 0xfe, 0xbd, 0xae, 0xf8, 0x4a, 0x68, 0x6a, 0x90, 0x53, 0xea, 0x0e, 0xcf, + 0x19, 0xf5, 0xd9, 0xf6, 0x92, 0x73, 0x35, 0x92, 0xe6, 0xfc, 0x34, 0x2b, + 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, + 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, + 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, + 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, + 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, + 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, + 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, + 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, + 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, + 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, + 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, + 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, + 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, + 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, + 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, + 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, + 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, + 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, + 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, + 0x73, 0x81, 0x9d, 0x6d, 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, + 0xf6, 0x99, 0xbd, 0x42, 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, + 0xc6, 0x98, 0xce, 0x05, 0xd8, 0xdf, 0x8b, 0xf7, 0x15, 0xae, 0x46, 0x1c, + 0x74, 0x56, 0x32, 0x33, 0xb3, 0x97, 0x72, 0x60, 0x81, 0x72, 0x37, 0x90, + 0x6a, 0x6a, 0xfe, 0x7f, 0x4f, 0x06, 0x9c, 0x13, 0x47, 0xd5, 0x87, 0x2e, + 0xa8, 0x40, 0x32, 0xc1, 0x50, 0x1f, 0xd2, 0x38, 0xc1, 0x0d, 0x77, 0xd9, + 0xc3, 0xed, 0x6d, 0x4c, 0x7d, 0x83, 0x2b, 0x0f, 0x27, 0xa7, 0xf9, 0x99, + 0x6f, 0x35, 0x32, 0xbd, 0x77, 0x0b, 0x78, 0x1e, 0x24, 0xe2, 0x01, 0xaf, + 0xa6, 0xa1, 0x41, 0x1a, 0xfe, 0xbd, 0xae, 0xf8, 0x4a, 0x68, 0x6a, 0x90, + 0x53, 0xea, 0x0e, 0xcf, 0x19, 0xf5, 0xd9, 0xf6, 0x92, 0x73, 0x35, 0x92, + 0xe6, 0xfc, 0x34, 0x2b, 0xc9, 0x81, 0x81, 0xeb, 0xe9, 0x98, 0x16, 0x05, + 0x9a, 0x8e, 0x4a, 0xb4, 0xaf, 0xa4, 0x59, 0x28, 0x98, 0xad, 0xba, 0x59, + 0xdc, 0xf3, 0x9c, 0xc3, 0x42, 0xe1, 0x64, 0x0e, 0x9b, 0x1f, 0xb9, 0x2e, + 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, + 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, + 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, + 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, + 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, + 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, + 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, + 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, + 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, + 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, + 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, + 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, + 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, + 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, + 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, + 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, + 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, 0x25, 0xbc, 0xbb, 0x3f, + 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, 0xa5, 0xe9, 0xea, 0xe2, + 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, 0xd8, 0xdf, 0x8b, 0xf7, + 0x15, 0xae, 0x46, 0x1c, 0x74, 0x56, 0x32, 0x33, 0xb3, 0x97, 0x72, 0x60, + 0x81, 0x72, 0x37, 0x90, 0x6a, 0x6a, 0xfe, 0x7f, 0x4f, 0x06, 0x9c, 0x13, + 0x47, 0xd5, 0x87, 0x2e, 0xa8, 0x40, 0x32, 0xc1, 0x50, 0x1f, 0xd2, 0x38, + 0xc1, 0x0d, 0x77, 0xd9, 0xc3, 0xed, 0x6d, 0x4c, 0x7d, 0x83, 0x2b, 0x0f, + 0x27, 0xa7, 0xf9, 0x99, 0x6f, 0x35, 0x32, 0xbd, 0x77, 0x0b, 0x78, 0x1e, + 0x24, 0xe2, 0x01, 0xaf, 0xa6, 0xa1, 0x41, 0x1a, 0xfe, 0xbd, 0xae, 0xf8, + 0x4a, 0x68, 0x6a, 0x90, 0x53, 0xea, 0x0e, 0xcf, 0x19, 0xf5, 0xd9, 0xf6, + 0x92, 0x73, 0x35, 0x92, 0xe6, 0xfc, 0x34, 0x2b, 0xc9, 0x81, 0x81, 0xeb, + 0xe9, 0x98, 0x16, 0x05, 0x9a, 0x8e, 0x4a, 0xb4, 0xaf, 0xa4, 0x59, 0x28, + 0x98, 0xad, 0xba, 0x59, 0xdc, 0xf3, 0x9c, 0xc3, 0x42, 0xe1, 0x64, 0x0e, + 0x9b, 0x1f, 0xb9, 0x2e, 0x3f, 0xd3, 0x5f, 0x0c, 0x9a, 0x9e, 0xc3, 0x58, + 0x7d, 0x4e, 0x68, 0x25, 0x1a, 0x38, 0xe3, 0xaf, 0x36, 0x3b, 0xf4, 0x0d, + 0x2e, 0xf1, 0xa3, 0x62, 0x86, 0xb6, 0x50, 0x57, 0x9c, 0xb3, 0x19, 0x25, + 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, + 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, + 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, 0x56, 0x2f, 0xaf, 0x03, + 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, 0xad, 0xee, 0x8c, 0x5b, + 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, 0xa8, 0x84, 0x7b, 0xd7, + 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, + 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, + 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, + 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, + 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, + 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, + 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, + 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, + 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, + 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, + 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, + 0xd8, 0xdf, 0x8b, 0xf7, 0x15, 0xae, 0x46, 0x1c, 0x74, 0x56, 0x32, 0x33, + 0xb3, 0x97, 0x72, 0x60, 0x81, 0x72, 0x37, 0x90, 0x6a, 0x6a, 0xfe, 0x7f, + 0x4f, 0x06, 0x9c, 0x13, 0x47, 0xd5, 0x87, 0x2e, 0xa8, 0x40, 0x32, 0xc1, + 0x50, 0x1f, 0xd2, 0x38, 0xc1, 0x0d, 0x77, 0xd9, 0xc3, 0xed, 0x6d, 0x4c, + 0x7d, 0x83, 0x2b, 0x0f, 0x27, 0xa7, 0xf9, 0x99, 0x6f, 0x35, 0x32, 0xbd, + 0x77, 0x0b, 0x78, 0x1e, 0x24, 0xe2, 0x01, 0xaf, 0xa6, 0xa1, 0x41, 0x1a, + 0xfe, 0xbd, 0xae, 0xf8, 0x4a, 0x68, 0x6a, 0x90, 0x53, 0xea, 0x0e, 0xcf, + 0x19, 0xf5, 0xd9, 0xf6, 0x92, 0x73, 0x35, 0x92, 0xe6, 0xfc, 0x34, 0x2b, + 0xc9, 0x81, 0x81, 0xeb, 0xe9, 0x98, 0x16, 0x05, 0x9a, 0x8e, 0x4a, 0xb4, + 0xaf, 0xa4, 0x59, 0x28, 0x98, 0xad, 0xba, 0x59, 0xdc, 0xf3, 0x9c, 0xc3, + 0x42, 0xe1, 0x64, 0x0e, 0x9b, 0x1f, 0xb9, 0x2e, 0x3f, 0xd3, 0x5f, 0x0c, + 0x9a, 0x9e, 0xc3, 0x58, 0x7d, 0x4e, 0x68, 0x25, 0x1a, 0x38, 0xe3, 0xaf, + 0x36, 0x3b, 0xf4, 0x0d, 0x2e, 0xf1, 0xa3, 0x62, 0x86, 0xb6, 0x50, 0x57, + 0x9c, 0xb3, 0x19, 0x25, 0x37, 0x48, 0x71, 0x02, 0x5c, 0x09, 0x74, 0xcb, + 0x3b, 0x4a, 0x1e, 0x59, 0x89, 0x73, 0x6c, 0xf9, 0x58, 0x02, 0xe0, 0xd7, + 0xbe, 0x4e, 0xe3, 0x54, 0x41, 0x84, 0x89, 0x74, 0x69, 0xf2, 0x76, 0x25, + 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, + 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, + 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, + 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, + 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, + 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, + 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, + 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, + 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, + 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, + 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, + 0x73, 0x81, 0x9d, 0x6d, 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, + 0xf6, 0x99, 0xbd, 0x42, 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, + 0xc6, 0x98, 0xce, 0x05, 0xd8, 0xdf, 0x8b, 0xf7, 0x15, 0xae, 0x46, 0x1c, + 0x74, 0x56, 0x32, 0x33, 0xb3, 0x97, 0x72, 0x60, 0x81, 0x72, 0x37, 0x90, + 0x6a, 0x6a, 0xfe, 0x7f, 0x4f, 0x06, 0x9c, 0x13, 0x47, 0xd5, 0x87, 0x2e, + 0xa8, 0x40, 0x32, 0xc1, 0x50, 0x1f, 0xd2, 0x38, 0xc1, 0x0d, 0x77, 0xd9, + 0xc3, 0xed, 0x6d, 0x4c, 0x7d, 0x83, 0x2b, 0x0f, 0x27, 0xa7, 0xf9, 0x99, + 0x6f, 0x35, 0x32, 0xbd, 0x77, 0x0b, 0x78, 0x1e, 0x24, 0xe2, 0x01, 0xaf, + 0xa6, 0xa1, 0x41, 0x1a, 0xfe, 0xbd, 0xae, 0xf8, 0x4a, 0x68, 0x6a, 0x90, + 0x53, 0xea, 0x0e, 0xcf, 0x19, 0xf5, 0xd9, 0xf6, 0x92, 0x73, 0x35, 0x92, + 0xe6, 0xfc, 0x34, 0x2b, 0xc9, 0x81, 0x81, 0xeb, 0xe9, 0x98, 0x16, 0x05, + 0x9a, 0x8e, 0x4a, 0xb4, 0xaf, 0xa4, 0x59, 0x28, 0x98, 0xad, 0xba, 0x59, + 0xdc, 0xf3, 0x9c, 0xc3, 0x42, 0xe1, 0x64, 0x0e, 0x9b, 0x1f, 0xb9, 0x2e, + 0x3f, 0xd3, 0x5f, 0x0c, 0x9a, 0x9e, 0xc3, 0x58, 0x7d, 0x4e, 0x68, 0x25, + 0x1a, 0x38, 0xe3, 0xaf, 0x36, 0x3b, 0xf4, 0x0d, 0x2e, 0xf1, 0xa3, 0x62, + 0x86, 0xb6, 0x50, 0x57, 0x9c, 0xb3, 0x19, 0x25, 0x37, 0x48, 0x71, 0x02, + 0x5c, 0x09, 0x74, 0xcb, 0x3b, 0x4a, 0x1e, 0x59, 0x89, 0x73, 0x6c, 0xf9, + 0x58, 0x02, 0xe0, 0xd7, 0xbe, 0x4e, 0xe3, 0x54, 0x41, 0x84, 0x89, 0x74, + 0x69, 0xf2, 0x76, 0x25, 0x3c, 0x27, 0xe3, 0x6c, 0x66, 0x27, 0xe9, 0xb8, + 0xf7, 0x00, 0x60, 0xe5, 0xf8, 0x65, 0x9c, 0x52, 0xda, 0x60, 0x6c, 0x54, + 0x9b, 0x93, 0xd6, 0xbb, 0x0b, 0xf5, 0x55, 0x4f, 0x10, 0x36, 0x9c, 0x0d, + 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, + 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, + 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, + 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, + 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, + 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, 0x3a, 0x63, 0xec, 0x5f, + 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, 0xec, 0xf3, 0x10, 0xf1, + 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, 0xe6, 0x0c, 0x47, 0x22, + 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, 0x25, 0xbc, 0xbb, 0x3f, + 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, 0xa5, 0xe9, 0xea, 0xe2, + 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, 0xd8, 0xdf, 0x8b, 0xf7, + 0x15, 0xae, 0x46, 0x1c, 0x74, 0x56, 0x32, 0x33, 0xb3, 0x97, 0x72, 0x60, + 0x81, 0x72, 0x37, 0x90, 0x6a, 0x6a, 0xfe, 0x7f, 0x4f, 0x06, 0x9c, 0x13, + 0x47, 0xd5, 0x87, 0x2e, 0xa8, 0x40, 0x32, 0xc1, 0x50, 0x1f, 0xd2, 0x38, + 0xc1, 0x0d, 0x77, 0xd9, 0xc3, 0xed, 0x6d, 0x4c, 0x7d, 0x83, 0x2b, 0x0f, + 0x27, 0xa7, 0xf9, 0x99, 0x6f, 0x35, 0x32, 0xbd, 0x77, 0x0b, 0x78, 0x1e, + 0x24, 0xe2, 0x01, 0xaf, 0xa6, 0xa1, 0x41, 0x1a, 0xfe, 0xbd, 0xae, 0xf8, + 0x4a, 0x68, 0x6a, 0x90, 0x53, 0xea, 0x0e, 0xcf, 0x19, 0xf5, 0xd9, 0xf6, + 0x92, 0x73, 0x35, 0x92, 0xe6, 0xfc, 0x34, 0x2b, 0xc9, 0x81, 0x81, 0xeb, + 0xe9, 0x98, 0x16, 0x05, 0x9a, 0x8e, 0x4a, 0xb4, 0xaf, 0xa4, 0x59, 0x28, + 0x98, 0xad, 0xba, 0x59, 0xdc, 0xf3, 0x9c, 0xc3, 0x42, 0xe1, 0x64, 0x0e, + 0x9b, 0x1f, 0xb9, 0x2e, 0x3f, 0xd3, 0x5f, 0x0c, 0x9a, 0x9e, 0xc3, 0x58, + 0x7d, 0x4e, 0x68, 0x25, 0x1a, 0x38, 0xe3, 0xaf, 0x36, 0x3b, 0xf4, 0x0d, + 0x2e, 0xf1, 0xa3, 0x62, 0x86, 0xb6, 0x50, 0x57, 0x9c, 0xb3, 0x19, 0x25, + 0x37, 0x48, 0x71, 0x02, 0x5c, 0x09, 0x74, 0xcb, 0x3b, 0x4a, 0x1e, 0x59, + 0x89, 0x73, 0x6c, 0xf9, 0x58, 0x02, 0xe0, 0xd7, 0xbe, 0x4e, 0xe3, 0x54, + 0x41, 0x84, 0x89, 0x74, 0x69, 0xf2, 0x76, 0x25, 0x3c, 0x27, 0xe3, 0x6c, + 0x66, 0x27, 0xe9, 0xb8, 0xf7, 0x00, 0x60, 0xe5, 0xf8, 0x65, 0x9c, 0x52, + 0xda, 0x60, 0x6c, 0x54, 0x9b, 0x93, 0xd6, 0xbb, 0x0b, 0xf5, 0x55, 0x4f, + 0x10, 0x36, 0x9c, 0x0d, 0x22, 0x1d, 0x57, 0x68, 0x00, 0xd6, 0xb1, 0x50, + 0xe6, 0x75, 0xea, 0xc4, 0x17, 0x90, 0xce, 0x42, 0x60, 0x64, 0x52, 0x98, + 0x12, 0x21, 0xf2, 0x70, 0x91, 0x31, 0x8f, 0x09, 0x31, 0x46, 0xba, 0x21, + 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, + 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, + 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, 0xbd, 0x88, 0x58, 0xd9, + 0x3a, 0x63, 0xec, 0x5f, 0x79, 0xef, 0xa5, 0x54, 0x7c, 0xab, 0xfb, 0xf5, + 0xec, 0xf3, 0x10, 0xf1, 0x0b, 0xdc, 0x38, 0x8d, 0x1d, 0x7c, 0xd8, 0xb4, + 0xe6, 0x0c, 0x47, 0x22, 0x46, 0x99, 0xa8, 0x61, 0x73, 0x81, 0x9d, 0x6d, + 0x25, 0xbc, 0xbb, 0x3f, 0xde, 0xba, 0x42, 0xc0, 0xf6, 0x99, 0xbd, 0x42, + 0xa5, 0xe9, 0xea, 0xe2, 0x7f, 0xf4, 0x05, 0x1b, 0xc6, 0x98, 0xce, 0x05, + 0xd8, 0xdf, 0x8b, 0xf7, 0x15, 0xae, 0x46, 0x1c, 0x74, 0x56, 0x32, 0x33, + 0xb3, 0x97, 0x72, 0x60, 0x81, 0x72, 0x37, 0x90, 0x6a, 0x6a, 0xfe, 0x7f, + 0x4f, 0x06, 0x9c, 0x13, 0x47, 0xd5, 0x87, 0x2e, 0xa8, 0x40, 0x32, 0xc1, + 0x50, 0x1f, 0xd2, 0x38, 0xc1, 0x0d, 0x77, 0xd9, 0xc3, 0xed, 0x6d, 0x4c, + 0x7d, 0x83, 0x2b, 0x0f, 0x27, 0xa7, 0xf9, 0x99, 0x6f, 0x35, 0x32, 0xbd, + 0x77, 0x0b, 0x78, 0x1e, 0x24, 0xe2, 0x01, 0xaf, 0xa6, 0xa1, 0x41, 0x1a, + 0xfe, 0xbd, 0xae, 0xf8, 0x4a, 0x68, 0x6a, 0x90, 0x53, 0xea, 0x0e, 0xcf, + 0x19, 0xf5, 0xd9, 0xf6, 0x92, 0x73, 0x35, 0x92, 0xe6, 0xfc, 0x34, 0x2b, + 0xc9, 0x81, 0x81, 0xeb, 0xe9, 0x98, 0x16, 0x05, 0x9a, 0x8e, 0x4a, 0xb4, + 0xaf, 0xa4, 0x59, 0x28, 0x98, 0xad, 0xba, 0x59, 0xdc, 0xf3, 0x9c, 0xc3, + 0x42, 0xe1, 0x64, 0x0e, 0x9b, 0x1f, 0xb9, 0x2e, 0x3f, 0xd3, 0x5f, 0x0c, + 0x9a, 0x9e, 0xc3, 0x58, 0x7d, 0x4e, 0x68, 0x25, 0x1a, 0x38, 0xe3, 0xaf, + 0x36, 0x3b, 0xf4, 0x0d, 0x2e, 0xf1, 0xa3, 0x62, 0x86, 0xb6, 0x50, 0x57, + 0x9c, 0xb3, 0x19, 0x25, 0x37, 0x48, 0x71, 0x02, 0x5c, 0x09, 0x74, 0xcb, + 0x3b, 0x4a, 0x1e, 0x59, 0x89, 0x73, 0x6c, 0xf9, 0x58, 0x02, 0xe0, 0xd7, + 0xbe, 0x4e, 0xe3, 0x54, 0x41, 0x84, 0x89, 0x74, 0x69, 0xf2, 0x76, 0x25, + 0x3c, 0x27, 0xe3, 0x6c, 0x66, 0x27, 0xe9, 0xb8, 0xf7, 0x00, 0x60, 0xe5, + 0xf8, 0x65, 0x9c, 0x52, 0xda, 0x60, 0x6c, 0x54, 0x9b, 0x93, 0xd6, 0xbb, + 0x0b, 0xf5, 0x55, 0x4f, 0x10, 0x36, 0x9c, 0x0d, 0x22, 0x1d, 0x57, 0x68, + 0x00, 0xd6, 0xb1, 0x50, 0xe6, 0x75, 0xea, 0xc4, 0x17, 0x90, 0xce, 0x42, + 0x60, 0x64, 0x52, 0x98, 0x12, 0x21, 0xf2, 0x70, 0x91, 0x31, 0x8f, 0x09, + 0x31, 0x46, 0xba, 0x21, 0xca, 0xf6, 0x10, 0xe0, 0xd1, 0xa1, 0x9b, 0x1d, + 0x39, 0x1b, 0x19, 0x57, 0xe1, 0xd0, 0xb1, 0xfb, 0x66, 0x89, 0x75, 0xc8, + 0xff, 0x1b, 0xb9, 0xd3, 0x28, 0x1f, 0x17, 0x8b, 0xdd, 0x99, 0xe3, 0x1d, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xbe, 0x7c, 0xeb, 0xfa, + 0x83, 0x38, 0x5a, 0x54, 0x3f, 0x7f, 0x79, 0xf1, 0xb8, 0x2a, 0x45, 0xbe, + 0xd0, 0x34, 0x5d, 0xb3, 0xbf, 0x11, 0x88, 0x81, 0xba, 0x24, 0x3f, 0xd1, + 0xaa, 0x96, 0xbb, 0x22, 0x41, 0x64, 0x4e, 0xc5, 0x33, 0x4c, 0x19, 0x85, + 0xa3, 0x66, 0x29, 0x7b, 0x49, 0x9f, 0x2f, 0x59, 0x6a, 0x8e, 0x96, 0xbe, + 0xcc, 0x3a, 0x74, 0x71, 0x66, 0xa8, 0x89, 0xd8, 0x1e, 0x9b, 0x14, 0x2d, + 0x72, 0x90, 0xc9, 0x21, 0xf9, 0x46, 0x99, 0xd3, 0xfb, 0x62, 0x45, 0x2f, + 0x21, 0x03, 0xa3, 0x6b, 0xda, 0x7e, 0xcc, 0x9d, 0x5d, 0x8a, 0xfc, 0x61, + 0x78, 0x20, 0x4b, 0x64, 0x40, 0xf6, 0x1c, 0x29, 0x73, 0x42, 0x22, 0xaf, + 0x26, 0x5d, 0x51, 0x2b, 0x47, 0xe9, 0x07, 0xc0, 0x36, 0x69, 0x92, 0xcd, + 0xc4, 0x6d, 0xc0, 0xea, 0xc1, 0xf1, 0x62, 0xf3, 0x71, 0xa5, 0xad, 0x4d, + 0x01, 0x3c, 0x6c, 0x2a, 0x10, 0xc2, 0x68, 0x8c, 0xa5, 0x4e, 0xe9, 0x31, + 0x7d, 0xe1, 0xa9, 0xe2, 0xc2, 0xbc, 0xb2, 0xcb, 0x10, 0xa8, 0x85, 0x96, + 0x16, 0xc0, 0x50, 0xab, 0x7f, 0xa0, 0x31, 0x26, 0x24, 0x69, 0x73, 0x28, + 0x4f, 0x53, 0xdf, 0x53, 0xc0, 0x40, 0x31, 0xb5, 0x17, 0x1d, 0x22, 0x7a, + 0x9f, 0x52, 0xad, 0xc9, 0xd8, 0x9c, 0x72, 0x6c, 0xce, 0xc2, 0x88, 0x84, + 0xe7, 0x62, 0x74, 0x44, 0x33, 0x92, 0xcb, 0x10, 0xdb, 0xcc, 0x08, 0x2c, + 0x4f, 0x02, 0x4d, 0x44, 0xe3, 0x2c, 0xf5, 0x85, 0xd2, 0x2c, 0x5d, 0x27, + 0xc3, 0x00, 0xcd, 0x98, 0xfd, 0x9f, 0x85, 0xfd, 0x62, 0x62, 0xfc, 0xe0, + 0x2b, 0x98, 0xcb, 0x0d, 0x9a, 0x89, 0x6d, 0x60, 0x15, 0xa7, 0x6d, 0x33, + 0xbf, 0x5c, 0x7a, 0x88, 0x85, 0x66, 0x98, 0x1a, 0xeb, 0xf6, 0x54, 0x9e, + 0x66, 0x32, 0x3c, 0x7d, 0x63, 0x33, 0x14, 0xb8, 0x05, 0xca, 0xc4, 0x0f, + 0x3d, 0x51, 0x43, 0x95, 0xa1, 0x35, 0x52, 0x13, 0xad, 0x39, 0x52, 0x6b, + 0x4a, 0x12, 0x1e, 0x0f, 0x58, 0x9e, 0x61, 0xde, 0x4a, 0xf3, 0x3f, 0x00, + 0x69, 0x6c, 0xc2, 0xed, 0x2d, 0x37, 0x8a, 0x02, 0x4b, 0x78, 0xd9, 0x12, + 0x6c, 0xb4, 0xd3, 0x53, 0xb7, 0x5d, 0xb8, 0xbe, 0xf0, 0x9f, 0x44, 0x0c, + 0x40, 0x3c, 0x16, 0x00, 0xd0, 0x9f, 0xa8, 0x0c, 0x80, 0x40, 0x76, 0x1a, + 0xd2, 0xf6, 0x03, 0x11, 0x60, 0xe1, 0x8b, 0x8e, 0x17, 0xd5, 0x49, 0xb7, + 0xcb, 0x63, 0x4d, 0x0a, 0x3c, 0x72, 0x08, 0xbc, 0xad, 0x3d, 0xc6, 0xc6, + 0xef, 0x7e, 0xb4, 0x0a, 0x3f, 0x08, 0x78, 0x21, 0xdf, 0x72, 0xc6, 0x25, + 0x69, 0xc2, 0x9a, 0x16, 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, + 0xd4, 0xc4, 0x63, 0x29, 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, + 0x75, 0x6c, 0x06, 0x46, 0x1b, 0x5c, 0xab, 0x2c, 0x3d, 0xea, 0x0b, 0xcb, + 0xc7, 0xd0, 0xc8, 0x3a, 0x66, 0xdc, 0x6e, 0xc0, 0xb6, 0xf1, 0xb3, 0x59, + 0x7d, 0x7d, 0x32, 0x18, 0xc1, 0x37, 0xd2, 0x60, 0x0b, 0x0c, 0x65, 0x4b, + 0x35, 0xff, 0x22, 0x0f, 0x49, 0x06, 0x69, 0xb4, 0xd5, 0x81, 0x2d, 0xf1, + 0xd3, 0xe5, 0x4c, 0x80, 0xd5, 0x87, 0x6b, 0x3d, 0x7a, 0x92, 0x3c, 0x48, + 0x44, 0x09, 0xf6, 0x12, 0x8c, 0x2f, 0x6f, 0x23, 0xa3, 0xad, 0xde, 0x19, + 0x7b, 0x76, 0xfd, 0x85, 0x58, 0x8c, 0xf4, 0x2f, 0xa0, 0x5e, 0x23, 0xce, + 0x64, 0xbb, 0x18, 0x4c, 0xbf, 0x1a, 0x14, 0x94, 0x0d, 0x0d, 0x22, 0x85, + 0x9f, 0xdb, 0xb3, 0x78, 0x4c, 0x8d, 0xe5, 0x0e, 0x1a, 0x8e, 0x52, 0x55, + 0x7f, 0xc7, 0xa4, 0xbd, 0xfa, 0xeb, 0x6e, 0x0f, 0xf3, 0x4d, 0x3f, 0xb4, + 0xa1, 0x5f, 0x99, 0x35, 0xc5, 0x19, 0x28, 0xc8, 0x1b, 0xf1, 0x11, 0x3c, + 0x9f, 0xc0, 0xbd, 0x14, 0x6f, 0x8b, 0x8c, 0x09, 0xda, 0xf1, 0x15, 0xc3, + 0x81, 0xc7, 0x85, 0xb3, 0xbe, 0xfc, 0xd6, 0x0c, 0x9c, 0xc3, 0x28, 0x68, + 0x3e, 0x1d, 0x03, 0xff, 0xbd, 0xaf, 0x05, 0xad, 0x27, 0xea, 0x78, 0x0d, + 0x83, 0x50, 0x79, 0xd7, 0x34, 0x31, 0x89, 0xb4, 0x0d, 0x26, 0x4f, 0xce, + 0x68, 0xbe, 0x42, 0x55, 0xf8, 0x95, 0x75, 0x55, 0x3f, 0xfd, 0xfb, 0x72, + 0x4c, 0xf3, 0x6a, 0x2e, 0xec, 0x1f, 0xb9, 0x1c, 0x54, 0x3e, 0x31, 0x3d, + 0x04, 0xa1, 0xef, 0x0b, 0x51, 0x3c, 0x42, 0x7e, 0x5d, 0xba, 0x04, 0xbd, + 0xf0, 0x9e, 0xa6, 0x05, 0x65, 0x75, 0x36, 0x1a, 0xcf, 0x8d, 0x24, 0x00, + 0xd5, 0x5e, 0x13, 0x00, 0x4a, 0x84, 0x05, 0x73, 0xaf, 0x19, 0xb1, 0x84, + 0xed, 0xa1, 0x36, 0x4e, 0x34, 0x36, 0x33, 0x1d, 0x0f, 0x45, 0x95, 0xd5, + 0xfe, 0xeb, 0x1b, 0xf5, 0xbe, 0x56, 0xef, 0x6a, 0x7f, 0xc3, 0xb1, 0x03, + 0x36, 0x74, 0x9d, 0xc7, 0xa6, 0x35, 0x11, 0xa8, 0xdb, 0x0f, 0x67, 0x58, + 0x7c, 0x69, 0xf5, 0xf9, 0xf2, 0x16, 0x4b, 0x5d, 0xd1, 0xa7, 0x58, 0xfa, + 0xb9, 0x99, 0x92, 0x4d, 0x94, 0x49, 0x46, 0x27, 0x70, 0xeb, 0xb3, 0xd6, + 0xda, 0x1f, 0xf6, 0x7e, 0x01, 0x43, 0xbd, 0xf6, 0x95, 0x36, 0xc4, 0xb5, + 0xd8, 0x86, 0x06, 0x2d, 0x29, 0xc6, 0xb5, 0xed, 0x77, 0xb3, 0x90, 0x12, + 0xb9, 0x28, 0x87, 0x0c, 0x54, 0x34, 0x5d, 0x7f, 0x3a, 0xbf, 0xd9, 0xc3, + 0xde, 0x30, 0x53, 0x42, 0x12, 0x6e, 0x4c, 0x68, 0xf3, 0xeb, 0x8a, 0x2f, + 0x34, 0x36, 0x0a, 0xa1, 0xb0, 0xb7, 0xcb, 0xe3, 0x9e, 0x08, 0xd5, 0x2d, + 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, 0x6e, 0xb1, 0xeb, 0x88, + 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, 0x7d, 0xa4, 0x63, 0x35, + 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, 0x49, 0x06, 0x69, 0xb4, + 0xd5, 0x81, 0x2d, 0xf1, 0xd3, 0xe5, 0x4c, 0x80, 0xd5, 0x87, 0x6b, 0x3d, + 0x7a, 0x92, 0x3c, 0x48, 0x44, 0x09, 0xf6, 0x12, 0x8c, 0x2f, 0x6f, 0x23, + 0xa3, 0xad, 0xde, 0x19, 0xf4, 0x82, 0x98, 0x2b, 0xe1, 0x35, 0x13, 0xb2, + 0x0f, 0x2e, 0x17, 0x55, 0xe0, 0x9a, 0x85, 0x03, 0x17, 0xe8, 0xb1, 0x09, + 0xff, 0xef, 0x0c, 0xde, 0x9b, 0xa2, 0x4d, 0xaa, 0x8c, 0xda, 0x44, 0x1d, + 0xba, 0x26, 0x28, 0xaf, 0xbc, 0xe2, 0xd5, 0xd1, 0x61, 0x19, 0xdb, 0x89, + 0x78, 0x0e, 0xe8, 0x3a, 0x84, 0x36, 0xa9, 0x07, 0xa8, 0xa4, 0x35, 0x22, + 0xf2, 0x44, 0xb1, 0xe2, 0x6a, 0x02, 0x01, 0x1d, 0x54, 0x1d, 0x25, 0x36, + 0x12, 0x2b, 0x1a, 0x6e, 0x43, 0x8b, 0x51, 0xdc, 0x85, 0x0e, 0x19, 0xb1, + 0xdc, 0x40, 0xdf, 0xdf, 0x5b, 0x29, 0xac, 0x46, 0x39, 0x20, 0x3f, 0x0e, + 0xed, 0xcb, 0xe3, 0x12, 0x75, 0xf5, 0xd1, 0xe4, 0x35, 0xd2, 0x5b, 0x28, + 0x1c, 0x56, 0xc0, 0x4a, 0xc2, 0x2c, 0xd3, 0x40, 0x26, 0xc5, 0xe9, 0x46, + 0xd7, 0x70, 0x7c, 0xe5, 0xf6, 0xf4, 0xea, 0xb6, 0x30, 0x40, 0x2c, 0x22, + 0x63, 0x4b, 0x28, 0x5f, 0xf3, 0x27, 0xc1, 0xfc, 0x64, 0x5a, 0xe8, 0xaf, + 0xc0, 0x15, 0xe9, 0x53, 0x5f, 0x83, 0x32, 0x3e, 0x4b, 0xa6, 0x3c, 0xfb, + 0x97, 0x69, 0x94, 0x83, 0x0d, 0x34, 0x0e, 0x01, 0x13, 0x46, 0x2e, 0x81, + 0x23, 0xc8, 0xf7, 0x26, 0x44, 0xfd, 0x30, 0xc6, 0xc9, 0xb4, 0xbc, 0x0d, + 0x4b, 0x2c, 0x7c, 0x85, 0x9e, 0xf3, 0x22, 0x45, 0xf1, 0xe8, 0x81, 0xdd, + 0x9f, 0x94, 0xd3, 0x14, 0x94, 0xa1, 0x7b, 0xdf, 0xd0, 0x1d, 0xb4, 0xdb, + 0xb6, 0xcf, 0xb1, 0x2b, 0xab, 0x97, 0xff, 0x8f, 0xab, 0x39, 0x36, 0xf6, + 0xe3, 0x3e, 0x25, 0x58, 0x20, 0x15, 0xd8, 0x38, 0x64, 0x10, 0x06, 0x2e, + 0xb4, 0x09, 0x10, 0xce, 0x9f, 0x8a, 0xa7, 0x5a, 0x07, 0x25, 0x5d, 0x66, + 0xdf, 0x33, 0x29, 0xd7, 0xeb, 0xd0, 0xaa, 0xf3, 0xcc, 0x9d, 0x52, 0xf8, + 0x6a, 0x48, 0xca, 0x8a, 0xf1, 0x1a, 0x61, 0x14, 0xf1, 0x80, 0x58, 0xb0, + 0x66, 0xaa, 0x02, 0x79, 0x7a, 0xd3, 0xf0, 0x88, 0x15, 0x02, 0x4f, 0x98, + 0xca, 0x45, 0x41, 0x04, 0xa0, 0xf8, 0x93, 0x38, 0xd7, 0xb3, 0x8c, 0x8b, + 0x6b, 0xae, 0x84, 0x1f, 0x01, 0xa0, 0x00, 0xb2, 0xf2, 0x0f, 0x31, 0x72, + 0x62, 0x0f, 0x03, 0x59, 0x8d, 0x90, 0x56, 0xef, 0x53, 0xb4, 0x61, 0x81, + 0x15, 0x76, 0xd1, 0xb3, 0xcf, 0xa7, 0xba, 0x21, 0xfa, 0x6a, 0x43, 0x2f, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x7b, 0x76, 0xfd, 0x85, + 0x58, 0x8c, 0xf4, 0x2f, 0xa0, 0x5e, 0x23, 0xce, 0x64, 0xbb, 0x18, 0x4c, + 0xbf, 0x1a, 0x14, 0x94, 0x0d, 0x0d, 0x22, 0x85, 0x9f, 0xdb, 0xb3, 0x78, + 0x4c, 0x8d, 0xe5, 0x0e, 0xba, 0x26, 0x28, 0xaf, 0xbc, 0xe2, 0xd5, 0xd1, + 0x61, 0x19, 0xdb, 0x89, 0x78, 0x0e, 0xe8, 0x3a, 0x84, 0x36, 0xa9, 0x07, + 0xa8, 0xa4, 0x35, 0x22, 0xf2, 0x44, 0xb1, 0xe2, 0x6a, 0x02, 0x01, 0x1d, + 0xcc, 0xc3, 0xa1, 0x0e, 0x57, 0x96, 0xcc, 0x37, 0x00, 0x76, 0x0d, 0x71, + 0x2d, 0xaf, 0xa2, 0xc2, 0x3e, 0x2e, 0x5f, 0xf7, 0x94, 0x65, 0x9b, 0x11, + 0xcc, 0xc9, 0x45, 0x9d, 0x44, 0xe5, 0xb1, 0x20, 0xa9, 0x13, 0xc5, 0x73, + 0x54, 0x59, 0xe5, 0x28, 0xfa, 0x7e, 0xea, 0xb5, 0x74, 0xfd, 0x2d, 0x0b, + 0xd0, 0x17, 0xc3, 0x68, 0xfd, 0x14, 0xd8, 0x02, 0x24, 0xef, 0x86, 0xb5, + 0xf8, 0xe0, 0xc3, 0x16, 0x67, 0x9a, 0x30, 0xb5, 0x75, 0x40, 0x12, 0x6c, + 0x29, 0x13, 0x9d, 0x7e, 0xcc, 0x5b, 0x5b, 0xce, 0xfc, 0x99, 0xe8, 0x57, + 0x1b, 0x11, 0xc3, 0x30, 0xfd, 0xda, 0x85, 0x16, 0x2f, 0x95, 0x22, 0x11, + 0x21, 0x3a, 0x73, 0x21, 0xe4, 0xcc, 0x07, 0x8c, 0x94, 0xa1, 0x12, 0x85, + 0x55, 0x77, 0x22, 0x92, 0x93, 0x6a, 0x90, 0x35, 0x2d, 0x8e, 0xd1, 0x1b, + 0x84, 0x6a, 0x82, 0xa9, 0x97, 0x0c, 0x97, 0x15, 0xf1, 0x92, 0x97, 0x65, + 0xa0, 0x66, 0x16, 0x79, 0x9f, 0x97, 0x98, 0x28, 0x9f, 0x60, 0x0a, 0x4b, + 0x26, 0x5b, 0x9f, 0x2a, 0x65, 0xb3, 0xbb, 0xb6, 0xb4, 0xd0, 0xbb, 0x9d, + 0x03, 0x53, 0xa5, 0x0c, 0x7c, 0x0d, 0xcd, 0xda, 0x64, 0x8f, 0x66, 0xec, + 0x28, 0x7c, 0xdf, 0x4f, 0x1a, 0xb6, 0x1a, 0x41, 0x9f, 0xc7, 0x02, 0xc5, + 0xe6, 0x67, 0xbd, 0xdc, 0x5e, 0x5e, 0xb8, 0xea, 0xf6, 0xba, 0xf9, 0x16, + 0x8f, 0x80, 0x21, 0x41, 0x63, 0xaa, 0x53, 0xef, 0xfe, 0xa2, 0xc6, 0x84, + 0x19, 0x7f, 0xff, 0xc6, 0x8b, 0x2b, 0x1e, 0x6c, 0x38, 0x04, 0xe4, 0x13, + 0xd9, 0xe9, 0xae, 0x56, 0x9f, 0x22, 0xf9, 0x1a, 0xb2, 0x63, 0x74, 0xe9, + 0x50, 0xac, 0xbf, 0xd4, 0xe5, 0x70, 0x57, 0x7c, 0xd9, 0xcb, 0xd4, 0x0e, + 0xc1, 0xa5, 0xe9, 0xa1, 0x9d, 0x0c, 0xd6, 0x28, 0x01, 0x8a, 0x3b, 0xbd, + 0xf6, 0xd2, 0x79, 0x0e, 0x71, 0x82, 0xe6, 0x66, 0x15, 0x3b, 0x39, 0x87, + 0xc2, 0x0c, 0xe7, 0xe8, 0x68, 0xa8, 0x28, 0xb3, 0xf2, 0x35, 0xcc, 0x65, + 0x7c, 0x22, 0x85, 0xb8, 0x77, 0x56, 0x31, 0x07, 0x5b, 0x40, 0x36, 0x03, + 0x78, 0x4e, 0xc6, 0xd9, 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, + 0xf1, 0xcb, 0x38, 0xa5, 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, + 0x17, 0xea, 0xab, 0x9e, 0x20, 0x6c, 0x38, 0x1b, 0x1a, 0x8e, 0x52, 0x55, + 0x7f, 0xc7, 0xa4, 0xbd, 0xfa, 0xeb, 0x6e, 0x0f, 0xf3, 0x4d, 0x3f, 0xb4, + 0xa1, 0x5f, 0x99, 0x35, 0xc5, 0x19, 0x28, 0xc8, 0x1b, 0xf1, 0x11, 0x3c, + 0x9f, 0xc0, 0xbd, 0x14, 0x54, 0x1d, 0x25, 0x36, 0x12, 0x2b, 0x1a, 0x6e, + 0x43, 0x8b, 0x51, 0xdc, 0x85, 0x0e, 0x19, 0xb1, 0xdc, 0x40, 0xdf, 0xdf, + 0x5b, 0x29, 0xac, 0x46, 0x39, 0x20, 0x3f, 0x0e, 0xed, 0xcb, 0xe3, 0x12, + 0xa9, 0x13, 0xc5, 0x73, 0x54, 0x59, 0xe5, 0x28, 0xfa, 0x7e, 0xea, 0xb5, + 0x74, 0xfd, 0x2d, 0x0b, 0xd0, 0x17, 0xc3, 0x68, 0xfd, 0x14, 0xd8, 0x02, + 0x24, 0xef, 0x86, 0xb5, 0xf8, 0xe0, 0xc3, 0x16, 0x22, 0x52, 0x35, 0xfa, + 0xe8, 0xcb, 0x60, 0xa7, 0xbf, 0x06, 0xbd, 0xda, 0x5a, 0xe6, 0x1d, 0xbf, + 0xeb, 0xb3, 0x35, 0x68, 0xf5, 0xf8, 0x2b, 0x83, 0xe3, 0xcd, 0x91, 0x5d, + 0xfd, 0xba, 0xb5, 0x02, 0x81, 0x3e, 0x9a, 0xe8, 0xf1, 0x1b, 0x47, 0x97, + 0xf8, 0xd6, 0xcb, 0x41, 0xa0, 0xb3, 0x50, 0xc7, 0xc4, 0x0f, 0x1c, 0x61, + 0x36, 0x44, 0x38, 0x1c, 0x5a, 0xb9, 0xd4, 0x6b, 0x2d, 0xd6, 0x2f, 0x1e, + 0x19, 0x6a, 0xb1, 0xbc, 0xd6, 0xa7, 0x72, 0xa6, 0x77, 0x54, 0xa5, 0x51, + 0xed, 0x18, 0xb7, 0xfe, 0x88, 0x9e, 0xcb, 0x29, 0x97, 0x31, 0x0b, 0x52, + 0x04, 0x11, 0x29, 0x51, 0x30, 0x55, 0x3a, 0x15, 0x86, 0x49, 0x55, 0xa3, + 0x04, 0x09, 0x53, 0x4b, 0xe3, 0xf2, 0xdd, 0xdb, 0x89, 0x91, 0x02, 0x8d, + 0x8c, 0xd3, 0xf2, 0xfd, 0xda, 0x67, 0x64, 0x96, 0xa6, 0x64, 0x6e, 0x3d, + 0x86, 0x2f, 0xaf, 0x19, 0x16, 0xf6, 0xff, 0x25, 0x35, 0x37, 0x92, 0x94, + 0x1d, 0x94, 0x15, 0x3a, 0x81, 0x66, 0x54, 0x28, 0x65, 0x7f, 0x99, 0x02, + 0x5d, 0xe1, 0xfa, 0xb7, 0x68, 0x2a, 0xf1, 0xe1, 0xa6, 0xcc, 0x71, 0x0d, + 0xc3, 0xd7, 0x9d, 0xe2, 0x21, 0xc3, 0xd2, 0x65, 0x03, 0x71, 0xd3, 0xd8, + 0x9c, 0x47, 0x0c, 0x8e, 0x23, 0x3b, 0xea, 0xd7, 0xbb, 0x07, 0xe7, 0xc9, + 0x00, 0x50, 0x20, 0x6a, 0xef, 0xfb, 0x65, 0x0a, 0xec, 0x40, 0x6e, 0x96, + 0x0f, 0x86, 0x44, 0x92, 0x90, 0x8a, 0x9d, 0x20, 0xfb, 0x86, 0x52, 0xe6, + 0x8c, 0x07, 0xa4, 0xc9, 0xbf, 0xc0, 0xc2, 0xf7, 0x49, 0x0d, 0x9e, 0x43, + 0x6a, 0xa8, 0x34, 0x2c, 0x32, 0xd6, 0xcd, 0x68, 0x61, 0x7a, 0x9b, 0x81, + 0xbc, 0xad, 0x6b, 0xb7, 0x0d, 0xbe, 0xbe, 0x44, 0x1e, 0x3f, 0xae, 0xec, + 0xa4, 0x1e, 0x8e, 0xb5, 0xe6, 0x64, 0xb2, 0x34, 0xf2, 0xc2, 0xd2, 0x18, + 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, 0xe4, 0x6b, 0xc0, 0x45, + 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, 0x49, 0xf2, 0x21, 0xef, + 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, 0x6f, 0x8b, 0x8c, 0x09, + 0xda, 0xf1, 0x15, 0xc3, 0x81, 0xc7, 0x85, 0xb3, 0xbe, 0xfc, 0xd6, 0x0c, + 0x9c, 0xc3, 0x28, 0x68, 0x3e, 0x1d, 0x03, 0xff, 0xbd, 0xaf, 0x05, 0xad, + 0x27, 0xea, 0x78, 0x0d, 0x75, 0xf5, 0xd1, 0xe4, 0x35, 0xd2, 0x5b, 0x28, + 0x1c, 0x56, 0xc0, 0x4a, 0xc2, 0x2c, 0xd3, 0x40, 0x26, 0xc5, 0xe9, 0x46, + 0xd7, 0x70, 0x7c, 0xe5, 0xf6, 0xf4, 0xea, 0xb6, 0x30, 0x40, 0x2c, 0x22, + 0x67, 0x9a, 0x30, 0xb5, 0x75, 0x40, 0x12, 0x6c, 0x29, 0x13, 0x9d, 0x7e, + 0xcc, 0x5b, 0x5b, 0xce, 0xfc, 0x99, 0xe8, 0x57, 0x1b, 0x11, 0xc3, 0x30, + 0xfd, 0xda, 0x85, 0x16, 0x2f, 0x95, 0x22, 0x11, 0x81, 0x3e, 0x9a, 0xe8, + 0xf1, 0x1b, 0x47, 0x97, 0xf8, 0xd6, 0xcb, 0x41, 0xa0, 0xb3, 0x50, 0xc7, + 0xc4, 0x0f, 0x1c, 0x61, 0x36, 0x44, 0x38, 0x1c, 0x5a, 0xb9, 0xd4, 0x6b, + 0x2d, 0xd6, 0x2f, 0x1e, 0xde, 0x70, 0xb8, 0x11, 0xf1, 0x84, 0x44, 0x1d, + 0xd6, 0xd8, 0xaa, 0x4d, 0x9c, 0xb9, 0x51, 0x8c, 0xdf, 0x11, 0x3a, 0x53, + 0x64, 0x4c, 0x7e, 0x64, 0x66, 0x3f, 0xfd, 0x11, 0x44, 0xc9, 0x89, 0x24, + 0x8f, 0xeb, 0xcc, 0x8d, 0x93, 0xdf, 0xed, 0x98, 0xe4, 0xe3, 0xa1, 0xf9, + 0xe3, 0x73, 0x18, 0x9d, 0x18, 0xba, 0xec, 0x3e, 0x40, 0xf6, 0xbe, 0xd7, + 0xb7, 0x44, 0x4a, 0xf7, 0xcd, 0x0f, 0xb6, 0x0d, 0xfb, 0x67, 0x4a, 0xad, + 0xf3, 0x93, 0x27, 0xe3, 0x23, 0x21, 0x00, 0x3b, 0x8b, 0x14, 0xc8, 0xf8, + 0xe3, 0xca, 0xa8, 0x3b, 0xba, 0xd5, 0x35, 0x40, 0x48, 0x24, 0xb9, 0x43, + 0x10, 0x5b, 0x9d, 0x0f, 0xab, 0xc2, 0xce, 0xb4, 0x92, 0x2a, 0x16, 0xee, + 0xea, 0x41, 0xc4, 0x4a, 0xe6, 0xd6, 0x4d, 0x70, 0x27, 0xa5, 0x0e, 0xa4, + 0xa1, 0x06, 0xdb, 0x8b, 0x94, 0x93, 0xe3, 0x00, 0x6c, 0x84, 0xdf, 0x10, + 0x26, 0x80, 0xa3, 0x89, 0x18, 0x54, 0xe6, 0x10, 0xaa, 0x2d, 0xdd, 0x10, + 0xc4, 0x7a, 0x95, 0x42, 0xa2, 0xf7, 0x3a, 0x4a, 0xbf, 0x23, 0xa9, 0xf5, + 0x3a, 0xbe, 0xe6, 0xea, 0x66, 0x25, 0x8d, 0x26, 0xc0, 0x25, 0x66, 0x7b, + 0x2c, 0x1d, 0x14, 0x19, 0x86, 0x05, 0x8d, 0x72, 0xe5, 0xd3, 0xad, 0x5b, + 0x30, 0x57, 0xf9, 0x09, 0x3b, 0xb2, 0x02, 0xf6, 0x5d, 0x6c, 0xa3, 0x35, + 0xd3, 0x1b, 0x56, 0x20, 0xb5, 0x44, 0xe5, 0x70, 0x88, 0x66, 0x1e, 0x13, + 0x42, 0xde, 0xd9, 0x16, 0xe0, 0xe4, 0xb9, 0x97, 0xb4, 0xb4, 0xac, 0x39, + 0x98, 0x4a, 0x94, 0xe9, 0x80, 0x98, 0xe1, 0x5a, 0xbf, 0x54, 0x66, 0x16, + 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, + 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, + 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, 0x83, 0x50, 0x79, 0xd7, + 0x34, 0x31, 0x89, 0xb4, 0x0d, 0x26, 0x4f, 0xce, 0x68, 0xbe, 0x42, 0x55, + 0xf8, 0x95, 0x75, 0x55, 0x3f, 0xfd, 0xfb, 0x72, 0x4c, 0xf3, 0x6a, 0x2e, + 0xec, 0x1f, 0xb9, 0x1c, 0x63, 0x4b, 0x28, 0x5f, 0xf3, 0x27, 0xc1, 0xfc, + 0x64, 0x5a, 0xe8, 0xaf, 0xc0, 0x15, 0xe9, 0x53, 0x5f, 0x83, 0x32, 0x3e, + 0x4b, 0xa6, 0x3c, 0xfb, 0x97, 0x69, 0x94, 0x83, 0x0d, 0x34, 0x0e, 0x01, + 0x21, 0x3a, 0x73, 0x21, 0xe4, 0xcc, 0x07, 0x8c, 0x94, 0xa1, 0x12, 0x85, + 0x55, 0x77, 0x22, 0x92, 0x93, 0x6a, 0x90, 0x35, 0x2d, 0x8e, 0xd1, 0x1b, + 0x84, 0x6a, 0x82, 0xa9, 0x97, 0x0c, 0x97, 0x15, 0x19, 0x6a, 0xb1, 0xbc, + 0xd6, 0xa7, 0x72, 0xa6, 0x77, 0x54, 0xa5, 0x51, 0xed, 0x18, 0xb7, 0xfe, + 0x88, 0x9e, 0xcb, 0x29, 0x97, 0x31, 0x0b, 0x52, 0x04, 0x11, 0x29, 0x51, + 0x30, 0x55, 0x3a, 0x15, 0x8f, 0xeb, 0xcc, 0x8d, 0x93, 0xdf, 0xed, 0x98, + 0xe4, 0xe3, 0xa1, 0xf9, 0xe3, 0x73, 0x18, 0x9d, 0x18, 0xba, 0xec, 0x3e, + 0x40, 0xf6, 0xbe, 0xd7, 0xb7, 0x44, 0x4a, 0xf7, 0xcd, 0x0f, 0xb6, 0x0d, + 0xfd, 0x45, 0x10, 0x19, 0xdc, 0x25, 0xaa, 0x26, 0x81, 0x02, 0x85, 0xb4, + 0x42, 0x26, 0x95, 0x71, 0xc8, 0x05, 0x0a, 0x0c, 0x52, 0x09, 0x2b, 0x97, + 0xb3, 0x0f, 0x29, 0x75, 0x99, 0xcf, 0xc8, 0x2f, 0x82, 0x95, 0xbc, 0xda, + 0x8e, 0xe2, 0x1a, 0x8b, 0xa9, 0x21, 0xb8, 0x11, 0xbf, 0x42, 0x51, 0x0c, + 0xe2, 0x4a, 0x63, 0x57, 0x0b, 0x1e, 0xcb, 0x96, 0xe8, 0x5f, 0x8a, 0x1d, + 0xe5, 0x38, 0xef, 0x26, 0x86, 0x10, 0x57, 0x2b, 0xd7, 0xaa, 0x3a, 0x37, + 0x2c, 0x36, 0xbf, 0x9e, 0x16, 0x5e, 0x45, 0xe5, 0x8d, 0xaa, 0x5e, 0x75, + 0x51, 0x86, 0x1b, 0xef, 0x7a, 0x39, 0xec, 0x10, 0x95, 0x4b, 0xec, 0x1c, + 0xcc, 0x90, 0x14, 0xf4, 0x90, 0xd3, 0xe4, 0x2e, 0x57, 0x03, 0xc3, 0x9c, + 0xbc, 0x38, 0x6c, 0x69, 0xdd, 0xb0, 0x0e, 0xb4, 0x29, 0x3e, 0x08, 0xd9, + 0x31, 0x8c, 0x57, 0x2c, 0x2d, 0xfd, 0x74, 0x13, 0xc7, 0xca, 0x3f, 0x5e, + 0x4c, 0x46, 0xb7, 0x0b, 0xc9, 0x2d, 0xcf, 0xa2, 0x0d, 0xf6, 0x5e, 0x09, + 0x86, 0x1b, 0xa8, 0x10, 0x54, 0x6d, 0x4f, 0x82, 0x90, 0x8b, 0x14, 0xc1, + 0x27, 0xf0, 0xa9, 0x1d, 0xbf, 0x99, 0x97, 0xba, 0xe8, 0xc4, 0x7d, 0x7d, + 0xe8, 0x78, 0xff, 0xaf, 0xb9, 0x48, 0xc7, 0x2c, 0xc3, 0xaa, 0x16, 0x9c, + 0xfc, 0xd9, 0x99, 0xa5, 0x45, 0x5b, 0x27, 0xdb, 0x4a, 0xb5, 0x37, 0x1c, + 0x8c, 0x78, 0xf8, 0x38, 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, + 0xba, 0xbd, 0xc3, 0x5d, 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, + 0x69, 0xa3, 0xe4, 0xf7, 0xa4, 0x14, 0xbc, 0x0c, 0x54, 0x3e, 0x31, 0x3d, + 0x04, 0xa1, 0xef, 0x0b, 0x51, 0x3c, 0x42, 0x7e, 0x5d, 0xba, 0x04, 0xbd, + 0xf0, 0x9e, 0xa6, 0x05, 0x65, 0x75, 0x36, 0x1a, 0xcf, 0x8d, 0x24, 0x00, + 0xd5, 0x5e, 0x13, 0x00, 0x13, 0x46, 0x2e, 0x81, 0x23, 0xc8, 0xf7, 0x26, + 0x44, 0xfd, 0x30, 0xc6, 0xc9, 0xb4, 0xbc, 0x0d, 0x4b, 0x2c, 0x7c, 0x85, + 0x9e, 0xf3, 0x22, 0x45, 0xf1, 0xe8, 0x81, 0xdd, 0x9f, 0x94, 0xd3, 0x14, + 0xf1, 0x92, 0x97, 0x65, 0xa0, 0x66, 0x16, 0x79, 0x9f, 0x97, 0x98, 0x28, + 0x9f, 0x60, 0x0a, 0x4b, 0x26, 0x5b, 0x9f, 0x2a, 0x65, 0xb3, 0xbb, 0xb6, + 0xb4, 0xd0, 0xbb, 0x9d, 0x03, 0x53, 0xa5, 0x0c, 0x86, 0x49, 0x55, 0xa3, + 0x04, 0x09, 0x53, 0x4b, 0xe3, 0xf2, 0xdd, 0xdb, 0x89, 0x91, 0x02, 0x8d, + 0x8c, 0xd3, 0xf2, 0xfd, 0xda, 0x67, 0x64, 0x96, 0xa6, 0x64, 0x6e, 0x3d, + 0x86, 0x2f, 0xaf, 0x19, 0xfb, 0x67, 0x4a, 0xad, 0xf3, 0x93, 0x27, 0xe3, + 0x23, 0x21, 0x00, 0x3b, 0x8b, 0x14, 0xc8, 0xf8, 0xe3, 0xca, 0xa8, 0x3b, + 0xba, 0xd5, 0x35, 0x40, 0x48, 0x24, 0xb9, 0x43, 0x10, 0x5b, 0x9d, 0x0f, + 0x82, 0x95, 0xbc, 0xda, 0x8e, 0xe2, 0x1a, 0x8b, 0xa9, 0x21, 0xb8, 0x11, + 0xbf, 0x42, 0x51, 0x0c, 0xe2, 0x4a, 0x63, 0x57, 0x0b, 0x1e, 0xcb, 0x96, + 0xe8, 0x5f, 0x8a, 0x1d, 0xe5, 0x38, 0xef, 0x26, 0xca, 0xc5, 0x35, 0xde, + 0x3d, 0x9f, 0x94, 0x68, 0x5f, 0xfc, 0xfa, 0xe2, 0xb6, 0x57, 0x84, 0x9f, + 0xf3, 0xb0, 0x00, 0x51, 0x18, 0x1f, 0xc6, 0x92, 0xc7, 0x59, 0xe4, 0xbd, + 0x57, 0x6c, 0x39, 0x1b, 0x62, 0x37, 0xed, 0xcd, 0x4f, 0x86, 0xc4, 0x17, + 0x91, 0x11, 0x19, 0xd8, 0x9e, 0x94, 0xd0, 0x75, 0xb3, 0xa4, 0x90, 0xf8, + 0x08, 0x2b, 0x29, 0x5f, 0xbb, 0xbe, 0xba, 0x4b, 0x16, 0x68, 0xcc, 0x06, + 0xe0, 0x61, 0xc4, 0x38, 0x17, 0x98, 0x68, 0x78, 0x58, 0xc9, 0x11, 0x38, + 0x35, 0xa7, 0xa2, 0x04, 0xcd, 0x03, 0x2d, 0xa0, 0x43, 0x58, 0xe6, 0x60, + 0x90, 0xf1, 0xba, 0xf0, 0x01, 0x60, 0x49, 0x21, 0x5d, 0x9c, 0x3f, 0x63, + 0x2c, 0xd9, 0x68, 0x89, 0xf6, 0xc7, 0x26, 0x29, 0x32, 0x1c, 0xf7, 0x8d, + 0xb1, 0x8d, 0x3a, 0x1a, 0x25, 0x15, 0xe7, 0x15, 0x32, 0xa8, 0x7c, 0xc7, + 0x96, 0x5d, 0x74, 0x01, 0xd3, 0xa6, 0x5c, 0xed, 0x4e, 0x06, 0x2c, 0xf7, + 0xc5, 0x44, 0x62, 0x8c, 0x13, 0x42, 0x4a, 0x89, 0x92, 0xde, 0x78, 0xc7, + 0x69, 0x9c, 0x5a, 0xa4, 0x90, 0xef, 0xe0, 0x82, 0x68, 0x16, 0x91, 0x2f, + 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, 0x75, 0x90, 0xe3, 0x83, + 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, 0xe9, 0xc6, 0xcd, 0xb7, + 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, 0x4a, 0x84, 0x05, 0x73, + 0xaf, 0x19, 0xb1, 0x84, 0xed, 0xa1, 0x36, 0x4e, 0x34, 0x36, 0x33, 0x1d, + 0x0f, 0x45, 0x95, 0xd5, 0xfe, 0xeb, 0x1b, 0xf5, 0xbe, 0x56, 0xef, 0x6a, + 0x7f, 0xc3, 0xb1, 0x03, 0x94, 0xa1, 0x7b, 0xdf, 0xd0, 0x1d, 0xb4, 0xdb, + 0xb6, 0xcf, 0xb1, 0x2b, 0xab, 0x97, 0xff, 0x8f, 0xab, 0x39, 0x36, 0xf6, + 0xe3, 0x3e, 0x25, 0x58, 0x20, 0x15, 0xd8, 0x38, 0x64, 0x10, 0x06, 0x2e, + 0x7c, 0x0d, 0xcd, 0xda, 0x64, 0x8f, 0x66, 0xec, 0x28, 0x7c, 0xdf, 0x4f, + 0x1a, 0xb6, 0x1a, 0x41, 0x9f, 0xc7, 0x02, 0xc5, 0xe6, 0x67, 0xbd, 0xdc, + 0x5e, 0x5e, 0xb8, 0xea, 0xf6, 0xba, 0xf9, 0x16, 0x16, 0xf6, 0xff, 0x25, + 0x35, 0x37, 0x92, 0x94, 0x1d, 0x94, 0x15, 0x3a, 0x81, 0x66, 0x54, 0x28, + 0x65, 0x7f, 0x99, 0x02, 0x5d, 0xe1, 0xfa, 0xb7, 0x68, 0x2a, 0xf1, 0xe1, + 0xa6, 0xcc, 0x71, 0x0d, 0xab, 0xc2, 0xce, 0xb4, 0x92, 0x2a, 0x16, 0xee, + 0xea, 0x41, 0xc4, 0x4a, 0xe6, 0xd6, 0x4d, 0x70, 0x27, 0xa5, 0x0e, 0xa4, + 0xa1, 0x06, 0xdb, 0x8b, 0x94, 0x93, 0xe3, 0x00, 0x6c, 0x84, 0xdf, 0x10, + 0x86, 0x10, 0x57, 0x2b, 0xd7, 0xaa, 0x3a, 0x37, 0x2c, 0x36, 0xbf, 0x9e, + 0x16, 0x5e, 0x45, 0xe5, 0x8d, 0xaa, 0x5e, 0x75, 0x51, 0x86, 0x1b, 0xef, + 0x7a, 0x39, 0xec, 0x10, 0x95, 0x4b, 0xec, 0x1c, 0x62, 0x37, 0xed, 0xcd, + 0x4f, 0x86, 0xc4, 0x17, 0x91, 0x11, 0x19, 0xd8, 0x9e, 0x94, 0xd0, 0x75, + 0xb3, 0xa4, 0x90, 0xf8, 0x08, 0x2b, 0x29, 0x5f, 0xbb, 0xbe, 0xba, 0x4b, + 0x16, 0x68, 0xcc, 0x06, 0xff, 0x59, 0x15, 0x1f, 0x26, 0x3b, 0x3e, 0x81, + 0x48, 0x71, 0x3d, 0xb6, 0x1b, 0x7e, 0x2f, 0x96, 0x9f, 0xf6, 0x85, 0xb1, + 0xab, 0xae, 0x7c, 0xdc, 0x7b, 0xae, 0xc1, 0xb4, 0x5a, 0xd9, 0x4d, 0x20, + 0xe3, 0x8e, 0x5b, 0xf0, 0xd9, 0x76, 0x6c, 0xd1, 0x9c, 0x97, 0x9d, 0xb6, + 0x29, 0xd9, 0x44, 0x44, 0xa4, 0xf3, 0x35, 0x7f, 0x5b, 0x72, 0x09, 0xe6, + 0x49, 0xd4, 0xc1, 0x4b, 0x98, 0x7a, 0x3e, 0x30, 0xdf, 0x1d, 0xb1, 0xd6, + 0x75, 0xa7, 0x55, 0xc6, 0x2b, 0x0e, 0xad, 0x63, 0x38, 0x6e, 0x31, 0xcd, + 0xcc, 0xb0, 0xf7, 0x01, 0x45, 0xe9, 0x70, 0xcb, 0x6b, 0x15, 0x52, 0x4b, + 0xbb, 0xe7, 0x95, 0x26, 0xb8, 0x93, 0x89, 0x45, 0x99, 0xa6, 0xe4, 0xcb, + 0x03, 0xae, 0xd0, 0x9d, 0xe9, 0xd4, 0x71, 0x2d, 0x42, 0x6d, 0x38, 0xed, + 0x01, 0xd2, 0xc8, 0x47, 0xdc, 0x5d, 0x3e, 0xc3, 0xf4, 0xb3, 0x35, 0x11, + 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, + 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, + 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, 0x36, 0x74, 0x9d, 0xc7, + 0xa6, 0x35, 0x11, 0xa8, 0xdb, 0x0f, 0x67, 0x58, 0x7c, 0x69, 0xf5, 0xf9, + 0xf2, 0x16, 0x4b, 0x5d, 0xd1, 0xa7, 0x58, 0xfa, 0xb9, 0x99, 0x92, 0x4d, + 0x94, 0x49, 0x46, 0x27, 0xb4, 0x09, 0x10, 0xce, 0x9f, 0x8a, 0xa7, 0x5a, + 0x07, 0x25, 0x5d, 0x66, 0xdf, 0x33, 0x29, 0xd7, 0xeb, 0xd0, 0xaa, 0xf3, + 0xcc, 0x9d, 0x52, 0xf8, 0x6a, 0x48, 0xca, 0x8a, 0xf1, 0x1a, 0x61, 0x14, + 0x8f, 0x80, 0x21, 0x41, 0x63, 0xaa, 0x53, 0xef, 0xfe, 0xa2, 0xc6, 0x84, + 0x19, 0x7f, 0xff, 0xc6, 0x8b, 0x2b, 0x1e, 0x6c, 0x38, 0x04, 0xe4, 0x13, + 0xd9, 0xe9, 0xae, 0x56, 0x9f, 0x22, 0xf9, 0x1a, 0xc3, 0xd7, 0x9d, 0xe2, + 0x21, 0xc3, 0xd2, 0x65, 0x03, 0x71, 0xd3, 0xd8, 0x9c, 0x47, 0x0c, 0x8e, + 0x23, 0x3b, 0xea, 0xd7, 0xbb, 0x07, 0xe7, 0xc9, 0x00, 0x50, 0x20, 0x6a, + 0xef, 0xfb, 0x65, 0x0a, 0x26, 0x80, 0xa3, 0x89, 0x18, 0x54, 0xe6, 0x10, + 0xaa, 0x2d, 0xdd, 0x10, 0xc4, 0x7a, 0x95, 0x42, 0xa2, 0xf7, 0x3a, 0x4a, + 0xbf, 0x23, 0xa9, 0xf5, 0x3a, 0xbe, 0xe6, 0xea, 0x66, 0x25, 0x8d, 0x26, + 0xcc, 0x90, 0x14, 0xf4, 0x90, 0xd3, 0xe4, 0x2e, 0x57, 0x03, 0xc3, 0x9c, + 0xbc, 0x38, 0x6c, 0x69, 0xdd, 0xb0, 0x0e, 0xb4, 0x29, 0x3e, 0x08, 0xd9, + 0x31, 0x8c, 0x57, 0x2c, 0x2d, 0xfd, 0x74, 0x13, 0xe0, 0x61, 0xc4, 0x38, + 0x17, 0x98, 0x68, 0x78, 0x58, 0xc9, 0x11, 0x38, 0x35, 0xa7, 0xa2, 0x04, + 0xcd, 0x03, 0x2d, 0xa0, 0x43, 0x58, 0xe6, 0x60, 0x90, 0xf1, 0xba, 0xf0, + 0x01, 0x60, 0x49, 0x21, 0xe3, 0x8e, 0x5b, 0xf0, 0xd9, 0x76, 0x6c, 0xd1, + 0x9c, 0x97, 0x9d, 0xb6, 0x29, 0xd9, 0x44, 0x44, 0xa4, 0xf3, 0x35, 0x7f, + 0x5b, 0x72, 0x09, 0xe6, 0x49, 0xd4, 0xc1, 0x4b, 0x98, 0x7a, 0x3e, 0x30, + 0x13, 0x34, 0xcc, 0xd7, 0xac, 0xb2, 0x3b, 0xfe, 0x2b, 0xa9, 0x72, 0xa8, + 0x6f, 0x23, 0x5a, 0xbe, 0x9b, 0xb6, 0x66, 0x44, 0xa6, 0x68, 0xbc, 0xc8, + 0x6e, 0x91, 0xca, 0x06, 0x6f, 0x5b, 0xab, 0x07, 0x15, 0x4e, 0x6a, 0x99, + 0xda, 0x57, 0x2a, 0xb0, 0xc0, 0xdd, 0xf9, 0x8c, 0x42, 0x86, 0xf7, 0xba, + 0x30, 0xdc, 0x29, 0x62, 0x86, 0x66, 0x01, 0x16, 0x26, 0x83, 0xb1, 0x26, + 0xa4, 0x9e, 0x06, 0x11, 0xdc, 0xb4, 0xa0, 0x21, 0x98, 0x8b, 0x60, 0x43, + 0xdb, 0x4e, 0xa2, 0xad, 0xa4, 0x99, 0xc8, 0x58, 0x8b, 0x27, 0x58, 0xbd, + 0xb6, 0xa5, 0x11, 0xeb, 0x09, 0x1b, 0xca, 0x60, 0xd9, 0x7d, 0x50, 0x0a, + 0x6c, 0xae, 0x05, 0xc4, 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, + 0x92, 0x6d, 0xb4, 0xcc, 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, + 0x30, 0x2a, 0x25, 0xad, 0xd6, 0x1a, 0x33, 0x02, 0x70, 0xeb, 0xb3, 0xd6, + 0xda, 0x1f, 0xf6, 0x7e, 0x01, 0x43, 0xbd, 0xf6, 0x95, 0x36, 0xc4, 0xb5, + 0xd8, 0x86, 0x06, 0x2d, 0x29, 0xc6, 0xb5, 0xed, 0x77, 0xb3, 0x90, 0x12, + 0xb9, 0x28, 0x87, 0x0c, 0xf1, 0x80, 0x58, 0xb0, 0x66, 0xaa, 0x02, 0x79, + 0x7a, 0xd3, 0xf0, 0x88, 0x15, 0x02, 0x4f, 0x98, 0xca, 0x45, 0x41, 0x04, + 0xa0, 0xf8, 0x93, 0x38, 0xd7, 0xb3, 0x8c, 0x8b, 0x6b, 0xae, 0x84, 0x1f, + 0xb2, 0x63, 0x74, 0xe9, 0x50, 0xac, 0xbf, 0xd4, 0xe5, 0x70, 0x57, 0x7c, + 0xd9, 0xcb, 0xd4, 0x0e, 0xc1, 0xa5, 0xe9, 0xa1, 0x9d, 0x0c, 0xd6, 0x28, + 0x01, 0x8a, 0x3b, 0xbd, 0xf6, 0xd2, 0x79, 0x0e, 0xec, 0x40, 0x6e, 0x96, + 0x0f, 0x86, 0x44, 0x92, 0x90, 0x8a, 0x9d, 0x20, 0xfb, 0x86, 0x52, 0xe6, + 0x8c, 0x07, 0xa4, 0xc9, 0xbf, 0xc0, 0xc2, 0xf7, 0x49, 0x0d, 0x9e, 0x43, + 0x6a, 0xa8, 0x34, 0x2c, 0xc0, 0x25, 0x66, 0x7b, 0x2c, 0x1d, 0x14, 0x19, + 0x86, 0x05, 0x8d, 0x72, 0xe5, 0xd3, 0xad, 0x5b, 0x30, 0x57, 0xf9, 0x09, + 0x3b, 0xb2, 0x02, 0xf6, 0x5d, 0x6c, 0xa3, 0x35, 0xd3, 0x1b, 0x56, 0x20, + 0xc7, 0xca, 0x3f, 0x5e, 0x4c, 0x46, 0xb7, 0x0b, 0xc9, 0x2d, 0xcf, 0xa2, + 0x0d, 0xf6, 0x5e, 0x09, 0x86, 0x1b, 0xa8, 0x10, 0x54, 0x6d, 0x4f, 0x82, + 0x90, 0x8b, 0x14, 0xc1, 0x27, 0xf0, 0xa9, 0x1d, 0x5d, 0x9c, 0x3f, 0x63, + 0x2c, 0xd9, 0x68, 0x89, 0xf6, 0xc7, 0x26, 0x29, 0x32, 0x1c, 0xf7, 0x8d, + 0xb1, 0x8d, 0x3a, 0x1a, 0x25, 0x15, 0xe7, 0x15, 0x32, 0xa8, 0x7c, 0xc7, + 0x96, 0x5d, 0x74, 0x01, 0xdf, 0x1d, 0xb1, 0xd6, 0x75, 0xa7, 0x55, 0xc6, + 0x2b, 0x0e, 0xad, 0x63, 0x38, 0x6e, 0x31, 0xcd, 0xcc, 0xb0, 0xf7, 0x01, + 0x45, 0xe9, 0x70, 0xcb, 0x6b, 0x15, 0x52, 0x4b, 0xbb, 0xe7, 0x95, 0x26, + 0x15, 0x4e, 0x6a, 0x99, 0xda, 0x57, 0x2a, 0xb0, 0xc0, 0xdd, 0xf9, 0x8c, + 0x42, 0x86, 0xf7, 0xba, 0x30, 0xdc, 0x29, 0x62, 0x86, 0x66, 0x01, 0x16, + 0x26, 0x83, 0xb1, 0x26, 0xa4, 0x9e, 0x06, 0x11, 0xf8, 0xb8, 0x96, 0xd4, + 0x70, 0xb2, 0x3a, 0x23, 0xf5, 0xd6, 0xd0, 0x0a, 0xa1, 0x4c, 0x9e, 0x98, + 0x2a, 0x38, 0xe2, 0xb3, 0xa1, 0x5d, 0x5a, 0x99, 0xbe, 0x85, 0x7a, 0x5a, + 0xb4, 0x2d, 0x71, 0x2a, 0xaa, 0x67, 0x77, 0xe1, 0xc6, 0xce, 0xb7, 0xbe, + 0xe7, 0xaa, 0x0a, 0x68, 0xa8, 0x67, 0xae, 0x5b, 0xe5, 0x89, 0xbb, 0xa1, + 0xf3, 0x01, 0x14, 0x84, 0xd5, 0xf0, 0xd6, 0x3a, 0x81, 0x07, 0x67, 0x29, + 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, 0xdf, 0x27, 0x20, 0x62, + 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, 0x04, 0xad, 0x97, 0x95, + 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04, 0x54, 0x34, 0x5d, 0x7f, + 0x3a, 0xbf, 0xd9, 0xc3, 0xde, 0x30, 0x53, 0x42, 0x12, 0x6e, 0x4c, 0x68, + 0xf3, 0xeb, 0x8a, 0x2f, 0x34, 0x36, 0x0a, 0xa1, 0xb0, 0xb7, 0xcb, 0xe3, + 0x9e, 0x08, 0xd5, 0x2d, 0x01, 0xa0, 0x00, 0xb2, 0xf2, 0x0f, 0x31, 0x72, + 0x62, 0x0f, 0x03, 0x59, 0x8d, 0x90, 0x56, 0xef, 0x53, 0xb4, 0x61, 0x81, + 0x15, 0x76, 0xd1, 0xb3, 0xcf, 0xa7, 0xba, 0x21, 0xfa, 0x6a, 0x43, 0x2f, + 0x71, 0x82, 0xe6, 0x66, 0x15, 0x3b, 0x39, 0x87, 0xc2, 0x0c, 0xe7, 0xe8, + 0x68, 0xa8, 0x28, 0xb3, 0xf2, 0x35, 0xcc, 0x65, 0x7c, 0x22, 0x85, 0xb8, + 0x77, 0x56, 0x31, 0x07, 0x5b, 0x40, 0x36, 0x03, 0x32, 0xd6, 0xcd, 0x68, + 0x61, 0x7a, 0x9b, 0x81, 0xbc, 0xad, 0x6b, 0xb7, 0x0d, 0xbe, 0xbe, 0x44, + 0x1e, 0x3f, 0xae, 0xec, 0xa4, 0x1e, 0x8e, 0xb5, 0xe6, 0x64, 0xb2, 0x34, + 0xf2, 0xc2, 0xd2, 0x18, 0xb5, 0x44, 0xe5, 0x70, 0x88, 0x66, 0x1e, 0x13, + 0x42, 0xde, 0xd9, 0x16, 0xe0, 0xe4, 0xb9, 0x97, 0xb4, 0xb4, 0xac, 0x39, + 0x98, 0x4a, 0x94, 0xe9, 0x80, 0x98, 0xe1, 0x5a, 0xbf, 0x54, 0x66, 0x16, + 0xbf, 0x99, 0x97, 0xba, 0xe8, 0xc4, 0x7d, 0x7d, 0xe8, 0x78, 0xff, 0xaf, + 0xb9, 0x48, 0xc7, 0x2c, 0xc3, 0xaa, 0x16, 0x9c, 0xfc, 0xd9, 0x99, 0xa5, + 0x45, 0x5b, 0x27, 0xdb, 0x4a, 0xb5, 0x37, 0x1c, 0xd3, 0xa6, 0x5c, 0xed, + 0x4e, 0x06, 0x2c, 0xf7, 0xc5, 0x44, 0x62, 0x8c, 0x13, 0x42, 0x4a, 0x89, + 0x92, 0xde, 0x78, 0xc7, 0x69, 0x9c, 0x5a, 0xa4, 0x90, 0xef, 0xe0, 0x82, + 0x68, 0x16, 0x91, 0x2f, 0xb8, 0x93, 0x89, 0x45, 0x99, 0xa6, 0xe4, 0xcb, + 0x03, 0xae, 0xd0, 0x9d, 0xe9, 0xd4, 0x71, 0x2d, 0x42, 0x6d, 0x38, 0xed, + 0x01, 0xd2, 0xc8, 0x47, 0xdc, 0x5d, 0x3e, 0xc3, 0xf4, 0xb3, 0x35, 0x11, + 0xdc, 0xb4, 0xa0, 0x21, 0x98, 0x8b, 0x60, 0x43, 0xdb, 0x4e, 0xa2, 0xad, + 0xa4, 0x99, 0xc8, 0x58, 0x8b, 0x27, 0x58, 0xbd, 0xb6, 0xa5, 0x11, 0xeb, + 0x09, 0x1b, 0xca, 0x60, 0xd9, 0x7d, 0x50, 0x0a, 0xaa, 0x67, 0x77, 0xe1, + 0xc6, 0xce, 0xb7, 0xbe, 0xe7, 0xaa, 0x0a, 0x68, 0xa8, 0x67, 0xae, 0x5b, + 0xe5, 0x89, 0xbb, 0xa1, 0xf3, 0x01, 0x14, 0x84, 0xd5, 0xf0, 0xd6, 0x3a, + 0x81, 0x07, 0x67, 0x29, 0xc2, 0xa3, 0x23, 0x0a, 0x7f, 0x69, 0x74, 0x1b, + 0x2a, 0xed, 0xdb, 0xa7, 0xe2, 0xd4, 0xb2, 0xbb, 0xf7, 0xe4, 0x5b, 0xf3, + 0x17, 0xc9, 0x05, 0x3b, 0xc0, 0xaf, 0x22, 0x8d, 0xc3, 0x75, 0x62, 0x25, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x39, 0x3c, 0xe3, 0xa8, + 0x9c, 0xb1, 0xea, 0x96, 0x8c, 0xe0, 0x38, 0x21, 0xa1, 0xdc, 0x21, 0xda, + 0xea, 0x56, 0x23, 0xf6, 0x36, 0x6a, 0x75, 0x0b, 0x0e, 0xb2, 0x88, 0x03, + 0x83, 0xde, 0xde, 0x2d, 0xa7, 0xac, 0x37, 0x56, 0x4e, 0x3b, 0xa7, 0x94, + 0x78, 0xa6, 0x18, 0x52, 0x4f, 0x11, 0x67, 0x3e, 0xec, 0xd3, 0x5f, 0xbf, + 0x4a, 0x24, 0x86, 0x7e, 0x9a, 0xec, 0x05, 0x50, 0xdc, 0x0d, 0x24, 0x2b, + 0xd7, 0x98, 0xb4, 0x88, 0xc6, 0xab, 0x8a, 0x05, 0x36, 0xdf, 0x33, 0x19, + 0xe0, 0x7a, 0x2e, 0xcd, 0xb8, 0x29, 0xb9, 0x7a, 0x5a, 0xf5, 0x26, 0x61, + 0x55, 0xbc, 0x3b, 0x39, 0xfe, 0x60, 0xaa, 0x06, 0x7f, 0xe0, 0x01, 0x98, + 0x08, 0x53, 0x6e, 0xd0, 0x77, 0x2d, 0x27, 0xc2, 0x5e, 0x55, 0x86, 0x83, + 0xe5, 0x92, 0xb2, 0xcb, 0x6f, 0x5f, 0xf6, 0x8b, 0xb8, 0xf5, 0xba, 0xb5, + 0x81, 0x47, 0x00, 0x0a, 0x1d, 0x73, 0x72, 0x6c, 0x1e, 0xa2, 0x39, 0x8c, + 0x25, 0xe2, 0x2b, 0x46, 0x7b, 0xbb, 0x22, 0x23, 0xfd, 0xe3, 0x85, 0x7d, + 0xe2, 0x4d, 0xa2, 0xfc, 0xab, 0x0e, 0xdc, 0xb2, 0x85, 0xd3, 0x9e, 0x2a, + 0xb3, 0x59, 0x41, 0x71, 0x8d, 0x76, 0x13, 0xf8, 0x02, 0x6e, 0xab, 0x64, + 0x4e, 0x3b, 0x0e, 0x6b, 0x43, 0x43, 0xa7, 0xd4, 0x14, 0x2d, 0x2c, 0xf7, + 0x54, 0xad, 0x85, 0x82, 0x27, 0x18, 0x99, 0x2b, 0x6d, 0xbb, 0x0d, 0xf0, + 0x7e, 0x3b, 0xf1, 0xb4, 0x2b, 0xdc, 0xfb, 0xc9, 0x82, 0x06, 0x33, 0x72, + 0xa4, 0x60, 0x09, 0xc4, 0x72, 0xb4, 0x3e, 0x89, 0xcb, 0x0b, 0x7c, 0x45, + 0x67, 0x6b, 0x5a, 0x20, 0xb6, 0xb6, 0xa7, 0xd5, 0x35, 0x33, 0xb6, 0xdd, + 0x28, 0xf5, 0xab, 0x38, 0xb0, 0x2d, 0xbc, 0xed, 0x97, 0xd4, 0x6e, 0x24, + 0x03, 0xe9, 0x32, 0x65, 0xb1, 0xc7, 0x8a, 0xc2, 0xae, 0xc7, 0x76, 0x25, + 0xbc, 0x24, 0xa0, 0x73, 0xbe, 0xfe, 0xcc, 0x22, 0x05, 0xf4, 0xa5, 0xee, + 0x3e, 0x2a, 0x04, 0x21, 0x00, 0x6c, 0x0f, 0xe5, 0x65, 0xcb, 0x9f, 0x03, + 0xb6, 0x05, 0x9c, 0xd0, 0xde, 0x8f, 0xae, 0x0c, 0xe1, 0x17, 0x91, 0x5f, + 0xd2, 0xb3, 0xd7, 0x34, 0x75, 0x09, 0x7c, 0x26, 0x25, 0x63, 0xf1, 0x1f, + 0x1c, 0x05, 0xf1, 0x40, 0xa0, 0x95, 0xe2, 0xf2, 0xb6, 0x9d, 0xcd, 0x5d, + 0xae, 0xe6, 0x5e, 0x08, 0xfa, 0x9d, 0x7e, 0x11, 0x95, 0x04, 0x67, 0x4a, + 0x0f, 0x38, 0xc7, 0xaf, 0x68, 0x54, 0xb9, 0x8c, 0xb2, 0x09, 0x80, 0x3f, + 0xf3, 0xbb, 0x95, 0x7c, 0xb3, 0x9c, 0x27, 0x50, 0x79, 0x9e, 0xcf, 0x22, + 0xe3, 0xf5, 0x50, 0xab, 0x46, 0x16, 0x3d, 0x89, 0x05, 0xf9, 0xae, 0x77, + 0x54, 0x56, 0xfa, 0x6e, 0x83, 0x29, 0x3a, 0xcc, 0x80, 0x48, 0x1c, 0x83, + 0x20, 0x53, 0x89, 0xc3, 0x6e, 0x89, 0x52, 0x24, 0xc8, 0xe4, 0x27, 0xd7, + 0x59, 0x76, 0x7a, 0x0b, 0x45, 0xe7, 0x21, 0x6b, 0x9c, 0x18, 0x17, 0x30, + 0x77, 0x42, 0xba, 0x3c, 0x06, 0xaa, 0x1d, 0x2b, 0xec, 0x12, 0xe5, 0xae, + 0x79, 0x24, 0xd0, 0x2d, 0x3b, 0x4a, 0x74, 0xcf, 0x7d, 0xef, 0x45, 0x73, + 0x94, 0x55, 0x68, 0xb9, 0x5d, 0x7d, 0x5b, 0x6e, 0xa1, 0x4c, 0x2c, 0x80, + 0xe4, 0x8e, 0x35, 0x75, 0xf0, 0x17, 0xeb, 0x00, 0xd6, 0xb3, 0xcd, 0x05, + 0x3d, 0xff, 0x90, 0x2d, 0xde, 0xfb, 0x02, 0x4c, 0x0c, 0x3f, 0x87, 0xed, + 0x35, 0x64, 0x1b, 0xe0, 0x6a, 0x37, 0x04, 0x99, 0xc9, 0x95, 0xa4, 0x62, + 0x62, 0x56, 0x57, 0x5f, 0xdc, 0xce, 0x2d, 0x0a, 0xeb, 0x05, 0xa1, 0xcd, + 0x79, 0xe2, 0x63, 0x9e, 0x9d, 0x6c, 0xa9, 0x3c, 0x5a, 0x81, 0x6e, 0x5f, + 0xa0, 0x5c, 0x01, 0x71, 0x78, 0x29, 0x31, 0xd2, 0x52, 0x59, 0x21, 0xec, + 0xa6, 0x3f, 0x0a, 0x0a, 0x40, 0x8c, 0x84, 0x4e, 0xc1, 0x5e, 0x4b, 0x5d, + 0x72, 0x66, 0x46, 0xdf, 0xca, 0xd4, 0x2e, 0x13, 0x51, 0xdd, 0x8d, 0x18, + 0xc7, 0x96, 0x3a, 0x13, 0xc4, 0x8a, 0xd2, 0xe3, 0x92, 0x5d, 0x41, 0x1c, + 0x27, 0xb1, 0x4e, 0xf2, 0x5f, 0xff, 0xbb, 0x7d, 0xd2, 0xe1, 0xd8, 0x96, + 0x5d, 0xc2, 0xe1, 0x2f, 0x2f, 0x00, 0x55, 0x71, 0x23, 0x69, 0xb7, 0x14, + 0xa7, 0x98, 0x36, 0x2c, 0x89, 0x54, 0x28, 0x2c, 0x1a, 0xb0, 0x1a, 0xc8, + 0x43, 0x41, 0x06, 0xd9, 0x47, 0xcf, 0x59, 0x6c, 0x3c, 0x2e, 0x84, 0x29, + 0x3f, 0x65, 0xbd, 0x40, 0xa5, 0xa6, 0x5d, 0xc9, 0x57, 0xe3, 0x6d, 0xeb, + 0xb2, 0x22, 0x46, 0x24, 0xe1, 0x53, 0x5d, 0x6c, 0xb6, 0x26, 0x80, 0xcc, + 0xb0, 0xd4, 0x47, 0x03, 0xbf, 0x36, 0x27, 0xb1, 0x5b, 0xd0, 0x4d, 0xba, + 0x53, 0x7b, 0x8e, 0xe5, 0xb5, 0x3a, 0xf8, 0x34, 0xab, 0x12, 0x0f, 0x1c, + 0xf5, 0x1e, 0xf1, 0x1f, 0x24, 0xa1, 0x82, 0xba, 0x68, 0x1d, 0xca, 0x5e, + 0xdc, 0x10, 0xe3, 0xb0, 0x03, 0x51, 0x22, 0x94, 0x3a, 0x8e, 0xc9, 0xac, + 0xb3, 0x57, 0x73, 0xd3, 0x40, 0x4f, 0x22, 0x01, 0xa8, 0xd7, 0xb7, 0x35, + 0x43, 0xbc, 0x96, 0x09, 0x58, 0x9e, 0x8d, 0xb2, 0xd7, 0xe7, 0x74, 0x85, + 0x5d, 0xf6, 0x61, 0xcd, 0x71, 0x21, 0x0a, 0x4f, 0x99, 0xca, 0xf0, 0xea, + 0x29, 0x9a, 0x1f, 0x1b, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x46, 0x0c, 0x55, 0x83, 0xa4, 0xfe, 0xa3, 0x38, 0xdb, 0x82, 0x29, 0x89, + 0x0b, 0x05, 0x6f, 0xa4, 0x11, 0xea, 0x75, 0xec, 0x28, 0x0a, 0xab, 0xdd, + 0x96, 0x50, 0x30, 0xc2, 0xb3, 0xd8, 0xe8, 0x23, 0x14, 0x7a, 0xeb, 0x86, + 0x40, 0xb1, 0xb5, 0x67, 0xf7, 0xd9, 0xb4, 0x2e, 0x49, 0x05, 0x6a, 0x51, + 0x7e, 0x2a, 0xa7, 0x4a, 0x5e, 0x11, 0xee, 0xec, 0x33, 0x92, 0xcc, 0x4d, + 0x6d, 0x09, 0x68, 0x29, 0x8d, 0x8e, 0xc2, 0xbe, 0x82, 0x68, 0x03, 0x9b, + 0xf5, 0xcd, 0xa3, 0xdf, 0xd5, 0xcd, 0x2d, 0x7f, 0x3a, 0xcb, 0x7b, 0xb8, + 0xd3, 0x22, 0xe7, 0x04, 0xff, 0xf4, 0x7d, 0xcb, 0xd9, 0x76, 0x10, 0x16, + 0x62, 0xa3, 0x62, 0x9d, 0x4d, 0x90, 0x93, 0xbd, 0x99, 0x99, 0x43, 0xee, + 0xa1, 0x4a, 0x97, 0x3f, 0xcb, 0xb7, 0xeb, 0x05, 0x11, 0x20, 0x46, 0xfb, + 0x68, 0x54, 0x83, 0x36, 0xe2, 0x8c, 0x52, 0x0f, 0xef, 0x96, 0xdd, 0x81, + 0x17, 0xb5, 0x74, 0x35, 0x13, 0xb7, 0x9c, 0xe6, 0x46, 0x8c, 0x37, 0xbd, + 0x35, 0x17, 0xf4, 0xf1, 0x9f, 0xf3, 0x3b, 0x06, 0x69, 0x18, 0x79, 0x65, + 0x8c, 0x04, 0x5d, 0x08, 0x17, 0x6e, 0xf2, 0xf0, 0xf6, 0x3e, 0x53, 0x5d, + 0xdf, 0x07, 0x77, 0xa9, 0x2e, 0x6f, 0x80, 0x66, 0x6a, 0x4c, 0xbf, 0x60, + 0x8f, 0xe4, 0x12, 0x2f, 0x38, 0x56, 0x21, 0x66, 0x63, 0xd0, 0x68, 0x25, + 0x96, 0x3d, 0x0f, 0x41, 0x57, 0x4e, 0xb7, 0xed, 0xa7, 0x9c, 0xc7, 0x56, + 0xbe, 0x28, 0xa1, 0x8e, 0xf5, 0x01, 0x15, 0x1b, 0xf6, 0x01, 0x98, 0x78, + 0xf8, 0xd9, 0xbc, 0x5c, 0x84, 0x7b, 0x40, 0x14, 0x71, 0x2a, 0xc2, 0x17, + 0x6c, 0x87, 0x1a, 0x8b, 0xa8, 0x6d, 0x61, 0x47, 0x9c, 0x16, 0x6b, 0xb6, + 0x7b, 0x32, 0x7f, 0x97, 0x5b, 0xf8, 0x93, 0x8f, 0x56, 0x03, 0xe3, 0xd9, + 0x59, 0x34, 0xef, 0x0a, 0x46, 0x8f, 0x23, 0xbe, 0x10, 0xb2, 0x41, 0x40, + 0x3a, 0xfc, 0x11, 0xee, 0x0b, 0x47, 0x08, 0x88, 0xde, 0x95, 0xca, 0x6f, + 0xa7, 0x17, 0x36, 0x02, 0xc5, 0xcb, 0x7f, 0x8a, 0x89, 0x1b, 0xec, 0x13, + 0xee, 0x8e, 0xb7, 0xb4, 0x19, 0x14, 0x27, 0xcc, 0x07, 0xa2, 0x03, 0x5e, + 0x7d, 0xe9, 0x35, 0x85, 0x36, 0x67, 0x4a, 0xfb, 0x1b, 0x8b, 0xbd, 0x64, + 0x70, 0xcd, 0x18, 0x05, 0x55, 0x41, 0x24, 0x16, 0x0a, 0xa8, 0x6a, 0xba, + 0x2d, 0x59, 0xbd, 0xe2, 0xcb, 0x4d, 0x0f, 0xcc, 0x90, 0x44, 0x04, 0xec, + 0x1d, 0x19, 0xc5, 0x6c, 0x57, 0x6e, 0x56, 0xb7, 0x70, 0xc1, 0x8a, 0x0f, + 0x1a, 0x77, 0xc5, 0x08, 0x9e, 0x28, 0xac, 0x4b, 0x94, 0x62, 0x51, 0x6a, + 0x56, 0xc0, 0x67, 0x81, 0x94, 0xe2, 0x1d, 0x94, 0x4f, 0xde, 0x91, 0xc2, + 0x83, 0x16, 0xd4, 0xfa, 0x45, 0x0e, 0xdf, 0xef, 0x03, 0x20, 0x48, 0x2b, + 0x8e, 0x48, 0x52, 0x6d, 0xc0, 0xc1, 0x30, 0xcf, 0xe0, 0x3b, 0x76, 0x99, + 0xef, 0x4f, 0x8d, 0x66, 0x18, 0x6f, 0x9e, 0xef, 0x50, 0x09, 0x82, 0x2c, + 0xb5, 0x75, 0x41, 0xad, 0x0b, 0x4e, 0x7a, 0x0b, 0xd5, 0xdb, 0x31, 0x5c, + 0x24, 0x41, 0x19, 0x86, 0x84, 0xb9, 0xc3, 0x33, 0x6c, 0x8f, 0xdf, 0x36, + 0xbf, 0xde, 0x18, 0xd4, 0x90, 0xc2, 0x67, 0x89, 0x90, 0x25, 0x67, 0xd7, + 0xd6, 0xb9, 0xb8, 0x0b, 0xc8, 0xf3, 0x14, 0x7f, 0x43, 0xf2, 0xea, 0x44, + 0x03, 0xba, 0xf6, 0x32, 0xc4, 0x6c, 0x5c, 0xc1, 0xec, 0x2c, 0xdb, 0x96, + 0x8e, 0x6b, 0x45, 0x45, 0xfa, 0x7d, 0xd3, 0x44, 0xbd, 0x09, 0x09, 0x19, + 0x46, 0x27, 0x29, 0x3b, 0x6f, 0x5e, 0x22, 0x20, 0x64, 0x28, 0x2c, 0x44, + 0x13, 0x94, 0x8e, 0x3d, 0xf7, 0x45, 0xcb, 0x79, 0x62, 0x28, 0x0c, 0x9a, + 0x00, 0x66, 0xfe, 0x48, 0xbb, 0xe0, 0x07, 0x07, 0x3a, 0x02, 0x52, 0x87, + 0x0f, 0xc1, 0x55, 0xfb, 0x28, 0x81, 0x99, 0xa6, 0xd6, 0x24, 0x4b, 0x35, + 0x24, 0xc4, 0x1a, 0x66, 0xb3, 0xa6, 0x4c, 0x6d, 0x4e, 0x66, 0xf1, 0x05, + 0x73, 0xa1, 0xb2, 0x22, 0x2a, 0xf2, 0x75, 0x25, 0xf0, 0xab, 0x02, 0xe4, + 0xbd, 0x4b, 0x4c, 0xe1, 0x97, 0x89, 0xfb, 0xa3, 0xc2, 0xb7, 0xac, 0x74, + 0x2a, 0x6c, 0x93, 0x31, 0xbb, 0x9d, 0xf4, 0xdb, 0xb1, 0x70, 0xd3, 0x06, + 0x36, 0x47, 0xb0, 0x8b, 0x43, 0x16, 0x20, 0x49, 0xd6, 0x76, 0x17, 0x60, + 0x60, 0xaa, 0x33, 0x44, 0x48, 0xf5, 0x8c, 0xc3, 0x8a, 0x15, 0x47, 0x1c, + 0x8e, 0xa2, 0x3e, 0x22, 0x3a, 0x52, 0x48, 0x19, 0x99, 0xf3, 0xd9, 0x44, + 0xce, 0xfc, 0xf6, 0x55, 0xd1, 0x36, 0x24, 0xc6, 0xf8, 0x34, 0x8b, 0xba, + 0xc5, 0x3b, 0x54, 0xdd, 0xa6, 0xa4, 0x70, 0x68, 0x6c, 0xd3, 0x6c, 0xed, + 0xcf, 0x7b, 0x4e, 0x1b, 0x81, 0x5a, 0xaf, 0x07, 0x52, 0x3e, 0x60, 0x55, + 0x90, 0x90, 0x88, 0x8c, 0xf6, 0x2e, 0x3f, 0xe5, 0x6d, 0x53, 0xb7, 0x7c, + 0x34, 0xd6, 0xa3, 0x97, 0xa1, 0x04, 0x27, 0x09, 0xd1, 0x92, 0x21, 0x2c, + 0x7b, 0xa6, 0x89, 0x7b, 0x81, 0xe1, 0x1a, 0xc0, 0xbb, 0x1f, 0xe5, 0x39, + 0xab, 0xa2, 0x93, 0x82, 0xd9, 0xd0, 0x1d, 0xe8, 0x99, 0x09, 0x07, 0x69, + 0x2b, 0x9a, 0xf8, 0x61, 0x1b, 0xd0, 0x69, 0x25, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xb6, 0x66, 0x1f, 0x44, 0x4a, 0x90, 0xde, 0x43, + 0x58, 0x9e, 0x3c, 0x01, 0x71, 0xb4, 0xd3, 0x76, 0xe8, 0x7d, 0x15, 0x63, + 0x42, 0x01, 0x93, 0x70, 0x5d, 0x37, 0x10, 0x1e, 0x35, 0x05, 0x08, 0x02, + 0x94, 0x62, 0xaf, 0xad, 0x72, 0xbb, 0xc6, 0xb5, 0x63, 0xe7, 0x61, 0xbc, + 0x4f, 0x98, 0xdd, 0x1d, 0xed, 0xcc, 0xec, 0x1b, 0x4d, 0x15, 0xcb, 0x32, + 0x71, 0x1e, 0x14, 0x6e, 0xa5, 0x61, 0xbf, 0x13, 0x6b, 0x1b, 0xc1, 0xc4, + 0x28, 0x8e, 0x29, 0x96, 0x1a, 0x76, 0x46, 0xdc, 0x26, 0x32, 0x1e, 0xa8, + 0x96, 0x71, 0x9f, 0xc2, 0x18, 0x97, 0xb0, 0x3e, 0xf8, 0xc6, 0xe9, 0x6b, + 0x0b, 0x98, 0x44, 0x1b, 0xfc, 0x79, 0xd6, 0x1d, 0x1f, 0xc4, 0x3c, 0x6e, + 0x2d, 0x0c, 0xa7, 0xc6, 0x7f, 0xe1, 0xe3, 0x5a, 0xf9, 0xa4, 0xc6, 0x03, + 0x02, 0xe4, 0x57, 0x48, 0x62, 0xb5, 0x21, 0x5c, 0x0f, 0xea, 0xdb, 0x0d, + 0x69, 0xf4, 0x76, 0xdf, 0x5e, 0xac, 0x47, 0x45, 0x9e, 0x39, 0xc5, 0x8f, + 0x9f, 0xeb, 0xeb, 0xcd, 0x15, 0xa4, 0x61, 0x6e, 0xd9, 0x29, 0x1f, 0xb8, + 0x2a, 0xe0, 0x13, 0x28, 0x27, 0x4f, 0x79, 0x2a, 0xf7, 0x02, 0xe8, 0xd7, + 0xa3, 0xc3, 0x4e, 0xcc, 0x93, 0x7d, 0x58, 0x84, 0x4c, 0xc0, 0xce, 0x96, + 0xf0, 0xee, 0x82, 0x83, 0x2c, 0x08, 0x46, 0x1a, 0x06, 0x9e, 0x2b, 0x3c, + 0x4c, 0x2a, 0xe6, 0x1e, 0xe9, 0x0d, 0xb7, 0xa2, 0x39, 0xed, 0x0a, 0x09, + 0x96, 0x1a, 0xf1, 0x02, 0x6a, 0x32, 0x81, 0xca, 0x55, 0x0c, 0x08, 0x6f, + 0xaf, 0x2f, 0x72, 0x26, 0x37, 0xea, 0x74, 0x74, 0x45, 0xf7, 0xea, 0x19, + 0xff, 0xb8, 0x97, 0x19, 0x16, 0x25, 0x76, 0x6c, 0xc0, 0x41, 0x08, 0x88, + 0xdf, 0x80, 0xd4, 0x11, 0x58, 0xbe, 0x39, 0x08, 0xf0, 0xbe, 0xde, 0x0c, + 0x71, 0xcf, 0x7c, 0x09, 0x5b, 0xc4, 0x24, 0x18, 0x5d, 0x66, 0xe6, 0x01, + 0xa2, 0x74, 0x92, 0xee, 0xd4, 0x11, 0x51, 0x7c, 0x77, 0x9e, 0x02, 0x6a, + 0x1b, 0x4a, 0x64, 0x49, 0xef, 0xe1, 0x38, 0x25, 0xd4, 0xf0, 0x1d, 0x62, + 0x57, 0xaa, 0xe6, 0x20, 0xdd, 0x1e, 0x92, 0x44, 0x1d, 0x8d, 0xba, 0x1f, + 0x20, 0xe6, 0x95, 0x75, 0x27, 0x76, 0x3f, 0xf7, 0xa3, 0x64, 0x05, 0xce, + 0x4e, 0xd1, 0x9c, 0xf2, 0xd6, 0x04, 0xbf, 0xd3, 0x93, 0xbb, 0x8c, 0x29, + 0x93, 0xd4, 0x33, 0xea, 0x51, 0x6b, 0xec, 0x19, 0x98, 0xec, 0x2e, 0x3c, + 0x7e, 0x22, 0x21, 0xbf, 0x85, 0xc7, 0x0a, 0xe5, 0xb1, 0x10, 0x3d, 0xfb, + 0x0c, 0x71, 0x8e, 0xf7, 0x33, 0x7e, 0x3a, 0x18, 0x66, 0x4d, 0xec, 0x0f, + 0x0c, 0xda, 0xee, 0x1a, 0xe1, 0x0e, 0xd0, 0x6c, 0x50, 0x9b, 0xcc, 0x55, + 0xfb, 0xf5, 0x2c, 0x88, 0xf5, 0xca, 0xa1, 0x65, 0xf8, 0x82, 0xa5, 0x77, + 0x2f, 0x52, 0x65, 0x20, 0x2e, 0x5c, 0x60, 0x0d, 0x41, 0x83, 0xaf, 0xe0, + 0x50, 0xe3, 0xdb, 0x6c, 0x7b, 0xf3, 0xce, 0xdb, 0x4d, 0xa6, 0xf2, 0xd8, + 0x89, 0xc1, 0x1a, 0x42, 0x55, 0xc1, 0xeb, 0x4c, 0xc8, 0xbb, 0xb2, 0x1c, + 0x0f, 0x7d, 0xc7, 0x6d, 0xf4, 0x54, 0x9c, 0x77, 0x97, 0xf5, 0xc7, 0x06, + 0xc0, 0x84, 0xbc, 0x34, 0xaf, 0x74, 0x2b, 0xcc, 0x89, 0xd2, 0x93, 0x32, + 0x2d, 0xd9, 0x21, 0x65, 0x50, 0xed, 0xcc, 0x0a, 0xa7, 0x79, 0xd8, 0xc1, + 0x2c, 0xbd, 0x11, 0xaf, 0x69, 0x05, 0x6d, 0xb2, 0xa0, 0xb0, 0x8d, 0x90, + 0x49, 0xf1, 0xa8, 0xcb, 0x67, 0x3c, 0x57, 0x1b, 0x37, 0x75, 0x31, 0xf6, + 0xd4, 0x6c, 0x81, 0x19, 0xe0, 0xd5, 0x9e, 0x73, 0x71, 0xdb, 0xd3, 0xcc, + 0x35, 0x54, 0x19, 0x93, 0xfc, 0x91, 0x43, 0x4f, 0x74, 0xc4, 0xde, 0x22, + 0x9f, 0xa4, 0x3f, 0x2e, 0x79, 0x47, 0x6d, 0x0c, 0x07, 0xa8, 0x49, 0x24, + 0xfb, 0x37, 0xa1, 0xf7, 0x64, 0xf1, 0x7f, 0x43, 0x25, 0x05, 0xf9, 0xa4, + 0x6f, 0x8f, 0x8b, 0xec, 0x2f, 0x31, 0x57, 0x4a, 0xa3, 0x36, 0xc4, 0xbc, + 0xd5, 0xe1, 0x87, 0xa7, 0x91, 0xad, 0x9e, 0x11, 0x6a, 0xbd, 0x5f, 0x99, + 0x37, 0x06, 0x75, 0x1f, 0x18, 0xeb, 0x30, 0x53, 0xd6, 0x75, 0x6b, 0x80, + 0x88, 0xa8, 0x02, 0xbb, 0x8b, 0xc2, 0xc3, 0x72, 0x2a, 0xc7, 0x0f, 0x30, + 0x7c, 0x06, 0x50, 0x2a, 0x50, 0xea, 0xb8, 0xfa, 0x76, 0xf5, 0xa1, 0xd2, + 0x67, 0xaa, 0xa5, 0xd7, 0xa2, 0xf8, 0x0b, 0x90, 0x11, 0x61, 0x8c, 0x26, + 0xac, 0xe6, 0x25, 0xc6, 0xd3, 0xd4, 0x6f, 0xc0, 0x81, 0x71, 0xca, 0x26, + 0x21, 0xee, 0x59, 0xd6, 0x62, 0x96, 0x4d, 0x89, 0x99, 0x65, 0x3a, 0x4a, + 0xc9, 0x92, 0x67, 0xbf, 0xad, 0x2c, 0xaf, 0xb7, 0x1d, 0x50, 0xbd, 0x58, + 0x10, 0x6a, 0x2b, 0xb5, 0xba, 0xee, 0x43, 0x21, 0xe7, 0xa2, 0x1d, 0xb5, + 0x36, 0xd3, 0x97, 0xbe, 0x94, 0x9d, 0x94, 0x04, 0x96, 0xe8, 0x3b, 0xa3, + 0x3c, 0x85, 0xb9, 0xda, 0x0f, 0xb9, 0x47, 0xe9, 0x10, 0xec, 0x9a, 0x09, + 0x68, 0x54, 0x5d, 0x2d, 0x4b, 0x33, 0xd1, 0xcc, 0x4e, 0x26, 0x17, 0x32, + 0xe4, 0x53, 0xb5, 0x3f, 0x0c, 0x39, 0x67, 0x88, 0x58, 0xd2, 0x35, 0x8b, + 0xbd, 0x7c, 0x82, 0x12, 0x8d, 0x17, 0x3d, 0x91, 0x10, 0xa1, 0x29, 0x00, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x65, 0xd0, 0x9d, 0xf0, + 0xf2, 0x84, 0x68, 0x44, 0x23, 0x41, 0xdc, 0x9d, 0x2c, 0x75, 0x1d, 0xa3, + 0x86, 0xc7, 0x59, 0x07, 0x54, 0x38, 0x82, 0xf5, 0x3d, 0xfe, 0x40, 0x58, + 0x82, 0x20, 0xad, 0x16, 0xfd, 0x5b, 0x08, 0x09, 0xdf, 0x6f, 0xc9, 0xbc, + 0x67, 0x23, 0x5d, 0x29, 0x9f, 0x81, 0x86, 0x6d, 0x02, 0x1a, 0x4b, 0xd3, + 0xc8, 0x2f, 0x6a, 0x6d, 0xb7, 0x43, 0x64, 0x13, 0xb4, 0xfb, 0xd2, 0x2b, + 0x85, 0xcf, 0x14, 0x40, 0x41, 0x3d, 0xe0, 0xa1, 0x16, 0x4a, 0x47, 0x9d, + 0xe7, 0x5c, 0x89, 0x78, 0xe3, 0x7f, 0x6c, 0x4d, 0xe2, 0xc0, 0x52, 0x7c, + 0x38, 0xf4, 0x86, 0xdf, 0x13, 0x8f, 0x27, 0x03, 0x35, 0x69, 0xfa, 0x6e, + 0x48, 0x6d, 0x90, 0x37, 0x8b, 0xfb, 0x36, 0xd1, 0xfc, 0x17, 0x6b, 0xae, + 0x15, 0x5b, 0xfd, 0x8c, 0x6e, 0x19, 0x4c, 0x94, 0x27, 0x02, 0xa2, 0x03, + 0xcd, 0x40, 0x64, 0x0a, 0x3d, 0x4c, 0x1f, 0x30, 0x2f, 0x69, 0x11, 0xfa, + 0x0a, 0xce, 0x5c, 0x90, 0x45, 0x18, 0xf2, 0x91, 0x68, 0x3d, 0xb5, 0x3a, + 0xe3, 0xe3, 0x48, 0x45, 0x3a, 0x23, 0x00, 0x7e, 0x24, 0xaf, 0xd1, 0x28, + 0x5b, 0xb8, 0xe3, 0x07, 0xa2, 0x90, 0xc3, 0x54, 0x02, 0x99, 0x3b, 0x97, + 0xae, 0x6e, 0x1c, 0x15, 0x17, 0x88, 0x55, 0x67, 0x47, 0x0d, 0xba, 0xe9, + 0x09, 0xd7, 0xac, 0x28, 0x96, 0x26, 0x70, 0x28, 0x17, 0xed, 0xec, 0x0f, + 0xb4, 0x9b, 0x92, 0xc8, 0xbe, 0xfa, 0x31, 0x98, 0x6e, 0xe5, 0x19, 0xbb, + 0xd8, 0xa0, 0x1d, 0x8a, 0xca, 0xf1, 0x1f, 0xb0, 0xa9, 0x93, 0xbd, 0x42, + 0x69, 0x81, 0xdd, 0x0a, 0x50, 0xe1, 0x28, 0x3b, 0x3f, 0xc9, 0x92, 0x13, + 0x9f, 0xc6, 0xff, 0x01, 0xc9, 0xb8, 0x2f, 0xa6, 0x96, 0x40, 0x0f, 0x82, + 0xb0, 0x22, 0xc4, 0x73, 0xe4, 0x18, 0xc0, 0x75, 0xe6, 0x9c, 0x3b, 0x10, + 0x5e, 0xd4, 0x41, 0xeb, 0x86, 0x6e, 0xb5, 0xb5, 0x55, 0x54, 0xbc, 0xb3, + 0x83, 0x47, 0x8a, 0x51, 0x47, 0x37, 0x68, 0xc8, 0x50, 0xce, 0x02, 0xeb, + 0x21, 0xd8, 0xa2, 0x86, 0x1d, 0x36, 0x99, 0x10, 0xf7, 0x10, 0x48, 0x84, + 0x48, 0x73, 0xf2, 0xdd, 0xb9, 0x6b, 0xd8, 0xca, 0x96, 0x2d, 0x26, 0xba, + 0x5f, 0x9a, 0x7c, 0xbc, 0xda, 0x0a, 0xe0, 0x24, 0x03, 0x07, 0xb4, 0x1b, + 0xc6, 0xaa, 0x06, 0x00, 0x7b, 0x78, 0xf9, 0xdc, 0x61, 0x41, 0xf7, 0xd6, + 0xa1, 0x7f, 0x20, 0x52, 0x85, 0x02, 0x92, 0x8a, 0x52, 0x26, 0x9e, 0x9d, + 0x93, 0x04, 0xfb, 0x00, 0xa5, 0x03, 0xce, 0xe5, 0x68, 0xbd, 0x72, 0x2d, + 0x46, 0xf8, 0xcb, 0xf0, 0xad, 0xc0, 0xb8, 0xf2, 0xa3, 0x83, 0x85, 0x5c, + 0xa0, 0x1b, 0x3e, 0xeb, 0x2a, 0x45, 0x2c, 0xb3, 0x03, 0xef, 0x48, 0xbd, + 0xcb, 0xb3, 0x3f, 0xe9, 0x3a, 0xd7, 0x7c, 0x0e, 0x42, 0x98, 0xb8, 0x4b, + 0x40, 0x6d, 0x3e, 0x52, 0x6c, 0x23, 0xba, 0xf4, 0x04, 0x96, 0xa5, 0x26, + 0xec, 0xce, 0xf5, 0x84, 0xa5, 0xaa, 0xd0, 0x53, 0xe6, 0xa7, 0x36, 0x15, + 0xa0, 0xff, 0xd2, 0x13, 0xe1, 0x27, 0x49, 0x99, 0x53, 0xd3, 0xae, 0x68, + 0xd9, 0x9e, 0x30, 0x9c, 0xd9, 0xe1, 0xea, 0xff, 0x4d, 0xef, 0xba, 0x7b, + 0x4f, 0xe4, 0x8a, 0x1e, 0x8e, 0x0c, 0xbf, 0xaf, 0x10, 0xfb, 0x92, 0x1a, + 0x08, 0x2f, 0xaa, 0x1e, 0xfa, 0xc0, 0xd0, 0x27, 0xeb, 0x7a, 0x06, 0x5b, + 0x78, 0xf8, 0x2d, 0x62, 0x96, 0x24, 0xb3, 0x91, 0x63, 0x61, 0xe1, 0xfe, + 0xf8, 0xf1, 0x49, 0x61, 0x52, 0x1a, 0x03, 0x26, 0x48, 0x0a, 0x42, 0x7b, + 0x57, 0x26, 0xa6, 0xf7, 0xf2, 0xa3, 0xc7, 0x99, 0xba, 0x36, 0xfc, 0xad, + 0xf1, 0x14, 0x3d, 0xe9, 0xf3, 0xf9, 0xc4, 0x3d, 0xff, 0x67, 0x91, 0xe0, + 0xe3, 0xf3, 0xed, 0x18, 0xc3, 0x6c, 0xc5, 0x15, 0xc8, 0xea, 0x14, 0x55, + 0x07, 0xd9, 0x87, 0xba, 0x4a, 0x68, 0x2b, 0x25, 0xdf, 0x64, 0x70, 0x20, + 0xc3, 0x90, 0x5b, 0x06, 0xb8, 0xec, 0x44, 0xf3, 0xd7, 0xb2, 0x88, 0x28, + 0x2a, 0x76, 0x82, 0x34, 0xc9, 0x71, 0xd2, 0x16, 0x8e, 0x88, 0xcb, 0x94, + 0x5c, 0x02, 0x36, 0x84, 0xec, 0x76, 0x07, 0x33, 0xbb, 0x60, 0xcf, 0x19, + 0x8d, 0xd7, 0xf7, 0x5d, 0x93, 0x2b, 0x04, 0x2b, 0x96, 0x28, 0xc3, 0x4a, + 0xdc, 0x09, 0xea, 0x8c, 0xdf, 0x43, 0xf1, 0xac, 0x8f, 0x93, 0x0c, 0xd6, + 0xcd, 0x7c, 0x3c, 0x00, 0xf1, 0x2c, 0x80, 0x43, 0xab, 0xb4, 0x8f, 0x2a, + 0xf6, 0x90, 0xce, 0x2a, 0xec, 0x62, 0x3a, 0x39, 0x08, 0xb0, 0xdf, 0x49, + 0xce, 0x65, 0x83, 0x06, 0x8f, 0x50, 0x82, 0x25, 0x17, 0x78, 0xc3, 0xf2, + 0x52, 0xb2, 0xe9, 0xbc, 0xb8, 0x8b, 0xd5, 0x89, 0xfc, 0xaa, 0xee, 0x16, + 0x03, 0xe1, 0x23, 0x6e, 0x47, 0xfb, 0x2c, 0x43, 0xe4, 0x85, 0xee, 0x8f, + 0xe9, 0x23, 0x0e, 0x6f, 0x1a, 0xff, 0x27, 0x5b, 0x1b, 0x42, 0x84, 0x7d, + 0xb5, 0x06, 0x4a, 0xd2, 0x6e, 0x6b, 0x98, 0x2e, 0xcb, 0x7b, 0xff, 0xf7, + 0xf9, 0xa7, 0xbf, 0x71, 0xf7, 0xa5, 0xd4, 0x96, 0xa0, 0x96, 0x9d, 0x12, + 0x23, 0x62, 0xd6, 0xc2, 0xfd, 0x14, 0xde, 0xd1, 0xe4, 0xf3, 0x53, 0x3d, + 0xd9, 0x92, 0x92, 0x26, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xa2, 0xa9, 0xf4, 0xab, 0xd7, 0x72, 0x3d, 0x3c, 0x44, 0xc0, 0xb5, 0x22, + 0x06, 0x16, 0x05, 0x9b, 0xa0, 0xc3, 0xaf, 0xcd, 0x24, 0x3c, 0x67, 0xfa, + 0xd3, 0x6a, 0xc4, 0xe8, 0x13, 0x2e, 0xa6, 0x2b, 0xe6, 0xcd, 0x26, 0x6b, + 0x1e, 0xb7, 0x71, 0xfc, 0x24, 0x3c, 0x74, 0xe5, 0xce, 0x0b, 0x9d, 0xf0, + 0xad, 0xce, 0x13, 0x1f, 0xc2, 0x40, 0x7d, 0xbc, 0xb9, 0x2c, 0x37, 0x84, + 0x9b, 0x5a, 0x12, 0x29, 0xa9, 0xb1, 0x6c, 0x1a, 0x69, 0x4a, 0x2b, 0xc4, + 0x77, 0x00, 0x34, 0x2b, 0xac, 0xea, 0x9a, 0x89, 0x0f, 0x5d, 0x41, 0x75, + 0x03, 0xaa, 0x5e, 0xa7, 0xb6, 0x84, 0x99, 0xd7, 0x78, 0x8f, 0x48, 0x2e, + 0x56, 0xd9, 0x14, 0x1e, 0xf4, 0x2c, 0x43, 0x2d, 0x1b, 0x13, 0xf0, 0x61, + 0x54, 0xa6, 0xef, 0x96, 0x96, 0x0f, 0x51, 0x15, 0xa2, 0x21, 0x91, 0xf3, + 0x42, 0x78, 0x5b, 0x92, 0xd4, 0xf3, 0x45, 0x07, 0x14, 0x5e, 0xae, 0x06, + 0xf5, 0xb5, 0xf8, 0x24, 0xcd, 0x92, 0x29, 0x77, 0xb0, 0x2f, 0x4e, 0xf1, + 0x01, 0x7a, 0x01, 0xbe, 0x77, 0x5c, 0x0c, 0x0c, 0x82, 0x5f, 0xf2, 0xa1, + 0x7f, 0xe6, 0xf7, 0x2c, 0x92, 0x07, 0x3e, 0x9c, 0x0c, 0xcb, 0xf4, 0x1f, + 0x28, 0xa9, 0x28, 0x69, 0xcc, 0xb9, 0x66, 0xb7, 0x12, 0x5f, 0xd8, 0x2b, + 0xc4, 0x42, 0x36, 0x7e, 0xbb, 0xc6, 0x5a, 0x44, 0x62, 0x01, 0xcb, 0x25, + 0x10, 0x83, 0x88, 0x3e, 0x2b, 0x76, 0xd0, 0xa5, 0x65, 0xef, 0xe9, 0xe4, + 0xd3, 0x0b, 0x8d, 0xa1, 0xfe, 0x40, 0x65, 0xf2, 0xc7, 0x7c, 0x94, 0xbc, + 0x4c, 0xa0, 0x7c, 0xcc, 0x49, 0x58, 0xde, 0x08, 0xa4, 0xa0, 0x5b, 0x51, + 0x79, 0xb8, 0x02, 0x2f, 0x0a, 0xec, 0xf4, 0xda, 0xed, 0x11, 0xfb, 0x9b, + 0xf1, 0x54, 0xee, 0x29, 0x4f, 0x10, 0x9b, 0xb7, 0xf1, 0xf2, 0xe1, 0x1c, + 0xbf, 0x33, 0x43, 0x1c, 0x0d, 0xfd, 0x60, 0x51, 0xd9, 0x6d, 0xd8, 0x28, + 0xb7, 0x43, 0xfb, 0xaf, 0xe2, 0x4e, 0xd8, 0xb1, 0x9b, 0xe4, 0x18, 0x31, + 0xee, 0xf6, 0x84, 0xab, 0x10, 0xf2, 0x0d, 0x51, 0x7f, 0x1f, 0xcd, 0x1a, + 0x55, 0x5a, 0x8a, 0xb5, 0xfb, 0x70, 0xae, 0x77, 0x32, 0xa8, 0x94, 0xce, + 0xbe, 0x3d, 0xc8, 0x06, 0x8f, 0x39, 0x53, 0x14, 0x4d, 0x9a, 0x11, 0xe4, + 0x49, 0x26, 0x23, 0x38, 0x27, 0xff, 0xdc, 0x00, 0x04, 0xfd, 0x82, 0x0c, + 0xe0, 0x52, 0xb6, 0x7a, 0x4b, 0xb9, 0x8a, 0x9d, 0x01, 0x76, 0x45, 0x64, + 0x84, 0x94, 0x9b, 0x26, 0x4c, 0x85, 0xc8, 0xe1, 0xf5, 0x83, 0x2b, 0x88, + 0x35, 0x7f, 0x03, 0x25, 0x02, 0xba, 0xdf, 0x88, 0xd9, 0xee, 0xa5, 0x77, + 0x33, 0xc6, 0x52, 0x0a, 0x28, 0x71, 0x4c, 0x73, 0xbf, 0x9f, 0xe0, 0xa7, + 0x2a, 0xde, 0x3d, 0xb7, 0x01, 0xd1, 0xfa, 0x7c, 0xa3, 0xe5, 0xa3, 0x19, + 0x2e, 0x53, 0x5a, 0x3d, 0x2f, 0x88, 0xca, 0xfd, 0x02, 0x51, 0xdb, 0xc5, + 0x6b, 0xdd, 0x38, 0x71, 0x0f, 0xa6, 0x08, 0xb1, 0xe7, 0x4e, 0x19, 0xd0, + 0x52, 0x6b, 0x5e, 0xa9, 0x4f, 0x40, 0xa1, 0x17, 0xfd, 0xe5, 0x6e, 0x6c, + 0x58, 0x49, 0x5f, 0xad, 0x4f, 0x52, 0x1c, 0x5e, 0x9b, 0xed, 0xb5, 0x98, + 0x30, 0x38, 0xd4, 0xb6, 0x81, 0x63, 0xea, 0x99, 0x41, 0xbb, 0x43, 0xc5, + 0x46, 0x8d, 0x60, 0x0b, 0xb5, 0x9d, 0xa3, 0x78, 0xd6, 0xbb, 0xe1, 0xf2, + 0x01, 0x62, 0x23, 0x80, 0xb7, 0xc1, 0x93, 0x51, 0x44, 0x50, 0xe4, 0xb3, + 0x93, 0x19, 0x99, 0x61, 0x2b, 0xdc, 0x42, 0x23, 0x3c, 0xe3, 0xf6, 0x16, + 0x7f, 0xa0, 0x8f, 0x7d, 0x8f, 0x9e, 0x18, 0x98, 0x7a, 0x98, 0xf7, 0xb7, + 0xea, 0xcb, 0xbc, 0x5b, 0xa6, 0xe4, 0xc6, 0x7c, 0x5c, 0x5d, 0xd8, 0x10, + 0xe9, 0xf6, 0x89, 0x08, 0xe3, 0x35, 0x60, 0x10, 0x48, 0x49, 0x45, 0x3c, + 0xfd, 0xba, 0xeb, 0xea, 0x1e, 0x29, 0x48, 0xd2, 0x02, 0x23, 0x1c, 0xe7, + 0xc9, 0xbe, 0x44, 0xc0, 0x20, 0x39, 0xdf, 0xf7, 0xe6, 0x13, 0x98, 0x91, + 0x7c, 0x69, 0xca, 0x28, 0x58, 0x1a, 0xd2, 0xf6, 0xc8, 0x9f, 0xd3, 0xe4, + 0x1d, 0x19, 0xec, 0xc2, 0xb8, 0xb5, 0xe1, 0xee, 0x73, 0x22, 0x9c, 0x0c, + 0x79, 0xb6, 0x29, 0x5c, 0xb9, 0xca, 0x93, 0xee, 0x7e, 0x5e, 0xc1, 0x05, + 0x23, 0x2d, 0xa6, 0x29, 0xe4, 0x37, 0x63, 0xe5, 0xc7, 0x4d, 0x40, 0x7d, + 0x61, 0x57, 0xa2, 0x2e, 0xe6, 0x15, 0xd6, 0x6a, 0x2b, 0xe3, 0x31, 0x52, + 0xa7, 0x71, 0xdf, 0x65, 0x84, 0xaa, 0x9b, 0x03, 0x1d, 0x8e, 0x52, 0xd6, + 0x6a, 0xd8, 0xd0, 0xdb, 0xb3, 0x1d, 0x72, 0xc9, 0x98, 0xe1, 0x43, 0x8a, + 0x6c, 0x4c, 0x2d, 0x4b, 0x2f, 0x40, 0xef, 0x83, 0x87, 0x0f, 0xb4, 0x8e, + 0x9a, 0xa1, 0xe9, 0x29, 0x11, 0x3b, 0x2e, 0xbf, 0xe0, 0x78, 0x9f, 0xcc, + 0x80, 0xe7, 0x9e, 0xe4, 0x01, 0x7c, 0x40, 0xd8, 0xf6, 0x97, 0x32, 0x55, + 0x61, 0xcd, 0x7f, 0x23, 0x52, 0xe0, 0xf7, 0x2c, 0x0b, 0x5f, 0x3d, 0x15, + 0xc9, 0x81, 0xd9, 0xf1, 0x88, 0xa0, 0x00, 0x77, 0x44, 0x2d, 0x12, 0xbc, + 0x85, 0x8d, 0x4b, 0xf6, 0x37, 0x41, 0x33, 0x61, 0xd9, 0x8f, 0x96, 0xdb, + 0xb4, 0x28, 0xbd, 0xc5, 0x58, 0x3d, 0xa0, 0x22, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xe8, 0x57, 0x61, 0x2c, 0xef, 0x45, 0x71, 0xf3, + 0x6f, 0x29, 0xd9, 0x1e, 0xd2, 0xa5, 0x73, 0x09, 0x8c, 0xf3, 0x95, 0x59, + 0x2b, 0x6f, 0xd7, 0x09, 0x7e, 0xc8, 0x0c, 0x53, 0x12, 0x39, 0x94, 0x08, + 0xe5, 0x12, 0xc0, 0x3d, 0xc2, 0x97, 0x9e, 0xc9, 0xf4, 0x50, 0x4a, 0x7e, + 0x12, 0x24, 0x7f, 0xa8, 0xaa, 0x58, 0x1c, 0xcf, 0x92, 0x4b, 0x8a, 0xe2, + 0x6d, 0x64, 0x7e, 0x13, 0x3f, 0x95, 0xc8, 0x25, 0xce, 0x1f, 0x97, 0x45, + 0xa0, 0xd8, 0x71, 0x48, 0x84, 0xa6, 0x2c, 0xdf, 0xbb, 0x15, 0xf9, 0xca, + 0x96, 0x5a, 0x76, 0xa6, 0xc8, 0x22, 0x6e, 0x04, 0xbc, 0xb5, 0xec, 0x09, + 0x30, 0xcd, 0x52, 0x2d, 0xe6, 0xc4, 0x29, 0x44, 0xf3, 0xfb, 0x95, 0xcb, + 0xd1, 0xbe, 0xec, 0xf6, 0xb3, 0x06, 0xb0, 0x08, 0x34, 0x1f, 0xf1, 0x5a, + 0x7b, 0x09, 0x89, 0x5e, 0x16, 0xae, 0x0d, 0xbf, 0xda, 0xa4, 0x1c, 0x04, + 0xf7, 0x42, 0x5f, 0xec, 0x63, 0x00, 0xbd, 0xeb, 0xf8, 0x8b, 0xba, 0x1c, + 0xc5, 0x2b, 0x1d, 0xe6, 0xc7, 0xc7, 0xbb, 0x9b, 0xa9, 0x4f, 0xd3, 0x39, + 0x9c, 0x83, 0xe9, 0xcf, 0x4c, 0x0f, 0xdb, 0x06, 0x41, 0x3a, 0xb5, 0x47, + 0xb2, 0x7a, 0x64, 0xda, 0x98, 0x89, 0x81, 0x54, 0x17, 0x65, 0xd2, 0x96, + 0x64, 0x3f, 0x2d, 0x2d, 0xef, 0xf6, 0x99, 0x96, 0x5d, 0xaf, 0x9d, 0x9e, + 0x96, 0x48, 0xd4, 0x17, 0x81, 0x4d, 0xf4, 0x9b, 0x15, 0x01, 0xad, 0x87, + 0x5a, 0x49, 0x3b, 0x81, 0x27, 0x0a, 0x84, 0x9a, 0xb0, 0xbb, 0x55, 0xdb, + 0xfd, 0x5c, 0x15, 0x7b, 0xd7, 0x98, 0xd4, 0xaa, 0x6c, 0xe8, 0x35, 0x2f, + 0x64, 0xf9, 0xc4, 0x94, 0xaf, 0x72, 0xa6, 0x84, 0x67, 0xe3, 0xeb, 0x46, + 0xef, 0x1a, 0xb9, 0x12, 0xf2, 0x28, 0x39, 0xd6, 0xad, 0x08, 0xf0, 0xa4, + 0x32, 0x93, 0x13, 0x33, 0x42, 0x60, 0xa3, 0x09, 0xf3, 0xac, 0xcb, 0x53, + 0x9b, 0x6c, 0xea, 0x9d, 0xa2, 0x2b, 0xe9, 0xb9, 0x24, 0x1f, 0x29, 0xab, + 0x44, 0x4e, 0xa5, 0x4e, 0x7a, 0x9c, 0xc3, 0xfc, 0x40, 0x06, 0xb5, 0x44, + 0x47, 0xc4, 0x0d, 0x2a, 0x6f, 0x1c, 0x75, 0xf6, 0xba, 0xc6, 0x44, 0x7c, + 0x81, 0x62, 0x32, 0x6b, 0x53, 0x2c, 0x77, 0x68, 0x9e, 0x28, 0x14, 0xa8, + 0x72, 0x56, 0x9f, 0x9d, 0xcc, 0xc4, 0x83, 0xfd, 0x06, 0x4a, 0xb2, 0x14, + 0xa0, 0x4e, 0x51, 0x75, 0xdf, 0x72, 0xbf, 0x61, 0xbc, 0x71, 0x7f, 0xf5, + 0xf0, 0xcd, 0xe1, 0x89, 0x85, 0xd8, 0x6c, 0xfe, 0xdc, 0x41, 0xb8, 0xc7, + 0x8c, 0x09, 0x11, 0xd0, 0xa1, 0xfa, 0xaa, 0x15, 0xb0, 0x34, 0xf4, 0xaa, + 0x5a, 0x1b, 0x08, 0x70, 0xb0, 0x49, 0xb8, 0x17, 0x66, 0x4d, 0x29, 0x52, + 0x42, 0x09, 0x95, 0x9f, 0x64, 0xe4, 0x07, 0xe0, 0xf2, 0x59, 0xc4, 0x6b, + 0xae, 0x98, 0xcb, 0x15, 0x1e, 0xfc, 0x2f, 0x8c, 0x1d, 0x18, 0xdb, 0xe8, + 0x87, 0xa2, 0xbb, 0xe6, 0xbb, 0xa4, 0x8c, 0xc2, 0xe6, 0xf6, 0x7a, 0xbf, + 0x6a, 0x62, 0x01, 0x54, 0x94, 0x8c, 0xbe, 0x96, 0xe0, 0xa3, 0xe9, 0x1f, + 0x3d, 0xf5, 0xa6, 0xdf, 0xae, 0xba, 0xef, 0x4f, 0x0c, 0xf7, 0x37, 0xd3, + 0xf2, 0xcf, 0x66, 0xee, 0x6f, 0x52, 0x74, 0x5e, 0x00, 0xfd, 0xdf, 0x3b, + 0x95, 0x80, 0xcf, 0x30, 0xe5, 0xd7, 0x38, 0x13, 0x19, 0x1f, 0x1f, 0xc4, + 0x0e, 0x25, 0x2b, 0xcd, 0x0b, 0x17, 0x05, 0x50, 0x51, 0xa9, 0x12, 0x0d, + 0x7f, 0xe9, 0x69, 0x92, 0x1a, 0xf2, 0x59, 0xbe, 0x3f, 0x76, 0x4f, 0x8b, + 0xfc, 0x51, 0x0d, 0x28, 0x3b, 0x74, 0xbb, 0x9e, 0xed, 0x04, 0x22, 0x7a, + 0xd6, 0x8a, 0xc8, 0x66, 0xe3, 0x3a, 0x62, 0x18, 0x9d, 0x89, 0xea, 0x0e, + 0x2c, 0x3e, 0xd6, 0xbc, 0x2b, 0x7d, 0xff, 0xca, 0x19, 0x6c, 0xb7, 0x0f, + 0xcd, 0x90, 0xfa, 0x8c, 0xd6, 0xcf, 0xf0, 0x1f, 0xca, 0x48, 0xcc, 0x15, + 0x72, 0x44, 0x15, 0x88, 0x92, 0xd0, 0x46, 0xb9, 0x0e, 0xc4, 0x7c, 0xe2, + 0x1f, 0x34, 0xdb, 0x1b, 0xfe, 0xa4, 0xbd, 0x07, 0xf8, 0x88, 0x06, 0x3f, + 0x12, 0xfb, 0x39, 0x04, 0xc0, 0x37, 0x24, 0x02, 0x1f, 0x94, 0x55, 0x4c, + 0x2d, 0x36, 0x3a, 0x63, 0x90, 0xb2, 0x91, 0x58, 0xbd, 0x6e, 0x6d, 0x84, + 0x76, 0x16, 0x6b, 0x22, 0x2a, 0x83, 0xb6, 0xf6, 0x35, 0xf0, 0xa4, 0x8c, + 0x6f, 0x59, 0xda, 0xbe, 0x81, 0xc8, 0xb0, 0xf6, 0x79, 0x83, 0xaf, 0xeb, + 0xe6, 0xcd, 0x0d, 0x7e, 0x69, 0xc7, 0xfb, 0xa6, 0xb4, 0xb3, 0x28, 0x08, + 0xd1, 0x15, 0x8c, 0x94, 0x7e, 0xc8, 0x39, 0x1e, 0x29, 0x44, 0xb9, 0x43, + 0xac, 0x35, 0x4e, 0xf6, 0x27, 0xff, 0x8b, 0x86, 0x6e, 0x41, 0xa3, 0xb7, + 0x21, 0x18, 0x5d, 0xe6, 0xa5, 0xa9, 0x63, 0x27, 0x1f, 0xb0, 0x3d, 0xad, + 0x6e, 0xd9, 0x88, 0xaa, 0x4f, 0x06, 0x3b, 0xd4, 0x79, 0xaa, 0x76, 0xf4, + 0x4b, 0x43, 0x3a, 0xf8, 0x54, 0x37, 0xf4, 0xe2, 0xff, 0x21, 0x0b, 0x87, + 0x45, 0x4f, 0x27, 0x1b, 0x59, 0x88, 0xf6, 0x06, 0x65, 0x50, 0xaf, 0x4b, + 0x05, 0x0c, 0xd1, 0x7e, 0x22, 0x45, 0xb7, 0x5f, 0x69, 0x86, 0xa3, 0xc2, + 0x3c, 0x9e, 0xb8, 0xe0, 0x2d, 0xc2, 0x56, 0xcd, 0xd7, 0x32, 0x03, 0x1c, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x6f, 0x3a, 0xfa, 0xb1, + 0xb9, 0x44, 0x2e, 0x97, 0x3e, 0xba, 0x27, 0x2b, 0x71, 0x75, 0xca, 0xa2, + 0x0e, 0xd0, 0x57, 0xcd, 0x7b, 0x3e, 0x19, 0xb4, 0x1c, 0x6a, 0xf4, 0x47, + 0x5c, 0xc1, 0xb6, 0x0b, 0xc0, 0xaf, 0xfa, 0xc6, 0x25, 0xe1, 0xad, 0xf4, + 0x69, 0xff, 0xaa, 0x31, 0x4a, 0xaf, 0x86, 0x64, 0x63, 0x7a, 0xfd, 0xcd, + 0x6d, 0x9a, 0xc0, 0x7b, 0x59, 0x3c, 0x55, 0xdc, 0x69, 0x5d, 0xad, 0x21, + 0xfd, 0x45, 0xc8, 0x0a, 0x08, 0xbb, 0xb1, 0x3a, 0x79, 0xed, 0x4b, 0x46, + 0x69, 0x92, 0x5d, 0x92, 0xb5, 0xe9, 0x17, 0x0a, 0x7e, 0x27, 0x71, 0x5c, + 0x70, 0xa2, 0x8a, 0x73, 0x97, 0xf0, 0x50, 0x1f, 0xc3, 0x3b, 0x4d, 0x43, + 0x9f, 0x13, 0x72, 0x9a, 0x44, 0x81, 0x80, 0xaf, 0xcd, 0x2d, 0x40, 0x35, + 0xf5, 0xcc, 0xa7, 0x1a, 0xba, 0x2f, 0x9b, 0xe0, 0x7b, 0x2b, 0x68, 0xeb, + 0x2b, 0x45, 0xd2, 0x0a, 0x1e, 0x8a, 0xca, 0xd2, 0x50, 0x7a, 0xac, 0x7b, + 0x48, 0x24, 0xc6, 0x29, 0xec, 0x17, 0xbc, 0xf9, 0x13, 0x64, 0x20, 0x39, + 0x81, 0xc8, 0xfc, 0x5a, 0xe5, 0xf4, 0x03, 0x25, 0x62, 0xde, 0x83, 0x01, + 0x84, 0x07, 0x3c, 0x89, 0xc9, 0xd8, 0x4e, 0x96, 0x84, 0xa2, 0xfc, 0xb0, + 0x98, 0x32, 0x6a, 0x46, 0xd2, 0x87, 0x40, 0xf2, 0x7e, 0x3c, 0xfd, 0x12, + 0x80, 0x28, 0xbf, 0xbd, 0xb0, 0xec, 0x0a, 0x22, 0x3d, 0x6b, 0xb9, 0x6c, + 0x1f, 0x58, 0x66, 0xe6, 0xce, 0x5b, 0x79, 0x9b, 0xd4, 0x18, 0x4c, 0xff, + 0x50, 0xcb, 0xc2, 0xcc, 0x88, 0x89, 0xe4, 0xef, 0x60, 0xb7, 0xcc, 0x81, + 0x67, 0x71, 0x4c, 0x21, 0xb9, 0xe6, 0x9e, 0xa9, 0x2e, 0x03, 0x32, 0xa4, + 0x03, 0x9c, 0x76, 0x72, 0x19, 0xe6, 0xa9, 0x00, 0xec, 0x07, 0xd4, 0x24, + 0x48, 0xfc, 0xe6, 0xa8, 0xe3, 0xc3, 0x19, 0x89, 0xfc, 0x5a, 0xda, 0x24, + 0x45, 0x5b, 0xed, 0xae, 0x59, 0xce, 0xf7, 0xce, 0xa5, 0x0c, 0xf8, 0xe1, + 0xa6, 0x49, 0x3b, 0x8c, 0x45, 0x53, 0x6c, 0x2d, 0xa8, 0x66, 0xcb, 0xe5, + 0xe1, 0x29, 0x5d, 0x5b, 0x1a, 0x55, 0xf3, 0x20, 0x3f, 0x49, 0x9f, 0x49, + 0x78, 0x4e, 0xc8, 0x93, 0x7f, 0xbe, 0x67, 0x48, 0x97, 0x88, 0xd8, 0x28, + 0x69, 0x42, 0x56, 0x30, 0x96, 0x23, 0xaa, 0xac, 0x46, 0xcc, 0x8b, 0xec, + 0xcf, 0x8b, 0x10, 0x00, 0x24, 0x19, 0x7b, 0x51, 0x28, 0x12, 0x8b, 0xfa, + 0xdb, 0x4d, 0x90, 0xfd, 0x84, 0xc3, 0x78, 0xbf, 0xc2, 0xd9, 0x66, 0x1e, + 0xfa, 0x85, 0xc3, 0xf8, 0x13, 0x7c, 0x5d, 0x08, 0x4c, 0xb7, 0xd2, 0x21, + 0x42, 0x66, 0xf0, 0xe6, 0x58, 0x99, 0xc0, 0xa3, 0xef, 0x39, 0x54, 0x76, + 0xa8, 0x8e, 0x40, 0x61, 0x66, 0x90, 0x80, 0x76, 0x8d, 0x8b, 0x93, 0x9b, + 0xf8, 0x20, 0xe1, 0x5b, 0x42, 0x8b, 0xc9, 0x0c, 0x67, 0x95, 0x3e, 0xb7, + 0x2e, 0x3a, 0x97, 0x25, 0x91, 0xd6, 0x7d, 0xf7, 0xc5, 0xf0, 0xa8, 0x8b, + 0x45, 0xa2, 0x8d, 0x42, 0x8c, 0xd6, 0xaa, 0x5e, 0xad, 0xe4, 0x73, 0xe2, + 0x7b, 0x7a, 0x2f, 0x0f, 0xb3, 0x99, 0x26, 0x7b, 0xc5, 0x04, 0xa1, 0x94, + 0x0b, 0x4c, 0x59, 0x1a, 0x14, 0x40, 0xd9, 0x2c, 0xf5, 0x2e, 0x07, 0xa1, + 0xc8, 0x73, 0xf7, 0x1d, 0x12, 0xcf, 0xed, 0xdc, 0x8f, 0x74, 0xb6, 0x16, + 0x1e, 0x0c, 0x37, 0x67, 0x48, 0xa3, 0xc6, 0x90, 0xe6, 0x41, 0xfd, 0x75, + 0xa6, 0xd6, 0x4a, 0xd5, 0x19, 0x1f, 0x14, 0xbc, 0xc7, 0xac, 0x63, 0x8d, + 0x1f, 0x4b, 0xc1, 0x0a, 0x79, 0x22, 0x96, 0x19, 0x8e, 0x6f, 0x75, 0xc0, + 0x14, 0xa2, 0x7e, 0xe4, 0x02, 0xb8, 0x37, 0x6b, 0xb5, 0xad, 0x83, 0xa5, + 0x45, 0x86, 0xb9, 0xc4, 0xc1, 0xca, 0x90, 0xb0, 0xbf, 0x8d, 0xc7, 0x9e, + 0x04, 0x19, 0x07, 0x29, 0x1d, 0x7e, 0x9a, 0x30, 0xb0, 0x16, 0x47, 0x51, + 0xd1, 0x2a, 0xb5, 0x2f, 0x36, 0x50, 0x35, 0xab, 0x3f, 0xaa, 0xa1, 0xf9, + 0xcc, 0x60, 0xd5, 0xd3, 0x7b, 0x9e, 0x9a, 0x82, 0xca, 0xb7, 0x4d, 0x10, + 0x7f, 0x37, 0x0b, 0x8b, 0x8c, 0xbc, 0x80, 0x9b, 0xb3, 0x84, 0x84, 0x08, + 0xb5, 0x40, 0x29, 0x2c, 0xd3, 0xf2, 0x29, 0x67, 0xc9, 0x96, 0xc5, 0x4b, + 0xd0, 0xbb, 0x8c, 0x5e, 0xb4, 0x1a, 0xa4, 0x23, 0x73, 0x55, 0xc5, 0xdf, + 0x1f, 0x7d, 0xad, 0xb1, 0x0b, 0x85, 0x7c, 0x6b, 0x34, 0x04, 0x22, 0x18, + 0xc6, 0x05, 0xc5, 0xa1, 0xa2, 0x4f, 0x75, 0x3e, 0xd7, 0x23, 0xd1, 0x8b, + 0xb7, 0xfd, 0xf5, 0x01, 0x8d, 0xe4, 0xb3, 0xed, 0xdc, 0x6f, 0x02, 0x72, + 0x2d, 0x7e, 0x00, 0x8c, 0xcd, 0xb1, 0x9f, 0x18, 0xd8, 0x19, 0xc4, 0x07, + 0x41, 0x95, 0xd5, 0x51, 0xd5, 0x21, 0x13, 0xd3, 0x63, 0x0a, 0x2c, 0x2a, + 0x88, 0x42, 0xfe, 0xed, 0xb5, 0x9a, 0xa9, 0xbb, 0x8a, 0xac, 0x64, 0x6c, + 0xc6, 0x7f, 0x52, 0x21, 0xad, 0xb3, 0x05, 0x04, 0xc1, 0xf9, 0xfd, 0x36, + 0x26, 0xf4, 0xd1, 0xda, 0x71, 0x88, 0xe1, 0x05, 0xeb, 0x68, 0x43, 0xd8, + 0xc3, 0xb6, 0x93, 0xca, 0x66, 0x9d, 0xfb, 0x9a, 0x7f, 0xbd, 0x53, 0x78, + 0x24, 0xc3, 0x41, 0xff, 0x5f, 0xce, 0x9b, 0x38, 0x3d, 0x8b, 0x47, 0x19, + 0x0a, 0xee, 0x30, 0x14, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x0f, 0x0d, 0x44, 0x9b, 0x73, 0x84, 0x55, 0x67, 0xb7, 0x93, 0x2d, 0x0b, + 0x5c, 0x0a, 0x3f, 0x50, 0x98, 0x6b, 0xa4, 0x9f, 0x92, 0x62, 0x04, 0x11, + 0x4c, 0x83, 0x06, 0x5a, 0x32, 0x11, 0xfa, 0x2e, 0xb4, 0xe1, 0x7f, 0x19, + 0x98, 0x28, 0xf6, 0x0b, 0xf1, 0xa2, 0x93, 0xba, 0x6e, 0xcc, 0x00, 0xb7, + 0x9f, 0xe8, 0x06, 0x73, 0x5b, 0xc2, 0x64, 0x6f, 0xd4, 0x87, 0x38, 0xa9, + 0x9a, 0x6b, 0x25, 0x0f, 0x05, 0x34, 0x89, 0x15, 0x39, 0xcc, 0xbf, 0x7f, + 0xb9, 0x85, 0xf3, 0x57, 0x5c, 0x73, 0xb3, 0xf2, 0xa3, 0xa3, 0x24, 0x29, + 0xa7, 0xf1, 0x3b, 0xc5, 0xe6, 0x9c, 0xf1, 0x5a, 0x92, 0xf3, 0x2e, 0x2e, + 0x42, 0x51, 0xa7, 0x71, 0x61, 0x90, 0x18, 0x27, 0xfc, 0x14, 0x74, 0x1e, + 0xa6, 0x31, 0x35, 0x31, 0xa1, 0x12, 0xd8, 0x39, 0xfa, 0x45, 0xad, 0x9d, + 0xb0, 0xd9, 0x2f, 0xa9, 0x1b, 0x3d, 0xb4, 0x1d, 0x0b, 0x6d, 0xc0, 0xe9, + 0x40, 0x6e, 0x13, 0xda, 0x9b, 0xf9, 0x4d, 0xcb, 0x18, 0x06, 0xb2, 0xaf, + 0x5d, 0xa7, 0x40, 0xa8, 0x77, 0xf4, 0xad, 0x1f, 0x3a, 0xd4, 0x1c, 0x06, + 0x31, 0x1e, 0x2e, 0x09, 0x5b, 0xd1, 0x74, 0xe3, 0xa4, 0x78, 0x2f, 0xce, + 0xac, 0xe8, 0x4a, 0x50, 0x21, 0xe4, 0x6b, 0x44, 0xa2, 0x6b, 0x94, 0x7a, + 0x21, 0xbe, 0x57, 0x36, 0x56, 0x71, 0x01, 0x5d, 0x75, 0xf5, 0x32, 0x12, + 0xe6, 0xa9, 0xd4, 0x9b, 0x8c, 0xdb, 0x14, 0xe0, 0x95, 0xd9, 0xf7, 0xa5, + 0xb4, 0x23, 0x12, 0x33, 0x83, 0xef, 0xbe, 0xa0, 0x19, 0xa9, 0x6d, 0x53, + 0x2b, 0x3c, 0x7f, 0xba, 0x0a, 0x6f, 0xef, 0x06, 0x1d, 0x77, 0x66, 0x0d, + 0xee, 0xd4, 0x6d, 0x0b, 0x58, 0x6a, 0xaf, 0x6a, 0x60, 0x06, 0x29, 0xb9, + 0xac, 0xfb, 0x39, 0xc6, 0x05, 0xf5, 0x84, 0xd4, 0xcb, 0xc3, 0x2f, 0x6d, + 0x83, 0xf2, 0x6c, 0x01, 0x2b, 0xd7, 0x6a, 0xbb, 0x4c, 0xd1, 0x9b, 0x90, + 0xc4, 0xe3, 0x1f, 0xdd, 0x3b, 0x5a, 0x2c, 0xc4, 0xc2, 0xa0, 0x96, 0xd8, + 0x5e, 0xa4, 0x27, 0x62, 0xdb, 0x1a, 0xe0, 0x24, 0x46, 0x24, 0x32, 0x13, + 0xd3, 0xb6, 0xa4, 0x25, 0x7a, 0x02, 0xa1, 0x99, 0x0c, 0xea, 0x04, 0xca, + 0x7a, 0xf5, 0x5d, 0x63, 0xf1, 0x9e, 0x2e, 0x61, 0x76, 0x89, 0x2e, 0xa1, + 0x9f, 0xd1, 0xcd, 0x12, 0xe8, 0x9a, 0x6b, 0x02, 0xd6, 0x59, 0x1d, 0x17, + 0x89, 0x2a, 0x03, 0x1d, 0x85, 0x5e, 0x31, 0xbd, 0x70, 0x08, 0x03, 0xa0, + 0xd5, 0x9c, 0xe8, 0xc5, 0x50, 0xbc, 0x22, 0xe0, 0x5b, 0x72, 0x7e, 0xf4, + 0xbb, 0xaa, 0xfe, 0x06, 0x0f, 0xc3, 0xfb, 0x2f, 0xa7, 0x54, 0x50, 0x8f, + 0x8d, 0xf8, 0xf9, 0x37, 0x65, 0xc9, 0x4a, 0xc2, 0x86, 0x52, 0xa7, 0xa6, + 0x8a, 0x93, 0x0f, 0xfd, 0xd6, 0x2c, 0xd7, 0x82, 0xab, 0x8e, 0x6f, 0x0a, + 0xaf, 0xc8, 0x8e, 0x8f, 0xa9, 0x31, 0x8e, 0x42, 0x1a, 0x54, 0x63, 0xaf, + 0xe3, 0x3e, 0xdb, 0xc9, 0x7c, 0x82, 0xcb, 0xe6, 0x33, 0x6e, 0x3b, 0x80, + 0x3a, 0x90, 0xff, 0xa0, 0x6a, 0x09, 0xc5, 0x2a, 0x2c, 0xf0, 0xd3, 0x6f, + 0x95, 0x4e, 0xe0, 0xc9, 0xc9, 0x9f, 0x8c, 0x82, 0xf1, 0x8e, 0xf3, 0x1e, + 0x77, 0x9c, 0x17, 0xb4, 0x2e, 0xd5, 0xb7, 0x3c, 0x7c, 0xbc, 0x26, 0x5d, + 0xf0, 0x3d, 0x4d, 0x26, 0xfa, 0x58, 0x57, 0x82, 0x64, 0x20, 0xde, 0x94, + 0x12, 0x6a, 0x09, 0x33, 0x10, 0x4f, 0xb0, 0x74, 0xde, 0xa3, 0xfc, 0xdd, + 0x7f, 0x69, 0x94, 0xa5, 0xa2, 0x0b, 0x4f, 0x8f, 0x8a, 0xf0, 0x20, 0x0c, + 0x4b, 0x88, 0x9e, 0xe9, 0x4f, 0x1d, 0xe4, 0xdd, 0x5d, 0x35, 0xd1, 0x53, + 0xe5, 0x2c, 0xdb, 0x1e, 0x4d, 0x92, 0x13, 0x36, 0x16, 0xf8, 0xe7, 0xbe, + 0x52, 0x45, 0x03, 0x78, 0x44, 0x22, 0xc0, 0x21, 0x42, 0xbc, 0x15, 0x56, + 0x56, 0x33, 0xf9, 0xb5, 0x37, 0xb1, 0x7b, 0xbb, 0xcc, 0xd2, 0x50, 0x6c, + 0x38, 0x7f, 0x24, 0x2c, 0x7a, 0x96, 0x44, 0x94, 0x5f, 0xa6, 0x54, 0xd0, + 0x29, 0xeb, 0xb1, 0x21, 0xae, 0x92, 0x76, 0xfb, 0x40, 0x46, 0x08, 0x6e, + 0x99, 0x55, 0x43, 0xf8, 0x17, 0x40, 0xb9, 0x85, 0xcb, 0x41, 0xa9, 0x2a, + 0x94, 0xdb, 0xcc, 0xf4, 0x5e, 0x70, 0x9d, 0xc7, 0x0e, 0xb5, 0xb7, 0x1c, + 0x59, 0x1d, 0x4c, 0xd2, 0x1c, 0xde, 0x5c, 0xe6, 0x4e, 0x44, 0xf9, 0xfd, + 0x14, 0xd4, 0x3f, 0xfe, 0x24, 0x84, 0x90, 0xea, 0x43, 0xab, 0x6f, 0x29, + 0x97, 0x3c, 0xbd, 0x82, 0x26, 0x4f, 0x27, 0x2b, 0xed, 0x0b, 0x65, 0xfd, + 0x83, 0xf3, 0x00, 0x77, 0xcb, 0x13, 0xd1, 0xbb, 0xab, 0xf5, 0xc8, 0xfa, + 0xd5, 0xff, 0x2c, 0xd9, 0x45, 0x9a, 0x65, 0x8d, 0x87, 0x17, 0x63, 0x26, + 0xba, 0x94, 0x88, 0x2b, 0xe9, 0x46, 0x6a, 0x34, 0x6e, 0x2c, 0x04, 0x69, + 0x56, 0x38, 0xb4, 0xbd, 0x44, 0x17, 0xf8, 0x5a, 0xcf, 0xfb, 0x51, 0xbe, + 0xb4, 0xed, 0x65, 0x5c, 0xfd, 0xa5, 0x04, 0x32, 0xc5, 0x0f, 0x60, 0x30, + 0xb9, 0xdf, 0xbf, 0x2a, 0x5d, 0x3f, 0x59, 0x32, 0xc1, 0xd0, 0xf3, 0x98, + 0x0e, 0x23, 0x4f, 0x93, 0x7a, 0x16, 0xf3, 0xa3, 0x25, 0xe1, 0x0c, 0x20, + 0x8e, 0x3b, 0x3e, 0x57, 0xa1, 0x53, 0xe9, 0x2d, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xdc, 0xd5, 0x7f, 0xfc, 0x8d, 0xa7, 0x1d, 0xc3, + 0x8d, 0x9a, 0x53, 0x47, 0x76, 0xa6, 0x45, 0xd9, 0x33, 0x57, 0x88, 0xfa, + 0x5c, 0xb0, 0x0c, 0xb1, 0xff, 0x29, 0x4a, 0x1c, 0x36, 0x01, 0x57, 0x2d, + 0xab, 0xd2, 0x9d, 0xda, 0x63, 0xd8, 0x1b, 0x7a, 0xb5, 0xf3, 0xde, 0xef, + 0x7d, 0xf5, 0x86, 0x13, 0x1f, 0x2b, 0x35, 0x64, 0x0f, 0xfd, 0xe1, 0x1f, + 0xb6, 0x9d, 0x55, 0xd8, 0x73, 0xb7, 0xed, 0x27, 0xc7, 0x8c, 0x34, 0xa6, + 0x4b, 0x72, 0xbe, 0x4d, 0xa2, 0x7c, 0x82, 0x5f, 0xc9, 0xe3, 0x62, 0x2b, + 0xc5, 0x59, 0x55, 0xeb, 0x3f, 0xf1, 0x6e, 0x52, 0x78, 0xf4, 0x5b, 0xc8, + 0x24, 0xda, 0x0a, 0x27, 0x3d, 0x44, 0x8b, 0x86, 0x44, 0x82, 0x45, 0x17, + 0xe3, 0x35, 0xa8, 0xad, 0xf9, 0xa9, 0xef, 0xec, 0x4f, 0xd5, 0x9f, 0xe4, + 0x56, 0x5b, 0xd7, 0xc3, 0x30, 0x20, 0x42, 0x58, 0x8c, 0x81, 0x8e, 0x22, + 0xb8, 0xfe, 0x07, 0x99, 0x3b, 0xee, 0x89, 0x4d, 0x13, 0x23, 0xbc, 0xc1, + 0x20, 0x9b, 0xdb, 0x06, 0xf2, 0xde, 0xcc, 0x15, 0xca, 0x3e, 0xdd, 0x91, + 0x0f, 0xdf, 0x5b, 0x6c, 0xe9, 0x5a, 0xb8, 0x18, 0x85, 0x3c, 0x17, 0x57, + 0x59, 0x37, 0x5a, 0xcd, 0x0c, 0x10, 0xe7, 0x4c, 0x79, 0xf5, 0x8a, 0xb6, + 0xb2, 0x0a, 0xe5, 0xc8, 0xed, 0x80, 0xbe, 0xc8, 0xaf, 0x78, 0x36, 0xea, + 0xc5, 0xff, 0xae, 0x1f, 0xbe, 0x75, 0xda, 0xec, 0x9e, 0xba, 0x17, 0x9e, + 0x43, 0x43, 0x37, 0x40, 0x91, 0x00, 0xe0, 0x2b, 0xca, 0x39, 0x7f, 0x43, + 0x6c, 0x80, 0xd2, 0x81, 0x9c, 0x78, 0xe5, 0xd0, 0x76, 0xb8, 0x16, 0x0c, + 0xf7, 0x7d, 0x80, 0x02, 0x66, 0xa9, 0x2f, 0x05, 0xec, 0x7c, 0xf2, 0x1b, + 0xc9, 0x14, 0x06, 0x00, 0x84, 0xa3, 0x2c, 0xdc, 0xb6, 0x37, 0x3f, 0x72, + 0x73, 0x9d, 0x0a, 0x99, 0xdb, 0xb1, 0x60, 0x05, 0x7c, 0x1a, 0x9d, 0xe3, + 0x48, 0x7f, 0x24, 0x74, 0x38, 0xd7, 0xbf, 0x58, 0xf8, 0x2c, 0x11, 0x7b, + 0x16, 0xa4, 0xd2, 0xa2, 0x86, 0xe9, 0xfb, 0xd8, 0x59, 0xcc, 0xc4, 0x81, + 0xbd, 0x30, 0xc3, 0x1d, 0xc5, 0xe2, 0xba, 0x4b, 0x8a, 0x38, 0xc5, 0x02, + 0xdb, 0xce, 0xc7, 0x58, 0xbb, 0xcd, 0x6a, 0x48, 0xe6, 0x62, 0xa9, 0xad, + 0xfe, 0x0e, 0x2d, 0xed, 0x40, 0x3d, 0xcc, 0x9a, 0x1c, 0x21, 0x57, 0x30, + 0x5c, 0x4f, 0x1b, 0xc9, 0x1e, 0x9a, 0x9f, 0x02, 0x5d, 0xfc, 0x83, 0x9b, + 0x4e, 0x1b, 0x45, 0x17, 0xfd, 0x63, 0xb2, 0x0b, 0x40, 0x6d, 0xf4, 0xff, + 0xc8, 0xca, 0xb0, 0x35, 0x57, 0xac, 0xa5, 0x2a, 0x76, 0xa9, 0x17, 0xc2, + 0xdb, 0x5e, 0xd7, 0xa7, 0x32, 0xb6, 0xa1, 0x57, 0xfe, 0x10, 0x89, 0x56, + 0x24, 0xbd, 0xb9, 0x52, 0x28, 0x98, 0xa8, 0xc9, 0x04, 0x8a, 0x36, 0xd6, + 0xf1, 0xda, 0x05, 0x2e, 0x12, 0xab, 0x40, 0xaa, 0xdf, 0xb7, 0xb3, 0x1f, + 0x7f, 0xe7, 0xd6, 0xd0, 0x2a, 0x49, 0xcd, 0x49, 0x71, 0xfe, 0xdf, 0x5c, + 0xf8, 0x7d, 0x6c, 0x35, 0xfe, 0x16, 0x4f, 0x00, 0x16, 0x39, 0xc7, 0x00, + 0x2f, 0xc9, 0x29, 0xff, 0xad, 0x99, 0x9f, 0x70, 0xca, 0xd8, 0xdd, 0xed, + 0xdc, 0xf4, 0xd5, 0xd7, 0x41, 0x12, 0x36, 0x8e, 0xea, 0xd4, 0xeb, 0xb1, + 0x62, 0x97, 0x7f, 0x4b, 0x5b, 0x07, 0x07, 0x0e, 0x21, 0xc1, 0x8e, 0x99, + 0x94, 0x0c, 0x73, 0xbd, 0xf0, 0xc5, 0xab, 0xdf, 0xa7, 0xe4, 0x37, 0x98, + 0x57, 0xb7, 0xfc, 0x3d, 0x9b, 0xe7, 0xba, 0x4d, 0x86, 0xfb, 0x27, 0x72, + 0xd6, 0x04, 0xc5, 0x18, 0x02, 0xa5, 0xb5, 0x7c, 0xf1, 0x47, 0x0d, 0x92, + 0x74, 0x63, 0x32, 0x5b, 0x5d, 0x1a, 0x70, 0xe0, 0x86, 0x79, 0x47, 0x8c, + 0xf4, 0x88, 0xf0, 0x8e, 0x9d, 0xd4, 0xce, 0x7f, 0xa5, 0xf5, 0xd8, 0x27, + 0x23, 0xa8, 0xe0, 0x0b, 0x1c, 0x1d, 0xfd, 0x78, 0x0c, 0x63, 0x5c, 0x1e, + 0xfe, 0x2c, 0xe0, 0xce, 0x4e, 0x93, 0x1d, 0xd6, 0xa5, 0xf5, 0x9a, 0x98, + 0x34, 0x11, 0x77, 0x5a, 0x38, 0xdc, 0xf0, 0x0d, 0xfe, 0x66, 0xb3, 0xb9, + 0xee, 0x6b, 0x19, 0x30, 0x52, 0x36, 0x7a, 0x8c, 0xd2, 0x9f, 0xca, 0xce, + 0xdc, 0x6e, 0xfb, 0x0b, 0xe1, 0x60, 0xa9, 0x00, 0x36, 0xd1, 0xa7, 0x17, + 0xed, 0xb9, 0x05, 0x06, 0x32, 0xaf, 0xb1, 0x34, 0x51, 0xc4, 0x07, 0x2b, + 0x4c, 0x65, 0x85, 0xf5, 0x1d, 0x71, 0xf7, 0x37, 0xc9, 0x26, 0xa3, 0xd0, + 0xb2, 0xd1, 0x6d, 0x73, 0xa7, 0xba, 0xbd, 0x4d, 0xb5, 0x77, 0x7a, 0x04, + 0x31, 0x14, 0xbb, 0xdc, 0xe9, 0x1f, 0x4f, 0x74, 0xb8, 0x9c, 0x5e, 0xa7, + 0x48, 0xf2, 0x01, 0xdf, 0x55, 0x17, 0x0b, 0xbb, 0x8d, 0xae, 0x15, 0x8d, + 0x49, 0xfc, 0x17, 0xb8, 0xbf, 0xd6, 0x2f, 0x14, 0x1b, 0x64, 0xfc, 0xec, + 0x96, 0xd2, 0x50, 0x56, 0xb2, 0x48, 0xed, 0x70, 0x08, 0x6c, 0xce, 0x5b, + 0x07, 0x1f, 0xf9, 0x37, 0xa4, 0x9f, 0xe6, 0x07, 0xb3, 0x23, 0x39, 0x51, + 0xaf, 0xa1, 0xc8, 0x19, 0x04, 0x1a, 0x88, 0x22, 0x10, 0x58, 0x9d, 0xf2, + 0xd7, 0xb4, 0x9e, 0xec, 0x35, 0x4f, 0xfe, 0x92, 0x9a, 0x3d, 0x26, 0xf0, + 0x89, 0x93, 0xbd, 0x70, 0xf5, 0x3a, 0xb3, 0x09, 0x30, 0x97, 0x62, 0x2d, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x15, 0xc2, 0xb0, 0x52, + 0x93, 0x9c, 0x9f, 0xdf, 0xf7, 0x32, 0x93, 0x43, 0x04, 0xb5, 0x5b, 0xe4, + 0x28, 0x09, 0xbc, 0x55, 0x37, 0x9d, 0xf4, 0xcd, 0x52, 0xf4, 0xc5, 0x26, + 0x39, 0xd3, 0x1a, 0x16, 0x03, 0xa9, 0xf5, 0x7d, 0x42, 0x97, 0x0a, 0x26, + 0xb0, 0xad, 0x52, 0x6f, 0x73, 0x21, 0x6a, 0x3f, 0xec, 0x6f, 0x5b, 0xeb, + 0xd3, 0xf1, 0xdc, 0x8f, 0xb4, 0x60, 0x9d, 0x72, 0xf5, 0xe3, 0xee, 0x2f, + 0x70, 0x4e, 0xef, 0x74, 0xbd, 0x07, 0xab, 0xdf, 0x3b, 0xfe, 0xb4, 0x09, + 0x81, 0x6b, 0xcf, 0x4e, 0xed, 0x94, 0xeb, 0xb0, 0xff, 0x65, 0xfa, 0x24, + 0x29, 0x64, 0x51, 0xaf, 0x6c, 0xa6, 0xe9, 0x25, 0xa1, 0x8b, 0x62, 0xea, + 0x6f, 0xbe, 0x8a, 0x7a, 0xf7, 0xc7, 0xa4, 0xd1, 0xf9, 0x7a, 0x88, 0x4a, + 0x0a, 0xca, 0xfd, 0x28, 0x58, 0x27, 0x09, 0x75, 0x6d, 0x63, 0x0e, 0x1f, + 0xb4, 0x1e, 0x99, 0x07, 0x4a, 0xea, 0x24, 0xd2, 0x76, 0xd5, 0xfb, 0xcf, + 0x67, 0xcd, 0xeb, 0xd4, 0x68, 0xd2, 0x66, 0xa5, 0x5c, 0x93, 0x83, 0xc3, + 0xd9, 0xd4, 0x3e, 0xac, 0xc9, 0x4c, 0x9f, 0x99, 0x24, 0x7d, 0x56, 0x19, + 0x18, 0xfe, 0xf9, 0x81, 0x87, 0xe5, 0xaf, 0x36, 0x75, 0x7e, 0x81, 0x45, + 0x38, 0xcc, 0xe4, 0xfa, 0xa0, 0xe3, 0x22, 0x18, 0x49, 0xcf, 0x75, 0xc1, + 0x35, 0x8b, 0x96, 0x7e, 0x2f, 0x6e, 0xac, 0x2c, 0x9d, 0x13, 0xbe, 0x5e, + 0x34, 0x8b, 0xcf, 0xf1, 0xfb, 0xd8, 0x1b, 0x81, 0xc4, 0xd5, 0x02, 0x3e, + 0x24, 0x33, 0x9f, 0x7d, 0x38, 0x1c, 0xa2, 0xf9, 0x09, 0x79, 0xa9, 0x5d, + 0xa2, 0x23, 0xa8, 0x2d, 0x81, 0xd8, 0x23, 0x4d, 0xd1, 0x71, 0xc1, 0x73, + 0x87, 0x19, 0xf1, 0x25, 0x81, 0x33, 0x32, 0xb3, 0x36, 0xf6, 0xe4, 0x0f, + 0x75, 0x4e, 0x3b, 0x12, 0x83, 0xfb, 0x14, 0x60, 0xa9, 0x0e, 0xcd, 0x17, + 0xf4, 0xe9, 0x01, 0x90, 0x41, 0xbe, 0xa7, 0x2a, 0xae, 0xf0, 0xda, 0x7a, + 0x89, 0x6e, 0x9b, 0xee, 0x57, 0x95, 0x2d, 0x8f, 0x44, 0xe6, 0xa6, 0x77, + 0x76, 0x1d, 0xe4, 0xb0, 0x01, 0xa7, 0x64, 0x21, 0x95, 0x02, 0x40, 0x33, + 0xf0, 0xa4, 0xff, 0x11, 0xea, 0x6a, 0xce, 0xdc, 0xc6, 0x45, 0x5c, 0x4d, + 0xe9, 0xb1, 0x2d, 0xae, 0x64, 0xc6, 0xfb, 0x59, 0x95, 0x8f, 0xa0, 0xad, + 0x5d, 0x4c, 0x0e, 0x26, 0x90, 0x29, 0x48, 0x4c, 0xaf, 0xea, 0x99, 0x8a, + 0x82, 0x67, 0x12, 0x8e, 0x3c, 0xab, 0x9f, 0x5c, 0x11, 0x78, 0xf3, 0x69, + 0xb8, 0x34, 0x68, 0x26, 0xcc, 0xa7, 0x59, 0xe1, 0xa3, 0x50, 0x22, 0x03, + 0x37, 0xed, 0xf1, 0xd4, 0x0c, 0x0b, 0x55, 0x04, 0xfb, 0xe6, 0xc3, 0x3f, + 0xf9, 0xb7, 0x96, 0x3d, 0x7b, 0xb3, 0x4d, 0x9c, 0x11, 0xfe, 0xf6, 0x7c, + 0x6a, 0x6a, 0x3f, 0x5e, 0xff, 0x1f, 0xfb, 0x21, 0x0a, 0x26, 0xdb, 0xb9, + 0xfd, 0xf1, 0x69, 0xe1, 0x51, 0x3c, 0x54, 0xd3, 0x51, 0xf3, 0x3a, 0xdb, + 0xe8, 0x59, 0xb6, 0x3b, 0x6c, 0x11, 0x08, 0x63, 0xd3, 0x5c, 0x6b, 0x7e, + 0x98, 0xff, 0xae, 0x2d, 0xe6, 0xd3, 0x85, 0xaf, 0x77, 0xfc, 0xbc, 0x0e, + 0xa0, 0xeb, 0x3b, 0x9d, 0x70, 0x2f, 0x83, 0x8b, 0xd4, 0x6a, 0xc6, 0x6c, + 0x7e, 0xb0, 0xb3, 0x94, 0xc3, 0x44, 0x93, 0x71, 0xf1, 0x5a, 0x0a, 0x19, + 0xe3, 0x03, 0x11, 0x10, 0x00, 0x83, 0x57, 0xba, 0xd3, 0x8c, 0x10, 0x59, + 0x9e, 0xaf, 0xbc, 0x85, 0xc9, 0x62, 0x01, 0x16, 0x1f, 0x8b, 0x0f, 0xff, + 0x22, 0x28, 0x07, 0xca, 0xde, 0x0b, 0x62, 0x18, 0xf1, 0xdd, 0xd8, 0xe8, + 0xbf, 0x64, 0x81, 0xc4, 0x69, 0x98, 0x3c, 0x46, 0xae, 0x12, 0xaf, 0xda, + 0x6c, 0x1d, 0xb2, 0xce, 0xc2, 0x99, 0x07, 0x0c, 0x5e, 0x22, 0x0a, 0x2e, + 0xe6, 0x56, 0x89, 0x0a, 0xdb, 0xc4, 0xd0, 0xfb, 0xc3, 0x3a, 0x30, 0xfb, + 0xb0, 0x20, 0x56, 0xcb, 0x69, 0xc5, 0x70, 0x21, 0xd2, 0xec, 0x01, 0xfd, + 0x02, 0x6d, 0x44, 0x16, 0xbe, 0x99, 0x97, 0x64, 0xd7, 0xf6, 0x94, 0x0e, + 0xf0, 0xa9, 0x24, 0x90, 0x03, 0xcf, 0xd0, 0xc5, 0x4b, 0x10, 0xca, 0x2f, + 0xc5, 0x94, 0x56, 0x9a, 0x97, 0x3d, 0x70, 0xd4, 0x8a, 0xa4, 0x40, 0x37, + 0xfa, 0xa5, 0xf5, 0x8f, 0x2a, 0x57, 0x6f, 0x1c, 0x28, 0x5a, 0x79, 0xce, + 0x54, 0x0c, 0xe0, 0x4b, 0x17, 0x50, 0x33, 0xfc, 0xa1, 0xb7, 0x86, 0x5e, + 0x10, 0x30, 0x1d, 0xdf, 0x6d, 0xae, 0x71, 0xc2, 0xe1, 0xd5, 0xa9, 0xcc, + 0xcd, 0xc0, 0x4d, 0x2a, 0xa2, 0xa5, 0x59, 0x04, 0x6c, 0x89, 0x92, 0x21, + 0x2e, 0x87, 0xb9, 0xe2, 0xa7, 0xf9, 0x1d, 0xe6, 0x1c, 0x58, 0x88, 0x8e, + 0xf0, 0xd1, 0x8f, 0x7d, 0xe5, 0x4f, 0x4d, 0x12, 0x26, 0xc3, 0xd2, 0x2e, + 0x77, 0x72, 0x33, 0xd4, 0x19, 0x1d, 0x6c, 0x35, 0x8f, 0xde, 0x2d, 0x6c, + 0x70, 0xdc, 0xca, 0x98, 0x78, 0x30, 0xc6, 0xad, 0x70, 0xa3, 0x1d, 0x9b, + 0x9e, 0x4a, 0xf7, 0x27, 0x63, 0x8d, 0x58, 0x2c, 0x4f, 0xac, 0x3d, 0xfe, + 0x0a, 0x88, 0xc6, 0x41, 0x0d, 0x4a, 0xda, 0xfb, 0xff, 0x58, 0x9a, 0x8e, + 0x28, 0x72, 0xf7, 0x8f, 0x06, 0xde, 0x60, 0xc2, 0xe5, 0x84, 0x39, 0x2e, + 0xeb, 0x70, 0x23, 0x06, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x22, 0x05, 0xe9, 0xb3, 0xed, 0x3f, 0x98, 0x4c, 0x54, 0xbe, 0xd8, 0x12, + 0x95, 0x9d, 0x51, 0x72, 0x47, 0xf8, 0xdf, 0x7e, 0x61, 0x22, 0x09, 0x5a, + 0x13, 0x6f, 0x4a, 0x6b, 0x26, 0xcd, 0x60, 0x25, 0x44, 0x77, 0x64, 0x02, + 0x11, 0xe3, 0x9a, 0x5e, 0x9a, 0xb9, 0xd5, 0x2b, 0x98, 0x64, 0x5b, 0xca, + 0x78, 0x44, 0xb1, 0x5b, 0xfe, 0xca, 0xa9, 0x84, 0xf1, 0x82, 0xe0, 0x34, + 0x49, 0x0d, 0x64, 0x03, 0x58, 0x4f, 0x43, 0x69, 0xd8, 0xbd, 0x1e, 0x4c, + 0x94, 0x71, 0x1f, 0xc5, 0x6b, 0x05, 0x4a, 0x70, 0x39, 0xa8, 0xe3, 0x95, + 0x42, 0x54, 0x6f, 0xdc, 0xf1, 0xb0, 0xed, 0x6a, 0xd9, 0xfe, 0xeb, 0x24, + 0xcc, 0x4e, 0x35, 0x46, 0xd3, 0xdd, 0x19, 0x7d, 0xb5, 0x96, 0xd4, 0xf5, + 0x7e, 0x09, 0x92, 0x24, 0x94, 0xd8, 0x02, 0x25, 0x35, 0xc2, 0x6e, 0x83, + 0xbf, 0x5b, 0x13, 0x9a, 0x7b, 0x0e, 0x4e, 0x1a, 0xbf, 0xb5, 0xe6, 0x9f, + 0x08, 0xb7, 0x31, 0x60, 0xb6, 0x6a, 0xa0, 0xe7, 0xa3, 0x17, 0x5e, 0xc5, + 0xae, 0x03, 0x2f, 0x83, 0x8b, 0x59, 0x91, 0x48, 0x7d, 0x9d, 0x6f, 0x92, + 0x1a, 0x9c, 0x72, 0x1e, 0x98, 0xa9, 0x2a, 0xfa, 0xad, 0x99, 0x0b, 0xbd, + 0x8a, 0x0b, 0x2c, 0x90, 0x22, 0x30, 0xb4, 0x57, 0x29, 0x88, 0x9e, 0xd0, + 0x56, 0x21, 0x17, 0xec, 0x06, 0x22, 0x7a, 0xfa, 0xef, 0x8b, 0x56, 0x16, + 0xd0, 0xb4, 0x34, 0x70, 0x03, 0x8f, 0x50, 0xb7, 0x39, 0x15, 0x69, 0xd5, + 0xdc, 0xfa, 0x60, 0xc9, 0x1e, 0x4c, 0x60, 0x60, 0x4c, 0xee, 0xd9, 0x18, + 0xec, 0x53, 0xeb, 0x80, 0x18, 0x51, 0x76, 0x27, 0x71, 0xcc, 0xbd, 0x26, + 0x4e, 0x51, 0x9d, 0x67, 0xbc, 0x7f, 0x18, 0x99, 0x25, 0xf2, 0x62, 0x8c, + 0x9f, 0xaa, 0x59, 0x74, 0x0d, 0x2d, 0xce, 0x72, 0x40, 0xe3, 0xce, 0x58, + 0x95, 0xfd, 0xd7, 0x0a, 0xc7, 0x08, 0x51, 0xc3, 0x8f, 0x88, 0x77, 0xea, + 0x04, 0xee, 0x4c, 0x5a, 0x4e, 0x86, 0x9d, 0xa7, 0xb5, 0x74, 0x61, 0xef, + 0x8a, 0xd8, 0x91, 0xbf, 0x91, 0xf0, 0xaa, 0x93, 0x42, 0xb0, 0x27, 0x12, + 0x80, 0x83, 0x4a, 0x7b, 0x71, 0xe5, 0x27, 0x55, 0x3a, 0x68, 0x99, 0xe5, + 0xe2, 0x10, 0xe3, 0xe2, 0x07, 0xb5, 0xde, 0x94, 0x64, 0x88, 0x2f, 0x2b, + 0xc8, 0xe2, 0x29, 0x11, 0x4c, 0x9a, 0xb2, 0x2d, 0x81, 0xf8, 0xcc, 0x86, + 0x77, 0x17, 0xad, 0x77, 0x19, 0x0c, 0x4f, 0x2d, 0x9e, 0xba, 0x8a, 0x54, + 0x83, 0x59, 0x8a, 0x5d, 0x43, 0x05, 0x07, 0x8d, 0x73, 0xa4, 0xcb, 0xbc, + 0xcc, 0xee, 0x35, 0x21, 0xee, 0xa5, 0x4f, 0x49, 0x34, 0x6d, 0xea, 0x24, + 0x4d, 0xce, 0xd8, 0xa2, 0xc7, 0xbc, 0xdb, 0x8e, 0x93, 0xe9, 0xca, 0xec, + 0xd5, 0x60, 0x7a, 0x0c, 0x29, 0xfb, 0x70, 0x41, 0xa4, 0x78, 0x50, 0x2f, + 0x78, 0x41, 0x3a, 0x8f, 0x29, 0x63, 0xdf, 0xa9, 0xbb, 0x65, 0x42, 0xd2, + 0x14, 0x01, 0x86, 0x86, 0x36, 0xff, 0xd1, 0x97, 0x6a, 0x21, 0x32, 0xe8, + 0x01, 0x6d, 0x13, 0xd7, 0x2b, 0x5d, 0xfb, 0x25, 0xb3, 0xe5, 0xe0, 0xad, + 0x71, 0xdc, 0xd0, 0x99, 0x27, 0x4f, 0xfe, 0xe2, 0x3e, 0xda, 0x33, 0xec, + 0x52, 0x7c, 0xc6, 0xf5, 0x5a, 0x2c, 0x1d, 0x1d, 0xe6, 0xeb, 0xe4, 0x25, + 0xec, 0x97, 0x6a, 0x10, 0xc8, 0x24, 0xbe, 0x43, 0xc4, 0x9b, 0xbd, 0xdb, + 0x94, 0x18, 0xc7, 0x87, 0xef, 0x33, 0xa7, 0x8f, 0x03, 0x23, 0x99, 0xb8, + 0x80, 0xdc, 0x42, 0x9d, 0x9d, 0x72, 0xa0, 0xec, 0xf0, 0x25, 0x77, 0x10, + 0xf2, 0x0a, 0xb8, 0x2b, 0x29, 0x18, 0xf9, 0xcc, 0xa5, 0x39, 0x0a, 0x2a, + 0x8a, 0xe7, 0x71, 0xfc, 0xbf, 0xce, 0x45, 0xb9, 0x81, 0xa7, 0xc2, 0xa2, + 0x31, 0xbb, 0x9c, 0x2b, 0xe3, 0xb1, 0xa2, 0x09, 0x26, 0xe4, 0x2d, 0x31, + 0x27, 0xf4, 0xe5, 0x63, 0x72, 0xf6, 0xd9, 0x71, 0x1d, 0xa5, 0x6b, 0xee, + 0xcf, 0x38, 0x10, 0x53, 0x95, 0x6c, 0x01, 0x85, 0x5d, 0x15, 0xe2, 0xa7, + 0x2a, 0xd0, 0x1f, 0x05, 0xea, 0x1d, 0x6e, 0x18, 0x08, 0xb1, 0xd7, 0xbf, + 0xf7, 0x17, 0x12, 0xc1, 0xb4, 0x6c, 0x3a, 0x78, 0xfd, 0xb6, 0x2c, 0xeb, + 0x3c, 0x8e, 0x53, 0x26, 0xcc, 0x78, 0x96, 0x22, 0xf1, 0xd8, 0x70, 0x03, + 0x6d, 0x51, 0xfc, 0x5a, 0x96, 0xd6, 0x3b, 0x0c, 0x8e, 0x6d, 0x6d, 0xd0, + 0x2b, 0x55, 0x7a, 0x04, 0x10, 0xb3, 0x6c, 0x3f, 0x98, 0x18, 0x68, 0xc5, + 0x93, 0xb1, 0xd7, 0x27, 0x69, 0x31, 0x5a, 0x28, 0xc1, 0xed, 0xd9, 0xb3, + 0x01, 0x62, 0x50, 0x00, 0x54, 0x12, 0x94, 0x11, 0x45, 0x15, 0x4e, 0xad, + 0x23, 0x97, 0x0a, 0xf1, 0x8a, 0x19, 0x30, 0xf2, 0x6a, 0x75, 0x09, 0x38, + 0x4e, 0xaf, 0x6a, 0x03, 0x02, 0x8e, 0x14, 0x01, 0xcb, 0xa8, 0xf7, 0xb5, + 0x00, 0x57, 0x08, 0x05, 0x20, 0xaf, 0xff, 0xf2, 0xc5, 0x74, 0xdc, 0x21, + 0xbb, 0xab, 0x2f, 0x24, 0xa4, 0xcd, 0x60, 0xe9, 0x5e, 0xdd, 0x9c, 0x13, + 0x82, 0x88, 0xfd, 0x4c, 0xf9, 0xc6, 0x0d, 0x0e, 0xdc, 0xfb, 0x15, 0x0e, + 0x12, 0xee, 0xbd, 0x09, 0x5b, 0xa4, 0x7e, 0xf1, 0xef, 0x8e, 0x6a, 0x9e, + 0xd1, 0xa9, 0x44, 0x9a, 0x28, 0x3f, 0xec, 0x0d, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xe5, 0x63, 0x7f, 0xa4, 0x85, 0x80, 0x73, 0xfe, + 0xdd, 0x80, 0x4a, 0x58, 0xa7, 0xfe, 0x98, 0x9a, 0x80, 0x8d, 0x07, 0x3d, + 0xa1, 0x03, 0xfd, 0xdd, 0x07, 0xbc, 0xcd, 0xc7, 0x6f, 0x22, 0xbe, 0x26, + 0xa3, 0x00, 0x10, 0x21, 0x2b, 0x12, 0x23, 0xf0, 0x66, 0x0c, 0x94, 0x5d, + 0xe3, 0x66, 0x35, 0x82, 0x1b, 0x35, 0x2b, 0x89, 0x1f, 0xfc, 0x6d, 0xed, + 0x95, 0xec, 0x79, 0xb9, 0x5a, 0xcf, 0xbc, 0x18, 0x7d, 0xb3, 0xad, 0x8d, + 0x69, 0x6e, 0x44, 0xfa, 0xcc, 0xfa, 0x67, 0x4a, 0x4f, 0xe0, 0xf5, 0xfa, + 0x7b, 0xe3, 0x39, 0x03, 0xb9, 0x00, 0xc7, 0xea, 0x55, 0x96, 0x4a, 0x32, + 0x1a, 0xa3, 0x30, 0x05, 0x0a, 0x24, 0xbd, 0xc2, 0xc8, 0xdb, 0x8c, 0xcc, + 0x59, 0x0f, 0x91, 0xba, 0xfc, 0x50, 0x40, 0xf6, 0xa4, 0xaa, 0x7e, 0xc0, + 0x0f, 0xc6, 0x45, 0xe1, 0x76, 0xa5, 0xba, 0x61, 0x78, 0x43, 0xb7, 0x1b, + 0x8e, 0xbb, 0x42, 0x17, 0x15, 0xed, 0xb4, 0xc5, 0xd7, 0x48, 0x7c, 0x3f, + 0x30, 0x2e, 0x19, 0xd1, 0x37, 0xe8, 0xa0, 0xcb, 0xb2, 0x26, 0x1c, 0x67, + 0x4c, 0x36, 0x42, 0xf9, 0x37, 0xb9, 0x75, 0x2d, 0x5f, 0x95, 0xbe, 0x8b, + 0x9f, 0x3b, 0x6e, 0x16, 0xdc, 0xdd, 0x49, 0xd2, 0x52, 0xac, 0x38, 0xbb, + 0x2d, 0x9a, 0xfc, 0x17, 0x9e, 0x4f, 0xb6, 0xac, 0x7c, 0x20, 0x2e, 0x46, + 0x01, 0x8f, 0xf1, 0x06, 0x41, 0x16, 0xe2, 0x53, 0x49, 0x29, 0x13, 0x15, + 0x1b, 0x6b, 0x26, 0x58, 0x56, 0x37, 0x48, 0xb1, 0x71, 0x81, 0xd7, 0x18, + 0x81, 0x22, 0xe8, 0xaa, 0x4c, 0xa6, 0x0d, 0x02, 0xf2, 0x71, 0x6e, 0x07, + 0x70, 0x94, 0x9f, 0xef, 0x38, 0xad, 0x8c, 0x94, 0x8b, 0xc8, 0x8a, 0xbe, + 0x92, 0xb8, 0x0a, 0x08, 0x33, 0x15, 0x8f, 0x04, 0x87, 0x93, 0x2b, 0x69, + 0xb4, 0xfa, 0x7f, 0x12, 0x7d, 0xce, 0x60, 0x0b, 0x89, 0x00, 0x21, 0x6e, + 0x83, 0x23, 0x77, 0x2d, 0x00, 0x6b, 0xc5, 0xd3, 0xb8, 0xc8, 0x0a, 0x01, + 0x7d, 0xcc, 0x9e, 0x21, 0x14, 0x3c, 0x5d, 0x26, 0x11, 0x4b, 0xa9, 0xc9, + 0xae, 0xde, 0xe6, 0x0b, 0x32, 0xa6, 0xf8, 0xa0, 0x17, 0x08, 0x34, 0xdd, + 0x19, 0xd3, 0x2b, 0xbc, 0xc5, 0xef, 0xad, 0xdd, 0xb2, 0xc3, 0x5c, 0x4e, + 0x4d, 0x77, 0x7d, 0x33, 0x0c, 0x1a, 0x21, 0x73, 0xc3, 0x18, 0x21, 0x13, + 0x56, 0x1c, 0xd8, 0x68, 0xb4, 0xd0, 0x1d, 0xe6, 0xec, 0x77, 0xe5, 0x6d, + 0x73, 0x4e, 0x79, 0xac, 0x68, 0x44, 0x4a, 0x30, 0x77, 0xa2, 0x66, 0xf5, + 0x2e, 0x2e, 0x45, 0xfc, 0x5f, 0xfb, 0x45, 0x2c, 0xa9, 0x23, 0xe6, 0x43, + 0x82, 0xb3, 0x4d, 0xe1, 0xad, 0x24, 0x5b, 0x21, 0xed, 0xb4, 0x66, 0x52, + 0x6f, 0xb7, 0x3b, 0x1b, 0x10, 0x0b, 0x62, 0x8b, 0x47, 0x37, 0xb1, 0xdb, + 0x6a, 0xb8, 0x2c, 0x26, 0xd8, 0x69, 0x4a, 0x83, 0x6a, 0x3a, 0x64, 0xe9, + 0xe1, 0xdc, 0x50, 0x4b, 0x77, 0xf5, 0x8d, 0x21, 0x0a, 0xd9, 0x2b, 0xef, + 0x96, 0xa0, 0xda, 0xe9, 0xf7, 0x52, 0xf4, 0xc5, 0xf3, 0x7d, 0x47, 0x24, + 0xa2, 0x0e, 0x99, 0xc0, 0x49, 0xeb, 0x71, 0x90, 0x85, 0xe9, 0x06, 0xae, + 0xb0, 0xec, 0xc4, 0x8f, 0x3f, 0x4a, 0xe3, 0x24, 0x9a, 0x1b, 0xca, 0x17, + 0xc6, 0x1c, 0x76, 0x31, 0xf7, 0x5b, 0x42, 0x1c, 0xa5, 0x0b, 0xa7, 0x16, + 0x73, 0x29, 0xd0, 0xc5, 0x44, 0xd6, 0xee, 0xa8, 0x35, 0x83, 0xb2, 0x8f, + 0xea, 0x3a, 0x6f, 0x2f, 0xff, 0x0a, 0x60, 0x2b, 0x71, 0xa0, 0x7c, 0x1f, + 0x66, 0x2e, 0xb0, 0x22, 0x96, 0x65, 0x31, 0x48, 0xf4, 0xce, 0x61, 0xc2, + 0x17, 0x3a, 0x1a, 0x5d, 0x5e, 0x49, 0xf7, 0x30, 0x1a, 0x85, 0x27, 0xef, + 0x31, 0xd5, 0xb0, 0x02, 0xa3, 0x35, 0xa8, 0x7c, 0x3f, 0x12, 0x5b, 0x1e, + 0x90, 0x28, 0x6e, 0xe4, 0x41, 0xf7, 0x87, 0xfa, 0x3d, 0xa0, 0x1a, 0x4a, + 0xc5, 0x5a, 0xb0, 0x63, 0xde, 0x6d, 0x1a, 0xe4, 0x02, 0xc1, 0x03, 0x68, + 0x4d, 0xab, 0x1d, 0xc8, 0xa2, 0x3d, 0x1c, 0x08, 0x35, 0x9d, 0x3d, 0xeb, + 0xc9, 0x29, 0xef, 0xd1, 0xad, 0x3e, 0xea, 0x9e, 0x76, 0x53, 0x06, 0xb3, + 0xaa, 0xba, 0x2c, 0xe3, 0x57, 0xaa, 0x32, 0x2c, 0x38, 0x37, 0xd5, 0x20, + 0xe6, 0xb6, 0x0b, 0x16, 0x5c, 0xc4, 0x20, 0x1b, 0x70, 0x11, 0x59, 0x5d, + 0xc7, 0x96, 0x48, 0xd3, 0x9e, 0xa2, 0xe8, 0x99, 0x08, 0x3b, 0x6a, 0xfb, + 0xda, 0x1c, 0x63, 0xf6, 0xc5, 0x6e, 0xc6, 0x79, 0xe5, 0x74, 0xe1, 0x25, + 0xac, 0x63, 0x0f, 0x5b, 0x0e, 0xf9, 0x8b, 0xfe, 0x15, 0x99, 0x43, 0x51, + 0x19, 0x8b, 0x94, 0x9c, 0x4a, 0x29, 0x90, 0xab, 0x64, 0x4e, 0xbf, 0x63, + 0xd8, 0x33, 0x98, 0xd6, 0xc2, 0xed, 0xc3, 0x2e, 0xc0, 0xdd, 0x63, 0xa8, + 0x16, 0xe6, 0x9f, 0x92, 0x74, 0x7e, 0x75, 0xd9, 0x6b, 0x00, 0x21, 0x29, + 0x73, 0xd1, 0xa6, 0x18, 0xbf, 0xea, 0x1f, 0xdc, 0xa8, 0x80, 0x1f, 0x25, + 0xd0, 0xf0, 0x50, 0x1d, 0x66, 0x96, 0x71, 0xa1, 0x38, 0x2f, 0x8b, 0x08, + 0x43, 0x59, 0x2e, 0xe4, 0xb1, 0x87, 0xa6, 0x79, 0x19, 0xe7, 0xcb, 0x46, + 0x64, 0x39, 0xdd, 0x3e, 0x21, 0xa2, 0xd6, 0xd4, 0x5d, 0xa8, 0x81, 0x02, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x90, 0x09, 0x21, 0xd8, + 0x67, 0xbc, 0x94, 0xf1, 0x9e, 0x75, 0x82, 0x54, 0x70, 0x47, 0xb7, 0x21, + 0xe7, 0x47, 0xca, 0x20, 0xd0, 0xd9, 0x96, 0x70, 0xa5, 0xad, 0x95, 0xa2, + 0x6b, 0xbd, 0xca, 0x2c, 0xe2, 0x08, 0xde, 0xc3, 0xdd, 0x84, 0x3c, 0xa7, + 0x74, 0x5d, 0x44, 0x01, 0xde, 0x24, 0x8c, 0xc6, 0xde, 0x78, 0x27, 0xd1, + 0x90, 0xce, 0x2c, 0x90, 0xfa, 0xff, 0xe2, 0xb4, 0x05, 0xc3, 0x7d, 0x15, + 0x59, 0x12, 0xa0, 0x9d, 0xae, 0x4e, 0xf1, 0x62, 0x3f, 0x96, 0xc4, 0x4c, + 0x56, 0x7e, 0xb7, 0xd2, 0x37, 0x69, 0xd2, 0x66, 0xd2, 0xae, 0x24, 0xac, + 0x57, 0xae, 0x57, 0xab, 0x19, 0x44, 0x00, 0x16, 0x2f, 0xf2, 0x90, 0xee, + 0x52, 0xa7, 0x37, 0xd9, 0x54, 0x5e, 0xf4, 0xd7, 0x74, 0xe5, 0xb8, 0x8e, + 0xeb, 0x21, 0x0d, 0xdf, 0x3a, 0x0f, 0x96, 0x84, 0x9d, 0x1e, 0xd9, 0x4b, + 0xe1, 0x0c, 0x6e, 0x11, 0xe6, 0x55, 0xc8, 0x46, 0xa6, 0x4a, 0x9f, 0x2a, + 0x1f, 0x53, 0x44, 0xb2, 0x34, 0xe8, 0x15, 0x68, 0xe9, 0x81, 0x21, 0x8d, + 0xba, 0x12, 0x4c, 0x3e, 0x31, 0x52, 0xc1, 0x83, 0x92, 0xd3, 0x55, 0x1c, + 0x42, 0xd2, 0x83, 0x43, 0x1d, 0x42, 0x72, 0x12, 0x5c, 0x45, 0xb5, 0x5b, + 0xc1, 0xd3, 0x9c, 0xdb, 0x34, 0xf4, 0x48, 0x7c, 0xce, 0x1b, 0x2a, 0x59, + 0x58, 0x6a, 0xf1, 0x9f, 0x65, 0x3e, 0x92, 0x1f, 0x1a, 0x29, 0x4b, 0x75, + 0xb0, 0x37, 0x59, 0xe4, 0x78, 0xea, 0x19, 0x25, 0x1c, 0xfe, 0xe1, 0x65, + 0x4f, 0xf5, 0x21, 0x41, 0xcd, 0x89, 0xf0, 0x01, 0x10, 0x2a, 0x45, 0xf0, + 0x67, 0x03, 0x3f, 0x21, 0x4c, 0x6d, 0x20, 0x89, 0x96, 0xa1, 0x0a, 0xdf, + 0x48, 0xb5, 0x5a, 0x42, 0xe4, 0x89, 0x60, 0x61, 0xbd, 0xe5, 0x16, 0x17, + 0xf7, 0x69, 0xbb, 0x14, 0x1d, 0x7c, 0x4a, 0xab, 0x8d, 0xcd, 0xe7, 0x1a, + 0x28, 0x91, 0xc0, 0x23, 0x20, 0x34, 0xc6, 0x7f, 0x5a, 0x3d, 0x71, 0x92, + 0xfe, 0x8c, 0xbf, 0x09, 0xcf, 0x69, 0x2f, 0x84, 0x18, 0xbe, 0x1a, 0x49, + 0x6e, 0x4d, 0x32, 0xfa, 0x2e, 0x04, 0xb8, 0x02, 0x81, 0x2d, 0xf6, 0xfe, + 0xb3, 0x06, 0x33, 0xda, 0x9e, 0x0f, 0x87, 0x67, 0xd1, 0x1d, 0x07, 0x3a, + 0xf1, 0x84, 0x66, 0x67, 0x1b, 0x8d, 0x48, 0x59, 0xc6, 0xf1, 0x0b, 0x0c, + 0x1f, 0xd8, 0x07, 0x13, 0xb1, 0xe3, 0x6a, 0x36, 0x74, 0x1c, 0x96, 0x61, + 0xfd, 0x92, 0x44, 0xa7, 0x15, 0x34, 0x7a, 0xef, 0x29, 0x4a, 0x7d, 0xb3, + 0x7f, 0x57, 0xfe, 0xe8, 0xaf, 0x23, 0xaf, 0x2a, 0x1b, 0x0a, 0x00, 0x29, + 0x6f, 0x30, 0xad, 0x93, 0x69, 0x1b, 0x4a, 0xa6, 0x22, 0xfa, 0x54, 0x93, + 0xf0, 0x50, 0x4a, 0x6d, 0xdf, 0x2a, 0xf9, 0x33, 0xa5, 0x68, 0x8f, 0xee, + 0xa7, 0x67, 0x05, 0xc6, 0x8a, 0xfd, 0x00, 0x12, 0xe7, 0xf0, 0x85, 0x7c, + 0xfe, 0x6c, 0xe4, 0x3f, 0x67, 0xe0, 0xca, 0x0b, 0xb0, 0x33, 0x56, 0x21, + 0x92, 0x63, 0xdc, 0x10, 0xd9, 0xe2, 0x98, 0x1d, 0xc6, 0x36, 0x89, 0x44, + 0xd0, 0x30, 0x82, 0x2f, 0xbd, 0xb2, 0x19, 0x6b, 0x88, 0x6c, 0x3d, 0xff, + 0x5f, 0x5c, 0x48, 0x31, 0x2b, 0x76, 0x5e, 0xb0, 0x09, 0x30, 0x46, 0xa2, + 0xd9, 0x55, 0x01, 0x2b, 0x59, 0xf7, 0x6e, 0x06, 0x59, 0x55, 0x71, 0x25, + 0x3c, 0x10, 0xa7, 0x37, 0xd4, 0x2b, 0xfa, 0x78, 0xe5, 0xc9, 0x5f, 0x5c, + 0x1b, 0xe6, 0x27, 0x54, 0x05, 0xc2, 0xd7, 0xa1, 0x4b, 0x8d, 0xe9, 0x10, + 0x6b, 0x1c, 0x95, 0x5b, 0x83, 0xd0, 0x39, 0x1b, 0x34, 0x43, 0x6f, 0x76, + 0xab, 0x26, 0x0a, 0x8f, 0xce, 0x93, 0x56, 0xe6, 0xdc, 0xb9, 0x1d, 0xa7, + 0x68, 0xab, 0x7b, 0x2c, 0xbf, 0xd5, 0x14, 0x92, 0x6e, 0x4a, 0xec, 0x7f, + 0x54, 0xbc, 0x74, 0x0a, 0x45, 0xa6, 0x38, 0xfa, 0x67, 0x49, 0x40, 0x08, + 0x4f, 0x43, 0x48, 0xa0, 0x9d, 0xcd, 0x55, 0xcf, 0x90, 0x6f, 0xd6, 0x43, + 0x78, 0xf2, 0xec, 0x82, 0xd1, 0x24, 0x36, 0xc5, 0xe2, 0x42, 0x4d, 0x1d, + 0x49, 0x90, 0x47, 0x1e, 0xc2, 0xfc, 0xab, 0x83, 0xed, 0x53, 0x0e, 0x86, + 0xd3, 0x8d, 0x15, 0x37, 0xbd, 0xbc, 0x02, 0x10, 0x2d, 0x79, 0xf5, 0xed, + 0x8a, 0x5e, 0xfb, 0xb2, 0xf9, 0x87, 0xd5, 0x14, 0x54, 0x5d, 0xf7, 0x70, + 0xc8, 0x5e, 0xae, 0x86, 0x4b, 0x87, 0x08, 0x06, 0xe6, 0xac, 0xa9, 0xea, + 0x47, 0x1d, 0xc0, 0x4d, 0xbf, 0x95, 0x3e, 0x12, 0xcd, 0x63, 0x55, 0x53, + 0xb1, 0x2e, 0x9b, 0x03, 0x79, 0xbc, 0xe3, 0x0c, 0xc1, 0xa1, 0x7f, 0x68, + 0xc2, 0xc1, 0xc3, 0x99, 0x7c, 0xe1, 0xbf, 0xbb, 0x3b, 0x91, 0x66, 0x18, + 0x52, 0x7e, 0x5a, 0xe8, 0xfc, 0xdf, 0x91, 0x1d, 0x1d, 0xb0, 0xbd, 0x29, + 0x23, 0xbc, 0x6f, 0xaf, 0xd4, 0xcd, 0xd1, 0xd4, 0xb3, 0x02, 0x1d, 0x48, + 0x57, 0xee, 0x2b, 0xda, 0xee, 0x5e, 0xd4, 0x3a, 0x99, 0x01, 0xf3, 0xf0, + 0xfd, 0x18, 0x70, 0xba, 0x4d, 0x72, 0x87, 0x2a, 0x97, 0x92, 0x52, 0xff, + 0x9d, 0xcf, 0xb9, 0xec, 0x92, 0x1e, 0x12, 0xb1, 0xe3, 0x70, 0xf2, 0x9d, + 0xa8, 0xa0, 0xe5, 0x99, 0x9c, 0xe3, 0x61, 0x6b, 0x48, 0xf8, 0x84, 0x6e, + 0xa9, 0xa9, 0xdc, 0x2f, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x1e, 0x3c, 0xca, 0x89, 0x80, 0xab, 0x40, 0x13, 0xe8, 0x7f, 0x86, 0xec, + 0x18, 0xee, 0x84, 0x40, 0x68, 0x44, 0xbb, 0x55, 0x5d, 0x57, 0x8f, 0x74, + 0xd4, 0x5f, 0x1e, 0x84, 0x54, 0xe4, 0x7c, 0x1f, 0xdc, 0x29, 0xa1, 0x93, + 0xd1, 0x35, 0x7b, 0x4d, 0x03, 0x52, 0xae, 0x80, 0x85, 0xc7, 0x3f, 0xc8, + 0x99, 0x63, 0xdb, 0xd5, 0xe8, 0xec, 0x91, 0xfd, 0xb2, 0x88, 0x3e, 0xf8, + 0xb9, 0x8f, 0x83, 0x12, 0x1d, 0x5f, 0x69, 0x09, 0x9f, 0xc4, 0x60, 0x98, + 0xe2, 0x23, 0x54, 0xde, 0x07, 0x37, 0xe7, 0xa4, 0xc7, 0x16, 0x65, 0xea, + 0x3d, 0xde, 0x74, 0xf9, 0x46, 0x37, 0x52, 0xe8, 0x99, 0x8a, 0x24, 0x1f, + 0x3c, 0xaa, 0xe3, 0xaf, 0xf7, 0x80, 0x3c, 0x1b, 0xc3, 0xe9, 0x09, 0x58, + 0xde, 0x4f, 0x90, 0xef, 0xc9, 0x9a, 0x7e, 0xea, 0xb7, 0x22, 0x41, 0x20, + 0xe6, 0xde, 0xfd, 0x2a, 0x77, 0xb9, 0x34, 0x07, 0x44, 0x06, 0xf3, 0x59, + 0x3c, 0x02, 0xa0, 0x32, 0xcd, 0xf6, 0x27, 0x44, 0x14, 0xfc, 0x4a, 0xfd, + 0xbc, 0xc0, 0xf6, 0x6b, 0xbf, 0x4a, 0x86, 0xc5, 0x0d, 0xc4, 0x32, 0xbf, + 0x44, 0xf4, 0xa1, 0x01, 0x77, 0x31, 0x0c, 0x6a, 0x0b, 0xb6, 0xb8, 0x92, + 0xdd, 0x29, 0x2d, 0x12, 0xf5, 0xa1, 0xb3, 0xba, 0x91, 0x97, 0x7c, 0x59, + 0x2c, 0xf3, 0x03, 0x3a, 0x52, 0x73, 0xa9, 0x7b, 0xce, 0x29, 0x07, 0x30, + 0xdb, 0xa3, 0x3c, 0x6f, 0x19, 0x99, 0x5b, 0xb5, 0x16, 0x23, 0x33, 0x7f, + 0x61, 0x58, 0xc1, 0x71, 0x6a, 0x23, 0xe8, 0x2b, 0xb4, 0x69, 0xa5, 0x65, + 0x3b, 0xaa, 0x8d, 0xbf, 0x8d, 0x82, 0x13, 0x08, 0xf5, 0xe8, 0xa4, 0xab, + 0xa2, 0x09, 0xb9, 0x1e, 0x55, 0x01, 0x77, 0x02, 0x43, 0x12, 0x18, 0xe7, + 0x8d, 0x8d, 0xc7, 0x62, 0x5d, 0xf7, 0xb3, 0x85, 0x4f, 0xc1, 0x40, 0x08, + 0xa3, 0x4e, 0xde, 0x17, 0x23, 0x8a, 0x47, 0x43, 0x95, 0xa9, 0x9c, 0x3c, + 0x40, 0x4a, 0xd9, 0xe2, 0xbd, 0xfc, 0xf3, 0xe6, 0xa0, 0xe6, 0xa7, 0xce, + 0xc7, 0x1a, 0x1f, 0xa1, 0xbd, 0xbe, 0xb0, 0xa5, 0xde, 0xc3, 0x4e, 0x27, + 0x99, 0xc5, 0xe7, 0x61, 0x1f, 0x9d, 0xc4, 0x35, 0xc6, 0x70, 0x45, 0x14, + 0xa5, 0x8f, 0x47, 0x0e, 0xe5, 0x55, 0xdd, 0x6f, 0xff, 0x86, 0x97, 0x74, + 0x70, 0x7a, 0x0e, 0xa7, 0x17, 0xd0, 0x68, 0x0e, 0x57, 0xe6, 0x27, 0xbf, + 0x76, 0x11, 0x3b, 0x37, 0x4c, 0x30, 0x41, 0x28, 0x62, 0x05, 0x37, 0x0e, + 0xbc, 0x0a, 0x18, 0x7d, 0xa0, 0x05, 0xaa, 0xc6, 0x2c, 0x81, 0xe3, 0xab, + 0x7a, 0xce, 0x18, 0x0e, 0x9a, 0xdd, 0xf9, 0xdd, 0x20, 0x1e, 0x03, 0x9c, + 0x01, 0x02, 0xc2, 0xcb, 0x87, 0x54, 0x8c, 0xed, 0xd6, 0x05, 0xbd, 0x8e, + 0x1f, 0x9e, 0x21, 0xf7, 0x1f, 0xad, 0xcd, 0xef, 0xc2, 0x8f, 0x3a, 0x18, + 0xfe, 0x80, 0x6a, 0xcb, 0x1a, 0xa7, 0x45, 0x37, 0x13, 0xa7, 0x98, 0xc0, + 0xfc, 0xf2, 0x95, 0x9a, 0x92, 0x58, 0x4b, 0x99, 0xe2, 0xe3, 0x8c, 0x65, + 0xf7, 0xc7, 0x73, 0xff, 0x2f, 0x60, 0x3a, 0x14, 0xcc, 0x82, 0x35, 0xbe, + 0xcf, 0x0b, 0xca, 0x56, 0x0d, 0x63, 0x16, 0xd6, 0x1f, 0xac, 0x6d, 0xd2, + 0xc9, 0x67, 0xe8, 0x18, 0x44, 0xb5, 0x5d, 0x20, 0x7d, 0x18, 0xe6, 0xa0, + 0xc7, 0x51, 0xaf, 0x0f, 0x1c, 0x18, 0x9c, 0x6d, 0x03, 0x10, 0x05, 0x11, + 0xc2, 0x56, 0xfa, 0x22, 0x10, 0x23, 0xc8, 0xc0, 0x02, 0x22, 0x3e, 0x86, + 0x99, 0x2e, 0x16, 0xf8, 0xd6, 0x66, 0xb2, 0xdc, 0xef, 0xbf, 0xea, 0x0e, + 0x43, 0xc6, 0xeb, 0xc7, 0xd8, 0x3a, 0x91, 0x30, 0xbb, 0xad, 0x4c, 0x36, + 0x9d, 0x96, 0xb7, 0x0b, 0xc2, 0x0d, 0xdc, 0x9e, 0x7a, 0x23, 0x94, 0xea, + 0x03, 0x98, 0xef, 0xd7, 0x79, 0xf2, 0x0a, 0x00, 0x6c, 0x62, 0x22, 0x37, + 0x67, 0xc7, 0x1e, 0x28, 0xe8, 0x0d, 0xb7, 0x45, 0xdb, 0x15, 0x92, 0xa3, + 0x30, 0x4b, 0xaf, 0xc3, 0x55, 0x4a, 0xe0, 0xa9, 0x60, 0x33, 0x98, 0x9a, + 0x32, 0xf9, 0x26, 0x18, 0x21, 0xa6, 0xeb, 0xff, 0x95, 0x53, 0x7b, 0xb6, + 0xd4, 0x68, 0x5f, 0xe4, 0x7d, 0xf4, 0xb8, 0x0c, 0xb3, 0x27, 0xbe, 0xb2, + 0xcb, 0xe1, 0x13, 0xff, 0xd2, 0xe9, 0x26, 0xeb, 0x7a, 0xe1, 0x08, 0x0c, + 0x79, 0xd2, 0xf1, 0x70, 0x9a, 0xd1, 0x7b, 0x6c, 0x7a, 0xfa, 0xa3, 0x8b, + 0xb0, 0x03, 0x1a, 0x42, 0x75, 0x64, 0xcc, 0x14, 0x41, 0x5d, 0x25, 0x34, + 0xac, 0x7b, 0xd9, 0xd2, 0x6c, 0x88, 0xec, 0x00, 0x57, 0x40, 0x75, 0xed, + 0x3f, 0x1b, 0x61, 0x60, 0xd2, 0x67, 0xc3, 0xb2, 0x97, 0x5a, 0x6c, 0x2d, + 0xf1, 0x85, 0x6b, 0x65, 0x7f, 0x45, 0x75, 0x53, 0x92, 0x4b, 0xeb, 0x75, + 0x13, 0x69, 0xa2, 0x2a, 0x7b, 0x35, 0xd1, 0xe5, 0x03, 0x60, 0xf7, 0x2e, + 0x5b, 0x67, 0xbc, 0x32, 0x15, 0x6f, 0x0b, 0x9b, 0xdb, 0x27, 0x9e, 0xbd, + 0xed, 0x1e, 0xe3, 0x31, 0x75, 0x41, 0x5d, 0x30, 0xbd, 0xd2, 0x0d, 0x06, + 0x5b, 0x43, 0x98, 0xa0, 0x34, 0xf2, 0x95, 0xa2, 0x8d, 0x2e, 0x5f, 0x91, + 0x43, 0xfe, 0x75, 0x90, 0x86, 0x2f, 0xc9, 0x6c, 0x09, 0x59, 0x60, 0x0a, + 0x1b, 0x73, 0xa0, 0xa3, 0x5f, 0x8e, 0xb9, 0x1c, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x7b, 0x15, 0x0d, 0x0e, 0xf0, 0x53, 0x2a, 0x17, + 0x43, 0x70, 0x3c, 0xb6, 0xaf, 0x2d, 0x15, 0x37, 0x42, 0x3c, 0xac, 0x63, + 0xf3, 0xaf, 0x14, 0x7f, 0xd6, 0xac, 0xd4, 0x9d, 0x80, 0x5a, 0x0d, 0x03, + 0x11, 0x8d, 0x4d, 0x3b, 0xda, 0xb1, 0x5e, 0x4f, 0x0f, 0x7f, 0x9e, 0x4b, + 0x0a, 0x37, 0x96, 0x9c, 0xb4, 0x67, 0x21, 0x2e, 0xed, 0x60, 0x9a, 0x58, + 0x1b, 0xa6, 0x63, 0x4d, 0x3f, 0x05, 0x1a, 0x00, 0x04, 0xe6, 0x97, 0x9c, + 0xa3, 0x69, 0xbd, 0xb4, 0x9e, 0xb4, 0xc5, 0x1c, 0x2c, 0xcc, 0x5c, 0xef, + 0xf3, 0xa4, 0xee, 0xf5, 0x5b, 0x93, 0x50, 0x98, 0x92, 0x1a, 0xa2, 0x3c, + 0x23, 0x82, 0xbf, 0x07, 0xec, 0x3b, 0x6a, 0x83, 0xe8, 0xcf, 0x4e, 0x74, + 0x87, 0xda, 0x7f, 0xaf, 0x17, 0xbe, 0xad, 0xe2, 0x56, 0x21, 0x6c, 0x14, + 0xfa, 0x45, 0xf9, 0xbc, 0x67, 0x16, 0x5b, 0x0f, 0x5f, 0x47, 0xdc, 0x05, + 0xb0, 0x23, 0xd2, 0xbb, 0x60, 0x82, 0x07, 0x72, 0x9f, 0x90, 0xef, 0x5a, + 0x51, 0xb9, 0xab, 0x2e, 0x9d, 0xcc, 0x36, 0x15, 0xeb, 0x5e, 0x82, 0x28, + 0x2d, 0x18, 0xd0, 0x1b, 0xba, 0x74, 0x5a, 0x15, 0xc0, 0xf6, 0xd1, 0xce, + 0x38, 0xa8, 0x12, 0xe3, 0x56, 0x43, 0xed, 0x9c, 0x48, 0xc8, 0xd9, 0x0f, + 0x96, 0x7e, 0x17, 0xde, 0x57, 0xcc, 0xfb, 0xd6, 0x56, 0xc4, 0x4a, 0x03, + 0xa2, 0x9d, 0x4a, 0x17, 0x51, 0x0a, 0x67, 0x55, 0x9e, 0xd7, 0x9e, 0xcf, + 0x81, 0x58, 0x69, 0xc1, 0x40, 0x1b, 0x57, 0x2e, 0xad, 0xcc, 0x0c, 0x19, + 0x83, 0x70, 0xbd, 0xc3, 0xad, 0x48, 0xd5, 0x39, 0x2a, 0xb8, 0x67, 0x0f, + 0x77, 0x5b, 0x41, 0xb3, 0x46, 0x3d, 0xb2, 0xa9, 0xbd, 0x9b, 0x26, 0x97, + 0x27, 0x08, 0xac, 0x4c, 0x09, 0x49, 0x3b, 0x49, 0x39, 0xac, 0x8e, 0xf7, + 0xe6, 0xd9, 0xab, 0x73, 0xa1, 0x23, 0xb0, 0x24, 0x03, 0xcf, 0x96, 0x2b, + 0xfb, 0x1c, 0xe3, 0xa6, 0x4c, 0x39, 0xe3, 0x02, 0x51, 0x30, 0x9b, 0xc9, + 0x69, 0x89, 0x40, 0x59, 0x38, 0x9d, 0xf0, 0xbc, 0xc2, 0x00, 0x29, 0xeb, + 0x73, 0x62, 0x38, 0x03, 0xbe, 0x4c, 0xc1, 0xe9, 0x1f, 0x46, 0x4f, 0x7e, + 0xe9, 0xc8, 0xc5, 0x53, 0x35, 0x29, 0x5e, 0x0c, 0xc2, 0x3c, 0xd4, 0x11, + 0x0a, 0x76, 0xa5, 0x6a, 0xb3, 0xec, 0x2c, 0x64, 0x06, 0x04, 0xa5, 0x0f, + 0xfa, 0xa5, 0xc8, 0xbd, 0xbf, 0x73, 0x01, 0x91, 0xbc, 0x20, 0x97, 0x6e, + 0x9e, 0x23, 0x81, 0x90, 0xd8, 0xec, 0x5f, 0xa5, 0x69, 0x7a, 0xae, 0x7d, + 0xcb, 0xc3, 0xa4, 0xa0, 0x73, 0x00, 0xc4, 0x04, 0x3b, 0x82, 0xc1, 0xb2, + 0xbb, 0xb9, 0x6f, 0xf0, 0x42, 0x8f, 0x56, 0x3f, 0x18, 0x52, 0x96, 0x54, + 0x60, 0x23, 0x39, 0x37, 0x26, 0x44, 0x0e, 0x9f, 0xb1, 0x89, 0xec, 0x9b, + 0x64, 0x93, 0xb7, 0x03, 0xe8, 0xd1, 0xd8, 0x8c, 0x00, 0x58, 0x41, 0x52, + 0xe7, 0x40, 0x89, 0x80, 0xe9, 0x6a, 0x57, 0x71, 0xfa, 0x48, 0xc8, 0xe4, + 0x41, 0x08, 0x48, 0xd1, 0x6e, 0x08, 0x25, 0x77, 0x42, 0x32, 0x01, 0x1e, + 0x26, 0xa7, 0xb8, 0xc5, 0x00, 0x98, 0xec, 0xb6, 0x1b, 0x23, 0x4d, 0xe9, + 0x2c, 0xd1, 0x97, 0x05, 0xc2, 0x1e, 0xa1, 0xb9, 0x37, 0xad, 0xf5, 0x20, + 0xb0, 0xd0, 0x00, 0x0d, 0x51, 0x1a, 0x6f, 0x2e, 0xb7, 0x95, 0xb6, 0x21, + 0x50, 0xca, 0xac, 0x6c, 0x98, 0x60, 0x7c, 0x70, 0xf4, 0x21, 0xb5, 0xfd, + 0xf4, 0xef, 0x7f, 0x41, 0x2c, 0x85, 0x91, 0xf9, 0xb5, 0x5d, 0x40, 0x20, + 0xfb, 0x22, 0x32, 0x17, 0x7d, 0xea, 0xb7, 0x35, 0x3a, 0x33, 0x0e, 0x73, + 0x52, 0xde, 0x8c, 0xf5, 0xd4, 0x99, 0xa8, 0xf2, 0xb6, 0x82, 0xbe, 0x4f, + 0x25, 0xc3, 0xeb, 0xd2, 0x76, 0x91, 0x23, 0xb9, 0x30, 0xa3, 0x77, 0x20, + 0x9f, 0x82, 0x00, 0x4f, 0x54, 0xc4, 0x36, 0x3c, 0xfc, 0xa1, 0xc2, 0xa3, + 0xf9, 0x0c, 0x88, 0xbf, 0x53, 0x1e, 0x2c, 0xf4, 0xce, 0x70, 0x79, 0x8a, + 0x6f, 0xdf, 0xce, 0xce, 0x49, 0xc0, 0x2c, 0x03, 0x5f, 0x85, 0xfd, 0x96, + 0xa5, 0x82, 0xf0, 0xc8, 0xe4, 0xf6, 0xbc, 0x62, 0x9c, 0xf7, 0x77, 0x3d, + 0x5c, 0xf1, 0x0a, 0x2e, 0xe2, 0x7e, 0x81, 0x93, 0xca, 0x58, 0x2f, 0x9a, + 0x92, 0x3b, 0xe6, 0x05, 0xf1, 0xd4, 0x21, 0xfe, 0x01, 0x4a, 0x70, 0x6b, + 0x17, 0x4b, 0x1c, 0xc4, 0x1e, 0x43, 0xda, 0x9a, 0x6f, 0x47, 0x25, 0xef, + 0x32, 0xcc, 0x8a, 0xee, 0x51, 0xb1, 0xa5, 0x85, 0xff, 0x87, 0xb4, 0x24, + 0x0c, 0xb9, 0xed, 0x57, 0x00, 0x78, 0x98, 0x1f, 0xe3, 0xa1, 0x16, 0xa6, + 0xcd, 0xc4, 0xa8, 0xb6, 0x87, 0x08, 0x82, 0x88, 0x16, 0x9e, 0x02, 0x5d, + 0x3c, 0xd6, 0xf1, 0xf3, 0x26, 0xe7, 0xa6, 0x00, 0x9d, 0x8f, 0x4e, 0xca, + 0x00, 0xcf, 0x8b, 0x24, 0xa9, 0xd9, 0x57, 0x9d, 0x4f, 0xa0, 0x12, 0x8c, + 0x5f, 0x13, 0x89, 0xbb, 0xd4, 0xce, 0x5b, 0x49, 0x8f, 0x84, 0x77, 0x09, + 0x12, 0x65, 0xe5, 0x18, 0x5e, 0xf1, 0x9a, 0x0f, 0xbf, 0x04, 0x19, 0x62, + 0xf9, 0xe0, 0x98, 0xd2, 0x33, 0x64, 0x82, 0xa1, 0xce, 0x12, 0x49, 0x4f, + 0xaf, 0xea, 0xe1, 0x1b, 0x6a, 0x71, 0xa7, 0xe5, 0x33, 0xf9, 0x77, 0x11, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x17, 0x31, 0xe4, 0xe1, + 0x4d, 0x14, 0xe4, 0x31, 0xc0, 0x84, 0x1f, 0x29, 0xfe, 0xef, 0x2a, 0xdd, + 0x6d, 0x48, 0x93, 0x45, 0x3c, 0x6a, 0x25, 0xb6, 0x90, 0x94, 0x8b, 0x7b, + 0xc2, 0x61, 0x49, 0x17, 0x08, 0xcd, 0x0f, 0xd2, 0xd7, 0x4c, 0xd3, 0x8e, + 0xd4, 0x41, 0x55, 0xf3, 0x70, 0xef, 0x07, 0x07, 0x21, 0xfc, 0xfe, 0xbc, + 0x79, 0xe3, 0x12, 0xa8, 0x58, 0x83, 0x4d, 0x50, 0x8c, 0x94, 0x97, 0x16, + 0x88, 0x17, 0xc0, 0xca, 0x91, 0xdb, 0x4b, 0xe6, 0x96, 0xd2, 0xf6, 0x70, + 0xa4, 0xca, 0x7d, 0xdf, 0xcb, 0xf7, 0xf8, 0x2d, 0x58, 0xf9, 0x3c, 0x41, + 0x12, 0x5a, 0x98, 0xf4, 0x06, 0x7c, 0x75, 0x1c, 0x92, 0x93, 0x62, 0x2a, + 0x6d, 0x51, 0x97, 0x4d, 0x71, 0x36, 0x6a, 0x7d, 0xe0, 0xb3, 0xda, 0x6a, + 0x31, 0xb9, 0x17, 0x87, 0x69, 0x0f, 0x50, 0x17, 0x71, 0x79, 0x4b, 0x04, + 0x94, 0x7f, 0x8f, 0x05, 0x72, 0xa2, 0x95, 0xa8, 0x4e, 0x13, 0xd5, 0x61, + 0x51, 0x78, 0xdb, 0x35, 0xa6, 0x29, 0xf2, 0x6e, 0x20, 0xa3, 0xcd, 0xeb, + 0xab, 0x9e, 0xfe, 0x55, 0x28, 0x9e, 0x23, 0x0a, 0x29, 0x84, 0xaf, 0x2c, + 0x85, 0x5f, 0xfa, 0x4d, 0x1f, 0x55, 0x40, 0x18, 0xe9, 0xd3, 0xe9, 0xa6, + 0xe6, 0x1d, 0x2e, 0xd8, 0x5a, 0xcc, 0xa3, 0x70, 0x80, 0x76, 0x68, 0x53, + 0xd5, 0xbb, 0x6e, 0x89, 0x67, 0x8e, 0x8b, 0x2e, 0x22, 0x52, 0x72, 0x56, + 0x97, 0xd3, 0xb2, 0xc7, 0x61, 0xe6, 0x2a, 0x0b, 0xe9, 0x4e, 0x44, 0x7d, + 0xf5, 0xae, 0x49, 0x47, 0xe5, 0x2f, 0x1e, 0xaf, 0xff, 0x75, 0x69, 0xd6, + 0xa8, 0xba, 0x8e, 0x1e, 0x73, 0x43, 0x04, 0x51, 0xfe, 0x5a, 0xe8, 0x12, + 0x74, 0xdb, 0xd3, 0xa5, 0x89, 0x55, 0xc0, 0x30, 0x9c, 0x0c, 0x24, 0xb4, + 0xd1, 0x19, 0xba, 0x9c, 0x88, 0x6f, 0x6e, 0xfc, 0x76, 0xff, 0xfa, 0x1a, + 0xf1, 0x56, 0x82, 0xf6, 0xde, 0x26, 0xbe, 0xba, 0x76, 0x22, 0x5d, 0x07, + 0xec, 0xf4, 0xea, 0xff, 0xcd, 0xa0, 0xa4, 0xd3, 0x4b, 0xd0, 0xf2, 0xdb, + 0x96, 0x67, 0x93, 0xd8, 0x71, 0x6c, 0x51, 0x1b, 0x2c, 0x9b, 0x54, 0x39, + 0x83, 0xf2, 0x8a, 0x75, 0x34, 0xe0, 0xad, 0x9d, 0xc8, 0x94, 0xf7, 0x44, + 0x84, 0xfc, 0xa7, 0x26, 0xe8, 0x01, 0x22, 0x27, 0x41, 0xf3, 0x0e, 0xba, + 0x6b, 0x35, 0xed, 0x07, 0xbb, 0x97, 0x8f, 0x85, 0xa1, 0x53, 0x72, 0x4b, + 0x96, 0xaa, 0xb4, 0x6d, 0xc9, 0x1b, 0x0d, 0x83, 0xed, 0x69, 0xd1, 0xc3, + 0x24, 0x61, 0x07, 0xe8, 0x8d, 0xb1, 0x62, 0xf4, 0xfc, 0x6f, 0xf8, 0x19, + 0x39, 0x48, 0x69, 0x07, 0x48, 0xf0, 0xf4, 0x43, 0x38, 0xdd, 0x71, 0x46, + 0xec, 0x2b, 0x60, 0xcf, 0xe3, 0xde, 0x07, 0xdb, 0x39, 0xc4, 0x25, 0xf0, + 0xe7, 0xe2, 0x55, 0x27, 0x86, 0xc3, 0x35, 0x2a, 0x3c, 0xfb, 0xfa, 0xc0, + 0x92, 0x87, 0x25, 0xb6, 0x71, 0x94, 0xc8, 0x64, 0x9e, 0x8b, 0x52, 0x2c, + 0x4f, 0x0b, 0x90, 0x67, 0x08, 0xfe, 0x1b, 0xa4, 0xbb, 0xc0, 0x6d, 0xd1, + 0x17, 0x78, 0xfa, 0x0d, 0x75, 0xd3, 0xa5, 0x61, 0x0a, 0x05, 0x10, 0x5f, + 0x6b, 0x13, 0x98, 0x77, 0xd6, 0x46, 0x8e, 0xc0, 0x7e, 0x2c, 0xd5, 0xaf, + 0xe8, 0xfe, 0xa4, 0xe5, 0xc8, 0x22, 0x9c, 0x19, 0x09, 0x6f, 0xc3, 0x16, + 0xe2, 0x47, 0xf8, 0xb9, 0x21, 0x2b, 0xf9, 0x05, 0x21, 0xa7, 0x3b, 0x22, + 0xfe, 0x7d, 0x70, 0xdf, 0xba, 0xb3, 0xed, 0x93, 0x86, 0x08, 0xe1, 0xe2, + 0xc4, 0x9f, 0x17, 0xf8, 0x98, 0x35, 0x98, 0x2a, 0x5a, 0x85, 0xe7, 0xb5, + 0x81, 0x7f, 0x25, 0xfa, 0x58, 0x1e, 0xeb, 0x90, 0x5c, 0xd5, 0x98, 0x2f, + 0x38, 0xad, 0xd4, 0xc4, 0x51, 0x8c, 0x73, 0x13, 0x84, 0x32, 0x34, 0xc7, + 0x06, 0xaf, 0x3c, 0x2e, 0x12, 0x00, 0x27, 0x52, 0xfb, 0x95, 0x1b, 0xe5, + 0x8c, 0x3e, 0xb1, 0x54, 0xf4, 0xe7, 0x48, 0xc7, 0xed, 0x3b, 0x28, 0x44, + 0xaa, 0xa8, 0xca, 0x89, 0x03, 0xc6, 0x59, 0x5a, 0xc2, 0x7d, 0x03, 0x1f, + 0x3c, 0xc6, 0x5f, 0xcf, 0xf0, 0x17, 0xf2, 0xf3, 0x46, 0xaf, 0x26, 0x06, + 0xb5, 0x80, 0x97, 0x85, 0xe6, 0x28, 0xbf, 0x03, 0x07, 0xb1, 0x02, 0x3a, + 0xee, 0x36, 0x53, 0x12, 0x2f, 0xe4, 0xab, 0x04, 0x13, 0x05, 0x13, 0x31, + 0x85, 0x08, 0x87, 0x66, 0xc8, 0x7a, 0xd6, 0xcb, 0xa0, 0xbe, 0x1f, 0x39, + 0x1a, 0xe3, 0x8e, 0x3f, 0x6b, 0x21, 0x55, 0x6f, 0x17, 0x15, 0xa5, 0xe4, + 0xc4, 0x4b, 0x6c, 0x10, 0xe5, 0x32, 0x9d, 0xa1, 0xc0, 0x8f, 0xb1, 0x4b, + 0x5e, 0x52, 0xf1, 0x75, 0xee, 0xe0, 0x44, 0x71, 0x41, 0x20, 0xf0, 0xb6, + 0xf1, 0x47, 0xe4, 0x2a, 0xb8, 0x1f, 0xa1, 0xaf, 0x9d, 0xad, 0xde, 0x14, + 0x50, 0x74, 0x5c, 0x61, 0x80, 0x7c, 0x7a, 0xe8, 0xce, 0xd7, 0x30, 0x46, + 0x72, 0x57, 0x6d, 0x86, 0xb8, 0xdc, 0x98, 0x85, 0x33, 0xb7, 0xa7, 0x55, + 0xf3, 0xb0, 0xe0, 0xd4, 0x3a, 0x5b, 0xb8, 0x27, 0x35, 0xc5, 0x73, 0x0f, + 0x47, 0x95, 0xf8, 0x6a, 0x79, 0x15, 0x3e, 0xb2, 0x18, 0xcc, 0x5b, 0xc9, + 0xc1, 0xad, 0x51, 0xaf, 0x24, 0x46, 0xfb, 0x1d, 0xb0, 0x19, 0xc1, 0x14, + 0x1e, 0x2b, 0x7a, 0x00, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x86, 0xe7, 0x8e, 0xe6, 0x2d, 0x5d, 0x0e, 0xaa, 0x4d, 0x11, 0x71, 0x27, + 0xe2, 0x29, 0x27, 0xc2, 0x87, 0x5f, 0x44, 0x1e, 0xf1, 0xed, 0x8e, 0x3e, + 0xb3, 0x42, 0xd9, 0x85, 0x74, 0x3a, 0x3c, 0x18, 0x87, 0xe5, 0xf0, 0xc4, + 0x08, 0xbc, 0x20, 0xf4, 0x2d, 0xda, 0x58, 0x2e, 0x69, 0xdd, 0xb8, 0xed, + 0xa2, 0x92, 0x27, 0xbe, 0x2b, 0x35, 0x33, 0x1e, 0x14, 0xb1, 0x81, 0x90, + 0x94, 0xba, 0x51, 0x21, 0xa5, 0x0c, 0x1b, 0x1e, 0xda, 0xfb, 0xa4, 0xfd, + 0xc8, 0x85, 0x92, 0x41, 0xb3, 0xdc, 0x33, 0x3c, 0x9e, 0x39, 0xa2, 0xba, + 0x93, 0xb1, 0xcb, 0x2e, 0x7f, 0x1d, 0x47, 0xfb, 0xc6, 0x92, 0xdb, 0x20, + 0xb1, 0x38, 0xe8, 0x73, 0xc6, 0xb6, 0xe9, 0xcd, 0x7d, 0x54, 0x6f, 0x3e, + 0x9b, 0xb5, 0x10, 0xe7, 0x6d, 0xe6, 0x32, 0x06, 0x41, 0x9e, 0x1c, 0x1d, + 0xea, 0x0b, 0x59, 0x62, 0x3f, 0x5a, 0x64, 0x2e, 0x2e, 0xf9, 0xf9, 0xd0, + 0xe0, 0x48, 0x32, 0xd5, 0x20, 0xc9, 0x38, 0xe2, 0xcf, 0xdd, 0xaa, 0x4a, + 0xc9, 0x30, 0x48, 0x25, 0x73, 0x0c, 0x42, 0x1f, 0xcc, 0x67, 0x47, 0xde, + 0x58, 0xdf, 0x18, 0x29, 0xef, 0xa1, 0x2d, 0xe7, 0xa9, 0xf7, 0xca, 0x53, + 0x34, 0x9a, 0x2c, 0xf2, 0x29, 0x5c, 0xd3, 0x38, 0x76, 0x50, 0x16, 0x3f, + 0x51, 0x71, 0x5b, 0x1d, 0xa6, 0xcb, 0x2e, 0x3f, 0x75, 0xa8, 0x80, 0x27, + 0x77, 0x2d, 0xa4, 0xae, 0xbf, 0x9a, 0xc9, 0x23, 0xef, 0x00, 0x1e, 0x79, + 0x92, 0x43, 0xba, 0xc2, 0x69, 0x76, 0x4a, 0xb9, 0x52, 0xf9, 0x9b, 0x1d, + 0xb8, 0xe2, 0xee, 0x31, 0x7a, 0x30, 0xc9, 0x1d, 0x9c, 0xfb, 0xa9, 0x8a, + 0xd5, 0x86, 0xb4, 0x41, 0xbb, 0xf4, 0x37, 0xea, 0x82, 0x5b, 0x5b, 0xc1, + 0x10, 0x95, 0x27, 0x77, 0x76, 0xcd, 0xe1, 0x79, 0x1f, 0x65, 0x8d, 0x02, + 0x8b, 0x48, 0xe1, 0x27, 0x05, 0xd3, 0x67, 0x5a, 0x74, 0x1a, 0x5c, 0xef, + 0xa1, 0x16, 0xc1, 0x87, 0x18, 0x22, 0x6b, 0xe7, 0x83, 0x32, 0x1c, 0x85, + 0x35, 0x5a, 0x1e, 0x39, 0x27, 0xee, 0x18, 0xb3, 0x22, 0x3e, 0x96, 0x2e, + 0x1b, 0x08, 0x43, 0xbe, 0x37, 0xc8, 0xb7, 0xb8, 0x19, 0x87, 0xbe, 0x3d, + 0x6a, 0x9a, 0x04, 0x54, 0x97, 0xba, 0x9a, 0x5f, 0xbf, 0x49, 0x6e, 0x61, + 0x9b, 0x5a, 0x2c, 0xd7, 0xed, 0xe9, 0xac, 0x21, 0xf2, 0xe6, 0xb3, 0x77, + 0x96, 0x6d, 0x80, 0x94, 0x21, 0xa7, 0x9d, 0x62, 0xf7, 0x25, 0xb9, 0xff, + 0x8d, 0xd6, 0x23, 0xfa, 0x8c, 0x24, 0xe4, 0xf7, 0x55, 0xf9, 0xd2, 0x98, + 0x68, 0xf6, 0x05, 0x1a, 0x5a, 0x7b, 0x1c, 0x16, 0x4e, 0x68, 0xdd, 0xbb, + 0x19, 0xe3, 0xe8, 0x0e, 0xc6, 0xbd, 0xf9, 0xb6, 0x9f, 0xcd, 0xde, 0x9d, + 0x90, 0xd4, 0x4d, 0x4b, 0x4f, 0xa1, 0x37, 0x60, 0x51, 0x83, 0xfd, 0x0a, + 0x9f, 0x8a, 0x52, 0x07, 0xdf, 0x9c, 0x26, 0x9e, 0xc6, 0x73, 0x5e, 0x47, + 0x89, 0x02, 0x91, 0x52, 0x09, 0x9f, 0x93, 0xa4, 0x3d, 0xf3, 0x82, 0xf8, + 0xe7, 0xde, 0xa6, 0x0f, 0xde, 0x0c, 0xff, 0x19, 0x7a, 0xd2, 0xf7, 0x0e, + 0x5e, 0x72, 0x13, 0x43, 0xcb, 0x33, 0xa7, 0x04, 0x1d, 0x1e, 0xd8, 0xe9, + 0xa8, 0x91, 0xa6, 0x7f, 0x82, 0x65, 0xfc, 0xb4, 0xc5, 0x5c, 0xd8, 0xa7, + 0x82, 0x0c, 0x45, 0x25, 0x17, 0x60, 0x4e, 0x03, 0x60, 0x7d, 0xa9, 0xf0, + 0x97, 0x42, 0xe2, 0x72, 0x64, 0x4e, 0x3c, 0xb3, 0x79, 0xb0, 0x0d, 0x71, + 0xd3, 0xd9, 0x05, 0x47, 0xee, 0xdf, 0x7a, 0x6d, 0x79, 0x99, 0xe6, 0x10, + 0xe0, 0x6c, 0xfd, 0x5a, 0x0e, 0x33, 0x74, 0x59, 0x1b, 0xbf, 0x7b, 0x0f, + 0x9d, 0x61, 0xbc, 0xcd, 0xb0, 0xb9, 0xc5, 0x09, 0x5b, 0xa7, 0x93, 0x9c, + 0xd2, 0x8c, 0xa2, 0xc2, 0x84, 0x4e, 0x0f, 0x2b, 0x25, 0x74, 0x30, 0x55, + 0xe4, 0x70, 0xbf, 0xbb, 0x5f, 0xc1, 0x99, 0xe2, 0x18, 0x5c, 0xfb, 0xcf, + 0x4d, 0x08, 0xc1, 0x73, 0xe6, 0x32, 0x81, 0x43, 0x46, 0x87, 0xf8, 0x63, + 0x3d, 0xe9, 0x04, 0x21, 0xf8, 0x6d, 0x58, 0x9a, 0x07, 0x06, 0xb0, 0xda, + 0x83, 0x99, 0xb8, 0x98, 0x47, 0xc8, 0xa6, 0x31, 0x15, 0x47, 0x23, 0xc1, + 0x9d, 0x92, 0xc1, 0xde, 0xcb, 0xb7, 0x95, 0xc1, 0xe6, 0x1c, 0x91, 0x25, + 0xc9, 0x58, 0x12, 0xa3, 0x8c, 0x5d, 0x91, 0xba, 0x41, 0x2c, 0x47, 0x20, + 0xf4, 0xaa, 0xf5, 0x6d, 0x73, 0xa8, 0x57, 0x5a, 0xde, 0x9c, 0x1d, 0x05, + 0x8a, 0x9e, 0x70, 0x76, 0x63, 0x65, 0x73, 0x13, 0x1f, 0xc9, 0xa5, 0x09, + 0x18, 0x6c, 0xc0, 0x09, 0xb4, 0x4a, 0x7d, 0x34, 0x42, 0x00, 0x58, 0x6e, + 0xcf, 0x68, 0x66, 0x84, 0x45, 0x49, 0x86, 0xd9, 0x06, 0x1c, 0x08, 0xf6, + 0xbd, 0xd9, 0xbf, 0x26, 0xfa, 0x82, 0x07, 0x3b, 0x63, 0xe8, 0x91, 0x4b, + 0x23, 0xc8, 0xc2, 0x00, 0x5a, 0x1b, 0xa7, 0x76, 0xd4, 0x12, 0x40, 0xde, + 0x34, 0xfd, 0x00, 0xff, 0x9d, 0x31, 0x64, 0xde, 0x97, 0x60, 0xcf, 0x01, + 0x15, 0x6d, 0x09, 0x73, 0xea, 0x15, 0xcc, 0xce, 0x1c, 0x95, 0xd0, 0xc4, + 0x68, 0x67, 0x38, 0x39, 0xa3, 0x4b, 0x9b, 0x50, 0x92, 0xdc, 0x99, 0x6e, + 0x23, 0x97, 0x28, 0x8a, 0x5b, 0xbb, 0x14, 0x29, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x5a, 0x10, 0xd0, 0x28, 0x08, 0xf2, 0x4d, 0x96, + 0xda, 0xf8, 0x7b, 0xe7, 0x37, 0xf4, 0x73, 0x29, 0x92, 0xd6, 0x1a, 0x00, + 0xf7, 0xeb, 0x9e, 0x2d, 0x05, 0xd5, 0x1c, 0x75, 0x52, 0x0a, 0x3c, 0x03, + 0x70, 0x1d, 0x8a, 0xb6, 0x30, 0xd1, 0xde, 0x4c, 0xfc, 0x16, 0xbe, 0xe2, + 0xb7, 0xbb, 0xf5, 0x42, 0x75, 0x14, 0x4e, 0xab, 0x96, 0x74, 0xff, 0x79, + 0x88, 0x61, 0xaa, 0xea, 0xf4, 0x06, 0x70, 0x0a, 0xe5, 0xf2, 0x92, 0x18, + 0xe6, 0x1a, 0xa8, 0x2a, 0x94, 0x57, 0x2f, 0x1e, 0x73, 0x62, 0x32, 0xec, + 0xa5, 0xe3, 0xc8, 0x8d, 0x52, 0x2e, 0x1b, 0x6c, 0xf6, 0x1d, 0x7f, 0xcb, + 0x4a, 0x08, 0x87, 0x17, 0xa0, 0x1b, 0x4c, 0xf4, 0x06, 0x8e, 0x53, 0xb3, + 0x3e, 0xcb, 0x2a, 0xa3, 0x88, 0x28, 0xa0, 0x3b, 0x34, 0x48, 0xe2, 0x48, + 0xd5, 0xb1, 0xb5, 0xc6, 0x5b, 0x67, 0x3c, 0x71, 0x52, 0xdc, 0xd8, 0x19, + 0x12, 0x77, 0x64, 0x48, 0x55, 0xed, 0x66, 0x2b, 0x99, 0xdd, 0x00, 0xe7, + 0x8d, 0x7d, 0x77, 0x1d, 0x0b, 0x11, 0x9a, 0x93, 0x20, 0x1f, 0x40, 0xf6, + 0x4c, 0x5a, 0x1b, 0xa4, 0x53, 0x4c, 0xd3, 0x2f, 0x52, 0x36, 0xef, 0x72, + 0x6c, 0x17, 0x4c, 0xd2, 0xd8, 0xfa, 0x5f, 0x41, 0x6f, 0x6e, 0xe9, 0x16, + 0x64, 0x76, 0xf2, 0x01, 0xee, 0xa4, 0x62, 0xd3, 0xd2, 0xb8, 0x85, 0x08, + 0xf9, 0xda, 0x48, 0x08, 0x35, 0x02, 0xfa, 0xad, 0x22, 0xfe, 0x71, 0x92, + 0x40, 0x60, 0xb5, 0x85, 0x4e, 0xd9, 0x66, 0x02, 0x69, 0x37, 0x70, 0xc0, + 0x6a, 0x9f, 0x1e, 0x2b, 0xd4, 0x28, 0x55, 0xe3, 0x5a, 0x7e, 0x9a, 0x20, + 0x71, 0xbb, 0x02, 0x92, 0xbc, 0xe9, 0x89, 0x11, 0x35, 0x03, 0x3e, 0xd8, + 0xbf, 0x0c, 0x84, 0x51, 0x9a, 0x93, 0x62, 0x73, 0x41, 0xc8, 0xdf, 0x66, + 0x22, 0x4c, 0xc6, 0x93, 0x27, 0x36, 0xfb, 0x10, 0xcb, 0x98, 0xb9, 0x03, + 0x3f, 0x5c, 0x40, 0x17, 0x4e, 0x3f, 0xd9, 0x95, 0xc0, 0xd1, 0x7d, 0x0f, + 0xb5, 0xe0, 0x2d, 0xc8, 0x93, 0xef, 0x2f, 0x37, 0x23, 0x13, 0xd1, 0xf5, + 0x9e, 0x01, 0x6a, 0x18, 0x8b, 0x77, 0x6b, 0xfd, 0xfc, 0x62, 0x7a, 0xdf, + 0xaf, 0x0f, 0x9c, 0x3a, 0xd7, 0xe1, 0x60, 0xfd, 0x76, 0x0a, 0x21, 0x02, + 0x05, 0xb2, 0x67, 0x2d, 0xbe, 0x72, 0x91, 0xee, 0x5f, 0x7d, 0x17, 0x21, + 0x47, 0xeb, 0xe1, 0xfd, 0x69, 0xc3, 0x48, 0x34, 0x51, 0x24, 0x9d, 0xf0, + 0x41, 0x68, 0x78, 0x03, 0xa5, 0xa4, 0x53, 0x39, 0xd5, 0x86, 0x36, 0x72, + 0x9e, 0x64, 0x57, 0x0a, 0x5d, 0x77, 0x42, 0x27, 0x54, 0x13, 0x4a, 0x6f, + 0x29, 0xad, 0x36, 0xca, 0xde, 0x62, 0xd2, 0x2a, 0xcd, 0x64, 0x73, 0x25, + 0xa7, 0x86, 0x47, 0x0f, 0xb6, 0xb2, 0xa4, 0x65, 0x6c, 0x36, 0xda, 0xbb, + 0x79, 0xb1, 0xc0, 0x1e, 0x9f, 0x99, 0x14, 0xe8, 0x08, 0xe3, 0xfd, 0xd2, + 0xf2, 0xc1, 0xdd, 0xc6, 0x2c, 0x2d, 0x83, 0xa3, 0x5d, 0xf2, 0xa6, 0x4d, + 0xe4, 0x87, 0xe3, 0xee, 0x02, 0x09, 0xaf, 0x44, 0x46, 0x42, 0x99, 0x12, + 0x95, 0xd5, 0xe5, 0xd5, 0xa6, 0x4a, 0x29, 0x14, 0x96, 0xcd, 0x8a, 0x13, + 0x4f, 0xf3, 0x10, 0xd8, 0x68, 0xe4, 0x27, 0x1f, 0x81, 0xbb, 0xf8, 0x05, + 0xc5, 0xc8, 0x4e, 0x58, 0x86, 0x4d, 0x3e, 0x1c, 0xa3, 0x84, 0x85, 0x47, + 0x1f, 0x2d, 0xc4, 0x60, 0xf5, 0x75, 0x22, 0x4d, 0x0c, 0x9a, 0x3d, 0x4c, + 0x42, 0xcf, 0xe1, 0xd6, 0x96, 0x72, 0x33, 0x9c, 0x76, 0x38, 0x8f, 0x41, + 0xbf, 0xe7, 0x0d, 0x06, 0xd0, 0x63, 0x75, 0x85, 0x62, 0x78, 0x73, 0x91, + 0x66, 0x56, 0x40, 0xfb, 0xa5, 0x77, 0xa1, 0x35, 0x3e, 0x50, 0xcd, 0x72, + 0x46, 0xbd, 0x6e, 0x59, 0x20, 0x91, 0x9a, 0x0d, 0xd6, 0xb1, 0x4a, 0x15, + 0x99, 0x21, 0x69, 0x7e, 0xe6, 0x87, 0xbc, 0x29, 0x05, 0xb5, 0x27, 0x2e, + 0x54, 0x61, 0xf3, 0x14, 0x55, 0xe1, 0x87, 0x76, 0xf3, 0xac, 0xeb, 0x90, + 0x51, 0x51, 0x71, 0x41, 0x55, 0x9f, 0x70, 0x00, 0xf5, 0x16, 0x30, 0x72, + 0x30, 0x37, 0x60, 0xa8, 0xdb, 0x44, 0xdb, 0x1d, 0xf3, 0xf0, 0x8a, 0x7e, + 0xa0, 0x49, 0x77, 0x0b, 0x31, 0x30, 0x1e, 0x05, 0x83, 0xa6, 0x77, 0x59, + 0xc6, 0xe5, 0x2f, 0x1b, 0xc7, 0xed, 0xf0, 0x6b, 0x33, 0x9f, 0x0c, 0xda, + 0x00, 0x8b, 0x21, 0xed, 0x5c, 0xc7, 0xdf, 0x02, 0x19, 0x5e, 0x80, 0x28, + 0xcf, 0x07, 0xa1, 0x73, 0xbb, 0x77, 0x63, 0x3b, 0x98, 0xa6, 0x5d, 0x01, + 0x7d, 0x26, 0x6f, 0xec, 0x76, 0x53, 0x90, 0x06, 0x0c, 0xed, 0x93, 0x33, + 0xd2, 0x98, 0xf3, 0x1e, 0x85, 0x58, 0x3a, 0xc9, 0xeb, 0x3f, 0x60, 0xc9, + 0x7f, 0xcd, 0x9d, 0xdf, 0xab, 0xc1, 0xd1, 0x2e, 0xef, 0xb3, 0x03, 0x0a, + 0x9d, 0xa0, 0xed, 0x1d, 0x3e, 0x36, 0x3a, 0xfe, 0xe0, 0xec, 0x37, 0xa8, + 0xcc, 0x2c, 0x66, 0x20, 0x49, 0x1c, 0x3c, 0xa4, 0xde, 0xc8, 0xf6, 0xba, + 0x73, 0x0a, 0x8b, 0x2e, 0xd9, 0xf7, 0x04, 0xd7, 0x97, 0x1b, 0x6e, 0xb2, + 0x39, 0x61, 0xc8, 0xf5, 0x60, 0x40, 0x8a, 0x06, 0x8f, 0x69, 0xf7, 0xdf, + 0x14, 0xa9, 0x50, 0x37, 0x0c, 0x15, 0xb4, 0xd4, 0x79, 0x4d, 0xe4, 0x17, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x23, 0x34, 0x41, 0x59, + 0xc9, 0x83, 0x47, 0x37, 0x47, 0xbc, 0x8a, 0xa0, 0xc3, 0x5b, 0x7f, 0xab, + 0x8b, 0x3c, 0x6e, 0x44, 0xe6, 0xa6, 0x2b, 0x28, 0xdc, 0x44, 0xbb, 0xcb, + 0xa2, 0x42, 0xa5, 0x02, 0x8c, 0x50, 0xd1, 0xe8, 0x97, 0x34, 0x4b, 0x09, + 0x02, 0xee, 0xfd, 0x78, 0xa3, 0xc5, 0x35, 0x2e, 0x1e, 0xb5, 0x89, 0x79, + 0xf5, 0x9f, 0xb5, 0x97, 0x97, 0x62, 0x73, 0x79, 0xcf, 0x58, 0x87, 0x22, + 0x5f, 0xfe, 0x00, 0x12, 0x53, 0xce, 0x20, 0xe2, 0x4a, 0xf2, 0x8b, 0x2f, + 0xf3, 0x12, 0x58, 0x7a, 0x12, 0x65, 0x88, 0x5b, 0xef, 0x20, 0x4f, 0x9b, + 0xc4, 0xd0, 0x86, 0xb7, 0x67, 0x07, 0x71, 0x08, 0xc1, 0xde, 0x1c, 0xbf, + 0x36, 0x7d, 0x13, 0x67, 0xd2, 0xe9, 0x07, 0xdd, 0x56, 0x12, 0x23, 0x51, + 0x4d, 0xec, 0xe4, 0x8c, 0xb3, 0x53, 0x25, 0x19, 0xac, 0x88, 0xc7, 0x62, + 0x85, 0xf7, 0x91, 0x17, 0x6f, 0x2f, 0x81, 0x42, 0xe0, 0xf6, 0x04, 0x2d, + 0x8f, 0x8c, 0x94, 0xab, 0xa3, 0x9b, 0xc6, 0x3b, 0x39, 0x68, 0xe1, 0x08, + 0x81, 0xba, 0xcf, 0xda, 0x09, 0xa5, 0xe1, 0x14, 0xb9, 0xed, 0x37, 0x1c, + 0xd5, 0xba, 0x9a, 0x5e, 0x91, 0x17, 0x47, 0xaa, 0x1f, 0xfa, 0x76, 0x5a, + 0x09, 0xc5, 0x03, 0xb8, 0xa8, 0x58, 0x4b, 0x4f, 0xf5, 0xf6, 0xbf, 0x01, + 0x76, 0x63, 0x5f, 0xde, 0xd9, 0x7f, 0xb4, 0x18, 0xa9, 0xe6, 0xf4, 0x5d, + 0x22, 0xc4, 0x12, 0xfe, 0x55, 0x76, 0xb1, 0xbe, 0x72, 0x19, 0x84, 0xc5, + 0xf4, 0xfe, 0x2a, 0x1f, 0xec, 0x86, 0x37, 0x36, 0x25, 0x94, 0xe8, 0x07, + 0x09, 0x99, 0xaa, 0x12, 0x02, 0xf1, 0x18, 0x3e, 0x6c, 0xec, 0xe3, 0x6e, + 0x09, 0xcc, 0x0e, 0x07, 0xbf, 0xb8, 0xf3, 0x92, 0xd6, 0xdb, 0xef, 0xc3, + 0x52, 0x75, 0xe3, 0x77, 0x52, 0x44, 0xdb, 0x71, 0xed, 0x87, 0x1c, 0x0b, + 0x77, 0xa0, 0xba, 0xbc, 0x76, 0x3f, 0x60, 0x1e, 0x5b, 0x51, 0x3f, 0xd0, + 0x17, 0x34, 0x8d, 0xbe, 0x1c, 0xcb, 0x8b, 0x7a, 0xf1, 0x7d, 0x7d, 0xe5, + 0xa6, 0x3a, 0x2f, 0x03, 0x5a, 0xc3, 0x35, 0x08, 0xd2, 0x3b, 0x28, 0x0d, + 0x7d, 0x35, 0xed, 0xac, 0x3b, 0x88, 0x6a, 0x78, 0xa7, 0x07, 0x37, 0xa1, + 0xfa, 0x7b, 0x7d, 0x4a, 0xfc, 0xfc, 0x4b, 0x67, 0x71, 0x57, 0xad, 0xbd, + 0x34, 0xac, 0x26, 0x26, 0x81, 0x69, 0xcd, 0x5e, 0xd9, 0x1a, 0xfd, 0x28, + 0xe8, 0x93, 0x5e, 0x41, 0xaa, 0x47, 0x05, 0x41, 0x92, 0xb5, 0xb4, 0xd3, + 0x60, 0xcc, 0x8f, 0xc0, 0x6d, 0xf8, 0x08, 0x88, 0x1c, 0x2c, 0x4c, 0x26, + 0x69, 0xd5, 0x16, 0x5e, 0x3c, 0x0b, 0xad, 0x48, 0x96, 0x7f, 0x78, 0xe7, + 0xc5, 0x85, 0xa4, 0x6b, 0x7b, 0x36, 0x59, 0xe4, 0x1b, 0xce, 0x87, 0x93, + 0x92, 0xc7, 0x52, 0xa5, 0xcb, 0xe3, 0x22, 0x2c, 0x44, 0x55, 0x1f, 0x90, + 0xda, 0x22, 0xf7, 0x80, 0x2c, 0x00, 0x83, 0x06, 0xed, 0x04, 0x7c, 0x56, + 0x39, 0x9b, 0xa4, 0x68, 0x6d, 0xf4, 0xa5, 0xfe, 0xda, 0x02, 0x8e, 0x3d, + 0xec, 0x2a, 0x41, 0x19, 0xce, 0x50, 0x5a, 0x1b, 0x5b, 0xc1, 0x62, 0xe8, + 0x0a, 0xf3, 0x0b, 0xd2, 0xb4, 0xc2, 0x74, 0x39, 0xab, 0x37, 0xa9, 0xd2, + 0x4e, 0x22, 0x2b, 0x73, 0x6b, 0x64, 0xc3, 0xfe, 0x9c, 0xc2, 0xff, 0x24, + 0x28, 0xbc, 0x1b, 0x5a, 0x50, 0xf1, 0x4b, 0xf8, 0xab, 0xf0, 0x0c, 0x65, + 0xe7, 0xb0, 0xb9, 0x4b, 0x22, 0x13, 0xde, 0x5d, 0x21, 0xe5, 0x80, 0x10, + 0x6c, 0x4e, 0x1a, 0x42, 0xf9, 0xe6, 0x53, 0x05, 0x57, 0xa8, 0x28, 0xd1, + 0xe2, 0x9f, 0x61, 0x43, 0x36, 0xf4, 0x3a, 0x52, 0x1c, 0x6f, 0xc2, 0x6e, + 0x57, 0xb7, 0xd2, 0x9d, 0xee, 0x7e, 0x7e, 0xec, 0x33, 0xde, 0x89, 0x24, + 0x52, 0x07, 0x11, 0x00, 0xab, 0x00, 0xd9, 0x9e, 0xe8, 0xaf, 0x31, 0xc9, + 0x08, 0x77, 0x27, 0x4b, 0x03, 0x78, 0x63, 0x6f, 0xc9, 0xe3, 0xc7, 0xf3, + 0xae, 0x10, 0x57, 0xf9, 0xe0, 0x6d, 0xc4, 0xcc, 0x7a, 0x3a, 0x79, 0x06, + 0xa3, 0x0c, 0xe8, 0x4c, 0x85, 0xe6, 0xf3, 0x60, 0xdd, 0x81, 0xf7, 0xbd, + 0x40, 0xfd, 0xe1, 0x9f, 0x24, 0x22, 0xff, 0xda, 0xd9, 0xe4, 0x3b, 0x90, + 0xbe, 0x04, 0xc4, 0x9b, 0x11, 0x79, 0x8e, 0x1f, 0x96, 0x53, 0xe6, 0xb5, + 0xca, 0x97, 0xec, 0x6a, 0xb6, 0xde, 0xec, 0x99, 0xd5, 0xd2, 0x6c, 0x69, + 0xa4, 0x31, 0x8e, 0xab, 0x81, 0x72, 0xfe, 0xa8, 0x11, 0xf0, 0xd2, 0xb6, + 0x6e, 0xf2, 0x77, 0x15, 0xf8, 0x26, 0x8c, 0xec, 0x6c, 0x47, 0xac, 0x9d, + 0x4a, 0x67, 0xb1, 0x45, 0xbe, 0x05, 0x0e, 0xa4, 0x26, 0xfe, 0xae, 0xd4, + 0x2c, 0xa7, 0xcc, 0x52, 0xba, 0xd6, 0xa4, 0x7f, 0x44, 0x29, 0xf3, 0x1d, + 0x63, 0x88, 0xad, 0xd1, 0x33, 0x69, 0x37, 0xf2, 0x04, 0xef, 0x56, 0x37, + 0x10, 0x80, 0x8d, 0x88, 0x04, 0xcb, 0x7c, 0xe9, 0xc4, 0x9f, 0x6b, 0x01, + 0x3f, 0xa2, 0x72, 0x1d, 0xdb, 0xf2, 0x90, 0x13, 0x11, 0xb0, 0x09, 0x48, + 0x78, 0x5c, 0xac, 0xf9, 0x6f, 0x8d, 0x2c, 0x25, 0xf1, 0x85, 0x2b, 0x81, + 0xbf, 0x4a, 0xa8, 0x63, 0x3e, 0xb5, 0xc6, 0x32, 0x2c, 0x2b, 0x62, 0x26, + 0xfa, 0x82, 0x86, 0x1f, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x2f, 0xbd, 0x82, 0x81, 0x99, 0x52, 0x9f, 0x9c, 0x95, 0x03, 0x11, 0x96, + 0xae, 0x3f, 0x39, 0xac, 0xbd, 0x99, 0x77, 0x37, 0x57, 0x7f, 0x0b, 0x9c, + 0x2b, 0xf7, 0x2c, 0x0b, 0x43, 0x49, 0x57, 0x03, 0xe3, 0xdb, 0x31, 0xda, + 0xc9, 0x62, 0xdd, 0xe1, 0x4d, 0xc7, 0xcc, 0x38, 0x9e, 0xaf, 0x85, 0x6c, + 0x3d, 0xb8, 0xd0, 0xb2, 0x39, 0x80, 0xf2, 0xfb, 0x1d, 0xf1, 0xed, 0x34, + 0xf7, 0x09, 0x3b, 0x2b, 0x0c, 0xca, 0x78, 0xf3, 0x56, 0xf9, 0xe3, 0x2d, + 0xf2, 0x2e, 0x58, 0x7d, 0x27, 0x22, 0xe8, 0x3e, 0x08, 0x9e, 0xb2, 0xa0, + 0x6e, 0xc7, 0x77, 0xb5, 0x91, 0x2e, 0xd8, 0x79, 0xf6, 0x18, 0xd6, 0x25, + 0x5e, 0xcd, 0x7b, 0x14, 0x82, 0xdd, 0xe7, 0x48, 0x7b, 0x4a, 0xe9, 0xf3, + 0x67, 0xbb, 0x72, 0x4f, 0x63, 0xcf, 0xbf, 0xbb, 0xfc, 0xcf, 0xf1, 0x2c, + 0x8a, 0xc3, 0x21, 0xef, 0x07, 0xb0, 0xa9, 0x02, 0x91, 0x53, 0x5f, 0x90, + 0x54, 0x11, 0xe6, 0x11, 0xcd, 0x4e, 0x2d, 0x8b, 0x61, 0x1c, 0xff, 0xc7, + 0x6e, 0x51, 0x75, 0x1e, 0x13, 0xbd, 0xd4, 0x33, 0x14, 0xdb, 0xb3, 0xed, + 0x24, 0xe4, 0xde, 0x17, 0x5e, 0xe8, 0x5f, 0x34, 0xe6, 0x78, 0x49, 0x21, + 0xd2, 0xfe, 0xff, 0x24, 0x0c, 0xa3, 0xb9, 0x43, 0x4e, 0x1e, 0x94, 0x0c, + 0xce, 0xe5, 0xce, 0x8c, 0x7b, 0x3b, 0xe8, 0x6b, 0xc9, 0x11, 0x2e, 0x0b, + 0x2b, 0xa5, 0xa4, 0x5e, 0x8d, 0x7c, 0xe4, 0x3f, 0x5c, 0x94, 0x6a, 0x7b, + 0x55, 0xb8, 0x04, 0x92, 0x24, 0x02, 0x24, 0x03, 0x80, 0x1f, 0xa1, 0x3e, + 0x14, 0x83, 0x15, 0xc8, 0xe7, 0x6d, 0xb1, 0x29, 0xef, 0xf0, 0xab, 0x29, + 0x8e, 0xbe, 0x19, 0x58, 0x3e, 0x56, 0x33, 0xbd, 0xaa, 0xb1, 0xfd, 0x79, + 0x3f, 0xcd, 0xe0, 0x7c, 0xdb, 0x4f, 0xa0, 0xcd, 0xb7, 0xdd, 0xde, 0xaa, + 0xf3, 0x58, 0x23, 0x30, 0xe2, 0xcc, 0xd0, 0x50, 0xe6, 0xb9, 0x09, 0xa3, + 0xa1, 0x6a, 0x60, 0xf4, 0x16, 0x75, 0x66, 0x31, 0x16, 0xe3, 0xd1, 0x5f, + 0x20, 0x91, 0x57, 0xf3, 0x70, 0x35, 0x64, 0x7d, 0x14, 0x60, 0x6b, 0x0e, + 0xb0, 0xdf, 0x17, 0x41, 0x3c, 0xaf, 0x74, 0xca, 0x89, 0x39, 0x37, 0x52, + 0xb2, 0x20, 0x00, 0xdc, 0x2d, 0x96, 0x78, 0x7e, 0xfe, 0x60, 0xdf, 0x69, + 0x26, 0x00, 0xa1, 0x0a, 0x1b, 0x90, 0x6c, 0x2c, 0x96, 0x22, 0x1f, 0x9a, + 0x33, 0xf0, 0xf9, 0xa7, 0xaf, 0x7f, 0x53, 0x50, 0xbb, 0x42, 0xf3, 0x72, + 0x10, 0xaf, 0xdd, 0xee, 0x0f, 0x31, 0x2a, 0x92, 0xdf, 0x50, 0xc8, 0xc9, + 0x9f, 0x12, 0x5e, 0x2c, 0xb0, 0xcc, 0xc9, 0x32, 0x8f, 0x00, 0x73, 0x45, + 0x7e, 0x0f, 0x31, 0x4a, 0x05, 0xea, 0x32, 0x63, 0x8e, 0xb9, 0x8b, 0x5a, + 0xc3, 0xa3, 0x5f, 0x23, 0x43, 0x61, 0xec, 0x35, 0xd4, 0x8e, 0x95, 0x15, + 0x81, 0x13, 0xa3, 0xac, 0x0f, 0x3f, 0x3b, 0xb5, 0xe0, 0x9c, 0xf9, 0x35, + 0xd8, 0x09, 0xd9, 0x50, 0x7a, 0xc4, 0x78, 0x47, 0x34, 0x28, 0xe6, 0xa5, + 0x33, 0x4d, 0x40, 0x1b, 0x6a, 0x75, 0xed, 0x22, 0x20, 0x65, 0x7f, 0x57, + 0xc4, 0x46, 0x98, 0x62, 0xe0, 0xd6, 0xc0, 0xa7, 0x63, 0xa6, 0x29, 0x9a, + 0x0d, 0xe2, 0x49, 0x55, 0x20, 0x1f, 0x96, 0xef, 0x76, 0x77, 0xd0, 0xc7, + 0xa6, 0xfb, 0x2a, 0x0c, 0x36, 0x4a, 0x65, 0xb9, 0xf6, 0xa5, 0x8a, 0xa3, + 0x46, 0x9a, 0x2a, 0x48, 0x7e, 0xed, 0x9a, 0x83, 0x3d, 0x26, 0x19, 0x5e, + 0x3a, 0xc5, 0x2e, 0xb6, 0xb2, 0x83, 0x0c, 0x0c, 0xe4, 0x92, 0x72, 0x1a, + 0xa4, 0x48, 0x30, 0x42, 0xd8, 0x06, 0x11, 0xcc, 0x07, 0xd4, 0x5a, 0xe8, + 0x7e, 0x3e, 0x4f, 0xd7, 0x3b, 0x67, 0x63, 0x45, 0xf8, 0x7a, 0x64, 0x7c, + 0xf2, 0x27, 0x98, 0xcd, 0xd2, 0x57, 0xa9, 0x2f, 0x24, 0x59, 0x27, 0x9d, + 0xeb, 0x78, 0xb9, 0x2f, 0xf0, 0xd6, 0x63, 0xbc, 0xcf, 0x84, 0x4a, 0x4f, + 0xdc, 0xc7, 0x7e, 0xde, 0xe6, 0xfe, 0x01, 0x79, 0x5d, 0x28, 0x1d, 0x70, + 0x26, 0xc3, 0x72, 0x10, 0xc5, 0x44, 0x49, 0x43, 0xc0, 0xc0, 0x20, 0x20, + 0x6a, 0xa7, 0xb5, 0xfa, 0xf3, 0x5d, 0x72, 0x7f, 0x13, 0x78, 0xa8, 0x81, + 0xe2, 0xc4, 0xcb, 0x93, 0x01, 0xbb, 0x82, 0x9a, 0x5a, 0xab, 0x6d, 0x18, + 0x09, 0x9c, 0x05, 0x8c, 0xfd, 0xdf, 0x1c, 0x51, 0x75, 0x02, 0x6a, 0x9e, + 0x1b, 0xd1, 0xd3, 0xf1, 0xdd, 0x98, 0x27, 0x59, 0xb3, 0x2e, 0x2a, 0x7c, + 0x47, 0x67, 0xb8, 0xfb, 0x78, 0x8e, 0x57, 0x04, 0xdc, 0xb8, 0x7e, 0x06, + 0x27, 0x04, 0xd2, 0x05, 0x9d, 0x1b, 0x79, 0x58, 0x93, 0x5b, 0x15, 0xfd, + 0xb7, 0x95, 0xd5, 0x0c, 0xb3, 0xa8, 0x50, 0x56, 0xb3, 0xc1, 0x57, 0x3d, + 0x13, 0x86, 0xf1, 0x2b, 0x40, 0x21, 0x76, 0xe0, 0xc9, 0x25, 0x77, 0xdc, + 0x5b, 0x29, 0xc6, 0xdd, 0xda, 0xc1, 0xc9, 0x27, 0x79, 0x03, 0x19, 0x95, + 0x4f, 0x47, 0xc0, 0xf5, 0x58, 0x98, 0xad, 0xac, 0xe1, 0xc7, 0x64, 0x13, + 0x15, 0x6c, 0xbe, 0x05, 0xf9, 0x8f, 0xe0, 0x2f, 0xeb, 0x33, 0x96, 0x20, + 0xfc, 0xc2, 0x04, 0x4d, 0x8f, 0xda, 0xaa, 0x25, 0xe2, 0x23, 0x71, 0x1e, + 0x2b, 0xb8, 0x7d, 0x79, 0x02, 0xa3, 0x42, 0x2f, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x27, 0x2b, 0xf7, 0xff, 0xc5, 0x9e, 0xae, 0x17, + 0xc7, 0xdd, 0x61, 0x64, 0x7a, 0xbd, 0x3b, 0x4a, 0x15, 0x3a, 0xf8, 0xbb, + 0xf5, 0x96, 0x6b, 0x22, 0x86, 0x60, 0x3b, 0x06, 0x19, 0x6b, 0xed, 0x2e, + 0x2e, 0xa2, 0xc9, 0xe7, 0x1a, 0xe1, 0x73, 0x7f, 0x05, 0x05, 0x82, 0xe3, + 0xb3, 0x2d, 0xa9, 0xd0, 0xb7, 0xb9, 0xc9, 0xa2, 0xd5, 0x72, 0xcc, 0x71, + 0x2e, 0x9c, 0x31, 0x65, 0x19, 0xcf, 0x5e, 0x2f, 0x2a, 0xab, 0xd1, 0x8d, + 0xbc, 0x62, 0x5a, 0xf0, 0x71, 0xe3, 0x13, 0x6b, 0xae, 0xaf, 0x0e, 0x6d, + 0xb0, 0xb1, 0x7a, 0x9f, 0xea, 0x00, 0x6f, 0xe3, 0x2f, 0x6d, 0xf1, 0xab, + 0x33, 0x27, 0x6a, 0x0f, 0x85, 0x5d, 0xeb, 0xa9, 0xaf, 0xc5, 0x64, 0x92, + 0x7a, 0xbf, 0xd5, 0xea, 0x67, 0xb0, 0x14, 0xfd, 0xa6, 0xb1, 0xe6, 0x26, + 0xc6, 0xfe, 0xea, 0x1d, 0xad, 0xe0, 0x68, 0x00, 0x2e, 0x72, 0xe5, 0x10, + 0x2d, 0x3d, 0x5c, 0x2f, 0x9d, 0x28, 0xd0, 0x7e, 0x76, 0xb2, 0x9f, 0x25, + 0xf3, 0x2b, 0x50, 0x0c, 0x10, 0x8b, 0xf9, 0x14, 0x12, 0x26, 0x12, 0xf6, + 0x6e, 0x11, 0xe3, 0xcc, 0x5e, 0xfc, 0xb4, 0x16, 0x27, 0xec, 0x86, 0x3d, + 0x64, 0xae, 0xbe, 0x99, 0xf1, 0xc3, 0xc4, 0x06, 0xbf, 0x63, 0xca, 0xe5, + 0x3f, 0x85, 0x6d, 0x13, 0x40, 0x77, 0x94, 0x1c, 0xaa, 0xee, 0x62, 0x4d, + 0xaf, 0x27, 0x5c, 0x23, 0xd6, 0xfb, 0xf9, 0xa0, 0x36, 0x9f, 0x32, 0x80, + 0xf3, 0x65, 0x47, 0xe5, 0xbc, 0xa6, 0x27, 0x0f, 0x5a, 0x80, 0x1f, 0x14, + 0xe5, 0x32, 0xc5, 0xd7, 0x07, 0x90, 0xdc, 0xb9, 0xa0, 0x66, 0x22, 0x2c, + 0x3f, 0x8e, 0x7a, 0x39, 0x26, 0x08, 0x40, 0x60, 0x05, 0xf1, 0x88, 0x07, + 0xa3, 0x51, 0xa0, 0x63, 0xbe, 0x42, 0x64, 0x4c, 0xcf, 0x9a, 0xd4, 0xeb, + 0x1f, 0x87, 0xbb, 0x1a, 0x15, 0x98, 0xea, 0x0f, 0x75, 0xb3, 0xfa, 0x48, + 0x37, 0xc3, 0x4d, 0x97, 0xb1, 0xc2, 0x7f, 0xb7, 0xf1, 0x39, 0x10, 0x33, + 0xd0, 0x19, 0x0f, 0x3f, 0xed, 0xb2, 0xc5, 0xef, 0x72, 0xed, 0x9d, 0x2a, + 0x77, 0x99, 0xca, 0x0c, 0x6a, 0x19, 0xb9, 0xc9, 0x4c, 0xab, 0x2c, 0x6b, + 0x87, 0x02, 0x23, 0x2d, 0x1b, 0xfd, 0x25, 0x6b, 0x0f, 0x7e, 0xce, 0x14, + 0x0d, 0x9a, 0x54, 0x80, 0xa1, 0xa8, 0x02, 0xa9, 0x7f, 0x24, 0xf4, 0x03, + 0x0b, 0xda, 0xe6, 0x77, 0x98, 0x31, 0x31, 0xc7, 0xc9, 0x0a, 0x01, 0x50, + 0x78, 0x0a, 0xf3, 0x09, 0x42, 0x9e, 0x3b, 0x7f, 0xa8, 0x69, 0x1d, 0x35, + 0xa7, 0xf4, 0x84, 0x5b, 0x23, 0x84, 0xc1, 0x1b, 0x3f, 0xf2, 0xa9, 0x3b, + 0x94, 0x37, 0xb0, 0x39, 0xdf, 0x11, 0xf9, 0x6d, 0x9e, 0xf2, 0x31, 0x9a, + 0xdb, 0x70, 0x9b, 0x99, 0xd8, 0x42, 0xbf, 0x8e, 0x19, 0x2e, 0x82, 0xc5, + 0xcc, 0xc9, 0x1f, 0x1b, 0x1b, 0x3c, 0x98, 0x3e, 0xda, 0xd8, 0x05, 0xc7, + 0xd9, 0x35, 0xd0, 0x66, 0x8b, 0x59, 0xb3, 0x44, 0x9b, 0xfe, 0xb8, 0x18, + 0xda, 0x51, 0xdd, 0x6d, 0x9a, 0x6b, 0xcf, 0x0e, 0xc0, 0x9b, 0x30, 0x2d, + 0xb6, 0xde, 0x27, 0x5a, 0x52, 0x3f, 0x0a, 0x8d, 0x26, 0x66, 0xda, 0x49, + 0xb6, 0xff, 0xbd, 0x60, 0x46, 0xb9, 0xad, 0x3a, 0xdf, 0xa7, 0xc8, 0xca, + 0x3a, 0xd8, 0x8d, 0x9f, 0x24, 0xe6, 0x38, 0x0e, 0x61, 0xc0, 0xc3, 0x77, + 0x7f, 0x09, 0x21, 0xd1, 0x96, 0xe1, 0xce, 0x9b, 0x3c, 0xdf, 0x3d, 0x94, + 0xbd, 0xde, 0xdd, 0x8d, 0xc4, 0x7a, 0x19, 0x65, 0x55, 0x1d, 0x1d, 0xa7, + 0x01, 0x07, 0xba, 0x1c, 0x1f, 0x00, 0x86, 0xe7, 0xff, 0x38, 0xc3, 0x4e, + 0xa9, 0xfc, 0x95, 0x83, 0xfc, 0x44, 0xa7, 0xdb, 0x2e, 0x6a, 0x7d, 0xdb, + 0x4f, 0x16, 0x0d, 0x8e, 0xb1, 0xed, 0xe3, 0xc8, 0xf5, 0x12, 0x96, 0x2f, + 0xde, 0x50, 0x57, 0xbe, 0xa4, 0xa7, 0x7f, 0x37, 0xd8, 0x62, 0x1c, 0xa6, + 0xcf, 0xda, 0x39, 0x49, 0x45, 0x40, 0x9b, 0xb2, 0xcd, 0x68, 0x71, 0x3f, + 0xef, 0x77, 0xc6, 0x68, 0x4a, 0x63, 0x7a, 0x25, 0xf9, 0xda, 0x98, 0x15, + 0x99, 0xc3, 0x4a, 0xea, 0x44, 0x6b, 0x9c, 0xc1, 0x24, 0x7d, 0x79, 0x47, + 0x3c, 0x9a, 0xef, 0xc7, 0x80, 0xf5, 0xec, 0xf8, 0x74, 0xc5, 0x24, 0x25, + 0x52, 0x3c, 0x72, 0x22, 0x19, 0x70, 0x46, 0x9c, 0x06, 0x6d, 0x56, 0x2e, + 0x23, 0x24, 0x01, 0x6e, 0x12, 0x46, 0xb4, 0x01, 0x3f, 0x12, 0xc7, 0x7d, + 0x4f, 0xbf, 0x3e, 0x5e, 0x2e, 0x85, 0x6d, 0x47, 0x7e, 0x9f, 0xd7, 0x27, + 0x03, 0x90, 0x05, 0x8a, 0xc6, 0xb8, 0x6b, 0xf1, 0x48, 0xbb, 0x7e, 0xfe, + 0xe1, 0x04, 0xdd, 0x02, 0x59, 0x1b, 0xe7, 0xab, 0x58, 0x76, 0xf0, 0xa8, + 0x48, 0xb9, 0x22, 0xa0, 0xd4, 0x7a, 0xc0, 0x12, 0xb9, 0x6f, 0x73, 0x3e, + 0x00, 0x37, 0x59, 0xf7, 0xd8, 0xf7, 0x32, 0x2e, 0x1b, 0x68, 0x6c, 0xbb, + 0x53, 0x1a, 0x23, 0x24, 0x9e, 0x62, 0xab, 0x5b, 0xc6, 0xed, 0x76, 0x7c, + 0x21, 0x9a, 0x15, 0x27, 0x3b, 0xe4, 0x0a, 0xf0, 0x92, 0xf4, 0x63, 0xd2, + 0x1b, 0x64, 0x88, 0x04, 0xf3, 0x58, 0x0d, 0xa7, 0x6f, 0xf1, 0xeb, 0x13, + 0x11, 0xb1, 0x54, 0x07, 0xd2, 0xb0, 0x07, 0x32, 0x60, 0xc8, 0xc5, 0x10, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x14, 0x59, 0xc1, 0x48, + 0x92, 0x47, 0x69, 0x62, 0x94, 0xff, 0x44, 0x62, 0x02, 0xe9, 0x02, 0x51, + 0x94, 0xed, 0x1d, 0x33, 0x13, 0xd9, 0x1f, 0xdc, 0x3f, 0x01, 0x87, 0x52, + 0xc5, 0xa7, 0xb6, 0x13, 0xc7, 0x0d, 0x4c, 0x9e, 0x07, 0x0c, 0x36, 0x57, + 0x26, 0x8f, 0xb4, 0x0e, 0x4b, 0x8d, 0x77, 0x31, 0xc1, 0x74, 0x1c, 0x0e, + 0x93, 0xca, 0x2e, 0x2b, 0x41, 0x7c, 0x83, 0x9e, 0xcf, 0xec, 0xa7, 0x27, + 0xe6, 0x58, 0xb7, 0x8a, 0x89, 0x6b, 0xaf, 0x06, 0xed, 0xfe, 0xa8, 0x36, + 0xe8, 0x52, 0x58, 0xa4, 0xbf, 0x13, 0x50, 0x6d, 0xf8, 0x15, 0x17, 0x51, + 0x36, 0xee, 0xc2, 0x61, 0x63, 0xc7, 0x8a, 0x26, 0xd4, 0xd4, 0xa4, 0xdd, + 0xee, 0x3b, 0x8c, 0x82, 0x5d, 0xb5, 0xe9, 0x16, 0xe3, 0x95, 0x55, 0xcd, + 0x07, 0x16, 0x4e, 0x36, 0xc8, 0xe8, 0x90, 0x35, 0xee, 0xaa, 0x1c, 0xa7, + 0x88, 0x70, 0x59, 0x2f, 0x0e, 0xc3, 0xfb, 0x79, 0xc6, 0xc5, 0x60, 0x54, + 0xca, 0xe1, 0x3b, 0x82, 0xf3, 0x5b, 0x83, 0xa8, 0x56, 0x5a, 0x50, 0xda, + 0x46, 0xe3, 0x7c, 0x34, 0x69, 0x00, 0x6d, 0x53, 0x50, 0x75, 0xd2, 0x29, + 0xa1, 0x99, 0xe5, 0x71, 0xc1, 0xbc, 0xd6, 0xd9, 0x6d, 0xc6, 0x41, 0x7b, + 0xc3, 0xf0, 0x05, 0xec, 0x12, 0xa6, 0x1c, 0x1b, 0x45, 0xa0, 0x27, 0x42, + 0x54, 0x63, 0x06, 0x56, 0x19, 0x6f, 0xe7, 0x2b, 0xe9, 0x07, 0x3f, 0xdb, + 0xf7, 0xab, 0x8c, 0xdc, 0x31, 0x7a, 0x5b, 0x57, 0x0e, 0xf6, 0xb9, 0x66, + 0xbb, 0x79, 0x27, 0xa0, 0x48, 0x18, 0x89, 0x40, 0x1a, 0x41, 0x7f, 0x59, + 0xe2, 0xbf, 0x42, 0x20, 0xf2, 0x88, 0x5d, 0x2a, 0x83, 0x42, 0x25, 0xd3, + 0x2c, 0x48, 0x6a, 0x97, 0x04, 0x01, 0x73, 0xdd, 0xf1, 0xe9, 0x36, 0x35, + 0x28, 0x94, 0xd7, 0xc4, 0x33, 0x84, 0x0c, 0x89, 0x1c, 0x12, 0x0d, 0x18, + 0x92, 0x08, 0x73, 0xac, 0x2b, 0xee, 0x1a, 0x4f, 0x38, 0xd8, 0xf0, 0xfc, + 0x21, 0xdc, 0x0a, 0xa4, 0xf1, 0xa3, 0xc9, 0x47, 0xc6, 0x2f, 0xdd, 0x4a, + 0x02, 0x9a, 0xd1, 0x37, 0x73, 0xf7, 0xe2, 0x0f, 0x9f, 0x70, 0x20, 0xe6, + 0x8c, 0xd4, 0x8f, 0xb0, 0x70, 0xab, 0x64, 0x0b, 0xc7, 0xce, 0xcf, 0x68, + 0x4b, 0x73, 0xc9, 0x7f, 0xb4, 0xd0, 0x1f, 0xea, 0xe1, 0x04, 0x9f, 0x05, + 0x98, 0x7c, 0x09, 0x11, 0x1f, 0x9e, 0xd0, 0x82, 0xd4, 0x26, 0xa2, 0x68, + 0x09, 0x80, 0xf9, 0x53, 0xcb, 0x51, 0x38, 0x43, 0xc3, 0xe4, 0x07, 0x82, + 0x09, 0x04, 0x92, 0xda, 0xb1, 0xb9, 0x20, 0x06, 0xd9, 0x3f, 0x6a, 0x08, + 0x30, 0x47, 0x24, 0x0b, 0x09, 0xaa, 0x91, 0x85, 0x0c, 0xb1, 0xb0, 0x36, + 0x10, 0x88, 0x8a, 0x24, 0x41, 0xf9, 0x7d, 0x70, 0xad, 0x5d, 0x1d, 0x09, + 0xad, 0x72, 0xbc, 0xf4, 0x19, 0x50, 0xd9, 0x2a, 0xb6, 0x45, 0x35, 0xd8, + 0xf1, 0x16, 0xe6, 0x79, 0x38, 0xca, 0x4a, 0xda, 0x03, 0x44, 0xb2, 0xcc, + 0x81, 0xd9, 0x31, 0xa0, 0xe9, 0xfc, 0x2a, 0x40, 0xd0, 0x3f, 0x6a, 0x45, + 0xce, 0x09, 0x00, 0x0e, 0xdb, 0xae, 0xaa, 0x1f, 0xc9, 0x2d, 0x31, 0x8a, + 0x05, 0xec, 0x2a, 0x1d, 0x80, 0x10, 0x28, 0xbd, 0x78, 0x53, 0x79, 0xb3, + 0xda, 0x6e, 0xc8, 0x16, 0x6d, 0x07, 0x96, 0xbc, 0xd6, 0x70, 0xe7, 0x26, + 0xdc, 0x99, 0xe7, 0xf8, 0xbb, 0xe9, 0x84, 0xf7, 0x43, 0x3f, 0x64, 0x76, + 0xc5, 0x9f, 0xf3, 0xcd, 0xcb, 0x01, 0x71, 0x87, 0x20, 0x4f, 0xed, 0xd1, + 0x62, 0x30, 0x7e, 0xaf, 0xf5, 0x15, 0x12, 0x15, 0xc3, 0xd2, 0x35, 0xab, + 0xf4, 0x25, 0x60, 0xd9, 0xaa, 0xa5, 0x35, 0x20, 0x11, 0x4e, 0x2b, 0xb0, + 0xb9, 0xfc, 0x39, 0x53, 0x70, 0x80, 0xb5, 0x7d, 0x14, 0x0f, 0x73, 0x32, + 0xb7, 0x56, 0xb6, 0x08, 0x97, 0xab, 0x75, 0x93, 0xd6, 0x7f, 0xd1, 0x46, + 0xfe, 0x94, 0x63, 0xcf, 0xf8, 0x0d, 0x24, 0x1a, 0xc4, 0x49, 0x7c, 0x02, + 0x26, 0x60, 0xe3, 0x12, 0x4c, 0x0c, 0xa0, 0xb1, 0x0a, 0x87, 0x1c, 0x27, + 0x08, 0xc5, 0xa7, 0xb4, 0xb0, 0x14, 0x56, 0xdd, 0xaf, 0x52, 0xf8, 0x12, + 0xbd, 0xc5, 0xc9, 0x42, 0xa8, 0xa6, 0x2a, 0xaa, 0x90, 0x56, 0x5c, 0xa9, + 0x9b, 0x03, 0x86, 0x08, 0x4b, 0x16, 0x25, 0x17, 0xd3, 0x3d, 0x5c, 0x94, + 0x70, 0x42, 0x98, 0x1f, 0xe4, 0x7b, 0x07, 0xcc, 0xff, 0x09, 0xc6, 0x32, + 0xcb, 0xba, 0x8c, 0x45, 0xf1, 0x2e, 0xa2, 0xfd, 0x8b, 0x8a, 0x4e, 0x26, + 0xd3, 0x50, 0x5f, 0x1f, 0xa0, 0x8d, 0x58, 0x92, 0x1a, 0x28, 0xa3, 0xf7, + 0x1f, 0x88, 0xfa, 0xed, 0xfc, 0x3a, 0xb7, 0x4f, 0x0d, 0xed, 0x53, 0x80, + 0xe7, 0x5c, 0x0e, 0x5d, 0xd6, 0x5f, 0x7e, 0x8f, 0x32, 0x2b, 0x2b, 0x1e, + 0x9f, 0x4f, 0x2a, 0xc7, 0x02, 0x3f, 0x59, 0xf4, 0x4d, 0xd9, 0x96, 0x71, + 0xac, 0xba, 0xe1, 0xb3, 0x53, 0x44, 0x8f, 0x48, 0x85, 0xd0, 0xab, 0x0c, + 0x6c, 0x7e, 0xfe, 0x8d, 0xd6, 0xd1, 0x9c, 0x2e, 0x18, 0xdb, 0x91, 0x95, + 0xa7, 0x2c, 0x48, 0xcf, 0xdf, 0x4b, 0xd3, 0x23, 0xf8, 0x7c, 0xa4, 0x88, + 0x41, 0xe1, 0xd1, 0x3a, 0x80, 0xad, 0x0d, 0x82, 0xa8, 0xb0, 0x40, 0x49, + 0x46, 0x17, 0xac, 0x08, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x94, 0x56, 0x0e, 0xf6, 0xea, 0x5b, 0xf0, 0xd7, 0xcd, 0x04, 0xd7, 0xe3, + 0xed, 0x91, 0x01, 0xf8, 0xb5, 0x22, 0xb9, 0xf0, 0xd4, 0x86, 0x0f, 0xa0, + 0xc0, 0x78, 0x04, 0x74, 0xbf, 0xaf, 0x03, 0x1a, 0x00, 0x9e, 0x31, 0x95, + 0xc3, 0xbf, 0xaf, 0x14, 0x29, 0x11, 0x4c, 0x3b, 0xcf, 0xf8, 0x39, 0x6a, + 0x43, 0xec, 0xbc, 0x99, 0x03, 0x81, 0xf6, 0xf9, 0xa6, 0xef, 0xa2, 0xe6, + 0xea, 0x06, 0xa2, 0x24, 0xde, 0x2e, 0x33, 0x27, 0x44, 0x4f, 0xf4, 0xe8, + 0x0c, 0x4c, 0x9b, 0xde, 0x26, 0x6f, 0xd1, 0x0e, 0x28, 0xfb, 0x37, 0xf5, + 0x57, 0x3e, 0x44, 0xc3, 0x74, 0x2e, 0x46, 0xda, 0x0a, 0xed, 0xdb, 0x20, + 0x15, 0xb9, 0x3e, 0x69, 0x3e, 0xce, 0x4d, 0x53, 0x52, 0xde, 0x73, 0x9e, + 0x62, 0x87, 0x1b, 0x99, 0xce, 0xbf, 0x48, 0xa0, 0x87, 0x60, 0x4e, 0x64, + 0xb0, 0xab, 0x93, 0x7a, 0x23, 0xab, 0x19, 0x1c, 0x31, 0x02, 0x41, 0x6e, + 0x51, 0x1c, 0x28, 0x74, 0xbe, 0x8b, 0xa0, 0x06, 0xda, 0x97, 0xa5, 0xf9, + 0x98, 0xb0, 0x3c, 0xa0, 0x7a, 0x8f, 0xf8, 0x60, 0xc2, 0x9a, 0xbd, 0x71, + 0x2d, 0xb3, 0x88, 0x20, 0xd1, 0x8f, 0xa6, 0x0c, 0x80, 0x9f, 0x3f, 0xb8, + 0x50, 0xa4, 0x42, 0xaa, 0xcd, 0xff, 0xf3, 0x23, 0xc3, 0x7b, 0x50, 0x72, + 0x2b, 0xba, 0xf1, 0x08, 0xc4, 0xdd, 0x46, 0x21, 0x8c, 0xa4, 0x7c, 0x24, + 0x4e, 0x3a, 0xbc, 0x1f, 0x72, 0xb1, 0x24, 0xc0, 0xad, 0xbd, 0xeb, 0xa9, + 0xd8, 0x88, 0x42, 0x96, 0xe7, 0xfd, 0x0d, 0x9f, 0xaa, 0x31, 0xef, 0x1d, + 0x7c, 0x24, 0xe0, 0x36, 0x8e, 0xef, 0x98, 0x22, 0xb7, 0xc5, 0xef, 0x4e, + 0xed, 0x15, 0x9e, 0xa5, 0x0c, 0x4a, 0xb9, 0xf1, 0x74, 0x79, 0x70, 0xc3, + 0x8c, 0x4d, 0x75, 0x57, 0x01, 0x35, 0x11, 0x8f, 0xc5, 0x83, 0x65, 0x6f, + 0xf0, 0xcd, 0xe4, 0x10, 0x6d, 0x5b, 0x7e, 0x4f, 0xab, 0x1b, 0x7f, 0xe9, + 0xea, 0x08, 0xfe, 0x3c, 0xa2, 0x84, 0x67, 0x39, 0x74, 0x62, 0x8f, 0x20, + 0x78, 0x0a, 0x2c, 0x09, 0x1e, 0xc2, 0xe2, 0x38, 0x44, 0xa2, 0x31, 0x1d, + 0x16, 0x58, 0x8b, 0xd4, 0x07, 0x02, 0x6e, 0xa2, 0x01, 0x47, 0x12, 0xb9, + 0x24, 0x9b, 0xcc, 0x3f, 0x0d, 0x9e, 0x1e, 0x22, 0xdf, 0x19, 0x95, 0xdd, + 0x7c, 0x16, 0x17, 0x99, 0x9c, 0xde, 0xbb, 0x2d, 0xd2, 0x3d, 0xbc, 0x97, + 0x6d, 0x0f, 0xf4, 0x22, 0xb0, 0x9f, 0xf0, 0x67, 0x03, 0xcd, 0x49, 0x3f, + 0x1e, 0xb3, 0x67, 0xf6, 0x73, 0xd9, 0xd8, 0xb5, 0x38, 0xa2, 0xd9, 0x2b, + 0xf8, 0x0c, 0x58, 0x0e, 0xfd, 0xd4, 0x58, 0xac, 0x12, 0x54, 0x9b, 0x74, + 0xc6, 0xb9, 0x3d, 0x99, 0xd6, 0xad, 0xc9, 0xde, 0xdf, 0xf5, 0xf4, 0xc8, + 0xff, 0xfc, 0x8a, 0xd2, 0x24, 0xb8, 0x92, 0x80, 0x8b, 0xa4, 0x98, 0x29, + 0x35, 0xbc, 0x30, 0x54, 0xf1, 0x46, 0x4c, 0x06, 0xb8, 0xfc, 0xd3, 0x5f, + 0x77, 0xd8, 0x82, 0x53, 0xa9, 0xbb, 0x75, 0x78, 0xc6, 0x70, 0xd7, 0x23, + 0xbb, 0x54, 0xdd, 0x07, 0x9a, 0x0c, 0xe7, 0x0e, 0x87, 0x2b, 0x30, 0xb9, + 0x6f, 0x4a, 0xdb, 0x5e, 0xb5, 0xfb, 0x09, 0xa9, 0x2e, 0xf4, 0x2b, 0x3b, + 0x34, 0xf6, 0xe5, 0xc4, 0x02, 0xef, 0x8a, 0x6d, 0x5d, 0xd9, 0x3e, 0xe3, + 0x92, 0xa7, 0x06, 0x1a, 0xb2, 0xde, 0xb1, 0x33, 0xb7, 0x43, 0x63, 0x3a, + 0xaf, 0x1a, 0x7b, 0x35, 0x86, 0x3b, 0x3c, 0xc5, 0xba, 0x4d, 0x5b, 0x7f, + 0x90, 0xff, 0x40, 0xb7, 0xdb, 0x4e, 0xf8, 0x81, 0x99, 0x56, 0x4d, 0x25, + 0xd9, 0x93, 0x6f, 0x3a, 0x3a, 0x37, 0x98, 0x44, 0x6e, 0xc4, 0x41, 0xe8, + 0x04, 0x47, 0xed, 0x65, 0x3f, 0x64, 0x94, 0x7c, 0xe2, 0x24, 0xae, 0xda, + 0x51, 0xa2, 0xd8, 0xa4, 0xd1, 0x80, 0x85, 0x1b, 0xb3, 0x68, 0x4f, 0x1f, + 0xf0, 0x9c, 0xd0, 0x78, 0xdd, 0x3d, 0xa0, 0x72, 0x4e, 0x70, 0x36, 0x4a, + 0x76, 0x2d, 0x01, 0xb1, 0x03, 0x3b, 0x52, 0xef, 0xc3, 0x13, 0x35, 0x69, + 0x1b, 0x87, 0x8e, 0x04, 0xe7, 0x84, 0x57, 0x1d, 0x44, 0xe0, 0x87, 0x46, + 0x38, 0x1b, 0xf4, 0xda, 0x50, 0x29, 0xc8, 0xf8, 0x6e, 0x4f, 0xb1, 0x0b, + 0x25, 0xcc, 0x35, 0x20, 0x43, 0x31, 0x8d, 0xde, 0x6f, 0xcb, 0x78, 0x2c, + 0x40, 0x41, 0xd0, 0x52, 0xdb, 0xa9, 0x66, 0x64, 0x40, 0x40, 0x6d, 0xac, + 0xb1, 0x83, 0x5f, 0x08, 0xce, 0x42, 0xf4, 0x53, 0x14, 0x19, 0xe1, 0x86, + 0xbf, 0xc0, 0x65, 0xf7, 0x2c, 0xb1, 0xb5, 0x23, 0x29, 0x8f, 0x5f, 0xe8, + 0xf6, 0x45, 0x24, 0x35, 0xe5, 0xdf, 0x38, 0x5b, 0x2c, 0xe8, 0x58, 0x55, + 0x61, 0xfc, 0xbe, 0xcd, 0x4a, 0x1e, 0x65, 0xbc, 0x3a, 0xce, 0xd9, 0x23, + 0x4f, 0xd5, 0x20, 0x07, 0xd2, 0x08, 0x42, 0xdf, 0x11, 0xdb, 0x0c, 0xcc, + 0x28, 0x24, 0xb2, 0x62, 0x3c, 0xc0, 0xe8, 0xf3, 0x90, 0x51, 0xe8, 0xdd, + 0x8b, 0xd8, 0x50, 0xd7, 0x83, 0x7a, 0xff, 0x47, 0x95, 0x63, 0x76, 0x15, + 0xde, 0x3e, 0x54, 0x03, 0xce, 0xd1, 0x5b, 0xe9, 0xa2, 0x50, 0x16, 0xc6, + 0x3c, 0xde, 0xb5, 0xed, 0x56, 0xfd, 0xf3, 0xef, 0x17, 0x71, 0x2f, 0x57, + 0x85, 0x34, 0xbc, 0x5d, 0x3b, 0x86, 0x31, 0x18, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x54, 0xc0, 0xc9, 0xc9, 0x02, 0x31, 0xf8, 0x30, + 0x7f, 0x05, 0x0c, 0xc9, 0xca, 0x18, 0x29, 0x6a, 0x8e, 0xd4, 0x35, 0xd5, + 0xc9, 0x39, 0xf6, 0x6f, 0x11, 0xc1, 0x7c, 0x74, 0x0d, 0xc5, 0xb6, 0x0d, + 0xb1, 0xc1, 0x6c, 0x99, 0xee, 0x49, 0xb2, 0xae, 0xd5, 0xa0, 0x60, 0xe1, + 0xae, 0xfa, 0x95, 0xe2, 0xc2, 0x75, 0xb8, 0x19, 0x3e, 0x6e, 0x04, 0x78, + 0x5a, 0x4b, 0xf4, 0xc2, 0x80, 0x84, 0x81, 0x27, 0x96, 0x24, 0x9f, 0xe9, + 0x4a, 0x23, 0x67, 0xcf, 0xc0, 0xc9, 0x5c, 0xf7, 0x90, 0x40, 0x84, 0x78, + 0x17, 0xc5, 0x5f, 0x2e, 0xdd, 0xde, 0x64, 0x8f, 0xa4, 0xde, 0x28, 0x21, + 0x8d, 0x78, 0xb4, 0x1c, 0x6c, 0xa1, 0x03, 0x2e, 0x0c, 0x4a, 0x47, 0x55, + 0xac, 0x86, 0x54, 0xce, 0xd3, 0xad, 0x4a, 0xe7, 0x11, 0x74, 0xc8, 0x83, + 0x4a, 0xe8, 0xd6, 0x49, 0xa5, 0x0a, 0xa3, 0x30, 0x0f, 0xd5, 0x10, 0x20, + 0xae, 0x7d, 0x07, 0xb8, 0x48, 0x39, 0x4f, 0x16, 0xb0, 0xfe, 0x90, 0x4f, + 0xcf, 0xe7, 0xfc, 0x6c, 0xe2, 0xa5, 0xc3, 0x9e, 0x86, 0x9d, 0x67, 0x9e, + 0x8e, 0xc7, 0xd3, 0xa9, 0x46, 0xe7, 0x9d, 0x0e, 0x19, 0xb7, 0x1f, 0xba, + 0x7c, 0xb6, 0xa1, 0x44, 0x65, 0xe0, 0x02, 0x23, 0x57, 0xd7, 0xb8, 0x4d, + 0x4b, 0xbf, 0xf3, 0x35, 0x3b, 0xde, 0x18, 0xd1, 0x54, 0x06, 0xc3, 0x82, + 0xf6, 0x50, 0x0f, 0x02, 0x35, 0x6c, 0x21, 0x83, 0xf7, 0x9c, 0xcf, 0x4b, + 0x0e, 0x15, 0x6a, 0xd1, 0xac, 0x1b, 0x36, 0x70, 0xce, 0xe2, 0x07, 0x97, + 0xa4, 0x32, 0x5e, 0xef, 0xad, 0xbb, 0xfa, 0x5a, 0x5b, 0xa3, 0x44, 0x23, + 0xaa, 0x1c, 0xf7, 0x9d, 0x16, 0x4d, 0x26, 0xcf, 0xeb, 0x19, 0x08, 0x62, + 0x6d, 0x74, 0x0b, 0xf2, 0x79, 0x55, 0x10, 0xf8, 0xde, 0xe6, 0x4c, 0x56, + 0x03, 0x15, 0x6b, 0x16, 0xf1, 0x30, 0x02, 0x1a, 0x26, 0xb1, 0x0f, 0xfa, + 0x48, 0xa1, 0xa0, 0x73, 0xd8, 0x88, 0xc8, 0x06, 0xce, 0x08, 0x8d, 0xb0, + 0xe5, 0x2b, 0x89, 0xf5, 0xa3, 0x83, 0x65, 0xaf, 0x78, 0x30, 0x76, 0x26, + 0xe4, 0xb6, 0x39, 0x0c, 0x96, 0xb9, 0xc5, 0x77, 0x6f, 0x43, 0x06, 0x7b, + 0xbb, 0x4c, 0x40, 0xe0, 0x42, 0x5a, 0x2f, 0x62, 0x2c, 0xb5, 0x8b, 0x25, + 0x4b, 0x4d, 0x9a, 0x26, 0xa0, 0x31, 0x4f, 0x75, 0x1a, 0xf1, 0x80, 0x0e, + 0x4d, 0x79, 0xba, 0x33, 0x05, 0xef, 0xb1, 0x03, 0x77, 0xfd, 0x42, 0x32, + 0xe3, 0x68, 0x04, 0x63, 0x76, 0xd0, 0xb1, 0x0f, 0x0d, 0x59, 0xeb, 0x31, + 0x42, 0xd5, 0xaf, 0xe9, 0x3c, 0xc0, 0x08, 0x27, 0xd9, 0x0f, 0x89, 0xce, + 0x0a, 0x4c, 0x53, 0xb1, 0xeb, 0xa8, 0xd6, 0xc4, 0xfb, 0x89, 0x22, 0x35, + 0xba, 0x91, 0xb8, 0xc0, 0x23, 0xe3, 0x86, 0x62, 0x9a, 0x29, 0xef, 0x03, + 0x32, 0x97, 0xdf, 0x0e, 0x16, 0x5e, 0x41, 0xa5, 0x6c, 0xd3, 0x49, 0xdf, + 0x60, 0x71, 0xa9, 0x9d, 0xc4, 0xa1, 0xbc, 0x34, 0xbd, 0x00, 0x0c, 0xd3, + 0x25, 0x3e, 0x64, 0xe2, 0x9b, 0x2e, 0xb7, 0xb7, 0x00, 0x55, 0xd6, 0x28, + 0x4f, 0x6f, 0xa7, 0x9f, 0xb5, 0xcf, 0xfa, 0xa9, 0x3d, 0x20, 0xbd, 0xe0, + 0xc2, 0x49, 0x85, 0xf5, 0xed, 0x37, 0xff, 0x35, 0x9c, 0x03, 0x67, 0xec, + 0x3e, 0x9e, 0xee, 0xee, 0x0a, 0xf1, 0xaf, 0x13, 0x59, 0x0d, 0x08, 0x57, + 0x7c, 0x10, 0x7d, 0xe9, 0x02, 0x5a, 0x59, 0x4c, 0xef, 0xdc, 0x45, 0x20, + 0x16, 0xe3, 0x31, 0xad, 0xa9, 0xa1, 0xd1, 0xfe, 0x7c, 0xa7, 0x51, 0x9c, + 0xa9, 0x18, 0xef, 0x20, 0x8a, 0x87, 0x3c, 0x66, 0x4b, 0xff, 0x41, 0xeb, + 0x52, 0x60, 0xdf, 0x5f, 0xce, 0x15, 0x40, 0xcb, 0xcd, 0xad, 0xda, 0xd8, + 0x8e, 0x88, 0x52, 0xfd, 0xa2, 0x2c, 0x4b, 0x39, 0xbb, 0x7e, 0xe2, 0x1e, + 0xca, 0xca, 0xdb, 0xd9, 0x99, 0xcc, 0xb4, 0x51, 0xbc, 0xa4, 0xf9, 0x30, + 0x33, 0x03, 0x03, 0x60, 0xa2, 0xbd, 0xc8, 0x05, 0xd2, 0x56, 0xdd, 0x01, + 0xdb, 0xa7, 0x6c, 0x69, 0x4b, 0xa5, 0x8b, 0x15, 0x88, 0x94, 0x2e, 0x1d, + 0x3e, 0x08, 0x82, 0x74, 0xe2, 0x1c, 0xba, 0x6b, 0xe5, 0x8d, 0x41, 0xf8, + 0x64, 0x93, 0xcd, 0x6a, 0x44, 0x2e, 0x83, 0x76, 0xd6, 0xf9, 0xe8, 0x29, + 0x75, 0xf9, 0x0f, 0x09, 0x2b, 0xd6, 0xb7, 0x6c, 0x5e, 0xad, 0x46, 0x9d, + 0x7f, 0xc6, 0xe9, 0x61, 0x65, 0xe8, 0xc5, 0xf8, 0xda, 0x6b, 0xc6, 0xbc, + 0x2b, 0xb0, 0x6b, 0xc1, 0x89, 0x70, 0x0b, 0x80, 0x93, 0xf8, 0xef, 0x04, + 0xb5, 0xcc, 0xb2, 0x16, 0x01, 0x32, 0x48, 0xb1, 0x87, 0xd9, 0xc0, 0x81, + 0x6e, 0x36, 0xd3, 0xff, 0xcb, 0xea, 0xa8, 0xc1, 0x55, 0x8c, 0x26, 0xa3, + 0xfb, 0xba, 0x9a, 0xb1, 0xb8, 0x7c, 0x10, 0x16, 0x9e, 0xaa, 0x1e, 0x16, + 0xa7, 0x4e, 0xa3, 0xef, 0x05, 0x27, 0x78, 0x72, 0x3e, 0xae, 0xd1, 0x45, + 0x6f, 0x59, 0x7e, 0x45, 0x35, 0xc5, 0x49, 0x0d, 0x96, 0x55, 0xdc, 0x7f, + 0x4e, 0x92, 0x43, 0x0f, 0xfc, 0xfc, 0xae, 0x8e, 0xd0, 0x3e, 0xc7, 0x4d, + 0x26, 0xb5, 0x66, 0xfe, 0x01, 0x85, 0x6d, 0xa1, 0x3d, 0x99, 0x4f, 0x72, + 0x02, 0x3c, 0x38, 0x4d, 0x52, 0x19, 0xc3, 0x0f, 0x1d, 0xa1, 0x0e, 0x2f, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xa5, 0x6a, 0xee, 0xf7, + 0xe8, 0x8e, 0xad, 0x87, 0x4c, 0x67, 0x64, 0xe3, 0x59, 0xe0, 0x62, 0x69, + 0xf2, 0xc4, 0xbc, 0x6b, 0x80, 0xd5, 0x70, 0x8b, 0xb0, 0x71, 0x63, 0x83, + 0x58, 0x52, 0xee, 0x0f, 0x5e, 0xd8, 0x94, 0x32, 0x75, 0xe0, 0x38, 0x2c, + 0x10, 0x53, 0xc5, 0x65, 0x21, 0xb2, 0xfc, 0x39, 0x26, 0x8f, 0xfc, 0xa8, + 0x98, 0xa2, 0xea, 0x7b, 0x37, 0x4c, 0xd8, 0xcd, 0x28, 0xfd, 0x0a, 0x17, + 0xab, 0xea, 0xff, 0x85, 0x01, 0x8d, 0x8e, 0xb9, 0x0c, 0xce, 0x48, 0x5e, + 0xca, 0x36, 0x88, 0x5b, 0x27, 0x75, 0x39, 0x25, 0x5e, 0x1e, 0xfd, 0x24, + 0xd3, 0xb6, 0xd1, 0xfe, 0x38, 0x3c, 0x03, 0x1c, 0x01, 0xe2, 0x80, 0x9d, + 0xaa, 0x4e, 0x53, 0x98, 0x61, 0xcb, 0x54, 0x89, 0xed, 0x30, 0x96, 0xd3, + 0x28, 0x2f, 0x70, 0x22, 0x7c, 0x65, 0x09, 0x04, 0xca, 0xd3, 0x44, 0xe6, + 0xf1, 0x20, 0x5f, 0x07, 0x6d, 0xee, 0x63, 0x8c, 0x8c, 0x65, 0x79, 0x31, + 0x32, 0x58, 0xac, 0x8e, 0xcb, 0x32, 0x57, 0x7d, 0xa9, 0x71, 0xee, 0x13, + 0x57, 0x93, 0xe2, 0x7b, 0xd4, 0xad, 0x8d, 0xb2, 0x9e, 0xa2, 0x71, 0x02, + 0x66, 0x68, 0xde, 0x76, 0xc9, 0x83, 0x00, 0xf1, 0x96, 0xef, 0x49, 0xf2, + 0x6d, 0x10, 0x98, 0x3e, 0x1d, 0x09, 0xd4, 0x2b, 0x8d, 0xac, 0x17, 0x12, + 0x6e, 0x74, 0xc8, 0x09, 0xb1, 0x12, 0xee, 0x2a, 0xc6, 0xac, 0x70, 0x02, + 0x3f, 0x25, 0x81, 0xbf, 0x43, 0x52, 0x04, 0x68, 0x36, 0xa9, 0x0f, 0x55, + 0x05, 0xd2, 0x82, 0xa0, 0x49, 0x80, 0x87, 0x38, 0x78, 0x44, 0x51, 0xdf, + 0x42, 0xfe, 0x78, 0x14, 0xd1, 0xe4, 0xd6, 0x8c, 0xfc, 0xe2, 0x77, 0xad, + 0xa7, 0xb2, 0x4c, 0x25, 0xa3, 0xce, 0xf0, 0x98, 0xef, 0xd2, 0xd2, 0x32, + 0x59, 0x0e, 0xa1, 0xd6, 0x50, 0x8f, 0x16, 0x33, 0xeb, 0x82, 0x78, 0x1c, + 0xce, 0x18, 0xd3, 0x22, 0x04, 0xf1, 0x0b, 0x8b, 0x28, 0x67, 0x65, 0x87, + 0xb8, 0x75, 0xaf, 0xea, 0x96, 0x9c, 0x63, 0xde, 0x88, 0xc2, 0xa2, 0x2d, + 0x0d, 0x02, 0x2d, 0x8f, 0xf7, 0x2f, 0x74, 0x09, 0x7a, 0xda, 0x84, 0x10, + 0xe5, 0xec, 0x85, 0x05, 0xab, 0xf3, 0xdb, 0x42, 0x97, 0x7c, 0xcf, 0x1b, + 0x73, 0x1b, 0xcf, 0xe4, 0xf7, 0xb5, 0xf8, 0xcf, 0xeb, 0x9f, 0x4a, 0x9a, + 0xea, 0x3b, 0x4d, 0x05, 0x72, 0x40, 0x7f, 0xc6, 0x7c, 0x5c, 0xbf, 0xd7, + 0x45, 0x0c, 0x11, 0x25, 0x93, 0xd4, 0x07, 0x2c, 0x4f, 0xd5, 0x50, 0x52, + 0xc8, 0x5d, 0xbb, 0x3f, 0x46, 0x01, 0x8f, 0x51, 0x7c, 0x3f, 0x31, 0x14, + 0x66, 0xf8, 0xf6, 0x40, 0x4e, 0x5f, 0x95, 0x9f, 0x3f, 0x00, 0x78, 0x44, + 0x79, 0xdd, 0x5b, 0xef, 0x17, 0x76, 0xfc, 0xdf, 0xd5, 0x5a, 0x84, 0xf5, + 0x1d, 0x80, 0xfc, 0xf5, 0x63, 0xb2, 0x1c, 0x00, 0xde, 0x16, 0x54, 0x25, + 0x9b, 0x3c, 0x63, 0x5a, 0x1d, 0x9b, 0xd9, 0x46, 0xfc, 0xbc, 0xdd, 0x35, + 0x23, 0xb5, 0x73, 0xeb, 0xbd, 0x23, 0x4f, 0x5e, 0xd6, 0x29, 0x08, 0x04, + 0x3b, 0x1d, 0xe0, 0x2c, 0x67, 0xc7, 0x4b, 0xef, 0x07, 0xef, 0x1a, 0xe7, + 0xc0, 0x8c, 0xf0, 0xc9, 0x5a, 0x67, 0xe0, 0x3b, 0x73, 0xf7, 0x61, 0xb9, + 0x03, 0xaf, 0x94, 0x28, 0xb8, 0x9f, 0xc7, 0x55, 0x0a, 0xfa, 0xd5, 0x04, + 0x8b, 0x83, 0xb8, 0x30, 0xb9, 0x4e, 0x7a, 0x74, 0xee, 0x8a, 0x88, 0x76, + 0xc9, 0xc6, 0x0e, 0xb1, 0x9c, 0xa1, 0xd7, 0xda, 0x3f, 0xef, 0x7d, 0x27, + 0x11, 0xd2, 0xd7, 0x71, 0x2d, 0x85, 0x7e, 0x2d, 0x3a, 0x8d, 0xec, 0xd1, + 0xac, 0xb3, 0x1f, 0x58, 0xe4, 0x8b, 0x0b, 0x73, 0x63, 0x2f, 0x49, 0xb3, + 0x2c, 0xb5, 0x3f, 0x2d, 0xee, 0x41, 0x38, 0x6a, 0x50, 0x8f, 0x02, 0xa3, + 0xaf, 0xcf, 0x57, 0x1b, 0x96, 0x01, 0xe7, 0x90, 0xe6, 0xe5, 0x87, 0x27, + 0xe8, 0x09, 0xe2, 0x40, 0xf6, 0x59, 0x13, 0x1c, 0x8d, 0x9d, 0xd3, 0x1c, + 0xd9, 0xf1, 0xaf, 0x05, 0x04, 0xce, 0xf6, 0x73, 0xc9, 0x92, 0x5c, 0x03, + 0x03, 0x4a, 0x79, 0xff, 0x7f, 0x29, 0x9b, 0xe6, 0x7d, 0x09, 0xe4, 0x5e, + 0x19, 0x41, 0xd5, 0x6e, 0x66, 0x3f, 0x90, 0xbc, 0x6d, 0x78, 0xa1, 0x89, + 0x52, 0x3d, 0xc7, 0x01, 0x8d, 0x60, 0x31, 0x14, 0x1a, 0xd8, 0x21, 0x58, + 0x15, 0x7a, 0x5c, 0x5f, 0xc8, 0x5a, 0x61, 0xa8, 0x44, 0xb3, 0xf5, 0xf9, + 0x8b, 0x71, 0x2f, 0x19, 0x31, 0x9b, 0x4b, 0x40, 0x93, 0xae, 0x6a, 0xe1, + 0xab, 0xb6, 0xb3, 0x0f, 0x22, 0xe3, 0x5b, 0x8f, 0xdc, 0x4d, 0xc5, 0x23, + 0xa4, 0xfa, 0x64, 0x8d, 0x34, 0xeb, 0xa9, 0xe4, 0x67, 0x14, 0x75, 0x60, + 0x7d, 0x5c, 0xfd, 0xe0, 0x36, 0x8e, 0x66, 0x23, 0x60, 0xd4, 0x4e, 0x25, + 0xbc, 0xe0, 0xea, 0xeb, 0x8b, 0xa8, 0xce, 0xa3, 0xfd, 0x0b, 0xe3, 0xcd, + 0x48, 0x3e, 0xe0, 0x5f, 0x32, 0xcd, 0x21, 0xce, 0xd7, 0x99, 0xbc, 0x06, + 0x63, 0x8a, 0x1b, 0x63, 0xb5, 0x4b, 0x73, 0x11, 0x7c, 0xc5, 0x6c, 0x8f, + 0x3d, 0x5c, 0x74, 0x99, 0x74, 0x0b, 0xad, 0x81, 0x1c, 0x5b, 0xd5, 0x4e, + 0x60, 0x5b, 0x1c, 0xcc, 0x86, 0x5c, 0x54, 0x5b, 0x9d, 0x39, 0xae, 0x7e, + 0x3b, 0xc0, 0x1b, 0x04, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xf6, 0xe6, 0x99, 0xc4, 0x68, 0x16, 0x37, 0x96, 0x6e, 0xa8, 0x5a, 0xd9, + 0x7f, 0x6e, 0x51, 0x05, 0xf1, 0x6b, 0x63, 0xc9, 0xe4, 0x07, 0x4a, 0x46, + 0x80, 0xfa, 0x39, 0xb5, 0x5e, 0x9a, 0x0c, 0x11, 0xbc, 0x0e, 0x19, 0x29, + 0x56, 0x0b, 0xb3, 0x9d, 0x60, 0x06, 0x5e, 0x0a, 0x85, 0xb1, 0x87, 0x7c, + 0x7b, 0xcd, 0xc0, 0xe7, 0x7b, 0x23, 0xee, 0x37, 0xbd, 0xf9, 0x34, 0xff, + 0xa2, 0x23, 0xe5, 0x2d, 0x79, 0x61, 0xcd, 0x8d, 0x2b, 0x78, 0x9e, 0xba, + 0x39, 0x4e, 0x9f, 0x47, 0x27, 0x3d, 0x72, 0x52, 0x22, 0x1f, 0xa5, 0x74, + 0xdb, 0x9e, 0x0b, 0xd0, 0xc4, 0xe1, 0x16, 0x78, 0x3c, 0xf8, 0xd6, 0x0a, + 0x0f, 0x6d, 0xe8, 0x7a, 0x1c, 0xce, 0x20, 0xd0, 0x96, 0xa6, 0x76, 0xfa, + 0xd3, 0x6a, 0xcc, 0xab, 0x8e, 0x7e, 0x31, 0x3a, 0xe6, 0xf6, 0x20, 0x3d, + 0x7a, 0xd9, 0x14, 0x5c, 0xc7, 0x0d, 0xce, 0x11, 0xa4, 0x0d, 0x2c, 0xd6, + 0xe4, 0xb0, 0x9d, 0x51, 0xca, 0x66, 0xf8, 0x86, 0x29, 0x8f, 0x94, 0xc1, + 0xfd, 0xf6, 0x49, 0x52, 0x1d, 0xb9, 0x57, 0xb1, 0xbc, 0x36, 0x1b, 0xd9, + 0x99, 0x86, 0x55, 0x05, 0x89, 0xd6, 0xe3, 0xd8, 0xb7, 0xb9, 0xc5, 0xa3, + 0xec, 0x61, 0xe9, 0x4d, 0x63, 0xf7, 0xf2, 0x3e, 0x28, 0xce, 0x26, 0xd6, + 0x4c, 0x77, 0x99, 0x10, 0x9b, 0xe8, 0x40, 0x61, 0xec, 0x68, 0xbb, 0x18, + 0xa8, 0x99, 0x6f, 0xde, 0xc6, 0x34, 0x8f, 0x83, 0xba, 0xb5, 0xd7, 0x84, + 0xab, 0xc1, 0x34, 0xcd, 0xeb, 0xc2, 0xa9, 0x11, 0x7f, 0x8f, 0xbb, 0x14, + 0x33, 0xf5, 0x53, 0x6c, 0x88, 0xfb, 0xb1, 0x09, 0x78, 0x67, 0x05, 0x44, + 0xc6, 0x28, 0xfc, 0x7e, 0x1f, 0x24, 0x1a, 0xf4, 0xa6, 0xfa, 0x01, 0x80, + 0x29, 0x78, 0x78, 0x9a, 0x12, 0xf0, 0xc0, 0xbb, 0x41, 0x23, 0xe2, 0xf7, + 0x65, 0xdb, 0x4d, 0x11, 0x5a, 0xee, 0xa3, 0xcb, 0x0f, 0x4f, 0xf6, 0x88, + 0xf4, 0xae, 0x09, 0xca, 0x64, 0x80, 0xd3, 0x13, 0x35, 0xcf, 0x62, 0x2d, + 0x0b, 0x7e, 0x3a, 0xdc, 0x65, 0xfc, 0xa6, 0x2b, 0xae, 0x30, 0xfa, 0x2a, + 0x42, 0xcc, 0x8a, 0x93, 0xda, 0xaf, 0xe0, 0x61, 0x7f, 0xcd, 0xcf, 0x86, + 0x3f, 0x89, 0x54, 0x18, 0x39, 0x14, 0x0f, 0xaa, 0x8d, 0x3b, 0xb2, 0x7f, + 0x47, 0x0f, 0x19, 0xec, 0x3f, 0x74, 0x98, 0x1a, 0xe5, 0x6b, 0x96, 0x74, + 0x56, 0xca, 0x12, 0x13, 0xbf, 0x62, 0xd9, 0x21, 0xce, 0x56, 0x71, 0x96, + 0xef, 0xec, 0xfd, 0xc8, 0x9d, 0x8d, 0xb9, 0xf9, 0x7e, 0x35, 0x72, 0x39, + 0x08, 0x27, 0x18, 0x09, 0x41, 0xc3, 0xbc, 0x91, 0x37, 0xed, 0x30, 0xe0, + 0x72, 0x84, 0x94, 0xd9, 0x32, 0x5f, 0x97, 0xd4, 0x89, 0x33, 0x69, 0x62, + 0xe1, 0xe6, 0x5d, 0x91, 0x87, 0x48, 0x3c, 0x7c, 0x01, 0xf9, 0x8e, 0x0a, + 0x57, 0xf1, 0x36, 0xe7, 0x22, 0xdb, 0xce, 0xb6, 0x2d, 0x72, 0x69, 0x5a, + 0x70, 0x7f, 0x24, 0x35, 0x6f, 0x0f, 0x9e, 0x31, 0xef, 0x6c, 0xcc, 0xa3, + 0x49, 0x9f, 0x72, 0x98, 0x59, 0x2f, 0x58, 0x29, 0x4f, 0x57, 0x6d, 0xe6, + 0x7c, 0x29, 0x1b, 0x2e, 0xa6, 0x51, 0x51, 0xd2, 0x16, 0xff, 0x38, 0x8f, + 0xb0, 0xb2, 0x6e, 0x74, 0xe7, 0x92, 0x92, 0x45, 0xc6, 0x35, 0xcc, 0x2e, + 0xeb, 0x0d, 0x2f, 0x0a, 0x86, 0x0d, 0x31, 0xe9, 0xcc, 0xe0, 0x2b, 0xaa, + 0x58, 0x63, 0x67, 0x54, 0xc7, 0x79, 0x22, 0x27, 0xa5, 0xd9, 0x3e, 0x19, + 0xbc, 0x5b, 0x48, 0x1e, 0x82, 0x10, 0x7b, 0xd6, 0x4c, 0x8d, 0x65, 0x19, + 0xfa, 0x1a, 0x41, 0xff, 0x83, 0x2a, 0x71, 0xe2, 0x40, 0xa3, 0x0b, 0x00, + 0x2f, 0x98, 0xc3, 0x66, 0x69, 0x53, 0x91, 0x9f, 0x0f, 0x50, 0x7a, 0x01, + 0xcd, 0x22, 0x1c, 0x70, 0x8e, 0x64, 0xf8, 0x07, 0xa9, 0xf7, 0xfe, 0xab, + 0x75, 0x11, 0x2f, 0x03, 0x85, 0xb1, 0xb1, 0xcb, 0x4f, 0xa9, 0x95, 0xae, + 0x32, 0xa9, 0xab, 0x68, 0xed, 0x6a, 0xc6, 0xeb, 0x7f, 0x08, 0x01, 0x1b, + 0x89, 0x25, 0x66, 0x18, 0x9c, 0xc2, 0x11, 0x52, 0x38, 0xb9, 0x2f, 0x72, + 0xba, 0xc8, 0x8e, 0xde, 0x8c, 0x9a, 0x6c, 0x9f, 0x0f, 0x2a, 0x1c, 0xa7, + 0x75, 0xa6, 0x52, 0xd6, 0xff, 0xdc, 0xd5, 0x0a, 0xad, 0x3e, 0xc3, 0x08, + 0x7d, 0xc4, 0x42, 0x66, 0x7b, 0x50, 0x11, 0x29, 0x38, 0x52, 0x00, 0x21, + 0x98, 0xf2, 0x8d, 0x2d, 0x2b, 0xe5, 0x4b, 0xd6, 0x2e, 0xb0, 0x5e, 0x25, + 0xfd, 0x96, 0x2c, 0x94, 0x54, 0x2e, 0x76, 0x17, 0xeb, 0x2d, 0x5f, 0xec, + 0x4b, 0xa6, 0x1d, 0xa9, 0x56, 0xd8, 0xf6, 0x61, 0x0a, 0xaf, 0xb3, 0xae, + 0xdd, 0x42, 0x4f, 0xea, 0xd1, 0xc7, 0x84, 0x39, 0x12, 0x08, 0x0f, 0xcc, + 0x06, 0xc5, 0x2e, 0x22, 0x31, 0x6a, 0x6c, 0x41, 0xd8, 0x47, 0xd0, 0x64, + 0x38, 0x19, 0x2c, 0xf5, 0x3b, 0x0e, 0x1c, 0xe1, 0x32, 0x4e, 0x58, 0xc1, + 0xd7, 0x57, 0xbf, 0xc6, 0x9a, 0xb3, 0x73, 0xba, 0xbd, 0x78, 0x77, 0x2a, + 0xba, 0xb5, 0xaa, 0x0d, 0x54, 0x45, 0x46, 0xce, 0x3c, 0xe2, 0x45, 0xeb, + 0xb6, 0x00, 0x8e, 0xf0, 0x34, 0xaf, 0xbd, 0x1a, 0xd7, 0x44, 0xbf, 0xe4, + 0xb3, 0xaf, 0x46, 0x5a, 0x2a, 0x66, 0x11, 0x1d, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x42, 0xeb, 0x20, 0xfb, 0x82, 0x76, 0x8a, 0x0a, + 0x7c, 0xb0, 0x79, 0xdc, 0x63, 0x46, 0x11, 0x86, 0xf8, 0x7e, 0x6c, 0xef, + 0xb7, 0x3a, 0x35, 0x2f, 0x11, 0x5d, 0x91, 0x01, 0xb8, 0x7f, 0x7e, 0x1e, + 0x30, 0xe1, 0x6f, 0x9c, 0x32, 0xe8, 0xf3, 0x06, 0x4a, 0x30, 0x1f, 0xf1, + 0x7c, 0x12, 0x71, 0x30, 0x13, 0xfb, 0xaf, 0xf9, 0x98, 0x85, 0x96, 0x34, + 0xe2, 0x0c, 0x17, 0x12, 0xcb, 0x6d, 0x1a, 0x22, 0x83, 0xe2, 0x7c, 0xf8, + 0xf7, 0x8a, 0xa8, 0x90, 0xe6, 0x4f, 0xc5, 0xe0, 0xe3, 0x76, 0xd0, 0x5a, + 0x87, 0x01, 0x6b, 0xcb, 0x78, 0xc9, 0x59, 0xab, 0x18, 0xcd, 0xdb, 0xe8, + 0xbc, 0xe6, 0x4f, 0x09, 0x31, 0x3c, 0xf9, 0x53, 0x37, 0xf8, 0x84, 0x82, + 0x83, 0x77, 0xa1, 0xa5, 0xab, 0x1d, 0xe1, 0x85, 0x94, 0x51, 0xf4, 0xa7, + 0x9e, 0x4d, 0xc7, 0x97, 0x73, 0xc6, 0xe2, 0x03, 0x09, 0xef, 0xcf, 0x1e, + 0x94, 0x4c, 0x0b, 0x52, 0x49, 0x21, 0xe0, 0x4d, 0x65, 0x13, 0x6b, 0xd0, + 0xed, 0x70, 0xc4, 0xc1, 0x0e, 0x21, 0xf0, 0x88, 0xad, 0x5d, 0x05, 0x8a, + 0xca, 0x2b, 0x51, 0x63, 0x87, 0x51, 0x54, 0x19, 0x73, 0x91, 0xe8, 0x50, + 0xf4, 0x6e, 0xc1, 0x4b, 0x3f, 0x14, 0x0b, 0xe4, 0xa7, 0x70, 0x52, 0xc6, + 0x48, 0xc1, 0xe6, 0x14, 0x64, 0x1a, 0x57, 0x0b, 0xcd, 0x21, 0x2f, 0x3e, + 0xf9, 0x93, 0x85, 0x17, 0x1a, 0x46, 0xfb, 0xab, 0x78, 0xdd, 0x0e, 0xb4, + 0xd1, 0x05, 0xc3, 0x40, 0xf1, 0xfd, 0x80, 0xf0, 0xa0, 0x57, 0x8c, 0x40, + 0x46, 0x3b, 0x95, 0x24, 0xf4, 0x83, 0xdc, 0xa4, 0xb9, 0x1a, 0x91, 0x02, + 0x29, 0x06, 0x9c, 0x8c, 0x4b, 0x6f, 0x56, 0x45, 0x3d, 0x6f, 0xa1, 0x1e, + 0x55, 0x02, 0xda, 0xed, 0x1a, 0x17, 0x33, 0x8e, 0x4f, 0x85, 0x0e, 0x94, + 0x8a, 0x5d, 0xd6, 0x6d, 0xd8, 0xed, 0x56, 0x2b, 0x7b, 0x62, 0x50, 0xab, + 0x50, 0x90, 0x19, 0x6d, 0x22, 0x18, 0x70, 0xf7, 0x25, 0x5d, 0x33, 0xea, + 0xfa, 0x14, 0x53, 0xb0, 0x71, 0xd2, 0x30, 0xad, 0xdd, 0x1e, 0x7f, 0x99, + 0x3a, 0x0a, 0x39, 0x1a, 0xa2, 0xc4, 0x7b, 0x22, 0x4c, 0x65, 0x08, 0xf2, + 0x31, 0xcc, 0x75, 0xab, 0x14, 0x73, 0x7e, 0x7f, 0x79, 0xc2, 0x86, 0x63, + 0xa9, 0x2a, 0x47, 0x4e, 0x94, 0x9a, 0xb7, 0xc3, 0xb9, 0xc9, 0xd3, 0x0f, + 0x25, 0xee, 0x36, 0x45, 0xa8, 0x61, 0x9e, 0x1f, 0xbf, 0x77, 0x2e, 0xf5, + 0x5e, 0x5a, 0x36, 0x58, 0x8c, 0xde, 0x33, 0x1e, 0xed, 0x19, 0x4c, 0xc3, + 0x8d, 0x62, 0x41, 0x38, 0x60, 0x66, 0x51, 0x02, 0x98, 0x2f, 0x3f, 0x6b, + 0x26, 0xc5, 0x40, 0x56, 0x68, 0xce, 0x86, 0x89, 0x5e, 0xaa, 0x47, 0x3b, + 0xd1, 0x04, 0x00, 0x79, 0x28, 0xdb, 0x7d, 0xcf, 0xa7, 0x40, 0x05, 0x74, + 0x8e, 0x23, 0xb6, 0x1e, 0xea, 0x81, 0x1d, 0x72, 0x1d, 0x3d, 0xc4, 0xf1, + 0x8a, 0xb7, 0xbd, 0x8d, 0x45, 0x61, 0xd8, 0x3a, 0xce, 0x23, 0x17, 0xf3, + 0xfe, 0x88, 0xb5, 0xeb, 0xbd, 0xa0, 0x92, 0xdb, 0x45, 0x64, 0x40, 0x04, + 0x77, 0x53, 0x38, 0x6a, 0x30, 0x3d, 0x3d, 0x00, 0xb7, 0x36, 0xea, 0x55, + 0x35, 0x05, 0x16, 0x1c, 0x0a, 0x82, 0x0e, 0x10, 0xf5, 0x79, 0x87, 0x19, + 0xb7, 0x62, 0xcc, 0xcd, 0x95, 0x5c, 0x28, 0x05, 0xd2, 0xb9, 0x79, 0xd3, + 0xda, 0xa5, 0xad, 0xf8, 0xce, 0x6e, 0x39, 0xec, 0x29, 0x46, 0x12, 0xed, + 0x7e, 0xaf, 0x4b, 0x42, 0x21, 0x1c, 0x84, 0x0c, 0x97, 0xdc, 0xe0, 0x7c, + 0x27, 0x5b, 0x95, 0x06, 0xc2, 0x80, 0x51, 0xe2, 0x27, 0xfb, 0x36, 0x3a, + 0xb7, 0xe2, 0xee, 0x12, 0x6a, 0x89, 0xcb, 0xe5, 0x14, 0x51, 0xad, 0x92, + 0xf4, 0x6c, 0xbe, 0xf0, 0xea, 0xc7, 0x4d, 0xe3, 0xbf, 0x8c, 0xea, 0x0e, + 0xa8, 0x1c, 0xad, 0xab, 0xd2, 0x66, 0xcf, 0xe9, 0x10, 0x36, 0x91, 0x69, + 0xdb, 0x9e, 0x67, 0x2d, 0x11, 0x70, 0x04, 0x9f, 0x22, 0x26, 0xfc, 0xb0, + 0xa0, 0x39, 0x91, 0x51, 0x29, 0x0f, 0x6b, 0x27, 0x46, 0x8a, 0x26, 0x5c, + 0x5e, 0x91, 0xea, 0x33, 0xbe, 0xcc, 0xd1, 0xac, 0x74, 0xff, 0xa5, 0x34, + 0x96, 0xe5, 0xaa, 0x7e, 0x27, 0xf4, 0x24, 0xba, 0x18, 0x55, 0xb4, 0x75, + 0x21, 0x2c, 0xd6, 0x00, 0x4b, 0xfe, 0x9f, 0x4b, 0x36, 0xd7, 0xf7, 0x49, + 0xdf, 0x3a, 0xcb, 0x96, 0x22, 0xf8, 0x87, 0xf5, 0x19, 0xa9, 0xdb, 0xe3, + 0x1a, 0x58, 0xa3, 0xb5, 0x8f, 0xcb, 0x66, 0x66, 0x50, 0x94, 0x51, 0x0b, + 0xdd, 0x2b, 0x11, 0x4e, 0xfc, 0x2a, 0xa7, 0x7d, 0xfc, 0xb6, 0xe3, 0x92, + 0xfb, 0x72, 0x14, 0x8e, 0xe9, 0xc9, 0xa0, 0x48, 0x44, 0xb7, 0xc0, 0x57, + 0x74, 0xaf, 0xe5, 0xd0, 0xfb, 0x7f, 0x94, 0x06, 0xfd, 0x39, 0xf6, 0x1e, + 0xc6, 0xd2, 0xb0, 0xbd, 0x9a, 0xab, 0xd5, 0xb0, 0x47, 0x78, 0x34, 0xba, + 0xd7, 0x33, 0xe8, 0xe7, 0xc3, 0xb9, 0xc9, 0xfb, 0x13, 0x09, 0x99, 0x77, + 0x0d, 0xdb, 0x7e, 0x0a, 0x32, 0x3d, 0xab, 0x2f, 0x41, 0x74, 0x83, 0x0d, + 0xfc, 0xc4, 0x75, 0x8d, 0x8d, 0x13, 0x3a, 0xc6, 0x73, 0x8a, 0xb6, 0x8c, + 0x77, 0x92, 0x2e, 0xd6, 0xb7, 0x73, 0xec, 0x86, 0x3b, 0x50, 0xf6, 0x11, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xb4, 0x14, 0x36, 0x33, + 0x1a, 0x46, 0xc6, 0x3c, 0x2d, 0x37, 0xfb, 0x6f, 0x4c, 0x7b, 0xf1, 0xbf, + 0x0d, 0xce, 0x65, 0x54, 0x8f, 0x70, 0xa2, 0xe1, 0xfb, 0xb6, 0x7e, 0x94, + 0xc7, 0x07, 0xaf, 0x03, 0x62, 0xad, 0x67, 0x53, 0xa0, 0x3e, 0x4a, 0xab, + 0x44, 0xfd, 0xc7, 0x10, 0x5d, 0xfe, 0xa6, 0xff, 0xd6, 0xbf, 0xbe, 0x6f, + 0xf5, 0xce, 0x64, 0x87, 0xb2, 0x6c, 0xbf, 0x0e, 0x82, 0x9b, 0x21, 0x21, + 0xb6, 0xcb, 0xe7, 0x55, 0x88, 0x0d, 0x8d, 0x34, 0x3b, 0xd0, 0xd3, 0x63, + 0xee, 0xa9, 0xc2, 0x70, 0xce, 0xe6, 0x19, 0xc5, 0xa8, 0xcc, 0xd7, 0x67, + 0xee, 0x63, 0x79, 0x14, 0x5e, 0x5e, 0xbb, 0x1d, 0x3e, 0x86, 0x96, 0x48, + 0xf8, 0x94, 0x54, 0x04, 0x64, 0x03, 0x1a, 0x10, 0x7e, 0xd8, 0x04, 0xd4, + 0xda, 0xc6, 0xb3, 0xd9, 0x4b, 0xa4, 0x73, 0xa4, 0xe9, 0x12, 0x33, 0x5f, + 0xfb, 0xcf, 0x5b, 0x1e, 0x1f, 0x5a, 0x29, 0x45, 0xb3, 0x4a, 0x98, 0x76, + 0x08, 0xa1, 0x87, 0x72, 0x8a, 0xbc, 0x50, 0xa3, 0x5f, 0x02, 0x20, 0x36, + 0x34, 0x08, 0xf3, 0xbe, 0x99, 0x06, 0x7d, 0x4c, 0x90, 0xa5, 0xfb, 0x21, + 0x09, 0x8c, 0x79, 0xfb, 0x9f, 0x89, 0xd2, 0xbb, 0x06, 0x47, 0x5d, 0xe2, + 0x66, 0xfd, 0x5f, 0x7d, 0x97, 0x90, 0x9b, 0x79, 0x5e, 0x3f, 0x50, 0x9e, + 0xdb, 0x99, 0x6a, 0x2e, 0x70, 0x7f, 0xbd, 0x2c, 0x7f, 0x0d, 0x7f, 0x77, + 0x45, 0x74, 0x53, 0xb8, 0xbd, 0xac, 0xd4, 0xf4, 0xe2, 0x0a, 0x7c, 0x34, + 0xfb, 0xef, 0x74, 0xa0, 0xed, 0x6d, 0x4d, 0x43, 0x0b, 0xb3, 0x80, 0xbf, + 0x94, 0x92, 0x49, 0x13, 0xa8, 0xba, 0x19, 0xe4, 0x59, 0x8c, 0x93, 0x53, + 0xaf, 0x68, 0x9c, 0xd3, 0x17, 0x16, 0xc2, 0x85, 0x74, 0xee, 0x93, 0x99, + 0x83, 0x2e, 0x79, 0x40, 0x78, 0x35, 0xdb, 0x18, 0xcb, 0xc9, 0x60, 0x03, + 0xf5, 0xa5, 0x78, 0xaf, 0x5a, 0xc3, 0xb3, 0xbb, 0x1a, 0x24, 0xa8, 0x4e, + 0x06, 0x12, 0x12, 0x34, 0x56, 0x15, 0x8a, 0x14, 0xa9, 0xd0, 0x65, 0x34, + 0x36, 0x34, 0x02, 0x75, 0x99, 0xc1, 0x06, 0x20, 0x72, 0xb3, 0x00, 0xc7, + 0x0f, 0x41, 0x60, 0xaf, 0x26, 0x6c, 0x41, 0xa6, 0xdd, 0xc7, 0x6d, 0x8c, + 0xde, 0x97, 0xa1, 0xb0, 0xdc, 0x41, 0x3a, 0x43, 0xcc, 0x4d, 0x59, 0xd3, + 0x60, 0xf9, 0x35, 0x0d, 0x9b, 0xf5, 0x06, 0x4a, 0x1e, 0xba, 0xeb, 0x16, + 0xf5, 0x36, 0xa2, 0xfc, 0x9e, 0x8d, 0x17, 0x66, 0x0d, 0xbe, 0x65, 0x73, + 0xf7, 0x77, 0xb8, 0xb3, 0x6c, 0x62, 0x02, 0xb6, 0x06, 0xd7, 0xa1, 0x24, + 0x7e, 0x70, 0xf8, 0x70, 0xea, 0xad, 0x5b, 0xa0, 0xba, 0xdb, 0xdd, 0xe0, + 0xff, 0x98, 0x36, 0x9d, 0x45, 0xfc, 0xfc, 0x9f, 0xa1, 0x9a, 0x39, 0xa8, + 0xd0, 0x30, 0xef, 0xe1, 0xce, 0x5d, 0xdc, 0x0f, 0xfc, 0x3f, 0x0d, 0x64, + 0x6c, 0xa2, 0xcd, 0xe6, 0xd2, 0x07, 0x5e, 0x12, 0x11, 0x8f, 0x05, 0xdc, + 0x2b, 0xb7, 0x09, 0x44, 0x50, 0xc6, 0xf3, 0x80, 0xdb, 0xfb, 0xaf, 0x27, + 0xd1, 0xcb, 0x20, 0x23, 0x93, 0x79, 0xc2, 0xed, 0x7c, 0xb5, 0x84, 0x12, + 0x8e, 0x27, 0x81, 0xb2, 0xbd, 0xf4, 0x71, 0x6b, 0x57, 0x92, 0x50, 0x09, + 0x3b, 0xfc, 0xaa, 0x2f, 0x3e, 0x62, 0xe4, 0x84, 0xf1, 0x70, 0x80, 0x1b, + 0xda, 0xa5, 0xf4, 0xd5, 0xbc, 0x05, 0x47, 0x9d, 0x71, 0x63, 0xca, 0x96, + 0x57, 0x5f, 0x3c, 0xea, 0x2d, 0x63, 0x59, 0x28, 0x47, 0xbc, 0xf6, 0x6c, + 0x91, 0x67, 0xf1, 0x8a, 0x20, 0xc7, 0x64, 0x2a, 0xf1, 0x6f, 0x61, 0x15, + 0x7b, 0x96, 0x3c, 0x0a, 0x2f, 0x81, 0x15, 0x07, 0xfe, 0x96, 0xeb, 0xbf, + 0xc0, 0xac, 0x11, 0x57, 0x68, 0xb0, 0x23, 0xfb, 0x98, 0x92, 0xea, 0xe2, + 0x2b, 0x24, 0xe9, 0x04, 0xcf, 0xaf, 0xfa, 0xa6, 0x5a, 0xa0, 0xf8, 0xaf, + 0xf9, 0x06, 0x95, 0x1d, 0xe9, 0xd1, 0x2a, 0xa2, 0x15, 0xad, 0xd8, 0x20, + 0x2a, 0x88, 0xae, 0xc2, 0xc3, 0xc8, 0x55, 0x1c, 0x04, 0x6d, 0xb1, 0x01, + 0x1a, 0x30, 0x13, 0x89, 0x2f, 0x09, 0x3e, 0xec, 0x7f, 0xa1, 0xd4, 0xab, + 0x60, 0x00, 0x10, 0x27, 0x3d, 0x70, 0x57, 0xdf, 0x79, 0x98, 0xa5, 0xab, + 0xcf, 0xab, 0xba, 0xaf, 0x73, 0x95, 0x38, 0x02, 0xde, 0x72, 0x9c, 0x8f, + 0xd6, 0x0b, 0x45, 0xea, 0xd6, 0x54, 0xcb, 0x18, 0x82, 0xb6, 0xbf, 0x13, + 0x87, 0xd9, 0x27, 0x87, 0x85, 0x6b, 0x9b, 0xb0, 0x65, 0x7f, 0xba, 0x2a, + 0x93, 0x68, 0x43, 0x1a, 0x4e, 0x8e, 0xc0, 0x60, 0xcc, 0xbd, 0x83, 0x56, + 0x76, 0x9a, 0xee, 0xe4, 0xba, 0x1d, 0x98, 0x65, 0x33, 0xfe, 0x78, 0x1d, + 0x23, 0x9e, 0x10, 0xb8, 0x88, 0x48, 0x4e, 0x6b, 0x3a, 0xc1, 0x69, 0x21, + 0x7f, 0x60, 0x2d, 0x9d, 0x6a, 0x48, 0x1c, 0x12, 0x0c, 0xab, 0x91, 0x9c, + 0xff, 0xe0, 0x40, 0x61, 0x48, 0x38, 0x6f, 0x94, 0xaa, 0x18, 0xee, 0xf6, + 0x76, 0x53, 0xfe, 0x81, 0xe8, 0x9d, 0x89, 0x1c, 0xca, 0xdd, 0x7b, 0x59, + 0xe2, 0x78, 0x0f, 0xd6, 0x7d, 0xa2, 0x6c, 0x4f, 0xb8, 0xc0, 0x51, 0x52, + 0xdc, 0x5a, 0x14, 0x95, 0x8d, 0x0b, 0x40, 0x27, 0xd5, 0x39, 0xc7, 0xf0, + 0x05, 0xc9, 0x94, 0x10, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x3e, 0x58, 0x7e, 0x44, 0x08, 0x30, 0xdb, 0xd5, 0x35, 0x9d, 0xa4, 0x37, + 0x1e, 0x14, 0x4d, 0xa0, 0x04, 0x61, 0xe5, 0xb4, 0x41, 0xe7, 0x37, 0x83, + 0x62, 0xa4, 0x57, 0x5a, 0xdc, 0x6d, 0x69, 0x01, 0x30, 0x95, 0xcd, 0xb3, + 0xc8, 0xdf, 0xfc, 0x96, 0x91, 0x8a, 0x46, 0x31, 0x78, 0xa4, 0xd1, 0x93, + 0x36, 0x18, 0xcf, 0x1d, 0xc3, 0xc6, 0xc3, 0xc3, 0x22, 0x18, 0xdf, 0x37, + 0xfb, 0x21, 0x8c, 0x02, 0x6f, 0x9d, 0x5e, 0xb0, 0xe1, 0x8d, 0xe1, 0xa6, + 0x03, 0xc8, 0x26, 0xe3, 0xc9, 0x0f, 0xfe, 0x1f, 0xfe, 0x20, 0x74, 0x5d, + 0x5c, 0x37, 0x38, 0xe0, 0x1e, 0xc3, 0xc7, 0x52, 0x6e, 0x4f, 0x57, 0x04, + 0xb8, 0xd5, 0x8b, 0x3c, 0x54, 0xda, 0xd3, 0x9c, 0x1e, 0xc8, 0x2c, 0x0b, + 0xd9, 0x31, 0x55, 0xf4, 0x75, 0xe3, 0xa7, 0xcd, 0x02, 0xc1, 0x3e, 0xde, + 0x5a, 0x7e, 0x3a, 0x4d, 0x87, 0x26, 0xe7, 0x29, 0x0e, 0x7e, 0xe3, 0x68, + 0xcb, 0xfb, 0x70, 0x5c, 0x66, 0x1a, 0xdc, 0xd2, 0x50, 0x5c, 0xcf, 0x52, + 0xd2, 0xc1, 0xb9, 0xa4, 0xe7, 0x5d, 0x39, 0x44, 0x8c, 0x46, 0x44, 0x24, + 0x09, 0xe7, 0x9c, 0x06, 0xc6, 0x13, 0xc2, 0x23, 0x1b, 0x12, 0xed, 0xf4, + 0xf1, 0x00, 0xba, 0x4f, 0x48, 0x59, 0x03, 0xa5, 0xe4, 0x5a, 0x5d, 0xb8, + 0x9b, 0xfa, 0x7e, 0x6d, 0x83, 0x6d, 0xfb, 0x2c, 0xf1, 0xa6, 0x46, 0x05, + 0xcb, 0xef, 0x50, 0xa0, 0x1f, 0x37, 0x75, 0xfd, 0xc0, 0x68, 0xa7, 0xfc, + 0xf2, 0xb5, 0x3f, 0x07, 0xc3, 0xff, 0x39, 0x05, 0xe7, 0x65, 0x7b, 0x4a, + 0x2a, 0x14, 0x0e, 0xe1, 0x66, 0xc8, 0x46, 0x27, 0x0f, 0x59, 0x4b, 0xa5, + 0x3a, 0x30, 0x10, 0xbb, 0x3e, 0xdd, 0x6f, 0xd6, 0x22, 0x4a, 0xe7, 0x18, + 0x53, 0x20, 0xe4, 0x11, 0xfd, 0x8e, 0xf4, 0x14, 0xc8, 0x36, 0x8f, 0x08, + 0x7f, 0x53, 0x9b, 0x10, 0xdd, 0x05, 0xb9, 0x91, 0xb4, 0x72, 0xda, 0xdf, + 0x93, 0x64, 0x69, 0xec, 0x44, 0x91, 0xd6, 0xb8, 0x96, 0x7b, 0x18, 0x8c, + 0x66, 0x96, 0x83, 0x38, 0xcb, 0x5a, 0x6e, 0x13, 0xa1, 0x5f, 0xf5, 0x13, + 0xb6, 0xec, 0x02, 0x6b, 0x78, 0xca, 0x21, 0x67, 0x7e, 0x30, 0x50, 0x22, + 0x27, 0xfb, 0xcc, 0x0e, 0x87, 0x86, 0x8d, 0xf7, 0xa6, 0x64, 0xd0, 0xa3, + 0x57, 0x11, 0xfd, 0x11, 0x2e, 0x08, 0xb8, 0x08, 0x0e, 0xc5, 0xec, 0x4b, + 0x1d, 0xe3, 0xab, 0x49, 0x52, 0x9f, 0x1d, 0x55, 0x8d, 0xe0, 0x06, 0xe0, + 0x07, 0xbe, 0xf3, 0x4d, 0xf2, 0xd4, 0xd2, 0x52, 0x10, 0x11, 0x5f, 0x00, + 0xa9, 0x1f, 0x30, 0x09, 0x51, 0xdd, 0xb9, 0xec, 0xcd, 0x3d, 0xa2, 0xd8, + 0x26, 0x14, 0xab, 0x9e, 0x83, 0x55, 0x2d, 0x3b, 0xd9, 0xbc, 0x17, 0xeb, + 0x10, 0x04, 0x1c, 0x61, 0xf6, 0xb9, 0x62, 0xa5, 0x8a, 0xea, 0x62, 0x24, + 0x0a, 0x28, 0x27, 0xc4, 0xf3, 0x55, 0x1e, 0xb8, 0x0d, 0x88, 0x8b, 0x08, + 0x6d, 0xfa, 0x79, 0x9a, 0xdf, 0x7b, 0xef, 0x0c, 0xb9, 0x8e, 0x05, 0x49, + 0x62, 0xaa, 0x43, 0xe9, 0x70, 0x40, 0x82, 0x28, 0x42, 0x90, 0x9f, 0x9c, + 0xf4, 0x2f, 0xd6, 0x39, 0x62, 0xc6, 0x7b, 0x3f, 0x14, 0x92, 0x56, 0xdc, + 0x35, 0xf2, 0x9a, 0x58, 0x7f, 0x09, 0x3e, 0xa1, 0xca, 0x33, 0x22, 0xb6, + 0x5e, 0x22, 0x28, 0x1d, 0xf3, 0x7d, 0xef, 0xf8, 0x48, 0x4f, 0x95, 0x91, + 0xba, 0xb3, 0x25, 0x23, 0xcf, 0x3a, 0x32, 0x6e, 0x3d, 0xe2, 0x3c, 0xbc, + 0xf4, 0x65, 0x09, 0xc7, 0xe9, 0x5a, 0xbf, 0xc2, 0x0e, 0x79, 0x28, 0x04, + 0xb2, 0x11, 0xe6, 0x47, 0xfb, 0x20, 0xfc, 0xce, 0x22, 0xbd, 0x0e, 0xd9, + 0x77, 0x66, 0x80, 0xb5, 0x5f, 0xc7, 0xd2, 0x71, 0x80, 0xd3, 0xdf, 0xc9, + 0x1d, 0x0a, 0xb9, 0x96, 0x6a, 0x82, 0xbd, 0x24, 0x39, 0x43, 0xd4, 0xa0, + 0x19, 0xfd, 0x75, 0x47, 0x8e, 0xc5, 0x8b, 0xa5, 0x17, 0xb4, 0x06, 0x22, + 0x37, 0xe7, 0x5f, 0xd8, 0x84, 0xe2, 0xe2, 0x59, 0x86, 0x3b, 0xc1, 0xff, + 0x79, 0x80, 0xc1, 0x2d, 0x91, 0x63, 0xdf, 0xe4, 0xb5, 0x19, 0xf6, 0x4e, + 0xdc, 0x64, 0xef, 0x42, 0xcd, 0xcb, 0xb7, 0x20, 0xba, 0x95, 0x95, 0xc2, + 0x85, 0x25, 0x23, 0xc5, 0xe1, 0xe4, 0x91, 0xf3, 0xc7, 0xe2, 0x1d, 0x06, + 0xc6, 0x81, 0xcd, 0xc7, 0xc4, 0x07, 0x0f, 0x39, 0xaf, 0xc9, 0xcd, 0x56, + 0x8e, 0x8e, 0xcd, 0x1e, 0xbf, 0x17, 0xb3, 0xba, 0xd3, 0x73, 0x9d, 0x4b, + 0xb8, 0x88, 0x72, 0x73, 0x3b, 0x92, 0xab, 0x26, 0x2e, 0x6a, 0x0b, 0xc4, + 0x6f, 0x84, 0x09, 0x72, 0x69, 0x1a, 0x53, 0x3d, 0x80, 0x45, 0x25, 0x69, + 0xdb, 0x6f, 0x7c, 0xb5, 0xf1, 0x31, 0x44, 0x82, 0x6b, 0x47, 0x58, 0x34, + 0xf3, 0xe8, 0x0e, 0x0a, 0x07, 0x38, 0x91, 0x41, 0xba, 0x29, 0x42, 0x54, + 0xfa, 0xbb, 0x4c, 0xc8, 0x91, 0x5f, 0xdc, 0x54, 0x8f, 0x37, 0x36, 0xea, + 0x33, 0xd4, 0x75, 0x04, 0x05, 0x54, 0x59, 0x20, 0xc6, 0xbe, 0x43, 0x18, + 0xd1, 0xc5, 0x14, 0xc9, 0x16, 0x8b, 0xef, 0xeb, 0x04, 0xf9, 0x22, 0xd7, + 0x3a, 0x4e, 0x9c, 0xb1, 0x55, 0x79, 0x19, 0x57, 0xa7, 0xfe, 0x83, 0x00, + 0xc6, 0x3b, 0xf1, 0x55, 0x83, 0x16, 0xfe, 0x1c, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x7c, 0x29, 0x1e, 0x38, 0x2c, 0x64, 0xbf, 0x02, + 0xc7, 0xdb, 0xd7, 0xcd, 0xa5, 0x4c, 0x49, 0x0b, 0x0a, 0xb5, 0xe0, 0x36, + 0x28, 0x98, 0xd9, 0xc9, 0x1a, 0x49, 0xfc, 0xc1, 0x9d, 0xf8, 0xc3, 0x24, + 0xa0, 0x3a, 0x8f, 0x37, 0x28, 0x30, 0x0c, 0x9d, 0x34, 0x7a, 0xd8, 0xd1, + 0xfe, 0x3b, 0xb6, 0x80, 0x3e, 0x00, 0x7a, 0x66, 0x20, 0xda, 0x4b, 0x9f, + 0xa1, 0x9e, 0x55, 0x32, 0xcf, 0x5b, 0xfe, 0x1e, 0x25, 0x24, 0x4d, 0x65, + 0x0d, 0x1a, 0x63, 0xfe, 0x1e, 0xcd, 0xaa, 0x3b, 0x06, 0x21, 0x09, 0x2c, + 0x2e, 0x03, 0xa1, 0x62, 0xd7, 0x37, 0x27, 0xf0, 0x2c, 0x24, 0x6c, 0x11, + 0xc7, 0x94, 0x20, 0x30, 0xae, 0x9d, 0x36, 0xa4, 0xeb, 0x3c, 0x13, 0x0c, + 0xa0, 0x5d, 0x64, 0x8e, 0x86, 0xe3, 0x9e, 0x7c, 0x5d, 0xa8, 0x10, 0xce, + 0xde, 0x0f, 0xbe, 0x3f, 0x42, 0x85, 0x9c, 0x73, 0x6c, 0x97, 0x59, 0x29, + 0xbe, 0xfc, 0x9e, 0x2a, 0xcc, 0x2c, 0x42, 0xf3, 0x1f, 0x5d, 0xe9, 0x84, + 0x41, 0xcb, 0x17, 0x56, 0x80, 0x5f, 0xec, 0xd6, 0x39, 0x88, 0xf0, 0x4a, + 0xc5, 0xa5, 0x6b, 0x96, 0xe5, 0x5f, 0x13, 0x03, 0xa3, 0xa7, 0x73, 0x3c, + 0xc0, 0x88, 0x62, 0xff, 0xd9, 0xa2, 0x1c, 0x89, 0x0c, 0xff, 0x47, 0x82, + 0xf1, 0x94, 0x3c, 0x19, 0x55, 0xcc, 0xe6, 0xc8, 0x94, 0xc8, 0x09, 0x2c, + 0x31, 0x52, 0xe4, 0x1a, 0xb8, 0x2c, 0xa5, 0xa2, 0xca, 0xc0, 0x0d, 0x5f, + 0xde, 0x6c, 0xff, 0xdd, 0x99, 0xe1, 0xfb, 0xef, 0xef, 0x70, 0xbc, 0xed, + 0xd9, 0x63, 0x70, 0x01, 0xa4, 0x7a, 0xab, 0xfc, 0xaf, 0xb6, 0x0b, 0x23, + 0x76, 0x21, 0x18, 0x8a, 0x51, 0x83, 0x31, 0x35, 0x04, 0xaf, 0x33, 0x13, + 0x56, 0x59, 0xf2, 0x71, 0xcd, 0x0e, 0x8d, 0xdf, 0x58, 0x0a, 0x27, 0x42, + 0x1b, 0x17, 0x18, 0xd1, 0x63, 0xb7, 0x75, 0x0f, 0xc8, 0x9f, 0xac, 0x5a, + 0x86, 0x2d, 0x7c, 0x9c, 0x35, 0xfe, 0x62, 0x2e, 0xfc, 0xbe, 0x10, 0x97, + 0xd1, 0xe3, 0xf5, 0xba, 0xce, 0x3d, 0xbb, 0x81, 0x4f, 0xab, 0xf2, 0xcb, + 0x3e, 0x95, 0xb4, 0x27, 0x99, 0x4e, 0xe6, 0x2a, 0x03, 0xbc, 0x09, 0x52, + 0x2c, 0x03, 0xaa, 0xfb, 0xef, 0x97, 0xed, 0x67, 0x1d, 0x2d, 0xf7, 0x2f, + 0xe5, 0x93, 0x7d, 0x3a, 0xba, 0x45, 0x33, 0x88, 0xbe, 0x6a, 0x04, 0x04, + 0xf9, 0x06, 0x1b, 0x9a, 0xe4, 0xee, 0xee, 0xac, 0x82, 0x66, 0x02, 0x25, + 0x75, 0x92, 0x4d, 0x55, 0x7a, 0x81, 0xd7, 0x59, 0xe5, 0x54, 0xb6, 0x15, + 0xa7, 0xd1, 0xca, 0x87, 0x6e, 0xcb, 0xa5, 0x26, 0x7e, 0x33, 0x54, 0x6d, + 0x5f, 0x70, 0xc9, 0x44, 0x0c, 0x83, 0x36, 0xdc, 0x45, 0x00, 0xb9, 0x7b, + 0x6f, 0x6e, 0x21, 0x1b, 0xd8, 0xda, 0xce, 0x62, 0x6f, 0xfa, 0x1a, 0x26, + 0xf2, 0x5a, 0x1b, 0x06, 0x7d, 0x4a, 0xcf, 0x23, 0x1c, 0x75, 0x1a, 0xb5, + 0x30, 0xcd, 0xeb, 0x32, 0x45, 0xe5, 0x69, 0x03, 0x50, 0x05, 0xb2, 0xbe, + 0xad, 0xe8, 0x58, 0x58, 0x5e, 0x81, 0x9c, 0xbd, 0x14, 0x7c, 0xfe, 0x10, + 0xe5, 0x05, 0x1c, 0x06, 0x19, 0x95, 0x12, 0xef, 0x7e, 0x16, 0xc9, 0x96, + 0xff, 0x77, 0x9e, 0x08, 0xb8, 0xb9, 0x88, 0xf2, 0x1b, 0xc9, 0xb6, 0x48, + 0xe8, 0x56, 0xcb, 0xd8, 0x36, 0x9d, 0xbb, 0x24, 0x5f, 0x02, 0x5a, 0xd0, + 0x23, 0xe0, 0xf6, 0xdf, 0x6b, 0x90, 0x53, 0xe2, 0xcf, 0x57, 0x81, 0x00, + 0x07, 0x30, 0xf1, 0xb6, 0x4a, 0x4d, 0x92, 0x22, 0xec, 0x41, 0x5d, 0x03, + 0xe0, 0xa2, 0x66, 0x20, 0x30, 0xed, 0x42, 0x84, 0x77, 0xea, 0xb3, 0x6d, + 0x6a, 0xf2, 0xfc, 0x72, 0x5a, 0xb5, 0xb0, 0xe0, 0x15, 0x9b, 0xa9, 0x9e, + 0xe6, 0x72, 0x67, 0xbc, 0xd6, 0x61, 0xf3, 0x1c, 0xdf, 0xa0, 0xb1, 0x0a, + 0xbf, 0x35, 0xd2, 0x4b, 0xa4, 0xfa, 0x80, 0x5f, 0x07, 0x14, 0x01, 0x15, + 0xde, 0x7e, 0xb4, 0x54, 0xd3, 0x6d, 0x89, 0x63, 0x4e, 0x97, 0x03, 0xa4, + 0x7b, 0x06, 0xa4, 0xb3, 0x5f, 0x8b, 0xf5, 0x01, 0xb7, 0xe3, 0x72, 0xcb, + 0x6d, 0x89, 0x67, 0x5b, 0xdb, 0x1b, 0xcf, 0xa0, 0xf9, 0xf3, 0x63, 0x6f, + 0x05, 0x04, 0xb3, 0x89, 0xcd, 0x5c, 0x3b, 0x1f, 0x52, 0x05, 0xdc, 0xd8, + 0x12, 0x19, 0xd7, 0x05, 0xab, 0x1c, 0xe5, 0x7e, 0x39, 0x62, 0xb1, 0x66, + 0x08, 0x9b, 0x69, 0x03, 0xf3, 0x21, 0x63, 0xc7, 0xc5, 0x20, 0x0f, 0x6c, + 0x00, 0x00, 0xda, 0xf9, 0x3d, 0x0d, 0xa9, 0x35, 0x99, 0xa3, 0x9d, 0x05, + 0x3b, 0x60, 0xfa, 0x6f, 0x3a, 0xd8, 0x00, 0x35, 0x9e, 0x0c, 0x86, 0x13, + 0xb5, 0x36, 0x3d, 0x65, 0xb2, 0x9d, 0xe7, 0xe1, 0x9d, 0x13, 0xfa, 0xfd, + 0x3f, 0x4e, 0xf9, 0x95, 0xa6, 0xde, 0xb2, 0x0f, 0xcf, 0x4a, 0xa0, 0xfc, + 0xa2, 0x4b, 0xc2, 0xea, 0x4c, 0xb0, 0xe5, 0x7c, 0xaf, 0xba, 0x08, 0xa4, + 0x60, 0x4c, 0xf6, 0x73, 0x22, 0xf9, 0x55, 0x33, 0x4f, 0xfb, 0x1a, 0x16, + 0xa2, 0x6a, 0x4d, 0x15, 0xef, 0xb9, 0x97, 0x77, 0x01, 0x14, 0xd6, 0x86, + 0xfc, 0x84, 0x46, 0x0d, 0xd9, 0x3f, 0x38, 0xa3, 0x8c, 0xa3, 0xc9, 0x7b, + 0x40, 0x6c, 0x2a, 0x61, 0x6d, 0x13, 0x71, 0x39, 0x7b, 0x99, 0x95, 0x11, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xce, 0x90, 0x15, 0xa8, + 0x03, 0xbb, 0xe7, 0xa9, 0x4f, 0x9e, 0xde, 0x6e, 0x92, 0x4f, 0x0c, 0xdf, + 0xbf, 0x0c, 0x47, 0xfd, 0x58, 0xc0, 0x88, 0x27, 0x88, 0xed, 0x31, 0x36, + 0x1a, 0x27, 0x0d, 0x30, 0x1f, 0x31, 0x37, 0xb1, 0x85, 0x32, 0x67, 0xb4, + 0x83, 0xc6, 0x14, 0x11, 0xab, 0xc8, 0xf1, 0xc2, 0xea, 0x83, 0x7d, 0x11, + 0x2c, 0x33, 0x7d, 0x79, 0x4c, 0x59, 0xf9, 0xdd, 0x83, 0x5e, 0x27, 0x28, + 0xe7, 0x98, 0xe5, 0xfd, 0xd5, 0x10, 0xf0, 0x19, 0x98, 0x09, 0x64, 0xea, + 0xc1, 0x5d, 0x01, 0xd6, 0x58, 0x63, 0xce, 0x82, 0xfd, 0x4a, 0x7c, 0x5f, + 0xd9, 0x20, 0x21, 0x05, 0xfe, 0x13, 0x41, 0x1f, 0x60, 0x62, 0x6e, 0x95, + 0x87, 0xf5, 0xd0, 0x26, 0xce, 0x37, 0x06, 0x7f, 0xae, 0x9c, 0xa5, 0x8b, + 0x01, 0x97, 0xfa, 0x72, 0xec, 0xf8, 0x53, 0xca, 0x0a, 0xee, 0xde, 0x8f, + 0xcd, 0xe3, 0xf2, 0x07, 0xae, 0xa3, 0x8a, 0x5d, 0x07, 0x75, 0x5f, 0x2b, + 0x49, 0x60, 0x0b, 0x71, 0xd4, 0x55, 0xbf, 0xfd, 0x0a, 0xa1, 0x08, 0xd1, + 0x0e, 0x14, 0x29, 0x6b, 0x9f, 0x7a, 0x66, 0x0c, 0x25, 0x97, 0x32, 0x28, + 0x32, 0x3f, 0x34, 0x40, 0x25, 0x6c, 0xe2, 0xd6, 0x85, 0xbf, 0x84, 0xe5, + 0x49, 0xca, 0x9f, 0x9d, 0x8e, 0xb6, 0x6f, 0x8e, 0x16, 0xc6, 0x99, 0xfc, + 0xe1, 0xc4, 0x6f, 0x65, 0xc4, 0x7c, 0x2d, 0x0e, 0x29, 0x29, 0x5d, 0x8c, + 0x14, 0x7b, 0x86, 0x8c, 0x07, 0x8d, 0xd3, 0xdf, 0xd3, 0x34, 0x87, 0x32, + 0x42, 0xc7, 0xfa, 0x7f, 0x9d, 0x89, 0x8d, 0x41, 0xc2, 0xde, 0xb6, 0x3f, + 0xeb, 0x01, 0xd0, 0x20, 0x3c, 0x15, 0x74, 0x6c, 0xf1, 0xe3, 0xc3, 0x4e, + 0x86, 0x91, 0x5d, 0x8b, 0xc2, 0x0b, 0xb6, 0x46, 0xd2, 0xcd, 0x64, 0xd0, + 0xfa, 0x1f, 0x71, 0x9b, 0xa7, 0x15, 0xf8, 0x26, 0xe8, 0x2f, 0x3e, 0x07, + 0xc6, 0x6d, 0x2c, 0x1c, 0x30, 0xef, 0x39, 0xb4, 0x0c, 0x52, 0x1c, 0x08, + 0xa9, 0x61, 0x46, 0xf4, 0xf0, 0x36, 0x0a, 0x92, 0xaf, 0xc2, 0xbe, 0x02, + 0xdf, 0xe1, 0x9e, 0x42, 0xe2, 0xe2, 0x52, 0x08, 0xa2, 0x3f, 0x28, 0x3b, + 0x45, 0xb1, 0x18, 0x16, 0x4c, 0x4e, 0x74, 0x45, 0xde, 0x7e, 0xf3, 0xc9, + 0x8c, 0xd5, 0x42, 0xc7, 0x77, 0x6a, 0x08, 0x59, 0x3e, 0xda, 0xaa, 0xe6, + 0x54, 0x1a, 0xcd, 0x20, 0x41, 0x89, 0x24, 0xc7, 0x90, 0xef, 0x16, 0x7c, + 0x61, 0x61, 0xb2, 0xc3, 0xe7, 0xa0, 0x53, 0x2c, 0x8e, 0x5a, 0xd9, 0xa2, + 0xad, 0xb1, 0xdc, 0xe5, 0x9c, 0xfc, 0x1d, 0x11, 0x40, 0xb6, 0x08, 0x1e, + 0xc3, 0xb4, 0x06, 0x41, 0xd9, 0x41, 0xd3, 0xfe, 0x98, 0xbf, 0x94, 0xf8, + 0x03, 0x2a, 0x1b, 0x5e, 0x61, 0xf8, 0x53, 0x64, 0x99, 0xd2, 0x8e, 0xa3, + 0x81, 0x26, 0x1b, 0x82, 0xd1, 0x73, 0x46, 0x0b, 0xad, 0x7c, 0x57, 0x50, + 0x87, 0xef, 0x4f, 0x12, 0x77, 0x48, 0x67, 0xd1, 0xd1, 0xe8, 0x59, 0x72, + 0x79, 0x8a, 0xf7, 0x92, 0xdb, 0x0c, 0xbf, 0x45, 0x66, 0x41, 0x59, 0x30, + 0x84, 0xaf, 0x36, 0x02, 0x94, 0xd4, 0xc3, 0xc8, 0xb0, 0x7a, 0x26, 0x21, + 0x79, 0x02, 0xc3, 0x7d, 0xb5, 0x3e, 0xf5, 0xc5, 0x32, 0x8f, 0xd4, 0x0c, + 0x0f, 0xd9, 0xb3, 0xd4, 0x58, 0xb8, 0x5f, 0xf1, 0x8d, 0x87, 0xd5, 0x15, + 0x21, 0xd9, 0x6d, 0x6a, 0x00, 0xc9, 0x0c, 0xda, 0x9b, 0x7e, 0xd7, 0x34, + 0x2e, 0x9f, 0x7a, 0x16, 0xe2, 0xad, 0x5a, 0xab, 0x38, 0x64, 0xfd, 0xfe, + 0x39, 0xfb, 0xc1, 0xe8, 0x71, 0x87, 0x8f, 0x25, 0x4f, 0x48, 0x67, 0x2e, + 0x7c, 0xdd, 0x61, 0x80, 0xef, 0x4a, 0x51, 0x73, 0x8d, 0xe6, 0x3f, 0xa0, + 0xe0, 0xfd, 0xaf, 0x51, 0x28, 0xa3, 0x77, 0xb2, 0x30, 0x77, 0xf6, 0xfe, + 0x7c, 0x2b, 0xc3, 0x04, 0xac, 0x41, 0x74, 0x54, 0xed, 0xeb, 0x6a, 0xa1, + 0x38, 0xe0, 0xf1, 0xbe, 0x86, 0x74, 0xe6, 0xea, 0x31, 0x89, 0xf7, 0x0c, + 0xf3, 0x69, 0x93, 0x40, 0x48, 0x6a, 0x80, 0xa3, 0xe5, 0x05, 0x36, 0x02, + 0xb5, 0x8a, 0x94, 0x94, 0x61, 0x4f, 0xdd, 0x97, 0xef, 0x2c, 0x3e, 0x50, + 0x3f, 0xba, 0xe5, 0xbb, 0x19, 0x9d, 0x8a, 0x32, 0x73, 0x1e, 0x51, 0xd0, + 0x76, 0x28, 0x5b, 0x60, 0xd4, 0x68, 0x7f, 0x0a, 0x56, 0x1f, 0x1a, 0x66, + 0x42, 0xdc, 0x02, 0xef, 0xce, 0xf0, 0x04, 0xbe, 0x76, 0xdd, 0x97, 0xa8, + 0x1f, 0x57, 0xd9, 0xaf, 0x84, 0x22, 0x76, 0xe6, 0x90, 0x91, 0x55, 0xb2, + 0x91, 0xcf, 0x91, 0x27, 0xea, 0x33, 0x95, 0xd9, 0xe5, 0x83, 0xde, 0xd0, + 0x5f, 0xa6, 0x4d, 0x8b, 0x91, 0xa0, 0xc1, 0x64, 0x17, 0xf3, 0xcc, 0x25, + 0x71, 0x14, 0xe6, 0x09, 0x1b, 0x7b, 0xc4, 0x30, 0x17, 0x3a, 0xed, 0x27, + 0xc3, 0x0f, 0x76, 0xaf, 0x2d, 0xe3, 0x19, 0xe9, 0xcc, 0x18, 0x47, 0x3d, + 0x34, 0xfb, 0x45, 0x82, 0x19, 0x6b, 0x9b, 0x95, 0x4a, 0xfb, 0xbd, 0xce, + 0x5b, 0xa4, 0xb4, 0x06, 0x7c, 0xca, 0x8f, 0x1a, 0xb4, 0x12, 0xe2, 0xbb, + 0x0f, 0xe3, 0x5b, 0xa1, 0xd6, 0x08, 0xcb, 0x81, 0xc8, 0x9b, 0xa0, 0xdd, + 0xfd, 0xf9, 0xef, 0xba, 0x2f, 0xde, 0x18, 0x82, 0x80, 0x33, 0x99, 0xa8, + 0x25, 0xa5, 0x62, 0x1b, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xfb, 0xab, 0x1c, 0x84, 0x63, 0x56, 0xec, 0x0d, 0xca, 0xdf, 0x92, 0x01, + 0xbf, 0xa8, 0x43, 0xb5, 0x84, 0x08, 0xdf, 0x8e, 0xbc, 0x31, 0xc4, 0x4b, + 0x9b, 0x27, 0x93, 0x85, 0xe6, 0x85, 0x7f, 0x08, 0x57, 0x2d, 0x3d, 0x06, + 0x58, 0xd9, 0x86, 0x4e, 0x07, 0x60, 0x05, 0xc5, 0x76, 0x33, 0x5d, 0x92, + 0x02, 0x2c, 0x83, 0xff, 0x59, 0x26, 0x37, 0x16, 0xfb, 0x5e, 0x5c, 0x21, + 0x0b, 0x49, 0xee, 0x29, 0x70, 0x16, 0x7e, 0xb3, 0xa2, 0x1a, 0x9d, 0x42, + 0x5b, 0xdc, 0xb8, 0xbb, 0xf5, 0x00, 0x59, 0xba, 0x75, 0x2c, 0x2c, 0xb4, + 0x86, 0xcd, 0x71, 0xb5, 0xb3, 0x9d, 0xa8, 0x1c, 0x4c, 0xd3, 0x3d, 0x06, + 0xcf, 0x36, 0xf3, 0xa3, 0xde, 0x64, 0x73, 0xac, 0xc5, 0xe3, 0xd0, 0xb0, + 0x31, 0xff, 0x18, 0x8a, 0x79, 0x09, 0xc7, 0x7d, 0xc2, 0x16, 0xe2, 0x4a, + 0x12, 0x83, 0x00, 0xe1, 0x20, 0x0d, 0x7a, 0x2d, 0xfb, 0x88, 0xed, 0xae, + 0xdb, 0xf4, 0xb1, 0x5e, 0x32, 0x2d, 0x53, 0x15, 0xf8, 0xb3, 0x5c, 0x52, + 0x19, 0xf2, 0x6c, 0x59, 0x9f, 0x1a, 0x23, 0x07, 0x8d, 0xfe, 0xd8, 0xf8, + 0x30, 0xb6, 0xd2, 0x23, 0xfb, 0x5f, 0x00, 0xf9, 0x56, 0x72, 0x82, 0x75, + 0x63, 0xa1, 0xb2, 0x7c, 0xa5, 0x73, 0x10, 0x0b, 0x63, 0x4d, 0x20, 0x0b, + 0x69, 0x18, 0xab, 0xee, 0x87, 0x2c, 0x0a, 0xd1, 0xd3, 0x54, 0x17, 0x03, + 0x01, 0xd4, 0xef, 0x27, 0x96, 0xcc, 0xa3, 0x03, 0x54, 0xf2, 0x46, 0xdb, + 0x72, 0xaf, 0xdc, 0xce, 0x26, 0x09, 0x57, 0xc5, 0x14, 0x35, 0x09, 0xb0, + 0x97, 0x8c, 0x35, 0xc9, 0x37, 0xf4, 0x66, 0x1c, 0x19, 0xf3, 0x3b, 0x0f, + 0x1b, 0xd7, 0xf3, 0x62, 0x52, 0x00, 0x9f, 0x4d, 0x63, 0x12, 0xb2, 0x41, + 0xa2, 0xd8, 0xd0, 0xf0, 0xfe, 0x75, 0x8a, 0x4f, 0xab, 0x5d, 0xd8, 0xd7, + 0xfa, 0x19, 0x72, 0x05, 0x53, 0xb8, 0xf1, 0xbe, 0x94, 0x15, 0xdf, 0xf4, + 0xb0, 0xb8, 0x39, 0x6c, 0xa7, 0x75, 0xdd, 0x72, 0xe4, 0xab, 0x2b, 0x56, + 0xdf, 0x92, 0x68, 0x29, 0x97, 0xf4, 0x84, 0xee, 0x90, 0x82, 0xa2, 0x1a, + 0xf7, 0x05, 0x32, 0xde, 0x7f, 0x01, 0x12, 0x86, 0x5a, 0xf6, 0x68, 0xe2, + 0xbb, 0x7a, 0xc3, 0x1f, 0xd3, 0x42, 0x30, 0xd5, 0x19, 0xbb, 0x84, 0xb8, + 0x1a, 0xda, 0x12, 0x9e, 0x49, 0x8a, 0xcc, 0x14, 0x3c, 0x18, 0x59, 0xdc, + 0x3e, 0xea, 0xe0, 0xb5, 0xea, 0x86, 0x89, 0x08, 0x96, 0x84, 0x86, 0x30, + 0x36, 0xf7, 0xbb, 0x2c, 0xfe, 0xff, 0xf6, 0x62, 0x9f, 0x8c, 0x36, 0xed, + 0xa8, 0x74, 0x60, 0x11, 0xcc, 0x93, 0x9d, 0x90, 0xac, 0x60, 0xce, 0xf6, + 0x1c, 0x83, 0xd9, 0x2b, 0x43, 0x22, 0x77, 0x04, 0x97, 0x87, 0x3f, 0xb9, + 0x73, 0x89, 0x84, 0x8c, 0xc5, 0x79, 0xa8, 0x5a, 0x09, 0xa8, 0xee, 0x0a, + 0xe6, 0x0c, 0x4c, 0xa0, 0x6e, 0x43, 0x6a, 0x45, 0xaf, 0xdf, 0xd2, 0x90, + 0x81, 0x7c, 0xe7, 0x1c, 0xe9, 0x6e, 0x96, 0x56, 0xd2, 0xf9, 0xa3, 0xf7, + 0x6b, 0x7f, 0xe1, 0x20, 0xd1, 0x5b, 0x45, 0x13, 0x42, 0x28, 0x88, 0xb0, + 0xb9, 0x1d, 0x60, 0xb7, 0x74, 0x47, 0xfb, 0x9d, 0x10, 0xb0, 0xa7, 0x7d, + 0x0d, 0x64, 0x14, 0x21, 0xb3, 0xa5, 0xaa, 0xa5, 0xfc, 0x6e, 0xc1, 0xed, + 0xa5, 0xd7, 0xd3, 0x23, 0x92, 0x34, 0x5a, 0xf3, 0xed, 0xa3, 0x97, 0x70, + 0xaf, 0xb1, 0xdc, 0x4f, 0x5e, 0x3e, 0x0e, 0xf6, 0x81, 0x13, 0xa9, 0x03, + 0x2a, 0x71, 0xd4, 0x9a, 0x65, 0x0a, 0xfb, 0x26, 0x09, 0x78, 0xea, 0x1b, + 0x51, 0x1c, 0x2d, 0x28, 0x76, 0x36, 0x25, 0x25, 0x56, 0x19, 0x42, 0xb5, + 0x04, 0xfd, 0x41, 0xc8, 0x2a, 0x62, 0x71, 0xd6, 0x1e, 0xf6, 0xdc, 0xa8, + 0x1e, 0x3a, 0xb6, 0xcb, 0xd8, 0x26, 0x4d, 0x0a, 0x1c, 0xa4, 0x17, 0xe9, + 0x4b, 0x3b, 0x25, 0x14, 0x73, 0x17, 0xc2, 0x84, 0xde, 0xa5, 0xd0, 0x54, + 0xfe, 0x85, 0x60, 0xd1, 0x41, 0xa7, 0x7b, 0x74, 0xea, 0xc0, 0x17, 0x3c, + 0x03, 0xd1, 0xfd, 0x0a, 0x68, 0x59, 0xed, 0x67, 0x35, 0x3b, 0x92, 0xf0, + 0xb1, 0xb0, 0xd5, 0x2e, 0x29, 0x1f, 0x39, 0x24, 0x5b, 0x9a, 0xb2, 0x14, + 0x98, 0x38, 0x13, 0xcb, 0xa8, 0x99, 0xb2, 0x2b, 0x5e, 0x0a, 0x7c, 0x25, + 0x9d, 0x22, 0x2e, 0x68, 0x83, 0x60, 0x5b, 0x37, 0xdd, 0x10, 0xee, 0x88, + 0xf3, 0x27, 0x15, 0x20, 0x9e, 0x27, 0xa9, 0x75, 0x90, 0x3d, 0xca, 0x5e, + 0x8e, 0x32, 0x08, 0xde, 0xf6, 0x08, 0xfd, 0x1b, 0xd2, 0x90, 0x17, 0x35, + 0xf9, 0x68, 0xe6, 0xea, 0xba, 0xb6, 0xc1, 0x23, 0x32, 0xbe, 0x28, 0xa1, + 0x40, 0xfd, 0xb1, 0xf6, 0xab, 0xeb, 0xb5, 0x3b, 0xa9, 0xc2, 0x0e, 0xa5, + 0xf6, 0x7b, 0x6a, 0x14, 0x88, 0x19, 0xbe, 0x0f, 0x48, 0x45, 0xd4, 0x09, + 0xb2, 0xdf, 0x73, 0x21, 0x64, 0xbf, 0x75, 0x25, 0xf3, 0x0d, 0x48, 0xd6, + 0x29, 0x39, 0x9c, 0x63, 0x02, 0x54, 0x9e, 0x0d, 0xc1, 0xda, 0xf1, 0x2d, + 0xc2, 0xa3, 0xfa, 0x48, 0x86, 0xca, 0x2a, 0xa8, 0xd4, 0x74, 0xe8, 0x4a, + 0xee, 0x05, 0x28, 0x46, 0x89, 0x6f, 0x86, 0xe1, 0x53, 0x9c, 0xab, 0xab, + 0xea, 0x7c, 0xf0, 0x87, 0xcf, 0xf1, 0xcb, 0x09, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x09, 0x2d, 0x9b, 0xaf, 0x73, 0x9d, 0x2d, 0x86, + 0xea, 0x1c, 0xda, 0x37, 0xb3, 0x37, 0xf3, 0x56, 0x13, 0x58, 0x71, 0x5b, + 0x8b, 0x6c, 0xb0, 0x8c, 0x0a, 0xea, 0xbb, 0x2b, 0x4b, 0x36, 0x19, 0x0a, + 0x0c, 0x06, 0x22, 0x88, 0x56, 0x78, 0x8d, 0x1a, 0xe3, 0x5c, 0xbd, 0x28, + 0xd6, 0xe1, 0x13, 0x83, 0x41, 0x45, 0xd0, 0xab, 0xab, 0x06, 0x9d, 0x58, + 0x5b, 0x11, 0xda, 0xa8, 0x58, 0xaf, 0xea, 0x0e, 0xb1, 0xf2, 0x82, 0xbe, + 0xac, 0x16, 0x4a, 0x07, 0x6f, 0x79, 0x38, 0x47, 0x78, 0x14, 0x38, 0x30, + 0x15, 0xaf, 0xdc, 0xd6, 0x59, 0xb7, 0x45, 0x6f, 0xe9, 0x13, 0x48, 0xaa, + 0xab, 0x79, 0x83, 0x19, 0xaa, 0xe6, 0xeb, 0x30, 0x9a, 0xb1, 0xa0, 0x12, + 0x49, 0x72, 0x98, 0x0d, 0x73, 0x30, 0xe2, 0x85, 0x8d, 0x89, 0xb5, 0x0f, + 0xb3, 0x7a, 0x48, 0x72, 0x8e, 0x2d, 0xde, 0x81, 0xe0, 0x07, 0xb0, 0x23, + 0x5e, 0xc3, 0x50, 0x38, 0x1e, 0x07, 0x61, 0x88, 0x96, 0xba, 0xee, 0x3a, + 0x4a, 0xa9, 0x55, 0xbe, 0x07, 0x94, 0x8e, 0x1e, 0x4c, 0x0a, 0xaf, 0xf8, + 0xab, 0x4d, 0xb0, 0x68, 0xae, 0xdb, 0x3a, 0x14, 0x9d, 0xfc, 0xde, 0xef, + 0x8e, 0xab, 0x91, 0x98, 0x28, 0x45, 0xc2, 0x65, 0xf7, 0x9b, 0x2c, 0x60, + 0xd0, 0x40, 0xe9, 0x37, 0x4e, 0xd8, 0xe1, 0xda, 0x26, 0x4a, 0x28, 0x36, + 0xd5, 0x89, 0x17, 0x06, 0xb0, 0x56, 0x83, 0xf6, 0x0f, 0x95, 0x76, 0x40, + 0xce, 0x57, 0xa2, 0x1b, 0xb4, 0xb2, 0xee, 0x3b, 0xd2, 0x16, 0xe2, 0x83, + 0x38, 0x5c, 0x39, 0x34, 0x18, 0x3c, 0x88, 0x14, 0x81, 0x43, 0x09, 0x16, + 0xc8, 0xde, 0x9c, 0xb6, 0xc3, 0x48, 0xd0, 0x64, 0x73, 0xb9, 0xcd, 0xde, + 0x31, 0xa8, 0x63, 0x00, 0x4e, 0xdd, 0x55, 0x45, 0xf9, 0x99, 0x3e, 0x3d, + 0x9c, 0x16, 0xd9, 0x2a, 0x15, 0xd4, 0xd7, 0x16, 0x5f, 0x4b, 0x13, 0x84, + 0xaf, 0xc9, 0x01, 0x63, 0xf6, 0xf1, 0x79, 0x91, 0x24, 0xa5, 0x23, 0x6d, + 0xc9, 0x71, 0x3c, 0xbe, 0x8f, 0x68, 0xf0, 0xfb, 0x7e, 0x47, 0x15, 0x16, + 0xc4, 0x1d, 0xcf, 0x18, 0x42, 0x9a, 0x3e, 0xad, 0x40, 0x78, 0x9a, 0xbc, + 0x23, 0x05, 0x35, 0x57, 0x9f, 0x0e, 0xdd, 0x08, 0xcb, 0xc5, 0xb1, 0xfe, + 0x97, 0xa9, 0x18, 0x2d, 0xda, 0x63, 0x91, 0x6a, 0x01, 0xc3, 0xd4, 0x15, + 0xe9, 0xe3, 0x51, 0x9a, 0x7f, 0x85, 0x10, 0x8c, 0x1e, 0x40, 0x78, 0xa6, + 0xce, 0x37, 0xc5, 0x55, 0x4a, 0x3c, 0xc5, 0x75, 0xae, 0x44, 0x8d, 0x69, + 0xae, 0x42, 0x01, 0x03, 0x4d, 0x7c, 0xfe, 0x25, 0xfe, 0x07, 0x37, 0x4b, + 0xa6, 0xdd, 0x18, 0x56, 0x62, 0x12, 0x92, 0x63, 0x67, 0x2e, 0xed, 0x4d, + 0xfa, 0xd2, 0xfa, 0xfe, 0x09, 0xb8, 0xc3, 0x57, 0x56, 0xdd, 0xc5, 0xf6, + 0x3c, 0xcd, 0xcb, 0x20, 0x37, 0x31, 0x46, 0x1b, 0xd2, 0x31, 0x01, 0x56, + 0xf3, 0x77, 0x34, 0x7c, 0x94, 0x76, 0x40, 0x11, 0xcf, 0xbf, 0xe7, 0x11, + 0x5e, 0x76, 0x24, 0x30, 0xc6, 0xbb, 0x17, 0x5d, 0x50, 0xc1, 0xed, 0x0c, + 0x4c, 0x9d, 0xb3, 0x06, 0xc4, 0x90, 0x44, 0x6c, 0xf9, 0x2a, 0xb2, 0x7d, + 0xf1, 0x8a, 0x62, 0x7f, 0x8c, 0x9c, 0x3c, 0xdc, 0x20, 0x87, 0x8d, 0x9b, + 0x5f, 0xba, 0xdb, 0x91, 0xce, 0xf1, 0x24, 0x29, 0xe7, 0x33, 0xeb, 0xc8, + 0x70, 0x7b, 0xea, 0x7f, 0x75, 0x9a, 0xc2, 0x5c, 0x32, 0xf7, 0x5d, 0xfd, + 0xed, 0x4a, 0x1b, 0x03, 0x80, 0x53, 0x9e, 0xba, 0x9c, 0xf8, 0xec, 0xe5, + 0xe7, 0xf0, 0xb5, 0x16, 0x4e, 0x83, 0x2e, 0xb0, 0xf2, 0x7b, 0xd2, 0x04, + 0xbe, 0x6f, 0x3a, 0x65, 0xce, 0x28, 0x18, 0x9a, 0x81, 0x61, 0x66, 0xc6, + 0x72, 0x46, 0xbf, 0x2d, 0xca, 0xfd, 0x1c, 0xce, 0xee, 0xd1, 0x36, 0x0f, + 0x6a, 0xbf, 0x35, 0x8b, 0x78, 0x8d, 0x11, 0x83, 0xfb, 0x4a, 0x13, 0xaf, + 0xfc, 0x4c, 0x2b, 0x5c, 0xb2, 0x51, 0x38, 0xa1, 0xbe, 0xf3, 0x3b, 0x69, + 0x60, 0xc3, 0xf9, 0xed, 0xfd, 0xe0, 0xe0, 0x2d, 0x0a, 0xa6, 0x90, 0x75, + 0x18, 0x5b, 0x09, 0x74, 0xe2, 0x7a, 0xbd, 0x32, 0x98, 0xf4, 0xf2, 0xbb, + 0x37, 0xc7, 0xe2, 0x6f, 0xbd, 0x9e, 0x64, 0x7d, 0xee, 0x85, 0x58, 0x5f, + 0x63, 0xd8, 0xaa, 0x1d, 0x9f, 0x93, 0x3b, 0x61, 0x1c, 0x1c, 0x85, 0xc5, + 0x1e, 0x14, 0x20, 0xd9, 0x45, 0x99, 0xe8, 0xe3, 0xb7, 0xa5, 0x62, 0xea, + 0xd6, 0x6f, 0x7d, 0xa2, 0x88, 0x3b, 0xb8, 0x0c, 0x9b, 0x7e, 0xdf, 0x19, + 0x02, 0x07, 0x65, 0xe3, 0xb7, 0xb7, 0x54, 0xf2, 0x85, 0x68, 0xb7, 0xe2, + 0x25, 0xab, 0x92, 0x51, 0xc0, 0x80, 0x7d, 0x44, 0x42, 0xff, 0x45, 0xd7, + 0xa6, 0x39, 0x46, 0x86, 0x21, 0x00, 0xc1, 0x1e, 0x3e, 0x80, 0x48, 0x46, + 0x9e, 0xa0, 0x26, 0xf5, 0x72, 0xd6, 0xc1, 0x75, 0x56, 0x15, 0xe6, 0xc3, + 0x00, 0x26, 0xdd, 0xdc, 0x9a, 0x5a, 0x32, 0xf0, 0x44, 0xdc, 0x7e, 0x9d, + 0xf7, 0x30, 0xa4, 0x26, 0x7c, 0x23, 0xf2, 0xea, 0x08, 0x64, 0xdc, 0x85, + 0x17, 0x9d, 0x71, 0x29, 0xb4, 0xcd, 0xdc, 0xc0, 0xc2, 0xae, 0x9e, 0x7f, + 0x64, 0x47, 0xb7, 0xc7, 0xf5, 0x2e, 0x47, 0x52, 0xa5, 0x5a, 0x75, 0x2b, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xd7, 0xc4, 0x8a, 0xd8, + 0x14, 0xaf, 0xd2, 0x18, 0x72, 0x4d, 0x75, 0x6d, 0xa1, 0x0a, 0x16, 0xf4, + 0x6c, 0xff, 0xb2, 0x59, 0x28, 0x1d, 0xc6, 0xc8, 0x3f, 0xe2, 0xb4, 0x80, + 0x8b, 0x22, 0x0f, 0x0e, 0x88, 0x89, 0x86, 0xb0, 0x56, 0xbb, 0x89, 0x89, + 0xb7, 0x02, 0x36, 0x9b, 0xce, 0xd7, 0x2a, 0xdc, 0xe1, 0xd9, 0x93, 0xa6, + 0x64, 0x42, 0x3e, 0xdf, 0x87, 0xd1, 0x0d, 0x1d, 0xab, 0x6b, 0x19, 0x06, + 0x83, 0x9e, 0x3f, 0x2e, 0xdb, 0xbe, 0x0c, 0xff, 0xb2, 0x58, 0x03, 0x43, + 0xfd, 0x3d, 0xbf, 0x9c, 0x5e, 0xa7, 0x85, 0xdf, 0x2b, 0x27, 0x39, 0x66, + 0x88, 0xb1, 0x86, 0x0a, 0x89, 0x28, 0xf6, 0x09, 0x58, 0x95, 0x15, 0x96, + 0xf2, 0xba, 0x4c, 0x00, 0xd9, 0x15, 0xb7, 0x3b, 0x87, 0xa4, 0x7f, 0x43, + 0x56, 0x62, 0xae, 0x5c, 0x6a, 0x1f, 0xb0, 0x42, 0x9d, 0x0f, 0xfd, 0xdb, + 0x1f, 0x05, 0x3e, 0x27, 0xb8, 0x56, 0x4b, 0xf2, 0x1e, 0xf3, 0xa8, 0x50, + 0xf5, 0x3e, 0x03, 0x6e, 0xf4, 0x73, 0x61, 0x53, 0x3c, 0x22, 0xfd, 0x23, + 0x5c, 0x7a, 0x35, 0xae, 0xd0, 0x06, 0xa4, 0xf4, 0xa0, 0x2a, 0x36, 0x19, + 0x1d, 0x8c, 0x93, 0x9a, 0x90, 0x8e, 0xe7, 0x95, 0x7d, 0xce, 0x66, 0xca, + 0xf2, 0xae, 0x41, 0x0a, 0x88, 0xec, 0x1e, 0x98, 0xad, 0xc3, 0x43, 0x0d, + 0xe4, 0x9d, 0x57, 0xf6, 0x60, 0x75, 0x95, 0x26, 0x28, 0x93, 0xdb, 0x9f, + 0xb7, 0x70, 0xcc, 0xbe, 0x33, 0x93, 0x8f, 0x46, 0x17, 0xd2, 0x63, 0xb0, + 0x85, 0x23, 0xbe, 0xb1, 0x62, 0xc8, 0x5f, 0x87, 0x48, 0x32, 0xc4, 0xf9, + 0x33, 0xa1, 0x7d, 0x0e, 0xe0, 0xfd, 0xd9, 0x3e, 0x9c, 0xac, 0x07, 0xe1, + 0xe8, 0xd0, 0x5f, 0x6d, 0x98, 0x0c, 0x55, 0xe4, 0xf0, 0x45, 0xd4, 0x2c, + 0xc8, 0x0b, 0xee, 0x66, 0xdf, 0x6d, 0xa4, 0x9a, 0x7b, 0xc9, 0x26, 0x09, + 0x2d, 0xf7, 0x5b, 0xcc, 0x96, 0x41, 0x2e, 0x80, 0xae, 0xcd, 0x2c, 0xcd, + 0xee, 0xb0, 0x96, 0x46, 0x81, 0x8d, 0xb1, 0x24, 0x7e, 0x49, 0xab, 0x82, + 0x28, 0x33, 0xfc, 0x71, 0xa2, 0x00, 0xf8, 0x05, 0x4e, 0x0d, 0x56, 0xc6, + 0xbf, 0x81, 0x7d, 0x0f, 0xed, 0x01, 0x4b, 0xbd, 0x50, 0x9f, 0x80, 0x57, + 0x07, 0xec, 0x7d, 0x77, 0x69, 0x78, 0x78, 0x1f, 0x86, 0xba, 0xf9, 0x33, + 0xa9, 0x52, 0x55, 0x1a, 0x87, 0x95, 0x0b, 0x56, 0x18, 0x2a, 0x2f, 0x3e, + 0x2e, 0xf4, 0x9b, 0xe7, 0x44, 0x32, 0xdc, 0x9d, 0x74, 0xab, 0xd6, 0x55, + 0x2b, 0xa1, 0x2c, 0xbd, 0xf8, 0xdc, 0xe9, 0x3c, 0x95, 0xed, 0xf1, 0x1a, + 0x64, 0xcb, 0x9e, 0x20, 0x0b, 0xb6, 0x6d, 0x0e, 0x24, 0x41, 0xdb, 0x0e, + 0x2c, 0x7a, 0x73, 0xbb, 0x9f, 0xa2, 0xb2, 0xd5, 0xe6, 0xf6, 0xc7, 0x91, + 0x7d, 0x9f, 0x35, 0xdc, 0xdb, 0xba, 0x49, 0x26, 0xc2, 0xc6, 0x43, 0x5f, + 0x2f, 0x69, 0xa8, 0x15, 0x9b, 0x37, 0xe3, 0xed, 0xef, 0xb9, 0x92, 0xfd, + 0xb1, 0x97, 0x26, 0x62, 0xb4, 0xaa, 0x82, 0x89, 0x12, 0x7b, 0xb3, 0x09, + 0xaa, 0x21, 0xac, 0x1d, 0xaa, 0xfb, 0x90, 0x17, 0x24, 0x8b, 0x67, 0x08, + 0xec, 0x64, 0x74, 0xad, 0x60, 0x54, 0x17, 0xdb, 0xfc, 0xc0, 0x6e, 0xf1, + 0xb9, 0xec, 0x3c, 0x00, 0x40, 0xaa, 0x54, 0xaa, 0xf5, 0x38, 0xab, 0x24, + 0xd3, 0x2e, 0xc3, 0x7d, 0x91, 0x40, 0xee, 0xbd, 0x12, 0xbf, 0xc9, 0xc3, + 0x92, 0x6b, 0x77, 0x13, 0x2d, 0x36, 0x92, 0x27, 0x5b, 0x2c, 0xd0, 0x9b, + 0xdb, 0x48, 0x86, 0x14, 0x68, 0xe9, 0x5e, 0x06, 0xba, 0x7e, 0x75, 0xbb, + 0xdf, 0x3f, 0x67, 0x82, 0xa0, 0xbc, 0x21, 0x4a, 0x9b, 0x93, 0x11, 0xd1, + 0xfb, 0x83, 0xb7, 0x16, 0xab, 0xf2, 0xb1, 0xcf, 0xe4, 0x5b, 0xd4, 0x14, + 0xb3, 0xe8, 0xaf, 0x23, 0x82, 0xa5, 0xca, 0xe4, 0x91, 0x86, 0x30, 0xc6, + 0xba, 0xd0, 0x49, 0xf6, 0x21, 0x38, 0x66, 0x50, 0x5d, 0xdb, 0xc5, 0xf5, + 0x3d, 0xae, 0xc9, 0x42, 0xf5, 0x72, 0xb9, 0xd0, 0xd5, 0x35, 0xff, 0x2c, + 0x8c, 0xff, 0x7d, 0x0b, 0x05, 0xe9, 0x34, 0x0b, 0x96, 0xa2, 0x32, 0x7a, + 0x40, 0xcf, 0x64, 0x0c, 0x08, 0x2a, 0xb8, 0x3c, 0xac, 0xb8, 0x75, 0xf0, + 0x60, 0x0d, 0x06, 0x1a, 0x31, 0xd4, 0x36, 0x1b, 0xc2, 0x93, 0x00, 0xb0, + 0x2c, 0x26, 0x4a, 0xde, 0xe1, 0x68, 0xc5, 0x6d, 0x13, 0xaa, 0x3c, 0xf8, + 0x45, 0x9f, 0x1e, 0x94, 0xfd, 0x02, 0xe2, 0xb0, 0x02, 0x87, 0xee, 0xda, + 0xec, 0xf2, 0xef, 0x03, 0x5c, 0xbf, 0x76, 0x35, 0x81, 0xa4, 0x20, 0x79, + 0xbb, 0x29, 0x9b, 0xfc, 0xad, 0xf2, 0xf3, 0xd3, 0x6b, 0x5e, 0x44, 0x2a, + 0xfc, 0x5f, 0x0e, 0x65, 0x2f, 0x3c, 0x27, 0x3c, 0x32, 0xa6, 0xd0, 0x1a, + 0x1a, 0x6d, 0x6f, 0x2f, 0x43, 0x40, 0x75, 0x1d, 0x1f, 0x7b, 0xec, 0x71, + 0xbc, 0x3b, 0x90, 0x22, 0xa5, 0x55, 0x22, 0x82, 0xd5, 0x3b, 0xfb, 0x0e, + 0x43, 0x22, 0xaf, 0x5c, 0x7b, 0xf2, 0x53, 0x18, 0xb2, 0xeb, 0xd6, 0x46, + 0x16, 0x84, 0x05, 0xb0, 0x1d, 0xb1, 0x19, 0xfc, 0x90, 0x33, 0x72, 0x23, + 0xf6, 0x94, 0x04, 0x32, 0xcd, 0x0a, 0x35, 0xea, 0x92, 0xea, 0xb1, 0x44, + 0x20, 0xbc, 0x9b, 0x17, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x3c, 0x6a, 0x9f, 0xd3, 0xff, 0xea, 0x87, 0xeb, 0x47, 0x2b, 0x0c, 0xdc, + 0x5e, 0xa3, 0x32, 0x1d, 0x96, 0xb7, 0x8d, 0x4e, 0x37, 0x0e, 0x5a, 0x14, + 0xeb, 0xc0, 0x67, 0xf4, 0x1c, 0x59, 0x34, 0x0b, 0xab, 0x0c, 0xc7, 0xeb, + 0xf5, 0xd0, 0x2b, 0xd4, 0xbd, 0x5e, 0x88, 0xad, 0x53, 0xd3, 0xb9, 0x01, + 0xfa, 0x40, 0xd8, 0xc0, 0x6a, 0xfc, 0x72, 0x48, 0x7d, 0x25, 0x17, 0x8a, + 0x6c, 0x26, 0x6d, 0x2d, 0xcf, 0x6f, 0x97, 0x0a, 0x09, 0x62, 0x15, 0x5d, + 0x72, 0xc4, 0x53, 0xd3, 0xb3, 0xad, 0x23, 0x71, 0x5f, 0x8c, 0x84, 0x45, + 0x90, 0xa4, 0x79, 0x09, 0x3a, 0xfa, 0x65, 0x07, 0x01, 0xa4, 0xc2, 0x25, + 0x27, 0x6e, 0xb6, 0xd8, 0x39, 0x20, 0xc0, 0x84, 0x0d, 0xd3, 0x45, 0x30, + 0x86, 0x2b, 0xf2, 0x77, 0xc5, 0xad, 0x96, 0xed, 0xe0, 0x3d, 0x99, 0x7a, + 0xf3, 0x93, 0x1b, 0xb0, 0x30, 0x10, 0xe5, 0x18, 0x5d, 0xaf, 0xbd, 0xfc, + 0x13, 0x6c, 0xf8, 0xe0, 0x58, 0x0b, 0xa9, 0xf8, 0x55, 0x96, 0xd1, 0xe1, + 0x19, 0x6b, 0x89, 0xca, 0x99, 0xb5, 0x50, 0xa6, 0x1d, 0xc9, 0x34, 0x2c, + 0x51, 0x54, 0xc6, 0x14, 0x6b, 0x69, 0x2c, 0x25, 0x68, 0xae, 0xad, 0x07, + 0x81, 0x8c, 0xda, 0xe4, 0xe8, 0xd2, 0x2a, 0xc1, 0xb4, 0xdc, 0x78, 0x90, + 0x5b, 0x29, 0xa6, 0x7d, 0x4f, 0x9f, 0xc2, 0x03, 0x0b, 0xb7, 0x7c, 0x04, + 0xad, 0xbe, 0x73, 0x76, 0xcc, 0x62, 0x43, 0x9a, 0x6b, 0xce, 0x87, 0x1e, + 0x93, 0x67, 0x64, 0x5e, 0x82, 0xd2, 0x6e, 0x09, 0xc1, 0x8e, 0x02, 0x4c, + 0xff, 0x9c, 0xe3, 0x3a, 0x9e, 0xbc, 0x84, 0x25, 0x16, 0x30, 0xcc, 0x31, + 0xd5, 0x85, 0xa5, 0xc3, 0x01, 0xbb, 0x86, 0x2a, 0x59, 0xd4, 0x2e, 0x05, + 0x03, 0x94, 0xcc, 0x78, 0x27, 0x1c, 0xed, 0x39, 0xce, 0xe4, 0x8e, 0x20, + 0xbb, 0x33, 0x5a, 0x22, 0x08, 0x9f, 0x51, 0xdd, 0x3b, 0xd5, 0x0b, 0xec, + 0x82, 0x3d, 0x42, 0x45, 0x59, 0xde, 0x74, 0xbc, 0xa5, 0x9b, 0x5c, 0xb3, + 0x90, 0x56, 0x8a, 0x63, 0xae, 0x9d, 0xd7, 0xed, 0xc2, 0xfb, 0x16, 0x0d, + 0x4c, 0x3c, 0xbe, 0x1b, 0x29, 0x6f, 0x54, 0x36, 0x57, 0x97, 0xd4, 0x3d, + 0x7c, 0x5a, 0x27, 0x90, 0xc5, 0x13, 0xf0, 0x37, 0x17, 0x90, 0x23, 0x1a, + 0x1c, 0x12, 0xe0, 0xb4, 0x45, 0x5a, 0xbc, 0x2b, 0xbe, 0xa6, 0xc7, 0x59, + 0x30, 0x1c, 0x85, 0x55, 0xf3, 0xad, 0x3a, 0x56, 0x2c, 0x91, 0x8b, 0x49, + 0xb2, 0x30, 0x8c, 0x4a, 0x1c, 0x3c, 0xac, 0x26, 0x2a, 0xce, 0xfd, 0x82, + 0xa2, 0x00, 0xcf, 0x0e, 0x68, 0x29, 0xaf, 0x2a, 0xfa, 0x06, 0x61, 0x8a, + 0x27, 0xa8, 0xa3, 0x6d, 0x6f, 0x5a, 0x56, 0x35, 0xf3, 0x52, 0x22, 0x99, + 0x90, 0x9a, 0x82, 0xd9, 0x8d, 0xce, 0xd6, 0x2b, 0x66, 0x56, 0xfc, 0x0e, + 0xa8, 0x2e, 0x38, 0x7c, 0xed, 0xa1, 0x1d, 0xc4, 0x6c, 0x9d, 0x4d, 0x97, + 0x5e, 0xed, 0x40, 0x8a, 0x52, 0xa4, 0xfb, 0x0e, 0x5b, 0xd2, 0xa2, 0x55, + 0xb6, 0x40, 0x72, 0x5a, 0x83, 0x3f, 0x62, 0x12, 0x3c, 0xdf, 0xf9, 0xba, + 0x63, 0x38, 0xbf, 0xb3, 0x46, 0x34, 0x97, 0x18, 0x19, 0x05, 0x8a, 0xbe, + 0x15, 0x52, 0xaf, 0x98, 0x10, 0x84, 0x2f, 0x42, 0x32, 0xbf, 0x35, 0x2b, + 0xf8, 0xb2, 0x34, 0x0b, 0x1e, 0x71, 0x46, 0x84, 0xe2, 0x2b, 0x6b, 0x0b, + 0x40, 0x97, 0x41, 0xed, 0x90, 0xf2, 0x1d, 0x77, 0xb3, 0x2e, 0x42, 0x66, + 0x22, 0x29, 0x3f, 0xe4, 0xd8, 0xcd, 0x12, 0x64, 0xaa, 0x74, 0x42, 0x10, + 0xd6, 0xa0, 0x6d, 0x8c, 0x03, 0x57, 0x2f, 0x51, 0xb7, 0xcd, 0xbf, 0xf7, + 0xc5, 0xe2, 0xf3, 0xf6, 0x73, 0x61, 0xb2, 0x29, 0x53, 0xb8, 0x28, 0xea, + 0xa5, 0xc0, 0x4b, 0x34, 0xb9, 0xe0, 0x03, 0x24, 0x62, 0x85, 0x1d, 0xbc, + 0x89, 0xfb, 0x04, 0x4e, 0x63, 0x4e, 0x8a, 0x93, 0x9a, 0x56, 0xfd, 0xe5, + 0x2d, 0x19, 0x57, 0x61, 0xab, 0x07, 0xd9, 0x6c, 0x22, 0x4b, 0x62, 0x79, + 0xaf, 0xb4, 0xd0, 0x01, 0x7f, 0xbf, 0x9a, 0x2e, 0xe7, 0xfb, 0x04, 0x4e, + 0xe2, 0x36, 0xb8, 0xf5, 0xe2, 0x22, 0x39, 0x68, 0xf7, 0x60, 0x75, 0x3b, + 0x33, 0x44, 0x8d, 0x2e, 0xd8, 0x25, 0x70, 0xb0, 0x32, 0x6e, 0xb4, 0x1a, + 0xdb, 0xfd, 0x57, 0x7a, 0x52, 0xec, 0x08, 0xad, 0xb7, 0x37, 0x29, 0x50, + 0x69, 0x93, 0xbf, 0x23, 0x4d, 0xd7, 0x7e, 0x6d, 0xb2, 0x4d, 0xae, 0xb6, + 0xf2, 0x8f, 0x84, 0x9c, 0x8c, 0x5c, 0x05, 0x07, 0x03, 0x9e, 0x6a, 0x7c, + 0x46, 0xa6, 0x4d, 0xb7, 0x99, 0x82, 0x8f, 0x9f, 0xd6, 0x9d, 0xdd, 0x89, + 0x47, 0x23, 0xf5, 0xb5, 0xf1, 0xa7, 0x21, 0x03, 0x22, 0xa3, 0xc0, 0xd8, + 0x26, 0xd0, 0x40, 0x20, 0xf5, 0x6d, 0xdd, 0xd3, 0x28, 0x57, 0xf6, 0x85, + 0xa6, 0x51, 0x5a, 0xa0, 0xa5, 0x1c, 0x63, 0x3b, 0x48, 0x90, 0xae, 0x57, + 0x95, 0x8c, 0x74, 0xac, 0x71, 0x0b, 0x90, 0x58, 0x68, 0x36, 0x04, 0x22, + 0xf8, 0xd4, 0x7b, 0xeb, 0xd6, 0xba, 0x50, 0x0b, 0x9a, 0x1f, 0x3e, 0x97, + 0x0e, 0xad, 0x4a, 0x56, 0xa6, 0xda, 0xe7, 0xb4, 0xc5, 0xf4, 0x37, 0xd0, + 0x61, 0xfd, 0xb4, 0x90, 0x82, 0x01, 0x7e, 0x07, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xfc, 0xe0, 0x62, 0xd6, 0x77, 0x7f, 0x7b, 0xa2, + 0x57, 0xee, 0x75, 0x37, 0x51, 0xa5, 0xd5, 0xff, 0x95, 0x87, 0x73, 0x59, + 0x40, 0xc5, 0x5a, 0x87, 0xd8, 0xa4, 0x34, 0x1d, 0x4e, 0x4e, 0xa9, 0x0a, + 0x6e, 0xab, 0x72, 0xd2, 0x14, 0xf4, 0x42, 0xe3, 0x61, 0xd7, 0x82, 0x97, + 0x96, 0xe6, 0x6c, 0x47, 0x05, 0x36, 0x21, 0x43, 0x21, 0x7a, 0x6a, 0x33, + 0xda, 0xed, 0x5c, 0x78, 0x00, 0x67, 0x14, 0x00, 0x03, 0xcb, 0x38, 0xf7, + 0x02, 0x73, 0xb3, 0x25, 0x84, 0xd0, 0xca, 0x9c, 0x9f, 0x24, 0xd3, 0xcf, + 0xdf, 0x9d, 0xaf, 0xa5, 0xa6, 0x0b, 0xce, 0x4e, 0x1d, 0xe0, 0x70, 0x64, + 0xad, 0x2e, 0x8d, 0x1f, 0xab, 0xde, 0xb8, 0x30, 0x00, 0x7a, 0xaa, 0x59, + 0x54, 0x39, 0x57, 0x58, 0x70, 0xaf, 0xa8, 0x1f, 0x61, 0xbc, 0x4a, 0x28, + 0xb9, 0x05, 0xa8, 0x99, 0x38, 0xd3, 0x76, 0xf8, 0x83, 0x3d, 0x55, 0x2e, + 0x14, 0xbb, 0x44, 0xc0, 0x09, 0x11, 0x37, 0x48, 0x87, 0xbe, 0x92, 0x46, + 0x49, 0x69, 0xc9, 0x1f, 0x68, 0xd1, 0x80, 0x30, 0xd9, 0xeb, 0xae, 0x6b, + 0x6d, 0x97, 0x39, 0x69, 0x4f, 0x1b, 0x65, 0x1d, 0xbb, 0x3e, 0x13, 0xce, + 0xd2, 0xb5, 0x8f, 0x74, 0x58, 0xf3, 0x07, 0x9c, 0xa8, 0xf2, 0xa2, 0x16, + 0x74, 0x72, 0xb1, 0x43, 0xdd, 0x21, 0x2c, 0x9d, 0x32, 0x96, 0xa9, 0x46, + 0xe1, 0x73, 0x04, 0x24, 0xdb, 0x49, 0x39, 0xf2, 0xcb, 0x12, 0xe6, 0xaf, + 0x85, 0x12, 0x5c, 0xd1, 0xc0, 0x0b, 0x82, 0xe5, 0x31, 0x0d, 0x10, 0x1c, + 0xe8, 0xdc, 0xd1, 0xa7, 0xf6, 0x99, 0x61, 0x4b, 0x67, 0x01, 0xe4, 0x0c, + 0xc1, 0x91, 0x6f, 0xcf, 0xcf, 0x6f, 0xdb, 0x80, 0x37, 0x69, 0xde, 0x50, + 0xeb, 0xc8, 0x28, 0x73, 0xf4, 0xaf, 0xa8, 0xbf, 0x56, 0xc4, 0xc4, 0x35, + 0x96, 0x1a, 0xce, 0x21, 0xdb, 0xda, 0x1a, 0x18, 0xc0, 0x65, 0xd4, 0x13, + 0xf9, 0x83, 0x6c, 0xde, 0x15, 0x2d, 0xd5, 0xfe, 0x74, 0xfa, 0x74, 0x0b, + 0x2a, 0x43, 0x0f, 0xfa, 0x67, 0xb8, 0x1d, 0x3b, 0x25, 0xec, 0xc0, 0x6e, + 0x9a, 0xdc, 0x10, 0x0e, 0x4c, 0x42, 0x89, 0x99, 0x82, 0xed, 0x95, 0x4f, + 0x1c, 0x56, 0x97, 0x89, 0x02, 0xe0, 0xe2, 0xe7, 0x6c, 0x6c, 0x33, 0xc9, + 0x59, 0xad, 0x65, 0xa1, 0x50, 0x0a, 0x7d, 0xdd, 0x00, 0x7f, 0x29, 0x10, + 0xe4, 0x56, 0x3c, 0x3a, 0x79, 0x88, 0x3c, 0x37, 0x97, 0xd8, 0xa6, 0x5f, + 0x00, 0x7e, 0xb8, 0xde, 0x27, 0xc3, 0x68, 0x25, 0x77, 0x25, 0xa0, 0xbd, + 0x33, 0xa2, 0x99, 0x99, 0xea, 0xf6, 0x5b, 0x0d, 0x9a, 0x8b, 0xaa, 0x43, + 0xc6, 0x36, 0x26, 0xde, 0x52, 0x42, 0xec, 0x9a, 0x3d, 0xc8, 0x68, 0x25, + 0x2d, 0x3a, 0x4b, 0x74, 0x18, 0x73, 0x11, 0xf8, 0x6f, 0x8b, 0xbf, 0xe3, + 0x79, 0x02, 0x0f, 0x23, 0x81, 0x15, 0x8f, 0xa1, 0xa5, 0xf7, 0x99, 0xc8, + 0x91, 0x7e, 0xb2, 0xdd, 0x09, 0xd3, 0x1c, 0x9d, 0xfd, 0x54, 0xa3, 0x07, + 0xc7, 0xaf, 0xa3, 0x2b, 0x6e, 0xa2, 0xc0, 0xaa, 0xba, 0x59, 0x5e, 0x15, + 0xfb, 0xd0, 0xc2, 0x9b, 0x33, 0x74, 0x73, 0x17, 0x83, 0x0f, 0x13, 0xe8, + 0x67, 0xa2, 0x50, 0x07, 0x3c, 0x80, 0x5d, 0xe7, 0xb1, 0x5f, 0x79, 0x81, + 0x0f, 0x46, 0x37, 0x06, 0xf4, 0x9f, 0x74, 0x06, 0x9f, 0xbe, 0x6b, 0x37, + 0xaf, 0x71, 0xb8, 0x58, 0xee, 0x72, 0x7b, 0x4d, 0x3a, 0xd1, 0x1f, 0x5e, + 0x17, 0xf0, 0xb6, 0xfc, 0xdc, 0x41, 0x15, 0x05, 0x07, 0x72, 0x2a, 0xc9, + 0x2c, 0x02, 0xb0, 0x2c, 0x14, 0x45, 0x46, 0xbf, 0xaa, 0x8c, 0x05, 0xbf, + 0x33, 0x7d, 0x61, 0x6b, 0xf4, 0x40, 0x2c, 0xab, 0xdb, 0x1d, 0xf3, 0x0b, + 0xec, 0xca, 0xd5, 0x02, 0xe7, 0xf2, 0x00, 0xbf, 0x49, 0xab, 0xfa, 0x16, + 0xb0, 0x9c, 0x56, 0x92, 0xef, 0xd2, 0x5e, 0xf6, 0x14, 0x07, 0x5a, 0x85, + 0x48, 0xc3, 0xa1, 0x5a, 0xc8, 0xb7, 0xae, 0xf6, 0xb6, 0xbc, 0xc9, 0xd2, + 0xa1, 0x74, 0x72, 0x36, 0x56, 0x6b, 0x18, 0x2b, 0x27, 0x3f, 0xb5, 0xdf, + 0xc8, 0x3e, 0xe8, 0xff, 0x43, 0x38, 0xb4, 0x82, 0x2a, 0x8b, 0x86, 0x91, + 0x39, 0xae, 0x98, 0x2b, 0x92, 0x52, 0xa4, 0x7a, 0x36, 0xf2, 0xe3, 0x76, + 0x93, 0x04, 0xce, 0x25, 0xcc, 0x90, 0x5d, 0x12, 0x49, 0x48, 0x98, 0xf5, + 0x68, 0xfb, 0x96, 0xec, 0x72, 0x26, 0x0a, 0x24, 0xd7, 0xa9, 0x31, 0xda, + 0x0e, 0x76, 0xd5, 0x74, 0x04, 0xfe, 0xe8, 0xd7, 0x68, 0x7f, 0xc1, 0x1c, + 0xe7, 0xac, 0xba, 0xed, 0x19, 0x06, 0x10, 0x1f, 0x48, 0x37, 0x41, 0x85, + 0xee, 0x5b, 0x70, 0x5c, 0x18, 0xc4, 0x4b, 0x41, 0xf8, 0xe4, 0x08, 0xca, + 0x4b, 0x46, 0x30, 0x43, 0xf2, 0xe1, 0xba, 0x1a, 0xb8, 0x8c, 0xed, 0x1e, + 0x53, 0x46, 0x7e, 0xbc, 0x40, 0x59, 0x41, 0xb7, 0x25, 0x4d, 0xa9, 0x5b, + 0xfe, 0x33, 0x6b, 0x1b, 0x0d, 0x80, 0x1f, 0xf0, 0x14, 0x3c, 0x9f, 0xd3, + 0xb7, 0x50, 0x74, 0x0a, 0x66, 0xcc, 0xbb, 0x5d, 0x4b, 0x84, 0xc4, 0xd5, + 0xe8, 0xdb, 0xb7, 0xcb, 0xa8, 0xfe, 0xbb, 0xb5, 0xde, 0xa1, 0x6a, 0x59, + 0x0d, 0x31, 0x88, 0x3c, 0xfa, 0x59, 0x4d, 0x03, 0xba, 0xc7, 0xd9, 0x12, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xec, 0xce, 0x16, 0x4c, + 0x9a, 0xdf, 0xd0, 0xdc, 0x6e, 0x95, 0xb4, 0xf8, 0x2d, 0xcc, 0x52, 0x4a, + 0x0c, 0xd7, 0x99, 0xef, 0x98, 0x2f, 0x5d, 0x88, 0x8f, 0xcf, 0x7f, 0xcc, + 0x8a, 0x4f, 0x32, 0x01, 0xae, 0x3c, 0xee, 0x12, 0x42, 0xb1, 0x13, 0x8a, + 0xf7, 0x4a, 0x2b, 0xdb, 0x94, 0x9d, 0x7b, 0x1b, 0x87, 0x90, 0xee, 0xe1, + 0xb3, 0xc2, 0xa0, 0x27, 0xc4, 0xe7, 0x8d, 0xfc, 0x0d, 0xb3, 0x14, 0x1a, + 0xd0, 0x29, 0xa3, 0x03, 0x7c, 0x3a, 0xaa, 0xfd, 0x7f, 0x73, 0xe0, 0xc0, + 0x51, 0xbd, 0xd9, 0xdb, 0x07, 0xd3, 0x33, 0x4d, 0x6d, 0xd6, 0xb9, 0xee, + 0x13, 0x13, 0xa5, 0xc0, 0xfe, 0xc6, 0x5f, 0x1d, 0x76, 0x7d, 0xfc, 0x30, + 0x47, 0x7c, 0xc0, 0x68, 0xbb, 0x72, 0x52, 0x4e, 0xf2, 0x26, 0x77, 0xc5, + 0x81, 0xc5, 0xa4, 0x07, 0xc0, 0x1b, 0xff, 0xd5, 0x2b, 0x8e, 0x90, 0xcd, + 0x34, 0x3a, 0xd6, 0x2d, 0x3f, 0x20, 0x2a, 0x82, 0xc2, 0xdb, 0x32, 0x5f, + 0xc6, 0x89, 0xcd, 0x4d, 0x0c, 0x93, 0x3a, 0x68, 0x14, 0x38, 0xc1, 0x06, + 0x5b, 0x27, 0xa7, 0x15, 0x54, 0xd1, 0xd0, 0x69, 0x00, 0xd2, 0xfa, 0x24, + 0xa3, 0xdf, 0xf4, 0xe8, 0xa5, 0x4f, 0x73, 0x54, 0x67, 0xc3, 0x1b, 0x20, + 0x2d, 0xbc, 0x4d, 0x50, 0x4c, 0x19, 0xd7, 0x31, 0x00, 0xaf, 0x60, 0x5e, + 0x40, 0xe8, 0xf8, 0x1a, 0xa7, 0x34, 0x59, 0x00, 0x2f, 0x72, 0x1b, 0xbb, + 0x78, 0xce, 0xc8, 0x82, 0x56, 0xdd, 0x70, 0x33, 0x9f, 0x15, 0xf6, 0x3b, + 0xd1, 0x47, 0x19, 0x67, 0xb1, 0xc9, 0xeb, 0xc7, 0xcc, 0x4f, 0xd0, 0x95, + 0xc3, 0xd3, 0xe0, 0x16, 0xb2, 0x29, 0x13, 0x40, 0x16, 0xa3, 0x4c, 0x73, + 0xef, 0x78, 0x18, 0x7f, 0xeb, 0xf9, 0xee, 0x73, 0x74, 0x89, 0xca, 0x34, + 0xbc, 0xa4, 0x92, 0xd0, 0x33, 0x7e, 0x94, 0xbe, 0x3e, 0x35, 0xf0, 0x21, + 0x7c, 0x0b, 0x2f, 0x3f, 0x89, 0x97, 0x32, 0x2e, 0xbe, 0x25, 0xaf, 0x46, + 0xd3, 0x06, 0x7d, 0xb7, 0xbf, 0x25, 0x0f, 0xca, 0xa1, 0x0e, 0xe7, 0x0c, + 0x49, 0xa7, 0x2c, 0x9e, 0xe5, 0xa1, 0xbd, 0x15, 0xd1, 0x67, 0x12, 0xa4, + 0x1f, 0xc4, 0x73, 0xab, 0x9a, 0xd7, 0x50, 0x1e, 0x10, 0xcf, 0xbc, 0xb5, + 0x8f, 0x88, 0x82, 0xc9, 0x31, 0x21, 0x9f, 0x13, 0xef, 0x05, 0x64, 0xdb, + 0xc2, 0xf6, 0xc4, 0x03, 0x44, 0x3c, 0xba, 0x13, 0xbe, 0xa4, 0xa6, 0x7f, + 0xad, 0xdf, 0x2c, 0x4e, 0xca, 0xe3, 0xea, 0x9f, 0x23, 0xe8, 0x5c, 0xbb, + 0x0b, 0xb8, 0x04, 0xc9, 0x5b, 0x6d, 0xa0, 0x38, 0x0f, 0xa0, 0xbd, 0x2e, + 0xfd, 0x70, 0xe2, 0xd9, 0x83, 0x0a, 0x97, 0x87, 0x15, 0x9a, 0x95, 0x06, + 0xd8, 0x1c, 0x97, 0x4a, 0x04, 0x9c, 0x04, 0xd3, 0x8e, 0xef, 0xd8, 0xc5, + 0x1d, 0xa6, 0x35, 0xf0, 0xf9, 0xb9, 0xd2, 0x0c, 0x88, 0x02, 0x5c, 0x88, + 0xbd, 0x0f, 0x01, 0x99, 0x73, 0x0a, 0xca, 0xac, 0x74, 0xe5, 0x30, 0x24, + 0x85, 0x40, 0x73, 0x63, 0x6f, 0x71, 0x1d, 0x09, 0x23, 0x70, 0x56, 0xd9, + 0xb4, 0xe5, 0xe3, 0x1a, 0xe3, 0x95, 0x4c, 0x62, 0x47, 0xb6, 0x2c, 0x4b, + 0xc7, 0x9b, 0x6e, 0xe9, 0xdb, 0xe7, 0x8a, 0xb4, 0xea, 0x6b, 0x5d, 0xda, + 0x57, 0x53, 0xaa, 0x76, 0x0b, 0x66, 0x85, 0xbd, 0x13, 0xac, 0xd1, 0x12, + 0x60, 0x00, 0xbd, 0x22, 0xee, 0x3d, 0x80, 0xee, 0x68, 0xcf, 0xd2, 0xaa, + 0x3a, 0x11, 0xa6, 0xa9, 0xab, 0xcd, 0xce, 0xb6, 0x71, 0x3e, 0x4b, 0xfc, + 0x80, 0xb4, 0x16, 0x40, 0x09, 0x34, 0x6b, 0x2b, 0x3c, 0x9e, 0xc8, 0xca, + 0x74, 0xcf, 0x93, 0xfc, 0x28, 0x14, 0x20, 0xa9, 0xf4, 0x5d, 0xe1, 0x88, + 0x67, 0x32, 0x78, 0xd6, 0x1f, 0xb9, 0x8d, 0xbe, 0x10, 0x84, 0x99, 0x59, + 0x55, 0x61, 0x4e, 0x2e, 0x22, 0x0d, 0x38, 0x56, 0x7d, 0x25, 0x4d, 0x04, + 0x6d, 0x6e, 0xf7, 0x9b, 0xfb, 0x8b, 0x19, 0x28, 0x90, 0x0e, 0x3c, 0x24, + 0x4c, 0x22, 0x69, 0x50, 0x3d, 0x88, 0x98, 0xf1, 0x53, 0x79, 0xad, 0x1e, + 0xef, 0xbe, 0x13, 0xe5, 0xc0, 0x07, 0x09, 0xf3, 0x25, 0xf1, 0x43, 0xe9, + 0x10, 0x91, 0x47, 0x28, 0x8e, 0x72, 0x6b, 0x65, 0x54, 0x19, 0x61, 0x80, + 0x4a, 0x2b, 0x91, 0x90, 0x53, 0xb7, 0xa5, 0x18, 0x14, 0xfc, 0xa3, 0x66, + 0x3f, 0x21, 0x3d, 0x59, 0x85, 0x41, 0x28, 0x76, 0x20, 0x07, 0xdb, 0x82, + 0x3a, 0xb2, 0xb8, 0x10, 0x5d, 0xbf, 0x22, 0x95, 0x42, 0x7b, 0x25, 0xac, + 0x75, 0x09, 0x64, 0x25, 0xa9, 0x12, 0xb2, 0x9c, 0x5a, 0x76, 0x81, 0x91, + 0x0a, 0xff, 0x18, 0xe4, 0x37, 0x6d, 0x13, 0x1c, 0x04, 0x23, 0xa4, 0x42, + 0xa5, 0x92, 0xd4, 0xde, 0xb6, 0x41, 0x06, 0xcf, 0x89, 0x56, 0x78, 0x14, + 0xa0, 0xa5, 0x07, 0x97, 0xe0, 0x4f, 0x93, 0xcd, 0x71, 0x50, 0xa3, 0x5e, + 0x59, 0x44, 0x55, 0x75, 0x80, 0xcb, 0x6e, 0xc9, 0x74, 0x11, 0x79, 0x9c, + 0x00, 0x24, 0xa3, 0x23, 0x9d, 0xb9, 0x63, 0x18, 0x35, 0x46, 0x79, 0x72, + 0xf7, 0x97, 0x0d, 0x8b, 0xfd, 0xcd, 0x2a, 0x82, 0x35, 0x21, 0xc7, 0x9c, + 0x39, 0x28, 0xb1, 0x55, 0x08, 0x44, 0xb1, 0xdd, 0x1e, 0xdf, 0xab, 0x24, + 0xba, 0x08, 0x82, 0x09, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x9e, 0x06, 0x6b, 0x13, 0x78, 0xff, 0x96, 0xe7, 0xaa, 0x8f, 0xc6, 0x49, + 0xec, 0xad, 0xcd, 0xee, 0x27, 0x47, 0xc5, 0x70, 0xfe, 0x4b, 0x8f, 0x3e, + 0x35, 0xd5, 0xe8, 0xd9, 0x03, 0x39, 0xb0, 0x26, 0x31, 0xd3, 0x32, 0xd0, + 0x21, 0x4b, 0x04, 0x7e, 0xb7, 0x48, 0xe8, 0x0e, 0x30, 0xda, 0x5b, 0x7e, + 0xc5, 0x94, 0xce, 0x2a, 0x70, 0x28, 0xfb, 0xf3, 0x99, 0xe2, 0xa3, 0x14, + 0xf8, 0x85, 0x10, 0x03, 0xae, 0x25, 0x33, 0x4f, 0x9e, 0x93, 0x79, 0x44, + 0x58, 0x6a, 0x02, 0x09, 0xd2, 0x7e, 0x9f, 0xff, 0x12, 0xac, 0x11, 0xef, + 0x0c, 0x62, 0xcd, 0x89, 0x05, 0x4b, 0x31, 0xb6, 0xbf, 0xb7, 0x03, 0x13, + 0x17, 0x67, 0x92, 0xef, 0x1f, 0xe0, 0x40, 0xce, 0x23, 0xdf, 0xfd, 0x07, + 0x73, 0xd4, 0x9d, 0x31, 0xad, 0x34, 0x46, 0xd5, 0x8a, 0xd3, 0x04, 0x2d, + 0x76, 0x7d, 0x6c, 0x81, 0x8d, 0x43, 0xa3, 0x12, 0x16, 0x9a, 0x34, 0x93, + 0xf1, 0x3d, 0x4e, 0x1f, 0xa8, 0xcb, 0x86, 0x26, 0xc6, 0xb2, 0xb0, 0x23, + 0x4b, 0x26, 0xa7, 0x5a, 0x16, 0x0b, 0xfe, 0xc7, 0xb0, 0xcf, 0xfb, 0xfb, + 0x01, 0xa7, 0xb8, 0x0f, 0xeb, 0xb4, 0xf4, 0x86, 0x9c, 0x1d, 0xdb, 0x69, + 0x98, 0xbe, 0x9c, 0xa6, 0x16, 0xcb, 0x0c, 0xb9, 0xc8, 0x48, 0xae, 0x03, + 0x1f, 0x1e, 0xf5, 0xd9, 0x7a, 0x6b, 0x6d, 0x90, 0xd1, 0x1f, 0x49, 0x16, + 0xf1, 0x2c, 0x1c, 0xb0, 0x67, 0x44, 0x80, 0xdd, 0x5c, 0x18, 0x36, 0xaa, + 0xee, 0x34, 0x48, 0x3e, 0xdf, 0x84, 0x6d, 0x08, 0x2b, 0xaf, 0x71, 0xf3, + 0xf5, 0x48, 0x71, 0x4f, 0xa0, 0xfd, 0xac, 0x21, 0x26, 0x7b, 0xfd, 0x25, + 0xb7, 0x9c, 0x2c, 0x6f, 0x6a, 0xcf, 0xe7, 0x4f, 0xca, 0x99, 0x51, 0x90, + 0xc5, 0x20, 0x9c, 0x98, 0x9a, 0xe2, 0x92, 0x5d, 0x81, 0xcf, 0x22, 0xe9, + 0x3d, 0x09, 0x7d, 0x1b, 0x48, 0x08, 0xd4, 0xfc, 0xcc, 0xa6, 0xb6, 0x6c, + 0x9a, 0x31, 0xb0, 0x98, 0x7b, 0x00, 0x3e, 0x8f, 0x76, 0xa3, 0x6b, 0xbb, + 0x1b, 0x91, 0x83, 0xf7, 0x33, 0xe2, 0xac, 0xe4, 0xca, 0x4e, 0x6c, 0x21, + 0x98, 0x30, 0x78, 0xfa, 0x07, 0x4b, 0x8f, 0xe8, 0x0b, 0x7a, 0xbb, 0xee, + 0xce, 0x8a, 0xe4, 0x73, 0x0d, 0xfa, 0xa4, 0x48, 0x0f, 0x49, 0x17, 0x34, + 0xfe, 0x0d, 0x9a, 0xed, 0x37, 0x57, 0x5f, 0x1f, 0x13, 0xa5, 0xac, 0xc3, + 0x90, 0xb1, 0x24, 0xcf, 0xbd, 0x69, 0xe2, 0xd0, 0x56, 0x91, 0x1e, 0x18, + 0xa2, 0x3a, 0xa4, 0xc6, 0xe0, 0x15, 0xd4, 0x00, 0xf8, 0xde, 0x78, 0xe6, + 0x15, 0xef, 0x74, 0x15, 0x03, 0xce, 0xb0, 0xeb, 0x9e, 0x2f, 0x3d, 0x2c, + 0xd8, 0xbe, 0x3f, 0x96, 0xec, 0x9d, 0x55, 0xaf, 0xe6, 0x10, 0x5f, 0xc3, + 0xf5, 0x5e, 0x1b, 0x48, 0xcd, 0xf6, 0x3f, 0x0f, 0x8d, 0xc0, 0xf3, 0x14, + 0x86, 0xc4, 0x1b, 0x5c, 0xf1, 0x23, 0x5a, 0xa7, 0x38, 0xa0, 0x46, 0xc5, + 0x5c, 0xef, 0x69, 0x5a, 0x76, 0x07, 0x90, 0x3e, 0x71, 0x69, 0x0d, 0xbb, + 0x25, 0xe4, 0xcf, 0xb4, 0x4f, 0x69, 0x01, 0x24, 0xf7, 0xf3, 0xf5, 0x4b, + 0xd8, 0x0d, 0xa4, 0xa8, 0xc9, 0xf1, 0x61, 0xa8, 0x95, 0x17, 0xf6, 0x85, + 0xe7, 0x32, 0x47, 0x06, 0x7d, 0x23, 0xf1, 0x60, 0xc4, 0x2d, 0xdb, 0x4e, + 0x13, 0x4d, 0x5f, 0x2c, 0xdf, 0x48, 0x4b, 0xc4, 0x7e, 0x06, 0x81, 0x9e, + 0x93, 0x07, 0x5e, 0xb5, 0x45, 0x79, 0x71, 0x16, 0xba, 0x3a, 0x64, 0x9e, + 0x69, 0x22, 0x94, 0x45, 0x95, 0xf1, 0x2d, 0x60, 0x27, 0xf0, 0x17, 0x15, + 0x59, 0xda, 0x83, 0xbf, 0x1e, 0x37, 0x1c, 0xfb, 0x3d, 0xf7, 0x22, 0x0f, + 0xed, 0xb5, 0x77, 0x61, 0xf8, 0x27, 0xf3, 0x71, 0x09, 0x9d, 0x1e, 0x33, + 0x6b, 0x54, 0xd1, 0x7f, 0x72, 0xec, 0x91, 0x15, 0x86, 0x3d, 0x49, 0x9e, + 0xce, 0x9d, 0x39, 0x87, 0x93, 0xb5, 0x7c, 0xa3, 0xe4, 0xb7, 0x82, 0xa6, + 0x0d, 0x24, 0x7e, 0xea, 0x61, 0x82, 0x72, 0x78, 0x91, 0xc3, 0x8b, 0x08, + 0xb0, 0x7e, 0x30, 0x07, 0x11, 0xdd, 0x0e, 0x07, 0xe6, 0xe5, 0x03, 0xde, + 0x26, 0xfc, 0x75, 0xb6, 0x5e, 0x8b, 0x6d, 0xf6, 0x97, 0xf1, 0x11, 0x78, + 0x1b, 0x5e, 0x2c, 0xbd, 0x2b, 0x08, 0xea, 0xa1, 0x55, 0x0c, 0xe3, 0x08, + 0xc0, 0xd1, 0x72, 0x08, 0xf1, 0x01, 0x88, 0x36, 0x49, 0x22, 0x8c, 0x6a, + 0xe9, 0xd2, 0xd1, 0x3f, 0xbb, 0x4b, 0x18, 0xde, 0x52, 0xb3, 0x23, 0x54, + 0x9d, 0xba, 0x9d, 0xbd, 0x73, 0x09, 0xea, 0x00, 0x2b, 0x6c, 0xc9, 0xa1, + 0xaf, 0xbb, 0xbc, 0x30, 0xd1, 0x1f, 0xdf, 0x92, 0xf1, 0xfd, 0x3f, 0xc9, + 0x7d, 0xb1, 0x44, 0x75, 0x3a, 0x4e, 0x96, 0x94, 0xe7, 0x42, 0xf0, 0x0a, + 0x7f, 0x83, 0x43, 0x19, 0xf5, 0x3c, 0xd6, 0x58, 0xc7, 0xde, 0x5f, 0xa0, + 0xaf, 0x38, 0xcf, 0xef, 0x83, 0xe9, 0x4a, 0xd6, 0xe9, 0x12, 0x20, 0xe2, + 0x18, 0xe8, 0x21, 0xf7, 0x6e, 0x78, 0xc9, 0x40, 0x46, 0x15, 0x78, 0x0f, + 0x15, 0xe7, 0xee, 0x9d, 0x7d, 0xd5, 0x7c, 0xc7, 0x03, 0x2b, 0x98, 0x91, + 0xad, 0xd3, 0x24, 0x82, 0x44, 0x31, 0x5d, 0xca, 0x9b, 0x6d, 0x10, 0xa7, + 0x21, 0xc5, 0xb3, 0x29, 0x87, 0x0e, 0xaa, 0x1f, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x9b, 0x57, 0xaa, 0x4b, 0x16, 0x24, 0xe0, 0x6d, + 0x2f, 0x6d, 0x0c, 0x92, 0x47, 0xd7, 0x60, 0x20, 0xfa, 0x85, 0xde, 0xff, + 0x66, 0xac, 0xef, 0x46, 0x5a, 0x40, 0xb5, 0xce, 0xf0, 0x88, 0x17, 0x0b, + 0x93, 0x22, 0x91, 0x57, 0xf9, 0xc5, 0xe4, 0x0c, 0x77, 0x74, 0x5a, 0xb0, + 0xca, 0x3d, 0x9a, 0x57, 0xb2, 0x50, 0xb9, 0x44, 0x27, 0x8d, 0x0b, 0x97, + 0xe6, 0x42, 0x38, 0xa7, 0x9c, 0x04, 0x79, 0x0c, 0x10, 0xe4, 0x90, 0x37, + 0x2e, 0xad, 0xc1, 0x5b, 0x5b, 0xbb, 0x6c, 0xbb, 0xad, 0x67, 0x86, 0x84, + 0xb4, 0x8e, 0x7e, 0x2f, 0xdd, 0x3e, 0xfc, 0x64, 0x87, 0x67, 0xe6, 0x31, + 0x5a, 0x4d, 0xc1, 0x26, 0x7a, 0x0e, 0x51, 0x16, 0x2b, 0xc7, 0x16, 0x61, + 0x65, 0xe3, 0xe3, 0x31, 0x51, 0x77, 0xfd, 0x3e, 0x7a, 0x3e, 0xc7, 0xdd, + 0x45, 0xde, 0x90, 0x66, 0x26, 0x70, 0x5a, 0x39, 0xb8, 0xa2, 0x8e, 0x05, + 0x3f, 0xbd, 0x47, 0xf4, 0x10, 0x15, 0xdd, 0x48, 0x24, 0xa6, 0x36, 0x52, + 0x83, 0x9b, 0x2b, 0xed, 0xfe, 0xbc, 0x94, 0x9c, 0xc2, 0x17, 0x79, 0x4a, + 0x04, 0x39, 0x3a, 0xbe, 0x29, 0x10, 0x2e, 0x06, 0x88, 0x25, 0x70, 0x91, + 0xb0, 0xbe, 0xd8, 0xc0, 0x26, 0x11, 0x40, 0xc0, 0x65, 0x3a, 0x72, 0x6e, + 0x0c, 0x7a, 0xbb, 0xe2, 0x7f, 0xca, 0x26, 0x1e, 0x58, 0x83, 0x5b, 0x53, + 0x44, 0x51, 0x03, 0x27, 0x98, 0x08, 0x82, 0x09, 0xd4, 0xb0, 0x9c, 0xab, + 0xc5, 0x3c, 0x5c, 0x2c, 0x68, 0x5b, 0xc1, 0x31, 0xd2, 0xa4, 0x55, 0x86, + 0xaf, 0x18, 0xd6, 0x7c, 0xbb, 0xcf, 0x0c, 0xbb, 0x84, 0xc3, 0x17, 0x0d, + 0x64, 0xd5, 0xdb, 0x87, 0x8c, 0xba, 0xec, 0x6c, 0xa6, 0xf3, 0xf8, 0xca, + 0x9f, 0xb5, 0xb1, 0x07, 0x3b, 0xc8, 0x53, 0x2c, 0xa2, 0x9a, 0x35, 0x18, + 0x2f, 0x06, 0x90, 0x50, 0x95, 0xb4, 0x3b, 0x07, 0x2e, 0x6b, 0x68, 0x01, + 0x51, 0x9f, 0xc9, 0x08, 0x3d, 0x35, 0x88, 0xaa, 0x65, 0xef, 0x36, 0x11, + 0xc7, 0x88, 0x29, 0x97, 0x29, 0xd9, 0x75, 0x1e, 0x91, 0x3f, 0xab, 0x34, + 0x7b, 0xf4, 0xd4, 0x02, 0x4b, 0x32, 0x0f, 0x36, 0x87, 0x12, 0xd2, 0xf1, + 0x11, 0x39, 0x9f, 0xa3, 0x2c, 0xe1, 0x0b, 0x28, 0x4b, 0x70, 0xcc, 0xb4, + 0x66, 0xc4, 0x58, 0x41, 0xa5, 0x2b, 0xf0, 0x8f, 0x87, 0xf7, 0xef, 0x00, + 0x4d, 0x24, 0x35, 0x0d, 0x12, 0x73, 0x04, 0x13, 0x82, 0x06, 0x7f, 0xa7, + 0xff, 0x1c, 0xd7, 0x26, 0xa5, 0x41, 0x64, 0xb2, 0x08, 0x13, 0x84, 0xda, + 0x2c, 0xb4, 0x42, 0x36, 0x93, 0x9f, 0x08, 0x30, 0x16, 0x10, 0xa3, 0xac, + 0x89, 0xc4, 0xd3, 0x8e, 0x9e, 0x4e, 0xd4, 0xb0, 0x5c, 0xbe, 0x82, 0xb5, + 0x68, 0x95, 0xc7, 0x80, 0x0e, 0xe6, 0xc5, 0x28, 0x0f, 0x8f, 0x94, 0xff, + 0xc3, 0x0b, 0x39, 0x09, 0x7d, 0xab, 0xe0, 0x88, 0x9e, 0xe7, 0xa2, 0x28, + 0x89, 0x08, 0x6c, 0x9e, 0x8d, 0xc1, 0x5d, 0xbe, 0xd2, 0x69, 0x54, 0x65, + 0xcc, 0x92, 0x41, 0xd5, 0x89, 0xfe, 0x87, 0x10, 0x37, 0x8a, 0xce, 0x22, + 0x78, 0xf4, 0x91, 0xe5, 0xd1, 0xbe, 0x1a, 0x12, 0xad, 0xd8, 0x98, 0xe0, + 0xb9, 0x9a, 0x89, 0x9e, 0xf3, 0xcf, 0x16, 0xfd, 0xd2, 0xc2, 0xd4, 0xb2, + 0xe3, 0xee, 0x0f, 0x7d, 0xfb, 0x52, 0x4c, 0x05, 0x3b, 0x94, 0x11, 0x0d, + 0x82, 0x57, 0x69, 0xb2, 0xad, 0x76, 0xcd, 0xfa, 0x95, 0xfd, 0x12, 0x60, + 0x5c, 0x8d, 0xfd, 0x36, 0x12, 0x73, 0xeb, 0x99, 0x6f, 0xd0, 0x73, 0x89, + 0xe8, 0x44, 0x7b, 0x1f, 0x4a, 0x44, 0x1d, 0x8e, 0xb4, 0x40, 0xcd, 0xd0, + 0x07, 0xf5, 0xe0, 0xf9, 0xc0, 0xbd, 0x3e, 0x3f, 0x6d, 0x6d, 0x82, 0x01, + 0xfe, 0x86, 0x30, 0x1e, 0xa9, 0x47, 0x90, 0x98, 0x31, 0x76, 0x96, 0x27, + 0x7e, 0x72, 0x09, 0xa9, 0xd8, 0x87, 0x78, 0x21, 0x5b, 0x26, 0x8d, 0x81, + 0x5b, 0x98, 0x03, 0xbc, 0x43, 0x57, 0x3d, 0xd9, 0xa7, 0x3b, 0xfb, 0xf9, + 0x40, 0x0f, 0xf8, 0x2d, 0x9b, 0xa1, 0x61, 0x2e, 0x98, 0x06, 0x49, 0x60, + 0x4b, 0x4b, 0x89, 0x09, 0x14, 0xd1, 0x7a, 0x2f, 0xbe, 0x30, 0x8c, 0x9a, + 0x28, 0x8a, 0x55, 0x04, 0xe8, 0x2d, 0xf5, 0xdb, 0xb4, 0x96, 0x29, 0x5f, + 0x93, 0x79, 0xc6, 0x1d, 0xe3, 0x58, 0x3f, 0x17, 0xf8, 0x55, 0x63, 0x53, + 0x5f, 0x01, 0xbe, 0x83, 0xa9, 0x05, 0xec, 0x61, 0xcf, 0x4e, 0xa3, 0xe2, + 0xe1, 0xb0, 0x04, 0xb4, 0x1d, 0xfd, 0x52, 0xd9, 0x34, 0xdc, 0xd4, 0x06, + 0x68, 0xe0, 0x06, 0xf9, 0x8d, 0x98, 0xb4, 0xc5, 0x93, 0x3f, 0xfe, 0xc4, + 0xf0, 0x44, 0x09, 0x92, 0x4c, 0xb4, 0xff, 0xba, 0xdb, 0x94, 0x09, 0xf7, + 0x6d, 0xcb, 0xde, 0xa4, 0x8a, 0xf0, 0xa4, 0x28, 0x8c, 0x38, 0xb9, 0x29, + 0x5f, 0xdb, 0x07, 0xea, 0xb7, 0xb0, 0x7b, 0x59, 0x8e, 0x66, 0x27, 0xad, + 0x51, 0x98, 0x00, 0x74, 0x30, 0xc1, 0x7e, 0x38, 0xb0, 0xf3, 0xb8, 0x1f, + 0xa5, 0x60, 0x78, 0x24, 0x27, 0x05, 0x42, 0xf1, 0x0e, 0x2c, 0x5e, 0x4e, + 0x1e, 0x95, 0x95, 0x55, 0x1d, 0x7e, 0xa1, 0xe5, 0x4a, 0x0f, 0xfc, 0x98, + 0xbd, 0x5a, 0xab, 0x30, 0xb2, 0x9e, 0x3b, 0x28, 0x51, 0xb1, 0xc1, 0x11, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x80, 0xd2, 0xbd, 0xce, + 0x72, 0x9d, 0x08, 0x89, 0xdf, 0x8b, 0x03, 0xf2, 0xcc, 0x32, 0xd2, 0xd1, + 0xfa, 0xb7, 0x26, 0x36, 0xcf, 0x24, 0xf7, 0x5b, 0x2c, 0x7a, 0xa3, 0xff, + 0xa6, 0xcf, 0xa0, 0x2a, 0x81, 0x2b, 0x82, 0xf1, 0x0d, 0xe3, 0xd0, 0xed, + 0x3c, 0xa9, 0x8b, 0xf7, 0x74, 0xc1, 0xcb, 0xad, 0xa1, 0x60, 0xba, 0xdd, + 0x42, 0xc1, 0x7f, 0xf6, 0x23, 0xb9, 0x17, 0x5b, 0xa7, 0x28, 0x84, 0x2a, + 0x31, 0xff, 0xf6, 0x92, 0xeb, 0x9a, 0xa7, 0x23, 0x9f, 0xb1, 0xc7, 0xc3, + 0x49, 0x6c, 0x8f, 0x2f, 0x56, 0x9e, 0x5b, 0x89, 0x73, 0x62, 0x30, 0x15, + 0x5d, 0x3f, 0x64, 0xd1, 0xbd, 0xdf, 0x16, 0x0b, 0x30, 0x5c, 0x05, 0xab, + 0x23, 0x8f, 0xfd, 0xf0, 0xe1, 0xac, 0x22, 0xb0, 0x0d, 0x23, 0x9d, 0x87, + 0xa1, 0xe9, 0xae, 0xbe, 0xcd, 0x77, 0x68, 0x7e, 0xa4, 0xc0, 0x2b, 0xb1, + 0xbf, 0x23, 0xac, 0x2f, 0x6e, 0xe1, 0x51, 0x35, 0x42, 0x3a, 0x4f, 0x34, + 0x61, 0xeb, 0x74, 0xac, 0x66, 0x1a, 0xb3, 0x39, 0x84, 0x62, 0x92, 0x85, + 0x3a, 0x8e, 0x21, 0xa8, 0xcd, 0x82, 0xdc, 0x21, 0xcb, 0xa0, 0xfe, 0x25, + 0xfb, 0xc7, 0xc2, 0x9e, 0xa3, 0x86, 0xd1, 0x5c, 0x8e, 0x69, 0xca, 0xf9, + 0xb2, 0x53, 0x24, 0x81, 0xb7, 0xb1, 0xd0, 0x36, 0xa7, 0x33, 0x3e, 0xb8, + 0x3f, 0xed, 0xbb, 0x65, 0x1e, 0xae, 0xed, 0x1b, 0x16, 0xf9, 0xea, 0xd5, + 0xea, 0x71, 0xbb, 0x5d, 0x40, 0x16, 0x1c, 0x43, 0xe5, 0x32, 0x5e, 0x15, + 0xfd, 0xe1, 0xc8, 0xaa, 0xef, 0x54, 0x3e, 0x8a, 0x3c, 0x4d, 0xfd, 0xe5, + 0x2e, 0xd6, 0x65, 0x2d, 0xc4, 0xbd, 0x59, 0x6a, 0x3b, 0xd2, 0x1f, 0x22, + 0xca, 0x95, 0x11, 0xd5, 0x9b, 0x17, 0xd2, 0xb8, 0xa1, 0x40, 0x21, 0x98, + 0x14, 0x39, 0x73, 0x7c, 0x16, 0x9c, 0xda, 0xcf, 0xc2, 0xde, 0xb9, 0x1c, + 0xc6, 0x02, 0xfd, 0xf5, 0xc9, 0xaa, 0xac, 0x8d, 0x16, 0xe5, 0xdd, 0x51, + 0xbd, 0xb0, 0x6a, 0x4c, 0xd1, 0xb0, 0x3e, 0x57, 0xa8, 0xc8, 0x96, 0xc1, + 0x78, 0x96, 0x17, 0xc5, 0xa3, 0x49, 0x5c, 0x24, 0xc4, 0xf0, 0x4d, 0x4c, + 0x5d, 0x06, 0x17, 0x54, 0x90, 0x01, 0x8e, 0xbc, 0x27, 0x4a, 0x37, 0xf9, + 0xed, 0x8c, 0xf9, 0x49, 0xbf, 0x33, 0x73, 0x05, 0x59, 0x2e, 0x13, 0x15, + 0x4d, 0xdb, 0x81, 0x11, 0x55, 0x26, 0x09, 0xe8, 0xab, 0xb3, 0x30, 0xb6, + 0x64, 0xdb, 0xcc, 0xfb, 0x83, 0x9a, 0x1e, 0x86, 0xc8, 0x0a, 0x74, 0xbb, + 0xbb, 0x9d, 0x99, 0xf3, 0xe8, 0xff, 0x08, 0x0a, 0x5d, 0xa8, 0xa1, 0x23, + 0x39, 0x42, 0xe5, 0x25, 0x47, 0xde, 0x85, 0xb4, 0x17, 0xad, 0x42, 0xee, + 0x4a, 0x2e, 0x7e, 0x3c, 0x7e, 0xd7, 0xce, 0x8e, 0x61, 0x29, 0xe3, 0x38, + 0x1b, 0x94, 0xe7, 0xe4, 0xd3, 0xf3, 0x07, 0x2c, 0x97, 0x9f, 0x02, 0x66, + 0x42, 0x84, 0xab, 0x5d, 0x73, 0xf1, 0x61, 0x8b, 0xae, 0x36, 0x9d, 0xe7, + 0xda, 0xe7, 0x2e, 0x95, 0x3d, 0x47, 0x96, 0x50, 0x68, 0x5f, 0xea, 0x4f, + 0xf5, 0x6a, 0x36, 0x25, 0xd9, 0xeb, 0x27, 0x96, 0xf4, 0xcc, 0x57, 0x35, + 0x1f, 0xf5, 0xf9, 0x2a, 0x8d, 0x34, 0x4d, 0xb6, 0x94, 0x52, 0x15, 0x17, + 0x53, 0xea, 0x06, 0xbf, 0x79, 0x5e, 0x18, 0xfc, 0x24, 0x58, 0x97, 0x11, + 0xc6, 0xeb, 0x04, 0x3a, 0x4a, 0x98, 0xa8, 0x14, 0x91, 0xc4, 0xd5, 0xdc, + 0x03, 0x18, 0x6d, 0x9f, 0x7d, 0xd3, 0x36, 0x1f, 0x14, 0x19, 0xb4, 0x50, + 0x03, 0x73, 0x2c, 0x11, 0x24, 0x85, 0xa9, 0x14, 0xfe, 0xd6, 0x63, 0x55, + 0x49, 0x82, 0xa7, 0xd2, 0xd5, 0x70, 0x65, 0x63, 0x25, 0xda, 0x12, 0x6c, + 0x66, 0x8b, 0x70, 0x0f, 0x77, 0x34, 0x6a, 0xc9, 0xe8, 0x8b, 0xd8, 0x1b, + 0xb6, 0x62, 0x97, 0x1c, 0xd2, 0x98, 0x90, 0xd7, 0x54, 0xa5, 0xab, 0x0a, + 0x79, 0x87, 0xc8, 0xd5, 0xc4, 0xa4, 0xf8, 0xf5, 0x3a, 0x3b, 0x63, 0xa4, + 0x62, 0xa0, 0x38, 0xef, 0xbe, 0x3b, 0xa5, 0xb9, 0x23, 0xf6, 0x6f, 0x2a, + 0x1b, 0xd3, 0x8e, 0x7d, 0xb9, 0xb5, 0x80, 0xe4, 0xee, 0xc6, 0x9a, 0x1d, + 0xea, 0xba, 0x29, 0x79, 0xc4, 0xaa, 0xc1, 0xb0, 0xcf, 0x63, 0x82, 0xb0, + 0x8a, 0x24, 0x02, 0x88, 0x3b, 0x5b, 0xae, 0x09, 0x30, 0xd1, 0xe9, 0x63, + 0xff, 0x39, 0x4b, 0x60, 0x59, 0xa4, 0xca, 0x86, 0x37, 0x8c, 0xc7, 0x8a, + 0x81, 0x1f, 0xe9, 0x07, 0x86, 0xd8, 0x50, 0x21, 0x95, 0xec, 0xe3, 0x3f, + 0xe6, 0xa0, 0xa2, 0x19, 0x0c, 0xc4, 0xad, 0xc1, 0x01, 0xfd, 0x27, 0x9d, + 0x27, 0x5b, 0x4a, 0x71, 0xec, 0xcc, 0x3b, 0x01, 0x58, 0xee, 0x66, 0x68, + 0x75, 0xb7, 0xea, 0x19, 0xf9, 0x7b, 0x6c, 0xfe, 0x7e, 0x5b, 0xc0, 0x13, + 0x94, 0x54, 0x6b, 0xb0, 0x94, 0x06, 0xcf, 0xc7, 0xca, 0xc1, 0x82, 0xf5, + 0x99, 0x60, 0x00, 0x38, 0xa5, 0xe8, 0x7a, 0x49, 0x63, 0x4f, 0x11, 0x4e, + 0x61, 0xb0, 0x25, 0x42, 0xd7, 0x1e, 0xd9, 0x01, 0x27, 0xd2, 0x74, 0xdc, + 0x13, 0x6a, 0x15, 0x74, 0xda, 0x35, 0x94, 0x17, 0x79, 0x7c, 0xe8, 0x53, + 0x4b, 0x03, 0xae, 0x4f, 0x52, 0xeb, 0x65, 0xeb, 0xb1, 0x67, 0x64, 0x2c, + 0x8d, 0x10, 0xd2, 0x08, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x4d, 0x11, 0x06, 0x86, 0xdd, 0x77, 0x67, 0x2c, 0x9c, 0x84, 0xe7, 0x6c, + 0xa3, 0xf9, 0x95, 0x04, 0x3b, 0xca, 0xbb, 0x62, 0x8d, 0x57, 0xb1, 0xa7, + 0x30, 0xee, 0x3d, 0xda, 0xe4, 0x1c, 0xf5, 0x23, 0xca, 0x82, 0x4b, 0x30, + 0x57, 0x8f, 0x2c, 0xc2, 0x2d, 0x84, 0xd9, 0x6a, 0x27, 0x3c, 0x11, 0x5c, + 0x07, 0xff, 0xaf, 0x7c, 0xd2, 0x99, 0x96, 0x9e, 0x4c, 0xeb, 0xa9, 0x10, + 0x70, 0xdf, 0xe4, 0x26, 0xbd, 0x4c, 0xdc, 0x58, 0xed, 0x36, 0x04, 0x60, + 0x09, 0xb2, 0xd7, 0x56, 0x5c, 0x1e, 0xa9, 0x7b, 0x7a, 0xa9, 0xcc, 0xaf, + 0x94, 0xf3, 0xa5, 0x12, 0xd1, 0xa3, 0x22, 0xaf, 0x5a, 0x07, 0x99, 0x17, + 0xc9, 0x82, 0xce, 0xe1, 0x9b, 0xbe, 0xd7, 0xbc, 0xe9, 0xa7, 0xb2, 0xb4, + 0x6d, 0x52, 0x6b, 0x20, 0xa4, 0x6d, 0xed, 0x33, 0x0a, 0x5e, 0x52, 0x97, + 0x7b, 0xf3, 0x3d, 0xdb, 0x43, 0xf3, 0x57, 0x1b, 0x9d, 0x31, 0xe7, 0xb2, + 0xb5, 0x38, 0x44, 0x0c, 0xed, 0x02, 0x6b, 0xb9, 0x99, 0x93, 0xbb, 0xcd, + 0x74, 0x70, 0x3c, 0x05, 0x97, 0x58, 0x29, 0xc6, 0x30, 0x9b, 0xf9, 0xca, + 0x89, 0x1b, 0x9d, 0x15, 0x73, 0xbc, 0xa5, 0x0a, 0xd6, 0x67, 0x6f, 0x04, + 0xdd, 0xa2, 0x44, 0x6e, 0x9d, 0x04, 0xab, 0x8d, 0x87, 0x55, 0x63, 0x10, + 0x33, 0x02, 0x55, 0x9e, 0xea, 0xfd, 0xee, 0x93, 0x00, 0x44, 0x86, 0x20, + 0xd2, 0x37, 0xe9, 0xcc, 0xa3, 0xb8, 0xab, 0x53, 0xa5, 0x06, 0x37, 0xca, + 0x16, 0x89, 0x3d, 0xf8, 0xc8, 0x09, 0xc0, 0x03, 0xa7, 0xe8, 0x3c, 0x61, + 0xa2, 0xb8, 0x03, 0xd0, 0x29, 0xc2, 0x14, 0x1a, 0x8a, 0xa1, 0xbf, 0x9e, + 0xf6, 0x27, 0xa9, 0x42, 0xee, 0xff, 0x43, 0xea, 0xa8, 0x76, 0xc9, 0x04, + 0x63, 0x20, 0x29, 0x40, 0x6a, 0x5e, 0x2c, 0xba, 0x52, 0xd0, 0x16, 0xce, + 0x34, 0x86, 0x6b, 0x02, 0x8e, 0x7a, 0x29, 0xe5, 0x52, 0xc9, 0xfe, 0xa1, + 0xd8, 0xe6, 0x66, 0xde, 0xf3, 0x45, 0xa5, 0xaf, 0x44, 0x61, 0xb3, 0x79, + 0x4e, 0xce, 0xcd, 0x84, 0x5a, 0x5e, 0xe4, 0x36, 0xd6, 0xa6, 0x88, 0x08, + 0x0f, 0x52, 0x89, 0x6f, 0x4b, 0xec, 0x66, 0xb3, 0xc1, 0x19, 0x7c, 0xaa, + 0x59, 0xd2, 0x7f, 0x0d, 0x43, 0xbc, 0x6a, 0x14, 0xc9, 0xa4, 0x05, 0xb1, + 0xc2, 0x1f, 0x3a, 0xe4, 0xc2, 0x33, 0x61, 0x25, 0xbb, 0xf4, 0x00, 0x0d, + 0xe9, 0x52, 0xdf, 0xd6, 0x29, 0x91, 0xde, 0x0d, 0xf2, 0x2c, 0x76, 0x17, + 0x9f, 0xad, 0x25, 0xd1, 0x8a, 0x15, 0xd9, 0xe0, 0x03, 0x85, 0x8d, 0x10, + 0x17, 0xe2, 0x4a, 0x05, 0x01, 0xcf, 0xed, 0xb1, 0x67, 0xbd, 0x76, 0xe1, + 0xb8, 0x8c, 0x92, 0xcc, 0x91, 0x2a, 0xfa, 0x48, 0xf0, 0x83, 0x4d, 0xc5, + 0x56, 0xae, 0x1b, 0xd2, 0x81, 0x2d, 0x34, 0xcd, 0x6a, 0x54, 0xf5, 0x04, + 0x15, 0x70, 0x31, 0x6f, 0x5f, 0xfc, 0xb8, 0x92, 0xa1, 0x66, 0x1d, 0x06, + 0x64, 0x22, 0x8c, 0xd5, 0x9c, 0x98, 0x58, 0xb8, 0x80, 0x98, 0x2f, 0x9a, + 0xff, 0xb5, 0xab, 0x99, 0xeb, 0x69, 0x2b, 0x08, 0xe1, 0xfc, 0x55, 0x18, + 0x33, 0x84, 0xa6, 0x21, 0x34, 0x51, 0x36, 0x34, 0xfc, 0x7f, 0xe5, 0x68, + 0x16, 0x82, 0x0e, 0x70, 0xb2, 0xed, 0x1d, 0x35, 0x8b, 0x95, 0x71, 0x3c, + 0xdd, 0xdd, 0xd2, 0x10, 0x36, 0x08, 0xca, 0xd9, 0x83, 0xdf, 0xdf, 0x1e, + 0x31, 0xf3, 0x5f, 0xc9, 0xb8, 0x98, 0x13, 0x87, 0xec, 0x6a, 0x0c, 0x9a, + 0x62, 0xf2, 0x42, 0x91, 0x52, 0xa3, 0xb9, 0xbe, 0xa8, 0xfa, 0x07, 0x02, + 0x95, 0xe7, 0x61, 0xaa, 0x81, 0x38, 0xfa, 0x7e, 0xd0, 0x95, 0x3b, 0xc9, + 0xaf, 0xe8, 0x7d, 0x2b, 0xfd, 0xf9, 0x3b, 0xc4, 0x1f, 0x2d, 0x82, 0x8c, + 0x92, 0xa7, 0xf2, 0xa8, 0x1a, 0xe4, 0x53, 0x2b, 0xdc, 0x8b, 0x77, 0x54, + 0x35, 0x98, 0x3c, 0x2c, 0xc6, 0xbd, 0x1e, 0x4d, 0x4c, 0x12, 0xb4, 0x08, + 0x81, 0xce, 0x24, 0xcf, 0x3a, 0x1d, 0xbd, 0x0b, 0x30, 0x77, 0xb0, 0x34, + 0x97, 0xa3, 0x61, 0x0b, 0x7c, 0xf5, 0x54, 0x29, 0x06, 0xcd, 0x3f, 0x03, + 0x22, 0xf0, 0x08, 0x44, 0xe4, 0xeb, 0xe0, 0x91, 0x82, 0x97, 0x92, 0xb9, + 0x22, 0x41, 0xef, 0x56, 0x41, 0x68, 0xb8, 0x0c, 0x8e, 0x1c, 0x4d, 0x13, + 0x12, 0x68, 0x50, 0x44, 0xa5, 0x57, 0x6f, 0x64, 0x54, 0x0c, 0xbb, 0x22, + 0x25, 0xda, 0xea, 0xfe, 0x2f, 0x23, 0xe9, 0x4a, 0x04, 0x56, 0xa2, 0x0f, + 0x03, 0xae, 0xc4, 0x7d, 0x89, 0x13, 0x3c, 0x16, 0xb7, 0x17, 0x46, 0x96, + 0x1e, 0x5c, 0xaf, 0x2c, 0x22, 0x05, 0x3a, 0xfa, 0x2b, 0x34, 0x62, 0x03, + 0xf1, 0x84, 0x3c, 0xb8, 0x61, 0x83, 0x5b, 0xfb, 0x0b, 0x1d, 0xab, 0x5f, + 0xec, 0xb8, 0x88, 0x19, 0x39, 0x9f, 0xe7, 0x5c, 0x3d, 0x05, 0x88, 0xeb, + 0x1f, 0xc0, 0x93, 0x4e, 0xa4, 0xff, 0xe5, 0x9e, 0x42, 0xd2, 0xfa, 0x26, + 0x11, 0xe3, 0xdd, 0xb4, 0x05, 0x74, 0x9e, 0xf7, 0xd0, 0x33, 0xd0, 0x0c, + 0xff, 0xe9, 0x2a, 0xf7, 0xf6, 0xdf, 0xde, 0x57, 0x0f, 0xe9, 0x3d, 0xbf, + 0x32, 0x54, 0x9b, 0x24, 0x70, 0x41, 0xf2, 0xfa, 0x58, 0xcf, 0xfb, 0xef, + 0x34, 0xbb, 0x2c, 0x94, 0xcb, 0xc5, 0xb0, 0x14, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x9c, 0x45, 0x88, 0x35, 0x16, 0x28, 0x7a, 0x47, + 0xf3, 0xe2, 0x35, 0x12, 0xf7, 0x15, 0xed, 0xe3, 0x20, 0x7a, 0xc4, 0x67, + 0x5e, 0x43, 0x68, 0x80, 0xce, 0x0a, 0xed, 0x72, 0xee, 0xbe, 0x99, 0x15, + 0x44, 0xda, 0x41, 0xb0, 0xf4, 0xa3, 0x2d, 0x85, 0x52, 0x3e, 0x87, 0x04, + 0x0a, 0xb6, 0xd0, 0x3a, 0x9a, 0x57, 0x61, 0x22, 0x09, 0xdf, 0x72, 0x1d, + 0x33, 0xf5, 0x62, 0x59, 0xf0, 0x87, 0x72, 0x11, 0x60, 0xec, 0x07, 0xf6, + 0x66, 0xf7, 0xbe, 0x1c, 0xf7, 0xca, 0xd6, 0x34, 0xa3, 0xc1, 0x2c, 0x5a, + 0xe9, 0x59, 0xc4, 0x77, 0xe3, 0xd7, 0xa6, 0xe8, 0xd7, 0x76, 0xd1, 0xb7, + 0xb4, 0xa6, 0x9e, 0x19, 0xf9, 0x99, 0x5d, 0x59, 0x45, 0x41, 0xc1, 0x6b, + 0x09, 0x14, 0x0c, 0xc5, 0xac, 0x2c, 0xe6, 0x89, 0x39, 0x46, 0xca, 0xe4, + 0x05, 0xf0, 0xb6, 0xc4, 0xba, 0x59, 0x06, 0xc0, 0xe5, 0x34, 0x9c, 0x04, + 0x6e, 0x3a, 0xe8, 0x17, 0xfe, 0x84, 0xfc, 0x5a, 0x01, 0x0c, 0x97, 0x1c, + 0x3a, 0xaa, 0x44, 0xd0, 0x68, 0x44, 0xdc, 0xda, 0x34, 0xa6, 0x81, 0x24, + 0x40, 0xd0, 0x00, 0x79, 0x0b, 0xcd, 0xa0, 0x06, 0x99, 0xeb, 0x4c, 0x5e, + 0xd2, 0xcf, 0x96, 0xbd, 0x93, 0x68, 0x78, 0xe5, 0xf3, 0x10, 0xb1, 0xb6, + 0xf1, 0x39, 0x8f, 0x2e, 0xf4, 0x62, 0xaa, 0x80, 0x93, 0x8c, 0xbd, 0x6c, + 0x84, 0x4c, 0x8a, 0x19, 0xd3, 0xee, 0x08, 0x12, 0x34, 0xa5, 0xa1, 0x12, + 0x02, 0x40, 0x36, 0x16, 0x66, 0x27, 0x19, 0x43, 0x5d, 0x1c, 0xfe, 0xd6, + 0x72, 0x8d, 0x69, 0xd6, 0x87, 0x8c, 0x08, 0xe4, 0x1b, 0x0c, 0xa7, 0x1e, + 0x84, 0x74, 0x2b, 0x63, 0xe0, 0x6c, 0x2e, 0xef, 0x08, 0x69, 0x66, 0x3a, + 0xff, 0xc6, 0xdb, 0x95, 0xb4, 0xfc, 0x18, 0x70, 0x6e, 0xdb, 0x9d, 0x9e, + 0x8f, 0xc5, 0xc1, 0xda, 0x7b, 0xda, 0x2d, 0x21, 0xa8, 0xc0, 0x41, 0x0d, + 0x59, 0x37, 0x0d, 0x5d, 0xdb, 0x0a, 0xe5, 0xb2, 0xcd, 0xd5, 0xfc, 0xfe, + 0x84, 0xf7, 0x57, 0x6f, 0x1f, 0xcf, 0x0f, 0xe3, 0x2e, 0xbc, 0x49, 0x47, + 0x32, 0xbe, 0x87, 0x08, 0x1e, 0x38, 0xea, 0x9f, 0x09, 0xf5, 0x92, 0x3c, + 0xd3, 0xd2, 0x66, 0x2a, 0x57, 0x76, 0x9f, 0xea, 0x99, 0x81, 0xae, 0x19, + 0x8c, 0xe5, 0x3a, 0x4c, 0x4d, 0x57, 0xd1, 0x8b, 0x2f, 0x52, 0xb6, 0x2c, + 0x46, 0x02, 0x86, 0x93, 0x7b, 0xbf, 0x02, 0x62, 0x59, 0x54, 0x6f, 0x81, + 0xde, 0x13, 0x00, 0x65, 0x4a, 0xfb, 0x22, 0xbd, 0x0d, 0xed, 0xeb, 0x47, + 0x1b, 0x5a, 0x38, 0x82, 0xb4, 0x0f, 0x49, 0x0a, 0xd9, 0x26, 0x7b, 0x5e, + 0x22, 0x62, 0x21, 0x1e, 0xc7, 0x70, 0x1d, 0x7e, 0x6e, 0x93, 0xf4, 0x45, + 0xcc, 0x92, 0xc1, 0xc6, 0x7e, 0x97, 0x07, 0x64, 0x35, 0x80, 0x82, 0xa1, + 0xf7, 0x39, 0x81, 0x1c, 0xbd, 0xf9, 0x78, 0x1d, 0xc1, 0x34, 0x45, 0x63, + 0x2f, 0x44, 0x5e, 0x45, 0x39, 0x57, 0x5c, 0x98, 0xe2, 0x56, 0xea, 0x80, + 0x90, 0x44, 0x00, 0xf2, 0x96, 0x7b, 0x0c, 0x7a, 0xb4, 0xd6, 0x25, 0x09, + 0x17, 0x89, 0xdb, 0xc7, 0x94, 0x29, 0x35, 0x84, 0x5f, 0x6f, 0x14, 0x6d, + 0x83, 0xf2, 0x34, 0x9c, 0xc6, 0x48, 0x99, 0x76, 0xf3, 0xed, 0x20, 0xc5, + 0xa7, 0xe3, 0x84, 0x84, 0x36, 0x04, 0xba, 0x0a, 0x64, 0x44, 0xc3, 0x77, + 0x1e, 0xdb, 0x65, 0xf0, 0x81, 0xd5, 0xe4, 0x1d, 0xb3, 0xa8, 0xa4, 0x71, + 0xad, 0x7b, 0x66, 0x26, 0x95, 0x22, 0x82, 0x5d, 0x89, 0x87, 0x74, 0xcf, + 0x67, 0x0c, 0xc1, 0x07, 0xe2, 0xed, 0xa0, 0xea, 0xa2, 0x8a, 0x9b, 0x14, + 0x81, 0x91, 0x1a, 0xed, 0x3a, 0x8f, 0x99, 0xcb, 0xf2, 0x85, 0xb5, 0xa1, + 0xff, 0x59, 0xc5, 0x28, 0x12, 0xbc, 0xf7, 0x83, 0x00, 0xd1, 0x69, 0x28, + 0x02, 0x9c, 0x28, 0xb2, 0x25, 0x19, 0x54, 0xc5, 0xc2, 0x03, 0x31, 0x5d, + 0x41, 0xeb, 0x27, 0x7a, 0x6d, 0x49, 0xb8, 0x30, 0x4a, 0x01, 0xed, 0x37, + 0x12, 0xef, 0xcc, 0xc2, 0x85, 0x97, 0x49, 0x02, 0x63, 0x27, 0x24, 0xa3, + 0xb0, 0x51, 0x61, 0xb5, 0x32, 0xb3, 0x79, 0xad, 0x89, 0xc5, 0x21, 0xa8, + 0xeb, 0x27, 0x52, 0x4c, 0x1a, 0xbb, 0x7e, 0x6f, 0x86, 0x17, 0xe1, 0xf6, + 0x2a, 0x69, 0x62, 0x0a, 0xce, 0x59, 0xc5, 0x6a, 0xc0, 0x5a, 0xc8, 0x52, + 0xe2, 0x9a, 0x55, 0x72, 0x80, 0x76, 0x91, 0x5b, 0x7a, 0xa2, 0xc6, 0xa2, + 0x3c, 0xb2, 0xd9, 0x93, 0x14, 0x2d, 0x70, 0xa3, 0x8c, 0x99, 0x7f, 0x07, + 0x68, 0x15, 0x8e, 0x25, 0xea, 0xfb, 0xde, 0x2f, 0x46, 0xc7, 0xef, 0xcc, + 0xac, 0x69, 0x45, 0x60, 0x50, 0x59, 0xa4, 0x7c, 0x92, 0x0b, 0x20, 0x2d, + 0xa4, 0xf2, 0xa4, 0xd4, 0xcf, 0x6f, 0x25, 0x1c, 0x68, 0x77, 0x9d, 0xf8, + 0x40, 0x20, 0x72, 0x17, 0x03, 0xac, 0x14, 0x24, 0x83, 0x62, 0xa3, 0x13, + 0x45, 0x9a, 0x96, 0x41, 0xf5, 0x49, 0x98, 0x06, 0x28, 0x70, 0xdd, 0x7d, + 0xb8, 0x40, 0x72, 0x05, 0x99, 0xab, 0x3b, 0x10, 0xab, 0x46, 0xa8, 0xa3, + 0xcd, 0xdb, 0x6b, 0xb7, 0x30, 0x19, 0x99, 0x81, 0xf9, 0x8c, 0x53, 0x06, + 0xd2, 0x3d, 0x99, 0x0a, 0xaa, 0xe0, 0x44, 0x76, 0x61, 0xdd, 0x3b, 0x10, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x59, 0xae, 0x12, 0x03, + 0xf6, 0x11, 0x08, 0xf5, 0xa1, 0xef, 0x68, 0x90, 0x3d, 0x3e, 0x4f, 0x3e, + 0xb3, 0xce, 0xe1, 0xe1, 0x92, 0x67, 0xda, 0x8c, 0x71, 0x14, 0xfc, 0x11, + 0xde, 0xe6, 0x4d, 0x22, 0xbd, 0x10, 0x2e, 0xd7, 0x4e, 0xbb, 0x02, 0xbc, + 0xfe, 0x59, 0xd1, 0xca, 0x05, 0x23, 0x0e, 0x58, 0xab, 0x9f, 0x99, 0xa1, + 0x4d, 0x0d, 0x11, 0xab, 0x90, 0xba, 0xf5, 0x9c, 0x0d, 0x21, 0x6e, 0x2a, + 0x75, 0x21, 0x42, 0x66, 0x9d, 0x7e, 0xf0, 0x8a, 0xe4, 0xf3, 0x6e, 0xbf, + 0xca, 0x72, 0x31, 0x52, 0x46, 0x10, 0x6c, 0x11, 0x9f, 0x58, 0x51, 0x89, + 0x46, 0x2e, 0x71, 0x38, 0x82, 0x5a, 0xca, 0x24, 0x89, 0x47, 0x3f, 0xf5, + 0xc5, 0xe3, 0xb5, 0x9f, 0x12, 0xba, 0x0d, 0xde, 0xd4, 0x08, 0x5a, 0xd3, + 0x6a, 0x20, 0x25, 0x73, 0x17, 0x99, 0xaf, 0x82, 0x8c, 0xf1, 0xdb, 0x38, + 0x28, 0x2d, 0x10, 0x10, 0xaa, 0x1b, 0xca, 0x4b, 0x7c, 0x2d, 0x36, 0x47, + 0x97, 0x10, 0x9a, 0x19, 0xd3, 0x79, 0xff, 0xa6, 0x6b, 0x83, 0xe5, 0x10, + 0x2d, 0x54, 0x4e, 0xce, 0x85, 0x9d, 0xe7, 0x66, 0x79, 0x0e, 0x4b, 0x2f, + 0x2a, 0x59, 0xbd, 0x45, 0x37, 0x7f, 0x84, 0x21, 0x13, 0x4d, 0x6f, 0x59, + 0xde, 0x9f, 0xd0, 0x58, 0x61, 0x56, 0x74, 0x51, 0x49, 0x30, 0x2a, 0x5d, + 0x14, 0xe0, 0x98, 0x86, 0x9b, 0x64, 0x8b, 0x0d, 0xba, 0xc2, 0x58, 0x17, + 0xbf, 0x48, 0x58, 0x6d, 0x50, 0xab, 0x69, 0x6c, 0xa5, 0xe2, 0x30, 0xe1, + 0x98, 0x4a, 0xe1, 0x89, 0x5f, 0x48, 0xad, 0xd9, 0xc2, 0x0b, 0x90, 0x02, + 0xea, 0x48, 0x73, 0x24, 0xdf, 0x37, 0xa9, 0x1a, 0x9e, 0xe7, 0xcd, 0x5c, + 0xb0, 0x82, 0xbc, 0x83, 0x0d, 0x6e, 0x8d, 0x12, 0xc0, 0x94, 0x3e, 0x02, + 0xb3, 0xbc, 0x43, 0xaf, 0x8f, 0xb5, 0x22, 0x38, 0x85, 0x87, 0x1d, 0x12, + 0x76, 0x8d, 0xf2, 0xd9, 0x68, 0x72, 0xd6, 0x70, 0x40, 0x55, 0xf2, 0xc9, + 0xee, 0x7a, 0x18, 0x75, 0xa8, 0x88, 0x6d, 0xdf, 0xfa, 0x3f, 0xf8, 0xf7, + 0x5f, 0x5c, 0xcf, 0x14, 0x67, 0x09, 0xb0, 0x2a, 0x4c, 0x11, 0x7c, 0x77, + 0x1f, 0x81, 0xe3, 0xa3, 0x27, 0xdb, 0x09, 0xa0, 0x9c, 0x03, 0x38, 0x1e, + 0xa0, 0xf8, 0x74, 0x4c, 0xa6, 0x2c, 0xb9, 0xa5, 0x56, 0x53, 0xfc, 0x94, + 0x56, 0x1f, 0xaa, 0x29, 0x09, 0x8f, 0xc4, 0x0c, 0x25, 0x6b, 0xb0, 0xb4, + 0xed, 0x6a, 0x28, 0xc8, 0x9c, 0x81, 0xd7, 0x39, 0x44, 0xb0, 0xe1, 0x8e, + 0xe4, 0x32, 0xe7, 0xe9, 0xce, 0x2e, 0x5a, 0xb9, 0x8d, 0x93, 0x3e, 0x1b, + 0x9b, 0x97, 0x99, 0xc6, 0x5d, 0xa8, 0x9c, 0x97, 0xfd, 0xd3, 0x7a, 0x3a, + 0x63, 0x33, 0x3f, 0xe0, 0x95, 0x37, 0x2a, 0x41, 0x78, 0x2d, 0x49, 0xd8, + 0xa3, 0xe9, 0x45, 0x23, 0x4c, 0x51, 0xf7, 0x1c, 0xc6, 0x39, 0xc5, 0xd8, + 0xe5, 0x1a, 0x21, 0xa7, 0xe8, 0x36, 0x61, 0x8c, 0x14, 0xca, 0x50, 0x95, + 0x90, 0xd1, 0xc6, 0x77, 0xc0, 0xee, 0xa5, 0x77, 0x82, 0x28, 0x91, 0x03, + 0x9b, 0x9a, 0x6c, 0x03, 0x40, 0x04, 0x1f, 0x85, 0x6b, 0x96, 0x9f, 0x80, + 0x2d, 0x5a, 0x71, 0x15, 0x6a, 0xf9, 0x99, 0x2b, 0x50, 0x9b, 0x04, 0xa5, + 0xb3, 0x2e, 0x35, 0x67, 0xbf, 0x4a, 0x89, 0xf9, 0x27, 0xc7, 0xaa, 0x26, + 0x7c, 0xcf, 0xc5, 0x76, 0x79, 0xf8, 0xd0, 0xe4, 0xc9, 0xaf, 0xde, 0x40, + 0x7f, 0xbd, 0x24, 0xde, 0xc8, 0xb5, 0x82, 0x27, 0x60, 0x55, 0xf6, 0x93, + 0xac, 0x6d, 0xd5, 0x04, 0x62, 0x39, 0x13, 0x06, 0xdf, 0xc5, 0xfb, 0x7a, + 0xd5, 0x08, 0x76, 0x44, 0x7a, 0xfb, 0xc1, 0xdb, 0x16, 0x6f, 0x26, 0x77, + 0x49, 0xfc, 0x83, 0x45, 0x87, 0x64, 0xe2, 0x09, 0x50, 0xa9, 0xa9, 0x4d, + 0x1c, 0x61, 0x6c, 0x18, 0xaa, 0x21, 0xa6, 0x2b, 0xb2, 0x59, 0xf8, 0xfb, + 0xde, 0x79, 0xb4, 0x2c, 0xd9, 0x4f, 0x14, 0x93, 0xd4, 0xe4, 0x90, 0x28, + 0x35, 0x4a, 0xc1, 0xc1, 0x49, 0x48, 0xa2, 0x8d, 0x81, 0xb9, 0xa8, 0x29, + 0xcb, 0xe9, 0xf3, 0x95, 0xe3, 0x40, 0x6a, 0x82, 0xef, 0x6c, 0x70, 0x31, + 0xc8, 0xd0, 0x9e, 0xd2, 0xcb, 0xa3, 0x2b, 0x33, 0xfa, 0xa4, 0xab, 0x0a, + 0xdd, 0x73, 0xbf, 0x94, 0x3e, 0x8d, 0xe5, 0x0c, 0x3d, 0x8d, 0xc3, 0x9c, + 0xf4, 0x49, 0xf8, 0x66, 0x8c, 0x3b, 0xe0, 0xe7, 0x18, 0xde, 0x53, 0xb3, + 0x77, 0xee, 0x10, 0xf2, 0x7e, 0x96, 0x69, 0xc2, 0x4d, 0xd3, 0xfa, 0x6d, + 0x18, 0xb9, 0x9a, 0x17, 0xb9, 0x2e, 0x4f, 0x6a, 0x7f, 0x76, 0xc0, 0x83, + 0xd4, 0x4c, 0x19, 0xac, 0x49, 0x70, 0x37, 0x96, 0x1b, 0xd5, 0xdc, 0x8a, + 0x52, 0x5b, 0xe9, 0xe1, 0xd2, 0xac, 0xbf, 0x3c, 0xb0, 0x1e, 0xd1, 0x2c, + 0x26, 0xe6, 0x21, 0x33, 0xad, 0x36, 0x00, 0xea, 0x89, 0x4c, 0xf4, 0xa2, + 0x6f, 0x74, 0x83, 0x60, 0x1f, 0x21, 0x0f, 0x4f, 0x55, 0x21, 0xdb, 0x3d, + 0x43, 0x60, 0xfb, 0xd1, 0x3b, 0x46, 0xed, 0x29, 0x71, 0xd8, 0xe7, 0xed, + 0xee, 0x7e, 0xfc, 0xea, 0xc2, 0x68, 0xfb, 0x0d, 0x23, 0x68, 0xbf, 0xc3, + 0x3b, 0x09, 0xd8, 0xae, 0x3e, 0x2e, 0x41, 0x04, 0x88, 0x6e, 0x86, 0x9e, + 0x33, 0xc2, 0x45, 0x22, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xa4, 0xd5, 0x52, 0x62, 0x30, 0xba, 0xc6, 0xf7, 0xdc, 0x56, 0x59, 0x96, + 0x12, 0x1f, 0xea, 0xa7, 0x7c, 0xc2, 0xc3, 0x7c, 0xda, 0xc4, 0xfd, 0x31, + 0x41, 0x00, 0xe3, 0x14, 0x4c, 0xce, 0xec, 0x01, 0xa1, 0xeb, 0x06, 0x60, + 0xae, 0xd2, 0xe3, 0xda, 0xb9, 0xda, 0xce, 0x7e, 0xf5, 0x9b, 0xcf, 0x8d, + 0xba, 0x94, 0x9d, 0xff, 0xf9, 0xc6, 0x62, 0x80, 0x6c, 0x90, 0xa8, 0xc1, + 0x2b, 0x0f, 0xc1, 0x2a, 0xd5, 0xbc, 0xc7, 0xd6, 0xe8, 0x4a, 0x8b, 0x0a, + 0x15, 0x0f, 0xc0, 0x73, 0x36, 0xc7, 0xc6, 0x6d, 0xe9, 0xa3, 0xf3, 0x31, + 0xe6, 0x3d, 0x9b, 0xc3, 0x9b, 0x5b, 0x84, 0x64, 0x0a, 0xb5, 0x41, 0x10, + 0x9c, 0x65, 0x7f, 0xc7, 0x1f, 0xef, 0x8d, 0x6d, 0xa7, 0xc0, 0xa8, 0x04, + 0xa0, 0x7b, 0x40, 0x55, 0x09, 0x25, 0x44, 0x3a, 0x19, 0xd9, 0xda, 0x0f, + 0x80, 0xf0, 0xa2, 0x0c, 0xcf, 0x34, 0xb3, 0x2c, 0xf5, 0x86, 0x97, 0xc7, + 0xe9, 0x19, 0xe5, 0xb0, 0xb9, 0x23, 0xe6, 0x5a, 0x80, 0x97, 0xea, 0xb3, + 0x92, 0xc2, 0x32, 0x61, 0x23, 0xfc, 0x3c, 0xaa, 0x3e, 0x83, 0x33, 0x67, + 0xce, 0x76, 0x10, 0x16, 0xcf, 0x69, 0x87, 0x7f, 0x65, 0x25, 0xd9, 0xdd, + 0xa0, 0x8a, 0xb3, 0x5e, 0x26, 0xaa, 0xd3, 0x1b, 0x92, 0xc2, 0x9e, 0x80, + 0x99, 0x32, 0x7b, 0x86, 0xae, 0x23, 0xab, 0x28, 0xa0, 0x8e, 0x8c, 0x0f, + 0x96, 0xa0, 0x2c, 0x4e, 0x43, 0xcc, 0x86, 0xea, 0x53, 0x0e, 0x87, 0xf9, + 0xc6, 0x32, 0xf9, 0x66, 0x78, 0x80, 0xca, 0x8c, 0xee, 0x05, 0xe1, 0x17, + 0xf6, 0x3f, 0x57, 0x0b, 0xcf, 0xee, 0x20, 0x01, 0xa9, 0xae, 0xf0, 0xdd, + 0xd3, 0xbb, 0x50, 0xbc, 0xb8, 0x38, 0x16, 0x0c, 0x0e, 0xba, 0x88, 0xac, + 0x4a, 0x40, 0x51, 0x9e, 0xd8, 0xc5, 0xb5, 0x4c, 0x52, 0x48, 0xde, 0xcd, + 0x58, 0x75, 0xe6, 0x15, 0x0d, 0x41, 0x98, 0xf6, 0x5d, 0x7c, 0xe4, 0x18, + 0x0b, 0xee, 0x2d, 0x0b, 0x40, 0x23, 0x6d, 0x7b, 0x32, 0x1b, 0x71, 0xac, + 0xb9, 0x42, 0x4a, 0xc2, 0xb1, 0x38, 0xdd, 0xdd, 0xc8, 0x44, 0xc6, 0x2a, + 0x31, 0xb9, 0xe7, 0xbe, 0xa4, 0x8b, 0x12, 0x02, 0x4a, 0x1c, 0xfa, 0x68, + 0x82, 0x06, 0xa0, 0xa2, 0x2f, 0x90, 0xec, 0x46, 0x5a, 0x02, 0x74, 0x60, + 0x41, 0xb8, 0xd2, 0xe4, 0x41, 0x2e, 0x65, 0x08, 0x28, 0x21, 0xb8, 0x53, + 0x4b, 0x70, 0x79, 0xd7, 0xd9, 0x3d, 0x11, 0x04, 0x91, 0xdb, 0x82, 0x9c, + 0xf3, 0xfa, 0x87, 0x8f, 0xc2, 0x60, 0x06, 0x21, 0x28, 0x86, 0x0c, 0xcd, + 0x3f, 0xca, 0x9b, 0x2e, 0xb3, 0x83, 0x19, 0x09, 0x4b, 0x81, 0xb2, 0xca, + 0x24, 0xc1, 0xe1, 0x02, 0x40, 0x8d, 0x5d, 0xa7, 0x26, 0x2e, 0x42, 0x63, + 0x70, 0xf8, 0x1b, 0x8e, 0xb5, 0x07, 0x84, 0x73, 0x31, 0xf2, 0x22, 0x0d, + 0x8a, 0xaf, 0x18, 0xee, 0x09, 0x6c, 0x4b, 0x69, 0x5d, 0x96, 0xde, 0x3e, + 0xa0, 0xda, 0x46, 0x14, 0x4b, 0xe6, 0xb1, 0x62, 0x64, 0x31, 0xfe, 0xda, + 0x4d, 0x39, 0x68, 0x24, 0x1a, 0x63, 0x72, 0x15, 0x7d, 0x21, 0x8e, 0x2d, + 0xf1, 0x25, 0x5f, 0xf0, 0x35, 0x9d, 0x7c, 0xa3, 0x1c, 0x75, 0xd2, 0x3b, + 0x9e, 0xc0, 0x7d, 0x21, 0xcf, 0x29, 0x92, 0x9d, 0x49, 0x4c, 0xa9, 0xc3, + 0xe4, 0x61, 0xf1, 0x27, 0xe8, 0xd6, 0x28, 0xcf, 0x8a, 0x9c, 0x24, 0xa3, + 0xcc, 0x87, 0xf6, 0x33, 0x68, 0xea, 0xfa, 0xe5, 0xbc, 0xca, 0xc9, 0x5d, + 0x2e, 0x46, 0xe8, 0x32, 0xef, 0x61, 0x89, 0x09, 0xf7, 0x0e, 0xa8, 0x28, + 0x86, 0x18, 0x41, 0xb7, 0x03, 0xc7, 0xc4, 0x2a, 0x57, 0x2a, 0x9b, 0xea, + 0xa1, 0x34, 0xa4, 0xcd, 0x56, 0x18, 0x30, 0x61, 0xa8, 0x53, 0x38, 0x0f, + 0xc2, 0xcc, 0x7d, 0xee, 0x15, 0x49, 0xac, 0x0e, 0xf0, 0x32, 0x0a, 0xaf, + 0x47, 0x96, 0x91, 0x23, 0xfb, 0x7c, 0x2a, 0xf8, 0xff, 0xdb, 0x17, 0x70, + 0xff, 0xa0, 0x31, 0x34, 0xb1, 0x44, 0x95, 0x73, 0x0a, 0x68, 0x1a, 0x75, + 0xf2, 0x05, 0x4b, 0x09, 0xd6, 0x70, 0xbb, 0xfa, 0x6f, 0x2f, 0x07, 0x23, + 0x92, 0xe0, 0x6d, 0x44, 0xcf, 0x6d, 0x7a, 0x03, 0x0f, 0xb2, 0xf2, 0x3e, + 0x79, 0x7e, 0x5e, 0xb2, 0x07, 0x28, 0x4c, 0xa6, 0xaa, 0x3c, 0xed, 0x02, + 0x3d, 0x02, 0xed, 0x3b, 0xc7, 0xcd, 0xaf, 0x8b, 0x3c, 0x4c, 0x41, 0x15, + 0x6b, 0x3f, 0x41, 0x1e, 0xe9, 0x2e, 0x98, 0x81, 0xea, 0xda, 0x14, 0x75, + 0x68, 0xe2, 0xb9, 0xff, 0x7e, 0xa1, 0x5c, 0x02, 0xc3, 0x03, 0xb8, 0xa9, + 0xab, 0x96, 0xc4, 0x3e, 0x32, 0x31, 0xd9, 0x5e, 0x54, 0x04, 0x47, 0x5e, + 0xa4, 0x1b, 0x9c, 0xf4, 0x1b, 0x90, 0xef, 0xe1, 0xfc, 0x43, 0x50, 0x40, + 0xf0, 0xe9, 0x79, 0x2d, 0xcb, 0x2b, 0xb9, 0xb4, 0xf8, 0x59, 0x59, 0x66, + 0xbb, 0x82, 0xf1, 0x5b, 0xeb, 0xd8, 0x64, 0x19, 0x8a, 0xfb, 0x30, 0xf3, + 0x15, 0xc8, 0xe0, 0xdc, 0x2e, 0xb2, 0x58, 0x18, 0x91, 0xa0, 0x26, 0x03, + 0x51, 0x8a, 0xfa, 0xaa, 0xd4, 0xec, 0xee, 0xbb, 0xa2, 0x6a, 0x7a, 0xbd, + 0x42, 0x06, 0x09, 0x25, 0x01, 0xaa, 0x5e, 0xf9, 0x0f, 0x4f, 0xa7, 0x08, + 0xa8, 0x1c, 0x51, 0x87, 0xe7, 0xa3, 0x34, 0x1b, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0x16, 0xf2, 0xd6, 0x2e, 0x87, 0x55, 0xd6, 0x24, + 0x3b, 0x4a, 0x3f, 0x59, 0xc1, 0x3d, 0x71, 0x70, 0xe2, 0x84, 0xbe, 0x07, + 0x76, 0xb9, 0x95, 0xbd, 0x50, 0xba, 0x43, 0xe7, 0x35, 0x16, 0x25, 0x07, + 0xe3, 0xf8, 0xb5, 0x24, 0x4f, 0x6b, 0x82, 0xa9, 0x59, 0xb0, 0xad, 0x19, + 0x85, 0x71, 0x4d, 0x04, 0x49, 0x38, 0x85, 0x0d, 0xf7, 0x2c, 0x9d, 0xe3, + 0xb3, 0x91, 0x64, 0xa0, 0x73, 0x69, 0x00, 0x27, 0x05, 0xe0, 0x54, 0x32, + 0x95, 0xb9, 0xaf, 0x64, 0x0b, 0x9d, 0xd5, 0xdd, 0x94, 0x11, 0x46, 0xff, + 0xb0, 0x7a, 0x84, 0x2c, 0x2e, 0xc9, 0xf8, 0x90, 0x51, 0x6f, 0x11, 0x9d, + 0x8a, 0x91, 0x1f, 0x2c, 0xc6, 0x15, 0x1c, 0x5d, 0x24, 0x55, 0x33, 0xd4, + 0xbe, 0x60, 0x53, 0x9c, 0x95, 0x80, 0x3b, 0xc9, 0x79, 0xb5, 0x2e, 0xfe, + 0xf6, 0x09, 0xda, 0x01, 0xa1, 0x8c, 0x67, 0x9a, 0x0d, 0x1a, 0xba, 0x18, + 0xea, 0x16, 0x84, 0x6b, 0x59, 0x68, 0xd3, 0xd8, 0xf6, 0x8f, 0xed, 0x54, + 0xbe, 0x44, 0x62, 0xa8, 0xc8, 0x50, 0x7f, 0xc6, 0x83, 0xc6, 0x5f, 0x7a, + 0x9d, 0x3c, 0x46, 0xa2, 0x26, 0x98, 0x2a, 0x02, 0xbe, 0xa9, 0xfa, 0x33, + 0x2b, 0x41, 0x75, 0x81, 0x89, 0x60, 0xd7, 0xd4, 0xe7, 0x50, 0x56, 0xc5, + 0x87, 0xde, 0xae, 0x07, 0x48, 0x4d, 0xf7, 0xca, 0x85, 0x3b, 0x11, 0x6f, + 0xc2, 0xd8, 0xae, 0x1b, 0xb6, 0x5b, 0xdc, 0xe0, 0x91, 0x67, 0x38, 0xc8, + 0x11, 0xa6, 0x88, 0x2c, 0xdc, 0xf8, 0x41, 0x3c, 0xa0, 0xc5, 0x92, 0x2d, + 0x58, 0x16, 0xc4, 0xdd, 0x76, 0x39, 0x73, 0x30, 0x9b, 0x0b, 0x00, 0x30, + 0x02, 0xbd, 0x87, 0x1d, 0xe6, 0xfe, 0xaf, 0x20, 0xea, 0x46, 0x60, 0x0c, + 0x65, 0x20, 0xbb, 0x1b, 0x5c, 0x3d, 0x9f, 0x47, 0xd3, 0x39, 0x99, 0x10, + 0xce, 0x94, 0xf5, 0xe9, 0x9b, 0x31, 0x61, 0x1e, 0xab, 0xb0, 0xd0, 0x94, + 0x5e, 0x0d, 0x74, 0xf5, 0x2f, 0x7b, 0xab, 0x6e, 0x79, 0x34, 0xd8, 0x69, + 0xb9, 0xbf, 0xec, 0x31, 0x20, 0xdd, 0x4d, 0x63, 0x76, 0xd3, 0x45, 0x0c, + 0x16, 0xf2, 0x2f, 0x12, 0xd8, 0x89, 0xac, 0xb3, 0x9e, 0x4d, 0x14, 0xeb, + 0x59, 0x8b, 0x51, 0x13, 0x05, 0x68, 0x3d, 0xf1, 0xdd, 0xd5, 0x91, 0x0e, + 0xed, 0xc8, 0x55, 0xfa, 0x8f, 0x18, 0x71, 0x15, 0x7d, 0x29, 0xfb, 0x0a, + 0xc3, 0xc0, 0xed, 0x15, 0x63, 0xf3, 0x1c, 0xe9, 0x5b, 0xee, 0x6f, 0x1f, + 0x84, 0x25, 0x9b, 0xe6, 0x20, 0x3b, 0xb3, 0xdc, 0xbf, 0x3e, 0xee, 0x6a, + 0xb4, 0xe1, 0xb6, 0xf9, 0x89, 0x8d, 0x3b, 0x2b, 0x00, 0x9b, 0x74, 0x73, + 0x58, 0x63, 0x77, 0x89, 0x37, 0x7a, 0x20, 0xbe, 0x13, 0x11, 0x1c, 0xd7, + 0xef, 0x94, 0x09, 0xb1, 0x6f, 0xd2, 0x2f, 0x7f, 0x62, 0xeb, 0x06, 0x60, + 0x62, 0xf4, 0xad, 0x0b, 0x3d, 0x3a, 0x65, 0x62, 0x8d, 0x6e, 0x00, 0x7a, + 0xef, 0xf4, 0x3d, 0x2f, 0x94, 0x98, 0xd8, 0x4d, 0x94, 0xcd, 0xc7, 0x6e, + 0x8c, 0x16, 0x15, 0xe8, 0xaa, 0x72, 0xee, 0x61, 0x4d, 0x2d, 0x04, 0x22, + 0x2a, 0x99, 0xbf, 0xf4, 0x0f, 0x4d, 0xba, 0xe9, 0xb2, 0xea, 0xf1, 0xa8, + 0x89, 0x79, 0x90, 0x66, 0x74, 0x70, 0x1a, 0x40, 0xa6, 0xc3, 0xcd, 0x57, + 0x29, 0xdd, 0x1e, 0x10, 0xe4, 0xcb, 0xe5, 0x21, 0x01, 0xd1, 0x7b, 0x06, + 0x94, 0x98, 0xeb, 0x5f, 0xa7, 0x14, 0x39, 0x63, 0x56, 0x2d, 0xd9, 0x2e, + 0x7d, 0x13, 0xa3, 0xe2, 0xb9, 0xf2, 0x1c, 0x08, 0x20, 0x71, 0x1d, 0xd8, + 0x97, 0x1d, 0xbe, 0x00, 0x30, 0x8d, 0xc4, 0xc8, 0x33, 0x63, 0x28, 0x3e, + 0xaa, 0xe0, 0x4b, 0xf5, 0x1c, 0xa1, 0xd7, 0x0b, 0x63, 0x36, 0x25, 0x43, + 0xb5, 0xee, 0xda, 0xc7, 0xad, 0xb4, 0x83, 0x66, 0xb6, 0x26, 0xb2, 0x08, + 0x4c, 0x50, 0x07, 0xb6, 0x39, 0xdc, 0x4c, 0x3a, 0xab, 0x66, 0xd2, 0x24, + 0x16, 0xc4, 0xbb, 0xd7, 0x45, 0x62, 0xc5, 0x3f, 0x09, 0xb3, 0x75, 0xd6, + 0x63, 0x9d, 0xa6, 0x7f, 0x89, 0x1c, 0xda, 0x24, 0x65, 0x7d, 0xb0, 0x8b, + 0x1e, 0x4d, 0xd3, 0x9f, 0x03, 0x7a, 0xb0, 0xb5, 0xd2, 0x97, 0xc4, 0x4d, + 0x49, 0x02, 0xad, 0xbf, 0x61, 0x7c, 0x0a, 0xfb, 0xdf, 0xee, 0x77, 0xed, + 0xb4, 0x9c, 0xea, 0x16, 0x28, 0x5d, 0x50, 0xed, 0xe0, 0x2e, 0xc3, 0xf5, + 0xb8, 0x54, 0x98, 0x34, 0xf4, 0x30, 0xea, 0x3b, 0xcc, 0x7b, 0x52, 0xb7, + 0x78, 0xf9, 0x34, 0x1f, 0xda, 0x1d, 0x5d, 0x59, 0xef, 0x82, 0x36, 0x04, + 0x62, 0x81, 0xba, 0xe9, 0x25, 0x09, 0x92, 0xf4, 0xb0, 0xde, 0xfe, 0x55, + 0xaf, 0x84, 0x8f, 0x44, 0x94, 0xb2, 0x3f, 0xfb, 0x59, 0x1a, 0x01, 0xa9, + 0x97, 0x98, 0xa3, 0x7d, 0xf2, 0xe4, 0x3a, 0x1e, 0xfb, 0xc6, 0x1f, 0x0f, + 0x2b, 0x31, 0xab, 0xce, 0x94, 0x7c, 0x33, 0xbc, 0x64, 0xf0, 0x41, 0xd5, + 0x63, 0xdc, 0xcf, 0x03, 0x14, 0xea, 0xe7, 0x23, 0x21, 0x08, 0xa6, 0x40, + 0xab, 0xe2, 0x81, 0x2a, 0x3c, 0xd6, 0xc0, 0xa5, 0x0d, 0x65, 0xa5, 0x96, + 0x4d, 0x0d, 0x51, 0xe7, 0xae, 0x59, 0x35, 0x36, 0x03, 0xd5, 0xaa, 0xe1, + 0x09, 0x0f, 0x51, 0x0c, 0x4b, 0x08, 0xcb, 0x7f, 0x35, 0x12, 0x7a, 0x2c, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x74, 0x78, 0x54, 0xd7, + 0x6a, 0x9b, 0x1a, 0x6a, 0x20, 0xc7, 0xf3, 0xdb, 0xe4, 0xc1, 0x83, 0xf1, + 0x72, 0xf7, 0xb8, 0xbc, 0x30, 0xab, 0xea, 0xdb, 0x72, 0x1e, 0xa3, 0xc0, + 0xd3, 0x1c, 0x7d, 0x0b, 0x7c, 0x23, 0xea, 0x69, 0x56, 0x2e, 0xf8, 0x50, + 0x0d, 0x69, 0x5c, 0x40, 0x0f, 0x02, 0xa9, 0x5b, 0x7e, 0x40, 0x66, 0x67, + 0x80, 0x65, 0x14, 0xc2, 0x62, 0x5f, 0x4b, 0x40, 0x94, 0x17, 0x47, 0x2d, + 0x17, 0xd4, 0x7d, 0x3a, 0xc0, 0x4b, 0x3a, 0xac, 0x8f, 0x93, 0x9d, 0x50, + 0xf7, 0x0a, 0x25, 0x5e, 0x39, 0x3a, 0x0e, 0xe3, 0xf2, 0x25, 0x11, 0xcc, + 0x2b, 0xdc, 0xee, 0xdf, 0x93, 0x81, 0xd6, 0x07, 0xd9, 0x73, 0x02, 0xa6, + 0xcf, 0xd4, 0x91, 0xfb, 0x94, 0x8d, 0x41, 0x67, 0xec, 0x82, 0xa9, 0x44, + 0xfe, 0x3b, 0xb8, 0xe2, 0x97, 0x33, 0x3a, 0xe3, 0x54, 0x22, 0x2f, 0xd6, + 0xbd, 0x03, 0x0f, 0x30, 0x1d, 0x3a, 0x24, 0x29, 0xe4, 0x62, 0xc8, 0xe1, + 0x01, 0x17, 0xa2, 0xac, 0xcd, 0xfc, 0x7c, 0x5d, 0x4f, 0xb6, 0x07, 0x42, + 0x57, 0x86, 0xd7, 0xe4, 0xf3, 0x45, 0x85, 0x71, 0x73, 0xc9, 0x45, 0x2c, + 0x95, 0xb1, 0x6f, 0x4a, 0x3f, 0xb2, 0x8a, 0x5a, 0x9e, 0xc1, 0x57, 0xd7, + 0x93, 0xd3, 0x6b, 0x53, 0xbe, 0x5f, 0xd0, 0xe7, 0x94, 0x0d, 0xa9, 0x3d, + 0xc7, 0x2b, 0x80, 0x66, 0x6a, 0x6a, 0xc1, 0x13, 0x81, 0x11, 0x35, 0x1e, + 0x7f, 0x2a, 0x12, 0x46, 0x81, 0xd3, 0x6b, 0xd1, 0x62, 0x48, 0xf4, 0x74, + 0x1b, 0x54, 0xf7, 0x2a, 0xc5, 0x0a, 0xeb, 0xd0, 0x56, 0x28, 0x49, 0xb4, + 0xec, 0x48, 0x29, 0x2e, 0x41, 0x0e, 0x15, 0xaf, 0x4f, 0x1d, 0x02, 0xb4, + 0x1f, 0xc6, 0x70, 0xd4, 0x3d, 0x72, 0x8f, 0x02, 0x42, 0x80, 0xe1, 0xdf, + 0xa4, 0xe0, 0xcd, 0xa8, 0xd3, 0x1c, 0x93, 0x91, 0xe8, 0x1f, 0x64, 0x25, + 0xd0, 0x0e, 0x10, 0x77, 0x19, 0x2c, 0x1f, 0x40, 0x76, 0xd1, 0xf6, 0xfd, + 0xaa, 0x3f, 0x9d, 0x8b, 0x63, 0x44, 0x9a, 0x08, 0x0e, 0xcb, 0x3d, 0xa1, + 0xb3, 0x34, 0x91, 0xcf, 0xbe, 0x45, 0xaf, 0x27, 0x56, 0x3f, 0xfd, 0x28, + 0x3a, 0xce, 0xe2, 0xee, 0x7e, 0x3d, 0x01, 0x11, 0x6f, 0x99, 0x23, 0xbd, + 0x9c, 0xc2, 0x8a, 0x38, 0x7b, 0xf3, 0xbc, 0x44, 0x21, 0x26, 0xea, 0xb1, + 0xe0, 0xc5, 0x14, 0x0e, 0x98, 0xf6, 0x8f, 0xba, 0xca, 0x5a, 0xfe, 0xf2, + 0xf4, 0x55, 0xae, 0x3e, 0xed, 0x0a, 0x52, 0x19, 0x6d, 0x20, 0xfd, 0x3f, + 0x13, 0x16, 0x2b, 0x1a, 0x31, 0x2a, 0x6e, 0x80, 0x07, 0x81, 0x2f, 0x27, + 0x57, 0xa2, 0x36, 0x0b, 0xe7, 0x09, 0xe4, 0x68, 0x1d, 0x27, 0x68, 0x0a, + 0xd5, 0x2c, 0xb2, 0xbd, 0xaa, 0xe2, 0x7e, 0xf7, 0xdb, 0x99, 0xf1, 0xbb, + 0xcb, 0xa6, 0x9b, 0xc8, 0x32, 0x8b, 0x72, 0x18, 0xb9, 0x97, 0x96, 0xd1, + 0xbd, 0xea, 0x23, 0x75, 0xbb, 0xcb, 0x08, 0x5d, 0x85, 0x00, 0xe9, 0x2c, + 0xa0, 0x70, 0x9e, 0x7c, 0x88, 0x5f, 0x3a, 0xe7, 0x8b, 0x99, 0x3d, 0xad, + 0xc4, 0x11, 0x0b, 0x03, 0xc6, 0x32, 0x3a, 0xc5, 0x05, 0xd9, 0x34, 0x00, + 0xbb, 0xad, 0x2b, 0xa4, 0xe5, 0x23, 0x79, 0xf4, 0x9a, 0x81, 0x2b, 0xda, + 0xda, 0xfa, 0xd9, 0x91, 0x83, 0xb1, 0x7b, 0x96, 0x57, 0x74, 0xf9, 0x1c, + 0xaa, 0x5d, 0xbe, 0xf0, 0xc5, 0x67, 0x59, 0xa5, 0x48, 0x22, 0x45, 0xf9, + 0x16, 0x8e, 0xb5, 0xbb, 0x1d, 0x4f, 0xfd, 0x39, 0xe7, 0x34, 0xbb, 0xef, + 0xf3, 0x8d, 0x17, 0x57, 0xe6, 0xc1, 0xef, 0x00, 0x8e, 0x9c, 0x34, 0x8f, + 0x64, 0xab, 0xcf, 0x05, 0x50, 0xa6, 0x4d, 0x34, 0x51, 0x6e, 0xe2, 0x5e, + 0x83, 0x3b, 0xae, 0x80, 0x9e, 0x75, 0xa7, 0x5b, 0xa3, 0x81, 0xb4, 0xb9, + 0x75, 0x13, 0xb3, 0x24, 0xd6, 0xc0, 0xc8, 0x9f, 0xc0, 0x6b, 0x33, 0xf5, + 0x93, 0x86, 0x1d, 0xf8, 0x4a, 0xc2, 0x0f, 0xf3, 0xf7, 0x1f, 0xd0, 0x20, + 0x77, 0x90, 0xc8, 0x00, 0x93, 0xf7, 0x3f, 0xa6, 0xb4, 0x90, 0x4d, 0x25, + 0x51, 0x00, 0x29, 0xc9, 0xb5, 0xcf, 0x7b, 0xef, 0xf8, 0xe8, 0xa7, 0x65, + 0x6f, 0x6f, 0x19, 0x72, 0x2e, 0xe3, 0xd0, 0xcc, 0xb8, 0x96, 0x5b, 0xcf, + 0x1e, 0xc9, 0x8b, 0xd2, 0xb9, 0xa3, 0x77, 0x0e, 0x01, 0xb1, 0x73, 0x42, + 0xd4, 0x9b, 0x28, 0x81, 0xfd, 0x23, 0x39, 0x0e, 0x09, 0x03, 0x38, 0x55, + 0xba, 0x06, 0x1b, 0x57, 0x88, 0x90, 0x1c, 0x93, 0xb9, 0x1c, 0x22, 0xb1, + 0xb6, 0xc4, 0x86, 0x22, 0x98, 0x12, 0xad, 0x1b, 0x49, 0x31, 0x16, 0x7f, + 0xc9, 0x12, 0x21, 0xfc, 0xc5, 0x85, 0xa0, 0x6a, 0x94, 0x75, 0x4f, 0x5f, + 0xb8, 0xa5, 0xfa, 0x16, 0x80, 0xcc, 0x74, 0x2f, 0x4c, 0x82, 0x58, 0x02, + 0x0a, 0x03, 0xa8, 0xef, 0xea, 0x5c, 0xe8, 0x93, 0x0c, 0x89, 0x22, 0x82, + 0x8a, 0x99, 0xa9, 0x53, 0x62, 0x94, 0xe1, 0x61, 0x37, 0x96, 0x97, 0x6f, + 0x63, 0xb1, 0xb7, 0xe4, 0xe3, 0xd4, 0x7f, 0x22, 0x77, 0xcd, 0x0e, 0xa4, + 0x0f, 0x96, 0xa8, 0x84, 0x54, 0xf6, 0xb6, 0x1a, 0x73, 0xc0, 0x57, 0x60, + 0x65, 0xba, 0x78, 0xf4, 0x56, 0x29, 0xf6, 0x35, 0x9e, 0x61, 0x31, 0x98, + 0x44, 0x01, 0xcd, 0x28, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xb6, 0xaf, 0xa8, 0x9a, 0x2b, 0xd0, 0xcc, 0x71, 0xcb, 0x8d, 0x46, 0x1b, + 0x28, 0x71, 0xef, 0xfe, 0xe2, 0x59, 0xf2, 0xa8, 0x71, 0x2b, 0x9c, 0xe9, + 0xa0, 0x9e, 0x2f, 0x5a, 0xe0, 0xed, 0xfe, 0x12, 0x6c, 0x1b, 0x1e, 0x44, + 0xe7, 0x7c, 0x39, 0xdf, 0x8f, 0x70, 0x85, 0xdc, 0xfa, 0x75, 0x86, 0x41, + 0x77, 0x26, 0x00, 0xc7, 0x46, 0xb0, 0x8f, 0xb4, 0x1e, 0x5f, 0xf3, 0x3f, + 0xf2, 0xd0, 0x0c, 0x25, 0x45, 0xe7, 0xa5, 0xa5, 0xe1, 0xf3, 0xfb, 0x62, + 0x8d, 0x98, 0x59, 0x45, 0x90, 0x2d, 0xcf, 0x08, 0x4f, 0xde, 0xd2, 0xf3, + 0xee, 0xf8, 0x4e, 0xaf, 0xce, 0x5a, 0xfd, 0x37, 0x17, 0xfe, 0xbe, 0x03, + 0x7a, 0xd0, 0x01, 0x3e, 0xc0, 0x50, 0x94, 0x9c, 0x59, 0x5d, 0xe7, 0x1c, + 0xe6, 0x86, 0xb3, 0xf5, 0x26, 0x82, 0xd8, 0xe2, 0xe1, 0x06, 0x9d, 0xab, + 0x0e, 0xb2, 0x86, 0x74, 0xf7, 0xea, 0x85, 0x0f, 0x97, 0x1a, 0x7b, 0xfa, + 0x34, 0xdb, 0xd5, 0x25, 0xc0, 0x96, 0xa7, 0x27, 0x28, 0x58, 0x74, 0xa2, + 0xc8, 0xd8, 0xd2, 0x3a, 0x27, 0x76, 0xc5, 0x26, 0xe7, 0x5d, 0x5d, 0x0d, + 0x71, 0xcf, 0xf8, 0x1f, 0x62, 0x97, 0x28, 0x43, 0x5b, 0x59, 0xae, 0x16, + 0xc7, 0xf9, 0x29, 0x1c, 0x02, 0xf6, 0x3f, 0x94, 0x4f, 0x8a, 0x29, 0xa0, + 0xb8, 0x28, 0x6e, 0x00, 0xa5, 0x4d, 0x8e, 0xbc, 0xc2, 0x07, 0x93, 0x1a, + 0xb5, 0x9f, 0xd7, 0xa4, 0x82, 0xeb, 0xdd, 0x6f, 0x13, 0x6d, 0xb6, 0xc2, + 0x5c, 0x82, 0x4c, 0x0a, 0x0b, 0x44, 0xc2, 0xae, 0xab, 0x19, 0xf5, 0x6e, + 0xc8, 0xb9, 0x7c, 0xad, 0x3a, 0x61, 0xf3, 0x08, 0x21, 0x97, 0xe5, 0x48, + 0x85, 0x14, 0xc5, 0x84, 0xd1, 0x7f, 0xe8, 0x40, 0x81, 0xd4, 0xfe, 0xcb, + 0x03, 0xbf, 0x5d, 0xfe, 0x0f, 0xb0, 0x57, 0xc0, 0x67, 0x60, 0xde, 0xf4, + 0xdc, 0x15, 0x35, 0x2a, 0xdd, 0xe8, 0xe6, 0xc1, 0x6c, 0x25, 0xb0, 0x28, + 0xe5, 0x7d, 0x88, 0x8d, 0xe4, 0xd3, 0x39, 0xd6, 0x5b, 0x0c, 0xe7, 0x6d, + 0x2a, 0x23, 0x2b, 0x0f, 0x56, 0xad, 0xfb, 0xfa, 0x29, 0x5c, 0xbc, 0x18, + 0x5b, 0x80, 0x7e, 0x2b, 0x72, 0x3f, 0xef, 0x62, 0x7d, 0xe7, 0x12, 0x3b, + 0x54, 0xf1, 0xec, 0xb5, 0xe0, 0x6d, 0xa2, 0xf8, 0xb5, 0xbe, 0xbe, 0x08, + 0xe4, 0xed, 0x87, 0x50, 0xc1, 0x25, 0x8d, 0x13, 0xca, 0x3b, 0x10, 0xcb, + 0x3b, 0x7a, 0x7b, 0x34, 0x60, 0x7e, 0xea, 0x2c, 0x74, 0xc2, 0xcc, 0x15, + 0x4c, 0x72, 0xf0, 0xfb, 0x9e, 0x3a, 0x84, 0xca, 0x23, 0xc0, 0xb7, 0x6e, + 0x97, 0x88, 0x0a, 0x17, 0x03, 0xc9, 0x9b, 0x63, 0xb6, 0x32, 0xc8, 0x8b, + 0x17, 0xef, 0x73, 0x56, 0x85, 0x7f, 0xe3, 0x12, 0x46, 0x5f, 0xd9, 0x00, + 0xf6, 0x24, 0x61, 0x74, 0x33, 0xbd, 0x0d, 0xbc, 0x41, 0x06, 0xe2, 0x16, + 0x82, 0xec, 0xdd, 0xe6, 0x90, 0x96, 0x4b, 0xdb, 0xc1, 0xdf, 0xe5, 0xcb, + 0x04, 0x1f, 0x9a, 0x9a, 0xfd, 0x82, 0x23, 0xec, 0x6e, 0x94, 0x11, 0xc5, + 0x13, 0x13, 0x9b, 0x4b, 0xe8, 0x56, 0x32, 0x13, 0x03, 0xb5, 0x1b, 0x71, + 0x7c, 0x00, 0x74, 0x32, 0x5b, 0xc2, 0x6e, 0x6d, 0x25, 0xcb, 0x67, 0x54, + 0x3b, 0x64, 0x83, 0xce, 0x39, 0xb8, 0x7a, 0xfd, 0xbb, 0x43, 0xb8, 0xad, + 0xee, 0xf0, 0x08, 0x06, 0xa0, 0xa9, 0x76, 0x4a, 0xf9, 0x95, 0x77, 0x1c, + 0x88, 0x9f, 0xd5, 0x72, 0x87, 0xf1, 0xaa, 0xdc, 0x7c, 0xbc, 0x04, 0xf5, + 0xcb, 0xa2, 0x3e, 0x45, 0x30, 0x57, 0x13, 0xcf, 0xb3, 0x74, 0x63, 0x11, + 0xba, 0x83, 0x3c, 0x2c, 0xe9, 0xff, 0x85, 0x3e, 0xd6, 0xd3, 0x95, 0xc3, + 0x46, 0x9e, 0xe3, 0x26, 0x69, 0xdc, 0x04, 0x2c, 0x78, 0x75, 0xdb, 0x81, + 0x8d, 0xc2, 0x96, 0xf5, 0x9f, 0xc3, 0x13, 0x10, 0xc0, 0xdb, 0x60, 0x26, + 0x93, 0xbf, 0x55, 0xde, 0x01, 0xd5, 0x08, 0x31, 0xc4, 0x13, 0xc5, 0x90, + 0x3d, 0xd0, 0xda, 0x97, 0x20, 0x35, 0x2b, 0x2a, 0x04, 0x8c, 0xa5, 0x42, + 0xf5, 0x6a, 0x0a, 0x28, 0xf9, 0xae, 0x82, 0xec, 0xef, 0xeb, 0x30, 0x4b, + 0x1c, 0xf4, 0xf3, 0xdb, 0xe4, 0x87, 0xc9, 0x88, 0x5e, 0xc7, 0xc0, 0xaa, + 0x9d, 0x94, 0x49, 0x92, 0xfe, 0x28, 0x5e, 0x96, 0x63, 0xc2, 0x3b, 0x2a, + 0x86, 0x77, 0x83, 0x06, 0x96, 0xba, 0x71, 0x70, 0xcf, 0xa7, 0x5e, 0x3d, + 0x91, 0xcb, 0x1a, 0x7d, 0xd2, 0x92, 0x3a, 0x74, 0x1d, 0xbc, 0xf1, 0xed, + 0xf8, 0xe0, 0xba, 0x10, 0xb6, 0xdb, 0x05, 0x1a, 0x77, 0x97, 0xe0, 0x07, + 0xb2, 0x1b, 0x7f, 0x09, 0x23, 0x06, 0xaa, 0x89, 0x14, 0x91, 0x7f, 0x15, + 0x13, 0x97, 0x1d, 0x52, 0x7b, 0x04, 0x10, 0x6c, 0xa7, 0x92, 0xe4, 0xd8, + 0x4d, 0xdb, 0x4d, 0x0f, 0x61, 0xc6, 0x72, 0x25, 0x00, 0x2a, 0xba, 0x24, + 0x09, 0x1c, 0xe2, 0x4f, 0x0f, 0x6c, 0xd6, 0x10, 0xca, 0xb9, 0xcc, 0xc1, + 0xbc, 0x77, 0xfd, 0xaf, 0x7c, 0x5d, 0x1c, 0xb2, 0x4c, 0x4d, 0xc5, 0x2a, + 0x74, 0x06, 0xe3, 0x35, 0x59, 0x10, 0xcb, 0xe3, 0x43, 0x5c, 0x76, 0xf5, + 0xd7, 0x62, 0x56, 0x0e, 0xe9, 0x5e, 0xa9, 0xdc, 0xfe, 0x8a, 0x64, 0x94, + 0xb9, 0x48, 0x10, 0x36, 0x52, 0x0d, 0x4b, 0x11, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xc6, 0x5a, 0x0b, 0xe2, 0xd3, 0x94, 0x6a, 0x73, + 0x9e, 0x90, 0x1a, 0x39, 0x01, 0x66, 0x26, 0x79, 0x27, 0x2f, 0x77, 0x27, + 0x3b, 0x59, 0x96, 0xa1, 0x77, 0xb4, 0xa1, 0x9e, 0x8c, 0x36, 0xdb, 0x15, + 0xde, 0x3a, 0xba, 0x82, 0x3e, 0x68, 0xcf, 0x07, 0x22, 0xa3, 0x09, 0x19, + 0xec, 0x4e, 0x93, 0x5d, 0x8e, 0x68, 0x4c, 0x0f, 0x65, 0x20, 0xc2, 0x94, + 0xb5, 0x10, 0xf7, 0x53, 0x42, 0x7f, 0x6c, 0x02, 0xe7, 0xc7, 0x28, 0x66, + 0xcb, 0x94, 0x9b, 0xa2, 0xe0, 0xae, 0x7e, 0x6b, 0x67, 0x99, 0x51, 0xc3, + 0x50, 0x3b, 0x76, 0xf7, 0xf6, 0x5f, 0xe4, 0x5a, 0x06, 0x3f, 0x12, 0x5e, + 0x61, 0x57, 0x9d, 0x06, 0x5f, 0x50, 0x68, 0x40, 0x0d, 0xa6, 0xee, 0x9f, + 0x01, 0x48, 0x17, 0x6b, 0x7e, 0x05, 0x43, 0x09, 0x8c, 0x73, 0xb4, 0x97, + 0x51, 0x98, 0xee, 0x54, 0xe5, 0xf7, 0x2b, 0x99, 0x3d, 0xc9, 0x43, 0x19, + 0xa6, 0xbd, 0x38, 0x3f, 0x33, 0x07, 0x6b, 0x53, 0x36, 0xc1, 0x00, 0xec, + 0xc5, 0x7d, 0x15, 0xaa, 0x2b, 0x68, 0x3f, 0x49, 0x1c, 0xf1, 0xe9, 0x9d, + 0xaf, 0x59, 0x15, 0x3e, 0x97, 0xed, 0x0f, 0x20, 0xb5, 0x03, 0x7e, 0x3e, + 0x30, 0x5b, 0x3f, 0x43, 0x8b, 0xc0, 0x27, 0x79, 0x40, 0x53, 0x03, 0x4b, + 0xfe, 0xc5, 0x11, 0x2a, 0x5d, 0x3d, 0x4d, 0x47, 0x9e, 0x37, 0x05, 0x4b, + 0x51, 0x89, 0x0a, 0x0a, 0x79, 0xf5, 0x76, 0xc3, 0x80, 0xeb, 0x1c, 0x63, + 0x14, 0xc7, 0x12, 0x66, 0x5e, 0x2e, 0x9d, 0xc7, 0xbe, 0xc0, 0x5a, 0x3d, + 0xe1, 0xd6, 0xd8, 0x3e, 0xa9, 0x9e, 0x18, 0x1d, 0xdb, 0xfe, 0xa9, 0x00, + 0x5a, 0x8d, 0x63, 0xea, 0x88, 0xd2, 0x15, 0x73, 0x6a, 0x7a, 0x4a, 0xb1, + 0x80, 0x61, 0x03, 0x88, 0x60, 0x0e, 0xae, 0xbf, 0x05, 0x52, 0xd9, 0x90, + 0x48, 0x2c, 0x9f, 0xb4, 0x02, 0xb9, 0x37, 0x28, 0xb9, 0x6f, 0xc9, 0xf7, + 0x4e, 0xea, 0x0c, 0x97, 0xf8, 0x27, 0xc5, 0x8c, 0x09, 0x95, 0xca, 0xe9, + 0xa3, 0xd5, 0xb1, 0x94, 0xc9, 0xaf, 0x7e, 0xa2, 0xc7, 0x3c, 0x7a, 0xec, + 0x51, 0x7e, 0x95, 0x28, 0xcf, 0xd3, 0xba, 0x97, 0x17, 0x43, 0xfd, 0x71, + 0x16, 0x4c, 0xc2, 0x91, 0x55, 0xd4, 0x8d, 0x93, 0xd2, 0x1c, 0xa5, 0x68, + 0x76, 0x8f, 0xe5, 0xca, 0x1d, 0xf7, 0xd9, 0x20, 0x8b, 0x50, 0x76, 0x10, + 0xdf, 0x29, 0x0f, 0x57, 0x1b, 0xff, 0xcb, 0x5c, 0x9c, 0x0c, 0xb4, 0x85, + 0x58, 0x56, 0x39, 0x01, 0x98, 0x03, 0x55, 0xdc, 0xdc, 0x95, 0x3c, 0xa5, + 0x06, 0x33, 0x86, 0x03, 0x29, 0x16, 0x47, 0x10, 0x5a, 0xe4, 0x27, 0x6b, + 0xb8, 0xd7, 0xad, 0x77, 0xee, 0xe7, 0xb2, 0x2e, 0x8d, 0xde, 0xae, 0xad, + 0x9b, 0x3d, 0xba, 0x99, 0x99, 0x30, 0xee, 0x1d, 0x2d, 0xa3, 0x77, 0x42, + 0x67, 0x88, 0x7f, 0x25, 0xf1, 0xbf, 0xa0, 0x84, 0xd9, 0x89, 0x54, 0x57, + 0x2e, 0x18, 0x3c, 0x40, 0xe8, 0x87, 0x30, 0xb6, 0xa3, 0x8f, 0x62, 0xe9, + 0x82, 0xa2, 0x8c, 0xba, 0xbf, 0x38, 0xf8, 0xb5, 0xe4, 0x71, 0xb8, 0x20, + 0x6d, 0x2c, 0xd8, 0x15, 0x09, 0x79, 0x0c, 0xe0, 0x32, 0x2f, 0x03, 0x2c, + 0x11, 0xe0, 0x9e, 0xbf, 0xc8, 0x06, 0x3a, 0x75, 0x1a, 0xbb, 0xb5, 0x54, + 0x6d, 0xeb, 0x57, 0xcf, 0xa4, 0x1c, 0xa1, 0x01, 0xcd, 0xfb, 0x1a, 0x0e, + 0x76, 0x41, 0xf8, 0x24, 0x8e, 0x24, 0x66, 0xff, 0xb0, 0xeb, 0xbb, 0xa0, + 0x21, 0xa8, 0x98, 0xb6, 0x0d, 0x0d, 0xbc, 0x68, 0x4f, 0x54, 0xed, 0x53, + 0x34, 0xae, 0x03, 0x20, 0xf9, 0x22, 0x74, 0x93, 0x6f, 0xb4, 0x04, 0x73, + 0x59, 0x79, 0xab, 0x0b, 0xea, 0x8a, 0x76, 0xe8, 0x8b, 0x77, 0x5e, 0x30, + 0xa5, 0x70, 0xfe, 0x7f, 0xf6, 0x1e, 0xe1, 0x6e, 0xb0, 0x24, 0xff, 0x29, + 0x3c, 0x73, 0xf9, 0xf3, 0x2c, 0x9b, 0x71, 0xd9, 0xf8, 0x2c, 0xb5, 0x23, + 0xbf, 0x91, 0xfa, 0xe3, 0xa3, 0xab, 0xc6, 0xc7, 0x0f, 0x02, 0xa0, 0x0c, + 0xcf, 0x74, 0x3f, 0x4b, 0xc3, 0x90, 0x7c, 0x1f, 0x6a, 0x6b, 0x57, 0xfd, + 0xc8, 0xcf, 0xfa, 0xb2, 0xc4, 0xa6, 0xbb, 0xd9, 0x84, 0x77, 0x99, 0x11, + 0x90, 0xe6, 0x2d, 0x00, 0x60, 0x5a, 0x25, 0xe6, 0xef, 0xa7, 0x71, 0x73, + 0xed, 0x20, 0x49, 0x17, 0x21, 0xdb, 0x29, 0x81, 0x6a, 0xfb, 0xa0, 0xce, + 0xac, 0x98, 0x83, 0xd8, 0xd6, 0xaf, 0x7a, 0xbd, 0xa0, 0xe9, 0x75, 0xef, + 0xc0, 0xf9, 0x62, 0x54, 0x40, 0x78, 0x38, 0xf4, 0xd1, 0xc0, 0x3c, 0x1d, + 0xac, 0xf7, 0x29, 0xb5, 0x99, 0xa1, 0x39, 0xb1, 0xae, 0xf2, 0xbd, 0x06, + 0xdc, 0xda, 0xd8, 0x32, 0x9d, 0x73, 0x7c, 0x78, 0xd5, 0xad, 0xd3, 0xe1, + 0x85, 0x7a, 0xdb, 0xcb, 0xaf, 0x50, 0x93, 0x1a, 0x67, 0xbc, 0xbc, 0x62, + 0x86, 0x1f, 0xb9, 0xf0, 0x40, 0x04, 0x57, 0xd1, 0x2e, 0x74, 0xe8, 0x47, + 0x11, 0xa7, 0x05, 0xcc, 0xda, 0x97, 0x4f, 0x5e, 0x4b, 0x65, 0xc7, 0x0d, + 0x67, 0x44, 0x36, 0x15, 0xbf, 0xb4, 0x09, 0x5d, 0x73, 0x0b, 0x08, 0x84, + 0xc4, 0x9e, 0x7c, 0xc0, 0x43, 0xfb, 0x83, 0x35, 0xe2, 0xdb, 0x92, 0xa7, + 0x30, 0x9a, 0x93, 0x3a, 0x57, 0x5e, 0xc4, 0x55, 0x2f, 0xca, 0xec, 0x03, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x51, 0x29, 0x58, 0x9b, + 0xa6, 0x58, 0xca, 0xe1, 0xc8, 0x7c, 0x4e, 0xf8, 0x76, 0xe3, 0xc7, 0xa8, + 0xc6, 0xfb, 0xf4, 0xb2, 0xb8, 0xe9, 0xfb, 0xeb, 0xfa, 0xd1, 0x53, 0x98, + 0x5d, 0x96, 0x58, 0x17, 0xad, 0x9f, 0x7d, 0x63, 0xfa, 0xb5, 0x56, 0xd6, + 0x92, 0xe9, 0x0f, 0x72, 0xbd, 0xf7, 0x71, 0x64, 0x75, 0x9e, 0x48, 0xbc, + 0x9f, 0x2a, 0x00, 0x9c, 0x10, 0x12, 0xa2, 0x1c, 0x06, 0x38, 0x59, 0x1a, + 0x1a, 0x9d, 0xb9, 0x6b, 0xcd, 0x5b, 0xcb, 0x84, 0x53, 0xe4, 0xe3, 0x7e, + 0x12, 0xca, 0xa5, 0xd6, 0x97, 0xb0, 0x50, 0x62, 0x85, 0x96, 0xf8, 0x8b, + 0xe9, 0xde, 0x51, 0x4f, 0xa3, 0x7e, 0x6f, 0x04, 0x32, 0xdc, 0xba, 0x2c, + 0x74, 0x1f, 0x68, 0xa5, 0xe7, 0x28, 0x2c, 0x0a, 0xde, 0xa1, 0x8b, 0x05, + 0x83, 0x68, 0xb4, 0x74, 0xad, 0xec, 0x5c, 0xa1, 0x18, 0x26, 0x75, 0xf1, + 0x3f, 0xeb, 0x10, 0x21, 0xf5, 0x1c, 0x26, 0xa9, 0x8c, 0x88, 0xa4, 0x39, + 0xd6, 0x1c, 0x61, 0xa8, 0xc1, 0x96, 0xda, 0xdd, 0xdc, 0x67, 0x4c, 0x53, + 0x37, 0x8c, 0xb3, 0x53, 0xae, 0xa8, 0xe1, 0x53, 0xe3, 0xde, 0xa6, 0x0f, + 0xab, 0x39, 0xf6, 0x53, 0xb8, 0xf0, 0xa7, 0x12, 0xc9, 0x19, 0x48, 0x07, + 0xfc, 0x93, 0xdb, 0x66, 0x4c, 0xbe, 0xf3, 0xfe, 0x99, 0xd7, 0x36, 0x45, + 0x4f, 0xe2, 0xb5, 0x21, 0x46, 0x6c, 0xea, 0x2d, 0xc8, 0x33, 0x91, 0x50, + 0xff, 0xa2, 0xb3, 0x4b, 0xa9, 0x72, 0x38, 0x1f, 0xf6, 0xd1, 0x96, 0x10, + 0x9f, 0x5a, 0x5e, 0xde, 0xd2, 0xe1, 0xb2, 0x74, 0x54, 0xd6, 0x99, 0xff, + 0x59, 0x26, 0xdd, 0x04, 0x79, 0x34, 0x44, 0x3c, 0x9a, 0x49, 0xea, 0xf8, + 0x27, 0x01, 0x53, 0x7c, 0x74, 0xc2, 0x73, 0x4f, 0x16, 0xe1, 0x79, 0x42, + 0x8c, 0x80, 0xc0, 0x5d, 0xf2, 0x3b, 0x87, 0x4b, 0xac, 0x79, 0xb5, 0x1c, + 0x53, 0x5a, 0x70, 0xbb, 0xe6, 0x97, 0xa4, 0x1d, 0xfc, 0x27, 0x3e, 0x27, + 0x47, 0x4c, 0x5c, 0x81, 0xae, 0xc8, 0xbe, 0xaf, 0xad, 0x20, 0x84, 0x6b, + 0x1e, 0xce, 0x92, 0x8a, 0xc9, 0xb9, 0xd9, 0x03, 0x95, 0x15, 0xe6, 0xc6, + 0x7e, 0xee, 0x8b, 0x5b, 0x53, 0x26, 0x6e, 0x5b, 0x3b, 0xa6, 0x85, 0x51, + 0x6a, 0xb0, 0x4d, 0xc6, 0xd3, 0x7d, 0x81, 0x28, 0xfe, 0x16, 0x16, 0x05, + 0x9a, 0x6a, 0x17, 0x1c, 0x0b, 0xd8, 0xf4, 0x46, 0x09, 0x8e, 0xe0, 0x8b, + 0x68, 0xf5, 0xe0, 0x5b, 0x23, 0xbb, 0xb0, 0x0f, 0x53, 0x58, 0x25, 0xd1, + 0x4c, 0x21, 0xd7, 0xa1, 0xda, 0xe8, 0xf5, 0xd4, 0x23, 0xd5, 0x9b, 0x13, + 0xd4, 0x3b, 0x50, 0x0c, 0xb1, 0xd3, 0xb3, 0xf3, 0x6f, 0x40, 0x72, 0xb6, + 0xf9, 0x30, 0x20, 0x64, 0xdd, 0x54, 0x4c, 0x27, 0x2b, 0x63, 0x81, 0x9e, + 0x66, 0x5e, 0x4b, 0xd0, 0xc2, 0x60, 0x7d, 0x1e, 0x5a, 0x4f, 0x57, 0x8c, + 0xdb, 0x43, 0xd2, 0x7a, 0x6f, 0x7f, 0xfd, 0x80, 0x6a, 0xf9, 0x4a, 0x08, + 0xd1, 0xd7, 0x67, 0x8a, 0x67, 0xd5, 0x1d, 0x69, 0x98, 0xc6, 0x3b, 0x98, + 0x60, 0xf3, 0xbe, 0x19, 0xa8, 0x5e, 0xe9, 0x17, 0x90, 0x94, 0x4c, 0x26, + 0x90, 0x24, 0x6e, 0xad, 0x1e, 0x21, 0xab, 0xe8, 0xa2, 0x94, 0x9c, 0xcd, + 0x45, 0x02, 0x94, 0x14, 0xab, 0x49, 0x45, 0x5e, 0xc1, 0xa3, 0xa0, 0x02, + 0xad, 0x9e, 0xd5, 0x13, 0xac, 0x95, 0xf1, 0x69, 0xc3, 0xfd, 0xd0, 0xa6, + 0x32, 0x4b, 0x97, 0x11, 0x9d, 0xbe, 0x9d, 0xd0, 0x37, 0xe1, 0x13, 0xee, + 0xc9, 0xa2, 0x6c, 0x1d, 0xf5, 0xb1, 0x00, 0x05, 0x48, 0xe5, 0xda, 0x3d, + 0x11, 0x0b, 0x9c, 0x5a, 0x2c, 0x6c, 0xf3, 0x77, 0xba, 0x94, 0x63, 0x13, + 0xec, 0x3e, 0xcc, 0xf6, 0x4c, 0xb0, 0x2a, 0x76, 0x05, 0x5d, 0xb4, 0xc9, + 0x25, 0xe8, 0x6f, 0x2a, 0x5f, 0xe3, 0xd0, 0xf9, 0xdd, 0x37, 0xb4, 0xe3, + 0x59, 0x5f, 0x40, 0x39, 0x3b, 0x2c, 0xee, 0x76, 0xe2, 0x26, 0x72, 0x73, + 0xff, 0x63, 0x72, 0x93, 0x85, 0x6c, 0x85, 0x5e, 0x37, 0x40, 0xea, 0x07, + 0x30, 0x85, 0x23, 0xac, 0x22, 0x48, 0x28, 0xa1, 0x09, 0x64, 0x58, 0xc5, + 0x38, 0x2b, 0xee, 0x4d, 0x50, 0x83, 0x19, 0x7f, 0xbf, 0x0e, 0x20, 0x44, + 0xb3, 0x45, 0x07, 0x09, 0x8f, 0x88, 0xf2, 0x26, 0x48, 0xd1, 0xa0, 0xb1, + 0x6e, 0x1b, 0x8a, 0xf5, 0x3f, 0x1e, 0x3c, 0x3a, 0x68, 0xe1, 0x00, 0xf1, + 0x0f, 0x8c, 0x7c, 0x77, 0x99, 0x78, 0xa5, 0x22, 0x28, 0xed, 0x2e, 0x8b, + 0x41, 0x50, 0xe6, 0x11, 0x60, 0xba, 0x28, 0xd5, 0xdc, 0x7c, 0x55, 0x0f, + 0x17, 0xdb, 0xee, 0x46, 0x21, 0x4b, 0x79, 0x15, 0xc2, 0x1f, 0x3d, 0xfa, + 0x39, 0x12, 0x24, 0xb0, 0x96, 0x05, 0x1d, 0x3e, 0x78, 0x0e, 0x52, 0x20, + 0xfe, 0xec, 0x1b, 0xef, 0x2f, 0x5d, 0x5e, 0x4f, 0x17, 0x15, 0xf5, 0xee, + 0xcd, 0x81, 0xa6, 0xb2, 0x80, 0x5e, 0x5a, 0xf9, 0x9e, 0xbf, 0xca, 0x59, + 0xec, 0x68, 0xc8, 0xee, 0x6a, 0xd7, 0xdd, 0x27, 0x72, 0xc1, 0x93, 0x0e, + 0xa9, 0xab, 0x1d, 0xf3, 0xc4, 0xde, 0x93, 0x40, 0x08, 0x8c, 0x27, 0xaf, + 0xff, 0x5d, 0x5f, 0x54, 0x60, 0xcf, 0x12, 0x50, 0xa6, 0xc6, 0x62, 0x03, + 0x62, 0x95, 0x15, 0x00, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0x5f, 0x95, 0xe2, 0x47, 0x38, 0x92, 0x77, 0x92, 0xf1, 0x6c, 0x77, 0x44, + 0xc9, 0x26, 0x34, 0xb5, 0x0a, 0xb6, 0x56, 0xd0, 0x3e, 0x16, 0x40, 0x9b, + 0xfc, 0xa7, 0xc5, 0x74, 0xc7, 0x12, 0x40, 0x14, 0x6d, 0xd6, 0x25, 0xe1, + 0x97, 0xcd, 0xa1, 0xef, 0x47, 0x39, 0xcf, 0xc7, 0x2a, 0x62, 0x2d, 0xca, + 0x71, 0x41, 0x2f, 0x13, 0x1b, 0x3e, 0xf5, 0x36, 0xc0, 0x97, 0x6c, 0xfc, + 0x37, 0xdb, 0x14, 0x17, 0x4e, 0xd9, 0x0d, 0xbb, 0x7f, 0x7c, 0xee, 0xa8, + 0xe4, 0x30, 0xaf, 0x69, 0xd1, 0xde, 0x8d, 0x8e, 0x54, 0x26, 0x89, 0x13, + 0xff, 0xd5, 0xd7, 0x4f, 0x76, 0xbb, 0xd7, 0x55, 0x28, 0x1c, 0xa7, 0x01, + 0x14, 0x25, 0xa8, 0x72, 0x7d, 0xa7, 0xb6, 0x8f, 0xb2, 0xcb, 0x15, 0xd8, + 0x57, 0xc8, 0x73, 0x72, 0xc8, 0x8b, 0x8e, 0xc7, 0xe7, 0x14, 0x7c, 0x62, + 0xab, 0xfa, 0xb3, 0xe2, 0x92, 0x17, 0x5e, 0x1d, 0xa6, 0xf3, 0x7f, 0x9e, + 0xdf, 0x1c, 0x6a, 0x10, 0x1f, 0xb7, 0x38, 0x13, 0x23, 0xa0, 0x89, 0x28, + 0xe1, 0x37, 0x56, 0x5d, 0x82, 0xaa, 0xf7, 0x12, 0x89, 0x04, 0x99, 0x2b, + 0x72, 0xc6, 0x3b, 0x26, 0xbb, 0xcc, 0x70, 0x7f, 0x0b, 0xf5, 0xf9, 0x51, + 0xfe, 0xb3, 0xc7, 0x35, 0xff, 0x26, 0x33, 0x94, 0x39, 0x1f, 0xa2, 0xee, + 0x42, 0x1a, 0xb0, 0x3f, 0x0e, 0xec, 0xd8, 0x8c, 0x10, 0xf1, 0xdc, 0x07, + 0x9e, 0xef, 0xc6, 0xe0, 0x46, 0x44, 0xd0, 0x3a, 0xd3, 0x32, 0xf5, 0x14, + 0x57, 0xa4, 0x19, 0x92, 0xee, 0xac, 0xc8, 0x2f, 0x91, 0xb8, 0x4d, 0x54, + 0x8b, 0xdc, 0x28, 0xf1, 0xd1, 0x29, 0x0e, 0x13, 0x21, 0x2a, 0x2a, 0x16, + 0x0b, 0x78, 0xb1, 0x68, 0xb5, 0x15, 0x18, 0x80, 0x69, 0xc0, 0x19, 0xf0, + 0x3e, 0xd0, 0x27, 0x00, 0xda, 0x48, 0xff, 0x57, 0x46, 0x70, 0x85, 0x27, + 0x4b, 0x18, 0x27, 0x05, 0xa1, 0x60, 0x71, 0x84, 0xb9, 0xc1, 0x50, 0xcd, + 0xa0, 0xd0, 0x5a, 0x83, 0xe7, 0xc9, 0xe9, 0x0a, 0xe1, 0x24, 0x51, 0x07, + 0xe0, 0x27, 0x7b, 0xc0, 0xa1, 0x56, 0x9f, 0x85, 0x6e, 0x31, 0x71, 0x14, + 0xa0, 0xe0, 0x0f, 0x86, 0xab, 0xc8, 0xad, 0x1a, 0x61, 0xf5, 0x96, 0x68, + 0xb9, 0xd1, 0x12, 0xd9, 0x8f, 0x05, 0x18, 0x6b, 0xa7, 0x6d, 0xb6, 0x93, + 0x69, 0x3f, 0x90, 0x7c, 0xbb, 0x68, 0x6c, 0x2a, 0x85, 0x74, 0xd2, 0x21, + 0x0f, 0xba, 0xdb, 0x78, 0x39, 0xc0, 0x97, 0x79, 0xda, 0xbf, 0x88, 0xef, + 0x84, 0x7e, 0x7d, 0x46, 0x34, 0x3e, 0x8f, 0x3b, 0xa5, 0x3d, 0x5c, 0xf6, + 0x66, 0x61, 0x3c, 0x01, 0x42, 0xba, 0xba, 0x4d, 0xd6, 0xb3, 0x5b, 0x82, + 0x7b, 0x2e, 0x89, 0x3a, 0xc6, 0xea, 0x6a, 0x4b, 0xe7, 0x9b, 0xa2, 0x94, + 0xf2, 0xa6, 0xc8, 0x30, 0x85, 0x61, 0xeb, 0x8e, 0xe1, 0x2d, 0x32, 0x1b, + 0xeb, 0x10, 0xf1, 0x0c, 0xa8, 0x65, 0x59, 0x70, 0x9a, 0x4a, 0x61, 0x06, + 0xfa, 0x0d, 0x2f, 0x1e, 0x72, 0x45, 0x23, 0x52, 0xe0, 0x0d, 0x11, 0x98, + 0x41, 0x4f, 0x9a, 0x3f, 0xf1, 0xd8, 0xa5, 0x0c, 0xab, 0x90, 0xc2, 0x5c, + 0x5f, 0x1f, 0x17, 0x78, 0xfa, 0xaa, 0x17, 0x85, 0xcb, 0x11, 0x15, 0xff, + 0x57, 0x8b, 0xcc, 0x6b, 0xd1, 0x43, 0xc7, 0xf1, 0x82, 0x52, 0x10, 0x4b, + 0xa6, 0xd2, 0x49, 0x0b, 0x2f, 0xa8, 0x43, 0x9c, 0x22, 0x74, 0x66, 0xf8, + 0xa2, 0x9f, 0xb6, 0x56, 0x04, 0x2f, 0xc0, 0x03, 0x40, 0xdc, 0x98, 0x9b, + 0x33, 0x2a, 0x92, 0x2c, 0x75, 0x60, 0x94, 0x5c, 0x6f, 0xf7, 0x3a, 0x0f, + 0x58, 0x8e, 0x7a, 0xc7, 0x43, 0x7f, 0xb2, 0xbb, 0xf8, 0x37, 0xcf, 0x85, + 0xc3, 0xcc, 0x5f, 0xf6, 0x33, 0xa4, 0x7a, 0x51, 0xae, 0x80, 0x04, 0xbe, + 0xbd, 0x40, 0x60, 0x54, 0xf8, 0x3a, 0xd7, 0x00, 0x76, 0x99, 0x8a, 0xea, + 0xb7, 0x6c, 0x07, 0x2e, 0xe2, 0x95, 0x21, 0xeb, 0x9e, 0xce, 0x6c, 0xd9, + 0x97, 0x24, 0x4c, 0x58, 0xef, 0x95, 0xfc, 0x8c, 0x28, 0x6e, 0x6a, 0x0a, + 0xc8, 0x84, 0x0a, 0x2e, 0xc0, 0xae, 0xdd, 0xe7, 0x16, 0x4e, 0xf1, 0x79, + 0xfb, 0x5a, 0x18, 0x6a, 0xc4, 0x38, 0xce, 0x3d, 0x15, 0xe3, 0x76, 0xe5, + 0x37, 0x23, 0xe7, 0xd8, 0x0c, 0xd0, 0xad, 0x93, 0x81, 0x64, 0xea, 0x11, + 0xc2, 0x53, 0x50, 0xde, 0x7f, 0xec, 0x36, 0x5a, 0xee, 0xf5, 0x14, 0xb9, + 0x4c, 0x7f, 0x3c, 0x40, 0x1e, 0x92, 0x4d, 0x1a, 0xe6, 0x4f, 0x80, 0x2a, + 0x73, 0xa4, 0xdf, 0x10, 0xc6, 0x51, 0x4a, 0x2f, 0x3b, 0xa1, 0x9d, 0x5b, + 0x47, 0x0c, 0x22, 0x94, 0xf1, 0x79, 0xe1, 0xc2, 0xed, 0x8e, 0x26, 0x96, + 0x98, 0xb5, 0xf1, 0xcd, 0xbc, 0xf5, 0x76, 0xcf, 0x52, 0x94, 0xca, 0x69, + 0x37, 0x4c, 0xb6, 0x10, 0x55, 0x6d, 0x1a, 0x6c, 0xd5, 0x55, 0x85, 0x06, + 0xa7, 0x7b, 0x60, 0x95, 0xe2, 0xa4, 0x2c, 0x4a, 0xe8, 0x1f, 0xaf, 0x78, + 0x62, 0x63, 0x78, 0x1c, 0xe5, 0x84, 0x63, 0xcf, 0x1e, 0xc2, 0xe7, 0x01, + 0xba, 0xba, 0x02, 0x60, 0xa0, 0x8b, 0xec, 0x6f, 0x88, 0x5f, 0x13, 0x45, + 0x61, 0xb2, 0x74, 0x06, 0xcf, 0x82, 0xb6, 0x63, 0x62, 0x1f, 0x99, 0x7c, + 0x66, 0x4e, 0xfb, 0x3c, 0x3b, 0xe8, 0x08, 0x18, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xe8, 0xe5, 0xfc, 0x04, 0xca, 0x9f, 0xcc, 0xf0, + 0x1b, 0x3b, 0x85, 0xd3, 0xad, 0x2a, 0x60, 0x11, 0x81, 0x8a, 0x33, 0x50, + 0x96, 0x2c, 0xc9, 0x66, 0x52, 0x17, 0xbe, 0x8c, 0xb6, 0x8d, 0x3b, 0x0a, + 0x7c, 0x09, 0x7f, 0x94, 0x01, 0xf5, 0x7f, 0x40, 0xd9, 0x70, 0x7b, 0x71, + 0x4b, 0x6a, 0xbc, 0x4c, 0xab, 0x64, 0x46, 0x43, 0x41, 0x3c, 0x1a, 0x93, + 0x9d, 0xb2, 0xba, 0x27, 0xfb, 0x58, 0x75, 0x04, 0x73, 0x8d, 0x19, 0x34, + 0xbc, 0xa8, 0xf2, 0xf6, 0x93, 0xd9, 0x53, 0xba, 0x1f, 0xb9, 0x76, 0xca, + 0x0b, 0xdb, 0xfc, 0x4b, 0xc7, 0x38, 0x13, 0x70, 0xf6, 0x3f, 0xfd, 0x12, + 0x26, 0x02, 0x78, 0x0f, 0xd2, 0x26, 0x15, 0x59, 0x49, 0xd1, 0x06, 0x1c, + 0x37, 0xf2, 0x92, 0x9d, 0x56, 0xee, 0x11, 0x8a, 0xc1, 0x54, 0x73, 0x77, + 0x36, 0x96, 0x3c, 0x9f, 0x3d, 0x46, 0x1a, 0xff, 0x27, 0x53, 0x67, 0x25, + 0x8a, 0x5a, 0xfa, 0xc3, 0xa7, 0xf9, 0xc7, 0xe3, 0x92, 0xef, 0x77, 0x68, + 0x2c, 0x05, 0x0f, 0xc3, 0xb7, 0xdd, 0xac, 0x30, 0x48, 0xd4, 0xb4, 0xf5, + 0xde, 0xed, 0x5f, 0x13, 0xe5, 0xf4, 0x37, 0x20, 0x46, 0x2c, 0x99, 0xc6, + 0xc4, 0xb0, 0xfe, 0x72, 0x40, 0x2f, 0xf4, 0xab, 0x7d, 0x6b, 0x16, 0x0e, + 0xf5, 0x87, 0x16, 0x82, 0xec, 0x26, 0xf7, 0x37, 0x2d, 0xa9, 0xab, 0x04, + 0x24, 0xfe, 0x71, 0x23, 0x22, 0x59, 0x68, 0x8e, 0x7e, 0x1a, 0x67, 0x30, + 0xcf, 0x96, 0x7b, 0xf6, 0xf1, 0x64, 0xab, 0xe1, 0x44, 0xd0, 0xb4, 0xf0, + 0xa3, 0xdb, 0x16, 0xd7, 0xfc, 0x7f, 0xc6, 0x6e, 0xd4, 0xeb, 0xc7, 0x13, + 0xf9, 0x1c, 0x2f, 0xdf, 0x80, 0xbe, 0x93, 0xb7, 0x84, 0x70, 0x3e, 0xbf, + 0x4c, 0x0e, 0xb4, 0x79, 0x66, 0x88, 0x93, 0x71, 0xb3, 0x57, 0xe1, 0x8d, + 0xa5, 0x97, 0x69, 0xf5, 0x1e, 0x3f, 0xc3, 0x28, 0x65, 0xe4, 0x45, 0x2e, + 0xd4, 0x40, 0x0e, 0xa1, 0x05, 0xc0, 0x1e, 0x77, 0xb5, 0x72, 0x68, 0xaf, + 0x6c, 0x9b, 0x3c, 0xca, 0xa3, 0x51, 0x22, 0x9e, 0xb8, 0xc7, 0x43, 0xba, + 0x1a, 0x97, 0x4b, 0x27, 0x87, 0x31, 0xa3, 0xd5, 0xea, 0x2f, 0x19, 0x02, + 0xe2, 0x2e, 0x8d, 0x82, 0x7b, 0xdc, 0x74, 0xf4, 0xef, 0x6e, 0x3d, 0xc8, + 0x75, 0xfc, 0x3e, 0xd8, 0x7d, 0xed, 0x6f, 0x96, 0x84, 0xd2, 0x7b, 0x03, + 0x91, 0x72, 0xcf, 0x60, 0x30, 0x10, 0xa6, 0x45, 0x57, 0x99, 0x5f, 0x28, + 0xb6, 0x80, 0x66, 0xeb, 0xd7, 0x98, 0x26, 0x8c, 0xd1, 0x9f, 0x66, 0xc5, + 0xbb, 0x62, 0xeb, 0xf1, 0xde, 0x2f, 0x2a, 0x2d, 0x20, 0xa1, 0x92, 0x7f, + 0xd6, 0x9e, 0x3b, 0x3b, 0x8e, 0xe8, 0x60, 0x8a, 0xff, 0x84, 0x68, 0x1b, + 0xd3, 0xba, 0xc3, 0x7a, 0xa6, 0x09, 0x61, 0x9d, 0x85, 0xfa, 0x79, 0x87, + 0xdd, 0xa6, 0xed, 0x2d, 0xe2, 0x0c, 0x7c, 0x63, 0x5e, 0xf5, 0x76, 0x63, + 0xde, 0x22, 0x04, 0xb6, 0x5e, 0xea, 0x79, 0x4d, 0xaf, 0x02, 0x77, 0x32, + 0x5b, 0x45, 0x83, 0x9d, 0x17, 0xcd, 0x36, 0xdd, 0x6d, 0x2a, 0x15, 0x2b, + 0x50, 0xd0, 0xba, 0xc3, 0x16, 0x69, 0x62, 0x97, 0x51, 0x0f, 0xcc, 0x79, + 0x93, 0x7f, 0xec, 0x2d, 0x25, 0x25, 0x98, 0x80, 0x7d, 0x2c, 0xf2, 0x11, + 0xf5, 0xe3, 0xf8, 0xd6, 0x3c, 0x45, 0x18, 0x0f, 0x59, 0x70, 0x17, 0xdf, + 0x13, 0x42, 0xc7, 0xfc, 0xc0, 0x8b, 0x26, 0x5d, 0x33, 0x80, 0x56, 0xf6, + 0xbe, 0x19, 0x30, 0x92, 0xe4, 0x9c, 0xa2, 0xa4, 0x21, 0x4c, 0x37, 0xe0, + 0x95, 0x4b, 0x57, 0x13, 0x9c, 0x4d, 0x62, 0x73, 0x33, 0x23, 0x8d, 0x74, + 0xd2, 0x3b, 0x8c, 0x2d, 0xa0, 0x6f, 0x2b, 0x00, 0x0e, 0xed, 0xe0, 0xed, + 0xb2, 0x27, 0x62, 0x7f, 0x79, 0x0a, 0x70, 0x0b, 0x9d, 0x86, 0x0a, 0x18, + 0xcc, 0x22, 0xd4, 0x9c, 0xaf, 0xdf, 0x3e, 0x16, 0xd2, 0xa8, 0x80, 0xd2, + 0xee, 0x4e, 0xe8, 0x50, 0x41, 0x8e, 0xb4, 0x09, 0xa1, 0xf0, 0x74, 0x17, + 0xea, 0x85, 0xd5, 0x19, 0x10, 0x07, 0xc5, 0x27, 0xa8, 0x71, 0x54, 0xa3, + 0xb5, 0x2b, 0x03, 0x4e, 0x4b, 0xdc, 0x34, 0xf8, 0x50, 0x7a, 0xa9, 0xd4, + 0x8c, 0x8d, 0x20, 0x43, 0x1b, 0x73, 0x17, 0x9e, 0x34, 0xed, 0xda, 0x95, + 0xa9, 0x8d, 0x05, 0x25, 0x96, 0x64, 0x29, 0x88, 0x6b, 0x58, 0xf4, 0x08, + 0xbc, 0xc3, 0xd8, 0x21, 0x7b, 0xa5, 0xc5, 0x6e, 0xb1, 0x4d, 0xd9, 0x7a, + 0x2a, 0x5b, 0x8a, 0x27, 0xca, 0x2e, 0x7a, 0xe7, 0xf7, 0x2f, 0x2e, 0x23, + 0x90, 0xcc, 0xf2, 0x32, 0xa8, 0x02, 0x86, 0xa9, 0xaf, 0x28, 0x62, 0x26, + 0x86, 0x9b, 0xad, 0xdb, 0xe3, 0x88, 0x55, 0x22, 0xef, 0x44, 0xe2, 0x47, + 0x87, 0x02, 0xf3, 0xb1, 0xff, 0x2d, 0x34, 0x08, 0xde, 0xfe, 0x8c, 0x81, + 0x73, 0xd5, 0xf5, 0x6a, 0x91, 0x7f, 0xcb, 0x4f, 0xff, 0x04, 0x64, 0x7b, + 0x76, 0x79, 0x40, 0xd5, 0x33, 0xa1, 0xc0, 0xf3, 0x06, 0x27, 0xf1, 0xb0, + 0x89, 0x13, 0x14, 0x07, 0x38, 0x17, 0x73, 0xf6, 0x08, 0xa0, 0x88, 0x96, + 0xe1, 0x4c, 0x13, 0x71, 0x35, 0xd3, 0xee, 0xb1, 0x00, 0x34, 0xdd, 0x46, + 0x5a, 0x7b, 0x76, 0xec, 0x7e, 0x9d, 0x96, 0x65, 0xa7, 0x2f, 0xec, 0x07, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0x81, 0xdd, 0x5b, 0x13, + 0xd7, 0xb2, 0xbb, 0x4d, 0x46, 0x4e, 0x67, 0x67, 0xda, 0xbe, 0x49, 0x33, + 0xe5, 0x11, 0x91, 0x70, 0x21, 0x9b, 0x60, 0x3a, 0x52, 0x9c, 0xfc, 0x8d, + 0xe1, 0x13, 0xb8, 0x2e, 0x20, 0x74, 0x7c, 0x98, 0x02, 0x18, 0xd2, 0x21, + 0x0b, 0xc2, 0x04, 0xdd, 0x29, 0xf0, 0x02, 0xfd, 0x9d, 0xfd, 0xa2, 0x9f, + 0xf9, 0xc6, 0xcc, 0x61, 0x08, 0xa5, 0x84, 0x10, 0x20, 0x4b, 0x20, 0x19, + 0xbb, 0x88, 0x93, 0x42, 0xbe, 0x75, 0xbd, 0x15, 0x7f, 0x8d, 0x9e, 0x80, + 0x08, 0xc5, 0xaf, 0x6d, 0xed, 0xc2, 0x8e, 0x92, 0xe0, 0xf7, 0x2c, 0x9d, + 0xca, 0x51, 0xa8, 0x0e, 0x36, 0xd1, 0x30, 0x08, 0xeb, 0x66, 0x03, 0xcf, + 0x86, 0x2a, 0xc9, 0xec, 0x91, 0x93, 0x84, 0xaa, 0xfc, 0x6e, 0x44, 0xaa, + 0x8e, 0xe3, 0x23, 0x0a, 0xaf, 0xfb, 0x40, 0xe3, 0xbe, 0x0c, 0xd8, 0x28, + 0x87, 0x12, 0x04, 0x00, 0x4f, 0x07, 0x48, 0x95, 0x95, 0xcd, 0xc6, 0x2d, + 0x83, 0xb4, 0x2f, 0x74, 0x34, 0x09, 0x79, 0x3f, 0xc2, 0xa5, 0xe7, 0xa1, + 0x63, 0xf3, 0xff, 0x8e, 0xc7, 0x05, 0xfe, 0x1b, 0x32, 0xce, 0x32, 0x2d, + 0x43, 0xc9, 0x3e, 0x0a, 0x68, 0xf7, 0xe4, 0x85, 0x46, 0x1a, 0xb9, 0x00, + 0xbf, 0xaa, 0xb7, 0x87, 0x3e, 0xd2, 0x38, 0x46, 0x55, 0xf1, 0x59, 0x03, + 0x16, 0x70, 0xb4, 0xf5, 0x73, 0x48, 0x40, 0x29, 0x5c, 0x56, 0xf4, 0x11, + 0xd4, 0xbf, 0x6f, 0x13, 0xd8, 0x57, 0x0b, 0xd3, 0xbf, 0xf6, 0x11, 0xca, + 0x64, 0x76, 0x4d, 0xe3, 0xe5, 0x6e, 0x25, 0x60, 0xe8, 0xff, 0x1e, 0xaf, + 0x92, 0x6d, 0x68, 0x11, 0x89, 0x72, 0x87, 0xf5, 0x7f, 0x55, 0xb4, 0x55, + 0x23, 0x41, 0xb8, 0xd9, 0xa1, 0xdf, 0x97, 0xfe, 0x9d, 0x06, 0xaa, 0x34, + 0xf0, 0x77, 0xa5, 0x78, 0x54, 0xfc, 0x85, 0x1c, 0x1d, 0xce, 0x44, 0x28, + 0xe0, 0x8f, 0xb8, 0x35, 0x20, 0x22, 0x7c, 0x04, 0xeb, 0x99, 0xa7, 0x65, + 0x3a, 0xa8, 0x1c, 0xa3, 0x80, 0xb7, 0x2f, 0x5b, 0x4b, 0x4a, 0x5d, 0xa5, + 0x9b, 0x05, 0x4c, 0x35, 0xdf, 0x18, 0xfc, 0x1b, 0xb0, 0x9c, 0xdf, 0xb3, + 0x46, 0x1b, 0xe1, 0xf2, 0xb8, 0xb8, 0xe6, 0x8c, 0x6a, 0x83, 0x62, 0x82, + 0x9f, 0x1c, 0xd9, 0x52, 0x7f, 0xda, 0x98, 0x47, 0xed, 0x88, 0x5c, 0x28, + 0xcf, 0x0d, 0x8a, 0x29, 0x32, 0x44, 0xb8, 0xa3, 0x49, 0x7c, 0x01, 0xd3, + 0xe2, 0x35, 0x13, 0xdf, 0xdf, 0xe9, 0xd1, 0x9b, 0xc0, 0x27, 0xe2, 0xa7, + 0x7a, 0x83, 0xfc, 0x83, 0xc3, 0x9b, 0xcd, 0xa0, 0x0e, 0xc6, 0xde, 0x29, + 0xe8, 0x46, 0x69, 0x23, 0x41, 0x5d, 0x02, 0x03, 0xa3, 0x2c, 0x58, 0x09, + 0xa7, 0x92, 0x29, 0x70, 0xa3, 0xd5, 0xe8, 0xaf, 0x81, 0x1c, 0x3c, 0xfc, + 0xb8, 0x1a, 0x8f, 0x48, 0xa7, 0x25, 0x85, 0x0a, 0xbd, 0xa0, 0x77, 0x21, + 0x7f, 0x57, 0xc2, 0xb9, 0x7f, 0x10, 0x8b, 0x6b, 0xe5, 0x03, 0xa4, 0x97, + 0x51, 0xe3, 0xa0, 0x26, 0x2f, 0x12, 0x0b, 0xff, 0x13, 0xad, 0xcb, 0x66, + 0xf7, 0xd6, 0xfe, 0x10, 0x8b, 0xdb, 0xa8, 0x32, 0xcb, 0xa5, 0x20, 0x4c, + 0x08, 0xfb, 0x8c, 0x1b, 0x49, 0xaa, 0x4d, 0xee, 0x56, 0xc8, 0x02, 0x75, + 0x34, 0x7c, 0x21, 0x5b, 0x35, 0x31, 0x31, 0x80, 0x1a, 0x8a, 0xf9, 0x23, + 0x4a, 0xd5, 0x20, 0x03, 0x35, 0xf6, 0x88, 0xcd, 0x9d, 0x11, 0x2f, 0xd9, + 0xba, 0x96, 0x7f, 0x49, 0x4f, 0x8a, 0x3f, 0xba, 0x40, 0x0b, 0x2f, 0xe2, + 0xff, 0xbb, 0x8f, 0x84, 0x49, 0xc2, 0x98, 0x21, 0x3b, 0x57, 0x40, 0x59, + 0xb0, 0xbc, 0xd3, 0xec, 0x9a, 0x86, 0xd2, 0xe8, 0xfe, 0x7b, 0x53, 0x39, + 0xa5, 0x6b, 0x05, 0xa0, 0xfb, 0x8e, 0x54, 0x7c, 0xe2, 0xfd, 0x9f, 0x53, + 0x70, 0x2b, 0x35, 0x1d, 0x2b, 0x77, 0x2b, 0xb9, 0xd6, 0x4e, 0x3b, 0x2f, + 0x9e, 0x61, 0x98, 0x3a, 0x88, 0x98, 0x09, 0xac, 0x71, 0x40, 0xac, 0xa5, + 0xd6, 0xed, 0xbe, 0x9e, 0x7e, 0xac, 0xda, 0x09, 0x43, 0x6c, 0x75, 0x2b, + 0xdf, 0x10, 0x78, 0x09, 0xa4, 0xb8, 0xef, 0x8a, 0x0b, 0x2a, 0x85, 0x74, + 0xcc, 0x6b, 0x71, 0x1f, 0xbe, 0x6e, 0x29, 0x53, 0x40, 0xd1, 0x4e, 0x42, + 0xd1, 0x34, 0x93, 0x72, 0x99, 0x77, 0x4b, 0x04, 0x27, 0x1b, 0xa2, 0x0c, + 0x88, 0xb7, 0x74, 0xf8, 0x31, 0x07, 0xac, 0x9e, 0x5a, 0x15, 0xca, 0x7b, + 0x59, 0xe9, 0xe2, 0x17, 0x55, 0x3e, 0xf3, 0x05, 0xf9, 0x4b, 0x5a, 0x02, + 0x92, 0x9d, 0x2d, 0x03, 0xe6, 0xaf, 0x14, 0xb5, 0x8e, 0x6d, 0x24, 0x15, + 0x86, 0xa6, 0x94, 0xea, 0xc8, 0x11, 0x95, 0xd8, 0xdc, 0xb4, 0xca, 0xed, + 0xaa, 0x0b, 0x49, 0x3c, 0x88, 0xda, 0x49, 0x69, 0x89, 0xd9, 0x9a, 0x24, + 0x69, 0xa1, 0x7c, 0xe3, 0x55, 0xdb, 0x2d, 0x37, 0x5d, 0x18, 0xb0, 0x3e, + 0x5a, 0xda, 0x50, 0xb5, 0xfb, 0xa4, 0xea, 0xa0, 0x42, 0x6c, 0x5e, 0xbd, + 0xf7, 0xa9, 0x5e, 0x46, 0x01, 0x0f, 0x09, 0x10, 0xb4, 0x34, 0x4b, 0xb2, + 0xb4, 0x22, 0x85, 0xb9, 0x69, 0x67, 0x44, 0x9b, 0x8b, 0x0b, 0x46, 0x55, + 0x60, 0x1b, 0x49, 0xd3, 0xde, 0xa1, 0xe5, 0x9e, 0x45, 0x71, 0x97, 0x43, + 0x64, 0x0b, 0xce, 0x1a, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xdf, 0xed, 0xe8, 0xa6, 0x51, 0x0e, 0x8c, 0x88, 0x45, 0xf7, 0x9a, 0x50, + 0xe3, 0x19, 0x20, 0x94, 0xdd, 0xe9, 0x7b, 0xe7, 0x9c, 0x80, 0xc6, 0x01, + 0xcd, 0x68, 0xdf, 0x7b, 0x12, 0xa7, 0x37, 0x1f, 0xa9, 0xba, 0xc4, 0x86, + 0x63, 0xce, 0x90, 0x5b, 0x60, 0x41, 0x4e, 0x20, 0x2e, 0x14, 0x4a, 0x4c, + 0xf7, 0x18, 0x4c, 0x64, 0x8f, 0xcf, 0x11, 0xdd, 0x07, 0x32, 0xb9, 0x11, + 0xf8, 0x45, 0x98, 0x29, 0x5c, 0xf4, 0x3d, 0xdf, 0x96, 0xf9, 0x46, 0x84, + 0xd5, 0x45, 0x55, 0x04, 0xee, 0xeb, 0x23, 0x7c, 0x77, 0x1e, 0x75, 0x1f, + 0xf7, 0x26, 0x20, 0x9a, 0x74, 0x38, 0xcc, 0x4f, 0x25, 0x4f, 0x34, 0x02, + 0x06, 0x05, 0xfb, 0xde, 0xc2, 0x16, 0x4a, 0xd7, 0x63, 0x4e, 0xa7, 0x81, + 0x50, 0xe2, 0x98, 0x53, 0x55, 0x01, 0x9c, 0x8c, 0x1d, 0xe0, 0x28, 0x23, + 0xd1, 0x60, 0x0f, 0xe9, 0xb4, 0x60, 0x21, 0x0c, 0xe5, 0x88, 0x16, 0x64, + 0x0e, 0xfa, 0xa6, 0xdd, 0x36, 0x67, 0xf9, 0x07, 0x0b, 0x56, 0xcb, 0x42, + 0x7e, 0x37, 0xfe, 0xec, 0x45, 0x3d, 0x6e, 0xc4, 0xcd, 0x16, 0xfb, 0x6e, + 0x76, 0x29, 0x46, 0x09, 0x5a, 0xc8, 0xca, 0x0b, 0x1d, 0xdd, 0x60, 0x2b, + 0x29, 0x44, 0x3f, 0x78, 0x3f, 0x1e, 0xc1, 0xba, 0xee, 0xd7, 0x81, 0x9b, + 0x8a, 0x9e, 0xfa, 0xe7, 0x08, 0x5a, 0xe1, 0x40, 0x56, 0x00, 0x21, 0x11, + 0x0b, 0x77, 0x78, 0x79, 0x2b, 0xa5, 0x36, 0xa7, 0xef, 0x3d, 0xdd, 0xdc, + 0xc6, 0x44, 0xec, 0xea, 0x33, 0x53, 0x01, 0xbd, 0xec, 0xb2, 0x5b, 0x9f, + 0xa8, 0xd5, 0x32, 0x74, 0x1b, 0x69, 0xd2, 0x12, 0xcf, 0xa5, 0xb2, 0x2d, + 0xaa, 0xb8, 0x82, 0x5d, 0xfa, 0x2c, 0xd3, 0xfe, 0xad, 0xb4, 0xb8, 0x59, + 0x57, 0xb9, 0x0b, 0x7a, 0x8d, 0xfd, 0x85, 0xbb, 0x86, 0x58, 0x8d, 0xef, + 0xfc, 0x7e, 0x7e, 0x2c, 0x9d, 0xb4, 0x4e, 0x3a, 0x1f, 0x2a, 0x1d, 0x82, + 0x3e, 0x1c, 0x11, 0x25, 0x25, 0x7c, 0x39, 0x37, 0x2b, 0x2f, 0xf1, 0xc6, + 0xc5, 0xbe, 0x77, 0xa7, 0x9a, 0x9a, 0x13, 0x8c, 0x35, 0x94, 0xdd, 0x2f, + 0x90, 0xcc, 0x7f, 0x7e, 0x7f, 0xf3, 0x8c, 0x5c, 0xa6, 0xc3, 0xc7, 0xa7, + 0xcc, 0x1a, 0x11, 0x3b, 0x6c, 0x73, 0x34, 0x90, 0x4e, 0xff, 0x5c, 0xcd, + 0xe9, 0x7c, 0x15, 0xda, 0xd9, 0x9c, 0x96, 0x09, 0x84, 0x41, 0xf2, 0xfb, + 0x9b, 0x4b, 0x4f, 0xe3, 0x93, 0xa4, 0xfc, 0x7a, 0x2d, 0x17, 0x28, 0xfe, + 0xb2, 0x65, 0x46, 0xae, 0xed, 0xee, 0x4f, 0x51, 0xf3, 0xd2, 0x6b, 0x05, + 0xd7, 0x9c, 0xe7, 0x0a, 0x78, 0x00, 0x9d, 0x1c, 0x1d, 0x80, 0x80, 0xed, + 0x3a, 0x55, 0xe2, 0x8b, 0x38, 0x92, 0xd7, 0xd5, 0xd6, 0x96, 0x94, 0x94, + 0xcf, 0x3c, 0xef, 0xc9, 0x0f, 0x0f, 0x25, 0x5c, 0x8a, 0xe8, 0x31, 0x04, + 0x13, 0x18, 0xcb, 0x81, 0x83, 0xb7, 0x2c, 0x04, 0x8d, 0x1e, 0x9d, 0x00, + 0x78, 0x0d, 0x0d, 0x70, 0x71, 0x34, 0xdf, 0x1b, 0x2f, 0x98, 0x9d, 0xcc, + 0x00, 0x63, 0xe5, 0xaf, 0x28, 0xe8, 0xab, 0x2c, 0x7c, 0xb9, 0x47, 0x74, + 0xee, 0xfc, 0x8e, 0xd0, 0x12, 0xf1, 0xcb, 0x00, 0xba, 0x13, 0x6b, 0x0a, + 0xc9, 0xd7, 0x05, 0x1b, 0xfa, 0x18, 0x22, 0x5a, 0x1f, 0x78, 0xd9, 0xc3, + 0x6e, 0x3e, 0xc8, 0x23, 0x8b, 0x16, 0x76, 0xef, 0x4f, 0x20, 0xf1, 0xde, + 0xcf, 0xda, 0x0a, 0xec, 0x63, 0x9b, 0x4a, 0x50, 0x7b, 0x59, 0xf3, 0x26, + 0xdc, 0xb9, 0x1c, 0xe1, 0x25, 0xa6, 0x55, 0x5d, 0x14, 0xf2, 0x7f, 0x2c, + 0xcb, 0x26, 0x97, 0xce, 0x0c, 0xcc, 0xe2, 0xd1, 0x35, 0x3b, 0x5b, 0x04, + 0x67, 0x63, 0x96, 0x4d, 0x83, 0xa0, 0x9c, 0x62, 0x16, 0xe1, 0x67, 0xb8, + 0x05, 0xef, 0xba, 0x76, 0x6a, 0xd3, 0x72, 0x2f, 0x74, 0x40, 0xce, 0x71, + 0x7e, 0x91, 0xbf, 0x60, 0xc5, 0x57, 0x4b, 0xf7, 0x5e, 0xfb, 0xa1, 0x4b, + 0xd2, 0xd0, 0x3b, 0x2a, 0x3d, 0x10, 0xfd, 0x4e, 0x4c, 0x7e, 0x7e, 0x58, + 0xa3, 0x36, 0x31, 0x1a, 0x9b, 0x63, 0xc3, 0x3e, 0x32, 0x2a, 0x8e, 0x7b, + 0xd5, 0xab, 0x6f, 0x9d, 0x63, 0x56, 0x0b, 0xb9, 0x4c, 0x35, 0x95, 0x04, + 0x98, 0xcb, 0x8d, 0xc4, 0x9d, 0x6a, 0x37, 0x3d, 0xdb, 0xf8, 0x18, 0x05, + 0x4f, 0x4d, 0x21, 0xc6, 0x0b, 0x4a, 0x2a, 0x31, 0xa0, 0x75, 0x6e, 0x33, + 0x2a, 0x68, 0xf0, 0x7e, 0xd8, 0x7a, 0xff, 0xec, 0x60, 0x58, 0xf0, 0x38, + 0xcd, 0xb4, 0xea, 0x3e, 0x6b, 0xe8, 0x6a, 0x1b, 0x48, 0x86, 0x9e, 0x94, + 0x1e, 0x30, 0x01, 0xa3, 0x82, 0x7f, 0xbf, 0x61, 0x5f, 0xa5, 0xec, 0x8f, + 0x58, 0x36, 0xb3, 0x32, 0xe0, 0xe3, 0x6e, 0xb5, 0xd3, 0x77, 0x47, 0x79, + 0xf4, 0x51, 0xca, 0x09, 0x47, 0x89, 0x7d, 0x24, 0xfe, 0xa1, 0x55, 0x07, + 0x2d, 0xb0, 0x88, 0x9d, 0x6a, 0xab, 0xe5, 0x65, 0xa4, 0x4e, 0xf2, 0xcb, + 0x8b, 0x8d, 0xdf, 0x2c, 0xcc, 0xb6, 0xd9, 0x00, 0xaa, 0x73, 0xad, 0x26, + 0xbf, 0x93, 0xb2, 0x3b, 0xce, 0x04, 0xb5, 0xc7, 0x8e, 0x84, 0xbe, 0x67, + 0x69, 0xb8, 0xf3, 0x78, 0x89, 0xe5, 0x8a, 0xda, 0x1a, 0x0e, 0x38, 0x03, + 0x21, 0x2d, 0xa8, 0x4b, 0x49, 0xac, 0x34, 0x18, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xa3, 0xf9, 0xed, 0xb1, 0x09, 0x68, 0x24, 0x7c, + 0x34, 0xab, 0x2e, 0x6e, 0xb8, 0x01, 0xfb, 0xdd, 0x80, 0x5f, 0x28, 0x9f, + 0x7e, 0xd8, 0xb5, 0x20, 0x84, 0x2b, 0x5a, 0x9b, 0x57, 0xf2, 0xb8, 0x03, + 0x6b, 0xd6, 0x86, 0xad, 0xf4, 0x83, 0x68, 0x19, 0x55, 0x31, 0x72, 0x0f, + 0x81, 0xe7, 0x79, 0xb8, 0x6a, 0xd2, 0x0b, 0xe5, 0xa7, 0xaf, 0x88, 0xa0, + 0x23, 0x50, 0x03, 0xa1, 0x27, 0x5b, 0xfe, 0x18, 0x04, 0x73, 0x68, 0x41, + 0xcd, 0xa7, 0xd6, 0x34, 0x7c, 0x0c, 0xc1, 0xaf, 0x92, 0x5d, 0x47, 0xa8, + 0x77, 0x04, 0xe8, 0x60, 0x67, 0x2e, 0x1e, 0xdc, 0x0c, 0xfd, 0x7b, 0xbc, + 0x41, 0x08, 0xa7, 0x1b, 0x47, 0x16, 0x23, 0xe6, 0x48, 0x5d, 0x04, 0xd6, + 0x92, 0x68, 0xcd, 0xc2, 0x66, 0xa6, 0x02, 0xfe, 0x03, 0xe9, 0x03, 0xcd, + 0x65, 0x74, 0x7b, 0xdd, 0xa2, 0x5b, 0x33, 0x7d, 0x72, 0x4e, 0x64, 0x30, + 0x5c, 0xaf, 0x0a, 0x7f, 0x0e, 0x41, 0xd8, 0x73, 0x01, 0xa1, 0x0d, 0xc8, + 0xe6, 0x30, 0xe3, 0x82, 0x3e, 0x87, 0xa4, 0xc6, 0xb4, 0x4c, 0xbb, 0x95, + 0xa2, 0x4b, 0x32, 0x49, 0x49, 0xe5, 0x62, 0x0b, 0x85, 0x37, 0x0a, 0x4a, + 0xd6, 0x62, 0x67, 0x47, 0xb2, 0x2b, 0x11, 0x1c, 0x79, 0x70, 0x3f, 0xae, + 0x2e, 0x21, 0x20, 0x6b, 0xfd, 0x42, 0x56, 0xba, 0x44, 0x1b, 0x16, 0x27, + 0xf4, 0x2b, 0x8a, 0x08, 0x0f, 0xe5, 0x9e, 0x3b, 0xa7, 0xf5, 0x38, 0x67, + 0x76, 0x5e, 0x04, 0xbd, 0x9a, 0xdd, 0x6c, 0x6b, 0x6f, 0x11, 0x8e, 0xcf, + 0x7d, 0x34, 0x5b, 0x6c, 0x80, 0x2b, 0x64, 0xb7, 0x28, 0xd0, 0xcb, 0x2c, + 0x99, 0xd4, 0x45, 0x22, 0x7e, 0x72, 0x5e, 0x93, 0x4f, 0x6f, 0xd7, 0x5e, + 0x34, 0x18, 0x35, 0xb1, 0x39, 0x8e, 0x67, 0x2e, 0x5e, 0x7c, 0x69, 0x27, + 0x62, 0x0f, 0x5d, 0x2e, 0x45, 0x43, 0x58, 0x04, 0xbf, 0x6f, 0xf8, 0xb8, + 0x08, 0x30, 0x08, 0x3b, 0xa8, 0x45, 0xac, 0x81, 0x79, 0x8d, 0x17, 0xbb, + 0x03, 0x75, 0x16, 0x57, 0xc3, 0xf5, 0x63, 0xb5, 0x1f, 0xb8, 0x2f, 0x95, + 0xa8, 0x7a, 0x23, 0x2d, 0x61, 0x10, 0xa6, 0x81, 0x06, 0x9a, 0xf5, 0x99, + 0x70, 0xa6, 0xd9, 0xd1, 0xe4, 0x36, 0x43, 0x24, 0x40, 0xcd, 0xc1, 0x95, + 0x30, 0xfa, 0x48, 0x54, 0x07, 0x7f, 0x2f, 0x0b, 0x95, 0x05, 0x95, 0x2c, + 0x76, 0x52, 0x70, 0x7b, 0xde, 0x24, 0x26, 0xea, 0xe9, 0x3e, 0xaf, 0x50, + 0xdb, 0xad, 0x60, 0xf4, 0x04, 0xd5, 0x04, 0x57, 0xf5, 0x83, 0xde, 0x33, + 0x5c, 0x5a, 0x7e, 0x00, 0x95, 0xd9, 0xc3, 0x03, 0xe2, 0xf4, 0x16, 0xc0, + 0xf1, 0xf1, 0xad, 0xc1, 0x93, 0x5a, 0x6f, 0x9b, 0x62, 0xbf, 0xb0, 0x37, + 0x7b, 0xa6, 0x01, 0xee, 0xcc, 0x86, 0x74, 0x02, 0x6f, 0x4a, 0x7e, 0x10, + 0xc0, 0x78, 0xf0, 0x15, 0xb9, 0x0e, 0x23, 0xc2, 0xdd, 0x75, 0xd3, 0x97, + 0xbd, 0xb2, 0x88, 0xee, 0x98, 0xd5, 0xec, 0x53, 0xa1, 0xac, 0x03, 0x4d, + 0x95, 0xcd, 0x19, 0x1e, 0xe6, 0xbd, 0xbe, 0x42, 0x7c, 0x5e, 0x19, 0x28, + 0x98, 0x21, 0x0c, 0x44, 0x82, 0xab, 0x4e, 0x0c, 0x4e, 0x36, 0xcb, 0x73, + 0xb9, 0x5b, 0xf1, 0xab, 0x62, 0xc6, 0x55, 0x5c, 0x1d, 0x3f, 0x76, 0xd4, + 0x5c, 0x9c, 0x0d, 0x9c, 0x9d, 0xc6, 0xa7, 0x1e, 0x2a, 0xbf, 0xd3, 0x4c, + 0x66, 0x36, 0x3c, 0x32, 0xf7, 0xed, 0x42, 0xbc, 0xdf, 0x89, 0x1c, 0x90, + 0x7f, 0x28, 0xf6, 0xcb, 0x13, 0xce, 0xe3, 0x66, 0x37, 0xda, 0xb0, 0xd3, + 0xf6, 0xe0, 0x02, 0x07, 0xc2, 0x79, 0x65, 0x08, 0xf3, 0xfc, 0x8f, 0x84, + 0x4c, 0x91, 0x88, 0x30, 0x67, 0x3e, 0xff, 0x84, 0x8e, 0xfb, 0xb6, 0x15, + 0x43, 0xfb, 0x7b, 0xe4, 0x98, 0x6a, 0xb8, 0x9d, 0x4e, 0x9f, 0x36, 0x0b, + 0x4b, 0x86, 0x72, 0x14, 0xa8, 0x17, 0xfd, 0xd7, 0x67, 0x4e, 0x0d, 0x1b, + 0x46, 0xee, 0x69, 0x9e, 0xe7, 0x3a, 0xa4, 0x0a, 0x32, 0x6c, 0x8b, 0xc5, + 0xbd, 0x03, 0x44, 0x10, 0x67, 0x65, 0xcb, 0x0b, 0x58, 0x36, 0x94, 0xf9, + 0x61, 0xd8, 0x1b, 0x1f, 0xe6, 0x91, 0x57, 0xf7, 0xaa, 0x10, 0x9e, 0x65, + 0x40, 0xab, 0x6d, 0xe2, 0x1a, 0x77, 0x7a, 0xbd, 0x9d, 0x6e, 0x1b, 0x48, + 0x97, 0x46, 0xba, 0x0e, 0xe5, 0x9d, 0x9d, 0x10, 0x65, 0xc8, 0x7c, 0xbb, + 0x41, 0xec, 0x00, 0xbd, 0x78, 0x53, 0xde, 0xb3, 0xf7, 0x82, 0xe9, 0xc1, + 0xf6, 0xf6, 0x54, 0xc4, 0xed, 0x41, 0xcb, 0x6e, 0x93, 0xde, 0xa4, 0x2c, + 0x89, 0x50, 0x67, 0x41, 0x9f, 0xa7, 0x49, 0x7f, 0x0e, 0xca, 0xc0, 0x05, + 0xdf, 0x84, 0x95, 0x78, 0xae, 0xd2, 0x71, 0x30, 0x26, 0x21, 0x7f, 0xe3, + 0xe5, 0x05, 0xa8, 0xcc, 0x66, 0x7d, 0xa1, 0x0f, 0xcf, 0x93, 0xee, 0x73, + 0x1a, 0x59, 0xab, 0x7b, 0xae, 0x41, 0x24, 0x7b, 0x30, 0x7e, 0xbb, 0xba, + 0x3c, 0x78, 0x88, 0xce, 0x4a, 0xaa, 0x78, 0x16, 0x31, 0xb9, 0x7a, 0x2e, + 0xea, 0x87, 0x2a, 0x0e, 0x5f, 0x60, 0x81, 0xf5, 0x31, 0x3f, 0x29, 0xb0, + 0x39, 0x8b, 0xf2, 0xcd, 0xcc, 0x3b, 0xb3, 0x26, 0xbe, 0x74, 0xfc, 0x00, + 0x66, 0xed, 0xb4, 0x1f, 0x09, 0x85, 0xd7, 0xde, 0xa8, 0x13, 0x3f, 0x1b, + 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, + 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, + 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, 0xbb, 0xb8, 0x1d, 0x33, + 0x33, 0x98, 0x7b, 0x57, 0xdc, 0x55, 0x17, 0xa2, 0x34, 0x15, 0x06, 0x6a, + 0xb1, 0xaa, 0x32, 0xf7, 0x56, 0x6b, 0xc1, 0xf5, 0x57, 0xd1, 0x84, 0x74, + 0x14, 0x85, 0x80, 0x21, 0x18, 0x62, 0xae, 0x6a, 0x56, 0x93, 0xcc, 0x90, + 0x21, 0xca, 0x01, 0x85, 0x14, 0x79, 0xe2, 0x7a, 0x61, 0xc8, 0x95, 0x14, + 0xbf, 0xb4, 0x1d, 0x85, 0xa3, 0x9d, 0x59, 0xd9, 0xbc, 0x92, 0xc7, 0x1d, + 0xc1, 0xce, 0xb7, 0x0f, 0x29, 0x79, 0xc2, 0x08, 0x5c, 0x61, 0xcb, 0x52, + 0x16, 0x6e, 0x2f, 0xca, 0x69, 0xd0, 0x2d, 0xee, 0xd0, 0xc0, 0x9d, 0xac, + 0x73, 0x3b, 0x50, 0x69, 0x10, 0xc2, 0xe9, 0x06, 0xc4, 0x99, 0x74, 0xba, + 0xb2, 0x14, 0xc2, 0x7f, 0xcc, 0x52, 0xdf, 0x6e, 0x88, 0x9d, 0xfd, 0x88, + 0x68, 0x8b, 0xa4, 0xb6, 0x43, 0x03, 0x77, 0xb2, 0xce, 0xed, 0x40, 0xa5, + 0x41, 0x08, 0xa7, 0x1b, 0xae, 0xca, 0xdb, 0xe7, 0x63, 0x2e, 0x3d, 0x18, + 0x81, 0x64, 0xa0, 0x4b, 0x67, 0x90, 0xa1, 0x86, 0x5c, 0xb7, 0xac, 0x8a, + 0x24, 0xf9, 0x90, 0xf7, 0x13, 0x4f, 0x7e, 0x1a, 0xa4, 0x72, 0xb1, 0x05, + 0xc7, 0xe7, 0xf7, 0x17, 0x42, 0xd6, 0x62, 0xcc, 0xad, 0x15, 0x38, 0xee, + 0x41, 0x38, 0x67, 0x96, 0x61, 0x09, 0xff, 0x7b, 0xb6, 0x45, 0x50, 0xb8, + 0x29, 0xa0, 0x31, 0xe1, 0x72, 0x4e, 0x64, 0x30, 0x8e, 0x81, 0x9a, 0xf5, + 0xc1, 0xcf, 0x78, 0x73, 0x42, 0xf3, 0x0c, 0xa1, 0xf0, 0x10, 0x4c, 0x2e, + 0x3f, 0x8a, 0x9e, 0xaf, 0xd1, 0xe7, 0xa0, 0x25, 0xcd, 0x31, 0x29, 0xe4, + 0xd6, 0x6b, 0x13, 0x14, 0x79, 0x14, 0x25, 0x02, 0x7d, 0x46, 0xa8, 0xd7, + 0xcf, 0x6a, 0xca, 0x66, 0x7a, 0xe9, 0x9a, 0x4f, 0xe6, 0x71, 0x43, 0x1d, + 0xab, 0x63, 0xff, 0x2d, 0x74, 0xcd, 0x24, 0x0f, 0x8b, 0x8f, 0x85, 0x17, + 0xc3, 0x62, 0x7c, 0x1f, 0x18, 0xdc, 0x39, 0x21, 0x28, 0xbc, 0x5c, 0x8b, + 0xbf, 0xf7, 0xfc, 0x53, 0x74, 0x1e, 0x12, 0xc6, 0x84, 0x77, 0xe2, 0x53, + 0x55, 0x54, 0x66, 0xdd, 0x00, 0xa2, 0x0a, 0x07, 0xbf, 0xb3, 0x86, 0x01, + 0x92, 0x4a, 0xeb, 0xf8, 0xdd, 0x08, 0x4d, 0x0d, 0x28, 0x2c, 0xaa, 0x42, + 0xda, 0xde, 0xfe, 0x25, 0xf9, 0x9f, 0x46, 0x69, 0x9d, 0xde, 0x4e, 0xb2, + 0x80, 0x2a, 0x2e, 0x22, 0x83, 0xc1, 0xe9, 0x11, 0x70, 0x4b, 0x74, 0xec, + 0x91, 0x67, 0xf7, 0x74, 0xd7, 0xe5, 0xf6, 0xc1, 0x51, 0x5a, 0x53, 0x6c, + 0x99, 0x60, 0x19, 0x13, 0x26, 0x60, 0xf5, 0xb4, 0xfe, 0x71, 0xf3, 0x25, + 0x17, 0xe7, 0x87, 0xfe, 0xaf, 0x75, 0xe9, 0xac, 0xe2, 0x93, 0x82, 0x1f, + 0xfc, 0xa6, 0x29, 0x1d, 0xd7, 0xd6, 0xc1, 0xf5, 0x1c, 0xe3, 0x88, 0x58, + 0xbf, 0x61, 0xd3, 0xcf, 0xec, 0xc1, 0x8f, 0x18, 0x43, 0xe7, 0x75, 0xd4, + 0xff, 0x49, 0x4f, 0x0e, 0x43, 0xd2, 0x4e, 0x7c, 0xf8, 0xf4, 0xf3, 0x36, + 0xbf, 0x3e, 0x7c, 0x08, 0x47, 0x75, 0x8f, 0x4f, 0x58, 0x6a, 0x12, 0xdc, + 0xcd, 0xf9, 0xf1, 0x29, 0xec, 0x57, 0xda, 0x90, 0x29, 0x65, 0xb2, 0x37, + 0x2c, 0xcc, 0x50, 0x9f, 0xdf, 0xe6, 0x27, 0x3a, 0xff, 0xe7, 0xba, 0xd9, + 0xbf, 0x01, 0xe3, 0x61, 0x6c, 0x26, 0x92, 0x05, 0x16, 0x4d, 0x1c, 0x03, + 0x01, 0xd4, 0x49, 0x95, 0xd3, 0xf7, 0xf7, 0x20, 0xe5, 0x1e, 0x5a, 0xdc, + 0xe2, 0xf4, 0x86, 0x5f, 0x19, 0x7f, 0xee, 0xf9, 0x4b, 0xfa, 0x8c, 0x45, + 0x3a, 0xb5, 0xe3, 0xca, 0x68, 0xba, 0x24, 0x07, 0x3b, 0x47, 0xa7, 0x3d, + 0x88, 0x06, 0xbf, 0x47, 0x1e, 0x1a, 0x26, 0xd7, 0x13, 0x79, 0xff, 0xc8, + 0x9a, 0x4d, 0x56, 0xa8, 0x7b, 0x0c, 0x44, 0x51, 0xfc, 0x27, 0x2e, 0x5f, + 0x94, 0xe8, 0x97, 0x01, 0xe4, 0x79, 0xa1, 0x55, 0xce, 0x6e, 0x29, 0xc7, + 0x45, 0xe2, 0xb5, 0x6e, 0x74, 0xef, 0x81, 0x03, 0xb2, 0xb5, 0x84, 0x8d, + 0x68, 0xbd, 0xba, 0xe6, 0x02, 0x59, 0x30, 0x83, 0xe2, 0xda, 0x00, 0x06, + 0x07, 0x60, 0xe3, 0x18, 0x70, 0x06, 0xbd, 0xcd, 0x1e, 0x85, 0xae, 0x76, + 0x88, 0x36, 0xf3, 0xf9, 0x3d, 0x35, 0x07, 0xb8, 0xb3, 0x76, 0xe2, 0xa0, + 0xc2, 0x8d, 0xb9, 0x95, 0x07, 0xc2, 0x2d, 0x0f, 0x8f, 0x80, 0xb6, 0xa9, + 0x36, 0xc0, 0xe5, 0x47, 0x56, 0xfb, 0x9b, 0x5f, 0x7d, 0x64, 0x75, 0x38, + 0x7e, 0x83, 0x7d, 0x34, 0x47, 0xd2, 0x54, 0xc6, 0x77, 0x4e, 0x71, 0x93, + 0x2f, 0x65, 0x4c, 0x2a, 0x1a, 0x28, 0x29, 0x3c, 0x7b, 0x99, 0x38, 0x04, + 0xa8, 0x31, 0xc5, 0xe1, 0x61, 0xdb, 0x70, 0xea, 0x66, 0xcd, 0x62, 0x12, + 0x1b, 0x4e, 0xe5, 0x27, 0x31, 0x25, 0xc2, 0xe0, 0x24, 0xcd, 0x09, 0x0e, + 0x08, 0x36, 0x0d, 0x8d, 0xfd, 0x2b, 0x40, 0xeb, 0xe3, 0x28, 0x73, 0xa7, + 0xed, 0x15, 0xc7, 0x6c, 0x06, 0xde, 0x22, 0xb9, 0x50, 0x61, 0x3e, 0x36, + 0x63, 0xae, 0x77, 0xab, 0xe3, 0x78, 0xd2, 0x20, 0x86, 0xa8, 0x66, 0xf5, + 0x40, 0xda, 0xa0, 0x37, 0x15, 0x8d, 0x67, 0xf4, 0xe7, 0x28, 0x28, 0x4e, + 0x11, 0xc9, 0x77, 0x4c, 0x76, 0x03, 0xe4, 0x37, 0x7c, 0x23, 0x8b, 0x3e, + 0x05, 0xd6, 0xf2, 0x28, 0x33, 0x14, 0x34, 0xda, 0x5e, 0x3a, 0xb8, 0x83, + 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, 0x7c, 0x8f, 0xa0, 0x60, + 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, 0x5a, 0xcb, 0x29, 0x14, + 0xc0, 0x07, 0x4e, 0x2b, 0x84, 0x9d, 0x5c, 0x05, 0x64, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0xce, 0x98, 0x6c, + 0x15, 0x23, 0x7c, 0x41, 0x2e, 0xa5, 0xc7, 0x3f, 0xf2, 0x8b, 0x01, 0x69, + 0x7f, 0x2a, 0x07, 0x91, 0x55, 0x0f, 0xf7, 0xd9, 0x9e, 0x8b, 0x37, 0x35, + 0x95, 0x37, 0xc9, 0x04, 0x40, 0xdb, 0x66, 0x56, 0x84, 0x81, 0x55, 0xb7, + 0xfa, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xd9, 0xdc, 0xc7, 0x2c, 0x8f, 0x8c, 0x03, 0x78, 0x1f, 0x09, 0xbc, 0x93, + 0xd5, 0xb9, 0xee, 0xd9, 0x42, 0x88, 0xa5, 0xa5, 0x14, 0xc4, 0x14, 0x5f, + 0x42, 0x29, 0x91, 0x0e, 0x52, 0xca, 0x90, 0x22, 0x33, 0x67, 0xae, 0xfd, + 0xbf, 0x5d, 0x8e, 0xba, 0x24, 0xb2, 0x38, 0x97, 0xfd, 0xc4, 0xda, 0x77, + 0x0c, 0x29, 0x44, 0x53, 0xdb, 0x6e, 0xea, 0xea, 0xb1, 0xc5, 0x3b, 0x42, + 0x9a, 0x9e, 0x3b, 0x0e, 0x1c, 0xfb, 0x40, 0xfb, 0x41, 0x80, 0x37, 0x05, + 0x50, 0x43, 0xb1, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, + 0x74, 0x59, 0xf1, 0x9a, 0x03, 0x52, 0x4f, 0x55, 0xc1, 0xae, 0x7c, 0xa6, + 0x56, 0x8e, 0xf6, 0x98, 0x8d, 0x67, 0x97, 0x78, 0xa1, 0xdc, 0xb5, 0x68, + 0x8f, 0x39, 0x12, 0xb1, 0xc7, 0x5c, 0x5d, 0x1d, 0xef, 0xeb, 0x39, 0xa7, + 0xfb, 0x32, 0x28, 0xe0, 0x3e, 0x3b, 0x24, 0x9d, 0x0a, 0x1f, 0xc5, 0x21, + 0x22, 0x8f, 0x26, 0xf3, 0x7a, 0x58, 0x14, 0x71, 0x36, 0xd5, 0x0d, 0xdc, + 0x7b, 0x80, 0xcf, 0x20, 0xd4, 0x80, 0x7e, 0xca, 0x47, 0x08, 0x6d, 0x4b, + 0x3e, 0xe6, 0xfa, 0x19, 0x1b, 0xfc, 0x2a, 0x7c, 0xa3, 0x2d, 0x25, 0x5b, + 0x6b, 0x53, 0xa1, 0x13, 0xd9, 0x85, 0xac, 0x16, 0xad, 0xb5, 0xd4, 0x15, + 0x26, 0xa6, 0x9e, 0x48, 0x38, 0xee, 0x4f, 0x9a, 0x0d, 0x21, 0xff, 0x82, + 0x06, 0x2d, 0xf5, 0xd4, 0x0a, 0x33, 0xf1, 0xcf, 0xcf, 0xf4, 0x14, 0x43, + 0xc2, 0x07, 0xe9, 0xcc, 0xf0, 0xf0, 0x49, 0x09, 0x53, 0xa7, 0x28, 0x0e, + 0x0e, 0x23, 0x97, 0x26, 0x82, 0xb0, 0xc6, 0xfb, 0x00, 0x46, 0xba, 0x40, + 0xf9, 0xef, 0xba, 0x9a, 0xae, 0x15, 0xda, 0xc7, 0xa5, 0x8e, 0xa4, 0xf5, + 0x53, 0xe6, 0xc7, 0x03, 0xac, 0x39, 0x42, 0x3d, 0xda, 0x6c, 0x80, 0x9c, + 0xe1, 0xf2, 0x4c, 0xa9, 0x58, 0x19, 0x68, 0x33, 0xb8, 0x98, 0xdc, 0xad, + 0x12, 0xb3, 0x73, 0xba, 0x57, 0xf0, 0x2d, 0x91, 0x34, 0x4f, 0x64, 0x0a, + 0x57, 0xb2, 0xce, 0x1c, 0x5a, 0x17, 0xb3, 0x31, 0x5c, 0x59, 0x77, 0x2d, + 0x88, 0x17, 0xfd, 0x49, 0xb4, 0x69, 0x9e, 0x84, 0xd0, 0x59, 0x9e, 0xe2, + 0x7e, 0x71, 0x49, 0xcd, 0x1d, 0xd8, 0x7f, 0x2d, 0xaf, 0x64, 0x71, 0x2b, + 0xe9, 0x65, 0xd7, 0x3e, 0x3b, 0xba, 0xb3, 0x58, 0x55, 0x34, 0x44, 0xa9, + 0xa7, 0x7f, 0x79, 0x06, 0xf4, 0xa1, 0xbc, 0x70, 0x30, 0xe3, 0xcc, 0xc6, + 0xe8, 0xfb, 0x6c, 0x17, 0x49, 0x4e, 0xd9, 0x9c, 0x53, 0xbb, 0x69, 0x4c, + 0x5b, 0x7b, 0xf5, 0xd8, 0x6f, 0x39, 0x06, 0xfb, 0x62, 0xc5, 0xa6, 0x8b, + 0xe8, 0x6a, 0x0e, 0xba, 0x98, 0x7f, 0xc4, 0x85, 0xb5, 0xe8, 0xda, 0x1c, + 0x84, 0xda, 0x4d, 0xe7, 0xdb, 0x4f, 0x1f, 0xaa, 0xc6, 0x7a, 0xab, 0x9e, + 0xa4, 0x6c, 0xd0, 0x43, 0x01, 0xa6, 0xe4, 0xfc, 0xe7, 0x62, 0x90, 0x1e, + 0x6d, 0x5b, 0x35, 0x52, 0x55, 0xf8, 0x65, 0x1a, 0x9a, 0x04, 0x61, 0x8b, + 0x9a, 0x21, 0xdb, 0x23, 0x98, 0xcc, 0xc3, 0x90, 0x25, 0x45, 0x50, 0x7b, + 0x20, 0xa5, 0x55, 0x48, 0x6c, 0xb6, 0x84, 0x3b, 0x6b, 0x59, 0x56, 0xf7, + 0x19, 0x49, 0x06, 0x2e, 0x8b, 0xf8, 0xfc, 0xb8, 0x09, 0xaa, 0x3d, 0x84, + 0x9a, 0x0f, 0x2c, 0xba, 0x51, 0xc8, 0xd1, 0xe2, 0x19, 0x84, 0x13, 0xd8, + 0x73, 0xf4, 0x3c, 0x7d, 0x64, 0xee, 0x8b, 0xfc, 0x1e, 0xfb, 0x50, 0x08, + 0xe3, 0xf7, 0x68, 0x51, 0x1b, 0x2a, 0xae, 0x0e, 0xc0, 0x6f, 0x4d, 0x55, + 0x04, 0xb2, 0xbc, 0xa1, 0xeb, 0xf3, 0xca, 0x8c, 0xa1, 0xad, 0xfc, 0x90, + 0x4b, 0x7c, 0xdb, 0x6c, 0x02, 0x14, 0x93, 0x0c, 0x8f, 0x6a, 0x0f, 0x13, + 0x0f, 0xe2, 0xf1, 0x1e, 0x84, 0x71, 0xaa, 0xa1, 0xd6, 0x09, 0x0a, 0x35, + 0x20, 0x24, 0xb9, 0x4b, 0x10, 0x45, 0x2d, 0x1f, 0x0d, 0x42, 0xf4, 0xba, + 0x5c, 0xb7, 0x9c, 0x1c, 0x81, 0x3b, 0x79, 0xd1, 0x55, 0xad, 0x75, 0x2d, + 0x26, 0x5d, 0x0e, 0xe0, 0xbe, 0x7a, 0xf9, 0x47, 0x42, 0x7a, 0xaa, 0x7e, + 0x11, 0x65, 0x3e, 0x23, 0xb1, 0xaa, 0xb2, 0xbb, 0x0b, 0x4c, 0xc2, 0x11, + 0xda, 0xc5, 0x3c, 0x60, 0xee, 0xa0, 0x9e, 0xeb, 0x86, 0x5e, 0xb8, 0x17, + 0xd7, 0x41, 0x66, 0x71, 0x65, 0x21, 0x8d, 0xf2, 0x87, 0x4d, 0x34, 0x7b, + 0xcf, 0xf1, 0x3e, 0xe2, 0x20, 0xf5, 0x01, 0x1b, 0x33, 0x14, 0x34, 0xda, + 0x5e, 0x3a, 0xb8, 0x83, 0x65, 0x14, 0xda, 0x40, 0x67, 0xec, 0x75, 0x54, + 0x7c, 0x8f, 0xa0, 0x60, 0x61, 0x72, 0x21, 0x62, 0x11, 0x58, 0x7f, 0x88, + 0x5a, 0xcb, 0x29, 0x14, 0xe3, 0x11, 0xf4, 0xd0, 0x0f, 0x9c, 0x51, 0x3d, + 0xc4, 0x29, 0x76, 0xbe, 0x9f, 0xd3, 0x0a, 0xdf, 0x7b, 0x29, 0x32, 0xf7, + 0x56, 0x6b, 0xc1, 0xf5, 0x57, 0xd1, 0x84, 0x74, 0x14, 0x85, 0x80, 0x21, + 0xf3, 0xf3, 0x60, 0xe5, 0x49, 0xbe, 0xba, 0xf6, 0xf0, 0x3e, 0xed, 0xbf, + 0x50, 0xd9, 0x55, 0x78, 0x2a, 0x0e, 0xad, 0x85, 0x1c, 0x05, 0xfd, 0x9d, + 0xdf, 0x83, 0x12, 0x67, 0xdc, 0x67, 0x98, 0x01, 0x3b, 0x70, 0xec, 0xa5, + 0xc0, 0xa9, 0x7b, 0x87, 0x3c, 0x32, 0x0c, 0xbf, 0x19, 0x09, 0x5c, 0x1c, + 0x28, 0xb8, 0xc9, 0xc9, 0x72, 0x42, 0xd9, 0x05, 0x5b, 0xb2, 0xf0, 0x3b, + 0x31, 0x46, 0xbd, 0x14, 0x1e, 0x60, 0xec, 0xa5, 0xc0, 0xa9, 0x7b, 0x87, + 0x3c, 0x32, 0x0c, 0xbf, 0x19, 0x09, 0x5c, 0x1c, 0x28, 0xb8, 0xc9, 0xc9, + 0x72, 0x42, 0xd9, 0x05, 0x5b, 0xb2, 0xf0, 0x3b, 0x31, 0x46, 0xbd, 0x14, + 0x6a, 0x75, 0x1c, 0x43, 0xe0, 0xca, 0xb8, 0x7d, 0xbc, 0x0d, 0x61, 0x2e, + 0xfb, 0x89, 0xb5, 0xef, 0x18, 0x52, 0x88, 0xa6, 0xb6, 0xdd, 0xd4, 0xd5, + 0x63, 0x8b, 0x77, 0x84, 0x34, 0x3d, 0x77, 0x1c, 0x06, 0x93, 0x93, 0x9e, + 0x33, 0xde, 0x5a, 0xfc, 0x93, 0xaf, 0x01, 0x17, 0xc5, 0xdc, 0x88, 0x7f, + 0xc1, 0xe9, 0xa6, 0x3d, 0x24, 0xc9, 0x87, 0xbc, 0x9f, 0x78, 0xf2, 0xd3, + 0x20, 0x95, 0x8b, 0x2d, 0xb4, 0xe8, 0xe1, 0x72, 0x7d, 0x59, 0x98, 0x4f, + 0x54, 0x35, 0x3d, 0xcb, 0x86, 0x4b, 0xbc, 0x75, 0x3b, 0xc9, 0x5a, 0x8e, + 0x3b, 0xed, 0x3b, 0x47, 0xf3, 0xca, 0x23, 0x05, 0xf7, 0xcd, 0x94, 0x0f, + 0xf3, 0x9c, 0x1b, 0xf8, 0x81, 0xe9, 0x33, 0xb9, 0x74, 0x04, 0xcd, 0x1e, + 0xaa, 0xa9, 0x68, 0x08, 0x4d, 0xc8, 0xed, 0x65, 0xbe, 0x25, 0xd0, 0xa9, + 0xa0, 0xff, 0xa6, 0xf9, 0xb0, 0x7d, 0xcc, 0x15, 0xfb, 0x27, 0x57, 0xf8, + 0xaf, 0x33, 0x8e, 0x0f, 0x78, 0xd2, 0x69, 0x65, 0xa5, 0xe3, 0xc5, 0xcf, + 0xef, 0x2a, 0xbf, 0x20, 0xb9, 0x82, 0xe7, 0x7b, 0xe4, 0x44, 0x8e, 0x3b, + 0x0b, 0x18, 0x1a, 0x1c, 0x5b, 0xbe, 0xbc, 0x5e, 0xf9, 0xd4, 0xa5, 0xe4, + 0x27, 0x77, 0x93, 0x3f, 0xd1, 0x4e, 0x6c, 0xb0, 0x72, 0x0f, 0xbb, 0xea, + 0x1f, 0x31, 0xe9, 0x33, 0x14, 0x95, 0x9b, 0x05, 0x64, 0x3f, 0x1f, 0x23, + 0xb0, 0xb4, 0x0c, 0x45, 0x74, 0x66, 0x3f, 0xb9, 0x86, 0xd7, 0x8b, 0x86, + 0x31, 0x86, 0x43, 0xb7, 0x5d, 0x90, 0x1d, 0x5e, 0x88, 0x59, 0xfe, 0x7b, + 0x6a, 0x47, 0x98, 0x8c, 0xba, 0xbf, 0xea, 0x21, 0x69, 0xc2, 0x9a, 0x16, + 0x15, 0xd0, 0x6c, 0xfc, 0x5a, 0xe2, 0xf2, 0xfd, 0xd4, 0xc4, 0x63, 0x29, + 0xa5, 0x8c, 0xed, 0x9e, 0x1e, 0x8f, 0xac, 0x47, 0x75, 0x6c, 0x06, 0x46, + 0x1b, 0x5c, 0xab, 0x2c, 0x01, 0xc7, 0x86, 0x85, 0x36, 0xb7, 0x62, 0xf8, + 0x6e, 0xb1, 0xeb, 0x88, 0x04, 0x66, 0x53, 0x89, 0x49, 0x7c, 0x9c, 0x1c, + 0x7d, 0xa4, 0x63, 0x35, 0xfc, 0x46, 0x39, 0x43, 0x5a, 0xab, 0x05, 0x26, + 0x37, 0xa9, 0x42, 0x40, 0x1d, 0xb1, 0x66, 0x75, 0x6d, 0xd2, 0x5e, 0xe2, + 0xa2, 0x05, 0x45, 0xc8, 0x0f, 0x1e, 0x67, 0x9a, 0xa5, 0x9c, 0xf7, 0x0c, + 0xe3, 0xcc, 0x6f, 0xcd, 0xc5, 0x18, 0xcf, 0x19, 0x78, 0x4e, 0xc6, 0xd9, + 0xcc, 0x4e, 0xd2, 0x71, 0xef, 0x01, 0xc0, 0xca, 0xf1, 0xcb, 0x38, 0xa5, + 0xb4, 0xc1, 0xd8, 0xa8, 0x36, 0x27, 0xad, 0x77, 0x17, 0xea, 0xab, 0x9e, + 0x20, 0x6c, 0x38, 0x1b, 0x4d, 0xf0, 0xa4, 0xe7, 0x8c, 0xb7, 0x16, 0xff, + 0xe4, 0x6b, 0xc0, 0x45, 0x31, 0x37, 0xe2, 0x5f, 0x70, 0xba, 0x69, 0x0f, + 0x49, 0xf2, 0x21, 0xef, 0x27, 0x9e, 0xfc, 0x34, 0x48, 0xe5, 0x62, 0x0b, + 0xfc, 0x60, 0xcb, 0x21, 0xf9, 0x2e, 0x3b, 0xd5, 0xa1, 0x94, 0x32, 0xc6, + 0xa5, 0xe4, 0xa4, 0xf2, 0x3b, 0x45, 0xc1, 0x96, 0xba, 0x7a, 0xf6, 0x66, + 0x27, 0x50, 0xcb, 0x9b, 0x33, 0x11, 0xb4, 0x2d, 0x8c, 0x78, 0xf8, 0x38, + 0x9a, 0xab, 0xd2, 0x0f, 0x5b, 0x1a, 0xcd, 0x79, 0xba, 0xbd, 0xc3, 0x5d, + 0x9f, 0x5a, 0x80, 0x4a, 0xa9, 0x70, 0x73, 0x4b, 0x69, 0xa3, 0xe4, 0xf7, + 0xa4, 0x14, 0xbc, 0x0c, 0x3b, 0x3e, 0x51, 0xa6, 0xdb, 0x27, 0x15, 0x67, + 0x75, 0x90, 0xe3, 0x83, 0xde, 0x1e, 0x14, 0x3c, 0xa3, 0xac, 0x2d, 0xd4, + 0xe9, 0xc6, 0xcd, 0xb7, 0xb4, 0x41, 0x60, 0x12, 0x31, 0x66, 0x74, 0x1f, + 0x56, 0x2f, 0xaf, 0x03, 0xcf, 0x24, 0x97, 0xa5, 0xf4, 0x20, 0x9d, 0xb0, + 0xad, 0xee, 0x8c, 0x5b, 0x86, 0xfd, 0x12, 0x13, 0xfe, 0xc2, 0x97, 0x23, + 0xa8, 0x84, 0x7b, 0xd7, 0xe6, 0x1c, 0x59, 0x19, 0x6c, 0xae, 0x05, 0xc4, + 0xe9, 0x34, 0xea, 0x3c, 0x4c, 0xe6, 0xed, 0x3e, 0x92, 0x6d, 0xb4, 0xcc, + 0x32, 0x3e, 0xfa, 0x62, 0xe5, 0xeb, 0x1a, 0x71, 0x30, 0x2a, 0x25, 0xad, + 0xd6, 0x1a, 0x33, 0x02, 0x49, 0x2c, 0x7a, 0x4a, 0x71, 0x22, 0x72, 0xc2, + 0xdf, 0x27, 0x20, 0x62, 0xf6, 0x99, 0xd3, 0x44, 0x13, 0x29, 0x59, 0xbd, + 0x04, 0xad, 0x97, 0x95, 0xaa, 0xf7, 0x3b, 0x4b, 0x79, 0x3e, 0x35, 0x04 + }; +} // namespace poseidon_constants +#endif diff --git a/icicle/curves/curve_config.cuh b/icicle/curves/curve_config.cuh index a9945bf31..8115c3b20 100644 --- a/icicle/curves/curve_config.cuh +++ b/icicle/curves/curve_config.cuh @@ -6,6 +6,7 @@ #define BLS12_381 2 #define BLS12_377 3 #define BW6_761 4 +#define GRUMPKIN 5 #include "../primitives/field.cuh" #include "../primitives/projective.cuh" @@ -26,6 +27,9 @@ using namespace bls12_377; #include "bls12_377_params.cuh" #include "bw6_761_params.cuh" using namespace bw6_761; +#elif CURVE_ID == GRUMPKIN +#include "grumpkin_params.cuh" +using namespace grumpkin; #endif /** diff --git a/icicle/curves/grumpkin_params.cuh b/icicle/curves/grumpkin_params.cuh new file mode 100644 index 000000000..4738bf0fa --- /dev/null +++ b/icicle/curves/grumpkin_params.cuh @@ -0,0 +1,22 @@ +#pragma once +#ifndef GRUMPKIN_PARAMS_H +#define GRUMPKIN_PARAMS_H + +#include "../utils/storage.cuh" +#include "bn254_params.cuh" + +namespace grumpkin { + typedef bn254::fq_config fp_config; + typedef bn254::fp_config fq_config; + + // G1 generator + static constexpr storage g1_gen_x = {0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000}; + static constexpr storage g1_gen_y = {0x823f272c, 0x833fc48d, 0xf1181294, 0x2d270d45, + 0x6a45d63, 0xcf135e75, 0x00000002, 0x00000000}; + + static constexpr storage weierstrass_b = {0xeffffff0, 0x43e1f593, 0x79b97091, 0x2833e848, + 0x8181585d, 0xb85045b6, 0xe131a029, 0x30644e72}; +} // namespace grumpkin + +#endif diff --git a/wrappers/rust/Cargo.toml b/wrappers/rust/Cargo.toml index 210ec30d2..9d3e0e1ab 100644 --- a/wrappers/rust/Cargo.toml +++ b/wrappers/rust/Cargo.toml @@ -7,4 +7,5 @@ members = [ "icicle-curves/icicle-bls12-377", "icicle-curves/icicle-bls12-381", "icicle-curves/icicle-bn254", + "icicle-curves/icicle-grumpkin", ] diff --git a/wrappers/rust/icicle-core/tests/grumpkin_constants.bin b/wrappers/rust/icicle-core/tests/grumpkin_constants.bin new file mode 100644 index 0000000000000000000000000000000000000000..684493dcbc2040ed98698c5de9c86a8889cce4a8 GIT binary patch literal 12096 zcmbu_byQr-o-go58+UitMuGK(&N8~Y>OuNFRTjbR{=qP{y!NvTU&8+q?{^9M?0^1;v| z0T);q3ACJ3|3s&Xf%4itDUuu4S%vj!67)%aAywyk#(_cu=4Adq1&DY#gL&+;UszptAu zp*|Xir2YKX1q)5}Vi$+hYh|kQEZp9-$jG4Nxw(VlZ34{I9%=PGtyWPdQTe3YmyKY++I-I*-|B4n0le_r!@B~l3~AB0%vP3 z!rmR26Lj%q7?Gq42#L;#0ee)8rSIVn$WLnxj)Nnh8cKehj7wZX%=j62on%i^BUGs=Y&Y+6qfv;9y?4!`Q7j-b;G#P+Pd`j!z4s0>`xfnt48;_&$Tfx>8 zPf1brjfV&w8`6;eI}hwjB1ESa5$W-E1@@rKS4Kl8(tz*EtGJj?R8xM2m3KlVyLNE4}8!B@87zoS|Ul9iO1(w9Pd;d*YC^|`xmbY)pcfi(Fvphnj$B7LfITZ2U3xe~ zO*(Q+6G8N+fw%xrcXoZ9m^3^GMc7w8^^4nX2C=x%%jIghzP7d#@ruE|Zs)X%mj6Jc zjdnk?qa8oQDJ&18*R+*6HZRYuKg>n&$|6H6OXkKi6NPaT2)Lbub7u02~qRiWwnY7Wxp_=luFM0C_rg%3bZv0}SUVI~D!WCzTt1OgA&a8mSGr7)_8?yUaAD zA6B|l{C?uoo@nRhGlH!~iBn!AIDZ^EDYdFO3K~ApyGrh-sn{C`cw#Op+zLM64Wl3? zlOSqVlop;Iahvh@l!1l6H9a2=>-BZ}df$@>C7wo*!1T!Fjkk%>)X%vSN2FeED>5Il z=PUE4w=z*sVe8#EF<(l{;;*BoasuhyU!f$JNxR9C^)Se-4XQgKZuhRV%mFHIofK(b zHoUqCC7m&85;+~HQaH$fS;60^OSGB9u%gmbyC7@BZ0(QXE=pfWerayYjH@x+jXn|) zCd&)dgQ{}ur1(i}dR0a$}rtjZDpDUr#S~<%1Yde@nlbH4*Uyres8hgm=9W@ zY1iIR%6dSP&Y#%ML7oIcph#LPU~!eecAgwfdbtSkTW!QII}lp}4r1(Dp(T~rbaNM=*@14G<73>*#78az$bLJWfH55lOq8b+spsIawU+Yz z)~VNbEjere0})g6ZX4LP)7liQUXtyERDqXn=H5ZNsxka|y|9AjH<8M8$>?5&1x;&h z&zxI7wQL^Vi@7dW3Tw(PK|xz_fvieJ1G_PKyg*sG{yTJ46oU8da`$(|f0B<|)j&3~g)O8f$5s zAojL_z=#&}8S_U}I6J8HBZXEADD5g$RdAb)te2GE5mCxudk8n>Bh2-+8N|L1UV^|d zN#!V~Ja-Be2hpw+PH^Cr|2S%u@`hXh?O4N#)FEa+xkOE_K!ct3?DG-yHYAHKnGd;? zI;z+Oi@WP%MPJv5#*yZhi|3Zk;H`TQTlnsrR2mCvC?TMpR5=dA4dpBA>%_vmJ@2*@ z7w@z)1c{utv@oklOIW-C!QIP2j;*9$g}&r4p~#tx_Et4s98OZoOEDzLE;jP>Nq`lq zR(n}=YpD?eA-!EcVdx9JNZZ6I=?a!eE!S^;io2A{5vbt0s|U7sykOsB3hK zP+TglOt>AAr!HOAvX!89mqYId9o2ZAh0gt4%fvUrA+USPOf92+y~QkEkItg071NW? zO}27JE?446_3hYQ9C#}C1=^`S|m?}Dw~sedv;;e&T*vl4=gV ztqHpTh>1YXNy5$%;kz|aG8G}xMi@#s#R5knokE=rb6gFh+)wCOb_iB-&6$|^NCvMm z2f`tkRBaVyf||whT~iSC^1QLhcE0_@A!|=?#Q(q7ThLk6|8#Z$j?mTnkN-L@xhE0n z>fRCUrKovDYe-h51NZ;nu5XKtWz*OytXE1kFa2Un?a7(j)FcM=rFQ&8xJU%<8zH#* zIE#l=%syov0B5*9EJw!hoLu&^3_PGDE;K(Qv?S;=Lw7-1zq?>LYU=Hp1!j@UcH`JG zgSK|<5h1wTr)3B6!PVzXbD?iLq;xdBU6H4V5cz!==X7@K6S7)tc2N0}fha6X!K$R_ z$a}iSwQB7y;i4?Bx(DseD~G4PbNskxv{hPg^#ON13>-rWWK=^b;dp8O0LG&{m%*H= z#8^-8a17&3C|@`cxcW%^cE`(!8M){d85yycR&5qNRDIMns7RB1JFA00HlV1QAI~*m z0Gg7V--HucuG8k3dfZJ_E!x7l>3m5yS0O31kN#9_Y^$3RcA{4y1XTC@v`+`$MM?ZI zz9%q5>WNUF!qty1;LI^7B9d|EnB9z41leNc8R|@3d0xQf`B!eEq9afN&c; zet@*osowoQd=y$&dIBsi}Yh?I`>w8w3?LrzG z*XWNfb6uE=NX!Y%IOZWAXq;N8W|elih8b~EaD!=hO4h~G;3zP_`4Bp+d)xOv>MFeO z+%VT)?omW+SxMcp!<7kXpea#sv$PjxU^PK-4zg~vPXQwFenw1u7p&>IK~IM3orsaM@P4fl(t#I>psG>Z=PfbCPV>Va)|n z=wpueTt0m1Y{Upvr3L46othxa3?pjP4%{e?+Zp#zi64=Xc4*HGFem;o zYy6!6mpH3*1+34Bw!NyfU-V>J`GCSes`KnfN~RCQJYqBN{glZq_UW$^ZdamTc83Pm zd9f98a_oz!ZKN+12Pm0)jo3=3F#0vZl>Kg9PFl|B-hgHs;qhIfGJEa!sJIocF-*~4 zsF$qYQ-6km6QRRpxdDLlW!ypx*;E>ysK8v0o3a++40msOEFk!W)P%X%$xy*i%u>?? z$sH%2&Rdsv4J=NXjxNfxu=1l>>g-){?D@j5ZgLP($OFUY?~G62F>@q^*_u`>bUkmZ z2AlhuG=02?`nRl6f`k?Vo1kJ+QiMY#$x+hnED`9N;P>EtGww!^!TCNx%PP*jcL<-a zrx0ndX23Q(34SL|Y^^|kgCx?>K91rTlZ!7b!{-0KI)AD1z_&I~B@l1TBld+Xg`)S_ za1RHzXhLLcId4bPfqHwtQC*f>Q!;X@BGAt9^K+O-&O7LCIe8Yn7jXzU2L>^!pCvAl ziHJtkoazMy=6Q&YaBzs=d~ed*wd*^Fw;%%4*Rj5+P<>VU+@-n#X?CfG8uoiJ1|k~> zw@-}o50)g}EU0*J-DPdmwXuXzL(L4-_vDZKI ztOA+nm=8k&a8Yo};_c3S6tq#hnB>hH53o@aXMbephoK%v{JilEFLkg39E>s1?9Z&9 zVs?MR3_@&+61Q_?UWNl#KlPZc1$F;g6ZN|kA7=^C<2AZHB&Lj{jJw**U%#j>;Zl4@ z-t>1CN2=}h`#hTxw}Y6HEd(lvEB$8q^1T5pd}|i`4aJdrtQuiyypjt?i zF!#Upga=aK`28^DKwCoq=fnK@F~*qSCQUwpGf=%#?|uI%fq^)m(XWa9U~~Oqf7q4b zEJ3}tukU{e$cWx$uvJVH%h2Vm)$fP%Y79o5z))RW){}*okg?0>fY>oyWK6SDGp2Uh8y)o&6JzVpxJehKtZwL$rqc<-x8ZU z*3#`T1x;$7x;lcUxXCDTuBwUV#o^{W;RPSa32_DW2Iou>3(!6d6i}K;o zYjlzXLmuYQbsrKrcWG>}}0ZygI7 zD81=akI4kKrn?Y+qi*I{65JqE2&46(1zZUJKwvJF*d0iu!dZr@Uhkp==R;I%!+bF| zS&&CAfe}M7)W@&9qKs>KoH0-;nz-vOC0pb~#GWJ{;gsBmma!>71F`4|s^trMBow^* zD#MPoVaz(POr(@Q-SdpYC!~D{9U|{F7|5n{pTrT=`Zm5e!90UfcWEOuv7|=RT|`(t zAifIy0P7p18ZStzM91Am0`~nX_Id`BF>0OIjvZ2c_-tR=Zl*YWRg}A9UVvVvP^XJI zT^8(y(GSellY3v%BW_>x1jwilOEkCHOCWXlO6*`aP^~&HZN7A zvLL|`BpB3p;O6|~tVvr6%>0~4%uiNBVUJjBvnQRe{!y!oPPe|Ufv2eEXSDQL&W@NU ztNZq1ask$M5w!MUQx$FDO``WFYkUntMs5z=0OhP`Nh#VVElQRS9rA`n=1{H7>lcR- zWT=+jlJV&g$G2}j-(fP!XKtCn`N|KbL4u%-n$UKyJQ#bL@97J8+Q|gM<#oT9r)c>V ziKct86)hTtq{~GHw<#HI)-~H8S~wien6Vy;4Tl)ze7ln+Q;>raq^` zA7?v0G+hLKqQPKxK-_(RtY-gC53YV`)g+L~@5ltVlEoQ1d>D+h=gcy;$G^2}ejm%9 z^qs*o-+VYHzIj77QTiqCVy(-L*(B*_I5U|4vJ{iS{?LzD|ESVr2Q4M0?8IbSF=J+N z2vS76mZpW#!pTT!f>j_&)X<;XS-(=lrs}Su?fG3n68OGj{kHOR&#KA{Jj*H?IG<4a zEAbrG(-Q2CoBZs zaS>X6gou`Rjf7IEw38n$0tue!J&OHpeK~|4sP_5$w$!xySMkc#wxFR|O>v7|Vz=3> zW**R;qe6GTtueIFDx@O&sHyVI%&>s-8Op2dtSK_c*2e=;6MHq1k-}G-Av*5R4*QkA z_APip{ESZ!_Xrf{4n*+B#ZM@ofA`e$0i-_^KjNE0km(^0L?{zj^dN8 zn1~{s(c9ZBCw7r2V=R{V_4|#Xu^1A^)WQ!1IHVgE5lpKE0aow)Y)p7d8F57(`z;{j z8?l5{UePf}(Mk#jon>E~fOa2UQ;W~io?IsT)kb_ljLTmWK=R@DG`|C1nY(Z`z>Y6d z?$`r?^bmcIDjm5J;r#Sd0`AK!C`}>gbs~7Z9@{v2j3S9cW4xA1^J?f!bBr)rqoVo% znp+c1_Mk56kpcis&*cqT)f~v*o=ZnwhV;}_sqKTACL_s&4Qy`NDIuwp{qj^Tt2n@z z|4zS7U^BnL;v3xWCE#prNv`+F3O-n$BMdC54kTPTPmdXkel6zo4pMk%Vl-dmk37z8 zhGjjJh#nW%kLF*r!(bu(w%#fCj1Ms(B5#fEtGI~(W9}Qs_+VMfrmu-4Xvl#8 znwe_(o{-fZLpyBza(S(!NeOAd_8RZ$lx@TkH_V4+`y)(azV{-AFkK-j1dQ1ADE4W;q`}2O1LgY;fSAsAPUx!WtYcr9_ZTFa#*T< z<3#l}_>l?aGK$8KyGy7h>Nz z^RNY78aqi+A#FBD7yJ=@Y*P4Ww;c(C7uwFlvkc|?VDb_s+Z*&5X#NdfAW2I2E$r6F zYY`f$cEmi3%dx=Qx}7E5KX`xS?@iu1^EO*2FaItmP6*RjxWLutfq0nh<_#oMS_vP@ zy$iWbugg&+BhafNH8=HGu^|*yJarmQllWp2tpU*6BY&|igHZSvg8kPV7HU$w+>L+EtDL zT9bQ{x1meJjtxaaCc9AP!u|lslC_>K->-j+4&K+PBc`Yps~baq(Owtb!DyOM_=$e| z1@b?5f8u0BvLD8 zV=J0eTuR~Y=>(#=S>L~6so_9H-cJ1jMl!egCw-0|ivT@pVH7z6lvp)?BX;m0f%i?; zd`H(e)bB|mu*sHryte)s?owOaTmuE_cKGXY!OrE zANhm196+z#^EDVD((kSCOeTb4kPXg0<$xn>D`eXzOM)QzN`U9H6%vrL1*&w5ZgoSt z`MEnl7(&soA79@Q`2py@7NmkG z{>wS&5inmVHlH=3XqtMZWJpI^>%Aa|N=~Kd?9Tcg?D_!!VCF0C(wo9jj7eAD9IRKX9DaXu$8qXWNbI-AL^2zVofvXV|AIp>@&C2X-1A{Eyd zn1ul+%l~hTe+@Jyk`v}Zd1)*1?64Ymhdh7g{gFSLw+7(XPu6=;tm7|jOYPr6*}WQC zr2m;eyIqVr`*Hd9qF&7#cx2mp%Sp~hxIr#+4PpCWgNb(BUPh?gnWjxmd94lK^3@u%qYM@%?g128^VHEUdrs{>WdO5k%Rf zS7xGvtFauELd)Ow&niSSq9rsw8w6%%B(RpPRjatEXM{h zaR2?wZ1EExP|cQsCeF=7e&wySi=s)L6#V$y8O{>01e5F|oPCzPEQjDf)O5cji zy9&Fo+iv4*G7Gmd-SYlV`O9-4ZE0tDYD>a``tcR{<&*;C{EX56o(ee95&MBYhpwn> z=7+eh?On3cojL4BCS>W&Qq&3M7wi`ae66t!k2Jr7ZKx4#* z#ZU-Fk@AcFgXEZrHBv#An<+x_7Yu~j$l~+6do%F!FDu(;O6Jvwo29NBBk2FZ11x8q z|0q^G^kIG5Nk3k}Kb9!}YyNn8eKgWz#jUZ~m?i4Ra$sf~ZH;+UVgnR>s1L3_jL(c+_n|K2*OQIRRd;vAtw#saWXTMS?P`%8i3uO0Tlis&NukR?NB+D`Oi7+&&oIv zw}MT~k99-c_S9Mf?s;aFz}A98frXHOYAG|N3BxjS(V6*4L+3e z)^<4UBMq-_A4+`*4I>rn^?u1w)LpPuI{gCwd{p>)_>O)I>p_b7?@8lNK-;lZR(36Z z3#{vUW#>@KiofTt@r}#lVV%m8M=-_6QV3pOQBSn0lzyQ4%tbuo3m*ujf%#@xcF@zk0!X{07nhWmWmp6Wa@YlVvpRCZqIGd#AQ#JI^jkdJD9#&6iFY z{&JU5tKtWmM?VH#$+eeZxlE}D1jOHv!0unNcGm(h{v!HoCn1F{6VZ;B}a z1HI7!H!_bGFPNmt2m*M>9ih@JG`wV5OgOEI|6YFRouMav9D2VFdae}xV({m9P7gR8 z+6Ab*%OQ)eV873I`hFt(RrJ>$d2`hA|LgpUNu7k~HJJi7syXgsg$;S-+`7U6@Rzhc zU>ibvAm9ST=A;>aXpixMT!^-Px}-sW98!qbC?XU&qsw7>|a5D>p`07 zZIr_ku>Pz3g*jE)OYp(i%xVE0q0-b+yb6IUeG{1(f5C$E!-j%%`{`6X(azP;Uo{r;GP`WxtPU6aRm=X21=|1y82;SWCi| zzg^V4Vsed)9m!45wR}T$M(DAQh3^Im?Gqj>6Hz}F;3>*Sx+y%B`;ws=<1sgQuJ?i6 w-vYw};P_~oxenr#u{aYAnWro@I%|H@Nqd2YIQo&F6*#$04(|L7xbrjr2cAO$ApigX literal 0 HcmV?d00001 diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/Cargo.toml b/wrappers/rust/icicle-curves/icicle-grumpkin/Cargo.toml new file mode 100644 index 000000000..a1a6db0ae --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "icicle-grumpkin" +version = "1.4.0" +edition = "2021" +authors = [ "Ingonyama" ] +description = "Rust wrapper for the CUDA implementation of Grumpkin elliptic curve by Ingonyama" +homepage = "https://www.ingonyama.com" +repository = "https://github.com/ingonyama-zk/icicle" + +[dependencies] +icicle-core = { path = "../../icicle-core" } +icicle-cuda-runtime = { path = "../../icicle-cuda-runtime" } +ark-grumpkin-test = { git = "https://github.com/ingonyama-zk/ark-grumpkin-test.git", optional = true} + +[build-dependencies] +cmake = "0.1.50" + +[dev-dependencies] +ark-std = "0.4.0" +ark-ff = "0.4.0" +ark-ec = "0.4.0" +ark-poly = "0.4.0" +icicle-core = { path = "../../icicle-core", features = ["arkworks"] } +icicle-grumpkin = { path = ".", features = ["arkworks"] } + +[features] +default = [] +arkworks = ["ark-grumpkin-test", "icicle-core/arkworks"] diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/build.rs b/wrappers/rust/icicle-curves/icicle-grumpkin/build.rs new file mode 100644 index 000000000..ee74306d7 --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/build.rs @@ -0,0 +1,19 @@ +use cmake::Config; + +fn main() { + println!("cargo:rerun-if-env-changed=CXXFLAGS"); + println!("cargo:rerun-if-changed=../../../../icicle"); + + let out_dir = Config::new("../../../../icicle") + .define("BUILD_TESTS", "OFF") //TODO: feature + .define("CURVE", "grumpkin") + .define("CMAKE_BUILD_TYPE", "Release") + .build_target("icicle") + .build(); + + println!("cargo:rustc-link-search={}/build", out_dir.display()); + + println!("cargo:rustc-link-lib=ingo_grumpkin"); + println!("cargo:rustc-link-lib=stdc++"); + println!("cargo:rustc-link-lib=cudart"); +} diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/src/curve.rs b/wrappers/rust/icicle-curves/icicle-grumpkin/src/curve.rs new file mode 100644 index 000000000..4af89147c --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/src/curve.rs @@ -0,0 +1,39 @@ +#[cfg(feature = "arkworks")] +use ark_grumpkin_test::{Fq, Fr, GrumpkinConfig as ArkG1Config}; +use icicle_core::curve::{Affine, Curve, Projective}; +use icicle_core::field::{Field, MontgomeryConvertibleField}; +use icicle_core::traits::{FieldConfig, FieldImpl, GenerateRandom}; +use icicle_core::{impl_curve, impl_field, impl_scalar_field}; +use icicle_cuda_runtime::device_context::DeviceContext; +use icicle_cuda_runtime::error::CudaError; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +pub(crate) const SCALAR_LIMBS: usize = 4; +pub(crate) const BASE_LIMBS: usize = 4; + +impl_scalar_field!("grumpkin", grumpkin_sf, SCALAR_LIMBS, ScalarField, ScalarCfg, Fr); +impl_field!(BASE_LIMBS, BaseField, BaseCfg, Fq); +impl_curve!( + "grumpkin", + grumpkin, + CurveCfg, + ScalarField, + BaseField, + ArkG1Config, + G1Affine, + G1Projective +); + +#[cfg(test)] +mod tests { + use super::ScalarField; + use super::{CurveCfg, BASE_LIMBS}; + use icicle_core::curve::Curve; + use icicle_core::impl_curve_tests; + use icicle_core::impl_field_tests; + use icicle_core::tests::*; + use icicle_core::traits::FieldImpl; + + impl_field_tests!(ScalarField); + impl_curve_tests!(BASE_LIMBS, CurveCfg); +} diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/src/lib.rs b/wrappers/rust/icicle-curves/icicle-grumpkin/src/lib.rs new file mode 100644 index 000000000..05ae4a201 --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/src/lib.rs @@ -0,0 +1,5 @@ +pub mod curve; +pub mod msm; +pub mod poseidon; +pub mod tree; +pub mod vec_ops; diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/src/msm/mod.rs b/wrappers/rust/icicle-curves/icicle-grumpkin/src/msm/mod.rs new file mode 100644 index 000000000..bbc5f0344 --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/src/msm/mod.rs @@ -0,0 +1,21 @@ +use crate::curve::CurveCfg; +use icicle_core::{ + curve::{Affine, Curve, Projective}, + error::IcicleResult, + impl_msm, + msm::{MSMConfig, MSM}, + traits::IcicleResultWrap, +}; +use icicle_cuda_runtime::{error::CudaError, memory::HostOrDeviceSlice}; + +impl_msm!("grumpkin", grumpkin, CurveCfg); + +#[cfg(test)] +pub(crate) mod tests { + use icicle_core::impl_msm_tests; + use icicle_core::msm::tests::*; + + use crate::curve::CurveCfg; + + impl_msm_tests!(CurveCfg); +} diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/src/poseidon/mod.rs b/wrappers/rust/icicle-curves/icicle-grumpkin/src/poseidon/mod.rs new file mode 100644 index 000000000..b93998d0f --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/src/poseidon/mod.rs @@ -0,0 +1,22 @@ +use crate::curve::{ScalarCfg, ScalarField}; + +use icicle_core::error::IcicleResult; +use icicle_core::impl_poseidon; +use icicle_core::poseidon::{Poseidon, PoseidonConfig, PoseidonConstants}; +use icicle_core::traits::IcicleResultWrap; +use icicle_cuda_runtime::device_context::DeviceContext; +use icicle_cuda_runtime::error::CudaError; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +use core::mem::MaybeUninit; + +impl_poseidon!("grumpkin", grumpkin, ScalarField, ScalarCfg); + +#[cfg(test)] +pub(crate) mod tests { + use crate::curve::ScalarField; + use icicle_core::impl_poseidon_tests; + use icicle_core::poseidon::tests::*; + + impl_poseidon_tests!(ScalarField, 32, "grumpkin", 56); +} diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/src/tree/mod.rs b/wrappers/rust/icicle-curves/icicle-grumpkin/src/tree/mod.rs new file mode 100644 index 000000000..63543afb6 --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/src/tree/mod.rs @@ -0,0 +1,21 @@ +use crate::curve::{ScalarCfg, ScalarField}; + +use icicle_core::error::IcicleResult; +use icicle_core::impl_tree_builder; +use icicle_core::poseidon::PoseidonConstants; +use icicle_core::traits::IcicleResultWrap; +use icicle_core::tree::{TreeBuilder, TreeBuilderConfig}; +use icicle_cuda_runtime::device_context::DeviceContext; +use icicle_cuda_runtime::error::CudaError; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +impl_tree_builder!("grumpkin", grumpkin, ScalarField, ScalarCfg); + +#[cfg(test)] +pub(crate) mod tests { + use crate::curve::ScalarField; + use icicle_core::impl_tree_builder_tests; + use icicle_core::tree::tests::*; + + impl_tree_builder_tests!(ScalarField); +} diff --git a/wrappers/rust/icicle-curves/icicle-grumpkin/src/vec_ops/mod.rs b/wrappers/rust/icicle-curves/icicle-grumpkin/src/vec_ops/mod.rs new file mode 100644 index 000000000..c8954d864 --- /dev/null +++ b/wrappers/rust/icicle-curves/icicle-grumpkin/src/vec_ops/mod.rs @@ -0,0 +1,20 @@ +use crate::curve::{ScalarCfg, ScalarField}; + +use icicle_core::error::IcicleResult; +use icicle_core::impl_vec_ops_field; +use icicle_core::traits::IcicleResultWrap; +use icicle_core::vec_ops::{VecOps, VecOpsConfig}; +use icicle_cuda_runtime::device_context::DeviceContext; +use icicle_cuda_runtime::error::CudaError; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +impl_vec_ops_field!("grumpkin", grumpkin, ScalarField, ScalarCfg); + +#[cfg(test)] +pub(crate) mod tests { + use crate::curve::ScalarField; + use icicle_core::impl_vec_add_tests; + use icicle_core::vec_ops::tests::*; + + impl_vec_add_tests!(ScalarField); +} From 275b2f4958a54a4a2e701186072ecfce5294e9bb Mon Sep 17 00:00:00 2001 From: yshekel Date: Thu, 22 Feb 2024 00:02:02 +0200 Subject: [PATCH 17/21] feature: mixed-radix NTT fast twiddles mode (#382) - this mode is allocating additional 4N twiddle-factors to achieve faster computation - enabled by flag for initDomain(). Defaults to false. Co-authored-by: hadaringonyama --- .../c++/polynomial_multiplication/example.cu | 2 +- icicle/appUtils/ntt/kernel_ntt.cu | 300 ++++++++++++++---- icicle/appUtils/ntt/ntt.cu | 72 ++++- icicle/appUtils/ntt/ntt.cuh | 5 +- icicle/appUtils/ntt/ntt_impl.cuh | 10 + icicle/appUtils/ntt/tests/verification.cu | 11 +- icicle/appUtils/ntt/thread_ntt.cu | 125 ++++++-- wrappers/rust/icicle-core/src/ntt/mod.rs | 28 +- wrappers/rust/icicle-core/src/ntt/tests.rs | 13 +- 9 files changed, 456 insertions(+), 110 deletions(-) diff --git a/examples/c++/polynomial_multiplication/example.cu b/examples/c++/polynomial_multiplication/example.cu index bc39f0c24..b9b0bd686 100644 --- a/examples/c++/polynomial_multiplication/example.cu +++ b/examples/c++/polynomial_multiplication/example.cu @@ -56,7 +56,7 @@ int main(int argc, char** argv) CHK_IF_RETURN(cudaEventCreate(&stop)); const test_scalar basic_root = test_scalar::omega(NTT_LOG_SIZE); - ntt::InitDomain(basic_root, ntt_config.ctx); + ntt::InitDomain(basic_root, ntt_config.ctx, true /*=fast_twidddles_mode*/); // (1) cpu allocation auto CpuA = std::make_unique(NTT_SIZE); diff --git a/icicle/appUtils/ntt/kernel_ntt.cu b/icicle/appUtils/ntt/kernel_ntt.cu index 01c8623d3..a45c90b58 100644 --- a/icicle/appUtils/ntt/kernel_ntt.cu +++ b/icicle/appUtils/ntt/kernel_ntt.cu @@ -6,12 +6,12 @@ namespace ntt { - static inline __device__ uint32_t dig_rev(uint32_t num, uint32_t log_size, bool dit) + static inline __device__ uint32_t dig_rev(uint32_t num, uint32_t log_size, bool dit, bool fast_tw) { uint32_t rev_num = 0, temp, dig_len; if (dit) { for (int i = 4; i >= 0; i--) { - dig_len = STAGE_SIZES_DEVICE[log_size][i]; + dig_len = fast_tw ? STAGE_SIZES_DEVICE_FT[log_size][i] : STAGE_SIZES_DEVICE[log_size][i]; temp = num & ((1 << dig_len) - 1); num = num >> dig_len; rev_num = rev_num << dig_len; @@ -19,7 +19,7 @@ namespace ntt { } } else { for (int i = 0; i < 5; i++) { - dig_len = STAGE_SIZES_DEVICE[log_size][i]; + dig_len = fast_tw ? STAGE_SIZES_DEVICE_FT[log_size][i] : STAGE_SIZES_DEVICE[log_size][i]; temp = num & ((1 << dig_len) - 1); num = num >> dig_len; rev_num = rev_num << dig_len; @@ -33,18 +33,18 @@ namespace ntt { enum eRevType { None, RevToMixedRev, MixedRevToRev, NaturalToMixedRev, NaturalToRev, MixedRevToNatural }; - static __device__ uint32_t generalized_rev(uint32_t num, uint32_t log_size, bool dit, eRevType rev_type) + static __device__ uint32_t generalized_rev(uint32_t num, uint32_t log_size, bool dit, bool fast_tw, eRevType rev_type) { switch (rev_type) { case eRevType::RevToMixedRev: // R -> N -> MR - return dig_rev(bit_rev(num, log_size), log_size, dit); + return dig_rev(bit_rev(num, log_size), log_size, dit, fast_tw); case eRevType::MixedRevToRev: // MR -> N -> R - return bit_rev(dig_rev(num, log_size, dit), log_size); + return bit_rev(dig_rev(num, log_size, dit, fast_tw), log_size); case eRevType::NaturalToMixedRev: case eRevType::MixedRevToNatural: - return dig_rev(num, log_size, dit); + return dig_rev(num, log_size, dit, fast_tw); case eRevType::NaturalToRev: return bit_rev(num, log_size); default: @@ -56,7 +56,7 @@ namespace ntt { // Note: the following reorder kernels are fused with normalization for INTT template static __global__ void reorder_digits_inplace_and_normalize_kernel( - E* arr, uint32_t log_size, bool dit, eRevType rev_type, bool is_normalize, S inverse_N) + E* arr, uint32_t log_size, bool dit, bool fast_tw, eRevType rev_type, bool is_normalize, S inverse_N) { // launch N threads (per batch element) // each thread starts from one index and calculates the corresponding group @@ -74,7 +74,7 @@ namespace ntt { uint32_t i = 1; for (; i < MAX_GROUP_SIZE;) { - next_element = generalized_rev(next_element, log_size, dit, rev_type); + next_element = generalized_rev(next_element, log_size, dit, fast_tw, rev_type); if (next_element < idx) return; // not handling this group if (next_element == idx) break; // calculated whole group group[i++] = next_element + size * batch_idx; @@ -91,12 +91,19 @@ namespace ntt { template __launch_bounds__(64) __global__ void reorder_digits_and_normalize_kernel( - E* arr, E* arr_reordered, uint32_t log_size, bool dit, eRevType rev_type, bool is_normalize, S inverse_N) + E* arr, + E* arr_reordered, + uint32_t log_size, + bool dit, + bool fast_tw, + eRevType rev_type, + bool is_normalize, + S inverse_N) { uint32_t tid = blockDim.x * blockIdx.x + threadIdx.x; uint32_t rd = tid; uint32_t wr = - ((tid >> log_size) << log_size) + generalized_rev(tid & ((1 << log_size) - 1), log_size, dit, rev_type); + ((tid >> log_size) << log_size) + generalized_rev(tid & ((1 << log_size) - 1), log_size, dit, fast_tw, rev_type); arr_reordered[wr] = is_normalize ? arr[rd] * inverse_N : arr[rd]; } @@ -116,7 +123,7 @@ namespace ntt { int tid = blockDim.x * blockIdx.x + threadIdx.x; if (tid >= n_elements * batch_size) return; int64_t scalar_id = tid % n_elements; - if (rev_type != eRevType::None) scalar_id = generalized_rev(tid, logn, dit, rev_type); + if (rev_type != eRevType::None) scalar_id = generalized_rev(tid, logn, dit, false, rev_type); out_vec[tid] = *(scalar_vec + ((scalar_id * step) % n_scalars)) * in_vec[tid]; } @@ -136,7 +143,8 @@ namespace ntt { bool strided, uint32_t stage_num, bool inv, - bool dit) + bool dit, + bool fast_tw) { NTTEngine engine; stage_metadata s_meta; @@ -150,14 +158,23 @@ namespace ntt { if (s_meta.ntt_block_id >= nof_ntt_blocks) return; - engine.loadBasicTwiddles(basic_twiddles, inv); + if (fast_tw) + engine.loadBasicTwiddles(basic_twiddles); + else + engine.loadBasicTwiddlesGeneric(basic_twiddles, inv); engine.loadGlobalData(in, data_stride, log_data_stride, log_size, strided, s_meta); if (twiddle_stride && dit) { - engine.loadExternalTwiddlesGeneric64( - external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); + if (fast_tw) + engine.loadExternalTwiddles64(external_twiddles, twiddle_stride, log_data_stride, strided, s_meta); + else + engine.loadExternalTwiddlesGeneric64( + external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); engine.twiddlesExternal(); } - engine.loadInternalTwiddles64(internal_twiddles, strided, inv); + if (fast_tw) + engine.loadInternalTwiddles64(internal_twiddles, strided); + else + engine.loadInternalTwiddlesGeneric64(internal_twiddles, strided, inv); #pragma unroll 1 for (uint32_t phase = 0; phase < 2; phase++) { @@ -171,8 +188,11 @@ namespace ntt { } if (twiddle_stride && !dit) { - engine.loadExternalTwiddlesGeneric64( - external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); + if (fast_tw) + engine.loadExternalTwiddles64(external_twiddles, twiddle_stride, log_data_stride, strided, s_meta); + else + engine.loadExternalTwiddlesGeneric64( + external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); engine.twiddlesExternal(); } engine.storeGlobalData(out, data_stride, log_data_stride, log_size, strided, s_meta); @@ -194,7 +214,8 @@ namespace ntt { bool strided, uint32_t stage_num, bool inv, - bool dit) + bool dit, + bool fast_tw) { NTTEngine engine; stage_metadata s_meta; @@ -209,9 +230,15 @@ namespace ntt { if (s_meta.ntt_block_id >= nof_ntt_blocks) return; - engine.loadBasicTwiddles(basic_twiddles, inv); + if (fast_tw) + engine.loadBasicTwiddles(basic_twiddles); + else + engine.loadBasicTwiddlesGeneric(basic_twiddles, inv); engine.loadGlobalData(in, data_stride, log_data_stride, log_size, strided, s_meta); - engine.loadInternalTwiddles32(internal_twiddles, strided, inv); + if (fast_tw) + engine.loadInternalTwiddles32(internal_twiddles, strided); + else + engine.loadInternalTwiddlesGeneric32(internal_twiddles, strided, inv); engine.ntt8win(); engine.twiddlesInternal(); engine.SharedData32Columns8(shmem, true, false, strided); // store @@ -219,8 +246,11 @@ namespace ntt { engine.SharedData32Rows4_2(shmem, false, false, strided); // load engine.ntt4_2(); if (twiddle_stride) { - engine.loadExternalTwiddlesGeneric32( - external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); + if (fast_tw) + engine.loadExternalTwiddles32(external_twiddles, twiddle_stride, log_data_stride, strided, s_meta); + else + engine.loadExternalTwiddlesGeneric32( + external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); engine.twiddlesExternal(); } engine.storeGlobalData32(out, data_stride, log_data_stride, log_size, strided, s_meta); @@ -242,7 +272,8 @@ namespace ntt { bool strided, uint32_t stage_num, bool inv, - bool dit) + bool dit, + bool fast_tw) { NTTEngine engine; stage_metadata s_meta; @@ -257,14 +288,23 @@ namespace ntt { if (s_meta.ntt_block_id >= nof_ntt_blocks) return; - engine.loadBasicTwiddles(basic_twiddles, inv); + if (fast_tw) + engine.loadBasicTwiddles(basic_twiddles); + else + engine.loadBasicTwiddlesGeneric(basic_twiddles, inv); engine.loadGlobalData32(in, data_stride, log_data_stride, log_size, strided, s_meta); if (twiddle_stride) { - engine.loadExternalTwiddlesGeneric32( - external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); + if (fast_tw) + engine.loadExternalTwiddles32(external_twiddles, twiddle_stride, log_data_stride, strided, s_meta); + else + engine.loadExternalTwiddlesGeneric32( + external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); engine.twiddlesExternal(); } - engine.loadInternalTwiddles32(internal_twiddles, strided, inv); + if (fast_tw) + engine.loadInternalTwiddles32(internal_twiddles, strided); + else + engine.loadInternalTwiddlesGeneric32(internal_twiddles, strided, inv); engine.ntt4_2(); engine.SharedData32Columns4_2(shmem, true, false, strided); // store __syncthreads(); @@ -290,7 +330,8 @@ namespace ntt { bool strided, uint32_t stage_num, bool inv, - bool dit) + bool dit, + bool fast_tw) { NTTEngine engine; stage_metadata s_meta; @@ -305,9 +346,15 @@ namespace ntt { if (s_meta.ntt_block_id >= nof_ntt_blocks) return; - engine.loadBasicTwiddles(basic_twiddles, inv); + if (fast_tw) + engine.loadBasicTwiddles(basic_twiddles); + else + engine.loadBasicTwiddlesGeneric(basic_twiddles, inv); engine.loadGlobalData(in, data_stride, log_data_stride, log_size, strided, s_meta); - engine.loadInternalTwiddles16(internal_twiddles, strided, inv); + if (fast_tw) + engine.loadInternalTwiddles16(internal_twiddles, strided); + else + engine.loadInternalTwiddlesGeneric16(internal_twiddles, strided, inv); engine.ntt8win(); engine.twiddlesInternal(); engine.SharedData16Columns8(shmem, true, false, strided); // store @@ -315,8 +362,11 @@ namespace ntt { engine.SharedData16Rows2_4(shmem, false, false, strided); // load engine.ntt2_4(); if (twiddle_stride) { - engine.loadExternalTwiddlesGeneric16( - external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); + if (fast_tw) + engine.loadExternalTwiddles16(external_twiddles, twiddle_stride, log_data_stride, strided, s_meta); + else + engine.loadExternalTwiddlesGeneric16( + external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); engine.twiddlesExternal(); } engine.storeGlobalData16(out, data_stride, log_data_stride, log_size, strided, s_meta); @@ -338,7 +388,8 @@ namespace ntt { bool strided, uint32_t stage_num, bool inv, - bool dit) + bool dit, + bool fast_tw) { NTTEngine engine; stage_metadata s_meta; @@ -353,14 +404,23 @@ namespace ntt { if (s_meta.ntt_block_id >= nof_ntt_blocks) return; - engine.loadBasicTwiddles(basic_twiddles, inv); + if (fast_tw) + engine.loadBasicTwiddles(basic_twiddles); + else + engine.loadBasicTwiddlesGeneric(basic_twiddles, inv); engine.loadGlobalData16(in, data_stride, log_data_stride, log_size, strided, s_meta); if (twiddle_stride) { - engine.loadExternalTwiddlesGeneric16( - external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); + if (fast_tw) + engine.loadExternalTwiddles16(external_twiddles, twiddle_stride, log_data_stride, strided, s_meta); + else + engine.loadExternalTwiddlesGeneric16( + external_twiddles, twiddle_stride, log_data_stride, s_meta, tw_log_size, inv); engine.twiddlesExternal(); } - engine.loadInternalTwiddles16(internal_twiddles, strided, inv); + if (fast_tw) + engine.loadInternalTwiddles16(internal_twiddles, strided); + else + engine.loadInternalTwiddlesGeneric16(internal_twiddles, strided, inv); engine.ntt2_4(); engine.SharedData16Columns2_4(shmem, true, false, strided); // store __syncthreads(); @@ -388,8 +448,9 @@ namespace ntt { } } + // Generic twiddles: 1N twiddles for forward and inverse NTT template - __global__ void generate_basic_twiddles(S basic_root, S* w6_table, S* basic_twiddles) + __global__ void generate_basic_twiddles_generic(S basic_root, S* w6_table, S* basic_twiddles) { S w0 = basic_root * basic_root; S w1 = (basic_root + w0 * basic_root) * S::inv_log_size(1); @@ -484,7 +545,7 @@ namespace ntt { if (log_size > 2) for (int i = 0; i < 3 - (log_size > 6 ? 0 : 6 - log_size); i++) temp_root = temp_root * temp_root; - generate_basic_twiddles<<<1, 1, 0, stream>>>(temp_root, w6_table, basic_twiddles); + generate_basic_twiddles_generic<<<1, 1, 0, stream>>>(temp_root, w6_table, basic_twiddles); const int NOF_BLOCKS = (log_size >= 8) ? (1 << (log_size - 8)) : 1; const int NOF_THREADS = (log_size >= 8) ? 256 : (1 << log_size); @@ -501,6 +562,100 @@ namespace ntt { return CHK_LAST(); } + // Fast-twiddles: 2N twiddles for forward, 2N for inverse + template + __global__ void generate_basic_twiddles_fast_twiddles_mode(S basic_root, S* basic_twiddles) + { + S w0 = basic_root * basic_root; + S w1 = (basic_root + w0 * basic_root) * S::inv_log_size(1); + S w2 = (basic_root - w0 * basic_root) * S::inv_log_size(1); + basic_twiddles[0] = w0; + basic_twiddles[1] = w1; + basic_twiddles[2] = w2; + } + + template + __global__ void generate_twiddle_combinations_fast_twiddles_mode( + S* w6_table, + S* w12_table, + S* w18_table, + S* w24_table, + S* w30_table, + S* external_twiddles, + uint32_t log_size, + uint32_t prev_log_size) + { + uint32_t tid = blockIdx.x * blockDim.x + threadIdx.x; + uint32_t exp = ((tid & ((1 << prev_log_size) - 1)) * (tid >> prev_log_size)) << (30 - log_size); + S w6, w12, w18, w24, w30; + w6 = w6_table[exp >> 24]; + w12 = w12_table[((exp >> 18) & 0x3f)]; + w18 = w18_table[((exp >> 12) & 0x3f)]; + w24 = w24_table[((exp >> 6) & 0x3f)]; + w30 = w30_table[(exp & 0x3f)]; + S t = w6 * w12 * w18 * w24 * w30; + external_twiddles[tid + (1 << log_size) - 1] = t; + } + + template + cudaError_t generate_external_twiddles_fast_twiddles_mode( + const S& basic_root, + S* external_twiddles, + S*& internal_twiddles, + S*& basic_twiddles, + uint32_t log_size, + cudaStream_t& stream) + { + CHK_INIT_IF_RETURN(); + + S* w6_table; + S* w12_table; + S* w18_table; + S* w24_table; + S* w30_table; + CHK_IF_RETURN(cudaMallocAsync(&w6_table, sizeof(S) * 64, stream)); + CHK_IF_RETURN(cudaMallocAsync(&w12_table, sizeof(S) * 64, stream)); + CHK_IF_RETURN(cudaMallocAsync(&w18_table, sizeof(S) * 64, stream)); + CHK_IF_RETURN(cudaMallocAsync(&w24_table, sizeof(S) * 64, stream)); + CHK_IF_RETURN(cudaMallocAsync(&w30_table, sizeof(S) * 64, stream)); + CHK_IF_RETURN(cudaMallocAsync(&basic_twiddles, 3 * sizeof(S), stream)); + + S temp_root = basic_root; + generate_base_table<<<1, 1, 0, stream>>>(basic_root, w30_table, 1 << (30 - log_size)); + if (log_size > 24) + for (int i = 0; i < 6 - (30 - log_size); i++) + temp_root = temp_root * temp_root; + generate_base_table<<<1, 1, 0, stream>>>(temp_root, w24_table, 1 << (log_size > 24 ? 0 : 24 - log_size)); + if (log_size > 18) + for (int i = 0; i < 6 - (log_size > 24 ? 0 : 24 - log_size); i++) + temp_root = temp_root * temp_root; + generate_base_table<<<1, 1, 0, stream>>>(temp_root, w18_table, 1 << (log_size > 18 ? 0 : 18 - log_size)); + if (log_size > 12) + for (int i = 0; i < 6 - (log_size > 18 ? 0 : 18 - log_size); i++) + temp_root = temp_root * temp_root; + generate_base_table<<<1, 1, 0, stream>>>(temp_root, w12_table, 1 << (log_size > 12 ? 0 : 12 - log_size)); + if (log_size > 6) + for (int i = 0; i < 6 - (log_size > 12 ? 0 : 12 - log_size); i++) + temp_root = temp_root * temp_root; + generate_base_table<<<1, 1, 0, stream>>>(temp_root, w6_table, 1 << (log_size > 6 ? 0 : 6 - log_size)); + for (int i = 0; i < 3 - (log_size > 6 ? 0 : 6 - log_size); i++) + temp_root = temp_root * temp_root; + generate_basic_twiddles_fast_twiddles_mode<<<1, 1, 0, stream>>>(temp_root, basic_twiddles); + + for (int i = 8; i < log_size + 1; i++) { + generate_twiddle_combinations_fast_twiddles_mode<<<1 << (i - 8), 256, 0, stream>>>( + w6_table, w12_table, w18_table, w24_table, w30_table, external_twiddles, i, STAGE_PREV_SIZES[i]); + } + internal_twiddles = w6_table; + + CHK_IF_RETURN(cudaFreeAsync(w12_table, stream)); + CHK_IF_RETURN(cudaFreeAsync(w18_table, stream)); + CHK_IF_RETURN(cudaFreeAsync(w24_table, stream)); + CHK_IF_RETURN(cudaFreeAsync(w30_table, stream)); + + return CHK_LAST(); + } + template cudaError_t large_ntt( E* in, @@ -514,6 +669,7 @@ namespace ntt { bool inv, bool normalize, bool dit, + bool fast_tw, cudaStream_t cuda_stream) { CHK_INIT_IF_RETURN(); @@ -529,11 +685,11 @@ namespace ntt { if (dit) { ntt16dit<<>>( in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, batch_size, 1, 0, 0, - false, 0, inv, dit); + false, 0, inv, dit, fast_tw); } else { // dif ntt16<<>>( in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, batch_size, 1, 0, 0, - false, 0, inv, dit); + false, 0, inv, dit, fast_tw); } if (normalize) normalize_kernel<<>>(out, S::inv_log_size(4)); return CHK_LAST(); @@ -545,11 +701,11 @@ namespace ntt { if (dit) { ntt32dit<<>>( in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, batch_size, 1, 0, 0, - false, 0, inv, dit); + false, 0, inv, dit, fast_tw); } else { // dif ntt32<<>>( in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, batch_size, 1, 0, 0, - false, 0, inv, dit); + false, 0, inv, dit, fast_tw); } if (normalize) normalize_kernel<<>>(out, S::inv_log_size(5)); return CHK_LAST(); @@ -560,7 +716,7 @@ namespace ntt { const int NOF_BLOCKS = (8 * batch_size + NOF_THREADS - 1) / NOF_THREADS; ntt64<<>>( in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, batch_size, 1, 0, 0, - false, 0, inv, dit); + false, 0, inv, dit, fast_tw); if (normalize) normalize_kernel<<>>(out, S::inv_log_size(6)); return CHK_LAST(); } @@ -571,17 +727,17 @@ namespace ntt { if (dit) { ntt16dit<<>>( in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 4) * batch_size, 1, 0, 0, false, 0, inv, dit); + (1 << log_size - 4) * batch_size, 1, 0, 0, false, 0, inv, dit, fast_tw); ntt16dit<<>>( out, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 4) * batch_size, 16, 4, 16, true, 1, inv, dit); + (1 << log_size - 4) * batch_size, 16, 4, 16, true, 1, inv, dit, fast_tw); } else { // dif ntt16<<>>( in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 4) * batch_size, 16, 4, 16, true, 1, inv, dit); + (1 << log_size - 4) * batch_size, 16, 4, 16, true, 1, inv, dit, fast_tw); ntt16<<>>( out, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 4) * batch_size, 1, 0, 0, false, 0, inv, dit); + (1 << log_size - 4) * batch_size, 1, 0, 0, false, 0, inv, dit, fast_tw); } if (normalize) normalize_kernel<<>>(out, S::inv_log_size(8)); return CHK_LAST(); @@ -591,43 +747,49 @@ namespace ntt { uint32_t nof_blocks = (1 << (log_size - 9)) * batch_size; if (dit) { for (int i = 0; i < 5; i++) { - uint32_t stage_size = STAGE_SIZES_HOST[log_size][i]; + uint32_t stage_size = fast_tw ? STAGE_SIZES_HOST_FT[log_size][i] : STAGE_SIZES_HOST[log_size][i]; uint32_t stride_log = 0; for (int j = 0; j < i; j++) - stride_log += STAGE_SIZES_HOST[log_size][j]; + stride_log += fast_tw ? STAGE_SIZES_HOST_FT[log_size][j] : STAGE_SIZES_HOST[log_size][j]; if (stage_size == 6) ntt64<<>>( i ? out : in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 6) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit); + (1 << log_size - 6) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit, + fast_tw); else if (stage_size == 5) ntt32dit<<>>( i ? out : in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 5) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit); + (1 << log_size - 5) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit, + fast_tw); else if (stage_size == 4) ntt16dit<<>>( i ? out : in, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 4) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit); + (1 << log_size - 4) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit, + fast_tw); } } else { // dif bool first_run = false, prev_stage = false; for (int i = 4; i >= 0; i--) { - uint32_t stage_size = STAGE_SIZES_HOST[log_size][i]; + uint32_t stage_size = fast_tw ? STAGE_SIZES_HOST_FT[log_size][i] : STAGE_SIZES_HOST[log_size][i]; uint32_t stride_log = 0; for (int j = 0; j < i; j++) - stride_log += STAGE_SIZES_HOST[log_size][j]; + stride_log += fast_tw ? STAGE_SIZES_HOST_FT[log_size][j] : STAGE_SIZES_HOST[log_size][j]; first_run = stage_size && !prev_stage; if (stage_size == 6) ntt64<<>>( first_run ? in : out, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 6) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit); + (1 << log_size - 6) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit, + fast_tw); else if (stage_size == 5) ntt32<<>>( first_run ? in : out, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 5) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit); + (1 << log_size - 5) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit, + fast_tw); else if (stage_size == 4) ntt16<<>>( first_run ? in : out, out, external_twiddles, internal_twiddles, basic_twiddles, log_size, tw_log_size, - (1 << log_size - 4) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit); + (1 << log_size - 4) * batch_size, 1 << stride_log, stride_log, i ? (1 << stride_log) : 0, i, i, inv, dit, + fast_tw); prev_stage = stage_size; } } @@ -648,6 +810,7 @@ namespace ntt { int max_logn, int batch_size, bool is_inverse, + bool fast_tw, Ordering ordering, S* arbitrary_coset, int coset_gen_index, @@ -706,10 +869,10 @@ namespace ntt { const bool is_reverse_in_place = (d_input == d_output); if (is_reverse_in_place) { reorder_digits_inplace_and_normalize_kernel<<>>( - d_output, logn, dit, reverse_input, is_normalize, S::inv_log_size(logn)); + d_output, logn, dit, fast_tw, reverse_input, is_normalize, S::inv_log_size(logn)); } else { reorder_digits_and_normalize_kernel<<>>( - d_input, d_output, logn, dit, reverse_input, is_normalize, S::inv_log_size(logn)); + d_input, d_output, logn, dit, fast_tw, reverse_input, is_normalize, S::inv_log_size(logn)); } is_normalize = false; d_input = d_output; @@ -718,11 +881,11 @@ namespace ntt { // inplace ntt CHK_IF_RETURN(large_ntt( d_input, d_output, external_twiddles, internal_twiddles, basic_twiddles, logn, max_logn, batch_size, is_inverse, - (is_normalize && reverse_output == eRevType::None), dit, cuda_stream)); + (is_normalize && reverse_output == eRevType::None), dit, fast_tw, cuda_stream)); if (reverse_output != eRevType::None) { reorder_digits_inplace_and_normalize_kernel<<>>( - d_output, logn, dit, reverse_output, is_normalize, S::inv_log_size(logn)); + d_output, logn, dit, fast_tw, reverse_output, is_normalize, S::inv_log_size(logn)); } if (is_on_coset && is_inverse) { @@ -743,6 +906,14 @@ namespace ntt { uint32_t log_size, cudaStream_t& stream); + template cudaError_t generate_external_twiddles_fast_twiddles_mode( + const curve_config::scalar_t& basic_root, + curve_config::scalar_t* external_twiddles, + curve_config::scalar_t*& internal_twiddles, + curve_config::scalar_t*& basic_twiddles, + uint32_t log_size, + cudaStream_t& stream); + template cudaError_t mixed_radix_ntt( curve_config::scalar_t* d_input, curve_config::scalar_t* d_output, @@ -753,6 +924,7 @@ namespace ntt { int max_logn, int batch_size, bool is_inverse, + bool fast_tw, Ordering ordering, curve_config::scalar_t* arbitrary_coset, int coset_gen_index, diff --git a/icicle/appUtils/ntt/ntt.cu b/icicle/appUtils/ntt/ntt.cu index 5cd3b72a3..ed10ff1e9 100644 --- a/icicle/appUtils/ntt/ntt.cu +++ b/icicle/appUtils/ntt/ntt.cu @@ -370,14 +370,23 @@ namespace ntt { int max_size = 0; int max_log_size = 0; S* twiddles = nullptr; + bool initialized = false; // protection for multi-threaded case std::unordered_map coset_index = {}; S* internal_twiddles = nullptr; // required by mixed-radix NTT S* basic_twiddles = nullptr; // required by mixed-radix NTT + // mixed-radix NTT supports a fast-twiddle option at the cost of additional 4N memory (where N is max NTT size) + S* fast_external_twiddles = nullptr; // required by mixed-radix NTT (fast-twiddles mode) + S* fast_internal_twiddles = nullptr; // required by mixed-radix NTT (fast-twiddles mode) + S* fast_basic_twiddles = nullptr; // required by mixed-radix NTT (fast-twiddles mode) + S* fast_external_twiddles_inv = nullptr; // required by mixed-radix NTT (fast-twiddles mode) + S* fast_internal_twiddles_inv = nullptr; // required by mixed-radix NTT (fast-twiddles mode) + S* fast_basic_twiddles_inv = nullptr; // required by mixed-radix NTT (fast-twiddles mode) + public: template - friend cudaError_t InitDomain(U primitive_root, device_context::DeviceContext& ctx); + friend cudaError_t InitDomain(U primitive_root, device_context::DeviceContext& ctx, bool fast_tw); cudaError_t ReleaseDomain(device_context::DeviceContext& ctx); @@ -389,7 +398,7 @@ namespace ntt { static inline Domain domains_for_devices[device_context::MAX_DEVICES] = {}; template - cudaError_t InitDomain(S primitive_root, device_context::DeviceContext& ctx) + cudaError_t InitDomain(S primitive_root, device_context::DeviceContext& ctx, bool fast_twiddles_mode) { CHK_INIT_IF_RETURN(); @@ -399,11 +408,11 @@ namespace ntt { // please note that this offers just basic thread-safety, // it's assumed a singleton (non-enforced) that is supposed // to be initialized once per device per program lifetime - if (!domain.twiddles) { + if (!domain.initialized) { // Mutex is automatically released when lock goes out of scope, even in case of exceptions std::lock_guard lock(Domain::device_domain_mutex); // double check locking - if (domain.twiddles) return CHK_LAST(); // another thread is already initializing the domain + if (domain.initialized) return CHK_LAST(); // another thread is already initializing the domain bool found_logn = false; S omega = primitive_root; @@ -430,6 +439,25 @@ namespace ntt { CHK_IF_RETURN(generate_external_twiddles_generic( primitive_root, domain.twiddles, domain.internal_twiddles, domain.basic_twiddles, domain.max_log_size, ctx.stream)); + + if (fast_twiddles_mode) { + // generating fast-twiddles (note that this cost 4N additional memory) + CHK_IF_RETURN(cudaMallocAsync(&domain.fast_external_twiddles, domain.max_size * sizeof(S) * 2, ctx.stream)); + CHK_IF_RETURN(cudaMallocAsync(&domain.fast_external_twiddles_inv, domain.max_size * sizeof(S) * 2, ctx.stream)); + + // fast-twiddles forward NTT + CHK_IF_RETURN(generate_external_twiddles_fast_twiddles_mode( + primitive_root, domain.fast_external_twiddles, domain.fast_internal_twiddles, domain.fast_basic_twiddles, + domain.max_log_size, ctx.stream)); + + // fast-twiddles inverse NTT + S primitive_root_inv; + CHK_IF_RETURN(cudaMemcpyAsync( + &primitive_root_inv, &domain.twiddles[domain.max_size - 1], sizeof(S), cudaMemcpyDeviceToHost, ctx.stream)); + CHK_IF_RETURN(generate_external_twiddles_fast_twiddles_mode( + primitive_root_inv, domain.fast_external_twiddles_inv, domain.fast_internal_twiddles_inv, + domain.fast_basic_twiddles_inv, domain.max_log_size, ctx.stream)); + } CHK_IF_RETURN(cudaStreamSynchronize(ctx.stream)); const bool is_map_only_powers_of_primitive_root = true; @@ -447,6 +475,7 @@ namespace ntt { domain.coset_index[domain.twiddles[i]] = i; } } + domain.initialized = true; } return CHK_LAST(); @@ -467,6 +496,19 @@ namespace ntt { basic_twiddles = nullptr; coset_index.clear(); + cudaFreeAsync(fast_external_twiddles, ctx.stream); + fast_external_twiddles = nullptr; + cudaFreeAsync(fast_internal_twiddles, ctx.stream); + fast_internal_twiddles = nullptr; + cudaFreeAsync(fast_basic_twiddles, ctx.stream); + fast_basic_twiddles = nullptr; + cudaFreeAsync(fast_external_twiddles_inv, ctx.stream); + fast_external_twiddles_inv = nullptr; + cudaFreeAsync(fast_internal_twiddles_inv, ctx.stream); + fast_internal_twiddles_inv = nullptr; + cudaFreeAsync(fast_basic_twiddles_inv, ctx.stream); + fast_basic_twiddles_inv = nullptr; + return CHK_LAST(); } @@ -607,9 +649,21 @@ namespace ntt { d_input, d_output, domain.twiddles, size, domain.max_size, batch_size, is_inverse, config.ordering, coset, coset_index, stream)); } else { + const bool is_on_coset = (coset_index != 0) || coset; + const bool is_fast_twiddles_enabled = (domain.fast_external_twiddles != nullptr) && !is_on_coset; + S* twiddles = is_fast_twiddles_enabled + ? (is_inverse ? domain.fast_external_twiddles_inv : domain.fast_external_twiddles) + : domain.twiddles; + S* internal_twiddles = is_fast_twiddles_enabled + ? (is_inverse ? domain.fast_internal_twiddles_inv : domain.fast_internal_twiddles) + : domain.internal_twiddles; + S* basic_twiddles = is_fast_twiddles_enabled + ? (is_inverse ? domain.fast_basic_twiddles_inv : domain.fast_basic_twiddles) + : domain.basic_twiddles; + CHK_IF_RETURN(ntt::mixed_radix_ntt( - d_input, d_output, domain.twiddles, domain.internal_twiddles, domain.basic_twiddles, size, domain.max_log_size, - batch_size, is_inverse, config.ordering, coset, coset_index, stream)); + d_input, d_output, twiddles, internal_twiddles, basic_twiddles, size, domain.max_log_size, batch_size, + is_inverse, is_fast_twiddles_enabled, config.ordering, coset, coset_index, stream)); } if (!are_outputs_on_device) @@ -645,10 +699,10 @@ namespace ntt { * value of template parameter (where the curve is given by `-DCURVE` env variable during build): * - `S` is the [scalar field](@ref scalar_t) of the curve; */ - extern "C" cudaError_t - CONCAT_EXPAND(CURVE, InitializeDomain)(curve_config::scalar_t primitive_root, device_context::DeviceContext& ctx) + extern "C" cudaError_t CONCAT_EXPAND(CURVE, InitializeDomain)( + curve_config::scalar_t primitive_root, device_context::DeviceContext& ctx, bool fast_twiddles_mode) { - return InitDomain(primitive_root, ctx); + return InitDomain(primitive_root, ctx, fast_twiddles_mode); } /** diff --git a/icicle/appUtils/ntt/ntt.cuh b/icicle/appUtils/ntt/ntt.cuh index 6285a3c9c..c91f54ff3 100644 --- a/icicle/appUtils/ntt/ntt.cuh +++ b/icicle/appUtils/ntt/ntt.cuh @@ -32,10 +32,13 @@ namespace ntt { * @param primitive_root Primitive root in field `S` of order \f$ 2^s \f$. This should be the smallest power-of-2 * order that's large enough to support any NTT you might want to perform. * @param ctx Details related to the device such as its id and stream id. + * @param fast_twiddles_mode A mode where more memory is allocated for twiddle factors in exchange for faster compute. + * In this mode need additional 4N memory when N is the largest NTT size to be supported (which is derived by the + * primitive_root). * @return `cudaSuccess` if the execution was successful and an error code otherwise. */ template - cudaError_t InitDomain(S primitive_root, device_context::DeviceContext& ctx); + cudaError_t InitDomain(S primitive_root, device_context::DeviceContext& ctx, bool fast_twiddles_mode = false); /** * @enum NTTDir diff --git a/icicle/appUtils/ntt/ntt_impl.cuh b/icicle/appUtils/ntt/ntt_impl.cuh index 9e82a336e..155878466 100644 --- a/icicle/appUtils/ntt/ntt_impl.cuh +++ b/icicle/appUtils/ntt/ntt_impl.cuh @@ -16,6 +16,15 @@ namespace ntt { uint32_t log_size, cudaStream_t& stream); + template + cudaError_t generate_external_twiddles_fast_twiddles_mode( + const S& basic_root, + S* external_twiddles, + S*& internal_twiddles, + S*& basic_twiddles, + uint32_t log_size, + cudaStream_t& stream); + template cudaError_t mixed_radix_ntt( E* d_input, @@ -27,6 +36,7 @@ namespace ntt { int max_logn, int batch_size, bool is_inverse, + bool fast_tw, Ordering ordering, S* arbitrary_coset, int coset_gen_index, diff --git a/icicle/appUtils/ntt/tests/verification.cu b/icicle/appUtils/ntt/tests/verification.cu index d8148102f..341d951ef 100644 --- a/icicle/appUtils/ntt/tests/verification.cu +++ b/icicle/appUtils/ntt/tests/verification.cu @@ -34,13 +34,14 @@ int main(int argc, char** argv) cudaEvent_t icicle_start, icicle_stop, new_start, new_stop; float icicle_time, new_time; - int NTT_LOG_SIZE = (argc > 1) ? atoi(argv[1]) : 4; // assuming second input is the log-size + int NTT_LOG_SIZE = (argc > 1) ? atoi(argv[1]) : 19; int NTT_SIZE = 1 << NTT_LOG_SIZE; bool INPLACE = (argc > 2) ? atoi(argv[2]) : false; - int INV = (argc > 3) ? atoi(argv[3]) : false; + int INV = (argc > 3) ? atoi(argv[3]) : true; int BATCH_SIZE = (argc > 4) ? atoi(argv[4]) : 1; int COSET_IDX = (argc > 5) ? atoi(argv[5]) : 0; const ntt::Ordering ordering = (argc > 6) ? ntt::Ordering(atoi(argv[6])) : ntt::Ordering::kNN; + bool FAST_TW = (argc > 7) ? atoi(argv[7]) : true; // Note: NM, MN are not expected to be equal when comparing mixed-radix and radix-2 NTTs const char* ordering_str = ordering == ntt::Ordering::kNN ? "NN" @@ -51,8 +52,8 @@ int main(int argc, char** argv) : "MN"; printf( - "running ntt 2^%d, inplace=%d, inverse=%d, batch_size=%d, coset-idx=%d, ordering=%s\n", NTT_LOG_SIZE, INPLACE, INV, - BATCH_SIZE, COSET_IDX, ordering_str); + "running ntt 2^%d, inplace=%d, inverse=%d, batch_size=%d, coset-idx=%d, ordering=%s, fast_tw=%d\n", NTT_LOG_SIZE, + INPLACE, INV, BATCH_SIZE, COSET_IDX, ordering_str, FAST_TW); CHK_IF_RETURN(cudaFree(nullptr)); // init GPU context (warmup) @@ -70,7 +71,7 @@ int main(int argc, char** argv) auto start = std::chrono::high_resolution_clock::now(); const test_scalar basic_root = test_scalar::omega(NTT_LOG_SIZE); - ntt::InitDomain(basic_root, ntt_config.ctx); + ntt::InitDomain(basic_root, ntt_config.ctx, FAST_TW); auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(stop - start).count(); std::cout << "initDomain took: " << duration / 1000 << " MS" << std::endl; diff --git a/icicle/appUtils/ntt/thread_ntt.cu b/icicle/appUtils/ntt/thread_ntt.cu index f39a9cf7b..9c071bc72 100644 --- a/icicle/appUtils/ntt/thread_ntt.cu +++ b/icicle/appUtils/ntt/thread_ntt.cu @@ -13,19 +13,33 @@ struct stage_metadata { uint32_t ntt_inp_id; }; -uint32_t constexpr STAGE_SIZES_HOST[31][5] = { - {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {4, 0, 0, 0, 0}, {5, 0, 0, 0, 0}, {6, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, {4, 4, 0, 0, 0}, {5, 4, 0, 0, 0}, {5, 5, 0, 0, 0}, {6, 5, 0, 0, 0}, {6, 6, 0, 0, 0}, {4, 5, 4, 0, 0}, - {4, 6, 4, 0, 0}, {5, 5, 5, 0, 0}, {6, 4, 6, 0, 0}, {6, 5, 6, 0, 0}, {6, 6, 6, 0, 0}, {6, 5, 4, 4, 0}, {5, 5, 5, 5, 0}, - {6, 5, 5, 5, 0}, {6, 5, 5, 6, 0}, {6, 6, 6, 5, 0}, {6, 6, 6, 6, 0}, {5, 5, 5, 5, 5}, {6, 5, 4, 5, 6}, {6, 5, 5, 5, 6}, - {6, 5, 6, 5, 6}, {6, 6, 5, 6, 6}, {6, 6, 6, 6, 6}}; - -__device__ constexpr uint32_t STAGE_SIZES_DEVICE[31][5] = { - {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {4, 0, 0, 0, 0}, {5, 0, 0, 0, 0}, {6, 0, 0, 0, 0}, - {0, 0, 0, 0, 0}, {4, 4, 0, 0, 0}, {5, 4, 0, 0, 0}, {5, 5, 0, 0, 0}, {6, 5, 0, 0, 0}, {6, 6, 0, 0, 0}, {4, 5, 4, 0, 0}, - {4, 6, 4, 0, 0}, {5, 5, 5, 0, 0}, {6, 4, 6, 0, 0}, {6, 5, 6, 0, 0}, {6, 6, 6, 0, 0}, {6, 5, 4, 4, 0}, {5, 5, 5, 5, 0}, - {6, 5, 5, 5, 0}, {6, 5, 5, 6, 0}, {6, 6, 6, 5, 0}, {6, 6, 6, 6, 0}, {5, 5, 5, 5, 5}, {6, 5, 4, 5, 6}, {6, 5, 5, 5, 6}, - {6, 5, 6, 5, 6}, {6, 6, 5, 6, 6}, {6, 6, 6, 6, 6}}; +#define STAGE_SIZES_DATA \ + { \ + {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {4, 0, 0, 0, 0}, {5, 0, 0, 0, 0}, \ + {6, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {4, 4, 0, 0, 0}, {5, 4, 0, 0, 0}, {5, 5, 0, 0, 0}, {6, 5, 0, 0, 0}, \ + {6, 6, 0, 0, 0}, {4, 5, 4, 0, 0}, {4, 6, 4, 0, 0}, {5, 5, 5, 0, 0}, {6, 4, 6, 0, 0}, {6, 5, 6, 0, 0}, \ + {6, 6, 6, 0, 0}, {6, 5, 4, 4, 0}, {5, 5, 5, 5, 0}, {6, 5, 5, 5, 0}, {6, 5, 5, 6, 0}, {6, 6, 6, 5, 0}, \ + {6, 6, 6, 6, 0}, {5, 5, 5, 5, 5}, {6, 5, 4, 5, 6}, {6, 5, 5, 5, 6}, {6, 5, 6, 5, 6}, {6, 6, 5, 6, 6}, \ + {6, 6, 6, 6, 6}, \ + } +uint32_t constexpr STAGE_SIZES_HOST[31][5] = STAGE_SIZES_DATA; +__device__ constexpr uint32_t STAGE_SIZES_DEVICE[31][5] = STAGE_SIZES_DATA; + +// construction for fast-twiddles +uint32_t constexpr STAGE_PREV_SIZES[31] = {0, 0, 0, 0, 0, 0, 0, 0, 4, 5, 5, 6, 6, 9, 9, 10, + 11, 11, 12, 15, 15, 16, 16, 18, 18, 20, 21, 21, 22, 23, 24}; + +#define STAGE_SIZES_DATA_FAST_TW \ + { \ + {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {4, 0, 0, 0, 0}, {5, 0, 0, 0, 0}, \ + {6, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {4, 4, 0, 0, 0}, {5, 4, 0, 0, 0}, {5, 5, 0, 0, 0}, {6, 5, 0, 0, 0}, \ + {6, 6, 0, 0, 0}, {5, 4, 4, 0, 0}, {5, 4, 5, 0, 0}, {5, 5, 5, 0, 0}, {6, 5, 5, 0, 0}, {6, 5, 6, 0, 0}, \ + {6, 6, 6, 0, 0}, {5, 5, 5, 4, 0}, {5, 5, 5, 5, 0}, {6, 5, 5, 5, 0}, {6, 5, 5, 6, 0}, {6, 6, 6, 5, 0}, \ + {6, 6, 6, 6, 0}, {5, 5, 5, 5, 5}, {6, 5, 5, 5, 5}, {6, 5, 5, 5, 6}, {6, 5, 5, 6, 6}, {6, 6, 6, 5, 6}, \ + {6, 6, 6, 6, 6}, \ + } +uint32_t constexpr STAGE_SIZES_HOST_FT[31][5] = STAGE_SIZES_DATA_FAST_TW; +__device__ uint32_t constexpr STAGE_SIZES_DEVICE_FT[31][5] = STAGE_SIZES_DATA_FAST_TW; template class NTTEngine @@ -36,7 +50,15 @@ public: S WI[7]; S WE[8]; - __device__ __forceinline__ void loadBasicTwiddles(S* basic_twiddles, bool inv) + __device__ __forceinline__ void loadBasicTwiddles(S* basic_twiddles) + { +#pragma unroll + for (int i = 0; i < 3; i++) { + WB[i] = basic_twiddles[i]; + } + } + + __device__ __forceinline__ void loadBasicTwiddlesGeneric(S* basic_twiddles, bool inv) { #pragma unroll for (int i = 0; i < 3; i++) { @@ -44,7 +66,31 @@ public: } } - __device__ __forceinline__ void loadInternalTwiddles64(S* data, bool stride, bool inv) + __device__ __forceinline__ void loadInternalTwiddles64(S* data, bool stride) + { +#pragma unroll + for (int i = 0; i < 7; i++) { + WI[i] = data[((stride ? (threadIdx.x >> 3) : (threadIdx.x)) & 0x7) * (i + 1)]; + } + } + + __device__ __forceinline__ void loadInternalTwiddles32(S* data, bool stride) + { +#pragma unroll + for (int i = 0; i < 7; i++) { + WI[i] = data[2 * ((stride ? (threadIdx.x >> 4) : (threadIdx.x)) & 0x3) * (i + 1)]; + } + } + + __device__ __forceinline__ void loadInternalTwiddles16(S* data, bool stride) + { +#pragma unroll + for (int i = 0; i < 7; i++) { + WI[i] = data[4 * ((stride ? (threadIdx.x >> 5) : (threadIdx.x)) & 0x1) * (i + 1)]; + } + } + + __device__ __forceinline__ void loadInternalTwiddlesGeneric64(S* data, bool stride, bool inv) { #pragma unroll for (int i = 0; i < 7; i++) { @@ -53,7 +99,7 @@ public: } } - __device__ __forceinline__ void loadInternalTwiddles32(S* data, bool stride, bool inv) + __device__ __forceinline__ void loadInternalTwiddlesGeneric32(S* data, bool stride, bool inv) { #pragma unroll for (int i = 0; i < 7; i++) { @@ -62,7 +108,7 @@ public: } } - __device__ __forceinline__ void loadInternalTwiddles16(S* data, bool stride, bool inv) + __device__ __forceinline__ void loadInternalTwiddlesGeneric16(S* data, bool stride, bool inv) { #pragma unroll for (int i = 0; i < 7; i++) { @@ -71,8 +117,47 @@ public: } } + __device__ __forceinline__ void + loadExternalTwiddles64(S* data, uint32_t tw_order, uint32_t tw_log_order, bool strided, stage_metadata s_meta) + { + data += tw_order * s_meta.ntt_inp_id + (s_meta.ntt_block_id & (tw_order - 1)); + +#pragma unroll + for (uint32_t i = 0; i < 8; i++) { + WE[i] = data[8 * i * tw_order + (1 << tw_log_order + 6) - 1]; + } + } + + __device__ __forceinline__ void + loadExternalTwiddles32(S* data, uint32_t tw_order, uint32_t tw_log_order, bool strided, stage_metadata s_meta) + { + data += tw_order * s_meta.ntt_inp_id * 2 + (s_meta.ntt_block_id & (tw_order - 1)); + +#pragma unroll + for (uint32_t j = 0; j < 2; j++) { +#pragma unroll + for (uint32_t i = 0; i < 4; i++) { + WE[4 * j + i] = data[(8 * i + j) * tw_order + (1 << tw_log_order + 5) - 1]; + } + } + } + + __device__ __forceinline__ void + loadExternalTwiddles16(S* data, uint32_t tw_order, uint32_t tw_log_order, bool strided, stage_metadata s_meta) + { + data += tw_order * s_meta.ntt_inp_id * 4 + (s_meta.ntt_block_id & (tw_order - 1)); + +#pragma unroll + for (uint32_t j = 0; j < 4; j++) { +#pragma unroll + for (uint32_t i = 0; i < 2; i++) { + WE[2 * j + i] = data[(8 * i + j) * tw_order + (1 << tw_log_order + 4) - 1]; + } + } + } + __device__ __forceinline__ void loadExternalTwiddlesGeneric64( - E* data, uint32_t tw_order, uint32_t tw_log_order, stage_metadata s_meta, uint32_t tw_log_size, bool inv) + S* data, uint32_t tw_order, uint32_t tw_log_order, stage_metadata s_meta, uint32_t tw_log_size, bool inv) { #pragma unroll for (uint32_t i = 0; i < 8; i++) { @@ -83,7 +168,7 @@ public: } __device__ __forceinline__ void loadExternalTwiddlesGeneric32( - E* data, uint32_t tw_order, uint32_t tw_log_order, stage_metadata s_meta, uint32_t tw_log_size, bool inv) + S* data, uint32_t tw_order, uint32_t tw_log_order, stage_metadata s_meta, uint32_t tw_log_size, bool inv) { #pragma unroll for (uint32_t j = 0; j < 2; j++) { @@ -97,7 +182,7 @@ public: } __device__ __forceinline__ void loadExternalTwiddlesGeneric16( - E* data, uint32_t tw_order, uint32_t tw_log_order, stage_metadata s_meta, uint32_t tw_log_size, bool inv) + S* data, uint32_t tw_order, uint32_t tw_log_order, stage_metadata s_meta, uint32_t tw_log_size, bool inv) { #pragma unroll for (uint32_t j = 0; j < 4; j++) { diff --git a/wrappers/rust/icicle-core/src/ntt/mod.rs b/wrappers/rust/icicle-core/src/ntt/mod.rs index 3d699e7c1..9c50dc5a3 100644 --- a/wrappers/rust/icicle-core/src/ntt/mod.rs +++ b/wrappers/rust/icicle-core/src/ntt/mod.rs @@ -119,6 +119,7 @@ pub trait NTT { output: &mut HostOrDeviceSlice, ) -> IcicleResult<()>; fn initialize_domain(primitive_root: F, ctx: &DeviceContext) -> IcicleResult<()>; + fn initialize_domain_fast_twiddles_mode(primitive_root: F, ctx: &DeviceContext) -> IcicleResult<()>; } /// Computes the NTT, or a batch of several NTTs. @@ -172,6 +173,13 @@ where { <::Config as NTT>::initialize_domain(primitive_root, ctx) } +pub fn initialize_domain_fast_twiddles_mode(primitive_root: F, ctx: &DeviceContext) -> IcicleResult<()> +where + F: FieldImpl, + ::Config: NTT, +{ + <::Config as NTT>::initialize_domain_fast_twiddles_mode(primitive_root, ctx) +} #[macro_export] macro_rules! impl_ntt { @@ -195,7 +203,11 @@ macro_rules! impl_ntt { ) -> CudaError; #[link_name = concat!($field_prefix, "InitializeDomain")] - pub(crate) fn initialize_ntt_domain(primitive_root: $field, ctx: &DeviceContext) -> CudaError; + pub(crate) fn initialize_ntt_domain( + primitive_root: $field, + ctx: &DeviceContext, + fast_twiddles_mode: bool, + ) -> CudaError; } } @@ -219,7 +231,10 @@ macro_rules! impl_ntt { } fn initialize_domain(primitive_root: $field, ctx: &DeviceContext) -> IcicleResult<()> { - unsafe { $field_prefix_ident::initialize_ntt_domain(primitive_root, ctx).wrap() } + unsafe { $field_prefix_ident::initialize_ntt_domain(primitive_root, ctx, false).wrap() } + } + fn initialize_domain_fast_twiddles_mode(primitive_root: $field, ctx: &DeviceContext) -> IcicleResult<()> { + unsafe { $field_prefix_ident::initialize_ntt_domain(primitive_root, ctx, true).wrap() } } } }; @@ -232,28 +247,29 @@ macro_rules! impl_ntt_tests { ) => { const MAX_SIZE: u64 = 1 << 17; static INIT: OnceLock<()> = OnceLock::new(); + const FAST_TWIDDLES_MODE: bool = false; #[test] fn test_ntt() { - INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID)); + INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID, FAST_TWIDDLES_MODE)); check_ntt::<$field>() } #[test] fn test_ntt_coset_from_subgroup() { - INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID)); + INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID, FAST_TWIDDLES_MODE)); check_ntt_coset_from_subgroup::<$field>() } #[test] fn test_ntt_arbitrary_coset() { - INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID)); + INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID, FAST_TWIDDLES_MODE)); check_ntt_arbitrary_coset::<$field>() } #[test] fn test_ntt_batch() { - INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID)); + INIT.get_or_init(move || init_domain::<$field>(MAX_SIZE, DEFAULT_DEVICE_ID, FAST_TWIDDLES_MODE)); check_ntt_batch::<$field>() } diff --git a/wrappers/rust/icicle-core/src/ntt/tests.rs b/wrappers/rust/icicle-core/src/ntt/tests.rs index fde182fc2..880c52f56 100644 --- a/wrappers/rust/icicle-core/src/ntt/tests.rs +++ b/wrappers/rust/icicle-core/src/ntt/tests.rs @@ -9,21 +9,25 @@ use rayon::iter::IntoParallelIterator; use rayon::iter::ParallelIterator; use crate::{ - ntt::{initialize_domain, ntt, NTTDir, NttAlgorithm, Ordering}, + ntt::{initialize_domain, initialize_domain_fast_twiddles_mode, ntt, NTTDir, NttAlgorithm, Ordering}, traits::{ArkConvertible, FieldImpl, GenerateRandom}, }; use super::NTTConfig; use super::NTT; -pub fn init_domain(max_size: u64, device_id: usize) +pub fn init_domain(max_size: u64, device_id: usize, fast_twiddles_mode: bool) where F::ArkEquivalent: FftField, ::Config: NTT, { let ctx = DeviceContext::default_for_device(device_id); let ark_rou = F::ArkEquivalent::get_root_of_unity(max_size).unwrap(); - initialize_domain(F::from_ark(ark_rou), &ctx).unwrap(); + if fast_twiddles_mode { + initialize_domain_fast_twiddles_mode(F::from_ark(ark_rou), &ctx).unwrap(); + } else { + initialize_domain(F::from_ark(ark_rou), &ctx).unwrap(); + } } pub fn reverse_bit_order(n: u32, order: u32) -> u32 { @@ -289,7 +293,8 @@ where .into_par_iter() .for_each(move |device_id| { set_device(device_id).unwrap(); - init_domain::(1 << 16, device_id); // init domain per device + // if have more than one device, it will use fast-twiddles-mode (note that domain is reused per device if not released) + init_domain::(1 << 16, device_id, true /*=fast twiddles mode*/); // init domain per device let test_sizes = [1 << 4, 1 << 12]; let batch_sizes = [1, 1 << 4, 100]; for test_size in test_sizes { From 9a6ab924c2837b2c617368f7d92364ef0c2cb54c Mon Sep 17 00:00:00 2001 From: ChickenLover Date: Thu, 22 Feb 2024 11:39:15 +0700 Subject: [PATCH 18/21] Update README.md (#385) (#387) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9094bf770..aed9204cd 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ ICICLE is a CUDA implementation of general functions widely used in ZKP. > [!NOTE] > Developers: We highly recommend reading our [documentation] + > [!TIP] > Try out ICICLE by running some [examples] using ICICLE in C++ and our Rust bindings From 402c9dfb53429320e2b5913cbf7d47bffd1a7a3f Mon Sep 17 00:00:00 2001 From: ChickenLover Date: Fri, 23 Feb 2024 00:39:58 +0700 Subject: [PATCH 19/21] Update Hall of Fame section (#394) Add nonam3e as contributor --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index aed9204cd..9b4d2860e 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ This will ensure our custom hooks are run and will make it easier to follow our - [Robik](https://github.com/robik75), for his ongoing support and mentorship - [liuxiao](https://github.com/liuxiaobleach), for being a top notch bug smasher - [gkigiermo](https://github.com/gkigiermo), for making it intuitive to use ICICLE in Google Colab. +- [nonam3e](https://github.com/nonam3e), for adding Grumpkin curve support into ICICLE ## Help & Support From efda4de48fc0d2d2fa639774b4380674b80b564a Mon Sep 17 00:00:00 2001 From: ChickenLover Date: Fri, 23 Feb 2024 00:47:40 +0700 Subject: [PATCH 20/21] add rust poseidon example (#392) add rust poseidon example --- .github/workflows/examples.yml | 2 +- .../rust/poseidon/.devcontainer/Dockerfile | 27 ++++++++++ .../poseidon/.devcontainer/devcontainer.json | 23 ++++++++ examples/rust/poseidon/Cargo.toml | 14 +++++ examples/rust/poseidon/src/main.rs | 53 +++++++++++++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 examples/rust/poseidon/.devcontainer/Dockerfile create mode 100644 examples/rust/poseidon/.devcontainer/devcontainer.json create mode 100644 examples/rust/poseidon/Cargo.toml create mode 100644 examples/rust/poseidon/src/main.rs diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 020c2046d..e7a10f598 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -23,7 +23,7 @@ concurrency: jobs: test-examples: - runs-on: [self-hosted, Linux, X64, icicle] # ubuntu-latest + runs-on: [self-hosted, Linux, X64, icicle, examples] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/examples/rust/poseidon/.devcontainer/Dockerfile b/examples/rust/poseidon/.devcontainer/Dockerfile new file mode 100644 index 000000000..1af12c34a --- /dev/null +++ b/examples/rust/poseidon/.devcontainer/Dockerfile @@ -0,0 +1,27 @@ +# Use the specified base image +#FROM nvidia/cuda:12.2.0-devel-ubuntu22.04 +FROM nvidia/cuda:12.0.0-devel-ubuntu22.04 + +# Update and install dependencies +RUN apt-get update && apt-get install -y \ + cmake \ + protobuf-compiler \ + curl \ + build-essential \ + git \ + llvm \ + clang \ + && rm -rf /var/lib/apt/lists/* + +# Install Rust +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +ENV PATH="/root/.cargo/bin:${PATH}" + +# Set the working directory in the container +WORKDIR /icicle-example + +# Copy the content of the local directory to the working directory +COPY . . + +# Specify the default command for the container +CMD ["/bin/bash"] \ No newline at end of file diff --git a/examples/rust/poseidon/.devcontainer/devcontainer.json b/examples/rust/poseidon/.devcontainer/devcontainer.json new file mode 100644 index 000000000..63e34f9b9 --- /dev/null +++ b/examples/rust/poseidon/.devcontainer/devcontainer.json @@ -0,0 +1,23 @@ +{ + "name": "Icicle Examples: rust poseidon", + "build": { + "dockerfile": "Dockerfile" + }, + "runArgs": [ + "--gpus", + "all" + ], + "postCreateCommand": [ + "nvidia-smi" + ], + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.cmake-tools", + "ms-azuretools.vscode-docker", + "rust-lang.rust-analyzer", + "vadimcn.vscode-lldb" + ] + } + } +} diff --git a/examples/rust/poseidon/Cargo.toml b/examples/rust/poseidon/Cargo.toml new file mode 100644 index 000000000..1ae3bed8b --- /dev/null +++ b/examples/rust/poseidon/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "poseidon" +version = "1.4.0" +edition = "2018" + +[dependencies] +icicle-cuda-runtime = { path = "../../../wrappers/rust/icicle-cuda-runtime" } +icicle-core = { path = "../../../wrappers/rust/icicle-core" } +icicle-bls12-381 = { path = "../../../wrappers/rust/icicle-curves/icicle-bls12-381" } + +clap = { version = "<=4.4.12", features = ["derive"] } + +[features] +profile = [] diff --git a/examples/rust/poseidon/src/main.rs b/examples/rust/poseidon/src/main.rs new file mode 100644 index 000000000..5b4f79c47 --- /dev/null +++ b/examples/rust/poseidon/src/main.rs @@ -0,0 +1,53 @@ +use icicle_bls12_381::curve::ScalarField as F; + +use icicle_cuda_runtime::device_context::DeviceContext; + +use icicle_core::poseidon::{load_optimized_poseidon_constants, poseidon_hash_many, PoseidonConfig}; +use icicle_core::traits::FieldImpl; +use icicle_cuda_runtime::memory::HostOrDeviceSlice; + +#[cfg(feature = "profile")] +use std::time::Instant; + +use clap::Parser; + +#[derive(Parser, Debug)] +struct Args { + /// Size of Poseidon input to run (20 for 2^20) + #[arg(short, long, default_value_t = 20)] + size: u8, +} + +fn main() { + let args = Args::parse(); + let size = args.size; + let test_size = 1 << size; + + println!("Running Icicle Examples: Rust Poseidon Hash"); + let arity = 2u32; + println!("---------------------- Loading optimized Poseidon constants for arity={} ------------------------", arity); + let ctx = DeviceContext::default(); + let constants = load_optimized_poseidon_constants::(arity, &ctx).unwrap(); + let config = PoseidonConfig::default(); + + println!("---------------------- Input size 2^{}={} ------------------------", size, test_size); + let inputs = vec![F::one(); test_size * arity as usize]; + let outputs = vec![F::zero(); test_size]; + let mut input_slice = HostOrDeviceSlice::on_host(inputs); + let mut output_slice = HostOrDeviceSlice::on_host(outputs); + + println!("Executing BLS12-381 Poseidon Hash on device..."); + #[cfg(feature = "profile")] + let start = Instant::now(); + poseidon_hash_many::( + &mut input_slice, + &mut output_slice, + test_size as u32, + arity as u32, + &constants, + &config, + ) + .unwrap(); + #[cfg(feature = "profile")] + println!("ICICLE BLS12-381 Poseidon Hash on size 2^{size} took: {} μs", start.elapsed().as_micros()); +} \ No newline at end of file From e8cd2d7a980410ae51efc11d0e5954e8d2a73f7d Mon Sep 17 00:00:00 2001 From: Jeremy Felder Date: Thu, 22 Feb 2024 20:52:48 +0200 Subject: [PATCH 21/21] GoLang bindings for v1.x (#386) --- .github/changed-files.yml | 4 +- .github/workflows/main-build.yml | 28 +- .github/workflows/main-test.yml | 39 +- README.md | 4 +- go.mod | 18 +- go.sum | 36 +- goicicle/Makefile | 34 -- goicicle/README.md | 82 ---- goicicle/curves/bls12377/g1.go | 328 ---------------- goicicle/curves/bls12377/g1_test.go | 198 ---------- goicicle/curves/bls12377/g2.go | 102 ----- goicicle/curves/bls12377/g2_test.go | 79 ---- goicicle/curves/bls12377/include/msm.h | 98 ----- goicicle/curves/bls12377/include/ntt.h | 195 ---------- goicicle/curves/bls12377/include/projective.h | 50 --- .../curves/bls12377/include/ve_mod_mult.h | 49 --- goicicle/curves/bls12377/msm.go | 209 ---------- goicicle/curves/bls12377/msm_test.go | 360 ----------------- goicicle/curves/bls12377/ntt.go | 222 ----------- goicicle/curves/bls12377/ntt_test.go | 148 ------- goicicle/curves/bls12377/utils.go | 38 -- goicicle/curves/bls12377/vec_mod.go | 42 -- goicicle/curves/bls12381/g1.go | 328 ---------------- goicicle/curves/bls12381/g1_test.go | 198 ---------- goicicle/curves/bls12381/g2.go | 102 ----- goicicle/curves/bls12381/g2_test.go | 79 ---- goicicle/curves/bls12381/include/msm.h | 98 ----- goicicle/curves/bls12381/include/ntt.h | 195 ---------- goicicle/curves/bls12381/include/projective.h | 50 --- .../curves/bls12381/include/ve_mod_mult.h | 49 --- goicicle/curves/bls12381/msm.go | 209 ---------- goicicle/curves/bls12381/msm_test.go | 360 ----------------- goicicle/curves/bls12381/ntt.go | 222 ----------- goicicle/curves/bls12381/ntt_test.go | 148 ------- goicicle/curves/bls12381/utils.go | 38 -- goicicle/curves/bls12381/utils_test.go | 81 ---- goicicle/curves/bls12381/vec_mod.go | 42 -- goicicle/curves/bn254/g1.go | 328 ---------------- goicicle/curves/bn254/g1_test.go | 198 ---------- goicicle/curves/bn254/g2.go | 102 ----- goicicle/curves/bn254/g2_test.go | 79 ---- goicicle/curves/bn254/include/msm.h | 94 ----- goicicle/curves/bn254/include/ntt.h | 193 --------- goicicle/curves/bn254/include/projective.h | 50 --- goicicle/curves/bn254/msm.go | 209 ---------- goicicle/curves/bn254/msm_test.go | 360 ----------------- goicicle/curves/bn254/ntt.go | 222 ----------- goicicle/curves/bn254/ntt_test.go | 148 ------- goicicle/curves/bn254/utils.go | 48 --- goicicle/curves/bn254/utils_test.go | 81 ---- goicicle/curves/bn254/vec_mod.go | 42 -- goicicle/curves/bw6761/g1.go | 328 ---------------- goicicle/curves/bw6761/g1_test.go | 212 ---------- goicicle/curves/bw6761/g2.go | 98 ----- goicicle/curves/bw6761/g2_test.go | 83 ---- goicicle/curves/bw6761/include/msm.h | 101 ----- goicicle/curves/bw6761/include/ntt.h | 198 ---------- goicicle/curves/bw6761/include/projective.h | 50 --- goicicle/curves/bw6761/include/ve_mod_mult.h | 49 --- goicicle/curves/bw6761/msm.go | 209 ---------- goicicle/curves/bw6761/msm_test.go | 367 ------------------ goicicle/curves/bw6761/ntt.go | 222 ----------- goicicle/curves/bw6761/ntt_test.go | 148 ------- goicicle/curves/bw6761/vec_mod.go | 42 -- goicicle/goicicle.go | 49 --- goicicle/setup.sh | 48 --- goicicle/templates/curves/curves.go | 52 --- goicicle/templates/curves/g1.go.tmpl | 310 --------------- goicicle/templates/curves/g1_test.go.tmpl | 180 --------- goicicle/templates/curves/g2.go.tmpl | 85 ---- goicicle/templates/curves/g2_test.go.tmpl | 61 --- goicicle/templates/hfiles/msm.h.tmpl | 84 ---- goicicle/templates/hfiles/ntt.h.tmpl | 181 --------- goicicle/templates/hfiles/projective.h.tmpl | 33 -- goicicle/templates/hfiles/ve_mod_mult.h.tmpl | 32 -- goicicle/templates/main.go | 312 --------------- goicicle/templates/msm/msm.go.tmpl | 191 --------- goicicle/templates/msm/msm_test.go.tmpl | 342 ---------------- goicicle/templates/ntt/ntt.go.tmpl | 204 ---------- goicicle/templates/ntt/ntt_test.go.tmpl | 130 ------- goicicle/templates/ops/vec_mod.go.tmpl | 24 -- icicle/appUtils/ntt/ntt.cu | 4 +- icicle/primitives/field.cuh | 2 +- wrappers/golang/README.md | 103 +++++ wrappers/golang/build.sh | 27 ++ wrappers/golang/core/error.go | 43 ++ wrappers/golang/core/internal/curve.go | 76 ++++ wrappers/golang/core/internal/curve_test.go | 101 +++++ wrappers/golang/core/internal/field.go | 79 ++++ wrappers/golang/core/internal/field_test.go | 82 ++++ wrappers/golang/core/internal/helpers_test.go | 31 ++ wrappers/golang/core/msm.go | 106 +++++ wrappers/golang/core/msm_test.go | 106 +++++ wrappers/golang/core/ntt.go | 68 ++++ wrappers/golang/core/ntt_test.go | 96 +++++ wrappers/golang/core/slice.go | 160 ++++++++ wrappers/golang/core/slice_test.go | 192 +++++++++ wrappers/golang/core/utils.go | 26 ++ wrappers/golang/core/utils_test.go | 78 ++++ wrappers/golang/cuda_runtime/const.go | 179 +++++++++ wrappers/golang/cuda_runtime/cuda_bindings.go | 50 +++ wrappers/golang/cuda_runtime/cuda_runtime.yml | 85 ++++ .../golang/cuda_runtime/device_context.go | 49 +++ .../cuda_runtime/device_context_test.go | 29 ++ wrappers/golang/cuda_runtime/error.go | 15 + wrappers/golang/cuda_runtime/error_test.go | 11 + wrappers/golang/cuda_runtime/memory.go | 87 +++++ wrappers/golang/cuda_runtime/memory_test.go | 42 ++ wrappers/golang/cuda_runtime/stream.go | 45 +++ wrappers/golang/cuda_runtime/stream_test.go | 45 +++ wrappers/golang/cuda_runtime/types.go | 19 + wrappers/golang/curves/bls12377/base_field.go | 79 ++++ .../golang/curves/bls12377/base_field_test.go | 82 ++++ wrappers/golang/curves/bls12377/bls12_377.go | 4 + wrappers/golang/curves/bls12377/curve.go | 173 +++++++++ wrappers/golang/curves/bls12377/curve_test.go | 101 +++++ .../golang/curves/bls12377/g2_base_field.go | 81 ++++ .../curves/bls12377/g2_base_field_test.go | 84 ++++ wrappers/golang/curves/bls12377/g2_curve.go | 175 +++++++++ .../golang/curves/bls12377/g2_curve_test.go | 103 +++++ wrappers/golang/curves/bls12377/g2_msm.go | 51 +++ .../golang/curves/bls12377/g2_msm_test.go | 167 ++++++++ .../golang/curves/bls12377/helpers_test.go | 31 ++ .../golang/curves/bls12377/include/curve.h | 23 ++ .../golang/curves/bls12377/include/g2_curve.h | 23 ++ .../golang/curves/bls12377/include/g2_msm.h | 17 + wrappers/golang/curves/bls12377/include/msm.h | 17 + wrappers/golang/curves/bls12377/include/ntt.h | 19 + .../curves/bls12377/include/scalar_field.h | 19 + wrappers/golang/curves/bls12377/msm.go | 49 +++ wrappers/golang/curves/bls12377/msm_test.go | 138 +++++++ wrappers/golang/curves/bls12377/ntt.go | 59 +++ wrappers/golang/curves/bls12377/ntt_test.go | 239 ++++++++++++ .../golang/curves/bls12377/scalar_field.go | 119 ++++++ .../curves/bls12377/scalar_field_test.go | 114 ++++++ wrappers/golang/curves/bls12381/base_field.go | 79 ++++ .../golang/curves/bls12381/base_field_test.go | 82 ++++ wrappers/golang/curves/bls12381/bls12_381.go | 4 + wrappers/golang/curves/bls12381/curve.go | 173 +++++++++ wrappers/golang/curves/bls12381/curve_test.go | 101 +++++ .../golang/curves/bls12381/g2_base_field.go | 81 ++++ .../curves/bls12381/g2_base_field_test.go | 84 ++++ wrappers/golang/curves/bls12381/g2_curve.go | 175 +++++++++ .../golang/curves/bls12381/g2_curve_test.go | 103 +++++ wrappers/golang/curves/bls12381/g2_msm.go | 51 +++ .../golang/curves/bls12381/g2_msm_test.go | 167 ++++++++ .../golang/curves/bls12381/helpers_test.go | 31 ++ .../golang/curves/bls12381/include/curve.h | 23 ++ .../golang/curves/bls12381/include/g2_curve.h | 23 ++ .../golang/curves/bls12381/include/g2_msm.h | 17 + wrappers/golang/curves/bls12381/include/msm.h | 17 + wrappers/golang/curves/bls12381/include/ntt.h | 19 + .../curves/bls12381/include/scalar_field.h | 19 + wrappers/golang/curves/bls12381/msm.go | 49 +++ wrappers/golang/curves/bls12381/msm_test.go | 138 +++++++ wrappers/golang/curves/bls12381/ntt.go | 59 +++ wrappers/golang/curves/bls12381/ntt_test.go | 239 ++++++++++++ .../golang/curves/bls12381/scalar_field.go | 119 ++++++ .../curves/bls12381/scalar_field_test.go | 114 ++++++ wrappers/golang/curves/bn254/base_field.go | 79 ++++ .../golang/curves/bn254/base_field_test.go | 82 ++++ wrappers/golang/curves/bn254/bn254.go | 4 + wrappers/golang/curves/bn254/curve.go | 173 +++++++++ wrappers/golang/curves/bn254/curve_test.go | 101 +++++ wrappers/golang/curves/bn254/g2_base_field.go | 81 ++++ .../golang/curves/bn254/g2_base_field_test.go | 84 ++++ wrappers/golang/curves/bn254/g2_curve.go | 175 +++++++++ wrappers/golang/curves/bn254/g2_curve_test.go | 103 +++++ wrappers/golang/curves/bn254/g2_msm.go | 51 +++ wrappers/golang/curves/bn254/g2_msm_test.go | 167 ++++++++ wrappers/golang/curves/bn254/helpers_test.go | 31 ++ wrappers/golang/curves/bn254/include/curve.h | 23 ++ .../golang/curves/bn254/include/g2_curve.h | 23 ++ wrappers/golang/curves/bn254/include/g2_msm.h | 17 + wrappers/golang/curves/bn254/include/msm.h | 17 + wrappers/golang/curves/bn254/include/ntt.h | 19 + .../curves/bn254/include/scalar_field.h | 19 + .../curves/bn254/include/ve_mod_mult.h | 43 +- wrappers/golang/curves/bn254/msm.go | 49 +++ wrappers/golang/curves/bn254/msm_test.go | 138 +++++++ wrappers/golang/curves/bn254/ntt.go | 59 +++ wrappers/golang/curves/bn254/ntt_test.go | 239 ++++++++++++ wrappers/golang/curves/bn254/scalar_field.go | 119 ++++++ .../golang/curves/bn254/scalar_field_test.go | 114 ++++++ wrappers/golang/curves/bw6761/base_field.go | 79 ++++ .../golang/curves/bw6761/base_field_test.go | 82 ++++ wrappers/golang/curves/bw6761/bw6_761.go | 4 + wrappers/golang/curves/bw6761/curve.go | 173 +++++++++ wrappers/golang/curves/bw6761/curve_test.go | 101 +++++ .../golang/curves/bw6761/g2_base_field.go | 81 ++++ .../curves/bw6761/g2_base_field_test.go | 84 ++++ wrappers/golang/curves/bw6761/g2_curve.go | 175 +++++++++ .../golang/curves/bw6761/g2_curve_test.go | 103 +++++ wrappers/golang/curves/bw6761/g2_msm.go | 51 +++ wrappers/golang/curves/bw6761/g2_msm_test.go | 140 +++++++ wrappers/golang/curves/bw6761/helpers_test.go | 31 ++ wrappers/golang/curves/bw6761/include/curve.h | 23 ++ .../golang/curves/bw6761/include/g2_curve.h | 23 ++ .../golang/curves/bw6761/include/g2_msm.h | 17 + wrappers/golang/curves/bw6761/include/msm.h | 17 + wrappers/golang/curves/bw6761/include/ntt.h | 19 + .../curves/bw6761/include/scalar_field.h | 19 + wrappers/golang/curves/bw6761/msm.go | 49 +++ wrappers/golang/curves/bw6761/msm_test.go | 138 +++++++ wrappers/golang/curves/bw6761/ntt.go | 59 +++ wrappers/golang/curves/bw6761/ntt_test.go | 239 ++++++++++++ wrappers/golang/curves/bw6761/scalar_field.go | 119 ++++++ .../golang/curves/bw6761/scalar_field_test.go | 114 ++++++ wrappers/golang/curves/include/types.h | 36 ++ wrappers/golang/internal/generator/main.go | 250 ++++++++++++ .../generator/templates/curve.go.tmpl | 178 +++++++++ .../generator/templates/curve_test.go.tmpl | 105 +++++ .../generator/templates/field.go.tmpl | 90 +++++ .../generator/templates/field_test.go.tmpl | 91 +++++ .../generator/templates/helpers_test.go.tmpl | 31 ++ .../generator/templates/include/curve.h.tmpl | 23 ++ .../templates/include/g2_curve.h.tmpl | 23 ++ .../generator/templates/include/g2_msm.h.tmpl | 17 + .../generator/templates/include/msm.h.tmpl | 17 + .../generator/templates/include/ntt.h.tmpl | 19 + .../templates/include/scalar_field.h.tmpl | 19 + .../templates/include/vec_ops.h.tmpl | 53 +++ .../internal/generator/templates/main.go.tmpl | 4 + .../internal/generator/templates/msm.go.tmpl | 53 +++ .../generator/templates/msm_test.go.tmpl | 187 +++++++++ .../internal/generator/templates/ntt.go.tmpl | 59 +++ .../generator/templates/ntt_test.go.tmpl | 239 ++++++++++++ .../generator/templates/scalar_field.go.tmpl | 46 +++ .../templates/scalar_field_test.go.tmpl | 34 ++ .../generator/templates/vec_ops.go.tmpl | 0 .../generator/templates/vec_ops_test.go.tmpl | 0 wrappers/rust/icicle-core/src/ntt/mod.rs | 6 +- 232 files changed, 11566 insertions(+), 11075 deletions(-) delete mode 100644 goicicle/Makefile delete mode 100644 goicicle/README.md delete mode 100644 goicicle/curves/bls12377/g1.go delete mode 100644 goicicle/curves/bls12377/g1_test.go delete mode 100644 goicicle/curves/bls12377/g2.go delete mode 100644 goicicle/curves/bls12377/g2_test.go delete mode 100644 goicicle/curves/bls12377/include/msm.h delete mode 100644 goicicle/curves/bls12377/include/ntt.h delete mode 100644 goicicle/curves/bls12377/include/projective.h delete mode 100644 goicicle/curves/bls12377/include/ve_mod_mult.h delete mode 100644 goicicle/curves/bls12377/msm.go delete mode 100644 goicicle/curves/bls12377/msm_test.go delete mode 100644 goicicle/curves/bls12377/ntt.go delete mode 100644 goicicle/curves/bls12377/ntt_test.go delete mode 100644 goicicle/curves/bls12377/utils.go delete mode 100644 goicicle/curves/bls12377/vec_mod.go delete mode 100644 goicicle/curves/bls12381/g1.go delete mode 100644 goicicle/curves/bls12381/g1_test.go delete mode 100644 goicicle/curves/bls12381/g2.go delete mode 100644 goicicle/curves/bls12381/g2_test.go delete mode 100644 goicicle/curves/bls12381/include/msm.h delete mode 100644 goicicle/curves/bls12381/include/ntt.h delete mode 100644 goicicle/curves/bls12381/include/projective.h delete mode 100644 goicicle/curves/bls12381/include/ve_mod_mult.h delete mode 100644 goicicle/curves/bls12381/msm.go delete mode 100644 goicicle/curves/bls12381/msm_test.go delete mode 100644 goicicle/curves/bls12381/ntt.go delete mode 100644 goicicle/curves/bls12381/ntt_test.go delete mode 100644 goicicle/curves/bls12381/utils.go delete mode 100644 goicicle/curves/bls12381/utils_test.go delete mode 100644 goicicle/curves/bls12381/vec_mod.go delete mode 100644 goicicle/curves/bn254/g1.go delete mode 100644 goicicle/curves/bn254/g1_test.go delete mode 100644 goicicle/curves/bn254/g2.go delete mode 100644 goicicle/curves/bn254/g2_test.go delete mode 100644 goicicle/curves/bn254/include/msm.h delete mode 100644 goicicle/curves/bn254/include/ntt.h delete mode 100644 goicicle/curves/bn254/include/projective.h delete mode 100644 goicicle/curves/bn254/msm.go delete mode 100644 goicicle/curves/bn254/msm_test.go delete mode 100644 goicicle/curves/bn254/ntt.go delete mode 100644 goicicle/curves/bn254/ntt_test.go delete mode 100644 goicicle/curves/bn254/utils.go delete mode 100644 goicicle/curves/bn254/utils_test.go delete mode 100644 goicicle/curves/bn254/vec_mod.go delete mode 100644 goicicle/curves/bw6761/g1.go delete mode 100644 goicicle/curves/bw6761/g1_test.go delete mode 100644 goicicle/curves/bw6761/g2.go delete mode 100644 goicicle/curves/bw6761/g2_test.go delete mode 100644 goicicle/curves/bw6761/include/msm.h delete mode 100644 goicicle/curves/bw6761/include/ntt.h delete mode 100644 goicicle/curves/bw6761/include/projective.h delete mode 100644 goicicle/curves/bw6761/include/ve_mod_mult.h delete mode 100644 goicicle/curves/bw6761/msm.go delete mode 100644 goicicle/curves/bw6761/msm_test.go delete mode 100644 goicicle/curves/bw6761/ntt.go delete mode 100644 goicicle/curves/bw6761/ntt_test.go delete mode 100644 goicicle/curves/bw6761/vec_mod.go delete mode 100644 goicicle/goicicle.go delete mode 100755 goicicle/setup.sh delete mode 100644 goicicle/templates/curves/curves.go delete mode 100644 goicicle/templates/curves/g1.go.tmpl delete mode 100644 goicicle/templates/curves/g1_test.go.tmpl delete mode 100644 goicicle/templates/curves/g2.go.tmpl delete mode 100644 goicicle/templates/curves/g2_test.go.tmpl delete mode 100644 goicicle/templates/hfiles/msm.h.tmpl delete mode 100644 goicicle/templates/hfiles/ntt.h.tmpl delete mode 100644 goicicle/templates/hfiles/projective.h.tmpl delete mode 100644 goicicle/templates/hfiles/ve_mod_mult.h.tmpl delete mode 100644 goicicle/templates/main.go delete mode 100644 goicicle/templates/msm/msm.go.tmpl delete mode 100644 goicicle/templates/msm/msm_test.go.tmpl delete mode 100644 goicicle/templates/ntt/ntt.go.tmpl delete mode 100644 goicicle/templates/ntt/ntt_test.go.tmpl delete mode 100644 goicicle/templates/ops/vec_mod.go.tmpl create mode 100644 wrappers/golang/README.md create mode 100755 wrappers/golang/build.sh create mode 100644 wrappers/golang/core/error.go create mode 100644 wrappers/golang/core/internal/curve.go create mode 100644 wrappers/golang/core/internal/curve_test.go create mode 100644 wrappers/golang/core/internal/field.go create mode 100644 wrappers/golang/core/internal/field_test.go create mode 100644 wrappers/golang/core/internal/helpers_test.go create mode 100644 wrappers/golang/core/msm.go create mode 100644 wrappers/golang/core/msm_test.go create mode 100644 wrappers/golang/core/ntt.go create mode 100644 wrappers/golang/core/ntt_test.go create mode 100644 wrappers/golang/core/slice.go create mode 100644 wrappers/golang/core/slice_test.go create mode 100644 wrappers/golang/core/utils.go create mode 100644 wrappers/golang/core/utils_test.go create mode 100644 wrappers/golang/cuda_runtime/const.go create mode 100644 wrappers/golang/cuda_runtime/cuda_bindings.go create mode 100644 wrappers/golang/cuda_runtime/cuda_runtime.yml create mode 100644 wrappers/golang/cuda_runtime/device_context.go create mode 100644 wrappers/golang/cuda_runtime/device_context_test.go create mode 100644 wrappers/golang/cuda_runtime/error.go create mode 100644 wrappers/golang/cuda_runtime/error_test.go create mode 100644 wrappers/golang/cuda_runtime/memory.go create mode 100644 wrappers/golang/cuda_runtime/memory_test.go create mode 100644 wrappers/golang/cuda_runtime/stream.go create mode 100644 wrappers/golang/cuda_runtime/stream_test.go create mode 100644 wrappers/golang/cuda_runtime/types.go create mode 100644 wrappers/golang/curves/bls12377/base_field.go create mode 100644 wrappers/golang/curves/bls12377/base_field_test.go create mode 100644 wrappers/golang/curves/bls12377/bls12_377.go create mode 100644 wrappers/golang/curves/bls12377/curve.go create mode 100644 wrappers/golang/curves/bls12377/curve_test.go create mode 100644 wrappers/golang/curves/bls12377/g2_base_field.go create mode 100644 wrappers/golang/curves/bls12377/g2_base_field_test.go create mode 100644 wrappers/golang/curves/bls12377/g2_curve.go create mode 100644 wrappers/golang/curves/bls12377/g2_curve_test.go create mode 100644 wrappers/golang/curves/bls12377/g2_msm.go create mode 100644 wrappers/golang/curves/bls12377/g2_msm_test.go create mode 100644 wrappers/golang/curves/bls12377/helpers_test.go create mode 100644 wrappers/golang/curves/bls12377/include/curve.h create mode 100644 wrappers/golang/curves/bls12377/include/g2_curve.h create mode 100644 wrappers/golang/curves/bls12377/include/g2_msm.h create mode 100644 wrappers/golang/curves/bls12377/include/msm.h create mode 100644 wrappers/golang/curves/bls12377/include/ntt.h create mode 100644 wrappers/golang/curves/bls12377/include/scalar_field.h create mode 100644 wrappers/golang/curves/bls12377/msm.go create mode 100644 wrappers/golang/curves/bls12377/msm_test.go create mode 100644 wrappers/golang/curves/bls12377/ntt.go create mode 100644 wrappers/golang/curves/bls12377/ntt_test.go create mode 100644 wrappers/golang/curves/bls12377/scalar_field.go create mode 100644 wrappers/golang/curves/bls12377/scalar_field_test.go create mode 100644 wrappers/golang/curves/bls12381/base_field.go create mode 100644 wrappers/golang/curves/bls12381/base_field_test.go create mode 100644 wrappers/golang/curves/bls12381/bls12_381.go create mode 100644 wrappers/golang/curves/bls12381/curve.go create mode 100644 wrappers/golang/curves/bls12381/curve_test.go create mode 100644 wrappers/golang/curves/bls12381/g2_base_field.go create mode 100644 wrappers/golang/curves/bls12381/g2_base_field_test.go create mode 100644 wrappers/golang/curves/bls12381/g2_curve.go create mode 100644 wrappers/golang/curves/bls12381/g2_curve_test.go create mode 100644 wrappers/golang/curves/bls12381/g2_msm.go create mode 100644 wrappers/golang/curves/bls12381/g2_msm_test.go create mode 100644 wrappers/golang/curves/bls12381/helpers_test.go create mode 100644 wrappers/golang/curves/bls12381/include/curve.h create mode 100644 wrappers/golang/curves/bls12381/include/g2_curve.h create mode 100644 wrappers/golang/curves/bls12381/include/g2_msm.h create mode 100644 wrappers/golang/curves/bls12381/include/msm.h create mode 100644 wrappers/golang/curves/bls12381/include/ntt.h create mode 100644 wrappers/golang/curves/bls12381/include/scalar_field.h create mode 100644 wrappers/golang/curves/bls12381/msm.go create mode 100644 wrappers/golang/curves/bls12381/msm_test.go create mode 100644 wrappers/golang/curves/bls12381/ntt.go create mode 100644 wrappers/golang/curves/bls12381/ntt_test.go create mode 100644 wrappers/golang/curves/bls12381/scalar_field.go create mode 100644 wrappers/golang/curves/bls12381/scalar_field_test.go create mode 100644 wrappers/golang/curves/bn254/base_field.go create mode 100644 wrappers/golang/curves/bn254/base_field_test.go create mode 100644 wrappers/golang/curves/bn254/bn254.go create mode 100644 wrappers/golang/curves/bn254/curve.go create mode 100644 wrappers/golang/curves/bn254/curve_test.go create mode 100644 wrappers/golang/curves/bn254/g2_base_field.go create mode 100644 wrappers/golang/curves/bn254/g2_base_field_test.go create mode 100644 wrappers/golang/curves/bn254/g2_curve.go create mode 100644 wrappers/golang/curves/bn254/g2_curve_test.go create mode 100644 wrappers/golang/curves/bn254/g2_msm.go create mode 100644 wrappers/golang/curves/bn254/g2_msm_test.go create mode 100644 wrappers/golang/curves/bn254/helpers_test.go create mode 100644 wrappers/golang/curves/bn254/include/curve.h create mode 100644 wrappers/golang/curves/bn254/include/g2_curve.h create mode 100644 wrappers/golang/curves/bn254/include/g2_msm.h create mode 100644 wrappers/golang/curves/bn254/include/msm.h create mode 100644 wrappers/golang/curves/bn254/include/ntt.h create mode 100644 wrappers/golang/curves/bn254/include/scalar_field.h rename {goicicle => wrappers/golang}/curves/bn254/include/ve_mod_mult.h (54%) create mode 100644 wrappers/golang/curves/bn254/msm.go create mode 100644 wrappers/golang/curves/bn254/msm_test.go create mode 100644 wrappers/golang/curves/bn254/ntt.go create mode 100644 wrappers/golang/curves/bn254/ntt_test.go create mode 100644 wrappers/golang/curves/bn254/scalar_field.go create mode 100644 wrappers/golang/curves/bn254/scalar_field_test.go create mode 100644 wrappers/golang/curves/bw6761/base_field.go create mode 100644 wrappers/golang/curves/bw6761/base_field_test.go create mode 100644 wrappers/golang/curves/bw6761/bw6_761.go create mode 100644 wrappers/golang/curves/bw6761/curve.go create mode 100644 wrappers/golang/curves/bw6761/curve_test.go create mode 100644 wrappers/golang/curves/bw6761/g2_base_field.go create mode 100644 wrappers/golang/curves/bw6761/g2_base_field_test.go create mode 100644 wrappers/golang/curves/bw6761/g2_curve.go create mode 100644 wrappers/golang/curves/bw6761/g2_curve_test.go create mode 100644 wrappers/golang/curves/bw6761/g2_msm.go create mode 100644 wrappers/golang/curves/bw6761/g2_msm_test.go create mode 100644 wrappers/golang/curves/bw6761/helpers_test.go create mode 100644 wrappers/golang/curves/bw6761/include/curve.h create mode 100644 wrappers/golang/curves/bw6761/include/g2_curve.h create mode 100644 wrappers/golang/curves/bw6761/include/g2_msm.h create mode 100644 wrappers/golang/curves/bw6761/include/msm.h create mode 100644 wrappers/golang/curves/bw6761/include/ntt.h create mode 100644 wrappers/golang/curves/bw6761/include/scalar_field.h create mode 100644 wrappers/golang/curves/bw6761/msm.go create mode 100644 wrappers/golang/curves/bw6761/msm_test.go create mode 100644 wrappers/golang/curves/bw6761/ntt.go create mode 100644 wrappers/golang/curves/bw6761/ntt_test.go create mode 100644 wrappers/golang/curves/bw6761/scalar_field.go create mode 100644 wrappers/golang/curves/bw6761/scalar_field_test.go create mode 100644 wrappers/golang/curves/include/types.h create mode 100644 wrappers/golang/internal/generator/main.go create mode 100644 wrappers/golang/internal/generator/templates/curve.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/curve_test.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/field.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/field_test.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/helpers_test.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/include/curve.h.tmpl create mode 100644 wrappers/golang/internal/generator/templates/include/g2_curve.h.tmpl create mode 100644 wrappers/golang/internal/generator/templates/include/g2_msm.h.tmpl create mode 100644 wrappers/golang/internal/generator/templates/include/msm.h.tmpl create mode 100644 wrappers/golang/internal/generator/templates/include/ntt.h.tmpl create mode 100644 wrappers/golang/internal/generator/templates/include/scalar_field.h.tmpl create mode 100644 wrappers/golang/internal/generator/templates/include/vec_ops.h.tmpl create mode 100644 wrappers/golang/internal/generator/templates/main.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/msm.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/msm_test.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/ntt.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/ntt_test.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/scalar_field.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/scalar_field_test.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/vec_ops.go.tmpl create mode 100644 wrappers/golang/internal/generator/templates/vec_ops_test.go.tmpl diff --git a/.github/changed-files.yml b/.github/changed-files.yml index 47968a0f6..48f7aaf17 100644 --- a/.github/changed-files.yml +++ b/.github/changed-files.yml @@ -1,5 +1,7 @@ golang: - - goicicle/**/*.go' + - wrappers/golang/**/*.go' + - wrappers/golang/**/*.h' + - wrappers/golang/**/*.tmpl' - go.mod rust: - wrappers/rust diff --git a/.github/workflows/main-build.yml b/.github/workflows/main-build.yml index 688b663f1..b83de630e 100644 --- a/.github/workflows/main-build.yml +++ b/.github/workflows/main-build.yml @@ -80,18 +80,22 @@ jobs: # Building from the root workspace will build all members of the workspace by default run: cargo build --release --verbose - # TODO: Re-enable once Golang bindings for v1+ is finished - # build-golang-linux: - # name: Build Golang on Linux - # runs-on: [self-hosted, Linux, X64, icicle] - # needs: check-changed-files - # steps: - # - name: Checkout Repo - # uses: actions/checkout@v3 - # - name: Build CUDA libs - # if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' - # run: make all - # working-directory: ./goicicle + build-golang-linux: + name: Build Golang on Linux + runs-on: [self-hosted, Linux, X64, icicle] + needs: check-changed-files + strategy: + matrix: + curve: [bn254, bls12_381, bls12_377, bw6_761] + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + - name: Build CUDA libs + if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + working-directory: ./wrappers/golang + run: | + export CPATH=$CPATH:/usr/local/cuda/include + ./build.sh ${{ matrix.curve }} ON # TODO: Add once Golang make file supports building for Windows # build-golang-windows: diff --git a/.github/workflows/main-test.yml b/.github/workflows/main-test.yml index 48af10fa6..7479e8267 100644 --- a/.github/workflows/main-test.yml +++ b/.github/workflows/main-test.yml @@ -75,20 +75,25 @@ jobs: if: needs.check-changed-files.outputs.cpp_cuda == 'true' run: ctest - # TODO: Re-enable once Golang bindings for v1+ is finished - # test-golang-linux: - # name: Test Golang on Linux - # runs-on: [self-hosted, Linux, X64, icicle] - # needs: check-changed-files - # steps: - # - name: Checkout Repo - # uses: actions/checkout@v3 - # - name: Build CUDA libs - # working-directory: ./goicicle - # if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' - # run: make libbn254.so - # - name: Run Golang Tests - # if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' - # run: | - # export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/goicicle - # go test ./goicicle/curves/bn254 -count=1 + test-golang-linux: + name: Test Golang on Linux + runs-on: [self-hosted, Linux, X64, icicle] + needs: check-changed-files + # strategy: + # matrix: + # curve: [bn254, bls12_381, bls12_377, bw6_761] + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + - name: Build CUDA libs + working-directory: ./wrappers/golang + if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + # builds all curves with g2 ON + run: | + export CPATH=$CPATH:/usr/local/cuda/include + ./build.sh all ON + - name: Run Golang Tests + if: needs.check-changed-files.outputs.golang == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true' + run: | + export CPATH=$CPATH:/usr/local/cuda/include + go test --tags=g2 ./... -count=1 -timeout 60m diff --git a/README.md b/README.md index 9b4d2860e..1ae6b07d2 100644 --- a/README.md +++ b/README.md @@ -143,10 +143,10 @@ See [LICENSE-MIT][LMIT] for details. [GRANT_PROGRAM]: https://medium.com/@ingonyama/icicle-for-researchers-grants-challenges-9be1f040998e [ICICLE-CORE]: ./icicle/ [ICICLE-RUST]: ./wrappers/rust/ -[ICICLE-GO]: ./goicicle/ +[ICICLE-GO]: ./wrappers/golang/ [ICICLE-CORE-README]: ./icicle/README.md [ICICLE-RUST-README]: ./wrappers/rust/README.md -[ICICLE-GO-README]: ./goicicle/README.md +[ICICLE-GO-README]: ./wrappers/golang/README.md [documentation]: https://dev.ingonyama.com/icicle/overview [examples]: ./examples/ diff --git a/go.mod b/go.mod index ba0be9083..6fbe19010 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,19 @@ module github.com/ingonyama-zk/icicle go 1.20 require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/kr/pretty v0.1.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + github.com/consensys/gnark-crypto v0.12.1 + github.com/stretchr/testify v1.8.2 ) require ( - github.com/consensys/bavard v0.1.13 - github.com/stretchr/testify v1.8.3 + github.com/bits-and-blooms/bitset v1.7.0 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + golang.org/x/sys v0.9.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 5da2f0604..a3e38a8d1 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,37 @@ +github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHlV4j7NEo= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/goicicle/Makefile b/goicicle/Makefile deleted file mode 100644 index a12860cc0..000000000 --- a/goicicle/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -CUDA_ROOT_DIR = /usr/local/cuda -NVCC = $(CUDA_ROOT_DIR)/bin/nvcc -CFLAGS = -Xcompiler -fPIC -std=c++17 -LDFLAGS = -shared -FEATURES = -DG2_DEFINED - -TARGET_BN254 = libbn254.so -TARGET_BW6761 = libbw6761.so -TARGET_BLS12_381 = libbls12_381.so -TARGET_BLS12_377 = libbls12_377.so - -VPATH = ../icicle/curves/bn254:../icicle/curves/bls12_377:../icicle/curves/bls12_381:../icicle/curves/bw6_761 - -SRCS_BN254 = lde.cu msm.cu projective.cu ve_mod_mult.cu -SRCS_BW6761 = lde.cu msm.cu projective.cu ve_mod_mult.cu -SRCS_BLS12_381 = lde.cu msm.cu projective.cu ve_mod_mult.cu poseidon.cu -SRCS_BLS12_377 = lde.cu msm.cu projective.cu ve_mod_mult.cu - -all: $(TARGET_BN254) $(TARGET_BLS12_381) $(TARGET_BLS12_377) $(TARGET_BW6761) - -$(TARGET_BN254): - $(NVCC) $(FEATURES) $(CFLAGS) $(LDFLAGS) $(addprefix ../icicle/curves/bn254/, $(SRCS_BN254)) -o $@ - -$(TARGET_BW6761): - $(NVCC) $(FEATURES) $(CFLAGS) $(LDFLAGS) $(addprefix ../icicle/curves/bw6_761/, $(SRCS_BW6761)) -o $@ - -$(TARGET_BLS12_381): - $(NVCC) $(FEATURES) $(CFLAGS) $(LDFLAGS) $(addprefix ../icicle/curves/bls12_381/, $(SRCS_BLS12_381)) -o $@ - -$(TARGET_BLS12_377): - $(NVCC) $(FEATURES) $(CFLAGS) $(LDFLAGS) $(addprefix ../icicle/curves/bls12_377/, $(SRCS_BLS12_377)) -o $@ - -clean: - rm -f $(TARGET_BN254) $(TARGET_BLS12_381) $(TARGET_BLS12_377) $(TARGET_BW6761) diff --git a/goicicle/README.md b/goicicle/README.md deleted file mode 100644 index a3e5e007d..000000000 --- a/goicicle/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# Golang Bindings - -To build the shared library: - -To build shared libraries for all supported curves. - -``` -make all -``` - -If you wish to build for a specific curve, for example bn254. - -``` -make libbn254.so -``` - -The current supported options are `libbn254.so`, `libbls12_381.so`, `libbls12_377.so` and `libbw6_671.so`. The resulting `.so` files are the compiled shared libraries for each curve. - -Finally to allow your system to find the shared libraries - -``` -export LD_LIBRARY_PATH=$LD_LIBRARY_PATH/ -``` - -## Running golang tests - -To run the tests for curve bn254. - -``` -go test ./goicicle/curves/bn254 -count=1 -``` - -## Cleaning up - -If you want to remove the compiled files - -``` -make clean -``` - -This will remove all shared libraries generated from the `make` file. - -# How do Golang bindings work? - -The shared libraries produced from the CUDA code compilation are used to bind Golang to ICICLE's CUDA code. - -1. These shared libraries (`libbn254.so`, `libbls12_381.so`, `libbls12_377.so`, `libbw6_671.so`) can be imported in your Go project to leverage the GPU accelerated functionalities provided by ICICLE. - -2. In your Go project, you can use `cgo` to link these shared libraries. Here's a basic example on how you can use `cgo` to link these libraries: - -```go -/* -#cgo LDFLAGS: -L/path/to/shared/libs -lbn254 -lbls12_381 -lbls12_377 -lbw6_671 -#include "icicle.h" // make sure you use the correct header file(s) -*/ -import "C" - -func main() { - // Now you can call the C functions from the ICICLE libraries. - // Note that C function calls are prefixed with 'C.' in Go code. -} -``` - -Replace `/path/to/shared/libs` with the actual path where the shared libraries are located on your system. - -# Common issues - -### Cannot find shared library - -In some cases you may encounter the following error, despite exporting the correct `LD_LIBRARY_PATH`. - -``` -/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1 -/usr/bin/ld: cannot find -lbn254: No such file or directory -/usr/bin/ld: cannot find -lbn254: No such file or directory -/usr/bin/ld: cannot find -lbn254: No such file or directory -/usr/bin/ld: cannot find -lbn254: No such file or directory -/usr/bin/ld: cannot find -lbn254: No such file or directory -collect2: error: ld returned 1 exit status -``` - -This is normally fixed by exporting the path to the shared library location in the following way: `export CGO_LDFLAGS="-L//"` diff --git a/goicicle/curves/bls12377/g1.go b/goicicle/curves/bls12377/g1.go deleted file mode 100644 index a8dd5814e..000000000 --- a/goicicle/curves/bls12377/g1.go +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12377 - -import ( - "unsafe" - - "encoding/binary" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ -lbls12_377 -// #include "projective.h" -// #include "ve_mod_mult.h" -import "C" - -const SCALAR_SIZE = 8 -const BASE_SIZE = 12 - -type G1ScalarField struct { - S [SCALAR_SIZE]uint32 -} - -type G1BaseField struct { - S [BASE_SIZE]uint32 -} - -/* - * BaseField Constructors - */ - -func (f *G1BaseField) SetZero() *G1BaseField { - var S [BASE_SIZE]uint32 - f.S = S - - return f -} - -func (f *G1BaseField) SetOne() *G1BaseField { - var S [BASE_SIZE]uint32 - - S[0] = 1 - - f.S = S - return f -} - -func (p *G1ProjectivePoint) FromAffine(affine *G1PointAffine) *G1ProjectivePoint { - out := (*C.BLS12_377_projective_t)(unsafe.Pointer(p)) - in := (*C.BLS12_377_affine_t)(unsafe.Pointer(affine)) - - C.projective_from_affine_bls12_377(out, in) - - return p -} - -func (f *G1BaseField) FromLimbs(limbs [BASE_SIZE]uint32) *G1BaseField { - copy(f.S[:], limbs[:]) - - return f -} - -/* - * BaseField methods - */ - -func (f *G1BaseField) Limbs() [BASE_SIZE]uint32 { - return f.S -} - -func (f *G1BaseField) ToBytesLe() []byte { - bytes := make([]byte, len(f.S)*4) - for i, v := range f.S { - binary.LittleEndian.PutUint32(bytes[i*4:], v) - } - - return bytes -} - -/* - * ScalarField methods - */ - -func (p *G1ScalarField) Random() *G1ScalarField { - outC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(p)) - C.random_scalar_bls12_377(outC) - - return p -} - -func (f *G1ScalarField) SetZero() *G1ScalarField { - var S [SCALAR_SIZE]uint32 - f.S = S - - return f -} - -func (f *G1ScalarField) SetOne() *G1ScalarField { - var S [SCALAR_SIZE]uint32 - S[0] = 1 - f.S = S - - return f -} - -func (a *G1ScalarField) Eq(b *G1ScalarField) bool { - for i, v := range a.S { - if b.S[i] != v { - return false - } - } - return true -} - -/* - * ScalarField methods - */ - -func (f *G1ScalarField) Limbs() [SCALAR_SIZE]uint32 { - return f.S -} - -func (f *G1ScalarField) ToBytesLe() []byte { - bytes := make([]byte, len(f.S)*4) - for i, v := range f.S { - binary.LittleEndian.PutUint32(bytes[i*4:], v) - } - - return bytes -} - -/* - * PointBLS12_377 - */ - -type G1ProjectivePoint struct { - X, Y, Z G1BaseField -} - -func (f *G1ProjectivePoint) SetZero() *G1ProjectivePoint { - var yOne G1BaseField - yOne.SetOne() - - var xZero G1BaseField - xZero.SetZero() - - var zZero G1BaseField - zZero.SetZero() - - f.X = xZero - f.Y = yOne - f.Z = zZero - - return f -} - -func (p *G1ProjectivePoint) Eq(pCompare *G1ProjectivePoint) bool { - // Cast *PointBLS12_377 to *C.BLS12_377_projective_t - // The unsafe.Pointer cast is necessary because Go doesn't allow direct casts - // between different pointer types. - // It'S your responsibility to ensure that the types are compatible. - pC := (*C.BLS12_377_projective_t)(unsafe.Pointer(p)) - pCompareC := (*C.BLS12_377_projective_t)(unsafe.Pointer(pCompare)) - - // Call the C function - // The C function doesn't keep any references to the data, - // so it'S fine if the Go garbage collector moves or deletes the data later. - return bool(C.eq_bls12_377(pC, pCompareC)) -} - -func (p *G1ProjectivePoint) IsOnCurve() bool { - point := (*C.BLS12_377_projective_t)(unsafe.Pointer(p)) - res := C.projective_is_on_curve_bls12_377(point) - - return bool(res) -} - -func (p *G1ProjectivePoint) Random() *G1ProjectivePoint { - outC := (*C.BLS12_377_projective_t)(unsafe.Pointer(p)) - C.random_projective_bls12_377(outC) - - return p -} - -func (p *G1ProjectivePoint) StripZ() *G1PointAffine { - return &G1PointAffine{ - X: p.X, - Y: p.Y, - } -} - -func (p *G1ProjectivePoint) FromLimbs(x, y, z *[]uint32) *G1ProjectivePoint { - var _x G1BaseField - var _y G1BaseField - var _z G1BaseField - - _x.FromLimbs(GetFixedLimbs(x)) - _y.FromLimbs(GetFixedLimbs(y)) - _z.FromLimbs(GetFixedLimbs(z)) - - p.X = _x - p.Y = _y - p.Z = _z - - return p -} - -/* - * PointAffineNoInfinityBLS12_377 - */ - -type G1PointAffine struct { - X, Y G1BaseField -} - -func (p *G1PointAffine) FromProjective(projective *G1ProjectivePoint) *G1PointAffine { - in := (*C.BLS12_377_projective_t)(unsafe.Pointer(projective)) - out := (*C.BLS12_377_affine_t)(unsafe.Pointer(p)) - - C.projective_to_affine_bls12_377(out, in) - - return p -} - -func (p *G1PointAffine) ToProjective() *G1ProjectivePoint { - var Z G1BaseField - Z.SetOne() - - return &G1ProjectivePoint{ - X: p.X, - Y: p.Y, - Z: Z, - } -} - -func (p *G1PointAffine) FromLimbs(X, Y *[]uint32) *G1PointAffine { - var _x G1BaseField - var _y G1BaseField - - _x.FromLimbs(GetFixedLimbs(X)) - _y.FromLimbs(GetFixedLimbs(Y)) - - p.X = _x - p.Y = _y - - return p -} - -/* - * Multiplication - */ - -func MultiplyVec(a []G1ProjectivePoint, b []G1ScalarField, deviceID int) { - if len(a) != len(b) { - panic("a and b have different lengths") - } - - pointsC := (*C.BLS12_377_projective_t)(unsafe.Pointer(&a[0])) - scalarsC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&b[0])) - deviceIdC := C.size_t(deviceID) - nElementsC := C.size_t(len(a)) - - C.vec_mod_mult_point_bls12_377(pointsC, scalarsC, nElementsC, deviceIdC) -} - -func MultiplyScalar(a []G1ScalarField, b []G1ScalarField, deviceID int) { - if len(a) != len(b) { - panic("a and b have different lengths") - } - - aC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&a[0])) - bC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&b[0])) - deviceIdC := C.size_t(deviceID) - nElementsC := C.size_t(len(a)) - - C.vec_mod_mult_scalar_bls12_377(aC, bC, nElementsC, deviceIdC) -} - -// Multiply a matrix by a scalar: -// -// `a` - flattenned matrix; -// `b` - vector to multiply `a` by; -func MultiplyMatrix(a []G1ScalarField, b []G1ScalarField, deviceID int) { - c := make([]G1ScalarField, len(b)) - for i := range c { - var p G1ScalarField - p.SetZero() - - c[i] = p - } - - aC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&a[0])) - bC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&b[0])) - cC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&c[0])) - deviceIdC := C.size_t(deviceID) - nElementsC := C.size_t(len(a)) - - C.matrix_vec_mod_mult_bls12_377(aC, bC, cC, nElementsC, deviceIdC) -} - -/* - * Utils - */ - -func GetFixedLimbs(slice *[]uint32) [BASE_SIZE]uint32 { - if len(*slice) <= BASE_SIZE { - limbs := [BASE_SIZE]uint32{} - copy(limbs[:len(*slice)], *slice) - return limbs - } - - panic("slice has too many elements") -} diff --git a/goicicle/curves/bls12377/g1_test.go b/goicicle/curves/bls12377/g1_test.go deleted file mode 100644 index 949820144..000000000 --- a/goicicle/curves/bls12377/g1_test.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12377 - -import ( - "encoding/binary" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNewFieldBLS12_377One(t *testing.T) { - var oneField G1BaseField - oneField.SetOne() - - rawOneField := [8]uint32([8]uint32{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}) - - assert.Equal(t, oneField.S, rawOneField) -} - -func TestNewFieldBLS12_377Zero(t *testing.T) { - var zeroField G1BaseField - zeroField.SetZero() - - rawZeroField := [8]uint32([8]uint32{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}) - - assert.Equal(t, zeroField.S, rawZeroField) -} - -func TestFieldBLS12_377ToBytesLe(t *testing.T) { - var p G1ProjectivePoint - p.Random() - - expected := make([]byte, len(p.X.S)*4) // each uint32 takes 4 bytes - for i, v := range p.X.S { - binary.LittleEndian.PutUint32(expected[i*4:], v) - } - - assert.Equal(t, p.X.ToBytesLe(), expected) - assert.Equal(t, len(p.X.ToBytesLe()), 32) -} - -func TestNewPointBLS12_377Zero(t *testing.T) { - var pointZero G1ProjectivePoint - pointZero.SetZero() - - var baseOne G1BaseField - baseOne.SetOne() - - var zeroSanity G1BaseField - zeroSanity.SetZero() - - assert.Equal(t, pointZero.X, zeroSanity) - assert.Equal(t, pointZero.Y, baseOne) - assert.Equal(t, pointZero.Z, zeroSanity) -} - -func TestFromProjectiveToAffine(t *testing.T) { - var projective G1ProjectivePoint - var affine G1PointAffine - - projective.Random() - - affine.FromProjective(&projective) - var projective2 G1ProjectivePoint - projective2.FromAffine(&affine) - - assert.True(t, projective.IsOnCurve()) - assert.True(t, projective2.IsOnCurve()) - assert.True(t, projective.Eq(&projective2)) -} - -func TestBLS12_377Eq(t *testing.T) { - var p1 G1ProjectivePoint - p1.Random() - var p2 G1ProjectivePoint - p2.Random() - - assert.Equal(t, p1.Eq(&p1), true) - assert.Equal(t, p1.Eq(&p2), false) -} - -func TestBLS12_377StripZ(t *testing.T) { - var p1 G1ProjectivePoint - p1.Random() - - p2ZLess := p1.StripZ() - - assert.IsType(t, G1PointAffine{}, *p2ZLess) - assert.Equal(t, p1.X, p2ZLess.X) - assert.Equal(t, p1.Y, p2ZLess.Y) -} - -func TestPointBLS12_377fromLimbs(t *testing.T) { - var p G1ProjectivePoint - p.Random() - - x := p.X.Limbs() - y := p.Y.Limbs() - z := p.Z.Limbs() - - xSlice := x[:] - ySlice := y[:] - zSlice := z[:] - - var pFromLimbs G1ProjectivePoint - pFromLimbs.FromLimbs(&xSlice, &ySlice, &zSlice) - - assert.Equal(t, pFromLimbs, p) -} - -func TestNewPointAffineNoInfinityBLS12_377Zero(t *testing.T) { - var zeroP G1PointAffine - - var zeroSanity G1BaseField - zeroSanity.SetZero() - - assert.Equal(t, zeroP.X, zeroSanity) - assert.Equal(t, zeroP.Y, zeroSanity) -} - -func TestPointAffineNoInfinityBLS12_377FromLimbs(t *testing.T) { - // Initialize your test values - x := [12]uint32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} - y := [12]uint32{9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} - xSlice := x[:] - ySlice := y[:] - - // Execute your function - var result G1PointAffine - result.FromLimbs(&xSlice, &ySlice) - - var xBase G1BaseField - var yBase G1BaseField - xBase.FromLimbs(x) - yBase.FromLimbs(y) - - // Define your expected result - expected := G1PointAffine{ - X: xBase, - Y: yBase, - } - - // Test if result is as expected - assert.Equal(t, expected, result) -} - -func TestGetFixedLimbs(t *testing.T) { - t.Run("case of valid input of length less than 8", func(t *testing.T) { - slice := []uint32{1, 2, 3, 4, 5, 6, 7} - expected := [8]uint32{1, 2, 3, 4, 5, 6, 7, 0} - - result := GetFixedLimbs(&slice) - assert.Equal(t, result, expected) - }) - - t.Run("case of valid input of length 8", func(t *testing.T) { - slice := []uint32{1, 2, 3, 4, 5, 6, 7, 8} - expected := [8]uint32{1, 2, 3, 4, 5, 6, 7, 8} - - result := GetFixedLimbs(&slice) - assert.Equal(t, result, expected) - }) - - t.Run("case of empty input", func(t *testing.T) { - slice := []uint32{} - expected := [8]uint32{0, 0, 0, 0, 0, 0, 0, 0} - - result := GetFixedLimbs(&slice) - assert.Equal(t, result, expected) - }) - - t.Run("case of input length greater than 8", func(t *testing.T) { - slice := []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9} - - defer func() { - if r := recover(); r == nil { - t.Errorf("the code did not panic") - } - }() - - GetFixedLimbs(&slice) - }) -} diff --git a/goicicle/curves/bls12377/g2.go b/goicicle/curves/bls12377/g2.go deleted file mode 100644 index 837354719..000000000 --- a/goicicle/curves/bls12377/g2.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12377 - -import ( - "encoding/binary" - "unsafe" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ -lbls12_377 -// #include "projective.h" -// #include "ve_mod_mult.h" -import "C" - -// G2 extension field - -type G2Element [6]uint64 - -type ExtentionField struct { - A0, A1 G2Element -} - -type G2PointAffine struct { - X, Y ExtentionField -} - -type G2Point struct { - X, Y, Z ExtentionField -} - -func (p *G2Point) Random() *G2Point { - outC := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(p)) - C.random_g2_projective_bls12_377(outC) - - return p -} - -func (p *G2Point) FromAffine(affine *G2PointAffine) *G2Point { - out := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(p)) - in := (*C.BLS12_377_g2_affine_t)(unsafe.Pointer(affine)) - - C.g2_projective_from_affine_bls12_377(out, in) - - return p -} - -func (p *G2Point) Eq(pCompare *G2Point) bool { - // Cast *PointBLS12_377 to *C.BLS12_377_projective_t - // The unsafe.Pointer cast is necessary because Go doesn't allow direct casts - // between different pointer types. - // It's your responsibility to ensure that the types are compatible. - pC := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(p)) - pCompareC := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(pCompare)) - - // Call the C function - // The C function doesn't keep any references to the data, - // so it's fine if the Go garbage collector moves or deletes the data later. - return bool(C.eq_g2_bls12_377(pC, pCompareC)) -} - -func (f *G2Element) ToBytesLe() []byte { - var bytes []byte - for _, val := range f { - buf := make([]byte, 8) // 8 bytes because uint64 is 64-bit - binary.LittleEndian.PutUint64(buf, val) - bytes = append(bytes, buf...) - } - return bytes -} - -func (p *G2PointAffine) FromProjective(projective *G2Point) *G2PointAffine { - out := (*C.BLS12_377_g2_affine_t)(unsafe.Pointer(p)) - in := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(projective)) - - C.g2_projective_to_affine_bls12_377(out, in) - - return p -} - -func (p *G2Point) IsOnCurve() bool { - // Directly copy memory from the C struct to the Go struct - point := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(p)) - res := C.g2_projective_is_on_curve_bls12_377(point) - - return bool(res) -} diff --git a/goicicle/curves/bls12377/g2_test.go b/goicicle/curves/bls12377/g2_test.go deleted file mode 100644 index f6652c9e9..000000000 --- a/goicicle/curves/bls12377/g2_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12377 - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestG2Eqg2(t *testing.T) { - var point G2Point - - point.Random() - - assert.True(t, point.Eq(&point)) -} - -func TestG2FromProjectiveToAffine(t *testing.T) { - var projective G2Point - projective.Random() - - var affine G2PointAffine - affine.FromProjective(&projective) - - var projective2 G2Point - projective2.FromAffine(&affine) - - assert.True(t, projective.IsOnCurve()) - assert.True(t, projective2.IsOnCurve()) - assert.True(t, projective.Eq(&projective2)) -} - -func TestG2Eqg2NotEqual(t *testing.T) { - var point G2Point - point.Random() - - var point2 G2Point - point2.Random() - - assert.False(t, point.Eq(&point2)) -} - -func TestG2ToBytes(t *testing.T) { - element := G2Element{0x6546098ea84b6298, 0x4a384533d1f68aca, 0xaa0666972d771336, 0x1569e4a34321993} - bytes := element.ToBytesLe() - - assert.Equal(t, bytes, []byte{0x98, 0x62, 0x4b, 0xa8, 0x8e, 0x9, 0x46, 0x65, 0xca, 0x8a, 0xf6, 0xd1, 0x33, 0x45, 0x38, 0x4a, 0x36, 0x13, 0x77, 0x2d, 0x97, 0x66, 0x6, 0xaa, 0x93, 0x19, 0x32, 0x34, 0x4a, 0x9e, 0x56, 0x1}) -} - -func TestG2ShouldConvertToProjective(t *testing.T) { - fmt.Print() // this prevents the test from hanging. TODO: figure out why - var pointProjective G2Point - pointProjective.Random() - - var pointAffine G2PointAffine - pointAffine.FromProjective(&pointProjective) - - var proj G2Point - proj.FromAffine(&pointAffine) - - assert.True(t, proj.IsOnCurve()) - assert.True(t, pointProjective.Eq(&proj)) -} diff --git a/goicicle/curves/bls12377/include/msm.h b/goicicle/curves/bls12377/include/msm.h deleted file mode 100644 index b9de09a86..000000000 --- a/goicicle/curves/bls12377/include/msm.h +++ /dev/null @@ -1,98 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -#include -// msm.h - -#ifndef _BLS12_377_MSM_H -#define _BLS12_377_MSM_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BLS12_377 projective and affine structs -typedef struct BLS12_377_projective_t BLS12_377_projective_t; -typedef struct BLS12_377_g2_projective_t BLS12_377_g2_projective_t; -typedef struct BLS12_377_affine_t BLS12_377_affine_t; -typedef struct BLS12_377_g2_affine_t BLS12_377_g2_affine_t; -typedef struct BLS12_377_scalar_t BLS12_377_scalar_t; -typedef cudaStream_t CudaStream_t; - -int msm_cuda_bls12_377( - BLS12_377_projective_t* out, BLS12_377_affine_t* points, BLS12_377_scalar_t* scalars, size_t count, size_t device_id); - -int msm_batch_cuda_bls12_377( - BLS12_377_projective_t* out, - BLS12_377_affine_t* points, - BLS12_377_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); - -int commit_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_scalar_t* d_scalars, - BLS12_377_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); - -int commit_batch_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_scalar_t* d_scalars, - BLS12_377_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id); - -int msm_g2_cuda_bls12_377( - BLS12_377_g2_projective_t* out, - BLS12_377_g2_affine_t* points, - BLS12_377_scalar_t* scalars, - size_t count, - size_t device_id); -int msm_batch_g2_cuda_bls12_377( - BLS12_377_g2_projective_t* out, - BLS12_377_g2_affine_t* points, - BLS12_377_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); -int commit_g2_cuda_bls12_377( - BLS12_377_g2_projective_t* d_out, - BLS12_377_scalar_t* d_scalars, - BLS12_377_g2_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); -int commit_batch_g2_cuda_bls12_377( - BLS12_377_g2_projective_t* d_out, - BLS12_377_scalar_t* d_scalars, - BLS12_377_g2_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id, - cudaStream_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BLS12_377_MSM_H */ diff --git a/goicicle/curves/bls12377/include/ntt.h b/goicicle/curves/bls12377/include/ntt.h deleted file mode 100644 index d897ddebc..000000000 --- a/goicicle/curves/bls12377/include/ntt.h +++ /dev/null @@ -1,195 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// ntt.h - -#ifndef _BLS12_377_NTT_H -#define _BLS12_377_NTT_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BLS12_377 projective and affine structs -typedef struct BLS12_377_projective_t BLS12_377_projective_t; -typedef struct BLS12_377_affine_t BLS12_377_affine_t; -typedef struct BLS12_377_scalar_t BLS12_377_scalar_t; - -typedef struct BLS12_377_g2_projective_t BLS12_377_g2_projective_t; -typedef struct BLS12_377_g2_affine_t BLS12_377_g2_affine_t; - -int ntt_cuda_bls12_377(BLS12_377_scalar_t* arr, uint32_t n, bool inverse, size_t device_id); -int ntt_batch_cuda_bls12_377( - BLS12_377_scalar_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -int ecntt_cuda_bls12_377(BLS12_377_projective_t* arr, uint32_t n, bool inverse, size_t device_id); -int ecntt_batch_cuda_bls12_377( - BLS12_377_projective_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -BLS12_377_scalar_t* -build_domain_cuda_bls12_377(uint32_t domain_size, uint32_t logn, bool inverse, size_t device_id, size_t stream); -int interpolate_scalars_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_evaluations, - BLS12_377_scalar_t* d_domain, - unsigned n, - unsigned device_id, - size_t stream); -int interpolate_scalars_batch_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_evaluations, - BLS12_377_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_points_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_projective_t* d_evaluations, - BLS12_377_scalar_t* d_domain, - unsigned n, - size_t device_id, - size_t stream); -int interpolate_points_batch_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_projective_t* d_evaluations, - BLS12_377_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_scalars_on_coset_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_evaluations, - BLS12_377_scalar_t* d_domain, - unsigned n, - BLS12_377_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int interpolate_scalars_batch_on_coset_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_evaluations, - BLS12_377_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - BLS12_377_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_scalars_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned device_id, - size_t stream); -int evaluate_scalars_batch_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_points_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_projective_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - size_t device_id, - size_t stream); -int evaluate_points_batch_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_projective_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_scalars_on_coset_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BLS12_377_scalar_t* coset_powers, - unsigned device_id, - size_t stream); -int evaluate_scalars_on_coset_batch_cuda_bls12_377( - BLS12_377_scalar_t* d_out, - BLS12_377_scalar_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BLS12_377_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_projective_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BLS12_377_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_batch_cuda_bls12_377( - BLS12_377_projective_t* d_out, - BLS12_377_projective_t* d_coefficients, - BLS12_377_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BLS12_377_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int reverse_order_scalars_cuda_bls12_377(BLS12_377_scalar_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_scalars_batch_cuda_bls12_377( - BLS12_377_scalar_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int reverse_order_points_cuda_bls12_377(BLS12_377_projective_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_points_batch_cuda_bls12_377( - BLS12_377_projective_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int add_scalars_cuda_bls12_377( - BLS12_377_scalar_t* d_out, BLS12_377_scalar_t* d_in1, BLS12_377_scalar_t* d_in2, unsigned n, size_t stream); -int sub_scalars_cuda_bls12_377( - BLS12_377_scalar_t* d_out, BLS12_377_scalar_t* d_in1, BLS12_377_scalar_t* d_in2, unsigned n, size_t stream); -int to_montgomery_scalars_cuda_bls12_377(BLS12_377_scalar_t* d_inout, unsigned n, size_t stream); -int from_montgomery_scalars_cuda_bls12_377(BLS12_377_scalar_t* d_inout, unsigned n, size_t stream); - -// points g1 -int to_montgomery_proj_points_cuda_bls12_377(BLS12_377_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_cuda_bls12_377(BLS12_377_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_cuda_bls12_377(BLS12_377_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_cuda_bls12_377(BLS12_377_affine_t* d_inout, unsigned n, size_t stream); - -// points g2 -int to_montgomery_proj_points_g2_cuda_bls12_377(BLS12_377_g2_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_g2_cuda_bls12_377(BLS12_377_g2_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_g2_cuda_bls12_377(BLS12_377_g2_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_g2_cuda_bls12_377(BLS12_377_g2_affine_t* d_inout, unsigned n, size_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BLS12_377_NTT_H */ diff --git a/goicicle/curves/bls12377/include/projective.h b/goicicle/curves/bls12377/include/projective.h deleted file mode 100644 index 7eddf2ccd..000000000 --- a/goicicle/curves/bls12377/include/projective.h +++ /dev/null @@ -1,50 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// projective.h - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BLS12_377_projective_t BLS12_377_projective_t; -typedef struct BLS12_377_g2_projective_t BLS12_377_g2_projective_t; -typedef struct BLS12_377_affine_t BLS12_377_affine_t; -typedef struct BLS12_377_g2_affine_t BLS12_377_g2_affine_t; -typedef struct BLS12_377_scalar_t BLS12_377_scalar_t; - -bool projective_is_on_curve_bls12_377(BLS12_377_projective_t* point1); - -int random_scalar_bls12_377(BLS12_377_scalar_t* out); -int random_projective_bls12_377(BLS12_377_projective_t* out); -BLS12_377_projective_t* projective_zero_bls12_377(); -int projective_to_affine_bls12_377(BLS12_377_affine_t* out, BLS12_377_projective_t* point1); -int projective_from_affine_bls12_377(BLS12_377_projective_t* out, BLS12_377_affine_t* point1); - -int random_g2_projective_bls12_377(BLS12_377_g2_projective_t* out); -int g2_projective_to_affine_bls12_377(BLS12_377_g2_affine_t* out, BLS12_377_g2_projective_t* point1); -int g2_projective_from_affine_bls12_377(BLS12_377_g2_projective_t* out, BLS12_377_g2_affine_t* point1); -bool g2_projective_is_on_curve_bls12_377(BLS12_377_g2_projective_t* point1); - -bool eq_bls12_377(BLS12_377_projective_t* point1, BLS12_377_projective_t* point2); -bool eq_g2_bls12_377(BLS12_377_g2_projective_t* point1, BLS12_377_g2_projective_t* point2); - -#ifdef __cplusplus -} -#endif diff --git a/goicicle/curves/bls12377/include/ve_mod_mult.h b/goicicle/curves/bls12377/include/ve_mod_mult.h deleted file mode 100644 index b1cccf89a..000000000 --- a/goicicle/curves/bls12377/include/ve_mod_mult.h +++ /dev/null @@ -1,49 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// ve_mod_mult.h - -#ifndef _BLS12_377_VEC_MULT_H -#define _BLS12_377_VEC_MULT_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BLS12_377_projective_t BLS12_377_projective_t; -typedef struct BLS12_377_scalar_t BLS12_377_scalar_t; - -int32_t vec_mod_mult_point_bls12_377( - BLS12_377_projective_t* inout, BLS12_377_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_scalar_bls12_377( - BLS12_377_scalar_t* inout, BLS12_377_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_device_scalar_bls12_377( - BLS12_377_scalar_t* inout, BLS12_377_scalar_t* scalar_vec, size_t n_elements, size_t device_id); -int32_t matrix_vec_mod_mult_bls12_377( - BLS12_377_scalar_t* matrix_flattened, - BLS12_377_scalar_t* input, - BLS12_377_scalar_t* output, - size_t n_elments, - size_t device_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _BLS12_377_VEC_MULT_H */ diff --git a/goicicle/curves/bls12377/msm.go b/goicicle/curves/bls12377/msm.go deleted file mode 100644 index da617de45..000000000 --- a/goicicle/curves/bls12377/msm.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12377 - -import ( - "errors" - "fmt" - "unsafe" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ -lbls12_377 -// #include "msm.h" -import "C" - -func Msm(out *G1ProjectivePoint, points []G1PointAffine, scalars []G1ScalarField, device_id int) (*G1ProjectivePoint, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BLS12_377_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BLS12_377_projective_t)(unsafe.Pointer(out)) - ret := C.msm_cuda_bls12_377(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_cuda_bls12_377 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2(out *G2Point, points []G2PointAffine, scalars []G1ScalarField, device_id int) (*G2Point, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BLS12_377_g2_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(out)) - - ret := C.msm_g2_cuda_bls12_377(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_g2_cuda_bls12_377 returned error code: %d", ret) - } - - return out, nil -} - -func MsmBatch(points *[]G1PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G1ProjectivePoint, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G1ProjectivePoint, batchSize) - - for i := 0; i < len(out); i++ { - var p G1ProjectivePoint - p.SetZero() - - out[i] = p - } - - outC := (*C.BLS12_377_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BLS12_377_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_cuda_bls12_377(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bls12_377 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2Batch(points *[]G2PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G2Point, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G2Point, batchSize) - - outC := (*C.BLS12_377_g2_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BLS12_377_g2_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BLS12_377_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_g2_cuda_bls12_377(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bls12_377 returned error code: %d", ret) - } - - return out, nil -} - -func Commit(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BLS12_377_projective_t)(d_out) - scalarsC := (*C.BLS12_377_scalar_t)(d_scalars) - pointsC := (*C.BLS12_377_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_cuda_bls12_377(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BLS12_377_g2_projective_t)(d_out) - scalarsC := (*C.BLS12_377_scalar_t)(d_scalars) - pointsC := (*C.BLS12_377_g2_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_g2_cuda_bls12_377(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitBatch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BLS12_377_projective_t)(d_out) - scalarsC := (*C.BLS12_377_scalar_t)(d_scalars) - pointsC := (*C.BLS12_377_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.commit_batch_cuda_bls12_377(d_outC, scalarsC, pointsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2Batch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BLS12_377_g2_projective_t)(d_out) - scalarsC := (*C.BLS12_377_scalar_t)(d_scalars) - pointsC := (*C.BLS12_377_g2_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.msm_batch_g2_cuda_bls12_377(d_outC, pointsC, scalarsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} diff --git a/goicicle/curves/bls12377/msm_test.go b/goicicle/curves/bls12377/msm_test.go deleted file mode 100644 index 6382c755c..000000000 --- a/goicicle/curves/bls12377/msm_test.go +++ /dev/null @@ -1,360 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12377 - -import ( - "fmt" - "math" - "testing" - "time" - "unsafe" - - "github.com/ingonyama-zk/icicle/goicicle" - "github.com/stretchr/testify/assert" -) - -func GeneratePoints(count int) []G1PointAffine { - // Declare a slice of integers - var points []G1PointAffine - - // populate the slice - for i := 0; i < 10; i++ { - var pointProjective G1ProjectivePoint - pointProjective.Random() - - var pointAffine G1PointAffine - pointAffine.FromProjective(&pointProjective) - - points = append(points, pointAffine) - } - - log2_10 := math.Log2(10) - log2Count := math.Log2(float64(count)) - log2Size := int(math.Ceil(log2Count - log2_10)) - - for i := 0; i < log2Size; i++ { - points = append(points, points...) - } - - return points[:count] -} - -func GeneratePointsProj(count int) []G1ProjectivePoint { - // Declare a slice of integers - var points []G1ProjectivePoint - // Use a loop to populate the slice - for i := 0; i < count; i++ { - var p G1ProjectivePoint - p.Random() - - points = append(points, p) - } - - return points -} - -func GenerateScalars(count int, skewed bool) []G1ScalarField { - // Declare a slice of integers - var scalars []G1ScalarField - - var rand G1ScalarField - var zero G1ScalarField - var one G1ScalarField - var randLarge G1ScalarField - - zero.SetZero() - one.SetOne() - randLarge.Random() - - if skewed && count > 1_200_000 { - for i := 0; i < count-1_200_000; i++ { - rand.Random() - scalars = append(scalars, rand) - } - - for i := 0; i < 600_000; i++ { - scalars = append(scalars, randLarge) - } - for i := 0; i < 400_000; i++ { - scalars = append(scalars, zero) - } - for i := 0; i < 200_000; i++ { - scalars = append(scalars, one) - } - } else { - for i := 0; i < count; i++ { - rand.Random() - scalars = append(scalars, rand) - } - } - - return scalars[:count] -} - -func TestMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1 << v - - points := GeneratePoints(count) - fmt.Print("Finished generating points\n") - scalars := GenerateScalars(count, false) - fmt.Print("Finished generating scalars\n") - - out := new(G1ProjectivePoint) - startTime := time.Now() - _, e := Msm(out, points, scalars, 0) // non mont - fmt.Printf("icicle MSM took: %d ms\n", time.Since(startTime).Milliseconds()) - - assert.Equal(t, e, nil, "error should be nil") - - assert.True(t, out.IsOnCurve()) - } -} - -func TestCommitMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1< -#include -#include -// msm.h - -#ifndef _BLS12_381_MSM_H -#define _BLS12_381_MSM_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BLS12_381 projective and affine structs -typedef struct BLS12_381_projective_t BLS12_381_projective_t; -typedef struct BLS12_381_g2_projective_t BLS12_381_g2_projective_t; -typedef struct BLS12_381_affine_t BLS12_381_affine_t; -typedef struct BLS12_381_g2_affine_t BLS12_381_g2_affine_t; -typedef struct BLS12_381_scalar_t BLS12_381_scalar_t; -typedef cudaStream_t CudaStream_t; - -int msm_cuda_bls12_381( - BLS12_381_projective_t* out, BLS12_381_affine_t* points, BLS12_381_scalar_t* scalars, size_t count, size_t device_id); - -int msm_batch_cuda_bls12_381( - BLS12_381_projective_t* out, - BLS12_381_affine_t* points, - BLS12_381_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); - -int commit_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_scalar_t* d_scalars, - BLS12_381_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); - -int commit_batch_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_scalar_t* d_scalars, - BLS12_381_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id); - -int msm_g2_cuda_bls12_381( - BLS12_381_g2_projective_t* out, - BLS12_381_g2_affine_t* points, - BLS12_381_scalar_t* scalars, - size_t count, - size_t device_id); -int msm_batch_g2_cuda_bls12_381( - BLS12_381_g2_projective_t* out, - BLS12_381_g2_affine_t* points, - BLS12_381_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); -int commit_g2_cuda_bls12_381( - BLS12_381_g2_projective_t* d_out, - BLS12_381_scalar_t* d_scalars, - BLS12_381_g2_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); -int commit_batch_g2_cuda_bls12_381( - BLS12_381_g2_projective_t* d_out, - BLS12_381_scalar_t* d_scalars, - BLS12_381_g2_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id, - cudaStream_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BLS12_381_MSM_H */ diff --git a/goicicle/curves/bls12381/include/ntt.h b/goicicle/curves/bls12381/include/ntt.h deleted file mode 100644 index 50568c773..000000000 --- a/goicicle/curves/bls12381/include/ntt.h +++ /dev/null @@ -1,195 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// ntt.h - -#ifndef _BLS12_381_NTT_H -#define _BLS12_381_NTT_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BLS12_381 projective and affine structs -typedef struct BLS12_381_projective_t BLS12_381_projective_t; -typedef struct BLS12_381_affine_t BLS12_381_affine_t; -typedef struct BLS12_381_scalar_t BLS12_381_scalar_t; - -typedef struct BLS12_381_g2_projective_t BLS12_381_g2_projective_t; -typedef struct BLS12_381_g2_affine_t BLS12_381_g2_affine_t; - -int ntt_cuda_bls12_381(BLS12_381_scalar_t* arr, uint32_t n, bool inverse, size_t device_id); -int ntt_batch_cuda_bls12_381( - BLS12_381_scalar_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -int ecntt_cuda_bls12_381(BLS12_381_projective_t* arr, uint32_t n, bool inverse, size_t device_id); -int ecntt_batch_cuda_bls12_381( - BLS12_381_projective_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -BLS12_381_scalar_t* -build_domain_cuda_bls12_381(uint32_t domain_size, uint32_t logn, bool inverse, size_t device_id, size_t stream); -int interpolate_scalars_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_evaluations, - BLS12_381_scalar_t* d_domain, - unsigned n, - unsigned device_id, - size_t stream); -int interpolate_scalars_batch_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_evaluations, - BLS12_381_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_points_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_projective_t* d_evaluations, - BLS12_381_scalar_t* d_domain, - unsigned n, - size_t device_id, - size_t stream); -int interpolate_points_batch_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_projective_t* d_evaluations, - BLS12_381_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_scalars_on_coset_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_evaluations, - BLS12_381_scalar_t* d_domain, - unsigned n, - BLS12_381_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int interpolate_scalars_batch_on_coset_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_evaluations, - BLS12_381_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - BLS12_381_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_scalars_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned device_id, - size_t stream); -int evaluate_scalars_batch_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_points_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_projective_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - size_t device_id, - size_t stream); -int evaluate_points_batch_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_projective_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_scalars_on_coset_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BLS12_381_scalar_t* coset_powers, - unsigned device_id, - size_t stream); -int evaluate_scalars_on_coset_batch_cuda_bls12_381( - BLS12_381_scalar_t* d_out, - BLS12_381_scalar_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BLS12_381_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_projective_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BLS12_381_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_batch_cuda_bls12_381( - BLS12_381_projective_t* d_out, - BLS12_381_projective_t* d_coefficients, - BLS12_381_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BLS12_381_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int reverse_order_scalars_cuda_bls12_381(BLS12_381_scalar_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_scalars_batch_cuda_bls12_381( - BLS12_381_scalar_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int reverse_order_points_cuda_bls12_381(BLS12_381_projective_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_points_batch_cuda_bls12_381( - BLS12_381_projective_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int add_scalars_cuda_bls12_381( - BLS12_381_scalar_t* d_out, BLS12_381_scalar_t* d_in1, BLS12_381_scalar_t* d_in2, unsigned n, size_t stream); -int sub_scalars_cuda_bls12_381( - BLS12_381_scalar_t* d_out, BLS12_381_scalar_t* d_in1, BLS12_381_scalar_t* d_in2, unsigned n, size_t stream); -int to_montgomery_scalars_cuda_bls12_381(BLS12_381_scalar_t* d_inout, unsigned n, size_t stream); -int from_montgomery_scalars_cuda_bls12_381(BLS12_381_scalar_t* d_inout, unsigned n, size_t stream); - -// points g1 -int to_montgomery_proj_points_cuda_bls12_381(BLS12_381_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_cuda_bls12_381(BLS12_381_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_cuda_bls12_381(BLS12_381_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_cuda_bls12_381(BLS12_381_affine_t* d_inout, unsigned n, size_t stream); - -// points g2 -int to_montgomery_proj_points_g2_cuda_bls12_381(BLS12_381_g2_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_g2_cuda_bls12_381(BLS12_381_g2_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_g2_cuda_bls12_381(BLS12_381_g2_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_g2_cuda_bls12_381(BLS12_381_g2_affine_t* d_inout, unsigned n, size_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BLS12_381_NTT_H */ diff --git a/goicicle/curves/bls12381/include/projective.h b/goicicle/curves/bls12381/include/projective.h deleted file mode 100644 index b95833ab7..000000000 --- a/goicicle/curves/bls12381/include/projective.h +++ /dev/null @@ -1,50 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// projective.h - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BLS12_381_projective_t BLS12_381_projective_t; -typedef struct BLS12_381_g2_projective_t BLS12_381_g2_projective_t; -typedef struct BLS12_381_affine_t BLS12_381_affine_t; -typedef struct BLS12_381_g2_affine_t BLS12_381_g2_affine_t; -typedef struct BLS12_381_scalar_t BLS12_381_scalar_t; - -bool projective_is_on_curve_bls12_381(BLS12_381_projective_t* point1); - -int random_scalar_bls12_381(BLS12_381_scalar_t* out); -int random_projective_bls12_381(BLS12_381_projective_t* out); -BLS12_381_projective_t* projective_zero_bls12_381(); -int projective_to_affine_bls12_381(BLS12_381_affine_t* out, BLS12_381_projective_t* point1); -int projective_from_affine_bls12_381(BLS12_381_projective_t* out, BLS12_381_affine_t* point1); - -int random_g2_projective_bls12_381(BLS12_381_g2_projective_t* out); -int g2_projective_to_affine_bls12_381(BLS12_381_g2_affine_t* out, BLS12_381_g2_projective_t* point1); -int g2_projective_from_affine_bls12_381(BLS12_381_g2_projective_t* out, BLS12_381_g2_affine_t* point1); -bool g2_projective_is_on_curve_bls12_381(BLS12_381_g2_projective_t* point1); - -bool eq_bls12_381(BLS12_381_projective_t* point1, BLS12_381_projective_t* point2); -bool eq_g2_bls12_381(BLS12_381_g2_projective_t* point1, BLS12_381_g2_projective_t* point2); - -#ifdef __cplusplus -} -#endif diff --git a/goicicle/curves/bls12381/include/ve_mod_mult.h b/goicicle/curves/bls12381/include/ve_mod_mult.h deleted file mode 100644 index 20eb5ad1b..000000000 --- a/goicicle/curves/bls12381/include/ve_mod_mult.h +++ /dev/null @@ -1,49 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// ve_mod_mult.h - -#ifndef _BLS12_381_VEC_MULT_H -#define _BLS12_381_VEC_MULT_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BLS12_381_projective_t BLS12_381_projective_t; -typedef struct BLS12_381_scalar_t BLS12_381_scalar_t; - -int32_t vec_mod_mult_point_bls12_381( - BLS12_381_projective_t* inout, BLS12_381_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_scalar_bls12_381( - BLS12_381_scalar_t* inout, BLS12_381_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_device_scalar_bls12_381( - BLS12_381_scalar_t* inout, BLS12_381_scalar_t* scalar_vec, size_t n_elements, size_t device_id); -int32_t matrix_vec_mod_mult_bls12_381( - BLS12_381_scalar_t* matrix_flattened, - BLS12_381_scalar_t* input, - BLS12_381_scalar_t* output, - size_t n_elments, - size_t device_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _BLS12_381_VEC_MULT_H */ diff --git a/goicicle/curves/bls12381/msm.go b/goicicle/curves/bls12381/msm.go deleted file mode 100644 index 726957102..000000000 --- a/goicicle/curves/bls12381/msm.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12381 - -import ( - "errors" - "fmt" - "unsafe" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ -lbls12_381 -// #include "msm.h" -import "C" - -func Msm(out *G1ProjectivePoint, points []G1PointAffine, scalars []G1ScalarField, device_id int) (*G1ProjectivePoint, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BLS12_381_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BLS12_381_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BLS12_381_projective_t)(unsafe.Pointer(out)) - ret := C.msm_cuda_bls12_381(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_cuda_bls12_381 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2(out *G2Point, points []G2PointAffine, scalars []G1ScalarField, device_id int) (*G2Point, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BLS12_381_g2_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BLS12_381_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BLS12_381_g2_projective_t)(unsafe.Pointer(out)) - - ret := C.msm_g2_cuda_bls12_381(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_g2_cuda_bls12_381 returned error code: %d", ret) - } - - return out, nil -} - -func MsmBatch(points *[]G1PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G1ProjectivePoint, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G1ProjectivePoint, batchSize) - - for i := 0; i < len(out); i++ { - var p G1ProjectivePoint - p.SetZero() - - out[i] = p - } - - outC := (*C.BLS12_381_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BLS12_381_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BLS12_381_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_cuda_bls12_381(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bls12_381 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2Batch(points *[]G2PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G2Point, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G2Point, batchSize) - - outC := (*C.BLS12_381_g2_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BLS12_381_g2_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BLS12_381_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_g2_cuda_bls12_381(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bls12_381 returned error code: %d", ret) - } - - return out, nil -} - -func Commit(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BLS12_381_projective_t)(d_out) - scalarsC := (*C.BLS12_381_scalar_t)(d_scalars) - pointsC := (*C.BLS12_381_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_cuda_bls12_381(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BLS12_381_g2_projective_t)(d_out) - scalarsC := (*C.BLS12_381_scalar_t)(d_scalars) - pointsC := (*C.BLS12_381_g2_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_g2_cuda_bls12_381(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitBatch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BLS12_381_projective_t)(d_out) - scalarsC := (*C.BLS12_381_scalar_t)(d_scalars) - pointsC := (*C.BLS12_381_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.commit_batch_cuda_bls12_381(d_outC, scalarsC, pointsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2Batch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BLS12_381_g2_projective_t)(d_out) - scalarsC := (*C.BLS12_381_scalar_t)(d_scalars) - pointsC := (*C.BLS12_381_g2_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.msm_batch_g2_cuda_bls12_381(d_outC, pointsC, scalarsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} diff --git a/goicicle/curves/bls12381/msm_test.go b/goicicle/curves/bls12381/msm_test.go deleted file mode 100644 index 15e1f0971..000000000 --- a/goicicle/curves/bls12381/msm_test.go +++ /dev/null @@ -1,360 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bls12381 - -import ( - "fmt" - "math" - "testing" - "time" - "unsafe" - - "github.com/ingonyama-zk/icicle/goicicle" - "github.com/stretchr/testify/assert" -) - -func GeneratePoints(count int) []G1PointAffine { - // Declare a slice of integers - var points []G1PointAffine - - // populate the slice - for i := 0; i < 10; i++ { - var pointProjective G1ProjectivePoint - pointProjective.Random() - - var pointAffine G1PointAffine - pointAffine.FromProjective(&pointProjective) - - points = append(points, pointAffine) - } - - log2_10 := math.Log2(10) - log2Count := math.Log2(float64(count)) - log2Size := int(math.Ceil(log2Count - log2_10)) - - for i := 0; i < log2Size; i++ { - points = append(points, points...) - } - - return points[:count] -} - -func GeneratePointsProj(count int) []G1ProjectivePoint { - // Declare a slice of integers - var points []G1ProjectivePoint - // Use a loop to populate the slice - for i := 0; i < count; i++ { - var p G1ProjectivePoint - p.Random() - - points = append(points, p) - } - - return points -} - -func GenerateScalars(count int, skewed bool) []G1ScalarField { - // Declare a slice of integers - var scalars []G1ScalarField - - var rand G1ScalarField - var zero G1ScalarField - var one G1ScalarField - var randLarge G1ScalarField - - zero.SetZero() - one.SetOne() - randLarge.Random() - - if skewed && count > 1_200_000 { - for i := 0; i < count-1_200_000; i++ { - rand.Random() - scalars = append(scalars, rand) - } - - for i := 0; i < 600_000; i++ { - scalars = append(scalars, randLarge) - } - for i := 0; i < 400_000; i++ { - scalars = append(scalars, zero) - } - for i := 0; i < 200_000; i++ { - scalars = append(scalars, one) - } - } else { - for i := 0; i < count; i++ { - rand.Random() - scalars = append(scalars, rand) - } - } - - return scalars[:count] -} - -func TestMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1 << v - - points := GeneratePoints(count) - fmt.Print("Finished generating points\n") - scalars := GenerateScalars(count, false) - fmt.Print("Finished generating scalars\n") - - out := new(G1ProjectivePoint) - startTime := time.Now() - _, e := Msm(out, points, scalars, 0) // non mont - fmt.Printf("icicle MSM took: %d ms\n", time.Since(startTime).Milliseconds()) - - assert.Equal(t, e, nil, "error should be nil") - - assert.True(t, out.IsOnCurve()) - } -} - -func TestCommitMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1< -#include -#include -// msm.h - -#ifndef _BN254_MSM_H -#define _BN254_MSM_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BN254 projective and affine structs -typedef struct BN254_projective_t BN254_projective_t; -typedef struct BN254_g2_projective_t BN254_g2_projective_t; -typedef struct BN254_affine_t BN254_affine_t; -typedef struct BN254_g2_affine_t BN254_g2_affine_t; -typedef struct BN254_scalar_t BN254_scalar_t; -typedef cudaStream_t CudaStream_t; - -int msm_cuda_bn254( - BN254_projective_t* out, BN254_affine_t* points, BN254_scalar_t* scalars, size_t count, size_t device_id); - -int msm_batch_cuda_bn254( - BN254_projective_t* out, - BN254_affine_t* points, - BN254_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); - -int commit_cuda_bn254( - BN254_projective_t* d_out, - BN254_scalar_t* d_scalars, - BN254_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); - -int commit_batch_cuda_bn254( - BN254_projective_t* d_out, - BN254_scalar_t* d_scalars, - BN254_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id); - -int msm_g2_cuda_bn254( - BN254_g2_projective_t* out, BN254_g2_affine_t* points, BN254_scalar_t* scalars, size_t count, size_t device_id); -int msm_batch_g2_cuda_bn254( - BN254_g2_projective_t* out, - BN254_g2_affine_t* points, - BN254_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); -int commit_g2_cuda_bn254( - BN254_g2_projective_t* d_out, - BN254_scalar_t* d_scalars, - BN254_g2_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); -int commit_batch_g2_cuda_bn254( - BN254_g2_projective_t* d_out, - BN254_scalar_t* d_scalars, - BN254_g2_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id, - cudaStream_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BN254_MSM_H */ diff --git a/goicicle/curves/bn254/include/ntt.h b/goicicle/curves/bn254/include/ntt.h deleted file mode 100644 index 4ca148e36..000000000 --- a/goicicle/curves/bn254/include/ntt.h +++ /dev/null @@ -1,193 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// ntt.h - -#ifndef _BN254_NTT_H -#define _BN254_NTT_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BN254 projective and affine structs -typedef struct BN254_projective_t BN254_projective_t; -typedef struct BN254_affine_t BN254_affine_t; -typedef struct BN254_scalar_t BN254_scalar_t; - -typedef struct BN254_g2_projective_t BN254_g2_projective_t; -typedef struct BN254_g2_affine_t BN254_g2_affine_t; - -int ntt_cuda_bn254(BN254_scalar_t* arr, uint32_t n, bool inverse, size_t device_id); -int ntt_batch_cuda_bn254(BN254_scalar_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -int ecntt_cuda_bn254(BN254_projective_t* arr, uint32_t n, bool inverse, size_t device_id); -int ecntt_batch_cuda_bn254( - BN254_projective_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -BN254_scalar_t* -build_domain_cuda_bn254(uint32_t domain_size, uint32_t logn, bool inverse, size_t device_id, size_t stream); -int interpolate_scalars_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_evaluations, - BN254_scalar_t* d_domain, - unsigned n, - unsigned device_id, - size_t stream); -int interpolate_scalars_batch_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_evaluations, - BN254_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_points_cuda_bn254( - BN254_projective_t* d_out, - BN254_projective_t* d_evaluations, - BN254_scalar_t* d_domain, - unsigned n, - size_t device_id, - size_t stream); -int interpolate_points_batch_cuda_bn254( - BN254_projective_t* d_out, - BN254_projective_t* d_evaluations, - BN254_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_scalars_on_coset_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_evaluations, - BN254_scalar_t* d_domain, - unsigned n, - BN254_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int interpolate_scalars_batch_on_coset_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_evaluations, - BN254_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - BN254_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_scalars_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned device_id, - size_t stream); -int evaluate_scalars_batch_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_points_cuda_bn254( - BN254_projective_t* d_out, - BN254_projective_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - size_t device_id, - size_t stream); -int evaluate_points_batch_cuda_bn254( - BN254_projective_t* d_out, - BN254_projective_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_scalars_on_coset_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BN254_scalar_t* coset_powers, - unsigned device_id, - size_t stream); -int evaluate_scalars_on_coset_batch_cuda_bn254( - BN254_scalar_t* d_out, - BN254_scalar_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BN254_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_cuda_bn254( - BN254_projective_t* d_out, - BN254_projective_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BN254_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_batch_cuda_bn254( - BN254_projective_t* d_out, - BN254_projective_t* d_coefficients, - BN254_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BN254_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int reverse_order_scalars_cuda_bn254(BN254_scalar_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_scalars_batch_cuda_bn254(BN254_scalar_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int reverse_order_points_cuda_bn254(BN254_projective_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_points_batch_cuda_bn254( - BN254_projective_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int add_scalars_cuda_bn254( - BN254_scalar_t* d_out, BN254_scalar_t* d_in1, BN254_scalar_t* d_in2, unsigned n, size_t stream); -int sub_scalars_cuda_bn254( - BN254_scalar_t* d_out, BN254_scalar_t* d_in1, BN254_scalar_t* d_in2, unsigned n, size_t stream); -int to_montgomery_scalars_cuda_bn254(BN254_scalar_t* d_inout, unsigned n, size_t stream); -int from_montgomery_scalars_cuda_bn254(BN254_scalar_t* d_inout, unsigned n, size_t stream); - -// points g1 -int to_montgomery_proj_points_cuda_bn254(BN254_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_cuda_bn254(BN254_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_cuda_bn254(BN254_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_cuda_bn254(BN254_affine_t* d_inout, unsigned n, size_t stream); - -// points g2 -int to_montgomery_proj_points_g2_cuda_bn254(BN254_g2_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_g2_cuda_bn254(BN254_g2_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_g2_cuda_bn254(BN254_g2_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_g2_cuda_bn254(BN254_g2_affine_t* d_inout, unsigned n, size_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BN254_NTT_H */ diff --git a/goicicle/curves/bn254/include/projective.h b/goicicle/curves/bn254/include/projective.h deleted file mode 100644 index 20e9842fa..000000000 --- a/goicicle/curves/bn254/include/projective.h +++ /dev/null @@ -1,50 +0,0 @@ - -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// projective.h - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BN254_projective_t BN254_projective_t; -typedef struct BN254_g2_projective_t BN254_g2_projective_t; -typedef struct BN254_affine_t BN254_affine_t; -typedef struct BN254_g2_affine_t BN254_g2_affine_t; -typedef struct BN254_scalar_t BN254_scalar_t; - -bool projective_is_on_curve_bn254(BN254_projective_t* point1); - -int random_scalar_bn254(BN254_scalar_t* out); -int random_projective_bn254(BN254_projective_t* out); -BN254_projective_t* projective_zero_bn254(); -int projective_to_affine_bn254(BN254_affine_t* out, BN254_projective_t* point1); -int projective_from_affine_bn254(BN254_projective_t* out, BN254_affine_t* point1); - -int random_g2_projective_bn254(BN254_g2_projective_t* out); -int g2_projective_to_affine_bn254(BN254_g2_affine_t* out, BN254_g2_projective_t* point1); -int g2_projective_from_affine_bn254(BN254_g2_projective_t* out, BN254_g2_affine_t* point1); -bool g2_projective_is_on_curve_bn254(BN254_g2_projective_t* point1); - -bool eq_bn254(BN254_projective_t* point1, BN254_projective_t* point2); -bool eq_g2_bn254(BN254_g2_projective_t* point1, BN254_g2_projective_t* point2); - -#ifdef __cplusplus -} -#endif diff --git a/goicicle/curves/bn254/msm.go b/goicicle/curves/bn254/msm.go deleted file mode 100644 index 4677c8ed8..000000000 --- a/goicicle/curves/bn254/msm.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bn254 - -import ( - "errors" - "fmt" - "unsafe" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ -lbn254 -// #include "msm.h" -import "C" - -func Msm(out *G1ProjectivePoint, points []G1PointAffine, scalars []G1ScalarField, device_id int) (*G1ProjectivePoint, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BN254_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BN254_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BN254_projective_t)(unsafe.Pointer(out)) - ret := C.msm_cuda_bn254(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_cuda_bn254 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2(out *G2Point, points []G2PointAffine, scalars []G1ScalarField, device_id int) (*G2Point, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BN254_g2_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BN254_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BN254_g2_projective_t)(unsafe.Pointer(out)) - - ret := C.msm_g2_cuda_bn254(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_g2_cuda_bn254 returned error code: %d", ret) - } - - return out, nil -} - -func MsmBatch(points *[]G1PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G1ProjectivePoint, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G1ProjectivePoint, batchSize) - - for i := 0; i < len(out); i++ { - var p G1ProjectivePoint - p.SetZero() - - out[i] = p - } - - outC := (*C.BN254_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BN254_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BN254_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_cuda_bn254(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bn254 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2Batch(points *[]G2PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G2Point, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G2Point, batchSize) - - outC := (*C.BN254_g2_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BN254_g2_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BN254_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_g2_cuda_bn254(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bn254 returned error code: %d", ret) - } - - return out, nil -} - -func Commit(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BN254_projective_t)(d_out) - scalarsC := (*C.BN254_scalar_t)(d_scalars) - pointsC := (*C.BN254_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_cuda_bn254(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BN254_g2_projective_t)(d_out) - scalarsC := (*C.BN254_scalar_t)(d_scalars) - pointsC := (*C.BN254_g2_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_g2_cuda_bn254(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitBatch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BN254_projective_t)(d_out) - scalarsC := (*C.BN254_scalar_t)(d_scalars) - pointsC := (*C.BN254_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.commit_batch_cuda_bn254(d_outC, scalarsC, pointsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2Batch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BN254_g2_projective_t)(d_out) - scalarsC := (*C.BN254_scalar_t)(d_scalars) - pointsC := (*C.BN254_g2_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.msm_batch_g2_cuda_bn254(d_outC, pointsC, scalarsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} diff --git a/goicicle/curves/bn254/msm_test.go b/goicicle/curves/bn254/msm_test.go deleted file mode 100644 index c8f04346e..000000000 --- a/goicicle/curves/bn254/msm_test.go +++ /dev/null @@ -1,360 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bn254 - -import ( - "fmt" - "math" - "testing" - "time" - "unsafe" - - "github.com/ingonyama-zk/icicle/goicicle" - "github.com/stretchr/testify/assert" -) - -func GeneratePoints(count int) []G1PointAffine { - // Declare a slice of integers - var points []G1PointAffine - - // populate the slice - for i := 0; i < 10; i++ { - var pointProjective G1ProjectivePoint - pointProjective.Random() - - var pointAffine G1PointAffine - pointAffine.FromProjective(&pointProjective) - - points = append(points, pointAffine) - } - - log2_10 := math.Log2(10) - log2Count := math.Log2(float64(count)) - log2Size := int(math.Ceil(log2Count - log2_10)) - - for i := 0; i < log2Size; i++ { - points = append(points, points...) - } - - return points[:count] -} - -func GeneratePointsProj(count int) []G1ProjectivePoint { - // Declare a slice of integers - var points []G1ProjectivePoint - // Use a loop to populate the slice - for i := 0; i < count; i++ { - var p G1ProjectivePoint - p.Random() - - points = append(points, p) - } - - return points -} - -func GenerateScalars(count int, skewed bool) []G1ScalarField { - // Declare a slice of integers - var scalars []G1ScalarField - - var rand G1ScalarField - var zero G1ScalarField - var one G1ScalarField - var randLarge G1ScalarField - - zero.SetZero() - one.SetOne() - randLarge.Random() - - if skewed && count > 1_200_000 { - for i := 0; i < count-1_200_000; i++ { - rand.Random() - scalars = append(scalars, rand) - } - - for i := 0; i < 600_000; i++ { - scalars = append(scalars, randLarge) - } - for i := 0; i < 400_000; i++ { - scalars = append(scalars, zero) - } - for i := 0; i < 200_000; i++ { - scalars = append(scalars, one) - } - } else { - for i := 0; i < count; i++ { - rand.Random() - scalars = append(scalars, rand) - } - } - - return scalars[:count] -} - -func TestMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1 << v - - points := GeneratePoints(count) - fmt.Print("Finished generating points\n") - scalars := GenerateScalars(count, false) - fmt.Print("Finished generating scalars\n") - - out := new(G1ProjectivePoint) - startTime := time.Now() - _, e := Msm(out, points, scalars, 0) // non mont - fmt.Printf("icicle MSM took: %d ms\n", time.Since(startTime).Milliseconds()) - - assert.Equal(t, e, nil, "error should be nil") - - assert.True(t, out.IsOnCurve()) - } -} - -func TestCommitMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1< -#include -#include -// msm.h - -#ifndef _BW6761_MSM_H -#define _BW6761_MSM_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BW6761 projective and affine structs -typedef struct BW6761_projective_t BW6761_projective_t; -typedef struct BW6761_g2_projective_t BW6761_g2_projective_t; -typedef struct BW6761_affine_t BW6761_affine_t; -typedef struct BW6761_g2_affine_t BW6761_g2_affine_t; -typedef struct BW6761_scalar_t BW6761_scalar_t; -typedef cudaStream_t CudaStream_t; - -int msm_cuda_bw6_761( - BW6761_projective_t* out, BW6761_affine_t* points, BW6761_scalar_t* scalars, size_t count, size_t device_id); - -int msm_batch_cuda_bw6_761( - BW6761_projective_t* out, - BW6761_affine_t* points, - BW6761_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); - -int commit_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_scalar_t* d_scalars, - BW6761_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); - -int commit_batch_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_scalar_t* d_scalars, - BW6761_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id); - -int msm_g2_cuda_bw6_761( - BW6761_g2_projective_t* out, - BW6761_g2_affine_t* points, - BW6761_scalar_t* scalars, - size_t count, - size_t device_id); - -int msm_batch_g2_cuda_bw6_761( - BW6761_g2_projective_t* out, - BW6761_g2_affine_t* points, - BW6761_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); - -int commit_g2_cuda_bw6_761( - BW6761_g2_projective_t* d_out, - BW6761_scalar_t* d_scalars, - BW6761_g2_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); - -int commit_batch_g2_cuda_bw6_761( - BW6761_g2_projective_t* d_out, - BW6761_scalar_t* d_scalars, - BW6761_g2_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id, - cudaStream_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BW6761_MSM_H */ diff --git a/goicicle/curves/bw6761/include/ntt.h b/goicicle/curves/bw6761/include/ntt.h deleted file mode 100644 index 61f371427..000000000 --- a/goicicle/curves/bw6761/include/ntt.h +++ /dev/null @@ -1,198 +0,0 @@ - - // Copyright 2023 Ingonyama - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// ntt.h - -#ifndef _BW6761_NTT_H -#define _BW6761_NTT_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of BW6761 projective and affine structs -typedef struct BW6761_projective_t BW6761_projective_t; -typedef struct BW6761_affine_t BW6761_affine_t; -typedef struct BW6761_scalar_t BW6761_scalar_t; - -typedef struct BW6761_g2_projective_t BW6761_g2_projective_t; -typedef struct BW6761_g2_affine_t BW6761_g2_affine_t; - -int ntt_cuda_bw6_761(BW6761_scalar_t* arr, uint32_t n, bool inverse, size_t device_id); -int ntt_batch_cuda_bw6_761( - BW6761_scalar_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -int ecntt_cuda_bw6_761(BW6761_projective_t* arr, uint32_t n, bool inverse, size_t device_id); -int ecntt_batch_cuda_bw6_761( - BW6761_projective_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -BW6761_scalar_t* -build_domain_cuda_bw6_761(uint32_t domain_size, uint32_t logn, bool inverse, size_t device_id, size_t stream); - -int interpolate_scalars_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_evaluations, - BW6761_scalar_t* d_domain, - unsigned n, - unsigned device_id, - size_t stream); -int interpolate_scalars_batch_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_evaluations, - BW6761_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_points_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_projective_t* d_evaluations, - BW6761_scalar_t* d_domain, - unsigned n, - size_t device_id, - size_t stream); -int interpolate_points_batch_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_projective_t* d_evaluations, - BW6761_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_scalars_on_coset_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_evaluations, - BW6761_scalar_t* d_domain, - unsigned n, - BW6761_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int interpolate_scalars_batch_on_coset_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_evaluations, - BW6761_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - BW6761_scalar_t* coset_powers, - size_t device_id, - size_t stream); - -int evaluate_scalars_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned device_id, - size_t stream); -int evaluate_scalars_batch_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_points_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_projective_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - size_t device_id, - size_t stream); -int evaluate_points_batch_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_projective_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_scalars_on_coset_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BW6761_scalar_t* coset_powers, - unsigned device_id, - size_t stream); -int evaluate_scalars_on_coset_batch_cuda_bw6_761( - BW6761_scalar_t* d_out, - BW6761_scalar_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BW6761_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_projective_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - BW6761_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_batch_cuda_bw6_761( - BW6761_projective_t* d_out, - BW6761_projective_t* d_coefficients, - BW6761_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - BW6761_scalar_t* coset_powers, - size_t device_id, - size_t stream); - -int reverse_order_scalars_cuda_bw6_761(BW6761_scalar_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_scalars_batch_cuda_bw6_761( - BW6761_scalar_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int reverse_order_points_cuda_bw6_761(BW6761_projective_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_points_batch_cuda_bw6_761( - BW6761_projective_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int add_scalars_cuda_bw6_761( - BW6761_scalar_t* d_out, BW6761_scalar_t* d_in1, BW6761_scalar_t* d_in2, unsigned n, size_t stream); -int sub_scalars_cuda_bw6_761( - BW6761_scalar_t* d_out, BW6761_scalar_t* d_in1, BW6761_scalar_t* d_in2, unsigned n, size_t stream); -int to_montgomery_scalars_cuda_bw6_761(BW6761_scalar_t* d_inout, unsigned n, size_t stream); -int from_montgomery_scalars_cuda_bw6_761(BW6761_scalar_t* d_inout, unsigned n, size_t stream); - -// points g1 -int to_montgomery_proj_points_cuda_bw6_761(BW6761_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_cuda_bw6_761(BW6761_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_cuda_bw6_761(BW6761_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_cuda_bw6_761(BW6761_affine_t* d_inout, unsigned n, size_t stream); - -// points g2 -int to_montgomery_proj_points_g2_cuda_bw6_761(BW6761_g2_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_g2_cuda_bw6_761(BW6761_g2_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_g2_cuda_bw6_761(BW6761_g2_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_g2_cuda_bw6_761(BW6761_g2_affine_t* d_inout, unsigned n, size_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _BW6761_NTT_H */ diff --git a/goicicle/curves/bw6761/include/projective.h b/goicicle/curves/bw6761/include/projective.h deleted file mode 100644 index 74f347d24..000000000 --- a/goicicle/curves/bw6761/include/projective.h +++ /dev/null @@ -1,50 +0,0 @@ - - // Copyright 2023 Ingonyama - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// projective.h - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BW6761_projective_t BW6761_projective_t; -typedef struct BW6761_g2_projective_t BW6761_g2_projective_t; -typedef struct BW6761_affine_t BW6761_affine_t; -typedef struct BW6761_g2_affine_t BW6761_g2_affine_t; -typedef struct BW6761_scalar_t BW6761_scalar_t; - -bool projective_is_on_curve_bw6_761(BW6761_projective_t* point1); - -int random_scalar_bw6_761(BW6761_scalar_t* out); -int random_projective_bw6_761(BW6761_projective_t* out); -BW6761_projective_t* projective_zero_bw6_761(); -int projective_to_affine_bw6_761(BW6761_affine_t* out, BW6761_projective_t* point1); -int projective_from_affine_bw6_761(BW6761_projective_t* out, BW6761_affine_t* point1); - -int random_g2_projective_bw6_761(BW6761_g2_projective_t* out); -int g2_projective_to_affine_bw6_761(BW6761_g2_affine_t* out, BW6761_g2_projective_t* point1); -int g2_projective_from_affine_bw6_761(BW6761_g2_projective_t* out, BW6761_g2_affine_t* point1); -bool g2_projective_is_on_curve_bw6_761(BW6761_g2_projective_t* point1); - -bool eq_bw6_761(BW6761_projective_t* point1, BW6761_projective_t* point2); -bool eq_g2_bw6_761(BW6761_g2_projective_t* point1, BW6761_g2_projective_t* point2); - -#ifdef __cplusplus -} -#endif diff --git a/goicicle/curves/bw6761/include/ve_mod_mult.h b/goicicle/curves/bw6761/include/ve_mod_mult.h deleted file mode 100644 index fbc2b5a8d..000000000 --- a/goicicle/curves/bw6761/include/ve_mod_mult.h +++ /dev/null @@ -1,49 +0,0 @@ - - // Copyright 2023 Ingonyama - // - // Licensed under the Apache License, Version 2.0 (the "License"); - // you may not use this file except in compliance with the License. - // You may obtain a copy of the License at - // - // http://www.apache.org/licenses/LICENSE-2.0 - // - // Unless required by applicable law or agreed to in writing, software - // distributed under the License is distributed on an "AS IS" BASIS, - // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - // See the License for the specific language governing permissions and - // limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -#include -#include -// ve_mod_mult.h - -#ifndef _BW6761_VEC_MULT_H -#define _BW6761_VEC_MULT_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BW6761_projective_t BW6761_projective_t; -typedef struct BW6761_scalar_t BW6761_scalar_t; - -int32_t vec_mod_mult_point_bw6_761( - BW6761_projective_t* inout, BW6761_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_scalar_bw6_761( - BW6761_scalar_t* inout, BW6761_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_device_scalar_bw6_761( - BW6761_scalar_t* inout, BW6761_scalar_t* scalar_vec, size_t n_elements, size_t device_id); -int32_t matrix_vec_mod_mult_bw6_761( - BW6761_scalar_t* matrix_flattened, - BW6761_scalar_t* input, - BW6761_scalar_t* output, - size_t n_elments, - size_t device_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _BW6761_VEC_MULT_H */ diff --git a/goicicle/curves/bw6761/msm.go b/goicicle/curves/bw6761/msm.go deleted file mode 100644 index c0a39ffcd..000000000 --- a/goicicle/curves/bw6761/msm.go +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bw6761 - -import ( - "errors" - "fmt" - "unsafe" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ -lbw6761 -// #include "msm.h" -import "C" - -func Msm(out *G1ProjectivePoint, points []G1PointAffine, scalars []G1ScalarField, device_id int) (*G1ProjectivePoint, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BW6761_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BW6761_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BW6761_projective_t)(unsafe.Pointer(out)) - ret := C.msm_cuda_bw6_761(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_cuda_bw6_761 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2(out *G2Point, points []G2PointAffine, scalars []G1ScalarField, device_id int) (*G2Point, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.BW6761_g2_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.BW6761_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.BW6761_g2_projective_t)(unsafe.Pointer(out)) - - ret := C.msm_g2_cuda_bw6_761(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_g2_cuda_bw6_761 returned error code: %d", ret) - } - - return out, nil -} - -func MsmBatch(points *[]G1PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G1ProjectivePoint, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G1ProjectivePoint, batchSize) - - for i := 0; i < len(out); i++ { - var p G1ProjectivePoint - p.SetZero() - - out[i] = p - } - - outC := (*C.BW6761_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BW6761_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BW6761_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_cuda_bw6_761(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bw6_761 returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2Batch(points *[]G2PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G2Point, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G2Point, batchSize) - - outC := (*C.BW6761_g2_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.BW6761_g2_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.BW6761_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_g2_cuda_bw6_761(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_bw6_761 returned error code: %d", ret) - } - - return out, nil -} - -func Commit(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BW6761_projective_t)(d_out) - scalarsC := (*C.BW6761_scalar_t)(d_scalars) - pointsC := (*C.BW6761_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_cuda_bw6_761(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.BW6761_g2_projective_t)(d_out) - scalarsC := (*C.BW6761_scalar_t)(d_scalars) - pointsC := (*C.BW6761_g2_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_g2_cuda_bw6_761(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitBatch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BW6761_projective_t)(d_out) - scalarsC := (*C.BW6761_scalar_t)(d_scalars) - pointsC := (*C.BW6761_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.commit_batch_cuda_bw6_761(d_outC, scalarsC, pointsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2Batch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.BW6761_g2_projective_t)(d_out) - scalarsC := (*C.BW6761_scalar_t)(d_scalars) - pointsC := (*C.BW6761_g2_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.msm_batch_g2_cuda_bw6_761(d_outC, pointsC, scalarsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} diff --git a/goicicle/curves/bw6761/msm_test.go b/goicicle/curves/bw6761/msm_test.go deleted file mode 100644 index 53b70a4fc..000000000 --- a/goicicle/curves/bw6761/msm_test.go +++ /dev/null @@ -1,367 +0,0 @@ -// Copyright 2023 Ingonyama -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Code generated by Ingonyama DO NOT EDIT - -package bw6761 - -import ( - "fmt" - "math" - "testing" - "time" - "unsafe" - - "github.com/ingonyama-zk/icicle/goicicle" - "github.com/stretchr/testify/assert" -) - -func GeneratePoints(count int) []G1PointAffine { - // Declare a slice of integers - var points []G1PointAffine - - // populate the slice - for i := 0; i < 10; i++ { - var pointProjective G1ProjectivePoint - pointProjective.Random() - - var pointAffine G1PointAffine - pointAffine.FromProjective(&pointProjective) - - points = append(points, pointAffine) - } - - log2_10 := math.Log2(10) - log2Count := math.Log2(float64(count)) - log2Size := int(math.Ceil(log2Count - log2_10)) - - for i := 0; i < log2Size; i++ { - points = append(points, points...) - } - - return points[:count] -} - -func GeneratePointsProj(count int) []G1ProjectivePoint { - // Declare a slice of integers - var points []G1ProjectivePoint - // Use a loop to populate the slice - for i := 0; i < count; i++ { - var p G1ProjectivePoint - p.Random() - - points = append(points, p) - } - - return points -} - -func GenerateScalars(count int, skewed bool) []G1ScalarField { - // Declare a slice of integers - var scalars []G1ScalarField - - var rand G1ScalarField - var zero G1ScalarField - var one G1ScalarField - var randLarge G1ScalarField - - zero.SetZero() - one.SetOne() - randLarge.Random() - - if skewed && count > 1_200_000 { - for i := 0; i < count-1_200_000; i++ { - rand.Random() - scalars = append(scalars, rand) - } - - for i := 0; i < 600_000; i++ { - scalars = append(scalars, randLarge) - } - for i := 0; i < 400_000; i++ { - scalars = append(scalars, zero) - } - for i := 0; i < 200_000; i++ { - scalars = append(scalars, one) - } - } else { - for i := 0; i < count; i++ { - rand.Random() - scalars = append(scalars, rand) - } - } - - return scalars[:count] -} - -func TestMSM(t *testing.T) { - fmt.Print() // this prevents the test from hanging. TODO: figure out why - for _, v := range []int{8} { - count := 1 << v - - points := GeneratePoints(count) - fmt.Print("Finished generating points\n") - scalars := GenerateScalars(count, false) - fmt.Print("Finished generating scalars\n") - - out := new(G1ProjectivePoint) - startTime := time.Now() - _, e := Msm(out, points, scalars, 0) // non mont - fmt.Printf("icicle MSM took: %d ms\n", time.Since(startTime).Milliseconds()) - - assert.Equal(t, e, nil, "error should be nil") - - assert.True(t, out.IsOnCurve()) - } -} - -func TestCommitMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1< -#include -*/ -import "C" - -import ( - "errors" - "unsafe" -) - -func CudaMalloc(size int) (dp unsafe.Pointer, err error) { - var p C.void - dp = unsafe.Pointer(&p) - if err := C.cudaMalloc(&dp, C.size_t(size)); err != 0 { - return nil, errors.New("could not create memory space") - } - return dp, nil -} - -func CudaFree(dp unsafe.Pointer) int { - if err := C.cudaFree(dp); err != 0 { - return -1 - } - return 0 -} - -func CudaMemCpyHtoD[T any](dst_d unsafe.Pointer, src []T, size int) int { - src_c := unsafe.Pointer(&src[0]) - if err := C.cudaMemcpy(dst_d, src_c, C.size_t(size), 1); err != 0 { - return -1 - } - return 0 -} - -func CudaMemCpyDtoH[T any](dst []T, src_d unsafe.Pointer, size int) int { - dst_c := unsafe.Pointer(&dst[0]) - - if err := C.cudaMemcpy(dst_c, src_d, C.size_t(size), 2); err != 0 { - return -1 - } - return 0 -} diff --git a/goicicle/setup.sh b/goicicle/setup.sh deleted file mode 100755 index 62f771b2c..000000000 --- a/goicicle/setup.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -SUDO='' -if [ "$EUID" != 0 ]; then - echo "Icicle setup script should be run with root privileges, please run this as root" - SUDO='sudo' -fi - - -TARGET_BN254="libbn254.so" -TARGET_BLS12_381="libbls12_381.so" -TARGET_BLS12_377="libbls12_377.so" -TARGET_BW6_671="libbw6_671.so" - -MAKE_FAIL=0 - -$SUDO make $1 || MAKE_FAIL=1 - -if [ $MAKE_FAIL != 0 ]; then - echo "make failed, install dependencies and re-run setup script with root privileges" - exit -fi - -TARGET_BN254_PATH=$(dirname "$(find `pwd` -name $TARGET_BN254 -print -quit)")/ -TARGET_BLS12_381_PATH=$(dirname "$(find `pwd` -name $TARGET_BLS12_381 -print -quit)")/ -TARGET_BLS12_377_PATH=$(dirname "$(find `pwd` -name $TARGET_BLS12_377 -print -quit)")/ -TARGET_BW6_671_PATH=$(dirname "$(find `pwd` -name $TARGET_BW6_671 -print -quit)")/ - - -if [[ "$TARGET_BLS12_377_PATH" != "" ]]; then - echo "BLS12_377 found @ $TARGET_BLS12_377_PATH" - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$TARGET_BLS12_377_PATH -fi - -if [[ "$TARGET_BN254_PATH" != "" ]]; then - echo "BN254 found @ $TARGET_BN254_PATH" - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$TARGET_BN254_PATH -fi - -if [[ "$TARGET_BLS12_381_PATH" != "" ]]; then - echo "BLS12_381 found @ $TARGET_BLS12_381_PATH" - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$TARGET_BLS12_381_PATH -fi - -if [[ "$TARGET_BW6_671_PATH" != "" ]]; then - echo "BW6_671 found @ $TARGET_BW6_671_PATH" - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$TARGET_BW6_671_PATH -fi diff --git a/goicicle/templates/curves/curves.go b/goicicle/templates/curves/curves.go deleted file mode 100644 index 535aef6d0..000000000 --- a/goicicle/templates/curves/curves.go +++ /dev/null @@ -1,52 +0,0 @@ -package config - -// {{.SharedLib}} -type Curve struct { - PackageName string - CurveNameUpperCase string - CurveNameLowerCase string - SharedLib string - ScalarSize int - BaseSize int - G2ElementSize int -} - -var BW6_761 = Curve{ - PackageName: "bw6761", - CurveNameUpperCase: "BW6761", - CurveNameLowerCase: "bw6_761", - SharedLib: "-lbw6761", - ScalarSize: 12, - BaseSize: 24, - G2ElementSize: 6, -} - -var BN_254 = Curve{ - PackageName: "bn254", - CurveNameUpperCase: "BN254", - CurveNameLowerCase: "bn254", - SharedLib: "-lbn254", - ScalarSize: 8, - BaseSize: 8, - G2ElementSize: 4, -} - -var BLS_12_377 = Curve{ - PackageName: "bls12377", - CurveNameUpperCase: "BLS12_377", - CurveNameLowerCase: "bls12_377", - SharedLib: "-lbls12_377", - ScalarSize: 8, - BaseSize: 12, - G2ElementSize: 6, -} - -var BLS_12_381 = Curve{ - PackageName: "bls12381", - CurveNameUpperCase: "BLS12_381", - CurveNameLowerCase: "bls12_381", - SharedLib: "-lbls12_381", - ScalarSize: 8, - BaseSize: 12, - G2ElementSize: 6, -} diff --git a/goicicle/templates/curves/g1.go.tmpl b/goicicle/templates/curves/g1.go.tmpl deleted file mode 100644 index 2edac159c..000000000 --- a/goicicle/templates/curves/g1.go.tmpl +++ /dev/null @@ -1,310 +0,0 @@ -import ( - "unsafe" - - "encoding/binary" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ {{.SharedLib}} -// #include "projective.h" -// #include "ve_mod_mult.h" -import "C" - -const SCALAR_SIZE = {{.ScalarSize}} -const BASE_SIZE = {{.BaseSize}} - -type G1ScalarField struct { - S [SCALAR_SIZE]uint32 -} - -type G1BaseField struct { - S [BASE_SIZE]uint32 -} - -/* - * BaseField Constructors - */ - -func (f *G1BaseField) SetZero() *G1BaseField { - var S [BASE_SIZE]uint32 - f.S = S - - return f -} - -func (f *G1BaseField) SetOne() *G1BaseField { - var S [BASE_SIZE]uint32 - - S[0] = 1 - - f.S = S - return f -} - -func (p *G1ProjectivePoint) FromAffine(affine *G1PointAffine) *G1ProjectivePoint { - out := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(p)) - in := (*C.{{.CurveNameUpperCase}}_affine_t)(unsafe.Pointer(affine)) - - C.projective_from_affine_{{.CurveNameLowerCase}}(out, in) - - return p -} - -func (f *G1BaseField) FromLimbs(limbs [BASE_SIZE]uint32) *G1BaseField { - copy(f.S[:], limbs[:]) - - return f -} - -/* - * BaseField methods - */ - -func (f *G1BaseField) Limbs() [BASE_SIZE]uint32 { - return f.S -} - -func (f *G1BaseField) ToBytesLe() []byte { - bytes := make([]byte, len(f.S)*4) - for i, v := range f.S { - binary.LittleEndian.PutUint32(bytes[i*4:], v) - } - - return bytes -} - -/* - * ScalarField methods - */ - -func (p *G1ScalarField) Random() *G1ScalarField { - outC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(p)) - C.random_scalar_{{.CurveNameLowerCase}}(outC) - - return p -} - -func (f *G1ScalarField) SetZero() *G1ScalarField { - var S [SCALAR_SIZE]uint32 - f.S = S - - return f -} - -func (f *G1ScalarField) SetOne() *G1ScalarField { - var S [SCALAR_SIZE]uint32 - S[0] = 1 - f.S = S - - return f -} - -func (a *G1ScalarField) Eq(b *G1ScalarField) bool { - for i, v := range a.S { - if b.S[i] != v { - return false - } - } - return true -} - -/* - * ScalarField methods - */ - -func (f *G1ScalarField) Limbs() [SCALAR_SIZE]uint32 { - return f.S -} - -func (f *G1ScalarField) ToBytesLe() []byte { - bytes := make([]byte, len(f.S)*4) - for i, v := range f.S { - binary.LittleEndian.PutUint32(bytes[i*4:], v) - } - - return bytes -} - -/* - * Point{{.CurveNameUpperCase}} - */ - -type G1ProjectivePoint struct { - X, Y, Z G1BaseField -} - -func (f *G1ProjectivePoint) SetZero() *G1ProjectivePoint { - var yOne G1BaseField - yOne.SetOne() - - var xZero G1BaseField - xZero.SetZero() - - var zZero G1BaseField - zZero.SetZero() - - f.X = xZero - f.Y = yOne - f.Z = zZero - - return f -} - -func (p *G1ProjectivePoint) Eq(pCompare *G1ProjectivePoint) bool { - // Cast *Point{{.CurveNameUpperCase}} to *C.{{.CurveNameUpperCase}}_projective_t - // The unsafe.Pointer cast is necessary because Go doesn't allow direct casts - // between different pointer types. - // It'S your responsibility to ensure that the types are compatible. - pC := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(p)) - pCompareC := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(pCompare)) - - // Call the C function - // The C function doesn't keep any references to the data, - // so it'S fine if the Go garbage collector moves or deletes the data later. - return bool(C.eq_{{.CurveNameLowerCase}}(pC, pCompareC)) -} - -func (p *G1ProjectivePoint) IsOnCurve() bool { - point := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(p)) - res := C.projective_is_on_curve_{{.CurveNameLowerCase}}(point) - - return bool(res) -} - -func (p *G1ProjectivePoint) Random() *G1ProjectivePoint { - outC := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(p)) - C.random_projective_{{.CurveNameLowerCase}}(outC) - - return p -} - -func (p *G1ProjectivePoint) StripZ() *G1PointAffine { - return &G1PointAffine{ - X: p.X, - Y: p.Y, - } -} - -func (p *G1ProjectivePoint) FromLimbs(x, y, z *[]uint32) *G1ProjectivePoint { - var _x G1BaseField - var _y G1BaseField - var _z G1BaseField - - _x.FromLimbs(GetFixedLimbs(x)) - _y.FromLimbs(GetFixedLimbs(y)) - _z.FromLimbs(GetFixedLimbs(z)) - - p.X = _x - p.Y = _y - p.Z = _z - - return p -} - -/* - * PointAffineNoInfinity{{.CurveNameUpperCase}} - */ - -type G1PointAffine struct { - X, Y G1BaseField -} - -func (p *G1PointAffine) FromProjective(projective *G1ProjectivePoint) *G1PointAffine { - in := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(projective)) - out := (*C.{{.CurveNameUpperCase}}_affine_t)(unsafe.Pointer(p)) - - C.projective_to_affine_{{.CurveNameLowerCase}}(out, in) - - return p -} - -func (p *G1PointAffine) ToProjective() *G1ProjectivePoint { - var Z G1BaseField - Z.SetOne() - - return &G1ProjectivePoint{ - X: p.X, - Y: p.Y, - Z: Z, - } -} - -func (p *G1PointAffine) FromLimbs(X, Y *[]uint32) *G1PointAffine { - var _x G1BaseField - var _y G1BaseField - - _x.FromLimbs(GetFixedLimbs(X)) - _y.FromLimbs(GetFixedLimbs(Y)) - - p.X = _x - p.Y = _y - - return p -} - -/* - * Multiplication - */ - -func MultiplyVec(a []G1ProjectivePoint, b []G1ScalarField, deviceID int) { - if len(a) != len(b) { - panic("a and b have different lengths") - } - - pointsC := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(&a[0])) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&b[0])) - deviceIdC := C.size_t(deviceID) - nElementsC := C.size_t(len(a)) - - C.vec_mod_mult_point_{{.CurveNameLowerCase}}(pointsC, scalarsC, nElementsC, deviceIdC) -} - -func MultiplyScalar(a []G1ScalarField, b []G1ScalarField, deviceID int) { - if len(a) != len(b) { - panic("a and b have different lengths") - } - - aC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&a[0])) - bC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&b[0])) - deviceIdC := C.size_t(deviceID) - nElementsC := C.size_t(len(a)) - - C.vec_mod_mult_scalar_{{.CurveNameLowerCase}}(aC, bC, nElementsC, deviceIdC) -} - -// Multiply a matrix by a scalar: -// -// `a` - flattenned matrix; -// `b` - vector to multiply `a` by; -func MultiplyMatrix(a []G1ScalarField, b []G1ScalarField, deviceID int) { - c := make([]G1ScalarField, len(b)) - for i := range c { - var p G1ScalarField - p.SetZero() - - c[i] = p - } - - aC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&a[0])) - bC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&b[0])) - cC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&c[0])) - deviceIdC := C.size_t(deviceID) - nElementsC := C.size_t(len(a)) - - C.matrix_vec_mod_mult_{{.CurveNameLowerCase}}(aC, bC, cC, nElementsC, deviceIdC) -} - -/* - * Utils - */ - -func GetFixedLimbs(slice *[]uint32) [BASE_SIZE]uint32 { - if len(*slice) <= BASE_SIZE { - limbs := [BASE_SIZE]uint32{} - copy(limbs[:len(*slice)], *slice) - return limbs - } - - panic("slice has too many elements") -} diff --git a/goicicle/templates/curves/g1_test.go.tmpl b/goicicle/templates/curves/g1_test.go.tmpl deleted file mode 100644 index d071e0353..000000000 --- a/goicicle/templates/curves/g1_test.go.tmpl +++ /dev/null @@ -1,180 +0,0 @@ -import ( - "encoding/binary" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestNewField{{.CurveNameUpperCase}}One(t *testing.T) { - var oneField G1BaseField - oneField.SetOne() - - rawOneField := [8]uint32([8]uint32{0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}) - - assert.Equal(t, oneField.S, rawOneField) -} - -func TestNewField{{.CurveNameUpperCase}}Zero(t *testing.T) { - var zeroField G1BaseField - zeroField.SetZero() - - rawZeroField := [8]uint32([8]uint32{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}) - - assert.Equal(t, zeroField.S, rawZeroField) -} - -func TestField{{.CurveNameUpperCase}}ToBytesLe(t *testing.T) { - var p G1ProjectivePoint - p.Random() - - expected := make([]byte, len(p.X.S)*4) // each uint32 takes 4 bytes - for i, v := range p.X.S { - binary.LittleEndian.PutUint32(expected[i*4:], v) - } - - assert.Equal(t, p.X.ToBytesLe(), expected) - assert.Equal(t, len(p.X.ToBytesLe()), 32) -} - -func TestNewPoint{{.CurveNameUpperCase}}Zero(t *testing.T) { - var pointZero G1ProjectivePoint - pointZero.SetZero() - - var baseOne G1BaseField - baseOne.SetOne() - - var zeroSanity G1BaseField - zeroSanity.SetZero() - - assert.Equal(t, pointZero.X, zeroSanity) - assert.Equal(t, pointZero.Y, baseOne) - assert.Equal(t, pointZero.Z, zeroSanity) -} - -func TestFromProjectiveToAffine(t *testing.T) { - var projective G1ProjectivePoint - var affine G1PointAffine - - projective.Random() - - affine.FromProjective(&projective) - var projective2 G1ProjectivePoint - projective2.FromAffine(&affine) - - assert.True(t, projective.IsOnCurve()) - assert.True(t, projective2.IsOnCurve()) - assert.True(t, projective.Eq(&projective2)) -} - -func Test{{.CurveNameUpperCase}}Eq(t *testing.T) { - var p1 G1ProjectivePoint - p1.Random() - var p2 G1ProjectivePoint - p2.Random() - - assert.Equal(t, p1.Eq(&p1), true) - assert.Equal(t, p1.Eq(&p2), false) -} - -func Test{{.CurveNameUpperCase}}StripZ(t *testing.T) { - var p1 G1ProjectivePoint - p1.Random() - - p2ZLess := p1.StripZ() - - assert.IsType(t, G1PointAffine{}, *p2ZLess) - assert.Equal(t, p1.X, p2ZLess.X) - assert.Equal(t, p1.Y, p2ZLess.Y) -} - -func TestPoint{{.CurveNameUpperCase}}fromLimbs(t *testing.T) { - var p G1ProjectivePoint - p.Random() - - x := p.X.Limbs() - y := p.Y.Limbs() - z := p.Z.Limbs() - - xSlice := x[:] - ySlice := y[:] - zSlice := z[:] - - var pFromLimbs G1ProjectivePoint - pFromLimbs.FromLimbs(&xSlice, &ySlice, &zSlice) - - assert.Equal(t, pFromLimbs, p) -} - -func TestNewPointAffineNoInfinity{{.CurveNameUpperCase}}Zero(t *testing.T) { - var zeroP G1PointAffine - - var zeroSanity G1BaseField - zeroSanity.SetZero() - - assert.Equal(t, zeroP.X, zeroSanity) - assert.Equal(t, zeroP.Y, zeroSanity) -} - -func TestPointAffineNoInfinity{{.CurveNameUpperCase}}FromLimbs(t *testing.T) { - // Initialize your test values - x := [8]uint32{1, 2, 3, 4, 5, 6, 7, 8} - y := [8]uint32{9, 10, 11, 12, 13, 14, 15, 16} - xSlice := x[:] - ySlice := y[:] - - // Execute your function - var result G1PointAffine - result.FromLimbs(&xSlice, &ySlice) - - var xBase G1BaseField - var yBase G1BaseField - xBase.FromLimbs(x) - yBase.FromLimbs(y) - - // Define your expected result - expected := G1PointAffine{ - X: xBase, - Y: yBase, - } - - // Test if result is as expected - assert.Equal(t, expected, result) -} - -func TestGetFixedLimbs(t *testing.T) { - t.Run("case of valid input of length less than 8", func(t *testing.T) { - slice := []uint32{1, 2, 3, 4, 5, 6, 7} - expected := [8]uint32{1, 2, 3, 4, 5, 6, 7, 0} - - result := GetFixedLimbs(&slice) - assert.Equal(t, result, expected) - }) - - t.Run("case of valid input of length 8", func(t *testing.T) { - slice := []uint32{1, 2, 3, 4, 5, 6, 7, 8} - expected := [8]uint32{1, 2, 3, 4, 5, 6, 7, 8} - - result := GetFixedLimbs(&slice) - assert.Equal(t, result, expected) - }) - - t.Run("case of empty input", func(t *testing.T) { - slice := []uint32{} - expected := [8]uint32{0, 0, 0, 0, 0, 0, 0, 0} - - result := GetFixedLimbs(&slice) - assert.Equal(t, result, expected) - }) - - t.Run("case of input length greater than 8", func(t *testing.T) { - slice := []uint32{1, 2, 3, 4, 5, 6, 7, 8, 9} - - defer func() { - if r := recover(); r == nil { - t.Errorf("the code did not panic") - } - }() - - GetFixedLimbs(&slice) - }) -} diff --git a/goicicle/templates/curves/g2.go.tmpl b/goicicle/templates/curves/g2.go.tmpl deleted file mode 100644 index 48be4fba0..000000000 --- a/goicicle/templates/curves/g2.go.tmpl +++ /dev/null @@ -1,85 +0,0 @@ -import ( - "encoding/binary" - "unsafe" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ {{.SharedLib}} -// #include "projective.h" -// #include "ve_mod_mult.h" -import "C" - -// G2 extension field - -type G2Element [{{.G2ElementSize}}]uint64 - -type ExtentionField struct { - A0, A1 G2Element -} - -type G2PointAffine struct { - X, Y ExtentionField -} - -type G2Point struct { - X, Y, Z ExtentionField -} - -func (p *G2Point) Random() *G2Point { - outC := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(p)) - C.random_g2_projective_{{.CurveNameLowerCase}}(outC) - - return p -} - - -func (p *G2Point) Eq(pCompare *G2Point) bool { - // Cast *Point{{.CurveNameUpperCase}} to *C.{{.CurveNameUpperCase}}_projective_t - // The unsafe.Pointer cast is necessary because Go doesn't allow direct casts - // between different pointer types. - // It's your responsibility to ensure that the types are compatible. - pC := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(p)) - pCompareC := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(pCompare)) - - // Call the C function - // The C function doesn't keep any references to the data, - // so it's fine if the Go garbage collector moves or deletes the data later. - return bool(C.eq_g2_{{.CurveNameLowerCase}}(pC, pCompareC)) -} - -func (f *G2Element) ToBytesLe() []byte { - var bytes []byte - for _, val := range f { - buf := make([]byte, 8) // 8 bytes because uint64 is 64-bit - binary.LittleEndian.PutUint64(buf, val) - bytes = append(bytes, buf...) - } - return bytes -} - -func (p *G2Point) FromAffine(affine *G2PointAffine) *G2Point { - out := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(p)) - in := (*C.{{.CurveNameUpperCase}}_g2_affine_t)(unsafe.Pointer(affine)) - - C.g2_projective_from_affine_{{.CurveNameLowerCase}}(out, in) - - return p -} - -func (p *G2PointAffine) FromProjective(projective *G2Point) *G2PointAffine { - out := (*C.{{.CurveNameUpperCase}}_g2_affine_t)(unsafe.Pointer(p)) - in := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(projective)) - - C.g2_projective_to_affine_{{.CurveNameLowerCase}}(out, in) - - return p -} - -func (p *G2Point) IsOnCurve() bool { - // Directly copy memory from the C struct to the Go struct - point := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(p)) - res := C.g2_projective_is_on_curve_{{.CurveNameLowerCase}}(point) - - return bool(res) -} diff --git a/goicicle/templates/curves/g2_test.go.tmpl b/goicicle/templates/curves/g2_test.go.tmpl deleted file mode 100644 index 3b90041f2..000000000 --- a/goicicle/templates/curves/g2_test.go.tmpl +++ /dev/null @@ -1,61 +0,0 @@ -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestG2Eqg2(t *testing.T) { - var point G2Point - - point.Random() - - assert.True(t, point.Eq(&point)) -} - -func TestG2FromProjectiveToAffine(t *testing.T) { - var projective G2Point - projective.Random() - - var affine G2PointAffine - affine.FromProjective(&projective) - - var projective2 G2Point - projective2.FromAffine(&affine) - - assert.True(t, projective.IsOnCurve()) - assert.True(t, projective2.IsOnCurve()) - assert.True(t, projective.Eq(&projective2)) -} - -func TestG2Eqg2NotEqual(t *testing.T) { - var point G2Point - point.Random() - - var point2 G2Point - point2.Random() - - assert.False(t, point.Eq(&point2)) -} - -func TestG2ToBytes(t *testing.T) { - element := G2Element{0x6546098ea84b6298, 0x4a384533d1f68aca, 0xaa0666972d771336, 0x1569e4a34321993} - bytes := element.ToBytesLe() - - assert.Equal(t, bytes, []byte{0x98, 0x62, 0x4b, 0xa8, 0x8e, 0x9, 0x46, 0x65, 0xca, 0x8a, 0xf6, 0xd1, 0x33, 0x45, 0x38, 0x4a, 0x36, 0x13, 0x77, 0x2d, 0x97, 0x66, 0x6, 0xaa, 0x93, 0x19, 0x32, 0x34, 0x4a, 0x9e, 0x56, 0x1}) -} - -func TestG2ShouldConvertToProjective(t *testing.T) { - fmt.Print() // this prevents the test from hanging. TODO: figure out why - var pointProjective G2Point - pointProjective.Random() - - var pointAffine G2PointAffine - pointAffine.FromProjective(&pointProjective) - - var proj G2Point - proj.FromAffine(&pointAffine) - - assert.True(t, proj.IsOnCurve()) - assert.True(t, pointProjective.Eq(&proj)) -} diff --git a/goicicle/templates/hfiles/msm.h.tmpl b/goicicle/templates/hfiles/msm.h.tmpl deleted file mode 100644 index 3ab9de119..000000000 --- a/goicicle/templates/hfiles/msm.h.tmpl +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -// msm.h - -#ifndef _{{.CurveNameUpperCase}}_MSM_H -#define _{{.CurveNameUpperCase}}_MSM_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of {{.CurveNameUpperCase}} projective and affine structs -typedef struct {{.CurveNameUpperCase}}_projective_t {{.CurveNameUpperCase}}_projective_t; -typedef struct {{.CurveNameUpperCase}}_g2_projective_t {{.CurveNameUpperCase}}_g2_projective_t; -typedef struct {{.CurveNameUpperCase}}_affine_t {{.CurveNameUpperCase}}_affine_t; -typedef struct {{.CurveNameUpperCase}}_g2_affine_t {{.CurveNameUpperCase}}_g2_affine_t; -typedef struct {{.CurveNameUpperCase}}_scalar_t {{.CurveNameUpperCase}}_scalar_t; -typedef cudaStream_t CudaStream_t; - -int msm_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* out, {{.CurveNameUpperCase}}_affine_t* points, {{.CurveNameUpperCase}}_scalar_t* scalars, size_t count, size_t device_id); - -int msm_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* out, - {{.CurveNameUpperCase}}_affine_t* points, - {{.CurveNameUpperCase}}_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); - -int commit_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_scalars, - {{.CurveNameUpperCase}}_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); - -int commit_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_scalars, - {{.CurveNameUpperCase}}_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id); - -int msm_g2_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_g2_projective_t* out, - {{.CurveNameUpperCase}}_g2_affine_t* points, - {{.CurveNameUpperCase}}_scalar_t* scalars, - size_t count, - size_t device_id); - -int msm_batch_g2_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_g2_projective_t* out, - {{.CurveNameUpperCase}}_g2_affine_t* points, - {{.CurveNameUpperCase}}_scalar_t* scalars, - size_t batch_size, - size_t msm_size, - size_t device_id); - -int commit_g2_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_g2_projective_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_scalars, - {{.CurveNameUpperCase}}_g2_affine_t* d_points, - size_t count, - unsigned large_bucket_factor, - size_t device_id); - -int commit_batch_g2_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_g2_projective_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_scalars, - {{.CurveNameUpperCase}}_g2_affine_t* d_points, - size_t count, - size_t batch_size, - size_t device_id, - cudaStream_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _{{.CurveNameUpperCase}}_MSM_H */ diff --git a/goicicle/templates/hfiles/ntt.h.tmpl b/goicicle/templates/hfiles/ntt.h.tmpl deleted file mode 100644 index 07fc474c4..000000000 --- a/goicicle/templates/hfiles/ntt.h.tmpl +++ /dev/null @@ -1,181 +0,0 @@ -#include -#include -// ntt.h - -#ifndef _{{.CurveNameUpperCase}}_NTT_H -#define _{{.CurveNameUpperCase}}_NTT_H - -#ifdef __cplusplus -extern "C" { -#endif - -// Incomplete declaration of {{.CurveNameUpperCase}} projective and affine structs -typedef struct {{.CurveNameUpperCase}}_projective_t {{.CurveNameUpperCase}}_projective_t; -typedef struct {{.CurveNameUpperCase}}_affine_t {{.CurveNameUpperCase}}_affine_t; -typedef struct {{.CurveNameUpperCase}}_scalar_t {{.CurveNameUpperCase}}_scalar_t; - -typedef struct {{.CurveNameUpperCase}}_g2_projective_t {{.CurveNameUpperCase}}_g2_projective_t; -typedef struct {{.CurveNameUpperCase}}_g2_affine_t {{.CurveNameUpperCase}}_g2_affine_t; - -int ntt_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_scalar_t* arr, uint32_t n, bool inverse, size_t device_id); -int ntt_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -int ecntt_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* arr, uint32_t n, bool inverse, size_t device_id); -int ecntt_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* arr, uint32_t arr_size, uint32_t batch_size, bool inverse, size_t device_id); - -{{.CurveNameUpperCase}}_scalar_t* -build_domain_cuda_{{.CurveNameLowerCase}}(uint32_t domain_size, uint32_t logn, bool inverse, size_t device_id, size_t stream); - -int interpolate_scalars_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_evaluations, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned n, - unsigned device_id, - size_t stream); -int interpolate_scalars_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_evaluations, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_points_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_projective_t* d_evaluations, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned n, - size_t device_id, - size_t stream); -int interpolate_points_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_projective_t* d_evaluations, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int interpolate_scalars_on_coset_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_evaluations, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned n, - {{.CurveNameUpperCase}}_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int interpolate_scalars_batch_on_coset_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_evaluations, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned n, - unsigned batch_size, - {{.CurveNameUpperCase}}_scalar_t* coset_powers, - size_t device_id, - size_t stream); - -int evaluate_scalars_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned device_id, - size_t stream); -int evaluate_scalars_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_points_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_projective_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - size_t device_id, - size_t stream); -int evaluate_points_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_projective_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - size_t device_id, - size_t stream); -int evaluate_scalars_on_coset_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - {{.CurveNameUpperCase}}_scalar_t* coset_powers, - unsigned device_id, - size_t stream); -int evaluate_scalars_on_coset_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, - {{.CurveNameUpperCase}}_scalar_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - {{.CurveNameUpperCase}}_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_projective_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - {{.CurveNameUpperCase}}_scalar_t* coset_powers, - size_t device_id, - size_t stream); -int evaluate_points_on_coset_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* d_out, - {{.CurveNameUpperCase}}_projective_t* d_coefficients, - {{.CurveNameUpperCase}}_scalar_t* d_domain, - unsigned domain_size, - unsigned n, - unsigned batch_size, - {{.CurveNameUpperCase}}_scalar_t* coset_powers, - size_t device_id, - size_t stream); - -int reverse_order_scalars_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_scalar_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_scalars_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int reverse_order_points_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* arr, int n, size_t device_id, size_t stream); -int reverse_order_points_batch_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* arr, int n, int batch_size, size_t device_id, size_t stream); -int add_scalars_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, {{.CurveNameUpperCase}}_scalar_t* d_in1, {{.CurveNameUpperCase}}_scalar_t* d_in2, unsigned n, size_t stream); -int sub_scalars_cuda_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* d_out, {{.CurveNameUpperCase}}_scalar_t* d_in1, {{.CurveNameUpperCase}}_scalar_t* d_in2, unsigned n, size_t stream); -int to_montgomery_scalars_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_scalar_t* d_inout, unsigned n, size_t stream); -int from_montgomery_scalars_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_scalar_t* d_inout, unsigned n, size_t stream); - -// points g1 -int to_montgomery_proj_points_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_affine_t* d_inout, unsigned n, size_t stream); - -// points g2 -int to_montgomery_proj_points_g2_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_projective_t* d_inout, unsigned n, size_t stream); -int from_montgomery_proj_points_g2_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_projective_t* d_inout, unsigned n, size_t stream); -int to_montgomery_aff_points_g2_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_affine_t* d_inout, unsigned n, size_t stream); -int from_montgomery_aff_points_g2_cuda_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_affine_t* d_inout, unsigned n, size_t stream); - -#ifdef __cplusplus -} -#endif - -#endif /* _{{.CurveNameUpperCase}}_NTT_H */ diff --git a/goicicle/templates/hfiles/projective.h.tmpl b/goicicle/templates/hfiles/projective.h.tmpl deleted file mode 100644 index 431fd10f3..000000000 --- a/goicicle/templates/hfiles/projective.h.tmpl +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -// projective.h - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct {{.CurveNameUpperCase}}_projective_t {{.CurveNameUpperCase}}_projective_t; -typedef struct {{.CurveNameUpperCase}}_g2_projective_t {{.CurveNameUpperCase}}_g2_projective_t; -typedef struct {{.CurveNameUpperCase}}_affine_t {{.CurveNameUpperCase}}_affine_t; -typedef struct {{.CurveNameUpperCase}}_g2_affine_t {{.CurveNameUpperCase}}_g2_affine_t; -typedef struct {{.CurveNameUpperCase}}_scalar_t {{.CurveNameUpperCase}}_scalar_t; - -bool projective_is_on_curve_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* point1); - -int random_scalar_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_scalar_t* out); -int random_projective_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* out); -{{.CurveNameUpperCase}}_projective_t* projective_zero_{{.CurveNameLowerCase}}(); -int projective_to_affine_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_affine_t* out, {{.CurveNameUpperCase}}_projective_t* point1); -int projective_from_affine_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* out, {{.CurveNameUpperCase}}_affine_t* point1); - -int random_g2_projective_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_projective_t* out); -int g2_projective_to_affine_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_affine_t* out, {{.CurveNameUpperCase}}_g2_projective_t* point1); -int g2_projective_from_affine_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_projective_t* out, {{.CurveNameUpperCase}}_g2_affine_t* point1); -bool g2_projective_is_on_curve_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_projective_t* point1); - -bool eq_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_projective_t* point1, {{.CurveNameUpperCase}}_projective_t* point2); -bool eq_g2_{{.CurveNameLowerCase}}({{.CurveNameUpperCase}}_g2_projective_t* point1, {{.CurveNameUpperCase}}_g2_projective_t* point2); - -#ifdef __cplusplus -} -#endif diff --git a/goicicle/templates/hfiles/ve_mod_mult.h.tmpl b/goicicle/templates/hfiles/ve_mod_mult.h.tmpl deleted file mode 100644 index 8339416f7..000000000 --- a/goicicle/templates/hfiles/ve_mod_mult.h.tmpl +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -// ve_mod_mult.h - -#ifndef _{{.CurveNameUpperCase}}_VEC_MULT_H -#define _{{.CurveNameUpperCase}}_VEC_MULT_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct {{.CurveNameUpperCase}}_projective_t {{.CurveNameUpperCase}}_projective_t; -typedef struct {{.CurveNameUpperCase}}_scalar_t {{.CurveNameUpperCase}}_scalar_t; - -int32_t vec_mod_mult_point_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_projective_t* inout, {{.CurveNameUpperCase}}_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_scalar_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* inout, {{.CurveNameUpperCase}}_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_device_scalar_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* inout, {{.CurveNameUpperCase}}_scalar_t* scalar_vec, size_t n_elements, size_t device_id); -int32_t matrix_vec_mod_mult_{{.CurveNameLowerCase}}( - {{.CurveNameUpperCase}}_scalar_t* matrix_flattened, - {{.CurveNameUpperCase}}_scalar_t* input, - {{.CurveNameUpperCase}}_scalar_t* output, - size_t n_elments, - size_t device_id); - -#ifdef __cplusplus -} -#endif - -#endif /* _{{.CurveNameUpperCase}}_VEC_MULT_H */ diff --git a/goicicle/templates/main.go b/goicicle/templates/main.go deleted file mode 100644 index 570d927d8..000000000 --- a/goicicle/templates/main.go +++ /dev/null @@ -1,312 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/consensys/bavard" - config "github.com/ingonyama-zk/icicle/goicicle/templates/curves" -) - -const ( - copyrightHolder = "Ingonyama" - generatedBy = "Ingonyama" - copyrightYear = 2023 - baseDir = "../curves/" -) - -var bgen = bavard.NewBatchGenerator(copyrightHolder, copyrightYear, generatedBy) - -func genMainFiles() { - bn254_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "g1.go"), Templates: []string{"g1.go.tmpl"}}, - } - - bls12377_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "g1.go"), Templates: []string{"g1.go.tmpl"}}, - } - - bls12381_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "g1.go"), Templates: []string{"g1.go.tmpl"}}, - } - - bw6761_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "g1.go"), Templates: []string{"g1.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./curves/", bls12377_entries...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./curves/", bn254_entries...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./curves/", bls12381_entries...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./curves/", bw6761_entries...)) - - bn254_g2_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "g2.go"), Templates: []string{"g2.go.tmpl"}}, - } - - bls12377_g2_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "g2.go"), Templates: []string{"g2.go.tmpl"}}, - } - - bls12381_g2_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "g2.go"), Templates: []string{"g2.go.tmpl"}}, - } - - bw6761_g2_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "g2.go"), Templates: []string{"g2.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./curves/", bls12377_g2_entries...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./curves/", bn254_g2_entries...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./curves/", bls12381_g2_entries...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./curves/", bw6761_g2_entries...)) - - bn254_msm_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "msm.go"), Templates: []string{"msm.go.tmpl"}}, - } - - bls12377_msm_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "msm.go"), Templates: []string{"msm.go.tmpl"}}, - } - - bls12381_msm_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "msm.go"), Templates: []string{"msm.go.tmpl"}}, - } - - bw6761_msm_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "msm.go"), Templates: []string{"msm.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./msm/", bls12377_msm_entries...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./msm/", bn254_msm_entries...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./msm/", bls12381_msm_entries...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./msm/", bw6761_msm_entries...)) - - bn254_ntt_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "ntt.go"), Templates: []string{"ntt.go.tmpl"}}, - } - - bls12377_ntt_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "ntt.go"), Templates: []string{"ntt.go.tmpl"}}, - } - - bls12381_ntt_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "ntt.go"), Templates: []string{"ntt.go.tmpl"}}, - } - - bw6761_ntt_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "ntt.go"), Templates: []string{"ntt.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./ntt/", bls12377_ntt_entries...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./ntt/", bn254_ntt_entries...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./ntt/", bls12381_ntt_entries...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./ntt/", bw6761_ntt_entries...)) - - bn254_vec_mod_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "vec_mod.go"), Templates: []string{"vec_mod.go.tmpl"}}, - } - - bls12377_vec_mod_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "vec_mod.go"), Templates: []string{"vec_mod.go.tmpl"}}, - } - - bls12381_vec_mod_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "vec_mod.go"), Templates: []string{"vec_mod.go.tmpl"}}, - } - - bw6761_vec_mod_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "vec_mod.go"), Templates: []string{"vec_mod.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./ops/", bls12377_vec_mod_entries...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./ops/", bn254_vec_mod_entries...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./ops/", bls12381_vec_mod_entries...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./ops/", bw6761_vec_mod_entries...)) - - h_msm_bn254 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "include", "msm.h"), Templates: []string{"msm.h.tmpl"}}, - } - - h_msm_bls12377 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "include", "msm.h"), Templates: []string{"msm.h.tmpl"}}, - } - - h_msm_bls12381 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "include", "msm.h"), Templates: []string{"msm.h.tmpl"}}, - } - - h_msm_bw6761 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "include", "msm.h"), Templates: []string{"msm.h.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./hfiles/", h_msm_bls12377...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./hfiles/", h_msm_bn254...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./hfiles/", h_msm_bls12381...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./hfiles/", h_msm_bw6761...)) - - h_ntt_bn254 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "include", "ntt.h"), Templates: []string{"ntt.h.tmpl"}}, - } - - h_ntt_bls12377 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "include", "ntt.h"), Templates: []string{"ntt.h.tmpl"}}, - } - - h_ntt_bls12381 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "include", "ntt.h"), Templates: []string{"ntt.h.tmpl"}}, - } - - h_ntt_bw6761 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "include", "ntt.h"), Templates: []string{"ntt.h.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./hfiles/", h_ntt_bls12377...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./hfiles/", h_ntt_bn254...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./hfiles/", h_ntt_bls12381...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./hfiles/", h_ntt_bw6761...)) - - ve_mod_mult_h_bn254 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "include", "ve_mod_mult.h"), Templates: []string{"ve_mod_mult.h.tmpl"}}, - } - - ve_mod_mult_h_bls12377 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "include", "ve_mod_mult.h"), Templates: []string{"ve_mod_mult.h.tmpl"}}, - } - - ve_mod_mult_ht_bls12381 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "include", "ve_mod_mult.h"), Templates: []string{"ve_mod_mult.h.tmpl"}}, - } - - ve_mod_mult_ht_bw6761 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "include", "ve_mod_mult.h"), Templates: []string{"ve_mod_mult.h.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./hfiles/", ve_mod_mult_h_bls12377...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./hfiles/", ve_mod_mult_h_bn254...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./hfiles/", ve_mod_mult_ht_bls12381...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./hfiles/", ve_mod_mult_ht_bw6761...)) - - projective_bn254 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "include", "projective.h"), Templates: []string{"projective.h.tmpl"}}, - } - - projective_bls12377 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "include", "projective.h"), Templates: []string{"projective.h.tmpl"}}, - } - - projective_bls12381 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "include", "projective.h"), Templates: []string{"projective.h.tmpl"}}, - } - - projective_bw6761 := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "include", "projective.h"), Templates: []string{"projective.h.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./hfiles/", projective_bls12377...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./hfiles/", projective_bn254...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./hfiles/", projective_bls12381...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./hfiles/", projective_bw6761...)) -} - -func genTestFiles() { - // G1 TESTS - bn254_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "g1_test.go"), Templates: []string{"g1_test.go.tmpl"}}, - } - - bls12377_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "g1_test.go"), Templates: []string{"g1_test.go.tmpl"}}, - } - - bls12381_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "g1_test.go"), Templates: []string{"g1_test.go.tmpl"}}, - } - - bw6761_entries := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "g1_test.go"), Templates: []string{"g1_test.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./curves/", bls12377_entries...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./curves/", bn254_entries...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./curves/", bls12381_entries...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./curves/", bw6761_entries...)) - - // G2 TESTS - bn254_entries_g2_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "g2_test.go"), Templates: []string{"g2_test.go.tmpl"}}, - } - - bls12377_entries_g2_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "g2_test.go"), Templates: []string{"g2_test.go.tmpl"}}, - } - - bls12381_entries_g2_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "g2_test.go"), Templates: []string{"g2_test.go.tmpl"}}, - } - - bw6761_entries_g2_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "g2_test.go"), Templates: []string{"g2_test.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./curves/", bls12377_entries_g2_test...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./curves/", bn254_entries_g2_test...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./curves/", bls12381_entries_g2_test...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./curves/", bw6761_entries_g2_test...)) - - // MSM TEST - bn254_entries_msm_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "msm_test.go"), Templates: []string{"msm_test.go.tmpl"}}, - } - - bls12377_entries_msm_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "msm_test.go"), Templates: []string{"msm_test.go.tmpl"}}, - } - - bls12381_entries_msm_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "msm_test.go"), Templates: []string{"msm_test.go.tmpl"}}, - } - - bw6761_entries_msm_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "msm_test.go"), Templates: []string{"msm_test.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./msm/", bls12377_entries_msm_test...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./msm/", bn254_entries_msm_test...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./msm/", bls12381_entries_msm_test...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./msm/", bw6761_entries_msm_test...)) - - // FFT TEST - bn254_entries_fft_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bn254", "ntt_test.go"), Templates: []string{"ntt_test.go.tmpl"}}, - } - - bls12377_entries_fft_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12377", "ntt_test.go"), Templates: []string{"ntt_test.go.tmpl"}}, - } - - bls12381_entries_fft_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bls12381", "ntt_test.go"), Templates: []string{"ntt_test.go.tmpl"}}, - } - - bw6761_entries_msm_test_entries_fft_test := []bavard.Entry{ - {File: filepath.Join(baseDir, "bw6761", "ntt_test.go"), Templates: []string{"ntt_test.go.tmpl"}}, - } - - assertNoError(bgen.Generate(config.BLS_12_377, config.BLS_12_377.PackageName, "./ntt/", bls12377_entries_fft_test...)) - assertNoError(bgen.Generate(config.BN_254, config.BN_254.PackageName, "./ntt/", bn254_entries_fft_test...)) - assertNoError(bgen.Generate(config.BLS_12_381, config.BLS_12_381.PackageName, "./ntt/", bls12381_entries_fft_test...)) - assertNoError(bgen.Generate(config.BW6_761, config.BW6_761.PackageName, "./ntt/", bw6761_entries_msm_test_entries_fft_test...)) -} - -func main() { - genMainFiles() - genTestFiles() -} - -func assertNoError(err error) { - if err != nil { - fmt.Printf("\n%s\n", err.Error()) - os.Exit(-1) - } -} diff --git a/goicicle/templates/msm/msm.go.tmpl b/goicicle/templates/msm/msm.go.tmpl deleted file mode 100644 index 72703069c..000000000 --- a/goicicle/templates/msm/msm.go.tmpl +++ /dev/null @@ -1,191 +0,0 @@ -import ( - "errors" - "fmt" - "unsafe" -) - -// #cgo CFLAGS: -I./include/ -// #cgo CFLAGS: -I/usr/local/cuda/include -// #cgo LDFLAGS: -L${SRCDIR}/../../ {{.SharedLib}} -// #include "msm.h" -import "C" - -func Msm(out *G1ProjectivePoint, points []G1PointAffine, scalars []G1ScalarField, device_id int) (*G1ProjectivePoint, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.{{.CurveNameUpperCase}}_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(out)) - ret := C.msm_cuda_{{.CurveNameLowerCase}}(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_cuda_{{.CurveNameLowerCase}} returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2(out *G2Point, points []G2PointAffine, scalars []G1ScalarField, device_id int) (*G2Point, error) { - if len(points) != len(scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - pointsC := (*C.{{.CurveNameUpperCase}}_g2_affine_t)(unsafe.Pointer(&points[0])) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&scalars[0])) - outC := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(out)) - - ret := C.msm_g2_cuda_{{.CurveNameLowerCase}}(outC, pointsC, scalarsC, C.size_t(len(points)), C.size_t(device_id)) - - if ret != 0 { - return nil, fmt.Errorf("msm_g2_cuda_{{.CurveNameLowerCase}} returned error code: %d", ret) - } - - return out, nil -} - -func MsmBatch(points *[]G1PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G1ProjectivePoint, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G1ProjectivePoint, batchSize) - - for i := 0; i < len(out); i++ { - var p G1ProjectivePoint - p.SetZero() - - out[i] = p - } - - outC := (*C.{{.CurveNameUpperCase}}_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.{{.CurveNameUpperCase}}_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_cuda_{{.CurveNameLowerCase}}(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_{{.CurveNameLowerCase}} returned error code: %d", ret) - } - - return out, nil -} - -func MsmG2Batch(points *[]G2PointAffine, scalars *[]G1ScalarField, batchSize, deviceId int) ([]G2Point, error) { - // Check for nil pointers - if points == nil || scalars == nil { - return nil, errors.New("points or scalars is nil") - } - - if len(*points) != len(*scalars) { - return nil, errors.New("error on: len(points) != len(scalars)") - } - - // Check for empty slices - if len(*points) == 0 || len(*scalars) == 0 { - return nil, errors.New("points or scalars is empty") - } - - // Check for zero batchSize - if batchSize <= 0 { - return nil, errors.New("error on: batchSize must be greater than zero") - } - - out := make([]G2Point, batchSize) - - outC := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(unsafe.Pointer(&out[0])) - pointsC := (*C.{{.CurveNameUpperCase}}_g2_affine_t)(unsafe.Pointer(&(*points)[0])) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(unsafe.Pointer(&(*scalars)[0])) - msmSizeC := C.size_t(len(*points) / batchSize) - deviceIdC := C.size_t(deviceId) - batchSizeC := C.size_t(batchSize) - - ret := C.msm_batch_g2_cuda_{{.CurveNameLowerCase}}(outC, pointsC, scalarsC, batchSizeC, msmSizeC, deviceIdC) - if ret != 0 { - return nil, fmt.Errorf("msm_batch_cuda_{{.CurveNameLowerCase}} returned error code: %d", ret) - } - - return out, nil -} - -func Commit(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.{{.CurveNameUpperCase}}_projective_t)(d_out) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(d_scalars) - pointsC := (*C.{{.CurveNameUpperCase}}_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_cuda_{{.CurveNameLowerCase}}(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2(d_out, d_scalars, d_points unsafe.Pointer, count, bucketFactor int) int { - d_outC := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(d_out) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(d_scalars) - pointsC := (*C.{{.CurveNameUpperCase}}_g2_affine_t)(d_points) - countC := (C.size_t)(count) - largeBucketFactorC := C.uint(bucketFactor) - - ret := C.commit_g2_cuda_{{.CurveNameLowerCase}}(d_outC, scalarsC, pointsC, countC, largeBucketFactorC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitBatch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.{{.CurveNameUpperCase}}_projective_t)(d_out) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(d_scalars) - pointsC := (*C.{{.CurveNameUpperCase}}_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.commit_batch_cuda_{{.CurveNameLowerCase}}(d_outC, scalarsC, pointsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} - -func CommitG2Batch(d_out, d_scalars, d_points unsafe.Pointer, count, batch_size int) int { - d_outC := (*C.{{.CurveNameUpperCase}}_g2_projective_t)(d_out) - scalarsC := (*C.{{.CurveNameUpperCase}}_scalar_t)(d_scalars) - pointsC := (*C.{{.CurveNameUpperCase}}_g2_affine_t)(d_points) - countC := (C.size_t)(count) - batch_sizeC := (C.size_t)(batch_size) - - ret := C.msm_batch_g2_cuda_{{.CurveNameLowerCase}}(d_outC, pointsC, scalarsC, countC, batch_sizeC, 0) - - if ret != 0 { - return -1 - } - - return 0 -} diff --git a/goicicle/templates/msm/msm_test.go.tmpl b/goicicle/templates/msm/msm_test.go.tmpl deleted file mode 100644 index 4f757ec33..000000000 --- a/goicicle/templates/msm/msm_test.go.tmpl +++ /dev/null @@ -1,342 +0,0 @@ -import ( - "fmt" - "math" - "testing" - "time" - "unsafe" - - "github.com/ingonyama-zk/icicle/goicicle" - "github.com/stretchr/testify/assert" -) - -func GeneratePoints(count int) []G1PointAffine { - // Declare a slice of integers - var points []G1PointAffine - - // populate the slice - for i := 0; i < 10; i++ { - var pointProjective G1ProjectivePoint - pointProjective.Random() - - var pointAffine G1PointAffine - pointAffine.FromProjective(&pointProjective) - - points = append(points, pointAffine) - } - - log2_10 := math.Log2(10) - log2Count := math.Log2(float64(count)) - log2Size := int(math.Ceil(log2Count - log2_10)) - - for i := 0; i < log2Size; i++ { - points = append(points, points...) - } - - return points[:count] -} - -func GeneratePointsProj(count int) []G1ProjectivePoint { - // Declare a slice of integers - var points []G1ProjectivePoint - // Use a loop to populate the slice - for i := 0; i < count; i++ { - var p G1ProjectivePoint - p.Random() - - points = append(points, p) - } - - return points -} - -func GenerateScalars(count int, skewed bool) []G1ScalarField { - // Declare a slice of integers - var scalars []G1ScalarField - - var rand G1ScalarField - var zero G1ScalarField - var one G1ScalarField - var randLarge G1ScalarField - - zero.SetZero() - one.SetOne() - randLarge.Random() - - if skewed && count > 1_200_000 { - for i := 0; i < count-1_200_000; i++ { - rand.Random() - scalars = append(scalars, rand) - } - - for i := 0; i < 600_000; i++ { - scalars = append(scalars, randLarge) - } - for i := 0; i < 400_000; i++ { - scalars = append(scalars, zero) - } - for i := 0; i < 200_000; i++ { - scalars = append(scalars, one) - } - } else { - for i := 0; i < count; i++ { - rand.Random() - scalars = append(scalars, rand) - } - } - - return scalars[:count] -} - -func TestMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1 << v - - points := GeneratePoints(count) - fmt.Print("Finished generating points\n") - scalars := GenerateScalars(count, false) - fmt.Print("Finished generating scalars\n") - - out := new(G1ProjectivePoint) - startTime := time.Now() - _, e := Msm(out, points, scalars, 0) // non mont - fmt.Printf("icicle MSM took: %d ms\n", time.Since(startTime).Milliseconds()) - - assert.Equal(t, e, nil, "error should be nil") - - assert.True(t, out.IsOnCurve()) - } -} - -func TestCommitMSM(t *testing.T) { - for _, v := range []int{8} { - count := 1< [G2_enabled] + +curve - The name of the curve to build or "all" to build all curves +G2_enabled - Optional - To build with G2 enabled +``` + +To build ICICLE libraries for all supported curves with G2 enabled. + +``` +./build.sh all ON +``` + +If you wish to build for a specific curve, for example bn254, without G2 enabled. + +``` +./build.sh bn254 +``` + +>[!NOTE] +>Current supported curves are `bn254`, `bls12_381`, `bls12_377` and `bw6_671` + +>[!NOTE] +>G2 is enabled by building your golang project with the build tag `g2` +>Make sure to add it to your build tags if you want it enabled + +## Running golang tests + +To run the tests for curve bn254. + +``` +go test ./wrappers/golang/curves/bn254 -count=1 +``` + +To run all the tests in the golang bindings + +``` +go test --tags=g2 ./... -count=1 +``` + +## How do Golang bindings work? + +The libraries produced from the CUDA code compilation are used to bind Golang to ICICLE's CUDA code. + +1. These libraries (named `libingo_.a`) can be imported in your Go project to leverage the GPU accelerated functionalities provided by ICICLE. + +2. In your Go project, you can use `cgo` to link these libraries. Here's a basic example on how you can use `cgo` to link these libraries: + +```go +/* +#cgo LDFLAGS: -L/path/to/shared/libs -lingo_bn254 +#include "icicle.h" // make sure you use the correct header file(s) +*/ +import "C" + +func main() { + // Now you can call the C functions from the ICICLE libraries. + // Note that C function calls are prefixed with 'C.' in Go code. +} +``` + +Replace `/path/to/shared/libs` with the actual path where the shared libraries are located on your system. + +## Common issues + +### Cannot find shared library + +In some cases you may encounter the following error, despite exporting the correct `LD_LIBRARY_PATH`. + +``` +/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1 +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +/usr/bin/ld: cannot find -lbn254: No such file or directory +collect2: error: ld returned 1 exit status +``` + +This is normally fixed by exporting the path to the shared library location in the following way: `export CGO_LDFLAGS="-L//"` + +### cuda_runtime.h: No such file or directory + +``` +# github.com/ingonyama-zk/icicle/wrappers/golang/curves/bls12381 +In file included from wrappers/golang/curves/bls12381/curve.go:5: +wrappers/golang/curves/bls12381/include/curve.h:1:10: fatal error: cuda_runtime.h: No such file or directory + 1 | #include + | ^~~~~~~~~~~~~~~~ +compilation terminated. +``` + +Our golang bindings rely on cuda headers and require that they can be found as system headers. Make sure to add the `cuda/include` of your cuda installation to your CPATH + +``` +export CPATH=$CPATH: +``` diff --git a/wrappers/golang/build.sh b/wrappers/golang/build.sh new file mode 100755 index 000000000..56ada79db --- /dev/null +++ b/wrappers/golang/build.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +G2_DEFINED=OFF + +if [[ $2 ]] +then + G2_DEFINED=ON +fi + +BUILD_DIR=$(realpath "$PWD/../../icicle/build") +SUPPORTED_CURVES=("bn254" "bls12_377" "bls12_381" "bw6_761") + +if [[ $1 == "all" ]] +then + BUILD_CURVES=("${SUPPORTED_CURVES[@]}") +else + BUILD_CURVES=( $1 ) +fi + +cd ../../icicle +mkdir -p build + +for CURVE in "${BUILD_CURVES[@]}" +do + cmake -DCURVE=$CURVE -DG2_DEFINED=$G2_DEFINED -DCMAKE_BUILD_TYPE=Release -S . -B build + cmake --build build +done \ No newline at end of file diff --git a/wrappers/golang/core/error.go b/wrappers/golang/core/error.go new file mode 100644 index 000000000..08b112715 --- /dev/null +++ b/wrappers/golang/core/error.go @@ -0,0 +1,43 @@ +package core + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type IcicleErrorCode int + +const ( + IcicleSuccess IcicleErrorCode = 0 + InvalidArgument IcicleErrorCode = 1 + MemoryAllocationError IcicleErrorCode = 2 + InternalCudaError IcicleErrorCode = 199999999 + UndefinedError IcicleErrorCode = 999999999 +) + +type IcicleError struct { + IcicleErrorCode IcicleErrorCode + CudaErrorCode cuda_runtime.CudaError + reason string +} + +func FromCudaError(error cuda_runtime.CudaError) (err IcicleError) { + switch error { + case cuda_runtime.CudaSuccess: + err.IcicleErrorCode = IcicleSuccess + default: + err.IcicleErrorCode = InternalCudaError + } + + err.CudaErrorCode = error + err.reason = "Runtime CUDA error." + + return err +} + +func FromCodeAndReason(code IcicleErrorCode, reason string) IcicleError { + return IcicleError{ + IcicleErrorCode: code, + reason: reason, + CudaErrorCode: cuda_runtime.CudaErrorUnknown, + } +} diff --git a/wrappers/golang/core/internal/curve.go b/wrappers/golang/core/internal/curve.go new file mode 100644 index 000000000..b5a4185e7 --- /dev/null +++ b/wrappers/golang/core/internal/curve.go @@ -0,0 +1,76 @@ +package internal + +type MockProjective struct { + X, Y, Z MockField +} + +func (p MockProjective) Size() int { + return p.X.Size() * 3 +} + +func (p MockProjective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *MockProjective) Zero() MockProjective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *MockProjective) FromLimbs(x, y, z []uint32) MockProjective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *MockProjective) FromAffine(a MockAffine) MockProjective { + z := MockField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +type MockAffine struct { + X, Y MockField +} + +func (a MockAffine) Size() int { + return a.X.Size() * 2 +} + +func (a MockAffine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *MockAffine) Zero() MockAffine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *MockAffine) FromLimbs(x, y []uint32) MockAffine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a MockAffine) ToProjective() MockProjective { + var z MockField + + return MockProjective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} diff --git a/wrappers/golang/core/internal/curve_test.go b/wrappers/golang/core/internal/curve_test.go new file mode 100644 index 000000000..0314a770a --- /dev/null +++ b/wrappers/golang/core/internal/curve_test.go @@ -0,0 +1,101 @@ +package internal + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestMockAffineZero(t *testing.T) { + var fieldZero = MockField{} + + var affineZero MockAffine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(BASE_LIMBS)) + y := generateRandomLimb(int(BASE_LIMBS)) + var affine MockAffine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestMockAffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + + var affine MockAffine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestMockAffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne MockField + fieldOne.One() + + var expected MockProjective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine MockAffine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestMockProjectiveZero(t *testing.T) { + var projectiveZero MockProjective + projectiveZero.Zero() + var fieldZero = MockField{} + var fieldOne MockField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + var projective MockProjective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestMockProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(BASE_LIMBS)) + + var projective MockProjective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestMockProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne MockField + fieldOne.One() + + var expected MockProjective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine MockAffine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint MockProjective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/core/internal/field.go b/wrappers/golang/core/internal/field.go new file mode 100644 index 000000000..b35025569 --- /dev/null +++ b/wrappers/golang/core/internal/field.go @@ -0,0 +1,79 @@ +package internal + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int8 = 8 +) + +type MockField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f MockField) Len() int { + return int(BASE_LIMBS) +} + +func (f MockField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f MockField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f MockField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *MockField) FromLimbs(limbs []uint32) MockField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *MockField) Zero() MockField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *MockField) One() MockField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *MockField) FromBytesLittleEndian(bytes []byte) MockField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f MockField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/core/internal/field_test.go b/wrappers/golang/core/internal/field_test.go new file mode 100644 index 000000000..c9a2b0f33 --- /dev/null +++ b/wrappers/golang/core/internal/field_test.go @@ -0,0 +1,82 @@ +package internal + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestMockFieldFromLimbs(t *testing.T) { + emptyField := MockField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the MockField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestMockFieldGetLimbs(t *testing.T) { + emptyField := MockField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the MockField's limbs") +} + +func TestMockFieldOne(t *testing.T) { + var emptyField MockField + emptyField.One() + limbOne := generateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "MockField with limbs to field one did not work") +} + +func TestMockFieldZero(t *testing.T) { + var emptyField MockField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "MockField with limbs to field zero failed") +} + +func TestMockFieldSize(t *testing.T) { + var emptyField MockField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestMockFieldAsPointer(t *testing.T) { + var emptyField MockField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestMockFieldFromBytes(t *testing.T) { + var emptyField MockField + bytes, expected := generateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestMockFieldToBytes(t *testing.T) { + var emptyField MockField + expected, limbs := generateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/core/internal/helpers_test.go b/wrappers/golang/core/internal/helpers_test.go new file mode 100644 index 000000000..2c24f7942 --- /dev/null +++ b/wrappers/golang/core/internal/helpers_test.go @@ -0,0 +1,31 @@ +package internal + +import ( + "math/rand" +) + +func generateRandomLimb(size int) []uint32 { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + return limbs +} + +func generateLimbOne(size int) []uint32 { + limbs := make([]uint32, size) + limbs[0] = 1 + return limbs +} + +func generateBytesArray(size int) ([]byte, []uint32) { + baseBytes := []byte{1, 2, 3, 4} + var bytes []byte + var limbs []uint32 + for i := 0; i < size; i++ { + bytes = append(bytes, baseBytes...) + limbs = append(limbs, 67305985) + } + + return bytes, limbs +} diff --git a/wrappers/golang/core/msm.go b/wrappers/golang/core/msm.go new file mode 100644 index 000000000..ed9fdb83f --- /dev/null +++ b/wrappers/golang/core/msm.go @@ -0,0 +1,106 @@ +package core + +import ( + "fmt" + + "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type MSMConfig struct { + /// Details related to the device such as its id and stream. + Ctx cuda_runtime.DeviceContext + + pointsSize int32 + + /// The number of extra points to pre-compute for each point. Larger values decrease the number of computations + /// to make, on-line memory footprint, but increase the static memory footprint. Default value: 1 (i.e. don't pre-compute). + PrecomputeFactor int32 + + /// `c` value, or "window bitsize" which is the main parameter of the "bucket method" + /// that we use to solve the MSM problem. As a rule of thumb, larger value means more on-line memory + /// footprint but also more parallelism and less computational complexity (up to a certain point). + /// Default value: 0 (the optimal value of `c` is chosen automatically). + C int32 + + /// Number of bits of the largest scalar. Typically equals the bitsize of scalar field, but if a different + /// (better) upper bound is known, it should be reflected in this variable. Default value: 0 (set to the bitsize of scalar field). + Bitsize int32 + + /// Variable that controls how sensitive the algorithm is to the buckets that occur very frequently. + /// Useful for efficient treatment of non-uniform distributions of scalars and "top windows" with few bits. + /// Can be set to 0 to disable separate treatment of large buckets altogether. Default value: 10. + LargeBucketFactor int32 + + batchSize int32 + + areScalarsOnDevice bool + + /// True if scalars are in Montgomery form and false otherwise. Default value: true. + AreScalarsMontgomeryForm bool + + arePointsOnDevice bool + + /// True if coordinates of points are in Montgomery form and false otherwise. Default value: true. + ArePointsMontgomeryForm bool + + areResultsOnDevice bool + + /// Whether to do "bucket accumulation" serially. Decreases computational complexity, but also greatly + /// decreases parallelism, so only suitable for large batches of MSMs. Default value: false. + IsBigTriangle bool + + /// Whether to run the MSM asynchronously. If set to `true`, the MSM function will be non-blocking + /// and you'd need to synchronize it explicitly by running `cudaStreamSynchronize` or `cudaDeviceSynchronize`. + /// If set to `false`, the MSM function will block the current CPU thread. + IsAsync bool +} + +// type MSM interface { +// Msm(scalars, points *cuda_runtime.HostOrDeviceSlice, cfg *MSMConfig, results *cuda_runtime.HostOrDeviceSlice) cuda_runtime.CudaError +// GetDefaultMSMConfig() MSMConfig +// } + +func GetDefaultMSMConfig() MSMConfig { + ctx, _ := cuda_runtime.GetDefaultDeviceContext() + return MSMConfig{ + ctx, // Ctx + 0, // pointsSize + 1, // PrecomputeFactor + 0, // C + 0, // Bitsize + 10, // LargeBucketFactor + 1, // batchSize + false, // areScalarsOnDevice + false, // AreScalarsMontgomeryForm + false, // arePointsOnDevice + false, // ArePointsMontgomeryForm + false, // areResultsOnDevice + false, // IsBigTriangle + false, // IsAsync + } +} + +func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfig, results HostOrDeviceSlice) { + scalarsLength, pointsLength, resultsLength := scalars.Len(), points.Len(), results.Len() + if scalarsLength%pointsLength != 0 { + errorString := fmt.Sprintf( + "Number of points %d does not divide the number of scalars %d", + pointsLength, + scalarsLength, + ) + panic(errorString) + } + if scalarsLength%resultsLength != 0 { + errorString := fmt.Sprintf( + "Number of results %d does not divide the number of scalars %d", + resultsLength, + scalarsLength, + ) + panic(errorString) + } + cfg.pointsSize = int32(pointsLength) + cfg.batchSize = int32(resultsLength) + cfg.areScalarsOnDevice = scalars.IsOnDevice() + cfg.arePointsOnDevice = points.IsOnDevice() + cfg.areResultsOnDevice = results.IsOnDevice() +} diff --git a/wrappers/golang/core/msm_test.go b/wrappers/golang/core/msm_test.go new file mode 100644 index 000000000..8b1cc820f --- /dev/null +++ b/wrappers/golang/core/msm_test.go @@ -0,0 +1,106 @@ +package core + +import ( + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core/internal" + "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/stretchr/testify/assert" +) + +func TestMSMDefaultConfig(t *testing.T) { + ctx, _ := cuda_runtime.GetDefaultDeviceContext() + expected := MSMConfig{ + ctx, // Ctx + 0, // pointsSize + 1, // PrecomputeFactor + 0, // C + 0, // Bitsize + 10, // LargeBucketFactor + 1, // batchSize + false, // areScalarsOnDevice + false, // AreScalarsMontgomeryForm + false, // arePointsOnDevice + false, // ArePointsMontgomeryForm + false, // areResultsOnDevice + false, // IsBigTriangle + false, // IsAsync + } + + actual := GetDefaultMSMConfig() + + assert.Equal(t, expected, actual) +} + +func TestMSMCheckHostSlices(t *testing.T) { + cfg := GetDefaultMSMConfig() + + randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8} + rawScalars := make([]internal.MockField, 10) + for i := range rawScalars { + var emptyField internal.MockField + emptyField.FromLimbs(randLimbs) + + rawScalars[i] = emptyField + } + scalars := HostSliceFromElements[internal.MockField](rawScalars) + + affine := internal.MockAffine{} + limbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8} + affine.FromLimbs(limbs, limbs) + rawAffinePoints := make([]internal.MockAffine, 10) + for i := range rawAffinePoints { + rawAffinePoints[i] = affine + } + points := HostSliceFromElements[internal.MockAffine](rawAffinePoints) + + output := make(HostSlice[internal.MockProjective], 1) + assert.NotPanics(t, func() { MsmCheck(scalars, points, &cfg, output) }) + assert.False(t, cfg.areScalarsOnDevice) + assert.False(t, cfg.arePointsOnDevice) + assert.False(t, cfg.areResultsOnDevice) + assert.Equal(t, int32(1), cfg.batchSize) + + output2 := make(HostSlice[internal.MockProjective], 3) + assert.Panics(t, func() { MsmCheck(scalars, points, &cfg, output2) }) +} + +func TestMSMCheckDeviceSlices(t *testing.T) { + cfg := GetDefaultMSMConfig() + + randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8} + rawScalars := make([]internal.MockField, 10) + for i := range rawScalars { + var emptyField internal.MockField + emptyField.FromLimbs(randLimbs) + + rawScalars[i] = emptyField + } + scalars := HostSliceFromElements[internal.MockField](rawScalars) + var scalarsOnDevice DeviceSlice + scalars.CopyToDevice(&scalarsOnDevice, true) + + affine := internal.MockAffine{} + limbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8} + affine.FromLimbs(limbs, limbs) + rawAffinePoints := make([]internal.MockAffine, 10) + for i := range rawAffinePoints { + rawAffinePoints[i] = affine + } + points := HostSliceFromElements[internal.MockAffine](rawAffinePoints) + var pointsOnDevice DeviceSlice + points.CopyToDevice(&pointsOnDevice, true) + + output := make(HostSlice[internal.MockProjective], 1) + assert.NotPanics(t, func() { MsmCheck(scalarsOnDevice, pointsOnDevice, &cfg, output) }) + assert.True(t, cfg.areScalarsOnDevice) + assert.True(t, cfg.arePointsOnDevice) + assert.False(t, cfg.areResultsOnDevice) + assert.Equal(t, int32(1), cfg.batchSize) + + output2 := make(HostSlice[internal.MockProjective], 3) + assert.Panics(t, func() { MsmCheck(scalarsOnDevice, pointsOnDevice, &cfg, output2) }) +} + +// TODO add check for batches and batchSize diff --git a/wrappers/golang/core/ntt.go b/wrappers/golang/core/ntt.go new file mode 100644 index 000000000..986573427 --- /dev/null +++ b/wrappers/golang/core/ntt.go @@ -0,0 +1,68 @@ +package core + +import ( + "fmt" + + "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type NTTDir int8 + +const ( + KForward NTTDir = iota + KInverse NTTDir = 1 +) + +type Ordering uint32 + +const ( + KNN Ordering = iota + KNR Ordering = 1 + KRN Ordering = 2 + KRR Ordering = 3 + KNM Ordering = 4 + KMN Ordering = 5 +) + +type NTTConfig[T any] struct { + /// Details related to the device such as its id and stream id. See [DeviceContext](@ref device_context::DeviceContext). + Ctx cuda_runtime.DeviceContext + /// Coset generator. Used to perform coset (i)NTTs. Default value: `S::one()` (corresponding to no coset being used). + CosetGen T + /// The number of NTTs to compute. Default value: 1. + BatchSize int32 + /// Ordering of inputs and outputs. See [Ordering](@ref Ordering). Default value: `Ordering::kNN`. + Ordering Ordering + areInputsOnDevice bool + areOutputsOnDevice bool + /// Whether to run the NTT asynchronously. If set to `true`, the NTT function will be non-blocking and you'd need to synchronize + /// it explicitly by running `stream.synchronize()`. If set to false, the NTT function will block the current CPU thread. + IsAsync bool +} + +func GetDefaultNTTConfig[T any](cosetGen T) NTTConfig[T] { + ctx, _ := cuda_runtime.GetDefaultDeviceContext() + return NTTConfig[T]{ + ctx, // Ctx + cosetGen, // CosetGen + 1, // BatchSize + KNN, // Ordering + false, // areInputsOnDevice + false, // areOutputsOnDevice + false, // IsAsync + } +} + +func NttCheck[T any](input HostOrDeviceSlice, cfg *NTTConfig[T], output HostOrDeviceSlice) { + inputLen, outputLen := input.Len(), output.Len() + if inputLen != outputLen { + errorString := fmt.Sprintf( + "input and output capacities %d; %d are not equal", + inputLen, + outputLen, + ) + panic(errorString) + } + cfg.areInputsOnDevice = input.IsOnDevice() + cfg.areOutputsOnDevice = output.IsOnDevice() +} diff --git a/wrappers/golang/core/ntt_test.go b/wrappers/golang/core/ntt_test.go new file mode 100644 index 000000000..509d99c71 --- /dev/null +++ b/wrappers/golang/core/ntt_test.go @@ -0,0 +1,96 @@ +package core + +import ( + // "unsafe" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core/internal" + "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "github.com/stretchr/testify/assert" +) + +func TestNTTDefaultConfig(t *testing.T) { + var cosetGenField internal.MockField + cosetGenField.One() + var cosetGen [1]uint32 + copy(cosetGen[:], cosetGenField.GetLimbs()) + ctx, _ := cuda_runtime.GetDefaultDeviceContext() + expected := NTTConfig[[1]uint32]{ + ctx, // Ctx + cosetGen, // CosetGen + 1, // BatchSize + KNN, // Ordering + false, // areInputsOnDevice + false, // areOutputsOnDevice + false, // IsAsync + } + + actual := GetDefaultNTTConfig(cosetGen) + + assert.Equal(t, expected, actual) +} + +func TestNTTCheckHostScalars(t *testing.T) { + randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8} + + var cosetGen internal.MockField + cosetGen.FromLimbs(randLimbs) + cfg := GetDefaultNTTConfig(&cosetGen) + + rawInput := make([]internal.MockField, 10) + var emptyField internal.MockField + emptyField.FromLimbs(randLimbs) + + for i := range rawInput { + rawInput[i] = emptyField + } + + input := HostSliceFromElements[internal.MockField](rawInput) + output := HostSliceFromElements[internal.MockField](rawInput) + assert.NotPanics(t, func() { NttCheck(input, &cfg, output) }) + assert.False(t, cfg.areInputsOnDevice) + assert.False(t, cfg.areOutputsOnDevice) + + rawInputLarger := make([]internal.MockField, 11) + for i := range rawInputLarger { + rawInputLarger[i] = emptyField + } + output2 := HostSliceFromElements[internal.MockField](rawInputLarger) + assert.Panics(t, func() { NttCheck(input, &cfg, output2) }) +} + +func TestNTTCheckDeviceScalars(t *testing.T) { + randLimbs := []uint32{1, 2, 3, 4, 5, 6, 7, 8} + + var cosetGen internal.MockField + cosetGen.FromLimbs(randLimbs) + cfg := GetDefaultNTTConfig(cosetGen) + + fieldBytesSize := 16 + numFields := 10 + rawInput := make([]internal.MockField, numFields) + for i := range rawInput { + var emptyField internal.MockField + emptyField.FromLimbs(randLimbs) + + rawInput[i] = emptyField + } + + hostElements := HostSliceFromElements[internal.MockField](rawInput) + + var input DeviceSlice + hostElements.CopyToDevice(&input, true) + + var output DeviceSlice + output.Malloc(numFields*fieldBytesSize, fieldBytesSize) + + assert.NotPanics(t, func() { NttCheck(input, &cfg, output) }) + assert.True(t, cfg.areInputsOnDevice) + assert.True(t, cfg.areOutputsOnDevice) + + var output2 DeviceSlice + output2.Malloc((numFields+1)*fieldBytesSize, fieldBytesSize) + assert.Panics(t, func() { NttCheck(input, &cfg, output2) }) +} + +// TODO add check for batches and batchSize diff --git a/wrappers/golang/core/slice.go b/wrappers/golang/core/slice.go new file mode 100644 index 000000000..5f4e3a444 --- /dev/null +++ b/wrappers/golang/core/slice.go @@ -0,0 +1,160 @@ +package core + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type HostOrDeviceSlice interface { + Len() int + Cap() int + IsEmpty() bool + IsOnDevice() bool +} + +type DevicePointer = unsafe.Pointer + +type DeviceSlice struct { + inner unsafe.Pointer + // capacity is the number of bytes that have been allocated + capacity int + // length is the number of elements that have been written + length int +} + +func (d DeviceSlice) Len() int { + return d.length +} + +func (d DeviceSlice) Cap() int { + return d.capacity +} + +func (d DeviceSlice) IsEmpty() bool { + return d.length == 0 +} + +func (d DeviceSlice) AsPointer() unsafe.Pointer { + return d.inner +} + +func (d DeviceSlice) IsOnDevice() bool { + return true +} + +// TODO: change signature to be Malloc(element, numElements) +// calc size internally +func (d *DeviceSlice) Malloc(size, sizeOfElement int) (DeviceSlice, cuda_runtime.CudaError) { + dp, err := cuda_runtime.Malloc(uint(size)) + d.inner = dp + d.capacity = size + d.length = size / sizeOfElement + return *d, err +} + +func (d *DeviceSlice) MallocAsync(size, sizeOfElement int, stream cuda_runtime.CudaStream) (DeviceSlice, cuda_runtime.CudaError) { + dp, err := cuda_runtime.MallocAsync(uint(size), stream) + d.inner = dp + d.capacity = size + d.length = size / sizeOfElement + return *d, err +} + +func (d *DeviceSlice) Free() cuda_runtime.CudaError { + err := cuda_runtime.Free(d.inner) + if err == cuda_runtime.CudaSuccess { + d.length, d.capacity = 0, 0 + d.inner = nil + } + return err +} + +type HostSliceInterface interface { + Size() int +} + +type HostSlice[T HostSliceInterface] []T + +func HostSliceFromElements[T HostSliceInterface](elements []T) HostSlice[T] { + slice := make(HostSlice[T], len(elements)) + copy(slice, elements) + + return slice +} + +func HostSliceWithValue[T HostSliceInterface](underlyingValue T, size int) HostSlice[T] { + slice := make(HostSlice[T], size) + for i := range slice { + slice[i] = underlyingValue + } + + return slice +} + +func (h HostSlice[T]) Len() int { + return len(h) +} + +func (h HostSlice[T]) Cap() int { + return cap(h) +} + +func (h HostSlice[T]) IsEmpty() bool { + return len(h) == 0 +} + +func (h HostSlice[T]) IsOnDevice() bool { + return false +} + +func (h HostSlice[T]) SizeOfElement() int { + return h[0].Size() +} + +func (h HostSlice[T]) CopyToDevice(dst *DeviceSlice, shouldAllocate bool) *DeviceSlice { + size := h.Len() * h.SizeOfElement() + if shouldAllocate { + dst.Malloc(size, h.SizeOfElement()) + } + if size > dst.Cap() { + panic("Number of bytes to copy is too large for destination") + } + + // hostSrc := unsafe.Pointer(h.AsPointer()) + hostSrc := unsafe.Pointer(&h[0]) + cuda_runtime.CopyToDevice(dst.inner, hostSrc, uint(size)) + dst.length = h.Len() + return dst +} + +func (h HostSlice[T]) CopyToDeviceAsync(dst *DeviceSlice, stream cuda_runtime.CudaStream, shouldAllocate bool) *DeviceSlice { + size := h.Len() * h.SizeOfElement() + if shouldAllocate { + dst.MallocAsync(size, h.SizeOfElement(), stream) + } + if size > dst.Cap() { + panic("Number of bytes to copy is too large for destination") + } + + hostSrc := unsafe.Pointer(&h[0]) + cuda_runtime.CopyToDeviceAsync(dst.inner, hostSrc, uint(size), stream) + dst.length = h.Len() + return dst +} + +func (h HostSlice[T]) CopyFromDevice(src *DeviceSlice) { + if h.Len() != src.Len() { + panic("destination and source slices have different lengths") + } + bytesSize := src.Len() * h.SizeOfElement() + cuda_runtime.CopyFromDevice(unsafe.Pointer(&h[0]), src.inner, uint(bytesSize)) +} + +func (h HostSlice[T]) CopyFromDeviceAsync(src *DeviceSlice, stream cuda_runtime.Stream) { + if h.Len() != src.Len() { + panic("destination and source slices have different lengths") + } + bytesSize := src.Len() * h.SizeOfElement() + cuda_runtime.CopyFromDeviceAsync(unsafe.Pointer(&h[0]), src.inner, uint(bytesSize), stream) +} diff --git a/wrappers/golang/core/slice_test.go b/wrappers/golang/core/slice_test.go new file mode 100644 index 000000000..c7c44cbcd --- /dev/null +++ b/wrappers/golang/core/slice_test.go @@ -0,0 +1,192 @@ +package core + +import ( + "math/rand" + "testing" + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core/internal" + "github.com/stretchr/testify/assert" +) + +func randomField(size int) internal.MockField { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + + var field internal.MockField + field.FromLimbs(limbs) + + return field +} + +func randomFields(numFields, fieldSize int) []internal.MockField { + var randFields []internal.MockField + + for i := 0; i < numFields; i++ { + randFields = append(randFields, randomField(fieldSize)) + } + + return randFields +} + +// This function is solely for the purpose of testing HostDeviceSlice +// It can produce invalid points and should not be used to test curve operations +func randomProjectivePoints(numPoints, fieldSize int) []internal.MockProjective { + var randProjectives []internal.MockProjective + + for i := 0; i < numPoints; i++ { + projective := internal.MockProjective{ + X: randomField(fieldSize), + Y: randomField(fieldSize), + Z: randomField(fieldSize), + } + randProjectives = append(randProjectives, projective) + } + + return randProjectives +} + +// This function is solely for the purpose of testing HostDeviceSlice +// It can produce invalid points and should not be used to test curve operations +func randomAffinePoints(numPoints, fieldSize int) []internal.MockAffine { + var randAffines []internal.MockAffine + + for i := 0; i < numPoints; i++ { + affine := internal.MockAffine{ + X: randomField(fieldSize), + Y: randomField(fieldSize), + } + randAffines = append(randAffines, affine) + } + + return randAffines +} + +const ( + numPoints = 4 + numFields = 4 + fieldSize = 8 + fieldBytesSize = fieldSize * 4 +) + +func TestHostSlice(t *testing.T) { + var emptyHostSlice HostSlice[internal.MockField] + assert.Equal(t, emptyHostSlice.Len(), 0) + assert.Equal(t, emptyHostSlice.Cap(), 0) + + randFields := randomFields(numFields, fieldSize) + + hostSlice := HostSliceFromElements(randFields) + assert.Equal(t, hostSlice.Len(), 4) + assert.Equal(t, hostSlice.Cap(), 4) +} + +func TestHostSliceIsEmpty(t *testing.T) { + var emptyHostSlice HostSlice[*internal.MockField] + assert.True(t, emptyHostSlice.IsEmpty()) + + randFields := randomFields(numFields, fieldSize) + + hostSlice := HostSliceFromElements(randFields) + assert.False(t, hostSlice.IsEmpty()) +} + +func TestHostSliceIsOnDevice(t *testing.T) { + var emptyHostSlice HostSlice[*internal.MockField] + assert.False(t, emptyHostSlice.IsOnDevice()) +} + +func TestHostSliceSizeOf(t *testing.T) { + randFields := randomFields(numFields, fieldSize) + hostSlice := HostSliceFromElements(randFields) + assert.Equal(t, hostSlice.SizeOfElement(), fieldSize*4) +} + +func TestDeviceSlice(t *testing.T) { + var emptyDeviceSlice DeviceSlice + assert.Equal(t, 0, emptyDeviceSlice.Len()) + assert.Equal(t, 0, emptyDeviceSlice.Cap()) + assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsPointer()) + + emptyDeviceSlice.Malloc(numFields*fieldBytesSize, fieldBytesSize) + assert.Equal(t, numFields, emptyDeviceSlice.Len()) + assert.Equal(t, numFields*fieldBytesSize, emptyDeviceSlice.Cap()) + assert.NotEqual(t, unsafe.Pointer(nil), emptyDeviceSlice.AsPointer()) + + emptyDeviceSlice.Free() + assert.Equal(t, 0, emptyDeviceSlice.Len()) + assert.Equal(t, 0, emptyDeviceSlice.Cap()) + assert.Equal(t, unsafe.Pointer(nil), emptyDeviceSlice.AsPointer()) +} + +func TestDeviceSliceIsEmpty(t *testing.T) { + var emptyDeviceSlice DeviceSlice + assert.True(t, emptyDeviceSlice.IsEmpty()) + + const bytes = numFields * fieldBytesSize + emptyDeviceSlice.Malloc(bytes, fieldBytesSize) + + randFields := randomFields(numFields, fieldSize) + hostSlice := HostSliceFromElements(randFields) + + hostSlice.CopyToDevice(&emptyDeviceSlice, false) + assert.False(t, emptyDeviceSlice.IsEmpty()) +} + +func TestDeviceSliceIsOnDevice(t *testing.T) { + var deviceSlice DeviceSlice + assert.True(t, deviceSlice.IsOnDevice()) +} + +func TestCopyToFromHostDeviceField(t *testing.T) { + var emptyDeviceSlice DeviceSlice + + numFields := 1 << 10 + randFields := randomFields(numFields, fieldSize) + hostSlice := HostSliceFromElements(randFields) + hostSlice.CopyToDevice(&emptyDeviceSlice, true) + + randFields2 := randomFields(numFields, fieldSize) + hostSlice2 := HostSliceFromElements(randFields2) + + assert.NotEqual(t, hostSlice, hostSlice2) + hostSlice2.CopyFromDevice(&emptyDeviceSlice) + assert.Equal(t, hostSlice, hostSlice2) +} + +func TestCopyToFromHostDeviceAffinePoints(t *testing.T) { + var emptyDeviceSlice DeviceSlice + + numPoints := 1 << 10 + randAffines := randomAffinePoints(numPoints, fieldSize) + hostSlice := HostSliceFromElements(randAffines) + hostSlice.CopyToDevice(&emptyDeviceSlice, true) + + randAffines2 := randomAffinePoints(numPoints, fieldSize) + hostSlice2 := HostSliceFromElements(randAffines2) + + assert.NotEqual(t, hostSlice, hostSlice2) + hostSlice2.CopyFromDevice(&emptyDeviceSlice) + emptyDeviceSlice.Free() + + assert.Equal(t, hostSlice, hostSlice2) +} + +func TestCopyToFromHostDeviceProjectivePoints(t *testing.T) { + var emptyDeviceSlice DeviceSlice + + numPoints := 1 << 15 + randProjectives := randomProjectivePoints(numPoints, fieldSize) + hostSlice := HostSliceFromElements(randProjectives) + hostSlice.CopyToDevice(&emptyDeviceSlice, true) + + randProjectives2 := randomProjectivePoints(numPoints, fieldSize) + hostSlice2 := HostSliceFromElements(randProjectives2) + + assert.NotEqual(t, hostSlice, hostSlice2) + hostSlice2.CopyFromDevice(&emptyDeviceSlice) + + assert.Equal(t, hostSlice, hostSlice2) +} diff --git a/wrappers/golang/core/utils.go b/wrappers/golang/core/utils.go new file mode 100644 index 000000000..d98ec775f --- /dev/null +++ b/wrappers/golang/core/utils.go @@ -0,0 +1,26 @@ +package core + +import ( + "encoding/binary" +) + +func ConvertUint32ArrToUint64Arr(arr32 []uint32) []uint64 { + arr64 := make([]uint64, len(arr32)/2) + for i := 0; i < len(arr32); i += 2 { + arr64[i/2] = (uint64(arr32[i]) << 32) | uint64(arr32[i+1]) + } + return arr64 +} + +func ConvertUint64ArrToUint32Arr(arr64 []uint64) []uint32 { + arr32 := make([]uint32, len(arr64)*2) + for i, v := range arr64 { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, v) + + arr32[i*2] = binary.LittleEndian.Uint32(b[0:4]) + arr32[i*2+1] = binary.LittleEndian.Uint32(b[4:8]) + } + + return arr32 +} diff --git a/wrappers/golang/core/utils_test.go b/wrappers/golang/core/utils_test.go new file mode 100644 index 000000000..5b5e9ef33 --- /dev/null +++ b/wrappers/golang/core/utils_test.go @@ -0,0 +1,78 @@ +package core + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestConvertUint32ArrToUint64Arr(t *testing.T) { + testCases := []struct { + name string + input []uint32 + expected []uint64 + }{ + { + name: "Test with incremental array", + input: []uint32{1, 2, 3, 4, 5, 6, 7, 8}, + expected: []uint64{4294967298, 12884901892, 21474836486, 30064771080}, + }, + { + name: "Test with all zeros", + input: []uint32{0, 0, 0, 0, 0, 0, 0, 0}, + expected: []uint64{0, 0, 0, 0}, + }, + { + name: "Test with maximum uint32 values", + input: []uint32{4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295}, + expected: []uint64{18446744073709551615, 18446744073709551615, 18446744073709551615, 18446744073709551615}, + }, + { + name: "Test with alternating min and max uint32 values", + input: []uint32{0, 4294967295, 0, 4294967295, 0, 4294967295, 0, 4294967295}, + expected: []uint64{4294967295, 4294967295, 4294967295, 4294967295}, + }, + { + name: "Test with alternating max and min uint32 values", + input: []uint32{4294967295, 0, 4294967295, 0, 4294967295, 0, 4294967295, 0}, + expected: []uint64{18446744069414584320, 18446744069414584320, 18446744069414584320, 18446744069414584320}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := ConvertUint32ArrToUint64Arr(tc.input) + assert.Equal(t, tc.expected, got, "Got %v, %v", got, tc.expected) + }) + } +} + +func TestConvertUint64ArrToUint32Arr(t *testing.T) { + testCases := []struct { + name string + input []uint64 + expected []uint32 + }{ + { + name: "test one", + input: []uint64{1, 2, 3, 4}, + expected: []uint32{1, 0, 2, 0, 3, 0, 4, 0}, + }, + { + name: "test two", + input: []uint64{100, 200, 300, 400}, + expected: []uint32{100, 0, 200, 0, 300, 0, 400, 0}, + }, + { + name: "test three", + input: []uint64{1000, 2000, 3000, 4000}, + expected: []uint32{1000, 0, 2000, 0, 3000, 0, 4000, 0}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := ConvertUint64ArrToUint32Arr(tc.input) + assert.Equal(t, tc.expected, got, "Got %v, %v", got, tc.expected) + }) + } +} diff --git a/wrappers/golang/cuda_runtime/const.go b/wrappers/golang/cuda_runtime/const.go new file mode 100644 index 000000000..548c6afd7 --- /dev/null +++ b/wrappers/golang/cuda_runtime/const.go @@ -0,0 +1,179 @@ +package cuda_runtime + +/* +#cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart +#cgo CFLAGS: -I /usr/local/cuda/include +#include +#include +#include +*/ +import "C" + +type CudaStreamCreateFlags C.uint + +const ( + // CudaStreamDefault as defined in include/driver_types.h:98 + CudaStreamDefault CudaStreamCreateFlags = iota + // CudaStreamNonBlocking as defined in include/driver_types.h:99 + CudaStreamNonBlocking CudaStreamCreateFlags = 1 +) + +type CudaStreamWaitFlags C.uint + +const ( + // CudaEventWaitDefault as defined in include/driver_types.h:129 + CudaEventWaitDefault CudaStreamWaitFlags = iota + // CudaEventWaitExternal as defined in include/driver_types.h:130 + CudaEventWaitExternal CudaStreamWaitFlags = 1 +) + +// CudaErrorT as declared in include/driver_types.h:2868 +type CudaError int32 + +// CudaErrorT enumeration from include/driver_types.h:2868 +const ( + CudaSuccess CudaError = iota + CudaErrorInvalidValue CudaError = 1 + CudaErrorMemoryAllocation CudaError = 2 + CudaErrorInitializationError CudaError = 3 + CudaErrorCudartUnloading CudaError = 4 + CudaErrorProfilerDisabled CudaError = 5 + CudaErrorProfilerNotInitialized CudaError = 6 + CudaErrorProfilerAlreadyStarted CudaError = 7 + CudaErrorProfilerAlreadyStopped CudaError = 8 + CudaErrorInvalidConfiguration CudaError = 9 + CudaErrorInvalidPitchValue CudaError = 12 + CudaErrorInvalidSymbol CudaError = 13 + CudaErrorInvalidHostPointer CudaError = 16 + CudaErrorInvalidDevicePointer CudaError = 17 + CudaErrorInvalidTexture CudaError = 18 + CudaErrorInvalidTextureBinding CudaError = 19 + CudaErrorInvalidChannelDescriptor CudaError = 20 + CudaErrorInvalidMemcpyDirection CudaError = 21 + CudaErrorAddressOfConstant CudaError = 22 + CudaErrorTextureFetchFailed CudaError = 23 + CudaErrorTextureNotBound CudaError = 24 + CudaErrorSynchronizationError CudaError = 25 + CudaErrorInvalidFilterSetting CudaError = 26 + CudaErrorInvalidNormSetting CudaError = 27 + CudaErrorMixedDeviceExecution CudaError = 28 + CudaErrorNotYetImplemented CudaError = 31 + CudaErrorMemoryValueTooLarge CudaError = 32 + CudaErrorStubLibrary CudaError = 34 + CudaErrorInsufficientDriver CudaError = 35 + CudaErrorCallRequiresNewerDriver CudaError = 36 + CudaErrorInvalidSurface CudaError = 37 + CudaErrorDuplicateVariableName CudaError = 43 + CudaErrorDuplicateTextureName CudaError = 44 + CudaErrorDuplicateSurfaceName CudaError = 45 + CudaErrorDevicesUnavailable CudaError = 46 + CudaErrorIncompatibleDriverContext CudaError = 49 + CudaErrorMissingConfiguration CudaError = 52 + CudaErrorPriorLaunchFailure CudaError = 53 + CudaErrorLaunchMaxDepthExceeded CudaError = 65 + CudaErrorLaunchFileScopedTex CudaError = 66 + CudaErrorLaunchFileScopedSurf CudaError = 67 + CudaErrorSyncDepthExceeded CudaError = 68 + CudaErrorLaunchPendingCountExceeded CudaError = 69 + CudaErrorInvalidDeviceFunction CudaError = 98 + CudaErrorNoDevice CudaError = 100 + CudaErrorInvalidDevice CudaError = 101 + CudaErrorDeviceNotLicensed CudaError = 102 + CudaErrorSoftwareValidityNotEstablished CudaError = 103 + CudaErrorStartupFailure CudaError = 127 + CudaErrorInvalidKernelImage CudaError = 200 + CudaErrorDeviceUninitialized CudaError = 201 + CudaErrorMapBufferObjectFailed CudaError = 205 + CudaErrorUnmapBufferObjectFailed CudaError = 206 + CudaErrorArrayIsMapped CudaError = 207 + CudaErrorAlreadyMapped CudaError = 208 + CudaErrorNoKernelImageForDevice CudaError = 209 + CudaErrorAlreadyAcquired CudaError = 210 + CudaErrorNotMapped CudaError = 211 + CudaErrorNotMappedAsArray CudaError = 212 + CudaErrorNotMappedAsPointer CudaError = 213 + CudaErrorECCUncorrectable CudaError = 214 + CudaErrorUnsupportedLimit CudaError = 215 + CudaErrorDeviceAlreadyInUse CudaError = 216 + CudaErrorPeerAccessUnsupported CudaError = 217 + CudaErrorInvalidPtx CudaError = 218 + CudaErrorInvalidGraphicsContext CudaError = 219 + CudaErrorNvlinkUncorrectable CudaError = 220 + CudaErrorJitCompilerNotFound CudaError = 221 + CudaErrorUnsupportedPtxVersion CudaError = 222 + CudaErrorJitCompilationDisabled CudaError = 223 + CudaErrorUnsupportedExecAffinity CudaError = 224 + CudaErrorUnsupportedDevSideSync CudaError = 225 + CudaErrorInvalidSource CudaError = 300 + CudaErrorFileNotFound CudaError = 301 + CudaErrorSharedObjectSymbolNotFound CudaError = 302 + CudaErrorSharedObjectInitFailed CudaError = 303 + CudaErrorOperatingSystem CudaError = 304 + CudaErrorInvalidResourceHandle CudaError = 400 + CudaErrorIllegalState CudaError = 401 + CudaErrorLossyQuery CudaError = 402 + CudaErrorSymbolNotFound CudaError = 500 + CudaErrorNotReady CudaError = 600 + CudaErrorIllegalAddress CudaError = 700 + CudaErrorLaunchOutOfResources CudaError = 701 + CudaErrorLaunchTimeout CudaError = 702 + CudaErrorLaunchIncompatibleTexturing CudaError = 703 + CudaErrorPeerAccessAlreadyEnabled CudaError = 704 + CudaErrorPeerAccessNotEnabled CudaError = 705 + CudaErrorSetOnActiveProcess CudaError = 708 + CudaErrorContextIsDestroyed CudaError = 709 + CudaErrorAssert CudaError = 710 + CudaErrorTooManyPeers CudaError = 711 + CudaErrorHostMemoryAlreadyRegistered CudaError = 712 + CudaErrorHostMemoryNotRegistered CudaError = 713 + CudaErrorHardwareStackError CudaError = 714 + CudaErrorIllegalInstruction CudaError = 715 + CudaErrorMisalignedAddress CudaError = 716 + CudaErrorInvalidAddressSpace CudaError = 717 + CudaErrorInvalidPc CudaError = 718 + CudaErrorLaunchFailure CudaError = 719 + CudaErrorCooperativeLaunchTooLarge CudaError = 720 + CudaErrorNotPermitted CudaError = 800 + CudaErrorNotSupported CudaError = 801 + CudaErrorSystemNotReady CudaError = 802 + CudaErrorSystemDriverMismatch CudaError = 803 + CudaErrorCompatNotSupportedOnDevice CudaError = 804 + CudaErrorMpsConnectionFailed CudaError = 805 + CudaErrorMpsRpcFailure CudaError = 806 + CudaErrorMpsServerNotReady CudaError = 807 + CudaErrorMpsMaxClientsReached CudaError = 808 + CudaErrorMpsMaxConnectionsReached CudaError = 809 + CudaErrorMpsClientTerminated CudaError = 810 + CudaErrorCdpNotSupported CudaError = 811 + CudaErrorCdpVersionMismatch CudaError = 812 + CudaErrorStreamCaptureUnsupported CudaError = 900 + CudaErrorStreamCaptureInvalidated CudaError = 901 + CudaErrorStreamCaptureMerge CudaError = 902 + CudaErrorStreamCaptureUnmatched CudaError = 903 + CudaErrorStreamCaptureUnjoined CudaError = 904 + CudaErrorStreamCaptureIsolation CudaError = 905 + CudaErrorStreamCaptureImplicit CudaError = 906 + CudaErrorCapturedEvent CudaError = 907 + CudaErrorStreamCaptureWrongThread CudaError = 908 + CudaErrorTimeout CudaError = 909 + CudaErrorGraphExecUpdateFailure CudaError = 910 + CudaErrorExternalDevice CudaError = 911 + CudaErrorInvalidClusterSize CudaError = 912 + CudaErrorUnknown CudaError = 999 + CudaErrorApiFailureBase CudaError = 10000 +) + +type CudaMemcpyKind C.uint + +const ( + // CudaMemcpyHostToHost as declared in include/driver_types.h:1219 + CudaMemcpyHostToHost CudaMemcpyKind = iota + // CudaMemcpyHostToDevice as declared in include/driver_types.h:1220 + CudaMemcpyHostToDevice CudaMemcpyKind = 1 + // CudaMemcpyDeviceToHost as declared in include/driver_types.h:1221 + CudaMemcpyDeviceToHost CudaMemcpyKind = 2 + // CudaMemcpyDeviceToDevice as declared in include/driver_types.h:1222 + CudaMemcpyDeviceToDevice CudaMemcpyKind = 3 + // CudaMemcpyDefault as declared in include/driver_types.h:1223 + CudaMemcpyDefault CudaMemcpyKind = 4 +) diff --git a/wrappers/golang/cuda_runtime/cuda_bindings.go b/wrappers/golang/cuda_runtime/cuda_bindings.go new file mode 100644 index 000000000..7df53b2ef --- /dev/null +++ b/wrappers/golang/cuda_runtime/cuda_bindings.go @@ -0,0 +1,50 @@ +package cuda_runtime + +/* +#cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart +#cgo CFLAGS: -I /usr/local/cuda/include +#include +#include +#include +*/ +import "C" +import ( + "unsafe" +) + +// CudaStreamWaitEvent function as declared in include/cuda_runtime_api.h:2707 +func cudaStreamWaitEvent(stream CudaStream, event CudaEvent, flags CudaStreamWaitFlags) CudaError { + cStream := (C.cudaStream_t)(stream) + cEvent := (C.cudaEvent_t)(event) + cFlags := (C.uint)(flags) + __ret := C.cudaStreamWaitEvent(cStream, cEvent, cFlags) + __v := (CudaError)(__ret) + return __v +} + +// CudaStreamQuery function as declared in include/cuda_runtime_api.h:2831 +func cudaStreamQuery(stream CudaStream) CudaError { + cStream := (C.cudaStream_t)(stream) + __ret := C.cudaStreamQuery(cStream) + __v := (CudaError)(__ret) + return __v +} + +// CudaMemset function as declared in include/cuda_runtime_api.h:7300 +func cudaMemset(devPtr unsafe.Pointer, value int32, count uint64) CudaError { + cValue := (C.int)(value) + cCount := (C.size_t)(count) + __ret := C.cudaMemset(devPtr, cValue, cCount) + __v := (CudaError)(__ret) + return __v +} + +// CudaMemsetAsync function as declared in include/cuda_runtime_api.h:7416 +func cudaMemsetAsync(devPtr unsafe.Pointer, value int32, count uint64, stream CudaStream) CudaError { + cValue := (C.int)(value) + cCount := (C.size_t)(count) + cStream := (C.cudaStream_t)(stream) + __ret := C.cudaMemsetAsync(devPtr, cValue, cCount, cStream) + __v := (CudaError)(__ret) + return __v +} diff --git a/wrappers/golang/cuda_runtime/cuda_runtime.yml b/wrappers/golang/cuda_runtime/cuda_runtime.yml new file mode 100644 index 000000000..346ddfe46 --- /dev/null +++ b/wrappers/golang/cuda_runtime/cuda_runtime.yml @@ -0,0 +1,85 @@ +--- +GENERATOR: + PackageName: cuda_bindings + PackageDescription: "Package runtime provides Go bindings" + PackageLicense: "THE AUTOGENERATED LICENSE. ALL THE RIGHTS ARE RESERVED BY ROBOTS." + SysIncludes: ["cuda.h", "cuda_runtime.h"] + FlagGroups: + - {name: LDFLAGS, flags: [-L/usr/local/cuda/lib64 -lcudart]} + - {name: CFLAGS, flags: [-I /usr/local/cuda/include]} +PARSER: + IncludePaths: ["/usr/local/cuda/include"] + SourcesPaths: ["cuda_runtime.h", "cuda_runtime_api.h", "driver_types.h"] + # SourcesPaths: ["cuda.h", "cuda_runtime.h"] +TRANSLATOR: + ConstCharIsString: true + ConstUCharIsString: false + ConstRules: + defines: eval + enum: eval + Rules: + global: + # - {action: accept, from: ".*"} + - {action: accept, from: "cudaError"} + - {action: accept, from: "cudaSuccess"} + # - {action: accept, from: "CUstream_st"} + # - {transform: export} + const: + - {action: accept, from: "^cudaMemcpy"} + - {action: accept, from: "cudaEventWaitDefault"} + - {action: accept, from: "cudaEventWaitExternal"} + - {action: accept, from: "cudaStreamDefault"} + - {action: accept, from: "cudaStreamNonBlocking"} + - {transform: export} + type: + - {action: accept, from: "cudaStream_t"} + - {action: replace, from: "cudaStream_t", to: "cudaStream"} + - {action: accept, from: "CUstream_st"} + - {action: replace, from: "CUstream_st", to: "cudaStream"} + - {action: accept, from: "cudaEvent_t"} + - {action: replace, from: "cudaEvent_t", to: "cudaEvent"} + - {action: accept, from: "CUevent_st"} + - {action: replace, from: "CUevent_st", to: "cudaEvent"} + - {action: accept, from: "cudaMemPool_t"} + - {action: replace, from: "cudaMemPool_t", to: "cudaMemPool"} + - {transform: export} + # - {action: replace, from: C.struct_CUstream_st, to: CudaStream} + function: + # memory management + - {action: accept, from: "^cudaFree$"} + - {action: accept, from: "^cudaMalloc$"} + # - {action: accept, from: "^cudaMemcpy$"} + # - {action: accept, from: "^cudaMemcpyAsync$"} + - {action: accept, from: "^cudaMemset$"} + - {action: accept, from: "^cudaMemsetAsync$"} + # device management + - {action: accept, from: "^cudaSetDevice$"} + # error handling + - {action: accept, from: "^cudaGetLastError$"} + # stream management + - {action: accept, from: "^cudaStreamCreate$"} + - {action: accept, from: "^cudaStreamCreateWithFlags$"} + - {action: accept, from: "^cudaStreamDestroy$"} + - {action: accept, from: "^cudaStreamQuery$"} + - {action: accept, from: "^cudaStreamSynchronize$"} + - {action: accept, from: "^cudaStreamWaitEvent$"} + # Stream Ordered Memory Allocator + - {action: accept, from: "^cudaFreeAsync$"} + - {action: accept, from: "^cudaMallocAsync$"} + + - {transform: export} + post-global: + - {load: snakecase} + PtrTips: + function: + - {target: ^cudaStreamCreate$, tips: [ref]} + - {target: ^cudaStreamCreateWithFlags$, tips: [ref, 0]} + - {target: "^cudaMalloc$", tips: [ref, 0]} + any: + - {target: cudaStream_t, tips: [ref]} + TypeTips: + function: + - {target: ^cudaStreamCreate$, tips: [named]} + MemTips: + - {target: cudaStream_t, self: raw} + diff --git a/wrappers/golang/cuda_runtime/device_context.go b/wrappers/golang/cuda_runtime/device_context.go new file mode 100644 index 000000000..56c726412 --- /dev/null +++ b/wrappers/golang/cuda_runtime/device_context.go @@ -0,0 +1,49 @@ +package cuda_runtime + +/* +#cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart +#cgo CFLAGS: -I /usr/local/cuda/include +#include +#include +#include +*/ +import "C" +import ( + "unsafe" +) + +type DeviceContext struct { + /// Stream to use. Default value: 0. + Stream *Stream // Assuming the type is provided by a CUDA binding crate + + /// Index of the currently used GPU. Default value: 0. + DeviceId uint + + /// Mempool to use. Default value: 0. + // TODO: use cuda_bindings.CudaMemPool as type + Mempool uint // Assuming the type is provided by a CUDA binding crate +} + +func GetDefaultDeviceContext() (DeviceContext, CudaError) { + var defaultStream Stream + + return DeviceContext{ + &defaultStream, + 0, + 0, + }, CudaSuccess +} + +func SetDevice(device int) CudaError { + cDevice := (C.int)(device) + ret := C.cudaSetDevice(cDevice) + err := (CudaError)(ret) + return err +} + +func GetDeviceCount() (int, CudaError) { + var count int + cCount := (*C.int)(unsafe.Pointer(&count)) + err := C.cudaGetDeviceCount(cCount) + return count, (CudaError)(err) +} diff --git a/wrappers/golang/cuda_runtime/device_context_test.go b/wrappers/golang/cuda_runtime/device_context_test.go new file mode 100644 index 000000000..34837ef4e --- /dev/null +++ b/wrappers/golang/cuda_runtime/device_context_test.go @@ -0,0 +1,29 @@ +package cuda_runtime + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetDefaultContext(t *testing.T) { + defaultCtx, err := GetDefaultDeviceContext() + + assert.Equal(t, CudaSuccess, err, "Couldn't get default device context due to %v", err) + assert.Nil(t, *defaultCtx.Stream) +} + +func TestSetDevice(t *testing.T) { + err := SetDevice(0) + assert.Equal(t, CudaSuccess, err, "Couldn't set device due to %v", err) + + count, _ := GetDeviceCount() + err = SetDevice(count) + assert.Equal(t, CudaErrorInvalidDevice, err, "Couldn't set device due to %v", err) +} + +func TestGetDeviceCount(t *testing.T) { + count, err := GetDeviceCount() + assert.Equal(t, CudaSuccess, err, "Could not get device count due to %v", err) + assert.GreaterOrEqual(t, count, 1, "Number of devices is 0, expected at least 1") +} diff --git a/wrappers/golang/cuda_runtime/error.go b/wrappers/golang/cuda_runtime/error.go new file mode 100644 index 000000000..71de63982 --- /dev/null +++ b/wrappers/golang/cuda_runtime/error.go @@ -0,0 +1,15 @@ +package cuda_runtime + +// #cgo CFLAGS: -I /usr/local/cuda/include +// #cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart +/* +#include +#include +*/ +import "C" + +func GetLastError() CudaError { + ret := C.cudaGetLastError() + err := (CudaError)(ret) + return err +} diff --git a/wrappers/golang/cuda_runtime/error_test.go b/wrappers/golang/cuda_runtime/error_test.go new file mode 100644 index 000000000..8dadc9ccf --- /dev/null +++ b/wrappers/golang/cuda_runtime/error_test.go @@ -0,0 +1,11 @@ +package cuda_runtime + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetLastError(t *testing.T) { + assert.NotPanicsf(t, func() { GetLastError() }, "Call to cuda GetLastError panicked") +} diff --git a/wrappers/golang/cuda_runtime/memory.go b/wrappers/golang/cuda_runtime/memory.go new file mode 100644 index 000000000..7460833d1 --- /dev/null +++ b/wrappers/golang/cuda_runtime/memory.go @@ -0,0 +1,87 @@ +package cuda_runtime + +// #cgo CFLAGS: -I /usr/local/cuda/include +// #cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart +/* +#include +#include +*/ +import "C" + +import ( + "unsafe" +) + +func Malloc(size uint) (unsafe.Pointer, CudaError) { + if size == 0 { + return nil, CudaErrorMemoryAllocation + } + + var p C.void + devicePtr := unsafe.Pointer(&p) + cSize := (C.size_t)(size) + + ret := C.cudaMalloc(&devicePtr, cSize) + err := (CudaError)(ret) + + return devicePtr, err +} + +func MallocAsync(size uint, stream CudaStream) (unsafe.Pointer, CudaError) { + if size == 0 { + return nil, CudaErrorMemoryAllocation + } + + var p C.void + devicePtr := unsafe.Pointer(&p) + cSize := (C.size_t)(size) + cStream := (C.cudaStream_t)(stream) + + ret := C.cudaMallocAsync(&devicePtr, cSize, cStream) + err := (CudaError)(ret) + + return devicePtr, err +} + +func Free(devicePtr unsafe.Pointer) CudaError { + ret := C.cudaFree(devicePtr) + err := (CudaError)(ret) + return err +} + +func FreeAsync(devicePtr unsafe.Pointer, stream Stream) CudaError { + cStream := (C.cudaStream_t)(stream) + ret := C.cudaFreeAsync(devicePtr, cStream) + err := (CudaError)(ret) + return err +} + +func CopyFromDevice(hostDst, deviceSrc unsafe.Pointer, size uint) (unsafe.Pointer, CudaError) { + cCount := (C.size_t)(size) + ret := C.cudaMemcpy(hostDst, deviceSrc, cCount, uint32(CudaMemcpyDeviceToHost)) + err := (CudaError)(ret) + return hostDst, err +} + +func CopyFromDeviceAsync(hostDst, deviceSrc unsafe.Pointer, size uint, stream CudaStream) CudaError { + cSize := (C.size_t)(size) + cStream := (C.cudaStream_t)(stream) + ret := C.cudaMemcpyAsync(hostDst, deviceSrc, cSize, uint32(CudaMemcpyDeviceToHost), cStream) + err := (CudaError)(ret) + return err +} + +func CopyToDevice(deviceDst, hostSrc unsafe.Pointer, size uint) (unsafe.Pointer, CudaError) { + cSize := (C.size_t)(size) + ret := C.cudaMemcpy(deviceDst, hostSrc, cSize, uint32(CudaMemcpyHostToDevice)) + err := (CudaError)(ret) + return deviceDst, err +} + +func CopyToDeviceAsync(deviceDst, hostSrc unsafe.Pointer, size uint, stream CudaStream) CudaError { + cCount := (C.size_t)(size) + cStream := (C.cudaStream_t)(stream) + ret := C.cudaMemcpyAsync(deviceDst, hostSrc, cCount, uint32(CudaMemcpyHostToDevice), cStream) + err := (CudaError)(ret) + return err +} diff --git a/wrappers/golang/cuda_runtime/memory_test.go b/wrappers/golang/cuda_runtime/memory_test.go new file mode 100644 index 000000000..610191d5f --- /dev/null +++ b/wrappers/golang/cuda_runtime/memory_test.go @@ -0,0 +1,42 @@ +package cuda_runtime + +import ( + "testing" + + "unsafe" + + "github.com/stretchr/testify/assert" +) + +func TestMalloc(t *testing.T) { + _, err := Malloc(20) + assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) +} + +func TestMallocAsync(t *testing.T) { + stream, _ := CreateStream() + _, err := MallocAsync(20, stream) + assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) +} + +func TestFree(t *testing.T) { + mem, err := Malloc(20) + assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) + + err = Free(mem) + assert.Equal(t, CudaSuccess, err, "Unable to free device memory due to %v", err) +} + +func TestCopyFromToHost(t *testing.T) { + someInts := make([]int32, 1) + someInts[0] = 34 + numBytes := uint(8) + deviceMem, _ := Malloc(numBytes) + deviceMem, err := CopyToDevice(deviceMem, unsafe.Pointer(&someInts[0]), numBytes) + assert.Equal(t, CudaSuccess, err, "Couldn't copy to device due to %v", err) + + someInts2 := make([]int32, 1) + _, err = CopyFromDevice(unsafe.Pointer(&someInts2[0]), deviceMem, numBytes) + assert.Equal(t, CudaSuccess, err, "Couldn't copy to device due to %v", err) + assert.Equal(t, someInts, someInts2, "Elements of host slices do not match. Copying from/to host failed") +} diff --git a/wrappers/golang/cuda_runtime/stream.go b/wrappers/golang/cuda_runtime/stream.go new file mode 100644 index 000000000..164c79887 --- /dev/null +++ b/wrappers/golang/cuda_runtime/stream.go @@ -0,0 +1,45 @@ +package cuda_runtime + +// #cgo CFLAGS: -I /usr/local/cuda/include +// #cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart +/* +#include +#include +*/ +import "C" + +type Stream = CudaStream + +func CreateStream() (Stream, CudaError) { + var stream Stream + cPStream := (*C.cudaStream_t)(&stream) + ret := C.cudaStreamCreate(cPStream) + err := (CudaError)(ret) + return stream, err +} + +func CreateStreamWithFlags(flags CudaStreamCreateFlags) (Stream, CudaError) { + var stream CudaStream + cPStream := (*C.cudaStream_t)(&stream) + cFlags := (C.uint)(flags) + ret := C.cudaStreamCreateWithFlags(cPStream, cFlags) + err := (CudaError)(ret) + return stream, err +} + +func DestroyStream(stream *Stream) CudaError { + cStream := (C.cudaStream_t)(*stream) + ret := C.cudaStreamDestroy(cStream) + err := (CudaError)(ret) + if err == CudaSuccess { + stream = nil + } + return err +} + +func SynchronizeStream(stream *Stream) CudaError { + cStream := (C.cudaStream_t)(*stream) + ret := C.cudaStreamSynchronize(cStream) + err := (CudaError)(ret) + return err +} diff --git a/wrappers/golang/cuda_runtime/stream_test.go b/wrappers/golang/cuda_runtime/stream_test.go new file mode 100644 index 000000000..97aa76639 --- /dev/null +++ b/wrappers/golang/cuda_runtime/stream_test.go @@ -0,0 +1,45 @@ +package cuda_runtime + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestCreateStream(t *testing.T) { + _, err := CreateStream() + assert.Equal(t, CudaSuccess, err, "Unable to create stream due to %d", err) +} + +func TestCreateStreamWithFlags(t *testing.T) { + _, err := CreateStreamWithFlags(CudaStreamDefault) + assert.Equal(t, CudaSuccess, err, "Unable to create stream due to %d", err) + + _, errNonBlocking := CreateStreamWithFlags(CudaStreamNonBlocking) + assert.Equal(t, CudaSuccess, errNonBlocking, "Unable to create stream due to %d", errNonBlocking) +} + +func TestDestroyStream(t *testing.T) { + stream, err := CreateStream() + assert.Equal(t, CudaSuccess, err, "Unable to create stream due to %d", err) + + err = DestroyStream(&stream) + assert.Equal(t, CudaSuccess, err, "Unable to destroy stream due to %d", err) +} + +func TestSyncStream(t *testing.T) { + stream, err := CreateStream() + assert.Equal(t, CudaSuccess, err, "Unable to create stream due to %d", err) + + _, err = MallocAsync(200000, stream) + assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) + + dp, err := Malloc(20) + assert.NotNil(t, dp) + assert.Equal(t, CudaSuccess, err, "Unable to allocate device memory due to %d", err) + + err = SynchronizeStream(&stream) + assert.Equal(t, CudaSuccess, err, "Unable to sync stream due to %d", err) + + err = DestroyStream(&stream) + assert.Equal(t, CudaSuccess, err, "Unable to destroy stream due to %d", err) +} diff --git a/wrappers/golang/cuda_runtime/types.go b/wrappers/golang/cuda_runtime/types.go new file mode 100644 index 000000000..1b7e26128 --- /dev/null +++ b/wrappers/golang/cuda_runtime/types.go @@ -0,0 +1,19 @@ +package cuda_runtime + +/* +#cgo LDFLAGS: -L/usr/local/cuda/lib64 -lcudart +#cgo CFLAGS: -I /usr/local/cuda/include +#include +#include +#include +*/ +import "C" + +// CudaStream as declared in include/driver_types.h:2873 +type CudaStream C.cudaStream_t + +// CudaEvent as declared in include/driver_types.h:2878 +type CudaEvent C.cudaEvent_t + +// CudaMemPool as declared in include/driver_types.h:2928 +type CudaMemPool C.cudaMemPool_t diff --git a/wrappers/golang/curves/bls12377/base_field.go b/wrappers/golang/curves/bls12377/base_field.go new file mode 100644 index 000000000..9a2c1e456 --- /dev/null +++ b/wrappers/golang/curves/bls12377/base_field.go @@ -0,0 +1,79 @@ +package bls12377 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int8 = 12 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bls12377/base_field_test.go b/wrappers/golang/curves/bls12377/base_field_test.go new file mode 100644 index 000000000..a52543df5 --- /dev/null +++ b/wrappers/golang/curves/bls12377/base_field_test.go @@ -0,0 +1,82 @@ +package bls12377 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField BaseField + emptyField.One() + limbOne := generateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField BaseField + bytes, expected := generateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField BaseField + expected, limbs := generateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bls12377/bls12_377.go b/wrappers/golang/curves/bls12377/bls12_377.go new file mode 100644 index 000000000..504ff58cc --- /dev/null +++ b/wrappers/golang/curves/bls12377/bls12_377.go @@ -0,0 +1,4 @@ +package bls12377 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build -lingo_bls12_377 -lstdc++ -lm +import "C" diff --git a/wrappers/golang/curves/bls12377/curve.go b/wrappers/golang/curves/bls12377/curve.go new file mode 100644 index 000000000..f000eda2e --- /dev/null +++ b/wrappers/golang/curves/bls12377/curve.go @@ -0,0 +1,173 @@ +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_377Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_377ToAffine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bls12377/curve_test.go b/wrappers/golang/curves/bls12377/curve_test.go new file mode 100644 index 000000000..724a0e739 --- /dev/null +++ b/wrappers/golang/curves/bls12377/curve_test.go @@ -0,0 +1,101 @@ +package bls12377 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = BaseField{} + + var affineZero Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(BASE_LIMBS)) + y := generateRandomLimb(int(BASE_LIMBS)) + var affine Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero Projective + projectiveZero.Zero() + var fieldZero = BaseField{} + var fieldOne BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + var projective Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(BASE_LIMBS)) + + var projective Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bls12377/g2_base_field.go b/wrappers/golang/curves/bls12377/g2_base_field.go new file mode 100644 index 000000000..02e7a0a7d --- /dev/null +++ b/wrappers/golang/curves/bls12377/g2_base_field.go @@ -0,0 +1,81 @@ +//go:build g2 + +package bls12377 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2_BASE_LIMBS int8 = 24 +) + +type G2BaseField struct { + limbs [G2_BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2_BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2_BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bls12377/g2_base_field_test.go b/wrappers/golang/curves/bls12377/g2_base_field_test.go new file mode 100644 index 000000000..8f5a45628 --- /dev/null +++ b/wrappers/golang/curves/bls12377/g2_base_field_test.go @@ -0,0 +1,84 @@ +//go:build g2 + +package bls12377 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField G2BaseField + emptyField.One() + limbOne := generateLimbOne(int(G2_BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2_BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField G2BaseField + bytes, expected := generateBytesArray(int(G2_BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField G2BaseField + expected, limbs := generateBytesArray(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bls12377/g2_curve.go b/wrappers/golang/curves/bls12377/g2_curve.go new file mode 100644 index 000000000..394724de5 --- /dev/null +++ b/wrappers/golang/curves/bls12377/g2_curve.go @@ -0,0 +1,175 @@ +//go:build g2 + +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "g2_curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_377G2Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_377G2ToAffine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377G2GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_377G2GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377G2AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377G2ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bls12377/g2_curve_test.go b/wrappers/golang/curves/bls12377/g2_curve_test.go new file mode 100644 index 000000000..2c97484ed --- /dev/null +++ b/wrappers/golang/curves/bls12377/g2_curve_test.go @@ -0,0 +1,103 @@ +//go:build g2 + +package bls12377 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = G2BaseField{} + + var affineZero G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(G2_BASE_LIMBS)) + y := generateRandomLimb(int(G2_BASE_LIMBS)) + var affine G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero G2Projective + projectiveZero.Zero() + var fieldZero = G2BaseField{} + var fieldOne G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bls12377/g2_msm.go b/wrappers/golang/curves/bls12377/g2_msm.go new file mode 100644 index 000000000..28fb546b2 --- /dev/null +++ b/wrappers/golang/curves/bls12377/g2_msm.go @@ -0,0 +1,51 @@ +//go:build g2 + +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "g2_msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0]) + } + cPoints := (*C.g2_affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[G2Projective])[0]) + } + cResults := (*C.g2_projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bls12_377G2MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bls12377/g2_msm_test.go b/wrappers/golang/curves/bls12377/g2_msm_test.go new file mode 100644 index 000000000..eb8432d64 --- /dev/null +++ b/wrappers/golang/curves/bls12377/g2_msm_test.go @@ -0,0 +1,167 @@ +//go:build g2 + +package bls12377 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" +) + +func projectiveToGnarkAffineG2(p G2Projective) bls12377.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := bls12377.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := bls12377.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := bls12377.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared bls12377.E2 + zSquared.Mul(&z, &z) + + var X bls12377.E2 + X.Mul(&x, &z) + + var Y bls12377.E2 + Y.Mul(&y, &zSquared) + + g2Jac := bls12377.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine bls12377.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points core.HostSlice[G2Affine], out G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12377.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + var msmRes bls12377.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12377.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSMG2(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := G2GenerateAffinePoints(totalSize) + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bls12377/helpers_test.go b/wrappers/golang/curves/bls12377/helpers_test.go new file mode 100644 index 000000000..ead8b7c12 --- /dev/null +++ b/wrappers/golang/curves/bls12377/helpers_test.go @@ -0,0 +1,31 @@ +package bls12377 + +import ( + "math/rand" +) + +func generateRandomLimb(size int) []uint32 { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + return limbs +} + +func generateLimbOne(size int) []uint32 { + limbs := make([]uint32, size) + limbs[0] = 1 + return limbs +} + +func generateBytesArray(size int) ([]byte, []uint32) { + baseBytes := []byte{1, 2, 3, 4} + var bytes []byte + var limbs []uint32 + for i := 0; i < size; i++ { + bytes = append(bytes, baseBytes...) + limbs = append(limbs, 67305985) + } + + return bytes, limbs +} diff --git a/wrappers/golang/curves/bls12377/include/curve.h b/wrappers/golang/curves/bls12377/include/curve.h new file mode 100644 index 000000000..0d7e9d38d --- /dev/null +++ b/wrappers/golang/curves/bls12377/include/curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_377_CURVE_H +#define _BLS12_377_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bls12_377Eq(projective_t* point1, projective_t* point2); +void bls12_377ToAffine(projective_t* point, affine_t* point_out); +void bls12_377GenerateProjectivePoints(projective_t* points, int size); +void bls12_377GenerateAffinePoints(affine_t* points, int size); +cudaError_t bls12_377AffineConvertMontgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_377ProjectiveConvertMontgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12377/include/g2_curve.h b/wrappers/golang/curves/bls12377/include/g2_curve.h new file mode 100644 index 000000000..a8409e722 --- /dev/null +++ b/wrappers/golang/curves/bls12377/include/g2_curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_377_G2CURVE_H +#define _BLS12_377_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bls12_377G2Eq(g2_projective_t* point1, g2_projective_t* point2); +void bls12_377G2ToAffine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_377G2GenerateProjectivePoints(g2_projective_t* points, int size); +void bls12_377G2GenerateAffinePoints(g2_affine_t* points, int size); +cudaError_t bls12_377G2AffineConvertMontgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_377G2ProjectiveConvertMontgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12377/include/g2_msm.h b/wrappers/golang/curves/bls12377/include/g2_msm.h new file mode 100644 index 000000000..85819e384 --- /dev/null +++ b/wrappers/golang/curves/bls12377/include/g2_msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BLS12_377_G2MSM_H +#define _BLS12_377_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bls12_377G2MSMCuda(scalar_t* scalars, g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12377/include/msm.h b/wrappers/golang/curves/bls12377/include/msm.h new file mode 100644 index 000000000..cf84172e8 --- /dev/null +++ b/wrappers/golang/curves/bls12377/include/msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BLS12_377_MSM_H +#define _BLS12_377_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bls12_377MSMCuda(scalar_t* scalars, affine_t* points, int count, MSMConfig* config, projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12377/include/ntt.h b/wrappers/golang/curves/bls12377/include/ntt.h new file mode 100644 index 000000000..3ff70a7c9 --- /dev/null +++ b/wrappers/golang/curves/bls12377/include/ntt.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_377_NTT_H +#define _BLS12_377_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bls12_377NTTCuda(scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bls12_377InitializeDomain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12377/include/scalar_field.h b/wrappers/golang/curves/bls12377/include/scalar_field.h new file mode 100644 index 000000000..01dc53664 --- /dev/null +++ b/wrappers/golang/curves/bls12377/include/scalar_field.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_377_FIELD_H +#define _BLS12_377_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +void bls12_377GenerateScalars(scalar_t* scalars, int size); +cudaError_t bls12_377ScalarConvertMontgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12377/msm.go b/wrappers/golang/curves/bls12377/msm.go new file mode 100644 index 000000000..bad05683e --- /dev/null +++ b/wrappers/golang/curves/bls12377/msm.go @@ -0,0 +1,49 @@ +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0]) + } + cPoints := (*C.affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0]) + } + cResults := (*C.projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bls12_377MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bls12377/msm_test.go b/wrappers/golang/curves/bls12377/msm_test.go new file mode 100644 index 000000000..5c41051fa --- /dev/null +++ b/wrappers/golang/curves/bls12377/msm_test.go @@ -0,0 +1,138 @@ +package bls12377 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-377" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" +) + +func projectiveToGnarkAffine(p Projective) bls12377.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bls12377.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.HostSlice[Affine], out Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12377.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + var msmRes bls12377.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12377.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSM(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := GenerateAffinePoints(totalSize) + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bls12377/ntt.go b/wrappers/golang/curves/bls12377/ntt.go new file mode 100644 index 000000000..8c15128ab --- /dev/null +++ b/wrappers/golang/curves/bls12377/ntt.go @@ -0,0 +1,59 @@ +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +func GetDefaultNttConfig() core.NTTConfig[[SCALAR_LIMBS]uint32] { + cosetGenField := ScalarField{} + cosetGenField.One() + var cosetGen [SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + core.NttCheck[T](scalars, cfg, results) + + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(scalars.Len() / int(cfg.BatchSize)) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg)) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[ScalarField])[0]) + } + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bls12_377NTTCuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitDomain(primitiveRoot ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bls12_377InitializeDomain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang/curves/bls12377/ntt_test.go b/wrappers/golang/curves/bls12377/ntt_test.go new file mode 100644 index 000000000..b857e9ceb --- /dev/null +++ b/wrappers/golang/curves/bls12377/ntt_test.go @@ -0,0 +1,239 @@ +package bls12377 + +import ( + "reflect" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" + "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/fft" + "github.com/stretchr/testify/assert" +) + +const ( + largestTestSize = 17 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + InitDomain(rouIcicle, cfg.Ctx, false) +} + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], output core.HostSlice[ScalarField], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} + +func TestNTTGetDefaultConfig(t *testing.T) { + actual := GetDefaultNttConfig() + expected := generateLimbOne(int(SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + cfg := GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[ScalarField], testSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := GetDefaultNttConfig() + largestBatchSize := 100 + scalars := GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{1, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[ScalarField], totalSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang/curves/bls12377/scalar_field.go b/wrappers/golang/curves/bls12377/scalar_field.go new file mode 100644 index 000000000..4635b8ded --- /dev/null +++ b/wrappers/golang/curves/bls12377/scalar_field.go @@ -0,0 +1,119 @@ +package bls12377 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + core "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int8 = 8 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalars := make([]ScalarField, size) + for i := range scalars { + scalars[i] = ScalarField{} + } + + scalarSlice := core.HostSliceFromElements[ScalarField](scalars) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bls12_377GenerateScalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsPointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_377ScalarConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang/curves/bls12377/scalar_field_test.go b/wrappers/golang/curves/bls12377/scalar_field_test.go new file mode 100644 index 000000000..f4302a8f3 --- /dev/null +++ b/wrappers/golang/curves/bls12377/scalar_field_test.go @@ -0,0 +1,114 @@ +package bls12377 + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField ScalarField + emptyField.One() + limbOne := generateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField ScalarField + bytes, expected := generateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField ScalarField + expected, limbs := generateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestMongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + ToMontgomery(&deviceScalars) + + scalarsMontHost := GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang/curves/bls12381/base_field.go b/wrappers/golang/curves/bls12381/base_field.go new file mode 100644 index 000000000..fce5a84e9 --- /dev/null +++ b/wrappers/golang/curves/bls12381/base_field.go @@ -0,0 +1,79 @@ +package bls12381 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int8 = 12 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bls12381/base_field_test.go b/wrappers/golang/curves/bls12381/base_field_test.go new file mode 100644 index 000000000..30a04f90f --- /dev/null +++ b/wrappers/golang/curves/bls12381/base_field_test.go @@ -0,0 +1,82 @@ +package bls12381 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField BaseField + emptyField.One() + limbOne := generateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField BaseField + bytes, expected := generateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField BaseField + expected, limbs := generateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bls12381/bls12_381.go b/wrappers/golang/curves/bls12381/bls12_381.go new file mode 100644 index 000000000..c7797bbce --- /dev/null +++ b/wrappers/golang/curves/bls12381/bls12_381.go @@ -0,0 +1,4 @@ +package bls12381 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build -lingo_bls12_381 -lstdc++ -lm +import "C" diff --git a/wrappers/golang/curves/bls12381/curve.go b/wrappers/golang/curves/bls12381/curve.go new file mode 100644 index 000000000..2eed613a8 --- /dev/null +++ b/wrappers/golang/curves/bls12381/curve.go @@ -0,0 +1,173 @@ +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_381Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bls12_381ToAffine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bls12381/curve_test.go b/wrappers/golang/curves/bls12381/curve_test.go new file mode 100644 index 000000000..788f3efde --- /dev/null +++ b/wrappers/golang/curves/bls12381/curve_test.go @@ -0,0 +1,101 @@ +package bls12381 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = BaseField{} + + var affineZero Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(BASE_LIMBS)) + y := generateRandomLimb(int(BASE_LIMBS)) + var affine Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero Projective + projectiveZero.Zero() + var fieldZero = BaseField{} + var fieldOne BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + var projective Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(BASE_LIMBS)) + + var projective Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bls12381/g2_base_field.go b/wrappers/golang/curves/bls12381/g2_base_field.go new file mode 100644 index 000000000..e0b15d1f3 --- /dev/null +++ b/wrappers/golang/curves/bls12381/g2_base_field.go @@ -0,0 +1,81 @@ +//go:build g2 + +package bls12381 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2_BASE_LIMBS int8 = 24 +) + +type G2BaseField struct { + limbs [G2_BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2_BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2_BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bls12381/g2_base_field_test.go b/wrappers/golang/curves/bls12381/g2_base_field_test.go new file mode 100644 index 000000000..da0e64dd8 --- /dev/null +++ b/wrappers/golang/curves/bls12381/g2_base_field_test.go @@ -0,0 +1,84 @@ +//go:build g2 + +package bls12381 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField G2BaseField + emptyField.One() + limbOne := generateLimbOne(int(G2_BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2_BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField G2BaseField + bytes, expected := generateBytesArray(int(G2_BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField G2BaseField + expected, limbs := generateBytesArray(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bls12381/g2_curve.go b/wrappers/golang/curves/bls12381/g2_curve.go new file mode 100644 index 000000000..8bcde14f0 --- /dev/null +++ b/wrappers/golang/curves/bls12381/g2_curve.go @@ -0,0 +1,175 @@ +//go:build g2 + +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "g2_curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bls12_381G2Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bls12_381G2ToAffine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381G2GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bls12_381G2GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381G2AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381G2ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bls12381/g2_curve_test.go b/wrappers/golang/curves/bls12381/g2_curve_test.go new file mode 100644 index 000000000..c9fb4f871 --- /dev/null +++ b/wrappers/golang/curves/bls12381/g2_curve_test.go @@ -0,0 +1,103 @@ +//go:build g2 + +package bls12381 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = G2BaseField{} + + var affineZero G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(G2_BASE_LIMBS)) + y := generateRandomLimb(int(G2_BASE_LIMBS)) + var affine G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero G2Projective + projectiveZero.Zero() + var fieldZero = G2BaseField{} + var fieldOne G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bls12381/g2_msm.go b/wrappers/golang/curves/bls12381/g2_msm.go new file mode 100644 index 000000000..4ecae93c3 --- /dev/null +++ b/wrappers/golang/curves/bls12381/g2_msm.go @@ -0,0 +1,51 @@ +//go:build g2 + +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "g2_msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0]) + } + cPoints := (*C.g2_affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[G2Projective])[0]) + } + cResults := (*C.g2_projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bls12_381G2MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bls12381/g2_msm_test.go b/wrappers/golang/curves/bls12381/g2_msm_test.go new file mode 100644 index 000000000..9ce775127 --- /dev/null +++ b/wrappers/golang/curves/bls12381/g2_msm_test.go @@ -0,0 +1,167 @@ +//go:build g2 + +package bls12381 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) + +func projectiveToGnarkAffineG2(p G2Projective) bls12381.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := bls12381.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := bls12381.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := bls12381.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared bls12381.E2 + zSquared.Mul(&z, &z) + + var X bls12381.E2 + X.Mul(&x, &z) + + var Y bls12381.E2 + Y.Mul(&y, &zSquared) + + g2Jac := bls12381.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine bls12381.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points core.HostSlice[G2Affine], out G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12381.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + var msmRes bls12381.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12381.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSMG2(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := G2GenerateAffinePoints(totalSize) + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bls12381/helpers_test.go b/wrappers/golang/curves/bls12381/helpers_test.go new file mode 100644 index 000000000..924a92ba3 --- /dev/null +++ b/wrappers/golang/curves/bls12381/helpers_test.go @@ -0,0 +1,31 @@ +package bls12381 + +import ( + "math/rand" +) + +func generateRandomLimb(size int) []uint32 { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + return limbs +} + +func generateLimbOne(size int) []uint32 { + limbs := make([]uint32, size) + limbs[0] = 1 + return limbs +} + +func generateBytesArray(size int) ([]byte, []uint32) { + baseBytes := []byte{1, 2, 3, 4} + var bytes []byte + var limbs []uint32 + for i := 0; i < size; i++ { + bytes = append(bytes, baseBytes...) + limbs = append(limbs, 67305985) + } + + return bytes, limbs +} diff --git a/wrappers/golang/curves/bls12381/include/curve.h b/wrappers/golang/curves/bls12381/include/curve.h new file mode 100644 index 000000000..d20f48f97 --- /dev/null +++ b/wrappers/golang/curves/bls12381/include/curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_381_CURVE_H +#define _BLS12_381_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bls12_381Eq(projective_t* point1, projective_t* point2); +void bls12_381ToAffine(projective_t* point, affine_t* point_out); +void bls12_381GenerateProjectivePoints(projective_t* points, int size); +void bls12_381GenerateAffinePoints(affine_t* points, int size); +cudaError_t bls12_381AffineConvertMontgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_381ProjectiveConvertMontgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12381/include/g2_curve.h b/wrappers/golang/curves/bls12381/include/g2_curve.h new file mode 100644 index 000000000..23ae11d4a --- /dev/null +++ b/wrappers/golang/curves/bls12381/include/g2_curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_381_G2CURVE_H +#define _BLS12_381_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bls12_381G2Eq(g2_projective_t* point1, g2_projective_t* point2); +void bls12_381G2ToAffine(g2_projective_t* point, g2_affine_t* point_out); +void bls12_381G2GenerateProjectivePoints(g2_projective_t* points, int size); +void bls12_381G2GenerateAffinePoints(g2_affine_t* points, int size); +cudaError_t bls12_381G2AffineConvertMontgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bls12_381G2ProjectiveConvertMontgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12381/include/g2_msm.h b/wrappers/golang/curves/bls12381/include/g2_msm.h new file mode 100644 index 000000000..5141172f0 --- /dev/null +++ b/wrappers/golang/curves/bls12381/include/g2_msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BLS12_381_G2MSM_H +#define _BLS12_381_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bls12_381G2MSMCuda(scalar_t* scalars, g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12381/include/msm.h b/wrappers/golang/curves/bls12381/include/msm.h new file mode 100644 index 000000000..dc21a96a7 --- /dev/null +++ b/wrappers/golang/curves/bls12381/include/msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BLS12_381_MSM_H +#define _BLS12_381_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bls12_381MSMCuda(scalar_t* scalars, affine_t* points, int count, MSMConfig* config, projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12381/include/ntt.h b/wrappers/golang/curves/bls12381/include/ntt.h new file mode 100644 index 000000000..12113666e --- /dev/null +++ b/wrappers/golang/curves/bls12381/include/ntt.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_381_NTT_H +#define _BLS12_381_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bls12_381NTTCuda(scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bls12_381InitializeDomain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12381/include/scalar_field.h b/wrappers/golang/curves/bls12381/include/scalar_field.h new file mode 100644 index 000000000..8abeef80c --- /dev/null +++ b/wrappers/golang/curves/bls12381/include/scalar_field.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BLS12_381_FIELD_H +#define _BLS12_381_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +void bls12_381GenerateScalars(scalar_t* scalars, int size); +cudaError_t bls12_381ScalarConvertMontgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bls12381/msm.go b/wrappers/golang/curves/bls12381/msm.go new file mode 100644 index 000000000..10d9f2860 --- /dev/null +++ b/wrappers/golang/curves/bls12381/msm.go @@ -0,0 +1,49 @@ +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0]) + } + cPoints := (*C.affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0]) + } + cResults := (*C.projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bls12_381MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bls12381/msm_test.go b/wrappers/golang/curves/bls12381/msm_test.go new file mode 100644 index 000000000..7f2d49358 --- /dev/null +++ b/wrappers/golang/curves/bls12381/msm_test.go @@ -0,0 +1,138 @@ +package bls12381 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fp" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) + +func projectiveToGnarkAffine(p Projective) bls12381.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bls12381.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.HostSlice[Affine], out Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bls12381.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + var msmRes bls12381.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bls12381.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSM(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := GenerateAffinePoints(totalSize) + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bls12381/ntt.go b/wrappers/golang/curves/bls12381/ntt.go new file mode 100644 index 000000000..e2ef983b1 --- /dev/null +++ b/wrappers/golang/curves/bls12381/ntt.go @@ -0,0 +1,59 @@ +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +func GetDefaultNttConfig() core.NTTConfig[[SCALAR_LIMBS]uint32] { + cosetGenField := ScalarField{} + cosetGenField.One() + var cosetGen [SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + core.NttCheck[T](scalars, cfg, results) + + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(scalars.Len() / int(cfg.BatchSize)) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg)) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[ScalarField])[0]) + } + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bls12_381NTTCuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitDomain(primitiveRoot ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bls12_381InitializeDomain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang/curves/bls12381/ntt_test.go b/wrappers/golang/curves/bls12381/ntt_test.go new file mode 100644 index 000000000..e3fc1d652 --- /dev/null +++ b/wrappers/golang/curves/bls12381/ntt_test.go @@ -0,0 +1,239 @@ +package bls12381 + +import ( + "reflect" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr/fft" + "github.com/stretchr/testify/assert" +) + +const ( + largestTestSize = 17 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + InitDomain(rouIcicle, cfg.Ctx, false) +} + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], output core.HostSlice[ScalarField], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} + +func TestNTTGetDefaultConfig(t *testing.T) { + actual := GetDefaultNttConfig() + expected := generateLimbOne(int(SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + cfg := GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[ScalarField], testSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := GetDefaultNttConfig() + largestBatchSize := 100 + scalars := GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{1, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[ScalarField], totalSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang/curves/bls12381/scalar_field.go b/wrappers/golang/curves/bls12381/scalar_field.go new file mode 100644 index 000000000..b1176bfee --- /dev/null +++ b/wrappers/golang/curves/bls12381/scalar_field.go @@ -0,0 +1,119 @@ +package bls12381 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + core "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int8 = 8 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalars := make([]ScalarField, size) + for i := range scalars { + scalars[i] = ScalarField{} + } + + scalarSlice := core.HostSliceFromElements[ScalarField](scalars) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bls12_381GenerateScalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsPointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bls12_381ScalarConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang/curves/bls12381/scalar_field_test.go b/wrappers/golang/curves/bls12381/scalar_field_test.go new file mode 100644 index 000000000..fa44d836c --- /dev/null +++ b/wrappers/golang/curves/bls12381/scalar_field_test.go @@ -0,0 +1,114 @@ +package bls12381 + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField ScalarField + emptyField.One() + limbOne := generateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField ScalarField + bytes, expected := generateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField ScalarField + expected, limbs := generateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestMongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + ToMontgomery(&deviceScalars) + + scalarsMontHost := GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang/curves/bn254/base_field.go b/wrappers/golang/curves/bn254/base_field.go new file mode 100644 index 000000000..e920a7671 --- /dev/null +++ b/wrappers/golang/curves/bn254/base_field.go @@ -0,0 +1,79 @@ +package bn254 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int8 = 8 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bn254/base_field_test.go b/wrappers/golang/curves/bn254/base_field_test.go new file mode 100644 index 000000000..50e14b2d3 --- /dev/null +++ b/wrappers/golang/curves/bn254/base_field_test.go @@ -0,0 +1,82 @@ +package bn254 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField BaseField + emptyField.One() + limbOne := generateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField BaseField + bytes, expected := generateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField BaseField + expected, limbs := generateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bn254/bn254.go b/wrappers/golang/curves/bn254/bn254.go new file mode 100644 index 000000000..2a8214ab7 --- /dev/null +++ b/wrappers/golang/curves/bn254/bn254.go @@ -0,0 +1,4 @@ +package bn254 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build -lingo_bn254 -lstdc++ -lm +import "C" diff --git a/wrappers/golang/curves/bn254/curve.go b/wrappers/golang/curves/bn254/curve.go new file mode 100644 index 000000000..e1216903c --- /dev/null +++ b/wrappers/golang/curves/bn254/curve.go @@ -0,0 +1,173 @@ +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bn254Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bn254ToAffine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bn254/curve_test.go b/wrappers/golang/curves/bn254/curve_test.go new file mode 100644 index 000000000..8d1bfda61 --- /dev/null +++ b/wrappers/golang/curves/bn254/curve_test.go @@ -0,0 +1,101 @@ +package bn254 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = BaseField{} + + var affineZero Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(BASE_LIMBS)) + y := generateRandomLimb(int(BASE_LIMBS)) + var affine Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero Projective + projectiveZero.Zero() + var fieldZero = BaseField{} + var fieldOne BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + var projective Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(BASE_LIMBS)) + + var projective Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bn254/g2_base_field.go b/wrappers/golang/curves/bn254/g2_base_field.go new file mode 100644 index 000000000..bcd7832bf --- /dev/null +++ b/wrappers/golang/curves/bn254/g2_base_field.go @@ -0,0 +1,81 @@ +//go:build g2 + +package bn254 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2_BASE_LIMBS int8 = 16 +) + +type G2BaseField struct { + limbs [G2_BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2_BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2_BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bn254/g2_base_field_test.go b/wrappers/golang/curves/bn254/g2_base_field_test.go new file mode 100644 index 000000000..2e4faf1c2 --- /dev/null +++ b/wrappers/golang/curves/bn254/g2_base_field_test.go @@ -0,0 +1,84 @@ +//go:build g2 + +package bn254 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField G2BaseField + emptyField.One() + limbOne := generateLimbOne(int(G2_BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2_BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField G2BaseField + bytes, expected := generateBytesArray(int(G2_BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField G2BaseField + expected, limbs := generateBytesArray(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bn254/g2_curve.go b/wrappers/golang/curves/bn254/g2_curve.go new file mode 100644 index 000000000..95881d032 --- /dev/null +++ b/wrappers/golang/curves/bn254/g2_curve.go @@ -0,0 +1,175 @@ +//go:build g2 + +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "g2_curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bn254G2Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bn254G2ToAffine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254G2GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bn254G2GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254G2AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254G2ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bn254/g2_curve_test.go b/wrappers/golang/curves/bn254/g2_curve_test.go new file mode 100644 index 000000000..5370adec9 --- /dev/null +++ b/wrappers/golang/curves/bn254/g2_curve_test.go @@ -0,0 +1,103 @@ +//go:build g2 + +package bn254 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = G2BaseField{} + + var affineZero G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(G2_BASE_LIMBS)) + y := generateRandomLimb(int(G2_BASE_LIMBS)) + var affine G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero G2Projective + projectiveZero.Zero() + var fieldZero = G2BaseField{} + var fieldOne G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bn254/g2_msm.go b/wrappers/golang/curves/bn254/g2_msm.go new file mode 100644 index 000000000..b8a9a2b78 --- /dev/null +++ b/wrappers/golang/curves/bn254/g2_msm.go @@ -0,0 +1,51 @@ +//go:build g2 + +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "g2_msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0]) + } + cPoints := (*C.g2_affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[G2Projective])[0]) + } + cResults := (*C.g2_projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bn254G2MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bn254/g2_msm_test.go b/wrappers/golang/curves/bn254/g2_msm_test.go new file mode 100644 index 000000000..c01b3e745 --- /dev/null +++ b/wrappers/golang/curves/bn254/g2_msm_test.go @@ -0,0 +1,167 @@ +//go:build g2 + +package bn254 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" +) + +func projectiveToGnarkAffineG2(p G2Projective) bn254.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := bn254.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := bn254.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := bn254.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared bn254.E2 + zSquared.Mul(&z, &z) + + var X bn254.E2 + X.Mul(&x, &z) + + var Y bn254.E2 + Y.Mul(&y, &zSquared) + + g2Jac := bn254.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine bn254.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points core.HostSlice[G2Affine], out G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bn254.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + var msmRes bn254.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bn254.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSMG2(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := G2GenerateAffinePoints(totalSize) + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bn254/helpers_test.go b/wrappers/golang/curves/bn254/helpers_test.go new file mode 100644 index 000000000..679a00495 --- /dev/null +++ b/wrappers/golang/curves/bn254/helpers_test.go @@ -0,0 +1,31 @@ +package bn254 + +import ( + "math/rand" +) + +func generateRandomLimb(size int) []uint32 { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + return limbs +} + +func generateLimbOne(size int) []uint32 { + limbs := make([]uint32, size) + limbs[0] = 1 + return limbs +} + +func generateBytesArray(size int) ([]byte, []uint32) { + baseBytes := []byte{1, 2, 3, 4} + var bytes []byte + var limbs []uint32 + for i := 0; i < size; i++ { + bytes = append(bytes, baseBytes...) + limbs = append(limbs, 67305985) + } + + return bytes, limbs +} diff --git a/wrappers/golang/curves/bn254/include/curve.h b/wrappers/golang/curves/bn254/include/curve.h new file mode 100644 index 000000000..608936747 --- /dev/null +++ b/wrappers/golang/curves/bn254/include/curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BN254_CURVE_H +#define _BN254_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bn254Eq(projective_t* point1, projective_t* point2); +void bn254ToAffine(projective_t* point, affine_t* point_out); +void bn254GenerateProjectivePoints(projective_t* points, int size); +void bn254GenerateAffinePoints(affine_t* points, int size); +cudaError_t bn254AffineConvertMontgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bn254ProjectiveConvertMontgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bn254/include/g2_curve.h b/wrappers/golang/curves/bn254/include/g2_curve.h new file mode 100644 index 000000000..aad0bd08b --- /dev/null +++ b/wrappers/golang/curves/bn254/include/g2_curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BN254_G2CURVE_H +#define _BN254_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bn254G2Eq(g2_projective_t* point1, g2_projective_t* point2); +void bn254G2ToAffine(g2_projective_t* point, g2_affine_t* point_out); +void bn254G2GenerateProjectivePoints(g2_projective_t* points, int size); +void bn254G2GenerateAffinePoints(g2_affine_t* points, int size); +cudaError_t bn254G2AffineConvertMontgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bn254G2ProjectiveConvertMontgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bn254/include/g2_msm.h b/wrappers/golang/curves/bn254/include/g2_msm.h new file mode 100644 index 000000000..e5c94a2a0 --- /dev/null +++ b/wrappers/golang/curves/bn254/include/g2_msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BN254_G2MSM_H +#define _BN254_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bn254G2MSMCuda(scalar_t* scalars, g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bn254/include/msm.h b/wrappers/golang/curves/bn254/include/msm.h new file mode 100644 index 000000000..664032aa0 --- /dev/null +++ b/wrappers/golang/curves/bn254/include/msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BN254_MSM_H +#define _BN254_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bn254MSMCuda(scalar_t* scalars, affine_t* points, int count, MSMConfig* config, projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bn254/include/ntt.h b/wrappers/golang/curves/bn254/include/ntt.h new file mode 100644 index 000000000..3031727d8 --- /dev/null +++ b/wrappers/golang/curves/bn254/include/ntt.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BN254_NTT_H +#define _BN254_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bn254NTTCuda(scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bn254InitializeDomain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bn254/include/scalar_field.h b/wrappers/golang/curves/bn254/include/scalar_field.h new file mode 100644 index 000000000..f4ef9f59f --- /dev/null +++ b/wrappers/golang/curves/bn254/include/scalar_field.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BN254_FIELD_H +#define _BN254_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +void bn254GenerateScalars(scalar_t* scalars, int size); +cudaError_t bn254ScalarConvertMontgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/goicicle/curves/bn254/include/ve_mod_mult.h b/wrappers/golang/curves/bn254/include/ve_mod_mult.h similarity index 54% rename from goicicle/curves/bn254/include/ve_mod_mult.h rename to wrappers/golang/curves/bn254/include/ve_mod_mult.h index fcd5753c0..31e1103c8 100644 --- a/goicicle/curves/bn254/include/ve_mod_mult.h +++ b/wrappers/golang/curves/bn254/include/ve_mod_mult.h @@ -16,6 +16,7 @@ // Code generated by Ingonyama DO NOT EDIT #include +#include #include // ve_mod_mult.h @@ -26,17 +27,41 @@ extern "C" { #endif -typedef struct BN254_projective_t BN254_projective_t; +typedef struct { + cudaStream_t stream; /**< Stream to use. Default value: 0. */ + int device_id; /**< Index of the currently used GPU. Default value: 0. */ + cudaMemPool_t mempool; /**< Mempool to use. Default value: 0. */ +} DeviceContext; + typedef struct BN254_scalar_t BN254_scalar_t; -int32_t -vec_mod_mult_point_bn254(BN254_projective_t* inout, BN254_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t -vec_mod_mult_scalar_bn254(BN254_scalar_t* inout, BN254_scalar_t* scalar_vec, size_t n_elments, size_t device_id); -int32_t vec_mod_mult_device_scalar_bn254( - BN254_scalar_t* inout, BN254_scalar_t* scalar_vec, size_t n_elements, size_t device_id); -int32_t matrix_vec_mod_mult_bn254( - BN254_scalar_t* matrix_flattened, BN254_scalar_t* input, BN254_scalar_t* output, size_t n_elments, size_t device_id); +int bn254AddCuda( + BN254_scalar_t* vec_a, + BN254_scalar_t* vec_b, + int n, + bool is_on_device, + DeviceContext ctx, + BN254_scalar_t* result +); + +int bn254SubCuda( + BN254_scalar_t* vec_a, + BN254_scalar_t* vec_b, + int n, + bool is_on_device, + DeviceContext ctx, + BN254_scalar_t* result +); + +int bn254MulCuda( + BN254_scalar_t* vec_a, + BN254_scalar_t* vec_b, + int n, + bool is_on_device, + bool is_montgomery, + DeviceContext ctx, + BN254_scalar_t* result +); #ifdef __cplusplus } diff --git a/wrappers/golang/curves/bn254/msm.go b/wrappers/golang/curves/bn254/msm.go new file mode 100644 index 000000000..5ffea6126 --- /dev/null +++ b/wrappers/golang/curves/bn254/msm.go @@ -0,0 +1,49 @@ +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0]) + } + cPoints := (*C.affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0]) + } + cResults := (*C.projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bn254MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bn254/msm_test.go b/wrappers/golang/curves/bn254/msm_test.go new file mode 100644 index 000000000..39834dfbd --- /dev/null +++ b/wrappers/golang/curves/bn254/msm_test.go @@ -0,0 +1,138 @@ +package bn254 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bn254" + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" +) + +func projectiveToGnarkAffine(p Projective) bn254.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bn254.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.HostSlice[Affine], out Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bn254.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + var msmRes bn254.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bn254.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSM(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := GenerateAffinePoints(totalSize) + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bn254/ntt.go b/wrappers/golang/curves/bn254/ntt.go new file mode 100644 index 000000000..3b9c54a1c --- /dev/null +++ b/wrappers/golang/curves/bn254/ntt.go @@ -0,0 +1,59 @@ +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +func GetDefaultNttConfig() core.NTTConfig[[SCALAR_LIMBS]uint32] { + cosetGenField := ScalarField{} + cosetGenField.One() + var cosetGen [SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + core.NttCheck[T](scalars, cfg, results) + + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(scalars.Len() / int(cfg.BatchSize)) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg)) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[ScalarField])[0]) + } + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bn254NTTCuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitDomain(primitiveRoot ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bn254InitializeDomain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang/curves/bn254/ntt_test.go b/wrappers/golang/curves/bn254/ntt_test.go new file mode 100644 index 000000000..fd5c8c38a --- /dev/null +++ b/wrappers/golang/curves/bn254/ntt_test.go @@ -0,0 +1,239 @@ +package bn254 + +import ( + "reflect" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" + "github.com/stretchr/testify/assert" +) + +const ( + largestTestSize = 17 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + InitDomain(rouIcicle, cfg.Ctx, false) +} + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], output core.HostSlice[ScalarField], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} + +func TestNTTGetDefaultConfig(t *testing.T) { + actual := GetDefaultNttConfig() + expected := generateLimbOne(int(SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + cfg := GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[ScalarField], testSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := GetDefaultNttConfig() + largestBatchSize := 100 + scalars := GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{1, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[ScalarField], totalSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang/curves/bn254/scalar_field.go b/wrappers/golang/curves/bn254/scalar_field.go new file mode 100644 index 000000000..2051bc083 --- /dev/null +++ b/wrappers/golang/curves/bn254/scalar_field.go @@ -0,0 +1,119 @@ +package bn254 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + core "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int8 = 8 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalars := make([]ScalarField, size) + for i := range scalars { + scalars[i] = ScalarField{} + } + + scalarSlice := core.HostSliceFromElements[ScalarField](scalars) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bn254GenerateScalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsPointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bn254ScalarConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang/curves/bn254/scalar_field_test.go b/wrappers/golang/curves/bn254/scalar_field_test.go new file mode 100644 index 000000000..0b3dcca41 --- /dev/null +++ b/wrappers/golang/curves/bn254/scalar_field_test.go @@ -0,0 +1,114 @@ +package bn254 + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField ScalarField + emptyField.One() + limbOne := generateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField ScalarField + bytes, expected := generateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField ScalarField + expected, limbs := generateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestMongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + ToMontgomery(&deviceScalars) + + scalarsMontHost := GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang/curves/bw6761/base_field.go b/wrappers/golang/curves/bw6761/base_field.go new file mode 100644 index 000000000..ff2700a06 --- /dev/null +++ b/wrappers/golang/curves/bw6761/base_field.go @@ -0,0 +1,79 @@ +package bw6761 + +import ( + "encoding/binary" + "fmt" +) + +const ( + BASE_LIMBS int8 = 24 +) + +type BaseField struct { + limbs [BASE_LIMBS]uint32 +} + +func (f BaseField) Len() int { + return int(BASE_LIMBS) +} + +func (f BaseField) Size() int { + return int(BASE_LIMBS * 4) +} + +func (f BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *BaseField) FromLimbs(limbs []uint32) BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *BaseField) Zero() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *BaseField) One() BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *BaseField) FromBytesLittleEndian(bytes []byte) BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bw6761/base_field_test.go b/wrappers/golang/curves/bw6761/base_field_test.go new file mode 100644 index 000000000..e5bbf9f78 --- /dev/null +++ b/wrappers/golang/curves/bw6761/base_field_test.go @@ -0,0 +1,82 @@ +package bw6761 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestBaseFieldFromLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestBaseFieldGetLimbs(t *testing.T) { + emptyField := BaseField{} + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the BaseField's limbs") +} + +func TestBaseFieldOne(t *testing.T) { + var emptyField BaseField + emptyField.One() + limbOne := generateLimbOne(int(BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "BaseField with limbs to field one did not work") +} + +func TestBaseFieldZero(t *testing.T) { + var emptyField BaseField + emptyField.Zero() + limbsZero := make([]uint32, BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "BaseField with limbs to field zero failed") +} + +func TestBaseFieldSize(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestBaseFieldAsPointer(t *testing.T) { + var emptyField BaseField + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestBaseFieldFromBytes(t *testing.T) { + var emptyField BaseField + bytes, expected := generateBytesArray(int(BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestBaseFieldToBytes(t *testing.T) { + var emptyField BaseField + expected, limbs := generateBytesArray(int(BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bw6761/bw6_761.go b/wrappers/golang/curves/bw6761/bw6_761.go new file mode 100644 index 000000000..4e679ffe3 --- /dev/null +++ b/wrappers/golang/curves/bw6761/bw6_761.go @@ -0,0 +1,4 @@ +package bw6761 + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build -lingo_bw6_761 -lstdc++ -lm +import "C" diff --git a/wrappers/golang/curves/bw6761/curve.go b/wrappers/golang/curves/bw6761/curve.go new file mode 100644 index 000000000..0cb5fe20a --- /dev/null +++ b/wrappers/golang/curves/bw6761/curve.go @@ -0,0 +1,173 @@ +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type Projective struct { + X, Y, Z BaseField +} + +func (p Projective) Size() int { + return p.X.Size() * 3 +} + +func (p Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *Projective) Zero() Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *Projective) FromLimbs(x, y, z []uint32) Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *Projective) FromAffine(a Affine) Projective { + z := BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p Projective) ProjectiveEq(p2 *Projective) bool { + cP := (*C.projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.projective_t)(unsafe.Pointer(&p2)) + __ret := C.bw6_761Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *Projective) ProjectiveToAffine() Affine { + var a Affine + + cA := (*C.affine_t)(unsafe.Pointer(&a)) + cP := (*C.projective_t)(unsafe.Pointer(&p)) + C.bw6_761ToAffine(cP, cA) + return a +} + +func GenerateProjectivePoints(size int) core.HostSlice[Projective] { + points := make([]Projective, size) + for i := range points { + points[i] = Projective{} + } + + pointsSlice := core.HostSliceFromElements[Projective](points) + pPoints := (*C.projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type Affine struct { + X, Y BaseField +} + +func (a Affine) Size() int { + return a.X.Size() * 2 +} + +func (a Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *Affine) Zero() Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *Affine) FromLimbs(x, y []uint32) Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a Affine) ToProjective() Projective { + var z BaseField + + return Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func AffineFromProjective(p *Projective) Affine { + return p.ProjectiveToAffine() +} + +func GenerateAffinePoints(size int) core.HostSlice[Affine] { + points := make([]Affine, size) + for i := range points { + points[i] = Affine{} + } + + pointsSlice := core.HostSliceFromElements[Affine](points) + cPoints := (*C.affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertAffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, true) +} + +func AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertAffinePointsMontgomery(points, false) +} + +func convertProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, true) +} + +func ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bw6761/curve_test.go b/wrappers/golang/curves/bw6761/curve_test.go new file mode 100644 index 000000000..aafbbcdd5 --- /dev/null +++ b/wrappers/golang/curves/bw6761/curve_test.go @@ -0,0 +1,101 @@ +package bw6761 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAffineZero(t *testing.T) { + var fieldZero = BaseField{} + + var affineZero Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(BASE_LIMBS)) + y := generateRandomLimb(int(BASE_LIMBS)) + var affine Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestAffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestAffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestProjectiveZero(t *testing.T) { + var projectiveZero Projective + projectiveZero.Zero() + var fieldZero = BaseField{} + var fieldOne BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + var projective Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(BASE_LIMBS)) + + var projective Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(BASE_LIMBS)) + var fieldOne BaseField + fieldOne.One() + + var expected Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bw6761/g2_base_field.go b/wrappers/golang/curves/bw6761/g2_base_field.go new file mode 100644 index 000000000..d74de5302 --- /dev/null +++ b/wrappers/golang/curves/bw6761/g2_base_field.go @@ -0,0 +1,81 @@ +//go:build g2 + +package bw6761 + +import ( + "encoding/binary" + "fmt" +) + +const ( + G2_BASE_LIMBS int8 = 24 +) + +type G2BaseField struct { + limbs [G2_BASE_LIMBS]uint32 +} + +func (f G2BaseField) Len() int { + return int(G2_BASE_LIMBS) +} + +func (f G2BaseField) Size() int { + return int(G2_BASE_LIMBS * 4) +} + +func (f G2BaseField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f G2BaseField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *G2BaseField) FromLimbs(limbs []uint32) G2BaseField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *G2BaseField) Zero() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *G2BaseField) One() G2BaseField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *G2BaseField) FromBytesLittleEndian(bytes []byte) G2BaseField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f G2BaseField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} diff --git a/wrappers/golang/curves/bw6761/g2_base_field_test.go b/wrappers/golang/curves/bw6761/g2_base_field_test.go new file mode 100644 index 000000000..9682866ce --- /dev/null +++ b/wrappers/golang/curves/bw6761/g2_base_field_test.go @@ -0,0 +1,84 @@ +//go:build g2 + +package bw6761 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2BaseFieldFromLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the G2BaseField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestG2BaseFieldGetLimbs(t *testing.T) { + emptyField := G2BaseField{} + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the G2BaseField's limbs") +} + +func TestG2BaseFieldOne(t *testing.T) { + var emptyField G2BaseField + emptyField.One() + limbOne := generateLimbOne(int(G2_BASE_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "G2BaseField with limbs to field one did not work") +} + +func TestG2BaseFieldZero(t *testing.T) { + var emptyField G2BaseField + emptyField.Zero() + limbsZero := make([]uint32, G2_BASE_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "G2BaseField with limbs to field zero failed") +} + +func TestG2BaseFieldSize(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestG2BaseFieldAsPointer(t *testing.T) { + var emptyField G2BaseField + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestG2BaseFieldFromBytes(t *testing.T) { + var emptyField G2BaseField + bytes, expected := generateBytesArray(int(G2_BASE_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestG2BaseFieldToBytes(t *testing.T) { + var emptyField G2BaseField + expected, limbs := generateBytesArray(int(G2_BASE_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} diff --git a/wrappers/golang/curves/bw6761/g2_curve.go b/wrappers/golang/curves/bw6761/g2_curve.go new file mode 100644 index 000000000..fc872f260 --- /dev/null +++ b/wrappers/golang/curves/bw6761/g2_curve.go @@ -0,0 +1,175 @@ +//go:build g2 + +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "g2_curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +type G2Projective struct { + X, Y, Z G2BaseField +} + +func (p G2Projective) Size() int { + return p.X.Size() * 3 +} + +func (p G2Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *G2Projective) Zero() G2Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *G2Projective) FromLimbs(x, y, z []uint32) G2Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *G2Projective) FromAffine(a G2Affine) G2Projective { + z := G2BaseField{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} + +func (p G2Projective) ProjectiveEq(p2 *G2Projective) bool { + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.g2_projective_t)(unsafe.Pointer(&p2)) + __ret := C.bw6_761G2Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *G2Projective) ProjectiveToAffine() G2Affine { + var a G2Affine + + cA := (*C.g2_affine_t)(unsafe.Pointer(&a)) + cP := (*C.g2_projective_t)(unsafe.Pointer(&p)) + C.bw6_761G2ToAffine(cP, cA) + return a +} + +func G2GenerateProjectivePoints(size int) core.HostSlice[G2Projective] { + points := make([]G2Projective, size) + for i := range points { + points[i] = G2Projective{} + } + + pointsSlice := core.HostSliceFromElements[G2Projective](points) + pPoints := (*C.g2_projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761G2GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} + +type G2Affine struct { + X, Y G2BaseField +} + +func (a G2Affine) Size() int { + return a.X.Size() * 2 +} + +func (a G2Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *G2Affine) Zero() G2Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *G2Affine) FromLimbs(x, y []uint32) G2Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a G2Affine) ToProjective() G2Projective { + var z G2BaseField + + return G2Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} + +func G2AffineFromProjective(p *G2Projective) G2Affine { + return p.ProjectiveToAffine() +} + +func G2GenerateAffinePoints(size int) core.HostSlice[G2Affine] { + points := make([]G2Affine, size) + for i := range points { + points[i] = G2Affine{} + } + + pointsSlice := core.HostSliceFromElements[G2Affine](points) + cPoints := (*C.g2_affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.bw6_761G2GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convertG2AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761G2AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, true) +} + +func G2AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2AffinePointsMontgomery(points, false) +} + +func convertG2ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.g2_projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761G2ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func G2ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, true) +} + +func G2ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convertG2ProjectivePointsMontgomery(points, false) +} diff --git a/wrappers/golang/curves/bw6761/g2_curve_test.go b/wrappers/golang/curves/bw6761/g2_curve_test.go new file mode 100644 index 000000000..c1426c7d3 --- /dev/null +++ b/wrappers/golang/curves/bw6761/g2_curve_test.go @@ -0,0 +1,103 @@ +//go:build g2 + +package bw6761 + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestG2AffineZero(t *testing.T) { + var fieldZero = G2BaseField{} + + var affineZero G2Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int(G2_BASE_LIMBS)) + y := generateRandomLimb(int(G2_BASE_LIMBS)) + var affine G2Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func TestG2AffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func TestG2AffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func TestG2ProjectiveZero(t *testing.T) { + var projectiveZero G2Projective + projectiveZero.Zero() + var fieldZero = G2BaseField{} + var fieldOne G2BaseField + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func TestG2ProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int(G2_BASE_LIMBS)) + + var projective G2Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func TestG2ProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int(G2_BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int(G2_BASE_LIMBS)) + var fieldOne G2BaseField + fieldOne.One() + + var expected G2Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine G2Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint G2Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/curves/bw6761/g2_msm.go b/wrappers/golang/curves/bw6761/g2_msm.go new file mode 100644 index 000000000..8d9a320ad --- /dev/null +++ b/wrappers/golang/curves/bw6761/g2_msm.go @@ -0,0 +1,51 @@ +//go:build g2 + +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "g2_msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func G2GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[G2Affine])[0]) + } + cPoints := (*C.g2_affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[G2Projective])[0]) + } + cResults := (*C.g2_projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bw6_761G2MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bw6761/g2_msm_test.go b/wrappers/golang/curves/bw6761/g2_msm_test.go new file mode 100644 index 000000000..388e7dbc7 --- /dev/null +++ b/wrappers/golang/curves/bw6761/g2_msm_test.go @@ -0,0 +1,140 @@ +//go:build g2 + +package bw6761 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" +) + +func projectiveToGnarkAffineG2(p G2Projective) bw6761.G2Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bw6761.G2Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsmG2(scalars core.HostSlice[ScalarField], points core.HostSlice[G2Affine], out G2Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bw6761.G2Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffineG2(v.ToProjective()) + } + var msmRes bw6761.G2Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bw6761.G2Jac + proj := projectiveToGnarkAffineG2(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSMG2(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := G2GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p G2Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} + +func TestMSMG2Batch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := G2GenerateAffinePoints(totalSize) + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsmG2(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMG2SkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := G2GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p G2Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = G2Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[G2Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsmG2(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bw6761/helpers_test.go b/wrappers/golang/curves/bw6761/helpers_test.go new file mode 100644 index 000000000..bb3d9e916 --- /dev/null +++ b/wrappers/golang/curves/bw6761/helpers_test.go @@ -0,0 +1,31 @@ +package bw6761 + +import ( + "math/rand" +) + +func generateRandomLimb(size int) []uint32 { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + return limbs +} + +func generateLimbOne(size int) []uint32 { + limbs := make([]uint32, size) + limbs[0] = 1 + return limbs +} + +func generateBytesArray(size int) ([]byte, []uint32) { + baseBytes := []byte{1, 2, 3, 4} + var bytes []byte + var limbs []uint32 + for i := 0; i < size; i++ { + bytes = append(bytes, baseBytes...) + limbs = append(limbs, 67305985) + } + + return bytes, limbs +} diff --git a/wrappers/golang/curves/bw6761/include/curve.h b/wrappers/golang/curves/bw6761/include/curve.h new file mode 100644 index 000000000..4630e6168 --- /dev/null +++ b/wrappers/golang/curves/bw6761/include/curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BW6_761_CURVE_H +#define _BW6_761_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bw6_761Eq(projective_t* point1, projective_t* point2); +void bw6_761ToAffine(projective_t* point, affine_t* point_out); +void bw6_761GenerateProjectivePoints(projective_t* points, int size); +void bw6_761GenerateAffinePoints(affine_t* points, int size); +cudaError_t bw6_761AffineConvertMontgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bw6_761ProjectiveConvertMontgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bw6761/include/g2_curve.h b/wrappers/golang/curves/bw6761/include/g2_curve.h new file mode 100644 index 000000000..55ed70443 --- /dev/null +++ b/wrappers/golang/curves/bw6761/include/g2_curve.h @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BW6_761_G2CURVE_H +#define _BW6_761_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool bw6_761G2Eq(g2_projective_t* point1, g2_projective_t* point2); +void bw6_761G2ToAffine(g2_projective_t* point, g2_affine_t* point_out); +void bw6_761G2GenerateProjectivePoints(g2_projective_t* points, int size); +void bw6_761G2GenerateAffinePoints(g2_affine_t* points, int size); +cudaError_t bw6_761G2AffineConvertMontgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t bw6_761G2ProjectiveConvertMontgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bw6761/include/g2_msm.h b/wrappers/golang/curves/bw6761/include/g2_msm.h new file mode 100644 index 000000000..38b4994e6 --- /dev/null +++ b/wrappers/golang/curves/bw6761/include/g2_msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BW6_761_G2MSM_H +#define _BW6_761_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bw6_761G2MSMCuda(scalar_t* scalars, g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bw6761/include/msm.h b/wrappers/golang/curves/bw6761/include/msm.h new file mode 100644 index 000000000..8101cb5c0 --- /dev/null +++ b/wrappers/golang/curves/bw6761/include/msm.h @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _BW6_761_MSM_H +#define _BW6_761_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bw6_761MSMCuda(scalar_t* scalars, affine_t* points, int count, MSMConfig* config, projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bw6761/include/ntt.h b/wrappers/golang/curves/bw6761/include/ntt.h new file mode 100644 index 000000000..6716834cd --- /dev/null +++ b/wrappers/golang/curves/bw6761/include/ntt.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BW6_761_NTT_H +#define _BW6_761_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t bw6_761NTTCuda(scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t bw6_761InitializeDomain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bw6761/include/scalar_field.h b/wrappers/golang/curves/bw6761/include/scalar_field.h new file mode 100644 index 000000000..65512600d --- /dev/null +++ b/wrappers/golang/curves/bw6761/include/scalar_field.h @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _BW6_761_FIELD_H +#define _BW6_761_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +void bw6_761GenerateScalars(scalar_t* scalars, int size); +cudaError_t bw6_761ScalarConvertMontgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/curves/bw6761/msm.go b/wrappers/golang/curves/bw6761/msm.go new file mode 100644 index 000000000..9bd2a8ce8 --- /dev/null +++ b/wrappers/golang/curves/bw6761/msm.go @@ -0,0 +1,49 @@ +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[Affine])[0]) + } + cPoints := (*C.affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[Projective])[0]) + } + cResults := (*C.projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.bw6_761MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/curves/bw6761/msm_test.go b/wrappers/golang/curves/bw6761/msm_test.go new file mode 100644 index 000000000..415f88cbe --- /dev/null +++ b/wrappers/golang/curves/bw6761/msm_test.go @@ -0,0 +1,138 @@ +package bw6761 + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/bw6-761" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fp" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" +) + +func projectiveToGnarkAffine(p Projective) bw6761.G1Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return bw6761.G1Affine{X: *x, Y: *y} +} + +func testAgainstGnarkCryptoMsm(scalars core.HostSlice[ScalarField], points core.HostSlice[Affine], out Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]bw6761.G1Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine(v.ToProjective()) + } + var msmRes bw6761.G1Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac bw6761.G1Jac + proj := projectiveToGnarkAffine(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSM(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} + +func TestMSMBatch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := GenerateAffinePoints(totalSize) + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSMSkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/curves/bw6761/ntt.go b/wrappers/golang/curves/bw6761/ntt.go new file mode 100644 index 000000000..009fff236 --- /dev/null +++ b/wrappers/golang/curves/bw6761/ntt.go @@ -0,0 +1,59 @@ +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +func GetDefaultNttConfig() core.NTTConfig[[SCALAR_LIMBS]uint32] { + cosetGenField := ScalarField{} + cosetGenField.One() + var cosetGen [SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + core.NttCheck[T](scalars, cfg, results) + + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(scalars.Len() / int(cfg.BatchSize)) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg)) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[ScalarField])[0]) + } + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.bw6_761NTTCuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitDomain(primitiveRoot ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.bw6_761InitializeDomain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang/curves/bw6761/ntt_test.go b/wrappers/golang/curves/bw6761/ntt_test.go new file mode 100644 index 000000000..392836368 --- /dev/null +++ b/wrappers/golang/curves/bw6761/ntt_test.go @@ -0,0 +1,239 @@ +package bw6761 + +import ( + "reflect" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" + "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/fft" + "github.com/stretchr/testify/assert" +) + +const ( + largestTestSize = 17 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + InitDomain(rouIcicle, cfg.Ctx, false) +} + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], output core.HostSlice[ScalarField], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} + +func TestNTTGetDefaultConfig(t *testing.T) { + actual := GetDefaultNttConfig() + expected := generateLimbOne(int(SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + cfg := GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[ScalarField], testSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := GetDefaultNttConfig() + largestBatchSize := 100 + scalars := GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{1, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[ScalarField], totalSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang/curves/bw6761/scalar_field.go b/wrappers/golang/curves/bw6761/scalar_field.go new file mode 100644 index 000000000..47245ce3b --- /dev/null +++ b/wrappers/golang/curves/bw6761/scalar_field.go @@ -0,0 +1,119 @@ +package bw6761 + +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +import ( + "encoding/binary" + "fmt" + core "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +const ( + SCALAR_LIMBS int8 = 12 +) + +type ScalarField struct { + limbs [SCALAR_LIMBS]uint32 +} + +func (f ScalarField) Len() int { + return int(SCALAR_LIMBS) +} + +func (f ScalarField) Size() int { + return int(SCALAR_LIMBS * 4) +} + +func (f ScalarField) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f ScalarField) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *ScalarField) FromLimbs(limbs []uint32) ScalarField { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *ScalarField) Zero() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *ScalarField) One() ScalarField { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *ScalarField) FromBytesLittleEndian(bytes []byte) ScalarField { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f ScalarField) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} + +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalars := make([]ScalarField, size) + for i := range scalars { + scalars[i] = ScalarField{} + } + + scalarSlice := core.HostSliceFromElements[ScalarField](scalars) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.bw6_761GenerateScalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsPointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.bw6_761ScalarConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, false) +} diff --git a/wrappers/golang/curves/bw6761/scalar_field_test.go b/wrappers/golang/curves/bw6761/scalar_field_test.go new file mode 100644 index 000000000..5a8b67457 --- /dev/null +++ b/wrappers/golang/curves/bw6761/scalar_field_test.go @@ -0,0 +1,114 @@ +package bw6761 + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestScalarFieldFromLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the ScalarField's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func TestScalarFieldGetLimbs(t *testing.T) { + emptyField := ScalarField{} + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the ScalarField's limbs") +} + +func TestScalarFieldOne(t *testing.T) { + var emptyField ScalarField + emptyField.One() + limbOne := generateLimbOne(int(SCALAR_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "ScalarField with limbs to field one did not work") +} + +func TestScalarFieldZero(t *testing.T) { + var emptyField ScalarField + emptyField.Zero() + limbsZero := make([]uint32, SCALAR_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "ScalarField with limbs to field zero failed") +} + +func TestScalarFieldSize(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func TestScalarFieldAsPointer(t *testing.T) { + var emptyField ScalarField + randLimbs := generateRandomLimb(int(SCALAR_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func TestScalarFieldFromBytes(t *testing.T) { + var emptyField ScalarField + bytes, expected := generateBytesArray(int(SCALAR_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func TestScalarFieldToBytes(t *testing.T) { + var emptyField ScalarField + expected, limbs := generateBytesArray(int(SCALAR_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} + +func TestGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestMongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + ToMontgomery(&deviceScalars) + + scalarsMontHost := GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +} diff --git a/wrappers/golang/curves/include/types.h b/wrappers/golang/curves/include/types.h new file mode 100644 index 000000000..1ce9e8c7b --- /dev/null +++ b/wrappers/golang/curves/include/types.h @@ -0,0 +1,36 @@ +#include + +// #define G2_DEFINED +// #include "../../../../../icicle/curves/curve_config.cuh" + +#ifndef _TYPES_H +#define _TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +// typedef curve_config::scalar_t scalar_t; +// typedef curve_config::projective_t projective_t; +// typedef curve_config::g2_projective_t g2_projective_t; +// typedef curve_config::affine_t affine_t; +// typedef curve_config::g2_affine_t g2_affine_t; + +// typedef struct uint32 unsigned long int; +typedef struct scalar_t scalar_t; +typedef struct projective_t projective_t; +typedef struct g2_projective_t g2_projective_t; +typedef struct affine_t affine_t; +typedef struct g2_affine_t g2_affine_t; + +typedef struct MSMConfig MSMConfig; +typedef struct NTTConfig NTTConfig; +typedef struct DeviceContext DeviceContext; + +typedef cudaError_t cudaError_t; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/wrappers/golang/internal/generator/main.go b/wrappers/golang/internal/generator/main.go new file mode 100644 index 000000000..4266ea409 --- /dev/null +++ b/wrappers/golang/internal/generator/main.go @@ -0,0 +1,250 @@ +package main + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "text/template" +) + +const ( + baseDir = "../../curves/" // wrappers/golang/curves +) + +func create(output string, buf *bytes.Buffer) error { + // create output dir if not exist + _ = os.MkdirAll(filepath.Dir(output), os.ModePerm) + + // create output file + file, err := os.Create(output) + if err != nil { + return err + } + + if _, err := io.Copy(file, buf); err != nil { + file.Close() + return err + } + + file.Close() + return nil +} + +type CurveData struct { + PackageName string + Curve string + GnarkImport string + ScalarLimbsNum int + BaseLimbsNum int + G2BaseLimbsNum int +} + +var bn254 = CurveData{ + PackageName: "bn254", + Curve: "bn254", + GnarkImport: "bn254", + ScalarLimbsNum: 8, + BaseLimbsNum: 8, + G2BaseLimbsNum: 16, +} +var bls12381 = CurveData{ + PackageName: "bls12381", + Curve: "bls12_381", + GnarkImport: "bls12-381", + ScalarLimbsNum: 8, + BaseLimbsNum: 12, + G2BaseLimbsNum: 24, +} +var bls12377 = CurveData{ + PackageName: "bls12377", + Curve: "bls12_377", + GnarkImport: "bls12-377", + ScalarLimbsNum: 8, + BaseLimbsNum: 12, + G2BaseLimbsNum: 24, +} +var bw6761 = CurveData{ + PackageName: "bw6761", + Curve: "bw6_761", + GnarkImport: "bw6-761", + ScalarLimbsNum: 12, + BaseLimbsNum: 24, + G2BaseLimbsNum: 24, +} + +type Entry struct { + outputName string + parsedTemplate *template.Template +} + +func toPackage(s string) string { + return strings.ReplaceAll(s, "-", "") +} + +func generateFiles() { + fmt.Println("Generating files") + funcs := template.FuncMap{ + "log": fmt.Println, + "toLower": strings.ToLower, + "toUpper": strings.ToUpper, + "toPackage": toPackage, + } + + curvesData := []CurveData{bn254, bls12377, bls12381, bw6761} + var entries []Entry + + templateFiles := []string{ + "main.go.tmpl", + "msm.go.tmpl", + "msm_test.go.tmpl", + "ntt.go.tmpl", + "ntt_test.go.tmpl", + "curve_test.go.tmpl", + "curve.go.tmpl", + /* "vec_ops.h.tmpl,"*/ + "helpers_test.go.tmpl", + } + + for _, tmplName := range templateFiles { + tmpl := template.New(tmplName).Funcs(funcs) + tmplParsed, err := tmpl.ParseFiles(fmt.Sprintf("templates/%s", tmplName)) + if err != nil { + panic(err) + } + fileName, ok := strings.CutSuffix(tmplName, ".tmpl") + if !ok { + panic(err) + } + entries = append(entries, Entry{outputName: fileName, parsedTemplate: tmplParsed}) + } + + templateG2Files := []string{ + "msm.go.tmpl", + "msm_test.go.tmpl", + "curve_test.go.tmpl", + "curve.go.tmpl", + } + + for _, tmplName := range templateG2Files { + tmpl := template.New(tmplName).Funcs(funcs) + tmplParsed, err := tmpl.ParseFiles(fmt.Sprintf("templates/%s", tmplName)) + if err != nil { + panic(err) + } + rawFileName, _ := strings.CutSuffix(tmplName, ".tmpl") + fileName := fmt.Sprintf("g2_%s", rawFileName) + entries = append(entries, Entry{outputName: fileName, parsedTemplate: tmplParsed}) + } + + templateFieldFiles := []string{ + "field.go.tmpl", + "field_test.go.tmpl", + } + + fieldFilePrefixes := []string{ + "base", + "g2_base", + "scalar", + } + + for _, tmplName := range templateFieldFiles { + tmpl := template.New(tmplName).Funcs(funcs) + tmplParsed, err := tmpl.ParseFiles(fmt.Sprintf("templates/%s", tmplName), "templates/scalar_field.go.tmpl", "templates/scalar_field_test.go.tmpl") + if err != nil { + panic(err) + } + fieldFile, _ := strings.CutSuffix(tmplName, ".tmpl") + for _, fieldPrefix := range fieldFilePrefixes { + fileName := strings.Join([]string{fieldPrefix, fieldFile}, "_") + entries = append(entries, Entry{outputName: fileName, parsedTemplate: tmplParsed}) + } + } + + // Header files + templateIncludeFiles := []string{ + "curve.h.tmpl", + "g2_curve.h.tmpl", + "scalar_field.h.tmpl", + "msm.h.tmpl", + "g2_msm.h.tmpl", + "ntt.h.tmpl", + /*"vec_ops.h.tmpl",*/ + } + + for _, includeFile := range templateIncludeFiles { + tmpl := template.New(includeFile).Funcs(funcs) + tmplParsed, err := tmpl.ParseFiles(fmt.Sprintf("templates/include/%s", includeFile)) + if err != nil { + panic(err) + } + fileName, _ := strings.CutSuffix(includeFile, ".tmpl") + entries = append(entries, Entry{outputName: fmt.Sprintf("include/%s", fileName), parsedTemplate: tmplParsed}) + } + + for _, curveData := range curvesData { + for _, entry := range entries { + fileName := entry.outputName + if strings.Contains(fileName, "main") { + fileName = strings.Replace(fileName, "main", curveData.Curve, 1) + } + outFile := filepath.Join(baseDir, curveData.PackageName, fileName) + var buf bytes.Buffer + data := struct { + CurveData + IsScalar bool + IsG2 bool + IsMock bool + }{ + curveData, + strings.Contains(fileName, "scalar_field"), + strings.Contains(fileName, "g2"), + false, + } + entry.parsedTemplate.Execute(&buf, data) + create(outFile, &buf) + } + } + + // Generate internal mock field and mock curve files for testing core package + internalTemplateFiles := []string{ + "curve_test.go.tmpl", + "curve.go.tmpl", + "field_test.go.tmpl", + "field.go.tmpl", + "helpers_test.go.tmpl", + } + + for _, internalTemplate := range internalTemplateFiles { + tmpl := template.New(internalTemplate).Funcs(funcs) + tmplParsed, err := tmpl.ParseFiles(fmt.Sprintf("templates/%s", internalTemplate)) + if err != nil { + panic(err) + } + fileName, _ := strings.CutSuffix(internalTemplate, ".tmpl") + outFile := filepath.Join("../../core/internal/", fileName) + + var buf bytes.Buffer + data := struct { + PackageName string + BaseLimbsNum int + IsMock bool + IsG2 bool + IsScalar bool + }{ + "internal", + 8, + true, + false, + false, + } + tmplParsed.Execute(&buf, data) + create(outFile, &buf) + } +} + +func main() { + generateFiles() +} diff --git a/wrappers/golang/internal/generator/templates/curve.go.tmpl b/wrappers/golang/internal/generator/templates/curve.go.tmpl new file mode 100644 index 000000000..33f319ac2 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/curve.go.tmpl @@ -0,0 +1,178 @@ +{{if .IsG2 -}} +//go:build g2 + +{{end -}} +package {{.PackageName}} +{{if not .IsMock}} +// #cgo CFLAGS: -I./include/ +// #include "{{if .IsG2 -}}g2_{{end}}curve.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) +{{end}} +type {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective struct { + X, Y, Z {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field +} + +func (p {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective) Size() int { + return p.X.Size() * 3 +} + +func (p {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective) AsPointer() *uint32 { + return p.X.AsPointer() +} + +func (p *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective) Zero() {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective { + p.X.Zero() + p.Y.One() + p.Z.Zero() + + return *p +} + +func (p *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective) FromLimbs(x, y, z []uint32) {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective { + p.X.FromLimbs(x) + p.Y.FromLimbs(y) + p.Z.FromLimbs(z) + + return *p +} + +func (p *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective) FromAffine(a {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine) {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective { + z := {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field{} + z.One() + + p.X = a.X + p.Y = a.Y + p.Z = z + + return *p +} +{{if not .IsMock}} +func (p {{if .IsG2}}G2{{end}}Projective) ProjectiveEq(p2 *{{if .IsG2}}G2{{end}}Projective) bool { + cP := (*C.{{if .IsG2}}g2_{{end}}projective_t)(unsafe.Pointer(&p)) + cP2 := (*C.{{if .IsG2}}g2_{{end}}projective_t)(unsafe.Pointer(&p2)) + __ret := C.{{.Curve}}{{if .IsG2}}G2{{end}}Eq(cP, cP2) + return __ret == (C._Bool)(true) +} + +func (p *{{if .IsG2}}G2{{end}}Projective) ProjectiveToAffine() {{if .IsG2}}G2{{end}}Affine { + var a {{if .IsG2}}G2{{end}}Affine + + cA := (*C.{{if .IsG2}}g2_{{end}}affine_t)(unsafe.Pointer(&a)) + cP := (*C.{{if .IsG2}}g2_{{end}}projective_t)(unsafe.Pointer(&p)) + C.{{.Curve}}{{if .IsG2}}G2{{end}}ToAffine(cP, cA) + return a +} + +func {{if .IsG2}}G2{{end}}GenerateProjectivePoints(size int) core.HostSlice[{{if .IsG2}}G2{{end}}Projective] { + points := make([]{{if .IsG2}}G2{{end}}Projective, size) + for i := range points { + points[i] = {{if .IsG2}}G2{{end}}Projective{} + } + + pointsSlice := core.HostSliceFromElements[{{if .IsG2}}G2{{end}}Projective](points) + pPoints := (*C.{{if .IsG2}}g2_{{end}}projective_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.{{.Curve}}{{if .IsG2}}G2{{end}}GenerateProjectivePoints(pPoints, cSize) + + return pointsSlice +} +{{end}} +type {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine struct { + X, Y {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field +} + +func (a {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine) Size() int { + return a.X.Size() * 2 +} + +func (a {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine) AsPointer() *uint32 { + return a.X.AsPointer() +} + +func (a *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine) Zero() {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine { + a.X.Zero() + a.Y.Zero() + + return *a +} + +func (a *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine) FromLimbs(x, y []uint32) {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine { + a.X.FromLimbs(x) + a.Y.FromLimbs(y) + + return *a +} + +func (a {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine) ToProjective() {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective { + var z {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field + + return {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective{ + X: a.X, + Y: a.Y, + Z: z.One(), + } +} +{{if not .IsMock}} +func {{if .IsG2}}G2{{end}}AffineFromProjective(p *{{if .IsG2}}G2{{end}}Projective) {{if .IsG2}}G2{{end}}Affine { + return p.ProjectiveToAffine() +} + +func {{if .IsG2}}G2{{end}}GenerateAffinePoints(size int) core.HostSlice[{{if .IsG2}}G2{{end}}Affine] { + points := make([]{{if .IsG2}}G2{{end}}Affine, size) + for i := range points { + points[i] = {{if .IsG2}}G2{{end}}Affine{} + } + + pointsSlice := core.HostSliceFromElements[{{if .IsG2}}G2{{end}}Affine](points) + cPoints := (*C.{{if .IsG2}}g2_{{end}}affine_t)(unsafe.Pointer(&pointsSlice[0])) + cSize := (C.int)(size) + C.{{.Curve}}{{if .IsG2}}G2{{end}}GenerateAffinePoints(cPoints, cSize) + + return pointsSlice +} + +func convert{{if .IsG2}}G2{{end}}AffinePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.{{if .IsG2}}g2_{{end}}affine_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.{{.Curve}}{{if .IsG2}}G2{{end}}AffineConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func {{if .IsG2}}G2{{end}}AffineToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convert{{if .IsG2}}G2{{end}}AffinePointsMontgomery(points, true) +} + +func {{if .IsG2}}G2{{end}}AffineFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convert{{if .IsG2}}G2{{end}}AffinePointsMontgomery(points, false) +} + +func convert{{if .IsG2}}G2{{end}}ProjectivePointsMontgomery(points *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.{{if .IsG2}}g2_{{end}}projective_t)(points.AsPointer()) + cSize := (C.size_t)(points.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.{{.Curve}}{{if .IsG2}}G2{{end}}ProjectiveConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func {{if .IsG2}}G2{{end}}ProjectiveToMontgomery(points *core.DeviceSlice) cr.CudaError { + return convert{{if .IsG2}}G2{{end}}ProjectivePointsMontgomery(points, true) +} + +func {{if .IsG2}}G2{{end}}ProjectiveFromMontgomery(points *core.DeviceSlice) cr.CudaError { + return convert{{if .IsG2}}G2{{end}}ProjectivePointsMontgomery(points, false) +} +{{end}} \ No newline at end of file diff --git a/wrappers/golang/internal/generator/templates/curve_test.go.tmpl b/wrappers/golang/internal/generator/templates/curve_test.go.tmpl new file mode 100644 index 000000000..2be5ffe7c --- /dev/null +++ b/wrappers/golang/internal/generator/templates/curve_test.go.tmpl @@ -0,0 +1,105 @@ +{{if .IsG2 -}} +//go:build g2 + +{{end -}} +package {{.PackageName}} + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func Test{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}AffineZero(t *testing.T) { + var fieldZero = {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field{} + + var affineZero {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine + assert.Equal(t, affineZero.X, fieldZero) + assert.Equal(t, affineZero.Y, fieldZero) + + x := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + y := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + var affine {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine + affine.FromLimbs(x, y) + + affine.Zero() + assert.Equal(t, affine.X, fieldZero) + assert.Equal(t, affine.Y, fieldZero) +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}AffineFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + + var affine {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine + affine.FromLimbs(randLimbs, randLimbs2) + + assert.ElementsMatch(t, randLimbs, affine.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, affine.Y.GetLimbs()) +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}AffineToProjective(t *testing.T) { + randLimbs := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + var fieldOne {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field + fieldOne.One() + + var expected {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine + affine.FromLimbs(randLimbs, randLimbs2) + + projectivePoint := affine.ToProjective() + assert.Equal(t, expected, projectivePoint) +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}ProjectiveZero(t *testing.T) { + var projectiveZero {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective + projectiveZero.Zero() + var fieldZero = {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field{} + var fieldOne {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field + fieldOne.One() + + assert.Equal(t, projectiveZero.X, fieldZero) + assert.Equal(t, projectiveZero.Y, fieldOne) + assert.Equal(t, projectiveZero.Z, fieldZero) + + randLimbs := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + var projective {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective + projective.FromLimbs(randLimbs, randLimbs, randLimbs) + + projective.Zero() + assert.Equal(t, projective.X, fieldZero) + assert.Equal(t, projective.Y, fieldOne) + assert.Equal(t, projective.Z, fieldZero) +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}ProjectiveFromLimbs(t *testing.T) { + randLimbs := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + randLimbs3 := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + + var projective {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective + projective.FromLimbs(randLimbs, randLimbs2, randLimbs3) + + assert.ElementsMatch(t, randLimbs, projective.X.GetLimbs()) + assert.ElementsMatch(t, randLimbs2, projective.Y.GetLimbs()) + assert.ElementsMatch(t, randLimbs3, projective.Z.GetLimbs()) +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}ProjectiveFromAffine(t *testing.T) { + randLimbs := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + randLimbs2 := generateRandomLimb(int({{if .IsG2}}G2_{{end}}BASE_LIMBS)) + var fieldOne {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}Base{{end}}Field + fieldOne.One() + + var expected {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective + expected.FromLimbs(randLimbs, randLimbs2, fieldOne.limbs[:]) + + var affine {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Affine + affine.FromLimbs(randLimbs, randLimbs2) + + var projectivePoint {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{end}}Projective + projectivePoint.FromAffine(affine) + assert.Equal(t, expected, projectivePoint) +} diff --git a/wrappers/golang/internal/generator/templates/field.go.tmpl b/wrappers/golang/internal/generator/templates/field.go.tmpl new file mode 100644 index 000000000..b6fdfb1af --- /dev/null +++ b/wrappers/golang/internal/generator/templates/field.go.tmpl @@ -0,0 +1,90 @@ +{{if .IsG2 -}} +//go:build g2 + +{{end -}} +package {{.PackageName}} +{{if .IsScalar}} +{{- template "scalar_field_c_imports" . -}} +{{end}} +import ( + "encoding/binary" + "fmt" + {{- if .IsScalar}} + {{- template "scalar_field_go_imports" -}} + {{end}} +) + +const ( + {{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS int8 = {{if .IsScalar}}{{.ScalarLimbsNum}}{{else}}{{if .IsG2}}{{.G2BaseLimbsNum}}{{else}}{{.BaseLimbsNum}}{{end}}{{end}} +) + +type {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field struct { + limbs [{{- if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS]uint32 +} + +func (f {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) Len() int { + return int({{- if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS) +} + +func (f {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) Size() int { + return int({{- if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS * 4) +} + +func (f {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) GetLimbs() []uint32 { + return f.limbs[:] +} + +func (f {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) AsPointer() *uint32 { + return &f.limbs[0] +} + +func (f *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) FromLimbs(limbs []uint32) {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field { + if len(limbs) != f.Len() { + panic("Called FromLimbs with limbs of different length than field") + } + for i := range f.limbs { + f.limbs[i] = limbs[i] + } + + return *f +} + +func (f *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) Zero() {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field { + for i := range f.limbs { + f.limbs[i] = 0 + } + + return *f +} + +func (f *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) One() {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field { + for i := range f.limbs { + f.limbs[i] = 0 + } + f.limbs[0] = 1 + + return *f +} + +func (f *{{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) FromBytesLittleEndian(bytes []byte) {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field { + if len(bytes)/4 != f.Len() { + panic(fmt.Sprintf("Called FromBytesLittleEndian with incorrect bytes length; expected %d - got %d", f.Len()*4, len(bytes))) + } + + for i := range f.limbs { + f.limbs[i] = binary.LittleEndian.Uint32(bytes[i*4 : i*4+4]) + } + + return *f +} + +func (f {{if .IsMock}}Mock{{else}}{{if .IsG2}}G2{{end}}{{- if .IsScalar}}Scalar{{else}}Base{{end}}{{end}}Field) ToBytesLittleEndian() []byte { + bytes := make([]byte, f.Len()*4) + for i, v := range f.limbs { + binary.LittleEndian.PutUint32(bytes[i*4:], v) + } + + return bytes +} +{{- if .IsScalar}} +{{template "scalar_field_funcs" . }}{{end}} diff --git a/wrappers/golang/internal/generator/templates/field_test.go.tmpl b/wrappers/golang/internal/generator/templates/field_test.go.tmpl new file mode 100644 index 000000000..6fefdf517 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/field_test.go.tmpl @@ -0,0 +1,91 @@ +{{if .IsG2 -}} +//go:build g2 + +{{end -}} +package {{.PackageName}} + +import ( + {{- if .IsScalar}} + {{- template "scalar_field_tests_imports" . -}}{{end}} + "github.com/stretchr/testify/assert" + "testing" +) + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldFromLimbs(t *testing.T) { + emptyField := {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field{} + randLimbs := generateRandomLimb(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + assert.ElementsMatch(t, randLimbs, emptyField.limbs, "Limbs do not match; there was an issue with setting the {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field's limbs") + randLimbs[0] = 100 + assert.NotEqual(t, randLimbs, emptyField.limbs) +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldGetLimbs(t *testing.T) { + emptyField := {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field{} + randLimbs := generateRandomLimb(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.ElementsMatch(t, randLimbs, emptyField.GetLimbs(), "Limbs do not match; there was an issue with setting the {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field's limbs") +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldOne(t *testing.T) { + var emptyField {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field + emptyField.One() + limbOne := generateLimbOne(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "Empty field to field one did not work") + + randLimbs := generateRandomLimb(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.One() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbOne, "{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field with limbs to field one did not work") +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldZero(t *testing.T) { + var emptyField {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field + emptyField.Zero() + limbsZero := make([]uint32, {{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS) + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "Empty field to field zero failed") + + randLimbs := generateRandomLimb(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + emptyField.Zero() + assert.ElementsMatch(t, emptyField.GetLimbs(), limbsZero, "{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field with limbs to field zero failed") +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldSize(t *testing.T) { + var emptyField {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field + randLimbs := generateRandomLimb(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, len(randLimbs)*4, emptyField.Size(), "Size returned an incorrect value of bytes") +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldAsPointer(t *testing.T) { + var emptyField {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field + randLimbs := generateRandomLimb(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + emptyField.FromLimbs(randLimbs[:]) + + assert.Equal(t, randLimbs[0], *emptyField.AsPointer(), "AsPointer returned pointer to incorrect value") +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldFromBytes(t *testing.T) { + var emptyField {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field + bytes, expected := generateBytesArray(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + + emptyField.FromBytesLittleEndian(bytes) + + assert.ElementsMatch(t, emptyField.GetLimbs(), expected, "FromBytes returned incorrect values") +} + +func Test{{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}FieldToBytes(t *testing.T) { + var emptyField {{if .IsMock}}Mock{{else}}{{if .IsScalar}}Scalar{{else}}{{if .IsG2}}G2{{end}}Base{{end}}{{end}}Field + expected, limbs := generateBytesArray(int({{if .IsScalar}}SCALAR{{else}}{{if .IsG2}}G2_{{end}}BASE{{end}}_LIMBS)) + emptyField.FromLimbs(limbs) + + assert.ElementsMatch(t, emptyField.ToBytesLittleEndian(), expected, "ToBytes returned incorrect values") +} +{{if .IsScalar}} +{{- template "scalar_field_tests" .}} +{{end}} \ No newline at end of file diff --git a/wrappers/golang/internal/generator/templates/helpers_test.go.tmpl b/wrappers/golang/internal/generator/templates/helpers_test.go.tmpl new file mode 100644 index 000000000..a469e7b65 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/helpers_test.go.tmpl @@ -0,0 +1,31 @@ +package {{.PackageName}} + +import ( + "math/rand" +) + +func generateRandomLimb(size int) []uint32 { + limbs := make([]uint32, size) + for i := range limbs { + limbs[i] = rand.Uint32() + } + return limbs +} + +func generateLimbOne(size int) []uint32 { + limbs := make([]uint32, size) + limbs[0] = 1 + return limbs +} + +func generateBytesArray(size int) ([]byte, []uint32) { + baseBytes := []byte{1, 2, 3, 4} + var bytes []byte + var limbs []uint32 + for i := 0; i < size; i++ { + bytes = append(bytes, baseBytes...) + limbs = append(limbs, 67305985) + } + + return bytes, limbs +} diff --git a/wrappers/golang/internal/generator/templates/include/curve.h.tmpl b/wrappers/golang/internal/generator/templates/include/curve.h.tmpl new file mode 100644 index 000000000..76ede8b74 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/include/curve.h.tmpl @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _{{toUpper .Curve}}_CURVE_H +#define _{{toUpper .Curve}}_CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool {{.Curve}}Eq(projective_t* point1, projective_t* point2); +void {{.Curve}}ToAffine(projective_t* point, affine_t* point_out); +void {{.Curve}}GenerateProjectivePoints(projective_t* points, int size); +void {{.Curve}}GenerateAffinePoints(affine_t* points, int size); +cudaError_t {{.Curve}}AffineConvertMontgomery(affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t {{.Curve}}ProjectiveConvertMontgomery(projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/internal/generator/templates/include/g2_curve.h.tmpl b/wrappers/golang/internal/generator/templates/include/g2_curve.h.tmpl new file mode 100644 index 000000000..dfe1dcad6 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/include/g2_curve.h.tmpl @@ -0,0 +1,23 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _{{toUpper .Curve}}_G2CURVE_H +#define _{{toUpper .Curve}}_G2CURVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +bool {{.Curve}}G2Eq(g2_projective_t* point1, g2_projective_t* point2); +void {{.Curve}}G2ToAffine(g2_projective_t* point, g2_affine_t* point_out); +void {{.Curve}}G2GenerateProjectivePoints(g2_projective_t* points, int size); +void {{.Curve}}G2GenerateAffinePoints(g2_affine_t* points, int size); +cudaError_t {{.Curve}}G2AffineConvertMontgomery(g2_affine_t* points, size_t n, bool is_into, DeviceContext* ctx); +cudaError_t {{.Curve}}G2ProjectiveConvertMontgomery(g2_projective_t* points, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/internal/generator/templates/include/g2_msm.h.tmpl b/wrappers/golang/internal/generator/templates/include/g2_msm.h.tmpl new file mode 100644 index 000000000..3d42a1ac2 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/include/g2_msm.h.tmpl @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _{{toUpper .Curve}}_G2MSM_H +#define _{{toUpper .Curve}}_G2MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t {{.Curve}}G2MSMCuda(scalar_t* scalars, g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/internal/generator/templates/include/msm.h.tmpl b/wrappers/golang/internal/generator/templates/include/msm.h.tmpl new file mode 100644 index 000000000..82acaf8fa --- /dev/null +++ b/wrappers/golang/internal/generator/templates/include/msm.h.tmpl @@ -0,0 +1,17 @@ +#include +#include "../../include/types.h" + +#ifndef _{{toUpper .Curve}}_MSM_H +#define _{{toUpper .Curve}}_MSM_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t {{.Curve}}MSMCuda(scalar_t* scalars, affine_t* points, int count, MSMConfig* config, projective_t* out); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/internal/generator/templates/include/ntt.h.tmpl b/wrappers/golang/internal/generator/templates/include/ntt.h.tmpl new file mode 100644 index 000000000..df915f06f --- /dev/null +++ b/wrappers/golang/internal/generator/templates/include/ntt.h.tmpl @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _{{toUpper .Curve}}_NTT_H +#define _{{toUpper .Curve}}_NTT_H + +#ifdef __cplusplus +extern "C" { +#endif + +cudaError_t {{.Curve}}NTTCuda(scalar_t* input, int size, int dir, NTTConfig* config, scalar_t* output); +cudaError_t {{.Curve}}InitializeDomain(scalar_t* primitive_root, DeviceContext* ctx, bool fast_twiddles); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/internal/generator/templates/include/scalar_field.h.tmpl b/wrappers/golang/internal/generator/templates/include/scalar_field.h.tmpl new file mode 100644 index 000000000..5cee5322d --- /dev/null +++ b/wrappers/golang/internal/generator/templates/include/scalar_field.h.tmpl @@ -0,0 +1,19 @@ +#include +#include "../../include/types.h" +#include + +#ifndef _{{toUpper .Curve}}_FIELD_H +#define _{{toUpper .Curve}}_FIELD_H + +#ifdef __cplusplus +extern "C" { +#endif + +void {{.Curve}}GenerateScalars(scalar_t* scalars, int size); +cudaError_t {{.Curve}}ScalarConvertMontgomery(scalar_t* d_inout, size_t n, bool is_into, DeviceContext* ctx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/internal/generator/templates/include/vec_ops.h.tmpl b/wrappers/golang/internal/generator/templates/include/vec_ops.h.tmpl new file mode 100644 index 000000000..36289da0a --- /dev/null +++ b/wrappers/golang/internal/generator/templates/include/vec_ops.h.tmpl @@ -0,0 +1,53 @@ +#include +#include +#include +// ve_mod_mult.h + +#ifndef _BN254_VEC_MULT_H +#define _BN254_VEC_MULT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + cudaStream_t stream; /**< Stream to use. Default value: 0. */ + int device_id; /**< Index of the currently used GPU. Default value: 0. */ + cudaMemPool_t mempool; /**< Mempool to use. Default value: 0. */ +} DeviceContext; + +typedef struct BN254_scalar_t BN254_scalar_t; + +int bn254AddCuda( + BN254_scalar_t* vec_a, + BN254_scalar_t* vec_b, + int n, + bool is_on_device, + DeviceContext ctx, + BN254_scalar_t* result +); + +int bn254SubCuda( + BN254_scalar_t* vec_a, + BN254_scalar_t* vec_b, + int n, + bool is_on_device, + DeviceContext ctx, + BN254_scalar_t* result +); + +int bn254MulCuda( + BN254_scalar_t* vec_a, + BN254_scalar_t* vec_b, + int n, + bool is_on_device, + bool is_montgomery, + DeviceContext ctx, + BN254_scalar_t* result +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/wrappers/golang/internal/generator/templates/main.go.tmpl b/wrappers/golang/internal/generator/templates/main.go.tmpl new file mode 100644 index 000000000..0645bb250 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/main.go.tmpl @@ -0,0 +1,4 @@ +package {{.PackageName}} + +// #cgo LDFLAGS: -L${SRCDIR}/../../../../icicle/build -lingo_{{.Curve}} -lstdc++ -lm +import "C" diff --git a/wrappers/golang/internal/generator/templates/msm.go.tmpl b/wrappers/golang/internal/generator/templates/msm.go.tmpl new file mode 100644 index 000000000..f86f4b02b --- /dev/null +++ b/wrappers/golang/internal/generator/templates/msm.go.tmpl @@ -0,0 +1,53 @@ +{{if .IsG2 -}} +//go:build g2 + +{{end -}} +package {{.PackageName}} + +// #cgo CFLAGS: -I./include/ +// #include "{{if .IsG2 -}}g2_{{end}}msm.h" +import "C" + +import ( + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +) + +func {{if .IsG2}}G2{{end}}GetDefaultMSMConfig() core.MSMConfig { + return core.GetDefaultMSMConfig() +} + +func {{if .IsG2}}G2{{end}}Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *core.MSMConfig, results core.HostOrDeviceSlice) cr.CudaError { + core.MsmCheck(scalars, points, cfg, results) + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + + var pointsPointer unsafe.Pointer + if points.IsOnDevice() { + pointsPointer = points.(core.DeviceSlice).AsPointer() + } else { + pointsPointer = unsafe.Pointer(&points.(core.HostSlice[{{if .IsG2}}G2{{end}}Affine])[0]) + } + cPoints := (*C.{{if .IsG2}}g2_{{end}}affine_t)(pointsPointer) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[{{if .IsG2}}G2{{end}}Projective])[0]) + } + cResults := (*C.{{if .IsG2}}g2_{{end}}projective_t)(resultsPointer) + + cSize := (C.int)(scalars.Len() / results.Len()) + cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg)) + + __ret := C.{{.Curve}}{{if .IsG2}}G2{{end}}MSMCuda(cScalars, cPoints, cSize, cCfg, cResults) + err := (cr.CudaError)(__ret) + return err +} diff --git a/wrappers/golang/internal/generator/templates/msm_test.go.tmpl b/wrappers/golang/internal/generator/templates/msm_test.go.tmpl new file mode 100644 index 000000000..9c3bbd200 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/msm_test.go.tmpl @@ -0,0 +1,187 @@ +{{if .IsG2 -}} +//go:build g2 + +{{end -}} +package {{.PackageName}} + +import ( + "github.com/stretchr/testify/assert" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fp" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr" +) +{{$isBW6 := eq .Curve "bw6_761"}}{{$isG1 := not .IsG2}}{{if or $isBW6 $isG1}} +func projectiveToGnarkAffine{{if and $isBW6 .IsG2}}G2{{end}}(p {{if and $isBW6 .IsG2}}G2{{end}}Projective) {{toPackage .GnarkImport}}.{{if and $isBW6 .IsG2}}G2{{else}}G1{{end}}Affine { + px, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.X).ToBytesLittleEndian())) + py, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Y).ToBytesLittleEndian())) + pz, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)((&p.Z).ToBytesLittleEndian())) + + zInv := new(fp.Element) + x := new(fp.Element) + y := new(fp.Element) + + zInv.Inverse(&pz) + + x.Mul(&px, zInv) + y.Mul(&py, zInv) + + return {{toPackage .GnarkImport}}.{{if and $isBW6 .IsG2}}G2{{else}}G1{{end}}Affine{X: *x, Y: *y} +} +{{end}} +{{- $isNotBW6 := ne .Curve "bw6_761"}}{{if and $isNotBW6 .IsG2 }} +func projectiveToGnarkAffineG2(p G2Projective) {{toPackage .GnarkImport}}.G2Affine { + pxBytes := p.X.ToBytesLittleEndian() + pxA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[:fp.Bytes])) + pxA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pxBytes[fp.Bytes:])) + x := {{toPackage .GnarkImport}}.E2{ + A0: pxA0, + A1: pxA1, + } + + pyBytes := p.Y.ToBytesLittleEndian() + pyA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[:fp.Bytes])) + pyA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pyBytes[fp.Bytes:])) + y := {{toPackage .GnarkImport}}.E2{ + A0: pyA0, + A1: pyA1, + } + + pzBytes := p.Z.ToBytesLittleEndian() + pzA0, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[:fp.Bytes])) + pzA1, _ := fp.LittleEndian.Element((*[fp.Bytes]byte)(pzBytes[fp.Bytes:])) + z := {{toPackage .GnarkImport}}.E2{ + A0: pzA0, + A1: pzA1, + } + + var zSquared {{toPackage .GnarkImport}}.E2 + zSquared.Mul(&z, &z) + + var X {{toPackage .GnarkImport}}.E2 + X.Mul(&x, &z) + + var Y {{toPackage .GnarkImport}}.E2 + Y.Mul(&y, &zSquared) + + g2Jac := {{toPackage .GnarkImport}}.G2Jac{ + X: X, + Y: Y, + Z: z, + } + + var g2Affine {{toPackage .GnarkImport}}.G2Affine + return *g2Affine.FromJacobian(&g2Jac) +} +{{end}} +func testAgainstGnarkCryptoMsm{{if .IsG2}}G2{{end}}(scalars core.HostSlice[ScalarField], points core.HostSlice[{{if .IsG2}}G2{{end}}Affine], out {{if .IsG2}}G2{{end}}Projective) bool { + scalarsFr := make([]fr.Element, len(scalars)) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + pointsFp := make([]{{toPackage .GnarkImport}}.{{if .IsG2}}G2{{else}}G1{{end}}Affine, len(points)) + for i, v := range points { + pointsFp[i] = projectiveToGnarkAffine{{if .IsG2}}G2{{end}}(v.ToProjective()) + } + var msmRes {{toPackage .GnarkImport}}.{{if .IsG2}}G2{{else}}G1{{end}}Jac + msmRes.MultiExp(pointsFp, scalarsFr, ecc.MultiExpConfig{}) + + var icicleResAsJac {{toPackage .GnarkImport}}.{{if .IsG2}}G2{{else}}G1{{end}}Jac + proj := projectiveToGnarkAffine{{if .IsG2}}G2{{end}}(out) + icicleResAsJac.FromAffine(&proj) + + return msmRes.Equal(&icicleResAsJac) +} + +func TestMSM{{if .IsG2}}G2{{end}}(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + points := {{if .IsG2}}G2{{end}}GenerateAffinePoints(size) + + stream, _ := cr.CreateStream() + var p {{if .IsG2}}G2{{end}}Projective + var out core.DeviceSlice + _, e := out.MallocAsync(p.Size(), p.Size(), stream) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + cfg.Ctx.Stream = &stream + e = {{if .IsG2}}G2{{end}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if .IsG2}}G2{{end}}Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{if .IsG2}}G2{{end}}(scalars, points, outHost[0])) + } +} + +func TestMSM{{if .IsG2}}G2{{end}}Batch(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{10, 16} { + for _, batchSize := range []int{1, 3, 16} { + size := 1 << power + totalSize := size * batchSize + scalars := GenerateScalars(totalSize) + points := {{if .IsG2}}G2{{end}}GenerateAffinePoints(totalSize) + + var p {{if .IsG2}}G2{{end}}Projective + var out core.DeviceSlice + _, e := out.Malloc(batchSize*p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = {{if .IsG2}}G2{{end}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if .IsG2}}G2{{end}}Projective], batchSize) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + for i := 0; i < batchSize; i++ { + scalarsSlice := scalars[i*size : (i+1)*size] + pointsSlice := points[i*size : (i+1)*size] + out := outHost[i] + assert.True(t, testAgainstGnarkCryptoMsm{{if .IsG2}}G2{{end}}(scalarsSlice, pointsSlice, out)) + } + } + } +} + +func TestMSM{{if .IsG2}}G2{{end}}SkewedDistribution(t *testing.T) { + cfg := GetDefaultMSMConfig() + for _, power := range []int{2, 3, 4, 5, 6, 7, 8, 10, 18} { + size := 1 << power + + scalars := GenerateScalars(size) + for i := size / 4; i < size; i++ { + scalars[i].One() + } + points := {{if .IsG2}}G2{{end}}GenerateAffinePoints(size) + for i := 0; i < size/4; i++ { + points[i].Zero() + } + + var p {{if .IsG2}}G2{{end}}Projective + var out core.DeviceSlice + _, e := out.Malloc(p.Size(), p.Size()) + assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed") + + e = {{if .IsG2}}G2{{end}}Msm(scalars, points, &cfg, out) + assert.Equal(t, e, cr.CudaSuccess, "Msm failed") + outHost := make(core.HostSlice[{{if .IsG2}}G2{{end}}Projective], 1) + outHost.CopyFromDevice(&out) + out.Free() + + // Check with gnark-crypto + assert.True(t, testAgainstGnarkCryptoMsm{{if .IsG2}}G2{{end}}(scalars, points, outHost[0])) + } +} diff --git a/wrappers/golang/internal/generator/templates/ntt.go.tmpl b/wrappers/golang/internal/generator/templates/ntt.go.tmpl new file mode 100644 index 000000000..12cd11f24 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/ntt.go.tmpl @@ -0,0 +1,59 @@ +package {{.PackageName}} + +// #cgo CFLAGS: -I./include/ +// #include "ntt.h" +import "C" + +import ( + "unsafe" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" +) + +func GetDefaultNttConfig() core.NTTConfig[[SCALAR_LIMBS]uint32] { + cosetGenField := ScalarField{} + cosetGenField.One() + var cosetGen [SCALAR_LIMBS]uint32 + for i, v := range cosetGenField.GetLimbs() { + cosetGen[i] = v + } + + return core.GetDefaultNTTConfig(cosetGen) +} + +func Ntt[T any](scalars core.HostOrDeviceSlice, dir core.NTTDir, cfg *core.NTTConfig[T], results core.HostOrDeviceSlice) core.IcicleError { + core.NttCheck[T](scalars, cfg, results) + + var scalarsPointer unsafe.Pointer + if scalars.IsOnDevice() { + scalarsPointer = scalars.(core.DeviceSlice).AsPointer() + } else { + scalarsPointer = unsafe.Pointer(&scalars.(core.HostSlice[ScalarField])[0]) + } + cScalars := (*C.scalar_t)(scalarsPointer) + cSize := (C.int)(scalars.Len() / int(cfg.BatchSize)) + cDir := (C.int)(dir) + cCfg := (*C.NTTConfig)(unsafe.Pointer(cfg)) + + var resultsPointer unsafe.Pointer + if results.IsOnDevice() { + resultsPointer = results.(core.DeviceSlice).AsPointer() + } else { + resultsPointer = unsafe.Pointer(&results.(core.HostSlice[ScalarField])[0]) + } + cResults := (*C.scalar_t)(resultsPointer) + + __ret := C.{{.Curve}}NTTCuda(cScalars, cSize, cDir, cCfg, cResults) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} + +func InitDomain(primitiveRoot ScalarField, ctx cr.DeviceContext, fastTwiddles bool) core.IcicleError { + cPrimitiveRoot := (*C.scalar_t)(unsafe.Pointer(primitiveRoot.AsPointer())) + cCtx := (*C.DeviceContext)(unsafe.Pointer(&ctx)) + cFastTwiddles := (C._Bool)(fastTwiddles) + __ret := C.{{.Curve}}InitializeDomain(cPrimitiveRoot, cCtx, cFastTwiddles) + err := (cr.CudaError)(__ret) + return core.FromCudaError(err) +} diff --git a/wrappers/golang/internal/generator/templates/ntt_test.go.tmpl b/wrappers/golang/internal/generator/templates/ntt_test.go.tmpl new file mode 100644 index 000000000..03e3f5c35 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/ntt_test.go.tmpl @@ -0,0 +1,239 @@ +package {{.PackageName}} + +import ( + "reflect" + "testing" + + "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr" + "github.com/consensys/gnark-crypto/ecc/{{.GnarkImport}}/fr/fft" + "github.com/stretchr/testify/assert" +) + +const ( + largestTestSize = 17 +) + +func initDomain[T any](largestTestSize int, cfg core.NTTConfig[T]) { + rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) + rou := rouMont.Bits() + rouIcicle := ScalarField{} + limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + + rouIcicle.FromLimbs(limbs) + InitDomain(rouIcicle, cfg.Ctx, false) +} + +func testAgainstGnarkCryptoNtt(size int, scalars core.HostSlice[ScalarField], output core.HostSlice[ScalarField], order core.Ordering, direction core.NTTDir) bool { + domainWithPrecompute := fft.NewDomain(uint64(size)) + scalarsFr := make([]fr.Element, size) + for i, v := range scalars { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + outputAsFr := make([]fr.Element, size) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + // DIT + BitReverse == Ordering.kRR + // DIT == Ordering.kRN + // DIF + BitReverse == Ordering.kNN + // DIF == Ordering.kNR + var decimation fft.Decimation + if order == core.KRN || order == core.KRR { + decimation = fft.DIT + } else { + decimation = fft.DIF + } + + if direction == core.KForward { + domainWithPrecompute.FFT(scalarsFr, decimation) + } else { + domainWithPrecompute.FFTInverse(scalarsFr, decimation) + } + + if order == core.KNN || order == core.KRR { + fft.BitReverse(scalarsFr) + } + return reflect.DeepEqual(scalarsFr, outputAsFr) +} + +func TestNTTGetDefaultConfig(t *testing.T) { + actual := GetDefaultNttConfig() + expected := generateLimbOne(int(SCALAR_LIMBS)) + assert.Equal(t, expected, actual.CosetGen[:]) + + cosetGenField := ScalarField{} + cosetGenField.One() + assert.ElementsMatch(t, cosetGenField.GetLimbs(), actual.CosetGen) +} + +func TestInitDomain(t *testing.T) { + cfg := GetDefaultNttConfig() + assert.NotPanics(t, func() { initDomain(largestTestSize, cfg) }) +} + +func TestNtt(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{4, largestTestSize} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + cfg.Ordering = v + + // run ntt + output := make(core.HostSlice[ScalarField], testSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, core.KForward)) + } + } +} + +func TestNttDeviceAsync(t *testing.T) { + cfg := GetDefaultNttConfig() + scalars := GenerateScalars(1 << largestTestSize) + + for _, size := range []int{1, 10, largestTestSize} { + for _, direction := range []core.NTTDir{core.KForward, core.KInverse} { + for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { + testSize := 1 << size + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:testSize]) + + stream, _ := cr.CreateStream() + + cfg.Ordering = v + cfg.IsAsync = true + cfg.Ctx.Stream = &stream + + var deviceInput core.DeviceSlice + scalarsCopy.CopyToDeviceAsync(&deviceInput, stream, true) + var deviceOutput core.DeviceSlice + deviceOutput.MallocAsync(testSize*scalarsCopy.SizeOfElement(), scalarsCopy.SizeOfElement(), stream) + + // run ntt + Ntt(deviceInput, direction, &cfg, deviceOutput) + output := make(core.HostSlice[ScalarField], testSize) + output.CopyFromDeviceAsync(&deviceOutput, stream) + + cr.SynchronizeStream(&stream) + + // Compare with gnark-crypto + assert.True(t, testAgainstGnarkCryptoNtt(testSize, scalarsCopy, output, v, direction)) + } + } + } +} + +func TestNttBatch(t *testing.T) { + cfg := GetDefaultNttConfig() + largestBatchSize := 100 + scalars := GenerateScalars(1 << largestTestSize * largestBatchSize) + + for _, size := range []int{4, largestTestSize} { + for _, batchSize := range []int{1, 16, largestBatchSize} { + testSize := 1 << size + totalSize := testSize * batchSize + + scalarsCopy := core.HostSliceFromElements[ScalarField](scalars[:totalSize]) + + cfg.Ordering = core.KNN + cfg.BatchSize = int32(batchSize) + // run ntt + output := make(core.HostSlice[ScalarField], totalSize) + Ntt(scalarsCopy, core.KForward, &cfg, output) + + // Compare with gnark-crypto + domainWithPrecompute := fft.NewDomain(uint64(testSize)) + outputAsFr := make([]fr.Element, totalSize) + for i, v := range output { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + outputAsFr[i] = slice64 + } + + for i := 0; i < batchSize; i++ { + scalarsFr := make([]fr.Element, testSize) + for i, v := range scalarsCopy[i*testSize : (i+1)*testSize] { + slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) + scalarsFr[i] = slice64 + } + + domainWithPrecompute.FFT(scalarsFr, fft.DIF) + fft.BitReverse(scalarsFr) + if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr[i*testSize:(i+1)*testSize])) { + t.FailNow() + } + } + } + } +} + +// func TestNttArbitraryCoset(t *testing.T) { +// for _, size := range []int{20} { +// for _, v := range [4]core.Ordering{core.KNN, core.KNR, core.KRN, core.KRR} { +// testSize := 1 << size +// scalars := GenerateScalars(testSize) + +// cfg := GetDefaultNttConfig() + +// var scalarsCopy core.HostSlice[ScalarField] +// for _, v := range scalars { +// var scalar ScalarField +// scalarsCopy = append(scalarsCopy, scalar.FromLimbs(v.GetLimbs())) +// } + +// // init domain +// rouMont, _ := fft.Generator(1 << 20) +// rou := rouMont.Bits() +// rouIcicle := ScalarField{} +// limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) + +// rouIcicle.FromLimbs(limbs) +// InitDomain(rouIcicle, cfg.Ctx) +// cfg.Ordering = v + +// // run ntt +// output := make(core.HostSlice[ScalarField], testSize) +// Ntt(scalars, core.KForward, &cfg, output) + +// // Compare with gnark-crypto +// domainWithPrecompute := fft.NewDomain(uint64(testSize)) +// scalarsFr := make([]fr.Element, testSize) +// for i, v := range scalarsCopy { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// scalarsFr[i] = slice64 +// } +// outputAsFr := make([]fr.Element, testSize) +// for i, v := range output { +// slice64, _ := fr.LittleEndian.Element((*[fr.Bytes]byte)(v.ToBytesLittleEndian())) +// outputAsFr[i] = slice64 +// } + +// // DIT + BitReverse == Ordering.kRR +// // DIT == Ordering.kRN +// // DIF + BitReverse == Ordering.kNN +// // DIF == Ordering.kNR +// var decimation fft.Decimation +// if v == core.KRN || v == core.KRR { +// decimation = fft.DIT +// } else { +// decimation = fft.DIF +// } +// domainWithPrecompute.FFT(scalarsFr, decimation, fft.OnCoset()) +// if v == core.KNN || v == core.KRR { +// fft.BitReverse(scalarsFr) +// } +// if !assert.True(t, reflect.DeepEqual(scalarsFr, outputAsFr)) { +// t.FailNow() +// } +// } +// } +// } diff --git a/wrappers/golang/internal/generator/templates/scalar_field.go.tmpl b/wrappers/golang/internal/generator/templates/scalar_field.go.tmpl new file mode 100644 index 000000000..0ed9256ab --- /dev/null +++ b/wrappers/golang/internal/generator/templates/scalar_field.go.tmpl @@ -0,0 +1,46 @@ +{{- define "scalar_field_c_imports" }} +// #cgo CFLAGS: -I./include/ +// #include "scalar_field.h" +import "C" +{{- end }} + +{{- define "scalar_field_go_imports" }} + core "github.com/ingonyama-zk/icicle/wrappers/golang/core" + cr "github.com/ingonyama-zk/icicle/wrappers/golang/cuda_runtime" + "unsafe" +{{- end }} + +{{- define "scalar_field_funcs" }} +func GenerateScalars(size int) core.HostSlice[ScalarField] { + scalars := make([]ScalarField, size) + for i := range scalars { + scalars[i] = ScalarField{} + } + + scalarSlice := core.HostSliceFromElements[ScalarField](scalars) + + cScalars := (*C.scalar_t)(unsafe.Pointer(&scalarSlice[0])) + cSize := (C.int)(size) + C.{{.Curve}}GenerateScalars(cScalars, cSize) + + return scalarSlice +} + +func convertScalarsMontgomery(scalars *core.DeviceSlice, isInto bool) cr.CudaError { + cValues := (*C.scalar_t)(scalars.AsPointer()) + cSize := (C.size_t)(scalars.Len()) + cIsInto := (C._Bool)(isInto) + defaultCtx, _ := cr.GetDefaultDeviceContext() + cCtx := (*C.DeviceContext)(unsafe.Pointer(&defaultCtx)) + __ret := C.{{.Curve}}ScalarConvertMontgomery(cValues, cSize, cIsInto, cCtx) + err := (cr.CudaError)(__ret) + return err +} + +func ToMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, true) +} + +func FromMontgomery(scalars *core.DeviceSlice) cr.CudaError { + return convertScalarsMontgomery(scalars, false) +}{{- end}} \ No newline at end of file diff --git a/wrappers/golang/internal/generator/templates/scalar_field_test.go.tmpl b/wrappers/golang/internal/generator/templates/scalar_field_test.go.tmpl new file mode 100644 index 000000000..0e9422957 --- /dev/null +++ b/wrappers/golang/internal/generator/templates/scalar_field_test.go.tmpl @@ -0,0 +1,34 @@ +{{- define "scalar_field_tests_imports"}} + "github.com/ingonyama-zk/icicle/wrappers/golang/core" +{{- end -}} +{{- define "scalar_field_tests"}} +func TestGenerateScalars(t *testing.T) { + const numScalars = 8 + scalars := GenerateScalars(numScalars) + + assert.Implements(t, (*core.HostOrDeviceSlice)(nil), &scalars) + + assert.Equal(t, numScalars, scalars.Len()) + zeroScalar := ScalarField{} + assert.NotContains(t, scalars, zeroScalar) +} + +func TestMongtomeryConversion(t *testing.T) { + size := 1 << 15 + scalars := GenerateScalars(size) + + var deviceScalars core.DeviceSlice + scalars.CopyToDevice(&deviceScalars, true) + + ToMontgomery(&deviceScalars) + + scalarsMontHost := GenerateScalars(size) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.NotEqual(t, scalars, scalarsMontHost) + + FromMontgomery(&deviceScalars) + + scalarsMontHost.CopyFromDevice(&deviceScalars) + assert.Equal(t, scalars, scalarsMontHost) +}{{end}} \ No newline at end of file diff --git a/wrappers/golang/internal/generator/templates/vec_ops.go.tmpl b/wrappers/golang/internal/generator/templates/vec_ops.go.tmpl new file mode 100644 index 000000000..e69de29bb diff --git a/wrappers/golang/internal/generator/templates/vec_ops_test.go.tmpl b/wrappers/golang/internal/generator/templates/vec_ops_test.go.tmpl new file mode 100644 index 000000000..e69de29bb diff --git a/wrappers/rust/icicle-core/src/ntt/mod.rs b/wrappers/rust/icicle-core/src/ntt/mod.rs index 9c50dc5a3..758b11e5b 100644 --- a/wrappers/rust/icicle-core/src/ntt/mod.rs +++ b/wrappers/rust/icicle-core/src/ntt/mod.rs @@ -204,7 +204,7 @@ macro_rules! impl_ntt { #[link_name = concat!($field_prefix, "InitializeDomain")] pub(crate) fn initialize_ntt_domain( - primitive_root: $field, + primitive_root: &$field, ctx: &DeviceContext, fast_twiddles_mode: bool, ) -> CudaError; @@ -231,10 +231,10 @@ macro_rules! impl_ntt { } fn initialize_domain(primitive_root: $field, ctx: &DeviceContext) -> IcicleResult<()> { - unsafe { $field_prefix_ident::initialize_ntt_domain(primitive_root, ctx, false).wrap() } + unsafe { $field_prefix_ident::initialize_ntt_domain(&primitive_root, ctx, false).wrap() } } fn initialize_domain_fast_twiddles_mode(primitive_root: $field, ctx: &DeviceContext) -> IcicleResult<()> { - unsafe { $field_prefix_ident::initialize_ntt_domain(primitive_root, ctx, true).wrap() } + unsafe { $field_prefix_ident::initialize_ntt_domain(&primitive_root, ctx, true).wrap() } } } };