aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/crypto/_fiat/field_p256r1/field.odin346
-rw-r--r--core/crypto/_fiat/field_p256r1/field64.odin501
-rw-r--r--core/crypto/_fiat/field_scalarp256r1/field.odin210
-rw-r--r--core/crypto/_fiat/field_scalarp256r1/field64.odin569
-rw-r--r--core/crypto/_weierstrass/fe.odin135
-rw-r--r--core/crypto/_weierstrass/point.odin548
-rw-r--r--core/crypto/_weierstrass/point_s11n_sec.odin95
-rw-r--r--core/crypto/_weierstrass/sc.odin76
-rw-r--r--core/crypto/_weierstrass/scalar_mul.odin204
-rw-r--r--core/crypto/_weierstrass/secp256r1_table.odin3985
-rw-r--r--core/crypto/_weierstrass/tools/ecc_gen_tables.odin99
-rw-r--r--core/crypto/crypto.odin3
-rw-r--r--tests/core/crypto/test_core_crypto_weierstrass.odin486
13 files changed, 7257 insertions, 0 deletions
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)
+}