From 5ce448a8d52bec3c3e8bd44629bfef870e06dac6 Mon Sep 17 00:00:00 2001 From: Yawning Angel Date: Thu, 2 Oct 2025 07:42:52 +0900 Subject: [PATCH] core/crypto: Start work on the NIST curves --- core/crypto/_fiat/field_p256r1/field.odin | 346 ++ core/crypto/_fiat/field_p256r1/field64.odin | 501 +++ .../_fiat/field_scalarp256r1/field.odin | 210 + .../_fiat/field_scalarp256r1/field64.odin | 569 +++ core/crypto/_weierstrass/fe.odin | 135 + core/crypto/_weierstrass/point.odin | 548 +++ core/crypto/_weierstrass/point_s11n_sec.odin | 95 + core/crypto/_weierstrass/sc.odin | 76 + core/crypto/_weierstrass/scalar_mul.odin | 204 + core/crypto/_weierstrass/secp256r1_table.odin | 3985 +++++++++++++++++ .../_weierstrass/tools/ecc_gen_tables.odin | 99 + core/crypto/crypto.odin | 3 + .../crypto/test_core_crypto_weierstrass.odin | 486 ++ 13 files changed, 7257 insertions(+) create mode 100644 core/crypto/_fiat/field_p256r1/field.odin create mode 100644 core/crypto/_fiat/field_p256r1/field64.odin create mode 100644 core/crypto/_fiat/field_scalarp256r1/field.odin create mode 100644 core/crypto/_fiat/field_scalarp256r1/field64.odin create mode 100644 core/crypto/_weierstrass/fe.odin create mode 100644 core/crypto/_weierstrass/point.odin create mode 100644 core/crypto/_weierstrass/point_s11n_sec.odin create mode 100644 core/crypto/_weierstrass/sc.odin create mode 100644 core/crypto/_weierstrass/scalar_mul.odin create mode 100644 core/crypto/_weierstrass/secp256r1_table.odin create mode 100644 core/crypto/_weierstrass/tools/ecc_gen_tables.odin create mode 100644 tests/core/crypto/test_core_crypto_weierstrass.odin diff --git a/core/crypto/_fiat/field_p256r1/field.odin b/core/crypto/_fiat/field_p256r1/field.odin new file mode 100644 index 000000000..b1662fd48 --- /dev/null +++ b/core/crypto/_fiat/field_p256r1/field.odin @@ -0,0 +1,346 @@ +package field_p256r1 + +import subtle "core:crypto/_subtle" +import "core:encoding/endian" +import "core:math/bits" +import "core:mem" + +fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) { + mem.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) +} + +fe_clear_vec :: proc "contextless" ( + arg1: []^Montgomery_Domain_Field_Element, +) { + for fe in arg1 { + fe_clear(fe) + } +} + +fe_from_bytes :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: []byte, + unsafe_assume_canonical := false, +) -> bool { + ensure_contextless(len(arg1) == 32, "p256r1: invalid fe input buffer") + + // Note: We assume the input is in big-endian. + tmp := Non_Montgomery_Domain_Field_Element { + endian.unchecked_get_u64be(arg1[24:]), + endian.unchecked_get_u64be(arg1[16:]), + endian.unchecked_get_u64be(arg1[8:]), + endian.unchecked_get_u64be(arg1[0:]), + } + defer mem.zero_explicit(&tmp, size_of(tmp)) + + // Check that tmp is in the the range [0, ELL). + if !unsafe_assume_canonical { + _, borrow := bits.sub_u64(ELL[0] - 1, tmp[0], 0) + _, borrow = bits.sub_u64(ELL[1], tmp[1], borrow) + _, borrow = bits.sub_u64(ELL[2], tmp[2], borrow) + _, borrow = bits.sub_u64(ELL[3], tmp[3], borrow) + if borrow != 0 { + return false + } + } + + fe_to_montgomery(out1, &tmp) + + return true +} + +fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { + ensure_contextless(len(out1) == 32, "p256r1: invalid fe output buffer") + + tmp: Non_Montgomery_Domain_Field_Element + fe_from_montgomery(&tmp, arg1) + + // Note: Likewise, output in big-endian. + endian.unchecked_put_u64be(out1[24:], tmp[0]) + endian.unchecked_put_u64be(out1[16:], tmp[1]) + endian.unchecked_put_u64be(out1[8:], tmp[2]) + endian.unchecked_put_u64be(out1[0:], tmp[3]) + + mem.zero_explicit(&tmp, size_of(tmp)) +} + +@(require_results) +fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int { + tmp: Montgomery_Domain_Field_Element + fe_sub(&tmp, arg1, arg2) + + // This will only underflow iff arg1 == arg2, and we return the borrow, + // which will be 1. + is_eq := subtle.u64_is_zero(fe_non_zero(&tmp)) + + fe_clear(&tmp) + + return int(is_eq) +} + +@(require_results) +fe_is_odd :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> int { + tmp: Non_Montgomery_Domain_Field_Element + defer mem.zero_explicit(&tmp, size_of(tmp)) + + fe_from_montgomery(&tmp, arg1) + return int(tmp[0] & 1) +} + +fe_pow2k :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, + arg2: uint, +) { + // Special case: `arg1^(2 * 0) = 1`, though this should never happen. + if arg2 == 0 { + fe_one(out1) + return + } + + fe_square(out1, arg1) + for _ in 1 ..< arg2 { + fe_square(out1, out1) + } +} + +fe_inv :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _110 = 2*_11 + // _111 = 1 + _110 + // _111000 = _111 << 3 + // _111111 = _111 + _111000 + // x12 = _111111 << 6 + _111111 + // x15 = x12 << 3 + _111 + // x16 = 2*x15 + 1 + // x32 = x16 << 16 + x16 + // i53 = x32 << 15 + // x47 = x15 + i53 + // i263 = ((i53 << 17 + 1) << 143 + x47) << 47 + // return (x47 + i263) << 2 + // + // Operations: 255 squares 11 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Note: Need to stash `arg1` (`xx`) in the case that `out1`/`arg1` alias, + // as `arg1` is used after `out1` has been altered. + t0, t1, xx: Montgomery_Domain_Field_Element = ---, ---, arg1^ + + // Step 1: z = x^0x2 + fe_square(out1, arg1) + + // Step 2: z = x^0x3 + fe_mul(out1, &xx, out1) + + // Step 3: z = x^0x6 + fe_square(out1, out1) + + // Step 4: z = x^0x7 + fe_mul(out1, &xx, out1) + + // Step 7: t0 = x^0x38 + fe_pow2k(&t0, out1, 3) + + // Step 8: t0 = x^0x3f + fe_mul(&t0, out1, &t0) + + // Step 14: t1 = x^0xfc0 + fe_pow2k(&t1, &t0, 6) + + // Step 15: t0 = x^0xfff + fe_mul(&t0, &t0, &t1) + + // Step 18: t0 = x^0x7ff8 + fe_pow2k(&t0, &t0, 3) + + // Step 19: z = x^0x7fff + fe_mul(out1, out1, &t0) + + // Step 20: t0 = x^0xfffe + fe_square(&t0, out1) + + // Step 21: t0 = x^0xffff + fe_mul(&t0, &xx, &t0) + + // Step 37: t1 = x^0xffff0000 + fe_pow2k(&t1, &t0, 16) + + // Step 38: t0 = x^0xffffffff + fe_mul(&t0, &t0, &t1) + + // Step 53: t0 = x^0x7fffffff8000 + fe_pow2k(&t0, &t0, 15) + + // Step 54: z = x^0x7fffffffffff + fe_mul(out1, out1, &t0) + + // Step 71: t0 = x^0xffffffff00000000 + fe_pow2k(&t0, &t0, 17) + + // Step 72: t0 = x^0xffffffff00000001 + fe_mul(&t0, &xx, &t0) + + // Step 215: t0 = x^0x7fffffff80000000800000000000000000000000000000000000 + fe_pow2k(&t0, &t0, 143) + + // Step 216: t0 = x^0x7fffffff800000008000000000000000000000007fffffffffff + fe_mul(&t0, out1, &t0) + + // Step 263: t0 = x^0x3fffffffc00000004000000000000000000000003fffffffffff800000000000 + fe_pow2k(&t0, &t0, 47) + + // Step 264: z = x^0x3fffffffc00000004000000000000000000000003fffffffffffffffffffffff + fe_mul(out1, out1, &t0) + + // Step 266: z = x^0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc + fe_pow2k(out1, out1, 2) + + fe_mul(out1, out1, &xx) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &t1, &xx}) +} + +@(require_results) +fe_sqrt :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) -> int { + // Square root candidate can be derived via exponentiation by `(p + 1) / 4` + // From sage: 28948022302589062190674361737351893382521535853822578548883407827216774463488 + // + // // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _1100 = _11 << 2 + // _1111 = _11 + _1100 + // _11110000 = _1111 << 4 + // _11111111 = _1111 + _11110000 + // x16 = _11111111 << 8 + _11111111 + // x32 = x16 << 16 + x16 + // return ((x32 << 32 + 1) << 96 + 1) << 94 + // + // Operations: 253 squares 7 multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Likewise this tramples over arg1, so stash another copy. + t0, xx: Montgomery_Domain_Field_Element = ---, arg1^ + + // Step 1: z = x^0x2 + fe_square(out1, arg1) + + // Step 2: z = x^0x3 + fe_mul(out1, &xx, out1) + + // Step 4: t0 = x^0xc + fe_pow2k(&t0, &xx, 2) + + // Step 5: z = x^0xf + fe_mul(out1, out1, &t0) + + // Step 9: t0 = x^0xf0 + fe_pow2k(&t0, out1, 4) + + // Step 10: z = x^0xff + fe_mul(out1, out1, &t0) + + // Step 18: t0 = x^0xff00 + fe_pow2k(&t0, out1, 8) + + // Step 19: z = x^0xffff + fe_mul(out1, out1, &t0) + + // Step 35: t0 = x^0xffff0000 + fe_pow2k(&t0, out1, 16) + + // Step 36: z = x^0xffffffff + fe_mul(out1, out1, &t0) + + // Step 68: z = x^0xffffffff00000000 + fe_pow2k(out1, out1, 32) + + // Step 69: z = x^0xffffffff00000001 + fe_mul(out1, &xx, out1) + + // Step 165: z = x^0xffffffff00000001000000000000000000000000 + fe_pow2k(out1, out1, 96) + + // Step 166: z = x^0xffffffff00000001000000000000000000000001 + fe_mul(out1, &xx, out1) + + // Step 260: z = x^0x3fffffffc0000000400000000000000000000000400000000000000000000000 + fe_pow2k(out1, out1, 94) + + // Ensure that our candidate is actually the square root. + check, zero: Montgomery_Domain_Field_Element + fe_square(&check, out1) + + is_valid := fe_equal(&check, &xx) + fe_cond_select(out1, &zero, out1, is_valid) + + fe_clear_vec([]^Montgomery_Domain_Field_Element{&t0, &xx, &check}) + + return is_valid + +} + +fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 +} + +fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +@(optimization_mode = "none") +fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Montgomery_Domain_Field_Element, arg1: int) { + mask := (u64(arg1) * 0xffffffffffffffff) + x := (out1[0] ~ out2[0]) & mask + x1, y1 := out1[0] ~ x, out2[0] ~ x + x = (out1[1] ~ out2[1]) & mask + x2, y2 := out1[1] ~ x, out2[1] ~ x + x = (out1[2] ~ out2[2]) & mask + x3, y3 := out1[2] ~ x, out2[2] ~ x + x = (out1[3] ~ out2[3]) & mask + x4, y4 := out1[3] ~ x, out2[3] ~ x + out1[0], out2[0] = x1, y1 + out1[1], out2[1] = x2, y2 + out1[2], out2[2] = x3, y3 + out1[3], out2[3] = x4, y4 +} + +@(optimization_mode = "none") +fe_cond_select :: #force_no_inline proc "contextless" ( + out1, arg1, arg2: ^Montgomery_Domain_Field_Element, + arg3: int, +) { + mask := (u64(arg3) * 0xffffffffffffffff) + x1 := ((mask & arg2[0]) | ((~mask) & arg1[0])) + x2 := ((mask & arg2[1]) | ((~mask) & arg1[1])) + x3 := ((mask & arg2[2]) | ((~mask) & arg1[2])) + x4 := ((mask & arg2[3]) | ((~mask) & arg1[3])) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_cond_negate :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element, ctrl: int) { + tmp1: Montgomery_Domain_Field_Element = --- + fe_opp(&tmp1, arg1) + fe_cond_select(out1, arg1, &tmp1, ctrl) + + fe_clear(&tmp1) +} diff --git a/core/crypto/_fiat/field_p256r1/field64.odin b/core/crypto/_fiat/field_p256r1/field64.odin new file mode 100644 index 000000000..940f2cd07 --- /dev/null +++ b/core/crypto/_fiat/field_p256r1/field64.odin @@ -0,0 +1,501 @@ +// The BSD 1-Clause License (BSD-1-Clause) +// +// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package field_p256r1 + +// The file provides arithmetic on the field Z/(2^256 - 2^224 + 2^192 + 2^96 - 1) +// using a 64-bit Montgomery form internal representation. It is derived +// primarily from the machine generated Golang output from the fiat-crypto +// project. +// +// While the base implementation is provably correct, this implementation +// makes no such claims as the port and optimizations were done by hand. +// +// WARNING: While big-endian is the common representation used for this +// curve, the fiat output uses least-significant-limb first. + +import fiat "core:crypto/_fiat" +import "core:math/bits" + +// ELL is the saturated representation of the field order, least-significant +// limb first. +ELL :: [4]u64{0xffffffffffffffff, 0xffffffff, 0x0, 0xffffffff00000001} + +Montgomery_Domain_Field_Element :: distinct [4]u64 +Non_Montgomery_Domain_Field_Element :: distinct [4]u64 + +fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg2[3]) + x8, x7 := bits.mul_u64(x4, arg2[2]) + x10, x9 := bits.mul_u64(x4, arg2[1]) + x12, x11 := bits.mul_u64(x4, arg2[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + x21, x20 := bits.mul_u64(x11, 0xffffffff00000001) + x23, x22 := bits.mul_u64(x11, 0xffffffff) + x25, x24 := bits.mul_u64(x11, 0xffffffffffffffff) + x26, x27 := bits.add_u64(x25, x22, u64(0x0)) + x28 := (u64(fiat.u1(x27)) + x23) + _, x30 := bits.add_u64(x11, x24, u64(0x0)) + x31, x32 := bits.add_u64(x13, x26, u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x15, x28, u64(fiat.u1(x32))) + x35, x36 := bits.add_u64(x17, x20, u64(fiat.u1(x34))) + x37, x38 := bits.add_u64(x19, x21, u64(fiat.u1(x36))) + x40, x39 := bits.mul_u64(x1, arg2[3]) + x42, x41 := bits.mul_u64(x1, arg2[2]) + x44, x43 := bits.mul_u64(x1, arg2[1]) + x46, x45 := bits.mul_u64(x1, arg2[0]) + x47, x48 := bits.add_u64(x46, x43, u64(0x0)) + x49, x50 := bits.add_u64(x44, x41, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x42, x39, u64(fiat.u1(x50))) + x53 := (u64(fiat.u1(x52)) + x40) + x54, x55 := bits.add_u64(x31, x45, u64(0x0)) + x56, x57 := bits.add_u64(x33, x47, u64(fiat.u1(x55))) + x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57))) + x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59))) + x62, x63 := bits.add_u64(u64(fiat.u1(x38)), x53, u64(fiat.u1(x61))) + x65, x64 := bits.mul_u64(x54, 0xffffffff00000001) + x67, x66 := bits.mul_u64(x54, 0xffffffff) + x69, x68 := bits.mul_u64(x54, 0xffffffffffffffff) + x70, x71 := bits.add_u64(x69, x66, u64(0x0)) + x72 := (u64(fiat.u1(x71)) + x67) + _, x74 := bits.add_u64(x54, x68, u64(0x0)) + x75, x76 := bits.add_u64(x56, x70, u64(fiat.u1(x74))) + x77, x78 := bits.add_u64(x58, x72, u64(fiat.u1(x76))) + x79, x80 := bits.add_u64(x60, x64, u64(fiat.u1(x78))) + x81, x82 := bits.add_u64(x62, x65, u64(fiat.u1(x80))) + x83 := (u64(fiat.u1(x82)) + u64(fiat.u1(x63))) + x85, x84 := bits.mul_u64(x2, arg2[3]) + x87, x86 := bits.mul_u64(x2, arg2[2]) + x89, x88 := bits.mul_u64(x2, arg2[1]) + x91, x90 := bits.mul_u64(x2, arg2[0]) + x92, x93 := bits.add_u64(x91, x88, u64(0x0)) + x94, x95 := bits.add_u64(x89, x86, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x87, x84, u64(fiat.u1(x95))) + x98 := (u64(fiat.u1(x97)) + x85) + x99, x100 := bits.add_u64(x75, x90, u64(0x0)) + x101, x102 := bits.add_u64(x77, x92, u64(fiat.u1(x100))) + x103, x104 := bits.add_u64(x79, x94, u64(fiat.u1(x102))) + x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104))) + x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106))) + x110, x109 := bits.mul_u64(x99, 0xffffffff00000001) + x112, x111 := bits.mul_u64(x99, 0xffffffff) + x114, x113 := bits.mul_u64(x99, 0xffffffffffffffff) + x115, x116 := bits.add_u64(x114, x111, u64(0x0)) + x117 := (u64(fiat.u1(x116)) + x112) + _, x119 := bits.add_u64(x99, x113, u64(0x0)) + x120, x121 := bits.add_u64(x101, x115, u64(fiat.u1(x119))) + x122, x123 := bits.add_u64(x103, x117, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x105, x109, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x107, x110, u64(fiat.u1(x125))) + x128 := (u64(fiat.u1(x127)) + u64(fiat.u1(x108))) + x130, x129 := bits.mul_u64(x3, arg2[3]) + x132, x131 := bits.mul_u64(x3, arg2[2]) + x134, x133 := bits.mul_u64(x3, arg2[1]) + x136, x135 := bits.mul_u64(x3, arg2[0]) + x137, x138 := bits.add_u64(x136, x133, u64(0x0)) + x139, x140 := bits.add_u64(x134, x131, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x132, x129, u64(fiat.u1(x140))) + x143 := (u64(fiat.u1(x142)) + x130) + x144, x145 := bits.add_u64(x120, x135, u64(0x0)) + x146, x147 := bits.add_u64(x122, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x124, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x126, x141, u64(fiat.u1(x149))) + x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151))) + x155, x154 := bits.mul_u64(x144, 0xffffffff00000001) + x157, x156 := bits.mul_u64(x144, 0xffffffff) + x159, x158 := bits.mul_u64(x144, 0xffffffffffffffff) + x160, x161 := bits.add_u64(x159, x156, u64(0x0)) + x162 := (u64(fiat.u1(x161)) + x157) + _, x164 := bits.add_u64(x144, x158, u64(0x0)) + x165, x166 := bits.add_u64(x146, x160, u64(fiat.u1(x164))) + x167, x168 := bits.add_u64(x148, x162, u64(fiat.u1(x166))) + x169, x170 := bits.add_u64(x150, x154, u64(fiat.u1(x168))) + x171, x172 := bits.add_u64(x152, x155, u64(fiat.u1(x170))) + x173 := (u64(fiat.u1(x172)) + u64(fiat.u1(x153))) + x174, x175 := bits.sub_u64(x165, 0xffffffffffffffff, u64(0x0)) + x176, x177 := bits.sub_u64(x167, 0xffffffff, u64(fiat.u1(x175))) + x178, x179 := bits.sub_u64(x169, u64(0x0), u64(fiat.u1(x177))) + x180, x181 := bits.sub_u64(x171, 0xffffffff00000001, u64(fiat.u1(x179))) + _, x183 := bits.sub_u64(x173, u64(0x0), u64(fiat.u1(x181))) + x184 := fiat.cmovznz_u64(fiat.u1(x183), x174, x165) + x185 := fiat.cmovznz_u64(fiat.u1(x183), x176, x167) + x186 := fiat.cmovznz_u64(fiat.u1(x183), x178, x169) + x187 := fiat.cmovznz_u64(fiat.u1(x183), x180, x171) + out1[0] = x184 + out1[1] = x185 + out1[2] = x186 + out1[3] = x187 +} + +fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg1[3]) + x8, x7 := bits.mul_u64(x4, arg1[2]) + x10, x9 := bits.mul_u64(x4, arg1[1]) + x12, x11 := bits.mul_u64(x4, arg1[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + x21, x20 := bits.mul_u64(x11, 0xffffffff00000001) + x23, x22 := bits.mul_u64(x11, 0xffffffff) + x25, x24 := bits.mul_u64(x11, 0xffffffffffffffff) + x26, x27 := bits.add_u64(x25, x22, u64(0x0)) + x28 := (u64(fiat.u1(x27)) + x23) + _, x30 := bits.add_u64(x11, x24, u64(0x0)) + x31, x32 := bits.add_u64(x13, x26, u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x15, x28, u64(fiat.u1(x32))) + x35, x36 := bits.add_u64(x17, x20, u64(fiat.u1(x34))) + x37, x38 := bits.add_u64(x19, x21, u64(fiat.u1(x36))) + x40, x39 := bits.mul_u64(x1, arg1[3]) + x42, x41 := bits.mul_u64(x1, arg1[2]) + x44, x43 := bits.mul_u64(x1, arg1[1]) + x46, x45 := bits.mul_u64(x1, arg1[0]) + x47, x48 := bits.add_u64(x46, x43, u64(0x0)) + x49, x50 := bits.add_u64(x44, x41, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x42, x39, u64(fiat.u1(x50))) + x53 := (u64(fiat.u1(x52)) + x40) + x54, x55 := bits.add_u64(x31, x45, u64(0x0)) + x56, x57 := bits.add_u64(x33, x47, u64(fiat.u1(x55))) + x58, x59 := bits.add_u64(x35, x49, u64(fiat.u1(x57))) + x60, x61 := bits.add_u64(x37, x51, u64(fiat.u1(x59))) + x62, x63 := bits.add_u64(u64(fiat.u1(x38)), x53, u64(fiat.u1(x61))) + x65, x64 := bits.mul_u64(x54, 0xffffffff00000001) + x67, x66 := bits.mul_u64(x54, 0xffffffff) + x69, x68 := bits.mul_u64(x54, 0xffffffffffffffff) + x70, x71 := bits.add_u64(x69, x66, u64(0x0)) + x72 := (u64(fiat.u1(x71)) + x67) + _, x74 := bits.add_u64(x54, x68, u64(0x0)) + x75, x76 := bits.add_u64(x56, x70, u64(fiat.u1(x74))) + x77, x78 := bits.add_u64(x58, x72, u64(fiat.u1(x76))) + x79, x80 := bits.add_u64(x60, x64, u64(fiat.u1(x78))) + x81, x82 := bits.add_u64(x62, x65, u64(fiat.u1(x80))) + x83 := (u64(fiat.u1(x82)) + u64(fiat.u1(x63))) + x85, x84 := bits.mul_u64(x2, arg1[3]) + x87, x86 := bits.mul_u64(x2, arg1[2]) + x89, x88 := bits.mul_u64(x2, arg1[1]) + x91, x90 := bits.mul_u64(x2, arg1[0]) + x92, x93 := bits.add_u64(x91, x88, u64(0x0)) + x94, x95 := bits.add_u64(x89, x86, u64(fiat.u1(x93))) + x96, x97 := bits.add_u64(x87, x84, u64(fiat.u1(x95))) + x98 := (u64(fiat.u1(x97)) + x85) + x99, x100 := bits.add_u64(x75, x90, u64(0x0)) + x101, x102 := bits.add_u64(x77, x92, u64(fiat.u1(x100))) + x103, x104 := bits.add_u64(x79, x94, u64(fiat.u1(x102))) + x105, x106 := bits.add_u64(x81, x96, u64(fiat.u1(x104))) + x107, x108 := bits.add_u64(x83, x98, u64(fiat.u1(x106))) + x110, x109 := bits.mul_u64(x99, 0xffffffff00000001) + x112, x111 := bits.mul_u64(x99, 0xffffffff) + x114, x113 := bits.mul_u64(x99, 0xffffffffffffffff) + x115, x116 := bits.add_u64(x114, x111, u64(0x0)) + x117 := (u64(fiat.u1(x116)) + x112) + _, x119 := bits.add_u64(x99, x113, u64(0x0)) + x120, x121 := bits.add_u64(x101, x115, u64(fiat.u1(x119))) + x122, x123 := bits.add_u64(x103, x117, u64(fiat.u1(x121))) + x124, x125 := bits.add_u64(x105, x109, u64(fiat.u1(x123))) + x126, x127 := bits.add_u64(x107, x110, u64(fiat.u1(x125))) + x128 := (u64(fiat.u1(x127)) + u64(fiat.u1(x108))) + x130, x129 := bits.mul_u64(x3, arg1[3]) + x132, x131 := bits.mul_u64(x3, arg1[2]) + x134, x133 := bits.mul_u64(x3, arg1[1]) + x136, x135 := bits.mul_u64(x3, arg1[0]) + x137, x138 := bits.add_u64(x136, x133, u64(0x0)) + x139, x140 := bits.add_u64(x134, x131, u64(fiat.u1(x138))) + x141, x142 := bits.add_u64(x132, x129, u64(fiat.u1(x140))) + x143 := (u64(fiat.u1(x142)) + x130) + x144, x145 := bits.add_u64(x120, x135, u64(0x0)) + x146, x147 := bits.add_u64(x122, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x124, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x126, x141, u64(fiat.u1(x149))) + x152, x153 := bits.add_u64(x128, x143, u64(fiat.u1(x151))) + x155, x154 := bits.mul_u64(x144, 0xffffffff00000001) + x157, x156 := bits.mul_u64(x144, 0xffffffff) + x159, x158 := bits.mul_u64(x144, 0xffffffffffffffff) + x160, x161 := bits.add_u64(x159, x156, u64(0x0)) + x162 := (u64(fiat.u1(x161)) + x157) + _, x164 := bits.add_u64(x144, x158, u64(0x0)) + x165, x166 := bits.add_u64(x146, x160, u64(fiat.u1(x164))) + x167, x168 := bits.add_u64(x148, x162, u64(fiat.u1(x166))) + x169, x170 := bits.add_u64(x150, x154, u64(fiat.u1(x168))) + x171, x172 := bits.add_u64(x152, x155, u64(fiat.u1(x170))) + x173 := (u64(fiat.u1(x172)) + u64(fiat.u1(x153))) + x174, x175 := bits.sub_u64(x165, 0xffffffffffffffff, u64(0x0)) + x176, x177 := bits.sub_u64(x167, 0xffffffff, u64(fiat.u1(x175))) + x178, x179 := bits.sub_u64(x169, u64(0x0), u64(fiat.u1(x177))) + x180, x181 := bits.sub_u64(x171, 0xffffffff00000001, u64(fiat.u1(x179))) + _, x183 := bits.sub_u64(x173, u64(0x0), u64(fiat.u1(x181))) + x184 := fiat.cmovznz_u64(fiat.u1(x183), x174, x165) + x185 := fiat.cmovznz_u64(fiat.u1(x183), x176, x167) + x186 := fiat.cmovznz_u64(fiat.u1(x183), x178, x169) + x187 := fiat.cmovznz_u64(fiat.u1(x183), x180, x171) + out1[0] = x184 + out1[1] = x185 + out1[2] = x186 + out1[3] = x187 +} + +fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(x1, 0xffffffffffffffff, u64(0x0)) + x11, x12 := bits.sub_u64(x3, 0xffffffff, u64(fiat.u1(x10))) + x13, x14 := bits.sub_u64(x5, u64(0x0), u64(fiat.u1(x12))) + x15, x16 := bits.sub_u64(x7, 0xffffffff00000001, u64(fiat.u1(x14))) + _, x18 := bits.sub_u64(u64(fiat.u1(x8)), u64(0x0), u64(fiat.u1(x16))) + x19 := fiat.cmovznz_u64(fiat.u1(x18), x9, x1) + x20 := fiat.cmovznz_u64(fiat.u1(x18), x11, x3) + x21 := fiat.cmovznz_u64(fiat.u1(x18), x13, x5) + x22 := fiat.cmovznz_u64(fiat.u1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, x9, u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xffffffff), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000001), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0)) + x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, x9, u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xffffffff), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, u64(0x0), u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000001), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0x1 + out1[1] = 0xffffffff00000000 + out1[2] = 0xffffffffffffffff + out1[3] = 0xfffffffe +} + +fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 { + return arg1[0] | (arg1[1] | (arg1[2] | arg1[3])) +} + +@(optimization_mode = "none") +fe_cond_assign :: #force_no_inline proc "contextless" ( + out1, arg1: ^Montgomery_Domain_Field_Element, + arg2: int, +) { + x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0]) + x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1]) + x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2]) + x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_from_montgomery :: proc "contextless" ( + out1: ^Non_Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, +) { + x1 := arg1[0] + x3, x2 := bits.mul_u64(x1, 0xffffffff00000001) + x5, x4 := bits.mul_u64(x1, 0xffffffff) + x7, x6 := bits.mul_u64(x1, 0xffffffffffffffff) + x8, x9 := bits.add_u64(x7, x4, u64(0x0)) + _, x11 := bits.add_u64(x1, x6, u64(0x0)) + x12, x13 := bits.add_u64(u64(0x0), x8, u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x12, arg1[1], u64(0x0)) + x17, x16 := bits.mul_u64(x14, 0xffffffff00000001) + x19, x18 := bits.mul_u64(x14, 0xffffffff) + x21, x20 := bits.mul_u64(x14, 0xffffffffffffffff) + x22, x23 := bits.add_u64(x21, x18, u64(0x0)) + _, x25 := bits.add_u64(x14, x20, u64(0x0)) + x26, x27 := bits.add_u64((u64(fiat.u1(x15)) + (u64(fiat.u1(x13)) + (u64(fiat.u1(x9)) + x5))), x22, u64(fiat.u1(x25))) + x28, x29 := bits.add_u64(x2, (u64(fiat.u1(x23)) + x19), u64(fiat.u1(x27))) + x30, x31 := bits.add_u64(x3, x16, u64(fiat.u1(x29))) + x32, x33 := bits.add_u64(x26, arg1[2], u64(0x0)) + x34, x35 := bits.add_u64(x28, u64(0x0), u64(fiat.u1(x33))) + x36, x37 := bits.add_u64(x30, u64(0x0), u64(fiat.u1(x35))) + x39, x38 := bits.mul_u64(x32, 0xffffffff00000001) + x41, x40 := bits.mul_u64(x32, 0xffffffff) + x43, x42 := bits.mul_u64(x32, 0xffffffffffffffff) + x44, x45 := bits.add_u64(x43, x40, u64(0x0)) + _, x47 := bits.add_u64(x32, x42, u64(0x0)) + x48, x49 := bits.add_u64(x34, x44, u64(fiat.u1(x47))) + x50, x51 := bits.add_u64(x36, (u64(fiat.u1(x45)) + x41), u64(fiat.u1(x49))) + x52, x53 := bits.add_u64((u64(fiat.u1(x37)) + (u64(fiat.u1(x31)) + x17)), x38, u64(fiat.u1(x51))) + x54, x55 := bits.add_u64(x48, arg1[3], u64(0x0)) + x56, x57 := bits.add_u64(x50, u64(0x0), u64(fiat.u1(x55))) + x58, x59 := bits.add_u64(x52, u64(0x0), u64(fiat.u1(x57))) + x61, x60 := bits.mul_u64(x54, 0xffffffff00000001) + x63, x62 := bits.mul_u64(x54, 0xffffffff) + x65, x64 := bits.mul_u64(x54, 0xffffffffffffffff) + x66, x67 := bits.add_u64(x65, x62, u64(0x0)) + _, x69 := bits.add_u64(x54, x64, u64(0x0)) + x70, x71 := bits.add_u64(x56, x66, u64(fiat.u1(x69))) + x72, x73 := bits.add_u64(x58, (u64(fiat.u1(x67)) + x63), u64(fiat.u1(x71))) + x74, x75 := bits.add_u64((u64(fiat.u1(x59)) + (u64(fiat.u1(x53)) + x39)), x60, u64(fiat.u1(x73))) + x76 := (u64(fiat.u1(x75)) + x61) + x77, x78 := bits.sub_u64(x70, 0xffffffffffffffff, u64(0x0)) + x79, x80 := bits.sub_u64(x72, 0xffffffff, u64(fiat.u1(x78))) + x81, x82 := bits.sub_u64(x74, u64(0x0), u64(fiat.u1(x80))) + x83, x84 := bits.sub_u64(x76, 0xffffffff00000001, u64(fiat.u1(x82))) + _, x86 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x84))) + x87 := fiat.cmovznz_u64(fiat.u1(x86), x77, x70) + x88 := fiat.cmovznz_u64(fiat.u1(x86), x79, x72) + x89 := fiat.cmovznz_u64(fiat.u1(x86), x81, x74) + x90 := fiat.cmovznz_u64(fiat.u1(x86), x83, x76) + out1[0] = x87 + out1[1] = x88 + out1[2] = x89 + out1[3] = x90 +} + +fe_to_montgomery :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Non_Montgomery_Domain_Field_Element, +) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, 0x4fffffffd) + x8, x7 := bits.mul_u64(x4, 0xfffffffffffffffe) + x10, x9 := bits.mul_u64(x4, 0xfffffffbffffffff) + x12, x11 := bits.mul_u64(x4, 0x3) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x20, x19 := bits.mul_u64(x11, 0xffffffff00000001) + x22, x21 := bits.mul_u64(x11, 0xffffffff) + x24, x23 := bits.mul_u64(x11, 0xffffffffffffffff) + x25, x26 := bits.add_u64(x24, x21, u64(0x0)) + _, x28 := bits.add_u64(x11, x23, u64(0x0)) + x29, x30 := bits.add_u64(x13, x25, u64(fiat.u1(x28))) + x31, x32 := bits.add_u64(x15, (u64(fiat.u1(x26)) + x22), u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x17, x19, u64(fiat.u1(x32))) + x35, x36 := bits.add_u64((u64(fiat.u1(x18)) + x6), x20, u64(fiat.u1(x34))) + x38, x37 := bits.mul_u64(x1, 0x4fffffffd) + x40, x39 := bits.mul_u64(x1, 0xfffffffffffffffe) + x42, x41 := bits.mul_u64(x1, 0xfffffffbffffffff) + x44, x43 := bits.mul_u64(x1, 0x3) + x45, x46 := bits.add_u64(x44, x41, u64(0x0)) + x47, x48 := bits.add_u64(x42, x39, u64(fiat.u1(x46))) + x49, x50 := bits.add_u64(x40, x37, u64(fiat.u1(x48))) + x51, x52 := bits.add_u64(x29, x43, u64(0x0)) + x53, x54 := bits.add_u64(x31, x45, u64(fiat.u1(x52))) + x55, x56 := bits.add_u64(x33, x47, u64(fiat.u1(x54))) + x57, x58 := bits.add_u64(x35, x49, u64(fiat.u1(x56))) + x60, x59 := bits.mul_u64(x51, 0xffffffff00000001) + x62, x61 := bits.mul_u64(x51, 0xffffffff) + x64, x63 := bits.mul_u64(x51, 0xffffffffffffffff) + x65, x66 := bits.add_u64(x64, x61, u64(0x0)) + _, x68 := bits.add_u64(x51, x63, u64(0x0)) + x69, x70 := bits.add_u64(x53, x65, u64(fiat.u1(x68))) + x71, x72 := bits.add_u64(x55, (u64(fiat.u1(x66)) + x62), u64(fiat.u1(x70))) + x73, x74 := bits.add_u64(x57, x59, u64(fiat.u1(x72))) + x75, x76 := bits.add_u64(((u64(fiat.u1(x58)) + u64(fiat.u1(x36))) + (u64(fiat.u1(x50)) + x38)), x60, u64(fiat.u1(x74))) + x78, x77 := bits.mul_u64(x2, 0x4fffffffd) + x80, x79 := bits.mul_u64(x2, 0xfffffffffffffffe) + x82, x81 := bits.mul_u64(x2, 0xfffffffbffffffff) + x84, x83 := bits.mul_u64(x2, 0x3) + x85, x86 := bits.add_u64(x84, x81, u64(0x0)) + x87, x88 := bits.add_u64(x82, x79, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x80, x77, u64(fiat.u1(x88))) + x91, x92 := bits.add_u64(x69, x83, u64(0x0)) + x93, x94 := bits.add_u64(x71, x85, u64(fiat.u1(x92))) + x95, x96 := bits.add_u64(x73, x87, u64(fiat.u1(x94))) + x97, x98 := bits.add_u64(x75, x89, u64(fiat.u1(x96))) + x100, x99 := bits.mul_u64(x91, 0xffffffff00000001) + x102, x101 := bits.mul_u64(x91, 0xffffffff) + x104, x103 := bits.mul_u64(x91, 0xffffffffffffffff) + x105, x106 := bits.add_u64(x104, x101, u64(0x0)) + _, x108 := bits.add_u64(x91, x103, u64(0x0)) + x109, x110 := bits.add_u64(x93, x105, u64(fiat.u1(x108))) + x111, x112 := bits.add_u64(x95, (u64(fiat.u1(x106)) + x102), u64(fiat.u1(x110))) + x113, x114 := bits.add_u64(x97, x99, u64(fiat.u1(x112))) + x115, x116 := bits.add_u64(((u64(fiat.u1(x98)) + u64(fiat.u1(x76))) + (u64(fiat.u1(x90)) + x78)), x100, u64(fiat.u1(x114))) + x118, x117 := bits.mul_u64(x3, 0x4fffffffd) + x120, x119 := bits.mul_u64(x3, 0xfffffffffffffffe) + x122, x121 := bits.mul_u64(x3, 0xfffffffbffffffff) + x124, x123 := bits.mul_u64(x3, 0x3) + x125, x126 := bits.add_u64(x124, x121, u64(0x0)) + x127, x128 := bits.add_u64(x122, x119, u64(fiat.u1(x126))) + x129, x130 := bits.add_u64(x120, x117, u64(fiat.u1(x128))) + x131, x132 := bits.add_u64(x109, x123, u64(0x0)) + x133, x134 := bits.add_u64(x111, x125, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x113, x127, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x115, x129, u64(fiat.u1(x136))) + x140, x139 := bits.mul_u64(x131, 0xffffffff00000001) + x142, x141 := bits.mul_u64(x131, 0xffffffff) + x144, x143 := bits.mul_u64(x131, 0xffffffffffffffff) + x145, x146 := bits.add_u64(x144, x141, u64(0x0)) + _, x148 := bits.add_u64(x131, x143, u64(0x0)) + x149, x150 := bits.add_u64(x133, x145, u64(fiat.u1(x148))) + x151, x152 := bits.add_u64(x135, (u64(fiat.u1(x146)) + x142), u64(fiat.u1(x150))) + x153, x154 := bits.add_u64(x137, x139, u64(fiat.u1(x152))) + x155, x156 := bits.add_u64(((u64(fiat.u1(x138)) + u64(fiat.u1(x116))) + (u64(fiat.u1(x130)) + x118)), x140, u64(fiat.u1(x154))) + x157, x158 := bits.sub_u64(x149, 0xffffffffffffffff, u64(0x0)) + x159, x160 := bits.sub_u64(x151, 0xffffffff, u64(fiat.u1(x158))) + x161, x162 := bits.sub_u64(x153, u64(0x0), u64(fiat.u1(x160))) + x163, x164 := bits.sub_u64(x155, 0xffffffff00000001, u64(fiat.u1(x162))) + _, x166 := bits.sub_u64(u64(fiat.u1(x156)), u64(0x0), u64(fiat.u1(x164))) + x167 := fiat.cmovznz_u64(fiat.u1(x166), x157, x149) + x168 := fiat.cmovznz_u64(fiat.u1(x166), x159, x151) + x169 := fiat.cmovznz_u64(fiat.u1(x166), x161, x153) + x170 := fiat.cmovznz_u64(fiat.u1(x166), x163, x155) + out1[0] = x167 + out1[1] = x168 + out1[2] = x169 + out1[3] = x170 +} diff --git a/core/crypto/_fiat/field_scalarp256r1/field.odin b/core/crypto/_fiat/field_scalarp256r1/field.odin new file mode 100644 index 000000000..73c01fb46 --- /dev/null +++ b/core/crypto/_fiat/field_scalarp256r1/field.odin @@ -0,0 +1,210 @@ +package field_scalarp256r1 + +import subtle "core:crypto/_subtle" +import "core:encoding/endian" +import "core:math/bits" +import "core:mem" + +@(private, rodata) +TWO_192 := Montgomery_Domain_Field_Element{ + 2482910415990817935, + 2879494685571067143, + 8732918506673730078, + 85565669603516024, +} +@(private, rodata) +TWO_384 := Montgomery_Domain_Field_Element{ + 2127524300190691059, + 17014302137236182484, + 16604910261202196099, + 3621421107472562910, +} +// 2^384 % p (From sage) +// 0x431905529c0166ce652e96b7ccca0a99679b73e19ad16947f01cf013fc632551 + +fe_clear :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) { + mem.zero_explicit(arg1, size_of(Montgomery_Domain_Field_Element)) +} + +fe_clear_vec :: proc "contextless" ( + arg1: []^Montgomery_Domain_Field_Element, +) { + for fe in arg1 { + fe_clear(fe) + } +} + +fe_from_bytes :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: []byte, +) -> bool { + ensure_contextless(len(out1) <= 64, "p256r1: invalid scalar input buffer") + + is_canonical := false + s_len := len(arg1) + switch { + case s_len < 32: + // No way this can be greater than the order. + fe_unchecked_set(out1, arg1) + is_canonical = true + case s_len == 32: + // It is quite likely that a reduction mod p is required, + // as the order of the curve is sufficiently smaller than + // 2^256-1, so just check if we actually needed to reduced + // and do the reduction anyway, so that things that require + // canonical scalars can reject non-canonical encodings. + is_canonical = fe_is_canonical(arg1) + fallthrough + case: + // Use Frank Denis' trick, as documented by Filippo Valsorda + // at https://words.filippo.io/dispatches/wide-reduction/ + // + // "I represent the value as a+b*2^192+c*2^384" + // + // Note: Omitting the `c` computation is fine as, reduction + // being length dependent provides no useful timing information. + + // Zero extend to 512-bits. + src_512: [64]byte + copy(src_512[64-s_len:], arg1) + defer mem.zero_explicit(&src_512, size_of(src_512)) + + fe_unchecked_set(out1, src_512[40:]) // a + b: Montgomery_Domain_Field_Element + fe_unchecked_set(&b, src_512[16:40]) // b + + fe_mul(&b, &b, &TWO_192) + fe_add(out1, out1, &b) + if s_len >= 48 { + c: Montgomery_Domain_Field_Element + fe_unchecked_set(&c, src_512[:16]) // c + fe_mul(&c, &c, &TWO_384) + fe_add(out1, out1, &c) + + fe_clear(&c) + } + + fe_clear(&b) + } + + return !is_canonical +} + +@(private) +fe_is_canonical :: proc "contextless" (arg1: []byte) -> bool { + _, borrow := bits.sub_u64(ELL[0] - 1, endian.unchecked_get_u64be(arg1[24:]), 0) + _, borrow = bits.sub_u64(ELL[1], endian.unchecked_get_u64be(arg1[16:]), borrow) + _, borrow = bits.sub_u64(ELL[2], endian.unchecked_get_u64be(arg1[8:]), borrow) + _, borrow = bits.sub_u64(ELL[3], endian.unchecked_get_u64be(arg1[0:]), borrow) + return borrow == 0 +} + +@(private) +fe_unchecked_set :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element, arg1: []byte) { + arg1_256: [32]byte + defer mem.zero_explicit(&arg1_256, size_of(arg1_256)) + copy(arg1_256[32-len(arg1):], arg1) + + tmp := Non_Montgomery_Domain_Field_Element { + endian.unchecked_get_u64be(arg1_256[24:]), + endian.unchecked_get_u64be(arg1_256[16:]), + endian.unchecked_get_u64be(arg1_256[8:]), + endian.unchecked_get_u64be(arg1_256[0:]), + } + defer mem.zero_explicit(&tmp, size_of(tmp)) + + fe_to_montgomery(out1, &tmp) +} + +fe_to_bytes :: proc "contextless" (out1: []byte, arg1: ^Montgomery_Domain_Field_Element) { + ensure_contextless(len(out1) == 32, "p256r1: invalid scalar output buffer") + + tmp: Non_Montgomery_Domain_Field_Element + fe_from_montgomery(&tmp, arg1) + + // Note: Likewise, output in big-endian. + endian.unchecked_put_u64be(out1[24:], tmp[0]) + endian.unchecked_put_u64be(out1[16:], tmp[1]) + endian.unchecked_put_u64be(out1[8:], tmp[2]) + endian.unchecked_put_u64be(out1[0:], tmp[3]) + + mem.zero_explicit(&tmp, size_of(tmp)) +} + +fe_equal :: proc "contextless" (arg1, arg2: ^Montgomery_Domain_Field_Element) -> int { + tmp: Montgomery_Domain_Field_Element + fe_sub(&tmp, arg1, arg2) + + is_eq := subtle.u64_is_zero(fe_non_zero(&tmp)) + + fe_clear(&tmp) + + return int(is_eq) +} + +fe_is_odd :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> int { + tmp: Non_Montgomery_Domain_Field_Element + defer mem.zero_explicit(&tmp, size_of(tmp)) + + fe_from_montgomery(&tmp, arg1) + return int(tmp[0] & 1) +} + +fe_zero :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0 + out1[1] = 0 + out1[2] = 0 + out1[3] = 0 +} + +fe_set :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[0] + x2 := arg1[1] + x3 := arg1[2] + x4 := arg1[3] + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +@(optimization_mode = "none") +fe_cond_swap :: #force_no_inline proc "contextless" (out1, out2: ^Montgomery_Domain_Field_Element, arg1: int) { + mask := (u64(arg1) * 0xffffffffffffffff) + x := (out1[0] ~ out2[0]) & mask + x1, y1 := out1[0] ~ x, out2[0] ~ x + x = (out1[1] ~ out2[1]) & mask + x2, y2 := out1[1] ~ x, out2[1] ~ x + x = (out1[2] ~ out2[2]) & mask + x3, y3 := out1[2] ~ x, out2[2] ~ x + x = (out1[3] ~ out2[3]) & mask + x4, y4 := out1[3] ~ x, out2[3] ~ x + out1[0], out2[0] = x1, y1 + out1[1], out2[1] = x2, y2 + out1[2], out2[2] = x3, y3 + out1[3], out2[3] = x4, y4 +} + +@(optimization_mode = "none") +fe_cond_select :: #force_no_inline proc "contextless" ( + out1, arg1, arg2: ^Montgomery_Domain_Field_Element, + arg3: int, +) { + mask := (u64(arg3) * 0xffffffffffffffff) + x1 := ((mask & arg2[0]) | ((~mask) & arg1[0])) + x2 := ((mask & arg2[1]) | ((~mask) & arg1[1])) + x3 := ((mask & arg2[2]) | ((~mask) & arg1[2])) + x4 := ((mask & arg2[3]) | ((~mask) & arg1[3])) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_cond_negate :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element, ctrl: int) { + tmp1: Montgomery_Domain_Field_Element = --- + fe_opp(&tmp1, arg1) + fe_cond_select(out1, arg1, &tmp1, ctrl) + + fe_clear(&tmp1) +} diff --git a/core/crypto/_fiat/field_scalarp256r1/field64.odin b/core/crypto/_fiat/field_scalarp256r1/field64.odin new file mode 100644 index 000000000..4217374a7 --- /dev/null +++ b/core/crypto/_fiat/field_scalarp256r1/field64.odin @@ -0,0 +1,569 @@ +// The BSD 1-Clause License (BSD-1-Clause) +// +// Copyright (c) 2015-2020 the fiat-crypto authors (see the AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, +// Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package field_scalarp256r1 + +// The file provides arithmetic on the field Z/(2^256 - 2^224 + 2^192 - +// 89188191075325690597107910205041859247) using a 64-bit Montgomery form +// internal representation. It is derived primarily from the machine +// generated Golang output from the fiat-crypto project. +// +// While the base implementation is provably correct, this implementation +// makes no such claims as the port and optimizations were done by hand. +// +// WARNING: While big-endian is the common representation used for this +// curve, the fiat output uses least-significant-limb first. + +import fiat "core:crypto/_fiat" +import "core:math/bits" + +// ELL is the saturated representation of the field order, least-significant +// limb first. +ELL :: [4]u64{0xf3b9cac2fc632551, 0xbce6faada7179e84, 0xffffffffffffffff, 0xffffffff00000000} + +Montgomery_Domain_Field_Element :: distinct [4]u64 +Non_Montgomery_Domain_Field_Element :: distinct [4]u64 + +fe_mul :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg2[3]) + x8, x7 := bits.mul_u64(x4, arg2[2]) + x10, x9 := bits.mul_u64(x4, arg2[1]) + x12, x11 := bits.mul_u64(x4, arg2[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + _, x20 := bits.mul_u64(x11, 0xccd1c8aaee00bc4f) + x23, x22 := bits.mul_u64(x20, 0xffffffff00000000) + x25, x24 := bits.mul_u64(x20, 0xffffffffffffffff) + x27, x26 := bits.mul_u64(x20, 0xbce6faada7179e84) + x29, x28 := bits.mul_u64(x20, 0xf3b9cac2fc632551) + x30, x31 := bits.add_u64(x29, x26, u64(0x0)) + x32, x33 := bits.add_u64(x27, x24, u64(fiat.u1(x31))) + x34, x35 := bits.add_u64(x25, x22, u64(fiat.u1(x33))) + x36 := (u64(fiat.u1(x35)) + x23) + _, x38 := bits.add_u64(x11, x28, u64(0x0)) + x39, x40 := bits.add_u64(x13, x30, u64(fiat.u1(x38))) + x41, x42 := bits.add_u64(x15, x32, u64(fiat.u1(x40))) + x43, x44 := bits.add_u64(x17, x34, u64(fiat.u1(x42))) + x45, x46 := bits.add_u64(x19, x36, u64(fiat.u1(x44))) + x48, x47 := bits.mul_u64(x1, arg2[3]) + x50, x49 := bits.mul_u64(x1, arg2[2]) + x52, x51 := bits.mul_u64(x1, arg2[1]) + x54, x53 := bits.mul_u64(x1, arg2[0]) + x55, x56 := bits.add_u64(x54, x51, u64(0x0)) + x57, x58 := bits.add_u64(x52, x49, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x50, x47, u64(fiat.u1(x58))) + x61 := (u64(fiat.u1(x60)) + x48) + x62, x63 := bits.add_u64(x39, x53, u64(0x0)) + x64, x65 := bits.add_u64(x41, x55, u64(fiat.u1(x63))) + x66, x67 := bits.add_u64(x43, x57, u64(fiat.u1(x65))) + x68, x69 := bits.add_u64(x45, x59, u64(fiat.u1(x67))) + x70, x71 := bits.add_u64(u64(fiat.u1(x46)), x61, u64(fiat.u1(x69))) + _, x72 := bits.mul_u64(x62, 0xccd1c8aaee00bc4f) + x75, x74 := bits.mul_u64(x72, 0xffffffff00000000) + x77, x76 := bits.mul_u64(x72, 0xffffffffffffffff) + x79, x78 := bits.mul_u64(x72, 0xbce6faada7179e84) + x81, x80 := bits.mul_u64(x72, 0xf3b9cac2fc632551) + x82, x83 := bits.add_u64(x81, x78, u64(0x0)) + x84, x85 := bits.add_u64(x79, x76, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x77, x74, u64(fiat.u1(x85))) + x88 := (u64(fiat.u1(x87)) + x75) + _, x90 := bits.add_u64(x62, x80, u64(0x0)) + x91, x92 := bits.add_u64(x64, x82, u64(fiat.u1(x90))) + x93, x94 := bits.add_u64(x66, x84, u64(fiat.u1(x92))) + x95, x96 := bits.add_u64(x68, x86, u64(fiat.u1(x94))) + x97, x98 := bits.add_u64(x70, x88, u64(fiat.u1(x96))) + x99 := (u64(fiat.u1(x98)) + u64(fiat.u1(x71))) + x101, x100 := bits.mul_u64(x2, arg2[3]) + x103, x102 := bits.mul_u64(x2, arg2[2]) + x105, x104 := bits.mul_u64(x2, arg2[1]) + x107, x106 := bits.mul_u64(x2, arg2[0]) + x108, x109 := bits.add_u64(x107, x104, u64(0x0)) + x110, x111 := bits.add_u64(x105, x102, u64(fiat.u1(x109))) + x112, x113 := bits.add_u64(x103, x100, u64(fiat.u1(x111))) + x114 := (u64(fiat.u1(x113)) + x101) + x115, x116 := bits.add_u64(x91, x106, u64(0x0)) + x117, x118 := bits.add_u64(x93, x108, u64(fiat.u1(x116))) + x119, x120 := bits.add_u64(x95, x110, u64(fiat.u1(x118))) + x121, x122 := bits.add_u64(x97, x112, u64(fiat.u1(x120))) + x123, x124 := bits.add_u64(x99, x114, u64(fiat.u1(x122))) + _, x125 := bits.mul_u64(x115, 0xccd1c8aaee00bc4f) + x128, x127 := bits.mul_u64(x125, 0xffffffff00000000) + x130, x129 := bits.mul_u64(x125, 0xffffffffffffffff) + x132, x131 := bits.mul_u64(x125, 0xbce6faada7179e84) + x134, x133 := bits.mul_u64(x125, 0xf3b9cac2fc632551) + x135, x136 := bits.add_u64(x134, x131, u64(0x0)) + x137, x138 := bits.add_u64(x132, x129, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x130, x127, u64(fiat.u1(x138))) + x141 := (u64(fiat.u1(x140)) + x128) + _, x143 := bits.add_u64(x115, x133, u64(0x0)) + x144, x145 := bits.add_u64(x117, x135, u64(fiat.u1(x143))) + x146, x147 := bits.add_u64(x119, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x121, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x123, x141, u64(fiat.u1(x149))) + x152 := (u64(fiat.u1(x151)) + u64(fiat.u1(x124))) + x154, x153 := bits.mul_u64(x3, arg2[3]) + x156, x155 := bits.mul_u64(x3, arg2[2]) + x158, x157 := bits.mul_u64(x3, arg2[1]) + x160, x159 := bits.mul_u64(x3, arg2[0]) + x161, x162 := bits.add_u64(x160, x157, u64(0x0)) + x163, x164 := bits.add_u64(x158, x155, u64(fiat.u1(x162))) + x165, x166 := bits.add_u64(x156, x153, u64(fiat.u1(x164))) + x167 := (u64(fiat.u1(x166)) + x154) + x168, x169 := bits.add_u64(x144, x159, u64(0x0)) + x170, x171 := bits.add_u64(x146, x161, u64(fiat.u1(x169))) + x172, x173 := bits.add_u64(x148, x163, u64(fiat.u1(x171))) + x174, x175 := bits.add_u64(x150, x165, u64(fiat.u1(x173))) + x176, x177 := bits.add_u64(x152, x167, u64(fiat.u1(x175))) + _, x178 := bits.mul_u64(x168, 0xccd1c8aaee00bc4f) + x181, x180 := bits.mul_u64(x178, 0xffffffff00000000) + x183, x182 := bits.mul_u64(x178, 0xffffffffffffffff) + x185, x184 := bits.mul_u64(x178, 0xbce6faada7179e84) + x187, x186 := bits.mul_u64(x178, 0xf3b9cac2fc632551) + x188, x189 := bits.add_u64(x187, x184, u64(0x0)) + x190, x191 := bits.add_u64(x185, x182, u64(fiat.u1(x189))) + x192, x193 := bits.add_u64(x183, x180, u64(fiat.u1(x191))) + x194 := (u64(fiat.u1(x193)) + x181) + _, x196 := bits.add_u64(x168, x186, u64(0x0)) + x197, x198 := bits.add_u64(x170, x188, u64(fiat.u1(x196))) + x199, x200 := bits.add_u64(x172, x190, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x174, x192, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x176, x194, u64(fiat.u1(x202))) + x205 := (u64(fiat.u1(x204)) + u64(fiat.u1(x177))) + x206, x207 := bits.sub_u64(x197, 0xf3b9cac2fc632551, u64(0x0)) + x208, x209 := bits.sub_u64(x199, 0xbce6faada7179e84, u64(fiat.u1(x207))) + x210, x211 := bits.sub_u64(x201, 0xffffffffffffffff, u64(fiat.u1(x209))) + x212, x213 := bits.sub_u64(x203, 0xffffffff00000000, u64(fiat.u1(x211))) + _, x215 := bits.sub_u64(x205, u64(0x0), u64(fiat.u1(x213))) + x216 := fiat.cmovznz_u64(fiat.u1(x215), x206, x197) + x217 := fiat.cmovznz_u64(fiat.u1(x215), x208, x199) + x218 := fiat.cmovznz_u64(fiat.u1(x215), x210, x201) + x219 := fiat.cmovznz_u64(fiat.u1(x215), x212, x203) + out1[0] = x216 + out1[1] = x217 + out1[2] = x218 + out1[3] = x219 +} + +fe_square :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, arg1[3]) + x8, x7 := bits.mul_u64(x4, arg1[2]) + x10, x9 := bits.mul_u64(x4, arg1[1]) + x12, x11 := bits.mul_u64(x4, arg1[0]) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + x19 := (u64(fiat.u1(x18)) + x6) + _, x20 := bits.mul_u64(x11, 0xccd1c8aaee00bc4f) + x23, x22 := bits.mul_u64(x20, 0xffffffff00000000) + x25, x24 := bits.mul_u64(x20, 0xffffffffffffffff) + x27, x26 := bits.mul_u64(x20, 0xbce6faada7179e84) + x29, x28 := bits.mul_u64(x20, 0xf3b9cac2fc632551) + x30, x31 := bits.add_u64(x29, x26, u64(0x0)) + x32, x33 := bits.add_u64(x27, x24, u64(fiat.u1(x31))) + x34, x35 := bits.add_u64(x25, x22, u64(fiat.u1(x33))) + x36 := (u64(fiat.u1(x35)) + x23) + _, x38 := bits.add_u64(x11, x28, u64(0x0)) + x39, x40 := bits.add_u64(x13, x30, u64(fiat.u1(x38))) + x41, x42 := bits.add_u64(x15, x32, u64(fiat.u1(x40))) + x43, x44 := bits.add_u64(x17, x34, u64(fiat.u1(x42))) + x45, x46 := bits.add_u64(x19, x36, u64(fiat.u1(x44))) + x48, x47 := bits.mul_u64(x1, arg1[3]) + x50, x49 := bits.mul_u64(x1, arg1[2]) + x52, x51 := bits.mul_u64(x1, arg1[1]) + x54, x53 := bits.mul_u64(x1, arg1[0]) + x55, x56 := bits.add_u64(x54, x51, u64(0x0)) + x57, x58 := bits.add_u64(x52, x49, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x50, x47, u64(fiat.u1(x58))) + x61 := (u64(fiat.u1(x60)) + x48) + x62, x63 := bits.add_u64(x39, x53, u64(0x0)) + x64, x65 := bits.add_u64(x41, x55, u64(fiat.u1(x63))) + x66, x67 := bits.add_u64(x43, x57, u64(fiat.u1(x65))) + x68, x69 := bits.add_u64(x45, x59, u64(fiat.u1(x67))) + x70, x71 := bits.add_u64(u64(fiat.u1(x46)), x61, u64(fiat.u1(x69))) + _, x72 := bits.mul_u64(x62, 0xccd1c8aaee00bc4f) + x75, x74 := bits.mul_u64(x72, 0xffffffff00000000) + x77, x76 := bits.mul_u64(x72, 0xffffffffffffffff) + x79, x78 := bits.mul_u64(x72, 0xbce6faada7179e84) + x81, x80 := bits.mul_u64(x72, 0xf3b9cac2fc632551) + x82, x83 := bits.add_u64(x81, x78, u64(0x0)) + x84, x85 := bits.add_u64(x79, x76, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x77, x74, u64(fiat.u1(x85))) + x88 := (u64(fiat.u1(x87)) + x75) + _, x90 := bits.add_u64(x62, x80, u64(0x0)) + x91, x92 := bits.add_u64(x64, x82, u64(fiat.u1(x90))) + x93, x94 := bits.add_u64(x66, x84, u64(fiat.u1(x92))) + x95, x96 := bits.add_u64(x68, x86, u64(fiat.u1(x94))) + x97, x98 := bits.add_u64(x70, x88, u64(fiat.u1(x96))) + x99 := (u64(fiat.u1(x98)) + u64(fiat.u1(x71))) + x101, x100 := bits.mul_u64(x2, arg1[3]) + x103, x102 := bits.mul_u64(x2, arg1[2]) + x105, x104 := bits.mul_u64(x2, arg1[1]) + x107, x106 := bits.mul_u64(x2, arg1[0]) + x108, x109 := bits.add_u64(x107, x104, u64(0x0)) + x110, x111 := bits.add_u64(x105, x102, u64(fiat.u1(x109))) + x112, x113 := bits.add_u64(x103, x100, u64(fiat.u1(x111))) + x114 := (u64(fiat.u1(x113)) + x101) + x115, x116 := bits.add_u64(x91, x106, u64(0x0)) + x117, x118 := bits.add_u64(x93, x108, u64(fiat.u1(x116))) + x119, x120 := bits.add_u64(x95, x110, u64(fiat.u1(x118))) + x121, x122 := bits.add_u64(x97, x112, u64(fiat.u1(x120))) + x123, x124 := bits.add_u64(x99, x114, u64(fiat.u1(x122))) + _, x125 := bits.mul_u64(x115, 0xccd1c8aaee00bc4f) + x128, x127 := bits.mul_u64(x125, 0xffffffff00000000) + x130, x129 := bits.mul_u64(x125, 0xffffffffffffffff) + x132, x131 := bits.mul_u64(x125, 0xbce6faada7179e84) + x134, x133 := bits.mul_u64(x125, 0xf3b9cac2fc632551) + x135, x136 := bits.add_u64(x134, x131, u64(0x0)) + x137, x138 := bits.add_u64(x132, x129, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(x130, x127, u64(fiat.u1(x138))) + x141 := (u64(fiat.u1(x140)) + x128) + _, x143 := bits.add_u64(x115, x133, u64(0x0)) + x144, x145 := bits.add_u64(x117, x135, u64(fiat.u1(x143))) + x146, x147 := bits.add_u64(x119, x137, u64(fiat.u1(x145))) + x148, x149 := bits.add_u64(x121, x139, u64(fiat.u1(x147))) + x150, x151 := bits.add_u64(x123, x141, u64(fiat.u1(x149))) + x152 := (u64(fiat.u1(x151)) + u64(fiat.u1(x124))) + x154, x153 := bits.mul_u64(x3, arg1[3]) + x156, x155 := bits.mul_u64(x3, arg1[2]) + x158, x157 := bits.mul_u64(x3, arg1[1]) + x160, x159 := bits.mul_u64(x3, arg1[0]) + x161, x162 := bits.add_u64(x160, x157, u64(0x0)) + x163, x164 := bits.add_u64(x158, x155, u64(fiat.u1(x162))) + x165, x166 := bits.add_u64(x156, x153, u64(fiat.u1(x164))) + x167 := (u64(fiat.u1(x166)) + x154) + x168, x169 := bits.add_u64(x144, x159, u64(0x0)) + x170, x171 := bits.add_u64(x146, x161, u64(fiat.u1(x169))) + x172, x173 := bits.add_u64(x148, x163, u64(fiat.u1(x171))) + x174, x175 := bits.add_u64(x150, x165, u64(fiat.u1(x173))) + x176, x177 := bits.add_u64(x152, x167, u64(fiat.u1(x175))) + _, x178 := bits.mul_u64(x168, 0xccd1c8aaee00bc4f) + x181, x180 := bits.mul_u64(x178, 0xffffffff00000000) + x183, x182 := bits.mul_u64(x178, 0xffffffffffffffff) + x185, x184 := bits.mul_u64(x178, 0xbce6faada7179e84) + x187, x186 := bits.mul_u64(x178, 0xf3b9cac2fc632551) + x188, x189 := bits.add_u64(x187, x184, u64(0x0)) + x190, x191 := bits.add_u64(x185, x182, u64(fiat.u1(x189))) + x192, x193 := bits.add_u64(x183, x180, u64(fiat.u1(x191))) + x194 := (u64(fiat.u1(x193)) + x181) + _, x196 := bits.add_u64(x168, x186, u64(0x0)) + x197, x198 := bits.add_u64(x170, x188, u64(fiat.u1(x196))) + x199, x200 := bits.add_u64(x172, x190, u64(fiat.u1(x198))) + x201, x202 := bits.add_u64(x174, x192, u64(fiat.u1(x200))) + x203, x204 := bits.add_u64(x176, x194, u64(fiat.u1(x202))) + x205 := (u64(fiat.u1(x204)) + u64(fiat.u1(x177))) + x206, x207 := bits.sub_u64(x197, 0xf3b9cac2fc632551, u64(0x0)) + x208, x209 := bits.sub_u64(x199, 0xbce6faada7179e84, u64(fiat.u1(x207))) + x210, x211 := bits.sub_u64(x201, 0xffffffffffffffff, u64(fiat.u1(x209))) + x212, x213 := bits.sub_u64(x203, 0xffffffff00000000, u64(fiat.u1(x211))) + _, x215 := bits.sub_u64(x205, u64(0x0), u64(fiat.u1(x213))) + x216 := fiat.cmovznz_u64(fiat.u1(x215), x206, x197) + x217 := fiat.cmovznz_u64(fiat.u1(x215), x208, x199) + x218 := fiat.cmovznz_u64(fiat.u1(x215), x210, x201) + x219 := fiat.cmovznz_u64(fiat.u1(x215), x212, x203) + out1[0] = x216 + out1[1] = x217 + out1[2] = x218 + out1[3] = x219 +} + +fe_add :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.add_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.add_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.add_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.add_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9, x10 := bits.sub_u64(x1, 0xf3b9cac2fc632551, u64(0x0)) + x11, x12 := bits.sub_u64(x3, 0xbce6faada7179e84, u64(fiat.u1(x10))) + x13, x14 := bits.sub_u64(x5, 0xffffffffffffffff, u64(fiat.u1(x12))) + x15, x16 := bits.sub_u64(x7, 0xffffffff00000000, u64(fiat.u1(x14))) + _, x18 := bits.sub_u64(u64(fiat.u1(x8)), u64(0x0), u64(fiat.u1(x16))) + x19 := fiat.cmovznz_u64(fiat.u1(x18), x9, x1) + x20 := fiat.cmovznz_u64(fiat.u1(x18), x11, x3) + x21 := fiat.cmovznz_u64(fiat.u1(x18), x13, x5) + x22 := fiat.cmovznz_u64(fiat.u1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +fe_sub :: proc "contextless" (out1, arg1, arg2: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(arg1[0], arg2[0], u64(0x0)) + x3, x4 := bits.sub_u64(arg1[1], arg2[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(arg1[2], arg2[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(arg1[3], arg2[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, (x9 & 0xf3b9cac2fc632551), u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xbce6faada7179e84), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, x9, u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000000), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_opp :: proc "contextless" (out1, arg1: ^Montgomery_Domain_Field_Element) { + x1, x2 := bits.sub_u64(u64(0x0), arg1[0], u64(0x0)) + x3, x4 := bits.sub_u64(u64(0x0), arg1[1], u64(fiat.u1(x2))) + x5, x6 := bits.sub_u64(u64(0x0), arg1[2], u64(fiat.u1(x4))) + x7, x8 := bits.sub_u64(u64(0x0), arg1[3], u64(fiat.u1(x6))) + x9 := fiat.cmovznz_u64(fiat.u1(x8), u64(0x0), 0xffffffffffffffff) + x10, x11 := bits.add_u64(x1, (x9 & 0xf3b9cac2fc632551), u64(0x0)) + x12, x13 := bits.add_u64(x3, (x9 & 0xbce6faada7179e84), u64(fiat.u1(x11))) + x14, x15 := bits.add_u64(x5, x9, u64(fiat.u1(x13))) + x16, _ := bits.add_u64(x7, (x9 & 0xffffffff00000000), u64(fiat.u1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +fe_one :: proc "contextless" (out1: ^Montgomery_Domain_Field_Element) { + out1[0] = 0xc46353d039cdaaf + out1[1] = 0x4319055258e8617b + out1[2] = u64(0x0) + out1[3] = 0xffffffff +} + +fe_non_zero :: proc "contextless" (arg1: ^Montgomery_Domain_Field_Element) -> u64 { + return arg1[0] | (arg1[1] | (arg1[2] | arg1[3])) +} + +@(optimization_mode = "none") +fe_cond_assign :: #force_no_inline proc "contextless" ( + out1, arg1: ^Montgomery_Domain_Field_Element, + arg2: int, +) { + x1 := fiat.cmovznz_u64(fiat.u1(arg2), out1[0], arg1[0]) + x2 := fiat.cmovznz_u64(fiat.u1(arg2), out1[1], arg1[1]) + x3 := fiat.cmovznz_u64(fiat.u1(arg2), out1[2], arg1[2]) + x4 := fiat.cmovznz_u64(fiat.u1(arg2), out1[3], arg1[3]) + out1[0] = x1 + out1[1] = x2 + out1[2] = x3 + out1[3] = x4 +} + +fe_from_montgomery :: proc "contextless" ( + out1: ^Non_Montgomery_Domain_Field_Element, + arg1: ^Montgomery_Domain_Field_Element, +) { + x1 := arg1[0] + _, x2 := bits.mul_u64(x1, 0xccd1c8aaee00bc4f) + x5, x4 := bits.mul_u64(x2, 0xffffffff00000000) + x7, x6 := bits.mul_u64(x2, 0xffffffffffffffff) + x9, x8 := bits.mul_u64(x2, 0xbce6faada7179e84) + x11, x10 := bits.mul_u64(x2, 0xf3b9cac2fc632551) + x12, x13 := bits.add_u64(x11, x8, u64(0x0)) + x14, x15 := bits.add_u64(x9, x6, u64(fiat.u1(x13))) + x16, x17 := bits.add_u64(x7, x4, u64(fiat.u1(x15))) + _, x19 := bits.add_u64(x1, x10, u64(0x0)) + x20, x21 := bits.add_u64(u64(0x0), x12, u64(fiat.u1(x19))) + x22, x23 := bits.add_u64(u64(0x0), x14, u64(fiat.u1(x21))) + x24, x25 := bits.add_u64(u64(0x0), x16, u64(fiat.u1(x23))) + x26, x27 := bits.add_u64(x20, arg1[1], u64(0x0)) + x28, x29 := bits.add_u64(x22, u64(0x0), u64(fiat.u1(x27))) + x30, x31 := bits.add_u64(x24, u64(0x0), u64(fiat.u1(x29))) + _, x32 := bits.mul_u64(x26, 0xccd1c8aaee00bc4f) + x35, x34 := bits.mul_u64(x32, 0xffffffff00000000) + x37, x36 := bits.mul_u64(x32, 0xffffffffffffffff) + x39, x38 := bits.mul_u64(x32, 0xbce6faada7179e84) + x41, x40 := bits.mul_u64(x32, 0xf3b9cac2fc632551) + x42, x43 := bits.add_u64(x41, x38, u64(0x0)) + x44, x45 := bits.add_u64(x39, x36, u64(fiat.u1(x43))) + x46, x47 := bits.add_u64(x37, x34, u64(fiat.u1(x45))) + _, x49 := bits.add_u64(x26, x40, u64(0x0)) + x50, x51 := bits.add_u64(x28, x42, u64(fiat.u1(x49))) + x52, x53 := bits.add_u64(x30, x44, u64(fiat.u1(x51))) + x54, x55 := bits.add_u64((u64(fiat.u1(x31)) + (u64(fiat.u1(x25)) + (u64(fiat.u1(x17)) + x5))), x46, u64(fiat.u1(x53))) + x56, x57 := bits.add_u64(x50, arg1[2], u64(0x0)) + x58, x59 := bits.add_u64(x52, u64(0x0), u64(fiat.u1(x57))) + x60, x61 := bits.add_u64(x54, u64(0x0), u64(fiat.u1(x59))) + _, x62 := bits.mul_u64(x56, 0xccd1c8aaee00bc4f) + x65, x64 := bits.mul_u64(x62, 0xffffffff00000000) + x67, x66 := bits.mul_u64(x62, 0xffffffffffffffff) + x69, x68 := bits.mul_u64(x62, 0xbce6faada7179e84) + x71, x70 := bits.mul_u64(x62, 0xf3b9cac2fc632551) + x72, x73 := bits.add_u64(x71, x68, u64(0x0)) + x74, x75 := bits.add_u64(x69, x66, u64(fiat.u1(x73))) + x76, x77 := bits.add_u64(x67, x64, u64(fiat.u1(x75))) + _, x79 := bits.add_u64(x56, x70, u64(0x0)) + x80, x81 := bits.add_u64(x58, x72, u64(fiat.u1(x79))) + x82, x83 := bits.add_u64(x60, x74, u64(fiat.u1(x81))) + x84, x85 := bits.add_u64((u64(fiat.u1(x61)) + (u64(fiat.u1(x55)) + (u64(fiat.u1(x47)) + x35))), x76, u64(fiat.u1(x83))) + x86, x87 := bits.add_u64(x80, arg1[3], u64(0x0)) + x88, x89 := bits.add_u64(x82, u64(0x0), u64(fiat.u1(x87))) + x90, x91 := bits.add_u64(x84, u64(0x0), u64(fiat.u1(x89))) + _, x92 := bits.mul_u64(x86, 0xccd1c8aaee00bc4f) + x95, x94 := bits.mul_u64(x92, 0xffffffff00000000) + x97, x96 := bits.mul_u64(x92, 0xffffffffffffffff) + x99, x98 := bits.mul_u64(x92, 0xbce6faada7179e84) + x101, x100 := bits.mul_u64(x92, 0xf3b9cac2fc632551) + x102, x103 := bits.add_u64(x101, x98, u64(0x0)) + x104, x105 := bits.add_u64(x99, x96, u64(fiat.u1(x103))) + x106, x107 := bits.add_u64(x97, x94, u64(fiat.u1(x105))) + _, x109 := bits.add_u64(x86, x100, u64(0x0)) + x110, x111 := bits.add_u64(x88, x102, u64(fiat.u1(x109))) + x112, x113 := bits.add_u64(x90, x104, u64(fiat.u1(x111))) + x114, x115 := bits.add_u64((u64(fiat.u1(x91)) + (u64(fiat.u1(x85)) + (u64(fiat.u1(x77)) + x65))), x106, u64(fiat.u1(x113))) + x116 := (u64(fiat.u1(x115)) + (u64(fiat.u1(x107)) + x95)) + x117, x118 := bits.sub_u64(x110, 0xf3b9cac2fc632551, u64(0x0)) + x119, x120 := bits.sub_u64(x112, 0xbce6faada7179e84, u64(fiat.u1(x118))) + x121, x122 := bits.sub_u64(x114, 0xffffffffffffffff, u64(fiat.u1(x120))) + x123, x124 := bits.sub_u64(x116, 0xffffffff00000000, u64(fiat.u1(x122))) + _, x126 := bits.sub_u64(u64(0x0), u64(0x0), u64(fiat.u1(x124))) + x127 := fiat.cmovznz_u64(fiat.u1(x126), x117, x110) + x128 := fiat.cmovznz_u64(fiat.u1(x126), x119, x112) + x129 := fiat.cmovznz_u64(fiat.u1(x126), x121, x114) + x130 := fiat.cmovznz_u64(fiat.u1(x126), x123, x116) + out1[0] = x127 + out1[1] = x128 + out1[2] = x129 + out1[3] = x130 +} + +fe_to_montgomery :: proc "contextless" ( + out1: ^Montgomery_Domain_Field_Element, + arg1: ^Non_Montgomery_Domain_Field_Element, +) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + x6, x5 := bits.mul_u64(x4, 0x66e12d94f3d95620) + x8, x7 := bits.mul_u64(x4, 0x2845b2392b6bec59) + x10, x9 := bits.mul_u64(x4, 0x4699799c49bd6fa6) + x12, x11 := bits.mul_u64(x4, 0x83244c95be79eea2) + x13, x14 := bits.add_u64(x12, x9, u64(0x0)) + x15, x16 := bits.add_u64(x10, x7, u64(fiat.u1(x14))) + x17, x18 := bits.add_u64(x8, x5, u64(fiat.u1(x16))) + _, x19 := bits.mul_u64(x11, 0xccd1c8aaee00bc4f) + x22, x21 := bits.mul_u64(x19, 0xffffffff00000000) + x24, x23 := bits.mul_u64(x19, 0xffffffffffffffff) + x26, x25 := bits.mul_u64(x19, 0xbce6faada7179e84) + x28, x27 := bits.mul_u64(x19, 0xf3b9cac2fc632551) + x29, x30 := bits.add_u64(x28, x25, u64(0x0)) + x31, x32 := bits.add_u64(x26, x23, u64(fiat.u1(x30))) + x33, x34 := bits.add_u64(x24, x21, u64(fiat.u1(x32))) + _, x36 := bits.add_u64(x11, x27, u64(0x0)) + x37, x38 := bits.add_u64(x13, x29, u64(fiat.u1(x36))) + x39, x40 := bits.add_u64(x15, x31, u64(fiat.u1(x38))) + x41, x42 := bits.add_u64(x17, x33, u64(fiat.u1(x40))) + x43, x44 := bits.add_u64((u64(fiat.u1(x18)) + x6), (u64(fiat.u1(x34)) + x22), u64(fiat.u1(x42))) + x46, x45 := bits.mul_u64(x1, 0x66e12d94f3d95620) + x48, x47 := bits.mul_u64(x1, 0x2845b2392b6bec59) + x50, x49 := bits.mul_u64(x1, 0x4699799c49bd6fa6) + x52, x51 := bits.mul_u64(x1, 0x83244c95be79eea2) + x53, x54 := bits.add_u64(x52, x49, u64(0x0)) + x55, x56 := bits.add_u64(x50, x47, u64(fiat.u1(x54))) + x57, x58 := bits.add_u64(x48, x45, u64(fiat.u1(x56))) + x59, x60 := bits.add_u64(x37, x51, u64(0x0)) + x61, x62 := bits.add_u64(x39, x53, u64(fiat.u1(x60))) + x63, x64 := bits.add_u64(x41, x55, u64(fiat.u1(x62))) + x65, x66 := bits.add_u64(x43, x57, u64(fiat.u1(x64))) + _, x67 := bits.mul_u64(x59, 0xccd1c8aaee00bc4f) + x70, x69 := bits.mul_u64(x67, 0xffffffff00000000) + x72, x71 := bits.mul_u64(x67, 0xffffffffffffffff) + x74, x73 := bits.mul_u64(x67, 0xbce6faada7179e84) + x76, x75 := bits.mul_u64(x67, 0xf3b9cac2fc632551) + x77, x78 := bits.add_u64(x76, x73, u64(0x0)) + x79, x80 := bits.add_u64(x74, x71, u64(fiat.u1(x78))) + x81, x82 := bits.add_u64(x72, x69, u64(fiat.u1(x80))) + _, x84 := bits.add_u64(x59, x75, u64(0x0)) + x85, x86 := bits.add_u64(x61, x77, u64(fiat.u1(x84))) + x87, x88 := bits.add_u64(x63, x79, u64(fiat.u1(x86))) + x89, x90 := bits.add_u64(x65, x81, u64(fiat.u1(x88))) + x91, x92 := bits.add_u64(((u64(fiat.u1(x66)) + u64(fiat.u1(x44))) + (u64(fiat.u1(x58)) + x46)), (u64(fiat.u1(x82)) + x70), u64(fiat.u1(x90))) + x94, x93 := bits.mul_u64(x2, 0x66e12d94f3d95620) + x96, x95 := bits.mul_u64(x2, 0x2845b2392b6bec59) + x98, x97 := bits.mul_u64(x2, 0x4699799c49bd6fa6) + x100, x99 := bits.mul_u64(x2, 0x83244c95be79eea2) + x101, x102 := bits.add_u64(x100, x97, u64(0x0)) + x103, x104 := bits.add_u64(x98, x95, u64(fiat.u1(x102))) + x105, x106 := bits.add_u64(x96, x93, u64(fiat.u1(x104))) + x107, x108 := bits.add_u64(x85, x99, u64(0x0)) + x109, x110 := bits.add_u64(x87, x101, u64(fiat.u1(x108))) + x111, x112 := bits.add_u64(x89, x103, u64(fiat.u1(x110))) + x113, x114 := bits.add_u64(x91, x105, u64(fiat.u1(x112))) + _, x115 := bits.mul_u64(x107, 0xccd1c8aaee00bc4f) + x118, x117 := bits.mul_u64(x115, 0xffffffff00000000) + x120, x119 := bits.mul_u64(x115, 0xffffffffffffffff) + x122, x121 := bits.mul_u64(x115, 0xbce6faada7179e84) + x124, x123 := bits.mul_u64(x115, 0xf3b9cac2fc632551) + x125, x126 := bits.add_u64(x124, x121, u64(0x0)) + x127, x128 := bits.add_u64(x122, x119, u64(fiat.u1(x126))) + x129, x130 := bits.add_u64(x120, x117, u64(fiat.u1(x128))) + _, x132 := bits.add_u64(x107, x123, u64(0x0)) + x133, x134 := bits.add_u64(x109, x125, u64(fiat.u1(x132))) + x135, x136 := bits.add_u64(x111, x127, u64(fiat.u1(x134))) + x137, x138 := bits.add_u64(x113, x129, u64(fiat.u1(x136))) + x139, x140 := bits.add_u64(((u64(fiat.u1(x114)) + u64(fiat.u1(x92))) + (u64(fiat.u1(x106)) + x94)), (u64(fiat.u1(x130)) + x118), u64(fiat.u1(x138))) + x142, x141 := bits.mul_u64(x3, 0x66e12d94f3d95620) + x144, x143 := bits.mul_u64(x3, 0x2845b2392b6bec59) + x146, x145 := bits.mul_u64(x3, 0x4699799c49bd6fa6) + x148, x147 := bits.mul_u64(x3, 0x83244c95be79eea2) + x149, x150 := bits.add_u64(x148, x145, u64(0x0)) + x151, x152 := bits.add_u64(x146, x143, u64(fiat.u1(x150))) + x153, x154 := bits.add_u64(x144, x141, u64(fiat.u1(x152))) + x155, x156 := bits.add_u64(x133, x147, u64(0x0)) + x157, x158 := bits.add_u64(x135, x149, u64(fiat.u1(x156))) + x159, x160 := bits.add_u64(x137, x151, u64(fiat.u1(x158))) + x161, x162 := bits.add_u64(x139, x153, u64(fiat.u1(x160))) + _, x163 := bits.mul_u64(x155, 0xccd1c8aaee00bc4f) + x166, x165 := bits.mul_u64(x163, 0xffffffff00000000) + x168, x167 := bits.mul_u64(x163, 0xffffffffffffffff) + x170, x169 := bits.mul_u64(x163, 0xbce6faada7179e84) + x172, x171 := bits.mul_u64(x163, 0xf3b9cac2fc632551) + x173, x174 := bits.add_u64(x172, x169, u64(0x0)) + x175, x176 := bits.add_u64(x170, x167, u64(fiat.u1(x174))) + x177, x178 := bits.add_u64(x168, x165, u64(fiat.u1(x176))) + _, x180 := bits.add_u64(x155, x171, u64(0x0)) + x181, x182 := bits.add_u64(x157, x173, u64(fiat.u1(x180))) + x183, x184 := bits.add_u64(x159, x175, u64(fiat.u1(x182))) + x185, x186 := bits.add_u64(x161, x177, u64(fiat.u1(x184))) + x187, x188 := bits.add_u64(((u64(fiat.u1(x162)) + u64(fiat.u1(x140))) + (u64(fiat.u1(x154)) + x142)), (u64(fiat.u1(x178)) + x166), u64(fiat.u1(x186))) + x189, x190 := bits.sub_u64(x181, 0xf3b9cac2fc632551, u64(0x0)) + x191, x192 := bits.sub_u64(x183, 0xbce6faada7179e84, u64(fiat.u1(x190))) + x193, x194 := bits.sub_u64(x185, 0xffffffffffffffff, u64(fiat.u1(x192))) + x195, x196 := bits.sub_u64(x187, 0xffffffff00000000, u64(fiat.u1(x194))) + _, x198 := bits.sub_u64(u64(fiat.u1(x188)), u64(0x0), u64(fiat.u1(x196))) + x199 := fiat.cmovznz_u64(fiat.u1(x198), x189, x181) + x200 := fiat.cmovznz_u64(fiat.u1(x198), x191, x183) + x201 := fiat.cmovznz_u64(fiat.u1(x198), x193, x185) + x202 := fiat.cmovznz_u64(fiat.u1(x198), x195, x187) + out1[0] = x199 + out1[1] = x200 + out1[2] = x201 + out1[3] = x202 +} diff --git a/core/crypto/_weierstrass/fe.odin b/core/crypto/_weierstrass/fe.odin new file mode 100644 index 000000000..1a160a03c --- /dev/null +++ b/core/crypto/_weierstrass/fe.odin @@ -0,0 +1,135 @@ +package _weierstrass + +import p256r1 "core:crypto/_fiat/field_p256r1" +import "core:math/bits" + +Field_Element_p256r1 :: p256r1.Montgomery_Domain_Field_Element + +FE_SIZE_P256R1 :: 32 + +fe_clear :: proc { + p256r1.fe_clear, +} + +fe_clear_vec :: proc { + p256r1.fe_clear_vec, +} + +fe_set_bytes :: proc { + p256r1.fe_from_bytes, +} +fe_bytes :: proc { + p256r1.fe_to_bytes, +} + +fe_set :: proc { + p256r1.fe_set, +} + +fe_zero :: proc { + p256r1.fe_zero, +} + +fe_a :: proc { + fe_a_p256r1, +} + +fe_b :: proc { + fe_b_p256r1, +} + +fe_gen_x :: proc { + fe_gen_x_p256r1, +} + +fe_gen_y :: proc { + fe_gen_y_p256r1, +} + +fe_one :: proc { + p256r1.fe_one, +} + +fe_add :: proc { + p256r1.fe_add, +} + +fe_sub :: proc { + p256r1.fe_sub, +} + +fe_negate :: proc { + p256r1.fe_opp, +} + +fe_mul :: proc { + p256r1.fe_mul, +} + +fe_square :: proc { + p256r1.fe_square, +} + +fe_inv :: proc { + p256r1.fe_inv, +} + +fe_sqrt :: proc { + p256r1.fe_sqrt, +} + +fe_equal :: proc { + p256r1.fe_equal, +} + +fe_is_odd :: proc { + p256r1.fe_is_odd, +} + +fe_is_zero :: proc { + fe_is_zero_p256r1, +} + +fe_cond_select :: proc { + p256r1.fe_cond_select, +} + +fe_a_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc + // = -3 mod p + fe[0] = 18446744073709551612 + fe[1] = 17179869183 + fe[2] = 0 + fe[3] = 18446744056529682436 +} + +fe_b_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b + fe[0] = 15608596021259845087 + fe[1] = 12461466548982526096 + fe[2] = 16546823903870267094 + fe[3] = 15866188208926050356 +} + +fe_gen_x_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // G_x = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296 + fe[0] = 8784043285714375740 + fe[1] = 8483257759279461889 + fe[2] = 8789745728267363600 + fe[3] = 1770019616739251654 +} + +fe_gen_y_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) { + // G_y = 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5 + fe[0] = 15992936863339206154 + fe[1] = 10037038012062884956 + fe[2] = 15197544864945402661 + fe[3] = 9615747158586711429 +} + +@(require_results) +fe_is_zero_p256r1 :: proc "contextless" (fe: ^Field_Element_p256r1) -> int { + ctrl := p256r1.fe_non_zero(fe) + _, borrow := bits.sub_u64(ctrl, 1, 0) + return int(borrow) +} diff --git a/core/crypto/_weierstrass/point.odin b/core/crypto/_weierstrass/point.odin new file mode 100644 index 000000000..cde82ebb2 --- /dev/null +++ b/core/crypto/_weierstrass/point.odin @@ -0,0 +1,548 @@ +package _weierstrass + +/* +This implements prime order short Weierstrass curves defined over a field +k with char(k) != 2, 3 (`y^2 = x^3 + ax + b`). for the purpose of +implementing ECDH and ECDSA. Use of this package for other purposes is +NOT RECOMMENDED. + +As an explicit simplicity/performance tradeoff, projective representation +was chosen so that it is possible to use the complete addition +formulas. + +See: +- https://eprint.iacr.org/2015/1060.pdf +- https://hyperelliptic.org/EFD/g1p/auto-shortw-projective.html + +WARNING: The point addition and doubling formulas are specialized for +`a = -3`, which covers secp256r1, secp384r1, secp521r1, FRP256v1, SM2, +and GOST 34.10. The brainpool curves and secp256k1 are NOT SUPPORTED +and would require slightly different formulas. +*/ + +Point_p256r1 :: struct { + x: Field_Element_p256r1, + y: Field_Element_p256r1, + z: Field_Element_p256r1, +} + +@(require_results) +pt_set_xy_bytes :: proc "contextless" (p: ^$T, x_raw, y_raw: []byte) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + x, y: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&x, &y}) + } else { + #panic("weierstrass: invalid curve") + } + + if len(x_raw) != FE_SZ || len(y_raw) != FE_SZ { + return false + } + + if !fe_set_bytes(&x, x_raw) { + return false + } + if !fe_set_bytes(&y, y_raw) { + return false + } + if !is_on_curve(&x, &y) { + return false + } + + fe_set(&p.x, &x) + fe_set(&p.y, &y) + fe_one(&p.z) + + return true +} + +@(require_results) +pt_set_x_bytes :: proc "contextless" (p: ^$T, x_raw: []byte, y_is_odd: int) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + x, y, yy, y_neg: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&x, &y, &yy, &y_neg}) + } else { + #panic("weierstrass: invalid curve") + } + + if len(x_raw) != FE_SZ { + return false + } + + if !fe_set_bytes(&x, x_raw) { + return false + } + set_yy_candidate(&yy, &x) + if fe_sqrt(&y, &yy) != 1 { + return false + } + + // Pick the correct y-coordinate. + fe_negate(&y_neg, &y) + parity_neq := (y_is_odd ~ fe_is_odd(&y)) & 1 + + fe_set(&p.x, &x) + fe_cond_select(&p.y, &y, &y_neg, parity_neq) + fe_one(&p.z) + + return true +} + +@(require_results) +pt_bytes :: proc "contextless" (x, y: []byte, p: ^$T) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + } else { + #panic("weierstrass: invalid curve") + } + + if pt_is_identity(p) == 1 { + return false + } + + // Convert to affine coordinates. + pt_rescale(p, p) + + switch len(x) { + case 0: + case FE_SZ: + fe_bytes(x, &p.x) + case: + panic_contextless("weierstrass: invalid x buffer") + } + switch len(y) { + case 0: + case FE_SZ: + fe_bytes(y, &p.y) + case: + panic_contextless("weierstrass: invalid y buffer") + } + + return true +} + +pt_set :: proc "contextless" (p, q: ^$T) { + fe_set(&p.x, &q.x) + fe_set(&p.y, &q.y) + fe_set(&p.z, &q.z) +} + +pt_identity :: proc "contextless" (p: ^$T) { + fe_zero(&p.x) + fe_one(&p.y) + fe_zero(&p.z) +} + +pt_generator :: proc "contextless" (p: ^$T) { + fe_gen_x(&p.x) + fe_gen_y(&p.y) + fe_one(&p.z) +} + +pt_clear :: proc "contextless" (p: ^$T) { + fe_clear(&p.x) + fe_clear(&p.y) + fe_clear(&p.z) +} + +pt_clear_vec :: proc "contextless" (arg: []^$T) { + for p in arg { + pt_clear(p) + } +} + +pt_add :: proc "contextless" (p, a, b: ^$T) { + // Algorithm 4 from "Complete addition formulas for prime + // order elliptic curves" by Renes, Costello, and Batina. + // + // The formula is complete in that it is valid for all a and b, + // without exceptions or extra assumptions about the inputs. + // + // The operation costs are `12M + 2mb + 29a`. + + when T == Point_p256r1 { + t0, t1, t2, t3, t4, b_fe: Field_Element_p256r1 + x3, y3, z3: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&t0, &t1, &t2, &t3, &t4, &x3, &y3, &z3}) + } else { + #panic("weierstrass: invalid curve") + } + + x1, y1, z1 := &a.x, &a.y, &a.z + x2, y2, z2 := &b.x, &b.y, &b.z + + fe_b(&b_fe) + + // t0 := X1 * X2 ; t1 := Y1 * Y2 ; t2 := Z1 * Z2 ; + fe_mul(&t0, x1, x2) + fe_mul(&t1, y1, y2) + fe_mul(&t2, z1, z2) + + // t3 := X1 + Y1 ; t4 := X2 + Y2 ; t3 := t3 * t4 ; + fe_add(&t3, x1, y1) + fe_add(&t4, x2, y2) + fe_mul(&t3, &t3, &t4) + + // t4 := t0 + t1 ; t3 := t3 - t4 ; t4 := Y1 + Z1 ; + fe_add(&t4, &t0, &t1) + fe_sub(&t3, &t3, &t4) + fe_add(&t4, y1, z1) + + // X3 := Y2 + Z2 ; t4 := t4 * X3 ; X3 := t1 + t2 ; + fe_add(&x3, y2, z2) + fe_mul(&t4, &t4, &x3) + fe_add(&x3, &t1, &t2) + + // t4 := t4 - X3 ; X3 := X1 + Z1 ; Y3 := X2 + Z2 ; + fe_sub(&t4, &t4, &x3) + fe_add(&x3, x1, z1) + fe_add(&y3, x2, z2) + + // X3 := X3 * Y3 ; Y3 := t0 + t2 ; Y3 := X3 - Y3 ; + fe_mul(&x3, &x3, &y3) + fe_add(&y3, &t0, &t2) + fe_sub(&y3, &x3, &y3) + + // Z3 := b * t2 ; X3 := Y3 - Z3 ; Z3 := X3 + X3 ; + fe_mul(&z3, &b_fe, &t2) + fe_sub(&x3, &y3, &z3) + fe_add(&z3, &x3, &x3) + + // X3 := X3 + Z3 ; Z3 := t1 - X3 ; X3 := t1 + X3 ; + fe_add(&x3, &x3, &z3) + fe_sub(&z3, &t1, &x3) + fe_add(&x3, &t1, &x3) + + // Y3 := b * Y3 ; t1 := t2 + t2 ; t2 := t1 + t2 ; + fe_mul(&y3, &b_fe, &y3) + fe_add(&t1, &t2, &t2) + fe_add(&t2, &t1, &t2) + + // Y3 := Y3 - t2 ; Y3 := Y3 - t0 ; t1 := Y3 + Y3 ; + fe_sub(&y3, &y3, &t2) + fe_sub(&y3, &y3, &t0) + fe_add(&t1, &y3, &y3) + + // Y3 := t1 + Y3 ; t1 := t0 + t0 ; t0 := t1 + t0 ; + fe_add(&y3, &t1, &y3) + fe_add(&t1, &t0, &t0) + fe_add(&t0, &t1, &t0) + + // t0 := t0 - t2 ; t1 := t4 * Y3 ; t2 := t0 * Y3 ; + fe_sub(&t0, &t0, &t2) + fe_mul(&t1, &t4, &y3) + fe_mul(&t2, &t0, &y3) + + // Y3 := X3 * Z3 ; Y3 := Y3 + t2 ; X3 := t3 * X3 ; + fe_mul(&y3, &x3, &z3) + fe_add(&y3, &y3, &t2) + fe_mul(&x3, &t3, &x3) + + // X3 := X3 - t1 ; Z3 := t4 * Z3 ; t1 := t3 * t0 ; + fe_sub(&x3, &x3, &t1) + fe_mul(&z3, &t4, &z3) + fe_mul(&t1, &t3, &t0) + + // Z3 := Z3 + t1 ; + fe_add(&z3, &z3, &t1) + + // return X3 , Y3 , Z3 ; + fe_set(&p.x, &x3) + fe_set(&p.y, &y3) + fe_set(&p.z, &z3) +} + +@(private) +pt_add_mixed :: proc "contextless" (p, a: ^$T, x2, y2: ^$U) { + // Algorithm 5 from "Complete addition formulas for prime + // order elliptic curves" by Renes, Costello, and Batina. + // + // The formula is mixed in that it assumes the z-coordinate + // of the addend (`Z2`) is `1`, meaning that it CAN NOT + // handle the addend being the point at infinity. + // + // The operation costs are `11M + 2mb + 23a` saving + // `1M + 6a` over `pt_add`. + + when T == Point_p256r1 && U == Field_Element_p256r1 { + t0, t1, t2, t3, t4, b_fe: Field_Element_p256r1 + x3, y3, z3: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&t0, &t1, &t2, &t3, &t4, &x3, &y3, &z3}) + } else { + #panic("weierstrass: invalid curve") + } + + x1, y1, z1 := &a.x, &a.y, &a.z + + fe_b(&b_fe) + + // t0 := X1 * X2 ; t1 := Y1 * Y2 ; t3 := X2 + Y2 ; + fe_mul(&t0, x1, x2) + fe_mul(&t1, y1, y2) + fe_add(&t3, x2, y2) + + // t4 := X1 + Y1 ; t3 := t3 * t4 ; t4 := t0 + t1 ; + fe_add(&t4, x1, y1) + fe_mul(&t3, &t3, &t4) + fe_add(&t4, &t0, &t1) + + // t3 := t3 − t4 ; t4 := Y2 * Z1 ; t4 := t4 + Y1 ; + fe_sub(&t3, &t3, &t4) + fe_mul(&t4, y2, z1) + fe_add(&t4, &t4, y1) + + // Y3 := X2 * Z1 ; Y3 := Y3 + X1 ; Z3 := b * Z1 ; + fe_mul(&y3, x2, z1) + fe_add(&y3, &y3, x1) + fe_mul(&z3, &b_fe, z1) + + // X3 := Y3 − Z3 ; Z3 := X3 + X3 ; X3 := X3 + Z3 ; + fe_sub(&x3, &y3, &z3) + fe_add(&z3, &x3, &x3) + fe_add(&x3, &x3, &z3) + + // Z3 := t1 − X3 ; X3 := t1 + X3 ;. Y3 := b * Y3 ; + fe_sub(&z3, &t1, &x3) + fe_add(&x3, &t1, &x3) + fe_mul(&y3, &b_fe, &y3) + + // t1 := Z1 + Z1 ; t2 := t1 + Z1 ; Y3 := Y3 − t2 ; + fe_add(&t1, z1, z1) + fe_add(&t2, &t1, z1) + fe_sub(&y3, &y3, &t2) + + // Y3 := Y3 − t0 ; t1 := Y3 + Y3 ; Y3 := t1 + Y3 ; + fe_sub(&y3, &y3, &t0) + fe_add(&t1, &y3, &y3) + fe_add(&y3, &t1, &y3) + + // t1 := t0 + t0 ; t0 := t1 + t0 ; t0 := t0 − t2 ; + fe_add(&t1, &t0, &t0) + fe_add(&t0, &t1, &t0) + fe_sub(&t0, &t0, &t2) + + // t1 := t4 * Y3 ; t2 := t0 * Y3 ; Y3 := X3 * Z3 ; + fe_mul(&t1, &t4, &y3) + fe_mul(&t2, &t0, &y3) + fe_mul(&y3, &x3, &z3) + + // Y3 := Y3 + t2 ; X3 := t3 * X3 ; X3 := X3 − t1 ; + fe_add(&y3, &y3, &t2) + fe_mul(&x3, &t3, &x3) + fe_sub(&x3, &x3, &t1) + + // Z3 := t4 * Z3 ; t1 := t3 * t0 ; Z3 := Z3 + t1 ; + fe_mul(&z3, &t4, &z3) + fe_mul(&t1, &t3, &t0) + fe_add(&z3, &z3, &t1) + + // return X3 , Y3 , Z3 ; + fe_set(&p.x, &x3) + fe_set(&p.y, &y3) + fe_set(&p.z, &z3) +} + +pt_double :: proc "contextless" (p, a: ^$T) { + // Algorithm 6 from "Complete addition formulas for prime + // order elliptic curves" by Renes, Costello, and Batina. + // + // The formula is complete in that it is valid for all a, + // without exceptions or extra assumptions about the inputs. + // + // The operation costs are `8M + 3S + 2mb + 21a`. + + when T == Point_p256r1 { + t0, t1, t2, t3, b_fe: Field_Element_p256r1 + x3, y3, z3: Field_Element_p256r1 + defer fe_clear_vec([]^Field_Element_p256r1{&t0, &t1, &t2, &t3, &x3, &y3, &z3}) + } else { + #panic("weierstrass: invalid curve") + } + + x, y, z := &a.x, &a.y, &a.z + + fe_b(&b_fe) + + // t0 := X ^2; t1 := Y ^2; t2 := Z ^2; + fe_square(&t0, x) + fe_square(&t1, y) + fe_square(&t2, z) + + // t3 := X * Y ; t3 := t3 + t3 ; Z3 := X * Z ; + fe_mul(&t3, x, y) + fe_add(&t3, &t3, &t3) + fe_mul(&z3, x, z) + + // Z3 := Z3 + Z3 ; Y3 := b * t2 ; Y3 := Y3 - Z3 ; + fe_add(&z3, &z3, &z3) + fe_mul(&y3, &b_fe, &t2) + fe_sub(&y3, &y3, &z3) + + // X3 := Y3 + Y3 ; Y3 := X3 + Y3 ; X3 := t1 - Y3 ; + fe_add(&x3, &y3, &y3) + fe_add(&y3, &x3, &y3) + fe_sub(&x3, &t1, &y3) + + // Y3 := t1 + Y3 ; Y3 := X3 * Y3 ; X3 := X3 * t3 ; + fe_add(&y3, &t1, &y3) + fe_mul(&y3, &x3, &y3) + fe_mul(&x3, &x3, &t3) + + // t3 := t2 + t2 ; t2 := t2 + t3 ; Z3 := b * Z3 ; + fe_add(&t3, &t2, &t2) + fe_add(&t2, &t2, &t3) + fe_mul(&z3, &b_fe, &z3) + + // Z3 := Z3 - t2 ; Z3 := Z3 - t0 ; t3 := Z3 + Z3 ; + fe_sub(&z3, &z3, &t2) + fe_sub(&z3, &z3, &t0) + fe_add(&t3, &z3, &z3) + + // Z3 := Z3 + t3 ; t3 := t0 + t0 ; t0 := t3 + t0 ; + fe_add(&z3, &z3, &t3) + fe_add(&t3, &t0, &t0) + fe_add(&t0, &t3, &t0) + + // t0 := t0 - t2 ; t0 := t0 * Z3 ; Y3 := Y3 + t0 ; + fe_sub(&t0, &t0, &t2) + fe_mul(&t0, &t0, &z3) + fe_add(&y3, &y3, &t0) + + // t0 := Y * Z ; t0 := t0 + t0 ; Z3 := t0 * Z3 ; + fe_mul(&t0, y, z) + fe_add(&t0, &t0, &t0) + fe_mul(&z3, &t0, &z3) + + // X3 := X3 - Z3 ; Z3 := t0 * t1 ; Z3 := Z3 + Z3 ; + fe_sub(&x3, &x3, &z3) + fe_mul(&z3, &t0, &t1) + fe_add(&z3, &z3, &z3) + + // Z3 := Z3 + Z3 ; + fe_add(&z3, &z3, &z3) + + // return X3 , Y3 , Z3 ; + fe_set(&p.x, &x3) + fe_set(&p.y, &y3) + fe_set(&p.z, &z3) +} + +pt_sub :: proc "contextless" (p, a, b: ^$T) { + b_neg: T + pt_negate(&b_neg, b) + pt_add(p, a, &b_neg) + + fe_clear(&b_neg) +} + +pt_negate :: proc "contextless" (p, a: ^$T) { + fe_set(&p.x, &a.x) + fe_negate(&p.y, &a.y) + fe_set(&p.z, &a.z) +} + +pt_rescale :: proc "contextless" (p, a: ^$T) { + // A = 1/Z1 + // X3 = A*X1 + // Y3 = A*Y1 + // Z3 = 1 + // + // As per "From A to Z: Projective coordinates leakage in the wild" + // leaking the Z-coordinate is bad. The modular inversion algorithm + // used in this library is based on Fermat's Little Theorem. + // + // See: https://eprint.iacr.org/2020/432.pdf + + was_identity := pt_is_identity(a) + + when T == Point_p256r1 { + z_inv: Field_Element_p256r1 + } else { + #panic("weierstrass: invalid curve") + } + + ident: T + fe_inv(&z_inv, &a.z) + fe_mul(&p.x, &a.x, &z_inv) + fe_mul(&p.y, &a.y, &z_inv) + fe_one(&p.z) + + pt_identity(&ident) + pt_cond_select(p, p, &ident, was_identity) + + fe_clear(&z_inv) +} + +pt_cond_select :: proc "contextless" (p, a, b: ^$T, ctrl: int) { + fe_cond_select(&p.x, &a.x, &b.x, ctrl) + fe_cond_select(&p.y, &a.y, &b.y, ctrl) + fe_cond_select(&p.z, &a.z, &b.z, ctrl) +} + +@(require_results) +pt_equal :: proc "contextless" (a, b: ^$T) -> int { + when T == Point_p256r1 { + x1z2, x2z1, y1z2, y2z1: Field_Element_p256r1 + } else { + #panic("weierstrass: invalid curve") + } + + // Check X1Z2 == X2Z1 && Y1Z2 == Y2Z1 + fe_mul(&x1z2, &a.x, &b.z) + fe_mul(&x2z1, &b.x, &a.z) + + fe_mul(&y1z2, &a.y, &b.z) + fe_mul(&y2z1, &b.y, &a.z) + + return fe_equal(&x1z2, &x2z1) & fe_equal(&y1z2, &y2z1) +} + +@(require_results) +pt_is_identity :: proc "contextless" (p: ^$T) -> int { + return fe_is_zero(&p.z) +} + +@(require_results) +pt_is_y_odd :: proc "contextless" (p: ^$T) -> int { + tmp: T + defer pt_clear(&tmp) + + fe_set(&tmp, p) + pt_rescale(&tmp) + + return fe_is_odd(&tmp.y) +} + +@(private) +is_on_curve :: proc "contextless" (x, y: ^$T) -> bool { + maybe_yy, yy: T + defer fe_clear_vec([]^T{&maybe_yy, &yy}) + + // RHS: x^3 + ax + b + set_yy_candidate(&maybe_yy, x) + + // LHS: y^2 + fe_square(&yy, y) + + return fe_equal(&maybe_yy, &yy) == 1 +} + +@(private) +set_yy_candidate :: proc "contextless" (maybe_yy, x: ^$T) { + // RHS: x^3 + ax + b + rhs, tmp: T + + fe_square(&tmp, x) + fe_mul(&rhs, &tmp, x) + + fe_a(&tmp) + fe_mul(&tmp, &tmp, x) + fe_add(&rhs, &rhs, &tmp) + + fe_b(&tmp) + fe_add(maybe_yy, &rhs, &tmp) + + fe_clear(&rhs) +} diff --git a/core/crypto/_weierstrass/point_s11n_sec.odin b/core/crypto/_weierstrass/point_s11n_sec.odin new file mode 100644 index 000000000..ae009edb0 --- /dev/null +++ b/core/crypto/_weierstrass/point_s11n_sec.odin @@ -0,0 +1,95 @@ +package _weierstrass + +@(require) import "core:mem" + +@(private) +SEC_PREFIX_IDENTITY :: 0x00 +@(private) +SEC_PREFIX_COMPRESSED_EVEN :: 0x02 +@(private) +SEC_PREFIX_COMPRESSED_ODD :: 0x03 +SEC_PREFIX_UNCOMPRESSED :: 0x04 + +@(require_results) +pt_set_sec_bytes :: proc "contextless" (p: ^$T, b: []byte) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + } else { + #panic("weierstrass: invalid curve") + } + + b_len := len(b) + if b_len < 1 { + return false + } + + switch b[0] { + case SEC_PREFIX_IDENTITY: + if b_len != 1 { + return false + } + pt_identity(p) + return true + case SEC_PREFIX_COMPRESSED_EVEN, SEC_PREFIX_COMPRESSED_ODD: + if b_len != 1 + FE_SZ { + return false + } + y_is_odd := b[0] - SEC_PREFIX_COMPRESSED_EVEN + return pt_set_x_bytes(p, b[1:], int(y_is_odd)) + case SEC_PREFIX_UNCOMPRESSED: + if b_len != 1 + 2 * FE_SZ { + return false + } + x, y := b[1:1+FE_SZ], b[1+FE_SZ:] + return pt_set_xy_bytes(p, x, y) + case: + return false + } +} + +@(require_results) +pt_sec_bytes :: proc "contextless" (b: []byte, p: ^$T, compressed: bool) -> bool { + when T == Point_p256r1 { + FE_SZ :: FE_SIZE_P256R1 + } else { + #panic("weierstrass: invalid curve") + } + + b_len := len(b) + if pt_is_identity(p) == 1 { + if b_len != 1 { + return false + } + b[0] = SEC_PREFIX_IDENTITY + return true + } + + x, y: []byte + y_: [FE_SZ]byte + switch compressed { + case true: + if b_len != 1 + FE_SZ { + return false + } + x, y = b[1:], y_[:] + case false: + if b_len != 1 + 2 * FE_SZ { + return false + } + b[0]= SEC_PREFIX_UNCOMPRESSED + x, y = b[1:1+FE_SZ], b[1+FE_SZ:] + } + if !pt_bytes(x, y, p) { + return false + } + if compressed { + // Instead of calling pt_is_y_odd, just serializing + // y into a temp buffer and checking the parity saves + // 1 redundant rescale call. + y_is_odd := byte(y[FE_SZ-1] & 1) + b[0] = SEC_PREFIX_COMPRESSED_EVEN + y_is_odd + mem.zero_explicit(&y_, size_of(y_)) + } + + return true +} diff --git a/core/crypto/_weierstrass/sc.odin b/core/crypto/_weierstrass/sc.odin new file mode 100644 index 000000000..2ed9459bc --- /dev/null +++ b/core/crypto/_weierstrass/sc.odin @@ -0,0 +1,76 @@ +package _weierstrass + +import p256r1 "core:crypto/_fiat/field_scalarp256r1" +import subtle "core:crypto/_subtle" + +Scalar_p256r1 :: p256r1.Montgomery_Domain_Field_Element + +SC_SIZE_P256R1 :: 32 + +sc_clear :: proc { + p256r1.fe_clear, +} + +sc_clear_vec :: proc { + p256r1.fe_clear_vec, +} + +sc_set_bytes :: proc { + p256r1.fe_from_bytes, +} +sc_bytes :: proc { + p256r1.fe_to_bytes, +} + +sc_set :: proc { + p256r1.fe_set, +} + +sc_zero :: proc { + p256r1.fe_zero, +} + +sc_one_p256r1 :: proc { + p256r1.fe_one, +} + +sc_add :: proc { + p256r1.fe_add, +} + +sc_sub :: proc { + p256r1.fe_sub, +} + +sc_negate :: proc { + p256r1.fe_opp, +} + +sc_mul :: proc { + p256r1.fe_mul, +} + +sc_square :: proc { + p256r1.fe_square, +} + +sc_cond_assign :: proc { + p256r1.fe_cond_assign, +} + +sc_equal :: proc { + p256r1.fe_equal, +} + +sc_is_odd :: proc { + p256r1.fe_is_odd, +} + +sc_is_zero :: proc { + sc_is_zero_p256r1, +} + +@(require_results) +sc_is_zero_p256r1 :: proc "contextless" (fe: ^Scalar_p256r1) -> int { + return int(subtle.u64_is_zero(p256r1.fe_non_zero(fe))) +} diff --git a/core/crypto/_weierstrass/scalar_mul.odin b/core/crypto/_weierstrass/scalar_mul.odin new file mode 100644 index 000000000..1781ac3b6 --- /dev/null +++ b/core/crypto/_weierstrass/scalar_mul.odin @@ -0,0 +1,204 @@ +package _weierstrass + +import "core:crypto" +import subtle "core:crypto/_subtle" +import "core:mem" + +pt_scalar_mul :: proc "contextless" ( + p, a: ^$T, + sc: ^$S, + unsafe_is_vartime: bool = false, +) { + when T == Point_p256r1 && S == Scalar_p256r1 { + SC_SZ :: SC_SIZE_P256R1 + } else { + #panic("weierstrass: invalid curve") + } + + b: [SC_SZ]byte = --- + sc_bytes(b[:], sc) + + pt_scalar_mul_bytes(p, a, b[:], unsafe_is_vartime) + + if !unsafe_is_vartime { + mem.zero_explicit(&b, size_of(b)) + } +} + +pt_scalar_mul_bytes :: proc "contextless" ( + p, a: ^$T, + sc: []byte, + unsafe_is_vartime: bool = false, +) { + when T == Point_p256r1 { + p_tbl: Multiply_Table_p256r1 = --- + q, tmp: Point_p256r1 = ---, --- + SC_SZ :: SC_SIZE_P256R1 + } else { + #panic("weierstrass: invalid curve") + } + + assert_contextless(len(sc) == SC_SZ, "weierstrass: invalid scalar size") + mul_tbl_set(&p_tbl, a, unsafe_is_vartime) + + pt_identity(&q) + for limb_byte, i in sc { + hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f + + if i != 0 { + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + } + mul_tbl_lookup_add(&q, &tmp, &p_tbl, u64(hi), unsafe_is_vartime) + + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + pt_double(&q, &q) + mul_tbl_lookup_add(&q, &tmp, &p_tbl, u64(lo), unsafe_is_vartime) + } + + pt_set(p, &q) + + if !unsafe_is_vartime { + mem.zero_explicit(&p_tbl, size_of(p_tbl)) + pt_clear_vec([]^T{&q, &tmp}) + } +} + +when crypto.COMPACT_IMPLS == true { + pt_scalar_mul_generator :: proc "contextless" ( + p: ^$T, + sc: ^$S, + unsafe_is_vartime: bool = false, + ) { + g: T + pt_generator(&g) + + pt_scalar_mul(p, &g, sc, unsafe_is_vartime) + } +} else { + pt_scalar_mul_generator :: proc "contextless" ( + p: ^$T, + sc: ^$S, + unsafe_is_vartime: bool = false, + ) { + when T == Point_p256r1 && S == Scalar_p256r1 { + p_tbl_hi := &Gen_Multiply_Table_p256r1_hi + p_tbl_lo := &Gen_Multiply_Table_p256r1_lo + tmp: Point_p256r1 = --- + SC_SZ :: SC_SIZE_P256R1 + } else { + #panic("weierstrass: invalid curve") + } + + b: [SC_SZ]byte + sc_bytes(b[:], sc) + + pt_identity(p) + for limb_byte, i in b { + hi, lo := (limb_byte >> 4) & 0x0f, limb_byte & 0x0f + mul_affine_tbl_lookup_add(p, &tmp, &p_tbl_hi[i], u64(hi), unsafe_is_vartime) + mul_affine_tbl_lookup_add(p, &tmp, &p_tbl_lo[i], u64(lo), unsafe_is_vartime) + } + + if !unsafe_is_vartime { + mem.zero_explicit(&b, size_of(b)) + pt_clear(&tmp) + } + } +} + +@(private="file") +Multiply_Table_p256r1 :: [15]Point_p256r1 + +@(private="file") +mul_tbl_set :: proc "contextless"( + tbl: ^$T, + point: ^$U, + unsafe_is_vartime: bool, +) { + when T == Multiply_Table_p256r1 && U == Point_p256r1{ + tmp: Point_p256r1 + pt_set(&tmp, point) + } else { + #panic("weierstrass: invalid curve") + } + + pt_set(&tbl[0], &tmp) + for i in 1 ..<15 { + pt_add(&tmp, &tmp, point) + pt_set(&tbl[i], &tmp) + } + + if !unsafe_is_vartime { + pt_clear(&tmp) + } +} + +@(private="file") +mul_tbl_lookup_add :: proc "contextless" ( + point, tmp: ^$T, + tbl: ^$U, + idx: u64, + unsafe_is_vartime: bool, + ) { + if unsafe_is_vartime { + switch idx { + case 0: + case: + pt_add(point, point, &tbl[idx - 1]) + } + return + } + + pt_identity(tmp) + for i in u64(1)..<16 { + ctrl := subtle.eq(i, idx) + pt_cond_select(tmp, tmp, &tbl[i - 1], int(ctrl)) + } + + pt_add(point, point, tmp) +} + +when crypto.COMPACT_IMPLS == false { + @(private) + Affine_Point_p256r1 :: struct { + x: Field_Element_p256r1, + y: Field_Element_p256r1, + } + + @(private="file") + mul_affine_tbl_lookup_add :: proc "contextless" ( + point, tmp: ^$T, + tbl: ^$U, + idx: u64, + unsafe_is_vartime: bool, + ) { + if unsafe_is_vartime { + switch idx { + case 0: + case: + pt_add_mixed(point, point, &tbl[idx - 1].x, &tbl[idx - 1].y) + } + return + } + + pt_identity(tmp) + for i in u64(1)..<16 { + ctrl := int(subtle.eq(i, idx)) + fe_cond_select(&tmp.x, &tmp.x, &tbl[i - 1].x, ctrl) + fe_cond_select(&tmp.y, &tmp.y, &tbl[i - 1].y, ctrl) + } + + // The mixed addition formula assumes that the addend is not + // the neutral element. Do the addition regardless, and then + // conditionally select the right result. + pt_add_mixed(tmp, point, &tmp.x, &tmp.y) + + ctrl := subtle.u64_is_non_zero(idx) + pt_cond_select(point, point, tmp, int(ctrl)) + } +} diff --git a/core/crypto/_weierstrass/secp256r1_table.odin b/core/crypto/_weierstrass/secp256r1_table.odin new file mode 100644 index 000000000..1a6bc3ef6 --- /dev/null +++ b/core/crypto/_weierstrass/secp256r1_table.odin @@ -0,0 +1,3985 @@ +package _weierstrass + +/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/ + +import "core:crypto" + +when crypto.COMPACT_IMPLS == false { + @(private,rodata) + Gen_Multiply_Table_p256r1_hi := [32][15]Affine_Point_p256r1 { + { + { + {9259451175701532574, 15597985540941612547, 4541553034987877619, 8927802479718285609}, + {14672230714928802576, 14284617950605306700, 13339970812390782046, 787078889494395850}, + }, + { + {18165439414433063919, 14693282888419586094, 14992616289789993230, 13232208150801553912}, + {16850347485914337693, 223364064845089224, 7302899015436300563, 4391216311540396088}, + }, + { + {12558388403188680537, 10687978569513354810, 9373570856564649772, 4079327722512691465}, + {5372437374337150740, 3297421622932790851, 9326853593823854687, 8305371884938201251}, + }, + { + {13121472331750731303, 323745485980480220, 15110308702528119977, 4696302365805118372}, + {9859094500834571602, 5315656270700787939, 4187063204400651801, 1695695129564818327}, + }, + { + {12817586844019849804, 15425488216915741929, 15293562913126043054, 11770898970765978555}, + {6806103820345670787, 17789094149138630459, 3807781571713999192, 5823254011289457198}, + }, + { + {10112524230916015604, 13571143908656270599, 6031089010487808103, 5774558171390644848}, + {1808959243244841573, 14071312530426692155, 9241399242704553402, 9836150050655369231}, + }, + { + {14083007972403535491, 16009534514129505275, 12481249112231139039, 10309390659262581143}, + {5782517315325366794, 16717384553294759530, 4578392002424884134, 239005024949492645}, + }, + { + {1836857790164349346, 11263074778654917115, 4786985732596838094, 10525445084936097674}, + {1484357665966453236, 3110871407036679558, 1668700683093601768, 2736269131339849752}, + }, + { + {9249362594190920246, 8088172462140746331, 4080107866285682736, 16205599538438551353}, + {18312943145606312277, 9100632964181080418, 3969991115337154345, 5340098959750368315}, + }, + { + {12122448407048035645, 2891250339380982359, 12794212052932523400, 7166035112141500392}, + {15777441312724841162, 4552528682229856831, 2210391301762911476, 16410254680957321386}, + }, + { + {6910044784455706429, 11951245774670922855, 207795885948948810, 3884359690300962405}, + {4578772752480772344, 2948797025787714138, 16774444535658202808, 1388183483009000463}, + }, + { + {16561979129019905420, 1881862411760441386, 15441950514711322010, 12933020223458438856}, + {5570341451312029630, 18172638959728259059, 9074261777549091198, 6171200053222754816}, + }, + { + {10126435102176037237, 1545112930055760251, 11563139991870561593, 10766754172364938834}, + {5116781688621052838, 14471715119500781375, 4724882615229687192, 10031687030722046325}, + }, + { + {15016829467434780812, 6777508689306592732, 3811682306063049290, 11475361222871876387}, + {6080948654298953274, 11612742274762615033, 5268311600240325047, 9147351973710519861}, + }, + { + {12130203770930472759, 3880998309361490881, 8807462332494735511, 9291388074337055133}, + {18165312304248982432, 12733144434841535979, 18090195697688236271, 5825342884125782172}, + }, + }, + { + { + {194633990068625151, 1028128699653523895, 7436102537486268753, 1855520454959348468}, + {5098690958966904466, 3342676718901330604, 6942212660412942406, 16510188838209674083}, + }, + { + {7963995066277321795, 14986230345162551366, 10616366460602472778, 16186943329215681149}, + {9522855644164647723, 9858336437877021178, 16344942402271072884, 18027353494090590022}, + }, + { + {13392726161043192788, 7606793939450765773, 9543984695709321129, 6135912406103198328}, + {10903991926178685177, 529801710637680784, 8207012095420105234, 4590962949922268360}, + }, + { + {13175608910844763921, 11168387468381338510, 5555873864224342205, 17780559602571640345}, + {1582669533588472814, 8145133762789622706, 1625372887980692455, 4576809104068554285}, + }, + { + {17616803153811079355, 17809794753465712025, 10788493879428408032, 1263026253532745742}, + {331896291298606534, 13299145463579793142, 8951131463540898010, 11121758705853021600}, + }, + { + {17015522374255846157, 7155392284047197223, 1248775493117789546, 9199472299655737207}, + {13126885324657282947, 12092989376083683289, 2035698983314262432, 835441512024005104}, + }, + { + {12481871371020004325, 15786477648044981224, 2586272424816191689, 4208704695692543659}, + {16940467964964992440, 11207566805119564978, 2858987625603639630, 9561510646236248154}, + }, + { + {2900978533555060931, 1749946807863203576, 11705734511931072459, 4446980691693419424}, + {14437524160594907241, 12795912566640000773, 10400036254697939154, 8356113088668925361}, + }, + { + {3770654812111500682, 7723332701546321657, 12057007323752084660, 11871339027463593983}, + {8927366002257844381, 331175455338905356, 6085376066711046662, 195998713859126244}, + }, + { + {15888580251537997623, 14253909833728698978, 14445538492667230716, 4028538972354525849}, + {7720263170150940477, 1190890222876864097, 8657188516818851005, 1987613286973742753}, + }, + { + {1556082539082087499, 9191446579576007527, 16923484407567577707, 4662661048159090855}, + {12760778972220173745, 3942937056545553996, 12952479961991875179, 8914103212381870290}, + }, + { + {8900726473285671992, 890209742292473781, 16059468388719373167, 16577940938542233221}, + {17381766864962227733, 231915274132518769, 16477817024012878700, 15646021286310268545}, + }, + { + {10104554368814337641, 170400126349943750, 16051269335758964391, 7842493858299913771}, + {9246756702190574744, 110682656515867335, 11402798562961521905, 17325237240525801251}, + }, + { + {15837018286366797690, 18114413810565810328, 9441874034567150801, 14075941137889189393}, + {12786763055047269260, 9121030808281463204, 1713778999270814105, 17015261864438490667}, + }, + { + {12997570542605430113, 5500897611058123544, 4160129407772614089, 13768264346635084004}, + {6638654171187871203, 6080635069726153281, 2255431148803290413, 3789670411999607189}, + }, + }, + { + { + {1830819081327272165, 11951292080860646547, 18002500803418629938, 13317986695217403840}, + {5005574200470766330, 10138179785738652504, 1610518863105278224, 13309443265578956954}, + }, + { + {14192194428653714479, 11578618567931657764, 6032668189933768881, 15981535562386193924}, + {8925792218631314923, 9408714146004183681, 8859017894477140398, 1675606340537058506}, + }, + { + {3265119697568866078, 13753322853248061974, 15435163376825672274, 13646180516491714938}, + {15620545622955090250, 18241486585498394565, 459566729126467878, 9728217493753855944}, + }, + { + {9883406233903270985, 17184231210468300584, 5498903678702785900, 6903833261382863389}, + {11489138095102981636, 9021901931786177471, 3227433089132150317, 16639455550797627042}, + }, + { + {839045372102318861, 2032615141683118500, 1921816835840256924, 504869150737570005}, + {15932184001422473505, 7849475855313305697, 1189994394722618598, 9874798350548229684}, + }, + { + {4636201671610663345, 16662311204732135584, 12398897461787695675, 1355753199357412657}, + {14695655628527768564, 1692838776852698754, 7346906782826540912, 14869028424564984700}, + }, + { + {14240080119980315297, 4751983902385717684, 7941412103662252178, 4796803816695225123}, + {9327986654018000413, 15111345676387005726, 3582558555283734415, 11913156735178831102}, + }, + { + {12915868875134296756, 3071143582305760275, 10848717856747030010, 10973183887638314967}, + {5983269487036236823, 9885184706933333413, 14509493669845681951, 9669608065801379977}, + }, + { + {7848634325810890057, 4356492357483949442, 8777700982672429871, 447737364627887590}, + {2892466086138453900, 12013259293340538023, 3423275627272380730, 11171074631447548946}, + }, + { + {14593553227914306527, 7393098159726367793, 959457858782426605, 12924066827318848802}, + {14790800265003508462, 13805969419986022239, 4408523909823076864, 16722715416825698787}, + }, + { + {8554182115079118694, 17233907570567075631, 12336560627384786590, 5123566378696582545}, + {96401035522143140, 10138155491929979850, 17651328686428132420, 3453390145222258032}, + }, + { + {16197242500758474188, 3349369240724295499, 9422940308750670637, 16888844525585804807}, + {14045424784406071799, 13180603138700207746, 2683581192503868543, 3842875784859878}, + }, + { + {17498073686183419231, 6922314891526280784, 16083733402282932920, 15425477806093217459}, + {12425976625898608391, 16458101989314253841, 10013521940061058050, 10858868879196007236}, + }, + { + {123600201037598181, 6690762836954208162, 17157040810691942664, 15263405971805161132}, + {8685477170453562173, 10331174323986544033, 5789045082422148337, 3007978469441468974}, + }, + { + {2402095889286816125, 18054120920831753009, 11753130221915918396, 10341553510464463050}, + {280903370426929900, 14994955837151914025, 13551362401871479612, 14711789630561753093}, + }, + }, + { + { + {14086745261650819748, 17953107869776717888, 1777725846494438428, 2765314406831814212}, + {2603997194371852991, 2223517025105045134, 15579901335531749634, 6571733615332171148}, + }, + { + {5478465698516556930, 287443454357750768, 12201204663663129285, 782849770204658255}, + {11270045035009204251, 18152683972363144337, 10463300037926642739, 14363641589598863851}, + }, + { + {3790592075869665284, 5120320091554329756, 15361581282394028709, 14360464660911164915}, + {15249656958991931940, 2563751872827049233, 13745792006936646733, 14572943674933168173}, + }, + { + {3167679014977537749, 3417445004776702290, 1709246158507866266, 5861367897285174360}, + {8437429877561342262, 17231607446243478748, 16047596399306766948, 17656438585829685897}, + }, + { + {12977336347094692192, 13723871955002954132, 17399919575273038847, 16163973860244779675}, + {14997921584659740746, 6543247361992425067, 4675926398794487109, 17580512382853194054}, + }, + { + {10778828023580771765, 9812611440536367405, 14168149065325522570, 6692229110872358750}, + {11010962724400581057, 13055203605065073902, 11396463140731730116, 16969789651736772232}, + }, + { + {3285258013801327520, 14114268241282882888, 5367399533198476395, 17277410244918727028}, + {2751895479568588421, 751309667192066167, 13038472116718581917, 16013586354334596135}, + }, + { + {12364168614988940500, 13194367252463423118, 12223406606527741280, 5014139294736037086}, + {11244699482831816093, 5336498572491451990, 14268404582568856142, 14502318820969599316}, + }, + { + {13295673091232554814, 313981772853781347, 11829785736449464030, 13341198421333360997}, + {16787450350663111566, 6525407229623764159, 2012189087039636323, 2110887590404698758}, + }, + { + {16984895766311549717, 1057465499230843916, 13565444352859773343, 1019268943988786852}, + {2190009140530404855, 10045598732295352970, 4789803496780829836, 10700158388954091321}, + }, + { + {14840255112988420500, 10066628133368048408, 6527354835873855384, 16106607076894419125}, + {3989024604987083046, 10713316697020150694, 16811389107269552264, 11294596059797019619}, + }, + { + {622403023838932676, 11423409007234191765, 17086830255702454786, 1213655124481948199}, + {3976593910085142945, 6315875935390432543, 17947502153968859628, 18031540937011531543}, + }, + { + {342675887578148289, 18366454547938469828, 3853530442390999217, 7499455395579634652}, + {768597405171336502, 1636271570683567151, 16786205337983572309, 13056241332863199715}, + }, + { + {15991153618414855143, 803325462494472241, 5709347424437559249, 10138502962472290727}, + {4675124205115228106, 9599016746550345197, 2769443894695609085, 12311020551315051087}, + }, + { + {11470964304318784059, 17313372553735202469, 10686997186364536871, 9228453594798060121}, + {57933324335302024, 8931389936300346353, 17823596478938529898, 1126996688113949835}, + }, + }, + { + { + {15804957839814547154, 7924193945337173678, 1080401129055171214, 10816444561878528576}, + {13171610473229361771, 8099842733764406841, 9284741070210451667, 9245195215372025289}, + }, + { + {7185947197544988797, 13306809398790059447, 11440959253278285287, 15084384140482244570}, + {5059824327869316332, 7585354587200615362, 6801884469610571467, 6427162399794357267}, + }, + { + {1505501490785526604, 6062033360335279190, 13214531355927393851, 8869230490276248430}, + {11596558698255017116, 6698268011950867978, 15445165013361223076, 4910055064120213146}, + }, + { + {1453348772281274490, 13028088570940491471, 16100623112750251840, 5210244400259879874}, + {9443916155735416174, 16869520919318450506, 7479400208826706574, 14374970913352602458}, + }, + { + {13057495656815142976, 1743194961605203063, 15733599697884179267, 3501754291485677593}, + {7405256272105757266, 12344297842308545819, 3389605493339498760, 3092252531918600248}, + }, + { + {5038191990715247960, 2723916483244871576, 4891019526710760134, 11094632341133260369}, + {6274429941353136467, 1408871421293516065, 12455625869488488781, 3401549469990652817}, + }, + { + {4716563932720198201, 1584625214845878997, 13213357619008940082, 13122950207230795185}, + {12303370001794463898, 6725033180592084698, 12302152314224424594, 6139100303374835750}, + }, + { + {10149597276931117465, 5778043705364022356, 13888443605241209218, 6889225091714429810}, + {16209363638493043975, 8516350006446457646, 9214830076046105138, 8894115046323798175}, + }, + { + {161027176918876103, 2287100732338401479, 16561946444121779293, 9805329436091376243}, + {11473978632757961256, 1245289731366992705, 7338435771556366282, 15749864527919116005}, + }, + { + {2753237807828198865, 11508305846735597339, 9058745440380813449, 3960739040735759442}, + {17921955885187582871, 10231929062430218022, 18115018235326517243, 17854413167898372208}, + }, + { + {638684488109167329, 14596365931372343092, 1917271942976854297, 12291978018935761003}, + {5076527739384635812, 7833625460571766680, 17060902137821849350, 17134703695475138982}, + }, + { + {13026208197163596446, 1935567165776196957, 17296090833026336866, 8461284827078097590}, + {14545382879887213077, 3302103559307506085, 16026840048628844803, 4599071908983273604}, + }, + { + {9156540407095300222, 7598243263658987831, 1996711254516517688, 13013193687414837552}, + {116495354444693499, 12803585308662671588, 8278106437192580735, 3374263264867687146}, + }, + { + {4318910866113560561, 8122780372606489166, 11952351993471767425, 9581759925599323445}, + {12268585667545114307, 7286163136539353394, 12697490728074784421, 7270019569202782882}, + }, + { + {16247467139569457576, 14043942371464607677, 6338399572126720647, 9528527345786650933}, + {16344656963096275115, 13804658662065732334, 2991248997774547140, 12174436388699549119}, + }, + }, + { + { + {1169887957113173798, 4936710663791789838, 8029349457377894665, 3317691225106441967}, + {3622769674498678594, 1954144360900150482, 1432045977341997899, 934737636789214593}, + }, + { + {9646181593082190523, 16068017411165381498, 13319927590045936565, 6113055520205251774}, + {5576373032696512038, 13880344501714804196, 12022206929479211261, 7387979357081975315}, + }, + { + {13553890993911526641, 1237937561304731611, 11053651340854998814, 8737874920379363783}, + {15414508226001886918, 9311523317130687807, 12080742822716708234, 4715194040021784977}, + }, + { + {17182132836049601530, 1486820395924546410, 14089047182364760490, 5375431386740917568}, + {2352352269256972682, 6220398075470064021, 11444733678216077372, 8173002234516562536}, + }, + { + {7896339057146013415, 17613745684396593735, 4238258305077796259, 15438639564771394288}, + {1482402451684594916, 3104492350488980260, 5195487229736262641, 1361150797580203482}, + }, + { + {15949855327936545010, 15892613064802301412, 7776232754624386979, 2193423430757249310}, + {10751855334513902678, 13772090376350944100, 5644047706587449960, 370992037484721524}, + }, + { + {16329953561108738383, 14553061366216182492, 5112198484879130320, 1893048255589705004}, + {11469678860036344015, 8992526488267920066, 18208245559304821518, 8980963391041920447}, + }, + { + {5783711159088718530, 3503029393593618754, 10736192136662142256, 15443859608128978668}, + {271805305647187927, 8244170003029416464, 17017071503038388446, 2536084345379259313}, + }, + { + {9850291665987916519, 6499970366121170030, 7001995026899086280, 9961826319039756858}, + {7497823327397141096, 6975352931548332265, 4068344268340314997, 15888973419716629698}, + }, + { + {3982898776583485812, 10403233710814076420, 8681461491810344216, 4116685619183896910}, + {18192868132325233114, 17377077437999490605, 17997716263755054576, 10376686656480866118}, + }, + { + {3479412946560984795, 5044366097675527819, 13707564929638264911, 5666779920208401261}, + {10137470376683230183, 2075467328249870088, 11457126564907274413, 13701087332649256159}, + }, + { + {12574253652565934836, 8388159655344384255, 16127953452716629313, 1877819316325313228}, + {8945746653921217760, 4616678606113198065, 1336330019150074567, 11910289150769410280}, + }, + { + {9565592090082898867, 1968790057506790036, 4797721149040405609, 13125809848505545280}, + {14122665390767023537, 17271175538744290850, 16007653062195668190, 16371835205840876479}, + }, + { + {10409691258933377688, 13736467137095186370, 2757793467881882435, 12443439690522935631}, + {17601924849565694404, 988048065500720515, 7554063443268400107, 4274248596892038508}, + }, + { + {8972162505776549196, 16209364130421564220, 13018196697272262431, 418388148277092169}, + {11645493996879973039, 5024734975063482607, 3708889997144620499, 11208942121415360714}, + }, + }, + { + { + {17596113920958619489, 11920824479658301378, 3786905428099710821, 11112764289322906111}, + {8817260450068629272, 6518847791514184438, 14593687325057339783, 18018581321332807475}, + }, + { + {2056254186648603335, 12143016575009965669, 3290271983033386616, 4338404082685850854}, + {12660444972475266123, 6345409453044955404, 13278869140778657354, 10063005167581762786}, + }, + { + {5303950317664091150, 17409642188139937758, 12135894348302287058, 16444741243419918751}, + {13935885817311324323, 8496908197501732703, 12163317723288843510, 16891353436915314685}, + }, + { + {4168420842704770545, 338440394515115377, 2102734009665481092, 9772725684473416465}, + {1247616337419130000, 4222072446972129729, 4836898447189504007, 9154346000276664999}, + }, + { + {14649401370738987318, 10044081678892811795, 1306517740393103656, 16586067283450489622}, + {8211832777731897494, 12849393859171286949, 17327526552807783018, 14171704619529498238}, + }, + { + {12849053390245557890, 12693731077061619694, 5891211584023409476, 1008960642219209210}, + {15593393872187214387, 7381248773473326001, 16559656086795428559, 2106025108820858934}, + }, + { + {4347667984894353308, 2129883711661222690, 1076488804494872856, 15059968377755299195}, + {12380937310378496242, 16425480883270944108, 4769192332535557551, 10388305045430499744}, + }, + { + {8553482596123775980, 12627020622203381515, 10774788686070344669, 6271789114731522097}, + {6270586844349642345, 5584690155569770537, 9478526526319537174, 3405597782572827563}, + }, + { + {10255408065071335198, 2384996481315588922, 10679447117297819075, 3734157461055440416}, + {1635042286365643780, 11321809677772938996, 2373960964139986040, 4869129159740273704}, + }, + { + {16681657814739017038, 2045405432090866328, 9473434018957974472, 5549808619751464269}, + {3650191693776946828, 15805634549736708741, 16764187297356548667, 6849534466635874363}, + }, + { + {15295973549776084894, 8150873746601283651, 8017271980921908229, 4899654767305073834}, + {15257501950484641691, 17365331272978440066, 14582514748324426172, 14727798284858071666}, + }, + { + {3180828552573045472, 17698570278585440462, 8986722854533057232, 4518665117523514004}, + {1718699978312382231, 16973074530347269964, 5684175730451960274, 17228649521631238473}, + }, + { + {2897180423141326703, 13691273076814343144, 2967066815351306232, 1032540647518716635}, + {16365716239989474776, 9503666134295232767, 4599017511227366879, 14475021161770955579}, + }, + { + {4512626226592149712, 13575110216387069176, 13488662643497927183, 9673147324484250604}, + {143936220816719815, 2307325398241477161, 468315224038772027, 17743582630124600591}, + }, + { + {1476494936296433813, 3408612621327299295, 11632756669813257564, 14296719897220703576}, + {2241234207239321749, 12237974399755684219, 16253635131573079566, 11892871179872526079}, + }, + }, + { + { + {9440495138081785154, 17328162383695942099, 1870751290505230781, 17987066187778049275}, + {9952223038481207705, 10126409487298126876, 1181369784146909444, 8158422380540037915}, + }, + { + {10892870009313407934, 5709686117526627488, 16343828906887149047, 16063790174205876315}, + {9076070192754075075, 4639156357669822592, 4904064385440242264, 5942264027390072320}, + }, + { + {14586043427955633062, 1886633882927769308, 12786104261802569226, 17414735423561048102}, + {3869682486341171982, 17146691898427698057, 9886217016173201579, 17515773620461053745}, + }, + { + {17271984572727555145, 2097715321690717305, 5328035183708920909, 13206781766168781008}, + {5915693606819932446, 3870849056297265622, 18070792155150730518, 7786839743829304936}, + }, + { + {14091274565690260814, 5039742420071412611, 2322945829654574283, 7678395717670225646}, + {17396071770599775867, 4747582460834310767, 13387178106758137047, 7224458787360678986}, + }, + { + {2020583809775623843, 3803516109208330416, 10492323079463714031, 18244921722581618682}, + {6400055933742731191, 18370212581946723247, 11415812944884122048, 5987324147127294665}, + }, + { + {3106709870210381627, 3437108621064387068, 3265644153772373951, 14353255805499610949}, + {11329727508866046420, 5461257448868659690, 8139681370942905079, 8439558396411914298}, + }, + { + {7939886940063870939, 3597929036186322512, 12732772396498766041, 13300425267730247515}, + {2345112231224079293, 12327614629296314761, 17106102937162407683, 1702694317559034053}, + }, + { + {4276582831142955483, 1304336253044853784, 18317056640605949326, 11200473213973297420}, + {3937030502759894542, 2315314353886242360, 2673827662906962132, 9781744582918546067}, + }, + { + {17837268310687096164, 10122495457633601623, 11985150009870152981, 11282144500794610389}, + {13999168735732598559, 9030771445951876212, 6423904381826094276, 6148980837201061250}, + }, + { + {14621142736654260750, 1806201536162806753, 12562675185535659971, 5326177198980139868}, + {8675433132905478434, 10796034085894917871, 7562073626744691385, 1491977564717017512}, + }, + { + {8821632341545057929, 16708916351043551467, 9171560460858577216, 5711973041149612575}, + {15808302665077457285, 8412173943543358851, 12602476370021215716, 4778674887660148537}, + }, + { + {7524796586818405222, 5468491023058834244, 7965536127579551161, 9575670558568595724}, + {4020611179055350793, 186082735900253826, 11198349470461895384, 2693853052562145978}, + }, + { + {7977371007734934919, 1442746893361509157, 15080044066626816201, 9179319344686817504}, + {17927184654813605164, 16541635384799094673, 1663389722548868092, 9157422724003022421}, + }, + { + {4167146676307544690, 12042136744739037957, 6606952994938338836, 7554398412699794678}, + {11844277247778765775, 8165791089025933303, 14954338535964037723, 16693854111477654477}, + }, + }, + { + { + {5841260956815214452, 9461234662498869948, 4761949640006529525, 18229823346336752572}, + {16055957459773168413, 4272222475092786627, 18249888117586812770, 4531982814021269346}, + }, + { + {7270238601276019194, 7318279377964882079, 5226788506940171017, 16838449902078450273}, + {3375184937745100689, 16320655850583231520, 2173229791272659780, 9816381971766204380}, + }, + { + {17113448198982970082, 8879656883528014268, 15215762680430094206, 15232212751792759071}, + {13699137317730183483, 11815206710130297569, 12298409691055054593, 2192455093917691024}, + }, + { + {9742819322069712752, 8779224519997661749, 2591205872359340025, 9144644967919881415}, + {10495832103710459914, 4557264342687723360, 935865282128150338, 7120324256648044882}, + }, + { + {4683169301229531061, 14940390399739549639, 13128742567354398401, 15222231511210090535}, + {7352694898928671332, 1221555526903686446, 8697118143614336514, 14515400523185205597}, + }, + { + {10239864229747754958, 12477284975467600510, 14054830413782031834, 17752968481181892755}, + {16082713391521411762, 17191329716867535304, 11245514405315337909, 15159733745232554536}, + }, + { + {15444441705629456398, 12030687282161152512, 16500102437404896225, 11467410246278043769}, + {14031300093087427598, 14458597378298191386, 9434445586505481169, 18221119130471329822}, + }, + { + {12694666558858009121, 10992313774737315187, 6046508760845509477, 16818819584649823054}, + {10464090160691032219, 1221502600750419478, 8658907655588546849, 16110628890984509877}, + }, + { + {14304143349839262251, 13048055876309896774, 8676204847923624352, 8365498293767636038}, + {13565995665971214654, 10895028049457785231, 5911971723937387023, 8436244239466286317}, + }, + { + {11501032393232899227, 3895174794911924947, 3230698222875450976, 7264134402609589101}, + {18091100044992147344, 13252184705645692134, 8424205723200969631, 5731735154358029264}, + }, + { + {12163905774765001813, 3911227235818691672, 9833792088244333742, 6413344327541478453}, + {15325942369130325853, 12629318625161567307, 8784755949357111975, 9462269284575183222}, + }, + { + {2157617452419341992, 3753997642171159286, 6553292364671628995, 4814048166016850277}, + {6152139240994642263, 14066819599579263267, 7377541740373798192, 17830582976167057789}, + }, + { + {6906089045659836134, 17967958089618664024, 13353206790928340833, 14671934547763383296}, + {12187232481950713594, 8718528695481423527, 18137604428804898613, 17758096361511845106}, + }, + { + {17646581888040948752, 8252837592394234071, 2508742924483223473, 5332070238932154531}, + {13165985796861395246, 4409584176627274781, 9230253121183107430, 8784052955551358471}, + }, + { + {5394535031187713437, 5279515585052353937, 14159976884067043134, 10130852155763718010}, + {13777927158878861230, 14015445621678244733, 3350717438960860318, 7071836838770144750}, + }, + }, + { + { + {10708602749843635238, 8046488591192123621, 11391158257016334553, 2512908912806916201}, + {14760224624269838038, 2631910198880826809, 2387247811669872033, 2048193899742148806}, + }, + { + {17392983665205025720, 12603331233691760840, 3752711326309791976, 8281544857330094164}, + {17004651346561270106, 10399322540256775923, 9721299450284863176, 3725182263994944884}, + }, + { + {13643198694788276032, 8127425924819487897, 14165945065582850538, 16520977003164405917}, + {1941948502806705647, 12390949208067741787, 17112117376594486408, 10232906951259490042}, + }, + { + {74190110112564319, 11227229657066745164, 10151080599595091944, 16591051376074591375}, + {8256332495682655293, 7127985739945537626, 5708687346183367016, 18310921046455023281}, + }, + { + {10040565835468209502, 3986586816478505371, 7957179672896506016, 13347112914739722590}, + {14099734293320932556, 13921950344400895005, 17478414833301838037, 961445463330402797}, + }, + { + {10553899634420153414, 4215979268474142438, 3643081140297634139, 11620906704125380460}, + {17733628678553828301, 137473878710304143, 6211837577294956591, 13926110616399428016}, + }, + { + {15203257341351417031, 11597829209697937782, 17317571979811895272, 15929491640570317745}, + {5731227916276913121, 17093153916149088230, 3908757069480556294, 18211818355208735794}, + }, + { + {6887629766078662088, 15330755394432598442, 14144608177273202986, 13258654996547018856}, + {8975611270007504091, 16869834856279102361, 12707970875852047823, 8520055680055874514}, + }, + { + {1643407997152867899, 5400650551136488814, 14663391437159245064, 4743209938058826866}, + {1728998201888511561, 11238331920657195520, 11617984741897247805, 13858029141809651878}, + }, + { + {14003691155137683825, 14641672309228817657, 4031783205073356111, 7414359968614421153}, + {8166814052414482491, 5209260157266028169, 17555696996149558694, 9780166780476833956}, + }, + { + {16029688335186691281, 4244772808651443261, 6450459413414527821, 695875191412722741}, + {11104054226249884864, 146461617619843327, 17480214580411209436, 11285418463967817315}, + }, + { + {4922928863857449168, 7226901725606965824, 7568276305032368752, 6253457805758596797}, + {14345040877576203078, 1718759302498746946, 3544444746772280646, 17880302727399449566}, + }, + { + {10693864548794383214, 736148233485985101, 5241869061152863453, 7166954323782542739}, + {16861482585847848251, 11483636939866570861, 5950529069765100144, 700887039653157350}, + }, + { + {3906969739692830848, 5546431121705298614, 10491799900914853406, 5871175286230239238}, + {2851574662174517162, 5511397532379144624, 17409985391224790540, 319012646822749823}, + }, + { + {15269778527761027251, 16471737837294177924, 8830398856035267114, 8206807757132984992}, + {1421214226977370752, 14233751335943482739, 9668238787333455452, 8700964319357541954}, + }, + }, + { + { + {16477698187919702699, 2757160833848759781, 5976267476122243443, 7375951277779829055}, + {6525111513935493528, 9969722922172879681, 12582700753056539952, 3861958159147836631}, + }, + { + {6001837395299394988, 7545846298204709215, 6662102781970969966, 12696054550672669874}, + {7436995610194789060, 9042605089262227561, 11621508125069628605, 7289479057360149973}, + }, + { + {9447061002880879247, 14620964119546151815, 12310553083192998735, 15923694411935453454}, + {7392925129127637753, 14135139889986895975, 12760571438361221130, 17000514617803354735}, + }, + { + {15555649500689005370, 7857014165815014600, 4664069234996337119, 8058230521837307501}, + {18090421626009183450, 9278179697462444898, 17138879353097908770, 18285223269807746171}, + }, + { + {6099842409325199202, 2732701612070195412, 18229871238556385053, 10275023622778520796}, + {5986266691884320152, 9796109565274465130, 8132405984970989382, 4521405733027618902}, + }, + { + {7427469853953577123, 9581104712231034671, 1702722776800247878, 12656779221313783543}, + {17977155285174544822, 7208039998659519604, 16978428797146101290, 4487821481774245164}, + }, + { + {8040999562333134211, 6854344540855006667, 2481534773419348751, 15571316619985340537}, + {10089854957334316687, 4775911690791701632, 15619815835608539594, 336338508421162031}, + }, + { + {12741225973381753432, 5461579923265799106, 4348015554411389960, 14970536173310927872}, + {11568371199139699619, 11748662751675667230, 15495664823061891700, 670495577617908409}, + }, + { + {6065163107315563308, 10179715614080542168, 15046885616273736618, 3965401047645186422}, + {7013093813183571821, 6087826007582017410, 14469686436525543908, 9620661780899615891}, + }, + { + {4469547109588409455, 11124190799085603197, 7471495874998642156, 14754586999614006506}, + {88849924092797594, 3031352551776027825, 15701321561580429717, 783416358537121491}, + }, + { + {16899538363784443428, 1224176808212436099, 8044883358999763192, 8119246882922976226}, + {1602185320898819533, 7795133078900055750, 15379182653822915088, 11717676755990779936}, + }, + { + {9865772269601493999, 7325690007062740244, 18437964667185475354, 9546360111100619473}, + {6266116854923135821, 295905071295541234, 16037468634731642095, 16602609756229843150}, + }, + { + {9871952371310035629, 16929106233175362415, 3445554197529258762, 1598752868683659684}, + {10123732080482057842, 2393692486932623922, 2380673894473467164, 14578017559552626408}, + }, + { + {16688239163561330036, 11170579336923472003, 3699145675255553709, 3266133724446548264}, + {13646430870088709566, 9802235972068927845, 4016187574117121322, 8646347483626678378}, + }, + { + {3473609455134319994, 8666646689587058890, 10588670228528079578, 1636194164122827747}, + {10443498896203771168, 1711092164750178258, 3641509682909832777, 11037852869436666140}, + }, + }, + { + { + {15254713655124736464, 6283719686609422435, 5417864180357938798, 14010638809605797246}, + {10873690600705871523, 15014239467130590294, 15765460219545280655, 6048061577845125750}, + }, + { + {12012729503226546642, 4811951115754240681, 2652621264600062520, 1108958391967017223}, + {2508980100759035797, 9023233544151778447, 11183557587641545146, 10726727280840759519}, + }, + { + {396296174223428093, 16763788748988621834, 10606803701784640909, 2399987183687936561}, + {3641562114746393614, 8536687357022564742, 14532545286961725758, 14658331097531946901}, + }, + { + {2386026063595321071, 9144724461940169335, 13121187420621518554, 17351696676224980491}, + {143495028693925520, 4590642171152119027, 8655406817079059692, 10005507077955932112}, + }, + { + {2047964090310465728, 14133690277069748515, 8287749071957055844, 16821270580974431218}, + {10324684883587585565, 9652498187344172497, 2461802306013063247, 15048850312040680643}, + }, + { + {105705035058376953, 7541598459498134635, 6627685529861836787, 5724525771392188178}, + {13865897118300842617, 627652561624109853, 167084371112939132, 14192831153344015422}, + }, + { + {12837696619944805389, 13470316523008526719, 3074966674353053986, 2630814767089382743}, + {13353767941686870870, 11405513520090968568, 3071969598389884693, 8212421686942839224}, + }, + { + {3464453985305889088, 7486900500389940957, 8944303108517222303, 18319933556403836918}, + {6782476025105836770, 12822840946923377510, 2799592944286097404, 8737598030273298051}, + }, + { + {170025682710985810, 13049055489275530431, 1714038719952287416, 8470425667049459662}, + {15692449588624337561, 6306908925988159475, 7292362624201217567, 10084542069209889549}, + }, + { + {5788423445465760069, 7489854375947810149, 2512436350424132958, 18422682564857699600}, + {5177251288327577128, 13879051611542381588, 12430182880452441435, 16367520376757404605}, + }, + { + {1828702178325893477, 504110179554648546, 13285173922848349127, 15811513724231368560}, + {5009291056218383875, 12726125712718222937, 2511326207435121241, 4878070763721166868}, + }, + { + {3151967592390934907, 8745573685636820318, 6591530195811780291, 2269684725432150574}, + {7575618284647930930, 14430170051221190457, 17370623489799706048, 17190167628015666439}, + }, + { + {13971505255871035961, 14447456703883945351, 7749508685925819836, 12281701633335081378}, + {4638096293890044597, 16388439049639616700, 2805317369196495081, 5611057071508020450}, + }, + { + {3416635149605340108, 10996030428276056653, 14121021550848949146, 17748729969482499931}, + {12079053778595035959, 7473419378019222577, 1862205264236631673, 13655366704192015583}, + }, + { + {4817911180954611512, 14468615228783100826, 5900448495927012352, 2522071476550218088}, + {15649024877429766334, 3445298745493942789, 2295617386899137580, 18376023059372246253}, + }, + }, + { + { + {5228416958727036186, 12534300056259911378, 6859045937063682340, 16561718753727911412}, + {9427589074776024847, 4167904055656501509, 10156691045253563236, 17557096561606923049}, + }, + { + {12847261474293104380, 15935635664155479706, 11956861064550631146, 11743590506948225647}, + {15973092866215748716, 8269726904881958353, 15639962392523441528, 15171417818360069012}, + }, + { + {2605212343977737441, 18393471024186189813, 2302707671753008158, 8606549841034095192}, + {3842822953634987820, 3094721493917442423, 6408313759447502937, 13486364200254727287}, + }, + { + {2191808101092881088, 128992526124656216, 738676021426139131, 10157323147642681558}, + {11221959943853120586, 18255489816550713347, 10885231659068427649, 12104397395119665023}, + }, + { + {7707807226411417919, 16609863548699265350, 17639371636697428128, 8755472387723764172}, + {164779854477783265, 9714199241756765614, 3491355372893948450, 17683742455036967163}, + }, + { + {13595758632462338296, 14515163666150177917, 6720823780841221770, 15071435664343609336}, + {9016075014492765983, 16881277609836316886, 6969993988115170067, 15419704786434737070}, + }, + { + {14933348768149415725, 8499210770493553168, 6778840616148281272, 13282837866452012488}, + {12007326272174861053, 11172739862019218274, 15202495365302649711, 8797477675597086120}, + }, + { + {17862558746132168231, 4941846130090682869, 17131557654945008226, 5312800819142473968}, + {5818269467205924209, 13458582047859447022, 2683428091382447153, 12956887954464730664}, + }, + { + {11820752998821943867, 5623379642132478491, 11666807493120740820, 7241997274572162616}, + {17165010508995490690, 1769225877906480182, 3814296306467163522, 1913823003062817434}, + }, + { + {11936813336110488997, 3878433838529606580, 6540053284493149566, 10610279324743393563}, + {14079852809920102066, 9176732841330794388, 14287311909822853963, 7146204303626670196}, + }, + { + {1222343790928490335, 2199405396044383670, 14080919887213592148, 7341303626667347624}, + {11784881532696657518, 17307742911086150556, 6036132721599132043, 12167106497065306941}, + }, + { + {13817073203406999359, 7220729284169210756, 14908407498603601482, 13536224989620701632}, + {1615171540711527931, 2063856048260214664, 10622581435417474559, 16378505765730768032}, + }, + { + {6855676470217754770, 9517149712286624325, 11080380031068971680, 667425509348698033}, + {6136243307299269825, 5326577850303193160, 16120190278345757447, 1982981965726975383}, + }, + { + {15399454106099176868, 3988744407816581672, 3596277710300384050, 15129113714633923498}, + {1554582462382333698, 3164553872715651710, 12729140363982748426, 16366728035709811784}, + }, + { + {11647936211409428873, 14704462653811533865, 10005129575282387925, 1526194796943187368}, + {10906326807488904308, 18256878690674435807, 13093574545395154003, 12352810226542367406}, + }, + }, + { + { + {17055119974261943875, 6266720893662254540, 13102139953381148874, 5249314164321788611}, + {7157525732140787612, 15381277459195914226, 17265025258266710353, 17573500432599548120}, + }, + { + {940679263188661008, 14653357165718140350, 15439920797347843673, 9415587255510557494}, + {18115037054677722678, 8165849408798239027, 17369387099667572407, 17619066457126678815}, + }, + { + {8649149223282317557, 7756351751136698462, 18239772072009739451, 9817506578949224559}, + {18378033667730800420, 16794121140066562876, 5288247581483071333, 12402303517382928119}, + }, + { + {11047138821675365077, 8918121441180891972, 26692501222219426, 15248413052700323978}, + {7305399157133896461, 7065644238942265367, 3949166834387057064, 14178248206708015607}, + }, + { + {2031270890855333638, 16982096442429440651, 16686304398848635900, 5829842366016448839}, + {14111080098472974183, 12565301877743332219, 1685254887702201709, 10638099573980009130}, + }, + { + {9618597135962048429, 4323708363301758294, 1934098864729515110, 12038442338797726450}, + {8373847126955513333, 3300151407444969023, 15888126952439796914, 1426880256839266097}, + }, + { + {6428576619669681259, 7657770350257045071, 17839413659396163406, 4702043961312931605}, + {8200928556018997183, 13282376860743810804, 13005614455417667639, 17419029631791664639}, + }, + { + {69860179712677448, 15464996655458230480, 15095351218136595554, 3792171085643513009}, + {3187131848664503636, 12713332789590787064, 6278731049699775392, 1597379696359884724}, + }, + { + {15673011075664376010, 15519225812231888543, 1336371877669824820, 4354970830277120843}, + {8744720488959125220, 17541792919601146935, 14299260104084112815, 16082554294713598652}, + }, + { + {13540612390708052286, 10213354985487483900, 11366371415587713866, 10334937577432263044}, + {13368390835254255145, 13453645319717588760, 6303196127329783110, 1204334422768264234}, + }, + { + {18221540219239501535, 8536815826205784644, 17328509446048600304, 13923028809228258331}, + {13984621134784540482, 10254983270679630247, 17457131706329229663, 927850905006752032}, + }, + { + {3952205381894147962, 11371446109407143937, 7231851263356642380, 11612512368538303138}, + {5227214975837085115, 10737565048439707166, 6333629542995218640, 12386725921557807638}, + }, + { + {3772067962000745672, 4436468403847408320, 10612599615182677580, 13738755391074136269}, + {13665557786177426407, 14568219921857752, 2691062926825113708, 14666515738377567975}, + }, + { + {5392936538333570234, 10526292103645946001, 14132494129869423619, 7207059073717065545}, + {283545293669631007, 15845011600683983526, 5081287846871250008, 17931854980704528162}, + }, + { + {8364400939527235175, 7959571573625351093, 15849019287994534535, 6982609389731776566}, + {6287382484291579264, 16496145344132275167, 12062306229709713775, 312030175316686885}, + }, + }, + { + { + {17224650011872599657, 11430188086182976152, 12892063618843720029, 5912993124689510433}, + {7069617917494051681, 1298012103142698333, 7943359430865057535, 9329776843721719539}, + }, + { + {9464085603669036454, 7848014338005901108, 2368914226155404065, 11578416111848517850}, + {6323647866244499941, 14399589996703947996, 2824522520842155768, 391310842153371124}, + }, + { + {9948650801233133770, 5836115460383443197, 11404170696974449207, 4791020823967734476}, + {423024247809958592, 11251668387880260801, 5562546584223492723, 578572156618131794}, + }, + { + {13988854693674964723, 10817154032069031941, 3171651998645961547, 5518712225783687705}, + {14706905091132091970, 13960758460934966876, 12141035142079693145, 3149939820435101269}, + }, + { + {2505301881938098126, 9962323478923652140, 9312199523950444342, 12957822502673689705}, + {8060810607849163143, 737408553843844193, 8143568733429881786, 18003168270780769476}, + }, + { + {4460927228453411137, 16058422703785787527, 8016770980039986075, 11450941100964860520}, + {2742597710491507274, 16940752978671801273, 5897441526901650840, 5926672707007682446}, + }, + { + {5772778048593061508, 15424756817708323928, 11842041259277183807, 17669952685051160523}, + {5405007811515938363, 4415223809135251038, 2223192286456742546, 15742105795795272774}, + }, + { + {11809342655313500273, 16822704101813284237, 13097372075606737923, 5463281428453250615}, + {11967866991673525562, 6828790575157689223, 12568831962097805646, 8385980093725157349}, + }, + { + {8090324765778815982, 15997433100218204643, 7771766025433829989, 914551143312324786}, + {4640358803642182649, 17428148208737756210, 12144967737399770998, 15075125743380741412}, + }, + { + {5954807828598238451, 3186352433639831389, 333598278340882889, 8647732331490039308}, + {3706589107409903019, 7338319463305947507, 3829684452513478938, 8551967121356509963}, + }, + { + {16753777599759754869, 12028154198579512953, 7911616552276519044, 789841268294170739}, + {8228995103825761982, 14293958931719060336, 2778055819582565008, 1399082948378499882}, + }, + { + {12492565198527218900, 17337285577296730202, 15088344513573802417, 4272568906387671217}, + {2365541522321646412, 678395397666822608, 437334842774934301, 13443327606166079837}, + }, + { + {1266313952277763194, 11470850617813390661, 10426389264474337810, 2996447663006153747}, + {15218295359022152122, 14634539952819815592, 1775270187047190460, 2942637199921677956}, + }, + { + {4952377176677649521, 7473631065005310719, 7363684030854414233, 12556891399998587233}, + {2190850394642244911, 5458637782288631421, 270926994697866523, 5528436328062366401}, + }, + { + {9497175173535366966, 25345745857275253, 5047829133239508177, 5340238103822773099}, + {3133339556064328840, 666970525709876149, 15575505473500291502, 12769675806855640654}, + }, + }, + { + { + {7669790431656261769, 2776517632462593286, 11694025667665633506, 9533794089008895277}, + {2895611631120558023, 11551410655448788956, 10026541900772270925, 6243136875017000843}, + }, + { + {9434484992529186384, 16435748047660609525, 16190660694150989986, 7083965852434071085}, + {4216306437741910756, 2698742177539497614, 5199793642504009017, 17298424769819019160}, + }, + { + {4041169394784902550, 5699517344009382913, 5306272267462320559, 15846674482556330025}, + {2606351264228884283, 4162585980422107281, 3715151019132039005, 6607223447043258693}, + }, + { + {8168579295855409503, 16727569921530031841, 6182114460261837773, 8940603165471931374}, + {6081572078077526926, 5890840443923124563, 11215305828294759727, 2875117534361804712}, + }, + { + {9045974983664041829, 905036705033699463, 6962033946652121779, 3027264198782618401}, + {13786415307358010100, 3643342525745067473, 13641958783381681886, 15675065537779359584}, + }, + { + {7507377696839752642, 1061259379811757443, 10276590160392917813, 6889137095037822679}, + {16373913505782725550, 12287733095803524526, 5695917172259210496, 6360958736925918808}, + }, + { + {7459854586357006968, 702429387211615855, 8231296036461604410, 628323703857882004}, + {1059802628602873385, 12517208225099517507, 2368172548334856593, 4792344750094708709}, + }, + { + {18352334786472886037, 7096021570596476676, 17045407505128867173, 2467670847537319400}, + {2225663888244226889, 1876713214939672742, 5329943993157142620, 12168650975912182188}, + }, + { + {6639850268372381409, 2284514769224558945, 15390110317831975716, 13933785559694229008}, + {12787641603764341997, 793886210532292741, 3222136169196008839, 11104892506868626444}, + }, + { + {12660547967989039787, 2109392063597767300, 9889743271997754037, 11803327596624324036}, + {6940409327849314286, 1466399127363116843, 2572333022681966275, 4216097356402537802}, + }, + { + {16858757460581672909, 5838407119753001493, 4453405435911954669, 2828665451507432751}, + {13657966632733241760, 6875986784381874300, 2390233934255482553, 17386653779125555159}, + }, + { + {2976756344404126744, 17032556609402836559, 16348907464011574182, 2196781021202618892}, + {8270822867494340805, 4738372358350764889, 6088256422707334932, 17121369334507507505}, + }, + { + {2081729301541563384, 5577186154173396778, 1865152567701500436, 1422284589642218069}, + {2489023909725140903, 276494395149046869, 17420927169263487236, 8292343688801608074}, + }, + { + {7819174654675104600, 12778055482430336726, 14615848543490171611, 17498415175263742825}, + {4785899184222234034, 5227136636239697699, 1570704808469050246, 2858953380860123257}, + }, + { + {4323577007857413306, 10524228743339400397, 5418808897687027557, 5939367271366264075}, + {3569359126353670574, 12961495213964770607, 8906990808988099905, 261084295374207271}, + }, + }, + { + { + {14408045416865494124, 2442199381796557002, 10475326303775862953, 13637445125954159957}, + {3778313603630758744, 9247460369874272772, 17572237597883145087, 11338350096360776602}, + }, + { + {4336697789732072031, 16054848662858822197, 17934449813415035557, 14518380622432694666}, + {14100582434152190048, 6262866632984449325, 18069160441815400774, 9798342103009260692}, + }, + { + {17244020587062193870, 7625407515295016845, 12692919397126044801, 739129074276464779}, + {977900962655641355, 1516169712468716336, 16875961107875019625, 1582931498538195018}, + }, + { + {687104890149081183, 1938816743979859301, 11342071981175913904, 4270322127259097184}, + {4964776270155503160, 17849333582861534767, 15814479527332819692, 8083943565773123408}, + }, + { + {7977186743666958490, 3126199553548085949, 16879636338977836444, 16647578924708995556}, + {5526017172393528596, 11328754652335568585, 8095074058116436597, 14648690727521713743}, + }, + { + {18335678403814425235, 13764304056086998207, 18139296224460762074, 17620705673387523052}, + {16059975647897396183, 14392541906869470064, 13641721532745636092, 6122032872822720831}, + }, + { + {13983401929934353021, 13860725962778449344, 11760533704789481157, 12566657951327299627}, + {14697122142882732522, 1606632877136342124, 7872716135734366961, 18220536079227927821}, + }, + { + {3986890035154628803, 15316660330065019741, 11560940574529263780, 12576851520091035878}, + {10883944418224886092, 9908329441525486205, 11238684990962507809, 12900626758810151662}, + }, + { + {2629393050548942288, 6363222898077806203, 18404650886731368903, 2691451856029551156}, + {5104932743043229112, 1302939624985069019, 11820239270922660661, 16228045717328023331}, + }, + { + {778457530134061801, 4290661013056586404, 12033745869654330486, 17833837257536520292}, + {950548111600899172, 16026254932420015523, 14620989142158250051, 8236598933984161995}, + }, + { + {8828068000936861634, 10901971915827198521, 15635295283164640480, 352740455954411610}, + {4853015383138960329, 2945696874639059776, 7204307993540375148, 11980890732241054979}, + }, + { + {4077800412543228484, 7173833470188867493, 4604439809988262876, 8090706047559948234}, + {6117166546062912279, 15748537214854486946, 16719594636199001564, 563850925691991999}, + }, + { + {4802884399593912281, 13437020732272033050, 12197788481695720547, 2162699662292229581}, + {4193517889478995518, 8610646873096992408, 9485787089338760040, 12392145097158647056}, + }, + { + {18079795516810465755, 15723042000668265475, 12488322519570427659, 14012836221417650412}, + {6534900133691249330, 8115921632235353076, 4093907116172233459, 16784728000548766561}, + }, + { + {6262200118048820167, 12719453838344002789, 5526427573572313315, 8520226123932607126}, + {3618116539863181413, 14020033065434801713, 15675496263723836857, 11987954535452978647}, + }, + }, + { + { + {10847249691051757241, 13332329214721571156, 12457628412284474075, 17044657510482764070}, + {5218221397478351943, 6922630493693541156, 6207927102810766143, 5644846665334649748}, + }, + { + {6506371904134856034, 9541373683805144018, 3149037850125132851, 7111810601994573897}, + {16732445693192247884, 4994069681898274622, 7223719243730104348, 5649174084086150712}, + }, + { + {16562962997045986629, 1977585352264948582, 15588655103333244279, 253344970359156714}, + {12939363813291366775, 12548224526376199974, 14450582788883748364, 5869541533939881460}, + }, + { + {13970586842647892965, 3680317572634289692, 3416494470839852757, 8341497967750607131}, + {5522860734580749818, 6847292760525096386, 9317394708872196559, 8522252330730808934}, + }, + { + {6838341670149165895, 12326189699069923388, 9258908232339348843, 17297038041466207989}, + {5242182985453021593, 9648294165629935142, 9715128265517308395, 2662662536493743894}, + }, + { + {6790869670806738567, 4499989093713728199, 17496748050437205626, 7194829324969293638}, + {18432532588985091708, 12041300075343806904, 7788543067151959941, 13703334460383638224}, + }, + { + {5996381448168274884, 8108757135223610234, 8067369725584584297, 7184925262427750366}, + {8199341143188441284, 13031376443169557016, 16036606349050125404, 11958720833222295864}, + }, + { + {9293668142017263584, 17134656749295164870, 5879480323258506465, 4788695233340705697}, + {17809277710857366810, 15157733645094688870, 14143869691462709080, 3162286338158090229}, + }, + { + {16056959590901591813, 1082823161154599460, 10221040439441372421, 18283403891485112294}, + {17582486701671091218, 6489397700174053547, 3952499348250646760, 4381145145005361247}, + }, + { + {464321249842430028, 11444362575253049653, 2734975360475017776, 4746579078625212558}, + {11326126526565916100, 7840007639237722362, 7545779893877671555, 8952053274372957788}, + }, + { + {9171324502111757965, 11245577625425383295, 15294815109909975990, 12306264653913762086}, + {5906268309303228662, 2685370982867857233, 5470203265560800284, 1354105134944127233}, + }, + { + {10610818607308010986, 1017341076592473937, 13259969743043862138, 1850907007366751943}, + {7689302552902672401, 15375957693502270090, 13877050204486881614, 16441247744335371320}, + }, + { + {18161720198110725057, 14887135440336057963, 6790952723850964648, 15120775513153544155}, + {11797493458812299470, 9090758778610315656, 605835259544633945, 14755333155432393992}, + }, + { + {14967102006962978091, 4301508725220174920, 11299977101982031802, 14410789725331022027}, + {17005709003661351591, 9843840931527318478, 11917612896070173894, 12007179364072802553}, + }, + { + {15913542135925395264, 2830138374220921671, 6395020779026969444, 1239443258852925290}, + {4519359001030231260, 9606729174209623750, 14291346135557028396, 16179513817501558495}, + }, + }, + { + { + {10223936123327786454, 2321887803300626936, 13607747528117965743, 10456421630388400123}, + {3266519591187534953, 1053691207967834494, 7151443045753788549, 18124688636664828399}, + }, + { + {6946488664257064464, 9775328903143754150, 58700362449753229, 7901817271072273406}, + {5074738678159003249, 18397239731906005785, 15911102965988125888, 9277654580204145348}, + }, + { + {1874700306906525099, 7337351570334852732, 7954195906114335343, 17230226427261850070}, + {5181329498860909261, 107167242193237170, 4364856176182710332, 14611171841443342914}, + }, + { + {10990327814895720476, 16588412771027628390, 2850177278998422188, 11569813740328484871}, + {3922148781422941186, 3581659216490446242, 3646872304052351376, 10887870617200051198}, + }, + { + {8175121141368087217, 15079393830876652065, 16766987879267543828, 10582796406546815217}, + {16832256009371376870, 10042650470778064892, 17867163453935683780, 7123418345572641116}, + }, + { + {1782651072016504775, 11033882508408412333, 11105300284232190625, 3276372405089292929}, + {6399472468041061588, 15319690780388315076, 4928530863063375966, 11596222198340277418}, + }, + { + {5452424185619067445, 12050433097586021281, 15018766900844679217, 273234254926088220}, + {15426383635547379531, 5213762666043737626, 2829185842069118470, 3230799283770935127}, + }, + { + {280030342772428106, 17354882606189694746, 17455445295460080284, 18076709382926018941}, + {9895982528034548913, 13681172423928175330, 1656433131309057012, 11935757350437721114}, + }, + { + {14437472586336929440, 17387041914242263390, 14861577074379746687, 5146556788377906297}, + {13036814755814090195, 15108836859245573802, 1667563994642521213, 14722845469958372258}, + }, + { + {7781061995240980266, 2066078418484154391, 4089376589847114892, 2434843609506038666}, + {18376509832460312721, 7187709121160627756, 2455436656049651823, 14419116837518875372}, + }, + { + {1270185079976403265, 9214436628411717184, 15450450827683432913, 2880014804806096082}, + {15448799931519826757, 10080240282127928735, 10673974088219619287, 12998944469117087518}, + }, + { + {18028691745165748687, 8931519595829275195, 18379893031942930865, 12120980098075498008}, + {9596371470855895261, 4133427878071274570, 13159312399982591699, 1639865074052258019}, + }, + { + {1661696187746428348, 2656198437014978712, 13769477291975851694, 12512848714492869444}, + {5980926616932344693, 15821983893144953005, 5816015630031200526, 15887565799959254415}, + }, + { + {16463929919291729278, 14920112063826664828, 10056471508435050704, 10696267144984026763}, + {12049530292963090991, 11926086636123189182, 9464890378472966538, 9719194510330239601}, + }, + { + {18110249193861022779, 5612784685592189906, 11360454032996393150, 6795401682138043705}, + {1961398978248902107, 8999847457729547905, 8941741619641401180, 6086938661427918241}, + }, + }, + { + { + {1119490156854665483, 16772836556735128526, 8607715508817325509, 9931017263385440911}, + {8799481055779587022, 11740562709785257943, 1956849872282864970, 595288629437737005}, + }, + { + {11601570184515356415, 11247678357869162156, 8415095559389686315, 9625816053586466047}, + {11807876143163335372, 15690209134241397733, 8684637224468015605, 15974968144193406020}, + }, + { + {6498861108824484382, 4670555282769381189, 6606014320886832914, 17078765892830617318}, + {546267528591230105, 17808649363082080722, 3219358059129920687, 9180845247506322192}, + }, + { + {11275984449259340674, 14922638629881602958, 17186426309348732477, 2094500549052461127}, + {1245672419927595636, 7529921141299797945, 3181089597449057707, 7749529014968942143}, + }, + { + {11277133910568934671, 4278895672933635880, 5062049475469993812, 2827897582327968966}, + {2992831031801695571, 13244636528396736375, 11509629662092358067, 9385849226639579800}, + }, + { + {8454236707620433029, 10192313737667573051, 18232259474515025711, 6196538652828521245}, + {6326999652188467228, 7611130140249634596, 5729331023083628955, 9386297316005425714}, + }, + { + {7621274909358193632, 3619625095597194913, 18038386254997645285, 17262892689028255302}, + {17953989125460428814, 4571031913557658215, 12218524221515562809, 12016327352942264220}, + }, + { + {12842581296013847382, 7845624487558348664, 8747439372999364825, 849305823897878133}, + {2217292264321907974, 8173534404179332054, 3588643190593022889, 12047811416592660080}, + }, + { + {8121746263843271081, 10363835147942471345, 312023379108980148, 17191823034761670562}, + {315776409136454719, 8322002171533871918, 659256727451485128, 6073539214057006838}, + }, + { + {5999134638957620752, 14196265207258829507, 5400793612736232063, 16259338359738368573}, + {11179852704740695306, 3486799782309774463, 3060529319750906379, 3540275797284687957}, + }, + { + {5485176043812882513, 10727553589889164848, 5617457077214333092, 15937493816713568462}, + {6287330459840726949, 5451240171054977850, 3524414944972920777, 8740440597273129486}, + }, + { + {6959527445237219799, 17170778245769606301, 807762173031474321, 9151445233487017286}, + {15103411489939446333, 7976669669591851659, 14824323986579638641, 1535817133122800221}, + }, + { + {13993486080187419934, 14882121651768660644, 7947881871819932407, 1364312030151957949}, + {10673187305202558690, 15038997055055408315, 9268330880459316485, 4319340556575124142}, + }, + { + {12846922591360496097, 15518450931549829779, 3843880753372237176, 11741559986398913430}, + {16974382348775305594, 7085384294841794242, 10278478682851578175, 16997904984485898637}, + }, + { + {13670930062027115328, 9912297966339314023, 17061419147322177635, 6220676237879734303}, + {12723388668517709225, 14967294924815531226, 7286002704046609276, 2105494380036834916}, + }, + }, + { + { + {17955247196574331290, 285928599571507431, 11902987704297070981, 2841167725097799100}, + {9281167410796848363, 16444340476026142274, 3423202423051178709, 9101021305726472246}, + }, + { + {8869273893561412239, 10349812081309865197, 8913824872487209090, 3148808685596180274}, + {530908416884501807, 10284103744075805979, 13606889938905754722, 2418062398586758364}, + }, + { + {2298603653884322501, 601221199968240092, 1285112712738261659, 13882709760355308533}, + {13563254433762438170, 13447718334658435053, 13493687958886238103, 11032778298151679283}, + }, + { + {8626760324117733843, 16403951745962159364, 5837394731212322914, 6847167719031297053}, + {2888142337636247281, 3409818743436360750, 1677113113408664401, 1222157560539217476}, + }, + { + {2294668553308381923, 17165287249067859297, 9897724011823072967, 17409851874231284314}, + {13888575318617508639, 12092766090379658603, 8412268183255186961, 8046572777745318483}, + }, + { + {13178439025428734594, 16388038968589028071, 16165750006742628176, 17903639397633243161}, + {9560319088110737392, 7888974492854359310, 16116323630343158496, 10177829649622711030}, + }, + { + {2378363646789710539, 494954399989334038, 6915496914984330558, 757197055392642378}, + {9097171378505823650, 12104288338329241488, 1905673690814481722, 13011078677095066032}, + }, + { + {12712274459771886808, 15748114764509451764, 1994630377849062253, 564390855806287868}, + {135493276425567450, 4305883520257541088, 4842008929542073044, 7035106970720249617}, + }, + { + {4772079965696324995, 15925041062593990538, 2818172089014580505, 11304215074611546986}, + {10130691823118346040, 11796228810049908587, 9262801389703476249, 6629344122525229781}, + }, + { + {11045983914861167112, 14106148195606833916, 4442596873181225087, 15627975325288846806}, + {8173496855557146242, 6061080385918934423, 5233260187121969538, 17554093556474728494}, + }, + { + {12122792368758575262, 810814789452398299, 6387727669765211854, 3304731719391402237}, + {15296845834923103160, 3685348582131767195, 12636335057478947340, 16971253767099552987}, + }, + { + {12345454807632743424, 11546569651702761483, 8873100774001529421, 7001975923028025552}, + {8129283832066039281, 18147888225504425296, 3510907297028745651, 897602195837260824}, + }, + { + {17896345382362222994, 2167374959533815311, 5029128091600127895, 1770543276160593316}, + {17234124146043512942, 5338191548265818047, 15676046602975694398, 1943153641089805200}, + }, + { + {11084819495273800718, 12966507689731825252, 15026437832429189138, 2506312683689776139}, + {7417463323869895004, 9819555221238697390, 1250200244896601539, 1394555910521460172}, + }, + { + {2221512141494043286, 9203854585477888176, 12171379127551511504, 10667358469120985695}, + {3795093165005123272, 6129005969593025264, 8738204659003189419, 5273583671698415302}, + }, + }, + { + { + {16549155412115374305, 75977962737081600, 8870825488941031605, 7403557657089993256}, + {5825394234709429518, 11978746413791918409, 1876293130790608838, 9416631623519692610}, + }, + { + {12346821858361333862, 6352722970730511156, 9920942104315084988, 10492373916708072181}, + {11163323626947992791, 17035282992056675772, 835685192553490421, 12792459312570503983}, + }, + { + {10447922451077327640, 1515090998837129975, 13498807582085718212, 1212623301098019779}, + {11573518650162536086, 4823461685803772444, 7289704908733783271, 13167881392748327839}, + }, + { + {16959954449957105311, 11051594981465026138, 16062472412226411858, 1976004115345602080}, + {3630495248560019222, 12698191555196404138, 10107923614229901155, 1597725222698864118}, + }, + { + {3416019089997140849, 3011417601086561495, 6275242351124667286, 14197557183081060761}, + {5633711018871057458, 9723496411345030748, 13910057756335530832, 7285051335492395815}, + }, + { + {16774605620279328247, 10223834398868957807, 15781733027568799739, 2607095622729296315}, + {16499590296954181006, 7576646116121533069, 16638313875339315529, 14296194207652471696}, + }, + { + {12874411821611501068, 1998417862388106640, 13882642435422318946, 5791129521978463837}, + {7512934139125398199, 6966283273373526248, 5475728301311080129, 13542211842758381589}, + }, + { + {7798993150530415596, 3288770257171840452, 13373286069558329631, 9784279046496345014}, + {15725032660238528813, 16038931923358478835, 6921788930154218900, 6093507035435214187}, + }, + { + {12194839527972802101, 8376199250979271449, 9055995864116790217, 8125030124567662718}, + {1070812422878398727, 3950906148308170707, 10121516919638719072, 813471384549762068}, + }, + { + {7610605259962047827, 14617655900985224117, 16089669078196617440, 10594009761533811214}, + {3425971360520359121, 1245021768718221594, 16690372892586114152, 9933179766195044175}, + }, + { + {15142732720676276463, 17435583143726694663, 6030257647680338377, 243683009289621849}, + {3064238900429394982, 7655019927497549159, 4484400084400458429, 11650860345018651068}, + }, + { + {16203650576183697977, 17614744533772112337, 1119292890050870301, 4574885263986729787}, + {8108207498737924504, 9708434439316056191, 10676823369888368482, 1078311554675991883}, + }, + { + {6876202174636220158, 18057502510666060150, 7821730895845187783, 8882321799602877790}, + {16220624224336230256, 15562800387021280583, 3043825293109091520, 697130162105054983}, + }, + { + {5394549491776704087, 14795348078061113966, 14206080764200897220, 4623073019242398493}, + {5850602047109930316, 13783531993760979209, 14764346975698048641, 8951680172224205890}, + }, + { + {7302725075484262769, 12572584665857403749, 6499691362933905099, 14476353114356185371}, + {7381716148644532401, 1573798302334388880, 8128390307766282880, 14547454176248589604}, + }, + }, + { + { + {4477325369345373420, 299141931133875776, 6787652129916359301, 2498016036564260464}, + {13342319943892943548, 11124287719737492205, 2456333599771808442, 5084719026388755304}, + }, + { + {12246932755942887931, 10842213418139067847, 1827392608284960926, 6961756951208563550}, + {14626966634382828071, 12653808277900379805, 3359368990539585596, 1190255644328095727}, + }, + { + {14845756090430871381, 1260135108359348096, 18373249503604334230, 14931345532671487262}, + {8304897926217252744, 16639705302116302354, 14578633917159176703, 5624357498623418462}, + }, + { + {10836955050615624183, 6228108794259714192, 3769609579318360527, 1481673673659326756}, + {301329772189110029, 3574710782304999603, 3037244905687722509, 14442941761397229485}, + }, + { + {3863379967423475252, 4598414140150397553, 13498347034161095546, 5995458763090398343}, + {8994138995797612256, 1053878477247308872, 16525881906724873538, 16597989933510424042}, + }, + { + {18195618552940791509, 12801347400921689158, 13372055618013067129, 14929951832730936581}, + {2563109394536979589, 3392102243539970867, 2978145866937578695, 15809561751101461921}, + }, + { + {6470844231261685519, 4860920111547376221, 6133864928365904793, 8914566156785557227}, + {8258394874597607714, 4464810914649217913, 120457844518757378, 18209291810039348360}, + }, + { + {7739110373965523311, 11019153332996240080, 7346010155518751797, 14853737521111213548}, + {2542883237207113209, 11015136828834421504, 1998601666328316353, 1540417751495800469}, + }, + { + {3376092179741497360, 12221254335784366861, 5282973200516004163, 11372960528472533628}, + {8188139842572259074, 3946305224334575645, 16643338862665650950, 5859492058050333909}, + }, + { + {14916042081488114271, 3303190861468284762, 14234546272335492538, 5776190344932209905}, + {16339988209459724195, 10022514953301624769, 7878363685856556300, 3127365206552843780}, + }, + { + {8340102858481562978, 5401806343794775245, 12619159636229742566, 16221085737347795155}, + {1241298364136442056, 9142635103215118982, 14403222699038355211, 12145678822325215894}, + }, + { + {599034134015360884, 11263317530774995092, 6667501365379084069, 9844276013103312691}, + {7566306886180438990, 13702768345615509363, 12525031963170717968, 8463786212988210464}, + }, + { + {7279390679700007004, 10579602100702377479, 4366146547587324748, 6962092370680728424}, + {16372420580520124739, 4597019194685908384, 13217149760366044828, 7222487257194391332}, + }, + { + {8454830421421057736, 4100731209937375984, 18348214289895908213, 6778376865226169852}, + {12945227893790929647, 1818657910008686277, 3629900123705314093, 2861658388952811590}, + }, + { + {15882969890737930334, 5849157078791136995, 10068103243390577755, 13131421240079433547}, + {10404642120419399290, 8199866428750316037, 1032443962738597455, 15582122438927179496}, + }, + }, + { + { + {6390361653475754940, 1093882175267357438, 3784079074949811167, 17343872969822169769}, + {3359715652121662979, 16808529787251986583, 5169730697018536870, 52766949850965558}, + }, + { + {13147212495082910072, 5628914243538540648, 439989514095330941, 7620472329041817834}, + {4272251824771633288, 16564977601507013119, 5441117136715882317, 5622571730905974389}, + }, + { + {4207421531032215145, 7924589143024019458, 5496622772676523695, 7061817399179278712}, + {7371689806847905735, 8282663810521090335, 11422487361383982601, 6397294642072086677}, + }, + { + {960381383357168877, 16774709963697143275, 17896181076874992240, 1150415168189819777}, + {5498481130530161530, 6895900060791069290, 2079514944189747822, 3428689507902936354}, + }, + { + {12056920178557394302, 5131253251712581899, 16251877995882633963, 10883064494054484051}, + {9473274815269607947, 8874308005470196739, 4412709653190846630, 16469366225886156991}, + }, + { + {3547198835521135552, 9940690805769919242, 15170549880149605690, 10701681269101530298}, + {5914809102954412895, 15790219349994701461, 13664049285300230863, 5735249081148743651}, + }, + { + {14753645881295168970, 9410794713982813264, 13485977523338061503, 14267793994973767571}, + {15813187206361118954, 16449603969001878152, 17705410933007144731, 10960511750491378082}, + }, + { + {4669722990542640772, 10017368027073540045, 13392819319228640800, 1070815632453829996}, + {7274130058405640448, 4460835865761538026, 15283885107956150892, 5815884817303156137}, + }, + { + {3469614802230980914, 18060080625283048965, 580464295809221798, 3338153928139206412}, + {9845192339392693455, 13250323899168115720, 11058696855422647818, 9665232062806155902}, + }, + { + {14461336556325939926, 16946363864290460645, 17546878353664479567, 17949437676666656135}, + {7932367178689988878, 4806368097560008659, 3460529608269790679, 6065321700046177254}, + }, + { + {16883816924971606835, 5486714189826473375, 15204267662844332028, 17199232837602035696}, + {15958749676770074119, 5540664038667498053, 15914281753951743318, 12225053486711127081}, + }, + { + {15346266095840263783, 14129675453960658911, 1781465630073142581, 12398710533895277470}, + {17697074063253841985, 13826156613321578228, 8855030685964401164, 3749659313217692983}, + }, + { + {14888039192306165275, 11233459160096048886, 709252573146299872, 17614748022803380926}, + {10853790173866038588, 2988411430602910678, 1343284586410250367, 4491892393582674365}, + }, + { + {5653853395031137185, 11847098886335071270, 15046954358935848863, 490763079643421287}, + {3113500211585712650, 15997550469331041114, 5281575885072775975, 2887311255648554506}, + }, + { + {5376335754670737023, 13164671289498247151, 6846569847526260467, 5496656304894178122}, + {2009132493403453913, 17250524577747091030, 2315376314333653245, 142024984008484689}, + }, + }, + { + { + {7237168574323016859, 17908810107504968137, 16225708127838178121, 11127095986977103648}, + {9346291308317410251, 7381283458277047010, 15168602815371846943, 9193719743691734294}, + }, + { + {9607254959726458411, 16837156817186931862, 16178143308706847393, 10970721795101931539}, + {10840376278605273092, 8298765077094727469, 15520543037910966843, 11484620381947762562}, + }, + { + {17395070963094117711, 7608132718922490881, 6531178971071758016, 1302814667007331361}, + {4002629363862769670, 14649492495298089937, 6868174210142585697, 15456170652716048683}, + }, + { + {3688308493559609536, 5123828159813683938, 6245436817220183971, 13062234263274605325}, + {1313395302496832996, 4961840797708687855, 4990192311341859196, 5283131006216350959}, + }, + { + {16952735659396950704, 1249482796824289329, 17859504101404809981, 13260403650830168625}, + {1583343855370236084, 11389120333403185826, 13676599385745755008, 5066667130137739346}, + }, + { + {4799264864906918301, 18347145714884655971, 17034125441088681346, 11828378178487279470}, + {1759038296522081901, 9582407833575609381, 4195817009050503354, 12618256395967210055}, + }, + { + {6486755100213398364, 5270923715575268322, 9268255346880651103, 3147724493117082267}, + {16710318779269985633, 1240462642985509644, 2400811796254219369, 13670743068809614358}, + }, + { + {11437779990773246594, 13609113239383378152, 31268927496646090, 11618772705165035208}, + {3078024460365036167, 12138983306908962712, 4779157919015181380, 11901698850260672002}, + }, + { + {14642787507945832432, 16258081639927585935, 2560321462542164242, 16286882196975458174}, + {4328159372518768969, 14313553865397841147, 13769372656320240568, 8950675126435331579}, + }, + { + {1309709344837422378, 18403288028608342631, 17102350491414677993, 1133523394849437315}, + {12526496222782003755, 5447309058259018864, 17311120581405946631, 3760058661125144368}, + }, + { + {17891474172606596407, 320094264574086461, 93927075222964142, 14355817838636249140}, + {1777882427773785068, 8237021421587560510, 11520559469641852991, 10567910693910023157}, + }, + { + {9164300764173563614, 12322279811717869943, 2768902015676238485, 7761799112151133995}, + {5740162933856370894, 8043946608495226840, 8923704438836381869, 15189322655373943849}, + }, + { + {12046275966378825708, 5909386969214935556, 1201990704907881028, 12128549009950617306}, + {10773478878317625320, 4554854625564648958, 14029736945871573056, 1353247251064221090}, + }, + { + {11909123603272307101, 5517949035179831783, 3295386484950432959, 5605137795524476293}, + {10718654547602473221, 4984952409581272095, 883267724006996723, 17328431094026829348}, + }, + { + {13671210467347025770, 9980617617519781731, 8339868735163579231, 2150724314757661915}, + {8571153021065445899, 9146903697769397191, 9122246102814640373, 7744779513085605450}, + }, + }, + { + { + {9508384588323002196, 4786531415304518048, 2690306308552249535, 12208815515689370850}, + {5145548243685871201, 1536915039528215765, 709289946127949333, 7152734178531880864}, + }, + { + {9627905753364576437, 12776456422166281355, 2851899644189834214, 16998174196920379994}, + {9001602524188761177, 8960294999163663712, 6580949973363012183, 7568306074815116797}, + }, + { + {7686633626025788546, 8110394872630496906, 8482210436161892079, 16882855163559885891}, + {1154081680627148904, 12804224766760790394, 1850455828762691082, 14191115350906359627}, + }, + { + {13345381996769253014, 6278048669175242345, 15990349685835870151, 16358261962292186792}, + {8505261070637963021, 9396725065098564446, 15331953351049782155, 16194796339208321205}, + }, + { + {15505898598362934929, 16825210854979603981, 4697782190623959274, 9370503401456774242}, + {12874840227707962403, 6119547445810629810, 9764164009057494220, 5416853666956021065}, + }, + { + {7699498684510298360, 16542285627069734869, 200751785530104649, 6985944962584804095}, + {7365545959109847649, 14865387755379324112, 4167319688751668987, 12162483513847343974}, + }, + { + {1039980316046001816, 7207503221801597145, 10591680158322288825, 11266400320575557454}, + {10706275395641440317, 9288394947884616208, 10167533985006762418, 1456585988309878747}, + }, + { + {7076257175157660597, 13221730879315432464, 4499548735964119085, 7559253754663705944}, + {10196808438730350168, 2391718471837563931, 914409564589897387, 6649744842278078706}, + }, + { + {10039057354622246685, 7195562849416781100, 17696866082062058984, 3668253949076972503}, + {3291647709604288622, 14581068695089559804, 10104544037456163379, 5446494334499941155}, + }, + { + {11083442423555675697, 16463352501129765262, 8326106600927169880, 14461723217830443766}, + {8960039240507947123, 6112452535158412156, 16298251376476091126, 5185774007776019173}, + }, + { + {5801222283949474418, 13946418525037992779, 2275515160040674505, 3244981365190546382}, + {9460698310301428534, 14807942233170768102, 6180104492182570514, 4695926909096500015}, + }, + { + {5502356275170104522, 12750322860129485966, 9581277511584938955, 3872282844937972630}, + {13668854758739140874, 15020438121087800965, 4581631138384430657, 13296613956093963588}, + }, + { + {7394309355461523862, 5374161350639568117, 2763783634295242959, 10215168014269656712}, + {10862202275249464165, 16813773246956503013, 4644566761082532589, 15300517379307655907}, + }, + { + {10894319502247195436, 16018449015752583379, 7936971022695592164, 8273950599391165937}, + {1130484969598457981, 10652972605389048300, 5964985167476071140, 1178111465674979168}, + }, + { + {3215460690308212256, 13044009109542950831, 1248575312568743704, 5805472854961471970}, + {16935262056111009166, 14323719510498371522, 4137201278518680629, 9262447671880633672}, + }, + }, + { + { + {10228366644420455452, 12084265406352277347, 10265869676493821892, 3560143954870272139}, + {14368775225608592689, 13173522067191372913, 3592475039513249949, 11243554718624931135}, + }, + { + {6543255501112359319, 6063422531520498671, 17228726254778244409, 7570754775709645369}, + {18222396492501523182, 14903937974816691813, 1216646642383641441, 7602781158453005929}, + }, + { + {14568782576170814716, 17582848432122737506, 1079387064102681806, 17278567874821675408}, + {3094302191119669899, 3730448048895347901, 3508894590334961422, 14091660942919228106}, + }, + { + {13329033749048978810, 4765695903433858377, 4452680451529163940, 5638854187414651620}, + {7897503022043776206, 17187635538005569019, 17766753195497526986, 13201529234556380285}, + }, + { + {8934119620399766972, 4226481091885914732, 16000709195004445297, 14687868180928846933}, + {16269913392757896907, 18294005838441325342, 17625669613551023126, 10864307042201644469}, + }, + { + {14722530431277419104, 12333728409662476827, 4162946257347548625, 7052045338975163666}, + {16435875989376103923, 527141841571514699, 8480360258792897962, 4322786951393806781}, + }, + { + {14380803034817149259, 11042134597430846555, 9992762805140200547, 9895143575678511242}, + {3228768306004664915, 16153114680219541243, 12036181641761325912, 491369524302296324}, + }, + { + {12320933424684960076, 8906954611339502145, 16931708732547376267, 6446897311644431583}, + {13749563256713530203, 11522599770043814384, 14455556215959342791, 9022955938835504923}, + }, + { + {8738648866901281761, 4688741093801776285, 17069682640810525423, 7158141773766072053}, + {11460933790638879246, 687134766504463570, 7796313120876518884, 11150451731319135164}, + }, + { + {13652684811535265600, 8494726433844453583, 15999979552047212740, 16433235792902853942}, + {13641303900302396790, 418630713805776951, 13090797093697365883, 6529658430803752768}, + }, + { + {3944614182924380177, 9542495129087581473, 6699683662731923419, 5017219913619823514}, + {17045736494588140273, 3578045824537114332, 15234910011456151711, 4392310298224006475}, + }, + { + {13050963220563520130, 16311879939705207639, 12461297624582251388, 9677731599265769222}, + {5160679975931966230, 3218707041599533629, 17098083534384492023, 2330141721984719029}, + }, + { + {8245975647138927146, 11496799090887525271, 1709462103065191917, 18401529677683893204}, + {13971543411749700717, 15107687167816783802, 7171906080161032790, 2549191081579169610}, + }, + { + {17251496610557148115, 13056982918233222110, 16321077587645226911, 15873643227887663856}, + {7790198561388957118, 9539520576306975575, 15234893276112958324, 12999697377068360422}, + }, + { + {16169560456946825943, 18091964243071526492, 4341876361632902705, 7532668331381251135}, + {15346381760818990405, 18301333564088079147, 6565096728885044125, 2494845330727350075}, + }, + }, + { + { + {16319476863352440541, 10283930715856640343, 17675054544532098447, 11261132162985242084}, + {13712716897981761400, 2681907143459288706, 6930256922080133347, 1445069157579547822}, + }, + { + {16928574868467385886, 166417019993787654, 5882811520342817815, 14106304179344008065}, + {3747123724781081800, 197109533566874475, 14303280595714789450, 15457633026018307066}, + }, + { + {10773597511592584859, 12552868588431074640, 13500771767160426835, 8002499270056378440}, + {13792839099998553174, 12949371255843262119, 1713974340992291550, 16150173130483658061}, + }, + { + {14745984256428057001, 9333707338036985191, 15365925315303462, 11789129028059619744}, + {7873100217437235208, 5289763977161829145, 17731215200358323788, 8876377479309635703}, + }, + { + {265950821974454804, 5047467530470542278, 17523044368516619801, 10054436503372765176}, + {10321185867287373431, 1212061937729015591, 15311258419138633926, 11236518538207084768}, + }, + { + {10904693956407098222, 9013418755007070130, 15510005599846320670, 995378633446250700}, + {12234095025518917836, 6689106237771514188, 2809193993744369126, 548124799387888260}, + }, + { + {267350765778774337, 2853877351938464055, 3677119082593358544, 7685335121077514739}, + {6491980094762370981, 1384870316654548002, 10568872345228996498, 241629538659623878}, + }, + { + {5839400175629113441, 5238299193248381245, 16787876416022887315, 6051613843621920008}, + {9219569873668974552, 5916753090530931032, 13390630214643423749, 3265335490455191268}, + }, + { + {1507475744849985303, 2597075068965622770, 14968669113917266926, 597606442423659891}, + {44293923912414886, 3832651144752540816, 17438860065613195810, 782112340603343331}, + }, + { + {9050896199196733903, 6427608033444590004, 13787696679536621857, 9682087046920409188}, + {4519093754155995429, 13564098392055667371, 10512507082236058799, 5289934424008191746}, + }, + { + {3477191607403300916, 18283244229745029067, 8462159792484018099, 3056576498976014760}, + {7259283167233712785, 12530251965039903998, 10232104933720625111, 14190745998092156987}, + }, + { + {15759362035410895911, 16075598437961371531, 4651513528876405575, 7694151626503869614}, + {14468862724637972284, 1838601521755586245, 4168957446435305706, 8694905613027663664}, + }, + { + {14825552838983151434, 8639609968952840931, 15547914584352392016, 2313507499500708287}, + {6902543375698033684, 9987468886016348918, 9068175779860656258, 6899641689193116297}, + }, + { + {7449110402827616954, 5689206471789540768, 12722069021950813669, 16017131401246233663}, + {2240977975275954837, 4794705713606614946, 5734937900461809607, 118285984764445639}, + }, + { + {13917685647531721740, 2432096911145792817, 17733637484624159521, 3848601825403209903}, + {8192433211051054683, 17388066421914150767, 14336306308847565282, 7501625553608785022}, + }, + }, + { + { + {9194523390605857831, 2335161171394626054, 12290490336543843159, 12464172604156286188}, + {15842196578033029974, 9081285134201585379, 6123406461662038242, 5504260508195082396}, + }, + { + {9599159247384506427, 13011559959971256245, 6331802547989957841, 2642320882309956905}, + {9140255367820630480, 6883541786494880896, 9560822438260750771, 9273862677291701694}, + }, + { + {12578940088863451089, 4698579870843180556, 13634180401794570924, 15763130743395284022}, + {7444441842547931942, 4944622454458561492, 9589156490791486440, 14762328488235724618}, + }, + { + {6185067974942684922, 6452325785873503452, 15247257292915812252, 3689324664200339196}, + {3264129576054154137, 14977721630214750038, 10720913377937894256, 15914487080763816378}, + }, + { + {8926126498606164569, 12956394005759769716, 16902149488499586013, 7841840983349613625}, + {10587053251468526108, 696362153501209498, 9784750880259098186, 1207696323194229080}, + }, + { + {6366297849225708271, 1653728037493780302, 924103820671018926, 2050213326049184692}, + {5527413390519421127, 129805527414320490, 11550889572378802302, 15667992622431666977}, + }, + { + {3759028419971240833, 201899490644698259, 16787882148977818573, 3755266958958128460}, + {16997526157701685291, 6920710029293447897, 14077301651040071328, 10880144992445166875}, + }, + { + {5498621600689515064, 11498885804037952971, 12697073118321478539, 13999008478737234463}, + {4324885099420360642, 14021182496192299466, 10763088992583373843, 12898585157666243299}, + }, + { + {9367059860785010847, 15787147891143727655, 2519720658767337732, 11593809545681651942}, + {11966083811953753216, 12761111316475086277, 5681625861426437827, 15920587591610358813}, + }, + { + {390729441391219522, 16780558466241830343, 1374488446906327562, 10865131913700232628}, + {10115076211715532468, 18184016780675566832, 8365356477197603014, 672096097598251136}, + }, + { + {2393424067712509928, 16879911507754196299, 6441307574161100589, 2818743579517374412}, + {7083174841445248189, 3410683030590349702, 14697584027599531676, 8328975445543175696}, + }, + { + {11622402383521841588, 18271726976204770291, 4805501248621435402, 13483122453682180759}, + {9288143526654965614, 4688427612851085031, 3280806057528512375, 2249349779106893174}, + }, + { + {6807440366000180651, 16399452121226315247, 5098169947999459087, 3558234272787006753}, + {1792969085845015294, 5524357634740353242, 9429244535996516945, 3937357214017147760}, + }, + { + {15504868609044485967, 6752328153557303622, 3778610801922734369, 13830970685441980645}, + {8715733351182855585, 13970559751738714496, 11410776131378170826, 5487441016062951646}, + }, + { + {13162254303511925286, 1500183854026947752, 6344593292969383689, 13968537166293685529}, + {3100593991852309751, 464141462036312207, 5107705843278430088, 1965835506583809167}, + }, + }, + { + { + {12081034000518110752, 2773740877021737013, 6429475399936543899, 6804412599792308979}, + {16082860502313571182, 10013838454082912732, 7176778953927883654, 8065751639278576331}, + }, + { + {17741525051518363144, 1374267330336191942, 4677891169679898540, 9639823611685431337}, + {5482431056894095950, 6629146695374718376, 3884574854221819712, 13266790928096813258}, + }, + { + {17505459029376928465, 14087658194607915364, 12240552390931686885, 1809009366037859941}, + {9468395484396723291, 9446052656478984520, 3720796795453397330, 18035355127900871187}, + }, + { + {18221138344920380175, 16761112742545021198, 14421639991115588619, 9419167563943683547}, + {6237248361283446238, 889754338720059891, 2289880386545166424, 4280148734121099084}, + }, + { + {5259165122317589354, 6306061166879114159, 2622163270351284906, 15212813592118086979}, + {11497359168652342849, 7085380391293263482, 11799059272489792659, 4912160901181298022}, + }, + { + {10512473611770099290, 11735037909076331019, 2922606398008539984, 2599799834378751770}, + {10226702495047936424, 6109026252412854338, 15572556822827169237, 11993701786788749663}, + }, + { + {5106897453764491321, 10540479232768400094, 3938246597140945859, 13156157265138481529}, + {4932443191001849637, 11374218582626530502, 2907557293167002437, 6807344711257391317}, + }, + { + {3993197157612782947, 14810882170056329119, 3476738916713041107, 1512933700383846542}, + {17820889751141311776, 9132720567660500233, 17598924894608972696, 9704537908665702455}, + }, + { + {12121941964759747109, 161674837074510172, 2599887134944602725, 10582301831176576187}, + {17746858667522793487, 10735346620578591475, 90382511151212475, 8756617880518165297}, + }, + { + {13269854730742674802, 16128423099443070808, 3557230428644480193, 9637953317416090984}, + {6295039911768726240, 7019479692290635445, 11667616931857432446, 7159479331923350611}, + }, + { + {14416651741118525418, 10180867452897498870, 5073925566889872021, 17399294023945814271}, + {2042657564518230341, 3364886656428812718, 6324877312192616572, 12778324589036538810}, + }, + { + {10574237360751578123, 5116798422805306054, 14491722292795290218, 10799156134310323684}, + {12689926633011134844, 2658342468671191169, 15293758403109373386, 16248058473163364262}, + }, + { + {17412396133163580666, 6474892296180387693, 3334160446575187305, 12749216946172573968}, + {18160154520597666127, 8818156595950176943, 16077267238396508593, 12651459389529897136}, + }, + { + {7837268594975894598, 3733413917041538879, 9408433334074005916, 9807113299110084489}, + {673053561909802023, 10235823672366472244, 9197803481286702511, 5670973022205283920}, + }, + { + {4435804333677545569, 12530066828083700918, 14652119799285589695, 7610189145859517535}, + {16049951379406478991, 1895939661259683634, 10886955028200106760, 10575752015672416378}, + }, + }, + { + { + {7454214833719424418, 2128900810399984335, 8254953962723841408, 5341529923812819418}, + {11486532916552139238, 4528331821405917357, 5048485034448492541, 4189495710753944825}, + }, + { + {9223539587116638677, 879142711399260546, 2878829560233905572, 13081522393987952773}, + {3067261963348061547, 16008150780594711643, 5466468631453287640, 16659147898971349582}, + }, + { + {8047766502132608624, 8715815570878148809, 9093649079884580138, 3437267783531715968}, + {17562225708466062266, 3512667182749067601, 9223059995161026858, 1366690634827047376}, + }, + { + {17929132376737482163, 5565926714491294456, 5252303555134107501, 8169975563698132305}, + {1829326230943509100, 13780918661853274468, 17736665596871232627, 4246797342334307384}, + }, + { + {5113556452592134569, 7304867793218750141, 6016631926489320290, 16471860203547627727}, + {3444471410714850041, 16571738096215232488, 2003912224952639024, 4203884000388032492}, + }, + { + {16858425223672505353, 3192567884201479579, 1688923188642613263, 4159042130811153987}, + {14900413503869744297, 7521485042788722327, 14038093805562042641, 14713051866364662650}, + }, + { + {3738774192924465076, 14037618828827556145, 12882915396530927286, 10882862194263941815}, + {13115222579444494605, 18244214260845794346, 17217867059738274194, 2458870331386500577}, + }, + { + {8768788172344064509, 2761897497254272960, 1400167175024837359, 2591319596670212133}, + {1499652044223484974, 6820326453941021707, 9701009499879906773, 6897435972338565418}, + }, + { + {8314355711464256163, 8435944020779763783, 1814803522962187872, 1875253356755380905}, + {8214588085484192137, 18062045700553127821, 6649947905482043494, 3119726140944397531}, + }, + { + {11881571666857493523, 6300786026612414187, 4928573492087752294, 18343550313462089203}, + {6770642120472453960, 11296815027803718740, 17312916793783562794, 13028515123652649961}, + }, + { + {583508939637547757, 3195115082527873085, 8497784022800549923, 15135719419829981016}, + {1180291993378114150, 5447281494912347899, 4710517655176242215, 606503081693490000}, + }, + { + {17732293765863716052, 853971165248416821, 2022886284923413326, 7522564752651732633}, + {1417954193520965954, 5046659528429172066, 11426939225844711305, 17687206690616539318}, + }, + { + {6518552374736169438, 7940416740434530770, 15228615103587329007, 10662504584317997513}, + {18370800756791469891, 5564085264882124489, 51043856061444814, 11996026931884728651}, + }, + { + {7009195269496826002, 18330778751427846129, 7903886241001925539, 8198930484643879628}, + {5453546027419466587, 10378692433982210944, 2242412603379120569, 14762161396393277464}, + }, + { + {6146718865488327808, 8559779132928137805, 14001994895150170346, 9915701789711858841}, + {17119408219089522083, 4345363585985782988, 7559492126634131602, 17074565022279033371}, + }, + }, + { + { + {9262509587234749312, 6377906816499461739, 15415592259881792841, 6113140067088447267}, + {17505803833889144731, 3922849788840338823, 6180172597177093790, 7272741317181956640}, + }, + { + {15620168851912893400, 13762314693487747007, 13577625382054330775, 4116976667540664996}, + {712200332640207605, 9098568002202933512, 8905476951567380032, 7075673514150314660}, + }, + { + {7724870937269356050, 12054277107553403808, 1881284905431205309, 14429595888039183277}, + {4176419490283315185, 803567059653412279, 12138878637145159139, 9651152331113389250}, + }, + { + {15811459837282651008, 4038049993244767161, 9054218236388056577, 10807376403937048775}, + {11113869110590438959, 10336442539492421506, 9228056645601479672, 2983388754829658480}, + }, + { + {5272549712777700740, 3890998652469537324, 2338530655383446899, 13889100994494825258}, + {2605827345546331653, 1946537408424111099, 5960128674616374312, 2996461229050766944}, + }, + { + {9235630643187100528, 7874836741106774683, 1509645736063284557, 1291934408179243533}, + {2170879231846765016, 18243888082459973651, 266993053446290594, 4551583084211481457}, + }, + { + {7680050744092380106, 10728235076013009138, 5020205498410121740, 8174117988374987111}, + {15823303896577313648, 6268651341788131847, 16646239256422284672, 7277830349937654337}, + }, + { + {7189376137127712298, 9147574701720272724, 3983921661449444789, 12479790317447783959}, + {13221020976679959405, 13001868979553711359, 17918176319017234744, 18030393246529651080}, + }, + { + {1277346094474678251, 9498303380775859142, 5384923668452161486, 1780647986160100011}, + {8642790494747200341, 9734232043260261391, 5142834828615817260, 13851307413031336094}, + }, + { + {13856162196947802633, 8991033151317963811, 9758143338284799726, 16669930361261935141}, + {2769693485089420097, 14961618614592883242, 6027973048684521312, 339045855685213514}, + }, + { + {4705473345956039571, 17384553086897199761, 4490030246274451948, 1509996255726148943}, + {13542663230247432557, 15148026535112827520, 10014941605271261089, 5488071105468657298}, + }, + { + {13903368497828271814, 8050546449078305498, 6932373216915935575, 16010012759059004304}, + {15451708272653450375, 211711129247219149, 10435723642185827585, 17790507800712341232}, + }, + { + {11196283625212661460, 11223173364796389182, 15927254202510526683, 15939111530538795368}, + {3486548927974609940, 8233744837082586587, 7138041412908951164, 12863368836600604627}, + }, + { + {587498550288996803, 9937849083717302378, 17460580580397185843, 16850270092759302710}, + {8661654791709545973, 2350686583325065432, 14816283856648791595, 13021196930055398267}, + }, + { + {9641099975481205848, 5936405208377074167, 16926315209235053832, 9612898534540818137}, + {17782980290875306043, 4118599702370009503, 5379494204096737612, 10529123509904334042}, + }, + }, + } + + @(private,rodata) + Gen_Multiply_Table_p256r1_lo := [32][15]Affine_Point_p256r1 { + { + { + {17511864284462479051, 4391315454785363822, 16633389246499252566, 4290325975494843430}, + {15912670649662225191, 14172733821603328367, 12709802627494541709, 9648238681838878635}, + }, + { + {12840624483048662115, 13614226123606379619, 15087571995173849344, 1395488309690794621}, + {7173958427217959878, 1198561064176820332, 16821886260165681626, 10019479169661217935}, + }, + { + {9901328250515532535, 12796305315632203942, 10819069447660403847, 12542238242508661240}, + {17077777737462854238, 4364294351375777648, 8335244153165894685, 8863541604979427311}, + }, + { + {11029520456752683158, 2297291237551781454, 7934683676555855479, 1563954733146546128}, + {2252805128528536255, 10523375695822939112, 4598652721256818062, 17493379105069761435}, + }, + { + {2747551692916263132, 3151123035150683281, 13938314333309683791, 11970864255483579560}, + {7894236725861110998, 10515613623232567716, 10445557830757066839, 11155097727742050955}, + }, + { + {9569762631377921701, 10341967309273270300, 4697570564829842013, 16684762125903667303}, + {5281929071085172097, 13027961546412671127, 18398764602992176314, 3872796039504642974}, + }, + { + {5035609627965208105, 6338722048255995169, 11594969687968475335, 5639340633771742838}, + {6928934109570365590, 11589609913085167707, 18353534295019770247, 6879412911232288750}, + }, + { + {10042008593756684008, 6713471518385846030, 10961845838926538977, 855334359173719954}, + {7598642325962297361, 18006511265377032901, 6844179774752820363, 248341098560552116}, + }, + { + {12797853895127133352, 17314687680589848148, 4801569699821499927, 9711604734594547217}, + {8212610645535363590, 17221681508724305642, 11398663136094709935, 14918164175449979798}, + }, + { + {14940688064094792027, 10874356086032303420, 9942334156288812894, 18314945846365913248}, + {2026773265909278528, 13079907189666226787, 2413436844382479762, 17172916412715413729}, + }, + { + {6906211734178583215, 2568977141255648055, 12122130143181371713, 828440041422552532}, + {9361946962651414191, 8982763378443381215, 13842936470438971226, 14726899303190381422}, + }, + { + {15233793159839573220, 7091365221489488397, 7026505041428577564, 7614138360854053029}, + {5906758210005848219, 18266182645583974519, 15465977441750183309, 15365799046100584430}, + }, + { + {5523310814149808824, 11103439607538154330, 10292039577546071548, 1169663949743807030}, + {902203905701917473, 12346725749938989079, 17633270407605278415, 6960688675023695455}, + }, + { + {4505161139988645144, 10689463780805884897, 9379083335142738351, 1333253488693735633}, + {16044931735888519844, 16145584549427855743, 15405407720239538978, 11239573776554839202}, + }, + { + {6975554318981968975, 15982286720404911512, 1685931425716796252, 17715405440768877495}, + {4827607732096558544, 6375626601740689475, 3502039151843227915, 12085565714635174559}, + }, + }, + { + { + {1190044221726873109, 732025666411072563, 7781096808432277694, 13079879637655900365}, + {9048680577986693793, 12528346194104542124, 10575369576322629835, 14068913038053465964}, + }, + { + {3297775431071502652, 7947266993949467566, 6161673381820779563, 10604626734847205996}, + {17669018066064502925, 2386071939136502354, 1076023928806956187, 16075459682742916440}, + }, + { + {12387028018538599950, 5791681577936683396, 7536922194386052138, 15377770247350254336}, + {6564316170002440575, 10629371267149545956, 16125760269901494382, 16051398044897962024}, + }, + { + {6237354803374899565, 1782400080026955610, 16115027077529639342, 17907259814836219524}, + {13179234383592426160, 7302978467158243198, 13607720993463749225, 6693531817169120736}, + }, + { + {9659467198848065929, 13765104107473534739, 820057324758632016, 16604163594878267405}, + {15321524555426147294, 14524167419333362957, 157291234996957911, 3689488130722730671}, + }, + { + {13896531645245568605, 13598412639648980920, 3875086557856143664, 9242105512956135595}, + {17410265178284161091, 14904754836127450463, 2354327747158525902, 3858493849578874654}, + }, + { + {17288438225198818690, 15275190140700748774, 14532856272428522409, 2192294551011758591}, + {4275966798014984695, 13252812474545742114, 8604705074440591847, 504054699541924162}, + }, + { + {3623027910997185067, 15957466839356832933, 3504133700071704955, 4135728439139397021}, + {1160600455691338871, 4431928072859292239, 1542956305318065546, 14109181184369694855}, + }, + { + {9135041378474229537, 15626265487594878380, 2645257479784082878, 8105679948445763432}, + {8579715781576202730, 13437359533149316300, 4344754720520585005, 13326372852934103673}, + }, + { + {11341622086474305983, 17104958945811183278, 8154944722722765678, 6696975609844549775}, + {10895966360082878017, 2277686037575837054, 12236842881540344526, 2086470279064067791}, + }, + { + {2942668817124399651, 11439025398519255779, 17477264434671471242, 9606507094132585461}, + {1771475584689465869, 10791261379080046759, 12901998265727968789, 16423426725595035468}, + }, + { + {555419805011031621, 13715683285513290290, 15526654591995532751, 7023761423093873354}, + {15093366433178982304, 8625749648874372840, 6412297471587129206, 12161114204724955762}, + }, + { + {9362623422820895267, 6491356159483508885, 8543224082493101588, 17290929683278258587}, + {17348088672546490894, 3323350644823701753, 398525379151271104, 17794417664139368677}, + }, + { + {5880914635028486784, 2898124605786107494, 7953506026198179840, 2189477357380899574}, + {11207122442953694293, 9288539232660208671, 13527697625010979453, 448462453367651162}, + }, + { + {11262205719433170585, 7539606872920196479, 492385789142086954, 16036594120332851267}, + {8084547797138041354, 10063336189771527714, 2484395715469739911, 4879298610504146231}, + }, + }, + { + { + {10457697409306668434, 7830477435299250296, 7772379952622394912, 6109610138112185532}, + {4382803614711332911, 286231563340803504, 14408860285425706036, 9445290615796219321}, + }, + { + {8838210194055479741, 16190279688839291456, 16520121358582757556, 16768959728701970634}, + {17279896910204983538, 3582816187015369256, 372137484481226748, 12972230207718993241}, + }, + { + {5372953569411270487, 17808033035436856194, 18122397266105109983, 7100719381161799491}, + {14789750485957107776, 7797117101197801156, 3512936690589352328, 17020065099624467120}, + }, + { + {11480031272463364121, 2525856087688686375, 5875255653057452580, 5606696614467440464}, + {12094715534218447962, 6173479337351577758, 18244015404482482803, 13199349349511499695}, + }, + { + {15137716704658930971, 10986987873306909694, 1939043496821343401, 831824210330752494}, + {1056638569496361761, 1714583153436391847, 5183439003162975519, 1665087783666164342}, + }, + { + {8618628902870211609, 18064648431799903596, 7274877928823092285, 5660734703123876155}, + {17178150811821260605, 5485275535084805985, 12607767610318589165, 2215859519135800862}, + }, + { + {14525253431314563485, 18061438239992695424, 3753059877845742067, 6434164734885086330}, + {7925955539869645215, 5236273722884803492, 17135463959633855728, 1885217581414238490}, + }, + { + {6097225965006328457, 2630336000831717722, 7049638698786526134, 4203465038263485233}, + {4677974565964393904, 16044036678123636261, 7266049959100300634, 11339674070148504929}, + }, + { + {8932509163442546090, 15088719838810504543, 16380598316811388529, 11816509227456545305}, + {16117098651837966507, 6506253137957995237, 7842840841723336777, 14854630695614255489}, + }, + { + {13319400996902371533, 7582870533150862327, 3853021819016824068, 1553148791440569506}, + {1383156799113954152, 15192818247458559870, 16096167687117464686, 6356494963887209448}, + }, + { + {16159738883836847557, 12797888767862801410, 14516904553705186948, 13070086184381080434}, + {916885380224317954, 9486576895096666538, 2320292919516422975, 5019772534786350963}, + }, + { + {1979992348876614621, 7494083465935166973, 16035723662722831744, 6820849908885211777}, + {16740735239901023053, 2017530162004533409, 3087262288875984227, 9072904925376793991}, + }, + { + {11716934526135332476, 433379719600995157, 14981324743710487461, 16580162143428931768}, + {17678216037230646787, 2252837520490636634, 15914299694597684738, 15253999728204986937}, + }, + { + {15673599333229961794, 8862902775863712472, 7565222536246787763, 6724910605061440481}, + {5835390808530098179, 9647776340035782792, 1038074137838521743, 3352456378381259564}, + }, + { + {13166325906224116930, 10408481058915151795, 13583679214409957982, 13238337156927685694}, + {16088785436819834700, 15860660615594092228, 6472158593272826810, 15600310172166391652}, + }, + }, + { + { + {16375505785562641226, 4903074653735993511, 10355787845763031761, 3188849033041803587}, + {3145147452182864049, 13878747873108378466, 2798650520315922121, 2325962694441538199}, + }, + { + {11530583608023224967, 15979155166527001287, 592931868138800645, 5361781029549479856}, + {11246418752830406096, 11882251984248471436, 12026389461944629423, 12289077922798223820}, + }, + { + {1328339467113622233, 13374824154992864223, 12057132015324007824, 8507647484414695512}, + {9286016370798146986, 9083798709648036612, 4312959727577073260, 3732271624824420608}, + }, + { + {14129872794455315922, 16354810591314135702, 3177417010197743958, 16494351130927698692}, + {16557765056328447818, 3139394196704738651, 16891813998271303650, 7374470997276173905}, + }, + { + {1547814412223404746, 14194709348405912167, 15771028929623393801, 10945048172868684389}, + {11234483878611528405, 9542605377580701681, 4555391547268120796, 14916872217451960022}, + }, + { + {15490131882364039637, 5140304620645573547, 9403655757498826823, 9824850954989176893}, + {6366139388903157264, 1981838834216345294, 14659870286877979556, 12091578124492612524}, + }, + { + {6832171775190531128, 7903951882621813138, 13717573220828409267, 15400575122727850054}, + {6101307565293576434, 17226772767105983314, 3485283905347036760, 18439321272895583847}, + }, + { + {6289130721434350290, 16129337673129720846, 6648351866142453445, 7705983837166554199}, + {8120136556582544814, 7924417299222764443, 7821995671300500892, 17697662726179084739}, + }, + { + {6669506511185916061, 7036555931205961476, 15471324228012955656, 1075869467462424743}, + {14834182808856841386, 9481869408708862398, 193651363902981365, 3496053494343565969}, + }, + { + {15198290782478916101, 16205293865829644684, 2104596565474767471, 7783918193658109501}, + {1567469099169331732, 11324634977690198924, 1374141643017900909, 18368642394438425630}, + }, + { + {13389638006727712302, 17518324493263447682, 13178832200681259657, 8955667391164524441}, + {9331759525815425703, 12920722511913101049, 15807602761711044426, 17873219821625976662}, + }, + { + {12103811390374960600, 2801185238127939998, 16289223959107648345, 17243660994858386104}, + {14818957729322960498, 10018491794651971206, 5502065678180783560, 4158378425043433526}, + }, + { + {10278921174996593635, 4630624563386647486, 11179643216044347020, 8701826069861381281}, + {5839989039471676569, 3060138177923841885, 11279648082143612852, 15207786733412131883}, + }, + { + {18277950978951138342, 2577918906618404946, 11684553042740786163, 3082582313241836872}, + {5222056779189126973, 7794579876203167869, 8527673475629739407, 9851790541007784515}, + }, + { + {671618501514350673, 3455246317052893537, 18161533457452722900, 8968434886308785175}, + {8445049055511813064, 16897132794064300993, 14420937999674600470, 11110627336577683437}, + }, + }, + { + { + {11535283160083833975, 15102917952496589829, 12909095696891909745, 4611119212602854744}, + {4195756524232932570, 3754603965149529000, 11539276962358607816, 4401424391553230481}, + }, + { + {6842993463058627120, 2708745114617181146, 3832382691810282630, 10333834458057320812}, + {15028197197004077388, 7681293343255119354, 16227537691626587485, 6703363869832495607}, + }, + { + {17567108285065737529, 8693245930330183070, 4025672038042952121, 3491067119247522844}, + {2100799837993193702, 9579542950705774054, 5091525285265581997, 1806757015709820088}, + }, + { + {7757354840118131559, 16227348978414023262, 5800861674805516343, 16486235803248700961}, + {15646700163023677309, 504258765210816549, 13724147899924699697, 13588899538317277096}, + }, + { + {15895596198730294923, 12513494396374459899, 13552575153453342654, 11312160635199213507}, + {12446618129881485796, 11286186116805515445, 1584191291800429567, 10188741008566636830}, + }, + { + {10157626021970320469, 6580688164585715207, 17158416694471177787, 2873484006255074946}, + {14852216457444863041, 7463041347566136496, 2190030775722958628, 1116223035803602728}, + }, + { + {8598875756176012541, 2146658618778432566, 17575736667490551813, 3602654209723135985}, + {7223347129734689099, 7256921024940026570, 12249118963297692963, 18168532365040819099}, + }, + { + {7585174044375463988, 2491923406404093282, 9355733262044036112, 11484079611349577325}, + {13145030009254943291, 1234932884591406048, 479845670619308618, 87735010308690865}, + }, + { + {17307641427543377277, 5862898330718319545, 485176909118483750, 9845223919324484076}, + {4293549583740204024, 12765124043303931186, 17870894781132657382, 6508172378961793849}, + }, + { + {14234156373312856400, 16210939788814051708, 6478880037923038392, 10435512103812909561}, + {18142844321802359753, 3243996803126554757, 395603619159523019, 10213589535656704607}, + }, + { + {13256075137060741204, 991285459654295161, 7857174835799942102, 16201105040554625727}, + {18398612085349994216, 4512860776717176840, 3521452275695011919, 10622137733045360311}, + }, + { + {14993897771652736376, 3320388672992783302, 18421556740970114213, 7438967127794745135}, + {15048397725789819354, 12721899159423777001, 1135125102123667189, 6637485660805148630}, + }, + { + {205606553319362431, 15484041062449893984, 12896720585684759529, 16675624014916513672}, + {7579112430564108390, 4602460356900251082, 2677787525524280838, 16723483619407414479}, + }, + { + {17981939084373319995, 3989926231875116241, 15342509934701840045, 12999252495311233519}, + {15389919024942778009, 6136335679373143315, 4117381415379544275, 13342256463740646775}, + }, + { + {7622769999043907199, 15227992053145045634, 2719412067263856950, 17811161335980566241}, + {15036003689029442301, 4919601685231030712, 6756893600905532338, 18029567067112075531}, + }, + }, + { + { + {8492025373682814159, 9341562763134230960, 10104358220305514878, 17545404790574939459}, + {15737064134098795026, 3880597485411313924, 388663918823974597, 15032915458906101183}, + }, + { + {9452334891928331309, 15207477416486363718, 8081596400773698461, 7528187414539292243}, + {4773782664413845594, 9435822414884353799, 2722451711480791323, 13642248100035410269}, + }, + { + {14202843175914986568, 9421566354325954710, 8667368258699634314, 8733557788892402517}, + {331451278037425751, 1109013653863287548, 8802742738207038150, 4667769857523050796}, + }, + { + {16570512961992288509, 15784840936011612960, 17797638261217375128, 10589124475671334830}, + {16848440972121709899, 697679021479737566, 1456738239410270672, 7214966028857473701}, + }, + { + {13782421991242364698, 14661156263311647121, 4726455119103158850, 5026680986111581594}, + {15610213195880130268, 13703306863846075517, 1371700218221235399, 16792392307217237043}, + }, + { + {3250188629442787152, 2728518744775098354, 3140694818026767341, 17566141747707001105}, + {9569291890730505101, 4439949820491175035, 13751802166620923317, 6602549032413906269}, + }, + { + {1067242659333881602, 11852011445832610026, 10644339539182752718, 15519552867360295119}, + {8817864336906465495, 8844034637292547409, 8850766994595652906, 5299330403389585218}, + }, + { + {11434157439953722433, 9090860151661100670, 8407869262026581159, 17882547383849407986}, + {5277257988019769029, 11463853580825342183, 13607489835500075467, 16878800997498950751}, + }, + { + {11526703690786988415, 6919770449526881259, 6713486711636442468, 14697284704991333147}, + {5405738839499060129, 4737011393825878948, 8707677918280383477, 16881185094380241198}, + }, + { + {9056014389564242176, 13179419520216397988, 9815298409700670396, 15302091100015307530}, + {12552178314548371153, 3975519917079954227, 17211203317279781814, 17755252427177154090}, + }, + { + {14056502343958951437, 9570378325961888046, 18335930130582329417, 12188057598786655680}, + {605832426765150582, 15265028749599155713, 4881763628803375168, 425422732543303669}, + }, + { + {16059297404709367406, 8426877510924536482, 15269952608796785555, 6256768900860981984}, + {13142655793714702073, 14566340391957173918, 17147065283704191109, 879106195264399}, + }, + { + {14152733561556558931, 6788431167332998309, 2303657738205239031, 12712406085467592411}, + {1740483284496903693, 7206807366776489586, 13420608648010812358, 9180900918550128115}, + }, + { + {7193311017682954852, 7916342489073401148, 7990830552202175554, 15066065171478273830}, + {15601436495559985484, 11056245839590890541, 15963012082312968312, 7270947051909344657}, + }, + { + {5010740583028703301, 15413348048560455978, 2028314374959411194, 16685660750422250777}, + {14284468905357216559, 13715859397068327775, 400943255937053645, 15390787503961331119}, + }, + }, + { + { + {2707032230021934480, 14943945588296447659, 13333962501998857701, 10603744732015256400}, + {3386903941135274495, 8507451908469049716, 9231176235773710950, 995464562185179329}, + }, + { + {1497127512412966214, 11292269970549257426, 13920714718237672232, 1363993524078475237}, + {3687544717271789391, 14097532154250414203, 8367320351336033564, 11089672460564007700}, + }, + { + {16993953276024768829, 12025590727803527383, 2672535181364381995, 2183111709986676538}, + {14822521615475063339, 10618745739454592027, 9957515072444869664, 4797521918890127374}, + }, + { + {18097777493026370528, 398882723487597643, 10462164796529820357, 7704526739683689547}, + {12438059168025171393, 8163001730991802064, 3319372757738711275, 11518015261707325261}, + }, + { + {7809927122217534998, 6003738786706135597, 16541272992243715653, 11352602417510156921}, + {6070703545889058045, 3742828100079104877, 9416263310824977145, 1406892456840131842}, + }, + { + {4005088727670892586, 10215872293486093012, 7634075494800881158, 7707144163086802537}, + {7085702388211248163, 12168208652772836726, 16347414703478252736, 9386623607672009940}, + }, + { + {16530167766100505402, 14672843572926881623, 10752276706209340624, 6888427606311779724}, + {9060900993058482991, 10439396339124215720, 17640982730425880863, 12916411341252677116}, + }, + { + {11776245660806714247, 18129100488268011560, 15389929343761297429, 14544292652959164154}, + {18063319363114104433, 13433144948667100183, 462314076175867487, 1862686058702915115}, + }, + { + {17306422602774323327, 17272002328208118653, 9314885036861009829, 7485631191912561636}, + {1933835651414138452, 15231897024969540970, 507247317572839552, 10741595984991150047}, + }, + { + {18297797979313130180, 16976628082093243813, 13059060093619519046, 6865085966096869228}, + {15021840537243000183, 17843637254308940381, 13122764022765250336, 12556030904692962295}, + }, + { + {11175787671000337381, 17757097628648374409, 13408571223487217321, 2720103532070247452}, + {3237822932023459208, 10155101091021157316, 13910068101949253623, 648579517754264097}, + }, + { + {16597587101652675879, 3941450686064909756, 17635514250964078220, 13107347044039852240}, + {8910347370050088758, 3114023981351548745, 5209360756412143979, 8990623441581200588}, + }, + { + {7692284195082081732, 15977071788000084350, 3594719301791478282, 16545490512039598136}, + {7629535887569375952, 3241949087900065139, 170526822997903747, 3422990592513330514}, + }, + { + {5473399325468482480, 2511351254139828397, 1124856552206019504, 210074180589003934}, + {9693298849967626723, 16185054013081266938, 16070865229793723400, 734500463998096984}, + }, + { + {4895849847827915947, 15252720925614851036, 5944268852782996266, 8171510665067151601}, + {10594809041696466609, 4377920841124876663, 3816206760439007336, 17150624011379500381}, + }, + }, + { + { + {6266830413981331818, 10890859480409122410, 738708598357264321, 9241173142142102299}, + {9152169484987657321, 12122430118903337055, 14270062735458703743, 13877635605034675649}, + }, + { + {4572419849863661964, 16330741525817240677, 5456771007607263420, 8798510164381810403}, + {16547183593064549865, 11355135595370359779, 17581910791451710925, 11684604415749005488}, + }, + { + {2766130068233451740, 15909689412657372214, 3272828023364980896, 12907534005596438003}, + {7065629942275705493, 10609982651084321649, 17330343421617897811, 1746246157222856918}, + }, + { + {13168953859078137190, 9072500190247791267, 11090199374278127099, 3503847851309060744}, + {14395788825673846582, 15073993563711333791, 12879874391706003251, 15417028700542288171}, + }, + { + {2686132933630431595, 334448852204016400, 5636563341880055087, 3897420469445246068}, + {10569177829735084588, 8244586887721364305, 17973493209847502315, 18083956436923498083}, + }, + { + {15514509130323617046, 9833490355170899102, 12028021566105512521, 6349458533674010018}, + {13470024118569549588, 7867188201997717819, 6110792121234766402, 9917858515766574695}, + }, + { + {8273062939911446888, 1936638151089648185, 44602505720759914, 7839132833110815763}, + {13045756168264521992, 5375972549477973022, 16964151563535745964, 2871770426902555432}, + }, + { + {14164643693563803212, 6386904235704679249, 931435629437735510, 4496152555914735639}, + {820099532545743339, 13419988718062417698, 8948965620484833159, 7238410427920554862}, + }, + { + {4387941928212462673, 8023190031094282215, 12322462122895470016, 17311901330042910195}, + {16445894183838823370, 690424095855074674, 12820742226551488738, 227935274674223825}, + }, + { + {17437729542205914525, 8439533239207225162, 2862942422640746698, 7340866642549630610}, + {6770451500989398335, 17262212260581413381, 2156505157624055602, 12195119268846383898}, + }, + { + {13685370053507732180, 8304030489296890211, 7042719123662732989, 12115154796394040286}, + {10496877583013829980, 8909625177349683785, 5268451666475070682, 8910488385056259560}, + }, + { + {8874918984373509240, 6652428549855789281, 14866714872885601270, 12093494664302554643}, + {10149999253136441007, 1611873554177023520, 10271627298853910516, 15171882630355491729}, + }, + { + {17085353800722834618, 3271271583189511718, 9338466116389304614, 4685545953421459012}, + {5059702655119414343, 201476627889215522, 6388612869673101372, 8357217932305360896}, + }, + { + {1836621694151238424, 11438765101326043062, 5537182303007083642, 2657011195641217678}, + {15370176245454161308, 1478361893117141052, 8729368992402422055, 4807782542738120272}, + }, + { + {5084555197036037383, 500829604818691390, 8128181767026348964, 17895639808733462562}, + {4138748420878083709, 267892430674902987, 8954358455330696651, 1946224964877667668}, + }, + }, + { + { + {17561670470565298976, 9524122142014309347, 12619871254022879995, 4098610542031538614}, + {8338691110372464881, 4378598564044777665, 16435680634249352743, 12067828180476756532}, + }, + { + {12574920924242276218, 18146097977073890534, 18281543194137545725, 4432773597060264867}, + {797962164984225968, 13432184750641235201, 12394976215803938078, 3054137600383896411}, + }, + { + {12910897300898239001, 14116919300756610521, 9737100313909655285, 8792063194563201934}, + {924297264228895146, 975866810375743708, 14953819883516375119, 9992561966868201517}, + }, + { + {18270562314314829224, 17574550722906577917, 15522987576586641271, 4200899284963891561}, + {15719788437321868967, 18390235318178988753, 17371818886753265385, 4583380351670429228}, + }, + { + {11290716045321163897, 423611636875887759, 8716385793549629027, 8029377844845093468}, + {16573848460451650185, 15094868140191104543, 14624483608434776103, 9086586764934160662}, + }, + { + {1320522168839874087, 6395673054871725696, 7793960979093413321, 11402054451286901177}, + {17278080290632229040, 3823680337747309837, 7840042035002848151, 17839593774203285281}, + }, + { + {10024545625018137606, 3780616370895328213, 1516632588067435378, 13846630703933575818}, + {14323905768888574358, 16062987352815864444, 13444338098535013457, 13400662018607341910}, + }, + { + {10102001197913431240, 6211688443233768420, 1986665099237206297, 9248907879269017005}, + {3081890249882755206, 7828527646248386813, 12676034092230326487, 14655968027461080131}, + }, + { + {3763532248936424432, 13507960710132312440, 2003243330622949364, 8723351916784911918}, + {17411870179533482591, 495549359712213584, 6958432541445845486, 7674356092204128350}, + }, + { + {11814337248412299972, 9347461245743305200, 15456560932072269534, 9579754357941936175}, + {2098168907840746456, 2063921976437345588, 9267808714920405578, 6482702408130663270}, + }, + { + {3313415711246730386, 4607422129142883607, 278072683866121896, 830840258180061490}, + {16961959739026004139, 7896385585906900106, 7610238284391475173, 7231671772874233939}, + }, + { + {11464797300361906821, 1444449385286554508, 12433005157477847389, 964895564896662942}, + {8457290958728547067, 7044433897330872257, 12292673928275053405, 13679355097865192207}, + }, + { + {15352304695586484723, 1527883079108513336, 5890042963344522083, 13407971103520766077}, + {12385239629152188662, 315706510218287516, 5361117161753711484, 8824676525356150938}, + }, + { + {4555925933619499493, 14889603365479712329, 15898222225673484215, 878884802170861101}, + {430001626591485427, 881428142547721183, 653855015067704092, 11378990354467312809}, + }, + { + {10219225570653005145, 9205374019534090202, 16828986596058027743, 1089575570166892706}, + {3079144130112884386, 4682944567048139400, 7674497449298779575, 14137535283566239898}, + }, + }, + { + { + {13266892287530449189, 2232961926857263527, 5934654989155432442, 5415975493246016158}, + {17117784386882463158, 3875398271691758986, 15755743581177209843, 11380746535012415659}, + }, + { + {10162459499000477259, 7534168794800651527, 6320985751131807192, 9263840233901040421}, + {12178625283764017250, 13143797113231152006, 13089053551699608219, 13480464010111258056}, + }, + { + {11426681347395118622, 17135867298562042628, 10870734720453621112, 13803364322975322217}, + {9740527283062276630, 13765238480893165263, 4792349632705804116, 18359029140065847048}, + }, + { + {1420251412241033168, 6449255753238336368, 7468624722117319576, 5716072259994197219}, + {8165015263320602150, 4757529151848960259, 2040364517493350115, 11069642333484542749}, + }, + { + {9434687670958330812, 4808705744496679962, 13910334628239183613, 2628594509406050235}, + {10055911465166862298, 8069256921143792190, 11886968715847498191, 6351594160398684406}, + }, + { + {5472832021993175857, 6120966193470238758, 13156950075464061259, 14833372202848630444}, + {5760885723102571027, 18022572190906170343, 9870918995920897221, 9546055667466056471}, + }, + { + {17124591880405051324, 3379747334483646957, 2084957978131092947, 2413497199486596627}, + {2867893699156486423, 1357836849049583382, 13607307985344221035, 18039194570940763745}, + }, + { + {13230815692170010235, 10662664037814374845, 10120384214921531334, 8892863196093018212}, + {4443096401408136417, 1896901619181196514, 739574867683694091, 11233952771600927581}, + }, + { + {13885878918475208407, 18415131106660406656, 14362601436612948914, 5740711586144226035}, + {220574937152712384, 16774016249557318959, 4658351269477373440, 7890975779439252404}, + }, + { + {16628715286876183012, 5300385226682547206, 4493053153469218188, 6690552861098862065}, + {9359345201611660030, 17390357193161728482, 9283655448484665614, 13747647357786913441}, + }, + { + {3101241556869117917, 4731590937333975732, 8347709942856514723, 580858462407103829}, + {8937550160715031857, 563888416351720575, 6928865729903641398, 8295908905021542009}, + }, + { + {2219303446125808132, 7766409607764464233, 4492816761527421087, 1687012079818776091}, + {9967512906892097592, 8099397263797608226, 264054732854154094, 14515622825083967497}, + }, + { + {10586626338424063837, 11285305220583812031, 1552873676034063335, 7108571382532772330}, + {12077600502438115659, 4925647731241250576, 887903929602864140, 3575833277214438245}, + }, + { + {14685642695197717757, 4830460343095831969, 1748938116371486214, 3212377924501398108}, + {7575821759023381902, 4416593227203343304, 17810665332121047202, 5387420006905173437}, + }, + { + {8644732068940188724, 17116805484232699355, 6611042643736763845, 12686480611232016266}, + {13422256101258226329, 15901664205323922499, 100273141428472746, 3184681836469139902}, + }, + }, + { + { + {2754563581284692865, 11257360722362829387, 8254261291934606879, 10023569920325096229}, + {7980898855627864603, 17162063449612285703, 9275759455936104363, 15936804738099638644}, + }, + { + {303387668469489035, 7978391052264888020, 15413722057350324494, 508608987485166058}, + {5585753287556892522, 1344134516582665443, 15144279405777509214, 17014353449841567149}, + }, + { + {12518577022215294774, 11347384788122950558, 17122718824958020364, 5431993665805279177}, + {1445831254446028321, 9845654210244803480, 18315778529692612284, 930563922336183289}, + }, + { + {4894710987714215219, 15704993603878996107, 1606204036324478223, 14308635149530198932}, + {5026736228773269251, 2911689442372084137, 9004077539360196849, 7770049130277452000}, + }, + { + {2745120518194234905, 17255944807561408883, 7371907591838942770, 11781525288383871227}, + {7814952754785494862, 15022715213812536212, 4112388658963418656, 13703771908397991335}, + }, + { + {17455440140812341569, 16738670164475421762, 13259904130186215994, 2168106064304872507}, + {1969289843772256992, 9025317999701057831, 5835661391798891929, 3826587698101558069}, + }, + { + {9149648374608464235, 7248346993716635643, 17283919168525322365, 10107681064815728795}, + {12176813938029507719, 15110337574289033068, 2436453685316043712, 5876967059744625564}, + }, + { + {6197919059881189313, 3300993078638782623, 9357667752372201437, 17688129755135009447}, + {5477090746558113696, 12602024521188880300, 15889961935507293355, 7135039746373941272}, + }, + { + {12561063426893244305, 3079971284510744316, 15695857190375815873, 16730673956207425338}, + {12065477821845465116, 13846158368121919228, 2126156187526559500, 3005167441915916768}, + }, + { + {3858987859895327040, 17043903959888117395, 5861237635520080595, 3292646198413575902}, + {14286644557048422360, 14346409530388980974, 12583555046601155161, 4665981927428063991}, + }, + { + {7657686120974201842, 2388299767028319466, 17934808017791217639, 16708640707026372313}, + {14122341266134976486, 9547124998857374491, 11194069918436025923, 14657538980930727877}, + }, + { + {18115789712912297420, 6543740714573413570, 1955886376702349613, 14736853369719086334}, + {3914330395250768396, 7607848156418885173, 18220633528980056514, 11930952850158858930}, + }, + { + {17010681753474701341, 6961088634819162945, 18395881317121515295, 11611411242007267179}, + {7996717433149311639, 2687736005475404867, 15340214362731923149, 7116441414289074727}, + }, + { + {14302198697220662403, 11915041511943922518, 12363437164440173650, 4047410026894059083}, + {11439743031696133447, 8776097395071907030, 6851061783357383945, 16484733576581941012}, + }, + { + {2861660066704264713, 16453202148771053225, 10039035813504063627, 6275446616881871868}, + {7150609984920482782, 11100941755544354363, 6219760433202580646, 2875377482232912143}, + }, + }, + { + { + {15290817014272444879, 8012864091692295774, 7591940515496590516, 9299619125326026848}, + {7297256232167521068, 17861204372399797627, 3100022958796565106, 15313770879200204613}, + }, + { + {9902363248877274636, 15776195244792726061, 1935342462634574355, 16572507349421626602}, + {7503944294807242065, 7454248748618678609, 2837392985175901475, 16494567631149775512}, + }, + { + {7821919851875204434, 3437243050078433703, 16281279739393410040, 3105985403882097775}, + {6392071520880083076, 2042340026857542253, 2492719020444109453, 7325465357665053546}, + }, + { + {12299242278498309265, 117303082144788574, 18382936515565701803, 7941141688858846015}, + {14923823358299367958, 15681089039073030752, 16878721085421212785, 3933697483394042011}, + }, + { + {17669228922922186836, 6423621568318435743, 16298886067880336557, 11009276012664659704}, + {2934438101395245878, 7492928446481808311, 1311515713186855284, 4493146166488261630}, + }, + { + {14009653500169461120, 12982754496644678513, 14586034645437015762, 18126832542767444974}, + {627541781236454235, 3801503508930355635, 14654684147782092084, 4179096323459534629}, + }, + { + {14829342742512426992, 12453047655591346244, 13146459409240287380, 18077963306248855764}, + {17149389409735171474, 13591892902058002302, 13872587256559899629, 15878632005942819501}, + }, + { + {2878536922988449879, 8819365314325664735, 2696760638950720974, 11357179421800829605}, + {14730809809256560583, 16277258726425730599, 13189689275745970592, 13769784951430309444}, + }, + { + {14706229979050107962, 8679247682181027680, 9705538653507374238, 12793525936716723768}, + {10022723640772366793, 2224403391050849804, 11511158380587667232, 3250960576892370870}, + }, + { + {17671892277522139639, 1384260767972381005, 7623504419117295292, 11197930232971575240}, + {14867469242175831789, 897596747715880677, 3892483173599058531, 13453254609965163080}, + }, + { + {2690362926234343281, 12134546410412600166, 15715872358030533545, 18160163251393343275}, + {12233720002415141519, 556081697748597124, 1099809960955937522, 15489604457800724223}, + }, + { + {10292669945637125918, 13595563061674492799, 18301330068714272653, 16981073598172019270}, + {4022713583718555211, 847970754090163894, 12867993617169467387, 10021141621864633865}, + }, + { + {5408393826294570360, 16896935186698126584, 13028972412622343885, 7850626233281656805}, + {962076344521148275, 12332350290936839731, 1774588207039851940, 17877147526933423087}, + }, + { + {11625440764115934244, 17372224561416726989, 13457342366450471135, 1569549943944038472}, + {17753658357081801983, 14093490077993040859, 1282770820260996510, 16402793994329437670}, + }, + { + {13086054618104175873, 11714492854942191582, 1743587223054035136, 5474094059388998723}, + {13150833497051757606, 17129392131927259958, 5739140380294248045, 10239738807213437974}, + }, + }, + { + { + {3631886121917081375, 14286411187847401959, 1546298555066841633, 4790996540037176549}, + {9541492152219486842, 12304868498960755609, 11426775785781090329, 10793898029125361155}, + }, + { + {10932352970046201499, 5875690226460998551, 3699681560657289718, 8665743594825198441}, + {10232089728487302472, 15664572298733091969, 7267222702489958195, 10552093353886118696}, + }, + { + {4008236965647744142, 8547116629188387980, 13874587567755370880, 12696453513706541959}, + {10752386832421030566, 365775083075323708, 14295272684753058141, 11024897725724291722}, + }, + { + {2399232949134869057, 16408469118941953277, 17229778225562184411, 15990256768949242309}, + {10694906341686584836, 2816242351659628719, 10794163145486835660, 15601904974333104002}, + }, + { + {1158521281204350113, 6232098057848694897, 12517518152351190341, 17852831094628421272}, + {11653774695260269881, 4420518556213490728, 13835371272800239099, 12119809446886544909}, + }, + { + {5143546864201185527, 6400878864024957342, 15513803558106064076, 6712861984922181478}, + {15623960351786428150, 3094277713920675576, 6184647748693682810, 7857605928718754519}, + }, + { + {2219152199405421709, 5367881810186787185, 9606063680551349934, 18233690822105957780}, + {9941441403610160291, 14996958158691873775, 4936282940888570414, 16608409936766385729}, + }, + { + {13270099407878039596, 11569032926557804346, 7759575992876193458, 8239088820951102451}, + {9633607727685959064, 9775909232917811341, 12297921731498614906, 14756100221590046549}, + }, + { + {3076166255574886489, 5587891405059542759, 2449830540875545916, 15616237426524550707}, + {17820334717580127167, 11506219580693301288, 15242532286743473103, 3266057695402840388}, + }, + { + {7193168093115966016, 8050992763687139302, 9734357192061785185, 15553552690657851227}, + {4632257996795951659, 1007158456255834509, 17052740163052114844, 15619284827675470063}, + }, + { + {4224824291132201768, 5709863556852834901, 13539485156399791894, 10330250853413634451}, + {2817020820518906625, 14306724568884734914, 10421968182740721623, 6943068506740047695}, + }, + { + {10830476567180688368, 10003074695797360184, 5589380226277136479, 14952961630386717087}, + {6354514974022878533, 3426762794422332369, 17950815054280597743, 14940277403242978595}, + }, + { + {14582622177810553114, 2819236216667324430, 11333005326119114902, 15900677556115860419}, + {12265999577465855236, 14521351376076108710, 3999293994697120555, 2365385934872188434}, + }, + { + {1803647016552158312, 12981833819573589527, 11371133227762071, 8210800033974528109}, + {16927172347295306236, 11674533305143999306, 1514600283696801303, 17036724058500952986}, + }, + { + {15551380071341300893, 1378878534597097794, 16601031904934455368, 14515377519758777108}, + {7039813638645241317, 12524221355672362377, 10483072291636269482, 5711815649533531303}, + }, + }, + { + { + {9246769514475702626, 5788284997389507365, 15857897362850327403, 13864676801095094218}, + {12881526722328523267, 2620841421323221200, 12599981775316397124, 12820989846844560040}, + }, + { + {13066648645100247757, 16727492115601921665, 15749471761440498106, 937594351871983779}, + {8381111811209734349, 10884357918725639691, 781591570669492079, 12778743765298428266}, + }, + { + {1797915488494232282, 17274756142259274463, 14207994319179101777, 9405903752538915237}, + {9001743317941152797, 15048752608061590843, 4925745663463425863, 17143694017177138485}, + }, + { + {11613437975225156304, 8619196433402562266, 11907033287998837424, 5056904365610561965}, + {7637552956459333558, 2827449950719061527, 9998507085256853501, 9238562885525900325}, + }, + { + {13246436769495027717, 5445015753017977819, 16266739009580878036, 15566606095998238977}, + {12196078605380432771, 4854324313875295137, 10974170498288217052, 6425550765546527417}, + }, + { + {14574824159194628650, 16992289415800830701, 3499062703303067574, 11220872042664151226}, + {18135860701984580530, 13630928571014923388, 2913126838766947469, 15869180955632349704}, + }, + { + {10621010745328025245, 14637275395423748577, 12928463178963493980, 3270672471462681194}, + {11765440832075775157, 8138439106739837848, 10004644076263261924, 12582897670868871780}, + }, + { + {9605391611675301152, 14014632424042523224, 4638465078692570733, 3013469722048440965}, + {10972600060210514686, 4497572559400894366, 2652629676209366276, 15827846806499715082}, + }, + { + {216774559418075105, 7056732230404238374, 4342481467357759950, 16143194646968227790}, + {12304857685680249595, 5021239809847286634, 745754913624924064, 1603290801266214539}, + }, + { + {2784418922013631805, 3554650219010546629, 8896448905401216908, 13445015286698819482}, + {6508982623352460996, 3322529327934132311, 18417788670080975365, 17554108945303789353}, + }, + { + {17620122226715347133, 9738429733440215024, 15577771434516492888, 12422193389576942718}, + {18383756008252443605, 12736926759685644351, 16981429110294392086, 11999528928951986433}, + }, + { + {14489177617081844909, 15995916840320959685, 6361381313838994395, 11146176143708648759}, + {17190512001934479207, 8406914945663974955, 18073221191428103088, 14075266763636071788}, + }, + { + {11493260321718935244, 7134447477334726345, 10489281872281557152, 6145540581503915475}, + {4002857892747271740, 5167943945955725680, 2892864850826359384, 16887114279977647596}, + }, + { + {16493058314197913501, 14642843949567816202, 8421201635021034279, 3645913604138483317}, + {6127272877310948153, 3660286308390076870, 14343325047340052700, 5355450922054278073}, + }, + { + {8426383571761073988, 17627146217941553397, 7396223609641674418, 2402241526082789613}, + {4067059813672963823, 10306840429023537942, 18342506396531908477, 7249869764848707701}, + }, + }, + { + { + {13937553904380032591, 9165760362893872288, 14159606902675650669, 7794101517494576908}, + {11994596892880464164, 16211278212275417034, 1568324133241165712, 6579463633356173526}, + }, + { + {369660229032730089, 11851915833529805698, 13485269529443969890, 1270120511649175022}, + {9128783725626301238, 6173048611666804214, 14151404531169195672, 18241008099921643437}, + }, + { + {16331025972320545471, 6852381640421896437, 9324740413214863495, 15718339035381717722}, + {1521756232012903545, 5431459367124818841, 5364830919043042094, 11104748870982011750}, + }, + { + {16226789363155700046, 13734705589524056856, 9629995513492843231, 2636144377026081617}, + {1233405076007260313, 2119672919365858964, 4932766292290315579, 4185117177904214366}, + }, + { + {6556637108078954923, 854911879338322327, 17335608616262058670, 8212786550755149003}, + {8111194132924193031, 15689965289081013375, 16641361924274000294, 13131032775030004856}, + }, + { + {8653575060724839982, 11482527594744353256, 10837608928215660048, 3651629796762058243}, + {7098570919231943894, 16903422906687575782, 6449467519885582678, 14455694979526406871}, + }, + { + {781149662684377075, 9606778745577048892, 16642923833572014687, 6804945833779567806}, + {7749938807818369385, 4119995592971432914, 17172069782410404367, 11558710124840085255}, + }, + { + {16996170392430604056, 2476294162951949891, 6677439492116109133, 1649550562276235959}, + {7307278264575968221, 17128676264244010843, 9768062299436691373, 3825325732056225433}, + }, + { + {6593955722549970555, 17069122731812152854, 9033349482403834703, 17728559655579364768}, + {16586780540128534825, 13307658170018069777, 3129405955501687685, 11183053750385689524}, + }, + { + {396019325068553604, 11523268935121791712, 15099363117146465288, 15263791092270534216}, + {13442484747453660303, 9234120847672647934, 12419564747087042045, 11765927783051357577}, + }, + { + {6946885342337567475, 7614129273290805579, 5593360004251714058, 12661112521307810378}, + {3109170497657341517, 17179338146382046416, 10757457188650866858, 6777926602245453235}, + }, + { + {5861627228365499618, 5011684805137210454, 1579621475012951778, 11535371650014354624}, + {12847902922833318241, 4997014846790385136, 9875988184618650628, 13094082946822736823}, + }, + { + {2372542806512167707, 4770713673953713652, 14348746494327256696, 7497346441434630132}, + {8937635379675246570, 8485257033326447249, 9021969910533595955, 17083952234675640995}, + }, + { + {15253158548483712314, 10967825792345015198, 9742716807127259344, 14359543366972625129}, + {6622650705673586588, 10738437674137632549, 1628663686364470696, 6788821495127737255}, + }, + { + {10456049238997614164, 3762844951386993276, 489305084297229810, 1360312650067674972}, + {11869321173985817492, 5817931657599210177, 16741327479242559412, 1205037582258757668}, + }, + }, + { + { + {7109145612337154341, 10502845970727626855, 6527587047878193251, 7049690136888681718}, + {16750703006415156202, 2559311261501721445, 1222802194566919230, 18019462938525560766}, + }, + { + {2592184418896595488, 1723751460114310463, 11198512454461769811, 6203707848404803677}, + {2601731234271436477, 18186700975610533226, 4757569424831899615, 13359873383138312209}, + }, + { + {13904640252203718708, 10747313134117021792, 14667070697514384141, 2600977347774743546}, + {15498986940124021079, 14740645313274577011, 17403811028932224808, 8060102076475954685}, + }, + { + {12990649636107730851, 13002224935892458030, 4380799638612122791, 7935443787987894924}, + {10438069978940053126, 302419699431148366, 551508078777729872, 366155636877501719}, + }, + { + {14734735764746786753, 1378251478826083755, 13509550209468602124, 14458158239096821346}, + {5681313138148713219, 9054039627425609375, 4235536482830620712, 1502753755874778370}, + }, + { + {8914021876030553161, 9071747156187788379, 14974736924255494885, 17070198435868341999}, + {3643991391224035758, 260637732328275649, 17609644917816078225, 2302996326941944665}, + }, + { + {5888744936142942064, 17277140802638358763, 10290028650289820825, 1940657436863195045}, + {10796401239257150661, 7788083050548605852, 13474393003015663489, 8961936186303685357}, + }, + { + {16407225233842256953, 13423683834633513951, 17454464203550700633, 6033758555290610449}, + {5063673994339442907, 12250392784929419939, 5954485814444410119, 10099095370725442279}, + }, + { + {4687621216548073298, 12683256962895584277, 1406415612737291460, 3991320149877222007}, + {403384179417053146, 7072351635192146705, 14388831570324308780, 2518546598792352745}, + }, + { + {2866701220158780648, 14345701180700655413, 10383205903323525163, 14561034237887346332}, + {4525630512028460468, 7470042867870921036, 12498636959757093905, 14959680069767374094}, + }, + { + {939355076355747784, 236998652239230884, 7862332576114728232, 3008745396212765985}, + {16892515157128448879, 1688671543548974140, 582235491724828261, 2879861045707356356}, + }, + { + {5793581539270397654, 12067972155882240315, 1914416028486337582, 2044052608129533771}, + {1045680055817519578, 6183307954634642810, 1115903654002488241, 9729229622559998051}, + }, + { + {11505233554542243613, 13650372171621554098, 11886401428750724176, 2616122636264787282}, + {9807875738265530891, 2065326856613209663, 3841177149705795822, 12478836916087572836}, + }, + { + {8725096612265348131, 16959754534248500306, 3934616751368449170, 887912345061829880}, + {11410178859948957868, 12867384504930748729, 4367798270196663137, 4359910421693489126}, + }, + { + {18221589825782480868, 15875305463032670629, 1054133002549446970, 2220911650204683784}, + {10874691797030180071, 13903803155513130100, 14873882741737344436, 9374498718172057556}, + }, + }, + { + { + {4471613312912718060, 13601785177495103328, 8083849806888905297, 9053545412554844461}, + {1876605639999952155, 6124537911475118673, 16877891074567085688, 16541720065079132344}, + }, + { + {18138305348849897995, 11498878557125400853, 14125346336359365201, 11991638807788804369}, + {13935355764550912568, 16209147067155729660, 11086190285777019292, 16727288863943596410}, + }, + { + {8873152377611229668, 6260821826956744083, 11489383533808918262, 6585112195310961861}, + {7365821041919648819, 1936165695028211587, 16164747634991415711, 17957320776652490392}, + }, + { + {13065030057172289846, 7278765836407486850, 383827150208081081, 7832055893191054601}, + {5249323286889945617, 1631661912887095912, 4431088469837785451, 2866263172993336891}, + }, + { + {6140213328062333551, 16704025329777067037, 5839832043209342792, 9196354634862869885}, + {2735762290983671190, 5323501742548818139, 3199127466610501482, 6719610946615763192}, + }, + { + {4032564124345275293, 240208626666701335, 10264845378648897042, 15608289126091352415}, + {17866864241918154829, 6207477318890336372, 491708931325462670, 7002400618323099260}, + }, + { + {11507747783030541234, 13683043390668171754, 9924966309328785763, 5549516466627385909}, + {3724001483041449858, 2408778220985427590, 10510707601023430105, 12862520912519186496}, + }, + { + {5012372868660694231, 12033652755433827667, 5960732801180177919, 6089487525155575261}, + {18400192045204062277, 12754175136438960528, 6170965736016609163, 10141374482047067946}, + }, + { + {11781193922347227447, 16937876011211881637, 2982972111293427964, 1728244726890919596}, + {3327997232304084768, 4754833121145407334, 5871027825507908591, 15772493911709624273}, + }, + { + {5862944033912881884, 11132730978666088350, 12167180155548291888, 16449838286695349787}, + {14399676610730016345, 17071083123672650337, 13727728787831175379, 7507765123422748291}, + }, + { + {4883057314704644529, 6606742732149784343, 16070555141087563722, 8408294891669305261}, + {4298316003054547788, 1573237855902568238, 5357176885445018289, 5855732582172939202}, + }, + { + {11721126538980357625, 7216004194033429913, 12765889884935948315, 6003399149613653734}, + {4571046290325663920, 15023470461830485075, 11463513436288928362, 16135217522406374542}, + }, + { + {14300855104129153291, 11491527690078786162, 5674183453812271017, 5044682546652747711}, + {9153978680942338831, 400454762074409409, 12351470849648616331, 10559229320903248832}, + }, + { + {11839166519633311143, 16489041153719856002, 4820713204385149226, 13768001962143023630}, + {13107713406478328396, 15471245828032402460, 6733652296473831544, 7665657127090105428}, + }, + { + {6114372925011600760, 13061069979571997963, 12156991017966837826, 12403009591138383583}, + {5761958709898299258, 1907771304051897263, 3007439379929412593, 18410854883912163962}, + }, + }, + { + { + {10153847769616409178, 16591913677701651064, 11369151065084080884, 9493662847124813178}, + {14299126668179023903, 2451525064998641745, 16055696673728703463, 7600736037142850105}, + }, + { + {3339871688614476269, 2937156932445032796, 2071344655111136329, 509603454456841298}, + {10929109734329673813, 4531629375826317764, 1802431569220697099, 7971315018970882891}, + }, + { + {831440329504272059, 17398063681351066636, 14954668702259408996, 5717183520144440084}, + {5683898996859918421, 9613688159291425744, 14476049487507222229, 3689544236835488368}, + }, + { + {4307546666223047416, 13914498777427309061, 6812156124789414732, 1680174913762530491}, + {6756325174405757110, 2535144759174364990, 11263393915003278429, 14767595249676286403}, + }, + { + {16671897597823309975, 8846923580617118936, 16420413907022376284, 2344779928765541883}, + {13727655669851883280, 934227091954463432, 4722713881950047653, 11812583008287470589}, + }, + { + {5321392406277114518, 347488367118035707, 13877286915167943316, 9829617275563347891}, + {12220860524024630629, 12190721936758412489, 7308208895364574537, 1525158119497637419}, + }, + { + {12984508126047021344, 13884472939864196037, 7382834581395586970, 11638480609720520178}, + {3822030693056621440, 16565826187005934945, 8411123762207988382, 1177726217844912325}, + }, + { + {6981289090623415465, 8930069945493884157, 8223216504978132408, 796477795300774057}, + {3120155459209743472, 14825603392456550470, 3711879425019804830, 11041054473536223927}, + }, + { + {6533202055887887500, 8435346764005128028, 14910943752455571727, 12906760590440667071}, + {6009159206340842586, 15232286290711710102, 13101554303130256987, 9535887764075322183}, + }, + { + {2364828287094520952, 12465747625792776806, 2520175043973011525, 17224593222741233568}, + {1891958595100476046, 14167979679885431508, 6587293950576996181, 438078840840804918}, + }, + { + {3740623254035318453, 2026091438664349886, 10842473205058238690, 5471257179527938221}, + {7725900701946760330, 2830662433803069280, 17799722315873409980, 10759084277615005300}, + }, + { + {14135544350792474553, 6171419888118563156, 12495035851387242130, 2843310747449412555}, + {5668766087526340552, 10117858698838396246, 5181027414039980750, 13247490124270426}, + }, + { + {5630566354382744149, 13019515676216329576, 5170054423571001981, 6980215251505169036}, + {12147009277250683724, 5685374899516102781, 10470553909247052379, 13479624060240397189}, + }, + { + {9352291669847160009, 8941401423217216209, 14488820078509299610, 16185610851702419585}, + {11995025321082820298, 8447817180287020945, 5861763576711981236, 14278368152612939946}, + }, + { + {17266177108677586607, 54295173557875478, 6565771227548453510, 11327083086584790599}, + {2516266639353612660, 16450448808532150212, 4693041555468884719, 10262468795248362309}, + }, + }, + { + { + {2365455792963674834, 2249234228455309648, 5237136544555745182, 8814246419234451463}, + {13017813702607013347, 2241193992640629733, 17982226236989862510, 9800528153239873634}, + }, + { + {17271890190678399664, 284117971978206043, 14999643475704678808, 6264699496666119083}, + {8859934981351804429, 8300880062060532031, 3667839168820458685, 17133003164910522197}, + }, + { + {17791633957402883820, 5938849497629314459, 8356801465373786047, 3163889445599730677}, + {9723709910898285412, 2841967670768995554, 10896757438566636700, 7434996874241771203}, + }, + { + {14086272070125896854, 12009239107306499026, 6592816798466831203, 11371087141421707743}, + {16277593907837607793, 16449564916599232060, 17471042072158213549, 11953382410698485455}, + }, + { + {14613304240735929191, 7658770973133328064, 3028731168325633068, 1486737152001467114}, + {16715835021406106944, 15214200823642287507, 18441898204110447697, 5669963154424393607}, + }, + { + {8381651800836461905, 275661552864412688, 5548629401959193001, 7174991431295718071}, + {7441251258233899268, 14052832476485122412, 301250917807487282, 17797202428295526090}, + }, + { + {16448089571044203401, 1396460397790470601, 9796571033221459545, 8162511506983092708}, + {13893406727199803081, 16188892369453405032, 16023105002157964343, 7061289566170423383}, + }, + { + {8743817608749172620, 7804846024944300667, 507107926259802795, 5258061329638283805}, + {15071070675288472598, 1848743106176521296, 16295570828486620412, 7409462376590083349}, + }, + { + {2825832734356158434, 10662490421734807455, 6363563030616301959, 16552149102037287266}, + {8852342875874616869, 16848248230809388411, 6581680050166700198, 245046966305064563}, + }, + { + {7828655274510399422, 8354801505584011854, 17818478328917068523, 17325245990806811268}, + {750899848242404370, 6729023687199559366, 5406329621088392947, 9196565205678366888}, + }, + { + {8064539304829538257, 6441901327220658696, 17278408443193767018, 6094106832683864460}, + {9824329910822370076, 5272517980512991724, 8211352561755619726, 16303987070546290759}, + }, + { + {16798983177239698753, 12189491924433050580, 9517619110936281609, 17570406314312177597}, + {9873809692789257777, 7539953961664846819, 14652839873293130968, 11082914471633564328}, + }, + { + {5471221015674785794, 8844747884377425274, 10084666525179707178, 11340747033059217003}, + {7295797213045550755, 8395678759725657352, 9654316500807954493, 9062353099996695484}, + }, + { + {4588282548354659427, 7317148840331807496, 1344326657487996813, 1542409176821028318}, + {16178223850158437787, 14916858636047869579, 13512744779273961596, 13549205429423761570}, + }, + { + {12307321769285447055, 293357554223804370, 1007020265087773203, 701738899338647839}, + {12276634770118212432, 14777553112070534726, 4541693432120405052, 9103025487888313415}, + }, + }, + { + { + {5757832545805155636, 17609080533053427627, 13855662030602089892, 9622498683452213297}, + {12281586442064581946, 610529441714948581, 14740357477019436626, 16983190111725558863}, + }, + { + {8470173855499872166, 15915210069852758660, 12368087246231545517, 3867174158581293223}, + {9082358201271846042, 16663463402757176964, 13740908859955866819, 7748969412274962298}, + }, + { + {13375424826931892789, 8508645806391261552, 18359272328758476903, 16433208398005282080}, + {13071423254987294580, 7999383023651164492, 14514701556577587750, 4848295889377673720}, + }, + { + {1020519568493754982, 10467781020270669620, 17607771250627508499, 6620300538436640218}, + {3858527175523168333, 13798129597334232823, 12495322651937391008, 3926713306087152023}, + }, + { + {5116038770086590715, 9943789276328255827, 13715439407309914230, 4887040860130243503}, + {18288477612078228131, 7640050573721350378, 14537362862524718973, 1658575506924200900}, + }, + { + {18400486168653423966, 18026904540891591040, 2037921821724043966, 18010956304511658647}, + {3751340308708032971, 16275459031633957091, 17177866831427164840, 1635431811339422016}, + }, + { + {3897330996014812355, 14347736534650088376, 16862404119462964612, 12216005411754788835}, + {11561909516001453735, 6261639657930189859, 9101978764314050064, 12280333151331067982}, + }, + { + {910276569977357717, 2872810615152156462, 1942106118995935911, 8734004121981822024}, + {13862118436432879698, 1912639548162720505, 13060137938875924732, 10642216911059510120}, + }, + { + {5132232031613377471, 3053931945527415993, 2695169719602504430, 11855046366025891084}, + {16462491222215366712, 16664416596202206835, 3077124688577987843, 7109495326459366311}, + }, + { + {3858762384693274897, 7520194928987242278, 4496744297661574884, 16159343214247089321}, + {6441167128044578145, 3604951495694157848, 3072075325567814428, 1964798869371174506}, + }, + { + {13689578474000942304, 8998724267038772595, 3350174507425430811, 15015413657749135511}, + {4848907595494161497, 7935644131326131098, 385849363817229511, 10087353746314516691}, + }, + { + {6067717601858189468, 10438404859927821308, 9991403870358837471, 17728358586134467771}, + {13476949968946830198, 7311235997042381570, 4429835371823736972, 17463216455983091974}, + }, + { + {3446799583712077997, 6763499387263152328, 9231082163128267527, 7733182914440272884}, + {17225092062157610409, 8163842076250628108, 14230171836718858439, 8195740716303697476}, + }, + { + {57759226194841354, 14962480748390190557, 2047254208877381876, 2830450574091058648}, + {14905486147404440754, 15792397930637469157, 16383409053580142957, 8686506861607761226}, + }, + { + {11120178572139812895, 11534611317577597022, 10437856602660752754, 13925966850017814278}, + {16776862023867799947, 17362554889424346260, 3408825299914455645, 2606150045870067742}, + }, + }, + { + { + {12109367644744157376, 18037756988516427980, 814572839386760074, 913616818805172815}, + {12974490864633240943, 5228203788953366069, 11458421156905635350, 14534725545904442520}, + }, + { + {13918155529832261002, 12953608416498491778, 4285102780598248527, 15853935066983430239}, + {2610351403194505517, 14905969693015035277, 12043976761492019990, 3883507340167876094}, + }, + { + {5439519346074792827, 2176389624009388617, 2631244572392601375, 15049241095214776941}, + {16292195309463965431, 4379169091046493311, 2454237863606964835, 16333960950959567989}, + }, + { + {10994470105201067642, 16033352651464686189, 15774427704233149170, 4596106024708523955}, + {8854068685612048031, 13529126595187822090, 11509928293490788309, 11620850709434334690}, + }, + { + {267621988570094461, 10587206279243947181, 11593510291287574067, 14787400314862354894}, + {4136983718443464652, 2976380359687256413, 11142324903811863489, 4610908641771667701}, + }, + { + {296274281547444433, 3085587185113256560, 12609265193181717917, 4535801536028989527}, + {3096496338675531142, 9292526016029159200, 13112825412047135381, 16663099831183411702}, + }, + { + {2767353193349225715, 8712112934471091092, 608599382922156785, 4028449356066786979}, + {17542394472389324402, 8680897831809226389, 7666317335732585298, 17261030852301003617}, + }, + { + {2068337952936280662, 6856444059219131741, 17213926210819196459, 513413453513211652}, + {5520465604253824995, 12970886588014924605, 12296275668437451137, 16808287251356954962}, + }, + { + {15914937173048753781, 12510295026185206015, 15954705664179129326, 9689253582699600268}, + {15356442010394775998, 2438265211465631320, 15141425278420483672, 17026865278332658671}, + }, + { + {775118291486058191, 14811108570252044526, 1277462327112210144, 1303109520734915949}, + {17662756477349124684, 3447822852149651619, 6150341860560710757, 13223916277431807977}, + }, + { + {9324118164416603919, 86833914568469678, 16815316898277944489, 5015780480822908208}, + {4077581079810359659, 6644887514971920354, 4892606269782662646, 12780428915404556278}, + }, + { + {3413637388791433603, 16937929882486384885, 11215805046681294327, 11559398419268924015}, + {11697258172757450737, 6137795229387768085, 3190984692021653574, 15347236891154706739}, + }, + { + {12504195828868930633, 14311735968635225029, 3580069346315758668, 12909891866007218579}, + {10780120525711488015, 17942431687417272891, 4966616543136223651, 11565637729828595342}, + }, + { + {12013939709036934636, 4233656138400235608, 5744753585886244254, 7800398410233442143}, + {15609887409465530711, 11633197710359969914, 4221051249637072360, 11317958694020095179}, + }, + { + {5703670472856822602, 8043375474958283103, 2470834322231268196, 13020386017071254236}, + {13795230438353673114, 9108571599173545401, 10145331563807416240, 17474439008571566321}, + }, + }, + { + { + {16430555432520738762, 11225321696360643709, 11777973654353154098, 13133115227828884393}, + {17678738157022850345, 1586660156856830642, 840647763693221003, 8645742354464326466}, + }, + { + {3598736754916501501, 4827022662021197854, 8203180748141933720, 10283251600632599041}, + {16186680658340956808, 15183393398087319142, 8714402370450665212, 13217902016653171217}, + }, + { + {11743016372336018414, 6125536020759642301, 16563280170798047733, 14529052521060111789}, + {15253502329174644388, 1556763737841306861, 3041940064290508531, 18020881359462953336}, + }, + { + {2297585344913389180, 13965959247788377604, 11341378863608387800, 9890953382689640379}, + {10443523266835246852, 9631856696811288063, 6944503116553031744, 10030824122780966395}, + }, + { + {6636244234467769744, 18284390012667441869, 722929822219329257, 3274166388651987221}, + {13177791837760949480, 2568122970128111127, 3477167651270374316, 11371867850093288299}, + }, + { + {12876460969864886954, 4692925517843901006, 17390372170975588763, 14692578774429957295}, + {1759864963511373267, 12016553435172103063, 13015881292003590351, 16187569590073958370}, + }, + { + {5868176722765418764, 8429364877332796959, 7785756492654137899, 14975349488807886278}, + {3272010964035218775, 8946396491617515063, 3774503492701710541, 2113917870331282160}, + }, + { + {13276631120161396750, 16968574704982977753, 2376454925072971568, 9477134218094425043}, + {13784622991820528988, 2074505569780291922, 14294803056569335889, 8759684036994631222}, + }, + { + {9884417819806228161, 10473583853313294601, 14339795822328931094, 8504498283323826917}, + {526127293629665058, 10891388783681447537, 4568472708151557518, 10369081088106148862}, + }, + { + {14875690099724520068, 15708131372860771936, 15063351920655636623, 13673754555867312132}, + {15920462627529593070, 9885706734937065436, 16823591115242423655, 1258777215756511827}, + }, + { + {8202515950988182345, 14546423651242108828, 14227698061016162353, 10918615690964448766}, + {17106085332738434415, 16355746637376756806, 990444867181428081, 15553043817355146246}, + }, + { + {3823475181283510630, 10848691050793796395, 6491636971888772243, 757676231362735550}, + {8973136455980928416, 6503381298194573307, 7834237673135397878, 10787325521157907075}, + }, + { + {455211601892268020, 1552688795129565862, 8165081519906588268, 5446810663215253742}, + {6750786745561416995, 6997284811902307211, 16012972729607911414, 9114458230677816387}, + }, + { + {10975008541567105079, 3750365577590028809, 13516995106985748006, 8919511738051569176}, + {12930984911878205493, 14293252788401143455, 1989517604536428154, 10167748824687611261}, + }, + { + {4403033949751056724, 8371165401092074176, 4457099049748166877, 18160854660487137945}, + {18090711188318162626, 2052332783995780991, 10990843822512572670, 8096670640545581193}, + }, + }, + { + { + {987127652983079722, 6872208513691823695, 10110578719299008714, 16457381243184327116}, + {10779072738879347999, 5965282398006505989, 18251577267494363268, 9321323379108563422}, + }, + { + {6119049170407437179, 12938407708038792521, 10105420405825346383, 3416306788177016826}, + {330648587825212481, 125568991290568141, 13857127346570918649, 4376080986981308805}, + }, + { + {5930434126597036589, 11240994623469578584, 839346533006694594, 10015087329724081709}, + {6285097815938761787, 17244606485954860090, 11523249727882012981, 7178451948850151803}, + }, + { + {16733615335426327004, 14833564736134873977, 15736159435317472941, 17560193966711884894}, + {4670172300306758374, 9477713670983496835, 14243955354032737980, 6459864769649694970}, + }, + { + {16053517698989562256, 2069464650596796670, 18305730134729303993, 1090863611964008044}, + {10595928817546105363, 11743183506441120484, 8584767248013363683, 9187452830514379903}, + }, + { + {6938579711827578880, 16268282168771714072, 4567473305742437221, 754548046014059669}, + {7773636946295303572, 8132380485366854656, 5054542590195827722, 6074347500754248128}, + }, + { + {3955857908381474930, 11852678900999621852, 13783017203403417097, 13616745777931267488}, + {13189924588414196918, 14519927295809952876, 9334100965942760501, 15172548734242885286}, + }, + { + {4869852132020793901, 14921212823114724347, 14342559113353033349, 13336827701782657309}, + {11168346789878684452, 9790480725902426052, 9171116079841529936, 9268902731763220711}, + }, + { + {4417372365016540659, 17280138652899703220, 6650972319709075180, 11252221422799491438}, + {6825784270383052414, 18308562203755695191, 4237445205082731447, 8485872406483449772}, + }, + { + {11718726714045105993, 2624508790343569765, 5794111482300008213, 12819216567095091385}, + {285329842793152354, 17257707863943097374, 16912487373614458842, 9501952033607497057}, + }, + { + {13074643344738491288, 8505193022029238118, 9932652098552590323, 267408114280737600}, + {14802861246220332716, 17506028737327736269, 15929083591675282371, 10937680132245212187}, + }, + { + {16688733766460131050, 12777635326299184071, 7769405825716531061, 12435979606514844725}, + {2767987141420672349, 6723940414217341603, 16114182069580717377, 4541113259200434040}, + }, + { + {8506371389960537559, 18031198550689409305, 11510251852995503442, 1923472385053944821}, + {6189904387119195613, 345664413118550356, 6439003191582953600, 18344385760549575361}, + }, + { + {5320548958745018096, 8341561189829530680, 3327828110998403156, 17981346269177513223}, + {14254804273025688074, 11111147827704077234, 9093333670517437191, 7272552282364063165}, + }, + { + {7587268797387514088, 4402481408866840263, 11260815389095334885, 14391444701764948710}, + {4224880318604689771, 2472148458660279030, 961218007313548745, 13826356220879831691}, + }, + }, + { + { + {5733697799130763963, 962857090393715865, 10538932452511329419, 3413281437172590207}, + {6635428480179771287, 4404718679994229138, 329074170931436370, 17746708206910902139}, + }, + { + {179238781994802586, 9017860544212172426, 16179187983079961859, 1380105261896053495}, + {6187003332254463653, 9896593306091975718, 17181949235068293496, 6820143159816507763}, + }, + { + {4652378169433586070, 2069013165869224423, 13972912433480425078, 2248203233787863058}, + {12819880125496785064, 12462800229583867169, 7969192387226362512, 15450728326339004590}, + }, + { + {11156900805411912784, 1737275748212365168, 16993486692205800040, 12538938066475152524}, + {13167476167764338790, 17373319366642541595, 6054831428930905282, 7118452124011953000}, + }, + { + {15319323094268250368, 15751569639563379275, 9174762389399453601, 5359273060607997116}, + {7548480167962649047, 4093535200286790152, 18255003581953064302, 17037929372197430710}, + }, + { + {3640693116491518731, 9689920283410066894, 16070225083132083168, 13505008973802466003}, + {750230942699692016, 15522838682331888368, 112268476925002814, 17491605970126192984}, + }, + { + {16769567946241955549, 17099752525969374817, 14041401861628609700, 13883170585376164878}, + {1568639950869924595, 7305902646691031157, 12536573783075304502, 12490145094151973568}, + }, + { + {743288751022377974, 9226164090128370715, 17669221687181604232, 1117842260351396541}, + {17697784451833850722, 14382209306891991103, 16951372733687268016, 188390802712613066}, + }, + { + {7332583781810119624, 11974900502289827649, 9825039434151224666, 13612433455140779130}, + {11167094757836568968, 148858902984029622, 4325547061862811500, 8439987427904092212}, + }, + { + {9775040802880336170, 2183956155792599391, 10102475962557589963, 14902149990037881859}, + {7528893974593517583, 18271333130592009124, 11812759747597590978, 3931581515688264350}, + }, + { + {7368734173241076742, 12419301291748626639, 10534790951032501149, 16676926058266807225}, + {13614593066288445663, 5547469267128540754, 5071513241190976074, 6206141439571986364}, + }, + { + {13268209255833199938, 16633146482265079265, 6044233937395578074, 1733872861371247406}, + {14239198956565602758, 4036306057099495106, 1778912298053970082, 6174082695927204648}, + }, + { + {9563897475320169888, 3828463449263891363, 4522408683909966848, 10085044841903958270}, + {15115863363467748291, 3921763467143122522, 3241611744432406503, 16149166019569794702}, + }, + { + {13355027832202142668, 13259310595418810737, 16638224598838046396, 388655643128437049}, + {6131988039969669992, 16758867465997134050, 793705445085763779, 16225736542798627427}, + }, + { + {12060616483613851492, 11185023117529741833, 15286366164051065546, 5407795227432242447}, + {3261413161331398298, 7182873809282605970, 2155509494582452911, 16998725707829879258}, + }, + }, + { + { + {14380343880230315251, 6834909096379668102, 15975839936772635678, 7738230945027714388}, + {7971648870467745046, 8320128435052726628, 10820026056424631461, 7058118462476293754}, + }, + { + {11165438517321289842, 8661037418831619311, 4401480924846865713, 9355650368902126256}, + {14352422544185763829, 12268031594529744663, 17607497268577344783, 12698954426769962214}, + }, + { + {5091534986326281709, 8005812102849517353, 17366496686564185717, 3658878980438307796}, + {8455810244524637026, 7649393961871195909, 8629386422022530934, 507133797409068858}, + }, + { + {10098955144981013765, 4095621933458866623, 313357785962326778, 14880249056209398407}, + {10605627454111004262, 7841561005378789988, 5015399193497762029, 5818383539901203899}, + }, + { + {829322392873083372, 3459913121476606612, 4547714508342797986, 5801286056105229312}, + {11591136160675314269, 17965845487226778560, 7022309609363885527, 5990586084398664157}, + }, + { + {6288277991521986035, 12231480617236286340, 8633990423689180869, 13535190275290488690}, + {13419223868164389899, 17622732596713666209, 10071779220640400024, 9451660464882303005}, + }, + { + {11761084765182152401, 9226969173242076459, 5445719591917489914, 9371133174853825566}, + {18381867235964583187, 17262888224001222346, 1934253649802391267, 3574888052111089863}, + }, + { + {15270079546607712667, 8471883658965202468, 10333206241569264742, 7414741159725097798}, + {7709713706668701850, 4461310100162632915, 10099194304024685274, 4760203118683828795}, + }, + { + {784143359277603248, 15514589681861498400, 4131024411374659852, 3624433493936743696}, + {3251402229976672212, 4649659622203715244, 926933500763282104, 6444675794782453444}, + }, + { + {3756269038539504739, 7020323719189662644, 9035687928909659722, 10611580746254894906}, + {6310976205075048332, 11776014447017145895, 18193543588427463707, 12941703752632419110}, + }, + { + {13258346207952257162, 14737306929596267614, 139896257833059475, 5049568122463438631}, + {12260461320589066027, 46497756452454082, 15185750105748824007, 3681406295924007900}, + }, + { + {2833339165549332500, 18300762432878821923, 13251805801497937312, 17798840894981774941}, + {10659715417364364943, 9241413425866019176, 9144746556705463526, 18018473193185776281}, + }, + { + {7436336871105679313, 3718902224813103412, 8186181643677715434, 17182578567975462342}, + {659724975715028710, 9425698860660002856, 796351253238186633, 18323943433898241577}, + }, + { + {13500588337778130334, 15143039800006025480, 5471884014140775766, 8599189774825271733}, + {14063442714998210193, 17130659899212878144, 2181888550891204616, 13594088124987533554}, + }, + { + {16216101853436910766, 13302132899821289315, 8876723129840557561, 2026846371223185778}, + {7753254296964005427, 16607365864296868674, 1800351426181020953, 12473523172043936884}, + }, + }, + { + { + {14734199666349771791, 4159865781008764547, 4413963548436270853, 4489431649937855880}, + {2824856157476907519, 5111945927271461159, 9825486821405155220, 7657332565522279292}, + }, + { + {8798422177670065832, 1250388939918922012, 5145324733132743026, 3716299737175574168}, + {14387202892738514375, 10255681359895407489, 8563822744122397080, 18430417713920116013}, + }, + { + {7857399215288147901, 2593284350589299949, 10086687882410147351, 14407837835956327624}, + {4469878646287387405, 6845712208092605310, 3019047164798827279, 2760591274816994522}, + }, + { + {10930605176025081830, 5850835312463207607, 9603163404664606781, 15623771803942139684}, + {4096748595672894276, 13060617166821837740, 11222939712741281346, 18445178894593253710}, + }, + { + {7976335583419810431, 16568954524837045521, 5581116346602990350, 18369129318179031997}, + {1930478946186473631, 14255806344323769850, 5302512325798050097, 10008570767203424472}, + }, + { + {929118050943456183, 445163760697913504, 7208246135487165437, 13565354217377841149}, + {3835063466770003968, 8214155842021576753, 2078717035803259674, 12502657820500987763}, + }, + { + {17741004372977419914, 16320851348541958575, 11853008901690968430, 9954777341381304447}, + {14274892887030297417, 10721339848307167540, 8731332510371325649, 13676383433520290197}, + }, + { + {6251805914672095769, 1063060143452094078, 16647397170554915088, 15454955736319919321}, + {11509235104607349098, 8441647766544589978, 956121464218389431, 10752793912033728149}, + }, + { + {14879603883666664508, 11158422912437249402, 8667988090392051507, 12702057193823135575}, + {13234479167199208223, 13752955092077643608, 1117550756888145931, 1184967682872965330}, + }, + { + {7004802666964716824, 395433501626287206, 16674151908279399004, 2279551165611331131}, + {18032555740803644790, 3573953642384243989, 9892480504006025100, 2397759375236735831}, + }, + { + {15032723931727013905, 4176673226777913017, 7270920367565154969, 8867675920919464620}, + {8174119413251699506, 15030539680120439131, 12325981936900309518, 2932283844656871802}, + }, + { + {3227890727136855788, 10772277744280338071, 10065219931092397730, 17233706446636791341}, + {1372997838851103811, 14430098741859995846, 3290287064497023581, 13054133915521430696}, + }, + { + {3404625123065318735, 11884832674715736469, 16513753127836546671, 2355202492840722899}, + {2182039060332057784, 17942518439766613327, 16731345075928062112, 5501869092504492134}, + }, + { + {15704211025163561149, 14596679078416770266, 10262177146233936833, 12443005669252298316}, + {1541294166390346144, 2952804996209068760, 15358481016273272880, 1321729586231860999}, + }, + { + {6862865331233391228, 15106279167311639122, 3283008666555627541, 13405610967904725343}, + {9845239597399801983, 10764942720093673542, 6506992344666983370, 2483131164245259278}, + }, + }, + { + { + {9844707592410952215, 8167497709587672711, 18115463401502884199, 8471563375691441535}, + {17525405040226359165, 2460181803833371342, 3375780580907171205, 3024376384135966552}, + }, + { + {18138724984190926809, 4154767406604950048, 5209478936276366634, 15469512148904762872}, + {3613429290324777670, 12631812917445459751, 10280179062385049041, 19656860716268566}, + }, + { + {14203862032167128161, 13470939927320077756, 10327441827790615277, 10318573137694660185}, + {14560780313347476436, 17088464982837309355, 733937949060316950, 14069325810788446179}, + }, + { + {12030193727051241373, 13981191132445467472, 18205169646206905593, 12162181194046583886}, + {10929925499200074058, 15291772758590352491, 8452344520852919320, 8199821440451878776}, + }, + { + {702956275289752726, 11856189935311796245, 14185745521831658392, 4370665693013677718}, + {4339320942948136612, 7422618440224759582, 871840009976682819, 1758213746931263134}, + }, + { + {7463305936638691553, 10552402742907536443, 9732741351132553899, 194397927117005699}, + {12837197785265289115, 4412933472643099429, 12440864981406580998, 17072316007921211511}, + }, + { + {5025653014579399483, 6266285559889618786, 17667439302823084142, 8837073500207072384}, + {16230880878690171580, 8966359704103918073, 2671625161783975934, 5761959268140569579}, + }, + { + {9876482463501409337, 17331045017548147052, 17542726936580732548, 8299195336372136083}, + {12891767721269002608, 14062358772374813347, 4165127680073507756, 16350672737379495431}, + }, + { + {15987859092221739938, 10999006767011320329, 16931834873460681704, 40989027820989117}, + {16439290771012023473, 6900965556474667785, 7253680936177336810, 17240235510851599487}, + }, + { + {4114449005477323279, 11333071244606712260, 5639227616302034307, 15107257128889549417}, + {5046122977641767311, 17558812465185003134, 18137671581165086239, 4382776603153058089}, + }, + { + {18024760665596162063, 4581156045659391508, 968287218068232238, 9228777525067749703}, + {17309990917327276325, 7114941925430814300, 16735731670154258613, 6290532662018771504}, + }, + { + {7595271959296927018, 15286771623821390629, 980612661413312852, 5738158184597378995}, + {6972117550390447038, 6246497134979772260, 2935831443692029059, 12837371529160496660}, + }, + { + {10790135298802805255, 7259368218310211690, 12050916808246223984, 2030323364779525994}, + {12824594050397534312, 4098150364864727064, 15604500991562385767, 2831443658783115116}, + }, + { + {6469454686530052235, 2594644969515545140, 5284951626835069400, 14441180041267617906}, + {16001664398759990060, 13049178223054879255, 3268931999230968043, 3072360434503949622}, + }, + { + {4565530397071857053, 857029374864691712, 15955478286869670604, 17781316921869181573}, + {16457191703043818907, 5989113593649065091, 4425872606756635499, 4532030700973621003}, + }, + }, + { + { + {2317249352525369754, 15030797481081533168, 12237590576308284360, 15660076992611440873}, + {11341015819700735887, 8280257602754365719, 9212501234696283343, 9673375202141178099}, + }, + { + {9762534010701623728, 15349113802811029024, 8305297169667044246, 18013018210154476198}, + {18414050009163335761, 2190126859433916996, 5444481274452218807, 13415988647365667724}, + }, + { + {11641532224340210206, 71261001011952801, 2321745415903209397, 6595984444855093239}, + {10341299657770272718, 11529878689049370930, 14381510695605158203, 6869272773579747365}, + }, + { + {1073778278665127828, 301289653767944933, 11482324780950168317, 10626716202328004967}, + {7258024014655363102, 12597648090458567878, 2617914106162603499, 12324652644266476584}, + }, + { + {13957732574177025801, 1100344278733481546, 12156946932617203965, 2007756425747006287}, + {16454508610548016441, 18058668363064769203, 15619001054652658323, 1201476243910931863}, + }, + { + {16341334571424533804, 4657494880554316004, 18092783076286521475, 19832895869027143}, + {8667365497283429486, 11501953273367138162, 5832487631687776985, 664754160781757174}, + }, + { + {13524719886605363170, 11553593166914861649, 12034020205580665813, 985175984881624722}, + {11040631342644137311, 12107496606245418129, 7328748654066365904, 14741972847454326011}, + }, + { + {12828567388121500364, 2264959796189127526, 6222205589523394088, 8827682270015065013}, + {2619170858745203321, 14835030117099398518, 5960028394532808010, 2233397097850889639}, + }, + { + {3879642723354138203, 5439355518658448857, 14194463322012776543, 14947367699252203702}, + {11497182458118153903, 16347396442451668378, 16912659817226286851, 6972297461053626970}, + }, + { + {14953681219966965709, 18116944572750863844, 16774540053916392198, 6518998682436778354}, + {11207035159486725904, 17279266785091386830, 15987732680339874714, 4953887381255790681}, + }, + { + {18128055290529398111, 4838636144867908799, 17655818333374840693, 5013823741985131317}, + {1920449774281311783, 13898340137609808546, 861099289958274037, 12441596565887895930}, + }, + { + {7244015348755525626, 13520825180887535513, 9165067445392785660, 9250553550156732893}, + {15663564389384259196, 5724018088820370997, 11379531752316746866, 17687565409319417941}, + }, + { + {11050714794366707475, 12230144450501707996, 12363862313107363407, 6348205119671766380}, + {14263471584626838352, 7350100163762375926, 1902788311165167298, 11691126042005505984}, + }, + { + {3948847772791576201, 11933738159609952054, 15749315384347059669, 8831922078851474178}, + {8463496071867925621, 12756218686011120865, 4691766390469398064, 5252134452066688477}, + }, + { + {4880806069791899809, 11099088460364672063, 12627384861893315861, 4239079797011518662}, + {14560690935803003234, 15267325636353169132, 16919582304973803583, 10073876067858458517}, + }, + }, + { + { + {15695265447782578013, 15506558718447241194, 12341861439298989232, 18400958156300100845}, + {13704811286967591150, 5802260047239067846, 3266013253411255445, 9892957742319181954}, + }, + { + {6053458788987550519, 3243549259991905443, 17990025476026266205, 3918149716414968130}, + {562225565996136148, 12175287017902713154, 16317970834262634990, 5431198806775607012}, + }, + { + {15123186170178367264, 3054913246068400920, 8130663466272395280, 2852812622149318730}, + {6747630551931917110, 18302049774259156971, 3663865061939346221, 12340091610704678811}, + }, + { + {17453312277789785069, 1148609799196055657, 5931758962926317381, 5297597381576544508}, + {9136842287749269744, 3007653173299649609, 12364677607049679091, 3656932227466449489}, + }, + { + {17732801126130995365, 16093023291975796560, 17028512234142609413, 6293028118993952199}, + {4019599708379609715, 3557632583507755601, 16737140015288442165, 7041678499288317736}, + }, + { + {5187842645752673199, 14914432544387315508, 4944360914161982641, 4177329533692612281}, + {18423887817846407126, 11935898134550505219, 9191754399457615042, 962223885189306707}, + }, + { + {5467152559317256227, 13407023128339380091, 656806207084558176, 10823228592509573890}, + {282802378108427873, 13003319652664166176, 11501612671901244594, 8595770155487539951}, + }, + { + {1805255869285898834, 11676967700876044626, 3486630203654875772, 8366336693945605431}, + {17874084888474647879, 8803709150655606891, 680993178667234696, 1603785777136148315}, + }, + { + {3637712241808318043, 1673622542455477465, 14468899013751477571, 6607241816357171779}, + {2332200248940843815, 14077155355848738174, 17298155509321457563, 13624623885136011130}, + }, + { + {12550073596584561722, 13898852145577133829, 31360866049197404, 12629522544897401454}, + {4563446134761510332, 7272813487383198495, 16767195814334178362, 13600498026689482359}, + }, + { + {5170414136067325373, 10875290278133558518, 7331268231382198947, 4082234313337835514}, + {11725295114019619895, 6488017511603508543, 11399466652931338200, 2898113599278666684}, + }, + { + {7553418756944942759, 2324485560009697358, 16004009784734101843, 8345371056076551939}, + {7377284629098981027, 11049718262343754276, 8021605820736410979, 8175349759714152494}, + }, + { + {805625092558946929, 11996029844853502332, 1725029464967101849, 8189609560660709539}, + {10396089572662865065, 1756007811373736605, 7645529329516777410, 2608132938055260111}, + }, + { + {17014595621244604813, 1574499958190108567, 8684546755761322906, 9997538531915911005}, + {5652402150243592363, 6315865356369667235, 8687115108443972047, 12369176255146729475}, + }, + { + {5117004045853299762, 2238407612548002914, 12392667457861900490, 10614312910576266709}, + {6446577503758597410, 3767883614425995197, 17954966454260719539, 5233322901463099}, + }, + }, + { + { + {1081257522368061155, 16144982029632101790, 2280210790959566458, 5000326950136078873}, + {10441086845859171982, 5717080014740953823, 16816253740467637151, 5185838557034755093}, + }, + { + {3897734650128449985, 3892478283047854402, 153850176068596076, 4448963435449755938}, + {9911011406822436713, 6379744721342779297, 360324666931028426, 8002086405015565067}, + }, + { + {13662666854424521459, 17028614494600252018, 13372166182804100759, 8978661571842967509}, + {1689945315009228820, 9997133634912151808, 4070075534875432478, 5780712439158341418}, + }, + { + {18068291112584812890, 10288580446655316879, 16866690514199445805, 15458664010538199871}, + {17175925202246173890, 12208778610361755998, 927739404697616036, 10330183209424493139}, + }, + { + {4422872630455196261, 14815650254807917367, 9426346157598724768, 17764302665164113296}, + {9474027272970951461, 3048886202121388617, 7073604597785890399, 9516006646305083675}, + }, + { + {16541317581647968302, 7221753201217091047, 554497992080233562, 12743131795939254731}, + {6113032707000257613, 4448176364247161206, 738044254484725063, 3096942233684051465}, + }, + { + {2801392933730991479, 15502003900939246745, 11340323610824656109, 13690394827169426680}, + {2298413291804124677, 12243772219106809119, 9550327342593445260, 18354548835264437008}, + }, + { + {17095781462759061506, 13984950766342782369, 7038608479806172868, 7073471193601880894}, + {9212126909381119712, 15865851343492198107, 3874039137971369196, 15366505242302572319}, + }, + { + {10476508037395688256, 5905562397524931472, 15147896444621280595, 3856601647293477321}, + {4204909177546012159, 17515684210872904454, 12561834979880779760, 6477848309789627185}, + }, + { + {3226022509034031128, 5771385963704757771, 17861700165696478115, 14976034400726774156}, + {17945959497662269352, 6322288130414861016, 3008853024335853994, 5599925939427067989}, + }, + { + {15408448007738805625, 3855259080280453396, 11776434265478354726, 11784885919111239520}, + {8108981861486003291, 16553896039002150783, 5694423121092647200, 16414563259092889693}, + }, + { + {3235058267792568155, 8030551941244615429, 12851363585510555514, 9786973022560471711}, + {4901414898060251968, 13240438628487941170, 4707852389766057435, 6503805666511566831}, + }, + { + {1178073204986944698, 10685133932326477495, 11710162005310407793, 11019188929725710305}, + {16244991946372165706, 3272168887117805467, 15045747299972144833, 8155681972478369649}, + }, + { + {12308450869393289693, 14268794937571237354, 9141189178824378983, 11605207657904000518}, + {17071770108549330148, 11045960524457021256, 13807710432855107212, 8427718050873363613}, + }, + { + {16762196363426636910, 7316863360113205703, 7937998445095491508, 3946557199536080470}, + {16019910399697645039, 11522845950519380293, 2362453023191035102, 6547077716792082654}, + }, + }, + { + { + {5218985848865375996, 5835476376320976237, 9096499658845542933, 8952489298840360492}, + {16605895184424459659, 505731104315931813, 17784248872812610986, 4151555707609374291}, + }, + { + {4963953120977916566, 6585250545846301109, 4490972754776862709, 10674499592300479120}, + {17494988318349821345, 1814042777264686189, 8938395423478059768, 9062966010283426056}, + }, + { + {3879469818714011415, 11493820457829716643, 10091807027724827301, 5032134849078736052}, + {18015749204009276046, 9667758283246223357, 4629693773460610802, 3807196436109718946}, + }, + { + {5724217930909760221, 15420221591912350415, 9910465013739250802, 12511683773790779491}, + {2841532862707547306, 16614426471009646589, 407574220261191228, 17422057170120224031}, + }, + { + {3725101809714764432, 2995111022132376824, 9338883729618021504, 8824923738291347476}, + {3745497072215538317, 3576446898425965872, 2350077748663612773, 15793255155885543355}, + }, + { + {12904339001067417585, 1972265247859388742, 8908590936681392405, 10320719400504224158}, + {8298368064038407143, 2105745729886511647, 16509751074757847095, 15156289751671616565}, + }, + { + {885617946245226760, 17871561572095909264, 16413308527330544768, 2938750343525834336}, + {6332736376778563648, 16772687696658236231, 9760470695949399178, 17420556823805232882}, + }, + { + {4407657041250297528, 13832960959347315977, 15056546959967740939, 4350443362134191429}, + {8013419913016572733, 8888684099801298477, 15401479253620745715, 18279947201669400847}, + }, + { + {16774767206504477529, 15784248755460218800, 890363416232172440, 6798249980336291014}, + {1295939576916968887, 14501516576359061383, 5181286196215569291, 8884842683907072200}, + }, + { + {12906144535917740163, 4179201185048577793, 8949647323841299627, 2168773816567792706}, + {1715683170634778607, 9901501903322086192, 7624633731287546358, 10530124063631858009}, + }, + { + {14199956317346734484, 13250211595320054421, 18197952479293091552, 16161313407818957084}, + {17435507292968186894, 6560268436714668609, 1299607057816966726, 8157462320016248727}, + }, + { + {3603583288706717651, 17387128326071547512, 17907604816622771553, 17853094381965037384}, + {12273843852205811233, 13840584476006398280, 2018654168596055410, 11549248055135584644}, + }, + { + {4742377140579111706, 845465928037625085, 12028953960657292824, 16438644767032965255}, + {17377088622232632294, 1631558517096568450, 11363064014018667511, 6006029335296807862}, + }, + { + {8877393780281438935, 9848923171251074575, 1554975198005028643, 2251034043951525516}, + {9696558687758873050, 3889942916226212472, 8326933892612496812, 7463785348361544799}, + }, + { + {4205364996189816688, 5453611962777060261, 16993840011943171053, 11689161310506207011}, + {16699173739044458906, 6254168288000491517, 12642281218300963313, 10028950653175051753}, + }, + }, + { + { + {8784043285714375740, 8483257759279461889, 8789745728267363600, 1770019616739251654}, + {15992936863339206154, 10037038012062884956, 15197544864945402661, 9615747158586711429}, + }, + { + {9583737883674400333, 12279877754802111101, 8296198976379850969, 17778859909846088251}, + {3401986641240187301, 1525831644595056632, 1849003687033449918, 8702493044913179195}, + }, + { + {18423170064697770279, 12693387071620743675, 7398701556189346968, 2779682216903406718}, + {12703629940499916779, 6358598532389273114, 8683512038509439374, 15415938252666293255}, + }, + { + {8408419572923862476, 5066733120953500019, 926242532005776114, 6301489109130024811}, + {3285079390283344806, 1685054835664548935, 7740622190510199342, 9561507292862134371}, + }, + { + {13698695174800826869, 10442832251048252285, 10672604962207744524, 14485711676978308040}, + {16947216143812808464, 8342189264337602603, 3837253281927274344, 8331789856935110934}, + }, + { + {4627808394696681034, 6174000022702321214, 15351247319787348909, 1371147458593240691}, + {10651965436787680331, 2998319090323362997, 17592419471314886417, 11874181791118522207}, + }, + { + {524165018444839759, 3157588572894920951, 17599692088379947784, 1421537803477597699}, + {2902517390503550285, 7440776657136679901, 17263207614729765269, 16928425260420958311}, + }, + { + {2878166099891431311, 5056053391262430293, 10345032411278802027, 13214556496570163981}, + {17698482058276194679, 2441850938900527637, 1314061001345252336, 6263402014353842038}, + }, + { + {8487436533858443496, 12386798851261442113, 3224748875345095424, 16166568617729909099}, + {2213369110503306004, 6246347469485852131, 3129440554298978074, 605269941184323483}, + }, + { + {3177531230451277512, 11022989490494865721, 8321856985295555401, 14727273563873821327}, + {876865438755954294, 14139765236890058248, 6880705719513638354, 8678887646434118325}, + }, + { + {16896703203004244996, 11377226897030111200, 2302364246994590389, 4499255394192625779}, + {1906858144627445384, 2670515414718439880, 868537809054295101, 7535366755622172814}, + }, + { + {339769604981749608, 12384581172556225075, 2596838235904096350, 5684069910326796630}, + {913125548148611907, 1661497269948077623, 2892028918424825190, 9220412792897768138}, + }, + { + {14754959387565938441, 1023838193204581133, 13599978343236540433, 8323909593307920217}, + {3852032956982813055, 7526785533690696419, 8993798556223495105, 18140648187477079959}, + }, + { + {11692087196810962506, 1328079167955601379, 1664008958165329504, 18063501818261063470}, + {2861243404839114859, 13702578580056324034, 16781565866279299035, 1524194541633674171}, + }, + { + {8267721299596412251, 273633183929630283, 17164190306640434032, 16332882679719778825}, + {4663567915067622493, 15521151801790569253, 7273215397645141911, 2324445691280731636}, + }, + }, + } +} diff --git a/core/crypto/_weierstrass/tools/ecc_gen_tables.odin b/core/crypto/_weierstrass/tools/ecc_gen_tables.odin new file mode 100644 index 000000000..e69927a90 --- /dev/null +++ b/core/crypto/_weierstrass/tools/ecc_gen_tables.odin @@ -0,0 +1,99 @@ +package weistrass_tools + +import secec "core:crypto/_weierstrass" +import "core:fmt" +import path "core:path/filepath" +import "core:os" +import "core:strings" + +// Yes this leaks memory, fite me IRL. + +GENERATED :: `/* + ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ DO NOT EDIT ------ GENERATED ------ +*/` + +main :: proc() { + gen_p256r1_tables() +} + +gen_p256r1_tables :: proc() { + Affine_Point_p256r1 :: struct { + x: secec.Field_Element_p256r1, + y: secec.Field_Element_p256r1, + } + Multiply_Table_p256r1_hi: [32][15]Affine_Point_p256r1 + Multiply_Table_p256r1_lo: [32][15]Affine_Point_p256r1 + + g, p: secec.Point_p256r1 + secec.pt_generator(&g) + + // Precompute ([1,15] << n) * G multiples of G, MSB->LSB + for i in 0..<32 { + b: [32]byte + for j in 1..<16 { + b[i] = u8(j) << 4 + secec.pt_scalar_mul_bytes(&p, &g, b[:], true) + secec.pt_rescale(&p, &p) + secec.fe_set(&Multiply_Table_p256r1_hi[i][j-1].x, &p.x) + secec.fe_set(&Multiply_Table_p256r1_hi[i][j-1].y, &p.y) + + b[i] = u8(j) + secec.pt_scalar_mul_bytes(&p, &g, b[:], true) + secec.pt_rescale(&p, &p) + secec.fe_set(&Multiply_Table_p256r1_lo[i][j-1].x, &p.x) + secec.fe_set(&Multiply_Table_p256r1_lo[i][j-1].y, &p.y) + + b[i] = 0 + } + } + + fn := path.join({ODIN_ROOT, "core", "crypto", "_weierstrass", "secp256r1_table.odin"}) + bld: strings.Builder + w := strings.to_writer(&bld) + + fmt.wprintln(w, "package _weierstrass") + fmt.wprintln(w, "") + fmt.wprintln(w, GENERATED) + fmt.wprintln(w, "") + fmt.wprintln(w, "import \"core:crypto\"") + fmt.wprintln(w, "") + fmt.wprintln(w, "when crypto.COMPACT_IMPLS == false {") + + fmt.wprintln(w, "\t@(private,rodata)") + fmt.wprintln(w, "\tGen_Multiply_Table_p256r1_hi := [32][15]Affine_Point_p256r1 {") + for &v, i in Multiply_Table_p256r1_hi { + fmt.wprintln(w, "\t\t{") + for &ap, j in v { + fmt.wprintln(w, "\t\t\t{") + + x, y := &ap.x, &ap.y + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d},\n", x[0], x[1], x[2], x[3]) + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d},\n", y[0], y[1], y[2], y[3]) + + fmt.wprintln(w, "\t\t\t},") + } + fmt.wprintln(w, "\t\t},") + } + fmt.wprintln(w, "\t}\n") + + fmt.wprintln(w, "\t@(private,rodata)") + fmt.wprintln(w, "\tGen_Multiply_Table_p256r1_lo := [32][15]Affine_Point_p256r1 {") + for &v, i in Multiply_Table_p256r1_lo { + fmt.wprintln(w, "\t\t{") + for &ap, j in v { + fmt.wprintln(w, "\t\t\t{") + + x, y := &ap.x, &ap.y + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d},\n", x[0], x[1], x[2], x[3]) + fmt.wprintf(w, "\t\t\t\t{{%d, %d, %d, %d},\n", y[0], y[1], y[2], y[3]) + + fmt.wprintln(w, "\t\t\t},") + } + fmt.wprintln(w, "\t\t},") + } + fmt.wprintln(w, "\t}") + + fmt.wprintln(w, "}") + + _ = os.write_entire_file(fn, transmute([]byte)(strings.to_string(bld))) +} diff --git a/core/crypto/crypto.odin b/core/crypto/crypto.odin index 435c5daaf..3fb369a54 100644 --- a/core/crypto/crypto.odin +++ b/core/crypto/crypto.odin @@ -5,6 +5,9 @@ import "base:runtime" import subtle "core:crypto/_subtle" import "core:mem" +// Omit large precomputed tables, trading off performance for size. +COMPACT_IMPLS: bool : #config(ODIN_CRYPTO_COMPACT, false) + // HAS_RAND_BYTES is true iff the runtime provides a cryptographic // entropy source. HAS_RAND_BYTES :: runtime.HAS_RAND_BYTES diff --git a/tests/core/crypto/test_core_crypto_weierstrass.odin b/tests/core/crypto/test_core_crypto_weierstrass.odin new file mode 100644 index 000000000..206e98bd7 --- /dev/null +++ b/tests/core/crypto/test_core_crypto_weierstrass.odin @@ -0,0 +1,486 @@ +package test_core_crypto + +import ec "core:crypto/_weierstrass" +import "core:encoding/hex" +import "core:math/big" +import "core:testing" + +@(private="file") +P256_G_X :: "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296" +@(private="file") +P256_G_Y :: "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" + +@(private="file") +P256_G_UNCOMPRESSED :: "04" + P256_G_X + P256_G_Y + +@(test) +test_p256_a :: proc(t: ^testing.T) { + a_str := "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc" + + fe, a_fe: ec.Field_Element_p256r1 + ec.fe_a(&fe) + ec.fe_a(&a_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expect(t, s == a_str) + + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b[:]) + + testing.expect(t, ec.fe_equal(&fe, &a_fe) == 1) +} + +@(test) +test_p256_b :: proc(t: ^testing.T) { + b_str := "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b" + + fe, b_fe: ec.Field_Element_p256r1 + ec.fe_b(&fe) + ec.fe_b(&b_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expect(t, s == b_str) + + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b[:]) + + testing.expect(t, ec.fe_equal(&fe, &b_fe) == 1) +} + +@(test) +test_p256_g_x :: proc(t: ^testing.T) { + fe, x_fe: ec.Field_Element_p256r1 + ec.fe_gen_x(&fe) + ec.fe_gen_x(&x_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expect(t, s == P256_G_X) + + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b[:]) + + testing.expect(t, ec.fe_equal(&fe, &x_fe) == 1) +} + +@(test) +test_p256_g_y :: proc(t: ^testing.T) { + fe, y_fe: ec.Field_Element_p256r1 + ec.fe_gen_y(&fe) + ec.fe_gen_y(&y_fe) + + b: [32]byte + ec.fe_bytes(b[:], &fe) + + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expect(t, s == P256_G_Y) + + ec.fe_zero(&fe) + ec.fe_set_bytes(&fe, b[:]) + + testing.expect(t, ec.fe_equal(&fe, &y_fe) == 1) +} + +@(test) +test_p256_scalar_reduce :: proc(t: ^testing.T) { + test_vectors := []struct { + raw: string, + reduced: string, + } { + // n + { + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "0000000000000000000000000000000000000000000000000000000000000000", + }, + // n + 1 + { + "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552", + "0000000000000000000000000000000000000000000000000000000000000001", + }, + // 2^384 (Sage) + { + "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "431905529c0166ce652e96b7ccca0a99679b73e19ad16947f01cf013fc632551", + }, + // SHA384 odin-linux-amd64-dev-2026-01.tar.gz (Sage) + { + "87622f79b4b0e76001f9c99b0337b61a0bcd2b5a8e9a3937176825ad75ef0fe8742a348a251dd2682d711f76b33df3e6", + "f66db86e28d903033d1e17d818c0eb13fe3d1ae095b4d2ecbcd1a1eccf9f2f8c", + }, + // SHA512 odin-linux-amd64-dev-2026-01.tar.gz (Sage) + { + "6f85507cec3a35fdb3d4f40d23583681144561e77bc4ea88ab0ea219d5c17b7c9178f5f5a6296a2d18eddd4bdf19e61830fc85d7de23fd4fbde31c4cf6694719", + "3217ecbee32c8b0dfcca0f10a884fe43658fbe91458f25d0f1bf2075759c5ebe", + }, + } + + for v, _ in test_vectors { + raw_bytes, _ := hex.decode(transmute([]byte)(v.raw), context.temp_allocator) + + sc: ec.Scalar_p256r1 + _ = ec.sc_set_bytes(&sc, raw_bytes) + + b: [ec.SC_SIZE_P256R1]byte + ec.sc_bytes(b[:], &sc) + s := (string)(hex.encode(b[:], context.temp_allocator)) + + testing.expectf(t, v.reduced == s, "sc: raw %s reduced: %s, expected: %s", v.raw, s, v.reduced) + } +} + +@(test) +test_p256_scalar_mul :: proc(t: ^testing.T) { + test_vectors := []struct { + scalar: string, // NOTE: Base 10 + x, y: string, + } { + // Test vectors from http://point-at-infinity.org/ecc/nisttv + { + "1", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + + }, + { + "2", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", + "07775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1", + }, + { + "3", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C", + "8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032", + }, + { + "4", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852", + "E0F1575A4C633CC719DFEE5FDA862D764EFC96C3F30EE0055C42C23F184ED8C6", + }, + { + "5", + "51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED", + "E0C17DA8904A727D8AE1BF36BF8A79260D012F00D4D80888D1D0BB44FDA16DA4", + }, + { + "6", + "B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9", + "E85C10743237DAD56FEC0E2DFBA703791C00F7701C7E16BDFD7C48538FC77FE2", + }, + { + "7", + "8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3", + "73EB1DBDE03318366D069F83A6F5900053C73633CB041B21C55E1A86C1F400B4", + }, + { + "8", + "62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393", + "AD5ACCBD91E9D8244FF15D771167CEE0A2ED51F6BBE76A78DA540A6A0F09957E", + }, + { + "9", + "EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0", + "2A2744C972C9FCE787014A964A8EA0C84D714FEAA4DE823FE85A224A4DD048FA", + }, + { + "10", + "CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F", + "878662A229AAAE906E123CDD9D3B4C10590DED29FE751EEECA34BBAA44AF0773", + }, + { + "11", + "3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1", + "9099209ACCC4C8A224C843AFA4F4C68A090D04DA5E9889DAE2F8EEFCE82A3740", + }, + { + "12", + "741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4", + "0770B46A9C385FDC567383554887B1548EEB912C35BA5CA71995FF22CD4481D3", + }, + { + "13", + "177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01", + "63BB58CD4EBEA558A24091ADB40F4E7226EE14C3A1FB4DF39C43BBE2EFC7BFD8", + }, + { + "14", + "54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B", + "F599F1BB29F4317542121F8C05A2E7C37171EA77735090081BA7C82F60D0B375", + }, + { + "15", + "F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F", + "B5B93EE3592E2D1F4E6594E51F9643E62A3B21CE75B5FA3F47E59CDE0D034F36", + }, + { + "16", + "76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E", + "A985FE61341F260E6CB0A1B5E11E87208599A0040FC78BAA0E9DDD724B8C5110", + }, + { + "17", + "47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E", + "AA005EE6B5B957286231856577648E8381B2804428D5733F32F787FF71F1FCDC", + }, + { + "18", + "1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA", + "F6F1645A15CBE5DC9FA9B7DFD96EE5A7DCC11B5C5EF4F1F78D83B3393C6A45A2", + }, + { + "19", + "CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83", + "58D7614B24D9EF515C35E7100D6D6CE4A496716E30FA3E03E39150752BCECDAA", + }, + { + "20", + "83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A", + "76E49B6DE2F73234AE6A5EB9D612B75C9F2202BB6923F54FF8240AAA86F640B8", + }, + { + "112233445566778899", + "339150844EC15234807FE862A86BE77977DBFB3AE3D96F4C22795513AEAAB82F", + "B1C14DDFDC8EC1B2583F51E85A5EB3A155840F2034730E9B5ADA38B674336A21", + }, + { + "112233445566778899112233445566778899", + "1B7E046A076CC25E6D7FA5003F6729F665CC3241B5ADAB12B498CD32F2803264", + "BFEA79BE2B666B073DB69A2A241ADAB0738FE9D2DD28B5604EB8C8CF097C457B", + }, + { + "029852220098221261079183923314599206100666902414330245206392788703677545185283", + "9EACE8F4B071E677C5350B02F2BB2B384AAE89D58AA72CA97A170572E0FB222F", + "1BBDAEC2430B09B93F7CB08678636CE12EAAFD58390699B5FD2F6E1188FC2A78", + }, + { + "057896042899961394862005778464643882389978449576758748073725983489954366354431", + "878F22CC6DB6048D2B767268F22FFAD8E56AB8E2DC615F7BD89F1E350500DD8D", + "714A5D7BB901C9C5853400D12341A892EF45D87FC553786756C4F0C9391D763E", + }, + { + "57896042899961394862005778464643882389978449576758748073725983489954366354431", + "878F22CC6DB6048D2B767268F22FFAD8E56AB8E2DC615F7BD89F1E350500DD8D", + "714A5D7BB901C9C5853400D12341A892EF45D87FC553786756C4F0C9391D763E", + }, + { + "1766845392945710151501889105729049882997660004824848915955419660366636031", + "659A379625AB122F2512B8DADA02C6348D53B54452DFF67AC7ACE4E8856295CA", + "49D81AB97B648464D0B4A288BD7818FAB41A16426E943527C4FED8736C53D0F6", + }, + { + "28948025760307534517734791687894775804466072615242963443097661355606862201087", + "CBCEAAA8A4DD44BBCE58E8DB7740A5510EC2CB7EA8DA8D8F036B3FB04CDA4DE4", + "4BD7AA301A80D7F59FD983FEDBE59BB7B2863FE46494935E3745B360E32332FA", + }, + { + "113078210460870548944811695960290644973229224625838436424477095834645696384", + "F0C4A0576154FF3A33A3460D42EAED806E854DFA37125221D37935124BA462A4", + "5B392FA964434D29EEC6C9DBC261CF116796864AA2FAADB984A2DF38D1AEF7A3", + }, + { + "12078056106883488161242983286051341125085761470677906721917479268909056", + "5E6C8524B6369530B12C62D31EC53E0288173BD662BDF680B53A41ECBCAD00CC", + "447FE742C2BFEF4D0DB14B5B83A2682309B5618E0064A94804E9282179FE089F", + }, + { + "57782969857385448082319957860328652998540760998293976083718804450708503920639", + "03792E541BC209076A3D7920A915021ECD396A6EB5C3960024BE5575F3223484", + "FC774AE092403101563B712F68170312304F20C80B40C06282063DB25F268DE4", + }, + { + "57896017119460046759583662757090100341435943767777707906455551163257755533312", + "2379FF85AB693CDF901D6CE6F2473F39C04A2FE3DCD842CE7AAB0E002095BCF8", + "F8B476530A634589D5129E46F322B02FBC610A703D80875EE70D7CE1877436A1", + }, + { + "452312848374287284681282171017647412726433684238464212999305864837160993279", + "C1E4072C529BF2F44DA769EFC934472848003B3AF2C0F5AA8F8DDBD53E12ED7C", + "39A6EE77812BB37E8079CD01ED649D3830FCA46F718C1D3993E4A591824ABCDB", + }, + { + "904571339174065134293634407946054000774746055866917729876676367558469746684", + "34DFBC09404C21E250A9B40FA8772897AC63A094877DB65862B61BD1507B34F3", + "CF6F8A876C6F99CEAEC87148F18C7E1E0DA6E165FFC8ED82ABB65955215F77D3", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044349", + "83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A", + "891B64911D08CDCC5195A14629ED48A360DDFD4596DC0AB007DBF5557909BF47", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044350", + "CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83", + "A7289EB3DB2610AFA3CA18EFF292931B5B698E92CF05C1FC1C6EAF8AD4313255", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044351", + "1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA", + "090E9BA4EA341A246056482026911A58233EE4A4A10B0E08727C4CC6C395BA5D", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044352", + "47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E", + "55FFA1184A46A8D89DCE7A9A889B717C7E4D7FBCD72A8CC0CD0878008E0E0323", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044353", + "76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E", + "567A019DCBE0D9F2934F5E4A1EE178DF7A665FFCF0387455F162228DB473AEEF", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044354", + "F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F", + "4A46C11BA6D1D2E1B19A6B1AE069BC19D5C4DE328A4A05C0B81A6321F2FCB0C9", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044355", + "54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B", + "0A660E43D60BCE8BBDEDE073FA5D183C8E8E15898CAF6FF7E45837D09F2F4C8A", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044356", + "177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01", + "9C44A731B1415AA85DBF6E524BF0B18DD911EB3D5E04B20C63BC441D10384027", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044357", + "741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4", + "F88F4B9463C7A024A98C7CAAB7784EAB71146ED4CA45A358E66A00DD32BB7E2C", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044358", + "3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1", + "6F66DF64333B375EDB37BC505B0B3975F6F2FB26A16776251D07110317D5C8BF", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044359", + "CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F", + "78799D5CD655517091EDC32262C4B3EFA6F212D7018AE11135CB4455BB50F88C", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044360", + "EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0", + "D5D8BB358D36031978FEB569B5715F37B28EB0165B217DC017A5DDB5B22FB705", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044361", + "62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393", + "52A533416E1627DCB00EA288EE98311F5D12AE0A4418958725ABF595F0F66A81", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044362", + "8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3", + "8C14E2411FCCE7CA92F9607C590A6FFFAC38C9CD34FBE4DE3AA1E5793E0BFF4B", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044363", + "B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9", + "17A3EF8ACDC8252B9013F1D20458FC86E3FF0890E381E9420283B7AC7038801D", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044364", + "51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED", + "1F3E82566FB58D83751E40C9407586D9F2FED1002B27F7772E2F44BB025E925B", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044365", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852", + "1F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044366", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C", + "78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044367", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", + "F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E", + }, + { + "115792089210356248762697446949407573529996955224135760342422259061068512044368", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A", + }, + } + + for v, _ in test_vectors { + x_bytes, _ := hex.decode(transmute([]byte)(v.x), context.temp_allocator) + y_bytes, _ := hex.decode(transmute([]byte)(v.y), context.temp_allocator) + + k_big: big.Int + err := big.set(&k_big, v.scalar, 10, context.temp_allocator) + testing.expectf(t, err == nil, "failed to parse k", err) + + k_sz: int + k_sz, err = big.int_to_bytes_size(&k_big, allocator = context.temp_allocator) + testing.expect(t, err == nil) + + k_bytes := make([]byte, k_sz, context.temp_allocator) + err = big.int_to_bytes_big(&k_big, k_bytes, allocator = context.temp_allocator) + + p, q, expected, g: ec.Point_p256r1 + sc: ec.Scalar_p256r1 + + _ = ec.sc_set_bytes(&sc, k_bytes) + + ec.pt_generator(&g) + ok := ec.pt_set_xy_bytes(&expected, x_bytes, y_bytes) + testing.expectf(t, ok, "failed to set point; %s, %s", v.x, v.y) + + ec.pt_scalar_mul(&p, &g, &sc) + ec.pt_scalar_mul_generator(&q, &sc) + ec.pt_rescale(&p, &p) + ec.pt_rescale(&q, &q) + + testing.expect(t, ec.pt_equal(&p, &q) == 1) + testing.expectf(t, ec.pt_equal(&p, &expected) == 1, "sc: %s actual: %v expected: %v", v.scalar, &p, &expected) + } +} + +@(test) +test_p256_s11n_sec_identity ::proc(t: ^testing.T) { + p: ec.Point_p256r1 + + ec.pt_generator(&p) + ok := ec.pt_set_sec_bytes(&p, []byte{0x00}) + testing.expect(t, ok) + testing.expectf(t, ec.pt_is_identity(&p) == 1, "%v", p) + + b := []byte{0xff} + ok = ec.pt_sec_bytes(b, &p, true) + testing.expect(t, ok) + testing.expect(t, b[0] == 0x00) + + b = []byte{0xff} + ok = ec.pt_sec_bytes(b, &p, false) + testing.expect(t, ok) + testing.expect(t, b[0] == 0x00) +} + +@(test) +test_p256_s11n_sec_generator ::proc(t: ^testing.T) { + p, g: ec.Point_p256r1 + + ec.pt_generator(&g) + ec.pt_identity(&p) + + b: [65]byte + ok := ec.pt_sec_bytes(b[:], &g, false) + testing.expect(t, ok) + s := (string)(hex.encode(b[:], context.temp_allocator)) + testing.expectf(t, s == P256_G_UNCOMPRESSED, "g: %v bytes: %v, %v", g, P256_G_UNCOMPRESSED, s) + + ok = ec.pt_set_sec_bytes(&p, b[:]) + testing.expectf(t, ok, "%s", s) + testing.expect(t, ec.pt_equal(&g, &p) == 1) +}