From 1416a6714a59c0a1cc4944a4ff64963b8fa97039 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 20 Feb 2026 18:21:44 +0000 Subject: [PATCH] =?UTF-8?q?feat(crypto):=20Phase=202a=20scaffold=20?= =?UTF-8?q?=E2=80=94=20vendored=20C++=20and=20CMake=20build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract CryptoNote crypto sources from upstream (fa1608cf). Build as static libcryptonote.a via CMake with compat stubs for external dependencies (warnings, logging, varint, profiling). 37 upstream files, 10 compat stubs, 680KB static library. Co-Authored-By: Charon --- .gitignore | 1 + crypto/CMakeLists.txt | 71 + crypto/PROVENANCE.md | 66 + crypto/bridge.cpp | 17 + crypto/bridge.h | 20 + crypto/common/crypto_stream_operators.h | 1 + crypto/compat/auto_val_init.h | 7 + .../compat/common/crypto_stream_operators.h | 3 + crypto/compat/common/int-util.h | 258 + crypto/compat/common/pod-class.h | 22 + crypto/compat/common/varint.h | 97 + crypto/compat/config/currency_config.h | 5 + crypto/compat/currency_core/crypto_config.h | 55 + crypto/compat/epee/include/misc_log_ex.h | 39 + crypto/compat/epee/include/profile_tools.h | 7 + crypto/compat/include_base_utils.h | 3 + crypto/compat/warnings.h | 39 + crypto/currency_core/crypto_config.h | 1 + crypto/upstream/RIPEMD160.c | 269 + crypto/upstream/RIPEMD160.h | 132 + crypto/upstream/RIPEMD160_helper.cpp | 77 + crypto/upstream/RIPEMD160_helper.h | 40 + crypto/upstream/blake2-impl.h | 162 + crypto/upstream/blake2.h | 202 + crypto/upstream/blake2b-ref.c | 381 ++ crypto/upstream/clsag.cpp | 1140 +++++ crypto/upstream/clsag.h | 187 + crypto/upstream/crypto-ops-data.c | 859 ++++ crypto/upstream/crypto-ops.c | 4473 +++++++++++++++++ crypto/upstream/crypto-ops.h | 168 + crypto/upstream/crypto-sugar.cpp | 1987 ++++++++ crypto/upstream/crypto-sugar.h | 1452 ++++++ crypto/upstream/crypto.cpp | 431 ++ crypto/upstream/crypto.h | 333 ++ crypto/upstream/crypto/crypto-ops.h | 1 + crypto/upstream/eth_signature.cpp | 417 ++ crypto/upstream/eth_signature.h | 80 + crypto/upstream/generic-ops.h | 71 + crypto/upstream/hash-ops.h | 76 + crypto/upstream/hash.c | 43 + crypto/upstream/hash.h | 69 + crypto/upstream/initializer.h | 45 + crypto/upstream/keccak.c | 129 + crypto/upstream/keccak.h | 43 + crypto/upstream/msm.cpp | 36 + crypto/upstream/msm.h | 185 + crypto/upstream/one_out_of_many_proofs.cpp | 336 ++ crypto/upstream/one_out_of_many_proofs.h | 58 + crypto/upstream/random.c | 234 + crypto/upstream/random.h | 43 + crypto/upstream/range_proof_bpp.h | 741 +++ crypto/upstream/range_proof_bppe.h | 759 +++ crypto/upstream/range_proofs.cpp | 29 + crypto/upstream/range_proofs.h | 159 + crypto/upstream/zarcanum.cpp | 435 ++ crypto/upstream/zarcanum.h | 314 ++ 56 files changed, 17308 insertions(+) create mode 100644 .gitignore create mode 100644 crypto/CMakeLists.txt create mode 100644 crypto/PROVENANCE.md create mode 100644 crypto/bridge.cpp create mode 100644 crypto/bridge.h create mode 120000 crypto/common/crypto_stream_operators.h create mode 100644 crypto/compat/auto_val_init.h create mode 100644 crypto/compat/common/crypto_stream_operators.h create mode 100755 crypto/compat/common/int-util.h create mode 100755 crypto/compat/common/pod-class.h create mode 100755 crypto/compat/common/varint.h create mode 100644 crypto/compat/config/currency_config.h create mode 100755 crypto/compat/currency_core/crypto_config.h create mode 100644 crypto/compat/epee/include/misc_log_ex.h create mode 100644 crypto/compat/epee/include/profile_tools.h create mode 100644 crypto/compat/include_base_utils.h create mode 100644 crypto/compat/warnings.h create mode 120000 crypto/currency_core/crypto_config.h create mode 100755 crypto/upstream/RIPEMD160.c create mode 100755 crypto/upstream/RIPEMD160.h create mode 100755 crypto/upstream/RIPEMD160_helper.cpp create mode 100755 crypto/upstream/RIPEMD160_helper.h create mode 100755 crypto/upstream/blake2-impl.h create mode 100755 crypto/upstream/blake2.h create mode 100755 crypto/upstream/blake2b-ref.c create mode 100755 crypto/upstream/clsag.cpp create mode 100755 crypto/upstream/clsag.h create mode 100755 crypto/upstream/crypto-ops-data.c create mode 100755 crypto/upstream/crypto-ops.c create mode 100755 crypto/upstream/crypto-ops.h create mode 100755 crypto/upstream/crypto-sugar.cpp create mode 100755 crypto/upstream/crypto-sugar.h create mode 100755 crypto/upstream/crypto.cpp create mode 100755 crypto/upstream/crypto.h create mode 120000 crypto/upstream/crypto/crypto-ops.h create mode 100755 crypto/upstream/eth_signature.cpp create mode 100755 crypto/upstream/eth_signature.h create mode 100755 crypto/upstream/generic-ops.h create mode 100755 crypto/upstream/hash-ops.h create mode 100755 crypto/upstream/hash.c create mode 100755 crypto/upstream/hash.h create mode 100755 crypto/upstream/initializer.h create mode 100755 crypto/upstream/keccak.c create mode 100755 crypto/upstream/keccak.h create mode 100755 crypto/upstream/msm.cpp create mode 100755 crypto/upstream/msm.h create mode 100755 crypto/upstream/one_out_of_many_proofs.cpp create mode 100755 crypto/upstream/one_out_of_many_proofs.h create mode 100755 crypto/upstream/random.c create mode 100755 crypto/upstream/random.h create mode 100755 crypto/upstream/range_proof_bpp.h create mode 100755 crypto/upstream/range_proof_bppe.h create mode 100755 crypto/upstream/range_proofs.cpp create mode 100755 crypto/upstream/range_proofs.h create mode 100755 crypto/upstream/zarcanum.cpp create mode 100755 crypto/upstream/zarcanum.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..371f359 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +crypto/build/ diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt new file mode 100644 index 0000000..82cece4 --- /dev/null +++ b/crypto/CMakeLists.txt @@ -0,0 +1,71 @@ +# SPDX-Licence-Identifier: EUPL-1.2 +# +# Builds libcryptonote.a from vendored upstream C/C++ sources. +# This is the build-system half of the CGo bridge. +# +cmake_minimum_required(VERSION 3.20) +project(cryptonote C CXX) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Include paths: upstream sources + compat stubs +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/upstream + ${CMAKE_CURRENT_SOURCE_DIR}/compat +) + +# --- Pure C sources (no dependencies beyond themselves) --- +set(C_SOURCES + upstream/crypto-ops.c + upstream/crypto-ops-data.c + upstream/keccak.c + upstream/hash.c + upstream/random.c + upstream/blake2b-ref.c + upstream/RIPEMD160.c +) + +# --- C++ sources (depend on compat layer + Boost headers) --- +# eth_signature.cpp excluded — needs bitcoin-secp256k1, not required for consensus crypto. +# The header (eth_signature.h) is still included for type definitions via crypto-sugar.h. +set(CXX_SOURCES + upstream/crypto.cpp + upstream/crypto-sugar.cpp + upstream/clsag.cpp + upstream/zarcanum.cpp + upstream/range_proofs.cpp + upstream/one_out_of_many_proofs.cpp + upstream/msm.cpp + upstream/RIPEMD160_helper.cpp + bridge.cpp +) + +# --- Find system dependencies --- +find_package(OpenSSL REQUIRED) +find_package(Boost REQUIRED) + +# --- Static library --- +add_library(cryptonote STATIC ${C_SOURCES} ${CXX_SOURCES}) + +target_include_directories(cryptonote PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/upstream + ${CMAKE_CURRENT_SOURCE_DIR}/compat + ${OPENSSL_INCLUDE_DIR} + ${Boost_INCLUDE_DIRS} +) + +target_link_libraries(cryptonote PRIVATE + OpenSSL::Crypto +) + +# Suppress warnings from upstream code (we don't modify it) +target_compile_options(cryptonote PRIVATE + -Wno-unused-variable + -Wno-unused-function + -Wno-sign-compare + -Wno-unused-parameter + -Wno-deprecated-declarations +) diff --git a/crypto/PROVENANCE.md b/crypto/PROVENANCE.md new file mode 100644 index 0000000..b106507 --- /dev/null +++ b/crypto/PROVENANCE.md @@ -0,0 +1,66 @@ +# Provenance + +Vendored from `~/Code/LetheanNetwork/blockchain/` at commit `fa1608cf`. + +## Upstream Files (unmodified copies) + +| Local Path | Upstream Path | Modified | +|-----------|---------------|----------| +| upstream/crypto-ops.c | src/crypto/crypto-ops.c | no | +| upstream/crypto-ops-data.c | src/crypto/crypto-ops-data.c | no | +| upstream/crypto-ops.h | src/crypto/crypto-ops.h | no | +| upstream/crypto.cpp | src/crypto/crypto.cpp | no | +| upstream/crypto.h | src/crypto/crypto.h | no | +| upstream/crypto-sugar.h | src/crypto/crypto-sugar.h | no | +| upstream/crypto-sugar.cpp | src/crypto/crypto-sugar.cpp | no | +| upstream/clsag.h | src/crypto/clsag.h | no | +| upstream/clsag.cpp | src/crypto/clsag.cpp | no | +| upstream/zarcanum.h | src/crypto/zarcanum.h | no | +| upstream/zarcanum.cpp | src/crypto/zarcanum.cpp | no | +| upstream/range_proofs.h | src/crypto/range_proofs.h | no | +| upstream/range_proofs.cpp | src/crypto/range_proofs.cpp | no | +| upstream/range_proof_bppe.h | src/crypto/range_proof_bppe.h | no | +| upstream/range_proof_bpp.h | src/crypto/range_proof_bpp.h | no | +| upstream/one_out_of_many_proofs.h | src/crypto/one_out_of_many_proofs.h | no | +| upstream/one_out_of_many_proofs.cpp | src/crypto/one_out_of_many_proofs.cpp | no | +| upstream/msm.h | src/crypto/msm.h | no | +| upstream/msm.cpp | src/crypto/msm.cpp | no | +| upstream/keccak.c | src/crypto/keccak.c | no | +| upstream/keccak.h | src/crypto/keccak.h | no | +| upstream/hash.c | src/crypto/hash.c | no | +| upstream/hash.h | src/crypto/hash.h | no | +| upstream/hash-ops.h | src/crypto/hash-ops.h | no | +| upstream/random.c | src/crypto/random.c | no | +| upstream/random.h | src/crypto/random.h | no | +| upstream/blake2.h | src/crypto/blake2.h | no | +| upstream/blake2-impl.h | src/crypto/blake2-impl.h | no | +| upstream/blake2b-ref.c | src/crypto/blake2b-ref.c | no | +| upstream/generic-ops.h | src/crypto/generic-ops.h | no | +| upstream/eth_signature.h | src/crypto/eth_signature.h | no | +| upstream/eth_signature.cpp | src/crypto/eth_signature.cpp | no | +| upstream/RIPEMD160.c | src/crypto/RIPEMD160.c | no | +| upstream/RIPEMD160.h | src/crypto/RIPEMD160.h | no | +| upstream/RIPEMD160_helper.h | src/crypto/RIPEMD160_helper.h | no | +| upstream/RIPEMD160_helper.cpp | src/crypto/RIPEMD160_helper.cpp | no | +| upstream/initializer.h | src/crypto/initializer.h | no | + +## Compat Files (extracted subsets or stubs) + +| Local Path | Origin | Notes | +|-----------|--------|-------| +| compat/currency_core/crypto_config.h | src/currency_core/crypto_config.h | unmodified copy | +| compat/common/pod-class.h | src/common/pod-class.h | unmodified copy | +| compat/common/varint.h | src/common/varint.h | unmodified copy | +| compat/warnings.h | N/A | stub — no-op macros | +| compat/epee/include/misc_log_ex.h | N/A | stub — no-op logging macros | +| compat/common/crypto_stream_operators.h | N/A | stub — empty | +| compat/include_base_utils.h | N/A | stub — empty | + +## Update Workflow + +1. Note the current provenance commit (`fa1608cf`) +2. In the upstream repo, `git diff fa1608cf..HEAD -- src/crypto/` +3. Copy changed files into `upstream/` +4. Rebuild: `cmake --build crypto/build --parallel` +5. Run tests: `go test -race ./crypto/...` +6. Update this file with new commit hash diff --git a/crypto/bridge.cpp b/crypto/bridge.cpp new file mode 100644 index 0000000..a775f7d --- /dev/null +++ b/crypto/bridge.cpp @@ -0,0 +1,17 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Thin C wrappers around CryptoNote C++ crypto library. +// This is the implementation of bridge.h. + +#include "bridge.h" + +#include +#include "crypto.h" +#include "hash-ops.h" + +extern "C" { + +void bridge_fast_hash(const uint8_t *data, size_t len, uint8_t hash[32]) { + crypto::cn_fast_hash(data, len, reinterpret_cast(hash)); +} + +} // extern "C" diff --git a/crypto/bridge.h b/crypto/bridge.h new file mode 100644 index 0000000..3ba9b2c --- /dev/null +++ b/crypto/bridge.h @@ -0,0 +1,20 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Stable C API for go-blockchain CGo bindings. +// Go code calls ONLY these functions — no C++ types cross this boundary. +#ifndef CRYPTONOTE_BRIDGE_H +#define CRYPTONOTE_BRIDGE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// ── Hashing ─────────────────────────────────────────────── +void bridge_fast_hash(const uint8_t *data, size_t len, uint8_t hash[32]); + +#ifdef __cplusplus +} +#endif +#endif // CRYPTONOTE_BRIDGE_H diff --git a/crypto/common/crypto_stream_operators.h b/crypto/common/crypto_stream_operators.h new file mode 120000 index 0000000..e8205c3 --- /dev/null +++ b/crypto/common/crypto_stream_operators.h @@ -0,0 +1 @@ +../compat/common/crypto_stream_operators.h \ No newline at end of file diff --git a/crypto/compat/auto_val_init.h b/crypto/compat/auto_val_init.h new file mode 100644 index 0000000..0b4ec9d --- /dev/null +++ b/crypto/compat/auto_val_init.h @@ -0,0 +1,7 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Compat stub for auto_val_init.h — replaces boost::value_initialized with +// aggregate zero-initialisation which is equivalent for POD types. +#pragma once + +#define AUTO_VAL_INIT(v) decltype(v){} +#define AUTO_VAL_INIT_T(t) t{} diff --git a/crypto/compat/common/crypto_stream_operators.h b/crypto/compat/common/crypto_stream_operators.h new file mode 100644 index 0000000..ee607b8 --- /dev/null +++ b/crypto/compat/common/crypto_stream_operators.h @@ -0,0 +1,3 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Compat stub — stream operators not needed for CGo bridge. +#pragma once diff --git a/crypto/compat/common/int-util.h b/crypto/compat/common/int-util.h new file mode 100755 index 0000000..808cda7 --- /dev/null +++ b/crypto/compat/common/int-util.h @@ -0,0 +1,258 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#include +#include +#include +#include + +#if defined(_MSC_VER) +#include +#include + +#if !defined(__ORDER_LITTLE_ENDIAN__) +#define __ORDER_LITTLE_ENDIAN__ 1011012001 +#endif + +#if !defined(__BYTE_ORDER__) +#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ +#endif + +#if !defined(__ORDER_BIG_ENDIAN__) +#define __ORDER_BIG_ENDIAN__ 0 +#endif + +static inline uint32_t rol32(uint32_t x, int r) { + static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers"); + return _rotl(x, r); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return _rotl64(x, r); +} + +#else + +static inline uint32_t rol32(uint32_t x, int r) { + return (x << (r & 31)) | (x >> (-r & 31)); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return (x << (r & 63)) | (x >> (-r & 63)); +} + +#endif + +static inline uint64_t hi_dword(uint64_t val) { + return val >> 32; +} + +static inline uint64_t lo_dword(uint64_t val) { + return val & 0xFFFFFFFF; +} + +static inline uint64_t mul128_manually(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) { + // multiplier = ab = a * 2^32 + b + // multiplicand = cd = c * 2^32 + d + // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d + uint64_t a = hi_dword(multiplier); + uint64_t b = lo_dword(multiplier); + uint64_t c = hi_dword(multiplicand); + uint64_t d = lo_dword(multiplicand); + + uint64_t ac = a * c; + uint64_t ad = a * d; + uint64_t bc = b * c; + uint64_t bd = b * d; + + uint64_t adbc = ad + bc; + uint64_t adbc_carry = adbc < ad ? 1 : 0; + + // multiplier * multiplicand = product_hi * 2^64 + product_lo + uint64_t product_lo = bd + (adbc << 32); + uint64_t product_lo_carry = product_lo < bd ? 1 : 0; + *product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry; + assert(ac <= *product_hi); + + return product_lo; +} + +static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) { + dividend |= ((uint64_t)*remainder) << 32; + *remainder = dividend % divisor; + return dividend / divisor; +} + +// Long division with 2^32 base +static inline uint32_t div128_32_manually(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) { + uint64_t dividend_dwords[4]; + uint32_t remainder = 0; + + dividend_dwords[3] = hi_dword(dividend_hi); + dividend_dwords[2] = lo_dword(dividend_hi); + dividend_dwords[1] = hi_dword(dividend_lo); + dividend_dwords[0] = lo_dword(dividend_lo); + + *quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32; + *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder); + *quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32; + *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder); + + return remainder; +} + +static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) +{ +// #if defined(_MSC_VER) +// return _umul128(multiplier, multiplicand, product_hi); +// #elif defined(__GNUC__) +// __uint128_t product = ((__uint128_t)multiplier) * multiplicand; +// *product_hi = (uint64_t)(product >> 64); +// return ((uint64_t)product) & ~(UINT64_C(0)); +// #else + return mul128_manually(multiplier, multiplicand, product_hi); +//#endif*/ +} +//*/ + +static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) +{ +// #if defined(__GNUC__) +// __uint128_t dividend = (((__uint128_t)dividend_hi) << 64) | dividend_lo; +// __uint128_t quotient = dividend / divisor; +// __uint128_t reminder = dividend % divisor; +// *quotient_hi = (uint64_t)(quotient >> 64); +// *quotient_lo = ((uint64_t)quotient) & ~(UINT64_C(0)); +// return (uint32_t)reminder; +// #else + return div128_32_manually(dividend_hi, dividend_lo, divisor, quotient_hi, quotient_lo); +//#endif +} +//*/ +#define IDENT32(x) ((uint32_t) (x)) +#define IDENT64(x) ((uint64_t) (x)) + +#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \ + (((uint32_t) (x) & 0x0000ff00) << 8) | \ + (((uint32_t) (x) & 0x00ff0000) >> 8) | \ + (((uint32_t) (x) & 0xff000000) >> 24)) +#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \ + (((uint64_t) (x) & 0x000000000000ff00) << 40) | \ + (((uint64_t) (x) & 0x0000000000ff0000) << 24) | \ + (((uint64_t) (x) & 0x00000000ff000000) << 8) | \ + (((uint64_t) (x) & 0x000000ff00000000) >> 8) | \ + (((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \ + (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \ + (((uint64_t) (x) & 0xff00000000000000) >> 56)) + +static inline uint32_t ident32(uint32_t x) { return x; } +static inline uint64_t ident64(uint64_t x) { return x; } + +static inline uint32_t swap32(uint32_t x) { + x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); + return (x << 16) | (x >> 16); +} +static inline uint64_t swap64(uint64_t x) { + x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8); + x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16); + return (x << 32) | (x >> 32); +} + +#if defined(__GNUC__) +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif +static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { } +#undef UNUSED + +static inline void mem_inplace_swap32(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]); + } +} +static inline void mem_inplace_swap64(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]); + } +} + +static inline void memcpy_ident32(void *dst, const void *src, size_t n) { + memcpy(dst, src, 4 * n); +} +static inline void memcpy_ident64(void *dst, const void *src, size_t n) { + memcpy(dst, src, 8 * n); +} + +static inline void memcpy_swap32(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]); + } +} +static inline void memcpy_swap64(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]); + } +} + +#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || !defined(__ORDER_BIG_ENDIAN__) +static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); +#endif + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define SWAP32LE IDENT32 +#define SWAP32BE SWAP32 +#define swap32le ident32 +#define swap32be swap32 +#define mem_inplace_swap32le mem_inplace_ident +#define mem_inplace_swap32be mem_inplace_swap32 +#define memcpy_swap32le memcpy_ident32 +#define memcpy_swap32be memcpy_swap32 +#define SWAP64LE IDENT64 +#define SWAP64BE SWAP64 +#define swap64le ident64 +#define swap64be swap64 +#define mem_inplace_swap64le mem_inplace_ident +#define mem_inplace_swap64be mem_inplace_swap64 +#define memcpy_swap64le memcpy_ident64 +#define memcpy_swap64be memcpy_swap64 +#endif + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define SWAP32BE IDENT32 +#define SWAP32LE SWAP32 +#define swap32be ident32 +#define swap32le swap32 +#define mem_inplace_swap32be mem_inplace_ident +#define mem_inplace_swap32le mem_inplace_swap32 +#define memcpy_swap32be memcpy_ident32 +#define memcpy_swap32le memcpy_swap32 +#define SWAP64BE IDENT64 +#define SWAP64LE SWAP64 +#define swap64be ident64 +#define swap64le swap64 +#define mem_inplace_swap64be mem_inplace_ident +#define mem_inplace_swap64le mem_inplace_swap64 +#define memcpy_swap64be memcpy_ident64 +#define memcpy_swap64le memcpy_swap64 +#endif diff --git a/crypto/compat/common/pod-class.h b/crypto/compat/common/pod-class.h new file mode 100755 index 0000000..47dca67 --- /dev/null +++ b/crypto/compat/common/pod-class.h @@ -0,0 +1,22 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +// in C++ no difference 'class' vs 'struct' except the default members access. +// maybe be better to erase the 'POD_CLASS' macro completely? +#define POD_CLASS struct diff --git a/crypto/compat/common/varint.h b/crypto/compat/common/varint.h new file mode 100755 index 0000000..31f48be --- /dev/null +++ b/crypto/compat/common/varint.h @@ -0,0 +1,97 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace tools { + + + //--------------------------------------------------------------- + template + size_t get_varint_packed_size(T v) + { + if(v <= 127) + return 1; + else if(v <= 16383) + return 2; + else if(v <= 2097151) + return 3; + else if(v <= 268435455) + return 4; + else if(v <= 34359738367) + return 5; + else if(v <= 4398046511103) + return 6; + else if(v <= 562949953421311) + return 7; + else + return 8; + } + template + typename std::enable_if::value && std::is_unsigned::value, void>::type + write_varint(OutputIt &&dest, T i) { + while (i >= 0x80) { + *dest++ = (static_cast(i) & 0x7f) | 0x80; + i >>= 7; + } + *dest++ = static_cast(i); + } + + template + std::string get_varint_data(const t_type& v) + { + std::stringstream ss; + write_varint(std::ostreambuf_iterator(ss), v); + return ss.str(); + } + + template + typename std::enable_if::value && std::is_unsigned::value && 0 <= bits && bits <= std::numeric_limits::digits, int>::type + read_varint(InputIt &&first, InputIt &&last, T &i) { + int read = 0; + i = 0; + for (int shift = 0;; shift += 7) { + if (first == last) { + return read; // End of input. + } + unsigned char byte = *first++; + ++read; + if (shift + 7 >= bits && byte >= 1 << (bits - shift)) { + return -1; // Overflow. + } + if (byte == 0 && shift != 0) { + return -2; // Non-canonical representation. + } + i |= static_cast(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) { + break; + } + } + return read; + } + + template + int read_varint(InputIt &&first, InputIt &&last, T &i) { + return read_varint::digits, InputIt, T>(std::move(first), std::move(last), i); + } +} diff --git a/crypto/compat/config/currency_config.h b/crypto/compat/config/currency_config.h new file mode 100644 index 0000000..06c0d67 --- /dev/null +++ b/crypto/compat/config/currency_config.h @@ -0,0 +1,5 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Compat stub — minimal subset of generated currency_config.h. +#pragma once + +#define CURRENCY_TX_MAX_ALLOWED_INPUTS 256 diff --git a/crypto/compat/currency_core/crypto_config.h b/crypto/compat/currency_core/crypto_config.h new file mode 100755 index 0000000..72d6a9b --- /dev/null +++ b/crypto/compat/currency_core/crypto_config.h @@ -0,0 +1,55 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once + +// hash domain separation strings, 32 bytes long (31 chars + \0) +// + +#define CRYPTO_HDS_OUT_AMOUNT_MASK "ZANO_HDS_OUT_AMOUNT_MASK_______" +#define CRYPTO_HDS_OUT_AMOUNT_BLINDING_MASK "ZANO_HDS_OUT_AMOUNT_BLIND_MASK_" +#define CRYPTO_HDS_OUT_ASSET_BLINDING_MASK "ZANO_HDS_OUT_ASSET_BLIND_MASK__" +#define CRYPTO_HDS_OUT_CONCEALING_POINT "ZANO_HDS_OUT_CONCEALING_POINT__" + +#define CRYPTO_HDS_CLSAG_GG_LAYER_0 "ZANO_HDS_CLSAG_GG_LAYER_ZERO___" +#define CRYPTO_HDS_CLSAG_GG_LAYER_1 "ZANO_HDS_CLSAG_GG_LAYER_ONE____" +#define CRYPTO_HDS_CLSAG_GG_CHALLENGE "ZANO_HDS_CLSAG_GG_CHALLENGE____" + +#define CRYPTO_HDS_CLSAG_GGX_LAYER_0 "ZANO_HDS_CLSAG_GGX_LAYER_ZERO__" +#define CRYPTO_HDS_CLSAG_GGX_LAYER_1 "ZANO_HDS_CLSAG_GGX_LAYER_ONE___" +#define CRYPTO_HDS_CLSAG_GGX_LAYER_2 "ZANO_HDS_CLSAG_GGX_LAYER_TWO___" +#define CRYPTO_HDS_CLSAG_GGX_CHALLENGE "ZANO_HDS_CLSAG_GGX_CHALLENGE___" + +#define CRYPTO_HDS_CLSAG_GGXG_LAYER_0 "ZANO_HDS_CLSAG_GGXG_LAYER_ZERO_" +#define CRYPTO_HDS_CLSAG_GGXG_LAYER_1 "ZANO_HDS_CLSAG_GGXG_LAYER_ONE__" +#define CRYPTO_HDS_CLSAG_GGXG_LAYER_2 "ZANO_HDS_CLSAG_GGXG_LAYER_TWO__" +#define CRYPTO_HDS_CLSAG_GGXG_LAYER_3 "ZANO_HDS_CLSAG_GGXG_LAYER_THREE" +#define CRYPTO_HDS_CLSAG_GGXG_CHALLENGE "ZANO_HDS_CLSAG_GGXG_CHALLENGE__" + +#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_0 "ZANO_HDS_CLSAG_GGXXG_LAYER_ZERO" +#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_1 "ZANO_HDS_CLSAG_GGXXG_LAYER_ONE_" +#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_2 "ZANO_HDS_CLSAG_GGXXG_LAYER_TWO_" +#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_3 "ZANO_HDS_CLSAG_GGXXG_LAYER_3___" +#define CRYPTO_HDS_CLSAG_GGXXG_LAYER_4 "ZANO_HDS_CLSAG_GGXXG_LAYER_FOUR" +#define CRYPTO_HDS_CLSAG_GGXXG_CHALLENGE "ZANO_HDS_CLSAG_GGXXG_CHALLENGE_" + +#define CRYPTO_HDS_ZARCANUM_LAST_POW_HASH "ZANO_HDS_ZARCANUM_LAST_POW_HASH" +#define CRYPTO_HDS_ZARCANUM_PROOF_HASH "ZANO_HDS_ZARCANUM_PROOF_HASH___" + +#define CRYPTO_HDS_ASSET_CONTROL_KEY "ZANO_HDS_ASSET_CONTROL_KEY_____" +#define CRYPTO_HDS_ASSET_CONTROL_ABM "ZANO_HDS_ASSET_CONTROL_ABM_____" +#define CRYPTO_HDS_ASSET_ID "ZANO_HDS_ASSET_ID______________" +#define CRYPTO_HDS_DETERMINISTIC_TX_KEY "ZANO_HDS_DETERMINISTIC_TX_KEY__" diff --git a/crypto/compat/epee/include/misc_log_ex.h b/crypto/compat/epee/include/misc_log_ex.h new file mode 100644 index 0000000..49331f2 --- /dev/null +++ b/crypto/compat/epee/include/misc_log_ex.h @@ -0,0 +1,39 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Compat stub for epee logging, exception handling, and misc macros. +#pragma once + +#include +#include + +#define ENDL std::endl + +#define LOG_PRINT_RED(msg, level) ((void)0) +#define LOG_PRINT_L0(msg) ((void)0) +#define LOG_PRINT_L1(msg) ((void)0) +#define LOG_PRINT_L2(msg) ((void)0) +#define LOG_PRINT_L3(msg) ((void)0) +#define LOG_PRINT_L4(msg) ((void)0) +#define LOG_ERROR(msg) ((void)0) + +#define CHECK_AND_ASSERT_MES(cond, ret, msg) \ + do { if (!(cond)) { return (ret); } } while(0) + +#define CHECK_AND_ASSERT_MES_NO_RET(cond, msg) \ + do { if (!(cond)) { return; } } while(0) + +#define CHECK_AND_NO_ASSERT_MES(cond, ret, msg) \ + do { if (!(cond)) { return (ret); } } while(0) + +#define ASSERT_MES_AND_THROW(msg) do { assert(false && (msg)); } while(0) + +// Exception handling macros (from misc_helpers.h) +#define TRY_ENTRY() try { +#define CATCH_ENTRY(location, return_val) } catch(...) { return (return_val); } +#define CATCH_ENTRY2(return_val) } catch(...) { return (return_val); } +#define CATCH_ENTRY_CUSTOM(location, custom_code, return_val) } catch(...) { custom_code; return (return_val); } +#define CATCH_ENTRY_CUSTOM2(custom_code, return_val) } catch(...) { custom_code; return (return_val); } +#define CATCH_ENTRY_L0(location, return_val) CATCH_ENTRY(location, return_val) +#define CATCH_ENTRY_L1(location, return_val) CATCH_ENTRY(location, return_val) + +// Location string helper +#define LOCATION_SS "" diff --git a/crypto/compat/epee/include/profile_tools.h b/crypto/compat/epee/include/profile_tools.h new file mode 100644 index 0000000..22ac31a --- /dev/null +++ b/crypto/compat/epee/include/profile_tools.h @@ -0,0 +1,7 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Compat stub for epee profiling macros. +#pragma once + +#define TIME_MEASURE_START(x) ((void)0) +#define TIME_MEASURE_FINISH(x) ((void)0) +#define PROFILE_FUNC(x) ((void)0) diff --git a/crypto/compat/include_base_utils.h b/crypto/compat/include_base_utils.h new file mode 100644 index 0000000..64e95a7 --- /dev/null +++ b/crypto/compat/include_base_utils.h @@ -0,0 +1,3 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Compat stub for include_base_utils.h +#pragma once diff --git a/crypto/compat/warnings.h b/crypto/compat/warnings.h new file mode 100644 index 0000000..d0cae13 --- /dev/null +++ b/crypto/compat/warnings.h @@ -0,0 +1,39 @@ +// SPDX-Licence-Identifier: EUPL-1.2 +// Compat stub for CryptoNote warning macros. +// Replaces contrib/epee/include/warnings.h without Boost dependency. +// Uses a double-stringify trick to replicate BOOST_PP_STRINGIZE. +#pragma once + +#define _CN_STRINGIFY_INNER(x) #x +#define _CN_STRINGIFY(x) _CN_STRINGIFY_INNER(x) + +#if defined(_MSC_VER) +#define PUSH_VS_WARNINGS __pragma(warning(push)) +#define POP_VS_WARNINGS __pragma(warning(pop)) +#define DISABLE_VS_WARNINGS(w) __pragma(warning(disable: w)) +#define PUSH_GCC_WARNINGS +#define POP_GCC_WARNINGS +#define DISABLE_GCC_WARNING(w) +#define DISABLE_CLANG_WARNING(w) +#define DISABLE_GCC_AND_CLANG_WARNING(w) +#define ATTRIBUTE_UNUSED +#else +#define PUSH_VS_WARNINGS +#define POP_VS_WARNINGS +#define DISABLE_VS_WARNINGS(w) +#define PUSH_GCC_WARNINGS _Pragma("GCC diagnostic push") +#define POP_GCC_WARNINGS _Pragma("GCC diagnostic pop") +#define ATTRIBUTE_UNUSED __attribute__((unused)) + +#define DISABLE_GCC_AND_CLANG_WARNING(w) \ + _Pragma(_CN_STRINGIFY(GCC diagnostic ignored _CN_STRINGIFY(-W##w))) + +#if defined(__clang__) +#define DISABLE_GCC_WARNING(w) +#define DISABLE_CLANG_WARNING DISABLE_GCC_AND_CLANG_WARNING +#else +#define DISABLE_GCC_WARNING DISABLE_GCC_AND_CLANG_WARNING +#define DISABLE_CLANG_WARNING(w) +#endif + +#endif diff --git a/crypto/currency_core/crypto_config.h b/crypto/currency_core/crypto_config.h new file mode 120000 index 0000000..1bdb324 --- /dev/null +++ b/crypto/currency_core/crypto_config.h @@ -0,0 +1 @@ +../compat/currency_core/crypto_config.h \ No newline at end of file diff --git a/crypto/upstream/RIPEMD160.c b/crypto/upstream/RIPEMD160.c new file mode 100755 index 0000000..edd6290 --- /dev/null +++ b/crypto/upstream/RIPEMD160.c @@ -0,0 +1,269 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +/* header files */ +#include +#include +#include +#include "RIPEMD160.h" + +/********************************************************************/ + +void MDinit(dword *MDbuf) +{ + MDbuf[0] = 0x67452301UL; + MDbuf[1] = 0xefcdab89UL; + MDbuf[2] = 0x98badcfeUL; + MDbuf[3] = 0x10325476UL; + MDbuf[4] = 0xc3d2e1f0UL; + + return; +} + +/********************************************************************/ + +void compress(dword *MDbuf, dword *X) +{ + dword aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], + dd = MDbuf[3], ee = MDbuf[4]; + dword aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], + ddd = MDbuf[3], eee = MDbuf[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[0], 11); + FF(ee, aa, bb, cc, dd, X[1], 14); + FF(dd, ee, aa, bb, cc, X[2], 15); + FF(cc, dd, ee, aa, bb, X[3], 12); + FF(bb, cc, dd, ee, aa, X[4], 5); + FF(aa, bb, cc, dd, ee, X[5], 8); + FF(ee, aa, bb, cc, dd, X[6], 7); + FF(dd, ee, aa, bb, cc, X[7], 9); + FF(cc, dd, ee, aa, bb, X[8], 11); + FF(bb, cc, dd, ee, aa, X[9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[7], 7); + GG(dd, ee, aa, bb, cc, X[4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[0], 12); + GG(ee, aa, bb, cc, dd, X[9], 15); + GG(dd, ee, aa, bb, cc, X[5], 9); + GG(cc, dd, ee, aa, bb, X[2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[4], 7); + HH(ee, aa, bb, cc, dd, X[9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[8], 13); + HH(bb, cc, dd, ee, aa, X[1], 15); + HH(aa, bb, cc, dd, ee, X[2], 14); + HH(ee, aa, bb, cc, dd, X[7], 8); + HH(dd, ee, aa, bb, cc, X[0], 13); + HH(cc, dd, ee, aa, bb, X[6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[1], 11); + II(bb, cc, dd, ee, aa, X[9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[0], 14); + II(cc, dd, ee, aa, bb, X[8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[3], 14); + II(cc, dd, ee, aa, bb, X[7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[5], 6); + II(dd, ee, aa, bb, cc, X[6], 5); + II(cc, dd, ee, aa, bb, X[2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[4], 9); + JJ(aa, bb, cc, dd, ee, X[0], 15); + JJ(ee, aa, bb, cc, dd, X[5], 5); + JJ(dd, ee, aa, bb, cc, X[9], 11); + JJ(cc, dd, ee, aa, bb, X[7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[1], 12); + JJ(bb, cc, dd, ee, aa, X[3], 13); + JJ(aa, bb, cc, dd, ee, X[8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[3], 15); + III(bbb, ccc, ddd, eee, aaa, X[7], 7); + III(aaa, bbb, ccc, ddd, eee, X[0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[4], 6); + III(bbb, ccc, ddd, eee, aaa, X[9], 15); + III(aaa, bbb, ccc, ddd, eee, X[1], 13); + III(eee, aaa, bbb, ccc, ddd, X[2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12], 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15], 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10], 12); + FFF(ddd, eee, aaa, bbb, ccc, X[4], 9); + FFF(ccc, ddd, eee, aaa, bbb, X[1], 12); + FFF(bbb, ccc, ddd, eee, aaa, X[5], 5); + FFF(aaa, bbb, ccc, ddd, eee, X[8], 14); + FFF(eee, aaa, bbb, ccc, ddd, X[7], 6); + FFF(ddd, eee, aaa, bbb, ccc, X[6], 8); + FFF(ccc, ddd, eee, aaa, bbb, X[2], 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13], 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14], 5); + FFF(eee, aaa, bbb, ccc, ddd, X[0], 15); + FFF(ddd, eee, aaa, bbb, ccc, X[3], 13); + FFF(ccc, ddd, eee, aaa, bbb, X[9], 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11], 11); + + /* combine results */ + ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ + MDbuf[1] = MDbuf[2] + dd + eee; + MDbuf[2] = MDbuf[3] + ee + aaa; + MDbuf[3] = MDbuf[4] + aa + bbb; + MDbuf[4] = MDbuf[0] + bb + ccc; + MDbuf[0] = ddd; + + return; +} + +/********************************************************************/ + +void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen) +{ + unsigned int i; /* counter */ + dword X[16]; /* message words */ + + memset(X, 0, 16 * sizeof(dword)); + + /* put bytes from strptr into X */ + for (i = 0; i<(lswlen & 63); i++) { + /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ + X[i >> 2] ^= (dword)*strptr++ << (8 * (i & 3)); + } + + /* append the bit m_n == 1 */ + X[(lswlen >> 2) & 15] ^= (dword)1 << (8 * (lswlen & 3) + 7); + + if ((lswlen & 63) > 55) { + /* length goes to next block */ + compress(MDbuf, X); + memset(X, 0, 16 * sizeof(dword)); + } + + /* append length in bits*/ + X[14] = lswlen << 3; + X[15] = (lswlen >> 29) | (mswlen << 3); + compress(MDbuf, X); + + return; +} + +/************************ end of file rmd160.c **********************/ diff --git a/crypto/upstream/RIPEMD160.h b/crypto/upstream/RIPEMD160.h new file mode 100755 index 0000000..e1d1a98 --- /dev/null +++ b/crypto/upstream/RIPEMD160.h @@ -0,0 +1,132 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#ifndef RMD160H /* make sure this file is read only once */ +#define RMD160H + +/********************************************************************/ +#include +/* typedef 8 and 32 bit types, resp. */ +/* adapt these, if necessary, +for your operating system and compiler */ +typedef unsigned char byte; +typedef uint32_t dword; + +/* if this line causes a compiler error, +adapt the defintion of dword above */ +typedef int the_correct_size_was_chosen[sizeof(dword) == 4 ? 1 : -1]; + +/********************************************************************/ + +/* macro definitions */ + +/* collect four bytes into one word: */ +#define BYTES_TO_DWORD(strptr) \ + (((dword) *((strptr)+3) << 24) | \ + ((dword) *((strptr)+2) << 16) | \ + ((dword) *((strptr)+1) << 8) | \ + ((dword) *(strptr))) + +/* ROL(x, n) cyclically rotates x over n bits to the left */ +/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ +#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) {\ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define GG(a, b, c, d, e, x, s) {\ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define HH(a, b, c, d, e, x, s) {\ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define II(a, b, c, d, e, x, s) {\ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define JJ(a, b, c, d, e, x, s) {\ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define FFF(a, b, c, d, e, x, s) {\ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define GGG(a, b, c, d, e, x, s) {\ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define HHH(a, b, c, d, e, x, s) {\ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define III(a, b, c, d, e, x, s) {\ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } +#define JJJ(a, b, c, d, e, x, s) {\ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +/********************************************************************/ + +/* function prototypes */ + +void MDinit(dword *MDbuf); +/* +* initializes MDbuffer to "magic constants" +*/ + +void compress(dword *MDbuf, dword *X); +/* +* the compression function. +* transforms MDbuf using message bytes X[0] through X[15] +*/ + +void MDfinish(dword *MDbuf, byte *strptr, dword lswlen, dword mswlen); +/* +* puts bytes from strptr into X and pad out; appends length +* and finally, compresses the last block(s) +* note: length in bits == 8 * (lswlen + 2^32 mswlen). +* note: there are (lswlen mod 64) bytes left in strptr. +*/ + +#endif /* RMD160H */ + +/*********************** end of file rmd160.h ***********************/ diff --git a/crypto/upstream/RIPEMD160_helper.cpp b/crypto/upstream/RIPEMD160_helper.cpp new file mode 100755 index 0000000..4ed7f5c --- /dev/null +++ b/crypto/upstream/RIPEMD160_helper.cpp @@ -0,0 +1,77 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#include "RIPEMD160_helper.h" +#include "auto_val_init.h" +extern "C" { +#include "RIPEMD160.h" +} + +#define RMDsize 160 + +namespace crypto { + + void RIPEMD160_hash(const void *data, size_t length_size_t, hash160 &h) + { + + dword MDbuf[RMDsize / 32] = {0}; /* contains (A, B, C, D(, E)) */ + byte* hashcode = (byte*)&h; /* hashcode[RMDsize / 8]; for final hash-value */ + dword X[16] = {0}; /* current 16-word chunk */ + unsigned int i = 0; /* counter */ + dword length = static_cast(length_size_t); /* length in bytes of message */ + dword nbytes = 0; /* # of bytes not yet processed */ + byte* message = (byte*)data; + + /* initialize */ + MDinit(MDbuf); + //length = (dword)strlen((char *)message); + + /* process message in 16-word chunks */ + for (nbytes = length; nbytes > 63; nbytes -= 64) { + for (i = 0; i < 16; i++) { + X[i] = BYTES_TO_DWORD(message); + message += 4; + } + compress(MDbuf, X); + }/* length mod 64 bytes left */ + + /* finish: */ + MDfinish(MDbuf, message, length, 0); + + for (i = 0; i < RMDsize / 8; i += 4) { + hashcode[i] = (byte)MDbuf[i >> 2]; /* implicit cast to byte */ + hashcode[i + 1] = (byte)(MDbuf[i >> 2] >> 8); /* extracts the 8 least */ + hashcode[i + 2] = (byte)(MDbuf[i >> 2] >> 16); /* significant bits. */ + hashcode[i + 3] = (byte)(MDbuf[i >> 2] >> 24); + } + } + + hash160 RIPEMD160_hash(const void *data, size_t length) + { + hash160 h = AUTO_VAL_INIT(h); + RIPEMD160_hash(data, length, h); + return h; + } + + hash RIPEMD160_hash_256(const void *data, size_t length) + { + hash160 h = RIPEMD160_hash(data, length); + hash h256 = AUTO_VAL_INIT(h256); + memcpy(&h256, &h, sizeof(h)); + return h256; + } + +} diff --git a/crypto/upstream/RIPEMD160_helper.h b/crypto/upstream/RIPEMD160_helper.h new file mode 100755 index 0000000..08d4693 --- /dev/null +++ b/crypto/upstream/RIPEMD160_helper.h @@ -0,0 +1,40 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#include "hash.h" + + +namespace crypto { + +#pragma pack(push, 1) + POD_CLASS hash160{ + char data[20]; + }; +#pragma pack(pop) + + void RIPEMD160_hash(const void *data, size_t length, hash160 &h); + hash160 RIPEMD160_hash(const void *data, size_t length); + hash RIPEMD160_hash_256(const void *data, size_t length); + +} + +POD_MAKE_HASHABLE(crypto, hash160) + + + diff --git a/crypto/upstream/blake2-impl.h b/crypto/upstream/blake2-impl.h new file mode 100755 index 0000000..6ee612f --- /dev/null +++ b/crypto/upstream/blake2-impl.h @@ -0,0 +1,162 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#ifndef BLAKE2_IMPL_H +#define BLAKE2_IMPL_H + +#include +#include + +#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) + #if defined(_MSC_VER) + #define BLAKE2_INLINE __inline + #elif defined(__GNUC__) + #define BLAKE2_INLINE __inline__ + #else + #define BLAKE2_INLINE + #endif +#else + #define BLAKE2_INLINE inline +#endif + +static BLAKE2_INLINE uint32_t load32( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint32_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint32_t )( p[0] ) << 0) | + (( uint32_t )( p[1] ) << 8) | + (( uint32_t )( p[2] ) << 16) | + (( uint32_t )( p[3] ) << 24) ; +#endif +} + +static BLAKE2_INLINE uint64_t load64( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint64_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) | + (( uint64_t )( p[6] ) << 48) | + (( uint64_t )( p[7] ) << 56) ; +#endif +} + +static BLAKE2_INLINE uint16_t load16( const void *src ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + uint16_t w; + memcpy(&w, src, sizeof w); + return w; +#else + const uint8_t *p = ( const uint8_t * )src; + return ( uint16_t )((( uint32_t )( p[0] ) << 0) | + (( uint32_t )( p[1] ) << 8)); +#endif +} + +static BLAKE2_INLINE void store16( void *dst, uint16_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + *p++ = ( uint8_t )w; w >>= 8; + *p++ = ( uint8_t )w; +#endif +} + +static BLAKE2_INLINE void store32( void *dst, uint32_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); +#endif +} + +static BLAKE2_INLINE void store64( void *dst, uint64_t w ) +{ +#if defined(NATIVE_LITTLE_ENDIAN) + memcpy(dst, &w, sizeof w); +#else + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); + p[6] = (uint8_t)(w >> 48); + p[7] = (uint8_t)(w >> 56); +#endif +} + +static BLAKE2_INLINE uint64_t load48( const void *src ) +{ + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) ; +} + +static BLAKE2_INLINE void store48( void *dst, uint64_t w ) +{ + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); +} + +static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 32 - c ) ); +} + +static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 64 - c ) ); +} + +/* prevents compiler optimizing out memset() */ +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) +{ + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); +} + +#endif diff --git a/crypto/upstream/blake2.h b/crypto/upstream/blake2.h new file mode 100755 index 0000000..46d6081 --- /dev/null +++ b/crypto/upstream/blake2.h @@ -0,0 +1,202 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#ifndef BLAKE2_H +#define BLAKE2_H + +#include +#include + +#if defined(_MSC_VER) +#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop)) +#else +#define BLAKE2_PACKED(x) x __attribute__((packed)) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + + enum blake2s_constant + { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8 + }; + + enum blake2b_constant + { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 + }; + + typedef struct blake2s_state__ + { + uint32_t h[8]; + uint32_t t[2]; + uint32_t f[2]; + uint8_t buf[BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2s_state; + + typedef struct blake2b_state__ + { + uint64_t h[8]; + uint64_t t[2]; + uint64_t f[2]; + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2b_state; + + typedef struct blake2sp_state__ + { + blake2s_state S[8][1]; + blake2s_state R[1]; + uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2sp_state; + + typedef struct blake2bp_state__ + { + blake2b_state S[4][1]; + blake2b_state R[1]; + uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + } blake2bp_state; + + + BLAKE2_PACKED(struct blake2s_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint16_t xof_length; /* 14 */ + uint8_t node_depth; /* 15 */ + uint8_t inner_length; /* 16 */ + /* uint8_t reserved[0]; */ + uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ + uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ + }); + + typedef struct blake2s_param__ blake2s_param; + + BLAKE2_PACKED(struct blake2b_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + }); + + typedef struct blake2b_param__ blake2b_param; + + typedef struct blake2xs_state__ + { + blake2s_state S[1]; + blake2s_param P[1]; + } blake2xs_state; + + typedef struct blake2xb_state__ + { + blake2b_state S[1]; + blake2b_param P[1]; + } blake2xb_state; + + + /* Padded structs result in a compile-time error */ + + enum { + BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES), + BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) + }; +// static_assert(sizeof(blake2s_param) == BLAKE2S_OUTBYTES, "Wrong size of blake2s_param"); +// static_assert(sizeof(blake2b_param) == BLAKE2B_OUTBYTES, "Wrong size of blake2b_param"); + + + /* Streaming API */ + int blake2s_init( blake2s_state *S, size_t outlen ); + int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); + int blake2s_update( blake2s_state *S, const void *in, size_t inlen ); + int blake2s_final( blake2s_state *S, void *out, size_t outlen ); + + int blake2b_init( blake2b_state *S, size_t outlen ); + int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); + int blake2b_update( blake2b_state *S, const void *in, size_t inlen ); + int blake2b_final( blake2b_state *S, void *out, size_t outlen ); + + int blake2sp_init( blake2sp_state *S, size_t outlen ); + int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen ); + int blake2sp_final( blake2sp_state *S, void *out, size_t outlen ); + + int blake2bp_init( blake2bp_state *S, size_t outlen ); + int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen ); + int blake2bp_final( blake2bp_state *S, void *out, size_t outlen ); + + /* Variable output length API */ + int blake2xs_init( blake2xs_state *S, const size_t outlen ); + int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen ); + int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen ); + int blake2xs_final(blake2xs_state *S, void *out, size_t outlen); + + int blake2xb_init( blake2xb_state *S, const size_t outlen ); + int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen ); + int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen ); + int blake2xb_final(blake2xb_state *S, void *out, size_t outlen); + + /* Simple API */ + int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + /* This is simply an alias for blake2b */ + int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/crypto/upstream/blake2b-ref.c b/crypto/upstream/blake2b-ref.c new file mode 100755 index 0000000..80219b2 --- /dev/null +++ b/crypto/upstream/blake2b-ref.c @@ -0,0 +1,381 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#include +#include +#include + +#include "blake2.h" +#include "blake2-impl.h" + +static const uint64_t blake2b_IV[8] = +{ + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL +}; + +static const uint8_t blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + + +static void blake2b_set_lastnode( blake2b_state *S ) +{ + S->f[1] = (uint64_t)-1; +} + +/* Some helper functions, not necessarily useful */ +static int blake2b_is_lastblock( const blake2b_state *S ) +{ + return S->f[0] != 0; +} + +static void blake2b_set_lastblock( blake2b_state *S ) +{ + if( S->last_node ) blake2b_set_lastnode( S ); + + S->f[0] = (uint64_t)-1; +} + +static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); +} + +static void blake2b_init0( blake2b_state *S ) +{ + size_t i; + memset( S, 0, sizeof( blake2b_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; +} + +/* init xors IV with input parameter block */ +int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) +{ + const uint8_t *p = ( const uint8_t * )( P ); + size_t i; + + blake2b_init0( S ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); + + S->outlen = P->digest_length; + return 0; +} + + + +int blake2b_init( blake2b_state *S, size_t outlen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + return blake2b_init_param( S, P ); +} + + +int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; + + P->digest_length = (uint8_t)outlen; + P->key_length = (uint8_t)keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + store32( &P->xof_length, 0 ); + P->node_depth = 0; + P->inner_length = 0; + memset( P->reserved, 0, sizeof( P->reserved ) ); + memset( P->salt, 0, sizeof( P->salt ) ); + memset( P->personal, 0, sizeof( P->personal ) ); + + if( blake2b_init_param( S, P ) < 0 ) return -1; + + { + uint8_t block[BLAKE2B_BLOCKBYTES]; + memset( block, 0, BLAKE2B_BLOCKBYTES ); + memcpy( block, key, keylen ); + blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ + } + return 0; +} + +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2*i+0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2*i+1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while(0) + +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + +static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) +{ + uint64_t m[16]; + uint64_t v[16]; + size_t i; + + for( i = 0; i < 16; ++i ) { + m[i] = load64( block + i * sizeof( m[i] ) ); + } + + for( i = 0; i < 8; ++i ) { + v[i] = S->h[i]; + } + + v[ 8] = blake2b_IV[0]; + v[ 9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ S->t[0]; + v[13] = blake2b_IV[5] ^ S->t[1]; + v[14] = blake2b_IV[6] ^ S->f[0]; + v[15] = blake2b_IV[7] ^ S->f[1]; + + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + ROUND( 10 ); + ROUND( 11 ); + + for( i = 0; i < 8; ++i ) { + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + } +} + +#undef G +#undef ROUND + +int blake2b_update( blake2b_state *S, const void *pin, size_t inlen ) +{ + const unsigned char * in = (const unsigned char *)pin; + if( inlen > 0 ) + { + size_t left = S->buflen; + size_t fill = BLAKE2B_BLOCKBYTES - left; + if( inlen > fill ) + { + S->buflen = 0; + memcpy( S->buf + left, in, fill ); /* Fill buffer */ + blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); + blake2b_compress( S, S->buf ); /* Compress */ + in += fill; inlen -= fill; + while(inlen > BLAKE2B_BLOCKBYTES) { + blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES); + blake2b_compress( S, in ); + in += BLAKE2B_BLOCKBYTES; + inlen -= BLAKE2B_BLOCKBYTES; + } + } + memcpy( S->buf + S->buflen, in, inlen ); + S->buflen += inlen; + } + return 0; +} + +int blake2b_final( blake2b_state *S, void *out, size_t outlen ) +{ + uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; + size_t i; + + if( out == NULL || outlen < S->outlen ) + return -1; + + if( blake2b_is_lastblock( S ) ) + return -1; + + blake2b_increment_counter( S, S->buflen ); + blake2b_set_lastblock( S ); + memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ + blake2b_compress( S, S->buf ); + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + memcpy( out, buffer, S->outlen ); + secure_zero_memory(buffer, sizeof(buffer)); + return 0; +} + +/* inlen, at least, should be uint64_t. Others can be size_t. */ +int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) +{ + blake2b_state S[1]; + + /* Verify parameters */ + if ( NULL == in && inlen > 0 ) return -1; + + if ( NULL == out ) return -1; + + if( NULL == key && keylen > 0 ) return -1; + + if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; + + if( keylen > BLAKE2B_KEYBYTES ) return -1; + + if( keylen > 0 ) + { + if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2b_init( S, outlen ) < 0 ) return -1; + } + + blake2b_update( S, ( const uint8_t * )in, inlen ); + blake2b_final( S, out, outlen ); + return 0; +} + +int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) { + return blake2b(out, outlen, in, inlen, key, keylen); +} + +#if defined(SUPERCOP) +int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) +{ + return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 ); +} +#endif + +#if defined(BLAKE2B_SELFTEST) +#include +#include "blake2-kat.h" +int main( void ) +{ + uint8_t key[BLAKE2B_KEYBYTES]; + uint8_t buf[BLAKE2_KAT_LENGTH]; + size_t i, step; + + for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) + key[i] = ( uint8_t )i; + + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + buf[i] = ( uint8_t )i; + + /* Test simple API */ + for( i = 0; i < BLAKE2_KAT_LENGTH; ++i ) + { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES ); + + if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) + { + goto fail; + } + } + + /* Test streaming API */ + for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) { + for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) { + uint8_t hash[BLAKE2B_OUTBYTES]; + blake2b_state S; + uint8_t * p = buf; + size_t mlen = i; + int err = 0; + + if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) { + goto fail; + } + + while (mlen >= step) { + if ( (err = blake2b_update(&S, p, step)) < 0 ) { + goto fail; + } + mlen -= step; + p += step; + } + if ( (err = blake2b_update(&S, p, mlen)) < 0) { + goto fail; + } + if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) { + goto fail; + } + + if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) { + goto fail; + } + } + } + + puts( "ok" ); + return 0; +fail: + puts("error"); + return -1; +} +#endif diff --git a/crypto/upstream/clsag.cpp b/crypto/upstream/clsag.cpp new file mode 100755 index 0000000..01c92d7 --- /dev/null +++ b/crypto/upstream/clsag.cpp @@ -0,0 +1,1140 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#include "clsag.h" +//#include "misc_log_ex.h" +#include "../currency_core/crypto_config.h" + +DISABLE_GCC_AND_CLANG_WARNING(unused-function) + +namespace crypto +{ +#if 0 +# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl +# define DBG_PRINT(x) std::cout << x << std::endl +#else +# define DBG_VAL_PRINT(x) (void(0)) +# define DBG_PRINT(x) (void(0)) +#endif + + static std::ostream &operator <<(std::ostream &o, const crypto::hash &v) { return o << pod_to_hex(v); } + static std::ostream &operator <<(std::ostream &o, const crypto::public_key &v) { return o << pod_to_hex(v); } + + bool generate_CLSAG_GG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const key_image& ki, + const scalar_t& secret_x, const scalar_t& secret_f, uint64_t secret_index, CLSAG_GG_signature& sig) + { + DBG_PRINT("generate_CLSAG_GG"); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(secret_index < ring_size, "secret_index is out of range"); + + // calculate key images + point_t ki_base = hash_helper_t::hp(ring[secret_index].stealth_address); + point_t key_image = secret_x * ki_base; + CRYPTO_CHECK_AND_THROW_MES(key_image == point_t(ki), "key image 0 mismatch"); + point_t K1_div8 = (c_scalar_1div8 * secret_f) * ki_base; + K1_div8.to_public_key(sig.K1); + point_t K1 = K1_div8; + K1.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(3 + 2 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + } + hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hash input_hash = hsc.calc_hash_no_reduce(); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + // calculate aggregate pub keys + std::vector W_pub_keys; + W_pub_keys.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys.emplace_back(agg_coeff_0 * point_t(ring[i].stealth_address) + agg_coeff_1 * (point_t(ring[i].amount_commitment).modify_mul8() - pseudo_out_amount_commitment)); + DBG_VAL_PRINT(W_pub_keys[i]); + } + + // aggregate secret key + scalar_t w_sec_key = agg_coeff_0 * secret_x + agg_coeff_1 * secret_f; + + // calculate aggregate key image + point_t W_key_image = agg_coeff_0 * key_image + agg_coeff_1 * K1; + DBG_VAL_PRINT(W_key_image); + + // initial commitment + scalar_t alpha = scalar_t::random(); + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(alpha * c_point_G); + hsc.add_point(alpha * ki_base); + scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} + + sig.r.resize_and_make_random(ring_size); + + for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) + { + if (i == 0) + sig.c = c_prev; // c_0 + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r[i] * c_point_G + c_prev * W_pub_keys[i]); + hsc.add_point(sig.r[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image); + c_prev = hsc.calc_hash(); // c_{i + 1} + } + + if (secret_index == 0) + sig.c = c_prev; + + sig.r[secret_index] = alpha - c_prev * w_sec_key; + + return true; + } + + + + bool verify_CLSAG_GG(const hash& m, const std::vector& ring, const crypto::public_key& pseudo_out_amount_commitment, const key_image& ki, + const CLSAG_GG_signature& sig) + { + DBG_PRINT("verify_CLSAG_GG"); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(ring_size == sig.r.size(), "ring size != r size"); + + point_t key_image(ki); + CRYPTO_CHECK_AND_THROW_MES(key_image.is_in_main_subgroup(), "key image 0 does not belong to the main subgroup"); + + point_t pseudo_out_amount_commitment_pt(pseudo_out_amount_commitment); + pseudo_out_amount_commitment_pt.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(3 + 2 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + } + hsc.add_pub_key(pseudo_out_amount_commitment); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hash input_hash = hsc.calc_hash_no_reduce(); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + + // calculate aggregate pub keys + std::vector W_pub_keys; + W_pub_keys.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys.emplace_back(agg_coeff_0 * point_t(ring[i].stealth_address) + agg_coeff_1 * (point_t(ring[i].amount_commitment).modify_mul8() - pseudo_out_amount_commitment_pt)); + DBG_VAL_PRINT(W_pub_keys[i]); + } + + // calculate aggregate key image + point_t W_key_image = agg_coeff_0 * key_image + agg_coeff_1 * point_t(sig.K1).modify_mul8(); + DBG_VAL_PRINT(W_key_image); + + scalar_t c_prev = sig.c; + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r[i] * c_point_G + c_prev * W_pub_keys[i]); + hsc.add_point(sig.r[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image); + c_prev = hsc.calc_hash(); // c_{i + 1} + } + + return c_prev == sig.c; + } + + + //--------------------------------------------------------------- + + // + // Disclaimer: extensions to the CLSAG implemented below are non-standard and are in proof-of-concept state. + // They shouldn't be used in production code until formal security proofs are done and (ideally) the code is peer-reviewed. + // -- sowle + // + + + bool generate_CLSAG_GGX(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_blinded_asset_id, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_t, uint64_t secret_index, CLSAG_GGX_signature& sig) + { + DBG_PRINT("== generate_CLSAG_GGX =="); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(secret_index < ring_size, "secret_index is out of range"); + + // calculate key images + point_t ki_base = hash_helper_t::hp(ring[secret_index].stealth_address); + point_t key_image = secret_0_xp * ki_base; + +#ifndef NDEBUG + CRYPTO_CHECK_AND_THROW_MES(key_image == point_t(ki), "key image 0 mismatch"); + CRYPTO_CHECK_AND_THROW_MES((secret_0_xp * c_point_G).to_public_key() == ring[secret_index].stealth_address, "secret_0_xp mismatch"); + CRYPTO_CHECK_AND_THROW_MES( secret_1_f * c_point_G == 8 * point_t(ring[secret_index].amount_commitment) - pseudo_out_amount_commitment, "secret_1_f mismatch"); + CRYPTO_CHECK_AND_THROW_MES( secret_2_t * c_point_X == 8 * point_t(ring[secret_index].blinded_asset_id) - pseudo_out_blinded_asset_id, "secret_2_t mismatch"); +#endif + + point_t K1_div8 = (c_scalar_1div8 * secret_1_f) * ki_base; + K1_div8.to_public_key(sig.K1); + point_t K1 = K1_div8; + K1.modify_mul8(); + + point_t K2_div8 = (c_scalar_1div8 * secret_2_t) * ki_base; + K2_div8.to_public_key(sig.K2); + point_t K2 = K2_div8; + K2.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(4 + 3 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + hsc.add_pub_key(ring[i].blinded_asset_id); + DBG_PRINT("ring[" << i << "]: sa:" << ring[i].stealth_address << ", ac:" << ring[i].amount_commitment << ", baid:" << ring[i].blinded_asset_id); + } + hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment); + hsc.add_point(c_scalar_1div8 * pseudo_out_blinded_asset_id); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hash input_hash = hsc.calc_hash_no_reduce(); + DBG_VAL_PRINT(input_hash); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + // may we get rid of it? + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_2); + hsc.add_hash(input_hash); + scalar_t agg_coeff_2 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_2); + + // prepare A_i, Q_i + std::vector A_i, Q_i; + A_i.reserve(ring_size), Q_i.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + A_i.emplace_back(ring[i].amount_commitment); + A_i.back().modify_mul8(); + Q_i.emplace_back(ring[i].blinded_asset_id); + Q_i.back().modify_mul8(); + DBG_PRINT("A_i[" << i << "] = " << A_i[i] << " Q_i[" << i << "] = " << Q_i[i]); + } + + // calculate aggregate pub keys (layers 0, 1; G components) + std::vector W_pub_keys_g; + W_pub_keys_g.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_g.emplace_back( + agg_coeff_0 * point_t(ring[i].stealth_address) + + agg_coeff_1 * (A_i[i] - pseudo_out_amount_commitment) + ); + DBG_VAL_PRINT(W_pub_keys_g[i]); + } + + // calculate aggregate pub keys (layer 2; X component) + std::vector W_pub_keys_x; + W_pub_keys_x.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_x.emplace_back( + agg_coeff_2 * (Q_i[i] - pseudo_out_blinded_asset_id) + ); + DBG_VAL_PRINT(W_pub_keys_x[i]); + } + + // aggregate secret key (layers 0, 1; G component) + scalar_t w_sec_key_g = agg_coeff_0 * secret_0_xp + agg_coeff_1 * secret_1_f; + DBG_VAL_PRINT(w_sec_key_g * c_point_G); + + // aggregate secret key (layer 2; X component) + scalar_t w_sec_key_x = agg_coeff_2 * secret_2_t; + DBG_VAL_PRINT(w_sec_key_x * c_point_X); + + // calculate aggregate key image (layers 0, 1; G component) + point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1; + DBG_VAL_PRINT(key_image); + DBG_VAL_PRINT(K1); + DBG_VAL_PRINT(W_key_image_g); + + // calculate aggregate key image (layer 2; X component) + point_t W_key_image_x = agg_coeff_2 * K2; + DBG_VAL_PRINT(K2); + DBG_VAL_PRINT(W_key_image_x); + +#ifndef NDEBUG + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_g * c_point_G == W_pub_keys_g[secret_index], "aggregated secret G and pub key mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_g * hash_helper_t::hp(ring[secret_index].stealth_address) == W_key_image_g, "aggregated secret G and key image mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_x * c_point_X == W_pub_keys_x[secret_index], "aggregated secret X and pub key mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_x * hash_helper_t::hp(ring[secret_index].stealth_address) == W_key_image_x, "aggregated secret X and key image mismatch"); +#endif + + // initial commitment + scalar_t alpha_g = scalar_t::random(); // randomness for layers 0,1 + scalar_t alpha_x = scalar_t::random(); // randomness for layer 2 + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(alpha_g * c_point_G); + hsc.add_point(alpha_g * ki_base); + hsc.add_point(alpha_x * c_point_X); + hsc.add_point(alpha_x * ki_base); + //DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")"); + scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} + + sig.r_g.resize_and_make_random(ring_size); + sig.r_x.resize_and_make_random(ring_size); + + for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) + { + DBG_PRINT("c[" << i << "] = " << c_prev); + if (i == 0) + sig.c = c_prev; // c_0 + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i]); + hsc.add_point(sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g); + hsc.add_point(sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i]); + hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); + c_prev = hsc.calc_hash(); // c_{i + 1} + } + DBG_PRINT("c[" << secret_index << "] = " << c_prev); + + if (secret_index == 0) + sig.c = c_prev; + + sig.r_g[secret_index] = alpha_g - c_prev * w_sec_key_g; + sig.r_x[secret_index] = alpha_x - c_prev * w_sec_key_x; + + return true; + } + + bool verify_CLSAG_GGX(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, + const public_key& pseudo_out_blinded_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig) + { + DBG_PRINT("== verify_CLSAG_GGX =="); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(ring_size == sig.r_g.size(), "ring size != r_g size"); + CRYPTO_CHECK_AND_THROW_MES(ring_size == sig.r_x.size(), "ring size != r_x size"); + + point_t key_image(ki); + CRYPTO_CHECK_AND_THROW_MES(key_image.is_in_main_subgroup(), "key image 0 does not belong to the main subgroup"); + + point_t pseudo_out_amount_commitment_pt(pseudo_out_amount_commitment); + pseudo_out_amount_commitment_pt.modify_mul8(); + + point_t pseudo_out_blinded_asset_id_pt(pseudo_out_blinded_asset_id); + pseudo_out_blinded_asset_id_pt.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(4 + 3 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + hsc.add_pub_key(ring[i].blinded_asset_id); + DBG_PRINT("ring[" << i << "]: sa:" << ring[i].stealth_address << ", ac:" << ring[i].amount_commitment << ", baid:" << ring[i].blinded_asset_id); + } + hsc.add_pub_key(pseudo_out_amount_commitment); + hsc.add_pub_key(pseudo_out_blinded_asset_id); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hash input_hash = hsc.calc_hash_no_reduce(); + DBG_VAL_PRINT(input_hash); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + // may we get rid of it? + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_LAYER_2); + hsc.add_hash(input_hash); + scalar_t agg_coeff_2 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_2); + + // prepare A_i, Q_i + std::vector A_i, Q_i; + A_i.reserve(ring_size), Q_i.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + A_i.emplace_back(ring[i].amount_commitment); + A_i.back().modify_mul8(); + Q_i.emplace_back(ring[i].blinded_asset_id); + Q_i.back().modify_mul8(); + DBG_PRINT("A_i[" << i << "] = " << A_i[i] << " Q_i[" << i << "] = " << Q_i[i]); + } + + // calculate aggregate pub keys (layers 0, 1; G components) + std::vector W_pub_keys_g; + W_pub_keys_g.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_g.emplace_back( + agg_coeff_0 * point_t(ring[i].stealth_address) + + agg_coeff_1 * (A_i[i] - pseudo_out_amount_commitment_pt) + ); + DBG_VAL_PRINT(W_pub_keys_g[i]); + } + + // calculate aggregate pub keys (layer 2; X component) + std::vector W_pub_keys_x; + W_pub_keys_x.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_x.emplace_back( + agg_coeff_2 * (Q_i[i] - pseudo_out_blinded_asset_id_pt) + ); + DBG_VAL_PRINT(W_pub_keys_x[i]); + } + + // calculate aggregate key image (layers 0, 1; G components) + point_t W_key_image_g = + agg_coeff_0 * key_image + + agg_coeff_1 * point_t(sig.K1).modify_mul8(); + DBG_VAL_PRINT(point_t(sig.K1).modify_mul8()); + DBG_VAL_PRINT(W_key_image_g); + + // calculate aggregate key image (layer 2; X component) + point_t W_key_image_x = + agg_coeff_2 * point_t(sig.K2).modify_mul8(); + DBG_VAL_PRINT(point_t(sig.K2).modify_mul8()); + DBG_VAL_PRINT(W_key_image_x); + + + scalar_t c_prev = sig.c; + DBG_PRINT("c[0] = " << c_prev); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGX_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i]); + hsc.add_point(sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g); + hsc.add_point(sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i]); + hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); + c_prev = hsc.calc_hash(); // c_{i + 1} + DBG_PRINT("c[" << i + 1 << "] = " << c_prev); + //DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); + } + + return c_prev == sig.c; + } + + + //--------------------------------------------------------------- + /* + + bool generate_CLSAG_GGXG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& extended_amount_commitment, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_x, const scalar_t& secret_3_q, uint64_t secret_index, CLSAG_GGXG_signature& sig) + { + DBG_PRINT("== generate_CLSAG_GGXG =="); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(secret_index < ring_size, "secret_index is out of range"); + + // calculate key images + point_t ki_base = hash_helper_t::hp(ring[secret_index].stealth_address); + point_t key_image = secret_0_xp * ki_base; + +#ifndef NDEBUG + CRYPTO_CHECK_AND_THROW_MES(key_image == point_t(ki), "key image 0 mismatch"); + CRYPTO_CHECK_AND_THROW_MES((secret_0_xp * c_point_G).to_public_key() == ring[secret_index].stealth_address, "secret_0_xp mismatch"); + CRYPTO_CHECK_AND_THROW_MES(secret_1_f * c_point_G == 8 * point_t(ring[secret_index].amount_commitment) - pseudo_out_amount_commitment, "secret_1_f mismatch"); + CRYPTO_CHECK_AND_THROW_MES(secret_3_q * c_point_G == 8 * point_t(ring[secret_index].concealing_point), "secret_3_q mismatch"); + CRYPTO_CHECK_AND_THROW_MES(secret_2_x * c_point_X == extended_amount_commitment - 8 * point_t(ring[secret_index].amount_commitment) - 8 * point_t(ring[secret_index].concealing_point), "secret_2_x mismatch"); +#endif + + point_t K1_div8 = (c_scalar_1div8 * secret_1_f) * ki_base; + K1_div8.to_public_key(sig.K1); + point_t K1 = K1_div8; + K1.modify_mul8(); + + point_t K2_div8 = (c_scalar_1div8 * secret_2_x) * ki_base; + K2_div8.to_public_key(sig.K2); + point_t K2 = K2_div8; + K2.modify_mul8(); + + point_t K3_div8 = (c_scalar_1div8 * secret_3_q) * ki_base; + K3_div8.to_public_key(sig.K3); + point_t K3 = K3_div8; + K3.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(4 + 3 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + hsc.add_pub_key(ring[i].concealing_point); + DBG_PRINT("ring[" << i << "]: sa:" << ring[i].stealth_address << ", ac:" << ring[i].amount_commitment << ", cp:" << ring[i].concealing_point); + } + hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment); + hsc.add_point(c_scalar_1div8 * extended_amount_commitment); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); + hash input_hash = hsc.calc_hash_no_reduce(); + DBG_VAL_PRINT(input_hash); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + // may we get rid of it? + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_2); + hsc.add_hash(input_hash); + scalar_t agg_coeff_2 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_2); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_3); + hsc.add_hash(input_hash); + scalar_t agg_coeff_3 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_3); + + // prepare A_i, Q_i + std::vector A_i, Q_i; + A_i.reserve(ring_size), Q_i.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + A_i.emplace_back(ring[i].amount_commitment); + A_i.back().modify_mul8(); + Q_i.emplace_back(ring[i].concealing_point); + Q_i.back().modify_mul8(); + DBG_PRINT("A_i[" << i << "] = " << A_i[i] << " Q_i[" << i << "] = " << Q_i[i]); + } + + // calculate aggregate pub keys (layers 0, 1, 3; G components) + std::vector W_pub_keys_g; + W_pub_keys_g.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_g.emplace_back( + agg_coeff_0 * point_t(ring[i].stealth_address) + + agg_coeff_1 * (A_i[i] - pseudo_out_amount_commitment) + + agg_coeff_3 * Q_i[i] + ); + DBG_VAL_PRINT(W_pub_keys_g[i]); + } + + // calculate aggregate pub keys (layer 2; X component) + std::vector W_pub_keys_x; + W_pub_keys_x.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_x.emplace_back( + agg_coeff_2 * (extended_amount_commitment - A_i[i] - Q_i[i]) + ); + DBG_VAL_PRINT(W_pub_keys_x[i]); + } + + // aggregate secret key (layers 0, 1, 3; G component) + scalar_t w_sec_key_g = agg_coeff_0 * secret_0_xp + agg_coeff_1 * secret_1_f + agg_coeff_3 * secret_3_q; + DBG_VAL_PRINT(w_sec_key_g * c_point_G); + + // aggregate secret key (layer 2; X component) + scalar_t w_sec_key_x = agg_coeff_2 * secret_2_x; + DBG_VAL_PRINT(w_sec_key_x * c_point_X); + + // calculate aggregate key image (layers 0, 1, 3; G component) + point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 + agg_coeff_3 * K3; + DBG_VAL_PRINT(key_image); + DBG_VAL_PRINT(K1); + DBG_VAL_PRINT(K3); + DBG_VAL_PRINT(W_key_image_g); + + // calculate aggregate key image (layer 2; X component) + point_t W_key_image_x = agg_coeff_2 * K2; + DBG_VAL_PRINT(K2); + DBG_VAL_PRINT(W_key_image_x); + +#ifndef NDEBUG + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_g * c_point_G == W_pub_keys_g[secret_index], "aggregated secret G and pub key mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_g * hash_helper_t::hp(ring[secret_index].stealth_address) == W_key_image_g, "aggregated secret G and key image mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_x * c_point_X == W_pub_keys_x[secret_index], "aggregated secret X and pub key mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_x * hash_helper_t::hp(ring[secret_index].stealth_address) == W_key_image_x, "aggregated secret X and key image mismatch"); +#endif + + // initial commitment + scalar_t alpha_g = scalar_t::random(); // randomness for layers 0,1,3 + scalar_t alpha_x = scalar_t::random(); // randomness for layer 2 + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(alpha_g * c_point_G); + hsc.add_point(alpha_g * ki_base); + hsc.add_point(alpha_x * c_point_X); + hsc.add_point(alpha_x * ki_base); + //DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")"); + scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} + + sig.r_g.resize_and_make_random(ring_size); + sig.r_x.resize_and_make_random(ring_size); + + for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) + { + DBG_PRINT("c[" << i << "] = " << c_prev); + if (i == 0) + sig.c = c_prev; // c_0 + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i]); + hsc.add_point(sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g); + hsc.add_point(sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i]); + hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); + c_prev = hsc.calc_hash(); // c_{i + 1} + } + DBG_PRINT("c[" << secret_index << "] = " << c_prev); + + if (secret_index == 0) + sig.c = c_prev; + + sig.r_g[secret_index] = alpha_g - c_prev * w_sec_key_g; + sig.r_x[secret_index] = alpha_x - c_prev * w_sec_key_x; + + return true; + } + + + bool verify_CLSAG_GGXG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, const public_key& extended_amount_commitment, + const key_image& ki, const CLSAG_GGXG_signature& sig) + { + DBG_PRINT("== verify_CLSAG_GGXG =="); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(ring_size == sig.r_g.size(), "ring size != r_g size"); + CRYPTO_CHECK_AND_THROW_MES(ring_size == sig.r_x.size(), "ring size != r_x size"); + + point_t key_image(ki); + CRYPTO_CHECK_AND_THROW_MES(key_image.is_in_main_subgroup(), "key image 0 does not belong to the main subgroup"); + + point_t pseudo_out_amount_commitment_pt(pseudo_out_amount_commitment); + pseudo_out_amount_commitment_pt.modify_mul8(); + + point_t extended_amount_commitment_pt(extended_amount_commitment); + extended_amount_commitment_pt.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(4 + 3 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + hsc.add_pub_key(ring[i].concealing_point); + DBG_PRINT("ring[" << i << "]: sa:" << ring[i].stealth_address << ", ac:" << ring[i].amount_commitment << ", cp:" << ring[i].concealing_point); + } + hsc.add_pub_key(pseudo_out_amount_commitment); + hsc.add_pub_key(extended_amount_commitment); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); + hash input_hash = hsc.calc_hash_no_reduce(); + DBG_VAL_PRINT(input_hash); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + // may we get rid of it? + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_2); + hsc.add_hash(input_hash); + scalar_t agg_coeff_2 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_2); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_LAYER_3); + hsc.add_hash(input_hash); + scalar_t agg_coeff_3 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_3); + + // prepare A_i, Q_i + std::vector A_i, Q_i; + A_i.reserve(ring_size), Q_i.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + A_i.emplace_back(ring[i].amount_commitment); + A_i.back().modify_mul8(); + Q_i.emplace_back(ring[i].concealing_point); + Q_i.back().modify_mul8(); + DBG_PRINT("A_i[" << i << "] = " << A_i[i] << " Q_i[" << i << "] = " << Q_i[i]); + } + + // calculate aggregate pub keys (layers 0, 1, 3; G components) + std::vector W_pub_keys_g; + W_pub_keys_g.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_g.emplace_back( + agg_coeff_0 * point_t(ring[i].stealth_address) + + agg_coeff_1 * (A_i[i] - pseudo_out_amount_commitment_pt) + + agg_coeff_3 * Q_i[i] + ); + DBG_VAL_PRINT(W_pub_keys_g[i]); + } + + // calculate aggregate pub keys (layer 2; X component) + std::vector W_pub_keys_x; + W_pub_keys_x.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_x.emplace_back( + agg_coeff_2 * (extended_amount_commitment_pt - A_i[i] - Q_i[i]) + ); + DBG_VAL_PRINT(W_pub_keys_x[i]); + } + + // calculate aggregate key image (layers 0, 1, 3; G components) + point_t W_key_image_g = + agg_coeff_0 * key_image + + agg_coeff_1 * point_t(sig.K1).modify_mul8() + + agg_coeff_3 * point_t(sig.K3).modify_mul8(); + DBG_VAL_PRINT(point_t(sig.K1).modify_mul8()); + DBG_VAL_PRINT(point_t(sig.K3).modify_mul8()); + DBG_VAL_PRINT(W_key_image_g); + + // calculate aggregate key image (layer 2; X component) + point_t W_key_image_x = + agg_coeff_2 * point_t(sig.K2).modify_mul8(); + DBG_VAL_PRINT(point_t(sig.K2).modify_mul8()); + DBG_VAL_PRINT(W_key_image_x); + + + scalar_t c_prev = sig.c; + DBG_PRINT("c[0] = " << c_prev); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i]); + hsc.add_point(sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g); + hsc.add_point(sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i]); + hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); + c_prev = hsc.calc_hash(); // c_{i + 1} + DBG_PRINT("c[" << i + 1 << "] = " << c_prev); + //DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); + } + + return c_prev == sig.c; + } + + */ + //--------------------------------------------------------------- + + + bool generate_CLSAG_GGXXG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_blinded_asset_id, const point_t& extended_amount_commitment, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_t, const scalar_t& secret_3_x, const scalar_t& secret_4_q, uint64_t secret_index, + CLSAG_GGXXG_signature& sig) + { + DBG_PRINT("== generate_CLSAG_GGXXG =="); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(secret_index < ring_size, "secret_index is out of range"); + + // calculate key images + point_t ki_base = hash_helper_t::hp(ring[secret_index].stealth_address); + point_t key_image = secret_0_xp * ki_base; + +#ifndef NDEBUG + CRYPTO_CHECK_AND_THROW_MES(key_image == point_t(ki), "key image 0 mismatch"); + CRYPTO_CHECK_AND_THROW_MES((secret_0_xp * c_point_G).to_public_key() == ring[secret_index].stealth_address, "secret_0_xp mismatch"); + CRYPTO_CHECK_AND_THROW_MES( secret_1_f * c_point_G == 8 * point_t(ring[secret_index].amount_commitment) - pseudo_out_amount_commitment, "secret_1_f mismatch"); + CRYPTO_CHECK_AND_THROW_MES( secret_2_t * c_point_X == 8 * point_t(ring[secret_index].blinded_asset_id) - pseudo_out_blinded_asset_id, "secret_2_t mismatch"); + CRYPTO_CHECK_AND_THROW_MES( secret_3_x * c_point_X == extended_amount_commitment - 8 * point_t(ring[secret_index].amount_commitment) - 8 * point_t(ring[secret_index].concealing_point), ""); + CRYPTO_CHECK_AND_THROW_MES( secret_4_q * c_point_G == 8 * point_t(ring[secret_index].concealing_point), "secret_3_q mismatch"); +#endif + + point_t K1_div8 = (c_scalar_1div8 * secret_1_f) * ki_base; + K1_div8.to_public_key(sig.K1); + point_t K1 = K1_div8; + K1.modify_mul8(); + + point_t K2_div8 = (c_scalar_1div8 * secret_2_t) * ki_base; + K2_div8.to_public_key(sig.K2); + point_t K2 = K2_div8; + K2.modify_mul8(); + + point_t K3_div8 = (c_scalar_1div8 * secret_3_x) * ki_base; + K3_div8.to_public_key(sig.K3); + point_t K3 = K3_div8; + K3.modify_mul8(); + + point_t K4_div8 = (c_scalar_1div8 * secret_4_q) * ki_base; + K4_div8.to_public_key(sig.K4); + point_t K4 = K4_div8; + K4.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(5 + 4 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + hsc.add_pub_key(ring[i].blinded_asset_id); + hsc.add_pub_key(ring[i].concealing_point); + DBG_PRINT("ring[" << i << "]: sa:" << ring[i].stealth_address << ", ac:" << ring[i].amount_commitment << ", baid:" << ring[i].blinded_asset_id << ", cp:" << ring[i].concealing_point); + } + hsc.add_point(c_scalar_1div8 * pseudo_out_amount_commitment); + hsc.add_point(c_scalar_1div8 * pseudo_out_blinded_asset_id); + hsc.add_point(c_scalar_1div8 * extended_amount_commitment); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); + hsc.add_pub_key(sig.K4); + hash input_hash = hsc.calc_hash_no_reduce(); + DBG_VAL_PRINT(input_hash); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + // may we get rid of it? + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_2); + hsc.add_hash(input_hash); + scalar_t agg_coeff_2 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_2); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_3); + hsc.add_hash(input_hash); + scalar_t agg_coeff_3 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_3); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_4); + hsc.add_hash(input_hash); + scalar_t agg_coeff_4 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_4); + + // prepare A_i, Q_i + std::vector A_i, P_i, Q_i; + A_i.reserve(ring_size), P_i.reserve(ring_size), Q_i.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + A_i.emplace_back(ring[i].amount_commitment); + A_i.back().modify_mul8(); + P_i.emplace_back(ring[i].blinded_asset_id); + P_i.back().modify_mul8(); + Q_i.emplace_back(ring[i].concealing_point); + Q_i.back().modify_mul8(); + DBG_PRINT("A_i[" << i << "] = " << A_i[i] << " P_i[" << i << "] = " << P_i[i] << " Q_i[" << i << "] = " << Q_i[i]); + } + + // calculate aggregate pub keys (layers 0, 1, 4; G components) + std::vector W_pub_keys_g; + W_pub_keys_g.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_g.emplace_back( + agg_coeff_0 * point_t(ring[i].stealth_address) + + agg_coeff_1 * (A_i[i] - pseudo_out_amount_commitment) + + agg_coeff_4 * Q_i[i] + ); + DBG_VAL_PRINT(W_pub_keys_g[i]); + } + + // calculate aggregate pub keys (layerx 2, 3; X component) + std::vector W_pub_keys_x; + W_pub_keys_x.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_x.emplace_back( + agg_coeff_2 * (P_i[i] - pseudo_out_blinded_asset_id) + + agg_coeff_3 * (extended_amount_commitment - A_i[i] - Q_i[i]) + ); + DBG_VAL_PRINT(W_pub_keys_x[i]); + } + + // aggregate secret key (layers 0, 1, 4; G component) + scalar_t w_sec_key_g = agg_coeff_0 * secret_0_xp + agg_coeff_1 * secret_1_f + agg_coeff_4 * secret_4_q; + DBG_VAL_PRINT(w_sec_key_g * c_point_G); + + // aggregate secret key (layer 2, 3; X component) + scalar_t w_sec_key_x = agg_coeff_2 * secret_2_t + agg_coeff_3 * secret_3_x; + DBG_VAL_PRINT(w_sec_key_x * c_point_X); + + // calculate aggregate key image (layers 0, 1, 4; G component) + point_t W_key_image_g = agg_coeff_0 * key_image + agg_coeff_1 * K1 + agg_coeff_4 * K4; + DBG_VAL_PRINT(key_image); + DBG_VAL_PRINT(K1); + DBG_VAL_PRINT(K4); + DBG_VAL_PRINT(W_key_image_g); + + // calculate aggregate key image (layer 2, 3; X component) + point_t W_key_image_x = agg_coeff_2 * K2 + agg_coeff_3 * K3; + DBG_VAL_PRINT(K2); + DBG_VAL_PRINT(K3); + DBG_VAL_PRINT(W_key_image_x); + +#ifndef NDEBUG + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_g * c_point_G == W_pub_keys_g[secret_index], "aggregated secret G and pub key mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_g * hash_helper_t::hp(ring[secret_index].stealth_address) == W_key_image_g, "aggregated secret G and key image mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_x * c_point_X == W_pub_keys_x[secret_index], "aggregated secret X and pub key mismatch"); + CRYPTO_CHECK_AND_THROW_MES(w_sec_key_x * hash_helper_t::hp(ring[secret_index].stealth_address) == W_key_image_x, "aggregated secret X and key image mismatch"); +#endif + + // initial commitment + scalar_t alpha_g = scalar_t::random(); // randomness for layers 0,1,4 + scalar_t alpha_x = scalar_t::random(); // randomness for layer 2,3 + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(alpha_g * c_point_G); + hsc.add_point(alpha_g * ki_base); + hsc.add_point(alpha_x * c_point_X); + hsc.add_point(alpha_x * ki_base); + //DBG_PRINT("c[" << secret_index << "] = Hs(ih, " << alpha_g * c_point_G << ", " << alpha_g * ki_base << ", " << alpha_x * c_point_X << ", " << alpha_x * ki_base << ")"); + scalar_t c_prev = hsc.calc_hash(); // c_{secret_index + 1} + + sig.r_g.resize_and_make_random(ring_size); + sig.r_x.resize_and_make_random(ring_size); + + for(size_t j = 0, i = (secret_index + 1) % ring_size; j < ring_size - 1; ++j, i = (i + 1) % ring_size) + { + DBG_PRINT("c[" << i << "] = " << c_prev); + if (i == 0) + sig.c = c_prev; // c_0 + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i]); + hsc.add_point(sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g); + hsc.add_point(sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i]); + hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); + c_prev = hsc.calc_hash(); // c_{i + 1} + //DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); + } + DBG_PRINT("c[" << secret_index << "] = " << c_prev); + + + if (secret_index == 0) + sig.c = c_prev; + + sig.r_g[secret_index] = alpha_g - c_prev * w_sec_key_g; + sig.r_x[secret_index] = alpha_x - c_prev * w_sec_key_x; + + return true; + } + + bool verify_CLSAG_GGXXG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, const public_key& pseudo_out_blinded_asset_id, const public_key& extended_amount_commitment, const key_image& ki, + const CLSAG_GGXXG_signature& sig) + { + DBG_PRINT("== verify_CLSAG_GGXXG =="); + size_t ring_size = ring.size(); + CRYPTO_CHECK_AND_THROW_MES(ring_size > 0, "ring size is zero"); + CRYPTO_CHECK_AND_THROW_MES(ring_size == sig.r_g.size(), "ring size != r_g size"); + CRYPTO_CHECK_AND_THROW_MES(ring_size == sig.r_x.size(), "ring size != r_x size"); + + point_t key_image(ki); + CRYPTO_CHECK_AND_THROW_MES(key_image.is_in_main_subgroup(), "key image 0 does not belong to the main subgroup"); + + point_t pseudo_out_amount_commitment_pt(pseudo_out_amount_commitment); + pseudo_out_amount_commitment_pt.modify_mul8(); + + point_t pseudo_out_blinded_asset_id_pt(pseudo_out_blinded_asset_id); + pseudo_out_blinded_asset_id_pt.modify_mul8(); + + point_t extended_amount_commitment_pt(extended_amount_commitment); + extended_amount_commitment_pt.modify_mul8(); + + // calculate aggregation coefficients + hash_helper_t::hs_t hsc(5 + 4 * ring_size); + hsc.add_scalar(m); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_pub_key(ring[i].stealth_address); + hsc.add_pub_key(ring[i].amount_commitment); + hsc.add_pub_key(ring[i].blinded_asset_id); + hsc.add_pub_key(ring[i].concealing_point); + DBG_PRINT("ring[" << i << "]: sa:" << ring[i].stealth_address << ", ac:" << ring[i].amount_commitment << ", baid:" << ring[i].blinded_asset_id << ", cp:" << ring[i].concealing_point); + } + hsc.add_pub_key(pseudo_out_amount_commitment); + hsc.add_pub_key(pseudo_out_blinded_asset_id); + hsc.add_pub_key(extended_amount_commitment); + hsc.add_key_image(ki); + hsc.add_pub_key(sig.K1); + hsc.add_pub_key(sig.K2); + hsc.add_pub_key(sig.K3); + hsc.add_pub_key(sig.K4); + hash input_hash = hsc.calc_hash_no_reduce(); + DBG_VAL_PRINT(input_hash); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_0); + hsc.add_hash(input_hash); + scalar_t agg_coeff_0 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_0); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_1); + hsc.add_hash(input_hash); + scalar_t agg_coeff_1 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_1); + + // may we get rid of it? + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_2); + hsc.add_hash(input_hash); + scalar_t agg_coeff_2 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_2); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_3); + hsc.add_hash(input_hash); + scalar_t agg_coeff_3 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_3); + + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_LAYER_4); + hsc.add_hash(input_hash); + scalar_t agg_coeff_4 = hsc.calc_hash(); + DBG_VAL_PRINT(agg_coeff_4); + + // prepare A_i, Q_i + std::vector A_i, P_i, Q_i; + A_i.reserve(ring_size), P_i.reserve(ring_size), Q_i.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + A_i.emplace_back(ring[i].amount_commitment); + A_i.back().modify_mul8(); + P_i.emplace_back(ring[i].blinded_asset_id); + P_i.back().modify_mul8(); + Q_i.emplace_back(ring[i].concealing_point); + Q_i.back().modify_mul8(); + DBG_PRINT("A_i[" << i << "] = " << A_i[i] << " P_i[" << i << "] = " << P_i[i] << " Q_i[" << i << "] = " << Q_i[i]); + } + + // calculate aggregate pub keys (layers 0, 1, 4; G components) + std::vector W_pub_keys_g; + W_pub_keys_g.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_g.emplace_back( + agg_coeff_0 * point_t(ring[i].stealth_address) + + agg_coeff_1 * (A_i[i] - pseudo_out_amount_commitment_pt) + + agg_coeff_4 * Q_i[i] + ); + DBG_VAL_PRINT(W_pub_keys_g[i]); + } + + // calculate aggregate pub keys (layer 2, 3; X component) + std::vector W_pub_keys_x; + W_pub_keys_x.reserve(ring_size); + for(size_t i = 0; i < ring_size; ++i) + { + W_pub_keys_x.emplace_back( + agg_coeff_2 * (P_i[i] - pseudo_out_blinded_asset_id_pt) + + agg_coeff_3 * (extended_amount_commitment_pt - A_i[i] - Q_i[i]) + ); + DBG_VAL_PRINT(W_pub_keys_x[i]); + } + + DBG_VAL_PRINT(point_t(ki)); + + // calculate aggregate key image (layers 0, 1, 4; G components) + DBG_VAL_PRINT(point_t(sig.K1).modify_mul8()); + point_t W_key_image_g = + agg_coeff_0 * key_image + + agg_coeff_1 * point_t(sig.K1).modify_mul8() + + agg_coeff_4 * point_t(sig.K4).modify_mul8(); + DBG_VAL_PRINT(point_t(sig.K1).modify_mul8()); + DBG_VAL_PRINT(point_t(sig.K4).modify_mul8()); + DBG_VAL_PRINT(W_key_image_g); + + // calculate aggregate key image (layer 2, 3; X component) + point_t W_key_image_x = + agg_coeff_2 * point_t(sig.K2).modify_mul8() + + agg_coeff_3 * point_t(sig.K3).modify_mul8(); + DBG_VAL_PRINT(point_t(sig.K2).modify_mul8()); + DBG_VAL_PRINT(point_t(sig.K3).modify_mul8()); + DBG_VAL_PRINT(W_key_image_x); + + + scalar_t c_prev = sig.c; + DBG_PRINT("c[0] = " << c_prev); + for(size_t i = 0; i < ring_size; ++i) + { + hsc.add_32_chars(CRYPTO_HDS_CLSAG_GGXXG_CHALLENGE); + hsc.add_hash(input_hash); + hsc.add_point(sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i]); + hsc.add_point(sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g); + hsc.add_point(sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i]); + hsc.add_point(sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x); + c_prev = hsc.calc_hash(); // c_{i + 1} + DBG_PRINT("c[" << i + 1 << "] = " << c_prev); + //DBG_PRINT("c[" << i + 1 << "] = Hs(ih, " << sig.r_g[i] * c_point_G + c_prev * W_pub_keys_g[i] << ", " << sig.r_g[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_g << ", " << sig.r_x[i] * c_point_X + c_prev * W_pub_keys_x[i] << ", " << sig.r_x[i] * hash_helper_t::hp(ring[i].stealth_address) + c_prev * W_key_image_x << ")"); + } + + return c_prev == sig.c; + } + + + +} // namespace crypto diff --git a/crypto/upstream/clsag.h b/crypto/upstream/clsag.h new file mode 100755 index 0000000..018eb8d --- /dev/null +++ b/crypto/upstream/clsag.h @@ -0,0 +1,187 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once +#include "crypto-sugar.h" + +namespace crypto +{ + // 2-CLSAG signature where both dimensions are with respect to the group element G (that's why 'GG') + struct CLSAG_GG_signature + { + scalar_t c; + scalar_vec_t r; // size = size of the ring + public_key K1; // auxiliary key image for layer 1 + }; + + + inline bool operator==(const CLSAG_GG_signature& lhs, const CLSAG_GG_signature& rhs) + { + return + lhs.c == rhs.c && + lhs.r == rhs.r && + lhs.K1 == rhs.K1; + } + + inline bool operator!=(const CLSAG_GG_signature& lhs, const CLSAG_GG_signature& rhs) { return !(lhs == rhs); } + + struct CLSAG_GG_input_ref_t + { + CLSAG_GG_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment) + : stealth_address(stealth_address), amount_commitment(amount_commitment) + {} + + const public_key& stealth_address; // P, not premultiplied by 1/8, TODO @#@#: make sure it's okay + const public_key& amount_commitment; // A, premultiplied by 1/8 + }; + + // pseudo_out_amount_commitment -- not premultiplied by 1/8 + bool generate_CLSAG_GG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const key_image& ki, + const scalar_t& secret_x, const scalar_t& secret_f, uint64_t secret_index, CLSAG_GG_signature& sig); + + // pseudo_out_amount_commitment -- premultiplied by 1/8 + bool verify_CLSAG_GG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, const key_image& ki, + const CLSAG_GG_signature& sig); + + + // + // d/v-CLSAG implementation + // See the whitepaper: https://hyle-team.github.io/docs/zano/dv-CLSAG-extension/dv-CLSAG-extension.pdf + // Review by Cypher Stack: https://github.com/cypherstack/zano-clsag-review + // -- sowle + // + + + + // + // 3/2-CLSAG + // + + + // 3/2-CLSAG signature (with respect to the group element G, G, X -- that's why 'GGX') + struct CLSAG_GGX_signature + { + scalar_t c; + scalar_vec_t r_g; // for G-components (layers 0, 1), size = size of the ring + scalar_vec_t r_x; // for X-component (layer 2), size = size of the ring + public_key K1; // auxiliary key image for layer 1 (G) + public_key K2; // auxiliary key image for layer 2 (X) + }; + + struct CLSAG_GGX_input_ref_t : public CLSAG_GG_input_ref_t + { + CLSAG_GGX_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment, const public_key& blinded_asset_id) + : CLSAG_GG_input_ref_t(stealth_address, amount_commitment) + , blinded_asset_id(blinded_asset_id) + {} + + const public_key& blinded_asset_id; // T, premultiplied by 1/8 + }; + + // pseudo_out_amount_commitment -- not premultiplied by 1/8 + // pseudo_out_asset_id -- not premultiplied by 1/8 + bool generate_CLSAG_GGX(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_asset_id, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_t, uint64_t secret_index, CLSAG_GGX_signature& sig); + + // pseudo_out_amount_commitment -- premultiplied by 1/8 + // pseudo_out_asset_id -- premultiplied by 1/8 + // may throw an exception TODO @#@# make sure it's okay + bool verify_CLSAG_GGX(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, + const public_key& pseudo_out_asset_id, const key_image& ki, const CLSAG_GGX_signature& sig); + + + /* + // + // 4/2-CLSAG (eventually, it's not used in Zano) + // + + + // 4/2-CLSAG signature (with respect to the group element G, G, X, G -- that's why 'GGXG') + struct CLSAG_GGXG_signature + { + scalar_t c; + scalar_vec_t r_g; // for G-components (layers 0, 1, 3), size = size of the ring + scalar_vec_t r_x; // for X-component (layer 2), size = size of the ring + public_key K1; // auxiliary key image for layer 1 (G) + public_key K2; // auxiliary key image for layer 2 (X) + public_key K3; // auxiliary key image for layer 3 (G) + }; + + struct CLSAG_GGXG_input_ref_t : public CLSAG_GG_input_ref_t + { + CLSAG_GGXG_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment, const public_key& concealing_point) + : CLSAG_GG_input_ref_t(stealth_address, amount_commitment) + , concealing_point(concealing_point) + {} + + const public_key& concealing_point; // Q, premultiplied by 1/8 + }; + + // pseudo_out_amount_commitment -- not premultiplied by 1/8 + // extended_amount_commitment -- not premultiplied by 1/8 + bool generate_CLSAG_GGXG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& extended_amount_commitment, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_x, const scalar_t& secret_3_q, uint64_t secret_index, CLSAG_GGXG_signature& sig); + + // pseudo_out_amount_commitment -- premultiplied by 1/8 + // extended_amount_commitment -- premultiplied by 1/8 + // may throw an exception TODO @#@# make sure it's okay + bool verify_CLSAG_GGXG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, + const public_key& extended_amount_commitment, const key_image& ki, const CLSAG_GGXG_signature& sig); + + */ + + // + // 5/2-CLSAG + // + + + // 5/2-CLSAG signature (with respect to the group element G, G, X, X, G -- that's why 'GGXXG') + struct CLSAG_GGXXG_signature + { + scalar_t c; + scalar_vec_t r_g; // for G-components (layers 0, 1, 4), size = size of the ring + scalar_vec_t r_x; // for X-component (layers 2, 3), size = size of the ring + public_key K1; // auxiliary key image for layer 1 (G) + public_key K2; // auxiliary key image for layer 2 (X) + public_key K3; // auxiliary key image for layer 2 (X) + public_key K4; // auxiliary key image for layer 3 (G) + }; + + struct CLSAG_GGXXG_input_ref_t : public CLSAG_GGX_input_ref_t + { + CLSAG_GGXXG_input_ref_t(const public_key& stealth_address, const public_key& amount_commitment, const public_key& blinded_asset_id, const public_key& concealing_point) + : CLSAG_GGX_input_ref_t(stealth_address, amount_commitment, blinded_asset_id) + , concealing_point(concealing_point) + {} + + const public_key& concealing_point; // Q, premultiplied by 1/8 + }; + + // pseudo_out_amount_commitment -- not premultiplied by 1/8 + // pseudo_out_asset_id -- not premultiplied by 1/8 + // extended_amount_commitment -- not premultiplied by 1/8 + bool generate_CLSAG_GGXXG(const hash& m, const std::vector& ring, const point_t& pseudo_out_amount_commitment, const point_t& pseudo_out_blinded_asset_id, const point_t& extended_amount_commitment, const key_image& ki, + const scalar_t& secret_0_xp, const scalar_t& secret_1_f, const scalar_t& secret_2_r, const scalar_t& secret_3_x, const scalar_t& secret_4_q, uint64_t secret_index, CLSAG_GGXXG_signature& sig); + + // pseudo_out_amount_commitment -- premultiplied by 1/8 + // pseudo_out_asset_id -- premultiplied by 1/8 + // extended_amount_commitment -- premultiplied by 1/8 + // may throw an exception TODO @#@# make sure it's okay + bool verify_CLSAG_GGXXG(const hash& m, const std::vector& ring, const public_key& pseudo_out_amount_commitment, const public_key& pseudo_out_blinded_asset_id, const public_key& extended_amount_commitment, const key_image& ki, + const CLSAG_GGXXG_signature& sig); + + +} // namespace crypto diff --git a/crypto/upstream/crypto-ops-data.c b/crypto/upstream/crypto-ops-data.c new file mode 100755 index 0000000..d5aebb5 --- /dev/null +++ b/crypto/upstream/crypto-ops-data.c @@ -0,0 +1,859 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#include + +#include "crypto-ops.h" + +/* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */ +/* d = -121665 / 121666 */ +const fe fe_d = {-10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116}; /* d */ +const fe fe_sqrtm1 = {-32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482}; /* sqrt(-1) */ +const fe fe_d2 = {-21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199}; /* 2 * d */ + +/* base[i][j] = (j+1)*256^i*B */ +const ge_precomp ge_base[32][8] = { + { + {{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, + {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, + {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}}, + {{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717, -11717903, -3814571, -358445, -10211303}, + {-21703237, 6903825, 27185491, 6451973, -29577724, -9554005, -15616551, 11189268, -26829678, -5319081}, + {26966642, 11152617, 32442495, 15396054, 14353839, -12752335, -3128826, -9541118, -15472047, -4166697}}, + {{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, + {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, + {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}}, + {{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379, -28926210, 15006023, 3284568, -6276540}, + {23599295, -8306047, -11193664, -7687416, 13236774, 10506355, 7464579, 9656445, 13059162, 10374397}, + {7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664, -3839045, -641708, -101325}}, + {{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, + {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, + {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}}, + {{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511, -19188627, -15224819, -9818940, -12085777}, + {-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240, -15689887, 1762328, 14866737}, + {-18199695, -15951423, -10473290, 1707278, -17185920, 3916101, -28236412, 3959421, 27914454, 4383652}}, + {{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, + {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, + {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}}, + {{14499471, -2729599, -33191113, -4254652, 28494862, 14271267, 30290735, 10876454, -33154098, 2381726}, + {-7195431, -2655363, -14730155, 462251, -27724326, 3941372, -6236617, 3696005, -32300832, 15351955}, + {27431194, 8222322, 16448760, -3907995, -18707002, 11938355, -32961401, -2970515, 29551813, 10109425}} + }, { + {{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384, -2378284, -1627556, 10092783, -4764171}, + {27939166, 14210322, 4677035, 16277044, -22964462, -12398139, -32508754, 12005538, -17810127, 12803510}, + {17228999, -15661624, -1233527, 300140, -1224870, -11714777, 30364213, -9038194, 18016357, 4397660}}, + {{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212, -26619106, 14544525, -17477504, 982639}, + {29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899, -4120128, -21047696, 9934963}, + {5793303, 16271923, -24131614, -10116404, 29188560, 1206517, -14747930, 4559895, -30123922, -10897950}}, + {{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264, 24191034, 4541697, -13338309, 5500568}, + {12650548, -1497113, 9052871, 11355358, -17680037, -8400164, -17430592, 12264343, 10874051, 13524335}, + {25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038, 5080568, -22528059, 5376628}}, + {{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897, -22321305, -9447443, 4535768, 1569007}, + {-2255422, 14606630, -21692440, -8039818, 28430649, 8775819, -30494562, 3044290, 31848280, 12543772}, + {-22028579, 2943893, -31857513, 6777306, 13784462, -4292203, -27377195, -2062731, 7718482, 14474653}}, + {{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965, -7236665, 24316168, -5253567}, + {13741529, 10911568, -33233417, -8603737, -20177830, -1033297, 33040651, -13424532, -20729456, 8321686}, + {21060490, -2212744, 15712757, -4336099, 1639040, 10656336, 23845965, -11874838, -9984458, 608372}}, + {{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547, 1123968, -6780577, 27229399, 23887}, + {-23244140, -294205, -11744728, 14712571, -29465699, -2029617, 12797024, -6440308, -1633405, 16678954}, + {-29500620, 4770662, -16054387, 14001338, 7830047, 9564805, -1508144, -4795045, -17169265, 4904953}}, + {{24059557, 14617003, 19037157, -15039908, 19766093, -14906429, 5169211, 16191880, 2128236, -4326833}, + {-16981152, 4124966, -8540610, -10653797, 30336522, -14105247, -29806336, 916033, -6882542, -2986532}, + {-22630907, 12419372, -7134229, -7473371, -16478904, 16739175, 285431, 2763829, 15736322, 4143876}}, + {{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801, -14594663, 23527084, -16458268}, + {33431127, -11130478, -17838966, -15626900, 8909499, 8376530, -32625340, 4087881, -15188911, -14416214}, + {1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055, 4357868, -4774191, -16323038}} + }, { + {{6721966, 13833823, -23523388, -1551314, 26354293, -11863321, 23365147, -3949732, 7390890, 2759800}, + {4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353, -4264057, 1244380, -12919645}, + {-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413, 9208236, 15886429, 16489664}}, + {{1996075, 10375649, 14346367, 13311202, -6874135, -16438411, -13693198, 398369, -30606455, -712933}, + {-25307465, 9795880, -2777414, 14878809, -33531835, 14780363, 13348553, 12076947, -30836462, 5113182}, + {-17770784, 11797796, 31950843, 13929123, -25888302, 12288344, -30341101, -7336386, 13847711, 5387222}}, + {{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611, 8763061, 3617786, -19600662, 10370991}, + {20246567, -14369378, 22358229, -543712, 18507283, -10413996, 14554437, -8746092, 32232924, 16763880}, + {9648505, 10094563, 26416693, 14745928, -30374318, -6472621, 11094161, 15689506, 3140038, -16510092}}, + {{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685, -27224800, 9448613, -28774454, 366295}, + {19153450, 11523972, -11096490, -6503142, -24647631, 5420647, 28344573, 8041113, 719605, 11671788}, + {8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916, -15266516, 27000813, -10195553}}, + {{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065, 5336097, 6750977, -14521026}, + {11836410, -3979488, 26297894, 16080799, 23455045, 15735944, 1695823, -8819122, 8169720, 16220347}, + {-18115838, 8653647, 17578566, -6092619, -8025777, -16012763, -11144307, -2627664, -5990708, -14166033}}, + {{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004, 27884329, 2847284, 2655861, 1738395}, + {-27537433, -14253021, -25336301, -8002780, -9370762, 8129821, 21651608, -3239336, -19087449, -11005278}, + {1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092, 5821408, 10478196, 8544890}}, + {{32173121, -16129311, 24896207, 3921497, 22579056, -3410854, 19270449, 12217473, 17789017, -3395995}, + {-30552961, -2228401, -15578829, -10147201, 13243889, 517024, 15479401, -3853233, 30460520, 1052596}, + {-11614875, 13323618, 32618793, 8175907, -15230173, 12596687, 27491595, -4612359, 3179268, -9478891}}, + {{31947069, -14366651, -4640583, -15339921, -15125977, -6039709, -14756777, -16411740, 19072640, -9511060}, + {11685058, 11822410, 3158003, -13952594, 33402194, -4165066, 5977896, -5215017, 473099, 5040608}, + {-20290863, 8198642, -27410132, 11602123, 1290375, -2799760, 28326862, 1721092, -19558642, -3131606}} + }, { + {{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786, 8076149, -27868496, 11538389}, + {-19935666, 3899861, 18283497, -6801568, -15728660, -11249211, 8754525, 7446702, -5676054, 5797016}, + {-11295600, -3793569, -15782110, -7964573, 12708869, -8456199, 2014099, -9050574, -2369172, -5877341}}, + {{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559, 1192730, -3714199, 15123619, 10811505}, + {14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363, 15776356, -28886779, -11974553}, + {-28241164, -8072475, -4978962, -5315317, 29416931, 1847569, -20654173, -16484855, 4714547, -9600655}}, + {{15200332, 8368572, 19679101, 15970074, -31872674, 1959451, 24611599, -4543832, -11745876, 12340220}, + {12876937, -10480056, 33134381, 6590940, -6307776, 14872440, 9613953, 8241152, 15370987, 9608631}, + {-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868, 15866074, -28210621, -8814099}}, + {{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233, 858697, 20571223, 8420556}, + {14620715, 13067227, -15447274, 8264467, 14106269, 15080814, 33531827, 12516406, -21574435, -12476749}, + {236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519, 7256740, 8791136, 15069930}}, + {{1276410, -9371918, 22949635, -16322807, -23493039, -5702186, 14711875, 4874229, -30663140, -2331391}, + {5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175, -7912378, -33069337, 9234253}, + {20590503, -9018988, 31529744, -7352666, -2706834, 10650548, 31559055, -11609587, 18979186, 13396066}}, + {{24474287, 4968103, 22267082, 4407354, 24063882, -8325180, -18816887, 13594782, 33514650, 7021958}, + {-11566906, -6565505, -21365085, 15928892, -26158305, 4315421, -25948728, -3916677, -21480480, 12868082}, + {-28635013, 13504661, 19988037, -2132761, 21078225, 6443208, -21446107, 2244500, -12455797, -8089383}}, + {{-30595528, 13793479, -5852820, 319136, -25723172, -6263899, 33086546, 8957937, -15233648, 5540521}, + {-11630176, -11503902, -8119500, -7643073, 2620056, 1022908, -23710744, -1568984, -16128528, -14962807}, + {23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819, 892185, -11513277, -15205948}}, + {{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819, 4763127, -19179614, 5867134}, + {-32765025, 1927590, 31726409, -4753295, 23962434, -16019500, 27846559, 5931263, -29749703, -16108455}, + {27461885, -2977536, 22380810, 1815854, -23033753, -3031938, 7283490, -15148073, -19526700, 7734629}} + }, { + {{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885, 7585295, -3176626, 18549497, 15302069}, + {-32658337, -6171222, -7672793, -11051681, 6258878, 13504381, 10458790, -6418461, -8872242, 8424746}, + {24687205, 8613276, -30667046, -3233545, 1863892, -1830544, 19206234, 7134917, -11284482, -828919}}, + {{11334899, -9218022, 8025293, 12707519, 17523892, -10476071, 10243738, -14685461, -5066034, 16498837}, + {8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925, -14124238, 6536641, 10543906}, + {-28946384, 15479763, -17466835, 568876, -1497683, 11223454, -2669190, -16625574, -27235709, 8876771}}, + {{-25742899, -12566864, -15649966, -846607, -33026686, -796288, -33481822, 15824474, -604426, -9039817}, + {10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697, -4890037, 1657394, 3084098}, + {10477963, -7470260, 12119566, -13250805, 29016247, -5365589, 31280319, 14396151, -30233575, 15272409}}, + {{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466, -25173957, -12636138, -25014757, 1950504}, + {-26180358, 9489187, 11053416, -14746161, -31053720, 5825630, -8384306, -8767532, 15341279, 8373727}, + {28685821, 7759505, -14378516, -12002860, -31971820, 4079242, 298136, -10232602, -2878207, 15190420}}, + {{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928, 8669718, 2742393, -26033313, -6875003}, + {-1580388, -11729417, -25979658, -11445023, -17411874, -10912854, 9291594, -16247779, -12154742, 6048605}, + {-30305315, 14843444, 1539301, 11864366, 20201677, 1900163, 13934231, 5128323, 11213262, 9168384}}, + {{-26280513, 11007847, 19408960, -940758, -18592965, -4328580, -5088060, -11105150, 20470157, -16398701}, + {-23136053, 9282192, 14855179, -15390078, -7362815, -14408560, -22783952, 14461608, 14042978, 5230683}, + {29969567, -2741594, -16711867, -8552442, 9175486, -2468974, 21556951, 3506042, -5933891, -12449708}}, + {{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683, -21284170, 8971513, -28539189, 15326563}, + {-19464629, 10110288, -17262528, -3503892, -23500387, 1355669, -15523050, 15300988, -20514118, 9168260}, + {-5353335, 4488613, -23803248, 16314347, 7780487, -15638939, -28948358, 9601605, 33087103, -9011387}}, + {{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461, -27444329, -15000531, -5996870, 15664672}, + {23294591, -16632613, -22650781, -8470978, 27844204, 11461195, 13099750, -2460356, 18151676, 13417686}, + {-24722913, -4176517, -31150679, 5988919, -26858785, 6685065, 1661597, -12551441, 15271676, -15452665}} + }, { + {{11433042, -13228665, 8239631, -5279517, -1985436, -725718, -18698764, 2167544, -6921301, -13440182}, + {-31436171, 15575146, 30436815, 12192228, -22463353, 9395379, -9917708, -8638997, 12215110, 12028277}, + {14098400, 6555944, 23007258, 5757252, -15427832, -12950502, 30123440, 4617780, -16900089, -655628}}, + {{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385, -15819999, 10154009, 23973261, -12684474}, + {-26531820, -3695990, -1908898, 2534301, -31870557, -16550355, 18341390, -11419951, 32013174, -10103539}, + {-25479301, 10876443, -11771086, -14625140, -12369567, 1838104, 21911214, 6354752, 4425632, -837822}}, + {{-10433389, -14612966, 22229858, -3091047, -13191166, 776729, -17415375, -12020462, 4725005, 14044970}, + {19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390, -1411784, -19522291, -16109756}, + {-24864089, 12986008, -10898878, -5558584, -11312371, -148526, 19541418, 8180106, 9282262, 10282508}}, + {{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257, 15522535, 8372215, 5542595, -10702683}, + {-10562541, 14895633, 26814552, -16673850, -17480754, -2489360, -2781891, 6993761, -18093885, 10114655}, + {-20107055, -929418, 31422704, 10427861, -7110749, 6150669, -29091755, -11529146, 25953725, -106158}}, + {{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294, 19390020, 6094296, -3315279, 12831125}, + {-15998678, 7578152, 5310217, 14408357, -33548620, -224739, 31575954, 6326196, 7381791, -2421839}, + {-20902779, 3296811, 24736065, -16328389, 18374254, 7318640, 6295303, 8082724, -15362489, 12339664}}, + {{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414, 15768922, 25091167, 14856294}, + {-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300, -12695493, -22182473, -9012899}, + {-11423429, -5421590, 11632845, 3405020, 30536730, -11674039, -27260765, 13866390, 30146206, 9142070}}, + {{3924129, -15307516, -13817122, -10054960, 12291820, -668366, -27702774, 9326384, -8237858, 4171294}, + {-15921940, 16037937, 6713787, 16606682, -21612135, 2790944, 26396185, 3731949, 345228, -5462949}, + {-21327538, 13448259, 25284571, 1143661, 20614966, -8849387, 2031539, -12391231, -16253183, -13582083}}, + {{31016211, -16722429, 26371392, -14451233, -5027349, 14854137, 17477601, 3842657, 28012650, -16405420}, + {-5075835, 9368966, -8562079, -4600902, -15249953, 6970560, -9189873, 16292057, -8867157, 3507940}, + {29439664, 3537914, 23333589, 6997794, -17555561, -11018068, -15209202, -15051267, -9164929, 6580396}} + }, { + {{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611, 17860444, -9273846, -2095802, 9304567}, + {20714564, -4336911, 29088195, 7406487, 11426967, -5095705, 14792667, -14608617, 5289421, -477127}, + {-16665533, -10650790, -6160345, -13305760, 9192020, -1802462, 17271490, 12349094, 26939669, -3752294}}, + {{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525, -27283495, -12348559, -3698806, 117887}, + {22263325, -6560050, 3984570, -11174646, -15114008, -566785, 28311253, 5358056, -23319780, 541964}, + {16259219, 3261970, 2309254, -15534474, -16885711, -4581916, 24134070, -16705829, -13337066, -13552195}}, + {{9378160, -13140186, -22845982, -12745264, 28198281, -7244098, -2399684, -717351, 690426, 14876244}, + {24977353, -314384, -8223969, -13465086, 28432343, -1176353, -13068804, -12297348, -22380984, 6618999}, + {-1538174, 11685646, 12944378, 13682314, -24389511, -14413193, 8044829, -13817328, 32239829, -5652762}}, + {{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647, -10350059, 32779359, 5095274}, + {-33008130, -5214506, -32264887, -3685216, 9460461, -9327423, -24601656, 14506724, 21639561, -2630236}, + {-16400943, -13112215, 25239338, 15531969, 3987758, -4499318, -1289502, -6863535, 17874574, 558605}}, + {{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700, 33499487, 5080151, 2085892, 5119761}, + {-22205145, -2519528, -16381601, 414691, -25019550, 2170430, 30634760, -8363614, -31999993, -5759884}, + {-6845704, 15791202, 8550074, -1312654, 29928809, -12092256, 27534430, -7192145, -22351378, 12961482}}, + {{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287, 16533930, 8206996, -30194652, -5159638}, + {-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630, 7031275, 7589640, 8945490}, + {-32152748, 8917967, 6661220, -11677616, -1192060, -15793393, 7251489, -11182180, 24099109, -14456170}}, + {{5019558, -7907470, 4244127, -14714356, -26933272, 6453165, -19118182, -13289025, -6231896, -10280736}, + {10853594, 10721687, 26480089, 5861829, -22995819, 1972175, -1866647, -10557898, -3363451, -6441124}, + {-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661, -2008168, -13866408, 7421392}}, + {{8139927, -6546497, 32257646, -5890546, 30375719, 1886181, -21175108, 15441252, 28826358, -4123029}, + {6267086, 9695052, 7709135, -16603597, -32869068, -1886135, 14795160, -7840124, 13746021, -1742048}, + {28584902, 7787108, -6732942, -15050729, 22846041, -7571236, -3181936, -363524, 4771362, -8419958}} + }, { + {{24949256, 6376279, -27466481, -8174608, -18646154, -9930606, 33543569, -12141695, 3569627, 11342593}, + {26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886, 4608608, 7325975, -14801071}, + {-11618399, -14554430, -24321212, 7655128, -1369274, 5214312, -27400540, 10258390, -17646694, -8186692}}, + {{11431204, 15823007, 26570245, 14329124, 18029990, 4796082, -31446179, 15580664, 9280358, -3973687}, + {-160783, -10326257, -22855316, -4304997, -20861367, -13621002, -32810901, -11181622, -15545091, 4387441}, + {-20799378, 12194512, 3937617, -5805892, -27154820, 9340370, -24513992, 8548137, 20617071, -7482001}}, + {{-938825, -3930586, -8714311, 16124718, 24603125, -6225393, -13775352, -11875822, 24345683, 10325460}, + {-19855277, -1568885, -22202708, 8714034, 14007766, 6928528, 16318175, -1010689, 4766743, 3552007}, + {-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514, 14481909, 10988822, -3994762}}, + {{15564307, -14311570, 3101243, 5684148, 30446780, -8051356, 12677127, -6505343, -8295852, 13296005}, + {-9442290, 6624296, -30298964, -11913677, -4670981, -2057379, 31521204, 9614054, -30000824, 12074674}, + {4771191, -135239, 14290749, -13089852, 27992298, 14998318, -1413936, -1556716, 29832613, -16391035}}, + {{7064884, -7541174, -19161962, -5067537, -18891269, -2912736, 25825242, 5293297, -27122660, 13101590}, + {-2298563, 2439670, -7466610, 1719965, -27267541, -16328445, 32512469, -5317593, -30356070, -4190957}, + {-30006540, 10162316, -33180176, 3981723, -16482138, -13070044, 14413974, 9515896, 19568978, 9628812}}, + {{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894, -6106839, -6291786, 3437740}, + {-18978877, 3884493, 19469877, 12726490, 15913552, 13614290, -22961733, 70104, 7463304, 4176122}, + {-27124001, 10659917, 11482427, -16070381, 12771467, -6635117, -32719404, -5322751, 24216882, 5944158}}, + {{8894125, 7450974, -2664149, -9765752, -28080517, -12389115, 19345746, 14680796, 11632993, 5847885}, + {26942781, -2315317, 9129564, -4906607, 26024105, 11769399, -11518837, 6367194, -9727230, 4782140}, + {19916461, -4828410, -22910704, -11414391, 25606324, -5972441, 33253853, 8220911, 6358847, -1873857}}, + {{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388, -4480480, -13538503, 1387155}, + {19646058, 5720633, -11416706, 12814209, 11607948, 12749789, 14147075, 15156355, -21866831, 11835260}, + {19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523, 15467869, -26560550, 5052483}} + }, { + {{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123, -12618185, 12228557, -7003677}, + {32944382, 14922211, -22844894, 5188528, 21913450, -8719943, 4001465, 13238564, -6114803, 8653815}, + {22865569, -4652735, 27603668, -12545395, 14348958, 8234005, 24808405, 5719875, 28483275, 2841751}}, + {{-16420968, -1113305, -327719, -12107856, 21886282, -15552774, -1887966, -315658, 19932058, -12739203}, + {-11656086, 10087521, -8864888, -5536143, -19278573, -3055912, 3999228, 13239134, -4777469, -13910208}, + {1382174, -11694719, 17266790, 9194690, -13324356, 9720081, 20403944, 11284705, -14013818, 3093230}}, + {{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424, 16271225, -24049421, -6691850}, + {-21911077, -5927941, -4611316, -5560156, -31744103, -10785293, 24123614, 15193618, -21652117, -16739389}, + {-9935934, -4289447, -25279823, 4372842, 2087473, 10399484, 31870908, 14690798, 17361620, 11864968}}, + {{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200, -12331205, -7486601, -25578460, -16240689}, + {14668462, -12270235, 26039039, 15305210, 25515617, 4542480, 10453892, 6577524, 9145645, -6443880}, + {5974874, 3053895, -9433049, -10385191, -31865124, 3225009, -7972642, 3936128, -5652273, -3050304}}, + {{30625386, -4729400, -25555961, -12792866, -20484575, 7695099, 17097188, -16303496, -27999779, 1803632}, + {-3553091, 9865099, -5228566, 4272701, -5673832, -16689700, 14911344, 12196514, -21405489, 7047412}, + {20093277, 9920966, -11138194, -5343857, 13161587, 12044805, -32856851, 4124601, -32343828, -10257566}}, + {{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605, 4752377, -8714640, -21679658, 2288038}, + {-26819236, -3283715, 29965059, 3039786, -14473765, 2540457, 29457502, 14625692, -24819617, 12570232}, + {-1063558, -11551823, 16920318, 12494842, 1278292, -5869109, -21159943, -3498680, -11974704, 4724943}}, + {{17960970, -11775534, -4140968, -9702530, -8876562, -1410617, -12907383, -8659932, -29576300, 1903856}, + {23134274, -14279132, -10681997, -1611936, 20684485, 15770816, -12989750, 3190296, 26955097, 14109738}, + {15308788, 5320727, -30113809, -14318877, 22902008, 7767164, 29425325, -11277562, 31960942, 11934971}}, + {{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669, 20638173, 4875028, 10491392, 1379718}, + {-13159415, 9197841, 3875503, -8936108, -1383712, -5879801, 33518459, 16176658, 21432314, 12180697}, + {-11787308, 11500838, 13787581, -13832590, -22430679, 10140205, 1465425, 12689540, -10301319, -13872883}} + }, { + {{5414091, -15386041, -21007664, 9643570, 12834970, 1186149, -2622916, -1342231, 26128231, 6032912}, + {-26337395, -13766162, 32496025, -13653919, 17847801, -12669156, 3604025, 8316894, -25875034, -10437358}, + {3296484, 6223048, 24680646, -12246460, -23052020, 5903205, -8862297, -4639164, 12376617, 3188849}}, + {{29190488, -14659046, 27549113, -1183516, 3520066, -10697301, 32049515, -7309113, -16109234, -9852307}, + {-14744486, -9309156, 735818, -598978, -20407687, -5057904, 25246078, -15795669, 18640741, -960977}, + {-6928835, -16430795, 10361374, 5642961, 4910474, 12345252, -31638386, -494430, 10530747, 1053335}}, + {{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384, -31462369, -2948985, 24018831, 15026644}, + {-22592535, -3145277, -2289276, 5953843, -13440189, 9425631, 25310643, 13003497, -2314791, -15145616}, + {-27419985, -603321, -8043984, -1669117, -26092265, 13987819, -27297622, 187899, -23166419, -2531735}}, + {{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473, 9716667, 16266922, -5070217, 726099}, + {29370922, -6053998, 7334071, -15342259, 9385287, 2247707, -13661962, -4839461, 30007388, -15823341}, + {-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109, 730663, 9835848, 4555336}}, + {{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977, 17693930, 544696, -11985298, 12422646}, + {31117226, -12215734, -13502838, 6561947, -9876867, -12757670, -5118685, -4096706, 29120153, 13924425}, + {-17400879, -14233209, 19675799, -2734756, -11006962, -5858820, -9383939, -11317700, 7240931, -237388}}, + {{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771, 1222336, 4389483, 3293637, -15551743}, + {-16684801, -14444245, 11038544, 11054958, -13801175, -3338533, -24319580, 7733547, 12796905, -6335822}, + {-8759414, -10817836, -25418864, 10783769, -30615557, -9746811, -28253339, 3647836, 3222231, -11160462}}, + {{18606113, 1693100, -25448386, -15170272, 4112353, 10045021, 23603893, -2048234, -7550776, 2484985}, + {9255317, -3131197, -12156162, -1004256, 13098013, -9214866, 16377220, -2102812, -19802075, -3034702}, + {-22729289, 7496160, -5742199, 11329249, 19991973, -3347502, -31718148, 9936966, -30097688, -10618797}}, + {{21878590, -5001297, 4338336, 13643897, -3036865, 13160960, 19708896, 5415497, -7360503, -4109293}, + {27736861, 10103576, 12500508, 8502413, -3413016, -9633558, 10436918, -1550276, -23659143, -8132100}, + {19492550, -12104365, -29681976, -852630, -3208171, 12403437, 30066266, 8367329, 13243957, 8709688}} + }, { + {{12015105, 2801261, 28198131, 10151021, 24818120, -4743133, -11194191, -5645734, 5150968, 7274186}, + {2831366, -12492146, 1478975, 6122054, 23825128, -12733586, 31097299, 6083058, 31021603, -9793610}, + {-2529932, -2229646, 445613, 10720828, -13849527, -11505937, -23507731, 16354465, 15067285, -14147707}}, + {{7840942, 14037873, -33364863, 15934016, -728213, -3642706, 21403988, 1057586, -19379462, -12403220}, + {915865, -16469274, 15608285, -8789130, -24357026, 6060030, -17371319, 8410997, -7220461, 16527025}, + {32922597, -556987, 20336074, -16184568, 10903705, -5384487, 16957574, 52992, 23834301, 6588044}}, + {{32752030, 11232950, 3381995, -8714866, 22652988, -10744103, 17159699, 16689107, -20314580, -1305992}, + {-4689649, 9166776, -25710296, -10847306, 11576752, 12733943, 7924251, -2752281, 1976123, -7249027}, + {21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041, -3371252, 12331345, -8237197}}, + {{8651614, -4477032, -16085636, -4996994, 13002507, 2950805, 29054427, -5106970, 10008136, -4667901}, + {31486080, 15114593, -14261250, 12951354, 14369431, -7387845, 16347321, -13662089, 8684155, -10532952}, + {19443825, 11385320, 24468943, -9659068, -23919258, 2187569, -26263207, -6086921, 31316348, 14219878}}, + {{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801, 27146014, 6992409, 29126555, 9207390}, + {32382935, 1110093, 18477781, 11028262, -27411763, -7548111, -4980517, 10843782, -7957600, -14435730}, + {2814918, 7836403, 27519878, -7868156, -20894015, -11553689, -21494559, 8550130, 28346258, 1994730}}, + {{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307, -19516951, 7174894, 22628102, 8115180}, + {-30405132, 955511, -11133838, -15078069, -32447087, -13278079, -25651578, 3317160, -9943017, 930272}, + {-15303681, -6833769, 28856490, 1357446, 23421993, 1057177, 24091212, -1388970, -22765376, -10650715}}, + {{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053, -14839018, -16554220, -1867018, 8398970}, + {-31969310, 2106403, -4736360, 1362501, 12813763, 16200670, 22981545, -6291273, 18009408, -15772772}, + {-17220923, -9545221, -27784654, 14166835, 29815394, 7444469, 29551787, -3727419, 19288549, 1325865}}, + {{15100157, -15835752, -23923978, -1005098, -26450192, 15509408, 12376730, -3479146, 33166107, -8042750}, + {20909231, 13023121, -9209752, 16251778, -5778415, -8094914, 12412151, 10018715, 2213263, -13878373}, + {32529814, -11074689, 30361439, -16689753, -9135940, 1513226, 22922121, 6382134, -5766928, 8371348}} + }, { + {{9923462, 11271500, 12616794, 3544722, -29998368, -1721626, 12891687, -8193132, -26442943, 10486144}, + {-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726, 2610596, -23921530, -11455195}, + {5408411, -1136691, -4969122, 10561668, 24145918, 14240566, 31319731, -4235541, 19985175, -3436086}}, + {{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976, -17577068, 8849297, 65030, 8370684}, + {-8320926, -12049626, 31204563, 5839400, -20627288, -1057277, -19442942, 6922164, 12743482, -9800518}, + {-2361371, 12678785, 28815050, 4759974, -23893047, 4884717, 23783145, 11038569, 18800704, 255233}}, + {{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847, 9066957, 19258688, -14753793}, + {-2936654, -10827535, -10432089, 14516793, -3640786, 4372541, -31934921, 2209390, -1524053, 2055794}, + {580882, 16705327, 5468415, -2683018, -30926419, -14696000, -7203346, -8994389, -30021019, 7394435}}, + {{23838809, 1822728, -15738443, 15242727, 8318092, -3733104, -21672180, -3492205, -4821741, 14799921}, + {13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804, 13496856, -9056018, 7402518}, + {2286874, -4435931, -20042458, -2008336, -13696227, 5038122, 11006906, -15760352, 8205061, 1607563}}, + {{14414086, -8002132, 3331830, -3208217, 22249151, -5594188, 18364661, -2906958, 30019587, -9029278}, + {-27688051, 1585953, -10775053, 931069, -29120221, -11002319, -14410829, 12029093, 9944378, 8024}, + {4368715, -3709630, 29874200, -15022983, -20230386, -11410704, -16114594, -999085, -8142388, 5640030}}, + {{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887, -16694564, 15219798, -14327783}, + {27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605, -1173195, -18342183, 9742717}, + {6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614, 7406442, 12420155, 1994844}}, + {{14012521, -5024720, -18384453, -9578469, -26485342, -3936439, -13033478, -10909803, 24319929, -6446333}, + {16412690, -4507367, 10772641, 15929391, -17068788, -4658621, 10555945, -10484049, -30102368, -4739048}, + {22397382, -7767684, -9293161, -12792868, 17166287, -9755136, -27333065, 6199366, 21880021, -12250760}}, + {{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128, 16557151, 8890729, 8840445, 4957760}, + {-15447727, 709327, -6919446, -10870178, -29777922, 6522332, -21720181, 12130072, -14796503, 5005757}, + {-2114751, -14308128, 23019042, 15765735, -25269683, 6002752, 10183197, -13239326, -16395286, -2176112}} + }, { + {{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537, -32013908, -3057104, 22208662, 2000468}, + {3065073, -1412761, -25598674, -361432, -17683065, -5703415, -8164212, 11248527, -3691214, -7414184}, + {10379208, -6045554, 8877319, 1473647, -29291284, -12507580, 16690915, 2553332, -3132688, 16400289}}, + {{15716668, 1254266, -18472690, 7446274, -8448918, 6344164, -22097271, -7285580, 26894937, 9132066}, + {24158887, 12938817, 11085297, -8177598, -28063478, -4457083, -30576463, 64452, -6817084, -2692882}, + {13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710, -3418511, -4688006, 2364226}}, + {{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024, -11697457, 15445875, -7798101}, + {29004207, -7867081, 28661402, -640412, -12794003, -7943086, 31863255, -4135540, -278050, -15759279}, + {-6122061, -14866665, -28614905, 14569919, -10857999, -3591829, 10343412, -6976290, -29828287, -10815811}}, + {{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636, 15372179, 17293797, 960709}, + {20263915, 11434237, -5765435, 11236810, 13505955, -10857102, -16111345, 6493122, -19384511, 7639714}, + {-2830798, -14839232, 25403038, -8215196, -8317012, -16173699, 18006287, -16043750, 29994677, -15808121}}, + {{9769828, 5202651, -24157398, -13631392, -28051003, -11561624, -24613141, -13860782, -31184575, 709464}, + {12286395, 13076066, -21775189, -1176622, -25003198, 4057652, -32018128, -8890874, 16102007, 13205847}, + {13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170, 8525972, 10151379, 10394400}}, + {{4024660, -16137551, 22436262, 12276534, -9099015, -2686099, 19698229, 11743039, -33302334, 8934414}, + {-15879800, -4525240, -8580747, -2934061, 14634845, -698278, -9449077, 3137094, -11536886, 11721158}, + {17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229, 8835153, -9205489, -1280045}}, + {{-461409, -7830014, 20614118, 16688288, -7514766, -4807119, 22300304, 505429, 6108462, -6183415}, + {-5070281, 12367917, -30663534, 3234473, 32617080, -8422642, 29880583, -13483331, -26898490, -7867459}, + {-31975283, 5726539, 26934134, 10237677, -3173717, -605053, 24199304, 3795095, 7592688, -14992079}}, + {{21594432, -14964228, 17466408, -4077222, 32537084, 2739898, 6407723, 12018833, -28256052, 4298412}, + {-20650503, -11961496, -27236275, 570498, 3767144, -1717540, 13891942, -1569194, 13717174, 10805743}, + {-14676630, -15644296, 15287174, 11927123, 24177847, -8175568, -796431, 14860609, -26938930, -5863836}} + }, { + {{12962541, 5311799, -10060768, 11658280, 18855286, -7954201, 13286263, -12808704, -4381056, 9882022}, + {18512079, 11319350, -20123124, 15090309, 18818594, 5271736, -22727904, 3666879, -23967430, -3299429}, + {-6789020, -3146043, 16192429, 13241070, 15898607, -14206114, -10084880, -6661110, -2403099, 5276065}}, + {{30169808, -5317648, 26306206, -11750859, 27814964, 7069267, 7152851, 3684982, 1449224, 13082861}, + {10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382, 15056736, -21016438, -8202000}, + {-33150110, 3261608, 22745853, 7948688, 19370557, -15177665, -26171976, 6482814, -10300080, -11060101}}, + {{32869458, -5408545, 25609743, 15678670, -10687769, -15471071, 26112421, 2521008, -22664288, 6904815}, + {29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737, 3841096, -29003639, -6657642}, + {10340844, -6630377, -18656632, -2278430, 12621151, -13339055, 30878497, -11824370, -25584551, 5181966}}, + {{25940115, -12658025, 17324188, -10307374, -8671468, 15029094, 24396252, -16450922, -2322852, -12388574}, + {-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390, 12641087, 20603771, -6561742}, + {-18882287, -11673380, 24849422, 11501709, 13161720, -4768874, 1925523, 11914390, 4662781, 7820689}}, + {{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456, 12172924, 16136752, 15264020}, + {-10349955, -14680563, -8211979, 2330220, -17662549, -14545780, 10658213, 6671822, 19012087, 3772772}, + {3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732, -15762884, 20527771, 12988982}}, + {{-14822485, -5797269, -3707987, 12689773, -898983, -10914866, -24183046, -10564943, 3299665, -12424953}, + {-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197, 6461331, -25583147, 8991218}, + {-17226263, 1816362, -1673288, -6086439, 31783888, -8175991, -32948145, 7417950, -30242287, 1507265}}, + {{29692663, 6829891, -10498800, 4334896, 20945975, -11906496, -28887608, 8209391, 14606362, -10647073}, + {-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695, 9761487, 4170404, -2085325}, + {-11587470, 14855945, -4127778, -1531857, -26649089, 15084046, 22186522, 16002000, -14276837, -8400798}}, + {{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047, -7113572, -9620092, 13240845, 10965870}, + {-7742563, -8256762, -14768334, -13656260, -23232383, 12387166, 4498947, 14147411, 29514390, 4302863}, + {-13413405, -12407859, 20757302, -13801832, 14785143, 8976368, -5061276, -2144373, 17846988, -13971927}} + }, { + {{-2244452, -754728, -4597030, -1066309, -6247172, 1455299, -21647728, -9214789, -5222701, 12650267}, + {-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813, 13770293, -19134326, 10958663}, + {22470984, 12369526, 23446014, -5441109, -21520802, -9698723, -11772496, -11574455, -25083830, 4271862}}, + {{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192, 75375, -4278529, -32526221, 8469673}, + {15854970, 4148314, -8893890, 7259002, 11666551, 13824734, -30531198, 2697372, 24154791, -9460943}, + {15446137, -15806644, 29759747, 14019369, 30811221, -9610191, -31582008, 12840104, 24913809, 9815020}}, + {{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414, -9103676, 13438769, 18735128, 9466238}, + {11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821, -10896103, -22728655, 16199064}, + {14576810, 379472, -26786533, -8317236, -29426508, -10812974, -102766, 1876699, 30801119, 2164795}}, + {{15995086, 3199873, 13672555, 13712240, -19378835, -4647646, -13081610, -15496269, -13492807, 1268052}, + {-10290614, -3659039, -3286592, 10948818, 23037027, 3794475, -3470338, -12600221, -17055369, 3565904}, + {29210088, -9419337, -5919792, -4952785, 10834811, -13327726, -16512102, -10820713, -27162222, -14030531}}, + {{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123, -29183421, -3769423, 2244111, -14001979}, + {-5152875, -3800936, -9306475, -6071583, 16243069, 14684434, -25673088, -16180800, 13491506, 4641841}, + {10813417, 643330, -19188515, -728916, 30292062, -16600078, 27548447, -7721242, 14476989, -12767431}}, + {{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937, -1644259, -27912810, 12651324}, + {-31185513, -813383, 22271204, 11835308, 10201545, 15351028, 17099662, 3988035, 21721536, -3148940}, + {10202177, -6545839, -31373232, -9574638, -32150642, -8119683, -12906320, 3852694, 13216206, 14842320}}, + {{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778, -31500847, 13765824, -27434397, 9900184}, + {14465505, -13833331, -32133984, -14738873, -27443187, 12990492, 33046193, 15796406, -7051866, -8040114}, + {30924417, -8279620, 6359016, -12816335, 16508377, 9071735, -25488601, 15413635, 9524356, -7018878}}, + {{12274201, -13175547, 32627641, -1785326, 6736625, 13267305, 5237659, -5109483, 15663516, 4035784}, + {-2951309, 8903985, 17349946, 601635, -16432815, -4612556, -13732739, -15889334, -22258478, 4659091}, + {-16916263, -4952973, -30393711, -15158821, 20774812, 15897498, 5736189, 15026997, -2178256, -13455585}} + }, { + {{-8858980, -2219056, 28571666, -10155518, -474467, -10105698, -3801496, 278095, 23440562, -290208}, + {10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275, 11551483, -16571960, -7442864}, + {17932739, -12437276, -24039557, 10749060, 11316803, 7535897, 22503767, 5561594, -3646624, 3898661}}, + {{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531, 7152530, 21831162, 1245233}, + {26958459, -14658026, 4314586, 8346991, -5677764, 11960072, -32589295, -620035, -30402091, -16716212}, + {-12165896, 9166947, 33491384, 13673479, 29787085, 13096535, 6280834, 14587357, -22338025, 13987525}}, + {{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778, -4300898, -5124639, -7469781, -2858068}, + {9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781, 6439245, -14581012, 4091397}, + {-8426427, 1470727, -28109679, -1596990, 3978627, -5123623, -19622683, 12092163, 29077877, -14741988}}, + {{5269168, -6859726, -13230211, -8020715, 25932563, 1763552, -5606110, -5505881, -20017847, 2357889}, + {32264008, -15407652, -5387735, -1160093, -2091322, -3946900, 23104804, -12869908, 5727338, 189038}, + {14609123, -8954470, -6000566, -16622781, -14577387, -7743898, -26745169, 10942115, -25888931, -14884697}}, + {{20513500, 5557931, -15604613, 7829531, 26413943, -2019404, -21378968, 7471781, 13913677, -5137875}, + {-25574376, 11967826, 29233242, 12948236, -6754465, 4713227, -8940970, 14059180, 12878652, 8511905}, + {-25656801, 3393631, -2955415, -7075526, -2250709, 9366908, -30223418, 6812974, 5568676, -3127656}}, + {{11630004, 12144454, 2116339, 13606037, 27378885, 15676917, -17408753, -13504373, -14395196, 8070818}, + {27117696, -10007378, -31282771, -5570088, 1127282, 12772488, -29845906, 10483306, -11552749, -1028714}, + {10637467, -5688064, 5674781, 1072708, -26343588, -6982302, -1683975, 9177853, -27493162, 15431203}}, + {{20525145, 10892566, -12742472, 12779443, -29493034, 16150075, -28240519, 14943142, -15056790, -7935931}, + {-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767, -3239766, -3356550, 9594024}, + {-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683, -6492290, 13352335, -10977084}}, + {{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091, -29783850, -7752482, -13215537, -319204}, + {20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742, 15077870, -22750759, 14523817}, + {27406042, -6041657, 27423596, -4497394, 4996214, 10002360, -28842031, -4545494, -30172742, -4805667}} + }, { + {{11374242, 12660715, 17861383, -12540833, 10935568, 1099227, -13886076, -9091740, -27727044, 11358504}, + {-12730809, 10311867, 1510375, 10778093, -2119455, -9145702, 32676003, 11149336, -26123651, 4985768}, + {-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043, 13794114, -19414307, -15621255}}, + {{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603, 6970005, -1691065, -9004790}, + {1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622, -5475723, -16796596, -5031438}, + {-22273315, -13524424, -64685, -4334223, -18605636, -10921968, -20571065, -7007978, -99853, -10237333}}, + {{17747465, 10039260, 19368299, -4050591, -20630635, -16041286, 31992683, -15857976, -29260363, -5511971}, + {31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999, -3744247, 4882242, -10626905}, + {29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198, 3272828, -5190932, -4162409}}, + {{12501286, 4044383, -8612957, -13392385, -32430052, 5136599, -19230378, -3529697, 330070, -3659409}, + {6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522, -8573892, -271295, 12071499}, + {-8365515, -4042521, 25133448, -4517355, -6211027, 2265927, -32769618, 1936675, -5159697, 3829363}}, + {{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550, -6567787, 26333140, 14267664}, + {-11067219, 11871231, 27385719, -10559544, -4585914, -11189312, 10004786, -8709488, -21761224, 8930324}, + {-21197785, -16396035, 25654216, -1725397, 12282012, 11008919, 1541940, 4757911, -26491501, -16408940}}, + {{13537262, -7759490, -20604840, 10961927, -5922820, -13218065, -13156584, 6217254, -15943699, 13814990}, + {-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681, 9257833, -1956526, -1776914}, + {-25045300, -10191966, 15366585, 15166509, -13105086, 8423556, -29171540, 12361135, -18685978, 4578290}}, + {{24579768, 3711570, 1342322, -11180126, -27005135, 14124956, -22544529, 14074919, 21964432, 8235257}, + {-6528613, -2411497, 9442966, -5925588, 12025640, -1487420, -2981514, -1669206, 13006806, 2355433}, + {-16304899, -13605259, -6632427, -5142349, 16974359, -10911083, 27202044, 1719366, 1141648, -12796236}}, + {{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894, 13475066, -3133972, 32674895, 13715045}, + {11423335, -5468059, 32344216, 8962751, 24989809, 9241752, -13265253, 16086212, -28740881, -15642093}, + {-1409668, 12530728, -6368726, 10847387, 19531186, -14132160, -11709148, 7791794, -27245943, 4383347}} + }, { + {{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599, -4862407, -4906449, 27193557, 6245191}, + {-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898, 3260492, 22510453, 8577507}, + {-12632451, 11257346, -32692994, 13548177, -721004, 10879011, 31168030, 13952092, -29571492, -3635906}}, + {{3877321, -9572739, 32416692, 5405324, -11004407, -13656635, 3759769, 11935320, 5611860, 8164018}, + {-16275802, 14667797, 15906460, 12155291, -22111149, -9039718, 32003002, -8832289, 5773085, -8422109}, + {-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725, 12376320, 31632953, 190926}}, + {{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328, -8288749, 4508564, -25341555, -3627528}, + {8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941, -14786005, -1672488, 827625}, + {-32720583, -16289296, -32503547, 7101210, 13354605, 2659080, -1800575, -14108036, -24878478, 1541286}}, + {{2901347, -1117687, 3880376, -10059388, -17620940, -3612781, -21802117, -3567481, 20456845, -1885033}, + {27019610, 12299467, -13658288, -1603234, -12861660, -4861471, -19540150, -5016058, 29439641, 15138866}, + {21536104, -6626420, -32447818, -10690208, -22408077, 5175814, -5420040, -16361163, 7779328, 109896}}, + {{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390, 12180118, 23177719, -554075}, + {26572847, 3405927, -31701700, 12890905, -19265668, 5335866, -6493768, 2378492, 4439158, -13279347}, + {-22716706, 3489070, -9225266, -332753, 18875722, -1140095, 14819434, -12731527, -17717757, -5461437}}, + {{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060, -820954, 2177225, 8550082, -15114165}, + {-18473302, 16596775, -381660, 15663611, 22860960, 15585581, -27844109, -3582739, -23260460, -8428588}, + {-32480551, 15707275, -8205912, -5652081, 29464558, 2713815, -22725137, 15860482, -21902570, 1494193}}, + {{-19562091, -14087393, -25583872, -9299552, 13127842, 759709, 21923482, 16529112, 8742704, 12967017}, + {-28464899, 1553205, 32536856, -10473729, -24691605, -406174, -8914625, -2933896, -29903758, 15553883}, + {21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572, 14513274, 19375923, -12647961}}, + {{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818, -6222716, 2862653, 9455043}, + {29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124, -2990080, 15511449, 4789663}, + {-20679756, 7004547, 8824831, -9434977, -4045704, -3750736, -5754762, 108893, 23513200, 16652362}} + }, { + {{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542, -6650416, -12936300, -18319198, 10212860}, + {2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801, 2600940, -9988298, -12506466}, + {-24645692, 13317462, -30449259, -15653928, 21365574, -10869657, 11344424, 864440, -2499677, -16710063}}, + {{-26432803, 6148329, -17184412, -14474154, 18782929, -275997, -22561534, 211300, 2719757, 4940997}, + {-1323882, 3911313, -6948744, 14759765, -30027150, 7851207, 21690126, 8518463, 26699843, 5276295}, + {-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586, 149635, -15452774, 7159369}}, + {{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009, 8312176, 22477218, -8403385}, + {18155857, -16504990, 19744716, 9006923, 15154154, -10538976, 24256460, -4864995, -22548173, 9334109}, + {2986088, -4911893, 10776628, -3473844, 10620590, -7083203, -21413845, 14253545, -22587149, 536906}}, + {{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551, 10589625, 10838060, -15420424}, + {-19342404, 867880, 9277171, -3218459, -14431572, -1986443, 19295826, -15796950, 6378260, 699185}, + {7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039, 15693155, -5045064, -13373962}}, + {{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616, 31730678, -10962840, -3918636, -9669325}, + {10188286, -15770834, -7336361, 13427543, 22223443, 14896287, 30743455, 7116568, -21786507, 5427593}, + {696102, 13206899, 27047647, -10632082, 15285305, -9853179, 10798490, -4578720, 19236243, 12477404}}, + {{-11229439, 11243796, -17054270, -8040865, -788228, -8167967, -3897669, 11180504, -23169516, 7733644}, + {17800790, -14036179, -27000429, -11766671, 23887827, 3149671, 23466177, -10538171, 10322027, 15313801}, + {26246234, 11968874, 32263343, -5468728, 6830755, -13323031, -15794704, -101982, -24449242, 10890804}}, + {{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544, -14982212, 16484931, 25180797, -5334884}, + {-586574, 10376444, -32586414, -11286356, 19801893, 10997610, 2276632, 9482883, 316878, 13820577}, + {-9882808, -4510367, -2115506, 16457136, -11100081, 11674996, 30756178, -7515054, 30696930, -3712849}}, + {{32988917, -9603412, 12499366, 7910787, -10617257, -11931514, -7342816, -9985397, -32349517, 7392473}, + {-8855661, 15927861, 9866406, -3649411, -2396914, -16655781, -30409476, -9134995, 25112947, -2926644}, + {-2504044, -436966, 25621774, -5678772, 15085042, -5479877, -24884878, -13526194, 5537438, -13914319}} + }, { + {{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648, -14876251, -1729667, 31234590, 6090599}, + {-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721, 15878753, -6970405, -9034768}, + {-27757857, 247744, -15194774, -9002551, 23288161, -10011936, -23869595, 6503646, 20650474, 1804084}}, + {{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995, -10329713, 27842616, -202328}, + {-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656, 5031932, -11375082, 12714369}, + {20807691, -7270825, 29286141, 11421711, -27876523, -13868230, -21227475, 1035546, -19733229, 12796920}}, + {{12076899, -14301286, -8785001, -11848922, -25012791, 16400684, -17591495, -12899438, 3480665, -15182815}, + {-32361549, 5457597, 28548107, 7833186, 7303070, -11953545, -24363064, -15921875, -33374054, 2771025}, + {-21389266, 421932, 26597266, 6860826, 22486084, -6737172, -17137485, -4210226, -24552282, 15673397}}, + {{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893, -20271184, 4733254, 3727144, -12934448}, + {6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594, 7975683, 31123697, -10958981}, + {30069250, -11435332, 30434654, 2958439, 18399564, -976289, 12296869, 9204260, -16432438, 9648165}}, + {{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266, 5248604, -26008332, -11377501}, + {17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711, 15298639, 2662509, -16297073}, + {-1172927, -7558695, -4366770, -4287744, -21346413, -8434326, 32087529, -1222777, 32247248, -14389861}}, + {{14312628, 1221556, 17395390, -8700143, -4945741, -8684635, -28197744, -9637817, -16027623, -13378845}, + {-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502, 9803137, 17597934, 2346211}, + {18510800, 15337574, 26171504, 981392, -22241552, 7827556, -23491134, -11323352, 3059833, -11782870}}, + {{10141598, 6082907, 17829293, -1947643, 9830092, 13613136, -25556636, -5544586, -33502212, 3592096}, + {33114168, -15889352, -26525686, -13343397, 33076705, 8716171, 1151462, 1521897, -982665, -6837803}, + {-32939165, -4255815, 23947181, -324178, -33072974, -12305637, -16637686, 3891704, 26353178, 693168}}, + {{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294, -400668, 31375464, 14369965}, + {-14370654, -7772529, 1510301, 6434173, -18784789, -6262728, 32732230, -13108839, 17901441, 16011505}, + {18171223, -11934626, -12500402, 15197122, -11038147, -15230035, -19172240, -16046376, 8764035, 12309598}} + }, { + {{5975908, -5243188, -19459362, -9681747, -11541277, 14015782, -23665757, 1228319, 17544096, -10593782}, + {5811932, -1715293, 3442887, -2269310, -18367348, -8359541, -18044043, -15410127, -5565381, 12348900}, + {-31399660, 11407555, 25755363, 6891399, -3256938, 14872274, -24849353, 8141295, -10632534, -585479}}, + {{-12675304, 694026, -5076145, 13300344, 14015258, -14451394, -9698672, -11329050, 30944593, 1130208}, + {8247766, -6710942, -26562381, -7709309, -14401939, -14648910, 4652152, 2488540, 23550156, -271232}, + {17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737, -5908146, -408818, -137719}}, + {{16091085, -16253926, 18599252, 7340678, 2137637, -1221657, -3364161, 14550936, 3260525, -7166271}, + {-4910104, -13332887, 18550887, 10864893, -16459325, -7291596, -23028869, -13204905, -12748722, 2701326}, + {-8574695, 16099415, 4629974, -16340524, -20786213, -6005432, -10018363, 9276971, 11329923, 1862132}}, + {{14763076, -15903608, -30918270, 3689867, 3511892, 10313526, -21951088, 12219231, -9037963, -940300}, + {8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216, -2909717, -15438168, 11595570}, + {15214962, 3537601, -26238722, -14058872, 4418657, -15230761, 13947276, 10730794, -13489462, -4363670}}, + {{-2538306, 7682793, 32759013, 263109, -29984731, -7955452, -22332124, -10188635, 977108, 699994}, + {-12466472, 4195084, -9211532, 550904, -15565337, 12917920, 19118110, -439841, -30534533, -14337913}, + {31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237, -10051775, 12493932, -5409317}}, + {{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087, 27218280, 2607121, 29375955, 6024730}, + {842132, -2794693, -4763381, -8722815, 26332018, -12405641, 11831880, 6985184, -9940361, 2854096}, + {-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645, 960770, 12121869, 16648078}}, + {{-15218652, 14667096, -13336229, 2013717, 30598287, -464137, -31504922, -7882064, 20237806, 2838411}, + {-19288047, 4453152, 15298546, -16178388, 22115043, -15972604, 12544294, -13470457, 1068881, -12499905}, + {-9558883, -16518835, 33238498, 13506958, 30505848, -1114596, -8486907, -2630053, 12521378, 4845654}}, + {{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600, 3409348, -873400, -6482306, -12885870}, + {-23561822, 6230156, -20382013, 10655314, -24040585, -11621172, 10477734, -1240216, -3113227, 13974498}, + {12966261, 15550616, -32038948, -1615346, 21025980, -629444, 5642325, 7188737, 18895762, 12629579}} + }, { + {{14741879, -14946887, 22177208, -11721237, 1279741, 8058600, 11758140, 789443, 32195181, 3895677}, + {10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575, -3566119, -8982069, 4429647}, + {-2453894, 15725973, -20436342, -10410672, -5803908, -11040220, -7135870, -11642895, 18047436, -15281743}}, + {{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455, 10993114, -12850837, -17620701, -9408468}, + {21987233, 700364, -24505048, 14972008, -7774265, -5718395, 32155026, 2581431, -29958985, 8773375}, + {-25568350, 454463, -13211935, 16126715, 25240068, 8594567, 20656846, 12017935, -7874389, -13920155}}, + {{6028182, 6263078, -31011806, -11301710, -818919, 2461772, -31841174, -5468042, -1721788, -2776725}, + {-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845, -4166698, 28408820, 6816612}, + {-10358094, -8237829, 19549651, -12169222, 22082623, 16147817, 20613181, 13982702, -10339570, 5067943}}, + {{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951, -19719286, 12746132, 5331210, -10105944}, + {30528811, 3601899, -1957090, 4619785, -27361822, -15436388, 24180793, -12570394, 27679908, -1648928}, + {9402404, -13957065, 32834043, 10838634, -26580150, -13237195, 26653274, -8685565, 22611444, -12715406}}, + {{22190590, 1118029, 22736441, 15130463, -30460692, -5991321, 19189625, -4648942, 4854859, 6622139}, + {-8310738, -2953450, -8262579, -3388049, -10401731, -271929, 13424426, -3567227, 26404409, 13001963}, + {-31241838, -15415700, -2994250, 8939346, 11562230, -12840670, -26064365, -11621720, -15405155, 11020693}}, + {{1866042, -7949489, -7898649, -10301010, 12483315, 13477547, 3175636, -12424163, 28761762, 1406734}, + {-448555, -1777666, 13018551, 3194501, -9580420, -11161737, 24760585, -4347088, 25577411, -13378680}, + {-24290378, 4759345, -690653, -1852816, 2066747, 10693769, -29595790, 9884936, -9368926, 4745410}}, + {{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276, -15462008, -11311852, 10931924, -11931931}, + {-16561513, 14112680, -8012645, 4817318, -8040464, -11414606, -22853429, 10856641, -20470770, 13434654}, + {22759489, -10073434, -16766264, -1871422, 13637442, -10168091, 1765144, -12654326, 28445307, -5364710}}, + {{29875063, 12493613, 2795536, -3786330, 1710620, 15181182, -10195717, -8788675, 9074234, 1167180}, + {-26205683, 11014233, -9842651, -2635485, -26908120, 7532294, -18716888, -9535498, 3843903, 9367684}, + {-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123, 8601684, -139197, 4242895}} + }, { + {{22092954, -13191123, -2042793, -11968512, 32186753, -11517388, -6574341, 2470660, -27417366, 16625501}, + {-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857, 2602725, -27351616, 14247413}, + {6314175, -10264892, -32772502, 15957557, -10157730, 168750, -8618807, 14290061, 27108877, -1180880}}, + {{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596, 33547976, -11058889, -27148451, 981874}, + {22833440, 9293594, -32649448, -13618667, -9136966, 14756819, -22928859, -13970780, -10479804, -16197962}, + {-7768587, 3326786, -28111797, 10783824, 19178761, 14905060, 22680049, 13906969, -15933690, 3797899}}, + {{21721356, -4212746, -12206123, 9310182, -3882239, -13653110, 23740224, -2709232, 20491983, -8042152}, + {9209270, -15135055, -13256557, -6167798, -731016, 15289673, 25947805, 15286587, 30997318, -6703063}, + {7392032, 16618386, 23946583, -8039892, -13265164, -1533858, -14197445, -2321576, 17649998, -250080}}, + {{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752, -15241566, -9525724, -2233253, 7662146}, + {-17558673, 1763594, -33114336, 15908610, -30040870, -12174295, 7335080, -8472199, -3174674, 3440183}, + {-19889700, -5977008, -24111293, -9688870, 10799743, -16571957, 40450, -4431835, 4862400, 1133}}, + {{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142, 7258061, 311861, -30594991, -7379421}, + {-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763, 16527196, 18278453, 15405622}, + {-4381906, 8508652, -19898366, -3674424, -5984453, 15149970, -13313598, 843523, -21875062, 13626197}}, + {{2281448, -13487055, -10915418, -2609910, 1879358, 16164207, -10783882, 3953792, 13340839, 15928663}, + {31727126, -7179855, -18437503, -8283652, 2875793, -16390330, -25269894, -7014826, -23452306, 5964753}, + {4100420, -5959452, -17179337, 6017714, -18705837, 12227141, -26684835, 11344144, 2538215, -7570755}}, + {{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241, -20474983, 1485421, -629256, -15958862}, + {-26804558, 4260919, 11851389, 9658551, -32017107, 16367492, -20205425, -13191288, 11659922, -11115118}, + {26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568, -10170080, 33100372, -1306171}}, + {{15121113, -5201871, -10389905, 15427821, -27509937, -15992507, 21670947, 4486675, -5931810, -14466380}, + {16166486, -9483733, -11104130, 6023908, -31926798, -1364923, 2340060, -16254968, -10735770, -10039824}, + {28042865, -3557089, -12126526, 12259706, -3717498, -6945899, 6766453, -8689599, 18036436, 5803270}} + }, { + {{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391, 4598332, -6159431, -14117438}, + {-31031306, -14256194, 17332029, -2383520, 31312682, -5967183, 696309, 50292, -20095739, 11763584}, + {-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117, -12613632, -19773211, -10713562}}, + {{30464590, -11262872, -4127476, -12734478, 19835327, -7105613, -24396175, 2075773, -17020157, 992471}, + {18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841, 8080033, -11574335, -10601610}, + {19598397, 10334610, 12555054, 2555664, 18821899, -10339780, 21873263, 16014234, 26224780, 16452269}}, + {{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804, -7618186, -20533829, 3698650}, + {14187449, 3448569, -10636236, -10810935, -22663880, -3433596, 7268410, -10890444, 27394301, 12015369}, + {19695761, 16087646, 28032085, 12999827, 6817792, 11427614, 20244189, -1312777, -13259127, -3402461}}, + {{30860103, 12735208, -1888245, -4699734, -16974906, 2256940, -8166013, 12298312, -8550524, -10393462}, + {-5719826, -11245325, -1910649, 15569035, 26642876, -7587760, -5789354, -15118654, -4976164, 12651793}, + {-2848395, 9953421, 11531313, -5282879, 26895123, -12697089, -13118820, -16517902, 9768698, -2533218}}, + {{-24719459, 1894651, -287698, -4704085, 15348719, -8156530, 32767513, 12765450, 4940095, 10678226}, + {18860224, 15980149, -18987240, -1562570, -26233012, -11071856, -7843882, 13944024, -24372348, 16582019}, + {-15504260, 4970268, -29893044, 4175593, -20993212, -2199756, -11704054, 15444560, -11003761, 7989037}}, + {{31490452, 5568061, -2412803, 2182383, -32336847, 4531686, -32078269, 6200206, -19686113, -14800171}, + {-17308668, -15879940, -31522777, -2831, -32887382, 16375549, 8680158, -16371713, 28550068, -6857132}, + {-28126887, -5688091, 16837845, -1820458, -6850681, 12700016, -30039981, 4364038, 1155602, 5988841}}, + {{21890435, -13272907, -12624011, 12154349, -7831873, 15300496, 23148983, -4470481, 24618407, 8283181}, + {-33136107, -10512751, 9975416, 6841041, -31559793, 16356536, 3070187, -7025928, 1466169, 10740210}, + {-1509399, -15488185, -13503385, -10655916, 32799044, 909394, -13938903, -5779719, -32164649, -15327040}}, + {{3960823, -14267803, -28026090, -15918051, -19404858, 13146868, 15567327, 951507, -3260321, -573935}, + {24740841, 5052253, -30094131, 8961361, 25877428, 6165135, -24368180, 14397372, -7380369, -6144105}, + {-28888365, 3510803, -28103278, -1158478, -11238128, -10631454, -15441463, -14453128, -1625486, -6494814}} + }, { + {{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843, -4885251, -9906200, -621852}, + {5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374, 1468826, -6171428, -15186581}, + {-4859255, -3779343, -2917758, -6748019, 7778750, 11688288, -30404353, -9871238, -1558923, -9863646}}, + {{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958, 14783338, -30581476, -15757844}, + {10566929, 12612572, -31944212, 11118703, -12633376, 12362879, 21752402, 8822496, 24003793, 14264025}, + {27713862, -7355973, -11008240, 9227530, 27050101, 2504721, 23886875, -13117525, 13958495, -5732453}}, + {{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291, -31889399, -10041781, 7340521, -15410068}, + {4646514, -8011124, -22766023, -11532654, 23184553, 8566613, 31366726, -1381061, -15066784, -10375192}, + {-17270517, 12723032, -16993061, 14878794, 21619651, -6197576, 27584817, 3093888, -8843694, 3849921}}, + {{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958, 32477045, -9017955, 5002294, -15550259}, + {-12057553, -11177906, 21115585, -13365155, 8808712, -12030708, 16489530, 13378448, -25845716, 12741426}, + {-5946367, 10645103, -30911586, 15390284, -3286982, -7118677, 24306472, 15852464, 28834118, -7646072}}, + {{-17335748, -9107057, -24531279, 9434953, -8472084, -583362, -13090771, 455841, 20461858, 5491305}, + {13669248, -16095482, -12481974, -10203039, -14569770, -11893198, -24995986, 11293807, -28588204, -9421832}, + {28497928, 6272777, -33022994, 14470570, 8906179, -1225630, 18504674, -14165166, 29867745, -8795943}}, + {{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891, -6367600, -13175392, 22853429, -4012011}, + {24191378, 16712145, -13931797, 15217831, 14542237, 1646131, 18603514, -11037887, 12876623, -2112447}, + {17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753, 608397, 16031844, 3723494}}, + {{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745, 17558842, -7872890, 23896954, -4314245}, + {-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064, 7229064, -9919646, -8826859}, + {28816045, 298879, -28165016, -15920938, 19000928, -1665890, -12680833, -2949325, -18051778, -2082915}}, + {{16000882, -344896, 3493092, -11447198, -29504595, -13159789, 12577740, 16041268, -19715240, 7847707}, + {10151868, 10572098, 27312476, 7922682, 14825339, 4723128, -32855931, -6519018, -10020567, 3852848}, + {-11430470, 15697596, -21121557, -4420647, 5386314, 15063598, 16514493, -15932110, 29330899, -15076224}} + }, { + {{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784, 3303702, 15490, -27548796, 12314391}, + {15683520, -6003043, 18109120, -9980648, 15337968, -5997823, -16717435, 15921866, 16103996, -3731215}, + {-23169824, -10781249, 13588192, -1628807, -3798557, -1074929, -19273607, 5402699, -29815713, -9841101}}, + {{23190676, 2384583, -32714340, 3462154, -29903655, -1529132, -11266856, 8911517, -25205859, 2739713}, + {21374101, -3554250, -33524649, 9874411, 15377179, 11831242, -33529904, 6134907, 4931255, 11987849}, + {-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539, 13861388, -30076310, 10117930}}, + {{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643, -6325503, 6704079, 12890019, 15728940}, + {-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376, -10428139, 12885167, 8311031}, + {-17516482, 5352194, 10384213, -13811658, 7506451, 13453191, 26423267, 4384730, 1888765, -5435404}}, + {{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729, -32251644, -12707869, -19464434, -3340243}, + {-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245, 14845197, 17151279, -9854116}, + {-24830458, -12733720, -15165978, 10367250, -29530908, -265356, 22825805, -7087279, -16866484, 16176525}}, + {{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182, -10363426, -28746253, -10197509}, + {-10626600, -4486402, -13320562, -5125317, 3432136, -6393229, 23632037, -1940610, 32808310, 1099883}, + {15030977, 5768825, -27451236, -2887299, -6427378, -15361371, -15277896, -6809350, 2051441, -15225865}}, + {{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398, -14154188, -22686354, 16633660}, + {4577086, -16752288, 13249841, -15304328, 19958763, -14537274, 18559670, -10759549, 8402478, -9864273}, + {-28406330, -1051581, -26790155, -907698, -17212414, -11030789, 9453451, -14980072, 17983010, 9967138}}, + {{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990, 7806337, 17507396, 3651560}, + {-10420457, -4118111, 14584639, 15971087, -15768321, 8861010, 26556809, -5574557, -18553322, -11357135}, + {2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121, 8459447, -5605463, -7621941}}, + {{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813, -849066, 17258084, -7977739}, + {18164541, -10595176, -17154882, -1542417, 19237078, -9745295, 23357533, -15217008, 26908270, 12150756}, + {-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168, -5537701, -32302074, 16215819}} + }, { + {{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835, 32574489, 12532905, -7503072, -8675347}, + {-27343522, -16515468, -27151524, -10722951, 946346, 16291093, 254968, 7168080, 21676107, -1943028}, + {21260961, -8424752, -16831886, -11920822, -23677961, 3968121, -3651949, -6215466, -3556191, -7913075}}, + {{16544754, 13250366, -16804428, 15546242, -4583003, 12757258, -2462308, -8680336, -18907032, -9662799}, + {-2415239, -15577728, 18312303, 4964443, -15272530, -12653564, 26820651, 16690659, 25459437, -4564609}, + {-25144690, 11425020, 28423002, -11020557, -6144921, -15826224, 9142795, -2391602, -6432418, -1644817}}, + {{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437, -27457225, -16344658, 6335692, 7249989}, + {-30333227, 13979675, 7503222, -12368314, -11956721, -4621693, -30272269, 2682242, 25993170, -12478523}, + {4364628, 5930691, 32304656, -10044554, -8054781, 15091131, 22857016, -10598955, 31820368, 15075278}}, + {{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788, -9650886, -17970238, 12833045}, + {19073683, 14851414, -24403169, -11860168, 7625278, 11091125, -19619190, 2074449, -9413939, 14905377}, + {24483667, -11935567, -2518866, -11547418, -1553130, 15355506, -25282080, 9253129, 27628530, -7555480}}, + {{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324, -9157582, -14110875, 15297016}, + {510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417, -11864220, 8683221, 2921426}, + {18606791, 11874196, 27155355, -5281482, -24031742, 6265446, -25178240, -1278924, 4674690, 13890525}}, + {{13609624, 13069022, -27372361, -13055908, 24360586, 9592974, 14977157, 9835105, 4389687, 288396}, + {9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062, 8317628, 23388070, 16052080}, + {12720016, 11937594, -31970060, -5028689, 26900120, 8561328, -20155687, -11632979, -14754271, -10812892}}, + {{15961858, 14150409, 26716931, -665832, -22794328, 13603569, 11829573, 7467844, -28822128, 929275}, + {11038231, -11582396, -27310482, -7316562, -10498527, -16307831, -23479533, -9371869, -21393143, 2465074}, + {20017163, -4323226, 27915242, 1529148, 12396362, 15675764, 13817261, -9658066, 2463391, -4622140}}, + {{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572, 9583558, 12851107, 4003896, 12673717}, + {-1731589, -15155870, -3262930, 16143082, 19294135, 13385325, 14741514, -9103726, 7903886, 2348101}, + {24536016, -16515207, 12715592, -3862155, 1511293, 10047386, -3842346, -7129159, -28377538, 10048127}} + }, { + {{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840, 18873298, -7297090, -32297756, 15221632}, + {-26478122, -11103864, 11546244, -1852483, 9180880, 7656409, -21343950, 2095755, 29769758, 6593415}, + {-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345, -6118678, 30958054, 8292160}}, + {{31429822, -13959116, 29173532, 15632448, 12174511, -2760094, 32808831, 3977186, 26143136, -3148876}, + {22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633, -1674433, -3758243, -2304625}, + {-15491917, 8012313, -2514730, -12702462, -23965846, -10254029, -1612713, -1535569, -16664475, 8194478}}, + {{27338066, -7507420, -7414224, 10140405, -19026427, -6589889, 27277191, 8855376, 28572286, 3005164}, + {26287124, 4821776, 25476601, -4145903, -3764513, -15788984, -18008582, 1182479, -26094821, -13079595}, + {-7171154, 3178080, 23970071, 6201893, -17195577, -4489192, -21876275, -13982627, 32208683, -1198248}}, + {{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505, -27315504, -10497842, -27672585, -11539858}, + {15941029, -9405932, -21367050, 8062055, 31876073, -238629, -15278393, -1444429, 15397331, -4130193}, + {8934485, -13485467, -23286397, -13423241, -32446090, 14047986, 31170398, -1441021, -27505566, 15087184}}, + {{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776, -15502406, 11461896, 16788528, -5868942}, + {-1947386, 16013773, 21750665, 3714552, -17401782, -16055433, -3770287, -10323320, 31322514, -11615635}, + {21426655, -5650218, -13648287, -5347537, -28812189, -4920970, -18275391, -14621414, 13040862, -12112948}}, + {{11293895, 12478086, -27136401, 15083750, -29307421, 14748872, 14555558, -13417103, 1613711, 4896935}, + {-25894883, 15323294, -8489791, -8057900, 25967126, -13425460, 2825960, -4897045, -23971776, -11267415}, + {-15924766, -5229880, -17443532, 6410664, 3622847, 10243618, 20615400, 12405433, -23753030, -8436416}}, + {{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801, 4378436, 2432030, 23097949, -566018}, + {4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264, 10103221, -18512313, 2424778}, + {366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678, 1344109, -3642553, 12412659}}, + {{-24001791, 7690286, 14929416, -168257, -32210835, -13412986, 24162697, -15326504, -3141501, 11179385}, + {18289522, -14724954, 8056945, 16430056, -21729724, 7842514, -6001441, -1486897, -18684645, -11443503}, + {476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959, 13403813, 11052904, 5219329}} + }, { + {{20678546, -8375738, -32671898, 8849123, -5009758, 14574752, 31186971, -3973730, 9014762, -8579056}, + {-13644050, -10350239, -15962508, 5075808, -1514661, -11534600, -33102500, 9160280, 8473550, -3256838}, + {24900749, 14435722, 17209120, -15292541, -22592275, 9878983, -7689309, -16335821, -24568481, 11788948}}, + {{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904, -20037437, 10410733, -24568470, -1458691}, + {-15659161, 16736706, -22467150, 10215878, -9097177, 7563911, 11871841, -12505194, -18513325, 8464118}, + {-23400612, 8348507, -14585951, -861714, -3950205, -6373419, 14325289, 8628612, 33313881, -8370517}}, + {{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838, -24805667, -10236854, -8940735, -5818269}, + {-6948785, -1795212, -32625683, -16021179, 32635414, -7374245, 15989197, -12838188, 28358192, -4253904}, + {-23561781, -2799059, -32351682, -1661963, -9147719, 10429267, -16637684, 4072016, -5351664, 5596589}}, + {{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565, 29266239, 2557221, 1768301, 15373193}, + {-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902, -4504991, -24660491, 3442910}, + {-30210571, 5124043, 14181784, 8197961, 18964734, -11939093, 22597931, 7176455, -18585478, 13365930}}, + {{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107, -8570186, -9689599, -3031667}, + {25008904, -10771599, -4305031, -9638010, 16265036, 15721635, 683793, -11823784, 15723479, -15163481}, + {-9660625, 12374379, -27006999, -7026148, -7724114, -12314514, 11879682, 5400171, 519526, -1235876}}, + {{22258397, -16332233, -7869817, 14613016, -22520255, -2950923, -20353881, 7315967, 16648397, 7605640}, + {-8081308, -8464597, -8223311, 9719710, 19259459, -15348212, 23994942, -5281555, -9468848, 4763278}, + {-21699244, 9220969, -15730624, 1084137, -25476107, -2852390, 31088447, -7764523, -11356529, 728112}}, + {{26047220, -11751471, -6900323, -16521798, 24092068, 9158119, -4273545, -12555558, -29365436, -5498272}, + {17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007, 12327945, 10750447, 10014012}, + {-10312768, 3936952, 9156313, -8897683, 16498692, -994647, -27481051, -666732, 3424691, 7540221}}, + {{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422, -16317219, -9244265, 15258046}, + {13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406, 2711395, 1062915, -5136345}, + {-19240248, -11254599, -29509029, -7499965, -5835763, 13005411, -6066489, 12194497, 32960380, 1459310}} + }, { + {{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197, -6101885, 18638003, -11174937}, + {31395534, 15098109, 26581030, 8030562, -16527914, -5007134, 9012486, -7584354, -6643087, -5442636}, + {-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222, 9677543, -32294889, -6456008}}, + {{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579, -7839692, -7852844, -8138429}, + {-15236356, -15433509, 7766470, 746860, 26346930, -10221762, -27333451, 10754588, -9431476, 5203576}, + {31834314, 14135496, -770007, 5159118, 20917671, -16768096, -7467973, -7337524, 31809243, 7347066}}, + {{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881, 19797970, -12211255, 15192876, -2087490}, + {-12663563, -2181719, 1168162, -3804809, 26747877, -14138091, 10609330, 12694420, 33473243, -13382104}, + {33184999, 11180355, 15832085, -11385430, -1633671, 225884, 15089336, -11023903, -6135662, 14480053}}, + {{31308717, -5619998, 31030840, -1897099, 15674547, -6582883, 5496208, 13685227, 27595050, 8737275}, + {-20318852, -15150239, 10933843, -16178022, 8335352, -7546022, -31008351, -12610604, 26498114, 66511}, + {22644454, -8761729, -16671776, 4884562, -3105614, -13559366, 30540766, -4286747, -13327787, -7515095}}, + {{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506, 8205540, 13585437, -17127465, 15115439}, + {23711543, -672915, 31206561, -8362711, 6164647, -9709987, -33535882, -1426096, 8236921, 16492939}, + {-23910559, -13515526, -26299483, -4503841, 25005590, -7687270, 19574902, 10071562, 6708380, -6222424}}, + {{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017, 9328700, 29955601, -11678310}, + {3096359, 9271816, -21620864, -15521844, -14847996, -7592937, -25892142, -12635595, -9917575, 6216608}, + {-32615849, 338663, -25195611, 2510422, -29213566, -13820213, 24822830, -6146567, -26767480, 7525079}}, + {{-23066649, -13985623, 16133487, -7896178, -3389565, 778788, -910336, -2782495, -19386633, 11994101}, + {21691500, -13624626, -641331, -14367021, 3285881, -3483596, -25064666, 9718258, -7477437, 13381418}, + {18445390, -4202236, 14979846, 11622458, -1727110, -3582980, 23111648, -6375247, 28535282, 15779576}}, + {{30098053, 3089662, -9234387, 16662135, -21306940, 11308411, -14068454, 12021730, 9955285, -16303356}, + {9734894, -14576830, -7473633, -9138735, 2060392, 11313496, -18426029, 9924399, 20194861, 13380996}, + {-26378102, -7965207, -22167821, 15789297, -18055342, -6168792, -1984914, 15707771, 26342023, 10146099}} + }, { + {{-26016874, -219943, 21339191, -41388, 19745256, -2878700, -29637280, 2227040, 21612326, -545728}, + {-13077387, 1184228, 23562814, -5970442, -20351244, -6348714, 25764461, 12243797, -20856566, 11649658}, + {-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944, 6114064, 33514190, 2333242}}, + {{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134, -6679750, -12670638, 24350578, -13450001}, + {-4116307, -11271533, -23886186, 4843615, -30088339, 690623, -31536088, -10406836, 8317860, 12352766}, + {18200138, -14475911, -33087759, -2696619, -23702521, -9102511, -23552096, -2287550, 20712163, 6719373}}, + {{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530, -3763210, 26224235, -3297458}, + {-17168938, -14854097, -3395676, -16369877, -19954045, 14050420, 21728352, 9493610, 18620611, -16428628}, + {-13323321, 13325349, 11432106, 5964811, 18609221, 6062965, -5269471, -9725556, -30701573, -16479657}}, + {{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940, 12248509, -5240639, 13735342, 1934062}, + {25089769, 6742589, 17081145, -13406266, 21909293, -16067981, -15136294, -3765346, -21277997, 5473616}, + {31883677, -7961101, 1083432, -11572403, 22828471, 13290673, -7125085, 12469656, 29111212, -5451014}}, + {{24244947, -15050407, -26262976, 2791540, -14997599, 16666678, 24367466, 6388839, -10295587, 452383}, + {-25640782, -3417841, 5217916, 16224624, 19987036, -4082269, -24236251, -5915248, 15766062, 8407814}, + {-20406999, 13990231, 15495425, 16395525, 5377168, 15166495, -8917023, -4388953, -8067909, 2276718}}, + {{30157918, 12924066, -17712050, 9245753, 19895028, 3368142, -23827587, 5096219, 22740376, -7303417}, + {2041139, -14256350, 7783687, 13876377, -25946985, -13352459, 24051124, 13742383, -15637599, 13295222}, + {33338237, -8505733, 12532113, 7977527, 9106186, -1715251, -17720195, -4612972, -4451357, -14669444}}, + {{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651, -2469266, -4141880, 7770569, 9620597}, + {23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528, -1694323, -33502340, -14767970}, + {1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801, 1220118, 30494170, -11440799}}, + {{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666, -26739026, 926050, -1684339, -13333647}, + {13908495, -3549272, 30919928, -6273825, -21521863, 7989039, 9021034, 9078865, 3353509, 4033511}, + {-29663431, -15113610, 32259991, -344482, 24295849, -12912123, 23161163, 8839127, 27485041, 7356032}} + }, { + {{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142, 2625015, 28431036, -16771834}, + {-23839233, -8311415, -25945511, 7480958, -17681669, -8354183, -22545972, 14150565, 15970762, 4099461}, + {29262576, 16756590, 26350592, -8793563, 8529671, -11208050, 13617293, -9937143, 11465739, 8317062}}, + {{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222, 14898637, 3848455, 20969334, -5157516}, + {-20384450, -14347713, -18336405, 13884722, -33039454, 2842114, -21610826, -3649888, 11177095, 14989547}, + {-24496721, -11716016, 16959896, 2278463, 12066309, 10137771, 13515641, 2581286, -28487508, 9930240}}, + {{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081, 18345767, -13403753, 16291481, -5314038}, + {-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774, 6957617, 4368891, 9788741}, + {16660756, 7281060, -10830758, 12911820, 20108584, -8101676, -21722536, -8613148, 16250552, -11111103}}, + {{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584, 10604807, -30190403, 4782747}, + {-1354539, 14736941, -7367442, -13292886, 7710542, -14155590, -9981571, 4383045, 22546403, 437323}, + {31665577, -12180464, -16186830, 1491339, -18368625, 3294682, 27343084, 2786261, -30633590, -14097016}}, + {{-14467279, -683715, -33374107, 7448552, 19294360, 14334329, -19690631, 2355319, -19284671, -6114373}, + {15121312, -15796162, 6377020, -6031361, -10798111, -12957845, 18952177, 15496498, -29380133, 11754228}, + {-2637277, -13483075, 8488727, -14303896, 12728761, -1622493, 7141596, 11724556, 22761615, -10134141}}, + {{16918416, 11729663, -18083579, 3022987, -31015732, -13339659, -28741185, -12227393, 32851222, 11717399}, + {11166634, 7338049, -6722523, 4531520, -29468672, -7302055, 31474879, 3483633, -1193175, -4030831}, + {-185635, 9921305, 31456609, -13536438, -12013818, 13348923, 33142652, 6546660, -19985279, -3948376}}, + {{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903, -8537131, -12833048, -30772034, -15486313}, + {-18006477, 12709068, 3991746, -6479188, -21491523, -10550425, -31135347, -16049879, 10928917, 3011958}, + {-6957757, -15594337, 31696059, 334240, 29576716, 14796075, -30831056, -12805180, 18008031, 10258577}}, + {{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591, -1853465, 1367120, 25127874, 6671743}, + {29701166, -14373934, -10878120, 9279288, -17568, 13127210, 21382910, 11042292, 25838796, 4642684}, + {-20430234, 14955537, -24126347, 8124619, -5369288, -5990470, 30468147, -13900640, 18423289, 4177476}} + } +}; + +const ge_precomp ge_Bi[8] = { + {{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605}, + {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692, 5043384, 19500929, -15469378}, + {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919, 11864899, -24514362, -4438546}}, {{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600, -14772189, 28944400, -1550024}, + {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577, -11775962, 7689662, 11199574}, + {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774, 10017326, -17749093, -9920357}}, {{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885, 14515107, -15438304, 10819380}, + {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668, 12483688, -12668491, 5581306}, + {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350, 13850243, -23678021, -15815942}}, {{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852, 5230134, -23952439, -15175766}, + {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025, 16520125, 30598449, 7715701}, + {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660, 1370708, 29794553, -1409300}}, {{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211, -1361450, -13062696, 13821877}, + {-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028, -7212327, 18853322, -14220951}, + {4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358, -10431137, 2207753, -3209784}}, {{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364, -663000, -31111463, -16132436}, + {25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789, 15725684, 171356, 6466918}, + {23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339, -14088058, -30714912, 16193877}}, {{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398, 4729455, -18074513, 9256800}, + {-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405, 9761698, -19827198, 630305}, + {-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551, -15960994, -2449256, -14291300}}, {{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575, 15033784, 25105118, -7894876}, + {-24326370, 15950226, -31801215, -14592823, -11662737, -5090925, 1573892, -2625887, 2198790, -15804619}, + {-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022, -16236442, -32461234, -12290683}} +}; + +/* A = 2 * (1 - d) / (1 + d) = 486662 */ +const fe fe_ma2 = {-12721188, -3529, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A^2 */ +const fe fe_ma = {-486662, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* -A */ +const fe fe_fffb1 = {-31702527, -2466483, -26106795, -12203692, -12169197, -321052, 14850977, -10296299, -16929438, -407568}; /* sqrt(-2 * A * (A + 2)) */ +const fe fe_fffb2 = {8166131, -6741800, -17040804, 3154616, 21461005, 1466302, -30876704, -6368709, 10503587, -13363080}; /* sqrt(2 * A * (A + 2)) */ +const fe fe_fffb3 = {-13620103, 14639558, 4532995, 7679154, 16815101, -15883539, -22863840, -14813421, 13716513, -6477756}; /* sqrt(-sqrt(-1) * A * (A + 2)) */ +const fe fe_fffb4 = {-21786234, -12173074, 21573800, 4524538, -4645904, 16204591, 8012863, -8444712, 3212926, 6885324}; /* sqrt(sqrt(-1) * A * (A + 2)) */ diff --git a/crypto/upstream/crypto-ops.c b/crypto/upstream/crypto-ops.c new file mode 100755 index 0000000..1ab2148 --- /dev/null +++ b/crypto/upstream/crypto-ops.c @@ -0,0 +1,4473 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#include +#include +#include +#include +#include "warnings.h" +#include "crypto-ops.h" +#include "hash-ops.h" // for cn_fast_hash + +DISABLE_VS_WARNINGS(4146 4244) + +/* Predeclarations */ + +void fe_mul(fe, const fe, const fe); +void fe_sq(fe, const fe); +void fe_tobytes(unsigned char *, const fe); +static void ge_msub(ge_p1p1 *, const ge_p3 *, const ge_precomp *); +static void ge_p2_0(ge_p2 *); +static void ge_p3_dbl(ge_p1p1 *, const ge_p3 *); +void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *); +static void fe_divpowm1(fe, const fe, const fe); + +/* Common functions */ + +static uint64_t load_3(const unsigned char *in) { + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + return result; +} + +static uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + result |= ((uint64_t) in[3]) << 24; + return result; +} + +/* From fe_0.c */ + +/* +h = 0 +*/ + +void fe_0(fe h) { + h[0] = 0; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} + +/* From fe_1.c */ + +/* +h = 1 +*/ + +static void fe_1(fe h) { + h[0] = 1; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} + +/* From fe_add.c */ + +/* +h = f + g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_add(fe h, const fe f, const fe g) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t h0 = f0 + g0; + int32_t h1 = f1 + g1; + int32_t h2 = f2 + g2; + int32_t h3 = f3 + g3; + int32_t h4 = f4 + g4; + int32_t h5 = f5 + g5; + int32_t h6 = f6 + g6; + int32_t h7 = f7 + g7; + int32_t h8 = f8 + g8; + int32_t h9 = f9 + g9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + +/* From fe_cmov.c */ + +/* +Replace (f,g) with (g,g) if b == 1; +replace (f,g) with (f,g) if b == 0. + +Preconditions: b in {0,1}. +*/ + +static void fe_cmov(fe f, const fe g, unsigned int b) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t x0 = f0 ^ g0; + int32_t x1 = f1 ^ g1; + int32_t x2 = f2 ^ g2; + int32_t x3 = f3 ^ g3; + int32_t x4 = f4 ^ g4; + int32_t x5 = f5 ^ g5; + int32_t x6 = f6 ^ g6; + int32_t x7 = f7 ^ g7; + int32_t x8 = f8 ^ g8; + int32_t x9 = f9 ^ g9; + assert((((b - 1) & ~b) | ((b - 2) & ~(b - 1))) == (unsigned int) -1); + b = -b; + x0 &= b; + x1 &= b; + x2 &= b; + x3 &= b; + x4 &= b; + x5 &= b; + x6 &= b; + x7 &= b; + x8 &= b; + x9 &= b; + f[0] = f0 ^ x0; + f[1] = f1 ^ x1; + f[2] = f2 ^ x2; + f[3] = f3 ^ x3; + f[4] = f4 ^ x4; + f[5] = f5 ^ x5; + f[6] = f6 ^ x6; + f[7] = f7 ^ x7; + f[8] = f8 ^ x8; + f[9] = f9 ^ x9; +} + +/* From fe_copy.c */ + +/* +h = f +*/ + +static void fe_copy(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + h[0] = f0; + h[1] = f1; + h[2] = f2; + h[3] = f3; + h[4] = f4; + h[5] = f5; + h[6] = f6; + h[7] = f7; + h[8] = f8; + h[9] = f9; +} + +/* From fe_invert.c */ + +void fe_invert(fe out, const fe z) { + fe t0; + fe t1; + fe t2; + fe t3; + int i; + + fe_sq(t0, z); + fe_sq(t1, t0); + fe_sq(t1, t1); + fe_mul(t1, z, t1); + fe_mul(t0, t0, t1); + fe_sq(t2, t0); + fe_mul(t1, t1, t2); + fe_sq(t2, t1); + for (i = 0; i < 4; ++i) { + fe_sq(t2, t2); + } + fe_mul(t1, t2, t1); + fe_sq(t2, t1); + for (i = 0; i < 9; ++i) { + fe_sq(t2, t2); + } + fe_mul(t2, t2, t1); + fe_sq(t3, t2); + for (i = 0; i < 19; ++i) { + fe_sq(t3, t3); + } + fe_mul(t2, t3, t2); + fe_sq(t2, t2); + for (i = 0; i < 9; ++i) { + fe_sq(t2, t2); + } + fe_mul(t1, t2, t1); + fe_sq(t2, t1); + for (i = 0; i < 49; ++i) { + fe_sq(t2, t2); + } + fe_mul(t2, t2, t1); + fe_sq(t3, t2); + for (i = 0; i < 99; ++i) { + fe_sq(t3, t3); + } + fe_mul(t2, t3, t2); + fe_sq(t2, t2); + for (i = 0; i < 49; ++i) { + fe_sq(t2, t2); + } + fe_mul(t1, t2, t1); + fe_sq(t1, t1); + for (i = 0; i < 4; ++i) { + fe_sq(t1, t1); + } + fe_mul(out, t1, t0); + + return; +} + +/* From fe_isnegative.c */ + +/* +return 1 if f is in {1,3,5,...,q-2} +return 0 if f is in {0,2,4,...,q-1} + +Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +int fe_isnegative(const fe f) { + unsigned char s[32]; + fe_tobytes(s, f); + return s[0] & 1; +} + +/* From fe_isnonzero.c, modified */ + +int fe_isnonzero(const fe f) { + unsigned char s[32]; + fe_tobytes(s, f); + return (((int) (s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] | s[8] | + s[9] | s[10] | s[11] | s[12] | s[13] | s[14] | s[15] | s[16] | s[17] | + s[18] | s[19] | s[20] | s[21] | s[22] | s[23] | s[24] | s[25] | s[26] | + s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1; +} + +/* From fe_mul.c */ + +/* +h = f * g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +Notes on implementation strategy: + +Using schoolbook multiplication. +Karatsuba would save a little in some cost models. + +Most multiplications by 2 and 19 are 32-bit precomputations; +cheaper than 64-bit postcomputations. + +There is one remaining multiplication by 19 in the carry chain; +one *19 precomputation can be merged into this, +but the resulting data flow is considerably less clean. + +There are 12 carries below. +10 of them are 2-way parallelizable and vectorizable. +Can get away with 11 carries, but then data flow is much deeper. + +With tighter constraints on inputs can squeeze carries into int32. +*/ + +void fe_mul(fe h, const fe f, const fe g) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */ + int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + int32_t g3_19 = 19 * g3; + int32_t g4_19 = 19 * g4; + int32_t g5_19 = 19 * g5; + int32_t g6_19 = 19 * g6; + int32_t g7_19 = 19 * g7; + int32_t g8_19 = 19 * g8; + int32_t g9_19 = 19 * g9; + int32_t f1_2 = 2 * f1; + int32_t f3_2 = 2 * f3; + int32_t f5_2 = 2 * f5; + int32_t f7_2 = 2 * f7; + int32_t f9_2 = 2 * f9; + int64_t f0g0 = f0 * (int64_t) g0; + int64_t f0g1 = f0 * (int64_t) g1; + int64_t f0g2 = f0 * (int64_t) g2; + int64_t f0g3 = f0 * (int64_t) g3; + int64_t f0g4 = f0 * (int64_t) g4; + int64_t f0g5 = f0 * (int64_t) g5; + int64_t f0g6 = f0 * (int64_t) g6; + int64_t f0g7 = f0 * (int64_t) g7; + int64_t f0g8 = f0 * (int64_t) g8; + int64_t f0g9 = f0 * (int64_t) g9; + int64_t f1g0 = f1 * (int64_t) g0; + int64_t f1g1_2 = f1_2 * (int64_t) g1; + int64_t f1g2 = f1 * (int64_t) g2; + int64_t f1g3_2 = f1_2 * (int64_t) g3; + int64_t f1g4 = f1 * (int64_t) g4; + int64_t f1g5_2 = f1_2 * (int64_t) g5; + int64_t f1g6 = f1 * (int64_t) g6; + int64_t f1g7_2 = f1_2 * (int64_t) g7; + int64_t f1g8 = f1 * (int64_t) g8; + int64_t f1g9_38 = f1_2 * (int64_t) g9_19; + int64_t f2g0 = f2 * (int64_t) g0; + int64_t f2g1 = f2 * (int64_t) g1; + int64_t f2g2 = f2 * (int64_t) g2; + int64_t f2g3 = f2 * (int64_t) g3; + int64_t f2g4 = f2 * (int64_t) g4; + int64_t f2g5 = f2 * (int64_t) g5; + int64_t f2g6 = f2 * (int64_t) g6; + int64_t f2g7 = f2 * (int64_t) g7; + int64_t f2g8_19 = f2 * (int64_t) g8_19; + int64_t f2g9_19 = f2 * (int64_t) g9_19; + int64_t f3g0 = f3 * (int64_t) g0; + int64_t f3g1_2 = f3_2 * (int64_t) g1; + int64_t f3g2 = f3 * (int64_t) g2; + int64_t f3g3_2 = f3_2 * (int64_t) g3; + int64_t f3g4 = f3 * (int64_t) g4; + int64_t f3g5_2 = f3_2 * (int64_t) g5; + int64_t f3g6 = f3 * (int64_t) g6; + int64_t f3g7_38 = f3_2 * (int64_t) g7_19; + int64_t f3g8_19 = f3 * (int64_t) g8_19; + int64_t f3g9_38 = f3_2 * (int64_t) g9_19; + int64_t f4g0 = f4 * (int64_t) g0; + int64_t f4g1 = f4 * (int64_t) g1; + int64_t f4g2 = f4 * (int64_t) g2; + int64_t f4g3 = f4 * (int64_t) g3; + int64_t f4g4 = f4 * (int64_t) g4; + int64_t f4g5 = f4 * (int64_t) g5; + int64_t f4g6_19 = f4 * (int64_t) g6_19; + int64_t f4g7_19 = f4 * (int64_t) g7_19; + int64_t f4g8_19 = f4 * (int64_t) g8_19; + int64_t f4g9_19 = f4 * (int64_t) g9_19; + int64_t f5g0 = f5 * (int64_t) g0; + int64_t f5g1_2 = f5_2 * (int64_t) g1; + int64_t f5g2 = f5 * (int64_t) g2; + int64_t f5g3_2 = f5_2 * (int64_t) g3; + int64_t f5g4 = f5 * (int64_t) g4; + int64_t f5g5_38 = f5_2 * (int64_t) g5_19; + int64_t f5g6_19 = f5 * (int64_t) g6_19; + int64_t f5g7_38 = f5_2 * (int64_t) g7_19; + int64_t f5g8_19 = f5 * (int64_t) g8_19; + int64_t f5g9_38 = f5_2 * (int64_t) g9_19; + int64_t f6g0 = f6 * (int64_t) g0; + int64_t f6g1 = f6 * (int64_t) g1; + int64_t f6g2 = f6 * (int64_t) g2; + int64_t f6g3 = f6 * (int64_t) g3; + int64_t f6g4_19 = f6 * (int64_t) g4_19; + int64_t f6g5_19 = f6 * (int64_t) g5_19; + int64_t f6g6_19 = f6 * (int64_t) g6_19; + int64_t f6g7_19 = f6 * (int64_t) g7_19; + int64_t f6g8_19 = f6 * (int64_t) g8_19; + int64_t f6g9_19 = f6 * (int64_t) g9_19; + int64_t f7g0 = f7 * (int64_t) g0; + int64_t f7g1_2 = f7_2 * (int64_t) g1; + int64_t f7g2 = f7 * (int64_t) g2; + int64_t f7g3_38 = f7_2 * (int64_t) g3_19; + int64_t f7g4_19 = f7 * (int64_t) g4_19; + int64_t f7g5_38 = f7_2 * (int64_t) g5_19; + int64_t f7g6_19 = f7 * (int64_t) g6_19; + int64_t f7g7_38 = f7_2 * (int64_t) g7_19; + int64_t f7g8_19 = f7 * (int64_t) g8_19; + int64_t f7g9_38 = f7_2 * (int64_t) g9_19; + int64_t f8g0 = f8 * (int64_t) g0; + int64_t f8g1 = f8 * (int64_t) g1; + int64_t f8g2_19 = f8 * (int64_t) g2_19; + int64_t f8g3_19 = f8 * (int64_t) g3_19; + int64_t f8g4_19 = f8 * (int64_t) g4_19; + int64_t f8g5_19 = f8 * (int64_t) g5_19; + int64_t f8g6_19 = f8 * (int64_t) g6_19; + int64_t f8g7_19 = f8 * (int64_t) g7_19; + int64_t f8g8_19 = f8 * (int64_t) g8_19; + int64_t f8g9_19 = f8 * (int64_t) g9_19; + int64_t f9g0 = f9 * (int64_t) g0; + int64_t f9g1_38 = f9_2 * (int64_t) g1_19; + int64_t f9g2_19 = f9 * (int64_t) g2_19; + int64_t f9g3_38 = f9_2 * (int64_t) g3_19; + int64_t f9g4_19 = f9 * (int64_t) g4_19; + int64_t f9g5_38 = f9_2 * (int64_t) g5_19; + int64_t f9g6_19 = f9 * (int64_t) g6_19; + int64_t f9g7_38 = f9_2 * (int64_t) g7_19; + int64_t f9g8_19 = f9 * (int64_t) g8_19; + int64_t f9g9_38 = f9_2 * (int64_t) g9_19; + int64_t h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; + int64_t h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; + int64_t h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; + int64_t h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; + int64_t h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; + int64_t h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; + int64_t h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; + int64_t h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; + int64_t h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; + int64_t h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + /* + |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) + i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 + |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) + i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 + */ + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + /* |h0| <= 2^25 */ + /* |h4| <= 2^25 */ + /* |h1| <= 1.71*2^59 */ + /* |h5| <= 1.71*2^59 */ + + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + /* |h1| <= 2^24; from now on fits into int32 */ + /* |h5| <= 2^24; from now on fits into int32 */ + /* |h2| <= 1.41*2^60 */ + /* |h6| <= 1.41*2^60 */ + + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + /* |h2| <= 2^25; from now on fits into int32 unchanged */ + /* |h6| <= 2^25; from now on fits into int32 unchanged */ + /* |h3| <= 1.71*2^59 */ + /* |h7| <= 1.71*2^59 */ + + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + /* |h3| <= 2^24; from now on fits into int32 unchanged */ + /* |h7| <= 2^24; from now on fits into int32 unchanged */ + /* |h4| <= 1.72*2^34 */ + /* |h8| <= 1.41*2^60 */ + + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + /* |h4| <= 2^25; from now on fits into int32 unchanged */ + /* |h8| <= 2^25; from now on fits into int32 unchanged */ + /* |h5| <= 1.01*2^24 */ + /* |h9| <= 1.71*2^59 */ + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + /* |h9| <= 2^24; from now on fits into int32 unchanged */ + /* |h0| <= 1.1*2^39 */ + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + /* |h0| <= 2^25; from now on fits into int32 unchanged */ + /* |h1| <= 1.01*2^24 */ + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + +/* From fe_neg.c */ + +/* +h = -f + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +*/ + +static void fe_neg(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t h0 = -f0; + int32_t h1 = -f1; + int32_t h2 = -f2; + int32_t h3 = -f3; + int32_t h4 = -f4; + int32_t h5 = -f5; + int32_t h6 = -f6; + int32_t h7 = -f7; + int32_t h8 = -f8; + int32_t h9 = -f9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + +/* From fe_sq.c */ + +/* +h = f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +void fe_sq(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; + int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; + int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; + int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; + int64_t h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; + int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; + int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; + int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; + int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; + int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + +/* From fe_sq2.c */ + +/* +h = 2 * f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +static void fe_sq2(fe h, const fe f) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; + int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; + int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; + int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; + int64_t h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; + int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; + int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; + int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; + int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; + int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + h0 += h0; + h1 += h1; + h2 += h2; + h3 += h3; + h4 += h4; + h5 += h5; + h6 += h6; + h7 += h7; + h8 += h8; + h9 += h9; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + +/* From fe_sub.c */ + +/* +h = f - g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_sub(fe h, const fe f, const fe g) { + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t h0 = f0 - g0; + int32_t h1 = f1 - g1; + int32_t h2 = f2 - g2; + int32_t h3 = f3 - g3; + int32_t h4 = f4 - g4; + int32_t h5 = f5 - g5; + int32_t h6 = f6 - g6; + int32_t h7 = f7 - g7; + int32_t h8 = f8 - g8; + int32_t h9 = f9 - g9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + +/* From fe_tobytes.c */ + +/* +Preconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + +Write p=2^255-19; q=floor(h/p). +Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). + +Proof: + Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. + Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. + + Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). + Then 0> 25; + q = (h0 + q) >> 26; + q = (h1 + q) >> 25; + q = (h2 + q) >> 26; + q = (h3 + q) >> 25; + q = (h4 + q) >> 26; + q = (h5 + q) >> 25; + q = (h6 + q) >> 26; + q = (h7 + q) >> 25; + q = (h8 + q) >> 26; + q = (h9 + q) >> 25; + + /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ + h0 += 19 * q; + /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ + + carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; + carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; + carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; + carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; + carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; + carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; + carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; + carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; + carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; + carry9 = h9 >> 25; h9 -= carry9 << 25; + /* h10 = carry9 */ + + /* + Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + Have h0+...+2^230 h9 between 0 and 2^255-1; + evidently 2^255 h10-2^255 q = 0. + Goal: Output h0+...+2^230 h9. + */ + + s[0] = h0 >> 0; + s[1] = h0 >> 8; + s[2] = h0 >> 16; + s[3] = (h0 >> 24) | (h1 << 2); + s[4] = h1 >> 6; + s[5] = h1 >> 14; + s[6] = (h1 >> 22) | (h2 << 3); + s[7] = h2 >> 5; + s[8] = h2 >> 13; + s[9] = (h2 >> 21) | (h3 << 5); + s[10] = h3 >> 3; + s[11] = h3 >> 11; + s[12] = (h3 >> 19) | (h4 << 6); + s[13] = h4 >> 2; + s[14] = h4 >> 10; + s[15] = h4 >> 18; + s[16] = h5 >> 0; + s[17] = h5 >> 8; + s[18] = h5 >> 16; + s[19] = (h5 >> 24) | (h6 << 1); + s[20] = h6 >> 7; + s[21] = h6 >> 15; + s[22] = (h6 >> 23) | (h7 << 3); + s[23] = h7 >> 5; + s[24] = h7 >> 13; + s[25] = (h7 >> 21) | (h8 << 4); + s[26] = h8 >> 4; + s[27] = h8 >> 12; + s[28] = (h8 >> 20) | (h9 << 6); + s[29] = h9 >> 2; + s[30] = h9 >> 10; + s[31] = h9 >> 18; +} + +/* From ge_add.c */ + +void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { + fe t0; + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->YplusX); + fe_mul(r->Y, r->Y, q->YminusX); + fe_mul(r->T, q->T2d, p->T); + fe_mul(r->X, p->Z, q->Z); + fe_add(t0, r->X, r->X); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_add(r->Z, t0, r->T); + fe_sub(r->T, t0, r->T); +} + +/* From ge_double_scalarmult.c, modified */ + +static void slide(signed char *r, const unsigned char *a) { + int i; + int b; + int k; + + for (i = 0; i < 256; ++i) { + r[i] = 1 & (a[i >> 3] >> (i & 7)); + } + + for (i = 0; i < 256; ++i) { + if (r[i]) { + for (b = 1; b <= 6 && i + b < 256; ++b) { + if (r[i + b]) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; r[i + b] = 0; + } else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + for (k = i + b; k < 256; ++k) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else + break; + } + } + } + } +} + +void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s) { + ge_p1p1 t; + ge_p3 s2, u; + ge_p3_to_cached(&r[0], s); + ge_p3_dbl(&t, s); ge_p1p1_to_p3(&s2, &t); + ge_add(&t, &s2, &r[0]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[1], &u); + ge_add(&t, &s2, &r[1]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[2], &u); + ge_add(&t, &s2, &r[2]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[3], &u); + ge_add(&t, &s2, &r[3]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[4], &u); + ge_add(&t, &s2, &r[4]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[5], &u); + ge_add(&t, &s2, &r[5]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[6], &u); + ge_add(&t, &s2, &r[6]); ge_p1p1_to_p3(&u, &t); ge_p3_to_cached(&r[7], &u); +} + +/* +r = a * A + b * B +where a = a[0]+256*a[1]+...+256^31 a[31]. +and b = b[0]+256*b[1]+...+256^31 b[31]. +B is the Ed25519 base point (x,4/5) with x positive. +*/ + +void ge_double_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { + signed char aslide[256]; + signed char bslide[256]; + ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ + ge_p1p1 t; + ge_p3 u; + int i; + + slide(aslide, a); + slide(bslide, b); + ge_dsm_precomp(Ai, A); + + ge_p2_0(r); + + for (i = 255; i >= 0; --i) { + if (aslide[i] || bslide[i]) break; + } + + for (; i >= 0; --i) { + ge_p2_dbl(&t, r); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Ai[aslide[i]/2]); + } else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Ai[(-aslide[i])/2]); + } + + if (bslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_madd(&t, &u, &ge_Bi[bslide[i]/2]); + } else if (bslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_msub(&t, &u, &ge_Bi[(-bslide[i])/2]); + } + + ge_p1p1_to_p2(r, &t); + } +} + +/* +r = a * A + b * B +where a = a[0]+256*a[1]+...+256^31 a[31]. +and b = b[0]+256*b[1]+...+256^31 b[31]. +B is the Ed25519 base point (x,4/5) with x positive. +*/ + +void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { + signed char aslide[256]; + signed char bslide[256]; + ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ + ge_p1p1 t; + ge_p3 u; + ge_p2 r_p2; + int i; + + slide(aslide, a); + slide(bslide, b); + ge_dsm_precomp(Ai, A); + + ge_p2_0(&r_p2); + + for (i = 255; i >= 0; --i) { + if (aslide[i] || bslide[i]) break; + } + + for (; i >= 0; --i) { + ge_p2_dbl(&t, &r_p2); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Ai[aslide[i]/2]); + } else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Ai[(-aslide[i])/2]); + } + + if (bslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_madd(&t, &u, &ge_Bi[bslide[i]/2]); + } else if (bslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_msub(&t, &u, &ge_Bi[(-bslide[i])/2]); + } + + if (i != 0) + ge_p1p1_to_p2(&r_p2, &t); + else + ge_p1p1_to_p3(r, &t); // last step + } +} + +void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A) { + signed char aslide[256]; + ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ + ge_p1p1 t; + ge_p3 u; + ge_p2 r_p2; + int i; + + slide(aslide, a); + ge_dsm_precomp(Ai, A); + + ge_p2_0(&r_p2); + ge_p3_0(r); + + for (i = 255; i >= 0; --i) { + if (aslide[i]) break; + } + + for (; i >= 0; --i) { + ge_p2_dbl(&t, &r_p2); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Ai[aslide[i] / 2]); + } + else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); + } + + if (i != 0) + ge_p1p1_to_p2(&r_p2, &t); + else + ge_p1p1_to_p3(r, &t); // last step + } +} + + +/* From ge_frombytes.c, modified */ + +int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s) { + fe u; + fe v; + fe vxx; + fe check; + + /* From fe_frombytes.c */ + + int64_t h0 = load_4(s); + int64_t h1 = load_3(s + 4) << 6; + int64_t h2 = load_3(s + 7) << 5; + int64_t h3 = load_3(s + 10) << 3; + int64_t h4 = load_3(s + 13) << 2; + int64_t h5 = load_4(s + 16); + int64_t h6 = load_3(s + 20) << 7; + int64_t h7 = load_3(s + 23) << 5; + int64_t h8 = load_3(s + 26) << 4; + int64_t h9 = (load_3(s + 29) & 8388607) << 2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + /* Validate the number to be canonical */ + if (h9 == 33554428 && h8 == 268435440 && h7 == 536870880 && h6 == 2147483520 && + h5 == 4294967295 && h4 == 67108860 && h3 == 134217720 && h2 == 536870880 && + h1 == 1073741760 && h0 >= 4294967277) { + return -1; + } + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + h->Y[0] = h0; + h->Y[1] = h1; + h->Y[2] = h2; + h->Y[3] = h3; + h->Y[4] = h4; + h->Y[5] = h5; + h->Y[6] = h6; + h->Y[7] = h7; + h->Y[8] = h8; + h->Y[9] = h9; + + /* End fe_frombytes.c */ + + fe_1(h->Z); + fe_sq(u, h->Y); + fe_mul(v, u, fe_d); + fe_sub(u, u, h->Z); /* u = y^2-1 */ + fe_add(v, v, h->Z); /* v = dy^2+1 */ + + fe_divpowm1(h->X, u, v); /* x = uv^3(uv^7)^((q-5)/8) */ + + fe_sq(vxx, h->X); + fe_mul(vxx, vxx, v); + fe_sub(check, vxx, u); /* vx^2-u */ + if (fe_isnonzero(check)) { + fe_add(check, vxx, u); /* vx^2+u */ + if (fe_isnonzero(check)) { + return -1; + } + fe_mul(h->X, h->X, fe_sqrtm1); + } + + if (fe_isnegative(h->X) != (s[31] >> 7)) { + /* If x = 0, the sign must be positive */ + if (!fe_isnonzero(h->X)) { + return -1; + } + fe_neg(h->X, h->X); + } + + fe_mul(h->T, h->X, h->Y); + return 0; +} + +/* From ge_madd.c */ + +/* +r = p + q +*/ + +void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { + fe t0; + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->yplusx); + fe_mul(r->Y, r->Y, q->yminusx); + fe_mul(r->T, q->xy2d, p->T); + fe_add(t0, p->Z, p->Z); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_add(r->Z, t0, r->T); + fe_sub(r->T, t0, r->T); +} + +/* From ge_msub.c */ + +/* +r = p - q +*/ + +static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { + fe t0; + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->yminusx); + fe_mul(r->Y, r->Y, q->yplusx); + fe_mul(r->T, q->xy2d, p->T); + fe_add(t0, p->Z, p->Z); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_sub(r->Z, t0, r->T); + fe_add(r->T, t0, r->T); +} + +/* From ge_p1p1_to_p2.c */ + +/* +r = p +*/ + +void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { + fe_mul(r->X, p->X, p->T); + fe_mul(r->Y, p->Y, p->Z); + fe_mul(r->Z, p->Z, p->T); +} + +/* From ge_p1p1_to_p3.c */ + +/* +r = p +*/ + +void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { + fe_mul(r->X, p->X, p->T); + fe_mul(r->Y, p->Y, p->Z); + fe_mul(r->Z, p->Z, p->T); + fe_mul(r->T, p->X, p->Y); +} + +/* From ge_p2_0.c */ + +static void ge_p2_0(ge_p2 *h) { + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); +} + +/* From ge_p2_dbl.c */ + +/* +r = 2 * p +*/ + +void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { + fe t0; + fe_sq(r->X, p->X); + fe_sq(r->Z, p->Y); + fe_sq2(r->T, p->Z); + fe_add(r->Y, p->X, p->Y); + fe_sq(t0, r->Y); + fe_add(r->Y, r->Z, r->X); + fe_sub(r->Z, r->Z, r->X); + fe_sub(r->X, t0, r->Y); + fe_sub(r->T, r->T, r->Z); +} + +/* From ge_p3_0.c */ + +void ge_p3_0(ge_p3 *h) { + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); + fe_0(h->T); +} + +/* From ge_p3_dbl.c */ + +/* +r = 2 * p +*/ + +static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { + ge_p2 q; + ge_p3_to_p2(&q, p); + ge_p2_dbl(r, &q); +} + +/* From ge_p3_to_cached.c */ + +/* +r = p +*/ + +void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { + fe_add(r->YplusX, p->Y, p->X); + fe_sub(r->YminusX, p->Y, p->X); + fe_copy(r->Z, p->Z); + fe_mul(r->T2d, p->T, fe_d2); +} + +/* From ge_p3_to_p2.c */ + +/* +r = p +*/ + +void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { + fe_copy(r->X, p->X); + fe_copy(r->Y, p->Y); + fe_copy(r->Z, p->Z); +} + +/* From ge_p3_tobytes.c */ + +void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) { + fe recip; + fe x; + fe y; + + fe_invert(recip, h->Z); + fe_mul(x, h->X, recip); + fe_mul(y, h->Y, recip); + fe_tobytes(s, y); + s[31] ^= fe_isnegative(x) << 7; +} + +/* From ge_precomp_0.c */ + +static void ge_precomp_0(ge_precomp *h) { + fe_1(h->yplusx); + fe_1(h->yminusx); + fe_0(h->xy2d); +} + +/* From ge_scalarmult_base.c */ + +static unsigned char equal(signed char b, signed char c) { + unsigned char ub = b; + unsigned char uc = c; + unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ + uint32_t y = x; /* 0: yes; 1..255: no */ + y -= 1; /* 4294967295: yes; 0..254: no */ + y >>= 31; /* 1: yes; 0: no */ + return y; +} + +static unsigned char negative(signed char b) { + unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ + x >>= 63; /* 1: yes; 0: no */ + return x; +} + +static void ge_precomp_cmov(ge_precomp *t, const ge_precomp *u, unsigned char b) { + fe_cmov(t->yplusx, u->yplusx, b); + fe_cmov(t->yminusx, u->yminusx, b); + fe_cmov(t->xy2d, u->xy2d, b); +} + +static void select(ge_precomp *t, int pos, signed char b) { + ge_precomp minust; + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + + ge_precomp_0(t); + ge_precomp_cmov(t, &ge_base[pos][0], equal(babs, 1)); + ge_precomp_cmov(t, &ge_base[pos][1], equal(babs, 2)); + ge_precomp_cmov(t, &ge_base[pos][2], equal(babs, 3)); + ge_precomp_cmov(t, &ge_base[pos][3], equal(babs, 4)); + ge_precomp_cmov(t, &ge_base[pos][4], equal(babs, 5)); + ge_precomp_cmov(t, &ge_base[pos][5], equal(babs, 6)); + ge_precomp_cmov(t, &ge_base[pos][6], equal(babs, 7)); + ge_precomp_cmov(t, &ge_base[pos][7], equal(babs, 8)); + fe_copy(minust.yplusx, t->yminusx); + fe_copy(minust.yminusx, t->yplusx); + fe_neg(minust.xy2d, t->xy2d); + ge_precomp_cmov(t, &minust, bnegative); +} + +/* +h = a * B +where a = a[0]+256*a[1]+...+256^31 a[31] +B is the Ed25519 base point (x,4/5) with x positive. + +Preconditions: + a[31] <= 127 +*/ + +void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) { + signed char e[64]; + signed char carry; + ge_p1p1 r; + ge_p2 s; + ge_precomp t; + int i; + + for (i = 0; i < 32; ++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + + carry = 0; + for (i = 0; i < 63; ++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + /* each e[i] is between -8 and 8 */ + + ge_p3_0(h); + for (i = 1; i < 64; i += 2) { + select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); + } + + ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r); + + for (i = 0; i < 64; i += 2) { + select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); + } +} + +/* From ge_sub.c */ + +/* +r = p - q +*/ + +void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { + fe t0; + fe_add(r->X, p->Y, p->X); + fe_sub(r->Y, p->Y, p->X); + fe_mul(r->Z, r->X, q->YminusX); + fe_mul(r->Y, r->Y, q->YplusX); + fe_mul(r->T, q->T2d, p->T); + fe_mul(r->X, p->Z, q->Z); + fe_add(t0, r->X, r->X); + fe_sub(r->X, r->Z, r->Y); + fe_add(r->Y, r->Z, r->Y); + fe_sub(r->Z, t0, r->T); + fe_add(r->T, t0, r->T); +} + +/* From ge_tobytes.c */ + +void ge_tobytes(unsigned char *s, const ge_p2 *h) { + fe recip; + fe x; + fe y; + + fe_invert(recip, h->Z); + fe_mul(x, h->X, recip); + fe_mul(y, h->Y, recip); + fe_tobytes(s, y); + s[31] ^= fe_isnegative(x) << 7; +} + +/* From sc_reduce.c */ + +/* +Input: + s[0]+256*s[1]+...+256^63*s[63] = s + +Output: + s[0]+256*s[1]+...+256^31*s[31] = s mod l + where l = 2^252 + 27742317777372353535851937790883648493. + Overwrites s in place. +*/ + +void sc_reduce(unsigned char *s) { + int64_t s0 = 2097151 & load_3(s); + int64_t s1 = 2097151 & (load_4(s + 2) >> 5); + int64_t s2 = 2097151 & (load_3(s + 5) >> 2); + int64_t s3 = 2097151 & (load_4(s + 7) >> 7); + int64_t s4 = 2097151 & (load_4(s + 10) >> 4); + int64_t s5 = 2097151 & (load_3(s + 13) >> 1); + int64_t s6 = 2097151 & (load_4(s + 15) >> 6); + int64_t s7 = 2097151 & (load_3(s + 18) >> 3); + int64_t s8 = 2097151 & load_3(s + 21); + int64_t s9 = 2097151 & (load_4(s + 23) >> 5); + int64_t s10 = 2097151 & (load_3(s + 26) >> 2); + int64_t s11 = 2097151 & (load_4(s + 28) >> 7); + int64_t s12 = 2097151 & (load_4(s + 31) >> 4); + int64_t s13 = 2097151 & (load_3(s + 34) >> 1); + int64_t s14 = 2097151 & (load_4(s + 36) >> 6); + int64_t s15 = 2097151 & (load_3(s + 39) >> 3); + int64_t s16 = 2097151 & load_3(s + 42); + int64_t s17 = 2097151 & (load_4(s + 44) >> 5); + int64_t s18 = 2097151 & (load_3(s + 47) >> 2); + int64_t s19 = 2097151 & (load_4(s + 49) >> 7); + int64_t s20 = 2097151 & (load_4(s + 52) >> 4); + int64_t s21 = 2097151 & (load_3(s + 55) >> 1); + int64_t s22 = 2097151 & (load_4(s + 57) >> 6); + int64_t s23 = (load_4(s + 60) >> 3); + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +/* New code */ + +static void fe_divpowm1(fe r, const fe u, const fe v) { + fe v3, uv7, t0, t1, t2; + int i; + + fe_sq(v3, v); + fe_mul(v3, v3, v); /* v3 = v^3 */ + fe_sq(uv7, v3); + fe_mul(uv7, uv7, v); + fe_mul(uv7, uv7, u); /* uv7 = uv^7 */ + + /*fe_pow22523(uv7, uv7);*/ + + /* From fe_pow22523.c */ + + fe_sq(t0, uv7); + fe_sq(t1, t0); + fe_sq(t1, t1); + fe_mul(t1, uv7, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + for (i = 0; i < 4; ++i) { + fe_sq(t1, t1); + } + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + for (i = 0; i < 9; ++i) { + fe_sq(t1, t1); + } + fe_mul(t1, t1, t0); + fe_sq(t2, t1); + for (i = 0; i < 19; ++i) { + fe_sq(t2, t2); + } + fe_mul(t1, t2, t1); + for (i = 0; i < 10; ++i) { + fe_sq(t1, t1); + } + fe_mul(t0, t1, t0); + fe_sq(t1, t0); + for (i = 0; i < 49; ++i) { + fe_sq(t1, t1); + } + fe_mul(t1, t1, t0); + fe_sq(t2, t1); + for (i = 0; i < 99; ++i) { + fe_sq(t2, t2); + } + fe_mul(t1, t2, t1); + for (i = 0; i < 50; ++i) { + fe_sq(t1, t1); + } + fe_mul(t0, t1, t0); + fe_sq(t0, t0); + fe_sq(t0, t0); + fe_mul(t0, t0, uv7); + + /* End fe_pow22523.c */ + /* t0 = (uv^7)^((q-5)/8) */ + fe_mul(t0, t0, v3); + fe_mul(r, t0, u); /* u^(m+1)v^(-(m+1)) */ +} + +static void ge_cached_0(ge_cached *r) { + fe_1(r->YplusX); + fe_1(r->YminusX); + fe_1(r->Z); + fe_0(r->T2d); +} + +static void ge_cached_cmov(ge_cached *t, const ge_cached *u, unsigned char b) { + fe_cmov(t->YplusX, u->YplusX, b); + fe_cmov(t->YminusX, u->YminusX, b); + fe_cmov(t->Z, u->Z, b); + fe_cmov(t->T2d, u->T2d, b); +} + +/* Assumes that a[31] <= 127 */ +void ge_scalarmult(ge_p2 *r, const unsigned char *a, const ge_p3 *A) { + signed char e[64]; + int carry, carry2, i; + ge_cached Ai[8]; /* 1 * A, 2 * A, ..., 8 * A */ + ge_p1p1 t; + ge_p3 u; + + carry = 0; /* 0..1 */ + for (i = 0; i < 31; i++) { + carry += a[i]; /* 0..256 */ + carry2 = (carry + 8) >> 4; /* 0..16 */ + e[2 * i] = carry - (carry2 << 4); /* -8..7 */ + carry = (carry2 + 8) >> 4; /* 0..1 */ + e[2 * i + 1] = carry2 - (carry << 4); /* -8..7 */ + } + carry += a[31]; /* 0..128 */ + carry2 = (carry + 8) >> 4; /* 0..8 */ + e[62] = carry - (carry2 << 4); /* -8..7 */ + e[63] = carry2; /* 0..8 */ + + ge_p3_to_cached(&Ai[0], A); + for (i = 0; i < 7; i++) { + ge_add(&t, A, &Ai[i]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[i + 1], &u); + } + + ge_p2_0(r); + for (i = 63; i >= 0; i--) { + signed char b = e[i]; + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + ge_cached cur, minuscur; + ge_p2_dbl(&t, r); + ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + ge_p1p1_to_p3(&u, &t); + ge_cached_0(&cur); + ge_cached_cmov(&cur, &Ai[0], equal(babs, 1)); + ge_cached_cmov(&cur, &Ai[1], equal(babs, 2)); + ge_cached_cmov(&cur, &Ai[2], equal(babs, 3)); + ge_cached_cmov(&cur, &Ai[3], equal(babs, 4)); + ge_cached_cmov(&cur, &Ai[4], equal(babs, 5)); + ge_cached_cmov(&cur, &Ai[5], equal(babs, 6)); + ge_cached_cmov(&cur, &Ai[6], equal(babs, 7)); + ge_cached_cmov(&cur, &Ai[7], equal(babs, 8)); + fe_copy(minuscur.YplusX, cur.YminusX); + fe_copy(minuscur.YminusX, cur.YplusX); + fe_copy(minuscur.Z, cur.Z); + fe_neg(minuscur.T2d, cur.T2d); + ge_cached_cmov(&cur, &minuscur, bnegative); + ge_add(&t, &u, &cur); + ge_p1p1_to_p2(r, &t); + } +} + +/* Assumes that a[31] <= 127 */ +void ge_scalarmult_p3(ge_p3 *result, const unsigned char *a, const ge_p3 *A) { + signed char e[64]; + int carry, carry2, i; + ge_cached Ai[8]; /* 1 * A, 2 * A, ..., 8 * A */ + ge_p1p1 t; + ge_p3 u; + ge_p2 r_tmp; + ge_p2* r = &r_tmp; + + carry = 0; /* 0..1 */ + for (i = 0; i < 31; i++) { + carry += a[i]; /* 0..256 */ + carry2 = (carry + 8) >> 4; /* 0..16 */ + e[2 * i] = carry - (carry2 << 4); /* -8..7 */ + carry = (carry2 + 8) >> 4; /* 0..1 */ + e[2 * i + 1] = carry2 - (carry << 4); /* -8..7 */ + } + carry += a[31]; /* 0..128 */ + carry2 = (carry + 8) >> 4; /* 0..8 */ + e[62] = carry - (carry2 << 4); /* -8..7 */ + e[63] = carry2; /* 0..8 */ + + ge_p3_to_cached(&Ai[0], A); + for (i = 0; i < 7; i++) { + ge_add(&t, A, &Ai[i]); + ge_p1p1_to_p3(&u, &t); + ge_p3_to_cached(&Ai[i + 1], &u); + } + + ge_p2_0(r); + for (i = 63; i >= 0; i--) { + signed char b = e[i]; + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + ge_cached cur, minuscur; + ge_p2_dbl(&t, r); + ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + ge_p1p1_to_p3(&u, &t); + ge_cached_0(&cur); + ge_cached_cmov(&cur, &Ai[0], equal(babs, 1)); + ge_cached_cmov(&cur, &Ai[1], equal(babs, 2)); + ge_cached_cmov(&cur, &Ai[2], equal(babs, 3)); + ge_cached_cmov(&cur, &Ai[3], equal(babs, 4)); + ge_cached_cmov(&cur, &Ai[4], equal(babs, 5)); + ge_cached_cmov(&cur, &Ai[5], equal(babs, 6)); + ge_cached_cmov(&cur, &Ai[6], equal(babs, 7)); + ge_cached_cmov(&cur, &Ai[7], equal(babs, 8)); + fe_copy(minuscur.YplusX, cur.YminusX); + fe_copy(minuscur.YminusX, cur.YplusX); + fe_copy(minuscur.Z, cur.Z); + fe_neg(minuscur.T2d, cur.T2d); + ge_cached_cmov(&cur, &minuscur, bnegative); + ge_add(&t, &u, &cur); + if (i > 0) + ge_p1p1_to_p2(r, &t); + else + ge_p1p1_to_p3(result, &t); // last iteration + } +} + +void ge_double_scalarmult_precomp_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b, const ge_dsmp Bi) { + signed char aslide[256]; + signed char bslide[256]; + ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ + ge_p1p1 t; + ge_p3 u; + int i; + + slide(aslide, a); + slide(bslide, b); + ge_dsm_precomp(Ai, A); + + ge_p2_0(r); + + for (i = 255; i >= 0; --i) { + if (aslide[i] || bslide[i]) break; + } + + for (; i >= 0; --i) { + ge_p2_dbl(&t, r); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Ai[aslide[i]/2]); + } else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Ai[(-aslide[i])/2]); + } + + if (bslide[i] > 0) { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Bi[bslide[i]/2]); + } else if (bslide[i] < 0) { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Bi[(-bslide[i])/2]); + } + + ge_p1p1_to_p2(r, &t); + } +} + +void ge_mul8(ge_p1p1 *r, const ge_p2 *t) { + ge_p2 u; + ge_p2_dbl(r, t); + ge_p1p1_to_p2(&u, r); + ge_p2_dbl(r, &u); + ge_p1p1_to_p2(&u, r); + ge_p2_dbl(r, &u); +} + +void ge_fromfe_frombytes_vartime(ge_p2 *r, const unsigned char *s) { + fe u, v, w, x, y, z; + unsigned char sign; + + /* From fe_frombytes.c */ + + int64_t h0 = load_4(s); + int64_t h1 = load_3(s + 4) << 6; + int64_t h2 = load_3(s + 7) << 5; + int64_t h3 = load_3(s + 10) << 3; + int64_t h4 = load_3(s + 13) << 2; + int64_t h5 = load_4(s + 16); + int64_t h6 = load_3(s + 20) << 7; + int64_t h7 = load_3(s + 23) << 5; + int64_t h8 = load_3(s + 26) << 4; + int64_t h9 = load_3(s + 29) << 2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + u[0] = h0; + u[1] = h1; + u[2] = h2; + u[3] = h3; + u[4] = h4; + u[5] = h5; + u[6] = h6; + u[7] = h7; + u[8] = h8; + u[9] = h9; + + /* End fe_frombytes.c */ + + fe_sq2(v, u); /* v = 2 * u^2 */ + fe_1(w); /* w = 1 */ + fe_add(w, v, w); /* w = 2 * u^2 + 1 */ + fe_sq(x, w); /* x = w^2 */ + fe_mul(y, fe_ma2, v); /* y = -A^2 * (2 * u^2) = -2 * A^2 * u^2 n.b. A = 2 * (1 - d) / (1 + d) = 486662*/ + fe_add(x, x, y); /* x = w^2 - 2 * A^2 * u^2 */ + fe_divpowm1(r->X, w, x); /* r->X = (w / x)^(m + 1) */ + fe_sq(y, r->X); /* y = (w / x)^(2*(m + 1)) */ + fe_mul(x, y, x); /* x = (w / x)^(2*(m + 1)) * (w^2 - 2 * A^2 * u^2) */ + fe_sub(y, w, x); /* y = 2 * u^2 + 1 - (w / x)^(2*(m + 1)) * (w^2 - 2 * A^2 * u^2) */ + fe_copy(z, fe_ma); /* z = -A */ + if (fe_isnonzero(y)) { + fe_add(y, w, x); + if (fe_isnonzero(y)) { + goto negative; + } else { + fe_mul(r->X, r->X, fe_fffb1); + } + } else { + fe_mul(r->X, r->X, fe_fffb2); + } + fe_mul(r->X, r->X, u); /* u * sqrt(2 * A * (A + 2) * w / x) */ + fe_mul(z, z, v); /* -2 * A * u^2 */ + sign = 0; + goto setsign; +negative: + fe_mul(x, x, fe_sqrtm1); + fe_sub(y, w, x); + if (fe_isnonzero(y)) { + assert((fe_add(y, w, x), !fe_isnonzero(y))); + fe_mul(r->X, r->X, fe_fffb3); + } else { + fe_mul(r->X, r->X, fe_fffb4); + } + /* r->X = sqrt(A * (A + 2) * w / x) */ + /* z = -A */ + sign = 1; +setsign: + if (fe_isnegative(r->X) != sign) { + assert(fe_isnonzero(r->X)); + fe_neg(r->X, r->X); + } + fe_add(r->Z, z, w); + fe_sub(r->Y, z, w); + fe_mul(r->X, r->X, r->Z); +#if !defined(NDEBUG) + { + fe check_x, check_y, check_iz, check_v; + fe_invert(check_iz, r->Z); + fe_mul(check_x, r->X, check_iz); + fe_mul(check_y, r->Y, check_iz); + fe_sq(check_x, check_x); + fe_sq(check_y, check_y); + fe_mul(check_v, check_x, check_y); + fe_mul(check_v, fe_d, check_v); + fe_add(check_v, check_v, check_x); + fe_sub(check_v, check_v, check_y); + fe_1(check_x); + fe_add(check_v, check_v, check_x); + assert(!fe_isnonzero(check_v)); + } +#endif +} + +void sc_0(unsigned char *s) { + int i; + for (i = 0; i < 32; i++) { + s[i] = 0; + } +} + +void sc_reduce32(unsigned char *s) { + int64_t s0 = 2097151 & load_3(s); + int64_t s1 = 2097151 & (load_4(s + 2) >> 5); + int64_t s2 = 2097151 & (load_3(s + 5) >> 2); + int64_t s3 = 2097151 & (load_4(s + 7) >> 7); + int64_t s4 = 2097151 & (load_4(s + 10) >> 4); + int64_t s5 = 2097151 & (load_3(s + 13) >> 1); + int64_t s6 = 2097151 & (load_4(s + 15) >> 6); + int64_t s7 = 2097151 & (load_3(s + 18) >> 3); + int64_t s8 = 2097151 & load_3(s + 21); + int64_t s9 = 2097151 & (load_4(s + 23) >> 5); + int64_t s10 = 2097151 & (load_3(s + 26) >> 2); + int64_t s11 = (load_4(s + 28) >> 7); + int64_t s12 = 0; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +void sc_add(unsigned char *s, const unsigned char *a, const unsigned char *b) { + int64_t a0 = 2097151 & load_3(a); + int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + int64_t a8 = 2097151 & load_3(a + 21); + int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + int64_t b0 = 2097151 & load_3(b); + int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + int64_t b8 = 2097151 & load_3(b + 21); + int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + int64_t s0 = a0 + b0; + int64_t s1 = a1 + b1; + int64_t s2 = a2 + b2; + int64_t s3 = a3 + b3; + int64_t s4 = a4 + b4; + int64_t s5 = a5 + b5; + int64_t s6 = a6 + b6; + int64_t s7 = a7 + b7; + int64_t s8 = a8 + b8; + int64_t s9 = a9 + b9; + int64_t s10 = a10 + b10; + int64_t s11 = a11 + b11; + int64_t s12 = 0; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +void sc_sub(unsigned char *s, const unsigned char *a, const unsigned char *b) { + int64_t a0 = 2097151 & load_3(a); + int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + int64_t a8 = 2097151 & load_3(a + 21); + int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + int64_t b0 = 2097151 & load_3(b); + int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + int64_t b8 = 2097151 & load_3(b + 21); + int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + int64_t s0 = a0 - b0; + int64_t s1 = a1 - b1; + int64_t s2 = a2 - b2; + int64_t s3 = a3 - b3; + int64_t s4 = a4 - b4; + int64_t s5 = a5 - b5; + int64_t s6 = a6 - b6; + int64_t s7 = a7 - b7; + int64_t s8 = a8 - b8; + int64_t s9 = a9 - b9; + int64_t s10 = a10 - b10; + int64_t s11 = a11 - b11; + int64_t s12 = 0; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +/* +Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + c[0]+256*c[1]+...+256^31*c[31] = c + +Output: + s[0]+256*s[1]+...+256^31*s[31] = (c-ab) mod l + where l = 2^252 + 27742317777372353535851937790883648493. +*/ + +void sc_mulsub(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c) { + int64_t a0 = 2097151 & load_3(a); + int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + int64_t a8 = 2097151 & load_3(a + 21); + int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + int64_t b0 = 2097151 & load_3(b); + int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + int64_t b8 = 2097151 & load_3(b + 21); + int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + int64_t c0 = 2097151 & load_3(c); + int64_t c1 = 2097151 & (load_4(c + 2) >> 5); + int64_t c2 = 2097151 & (load_3(c + 5) >> 2); + int64_t c3 = 2097151 & (load_4(c + 7) >> 7); + int64_t c4 = 2097151 & (load_4(c + 10) >> 4); + int64_t c5 = 2097151 & (load_3(c + 13) >> 1); + int64_t c6 = 2097151 & (load_4(c + 15) >> 6); + int64_t c7 = 2097151 & (load_3(c + 18) >> 3); + int64_t c8 = 2097151 & load_3(c + 21); + int64_t c9 = 2097151 & (load_4(c + 23) >> 5); + int64_t c10 = 2097151 & (load_3(c + 26) >> 2); + int64_t c11 = (load_4(c + 28) >> 7); + int64_t s0; + int64_t s1; + int64_t s2; + int64_t s3; + int64_t s4; + int64_t s5; + int64_t s6; + int64_t s7; + int64_t s8; + int64_t s9; + int64_t s10; + int64_t s11; + int64_t s12; + int64_t s13; + int64_t s14; + int64_t s15; + int64_t s16; + int64_t s17; + int64_t s18; + int64_t s19; + int64_t s20; + int64_t s21; + int64_t s22; + int64_t s23; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + int64_t carry17; + int64_t carry18; + int64_t carry19; + int64_t carry20; + int64_t carry21; + int64_t carry22; + + s0 = c0 - a0*b0; + s1 = c1 - (a0*b1 + a1*b0); + s2 = c2 - (a0*b2 + a1*b1 + a2*b0); + s3 = c3 - (a0*b3 + a1*b2 + a2*b1 + a3*b0); + s4 = c4 - (a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0); + s5 = c5 - (a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0); + s6 = c6 - (a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0); + s7 = c7 - (a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0); + s8 = c8 - (a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0); + s9 = c9 - (a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0); + s10 = c10 - (a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0); + s11 = c11 - (a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0); + s12 = -(a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1); + s13 = -(a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2); + s14 = -(a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3); + s15 = -(a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4); + s16 = -(a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5); + s17 = -(a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6); + s18 = -(a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7); + s19 = -(a8*b11 + a9*b10 + a10*b9 + a11*b8); + s20 = -(a9*b11 + a10*b10 + a11*b9); + s21 = -(a10*b11 + a11*b10); + s22 = -a11*b11; + s23 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + carry18 = (s18 + (1<<20)) >> 21; s19 += carry18; s18 -= carry18 << 21; + carry20 = (s20 + (1<<20)) >> 21; s21 += carry20; s20 -= carry20 << 21; + carry22 = (s22 + (1<<20)) >> 21; s23 += carry22; s22 -= carry22 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + carry17 = (s17 + (1<<20)) >> 21; s18 += carry17; s17 -= carry17 << 21; + carry19 = (s19 + (1<<20)) >> 21; s20 += carry19; s19 -= carry19 << 21; + carry21 = (s21 + (1<<20)) >> 21; s22 += carry21; s21 -= carry21 << 21; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + carry12 = (s12 + (1<<20)) >> 21; s13 += carry12; s12 -= carry12 << 21; + carry14 = (s14 + (1<<20)) >> 21; s15 += carry14; s14 -= carry14 << 21; + carry16 = (s16 + (1<<20)) >> 21; s17 += carry16; s16 -= carry16 << 21; + + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + carry13 = (s13 + (1<<20)) >> 21; s14 += carry13; s13 -= carry13 << 21; + carry15 = (s15 + (1<<20)) >> 21; s16 += carry15; s15 -= carry15 << 21; + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1<<20)) >> 21; s1 += carry0; s0 -= carry0 << 21; + carry2 = (s2 + (1<<20)) >> 21; s3 += carry2; s2 -= carry2 << 21; + carry4 = (s4 + (1<<20)) >> 21; s5 += carry4; s4 -= carry4 << 21; + carry6 = (s6 + (1<<20)) >> 21; s7 += carry6; s6 -= carry6 << 21; + carry8 = (s8 + (1<<20)) >> 21; s9 += carry8; s8 -= carry8 << 21; + carry10 = (s10 + (1<<20)) >> 21; s11 += carry10; s10 -= carry10 << 21; + + carry1 = (s1 + (1<<20)) >> 21; s2 += carry1; s1 -= carry1 << 21; + carry3 = (s3 + (1<<20)) >> 21; s4 += carry3; s3 -= carry3 << 21; + carry5 = (s5 + (1<<20)) >> 21; s6 += carry5; s5 -= carry5 << 21; + carry7 = (s7 + (1<<20)) >> 21; s8 += carry7; s7 -= carry7 << 21; + carry9 = (s9 + (1<<20)) >> 21; s10 += carry9; s9 -= carry9 << 21; + carry11 = (s11 + (1<<20)) >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + carry11 = s11 >> 21; s12 += carry11; s11 -= carry11 << 21; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + + carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; + carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; + carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; + carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; + carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; + carry5 = s5 >> 21; s6 += carry5; s5 -= carry5 << 21; + carry6 = s6 >> 21; s7 += carry6; s6 -= carry6 << 21; + carry7 = s7 >> 21; s8 += carry7; s7 -= carry7 << 21; + carry8 = s8 >> 21; s9 += carry8; s8 -= carry8 << 21; + carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; + carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +/* Assumes that a != INT64_MIN */ +static int64_t signum(int64_t a) { + return (a >> 63) - ((-a) >> 63); +} + +int sc_check(const unsigned char *s) { + int64_t s0 = load_4(s); + int64_t s1 = load_4(s + 4); + int64_t s2 = load_4(s + 8); + int64_t s3 = load_4(s + 12); + int64_t s4 = load_4(s + 16); + int64_t s5 = load_4(s + 20); + int64_t s6 = load_4(s + 24); + int64_t s7 = load_4(s + 28); + return (signum(1559614444 - s0) + (signum(1477600026 - s1) << 1) + (signum(2734136534 - s2) << 2) + (signum(350157278 - s3) << 3) + (signum(-s4) << 4) + (signum(-s5) << 5) + (signum(-s6) << 6) + (signum(268435456 - s7) << 7)) >> 8; +} + +int sc_isnonzero(const unsigned char *s) { + return (((int) (s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] | s[8] | + s[9] | s[10] | s[11] | s[12] | s[13] | s[14] | s[15] | s[16] | s[17] | + s[18] | s[19] | s[20] | s[21] | s[22] | s[23] | s[24] | s[25] | s[26] | + s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1; +} + +// see implmentation of ge_frombytes_vartime above +void fe_frombytes(fe h, const unsigned char *s) +{ + /* From fe_frombytes.c */ + + int64_t h0 = load_4(s); + int64_t h1 = load_3(s + 4) << 6; + int64_t h2 = load_3(s + 7) << 5; + int64_t h3 = load_3(s + 10) << 3; + int64_t h4 = load_3(s + 13) << 2; + int64_t h5 = load_4(s + 16); + int64_t h6 = load_3(s + 20) << 7; + int64_t h7 = load_3(s + 23) << 5; + int64_t h8 = load_3(s + 26) << 4; + int64_t h9 = (load_3(s + 29) & 8388607) << 2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = (h9 + (int64_t)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry0 = (h0 + (int64_t)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + +/* +// Old naive and slow implementation using sc_mulsub +void sc_mul(unsigned char *s, const unsigned char *a, const unsigned char *b) +{ + unsigned char c[32]; + unsigned char neg_a[32]; + sc_0(c); + sc_sub(neg_a, c, a); + // s = c - ab + sc_mulsub(s, neg_a, b, c); +} +*/ + +/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ +/* + Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + * + Output: + s[0]+256*s[1]+...+256^31*s[31] = (ab) mod l + where l = 2^252 + 27742317777372353535851937790883648493. + */ +void sc_mul(unsigned char* s, const unsigned char* a, const unsigned char* b) +{ + int64_t a0 = 2097151 & load_3(a); + int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + int64_t a8 = 2097151 & load_3(a + 21); + int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + + int64_t b0 = 2097151 & load_3(b); + int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + int64_t b8 = 2097151 & load_3(b + 21); + int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + + int64_t s0; + int64_t s1; + int64_t s2; + int64_t s3; + int64_t s4; + int64_t s5; + int64_t s6; + int64_t s7; + int64_t s8; + int64_t s9; + int64_t s10; + int64_t s11; + int64_t s12; + int64_t s13; + int64_t s14; + int64_t s15; + int64_t s16; + int64_t s17; + int64_t s18; + int64_t s19; + int64_t s20; + int64_t s21; + int64_t s22; + int64_t s23; + + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + int64_t carry17; + int64_t carry18; + int64_t carry19; + int64_t carry20; + int64_t carry21; + int64_t carry22; + + s0 = a0 * b0; + s1 = a0 * b1 + a1 * b0; + s2 = a0 * b2 + a1 * b1 + a2 * b0; + s3 = a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; + s4 = a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; + s5 = a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; + s6 = a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; + s7 = a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + + a6 * b1 + a7 * b0; + s8 = a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + + a6 * b2 + a7 * b1 + a8 * b0; + s9 = a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; + s10 = a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; + s11 = a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; + s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; + s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; + s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + + a9 * b5 + a10 * b4 + a11 * b3; + s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + + a10 * b5 + a11 * b4; + s16 = + a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; + s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; + s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; + s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; + s20 = a9 * b11 + a10 * b10 + a11 * b9; + s21 = a10 * b11 + a11 * b10; + s22 = a11 * b11; + s23 = 0; + + carry0 = (s0 + (int64_t)(1L << 20)) >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry2 = (s2 + (int64_t)(1L << 20)) >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry4 = (s4 + (int64_t)(1L << 20)) >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry6 = (s6 + (int64_t)(1L << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry8 = (s8 + (int64_t)(1L << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry10 = (s10 + (int64_t)(1L << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + carry12 = (s12 + (int64_t)(1L << 20)) >> 21; + s13 += carry12; + s12 -= carry12 * ((uint64_t)1L << 21); + carry14 = (s14 + (int64_t)(1L << 20)) >> 21; + s15 += carry14; + s14 -= carry14 * ((uint64_t)1L << 21); + carry16 = (s16 + (int64_t)(1L << 20)) >> 21; + s17 += carry16; + s16 -= carry16 * ((uint64_t)1L << 21); + carry18 = (s18 + (int64_t)(1L << 20)) >> 21; + s19 += carry18; + s18 -= carry18 * ((uint64_t)1L << 21); + carry20 = (s20 + (int64_t)(1L << 20)) >> 21; + s21 += carry20; + s20 -= carry20 * ((uint64_t)1L << 21); + carry22 = (s22 + (int64_t)(1L << 20)) >> 21; + s23 += carry22; + s22 -= carry22 * ((uint64_t)1L << 21); + + carry1 = (s1 + (int64_t)(1L << 20)) >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry3 = (s3 + (int64_t)(1L << 20)) >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry5 = (s5 + (int64_t)(1L << 20)) >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry7 = (s7 + (int64_t)(1L << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry9 = (s9 + (int64_t)(1L << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry11 = (s11 + (int64_t)(1L << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + carry13 = (s13 + (int64_t)(1L << 20)) >> 21; + s14 += carry13; + s13 -= carry13 * ((uint64_t)1L << 21); + carry15 = (s15 + (int64_t)(1L << 20)) >> 21; + s16 += carry15; + s15 -= carry15 * ((uint64_t)1L << 21); + carry17 = (s17 + (int64_t)(1L << 20)) >> 21; + s18 += carry17; + s17 -= carry17 * ((uint64_t)1L << 21); + carry19 = (s19 + (int64_t)(1L << 20)) >> 21; + s20 += carry19; + s19 -= carry19 * ((uint64_t)1L << 21); + carry21 = (s21 + (int64_t)(1L << 20)) >> 21; + s22 += carry21; + s21 -= carry21 * ((uint64_t)1L << 21); + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + + carry6 = (s6 + (int64_t)(1L << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry8 = (s8 + (int64_t)(1L << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry10 = (s10 + (int64_t)(1L << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + carry12 = (s12 + (int64_t)(1L << 20)) >> 21; + s13 += carry12; + s12 -= carry12 * ((uint64_t)1L << 21); + carry14 = (s14 + (int64_t)(1L << 20)) >> 21; + s15 += carry14; + s14 -= carry14 * ((uint64_t)1L << 21); + carry16 = (s16 + (int64_t)(1L << 20)) >> 21; + s17 += carry16; + s16 -= carry16 * ((uint64_t)1L << 21); + + carry7 = (s7 + (int64_t)(1L << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry9 = (s9 + (int64_t)(1L << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry11 = (s11 + (int64_t)(1L << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + carry13 = (s13 + (int64_t)(1L << 20)) >> 21; + s14 += carry13; + s13 -= carry13 * ((uint64_t)1L << 21); + carry15 = (s15 + (int64_t)(1L << 20)) >> 21; + s16 += carry15; + s15 -= carry15 * ((uint64_t)1L << 21); + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (int64_t)(1L << 20)) >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry2 = (s2 + (int64_t)(1L << 20)) >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry4 = (s4 + (int64_t)(1L << 20)) >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry6 = (s6 + (int64_t)(1L << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry8 = (s8 + (int64_t)(1L << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry10 = (s10 + (int64_t)(1L << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + + carry1 = (s1 + (int64_t)(1L << 20)) >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry3 = (s3 + (int64_t)(1L << 20)) >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry5 = (s5 + (int64_t)(1L << 20)) >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry7 = (s7 + (int64_t)(1L << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry9 = (s9 + (int64_t)(1L << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry11 = (s11 + (int64_t)(1L << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 * ((uint64_t)1 << 5)); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 * ((uint64_t)1 << 2)); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 * ((uint64_t)1 << 7)); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 * ((uint64_t)1 << 4)); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 * ((uint64_t)1 << 1)); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 * ((uint64_t)1 << 6)); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 * ((uint64_t)1 << 3)); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 * ((uint64_t)1 << 5)); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 * ((uint64_t)1 << 2)); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 * ((uint64_t)1 << 7)); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ +/* + Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + c[0]+256*c[1]+...+256^31*c[31] = c + * + Output: + s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l + where l = 2^252 + 27742317777372353535851937790883648493. + */ +void sc_muladd(unsigned char* s, const unsigned char* a, + const unsigned char* b, const unsigned char* c) +{ + int64_t a0 = 2097151 & load_3(a); + int64_t a1 = 2097151 & (load_4(a + 2) >> 5); + int64_t a2 = 2097151 & (load_3(a + 5) >> 2); + int64_t a3 = 2097151 & (load_4(a + 7) >> 7); + int64_t a4 = 2097151 & (load_4(a + 10) >> 4); + int64_t a5 = 2097151 & (load_3(a + 13) >> 1); + int64_t a6 = 2097151 & (load_4(a + 15) >> 6); + int64_t a7 = 2097151 & (load_3(a + 18) >> 3); + int64_t a8 = 2097151 & load_3(a + 21); + int64_t a9 = 2097151 & (load_4(a + 23) >> 5); + int64_t a10 = 2097151 & (load_3(a + 26) >> 2); + int64_t a11 = (load_4(a + 28) >> 7); + + int64_t b0 = 2097151 & load_3(b); + int64_t b1 = 2097151 & (load_4(b + 2) >> 5); + int64_t b2 = 2097151 & (load_3(b + 5) >> 2); + int64_t b3 = 2097151 & (load_4(b + 7) >> 7); + int64_t b4 = 2097151 & (load_4(b + 10) >> 4); + int64_t b5 = 2097151 & (load_3(b + 13) >> 1); + int64_t b6 = 2097151 & (load_4(b + 15) >> 6); + int64_t b7 = 2097151 & (load_3(b + 18) >> 3); + int64_t b8 = 2097151 & load_3(b + 21); + int64_t b9 = 2097151 & (load_4(b + 23) >> 5); + int64_t b10 = 2097151 & (load_3(b + 26) >> 2); + int64_t b11 = (load_4(b + 28) >> 7); + + int64_t c0 = 2097151 & load_3(c); + int64_t c1 = 2097151 & (load_4(c + 2) >> 5); + int64_t c2 = 2097151 & (load_3(c + 5) >> 2); + int64_t c3 = 2097151 & (load_4(c + 7) >> 7); + int64_t c4 = 2097151 & (load_4(c + 10) >> 4); + int64_t c5 = 2097151 & (load_3(c + 13) >> 1); + int64_t c6 = 2097151 & (load_4(c + 15) >> 6); + int64_t c7 = 2097151 & (load_3(c + 18) >> 3); + int64_t c8 = 2097151 & load_3(c + 21); + int64_t c9 = 2097151 & (load_4(c + 23) >> 5); + int64_t c10 = 2097151 & (load_3(c + 26) >> 2); + int64_t c11 = (load_4(c + 28) >> 7); + + int64_t s0; + int64_t s1; + int64_t s2; + int64_t s3; + int64_t s4; + int64_t s5; + int64_t s6; + int64_t s7; + int64_t s8; + int64_t s9; + int64_t s10; + int64_t s11; + int64_t s12; + int64_t s13; + int64_t s14; + int64_t s15; + int64_t s16; + int64_t s17; + int64_t s18; + int64_t s19; + int64_t s20; + int64_t s21; + int64_t s22; + int64_t s23; + + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + int64_t carry17; + int64_t carry18; + int64_t carry19; + int64_t carry20; + int64_t carry21; + int64_t carry22; + + s0 = c0 + a0 * b0; + s1 = c1 + a0 * b1 + a1 * b0; + s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; + s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; + s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; + s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; + s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + + a6 * b0; + s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + + a6 * b1 + a7 * b0; + s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + + a6 * b2 + a7 * b1 + a8 * b0; + s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; + s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; + s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; + s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; + s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; + s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + + a9 * b5 + a10 * b4 + a11 * b3; + s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + + a10 * b5 + a11 * b4; + s16 = + a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; + s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; + s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; + s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; + s20 = a9 * b11 + a10 * b10 + a11 * b9; + s21 = a10 * b11 + a11 * b10; + s22 = a11 * b11; + s23 = 0; + + carry0 = (s0 + (int64_t)(1L << 20)) >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry2 = (s2 + (int64_t)(1L << 20)) >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry4 = (s4 + (int64_t)(1L << 20)) >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry6 = (s6 + (int64_t)(1L << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry8 = (s8 + (int64_t)(1L << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry10 = (s10 + (int64_t)(1L << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + carry12 = (s12 + (int64_t)(1L << 20)) >> 21; + s13 += carry12; + s12 -= carry12 * ((uint64_t)1L << 21); + carry14 = (s14 + (int64_t)(1L << 20)) >> 21; + s15 += carry14; + s14 -= carry14 * ((uint64_t)1L << 21); + carry16 = (s16 + (int64_t)(1L << 20)) >> 21; + s17 += carry16; + s16 -= carry16 * ((uint64_t)1L << 21); + carry18 = (s18 + (int64_t)(1L << 20)) >> 21; + s19 += carry18; + s18 -= carry18 * ((uint64_t)1L << 21); + carry20 = (s20 + (int64_t)(1L << 20)) >> 21; + s21 += carry20; + s20 -= carry20 * ((uint64_t)1L << 21); + carry22 = (s22 + (int64_t)(1L << 20)) >> 21; + s23 += carry22; + s22 -= carry22 * ((uint64_t)1L << 21); + + carry1 = (s1 + (int64_t)(1L << 20)) >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry3 = (s3 + (int64_t)(1L << 20)) >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry5 = (s5 + (int64_t)(1L << 20)) >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry7 = (s7 + (int64_t)(1L << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry9 = (s9 + (int64_t)(1L << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry11 = (s11 + (int64_t)(1L << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + carry13 = (s13 + (int64_t)(1L << 20)) >> 21; + s14 += carry13; + s13 -= carry13 * ((uint64_t)1L << 21); + carry15 = (s15 + (int64_t)(1L << 20)) >> 21; + s16 += carry15; + s15 -= carry15 * ((uint64_t)1L << 21); + carry17 = (s17 + (int64_t)(1L << 20)) >> 21; + s18 += carry17; + s17 -= carry17 * ((uint64_t)1L << 21); + carry19 = (s19 + (int64_t)(1L << 20)) >> 21; + s20 += carry19; + s19 -= carry19 * ((uint64_t)1L << 21); + carry21 = (s21 + (int64_t)(1L << 20)) >> 21; + s22 += carry21; + s21 -= carry21 * ((uint64_t)1L << 21); + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + + carry6 = (s6 + (int64_t)(1L << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry8 = (s8 + (int64_t)(1L << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry10 = (s10 + (int64_t)(1L << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + carry12 = (s12 + (int64_t)(1L << 20)) >> 21; + s13 += carry12; + s12 -= carry12 * ((uint64_t)1L << 21); + carry14 = (s14 + (int64_t)(1L << 20)) >> 21; + s15 += carry14; + s14 -= carry14 * ((uint64_t)1L << 21); + carry16 = (s16 + (int64_t)(1L << 20)) >> 21; + s17 += carry16; + s16 -= carry16 * ((uint64_t)1L << 21); + + carry7 = (s7 + (int64_t)(1L << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry9 = (s9 + (int64_t)(1L << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry11 = (s11 + (int64_t)(1L << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + carry13 = (s13 + (int64_t)(1L << 20)) >> 21; + s14 += carry13; + s13 -= carry13 * ((uint64_t)1L << 21); + carry15 = (s15 + (int64_t)(1L << 20)) >> 21; + s16 += carry15; + s15 -= carry15 * ((uint64_t)1L << 21); + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (int64_t)(1L << 20)) >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry2 = (s2 + (int64_t)(1L << 20)) >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry4 = (s4 + (int64_t)(1L << 20)) >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry6 = (s6 + (int64_t)(1L << 20)) >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry8 = (s8 + (int64_t)(1L << 20)) >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry10 = (s10 + (int64_t)(1L << 20)) >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + + carry1 = (s1 + (int64_t)(1L << 20)) >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry3 = (s3 + (int64_t)(1L << 20)) >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry5 = (s5 + (int64_t)(1L << 20)) >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry7 = (s7 + (int64_t)(1L << 20)) >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry9 = (s9 + (int64_t)(1L << 20)) >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry11 = (s11 + (int64_t)(1L << 20)) >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + carry11 = s11 >> 21; + s12 += carry11; + s11 -= carry11 * ((uint64_t)1L << 21); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= carry0 * ((uint64_t)1L << 21); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= carry1 * ((uint64_t)1L << 21); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= carry2 * ((uint64_t)1L << 21); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= carry3 * ((uint64_t)1L << 21); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= carry4 * ((uint64_t)1L << 21); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= carry5 * ((uint64_t)1L << 21); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= carry6 * ((uint64_t)1L << 21); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= carry7 * ((uint64_t)1L << 21); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= carry8 * ((uint64_t)1L << 21); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= carry9 * ((uint64_t)1L << 21); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= carry10 * ((uint64_t)1L << 21); + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 * ((uint64_t)1 << 5)); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 * ((uint64_t)1 << 2)); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 * ((uint64_t)1 << 7)); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 * ((uint64_t)1 << 4)); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 * ((uint64_t)1 << 1)); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 * ((uint64_t)1 << 6)); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 * ((uint64_t)1 << 3)); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 * ((uint64_t)1 << 5)); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 * ((uint64_t)1 << 2)); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 * ((uint64_t)1 << 7)); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ +void sc_sqmul(unsigned char s[32], const int n, const unsigned char a[32]) +{ + int i; + for (i = 0; i < n; ++i) + sc_mul(s, s, s); + sc_mul(s, s, a); +} + +/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */ +void sc_invert(unsigned char* recip, const unsigned char* s) +{ + unsigned char _10[32], _100[32], _1000[32], _10000[32], _100000[32], + _1000000[32], _10010011[32], _10010111[32], _100110[32], _1010[32], + _1010000[32], _1010011[32], _1011[32], _10110[32], _10111101[32], + _11[32], _1100011[32], _1100111[32], _11010011[32], _1101011[32], + _11100111[32], _11101011[32], _11110101[32]; + + sc_mul(_10, s, s); + sc_mul(_11, s, _10); + sc_mul(_100, s, _11); + sc_mul(_1000, _100, _100); + sc_mul(_1010, _10, _1000); + sc_mul(_1011, s, _1010); + sc_mul(_10000, _1000, _1000); + sc_mul(_10110, _1011, _1011); + sc_mul(_100000, _1010, _10110); + sc_mul(_100110, _10000, _10110); + sc_mul(_1000000, _100000, _100000); + sc_mul(_1010000, _10000, _1000000); + sc_mul(_1010011, _11, _1010000); + sc_mul(_1100011, _10000, _1010011); + sc_mul(_1100111, _100, _1100011); + sc_mul(_1101011, _100, _1100111); + sc_mul(_10010011, _1000000, _1010011); + sc_mul(_10010111, _100, _10010011); + sc_mul(_10111101, _100110, _10010111); + sc_mul(_11010011, _10110, _10111101); + sc_mul(_11100111, _1010000, _10010111); + sc_mul(_11101011, _100, _11100111); + sc_mul(_11110101, _1010, _11101011); + + sc_mul(recip, _1011, _11110101); + + sc_sqmul(recip, 126, _1010011); + + sc_sqmul(recip, 9, _10); + sc_mul(recip, recip, _11110101); + sc_sqmul(recip, 7, _1100111); + sc_sqmul(recip, 9, _11110101); + sc_sqmul(recip, 11, _10111101); + sc_sqmul(recip, 8, _11100111); + sc_sqmul(recip, 9, _1101011); + sc_sqmul(recip, 6, _1011); + sc_sqmul(recip, 14, _10010011); + sc_sqmul(recip, 10, _1100011); + sc_sqmul(recip, 9, _10010111); + sc_sqmul(recip, 10, _11110101); + sc_sqmul(recip, 8, _11010011); + sc_sqmul(recip, 8, _11101011); +} + +/* + In: t (x, y, z) + Out: r (x, t, z, t) + + Note: expensive conversion because of fe_invert +*/ +void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t) +{ + fe_copy(r->X, t->X); + fe_copy(r->Y, t->Y); + fe_copy(r->Z, t->Z); + fe_invert(r->T, t->Z); + fe_mul(r->T, r->T, t->Y); + fe_mul(r->T, r->T, t->X); +} + + +/* + In: data -- points to 'size' bytes of data + Out: res = Hp(data) + where Hp = 8 * ge_fromfe_frombytes_vartime(cn_fast_hash(data)) +*/ +void ge_bytes_hash_to_ec(ge_p3 *res, const void *data, size_t size) +{ + unsigned char h[HASH_SIZE]; + ge_p2 point; + ge_p1p1 point2; + + cn_fast_hash(data, size, (char*)h); + ge_fromfe_frombytes_vartime(&point, &h[0]); + /*ge_p2_to_p3(res, &point); -- can be used to avoid multiplication by 8 for debugging */ + ge_mul8(&point2, &point); + ge_p1p1_to_p3(res, &point2); +} + +void ge_bytes_hash_to_ec_32(ge_p3 *res, const unsigned char *ge_bytes) +{ + ge_bytes_hash_to_ec(res, ge_bytes, 32); +} + +void ge_mul8_p3(ge_p3 *r, const ge_p3 *t) +{ + ge_p1p1 p1; + ge_p2 p2; + + // TODO: consider removing the following copy, replace &p2 by (ge_p2*)t as it's ugly but possible + ge_p3_to_p2(&p2, t); // copying + + ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub + ge_p1p1_to_p2(&p2, &p1); // 3 fe_mul + ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub + ge_p1p1_to_p2(&p2, &p1); // 3 fe_mul + ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub + + ge_p1p1_to_p3(r, &p1); // 4 fe_mul +} + + +// returns the most non-zero index of r +int slide_v2(signed char *r, const unsigned char *a) +{ + int i; + int b; + int k; + int nzi = 0; + + for (i = 0; i < 256; ++i) { + r[i] = 1 & (a[i >> 3] >> (i & 7)); + } + + for (i = 0; i < 256; ++i) { + if (r[i]) { + for (b = 1; b <= 6 && i + b < 256; ++b) { + if (r[i + b]) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; r[i + b] = 0; + } + else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + for (k = i + b; k < 256; ++k) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } + else + break; + } + } + if (r[i]) + nzi = i; + } + } + + return nzi; +} + +void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A) +{ + signed char aslide[256]; + ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */ + ge_p1p1 t; + ge_p3 u; + ge_p2 r_p2; + int i; + + i = slide_v2(aslide, a); + + if (i == 0) + { + ge_p3_0(r); + return; + } + + ge_dsm_precomp(Ai, A); + ge_p2_0(&r_p2); + + for (; i >= 0; --i) + { + ge_p2_dbl(&t, &r_p2); + if (aslide[i] > 0) + { + ge_p1p1_to_p3(&u, &t); + ge_add(&t, &u, &Ai[aslide[i] / 2]); + } + else if (aslide[i] < 0) + { + ge_p1p1_to_p3(&u, &t); + ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]); + } + if (i != 0) + ge_p1p1_to_p2(&r_p2, &t); + else + ge_p1p1_to_p3(r, &t); + } +} + + +void ge_cached_to_p2(ge_p2 *r, const ge_cached *c) +{ + static const fe inv2 = { 10, 0, 0, 0, 0, 0, 0, 0, 0, -16777216 }; + + fe_sub(r->X, c->YplusX, c->YminusX); + fe_mul(r->X, r->X, inv2); + + fe_add(r->Y, c->YplusX, c->YminusX); + fe_mul(r->Y, r->Y, inv2); + + fe_copy(r->Z, c->Z); +} + + +/////////////////////////// +// EXPERIMENTAL +// + +// With these select_vartime/ge_scalarmult_base_vartime I got ~25% speed up comparing to the select/ge_scalarmult_base -- sowle +static void select_vartime(ge_precomp *t, int pos, signed char b) +{ + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + const ge_precomp* base; + + if (babs == 0) + { + ge_precomp_0(t); + } + else if (bnegative == 0) + { + base = &ge_base[pos][babs - 1]; + fe_copy(t->yplusx, base->yplusx); + fe_copy(t->yminusx, base->yminusx); + fe_copy(t->xy2d, base->xy2d); + } + else + { + base = &ge_base[pos][babs - 1]; + fe_copy(t->yplusx, base->yminusx); + fe_copy(t->yminusx, base->yplusx); + fe_neg(t->xy2d, base->xy2d); + } +} + +void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a) +{ + signed char e[64]; + signed char carry; + ge_p1p1 r; + ge_p2 s; + ge_precomp t; + int i; + + for (i = 0; i < 32; ++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + + carry = 0; + for (i = 0; i < 63; ++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + /* each e[i] is between -8 and 8 */ + + ge_p3_0(h); + for (i = 1; i < 64; i += 2) { + select_vartime(&t, i / 2, e[i]); + ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); + } + + ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r); + + for (i = 0; i < 64; i += 2) { + select_vartime(&t, i / 2, e[i]); + ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); + } +} + + +static void select_custom_precomp_vartime(ge_precomp *t, const precomp_data_t base_precomp, int pos, signed char b) +{ + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + const ge_precomp* base; + + if (babs == 0) + { + ge_precomp_0(t); + } + else if (bnegative == 0) + { + base = &base_precomp[pos][babs - 1]; + fe_copy(t->yplusx, base->yplusx); + fe_copy(t->yminusx, base->yminusx); + fe_copy(t->xy2d, base->xy2d); + } + else + { + base = &base_precomp[pos][babs - 1]; + fe_copy(t->yplusx, base->yminusx); + fe_copy(t->yminusx, base->yplusx); + fe_neg(t->xy2d, base->xy2d); + } +} + + +void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a) +{ + signed char e[64]; + signed char carry; + ge_p1p1 r; + ge_p2 s; + ge_precomp t; + int i; + + for (i = 0; i < 32; ++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + + carry = 0; + for (i = 0; i < 63; ++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + /* each e[i] is between -8 and 8 */ + + ge_p3_0(h); + for (i = 1; i < 64; i += 2) { + select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]); + ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); + } + + ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r); + + for (i = 0; i < 64; i += 2) { + select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]); + ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r); + } +} + +void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p) +{ + fe recip; + fe x; + fe y; + //unsigned char s[32]; + + fe_invert(recip, p->Z); + fe_mul(x, p->X, recip); + fe_mul(y, p->Y, recip); + fe_sub(r->yminusx, y, x); + fe_add(r->yplusx, y, x); + fe_mul(r->xy2d, x, y); + fe_mul(r->xy2d, r->xy2d, fe_d2); + + // to get canonical representation and obtain the very same beautiful numbers for ge_base in crypto-ops-data.c (maybe unnecessary, TODO -- sowle) + //fe_tobytes(s, r->yminusx); fe_frombytes(r->yminusx, s); + //fe_tobytes(s, r->yplusx); fe_frombytes(r->yplusx, s); + //fe_tobytes(s, r->xy2d); fe_frombytes(r->xy2d, s); +} + diff --git a/crypto/upstream/crypto-ops.h b/crypto/upstream/crypto-ops.h new file mode 100755 index 0000000..f5bd754 --- /dev/null +++ b/crypto/upstream/crypto-ops.h @@ -0,0 +1,168 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once +#include // size_t + +/* From fe.h */ + +typedef int32_t fe[10]; + +/* From ge.h */ + +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p3; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p1p1; + +typedef struct { + fe yplusx; + fe yminusx; + fe xy2d; +} ge_precomp; + +typedef struct { + fe YplusX; + fe YminusX; + fe Z; + fe T2d; +} ge_cached; + +/* From ge_add.c */ + +void ge_add(ge_p1p1 *, const ge_p3 *, const ge_cached *); + +/* From ge_double_scalarmult.c, modified */ + +typedef ge_cached ge_dsmp[8]; +extern const ge_precomp ge_Bi[8]; +void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s); +void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *); + +/* From ge_frombytes.c, modified */ + +extern const fe fe_sqrtm1; +extern const fe fe_d; +extern const fe fe_d2; +int ge_frombytes_vartime(ge_p3 *, const unsigned char *); + +/* From ge_p1p1_to_p2.c */ + +void ge_p1p1_to_p2(ge_p2 *, const ge_p1p1 *); + +/* From ge_p1p1_to_p3.c */ + +void ge_p1p1_to_p3(ge_p3 *, const ge_p1p1 *); + +/* From ge_p2_dbl.c */ + +void ge_p2_dbl(ge_p1p1 *, const ge_p2 *); + +/* From ge_p3_to_cached.c */ + +extern const fe fe_d2; +void ge_p3_to_cached(ge_cached *, const ge_p3 *); + +/* From ge_p3_to_p2.c */ + +void ge_p3_to_p2(ge_p2 *, const ge_p3 *); + +/* From ge_p3_tobytes.c */ + +void ge_p3_tobytes(unsigned char *, const ge_p3 *); + +/* From ge_scalarmult_base.c */ + +extern const ge_precomp ge_base[32][8]; +void ge_scalarmult_base(ge_p3 *, const unsigned char *); + +/* From ge_tobytes.c */ + +void ge_tobytes(unsigned char *, const ge_p2 *); + +/* From sc_reduce.c */ + +void sc_reduce(unsigned char *); + +/* New code */ + +void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *); +void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *); +void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp); +void ge_mul8(ge_p1p1 *, const ge_p2 *); +void ge_mul8_p3(ge_p3 *, const ge_p3 *); +void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *); +void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t); +void ge_bytes_hash_to_ec(ge_p3 *, const void *, size_t); +void ge_bytes_hash_to_ec_32(ge_p3 *, const unsigned char *); +void ge_cached_to_p2(ge_p2 *r, const ge_cached *c); +void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); + +void ge_p3_0(ge_p3 *h); +void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *); +void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); +void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A); +void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A); +void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a); + +/* precomp_data[i][j] = (j + 1) * 256^i * G */ +typedef ge_precomp (precomp_data_t)[32][8]; +void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a); +void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p); + +extern const fe fe_ma2; +extern const fe fe_ma; +extern const fe fe_fffb1; +extern const fe fe_fffb2; +extern const fe fe_fffb3; +extern const fe fe_fffb4; + +void sc_0(unsigned char *); +void sc_reduce32(unsigned char *); +void sc_add(unsigned char *, const unsigned char *, const unsigned char *); +void sc_sub(unsigned char *, const unsigned char *, const unsigned char *); +void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *); +void sc_mul(unsigned char *, const unsigned char *, const unsigned char *); +void sc_muladd(unsigned char* s, const unsigned char* a, const unsigned char* b, const unsigned char* c); +int sc_check(const unsigned char *); +int sc_isnonzero(const unsigned char *); /* Doesn't normalize */ +void sc_invert(unsigned char*, const unsigned char*); + +void fe_sq(fe h, const fe f); +int fe_isnonzero(const fe f); +void fe_add(fe h, const fe f, const fe g); +void fe_sub(fe h, const fe f, const fe g); +void fe_mul(fe, const fe, const fe); +void fe_frombytes(fe h, const unsigned char *s); +void fe_invert(fe out, const fe z); +void fe_tobytes(unsigned char *s, const fe h); +int fe_isnegative(const fe f); diff --git a/crypto/upstream/crypto-sugar.cpp b/crypto/upstream/crypto-sugar.cpp new file mode 100755 index 0000000..92a595a --- /dev/null +++ b/crypto/upstream/crypto-sugar.cpp @@ -0,0 +1,1987 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#include "crypto-sugar.h" + +namespace crypto +{ + + void construct_precomp_data(precomp_data_t precomp_data, const point_t& point) + { + point_t A = point; + for(size_t i = 0; i < 32; ++i) + { + point_t B = A; + ge_p3_to_precomp(&precomp_data[i][0], &B.m_p3); + for(size_t j = 1; j < 8; ++j) + { + B += A; // B = (j+1) * 256^i * point + ge_p3_to_precomp(&precomp_data[i][j], &B.m_p3); + } + + if (i != 31) + A.modify_mul_pow_2(8); // *= 256 + } + } + + + + namespace xdetails + { + // correctness of the data below is checked in crypto_generators_precomp + const precomp_data_t c_point_H_precomp_data = { + { + {{-25839914, 157462, -1791824, 10231988, 22558850, 19431640, 1713390, -20343323, 20342775, 1666609}, {12627670, 3909784, 17340562, 12788648, -22385878, -8266372, -35905398, -3684433, 17151013, 3727105}, {-28348363, -14228846, -10343840, -8899709, -10188216, 6790737, 28668879, 2065510, 25295296, -16739572}}, + {{12123870, 4350399, 31368205, -22615939, 989700, -1440444, 15590912, -7885237, 44322961, -33221404}, {-28041004, 10461293, -8953557, -1384985, -14277550, -18504792, 49472974, 1396059, -658645, 75728}, {13727829, 11677165, 26433470, 12146275, 32407426, -2423122, 27136530, -10656245, -3753335, 16230956}}, + {{51118090, 23785065, 39026994, 2444219, -30603395, -10804617, 38098061, 2907744, -11829286, 22814379}, {15342100, -9010597, -4035044, 20632301, 24850527, -5195793, 3876595, -11041592, -6587238, 8562267}, {26743467, -11422186, -13358731, 5744188, 4533953, -16135507, 30744883, 9806359, 14389811, 8975338}}, + {{56115520, -18546359, -19913338, 25001369, -44259974, -14499756, 16792302, 24258992, -13788063, -3143064}, {2585728, 5642651, 3745158, 7694735, -3406330, -1325930, 49431660, -8643236, 36098755, -5309184}, {13514064, 9335126, -16596225, -10753192, -30689993, -13556891, -24905790, 13661483, 18360127, -5012662}}, + {{40257206, 5111877, -1861784, 16048642, 43576417, -4669748, 19711942, -13265373, 55653581, 5997509}, {-7985782, -24758881, -22389642, -13273734, -20216997, 4479316, -31781518, 12429299, -6234603, 11644217}, {8308870, 7279307, 2148143, 6729248, 13588178, 6069241, -7335771, -3739510, -20848443, -4679153}}, + {{-20737583, 27643402, 2873210, -18261180, -18291839, -6268028, -44531715, -26015787, 30895024, -19385598}, {20881151, 508072, -43245146, -13149954, 22807711, -10594262, -2548441, 6997175, -26672556, 8968670}, {-3147785, 4292662, 9423734, 1742649, -19533160, 13807977, -31176939, -12874821, 15603023, 8351508}}, + {{37413813, -1313394, 23553487, 8302956, 12352081, -3174611, -6777671, 1421792, 20288577, -3464110}, {28674127, -30915570, -9713975, -901872, -1830099, 15958287, -42359115, -25372112, 41343195, -18340440}, {-29145482, 8990939, 31593182, -6148974, 32107442, 14618056, -18645181, -2212088, 18396641, -10005536}}, + {{35535538, 25794127, 43515704, 7451164, 30438366, -13113112, -35782574, -341097, 17819789, -11389240}, {-16377682, -2898071, -14119008, 17585196, 28897698, 18946252, 12492268, 1927079, 839259, 20827124}, {18576950, -7897849, 5919315, -9586273, 9031580, -5030272, -27116638, -3256204, -26195311, 10194521}} + }, + { + {{-36262283, -8280932, -16610732, -2898617, 54211337, -1517172, 21906950, 28435490, 43210590, 1218117}, {-1682705, 21957008, -43519870, -21918475, 8453905, 8719882, 41295776, 1553544, -1661538, 21673717}, {-9313596, 3378603, 30865986, 4384431, 16516598, -12721875, 19781157, -3772318, 948918, 2360171}}, + {{11810118, 5302376, -53718285, -31290081, 13990972, 1666459, 6304131, -1281229, -7153374, 13608666}, {-29575724, -1961816, -9798595, 1984375, -19036358, -10172507, 59208415, -31173633, -4781370, 16988722}, {-6095994, 133097, 24224235, 15247983, -4182301, -14756634, 21587507, 15178946, 20553208, 139840}}, + {{2291056, -9094995, -18537175, 13841361, -9273433, 11351059, -39031822, -14003027, -30576624, -5092422}, {-38783152, 2494507, -5017801, -17472967, -30855757, -6211997, -21681524, -9899335, -30822138, 15804444}, {-4183462, 5813348, 29610200, -9958924, 25900635, 1141273, -33371288, 15312502, 23382985, -15625255}}, + {{-1724561, 19851118, 3919214, -2434649, 4130055, 20191732, 2517693, 13459913, -23620343, -25742142}, {-17758693, -10804838, 6776962, 15458523, 32038261, 7791842, -406949, -4282451, 2266571, 153584}, {-23310663, -9743136, 698945, 958768, 5459145, 6080624, -21941743, -3333725, -15816139, -8876490}}, + {{28128915, 23717069, -14254111, 2468716, -1635116, 18789860, -47465541, -22684584, 22941926, 3043558}, {-31309425, -5190323, -40715825, -24164380, 26692650, 7205330, 9697223, 5927456, -23103520, -17034232}, {14136931, -16019746, -30971127, 10213637, -18320195, -15932654, -29761632, -10025284, 17978682, -4780093}}, + {{-16194700, 14443627, -457615, 3365937, -25122175, 4893010, -8305342, 4674804, 26476643, -2742423}, {2041920, 18261487, -9367817, 15814617, 28453069, -5976986, -27177734, -5350136, 7076635, 22120243}, {-20867270, -16604482, 10073765, 11011343, -10881223, -16058169, -6868310, 4582827, 26986633, 13221031}}, + {{19072366, 403182, 21379737, 8772482, 16514929, -1966122, -9491088, -2999541, -44055881, -1946664}, {-28972312, -26192360, 1124223, -17812394, -32715399, 14219630, 54954794, 28715165, 7867853, 9844806}, {-7630275, -14547412, -33539487, -10085666, 21792472, -16652098, -32937274, -7466694, 8795856, -1457197}}, + {{9731789, 3178613, -7600042, 5767160, -8969708, -15253601, -20961771, -16367485, -20006727, -26056008}, {-41832827, -1543225, 41196390, 18278104, 5428010, 1099055, 24798383, 14642177, 5003627, -1244530}, {-2128966, -6957926, 27996724, 11491959, 3338739, -9092543, -15839431, 11002022, -5046122, -1189604}} + }, + { + {{-2755970, -17615939, 31275222, 7003405, 26870823, 17119318, 8784719, 16951735, 23823587, 22420775}, {3795378, 417741, 4513574, 16119343, 10251751, 15662672, -47304547, -7686413, 8368547, 397985}, {-8607656, 8976384, 23477053, -11277011, -16031733, -2258893, -5744423, -12596121, -1025983, 8903149}}, + {{46492022, 19075568, -7280406, 21312445, -15381910, 12162940, 8484731, -5280304, -14038525, -9569164}, {10924154, -8238952, 10662028, 11586411, -10231798, -7854982, -53695283, 25786846, -5747327, -9244520}, {25416017, -3015298, 2232993, 986105, -22542935, -7403014, 26926670, 10959798, 26456258, 13853419}}, + {{-18813663, 25671181, -3327225, -14675081, -36027192, -15747345, 29400343, 5510556, 28265959, 25997330}, {12504319, -2673615, 7754695, -6359023, 24428200, 9725937, -986369, -8462474, 11649175, -4890996}, {-3886018, 2881276, 14485325, 5704885, 10124062, -2411325, -23827009, -2616965, -248597, -3411051}}, + {{43015230, -19466620, -3112785, 576202, -30255336, -18980032, 30566133, 13610387, 12538250, -2688932}, {-6324288, 8810792, -14431995, 13325638, 35085954, 12963350, -25633195, -7262641, 1592670, -1070658}, {-20025782, -5929817, -5948477, -12209150, -30422648, -5852552, -21153879, -10498881, 15928534, 7306252}}, + {{1369064, -174574, 7891892, -13901643, 18853442, 32561514, 1820385, 5914406, 40122046, 21924508}, {46303380, 1590416, -36037734, -516813, -2182578, 174516, -30062745, -24225382, 23144124, 50412}, {-29913522, -5202763, 10237212, 6911594, -11175683, -1789467, 30303688, -6420599, 7185367, -5903626}}, + {{10885717, 4105436, -61588901, 24307660, 19399021, 20354659, -1006139, -7900455, -46057752, -22251609}, {-19429393, -16605802, -2509963, -7054416, 23985299, 12887055, 31727579, -14897333, 17999672, -4749751}, {21240607, -9429948, -24614879, -11498166, 32785046, 15460686, -9241910, -15919920, -12629980, -8274375}}, + {{1555174, 1158950, 25220076, -4350735, 17963249, 8413985, -1843022, 5017864, 34521910, -19709895}, {23548174, 3859228, 25952162, 13795931, -28235101, 3069917, -29375156, 14878586, 11966332, 7752083}, {-10051192, -15202422, -2752080, 8776402, 18981704, 7873536, -20164398, 5937515, -22424852, -8610723}}, + {{24562618, -12686561, 34118835, 5129440, -1417873, 21377538, -35562536, 111702, -589296, 7759505}, {41538744, -12046915, -13795389, -14711452, 27281987, -4994032, 21029814, -2825392, 15603256, 25224169}, {-27185999, -8792352, 3312599, -5994395, -31599120, 3101325, 7539730, -16383545, 16053653, 12256453}} + }, + { + {{2117860, 21019143, 51468699, -8363520, 46685088, 1041470, 32562387, -17898779, -2873788, 4039881}, {51533770, 7511465, 13293793, -4059978, 11153614, 11009888, 11043633, 5149393, 61640404, -6800453}, {-4552117, -8561660, 23195450, -4554595, -27170724, -1970990, -4977038, -13883135, -5725165, -15808316}}, + {{11711306, -7715099, 13402543, 4886294, 3948457, -16861821, 54588649, -8627574, 15335566, -13496004}, {47849638, -7676775, 10746151, -25318768, -22127087, -97467, 5139847, -24024518, 45927328, -10995204}, {-2282561, -10611488, -4674912, -6559561, 18594050, -16435781, 11874818, 3046069, -17026318, 5728361}}, + {{41856251, 12950385, -49564258, -3338865, 17211570, 9374416, -17508886, -84564, -11279731, 14738720}, {10571673, -1007843, -10278648, 4715025, -22625794, -13812080, -36837170, -10092196, 27964543, 12132548}, {31633897, 5333003, 17305989, -15620601, 31420706, 7077450, -1282785, 14064373, 22859149, -5366780}}, + {{29401271, 17590888, 40211130, 16393297, -16781728, 21756168, -34072615, 824872, -46599901, 7258734}, {14907187, -6894438, 1941780, 910997, -22528838, -7424968, -13182161, -8108566, 19729241, 601214}, {22111325, 686053, 20766182, 16117728, 8108657, -7431453, -32100036, 7690467, 20467985, 2064394}}, + {{-9563965, 1799585, -55856440, 24457121, 2609002, -1619031, -20010702, -8967675, -586297, 3782758}, {14310681, -14492783, 11159344, -6800783, -24070908, -29321517, -3770592, 7183761, 37294119, 29117522}, {-21492008, -10816384, -16589540, -1859657, 11525668, -15915177, 23032110, -6363217, -25557687, 5298613}}, + {{-25032759, 10137207, -21211248, -1034086, 39026407, 7671727, -43707450, 27535838, -15322601, -4497902}, {11942565, 7163909, 42601550, -24698096, 17808541, 14931203, -11547292, -5943574, -28868475, -26215578}, {14343863, -10932853, -5696991, -15930429, 1361756, 3515646, -20327658, 11789280, -8527009, -11974718}}, + {{-11359733, 6002309, -8194230, -507343, -9059323, -6304308, 24341964, 23549098, -59528413, 15137157}, {-50282777, -3995829, 55101228, -31906299, -23919849, -21007134, 6100310, -9828078, -6180425, -3361637}, {8981133, -9453900, -8051056, -8941797, -18262629, 8468728, -22819884, 15223516, -14658504, 11171251}}, + {{6674374, 10785646, -4108828, -20474317, -4107060, -9714386, 23875362, 16560960, -7939903, -5481596}, {18327574, -11544652, 6892376, -5234831, 27509434, -579964, -27318176, 957470, -31859127, -6020504}, {-4939268, 10764095, 4739768, 9712551, 25335990, 316087, 23616732, 13096853, -793009, 1895383}} + }, + { + {{2543110, -9808347, 4640240, -7010430, -47238686, -2552162, 4162536, 10379266, -9885342, -2539863}, {-26280850, -23281219, -59949252, 24374544, -686566, 18693896, -9672404, -20736822, -29243944, 29417147}, {-21990215, 14672579, 7157233, -10322365, -15041058, 5857122, 5758298, 11088514, 23812375, 842231}}, + {{-18705612, 2687256, 11824336, 4480752, -36363579, -7660875, 8785758, 8793908, -14316875, -12590786}, {-31902556, 14677678, 5320722, 16466372, -12295499, -15254163, 11452314, -13028410, -14238999, -15351652}, {18718379, -15630347, 31248183, 9915829, 6883322, 12295368, -18266196, -1000492, 9640603, 5026495}}, + {{32867173, 9713255, 2509886, 2391981, -3573937, -7843211, -13959718, -3563177, 22213554, 22944211}, {-762971, 8382357, -35082658, -29670317, 52550109, 17901337, 39668850, 12599955, -41857292, 434617}, {4175818, 6202136, -12981802, 10989660, -13446840, 13409458, -8145375, -398509, 30749406, 915555}}, + {{4634039, 1303916, -22754903, -21524256, 14068582, 16069808, -16878209, 22976842, -28822159, -8825216}, {17868875, 23791960, -24264405, 4862386, 39600206, 6002486, -9879199, -2411588, 24192121, 21457056}, {27118539, -3102105, 17342980, 1586278, -24597424, -11260946, 17727987, 14885443, 6489081, -16506177}}, + {{17995544, -8765498, 5909664, 12827982, -298225, 4966027, -21497021, -21247921, -9748613, -14917233}, {33627094, 19855512, 38840280, -9008172, 3438267, -20222203, 35781059, -1283183, -42823477, -3873729}, {32062430, -6288947, 23295494, -9453258, 227865, -7475030, -9517768, -2542778, 16094581, -13647547}}, + {{-793671, -14570717, -56571197, 6602565, 8352983, 5383136, 20073779, -5725618, 30790587, 2760327}, {18673609, -4434905, -9896767, -16492307, 19553749, 12166150, 46972893, 1214842, -17742015, -23402027}, {-29663253, -12436383, 5475870, -10905550, -857503, -12499416, -32109832, 14728704, 6093894, 14964981}}, + {{9481017, -7763642, 11376981, -4421714, 6488144, 227795, -39110010, 8413171, -1805191, -18704214}, {44704145, -25100814, -34948723, -4099268, -26111248, 3476373, -4360006, -9717733, -20338933, -5084634}, {-5048671, -10975302, 24921200, -14328979, -1143468, 930428, -29583430, 711968, -31536251, 4173233}}, + {{23571098, 17917014, -42844963, 27084836, -2723388, 9411004, -17205187, 20670486, 204409, 1032379}, {8062384, 12085736, -3230951, 2713858, -5187980, 16498068, -19462575, -6606642, -30054249, 3236679}, {11234981, -614076, 12581588, 11210266, 149116, 2959366, -19799199, 6852842, -23892167, 14326076}} + }, + { + {{-55407608, 10389205, -13719459, -2798022, -50197552, 14459564, 18222745, 21430201, 32575812, -8706832}, {-2564000, 13377951, -22379461, 11840346, 3388836, 13098300, -36010183, -4645599, 8583764, -15216002}, {8844512, -14692897, 18384808, 15191210, -31354755, -640150, 14796127, 2046560, -4888509, 7877940}}, + {{-31758000, -17823772, -11824015, -29062393, 8891526, -6664321, 5502853, 8024723, -22944602, -15063066}, {30418160, -2270432, 38309221, 1972107, -12567508, -19040641, 25038133, 21969139, -9754328, 6486026}, {-15209373, 14879569, -12278800, 8242447, 21217813, -2706193, -11674610, 3776800, -26436037, -2772941}}, + {{13887517, 2793678, 25907763, -16634306, -65840, -6202767, 55572925, 31310928, -8676929, -6897952}, {5270009, -20924388, 23172827, -13573232, 12490658, -5078395, -6139227, 273190, -1980075, -2701458}, {25806042, 13685317, 25123807, -3440883, -22680732, -10820546, -6184384, -14704447, -16822836, -13171217}}, + {{-24206352, 12893245, 4424093, -29853833, 19045229, -2822333, -20693465, -8898606, -28285556, -10932499}, {-39992522, -15746847, -36152997, -2454855, -30967513, -9484603, 40560125, -22691342, 3152880, 22543637}, {25251286, -4412149, -3137687, 12914226, 4215400, -6359262, 14279424, -9974704, -4975655, 5727071}}, + {{-12723933, 5664973, -32702910, 6392489, -38337493, 12732070, 10066344, -6355754, -43893475, 18466328}, {-53801615, -21581197, 18254024, -21559193, 15933113, -13981074, 14179938, 15136906, 2131091, 330460}, {-20916166, 8517295, -15047901, 7866106, 23068626, 2776944, 20230557, -13171647, 27542922, 1272190}}, + {{18625220, 20038591, 29117886, 2551065, 7597130, -24925654, 49173757, -14071381, 1652545, 12919204}, {36848386, -4455055, 32915122, 5036091, 12485852, -4465570, 12568205, -18115249, -62704171, 19541718}, {9730256, -274817, 32374106, -12264171, -23404505, 13869684, -8315359, -8284483, 8794383, -4179338}}, + {{47715457, -20478414, 26959996, 4620275, 41356265, -27076409, 5057058, 14750257, -1220827, -3274470}, {9295203, 7485020, -23371420, 19197583, 13649391, 1942759, -34609024, -2086483, -41922107, 25475742}, {15032034, -16351658, -25832415, 6367304, -29970907, 15969403, 27884976, -11464895, -16996239, -7730352}}, + {{19431047, -2260397, -10477516, 12987323, -28637035, 4788502, 50062278, 16109873, 12054936, 14649909}, {14068557, 25603425, -29318290, 14735201, -29487071, -3659852, 6013412, -779311, -25677432, 4593481}, {-8985336, 16768214, -17001696, 5044973, -30451488, -8576060, -24873505, -9261152, 20349988, 9722404}} + }, + { + {{16244425, 19386605, 13179016, 16779731, -30413594, 2771521, 26266816, -29965121, -19580065, -21702146}, {-10286589, 10328523, -3557058, 7082567, 9264482, 10014543, -33567546, 1785693, -28595425, -4403048}, {20613396, 3045350, 26511462, 846589, 1825114, 6510426, -1159746, 13715579, -4677392, 4700223}}, + {{32349255, -1888695, 10005871, 8154731, 51249234, -20187563, 47865489, 14968746, 26874060, -3634423}, {2327953, -26050361, -47093437, 23300365, 2090724, -12450009, -12126499, -8782200, 20557240, 2698983}, {3670930, 4474936, 5884156, 3007236, 18126028, 4038474, -10256988, -4400184, -24987311, 2654997}}, + {{5533532, 20562652, -635126, -7848089, -13086965, 13192141, -3410187, -9191554, 34865324, -11912506}, {-29597680, -3633734, -20926288, 14155461, -52963837, -19574309, -25891125, -1702880, 23825504, -237972}, {-18346199, 968436, -2131689, 6191929, 23849553, 13006847, -26057361, 13509301, -21018175, 11596373}}, + {{39453651, -1135365, -1065127, -2136909, 14021839, 373282, 6049833, -4481292, 29651109, 22055750}, {-2020135, 20780431, -30250459, 2974907, -19840931, -3341590, -11113897, -14225426, 4123457, 9244600}, {4040937, -8135822, -8225471, 13967399, -3430292, -2062606, 30224578, 1456799, -13622851, 14626044}}, + {{-48264804, 948333, -40876951, 2308305, -15905104, -3151435, -49326789, -5347391, -21668059, -22869817}, {-2938060, 1790191, -21896787, -15138945, 8333162, 40791, 5881669, -13278349, -36626565, 7065921}, {22908134, -10952941, -32040081, -4228188, -30346707, 14226961, 32514498, 9158454, 19853999, -13650510}}, + {{52592, 23183064, 12822258, 5295898, -30584287, 15141493, -40102815, 30555412, 15395867, -6057918}, {54410792, 7131574, -28912024, 12922570, -6534349, -9585759, 3731999, 257018, -29197749, -18737952}, {-174622, 9813123, -9335186, 11240533, -609670, 2141034, 11990383, 15382033, -27641020, -9934187}}, + {{-42856892, 2801630, -12092033, -7826833, -36150139, -3058418, -15797991, -22222372, 8853262, 15067461}, {-13333114, 10291648, -11261243, 16808507, -29620407, 16581608, 36763155, 3151030, 829028, -18276069}, {-32412756, -3132827, -3877653, -2633776, 19498083, -6681205, -24598890, -14645255, 30099164, 1501624}}, + {{-14564585, -5495570, 35218902, 11789804, 3723625, 4078436, 28190283, -11969816, -19233658, -15477722}, {1731709, -14408930, -20806568, 13954940, -27871721, 21453590, 38687519, 16951100, 20128750, -797404}, {-26482066, 13341206, -19287886, 14511797, 20664472, 1928783, -20158033, 13260751, 7633852, 2523852}} + }, + { + {{-43260040, 6473328, 1557622, -21385728, 24624685, 11053362, -24465831, 12027121, -1296883, 9498438}, {-16064298, 20871518, 11964026, 5201486, -36037983, 18277458, 28053689, 17963957, 44543663, 10070674}, {-27698134, -12414407, -17523137, 9603262, -15925455, 15527330, 16231856, 12548929, -8177364, -6027408}}, + {{54662134, -16031162, -32531502, -6748029, -27373251, -17154859, -2919279, -4967069, -19857396, -12138642}, {-4528692, -4676104, -532628, 22644343, 23361237, -8451575, -19988603, 13755583, 38755320, 13494238}, {28034349, 16011370, 6132375, -8026861, -19955403, -7342119, 16292641, -74506, -21896084, -11403465}}, + {{-27593454, 13094223, 35050187, 1112152, 45305703, 10174602, 4540352, -22476723, 8851103, 26977909}, {27603070, 16225037, 10003177, -10210650, 3042761, -11799892, -18967616, 3300265, 55941741, -1322865}, {-975595, -8515612, 20576907, 2962944, 12376740, -5009942, 21475070, -16247744, -13639259, -16622990}}, + {{-6110762, -12336453, -2318130, -5293577, 10242972, 21717357, 9484750, -21048697, -16405325, -3121616}, {-36766202, -10738143, -12260760, 2799389, 13880050, -5957397, -56205822, 12279109, 32843571, 19087862}, {15875026, 3224511, -12725397, 661269, -16504206, 10113042, 671550, -10167884, -16476069, -5775251}}, + {{24174059, 16800154, -35453149, -20683887, -16630766, -235749, -49655106, -19201968, -14957929, 302652}, {21095113, 16413642, 25034797, 12281045, -25995382, -15574183, 11387976, 13951464, -6296971, -3614340}, {7701316, 9057097, -12978262, -6751617, 16046484, 14808471, 18295322, 7703037, 17283873, 16412759}}, + {{24766011, 3466911, 20112996, 10045961, -11731260, 27258118, -21214589, -5138226, 22956653, 20127633}, {-13819457, -19663829, 3731692, 9071875, -24835514, 3391776, 5955643, -13096752, -15111547, 12696429}, {16184053, 4573318, -17066559, -472613, -2224225, 2916776, 21667607, -10476553, -30048037, -1341833}}, + {{4557388, -1972662, -34743601, 13494495, 22917070, 22449028, -22203466, 4083592, -30902632, -4735027}, {11406160, -19148786, -13354069, -508601, -26264648, -745760, 7422244, 701712, 30980020, -21199307}, {14333857, -5590987, 6336464, 8243629, -1569954, 15610409, 4031224, 5913240, 30974437, -10097923}}, + {{60565938, 18605270, -22643533, -14144463, 4580055, 14974313, -42658993, -17338515, 55114833, -14643191}, {-1959344, 4923498, -9091303, -18659853, -14989713, 11476693, 13934329, 10418799, 9581511, 16236503}, {1739437, 1129470, -12558964, -14599784, -30795209, 11604674, -5463951, -5930706, 12186005, 13818430}} + }, + { + {{-35478255, -19403058, 29130078, -3642192, -34054760, 12773830, 24323609, 25676557, -26930001, 6357793}, {18267019, 5036964, -17784856, -19703634, -23254380, 15482690, -4580859, 6326055, 24342013, -9259319}, {-2950009, 3333325, -32927075, -12107849, -6923141, 9900443, -3010914, 5671126, 16389078, 1557327}}, + {{10712172, 818755, 7114214, 10157030, 19626281, 8732952, 33425659, 17622561, -27215469, -8473975}, {19409164, -9071443, 59470274, -6383510, 19652897, 20077708, -29602987, 9423745, 3533003, 23726147}, {-18023673, 503440, 18201137, 12757869, 22934174, 1069362, 5479785, 1332067, 16669690, -3732180}}, + {{30095728, -1023560, -34998228, 3543534, 7033440, 30383354, 7008416, -12802313, -39158980, 21350261}, {1500790, 32163628, 15195912, -4749332, 11244090, -345690, -39114600, -4356623, 20191942, 5711477}, {18544374, -2437080, -10415432, 8680001, -8473986, -10631562, 31052589, -4760889, 26647148, 7652851}}, + {{-310955, -16499706, -635305, -686453, -44988759, 9642745, 60244219, -10445966, -7916156, 6506535}, {-24768229, 7400614, 13965641, 11719377, 6626005, -18788057, -2556845, 1486824, -7401572, -25244247}, {-4820920, 12142029, -1139587, -6661198, 27235613, -2483020, 10372730, -10526385, -11360259, -9895901}}, + {{20981792, 4993609, 2988489, 14558375, 22384493, -7571434, -3059548, 24452930, 7152018, 8227212}, {-20323276, -28219857, -6886853, -6962443, -31824749, -13156966, -10764090, 2798338, 22844258, 23870578}, {11918979, 3062159, -4786142, -3857810, -26146709, -15843897, 9528498, 15484827, -10327136, -1746398}}, + {{-36733054, -17098633, 9026429, 19135840, 37747779, -27559988, -26286152, -7444604, 21768385, -11637434}, {1811862, -5871527, -29000157, 13727644, 2680547, 687652, 5779176, -8569598, -44773239, 17208944}, {27919463, -5431219, 4145592, 4896258, 23901878, -6342172, 7447305, 12138807, -21821064, -13317856}}, + {{-63347, -9814554, 7668513, 27954176, 21976240, 2241302, 11545847, 4113160, 13342234, -437965}, {55895825, 22698358, -31745797, -4544224, -7756956, 11469750, -31063721, -4707422, -44478960, -25234225}, {-28786201, 15355265, -6595787, -5899836, 22617098, 5066812, 4049296, -554708, -2282219, -10143923}}, + {{-57035299, 7525263, -7759463, -3860455, 7863270, -12163150, 13088274, -34470, 47799063, 3872567}, {7751963, -9466541, 13131857, 3765811, 49026840, -7923420, -2137972, 29165054, -4573467, 10747679}, {-7889899, -15989294, 10543109, -8174449, 7082557, -6339215, 24191217, -15720948, -18571862, 8288783}} + }, + { + {{31309227, -10120033, -13429146, 3234061, 18088861, 3111663, -8801175, 17996011, 4769010, 14877554}, {28378843, -21528929, 10080100, -23750517, -4265317, -21010053, 14789483, 8513905, 47848204, 6371606}, {14817669, -5700112, 16317964, 4628849, 14421506, -2827628, 21780208, 9496046, -1975569, -15947664}}, + {{10708579, -663718, 14424671, 11438950, -4290406, 1370867, 19810548, 8964001, -10534574, 25360025}, {22613355, -15549820, -22727309, 3537740, -18558418, -19889309, -44420352, -20699201, -6487080, 4086117}, {-33332299, 14506969, 13111404, -3065059, -5334306, -15140417, 314023, 6631436, -24016063, -13927512}}, + {{47577230, 26081704, 44087640, -12653324, 44880330, -12535475, 4091120, -5980698, -16019469, -6988148}, {-6316018, 254878, -20381742, -19059830, 15070988, -1975275, 49017536, -25812022, 38570443, 4733444}, {5941462, 10715296, 20618971, 12996738, -27961003, 9287116, -13261369, -14265766, 19222667, 9694024}}, + {{50424099, 15808062, -228330, 21105609, 23247468, -17656986, 40809196, -22805126, 3651122, -25519565}, {-9303781, -15714356, 56345338, -3627083, -39042480, 5749722, 2755528, -2410224, -38591278, 1621663}, {6784609, 11617250, -8516435, -15425251, 13363912, -3305824, -6389143, -14881764, 26775080, 328929}}, + {{-6343434, -3807555, 14111814, 142075, 26569243, 4377956, 21258632, 28483037, -14604571, 5428106}, {-1825334, 14697797, 51742052, -19721041, -14807097, -24634572, 45205776, 2753003, -9906043, 3227470}, {6843194, 13129334, -25344427, 6959244, -27940482, -15930143, -25342017, 8526681, 32584402, -19181}}, + {{48603459, 1622843, 10690168, -20815014, 42891414, -685473, -23520500, 13623750, 23771584, 25338055}, {15821205, 14084935, -53143204, 4755752, 23247376, -27381429, 37299558, 10926412, -38889646, 5703581}, {979907, 12364857, 15521822, -6791124, 125160, 653393, 5818060, -10976810, -3077837, -3561753}}, + {{16247896, -6972098, -3117418, -23371848, -14508093, -24209133, 34053148, -8080607, 8768009, -2819682}, {-2542448, -7614620, 57701658, 7104698, -20507567, -4917351, -16909516, 8057001, -36253219, 29603518}, {10602149, 14586027, 33238613, 968724, 14073078, -14262826, -18990197, -11128373, 17933689, 1865638}}, + {{-1685718, 2399540, -27537630, -3785648, -24186603, -2815001, 15877013, -12997876, 10506457, 15106158}, {-31268322, 5974314, 2565124, 5022928, -29203089, 17059499, 14032757, 8734438, -52574125, -14648992}, {15590977, -4990683, -22095383, -16512348, -4299452, -3852649, 9403715, 15655990, -23393954, -14460372}} + }, + { + {{-37369470, -4604374, -13299226, -12500975, 1090943, 9931909, -2540543, 3345536, 8805568, -3847581}, {3448882, -11039762, -498478, 8160031, -32767971, 14059967, -8274027, -29682076, -23057400, 27264979}, {6733683, 12574311, 32233740, 15210420, 30532307, -4990676, -11354801, 5044573, -33368350, -7055348}}, + {{3332860, 7330151, 14119860, 548331, -32089682, -13355081, -62005018, -3262142, 11384920, 1613906}, {-20989898, -9767083, 26727662, -6555871, -31170204, -18158849, -361110, 26372934, 40556624, 6592026}, {-14382, -10034696, 21180475, -13481209, -8858357, -879701, -10010244, -12628483, 5381832, 15522788}}, + {{23442936, -9645451, -3095778, -1972364, 8661736, -6340237, -28010800, 11065785, -14487431, 12313579}, {-9498676, 4731359, 20794022, -27114326, -45878634, 9580915, 18659456, 21026965, -26651563, 9257031}, {20098670, -2165836, -22463512, 9495619, -8584563, -14416361, 28126763, -10967903, 15508507, -13170138}}, + {{25913605, 1969581, 864912, -24569567, 20475136, 1302815, -35026388, -13316709, -10841039, 2655272}, {-35890007, 24248971, 43076998, 989791, -12095108, 8863341, -4423904, -12105939, 51462723, -6235022}, {28032028, -9287453, -6706938, -13875364, -15082336, 4173292, 20614416, -3672459, 20376541, 3730791}}, + {{-47966139, -3723482, -23105532, -20264332, -14454715, 10507468, -17799502, 14906682, -30484758, 23141559}, {13962911, -5035296, 39238248, 7090710, 39307349, -11801732, 7498818, 16807300, -24044194, -9491447}, {9876300, -6253555, -5795237, 16623989, 15150684, 10230086, 28143791, 14904824, -25321821, 12582879}}, + {{13878510, 8136782, -44827884, 211696, -23663124, -27674970, 43180760, -8111421, 28806806, 1871728}, {-20937788, 9190664, 9063434, 8148344, 33620962, 3292652, -20283470, -25052025, -27042338, 26507414}, {13269905, 5741364, 6572729, -7083198, 1063870, -612394, 18258440, -16729936, 30210502, -12036586}}, + {{-43340533, -1659297, 32502357, -8168562, 14551290, 11303417, 30633369, -16404919, -6687359, 2697908}, {18797601, -30823125, 12697389, 25216842, 4085606, -9751835, 13690333, -12522671, 21935261, 9453278}, {21604819, 11323086, 31609022, -16567650, 27157754, 6691142, 5270536, -8989324, 21208395, -3994233}}, + {{4491535, -3901970, -17432264, 21965530, 15209514, -9715706, 38557094, -7374169, -7383038, 1560053}, {-40426265, -23815208, 22565190, -6206930, 42106308, -15153260, 8756382, 2019395, 19169788, -16659457}, {-29803206, -6105424, 22810027, 6907244, -2770486, 4787824, 5434016, 8936077, -23072042, 6465499}} + }, + { + {{1359526, -24496517, 12739718, 15825090, 13757731, -85826, -5634793, -26099760, -12697211, 18193534}, {-30665532, -3700315, 35823346, -8583334, 48650885, -18459174, -11166307, 4088974, 4409515, -13737722}, {5883165, 10377734, 28162516, -1270493, -7170962, -14378797, -24381074, 15601881, -2015194, 16340442}}, + {{40776751, 7628001, -36800135, -23784731, 10527576, -2276280, 1005673, 5305084, 34977839, 7027929}, {25785539, -8358493, -14169157, -941665, -26727096, -8572452, -37347281, 26636568, 5428891, -16363291}, {20812660, -16641501, 16501026, 11766799, 8242740, 8504683, -32152645, -13636741, 5182832, -12868494}}, + {{-11426179, -16123489, 9211968, -3793779, -1415467, -24016961, 44379617, -19425014, 9288996, -1283140}, {-31623749, -7257865, -22402126, 5544031, -19404557, -4057317, 1073669, 9849860, -1911856, -28320334}, {-9189155, -5231005, 28794763, -2421382, -8377667, -1076498, -25284938, 4798666, -30829635, -16494880}}, + {{7748378, -8485428, 17925664, -1037621, 29601847, 28681986, -28410463, 23057803, 2571240, -12202391}, {43967412, 13465308, 31093816, -3101433, -6966813, 248984, -31559605, 2659161, -38301184, 367885}, {1077792, -10693550, -31685170, 12960093, -21815056, -12333718, 21110948, -8355869, -20551815, -13082804}}, + {{-16658278, -1776747, -49320746, 3268840, -9161932, 3366653, 13547568, 464960, -6663953, 31367815}, {9178132, -6190845, -1488318, -17126490, 54784914, 17732495, -51588184, 10003598, 45290107, -439977}, {-5745670, 14361424, -16869431, -7959435, 8475014, 149961, 5416937, 2316944, 5620355, -11502920}}, + {{-23119897, -278325, -40471835, -7725944, -36491612, -18075366, 11989701, 14246374, -25468931, -20403038}, {6774845, 12418993, -3607903, -232642, 3816628, -7391076, 32177423, 13233488, -41072015, -12292622}, {12249995, -1086614, 15059650, 14759477, -10480279, -2927245, -23701950, 8802868, -16881368, 13226705}}, + {{-4617370, 730165, 6275053, 2018584, 33324113, -20772082, 19313139, -5717890, 25081460, -748756}, {21700676, -18005757, 8939095, 17757354, 17339219, 7413892, -11924225, -26230164, 7336468, 10944214}, {27906889, -6186337, 2933378, 6045852, -22395141, 7566091, 20652, -9292812, 12869332, -7249143}}, + {{29306699, 11394548, -26402239, 9596096, -48987263, 15755348, -13990905, 3552647, 30504592, -11033892}, {-24214285, 12852074, -40141535, -4071498, 9210503, 9187860, -10030141, 5519251, 34591920, 5583424}, {-7379292, 9129651, -27605104, -2097314, 27463602, -10277545, -7870303, 607936, 31933339, 5106556}} + }, + { + {{4963336, 30566458, -37136792, 4067521, 23891759, -4720023, -12816701, -11241268, 55320303, 1681387}, {15572948, 1586798, -28125896, 15671757, 29155331, 17673481, -34717495, -11365824, 113643, -31577145}, {6762588, 10685233, -8185349, -15717909, 5086315, 295811, -8997093, -9079304, 27737567, -1733458}}, + {{13002352, 16645200, 35722894, -10650753, -747123, 17328050, -24844918, 23399376, -19265384, -17742834}, {14753640, -13174550, -30840888, -14673027, -44036543, 10285590, 7337012, -9120376, -3487394, 14269638}, {7874396, 10712779, 29245055, -2747462, 7138405, -6636924, -25434782, -10508735, -23592427, -5389218}}, + {{-50164345, -11794259, 19659702, -8196770, 20274739, -6312077, 2700612, -3027608, -5113712, 15337537}, {6999467, 16080959, 44188308, 6905376, 9606919, -18176839, 49565008, -27684824, -37868634, -17912063}, {-13996803, -15465353, 33254067, -4645956, 5129744, -9412605, -17163224, -11740413, -21611420, -12468971}}, + {{12532020, -16701407, 38834575, 26174269, -16525516, 12418955, 30854724, -24095435, 9173016, 24509775}, {40312388, -8767627, -6631607, 5517149, -50471458, -7397475, -14955174, 1762317, -4466492, -7050493}, {8010439, -11120597, -20666396, -5670804, -24665933, 6998169, -1215708, 15533381, 27712093, 11647611}}, + {{6295646, 7402540, -31719851, 1673087, 30802846, 28126431, 25335594, -16219328, -37404513, 17052354}, {35977310, 9516280, 11288617, -22896661, 33492032, 2192159, -2413372, 14896262, -8809959, 15613754}, {32482139, 1018569, 6746330, 9727262, 19722395, 15969951, 18153008, -5153011, -18580360, 15187146}}, + {{-9659530, 10483762, -7711787, 6503533, 23723680, -14168934, -18766723, 3380559, 15825727, -10678023}, {37979770, -4123562, 11687469, -23732759, 7044880, -4832668, 20773237, 9009651, 8899955, -21901477}, {-16637573, 9260475, 29195132, 5043537, 32477611, 16711561, -9855228, -2335720, -16457364, 3972439}}, + {{-27275346, 14198716, 37705088, -5737219, -5966388, 5310384, 30973546, -10799630, 11686946, -3472324}, {-26575214, 12416248, 12851324, 620561, 38402614, 18181650, 22087592, -16733900, 13929664, 9066520}, {19574371, -10420795, -28302872, 2640062, -26714255, -13400364, -13705673, -8131657, -14448411, 55284}}, + {{14540970, 29727830, -30602401, 18990126, 33980643, -16229364, 6699745, -5043718, 44511147, 12134296}, {28598058, 3700600, -267003, 7852376, -16837049, -13653616, 30860547, -25980090, -5529243, -1996986}, {29512945, -7269820, -18080422, -3726556, 19414872, 5420554, 21801352, -6568354, 24841549, 3679173}} + }, + { + {{391066, -6119647, 53075195, 21658749, -2381210, 8221754, -9761010, -27409326, -10197081, -16082891}, {41715756, -9154201, -6700157, -3279735, 32254248, 10719048, -864674, 2811352, 37636847, -1358927}, {-18493825, 13328651, 30775311, -10858279, -19652172, -15451753, -25193859, -14919662, 22115005, 15238952}}, + {{-37909950, -4192427, 30763759, 4709595, 6440100, -2496575, -8313792, -134671, 25584787, -17709141}, {23415766, 507961, -8540857, 19584539, -17226726, 20277901, -4744136, 9020001, -18669633, -7221827}, {-13944774, 12082688, -21867733, -11816481, 14018582, 5580472, 29102869, 8058592, 19045045, 7370374}}, + {{9705609, 7038527, -58230350, -2209017, -57423030, 4600011, -32248810, -2169572, 16216102, 26345175}, {16418235, 18291867, 680530, -3210101, -3828314, 19652983, 14073034, 21243878, -9207572, -2288927}, {22369071, -14609655, -31116570, 2112500, 16859660, -8092573, -14483593, -6949857, -1972633, -7815412}}, + {{-12800678, -13905288, -27451889, 30926977, 12519625, -10453572, -18014280, 3951332, 37755617, -17506232}, {49451072, -690596, 5460063, 824367, 25433997, 3255182, -568244, 21039574, 29149223, -68094}, {-22170908, 11982726, 23379989, 15914039, -19728121, 4718196, 16063195, 4276575, -30749654, 944442}}, + {{3507922, -1425483, 29783822, -12479867, -15770827, -9983485, 11572826, -2076547, 26346169, 5967647}, {-62870078, -29517849, -23683284, 5935613, -50475545, 3076951, -52330402, -30033345, -9663027, -17932715}, {25162683, -6473299, 2353629, 14862607, 18708912, 1571931, 16861776, -5747884, -5108055, -3109486}}, + {{1234152, -28457094, 37980852, 2473998, 41455415, -5755878, -40492603, -3808641, -62657876, 4804142}, {5492734, -3579724, -6764702, 28414580, -1758437, 5241018, 25397671, 3228983, -1588100, -24365962}, {-2763454, -4585844, -20110752, -15332706, -27379233, 7178363, 9970084, 5116494, 17538635, -3624594}}, + {{-20805311, -5931254, 56412512, -1608050, -11523407, 23859878, 21365865, 113887, 36730200, 15056083}, {39914069, 19449542, 3892770, 13534694, 48838993, -3952798, 11326589, 24503511, -948032, 4774861}, {11185844, -16645023, 27830878, -15207952, -31579784, -1217890, -18632641, 10274575, -5164967, 6798995}}, + {{-3943884, 3750725, -39942933, -2202737, 26663773, 28874785, 19208707, 19642878, -5073211, 20630016}, {1531932, -6260105, 21645569, -20776181, -22015031, -1049151, 44581341, -1150520, -36055919, -10315592}, {-20274886, 3155403, -32509797, 6623133, 9261194, 2412207, 30805150, 260264, 30935086, 3378893}} + }, + { + {{2456609, 5044184, 27761770, 15627626, -3940971, -9335846, 15290318, -17081414, 42038554, 19706346}, {-41097223, 5892414, -15032582, -12463660, 32708353, -20099178, 47350188, 2522908, -21093508, 13321318}, {5518369, 6348967, -25201570, 289887, 560978, 16568987, -15355900, 568715, -31190019, 4727475}}, + {{31185336, -10483456, -37299080, 8356920, 27424791, -7362674, 24036320, -6022865, -5078922, -3574816}, {11177636, -20684076, -13686546, 16140950, 25909933, -18451818, 14995958, -14234263, -16615184, 20696602}, {3813290, -3117879, 15037061, 3816371, -1034575, 2871123, -22604995, 16662721, 24637410, -16185671}}, + {{-8987896, 13194029, 11155201, -8963227, -37870035, 26494547, -28330859, 27932297, 44786771, 7961589}, {-45578616, 2857209, -521875, -11450219, 4802629, -5386173, 4688241, -3348823, -3783463, 20074769}, {-12147244, 7998077, -25771417, 14239968, 23951091, 11211112, 26698027, -8087972, -15680427, -9159835}}, + {{-27243225, -17438566, 17434233, -10890708, -14737439, 12480835, 16491251, -9343239, 19565049, -14877451}, {23555493, 9071130, -26367681, -1168928, 37963929, 14731387, 11305463, 579837, 8934479, -4076145}, {32635109, 12910790, 8282213, -9490747, -7579958, 8628252, 18891913, -814219, -482373, -15415349}}, + {{-34497475, -12678735, 3470092, -565063, 34727988, -8464845, -14968563, 19053231, 11257197, -17824793}, {-5609425, -10735585, 22720772, -23774369, 18822870, -24738365, -28219297, 8527519, 40109007, 8196727}, {5899615, -14070754, -25725508, 5046551, -11104529, -12447238, 2609755, 7511132, -2422836, 13603924}}, + {{50279223, -6542922, 57577079, 4157343, 28588577, 10816789, -4169143, 14389080, 18933993, -11936162}, {-2892733, -13291544, 4167479, -6050935, 8843247, 13500705, 5440479, 2716608, 21774931, 14816432}, {-1515500, 10096176, 15458216, 6580225, -15799990, -13162512, 11945, 6056042, -29278354, 7784731}}, + {{-17292251, 22921824, -41980180, 6880360, -20277830, -385380, -6248053, 19142825, 39153746, 24117310}, {2365821, 8923556, 20174252, -7419762, -5987630, 27493092, 42106317, 12657137, -4887740, -4018944}, {22418897, 4406093, 14754619, 16080495, 16667366, 1275772, 18794492, -13435985, -8834707, -8557653}}, + {{-5519360, -22306381, 17393012, 132810, -28174213, -5967401, 19543649, -8522749, 18008387, -12925150}, {-17725306, 10765521, -8350494, 10589526, -38535239, -175247, 19787205, 16895045, 8342735, -5746916}, {-19597732, 14277837, 5271372, 8893441, 12867329, 10024988, -30069463, -16722246, 18027331, -8111094}} + }, + { + {{8211443, 6846191, 6945247, 7074724, -16163053, 15261919, -4711628, 598717, -2132537, -14458264}, {43176173, -2930209, -27378935, -17199378, -50191235, 10250513, -50228070, 21301081, -53402185, 7938340}, {-10404692, 238394, -17223298, 6317408, -4597422, 11845257, -25086201, 14106911, -13527225, -4046014}}, + {{-14175163, 15668594, -6576950, -7210777, -1888191, -366448, 25645549, -16272198, -4885076, 3841556}, {2511583, -5186496, 55890844, 23657615, -21883851, 27772590, -39009655, -8971750, 14765424, 19640334}, {26025475, 3849658, -28905409, 8029819, -27234840, 13808387, 24915058, 10020824, 29062335, 4425302}}, + {{1734057, -26209178, 26725763, -22326962, -5230996, -1052637, 6999425, 2262570, -19773062, -1700510}, {-15374263, -5806068, 32689871, -5088860, -31436222, -8321645, -40985977, -21502672, 35714796, -18222214}, {-14768861, 5265598, 27017752, -11383707, 25272910, -10608235, -19841735, 8143974, 14355736, 4895974}}, + {{2564989, 17774433, -39389878, 7381726, 4788616, 14437703, 46532039, -15500352, -35606481, -9383279}, {31821159, 11038283, -15096324, 17036130, 12947696, 6672291, 6712285, 10625526, 17575711, 17919583}, {-15547771, 5972443, 25740339, 5225389, 6240913, -14419532, -13177629, -14025954, 25433375, 6923784}}, + {{-39602241, -22451961, -6679348, -1879873, -31306455, -4673801, 42003200, 15633673, -25485306, 3618740}, {18966027, -2937179, 44083354, -11883267, -26013759, -21812007, -14601802, 15200437, 12874508, 24527692}, {-13595163, 13994428, 28115928, 9952765, 11976530, -3003087, 17405764, -11778077, 10153753, 10737243}}, + {{4758365, -18760313, -39703731, -5769023, -22327353, -12858180, 10132725, 25214914, 30390380, 22401913}, {43780679, 2887997, -12734617, 6126773, 12526713, -7150442, -27133987, 3407118, -25816654, -8843037}, {-4646664, 16249032, 12870592, -15878236, 17245698, 2787385, 15233470, 12902660, 6727344, -4068799}}, + {{41164736, -28920406, 11332370, 5410817, 1165589, 2906065, -14252437, -9444526, -33243955, -5692085}, {-9837778, 2527990, 4758344, 288519, -52472379, 1716431, -40267701, -21808582, 20704447, 9165943}, {-27558528, 1633938, 12095478, -3638629, -12376063, -11786771, -13580026, -10396607, 18139106, -6907116}}, + {{-20942300, 5288895, 16229812, 17290276, -21431368, 20894445, 9565998, -6703699, 1531117, -2716733}, {-42200530, -10464245, -17551450, -3224172, -6941756, -7526915, -49506544, 16138347, 29988743, -10203681}, {21142628, -9617101, -6798344, -12336852, -27439461, 14607255, 4827507, -7738199, 10888156, -11850843}} + }, + { + {{46442335, 20022981, -30174785, 1639361, 10908209, -15989410, 5883434, -9828987, -1342268, 8009605}, {19870337, 2137623, 31457303, 27150691, -36661303, -8047878, -20259582, -3473899, 30616924, -24381463}, {18884536, 6107716, -11768092, 3174545, -586100, -2552734, 7116535, 7778418, -11626304, -2320061}}, + {{5162076, 8030429, 20527820, 19052206, -16398563, -14931087, -5719020, -4303477, 14281076, -5514691}, {1715888, 14778911, 16583086, -5247974, -17403139, -14625025, 8168148, -7273509, -45753064, 3468687}, {-31998034, 5912797, 5381880, 2727614, 25852718, -11105864, 17721587, 9423814, -13913530, -5524258}}, + {{-12510292, 10558159, -54960122, 24194901, 23421792, 151806, -32597520, 30133382, 7071739, -20341567}, {29680924, 3605605, 9451608, 222173, 26833656, -25335820, 32494322, -979772, -27270479, 1146903}, {4227910, -8556105, 29479265, -5632632, -19995287, 11984129, 28326151, 10998690, -10999665, -717597}}, + {{34493157, -11459179, 11636869, 8222916, -22618221, 6526973, -12728656, 5088057, 9911920, -20256756}, {27537703, -12282099, 49626567, -229380, 6084025, -5156281, -15646540, 15368259, 3750196, 11875318}, {24873443, 2925400, -23926024, -10124859, 20453383, -6977954, -18933389, 6763057, -10825186, 4126459}}, + {{36484309, 9858199, -14454476, 2638398, -3973101, 13590454, 9296251, -447982, 47398700, 5497464}, {-27741289, 4777305, -33582564, -21758322, 54773125, 8843910, 19325083, 17636332, 1372052, 27106988}, {-31991681, 1193232, 29094172, 10252713, -7647724, -14588701, 12843696, -16151942, -23258064, 14243828}}, + {{-26316538, -4397665, -9106766, 6560489, -35540410, -5413324, 27757919, -3957618, 58253931, -10038267}, {15241974, -17355079, -16681030, 29171, -19551186, -6885608, -34766411, -23315986, -4968459, -2567355}, {22685865, -12865180, 11595686, -2115801, -15016214, 16721696, 33367997, 6993411, -7134246, 1287309}}, + {{4940959, 10255882, 22827773, 1050551, -13108547, -12542581, -9620993, -7105733, 7536868, 13015885}, {50033601, -17535378, -9884855, 26346557, -11906721, -17662525, 54356173, -13113075, 39890210, -1683557}, {-19387962, -7741720, 6697790, 16078299, 28696877, 5372129, -121762, -1120762, -7359916, 13971721}}, + {{-52447619, -7371581, 14542901, 6819160, -21375967, -4034422, 41076656, -3790396, -54001792, 8265953}, {6382427, -25826319, 23432797, -12740892, -33579331, -22041686, 1610560, -4106612, 930186, 2074871}, {-18646343, -3409491, 23427158, 15485903, -4577804, 11428084, -27871866, 9852304, -22329397, 384241}} + }, + { + {{22380193, -774208, 21177592, -9135097, -12430109, 15227152, -2091457, 4299381, 5285727, 12195441}, {17654285, 6758324, 31877792, -15536779, 43882115, -8603846, 62456331, -8223789, 56630889, 19626321}, {-2381007, -12555643, 32821184, 8760545, -14042905, 14417333, 16183366, 12199248, -25863146, 10648350}}, + {{20220081, -21581630, -18788235, -7356089, 15506206, 12511511, 16779346, -31746312, -29836998, 1581806}, {24956569, -6655186, 10990897, -7222177, 21123636, 19816493, -38245450, 697716, -9166186, 23184666}, {-4246751, 3261371, 14729629, 2041727, -18233351, 5192999, -9839070, -5946266, -15405468, 159061}}, + {{-9072937, -8909298, -22910847, -7238598, -30347664, -8961600, -3394074, -2568861, 1660466, 22542141}, {19368157, -9071034, -16352223, 2057668, 32937992, -12317132, -26418654, -14923613, -54167498, -5014341}, {-33187100, 8862843, 31013880, -2319269, -27771116, 14149783, 13009386, -12871355, 21345500, -10101248}}, + {{-3616740, 18307642, 18813789, -7488720, -774201, 853380, -5386311, 7683876, 27587359, -3296437}, {21380634, -13059198, -27783281, -21163482, 59302343, 17928486, -19508357, 22481818, -25233813, -15000511}, {6807416, 15503976, -2889202, 2342867, 15846120, 12482545, 29285683, 16765419, -31305936, -1578772}}, + {{-4437113, 26661900, -21096269, -2176040, -5177504, 17666790, -33248055, 12072430, -12604477, 14543344}, {-46735181, 3713100, 40958899, 5670766, -13443402, -1553320, -14158135, 2484436, 4569601, -9514196}, {-21813875, 14918538, 2763816, -10706009, 15620397, -9206867, -10288471, 6635873, -20366857, 8316067}}, + {{11441426, 12972742, -54071738, 23414172, -25591652, 1575021, 12645919, 11871072, 16112061, -14157153}, {8845736, -2674532, -11642612, -6956724, 18933990, 27663179, -37996041, 5689908, 27562457, -1329079}, {14001266, 4205919, 18709974, -5774580, -11201628, 16178451, 6093957, -5300086, -32187534, -15385905}}, + {{34997200, -26844355, 5907436, 221778, -15902142, 7448183, -37342831, 9466024, -2655079, 6593776}, {-29737398, 3876053, 8208376, 32952728, 14962142, 25197661, 20386991, 22638926, -45028933, 16459938}, {-31717996, 230725, 1915938, 1360014, 31922109, 2773834, -24697519, -72491, -32405369, 9504623}}, + {{47160139, -986585, 35161879, 17621132, 24998105, 12701886, 22519120, 14675719, -1385488, -16066358}, {1978165, 2663801, -30663103, -1179874, 14412471, -3351898, -39432286, -10893883, 36895920, 6196654}, {25771127, -13637847, -27697259, -13341976, -15772917, 6787999, 10241394, 13025730, -30853434, -5852331}} + }, + { + {{-10036944, -1178727, -54350809, 5762453, -35359980, 20916280, -40195417, 2111230, 10564190, -12460758}, {50100950, -24880685, -5896947, -5240283, 20836686, -7966896, -18105625, 15321160, -55233832, -16446196}, {13194994, 13360959, 1122733, -8329237, -2048617, 14809352, -7662514, -3064330, -32677874, -13712857}}, + {{-49416720, 26007386, 8911628, -11883083, 15918315, 21775197, 26799351, 3326989, -20778662, -4340840}, {-8613604, 1588042, -51972390, 1400871, 28236697, 9849093, 21231045, 19550623, -40267606, 19834536}, {20258676, 15794201, 3794787, -11921710, -25070311, 13635965, 23336626, 3428637, 26267934, 5059546}}, + {{45266555, 476391, -9428630, 19524463, 30098241, -17198725, 11410609, -16864615, -9829451, 17021686}, {6349499, 3802067, -524184, -6171585, -34279835, -6791947, 4351385, -6399333, -27592041, -14173394}, {20309102, -3527400, 6582513, 11881128, -20844031, 11697089, -10446543, 10376697, -2006210, -534397}}, + {{-8576479, -28049474, 15849114, -5944461, -55834690, -17308430, -3228531, -20220061, -6152375, -5881115}, {32113177, -3178742, -8800150, -9509109, 4174646, -8947340, 55116929, -8386317, 55302133, 2238051}, {-26181277, -4964839, -1641604, -12138242, 7401998, -16629768, -3832335, 16719729, -13044645, 9754033}}, + {{-29411565, 9635329, 13850390, -6916814, -37441870, 28492705, -33171881, -6669723, 60737155, -26451792}, {-19429731, -13881909, -34766134, 15380856, 16826408, -2552535, 16029129, -17345175, -3200145, 1033670}, {-28035038, -1199811, 16014261, 8163815, -23622951, 8331133, 2923740, 9634702, 28894924, 4005454}}, + {{47184039, 6885890, -39935156, -8159085, 39619139, 7241498, -18993360, 2281368, 16811900, 1749927}, {-4260141, 17484926, 11669026, -22713899, -13064847, -20599818, -20931716, 13517220, -25720518, 8811041}, {21774659, 286194, 2605428, 15962307, 6591658, 13085920, -27468990, -9189507, 22275785, 14139829}}, + {{7479565, -3942697, -15964766, 11314364, -26316534, 18837305, -15116415, 12881705, -8128062, 4717458}, {13503535, 21520361, -17031866, 2459288, 7075930, -9316021, 6913585, -16779315, -45429892, 2113414}, {32020547, -10540229, 11668446, -11578723, -16478716, -7961648, 24488273, 5250452, 16748276, 15880086}}, + {{-31433645, 12184154, 2862750, -5343990, -12296416, -1924057, -7816956, -8611828, -31569254, 1993397}, {22307675, -6130664, -26008624, -25704110, 44938842, 1475961, 3231360, 13106454, -3830980, -11546473}, {30443454, 13936992, -15314957, 11774100, -1951081, 5775511, -29535429, -5730092, -23137303, -14182245}} + }, + { + {{-12330803, 1143085, -32624931, -10751183, 20669126, 2776129, 267303, 27522394, 2325333, -5581150}, {42745701, 12837201, -9289373, -17923323, -10061932, -7082793, 48448417, 1886454, 42366673, -6564326}, {29644466, -10209851, -7696381, -2168964, 21680763, -15148007, -17534596, -1769759, -30632614, 5768687}}, + {{7457057, -8078131, -56306823, -4227591, -48285590, -10963522, -9493381, 12540517, -28610554, -13629656}, {13037701, -13157827, 10316191, 26452677, -15846010, 20467394, 38344655, 9672583, -27004432, 4785818}, {8915618, -2828481, -33309771, 13346242, 28357898, -12173265, 20492967, 711607, -2009724, 9308573}}, + {{-7658141, 4541601, -14839622, -13289209, -1699297, -11696381, 45936866, 23381502, -41063118, 6577904}, {20805365, -821979, 46076620, 14262441, 39869267, -7088223, 14243928, -9619942, 13243712, -6475322}, {-11838456, 13743429, -24834644, 257095, 10863556, 14209528, 25334969, 132943, -15278828, -9889544}}, + {{-30268002, -6165457, 34643735, 418570, 32951028, 5330868, 32344142, 3334065, 21296460, -9057932}, {-11969880, 847181, 14079977, -19809942, -7170664, -18947672, -11231422, 9306689, 2969482, 2550636}, {1449176, 4869547, 18336933, -3191085, -27767424, -7773488, 8997162, -11418487, -26372279, -9829096}}, + {{12082909, 4327811, -15961017, 29819219, -36191567, 17377959, -49308509, -6926541, -11612298, -372702}, {-41196689, -9987043, 22213559, 1613413, -27234283, -11588861, 16263433, 11421503, -23087420, 2151008}, {-12247082, 13631630, 28043816, -11947450, 12638460, -12782345, -11472468, -5636958, 8979710, 3596526}}, + {{-11009312, -5512300, 43850138, 30694300, 15579577, 3017073, 8031303, -6196057, -33385293, 26189167}, {-16376082, 9431638, 14720450, 44634, -6537145, 28864587, 32605347, -1505253, 4679871, 6435537}, {30018183, -6069455, -25725588, 743254, -16385537, -7878880, 11861000, -4338799, 23419142, -10520518}}, + {{40243971, -1341160, -29529293, -11171831, 18008168, 24820416, 35534712, 14118618, -46992849, -9439465}, {-26170575, 28489148, -4178205, -6932623, -523666, 4179118, 11620422, -251962, 15427577, -22090507}, {13657932, 15910284, 8978373, -4361060, -9718502, 5496408, -17699573, -577430, -2490610, 84652}}, + {{-31655697, 5877788, -1537102, 16982041, -58451201, -11430351, 35475010, -13519178, -16742258, -20584639}, {5297037, 14437542, -53952082, -7884927, 4306431, -5558257, -12149548, -3133052, -22262956, -593287}, {31169591, -11578699, 28435945, 6797090, -29588415, 14663912, 17434039, 2549174, -4630565, 6639184}} + }, + { + {{-16077699, -4871953, -17068088, -10604271, -13091755, -12191697, -5653585, 2444499, 12787652, -18664055}, {47496039, 11262291, -17960294, 16918239, -15116133, -6529245, 34601187, 10425601, -25901004, -2101747}, {14091554, 13940974, 9489758, -8458363, 32933998, -13957122, 33435792, 13929468, -27760484, 183561}}, + {{8240048, -21495785, 3348697, -15022023, -32237092, 7755881, -54284203, 12858872, 917532, -21576371}, {-41073382, 5890643, 4437149, 6758029, -5745246, 3556615, 5584519, -14119054, -11690882, 11146349}, {25886453, 3934974, 10725582, 544784, 30968282, 8197276, -21998269, 3990031, -27190165, 16370408}}, + {{-7962900, -5184139, 38404475, -9536744, 44161380, 9957181, -16526435, 4756329, 51547511, 9194889}, {26706586, 13056357, 515183, 13665754, 2334688, 9415641, -41899299, -15205537, -9485115, -8870681}, {27209742, 5390552, 7712247, 903017, -19722339, -2721273, 22707290, 15873800, -16041171, 7940656}}, + {{-38385245, -18970700, -9348812, 14996362, -5190427, 9722239, -13488902, 6746020, 10950281, -26543218}, {-21194087, 7627968, -40044192, 8571554, -24165097, 7566229, -48572974, 26517994, 30899149, 4017914}, {-9349453, 12011098, -19742503, -12383817, 29097452, 7811101, 13417314, -7894957, 14580221, -4092451}}, + {{-3160113, 12482369, -24884617, 1807399, -5489908, 10892782, -43722918, -19675386, 6934105, -24102004}, {-12244283, -3379461, 15381571, -9495467, 34352170, 14266294, 9566882, 2349204, 48496045, 7808884}, {-8436830, 8568202, -25205482, -6157173, -558641, 9520439, 31487547, 3265867, 17748893, -217261}}, + {{-22246624, 3541471, -16988801, 14038944, -10028097, 2854976, -8344494, -19399989, 2760371, 5157469}, {-35733864, -10396393, -23229601, -110182, -3209495, -352442, -13740102, -12455075, 52463675, -27628957}, {-10364393, -13698860, -14359281, 16388345, -11913002, -6429765, 13953751, -5758523, -5230703, 6103627}}, + {{4898350, -19574659, -24191410, 3168148, 7901310, -10187883, -45321764, 24638522, -31644266, 12497637}, {11574480, -3053415, -18259930, 7639208, 46578954, -7162045, -20607222, 3489230, -29154168, 20924959}, {-9274133, 16538460, -22829785, -14674045, 14354342, 3648609, -1407179, 10793178, 18168152, -3492942}}, + {{-4069522, 25031597, -14981410, 6217685, -21372347, -12211681, 18741794, 8407040, 32842200, -11062489}, {-35108682, -2939505, 36719574, 5040095, -44879755, 20849955, -12067896, 20752956, 14130366, 5176139}, {25154123, -13820491, -10490402, -2716227, 32896275, 8062637, -9065595, 16138075, -31346054, -1235067}} + }, + { + {{-24275686, 18585821, 60870376, 14695828, -35827449, 8922231, -15197593, -12084623, -10512611, -7885255}, {-7555556, -4456495, -1246332, 470002, 26469059, -4122555, 14000727, -8800995, 54755155, 24563641}, {23989392, -12342090, -25601619, -6862450, -16938891, -5179609, 9601924, 14488460, -27658088, 2804299}}, + {{-4093521, 21924647, -7682247, 4959658, 1074577, 4245873, -26266998, 6854880, 31529862, 23238557}, {-53995709, 909867, -47194201, 22232554, 32157413, 7508409, -37706860, 6134432, 29468104, -3269391}, {25743468, 7856445, -16487295, -3162068, 10094228, -13975139, 17163271, 2565920, -17508456, -6769045}}, + {{8650007, 15674276, -18719406, 6607069, 40509273, 5718999, -41941372, -17099507, 3481737, -11686756}, {-20601981, 10777586, 38296910, 1249629, 13715287, 22335501, -14510044, 10359233, 43001939, -9355462}, {-12935014, -8269153, -33527032, 8380729, 1859999, 2477818, -14778899, -4188028, 17150746, -575640}}, + {{-32652154, 14667869, 18517568, -19143560, 40484187, 15990714, 16281632, 9876087, 24550757, 2202907}, {-23428650, 15712725, 36821068, -9599364, 1881653, -1663938, -4562586, -17769171, -33014463, -13209263}, {-27129276, -9542608, 30921893, -10287936, 15166350, -9716832, 20830480, 15162498, 15631251, -14332645}}, + {{-20751106, 5664865, -22663193, -6291889, 4972690, 5395501, 13866143, -10918946, -33130404, -10187752}, {-4600188, 8325367, 37777479, -2943499, -30181984, 19249681, 27900745, -7650506, -24274346, 386940}, {-8127806, 10013726, 19146133, 1913608, -7044610, 14721699, 9485033, -1338415, -26578859, 4988210}}, + {{-20417441, 9343563, -52822506, 11642332, 29353193, -8334153, -27778308, -15959603, -10640422, 10736555}, {-39826465, -4659195, 1848736, -9595004, -16579109, -14898577, 17220948, -1806129, -3492958, -2687331}, {30341613, 15459851, -13654809, 13222522, -14798883, -6904613, -32408200, 6126396, -22535718, -7589584}}, + {{30160553, -28293430, 33932267, -5707758, -56132185, -4412706, -21869648, 11941975, 17572114, -8342403}, {-22790887, 532754, 24622353, 18017270, 9810403, 2013680, 34818586, -17072925, 18531420, 15441025}, {22209464, -1751800, -10958223, 12660076, -19237236, -15520139, 9479748, 14656075, -20272152, 7658749}}, + {{-7322772, 3421924, 33793374, -3666974, 28824200, -5615820, -55178202, -4124604, -61611521, 3886869}, {39029764, -2812128, 21418062, 20591602, -14784680, 6557610, -10977016, -13499450, -2107627, -10712343}, {-14542223, -1797166, 32221055, 14879140, 12441631, -918701, 29124516, -14719167, -24611598, -330993}} + }, + { + {{-14965935, -3081309, -245121, 23310995, -37786183, -1176708, 2787027, 8262215, 1509139, 1608445}, {-21095169, -8323977, -63526063, 364499, 26363617, -23743256, -13013389, 3360011, -13958441, -22506559}, {-27924233, -6322140, -3128444, 12134434, -16681588, -2944858, -5148397, 71764, 11969447, 7312666}}, + {{-21443993, 22782903, -32139077, -18735366, -38522465, -8049071, -33332368, 16085756, -53244646, -16248183}, {24229469, -3311245, -19141103, 14062650, 8503919, 1721089, -2169028, -6799618, -4679170, -1460303}, {8700676, -16776829, 1250533, -8747786, -33236237, -13798049, 31012017, -5647992, 551684, 14704598}}, + {{17206080, -15466406, -4104150, 1964600, -51768655, 14101752, -24768310, 3149284, 38150714, -1258159}, {24549480, -1156012, -13067086, 13001194, 14007553, -19031174, 22684294, 9474468, 4186074, 20947461}, {14477435, -14254425, 28912486, -8941225, -21344859, 4462146, -7741583, -7175021, 687135, -7379188}}, + {{-44923402, 19847908, -30053309, -14549245, -5827256, 12824549, -28543325, -367084, 26273433, 11121167}, {20297124, -12156998, 1365687, 5830819, 29493544, -13228363, -1008283, -12711536, -11571275, 11686193}, {-24252006, -4326029, 13973466, 10109813, 7811467, 753645, 32855840, 2859514, 11131016, -13636295}}, + {{27071989, 10045897, 13822425, 16758349, -38736123, 9315461, 2153745, 5935554, -27804304, 6829558}, {19423051, 14109257, 11976047, 1709289, -1243789, 4741937, -57935185, 8692824, 27294558, 2193626}, {13485706, 3691821, 105301, 13152145, 205473, -2967944, -20241208, -13270952, -32297397, 5755055}}, + {{-5148022, 16694606, -40604950, -15388679, -46160474, 22834965, -2735431, 5834358, -4660717, 2723537}, {-36947570, 12253142, -16705146, 6592167, -12454994, -4597087, -23373039, 10996596, -35413129, 12348191}, {16099257, -15770052, 28015466, 13188742, -24401191, 2670699, -12907784, 9264742, 2715512, 3053692}}, + {{-4131032, 14200387, 22623170, 16210391, -14552056, 21112595, -20542463, 9492499, -11633087, 28770205}, {-52038290, 2775533, 6141282, -5294329, 2228044, 10662545, 37773107, 17725543, -18574571, 1129745}, {27573577, -1130880, -16678767, -11811991, 9369649, 8193739, -30524832, 10571190, 10718862, 10266584}}, + {{-13670117, -11979452, -44425879, -23076654, -3394139, 20156689, 31003764, -4297210, -10514190, 922673}, {44935189, -1287278, 18038093, 1264440, -53737611, 10137807, 12357312, -5574926, 33325362, -21736471}, {-28673983, 11561639, 11492688, -14879231, -26686587, -10507978, -1603528, -909712, -10263694, -10833814}} + }, + { + {{-6149938, -15961306, 1768492, 464537, 4514197, -8106416, 4087271, -10806766, 31926516, 11666885}, {-8602796, 13102796, -50515890, -25075885, -7436747, 15700580, -21221355, 21152402, 13767024, -11516601}, {-12834353, -14483673, -4399756, -15054663, -24421122, 12979651, 22145289, -7770474, 22171576, 5852029}}, + {{20420150, -11251, 32140283, -13915662, 9857788, -2595421, -25180507, -11105261, 16204690, -3434549}, {-32933582, -29022755, 17005181, 16977288, 57238240, 24745383, 40775553, -5508543, 3886056, 849859}, {6260560, 1725159, -22979654, 3334386, 1140826, 7461970, -31250723, -16274746, 818393, 7223834}}, + {{16122180, -2590100, 15830006, 12470846, -32242752, 17882764, -43731753, 2016139, 23846925, -21194961}, {20595150, 18351586, -30857572, 12483282, -4265502, -5415720, -14204273, 3834831, -27131605, 7730115}, {-21268674, -5126381, 22669729, 682159, -17845187, 9434000, -8122140, -13106337, -30055656, -575262}}, + {{6057852, -4488437, -23620524, -13595276, -10014390, -4465270, 17914766, -17539515, 15832432, -18009279}, {-41056872, -28560503, 33713164, 4639408, -10214704, -27164382, -32959764, 10954725, 49291180, -9797843}, {13903039, 10264833, 26047182, -6049697, -14086595, -8600709, -31847535, 1979127, 6050181, 1229728}}, + {{22663958, 3726149, 12459368, -10055670, -18154295, 6317181, -9182952, 5137832, 23175783, -5649718}, {8890220, 17607059, 16937352, -20479804, -348713, 5899865, 3848004, 22683582, -21181741, -23858116}, {-290744, -14827929, 29582898, -12527855, 6972646, 16626318, 30074986, 9562086, 12403211, -4896385}}, + {{-41830917, 8299665, -41105872, 16067430, -26238463, -906604, -36731065, -3315165, 2130295, -25266504}, {15628125, -16014373, 11214306, -9289978, 3100347, 1551886, 16394107, 15090137, -38895607, -2893004}, {-31177646, -15086545, 12819661, 4629958, 20607739, 1417445, 20204874, -8143631, 20811174, 8518762}}, + {{43299800, 4499391, -26442195, 22280867, 46461525, 20625889, -48088816, 6430312, 13159232, 1015856}, {-23506606, 16687725, -7378951, 5714389, 1578501, -8614487, 7479424, -21963748, 47157850, -10790868}, {17562755, -3350576, 23344247, 13770084, -20073087, 1184377, -2100985, -14484858, 19129300, 6591827}}, + {{-26845075, -11467602, 359909, -9547177, 37150536, 5075840, -31408603, -25176716, 37260826, -11603837}, {18302961, 13877698, 626441, -4331645, -4532834, -27049826, -9924941, -1304610, 27766772, 5320093}, {-10309634, -5562757, -27818757, -5840693, 23391665, 14832354, -24191575, 3571749, -22604014, 16344263}} + }, + { + {{5667034, 3110145, 45307642, 111469, -41959155, 28411302, 28097759, 11969087, 26201392, -18879483}, {-33532914, -4500273, -2139366, 19129225, 8004819, -4052432, 3836053, -10914731, 13906386, -7857815}, {49033, 658065, -29504796, 13128215, -1115699, -311235, -6659448, -5038373, 19015182, 7348486}}, + {{29395281, -12451081, 3887739, 15810788, 13855073, -19507014, -30720696, -9882946, 6894461, 2660804}, {-10725239, 9629427, 19773977, 7943236, 6323723, -9389876, 26908968, -21261220, 38056121, -18588326}, {25319146, -11533696, -14394908, 7121539, 20648772, 1152642, -8619146, 9328209, -14006152, -14138888}}, + {{30696528, -21939260, -1237921, 4578424, -47496075, 23050600, -44875619, 7674648, 15546603, 11120728}, {24197946, -8612502, 53554049, 19661888, 11861785, 3224960, 14548947, -12334504, -16425089, 222962}, {-2916482, 10948319, -23783613, 6893699, 25672714, -5777322, -31406997, 4838666, 16885491, -1395114}}, + {{-46881, 12028884, 17537599, -14168942, -16520380, 3564052, 46562440, -1288918, 22873348, -9261105}, {-24004675, 9762552, 12601821, -16347460, 32073830, -21876332, -182850, 298066, -25359434, -21626415}, {22032182, 15941636, -16919076, -9460721, -6058805, -5072374, 10653706, -11915427, -8129074, 14722785}}, + {{28484005, 22460910, -39904683, 23000855, 9247363, 7189785, 4921919, 4669948, 11487196, -14003452}, {-34837687, -5344354, 14029235, -3843425, -11436283, -17620191, 2803721, 12119926, 43080540, 13633030}, {12818992, 1990998, -19799337, 7472472, 28152523, 15197231, -19926346, 5086113, -25075877, -8359309}}, + {{6593347, 18326428, 13447191, 17897168, -38147926, 15725373, -19113428, 5633255, 23729515, -11131937}, {27486785, -2612982, 17618139, 3843268, 25414244, 13954813, -26327014, -24901477, 14640489, 6891937}, {27811901, -5492966, -31953163, 13935272, 24193240, -9485637, -13227860, -11159819, -29264743, -6133141}}, + {{6645254, -1052051, 20064138, 1030104, -7071436, -18997732, -8485043, -2487473, -56198046, 373570}, {-44473388, 27493613, 45121738, 7627536, -42862996, 11089950, 38456561, -20721191, -5600602, -17638964}, {-30437631, -14994705, 8167759, 3272512, -3178985, -1695159, 9945417, -7474696, -9041240, -6680359}}, + {{4387973, -29674349, -26528441, -4332124, -25986678, 1714648, -7371503, -20084181, -7000771, 4527817}, {-44675847, -321177, 16948867, -415160, -2018198, 25795942, -51361817, -2070277, 129285, -25800947}, {22859435, -14313065, 3135184, -10905638, 21609405, 12214462, -1396273, -5378204, 28665183, -2126652}} + }, + { + {{-18011698, -5063501, -31026256, -20550845, 20119567, 859468, 29070010, -14692563, 31324961, -19315826}, {46842698, 25940563, 24327998, -3082235, -38182885, 17900270, -12885390, -17527613, -25484381, 1950248}, {-11983217, -14230420, -2879362, -5460886, -23179949, -11862385, 17931235, 13352494, 31137456, -15910046}}, + {{41022720, 1610062, 12973782, 17643810, -15715632, 11732337, 44313118, 5264056, -31936223, 3554519}, {3211768, 12354914, 26573118, -5566922, -37980604, -18836117, -2589274, -13311556, -28919299, 10768447}, {30557421, 10566275, -26330181, 7995848, -32787174, -8705350, 27019213, -2178187, 15593423, 1784678}}, + {{-17257830, 18961672, 50137922, 10645555, 17524948, -16102471, 36916900, -931346, -19350137, 17768272}, {36527660, 11801834, 11968934, 21796761, -22693258, 7914073, -29833324, 26912302, -33189891, -7955698}, {-19039808, -110184, -28803828, -1230840, -18703781, -14008297, -26794668, 1143570, -23155542, 15437117}}, + {{51350209, 12414086, 27472212, -3239756, 17621156, -10558139, 17572042, -4905421, 26041862, 4614489}, {3572225, 20592798, 4667818, 3845230, 49249474, -21420153, -14608222, -8963765, 8529154, -25652601}, {10022776, 13962768, -30719547, -8457969, 19210702, 7845647, -21708846, -16259458, -20884794, -318869}}, + {{9853927, 22545275, 13442128, -715853, -12193242, 3360537, 668424, 114894, -47779478, 690575}, {35761327, 2888407, -6674526, 21791631, 17296064, -6706781, 7100850, -1716614, -15467376, 14441175}, {-20880846, 1640137, 8361119, -9935676, -5078191, 14778108, 31889895, -548689, -16026862, -6658382}}, + {{-438480, -15961773, -18926622, -16667001, -43786490, -20224863, -613173, 12627717, 7941167, -8073057}, {-4832616, -11106537, 20841592, -16634581, -23029168, -4610139, 54636179, 7848931, -20219417, 7143829}, {22719107, 7504236, -16790409, 7984459, -21347693, 8991284, -32685915, 4873930, 25465096, 7828544}}, + {{-30691440, 21600727, 31949287, -13371278, 24292080, -3065150, 1099478, -1633043, -1911830, -8578389}, {-26703780, 8805787, 34585069, 823450, -38984890, 10371950, 34294052, -19915649, 37687642, 10720017}, {-25149299, 9814017, -28086450, 12105687, -16690193, 9638489, -15255343, 15039521, 20758484, 6261619}}, + {{10945487, 31750512, 45774032, -15500045, 26895933, -14090736, -42934621, 2842170, 3229426, 4821889}, {-46821711, -656442, 18864572, -16206047, -18907973, -7850188, -2027387, -26397778, -235658, 16963859}, {22728565, 13531960, -2521144, 9106743, -29535885, -8266896, -7275023, 7237440, -32749614, -12062037}} + }, + { + {{30482783, -3539076, -23942491, -297735, -11891225, -12001003, 6069179, -7583453, -12755578, 14180918}, {30721073, 24740612, 43149017, -30877415, 23245533, -21026127, 9138229, 16567983, -43054972, -1237428}, {-30864606, -6692250, 25015085, -4987651, -1944488, 6711292, -20348234, -10165779, 15756892, -13134734}}, + {{10509489, -4286251, 7919515, 11261265, 28731723, 26136429, 13612912, -5737581, -41040271, 11759714}, {-22296989, -5919281, -15353709, 5754431, -21361663, 3562559, -22524816, 23962997, -19056343, -18025024}, {15807643, -5550548, -15869403, 7383156, 3061642, -11234173, -10104923, 8171991, 22248078, -2727994}}, + {{27675369, 4851060, 4741427, -5026636, 19612669, 14390933, 42667451, -11194815, 14804093, -6272893}, {26705347, 2425322, 58908121, 8861092, 43125183, 18606705, -17338799, -19388335, -12520343, -7251899}, {-28704869, -13418046, 21431753, -8147678, -12087642, -15798041, 27640372, 6183513, 21762596, 11909994}}, + {{-15451744, 2499700, 16217268, -28485189, 3107559, 493576, 25525023, 1822124, -14173125, -4507514}, {40630266, -13774118, -39289082, -895353, -20824855, -15175954, -30162801, -7364676, -26250633, 13328314}, {15145853, -11579062, -394678, 4704532, -8014559, -6492526, 24862101, 15666460, 29187210, 12572565}}, + {{1629152, 6190082, 45187641, -32064692, 30775207, 522837, -1094740, -14386624, 33279326, -2184058}, {46114518, 25619656, -8239841, -1322844, 34175415, -14728257, -38914900, -13105064, -25912890, -20408364}, {-15427277, -5159064, 10281448, -4151178, 6461960, 4532643, -28316554, -10346390, -17885321, -16621647}}, + {{-18098727, 21490993, 8828669, 3621981, 3409449, -5319823, -35024428, 1120257, 4810083, 4262176}, {-11164139, -3491169, -44840937, -16704381, -57133421, -25118167, 26480158, 9437685, -50746805, -27165434}, {5178459, 16025867, -14614723, 10765661, 22852478, -11145040, 13115158, 14463292, -28661535, -4645029}}, + {{25283403, -4672726, -39248911, 10074524, -16226424, -7632015, -28015953, -17555553, -12099627, 30431328}, {62631, 26935122, 20407295, -19914460, 37379362, -21135943, 15346477, 12287, 16467143, -2386890}, {-24984543, 1212989, -18812296, -12854467, -32751934, -12150034, 25928171, 9785034, 7255938, -6074826}}, + {{7561277, -20717156, -2547310, -1029649, -2934258, -19157902, 21993495, 14254246, -18848869, -659100}, {22198685, 3107960, 26691326, 17685985, 18675126, 3830928, 40920207, 12494954, 21660857, -21876054}, {15931175, -4834752, 30548740, 3478497, -2669521, 2031616, 27165788, -14460204, -942591, 13205301}} + }, + { + {{-18350282, -5619521, -8234683, -9762916, -42055665, 16320474, 45168308, 1046861, 54081539, 13127149}, {46411488, -17634349, 40229697, -16189708, -12386523, 12914066, 21475766, -17128257, 783853, -2426865}, {4299199, 7744759, -7398198, 10474049, -19935309, 4413921, 1577092, 7155308, 17005665, 1950406}}, + {{-17235550, 2043974, 23962594, 7694883, 23100954, -29480529, -1290117, 8617518, -33291876, 1334190}, {-5441980, 17904384, -8835576, -2050723, 43129574, 2867735, 630489, -7868152, 29980310, 16300766}, {13119730, 207127, 13045935, 3238455, 2716542, 14996271, -17781201, 13970902, -8285479, 12468570}}, + {{-18737276, -21712206, -10242020, -16433787, -23227637, 16909084, 2096647, -69131, 490867, -14532578}, {47329756, 5218862, 48135750, 979645, -32716241, -9936788, 32880437, -18102927, 32301071, -1369640}, {5426848, -7729229, -18699514, -3504234, 11025601, -14892042, -5497164, 11797418, -23599077, 16331942}}, + {{39120913, 16671342, -40082554, 22347792, -30010638, -5265514, 1105400, -4705441, -63405855, -23333449}, {-13605823, 16738302, 21559630, -2334802, 19932948, 1971060, -53824754, -17477431, -3307517, 561979}, {-4683345, -7111455, 13021905, -1857981, 631462, -15159045, 16144015, 4901744, 30386625, -14652465}}, + {{48283255, -4991022, 49978208, -1643748, -45802983, 6398831, -2235508, 841836, 5810239, 25467582}, {-10670207, 23197216, -14641170, 22872208, -9742231, -20895951, -10733158, 21627860, 48036693, 2649458}, {7599460, -10891376, -4606550, -15658616, -1426138, -15450732, 4104883, -3864178, 19275178, -2766225}}, + {{38594964, 24713096, -1326729, 20661522, 32699719, 754655, 5443278, 13882987, -2613139, 19434704}, {-1316990, -2382558, 56427605, -5337956, 3930105, 16167605, 46272614, 1224397, 12167819, -360918}, {-25858707, 6075614, -22004506, 5602028, -32925455, 16083954, -8775562, 14421937, 20652995, -4990991}}, + {{-6680391, 11712996, 10728491, -1974281, -13260636, -21936740, 56420748, -8738739, 51316031, 15672840}, {9249689, -21554752, -14874459, -21437743, -26642762, -3432764, 10138360, 3195837, -12009137, -6648442}, {-15322474, -4099943, 25577032, 15010949, -18087753, 10148193, 21753308, -11381978, 24920941, -7186311}}, + {{778269, -30002764, -23597417, 9665291, -17938686, -7982645, -54487477, -24226484, 21814226, 554352}, {21828057, -1849718, -31960819, -10325739, 5781770, 15532819, 6642763, 8996044, -20350134, 4440702}, {29685405, 14062662, 28060298, -10696777, 1067072, 2961430, 28536687, 11005956, -24196142, -11160858}} + }, + { + {{-1960230, 23384140, 25862295, 2487283, 24565203, -11566964, 16357212, 10174710, -15523768, -9632117}, {10934880, -3904758, 16198345, -16389711, -1820413, 3951654, -7454192, -1046894, -11582432, -6681729}, {21581929, 10652514, -10887288, 7104048, -3270509, 14460920, 33218460, 4694233, 12517854, 10563185}}, + {{19519888, 7001121, -21999039, -10183106, -37087520, 18834209, 51765895, 9169380, -11564825, 23286409}, {18186536, -2644655, 21046655, 7571250, 4701532, -5563359, 3037945, -10322148, 33132687, -7146329}, {2371774, 11054652, 19080617, 2645559, 7570559, -11152672, -9834565, 9658888, 32535339, -9449345}}, + {{7621256, 2684922, 5897826, -15112285, 11070292, 3659897, 29965078, -4313522, -5548401, 3821808}, {-22759400, 17898744, -37187452, -17052659, 52956104, -21841639, 14927064, 25406264, -26783977, -26089530}, {11707971, 15804502, 23574353, -9450473, 7900408, 11983346, -14547413, 16327592, 7576102, -9085228}}, + {{-43366442, 9466902, 30806326, -19917973, -6276039, -24350125, -28887713, -13791380, -28345333, 7970465}, {-7593872, 13748626, -31160462, 8417081, 42185535, 417631, -14366197, 19563846, 9004619, 6784321}, {-24101968, 12368798, -13781516, -16623087, 10246168, 15483707, 32125145, -14810169, 1098411, 5465506}}, + {{-920815, -22392489, 12909046, 6145976, -14623780, -2271277, 5354014, 794203, 43045970, 5646107}, {13237005, -2179149, -50569872, 4691402, -50286604, 13989483, -37929608, 29766037, 13219852, 25219789}, {2029608, -14065469, -9384689, -16016330, 33190562, 6932606, 1894474, 7081878, -20098687, 7522690}}, + {{7561297, 13475462, 9683655, -11932233, -33714519, -20151657, 48694304, -5310808, -14862524, 11549813}, {-59534903, -5433644, -29610315, 20282723, 20601553, 9113655, -4113074, 15543460, 52069186, 2186895}, {-8558987, -10176903, -12755947, 13933707, 33193566, 8321460, 32668838, 6060337, -2701190, 4580815}}, + {{28449931, 13840790, 33312251, 15968595, -6516946, -9754255, -24219314, 7029229, 19250679, -8573402}, {15096671, 17289750, 21866487, -12451447, -50646082, -13109745, 28431952, -20467117, -24746153, 24528604}, {15883515, -7979703, 27231058, -7568473, -32194874, 11833960, -8031188, -13404985, -2483088, -16137831}}, + {{-37832548, 10481771, -40705740, 19417582, -55863352, -10191875, -1332104, 9320409, -20192947, -3462890}, {-23850414, 12895457, -5589606, 5202172, 8659872, 1340527, -44084058, -22316099, -6211459, 26238566}, {-9596629, -2883564, 27026337, 1157428, -13587089, -5093462, 15162268, 402608, 16314011, -14651535}} + }, + { + {{-36135171, 11259808, -25530423, 5341468, 51244599, -7149697, 63840467, -9761334, 19732234, -15414661}, {-19359895, -16780024, -1969181, 11977098, -4578147, 24513805, 1463611, -20135458, 36217632, 4393131}, {-11515840, -8672379, -1713217, -15073795, 32896088, -12749816, -15691954, 11592582, -15644828, -15653665}}, + {{14537560, 22130269, 25043355, -9942622, -22443820, 24863387, -47799392, 13123752, 41947168, -16017278}, {8009582, 4519273, 5235533, -7886720, -3739236, 3007753, 10574782, -11111888, 3890018, -3386556}, {1659623, -13918385, 13470461, -7613812, 28961651, 9155334, -13337505, -1860546, -28882595, 13106224}}, + {{-2116528, 593689, -6641219, 13026571, 48371289, -1372172, 33202749, -24445354, -23083499, 21634585}, {17219676, -13844639, 53144625, 5568191, 2848929, 5952392, -1650167, -3332656, 9154385, 6702789}, {21183607, -4797073, -27278343, 4414871, 6723493, -9194010, 9421562, 1606691, 29257493, 13759966}}, + {{-29474321, -2239497, 11623396, 3370949, -34197780, -22480710, -11417658, 4928430, 4199123, 6857854}, {28582967, -22634531, -50526380, -1367097, -6990186, -60708, 12171334, -23300052, -45432383, 1794804}, {-2846841, -7698790, 2182683, 13145669, 9501697, -8960002, -18626018, -2170049, -8934859, -3556362}}, + {{54522402, -4478858, -8553426, 9570135, 42166565, -7773550, -4433461, 619275, 18596151, 1458808}, {-5514982, 25148834, -1734684, 13282685, 15525379, -1772338, -24316051, 22690161, 36622989, -24651808}, {25933792, 2510086, 15910471, 352613, 602345, -9541031, 4380882, -2225183, 3955267, 13899102}}, + {{4767909, 5272007, -24767547, -6607470, 8287496, 6705266, -5347953, 1901015, -11719540, -13675335}, {35080973, 4774855, 13568349, -14819810, 28893436, 12696204, 16811065, -4986345, 44531286, -16499265}, {2443435, -2512829, -4490328, 11644891, -14506109, 6558854, 17510163, 10479708, -32590283, 12330004}}, + {{43473308, -12001478, 32016830, -614281, 24112591, 17632411, 6576306, 10271114, -38111023, -19592756}, {2543494, -21478956, -30483992, -10032857, 7451625, 15909227, -35959828, 10320124, -2144921, -10511270}, {-7411430, -16205342, -25795665, -10674243, 27566078, -8778753, -15754606, 3126350, 24016607, -1285213}}, + {{1738947, -10453884, 40017859, -12344387, 23773558, 5728318, -17836723, 9336201, -22970850, 9770553}, {26295865, 19975784, -5978717, 9785393, 24103472, -95302, 42077713, 13385687, -32352546, 17883427}, {-996798, 4882062, -18645127, -2741650, -29074528, -12880499, 872224, 5725399, 26953514, -11662986}} + }, + { + {{-9711242, -24660091, 59831857, -21652521, 15211448, 9312754, 18707334, -14377756, -3062343, 14039577}, {1292530, 1655795, 3211629, 8144685, 41076934, 5044874, -30632694, 13820848, -2370347, 4571575}, {-4974507, -8855215, 3089378, 2530286, 29830871, 11782247, -11656043, 10373949, -17868864, 16621802}}, + {{-39813536, -10061740, 30826340, -3327110, 6725751, 6917096, 35772528, -10465914, -39545236, 18727027}, {-17155820, -13507634, -17858902, 20180914, -37366597, 19842038, 20595746, 6523388, 7913018, 9397053}, {-20471037, 14568028, -22463044, 10145497, -16723180, 136904, 14480426, 6773671, 20326999, -6554507}}, + {{-59830341, 2092949, 3994365, -17640894, 8912261, 5276749, 24926789, -8156981, 33387707, 7191425}, {4435973, -4893179, -11029997, -8314012, -18881965, 5210479, -7410961, -4190643, 12399979, 8378737}, {4909514, 9037026, 28322279, -4629659, 7427235, 7911101, 27358016, -11229910, 17630020, 16164682}}, + {{-33621441, 19982083, -12353033, 14697763, -7381971, 3683295, -31704847, -5884532, -27535721, 6007835}, {17428919, 771973, 10044567, -18191603, -40782297, -21458847, -26640533, -9887798, -16680171, -7893351}, {-28280845, 11038172, 11085797, 13174912, -22954779, 5160137, -19346379, 11993405, -26479407, -2496915}}, + {{1173857, 3376591, 6511072, 7569659, 21466328, 15094784, -15462495, 14145091, -52072721, -2578544}, {-64929667, 28502485, -23923394, -11691121, -17221158, 6238148, 19353821, 3934377, 1550073, -15201318}, {-13156709, -7502305, -21476389, -4490502, -31855871, 10535120, 25439814, -16493932, 6539442, 6881101}}, + {{-118439, 29845467, 36942582, -11151420, 6588690, 4394329, 2061200, 13783949, 60082727, -14717446}, {-9792313, 1367985, -12181622, 2760900, -58967280, 9287283, -36938834, -18486015, 4902125, 16588036}, {-10594679, -14333565, -15237274, -15466125, 31306228, -12355905, 33459482, 8376869, 1805838, -10636182}}, + {{-5402617, 8202912, 2614200, -1215083, 4909674, 8426721, 16627746, -7800962, 5889648, 10152491}, {-3357145, 12424868, 474376, -7067429, 33874198, -16022437, 7759044, 18647886, 8971522, -19406233}, {-113444, -8901869, 22380116, -14825561, -4587246, 2442182, 9442227, -15475265, -12931590, -2531570}}, + {{39455221, -17126481, -16114848, -19641602, -35269429, 6134274, -4332956, 18052281, 23881726, 22752985}, {10075009, -14133513, -70074, -4495914, 7127711, 11438088, -43286674, -10172341, -27365908, -8220659}, {-2213774, 13962815, 32148126, -1294400, -31447847, 10080428, 18320844, -4531750, -26355477, -14297565}} + }, + { + {{-16773618, 11671353, -38055315, -10609511, -20057542, -82628, 10556781, 5300747, 44864962, -5187281}, {-16959332, 5420905, 25578389, -14214587, 12377448, 7465890, 35488287, 7377241, 2090208, -13546075}, {19313172, 4721754, 13231764, -9675570, 8383079, 6549129, 4002446, -10733162, -25554889, -14124383}}, + {{8766721, -10955055, -43972707, -18787085, -1900352, -9389696, -42332159, -2881433, -14737616, -3003390}, {55793339, -20837847, 1426025, -1402585, -38754332, 837696, 10954951, -4043921, -37626704, 6556416}, {24887701, 9060370, -23932321, -662244, 17477317, -552784, -3260861, -11716013, 15903339, 12126795}}, + {{-16792389, -17397915, 19086054, 3059062, -614429, -10203097, 46495463, 27650286, -12917216, 3891207}, {-34626601, 8812771, 23936322, -20226460, 28778113, -963629, -9092873, 3607930, 37642812, 22376149}, {-27632297, 4099588, 23211695, 9938769, -21033406, -4384137, 15561628, -10787186, -19135346, 9226417}}, + {{28879676, -16184395, -35430707, 20791088, -35325001, -22235887, -31366089, -23834864, -16207179, -914140}, {19440300, -16850569, -1790509, 7951042, -26781441, 9548561, -21876537, 7401572, -44116137, -21811396}, {-2758864, -6388640, 1437790, 10895317, 12714152, -4387256, 5570406, -1031995, 29221173, -15700913}}, + {{-25511264, 2380837, -9853237, 17781, 26557435, -1375633, 31271014, 15524874, 19340405, -6384995}, {6092904, -3703557, -36351135, 22861469, -38332685, 7774917, 8614466, 14723234, 11995975, 4538483}, {12045260, -16075550, -14354085, -14066581, -14168970, 15666235, 32956483, -8210523, -11701257, -13603519}}, + {{-2366110, 1744000, 56461338, -28210195, -13005109, 15757820, -10870938, -28957444, -28578903, -5070408}, {-30926166, -26255906, 7571906, 4406307, -22899045, -13885376, 29440830, -4573846, 13822435, -25913082}, {-14203080, -5954298, 7200620, -3278961, 26188220, 16237208, -20362366, -9464074, 497469, 186838}}, + {{-25907110, 12248204, 28314799, -8145142, 38539069, -339459, -4763841, 12565494, -44711413, -11043585}, {-674158, -7845814, -37702427, 3204772, -25815477, -13360609, -50403183, -19645970, -6709805, 14756549}, {22161928, -3849992, 25683298, -508470, 3832006, -14880064, -19607207, 11690942, -4059446, 96424}}, + {{-2761540, -11437055, -50520011, -17700545, 21023811, 3766059, -9164893, 14538903, 37227749, -5246687}, {-31060750, -20824373, -6723857, 5115157, -5476521, -21382943, 38940813, 15938569, 3712347, 6069957}, {-25479380, 14778084, -16964379, -7972310, 23719456, 12440670, -20307049, 1027289, -31317021, 8723370}} + } + }; + const precomp_data_t c_point_H2_precomp_data = { + { + {{23610453, -10197163, 10334660, -1046801, 28262922, 23750756, 37087102, -21947201, -6803415, 4692852}, {-1734415, -16841411, 48353496, -3092747, 32326978, -4115300, -20574968, -6369407, -10503341, -17594610}, {-1247968, 15942191, -32202222, -1358983, 7143418, 15927757, -9352400, 12396253, -14973030, -6368958}}, + {{17755505, 12894802, -23987473, -3257850, 23634369, -26289278, -12209287, -14935238, -40028276, -30983511}, {8875627, 10858572, -11862557, 7456586, -28151737, 1241520, 41063381, 17507356, -1328068, 1514689}, {-25303051, 8258917, 28704031, -2421967, -4727799, 10997196, -1644525, -6151933, -5563523, 9799204}}, + {{47118159, -6637357, 26730232, -12431766, 12075361, 4565753, -888637, 22837710, 3493396, 7848575}, {-9148317, -16884047, -5737366, -16771976, 22811149, -7473475, -711611, -575766, -44156924, 8544179}, {-25893401, -16528654, 13141632, 6865639, 32051656, 15250249, 20843742, 13316750, -10857994, 11925667}}, + {{-32759985, -10673291, 10628477, 8303284, 664857, -6606738, 19296263, 13409361, 7612818, 18982889}, {-5304683, 2445705, 26290523, 20839266, 59572603, 26944470, 32618913, 13063829, 39274036, 7682265}, {26372079, 8750710, 21277144, 8989302, -23975261, -2391322, -2944708, 4030089, 32409876, 5341227}}, + {{45100691, -585597, 6765334, 24838367, 664798, -6723481, 12077649, -1093433, -40798545, -1026535}, {-21550983, 16062439, 44583522, -7009965, -64485034, -12832191, -10275177, 12338273, -17766243, -29085867}, {13385028, -4890080, -16855119, 3670999, -26654461, 13818535, 12976988, -3624089, -16290439, -14486598}}, + {{-60319207, 8986121, -40021847, 5055134, 6153569, -7297941, -1857158, 3303310, -2125776, 20377154}, {-3731461, -692441, -21494781, 3381506, 25219331, -25180023, -43792600, 8781696, -17190212, -11590964}, {-20685896, 6277532, 13239062, 8809213, -18620912, -12835415, 18186334, -16146762, 11884264, 11853646}}, + {{28956819, -15792195, -28723537, -7543141, 45151417, 25200898, -15652788, 10947254, 3013145, -10215920}, {2261865, 16437773, 4187195, -10935411, -6457075, 2013660, -26005186, -21934994, 14612669, -19171662}, {-18829066, 7839851, 26058003, -4333209, 1671208, 1627868, 25442175, -2385068, 23451972, 15535658}}, + {{-22395440, -28910877, 46940867, 5692433, -12502626, 5452727, -8254590, -4458344, 30749193, -31534208}, {-22507698, 3969289, -17709601, -24109049, -43218660, -20798999, -22153068, 26773432, -32174549, -2004442}, {-3156810, -3452724, 30798060, 14916829, -32623602, 3219559, 5772241, 4373987, -2681269, 11704334}} + }, + { + {{-20034677, 2793757, -5691269, 28918384, -14931901, -20588194, -24026474, 29121661, -54093011, -15214214}, {3026193, 26729439, -24010413, -3113416, -10464013, -6452146, 4859500, 3776949, 12234675, 3897924}, {-1505758, 5331777, 15179416, -4976123, -12323937, 14423591, 4389319, 16297479, -33410831, 8103492}}, + {{-9153308, -11509288, 21368648, 9775977, 27399820, 3559009, 13234285, -1909513, 30787262, 3594378}, {16898018, -20899144, 36682048, 23243173, -8952002, -18570919, 28378567, 13160573, 6930692, -3150740}, {4792947, -511449, -26657424, 6462286, 24205795, 14794771, 22985471, -15149066, 7853377, -4303746}}, + {{-9576682, 8963562, 28696180, -20127107, -1935288, 4589286, -19692690, -3502380, -9934955, -2507743}, {-3653422, 8614208, -21531954, 11016347, -16387132, -19439856, -14752834, 13096524, -56781185, 20263515}, {9294991, 10631362, 22058885, -1571357, -5979351, -13170753, -21183311, 13139231, -18133908, 7769266}}, + {{1647299, -12472224, 28451628, 8668059, 4354749, -5585797, -50797202, 22282046, 21735112, -16569680}, {5591193, -8806398, -5947156, 24329437, -416857, -13730775, -2512106, 5973498, -21575118, -11647074}, {9696406, 2894616, 25648801, -7312874, 29635185, 11722015, 32019359, 2832667, 30313601, -16766676}}, + {{-34826610, -19473647, 24116279, 7662284, -43276419, -24819955, 3799955, 1815731, 33681656, -18659056}, {-12723970, -9318793, -39583641, -23887066, 20837261, -3968337, 35095995, -22863895, -23767900, -3307210}, {-33339234, 14758149, 2538384, 7778526, 13724029, 3532965, 17108365, -5456741, 6907760, -15909473}}, + {{-55816078, 19897571, 30916593, 7325727, -44301640, -9135525, -15643364, 26326651, -25751547, -5212259}, {-3523370, -9790613, 17183517, 1896533, -11635272, -1128603, -14554190, -3209249, 34771801, -4394401}, {6232369, 8354610, -5737998, 4577123, -26334194, 3109061, -27891834, -5423878, 25514483, -5913640}}, + {{15262452, -13072717, -51172700, 13571264, -29880994, 811995, 57944293, 10157809, 14691660, 888388}, {-12416476, 3735271, -15304116, 3961668, 14065192, 4842113, -266359, -2450965, 9643760, 9706648}, {6951241, -6052340, 27448200, -14365454, 16633820, -5275760, 30785445, -2103785, 32220672, -6886415}}, + {{3684964, -151508, 38066858, -7037875, -7616828, -1318260, 43061286, -11775969, -14052688, -17567087}, {-58732772, -5421540, -11708264, 7604465, -45808494, -4083228, 12277976, -11339615, -38187456, 11811679}, {11730541, 12744338, -9733274, 11669097, 33458593, -2195273, -19395831, -148040, 23800597, 1650782}} + }, + { + {{-14724575, 16440443, 40350416, -8279882, -35573071, 7084425, 451753, -17313479, -50101344, 4266775}, {-4225159, -10252219, 5501110, 23915638, -10438293, -15550817, 24867535, -303761, 9986890, -565121}, {15055785, -7923531, -16528133, 7731362, -7871094, -8117118, 30990862, 3476810, 9308229, -4614296}}, + {{-14758431, 10283514, -10922843, 11048915, 3112425, -28350336, 11944016, -8853544, -21585011, -22485275}, {-51897993, 18055446, -9364401, -5902927, -19289541, -1689070, 16791058, 14821558, -43781863, 986017}, {-13009087, 3656388, -31387104, 8741572, 1463959, -10222543, 5579290, -4018764, -123630, -5698414}}, + {{29239628, 15999601, -44683953, -23930934, -356731, 19107160, -14719351, 9381990, -14022131, -6489065}, {-21162206, 2088333, 4811881, 9121716, -34781453, -2549986, -1013783, -4798106, -40421789, -17316661}, {13518436, 6993028, -1095696, 732379, 21246838, 15962915, 23545992, 15403408, 32083560, 16276410}}, + {{42486736, -27947783, 9089008, 10694575, 59611971, -13152397, 2435517, -650430, 14352885, 24168703}, {-14744714, 3107667, -37941256, -18227197, -3528033, -14420201, 8000625, 25165456, -17518187, -721787}, {30523716, -14312839, -19753346, -7689847, -25619183, 6368165, -22087608, -550760, 17487950, -6279928}}, + {{-7244498, 11793136, 3847324, 19090337, 14092544, -3608956, -38845618, -15066943, 35138832, 24621170}, {30542, 1693362, 9921686, 13916893, -7950056, -607080, 5802106, -2283435, -3376992, -5348992}, {-20489093, -2004226, -9859271, -11433986, -11545872, -7116294, 30480536, -79605, 31739411, -5587724}}, + {{-1872218, -3126679, -15306611, -9292298, 11030547, 12550324, -43456217, 20418278, 19844162, 7125039}, {-61827536, 22194559, -34266869, -2253800, 27189767, -16858506, -10290747, 13116026, -11735076, 6308189}, {-19331921, 4286924, -1617640, 3931267, -5659779, 10011539, -2539694, -10684967, -4855502, -14338144}}, + {{38000273, -7875032, 42447977, -7683284, 25708997, -13116905, 41126314, 1998099, -12251179, 5595177}, {-9881583, -23698148, 13855457, -8140698, -19434201, 8802445, -23028134, 24094513, -5058417, 17557159}, {-5432625, 10619389, -1308206, 12691920, 30959143, -3607328, -29980221, 10685818, 29350398, 11537191}}, + {{37371343, 14877476, 24709379, -13411181, -7503542, 16045099, -234750, -25932520, 32292539, -6688909}, {-22892931, 742678, -4377969, -8093901, 53452490, 4648829, -1867326, -1549360, -20583917, -22696067}, {29333999, 7104917, -10169373, 9695952, 596892, -2655631, -14926444, 2273427, 21336726, 15631847}} + }, + { + {{26133029, 2893146, -20026194, 8306573, -10666150, -814324, 6118993, -10519093, 5970690, 8767152}, {19007521, 13339434, 32875070, -19497763, 27640618, -16157802, 60591895, -21332445, 32404752, 1139816}, {-6126462, -6789887, -15511621, -12520897, 29701063, -4199950, 28091989, 9448981, -20857463, 12863811}}, + {{-4199478, -21754692, -8722132, 20445470, 11560923, -10625363, 14609823, -6628736, 1477710, 5551610}, {-35924504, 8857454, -45032362, 6093000, 30214809, 13389775, -10317951, -15798260, -64478240, -3200926}, {-32078097, 15549780, -13918853, 11740353, 29202268, 6788459, 9231245, 7114353, -3093924, -8875636}}, + {{7477389, 7157155, 46869714, -6967000, -7002432, 15122711, -39373689, -14013504, -44871181, 17315277}, {-898231, 7522291, 14050152, -25568922, 31498166, -6650291, -16407583, 16414650, 20191187, -1335191}, {-22727631, 10386983, -31350889, 6626608, -27024239, -11960121, 21613613, 2101958, -20208160, -14994732}}, + {{-29256113, 4991897, 42170171, -17575198, -34268742, -19587473, 11853891, 16079871, 37173516, -4874019}, {33696909, -19392621, -1993615, 4521016, 4320412, 9646943, 30780215, 11031437, 18241268, 24349241}, {-28171680, -12112427, -662507, -12174971, 32810403, 11566509, 13301937, -10196786, 1981075, 14435433}}, + {{-30887427, 3188726, 23346623, 18238828, -25157860, -1696761, 16314340, -3618957, 15158432, 31818780}, {-31224553, 16165424, 8993117, 9849222, -427432, -18389513, 50021340, -10329597, -12602608, -547904}, {14136086, 16168803, -1149795, 2836927, -21464573, 7236755, 13571289, 7213996, -9632949, 11894669}}, + {{26307181, -2068672, 41764199, -5290138, -22060663, 2286219, -37950240, 32138589, 31590206, -2334490}, {-25515967, -7491760, -8182973, -20491418, -23355005, -13940545, -8924944, -957731, 11980022, 30484664}, {2167785, -13796440, -16771248, -15201569, 18341386, 155682, -16375673, -12946436, -20704690, 16366062}}, + {{-14851091, 3834241, 23500615, 7352839, 15378973, -26973092, -23868357, -6381556, -52830929, -6411228}, {32116001, -2083367, 39449867, -11115641, 45034733, -1969130, -33371589, 4921204, -6906713, 3888680}, {-30088676, 3734464, 10326777, 4080086, -5745945, 976639, 8600626, 6227353, -4009424, -13874351}}, + {{27110177, 6970429, 12985075, 18195205, 13035461, 23608908, -21508551, -14595570, -13260572, -8052168}, {36677643, -3408013, 25445137, -782973, 40550479, -5211098, -3189183, 8435268, -33524190, 17377748}, {32550115, -16650662, 5167635, -16768200, 22925505, 12479081, 30907141, -5455749, -17591881, -10462184}} + }, + { + {{8433594, -5281514, 28743388, -27585707, 1957245, 9638769, -43302973, 10098494, 38292641, 6604950}, {-31069768, -8992758, -22353880, 4099243, -52025267, 3727331, -9703643, 9970704, -20482539, -696196}, {33243480, 3209120, -21486924, 9305640, -13012910, -10086177, 27422245, 13728436, 16233991, -855978}}, + {{16547645, 2377427, -7645304, 6593644, 28695743, 547751, -3808941, -17976783, 21905009, -47955}, {-49983965, -1415191, -52153056, 15097614, 18660125, -31627509, 59703961, 15225859, -39915959, -15450853}, {22813482, -11987249, -27630393, -6894053, -21830697, 12422562, -15531016, -3816008, -11418140, 3952649}}, + {{41339876, 4856753, -28073776, 14044740, -44935123, 13426469, -44863083, -3207137, 38478330, -4154045}, {-777504, 13884953, 23849386, -6483530, -4646659, 11749323, -4393183, -23904789, 13557864, 21570933}, {10451757, 10221921, -24533663, -16091676, -6526648, -8451170, -606907, -16356501, -31074807, 15194543}}, + {{14726565, 6760794, 33029166, 21219911, -4902918, -15593805, 24382667, -630486, 26482148, -11963664}, {36357299, 1729620, -18523596, 1150127, 18257866, 8214477, -12103791, -24311444, 10702066, -9770904}, {-9677925, -4942029, -9135581, 11783500, 32373628, -15657475, -18830790, 16450132, 29225444, -2404334}}, + {{-7856575, -26295132, -38977785, -3497626, -32099658, -12988324, 23312401, -11319206, -24680215, -9410840}, {34771979, -5013240, -27641227, 11259976, 6916156, -3609654, -42999121, 14488526, 40461251, -21823154}, {29640410, 15261060, 24778523, -482602, 19242559, 9885319, -22285103, -11786425, -2720304, 16429871}}, + {{-11225024, 8594224, 11301766, -1483214, 6521310, -926474, -16070436, 2802545, 42497233, 1756108}, {-19998878, 12421046, -50092558, -3883148, 24660864, -6044404, 25191484, -9214383, -22111817, -9000308}, {14535542, -2782853, -2624890, -10292291, 27831852, -11532908, 1530707, -8735937, -1835514, -13778559}}, + {{33697322, 1689611, -21314096, -17869138, 26463755, 1672256, 2730835, 19984585, -18127152, -9087688}, {-19497240, -14983417, -8154854, 13196202, -13905997, -20895092, 47313915, 9205505, -15220296, -17704226}, {29951904, -3288605, 2501602, 12506806, -17346544, 13421420, 30053387, 10627815, 8850046, -14187876}}, + {{-16778101, -2671049, -7169161, -19819047, 16899914, 10402487, -12191365, 2771458, -54771607, -1847822}, {-32733551, 11014271, -6016161, 7677153, 12933912, -15587383, 45953301, -6844804, 3425627, 21539478}, {-17026422, 13782402, -2087319, 1223799, -17511782, -8479009, 7518008, 595556, -15284465, 11443290}} + }, + { + {{-4912019, -5957006, -718330, 13600497, 25963507, 5477154, -55021761, 12570139, -1120374, -7677310}, {-53879637, -25942626, -4174846, -11945355, -16189501, 18265652, -454975, 9774447, -38065456, -23493278}, {5731776, 13545348, -31543713, -10489396, -24526802, -12042548, -20255794, 15013795, 28201443, -2518481}}, + {{-55413758, 20467831, 3917403, -14086196, -40241592, -7342363, 7872566, 18631892, -39955624, -3567519}, {5780922, 4150171, -13904305, 6672342, 9142962, -18586609, -31827656, -395776, -9271856, 6591845}, {228728, -15203967, -20407515, 1943522, 1235999, -6410713, -2348515, -4920516, 20848237, -14205641}}, + {{34326441, -6029585, 16180666, 6524526, 15710404, -276602, -25003437, 2280285, 11560278, 8884249}, {-18085781, 8971971, -39315214, 14330858, -37076514, 9859918, 230247, -6953787, -45877550, -2666691}, {-15018925, 15780755, 12327319, -1057402, -20317956, -8368744, 24800838, 943542, 19769142, 16549089}}, + {{18412730, -25786085, -7565998, -30927058, -1171729, 10160031, 9558305, -21711595, -35549127, 5278754}, {36903206, 4968005, -55451572, 2296134, -49434531, 12506377, -10832613, -1275733, 29307367, 23846112}, {1230678, 1729663, -29732587, 451081, 32951765, -2881788, -16476865, -13995906, 17285176, 16723767}}, + {{20264328, 2704707, -52004434, 14327074, -21883652, 13197618, -42435285, -6263934, -16317382, -7314715}, {33014758, 24866911, -11533294, 12187418, 38235796, -3130262, -4890063, 26506154, -45593360, -22951807}, {-11172678, -2389242, 31822323, 12375549, -9928997, -14225737, 29607613, -46028, 4333571, -13318325}}, + {{20716717, 2218620, 57640816, 21933071, 36441999, 20472871, 21871024, 14986202, -17312619, -14438073}, {-25676649, 9442512, 618152, 697079, 21123583, -12828549, 13696030, 2765820, 18890525, 15770455}, {9160067, -6341821, 24463025, 15086299, -15307748, -16252573, -32514043, 5892754, -22561037, 16076197}}, + {{21607715, -379296, -18661611, 6080823, 42028638, -5620093, -8887505, 13093550, -16226014, 11274317}, {39756499, 12576244, 48029803, 23508537, -1530388, 18070173, 7020175, -20195360, -14970764, -11707185}, {-18404446, 3581272, 15662048, -3802070, -29054680, -5907690, -29867985, -14343739, -6140471, 11213427}}, + {{-22187341, -8684346, 55836905, -16228496, 42481807, 5870584, -31836533, 24799856, -29470004, 4144324}, {28713681, 5459258, 11124941, 15336254, 23512065, 3733118, -5447753, -7971072, -5760296, -22512082}, {7073035, 942719, 5602019, 2800655, 31010500, -6093617, 22283843, -9486169, 731962, 7356198}} + }, + { + {{7740972, -7022247, -17297381, -20976461, -4107637, 11933789, 18219552, 8911812, 15120174, 17113873}, {-3430360, -7952127, -30062851, 3148167, -38131433, -8029739, -11325692, 12437974, -45609420, -11842431}, {-29331386, -16183625, -33034033, 12676157, 347216, 8779411, -28828299, -2399616, -24177952, -4956823}}, + {{27495132, -16103732, -7814039, 5697805, 16599390, 25427890, 38242581, 9474710, 19651758, 9212219}, {30059674, -16637360, 7420339, 1460291, -5427130, 229190, 24760877, -18543152, -10719178, -13286133}, {5559646, 7313368, -8835893, -11098930, -30509283, -12129762, -2818997, -6511934, -32986721, -1501007}}, + {{-22157950, -11795250, 54115948, -2487099, -12557689, 10093689, -17314542, 14235589, 7599955, -105828}, {13033122, -16062246, -8854464, 21387387, 12886011, 1096091, 41415196, -11582039, 23611267, 28141332}, {-22693401, 6715552, 890911, 18916, 1456723, -13351692, -18222348, 14476059, 27271787, 16550727}}, + {{20578300, 31064455, 38600758, -7225755, -27239721, 5723006, 8693893, -28850224, 19666208, 21287325}, {39709612, 1512307, 21340716, -17030971, 37456295, 6133416, 19975937, -1224798, -12751978, 6672455}, {14484051, -13910897, -18448585, 14858847, -28216107, 5901991, -21625461, -7280254, 18057160, 1569806}}, + {{-11974612, 5944460, -3917683, 589122, -11807707, 18800759, 15383044, 9273334, 6670448, -2358582}, {-14626402, 24695748, 49448293, 13619778, 38040959, -11117575, -31015660, 11107310, 19185570, 12340994}, {443925, 15625757, 10325567, -2159394, 21731532, 3376696, -20166043, -3141704, 7093221, -6165625}}, + {{29070350, 15096134, 13004338, -10931429, -36340198, 14719935, 43957308, 9875187, -4790376, -10867548}, {-11863658, -13084386, -3282962, -6374763, -368554, -467567, -21658844, 11014405, 47465664, -21561720}, {7698683, -2951603, 26726925, -9303198, -27975568, 6939863, 2681841, -3717620, 6894736, -14089352}}, + {{19955480, -1472176, -56903209, -24901238, -5971675, 14617121, -1208357, -9896607, -12138653, -1219039}, {22113604, 10963142, 5671789, 4053510, -54728829, -17081071, 10116973, -17760743, 45479397, -3692131}, {-26634914, 16352624, 15570714, -15003401, 11685316, 2244492, -14014926, -3705114, -10458055, 2151035}}, + {{17560720, -15107137, -13004435, -7624337, 60154435, -6615448, -2470116, -28515130, -2689142, -3133113}, {-19968864, -1833917, 17729213, -1539251, 5312435, 25257678, -32425146, 3171098, 20142216, 5321209}, {-26131327, -15354316, -27201089, 15294823, 29235539, 8177033, 31750532, -13180804, 9795573, -6341949}} + }, + { + {{1709594, -6764999, 5058302, 6467823, 25003101, -4960497, -19723790, -4518096, -44629248, 297107}, {36633556, -20917513, -16687140, -3908081, -737089, 14636139, -3332650, -20368716, 6959730, 24344615}, {18285571, 9168132, 550262, 1733404, -19807074, -4167230, 32169889, -15717122, 6393103, 7007288}}, + {{-10748395, -13244870, -6994062, 12904473, -18957380, -20989332, 51529300, -27410805, 32283115, 16825933}, {-3914105, 19945096, 12632334, -15342137, 836554, 9771652, -10885036, 3891923, 17789639, -3585951}, {-21869924, 8099341, 27176997, 3993493, -6503292, -3167195, -15186988, 5908065, -14023591, -53042}}, + {{28430102, 11260999, 10294873, 6445973, 6147664, 21187743, -3112334, -8025619, -10029390, 4687018}, {36145182, -6264909, 46669893, -7027597, 8832590, -6596555, 27848112, -2246677, -24994832, 15820322}, {15753971, -4975167, 30369075, -13583450, 16557778, 5495984, -12686338, -5030297, -11110828, -10034464}}, + {{6678999, 4066374, 21286452, 15916437, -27378518, 15119177, 30419784, -5107094, 6725301, -3848374}, {-22705395, 12903586, 7798992, -6114427, -20657270, 4126515, 34670936, -11583158, 34737123, -27435392}, {-25889745, -20277, 30156072, 12524679, -18893395, 3083754, -26647413, 8838869, 4511624, -16633945}}, + {{11559610, -16794157, -32091511, -11056905, -23156576, 1469293, 48647731, -1928391, 32221952, 19350492}, {23010166, 16409067, -16639463, -9970647, 27971232, 28654623, -7980493, -6430959, 4533894, 2811394}, {-22085302, -13691835, -7495272, 528654, -348024, -10028278, 28985332, 15977545, 23940801, 16121274}}, + {{51383485, -6137396, -34052011, -10111093, 9328200, -19243755, -33255620, -25271502, -2442694, -4325415}, {-11214355, 20793934, -4725083, -14349559, -36836486, 11014453, 28824674, 4512366, -17230914, 13649301}, {28323530, -1506670, 3341384, 6644922, 28065254, -9851207, 10876499, -9541164, -16502736, 1445810}}, + {{-26342253, 19775372, 22707058, 23551084, -628599, -7337175, -20492792, 29423907, 4279403, 15296549}, {-23227657, -10542956, 32230500, -385196, 8240223, 17194429, -38983718, 1573743, 2973809, 14790431}, {-23802098, 5253656, -27900875, -548693, -8011737, 13065997, 16272532, 11403888, 12550985, -13688979}}, + {{54413719, -6911486, -49205797, -25703116, -7648320, 8522704, -32838290, 6333609, -8716194, -5152881}, {-9986157, -17484646, 523895, -762352, 57951446, -8862230, -15244226, -24844463, 8374102, 12866865}, {7211386, 2436005, 30489771, -7337251, -26804882, -14687022, -21258678, -2975894, -16816388, 13598905}} + }, + { + {{-30750658, 4322504, 9774638, -11010650, 4490014, -535825, -37791205, -14724401, -8755973, 2369806}, {-29460752, 4559748, 35211824, -21791042, 47582522, -31967857, -16973521, 10931821, -43024739, 9708894}, {26304653, -9191791, 20688320, -15845384, -20406793, -8332741, -3333767, -4164249, -1763126, 3255590}}, + {{40555939, 16845244, -17475511, -24012291, -27846037, 605095, -15442588, -11923084, 13423283, -20171283}, {19624633, 16449508, 27852435, 6076521, 12384603, -30908067, -4032604, -10699776, 51343235, 7716021}, {-6154355, 3441983, -17521120, 15229391, 1811733, -15487254, -1270122, 15254781, -6223867, 4118500}}, + {{-61955099, 12996014, 26714235, -4109203, -4229287, -9175064, 32480480, -10850756, -20093037, -3233580}, {779533, -1187024, -22187815, 9542329, 46144495, 6365352, -17338416, 11525334, 23349375, -23172826}, {17963740, -13729332, 6262943, 14060843, -5813318, 8330712, -13820169, 4147564, -10924379, -5149270}}, + {{24324508, -115349, -2876938, 10042, 35461492, 3306667, -13733255, 1493340, 43139360, 23710805}, {-8550406, 9417841, -8627208, 8881290, 30679310, -15127095, -4791871, 31912500, 21114856, 9595463}, {-16390338, 13089242, 1710124, 5770746, 882392, 9085908, -29433376, 15236377, -21411656, -9196424}}, + {{-2509118, -23614787, 9075743, 14882181, 22958508, 16405809, 8888574, 5989660, 23344644, -25742374}, {22578616, 3081689, 47838145, 16324989, -44046478, 2752763, 44266894, 6168204, -2241978, -1329554}, {6028634, 6360042, 10962670, -14488379, -26034920, 128004, -17294535, 16510447, 15809534, 15150696}}, + {{8011032, -5564523, -10755051, -5509139, 14967804, 9243973, 11910970, -8884552, -14357746, -24053365}, {-4702938, -2742433, -41636653, 19041029, -49442792, 14509631, 47045148, -14802624, -29838494, -3195501}, {-6978238, -9692532, -12018455, -14998792, -24538187, -14279720, -24387323, -10315732, -22286236, -10814112}}, + {{-26242516, -30159939, 19683916, -5964233, -18798573, 1260879, -33141870, -277366, 21649547, -11629387}, {-9025588, -2626683, 12887160, 3680459, -24993005, 6902223, -19430166, -20303862, 22565337, 16267783}, {-28712910, -14358908, 19106383, 1794762, -23574467, 6298834, -21226959, -2141624, -5574967, 17516}}, + {{3912021, 5634389, -37246402, 1402208, -13385108, -4129927, -8178715, -16447407, 6327478, 21304566}, {38987111, -25120695, 19511804, -19906912, 35181692, 8054125, 21775119, 633117, -18592220, -10864560}, {-17680532, -589993, -16271264, -11475361, 851465, 1092592, 10540768, -10518762, 4216841, -6902398}} + }, + { + {{30914954, 12146126, 8526006, -3266450, -15424357, 15434375, -48397892, -6694812, 38231161, 1896064}, {24794562, -8110468, 46102702, 12362792, -32567789, -10299139, -4780436, 16339322, -3744789, -31645562}, {-19443713, 5564725, 25048577, -14135563, 29215505, -192506, 22232127, -9071733, 14128945, 8795047}}, + {{-7433894, 24383229, -392555, -1490876, -32016000, -16516888, -49283055, -13078101, -6259504, -2018168}, {-49623750, -4038235, 13992073, -7098018, 17385806, -16920560, -4333085, 969079, 54528094, -19824426}, {4223080, -7294741, -23998292, -16385580, -30565982, 15169602, 12335917, 4240903, 2103630, -9137633}}, + {{-32805198, -3998613, 29810641, -3230756, -50965107, 2425722, -13650156, -1712020, 33652058, 3879391}, {27846158, -28469341, -4660967, 16358016, -9069969, 30360174, -13463520, 24032692, -2212234, 21677905}, {28660304, -7583602, -16609945, -678383, -8225903, -11456306, 18028044, -11924499, 1186370, 9895410}}, + {{9679280, -4163722, -16056077, -20144317, 365795, 5457414, 8792098, 16203617, -9844847, -463953}, {-33243610, 4026096, -12217873, 9533429, -51162923, 22753580, 39552418, 116161, -30146633, 4040387}, {-27734353, -6809888, 5586103, 8469490, 18774284, 13137587, -30215519, -12438654, 16638716, 4560733}}, + {{4371115, 7498100, -23388106, 10354103, -7785516, 8436388, 32399487, -10597087, -37272536, 2809025}, {37803507, -18813218, -8345820, -423917, -31248638, 17095330, -1462607, 6899351, -22633782, -16543659}, {16182472, -2573450, -14968428, -11800360, -24497100, -8398876, 30765205, 15264971, -6170771, 3460644}}, + {{-15812881, -2643411, -16412924, -2726639, -4941238, -25722704, -9018240, 15333560, 2874478, -12986986}, {17994683, 21453081, 24157834, -30619609, -38171934, 1869468, 19455606, -11276752, -2898378, -7910112}, {-28009686, -5796885, 6480577, 9154995, -30896303, -8593053, 9806116, -12697706, -5243237, 2536179}}, + {{-9621374, -27115803, -13632784, 14440150, 34135760, 26242974, -4404474, 5261522, 34019656, -683444}, {47952380, -2406675, -4827054, 16781782, 21528390, 810504, 14919678, 22792690, 26553984, 19882784}, {22528843, 10074794, -27906239, 4876428, -26716387, 12437646, -12096861, -9949277, 14448071, -10023899}}, + {{-11835138, 16601287, -6327046, -12021637, 15299731, -5013486, -52113028, 7299666, -11479598, 10301855}, {-13581288, -12004661, -3722102, 12123765, -37199837, 26011192, -7128570, 19327616, -17602338, 966831}, {6556201, -13049320, 15804839, 14063137, 4312990, -13530475, 3838047, 15682163, 30124468, -9393252}} + }, + { + {{42794524, -2381231, -32439940, -4035209, -24853724, -21830588, -43816418, 14156542, 42935431, -1079240}, {-16272504, -13600845, -29475756, 17078293, 24494158, 3429354, -9841628, 9448534, -22309709, -10073892}, {-3418021, 16032315, -32755454, 15131056, -20288352, -7805532, 24623019, -86803, -3710510, 12631391}}, + {{2573856, -23071879, 7701848, 18073791, -37785761, 267256, -8763844, -22895023, 9928634, -11094702}, {33524328, -906579, -30575080, 11309359, -17414001, 390368, -42148726, -9030841, -3009618, -4928154}, {27474522, 7987637, -9800345, 8769843, 23420548, -15599528, -19619385, -11327210, -30141887, 8017353}}, + {{43669655, -868197, 32856492, 15428807, 15663183, -11770284, 16787406, 532645, -11148431, 1558690}, {8680473, 15086905, 16341510, -11918567, -4463421, 21406912, 1356280, 9524311, 14009921, 14957340}, {22042740, -14670074, 20632004, -15163654, -19192419, -379101, -6618630, -15612305, 31532434, -6250743}}, + {{-32318010, -5052771, 1141731, -594160, 7069936, 15786855, -8044069, -16889047, -1312350, 27008636}, {19196752, 25793505, -12950563, 18315158, 51125260, 977399, -41955363, -16381137, 65105100, 1584088}, {-30026416, -2557077, 16729378, 5684158, -5640886, 13763766, -11840485, -814808, 22137261, -2664475}}, + {{-14670579, -2452657, 26445137, 7734423, 4011308, -21801567, -5635281, 15605926, 43285416, -2813168}, {20600277, 9081945, -32850367, 24590459, -34959430, 8329831, -48126563, 11472426, -6605232, 8910046}, {18503895, -15782879, -11642995, 14314085, 29834937, 5335074, -26404884, -6667127, -13329384, -4271988}}, + {{-30497387, -830385, -1375842, -4090360, -44366916, 9814725, -47493003, 8170861, 31507261, -10458140}, {22218223, -28046349, 26554538, 17509158, 11980798, -3676183, -10953087, 7661783, -30791989, 11106814}, {18561295, -11584840, 12547454, -2722773, 29235962, 6154795, -15732346, -425300, 21227796, 7936601}}, + {{-18067742, -15872387, -49524017, -7347618, 48866038, 23374212, -18779797, -16608108, -41684810, -149402}, {13686196, -17251061, -12552661, 7656326, 12176840, 9965110, -47792567, -8203744, -1358006, -9176846}, {-24053375, -7583283, -4843297, 638032, -6386949, 6837891, -21520100, 8966685, 23738469, 3341022}}, + {{33697762, 13127558, -22831209, -9610315, 6653293, -15224091, 27529257, 9549014, -11863714, 26978237}, {-13317824, -8754148, 37663467, -21934285, 49368731, 5491453, 37428167, -12833670, 25387784, -5610553}, {8796480, 2250199, 2524635, -1942307, -33401320, 12669113, 25948686, 1983218, 29127136, 6760762}} + }, + { + {{57806240, 7228362, 20616580, 14284504, -28782463, 2823013, 9206849, 12648486, -3623747, -1803087}, {-9038902, 26095202, 31469060, 16157526, -23074249, -5578189, -3889855, 6996890, -59596763, 29088873}, {16685317, 15153911, -8902375, 9468465, -6249345, -4381316, -26531497, 7009707, -13674428, -16743399}}, + {{-13182275, -72602, 28138250, 18664812, -26404672, -5276177, -10798397, 6434402, 13417386, 10013045}, {51333993, 3401274, -18422022, -9892712, 33627848, 18117161, 714659, 21293674, -39140894, 12848871}, {-32648888, -12517069, 8530370, -1879077, 26651729, 13181320, 14227346, -907330, -1333745, -16249377}}, + {{-21167492, 18566106, 21233922, 11814353, -35772598, -15577841, -28749665, 15701737, 9341751, -6459617}, {-26841386, 6496998, -8216180, 15789815, -22164518, 5867523, -33252475, 2157813, 24405321, 24789123}, {26425025, 1383760, 12767512, -13808201, -29841745, 11762682, -607609, -16052614, -5241033, -293725}}, + {{9177274, 11565804, 2825778, -12681290, 12592839, -21589838, -5754909, 9516205, -28139086, -11238614}, {50763678, 507178, -58046652, 12715732, -21757915, -4267498, 27547629, -17232997, 26177180, 403794}, {19918606, 16358380, 13719493, 5430158, -4144315, -1099418, 10919664, -15388160, 20266821, 15633966}}, + {{9574571, -7375454, 31851660, 9073740, -25221253, -14355273, 2794859, -17024722, -19381344, 6647589}, {23056921, 11159026, -28969440, 16281246, 38514673, -10931343, 1466753, 11701660, 28429996, -9982721}, {24317270, 1280065, -6044486, 11382262, -4042300, 14335214, -18837253, 14288789, -12338213, 8393929}}, + {{-23374473, 23279135, -24972725, 14952027, -7545313, 2795496, 7779098, 8576359, -11485645, -18769700}, {-21919037, 8048199, -17950731, 4277469, 2728791, -1500556, 35150694, -8789173, -37326133, 11001626}, {-4666832, -5748346, 30788583, 6571845, 15503000, -16278643, 10378253, -14846675, 2035436, -9466514}}, + {{-11559482, 10915777, -21542537, 18417532, -15143966, -14542926, 10660378, -6187861, -4420575, -2661860}, {-27704630, -22262109, 18416975, -12921584, 18005326, 13550930, 11183814, -8496739, -43066727, 21994872}, {-15365697, -1195130, 19463943, -10687805, 29628533, -10944808, 11987077, 12823981, 26639169, 7230847}}, + {{62322254, 1657040, -12299495, 11306683, -58392225, -17094618, -3171101, -4573598, -4809133, 19549114}, {1834044, -12331760, 1254495, 20820981, -6690165, 13535338, 35363253, -22742632, 18066591, 3782754}, {4548426, 12956410, -129925, -14391324, 15341604, 3815469, -19427362, -12381336, -1979714, 10910600}} + }, + { + {{-38552334, -1674113, 13824829, -7707137, -38246571, -2776238, 6007454, 17680412, -47692495, 781973}, {-13484588, -13692401, 39983639, 9893593, 4642169, 23617908, -57486186, -12510648, -7743095, -10884967}, {16176947, 13645689, -5220781, -5134791, -3834690, -3923418, -23840838, -15301830, -31177373, 16659305}}, + {{6157405, -10462727, 912143, 3840737, -13751776, -8704048, -22403706, 21941179, 51052856, 12402937}, {60642057, 6624811, -39495199, -1606279, -23344440, -3344022, 31725842, 7479395, -4017546, -8256901}, {-33350972, -2197208, -8878619, 903920, 5738083, 16409768, -9852952, 7108453, 17599689, 6848797}}, + {{-39277321, 14582070, -9521145, 9982836, 48637199, -18673526, -27720961, 5370770, 7117766, -23728685}, {-14006475, 13970368, -29170739, -14829578, 2130755, -11892984, 3295431, -19058226, 41819084, 5523103}, {-2104061, -15973762, 23645554, -1687583, 17940242, 5600506, 1412545, 11022192, -3039763, 13294268}}, + {{-33867168, -6091684, 33986476, 18833587, 7817636, 25365379, -27563800, -21928376, 1906175, 7763458}, {-18721644, 18333060, -5286710, 6609657, 55044558, -3151875, 19890076, 7167678, -42074971, -4845472}, {2007142, -13990815, 11407379, -9973400, 14642474, 8584678, 26859480, -9160366, 13585466, 2992722}}, + {{12967633, 4152282, 2150258, -7589830, -8849272, -4983507, 27997326, -17832677, 2709915, -3583083}, {-27376669, 10647490, 47762316, 16329854, 49904088, 4531285, 11865942, -2804177, 163707, -23964201}, {15705786, 2935047, 9390318, 13193964, 23115832, -11519649, 20133359, 12377882, -1344753, 140488}}, + {{-8799804, 18948774, -30892571, 123022, -25926079, 4960734, -6090411, -22324977, -25361643, -2167132}, {-28717210, 8697646, -9749505, -32951390, 11502509, 4594706, -29227535, -1414993, 7741851, -5014568}, {4650499, -8478108, -24234179, -5976394, 28331190, -10943442, 30087051, -7919740, 18817885, 7188952}}, + {{30165814, -3069837, 30101180, 6008318, 13668287, 11820720, -31131002, 25156808, 27901561, 18904336}, {-31716998, 8813227, 597464, -9379422, 36959323, -15102790, -9007846, 2320316, 19323359, -4138334}, {-31298362, 10253492, 6664395, -16317626, 885300, -12741158, 8160207, 8350209, -20339801, -5264656}}, + {{-27244760, -8547892, 50279040, 4134124, -34582954, 973191, 32905874, 23822243, -14449954, -3181538}, {24282140, -14077998, 2933130, 11324368, -2880596, 28637719, 8132098, -6556207, 3785372, -1798604}, {-28316408, -6555922, -20197428, -15990077, 5162908, 11249778, -25883916, -2545329, 6596172, 5270674}} + }, + { + {{-38667392, 13210848, -33307206, 5850996, 12145811, 23373861, -35656976, -1789964, -38566886, 10582119}, {-8543892, -9571188, -23473058, 19100686, 45509655, 108361, -15742816, 31197730, -15119888, 22704295}, {-18472517, 1629208, -5362290, 8854934, 11051026, -10324782, -3993819, -5955589, 14771, -14391565}}, + {{38443193, 704092, 15188765, -12896432, 44193811, 2194475, -8595905, -3092667, 9710611, -21131290}, {-10995957, -9649678, 10446831, -129182, -14679713, 14996019, 34719083, -6862053, -49349663, -3302412}, {-22021726, 15445154, -24262574, 634789, -25198277, -983430, 4185055, -2352078, 22668225, -1722550}}, + {{-23718274, -21887065, -9513369, -7091534, -14870744, 13484647, -16058542, 945861, 22125110, -655019}, {34831924, 2392289, 17288431, 17937944, 48862138, -14093787, 12201322, -9544239, -33739394, 25913119}, {-17970941, 4004116, 25769446, -1053913, 15780980, 3165620, -4455598, -2472824, 2834803, 3417684}}, + {{-8397652, 19358521, -11963686, -3036062, 7546576, -6921071, 4844564, 12468145, 6430929, -6838056}, {-8274054, -10148467, -2906088, -24297872, 24652242, 4192509, -10397362, -17281041, -59288565, 7201022}, {-20915932, 111530, 16241897, 2478728, 3406713, 1256919, 19698614, -8699613, 9035742, 12182261}}, + {{-32995188, -15115632, 37258684, 17430696, 47552834, 8794301, -2060438, 18101965, -40984287, 16632799}, {18651726, 6528182, -12706870, 2674756, -11310250, 21894611, 31553714, -6465861, 23883313, 4998257}, {-10614176, 12469321, -12339175, -12747778, -21155744, -2540745, -22556916, 7741387, 11428660, 12299369}}, + {{-42679880, 23000554, -32228427, -10908892, -9318270, 4545974, -58832230, -14942697, 23024210, -14356561}, {3774922, -6937510, 14508043, -19178364, 29786202, 13012958, 4950256, 8804383, 1642790, 1371531}, {-14455491, -10477211, -28254508, -474780, -2194307, 9122980, 32050743, 1155505, -11713511, -16747011}}, + {{-53547702, -5320176, 5102765, 1474641, -31217815, 32849077, 6647165, 15695209, -3792131, 12531790}, {-932750, 23568448, -11508473, -6986319, 360491, 176275, -46541063, -9459947, -46409297, 18452054}, {-1125544, -16388332, 20686417, 16595423, 234001, -16349458, 5942241, -3784534, -11880382, -11724241}}, + {{-2655528, -8075382, -48931117, 5947432, 16717737, -1653214, -35438877, -18141466, -17861017, -7543645}, {20611566, 952546, 18155437, -20285314, 21833189, -7656072, 28513395, -1692066, -24691439, -3322263}, {-28128553, 716673, 16150942, -7563589, 26623406, 9599383, -17399126, 14291296, 7294390, -16283848}} + }, + { + {{15951474, -6165063, -24713108, 3020202, -21126305, 6580972, 11338787, -16318446, -3181650, -11259016}, {-26909818, -8392267, -27094078, 4789702, 41947599, 13583584, -49187389, 13487774, 46338732, 10811840}, {31401188, 1843916, -30394342, 6462582, -25241060, 9172182, 27707571, -12852177, -1090419, -4399935}}, + {{14593295, 12868025, -17695553, -19073336, 28485259, -14550490, 24559545, -24522582, 23773820, -13892509}, {-45228611, 10023323, -16335629, -10257946, -4285115, -14444742, 22579651, 1781890, 3109558, -6840133}, {14242295, -3273120, -31754910, -15307970, -25033843, 8857398, 15856525, -11286375, -18860555, 240513}}, + {{-10981981, -12506190, -47455560, -6701671, 5755731, -13776354, 53550070, 7020704, 22980087, 28880300}, {-25008291, 11239272, 7342260, -24408967, -13503775, 13049946, -5496898, 22285892, 7702877, 1550722}, {-7309743, -7512914, -26198389, -5268732, 30062279, 8648380, -22789201, -15251718, -16593277, 5025464}}, + {{31675213, 2666747, 28374317, -11696736, 20540832, -12644373, 4809514, -28193847, -4543699, -8893966}, {-24385595, -29063763, -17155075, -14520186, 18464716, 5378247, 55140562, 372559, -19606765, -18275082}, {-25178714, -14527666, 15482133, 7813962, 2829666, 13928039, 23512340, 7093410, -1027501, 14004062}}, + {{-18442473, 18501140, 4432715, 9976722, -18757918, -9496918, -8061222, 8917810, -7369978, 19298341}, {2496041, 6587216, -26091171, 5676636, -41124196, -19853332, -18007750, -2258546, 47768812, -295205}, {-9606265, 786277, -7467533, -11301640, -24008558, -1014297, 9669707, -14466099, -19237504, 3722080}}, + {{12016113, 1171181, -9068133, 12952596, -17026125, -2373911, -26348505, 2376042, 19982346, -5124419}, {-30847405, 23521629, -37962973, -13586972, -942005, -7409027, 28883483, 4611452, -16763204, -11286081}, {32796282, -11777689, 20818262, -7507646, 21797715, -12850907, -29262075, 9013853, -13555524, -13244605}}, + {{17981215, 26192017, -11356892, 5561863, -23128861, 17400289, -9617210, -6747416, 9689737, 13543395}, {-14332371, 3748205, 16494752, 17324005, 35761461, 11936211, 1070490, -11205368, -23011931, -2984343}, {21669580, -14138005, 22855790, 10983889, -30324463, 12873947, -13228577, 6740440, -24103611, 12124086}}, + {{-45741381, 7738143, -36056761, -13165187, -30175580, -17624680, -52997180, 10091280, 33449354, 14238430}, {19082763, 11813981, 30559763, 2432633, -7376964, -10447030, 12327684, -1596574, -30603158, -12928940}, {15909369, -8895034, 29479442, -16565154, 14673542, -952999, 30925730, 588157, 11548416, 2933685}} + }, + { + {{28069860, 1877175, -19879034, -5335257, 20988053, -4708031, 18159376, 14578108, 2445060, -2025653}, {-34015378, 4845815, 24102402, -20562117, -26424633, -710069, 5535764, -6291716, 57092020, -7081101}, {16381298, -12870384, 14484367, -44687, 30299161, -14186383, 7419883, -14247799, -19582782, 4084076}}, + {{-3171570, -21804057, -15564411, -6845524, 26219945, 10630100, 33115123, -28178759, 30095246, 3400652}, {31704056, 6076381, 7332161, -20990058, -34126791, 9027192, -22318129, -5168499, -19065500, -27760784}, {7488585, -6136453, -16395525, -7965906, 454030, 951042, 5629664, 2678657, -28566004, 13527904}}, + {{11887898, -9143190, -24098626, 3620260, -3177084, -15628638, 2445925, -2917326, 38183188, -6307758}, {28621564, 14449764, 29523464, -13982930, 45654000, 4800782, -41285919, -14669908, 21692482, 1289580}, {-27206189, -370472, 23194933, 9563131, 3338308, 3077760, 12847343, 13688850, -14052670, 3760635}}, + {{41549906, -1912894, -509598, -5485806, -4353869, 9561787, -28514181, -7298876, 1310324, 17676319}, {20975262, 13871306, 35903860, -17845494, 38431737, -4990997, 16979027, 23284948, -26396126, 13457065}, {17287694, 12793917, 24588923, 4098363, -25209332, -5192583, -4050773, 1817968, 9117098, 13732701}}, + {{-51709512, -14803577, -33158229, 26433818, -694500, -15809365, -29787867, 19881765, 3123617, -23071146}, {-7433568, 11926265, -4157311, -4233896, 29108964, -9210253, 23185565, 12481585, 9605777, 7121526}, {-522124, 9045629, -20970385, 9130673, -33199548, 838118, 17118221, -13958169, -4019157, 13351332}}, + {{18294551, -7161526, -30839606, 2163071, 18724391, 85963, -39775208, -15489265, 12054016, -22379855}, {-30757971, -10977124, 18653818, -1249481, 11144959, 11517761, 17742716, -5370439, -29531146, 6964539}, {15289642, 8154819, 13081681, -7848620, 15002584, 10694084, 20407358, 12392892, -18847996, -3930071}}, + {{-50599246, -2795410, -33637676, -9186433, -19939199, -2572823, 14969974, 15216433, -16661021, 4696220}, {-2175068, -15086708, 28384364, -7884463, -3858661, -29120007, 25421116, -18274813, -43962457, 10416192}, {-29504887, -11161369, -2172272, 9297440, -19278153, -766763, -19260277, -12385764, 30852696, -11187220}}, + {{-40727924, -4627313, 32065847, -1293590, -5746940, -26696462, 14309374, 1667063, -4607115, 4383687}, {10453014, 434007, 2121837, -26273270, 42046800, 3064812, -870924, 5996809, -13954321, -19974335}, {-8722153, -15621861, 559085, 8054133, -24822921, 4366202, 24393788, 13098730, -11502807, 10601459}} + }, + { + {{-966450, -30402611, -12644169, -53673, -963301, -16438426, 8220767, 14379783, -56455508, -4353391}, {53321322, 2974589, 16991801, -25000617, 21017031, 382366, -10303755, -14141547, 9265824, -21328631}, {-24556348, -5687794, -10763376, -12078400, -21952764, 3592903, -33183940, -6201967, -29227322, -11822114}}, + {{44619219, -16334077, 44024690, 27695822, -37052357, 12661787, 46208222, 11867330, 31137121, 5671685}, {-555221, 3693281, 20631972, 1306950, -24253561, -9147863, 14680196, -4185504, -18532373, 1083803}, {-30953814, -15165724, -9275486, -7890591, 27453208, -9604106, -1000474, -2286088, -13567856, -12218450}}, + {{-16952569, -3750531, 8349941, 11470578, -15048481, -318484, -55246746, 11673740, 26158134, -5014861}, {-18935191, -2484045, 41560879, 14437248, -22848099, -9952280, 6161298, -9352392, -6881974, -26020627}, {31460808, 153148, 26585404, 3019357, 666041, -16237331, -16963433, 10955987, -20045330, -9829343}}, + {{-16115204, -13665657, 17177759, -1291792, -37726815, -88365, -7377865, 1849876, -30252688, 23155168}, {-48115178, -3929103, 13478747, 197348, -21117613, 26871619, 38466083, 5303224, 21401868, 7587128}, {27003283, -2806951, -28229348, -9536569, -12364426, 7974619, -14157275, 5543898, 28049418, -11073580}}, + {{5637937, -4856136, 54506869, -6298031, -10279955, 13481493, 9358571, 8578289, 18111743, 4335206}, {-24755, -10559160, 9648859, -12827439, 42300115, -17355863, 12207415, -9385941, 8637021, -20246160}, {-26547052, 14396388, -2040183, -10514442, 2689497, 6789836, 25429098, -8850507, 25426132, -813766}}, + {{-4978857, -18809765, 9046106, -26154978, 709570, 11424894, -35987352, 11837396, 26325368, -2742667}, {-32165499, 8572883, -23515986, 5308114, -17243130, 7876742, -14657218, -1315188, -7160952, 13678181}, {-12306051, -6770458, -29616752, 2299356, -30830648, 251423, -5912285, 3301306, 14337248, -5525478}}, + {{45769709, 8698111, -16598074, 2947372, -43702160, 12189976, -23092259, -16011368, -26058863, 625353}, {15058455, 10790581, 36399450, 128168, -13472814, -18266142, 41951993, 2511548, -29224801, -32357471}, {16727436, -14582452, 12745776, 2420150, 18806762, 7234328, 26064656, -2800247, -25732629, 4380244}}, + {{45060466, 449204, 7721178, 21642765, -155775, -13458270, -15548838, 8979986, 19909825, -21002300}, {11237752, 7642748, 828622, -9374495, -18573837, -18941418, -36400644, -1172904, -26806027, 9205816}, {-20470965, 7363766, 29175534, -5831980, -9392275, 3060228, -24512627, 5531105, -23804044, 14076624}} + }, + { + {{-18258446, -3318270, -32848356, 25675553, -25361929, 27857758, -2913052, 12881837, -44123302, 2619052}, {27637822, -25944186, -11125438, 4486755, 11429423, -2404882, 11455944, -18492289, -7720872, -19356708}, {-17848879, -11195199, -29015579, -12558098, 14111422, 16102748, -15220813, -6853985, -20600529, -5182416}}, + {{15486582, 18289085, 7268246, 284838, -12217841, 1110733, -23506508, 9533700, -24204709, 7975104}, {-22341782, -4208559, 3878536, -19445298, 45901049, 9931439, 31044376, 23730138, -40245929, -7316852}, {-26693296, -656940, 13290249, 1110970, 8151646, -5676179, -19885726, -16095731, -32104593, 1357015}}, + {{-54715728, -28871527, 35056270, 23213976, 6986703, 10629506, -13241869, 9311894, -22141970, 5914483}, {-1934762, 2874575, 24305628, -6476528, -24607221, -22175888, -49997475, 22348634, 39493466, -15179109}, {24850203, -5611149, 10501270, -3696248, -30839791, -300360, -31733851, -11170382, 21347498, -1731647}}, + {{-18694325, 11758642, 23864952, -7378016, 15405248, -11460879, 10377122, 243203, 27760782, -6814983}, {45014951, -14312226, -7610556, 9219988, 4282952, 10784739, -33101240, -22481951, -5898594, 19790389}, {24168738, 11942278, 30806566, 6711907, 22569134, 11352821, 13750688, -1211435, -17003358, 8504337}}, + {{-20990924, -26726112, -1561220, 2581464, 36703966, 7384891, -20437684, -963986, -12017574, 10078352}, {44546398, -6195706, -13263876, -6889370, -9990314, 5490315, 17790102, -18305424, 8094996, 13150402}, {-18185856, 10614524, -16249958, 12105960, -8110176, 14331748, 3789535, 7446683, 24636781, -3336522}}, + {{-29465188, 656996, 11322325, 3242789, 22241845, 7979077, 7316933, 12553368, -2082808, -11928000}, {6775954, 31848720, -47793421, -2745711, -41535829, 21621905, -26651319, 10575258, -62509450, 4264872}, {7387092, -13963122, -1618411, 7695297, 21762133, -3426288, -12195905, -8101472, 10545621, -9748140}}, + {{-44234101, -10508452, 29445192, 19601939, 55011618, -16064604, 9615770, 22419939, 9350874, -24151813}, {-13779747, -19920456, 11806564, 7403467, -8696642, -4730874, -1931636, -5373001, 12311304, 3259565}, {28884484, -13411087, -431383, 14160742, 23402768, 16185028, -29742381, 13402248, 32007430, 7561845}}, + {{-27108654, 13384827, -2825517, 26811819, 34570487, -17192999, 52176956, -21289465, -59408482, 15463205}, {-9434982, -13497623, -15948585, -6050805, -23012011, -10771169, -3542714, 3026177, -6705634, -9477233}, {28231455, -11946194, 16087307, -8177657, 9669996, -14601577, 30102267, 9782975, -32621834, 2932348}} + }, + { + {{16969320, 17234676, -22732950, 8227063, -56388696, 2973270, 15749100, 24899433, -3766821, -25955931}, {-25711458, 7696992, 31164412, 10426945, -8320462, -14626458, -41368926, 2897705, 20231473, -5290195}, {8223521, 9196688, -214582, -5544595, 10200703, -8273658, 16993083, 2087643, 2123428, -9883122}}, + {{1194080, 14703913, -15188387, 6141181, -6351354, -13184431, 4700374, 3525079, -28559097, 30633359}, {-28539494, -3795177, 22031421, -23108319, -21618798, -7278871, 53755342, 5793003, -17859245, -35627}, {-17459370, 5245982, 33161617, 6310472, 14748129, -2461490, -32444142, 2043962, 31334894, -135868}}, + {{-15953062, 3881209, 4993659, -11928638, 1192579, 3836314, 25594841, -7554134, -35705922, 30118995}, {-19066562, -13929513, -7371689, -20065786, 34762841, 11610024, -13907531, 11579956, 19576998, 2727053}, {14303644, -15830796, -24284748, 1205837, 29361854, 4709922, 3016836, 648247, -18761361, -16753367}}, + {{-26257905, 1283683, -9233769, 20703674, 1569047, -12159426, -2882244, -21990395, 11640748, -866783}, {8977685, 29521265, 3275429, -6912834, 10925315, -9813230, 42344210, -8302515, -1413644, -5235063}, {-29257080, 15828249, 27975331, 1591540, -8088139, -12931733, -7563789, -14479631, -21581550, 8055875}}, + {{34520562, 6352844, -4095819, 4635627, -10839447, -2495095, -14160925, 11849402, 1402663, 8997259}, {1106530, 10419646, 50964787, 9952297, -48024183, 15598061, 13183775, 6540034, -22415195, 5951121}, {-762108, 3904485, 19158577, -3538817, 14764022, -14546828, -18445729, 9331397, 17146507, -16766684}}, + {{-21161214, 6202497, -26368382, 2164595, -42507709, 2980669, -38060784, -16387029, 45143123, 25756280}, {-31376490, -13482135, 20511660, -17278199, -14098323, -2527735, 17388740, 7725693, 16475625, 7215334}, {32356341, -15570266, -14832424, 16715481, 28755912, 7286123, 22390081, -14648250, -6832801, 12446510}}, + {{55964494, -4605394, -10849265, 1481851, -17781660, 24541923, -44665025, -1263850, -12022806, -7041674}, {-3134048, -7807798, 35209161, -28466591, 13468314, -8577539, -18997419, 3947150, -37939660, -22343534}, {6369081, 6180251, -7872600, -16032841, 20244109, 8650901, -26794383, -9145933, -28851158, -6960118}}, + {{28103248, -8705428, -19169873, 830532, -4377671, -24253347, -35750672, 6846600, 16979763, -6132725}, {-18316378, -3169184, -825123, 10764318, -30750411, -5501313, 692460, -2488596, 2565163, 804967}, {4476935, -14373935, 790324, -205802, 1151114, -7932135, -32314175, -14646915, -26721453, 11163434}} + }, + { + {{12424935, -3449399, -53321825, -29949789, -24039420, 6284672, -21611232, -4913079, 16572914, 5570618}, {-53125547, 10159197, 4423999, -2238463, 25969514, -2767014, -31950282, 18989929, -35225774, 7081418}, {6091323, -14658033, -29899729, 10677201, 9308624, -13209939, 19490453, -13405934, -14927449, -9603962}}, + {{37597755, -12955933, -19085719, 14951484, -7775969, -8344037, -53245291, 2305231, 24411922, -3467018}, {-26616793, -1894205, -27180615, -5823704, -33781219, -5561249, 6184881, 9779385, -3965220, 16892040}, {-17833968, 12924928, -32152531, 8827095, -3353236, -2121315, -15313632, -8364937, -29465225, 6386200}}, + {{4283943, 1009693, -54504831, 8074023, -18980721, 18529801, 36358451, 13315461, -17587000, 12936945}, {2037579, -25769481, 2913001, 22517299, -44918265, -6292433, -2709445, 9808345, 20168244, -8759595}, {-1930938, -9097937, 12481376, -5397528, -16938280, 9840609, 16466705, -6747606, -32178070, 782236}}, + {{13980821, 6758030, 18061861, 16978070, -7971412, -26092470, 21668597, -10479903, 8987858, 2953783}, {-26243053, 7293246, 26458749, 3600164, -53859664, -1607850, -16456353, -13917693, 44069908, -29900787}, {-180078, -2771119, -8538678, 2969107, -23850993, -3352251, -29715092, 9416339, 2046898, -9526062}}, + {{-31747597, 23854701, 10559273, -943622, 50738129, -313044, 26771418, 18179175, 10869233, 5295165}, {29246117, 9321157, -7789851, 27459176, 1458113, -16840720, -9161520, -5641519, -14442651, -18587231}, {33228819, -13455556, 25672265, -15110283, -24778489, -2301770, -18228958, 5792840, -13192705, -5737719}}, + {{45096486, -24940475, 906955, -19221577, -26519898, -13442027, -36130657, -9206943, 19608784, 7494867}, {10762104, 1104907, -18979559, -12673179, 30111418, -15696671, -5105381, 7881807, -34730342, 14751043}, {-9249323, -14499636, 25155891, -12493225, 22699522, -6914061, 16402255, -1884250, 18826668, 7371701}}, + {{21784549, 9703671, -41364139, -282496, 26578843, 13628399, -41205202, 13652163, -51756783, 24389386}, {23284893, -15494943, -13981341, 5433862, -10771465, 418285, 16005920, 11006309, 509879, -1844740}, {10918370, -5040304, -26869254, 15357203, 4838247, 13059509, 19964070, -9207574, 21131674, -15516155}}, + {{11785541, 22018343, 5369226, -18839722, -23638407, 628128, -18986744, -21727402, -15861035, 10857150}, {-16828749, -6288963, -32255206, -9263498, -31260493, 19576090, -3404032, -7235828, -49652267, 16792576}, {25499178, 6758661, 26939079, -10298607, 9088272, 9477881, -28544561, -6022609, 4557153, -4644304}} + }, + { + {{27512318, -7557993, 5355984, -11897770, 12640055, -7738845, -13609771, -21756843, -49672819, 4810580}, {18764394, 7450569, 25475874, 18800020, -27668151, 4442009, 17988093, -4488327, -11634737, 17162862}, {-31931739, 13899134, -19453302, 9259831, -19003826, -16264365, -9994605, -672241, 30174360, -14356336}}, + {{25173939, -11144381, 27550844, -3246798, -30373504, -19436490, 49403767, -9121574, 31674056, 18702182}, {-24468887, -10733667, 2079448, 21229662, -34108862, 8415258, -1803971, -2185814, 31859758, 7389172}, {-6098113, -4138622, -27668167, -1550502, -10607159, -12386679, 1315120, -10879027, 11427428, 4210121}}, + {{27025317, 3042520, 4191743, -3570900, -4170398, -4079519, 34768006, -7785905, -11816567, -12046569}, {25184891, -18385410, 23515223, -17319072, -53070244, 11171831, 18640200, -17799219, -50910185, 19867329}, {-22460255, -9544952, -28488125, -5302884, 8254972, -11506979, 32029916, 7054717, 14796967, 7187195}}, + {{-10709958, -8789411, 23052298, -9162003, -36675284, -7152223, -34050444, -14125112, 41622236, 10971232}, {6954590, 4356549, -10067032, 6681119, 25975138, 12130373, 15293362, -18530686, 1939530, -484238}, {-32117218, -11582846, -11223524, -10416400, -32041872, 11400119, -32870814, -12681231, -25272944, -5305529}}, + {{-5658434, -7801507, 19023416, -168234, 48724503, -7677825, -58150303, -837731, 2669511, -10761181}, {-41113188, 17884909, -32745606, 29056746, 14749629, 2150939, 7345679, -29096687, -21077023, -8155641}, {-28140721, 16171494, -21262539, 12820399, 32070932, -12417211, -3735800, -2206805, 1517902, 5781829}}, + {{-38550612, -2780789, -47546320, 20705923, 20958262, 1097646, -64011135, 21187111, -60993642, -19572175}, {24817358, 19879443, -16772584, 2310157, 16901698, -30806424, -2273999, -9979407, -3651772, -6824805}, {-27062814, -1574409, -2919655, -7459533, -24823809, 1691306, 28669487, -11490125, -6491745, -6417443}}, + {{-39430014, 6425937, 24601643, -22505609, -5620270, -20510652, 15352019, 2856252, 13053719, -5521392}, {4871098, -24695083, 26725419, 2636087, -50666488, -9790016, -40971609, -5022, -12163751, -2590630}, {33515979, 12221244, -18627345, -16002739, 9166746, 3747507, 303798, 10520970, 20929735, -10026153}}, + {{62859648, 19520624, 39007696, 15028484, -22465495, -590499, 55022326, -18542, 860519, -5832795}, {1562852, -3849288, -21460624, -17277932, 911031, -29333693, -3436336, -4794594, 37213285, -12632115}, {-3699785, -10857473, -13767629, -7262623, 9936077, 16629185, 23824764, -1205576, 12223576, 10757929}} + }, + { + {{34925762, 10968294, -8267307, 9866088, -8913536, -11786485, 4566139, 7431515, -11139562, -18533512}, {-2415354, -12393144, -37577157, 15206404, -31440918, -15212141, 12875363, 25626635, -5196272, 4486232}, {-19361008, 3713816, -17917997, -9658705, -21681821, -7324642, -22443757, -12669502, 20343009, -11236153}}, + {{-18516237, 429863, 4714232, 23219551, 13870705, 19509491, -41379142, 17665608, 48039822, 12331926}, {-9671591, 127767, -8962072, 6567487, -37079111, 4977285, 1130514, 15231408, 10995454, 5177764}, {-11298519, 3649040, -1638836, 9583437, -14298386, -15747976, 14676019, -1854524, 2703093, -8681723}}, + {{-19798899, -3871552, 19906595, 46772, -44856455, 6941284, -19688721, -9653102, 3808716, 24784276}, {-6904191, -23611898, -42785705, -3641674, 20555425, 26239536, -3735543, 1730492, -51196162, -1796836}, {26232540, 6963531, 25931188, -3510906, 23742047, 6696445, 29264160, -10661874, 8334083, -14045517}}, + {{-32301401, 2463799, 30175949, -13276747, -6048294, -3555713, -12917714, 13099945, 8986575, -7554189}, {11772721, -2232229, -27159809, 12371745, 9424298, -29845271, 37551480, -4175051, 38478023, -14209269}, {9026199, 8195352, -22697161, 1927558, -19239390, 14758919, -696302, -5191580, -11239378, 7729390}}, + {{46905910, -8483233, 36780835, 5100016, -13585677, -4802768, 6251061, 3812952, 387110, 9806453}, {-14807030, 19932787, -16365117, 17351678, -28227295, -11721452, 29285925, 9509548, 36755022, -20352267}, {-28935712, 13874573, -2546502, -5851443, 7531639, 16524377, -29678302, 6633546, 28313353, 921649}}, + {{-24903946, 21922546, -19260516, -2366543, -43821587, 17456675, 4783767, -14781401, 36980392, -267613}, {14657150, 92630, 31633338, -13080675, 20345729, -7308485, 6662695, 2745013, 19541906, -16155983}, {-11049871, 12279382, -20842653, -9865370, 25734390, 9799492, -2250713, 2237554, -12194048, 1799858}}, + {{109274, 3335765, 26487200, 595661, 13406892, -1644809, -8642854, -3512970, -29136672, -2431349}, {57800484, 18971161, 18347992, -3519269, -7503286, 25110611, 45047684, 13452224, 13251332, 8547571}, {-232469, 6655636, 16845815, -13387722, 15156149, -3830859, -22811691, -11471615, -503172, 12232133}}, + {{40521306, 17685131, -15339419, -5626639, 35780177, -8911021, 15313562, -5156075, -23304430, 9267515}, {871880, -11492283, -13083447, 4278101, -10968521, -18639029, 47303174, 22510795, 23657226, 10416285}, {1528365, -15036127, -26250973, 6792947, -22723868, -7494357, -22805928, -16408225, -19227962, 15927708}} + }, + { + {{-1423943, 19524099, -5247172, 13868955, -23267366, -5753678, -39415254, -11938850, -8302758, 12818804}, {45544923, -824325, 55686744, -14469601, -22671872, -4289656, -3316360, -20339502, 54994008, 8651854}, {-26254604, -4043901, -14054807, -11868335, 28493523, -3048363, -18336029, 6707620, 32666516, 11056459}}, + {{-7721316, -15251135, -35450127, -9681428, -34070677, 3639387, 29248791, 15759720, -837790, -6151614}, {-56371412, 7045833, 24798439, 5107612, -9815651, 9551743, -29786877, -13003504, 11635362, -26813058}, {5927126, -7958644, 23263856, -2733007, 32528045, -7083978, -17748736, -9472339, 32082732, 4734075}}, + {{-51064968, 637992, 8452171, 29886034, -11757697, 12429826, -9843274, -8155393, -18606753, 4957564}, {-907196, 14405046, 34388889, 68744, -39098729, -7955384, 13841872, 13917375, -2281339, -5855690}, {-2748474, 8997861, -8871038, 10338485, 7357588, 10088, 12166520, 3418358, -1315104, 5114321}}, + {{-5645837, -5691594, -11776744, -1630751, -5214715, 1291044, 315868, 20529419, 11468652, 6655299}, {23701205, 25184464, -29112992, 22192831, -6550945, -58796, -50160230, -8681855, -9644620, -7607349}, {32260619, -11304317, 21188968, -57304, -22611514, -9164398, 29404909, 7064910, -16732112, -3139718}}, + {{12290912, -4459248, -29963772, 5238219, 27039979, 9771718, 44602162, -153154, 28153610, 19989971}, {-35214026, 8374738, -19714848, 1316893, -11735551, 6564020, 17591394, 12474764, -19904788, 2792231}, {14212330, 6292165, -12957477, 8070605, 14250545, 7663469, -32283559, 2087281, -22650110, -3433926}}, + {{5539059, 6238809, -19811080, -610180, -7317314, 25637119, 16472853, -15949027, 26189006, 15553978}, {-44785057, -6987661, 512094, 17104278, 37522256, -3021799, 41973353, 10599485, 28891922, 7817024}, {29703001, 11656746, -1723371, 5899699, 22527490, 895591, -12547251, -2682520, -26216488, -13029539}}, + {{43693671, 14141467, -24958060, 19936483, -4634552, -15097598, -403647, 623889, -47054557, -10798267}, {-11707235, 11636021, 37878606, -3855301, -5995036, 11721240, -63311319, -31794565, 5408607, -10604791}, {32374395, -12940199, 3314518, -4020119, 20490662, -14398446, 31628346, 5366985, 21238103, 14346803}}, + {{-44404558, 8878453, -36115029, 14203784, -23661477, 22579354, -20036310, -4501706, -11329544, 4318958}, {9603456, -14831073, 12681789, -3054508, 489709, -3707858, 13490628, 6537444, -43699668, -27492570}, {-14543640, 619055, 14984400, -8839512, -5190805, -9901441, 811326, 10494156, -10747860, -7471311}} + }, + { + {{32142955, -14234107, 19184741, -17747145, 8689508, 18561262, 7496575, 14921346, -49036425, 4450677}, {-32814455, 15460001, 32472523, -9002931, -25331434, 11075040, 38426719, 16592306, 3765077, -1267167}, {15821339, -3737218, 25574186, -1471289, -31438111, -2617507, 11080214, -6765759, 899125, 16148510}}, + {{18683582, 3965032, -147692, 9151759, -32068523, 4316680, 23305702, -28202780, 60964743, 16525789}, {30724434, 85394, 48975902, 8972435, -28256953, 21356716, -29693896, 5272784, -2187249, -5024005}, {-12513295, -15802354, 2015919, -14469021, -14545679, 14153212, 18882500, -12113215, -16338042, -16046539}}, + {{-4773237, -2130724, -16972793, 14769971, 25279295, -7282194, -43805081, -4714762, 25812630, 3083386}, {-42706305, -29684202, 19475275, -15957155, 39062453, 1562672, -17780397, -19648540, -38820868, 1962588}, {-614264, 14982935, -7849474, 2930005, -24905938, 11306140, -13730780, -9555652, 14021609, -11062773}}, + {{-18832558, 12197703, -23156800, 4768765, 12806438, -13942309, -35974235, -3743307, 36385852, -19742197}, {38556308, -13950671, -13578048, 21803767, 20741898, -17919929, -3266761, -7969173, 26562114, -3073243}, {-20170752, 7343934, -7541981, -13410891, 10141195, 10446273, 21905429, -6440795, -14831040, -12515083}}, + {{-18932315, 13127699, 6820553, 5495106, 1960517, 10421282, -18712383, 4634381, -4355479, 10027615}, {-29717477, 9281683, -38759853, -585638, -51528067, 19275836, 21432803, -7184863, 43016751, 20236285}, {6576903, 6948015, 31188994, -4727511, -16021372, 14867226, 32606854, 13079982, 7304891, -13172603}}, + {{-18166850, 19187800, -45014384, 13661463, 3227516, -8834860, 456120, 1889594, 6631576, -4243204}, {22692492, -4412464, -5257584, 7516215, -38333328, -8005116, 58405076, -30590872, 6583294, 21130060}, {5554996, 759793, 27065433, 6201701, -12308485, 4185005, 22643252, 6296810, -7050038, 7916347}}, + {{32597259, -18231697, -5959173, -13354428, -46089079, 4159362, -5453582, -2532797, 8839265, 25666124}, {-5590957, 9606273, 59810143, -17322186, 8223399, -3986384, 16965376, 15378203, 37770041, 2070162}, {-31073238, 13893232, -845267, -16676671, -21258018, 2854278, -27507451, 15527104, 10973693, 2729142}}, + {{2566384, -9440423, 37485538, 5438592, 4159191, -602710, -9791057, 14087580, 18336825, 7907713}, {32651048, 20826157, 27580292, 27871120, 17134577, -15500340, -23137773, 13698840, -4860475, -25042877}, {14304456, -1696809, -13034450, 15503161, 4430663, 15397873, 30969618, -3036150, -24358494, -6513865}} + }, + { + {{-857230, -9485579, 23552403, -11039089, 26131571, 14416567, 12771157, 17681843, 2240483, -13665691}, {-26128406, 19183455, 33598005, -18885517, 33505033, 3628675, 14364673, -13064561, 62932161, 11241919}, {22529449, 10400780, 3114202, -3127238, 25820725, -14645285, -17246222, 3543721, -10559855, 3410062}}, + {{-21203888, -26394583, -2030002, -18591333, -41701030, -31307517, 21202609, -16950400, 31872542, 9413196}, {5545628, -4328203, 11546928, 5386943, -1411554, 143129, 24828505, 5051844, 9554670, -10008718}, {-28670131, 6174081, 21670660, 15929513, 8091846, 9973174, 4016395, -12093222, -30968586, 9298545}}, + {{-23486358, 8839324, 52212850, 9072376, 9892877, 20617547, -14002543, 2559370, -39415702, 16686864}, {-16714644, 22175336, -7387454, -3719964, 31435391, -10105161, 31806339, 9318296, 11739638, -16603042}, {-1914678, -10255818, -18333956, -4090878, -10396208, 13713384, -14008910, 4128697, -23017589, 1638209}}, + {{58853069, -16727379, 31038469, -535197, -7152765, -7769610, -11044232, -14097842, -46104681, -6594829}, {-1820893, 10840377, -19534793, 17202043, 53836377, 9831562, -47770056, 10186170, 9640919, 4015489}, {-8860848, -14813381, 3891229, 16398617, 4387760, -10967061, 7112070, 777585, 26413033, 9151808}}, + {{-3484777, -15865911, -46624656, 21026078, -3438226, -19091358, -30787, -13117583, 2955970, -1412784}, {14365179, -8657089, -4575200, 12256488, -34169360, 6927670, 6489451, -15034975, -31018200, 16694030}, {23974024, -4695344, -25735147, 1849074, 9002353, 5704357, -21374919, 16776491, -31484292, 966955}}, + {{21716456, -5957992, 40581840, 15312351, -28976962, 6734286, 64951503, 6581321, 28927804, 23885069}, {-38617104, 10315948, -14167134, 1108241, 9415872, 21531848, 1556797, 2706429, 7429342, 6653301}, {-26995015, -5880669, 16361897, 5842721, 26930976, 15486318, -19174572, 15758906, -20956566, 16333713}}, + {{37636271, 3539061, 19586838, 928921, -14066177, 2924468, -47241307, 11097811, 1905367, -1520269}, {-23123431, -3313085, -4711932, -8488395, -51731741, 21428632, -15225463, -2322025, 34066075, 12317853}, {-31047858, -13676722, 28093087, 15465818, 22787487, 426738, -4841535, -15620892, -25789810, 11208546}}, + {{-16222562, 19745771, -36387031, 18275320, -12454610, 28772765, 15109989, 7978600, -29158249, -9769882}, {-38711780, -6503517, -1336521, -10507952, -44894980, 4416389, 36712485, -4356406, -28079219, -12116410}, {-2739324, -156151, 27501166, -15272775, -20826195, -14069020, -13050709, -10074879, 31374950, -10528115}} + }, + { + {{-14075800, -9399340, -12285950, 13139767, -12200289, -1415459, 16340171, 23389367, 22044922, -4933136}, {-19800318, 19665578, -15837062, -6651705, 47095113, 26184149, 23472667, -6770755, -35702468, 16378518}, {-19257789, 8326531, 2126376, 10409852, -13952914, 10952229, -15042613, -14537407, 31086406, -13992609}}, + {{6324061, 21513221, 27534592, -11680911, 24988272, 776777, 49028786, -6191180, -16044389, 24251280}, {-48600917, -3504997, 15834618, 6776249, -21384884, -32190121, 17026272, -13583214, -44522959, -6191052}, {-11477141, -4739885, -18547021, 11032317, -3821556, -1568687, 13236197, 4586148, -28039321, 5334661}}, + {{-2619358, 22512042, 2241930, -15826919, 13562409, 27594158, -25679190, -2084515, -9064737, 12332302}, {-877092, 2850102, 24911692, -14227753, 15702129, 1019146, 230084, -18381601, 57982277, 14405892}, {12130539, 2336856, 17056493, 5912685, 30138703, 4316057, -22568172, 15528462, -24424532, -5548561}}, + {{-52972512, -4981211, -12634050, -25446031, 27049436, -26411159, 33429513, -2094461, -25905172, -12386442}, {2634218, -17843515, -8852632, -5412381, -25557678, 3237315, -240719, 8694519, 4347238, -14171538}, {-9908341, 1163932, -7451503, 13637099, -2802628, -13219563, 21169668, 6125015, -249123, -8494004}}, + {{38186145, -3058580, 29809585, -8395125, 7163965, 4826511, -53103150, -21478203, 5486419, -1068758}, {-3558435, -13641834, 30730977, -3913631, 17329933, -16423241, 11101940, -78463, 2255853, 17005196}, {32312362, 16773765, 16518712, -12027454, 5900170, -5137849, -8634192, -10594433, -18488305, -10341519}}, + {{24190553, 17572765, 28701366, -29613504, -13866358, 6594642, 31867683, -23657434, 36525052, 383257}, {19368499, 2762667, 7708080, -2272096, 18333904, 10858678, -21814485, -6142076, 21566776, 15259963}, {-4294074, -13742435, -920227, 1796123, -4563244, -13426141, -9631993, -14111736, -19327234, -6213940}}, + {{-32684508, 4383726, 11858215, -17708657, -57553080, 4832659, 26634910, 22990568, -50359035, 2015531}, {14989942, 8809736, 26333397, -12976593, -1495178, -6841723, 39921656, 10345260, -10265025, 20685407}, {-2242168, 1543553, -27142733, 16564501, -23073118, -12431211, 13122421, -3894952, 25414823, -13752663}}, + {{-19767683, 2131098, -16591047, 7078616, -17656611, -9707019, 23065468, 11353498, 44773685, 2587764}, {-28976777, 16184616, 40088455, -22478058, -18088847, -23460733, 30109326, 5506666, -4722083, -2040686}, {-19288724, -1868825, 24732477, -15504375, 12960881, -4985132, -14623906, 2657502, -1827315, -13595382}} + }, + { + {{-8936079, -624212, 17371152, -2850516, -28384497, -8137346, 26687379, 16146721, -5732, 764625}, {55989277, -10151044, -38088438, -29288274, -27405495, 22976954, 9069537, -2679253, -26093856, -11364643}, {20694731, -10228796, 4251326, -4091115, -15141256, -2943096, -18818842, 2384024, 11016559, 12794368}}, + {{40646283, 14514015, 8902129, -11735239, -8821263, -22670335, 29080985, 10607398, -3214977, 27524141}, {-20677911, 9051949, -37551969, 16728521, 39064527, 7537021, -20403881, 20821592, 21061613, -4825179}, {32173032, 1473973, 6485660, -8417283, -17755228, 8960238, -26330720, -5250731, 11481558, -11225370}}, + {{35700029, -17567466, 33511166, -27856027, -1585208, 5664916, 25085093, -15019861, 11538646, 7375866}, {-11738419, 12553846, 10803406, 581661, 54956572, -6591880, 39640389, 11617463, -55252814, 11185526}, {32173647, -10628329, 598580, -8522520, 17990667, 6919274, 22886872, 1459775, -4157645, 9509268}}, + {{-9299184, 4441397, -7228378, -3090046, -8861529, -7314148, 42460574, -4877779, -19532772, -10505248}, {39703118, -273979, -51213718, -13414682, 55734397, 25584678, -19592638, -22836377, 16908416, -20801490}, {17117149, 13458836, -5864262, 8890227, -2555331, -10048017, -11135890, 1873321, 25877864, 7268867}}, + {{44143903, -9745505, 5446202, 7489679, 37435312, 955223, 3483756, 6441665, -4848247, -10421083}, {13676857, 7500655, 42355678, 3389713, 13327726, 30617045, 52884588, -25438959, -4842107, 5938227}, {-31806912, -14215249, -8111925, 6791380, -10384573, 9606611, -15178218, -11872148, -3214751, 10257702}}, + {{-45940845, 23443796, 3323080, -15747783, 1227119, -25701334, -26721620, -12253851, 466570, -10655820}, {20468875, -2925362, -50270794, -13686541, -17664951, -6616, -13152836, -15116867, -7781678, 18540692}, {25450632, 7658693, -32092065, -11429089, -31045454, 1316157, -22278049, -11102465, 3710638, 1021259}}, + {{2860417, -11480252, -44851855, -30453893, -8953103, -22612976, 17044811, -30231067, 1622435, -4601836}, {-20675545, 5911266, 2920499, 2523165, 21487869, -7646092, -2462535, 981501, -41871177, 25706774}, {18904592, -2778600, -32863561, -7136314, -31361065, -14054167, -12346058, -5530035, -14413329, 7894741}}, + {{25398772, 19186422, -31322310, 21466355, 40832827, -9702273, -19046501, -1527989, -9323858, -12517635}, {14825684, 7154806, 14268656, 3616685, -10534257, -18436583, 19638265, -23341155, 31854416, 8021487}, {-30028109, -7485277, 6136224, 6157215, 19526013, 7206629, 25599471, -15516603, -21830485, -2378940}} + }, + { + {{30209710, -12136814, -1916338, 7065944, 8939954, -20966499, 7552139, 10546452, 31038701, -2874977}, {35447076, 18349298, 7267608, -5213386, -23933450, -1725633, 52675117, -15215440, -30685315, -7268561}, {6356887, -11681156, 33071618, -10365216, -754410, 9603242, -12103852, -765715, -25290960, 5702386}}, + {{24013097, 14053868, 22613110, 4132376, 449379, 20163477, -42858381, 2208105, 37684861, -16117030}, {-37317277, 1136464, 39327598, -2292778, 53439725, 11084415, 10426621, 28451959, -9126587, 71718}, {-27701957, -15869075, -31502603, -1506411, 11849132, -6446750, -16227862, 10721043, -30078713, 368527}}, + {{-12473016, 2814820, 19011417, -9923852, 40512521, -1202041, -9231787, -24738399, -33079348, -4703748}, {46365632, -3327190, 35922439, 4375784, -26509577, 11507685, -3440145, 277473, -1336798, 5503656}, {30974829, 13350517, 18821201, 4870009, -11888251, 10366408, 28885516, 5985354, 22497265, -15639317}}, + {{11471315, -11081232, -21735702, -1776143, -7183060, -1918321, -941542, -11349561, -5461366, -18786047}, {-8364605, 14227320, -28420498, -11592453, -59127574, -5373595, -59611798, 12108279, -35963070, 8635591}, {4746578, -13407997, 18323668, 16532670, 11131056, -9626746, -22869112, -14363864, -13298798, 173999}}, + {{-1763077, -18448405, 25697776, 20713767, 16236594, -10134398, 28986449, -18196009, -16481896, -214038}, {57572269, 7723477, 4103648, 4879773, 29822812, 21912786, 9949145, -13837069, 18828366, 11938130}, {-6596556, -10136682, 951981, -9924963, 10171395, 9878507, -12834721, -13809230, 3313618, 10217624}}, + {{2010972, -10591760, -35636905, 6528427, -17675326, -21338214, -13577869, -11781316, -48814573, 18789255}, {40210200, 8210760, 24458609, 3406401, 21613600, 3914014, -11450377, 14644418, -15961259, 599025}, {-1698843, 2786491, -24001199, 4497816, 9590116, 4559892, 2828221, 9283569, 12305326, -16305274}}, + {{4324312, 9780992, 37550755, -8726335, -3066238, -19608225, 14398144, 3396285, 56793496, -11281779}, {50556186, 10777892, 20257441, -20441969, 59803598, -5998319, 51211510, -4851201, -5399940, 18943709}, {-6234933, 6554323, 2962738, -67063, 11026438, -11328215, 11760473, 2334415, -1683529, 1997343}}, + {{-28726810, -8363831, -64496629, 181911, 47256033, 2092844, -16571926, 16374091, -55975864, -20189330}, {36412292, 12810389, 1769755, 11947997, 8296283, 2846528, -39909634, -14465219, 2114814, -13173814}, {22914282, 1461641, 9478566, -4509861, 14925927, 7960522, 6192780, -13404007, -20484559, -1124372}} + }, + { + {{-48356557, -13583095, -30052214, 14265614, -24244, -6544158, -36555718, -14990097, 19571659, 4254750}, {5253575, -12816731, 672382, -12672324, 32469208, 18848746, 18007584, -3740563, 27915383, 26900610}, {31788392, 12983075, -5589487, -12593692, 24935609, 4845313, 14897764, 8591081, 28221720, 10075125}}, + {{7935423, -22787606, -18329320, -2688602, -6931935, -8013917, -7731891, 18683789, 12045352, -5487624}, {-43716823, -1328044, -27456354, -14287776, 53916523, 23806877, -28575745, 8636531, 30518226, -12995618}, {-28099053, -818544, -31373885, -2976712, 19028916, 16395582, 20250507, -1728685, -13578109, 9957552}}, + {{-1562624, -10989062, -18179938, -11310626, -45993350, 11634620, 12634721, 11287051, 31614119, 8213565}, {29619932, 12775220, -40218418, -9733114, 17041914, 15739232, 49097927, 9378315, -17633593, -11768909}, {21099784, 8606062, 23763716, 1601132, -23395830, -3019104, -19482091, 1808464, -2411989, 1018595}}, + {{22937598, 1838098, 32470918, 7380128, 28629672, -399855, -9806796, -11492909, 14882232, -17300888}, {-24555288, 16733010, -22418858, -1031154, 34017890, 23935503, -56293956, -8885819, 38509354, -7906696}, {-13568330, 15036664, -9250347, -15359398, -33390767, -4966302, 24779792, -4366832, 29989605, 10417522}}, + {{25481955, -2971417, -9243091, -5701292, -9101774, -6462099, -43119587, -22200474, 2358414, -19730111}, {-2141201, 11418059, 16352079, -5332818, 14679580, -20503457, -23182047, -9484436, 45194680, 1265757}, {8170761, -10557984, 31893455, 524848, 939434, -11211186, 21534099, -9355934, -30402679, -12977960}}, + {{-26458562, -200710, -5547300, 19666549, 6057638, -4838379, -20541871, 14482648, -34086864, -327946}, {-19707632, -262700, -15184978, -11421759, -27610948, 1236747, -33609799, 12122536, 5641328, -1102644}, {32481726, -4894475, 9764775, -15288225, 22718090, 1968754, -670351, 15699563, 27713188, 11123973}}, + {{37074940, 15949138, 23657077, -1349459, 23376913, 2730287, -28050327, -17532097, -6367233, -8087241}, {22843200, 11318246, -8466753, -17821045, -27704923, 15516595, -10125189, -15014005, 27762999, 24657151}, {-22939333, 2151132, -30402250, 6428690, -21877119, -6210357, 27068901, 11258091, 22014806, -12368131}}, + {{3928213, 10610759, -32281880, -21725016, -8410662, 29003345, -39232312, -25441570, 39540090, -16047354}, {-8399711, -10879097, 33651302, 8131276, 2824482, 399681, 18113604, -7600042, -23501990, -2750372}, {-32371872, 11017221, -18870913, -12340972, 2903156, -1070081, -16480170, 9021909, -1362829, 7132558}} + }, + { + {{7198550, -790465, -3539049, -21880346, -1838471, -11017531, 54705489, 16117265, -22220767, -11478716}, {19759704, -2856005, 16759835, 8015336, -62575097, 7818605, -587103, 13589089, -22032795, -14835900}, {-16500089, 12447130, 415528, -15467095, -13949277, -3107739, -19988593, -16687131, 24142377, 14636241}}, + {{32051407, -16489353, 1780611, 11706957, -313444, 15547126, -26481454, 10421533, 43817482, -760064}, {6888387, -14809577, -15646819, 16421865, 49796222, 8740356, 27918734, -1031295, 9298014, 8923066}, {16319645, 9700648, -28775170, 11271508, 30869129, 1691406, -12588888, -11255191, 29805557, 10534822}}, + {{-6147902, -5938808, 43823571, 4091494, -17544361, -24378157, -26687671, 7466258, -18243738, 1234620}, {-32101896, -12209518, 5715473, 27018702, -36131751, 6933055, 2019421, -17870480, -640456, 8623550}, {24092151, -4993781, 28076876, -1299404, -14623116, 14877627, -3756995, 3672951, 25616949, 9498537}}, + {{29858568, -20921731, -1325368, 3820945, -2899207, -14219729, -4091943, -7080801, 11921852, 2676756}, {28525116, -8942833, 16659802, -16425585, 20848969, -380381, 46414433, 3430315, 37901266, 22799864}, {-17619557, -3143602, -20813443, -1788233, 21445578, 12287313, 21288662, 8323067, -17926738, 2681405}}, + {{29816944, 18817708, 12408238, -15144529, -3323076, -6386331, -36926058, 9734772, 26971585, 29971242}, {32945520, 3466400, 29541766, -4967599, -17829474, -25229227, -22020928, 5777560, 10105247, 1916122}, {-20885121, -4592196, 16082014, -11679847, 26795101, 1589201, -9583407, 14993606, -15327676, -4223514}}, + {{34152503, -12806367, 49843136, 16572132, 10766134, 28653778, 49045554, 5231702, 48312918, -14320689}, {2509787, -6908337, 12776026, -11727558, -4021036, 2439578, -1877850, -12811498, -17651202, 16104565}, {18193446, 9942891, -6307165, 12005666, -30113179, 4238270, -25355194, 6893190, -25394433, 2925408}}, + {{-19427063, 3213285, -26539268, -4158110, 36153071, 9164947, -38867627, 2337304, -15459446, -7319451}, {-42886597, -554777, -1239812, -16773902, 7726651, -245367, -20966287, -26093072, 672094, 8120691}, {21386735, 16225707, 8432961, 2943899, 13327603, -7276609, -14463221, 6566920, -10652520, 2160268}}, + {{-18541219, 27448115, 8409101, -9566646, -30174482, 1451808, -39839508, -6461572, 7579055, -3571553}, {-28062385, -2567119, -9900245, -1454908, -29247856, 19869432, -9549530, -858614, 39377171, 29087379}, {25789199, 96213, -23912495, -1235268, 23049914, -13015811, 26015603, 4286937, 1215656, 7580405}} + }, + { + {{1474379, 767676, 28046259, -510249, -4478062, -11331252, -21652843, 17113336, -47658788, -11827075}, {-27157567, -8336752, 32392083, -1382887, 15167394, 18719724, 25512739, -16101398, -12394698, 15734839}, {11332719, -3762724, 4567390, 9539265, 17165088, -10586494, 24471075, -13417333, -5036958, -7062524}}, + {{-17100196, 11080469, -4877685, 23482882, -34581688, -5453369, 29387974, -19298785, -39759097, 7469060}, {3882450, -15097029, 26708189, -5589086, 23723098, 22309807, -37280820, 14041345, -12888481, -23265886}, {14149250, 9686184, 5636871, -8702290, -17773072, -6118224, -1732763, -4871910, -30113489, -904725}}, + {{-5509993, -9173760, 24692369, -7003990, 31128190, 18085235, -9284958, 5810220, 32186999, -18761294}, {4731997, -19004378, -30052527, 8359588, 6375166, 5446345, 8329288, 353138, 1267859, -14456476}, {-13564966, 14077469, 28342131, 13226695, -29479434, 6874442, 3661577, 8859108, -30294100, -10391685}}, + {{38872717, 18247047, 22003177, 8443285, -39340091, 11685709, -9852806, 19312236, 3587913, -1854817}, {-16116081, -5852595, -33383431, 2120723, -12461487, 8998439, -40717610, -3968154, 37572397, 2579557}, {-6923224, -7914839, -23084058, -7901660, 27042873, -10681515, 28541629, 6861003, 232162, 11147634}}, + {{-38312832, 10967558, 27504529, -19754503, -18005786, 21906477, 20939182, 756778, -5490643, -28020368}, {-12799940, 21671414, 21365697, 12118217, 47771016, 6295023, -2430544, 26945436, -23326131, 4202242}, {25696407, 15917313, -312118, -15301808, -3830230, -11581913, 156455, -3436414, 25524791, 613491}}, + {{-25566549, -56080, 31493939, 21225921, 52961329, 14264305, 40304781, 10822622, 40892046, -872935}, {-32658801, 16227736, 24407093, 650197, 4018469, -14960869, -20535111, 15324344, 25483028, -3583427}, {-12063057, 10551264, -24463098, -14410296, -6552165, -14108746, 18193369, 4542824, -16278909, 3905086}}, + {{32805835, -2192892, 12790592, 9585591, -16666892, -7907341, -53398583, 5539631, -34650839, -4410024}, {-2863443, 29634720, 5551534, -19773515, 24037792, 6247963, 10364953, 14489359, -11747867, 27860702}, {15589296, -11914797, -28208475, 9908443, -7631186, -15786947, -21098983, -9302795, -10091076, 1611389}}, + {{-25562706, 15752324, -9341517, -13233468, -46999934, -13285091, -914197, -20139420, -16355215, -1798356}, {20110980, 17615890, -21824287, -8358000, 18811852, 19433161, 46762075, 830092, -3657265, -20867414}, {-13752464, 4287126, 12171345, -14324878, 24085231, 1211565, 2659414, -12356834, 18023416, -12727905}} + }, + { + {{1351240, 2121699, -12971014, -4971252, -9311706, -29554026, -50398696, -6826969, -7131437, 8145328}, {12357802, 28327197, -10092702, -8703594, -39863048, 2658130, -383684, 17883761, -31320429, 15580358}, {5888787, 13384381, 1299211, -4061897, 20267237, -6419675, -10469872, 7667392, -24680870, 5017539}}, + {{-34005260, 10119527, -3580853, 8989378, 895381, 8143539, -10533987, 11608957, -8161742, -1936625}, {20464188, -14863795, -48007427, -5314450, 53637779, 15869943, 14107835, -2972969, -36483108, 15668553}, {-13808714, 10893271, 12599331, -3348740, -794353, -10155873, -29681092, 16701014, 29195457, -4022766}}, + {{-43411893, 3577206, -28037224, 16807034, -25289408, -9418693, 16197448, -24544154, 40225060, 18636381}, {16445477, 14732604, 7589850, -15217354, 5748166, 19712723, 44786330, -2143212, 26073708, -8248061}, {-5788750, -8494845, -12219966, 10257966, -14425665, 2702211, 11875879, 4087042, -33467271, 15326962}}, + {{-1141122, -5652491, 28815066, -3483722, -10471953, 8334983, -64851051, -1787741, 22834042, -14162113}, {21777604, -13977131, -14752690, -6724722, -7596903, 14167459, 2157753, 20490823, -30058230, -3148469}, {1569197, -1316784, -8937866, 5052647, 18233833, -10068412, -20654955, 1919659, -15604453, -8741437}}, + {{19947058, 18751944, 37857632, 12045670, 51794406, -22809990, -32506734, -18029052, 28094178, -16218916}, {-4378830, -12495588, -6315320, 10868332, -1606450, 9964854, -33270284, 1485524, -9206258, 1757942}, {-12632192, -15623307, 21120199, 5234349, -26483174, -11415028, -21412231, 4220004, 26555223, -13528462}}, + {{-57119433, 16843357, 22397659, -4486492, 10112303, -6050645, -22438743, 7863291, -2120258, 2079086}, {1640119, -12137173, 8291069, -14033902, 13243601, 14168897, 25749283, 23299113, -1546122, -20357040}, {22479625, 4777302, -24070230, -3331738, 15909669, -6249610, -10354202, 14585573, 22188176, -16196881}}, + {{58840856, 12044546, 6190726, 2063481, -3984173, 1111942, -42173456, -7097491, -22383958, -18043949}, {-2812640, -508700, -31787092, -27220355, 35020199, -8234422, 660122, -3082503, 17406366, -8641009}, {-17008359, -2886561, 18650764, 8661589, 31166214, 8543335, 18617610, -6914556, -30200445, -10186459}}, + {{42976243, 12315309, -36415092, -6774977, 3181972, -27727570, 3009046, -13426824, -9830591, -17287570}, {-6588685, -11116589, 15354244, 17761537, 39679660, -2290850, -34498476, 5767046, 45903503, 10498496}, {-13053087, -291457, -18943017, 5484483, 10438655, -10528915, 19871984, -16503341, -33303222, 1552718}} + } + }; + const precomp_data_t c_point_U_precomp_data = { + { + {{21400817, 3163693, 22274602, 1860235, 12921482, 1217493, -11010042, -1386984, -15511344, 23938104}, {30785711, -8713869, -11504484, -6188623, -35803896, 20705931, 27072746, 27026120, 50090152, -6224356}, {-1226464, -15432576, -15257994, 7722966, 5301836, 15823262, 12121778, 1127837, 29573438, -10846212}}, + {{45327989, 5871829, -21594162, 14686109, -4371676, -21253280, -22930729, -16081648, 1113028, 6113431}, {20703019, -5933743, -12557770, -13311857, -58245242, 173658, 36988907, -4687232, 1813788, -5769667}, {-22224350, -10189375, -33502324, -8837358, -24941208, 2322074, -4449737, 102988, 22334713, 5211518}}, + {{-40433145, 15676162, 24174310, -5452025, -28574992, -10027714, -17820899, -15072104, 2824082, 2984497}, {21270833, 5317458, -13140896, -11765051, -32117936, 3735404, -13464599, 10077550, 540454, -17926889}, {-20312935, -938058, 18992962, -6806474, -8113796, 1188520, -7182097, 1160431, 11617041, -15673135}}, + {{11598233, -11778045, 34249849, -2615407, -44314803, 17924865, 10170798, -10830372, 6192954, 7353666}, {-6124853, -14828989, 25116753, -14794893, -3102119, 9585375, 35636402, 13895290, -38805522, -4671304}, {-16956137, 3817673, -29557250, 2045834, -9572915, 2591103, -29509266, -8549542, 8891002, -801087}}, + {{-41967606, 22877756, 1990357, -4034603, 1692575, 23004174, -51002576, 21174571, 828401, -13030510}, {-15827162, 9380470, 22320399, -29334007, 39740385, -8244670, -13046724, -11955551, 43264599, -17758528}, {-12066457, -8379790, 1536996, 10598975, -1739367, -16406896, 7889871, -6492654, 14788936, 779109}}, + {{42857109, -7040391, 5234992, 24780567, 16763369, -8281032, -7873761, 9570332, 24965615, 27017395}, {19124589, -3398123, 55594858, -6538179, -28875407, 18600156, -18212993, 5186814, -22204219, -630987}, {8399475, -4775346, -2933541, 16133392, -30265491, 4957974, 2019696, 11267383, 30760770, 7936054}}, + {{-26931544, -18046377, -47201091, -7802111, -11092383, 13783932, -21729506, 7106849, 27873134, -158273}, {21811244, -12626227, -6754731, -14202005, 9589809, 8001416, 16323792, -26428371, 5627506, -166141}, {-21859253, 10600718, 26921550, 4044339, 4505490, 12102917, -13774706, 4209054, 16481168, -6927667}}, + {{55260815, -10410945, 35442582, -7640429, -7395681, -2391876, -47948153, 11525422, 4043023, -7661067}, {8483789, -10513719, 20297604, -3810215, 19151559, 23743620, -3236399, -19713798, 45690193, 9352781}, {-1892598, 8388723, -10847476, 10245778, 23648170, -3843865, -10668156, -14489545, -16648787, 15188601}} + }, + { + {{25506571, 7945237, 41600708, 11844722, 65265347, -17270926, 5047425, -31135447, 60975653, 9157525}, {-15792503, 19784533, -6958908, 5608070, 781171, -11283938, 24272321, 432561, 1613055, -13163005}, {21513897, 9636317, 16941719, -6911072, 6195929, -3671325, 22791277, -14570606, -14700953, -10948616}}, + {{33070143, -10765333, 25103670, -11212169, -12402674, 18423482, 49348287, -5353246, 19708628, 4751521}, {-19124641, 15715391, -21079244, 16965343, 7229218, -2226310, 11745475, -21568376, -4773822, 9908963}, {20883861, -13761293, -1522628, -14785625, -11823055, -5836644, -31702871, 6202713, -14389333, 6429013}}, + {{-11223367, 9697587, -16427304, 4474359, -3392450, 1554389, -59409700, -3167599, -15488847, 8272507}, {-1992285, -11115335, 10389108, -24898801, -63334200, -21692137, 5519670, 16655461, -37762011, -24713223}, {-30140237, -16218231, 12775094, 15125862, 3890378, -3728490, 10472548, 6560970, -21966672, -13082644}}, + {{34168899, -3485811, -28209517, 28775381, 2302824, 8320216, 49024020, 4318521, -5533315, -9380818}, {23647575, -24091067, 4047869, -3725269, -13858824, 20395678, 12041412, -10571409, 56559289, 13382532}, {-14715844, -4451100, -788220, -13945913, 12870848, -3520187, -24568277, 14413924, 31674092, -14163866}}, + {{-8933277, 19450408, -27687797, -25259231, -6301687, 15620015, -62311319, 7352453, -37907278, -9143933}, {-11319961, -5873170, -1989343, -6264895, 7859775, 17647595, -1742729, 14421953, 28821682, 8809}, {23015648, 5308572, -21881258, 14710766, 6858446, 12585267, 30716303, 9314280, -17397279, -9354899}}, + {{-22082137, -7230564, 5140405, -9409185, -10273540, 20543491, -46279432, -7773660, 5107999, -20657602}, {-12411819, -6960452, -53879503, -10241687, -49373306, -4627803, -9618562, -14654672, -46208021, -3117826}, {10393974, 14869052, 19368793, -3280110, -8659708, -15809183, -20313348, 10911522, 27192683, -16200195}}, + {{16349460, -13126197, 13146431, -1111546, 29461269, -12594359, 8895140, -2187638, -9766695, -3297816}, {-17120700, -6995019, 15340103, 12094536, 33467457, 16063025, -35182096, 15999426, -52282685, 20048888}, {3493927, 4160370, 26629316, -12296895, 15033159, 9309960, -32556256, 8393376, 18158430, -4881495}}, + {{-7169172, -3379761, 27359109, -22709263, 11040054, 22141768, 22373571, 269576, 3767580, 13538257}, {47694186, -239293, -23191091, 5600227, -50256446, 867788, 15746955, 20662518, -2343950, 607267}, {-18444565, -9996701, 3087961, -13584228, 4563432, -12519946, -23085936, -15217747, 21879690, 14546420}} + }, + { + {{-5194639, -17405206, 12246799, 9986762, -6317394, -7160137, -58574601, 9056940, 54692645, -16024377}, {-49065489, 7814000, -44469597, 6546786, 11290552, -4685507, -2130541, -6279448, 672321, -2895325}, {-8375034, 10820574, 1172628, 1905088, 15930430, 6361886, -17706862, 3371162, -197968, -8645992}}, + {{-26427495, -22741364, -26845176, -10271264, 18066812, -26723285, 4723313, -7963587, 13780571, -1244501}, {30665383, -5164136, -18325886, 1192976, 17727240, 4673639, 51223995, -14734927, 31296541, -24445765}, {28800614, 7788910, -9626102, -9373933, 18176018, 16434454, 29271334, -11709612, 4676187, -14110139}}, + {{-3947612, -10754833, 27591523, -27467688, 52133421, -8929969, 45487466, 1515672, 43342755, 17872513}, {1280422, -381637, -25447861, -4119862, 12742175, -19779443, -20013910, -27800488, 14275151, -6363545}, {-9479163, -3758477, 11737093, 12702205, -17637712, 10363181, -19355887, -12578140, -9396983, -4776752}}, + {{2096513, -2267196, 11936679, 1782723, 20448771, 11778946, -19475709, -6099403, -43536990, 25367994}, {-34096629, -7171850, -28317139, -28745247, 28947737, -17050368, -19085329, -7896939, 10344190, -253598}, {-31290702, 9800542, 11290998, -9464834, -19598255, -2161841, 12873495, 4689289, 22954164, 13514304}}, + {{-3787120, 3973012, 30558934, -25709373, -61620640, 19443021, 20468873, 15111302, 9225851, -19454170}, {-2748378, -29020866, 4385170, 2185963, -4233858, -8297455, -43689849, 5607494, 39333339, -4273002}, {-22648318, -1360902, 28875203, -15070101, -32848173, -7465791, 13736107, 8320313, 26426802, 2774517}}, + {{-16067241, -2791905, 4046103, 21113860, -17899048, -7267429, -4789130, 4183094, -13998320, -2476735}, {7591683, -17845351, 59286301, -11317040, 23158166, -4217383, -18301942, 27269986, -31214972, 21888213}, {-11165442, -6027294, -24570471, -13115491, -1401089, -16204326, -19616912, -187756, 19605199, 7170146}}, + {{19272481, -13839902, -13039890, 1437516, -10582784, 3982984, -27483243, 7376024, -41926009, 29385359}, {-34790885, 12009258, 28590, 20870862, 25497374, 28724304, -21349539, 483196, -18318997, -1175729}, {9229787, 6165257, -27305092, 8748874, 31704322, 9094389, -20225216, 1016337, 21874897, 5964388}}, + {{47302564, 11715632, 627035, 7025881, 15340764, 10151256, 14562363, -5840511, -22115537, -11899643}, {15477906, -19921498, 16159813, -20825445, 37392754, 11999780, -50034227, 19923643, 13353775, -21373517}, {-3453479, 4121616, 4612837, 14947539, 5028183, -5409464, 19507391, -15370708, 11765359, 7397361}} + }, + { + {{27076818, 4524251, -34226325, -19462953, -28535350, 11770006, -19392859, 29406929, -7191906, 26037625}, {-2677336, 916831, 28740215, -11380649, -23568166, -4562024, 27088031, 2705799, -58172370, 5114555}, {-18501073, -13529826, -5813540, -489954, 9077115, -5099869, 19502351, -11229239, 19357306, -11398725}}, + {{-46911801, 863915, 43881108, -23891609, -26296305, 2968177, 34048949, 4665302, -31275000, -10769706}, {-396939, 24161397, -18867668, -2860891, 32136939, 5313905, 16644033, -1038800, -27250952, 7741148}, {16746505, 12865776, -21968774, -203381, -9105630, 13163165, -32465242, -221738, -33424817, -3062980}}, + {{-8210801, -26209480, -26679135, -15480950, 12303016, -6048446, -3492734, 10531172, -25038375, 23046362}, {42590927, 287556, 17584803, -9046782, -38841108, 5190, 23196008, 19971946, -18424177, -690238}, {-22401260, -6810210, -4122210, -9473286, -18524699, 4687565, 11145141, -11649840, -3844979, -10677206}}, + {{52306617, 12584365, 22664274, -13132153, -14847854, 1983428, 7941050, 1083003, -656554, 15296442}, {14719121, -2093329, 15606776, -8606493, -27328422, -4205130, -26554306, 10329115, 12649024, -9038552}, {-18470727, 2509443, 20553916, -11220716, 1033280, -8460030, 4333659, -242755, -22473618, -15635893}}, + {{14545158, 8832150, 24650238, -10787567, 47634984, -1737658, -7934640, -26997285, 12105430, 8353682}, {-42390788, 14686046, -29717384, -6798805, -12825344, 27213328, -42349040, 5549975, -6549564, -18933724}, {-29829740, -9294276, -29488424, 5325172, -12746994, 14209437, 18113419, -15318009, -32007530, -9731684}}, + {{-7800316, -19075152, -25543723, 4672022, 4948390, 17415014, -28512674, 257557, -14855162, -757655}, {52915554, -4793556, -39212767, -25519070, -7460576, -12082014, -6147096, 22056243, -41293964, -29224299}, {16192336, -4280048, -11362898, -11497151, 21377601, 360081, 6472272, -165764, -2516455, 7287911}}, + {{-1322555, 11190443, 58060280, 7606875, -21936236, -6852947, 56142145, 15639580, 12468310, 8497246}, {37756747, 9685009, 4460566, 5668117, -20704860, -20981389, 5158869, 8983688, 37507162, -16248348}, {24185168, 13891564, 20630317, -9688438, -29541532, 11312669, -33288378, -16739778, -25340631, -7348754}}, + {{-10122935, 12057038, -10118730, -10095215, -31143731, -13646125, -7593764, 29724284, 26550398, 7084395}, {-52212269, 3335262, 38828316, -19665313, 5683557, 19150955, 22359824, -2289626, -13464534, -3115701}, {25567444, 14101706, -29034029, -1802169, 17624061, -10644450, 20839963, -7953766, 308794, 2161336}} + }, + { + {{-53632147, -19297912, 7851043, -19252445, 14673089, -7540948, -5053916, -13567430, 13041628, 2702244}, {3265277, -3169432, -52429811, -9234543, 42224393, -7535492, -10346398, -17435050, 42830034, 26763220}, {-11499612, -407539, -19405702, -3417701, 28667824, -4712709, -16633706, 14287193, 27529852, -14804943}}, + {{-8301357, -14900350, -17375714, -3660324, 47967085, -4543541, -38274004, 3281764, 25894277, -12561246}, {20987349, -16326790, 4110462, -12897112, 2722633, -4901387, 22350170, 6963924, -26307375, -6443544}, {-2563812, 3599819, 18829948, 3183156, -12197117, 5129877, 29150342, -14897435, -19190851, 2122615}}, + {{-16069099, 14771196, -14778229, 15381287, 51127423, -8635291, 27351265, -16501607, 17994466, -16222381}, {794113, 9191748, -15924201, 15412365, -15533765, -21467457, 6308539, 6843923, 47315244, 15799959}, {10088614, 5952697, 27537331, -1544805, 24574773, 13924786, 31119711, 6301629, 10303499, -7287322}}, + {{7075939, 18188428, -40247109, -16502560, -7223662, -25685700, 22637065, 2884203, 9026750, -22469568}, {-49597223, -13630182, -11524239, 9975492, -29541480, -7017266, -36556527, -12297061, -39503516, -10762316}, {-29976429, 7980108, -18082939, 9182347, -33445980, -10362838, -17271146, -11680127, 4699758, -16708223}}, + {{25341363, 11776665, 31744444, -11419676, 243644, -25427420, 31957294, 8004336, 4446158, 9676944}, {9159503, 19691573, 7788124, -9120656, -41866304, -473450, -22633936, 12391048, 9397710, -14761412}, {2176050, 3093922, 28099816, -4056095, 30379992, -12625193, 25514304, 11141377, 9537024, -11749925}}, + {{11874013, 6619415, -45978048, 19241982, 34593233, 11566782, 18188546, -1365421, 17464619, -4714579}, {28186675, 18734191, 11704546, 5057494, -5844419, 7578296, -2670132, 21398537, -25437539, -2813399}, {-29773614, 7521501, -13581548, 10189780, 10221976, -9641327, -20027861, -16116914, 17230353, 1768638}}, + {{-3254002, 17609610, 23438741, 10401967, -29386498, 15470644, -36983910, -13296870, 13417255, -1309952}, {-25997506, -15766158, -3848077, -16853213, 30112220, 4704934, 19839126, -815994, 42172439, -16667738}, {31601561, 4387898, 19403396, -8066749, 1731270, 13103102, 9654742, 13702377, -18212837, 9952789}}, + {{-44139895, -15956322, -1957914, -2500572, 4566616, 10111288, 28971372, 2891716, 23352576, 3717199}, {-10910821, 1666028, -31990134, 3797314, 47243712, 16585440, -9724960, 11409606, 18148620, 15664225}, {21172951, -8001181, 23183655, 432573, 30241199, 4892338, -28903830, 8610070, -7562878, -3980656}} + }, + { + {{-11816810, -19915072, 37188575, 6470387, -31312211, 13246135, 20092706, -7506079, -15718424, 715126}, {24022790, 1956096, 8841263, -18290443, -31127755, 16005317, 40649566, -2905019, -34241314, 20967056}, {13055553, 8117336, 18719627, -10365508, 18397015, 14640603, 17467129, -1986190, -320941, 8361948}}, + {{-14521183, -23769948, 21191246, 12247482, -3562472, 2707409, 10434951, -16936371, 5782639, 25639197}, {-51048857, 8631686, 32411618, -17284250, -3407982, -14563907, 32796079, -7019501, 52589169, 5372049}, {-32250310, -9817791, -32637302, 3725332, 28293155, -9050488, 20728637, -10324377, 27717987, 16267042}}, + {{32023888, -783150, 4785230, -17138565, -39648428, -31034576, -40383990, -3634561, -25769739, 7689973}, {6912362, -7909410, 4303540, 966043, -6096238, 33366, -3787830, -3292555, -1326115, 8539691}, {1381231, -696710, 15240934, -6947313, 25439302, 7832102, 11958236, 9121109, 32276529, 9721629}}, + {{15611385, 10451860, 7671020, 14013035, 16120236, 7361510, -4011236, -6487063, 17796936, -3693871}, {-39353005, 13952346, -47949076, -14003915, 4003532, 22499616, -33360884, 20534449, -2972380, -14582167}, {-29390304, -14549954, 30381525, 12364253, -23605127, 6869491, -17326770, 979791, 30841144, 16060616}}, + {{4080064, -12497594, -44198573, -8081902, 14616558, -7768002, -41675050, -8377750, -29772327, 4705291}, {48835856, 9779674, -15927079, -14998518, -41701442, -14682958, -24688548, 12322916, -16759627, 4709337}, {6589560, 6227897, -23163418, -8970289, -12171602, -2919728, -29547009, -1785520, 27672278, 3650290}}, + {{-22091384, -3625527, 32715760, 3651334, -58539472, -7090241, -16937807, 3169616, -24203624, -28036760}, {10376200, -24403595, 21025242, 14294718, -6449086, 585479, -41405829, -21889836, -36418472, -4899164}, {-7327120, 14833697, -30806744, -9850547, 26681265, -3568703, -16608041, 3541556, -2412469, -1012658}}, + {{-32676245, -23992860, -32952502, 1989465, 3238914, -2336243, -16914311, -15838377, -6014409, -16522751}, {-5851991, -5958798, 2445376, 28237383, 60531312, 638899, -291729, -8874337, -26232113, -3597917}, {-28173937, 15302781, 26271996, 203601, -22845788, -3307013, -18135061, -15871767, -18926213, -13496340}}, + {{-52426849, 21754560, 10090652, 5337450, -15538526, 1801084, 45714336, -17116940, -58319637, 20128327}, {413919, 5706932, 11535956, 4627188, -40617692, -31734786, 10899228, 5962722, 1024087, 8194973}, {18337047, -7284893, 7491958, 10525473, 31961567, -1678768, -1547025, 14371604, -22744796, 4698159}} + }, + { + {{43351150, -588882, -36366579, -26056933, -9619574, 6925998, 31478572, 2692096, 24354711, 2682425}, {20923520, -24204434, 21893893, -5408851, 12914668, -16049166, -6993296, -21602360, 469807, 26686163}, {9339777, -8207030, 4314230, 9570787, -3516856, -4024696, 33090081, -12756335, -30468354, 13396906}}, + {{9203288, 23961019, -26767913, 5516456, 25105329, -18076407, 63608830, 4060334, -15052739, 13229365}, {-1348838, -3556357, 10475321, 25265070, -33254321, -11599699, 2857072, 23309682, 22732619, -15901463}, {-32525251, 12169067, 29336863, 4101986, 2151670, 16052581, 22276645, -11493640, 12676394, 10258694}}, + {{-17554809, -13787712, -11025142, 14876753, -40118174, 18974318, -21578599, 6796514, -4053262, 8677611}, {48568723, -32020, -35620496, -11274647, 19006276, -1767732, 7662943, 4925442, 56424884, -22047261}, {29743608, -7733462, -12177671, -5865054, -12183413, 13583398, 10721348, 2811407, 1213662, 9131075}}, + {{-23816021, -8048064, 7868206, 26337902, 19324726, -1399859, 9702712, 19484799, 46764827, 17231076}, {-38024843, -7221068, 49939882, -5860408, 3327122, -16446701, 21964702, 6789343, -19098923, 4737778}, {29374697, 11481730, -32802579, -4503681, 27181806, 10360625, 1447634, -472403, -20234666, 10334446}}, + {{41668297, 10359775, 8669632, -6178194, -21825744, 11802716, 24802855, 3427172, -25778662, 350618}, {1230315, 22325029, 7807580, -1823752, 10186616, -20560370, -28424085, -19670254, 38957216, 2824804}, {-7886425, 6499919, -23283594, 12359535, 965805, -10236454, -32549462, 12052952, -3758080, -2471270}}, + {{-5547854, 19784999, -35447435, 20553317, -17701114, -13187984, 38467376, 1171395, 9365841, -7062164}, {-56513536, 9696009, -20127221, 972081, -14231294, 8821764, 17262234, -6139307, 51949033, -9436610}, {-4687806, 5999100, 25178467, 14797599, 6952404, 4546284, -15627092, 5991648, 219807, 16032050}}, + {{-1047468, -7243345, 47365456, 23365970, -35553916, -18767485, -25391721, -13883062, -53555913, -9484644}, {20495300, -23001887, 3392056, -2125134, -14556524, -709017, -21609347, -11561124, 349451, 1294384}, {7676867, 1006260, -3758076, 6765762, 28290455, 13072227, -11609734, 3166723, -674222, -1134818}}, + {{-14972664, 17633897, 1692511, 185566, -21244527, 25518826, 7394720, 4751801, 29267882, 19972782}, {3928634, 14533081, -24038345, -17238092, 40171657, 1175224, 35340550, 22960517, -20135988, -5866276}, {3652859, -1778288, -33487780, 243434, -4743221, 7049705, 3082275, -16457788, -18804698, -7144338}} + }, + { + {{55331044, -1420309, 4435479, 880031, 31089417, 5467239, 54079640, 27991572, -28455899, 7854713}, {-4121464, -21536325, -48237411, 29665535, -14298975, 18917965, 6477192, -4128210, 3344415, 13060395}, {20285583, -1135092, -24544630, -5255955, -25710050, 9403569, 25174527, 495402, -32916698, -3009540}}, + {{-3153458, 11796963, -15716455, -16741866, -17429005, -7030645, -12176607, 276827, -411254, -5332283}, {-36493560, -11175759, -37255759, 8658492, -17112879, 18763657, -28083777, 5905875, 3154188, 609487}, {12273567, 15749129, -7429755, 14903661, -301173, 865323, 6457533, 6428510, -5953631, 6259914}}, + {{18617203, 8815703, -12153981, -9554751, 34912102, 11514624, 758291, 10163248, -11418724, -12025821}, {-26115019, 22708635, 2086307, -8941743, -2498150, 5363060, 39909701, -20358666, -29782214, 6119971}, {-752715, -12596371, -56598, -9459133, -22132101, -5358562, -19423309, 11966194, -18210258, 5690985}}, + {{-26520151, -29215183, -2253624, -3348221, -54325373, -27573751, 10957145, -25991202, 7653165, -15497401}, {34099361, 967115, 58612226, 24239965, -893363, 2849437, -25248007, 3763624, -27612985, 11542815}, {-20772267, 14145173, 5282971, -8812179, -7078260, 8921497, 11940792, 10279761, -19464323, -8010440}}, + {{25813128, 16480356, 22679498, -16049051, -26598203, 27580462, 34953514, 5601637, -44501, -11843411}, {-24733698, -1961384, 15201966, 13112221, 38209529, 4157132, -19844052, 9816241, -45732865, 1367475}, {19351532, 2382159, 27418270, 4524477, 2503389, 10539383, 7846614, -5738295, -32795192, -10752993}}, + {{11520857, -13340536, 15491968, 26289791, -6372351, -3173916, -37363664, 3995146, 15417852, 1129412}, {-4305067, -6282000, -31514358, -602935, 18198007, 4142140, 8691400, -21592724, -32500830, -24545160}, {31712935, 3292838, 8835775, 6582377, 14669388, -16006981, 7471269, -4726128, 17614270, -9248409}}, + {{-25775103, 249526, 18505028, 25688636, 8967600, -27361044, 20105651, 16235853, -7335341, 7387083}, {-10584561, 5040868, -13182150, 2344132, 25998968, 282136, 28758755, 15095675, 8647171, 12932595}, {3950884, 384926, 10816601, -3063259, -4401418, 10769962, -28456035, 11676938, -25115260, -6146523}}, + {{-6677137, 12328716, -16678017, -2379406, -29707775, 8666753, 6060062, 4945120, -24351387, 6195581}, {-57759185, -9754408, 26491971, -8899700, 16611093, 10609973, 25225046, 13811756, -14235955, 16118427}, {-33021547, 10353715, -30309957, 13458071, 29472936, -1856233, -18910184, -15721056, -11724525, 1838630}} + }, + { + {{-12779114, 17814598, 9239159, -3170050, 14621128, -2679121, 5908225, -10464729, 4260814, -10774047}, {1889722, 14432906, 7229891, -17837374, -35444232, 30144593, 35835389, 20676355, 4715542, 8290169}, {29833003, -7400284, -8366833, 766560, -2543398, 3834907, 24315777, -2101078, -1435092, -2602241}}, + {{-13682017, 19857047, 6817675, 13785135, 4367821, -1040013, 535585, -5601948, 48929678, -3956130}, {-25745197, -4229737, -27877193, 5257331, -59618795, 11766533, -14198617, -8883652, -14726808, 1267258}, {-26727260, 9005423, 31812111, 8781886, -18526320, -7055834, -18816509, 5439406, 29536692, 9974094}}, + {{-21267201, 18105230, 1083455, 16094635, 27393470, 7683511, 33072266, -2369824, -27676569, -19852422}, {14754309, -4117502, -1777927, 8089063, 2108552, -19123433, -23738930, 22149874, -4630903, 265854}, {-4889417, 12389622, -23363648, -3918822, 26063762, -5273380, -9616626, 11353698, 21231496, 6111283}}, + {{27797966, 19826492, -10461777, -4091506, 52836276, 14186155, -24277031, -17159288, 26299275, -4668060}, {-31605914, 12637110, 47660677, -13376080, 13010250, -7889567, 24028743, -1663304, 36064107, -7118774}, {-25005770, -3561701, 26194375, -967881, -1382406, 2544746, -30285897, -12719084, 31220348, -5596773}}, + {{-10467, 22955672, 3411582, 2704035, -1351543, -13479051, -35912531, 8562645, 2597061, -676511}, {53760723, 596788, 4630358, 20615363, 7523231, -6986771, -6767329, -20320143, -49467619, -25896591}, {-17790000, -9956849, -1824537, 6140131, -8411040, 12088420, -16159680, -13117618, -14291890, -12872811}}, + {{17995859, 22254211, -54008885, -11288046, -8815298, -9819763, -11675856, 21929989, 8303064, 5889278}, {48546871, 2485065, 7920073, 8942916, 22525378, -9888759, 7660488, -995037, -6845272, 22512440}, {-28333343, -500191, 21873009, -3807879, -20817827, 6650332, -32238067, 5789174, 6554628, -1701304}}, + {{-2051226, 5442098, 46135450, 1835909, -14243459, -21188523, 23811933, 28086848, -21490573, -9636746}, {-38839776, 8066970, -15057216, -24537195, 32155947, -3789769, 30490089, 875290, 22694133, 22235590}, {19095043, 16671712, 31277513, -11165139, -7692084, 10667847, -31097462, 4723628, -29147100, -9587365}}, + {{-15119167, 8814272, -5174893, 26643847, 36097719, -12590537, -45059703, -2666881, 28587804, -7335038}, {-16289069, -4962940, 10285903, 5254617, -10257473, -8946379, 3335545, -28042491, 6431198, -10650104}, {30038894, 7725118, 2808985, 10736215, 15023633, -9406449, 10497389, 12045126, -27094617, -7548629}} + }, + { + {{14918785, 18024772, -4722298, -4424152, -6076214, 2304917, -1706576, 1208063, 21016376, -18211117}, {-17327411, 14808258, -30060848, -7069016, 53967720, -19620835, 63589680, 1112827, -9712322, 6550357}, {-1723307, -11804555, -8589229, -12134750, -28201370, -8188855, 15157936, 8755658, 4195758, 12686901}}, + {{20914772, 9115799, -22056090, -5818874, 26663128, -18071637, -4934263, 5199490, 19322986, 17648253}, {19856262, -17965947, 25643562, 7863524, 6595748, 1288697, -57895535, -25350548, -39344646, 843711}, {-9420126, -15553069, 2424906, -10198389, 19420543, 1033386, 29818850, -8136028, 11164437, -1236018}}, + {{-33498136, -21636094, 7616807, 11089259, 40667805, -8362729, 64000, -15648705, -3125491, -6908722}, {31362760, -11080620, -45897793, -17501295, -6431949, 11603447, 3359312, -8832559, 16344239, 6756022}, {-19871429, 11694145, -32861505, -13666198, 12591691, 2861761, 25663027, 16736068, -12965933, 13879093}}, + {{51027461, -11163235, 16469464, 6657424, -20311839, -6717721, 21748092, 20378605, -28072861, -1110054}, {8460111, 13797263, -30167508, 3847426, 5683747, 16866133, 19569376, 4930909, -17835641, -28075440}, {13558742, 16398711, 4344721, -14106344, -7583263, 12087066, 32447873, -12969717, -967399, -13532136}}, + {{12074185, 7881773, 26469634, 2638374, 12839268, -8384330, 7629071, 8732121, -35756987, 659600}, {42181985, 8960393, -3534036, -19125798, -34219226, -8021704, -58068487, -19679081, 888127, 6105738}, {-2756963, 13596323, 25849130, -3226454, -2209421, 263891, 12153527, 11673404, 2839249, -12420891}}, + {{24795253, -25810134, 34311448, -64578, 19467911, 25523867, 6824412, -19014212, -18028036, -1244695}, {-18626657, -6609900, -28261860, 19242644, 31222285, 3097585, 52859228, -12713832, -17247356, -25502553}, {-30585191, 14658695, 32758140, 5017987, -19319587, 4147693, 16328924, 11544909, 31354105, -10014276}}, + {{-35899892, -3360190, -1409677, 1927137, -40801073, -19297291, 5204966, -1571298, -13085851, 19409965}, {-8680608, 25637368, 16526103, 31471237, 8496117, 3137959, -15456740, 14460736, -46852731, -6883247}, {1073308, -14496333, -29239477, -16342522, -192958, -6688842, -6293045, -7109357, -2298146, -14025476}}, + {{-15182674, 2513800, 4912099, -21331461, 63424337, -29130680, -41842028, -12762921, 15037127, -20913842}, {-18270498, 30316820, -26347623, 2496021, -2661307, 1918928, -23230248, 14368073, 46305879, 8375506}, {10274789, 14728503, 32886420, -14214374, -24656508, -12470783, 994457, 6486555, 31976259, -2064185}} + }, + { + {{9990203, -5967259, -30332837, 1055274, -18783335, -12780352, -21409809, 6219889, -39376677, -20652491}, {30876017, -20522249, 22246067, -8056110, -21244829, 1336982, -36898153, -9493909, -15913415, 3256617}, {23859788, -4043697, -16223224, -6754761, 9896599, -14885134, 31298122, -16340146, -12250956, -5305952}}, + {{-53319311, 3106654, 8721301, -11395142, 13140040, -9129418, -15357883, 7203076, -38674320, 13888072}, {12605857, -13192576, -49237133, 8613668, -36140560, -7851688, 15805915, -4180380, -997028, 10789668}, {-5297326, -5777508, 23302902, 14842703, -12562807, 11020072, 2987886, -15082645, 29774821, 6247520}}, + {{-37564715, -9016525, 13794389, -18536733, -1032967, 10506215, -9922525, -14568811, 41830860, 12975603}, {-21916819, 15871973, -6306461, 14798307, -62193347, 1770329, -20035489, 13914217, -799588, -8987421}, {651070, 6371430, 29015104, -12763830, -30584778, -543170, 22140204, -9608478, -30165575, 6322648}}, + {{-25144413, 520510, -3729071, -23346798, -8240287, 3991741, -7330644, 8639522, -21362215, 919329}, {-10483395, 31191720, -62299449, -561558, 13189023, 3120357, 27786486, -22321778, 43469341, -17397899}, {-25322560, -2061845, 367197, -11394346, 20390480, 11750136, -14206323, -9047122, 31199947, -16650219}}, + {{-41299908, -12790343, -28239884, 12445701, -20762490, -32194987, -31455913, 4740323, -17248352, 2771031}, {16221936, 14750765, 35569402, 4954223, -12518312, 253349, 18576205, -2779111, -34541718, 25337427}, {-7973759, -5847015, 25455621, -3879582, 5139126, -6373795, -15407115, 13219501, 13308272, -11727506}}, + {{-45941112, -3476303, -12717164, 27994331, 40824020, 14135375, 37778174, -2091169, 35585628, -3824899}, {19724364, 3721529, -21562592, 3959139, 18430156, 5219205, -842232, -22301357, -27212694, -7721703}, {15652879, -1922681, -26056293, -13276870, 25823596, 1502634, -26171908, -5297454, -17206011, 1798182}}, + {{25513553, 9228159, -41225286, 1075272, 27566243, 26740475, 847083, 12721834, -23652663, -21583787}, {34329181, -3898851, -4680698, -21651996, 30934081, -2986925, 56667207, -13616386, -11872671, -6419859}, {27711615, -2610993, -29650256, 479315, 18032972, 8495595, 11809682, 10764680, 16163597, 11782681}}, + {{-1080167, 20913279, 11222009, 5231033, 19586685, -19081404, -25560724, 3060413, 9369581, -21037334}, {-55853605, -604871, -30586595, 11184291, -44377297, -12410506, 546040, 20831127, 54768427, -2020408}, {25111202, 4937874, -19359157, -10888901, 52262, -4871270, 6947793, -7167452, -2708633, -13933048}} + }, + { + {{-37490698, -1044014, 13172992, -15792835, -29278609, -21703359, 17587066, 13822930, -25063775, -5408585}, {-14506614, -4554562, -24975322, -15121369, 31918211, -2815099, 9245590, -10494948, -32218177, -20194407}, {33095577, 10772817, -30109058, 3735455, -903060, 11779796, -22276963, 5647339, -19898785, -2427259}}, + {{-35567230, -8298746, -30427298, -2008615, 6578320, -28333482, 4647843, -7203744, 21410852, 4935677}, {19449456, -12021944, 26998278, -20985261, -10001164, -3849334, -42124703, 22950244, -43841566, -2386869}, {6188251, -16387018, -26256516, 11523151, -27111541, -14694407, -30832690, 2347978, -9338022, -15708579}}, + {{15434287, 6643431, 23435499, 578214, 1545961, 6256578, 29410474, 5645137, 7298830, -1190423}, {-49873669, 6172407, -2815369, -13320018, 17718471, -6647968, 35792074, 26128923, 14935630, -3855593}, {-6561401, 6082764, 10619558, -12080069, 3736379, 8205603, 7726617, 15485177, 26425072, 5964669}}, + {{-19009143, 11144788, -26170506, -7469698, -12042595, 6769324, -46424487, 7188576, -54190, 13467043}, {14833485, 15106902, 39786628, 9576478, 7682467, 12427144, 18962549, 21453064, 46849696, 8135823}, {27102186, 4002428, 3820464, 8059627, 9296768, -16573407, 29427330, 6056765, 31299382, 11434844}}, + {{10147554, -3304203, -31566020, 7455365, 9054617, -7026253, -26004212, 9417844, 33148937, 5567818}, {-30957680, -15079499, 12503190, 12210223, 12492353, -13255867, 16087858, -1724966, 29065181, -16903384}, {-8689265, 16342304, -29112667, -13948144, 2271372, 13680506, -20647317, 11265632, -6271831, -13550605}}, + {{-43981712, 3667339, -5774353, -4127724, 49033143, -20763656, -4362649, -5585012, -6097844, 23047690}, {18241914, 18780295, 17835175, 23839864, 10367743, -7932052, -17351125, -10024804, -41459272, -8899310}, {-26184270, -13291747, -23818836, 9003362, -13056713, 1731343, 17126866, -15849032, -7620786, -15197126}}, + {{35225841, -17608455, 52560174, -14493248, -3202298, 12453088, -19300486, -146725, -3685468, 12252323}, {25224829, -5151489, -553432, -6461064, 803174, -6826920, 12356718, -14804525, 21520816, -19497989}, {31581702, 13887699, -11113271, -3509799, -29892103, -1339694, -23766891, -4379212, -27361250, 6521470}}, + {{25689009, 1301840, -32432264, 2041722, -9292384, -11455248, 16822275, -12529983, -25278496, 11030628}, {39827663, -23485080, 10195846, -28093486, 39482802, 21857762, 13689719, 16786591, -13165936, 10604194}, {-24235173, 6299697, 17500880, -4675077, -15297533, 1159291, -31114335, 4151979, 4511865, -337858}} + }, + { + {{-28331035, -932771, 25317856, 18389196, -1654470, -18747303, 20165848, 25259009, 40793161, 8387571}, {-31555707, 70687, -29207696, 12039632, 4692468, 10360981, -35700940, 5605229, -6454753, 10933815}, {-4039096, 13783539, 32581867, 8360647, -4024823, -13078472, -25287757, 8105424, 18055378, 15459087}}, + {{-31034575, -8782829, 4438967, 3487891, -3842866, 73696, -20992160, -632729, 40548482, -3821511}, {20154487, -12110395, 25790203, -14732921, 50263830, 17079256, 16189826, -24550693, -11591350, -27192289}, {-26957121, -232995, -25926181, -8068404, 28968615, 8439329, 4177301, 14600993, -12309690, -7683509}}, + {{15113767, -20210410, 9862332, -24270992, 6750959, -15722016, 57587876, -8785178, -14388356, 22486190}, {16294061, -10374390, -13940832, 5386570, 22589699, 14408744, 8621304, -7678460, -27908864, -1454410}, {-17932180, -11489769, 24239088, 7432798, 26783544, 13155981, -5946726, -1824310, 20243099, -16583330}}, + {{-5341368, 4089037, 13994677, -2321488, -25886605, 1955838, -17713115, 10096472, 22063283, -20840893}, {43013314, 10849261, -49484229, -12925370, -18395631, -3755188, -9363551, 20854856, 11741859, 10408771}, {-15708765, -13112700, 9648732, -5986263, 11569212, -979061, 16059478, 11274274, 22182219, -14445752}}, + {{54036905, 4378170, 4458469, 1068139, 33946900, -6741746, -29127999, -4191304, -33312792, -4447126}, {-11572087, -24675294, 42086451, 15598001, 26972182, 6198910, 22922963, -8631160, -22811142, 24506016}, {-3691007, -5680657, -4814481, 6540764, -29270991, 13196195, -662301, -7429681, 29699892, 11841653}}, + {{-35195742, 1316948, 19158145, -14467042, 15561375, 21590178, 6585959, -9918082, -29668441, -25037241}, {-16843434, -26783648, 18148929, 5763658, 23408021, 5201398, 24855689, 2985416, 36007991, -8323065}, {-26289045, 5805905, -297042, -2018399, -2687990, 1174877, -20931135, -12873489, -11140391, -13339997}}, + {{-4693919, -7359640, 3999575, -4185824, -28261425, -11290306, 57089848, -24004471, 6955189, 7297210}, {-27387317, 4854504, 63054037, -4958334, 17673385, -15681226, 507320, 2150569, -15708635, -10900332}, {19256573, -14400625, 9588188, -16152506, -13220658, 2766395, 15435464, 12740678, 4188656, -25347}}, + {{62186136, 8388256, -1011792, -2221534, 61444893, 4236051, -3754780, -9218215, 30908178, 342327}, {2923566, 16397468, 58662336, 16605610, -3674617, 561073, -53256148, -7100625, 18583054, 14876091}, {9460626, -5314354, -12636528, 13071581, 29516597, 16199649, 12119025, 7338875, -28755942, -8966924}} + }, + { + {{11511840, -1665259, -19136370, 6532560, 54685096, 5713989, -14697619, -4366344, -32184502, -21914214}, {1771640, -30141505, -20388968, -23647180, -423212, 23744461, -22796913, 17113446, 29916502, -5848786}, {15791191, -2109811, 14327684, 8764175, -17786032, -10430002, 4964801, -13412377, -26772786, 7688229}}, + {{-7902173, -6019250, 40686331, -24334672, -29056443, 6966900, -36105368, -28821420, 34143326, -15682381}, {-38263067, 13050516, 19137267, 6754728, 23211307, 25975088, 27086126, -2207410, 14310880, -13075993}, {-26941894, 8202847, -18600854, 921448, 11680995, -4671504, -27324300, -4380528, 23083931, -15469828}}, + {{-43940803, 6112622, -55306089, 11959216, 1735450, 6341156, 37310734, 26669520, 7354935, -9435487}, {-9665877, 17972374, 1946167, 16787448, 1956736, -694100, -6947230, -380162, 19480077, 5882021}, {7490942, -10521386, 19442185, -7215960, -14036843, -11619923, 25178526, -9062626, -24632881, 10852529}}, + {{-26492998, 11342117, 28884660, -8177643, 3439950, -12251595, -959766, 15748278, -8223278, 3943321}, {-18038654, 6403417, -34265994, -18153447, -61286870, 3856099, 11140474, 7165146, 27891324, -12776499}, {4577308, -15878030, -3903294, -7330277, 22428625, -6625135, 20662741, -2434892, -27534336, 4208334}}, + {{27688057, -5060984, 44641245, -6577389, 49639352, -2511484, 25822546, 17766635, -9184372, -8105914}, {29700193, 27440946, 8555541, -26919561, -1082862, -3528740, -28694946, -135249, 46942038, 8495726}, {-16920911, -8666716, 21343143, 12774679, -13739185, -12807704, 11544306, -10114116, -4880213, 9344665}}, + {{25176266, -6433898, 27677827, 313210, -16240450, -7181904, 30164031, -12338723, 5393388, -8005398}, {-28318212, -25699654, -24936345, 26738450, 37211692, 11983534, -22679709, 17739395, -14774276, 7537428}, {15535300, 7022682, -20799105, -7889266, 12927080, 3712147, -31972106, -10255157, -16621777, -11151260}}, + {{-24410108, 3479459, -41589759, -4447761, -18568451, 22663701, 32748895, 11115308, -12284407, -15389900}, {-6760606, -19837809, -19530593, 14152921, 35427657, -5027879, -15474589, 6745428, -14443949, -5772916}, {-15250650, -12583248, -28636511, 546259, -12004342, 15967832, -23455893, 2920967, -22538806, 5055360}}, + {{-2219393, 3321283, 8170070, -8617562, -20147954, -9278498, 35722589, -14081358, -19999667, 8982741}, {-33763235, -23843485, 221098, 15173648, 2296064, -7218468, 13278565, -6586432, -597671, 1120995}, {-27539003, 1778274, -22789481, -3688017, 14635861, 9115454, 12318310, -709741, -28204433, -16352670}} + }, + { + {{25257545, 11533366, 25218272, -2494770, 18802692, -2363380, -26097661, 14576356, -38512485, -5187941}, {-30381359, -20830496, 27741414, -28574206, -41514748, 4998680, 36635147, -15195432, -27578093, 9305681}, {16606172, 11705746, -14147913, -8770685, 31186589, -8644456, 31402982, 9388599, -26387100, 5576153}}, + {{-6148291, -11616611, -2001017, 4460180, -46961444, -993243, -17399939, -2775375, -19302330, -8036435}, {49979399, 14878019, 57820349, -6099824, 2891926, 12054841, -21659107, -24212901, -14593944, 10783693}, {-24091814, 12985630, 11144932, -1429148, 14875805, -2078873, -10111610, -7702914, 10846607, 13747257}}, + {{36911364, 10948579, -28413656, 24143747, 4515461, -3960858, -2348996, 27345124, 10316530, -24949901}, {-21692652, -22405245, -17453212, 8169457, -16515159, 12190660, 39981308, 3609692, 17157480, 3121209}, {6077504, 14029113, 4337395, 1306459, 9684798, 15918966, -3244009, -4229876, 21040785, -10798988}}, + {{7668306, -19090854, -5293078, -22956488, -38340520, -16339453, -34484174, 28548090, 31375307, 8091612}, {-51989388, -5808618, 3622130, 9231498, 8844936, -9458099, 13324236, 1509330, -30007183, 18296042}, {8831229, 2675955, -24740796, 1567748, 11964637, -4511275, 922779, 11925288, -23562635, -13199293}}, + {{-8459824, 17776744, -16794531, -1634377, 11496794, -17660299, 14450538, 23701697, 38902693, 26600308}, {21667500, -11524526, -34133815, 1769437, -17166618, 2763111, -10753286, -4172125, -18096967, 5418248}, {-12178112, -4909537, 25582507, 4680118, 7059472, -11280879, -9003908, 8866899, 13329639, 4238169}}, + {{42443042, 6292956, -2084303, -11763676, 24975474, 11368292, -30898668, 5572274, -45565766, 9398246}, {22723190, 312074, -17099501, 16350856, 8515958, 20547652, 8807846, 2765002, 15999424, -4068078}, {-30614567, -11470659, -19762629, 7071817, -24095797, -13388644, 29419234, -5810613, -20924314, 3837380}}, + {{-22469114, -19139340, -20702469, -14754774, -5718158, 18391345, -6231317, -8141877, -15897665, -18559777}, {-41031938, 10389662, -41776673, 3185884, 42439276, 6033273, -58815329, 683441, 7702333, 11399897}, {-21367884, -6025163, -12057795, -13996675, -27339696, -14111499, -31851211, -8971979, 26601810, 6660546}}, + {{-5232669, 15939098, -2119211, 842888, 16119703, -9667841, -4642603, 9814654, 32706526, -858959}, {-59608155, 3697050, 45791883, 2064118, 35254379, 19455477, 45614343, -18331084, 19371274, 25640931}, {-28281021, -1101796, 24885422, -15255417, -5592209, 10253751, -22422564, -8414043, -27911262, -10623034}} + }, + { + {{-55057202, 6378825, 19631718, 756405, -34988934, 4516814, -16435470, -4930571, 30624761, 20330609}, {-8208226, -14288525, 38404288, 8942131, -25299612, -25976524, 43933580, -7922601, -31050791, -10908951}, {8786645, -15297829, -12483842, 2869450, -9683319, -4239050, -30933725, 1062188, 27143818, 5886214}}, + {{-26737082, -1899955, -367625, 27274173, -8454719, -11179265, 13427152, 18642181, 47786141, -2273639}, {19969048, -19849713, 46685033, 3293785, -14767899, -1216797, 37244964, -3381615, -9556757, -24219143}, {-27567744, 9961330, -3088138, -13054108, 14790952, 3220167, 11478440, 8221775, 14761946, -6757723}}, + {{11826681, 352716, 23222433, -15455054, 42599497, 10063600, 23755789, -17252467, 21355038, -8827818}, {21775839, -15993184, 36435609, 3291826, -7381825, 16933248, -39535739, -8709807, -45486390, -14515174}, {30205341, -9479593, 2037871, -16638944, -2228154, 15931842, -4436386, 8631014, 6187979, 108908}}, + {{42318821, 19249862, 16194985, 2121230, -14990441, -12137969, 15615270, -2683529, -13323686, -16340510}, {13992761, -829274, 8933097, 4520642, 29444599, 3475757, -49197208, -26194147, -38686216, 14181818}, {-23798899, 2330895, -4652825, 14830432, -25678753, 7862970, 32146306, 149740, -20686016, -2171183}}, + {{13228166, 8683127, 29199684, 5702426, 44442457, 1826412, 28424691, -25618736, -4207569, 5199421}, {-22335274, 23961463, 4370798, -2889588, -17790505, -27266890, -34418235, -1614424, -49498341, -15752993}, {-31492371, 5156621, -6391078, 8593133, 24504251, -10312562, 563525, 5921880, -728680, 9599279}}, + {{21416355, 22195779, 16210636, 17033980, 24374302, -18731958, -3027469, 23784111, -45806750, -11451168}, {45145735, 11149429, -6951660, 14464006, 9971454, -379628, 42374839, -3726251, -16347552, 14823674}, {11795482, -1089103, -29916118, -11131363, -31036091, 10270300, -6711465, 11097938, -4371724, 5871181}}, + {{-11214574, 16908005, -12291457, -9603906, -1652526, 28466696, -9044973, 6916569, -6520907, -10285873}, {7762316, -3647905, 26127669, 7573394, -14182596, 1930208, -40489431, -785703, -48431371, -22612509}, {15935391, 2290505, 22952617, -12403000, -10101040, 8832520, 387081, 12538506, 31956379, -14946003}}, + {{-7686129, 137205, -4370712, -8918193, -4290947, 9475151, -20484825, -8423193, -33056437, -2554745}, {23723239, -29344125, -62499762, 5718101, 21573291, -4261653, -24657439, 19863043, 29031919, -25727007}, {-28374288, 8875243, -23132911, -2298412, -19931997, 593979, -7405445, 11680489, 13236130, 14839068}} + }, + { + {{-987051, 5562425, -11800666, -22103535, 8673924, 9678683, -14053355, 32972854, -34158331, -3338884}, {-34388941, -17948089, -52721330, -3615805, -51554588, -18737381, -50727173, 377542, -28652825, 19619218}, {11300961, 897205, 5130351, 13808650, -28542799, -10549305, 16340952, 6714098, -10660298, -2170878}}, + {{5790482, 6491469, -1330045, -14939952, 53564095, 5240620, -19790260, 969656, 16860529, -8405479}, {-20560616, -3707443, 53641243, -8691694, -748775, -25868396, 20842640, 21529108, -21913019, -9631965}, {18284543, 637113, 33128611, -13266843, -29697975, -7329960, 5200253, -11890204, -4071145, -1028192}}, + {{17888677, 20530997, 22220029, -18276070, 1663089, 3318263, -35915575, 29684594, 15354062, 10216201}, {-24491755, 9458137, -23127177, -13623564, -50085809, -23123747, -4156083, -3107162, -38248080, -5679355}, {-7819256, -10810159, -24715405, -11711408, 17617655, 2047218, -4024978, -15281372, -32865239, 4373586}}, + {{-51344261, -5158703, -7793863, -18441242, 9734330, 21318358, -46581642, 11058039, -54707399, 19439764}, {-3382543, 22542463, -50416971, -3924910, -6465114, -931770, -5429136, -21875927, -8590093, -11902142}, {-31960433, 9373829, -14915278, 14819514, 8095096, 6833029, 12171935, 8564995, 32065227, -11120642}}, + {{-16515561, -13196709, 27138445, 404024, 19894347, -3954293, 5339438, -9746382, -6588923, 6843627}, {30249921, -4130527, 31556997, 6593292, 6593869, -19282455, -26052504, 22029184, 5569383, -13916983}, {13674504, -14033856, -24276015, 4706385, -25265137, 2200830, -21480691, 4602582, 21098137, 701605}}, + {{21847532, 12175368, -12371944, -8104195, -25736914, 31845971, -60634207, -24155009, 12393531, -2287134}, {37929796, 8543650, -39600578, -10358787, -20684020, 1053969, -2757197, -5879487, 39244193, 5946608}, {8484480, -5939254, 14313729, 12410469, -20549288, 14398210, 18548293, 7100757, 2495604, 10724295}}, + {{16926943, 9336241, -2438882, 4471603, 20510598, -8651640, -11418532, -13753237, 28597327, -7267630}, {-16010267, -12762075, -18689898, 17857223, 12591056, 11098402, -48288252, 5804891, -3723889, 4365132}, {13764499, -8280239, -24942451, 4889060, -19904099, 727785, 4209862, -15163390, -7325828, 8495506}}, + {{29407842, 11465377, 37317837, 4655927, -30071787, -8993417, 11865876, -11075201, 16714864, 9510229}, {26949728, 14486351, 11630615, -25707221, 11735667, 13746667, 39706876, -18263647, 16171558, -4321793}, {-14293430, -15528155, 3488620, 5525440, -8146317, 3348549, -28951018, -9275972, 22227490, -14658006}} + }, + { + {{8341526, 9135376, 36559071, -18590417, -48714375, -19066806, 3627180, 11898351, 267776, 21143530}, {-40942664, 23890018, 18779557, 8871265, -14008243, 12620922, -104184, 6714037, -39469180, -4258372}, {11033913, -4888297, 16500898, 10571855, 9498786, -2249341, -21778808, -14301778, 24638927, 1112183}}, + {{-32059891, -2418396, 2874336, 1644452, 28119630, -780896, 29186072, -6247365, -26592247, 7877172}, {2366275, 8543026, 10691886, -3228808, 6963720, 13391140, -4845522, 10528353, 29250131, -10725412}, {-5657077, -16444590, 6995443, 1960854, 23986040, -2319907, 23781513, -10020120, 10326676, 12107890}}, + {{-7434652, -9185555, 8061655, 24720318, -5364033, 1840387, 11780320, 9824041, 23974906, 7822326}, {-1465520, -22967181, 39447969, 5215706, -25707159, -6114731, -12687172, -16978581, 37637112, 11131730}, {12773617, -1342447, -23786450, 5289410, -18847162, -2347558, -7839726, 4406978, -21344733, 16013542}}, + {{-36243101, 3070801, 34470044, 4639401, -7933367, -11783223, 31630698, 1849951, 6030251, -12527787}, {-29433879, -618021, 19941798, 23023291, 19799845, 7130937, -5349534, 18067503, -39078123, -13668197}, {-28927723, -10470735, 32230972, -10476071, -14028070, -15297342, 28119397, 15338897, 9961760, 1054851}}, + {{-25097562, -1321059, 28292687, 3727672, -31711122, -8653209, 30985925, -626922, 31016711, 23146477}, {33047704, -25929301, 34894649, -20896684, -31897618, 8834545, 7947427, -19361640, 16957405, -4073057}, {28044587, 9495890, -31940851, 10333746, 29762300, 13075082, -8375364, -15214581, 18651589, 13094016}}, + {{17213979, 11054986, 30533135, -3934956, -43588530, 478355, -37505792, 14964349, -386537, 12341855}, {13448413, -4693866, -23046777, 5235722, -13998564, -5167259, 12996444, 16679831, -64586551, 9052683}, {-30174882, 10093711, -26757581, 1084986, 8051687, 618977, 11146731, 13311402, 21714652, 19368}}, + {{17503336, 12363630, -49927974, 13612196, 42258047, -26268747, -40765390, 14503737, 36455904, 13310907}, {-45598212, -3129198, 9397682, 6570264, -19614387, 657789, 2074636, -6716569, -17993662, 2709105}, {5791858, 320094, 1215501, 1331958, 15210784, 3686874, 24240223, -4048687, 26876685, -7784262}}, + {{12793810, -1755324, -52080827, 18621135, 5803810, -5130130, -5634768, -11609347, -31596597, -2230481}, {50920392, -7032796, 321339, 2922571, 44466672, -23553212, -58540700, 2418495, -14131697, -23139655}, {-16121097, 14645489, -1367010, -8903827, -29838753, 5051785, 20140313, -12701143, 6017429, 603307}} + }, + { + {{404050, -7741972, 330502, -6081106, -51939030, -20431548, 26783096, 8633269, 7119109, 22345526}, {20912120, -23711036, -5336750, 11880854, -9651254, -359076, 34210766, 24432809, -17697159, -5715664}, {22458831, -12336979, 23629108, 16228749, -16861491, -3578057, -18947629, -14549213, -12447100, -5543440}}, + {{29093191, 17582584, -23163120, 1199904, -16158920, 26236961, -29484535, 13348310, 12176383, 6986504}, {-12320591, 5351896, -28844080, -23271960, 852822, 6570223, -34307581, 5655588, -44144655, 15067840}, {-31001499, 3972157, -13089882, -7611522, 13388450, -979320, 19561119, 2434129, -9204239, -2193769}}, + {{10062081, -5556064, 42967175, 3463476, 2554725, 7233097, 10758961, 20088224, 41065460, 16721167}, {9227033, -5471040, 11316055, -6232944, -12102343, 17841869, -35517661, 11900928, 3846820, -12410655}, {-10494456, -1357396, -19828924, 6937013, 2549215, -14791397, -6099912, 1952413, -8500482, -10563420}}, + {{-1376309, 11276878, 11963826, 14279110, 21775767, -5267980, -44242608, -29629663, -32566241, 6387326}, {-63261213, 16758266, 45407304, 10897038, -17274961, -21639730, 16962290, 1982899, 2489767, -2933976}, {-4368283, 16502157, 26891628, 13616133, -18161528, -15747170, 20015242, 6342508, 10520032, -4966647}}, + {{-39406051, -2813234, -8357141, 17831256, 10659844, 24511868, 15252319, -18060818, -614659, -3717078}, {15735657, 27230990, 25961169, 1534360, 41783784, 1332700, 31990407, 13214644, -44855883, 2608634}, {14156816, -11435795, 26857235, -15126941, 13609716, 12432857, -16937857, 5422930, 20368290, -9613082}}, + {{2475341, -6632035, 20617578, 13486704, 44146687, -2141, 21469294, 15768566, -7493267, 19637701}, {-28756049, 26812869, 43329014, 4954580, -1835737, 9411829, -25245990, 7723982, -35669253, 884141}, {-11759833, 6116980, 662187, -13313409, 32439104, 11791946, 31148147, -7273741, -2431450, 2135258}}, + {{-4922235, -5222084, 43014952, -17637310, 16286411, -30258137, 1613202, 14724323, 13638373, -889552}, {48928035, 26976454, 15692716, -14233376, 20185675, 3180091, -4011708, 13515099, 13550947, 4169954}, {2489717, -12340755, -4603758, 2457203, -21740260, 9369185, -24424090, 12201995, 31929392, 11461713}}, + {{5906009, 8158769, -17575, 11419456, -8639988, -1744376, -8382686, 8728158, 1878456, -77536}, {-9655359, 23316245, 24981345, -8574668, 42441016, 29193660, 33159422, 12778906, 36797796, -1311526}, {-10913350, -4107965, -28867768, -13873545, -1477459, -5372942, -7475698, -15717960, 22040610, -15630804}} + }, + { + {{46456823, -23535491, -26797598, -1260148, -12127215, -1531814, -5643008, 4798561, -6393937, -17797758}, {-12588679, -6404931, 30220700, -18842962, -43728663, -16072178, 33062136, -7484305, 32210625, 13434344}, {18269665, -12820853, -22130632, -7380028, 25497206, -6489483, 21663560, 14774309, 15215702, -14107459}}, + {{-51502018, -26654721, -16242613, -8207162, 13341598, -164756, -24240060, 13593316, -880047, 7281934}, {-11915866, 1932441, -26162873, -21455140, -53555250, 14119198, -11420984, -13346978, 18791377, 21538844}, {-4326243, -16321878, -5640471, 1617206, -28670839, 9802783, -2239304, -3321085, -16717219, 1237042}}, + {{-27149780, 7077606, -46683038, 10920998, 5295723, 27801857, 19910592, 20232699, -10232114, -4474841}, {19961540, -26112530, 1784894, -3938428, 5909123, -4644973, 7212108, -11699965, 41930782, -13893293}, {7936103, 11566587, -24367556, -8347490, -27200037, -1873506, -30028971, -14623039, 30853864, 5270946}}, + {{-6877084, -19091010, -45617631, 135087, -3868409, 12047480, 13655016, -27664778, 41310036, 2705169}, {24214380, 305106, 11556141, 16467973, 15778645, 13087470, -20210126, 4278430, -4411252, -1240137}, {6901797, 2223022, 17366396, 15250809, -18833319, -8020076, -24216545, 11984084, -14303230, -9915763}}, + {{-38037179, -6671142, 4355944, -11569093, -5275350, 23156277, 44586329, 319656, 20702811, 26469898}, {-9243193, -23295134, -27603604, 15430501, 26023798, 2537741, -7261677, -29732140, -10784125, 5716680}, {3777622, 3369244, 26282752, 6314395, 11639080, 7957693, -11901022, -16547275, 19116266, 12459246}}, + {{-40691049, 2778209, -22047928, -27209209, -19821550, 20740610, -45761975, 1535890, 7738640, -1910061}, {-25088877, 26262435, 41637190, 4129293, 29488220, 2090844, 19870777, -13590190, 27070674, 23775643}, {10612005, 2125825, -13957850, 6538830, -10288042, 11830865, -24317686, 10933861, -22220109, -16154094}}, + {{38562370, 14378227, 12484217, 19177777, -47355614, 26707819, 49377645, 251260, -43114316, -16602797}, {-26808892, -965889, -28117557, 8763997, 17407410, 5813345, 14923081, -12669566, 5464842, -1730965}, {21687422, -11430003, 18812409, -5130186, -7383548, -5236189, 6023111, 15787364, 17582223, 6892633}}, + {{-12032591, 10248317, -42585785, -3845574, 53986023, 20154060, 43786405, -25612960, -642869, -2918800}, {25777833, 15946475, -10544123, -16217584, 709313, -9444308, -19925505, 2291406, 5633127, 8717624}, {14988937, 5457937, -20743481, 12004409, 7320105, 10748807, -4363890, -14164562, 3243784, 6227597}} + }, + { + {{-22923850, -5555182, 40377373, 13604901, 12247301, -779024, -20841135, -13024139, 16307497, 15132661}, {21999582, 5224700, -3324157, 4773983, -28222069, -30489276, -3622777, 1324435, -18268923, 255675}, {31627320, -1226688, -17074672, -4781650, 5273733, -3066321, -18594146, -6957259, -32991896, -2977514}}, + {{1815644, -1914359, -5078016, 28164063, -55329536, -5411845, 16709725, 1267925, -55460021, -3130507}, {7206184, -6688241, 10636646, 2551779, 6257804, 15422727, 36221259, -1539373, 10162101, -2231089}, {31029007, -12422438, 3387860, -13582127, -4523047, 11861943, 21068164, 14029970, 1455735, 13002171}}, + {{-60437892, 25279933, 7268339, -26031520, -34648833, -2999157, -26186194, -2164710, -27072724, 17532815}, {-4153430, 3697419, 58301913, 4171216, -20060343, 829749, 18809056, -11075424, -26569754, -1472447}, {-19857132, 7885685, -12419001, -16535955, 14206520, 8160375, 25070127, 14223275, 30157906, 648789}}, + {{36559589, -15880007, 11516278, 21612696, 11872070, 3639563, -9565112, -8721682, -3242922, -13105382}, {16100215, 10511505, -39614918, 7273284, -18796566, -3289769, 40925738, 14513702, 49205668, -10624240}, {-30348338, 11601261, -8588238, -4401100, -10179505, 13961191, -21558654, 15064039, -7766808, 4247048}}, + {{-8426452, 6781035, -18900479, 3121829, 8967367, 6152656, 14348919, 29700380, -32822910, -11026791}, {-1935248, 20932617, -3389439, 3876819, 3112115, -1202918, 12971999, -2379052, 12591612, 10081537}, {-22529436, -8692826, 30381171, 3298511, 28481585, -16661393, -10852824, 7188371, 13445185, 5030737}}, + {{-35136085, 757273, 11365976, 21773803, 32987990, -25537452, -10618646, 2704790, 18476915, -19985173}, {-30242937, 23497357, -15476128, 9392379, -31525088, 2220766, -20084452, -29375144, -21070633, -1395107}, {-15427379, 15020848, 8334960, 3093430, 7358696, -3448559, -19345403, 15917153, 3260156, 3856332}}, + {{25027144, -5479262, -42810252, -6371772, 261777, 17186623, -8974417, -16194871, -25138105, 23534389}, {-31628594, 4089756, -11247582, -5757862, 64306869, 6963607, -2788153, -6243821, 38157095, 5890485}, {27034602, 12655182, -29407594, 9777026, -21467567, 12867916, 7964266, -13385223, -11734950, -10171169}}, + {{-51075004, -20344219, -1458929, 14018787, -1652907, 11800757, 40150506, 25248275, 28859508, -21625891}, {-14879998, -675609, 28433595, 9789929, 18944317, 6642099, 5430144, -483869, -26095342, 6999495}, {9286180, 7442362, -7028254, 15839862, -6598437, -7501046, 26460087, 3091629, -26965804, -10770393}} + }, + { + {{8728274, 17051302, 8600130, 3624135, -5853975, 11796199, 8110745, 3531605, 3638044, -17510793}, {16047072, -8173472, 14466736, 8273501, 59415349, -4521159, 12177173, 8035379, -48293432, -1154197}, {-8301373, -9195531, -15897839, -9757666, 17168039, 11557098, -1305837, 9889389, 27398697, 16382160}}, + {{31709505, 384789, -22135475, 284026, 33005822, -19797065, -9515371, 2236752, -25813971, -19150546}, {13541913, 14549455, 21976781, -32339968, 13483854, 8695097, 49848275, -2836762, 9562407, -10453222}, {-22834552, 3304728, 14613251, 8074645, -3858624, -15144087, -7827521, -92062, -24346779, 746851}}, + {{-22760032, -3379324, -33872202, -6549210, -11906093, 5063730, -12639066, -426272, -45295500, -9416033}, {-21196376, 14022434, 25600942, -4343276, -40144475, -27922354, 7230886, -28798928, 11258374, -11087789}, {15751392, -15199175, -4274743, -8868442, -24667940, -1574930, -5220072, -16174443, -24241625, -11627928}}, + {{29058654, 12885739, -1776644, 2476833, -19362622, -1535032, -2535015, -14799679, 17461187, 21474351}, {-25745548, -18423355, -1305842, 6190705, -11109982, 14895596, 37691773, -18231889, 13475551, -10009505}, {-4056015, -13025210, 3293376, 16184496, 7158044, 6599588, -12428643, -13162720, 1290113, -3890088}}, + {{30335495, 17486276, -5952509, -1180672, 21988768, 6582000, 27264677, -12569124, 35628270, -17628778}, {30113805, 7586420, -22496137, -19699052, 15857568, 12495578, 26467287, -11167802, 28668736, 12227052}, {647097, -4591418, 10303807, -14376937, 242186, -480702, 674765, 3609842, -10109818, -6469112}}, + {{20196954, 10979819, 29548427, 583186, 26115250, -5925385, -39841669, 7154129, 7696245, 10883754}, {-41434246, -16991743, -6511711, 9008446, -13930548, 12660829, -421737, -21252285, 50313413, -2219586}, {31319850, -16074086, -24140983, 307177, -5608349, 16213395, -26497910, -11795151, -24922192, -1202439}}, + {{-49065196, -4879580, -39622848, 13296055, -7149416, 10001310, 18161241, -17865154, -17347704, -22833707}, {-14156954, 10321424, 22916654, 7321919, 27535496, -2323716, -10814467, -1117300, -19218440, 1296697}, {-11882811, -2514678, 26403745, 13711217, 24270415, -7464488, 9407476, -4569810, -30789642, -5954590}}, + {{7541117, 6770422, -23074921, -18173687, 30761719, -19429178, -37300486, 2176346, -28442655, -24712383}, {52316953, -10265214, 42525907, -1056833, -16651657, -13156788, -15128680, -8060864, 25419135, -7537035}, {14618434, 4926921, -24487582, 4021056, -29619859, -8812469, 27667633, 12037151, -8168237, 1839658}} + }, + { + {{-47265079, 15044385, 27967853, -5989120, -13949326, 17765209, 29258884, -16204684, 33286176, -7078615}, {-17287243, -5199215, -11335005, 24399378, 48066896, -15159427, 24447920, -2235590, -14578446, 17598295}, {-2821248, 1791599, -22157216, -9605755, -4830261, -14079271, -8004687, 16636639, 19641394, -11934374}}, + {{2700555, -20264511, 7576935, -16467834, -33915860, 3308658, 33301737, -3821959, 2431901, 10763276}, {-4339597, -9002107, 37050817, 14093368, -33022044, -9947096, 2080221, 12291707, 10700443, -2423406}, {-24570320, 12286179, 32096498, 14866908, -24023771, 10476507, 3101048, -745752, 2131008, 3905640}}, + {{2066568, -17118783, 31691983, -17980245, -48769966, 20277627, 17875575, 4834517, -38291583, -6082975}, {24750766, 9014861, 19885069, -5749069, 4837512, 10025491, -28740283, -11827173, -11103423, 22647761}, {7467605, 16178466, -28121660, -1439327, 3505647, 15941077, -24010595, -8922211, 19879397, -442436}}, + {{-19266702, 6359181, 38504427, -15620108, -19657947, 2370404, 12394637, -1150843, 12634671, 4724772}, {-16323372, -2874755, -21448441, -13297556, -40210257, 11324608, -34245109, -29959117, -34049545, 23022456}, {-24390449, -15699014, 26846832, -12727572, 12784032, 15832708, -25400430, -7908507, 14474076, 16662407}}, + {{11312008, -2341146, -5169014, 25104527, 18241336, 24625254, 13837791, -2898199, -4701851, 13134951}, {54146394, 24027340, -30243094, -4816993, 9011646, 7851636, 9314351, -20090509, -32220851, -8382357}, {30847011, 13013245, -12062216, -12016233, -15198633, 4462233, -24774898, -2328568, 29420201, -15080900}}, + {{13844983, -1768163, -28630150, -1945930, -30326231, -12863663, -56988115, 3536346, 25782786, -7355188}, {46409187, -19417123, 12452258, -29612192, 20077523, 2739989, 8108487, -21229602, -22184726, 1292384}, {-6082331, -6285247, -12403758, -10970529, -4298154, -690180, -10234638, 14465308, 7362888, -11116200}}, + {{-26821652, -7763053, -45210230, -7051423, -572961, 2751508, -35704515, -11049191, 56659004, 4751779}, {12316490, -8734715, -8343274, -8891043, 22989299, -3264194, 523855, -5937901, -998662, 28246749}, {-1937941, -8328216, -26181039, 10006101, -25155749, 5936680, -6133181, 4549091, 27660263, 2195433}}, + {{-1951595, 1204779, -36912737, -7354312, -2040302, 10978640, 8351774, -6738966, 46654365, 15007657}, {-33248491, -32003065, -18897305, 16335018, 27823660, 7176086, -40563684, -19547746, 502543, 18540735}, {18699843, 8239701, -16138985, -11477323, -4459333, -3286544, -26068838, 13219267, 23288971, -13002950}} + }, + { + {{-39086040, -9139271, -15802662, -14561742, 24298787, 23731258, -10092461, -10641140, -7332530, 17738188}, {-11666546, 21185089, 3351980, 2388784, 40170541, 9007700, -13344185, 3263560, -42827248, -7835024}, {-26554159, -12547841, 11827677, 800092, -12775000, 2948320, -4804345, -8984531, -9893513, 9852661}}, + {{-28548133, 2207511, -2426156, -4381836, 3543792, 3282897, -9996535, -15778566, 53390566, -4399737}, {-35061477, -31004671, 38499408, 3563278, -50566546, 2528317, 32655573, 3048894, -4886652, -16167111}, {-12311587, 3865772, -22341946, -13841850, 11325227, 3405904, -25313715, -4268399, -20462952, 11414295}}, + {{-35793880, 7173705, -40932727, 1440566, -499452, -2732388, 9611134, -22591999, -30833, 14243192}, {22628784, 17708971, -9099979, 31102546, 62241852, -3145648, 46558730, 6683383, 8715915, 14522198}, {31100735, -9289283, 6683360, 6500820, -5018632, -6670026, 22752090, -13728784, -3284671, 9112387}}, + {{-9520996, -5641012, -10624066, 3498994, 17802577, 13376272, -25029438, -7176059, -11001963, -12399975}, {-1286004, 8699394, -47540094, 18058700, 11730635, -8313304, -7800784, -19732961, -7282187, 7263453}, {29710087, 6492136, -26386898, 1708539, 1357589, -2570452, -28141072, -15133121, 30091876, 4246345}}, + {{-266389, 11426632, -31615458, -1414069, -22879186, -10518565, -14372145, -14663465, -11883820, 13923297}, {-37127355, 19941626, -31071518, 1515345, -43234864, 9242989, -2106319, -2850553, -49265312, 19048827}, {-20015165, -3147341, -25385089, -9131901, 8512033, -347015, -12828402, 10378369, -1606157, -196000}}, + {{-28278546, -2049463, -16258570, 15757294, 48818856, -9457235, -5936047, 30097589, 20307641, -24341972}, {13005642, 11565419, 21631530, 15362938, -3532144, -3704381, 53767877, -2268977, 25962833, 7126498}, {24950461, 8374617, 12989681, 2747021, 17679041, 13404353, 3626542, -12855331, 10528185, -1143695}}, + {{-33425850, -9739004, 11380669, 17918867, 7189368, -13248264, -17594339, 22434556, -12614809, -22982276}, {-33140152, 12022716, 29479353, 2484187, 38602976, 153634, 36401593, -8048456, 31604181, 8190276}, {24767633, 11452180, 15130812, -3406247, -14546597, 15891807, -3157181, 12064601, 29787307, -4660625}}, + {{-28850999, 8829007, 59072466, -9735468, -23179130, -6363735, 9157187, 6901090, -16218080, -2173370}, {-37858901, -13000853, -2776800, 7679436, 28986496, 21156063, -21148173, -25323428, -47509784, 23078896}, {-10412415, 8568171, 2891528, -6240979, 32956538, 4892991, 2498371, -13053880, -19314114, -11533260}} + }, + { + {{-6798592, 2865990, -19870192, 2217994, -8034107, 12309066, -7133459, 11538679, 57505907, -18309735}, {28096866, -9649308, 15274128, -12615726, -50929929, 9475814, 58365117, 912027, 933059, 12088251}, {-22355268, 1502605, 27500451, 15453435, 15111070, 9700576, 26503320, 3611306, -28850031, 3359397}}, + {{-19631592, -2464233, -10589012, 2585665, 4999749, 352148, 17531454, -19707786, 1418865, -19460977}, {-19566470, -3313379, -25880908, -30537833, -7916383, -19822508, -37322214, 10720204, -50741555, 7686261}, {4336617, 1227470, -654152, -5911688, -19480893, -9945594, -15385990, 16260592, 15785293, -14667016}}, + {{-28973032, 14147662, 20455909, 4507057, 1415984, 12652605, 694189, 13069043, 889603, -27166604}, {-27236136, -15069186, -31524717, -14535279, -40756674, 5977525, -59918157, 19233159, 15824999, -1622224}, {-32312952, -5820342, 32069839, -7356037, 13981799, -3941953, -10830463, 16284281, -25288312, -3703752}}, + {{-20782860, -10275499, 11045596, 1927035, -45827724, 9628686, 35695506, -17483530, -41277323, 3277006}, {-33466152, 16373195, 20612170, -24240265, -8773878, 11911034, 25637830, 11302862, 8286629, -11629948}, {-1415775, 11002899, 33180965, -5015538, -20316680, 13784087, 20294380, 6979821, 29547283, -6881147}}, + {{41186940, 21363252, -14606938, 2084721, -13837673, 6056516, -42121285, -7517846, 18262785, 6833148}, {8863438, 5031930, 50291188, 22741977, 15258335, -26282646, 10839273, -6622668, -6496259, 5530736}, {-2663101, 12461283, -16935567, 5513486, 32103531, -13450651, 6734378, 11801712, -6888115, -5894605}}, + {{-40737929, 283885, 11032750, 13073453, 27081140, -18568468, 18976944, 1463142, -33869259, -23725473}, {13815539, 7947577, -31858250, -2062353, -28472314, -12188652, 40099138, 22643320, -30060245, -4670727}, {-13546593, -9778820, 4483917, -16291673, 15345496, -1322602, -30175900, 13087670, -19502906, -9894161}}, + {{-51458984, 25466955, 26626968, 4989301, -3831619, -18286376, -6066743, 11910020, -36604178, -4737300}, {9294614, 4208111, -5159362, -16255537, -48309591, 2523444, -53932033, -4193178, -4231388, -8214234}, {-5822256, -15877538, 25304291, 10997483, 33520679, 16235718, -16594075, 9453350, 15193436, -11702926}}, + {{7513104, -1302983, -30758065, -3180399, -26836242, 25193640, -51864366, -15347565, 28696554, -537298}, {42721804, 25993825, 13921233, -4846033, 34545258, -2121612, -12000000, 3353441, 29517028, 30903198}, {-30158356, 13596867, 543864, -16389812, -9077550, -16367201, 460417, -16279319, 20863560, 10144047}} + }, + { + {{-4308726, -7761298, 34810064, -581777, 48978698, -19750524, -10205100, -25782686, -38701263, -10087552}, {-5441058, 1628912, 13871134, 9746575, -9830696, 7716160, 3125930, -1388950, -4132795, -17148064}, {27394240, 5593938, -2918651, 2394704, 24372047, -11764024, 24447171, 11424405, 11420526, -5782788}}, + {{15906666, -19985369, -19171361, 13031394, 25527102, -6243850, -6343134, 6651889, -781445, 2696038}, {-45350286, 6488585, -44537833, 12583966, -1465378, 4998382, -36330436, -2650059, -1741275, 15441722}, {-31894236, 3009576, 5227337, -10729943, 21389375, -6671001, 20338060, -3851759, 22951285, -12757211}}, + {{-14453187, 8175100, 4207069, 1243877, -24179117, 11062394, 12783317, -10793213, 21070435, -17844326}, {51156507, 11012832, -52003911, -4186075, -25413723, 15071934, -2072457, 16415021, -278333, 8633138}, {-25034748, -12655786, 25139144, -10181834, -23069772, 4590711, -19569450, -4241464, 7712811, -13492146}}, + {{-9934525, -3757850, 22432462, 963498, -15708635, 9983624, -9666020, 16117851, 2998544, -5059373}, {-16015009, -22190720, 23595696, 21083842, -875089, 15938140, -25278368, 10122107, 10401816, -1537031}, {-21476348, -2146882, 16301341, -6566558, -26860592, -4098336, 24051928, -2581646, 26112716, 9955914}}, + {{19068167, -18375999, -2216334, 4694057, -12007904, -62763, -25783231, -7266226, 41166542, 21748339}, {-27066991, -1262081, -50656950, 20222863, -948176, 29538865, -5687709, -2112042, 5991758, 10101383}, {-31607825, 705687, -12058053, -11379024, 9280883, 5524815, 11293838, 833453, -24702623, 3430888}}, + {{-37666253, 15013045, 16972156, 4486451, 12430995, 6340369, -11266788, 12224290, 31436469, -18503575}, {7485707, 14336629, 25843236, 26366269, 49241431, 24476935, -34119870, -2367448, 7044707, 6357487}, {20030467, 12615520, -13961332, 2068738, -8958093, 10787560, 11507305, 4144883, -18868406, 12835569}}, + {{27213136, 11907390, 7994644, 2046027, 33697006, 8354926, -2677475, 5040073, -1390254, 7790874}, {-21523416, -15386820, 59067854, -8932233, -20584000, 11773766, 12383219, 13232631, 18386530, -8604402}, {-11429204, -10415045, -14047623, -14255914, 15280216, -3236912, -17652895, -5269741, -12238277, 13158926}}, + {{-20892869, -2967, -15699107, 4981142, 8383424, -2531192, 50162938, -20871788, 16369001, 6876718}, {29561145, -31464577, 20738735, 26176828, -1614538, -29702704, -3861374, 239286, -20551569, 24034322}, {16746666, -14221941, -21795265, 1348851, -18661573, -5632707, -3540875, -4390284, -5616955, -7730410}} + }, + { + {{6154975, -1327631, 46895667, 5406121, -36071287, 15445555, -42232883, 9936332, 449254, -11525245}, {29299569, 8174717, 6903403, -12536407, 11104975, 6084711, 7451409, 15650704, -16881170, 4624275}, {23266700, -14093209, -1885983, 9133528, 12581344, 15638739, -10024096, -8658155, -2568111, 690476}}, + {{-25785424, -23733047, -42038847, 4214219, -37085773, -3219058, -29534247, -15120504, 2654980, -11178384}, {39906430, -390921, -2305163, 7139763, 12890961, -22673412, 7763845, -17227966, 63037834, 7278496}, {14166467, -16276761, -7428666, 12818281, -16359036, -1441680, -11120692, 7758049, -32872071, 9420303}}, + {{3872057, 12083699, -7989677, -26293176, 7892710, -5061961, -44473636, -15471772, -4463687, 8603541}, {22278301, 16417825, 38723645, 4238654, 358274, -18754603, -16096090, 7167810, 61931285, -15619787}, {-32849309, -13562471, -19524347, 8385958, 32690729, 7979712, -18218834, 11159938, 24949071, 16519111}}, + {{-43304418, 12381045, -2248602, 11637593, -34747294, 1140999, 42949255, -11283022, 2640681, 60384}, {-5658868, 6266775, 28658666, -12947181, 14062358, 9416293, 2526199, 3168970, 20732091, -12634886}, {-16540080, -12281379, -21912978, -8732011, -7627663, -6603379, 4845895, 6798936, 15629762, -15484118}}, + {{-6241358, 14123225, 7990304, -6230293, -32121522, 6788882, 1321877, 15579735, 46168100, 1094526}, {59521290, 17379495, 27093570, 13297729, 16419210, -20228708, 4701769, -17587215, -16197008, 16600488}, {-22981454, 13037600, 4804609, -13825535, 10859162, -13870970, 23705637, 1787046, 19305937, -3436666}}, + {{-43223096, 2424348, 3949521, 14665317, 15470028, 21953792, -8610620, -8137114, 29016300, -29868995}, {-8489914, 20596370, 50870883, 15582467, 36141528, 9136612, -19071800, 19951894, -28783952, -3210411}, {28663358, 8578444, 16773988, 3721180, -26100146, -13849438, -21816989, 3491747, -19508628, -10641718}}, + {{-13554234, -4269196, 14660944, 28220037, -12665117, -633062, -4175694, -1712187, -42118903, 12382487}, {24527100, -12082470, 41670592, 4157887, 2500895, -5634172, 37856426, 14476347, 9522249, -1318373}, {-31497721, 6490377, 10298222, -2004081, -27699338, -16401910, 13298222, -10447333, -29806091, 15052234}}, + {{-32188752, -30812149, 3288396, -1168348, -32742669, -827708, -2619825, -16507606, 27538821, -12857524}, {-6853712, -1414445, -37850348, -9050828, 32827241, -26059954, -32472691, 6433306, -26839769, -3855226}, {-10516253, -1903386, 1136364, -13884075, 4108212, 14678247, 6986091, 14058543, 15629290, -12069165}} + }, + { + {{19043048, -11158751, -22412791, 19580575, 29030423, 5952440, -20550561, -2968156, 48293408, -7373061}, {24848376, -1930831, -5866097, -9884885, 19302533, -13288180, -9918159, -14807388, -7432200, 2651987}, {17608058, -11179157, -17345761, -14881390, -7393602, 13602629, 20769287, 14553297, 25663193, 2863240}}, + {{-36697212, 20408385, 2155539, -13979836, -15026041, -22353110, 3836020, 23525635, 6440003, -562694}, {-25836354, 4525637, -2890603, 18188312, -31155367, -10743650, 19765218, -1507607, -26046849, 18325092}, {-3854072, 5901665, 10838121, -6460548, -13969838, -16334174, 22958429, 12934534, -7811105, -4349524}}, + {{37684334, -6945567, -43334493, -257316, -56193161, 18008017, -12031414, 10099613, 3630258, 18484523}, {24144678, -11489249, 10393199, 19646648, -3681003, 6727115, 48969088, 10517589, 40864878, -5711797}, {-22124624, -4687825, -16694937, -1206589, -3408745, -4324170, -26084442, -14630587, -4272268, -1486019}}, + {{37238966, -8225776, -10422896, 13925140, -21500222, 11799383, 9434773, 13601467, -1393114, 31674193}, {-21438464, 7639226, 43423348, -2306904, 44846712, 3807553, 14168045, -14211745, 7538526, 1511183}, {23049310, -7397764, -15930122, 8913438, 8113942, -11271712, 11802400, 6801972, -11756002, 7481414}}, + {{34973879, 3854583, 2240915, -9171425, 32182406, -11477749, 2486667, -7668072, 20920187, 21468109}, {12190257, -23300205, 54210245, 1034593, 5793784, 4046317, 42521059, 19926768, -29945111, 10577783}, {5483467, 5537708, 31270988, 15853568, 31465905, 12697548, -15644379, -14831462, 32704069, 12734655}}, + {{-17315785, 31223134, 18941656, -11524168, 48402250, 24344403, -25607204, -1068221, -15307045, 15880342}, {13643125, 299248, -15784310, 20405378, -14160558, -5260651, -38817082, -4590997, -40777683, 9211568}, {14538963, -6980857, -3878247, 9216616, -4863854, 8594013, -11160520, -9333194, 11435004, -15077899}}, + {{-24396246, 16764623, -43417959, 15166367, 8449472, -13141818, 5177336, -23728168, -20698976, 1223185}, {12960016, -10955765, -19862613, 4287407, -23274048, -19471566, -45301530, -3332884, 3796024, -29880163}, {-25411170, 8156721, 4536509, 13436096, 28177758, 5389321, 18254594, -12934119, -15770614, -6648705}}, + {{21546772, 16638523, 31137237, 5797275, -7541773, 12432411, 28110943, -7722413, -23581888, 2754516}, {17583014, -1544745, 17561387, 2716119, -40170709, -11243435, 8446453, -3157181, -12749564, 7412966}, {-21910806, 16605247, 26181759, 261054, 7265576, -15568518, 4857917, 13412686, 1262015, 11882132}} + }, + { + {{455099, 6712577, 28008806, -511803, -14627143, -17933537, -2516458, 2322206, -49930903, -6006745}, {-32946091, 21061033, -16052556, 19167397, 36021137, -7531661, 60158270, 23127510, -4742145, -5687399}, {31169025, 6976264, 16583672, -15934962, -6712272, 7236931, -31124844, 7303698, 20476326, 11538948}}, + {{-28260274, -7826252, 5609897, 14001160, 27218440, -7597269, -33781746, 22822893, -3006740, 5191276}, {-22246590, 3841106, -59905437, -1009146, 2299552, -24715251, -16349880, -4872415, -52866218, -18136214}, {-4678744, 5839195, -28817727, -16224902, -25312296, -3165444, -31665829, 2076739, 21905224, 12955274}}, + {{-21167818, -12343459, -43119910, -29459784, -29857002, 5305355, 34178604, -24028913, 31423389, -7488887}, {36094410, -19112779, 10016806, 2407594, 25150482, 9935463, -31037274, -2753143, -27766183, 9668717}, {9019763, -9878832, -32405854, 2812270, 31750066, -3170391, 29375997, 11143881, 17766608, 16435198}}, + {{39382705, 26245298, 49307946, -26536297, -12551662, 10015293, 52036244, -9245152, -2355717, 30895486}, {-23683751, 5594630, 16048590, 5908677, 22386650, -2636093, -57054, -13264714, 15503247, 1953626}, {-26885157, 16602373, 11192005, -8701859, -10517925, 9836031, 32722367, 5818327, 28925916, 5468368}}, + {{2173626, 716088, -7688895, -3935673, -33719332, -1573138, 5441090, 10409765, -17608416, -4928175}, {-4324294, -7210262, 29703353, 21579955, -30249226, -24243226, 33747184, -2585605, 45063606, 816423}, {-31484577, 9602077, -19039908, -2437135, 11013304, 1161468, -17723919, -10820529, -1937866, -5628742}}, + {{-40203088, -14634159, 15462880, -6622396, -696770, -20006949, 32803778, 8041373, 15364829, -527761}, {-11503560, 6334161, -36006182, -23969174, 65608910, 7743545, -17705244, 10866415, -44320597, -20011937}, {-11081774, 2271147, -3085285, 6381882, -10440829, -13618892, 26009551, -10488572, -15808495, -5097188}}, + {{22100181, 24475296, -6069968, 14668892, 56142829, -13972494, -51206120, 14528474, 26176209, -21167215}, {-36681749, 5632410, -19753044, 11913232, 7405039, -15879740, -8633868, 7232868, -19657685, 4119047}, {-14333824, -14956457, 27767270, 2279435, -18432412, 14744271, 5883425, 16402092, -22794933, 9448897}}, + {{7417308, 14032088, -37431263, -6738139, 40425088, -8120984, 19670583, -18490177, -22720733, 8015627}, {28870804, -16371842, 26932487, -17716287, 25968790, -6585424, -9262099, 977667, -40256557, 15633173}, {-25813414, 12599253, -15234699, 11816034, 12949624, 14772195, 29199304, -4412113, 8132817, 740828}} + }, + { + {{-2030230, 20618348, 31062598, 4018711, 56694731, 3989174, -2563829, 361570, 23437119, 6778967}, {43325502, -3542332, -28020096, -4061023, -3558021, -3169148, 235755, -10892880, 18530913, -2094835}, {-20222117, -14253451, 6758909, -706825, -30149299, 12653544, 2014140, -161183, -22008553, -13173419}}, + {{-43516037, -14086245, 28184267, -11024482, 60620925, 17431754, 39182614, 15751474, -18759124, 161713}, {4729683, -8069315, -1792645, -7208636, -56789, -12751630, 23458598, 13907982, -35420664, 198359}, {-5807171, 1099543, 7343878, 4583497, -5767064, 16155071, -33275584, -8141370, -21852677, -12312367}}, + {{17505893, -14046918, -26324808, -10562467, 21731961, 25803496, 28282100, 15979011, 22771019, 1597476}, {8854983, -7550666, 26040598, -17109827, 13712141, 7175168, -16264462, -16205507, 20496363, -22407094}, {20605360, -5970971, 11091782, 10193769, 29733876, -5046281, -28712397, -10884143, -27531604, 13637921}}, + {{8416581, -12374720, 12861292, 12145640, -57254515, -1988240, -11324726, 636145, 24087094, 25804437}, {40587133, 3594284, 37244902, 4080504, -8924063, 7006452, 34037594, -19084445, 12983006, 1090731}, {-19080442, 160026, 21222210, 14602893, 30451522, -10082475, 17497585, 5104507, 33024859, -4084859}}, + {{509304, -11633970, 29727695, 14560235, -19635227, 12528010, -29002291, 9233101, 228870, -26617625}, {11859306, 16012302, 6312131, 17493827, -11444307, 6022290, 6769927, 7971725, -6532882, -2093895}, {18370249, -12536324, 26233524, 10374124, 20779194, 12823119, -7314456, -7510601, 20728149, -6051812}}, + {{-2294574, 4576374, -14343898, -9686494, -40627092, -1657579, 21567658, -12834678, 50200945, 1374066}, {22741386, 22566322, -30018176, -22815168, -18295392, 11734155, -43870532, -11903518, -14914565, 20328280}, {21011817, 13149059, 14296848, 15820987, -28783032, 12996035, -30382383, -11958806, -3601928, -3137672}}, + {{41504363, -852805, -53234768, -1469239, -7490324, -2569964, -22966519, 2356435, -31750627, 13689591}, {-22384459, 6375005, 11586486, 22458329, 51888930, -19720468, -5675145, 4467951, 25467085, 1883021}, {26918878, 6967172, 31853010, -13731280, -27214586, 8270178, 1099559, -1979823, -23941717, 1287318}}, + {{-22166771, 2472850, 16401636, -6201821, 4597610, 7189329, -64612654, 2006293, 41489684, 7799866}, {13731431, 20612128, 46467752, -15330561, -25649108, -5523175, 746152, 1025145, 10213772, -7789908}, {-400784, 6883307, -21065306, 14605541, -6878792, 3135059, 24975218, 1852365, 10150954, 14928567}} + }, + { + {{24607714, -209575, -20404066, -14725257, -27010732, 5700195, -3774563, 3275553, -26699439, -17342658}, {-34332006, 24286963, -23539408, 11024237, 16581588, -1067749, -20525769, -19103199, 49863, 197284}, {-24655565, 4836455, -32607763, -6874765, 3293039, -9962652, -15676880, -16222288, -1582769, -14127546}}, + {{30505728, -13762931, 7066973, 31164960, -34523744, 18443788, 32795565, -21064252, -8757755, -23605120}, {-34813620, 5542679, 44130199, -909496, 10934654, 1510884, -26930579, 3301648, 56570223, 6277588}, {21433837, -7453079, 28548229, -12265274, 3070157, -12876735, 20459713, -4479937, 22946665, -15697418}}, + {{30913415, 7701282, 49015476, -10848782, 46414057, 623053, -3800700, 17025444, -25700243, 3790315}, {-26539703, 19996034, -12248622, -9340832, -19138601, 22641411, -42292694, 13824332, 32760891, 9700259}, {-27413992, 642997, -29628648, 2778992, 12236340, 2246672, -29815886, 13758802, -1110289, -8634591}}, + {{-10768286, 13883285, 40119830, -15270939, 24226394, 7454822, 13382572, 7222611, 26021676, -8385696}, {-42046718, 17146817, -12278880, -7449625, -21272636, -16967538, -1037602, -21155367, -26663156, 11881804}, {-18385654, -14956148, -14326695, -13461520, 28666062, -3855530, -6607651, -9927191, -6620149, 10051578}}, + {{-2371004, 9774777, 3803781, 5457594, -29927250, -12743801, -4352591, 262539, 691137, -7905711}, {58314158, 6327839, -42951677, 7873996, 18055152, -5109547, 30261705, -21651689, -43182039, -13520737}, {20669823, -12380627, -18244835, 1615510, 10283843, -13700563, 7447350, 1401693, 25383846, 6172176}}, + {{-22821906, 5488084, 21086780, -25558886, 22252680, -21699607, 50702206, 4327724, 24677981, -372375}, {20887362, 12058690, 22618110, 4539020, 26349768, 8900173, 15705602, -3794254, 13774527, -23541627}, {7468380, -7994630, -33268380, 7969418, 29999094, -5607830, 28248730, 2554714, -8674808, 12535347}}, + {{50659, 9867436, 8530474, -10476653, 30062327, 889699, 3030675, -2948987, 19420240, -15118129}, {-34279531, -17885776, -8955624, -18310967, 12012643, -31893989, 20434517, 24330161, 8445430, -11828513}, {-33133221, -5796760, 22274599, 4599804, 14989963, 11486836, 14135821, -12742220, 14990697, -8047746}}, + {{-61336608, 8593845, -874124, -1373303, -4756185, -21471525, -20142611, -13319568, -5876976, -5820787}, {3540074, -8091289, 3867720, -22455239, -48226401, -8514313, -28887731, -16282344, 60765196, -11589793}, {31379768, -8252534, 18313303, 1987366, -4803041, 760650, 23065504, 9740160, 10477923, 9247310}} + }, + { + {{-13741009, 26909276, 1241107, 15933805, -954041, -1452312, -20149884, -16412320, 34502400, 26150857}, {-38781453, -2036516, 10786365, -14546773, 64310057, -11486366, 22676530, 6678686, -20041108, 5000877}, {32820874, -6997790, -16859176, -11031315, 20460470, 16675995, -2420787, 2717162, 12584284, 6625237}}, + {{9022780, -14861876, 19059868, -14041893, 8194389, -6468749, -2792195, -665723, -15811767, 7197654}, {10776156, -3209336, -11798700, 12496483, -48377379, 4825143, 12922921, -18715995, -36753743, -14195268}, {11793976, 3804449, 28585923, -2963650, 31031643, 15655009, 19457944, -12192250, -28405142, -640594}}, + {{-15240081, -4032455, -42362123, 11846734, 24485029, -682507, -31321558, -2747237, 24890288, 18168131}, {-46657089, 26917229, 14850187, -8077188, 22343971, 32432621, 9355184, -14821869, -12220236, 4610131}, {-24507391, -9283547, 27152155, 6700897, -31611090, -10220025, 12401123, 763637, -26598113, -3417122}}, + {{27232184, 22336091, -17019043, 28439417, 25041529, 8684528, -7855730, 15280436, 26609024, -21823089}, {-18505354, -6813535, 33104155, 3101437, -662589, -2139912, -49858058, -16656438, -7632864, 162057}, {-2653248, -6577513, 26248188, 2540997, 8997775, 9693846, 15724053, 14411565, 29404978, 2294504}}, + {{-29352353, 7659111, 18307208, -5132698, -34923855, 2987786, 26940026, 19760432, -25790650, 27314455}, {-2734231, 18164883, 20381250, 25081556, 25161409, 16472984, 1828398, -12091628, 17271306, -2905941}, {-41192, 1114983, -28068506, -14150245, -26255990, -16678006, 4258735, -13459782, 22573379, -1984925}}, + {{39946682, -30419824, 12246211, -4314417, 36691407, -8353801, 45984250, -6054958, 8193854, -5201230}, {25882254, 600490, 12835805, 20344417, -6527017, 8815201, -17479928, 2883244, -1927296, -18971086}, {-7597807, 7510887, -30542614, -3227164, 19961694, 50261, 15533539, 9885203, -2494096, -14370163}}, + {{-27701408, -2454992, -16752906, 14268123, -34121062, 7499401, -40778319, -3526663, 963233, 9075617}, {-3911352, 13941856, -13668650, 1700501, -2375060, 13869797, -11142659, 16081037, 29487417, -24243933}, {17440201, 15732344, -30068222, 362868, -39844, 6029512, -4608024, -14684947, -4756, 11869296}}, + {{10119149, -1068356, 6736641, 188270, 59581482, 13772988, -45194379, 17322772, -27466934, -11605235}, {-51349923, -2585238, -28733843, 800886, -7233796, -3016776, 561391, -15370632, -20739574, 14178797}, {29930485, -10309686, -21239696, -16724754, 9322487, 7332189, -23348886, -13233982, 7762994, 14852945}} + } + }; + const precomp_data_t c_point_X_precomp_data = { + { + {{-9925073, 26743494, -5062208, 25549408, -23824429, -8353439, -8949217, -17987274, 12129322, 255445}, {1031237, -1929432, 33861812, 2513264, -39594719, -10522603, -42353743, 6231162, 9960060, 16637053}, {31813747, 15679110, -10191224, 16224642, -16487226, -6872092, -17580551, 8154917, 6688750, -10310772}}, + {{-26258524, 8249826, -11920146, 3220610, -24357770, 2758284, 33572638, 10160420, 29050799, -949892}, {-13180558, 17628516, 46801898, -14581552, -12176584, -18216314, -2631302, 3474116, -18397157, -5937320}, {23740252, 2896603, 16970314, -13205076, 53532, 7427132, -22291986, 10806190, 31874506, -16594478}}, + {{16623322, 18109907, 41423559, 5840730, -46771774, -19993, 20802483, -2611191, -40637520, 27693075}, {-8703592, -8836357, -19440975, 10495450, 6339720, -24160885, 37565017, 5918651, -4876836, -3083069}, {-31453716, 11855245, -23502269, -11985705, 25889705, -5314538, 29637309, 10820067, -28550748, -3813260}}, + {{7017164, -6897969, -33913710, 16583058, -8111349, -19406264, 9215154, 4350131, -44611155, 17532980}, {45411924, 6181163, 22622750, 1380856, 9222969, 12577204, -14000760, -28290001, -855249, 13913042}, {-12902741, -9688913, 25080009, -5038444, 5752883, -11873607, -9421806, -9565805, -18945978, 15802926}}, + {{-6101955, -14033093, 51429122, -10006715, -38781575, -13638306, -7164640, 9004893, -27181253, -8083663}, {3691659, 15570053, 1689402, -12800317, -26222541, 18378560, -35232774, -22877429, 38616177, -15390977}, {-15244972, -3907280, 14186228, -4066913, 20426089, 2483686, 12711062, -2570137, -912628, -14954285}}, + {{6276040, 4043466, 9840097, 338441, 4039527, 4572619, 17463228, 11584608, 18778626, 5603048}, {56126112, -16761180, -19107173, 22169291, 15049793, -22534551, -32149320, 12110460, -9403382, 22795358}, {19190418, -3110177, 14835489, 4377510, -14278199, -2822050, -14350100, 16595507, -9377841, -12291950}}, + {{2815092, -9621621, 41018428, -3528437, 39594537, 11866850, -52414734, 1419318, -8855129, 722048}, {10823696, -1907121, -15600852, 20928657, 16406711, 14276316, -6539620, -3186454, 36647913, 27546732}, {-18966877, 7522473, 6497539, -1590388, -3334580, 5380615, 17074346, 11369609, 26431835, -14438484}}, + {{-7166735, 1048159, -25949760, -1295085, 51229292, -15154352, -2022499, -20518673, -14230207, -23174226}, {26255677, -31929091, 8602602, -19027417, -5238014, 7479254, 25744591, -2675509, -27746215, -10299140}, {-22365641, 9338853, -18558509, 13708789, 14731619, 2442124, 20536292, 12086991, 25151000, -6539538}} + }, + { + {{-17021075, -1086156, -47131246, -13542165, -29424140, 2195133, -39945033, -22276920, -7282337, -11453561}, {27786437, -25084114, 4990714, -12465777, 20011752, 24561515, 767011, 9055026, 21277599, -4681673}, {9121598, 313272, 12015524, 9742163, -22229405, 12729123, 22987767, -8389509, -15264956, 838421}}, + {{11573410, -13935635, -5066484, -17416680, -17991065, -2069096, -24183113, 14208535, -10767307, 12879393}, {-40148220, 14456913, -33810098, 3432770, -17017009, 29326752, 14548051, 7893373, -31786859, -8932873}, {14518345, 8442387, -792876, -3670002, -11880446, -9677565, -29046681, -7419463, 16837240, 8745192}}, + {{-10591381, -8169660, 18482420, 15476535, 17119804, 9234289, 3416993, -2655518, 16936012, -18428353}, {-33344735, 4394610, 46182920, 7275483, 2439942, 14028071, 53750491, -10345208, 44840886, -8875647}, {-30859141, 2905823, -30189765, 11516754, -5605434, -8713831, 5303054, -6676518, -373180, -11645300}}, + {{4420245, -23788229, -29201201, 2914077, -12813981, -7469425, -46628490, 23492078, 27504167, 13974905}, {-49364827, 9087829, 2538539, 8768675, 30409945, -19926379, 20033162, 5476590, 26565685, 12524959}, {1868221, -15326706, 32811195, -10505065, -7928132, -419852, -10304072, -1816565, -6567458, -232855}}, + {{-9948680, 10338652, -40209746, -25851403, -7064323, -12113709, 6197722, -25056812, 18629073, -19644536}, {44958732, -20915350, -17356350, 873381, -24621469, -17392137, 20784430, -3526504, -28681823, -12180538}, {-28461416, -11105654, 7451953, 814288, -8844199, 813795, 9343984, 15837990, 18422838, -2907081}}, + {{20705878, -21114331, -40945256, -20308307, 9875081, -6938015, 60341196, 14675594, -6172905, 698001}, {38356990, 1606965, -5255562, -7503835, -49779611, 5332185, 5994582, 1466638, -4244565, 10134701}, {-31760956, 3554413, 21709994, -12125057, 23322260, -15347454, -24169173, -5832763, -6061945, -4852915}}, + {{-38153296, -15684075, -12330268, -15480639, -21241030, -1372824, -733088, 15431800, -7197638, 4386536}, {-27258378, -2735603, 14782618, 955633, -38527088, -17216618, 42881008, 214044, 43586958, 9041170}, {2575867, -13734991, -8036952, 7826637, 30781674, -4413255, 28134891, 14018278, 15475450, 8924675}}, + {{45207703, 15067912, -23507819, 676613, 11020367, -9893589, 2843960, -24371618, 16817465, -10001484}, {-18319171, -9311910, 35850813, 29870037, -4562115, -5235589, 63381246, -4824186, 3827303, -16647264}, {32865588, 6706033, -7660931, 8976827, 8006496, -12905440, -19842033, -14047132, 14857834, -15497711}} + }, + { + {{-22693092, 8017147, 29591323, -8080208, -6885791, 4571937, 20363651, 28828416, 6394698, 17166984}, {-20061494, 13152315, -17725009, 9457292, -21786217, 8691873, 17484039, -690102, 2655302, -2940198}, {6146204, 12560930, 18873445, 11923903, 27087197, 4596192, -27018806, -12348128, -9939415, -10205248}}, + {{50072831, -7019805, 2847706, 1627965, -9712522, -4973988, 19606569, -14135499, -1050946, 1407051}, {1840295, -3976735, 2716272, 720687, 38323264, -1774604, 9179865, 16150861, 33601464, 25583199}, {-21099596, 3820238, 33036488, -3887022, 20756498, 14956048, 1866130, -5557194, -13454832, -16269607}}, + {{6479923, -12555450, 13861880, 9268378, -15128239, -7433362, 23544668, 6779440, -54120528, -23623937}, {5866103, 9558424, 28247696, -5363770, 34812117, 18480860, -25246014, 20597862, -2015934, -1415437}, {21558574, 4502987, 23045216, 3464412, 8795334, 6481413, -14215967, 7868967, 10707034, -12940180}}, + {{4848948, -2686697, 17788203, -6140395, -42806973, -3126011, -12145118, 9756294, 18245466, -518932}, {33190324, 4089173, -38538293, -11668037, 18417269, 28454503, -34823286, 11108390, 9900348, -13650032}, {31446738, -6946210, 27988280, -8730253, 14094387, -10702688, -11256674, 15722699, -18254027, 4655186}}, + {{2775690, -4188982, -22064328, 6353788, -59271234, 379771, 1345222, -4160372, 34524416, 13627746}, {39502124, -2893462, -24282452, -23754812, -567730, 17162859, 17641658, -10974914, -4753646, 7124694}, {-5174634, 14108658, 16143543, -9702346, 31310094, -4068404, -17859348, -16192021, 26903079, -5209198}}, + {{-26044727, -17709228, 3714116, -17813319, -55797102, 10967436, -12110852, -16915226, -58986298, 19952785}, {1146995, -3849706, 8405880, 14968127, -10567256, 19000038, -17389550, -6936810, -819708, -5383323}, {25856642, 1227937, 29900997, 9382946, 5961425, -4744883, 27210332, 8613451, -32512286, -1906669}}, + {{-2997237, -26508410, -36133037, -18140637, 23078462, -18324638, -31053924, -17029633, 25000084, -11464033}, {-13122861, 3517674, -1337035, -5814281, -14781858, 9804458, 32208892, 1774463, 7728424, 14634553}, {3492189, -10152017, 16915533, 16634536, 9299741, -8779832, -5143673, -14176906, -23745225, -14643829}}, + {{-8310232, -11138411, 618693, 11923120, -31146167, 6722857, -22500141, -7864903, 29774140, 9674896}, {-8894722, 10567083, -18199573, -11333266, 28836027, -14154657, 27598277, 1141805, 17950008, -2385314}, {9789858, 12498604, 12737842, -2907639, 18619548, -9676320, 8707957, -742267, 10290691, -6486551}} + }, + { + {{13705950, 12450428, 9120030, 2465519, -15828491, -5562236, 37592515, -21358697, 12453347, 120814}, {-19566844, -17782026, 53185744, 25212389, -38821533, 17839750, 11456871, 3545255, 45083731, -6707124}, {26716233, -8638759, 3309314, -15895355, 7445089, -10101916, -25328595, -8358269, -3063496, 9172861}}, + {{5269805, 3639279, -41556084, -9881131, 839659, 14795347, 26835949, 15904041, 13126700, -1901164}, {-6952915, -24969237, -20179704, 5529059, -53620187, -10208001, -38743805, -1198243, 24168106, -506096}, {10298328, 10263207, 6861475, -9516241, 5270201, -9221672, 26729396, 16637124, -4694734, 7424148}}, + {{-37748075, -7288892, 4315129, -25874077, -9303427, 542817, 10671194, -15645416, 40859595, 3693631}, {-18546111, -6154954, -34931871, 3549833, -32374313, 12218825, -41429590, -8811818, -20954943, -1896183}, {17929209, -10979729, 14613278, -4466084, 21767705, 6905685, 6389555, -2300268, 4481916, 10678519}}, + {{-30898830, 16124895, -22984080, -5884104, -40280250, 28833783, 12667656, -9767390, -31285804, 16859115}, {-6053294, 1633667, -20072328, 14235096, 13683260, 2091841, -3212504, -8273222, -4702328, -6418859}, {9882818, 4628411, 29813118, 15987895, -14839248, 10604449, -25217399, -11319882, 22746844, -1187071}}, + {{-1915884, -3678535, -2246426, -7177863, -28347074, 14705733, 49024374, -8299944, 24245214, 280453}, {-64377298, 23591153, 62234218, -5717327, 13972058, -9658231, 2494924, -21795562, -13771174, -30735313}, {-9126427, 10912151, -5766111, 13765949, 30795859, -333123, -18879428, 3009229, 32082911, -2932925}}, + {{-36175496, -834709, -2640027, -892920, -36012132, -21161194, 21749145, 4321050, 34663554, 17748450}, {-21958692, 871163, 7932691, 9230934, 2677006, -119956, 23895867, -27471408, 25886314, 1942878}, {28528007, -14546005, 30045547, -13088445, 18380890, 15918929, -30103177, -5916713, 7313738, 11487581}}, + {{8432767, -24224946, -15556188, -18582243, 1345824, -13209265, -31025624, -9815700, -7814949, -2119715}, {30832407, 3088944, 50721150, 10899507, -25644184, -17859303, 17034916, -6078072, 5820017, 16813537}, {-17941222, 16449532, 11333308, 1321968, -13013805, 5565755, 19151187, -9767397, 17037669, -5091116}}, + {{-2172024, 8179575, 1451741, -15405484, 16866607, -11344101, 13140670, -4416747, -5617358, 10412573}, {23540440, 23568067, 7113067, 6554334, 34092659, -15644397, -21414620, -8721275, 45047848, -14660045}, {7500324, 2162073, 31143948, -14925908, 10715631, 860170, 24194172, 9222043, -7811541, 8635776}} + }, + { + {{33417021, -16477444, -12257057, -7665810, -44694155, -2003138, 19183172, -15823475, 35333901, 813879}, {25634161, -16286656, 54616993, 11397754, -13947065, 16533190, -39701202, -11821083, -13373597, 20341787}, {20823119, 1685608, 17501032, 2573292, 27721633, -16375351, 15431038, 10619705, -18295175, -4238392}}, + {{8369304, 13864786, -40937388, 635054, 11655695, 23402186, 16350073, -16089660, -25406748, 5144051}, {25354388, 12927444, -10327642, -6556414, 5503085, -9508260, -25581327, 12063066, 39326058, 4044659}, {-28124709, -6944253, -10857160, -12613978, 6601494, -6907745, -26640726, 5995244, 26707639, 8680838}}, + {{1157002, -25923892, -5114311, 13591500, -24861029, -5875947, 21241852, 1126622, 24697613, 19601732}, {-11984102, -5371810, -55230315, 83482, -29539457, 15163593, -23449488, 16668592, -30168265, 12985874}, {19802764, 8580221, -24653444, -929381, 750670, 3236963, -1172427, 6059417, -16734575, 13893210}}, + {{-22719120, -14677052, 20616602, -21048236, 8351548, -21171701, 36517372, 11239391, -1173857, -10069670}, {-25566894, 13221036, 21805880, 1885868, -7937988, -4227045, 22348250, -19700781, -63824943, 9382592}, {-32859384, 2108287, 19233257, 8885464, -5250139, 15331624, 29498046, -10485184, -2625716, -1310005}}, + {{12827255, -19954565, -32611118, -2985987, -9186835, 11164505, -25859105, -17815429, 15965668, 15498235}, {-40141975, 10457043, 10683464, -2791451, 10573731, 18433409, -20524007, -5182881, 40641240, 13911807}, {508289, 8485112, 9734998, 11170299, -9788621, 6240999, 30666318, -9079614, -28986462, -11826509}}, + {{-527778, 4743186, 15525988, 1608798, -15638258, -7475873, -8403490, -29431106, 14926115, 18524448}, {-4426554, -13172146, 20938868, -1510872, 32042520, -21426069, 46491348, 296950, -2351175, 14024614}, {-14057267, -3152186, 32396964, 16437300, 31379036, -6910223, -17758800, -13966108, -18898169, -3795220}}, + {{42823446, -21372965, -46746435, 29730653, -5498726, 11595227, 10202989, 5998412, -27981667, -8463264}, {-12879228, -7794387, 8905889, 2575659, -34146134, -12106825, -48282491, -18880512, -22270817, -10555268}, {-28245329, -6650204, 9884703, -16304671, -23417722, -1077640, 25012455, 6929759, -877869, -9767227}}, + {{2525725, -2218052, -26419115, -1321262, -4981994, -1472980, 17612658, -5897731, -27956222, 11094763}, {43857741, -8529860, -29685497, 29713588, 18054608, 2398264, -36055986, 11862259, 34729174, -1819829}, {9059392, -15013615, -21923917, 6249922, 20623501, -9365512, 14493275, 5484189, -20290605, 13306824}} + }, + { + {{7781197, -23872251, 24903650, 5464850, -9962504, 22597747, -214718, -10404668, -58092469, 19395897}, {58572843, 2397673, 41447104, 16449462, 19418334, 8293275, -18983198, -7914322, -6070561, -13199549}, {-9320084, -7902792, 9419833, 5179364, -17221978, 16748384, -14440596, 16450005, 22661752, -5959635}}, + {{7605771, -3209115, -18863410, 5402055, -50107383, -4544487, 2583286, 383747, -13334363, 7883980}, {-51198241, 5336579, -14593812, 27350173, -9246111, -19619529, -49340348, -14825927, -23997179, 24418786}, {-5725119, 14680141, -24409113, 8698670, -13043080, -5948038, 9922273, 6132427, -8237209, 14196159}}, + {{-11982836, -14437245, 25277016, 13787344, 6915674, -3178827, 89345, -2216600, 15143445, 26661343}, {36637448, -4390407, 32170910, 9628810, 2551210, 28282997, 46465813, 16632406, -24270017, -3590883}, {27494446, 9030249, -7253809, -15543398, -9001709, -6580636, -10418385, 14834819, 22738518, 13402679}}, + {{11712153, -4140331, 23847393, 7676907, -39571154, 530224, -22238313, -5527730, -34678102, 3620182}, {11933091, 498795, -17267417, -8846981, 5049674, 27385258, -15598879, 10612136, 29060570, -26309692}, {24486527, 1212661, 26010709, 9580499, -16677342, 2279442, 6943284, -3847772, 18149636, -1417711}}, + {{-8051127, 4117194, -12327491, 7343230, -20878, -14307016, 27435091, -17526912, 26807370, -19107454}, {-23753759, -24021010, -32498927, 8198422, 52097830, -6539890, 19853229, -7869456, -12783718, -10230432}, {-14298613, -12284947, -4538345, -4950001, 3010648, 5341923, -9268774, 7995049, 13713344, -1366889}}, + {{-44813479, 10215221, -23761368, 1290861, -7156268, 2925327, 29616627, 8731000, -23424163, 460738}, {-21612287, 8424771, -31528252, -27786811, 26604412, 9613569, -12495595, -94544, -16988595, 1480850}, {-26295779, 1263795, -29339759, -562114, 26936882, -12797839, 30057493, 14093051, 20985678, 3144123}}, + {{-11149967, 20512111, 50048217, 6633761, 24499123, 2996098, -2453910, 7037193, -34632758, 15413513}, {-17490501, 5576773, 11413689, 13735893, -5088787, -25620252, 16061140, -4049007, 22028686, -6334103}, {6476521, -8000266, 322964, 6555404, -4228129, -8729666, -17376684, -3241316, -25192721, -13006680}}, + {{-32933549, 6734540, -14069729, -7372171, 37945303, -11102991, 6053904, -1664098, 36260430, 6107596}, {-10801265, 17856494, 30427603, -3827155, 16080819, 21442617, 46736610, 8184376, 18041324, 21631104}, {11648954, -6927077, -20876261, 1153, -24604951, 6788370, 20270559, -1320581, 13070661, -12328110}} + }, + { + {{-3838927, 8946066, 3549599, -1729060, -19911708, 9167708, -49329485, 23366835, -30812418, -7863363}, {-29175819, 24187304, -45996371, -27411182, 38663122, -3872736, -7091343, 6647259, -8113822, -22804141}, {19872821, 2524097, 14632834, -2026936, 17227993, 10225307, 23867627, -332493, 20240346, 5658453}}, + {{1139148, 5031020, 44772867, -11875043, -39621358, 11855701, -15862588, 4734687, -8063605, -12988652}, {-23232102, -24469460, 9208535, -4694071, 18544666, -3689607, -42299930, 6570595, -41261687, 10749636}, {31740485, -4337219, -7287261, 13549385, -22964606, -4861393, 944573, 5592917, 15538877, 7588967}}, + {{4876099, -5603003, 54696426, -24075106, -369499, -550105, 28609270, -25900127, -7825168, 25713127}, {-35726323, 751135, -8368212, 9380398, -18475817, -7801643, 18137636, -3070081, 52672466, 2217411}, {-19934497, 6805369, 19741409, -8061374, -4121630, -16270404, -6239152, -11357129, 5149176, 15309549}}, + {{10972750, -9549629, -6866509, -13329860, 23902041, -3888075, -41305404, -11418468, 36536856, 4275522}, {-13502876, -12453779, 33257265, 11654262, 26796167, 13249095, -3390058, -9334918, -4796118, 15216970}, {578374, -9641998, 4235917, -8928301, -17735081, -2492971, -20495300, -10223647, -3234201, 11500313}}, + {{-44805286, -6953675, -4507923, -20765033, 10327957, 2649924, 34853514, -4956448, 11964540, -14608488}, {20630308, -15028891, -5427483, 9950831, -27331317, -8404078, -10841898, 22366260, 14320008, 18914094}, {11452089, 10807727, 7665005, -8320296, -10855984, 8892810, -5716860, -9070184, 19383200, 11673555}}, + {{28421080, -8407665, -37640427, 15575176, -37792345, 13262508, 49667403, 8020276, 38927974, -7752948}, {2272500, -12423517, 6015163, -9770834, -20300409, -15629408, 10207407, -14711944, -19252580, -22643052}, {6302340, -15939742, -831123, 9378674, -1567862, 13969657, -11884332, 5052070, 30142691, 4789338}}, + {{34684214, 5771666, 24463802, -3326522, 33029431, -5327469, 45516411, -13912463, -10750094, 32416976}, {29176214, 18120548, -24420374, -3207332, -30264975, -22644525, -4558995, 8212389, 45425618, -786578}, {31328129, -12145582, 2096803, -11086590, -18250048, 11346082, -27683390, 4314292, 18536695, 2521507}}, + {{-5168329, -7077097, -4615929, 2903099, -27443549, 13685814, 2068768, 15274759, 22004256, 18945176}, {-8824521, -3637975, -40579725, 28113849, -25014309, 6257674, -3077398, -11530939, -7840690, -13537010}, {25410120, 1724187, 17119604, 15206198, 31819350, 13295816, -22930641, 9401229, -27497255, 7824654}} + }, + { + {{9633463, 19022023, 33888879, 8168625, -8454388, -6465593, 314346, -23197429, 3856764, -6979123}, {51764025, -2356863, -23607655, -15867521, -46231348, 3103519, -64806666, 4799889, 39026226, 16620939}, {-30022012, -9109746, -7724838, -16245898, 19623957, -7566246, 28829868, -16310392, -3522604, -7659236}}, + {{-29379687, 10200010, -31910288, -25482835, 3983975, 3907793, 46863568, -4852990, -34845469, 9291323}, {18934329, 21435332, 20963626, -4073563, -53412467, -24688599, 11861146, -26481682, 20809759, -5940613}, {-20791200, -13841150, -24779295, 9325480, 13338835, -15576530, 4173723, 10010420, 20325101, 1871524}}, + {{-61092863, 23339718, 38524874, -15161353, 56174083, 436882, -49850362, -4503872, -46402848, -8094857}, {-3077431, 2094324, -8312012, 18097839, 378101, -2485884, -4310474, -24849174, -15294248, 17574937}, {15484284, 1704895, 14937434, -14787341, -10758627, 10726051, 10987595, -9032118, -15609854, -12712258}}, + {{-28708526, 648962, 26139151, -7773381, -50120651, -8564213, -48894023, 7607981, -63567381, 8507712}, {-9311400, 32377742, -23552425, -14883399, 16585693, 24110063, -16467893, -15690037, -2233505, -17312754}, {19862803, -14366842, 22497873, -5713553, 14272944, -2509295, 33285202, 13819558, 9433193, 11353155}}, + {{18254872, 148107, 10616064, 8663081, 7817692, -14250063, -5050090, -1248892, 16687945, -10231461}, {-18552634, -10466209, -42788350, -7179895, -46504900, -8143525, 60814050, 5400760, -9823067, 7310915}, {-32309400, 14643274, -9155565, -6884180, 13489400, -11838108, 26834567, 3153122, 27372500, -7068152}}, + {{-37690472, -10395223, -34750913, -9320800, -9764303, 10503605, 58536452, 5303841, 22315889, -6989491}, {18774894, 11320303, 972729, -13370994, -11559755, -10871769, -2661898, -11273345, -44401413, 8848277}, {17288840, -10777765, -5217896, 12629893, 30788509, -8763345, 33175474, -1044331, 7005680, -7837114}}, + {{-5940475, -6641804, 16107249, -26136265, 15111311, -22285541, 17640399, 2233685, 14602706, -4672795}, {43418481, 7840500, 38381785, -2312057, 24853207, -8055059, 43014989, -7256369, -20927528, -7858265}, {3457320, 8177085, 510551, -8815010, 19355487, -10661008, -10061460, -9637670, 29826183, 4336994}}, + {{31574019, 3809579, -22508527, 22652243, 43795993, 13936395, 17446167, -10644831, 10388397, 5290794}, {25799569, 19797219, 17700069, 983253, 15141595, 18240779, 25682163, -16041789, 50942243, -15906000}, {33433102, -5628405, -4206130, -6607006, -33360919, 11248238, -19655535, -4249099, 14682177, 11920747}} + }, + { + {{-23519789, 10406991, -46809255, -4784065, 490724, -27367194, 33105022, 1255552, -44489131, -3853297}, {-7269189, 7789797, 12114391, 15296039, -30974954, -2820992, 10410220, 4598304, -16412453, 21668293}, {-25760035, -9219079, -15505593, 3068385, -30628222, 7869335, 30225275, -2084026, 387578, 15035110}}, + {{11858284, 4765786, -52990305, 6796455, 28429186, -7060115, -9277332, 19417647, -33953751, -954065}, {-40755362, 8539736, 7078039, -877589, 4772832, 7172185, -40668770, -11756941, 7310117, 27161145}, {-28139345, 14001530, 8746141, -14360244, -24961820, -11666031, -24206229, -740468, -13490173, -16745850}}, + {{22660733, 15449395, -40905725, -17610557, 25037680, -4130114, -5167748, -10914968, 8964622, 1767854}, {29878289, -4322833, -8743227, 349607, -29483960, 11085302, -2615354, 10106182, 31851150, 16289140}, {-4208916, -4071575, -21914828, 5518522, 24050822, 13454051, -21543505, 7199088, -9993362, 3347156}}, + {{-25985108, 14401474, 18648778, -10269203, 45694807, -4157955, 19570750, -17965006, -4947942, 3910866}, {-6126654, -13158428, -21387364, 21204681, 7247131, -4270443, -10760642, -15295222, 36793694, 5452922}, {-16769619, -15211648, -1635154, 12370186, -15925548, 12407219, -8437298, 8155029, -3524633, -3199311}}, + {{2475991, 15803685, -23237256, 967965, -56799291, -12679736, -3533646, 16208206, 13354320, 8271275}, {-39383627, -7321135, 16068778, -11788879, -10182237, 5914566, 3574922, 16500084, 24520402, -11251911}, {-23011505, 13193575, -237673, 3317282, -22612403, -14153553, -26631337, 188911, 1844312, 6710881}}, + {{-30909140, -622071, -12484695, 3137877, -40581965, -19341834, 38913841, -15665521, 26710943, -12848095}, {-18729028, 26429631, 1694727, 8693493, 11329231, -4241588, -24979535, 5628123, -3540907, -1002645}, {-22195518, -11149016, 21539980, -8898580, -7048212, -6898265, 4171045, -16493069, 5535737, -5049994}}, + {{-8621017, 2452093, 28171278, -10095170, -5278703, 3331664, 11585851, -14187355, 30316770, -24971062}, {-31843233, 26126115, 8310400, -17249758, 38945201, -16090690, -21781465, 734413, 22142956, -1715802}, {-30834651, 4117123, 23300299, 5880686, 11904328, -12736297, 15634660, -15704869, -15005515, -13560465}}, + {{-37137731, -24139743, 48352752, -695146, 32448851, -6130157, 35875951, 5604310, -47841979, 4221117}, {-547897, -799509, 6828634, 31423322, -20417627, 6038685, -6883809, 23562360, -10067907, 17214641}, {-3051884, 4040580, 10045488, -16755994, -21674943, 7791887, -32559275, 4015114, 10614076, -15724071}} + }, + { + {{1772032, 6562740, -32765258, 19522226, -11014089, -1604338, 31163259, 27191143, 30760040, 18204251}, {15980952, -11501072, -32181484, 12628584, -27562797, 14005320, -26756491, -1139673, 3915074, -10137757}, {19879210, 15086081, -19617493, -9097496, -2730175, 11970752, 30951967, -4435125, 2716516, -2539676}}, + {{19521463, -3949233, -10860355, -2489194, 49494, -13950832, 43105128, 6607152, 48312455, -5648381}, {1934639, 21832443, -43890967, 23400028, -64128388, -8197912, 1331792, 897064, 946713, 8597279}, {-16507401, -6235703, 8260507, 3128911, 3409192, -2438562, 1256656, -13324301, 2588622, -12249350}}, + {{-54238853, 4355243, -49922517, -7115449, 17202782, -17185542, -7993070, -7583160, -40176346, 28676669}, {-1289905, -6280661, -2973463, 5383253, -10479492, -2710004, -33482746, 1850812, 13899552, 3850869}, {-2508306, -12785040, -12226153, -11184759, 5148014, -7507834, 4505285, 11639391, -22561547, 937240}}, + {{41333243, -10765611, -50610897, 1857287, 16762316, 11513673, 15250259, 22160801, -4624997, 4349912}, {169169, 16151463, -5451187, 15250731, -12066600, -9843421, 26556231, -7500269, -43193915, -21655612}, {-10993330, 8342750, 21656403, -11510214, 12918822, 5182173, 2621656, 8791455, 6329052, 6089645}}, + {{23811143, -9440291, 2754878, -18206922, 45829880, 857788, -40132370, 4508093, -2943759, 12463099}, {32497633, -2601911, 63227034, 4250836, 6241316, 26657154, -7432806, -24156365, 24852155, -5389941}, {-8127989, -12910418, 21816828, -142209, 7335542, 3319621, -5345522, 11161584, 31044453, -15030962}}, + {{-9584327, -8134729, -28261175, 14489186, 8222045, 16186498, -3852745, 1795619, 19336829, 17739098}, {-7730297, 19252347, -23159639, 14268088, -32247371, -3006398, -54382461, -27556917, 45982681, -5703162}, {9808449, 3945217, -32465180, -8796425, 31328457, 15880418, 8370728, -6148005, -15290446, -6557579}}, + {{-44687768, 5670824, -14722582, -4733173, 17122073, -847952, -5627965, 19009838, -23747165, -1453207}, {2234786, 10088248, 22316174, -15574667, -19272793, -18153464, 29156957, -7446492, 3251115, -25178741}, {29304403, -10728396, 25647583, 12198426, 27346955, 63950, 18242102, -16547413, -7574627, 10871964}}, + {{-48929340, 2968446, 474182, -6757543, -38388721, 15208207, -31806867, 14190812, -48845928, -1470502}, {-2545304, -24000016, -59811098, -1939209, -17623469, -9799745, 25683227, 12196064, 4214740, -14740518}, {26933806, 7407287, -13150154, -9490061, -29239123, -2802803, -9231566, 6825264, -21611219, -9933017}} + }, + { + {{43016965, 15705701, 20442551, -7940737, 2555029, 10725950, 29166376, -1667668, -20312657, -10689236}, {3820175, -6474265, -46035043, -13531173, 41430843, 10417362, -33288026, -14620978, -1401597, 8447294}, {-20433226, -12241763, -3016794, 1891356, 16496144, 7850955, -18347536, 10034820, -9746714, -14507431}}, + {{-48407507, -11683773, -18012190, 11863672, -29753768, 4683670, -36975564, 13576809, -14701774, 1535040}, {10239005, -9826803, 36891100, 1500216, -6645424, 9643274, -7509334, -9268757, -18155778, -6816944}, {-23498461, 9411269, -26557906, -6406986, -5272428, 12503415, -32831925, 11143016, 5590245, 8334430}}, + {{61031549, -1101793, 54103057, 9091967, -4436371, -9402358, 25991824, 30371397, -19841010, 7937313}, {388675, 27218059, 12612625, -2638969, -2964893, 4983792, 24305498, -2185609, 20428302, -21524003}, {-18960973, 7893016, 27045114, 4079921, 27536921, -9829181, -25958628, -14883683, 30398174, 10277245}}, + {{-1587781, -11497733, -11573560, 13126556, 20845495, 17270956, -30510292, -12694926, 27519491, 28729686}, {-7157511, -2397111, -53844340, 3627788, 16602851, -14027862, -696788, -2274626, 38222831, 2252584}, {-12405263, -1681681, -13159821, -6320119, 7316360, 3727073, -18309962, -4647016, 28529514, 15416492}}, + {{-13280399, -30506359, 5854795, 806575, 1954876, -3535888, -22784558, 10017133, -5618694, -9743775}, {-28028201, -2378015, -23019059, -29100543, -34330076, -24985398, 32985014, 16281077, 43725756, 18259245}, {11675001, 5510446, 22873075, -6864006, 27375376, 13662394, 5462602, 6927570, 14233094, -12971689}}, + {{12057457, 32210870, 20720679, 13354573, -3629017, -7026667, 3957924, -14338893, 41433789, 4136818}, {11158283, -670016, -4976523, -12123511, 44375853, -6403451, 5876206, -18558063, 24673395, 24834106}, {26168421, 8280272, -23051079, -14608992, -14879826, 3779315, 16641301, 15793570, -26079168, 9812423}}, + {{14770462, 12587776, 15869411, 20957799, -43788533, 20713332, -28183953, -3527847, 39048655, -1940462}, {-14714352, -13775000, 18145021, 10029113, 20649581, 3009514, -36394907, -11391867, -3506311, 12277302}, {28049054, 14229852, -8274110, 16738645, -25483858, -5691080, -29572070, -12661299, 22517783, 919782}}, + {{-22646895, -21484547, 1633663, -14629481, 11267690, -22274954, 12265181, -7887248, 8640479, 20949759}, {-30020693, 7329989, -24393997, -5132585, 47564484, -9776898, 24212213, -6248484, -35350807, -12327603}, {-7271169, -13975579, -5673027, -7308174, 26750467, 9831537, -27902974, -13239923, -29041094, -14755279}} + }, + { + {{-13480994, -11555397, -7529704, -9323042, 1116673, -9613410, 37881920, -20965519, -41828922, -7043913}, {50456984, 21529939, -41081758, -9848290, -3487467, -18945280, -8374910, 1480559, 7884372, 14936035}, {2346705, 3885707, -27465055, 10185648, -4812999, -4919831, -26651064, 14754641, 33071412, 5885392}}, + {{5173867, 2018447, 56311889, 856479, 38484641, 859318, -28292444, 13890182, 15709885, 13775830}, {-61593233, -29640793, 3972815, 3073373, 16652323, 11086676, 31894278, -14464524, -30278767, -2545818}, {32931840, -4763919, -14868942, -14614327, 3193474, -3158083, 22304681, -12183868, 27372706, 13117669}}, + {{-11094849, -63737, 11733891, -786851, -13472103, -23011570, -26315335, -7846878, -16360367, -14838937}, {-31144197, 11737121, 7255115, 18385417, -36011801, 6846178, 38611497, 2902212, -26285887, 11696021}, {13382936, 13178758, -12025171, -13254045, -27638619, -14364504, -5618523, 2391432, -13383826, -2150070}}, + {{11750358, 7914028, -23042152, 8030277, 39615918, 9182310, -25907301, 2699271, -21126979, 5751665}, {25292924, 17493830, 21577616, 3294247, -12797430, 19577632, 20037337, 13237939, -28093719, 2186785}, {-1082149, 15209818, -21738315, 10641033, 32225978, -8265653, -25257733, -882178, 28360034, 6570301}}, + {{9143403, 23839022, 35353980, -22505492, 114165, 5113169, 6089871, -19108137, -22789338, 31675048}, {45866659, 7422934, 24338976, 3658842, 13952863, 3126973, -35311739, 2024897, -31974330, -1710440}, {-9150036, 9331663, -30127934, 7261514, 28694748, -3426370, -16300972, 11615619, 7439595, -12065698}}, + {{-6946029, -3094691, 6122324, -6237880, 22728728, -1655440, -42516506, -12961649, -5854097, -6338047}, {37792697, 25767993, 34008524, 26933886, 1468676, -4740418, -16103580, -4686169, -12286155, 1802567}, {-24852984, 4608095, 18070382, -14845825, -23142308, -14350367, 23638504, -856790, 23672653, -14163830}}, + {{-23634568, -11958769, 61608906, -29050370, 41285625, 105434, -6561790, -4438594, -33292274, -7684946}, {-31517528, -20455273, 1591586, -2076804, -16316523, 33047852, -1322618, -4614424, 6659498, -5165052}, {-13737946, 12031439, -32382748, 13235148, -8814629, 13605013, -12461644, 5402562, -15891845, 4767741}}, + {{-8340464, 12290254, 9696374, -27635151, 5447897, -4962608, -2555388, 20864333, -18929971, 14682090}, {7326350, -14051670, 36958530, 5236393, 10585213, -1655034, -43306320, 1201929, 45742857, 1723804}, {28984607, -8062399, 12382644, -13411363, -8302161, 1185523, 5798259, -15291873, -10210235, 16755402}} + }, + { + {{16920676, 16715259, 38145133, 4785281, 1451168, 7735604, -33281925, -8688939, 1199163, 20394696}, {24193060, 15252485, -9385529, -16267613, 7141382, -8225994, -27882531, -12148187, 2459699, 9049808}, {-32556976, -1167865, 11418257, 8056263, 9550693, 7227052, 5964360, 4857140, 27143497, -4111365}}, + {{39817193, -9830193, -16026583, -1858407, 24498623, -10604985, 4840981, 18346064, -35506492, -1518604}, {17780935, -15507949, -40328285, 17134723, 37227365, -10294427, 37117755, 14077886, -24533620, -13386792}, {19434905, -6445005, -5302583, -8024017, 12497703, -6346095, 9276329, -11657559, -18713435, -9163875}}, + {{-2658895, 5484905, -23304555, -6179240, 7853468, -18159650, -42007502, 2244695, -1048321, -8867171}, {-9541025, 14553687, -22038865, 12406006, -4669674, -2533266, 11360372, -29353103, 35549887, 2878079}, {-19460989, 8848965, 11242605, 4720082, 23940066, -12182196, 19657279, 13861652, 14245366, -4262405}}, + {{20433395, 9138713, 16524632, 23665100, 33180240, -1312297, -34304099, 6222943, 9644596, 4167688}, {23398647, 17645543, -34768544, -490194, 13561630, -20711293, 31661255, 6093001, -4576544, 28813278}, {22277382, -7545728, -14268136, -12035122, 31230436, 1201743, -29397285, -12319388, -5571886, -8099235}}, + {{-3532555, -3063346, -2362686, -27218502, -34810150, 23173153, -21022797, 869907, -1416822, 11984683}, {-32690879, -29278752, 48411730, 5531838, 22586942, -8260081, -22395517, 15424083, 37340188, -12027481}, {-11898027, 241191, 12868313, -12540493, 33291329, -2895370, 5354657, 15636945, 17430868, -1528003}}, + {{-18239631, 7159148, -2492250, 9169283, 577887, 4929610, -26679656, 21184233, -18227970, 20271950}, {47007109, 16108010, 33364994, -18183881, -41920803, -22032508, 37374200, 9349329, -19872404, 200584}, {13795360, -9738463, 20295911, -8727094, -32972237, -12516214, 5607958, -3800534, -28273841, -8179638}}, + {{-7940918, 14445664, 37472019, 7673591, 15526413, 1142009, -1587886, 13426454, -25100819, 14531703}, {-8249900, 17975860, 18229797, 9000485, -33170559, -1385195, 39477234, 14779280, 3023371, -16826195}, {2613522, -7309805, -10698441, 13079416, -19673545, 8908889, -14262870, -14297501, 14984663, 12961997}}, + {{-36560275, -24678255, 25531236, -19681840, -23845161, -18340656, -38747189, -8124717, 58776406, 4415882}, {9262225, -2985175, 34127952, -12604714, -36318985, -11344174, 7597161, 1546003, -5014406, 29026088}, {9535890, -851902, -9132361, -11035441, 11548366, 9634834, -1946027, 7078086, 14212407, 7217403}} + }, + { + {{57423576, -10292629, -2592212, 2235804, 3661669, 18270881, 31537531, -22712105, -6195683, 7808912}, {7797084, 454143, -13161378, -18826374, -40734425, 6345021, 29967859, 2918283, -58754971, -10409200}, {-13249253, -7329951, 22231134, 4459089, 10882220, 4860743, -24698083, -9978431, -5670105, -12238132}}, + {{-53004124, -5167567, 15085886, 16736499, 22058360, 17546247, 33402290, -3482449, 4415911, 2060642}, {13490798, 25388575, -38810830, 7017943, 1924398, 5183359, -29909506, 1386739, 23387649, -22674070}, {-29458736, 2492433, -13556795, 11205665, 5611991, -2334748, -15775678, -748234, -1064772, -6627890}}, + {{-25413498, -11501850, -39078455, 3459141, -1312737, 11802978, 5222471, -12187652, -49890945, -2774679}, {-8545304, 10829884, -16118899, -2584317, 16517895, 19442656, 19487957, -10665948, -13785077, -1126361}, {26083646, -3365846, -7761387, 13193122, -16798931, -10773697, 10735134, -10064491, -631120, -3597651}}, + {{37713250, 25562955, -34148392, 19546437, -28591503, 22733045, 30032242, -8493268, -46165976, -1307385}, {6336844, 7177473, -17252068, -10225857, -117641, -970677, -5846042, -4627888, 16077668, 21643231}, {-1953103, -6202443, 6215146, 6858001, -31665887, 1767882, 9065802, 13748405, 4391154, 15125407}}, + {{-1246957, -5713173, -10965980, 21528319, -802220, -1581441, -34127986, -7208245, -1546234, -7831521}, {16315129, 18738101, -43749014, 8120457, -61330822, 11005527, 12851608, -14466907, -42071268, -24312427}, {18246764, -12570019, -32115190, -11475783, 28055067, -3268351, 12083407, -7144167, 1986840, -11974960}}, + {{-16495641, -6305095, -465574, 26891470, -14945650, 5686905, 51114414, 7396298, 17851979, 2075751}, {-42361147, -2756757, -4354846, 5332258, -20891836, 15194993, -2767554, -25458098, -33474145, 30974835}, {4354329, 13304857, 23978922, -10718411, -24725471, 11349719, 16727616, 756811, 31349636, 9287913}}, + {{4954258, 25212368, 33338703, -14077779, 26545665, 4848917, -27615055, 3427857, 17990812, -24979274}, {18233158, 7461744, 7720987, 1464809, 31058651, -14033807, -38319807, 18136481, -23330916, -7631018}, {16032681, 8136631, -23556212, -3150664, 16622171, 7980128, -25727701, 5626779, 5190447, -2344328}}, + {{31705814, -5147275, 52005727, -24537023, -7338334, 3638109, -49222509, 26008835, 32931979, 12843402}, {-27709400, 13248641, -8524705, 2457713, 41586318, -28938943, 3221771, -4119929, -12860975, 18037028}, {-21656822, -5210725, -6430278, 660178, 5940859, 6216710, 7908540, 11228907, -7911737, -11283781}} + }, + { + {{19447848, 12079480, 18084012, -19364727, 29309442, -14161359, -8563027, -6912806, -47392349, -7802083}, {-46591322, -18757630, 25853694, -3476351, 24526328, -4811551, 20172795, 25381790, -16367335, -12356703}, {7094404, -9637684, -10386451, 13743093, 21134780, -14567892, 27055785, -14632052, -6505660, -7976678}}, + {{24447028, 31663572, 32402997, -10532248, -31138504, -16630801, -48353038, -19147303, -64897597, 1158936}, {24922986, 917316, 15516165, -4507326, 3900200, -8263679, -6130850, 3765009, -412407, -25676548}, {10015781, -13588022, 6185149, 10420138, -12350239, -10426361, -24076311, 14497252, 13526594, -3129301}}, + {{-7280977, 17509339, -11260345, 10160761, 2323115, -13864406, -3146521, -13371384, -4944466, -2202578}, {-38303471, -1299679, 32240355, 4035543, -56302311, 5378430, 41929079, -1470616, -56609454, -1437084}, {4807734, 10589874, -30176402, -15726584, -32976194, 77734, 18517570, 10244433, 18191544, 12803322}}, + {{-31426453, 9478167, -42043789, 16661854, 5841857, 4378474, -20534652, 5627989, 26217404, -23194481}, {-27276087, 2045817, 3193901, -12870658, -14201131, -1952602, 36599648, -27467711, 30806230, 4980965}, {-3873087, 10746631, -21263291, 9115873, -30003099, 5027981, -16843621, 9760922, -21977224, 11975187}}, + {{25728997, 14671420, -29671617, 9545971, 16085808, 7356686, 28422751, 4087701, 11644116, 2800038}, {-16893223, 16591756, 33261895, 14044461, -51007496, 15573340, -23013943, 22191497, 36413112, 9718784}, {-29463084, -5675285, 10662787, 15123659, -9942558, 11004487, -20091178, 16640809, 12303796, 6569712}}, + {{-45464670, -15443267, -41363101, 5182103, 32816612, 11861614, 6778429, -8065578, -19759551, 12516634}, {-11130112, -5957825, -19862013, -15112507, 21294814, 18729764, 55280511, -18866902, 21394761, 12947556}, {-1557852, 4371262, 15721765, 3754968, -13847973, 4644561, -29260226, -16532003, -26854538, 13438948}}, + {{11530327, 23830935, -18227916, 7159165, -2384902, -13197972, -13004181, -3534851, -59294380, -4601491}, {25765887, -6930129, -25054022, 5806559, -64031010, -18150826, 14667767, -13684315, 877866, 7065493}, {-22828789, -13635377, -32460078, 6570579, -2081246, 4209314, -13879090, 3929682, 18018189, -11785201}}, + {{43086446, -940424, 4887104, -3791393, 6272476, -9751170, 5613006, -1645161, -44013374, -23002310}, {19876454, 8288864, 57206042, 18226959, -56007676, 15845474, -50037474, -3944443, -9809968, 751928}, {-4107972, -12891678, 23403514, 4567926, 12940627, -7298088, -8301375, 6655803, 15962126, -1598127}} + }, + { + {{-1571427, -2814715, -31976013, 1210216, 29042018, 3427595, -10167065, -19511425, -31601765, 3144951}, {-50719607, -47205, 8793361, 17693924, -1743102, -9314481, -33057089, -6662971, -2900209, 28716927}, {-12100043, -9596968, -13097994, 437903, -32638031, -3257815, -1315247, 5614343, -22590535, -6979661}}, + {{-13455280, 4468453, 28289229, -3425348, 29533497, -22288655, -2718837, 5361191, 7004777, -3469891}, {51483606, 16901385, -33813283, 6633534, 15131383, -3660957, 508813, 22752811, -50653045, 20727109}, {-31584628, 3360148, 15286482, -8723984, -16491044, 15088405, -26324370, -5284548, -13188281, -1431289}}, + {{26549737, 5387195, 14915140, -20434555, -14098228, -1416501, 17925290, -29253878, 8430145, 18882291}, {-17317071, 3862581, 30325710, -11928459, 23986332, -21615745, -2235258, -2333606, -4444593, 3141473}, {23362670, -10020277, 16626575, 13783623, 3127639, -110896, 21657368, 11839891, -8823705, 15673145}}, + {{24398850, -13259537, 32123665, -12098537, -39525846, 16528106, -34122946, -4150212, 38681337, 2190321}, {30885110, 14321117, -34368297, 15189965, 14885346, -7786788, -30598992, 29268436, -7991659, 24007869}, {-6105722, 7457049, 18756718, -9896105, 30265139, 3478624, -33127370, 4183499, 14245730, -2314081}}, + {{-29121228, 22130367, 10405634, -29133896, -1442124, -17735351, -5986555, 3256899, -30211779, 10459334}, {-7471950, -10470709, -43129432, -438472, -28755566, -12571235, -44867755, 18331991, -13798043, -6673726}, {31090790, -14430637, 2506609, 11709900, 18344597, -10525137, 21818404, -8786312, 32126131, 12845770}}, + {{-48373811, 9559789, 37042620, 21996038, 7453854, -22634569, 1086003, 5225244, 47823391, 1214140}, {-7558809, -15025707, -12931256, 8495596, 28851846, -2847845, 41101507, 10297290, -9559711, 812902}, {13711262, 9982769, -9898343, 1733229, -28802434, -12044815, -18354644, 8849330, -10034897, 3451680}}, + {{1108160, 11326080, 33383781, 24102167, 30332279, -21864759, 33265664, 17693415, -274492, 20184839}, {8986870, -13854146, -22073055, 2757829, -26354323, 813579, 15356358, -8914267, 55811500, -4915921}, {31781453, 5859939, 21838109, 689743, 15106474, -11026098, 207134, -11210873, 16130072, -5233974}}, + {{9615249, -18348909, -49401245, -5757686, -34015637, -4958617, 37761478, 24352231, -57305458, 11827354}, {43990315, -4491023, 13000533, 18331472, 8710495, 16278677, 24989444, 8467983, -5164130, 19176592}, {7206760, 14366796, 18553843, 14622639, -14270824, -4358078, -8218032, 7664097, -28607267, -14628083}} + }, + { + {{1892499, 1301069, -27743734, -8924509, 35981140, -10432725, -4754318, 8655230, -16406815, -339205}, {-50958721, 11127195, -11019952, -10307257, -20165218, 20063985, 21894512, -19900958, -30144355, -20656095}, {15607830, 7616443, 19713312, -12323979, -20964194, 4107936, -30447440, 6495422, 5992666, -10307573}}, + {{-21232449, 16431459, 12530510, 16695237, 12906731, -3768714, -10763240, 29654181, 59974317, -21800748}, {-44211361, -13375153, -32095666, -13501201, -11533529, -29643668, 10565180, 1283857, 815371, 10845004}, {27854714, 14161699, 1699881, -7967975, 15760551, -15577950, -23066901, 5022467, -14516336, 564619}}, + {{-17950534, -13299806, 56486934, -19559260, -34409780, -7218915, -11146345, 22094273, 39816748, -12234679}, {-46183462, -19123792, 26464, -6685880, -30478768, 23752647, 51609111, 4254955, -5574854, 20412299}, {-11422616, 5102964, 2738206, 11476294, -32399966, -2790740, -9993091, 6486712, -27440649, 1761067}}, + {{3439151, -29722082, 35417832, -1525657, 45042730, -1430905, 17467124, -22670777, 4719515, -1132811}, {-10222803, 2073120, -2377230, 21432397, -4221180, -25187825, 42489004, 849761, -28361529, -31769337}, {-31065392, 286699, 26599688, 9679662, -21314829, 4809486, 20702915, 4553314, -18747115, -8319858}}, + {{-1603332, -13585818, -38358591, -16079890, -10931437, 8490731, -12776452, 5215299, -12124365, 378813}, {25498658, -644766, 9756365, 475122, -7662851, -15572361, 25107722, 26515205, 19185213, 6224105}, {-21429699, 6351015, -16879801, 8380446, 9507014, 11769912, 23586254, -1807951, 26737090, -2008366}}, + {{7081450, 2677166, 22671383, -4828317, 17842808, -15335283, -3041432, 5399867, -1819170, -7720992}, {30161366, 9103968, 44382849, -10033545, 33076528, -11607557, -42368046, -22809965, -47760522, 5483306}, {1593389, -6024160, 3395147, 16575517, 7493064, 95550, 15558992, 16506356, -7042011, 8389603}}, + {{-4481238, -5684599, -35685590, -19080336, 53283160, 13406199, -10004250, 906158, 3289076, 16806125}, {26189832, -15004967, 8182468, 5716584, 6111736, -17915331, 45014602, -27581184, -49118074, 11755683}, {-22965161, 16434546, 24594714, 3578195, 9798345, -3698700, 5777307, 1926114, 17712616, -7068040}}, + {{59485861, 5072769, 692255, 5642719, 12193516, 5984165, -20420432, -17690777, 8318789, -7961945}, {5539095, -9840791, -60584193, 26711215, -31516814, -16062777, 39035052, 2837629, 46689805, -14152839}, {-2800992, -3638477, -11821662, 7268400, -27577991, -796098, -24672533, 13747705, -26016389, 13661609}} + }, + { + {{30605491, 5233683, -18648915, 2025168, -3231586, 9978261, 47401907, -10936090, 11058061, -1003749}, {-28718039, 1272771, 31278905, -27679744, 39451156, 21400207, -11209003, 11451658, 12210251, -27478759}, {23534670, 4113853, -32054153, -9593556, -24628615, -6776535, -30687006, 14199133, 8497366, -10031923}}, + {{-34921403, 2693281, -17918198, 25403779, 40434373, -19620678, 20053337, 8747850, -6150160, -12137216}, {-18562189, 13284305, 40707434, 7579221, -23136315, -13002288, 39016445, -8649162, 50464212, -14897864}, {29528755, -2518696, -28086015, -4005256, 33200944, -6589857, -16301731, -1100097, 12786545, 6236340}}, + {{21877076, -9653759, -46280374, -6059209, 54607270, -3842219, 6144769, -14831167, -54471346, 9719011}, {514702, -16351079, -20306558, 25172595, -12450502, -17335867, 19483881, 17066147, -5547228, 6176435}, {-33303974, -15303094, 84074, -4152103, 296884, -12624825, 22111513, -15126980, -27912698, 14821492}}, + {{4837397, 11485892, 16390648, -16411498, -33782265, 4594245, -9123571, 9652566, -37410166, 21597429}, {769821, -17556746, -22344850, -8660584, -7031031, -11081149, 33972831, 15307650, 14124834, 7085331}, {9069320, 13852193, 8781666, -2665310, 32998180, 4491983, -11645413, -2562603, 29676695, 10247957}}, + {{-25214309, 19553785, 11318253, -12272481, 42808410, -4352309, 6963919, 1108204, -23778174, -15807661}, {-21478791, -6580893, 54255551, 16102105, -8507256, -5811021, 21022471, -25765618, 41154780, 1950333}, {-24657512, 12995163, -16060577, -8507773, 18556150, -9892215, 20595578, 10347876, -27684225, -11424345}}, + {{26748617, 5217478, -37757767, 14419725, -9387810, -6808361, 23756843, 16095648, -26580434, 23233420}, {35969251, -16568118, 21145299, -16513097, -12942810, 18818351, -28126091, 11474178, 33397936, 5836170}, {-26462996, -9253929, 22646536, -14658531, 5071262, -8828652, 9072972, -10810039, -12377202, -2804440}}, + {{2018046, -1709, 48507269, -7787147, -28056527, 26387205, -255883, -8097302, -39604149, -10885642}, {22259878, -22451123, 8483601, 16952131, 14258005, -7112561, -10223101, 16257746, -10089653, -11357640}, {27412614, 11045568, 33397042, 7204032, -3944880, -6771874, -19083287, -12096530, -19977728, 12208290}}, + {{60919288, -19127799, -12608309, 15256300, -42904216, -1055666, 32441480, 19654131, 45013609, -7445754}, {-679860, 628111, 37171641, 4824046, 10752632, 7804374, 10004116, 4364635, -3386311, 10007218}, {29662446, -4860596, -21168821, -9838285, -20050937, 1941410, 25646132, -425216, -22341736, 396489}} + }, + { + {{-15193484, 2788165, -12181519, 3709794, 42199369, -481751, -19021085, 10410541, -7378715, 18806491}, {-27375094, 24835931, -39872275, -11792390, -12347277, 6866025, -40699781, -99929, -23356017, -5362725}, {33526364, 15737244, -26411103, 1851538, 29015293, -1595757, -8595260, -11612436, -8530927, 6897225}}, + {{-31500107, -5199030, 5079707, -13171164, -24538393, 7039991, -25071558, -20669002, -22698480, -1314761}, {27900021, 12288234, 19298847, -8119100, 38654067, -23272975, 39006784, -9038910, -39479518, -9056017}, {-27252394, 12068223, -28382014, 8487941, 13903446, 343731, 6801282, -9223125, -25595497, 8692445}}, + {{24382178, -16090484, -40674628, 5282641, 12906032, -4066779, -9743704, -22220867, -26888463, -20062337}, {-35328422, -2883978, -18340604, 8240619, -21614224, 7375113, 8364606, -5823919, 37740627, -12267491}, {-20682878, 13061381, -10485799, 14040118, 32996892, -5882029, -20610157, 13825235, 10364287, 8210274}}, + {{26284729, 383293, 37169244, 31100394, -6468611, 6388726, -20326624, -27009263, -1031524, 1170464}, {11852283, 2339785, -18011850, -2314762, -2815855, 19942432, -35450298, 6078081, 25270744, 3041866}, {29171716, 7019663, -20742479, -1118566, -3568078, -9910144, 31141797, 1555531, -13556891, -5756363}}, + {{15771167, -4873782, -30766854, 11344373, -11422977, 23660609, -315085, 13769878, -10987507, 12753408}, {-25681415, -16156792, -17085662, 19167871, -53549737, 403251, 11651317, 9480222, 30052241, -2064388}, {-21286638, -1233670, -28520950, 4287841, 4495089, -1679170, 539292, -12052974, -5118353, 8704104}}, + {{44846785, 10136198, -22108177, 25856249, -22615749, -10052046, -2583020, -4331118, -13081104, 5855409}, {18197757, 19651220, 23739125, -2404843, -33685161, -561938, -38195050, -18725610, 28155478, -14788537}, {23388591, -938413, -9710789, -14997126, -15060280, -11417608, -13969067, -2814196, -10387481, 376732}}, + {{20361675, 1291578, 31503038, 13978856, 9218557, 1027241, 12853225, 13267865, -26506324, -13628916}, {-31178027, 31394234, -15796976, -7394198, 11947197, 3178417, 44681635, 18544083, 38615548, 12992196}, {26330014, -16426657, 12841105, 11268705, 776927, -1239057, 22981633, 8158639, 18960215, -1177179}}, + {{-13504629, 17237673, -14038583, 12244930, 10017779, 13514040, 34630029, 19762283, -28530594, 6407882}, {-27580741, -3187769, -5677929, 458022, -34094587, -19402390, 26696381, 9486941, 15046978, 81160}, {-17705173, 15416103, 31126353, 3058411, 26848404, 16666221, -22793898, 5886459, 16469624, 9146198}} + }, + { + {{-29734036, -22468588, -38362848, 25094892, -35606527, -914829, 2747745, -13089201, 47543140, -13278696}, {-22459978, -2391576, -12956000, -6732944, -9397545, 2648507, 54081039, -18516863, -3236926, 16808512}, {-5991963, -487406, -32133911, 2522033, 19745315, -16223281, 1670937, -6597607, 6828882, 747789}}, + {{-19113981, 24361885, 30958985, -20641386, 12169016, 5180, -22828927, 9401377, -57422792, 29188486}, {22324213, 5161589, -2917979, -11448782, 26571604, 19159532, 122011, -14194923, -8829774, 1228164}, {-6564432, -206710, 23034799, -2305964, 11448685, 13852631, -6757732, -5559800, -10761830, 9235392}}, + {{22139345, -24859394, -3476901, 6564307, -45599688, 18371843, -4353246, 21279849, 6891787, 5909226}, {-15203745, 4995310, 34529277, 11712187, -15095434, -10971169, -14712264, 8146817, 2172151, -8281734}, {16435126, -4004221, 26140808, -3525150, -28634168, 13078851, -28179608, -16409319, 23142677, 640772}}, + {{-7103397, 1737046, 58560262, 20608710, 23465831, 15653906, 22354223, 2815185, 30940891, 1862603}, {-35661199, 13180474, -836164, -2416240, -40775515, -7908016, 6590117, 15823587, 19986247, 20334633}, {21667647, 12375693, 18588748, 13551272, 12238921, -16466422, -19798363, -14312401, 12923063, 11691182}}, + {{58372513, 13412053, -51717636, -14673861, 19135889, -10333378, -41242272, 3188039, -46425403, -20413821}, {55755, 17299671, 474110, 11085049, -13888145, -20438928, -9066290, 15651729, 4933453, 5638481}, {-30792139, -4504491, -23435833, 3259673, -17050867, -15255784, 24195029, -9374589, 5623044, 1300016}}, + {{15758880, 6032776, 5951804, -3482564, -10868027, 7429092, -8173543, 15840329, 38918720, -2726468}, {-42088266, 12583448, -54069028, 17864914, 30199323, 16504492, 24777599, 3265919, 19553510, 14535496}, {-13075624, 15836358, -5798448, 2761473, -174881, 7995654, -4743560, -3756902, -31547717, 13634612}}, + {{18169612, -8271187, -24775016, -2018822, -51210415, 10429073, 30039743, 14672026, -43725169, -17717800}, {12802166, -9323803, 3427594, -10388248, 9667099, 5397143, -13515713, 9777914, 7064345, 13045374}, {-5585305, -591177, -15352186, -16477297, 27682970, 15587978, 14051175, -13437493, -33451365, -6439289}}, + {{-22821437, 7348073, -57610231, 971502, 49917670, -8247521, -21081986, 11518620, -12892125, -10801170}, {673353, -24801559, 6458207, -15489076, 2230510, 12457365, 43074670, -506244, -21519267, 11006488}, {-9346991, -7484442, 27037940, 1875498, 19795928, -4956257, 20546628, 16409829, -32103044, -3770496}} + }, + { + {{-6053355, 5957591, -3096160, -14684838, -19509243, 17265264, 35558927, -1292717, -17686206, -29109752}, {-10335145, -2510531, -63618412, 4603640, -6388893, -10415332, 27468929, 6121407, 23442018, 2853122}, {-16531287, -4201170, -28979984, 7861948, 21847948, -6499485, 2398236, 8988299, 9454785, 2346859}}, + {{7027823, 14012849, -26067748, 2086198, 5416080, 4329447, -3632979, -10950637, -9243725, 16213552}, {12976523, -18179449, 21169212, 27492778, -42871986, 16383429, -15216263, -5416753, -36815449, -1697964}, {20560027, 16732727, -8009172, -12133027, 16680096, 2519568, 19666073, 11778464, -32729378, 9916572}}, + {{26185632, 19247883, 13581152, -20510005, -2230418, 23379293, 49152034, 20413823, -41079177, 3212648}, {18631446, 11664165, 28862132, -9589805, 748250, -8751757, -16555878, 12407771, -11746415, 28333202}, {-33150753, 4677831, 559938, -10005383, -24898218, 12996920, -14582876, -4351918, -31887190, 6477373}}, + {{-7747450, -13976192, -11307973, 4522662, -3369203, 10276650, 17257139, -2571323, 1005204, 3854170}, {-44591072, 1311192, 31124063, 3767098, -14402707, 439882, -15630889, 4915415, -51713468, -259270}, {21695387, -5142812, 17577428, 10717642, 14492804, 11348066, 3130461, 10524767, 19396835, 16302425}}, + {{-1321559, -2586468, -46091502, -5188924, -15950941, 23277684, -48813366, -402395, 12620220, -20626394}, {-57080789, -17364618, 12636502, 19193818, 38319131, -5588836, 13245760, 1003189, -8050568, 11192080}, {-28717465, 4010233, 990021, -11679532, -6579244, 13514138, 1721412, -15845396, 9781793, -1291292}}, + {{345153, 2601171, -11634960, -2335693, -18704106, -18573583, 43815987, 7941013, 34564182, -9914100}, {-39334757, -17199891, -39912054, 22582761, -13062860, -6411533, -18631029, -9485565, 23036810, 19377614}, {-18007015, -1043780, -6666455, -4014379, -23368209, 2497268, 19846172, -9985766, -11778753, -10032281}}, + {{51646069, -24408634, 33054920, 8392374, 29882271, 20849105, -27960634, -12074397, -20392903, 4001414}, {8017143, -7532302, 26470648, 7481626, -26950701, -8556155, 32513510, 13501595, -36260203, -1119152}, {-22748933, -6829013, 16647598, 11386422, 19202752, 5157355, -5884124, 13437553, 14302869, 12786880}}, + {{-63701949, 1819635, 29402356, -11913036, 37809359, 4877194, -13464801, -2685267, -24663653, 21367214}, {125387, -25804933, 36409802, 21113746, 10532223, 19040626, 16144795, -17613137, 1025477, -5721906}, {-33127540, -1588520, -32098876, 1654571, -23073070, -12232421, 27322957, 1129164, 24053819, -6589927}} + }, + { + {{1735329, 1628081, 11231213, -30193638, 10738152, 10308662, -19953896, 18375720, -4296858, 3328224}, {56354711, 24206661, -41241667, 816820, 19783692, 20183790, 26418936, 12544096, -583668, 29523826}, {-13626072, 11712188, 18618159, 3056994, -19955192, 12604886, 13144852, 11121563, 6927152, -6413613}}, + {{27172128, -19869168, 28648548, -8133215, 1928989, -5541754, -573629, 20185621, 52294334, -5732640}, {34239652, 2744418, 30275528, -2285233, -26355337, 23097640, -10613335, -858481, -6529684, -17844184}, {-16546559, -8403385, -5476328, -6298095, 28065830, 4077456, 2909570, 2606558, -27312956, 15234298}}, + {{-21608265, 5696141, 46683152, -6383046, -9406651, 19939635, 35117770, -10292698, 55102781, -11907009}, {-16459827, -19611397, -5058566, -10401132, 11221041, 8936151, -31257532, -1225794, 1737455, -2291935}, {-14779154, 13758551, -25503035, 3561561, -12169351, 5552333, -6887735, 5809516, -14201691, -3457541}}, + {{10489806, -25334458, 19316619, 3843737, -2001728, -15605646, 18687602, -9106868, -37429212, 19234769}, {-22388198, -4733810, -9950613, 22914669, 15187188, 3768550, -33370752, -6977892, 12472542, 10099123}, {-29543521, 14321335, 4531993, -10479902, 29540741, -16542774, 30757708, 6157960, 26449686, 11537214}}, + {{-15353460, 26732831, 7547212, 1493363, -587936, 12431131, 25712772, 16310760, 7319382, -16907861}, {-6361544, 6739709, -9210384, -4988941, 9209698, 628323, 1607162, 3656766, -23681102, -15592645}, {-16427761, -1751937, 13978822, -13716010, -5726380, -7964773, -30983087, 13376300, -6872599, -7993024}}, + {{23467673, 3233899, -55125596, 6731073, -55043395, 2277752, 24422551, 12613305, -11695896, 27691915}, {-33213633, 8983015, 6863898, 25737719, 4531733, 22734666, -11381677, -3434367, -17516448, 5310879}, {-8177770, 3449422, -12207556, -15928314, 4066127, 10281971, 21125971, -13911586, -13656309, -6493298}}, + {{7385689, 5209181, 39377058, 1409693, -42748330, 1257683, -3984412, -6899882, 31357716, -10405277}, {10819495, 2314213, -11449318, -16833093, 22584754, -23994129, 18964782, 12532364, -23447792, 23130795}, {-7374521, -4925285, -22285880, 1031410, 9590514, 11169572, -8444009, -15833407, 27442000, 9517778}}, + {{38427600, -1930552, -21520517, 5572927, 14179321, 32192515, -26181759, -10504508, -27064141, -2577263}, {-20942126, 10036730, -6326359, 1443973, 46750571, -274697, -9496931, -17698940, 38860995, -2712775}, {-23257480, -3999821, -28566943, -7985056, -21359934, -9723986, 13047655, 15663364, 2084243, -696998}} + }, + { + {{21888815, -27077762, -24364451, -631788, 23977222, 3017341, -7423642, 17517293, 28562375, 29083510}, {-9306403, 3176022, -32954593, -16833694, -19530782, 20535015, -35362336, -13525259, -11738273, 784528}, {23907366, -2472729, 19634150, 8228425, 16289884, 6574817, -27167746, 5378870, 18119192, 11110101}}, + {{4552584, 19017231, -6537129, -233087, 31002726, -1816626, 43261950, -18425438, -22728591, 17647556}, {47343362, 12495493, -17138979, 20998695, 23447210, 1684470, -9397734, -8251694, -39161659, 15667944}, {24980505, -15157779, 24057809, -55106, 25738505, -9625496, -29431441, -2186653, -428611, -2112901}}, + {{-59861155, 7730966, 5343067, 15171445, -3435152, 9904377, -2961978, 21575454, 39420661, -10779987}, {-3667411, 15290322, 11879213, -1018839, -9352930, -8984709, 14126448, 3779038, 3631293, -22182215}, {20208094, -10365143, -20674337, 12040353, 26649578, -16622096, 7047463, -9265311, -7038829, 6022238}}, + {{5844248, 9329218, -26837002, -12631765, -1924121, -5689527, 26115535, -8674230, -52993963, 13986275}, {-42646266, -21978310, 244490, -7283455, 2736817, -18753215, 2655267, 22200210, -4094895, 4618381}, {-4821381, -9313798, -12867886, -12119302, -22060598, 16605302, -13372899, 4183677, -3168975, 7670585}}, + {{874764, 1026080, -23020362, -6508077, -15431910, -12847778, -2593129, 3352636, -32829633, 22115317}, {-44558004, 20363560, 25304644, 25121305, -3297410, -7752716, 43644441, 7132374, -18807691, -1390711}, {25218336, -15105684, 20100384, -13563112, 31371446, 1816197, 10586533, -2368944, -30923243, 16517917}}, + {{18954559, 2712079, 28879420, 13861899, -34820105, 29906073, 13798235, -6224918, 5997482, 7179198}, {20445041, 22110151, 9040812, 9474421, -9631055, 2810215, 24098571, -4682070, -50100850, -12869832}, {9276152, -8467413, 28810655, 6767044, -14793005, -3071425, -30896012, -13809894, -9166284, 8320089}}, + {{126982, 3682839, -13109537, 5133041, 17639152, -9466584, -28575722, -32547751, 40505143, -14234705}, {2021270, 3551461, -52953301, -16029777, 34814372, 16859246, -10347600, 335563, -11336195, 1346737}, {-14159270, 13552339, 22825885, -12410953, 2132839, -773566, 26032624, -10986378, 3471395, 3605917}}, + {{-39399837, -8355182, 53059756, 1019022, 21207611, -28768770, 40157885, -10602106, 12385270, 370831}, {-13726691, -9794896, 7349732, 8726048, -9936421, 2579930, 7389197, 19985910, 30588216, -25659699}, {-23333346, -13598637, -24502936, 14926238, -593728, -3173350, -19125474, 9885020, 4383659, -10964345}} + }, + { + {{-19603802, -5643093, -43867114, 14332784, -61984859, -26186041, 38206081, -18398124, -44404725, -8159949}, {-43470756, 27088661, -15481990, 7674560, -2166367, -7218735, -17028855, 8286080, 20325205, -19537423}, {24613200, -5618245, -5571478, -4996886, -7421610, 971727, 20270207, -2956549, 18166387, -5795164}}, + {{-41434767, 4940396, -4389540, 49275, -11408586, -2866025, -15258140, -20837715, 24704723, -12476341}, {17462521, -14802094, -9532510, 33293143, -22563748, -27165253, 14296034, -4883745, 31696431, 1819053}, {31212172, -3426959, -33496665, 468603, 15839340, -10550360, -2448605, 15705413, 12062149, 13444284}}, + {{9973513, -21090283, -56842664, -1857736, -9485792, -1572883, -11660999, 139207, -17475535, -13264643}, {34784813, 8451673, -5581732, -31429532, 5344592, -2356513, -21949087, 5370001, 38548907, 11812955}, {13213453, 12708416, 14293484, 8158250, 26119855, -1595999, -18040690, 13476632, 26797235, 3391523}}, + {{4575152, 20662273, -19216941, 9501479, -60081769, 5359171, 34655556, 21158819, -15005290, -3790453}, {29834326, 6360697, -18289543, 18793915, 2001373, 14737819, 7894700, 9554467, 4822220, -13236795}, {16428034, 16356947, -5821995, -15681871, -26366898, -6264635, -23112840, -9368094, 12251961, 9528760}}, + {{-31952028, 5377655, 36187832, 7405111, -6228544, 2455875, 7245414, -6460559, -10867102, -15087550}, {30616426, 16242589, 30622406, -18981597, 10704936, 21369475, -23873170, -940729, 9176454, -17455772}, {33248510, 15373608, -27355698, -10566187, -8681912, 6962342, -5739495, -14073168, 12519634, -8066785}}, + {{-24168453, -16479408, -6649457, 15270338, -16646429, 15731444, 38681614, 9463522, -23939326, -1332658}, {4761003, 12875822, -39674579, -8918256, -11736101, -14823434, -17328630, -15912636, 14424698, 29256108}, {-469213, -8171959, -13549599, 1676962, -10981161, 15586841, -17705167, 2723666, -32041126, -1521100}}, + {{-6017212, -5549830, 27177484, 2166190, -9612618, -14225331, 24588380, -11839501, -5494342, -6384723}, {-10949774, 10762948, -10056596, -26714934, -30761322, -4031775, -22693466, -16365273, -36442500, -3306271}, {-3891582, -16198826, -24541082, -7243985, -7758215, 5537387, 24815381, 136784, -4589866, -15049647}}, + {{16522000, 18053634, -27371531, -8191948, -12154110, 8416557, 11081997, -8905964, 806537, -18964242}, {-32848858, -3463858, -4242697, -11037350, -31982978, 3449951, -29340819, 12677546, -11479495, 10289006}, {15203014, -5091561, -32723026, -15567904, 14761744, 2184359, 8059989, 936981, -33237645, -8854612}} + }, + { + {{9837677, -2607676, 20178357, -19688768, 2558522, -18727420, -58320446, 4144069, 30101922, 9585873}, {13129089, 12960730, 44982295, 11050610, 22792836, -5267798, 8687948, 9049753, 18305776, -5473769}, {1102353, 12666974, 22302942, -13537021, -11928818, -6085966, 26314378, 11472052, 25410139, 11377342}}, + {{986592, -15755811, 22009102, 20814482, 61267677, 27948149, -4491240, 14982613, 17538699, 10508198}, {1521066, -16858799, -20201788, 1483336, 1192519, -280879, -50475902, 4073211, 18960837, 285284}, {-8291661, 5575633, -13654168, 6343458, 8174236, -6708508, -32707451, 9271709, 26779883, 7692720}}, + {{-2957975, 37766, 9539688, 4921220, 11552799, -6115941, -6892506, -2212218, 596386, 16550818}, {37847823, -8063074, 4029294, 12811026, -46466477, -1095011, 50102376, -11294682, 15921834, -3412346}, {-9106740, 1285800, -19477422, -14551961, 2271228, -7359281, 519182, 9055293, -19544071, -12362094}}, + {{-39137312, -1718814, -1636413, 12092079, 32833389, 22829655, -34086853, 15680798, 40874209, 19815408}, {11108870, -18059802, -6998131, -11996791, 7165103, -512863, 26571085, 15206310, 25179629, -13659864}, {27510118, -4898975, -11390514, -15849140, 20658520, 15709350, -14256333, -3111238, -23081311, -16576185}}, + {{-8551498, 20401767, -58556332, 2510777, -58616583, -28822, -13231064, -7330565, 34348160, -1955173}, {11645588, -4816561, -3759348, 21406417, 4425465, 8778736, -8692836, 18797813, 21234836, -14185173}, {-317585, 1908637, -14377950, -12843490, 22768039, 12744777, 11022318, 7586747, -11226979, 9002105}}, + {{-47158640, -16772944, 26266534, 17873836, 1065635, 335890, -10031263, 22400922, 2083016, -22333226}, {-1740742, 10836084, 32483460, -15035628, -54748963, -26499710, -30024275, 3176738, -12644374, -2647560}, {-32143363, 15197820, 10833962, 11761878, 14569475, 3769646, 13424782, 464216, -15761096, -3871309}}, + {{11047134, -384577, 28158262, -13631995, -14591131, -8007127, -5121543, 1969265, -57638947, -4646192}, {-53201390, 21540133, 19969824, 17002409, -19385217, 18551101, 18902729, 19637557, -9184587, 16628338}, {10645328, 171115, 8988235, -7484204, 11308452, 10599320, -28836218, -9546533, -4508963, 13817404}}, + {{-18598715, -8204260, 46554290, -3972234, -5962527, 14684835, 42815485, -23799613, 4655468, -5981867}, {28113671, 23616250, 2657614, 10905660, 33258015, -10190475, 21391919, -1747023, 32773778, 5741719}, {-1205848, -16389911, -31335189, -13953695, -20458357, 10717788, -13377567, -11274027, 12742455, 10976284}} + }, + { + {{-41024668, -9877063, 610501, 687470, -57798428, -16151392, 708322, -28028073, 28553250, -22584450}, {4281748, -5235995, 29396891, 5455920, 5599012, -12829074, -18332238, -2776639, -13744578, -7846766}, {6867433, 541206, -12581916, -16526557, 25227505, 10499117, 3895512, 9663944, -25790398, 4119878}}, + {{39162052, 3903741, -3908266, 10929339, -23416889, -20866175, -32678760, 8939835, -6006117, -8891068}, {1619176, 9228347, 30746950, -7345217, -36932439, -11785083, 32906702, -2153265, -31496785, -17235316}, {-5856108, -1446617, 23743806, -5963008, 6136016, -1179313, -18888696, 519290, 19032119, 11408112}}, + {{-17916871, 8451418, -62562757, 21695852, 18340573, 11533762, -20301620, -7116805, 53534436, 4239090}, {-34979977, 21741928, -4483165, 11534852, 19886219, -12770244, 33723682, -22847217, 8220982, -11635912}, {29087111, 4758701, 32485056, 4746947, 24287783, -2902553, 11817669, 10462218, 4866160, 9028780}}, + {{-35069994, -1496165, -14338699, -3536767, 17190544, 26133484, 62946141, 19977771, 16845706, 1542120}, {7390112, -10386491, 12509883, -16005273, -2279362, -5145672, -309903, -9852861, -40675314, -809208}, {10345044, 10573183, -7060326, 6695983, -23750422, -6736076, 5325737, -11780767, -21876240, -1005965}}, + {{-29820773, -6455280, -64377582, -8642934, -6599634, 16184775, -46535994, -20248177, -38489384, -25008060}, {23334183, 17132088, -2201718, -9711938, 57876588, -110627, 5192392, -652085, 20983558, 5901490}, {-30515039, -10806648, 32348204, -7806622, 665784, -8719485, 5425851, 12686350, -13464374, 13539981}}, + {{54971182, 15357420, -37007372, 6545610, 22706710, -6863872, -21169289, 4265499, -7937529, 7919882}, {-8971078, -16360988, 20173958, -18706226, 18523514, -6238852, 28829439, 13078421, 18601537, -20973910}, {-28106111, -4354954, 6334668, -12161732, 11833871, 2040195, -12416467, 13780587, 24868210, 10112227}}, + {{-7531044, -10112472, 3967911, -23644951, -50441556, -14079072, -2266258, -18342896, 4792795, -1946429}, {-19982572, -5908682, 34770683, -2454557, 1259758, 5383930, 60118216, -7264338, 62246605, 26020299}, {-9908931, 12605782, -26560052, -12885715, -2949603, -1517770, -33539741, -1710018, 5185795, 1061232}}, + {{-18891275, -739287, 5281578, -8199782, -29521591, 18423623, -19813362, -7657935, 1514614, 603040}, {33589585, -9082515, 32880812, -3754100, 15747309, -857609, 19276620, -23511651, 30548370, -11888642}, {8538077, -16318295, -5911090, 11509697, -17677105, -10383284, -12717189, -11268137, -11316729, 4256700}} + }, + { + {{2142694, -15849014, 24642949, -8168588, -35495720, -5300219, -47512235, 11174251, -4002237, 6487240}, {-7198354, -6903200, -11356401, -3522832, 14799598, 16556265, -6838721, 10689091, -38154767, 7286150}, {-32453304, 3754344, 21497350, -8708497, 23859718, -762885, -3786160, 4076401, -18329406, -9356943}}, + {{30632067, -16618538, -11410768, 10780889, -23780183, -15953050, 38909299, 16493642, 25546403, 13830176}, {4629491, -8688198, 28256060, -17626069, -8167039, -12886036, -13529907, 13081088, 15766613, 4012036}, {-19067629, 2815720, -6029213, -194855, 6029984, 6601656, 10088496, -5109482, -21806745, 6757046}}, + {{-18313439, -9859853, -3348319, -6767975, -36349788, 1733947, 5245546, 23235525, -31496512, -14777305}, {11516693, 10971083, -31691415, -21132849, -5898920, -20719593, -44104056, 7111671, 28405808, -18692681}, {-15760155, 7563636, -4891161, -2781329, 17135328, -11210549, -5708387, -3846806, 12678297, -579271}}, + {{-14593554, 18119213, 29271824, -5599594, -4278592, 1977100, -23019480, -8440920, -6891717, 2699123}, {49567964, -13931331, 26123624, -24225222, 41330202, -3323854, -13937236, 13473938, -16320673, 8745215}, {22238002, -12832840, -9482152, 9889995, 30868814, -13607639, 25698514, -9069575, -3172120, -10656554}}, + {{-52181458, -1367487, -16340626, 21629825, -37452140, 9775973, -39054474, -12028429, 10602123, -3463626}, {7492062, -11819557, -36858712, 6494165, -7796010, -18657921, 26841482, 9719503, 42278031, -16674142}, {-15714027, 1109172, -22574544, 4777304, -13357338, -15757220, -3911290, -9824223, 14020326, 4504203}}, + {{-3685272, 13964660, 15572356, -22541543, -20930484, 19649325, 28036685, -12021077, -41201626, 8270178}, {-31993038, 11671062, -12810932, -5479475, -33796464, 6743959, -21790797, 3558825, 17425282, -22568356}, {-3170641, -13080450, -11570623, -858210, 21099088, -10525270, 3181675, 7744886, 32509643, -10541136}}, + {{61570150, -6351153, -24868635, 31892298, -191469, 9171670, 17228190, -15503187, 32010753, -2812745}, {1803028, -24293339, -29502163, -1438964, -14749855, -11300528, -16106116, 7991287, -7018047, -8624755}, {-32283293, -11848447, -21341563, -13862381, 28155668, 10919886, -21965432, -14763817, 12730861, 9683404}}, + {{10560557, -4082309, 3104917, 19655939, -2082995, -4813105, -15589911, -3288619, 4719198, 19347002}, {2772995, 27255871, -58184621, 2614383, 19130087, -22576163, 45143437, 13343095, 37539714, -11378394}, {25044717, 15236842, -32235571, 11729681, 29740450, 7156238, -31715797, -9349217, 14963091, 3673915}} + }, + { + {{17483193, 21467423, -1591323, -9006134, 18801074, 11142309, -20838953, 2747374, 45476742, 13010390}, {29023351, -8173027, -19512723, 15449896, 46841422, -19674425, -1872071, 6298660, 1423894, -9048748}, {33002451, -5227527, -29846033, -13346115, -6902340, 1048865, -24350558, -1880902, -854515, -9554958}}, + {{14688424, 12735655, -16937502, -4016228, 5749722, 825173, 8158230, 17898817, -60467930, 13198214}, {6117604, 10285301, 36932732, -21717834, -41364420, 14847559, -32440254, -12680957, 769558, 4637816}, {-4061555, 10529869, -10185484, -13911327, -30723037, 5397559, 4844125, 1225375, 7650683, 10764234}}, + {{13538123, -18674056, 22365192, 21872768, -9226492, 10582199, -4335212, -12794849, 24240713, -18071738}, {-15738093, 8388276, 1125508, -8440178, 1034048, -1911003, 1621042, -2682833, 41418595, 1990564}, {-11686010, -4564167, -10893177, 1771245, 1274582, 5313908, 12847994, 13511849, 20105450, 2384127}}, + {{-15285220, 6219896, 6451658, 12007065, -43657520, 6191896, -26819787, 15780173, 18711805, 12851607}, {-3019370, -22136886, -56742030, 7375391, -19279910, 2838240, -37954597, -15754877, 32582697, -9026927}, {-4060781, 945298, 32046953, -590543, 2850097, 3357802, 4740336, 16066484, 18576720, 8054438}}, + {{-14540432, -13269279, -34705466, 4315743, 14449688, 6027827, 8742513, -14139854, -13445047, -3461221}, {-23028730, -15811467, 24115012, 14231831, -21052122, 12642493, -53280697, -4602488, 8627937, -19321547}, {-1393968, -8963414, -19300361, -11822412, -8307014, -2798372, -16541784, 12421994, 1462153, 417792}}, + {{-4668059, -9968764, -8918170, 11309172, -11651694, -13971714, -17324805, -27382719, -25365707, 21970527}, {30752641, -17553672, -40000466, -9583496, -40769424, -5180062, -7416627, 986079, -38074397, 5151187}, {-25197975, 10889710, 2074302, 16701072, -1184441, -4609339, -18753730, 4636728, 4028379, -7159106}}, + {{-11870770, 5171122, -33503201, -876655, 23805302, -15237773, -29456044, -18986554, 8670272, -18256782}, {-41515584, -535906, 12681209, -29692675, 33310160, -852063, 11421114, 10285726, 35544994, 1056982}, {12221193, 7527020, 32458392, 7981558, -18039033, 4817434, -15335166, -8469665, -4117209, 13725893}}, + {{22663146, 29732869, -21269448, -1076707, -30326997, 2094147, 4524432, 1120603, -29329347, -4818916}, {30325592, -3609605, 10287160, 2912165, 3114071, 23238219, -57948022, -23788753, -9187799, -14680484}, {-20751568, 5188145, -1831778, -3602865, 18762455, -9657296, -26589846, -12327940, 2307772, -13531969}} + }, + { + {{3738470, 6806917, -6520070, -10897511, -24188055, 1667133, -23436367, 15141053, 5199139, 4977140}, {22140076, -261769, 59257688, -2820917, -4981267, 26792385, -16022953, -643729, 2939013, 18928850}, {28701875, -6219062, 8144979, 13251080, 28719284, -8848901, -13494766, -13548711, 21905725, 6311464}}, + {{-40123606, -6588069, 48611592, 14812924, -4609749, 22775660, 20594442, -27366042, -11691916, -19989648}, {11042516, 26822251, -4993288, 11822956, 60713855, 7396464, -38556710, 95792, -48261844, 1788236}, {-4787463, 6302363, -27799488, -14546536, -33235827, 12332815, 18034131, -9318827, 6947300, -12794262}}, + {{-41916317, -18498954, 12896682, -16525176, -40290202, -15788122, -27846772, 21471253, 664451, 1375070}, {7416637, -6453076, -2130444, -11534458, -26313296, 4371340, -27759728, -8306503, 13656297, 8436872}, {17227919, 16214490, 19267967, 7556965, 18770244, 5484290, -12831814, -14044493, -25390327, 2194539}}, + {{-56739346, -27308430, -55476180, -11239913, 9739286, -14341354, -8336939, -8847596, 55360984, 21987700}, {7977560, 857218, 769390, 9310163, 36476170, -12194902, 4947105, 18846662, -7961686, 2123356}, {-13576806, 7411087, -15045940, 861424, -10989411, 11825283, 9111155, 8488852, 18174871, -9752144}}, + {{-23036900, 2125692, -35712986, -2572408, 43165259, -12743182, -5197169, 8798203, -33814611, 16302899}, {-26159332, 15245172, -16953236, -16921906, 23674331, 11214856, 1598045, -6650711, 23572821, -3571109}, {26440449, 133755, 19758318, 5090892, 4788418, 1827186, -16320171, 9981219, -13252712, -630893}}, + {{-34314942, 6414556, 55563439, 4361353, -10556688, 6027376, 17799925, 20469385, -29767576, 21665632}, {27539656, 11508462, 685223, -1223071, 7166162, -22350614, 42303153, 9043559, 17199660, -1640106}, {-4033417, 15802033, 25471815, -13054267, 9916614, 12439096, -15857402, 11118670, 9012861, -11993207}}, + {{-1024639, -12108992, 4567250, -4821543, -33283727, 25812786, -2839767, -3634522, 53439675, 11411859}, {-37192361, 16503820, -73436, -89097, -4368403, -1339858, -48555041, 13376758, -2912495, -8702321}, {-3794781, -13136002, -13950925, -6247393, 18266603, 236991, 1041825, -994782, 7952989, 5302871}}, + {{-18119566, -555624, 58996406, 11596601, 46711212, -654569, 32013940, 5911401, 4438451, 23446883}, {-28110526, -22249960, -2152858, -16464333, 4074200, -13699569, 20968358, 21027297, 34923221, -8492061}, {-16904139, 12540396, 5620177, -1802274, -521455, -9335956, 29448915, -5702647, -7987239, 3630179}} + }, + { + {{12591644, 22159517, 45571918, 13029776, 46556602, 4830479, 41411109, 12046748, -58198390, -11596763}, {38301994, -8496503, 10446328, -19463286, 17655978, -26850125, -11315475, 18600976, 5412234, 20803831}, {-17632683, 8738447, 16357440, 9209779, 18829510, 13065089, -8127903, -15381601, 26220416, -9755705}}, + {{14177715, 9440160, 39938701, 4681376, -36096046, -10418968, 23065821, 27571057, -34577851, 7774755}, {30199491, -5650938, 13070879, 20267452, -6778768, 2790644, 4315115, -3334179, -31133917, -16191275}, {-9501784, -5031472, -29798389, -11258641, 17764614, 3899897, 27609666, 12319738, -8027490, -16630904}}, + {{-11699062, 3637241, -46962960, -10160349, 7273829, 23649189, -32924862, -13681360, 45590947, 16238133}, {44154594, 23741965, 9485802, 20274783, 28555987, 6947793, 8671790, 10989966, 12275299, -13298431}, {14652917, 14296411, -29770150, 10860994, -6026464, 13434770, 7429042, 9960010, -19218799, -9160206}}, + {{5366556, 11152466, 5823897, 2653695, 15133234, -7148640, 33719264, 9182005, -24816973, 18798375}, {-34762570, 9773470, 47732739, 2870449, -100284, 25962086, 33058498, -17547951, 5655441, -11863911}, {-14631533, -14184653, 13764627, -6461784, 4387385, 4866889, 25642753, -2157149, 10877130, -13910995}}, + {{-21626613, -8635584, 23871605, 11704718, 12257850, -6515884, -10653466, -17082100, -981817, 12604805}, {9115705, -19460954, -17068981, 6035042, 25291048, 7944066, -24555090, 12124848, 19202385, -6237263}, {-14533513, -15046020, -29795172, 1382019, 7783365, 12218772, 7664868, -1271157, 21001150, -10882000}}, + {{-22443837, -3278121, 45604952, -23413718, -51665140, 9773090, 10551883, -11001823, 12930311, 11981367}, {-31381113, -25871583, 8924620, 7668408, 10817278, 3861974, -50848635, 676905, 45970255, -16910009}, {-11191171, -1519528, 15007122, 4916314, -17211931, 967948, 9070158, 13268535, -23988397, -7067127}}, + {{20106485, -2843332, 865761, 2533345, 2929876, 6049643, 58194301, 466469, -41888370, 18988926}, {-41891103, -25124458, -55911967, 22418615, 62577820, 1554259, 7229937, -15630215, 19894016, 13655656}, {-18159525, -6243765, 29656888, -16099832, -27160808, -10436660, 16269815, 11035304, 29795808, -12945009}}, + {{19963474, -1354545, -43082808, 11482511, -39529103, 12846294, 30427313, -20848524, -31768998, 3348335}, {-30521604, -13791963, -3486620, 7003293, 16507403, -4510348, 19767065, 6204174, -5380610, -25751039}, {11012574, -5313970, 14922430, -16396213, -568274, -13259503, -21229604, -13485170, 29672659, 8020257}} + }, + { + {{33415314, 8935847, 20575732, -5989115, -2077310, -31629838, 10174297, 7918881, 14277654, -2522145}, {18796036, 11515829, -26341750, -18282497, -6278492, -959926, 32899969, 20876811, -32839540, 5864337}, {21550307, 2275228, 4927931, 14261390, -27648146, -4533352, 8248502, -2822002, 5613183, 2560827}}, + {{-223217, -22768392, -45525457, -4793157, -16121107, -11018665, 4789789, -10425166, 22605248, 13365262}, {-38969511, -9331626, 9825759, -26130137, 8260681, -10112241, -6922361, -9288414, 31646000, 8565862}, {11605023, -13465051, -15209306, -13612207, 19230876, 9598195, -32187147, 14824784, -5317844, -12122633}}, + {{-19339154, 21231144, -2166785, 7793076, 17270165, 7508588, 3515854, 11443875, 14226705, -12804553}, {-46617584, -10937038, -63869361, 13249330, 47239387, 21396988, 49200212, -20266527, 40611343, -4057571}, {-15987479, -2785329, -8472794, 2305526, 9347523, -12035002, -29608536, -3601332, -24047252, -9945032}}, + {{16192366, -4639192, -24929048, -10035998, 21769211, -3294602, -3774844, 10077552, -6047589, 10088555}, {-34221574, 28118666, 21558284, -12289236, -25844273, 1213590, -56913062, 19093596, 34323337, 22517731}, {-20367915, -9650057, 16080513, 4740764, 14926534, -13507506, -33435459, 7117583, -22421758, -773279}}, + {{-11590811, -12486994, 6857453, -10581230, 56247370, 8638570, -30639674, 96854, 12350869, 895287}, {52242329, 5271826, -46498149, -20728924, -1866918, 11946444, 22240448, 16899414, -47795731, 16012777}, {4652271, 13637900, 4000742, -2835219, -15676600, 15348101, -8685770, 15250576, -8140380, 9857872}}, + {{-12592837, 11554340, 23804250, 3350424, -15253385, -13215355, -45129304, 7870624, -45050509, 2994691}, {-46319533, -18565804, 19788862, 20214996, 8869841, 4656673, 13655346, -20171172, -13460899, -14137387}, {4722572, 10806684, 9487098, -3047743, 31196864, -10032748, 420200, 7795475, -5608109, -14642975}}, + {{31224954, -6899866, 28320056, 10750209, 29443459, 1008548, -25441751, 2525118, 6331705, 13112230}, {-25804448, 3068766, 25911822, 6380327, -26288837, -4340438, -33065685, -14811758, 5693183, -19588494}, {-8151699, -9117298, 9258947, 15060309, 24828599, -1024298, 18824775, 11154865, -26906427, 15012221}}, + {{14119739, 7823199, -16275881, -7624482, 11144011, -2875661, -20056080, -4229491, -32760678, 2590714}, {9627191, 18236503, -27236629, -25837616, -45444437, 26025595, -5995972, 13583987, 26988550, -24154834}, {26370245, 10789731, -6785238, -13517725, 4168988, -3492154, -27236508, -12641367, -21787846, 7435359}} + }, + { + {{4025709, -18443049, 63145583, -17093650, 9160084, 442019, 6137549, 11688790, 10446734, -5877762}, {51028153, 10088979, 266211, 8379088, 41412198, 15574635, 59882137, 9771596, -47033066, 26421194}, {-22143940, 6332934, -5899499, -7459829, 20257201, -2161124, -22839614, 7413369, 14836514, 667274}}, + {{-14940628, -25247842, 10939384, -8204221, -46631366, 10606092, 15321404, 23272801, 9968507, 17476099}, {9622502, -7713926, 40663578, -18208253, 8291926, -17699142, -21443082, -6369739, 8731231, 3075459}, {911575, -1965705, 32801069, 7303022, -24865207, -6586476, -21037828, -8619572, 8268268, 13003069}}, + {{13391403, -14369812, -8495941, 15348703, 14039596, 12429524, 41821521, -5658261, 13750930, 6438876}, {37821067, -12493324, -35374899, 11675763, -48025748, 19633964, 6958553, -12969327, 35409782, -8167538}, {30911389, -4773241, -7102624, 7733251, -9660818, 3164814, -26044459, -5006731, -14247956, -5637609}}, + {{26944116, 11925, 66230473, -13659283, -11712891, -1450033, 38104492, -4643346, -51938065, -1863542}, {26513594, 20634555, -317371, -1074059, -12289915, -7238977, 3578752, -23025196, 14392431, -12631060}, {19086246, 13108905, 4585208, 9845640, -30881832, -12875727, -17744269, -15873825, 2163716, -11296357}}, + {{-1519327, -8701848, -19900325, -19237335, 35270482, -4058364, -2760111, -9187123, -24809820, 958912}, {-60143087, 24434408, 13330213, 2757095, 8879892, 14250846, 11171953, 19899415, -37791526, 22278482}, {31761595, -7987220, 10232969, 804235, 29770030, 9696724, -14890810, -3285397, -18187339, -10613633}}, + {{-32730866, -17348548, -5919344, -20494304, 15333268, 28523996, 55878583, -28368677, 6837327, 4993611}, {30033270, -13705710, -5162882, 840858, 28865852, 357546, 582019, -4017921, 1358927, 8174059}, {21252600, 2681360, -17716283, -8252559, -16622936, -9188324, -1401976, -754088, -1405316, -15305444}}, + {{19061825, 16984239, -15705648, -5158012, 45632648, 9152108, -45407737, -24127941, 897835, -12082177}, {9835713, -5561447, 1267434, -23647200, 1842256, 21213416, -10356573, -6829705, 64476145, -683241}, {-30552595, -12160723, -26873350, 3292037, -20145367, -13037247, -31356772, 3087465, 27506284, 9790325}}, + {{31218109, 2219693, -17554694, -2249580, -18769049, -3212128, -16635537, 9637750, 25613573, -7514198}, {-29731409, -1525607, 34872882, 27080576, 14089863, 14087084, -12185371, -23852912, -20434919, 2201374}, {-5069914, 4236508, 20683731, 7163480, -25409383, 13489940, -25275733, 10045725, -24985967, -13203315}} + } + }; + const precomp_data_t c_point_H_plus_G_precomp_data = { + { + {{-39816155, -14164145, 48882322, 7837288, 41754222, -8201549, -4905830, -940314, 5566603, 23894046}, {-3897773, 9695913, 9748846, 7901230, -1867182, -15802569, 45602682, 28911996, 28118415, -8768894}, {-22093752, 3067055, 30439696, 178853, 18503999, 4759602, 2547356, 14224684, -11930853, 7527284}}, + {{-33178079, 17479951, -15720239, 7540167, 27425573, 2953492, -34953726, -22060024, -36629404, -11328152}, {21324973, -3140901, 44002477, -8150207, 9851945, 30239584, -9317524, 6239104, 3110932, -21123908}, {23176510, -3672222, -12879907, 10855153, 4567818, -2709871, 8880416, -8358471, -14822505, 6744257}}, + {{4781330, -10547915, 57841035, 13962885, 1005889, -17806800, 7849169, -1976802, 54527990, 11717841}, {60401008, -2322939, -7572909, 1160963, 48156737, -8617152, 44610211, -16172534, -9446496, 19859225}, {29596428, -841061, -7893253, -3338784, -254482, -5470475, -32104407, -9382379, -7944614, -8445992}}, + {{39674153, -20880417, -31299919, 7880190, 15754698, 11056602, 15516266, -30547630, -17858838, 10115578}, {4497415, -7215627, -35712505, -21138390, -36705192, -19073450, 2337440, 872088, 46466222, 8682426}, {-29955884, 11442916, 16603336, -7611518, 5660466, -10855859, 26643219, 16373229, -26939401, -1298463}}, + {{43102341, 18198569, 8522111, 5706359, 8916980, 12789951, -26578270, -3620357, -26589640, 926472}, {9883233, 269211, 12572191, -12735575, 22786780, -2406009, 19874534, 23449165, 33955000, 30091692}, {-24923472, 6151350, -20658077, 594681, 25606782, -6037728, 17807754, -15381768, -29259970, 14286158}}, + {{51826403, -20042320, 5147727, -3572212, 24208596, -11076997, -17339556, 20883653, 27109678, 27054645}, {-13082675, 8853666, 61177593, -25383676, -2370406, -14466031, -7691442, -8775889, 33066158, -559297}, {21403619, -1320936, 1360119, -8883150, 21544362, -2963323, -3310606, 16086066, -28510335, -8053339}}, + {{39056265, 8037988, 41799363, 9784428, 52925127, -18736311, 7924076, 3054646, 14375658, 20316097}, {-10245689, -2669280, -3665135, -21355352, -3715551, -5371903, -4893442, -29947104, -5453398, 7598109}, {30824562, 729643, 19143152, -3260694, 20969927, -5587726, 30493589, 1462502, 28653229, 14878396}}, + {{-14504849, -4563013, 4220720, -9490250, -20753614, 15257510, -28817611, -1960666, 26681323, -17931229}, {-2500401, -12353373, -8888886, -14805214, -39590484, -7403478, -1349549, -85204, 13251279, -13891541}, {6749103, -16059744, -17316796, 6901963, -5756718, 4914193, 13614189, 6932543, -16976821, 7805464}} + }, + { + {{-44275891, -10549189, -29633106, -1340455, -15599665, -7998887, -35451108, 13776858, -32587407, 18348606}, {-9395149, 15647601, -28188200, 31802895, -9180843, -24751947, -23861408, 382848, 32754567, 11525716}, {19941335, 10758860, 7228790, 12016419, 20288948, 5689631, 26475660, -4135779, 5184338, 15306891}}, + {{10755570, -8397137, 40506658, -11976361, 4026458, 7220523, -5929864, 30243879, 22426643, 10267958}, {28258108, -2037957, -22727494, -13664445, -57238946, 25895659, 15615216, -3005277, -36350911, 11364854}, {5370615, 13212887, 10228227, 6698108, -2642399, 2050167, 24589932, 730321, 20699130, -804432}}, + {{7855537, -1728788, -8172066, 7241596, 18927222, 14854403, -36749684, 12257355, 56266033, 12555330}, {-1908271, 21052618, -45686424, -7386012, -17039018, -10246239, 19254420, 3833491, -3814213, -7220692}, {13883675, 7156278, 16569944, 16588969, -26199383, 7401551, -14421464, 10408321, -17172928, 15458510}}, + {{17794920, 31469639, -30428873, -7218808, -723502, 2975322, 23234843, 2863881, 28870439, 13104642}, {-196758, 239089, 35995605, 7758340, 41156672, 20984780, 19101577, -23441029, 14306617, 411502}, {19726973, 11802972, 27683603, 12627856, 5217821, 6288537, 14447538, 7990474, -5564574, -2213531}}, + {{-23702731, 6702770, -15055475, 13293291, 11699010, -18178053, 697130, 3769109, -28255259, 6153291}, {-39579703, 23236612, -25625567, -4524603, -19531286, 4978935, 57018384, -595609, -2849043, 17575319}, {6905822, 11533546, 6577832, -89916, -32878805, 5774877, 16920332, -8161675, 25727859, -14748005}}, + {{-2955371, -3558440, -12188170, -14445359, -32360363, 7715772, -16250455, -12579521, -41679923, -16040535}, {-52567891, -1968260, 31681636, -170049, -8717115, 24856524, 46911047, 13924431, -23298237, 5893055}, {-32105925, -16746082, 13745662, -5439013, 7651536, -11363101, -18979155, 2062899, -29798386, -7471732}}, + {{-20573579, 14520367, -60191044, 9243789, 8326181, -7643250, 4690664, -3444268, -24227062, 11624492}, {-9281001, 15989647, 1359004, 10622121, -55808191, 23000254, -7565506, 23959584, -28258262, -7390124}, {29131250, 15551810, -30149942, 1993386, -16571959, -2899547, -15032089, 4422476, 11099219, -11684360}}, + {{16186045, -2013545, -53752884, 5434695, 34529660, -2391375, -25201828, -2112332, 7910643, 7519069}, {6164297, -21305655, -5276460, -22637987, -3412090, 2289719, 1541288, -26950718, 3180065, -7279669}, {7603051, 9278472, -10049272, 9382712, -7003090, -2295281, 10188592, 13241980, 31675094, 16318086}} + }, + { + {{2975510, -1577378, 22890889, -5670236, 461218, 8986275, -44510758, 4684468, 583866, 29578997}, {19723706, -22469934, -28100401, 23994004, 29345630, 15954823, -13556128, 9839972, -55632320, 1005363}, {12134884, -7584508, -21509432, 14429074, 27282079, -6602364, -29053434, -7441264, 24318575, -11506694}}, + {{1407898, 2582456, -4919586, -26454360, -7368007, -13719869, 60757731, -10808283, -41492701, 6629201}, {61057990, 29903098, 28430992, -4894826, -40460465, 9522447, 1443153, -6078853, -3098057, -3083809}, {-11163398, 2419037, 28832173, 889805, -26704627, 14084807, 17746839, -2772825, 19921864, -11161548}}, + {{-3962272, -3690118, -18061043, -5772127, -17503319, -16634144, 44538355, -16032582, -4398875, 6898215}, {31593788, -23527462, -48486767, 14759745, -14925507, -13602730, 11752611, -9655452, 2974399, 11968327}, {1969039, -3228099, -3003791, 16200162, -13377098, -258562, 13645098, -10481060, 5186361, 6385842}}, + {{-36235914, 8877168, 12072077, -17882844, -19808886, -18852943, 18265665, -27504581, -43276159, 14482117}, {6095148, -11723272, -43394993, 3953286, 24086676, -1638453, -48122799, 1634227, 2204931, 14373043}, {-20566259, -5480640, -2756642, 15726313, -29953128, -8188145, -32670951, -1309507, 7128752, -15681127}}, + {{-20107442, -11808548, -15656323, -12014820, -13493428, -5707496, -52054164, 6578313, -22285735, 20090720}, {-32212866, -1055690, -6777057, 7448460, 25835512, 24475010, -7334546, 24237757, -36771343, 8408984}, {-15713494, 7985225, -3569442, -1506701, 24625410, -1318351, -20059465, 4525794, 1689122, -1705793}}, + {{3122738, -10983934, -16969286, -8542449, 4121662, -185607, 13388420, 20588369, -1796272, 17334688}, {54996510, -1815770, 46604656, -13012427, -49071988, 13199547, 34978298, 5496051, -3518400, -14055130}, {10414456, -14616205, -19118516, -16447912, -18164989, 14150808, -17637886, -5247132, 29445603, -11448910}}, + {{12029006, -3257997, 43557227, -10814381, 13341517, 432465, -1549056, 17277135, -42831971, -25378562}, {-17258378, -6937139, 8136229, -2333299, -15880299, -12513035, -48841046, -12912639, 8346791, 7061462}, {4811171, -4798778, -9029413, -2806939, -17541829, -2631553, -8356050, 7470782, -3158007, -4732898}}, + {{-27857882, 4702807, -19403619, 15709479, 20626880, 4923387, 14211270, -12445725, -12348753, -21410306}, {9747986, 24912909, -10679843, -5528609, 37718652, -1581829, 18774428, -10987579, -52918005, 7024296}, {-29663347, 12694597, 14207632, 3295450, -5496877, 5123054, 26132781, -11491386, -15452594, 11868693}} + }, + { + {{47880066, 14225621, -14470245, -19705222, -46008472, 13221251, 15408768, 5643435, 28837478, 3855353}, {857820, -3301773, 41798831, -8303062, 386312, 818057, -6842152, -1911481, 22374950, -28291539}, {-31814060, 8064783, -17053164, -6176522, 19048354, -11591068, 7668908, 10258759, 1857924, 1592875}}, + {{-8354350, 13982902, 1438414, 3013202, 33012597, 26662689, 472999, -7510509, 12707279, 2935385}, {-44523142, -16191620, -19693918, 26866768, -9384271, 6719687, -35309813, 1501863, 19451035, 6808289}, {-17142771, 13261661, 13878175, -5224933, 13092929, 5712649, -24249045, -7621190, 22720777, -5735487}}, + {{14584926, 5035261, -48903167, 3873736, 14684796, -22599718, 6592752, -3579494, 41382834, 20929245}, {21955206, 12350013, 4054179, -1159310, -48935108, 7150278, -3074452, 20251724, -10661684, -4783395}, {-12038883, -14854984, -1653699, -9894098, 3332471, 12516008, -27467863, 16759479, 17054920, -1045585}}, + {{-371653, -21319317, 14269602, 14876936, 2675616, 20104303, 46577283, 15247014, 2295086, 19960666}, {-34337263, 9062359, 3605352, 3811574, -290942, 151793, 5609515, 17268538, -5824646, -1507552}, {31341569, -6150200, 30915203, -3934320, 9170042, -2821122, 19539775, -8309478, -21506835, 3909703}}, + {{32575469, 5038442, 5894533, -24684650, -26976210, -3130646, 35899912, -8306591, -19575522, -927242}, {30520527, 4298102, 60219981, -8778528, 31412296, 24862674, -23675544, 4980333, -2177014, -26498470}, {20799789, 10250199, -23357518, 5235379, -17318365, 4995373, 11351608, -14329977, -4241062, -7135437}}, + {{-33708961, -10681744, 44893908, 20160328, 42923179, 9915773, -3420761, 18596951, 11284167, -8998884}, {2582953, 8283502, 4386626, -1306842, 20441991, -4892387, 2690307, 12028025, -21980001, -5571110}, {11436030, 13706606, 18295930, -13040673, -11313853, 11794175, 12631614, 8169005, -18535511, -13157575}}, + {{-9640722, 6792220, -254348, -12924221, 24425860, 4517358, 1463652, -10259333, 22154576, -21700687}, {16193300, -20305974, 60516020, -2690805, 9602228, -5601208, 52465390, -1370049, -18119120, -1587787}, {-18665987, 8255087, 12358781, 13159454, 21161438, 15792077, 30147037, -16229979, -32698768, -14941592}}, + {{-2307405, 10485747, 39295370, 14588786, 4398246, 6429581, -1367673, -17148995, -1427005, 16592987}, {-36661597, -22159389, 20182562, 11367804, 50893914, -10502039, 54187961, -11518549, -15338969, 8686865}, {-589443, 10055237, 2248329, 1681864, -25869653, -10483390, 8141259, 9185076, -764620, -2255836}} + }, + { + {{-7539919, 9636200, -21714907, -6368333, -7235053, -6939034, -9118147, -14563464, -9413611, 19620509}, {-45327821, 4153668, -28809623, -4801677, -21486751, 2353782, 47659657, 5772650, -37372651, -13580107}, {31551118, 13663464, -32586548, -9442420, 1599988, 9648514, 7021663, 10037197, 8547400, -5396572}}, + {{7159452, 1840193, 25466750, 18577392, 835761, 7323218, -30678863, -16353979, -18852036, -7337690}, {-32831410, 18027379, 18863650, 8284076, -38140067, -7075396, -24839181, 2961457, 35059954, 14893170}, {-24266347, -5350595, -24950691, -10540916, -6804388, -13956470, -7127420, 8559388, -10225705, 2372921}}, + {{-13513356, -13649907, -6339001, -1958880, -48187167, 8902386, 962999, 7424926, -31340554, -22447536}, {-23638418, 17970353, -54753529, 24193844, 7095187, 21529604, -2360327, 10076102, 14010140, 8567408}, {-31310372, -9223279, -16586937, -13453731, 14498347, 233201, 27810972, 13029701, 402562, -3455197}}, + {{-27249316, -1605410, 34623441, 6711490, 36047504, 5231705, 40768761, -17656033, -55345257, -9075209}, {12561880, 15226052, -2767207, 21899734, -8226358, -22004263, -13717073, 5466303, -5911661, 5114417}, {8136691, 12887366, 29097493, -16010242, -18845685, -16525917, 31273501, 5649551, 25544463, 5891661}}, + {{-9060044, 28573534, 26621156, 2412287, 11736156, -21702233, 41606651, -11903065, -37425711, -4305523}, {-52689042, 923938, 26534790, -21929301, 9230164, 758897, 1252353, -18079999, -643561, -15073995}, {-11144596, -3685331, 28815967, -5860993, -15674460, 1972033, 25777812, -1617499, 32154038, -8896107}}, + {{-6369589, -13172710, -5064996, 9138800, -26749468, 11900879, -15940458, -2576560, -7092540, -25782458}, {-57529209, -10995646, -56002602, 16675466, 22787278, -18138335, -37305050, -19921114, 15505056, -7476256}, {20036634, -8236744, 9488775, 9980126, 793048, -5544256, 24326142, -16680515, -27516278, 5404821}}, + {{11502921, 11861465, 26708889, -25307943, 43650436, -16766722, 11011775, 21788652, 46378003, 11742133}, {-47650185, -6096437, 6293355, 1762141, 8158190, -10280788, 35269981, -366506, -4492163, -54793}, {19571938, -11208475, 12715447, 8032888, -18405626, -9156617, 24219268, 472527, -8931641, -16211728}}, + {{-8599983, 2034158, 19328980, 9714767, -17915523, 16006984, 14164091, -720137, 19355077, -10309490}, {39767111, -17528894, -1630748, 13701701, -44632761, 11807268, -28489629, -10680531, 322797, -14654952}, {1809044, 12210040, -32449423, -9338725, -7423952, 12752681, 26906835, -8734553, -8367622, 82184}} + }, + { + {{-47006746, 22052935, 20792602, -8280800, 32254004, 11436994, 17785759, -1221897, -13662270, -3275645}, {18913246, -3934333, -8493930, 5603482, -720236, 8682806, -9892239, -75935, 47506872, 28002705}, {-12998522, -13382572, -25058578, -8727237, 33120415, -9513563, -17530532, 8914472, -589545, 12119368}}, + {{-20528441, -22161340, -30056218, -15320984, 40597827, -5215401, -16411330, 5623363, 8146138, 4967917}, {-18880063, -7537208, -15812678, 8125220, -15761477, 4435839, -5843780, -11949479, -52544210, 103971}, {20876164, -5702948, -30661348, -15372457, -16354433, 12735128, -7683175, -1706780, 20482728, -12025587}}, + {{-15181362, -1738141, 2937403, -4560472, 56106319, 18388054, 17281731, 2547295, -20480012, -1402021}, {-13301360, -6911083, -50796187, -25175850, 9723393, -8085126, -12442115, -8939305, 259254, 11964369}, {-10278774, -8926581, 21910465, 11128139, -33177783, 15466487, 20599725, 13573408, 4036183, 4175976}}, + {{54200020, 12073598, -749739, -7578170, 12017807, 11479032, 18819357, -30580182, -5661613, 482835}, {1378798, 11508946, 15315091, 18385986, -17543837, -5127372, 41636169, -798590, 4491173, 8249327}, {-10980326, -11152026, 27249123, 5129660, -3354569, -12162018, 13624268, 10802616, -25244815, -7042942}}, + {{5380650, -2641214, -19286494, 21327095, -30667976, -20148346, -35733992, 3369526, -7982752, 10619641}, {-45099848, 28173840, -20372660, 6613511, 11561244, 5875282, 31187260, 4610810, -29858618, 16996395}, {-19519076, -11159398, 18325381, -2841346, 32378721, 8265003, -32477166, -6929808, 27632659, -1154477}}, + {{6952423, 28751626, -3627919, 7286683, 32291810, -2792450, 4091282, -7150922, 19624973, -5193059}, {-58036529, -3933022, 50972131, 10172373, -28197802, -11919806, 35212826, -10942488, 42827699, 15831257}, {4119541, 6283558, 29775101, 8468756, 22993602, -13511415, 16193943, 11355974, -13095932, -16702609}}, + {{36793192, 17715925, -47017796, -14058455, 14972505, 26066588, 28864773, 5891275, -8060731, 12830682}, {11152062, 14259313, 12115186, 19300717, 48065293, -1460298, -25375661, 19922469, 33108561, 3505536}, {11491384, 15053639, 21255018, -14953116, -18661055, -2213136, -16327369, -16397206, 17857063, -3455721}}, + {{-19201792, -21056533, -4688573, 24718809, -3249546, 9920935, 12519271, -4245354, -1652915, 10661070}, {35094748, -8177713, -37040773, 3836519, 39743782, 22508963, -54135633, 20126170, -50823579, -7794132}, {16323604, 15349402, -32076211, -4707988, -7798519, -3064483, -26758500, 13292075, 25656674, -9043825}} + }, + { + {{43734659, -5319012, 46016463, -1620988, -38496562, 87293, -42546871, -7604965, 578936, 4426260}, {-5432409, 13064322, -20467239, 22120972, -15091024, -26535371, 2635367, -24677553, -54376868, -19781556}, {14345465, 16270852, 4756840, 7458194, 33275228, 3859916, 9802211, -765685, 70576, -14370386}}, + {{16611858, -1910689, 14319970, -10912303, 5232448, -2539253, -14037507, -25466057, -13570421, -2411747}, {-37413772, 4902867, -52467614, 6283407, 16050762, -7675881, 41640783, 6681257, 337963, -14342581}, {32861921, 3390058, -18056251, 14576342, 31934267, 7199830, 28917854, 12944757, 17111743, 5007086}}, + {{-7500517, 21308112, -37722218, 8083693, -18833401, 29186607, -4472399, 12369414, -16608573, -2621474}, {24589151, -8107860, -24991284, -17719105, -23421711, -826369, -11449941, -10445110, 35787931, 3057602}, {-29008638, -11234989, -5718810, -1901776, 24867316, 16042440, 33300654, -6687520, -31368037, -8960341}}, + {{-23670453, -1093376, 18609580, 8122059, 47415668, 11784982, 4471102, 6501945, -54795554, -364561}, {39376025, -5880334, -23389712, 24428343, 10589228, 19695952, -27661262, 13470783, -5521988, 29658649}, {-26687343, 15201886, 118242, 3657794, -28872101, 5501148, -15305078, 16654470, -15261454, -14594552}}, + {{-13306269, 19947636, 8483811, -3190176, -23627707, 10252917, 14832587, 24759739, -902752, -1166842}, {-26114653, 11829916, -54505725, -28666150, -29923991, -16228737, -4727451, 5781843, 55410772, -4561886}, {-29735991, 11466236, -14569729, -11827406, -26512116, 6710111, -10274674, -14237170, -20461738, -16244003}}, + {{12625398, 20046721, 5286337, 7474914, -22825196, -6381699, 9714385, 16895522, -13126949, -14199931}, {-2031800, 9361451, 28810765, -18545230, 7579584, 16517267, 14150271, -11432708, -11386907, 12185845}, {29962090, 3436662, -30434232, 16542079, -15783147, 6389271, -8401182, 5098617, -451357, 15925153}}, + {{-21081701, -9429138, 18520545, -23679835, -16457908, 25085243, 1855293, -14824660, 27942702, 8972269}, {-45958849, -17252154, -36117755, -5614007, 2734706, -6273399, 52441231, -13591968, 8620728, 5175773}, {19264689, 1667404, 33205073, 3308919, 687683, -8250375, 13373288, -9785873, 11395092, -1751113}}, + {{-19999590, -20756181, 8948023, -22355120, 57822735, -6417901, 9163919, 16852846, 56150656, -23780885}, {-17273210, -3051139, -48089577, 2762258, 2931577, 23780341, 23017019, 10235004, -6633220, 4094699}, {-15471108, -7628914, -20513916, -5495033, 24194398, -10045738, 3339675, -6469880, -26817235, 170334}} + }, + { + {{11043804, -21056413, 25089102, -23689432, 8790566, 7233991, 44727817, -5513045, -24304116, -24807950}, {39999434, 887787, 23080950, 792782, -5434700, -25043299, 17882515, -15450801, -423426, -5918810}, {23824631, -5728349, 5017134, -6480680, -23176854, 15426646, 21535341, 13596483, -31731756, -9009266}}, + {{-27396310, -8333033, 10986646, 8586168, 6785995, -28090074, 7941057, -17083636, -27899235, 9838332}, {-37871958, 154117, -52690902, 13816960, 42499085, -4482764, 48719803, -3174796, 4349027, -12371940}, {-28501050, 1590284, -32590995, -15830730, -18209072, -10354716, 18729561, 2693146, -20269448, -9203605}}, + {{-5417941, -3424753, 30842445, 9195024, -12394505, -18152018, -11189800, -11080382, 8589175, -2910070}, {43086965, 25206781, -34785907, -22089246, 24552255, -4805866, -4482744, 18017836, -14735643, 13311078}, {-8935163, -6369419, -28359239, -11248624, 21311049, 1317697, -29891217, 4173532, -30402596, 15076650}}, + {{-12264026, 13499738, -554276, 7911328, 5642702, -4487235, -33195201, -7547462, -6794648, 23195101}, {-21962104, 18804840, -30339708, -4031892, 38225180, -14220233, -7777789, -19438232, 22781890, -547965}, {32870892, 12137760, 18144990, 6711236, 11978906, -8820990, -2304588, 3559244, -8510327, -13421304}}, + {{-52986775, 12866719, 1610794, 3617512, -30276811, -10032788, 32625752, -8521784, 36232382, 19481123}, {3030971, 379053, 25866748, 3490964, -30817835, 7579484, -22858980, 9847760, -2371614, -5099489}, {32600431, -16683718, 25469662, -7863878, 27145324, 2231208, -25947987, 8612277, 25004875, 8507401}}, + {{13550201, 20507378, -3075593, 29173187, -49171591, -9693568, -44839713, -660091, -14277642, 18757544}, {-50645363, 6332734, 34190113, 636645, 17696443, 8057372, 5049185, -22967915, -28892196, 10920130}, {841263, -5293490, 2054521, -16537763, -25582619, 14313554, 27411062, 3822201, -18603128, 8312231}}, + {{-22602757, 13740868, -7303800, 4602319, 30573397, -13242526, 11086875, 6457252, 45452323, 19929429}, {-23754957, -13960182, 51455444, -22458279, 33235925, -1672610, 32592089, -4573286, 11320673, 8405483}, {-23879553, -7888804, -29791171, -12847132, -1235076, -15092650, -21935205, 12760100, -29339533, 15761064}}, + {{-2694348, 5098757, -11181611, -17830607, 15473799, -6229150, -24574053, 10298157, -44445244, 1811460}, {23717824, 27608831, -6887543, -9211003, 10428489, -19796712, 11021297, -10556929, 2178676, -21845872}, {-19590486, -13933828, -5439581, 4275259, 2098080, -12142172, -18225325, 14993971, 5425290, -8733882}} + }, + { + {{11868497, -15697319, -34268477, 16386778, -26868445, 15273532, 1480123, -18429566, 19765721, 17394524}, {19027887, 7192035, 12175469, 12676252, -30507951, 11707640, -21602451, -1577106, 2601223, 15479076}, {-7311472, 11351662, -17020174, 1960486, 29137035, 10865402, 23151197, -8175138, -6541259, -3657642}}, + {{9066941, -7381651, 51291726, 6711314, -41686369, 26395419, -10311274, 2359341, 872108, -6244488}, {-48442999, 2273909, -2525474, 25866780, 422887, 3382637, 34569616, 29208299, 18670392, 6639296}, {-27264479, 3582609, -10865205, -9931850, -5815604, -7506492, 5258546, 9844697, 9620260, -16046213}}, + {{-45366823, -25595363, -14185658, 2792812, -1406255, -9514017, 13078107, 17920026, -9641979, -10451827}, {1673165, -4266617, 11678154, -16004648, -63153053, 15162283, -39261865, 5278734, -37064813, 308469}, {23216144, -11791662, 6983650, 16064509, -32439035, -4711682, -32554489, -7478003, 11386580, 2460998}}, + {{25014893, 1661827, 35291946, -8325231, 19066372, -7871500, 34292790, 14328673, -10766114, 202214}, {27860965, 11944471, 23517710, -12963093, 4143268, -7019080, -640732, 6818193, 3774858, 19112238}, {-5098815, 2127323, -15039286, 9136963, -28256147, 16187371, -32731642, 8523431, 25045644, 223176}}, + {{50664585, 9322598, 19045209, -9889331, 23897592, -1310554, -4326164, -3657302, 11756593, 12619930}, {14272493, 9445898, 21434933, -6904549, 22350086, 9627926, 39938834, -18462276, -17512323, -1432994}, {14976161, -6822416, -7305954, 10992127, -11702300, -13259011, -28504633, 4143217, 26906184, -10306442}}, + {{28675118, 730638, 50340525, 14203387, 46493654, 22076072, -33261142, 8962596, -19605777, 16890867}, {37699570, 14485336, -5370675, 5271311, 16688070, 4156724, -20296922, -22625348, 34914055, 1900223}, {6562372, -11538119, -5902312, 12288803, 17014998, -352611, -26944539, 8861346, 10220582, 1452785}}, + {{3737307, -18904342, 64597078, -14042352, 12310755, 25424280, -35654520, 23472428, -61527131, -7556604}, {-37953739, -3969890, 1324420, -12004366, 39682155, 6455782, 26173376, -8499360, -4027711, 14656856}, {-1493633, -9433218, 4574097, 11407729, 31951489, -9687820, -1960263, 8177264, -29685295, 8838512}}, + {{-9181421, 7414816, 52381403, 9121363, 2074896, -14432263, 36641428, 6525110, 5596258, -8764633}, {45933847, -4758718, -5001577, 18761461, 62010382, 11543699, 6422236, 16736246, 59245546, -9856947}, {-29095073, 11416823, -18243034, 5629155, 24543272, 10401618, 12511961, -7280966, -12730211, -708266}} + }, + { + {{4274524, 4043839, -3436567, -27481630, -12762020, 23378465, 19910257, 4913107, -28189976, -2860031}, {18406284, -14642887, -63449915, -863030, -285954, -9288393, 42341973, -12024559, -22407158, 9482419}, {-18058683, -8621771, 24921325, 5278095, 3129192, -2553350, -23858739, -12224329, -24340787, -4546840}}, + {{-5499935, -2106328, -12451912, 19452688, -54368327, -8220771, -28990438, 3834078, 479955, -3213376}, {-17012887, 4786820, -11197850, 10714672, -11240765, -20691279, -1522762, 10982182, -7089813, 7633296}, {-23325848, 1459410, 1522332, 9664337, -3801705, 1847048, -13410787, -6281860, 1562599, -15096582}}, + {{30622958, 24906198, -35101214, -11879242, -18715863, 9057270, 5075352, 21951583, 45884824, 2643432}, {13266016, 348498, -23380786, -16792532, 17571361, -14434194, 44313334, -4280113, 11549418, 12208036}, {26895749, -15969948, -30058895, 13648122, 28837164, -14314292, 22466429, 16445787, -15153187, -12487027}}, + {{-21674573, 11232028, -25758077, 12198258, -38742442, -12462435, 36857050, 3032813, -47633805, 4282955}, {24718159, -3746650, -40637029, -18179914, 27761490, -18098213, 15787118, -23735657, 2037029, 15964843}, {-27286718, -12408889, 24851666, 12931506, 8307759, -2266172, 12434919, 15016983, -23277661, 16245465}}, + {{-31447267, -5415111, 33056600, 6951713, -26536105, 7700093, -11835192, 22400862, 41776236, 856932}, {20376065, 4839581, -3655566, -15695319, -31026483, -6749275, -31021074, -518708, 25216662, 22944914}, {8360147, -14325725, -18313567, 16261547, -26556470, -6476300, 1647620, 14461306, 3301654, -9201704}}, + {{16173558, -22951298, -2997348, 13903933, 22219511, -10474787, 12085799, -10966125, -7555703, 25722726}, {27971794, 8240868, -14328426, 10062703, -36555115, 11719359, -32024967, 8420287, 11077871, 5865106}, {-18560176, -3802162, 28514586, -11754909, 10317955, 607211, 27209043, 5972680, 5193874, -7034813}}, + {{-11821884, -7952985, -33020217, -25097199, 31154469, 17429913, 59044666, -3824103, 27604607, -10355219}, {47307216, -22733273, -29410287, -1772129, -30735969, 10432159, 2786244, 15070221, -37362553, -4774799}, {-4242055, -9074276, -27644267, 6498676, -28316989, -11838829, 21733081, -4025959, -19805396, -5162801}}, + {{51842380, -29895254, 11656750, -12072397, -5593318, 21989962, 5965537, 11990104, 44857092, 11836311}, {-13322340, -2798438, 4498144, -21036269, -26363924, 866862, 33252693, -16927192, 11656052, 16144963}, {21364854, -1862192, 24090206, 2902059, 23631541, 1800706, -7273027, 6531510, -23867735, -14401077}} + }, + { + {{5865692, -10990278, -49548354, 771099, 17186560, 5335367, 10468747, 10163615, 52929227, 2171626}, {-10901652, 17180646, 157162, -25525593, -17572704, -20528723, 47051193, 8174325, -10136135, 6495104}, {-8204966, 8235740, -407041, -15919231, 18364222, 15026736, 18597875, -10166673, -9414578, -11757991}}, + {{-10620328, 1198843, -37929729, -11608122, 20480468, 27536757, 12170690, 7423691, 10301440, -12736492}, {43745252, -21035541, 3438449, 14565576, -42395858, 1092785, -30097654, -2539473, -9410188, 825662}, {-1324395, 13857709, 2453979, 9006577, -11123272, 4638946, 18392923, 16113861, -23790723, -4481210}}, + {{-57914452, 28683635, -24569693, 13929141, 7131270, -18012389, -13169297, -1418990, -12971680, 17334927}, {-8518276, 1776957, -16914507, 14556573, 24016058, 6122261, -46009447, -1300374, -10222214, -8793587}, {-27768700, -909734, -20564255, -15908800, -7521595, 6373943, 11064646, 1195344, -4531986, -4886072}}, + {{21647556, -3796541, -21502048, 880719, -342288, 2282331, -39115512, -20744592, -31100237, -24433937}, {-8160646, -13936417, 41711308, 31098987, 16658418, 6818397, -9007358, -11918838, -29796567, 176149}, {32238907, 5231486, 1497188, -4651881, 21946425, 5030819, 1264715, 14943645, 30894263, 1625632}}, + {{17203878, -4796080, -21130245, -4160173, 5606274, -29031362, 23204629, -25696419, 38432167, 9226813}, {-4668224, 21518930, -15908641, 7679225, -50575008, 3569644, 35259827, -7140159, -14278545, -14846537}, {-15203667, 2386472, -20251662, 9962415, -28531198, -5270844, -23223743, 11417386, -30217541, -14504578}}, + {{-11206718, 9200636, -22908572, 9460721, -2823776, 17033139, -54053169, 3319518, 12838480, 22750692}, {-9752604, 9190512, 38513758, -11442623, -58442626, 12761629, 4376113, 14118008, -15040304, 9091106}, {16752388, -16143747, 33314870, -14311799, 32157971, -7897476, 14140004, 8370204, -18523694, 483143}}, + {{22370069, -9339523, -18801952, -29694324, -58952488, 8784277, -10575482, 4180677, 9096253, -9393846}, {24595611, -22263643, -18300354, 3669876, -4929472, -235397, 53928782, -24964699, 33718097, -19141618}, {24428247, -871725, 10210264, 9478951, 3623055, -3814634, -7313353, -10162077, 17467920, 7478866}}, + {{-9283312, -26068376, -6092731, 20047102, 29778957, 12622472, -26158322, 493978, -3600563, -1191718}, {-33854016, -1622716, 13886351, 5847670, 17650007, 5431806, 36696916, 14118562, -19676177, 11832314}, {-16338391, 5600499, 21868803, -5014094, 32567511, -10507217, 24242605, -10006561, -3539820, 7939342}} + }, + { + {{22056877, -23746613, 32915302, -8097070, 60146192, -560866, 60093742, -9504884, -6423528, 26871254}, {-28561339, -1184089, 15977638, -5183824, 3976576, -29827192, -2534322, 9081748, 45910056, -2061508}, {-26351622, -5119641, -22244376, 15796890, -5024905, 303706, 28031488, 15272809, -31950268, 4197464}}, + {{5662611, 23128849, 38051423, -5439130, 36415774, 10980264, 8310415, -4728883, -47302572, 4451244}, {-55519269, 49313, 9999529, 10432862, 28963156, 12843400, 30216795, 18336573, -13517506, 27214170}, {-32914120, -11072305, -21846804, -10912675, -15300186, 3464788, 3448882, 4096485, 26830356, 10804921}}, + {{-228397, 18677807, 3996163, -5765357, -17982455, -8134509, -18461152, -3870005, -16042828, -1504049}, {-41679557, 5439403, 37914863, 25724453, -44473333, -15960701, 33616338, 23930503, -42049746, 14909589}, {-16078716, 865701, -1526166, -3350480, -27398086, -2860566, 9605139, -7499346, 367350, 5030116}}, + {{22675004, 1517635, 23537301, -28309720, -10539962, -17732259, 54022275, 1380666, -265430, 15507642}, {35604954, -13504165, -26826687, 4591566, -35333806, 1977687, 781185, 15763796, 25388976, 13991338}, {15460778, 16733299, 19344988, 14048475, 30225606, 8919546, -3966554, 10157665, -22964020, 2411969}}, + {{-16245774, 27498100, 12684623, 7625322, -42605118, 3193624, 37310834, 10322027, 30809245, 6704937}, {-28272380, 3735790, -12023325, 14649270, -6525718, -5995068, 12663382, -13284889, 9026309, 17946619}, {-23177053, 12058737, 27221295, -2377426, -18376458, 9422949, 24453601, 12458087, -27966925, 8914550}}, + {{-11908904, 877246, 5148687, 712427, -37230060, 18249745, 20813181, -13585843, 15887850, -1716780}, {-11069340, 4018956, -19254115, -7652235, 1185650, -10458653, 40775407, 10258635, 31033662, 4391874}, {-8268906, -3654045, -28095940, 6636281, 16194123, 7657250, -29860191, 15870904, 1972975, 1735469}}, + {{13273532, 10829905, 29379327, 9334401, 25713862, -10758552, 29273542, -2552977, -33752072, -256896}, {-47219880, -12738379, 18657909, 21589833, -988160, 144006, 14595866, -29760307, 12617774, 27841618}, {21876908, -13242878, 17288627, 4977951, 3533917, 6527972, -18397968, -2983052, 17126580, -7992068}}, + {{-22738888, -1506617, 13748129, 5285807, 40232065, -16963695, -1010856, -7160209, 5275429, -3360475}, {-23283294, 5480091, 47642641, -11895325, -19152455, -13686675, 25639596, -21424409, -55672117, -17385167}, {-19757089, -8408606, -14911817, 13535907, 32141588, 10641593, -22660401, 15848366, -3871962, -16717742}} + }, + { + {{32299526, 14010149, -17432650, 11192953, 15013299, -27188126, 5462092, 6624559, -31322253, 5319111}, {13542630, -6438957, -13530398, -1527729, -14524931, 5357968, -7648166, -3503027, 23511577, -12430839}, {20879803, -4712607, 14870949, 11273192, 25222438, -13559273, -3095352, 15381835, 8038196, -4967077}}, + {{57875636, 7026832, -5385325, -408641, 12233482, -11407251, 16097979, -28434484, 52893470, 4897165}, {5891070, 2492936, 37563627, -27745775, -21811416, -8708341, -39292411, 2632112, -5621344, 25833365}, {20666607, -3144579, 8036694, -6144155, -15823358, 13028530, 31388536, 8498975, -30673072, -13005232}}, + {{-32299419, -10517716, -49443845, 10885897, -60563720, -4503825, 28681110, -1287509, 4402368, 1347495}, {-2265851, 16901066, -17583997, 1273955, 4021950, -11807027, -18043134, -14360713, 51248848, 32163777}, {-23736727, -12930783, 3702641, -4265401, 9417206, -9972194, 7692344, -16235623, 31067762, 161254}}, + {{-10206081, -11559961, 793952, -4142645, -19651913, 6312231, -52760030, 25947542, 1025162, 4279591}, {16516157, 20806323, 60845594, 17589785, 33156225, -25053763, -7706302, -3152586, -33274614, -17612693}, {33494023, 7410590, -18701402, 6156442, 29227126, -11066669, -5746013, -4772912, 23521452, 5865860}}, + {{-6373298, -2417154, 10022351, -3426242, 15113772, -25001335, 38113349, -16915972, -12213262, -8974306}, {-54587852, 2532534, -26557371, 27694748, -15541534, 851563, 27927061, 2058506, -13496946, -21242092}, {-15691788, -2807083, 22073819, 15886978, 26165883, -16600654, 18375257, -14137950, 22379487, 618932}}, + {{-38532955, -975675, -38996694, 7824194, -31093477, -4019014, -22236522, 4774558, 54687979, 24033175}, {-248783, -5373335, 11054690, -20676618, 3856353, 26198340, -16948412, 26655852, -3924657, 7401867}, {8122203, 8304380, -7766078, 6670570, 1288859, 5431766, 25898492, 1928592, -27685506, 12421188}}, + {{13447626, -19058772, 11292036, -7681052, 28894196, 1453354, -23547996, -7697542, -24272981, 166285}, {-35806612, -12174128, 37881920, 20096248, -28320612, 24786884, -11801752, -24769450, 41109149, -11890645}, {-6174077, -7707778, -3861523, 14160188, 19056730, 6931147, -31011646, 3419044, 29894448, -9406799}}, + {{29777954, 25592649, -19209298, -15308765, -29195760, -13060489, -11993888, -1050799, -24769719, -11422860}, {-18699344, 7201511, -22867982, -9857825, 37612322, -4114883, 420142, 25709239, -42307665, 17970078}, {33313729, 15801707, -30212345, -9693203, 3419268, -1522298, -33446197, 14905997, 25587876, 14546747}} + }, + { + {{2798209, 15162277, -15684307, -4848309, 51519813, 12550851, 3378246, -14208963, 6379504, -19126213}, {48045213, 7344295, -45496227, 19454081, -6532983, -7006177, -9684552, 16904569, 40189328, 2692675}, {-24290205, -13822302, -16731339, -9196708, -10231625, -12475402, -3927078, -16145637, -26340719, -4923758}}, + {{-13039496, -10977593, 25286947, 11491589, 8276800, -28332148, 3261445, 20136297, -2721162, -6207702}, {-41819530, 12972479, -28605725, -2226919, 34883486, 3609596, -62887815, 13102923, -30434074, -14511876}, {-12017955, -6504858, -20792181, -13657198, 16210598, 13575295, -11699255, -3920091, -23451271, 11663395}}, + {{2448139, 8499647, 29232582, -4968985, -26238588, 1234082, -15273636, 6493604, 15215528, 34243}, {34654291, -6232523, -12466028, -13749033, -18095494, -4850258, 17014508, -862816, 5795906, 1346193}, {-2593676, -14695430, -17573850, -9364354, 12972475, 2750912, 20876789, -14491819, -11179005, 16692910}}, + {{-58215422, -10434322, -35418615, -23019613, 34157818, -4032813, 46756009, -14667443, 10820011, -25962072}, {911212, 15615834, -27683427, -1291661, 20149292, -3964483, 18302855, -9077593, 41450369, 1345878}, {-11506608, -920266, 19069735, 4877100, -14879476, -8212985, -20750288, 2110258, 25194250, -4793958}}, + {{30982165, 13182276, 1804145, 19165108, 3557553, -16004629, 25397760, 1860407, -11333198, 10921092}, {5027671, 2444414, -47256149, -4582924, 36860387, -10913313, 21051062, 474703, -47565962, -2916184}, {-28264421, 590343, 26675165, -4492599, 29616661, 2699360, 11900358, -6732605, 30546923, -4563008}}, + {{12936229, -1552598, -17694160, 22984065, -13555215, 6642616, -16856542, -8340473, 3038360, -15138845}, {-7372957, -28977422, 7334578, -2604645, -24938121, 9431038, -13358950, 17719871, -55448604, -13172419}, {28780855, -2011440, 10075099, -11361048, 2794942, -2710954, 8534199, 4760106, -27712482, 6458713}}, + {{-21083355, 3030110, 63096983, -4386925, -14310636, 6719788, -4636422, -21743059, 6194601, -1795854}, {-10819193, 9973112, 1884851, 262107, 19590488, 21248586, -45883418, -10873873, 288313, -23063750}, {-103962, 12079084, 12597255, 6824992, 15885472, -13668986, -2535647, 1226717, 7344363, -13634998}}, + {{4176437, 22729955, 17496502, -6849030, -34221611, -27806794, -14046608, -5108398, -20401601, 17504009}, {6244243, 6704419, -27025810, 11039886, -26009693, -2450896, 30647416, 13665916, -34776579, 6877025}, {-16064951, 1034624, -23160982, -15440085, -21717774, 1315083, 557758, 1360821, 2657758, -346509}} + }, + { + {{13575072, -19789355, -15499669, -27774828, -1573937, 19608228, 38837589, 7466530, 43596560, 17244295}, {41466462, -9380539, 13479671, -1611996, -39688031, -10402250, -11933573, -18192774, 3331120, -6785231}, {-685245, -13527226, 595337, -6824797, 13606588, -5948857, 21008141, -14434553, -11578884, -3503288}}, + {{-3792452, -4510799, 31359450, -2520482, 56370085, 2060123, -44350761, -5942082, 44210401, 11548167}, {33875256, -6837799, -34036404, 9731002, -10116281, 28503947, 3018095, 15729244, 16667291, 740075}, {-17064493, -956828, -28220343, -16697818, -3731639, -6827899, 30938545, 14039606, 32576944, -10347818}}, + {{10757077, 14795809, -3407355, -780345, 16283675, -5176350, -40163988, -28650767, -5493307, 2075772}, {-32342609, 4029633, -32995121, 16421377, -24072275, 17951028, -23139410, 4034865, 53224171, -17508228}, {-6732679, -15214583, -27085518, -8968614, 11755012, -1499677, 6585597, -6797409, 14527081, 315054}}, + {{27307543, -527023, -58871446, -10931824, 32029460, -20768624, 42545415, 22418653, -51258657, -6176237}, {-9637979, 25428695, -7638516, -3621772, -32093254, 10596574, 18521249, -1129577, -7781761, -6925725}, {-17340695, -14918561, -17238962, -3358619, -9271226, -2732075, 30094692, 206540, 8047861, -5583327}}, + {{-23296813, 5372514, -55447356, -25438752, -394468, -1422767, 12271280, -12717025, 43935041, 3178842}, {30686435, 12736214, -10409960, 2397260, 26737592, 1240199, 7221192, -15254327, -22198131, 12243948}, {32396051, 10530849, 8542907, -6234439, -33143475, 5195376, -24616744, 13069327, 19123269, 15103570}}, + {{-61599163, 10407914, 15146127, -9577140, 2850555, -11434349, -10341117, 11688165, 57222980, 7443309}, {-1959157, 4123922, 46859779, 8039580, -21208177, -18798009, -24182107, -2946369, 1732410, 25984845}, {25946003, -12168188, 2048333, -13538555, -17578310, 13342801, -20932457, 2885364, 29616721, 11594640}}, + {{-40904044, 2945685, 11087344, -6564107, -57015017, -7934886, -42681448, 6648344, -31265094, 21506383}, {-21986860, -20326005, -3353394, 15341865, -6188985, 24351388, -656416, -494508, -26351318, -2036887}, {18250574, -15295358, -11832137, -5452519, 27980331, 16723298, 1292225, -4636338, -13285349, -14831043}}, + {{-15822181, -8220514, 44676240, 4837785, -10965147, 20758580, -6087251, -4268667, 15695528, -33273123}, {27699263, -11559548, -1680314, 17010295, -19865797, 7432280, 1175039, -7527665, 2498720, 132583}, {-20662680, 3812012, 28215072, 9683375, -32934656, 5848009, -28282421, -6651754, 1742396, 10862429}} + }, + { + {{-22733894, 22365918, 34991744, 22930598, -19496866, -8163136, 30107089, 7907709, -14553008, -11632657}, {-37296292, -2003218, 24591582, 9095488, -47173448, 14774464, 3246025, -10677419, 2569096, 445185}, {-13942373, -3559994, -9371297, 1580480, -20158109, 8513092, 11163834, -9623612, 28591763, -13690156}}, + {{11703909, -2375544, -12981611, 28562070, 12367055, 6822582, 32478995, -28584327, 21619877, -9192478}, {-37995101, -3593230, 41950501, -1831386, -24598319, -9607356, -14181623, 3703567, 42309421, -7195304}, {23029114, 10927269, -16101987, -10277174, 15635784, 14878063, -23215498, -1109595, 2198987, 5853567}}, + {{-37129983, -6412591, -37361902, 1346509, 7007490, -9977950, -25107526, -27806347, -14051851, 14030690}, {-20788269, -19804041, 7748724, 9563555, -56756344, -6202546, -1035170, -3893167, -17621495, -2261696}, {-28906373, 204764, -21936639, -13331811, 3966595, -8657893, 18798011, 15222066, -3951168, 16033081}}, + {{-23835089, 14694641, -61354419, 5610348, -10283594, 10840185, 6713333, -4080751, -10670280, 2370248}, {21454405, 5960615, 2048703, 1217562, 24554212, 13565407, -47321821, 28902575, -13897714, 27306186}, {-6032661, -10676923, 27946394, 2598890, -22637840, 6652672, -29695474, 6675520, 16441846, 4656403}}, + {{-13451707, 4507055, 62188672, -7988103, -19447422, 720632, 19254914, 12569311, 6252001, 16384964}, {14786925, -14783207, 3749232, 9850861, -44938020, -5908734, 9804106, -639181, -20593585, -15057988}, {-7443582, -11232846, 4954094, -5823514, 16748077, 9380015, 5897105, -8290425, 5871898, 9086861}}, + {{-34382229, -5828752, 15152997, -11124460, -8252533, 4873628, -19056104, 10644378, -24535978, -12602029}, {-17990235, -16524194, -26248761, 8719524, -30352475, -2606228, 24376282, -12539724, 532544, -9905963}, {-26261900, 1594704, -30851260, -15733673, -16245265, -724673, -25937603, -3280158, 31051504, 13183415}}, + {{-4433901, 22898181, 4408403, 4089599, 7026019, 725982, -35998453, -16160374, -49882415, 21440714}, {-34658715, -5989601, -2370793, 12922491, -315799, 21918616, -25558631, -1306328, 1786989, -4463662}, {24299172, 6407606, 30243748, -12413076, 19777849, 4778790, 20007455, 11060481, 92567, 14380440}}, + {{-62546359, -1117901, -952074, 7995591, 27044812, 13813422, -518271, 14514359, -7559876, 20776990}, {4194309, -29001351, 29866184, -24269021, -15696020, 14141518, -62562609, -8282275, -2484076, 7273808}, {-17821991, 6257652, 29709259, -9550721, -16005147, -5755011, 16908019, -9094499, -5282110, -8106630}} + }, + { + {{28685451, -6107266, 30239148, 6290924, 30696512, -8147733, 2960158, -14334512, -38921075, 4626660}, {1583703, -12161614, 22432712, -21621714, 24630924, 6162155, 59141724, 5599546, -17405309, 22280348}, {-29844040, -471409, -10622236, 12210452, -8239642, -11983887, -15183804, 16381174, 17319255, -2956271}}, + {{-2403083, 12925626, -13099156, 28363373, -7421956, 16456989, 26157882, 7667907, -27281693, -9167492}, {-45717659, -15626026, 50173092, -3406701, -54970694, 7385663, 24757090, -18564339, -4645939, 21629820}, {-32751670, 10248246, -21066690, -3059537, 26806646, -2312121, -17653642, 1520921, -27460759, -12323097}}, + {{13248067, 6436040, 8030453, -25818031, 30780082, -1430948, 18201771, 8897427, 19847298, -2659562}, {50680655, 13582932, -17146553, 4912299, -2595212, -17399816, -10502859, -12069603, 9084258, -14719238}, {31515119, 2251073, 4922241, 2492364, 20234810, -2120720, -26567634, 1872447, -26158151, -3820091}}, + {{3059908, 10356510, 3160147, -5814463, 6619250, 6005354, -18146875, 28990675, 6485346, -3393885}, {-18912530, 22467822, -60653559, 1552123, 17365776, -24805772, -44753569, -2181397, 847216, 17829951}, {-24027306, 1499890, 29296657, -4767293, -11192239, -15482208, -30071603, -13224053, -21934731, 337399}}, + {{1216703, -5387360, 14421225, -353640, 13814558, 27034582, 38058105, -9449465, 11449174, -22314414}, {-24922703, -15978446, -42236369, -3997012, -34641380, -5774914, -20346071, 20193613, -40743840, 9848360}, {12833052, 5696999, -22504492, -7743199, -29120426, -2764382, 26734085, 12053780, 8854624, -14858885}}, + {{35510797, -981503, 14318929, -3469597, 10336566, 21370992, -973336, 1867849, -28297193, 7062219}, {16394267, 12877663, 26342859, 13428701, 10841234, 10087180, -2265170, 5788091, -35468571, 24964845}, {14425123, 3556895, -28505669, -11596774, -32205271, 14061926, 33096714, -9460010, -25504553, 1459596}}, + {{24576115, 22264595, -39113376, 12822398, -48871562, 7948464, 63116078, 7228755, -27405020, -53976}, {8086679, 8186447, 19157134, -8249296, 4699914, 14764776, -2002260, -11057409, 27716466, -16081150}, {-27050118, -3528220, -1516699, -2231374, -12636934, 9995609, 25685841, -4140179, -3409048, -15464812}}, + {{-7531403, 4325881, 7535396, 7859314, -22699673, 7976792, 2479226, -6835756, -32588365, -392602}, {-46120529, 9916327, 38374782, 21688084, -19401825, -12255854, -31333428, 18558666, -21135491, -6668554}, {13991326, 12860930, -4422015, 10881593, 32950975, -283682, -28450269, -16032545, 9672918, -11362754}} + }, + { + {{609922, -16247499, 14961059, -1570609, -28091802, 14169626, -41783295, -13089622, 4930102, -3436202}, {9329866, -657063, -44356797, -15301661, -29486294, -17703348, 8805283, -14270540, -20958948, -26960484}, {23477300, -12109362, 25444691, -7136047, 9244360, 3145110, 19327657, 9308319, 28572142, 1225335}}, + {{8267621, -4527619, -27664281, -19631026, 7103467, 8015983, 19980277, -20523192, -33106752, -9640324}, {-49140895, -14621999, 9804745, 11746362, 1328203, -7481863, -9767851, 340196, -4927892, -2341788}, {-30353118, 622051, 10357298, -11276182, 23732131, -4604752, 29769254, 15682613, 14502745, 1692468}}, + {{1260912, -5294878, -53574238, 1785181, -6140895, 7516954, 13950460, -12831935, -44549610, -21761599}, {-31177968, 8480756, -13273798, -10571863, 47258623, 20807548, -24434810, 16780381, 14669642, 8224809}, {28182450, -9865310, -18750048, 14220580, -31294501, -12254360, -24830749, 3333773, 16756756, 3674180}}, + {{-6402360, -6335805, -33097256, -9850907, -4824695, -21057881, -15064635, 4889122, -22240663, -13412349}, {-44163136, 17929609, -31558170, -18775313, 16737199, 11833309, 47647709, 17892042, 27454173, -11748923}, {7733705, 3101270, -7805155, -5082179, 27897611, -11801644, 12061037, 7405405, -16546491, 15403389}}, + {{-4492968, 343804, 38266516, 32477765, -25777001, 13550643, 46526645, 17121454, -14426206, 18420417}, {-46530416, 1424718, 24723148, -680817, -40884673, 8897391, -13370151, -15981258, 36955976, 8156639}, {-24543854, -15223067, -2543355, 16106116, -14644361, -11276692, -25446112, -3383546, 1372079, 9830245}}, + {{-45249865, 5860643, -511570, 1494755, -24871604, 13184267, -25232936, -3704812, 41046541, 15652109}, {-20701335, 2062533, 4978884, 611175, -30157770, -15586203, -7510502, -19563320, -13272327, 5150375}, {10708302, -3863498, -22395389, 16573914, -5145231, -4552434, -4603892, -8967772, -1517224, 10636936}}, + {{22812080, -18752417, 9910097, 1108862, -16257891, 1138559, 2414519, -13730584, -10249269, 2676014}, {-20435954, 11175275, 45231099, 6155242, -48353071, 24683369, -59216429, 17111970, -22023587, -19928584}, {25874111, 6383009, 13602754, -6088836, -20233593, -3580839, 27183994, -11837778, -29518672, -2860903}}, + {{-1681560, -11679105, 400217, -6168948, -46402196, 1534799, -6234380, -45604, -2757186, 31803865}, {-15876686, 10637109, 30465123, -25542824, 18668596, -820323, -39800218, -21603264, 54303356, -1363285}, {-17522273, -15566672, -29122873, 7399164, 33527165, 12928839, 5585868, -15504027, 31653797, 10489380}} + }, + { + {{-8372444, 7555339, 32540989, -19186451, -11202553, -27432492, -45917828, -10768103, 20962520, -11534894}, {19695734, 12580309, -11811267, 10021575, 46310557, -411332, 2870540, -525511, 22740298, 9835954}, {27255654, 7099090, 12404130, 13814764, -7475522, -13667972, -21749346, 14576154, 7990399, -12406876}}, + {{11527801, 11839779, 17463740, -12828497, -30323835, -533377, -18537666, -2971505, 33445637, 1378899}, {-5182347, 2305541, -43036482, -12755443, -19326901, -25584801, -46604822, 108557, -32639917, 21539705}, {9401944, 7738115, 3634928, -5218468, 1792182, 11012020, -10935528, 9848524, -8395638, 1752383}}, + {{20087513, -291352, 34200431, -9266428, 62742024, -11465814, 25160028, -23260583, 20949348, 4741970}, {-34742547, 4824060, -24760277, 15520282, -3746158, 9908304, -15131750, 615003, 23774668, -4622502}, {30152793, 14686972, 18175085, 7025501, -16572275, -10778346, -3777754, 1265518, 4148852, -13707789}}, + {{-38414435, -12792916, -2239329, -3207407, -20902781, -7236076, 20364640, 14570920, -21750082, -1957286}, {-26406891, 588662, 42602249, 18949875, 40283141, 8327480, 44288302, 11085620, -42944036, -24193688}, {24058929, -11521453, -8974101, 8545768, 7842586, 5283701, -5952655, -16759937, -28459199, 2855313}}, + {{-22950445, 2636586, 16485375, 23498857, -50586070, 8299269, 44530771, -1084345, -12093804, -12285062}, {26623543, -10037872, 25079369, 6181813, -10081082, 7047923, -8641075, -26766059, 52958854, 1962838}, {-14692059, 3189504, -1141773, -6869718, 16477874, -16186435, 10319878, -12263639, 27007849, -11168270}}, + {{1395398, -2560759, 19469476, 28776421, -10401013, 1426902, 43387733, -15775984, -2907552, -3878368}, {44130694, -18470819, -42832262, -1157721, -19297931, 27290380, 9680329, -14007508, -19301064, -25801940}, {-9077853, 12479035, 32279877, 309923, 32237763, 11557611, -14314225, -6638385, 21114797, -12559936}}, + {{-1074752, -12711000, 11779129, -6005334, 18492568, 813113, -23399152, -17827765, -27283475, 897128}, {-5877536, -19332004, -32558825, 21223296, 14993686, -13962833, -42176122, -1104083, 14232253, -15133784}, {-19690492, 6937960, 25377806, 9508659, -510153, -14981949, -9629935, -4642867, 28215996, 61378}}, + {{-2424643, -23482508, 17854580, -12384463, -6175769, -7029740, 2895954, 7260602, 4923635, -9163617}, {-22476207, 4360038, -10341294, -17982317, -3199499, 18985914, 1781084, -13251932, -19610353, -13719439}, {30725364, -2670803, 30379991, 6502287, -6324103, -13835465, -30857651, 11056502, -11206851, -11544011}} + }, + { + {{25613616, -3102602, 40789082, 15098034, -27085595, -28107115, -24729657, 9846294, 64147258, 8535304}, {5544284, -29420706, -847298, -12517760, 16311373, -2661037, -26206351, -19068264, 2059874, 8195880}, {6669623, 1911069, -1424926, -11047889, -1797036, 5077921, -10177871, 4954835, -17974230, -12151160}}, + {{53838367, 18498333, 29327101, -18307717, -27697332, -6262662, 18729755, 10337992, -6784427, -12669848}, {-219965, 10998769, -13624131, 12996865, -22399952, 23493860, 13600601, -18769408, 20883561, 20137308}, {21917704, 666621, 29983376, -12912559, 33297656, 14065983, -14663339, -13679339, 12578619, -16118527}}, + {{560628, 14919700, 1508980, -11236102, 48897615, 20442779, 3014560, -26431507, 44332294, 1132925}, {13641098, 7148772, 63423392, 2454340, 266701, -10477331, 53865232, 5770029, 14388618, -12499003}, {23680383, -9234375, 13985236, -6697353, 2164536, 4153861, 13315193, 15804309, 22736038, -14401730}}, + {{-28797906, 19629356, 1528610, -16221572, -40039242, -218904, 4026062, 24818856, -5842348, 2442806}, {-22117432, 4453156, -20160710, 6594242, -4416272, 32605326, -46568762, -4076794, 42785798, 27679198}, {17658618, -10828002, 21213762, 1082858, 5596600, 7970557, 10413717, 15361795, 30096544, -14984181}}, + {{-34398711, 13610827, -7533094, 18637497, 13228901, -15549551, 34454960, -931237, 37709517, -5866337}, {-10580883, 5781373, -16402464, -9730763, 52388739, 4648305, 16976166, -17304963, 13365317, 24556797}, {-23208171, -4866820, 9566555, -2385155, 32031436, -1912329, -26656342, -13720432, 29996919, -16622340}}, + {{-14044704, 20590387, -19224032, -15661458, -30514062, 19176348, 18002615, -9139157, -54872916, 4783343}, {8745298, 6103435, 16808486, -15382452, 6883638, 13991438, -710423, -22054081, 9614176, 10941823}, {-20054347, -1473522, -13963513, -12909374, 32183518, -9397961, -30746382, -12228468, 31752780, -11444156}}, + {{53597225, 11311815, 51366539, 4168341, 38588940, -9441254, 34224936, -4331012, -5898761, -15177316}, {11566971, -14572795, 864689, 11811969, -10947644, 22048946, -7055954, 17376260, -5170355, 3726178}, {18017909, 5290946, 4193366, -7542284, 23281477, -12847996, -27373724, 4478364, -27664855, -1638231}}, + {{6492510, -10992036, -17181759, 26181968, -13816983, -3239659, 5097351, 918347, -10497797, -18113476}, {-35106388, 398620, 34036107, 931208, -33293947, -8334349, -18454969, -26315265, 5152047, -8450474}, {-6825120, -5661866, 3152790, -334544, 30064065, -14377643, -32647844, 7261409, 21680638, -11642126}} + }, + { + {{-26325513, -8248593, -3247140, 1740121, -34992129, -18480334, -19932573, 27682074, -46819460, -12935819}, {4372323, -20195835, 48957234, 22171431, 21759893, 15021816, 20161859, -5774394, -6423072, 14280917}, {-2345355, 14800842, -33176513, -14576316, -6275749, -7130565, -22666781, -11553044, 20757373, 7638412}}, + {{18554129, 1883773, 33190000, -137057, -38265135, -2458605, 12151744, -3941042, -24904603, 5182536}, {-45627519, 18696043, 6833972, -16969839, -23385441, -10799057, 29598860, 16700748, 41400259, -22784054}, {-9975310, 9942494, 32932345, 9470829, -19659249, 8806378, -24570784, 14852161, 19807157, -9112620}}, + {{20728432, -2965451, -16983203, -8355403, 13568410, -19649207, -33100963, -9061445, 39853397, -17601764}, {33435384, 15050151, -2695531, -6769507, 34423744, -9209925, -23362771, 10679619, -10219535, 3020820}, {-24169278, 12088578, 30194499, -14423347, 4621968, -11420678, -12857712, 1445253, 2454940, -5098990}}, + {{-50090410, -11937497, 20023918, -28422725, -25901937, -4562103, 2957441, 9350542, 27011030, 22919199}, {-16855872, -14285699, 41271594, -4437213, 23047931, 24003335, -21274185, -3716982, -10501104, 1224083}, {31381937, -15006606, 22569079, 849892, 25067525, -12846614, 18279065, -2688830, 4086724, -11375950}}, + {{-25807098, 664214, -20940416, 16721299, -13781153, -9825407, -11144281, 7087253, 39991176, -4321267}, {35916106, -16130278, -45522856, 4299345, 49211559, -1431649, 19013381, -1997569, 7898424, 13808859}, {-21081302, 7761271, 14799146, 10140929, -25916611, 4883839, -30034870, -5553186, -14047385, 15516431}}, + {{27336411, 3025295, 4763606, -18353613, -22285434, -2393666, -10650120, -14195341, 1208838, 5305816}, {33041431, -3031923, -48542168, -8010493, 16840522, -17236746, -35808808, -9896367, 15521690, 5581358}, {12964476, 9619386, 7525095, -1197026, 6449927, -10883525, 30807774, 2498372, -21141039, -3450882}}, + {{-36131818, -1284028, 21128192, -906526, -25769228, 1583451, -4294356, -11463455, 7181513, 18882049}, {27034390, 23461406, 12012698, 30665976, -17137104, -28414025, -16095762, -16380803, -7340749, -8589025}, {-15942564, -583248, 4994353, 477050, -25858706, -323177, 22093563, 766157, -12827507, -6319082}}, + {{22634837, 17227779, 2060432, -16826865, -20349374, 5789274, -20032198, -5620537, -40330372, 9990778}, {31284447, -1278585, -40294954, -1499651, -43891760, 6715506, -19491732, 2135147, 22416580, 7682118}, {-2901436, -8239520, 27494476, 13096587, 23762647, -1548528, -30477045, 3457949, 10095228, -7581833}} + }, + { + {{2114197, 17030051, -13659256, 9852839, -7653641, -17120494, 26934226, -16806072, -36500363, -23965140}, {-60558843, 13901365, -20685490, -3222777, 57453737, 7790306, 3132824, -11661968, 7015193, -1481912}, {2606844, -15219131, -23863412, 5506284, -28216375, -11753603, 28396964, -2821608, -8177325, -5229292}}, + {{2117620, 5071400, -51371060, 8659595, -1555064, -9254065, -16793387, 867368, -30116922, -11099567}, {-3074486, 6051358, -4580212, 17909015, 62691798, 5707253, 39685481, -1564528, -8106780, -10769123}, {26393433, 477586, 21455749, -3024754, -23080611, -4445543, -22936291, -11700610, -13410903, 15714181}}, + {{-31064456, -423253, 17927519, -15078939, -3651989, -4604710, -55755692, -6380619, 23667075, 2254886}, {-8866532, 26907601, -38178645, 12541627, -41761655, 15894554, 6139818, -9980589, -32669393, -31037282}, {8331842, 12088797, 8743449, 5199715, 7827646, 14995800, 32818339, -15785319, 26039508, 8660820}}, + {{29608880, -25012307, -3741475, 2263012, 17390139, 14671399, -46672426, -2644670, 31072720, -16370835}, {31432406, -7112671, 11848109, 25118790, -13938283, 11538983, 4069966, -18394394, -5824836, -1329775}, {-14433949, 4946823, -7500924, 12196981, 13338029, -15298747, -7069294, 16291914, -14596651, -764794}}, + {{-47671656, 5321445, 25113508, 25839794, 11138831, 11243554, -7992278, -492744, 3259159, 21502307}, {7246326, 1660785, -3260474, 6454628, 32064949, 17015606, -18472972, 20915418, -54909651, -3050597}, {15768270, -10694330, -28616776, 8679482, 12703510, 16040531, -32739301, -11567793, 24758624, 9552392}}, + {{57612225, 17986091, 3746391, 10734441, 3986026, -21094603, 16387973, -12469457, 3881315, -9926314}, {-624623, 12461149, -51123123, -22504775, 37750130, -7879511, 11693933, -7847909, 4979163, -14061758}, {-9228097, -16612591, -30048092, 9179101, -1510092, -12371889, -10272294, -7719712, 8198600, 14178374}}, + {{-44524641, 11655384, -3094856, -4653367, 14629907, 28489197, 22967506, 12213495, -2529582, 1078481}, {6176435, -17402926, 3629314, 27064491, 4067273, -3887667, 40995892, 4419129, 20423036, -9367845}, {17891255, 8589105, -24215999, -14819511, 19880982, 780210, -33205145, 11448404, 22097349, -11182687}}, + {{-56614347, -11578188, 35985602, -7657125, -33304359, -28085372, -11902129, -10381139, 4829275, -5224705}, {7662417, 16677484, 3043718, 18325901, 32667751, 2300018, -47786427, 17253601, 24265597, -18169169}, {-18998173, 12084374, 14914736, 184926, 10136115, -7636021, -1182475, 2011448, -3200275, 16596418}} + }, + { + {{20417236, 3754420, -6738616, 8258483, 8799896, 13466324, -23880510, 11012604, 6303439, -3234445}, {-9662424, -26686038, -46906146, -11028221, -22584644, 1743532, 43009814, -13291636, -47986433, -18890135}, {-6481517, 4004191, 4493109, -5202130, -31648275, 11051930, 5985603, -13179900, -26804977, 6841092}}, + {{-33140236, -26703602, -466711, 995232, 13691879, -4875991, -4209980, 2211678, 12277522, 8419710}, {26163546, 5021636, -35722295, -20577268, -44821239, 955253, 8256638, -25191066, -4483980, 22437190}, {-26364811, 3746737, 29973408, -13605927, 15675876, 8003871, 11707655, -16697620, 12112406, 4013808}}, + {{27492119, -14475041, -15050357, 25726237, 20610151, -13989916, 8011822, -1373664, 23660358, -27162084}, {34860435, -14275633, -35512837, 1671599, -8790883, -17961386, -23719502, -10031868, 42881268, -4549920}, {29021594, -3019356, 8587009, 11384121, -25402734, -7392345, 32885066, 14460607, -15018066, -15719330}}, + {{-36428323, 10993200, -17511364, 9372077, 20074151, 9525006, 27348409, 459280, 3871179, -8165676}, {15159929, -14398564, -38057784, -17699073, -15046129, 20874698, -8384091, 21642740, 15388743, -6182942}, {6938581, 8822343, 8620932, -8578754, -4104627, -5936118, -26735367, 12738036, 13629323, 11082567}}, + {{-10094361, -334652, 38476983, 2790439, 27359870, 9552721, 32053453, -6969029, 10042131, 1926471}, {30282419, -2678756, -19246779, 1725181, 37410474, 20135333, 12145193, -21815855, 19828393, 20800757}, {26753059, -13933234, 27619188, -7497265, 16033163, 16756554, -22110989, 6046760, 4021520, -12705457}}, + {{-17531609, 15683192, -60939575, -3448475, 715976, 10128494, 2939400, 25784735, 58743432, -16073813}, {-20867029, 11543468, -2401509, -10757695, 63356468, -1332856, -35145770, -7583819, 2140192, 14736421}, {20912186, -9499909, 17368552, -5248439, 383852, 3792929, -15675370, -7000153, 25685400, -13601909}}, + {{1414967, 26315702, -47285501, -12511107, -26584273, -8841287, -11498324, 10640443, -24532611, -6408984}, {18127227, 864012, -9629079, 11593257, 1974271, -5312585, 39105750, 7314787, 42290595, -388650}, {24881185, 14073561, 4685989, 1030574, 5144912, -2519431, -20326615, 15917167, -4984945, -3376538}}, + {{-62565663, 4920478, -55376449, -476735, -43677535, 17959977, 38328264, -10344668, 505340, -28100303}, {3438657, -93716, 8832861, 1390381, 2767865, 13100345, -3166778, 17063164, 40430482, 3196597}, {-30623883, 6302481, -22871030, -1596089, -27318556, -1845828, -30934853, -11670445, -24178997, 2237082}} + }, + { + {{-42013187, -21787042, -1974859, 641794, -29012986, 27248518, -11318182, 5528619, 47218899, -27053971}, {21399495, -6961006, -60149823, -27990936, 32659538, 402218, -17546244, -17599875, 3654601, 2799325}, {25901287, -9761761, -3723331, -8371812, 25859324, 13536452, -18715963, -16042698, 17594096, 11317273}}, + {{-42888393, 19107059, -13724666, 2457030, 35585086, 15454849, 56449705, 6596061, -27137418, -10313846}, {-18245557, -12694977, 52885490, 17475442, -9942024, -4476971, -3203117, -553835, -15881918, -13413996}, {12202693, -12337785, -30153666, -4395318, 14717208, -4425600, -22858811, -13185192, -17959265, 2144141}}, + {{51166048, -26529493, 998246, -19904447, 21680565, 70271, 58588815, 11104313, -29340186, -15589375}, {10396306, 556339, -20794266, -10222229, 43439911, -19881575, -8125073, 409357, -29955322, -5006503}, {33021662, -1104036, -31710826, 8226104, -20213488, -1213314, 29757292, 12547987, -7586901, 2216753}}, + {{-35407447, 18766745, -29406085, 4524650, -19274474, -20474329, -29645035, 4173870, -18612774, -28994444}, {4417599, -13567597, -27595143, 24830672, 23713420, 11302197, -24087205, 21047428, 43127268, 2647518}, {-10840209, -4031615, 3434966, -2883654, -33078119, 11883954, -4958608, -3035636, 23436012, -4139629}}, + {{55573275, -10384260, 48760956, -8245044, 5563808, -3927548, -12376512, 10483595, 24339695, 24222716}, {3381031, -772374, -11089900, -13843410, -32834346, -23935396, 29059114, 5645517, -10519961, 3236912}, {23037092, -1287504, 7295737, -961721, -11545579, -14357320, -5928040, 12927381, 33019745, 7517994}}, + {{-10919893, 10029121, -1170858, 5096908, 22114728, 8472664, 15995883, -2832011, -13953384, -23651018}, {34866095, -1771857, 36174248, 2540622, -32624908, -6779600, -33549631, 3465737, -24182162, 4056752}, {12704410, 7507131, -7289543, 10523503, -22979044, 3716496, -608065, 11785705, 4833052, -12397016}}, + {{-20098856, -8357022, -13509875, -4260610, -1155839, -2460344, -11909914, 14519853, -11674164, -4932027}, {-20235794, 5667344, -34325855, -27044324, 34168809, 19411772, -31226346, -5984537, 11679534, -812723}, {-10928038, 3725640, 15839793, 2209351, 18379523, 16032103, 1913182, -15696614, -27517459, -8157489}}, + {{-18782125, -24814076, -3958506, 26630408, 60814430, 4813699, 33756661, 5374436, 27014220, -12974732}, {17864349, -8685810, -40310934, 2052652, 1728180, -23835879, 703879, 15354684, 29682008, 16487546}, {17771672, -11482859, -7287302, -11938074, -12767482, -8666772, -19744227, -7739340, 20155770, -3540752}} + }, + { + {{-20537140, -2325676, -18195382, 24196641, -15647052, 20118839, -12925105, 17045916, 34499709, -17229790}, {35193252, 8694668, 35544716, -7655657, 27470362, -3594335, -46317185, 10996548, 9029315, -12706320}, {13627845, -14179605, 27664073, -4176906, 30076695, -5368248, -28022384, 10437867, 31092096, -10165457}}, + {{26082898, 1481922, 42354473, 22859843, -47160656, -31990941, 22146898, -14550325, 13976901, 14484952}, {32189144, -8924380, -9072391, 4619295, 8692690, 1181533, -13742008, 8049019, 38048563, -13701850}, {-6553634, -7387076, 2142769, -1783714, -12658909, 4088377, -14531792, 15589041, 9532256, -5214258}}, + {{21903333, 835551, 25948411, 8087994, 10579336, -19159877, 10063391, 6406466, 26035008, 24825436}, {-7991019, 23450851, 28067991, 10971202, -44508446, -2071805, -26934681, -5349122, -31058556, 6922554}, {-23535575, 14721737, 19897836, 7195206, 18514260, 10267975, 32597365, 7146760, -26220125, -4181103}}, + {{-8377112, -15053012, 19701631, -1143892, 29173097, -7711884, 7533159, -11284451, 22602583, -202085}, {-12081374, 12320872, -18577273, -25481020, 6063795, -457184, 11528113, 6761257, 15950727, 2016225}, {-3488474, -1252458, 27598369, -9564249, -13868383, 12663504, 13034117, 10389639, 25008987, 12869544}}, + {{-41287488, 5097899, -8017582, 16515062, 4005319, 2886222, -26248725, 30756415, 37890545, -9382902}, {14169058, 21213397, -5825866, 2602682, 40886443, -27926390, -919315, 1053779, -14443655, -8976564}, {-26523777, 11005501, -13398213, -1504220, 17120379, -11293324, 4627812, -15843648, -13055828, 15956039}}, + {{2548227, -11481600, -17475494, -10395519, 12804828, 2200128, 681831, 22496890, -59662, -13031715}, {-57903567, 8975256, -42926640, 3285287, 32744596, -9503574, 28043407, -527888, -49147912, -10727719}, {9506135, -10079608, -27371911, -3187209, 31426795, -3119051, 12656925, -12472556, -19389021, -12220760}}, + {{25040145, 5375975, -16032779, -16207116, -24837545, 1229911, -18870216, -3502521, -38635521, -24186669}, {4129107, -9049199, -43495961, -4674306, 14771801, 26152529, 1639988, -22909721, -19916249, 5570799}, {7930351, 7168936, -18962536, 4388632, 6861069, 1314713, -11935473, -6148385, 6893105, -2679637}}, + {{14209111, -8618739, 10194979, 2677300, 4013085, 9775729, 19731499, -13248526, -13730102, 15670809}, {1951811, -16648029, 10124883, 23538690, 57732181, -151453, -17384431, 5916614, -42862646, -10821399}, {-12843967, -12783694, -5060981, 13040075, -3965076, -2110951, -32363179, -2348882, 19898655, -3575970}} + }, + { + {{-34792196, 10961077, 12194610, -4593557, -51395077, 10010208, -26461909, -1002357, 261319, -503468}, {-29207090, -6676381, -48195486, -25111299, -1638025, 11265984, -8328237, 211091, 34106289, 26184676}, {30472641, -2165883, 18114708, 3293995, -4965577, 4084296, 31866003, -7230542, -25605491, 8816749}}, + {{5482036, 9596271, -12015879, -12654964, -6454965, 3709767, 11700907, 2388819, -57663235, 3276276}, {-20962264, -9019427, 54613037, 12841154, -14598765, 5875969, -38133515, 22983389, 6067571, -7706478}, {14039908, 9441265, 24349126, -11164888, -25009241, 16168687, -29220409, 3453089, 20283883, -11622176}}, + {{-24958806, 7999411, 26453178, -8644238, 37004539, 9520148, -44953608, -4942104, -49827416, 6739321}, {-15417434, -22489529, 28384358, -8360578, -24069667, 21421860, -17147560, -8528850, 16955778, 1845317}, {18676342, 14475508, -25360785, -8450461, 5095309, 12998774, -8725611, -16378797, 17352997, -7873738}}, + {{6088013, 15443631, 15367919, 6931010, 7383773, -8971235, 3134230, -17993438, 19885092, -15431371}, {-36868691, 1848785, 28117399, -12178392, -32202919, -2935929, -41541808, -13740268, -1903224, 12010861}, {15872540, 8482255, 10321834, -9675351, -11648295, -7642890, 16801676, 10997144, -29109315, 5395913}}, + {{21122930, -14654623, -4691857, -20599888, -3407677, 8298546, 1212356, 20368845, 11864426, 17078944}, {-7942474, -3116257, -18091609, 10415574, 19535041, 18089154, -24275846, 1802933, 29309900, -14749954}, {-33017200, -10927095, -19262732, 8479894, -22891975, -15495620, -24826565, 173807, -28824337, 9766249}}, + {{10187499, -14842972, 1765958, 5454142, -29038474, -11108464, -7325191, -6006206, 3359839, 14414352}, {35404123, -1243790, 36161128, 23385616, -11058392, -1044806, 50151439, 13948196, 26832723, 7453256}, {-13954451, 5021979, 7140615, -11141845, 5062172, 9122582, -27422342, 11371205, -26697878, -7980757}}, + {{-15101525, 19083247, 49815512, 5467110, 55249963, 7815419, -22701226, 9352040, -17207788, -9327396}, {24432659, -3429041, -10078804, -23645764, 3705141, 7636697, -24328046, 3752550, -33924128, -10417608}, {4263947, -14573397, 1561691, -16719679, -15027272, 13811718, 7916120, 15642183, -12100015, -12542066}}, + {{-1246283, -16919000, 20714304, 9342413, 4463122, -3091715, -16615071, 8350186, 28517447, 7256289}, {-60583887, 10129604, 8033426, 12645057, 15784562, -24923815, -40527691, 2345010, -2630711, 5565399}, {24853847, -6571768, -4123529, 12035347, 27742746, 10789343, 21227012, 14204447, 26950712, 15226435}} + }, + { + {{38293607, 9950574, 34571061, 18019104, -4796135, -12903233, -37153980, 11988194, 64667371, -1295399}, {1990479, -3993934, 15302587, -13624854, -50925443, -10162423, 12470946, -12501532, -398257, -4518189}, {-2123361, 15868208, 20504658, -5640753, 12828365, 2917800, -23159772, 9610427, -22229642, 8514192}}, + {{60152501, -7881029, -5735493, 27067102, 15216094, -25578865, 5775396, -18282676, -32004183, 333751}, {-2942997, -19709343, 5657549, 5187848, -41462598, -1889377, 31388930, 12989898, -18862997, 17561703}, {27452835, 11888074, 2130182, -13375267, -27335132, 11090572, 26997919, -14726058, -6038282, 5670406}}, + {{24606109, -3086065, -6334722, -7104165, -17038207, 3899991, 43535930, -27376513, -14631009, -26472435}, {-41220877, 22579683, 1597526, -9250673, -29385377, -9619937, -22573078, 1989229, 44859531, 6507783}, {-15529106, 393113, -931832, -8044029, -4718990, 8311519, -30956863, -13990446, -1115870, -640824}}, + {{-18312096, 7296216, 29905169, 25918428, 1044356, 11106126, -52239421, 15937722, -22413453, 8019028}, {34783270, 17243468, -2583019, -6229442, 22256742, 11066256, 11271803, -12193662, 2341667, -11740674}, {23620188, 5155673, 28287869, -5403815, 27901784, 3248580, -11693777, -6246066, 2690945, -4535794}}, + {{-3476170, 25705465, -35582829, -6211080, 32037996, 19319806, -1946921, 2881239, 4200013, 24664725}, {-24648332, -2355153, -5164445, 1415306, -17921628, 5735806, -11414171, -28844433, -9840029, -1554479}, {29536729, 3727365, 30118034, -16717889, 9563888, -9113834, -19443307, -12170618, -2320751, -14161678}}, + {{-49927995, -23511266, 1925927, -22529664, 28821505, -8939245, -14236007, -8614804, 9368285, -8849337}, {-6508507, 5065926, -62306881, -7969506, 20657007, -9110349, -18390589, -8734012, -52065503, -6397031}, {-4258866, 12403757, 23357823, -5147989, 22816681, 14989671, -18261135, -12259319, -18169940, 15689278}}, + {{-43701663, 7343034, 35625243, 6830390, 38456241, 8090418, -39362684, 14665127, 42418672, -780303}, {-2622183, 20216964, 13038227, 8116138, 21533737, 12653508, -17065706, -15673089, -3998786, -30481879}, {-23923362, 4340854, 590054, -12912692, 8291014, -1995009, 16612887, -14602635, -5134320, -6609129}}, + {{-2605458, -10075893, -18084324, 1785292, -24201087, -7331775, -42147543, -1178129, 14910313, 18415851}, {-3772848, 7289091, 14209634, 26755102, 29108767, 19329837, 17330869, -28922531, -47107019, -797789}, {19507809, -5258985, 19827066, 9929560, -33064263, -11557847, 32396361, 9850512, 23796890, -1444503}} + }, + { + {{-12384446, -13010874, 2487059, 31217155, -13004356, 2408366, -27841844, -20200143, -16196, 8381494}, {-39680994, 4117412, -11547829, -64191, 18815740, 4549986, -1766722, -4552917, -6845154, 9783316}, {-29956699, -4572563, 6682169, 12636669, 17213151, 9006121, 29971302, -10155332, 1096947, 3628954}}, + {{-18465775, -908661, 49529146, 10305432, -258983, 23207363, -48359991, 18872011, -4327240, 7239294}, {11704483, 3567689, 6504514, -19537956, -25889227, 9574331, -9054889, -12073385, -52083106, -25638862}, {14856235, 11513568, 28357905, 15327185, -1082760, 14173294, -30704370, 11901690, 8802214, 16581834}}, + {{-9294664, -8457878, -10859921, 20428339, -15313257, -7900880, -4836246, 12327012, -23875432, 18148872}, {29748992, 19265676, 55897757, 2341831, -32343551, 16165530, 18983458, -10735336, -33163498, -11994620}, {31177644, -6686720, 4589526, -1943272, -31542249, -13403714, -16612505, -11535916, -16130625, 4101054}}, + {{-22368116, -3844438, -19803753, 1659525, -5314680, -33207352, -2393824, 158285, -22091012, 140342}, {21845392, 25861238, -3508139, -8460531, -52731176, -337492, 44029314, 11925833, -9152248, -3183260}, {-26957058, -985488, 11453566, 8162404, -9971724, 565243, -19106334, 15417138, 9570869, -8065373}}, + {{-7721498, -4576026, -49911119, 20372007, 20354437, 1785214, -18870524, 13216149, 13918268, -8338041}, {-18075312, 9107134, -13490015, 4262595, -3728271, -14273974, 27655182, 14282167, 18990264, -11873043}, {31949564, 7089028, 25036939, -147319, 6152506, -10917749, 21271289, 16352110, -4421421, 6096833}}, + {{-26160543, 23504438, 11550855, -22659236, 46630207, 24953409, -24064935, -2746233, 2457397, -8551569}, {-9276343, -6010072, -51234109, 6197754, 168167, 8495751, -8515229, -26660199, 44782121, -16745075}, {-23133267, -16088093, 32728011, 12088731, -22980897, 12361190, 13199668, 7106395, 16088520, -14360530}}, + {{11203394, 3535766, 494786, 2853581, 9470242, -10646902, -23262130, -3003340, -3438958, 4422278}, {-32520048, -15070518, 50782614, 606509, -34539328, -21730270, 26791576, 29915800, -1159434, -10942548}, {-26091274, -13738808, 26351380, -5292040, 8784328, -10413437, -17838113, -13270798, 32104096, -8195358}}, + {{-19763951, -493920, 37902700, -8894654, -21572, 9573680, -14380422, -5852103, -48784846, -2268320}, {-13451423, 8885698, -8613990, 14234224, -66053122, -1944250, -28789948, 10126155, 8041774, -8216666}, {-25625293, -12364030, -12897751, 15561517, -23966084, 15039628, 8398684, -12669672, 25537255, -3738530}} + }, + { + {{-26823707, -3014143, 9257839, 16598020, -57710506, 26340007, 14598539, -6911811, 8624957, -3355993}, {37578051, -27305543, 20671357, -16093098, 5470554, 7124597, -33166821, -19298833, 44351923, 3093751}, {5192241, 5198744, 8259336, 14807706, 16734428, -10213346, 12579450, 1529321, 3710929, -13803643}}, + {{32567887, -12778530, -4546434, -5195811, -23112588, -14382296, -2610796, 7243838, 6824785, 24853059}, {-33100475, 2101530, 14782812, -2946043, -13097786, -18547340, -147316, 4263580, 49118509, 389861}, {-26433271, 3095771, -21099841, 8183997, -17979696, 2375076, -6173115, 12351253, -15162325, -7325167}}, + {{-36410699, 7509499, -773676, 18481494, -1306270, 9379297, -7169729, 28985213, 23974182, -1469573}, {23013773, -2363861, 42337730, -14636146, -17262958, 212079, -47624395, 1262009, 2909484, -3851459}, {-26149346, -1598074, -31721571, 15768718, -21769911, 14908480, 23446540, -12658378, 16915236, -3638875}}, + {{-9573611, 4971503, -3191607, -11944444, -29560811, 11869309, -47019588, 4824066, 46060921, 8814279}, {4177875, -3528885, 43536831, 6554046, -5867355, 15354279, 11252984, 2571750, 365885, 9982789}, {-27327055, 5118536, -31003207, -2703988, -10913454, -6579013, -347619, -13536091, 22064770, 2451589}}, + {{-4054695, 5508150, 8968001, 15696040, 34336025, -19961059, 39155732, -7741309, 3460211, 8754601}, {53223993, -10795298, 1673849, 6566416, -25196301, -8107069, -15920352, 5890225, 30723453, -3973739}, {-10930190, -3718190, -24018573, -5446691, -27124800, -2428338, -6552058, 10097421, 32754393, -12001899}}, + {{9541613, 578230, 46189570, 932191, -39549476, 14125606, -20809415, 3664578, 38544816, -7737920}, {-7785869, 22461888, 17548446, -31568433, -25462556, 113852, -24901067, 10900994, -1525684, 10284652}, {12805753, -6731773, 28606412, -15976473, 17923858, 4215695, -8478244, 2410106, -5118417, 3095629}}, + {{-1274366, -14111579, -17609504, -9308071, -2709772, 20098094, 32833994, -8567754, 39391185, -13251562}, {49592320, 4207465, -29712732, 12885247, -27241144, 10683524, -7141288, -5135490, -25568193, -20093574}, {-8692174, -15973418, 14281508, -8382675, -477954, -9393444, -16847821, 547829, -822026, 6187183}}, + {{55926199, -13775110, -29489980, 8866140, 2339475, 3058935, 10330494, 239241, -12863051, 5699647}, {-10902873, 5615930, 28459160, -13948794, -14276655, 17635101, -4830130, 15571287, 41027545, -19163461}, {7107704, 4303869, 11655336, 14710427, 20216631, 8353283, 33184466, 1711678, -5172945, 11112386}} + }, + { + {{-21095760, 5299745, -27763118, 28284282, 1436142, -11502593, 36039271, -8549379, 14317211, 4479743}, {5683176, -14334649, -21838364, 4193246, 25608474, 16596289, -12362999, -4451691, -38177811, -9629351}, {-31491964, -9284285, -13811425, -16199088, 33353176, 13273993, 18365355, -11123036, -10830146, -1597417}}, + {{34402472, -3135277, 27771230, 22812093, 23940857, 11598071, -3989002, -5470641, 8010160, -10175848}, {-8288232, 10607321, -29598962, 6489101, 18323079, 19296159, 36126604, -4683323, 47574698, 12220272}, {16539663, -16433251, 28689171, 12952953, 22598174, 4283866, 32968775, -12075843, -33205368, 9921492}}, + {{28911702, -624890, -1956282, 20708125, -5990290, 10957759, 20918129, -11179075, -26234635, 19409040}, {-3987662, 25401092, -50912550, -9360127, 9291736, 19825745, 25396275, -3992341, -21209227, 5763050}, {-7167022, -11584585, -7333411, 8659035, -3813935, -2472291, -24501709, -582095, -31003960, -7572359}}, + {{7377972, -7045175, 3171818, 26600343, -21971503, -827928, 799562, 6807644, 12089895, -1568018}, {-26854334, 604743, -37384910, 6651275, 37667675, 5825320, 30304082, 16548576, 18929689, 6380490}, {-4734860, 2916604, 13659705, 1230109, 7914478, 1161122, 25569968, 16095238, -15211374, -12625431}}, + {{60046092, -19290031, 55644508, 5924598, -16766437, 3649303, 15210001, -17200016, 8334941, -17348311}, {3053696, -3308889, -1659352, -23119850, 48903761, 20154609, -2016783, -1501822, -13598205, 15227395}, {-14027328, 14143977, -29622540, 5698529, -17797829, 8965460, 24478568, 10860023, 6255778, 1962558}}, + {{12838367, 21455368, 12394529, -139996, -13218318, 14835646, 2847962, 1094168, -61604547, 23469499}, {2855951, 6031460, 45288055, 3797286, -51243370, -15934874, 19639606, -31254818, 5495231, 5512993}, {-18991821, 9505719, 20743211, -7202131, -2855225, -2478301, 29885329, 978005, 31385863, 4697927}}, + {{35701794, -24267613, 17101414, 12014107, 4146841, -12963378, 27534917, -23554339, -7899590, 16246191}, {-9676560, -3481087, -6536306, -3008555, -54980755, -20435504, -34010965, 7211889, -37950560, -9244615}, {-32523039, -14841927, 10221226, 14841350, -10266079, -5102634, 23372907, -5705056, -19578232, -8060045}}, + {{-7658070, -19432232, -47290862, 8957403, 17168605, 906858, -36808100, -6985063, -31491665, -14371382}, {-58222020, 5666018, 2688918, -3396193, 5751191, 12826358, -8403380, -25463309, -5058029, -6124326}, {-19076639, -15036080, 2429930, -11958307, 12461663, 5994178, 10138261, 6269717, -12097369, 7547950}} + }, + { + {{-46501177, -2125548, -9548106, -8843125, -2923066, 17176878, -30171081, -16913256, -39048947, -305231}, {15266631, -24114366, 27253976, 7266039, -54091222, 3501254, 15435497, 3471258, -25936019, 8170263}, {26834881, -6062492, -28449840, 3483898, -31136580, -9544420, -1756407, -10450795, -21653034, -8003913}}, + {{-37125907, -18209626, 42135247, 3809737, -16359931, -20806125, 23739718, 21900517, -29352752, 10613960}, {1860629, -4579294, -9973737, 3344677, -38038503, 8441211, -30132174, -950057, 9038008, 8935044}, {5979120, 13663981, 19260467, 15739069, 27378585, 1446046, -21112071, -4946305, 22988438, 684503}}, + {{-2821514, 906697, 24154172, 9182143, 54560520, 7609207, 8431926, 929296, 61087790, 1230495}, {63944476, -4178687, -22626644, -9457701, -8623058, -15014277, -55330302, -22871710, 2432744, -19211541}, {20709859, 8567199, 2865684, 12071011, 32610891, 11210795, -13386246, 7474652, -27491454, 11439199}}, + {{40618909, 2429404, 12141943, 2539210, 30163754, -14208132, 1444025, -2768015, -8060932, -6270219}, {-19029653, 7452358, 36903839, -18229978, 29530390, -1487086, -38416541, -2255473, 28777554, 6458181}, {-24736275, 12395257, -27149879, -12163758, 27353740, 3047870, -497024, 8252410, -1861756, 8325048}}, + {{-36754971, 15524492, -47907677, -1948229, 60658959, 18598121, 18387763, 611185, -41792300, -3677476}, {16737065, 305526, -12219471, 23726739, -5881191, -9681727, -23718217, 214461, 17177818, 26128170}, {-2349448, -3006891, -16439659, -2783518, 31486676, 3252129, -10712863, 14938612, 14702113, 13672012}}, + {{-11078323, -11838290, 4031, -3913152, -43826065, 21341690, 2790193, 6092619, 20805703, -23233766}, {-315631, -16147466, 45991095, 18206444, -2723379, -2056742, -41115611, 1257537, -37773205, -2067726}, {-12946980, 8349042, -2453180, 6392083, -23278159, 1324510, -6586009, -15419707, -4698574, 7511985}}, + {{-16694705, -11719309, 19858215, 4865671, -32480902, -8813778, 872249, 2334335, 14288878, 7189027}, {29113853, -18272411, 20500473, 18454115, 8794268, 19465256, -61828077, 730165, -45433566, 10039083}, {-27484780, -14872853, -23616577, 14291991, 23179101, 2019501, -19966087, 10999600, 32749372, 9970115}}, + {{3120511, 12269787, -3001538, 13290995, -1128459, -3481406, -6308853, 26046984, -5928423, -17110672}, {41139613, 13355719, 19291380, 3565697, 12270911, -17843794, 4235029, 6593636, -11185463, 6773264}, {5410979, -15251835, 21503951, -7887542, 2977573, -1161386, -3124857, 4720118, 11858001, 15384199}} + }, + { + {{25842592, 14593617, -19437269, -26592244, -6163586, 5373095, 17971662, -4789035, -16745698, 7068030}, {33768684, -8167397, -37168547, 63420, -44920202, 1433361, -23680212, -25269253, 19830680, -5240624}, {30461964, -5231669, -22849638, -14765530, -15189444, -16503368, 23230047, -14909056, -31679936, 644866}}, + {{8273882, 1137072, -17194898, -5578430, 26342019, -1090966, 16911388, 20207695, -3899499, -4290289}, {16643296, -31529108, -34850220, 12143484, -34461267, -3952664, -48204260, -7940513, -62326311, 23363653}, {7823844, 1044908, 9499386, -14637325, 31335916, 5619583, -23107982, 15533932, -14375910, -2155920}}, + {{24044439, 1439152, -58692596, -23133087, -41434693, 10688871, -45479206, 23405942, -12616434, -31798408}, {18159805, -13294066, -7075670, -5315801, 23470783, -14882841, 15090878, -5998356, 27399272, -77364}, {28684746, 5552489, 13110666, -9360878, 23897373, 4785350, 12631889, 10803881, 32275034, -6016527}}, + {{29274470, 10290674, -26252361, 27218709, -37048082, 1396228, 20172216, -15922336, 27285750, -26395538}, {-25287388, -15964396, 30064587, 3443053, -21460268, -14306662, -22954362, -3355594, 20342682, 419844}, {10786511, 8716378, -6325750, 2073134, 6445759, 6261624, 11360770, 2552677, -25621162, 12562267}}, + {{2387080, -11104386, -9798463, -22862391, -24757118, 2688514, 10978011, -9250992, -24706257, -30298702}, {13626152, 2590112, -19831931, 10156093, 8267612, -19284278, 10914457, -4827762, -7259217, 166518}, {18404147, -5172921, -10162167, 7964586, -29616364, -16556923, 14188521, -923817, -26394286, -11217322}}, + {{34295166, 5743559, -18395630, 7469162, -18857391, -2645298, 13980834, -26188707, 48951990, -5380091}, {-29630942, -26496615, 16671040, 3774880, 4578729, 27792736, -21803778, 6028099, -8320440, -1343449}, {-29007999, 2822961, -27850650, -6358270, -29504994, 14776822, -29783422, 5491385, -15122731, 16026941}}, + {{10454926, -14968006, -44739754, -11474677, -11318865, -6949916, -45687944, 22700739, 24453662, 19521493}, {14002326, 9863826, 15089352, -10779243, -10222377, 20896362, 13052866, -5438783, -10231186, 11334689}, {7410930, -14482625, -32716468, 8084678, -17291177, 4078433, -33186515, -8317799, 13550674, -3892341}}, + {{-35242978, 19954316, 54932693, 4828405, -43760401, 6985755, -845447, 23447781, 787324, 11746620}, {-11704610, -1037314, -849121, -5947239, 172063, 20938781, 19758853, -5602025, 56372880, 17452406}, {197997, -9955048, 23504559, 505454, -27257424, 6982508, 2410414, -6548151, -2163243, 9901807}} + } + }; + const precomp_data_t c_point_H_minus_G_precomp_data = { + { + {{-6101338, -6661723, 52466201, -2210993, 16947924, -6747813, -24932024, 17916559, -16983562, 8042810}, {-54955706, 22617141, 2814423, -28338455, 23705580, 7914563, -29397226, 7209197, -5399064, 7366774}, {2312352, -11391293, 18244857, 11704705, 3971365, 12980627, 17392726, 783360, 8460342, 15646137}}, + {{-20239555, 16082865, -5854372, 22689119, -7684622, 12313183, -12275638, -18070683, 4693680, -11046235}, {-17340869, -13616255, -5868684, -10034569, -15191572, 20137865, -20432096, 5217101, -29198262, -17197667}, {-13685239, 4994663, 25885257, 9060606, -4861059, -14098338, -30355925, 425817, 1219864, 5667302}}, + {{5991822, -22900537, -6527229, 23208262, -126517, 17458959, -22547298, -22409515, -40843093, 17103489}, {-16401884, -9000615, -32108929, 8000482, -36348053, 15767611, -33755660, 2466271, 19524833, -13710855}, {4596153, 864108, -26663913, -659755, 21662553, 1137542, 28544394, 11343556, -19996170, 9764152}}, + {{41479917, 6952184, -13202757, 6711746, 17108574, 7914425, 4831608, 3294066, 31787017, 16696458}, {-9912859, -21873314, 15974497, 17625586, 20721458, 25328353, -19083950, -29020540, -13141149, 1810816}, {23468401, 5254789, 29322678, -9793262, 27357687, 2411445, -31933501, 10461585, 16938452, 1175935}}, + {{24829240, -3415607, -11553057, 8637555, -21727752, 3944011, -21512010, 24623326, 2106329, 7397722}, {23165968, -18826827, -10267919, 23330437, 39673374, 25743475, -21908638, -8641762, 15992797, -23513728}, {-33263330, 4348463, -16739005, -12021537, 29127092, 15733434, -13569724, 9201179, -25105627, -8061119}}, + {{27567445, 25874627, 55288586, -17029271, 12554428, -16506064, -15001211, -12229245, 16957695, 4743941}, {-30012489, 1952641, -8591164, 4574331, -28105692, -11347574, 17638339, -15628181, -29278721, -25796869}, {28622941, -15482155, 16373432, -5796090, 31354806, 13291649, 11974248, 8564048, -2391125, -2058564}}, + {{-39990477, 28902297, 37601462, -15831416, 48058401, -17625888, 20067627, 4398, 1948666, 14493563}, {-9409557, -105773, -2776738, 4745850, -13838289, 10991370, -7785533, 15894196, -28376356, -8844791}, {5139613, -14511542, -16274525, -11962880, 22127615, -2586245, 25435983, 10515753, -31880884, 6339475}}, + {{-18563230, 820202, -160035, -474925, 185300, 26736048, 10555513, 3119407, -35591431, -17474400}, {27715556, -25786876, -53868953, -10536111, 40312998, -5838076, 16098811, -4768381, 24066977, -13251714}, {-14742388, -9988774, 28760055, -1137973, -17423163, 2820556, 13462902, -15063755, 2365930, 10207166}} + }, + { + {{-22120743, 8214777, -16537524, -13170506, -30367655, -3804888, 14277082, -7655723, -29891106, -3073435}, {9645547, -23046469, 45032692, -7413748, 25238101, 18015860, 23375640, 3930457, -14721544, -13063069}, {8892071, 10874043, 26183267, 11572119, -19978778, -6189764, 11165268, -13836282, 28945919, 12576697}}, + {{-43713126, 10624462, 2244625, -5556759, 25677104, -4558855, 15921880, -2953411, -10126390, -15025580}, {21154744, -8623864, 34292103, -3947205, 14634966, 9802863, 1030798, -21831087, -45813164, -6575692}, {-15858732, 13244353, -9311750, -16777004, -24476168, 6533093, -14726264, -1857811, -30842811, 14092289}}, + {{-20741142, -13333832, 27103343, 133627, 37750992, -3004882, 38886057, -29382432, 1034177, 11512600}, {-24347748, 3329888, 8876127, -22219603, -27419014, 25634800, 7617255, 2189800, 51893749, -5986452}, {-28491424, -15032272, 17877437, -14849685, 24733680, 12923188, -19810832, 15978551, 10922438, -7062212}}, + {{-26640111, -178237, -35738854, 21282776, -5490584, 25289123, -6794212, -26318179, -34919902, -11673855}, {-18238855, -20673019, 22503232, 4914042, 1855146, -6596791, -16049626, 851155, -21473438, 7239795}, {-13957512, -10845007, -9344893, 3930543, -27685800, 6937443, -23691600, -4918076, 32589247, 6455341}}, + {{16526111, -6392092, 1708620, 3103013, -10506175, -15044426, -3405340, 3390661, 9295024, 2063528}, {-49932405, 13823922, 23742874, 8829607, 14400923, -9972258, -41905254, 9219263, -35315460, 3521880}, {6238471, -10947822, -24612275, -3062096, -574262, 16197161, 18544232, 16526487, 6451418, 11587300}}, + {{-50698541, -6087676, -27232443, -12883517, 23198182, -4733605, 31122254, 7534375, 17334832, -2172862}, {2652287, -6328240, -16488621, 4399119, 35828600, -13855299, -6507372, 19854551, -11675082, 2715146}, {1779170, -11057330, -17013399, 10794427, -29670278, 5041182, 4162604, 4819058, -5876700, 5891788}}, + {{-20128844, 12960738, -26095675, 8724256, -21288208, 9502783, 29514068, -7023482, 8760189, -21777967}, {10315580, 7944400, 6193735, -2872928, -14712394, 16709417, -33625212, 16370780, 783701, -1285117}, {-14308805, 2475807, 21851135, -5618028, 14019294, -1367027, 29930296, -7504524, -22810989, -1325662}}, + {{3034705, -379052, 27627388, -29829746, 53617870, 8781049, 4100868, -3891310, 18918766, -1184752}, {34079955, -25432848, -24804370, -1454352, 4794280, -12552821, -27137072, 24569148, -21636950, 1993120}, {-3631411, -7915777, 6881202, 13646543, -17280490, -15203821, 6059144, -3096132, -7623624, -1486531}} + }, + { + {{-30794706, 4193518, -3100471, 16293049, -44803351, -14138044, -6883710, -13589283, -2137231, -22048690}, {-10704982, 3112646, -49264641, -12320505, -8473927, -7380064, -54108640, -4496501, 22032607, -7023850}, {32205918, -1999462, -31763801, -6635700, 1471421, -4013239, 11109037, 4381075, -30055289, 1647751}}, + {{963806, -129029, 24200205, 6647995, -9310093, 14434334, 21033793, 14209113, -8941803, 13304238}, {-42256054, -21328797, -1079861, 20566913, 54126569, -2594292, 15916909, -3625267, -24490541, -10323520}, {20035969, -10243999, -361060, 10756081, 3708164, -3820680, -24684404, 15141043, 6122086, 11727407}}, + {{-20761434, 20468957, 19441516, -4801237, -13285554, -2855042, 20509510, -8317203, -2231314, 14226324}, {3230036, 4083709, -20861872, 22688277, 26776420, -22898826, -16397120, -16389131, -16327352, 9745498}, {23055320, -1015854, -22173868, 11817687, 3875936, -5554632, 10818006, 11975513, -30064607, 5602738}}, + {{-3797584, 2143396, 41373422, 10088770, -4323111, -8006060, -28733171, 31937202, -15515802, -19245910}, {-18084114, -21375490, 21067414, 21399088, 41438069, 16598512, -10735599, 624980, 43989634, -8186604}, {19265941, -11752947, 13008137, -440499, -28197295, -8194060, -8167619, -5402200, -9371860, -1511455}}, + {{20014993, 3036485, -2411032, 5201030, 15452009, -11532833, -3762505, -8116517, 14198543, -9759075}, {33803163, -12092281, 51716774, 12265996, -6263457, 13381537, -57412117, -15468831, 17489717, 13992345}, {-7050586, -13229311, -14053896, -2607878, -30391729, 4333136, 20018106, 5769504, 16075790, -2822102}}, + {{-52894114, -15629487, -46141433, -6403030, -42466534, -25929688, 40568651, 4319114, 3029340, -1641405}, {-1351028, -1895103, -5958939, 9371256, 12742380, -7016350, -3107701, 22045356, 60038268, -15536511}, {-3641558, -15695305, 17320295, -8496472, 27104650, 633886, -16487319, 4002986, 29368940, 14253059}}, + {{-25329185, 6803809, 4972840, 27875024, -12209055, 9576734, 14785991, 21810088, 9438919, -18962595}, {19468239, -6004183, -20351276, -2692078, 33748531, 18594702, 31208815, 7746930, -25008727, -13861261}, {26935831, -9007108, 20829108, 10561049, 2588905, 5176098, 30880933, -10060792, 22768114, 2121024}}, + {{39565998, 849850, 7902098, -10429778, 55170890, 727178, 6039426, -13823556, -12125552, -1422093}, {-27479186, -3738654, -19540892, 8121694, -7717904, 26193154, -31340900, 12424846, -40892244, 2374969}, {10378627, 4280903, -20059863, 10785942, -3881646, -1484235, -11088665, -14432213, -9713771, 4940833}} + }, + { + {{1321341, 7822682, 30129669, 15003251, -34242353, -3199130, -38699977, 15818464, -25668076, -17890301}, {21893467, -10495072, -11393613, -8011643, -24395793, -8315754, -24636887, 2020314, 38141242, 11640697}, {537710, -985963, -20113460, 772213, -17074876, 6579162, -29261232, -277742, -13691266, 16596486}}, + {{-6575860, -11322994, 16005315, 25640240, -38363617, 12480731, -16895113, 6663001, 31273057, 26261951}, {-35662360, 21760402, 9794695, -5673532, -15607703, 14029503, -12256697, 18025009, -15179731, -2020021}, {16240855, 9341981, -22062926, 1032788, 32459121, -1346271, -5024171, 848026, 31529680, 14449571}}, + {{23589167, -3082355, -4158355, 25692800, -5440287, 14910648, -39128857, 8743929, 18404903, -1271302}, {-39982651, 7808109, 42406191, 204492, -56770365, 17067524, 16864465, 24295675, 7470461, -2966368}, {-769302, -10524785, -22960090, -3059387, 20456220, 2995609, -31691673, 12811332, -25375538, -6866131}}, + {{-5479409, 7184848, -61386185, -27165755, 12508891, -800753, -28294762, 2001146, -42658474, 15583920}, {10278091, 16087604, 3504711, 2627493, -30529291, 1044625, -20264556, -277244, 15718644, -14245200}, {-23585994, -5170531, 13605139, -6824381, -31877964, -14467529, 20989739, -1962312, -20651386, -4810754}}, + {{1663747, -10381012, 7061354, -2926878, 16643780, -13303228, -21701068, -5385587, -1005304, 2270822}, {9694317, -11897358, 16694536, -16421760, -22993144, 18408490, 29670560, -20192631, 23823048, -19855070}, {23765827, -2140427, 16895410, -10593501, 21772748, 1266351, 9253368, -7750571, 10654946, -11719271}}, + {{-5229250, -26563297, -19240791, 23303806, -18607470, 4765156, 22256589, -21365648, 19967362, 6617878}, {29082160, 4783087, -36336837, 8269700, -15340274, 25786716, -12018871, -10424922, -39427114, 16449334}, {-18458034, -13537141, 19169152, -13127868, 16016807, 940859, 4939512, -15032988, -26006392, -3762429}}, + {{-15120130, -7906905, -27001641, -8478349, 20297117, -9569850, -36779926, -7254406, 31942900, -976659}, {-25257406, 12042933, -37406413, 4868777, -6799057, -11952414, 26178830, -6802520, -11400198, 15407065}, {29101999, -16768541, -3466200, -3200415, -28041044, -5939374, -20439036, 8961453, 22139600, 2515024}}, + {{-13170662, -3120571, -30040295, 19550841, 20687868, -25764859, -7537027, 1396706, 10954150, -4426632}, {-26476568, -28220503, 30554065, -9938631, -25055028, 5360813, -36499451, -21577222, 2956918, -18505338}, {-31586365, 4019163, 20171651, 16446367, 6564339, 7881865, 17166893, -6973576, -8741426, 15217631}} + }, + { + {{37724191, 2128753, 40127511, -8621902, -11394166, -9978726, 23322676, -4342525, 24708417, 4155493}, {7564583, -28658637, -24011221, 11812306, -13125602, 807260, 25677764, 10254029, 34021623, -27174203}, {23158489, -14256612, 7239011, 13353059, 12116206, 7147839, 21636686, -7629531, 934063, -6360107}}, + {{15947591, 11065498, 47165515, -10874162, 4263318, -9309466, -10147489, -12632364, 12907733, 4889582}, {36916327, -22280792, 4329529, 22133766, -57566424, 21473618, -25502043, 5592570, 34395511, 20213400}, {32534470, 4744775, 13893135, 14635756, -8593258, -6280686, 19835917, 956060, -26940546, 3268553}}, + {{-14834121, 21275574, -27307203, 18073803, 33679433, -10892766, 16360541, -16737284, 21425539, -14175139}, {-38126757, -541986, 30356987, -10054699, 21323519, -5830432, 21313753, -6311744, 10248145, 8132563}, {-5708334, 9104274, 31813558, 7785104, -18336653, 6878670, 17404302, -5911886, -459625, -3610891}}, + {{20386923, -15677149, -12200355, -12784041, 47888652, -29759045, -7999005, 28411685, 29882388, 10794353}, {15693305, 7201225, 42110843, 20650073, -12074238, -369965, 27791119, -1255461, -8839378, 19477021}, {-1560321, -16752443, 19288819, 12537089, -9300441, 10089807, 16528900, -8449695, 6522695, -6565250}}, + {{3123481, -7047683, -34225299, -207468, -47673061, 3799009, -46924314, 2435848, -15840276, -16602601}, {-28759085, 12257437, -16055881, -28804748, 18334973, 28629045, 1515542, -22654612, -46605844, 11625777}, {-9916527, 10074067, 22878367, -4934849, 6894510, -15343499, 10761228, -15484688, 24914775, -9765601}}, + {{18494000, 27335693, -15198265, 13456320, -54433815, 19359117, 24303592, -2866310, 6218073, -2795545}, {-44583996, 3666011, 16986825, -17177156, 7779961, 2983503, -7723854, 18341634, 54958497, -17011269}, {-3049511, -3192827, 3697038, -15732998, 18333717, 14801153, 8967530, 307604, -28163105, 2934167}}, + {{21281758, -15806243, -14063749, -6126978, -2980791, 12388256, 58512170, 6028561, 37380758, 19708289}, {-17516074, 10109337, 33917323, -4860180, 11309595, 3509268, -5216114, -14479775, -9112088, 1307621}, {-28602911, -12769632, -9927277, 5377764, -18663180, -5109576, -2879888, 13866478, -2134299, -9309278}}, + {{-27219617, -8386696, -1756998, 11339489, -26522536, -491182, -52012366, -8811791, -231732, 10704184}, {18924945, 16353718, 24735484, 508745, -38110110, 32940662, 7594046, -8852717, -118966, 9806590}, {33106709, -14738830, -29721239, -10755676, 30395984, 6505380, 2577250, 7670846, -32171920, 13080748}} + }, + { + {{40538795, -4216279, -34572866, 7346784, -58158763, 3931894, -42144891, 13283221, 17300235, -6571408}, {-2489815, 28162463, 27387040, 22105246, -2372369, 10646282, -3434155, -18142427, 28619093, 21422272}, {-25111500, 3173572, -30905814, -10495414, 11698025, -13016057, 18734520, -802179, -7251386, 2117515}}, + {{42079065, 22103740, 11599837, -24909164, -3892297, 8461553, 44682053, 22776278, 4892668, 10481772}, {-15902141, -3914706, -16818939, -3786126, 46346375, 126419, -15906359, -6596048, 45009884, -5225704}, {22832941, 6653227, -23548897, 7600611, -22883790, 15730731, 11385385, 3236069, 14005890, -4631081}}, + {{-34671908, 2394114, -21140842, 4364765, -18714643, 14159622, -3566512, 8157898, 18324055, 22295943}, {-21201954, 12073618, 4148242, 19378675, -16364813, -2800964, -13005626, -8243080, 36311749, -9226055}, {-24556325, 12868514, -1657543, 1092057, -8011455, -2096939, 22210132, 12091612, -22782604, -10109916}}, + {{-28147016, 6703441, 3973677, -9623541, -16382462, 1667979, 3322106, 5854035, 36512345, -5400534}, {-443898, 21627577, 17566599, 18783545, 12847094, 14035793, 2960664, 13020009, -11549121, 2861778}, {-4522181, 11882774, 8475789, -14118257, -25417618, 7582031, 10885084, 15307303, 6828798, -9938396}}, + {{1291838, -30757626, 2745849, -12233840, 9638012, -16205526, -3794322, 22529482, 34743255, 20697921}, {7323886, -2031622, 1226007, 17838176, 8785098, 6351908, -34562784, -9215646, -19342019, 1557175}, {32667632, 7899099, 23830378, 2738684, -4038286, 3083299, -6230727, 14227100, -16910821, 11170159}}, + {{-50674843, 9630416, 21490359, -8922849, 22746412, -9227086, -4045943, 13530732, 2821767, -5361895}, {-1520365, -20515430, -12784209, -22859873, 14610844, -10143662, -44108161, 19218786, 55375617, 6555865}, {-12546186, 11588292, -21884389, 10163443, -25738849, 10366640, -776566, 12205382, 4642095, -972485}}, + {{-34675374, -269954, -25203603, -3175750, -39262251, 14563508, -40309164, -10560664, 46998209, -7880691}, {-23607712, -21981252, 37820109, -25583106, 26421879, 13459474, 16102520, 17199398, -11204903, -7709979}, {-33344548, -10610181, -32338187, 4502935, -21293101, -2739559, 31631278, 724711, 2055601, 15508788}}, + {{28807944, 23468451, 15536506, 4408442, -26621895, -23509414, 29527667, 9871672, 30198537, 1267620}, {-25869962, -5004855, -4272376, -10698046, -21064195, -7358662, -3226745, -722504, -11481489, -25363828}, {21625714, -909969, -14009617, 3749410, -8687689, 16017672, -27521046, -546939, 13129805, 5674757}} + }, + { + {{-20183821, 19532978, -32191009, -6156540, -37202121, -21409439, 44374168, 455503, -29190069, 5436715}, {-19993685, -237584, 4391783, 6025922, -12686313, -6184127, 12209294, -19390657, -37189161, -18447813}, {30056282, 9042644, -21846172, -947930, 13832123, -6723925, 24553441, -2250546, 31520440, 13124751}}, + {{54012931, 8747996, -7042666, 23882753, 21689448, -21244501, 9683790, -6643746, 26475259, -20112532}, {-9080279, 4590244, 58648868, 7181005, 12444242, -1045169, -6357594, -8370376, -29050935, -13160086}, {-23220929, 8551641, -18344564, -10860643, 5166534, 15227920, -14311635, 9346907, -27745370, -4242627}}, + {{6030328, -14326048, -14395069, -18988503, 2510641, 6568118, 20085405, 18264092, -7901093, 1331527}, {48201032, -11355804, 39104275, -9330837, -53756247, -22282096, 10606201, -5617870, -48235113, -12073137}, {30730367, 16552973, 955166, 7614078, -11766958, -2987945, 109054, 13883679, -4820682, 3232770}}, + {{35847261, 7893146, -4753404, 14715425, 5001162, -8483603, 9446375, 794052, -2238517, -19422030}, {-113825, -2023890, 47155862, -9008631, -33086870, -2992677, -55064941, -6656434, 56237155, 365374}, {-27132279, 6776707, 9606112, 12642639, -4958885, -2165454, 20090003, -12012175, 26849783, 9369239}}, + {{24498148, -68029, 32314769, 21871950, -1778691, 25867830, -38784775, -9779251, -37100537, -18380968}, {-26574082, -5857179, 11612663, 11177058, 16265295, -1980800, -24693427, -13974811, -9090895, 15015066}, {-12646670, -13544908, 14736317, -10408651, 29354900, 7546326, -5056778, -12160712, 14219988, 12020647}}, + {{2078977, 7756535, -2094336, 22250581, 38264716, 18702332, 35507824, -9746461, -45640296, -16787975}, {-63395, -15724695, 4917594, -7096055, -12544212, 12643738, 2129126, -1762963, -9689822, -13903891}, {12226091, -3745837, -24449171, 7138866, 10310764, 3478407, 24968873, 74508, -5893517, -8182326}}, + {{2474386, 19137005, 517900, -22293688, -35515458, -20683174, -10953486, -11862798, -13592164, 14998659}, {33158240, 5485931, -57096662, -5830178, -1484168, -6321034, 24526860, 1853740, 1713002, 781495}, {22150625, 16448009, 15541097, 13740537, -26397610, -2097295, -16644217, 14340770, 14497042, -1793232}}, + {{-20654129, -14872657, 45958603, 2546808, -1633955, -13389878, 4656838, 20420007, 46019738, 4764726}, {-2383585, -5472081, -4199067, -7444262, 16241707, 15511626, -41611650, -5660155, -20669084, 5701238}, {-957032, 14983808, 18341670, 14859549, 5760984, -11884467, -17939351, 10825550, 32732196, 9180328}} + }, + { + {{-15671227, 12842223, -46578346, 179553, -13722203, -4848162, 13283797, 17360002, 27616, -15380514}, {-45791795, -16228121, -17382166, -1905151, -44241699, 26894330, -7621401, -13387180, -51390268, -4641508}, {31574022, -951629, -10106442, -16591659, -14640758, -8789942, -16159450, -4494554, -10869913, 16717839}}, + {{36519535, -2061677, -3680068, -13614447, -7774275, 4403594, -53468676, -3096111, 30419643, 245891}, {-10761735, 26264941, 60870546, -5407247, -46979489, -1044766, 9445600, 8396857, -23854355, -10365889}, {21023294, 9978609, 6499153, -4862005, -8176891, 12085401, -10516889, -11285832, -606036, -2449999}}, + {{12479823, 2351623, 9251973, 2307144, -50997327, 9589083, 34956101, -17432615, 14290551, -25154724}, {14448917, -13177279, 53903265, 29505116, -1425903, 12157093, -1470743, -6334861, 42959535, -2396850}, {31161346, 10595307, -28610140, -848835, 10531704, -16436132, 22736169, 16667233, 20472468, 6175809}}, + {{-3147237, -9296413, -21260341, 12281885, 21515855, -14017069, -33563970, 3418846, 635705, 22095990}, {10546539, -16537939, 7724965, 4504747, -24072385, 7829417, -16843652, -5095778, 50390213, -2611288}, {-3980401, -8112514, -5173618, -10517685, -17223841, -5724252, -6688177, -6063807, 11816545, 16288045}}, + {{-15789337, 2788875, 40358750, -19893926, 1194945, 3868426, -41524624, 1897471, 15690471, -23343573}, {17397455, -25043369, 26080578, -1347894, 4544451, 17379882, -18410134, 18216929, 27018093, 1504693}, {-33377072, 14930193, -18958152, 146826, -3960760, -15963346, 7278738, 1221107, -15122463, -6044983}}, + {{21672262, -9863187, 33742395, -1311619, 11369404, 813149, 13860947, 8295531, 32642558, 13345380}, {-20280992, -9025217, 19703555, 15780543, 16216708, -13027053, -23028721, -9418037, 9617648, 11679344}, {28380250, 3967585, 16535461, 13619847, -4389541, -10046677, 23115554, -8322993, 9737103, 5407274}}, + {{-9582309, -3601605, 30404757, -13579377, -1385789, -3926919, 5824215, 20646794, -11241092, -14480467}, {33388693, 3833459, -8958705, 14331131, -60715931, -6494861, -37357921, -11047264, -9884794, -8874553}, {15135988, -10980931, -13349750, 11547314, 15189829, -9394623, 17645388, 2563198, -19348674, -12491350}}, + {{-52019408, -757959, 4357729, 14467913, -43421269, 18530286, -14445533, 15404627, 3559916, 1362776}, {-5145972, 23176057, 27491243, -5439415, 16179451, -6360704, 13700485, 8397943, -57288586, 11684958}, {17503686, 2541735, -23937769, 7155589, -15084486, -15742750, -16592, -265052, 26699193, 11820699}} + }, + { + {{-7344556, 14568660, -9287434, 8931746, -36763984, 23570463, -37008013, 1116413, 40616431, -94720}, {31610102, 4522094, -33374130, 13379140, 7360328, 7338337, 13607859, 29459031, -10585567, -28763936}, {-28270377, -14406710, -24751012, 3128366, -21126881, -9520388, -4374494, -10754448, -18452083, -11693577}}, + {{15394067, 1825726, -8734562, 12191035, -27304026, 12212917, 14551275, -1532335, -27285732, 25314605}, {-27910433, 10570206, -8709850, 14720953, 21963748, 11343969, 47180677, -7603861, 7933956, 5498311}, {28006027, -16151472, 13521442, 13243177, -529806, -16475123, -15274578, -8403326, -535931, -12600370}}, + {{-21625743, -26815416, 59945131, -3335279, -36794607, 16945693, -26388970, 8418032, -2776502, 21711883}, {7139017, 2567070, -6626235, 25992455, -16239273, -1402175, -2337384, 4391236, 13103206, -3416433}, {2462485, -8606454, 19628903, 6490117, -22774658, 6624825, -17127006, -3650734, 20524392, -3437325}}, + {{-53429272, 13875079, 26093790, 29354958, -11789948, -22938565, 19035002, -22915758, -8059486, -17995383}, {-6902074, -2129399, -36254496, -751884, 47716622, -9107675, 18577148, -1841492, 37832574, -11639429}, {25887122, -5820371, -23646576, -16091471, 23431591, 4391114, -27719401, 15537084, -19873079, -8508401}}, + {{-2317688, 7924430, -16990939, -2473366, -17981926, -9922110, -13416919, -1601779, 42558120, -26549126}, {-16199864, 8765112, 12953133, -4665338, -16355488, 21605980, -5709959, -1409723, -8933390, 1204012}, {28135877, 9205068, -24000920, 931630, -19560795, -739988, 5927878, -7368152, -15649425, 11646223}}, + {{9257311, 17876361, 28774520, 13645993, 28074009, 15984758, -61648790, 8268728, 42992812, -11630774}, {-45990987, -14354733, -20188398, 17827247, 1818379, 11194828, 3382554, -20347218, 18368342, 20135378}, {-2793074, -4852944, -26600001, -12448385, -33484513, 2696115, -27189303, 6765467, 23538784, 4165256}}, + {{7287098, -12926256, -45342968, 9718509, -10185494, -15236620, -10750624, -5972283, 21150789, 22474196}, {-29246526, -3192908, 3664230, 22597429, -46513944, -12414458, -28147984, 6283953, -24048835, 4227258}, {8360069, 16338978, 22519826, -260286, 6100160, -2406678, 21978122, -11580253, -7658037, 12005667}}, + {{-26068061, -2523003, -9439380, -17189516, 30990991, -8802709, -3578935, 4770212, 19147364, -17664828}, {19772521, 15129153, -15759600, -3497000, -21374223, -22095889, 28312339, 25466624, -65908, 12595568}, {-1122238, 2770614, -7412651, -12281534, -16654926, -1670658, 18067237, -13464010, -1833292, -7183382}} + }, + { + {{31381525, 7369560, 1973649, 7307845, 21541450, 16162690, -16259507, 9534176, -7691517, -14805525}, {8394915, 15348212, 48565281, 9225407, -38629408, 13209262, 16333445, 20342002, 46261201, 3539707}, {-18539019, 2106577, 9288885, 3325718, -263466, -14448806, -27788587, 4671734, -11848226, -8886225}}, + {{-300067, 22970948, -13975962, -5728090, 5140208, 9652038, 5155759, -21573460, 23663092, 2652448}, {35841085, 4407610, 33081538, -22133262, -28467234, -8281880, 44469699, -4934818, 30104160, -9208820}, {-19698986, 1335808, -21417594, 811874, -12814240, 16506262, 5879011, -311305, -18960987, 16364484}}, + {{-30111230, -7222663, -14683557, -17378652, 45350896, 7665112, -3057012, -5726529, 41332385, -16361164}, {-16070448, 14077903, -36081801, -12728696, 11713258, 24161708, -36999146, 7201523, 25424681, -10984438}, {-21882237, 13033240, -6629172, -7946221, 27705890, -2499569, 30322965, -10223164, -8591208, -2635625}}, + {{-52514684, 4053331, 4713098, -2944649, -29552992, 25610776, 25689684, -772588, -20956868, -4226923}, {1785260, 1400139, -33552198, 27751923, -7718692, -2472450, 10232018, 3864406, -34956572, -28898285}, {30136313, -3170020, -5895703, -4034764, -19409224, 13548140, 29154246, -7502233, 4297010, -12426185}}, + {{37285856, 6620401, 33032219, 12520925, -16731830, 18030763, -48730100, -15385640, 13422210, -30695821}, {-24896606, -2337679, 1514039, 10809135, -49006636, 3715431, -4467266, -59684, -38931554, 178377}, {30579906, -2804849, -14021137, 4914833, 19829198, -16417336, -14022916, 7709701, 10019045, 1326128}}, + {{15573024, 22077344, 40657518, 17428306, -32837137, -12312428, -1352150, -24427651, 13171649, 22861580}, {40345416, 10245140, -21686088, -11631184, -15294725, -6993572, 37932074, -5394379, -22015921, 2937354}, {12285896, 10015721, 11181068, -16075205, 25435143, -4993092, -7906923, -4104819, -33088426, 6911007}}, + {{-14288714, 24611891, -9318638, 18425515, -29551975, 32061897, 44501306, 9986976, -53007122, 16841307}, {-26203570, -209751, 55784778, -13989061, -24066219, 698831, 10463736, 12671504, 13180164, 5765713}, {14584465, -6840259, -20336593, -16089054, 14531784, -7914842, 7285215, 8297456, -499589, 12702118}}, + {{48080161, 8499401, 21375945, -5062693, 49962757, -8138420, -45926519, 11270415, 53591414, -8152215}, {8808527, 7201917, -22829747, 20035413, 16031651, -13250504, 2608313, 3594091, -9411994, -13650797}, {-21057039, 12514712, 24066971, -9909449, -23147245, -309497, 10289333, 16455742, -26715169, -12780043}} + }, + { + {{50850482, 2749855, 24073715, -23935977, 22552105, 4110591, 9903456, -18616850, 36277032, -21602916}, {-6475044, -5027387, -14000411, -4740205, -28020029, -10063133, -38361248, 3542210, 29120388, -7631060}, {130434, -9901027, 22113620, -5656710, -17048528, 4560621, -22498012, -4195487, 23698948, -530703}}, + {{-217036, -20099660, 8883879, -7740627, -28471174, -5096333, -24104800, -9237006, -23600083, 22889535}, {-40280378, -6603470, -7992535, 24243861, -17282752, -23756609, 25944016, -18416066, 210447, 4087533}, {546356, 4369567, 19111426, -13494740, -4310689, -2262866, 15867136, -4508329, -26759003, -872130}}, + {{-47143961, -2830753, -52476752, 4310356, 30932359, 26924585, -15333652, -1324616, -56713655, -5371453}, {15704297, 25068011, -10255402, -10403192, 32876973, 3434419, 31806200, 15557734, 8574335, -3041719}, {-30670366, -14649251, 20100519, -9873163, 13151223, -9463920, -19375915, 2292491, 18335487, 10612683}}, + {{4323708, 4632738, 34150237, -16521458, 35976929, 21966351, 43256286, 13665358, 47051586, -4020804}, {14793854, -27828124, -14220909, 3219190, 2870165, 8536493, -10242664, -6177318, 4770504, -3196018}, {32820291, 7385782, -191408, -2202015, -11385888, 9783485, -1357779, 4434160, 30737354, 5266517}}, + {{21255691, -722666, -43664660, 18487204, 8986992, -14480190, -8041651, -2496643, 22426536, -15482301}, {11038069, 25055488, 4226810, -4601668, 6350444, -5476734, -11004769, -114427, 9861282, -108863}, {-24293464, -8648141, 24285522, 8481277, -9855532, -16193435, -8778236, -6573546, -24555327, 2174770}}, + {{44243230, -6236312, 3130865, 9438300, -20293736, -2626002, -31544808, 50105, -43328493, -6894090}, {-21737236, -1879554, 10124873, -20228092, -20172110, 27483514, -10380300, 32545017, 13580881, 7835806}, {22813744, -6818496, 25498943, 7689915, -32235693, 4414276, 3546736, -1725664, 20537352, -14812348}}, + {{-39681599, -13027117, -10085298, 13899170, 22032372, -8387711, 4766332, 2845365, -43365804, -2206284}, {-12589561, -4412273, -26724102, 15852826, -23580010, -14272341, -55526656, 14560509, -12132536, 18706252}, {-17897852, 1457829, 7072841, -3312722, -8507461, -6932282, -14939438, -2267674, 8711246, -8911855}}, + {{-22882335, 16065570, 14994245, 4113494, 2866064, -25543377, 11353097, 8199010, 24012927, 766219}, {24431873, 3238284, -11830995, 3913078, 11527904, 5966513, 44574273, 17620630, -28724833, 27837069}, {13967849, -15046043, 22345380, -12767227, -19259529, 562705, -19403118, -5046868, -9526521, -12715162}} + }, + { + {{-39820767, 6776276, -23668008, -12048052, 33609065, -4271605, 2060600, 26138553, 46769322, 7119129}, {-7207495, 25887498, -4805744, 3343738, -10732775, 10373369, -62019564, 1532137, -18743706, 25642887}, {25409378, 12250175, 2070113, -15020952, 474928, -11107280, 3951694, -9152751, 30073579, -11343063}}, + {{12864865, -6802072, -16611084, -7905641, 26913129, -841686, -16861889, -17634633, -29923863, -3123800}, {43292161, 17555728, 14252832, -11427467, -2566889, -21070308, -20426205, -3683745, 10655581, 23131590}, {-6358451, -13293247, -1425317, 3877821, 17813511, 4309397, 10356114, 13699815, -3351785, -14081265}}, + {{9494470, -22287009, -16712259, 28478462, -37773704, -14779305, -16205871, 22921864, 24377294, 14569588}, {-22203858, 3292119, -28484341, -1204402, -25954842, -14338483, -26518921, 8973086, 23667804, -12320432}, {-23941480, 11267256, -7644860, 632755, -6937570, 10295099, -24515263, -12663303, 9447263, 4961601}}, + {{34074416, -12441443, 38319594, -5871650, 8169086, -16138764, -19288698, 9660786, -3136994, 1547067}, {-23372406, -8293177, 25635912, -11062256, -36804170, 4734560, -13498420, 16285644, -480032, 23593399}, {-25746855, 2587547, 23911025, -14346287, -6941211, -15706289, -12706124, 1198596, -15390273, -7900426}}, + {{-7398424, 3142689, 6236726, 19442358, -44839758, 22168913, 16575104, -21333845, 14955261, -7555418}, {-23408832, -18436287, 12792808, -13392254, 20435778, 3155259, -22477364, -1959705, -35280187, 3465296}, {1996299, 2009172, 14565758, 696622, 2249076, 2795060, 23765683, 14231066, 16843298, -3201933}}, + {{12517148, 2287125, 4019448, 251157, 25236885, 26586196, 22961137, 718639, -582588, 2265158}, {-5576116, 10007877, -2944188, -5960161, 14164159, -3845760, -30841917, -22076311, -106000, 6564564}, {26669805, -12541152, -3624879, 5120978, -17172980, -204965, -27288057, -12136365, 7621505, 7173844}}, + {{57209026, 15513145, 45703935, -3162825, 37406001, 3236942, -33788732, 20283729, 13807754, -4389031}, {5575802, -9126945, -18116241, 145459, 16114841, -28337650, 18192264, 10717423, -51631662, -1930275}, {12584317, -2295278, -11269350, 7421592, -9640278, 7435192, -7066145, 15599928, -28484532, -3282382}}, + {{47342509, 19856909, 31371440, -3945729, 62974096, 341200, 47491687, -15411774, 16189419, 1211487}, {11395021, -4007771, -28185832, -21541697, 2385406, 29678930, 15977397, -15178308, 41897595, -5069595}, {-19095124, 2768029, -30762992, 14184730, 4233096, -3769464, -25037804, 14705020, 3123388, 14530603}} + }, + { + {{-18525889, 17138373, 29042158, 14137769, -17372829, 8654497, 52390884, -10433960, -8524586, -27839513}, {-48485845, -6370071, -499592, -8462583, -20009811, -4454575, -1825914, -2193120, 26866342, -4141309}, {9722368, -7121433, 31113300, -10284803, -28346927, -8148277, 28156781, 7580576, -7239971, 8622867}}, + {{-37796726, -5204955, 21783385, 21641843, -109558, -27410069, -23732531, -11221930, -9989085, -11735135}, {-10819190, -14862615, 44752859, -3411779, 26968106, -5634653, -6702499, 664572, -16397797, -12579957}, {24917068, -7486329, -32783494, 388898, -1012434, -12839893, 6079384, -8542826, -12345333, 7946207}}, + {{-21647665, 23918503, -21508182, 8414467, 60647236, 792838, -31138855, 11016774, 30310668, 19414142}, {38099859, 9578003, 12500248, -14104581, 678886, -27321002, 25065611, -16505548, -2524442, 12319632}, {30086556, 830841, -3358317, 5150139, 32597201, -489067, 19457685, 2719442, -18387484, -6667758}}, + {{56130959, 14898690, -3884690, -23629271, -33522977, 11207766, -22627471, -17254133, 5539868, 29474487}, {-2134591, 1523912, -3554418, -2470559, -25991329, 3404402, -40720875, 4981355, -26095872, 164157}, {-16900663, 12194516, -5332114, 10032737, -5429007, 5684677, -20476671, -5058578, -22125616, -14310862}}, + {{-1783533, 20400492, -41881650, 24761328, -29290244, 7662499, 45790533, -14338779, 17617045, 9779659}, {-50286451, -12611450, 4495760, -7731898, -2047468, -13955469, 3663473, 4510295, 17451555, 16334987}, {-8124186, -3801254, 32046426, 14151697, -5576546, 109242, 28637198, -8022098, -25183720, 13356933}}, + {{-4034800, 21558875, 22914988, 11119515, -24683763, -2007230, -17896643, -6273340, 12994036, 2473578}, {-32758292, -11274547, -5844754, 10869667, 12221695, -21759088, -46953217, -25055634, -19125682, -29674312}, {5071020, 3877017, -8645050, -9596892, 17263025, -7197522, -28704943, 13832685, -8783218, 6413660}}, + {{14144390, 19181808, -25704298, 26818159, 28848665, 9345515, 23970260, 7911173, -11353037, -1819621}, {22822046, 12307254, 32047164, 4696707, 32187419, -8583427, -3915416, 9062451, -35815657, 10093493}, {28464880, 15785048, 17661023, -4005670, -25551887, 984698, -12251310, 3503149, 33055808, 8060338}}, + {{-33743123, -2916767, -4379, -2587098, -9879202, 1022641, 10599020, -13383434, 31845933, -1837512}, {-6930475, -29735353, -36952499, 25194324, 3669988, -9961461, -7151658, -14326802, 16528629, 7236584}, {15103232, -2015950, 31257417, 14072555, 32869846, 12299958, -18292988, 1026559, 8551780, 1635000}} + }, + { + {{-31662976, 8958841, -14654458, -4179414, -41574230, -17679439, -18937210, -9610204, 8647177, 22011503}, {8885704, -5344821, -22485940, -11968268, -23079344, -3704621, 27181962, 1086904, 24405269, -4137449}, {15891365, 7452623, 10460008, -14008611, -266460, 1031555, -4620742, 13018479, -29201294, 13834416}}, + {{34471598, 15278043, 43919973, 22012852, 44816636, -17757645, 29986028, -8440898, 28581512, -9359487}, {22656740, -13792385, 8041091, -9350418, 12598278, -14896685, 24204856, 21347788, 24714666, 8519359}, {-9501718, -14336701, -22953382, 4400117, -32090846, -6362084, 7552182, 2235220, 2612341, -1820301}}, + {{-28775543, -4358039, 26807764, 14705257, -43000127, 13329433, -14303645, -6766772, -18470575, 18625427}, {-18036555, -348937, 35310924, 8459859, 6029535, 17259535, 47823333, -18629930, -2830345, -9364869}, {-30456145, 9479301, 16063119, -3370909, -29004960, 2016638, -11533095, 5777110, 24940508, 15280863}}, + {{17557595, 16083579, 38585583, 6793806, -16690589, -18051590, 882379, 11436116, -11309232, -9679360}, {22166143, -1178217, 330723, -20645864, 10976369, 10372194, -17151687, -20427418, -27861530, -16817682}, {13508061, -3174824, -465059, -14284813, 26466556, -8807977, 24491526, -11922839, -1405911, -4327734}}, + {{10139163, -1900884, -58914887, 17907544, 6518674, -4644578, 12948627, -31837537, 27319758, 4062509}, {55457011, 9349254, -5426693, 8587368, -11558266, 50292, 4305177, 139543, 26008046, -10992799}, {18958788, 14819383, 30575075, -11168986, 19810082, 1314669, -31027712, -6897778, 17679746, -12225249}}, + {{20904177, -22631243, 34134169, 24044631, 21939305, 10340658, -20372174, -2602514, -14710351, -5004948}, {-44045525, -4481633, 12289611, -8760145, 17164799, 5452614, -25951722, -10567854, -12082659, -2748718}, {-2560181, -634447, -13608293, -31388, -31725070, -11295361, -9247745, 11888155, -7337341, 11831017}}, + {{10846006, -18090141, -38379545, -7386916, 19596799, 6029769, -4847312, 6770113, -24390465, 4341473}, {-27678342, 11755, 20278643, 20214922, 5822615, 17803117, -47977414, 6644473, 37867431, -15775441}, {-25880155, 13349044, -11867884, -12824451, 3220859, 3596583, 8678256, 11812352, 26829290, 8220258}}, + {{-4340162, 9536647, -21668847, 7979419, 294226, -5459876, -31663424, 289354, 15833344, -11719981}, {-52759734, -21859245, 35454203, 11753087, -3256380, -24551532, 21661116, 14282500, -39409088, 12242465}, {4494438, -9546037, -31946858, -13353048, 8384942, 6460545, -28378633, -10482028, 31520164, -16283970}} + }, + { + {{1823626, 164039, 6461336, 7798609, -31273028, 13541331, 6207654, 2325763, 27140802, 12383711}, {-3433076, 15948061, 53497752, 25704201, -32864044, 15711411, 24952554, 28036443, -22568840, 16780115}, {7184659, -6564327, -6516411, 10789908, 21629741, 6009096, -8582179, 15524312, 7161881, 10617461}}, + {{-19502308, 4005235, -28153157, 9404004, -22140058, 2561562, -8534572, -16868024, -2188013, -26341007}, {-22696148, -27364095, -34314189, 213302, 13489404, 1233746, -36406152, -1494354, -11798213, 5207823}, {10323777, -3403827, -19007544, 1513525, -25811617, 10650396, -21173598, 14688881, -21549067, 16012913}}, + {{-7849997, -3366236, 15310319, -15467523, -19141525, 1007081, 2087036, -18421124, 24050989, 4131757}, {-45336901, -27615724, -7398301, 12294815, -41100077, -27611265, -24797666, 6379018, -37086247, -26999935}, {-17750002, 13613060, -303811, 16168062, -4262376, -11068231, -22720502, -1951968, -16556703, 13583126}}, + {{18977855, 21759944, 12487308, 4100649, -13508850, -28364085, -7367638, 563382, 19742486, -22962575}, {42314517, -7937334, 44436998, -14352745, 51513304, 411635, 7127746, 22808726, 3689770, -3232419}, {7548212, -15674536, -2333, 15170591, 24564996, 4235775, 14899168, -8303579, -6717422, -13727730}}, + {{28113017, 479317, 4022895, -15473220, -2559427, 6950201, 52750440, 13519017, 17913462, -10143116}, {18220929, -18962957, -5140271, -6298306, -16543649, -7602787, 3539696, 2138217, -22059040, -1624534}, {-26189272, -14347880, 8062736, -11695287, 1388463, 3799049, 12425595, 12539193, -11388745, 11608334}}, + {{-41286948, 4869802, -39742514, 23662890, 4062368, -3738095, 2846143, 2153062, 10111519, -1799906}, {-25438954, -22814338, 5396684, 7621518, 53849136, -23716835, 8822111, 26421232, -47364075, -9801690}, {32789462, -11214154, 10420674, -3654170, -25703630, -16154276, -10601462, 10408728, 8736892, -13060362}}, + {{22634572, -3107544, 9830354, -8547906, -6162562, 27363909, -28750596, 5920635, 6567069, -25142374}, {-4839114, -2466208, -12650650, 8077202, 3556502, -4239449, -12150974, 23786971, -37764563, 2459454}, {10144581, 5240153, -14451382, 5965429, 11618438, 841827, 15281025, -1348268, -31508007, -7995501}}, + {{24758741, 16354783, -7366128, -13977677, -6445335, -2694037, 254410, -12497025, 23561941, 10993724}, {-12995879, 9724549, 23918628, 12056021, -44750009, -14132229, 24725978, -19259725, 40201583, -20874418}, {-13201520, 4302453, -15939827, 11311839, 33154413, -15348448, 18697942, 891386, -26950337, 6785366}} + }, + { + {{-11424236, -6308055, -2275825, -7778527, -3527645, 16629222, 26709899, 331681, -16208657, -24883803}, {-6254122, -9612153, -32896023, -17385797, 16373931, -4765142, 19791235, -2187747, 38237465, 620345}, {25059852, -3850968, -23204090, 9059955, 28643675, -6569464, 9635436, -15128183, -11160954, 3833112}}, + {{-38003765, 6153252, -2842076, -9731111, 4421241, -12184984, -37757271, 14429182, 20386613, 2049315}, {9469019, 10706068, -2113554, -12475299, 53586019, -474094, -10157103, -13966460, -30540057, -11472015}, {2455870, -4742727, 31902303, -4627546, -3277979, 8688119, -5883910, 16714116, -88784, -4308453}}, + {{-24239643, -12299051, -38353083, 5411710, -12876002, -4391588, -19321210, 949852, 38956437, -7354473}, {-14624107, 21205915, 4382713, -8746628, -8631424, -2062476, 1479778, -23225268, 6459693, -18321013}, {12521862, 2066705, 25392497, -13277316, 32548320, -2441127, 28468780, 10330770, -15270601, -7288882}}, + {{-35199004, 7886915, 31121378, 20825492, 31522816, -7723892, -1023394, 7264499, 22636567, 9524415}, {23905240, 14503887, -21443014, -5863770, 14920894, -17871760, 8180294, -17509853, 14188797, 4486217}, {10756438, -3911038, 5537383, 8842117, -20625762, -8763378, 10005140, 5719136, 2810700, 13392372}}, + {{-27941545, 27103969, 41576616, 23137423, -27766909, -24058602, 18990635, -4882828, -10791117, 1418526}, {-27948077, 2508871, 18632218, 10190327, 31271101, 7920476, 19303613, -4164096, -50561487, 6334902}, {-19248518, -14164021, 11281311, -12934077, -2937595, 9619497, 25103629, 13683159, -29223005, 16754133}}, + {{61250094, 5666997, -17554994, -9723180, 1792060, 23128892, -17863111, -9503155, -11440099, 8349519}, {1630604, -11699473, 7074740, -20998654, -61647292, -8501842, -7922013, 86401, -3454875, -5978241}, {-32533060, 2643395, -24933394, -5446718, 4658778, 9736946, -22895558, 13076296, -32217997, 3850312}}, + {{-40793207, 23131557, -58643230, 1453850, 18456888, -11681071, -11357218, 5934760, -15411101, -16603265}, {14291997, 10028183, -3522076, -19146146, -31657422, -11191445, 10113996, -13682306, -933881, 14158979}, {-20971877, -6015806, 32628147, 15387987, 24888678, 461773, -26446677, -3509034, 7501495, -15319879}}, + {{-10368704, 21074423, 62643283, 13992099, 56467685, 18782384, 12166517, 7409948, 40907504, -21429229}, {-45845424, 535989, -2371303, 19222689, 3245523, 11996814, -30575555, 12398712, -23739320, -4776379}, {2387154, -10664708, -15449141, 11069350, 20161808, -4565500, -19956162, -7030308, 25812806, -8047788}} + }, + { + {{-11393788, -31195641, 5914009, -8226580, -24992165, -13603463, -8419497, 9196904, 9942709, 17023821}, {380918, 2093827, -42908935, -13269472, -28502501, 13869739, -45706159, 18355538, 46404415, 6844933}, {-15657003, -2082160, -19313214, 10506720, 30813871, -3008467, 4864735, 10542907, 5146482, -16066099}}, + {{-26012206, 2440624, 34968934, 1674080, -12124996, 12254092, -35618687, 12993229, 52734543, -8754976}, {8363658, -22650692, 10471620, -19946100, 45702754, 6267052, 2816295, -2346457, 1012695, -21718010}, {4722214, 11565915, -29222713, -7632932, 14690342, -9309653, 9473536, 2287339, 5535428, 6082468}}, + {{37715665, -12032259, 17427076, -20118777, 619081, 1153738, 13837579, -9801709, -19023845, -1509944}, {25606015, 11917187, -31135502, -11291017, 50905807, -3420204, 49630657, 19991205, 38594971, -7151340}, {14797569, 7275261, -17622375, -12677304, 15863283, -4386891, -6821285, 1047435, 29221350, -12442876}}, + {{18223382, -5557019, -13941971, -270107, -6276162, -2649297, -25516399, -30398943, -30376112, 1934432}, {-24481222, 18332455, 42074839, 31113399, -50585006, 21419319, 31751971, 1604499, -31432334, 4012114}, {-5614394, 16118667, 17842984, 10154293, 7203392, -11760100, 12786533, 13539782, -11699136, 8069706}}, + {{-52415221, 11390392, 10634948, 5760017, 17503383, -19305298, 400282, 6562410, -45578538, 7471700}, {3785437, 9616354, 35505798, 5251077, -25848885, -8841316, 3089148, -18514060, 20029008, -18435942}, {837545, 6435504, 14517599, -2990881, 23535142, 10294946, -17303464, 1348860, -7846038, 12477368}}, + {{34024961, -19636451, -49400571, -440123, -13551236, -11721832, -24006897, -3642120, 6614492, 6991166}, {22424621, 13818795, 14059635, -19211115, -51683566, -11787346, 41264997, -16154432, 38529916, -8673210}, {-29242768, -7080381, 767860, -15762290, -13884415, -14008837, -8360107, 7262483, 29698713, 951923}}, + {{3993534, 11930001, 8116396, -13312413, -58362634, -23134275, 39248444, -1158132, -5010070, -9536476}, {46775790, -4717339, 8506206, 10843861, -4752500, -4112565, 7970818, -28209784, 1674628, 18226918}, {15014429, 7514026, 19143248, 3136851, 32633519, -3951912, 20990367, -1419185, 21553726, 12441390}}, + {{10478111, -23383406, -18952330, -167817, -19095938, -9134562, -30597693, -1530271, 7044267, 2592452}, {7133155, 5347562, -39013062, -18434567, -526094, 7129772, -575345, 5362853, 41758291, 2140598}, {-2947421, 15525486, -23996411, 6039451, 18811643, 13891367, 21702656, -11044360, 26127980, -13714955}} + }, + { + {{-2512461, -1372206, -35467931, -176266, 18461162, -1792418, 1287107, 8100825, -52504725, 24588235}, {-40949821, -1132156, 18799869, -1764834, -36085632, 610810, 2580243, -6649053, -12205113, 1062337}, {-22421880, 16776151, -26039760, -2906207, 11402611, -7283455, -29204913, 13188295, -1116466, -6742792}}, + {{-32390999, -14812052, 30933349, -7137404, -12995009, -10371462, -7075396, -17579330, -7884075, -9885737}, {23979633, 2778906, 20243223, -25070876, -11426251, 2381934, 20057128, 8148502, -49449311, 2906429}, {12643697, 12434471, -14574200, -14016002, -31206316, -13553402, 14367322, -4716995, -10905587, 1670326}}, + {{19026480, 23287111, 6272697, 27663013, 29247445, 7383421, 15703093, 4310091, -343132, -25508622}, {37550200, -6934929, 27827057, -4610215, -2745461, 17000769, -33562771, -2487325, -59541030, -2971006}, {17444074, -2714269, -30164474, 11479010, 17083699, -7174135, 15211210, 3716649, 1375112, -12633664}}, + {{-29695567, -19798119, 48199665, 6314768, -24908887, -16878777, -22312220, 21381561, -62609455, -4465042}, {18520321, -3430727, 7899957, 12334232, 10352651, -4728781, 36879380, 7591311, -1851449, -24330098}, {-9441852, 6514454, -2730097, 12017911, 23787864, -4685660, 27118696, 3902741, 32393460, -913193}}, + {{-680569, 27368161, 19897314, -4427070, 51833741, -5565835, -6494526, -14596372, -5717784, -5606705}, {-57689313, -129247, -28727214, -20715426, 10427619, -26237139, 59927698, 7945678, 19482960, -14914347}, {7639586, -10357575, 26177609, 13768483, 13693595, -9188690, -3274292, -6963965, -21719587, -7131527}}, + {{37990613, -4665460, -37182009, 7688230, -30857295, 16532957, 2229769, 8152048, 33472640, 22003191}, {15092871, -5593572, -26526525, -17792398, -26526325, -7720867, -49984255, 3017412, 30171526, 2377085}, {-3854974, -6002816, -14612785, -1109631, -11345964, 5854705, 26977843, -4913550, -28719386, -4944419}}, + {{26782420, -16703981, -32417800, 4779205, 35800529, -4923134, -22539402, -10875321, 5783305, -17221701}, {-19579296, 4797349, -33050308, 10979287, -5806745, 27289964, -8032346, 7722629, -33960437, 11392773}, {-28495461, -3191753, 30384833, 12690226, -32809025, -13118074, 20050301, -4432640, 23462068, -10746844}}, + {{-6192253, -3176327, 13759314, -11547622, 42355806, 5203471, 16835539, -18940708, -50799058, -19138803}, {21848409, -28044655, -11132206, 3173030, -23106916, 6377869, 13394871, 11254226, 13056196, 13282063}, {10903815, -318931, 20023736, -3062161, -33043718, -10483177, 13980354, 5850500, -3787447, 8279326}} + }, + { + {{-15332054, -3128134, 4217626, -23920213, -12813941, -8669465, 34295434, -4767981, -1921001, -12110719}, {-14316922, -7762186, -347748, -8317589, 30561813, -24326271, 7885374, -13156847, 42586295, -11598391}, {-5986075, 5716527, -21449148, 15827466, 10298570, 4796847, 26143678, -5517979, 26117337, 3215551}}, + {{-450797, -3960386, 4350998, 7511133, -19503884, 16372261, -24072091, 17323231, 252397, 24141690}, {29606469, -13112434, -30673940, 13445053, 10527018, -15896619, 2043099, -16095025, 2317389, -7701232}, {-21724989, -6843647, 5520708, -2804427, 30302861, 14193429, 31996951, -10764110, 18800609, -8435028}}, + {{-16092415, 4125816, -25947826, -5090834, 57798801, -15761098, -49435062, 22712141, 7198617, -8184157}, {7046437, 13066462, 19988158, 1668368, -5624737, -10781580, -6252040, -1293161, -36939853, -24156343}, {-15912134, 15554644, 20529504, -1964149, 25218951, -12492275, -2931377, 6809197, 32591275, 8141438}}, + {{43901294, 18638240, -17033266, -5068779, -27799472, -22140071, 44302090, 12820344, -10004646, 4899896}, {-19736902, 5738452, -9419198, -3263459, 17455508, -9670269, 18578554, 13440702, -54950948, -19629796}, {12087288, 9590630, -21952880, 14511399, 7160045, -8366025, -4259298, 15490224, -8111985, -14586351}}, + {{-7729310, -7411401, -18536796, -19063948, -50090493, -27466784, -12601316, -3337327, -32338683, -19832706}, {-55484508, -15637761, 28701456, -291864, 4782889, -549112, 54204536, 17511485, 14841627, 11131542}, {3482227, -4765013, 2128235, -5818091, 990479, 5647839, 1811126, -10065411, -10477514, -12719470}}, + {{-43296735, 22624866, -21885794, 13983934, -7585917, 979767, -31729817, 3092820, -11192523, 13045424}, {21936353, 3859126, 8674162, 14119524, -26036453, 3747117, -8540865, -92476, -7831533, 6148760}, {-28595098, -12010122, 9629784, 46145, 18039016, -6847849, -20262167, 11672034, 21004208, 10422611}}, + {{-42896688, -1926529, 48588324, -1156191, 38199580, -4254732, -45800601, -16745548, 5000677, -5591791}, {-4192014, 25615407, 10866648, -13427877, -24451378, -25657316, 2614871, 14762132, -48515979, -16992495}, {-7230360, 12536213, 3274484, 14850230, -28111654, -3879449, -14085489, 9446178, 3570569, 10000749}}, + {{26045226, 4594337, -40303866, 14329443, -39514437, -2022349, 33837398, 10307831, 4354304, 8921946}, {-7224138, 1431025, -13384774, 12191821, 11379371, 23560909, -27871846, -6722167, 17300704, 11717938}, {-19215969, 6010490, -31869912, 2483556, 6213569, -713937, 22848401, -11424117, -20172080, -11678587}} + }, + { + {{6607421, 12480494, 25428027, -18102165, -160701, -23724349, -5141897, -8553616, 28810543, 6922662}, {-39677521, 14421070, -18906753, 7702897, 5044227, 378013, 14146435, 9493068, -32891707, 10816192}, {-22673527, 10415048, -810235, 13256181, -3056072, 15894912, 12832664, -13856055, -22736135, -7124374}}, + {{24775529, 15012151, 15040989, 10514838, -20190653, 15618124, 21288611, -218153, -27800043, -26742}, {31379615, 5911423, -21178843, 20633530, -2440443, 10677890, 30938733, 25469277, 8553689, 9418830}, {-2752675, 9858208, 14285659, -10165248, 16638743, -9280038, 21498686, -7213728, 13108400, -5038892}}, + {{-9449484, -19316521, 4072499, 14995111, -9380605, 590509, 45719950, 14060381, -20627956, 6405383}, {-50875938, -8132887, -5088825, -1533161, -9897577, -15743051, -12171054, 11107961, 9598642, -12786005}, {24540837, -8914962, 13445348, -2226882, -12722019, 12245570, 3464372, 6923363, 23802564, -3354405}}, + {{12719393, 6186229, 3205364, -5309560, -18616217, -24988006, -4902262, 7772882, 1582263, 6479024}, {50382271, 8205633, -18040270, 5921760, 44849781, 4236674, 9646882, -17787846, -60502809, -25274328}, {-21870160, -8943416, -18857714, -13669387, 6581785, -8690535, 4610705, 7483982, 12708371, 5866112}}, + {{-3006154, -7557724, -22169959, -6284017, -10118629, 23728740, -12691610, 10394222, 691290, 13884352}, {10308096, -3147832, 1635715, 24866371, 32799905, 9767350, 43350518, 11620206, 61080638, -5279360}, {20773313, 6997282, -3809124, 12542279, 24703297, -8295618, 22040350, -6130895, -31020058, -8415480}}, + {{-26518614, -2719445, -22713946, -15613749, -27498654, -1251922, -52784874, 26006039, -1810392, -5264225}, {19526420, 9832513, 34645312, 10566587, -23229568, -24851960, 601760, -788989, -28878666, -17591219}, {-11194361, 9496633, 11574094, -15967320, 31868038, -2017814, -28314077, -5028405, 786536, -15233245}}, + {{21423278, 16274071, 7729969, 3728528, -49745765, -2189717, -9661071, -20965510, 27573690, -20056221}, {-39581388, -9448779, 45916493, -4188474, -7221443, 10078893, 40914437, -12218440, 31393268, 11136943}, {-19025067, -8937790, -1863238, -14696416, 13564285, -5096605, 29657450, 7256514, -16798239, -16552850}}, + {{-19847897, -5594469, 39344403, -4683436, -22625766, 23550447, -17378786, -334265, 37033298, -8633938}, {37873295, 21733533, -18576983, -24263718, 11311508, -2510227, -25489582, -11099607, -20215982, -23396432}, {31638938, 11266002, -14017046, 6454660, -3708082, 13857499, -29674180, 11217059, -9944124, 2404134}} + }, + { + {{-261678, -7849141, -34843012, -18330714, 12823110, -5409085, -637386, -3306802, -46619295, -3929080}, {-27165578, -24071059, 15212854, -8076208, -32981854, 4584589, 35033258, -27183974, 16211721, 14098878}, {-19944482, 9217160, 29166980, 10599437, 17168629, -9153918, 30127943, -5149380, 7115294, -15721402}}, + {{28718822, -14728241, 10922201, 5552845, -16998365, -8637291, -20572626, -23695944, 31266022, -15838481}, {19356870, 18101731, -22279113, 23485403, 34937339, -12195567, 18925240, -2534584, 24353654, 3022973}, {-8493708, -7900692, -31911097, 13374247, -31325809, -11138877, -29965332, 679570, -186672, 6927918}}, + {{-19371557, 6365963, -23021669, -12092535, -32190310, 23811729, -35212946, -6690732, -4425401, 1709924}, {-6912921, -23684853, 33021145, -9381373, 16503662, -6786035, 20300954, -2943916, 34176675, -14086980}, {-6568424, 13771726, 21857256, -14647726, 2979870, -507464, -4144029, 10367676, -9694929, 15963105}}, + {{-6504962, 3895999, 15330575, 6085731, -23338413, 7287105, 13358854, -21092609, 16274219, 17893318}, {-55096654, -28630821, -27498625, 10064439, -17110189, -5629883, 18381524, 12443615, -25787413, -5389020}, {-13562914, 125101, 10069578, -3267751, 15126173, 11128659, 28860725, -2220394, 31209598, 4741592}}, + {{-4171361, -16887831, -6824220, -3692201, -8714977, -3089811, 23584908, 8179016, 348585, 14700807}, {60333581, -4479775, 2964970, -22014545, -13655147, -8932453, 31945652, 19344532, 8315339, 9725067}, {-29492579, -11988190, 29868297, 15668335, 19515758, 5208175, 18570645, -12453448, -22651150, 12257559}}, + {{9297415, 1201627, 33167590, -396664, -35635797, 886522, 32001557, 6690554, -13391828, -7914547}, {-43738093, 30935445, 918928, 22105178, -4858945, 17798468, -11303337, 9751766, 29668922, 15368961}, {6349498, 6435647, -16762609, -871321, 24390394, -11228126, -27382581, 1428982, -29386922, 13093878}}, + {{57975408, -2027510, 45435287, -23089566, -16756208, -9193864, 14612730, -10391203, 12786762, 8187923}, {1469460, -15707970, 5635697, 8770840, -22627256, -11216978, -10949710, -20820501, -13492462, -15746741}, {-6035260, 8267404, 362534, 11537538, -29897307, 1151760, 11763092, -4363531, -13651065, -4561529}}, + {{28689216, 6409485, 12220204, -22516376, 5364707, 15733115, -6501438, -1478390, -23146730, 3734217}, {5664034, 10051653, -43413392, -6735256, -101135, -5681113, 38821030, -14021930, -17485088, 28200305}, {22221784, -15241964, 28292310, 10693661, 9115461, 4679508, 22886641, 10215724, -12891591, -2706350}} + }, + { + {{-11319013, 22092125, 6101371, -23112833, 4724792, -737430, -43154064, 8855918, 2368215, -14753784}, {13052289, -2211683, -17141905, 8918483, -47820468, -1104286, -6861658, -12957206, 46761279, -10669384}, {24527779, 9111443, -10606660, -6994118, 6360508, 8277150, -14301108, -5589450, 7995916, 2601089}}, + {{-20567677, 3869833, 22792031, 3877340, -5358238, -24675582, 2151592, 17806016, 8546022, 9282780}, {-1024971, -17593947, 4033769, 22284144, 52848512, 191028, -26685112, 2325830, 29271732, 269852}, {21914383, -8508981, 1584359, 9381216, 27077910, 9548224, 8083125, 9843874, 32662283, -6224944}}, + {{44977225, -17425911, -35662966, -11955772, -41081617, -5655595, -33889802, -11639581, 20559423, -12699812}, {18635889, 1717141, -743872, -21530196, -12575309, -21227371, -11961210, 7698111, 17344797, 5772870}, {31755093, 12835492, -28111039, -13882334, -6114100, 7804109, 27718359, -9748879, 26302609, 15894773}}, + {{-10479308, -30736552, 15655479, 18560091, -45784687, -1208851, -7464237, -5347583, 37602567, 3188747}, {-50795294, -362692, -25025471, 12626779, -9787325, 6479703, -42673855, 25275063, -21968891, -15939305}, {-14237323, -7667471, -2394791, 7563450, -28011184, 3757401, -13138955, -338927, -12550810, -4705688}}, + {{-997731, -11244355, 28307844, 31003171, -52648343, 13823368, -25119261, 195539, -22291166, -16449592}, {-54287065, -14202267, -4225368, -1386245, 7078343, -16715166, -25188893, -30908833, 8142782, 8193182}, {-31812856, -14454650, 21973231, -15942473, 13881138, -10421780, 29865093, 257485, 19188036, -2355462}}, + {{36607347, 2562141, -4061810, -8323178, 26030653, 19069729, -19911809, -973682, 28123549, 13069082}, {-29679391, 21962881, 33828672, 3669408, 32342651, -3428973, -38829285, 31897352, -9786281, 334240}, {-18958476, -9448616, 22047089, 14137801, 29557406, 13622841, 19309512, 1213569, -6970559, -14022250}}, + {{2567752, 30051368, -7869717, -30839292, -3346152, 14373100, -16374082, -8772262, 2390004, 10489445}, {-8168154, -940848, -56942419, 1855388, -10634282, -10061176, 50527334, -14943440, -42675052, 4945351}, {-2161578, -2129839, -24322080, 5238648, -1913956, -15052225, 13192063, 4524122, 27281408, -2567409}}, + {{5316974, -1652106, 23421334, 14286024, 5169539, -10278519, 7299556, -4916105, -11399259, -7995221}, {-56120566, -16699148, 35877614, 352134, 23842397, -18517099, -36670982, -16201841, 40381317, -14975627}, {20358374, -16032261, 21372886, 2229448, -12128163, 8384962, -20268879, 13945650, -11738322, -6352788}} + }, + { + {{48633486, -10216478, 12261071, 8645742, 7209828, 1201092, 19902952, 5679173, -12787484, 29787725}, {4237894, -8186226, -9620455, 10857166, 11357206, -21380442, -29207530, -5718719, -53691854, -3077103}, {-27312813, 15365228, -24022056, -4062791, -31056990, -1167716, 23863648, -4168917, 21152744, -7692607}}, + {{-4692465, -8612662, 25089518, -13362237, 17071702, 18545769, 3946832, -6215074, -23802544, -10377682}, {-23139891, -9823966, -4436690, 4520993, -42243454, -14678911, -14115386, -10878842, -35023202, 6505784}, {-7326378, -4764331, -16791732, 4328265, -24065452, -5898905, -15420255, 8536200, 739691, 13784933}}, + {{-45913725, 16629500, 13265621, -14270983, -4850195, 10441223, -21880345, 674614, 8141975, 21140875}, {-5917149, 6961978, 21961727, 7049701, -23105367, -10984291, 13950487, 7986758, 9038183, -12224179}, {11607489, -275019, 8794399, 1368189, 30180196, 11088225, 11603248, 211230, -26074831, -6437645}}, + {{-14554577, 9179014, 52781341, 376983, 1996737, 7973725, 3224830, 16479358, -58755195, 21010121}, {34578699, -7266060, 9081145, -12880641, -54401093, -25306157, -41468422, -15033426, 4654677, 10635069}, {-5205201, 7920985, 18658730, 9487273, 9049638, -11418646, 1721950, -8843881, 10455628, 12638026}}, + {{-31095281, -3649727, -10281050, -2192978, -46553189, 7366778, -21105682, 6603721, 4013012, -9486255}, {21994247, 22093215, 28324720, -20018730, 14962185, -25397368, 20088288, -1155741, -21152232, -9486345}, {29734196, 6899570, 22755892, 7095432, 29404584, -9982700, 6976163, -5933582, -8292488, -3951721}}, + {{-2823903, -10004932, -41642800, 17529940, -48438413, 16426593, -38347076, -10754706, 18529362, 1960110}, {-38993205, 23080306, 7715564, -5727918, 8703491, 13721445, -16103650, -4601126, -3222526, -10841104}, {22977101, -12797824, 18541274, -11855741, 4488929, 6624312, 15196080, 3421855, -15121122, -11941867}}, + {{-12279917, -11378351, -39458155, 10295352, -2381383, 1218040, 4250328, 1515750, -18043501, -8782361}, {8204255, -48669, -18012017, 3366462, -40211283, -12108228, 38487690, -24158700, 9375025, 20073937}, {-33211899, 878451, -13779691, 158784, 28571850, 3247815, -13420149, -9882438, 19630879, -9578616}}, + {{-1524162, 19359075, -54952182, 19936457, 29370414, -23041747, 18452380, -1682646, -45403846, -2872255}, {46482800, -9213111, -11326644, -10537127, 17886942, 3312703, 36280558, 31723292, 8754472, -10822831}, {29788745, -9578704, -32124397, -5237515, 13098731, 15495801, 9656793, 4992360, -31738654, -9173569}} + }, + { + {{-16278546, 7545261, -24908860, 10758830, 22765661, 8474008, 29761503, 8003328, -1616915, -18908405}, {17257026, -19687865, -10758910, -20875664, -19406683, 1562912, 7243455, 20839660, 5630677, -10593529}, {-17155060, -3795378, -12076573, -2699534, -31665702, -9435070, 4160877, 1277205, -11721623, 14441223}}, + {{-31270598, -12678036, 29863664, 6036798, 2800311, -8142142, -26282720, -9547816, 14026837, 15100824}, {-22366596, -1211390, -59216, -24784520, -28178807, 18056568, -817118, 12533760, 33355343, 7518302}, {-30983313, 6066747, 31034036, 15849538, -28343758, -9704223, -32559485, -3633862, 25842669, 9690479}}, + {{-8429032, 11392209, -1185641, -1949265, -9976804, 14945095, 41691304, -12416661, -33983295, -1832878}, {40970370, -18174883, -4320197, -24727969, -8030934, -17322773, -19795048, -9287653, 1741393, 21504952}, {-2612267, -14084516, 23371323, 14909696, -9777105, 8575292, -24712515, -1407767, 26673843, 13318593}}, + {{11258435, -3335510, -9378347, 9080874, -48037378, 1818100, -4673614, 13124593, -13445986, -19457862}, {-33282745, 23090950, 3670039, 15362154, 7785536, 5758718, 19067094, -8232413, 31123236, -10239406}, {31236959, -15451213, -13569986, 6863849, 1456103, 3255861, -1015217, -7348569, -10529144, -5973171}}, + {{-17355114, 6408303, -31757344, -21037718, -29332963, 265342, -3620892, -13917787, -12986841, 821907}, {-44193642, -4780261, -15560790, -10980740, -5301083, 16943326, 34038688, -18319439, 47714905, 9176477}, {-30408593, -13933451, 12540587, 10205245, -21156684, -2193434, -32644367, -2195594, -33227571, 1348962}}, + {{37300238, 13718999, -5440778, 23211687, -25434566, 16930020, 19002350, -11338408, -17165461, -1066853}, {-11256888, -14158089, 30550652, -496849, -10975066, -11590790, -30284342, -17105514, 36397093, 29841231}, {-3064649, 8804459, -25750541, -12180868, 22773076, -97238, -10307135, -4458757, 32735900, 5532092}}, + {{1532666, -13551228, 17062576, -6914464, -29699, -6163623, -32622423, 27358854, -23035478, -6675198}, {-65356094, 14641824, 39218996, -11105288, -5613813, 25527829, -12582169, 3931336, -42632342, -16488088}, {3310269, -2510089, -31795607, -3903471, 19216137, 9503161, -11692250, -2123365, -30741088, 1641923}}, + {{-10225624, -14754950, -40072478, -16547638, -19110590, -2092035, -21620770, 21427043, 3916097, -9477213}, {1447108, 2926094, -2949786, -4723118, 34413150, -6739645, -24584222, 6767619, 39145241, 10386667}, {-15561955, -16550369, 20291638, 10943916, -23414577, -6185458, 3379566, 16280619, 10525150, -13947491}} + }, + { + {{34658977, -16038847, -12802226, -13014151, 3247514, 4852077, 39865196, 10455200, 30045437, 16991276}, {24311145, -4913651, -45278920, -20411815, -25341898, -23925191, -24739212, 16469980, 16417381, 6451612}, {-16689431, -11998462, -9414744, -7261308, 6616461, -6574033, -16590968, 7616942, 19327058, -6851401}}, + {{-43347425, 11719412, 15552158, -24147106, -20651836, 9836617, 28125896, -28600360, 23325076, 11812607}, {-3508109, -10746900, 20787140, 8538944, 31980116, -17564519, -26852974, 4206554, -37601064, 18724725}, {4577393, -3230998, -154546, 11200325, 16900801, -13303198, 703161, 10326633, -9111559, 12622501}}, + {{-39725809, 13031525, -45619966, -1065900, 12977682, -26984824, 14396739, 23479074, 13854702, -7277246}, {-8666981, -9809045, -5828644, -1589910, -38666562, 2402226, -38187511, -2130616, -20658206, -18926322}, {3021153, 6293510, -12950698, -12635396, 22253895, -2704326, -4346713, -13545669, 16658927, 11656843}}, + {{-59858598, 14117142, -34942776, 13455194, -30347266, 12968167, -349016, -20272076, 1493980, -29128478}, {-311366, -13578650, -3624800, 17993138, 7052438, -14442621, -47595120, 8823830, 26377542, 423482}, {-15043195, 14759856, 12260841, -8268503, 11492641, 1734953, 8133531, -2641481, 19962273, -7414005}}, + {{-7319995, 14066561, 306018, -9411916, -9106104, 28412794, 4492154, 6686869, 2747033, -1712248}, {11409799, 15502609, -51140592, -10331378, -25666946, 4479790, 41995232, 3580355, 33962015, 21352220}, {12328954, 9749794, 28967140, -13246240, -21591005, 16352433, -32813092, -13950724, -2422183, -13272071}}, + {{-8704834, -13611958, -28725837, -5418165, -11662524, 1903780, 21191194, -19423669, 21840672, -4046432}, {33868948, -14602450, 17355767, -17469989, -9306120, 9991434, -36134744, -8906221, -14525880, 15878400}, {-2082348, 4968230, 867409, -14954533, 15018454, 16113129, -7179385, 15112575, 2207326, -2934540}}, + {{-950243, 765343, -17592467, 1469970, 3671602, 25269497, -19548977, 5934984, 27925413, 1252282}, {-24875987, -15215583, 2273293, -28049708, 34702386, -3402235, 45132453, 6703626, 25515525, 19721494}, {16396177, 8613584, -3757212, 2125711, 11975069, 2236439, -14826164, -10807755, 22775664, 6368252}}, + {{37631100, 11452175, 37996574, 28403091, 2042038, -25510785, -2244471, 20395577, -38771575, -21028519}, {-28395458, -15337803, 6533566, -949631, -32782254, -1683835, 12320247, 4327475, -20953713, 5677971}, {13046115, 9330037, -21424794, -1647804, -18873081, -10227439, -32108018, 5191824, -27460387, 4779906}} + }, + { + {{-13132390, 15900078, -35837620, 6138995, -16379525, 11099368, -30563068, -5811453, -22643042, 2789555}, {-17544404, -4350164, 17681678, 5542577, -10792183, -2960672, -22627138, -26233007, -42909694, -15508303}, {-18571556, -1708862, -11142004, 12397824, 16334994, -15561902, 10481689, 2473907, -23820826, -1317082}}, + {{-53900779, -11293054, -18662763, 19090140, -644060, -2518627, 8996174, 10536067, -19839854, -18190256}, {-1981303, -8058462, -22504681, 9193390, 16049798, -24235085, -51867624, -13768197, 29045932, 11552058}, {-17481070, -10146213, -2297259, -3142673, 12810526, -14280422, -4843334, -11927523, 24825679, -5561024}}, + {{15182206, -12852170, 4415707, -4284980, 1820581, 6208857, -22937108, 158677, -2418885, 15496217}, {-10640676, -13722574, -9233807, 1945194, 31321909, -27138585, -19043254, -11468265, 52878507, -15736175}, {-7942886, -14488153, -18458357, 13283736, -30617597, 8540108, 28634387, -16048077, 22446330, -9291456}}, + {{51951741, 1401316, 13819841, -10463224, 56112635, 5549412, 13922999, 7678647, -28351533, 12447598}, {-4586801, -19006962, 34850255, -22402400, 2533259, 20384162, -2311659, 10867869, 5705219, -20858768}, {-31191831, 1392011, -1145725, 13721318, 21857534, -12599402, -6210695, -4231569, -19891740, -7519416}}, + {{2370009, 20559918, 48498973, -4318784, -7398063, -3539373, -37041833, 12935251, -15719038, 607}, {45474899, 2381236, -873295, 17048136, 4009737, -9661675, -29179009, 16938359, -47207048, -14558157}, {-24091442, -10155633, 22844512, 10159654, 14068589, -2959969, 6159407, -5555702, 26419751, 13312649}}, + {{-5729427, 3619546, 26751877, -6582025, -18775514, -15859921, -39862434, -2934988, 4285811, 1198554}, {959289, 28703180, 4690625, -14221985, 40298260, 2933865, 25167294, 3749282, -60098589, -7448486}, {1425431, 11181969, -24988041, -16772793, -30681102, -1633118, -4588255, -490460, -17856864, -13059939}}, + {{12136150, 12152835, -8816684, 1269564, -21628783, -6466972, -17883602, -8157915, 4152133, -32374445}, {12546740, 11779659, 1422338, 20631740, -5537253, -4622706, 4551832, -6940805, 56184709, 904171}, {-28203630, 5856240, 23492855, 7672591, 26254943, 3206013, 24126176, 2480892, 6462164, 773285}}, + {{17058894, 12754689, 13661051, -16724573, -23285751, 12561383, 7477610, -4399654, -29734046, -4657536}, {-18579100, 4740393, 49935491, -14043397, 1785623, 5306303, 17241740, 24210984, 35074424, -14938694}, {26931965, -8440503, 22021231, -3228157, 23192224, -2082498, 31831419, 488532, 11056805, -4935150}} + }, + { + {{45685475, -8915848, 11706361, 26190642, -12915492, -10568751, 11413192, 22516022, 24402910, 19366350}, {-16280547, 14048926, 53355501, 203746, 3536470, 17310775, -25706326, 2965098, -23359130, -7019028}, {5219255, -13887489, 11530381, 8658685, -7970465, 2776178, 11655378, 8517982, 1942227, -2822448}}, + {{23273232, 6228496, 32138310, -3720228, 1034832, 8006940, 5760605, -1219334, 47209076, -1758613}, {28409420, -16146936, -12120684, -4267306, 62110870, 5712626, -23251639, -11075712, 15064378, 1888835}, {22925844, 13439451, 19978779, -11645437, -21236831, 12919717, 21475696, 5255011, -24111181, -1653030}}, + {{13889598, 6667069, 28886474, -8423735, 12627155, -22617676, 47396268, -11411299, 1419336, -6073487}, {-40253212, -12438049, 15138634, 3102653, -7839729, 6284108, 9544580, 13025665, 18218292, -9653413}, {-28548077, 6678572, -18967881, -12810072, -7223432, 14162449, 3655387, -5394146, -21806212, -16053453}}, + {{-20354796, 10453072, -5438313, -3955364, 21297494, -31107146, -8320689, 20633477, -26174801, -9330454}, {-16088198, 2892522, -20320971, -8698070, -29656494, 1606756, 58463095, -97109, 19616555, 18189512}, {27361092, 4322173, 12085912, -11381998, 18190737, 5708430, -26275044, 7165633, -9779984, -7005107}}, + {{21320473, 13996983, -57788174, 16914923, -10635504, 19089852, 7947688, -18038830, 17253651, 7317}, {18393349, 3176647, 769142, -1803903, 40651564, -12410346, -31852970, -8782034, -1992083, 8508993}, {-5374050, -7289834, -7153403, -2693727, 2148712, -13034476, 20610076, 8047910, 17892981, 10999419}}, + {{13571194, -3603298, -8872349, -2734879, -22504925, 11752829, -6842514, -13325989, -1741590, -11986556}, {-44576662, -17187304, -15291721, -8435243, 35874627, 6776207, -2055368, 1286983, 19340064, -18770834}, {-24330704, -8410612, -27321457, -15290306, -8779956, 12445176, 10359557, -1091854, -18442413, -7485155}}, + {{-17386538, 11979807, -46738526, 5048062, -54438144, 4405898, 15653779, -4176485, -19550053, 5427115}, {37242168, -114217, -13721474, 5045494, -11313016, 12872040, 26949855, 28864745, -39675857, 21523831}, {22507400, -8955250, 11955417, 3563585, -22259890, -11000825, 994347, -7600384, -5366041, 7044447}}, + {{-22194577, -27776645, 22482313, 12192501, -8553630, -13035554, 25200811, -15619470, 23778753, 27463106}, {-23566873, 2949467, 20829737, -6857829, -47006730, -3645552, -21517917, 5158284, -20183871, 4528420}, {-22090186, -2938287, -13033320, -16025050, -15959805, 2354862, -26621182, -7756844, -1196188, -11909316}} + }, + { + {{10370741, -5849955, 37123447, 18627351, -38720430, -5467337, -4646845, 282641, -16154810, -16954981}, {-25472479, -17218909, -29684541, 12586127, -18568342, 12085373, -7760527, -21475559, -13608206, 11699731}, {-25850627, 2849911, -22714356, 359324, -21369627, 11760766, 311767, -6363096, -20461078, 8200446}}, + {{51072371, -3885664, 24357186, 11765997, -31518666, -14327232, 26378127, -4529571, 4823539, -400306}, {-13132435, -19524316, -11075498, 15144095, 1386480, 7361216, 30733459, -16314427, 58072575, -26871542}, {-10685263, -12470842, 7658527, -873382, -17370174, -8328204, 24529973, 13255259, -13717250, -1145719}}, + {{-13155673, 15148313, -6237775, -8395215, -1364956, 12324015, 7578661, -7310534, 726779, -3892337}, {40017501, -1615435, -3576083, -12815803, 61932558, -10481385, 24841361, -22656372, -57273247, 135839}, {13130868, 7741076, -8053394, 5139371, 26669021, 10292387, -18188600, -4194478, -16156745, 2276057}}, + {{22695589, -9049988, -11216284, 18617738, -37469072, -4533426, -25210722, -1426655, -34085926, 7157229}, {-43379737, 13335278, -20074050, -12769148, -16636996, 14222596, -26473252, 18660333, -4677240, 24459041}, {3529739, 15115762, 2302159, -3601460, 24599977, 7260078, -23813764, 10706074, 23285160, -12260470}}, + {{1451402, -17978089, 4597652, -15136952, -24951520, 3349082, -31776203, -6166722, 16052817, 15578885}, {51786128, 9316193, 61979592, -10708090, 12271806, 7103764, 18545795, -9993308, -2886143, -6367303}, {13614916, 5454106, 18133988, 13974460, -16811344, 11294589, -18541412, 16215340, -15601800, 16352907}}, + {{6078819, -28262430, 1584794, -913250, -40032119, -11054435, 37478168, -14887045, 9851400, -9124994}, {-29383825, 846616, 19913242, -29348542, -4341087, 9879255, -13017782, 4141027, 56652888, 14154446}, {-21893532, 1751180, -22535928, -16418651, 1364239, 3379320, 31823798, -6441385, -16909191, -9631510}}, + {{-8798801, -17484910, -37085208, -4291375, -36708389, 405485, -3095693, -1897294, -15644675, 13201982}, {32174837, -12212012, 23906956, -9909357, -14878771, 16633681, 60281493, 4276490, -30821537, -2775138}, {-11837084, -5940846, 19286133, 12058815, 1577408, -10828924, 15301192, -16029574, 4699423, 15661197}}, + {{34815454, 28015558, 4984809, 23392680, 33677987, -19483212, -1801982, -21250999, -21444537, 27974827}, {9948478, -1836720, 7042909, -8912112, 17262215, 12098480, 51795848, 2711109, 40943719, -913629}, {-17613939, 8046125, 11877622, 7432861, 18881470, 12440012, 32878290, -16196398, -9439869, -1788868}} + }, + { + {{10205625, 18556565, 30374593, 5360360, -28809914, -6654000, -30267152, 20017871, 23439758, 19154333}, {-37791349, -2410869, -29226287, 23509664, 5889402, -20757308, 21603682, 1275863, -13216756, 7891299}, {29064179, -8479148, 15927568, 7407812, -27474199, 12419690, -19402948, 14555587, -4636876, 12854421}}, + {{35370478, 19649812, -37142240, -1339443, 12003445, -748041, 11921942, -8402832, -20024589, 10466678}, {-26687858, -13698008, 25888790, 28537401, 29009219, 6282429, -19372364, -4701276, 29500147, -21772314}, {-30155490, -1987836, -17629768, -7818777, 1199936, -9380234, 33257641, 6471997, 12280314, 10562436}}, + {{30242126, 3877144, -19160079, 13268125, -33233886, -27732747, 37329373, -1878923, -14981108, -11939081}, {23144988, -19625784, 19046919, -4606943, -19262334, 4435259, -29386565, 8342603, 32304512, 3926419}, {19740826, -14912918, 19841820, -1597371, 4000270, 3389137, 4304790, 8121605, -27599560, -9747665}}, + {{19955356, -11145715, 6723940, -9994548, -26447212, 16548776, 10204833, -13807843, -47500226, 4403134}, {-17432352, -4910523, 57888570, -7417520, 19158016, -8309066, -44266607, -12158363, -19278914, -11716194}, {-25096878, 15458827, -10969951, -146448, 30984047, -5646634, -31063597, -14068899, 31830986, 2482761}}, + {{34818770, 15336838, -10130245, -8925970, -12691036, 384437, 45736985, -155758, -36149061, 14027774}, {-4892, 7226782, -43149099, -8606054, -21859176, 4467743, -4065245, 31114504, -2394543, 6394198}, {-19454401, -8025470, 21005645, 935332, 4917028, 7033446, -4184343, -15083863, -30030715, 15685521}}, + {{37542805, 4271665, 2208642, 1857121, -3016247, -16972309, 57340351, -20309387, -11492591, -10203611}, {5201117, 19372089, -55047518, -17880649, 57292149, 3410863, -2501683, 10098047, 13523057, -19270659}, {-17011846, -7712403, -25913258, -15809123, -1872535, 5810276, 1015925, -5675459, 38638, -3671513}}, + {{3100286, -5837234, -23845272, 10938240, -20489584, 3639910, -9424498, 23060430, 43098682, -13308335}, {55720054, 20836422, -13256474, -6348632, -356440, 13207144, 19597314, -6777198, -19189604, -18200689}, {-364677, 2328345, -27523538, 15770527, -31973053, 8298802, -28499320, -11917079, 14607248, -9578452}}, + {{6756845, -8319734, -48155565, -12599467, 47322238, 3406568, 8817526, -22872889, 37772233, 1975826}, {-48809499, 19934514, 4820385, -6585299, 8591474, 27330954, -20068414, 5423895, -19754061, 3600822}, {-14438400, -8710252, 4397511, 13226636, -7622546, -15749654, 7487783, -6721987, 20749017, 8579430}} + }, + { + {{-13146224, -2954947, -19590290, 20584521, -35459163, 11484969, -17126902, -8893150, -22479218, 11943067}, {-19049940, 11536899, -35323094, 556155, 9444115, 17958867, 30448722, 15374052, 23740496, 21079421}, {-26898625, -6305106, 22653382, 7807030, 10193539, 13674411, -7048774, -7368330, -12087741, -2225551}}, + {{31867921, 10268601, 3589104, -10012663, 26122424, 3477368, 9206722, -4315560, 65626390, 5555194}, {18159207, 8603687, -6754636, -4993133, 10307820, -10460550, -14328676, 1941410, 753672, 6178}, {-30871685, 4971753, 7968986, 6377816, 24590769, -15347388, 4760760, 4938503, 15289388, 15153085}}, + {{-29833047, -22292033, -22437058, 10332517, -34915257, 5021570, 10011688, -7072021, -10336485, 6036439}, {23685721, -3613645, -40659620, -8299579, 23709783, 19982638, -32310986, 17866669, -5732883, 12210417}, {-23995707, -15472489, 7434900, 1921136, 11683526, 9881768, 3316359, -8282501, -3590943, 4763628}}, + {{-17136866, 4730105, 1340099, -6875053, 25920590, -6029800, -7897896, 7581765, -14118149, -614562}, {23844848, -8151697, -31350471, -5342619, -28146318, 6283042, 44335606, -6544861, -11177633, -2446974}, {-3964339, -3839709, -15556623, 9441366, 5019525, -8091531, 28857685, -15031226, 3636920, -13272435}}, + {{-17342167, -1799988, -2170322, 8552679, -10836031, 14275500, -48765297, -13025244, 34151360, -22381535}, {-9949023, 9538602, -15472544, -12370925, -7847713, 2368516, 1638365, -61652, -21123564, 2954541}, {9689996, 15184810, -29305262, 889957, 13792324, -3813673, -23916772, 9116177, 13239538, 14930571}}, + {{31398648, 516541, 53606342, 11861023, 12041363, -569634, 14181954, -13526625, 15261730, -4304743}, {-34431698, -6096219, -1188872, 4402503, -22779147, 24668920, -30651584, -13352147, -49236280, -3434639}, {-15604012, -5264712, -11285439, 11110692, -7419900, -1502294, 27919368, 15210720, 4352870, -8493384}}, + {{7880935, -26390635, 46079526, 2506887, 16984345, -24814996, 5237891, 17822620, 21752103, -26033559}, {-6190515, 5184159, 10181130, 10437621, 49407683, 6511732, -8233135, -12743142, -44107201, -1247359}, {-13491364, -6148630, -3221987, -15566188, 23146895, -11292831, 7819274, 15713104, 23517505, 16674487}}, + {{48428456, 4955956, -33767168, -23340410, -8662788, 12840906, -37340376, -14836638, -37267716, 3915624}, {18525716, 15497702, 4301192, -1953478, 31876770, -1131954, 28521674, 14010098, 4263976, 17623252}, {-26612028, -11434336, 14399011, 7727697, 21012650, 10977323, -22941610, 10192918, -14221003, 12258630}} + }, + { + {{18461603, 19334769, 41626573, 30794010, 2447121, 7050875, -12485913, 7215464, -2638972, 18431314}, {27439569, 14131655, -22466189, -1293104, -15246553, -25865639, 36203059, -10561582, -50671236, -1862930}, {-14225014, 8116107, -28215804, -9115491, 19533420, 4320566, 13478181, -1983082, 30167813, 8615589}}, + {{-6083862, -4200087, -43295848, -13943285, 776816, 3953840, 32847732, 10592737, -28337734, 5966991}, {-5647530, 5367613, 12475298, 15351869, -28056684, -5668070, 17921134, 13162707, 19185340, -22815747}, {-5613802, 13717358, -15598817, 1742192, -23583967, 7643889, -26953420, 15291792, 21698821, 6778229}}, + {{15529409, 17737558, 27589150, -13404401, 13434918, 15953748, -40577857, -18930872, -5940993, 18412185}, {15431317, -5038316, 4006854, -8721341, -24385588, -10054860, 22137441, -9813452, -23546035, 14254115}, {30382387, -3623060, -2962801, 4554754, 20603172, 14059127, -28685202, 9141484, -3849827, 10868327}}, + {{-14830708, 2899979, -32763136, -6755264, -8167621, -2496553, 4331022, 1064783, -7633743, -221036}, {44284226, -7062841, -1487288, 11592510, -56074797, 14818061, 44759376, -31782279, -23596513, -26061520}, {33088530, -10148397, 4662017, -5108256, 18148225, -5541506, -18654764, -5208915, 18019369, 15991016}}, + {{-1429469, -9581126, -302813, 26119688, -34154899, -23074232, -29836717, 31226655, -53723906, 26403907}, {47022657, 11267624, -56447379, -7088792, 32842011, 9713110, 29398155, 254627, 2432470, 4179577}, {-20692569, 9922705, -31906572, -9601808, -28142304, -12921421, -17914161, 1742332, -7859613, -6947127}}, + {{7986855, 17326819, 13578518, -200706, -47207399, -23181541, -43813273, 1845740, 8591475, -18210641}, {14271005, 9048027, 2140550, -27737820, -5252421, -4986805, 8682083, 22215462, -42218895, 8177129}, {12143199, 12169114, 5234082, 3227428, 10994855, 10993953, 11764913, 12616492, 683268, -1156488}}, + {{-28470508, 7642334, -13487543, -738157, -18930221, 30130757, 11554695, -21280161, -36627196, 23134539}, {112890, 9614314, 6856911, -10235405, 7361329, 421635, -11397375, -2121755, -20868284, -5212421}, {-15228284, 8267145, 5669929, 9640028, -917259, -8803923, -10942571, 5131020, 14128410, 7943530}}, + {{4583611, 16716097, -26997228, 8060844, 51908307, -13987189, 14269818, -16808042, 37942216, -2090590}, {-5027987, -9477151, -1394526, 25316732, -4975047, 2999255, 36547122, 4096572, 8115074, 30906874}, {28287543, 14133046, 1613100, -14164584, 23636363, 539921, 31097529, -2227320, 10335728, -10244474}} + }, + { + {{2895439, -30560411, -327139, 9675191, -15017358, 15835757, -1177063, -6745408, -23826127, -2439594}, {-60030525, -1507583, -24361893, 13997631, -1844748, -11342021, -26806363, 12267496, 26693091, -29998374}, {-13944340, 2977451, 19254875, -10656317, 9406954, 7268860, 2284270, 11952343, -9352332, -11814407}}, + {{-13000992, -18686758, 13475406, -20147895, 1593323, 15870377, -43782350, -6279630, 12071815, -21208679}, {49532208, 7264330, 38295652, -10551851, 52877285, 15613029, 9660816, 4307276, 34207995, -6039035}, {-9514134, 13690325, -33095814, -13410082, 25521150, -6940493, -22665108, 3311338, -28943807, -4614883}}, + {{58069710, 18929976, -11973308, 763240, 5244704, 3063245, 2034616, -14476405, 2869202, -14296406}, {3835584, -13870550, -35354044, -783914, -58099088, -22223657, -41269458, -18814237, -59367646, -8517344}, {-12958588, 8917584, -25298683, 15025459, -23309616, -3728746, 25229622, 14317972, 16318660, -4325041}}, + {{-15889803, -4035574, -16079905, -8415284, 29533240, 211888, -18626912, 2055459, 16607394, -27985702}, {40161533, -14516308, -36318099, 17884384, -17840614, -31484142, -25238516, 2119899, -5774124, -210654}, {7068417, -3254611, -27755301, 12521512, -27658780, -14245089, 26875648, -10638219, 13613282, -16016504}}, + {{-53004389, 22383610, -36057796, -12849854, 26615852, -2056503, -17151262, 18045970, 2945620, -3151953}, {7377715, -437098, -3002130, 4635002, 17766494, -27330215, -35491036, -8149012, -48581904, 1638527}, {-32193286, -9978043, -1419468, 1133310, -841762, 12456261, -1343545, 11949008, 21169603, 16313404}}, + {{16844907, 18476701, 13152707, 19998654, -8668918, -2993051, 1784707, -15774798, 11000621, -22750860}, {-10539685, 14655711, -21578269, -10650708, -7852222, -12944943, -16837235, -14380980, -54034761, 10124948}, {24701369, 7895900, -6682712, 2965095, 10724482, 5022449, 3296228, 4274525, 32055641, 13835830}}, + {{27170402, -16235602, 11716741, -10442355, 5352783, -1463503, -31357254, -21231204, 34820749, 4327579}, {-4596320, -264450, 1060311, -7855103, 11255889, 22437779, 22653770, -4793884, -25439297, -25824827}, {5194772, -11483286, -5013654, -8083761, -16992136, -3806751, -10109976, 4246728, 27365334, -286554}}, + {{10659177, -5655881, -6931258, -25775410, -18301523, 12858801, -1270020, -9363199, -31850180, -20743355}, {-54628161, 6255435, 52777798, -5472114, -19377665, -16320325, 20173754, -8442787, 32139964, 10336855}, {23911158, 15020529, -32222967, 812010, 30771383, -15992822, 4804002, 7159864, 23506724, -10668240}} + } + }; + + }; + + //const point_pc_t c_point_H2 {{ 1318371, 14804112, 12545972, -13482561, -12089798, -16020744, -21221907, -8410994, -33080606, 11275578, 3807637, 11185450, -23227561, -12892068, 1356866, -1025012, -8022738, -8139671, -20315029, -13916324, -6475650, -7025596, 12403179, -5139984, -12068178, 10445584, -14826705, -4927780, 13964546, 12525942, -2314107, -10566315, 32243863, 15603849, 5154154, 4276633, -20918372, -15718796, -26386151, 8434696 }}; + //const point_pc_t c_point_U {{ 30807552, 984924, 23426137, -5598760, 7545909, 16325843, 993742, 2594106, -31962071, -959867, 16454190, -4091093, 1197656, 13586872, -9269020, -14133290, 1869274, 13360979, -24627258, -10663086, 2212027, 1198856, 20515811, 15870563, -23833732, 9839517, -19416306, 11567295, -4212053, 348531, -2671541, 484270, -19128078, 1236698, -16002690, 9321345, 9776066, 10711838, 11187722, -16371275 }}; + //const point_pc_t c_point_X {{ 25635916, -5459446, 5768861, 5666160, -6357364, -12939311, 29490001, -4543704, -31266450, -2582476, 23705213, 9562626, -716512, 16560168, 7947407, 2039790, -2752711, 4742449, 3356761, 16338966, 17303421, -5790717, -5684800, 12062431, -3307947, 8139265, -26544839, 12058874, 3452748, 3359034, 26514848, -6060876, 31255039, 11154418, -21741975, -3782423, -19871841, 5729859, 21754676, -12454027 }}; + //const point_pc_t c_point_H_plus_G {{ 12291435, 3330843, -3390294, 13894858, -1099584, -6848191, 12040668, -15950068, -7494633, 12566672, -5526901, -16645799, -31081168, -1095427, -13082463, 4573480, -11255691, 4344628, 33477173, 11137213, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -6229107, -9324867, 558657, 6493750, 4895261, 12642545, 9549220, 696086, 21894285, -10521807 }}; + //const point_pc_t c_point_H_minus_G {{ -28347682, 3523701, -3380175, -14453727, 4238027, -6032522, 20235758, 4091609, 12557126, -8064113, 4212476, -13419094, -114185, -7650727, -24238, 16663404, 23676363, -6819610, 18286466, 8714527, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -20450317, 13815641, -11604061, -447489, 27380225, 9400847, -8551293, -1173627, -28110171, 14241295 }}; + +} // namespace crypto diff --git a/crypto/upstream/crypto-sugar.h b/crypto/upstream/crypto-sugar.h new file mode 100755 index 0000000..cd6d789 --- /dev/null +++ b/crypto/upstream/crypto-sugar.h @@ -0,0 +1,1452 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once +#include +#include +#include "crypto.h" +#include "eth_signature.h" + +namespace crypto +{ + namespace mp = boost::multiprecision; + + extern "C" + { +#include "crypto/crypto-ops.h" + } // extern "C" + + // + // Helpers + // + + // returns greatest k, s.t. n**k <= v + // tests in crypto_tests_range_proofs.h + constexpr uint64_t constexpr_floor_log_n(uint64_t v, uint64_t n) + { + return (v < n || n <= 1) ? 0 : constexpr_floor_log_n(v / n, n) + 1; + } + + // returns smallest k, s.t. v <= n**k + // tests in crypto_tests_range_proofs.h + constexpr uint64_t constexpr_ceil_log_n(uint64_t v, uint64_t n) + { + return (v <= 1 || n <= 1) ? 0 : constexpr_floor_log_n(v - 1, n) + 1; + } + + // returns smallest k, s.t. v <= 2**k + // tests in crypto_tests_range_proofs.h + constexpr uint64_t constexpr_ceil_log2(uint64_t v) + { + return constexpr_ceil_log_n(v, 2); + } + + // returns base ** k + constexpr uint64_t constexpr_pow(uint64_t k, uint64_t base) + { + return k == 0 ? 1 : base * constexpr_pow(k - 1, base); + } + + + inline std::string buff_to_hex(const void* pdata, size_t len, bool reversed = false) + { + constexpr char hexmap[] = "0123456789abcdef"; + const unsigned char* data = reinterpret_cast(pdata); + + std::string s(len * 2, ' '); + if (!reversed) + { + for (size_t i = 0; i < len; ++i) + { + s[2 * i] = hexmap[data[i] >> 4]; + s[2 * i + 1] = hexmap[data[i] & 0x0F]; + } + } + else + { + for (size_t i = 0; i < len; ++i) + { + s[2 * i] = hexmap[data[len - 1 - i] >> 4]; + s[2 * i + 1] = hexmap[data[len - 1 - i] & 0x0F]; + } + } + + return s; + } + + template + std::string pod_to_hex_reversed(const pod_t &h) + { + return buff_to_hex(&h, sizeof h, true); + } + + template + std::string pod_to_hex(const pod_t &h) + { + return buff_to_hex(&h, sizeof h); + } + + template + std::string pod_to_hex_comma_separated_bytes(const pod_t &h) + { + std::stringstream ss; + ss << std::hex << std::setfill('0'); + size_t len = sizeof h; + const unsigned char* p = (const unsigned char*)&h; + for (size_t i = 0; i < len; ++i) + { + ss << "0x" << std::setw(2) << static_cast(p[i]); + if (i + 1 != len) + ss << ", "; + } + return ss.str(); + } + + template + std::string pod_to_comma_separated_chars(const pod_t &h) + { + std::stringstream ss; + ss << std::hex << std::setfill('0'); + size_t len = sizeof h; + const unsigned char* p = (const unsigned char*)&h; + for (size_t i = 0; i < len; ++i) + { + ss << "'\\x" << std::setw(2) << static_cast(p[i]) << "'"; + if (i + 1 != len) + ss << ", "; + } + return ss.str(); + } + + template + std::string pod_to_hex_comma_separated_uint64(const pod_t &h) + { + static_assert((sizeof h) % 8 == 0, "size of h should be a multiple of 64 bit"); + size_t len = (sizeof h) / 8; + std::stringstream ss; + ss << std::hex << std::setfill('0'); + const uint64_t* p = (const uint64_t*)&h; + for (size_t i = 0; i < len; ++i) + { + ss << "0x" << std::setw(16) << static_cast(p[i]); + if (i + 1 != len) + ss << ", "; + } + return ss.str(); + } + + template + std::string pod_to_comma_separated_int32(const pod_t &h) + { + static_assert((sizeof h) % 4 == 0, "size of h should be a multiple of 32 bit"); + size_t len = (sizeof h) / 4; + std::stringstream ss; + const int32_t* p = (const int32_t*)&h; + for (size_t i = 0; i < len; ++i) + { + ss << static_cast(p[i]); + if (i + 1 != len) + ss << ", "; + } + return ss.str(); + } + + template + bool parse_tpod_from_hex_string(const std::string& hex_str, t_pod_type& t_pod) + { + static const int16_t char_map[256] = { // 0-9, a-f, A-F is only allowed + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00 - 0x1F + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 0x20 - 0x3F + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x40 - 0x5F + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x60 - 0x7F + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x80 - 0x9F + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xA0 - 0xBF + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0xC0 - 0xDF + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // 0xE0 - 0xFF + + size_t pod_size = sizeof t_pod; + uint8_t *p = reinterpret_cast(&t_pod); + + if (hex_str.size() != 2 * pod_size) + return false; + + for (size_t i = 0; i < pod_size; ++i) + { + int16_t hi = char_map[static_cast(hex_str[2 * i])]; + int16_t lo = char_map[static_cast(hex_str[2 * i + 1])]; + if (hi < 0 || lo < 0) + { + // invalid characters in hex_str + memset(p, 0, pod_size); + return false; + } + p[i] = static_cast(hi * 16 + lo); // write byte to pod + } + return true; + } + + template + t_pod_type parse_tpod_from_hex_string(const std::string& hex_str) + { + t_pod_type t_pod = AUTO_VAL_INIT(t_pod); + crypto::parse_tpod_from_hex_string(hex_str, t_pod); // using fully qualified name to avoid Argument-Dependent Lookup issues + return t_pod; + } + + // + // scalar_t - holds a 256-bit scalar, normally in [0..L-1] + // + struct /* TODO alignas(32) */ scalar_t + { + union + { + uint64_t m_u64[4]; + unsigned char m_s[32]; + crypto::secret_key m_sk; + }; + + scalar_t() = default; + + // won't check scalar range validity (< L) + constexpr scalar_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) noexcept + : m_u64{a0, a1, a2, a3} + { + } + + // won't check scalar range validity (< L) + scalar_t(const unsigned char(&v)[32]) + { + memcpy(m_s, v, 32); + } + + // won't check secret key validity (sk < L) + scalar_t(const crypto::secret_key& sk) + { + from_secret_key(sk); + } + + // copy data and reduce + scalar_t(const crypto::hash& hash) + { + m_u64[0] = ((uint64_t*)&hash)[0]; + m_u64[1] = ((uint64_t*)&hash)[1]; + m_u64[2] = ((uint64_t*)&hash)[2]; + m_u64[3] = ((uint64_t*)&hash)[3]; + sc_reduce32(&m_s[0]); + } + + scalar_t(uint64_t v) + { + zero(); + m_u64[0] = v; + // do not need to call reduce as 2^64 < L + } + + // copy at most 256 bits (32 bytes) and reduce + template + explicit scalar_t(const boost::multiprecision::number& bigint) + { + zero(); + size_t bytes_to_copy = bigint.backend().size() * bigint.backend().limb_bits / 8; + if (bytes_to_copy > sizeof *this) + bytes_to_copy = sizeof *this; + memcpy(&m_s[0], bigint.backend().limbs(), bytes_to_copy); + sc_reduce32(&m_s[0]); + } + + unsigned char* data() + { + return &m_s[0]; + } + + const unsigned char* data() const + { + return &m_s[0]; + } + + crypto::secret_key &as_secret_key() + { + return m_sk; + } + + const crypto::secret_key& as_secret_key() const + { + return m_sk; + } + + operator crypto::secret_key() const + { + return m_sk; + } + + void from_secret_key(const crypto::secret_key& sk) + { + m_sk = sk; + // assuming secret key is correct (< L), so we don't need to call reduce here + } + + void zero() + { + m_u64[0] = 0; + m_u64[1] = 0; + m_u64[2] = 0; + m_u64[3] = 0; + } + + // genrate 0 <= x < L + static scalar_t random() + { + scalar_t result; + result.make_random(); + return result; + } + + // generate 0 <= x < L + void make_random() + { + unsigned char tmp[64]; + crypto::generate_random_bytes(64, tmp); + sc_reduce(tmp); + memcpy(&m_s, tmp, sizeof m_s); + + /* // for tests + int x[8] = { rand() }; + crypto::cn_fast_hash(&x, sizeof x, *(crypto::hash*)this); + sc_reduce32(m_s); + */ + } + + bool is_zero() const + { + return sc_isnonzero(&m_s[0]) == 0; + } + + bool is_reduced() const + { + return sc_check(&m_s[0]) == 0; + } + + void reduce() + { + sc_reduce32(&m_s[0]); + } + + scalar_t operator+(const scalar_t& v) const + { + scalar_t result; + sc_add(&result.m_s[0], &m_s[0], &v.m_s[0]); + return result; + } + + scalar_t& operator+=(const scalar_t& v) + { + sc_add(&m_s[0], &m_s[0], &v.m_s[0]); + return *this; + } + + scalar_t operator-(const scalar_t& v) const + { + scalar_t result; + sc_sub(&result.m_s[0], &m_s[0], &v.m_s[0]); + return result; + } + + scalar_t& operator-=(const scalar_t& v) + { + sc_sub(&m_s[0], &m_s[0], &v.m_s[0]); + return *this; + } + + scalar_t operator*(const scalar_t& v) const + { + scalar_t result; + sc_mul(result.m_s, m_s, v.m_s); + return result; + } + + scalar_t& operator*=(const scalar_t& v) + { + sc_mul(m_s, m_s, v.m_s); + return *this; + } + + scalar_t operator-() const + { + static unsigned char zero[32] = { 0 }; + scalar_t result; + sc_sub(&result.m_s[0], zero, &m_s[0]); + return result; + } + + // returns this = a * b + scalar_t& assign_mul(const scalar_t& a, const scalar_t& b) + { + sc_mul(m_s, a.m_s, b.m_s); + return *this; + } + + /* + I think it has bad symantic (operator-like), consider rename/reimplement -- sowle + */ + // returns c + this * b + scalar_t muladd(const scalar_t& b, const scalar_t& c) const + { + scalar_t result; + sc_muladd(result.m_s, m_s, b.m_s, c.m_s); + return result; + } + + // returns this = c + a * b + scalar_t& assign_muladd(const scalar_t& a, const scalar_t& b, const scalar_t& c) + { + sc_muladd(m_s, a.m_s, b.m_s, c.m_s); + return *this; + } + + // returns this = c - a * b + scalar_t& assign_mulsub(const scalar_t& a, const scalar_t& b, const scalar_t& c) + { + sc_mulsub(m_s, a.m_s, b.m_s, c.m_s); + return *this; + } + + scalar_t reciprocal() const + { + scalar_t result; + sc_invert(result.m_s, m_s); + return result; + } + + scalar_t operator/(const scalar_t& v) const + { + return operator*(v.reciprocal()); + } + + scalar_t& operator/=(const scalar_t& v) + { + scalar_t reciprocal; + sc_invert(&reciprocal.m_s[0], &v.m_s[0]); + sc_mul(&m_s[0], &m_s[0], &reciprocal.m_s[0]); + return *this; + } + + bool operator==(const scalar_t& rhs) const + { + return + m_u64[0] == rhs.m_u64[0] && + m_u64[1] == rhs.m_u64[1] && + m_u64[2] == rhs.m_u64[2] && + m_u64[3] == rhs.m_u64[3]; + } + + bool operator!=(const scalar_t& rhs) const + { + return + m_u64[0] != rhs.m_u64[0] || + m_u64[1] != rhs.m_u64[1] || + m_u64[2] != rhs.m_u64[2] || + m_u64[3] != rhs.m_u64[3]; + } + + bool operator<(const scalar_t& rhs) const + { + if (m_u64[3] < rhs.m_u64[3]) return true; + if (m_u64[3] > rhs.m_u64[3]) return false; + if (m_u64[2] < rhs.m_u64[2]) return true; + if (m_u64[2] > rhs.m_u64[2]) return false; + if (m_u64[1] < rhs.m_u64[1]) return true; + if (m_u64[1] > rhs.m_u64[1]) return false; + if (m_u64[0] < rhs.m_u64[0]) return true; + if (m_u64[0] > rhs.m_u64[0]) return false; + return false; + } + + bool operator>(const scalar_t& rhs) const + { + if (m_u64[3] < rhs.m_u64[3]) return false; + if (m_u64[3] > rhs.m_u64[3]) return true; + if (m_u64[2] < rhs.m_u64[2]) return false; + if (m_u64[2] > rhs.m_u64[2]) return true; + if (m_u64[1] < rhs.m_u64[1]) return false; + if (m_u64[1] > rhs.m_u64[1]) return true; + if (m_u64[0] < rhs.m_u64[0]) return false; + if (m_u64[0] > rhs.m_u64[0]) return true; + return false; + } + + friend std::ostream& operator<<(std::ostream& ss, const scalar_t &v) + { + return ss << pod_to_hex(v); + } + + std::string to_string_as_hex_number() const + { + return pod_to_hex_reversed(*this); + } + + std::string to_string_as_secret_key() const + { + return pod_to_hex(*this); + } + + template + MP_type as_boost_mp_type() const + { + MP_type result = 0; + static_assert(sizeof result >= sizeof *this, "size missmatch"); // to avoid using types less than uint256_t + unsigned int sz = sizeof *this / sizeof(boost::multiprecision::limb_type); + result.backend().resize(sz, sz); + memcpy(result.backend().limbs(), &m_s[0], sizeof *this); + result.backend().normalize(); + return result; + } + + // Little-endian assumed; TODO: consider Big-endian support + bool get_bit(uint8_t bit_index) const + { + return (m_u64[bit_index >> 6] & (1ull << (bit_index & 63))) != 0; + } + + // Little-endian assumed; TODO: consider Big-endian support + void set_bit(size_t bit_index) + { + m_u64[bit_index >> 6] |= (1ull << (bit_index & 63)); + } + + // Little-endian assumed; TODO: consider Big-endian support + void clear_bit(size_t bit_index) + { + m_u64[bit_index >> 6] &= ~(1ull << (bit_index & 63)); + } + + // the result is guaranteed to be within [ 0; 2 ^ bits_count ) + uint64_t get_bits(uint8_t bit_index_first, uint8_t bits_count) const + { + if (bits_count == 0 || bits_count > 64) + return 0; + uint8_t bits_count_m_1 = bits_count - 1; + unsigned int bit_index_last = bit_index_first + bits_count_m_1; + if (bit_index_last > 255) + bit_index_last = 255; + + uint64_t result = m_u64[bit_index_first >> 6] >> (bit_index_first & 63); + if (bits_count_m_1 > (bit_index_last & 63)) + result |= m_u64[bit_index_last >> 6] << (bits_count_m_1 - (bit_index_last & 63)); + + uint64_t result_mask = ((1ull << bits_count_m_1) - 1) << 1 | 1; // (just because 1ull << 64 in undefined behaviour, not a 0 as one would expect) + return result & result_mask; + } + + // does not reduce + static scalar_t power_of_2(uint8_t exponent) + { + scalar_t result = 0; + result.set_bit(exponent); + return result; + } + + }; // struct scalar_t + + // + // Global constants (checked in crypto_constants) + // + + static constexpr scalar_t c_scalar_0 = { 0, 0, 0, 0 }; + static constexpr scalar_t c_scalar_1 = { 1, 0, 0, 0 }; + static constexpr scalar_t c_scalar_2p64 = { 0, 1, 0, 0 }; + static constexpr scalar_t c_scalar_L = { 0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 }; + static constexpr scalar_t c_scalar_Lm1 = { 0x5812631a5cf5d3ec, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 }; + static constexpr scalar_t c_scalar_P = { 0xffffffffffffffed, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff }; + static constexpr scalar_t c_scalar_Pm1 = { 0xffffffffffffffec, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff }; + static constexpr scalar_t c_scalar_256m1 = { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff }; + static constexpr scalar_t c_scalar_1div8 = { 0x6106e529e2dc2f79, 0x07d39db37d1cdad0, 0x0, 0x0600000000000000 }; + + static_assert(sizeof(scalar_t::m_sk) == sizeof(scalar_t::m_u64) && sizeof(scalar_t::m_u64) == sizeof(scalar_t::m_s), "size missmatch"); + + // + // + // + struct point_t + { + struct tag_zero {}; + + // A point(x, y) is represented in extended homogeneous coordinates (X, Y, Z, T) + // with x = X / Z, y = Y / Z, x * y = T / Z. + ge_p3 m_p3; + + point_t() = default; + + explicit point_t(const crypto::public_key& pk) // can throw std::runtime_error + { + CRYPTO_CHECK_AND_THROW_MES(from_public_key(pk), "invalid public key"); + } + + point_t(const unsigned char(&v)[32]) // can throw std::runtime_error + { + static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch"); + CRYPTO_CHECK_AND_THROW_MES(from_public_key(*(const crypto::public_key*)v), "invalid public key (char[32])"); + } + + point_t(const uint64_t(&v)[4]) // can throw std::runtime_error + { + static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch"); + CRYPTO_CHECK_AND_THROW_MES(from_public_key(*(const crypto::public_key*)v), "invalid public key (uint64_t[4])"); + } + + point_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) // can throw std::runtime_error + { + crypto::public_key pk; + ((uint64_t*)&pk)[0] = a0; + ((uint64_t*)&pk)[1] = a1; + ((uint64_t*)&pk)[2] = a2; + ((uint64_t*)&pk)[3] = a3; + + CRYPTO_CHECK_AND_THROW_MES(from_public_key(pk), "invalid public key (four uint64_t)"); + } + + explicit point_t(tag_zero&&) + { + zero(); + } + + explicit point_t(const key_image& ki) // can throw std::runtime_error + : point_t(static_cast(static_cast(ki))) + { + } + + explicit constexpr point_t(const int32_t(&v)[40]) noexcept + : m_p3{ + {v[ 0], v[ 1], v[ 2], v[ 3], v[ 4], v[ 5], v[ 6], v[ 7], v[ 8], v[9]}, + {v[10], v[11], v[12], v[13], v[14], v[15], v[16], v[17], v[18], v[19]}, + {v[20], v[21], v[22], v[23], v[24], v[25], v[26], v[27], v[28], v[29]}, + {v[30], v[31], v[32], v[33], v[34], v[35], v[36], v[37], v[38], v[39]} + } + { + } + + // as we're using additive notation, zero means identity group element (EC point (0, 1)) here and after + void zero() + { + ge_p3_0(&m_p3); + } + + bool is_zero() const + { + // (0, 1) ~ (0, z, z, 0) for any non-zero z https://www.rfc-editor.org/rfc/rfc8032#page-17 + if (fe_isnonzero(m_p3.X) != 0) + return false; // x != 0 + if (fe_isnonzero(m_p3.Z) == 0) + return false; // z == 0 + if (fe_isnonzero(m_p3.T) != 0) + return false; // t != 0 + fe y_minus_z; + fe_sub(y_minus_z, m_p3.Y, m_p3.Z); + return fe_isnonzero(y_minus_z) == 0; + } + + bool is_in_main_subgroup() const + { + return (c_scalar_L * *this).is_zero(); + } + + bool from_public_key(const crypto::public_key& pk) + { + return ge_frombytes_vartime(&m_p3, reinterpret_cast(&pk)) == 0; + } + + bool from_key_image(const crypto::key_image& ki) + { + return ge_frombytes_vartime(&m_p3, reinterpret_cast(&ki)) == 0; + } + + bool from_string(const std::string& str) + { + crypto::public_key pk; + if (!parse_tpod_from_hex_string(str, pk)) + return false; + return from_public_key(pk); + } + + crypto::public_key to_public_key() const + { + crypto::public_key result; + ge_p3_tobytes((unsigned char*)&result, &m_p3); + return result; + } + + void to_public_key(crypto::public_key& result) const + { + ge_p3_tobytes((unsigned char*)&result, &m_p3); + } + + crypto::key_image to_key_image() const + { + crypto::key_image result; + ge_p3_tobytes((unsigned char*)&result, &m_p3); + return result; + } + + point_t operator+(const point_t& rhs) const + { + point_t result; + ge_cached rhs_c; + ge_p1p1 t; + ge_p3_to_cached(&rhs_c, &rhs.m_p3); + ge_add(&t, &m_p3, &rhs_c); + ge_p1p1_to_p3(&result.m_p3, &t); + return result; + } + + point_t& operator+=(const point_t& rhs) + { + ge_cached rhs_c; + ge_p1p1 t; + ge_p3_to_cached(&rhs_c, &rhs.m_p3); + ge_add(&t, &m_p3, &rhs_c); + ge_p1p1_to_p3(&m_p3, &t); + return *this; + } + + point_t operator-(const point_t& rhs) const + { + point_t result; + ge_cached rhs_c; + ge_p1p1 t; + ge_p3_to_cached(&rhs_c, &rhs.m_p3); + ge_sub(&t, &m_p3, &rhs_c); + ge_p1p1_to_p3(&result.m_p3, &t); + return result; + } + + point_t& operator-=(const point_t& rhs) + { + ge_cached rhs_c; + ge_p1p1 t; + ge_p3_to_cached(&rhs_c, &rhs.m_p3); + ge_sub(&t, &m_p3, &rhs_c); + ge_p1p1_to_p3(&m_p3, &t); + return *this; + } + + friend point_t operator*(const scalar_t& lhs, const point_t& rhs) + { + point_t result; + //ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3); + ge_scalarmult_vartime_p3(&result.m_p3, lhs.m_s, &rhs.m_p3); + return result; + } + + point_t& operator*=(const scalar_t& rhs) + { + //ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3); + ge_scalarmult_vartime_p3(&m_p3, rhs.m_s, &m_p3); + return *this; + } + + friend point_t operator/(const point_t& lhs, const scalar_t& rhs) + { + point_t result; + scalar_t reciprocal; + sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]); + //ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3); + ge_scalarmult_vartime_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3); + return result; + } + + point_t operator-() const + { + point_t result = *this; + fe zero = {0}; + fe_sub(result.m_p3.Y, zero, result.m_p3.Y); + fe_sub(result.m_p3.Z, zero, result.m_p3.Z); + return result; + } + + point_t& modify_mul8() + { + ge_mul8_p3(&m_p3, &m_p3); + return *this; + } + + point_t modify_mul_pow_2(size_t power) + { + if (power > 0) + { + ge_p1p1 p1; + ge_p2 p2; + ge_p3_to_p2(&p2, &m_p3); + for (size_t i = 1; i < power; ++i) + { + ge_p2_dbl(&p1, &p2); + ge_p1p1_to_p2(&p2, &p1); + } + ge_p2_dbl(&p1, &p2); + ge_p1p1_to_p3(&m_p3, &p1); + } + return *this; + } + + // returns a * this + G + point_t mul_plus_G(const scalar_t& a) const + { + static const unsigned char one[32] = { 1 }; + static_assert(sizeof one == sizeof(crypto::ec_scalar), "size missmatch"); + + point_t result; + ge_double_scalarmult_base_vartime_p3(&result.m_p3, &a.m_s[0], &m_p3, &one[0]); + return result; + } + + // returns a * this + b * G + point_t mul_plus_G(const scalar_t& a, const scalar_t& b) const + { + point_t result; + ge_double_scalarmult_base_vartime_p3(&result.m_p3, &a.m_s[0], &m_p3, &b.m_s[0]); + return result; + } + + // *this = a * A + b * G + void assign_mul_plus_G(const scalar_t& a, const point_t& A, const scalar_t& b) + { + ge_double_scalarmult_base_vartime_p3(&m_p3, &a.m_s[0], &A.m_p3, &b.m_s[0]); + } + + friend bool operator==(const point_t& lhs, const point_t& rhs) + { + return (lhs - rhs).is_zero(); + } + + friend bool operator!=(const point_t& lhs, const point_t& rhs) + { + return !(lhs == rhs); + } + + friend bool operator==(const point_t& lhs, const public_key& rhs) + { + return lhs.to_public_key() == rhs; + } + + friend bool operator!=(const point_t& lhs, const public_key& rhs) + { + return !(lhs == rhs); + } + + friend bool operator==(const public_key& lhs, const point_t& rhs) + { + return lhs == rhs.to_public_key(); + } + + friend bool operator!=(const public_key& lhs, const point_t& rhs) + { + return !(lhs == rhs); + } + + friend std::ostream& operator<<(std::ostream& ss, const point_t &v) + { + crypto::public_key pk = v.to_public_key(); + return ss << pod_to_hex(pk); + } + + operator std::string() const + { + crypto::public_key pk = to_public_key(); + return pod_to_hex(pk); + } + + std::string to_string() const + { + crypto::public_key pk = to_public_key(); + return pod_to_hex(pk); + } + + std::string to_hex_comma_separated_bytes_str() const + { + crypto::public_key pk = to_public_key(); + return pod_to_hex_comma_separated_bytes(pk); + } + + std::string to_hex_comma_separated_uint64_str() const + { + crypto::public_key pk = to_public_key(); + return pod_to_hex_comma_separated_uint64(pk); + } + + std::string to_comma_separated_int32_str() const + { + return pod_to_comma_separated_int32(m_p3); + } + + }; // struct point_t + + + // + // point_g_t -- special type for curve's base point + // + struct point_g_t : public point_t + { + explicit constexpr point_g_t(const int32_t(&v)[40]) noexcept + : point_t(v) + { + } + + friend point_t operator*(const scalar_t& lhs, const point_g_t&) + { + point_t result; + //ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]); + ge_scalarmult_base_vartime(&result.m_p3, &lhs.m_s[0]); + return result; + } + + friend point_t operator/(const point_g_t&, const scalar_t& rhs) + { + point_t result; + scalar_t reciprocal; + sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]); + //ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]); + ge_scalarmult_base_vartime(&result.m_p3, &reciprocal.m_s[0]); + return result; + } + + static_assert(sizeof(crypto::public_key) == 32, "size error"); + + }; // struct point_g_t + + + void construct_precomp_data(precomp_data_t precomp_data, const point_t& point); + + // + // point_pc_t -- point with 30kB of precomputed data, which make possible to do very fast single scalar multiplication + // + struct point_pc_t : public point_t + { + constexpr point_pc_t(const int32_t(&v)[40], const precomp_data_t* precomp_data_p) + : point_t(v) + , m_precomp_data_p(precomp_data_p) + { + //construct_precomp_data(m_precomp_data, *this); + } + + friend point_t operator*(const scalar_t& lhs, const point_pc_t& self) + { + point_t result; + ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &lhs.m_s[0]); + return result; + } + + friend point_t operator/(const point_pc_t& self, const scalar_t& rhs) + { + point_t result; + scalar_t reciprocal; + sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]); + ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &reciprocal.m_s[0]); + return result; + } + + static_assert(sizeof(crypto::public_key) == 32, "size error"); + + const precomp_data_t* m_precomp_data_p; + }; // struct point_pc_t + + + // + // vector of scalars + // + struct scalar_vec_t : public std::vector + { + typedef std::vector super_t; + + scalar_vec_t() {} + scalar_vec_t(size_t n) : super_t(n) {} + scalar_vec_t(std::initializer_list init_list) : super_t(init_list) {} + + bool is_reduced() const + { + for (auto& el : *this) + if (!el.is_reduced()) + return false; + return true; + } + + // add a scalar rhs to each element + scalar_vec_t operator+(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) + rhs; + return result; + } + + // subtract a scalar rhs to each element + scalar_vec_t operator-(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) - rhs; + return result; + } + + // multiply each element of the vector by a scalar + scalar_vec_t operator*(const scalar_t& rhs) const + { + scalar_vec_t result(size()); + for (size_t i = 0, n = size(); i < n; ++i) + result[i] = at(i) * rhs; + return result; + } + + // component-wise multiplication (a.k.a the Hadamard product) (only if their sizes match) + scalar_vec_t operator*(const scalar_vec_t& rhs) const + { + scalar_vec_t result; + const size_t n = size(); + if (n != rhs.size()) + return result; + + result.resize(size()); + for (size_t i = 0; i < n; ++i) + result[i] = at(i) * rhs[i]; + return result; + } + + // add each element of two vectors, but only if their sizes match + scalar_vec_t operator+(const scalar_vec_t& rhs) const + { + scalar_vec_t result; + const size_t n = size(); + if (n != rhs.size()) + return result; + + result.resize(size()); + for (size_t i = 0; i < n; ++i) + result[i] = at(i) + rhs[i]; + return result; + } + + // zeroes all elements + void zero() + { + PUSH_GCC_WARNINGS + DISABLE_GCC_WARNING(class-memaccess) + size_t size_bytes = sizeof(scalar_t) * size(); + memset(data(), 0, size_bytes); + POP_GCC_WARNINGS + } + + // invert all elements in-place efficiently: 4*N muptiplications + 1 inversion + void invert() + { + // muls muls_rev + // 0: 1 2 3 .. n-1 + // 1: 0 2 3 .. n-1 + // 2: 0 1 3 .. n-1 + // + // n-1: 0 1 2 3 .. n-2 + + const size_t size = this->size(); + + if (size < 2) + { + if (size == 1) + at(0) = at(0).reciprocal(); + return; + } + + scalar_vec_t muls(size), muls_rev(size); + muls[0] = 1; + for (size_t i = 0; i < size - 1; ++i) + muls[i + 1] = at(i) * muls[i]; + + muls_rev[size - 1] = 1; + for (size_t i = size - 1; i != 0; --i) + muls_rev[i - 1] = at(i) * muls_rev[i]; + + scalar_t inv = (muls[size - 1] * at(size - 1)).reciprocal(); + + for (size_t i = 0; i < size; ++i) + at(i) = muls[i] * inv * muls_rev[i]; + } + + scalar_t calc_hs() const; + + void make_random() + { + for(size_t size = this->size(), i = 0; i < size; ++i) + at(i).make_random(); + } + + void resize_and_make_random(size_t size) + { + this->resize(size); + make_random(); + } + + }; // scalar_vec_t + + + // treats vector of scalars as an M x N matrix just for convenience + template + struct scalar_mat_t : public scalar_vec_t + { + typedef scalar_vec_t super_t; + static_assert(N > 0, "invalid N value"); + + scalar_mat_t() {} + scalar_mat_t(size_t n) : super_t(n) {} + scalar_mat_t(std::initializer_list init_list) : super_t(init_list) {} + + // matrix accessor M rows x N cols + scalar_t& operator()(size_t row, size_t col) + { + return at(row * N + col); + } + }; // scalar_mat_t + + + + // + // Global constants (checked in crypto_constants and crypto_generators_precomp tests) + // + + namespace xdetails + { + extern const precomp_data_t c_point_H_precomp_data; + extern const precomp_data_t c_point_H2_precomp_data; + extern const precomp_data_t c_point_U_precomp_data; + extern const precomp_data_t c_point_X_precomp_data; + extern const precomp_data_t c_point_H_plus_G_precomp_data; + extern const precomp_data_t c_point_H_minus_G_precomp_data; + }; + + inline constexpr point_t c_point_0 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}; + inline constexpr point_g_t c_point_G {{ 25485296, 5318399, 8791791, -8299916, -14349720, 6939349, -3324311, -7717049, 7287234, -6577708, -758052, -1832720, 13046421, -4857925, 6576754, 14371947, -13139572, 6845540, -2198883, -4003719, -947565, 6097708, -469190, 10704810, -8556274, -15589498, -16424464, -16608899, 14028613, -5004649, 6966464, -2456167, 7033433, 6781840, 28785542, 12262365, -2659449, 13959020, -21013759, -5262166 }}; + + inline constexpr point_pc_t c_point_H {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }, &xdetails::c_point_H_precomp_data }; + inline constexpr point_pc_t c_point_H2 {{ 1318371, 14804112, 12545972, -13482561, -12089798, -16020744, -21221907, -8410994, -33080606, 11275578, 3807637, 11185450, -23227561, -12892068, 1356866, -1025012, -8022738, -8139671, -20315029, -13916324, -6475650, -7025596, 12403179, -5139984, -12068178, 10445584, -14826705, -4927780, 13964546, 12525942, -2314107, -10566315, 32243863, 15603849, 5154154, 4276633, -20918372, -15718796, -26386151, 8434696 }, &xdetails::c_point_H2_precomp_data }; + inline constexpr point_pc_t c_point_U {{ 30807552, 984924, 23426137, -5598760, 7545909, 16325843, 993742, 2594106, -31962071, -959867, 16454190, -4091093, 1197656, 13586872, -9269020, -14133290, 1869274, 13360979, -24627258, -10663086, 2212027, 1198856, 20515811, 15870563, -23833732, 9839517, -19416306, 11567295, -4212053, 348531, -2671541, 484270, -19128078, 1236698, -16002690, 9321345, 9776066, 10711838, 11187722, -16371275 }, &xdetails::c_point_U_precomp_data }; + inline constexpr point_pc_t c_point_X {{ 25635916, -5459446, 5768861, 5666160, -6357364, -12939311, 29490001, -4543704, -31266450, -2582476, 23705213, 9562626, -716512, 16560168, 7947407, 2039790, -2752711, 4742449, 3356761, 16338966, 17303421, -5790717, -5684800, 12062431, -3307947, 8139265, -26544839, 12058874, 3452748, 3359034, 26514848, -6060876, 31255039, 11154418, -21741975, -3782423, -19871841, 5729859, 21754676, -12454027 }, &xdetails::c_point_X_precomp_data }; + inline constexpr point_pc_t c_point_H_plus_G {{ 12291435, 3330843, -3390294, 13894858, -1099584, -6848191, 12040668, -15950068, -7494633, 12566672, -5526901, -16645799, -31081168, -1095427, -13082463, 4573480, -11255691, 4344628, 33477173, 11137213, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -6229107, -9324867, 558657, 6493750, 4895261, 12642545, 9549220, 696086, 21894285, -10521807 }, &xdetails::c_point_H_plus_G_precomp_data }; + inline constexpr point_pc_t c_point_H_minus_G {{ -28347682, 3523701, -3380175, -14453727, 4238027, -6032522, 20235758, 4091609, 12557126, -8064113, 4212476, -13419094, -114185, -7650727, -24238, 16663404, 23676363, -6819610, 18286466, 8714527, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -20450317, 13815641, -11604061, -447489, 27380225, 9400847, -8551293, -1173627, -28110171, 14241295 }, &xdetails::c_point_H_minus_G_precomp_data }; + + + // + // hash functions' helper + // + struct hash_helper_t + { + static scalar_t hs(const scalar_t& s) + { + return scalar_t(crypto::cn_fast_hash(s.data(), sizeof s)); // will reduce mod L + } + + static scalar_t hs(const void* data, size_t size) + { + return scalar_t(crypto::cn_fast_hash(data, size)); // will reduce mod L + } + + static scalar_t hs(const std::string& str) + { + return scalar_t(crypto::cn_fast_hash(str.c_str(), str.size())); // will reduce mod L + } + + static hash h(const std::string& str) + { + return crypto::cn_fast_hash(str.c_str(), str.size()); + } + + struct hs_t + { + hs_t(size_t size_to_reserve = 0) + { + static_assert(sizeof(scalar_t) == sizeof(crypto::public_key), "unexpected size of data"); + m_elements.reserve(size_to_reserve); + } + + void reserve(size_t elements_count) + { + m_elements.reserve(elements_count); + } + + void resize(size_t elements_count) + { + m_elements.resize(elements_count); + } + + void clear() + { + m_elements.clear(); + } + + void add_scalar(const scalar_t& scalar) + { + m_elements.emplace_back(scalar); + } + + void add_point(const point_t& point) + { + m_elements.emplace_back(point.to_public_key()); + } + + void add_pub_key(const crypto::public_key& pk) + { + m_elements.emplace_back(pk); + } + + void add_eth_pub_key(const crypto::eth_public_key& epk) + { + static_assert(sizeof(item_t) == 32, "unexpected size of hs_t::item_t"); + static_assert(sizeof epk.data == 33, "unexpected size of eth_public_key"); + m_elements.emplace_back(c_scalar_0); + m_elements.emplace_back(c_scalar_0); + char* p = m_elements[m_elements.size() - 2].c; // pointer to the first of the two added items + memcpy(p, &epk.data, sizeof epk.data); + } + + void add_key_image(const crypto::key_image& ki) + { + m_elements.emplace_back(ki); + } + + scalar_t& access_scalar(size_t index) + { + return m_elements[index].scalar; + } + + public_key& access_public_key(size_t index) + { + return m_elements[index].pk; + } + + void add_points_array(const std::vector& points_array) + { + for (size_t i = 0, size = points_array.size(); i < size; ++i) + add_point(points_array[i]); + } + + void add_pub_keys_array(const std::vector& pub_keys_array) + { + for (size_t i = 0, size = pub_keys_array.size(); i < size; ++i) + m_elements.emplace_back(pub_keys_array[i]); + } + + void add_key_images_array(const std::vector& key_image_array) + { + for (size_t i = 0, size = key_image_array.size(); i < size; ++i) + m_elements.emplace_back(key_image_array[i]); + } + + void add_hash(const hash& h) + { + m_elements.emplace_back(h); + } + + void add_32_chars(const char(&str32)[32]) + { + m_elements.emplace_back(str32); + } + + scalar_t calc_hash(bool clear = true) + { + size_t data_size_bytes = m_elements.size() * sizeof(item_t); + crypto::hash hash; + crypto::cn_fast_hash(m_elements.data(), data_size_bytes, hash); + if (clear) + this->clear(); + return scalar_t(hash); // this will reduce to L + } + + hash calc_hash_no_reduce(bool clear = true) + { + size_t data_size_bytes = m_elements.size() * sizeof(item_t); + hash result; + crypto::cn_fast_hash(m_elements.data(), data_size_bytes, result); + if (clear) + this->clear(); + return result; + } + + void assign_calc_hash(scalar_t& result, bool clear = true) + { + static_assert(sizeof result == sizeof(crypto::hash), "size missmatch"); + size_t data_size_bytes = m_elements.size() * sizeof(item_t); + crypto::cn_fast_hash(m_elements.data(), data_size_bytes, (crypto::hash&)result); + result.reduce(); + if (clear) + this->clear(); + } + + union item_t + { + item_t() {} + item_t(const scalar_t& scalar) : scalar(scalar) {} + item_t(const crypto::public_key& pk) : pk(pk) {} + item_t(const crypto::key_image& ki) : ki(ki) {} + item_t(const crypto::hash& h) : h(h) {} + item_t(const char(&str32)[32]) { memcpy(c, str32, sizeof c); } + scalar_t scalar; + crypto::public_key pk; + crypto::key_image ki; + crypto::hash h; + char c[32]; + }; + + static_assert(sizeof(item_t::c) == sizeof(item_t::pk), "size missmatch"); + static_assert(sizeof(item_t::h) == sizeof(item_t::pk), "size missmatch"); + + std::vector m_elements; + }; + + static scalar_t hs(const scalar_t& s, const std::vector& ps0, const std::vector& ps1) + { + hs_t hs_calculator(3); + hs_calculator.add_scalar(s); + hs_calculator.add_points_array(ps0); + hs_calculator.add_points_array(ps1); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const crypto::hash& s, const std::vector& ps0, const std::vector& ps1) + { + static_assert(sizeof(crypto::hash) == sizeof(scalar_t), "size missmatch"); + hs_t hs_calculator(3); + hs_calculator.add_scalar(*reinterpret_cast(&s)); + hs_calculator.add_pub_keys_array(ps0); + hs_calculator.add_key_images_array(ps1); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const std::vector& ps0, const std::vector& ps1) + { + hs_t hs_calculator(2); + hs_calculator.add_points_array(ps0); + hs_calculator.add_points_array(ps1); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const char(&str32)[32], const scalar_t& s) + { + hs_t hs_calculator(2); + hs_calculator.add_32_chars(str32); + hs_calculator.add_scalar(s); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const char(&str32)[32], const scalar_t& s, const crypto::public_key& pk) + { + hs_t hs_calculator(2); + hs_calculator.add_32_chars(str32); + hs_calculator.add_scalar(s); + hs_calculator.add_pub_key(pk); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const crypto::public_key& pk, const uint64_t i) + { + hs_t hs_calculator(2); + hs_calculator.add_pub_key(pk); + hs_calculator.add_scalar(scalar_t(i)); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const crypto::secret_key& sk, const uint64_t i) + { + hs_t hs_calculator(2); + hs_calculator.add_scalar(sk); + hs_calculator.add_scalar(scalar_t(i)); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const char(&str32)[32], const crypto::public_key& pk, const uint64_t i) + { + hs_t hs_calculator(3); + hs_calculator.add_32_chars(str32); + hs_calculator.add_pub_key(pk); + hs_calculator.add_scalar(scalar_t(i)); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const char(&str32)[32], const crypto::hash& h) + { + hs_t hs_calculator(2); + hs_calculator.add_32_chars(str32); + hs_calculator.add_hash(h); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const char(&str32)[32], const crypto::point_t& p) + { + hs_t hs_calculator(2); + hs_calculator.add_32_chars(str32); + hs_calculator.add_point(p); + return hs_calculator.calc_hash(); + } + + static scalar_t hs(const char(&str32)[32], const crypto::key_derivation& derivation, uint64_t index) + { + hs_t hs_calculator(3); + hs_calculator.add_32_chars(str32); + hs_calculator.add_pub_key(reinterpret_cast(derivation)); + hs_calculator.add_scalar(index); + return hs_calculator.calc_hash(); + } + + static point_t hp(const point_t& p) + { + point_t result; + crypto::public_key pk = p.to_public_key(); + + ge_bytes_hash_to_ec_32(&result.m_p3, (const unsigned char*)&pk); + + return result; + } + + static point_t hp(const crypto::public_key& p) + { + point_t result; + ge_bytes_hash_to_ec_32(&result.m_p3, (const unsigned char*)&p); + return result; + } + + static point_t hp(const scalar_t& s) + { + point_t result; + ge_bytes_hash_to_ec_32(&result.m_p3, s.data()); + return result; + } + + static point_t hp(const void* data, size_t size) + { + point_t result; + ge_bytes_hash_to_ec(&result.m_p3, data, size); + return result; + } + + static point_t hp(const std::string& str) + { + point_t result; + ge_bytes_hash_to_ec(&result.m_p3, str.data(), str.size()); + return result; + } + + }; // hash_helper_t struct + + + inline scalar_t scalar_vec_t::calc_hs() const + { + // hs won't touch memory if size is 0, so it's safe + return hash_helper_t::hs(data(), sizeof(scalar_t) * size()); + } + +} // namespace crypto diff --git a/crypto/upstream/crypto.cpp b/crypto/upstream/crypto.cpp new file mode 100755 index 0000000..49650a6 --- /dev/null +++ b/crypto/upstream/crypto.cpp @@ -0,0 +1,431 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common/varint.h" +#include "warnings.h" +#include "crypto.h" +#include "hash.h" + +#if !defined(NDEBUG) +# define crypto_assert(expression) assert(expression); CRYPTO_CHECK_AND_THROW_MES(expression, #expression) +#else +# define crypto_assert(expression) CRYPTO_CHECK_AND_THROW_MES(expression, #expression) +#endif + +namespace crypto { + + DISABLE_GCC_AND_CLANG_WARNING(strict-aliasing) + const unsigned char Z_[32] = { 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, 0x00 }; + const unsigned char I_[32] = { 0x01, 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 }; + const unsigned char L_[32] = { 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 }; + + const key_image Z = *reinterpret_cast(&Z_); + const key_image I = *reinterpret_cast(&I_); + const key_image L = *reinterpret_cast(&L_); + + extern "C" { +#include "crypto-ops.h" +#include "random.h" + } + + + std::mutex& random_lock_accessor() noexcept + { + // this is a thread-safe approach + // note section 6.7: "If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization." + static std::mutex random_lock; + return random_lock; + } + + + static inline unsigned char *operator &(ec_point &point) { + return &reinterpret_cast(point); + } + + static inline const unsigned char *operator &(const ec_point &point) { + return &reinterpret_cast(point); + } + + static inline unsigned char *operator &(ec_scalar &scalar) { + return &reinterpret_cast(scalar); + } + + static inline const unsigned char *operator &(const ec_scalar &scalar) { + return &reinterpret_cast(scalar); + } + + static inline void random_scalar_no_lock(ec_scalar &res) + { + unsigned char tmp[64]; + generate_random_bytes_no_lock(64, tmp); + sc_reduce(tmp); + memcpy(&res, tmp, 32); + } + + void crypto_ops::keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size) + { + unsigned char tmp[64] = { 0 }; + + if (!(sizeof(tmp) >= keys_seed_binary_size)) + { + throw std::runtime_error("size mismatch"); + } + + memcpy(tmp, a_part, keys_seed_binary_size); + + cn_fast_hash(tmp, 32, (char*)&tmp[32]); + + sc_reduce(tmp); + memcpy(&sec, tmp, 32); + ge_p3 point; + ge_scalarmult_base(&point, &sec); + ge_p3_tobytes(&pub, &point); + } + + void crypto_ops::generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size) + { + keys_seed_binary.resize(keys_seed_binary_size, 0); + generate_random_bytes(keys_seed_binary_size, keys_seed_binary.data()); + keys_from_default(keys_seed_binary.data(), pub, sec, keys_seed_binary_size); + } + + static inline void hash_to_scalar(const void *data, size_t length, ec_scalar &res) + { + cn_fast_hash(data, length, reinterpret_cast(res)); + sc_reduce32(&res); + } + + void crypto_ops::generate_keys(public_key &pub, secret_key &sec) + { + std::lock_guard lock(random_lock_accessor()); + ge_p3 point; + random_scalar_no_lock(sec); + ge_scalarmult_base(&point, &sec); + ge_p3_tobytes(&pub, &point); + } + + void crypto_ops::dependent_key(const secret_key& first, secret_key& second) + { + hash_to_scalar(&first, 32, second); + if (sc_check((unsigned char*)&second) != 0) + throw std::runtime_error("Failed to derive key"); + } + + + bool crypto_ops::check_key(const public_key &key) { + ge_p3 point; + return ge_frombytes_vartime(&point, &key) == 0; + } + + /* + Fix discovered by Monero Lab and suggested by "fluffypony" (bitcointalk.org) + */ + key_image scalarmult_key(const key_image & P, const key_image & a) + { + ge_p3 A = ge_p3(); + ge_p2 R = ge_p2(); + if (ge_frombytes_vartime(&A, reinterpret_cast(&P)) != 0) + return Z; + ge_scalarmult(&R, reinterpret_cast(&a), &A); + key_image a_p = key_image(); + ge_tobytes(reinterpret_cast(&a_p), &R); + return a_p; + } + + bool crypto_ops::validate_key_image(const key_image& ki) + { + if (!(scalarmult_key(ki, L) == I)) + return false; + + return true; + } + + bool crypto_ops::secret_key_to_public_key(const secret_key &sec, public_key &pub) { + ge_p3 point; + if (sc_check(&sec) != 0) { + return false; + } + ge_scalarmult_base(&point, &sec); + ge_p3_tobytes(&pub, &point); + return true; + } + + bool crypto_ops::generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { + ge_p3 point; + ge_p2 point2; + ge_p1p1 point3; + crypto_assert(sc_check(&key2) == 0); + if (ge_frombytes_vartime(&point, &key1) != 0) { + return false; + } + ge_scalarmult(&point2, &key2, &point); + ge_mul8(&point3, &point2); + ge_p1p1_to_p2(&point2, &point3); + ge_tobytes(&derivation, &point2); + return true; + } + + void crypto_ops::derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) + { + struct { + key_derivation derivation; + char output_index[(sizeof(size_t) * 8 + 6) / 7]; + } buf; + char *end = buf.output_index; + buf.derivation = derivation; + tools::write_varint(end, output_index); + if (!(end <= buf.output_index + sizeof buf.output_index)) + { + crypto_assert(false); + return; + } + hash_to_scalar(&buf, end - reinterpret_cast(&buf), res); + } + + bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index, + const public_key &base, public_key &derived_key) { + ec_scalar scalar; + ge_p3 point1; + ge_p3 point2; + ge_cached point3; + ge_p1p1 point4; + ge_p2 point5; + if (ge_frombytes_vartime(&point1, &base) != 0) { + return false; + } + derivation_to_scalar(derivation, output_index, scalar); + ge_scalarmult_base(&point2, &scalar); + ge_p3_to_cached(&point3, &point2); + ge_add(&point4, &point1, &point3); + ge_p1p1_to_p2(&point5, &point4); + ge_tobytes(&derived_key, &point5); + return true; + } + + void crypto_ops::derive_secret_key(const key_derivation &derivation, size_t output_index, + const secret_key &base, secret_key &derived_key) { + ec_scalar scalar; + crypto_assert(sc_check(&base) == 0); + derivation_to_scalar(derivation, output_index, scalar); + sc_add(&derived_key, &base, &scalar); + } + + struct s_comm { + hash h; + ec_point key; + ec_point comm; + }; + + void crypto_ops::generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) { + std::lock_guard lock(random_lock_accessor()); + ge_p3 tmp3; + ec_scalar k; + s_comm buf; +#if !defined(NDEBUG) + { + ge_p3 t; + public_key t2; + crypto_assert(sc_check(&sec) == 0); + ge_scalarmult_base(&t, &sec); + ge_p3_tobytes(&t2, &t); + crypto_assert(pub == t2); + } +#endif + buf.h = prefix_hash; + buf.key = pub; + random_scalar_no_lock(k); + ge_scalarmult_base(&tmp3, &k); + ge_p3_tobytes(&buf.comm, &tmp3); + hash_to_scalar(&buf, sizeof(s_comm), sig.c); + sc_mulsub(&sig.r, &sig.c, &sec, &k); + } + + bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { + ge_p2 tmp2; + ge_p3 tmp3; + ec_scalar c; + s_comm buf; + crypto_assert(check_key(pub)); + buf.h = prefix_hash; + buf.key = pub; + if (ge_frombytes_vartime(&tmp3, &pub) != 0) { + return false; + } + if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) { + return false; + } + ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r); + ge_tobytes(&buf.comm, &tmp2); + hash_to_scalar(&buf, sizeof(s_comm), c); + sc_sub(&c, &c, &sig.c); + return sc_isnonzero(&c) == 0; + } + + static void hash_to_ec(const public_key &key, ge_p3 &res) { + hash h; + ge_p2 point; + ge_p1p1 point2; + cn_fast_hash(std::addressof(key), sizeof(public_key), h); + ge_fromfe_frombytes_vartime(&point, reinterpret_cast(&h)); + ge_mul8(&point2, &point); + ge_p1p1_to_p3(&res, &point2); + } + + void crypto_ops::generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) { + // image = sec * 8 * ge_fromfe_frombytes_vartime(cn_fast_hash(pub)) = sec * Hp( pub ) + ge_p3 point; + ge_p2 point2; + crypto_assert(sc_check(&sec) == 0); + hash_to_ec(pub, point); + ge_scalarmult(&point2, &sec, &point); + ge_tobytes(&image, &point2); + } + +PUSH_VS_WARNINGS +DISABLE_VS_WARNINGS(4200) + struct rs_comm_entry + { + ec_point a, b; + }; + + struct rs_comm + { + hash h; + struct rs_comm_entry ab[]; + }; +POP_VS_WARNINGS + + static inline size_t rs_comm_size(size_t pubs_count) { + return sizeof(rs_comm)+pubs_count * sizeof(rs_comm_entry); + } + + void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image, + const public_key *const *pubs, size_t pubs_count, + const secret_key &sec, size_t sec_index, + signature *sig) { + std::lock_guard lock(random_lock_accessor()); + size_t i; + ge_p3 image_unp; + ge_dsmp image_pre; + ec_scalar sum, k, h; + rs_comm *const buf = reinterpret_cast(alloca(rs_comm_size(pubs_count))); + if (!(sec_index < pubs_count)) + { + crypto_assert(false); + return; + } +#if !defined(NDEBUG) + { + ge_p3 t; + public_key t2; + key_image t3; + crypto_assert(sc_check(&sec) == 0); + ge_scalarmult_base(&t, &sec); + ge_p3_tobytes(&t2, &t); + crypto_assert(*pubs[sec_index] == t2); + generate_key_image(*pubs[sec_index], sec, t3); + crypto_assert(image == t3); + for (i = 0; i < pubs_count; i++) { + crypto_assert(check_key(*pubs[i])); + } + } +#endif + if (ge_frombytes_vartime(&image_unp, &image) != 0) { + abort(); + } + ge_dsm_precomp(image_pre, &image_unp); + sc_0(&sum); + buf->h = prefix_hash; + for (i = 0; i < pubs_count; i++) { + ge_p2 tmp2; + ge_p3 tmp3; + if (i == sec_index) { + random_scalar_no_lock(k); + ge_scalarmult_base(&tmp3, &k); + ge_p3_tobytes(&buf->ab[i].a, &tmp3); + hash_to_ec(*pubs[i], tmp3); + ge_scalarmult(&tmp2, &k, &tmp3); + ge_tobytes(&buf->ab[i].b, &tmp2); + } else { + random_scalar_no_lock(sig[i].c); + random_scalar_no_lock(sig[i].r); + if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { + abort(); + } + ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); + ge_tobytes(&buf->ab[i].a, &tmp2); + hash_to_ec(*pubs[i], tmp3); + ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); + ge_tobytes(&buf->ab[i].b, &tmp2); + sc_add(&sum, &sum, &sig[i].c); + } + } + hash_to_scalar(buf, rs_comm_size(pubs_count), h); + sc_sub(&sig[sec_index].c, &h, &sum); + sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &sec, &k); + } + + bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image, + const public_key *const *pubs, size_t pubs_count, + const signature *sig) { + size_t i; + ge_p3 image_unp; + ge_dsmp image_pre; + ec_scalar sum, h; + rs_comm *const buf = reinterpret_cast(alloca(rs_comm_size(pubs_count))); +#if !defined(NDEBUG) + for (i = 0; i < pubs_count; i++) { + crypto_assert(check_key(*pubs[i])); + } +#endif + if (ge_frombytes_vartime(&image_unp, &image) != 0) { + return false; + } + ge_dsm_precomp(image_pre, &image_unp); + sc_0(&sum); + buf->h = prefix_hash; + for (i = 0; i < pubs_count; i++) { + ge_p2 tmp2; + ge_p3 tmp3; + if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) { + return false; + } + if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) { + return false; + } + ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); // L_i = r_i * G + c_i * P_i + ge_tobytes(&buf->ab[i].a, &tmp2); + hash_to_ec(*pubs[i], tmp3); + ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); // R_i = r_i * Hp(P_i) + c_i * I + ge_tobytes(&buf->ab[i].b, &tmp2); + sc_add(&sum, &sum, &sig[i].c); + } + hash_to_scalar(buf, rs_comm_size(pubs_count), h); + sc_sub(&h, &h, &sum); + return sc_isnonzero(&h) == 0; + } + +} // namespace crypto diff --git a/crypto/upstream/crypto.h b/crypto/upstream/crypto.h new file mode 100755 index 0000000..95ddc90 --- /dev/null +++ b/crypto/upstream/crypto.h @@ -0,0 +1,333 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#include +#include +#include +#include +#include + +#include "common/pod-class.h" +#include "generic-ops.h" +#include "hash.h" +#include "warnings.h" + +#define CRYPTO_STR_(X) #X +#define CRYPTO_STR(X) CRYPTO_STR_(X) +#define CRYPTO_CHECK_AND_THROW_MES(cond, msg) if (!(cond)) { throw std::runtime_error(msg " @ " __FILE__ ":" CRYPTO_STR(__LINE__)); } + +PUSH_GCC_WARNINGS +DISABLE_CLANG_WARNING(unused-private-field) + + +namespace crypto { + + extern "C" { +#include "random.h" + } + + std::mutex& random_lock_accessor() noexcept; + +#pragma pack(push, 1) + POD_CLASS ec_point { + char data[32]; + }; + + POD_CLASS ec_scalar { + char data[32]; + }; + + POD_CLASS public_key: ec_point { + friend class crypto_ops; + }; + + POD_CLASS secret_key: ec_scalar { + friend class crypto_ops; + }; + + POD_CLASS key_derivation: ec_point { + friend class crypto_ops; + }; + + POD_CLASS key_image: public ec_point { + friend class crypto_ops; + }; + + POD_CLASS signature { + ec_scalar c, r; + friend class crypto_ops; + }; +#pragma pack(pop) + + static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 && + sizeof(public_key) == 32 && sizeof(secret_key) == 32 && + sizeof(key_derivation) == 32 && sizeof(key_image) == 32 && + sizeof(signature) == 64, "Invalid structure size"); + + class crypto_ops { + crypto_ops(); + crypto_ops(const crypto_ops &); + void operator=(const crypto_ops &); + ~crypto_ops(); + + static void generate_keys(public_key &, secret_key &); + friend void generate_keys(public_key &, secret_key &); + static void generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size); + friend void generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size); + static void keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size); + friend void keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size); + static void dependent_key(const secret_key& first, secret_key& second); + friend void dependent_key(const secret_key& first, secret_key& second); + static bool check_key(const public_key &); + friend bool check_key(const public_key &); + static bool secret_key_to_public_key(const secret_key &, public_key &); + friend bool secret_key_to_public_key(const secret_key &, public_key &); + static bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); + friend bool generate_key_derivation(const public_key &, const secret_key &, key_derivation &); + static void derivation_to_scalar(const key_derivation &, size_t, ec_scalar &); + friend void derivation_to_scalar(const key_derivation &, size_t, ec_scalar &); + static bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); + friend bool derive_public_key(const key_derivation &, std::size_t, const public_key &, public_key &); + static void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); + friend void derive_secret_key(const key_derivation &, std::size_t, const secret_key &, secret_key &); + static void generate_signature(const hash &, const public_key &, const secret_key &, signature &); + friend void generate_signature(const hash &, const public_key &, const secret_key &, signature &); + static bool check_signature(const hash &, const public_key &, const signature &); + friend bool check_signature(const hash &, const public_key &, const signature &); + static void generate_key_image(const public_key &, const secret_key &, key_image &); + friend void generate_key_image(const public_key &, const secret_key &, key_image &); + static void generate_ring_signature(const hash &, const key_image &, + const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *); + friend void generate_ring_signature(const hash &, const key_image &, + const public_key *const *, std::size_t, const secret_key &, std::size_t, signature *); + static bool check_ring_signature(const hash &, const key_image &, + const public_key *const *, std::size_t, const signature *); + friend bool check_ring_signature(const hash &, const key_image &, + const public_key *const *, std::size_t, const signature *); + friend bool validate_key_image(const key_image& ki); + static bool validate_key_image(const key_image& ki); + + }; + + // thread-safe version + inline void generate_random_bytes(size_t size, void* p_data) + { + std::lock_guard lock(random_lock_accessor()); + generate_random_bytes_no_lock(size, p_data); + } + + + /* Generate a value filled with random bytes. + */ + template + typename std::enable_if::value, T>::type rand() + { + typename std::remove_cv::type res; + std::lock_guard lock(random_lock_accessor()); + generate_random_bytes_no_lock(sizeof(T), &res); + return res; + } + + /* An adapter, to be used with std::shuffle, etc. + * Uses thread-safe crypto::rand<>(). + */ + struct uniform_random_bit_generator + { + typedef uint64_t result_type; + static CONSTEXPR uint64_t min() { return 0; } + static CONSTEXPR uint64_t max() { return UINT64_MAX; } + uint64_t operator()() { return rand(); } + }; + + + /* Generate a new key pair + */ + inline void generate_keys(public_key &pub, secret_key &sec) { + crypto_ops::generate_keys(pub, sec); + } + + inline void generate_seed_keys(public_key &pub, secret_key &sec, std::vector& keys_seed_binary, size_t keys_seed_binary_size) + { + crypto_ops::generate_seed_keys(pub, sec, keys_seed_binary, keys_seed_binary_size); + } + + inline void keys_from_default(const unsigned char* a_part, public_key &pub, secret_key &sec, size_t keys_seed_binary_size) + { + crypto_ops::keys_from_default(a_part, pub, sec, keys_seed_binary_size); + } + + inline void dependent_key(const secret_key& first, secret_key& second){ + return crypto_ops::dependent_key(first, second); + } + + /* Check a public key. Returns true if it is valid, false otherwise. + */ + inline bool check_key(const public_key &key) { + return crypto_ops::check_key(key); + } + + inline bool validate_key_image(const key_image& ki){ + return crypto_ops::validate_key_image(ki); + } + /* Checks a private key and computes the corresponding public key. + */ + inline bool secret_key_to_public_key(const secret_key &sec, public_key &pub) { + return crypto_ops::secret_key_to_public_key(sec, pub); + } + + /* To generate an ephemeral key used to send money to: + * * The sender generates a new key pair, which becomes the transaction key. The public transaction key is included in "extra" field. + * * Both the sender and the receiver generate key derivation from the transaction key, the receivers' "view" key and the output index. + * * The sender uses key derivation and the receivers' "spend" key to derive an ephemeral public key. + * * The receiver can either derive the public key (to check that the transaction is addressed to him) or the private key (to spend the money). + */ + inline bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) { + return crypto_ops::generate_key_derivation(key1, key2, derivation); + } + inline void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &result) { + crypto::crypto_ops::derivation_to_scalar(derivation, output_index, result); + } + + inline bool derive_public_key(const key_derivation &derivation, std::size_t output_index, + const public_key &base, public_key &derived_key) { + return crypto_ops::derive_public_key(derivation, output_index, base, derived_key); + } + inline void derive_secret_key(const key_derivation &derivation, std::size_t output_index, + const secret_key &base, secret_key &derived_key) { + crypto_ops::derive_secret_key(derivation, output_index, base, derived_key); + } + + /* Generation and checking of a standard signature. + */ + inline void generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) { + crypto_ops::generate_signature(prefix_hash, pub, sec, sig); + } + inline bool check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) { + return crypto_ops::check_signature(prefix_hash, pub, sig); + } + + /* To send money to a key: + * * The sender generates an ephemeral key and includes it in transaction output. + * * To spend the money, the receiver generates a key image from it. + * * Then he selects a bunch of outputs, including the one he spends, and uses them to generate a ring signature. + * To check the signature, it is necessary to collect all the keys that were used to generate it. To detect double spends, it is necessary to check that each key image is used at most once. + */ + inline void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) { + crypto_ops::generate_key_image(pub, sec, image); + } + inline void generate_ring_signature(const hash &prefix_hash, const key_image &image, + const public_key *const *pubs, std::size_t pubs_count, + const secret_key &sec, std::size_t sec_index, + signature *sig) { + crypto_ops::generate_ring_signature(prefix_hash, image, pubs, pubs_count, sec, sec_index, sig); + } + inline bool check_ring_signature(const hash &prefix_hash, const key_image &image, + const public_key *const *pubs, std::size_t pubs_count, + const signature *sig) { + return crypto_ops::check_ring_signature(prefix_hash, image, pubs, pubs_count, sig); + } + + /* Variants with vector parameters. + */ + inline void generate_ring_signature(const hash &prefix_hash, const key_image &image, + const std::vector &pubs, + const secret_key &sec, std::size_t sec_index, + signature *sig) { + generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig); + } + inline bool check_ring_signature(const hash &prefix_hash, const key_image &image, + const std::vector &pubs, + const signature *sig) { + return check_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sig); + } + + class stream_cn_hash + { + public: + static constexpr size_t DATA_BLOCK_SIZE = 1024 * 1024; + + stream_cn_hash() + : m_buffer(HASH_SIZE + DATA_BLOCK_SIZE, '\0') + , m_p_hash(const_cast(reinterpret_cast(m_buffer.data()))) + , m_p_data(const_cast(reinterpret_cast(m_buffer.data())) + HASH_SIZE) + , m_ready(false) + , m_data_used(0) + { + m_ready = true; + } + + bool update(const void* data, size_t size) + { + if (!m_ready) + return false; + + const uint8_t* p_source_data = reinterpret_cast(data); + + while(size > 0) + { + // fill the buffer up + size_t bytes_to_copy = std::min(size, DATA_BLOCK_SIZE - m_data_used); + memcpy(m_p_data + m_data_used, p_source_data, bytes_to_copy); + m_data_used += bytes_to_copy; + p_source_data += bytes_to_copy; + size -= bytes_to_copy; + + if (m_data_used == DATA_BLOCK_SIZE) + { + // calc imtermediate hash of the whole buffer and put the result into the beginning of the buffer + *m_p_hash = cn_fast_hash(m_buffer.data(), HASH_SIZE + m_data_used); + // clear data buffer for new bytes + memset(m_p_data, 0, DATA_BLOCK_SIZE); + m_data_used = 0; + } + + // repeat if there are source bytes left + } + + return true; + } + + hash calculate_hash() + { + if (m_data_used == 0) + return *m_p_hash; + + m_ready = false; + return cn_fast_hash(m_buffer.data(), HASH_SIZE + m_data_used); + } + + private: + const std::string m_buffer; + hash* const m_p_hash; + uint8_t* const m_p_data; + size_t m_data_used; + bool m_ready; + }; // class stream_cn_hash + +} // namespace crypto + +POD_MAKE_HASHABLE(crypto, public_key) +POD_MAKE_LESS_OPERATOR(crypto, public_key) +POD_MAKE_COMPARABLE(crypto, secret_key) +POD_MAKE_HASHABLE(crypto, key_image) +POD_MAKE_COMPARABLE(crypto, signature) +POD_MAKE_COMPARABLE(crypto, key_derivation) +POD_MAKE_LESS_OPERATOR(crypto, hash) +POD_MAKE_LESS_OPERATOR(crypto, key_image) +POP_GCC_WARNINGS diff --git a/crypto/upstream/crypto/crypto-ops.h b/crypto/upstream/crypto/crypto-ops.h new file mode 120000 index 0000000..01087ca --- /dev/null +++ b/crypto/upstream/crypto/crypto-ops.h @@ -0,0 +1 @@ +../crypto-ops.h \ No newline at end of file diff --git a/crypto/upstream/eth_signature.cpp b/crypto/upstream/eth_signature.cpp new file mode 100755 index 0000000..d6e7193 --- /dev/null +++ b/crypto/upstream/eth_signature.cpp @@ -0,0 +1,417 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#include "eth_signature.h" +#include "crypto.h" +#ifndef USE_OPEN_SSL_FOR_ECDSA + #include "bitcoin-secp256k1/include/secp256k1.h" +#endif +#include "random.h" +#include "misc_language.h" +#include + + +#ifdef USE_OPEN_SSL_FOR_ECDSA + #include + #include + #include + #include + #include +#endif + + +// Function to create EC_KEY from raw 32 - byte private key +EC_KEY * create_ec_key_from_private_key(const unsigned char* private_key) { + EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1); + if (!key) { + std::cerr << "Failed to create new EC Key" << std::endl; + return nullptr; + } + + BIGNUM* priv_key_bn = BN_bin2bn(private_key, 32, nullptr); + if (!priv_key_bn) { + std::cerr << "Failed to convert private key to BIGNUM" << std::endl; + EC_KEY_free(key); + return nullptr; + } + + if (!EC_KEY_set_private_key(key, priv_key_bn)) { + std::cerr << "Failed to set private key" << std::endl; + EC_KEY_free(key); + BN_free(priv_key_bn); + return nullptr; + } + + BN_free(priv_key_bn); + return key; +} + + +void ensure_canonical_s(BIGNUM* s, const EC_GROUP* group) { + // Get the order of the curve + BIGNUM* order = BN_new(); + EC_GROUP_get_order(group, order, nullptr); + + // Compute half of the order: `n / 2` + BIGNUM* half_order = BN_new(); + BN_rshift1(half_order, order); + + // If `s` is greater than `n / 2`, replace `s` with `n - s` + if (BN_cmp(s, half_order) > 0) { + BN_sub(s, order, s); + } + + BN_free(order); + BN_free(half_order); +} + +// Update the function to ensure canonical `s` +bool generate_ethereum_signature(const unsigned char* hash, const unsigned char* private_key, crypto::eth_signature& sig_res) { + EC_KEY* ec_key = create_ec_key_from_private_key(private_key); + if (!ec_key) { + throw std::runtime_error("Failed to create EC key from private key"); + } + + // Sign the hash + unsigned int sig_len = ECDSA_size(ec_key); + std::vector signature(sig_len); + if (ECDSA_sign(0, hash, 32, signature.data(), &sig_len, ec_key) == 0) { + EC_KEY_free(ec_key); + throw std::runtime_error("Failed to create signature"); + } + signature.resize(sig_len); + + + // The OpenSSL ECDSA signature output is DER encoded, Ethereum expects (r, s, v) + const unsigned char* p = signature.data(); + ECDSA_SIG* sig = d2i_ECDSA_SIG(nullptr, &p, sig_len); + if (!sig) { + EC_KEY_free(ec_key); + throw std::runtime_error("Failed to parse ECDSA signature"); + } + + const BIGNUM* r = nullptr; + const BIGNUM* s = nullptr; + ECDSA_SIG_get0(sig, &r, &s); + + // Ensure canonical `s` + BIGNUM* s_canonical = BN_dup(s); + ensure_canonical_s(s_canonical, EC_KEY_get0_group(ec_key)); + + BN_bn2binpad(r, (unsigned char* )&sig_res.data[0], 32); + BN_bn2binpad(s_canonical, (unsigned char*)&sig_res.data[32], 32); + + + ECDSA_SIG_free(sig); + BN_free(s_canonical); + EC_KEY_free(ec_key); + return true; +} + +// Convert raw 33-byte compressed public key to EC_KEY object +EC_KEY* create_ec_key_from_compressed_public_key(const unsigned char* compressed_pub_key) { + EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1); + if (!key) { + std::cerr << "Failed to create EC_KEY object" << std::endl; + return nullptr; + } + + EC_POINT* pub_point = EC_POINT_new(EC_KEY_get0_group(key)); + if (!EC_POINT_oct2point(EC_KEY_get0_group(key), pub_point, compressed_pub_key, 33, nullptr)) { + std::cerr << "Failed to convert compressed public key" << std::endl; + EC_POINT_free(pub_point); + EC_KEY_free(key); + return nullptr; + } + + if (!EC_KEY_set_public_key(key, pub_point)) { + std::cerr << "Failed to set public key" << std::endl; + EC_POINT_free(pub_point); + EC_KEY_free(key); + return nullptr; + } + + EC_POINT_free(pub_point); + return key; +} + +// Function to verify Ethereum-compatible signature +bool verify_ethereum_signature(const crypto::hash& m, const crypto::eth_signature& sig_res, const crypto::eth_public_key& compressed_pub_key) { + EC_KEY* ec_key = create_ec_key_from_compressed_public_key((const unsigned char*)&compressed_pub_key.data[0]); + if (!ec_key) { + throw std::runtime_error("Failed to create EC key from compressed public key"); + } + const unsigned char* r = (unsigned char*)&sig_res.data[0]; + const unsigned char* s = (unsigned char*)&sig_res.data[32]; + const unsigned char* hash = (unsigned char*)&m; + + // Create ECDSA_SIG from r and s + BIGNUM* bn_r = BN_bin2bn(r, 32, nullptr); + BIGNUM* bn_s = BN_bin2bn(s, 32, nullptr); + if (!bn_r || !bn_s) { + EC_KEY_free(ec_key); + BN_free(bn_r); + BN_free(bn_s); + throw std::runtime_error("Failed to convert r or s to BIGNUM"); + } + + ECDSA_SIG* sig = ECDSA_SIG_new(); + if (!sig) { + EC_KEY_free(ec_key); + BN_free(bn_r); + BN_free(bn_s); + throw std::runtime_error("Failed to create ECDSA_SIG object"); + } + + if (!ECDSA_SIG_set0(sig, bn_r, bn_s)) { + EC_KEY_free(ec_key); + ECDSA_SIG_free(sig); + BN_free(bn_r); + BN_free(bn_s); + throw std::runtime_error("Failed to set r and s in ECDSA_SIG"); + } + + // Verify the signature + int verification_result = ECDSA_do_verify(hash, 32, sig, ec_key); + + ECDSA_SIG_free(sig); + EC_KEY_free(ec_key); + + + return verification_result == 1; +} + + +// +// struct KeyPair { +// std::vector private_key; // 32 bytes +// std::vector public_key; // 33 bytes (compressed format) +// }; + +// Function to generate an Ethereum-compatible key pair +bool generate_ethereum_key_pair(crypto::eth_secret_key& sec_key, crypto::eth_public_key& pub_key) { + /*KeyPair keypair;*/ + + // Create a new EC_KEY object with the secp256k1 curve + EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1); + if (!key) { + throw std::runtime_error("Failed to create new EC_KEY object"); + } + + // Generate the key pair + if (EC_KEY_generate_key(key) == 0) { + EC_KEY_free(key); + throw std::runtime_error("Failed to generate key pair"); + } + + // Extract the private key + const BIGNUM* priv_bn = EC_KEY_get0_private_key(key); + if (!priv_bn) { + EC_KEY_free(key); + throw std::runtime_error("Failed to get private key"); + } + + BN_bn2binpad(priv_bn, (unsigned char*)&sec_key.data[0], 32); + + // Extract the public key in compressed format + const EC_POINT* pub_point = EC_KEY_get0_public_key(key); + if (!pub_point) { + EC_KEY_free(key); + throw std::runtime_error("Failed to get public key"); + } + + //keypair.public_key.resize(33); // Compressed format + if (EC_POINT_point2oct(EC_KEY_get0_group(key), pub_point, POINT_CONVERSION_COMPRESSED, + (unsigned char*)&pub_key.data[0], sizeof(pub_key.data), nullptr) == 0) { + EC_KEY_free(key); + throw std::runtime_error("Failed to convert public key to compressed format"); + } + + EC_KEY_free(key); + return true; +} + + + + + +namespace crypto +{ + bool generate_eth_key_pair(eth_secret_key& sec_key, eth_public_key& pub_key) noexcept + { + try + { +#ifndef USE_OPEN_SSL_FOR_ECDSA + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + auto slh = epee::misc_utils::create_scope_leave_handler([&ctx](){ + secp256k1_context_destroy(ctx); + ctx = nullptr; + }); + + uint8_t randomness[32]; + crypto::generate_random_bytes(sizeof randomness, randomness); + if (!secp256k1_context_randomize(ctx, randomness)) + return false; + + for(size_t i = 1024; i != 0; --i) + { + crypto::generate_random_bytes(sizeof sec_key, sec_key.data); + if (secp256k1_ec_seckey_verify(ctx, sec_key.data)) + break; + if (i == 1) + return false; + } + + secp256k1_pubkey uncompressed_pub_key{}; + if (!secp256k1_ec_pubkey_create(ctx, &uncompressed_pub_key, sec_key.data)) + return false; + + size_t output_len = sizeof pub_key; + if (!secp256k1_ec_pubkey_serialize(ctx, pub_key.data, &output_len, &uncompressed_pub_key, SECP256K1_EC_COMPRESSED)) + return false; + + return true; +#else + return generate_ethereum_key_pair(sec_key, pub_key); +#endif + } + catch(...) + { + return false; + } + } + +#ifndef USE_OPEN_SSL_FOR_ECDSA + bool eth_secret_key_to_public_key(const eth_secret_key& sec_key, eth_public_key& pub_key) noexcept + { + try + { + // TODO: do we need this? consider using static context + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + auto slh = epee::misc_utils::create_scope_leave_handler([&ctx](){ + secp256k1_context_destroy(ctx); + ctx = nullptr; + }); + + secp256k1_pubkey uncompressed_pub_key{}; + if (!secp256k1_ec_pubkey_create(ctx, &uncompressed_pub_key, sec_key.data)) + return false; + + size_t output_len = sizeof pub_key; + if (!secp256k1_ec_pubkey_serialize(ctx, pub_key.data, &output_len, &uncompressed_pub_key, SECP256K1_EC_COMPRESSED)) + return false; + + return true; + } + catch(...) + { + return false; + } + } +#endif + // generates secp256k1 ECDSA signature + bool generate_eth_signature(const hash& m, const eth_secret_key& sec_key, eth_signature& sig) noexcept + { + try + { +#ifndef USE_OPEN_SSL_FOR_ECDSA + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + auto slh = epee::misc_utils::create_scope_leave_handler([&ctx](){ + secp256k1_context_destroy(ctx); + ctx = nullptr; + }); + + uint8_t randomness[32]; + crypto::generate_random_bytes(sizeof randomness, randomness); + if (!secp256k1_context_randomize(ctx, randomness)) + return false; + + secp256k1_ecdsa_signature secp256k1_ecdsa_sig{}; + if (!secp256k1_ecdsa_sign(ctx, &secp256k1_ecdsa_sig, (const unsigned char*)m.data, sec_key.data, NULL, NULL)) + return false; + + if (!secp256k1_ecdsa_signature_serialize_compact(ctx, sig.data, &secp256k1_ecdsa_sig)) + return false; + + return true; +#else + return generate_ethereum_signature((const unsigned char*)&m.data, (unsigned char*)&sec_key.data, sig); +#endif + } + catch(...) + { + return false; + } + } + + // verifies secp256k1 ECDSA signature + bool verify_eth_signature(const hash& m, const eth_public_key& pub_key, const eth_signature& sig) noexcept + { + try + { + // TODO (performance) consider using secp256k1_context_static for verification -- sowle +#ifndef USE_OPEN_SSL_FOR_ECDSA + secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_NONE); + auto slh = epee::misc_utils::create_scope_leave_handler([&ctx](){ + secp256k1_context_destroy(ctx); + ctx = nullptr; + }); + + uint8_t randomness[32]; + crypto::generate_random_bytes(sizeof randomness, randomness); + if (!secp256k1_context_randomize(ctx, randomness)) + return false; + + secp256k1_ecdsa_signature secp256k1_ecdsa_sig{}; + secp256k1_pubkey uncompressed_pub_key{}; + + if (!secp256k1_ecdsa_signature_parse_compact(ctx, &secp256k1_ecdsa_sig, sig.data)) + return false; + + if (!secp256k1_ec_pubkey_parse(ctx, &uncompressed_pub_key, pub_key.data, sizeof pub_key)) + return false; + + // verify a signature + if (!secp256k1_ecdsa_verify(ctx, &secp256k1_ecdsa_sig, (const unsigned char*)m.data, &uncompressed_pub_key)) + return false; + + return true; +#else + return verify_ethereum_signature(m, sig, pub_key); +#endif + } + catch(...) + { + return false; + } + } + + std::ostream& operator<<(std::ostream& o, const eth_secret_key& v) + { + return o << epee::string_tools::pod_to_hex(v); + } + + std::ostream& operator<<(std::ostream& o, const eth_public_key& v) + { + return o << epee::string_tools::pod_to_hex(v); + } + std::ostream& operator<<(std::ostream& o, const eth_signature& v) + { + return o << epee::string_tools::pod_to_hex(v); + } + + +} // namespace crypto diff --git a/crypto/upstream/eth_signature.h b/crypto/upstream/eth_signature.h new file mode 100755 index 0000000..b412e96 --- /dev/null +++ b/crypto/upstream/eth_signature.h @@ -0,0 +1,80 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once +#include +#include +#include "hash.h" + +namespace crypto +{ + + // secp256k1 public key in serialized (compressed) form that is used in Etherium + struct eth_public_key + { + uint8_t data[33]; + }; + + // secp256k1 secret key + struct eth_secret_key + { + uint8_t data[32]; + }; + + // secp256k1 ECDSA signature is serialized (compressed) form that is used in Etherium + struct eth_signature + { + uint8_t data[64]; + }; + + // generates secp256k1 keypair + bool generate_eth_key_pair(eth_secret_key& sec_key, eth_public_key& pub_key) noexcept; + + // converts eth_secret_key to eth_public_key + //bool _eth_secret_key_to_public_key(const eth_secret_key& sec_key, eth_public_key& pub_key) noexcept; + + // generates secp256k1 ECDSA signature + bool generate_eth_signature(const hash& m, const eth_secret_key& sec_key, eth_signature& sig) noexcept; + + // verifies secp256k1 ECDSA signature + bool verify_eth_signature(const hash& m, const eth_public_key& pub_key, const eth_signature& sig) noexcept; + + + inline bool operator==(const eth_public_key& lhs, const eth_public_key& rhs) + { + return memcmp(lhs.data, rhs.data, sizeof lhs.data) == 0; + } + + inline bool operator!=(const eth_public_key& lhs, const eth_public_key& rhs) + { + return !(lhs == rhs); + } + + inline bool operator==(const eth_secret_key& lhs, const eth_secret_key& rhs) + { + return memcmp(lhs.data, rhs.data, sizeof lhs.data) == 0; + } + + inline bool operator!=(const eth_secret_key& lhs, const eth_secret_key& rhs) + { + return !(lhs == rhs); + } + + std::ostream& operator<<(std::ostream& o, const eth_secret_key& v); + std::ostream& operator<<(std::ostream& o, const eth_public_key& v); + std::ostream& operator<<(std::ostream& o, const eth_signature& v); + +} // namespace crypto diff --git a/crypto/upstream/generic-ops.h b/crypto/upstream/generic-ops.h new file mode 100755 index 0000000..430619a --- /dev/null +++ b/crypto/upstream/generic-ops.h @@ -0,0 +1,71 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#include +#include +#include + +#define POD_MAKE_COMPARABLE(space, type) \ +namespace space { \ + inline bool operator==(const type &_v1, const type &_v2) { \ + return std::memcmp(&_v1, &_v2, sizeof(type)) == 0; \ + } \ + inline bool operator!=(const type &_v1, const type &_v2) { \ + return std::memcmp(&_v1, &_v2, sizeof(type)) != 0; \ + } \ +} + +#define POD_MAKE_LESS_OPERATOR(space, type) \ +namespace space { \ + inline bool operator<(const type &_v1, const type &_v2) { \ + return std::memcmp(&_v1, &_v2, sizeof(type)) < 0; \ + } \ +} + +#define POD_MAKE_HASHABLE(space, type) \ + POD_MAKE_COMPARABLE(space, type) \ +namespace space { \ + static_assert(sizeof(std::size_t) <= sizeof(type), "Size of " #type " must be at least that of size_t"); \ + inline std::size_t hash_value(const type &_v) { \ + return reinterpret_cast(_v); \ + } \ +} \ +namespace std { \ + template<> \ + struct hash { \ + std::size_t operator()(const space::type &_v) const { \ + return reinterpret_cast(_v); \ + } \ + }; \ +} + +// +// CONSTEXPR +// +#if ( defined(_MSC_VER) && (_MSC_VER < 1800) ) + #error MS compilers prior to v 18.00 (MSVC 2013) are not supported +#endif + +// compilation workaround for MSVC 2013 Update 5 wich does not support constexpr +#if ( defined(_MSC_VER) && (1800 <= _MSC_VER) && (_MSC_VER < 1900) ) + #define CONSTEXPR +#else // all other platforms or MSVC 2015 and later + #define CONSTEXPR constexpr +#endif + diff --git a/crypto/upstream/hash-ops.h b/crypto/upstream/hash-ops.h new file mode 100755 index 0000000..854846e --- /dev/null +++ b/crypto/upstream/hash-ops.h @@ -0,0 +1,76 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#if !defined(__cplusplus) + +#include +#include +#include +#include + +#include "common/int-util.h" +#include "warnings.h" + +static inline void *padd(void *p, size_t i) { + return (char *) p + i; +} + +static inline const void *cpadd(const void *p, size_t i) { + return (const char *) p + i; +} + +PUSH_VS_WARNINGS +DISABLE_VS_WARNINGS(4267) +static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t must be 4 or 8 bytes long"); +static inline void place_length(uint8_t *buffer, size_t bufsize, size_t length) { + if (sizeof(size_t) == 4) { + *(uint32_t *) padd(buffer, bufsize - 4) = swap32be(length); + } else { + *(uint64_t *) padd(buffer, bufsize - 8) = swap64be(length); + } +} +POP_VS_WARNINGS + +#pragma pack(push, 1) +union hash_state { + uint8_t b[200]; + uint64_t w[25]; +}; +#pragma pack(pop) +static_assert(sizeof(union hash_state) == 200, "Invalid structure size"); + +void hash_permutation(union hash_state *state); +void hash_process(union hash_state *state, const uint8_t *buf, size_t count); + +#endif + + +#define HASH_SIZE 32 +#define HASH_DATA_AREA 136 + + +void cn_fast_hash_old(const void *data, size_t length, char *hash); +void cn_fast_hash(const void *data, size_t length, char *hash); + +void hash_extra_blake(const void *data, size_t length, char *hash); +void hash_extra_groestl(const void *data, size_t length, char *hash); +void hash_extra_jh(const void *data, size_t length, char *hash); +void hash_extra_skein(const void *data, size_t length, char *hash); + +void tree_hash(const char (*hashes)[HASH_SIZE], size_t count, char *root_hash); diff --git a/crypto/upstream/hash.c b/crypto/upstream/hash.c new file mode 100755 index 0000000..4520346 --- /dev/null +++ b/crypto/upstream/hash.c @@ -0,0 +1,43 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#include +#include +#include + +#include "hash-ops.h" +#include "keccak.h" + +void hash_permutation(union hash_state *state) { + keccakf((uint64_t*)state, 24); +} + +void hash_process(union hash_state *state, const uint8_t *buf, size_t count) { + keccak1600(buf, (int)count, (uint8_t*)state); +} + +void cn_fast_hash_old(const void *data, size_t length, char *hash) +{ + union hash_state state; + hash_process(&state, data, length); + memcpy(hash, &state, HASH_SIZE); +} + +void cn_fast_hash(const void *data, size_t length, char *hash) +{ + keccak(data, (int)length, (uint8_t*)hash, HASH_SIZE); +} diff --git a/crypto/upstream/hash.h b/crypto/upstream/hash.h new file mode 100755 index 0000000..41faad9 --- /dev/null +++ b/crypto/upstream/hash.h @@ -0,0 +1,69 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#include + +#include "common/pod-class.h" +#include "generic-ops.h" +#include "warnings.h" +PUSH_VS_WARNINGS +DISABLE_VS_WARNINGS(4804) +#include "blake2.h" +POP_VS_WARNINGS +namespace crypto { + + extern "C" { +#include "hash-ops.h" + } + +#pragma pack(push, 1) + POD_CLASS hash { + char data[HASH_SIZE]; + }; +#pragma pack(pop) + + static_assert(sizeof(hash) == HASH_SIZE, "Invalid structure size"); + + /* + Cryptonight hash functions + */ + + inline void cn_fast_hash(const void *data, std::size_t length, hash &hash) { + cn_fast_hash(data, length, reinterpret_cast(&hash)); + } + + inline hash cn_fast_hash(const void *data, std::size_t length) { + hash h; + cn_fast_hash(data, length, reinterpret_cast(&h)); + return h; + } + + inline void tree_hash(const hash *hashes, std::size_t count, hash &root_hash) { + tree_hash(reinterpret_cast(hashes), count, reinterpret_cast(&root_hash)); + } + + inline hash blake2_hash(const void *data, std::size_t length) { + hash h; + blake2(&h, sizeof(h), data, length, nullptr, 0); + return h; + } + +} + +POD_MAKE_HASHABLE(crypto, hash) diff --git a/crypto/upstream/initializer.h b/crypto/upstream/initializer.h new file mode 100755 index 0000000..a84bcf3 --- /dev/null +++ b/crypto/upstream/initializer.h @@ -0,0 +1,45 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#if defined(__GNUC__) +#define INITIALIZER(name) __attribute__((constructor(101))) static void name(void) +#define FINALIZER(name) __attribute__((destructor(101))) static void name(void) +#define REGISTER_FINALIZER(name) ((void) 0) + +#elif defined(_MSC_VER) +#include +#include +// http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc +// http://msdn.microsoft.com/en-us/library/bb918180.aspx +#pragma section(".CRT$XCT", read) +#define INITIALIZER(name) \ + static void __cdecl name(void); \ + __declspec(allocate(".CRT$XCT")) void (__cdecl *const _##name)(void) = &name; \ + static void __cdecl name(void) +#define FINALIZER(name) \ + static void __cdecl name(void) +#define REGISTER_FINALIZER(name) \ + do { \ + int _res = atexit(name); \ + assert(_res == 0); \ + } while (0); + +#else +#error Unsupported compiler +#endif diff --git a/crypto/upstream/keccak.c b/crypto/upstream/keccak.c new file mode 100755 index 0000000..857c6e3 --- /dev/null +++ b/crypto/upstream/keccak.c @@ -0,0 +1,129 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +// keccak.c +// 19-Nov-11 Markku-Juhani O. Saarinen +// A baseline Keccak (3rd round) implementation. + +#include "hash-ops.h" +#include "keccak.h" + +const uint64_t keccakf_rndc[24] = +{ + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 +}; + +const int keccakf_rotc[24] = +{ + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +}; + +const int keccakf_piln[24] = +{ + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +}; + +// update the state with given number of rounds + +void keccakf(uint64_t st[25], int rounds) +{ + int i, j, round; + uint64_t t, bc[5]; + + for (round = 0; round < rounds; round++) { + + // Theta + for (i = 0; i < 5; i++) + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + + for (i = 0; i < 5; i++) { + t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); + for (j = 0; j < 25; j += 5) + st[j + i] ^= t; + } + + // Rho Pi + t = st[1]; + for (i = 0; i < 24; i++) { + j = keccakf_piln[i]; + bc[0] = st[j]; + st[j] = ROTL64(t, keccakf_rotc[i]); + t = bc[0]; + } + + // Chi + for (j = 0; j < 25; j += 5) { + for (i = 0; i < 5; i++) + bc[i] = st[j + i]; + for (i = 0; i < 5; i++) + st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + + // Iota + st[0] ^= keccakf_rndc[round]; + } +} + +// compute a keccak hash (md) of given byte length from "in" +typedef uint64_t state_t[25]; + +int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen) +{ + state_t st; + uint8_t temp[144]; + int i, rsiz, rsizw; + + rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen; + rsizw = rsiz / 8; + + memset(st, 0, sizeof(st)); + + for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) { + for (i = 0; i < rsizw; i++) + st[i] ^= ((uint64_t *) in)[i]; + keccakf(st, KECCAK_ROUNDS); + } + + // last block and padding + memcpy(temp, in, inlen); + temp[inlen++] = 1; + memset(temp + inlen, 0, rsiz - inlen); + temp[rsiz - 1] |= 0x80; + + for (i = 0; i < rsizw; i++) + st[i] ^= ((uint64_t *) temp)[i]; + + keccakf(st, KECCAK_ROUNDS); + + memcpy(md, st, mdlen); + + return 0; +} + +void keccak1600(const uint8_t *in, int inlen, uint8_t *md) +{ + keccak(in, inlen, md, sizeof(state_t)); +} diff --git a/crypto/upstream/keccak.h b/crypto/upstream/keccak.h new file mode 100755 index 0000000..3842a06 --- /dev/null +++ b/crypto/upstream/keccak.h @@ -0,0 +1,43 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +// keccak.h +// 19-Nov-11 Markku-Juhani O. Saarinen + +#ifndef KECCAK_H +#define KECCAK_H + +#include +#include + +#ifndef KECCAK_ROUNDS +#define KECCAK_ROUNDS 24 +#endif + +#ifndef ROTL64 +#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) +#endif + +// compute a keccak hash (md) of given byte length from "in" +int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen); + +// update the state +void keccakf(uint64_t st[25], int norounds); + +void keccak1600(const uint8_t *in, int inlen, uint8_t *md); + +#endif diff --git a/crypto/upstream/msm.cpp b/crypto/upstream/msm.cpp new file mode 100755 index 0000000..74abf8b --- /dev/null +++ b/crypto/upstream/msm.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#include "epee/include/misc_log_ex.h" +//#include "zarcanum.h" +#include "msm.h" +//#include "../currency_core/crypto_config.h" // TODO: move it to the crypto +//#include "../common/crypto_stream_operators.h" // TODO: move it to the crypto + +#if 0 +# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl +# define DBG_PRINT(x) std::cout << x << std::endl +#else +# define DBG_VAL_PRINT(x) (void(0)) +# define DBG_PRINT(x) (void(0)) +#endif + +namespace crypto +{ + + + +} // namespace crypto diff --git a/crypto/upstream/msm.h b/crypto/upstream/msm.h new file mode 100755 index 0000000..f58ae6f --- /dev/null +++ b/crypto/upstream/msm.h @@ -0,0 +1,185 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once + +// This file contains Multi-Scalar Multiplication routines + +#include "epee/include/misc_log_ex.h" +#include "crypto-sugar.h" + +namespace crypto +{ + + template + bool msm_and_check_zero_naive(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand) + { + CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized"); + CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized"); + + point_t result = summand; + + for (size_t i = 0; i < g_scalars.size(); ++i) + result += g_scalars[i] * CT::get_generator(false, i); + + for (size_t i = 0; i < h_scalars.size(); ++i) + result += h_scalars[i] * CT::get_generator(true, i); + + if (!result.is_zero()) + { + LOG_PRINT_L0("msm result is non zero: " << result); + return false; + } + return true; + } + + + // https://eprint.iacr.org/2022/999.pdf + // "Pippenger algorithm [1], and its variant that is widely used in the ZK space is called the bucket method" + template + bool msm_and_check_zero_pippenger_v3(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, uint8_t c) + { + // TODO: with c = 8 and with direct access got much worse result than with c = 7 and get_bits() for N = 128..256, consider checking again for bigger datasets (N>256) + // TODO: consider preparing a cached generators' points + + CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized"); + CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized"); + CHECK_AND_ASSERT_MES(c < 10, false, "c is too big"); + + size_t C = 1ull << c; + + // k_max * c + (c-1) >= max_bit_idx + // + // max_bit_idx - (c - 1) max_bit_idx - (c - 1) + (c - 1) max_bit_idx + // k_max = ceil ( --------------------- ) = floor ( ------------------------------ ) = floor ( ----------- ) + // c c c + const size_t b = 253; // the maximum number of bits in x https://eprint.iacr.org/2022/999.pdf TODO: we may also scan for maximum bit used in all the scalars if all the scalars are small + const size_t max_bit_idx = b - 1; + const size_t k_max = max_bit_idx / c; + const size_t K = k_max + 1; + + std::vector buckets(C * K); + std::vector buckets_inited(C * K); + std::vector Sk(K); + std::vector Sk_inited(K); + std::vector Gk(K); + std::vector Gk_inited(K); + + // first loop, calculate partial bucket sums + for (size_t n = 0; n < g_scalars.size(); ++n) + { + for (size_t k = 0; k < K; ++k) + { + uint64_t l = g_scalars[n].get_bits((uint8_t)(k * c), c); // l in [0; 2^c-1] + if (l != 0) + { + size_t bucket_id = l * K + k; + if (buckets_inited[bucket_id]) + buckets[bucket_id] += CT::get_generator(false, n); + else + { + buckets[bucket_id] = CT::get_generator(false, n); + buckets_inited[bucket_id] = true; + } + } + } + } + // still the first loop (continued) + for (size_t n = 0; n < h_scalars.size(); ++n) + { + for (size_t k = 0; k < K; ++k) + { + uint64_t l = h_scalars[n].get_bits((uint8_t)(k * c), c); // l in [0; 2^c-1] + if (l != 0) + { + size_t bucket_id = l * K + k; + if (buckets_inited[bucket_id]) + buckets[bucket_id] += CT::get_generator(true, n); + else + { + buckets[bucket_id] = CT::get_generator(true, n); + buckets_inited[bucket_id] = true; + } + } + } + } + + // the second loop + for (size_t l = C - 1; l > 0; --l) + { + for (size_t k = 0; k < K; ++k) + { + size_t bucket_id = l * K + k; + if (buckets_inited[bucket_id]) + { + if (Sk_inited[k]) + Sk[k] += buckets[bucket_id]; + else + { + Sk[k] = buckets[bucket_id]; + Sk_inited[k] = true; + } + } + + if (Sk_inited[k]) + { + if (Gk_inited[k]) + Gk[k] += Sk[k]; + else + { + Gk[k] = Sk[k]; + Gk_inited[k] = true; + } + } + } + } + + // the third loop: Horner’s rule + point_t result = Gk_inited[K - 1] ? Gk[K - 1] : c_point_0; + for (size_t k = K - 2; k != SIZE_MAX; --k) + { + result.modify_mul_pow_2(c); + if (Gk_inited[k]) + result += Gk[k]; + } + + result += summand; + + if (!result.is_zero()) + { + LOG_PRINT_L0("multiexp result is non zero: " << result); + return false; + } + + return true; + } + + + + + + // Just switcher + + template + bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand) + { + //return msm_and_check_zero_naive(g_scalars, h_scalars, summand); + return msm_and_check_zero_pippenger_v3(g_scalars, h_scalars, summand, 7); + } + + + +} // namespace crypto diff --git a/crypto/upstream/one_out_of_many_proofs.cpp b/crypto/upstream/one_out_of_many_proofs.cpp new file mode 100755 index 0000000..89028f2 --- /dev/null +++ b/crypto/upstream/one_out_of_many_proofs.cpp @@ -0,0 +1,336 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#include "one_out_of_many_proofs.h" +#include "../currency_core/crypto_config.h" +#include "config/currency_config.h" // for static asset checks +#include "epee/include/misc_log_ex.h" + +//DISABLE_GCC_AND_CLANG_WARNING(unused-function) + +#if 0 +# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl +# define DBG_PRINT(x) std::cout << x << std::endl +#else +# define DBG_VAL_PRINT(x) (void(0)) +# define DBG_PRINT(x) (void(0)) +#endif + +namespace crypto +{ + static const size_t N_max = 256; + static const size_t mn_max = 16; + + static_assert(CURRENCY_TX_MAX_ALLOWED_INPUTS <= N_max, "CURRENCY_TX_MAX_ALLOWED_INPUTS is inconsistent with one-out-of-many proof limits"); // TODO: consider moving this check out -- sowle + + const point_t& get_BGE_generator(size_t index, bool& ok) + { + static std::vector precalculated_generators; + if (precalculated_generators.empty()) + { + precalculated_generators.resize(mn_max * 2); + + scalar_t hash_buf[2] = { hash_helper_t::hs("Lethean BGE generator"), 0 }; + + for(size_t i = 0; i < precalculated_generators.size(); ++i) + { + hash_buf[1].m_u64[0] = i; + precalculated_generators[i] = hash_helper_t::hp(&hash_buf, sizeof hash_buf); + } + } + + if (index >= mn_max * 2) + { + ok = false; + return c_point_0; + } + + ok = true; + return precalculated_generators[index]; + } + + + + +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("generate_BGE_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + bool generate_BGE_proof(const hash& context_hash, const std::vector& ring, const scalar_t& secret, const size_t secret_index, BGE_proof& result, uint8_t* p_err /* = nullptr */) + { + static constexpr size_t n = 4; // TODO: @#@# move it out + + DBG_PRINT(" - - - generate_BGE_proof - - -"); + size_t ring_size = ring.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ring_size > 0, 0); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(secret_index < ring_size, 1); + +#ifndef NDEBUG + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ring[secret_index] == secret * crypto::c_point_X, 2); +#endif + + + const size_t m = std::max(static_cast(1), constexpr_ceil_log_n(ring_size, n)); + const size_t N = constexpr_pow(m, n); + const size_t mn = m * n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(N <= N_max, 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(mn <= mn_max, 4); + + scalar_mat_t a_mat(mn); // m x n matrix + a_mat.zero(); + std::vector l_digits(m); // l => n-ary gidits + size_t l = secret_index; + for(size_t j = 0; j < m; ++j) + { + for(size_t i = n - 1; i != 0; --i) // [n - 1; 1] + { + a_mat(j, i).make_random(); + a_mat(j, 0) -= a_mat(j, i); // a[j; 0] = -sum( a[j; i] ), i in [1; n-1] + } + + size_t digit = l % n; // j-th digit of secret_index + l_digits[j] = digit; + l = l / n; + } + +#ifndef NDEBUG + for(size_t j = 0; j < m; ++j) + { + scalar_t a_sum{}; + for(size_t i = 0; i != n; ++i) + a_sum += a_mat(j, i); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(a_sum.is_zero(), 230); + } +#endif + + // + // coeffs calculation (naive implementation, consider optimization in future) + // + scalar_vec_t coeffs(N * m); // m x N matrix + coeffs.zero(); + for(size_t i = 0; i < N; ++i) + { + coeffs[i] = c_scalar_1; // first row is (1, ..., 1) + size_t i_tmp = i; + size_t m_bound = 1; + for(size_t j = 0; j < m; ++j) + { + size_t i_j = i_tmp % n; // j-th digit of i + i_tmp /= n; + + if (i_j == l_digits[j]) // true if j-th digits of i and l matches + { + scalar_t carry{}; + for(size_t k = 0; k < m_bound; ++k) + { + scalar_t old = coeffs[k * N + i]; + coeffs[k * N + i] *= a_mat(j, i_j); + coeffs[k * N + i] += carry; + carry = old; + } + if (m_bound < m) + coeffs[m_bound * N + i] += carry; + ++m_bound; + } + else + { + for(size_t k = 0; k < m_bound; ++k) + coeffs[k * N + i] *= a_mat(j, i_j); + } + } + } + + scalar_t r_A = scalar_t::random(); + scalar_t r_B = scalar_t::random(); + scalar_vec_t ro(m); + ro.make_random(); + + point_t A = c_point_0; + point_t B = c_point_0; + + result.Pk.clear(); + + bool r = false, r2 = false; + for(size_t j = 0; j < m; ++j) + { + for(size_t i = 0; i < n; ++i) + { + const point_t& gen_1 = get_BGE_generator((j * n + i) * 2 + 0, r); + const point_t& gen_2 = get_BGE_generator((j * n + i) * 2 + 1, r2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(r && r2, 5); + const scalar_t& a = a_mat(j, i); + A += a * gen_1 - a * a * gen_2; + if (l_digits[j] == i) + B += gen_1 - a * gen_2; + else + B += a * gen_2; + } + + point_t Pk = c_point_0; + for(size_t i = 0; i < ring_size; ++i) + Pk += coeffs[j * N + i] * ring[i]; + for(size_t i = ring_size; i < N; ++i) + Pk += coeffs[j * N + i] * ring[ring_size - 1]; + + Pk += ro[j] * c_point_X; + result.Pk.emplace_back(std::move((c_scalar_1div8 * Pk).to_public_key())); + } + + A += r_A * c_point_X; + result.A = (c_scalar_1div8 * A).to_public_key(); + B += r_B * c_point_X; + result.B = (c_scalar_1div8 * B).to_public_key(); + + hash_helper_t::hs_t hsc(1 + ring_size + 2 + m); + hsc.add_hash(context_hash); + for(auto& ring_el : ring) + hsc.add_point(c_scalar_1div8 * ring_el); + hsc.add_pub_key(result.A); + hsc.add_pub_key(result.B); + hsc.add_pub_keys_array(result.Pk); + scalar_t x = hsc.calc_hash(); + DBG_VAL_PRINT(x); + + result.f.resize(m * (n - 1)); + for(size_t j = 0; j < m; ++j) + { + for(size_t i = 1; i < n; ++i) + { + result.f[j * (n - 1) + i - 1] = a_mat(j, i); + if (l_digits[j] == i) + result.f[j * (n - 1) + i - 1] += x; + } + } + + result.y = r_A + x * r_B; + + result.z = 0; + scalar_t x_power = c_scalar_1; + for(size_t k = 0; k < m; ++k) + { + result.z -= x_power * ro[k]; + x_power *= x; + } + result.z += secret * x_power; + + return true; + } +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + //--------------------------------------------------------------- + + +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("generate_BGE_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + bool verify_BGE_proof(const hash& context_hash, const std::vector& ring, const BGE_proof& sig, uint8_t* p_err /* = nullptr */) + { + static constexpr size_t n = 4; // TODO: @#@# move it out + + DBG_PRINT(" - - - verify_BGE_proof - - -"); + size_t ring_size = ring.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(ring_size > 0, 0); + + const size_t m = std::max(static_cast(1), constexpr_ceil_log_n(ring_size, n)); + const size_t N = constexpr_pow(m, n); + //const size_t mn = m * n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.Pk.size() == m, 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.f.size() == m * (n - 1), 2); + + hash_helper_t::hs_t hsc(1 + ring_size + 2 + m); + hsc.add_hash(context_hash); + for(const public_key* ppk : ring) + hsc.add_pub_key(*ppk); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + hsc.add_pub_keys_array(sig.Pk); + scalar_t x = hsc.calc_hash(); + DBG_VAL_PRINT(x); + + scalar_vec_t f0(m); // the first column f_{i,0} = x - sum{j=1}{n-1}( f_{i,j} ) + for(size_t j = 0; j < m; ++j) + { + f0[j] = x; + for(size_t i = 1; i < n; ++i) + f0[j] -= sig.f[j * (n - 1) + i - 1]; + } + + // + // 1 + // + point_t A = point_t(sig.A).modify_mul8(); + point_t B = point_t(sig.B).modify_mul8(); + + point_t Z = A + x * B; + + bool r = false, r2 = false; + for(size_t j = 0; j < m; ++j) + { + for(size_t i = 0; i < n; ++i) + { + const point_t& gen_1 = get_BGE_generator((j * n + i) * 2 + 0, r); + const point_t& gen_2 = get_BGE_generator((j * n + i) * 2 + 1, r2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(r && r2, 5); + const scalar_t& f_ji = (i == 0) ? f0[j] : sig.f[j * (n - 1) + i - 1]; + + Z -= f_ji * gen_1 + f_ji * (x - f_ji) * gen_2; + } + } + Z -= sig.y * c_point_X; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(Z.is_zero(), 100); + + // + // 2 + // + scalar_vec_t p_vec(N); + for(size_t i = 0; i < N; ++i) + { + p_vec[i] = c_scalar_1; + size_t i_tmp = i; + for(size_t j = 0; j < m; ++j) + { + size_t i_j = i_tmp % n; // j-th digit of i + i_tmp /= n; + const scalar_t& f_jij = (i_j == 0) ? f0[j] : sig.f[j * (n - 1) + i_j - 1]; + p_vec[i] *= f_jij; + } + } + + for(size_t i = 0; i < ring_size; ++i) + Z += p_vec[i] * point_t(*ring[i]).modify_mul8(); + for(size_t i = ring_size; i < N; ++i) + Z += p_vec[i] * point_t(*ring[ring_size - 1]).modify_mul8(); + + scalar_t x_power = c_scalar_1; + for(size_t k = 0; k < m; ++k) + { + Z -= x_power * point_t(sig.Pk[k]).modify_mul8(); + x_power *= x; + } + + Z -= sig.z * c_point_X; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(Z.is_zero(), 101); + + return true; + } + +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + +} // namespace crypto diff --git a/crypto/upstream/one_out_of_many_proofs.h b/crypto/upstream/one_out_of_many_proofs.h new file mode 100755 index 0000000..3746f39 --- /dev/null +++ b/crypto/upstream/one_out_of_many_proofs.h @@ -0,0 +1,58 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once +#include "crypto-sugar.h" + +namespace crypto +{ + // + // BGE stands for Bootle, Groth, Esgin + // + // This is a proof-of-concept implementation of a log-size one-out-of-many proof based on ideas and approaches by Bootle et al, Groth et al and Esgin et al + // + // https://eprint.iacr.org/2014/764 + // https://eprint.iacr.org/2015/643 + // https://eprint.iacr.org/2019/1287 + // + // Disclaimer: shouldn't be used in production code until the security proofs and the code are peer-reviewed. + // + + // m+2 group elements, m(n-1)+2 field elements. + // Assuming fixed n=4, m = log4(ring_sz) the size is (log4(ring_sz) + 2) group elements and (3*log4(ring_sz) + 2) or, in total, (4*log4(ring_sz) + 4) 32-bytes words + + // ring_sz = m (inputs number) + // sig_count = k (outputs number) + // thus: + // k * (log4(m) + 2) group elements and k * (3*log4(m) + 2) field elements + + struct BGE_proof + { + public_key A; // premultiplied by 1/8 + public_key B; // premultiplied by 1/8 + std::vector Pk; // premultiplied by 1/8, size = m + scalar_vec_t f; // size = m * (n - 1) + scalar_t y; + scalar_t z; + }; + + bool generate_BGE_proof(const hash& context_hash, const std::vector& ring, const scalar_t& secret, const size_t secret_index, BGE_proof& result, uint8_t* p_err = nullptr); + + + bool verify_BGE_proof(const hash& context_hash, const std::vector& ring, const BGE_proof& sig, uint8_t* p_err = nullptr); + + +} // namespace crypto diff --git a/crypto/upstream/random.c b/crypto/upstream/random.c new file mode 100755 index 0000000..3d0f4b3 --- /dev/null +++ b/crypto/upstream/random.c @@ -0,0 +1,234 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#include +#include +#include +#include +#include + +#include "hash-ops.h" +#include "random.h" + +static_assert(RANDOM_STATE_SIZE >= HASH_DATA_AREA, "Invalid RANDOM_STATE_SIZE"); + +#if defined(_WIN32) + +#include +#include + +// thread-safe version +bool generate_system_random_bytes(size_t n, void *result) +{ + if (n == 0) + return true; + + if (result == NULL) + return false; + + NTSTATUS status = BCryptGenRandom(NULL, (PUCHAR)result, (ULONG)n, BCRYPT_USE_SYSTEM_PREFERRED_RNG); + return BCRYPT_SUCCESS(status); +} + +void generate_system_random_bytes_or_die(size_t n, void *result) +{ + if (!generate_system_random_bytes(n, result)) + { + fprintf(stderr, "Error: generate_system_random_bytes failed and this is fatal\n\n"); + fflush(stderr); + _exit(EXIT_FAILURE); + } +} + +#else + +#include +#include +#include +#include +#include +#include +#include + +bool generate_system_random_bytes(size_t n, void *result) +{ + int fd; + + fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd < 0) + return false; + + size_t bytes_read = 0; + while (bytes_read < n) + { + ssize_t res = read(fd, (char*)result + bytes_read, n - bytes_read); + if (res < 0) + { + if (errno != EINTR) + { + close(fd); + return false; + } + // EINTR - interrupted by signal, continue reading + } + else if (res == 0) + { + // EOF - should not happen with /dev/urandom + close(fd); + return false; + } + else + { + bytes_read += res; + } + } + + close(fd); // don't check, 'cuz failing to close /dev/urandom is not truly fatal, the OS will clean up + return true; +} + +void generate_system_random_bytes_or_die(size_t n, void *result) +{ + if (!generate_system_random_bytes(n, result)) + { + fprintf(stderr, "FATAL: Failed to generate %zu random bytes: %s\n\n", n, strerror(errno)); + fflush(stderr); + exit(EXIT_FAILURE); + } +} + +#endif + +static union hash_state state; + +static_assert(sizeof(union hash_state) == RANDOM_STATE_SIZE, "RANDOM_STATE_SIZE and hash_state size missmatch"); + +#if !defined(NDEBUG) +static volatile int curstate; /* To catch thread safety problems. */ +#endif +/* +FINALIZER(deinit_random) { +#if !defined(NDEBUG) + assert(curstate == 1); + curstate = 0; +#endif + memset(&state, 0, sizeof(union hash_state)); +} +*/ + +void init_random(void) +{ + generate_system_random_bytes_or_die(HASH_DATA_AREA, &state); + +#if !defined(NDEBUG) + assert(curstate == 0); + curstate = 1; +#endif +} + + +void grant_random_initialize_no_lock(void) +{ + static bool initalized = false; + if(!initalized) + { + init_random(); + initalized = true; + } +} + +void random_prng_initialize_with_seed_no_lock(uint64_t seed) +{ + grant_random_initialize_no_lock(); +#if !defined(NDEBUG) + assert(curstate == 1); + curstate = 3; +#endif + memset(&state, 0, sizeof state); + memcpy(&state, &seed, sizeof seed); + for(size_t i = 0, count = seed & 31; i < count; ++i) + hash_permutation(&state); +#if !defined(NDEBUG) + assert(curstate == 3); + curstate = 1; +#endif +} + +void random_prng_get_state_no_lock(void *state_buffer, const size_t buffer_size) +{ + grant_random_initialize_no_lock(); +#if !defined(NDEBUG) + assert(curstate == 1); + curstate = 4; +#endif + + assert(sizeof state == buffer_size); + memcpy(state_buffer, &state, buffer_size); + +#if !defined(NDEBUG) + assert(curstate == 4); + curstate = 1; +#endif +} + +void random_prng_set_state_no_lock(const void *state_buffer, const size_t buffer_size) +{ + grant_random_initialize_no_lock(); +#if !defined(NDEBUG) + assert(curstate == 1); + curstate = 5; +#endif + + assert(sizeof state == buffer_size); + memcpy(&state, state_buffer, buffer_size); + +#if !defined(NDEBUG) + assert(curstate == 5); + curstate = 1; +#endif +} + +void generate_random_bytes_no_lock(size_t n, void *result) +{ + grant_random_initialize_no_lock(); +#if !defined(NDEBUG) + assert(curstate == 1); + curstate = 2; +#endif + if (n == 0) { +#if !defined(NDEBUG) + assert(curstate == 2); + curstate = 1; +#endif + return; + } + for (;;) { + hash_permutation(&state); + if (n <= HASH_DATA_AREA) { + memcpy(result, &state, n); +#if !defined(NDEBUG) + assert(curstate == 2); + curstate = 1; +#endif + return; + } else { + memcpy(result, &state, HASH_DATA_AREA); + result = padd(result, HASH_DATA_AREA); + n -= HASH_DATA_AREA; + } + } +} diff --git a/crypto/upstream/random.h b/crypto/upstream/random.h new file mode 100755 index 0000000..aec69e2 --- /dev/null +++ b/crypto/upstream/random.h @@ -0,0 +1,43 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#pragma once + +#include +#include + +// NOT thread-safe, use with caution +void generate_random_bytes_no_lock(size_t n, void *result); + +#define RANDOM_STATE_SIZE 200 + +// explicitly define USE_INSECURE_RANDOM_RPNG_ROUTINES for using random_initialize_with_seed +#ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES +// reinitializes PRNG with the given seed +// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH! +// Use with care and ONLY for tests or debug purposes! +void random_prng_initialize_with_seed_no_lock(uint64_t seed); + +// gets internal RPNG state (state_buffer should be 200 bytes long) +void random_prng_get_state_no_lock(void *state_buffer, const size_t buffer_size); + +// sets internal RPNG state (state_buffer should be 200 bytes long) +// !!!ATTENTION!!!! Improper use of this routine may lead to SECURITY BREACH! +// Use with care and ONLY for tests or debug purposes! +void random_prng_set_state_no_lock(const void *state_buffer, const size_t buffer_size); + +#endif // #ifdef USE_INSECURE_RANDOM_RPNG_ROUTINES diff --git a/crypto/upstream/range_proof_bpp.h b/crypto/upstream/range_proof_bpp.h new file mode 100755 index 0000000..b855780 --- /dev/null +++ b/crypto/upstream/range_proof_bpp.h @@ -0,0 +1,741 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once + +// +// This file contains the implementation of range proof protocol. +// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735 +// + +namespace crypto +{ + struct bpp_signature + { + std::vector L; // size = ceil( log_2(m * n) ) + std::vector R; + public_key A0; + public_key A; + public_key B; + scalar_t r; + scalar_t s; + scalar_t delta; + }; + +#if 0 +# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl +# define DBG_PRINT(x) std::cout << x << std::endl +#else +# define DBG_VAL_PRINT(x) (void(0)) +# define DBG_PRINT(x) (void(0)) +#endif + + +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + + template + bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const std::vector& commitments_1div8, bpp_signature& sig, uint8_t* p_err = nullptr) + { + // Note: commitments_1div8 are supposed to be already calculated + static_assert(CT::c_bpp_n <= 255, "too big N"); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && values.size() == commitments_1div8.size(), 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced(), 3); + + const size_t c_bpp_log2_m = constexpr_ceil_log2(values.size()); + const size_t c_bpp_m = 1ull << c_bpp_log2_m; + const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n; + const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n; + +#ifndef NDEBUG + for(size_t i = 0; i < values.size(); ++i) + { + point_t V{}; + CT::calc_pedersen_commitment(values[i], masks[i], V); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(point_t(*commitments_1div8[i]).modify_mul8() == V, 4); + } +#endif + + // s.a. BP+ paper, page 15, eq. 11 + // decompose v into aL and aR: + // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product + // aR = aL - (1, 1, ... 1) + // aR o aL = 0 + + // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar + + scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); + aLs.zero(); + aRs.zero(); + // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) + for (size_t i = 0; i < values.size(); ++i) + { + const scalar_t& v = values[i]; + for (uint8_t j = 0; j < CT::c_bpp_n; ++j) + { + if (v.get_bit(j)) + aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 + else + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + } + } + + for (size_t i = values.size(); i < c_bpp_m; ++i) + for (size_t j = 0; j < CT::c_bpp_n; ++j) + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + + + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, commitments_1div8); + + // BP+ paper, page 15: The prover begins with sending A = g^aL h^aR h^alpha (group element) + // so we calculate A0 = alpha * H + SUM(aL_i * G_i) + SUM(aR_i * H_i) + + scalar_t alpha = scalar_t::random(); + point_t A0 = alpha * CT::bpp_H; + + for (size_t i = 0; i < c_bpp_mn; ++i) + A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); + + // pre-multiply all output points by c_scalar_1div8 + // in order to enforce these points to be in the prime-order subgroup (after mul by 8 in bpp_verify()) + A0 *= c_scalar_1div8; + A0.to_public_key(sig.A0); + + DBG_VAL_PRINT(alpha); + DBG_VAL_PRINT(A0); + + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + scalar_t y = hsc.calc_hash(); + scalar_t z = hash_helper_t::hs(y); + e = z; // transcript for further steps + DBG_VAL_PRINT(y); + DBG_VAL_PRINT(z); + + // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) + // (note: elements are stored column-by-column in memory) + // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | + // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | + // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | + // | ....................................................................................... | + // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | + // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) + + scalar_t z_sq = z * z; + scalar_mat_t d(c_bpp_mn); + d(0, 0) = z_sq; + // first row + for (size_t i = 1; i < c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + + // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) + // (calculate two more elements (1 and y^(mn+1)) for convenience) + scalar_vec_t y_powers(c_bpp_mn + 2); + y_powers[0] = 1; + for (size_t i = 1; i <= c_bpp_mn + 1; ++i) + y_powers[i] = y_powers[i - 1] * y; + + const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; + + DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); + + // aL_hat = aL - 1*z + scalar_vec_t aLs_hat = aLs - z; + // aR_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) + scalar_vec_t aRs_hat = aRs + z; + for (size_t i = 0; i < c_bpp_mn; ++i) + aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; + + DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); + DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); + + // calculate alpha_hat + // alpha_hat = alpha + SUM(z^(2j) * gamma_j * y^(mn+1)) for j = 1..m + // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j + scalar_t alpha_hat = 0; + for (size_t i = 0; i < masks.size(); ++i) + alpha_hat += d(i, 0) * masks[i]; + alpha_hat = alpha + y_mn_p1 * alpha_hat; + + DBG_VAL_PRINT(alpha_hat); + + // calculate 1, y^-1, y^-2, ... + const scalar_t y_inverse = y.reciprocal(); + scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) + y_inverse_powers[0] = 1; + for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; + + // prepare generator's vector + std::vector g(c_bpp_mn), h(c_bpp_mn); + for (size_t i = 0; i < c_bpp_mn; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + + // WIP zk-argument called with zk-WIP(g, h, G, H, A_hat, aL_hat, aR_hat, alpha_hat) + + scalar_vec_t& a = aLs_hat; + scalar_vec_t& b = aRs_hat; + + sig.L.resize(c_bpp_log2_mn); + sig.R.resize(c_bpp_log2_mn); + + // zk-WIP reduction rounds (s.a. the preprint page 13 Fig. 1) + for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) + { + DBG_PRINT(ENDL << "#" << ni); + + // zk-WIP(g, h, G, H, P, a, b, alpha) + + scalar_t dL = scalar_t::random(); + DBG_VAL_PRINT(dL); + scalar_t dR = scalar_t::random(); + DBG_VAL_PRINT(dR); + + // a = (a1, a2), b = (b1, b2) -- vectors of scalars + // cL = -- scalar + scalar_t cL = 0; + for (size_t i = 0; i < n; ++i) + cL += a[i] * y_powers[i + 1] * b[n + i]; + + DBG_VAL_PRINT(cL); + + // cR = * y^n -- scalar + scalar_t cR = 0; + for (size_t i = 0; i < n; ++i) + cR += a[n + i] * y_powers[i + 1] * b[i]; + cR *= y_powers[n]; + + DBG_VAL_PRINT(cR); + + // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H -- point + point_t sum = c_point_0; + for (size_t i = 0; i < n; ++i) + sum += a[i] * g[n + i]; + point_t L; + CT::calc_pedersen_commitment(cL, dL, L); + for (size_t i = 0; i < n; ++i) + L += b[n + i] * h[i]; + L += y_inverse_powers[n] * sum; + L *= c_scalar_1div8; + DBG_VAL_PRINT(L); + + // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H -- point + sum.zero(); + for (size_t i = 0; i < n; ++i) + sum += a[n + i] * g[i]; + point_t R; + CT::calc_pedersen_commitment(cR, dR, R); + for (size_t i = 0; i < n; ++i) + R += b[i] * h[n + i]; + R += y_powers[n] * sum; + R *= c_scalar_1div8; + DBG_VAL_PRINT(R); + + // put L, R to the sig + L.to_public_key(sig.L[ni]); + R.to_public_key(sig.R[ni]); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[ni]); + hsc.add_pub_key(sig.R[ni]); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // recalculate arguments for the next round + scalar_t e_squared = e * e; + scalar_t e_inverse = e.reciprocal(); + scalar_t e_inverse_squared = e_inverse * e_inverse; + scalar_t e_y_inv_n = e * y_inverse_powers[n]; + scalar_t e_inv_y_n = e_inverse * y_powers[n]; + + // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points + for (size_t i = 0; i < n; ++i) + g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; + + // h_hat = e * h1 + e^-1 * h2 -- vector of points + for (size_t i = 0; i < n; ++i) + h[i] = e * h[i] + e_inverse * h[n + i]; + + // P_hat = e^2 * L + P + e^-2 * R -- point + + // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + a[i] = e * a[i] + e_inv_y_n * a[n + i]; + + // b_hat = e^-1 * b1 + e * b2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + b[i] = e_inverse * b[i] + e * b[n + i]; + + // alpha_hat = e^2 * dL + alpha + e^-2 * dR -- scalar + alpha_hat += e_squared * dL + e_inverse_squared * dR; + + // run next iteraton zk-WIP(g_hat, h_hat, G, H, P_hat, a_hat, b_hat, alpha_hat) + } + DBG_PRINT(""); + + // zk-WIP last round + scalar_t r = scalar_t::random(); + scalar_t s = scalar_t::random(); + scalar_t delta = scalar_t::random(); + scalar_t eta = scalar_t::random(); + DBG_VAL_PRINT(r); + DBG_VAL_PRINT(s); + DBG_VAL_PRINT(delta); + DBG_VAL_PRINT(eta); + + // A = r * g + s * h + (r y b + s y a) * G + delta * H -- point + point_t A = c_point_0; + CT::calc_pedersen_commitment(y * (r * b[0] + s * a[0]), delta, A); + A += r * g[0] + s * h[0]; + A *= c_scalar_1div8; + A.to_public_key(sig.A); + DBG_VAL_PRINT(A); + + // B = (r * y * s) * G + eta * H + point_t B = c_point_0; + CT::calc_pedersen_commitment(r * y * s, eta, B); + B *= c_scalar_1div8; + B.to_public_key(sig.B); + DBG_VAL_PRINT(B); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // finalize the signature + sig.r = r + e * a[0]; + sig.s = s + e * b[0]; + sig.delta = eta + e * delta + e * e * alpha_hat; + DBG_VAL_PRINT(sig.r); + DBG_VAL_PRINT(sig.s); + DBG_VAL_PRINT(sig.delta); + + return true; + } // bpp_gen() + + + // convenient overload for tests + template + bool bpp_gen(const scalar_vec_t& values, const scalar_vec_t& masks, bpp_signature& sig, std::vector& commitments_1div8_to_be_generated, uint8_t* p_err = nullptr) + { + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() == masks.size(), 91); + commitments_1div8_to_be_generated.resize(values.size()); + std::vector commitments_1div8(values.size()); + std::vector commitments_1div8_pointers(values.size()); + for(size_t i = 0; i < values.size(); ++i) + { + CT::calc_pedersen_commitment(c_scalar_1div8 * values[i], c_scalar_1div8 * masks[i], commitments_1div8_to_be_generated[i]); + commitments_1div8[i] = (commitments_1div8_to_be_generated[i]).to_public_key(); + commitments_1div8_pointers[i] = &commitments_1div8[i]; + } + return bpp_gen(values, masks, commitments_1div8_pointers, sig, p_err); + } +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + + struct bpp_sig_commit_ref_t + { + bpp_sig_commit_ref_t(const bpp_signature& sig, const std::vector& commitments) + : sig(sig) + , commitments(commitments) + {} + const bpp_signature& sig; + const std::vector& commitments; // assumed to be premultiplied by 1/8 + }; + + + template + bool bpp_verify(const std::vector& sigs, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bpp_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + DBG_PRINT(ENDL << " . . . . bpp_verify() . . . . "); + + static_assert(CT::c_bpp_n <= 255, "too big N"); + const size_t kn = sigs.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); + + struct intermediate_element_t + { + scalar_t y; + scalar_t z; + scalar_t z_sq; + scalar_vec_t e; + scalar_vec_t e_sq; + scalar_t e_final; + scalar_t e_final_sq; + size_t inv_e_offset; // offset in batch_for_inverse + size_t inv_y_offset; // offset in batch_for_inverse + size_t c_bpp_log2_m; + size_t c_bpp_m; + size_t c_bpp_mn; + point_t A; + point_t A0; + point_t B; + std::vector L; + std::vector R; + }; + std::vector interms(kn); + + size_t c_bpp_log2_m_max = 0; + for (size_t k = 0; k < kn; ++k) + { + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta.is_reduced(), 4); + + intermediate_element_t& interm = interms[k]; + interm.c_bpp_log2_m = constexpr_ceil_log2(bsc.commitments.size()); + if (c_bpp_log2_m_max < interm.c_bpp_log2_m) + c_bpp_log2_m_max = interm.c_bpp_log2_m; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + CT::c_bpp_log2_n, 5); + + interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; + interm.c_bpp_mn = interm.c_bpp_m * CT::c_bpp_n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); + interm.L.resize(sig.L.size()); + interm.R.resize(sig.R.size()); + for (size_t i = 0; i < interm.L.size(); ++i) + { + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); + } + } + const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; + const size_t c_bpp_mn_max = c_bpp_m_max * CT::c_bpp_n; + const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + CT::c_bpp_log2_n; + + + // + // prepare stuff + // + /* + std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); + for (size_t i = 0; i < c_bpp_mn_max; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + */ + + scalar_vec_t batch_for_inverse; + batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); + + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // restore y and z + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, bsc.commitments); + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + hsc.assign_calc_hash(interm.y); + interm.z = hash_helper_t::hs(interm.y); + interm.z_sq = interm.z * interm.z; + DBG_VAL_PRINT(interm.y); + DBG_VAL_PRINT(interm.z); + e = interm.z; // transcript for further steps + + interm.inv_y_offset = batch_for_inverse.size(); + batch_for_inverse.push_back(interm.y); + interm.inv_e_offset = batch_for_inverse.size(); + + interm.e.resize(sig.L.size()); + interm.e_sq.resize(sig.L.size()); + + for (size_t i = 0; i < sig.L.size(); ++i) + { + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[i]); + hsc.add_pub_key(sig.R[i]); + hsc.assign_calc_hash(e); + interm.e[i] = e; + interm.e_sq[i] = e * e; + DBG_PRINT("e[" << i << "]: " << e); + batch_for_inverse.push_back(e); + } + + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + hsc.assign_calc_hash(interm.e_final); + interm.e_final_sq = interm.e_final * interm.e_final; + DBG_VAL_PRINT(interm.e_final); + } + + batch_for_inverse.invert(); + + // Notation: + // 1_vec ^ n = (1, 1, 1, ..., 1) + // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) + // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) + // y<^n = (y^n, y^(n-1), ..., y^1) + // y>^n = (y^1, y^2, ..., y^n) + + // from page 13, Fig 1: + // Verifier outputs Accept IFF the following equality holds (single proof): + // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta' + // (where g and h are calculated in each round) + // The same equation in additive notation: + // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H + // <=> + // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta' * H - e^2 * P - e * A - B == 0 (*) + // where A, B, r', s', delta' is taken from the signature + // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds + // + // from page 18, Fig 3: + // P and V computes: + // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // (calculated once) + // + // As suggested in Section 6.1 "Practical Optimizations": + // 1) g and h exponentianions can be optimized in order not to be calculated at each round as the following (page 20): + // + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * A_hat + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 (**) + // + // where: + // g, h - vector of fixed generators + // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) + // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) + // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) + // b(i, j) = { 2 * ((1< + + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta' * H - + // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // ) + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 + + // => + + // (for single signature) + // + // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are + // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators + // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all + // + delta' * H | the signatures + // + // - e^2 * A0 + // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) + // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + // - e * A - B = 0 (***) + // + // All (***) will be muptiplied by random weightning factor and then summed up. + + // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. + scalar_vec_t g_scalars; + g_scalars.resize(c_bpp_mn_max, 0); + scalar_vec_t h_scalars; + h_scalars.resize(c_bpp_mn_max, 0); + scalar_t G_scalar = 0; + scalar_t H_scalar = 0; + point_t summand = c_point_0; + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bpp_sig_commit_ref_t& bsc = sigs[k]; + const bpp_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // random weightning factor for speed-optimized batch verification (preprint page 20) + const scalar_t rwf = scalar_t::random(); + DBG_PRINT("rwf: " << rwf); + + // prepare d vector (see also d structure description in proof function) + scalar_mat_t d(interm.c_bpp_mn); + d(0, 0) = interm.z_sq; + // first row + for (size_t i = 1; i < interm.c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * interm.z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < interm.c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + // sum(d) (see also note in proof function for this) + const scalar_t sum_d = CT::get_2_to_the_power_of_N_minus_1() * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + DBG_PRINT("sum(d): " << sum_d); + + const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; + auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] + + // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) + // complexity (sc_mul's): MN+2*log2(MN)-2 + // the idea is the following: + // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 + // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 + const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n + scalar_vec_t s_vec(interm.c_bpp_mn); + s_vec[0] = get_e_inv(0); + for (size_t i = 1; i < log2_mn; ++i) + s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 + DBG_PRINT("[0] " << s_vec[0]); + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + { + size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) + size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base + s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 + DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); + } + + // prepare y_inv vector + scalar_vec_t y_inverse_powers(interm.c_bpp_mn); + y_inverse_powers[0] = 1; + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; + + // y^(mn+1) + scalar_t y_power_mnp1 = interm.y; + for (size_t i = 0; i < log2_mn; ++i) + y_power_mnp1 *= y_power_mnp1; + y_power_mnp1 *= interm.y; + DBG_VAL_PRINT(y_power_mnp1); + + // now calculate all multiplicands for common generators + + // g vector multiplicands: + // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = + // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) + scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_r_e = rwf * interm.e_final * sig.r; + for (size_t i = 0; i < interm.c_bpp_mn; ++i) + g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; + + DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); + + // h vector multiplicands: + // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) + // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) + //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_s_e = rwf * sig.s * interm.e_final; + scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; + for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) + { + h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; + rwf_e_sq_y *= interm.y; + } + + DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); + + // G point multiplicands: + // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = + // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) + G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; + G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); + DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); + DBG_PRINT("G_scalar: " << G_scalar); + + // H point multiplicands: + // rwf * delta + H_scalar += rwf * sig.delta; + DBG_PRINT("H_scalar: " << H_scalar); + + // uncommon generators' multiplicands + point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand + // - rwf * e^2 * A0 + summand_8 -= rwf * interm.e_final_sq * interm.A0; + DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); + + // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) + scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; + for (size_t j = 0; j < bsc.commitments.size(); ++j) + { + e_sq_y_mn1_z_sq_power *= interm.z_sq; + summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; + DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); + } + + // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + scalar_t rwf_e_sq = rwf * interm.e_final_sq; + for (size_t j = 0; j < log2_mn; ++j) + { + summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); + DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); + DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); + } + + // - rwf * e * A - rwf * B = 0 + summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; + DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); + DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); + + summand_8.modify_mul8(); + summand += summand_8; + } + + point_t GH_exponents = c_point_0; + CT::calc_pedersen_commitment(G_scalar, H_scalar, GH_exponents); + bool result = msm_and_check_zero(g_scalars, h_scalars, summand + GH_exponents); + if (result) + DBG_PRINT(ENDL << " . . . . bpp_verify() -- SUCCEEDED!!!" << ENDL); + return result; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } + +#undef DBG_VAL_PRINT +#undef DBG_PRINT + +} // namespace crypto diff --git a/crypto/upstream/range_proof_bppe.h b/crypto/upstream/range_proof_bppe.h new file mode 100755 index 0000000..f1ad30c --- /dev/null +++ b/crypto/upstream/range_proof_bppe.h @@ -0,0 +1,759 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once + +// +// This file contains the implementation of range proof protocol. +// Namely, Bulletproofs+ https://eprint.iacr.org/2020/735 +// Double-blinded commitments extension implemented as in Appendix D in the Zarcanum whitepaper: https://eprint.iacr.org/2021/1478 + +namespace crypto +{ + struct bppe_signature + { + std::vector L; // size = log_2(m * n) + std::vector R; + public_key A0; + public_key A; + public_key B; + scalar_t r; + scalar_t s; + scalar_t delta_1; + scalar_t delta_2; + }; + +#if 0 +# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl +# define DBG_PRINT(x) std::cout << x << std::endl +#else +# define DBG_VAL_PRINT(x) (void(0)) +# define DBG_PRINT(x) (void(0)) +#endif + +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bppe_gen: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + + template + bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, const std::vector& commitments_1div8, bppe_signature& sig, uint8_t* p_err = nullptr) + { + // Note: commitments_1div8 are supposed to be already calculated + static_assert(CT::c_bpp_n <= 255, "too big N"); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(values.size() > 0 && values.size() <= CT::c_bpp_values_max && values.size() == masks.size() && masks.size() == masks2.size() && values.size() == commitments_1div8.size(), 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(masks.is_reduced() && masks2.is_reduced(), 3); + + const size_t c_bpp_log2_m = constexpr_ceil_log2(values.size()); + const size_t c_bpp_m = 1ull << c_bpp_log2_m; + const size_t c_bpp_mn = c_bpp_m * CT::c_bpp_n; + const size_t c_bpp_log2_mn = c_bpp_log2_m + CT::c_bpp_log2_n; + +#ifndef NDEBUG + for(size_t i = 0; i < values.size(); ++i) + { + point_t V{}; + CT::calc_pedersen_commitment_2(values[i], masks[i], masks2[i], V); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(point_t(*commitments_1div8[i]).modify_mul8() == V, 4); + } +#endif + + // s.a. BP+ paper, page 15, eq. 11 + // decompose v into aL and aR: + // v = aL o (1, 2, 2^2, ..., 2^n-1), o - component-wise product aka Hadamard product + // aR = aL - (1, 1, ... 1) + // aR o aL = 0 + + // aLs = (aL_0, aL_1, ..., aL_m-1) -- `bit` matrix of c_bpp_m x c_bpp_n, each element is a scalar + + scalar_mat_t aLs(c_bpp_mn), aRs(c_bpp_mn); + aLs.zero(); + aRs.zero(); + // m >= values.size, first set up [0..values.size-1], then -- [values.size..m-1] (padding area) + for (size_t i = 0; i < values.size(); ++i) + { + const scalar_t& v = values[i]; + for (uint8_t j = 0; j < CT::c_bpp_n; ++j) + { + if (v.get_bit(j)) + aLs(i, j) = c_scalar_1; // aL = 1, aR = 0 + else + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + } + } + + for (size_t i = values.size(); i < c_bpp_m; ++i) + for (size_t j = 0; j < CT::c_bpp_n; ++j) + aRs(i, j) = c_scalar_Lm1; // aL = 0, aR = -1 + + + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, commitments_1div8); + + // Zarcanum paper, page 33, Fig. D.3: The prover chooses alpha_1, alpha_2 and computes A = g^aL h^aR h_1^alpha_1 h_2^alpha_2 + // so we calculate A0 = alpha_1 * H + alpha_2 * H_2 + SUM(aL_i * G_i) + SUM(aR_i * H_i) + + scalar_t alpha_1 = scalar_t::random(), alpha_2 = scalar_t::random(); + point_t A0 = alpha_1 * CT::bpp_H + alpha_2 * CT::bpp_H2; + + for (size_t i = 0; i < c_bpp_mn; ++i) + A0 += aLs[i] * CT::get_generator(false, i) + aRs[i] * CT::get_generator(true, i); + + // part of 1/8 defense scheme + A0 *= c_scalar_1div8; + A0.to_public_key(sig.A0); + + DBG_VAL_PRINT(alpha_1); + DBG_VAL_PRINT(alpha_2); + DBG_VAL_PRINT(A0); + + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + scalar_t y = hsc.calc_hash(); + scalar_t z = hash_helper_t::hs(y); + e = z; // transcript for further steps + DBG_VAL_PRINT(y); + DBG_VAL_PRINT(z); + + // Computing vector d for aggregated version of the protocol (BP+ paper, page 17) + // (note: elements are stored column-by-column in memory) + // d = | 1 * z^(2*1), 1 * z^(2*2), 1 * z^(2*3), ..., 1 * z^(2*m) | + // | 2 * z^(2*1), 2 * z^(2*2), 2 * z^(2*3), ..., 2 * z^(2*m) | + // | 4 * z^(2*1), 4 * z^(2*2), 4 * z^(2*3), ..., 4 * z^(2*m) | + // | ....................................................................................... | + // | 2^(n-1) * z^(2*1), 2^(n-1) * z^(2*2), 2^(n-1) * z^(2*3), ..., 2^(n-1) * z^(2*m)) | + // Note: sum(d_i) = (2^n - 1) * ((z^2)^1 + (z^2)^2 + ... (z^2)^m)) = (2^n-1) * sum_of_powers(x^2, log(m)) + + scalar_t z_sq = z * z; + scalar_mat_t d(c_bpp_mn); + d(0, 0) = z_sq; + // first row + for (size_t i = 1; i < c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + + // calculate extended Vandermonde vector y = (1, y, y^2, ..., y^(mn+1)) (BP+ paper, page 18, Fig. 3) + // (calculate two more elements (1 and y^(mn+1)) for convenience) + scalar_vec_t y_powers(c_bpp_mn + 2); + y_powers[0] = 1; + for (size_t i = 1; i <= c_bpp_mn + 1; ++i) + y_powers[i] = y_powers[i - 1] * y; + + const scalar_t& y_mn_p1 = y_powers[c_bpp_mn + 1]; + + DBG_PRINT("Hs(y_powers): " << y_powers.calc_hs()); + + // aL_hat = aL - 1*z + scalar_vec_t aLs_hat = aLs - z; + // aR_hat = aR + d o y^leftarr + 1*z where y^leftarr = (y^n, y^(n-1), ..., y) (BP+ paper, page 18, Fig. 3) + scalar_vec_t aRs_hat = aRs + z; + for (size_t i = 0; i < c_bpp_mn; ++i) + aRs_hat[i] += d[i] * y_powers[c_bpp_mn - i]; + + DBG_PRINT("Hs(aLs_hat): " << aLs_hat.calc_hs()); + DBG_PRINT("Hs(aRs_hat): " << aRs_hat.calc_hs()); + + // calculate alpha_hat + // alpha_hat_1 = alpha_1 + SUM(z^(2j) * gamma_1,j * y^(mn+1)) for j = 1..m + // alpha_hat_2 = alpha_2 + SUM(z^(2j) * gamma_2,j * y^(mn+1)) for j = 1..m + // i.e. \hat{\alpha} = \alpha + y^{m n+1} \sum_{j = 1}^{m} z^{2j} \gamma_j + scalar_t alpha_hat_1 = 0, alpha_hat_2 = 0; + for (size_t i = 0; i < masks.size(); ++i) + { + alpha_hat_1 += d(i, 0) * masks[i]; + alpha_hat_2 += d(i, 0) * masks2[i]; + } + alpha_hat_1 = alpha_1 + y_mn_p1 * alpha_hat_1; + alpha_hat_2 = alpha_2 + y_mn_p1 * alpha_hat_2; + + DBG_VAL_PRINT(alpha_hat_1); + DBG_VAL_PRINT(alpha_hat_2); + + // calculate 1, y^-1, y^-2, ... + const scalar_t y_inverse = y.reciprocal(); + scalar_vec_t y_inverse_powers(c_bpp_mn / 2 + 1); // the greatest power we need is c_bpp_mn/2 (at the first reduction round) + y_inverse_powers[0] = 1; + for (size_t i = 1, size = y_inverse_powers.size(); i < size; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inverse; + + // prepare generator's vector + std::vector g(c_bpp_mn), h(c_bpp_mn); + for (size_t i = 0; i < c_bpp_mn; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + + // WIP zk-argument called with zk-WIP(g, h, G, H, H2, A_hat, aL_hat, aR_hat, alpha_hat_1, alpha_hat_2) + + scalar_vec_t& a = aLs_hat; + scalar_vec_t& b = aRs_hat; + + sig.L.resize(c_bpp_log2_mn); + sig.R.resize(c_bpp_log2_mn); + + // zk-WIP reduction rounds (s.a. Zarcanum preprint page 24 Fig. D.1) + for (size_t n = c_bpp_mn / 2, ni = 0; n >= 1; n /= 2, ++ni) + { + DBG_PRINT(ENDL << "#" << ni); + + // zk-WIP(g, h, G, H, H2, P, a, b, alpha_1, alpha_2) + + scalar_t dL = scalar_t::random(), dL2 = scalar_t::random(); + DBG_VAL_PRINT(dL); DBG_VAL_PRINT(dL2); + scalar_t dR = scalar_t::random(), dR2 = scalar_t::random(); + DBG_VAL_PRINT(dR); DBG_VAL_PRINT(dR2); + + // a = (a1, a2), b = (b1, b2) -- vectors of scalars + // cL = -- scalar + scalar_t cL = 0; + for (size_t i = 0; i < n; ++i) + cL += a[i] * y_powers[i + 1] * b[n + i]; + + DBG_VAL_PRINT(cL); + + // cR = * y^n -- scalar + scalar_t cR = 0; + for (size_t i = 0; i < n; ++i) + cR += a[n + i] * y_powers[i + 1] * b[i]; + cR *= y_powers[n]; + + DBG_VAL_PRINT(cR); + + // L = y^-n * a1 * g2 + b2 * h1 + cL * G + dL * H + dL2 * H2 -- point + point_t sum = c_point_0; + for (size_t i = 0; i < n; ++i) + sum += a[i] * g[n + i]; + point_t L; + CT::calc_pedersen_commitment_2(cL, dL, dL2, L); + for (size_t i = 0; i < n; ++i) + L += b[n + i] * h[i]; + L += y_inverse_powers[n] * sum; + L *= c_scalar_1div8; + DBG_VAL_PRINT(L); + + // R = y^n * a2 * g1 + b1 * h2 + cR * G + dR * H + dR2 * H2 -- point + sum.zero(); + for (size_t i = 0; i < n; ++i) + sum += a[n + i] * g[i]; + point_t R; + CT::calc_pedersen_commitment_2(cR, dR, dR2, R); + for (size_t i = 0; i < n; ++i) + R += b[i] * h[n + i]; + R += y_powers[n] * sum; + R *= c_scalar_1div8; + DBG_VAL_PRINT(R); + + // put L, R to the sig + L.to_public_key(sig.L[ni]); + R.to_public_key(sig.R[ni]); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[ni]); + hsc.add_pub_key(sig.R[ni]); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // recalculate arguments for the next round + scalar_t e_squared = e * e; + scalar_t e_inverse = e.reciprocal(); + scalar_t e_inverse_squared = e_inverse * e_inverse; + scalar_t e_y_inv_n = e * y_inverse_powers[n]; + scalar_t e_inv_y_n = e_inverse * y_powers[n]; + + // g_hat = e^-1 * g1 + (e * y^-n) * g2 -- vector of points + for (size_t i = 0; i < n; ++i) + g[i] = e_inverse * g[i] + e_y_inv_n * g[n + i]; + + // h_hat = e * h1 + e^-1 * h2 -- vector of points + for (size_t i = 0; i < n; ++i) + h[i] = e * h[i] + e_inverse * h[n + i]; + + // P_hat = e^2 * L + P + e^-2 * R -- point + + // a_hat = e * a1 + e^-1 * y^n * a2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + a[i] = e * a[i] + e_inv_y_n * a[n + i]; + + // b_hat = e^-1 * b1 + e * b2 -- vector of scalars + for (size_t i = 0; i < n; ++i) + b[i] = e_inverse * b[i] + e * b[n + i]; + + // alpha_hat_1 = e^2 * dL + alpha_1 + e^-2 * dR -- scalar + // alpha_hat_2 = e^2 * dL2 + alpha_2 + e^-2 * dR2 -- scalar + alpha_hat_1 += e_squared * dL + e_inverse_squared * dR; + alpha_hat_2 += e_squared * dL2 + e_inverse_squared * dR2; + + // run next iteraton zk-WIP(g_hat, h_hat, G, H, H2, P_hat, a_hat, b_hat, alpha_hat_1, alpha_hat_2) + } + DBG_PRINT(""); + + // zk-WIP last round + scalar_t r = scalar_t::random(); + scalar_t s = scalar_t::random(); + scalar_t delta_1 = scalar_t::random(), delta_2 = scalar_t::random(); + scalar_t eta_1 = scalar_t::random(), eta_2 = scalar_t::random(); + DBG_VAL_PRINT(r); + DBG_VAL_PRINT(s); + DBG_VAL_PRINT(delta_1); DBG_VAL_PRINT(delta_2); + DBG_VAL_PRINT(eta_1); DBG_VAL_PRINT(eta_2); + + // A = r * g + s * h + (r y b + s y a) * G + delta_1 * H + delta_2 * H2 -- point + point_t A = c_point_0; + CT::calc_pedersen_commitment_2(y * (r * b[0] + s * a[0]), delta_1, delta_2, A); + A += r * g[0] + s * h[0]; + A *= c_scalar_1div8; + A.to_public_key(sig.A); + DBG_VAL_PRINT(A); + + // B = (r * y * s) * G + eta_1 * H + eta_2 * H2 + point_t B = c_point_0; + CT::calc_pedersen_commitment_2(r * y * s, eta_1, eta_2, B); + B *= c_scalar_1div8; + B.to_public_key(sig.B); + DBG_VAL_PRINT(B); + + // update the transcript + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + e = hsc.calc_hash(); + DBG_VAL_PRINT(e); + + // finalize the signature + sig.r = r + e * a[0]; + sig.s = s + e * b[0]; + sig.delta_1 = eta_1 + e * delta_1 + e * e * alpha_hat_1; + sig.delta_2 = eta_2 + e * delta_2 + e * e * alpha_hat_2; + DBG_VAL_PRINT(sig.r); + DBG_VAL_PRINT(sig.s); + DBG_VAL_PRINT(sig.delta_1); + DBG_VAL_PRINT(sig.delta_2); + + return true; + } // bppe_gen() + + + // convenient overload for tests + template + bool bppe_gen(const scalar_vec_t& values, const scalar_vec_t& masks, const scalar_vec_t& masks2, bppe_signature& sig, std::vector& commitments_1div8_to_be_generated, uint8_t* p_err = nullptr) + { + // calc commitments vector as commitments[i] = 1/8 * values[i] * G + 1/8 * masks[i] * H + 1/8 * masks2[i] * H2 + commitments_1div8_to_be_generated.resize(values.size()); + std::vector commitments_1div8(values.size()); + std::vector commitments_1div8_pointers(values.size()); + for (size_t i = 0; i < values.size(); ++i) + { + CT::calc_pedersen_commitment_2(values[i] * c_scalar_1div8, masks[i] * c_scalar_1div8, masks2[i] * c_scalar_1div8, commitments_1div8_to_be_generated[i]); + commitments_1div8[i] = (commitments_1div8_to_be_generated[i]).to_public_key(); + commitments_1div8_pointers[i] = &commitments_1div8[i]; + } + return bppe_gen(values, masks, masks2, commitments_1div8_pointers, sig, p_err); + } + #undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + + struct bppe_sig_commit_ref_t + { + bppe_sig_commit_ref_t(const bppe_signature& sig, const std::vector& commitments) + : sig(sig) + , commitments(commitments) + {} + const bppe_signature& sig; + const std::vector& commitments; // assumed to be premultiplied by 1/8 + }; + + + template + bool bppe_verify(const std::vector& sigs, uint8_t* p_err = nullptr) + { +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("bppe_verify: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + DBG_PRINT(ENDL << " . . . . bppe_verify() . . . . "); + + static_assert(CT::c_bpp_n <= 255, "too big N"); + const size_t kn = sigs.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(kn > 0, 1); + + struct intermediate_element_t + { + scalar_t y; + scalar_t z; + scalar_t z_sq; + scalar_vec_t e; + scalar_vec_t e_sq; + scalar_t e_final; + scalar_t e_final_sq; + size_t inv_e_offset; // offset in batch_for_inverse + size_t inv_y_offset; // offset in batch_for_inverse + size_t c_bpp_log2_m; + size_t c_bpp_m; + size_t c_bpp_mn; + point_t A; + point_t A0; + point_t B; + std::vector L; + std::vector R; + }; + std::vector interms(kn); + + size_t c_bpp_log2_m_max = 0; + for (size_t k = 0; k < kn; ++k) + { + const bppe_sig_commit_ref_t& bsc = sigs[k]; + const bppe_signature& sig = bsc.sig; + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bsc.commitments.size() > 0, 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() > 0 && sig.L.size() == sig.R.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.r.is_reduced() && sig.s.is_reduced() && sig.delta_1.is_reduced() && sig.delta_2.is_reduced(), 4); + + intermediate_element_t& interm = interms[k]; + interm.c_bpp_log2_m = constexpr_ceil_log2(bsc.commitments.size()); + if (c_bpp_log2_m_max < interm.c_bpp_log2_m) + c_bpp_log2_m_max = interm.c_bpp_log2_m; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.L.size() == interm.c_bpp_log2_m + CT::c_bpp_log2_n, 5); + + interm.c_bpp_m = 1ull << interm.c_bpp_log2_m; + interm.c_bpp_mn = interm.c_bpp_m * CT::c_bpp_n; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A0.from_public_key(sig.A0), 6); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.A.from_public_key(sig.A), 7); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.B.from_public_key(sig.B), 8); + interm.L.resize(sig.L.size()); + interm.R.resize(sig.R.size()); + for (size_t i = 0; i < interm.L.size(); ++i) + { + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.L[i].from_public_key(sig.L[i]), 9); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(interm.R[i].from_public_key(sig.R[i]), 10); + } + } + const size_t c_bpp_m_max = 1ull << c_bpp_log2_m_max; + const size_t c_bpp_mn_max = c_bpp_m_max * CT::c_bpp_n; + const size_t c_bpp_LR_size_max = c_bpp_log2_m_max + CT::c_bpp_log2_n; + + + // + // prepare stuff + // + /* + std::vector g(c_bpp_mn_max), h(c_bpp_mn_max); + for (size_t i = 0; i < c_bpp_mn_max; ++i) + { + g[i] = CT::get_generator(false, i); + h[i] = CT::get_generator(true, i); + } + */ + + scalar_vec_t batch_for_inverse; + batch_for_inverse.reserve(kn + kn * c_bpp_LR_size_max); + + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bppe_sig_commit_ref_t& bsc = sigs[k]; + const bppe_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // restore y and z + // using e as Fiat-Shamir transcript + scalar_t e = CT::get_initial_transcript(); + DBG_PRINT("initial transcript: " << e); + hash_helper_t::hs_t hsc; + CT::update_transcript(hsc, e, bsc.commitments); + // calculate scalar challenges y and z + hsc.add_scalar(e); + hsc.add_pub_key(sig.A0); + hsc.assign_calc_hash(interm.y); + interm.z = hash_helper_t::hs(interm.y); + interm.z_sq = interm.z * interm.z; + DBG_VAL_PRINT(interm.y); + DBG_VAL_PRINT(interm.z); + e = interm.z; // transcript for further steps + + interm.inv_y_offset = batch_for_inverse.size(); + batch_for_inverse.push_back(interm.y); + interm.inv_e_offset = batch_for_inverse.size(); + + interm.e.resize(sig.L.size()); + interm.e_sq.resize(sig.L.size()); + + for (size_t i = 0; i < sig.L.size(); ++i) + { + hsc.add_scalar(e); + hsc.add_pub_key(sig.L[i]); + hsc.add_pub_key(sig.R[i]); + hsc.assign_calc_hash(e); + interm.e[i] = e; + interm.e_sq[i] = e * e; + DBG_PRINT("e[" << i << "]: " << e); + batch_for_inverse.push_back(e); + } + + hsc.add_scalar(e); + hsc.add_pub_key(sig.A); + hsc.add_pub_key(sig.B); + hsc.assign_calc_hash(interm.e_final); + interm.e_final_sq = interm.e_final * interm.e_final; + DBG_VAL_PRINT(interm.e_final); + } + + batch_for_inverse.invert(); + + // Notation: + // 1_vec ^ n = (1, 1, 1, ..., 1) + // 2_vec ^ n = (2^0, 2^1, 2^2, ..., 2^(n-1)) + // -1_vec ^ n = ((-1)^0, (-1)^1, (-1)^2, ... (-1)^(n-1)) = (1, -1, 1, -1, ...) + // y<^n = (y^n, y^(n-1), ..., y^1) + // y>^n = (y^1, y^2, ..., y^n) + + // from Zarcanum page 24, Fig D.1: + // Verifier outputs Accept IFF the following holds: + // P^e^2 * A^e * B == g ^ (r' e) * h ^ (s' e) * G ^ (r' y s') * H ^ delta'_1 * H2 ^ delta'_2 + // (where g and h are calculated in each round) + // The same equation in additive notation: + // e^2 * P + e * A + B == (r' * e) * g + (s' * e) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 + // <=> + // (r' * e) * g + (s' * e) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 - e^2 * P - e * A - B == 0 (*) + // where A, B, r', s', delta'_1, delta'_2 is taken from the signature + // and P_{k+1} = e^2 * L_k + P_k + e^-2 * R_k for all rounds + // + // from Zarcanum preprint page 33, Fig D.3: + // P and V computes: + // A_hat = A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // (calculated once) + // + // As suggested in BPP preprint Section 6.1 "Practical Optimizations": + // 1) g and h exponentianions can be optimized in order not to be calculated at each round + // as the following (page 20, with delta'_2 and H2 added): + // + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 - + // - e^2 * A_hat + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 (**) + // + // where: + // g, h - vector of fixed generators + // s_vec_i = y^(1-i) * PROD{j=1..log(n)}(e_j ^ b(i,j)) + // s'_vec_i = PROD{j=1..log(n)}(e_j ^ -b(i,j)) + // b(i, j) = { 2 * ((1<<(j-1)) & (i-1)) - 1) (counting both from 1) (page 20) + // b(i, j) = { 2 * ((1< + + // (r' * e * s_vec) * g + (s' * e * s'_vec) * h + (r' y s') * G + delta'_1 * H + delta'_2 * H2 - + // - e^2 * (A0 + (- 1^(mn) * z) * g + (d o y<^(mn) + 1^(mn) * z) * h + + // + y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j) + + // + (z*SUM(y^>mn) - z*y^(mn+1)*SUM(d) - z^2 * SUM(y^>mn)) * G + // ) + // - SUM{j=1..log(n)}(e_final^2 * e_j^2 * L_j + e_final^2 * e_j^-2 * R_j) + // - e * A - B = 0 + + // => + + // (for single signature) + // + // (r' * e * s_vec - e^2 * (- 1_vec^(mn) * z)) * g | these are + // + (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) * h | fixed generators + // + (r' y s' - e^2 * ((z - z^2)*SUM(y^>mn) - z*y^(mn+1)*SUM(d)) * G | across all + // + delta'_1 * H | the signatures + // + delta'_2 * H2 | the signatures + // + // - e^2 * A0 + // - e^2 * y^(mn+1) * (SUM{j=1..m} z^(2j) * V_j)) + // - e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + // - e * A - B = 0 (***) + // + // All (***) will be muptiplied by random weightning factor and then summed up. + + // Calculate cummulative sclalar multiplicand for fixed generators across all the sigs. + scalar_vec_t g_scalars; + g_scalars.resize(c_bpp_mn_max, 0); + scalar_vec_t h_scalars; + h_scalars.resize(c_bpp_mn_max, 0); + scalar_t G_scalar = 0; + scalar_t H_scalar = 0; + scalar_t H2_scalar = 0; + point_t summand = c_point_0; + + for (size_t k = 0; k < kn; ++k) + { + DBG_PRINT(ENDL << "SIG #" << k); + const bppe_sig_commit_ref_t& bsc = sigs[k]; + const bppe_signature& sig = bsc.sig; + intermediate_element_t& interm = interms[k]; + + // random weightning factor for speed-optimized batch verification (preprint page 20) + const scalar_t rwf = scalar_t::random(); + DBG_PRINT("rwf: " << rwf); + + // prepare d vector (see also d structure description in proof function) + scalar_mat_t d(interm.c_bpp_mn); + d(0, 0) = interm.z_sq; + // first row + for (size_t i = 1; i < interm.c_bpp_m; ++i) + d(i, 0) = d(i - 1, 0) * interm.z_sq; + // all rows + for (size_t j = 1; j < CT::c_bpp_n; ++j) + for (size_t i = 0; i < interm.c_bpp_m; ++i) + d(i, j) = d(i, j - 1) + d(i, j - 1); + // sum(d) (see also note in proof function for this) + const scalar_t sum_d = CT::get_2_to_the_power_of_N_minus_1() * sum_of_powers(interm.z_sq, interm.c_bpp_log2_m); + + DBG_PRINT("Hs(d): " << d.calc_hs()); + DBG_PRINT("sum(d): " << sum_d); + + const scalar_t& y_inv = batch_for_inverse[interm.inv_y_offset]; + auto get_e_inv = [&](size_t i) { return batch_for_inverse[interm.inv_e_offset + i]; }; // i belongs to [0; L.size()-1] + + // prepare s_vec (unlike the paper here we moved y-component out of s_vec for convenience, so s_vec'[x] = s_vec[~x & (MN-1)]) + // complexity (sc_mul's): MN+2*log2(MN)-2 + // the idea is the following: + // s_vec[00000b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^-1 * (e_1)^-1 * (e_0)^-1 + // s_vec[00101b] = ... * (e_4)^-1 * (e_3)^-1 * (e_2)^+1 * (e_1)^-1 * (e_0)^+1 + const size_t log2_mn = sig.L.size(); // at the beginning we made sure that sig.L.size() == c_bpp_log2_m + c_bpp_log2_n + scalar_vec_t s_vec(interm.c_bpp_mn); + s_vec[0] = get_e_inv(0); + for (size_t i = 1; i < log2_mn; ++i) + s_vec[0] *= get_e_inv(i); // s_vec[0] = (e_0)^-1 * (e_1)^-1 * .. (e_{log2_mn-1})^-1 + DBG_PRINT("[0] " << s_vec[0]); + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + { + size_t base_el_index = i & (i - 1); // base element index: 0, 0, 2, 0, 4, 4, 6, 0, 8, 8, 10... base element differs in one bit (0) from the current one (1) + size_t bit_index = log2_mn - calc_lsb_32((uint32_t)i) - 1; // the bit index where current element has the difference with the base + s_vec[i] = s_vec[base_el_index] * interm.e_sq[bit_index]; // (e_j)^-1 * (e_j)^2 = (e_j)^+1 + DBG_PRINT("[" << i << "] " << " " << base_el_index << ", " << bit_index << " : " << s_vec[i]); + } + + // prepare y_inv vector + scalar_vec_t y_inverse_powers(interm.c_bpp_mn); + y_inverse_powers[0] = 1; + for (size_t i = 1; i < interm.c_bpp_mn; ++i) + y_inverse_powers[i] = y_inverse_powers[i - 1] * y_inv; + + // y^(mn+1) + scalar_t y_power_mnp1 = interm.y; + for (size_t i = 0; i < log2_mn; ++i) + y_power_mnp1 *= y_power_mnp1; + y_power_mnp1 *= interm.y; + DBG_VAL_PRINT(y_power_mnp1); + + // now calculate all multiplicands for common generators + + // g vector multiplicands: + // rwf * (r' * e * (1, y^-1, y^-2, ...) o s_vec + e^2 * z) = + // rwf * r' * e * ((1, y^-1, ...) o s_vec) + rwf * e^2 * z * (1, 1, ...) + scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_r_e = rwf * interm.e_final * sig.r; + for (size_t i = 0; i < interm.c_bpp_mn; ++i) + g_scalars[i] += rwf_r_e * y_inverse_powers[i] * s_vec[i] + rwf_e_sq_z; + + DBG_PRINT("Hs(g_scalars): " << g_scalars.calc_hs()); + + // h vector multiplicands: + // rwf * (s' * e * s'_vec - e^2 * (d o y<^(mn) + 1_vec^(mn) * z)) + // rwf * s' * e * s'_vec - rwf * e^2 * z * (1, 1...) - rwf * e^2 * (d o y<^(mn)) + //scalar_t rwf_e_sq_z = rwf * interm.e_final_sq * interm.z; + scalar_t rwf_s_e = rwf * sig.s * interm.e_final; + scalar_t rwf_e_sq_y = rwf * interm.e_final_sq * interm.y; + for (size_t i = interm.c_bpp_mn - 1; i != SIZE_MAX; --i) + { + h_scalars[i] += rwf_s_e * s_vec[interm.c_bpp_mn - 1 - i] - rwf_e_sq_z - rwf_e_sq_y * d[i]; + rwf_e_sq_y *= interm.y; + } + + DBG_PRINT("Hs(h_scalars): " << h_scalars.calc_hs()); + + // G point multiplicands: + // rwf * (r' y s' - e ^ 2 * ((z - z ^ 2)*SUM(y^>mn) - z * y^(mn+1) * SUM(d)) = + // = rwf * r' y s' - rwf * e^2 * (z - z ^ 2)*SUM(y^>mn) + rwf * e^2 * z * y^(mn+1) * SUM(d) + G_scalar += rwf * sig.r * interm.y * sig.s + rwf_e_sq_y * sum_d * interm.z; + G_scalar -= rwf * interm.e_final_sq * (interm.z - interm.z_sq) * sum_of_powers(interm.y, log2_mn); + DBG_PRINT("sum_y: " << sum_of_powers(interm.y, log2_mn)); + DBG_PRINT("G_scalar: " << G_scalar); + + // H point multiplicands: + // rwf * delta_1 + H_scalar += rwf * sig.delta_1; + DBG_PRINT("H_scalar: " << H_scalar); + + // H2 point multiplicands: + // rwf * delta_2 + H2_scalar += rwf * sig.delta_2; + DBG_PRINT("H2_scalar: " << H2_scalar); + + // uncommon generators' multiplicands + point_t summand_8 = c_point_0; // this summand to be multiplied by 8 before adding to the main summand + // - rwf * e^2 * A0 + summand_8 -= rwf * interm.e_final_sq * interm.A0; + DBG_PRINT("A0_scalar: " << c_scalar_Lm1 * interm.e_final_sq * rwf); + + // - rwf * e^2 * y^(mn+1) * (SUM{j=1..m} (z^2)^j * V_j)) + scalar_t e_sq_y_mn1_z_sq_power = rwf * interm.e_final_sq * y_power_mnp1; + for (size_t j = 0; j < bsc.commitments.size(); ++j) + { + e_sq_y_mn1_z_sq_power *= interm.z_sq; + summand_8 -= e_sq_y_mn1_z_sq_power * bsc.commitments[j]; + DBG_PRINT("V_scalar[" << j << "]: " << c_scalar_Lm1 * e_sq_y_mn1_z_sq_power); + } + + // - rwf * e^2 * SUM{j=1..log(n)}(e_j^2 * L_j + e_j^-2 * R_j) + scalar_t rwf_e_sq = rwf * interm.e_final_sq; + for (size_t j = 0; j < log2_mn; ++j) + { + summand_8 -= rwf_e_sq * (interm.e_sq[j] * interm.L[j] + get_e_inv(j) * get_e_inv(j) * interm.R[j]); + DBG_PRINT("L_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * interm.e_sq[j]); + DBG_PRINT("R_scalar[" << j << "]: " << c_scalar_Lm1 * rwf_e_sq * get_e_inv(j) * get_e_inv(j)); + } + + // - rwf * e * A - rwf * B = 0 + summand_8 -= rwf * interm.e_final * interm.A + rwf * interm.B; + DBG_PRINT("A_scalar: " << c_scalar_Lm1 * rwf * interm.e_final); + DBG_PRINT("B_scalar: " << c_scalar_Lm1 * rwf); + + summand_8.modify_mul8(); + summand += summand_8; + } + + point_t GH_exponents = c_point_0; + CT::calc_pedersen_commitment_2(G_scalar, H_scalar, H2_scalar, GH_exponents); + bool result = msm_and_check_zero(g_scalars, h_scalars, summand + GH_exponents); + if (result) + DBG_PRINT(ENDL << " . . . . bppe_verify() -- SUCCEEDED!!!" << ENDL); + return result; +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + } + +#undef DBG_VAL_PRINT +#undef DBG_PRINT + +} // namespace crypto diff --git a/crypto/upstream/range_proofs.cpp b/crypto/upstream/range_proofs.cpp new file mode 100755 index 0000000..d2932b3 --- /dev/null +++ b/crypto/upstream/range_proofs.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#include "range_proofs.h" + +namespace crypto +{ + // TODO @#@# redesign needed, consider changing to inline constexpr + const point_t& bpp_ct_generators_HGX::bpp_G = c_point_H; + const point_t& bpp_ct_generators_HGX::bpp_H = c_point_G; + const point_t& bpp_ct_generators_HGX::bpp_H2 = c_point_X; + + const point_t& bpp_ct_generators_UGX::bpp_G = c_point_U; + const point_t& bpp_ct_generators_UGX::bpp_H = c_point_G; + const point_t& bpp_ct_generators_UGX::bpp_H2 = c_point_X; +} diff --git a/crypto/upstream/range_proofs.h b/crypto/upstream/range_proofs.h new file mode 100755 index 0000000..c35d34f --- /dev/null +++ b/crypto/upstream/range_proofs.h @@ -0,0 +1,159 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once + +#include "epee/include/misc_log_ex.h" +#include "crypto-sugar.h" + +namespace crypto +{ + + // returns x + x^2 + x^3 + ... + x^(2^f) + // == x * (x + 1) * (x^2 + 1) * (x^4 + 1) * ...(x^(f+1) + 1) + inline scalar_t sum_of_powers(scalar_t x, size_t f) + { + scalar_t result = x; + for (size_t i = 0; i < f; ++i) + { + result.assign_muladd(result, x, result); + x *= x; + } + return result; + } + + // returns least significant bit uing de Bruijn sequence + // http://graphics.stanford.edu/~seander/bithacks.html + inline uint8_t calc_lsb_32(uint32_t v) + { + static const uint8_t multiply_de_bruijn_bit_position[32] = + { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + return multiply_de_bruijn_bit_position[((uint32_t)((v & -(int32_t)v) * 0x077CB531U)) >> 27]; + } + + + //////////////////////////////////////// + // crypto trait for Zano + //////////////////////////////////////// + struct bpp_ct_generators_HGX + { + // NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp + static const point_t& bpp_G; + static const point_t& bpp_H; + static const point_t& bpp_H2; + }; + + struct bpp_ct_generators_UGX + { + // NOTE! This notation follows the original BP+ whitepaper, see mapping to Zano's generators in range_proofs.cpp + static const point_t& bpp_G; + static const point_t& bpp_H; + static const point_t& bpp_H2; + }; + + + template + struct bpp_crypto_trait_zano : gen_trait_t + { + static constexpr size_t c_bpp_n = N; // the upper bound for the witness's range + static constexpr size_t c_bpp_values_max = values_max; // maximum number of elements in BP+ proof, i.e. max allowed BP+ outputs + static constexpr size_t c_bpp_log2_n = constexpr_ceil_log2(c_bpp_n); + static constexpr size_t c_bpp_mn_max = c_bpp_n * c_bpp_values_max; + + static void calc_pedersen_commitment(const scalar_t& value, const scalar_t& mask, point_t& commitment) + { + // commitment = value * bpp_G + mask * bpp_H + commitment = operator*(value, bpp_G) + mask * bpp_H; + } + + static void calc_pedersen_commitment_2(const scalar_t& value, const scalar_t& mask1, const scalar_t& mask2, point_t& commitment) + { + // commitment = value * bpp_G + mask1 * bpp_H * mask2 * bpp_H2 + commitment = operator*(value, bpp_G) + mask1 * bpp_H + mask2 * bpp_H2; + } + + static const scalar_t& get_initial_transcript() + { + static scalar_t value = hash_helper_t::hs("Lethean BP+ initial transcript"); + return value; + } + + // assumes hsc is cleared + static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector& points) + { + hsc.add_scalar(e); + hsc.add_points_array(points); + e = hsc.calc_hash(); + } + + // assumes hsc is cleared + static void update_transcript(hash_helper_t::hs_t& hsc, scalar_t& e, const std::vector& pub_keys) + { + hsc.add_scalar(e); + for(auto p : pub_keys) + hsc.add_pub_key(*p); + e = hsc.calc_hash(); + } + + // TODO: refactor with proper OOB handling + static const point_t& get_generator(bool select_H, size_t index) + { + if (index >= c_bpp_mn_max) + return c_point_0; // out of bound + + static std::vector generators(2 * c_bpp_mn_max); + static bool calculated = false; + if (!calculated) + { + scalar_t hash_buf[2] = { hash_helper_t::hs("Lethean BP+ generator"), 0 }; + for (size_t i = 0; i < 2 * c_bpp_mn_max; ++i) + { + hash_buf[1].m_u64[0] = i; + ge_bytes_hash_to_ec(&generators[i].m_p3, &hash_buf, sizeof hash_buf); + } + calculated = true; + } + + return generators[2 * index + (select_H ? 1 : 0)]; + } + + static const scalar_t& get_2_to_the_power_of_N_minus_1() + { + static scalar_t result = scalar_t::power_of_2(c_bpp_n) - 1; + return result; + } + + using gen_trait_t::bpp_G; + using gen_trait_t::bpp_H; + using gen_trait_t::bpp_H2; + }; // struct bpp_crypto_trait_zano + + + typedef bpp_crypto_trait_zano bpp_crypto_trait_ZC_out; + + typedef bpp_crypto_trait_zano bpp_crypto_trait_Zarcanum; + + +} // namespace crypto + +#include "epee/include/profile_tools.h" // <- remove this, sowle + +#include "msm.h" +#include "range_proof_bpp.h" +#include "range_proof_bppe.h" diff --git a/crypto/upstream/zarcanum.cpp b/crypto/upstream/zarcanum.cpp new file mode 100755 index 0000000..12f386b --- /dev/null +++ b/crypto/upstream/zarcanum.cpp @@ -0,0 +1,435 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#include "epee/include/misc_log_ex.h" +#include "zarcanum.h" +#include "range_proofs.h" +#include "../currency_core/crypto_config.h" // TODO: move it to the crypto +#include "../common/crypto_stream_operators.h" // TODO: move it to the crypto + +#if 0 +# define DBG_VAL_PRINT(x) std::cout << std::setw(30) << std::left << #x ": " << x << std::endl +# define DBG_PRINT(x) std::cout << x << std::endl +#else +# define DBG_VAL_PRINT(x) (void(0)) +# define DBG_PRINT(x) (void(0)) +#endif + +namespace crypto +{ + const scalar_t c_zarcanum_z_coeff_s = { 0, 1, 0, 0 }; // c_scalar_2p64 + const mp::uint256_t c_zarcanum_z_coeff_mp = c_zarcanum_z_coeff_s.as_boost_mp_type(); + + template + inline std::ostream &operator <<(std::ostream &o, const std::vector &v) + { + for(size_t i = 0, n = v.size(); i < n; ++i) + o << ENDL << " [" << std::setw(2) << i << "]: " << v[i]; + return o; + } + + mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty) + { + //LOG_PRINT_GREEN_L0(ENDL << "floor( l / (z * D) ) = " << c_scalar_L.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * pos_difficulty)); + return c_scalar_L.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * pos_difficulty); // == floor( l / (z * D) ) + } + + mp::uint256_t zarcanum_precalculate_z_l_div_z_D(const mp::uint128_t& pos_difficulty) + { + //LOG_PRINT_GREEN_L0(ENDL << "z * floor( l / (z * D) ) = " << c_zarcanum_z_coeff_mp * (c_scalar_L.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * pos_difficulty))); + return c_zarcanum_z_coeff_mp * (c_scalar_L.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * pos_difficulty)); // == z * floor( l / (z * D) ) + } + + bool zarcanum_check_main_pos_inequality(const hash& kernel_hash, const scalar_t& blinding_mask, const scalar_t& secret_q, + const scalar_t& last_pow_block_id_hashed, const mp::uint256_t& z_l_div_z_D, uint64_t stake_amount, mp::uint256_t& lhs, mp::uint512_t& rhs) + { + scalar_t lhs_s = scalar_t(kernel_hash) * (blinding_mask + secret_q + last_pow_block_id_hashed); // == h * (f + q + f') mod l + lhs = lhs_s.as_boost_mp_type(); + rhs = static_cast(z_l_div_z_D) * stake_amount; // == floor( l / (z * D) ) * z * a + + //LOG_PRINT_GREEN_L0(ENDL << + // "z_l_div_z_D = " << z_l_div_z_D << ENDL << + // "stake_amount = " << stake_amount << ENDL << + // "lhs = " << lhs << ENDL << + // "rhs = " << rhs); + + return lhs < rhs; // h * (f + q + f') mod l < floor( l / (z * D) ) * z * a + } + + #define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("zarcanum_generate_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, + const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki, + const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, uint64_t stake_amount, + const scalar_t& stake_out_asset_id_blinding_mask, const scalar_t& stake_out_amount_blinding_mask, const scalar_t& pseudo_out_amount_blinding_mask, + zarcanum_proof& result, uint8_t* p_err /* = nullptr */) + { + DBG_PRINT("zarcanum_generate_proof"); + const scalar_t a = stake_amount; + const scalar_t h = scalar_t(kernel_hash); + const scalar_t f_plus_q = stake_out_amount_blinding_mask + secret_q; + const scalar_t f_plus_q_plus_fp = f_plus_q + last_pow_block_id_hashed; + const scalar_t lhs = h * f_plus_q_plus_fp; // == h * (f + q + f') mod l + const mp::uint256_t d_mp = lhs.as_boost_mp_type() / (c_zarcanum_z_coeff_mp * stake_amount) + 1; + result.d = scalar_t(d_mp); + + const scalar_t dz = result.d * c_zarcanum_z_coeff_s; + + const scalar_t ba = dz * a - lhs; // b_a = dza - h(f + q + f') + + const scalar_t bf = dz * f_plus_q - h * a; // b_f = dz(f + q) - ha + + const scalar_t x0 = scalar_t::random(), x1 = scalar_t::random(), x2 = scalar_t::random(); + + const scalar_t bx = x2 - h * x1 + dz * x0; // b_x = x'' - hx' + dzx + + point_t C = x0 * c_point_X + a * c_point_H + f_plus_q * c_point_G; + point_t C_prime = x1 * c_point_X + f_plus_q * c_point_H + a * c_point_G; + point_t E = bx * c_point_X + ba * c_point_H + bf * c_point_G; + + result.C = (c_scalar_1div8 * C).to_public_key(); + result.C_prime = (c_scalar_1div8 * C_prime).to_public_key(); + result.E = (c_scalar_1div8 * E).to_public_key(); + + // three proofs with a shared Fiat-Shamir challenge c + // 1) linear composition proof for the fact, that C + C' = lin(X, H + G) = (x + x') X + (a + f + q) (H + G) + // 2) linear composition proof for the fact, that C - C' = lin(X, H - G) = (x - x') X + (a - f - q) (H - G) + // 3) Schnorr proof for the fact, that hC' - dzC + E + f'hH = lin(X) = x'' X + + point_t F = h * C_prime - dz * C + E + last_pow_block_id_hashed * h * c_point_H; + + DBG_VAL_PRINT(h); DBG_VAL_PRINT(last_pow_block_id_hashed); DBG_VAL_PRINT(dz); + DBG_VAL_PRINT(C); DBG_VAL_PRINT(C_prime); DBG_VAL_PRINT(E); DBG_VAL_PRINT(F); + + scalar_t r0 = scalar_t::random(); + scalar_t r1 = scalar_t::random(); + scalar_t r2 = scalar_t::random(); + scalar_t r3 = scalar_t::random(); + scalar_t r4 = scalar_t::random(); + + point_t R_01 = r0 * c_point_X + r1 * c_point_H_plus_G; + point_t R_23 = r2 * c_point_X + r3 * c_point_H_minus_G; + point_t R_4 = r4 * c_point_X; + + hash_helper_t::hs_t hash_calc(7); + hash_calc.add_32_chars(CRYPTO_HDS_ZARCANUM_PROOF_HASH); + hash_calc.add_point(R_01); + hash_calc.add_point(R_23); + hash_calc.add_point(R_4); + hash_calc.add_point(C + C_prime); + hash_calc.add_point(C - C_prime); + hash_calc.add_point(F); + result.c = hash_calc.calc_hash(); + + result.y0 = r0 + result.c * (x0 + x1); // y_0 = r_0 + c (x + x') + result.y1 = r1 + result.c * (a + f_plus_q); // y_1 = r_1 + c (a + f + q) + result.y2 = r2 + result.c * (x0 - x1); // y_2 = r_2 + c (x - x') + result.y3 = r3 + result.c * (a - f_plus_q); // y_3 = r_3 + c (a - f - q) + result.y4 = r4 + result.c * x2; // y_4 = r_4 + c x'' + + // range proof for E + const scalar_vec_t values = { ba }; // H component + const scalar_vec_t masks = { bf }; // G component + const scalar_vec_t masks2 = { bx }; // X component + const std::vector E_1div8_vec_ptr = { &result.E }; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bppe_gen(values, masks, masks2, E_1div8_vec_ptr, result.E_range_proof), 10); + + // = five-layers ring signature data outline = + // (j in [0, ring_size-1]) + // layer 0 ring + // A[j] ( = ring[j].stealth_address) + // layer 0 secret (with respect to G) + // secret_x + // layer 0 linkability + // stake_ki + // + // layer 1 ring + // ring[j].amount_commitment - pseudo_out_amount_commitment + // layer 1 secret (with respect to G) + // stake_out_amount_blinding_mask - pseudo_out_amount_blinding_mask ( = f_i - f'_i ) + // + // additional layer for confidential assets: + // + // layer 2 ring + // ring[j].blinded_asset_id - pseudo_out_blinded_asset_id + // layer 2 secret (with respect to X) + // -pseudo_out_asset_id_blinding_mask ( = -r'_i ) + // + // additional layers for Zarcanum: + // + // layer 3 ring + // C - A[j] - Q[j] + // layer 3 secret (with respect to X) + // x0 - a * stake_out_asset_id_blinding_mask ( = x - a * r_i ) + // + // layer 4 ring + // Q[j] + // layer 4 secret (with respect to G) + // secret_q + + // such pseudo_out_asset_id_blinding_mask effectively makes pseudo_out_blinded_asset_id == currency::native_coin_asset_id_pt == point_H + scalar_t pseudo_out_asset_id_blinding_mask = -stake_out_asset_id_blinding_mask; // T^p_i = T_i + (-r_i) * X = H + + point_t stake_out_asset_id = c_point_H + stake_out_asset_id_blinding_mask * c_point_X; // T_i = H + r_i * X + + point_t pseudo_out_amount_commitment = a * stake_out_asset_id + pseudo_out_amount_blinding_mask * c_point_G; // A^p_i = a_i * T_i + f'_i * G + result.pseudo_out_amount_commitment = (c_scalar_1div8 * pseudo_out_amount_commitment).to_public_key(); + + TRY_ENTRY() + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(generate_CLSAG_GGXXG(m, ring, pseudo_out_amount_commitment, c_point_H, C, stake_ki, + secret_x, stake_out_amount_blinding_mask - pseudo_out_amount_blinding_mask, -pseudo_out_asset_id_blinding_mask, x0 - a * stake_out_asset_id_blinding_mask, secret_q, secret_index, + result.clsag_ggxxg), 20); + CATCH_ENTRY2(false); + + return true; + } + #undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + + + #define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("zarcanum_verify_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + bool zarcanum_verify_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, + const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki, + const mp::uint128_t& pos_difficulty, + const zarcanum_proof& sig, uint8_t* p_err /* = nullptr */) noexcept + { + TRY_ENTRY() + { + DBG_PRINT("zarcanum_verify_proof"); + //bool r = false; + + //std::cout << "===== zarcanum_verify_proof =====" << ENDL + // << "m: " << m << ENDL + // << "kernel_hash: " << kernel_hash << ENDL + // << "last_pow_block_id_hashed: " << last_pow_block_id_hashed << ENDL + // << "stake_ki: " << stake_ki << ENDL + // << "pos_difficulty: " << pos_difficulty << ENDL; + //size_t ii = 0; + //for(const auto& el : ring) + //{ + // std::cout << "[" << ii << "]" << ENDL + // << " amount_commitment: " << el.amount_commitment << ENDL + // << " blinded_asset_id: " << el.blinded_asset_id << ENDL + // << " concealing_point: " << el.concealing_point << ENDL + // << " stealth_address: " << el.stealth_address << ENDL; + //} + + // make sure 0 < d <= l / floor(z * D) + const mp::uint256_t l_div_z_D_mp = zarcanum_precalculate_l_div_z_D(pos_difficulty); + const scalar_t l_div_z_D(l_div_z_D_mp); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(!sig.d.is_zero() && sig.d < l_div_z_D, 2); + const scalar_t dz = sig.d * c_zarcanum_z_coeff_s; + + // calculate h + const scalar_t h = scalar_t(kernel_hash); + + // calculate F + point_t C_prime = point_t(sig.C_prime); + C_prime.modify_mul8(); + point_t C = point_t(sig.C); + C.modify_mul8(); + point_t E = point_t(sig.E); + E.modify_mul8(); + point_t F = h * C_prime - dz * C + E + last_pow_block_id_hashed * h * c_point_H; + + DBG_VAL_PRINT(h); DBG_VAL_PRINT(last_pow_block_id_hashed); DBG_VAL_PRINT(dz); + DBG_VAL_PRINT(C); DBG_VAL_PRINT(C_prime); DBG_VAL_PRINT(E); DBG_VAL_PRINT(F); + + // check three proofs with a shared Fiat-Shamir challenge c + point_t C_plus_C_prime = C + C_prime; + point_t C_minus_C_prime = C - C_prime; + hash_helper_t::hs_t hash_calc(7); + hash_calc.add_32_chars(CRYPTO_HDS_ZARCANUM_PROOF_HASH); + hash_calc.add_point(sig.y0 * c_point_X + sig.y1 * c_point_H_plus_G - sig.c * C_plus_C_prime); // y_0 * X + y1 (H + G) - c (C + C') + hash_calc.add_point(sig.y2 * c_point_X + sig.y3 * c_point_H_minus_G - sig.c * C_minus_C_prime); // y_2 * X + y3 (H - G) - c (C - C') + hash_calc.add_point(sig.y4 * c_point_X - sig.c * F); // y_4 * X - c * F + hash_calc.add_point(C_plus_C_prime); + hash_calc.add_point(C_minus_C_prime); + hash_calc.add_point(F); + scalar_t c_prime = hash_calc.calc_hash(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.c == c_prime, 3); + + // check extended range proof for E + std::vector E_for_range_proof = { point_t(sig.E) }; // consider changing to 8*sig.E to avoid additional conversion + std::vector range_proofs = { bppe_sig_commit_ref_t(sig.E_range_proof, E_for_range_proof) }; + + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(bppe_verify(range_proofs), 10); + + static public_key native_coin_asset_id = (c_scalar_1div8 * c_point_H).to_public_key(); // consider making it less ugly -- sowle + + // check extended CLSAG-GGXG ring signature + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(verify_CLSAG_GGXXG(m, ring, sig.pseudo_out_amount_commitment, native_coin_asset_id, sig.C, stake_ki, sig.clsag_ggxxg), 1); + } + CATCH_ENTRY_CUSTOM2({if (p_err) *p_err = 100;}, false) + + return true; + } + + #undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("generate_vector_UG_aggregation_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets0, const scalar_vec_t& g_secrets1, + const std::vector& amount_commitments, + const std::vector& amount_commitments_for_rp_aggregation, + const std::vector& blinded_asset_ids, + vector_UG_aggregation_proof& result, uint8_t* p_err /* = nullptr */) + { + // w - public random weighting factor + // proof of knowing e_j and y'' in zero knowledge in the following eq: + // E_j + w * E'_j = e_j * (T'_j + w * U) + (y_j + w * y'_j) * G + // where: + // e_j -- output's amount + // T'_j -- output's blinded asset tag + // E_j == e_j * T'_j + y_j * G -- output's amount commitments + // E'_j == e_j * U + y'_j * G -- additional commitment to the same amount for range proof aggregation + + // amount_commitments[j] + w * amount_commitments_for_rp_aggregation[j] + // == + // u_secrets[j] * (blinded_asset_ids[j] + w * U) + (g_secrets0[j] + w * g_secrets1[j]) * G + + const size_t n = u_secrets.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n != 0, 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == g_secrets0.size(), 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == g_secrets1.size(), 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments.size(), 4); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == amount_commitments_for_rp_aggregation.size(), 5); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n == blinded_asset_ids.size(), 6); + + hash_helper_t::hs_t hash_calculator(1 + 3 * n); + hash_calculator.add_hash(m); + hash_calculator.add_points_array(amount_commitments); + hash_calculator.add_points_array(amount_commitments_for_rp_aggregation); + scalar_t w = hash_calculator.calc_hash(false); // don't clean the buffer + DBG_VAL_PRINT(w); + +#ifndef NDEBUG + for(size_t j = 0; j < n; ++j) + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(amount_commitments[j] + w * amount_commitments_for_rp_aggregation[j] == u_secrets[j] * (blinded_asset_ids[j] + w * c_point_U) + (g_secrets0[j] + w * g_secrets1[j]) * c_point_G, 20); +#endif + + result.amount_commitments_for_rp_aggregation.clear(); + result.y0s.clear(); + result.y1s.clear(); + + scalar_vec_t r0, r1; + r0.resize_and_make_random(n); + r1.resize_and_make_random(n); + + std::vector asset_tag_plus_U_vec(n); + for(size_t j = 0; j < n; ++j) + asset_tag_plus_U_vec[j] = blinded_asset_ids[j] + w * c_point_U; + + std::vector R(n); + for(size_t j = 0; j < n; ++j) + R[j].assign_mul_plus_G(r0[j], asset_tag_plus_U_vec[j], r1[j]); // R[j] = r0[j] * asset_tag_plus_U_vec[j] + r1[j] * G + + hash_calculator.add_points_array(R); + result.c = hash_calculator.calc_hash(); + + DBG_VAL_PRINT(asset_tag_plus_U_vec); DBG_VAL_PRINT(m); DBG_VAL_PRINT(amount_commitments); DBG_VAL_PRINT(amount_commitments_for_rp_aggregation); DBG_VAL_PRINT(R); + DBG_VAL_PRINT(result.c); + + for(size_t j = 0; j < n; ++j) + { + result.y0s.emplace_back(r0[j] - result.c * u_secrets[j]); + result.y1s.emplace_back(r1[j] - result.c * (g_secrets0[j] + w * g_secrets1[j])); + result.amount_commitments_for_rp_aggregation.emplace_back((c_scalar_1div8 * amount_commitments_for_rp_aggregation[j]).to_public_key()); + } + + return true; + } +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + +#define CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(cond, err_code) \ + if (!(cond)) { LOG_PRINT_RED("verify_vector_UG_aggregation_proof: \"" << #cond << "\" is false at " << LOCATION_SS << ENDL << "error code = " << (int)err_code, LOG_LEVEL_3); \ + if (p_err) { *p_err = err_code; } return false; } + + bool verify_vector_UG_aggregation_proof(const hash& m, const std::vector amount_commitments_1div8, const std::vector blinded_asset_ids_1div8, + const vector_UG_aggregation_proof& sig, uint8_t* p_err /* = nullptr */) noexcept + { + TRY_ENTRY() + { + const size_t n = amount_commitments_1div8.size(); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(n > 0, 1); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(blinded_asset_ids_1div8.size() == n, 2); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.amount_commitments_for_rp_aggregation.size() == n, 3); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.y0s.size() == n, 4); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.y1s.size() == n, 5); + + hash_helper_t::hs_t hash_calculator(1 + 3 * n); + hash_calculator.add_hash(m); + DBG_VAL_PRINT(m); + + std::vector amount_commitments_pt; + for(size_t j = 0; j < n; ++j) + { + point_t A = point_t(*amount_commitments_1div8[j]).modify_mul8(); + hash_calculator.add_point(A); + amount_commitments_pt.emplace_back(A); + DBG_VAL_PRINT(A); + } + + std::vector amount_commitments_for_rp_aggregation_pt; + for(size_t j = 0; j < n; ++j) + { + point_t Arpa = point_t(sig.amount_commitments_for_rp_aggregation[j]).modify_mul8(); + hash_calculator.add_point(Arpa); // TODO @#@ performance: consider adding premultiplied by 1/8 points to the hash + amount_commitments_for_rp_aggregation_pt.emplace_back(Arpa); + DBG_VAL_PRINT(Arpa); + } + + scalar_t w = hash_calculator.calc_hash(false); // don't clear the buffer + DBG_VAL_PRINT(w); + + std::vector asset_tag_plus_U_vec(n); + for(size_t j = 0; j < n; ++j) + asset_tag_plus_U_vec[j] = point_t(*blinded_asset_ids_1div8[j]).modify_mul8() + w * c_point_U; + DBG_VAL_PRINT(asset_tag_plus_U_vec); + + for(size_t j = 0; j < n; ++j) + { + hash_calculator.add_pub_key(point_t( + sig.y0s[j] * asset_tag_plus_U_vec[j] + + sig.y1s[j] * c_point_G + + sig.c * (amount_commitments_pt[j] + w * amount_commitments_for_rp_aggregation_pt[j]) + ).to_public_key()); + DBG_VAL_PRINT(hash_calculator.m_elements.back().pk); + } + + scalar_t c = hash_calculator.calc_hash(); + DBG_VAL_PRINT(c); DBG_VAL_PRINT(sig.c); + CHECK_AND_FAIL_WITH_ERROR_IF_FALSE(sig.c == c, 0); + } + CATCH_ENTRY_CUSTOM2({if (p_err) *p_err = 100; }, false) + + return true; + } +#undef CHECK_AND_FAIL_WITH_ERROR_IF_FALSE + + + +} // namespace crypto diff --git a/crypto/upstream/zarcanum.h b/crypto/upstream/zarcanum.h new file mode 100755 index 0000000..5621c78 --- /dev/null +++ b/crypto/upstream/zarcanum.h @@ -0,0 +1,314 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// +#pragma once +#include "crypto-sugar.h" +#include "range_proofs.h" +#include "clsag.h" + +namespace crypto +{ + extern const mp::uint256_t c_zarcanum_z_coeff_mp; + extern const scalar_t c_zarcanum_z_coeff_s; + + mp::uint256_t zarcanum_precalculate_l_div_z_D(const mp::uint128_t& pos_difficulty); + mp::uint256_t zarcanum_precalculate_z_l_div_z_D(const mp::uint128_t& pos_difficulty); + + bool zarcanum_check_main_pos_inequality(const hash& kernel_hash, const scalar_t& blinding_mask, const scalar_t& secret_q, + const scalar_t& last_pow_block_id_hashed, const mp::uint256_t& z_l_div_z_D_, uint64_t stake_amount, mp::uint256_t& lhs, mp::uint512_t& rhs); + + + struct zarcanum_proof + { + scalar_t d = 0; + public_key C; // premultiplied by 1/8 + public_key C_prime; // premultiplied by 1/8 + public_key E; // premultiplied by 1/8 + + scalar_t c; // shared Fiat-Shamir challenge for the following three proofs + scalar_t y0; // 1st linear composition proof + scalar_t y1; // ( C + C' = lin(X, H + G) ) + scalar_t y2; // 2nd linear composition proof + scalar_t y3; // ( C - C' = lin(X, H - G) ) + scalar_t y4; // Schnorr proof (F = lin(X)) + + bppe_signature E_range_proof; + + public_key pseudo_out_amount_commitment; // premultiplied by 1/8 + CLSAG_GGXXG_signature clsag_ggxxg; + }; + + bool zarcanum_generate_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, + const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki, + const scalar_t& secret_x, const scalar_t& secret_q, uint64_t secret_index, uint64_t stake_amount, + const scalar_t& stake_out_asset_id_blinding_mask, const scalar_t& stake_out_amount_blinding_mask, const scalar_t& pseudo_out_amount_blinding_mask, + zarcanum_proof& result, uint8_t* p_err = nullptr); + + + bool zarcanum_verify_proof(const hash& m, const hash& kernel_hash, const std::vector& ring, + const scalar_t& last_pow_block_id_hashed, const key_image& stake_ki, + const mp::uint128_t& pos_difficulty, + const zarcanum_proof& sig, uint8_t* p_err = nullptr) noexcept; + + + // TODO @#@#: make sure it is used, implement, then move it to an appropriate place + struct linear_composition_proof + { + scalar_t c; + scalar_t y0; + scalar_t y1; + }; + + enum generator_tag { gt_void = 0, gt_G = 1, gt_H = 2, gt_H2 = 3, gt_X = 4, gt_U = 5 }; + + template + bool generate_linear_composition_proof(const hash& m, const public_key& A, const scalar_t& secret_a, const scalar_t& secret_b, linear_composition_proof& result, uint8_t* p_err = nullptr) + { + // consider embedding generators' tags into random entropy to distinguish proofs made with different generators during verification + return false; + } + + template + bool verify_linear_composition_proof(const hash& m, const public_key& A, const linear_composition_proof& sig, uint8_t* p_err = nullptr) + { + return false; + } + + + struct generic_schnorr_sig + { + scalar_t c; + scalar_t y; + }; + + + template + inline bool generate_schnorr_sig_custom_generator(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result, const generator_t& g_point_g) + { +#ifndef NDEBUG + if (A != secret_a * g_point_g) + return false; +#endif + scalar_t r = scalar_t::random(); + point_t R = r * g_point_g; + hash_helper_t::hs_t hsc(3); + hsc.add_hash(m); + hsc.add_point(A); + hsc.add_point(R); + result.c = hsc.calc_hash(); + result.y.assign_mulsub(result.c, secret_a, r); // y = r - c * secret_a + return true; + } + + template + inline bool generate_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result); + + template<> + inline bool generate_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result) + { + return generate_schnorr_sig_custom_generator(m, A, secret_a, result, c_point_G); + } + + template<> + inline bool generate_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, generic_schnorr_sig& result) + { + return generate_schnorr_sig_custom_generator(m, A, secret_a, result, c_point_X); + } + + inline bool generate_schnorr_sig(const hash& m, const public_key& A, const secret_key& secret_a, generic_schnorr_sig& result) + { + return generate_schnorr_sig(m, point_t(A), scalar_t(secret_a), result); + } + + inline bool generate_schnorr_sig(const hash& m, const secret_key& secret_a, generic_schnorr_sig& result) + { + scalar_t secret_a_s(secret_a); + if (!secret_a_s.is_reduced()) + return false; + point_t A = secret_a_s * c_point_G; + return generate_schnorr_sig_custom_generator(m, A, secret_a_s, result, c_point_G); + } + + + template + inline bool verify_schnorr_sig(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept; + + // TODO @#@# make optimized version inline bool verify_schnorr_sig(const hash& m, const point_t& A, const generic_schnorr_sig& sig) noexcept; + // and change check_tx_balance() accordingly + + template<> + inline bool verify_schnorr_sig(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept + { + try + { + if (!sig.c.is_reduced() || !sig.y.is_reduced()) + return false; + hash_helper_t::hs_t hsc(3); + hsc.add_hash(m); + hsc.add_pub_key(A); + hsc.add_point(point_t(A).mul_plus_G(sig.c, sig.y)); // sig.y * G + sig.c * A + return sig.c == hsc.calc_hash(); + } + catch(...) + { + return false; + } + } + + template<> + inline bool verify_schnorr_sig(const hash& m, const public_key& A, const generic_schnorr_sig& sig) noexcept + { + try + { + if (!sig.c.is_reduced() || !sig.y.is_reduced()) + return false; + hash_helper_t::hs_t hsc(3); + hsc.add_hash(m); + hsc.add_pub_key(A); + hsc.add_point(sig.y * c_point_X + sig.c * point_t(A)); + return sig.c == hsc.calc_hash(); + } + catch(...) + { + return false; + } + } + + // -------------------------------------------- + + // multi-base Schnorr-like proof (two generators, two secrets, one Fiat-Shamir challenge) + struct generic_double_schnorr_sig + { + scalar_t c; + scalar_t y0; + scalar_t y1; + }; + + template + inline bool generate_double_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result); + + template<> + inline bool generate_double_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result) + { +#ifndef NDEBUG + if (A != secret_a * c_point_G || B != secret_b * c_point_G) + return false; +#endif + scalar_t r0 = scalar_t::random(); + scalar_t r1 = scalar_t::random(); + point_t R0 = r0 * c_point_G; + point_t R1 = r1 * c_point_G; + hash_helper_t::hs_t hsc(5); + hsc.add_hash(m); + hsc.add_point(A); + hsc.add_point(B); + hsc.add_point(R0); + hsc.add_point(R1); + result.c = hsc.calc_hash(); + result.y0.assign_mulsub(result.c, secret_a, r0); // y0 = r0 - c * secret_a + result.y1.assign_mulsub(result.c, secret_b, r1); // y1 = r1 - c * secret_b + return true; + } + + template<> + inline bool generate_double_schnorr_sig(const hash& m, const point_t& A, const scalar_t& secret_a, const point_t& B, const scalar_t& secret_b, generic_double_schnorr_sig& result) + { +#ifndef NDEBUG + if (A != secret_a * c_point_X || B != secret_b * c_point_G) + return false; +#endif + scalar_t r0 = scalar_t::random(); + scalar_t r1 = scalar_t::random(); + point_t R0 = r0 * c_point_X; + point_t R1 = r1 * c_point_G; + hash_helper_t::hs_t hsc(5); + hsc.add_hash(m); + hsc.add_point(A); + hsc.add_point(B); + hsc.add_point(R0); + hsc.add_point(R1); + result.c = hsc.calc_hash(); + result.y0.assign_mulsub(result.c, secret_a, r0); // y0 = r0 - c * secret_a + result.y1.assign_mulsub(result.c, secret_b, r1); // y1 = r1 - c * secret_b + return true; + } + + template + inline bool verify_double_schnorr_sig(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept; + + template<> + inline bool verify_double_schnorr_sig(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept + { + try + { + if (!sig.c.is_reduced() || !sig.y0.is_reduced() || !sig.y1.is_reduced()) + return false; + hash_helper_t::hs_t hsc(5); + hsc.add_hash(m); + hsc.add_point(A); + hsc.add_pub_key(B); + hsc.add_point(A.mul_plus_G(sig.c, sig.y0)); // sig.y0 * G + sig.c * A + hsc.add_point(point_t(B).mul_plus_G(sig.c, sig.y1)); // sig.y1 * G + sig.c * B + return sig.c == hsc.calc_hash(); + } + catch(...) + { + return false; + } + } + + template<> + inline bool verify_double_schnorr_sig(const hash& m, const point_t& A, const public_key& B, const generic_double_schnorr_sig& sig) noexcept + { + try + { + if (!sig.c.is_reduced() || !sig.y0.is_reduced() || !sig.y1.is_reduced()) + return false; + hash_helper_t::hs_t hsc(5); + hsc.add_hash(m); + hsc.add_point(A); + hsc.add_pub_key(B); + hsc.add_point(sig.y0 * c_point_X + sig.c * A); + hsc.add_point(point_t(B).mul_plus_G(sig.c, sig.y1)); // sig.y1 * G + sig.c * B + return sig.c == hsc.calc_hash(); + } + catch(...) + { + return false; + } + } + + + // TODO: improve this proof using random weightning factor + struct vector_UG_aggregation_proof + { + std::vector amount_commitments_for_rp_aggregation; // E' = e * U + y' * G, premultiplied by 1/8 + scalar_vec_t y0s; + scalar_vec_t y1s; + scalar_t c; // common challenge + }; + + bool generate_vector_UG_aggregation_proof(const hash& m, const scalar_vec_t& u_secrets, const scalar_vec_t& g_secrets0, const scalar_vec_t& g_secrets1, + const std::vector& amount_commitments, + const std::vector& amount_commitments_for_rp_aggregation, + const std::vector& blinded_asset_ids, + vector_UG_aggregation_proof& result, uint8_t* p_err = nullptr); + + bool verify_vector_UG_aggregation_proof(const hash& m, const std::vector amount_commitments_1div8, const std::vector blinded_asset_ids_1div8, + const vector_UG_aggregation_proof& sig, uint8_t* p_err = nullptr) noexcept; + + +} // namespace crypto \ No newline at end of file