1*de0e0e4dSAntonio Huete Jimenez /*	$OpenBSD: curve25519.c,v 1.6 2022/02/08 16:44:23 tb Exp $ */
272c33676SMaxim Ag /*
372c33676SMaxim Ag  * Copyright (c) 2015, Google Inc.
472c33676SMaxim Ag  *
572c33676SMaxim Ag  * Permission to use, copy, modify, and/or distribute this software for any
672c33676SMaxim Ag  * purpose with or without fee is hereby granted, provided that the above
772c33676SMaxim Ag  * copyright notice and this permission notice appear in all copies.
872c33676SMaxim Ag  *
972c33676SMaxim Ag  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1072c33676SMaxim Ag  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1172c33676SMaxim Ag  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
1272c33676SMaxim Ag  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1372c33676SMaxim Ag  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
1472c33676SMaxim Ag  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1572c33676SMaxim Ag  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1672c33676SMaxim Ag  */
1772c33676SMaxim Ag 
1872c33676SMaxim Ag /*
1972c33676SMaxim Ag  * This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
2072c33676SMaxim Ag  * 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
2172c33676SMaxim Ag  * public domain but this file has the ISC license just to keep licencing
2272c33676SMaxim Ag  * simple.
2372c33676SMaxim Ag  *
2472c33676SMaxim Ag  * The field functions are shared by Ed25519 and X25519 where possible.
2572c33676SMaxim Ag  */
2672c33676SMaxim Ag 
2772c33676SMaxim Ag #include <stdlib.h>
2872c33676SMaxim Ag #include <string.h>
2972c33676SMaxim Ag 
3072c33676SMaxim Ag #include <openssl/curve25519.h>
3172c33676SMaxim Ag 
3272c33676SMaxim Ag #ifdef ED25519
3372c33676SMaxim Ag #include <openssl/sha.h>
3472c33676SMaxim Ag #endif
3572c33676SMaxim Ag 
3672c33676SMaxim Ag #include "curve25519_internal.h"
3772c33676SMaxim Ag 
3872c33676SMaxim Ag static const int64_t kBottom25Bits = 0x1ffffffLL;
3972c33676SMaxim Ag static const int64_t kBottom26Bits = 0x3ffffffLL;
4072c33676SMaxim Ag static const int64_t kTop39Bits = 0xfffffffffe000000LL;
4172c33676SMaxim Ag static const int64_t kTop38Bits = 0xfffffffffc000000LL;
4272c33676SMaxim Ag 
load_3(const uint8_t * in)4372c33676SMaxim Ag static uint64_t load_3(const uint8_t *in) {
4472c33676SMaxim Ag   uint64_t result;
4572c33676SMaxim Ag   result = (uint64_t)in[0];
4672c33676SMaxim Ag   result |= ((uint64_t)in[1]) << 8;
4772c33676SMaxim Ag   result |= ((uint64_t)in[2]) << 16;
4872c33676SMaxim Ag   return result;
4972c33676SMaxim Ag }
5072c33676SMaxim Ag 
load_4(const uint8_t * in)5172c33676SMaxim Ag static uint64_t load_4(const uint8_t *in) {
5272c33676SMaxim Ag   uint64_t result;
5372c33676SMaxim Ag   result = (uint64_t)in[0];
5472c33676SMaxim Ag   result |= ((uint64_t)in[1]) << 8;
5572c33676SMaxim Ag   result |= ((uint64_t)in[2]) << 16;
5672c33676SMaxim Ag   result |= ((uint64_t)in[3]) << 24;
5772c33676SMaxim Ag   return result;
5872c33676SMaxim Ag }
5972c33676SMaxim Ag 
fe_frombytes(fe h,const uint8_t * s)6072c33676SMaxim Ag static void fe_frombytes(fe h, const uint8_t *s) {
6172c33676SMaxim Ag   /* Ignores top bit of h. */
6272c33676SMaxim Ag   int64_t h0 = load_4(s);
6372c33676SMaxim Ag   int64_t h1 = load_3(s + 4) << 6;
6472c33676SMaxim Ag   int64_t h2 = load_3(s + 7) << 5;
6572c33676SMaxim Ag   int64_t h3 = load_3(s + 10) << 3;
6672c33676SMaxim Ag   int64_t h4 = load_3(s + 13) << 2;
6772c33676SMaxim Ag   int64_t h5 = load_4(s + 16);
6872c33676SMaxim Ag   int64_t h6 = load_3(s + 20) << 7;
6972c33676SMaxim Ag   int64_t h7 = load_3(s + 23) << 5;
7072c33676SMaxim Ag   int64_t h8 = load_3(s + 26) << 4;
7172c33676SMaxim Ag   int64_t h9 = (load_3(s + 29) & 8388607) << 2;
7272c33676SMaxim Ag   int64_t carry0;
7372c33676SMaxim Ag   int64_t carry1;
7472c33676SMaxim Ag   int64_t carry2;
7572c33676SMaxim Ag   int64_t carry3;
7672c33676SMaxim Ag   int64_t carry4;
7772c33676SMaxim Ag   int64_t carry5;
7872c33676SMaxim Ag   int64_t carry6;
7972c33676SMaxim Ag   int64_t carry7;
8072c33676SMaxim Ag   int64_t carry8;
8172c33676SMaxim Ag   int64_t carry9;
8272c33676SMaxim Ag 
8372c33676SMaxim Ag   carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
8472c33676SMaxim Ag   carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
8572c33676SMaxim Ag   carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
8672c33676SMaxim Ag   carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
8772c33676SMaxim Ag   carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
8872c33676SMaxim Ag 
8972c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
9072c33676SMaxim Ag   carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
9172c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
9272c33676SMaxim Ag   carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
9372c33676SMaxim Ag   carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
9472c33676SMaxim Ag 
9572c33676SMaxim Ag   h[0] = h0;
9672c33676SMaxim Ag   h[1] = h1;
9772c33676SMaxim Ag   h[2] = h2;
9872c33676SMaxim Ag   h[3] = h3;
9972c33676SMaxim Ag   h[4] = h4;
10072c33676SMaxim Ag   h[5] = h5;
10172c33676SMaxim Ag   h[6] = h6;
10272c33676SMaxim Ag   h[7] = h7;
10372c33676SMaxim Ag   h[8] = h8;
10472c33676SMaxim Ag   h[9] = h9;
10572c33676SMaxim Ag }
10672c33676SMaxim Ag 
10772c33676SMaxim Ag /* Preconditions:
10872c33676SMaxim Ag  *  |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
10972c33676SMaxim Ag  *
11072c33676SMaxim Ag  * Write p=2^255-19; q=floor(h/p).
11172c33676SMaxim Ag  * Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
11272c33676SMaxim Ag  *
11372c33676SMaxim Ag  * Proof:
11472c33676SMaxim Ag  *   Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
11572c33676SMaxim Ag  *   Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
11672c33676SMaxim Ag  *
11772c33676SMaxim Ag  *   Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
11872c33676SMaxim Ag  *   Then 0<y<1.
11972c33676SMaxim Ag  *
12072c33676SMaxim Ag  *   Write r=h-pq.
12172c33676SMaxim Ag  *   Have 0<=r<=p-1=2^255-20.
12272c33676SMaxim Ag  *   Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
12372c33676SMaxim Ag  *
12472c33676SMaxim Ag  *   Write x=r+19(2^-255)r+y.
12572c33676SMaxim Ag  *   Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
12672c33676SMaxim Ag  *
12772c33676SMaxim Ag  *   Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
12872c33676SMaxim Ag  *   so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q. */
fe_tobytes(uint8_t * s,const fe h)12972c33676SMaxim Ag static void fe_tobytes(uint8_t *s, const fe h) {
13072c33676SMaxim Ag   int32_t h0 = h[0];
13172c33676SMaxim Ag   int32_t h1 = h[1];
13272c33676SMaxim Ag   int32_t h2 = h[2];
13372c33676SMaxim Ag   int32_t h3 = h[3];
13472c33676SMaxim Ag   int32_t h4 = h[4];
13572c33676SMaxim Ag   int32_t h5 = h[5];
13672c33676SMaxim Ag   int32_t h6 = h[6];
13772c33676SMaxim Ag   int32_t h7 = h[7];
13872c33676SMaxim Ag   int32_t h8 = h[8];
13972c33676SMaxim Ag   int32_t h9 = h[9];
14072c33676SMaxim Ag   int32_t q;
14172c33676SMaxim Ag 
14272c33676SMaxim Ag   q = (19 * h9 + (((int32_t) 1) << 24)) >> 25;
14372c33676SMaxim Ag   q = (h0 + q) >> 26;
14472c33676SMaxim Ag   q = (h1 + q) >> 25;
14572c33676SMaxim Ag   q = (h2 + q) >> 26;
14672c33676SMaxim Ag   q = (h3 + q) >> 25;
14772c33676SMaxim Ag   q = (h4 + q) >> 26;
14872c33676SMaxim Ag   q = (h5 + q) >> 25;
14972c33676SMaxim Ag   q = (h6 + q) >> 26;
15072c33676SMaxim Ag   q = (h7 + q) >> 25;
15172c33676SMaxim Ag   q = (h8 + q) >> 26;
15272c33676SMaxim Ag   q = (h9 + q) >> 25;
15372c33676SMaxim Ag 
15472c33676SMaxim Ag   /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
15572c33676SMaxim Ag   h0 += 19 * q;
15672c33676SMaxim Ag   /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
15772c33676SMaxim Ag 
15872c33676SMaxim Ag   h1 += h0 >> 26; h0 &= kBottom26Bits;
15972c33676SMaxim Ag   h2 += h1 >> 25; h1 &= kBottom25Bits;
16072c33676SMaxim Ag   h3 += h2 >> 26; h2 &= kBottom26Bits;
16172c33676SMaxim Ag   h4 += h3 >> 25; h3 &= kBottom25Bits;
16272c33676SMaxim Ag   h5 += h4 >> 26; h4 &= kBottom26Bits;
16372c33676SMaxim Ag   h6 += h5 >> 25; h5 &= kBottom25Bits;
16472c33676SMaxim Ag   h7 += h6 >> 26; h6 &= kBottom26Bits;
16572c33676SMaxim Ag   h8 += h7 >> 25; h7 &= kBottom25Bits;
16672c33676SMaxim Ag   h9 += h8 >> 26; h8 &= kBottom26Bits;
16772c33676SMaxim Ag                   h9 &= kBottom25Bits;
16872c33676SMaxim Ag                   /* h10 = carry9 */
16972c33676SMaxim Ag 
17072c33676SMaxim Ag   /* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
17172c33676SMaxim Ag    * Have h0+...+2^230 h9 between 0 and 2^255-1;
17272c33676SMaxim Ag    * evidently 2^255 h10-2^255 q = 0.
17372c33676SMaxim Ag    * Goal: Output h0+...+2^230 h9.  */
17472c33676SMaxim Ag 
17572c33676SMaxim Ag   s[0] = h0 >> 0;
17672c33676SMaxim Ag   s[1] = h0 >> 8;
17772c33676SMaxim Ag   s[2] = h0 >> 16;
17872c33676SMaxim Ag   s[3] = (h0 >> 24) | ((uint32_t)(h1) << 2);
17972c33676SMaxim Ag   s[4] = h1 >> 6;
18072c33676SMaxim Ag   s[5] = h1 >> 14;
18172c33676SMaxim Ag   s[6] = (h1 >> 22) | ((uint32_t)(h2) << 3);
18272c33676SMaxim Ag   s[7] = h2 >> 5;
18372c33676SMaxim Ag   s[8] = h2 >> 13;
18472c33676SMaxim Ag   s[9] = (h2 >> 21) | ((uint32_t)(h3) << 5);
18572c33676SMaxim Ag   s[10] = h3 >> 3;
18672c33676SMaxim Ag   s[11] = h3 >> 11;
18772c33676SMaxim Ag   s[12] = (h3 >> 19) | ((uint32_t)(h4) << 6);
18872c33676SMaxim Ag   s[13] = h4 >> 2;
18972c33676SMaxim Ag   s[14] = h4 >> 10;
19072c33676SMaxim Ag   s[15] = h4 >> 18;
19172c33676SMaxim Ag   s[16] = h5 >> 0;
19272c33676SMaxim Ag   s[17] = h5 >> 8;
19372c33676SMaxim Ag   s[18] = h5 >> 16;
19472c33676SMaxim Ag   s[19] = (h5 >> 24) | ((uint32_t)(h6) << 1);
19572c33676SMaxim Ag   s[20] = h6 >> 7;
19672c33676SMaxim Ag   s[21] = h6 >> 15;
19772c33676SMaxim Ag   s[22] = (h6 >> 23) | ((uint32_t)(h7) << 3);
19872c33676SMaxim Ag   s[23] = h7 >> 5;
19972c33676SMaxim Ag   s[24] = h7 >> 13;
20072c33676SMaxim Ag   s[25] = (h7 >> 21) | ((uint32_t)(h8) << 4);
20172c33676SMaxim Ag   s[26] = h8 >> 4;
20272c33676SMaxim Ag   s[27] = h8 >> 12;
20372c33676SMaxim Ag   s[28] = (h8 >> 20) | ((uint32_t)(h9) << 6);
20472c33676SMaxim Ag   s[29] = h9 >> 2;
20572c33676SMaxim Ag   s[30] = h9 >> 10;
20672c33676SMaxim Ag   s[31] = h9 >> 18;
20772c33676SMaxim Ag }
20872c33676SMaxim Ag 
20972c33676SMaxim Ag /* h = f */
fe_copy(fe h,const fe f)21072c33676SMaxim Ag static void fe_copy(fe h, const fe f) {
21172c33676SMaxim Ag   memmove(h, f, sizeof(int32_t) * 10);
21272c33676SMaxim Ag }
21372c33676SMaxim Ag 
21472c33676SMaxim Ag /* h = 0 */
fe_0(fe h)21572c33676SMaxim Ag static void fe_0(fe h) { memset(h, 0, sizeof(int32_t) * 10); }
21672c33676SMaxim Ag 
21772c33676SMaxim Ag /* h = 1 */
fe_1(fe h)21872c33676SMaxim Ag static void fe_1(fe h) {
21972c33676SMaxim Ag   memset(h, 0, sizeof(int32_t) * 10);
22072c33676SMaxim Ag   h[0] = 1;
22172c33676SMaxim Ag }
22272c33676SMaxim Ag 
22372c33676SMaxim Ag /* h = f + g
22472c33676SMaxim Ag  * Can overlap h with f or g.
22572c33676SMaxim Ag  *
22672c33676SMaxim Ag  * Preconditions:
22772c33676SMaxim Ag  *    |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
22872c33676SMaxim Ag  *    |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
22972c33676SMaxim Ag  *
23072c33676SMaxim Ag  * Postconditions:
23172c33676SMaxim Ag  *    |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
fe_add(fe h,const fe f,const fe g)23272c33676SMaxim Ag static void fe_add(fe h, const fe f, const fe g) {
23372c33676SMaxim Ag   unsigned i;
23472c33676SMaxim Ag   for (i = 0; i < 10; i++) {
23572c33676SMaxim Ag     h[i] = f[i] + g[i];
23672c33676SMaxim Ag   }
23772c33676SMaxim Ag }
23872c33676SMaxim Ag 
23972c33676SMaxim Ag /* h = f - g
24072c33676SMaxim Ag  * Can overlap h with f or g.
24172c33676SMaxim Ag  *
24272c33676SMaxim Ag  * Preconditions:
24372c33676SMaxim Ag  *    |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
24472c33676SMaxim Ag  *    |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
24572c33676SMaxim Ag  *
24672c33676SMaxim Ag  * Postconditions:
24772c33676SMaxim Ag  *    |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
fe_sub(fe h,const fe f,const fe g)24872c33676SMaxim Ag static void fe_sub(fe h, const fe f, const fe g) {
24972c33676SMaxim Ag   unsigned i;
25072c33676SMaxim Ag   for (i = 0; i < 10; i++) {
25172c33676SMaxim Ag     h[i] = f[i] - g[i];
25272c33676SMaxim Ag   }
25372c33676SMaxim Ag }
25472c33676SMaxim Ag 
25572c33676SMaxim Ag /* h = f * g
25672c33676SMaxim Ag  * Can overlap h with f or g.
25772c33676SMaxim Ag  *
25872c33676SMaxim Ag  * Preconditions:
25972c33676SMaxim Ag  *    |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
26072c33676SMaxim Ag  *    |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
26172c33676SMaxim Ag  *
26272c33676SMaxim Ag  * Postconditions:
26372c33676SMaxim Ag  *    |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
26472c33676SMaxim Ag  *
26572c33676SMaxim Ag  * Notes on implementation strategy:
26672c33676SMaxim Ag  *
26772c33676SMaxim Ag  * Using schoolbook multiplication.
26872c33676SMaxim Ag  * Karatsuba would save a little in some cost models.
26972c33676SMaxim Ag  *
27072c33676SMaxim Ag  * Most multiplications by 2 and 19 are 32-bit precomputations;
27172c33676SMaxim Ag  * cheaper than 64-bit postcomputations.
27272c33676SMaxim Ag  *
27372c33676SMaxim Ag  * There is one remaining multiplication by 19 in the carry chain;
27472c33676SMaxim Ag  * one *19 precomputation can be merged into this,
27572c33676SMaxim Ag  * but the resulting data flow is considerably less clean.
27672c33676SMaxim Ag  *
27772c33676SMaxim Ag  * There are 12 carries below.
27872c33676SMaxim Ag  * 10 of them are 2-way parallelizable and vectorizable.
27972c33676SMaxim Ag  * Can get away with 11 carries, but then data flow is much deeper.
28072c33676SMaxim Ag  *
28172c33676SMaxim Ag  * With tighter constraints on inputs can squeeze carries into int32. */
fe_mul(fe h,const fe f,const fe g)28272c33676SMaxim Ag static void fe_mul(fe h, const fe f, const fe g) {
28372c33676SMaxim Ag   int32_t f0 = f[0];
28472c33676SMaxim Ag   int32_t f1 = f[1];
28572c33676SMaxim Ag   int32_t f2 = f[2];
28672c33676SMaxim Ag   int32_t f3 = f[3];
28772c33676SMaxim Ag   int32_t f4 = f[4];
28872c33676SMaxim Ag   int32_t f5 = f[5];
28972c33676SMaxim Ag   int32_t f6 = f[6];
29072c33676SMaxim Ag   int32_t f7 = f[7];
29172c33676SMaxim Ag   int32_t f8 = f[8];
29272c33676SMaxim Ag   int32_t f9 = f[9];
29372c33676SMaxim Ag   int32_t g0 = g[0];
29472c33676SMaxim Ag   int32_t g1 = g[1];
29572c33676SMaxim Ag   int32_t g2 = g[2];
29672c33676SMaxim Ag   int32_t g3 = g[3];
29772c33676SMaxim Ag   int32_t g4 = g[4];
29872c33676SMaxim Ag   int32_t g5 = g[5];
29972c33676SMaxim Ag   int32_t g6 = g[6];
30072c33676SMaxim Ag   int32_t g7 = g[7];
30172c33676SMaxim Ag   int32_t g8 = g[8];
30272c33676SMaxim Ag   int32_t g9 = g[9];
30372c33676SMaxim Ag   int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */
30472c33676SMaxim Ag   int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
30572c33676SMaxim Ag   int32_t g3_19 = 19 * g3;
30672c33676SMaxim Ag   int32_t g4_19 = 19 * g4;
30772c33676SMaxim Ag   int32_t g5_19 = 19 * g5;
30872c33676SMaxim Ag   int32_t g6_19 = 19 * g6;
30972c33676SMaxim Ag   int32_t g7_19 = 19 * g7;
31072c33676SMaxim Ag   int32_t g8_19 = 19 * g8;
31172c33676SMaxim Ag   int32_t g9_19 = 19 * g9;
31272c33676SMaxim Ag   int32_t f1_2 = 2 * f1;
31372c33676SMaxim Ag   int32_t f3_2 = 2 * f3;
31472c33676SMaxim Ag   int32_t f5_2 = 2 * f5;
31572c33676SMaxim Ag   int32_t f7_2 = 2 * f7;
31672c33676SMaxim Ag   int32_t f9_2 = 2 * f9;
31772c33676SMaxim Ag   int64_t f0g0    = f0   * (int64_t) g0;
31872c33676SMaxim Ag   int64_t f0g1    = f0   * (int64_t) g1;
31972c33676SMaxim Ag   int64_t f0g2    = f0   * (int64_t) g2;
32072c33676SMaxim Ag   int64_t f0g3    = f0   * (int64_t) g3;
32172c33676SMaxim Ag   int64_t f0g4    = f0   * (int64_t) g4;
32272c33676SMaxim Ag   int64_t f0g5    = f0   * (int64_t) g5;
32372c33676SMaxim Ag   int64_t f0g6    = f0   * (int64_t) g6;
32472c33676SMaxim Ag   int64_t f0g7    = f0   * (int64_t) g7;
32572c33676SMaxim Ag   int64_t f0g8    = f0   * (int64_t) g8;
32672c33676SMaxim Ag   int64_t f0g9    = f0   * (int64_t) g9;
32772c33676SMaxim Ag   int64_t f1g0    = f1   * (int64_t) g0;
32872c33676SMaxim Ag   int64_t f1g1_2  = f1_2 * (int64_t) g1;
32972c33676SMaxim Ag   int64_t f1g2    = f1   * (int64_t) g2;
33072c33676SMaxim Ag   int64_t f1g3_2  = f1_2 * (int64_t) g3;
33172c33676SMaxim Ag   int64_t f1g4    = f1   * (int64_t) g4;
33272c33676SMaxim Ag   int64_t f1g5_2  = f1_2 * (int64_t) g5;
33372c33676SMaxim Ag   int64_t f1g6    = f1   * (int64_t) g6;
33472c33676SMaxim Ag   int64_t f1g7_2  = f1_2 * (int64_t) g7;
33572c33676SMaxim Ag   int64_t f1g8    = f1   * (int64_t) g8;
33672c33676SMaxim Ag   int64_t f1g9_38 = f1_2 * (int64_t) g9_19;
33772c33676SMaxim Ag   int64_t f2g0    = f2   * (int64_t) g0;
33872c33676SMaxim Ag   int64_t f2g1    = f2   * (int64_t) g1;
33972c33676SMaxim Ag   int64_t f2g2    = f2   * (int64_t) g2;
34072c33676SMaxim Ag   int64_t f2g3    = f2   * (int64_t) g3;
34172c33676SMaxim Ag   int64_t f2g4    = f2   * (int64_t) g4;
34272c33676SMaxim Ag   int64_t f2g5    = f2   * (int64_t) g5;
34372c33676SMaxim Ag   int64_t f2g6    = f2   * (int64_t) g6;
34472c33676SMaxim Ag   int64_t f2g7    = f2   * (int64_t) g7;
34572c33676SMaxim Ag   int64_t f2g8_19 = f2   * (int64_t) g8_19;
34672c33676SMaxim Ag   int64_t f2g9_19 = f2   * (int64_t) g9_19;
34772c33676SMaxim Ag   int64_t f3g0    = f3   * (int64_t) g0;
34872c33676SMaxim Ag   int64_t f3g1_2  = f3_2 * (int64_t) g1;
34972c33676SMaxim Ag   int64_t f3g2    = f3   * (int64_t) g2;
35072c33676SMaxim Ag   int64_t f3g3_2  = f3_2 * (int64_t) g3;
35172c33676SMaxim Ag   int64_t f3g4    = f3   * (int64_t) g4;
35272c33676SMaxim Ag   int64_t f3g5_2  = f3_2 * (int64_t) g5;
35372c33676SMaxim Ag   int64_t f3g6    = f3   * (int64_t) g6;
35472c33676SMaxim Ag   int64_t f3g7_38 = f3_2 * (int64_t) g7_19;
35572c33676SMaxim Ag   int64_t f3g8_19 = f3   * (int64_t) g8_19;
35672c33676SMaxim Ag   int64_t f3g9_38 = f3_2 * (int64_t) g9_19;
35772c33676SMaxim Ag   int64_t f4g0    = f4   * (int64_t) g0;
35872c33676SMaxim Ag   int64_t f4g1    = f4   * (int64_t) g1;
35972c33676SMaxim Ag   int64_t f4g2    = f4   * (int64_t) g2;
36072c33676SMaxim Ag   int64_t f4g3    = f4   * (int64_t) g3;
36172c33676SMaxim Ag   int64_t f4g4    = f4   * (int64_t) g4;
36272c33676SMaxim Ag   int64_t f4g5    = f4   * (int64_t) g5;
36372c33676SMaxim Ag   int64_t f4g6_19 = f4   * (int64_t) g6_19;
36472c33676SMaxim Ag   int64_t f4g7_19 = f4   * (int64_t) g7_19;
36572c33676SMaxim Ag   int64_t f4g8_19 = f4   * (int64_t) g8_19;
36672c33676SMaxim Ag   int64_t f4g9_19 = f4   * (int64_t) g9_19;
36772c33676SMaxim Ag   int64_t f5g0    = f5   * (int64_t) g0;
36872c33676SMaxim Ag   int64_t f5g1_2  = f5_2 * (int64_t) g1;
36972c33676SMaxim Ag   int64_t f5g2    = f5   * (int64_t) g2;
37072c33676SMaxim Ag   int64_t f5g3_2  = f5_2 * (int64_t) g3;
37172c33676SMaxim Ag   int64_t f5g4    = f5   * (int64_t) g4;
37272c33676SMaxim Ag   int64_t f5g5_38 = f5_2 * (int64_t) g5_19;
37372c33676SMaxim Ag   int64_t f5g6_19 = f5   * (int64_t) g6_19;
37472c33676SMaxim Ag   int64_t f5g7_38 = f5_2 * (int64_t) g7_19;
37572c33676SMaxim Ag   int64_t f5g8_19 = f5   * (int64_t) g8_19;
37672c33676SMaxim Ag   int64_t f5g9_38 = f5_2 * (int64_t) g9_19;
37772c33676SMaxim Ag   int64_t f6g0    = f6   * (int64_t) g0;
37872c33676SMaxim Ag   int64_t f6g1    = f6   * (int64_t) g1;
37972c33676SMaxim Ag   int64_t f6g2    = f6   * (int64_t) g2;
38072c33676SMaxim Ag   int64_t f6g3    = f6   * (int64_t) g3;
38172c33676SMaxim Ag   int64_t f6g4_19 = f6   * (int64_t) g4_19;
38272c33676SMaxim Ag   int64_t f6g5_19 = f6   * (int64_t) g5_19;
38372c33676SMaxim Ag   int64_t f6g6_19 = f6   * (int64_t) g6_19;
38472c33676SMaxim Ag   int64_t f6g7_19 = f6   * (int64_t) g7_19;
38572c33676SMaxim Ag   int64_t f6g8_19 = f6   * (int64_t) g8_19;
38672c33676SMaxim Ag   int64_t f6g9_19 = f6   * (int64_t) g9_19;
38772c33676SMaxim Ag   int64_t f7g0    = f7   * (int64_t) g0;
38872c33676SMaxim Ag   int64_t f7g1_2  = f7_2 * (int64_t) g1;
38972c33676SMaxim Ag   int64_t f7g2    = f7   * (int64_t) g2;
39072c33676SMaxim Ag   int64_t f7g3_38 = f7_2 * (int64_t) g3_19;
39172c33676SMaxim Ag   int64_t f7g4_19 = f7   * (int64_t) g4_19;
39272c33676SMaxim Ag   int64_t f7g5_38 = f7_2 * (int64_t) g5_19;
39372c33676SMaxim Ag   int64_t f7g6_19 = f7   * (int64_t) g6_19;
39472c33676SMaxim Ag   int64_t f7g7_38 = f7_2 * (int64_t) g7_19;
39572c33676SMaxim Ag   int64_t f7g8_19 = f7   * (int64_t) g8_19;
39672c33676SMaxim Ag   int64_t f7g9_38 = f7_2 * (int64_t) g9_19;
39772c33676SMaxim Ag   int64_t f8g0    = f8   * (int64_t) g0;
39872c33676SMaxim Ag   int64_t f8g1    = f8   * (int64_t) g1;
39972c33676SMaxim Ag   int64_t f8g2_19 = f8   * (int64_t) g2_19;
40072c33676SMaxim Ag   int64_t f8g3_19 = f8   * (int64_t) g3_19;
40172c33676SMaxim Ag   int64_t f8g4_19 = f8   * (int64_t) g4_19;
40272c33676SMaxim Ag   int64_t f8g5_19 = f8   * (int64_t) g5_19;
40372c33676SMaxim Ag   int64_t f8g6_19 = f8   * (int64_t) g6_19;
40472c33676SMaxim Ag   int64_t f8g7_19 = f8   * (int64_t) g7_19;
40572c33676SMaxim Ag   int64_t f8g8_19 = f8   * (int64_t) g8_19;
40672c33676SMaxim Ag   int64_t f8g9_19 = f8   * (int64_t) g9_19;
40772c33676SMaxim Ag   int64_t f9g0    = f9   * (int64_t) g0;
40872c33676SMaxim Ag   int64_t f9g1_38 = f9_2 * (int64_t) g1_19;
40972c33676SMaxim Ag   int64_t f9g2_19 = f9   * (int64_t) g2_19;
41072c33676SMaxim Ag   int64_t f9g3_38 = f9_2 * (int64_t) g3_19;
41172c33676SMaxim Ag   int64_t f9g4_19 = f9   * (int64_t) g4_19;
41272c33676SMaxim Ag   int64_t f9g5_38 = f9_2 * (int64_t) g5_19;
41372c33676SMaxim Ag   int64_t f9g6_19 = f9   * (int64_t) g6_19;
41472c33676SMaxim Ag   int64_t f9g7_38 = f9_2 * (int64_t) g7_19;
41572c33676SMaxim Ag   int64_t f9g8_19 = f9   * (int64_t) g8_19;
41672c33676SMaxim Ag   int64_t f9g9_38 = f9_2 * (int64_t) g9_19;
41772c33676SMaxim Ag   int64_t h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38;
41872c33676SMaxim Ag   int64_t h1 = f0g1+f1g0   +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19;
41972c33676SMaxim Ag   int64_t h2 = f0g2+f1g1_2 +f2g0   +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38;
42072c33676SMaxim Ag   int64_t h3 = f0g3+f1g2   +f2g1   +f3g0   +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19;
42172c33676SMaxim Ag   int64_t h4 = f0g4+f1g3_2 +f2g2   +f3g1_2 +f4g0   +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38;
42272c33676SMaxim Ag   int64_t h5 = f0g5+f1g4   +f2g3   +f3g2   +f4g1   +f5g0   +f6g9_19+f7g8_19+f8g7_19+f9g6_19;
42372c33676SMaxim Ag   int64_t h6 = f0g6+f1g5_2 +f2g4   +f3g3_2 +f4g2   +f5g1_2 +f6g0   +f7g9_38+f8g8_19+f9g7_38;
42472c33676SMaxim Ag   int64_t h7 = f0g7+f1g6   +f2g5   +f3g4   +f4g3   +f5g2   +f6g1   +f7g0   +f8g9_19+f9g8_19;
42572c33676SMaxim Ag   int64_t h8 = f0g8+f1g7_2 +f2g6   +f3g5_2 +f4g4   +f5g3_2 +f6g2   +f7g1_2 +f8g0   +f9g9_38;
42672c33676SMaxim Ag   int64_t h9 = f0g9+f1g8   +f2g7   +f3g6   +f4g5   +f5g4   +f6g3   +f7g2   +f8g1   +f9g0   ;
42772c33676SMaxim Ag   int64_t carry0;
42872c33676SMaxim Ag   int64_t carry1;
42972c33676SMaxim Ag   int64_t carry2;
43072c33676SMaxim Ag   int64_t carry3;
43172c33676SMaxim Ag   int64_t carry4;
43272c33676SMaxim Ag   int64_t carry5;
43372c33676SMaxim Ag   int64_t carry6;
43472c33676SMaxim Ag   int64_t carry7;
43572c33676SMaxim Ag   int64_t carry8;
43672c33676SMaxim Ag   int64_t carry9;
43772c33676SMaxim Ag 
43872c33676SMaxim Ag   /* |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
43972c33676SMaxim Ag    *   i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
44072c33676SMaxim Ag    * |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
44172c33676SMaxim Ag    *   i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */
44272c33676SMaxim Ag 
44372c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
44472c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
44572c33676SMaxim Ag   /* |h0| <= 2^25 */
44672c33676SMaxim Ag   /* |h4| <= 2^25 */
44772c33676SMaxim Ag   /* |h1| <= 1.71*2^59 */
44872c33676SMaxim Ag   /* |h5| <= 1.71*2^59 */
44972c33676SMaxim Ag 
45072c33676SMaxim Ag   carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
45172c33676SMaxim Ag   carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
45272c33676SMaxim Ag   /* |h1| <= 2^24; from now on fits into int32 */
45372c33676SMaxim Ag   /* |h5| <= 2^24; from now on fits into int32 */
45472c33676SMaxim Ag   /* |h2| <= 1.41*2^60 */
45572c33676SMaxim Ag   /* |h6| <= 1.41*2^60 */
45672c33676SMaxim Ag 
45772c33676SMaxim Ag   carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
45872c33676SMaxim Ag   carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
45972c33676SMaxim Ag   /* |h2| <= 2^25; from now on fits into int32 unchanged */
46072c33676SMaxim Ag   /* |h6| <= 2^25; from now on fits into int32 unchanged */
46172c33676SMaxim Ag   /* |h3| <= 1.71*2^59 */
46272c33676SMaxim Ag   /* |h7| <= 1.71*2^59 */
46372c33676SMaxim Ag 
46472c33676SMaxim Ag   carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
46572c33676SMaxim Ag   carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
46672c33676SMaxim Ag   /* |h3| <= 2^24; from now on fits into int32 unchanged */
46772c33676SMaxim Ag   /* |h7| <= 2^24; from now on fits into int32 unchanged */
46872c33676SMaxim Ag   /* |h4| <= 1.72*2^34 */
46972c33676SMaxim Ag   /* |h8| <= 1.41*2^60 */
47072c33676SMaxim Ag 
47172c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
47272c33676SMaxim Ag   carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
47372c33676SMaxim Ag   /* |h4| <= 2^25; from now on fits into int32 unchanged */
47472c33676SMaxim Ag   /* |h8| <= 2^25; from now on fits into int32 unchanged */
47572c33676SMaxim Ag   /* |h5| <= 1.01*2^24 */
47672c33676SMaxim Ag   /* |h9| <= 1.71*2^59 */
47772c33676SMaxim Ag 
47872c33676SMaxim Ag   carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
47972c33676SMaxim Ag   /* |h9| <= 2^24; from now on fits into int32 unchanged */
48072c33676SMaxim Ag   /* |h0| <= 1.1*2^39 */
48172c33676SMaxim Ag 
48272c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
48372c33676SMaxim Ag   /* |h0| <= 2^25; from now on fits into int32 unchanged */
48472c33676SMaxim Ag   /* |h1| <= 1.01*2^24 */
48572c33676SMaxim Ag 
48672c33676SMaxim Ag   h[0] = h0;
48772c33676SMaxim Ag   h[1] = h1;
48872c33676SMaxim Ag   h[2] = h2;
48972c33676SMaxim Ag   h[3] = h3;
49072c33676SMaxim Ag   h[4] = h4;
49172c33676SMaxim Ag   h[5] = h5;
49272c33676SMaxim Ag   h[6] = h6;
49372c33676SMaxim Ag   h[7] = h7;
49472c33676SMaxim Ag   h[8] = h8;
49572c33676SMaxim Ag   h[9] = h9;
49672c33676SMaxim Ag }
49772c33676SMaxim Ag 
49872c33676SMaxim Ag /* h = f * f
49972c33676SMaxim Ag  * Can overlap h with f.
50072c33676SMaxim Ag  *
50172c33676SMaxim Ag  * Preconditions:
50272c33676SMaxim Ag  *    |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
50372c33676SMaxim Ag  *
50472c33676SMaxim Ag  * Postconditions:
50572c33676SMaxim Ag  *    |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
50672c33676SMaxim Ag  *
50772c33676SMaxim Ag  * See fe_mul.c for discussion of implementation strategy. */
fe_sq(fe h,const fe f)50872c33676SMaxim Ag static void fe_sq(fe h, const fe f) {
50972c33676SMaxim Ag   int32_t f0 = f[0];
51072c33676SMaxim Ag   int32_t f1 = f[1];
51172c33676SMaxim Ag   int32_t f2 = f[2];
51272c33676SMaxim Ag   int32_t f3 = f[3];
51372c33676SMaxim Ag   int32_t f4 = f[4];
51472c33676SMaxim Ag   int32_t f5 = f[5];
51572c33676SMaxim Ag   int32_t f6 = f[6];
51672c33676SMaxim Ag   int32_t f7 = f[7];
51772c33676SMaxim Ag   int32_t f8 = f[8];
51872c33676SMaxim Ag   int32_t f9 = f[9];
51972c33676SMaxim Ag   int32_t f0_2 = 2 * f0;
52072c33676SMaxim Ag   int32_t f1_2 = 2 * f1;
52172c33676SMaxim Ag   int32_t f2_2 = 2 * f2;
52272c33676SMaxim Ag   int32_t f3_2 = 2 * f3;
52372c33676SMaxim Ag   int32_t f4_2 = 2 * f4;
52472c33676SMaxim Ag   int32_t f5_2 = 2 * f5;
52572c33676SMaxim Ag   int32_t f6_2 = 2 * f6;
52672c33676SMaxim Ag   int32_t f7_2 = 2 * f7;
52772c33676SMaxim Ag   int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
52872c33676SMaxim Ag   int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
52972c33676SMaxim Ag   int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
53072c33676SMaxim Ag   int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
53172c33676SMaxim Ag   int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
53272c33676SMaxim Ag   int64_t f0f0    = f0   * (int64_t) f0;
53372c33676SMaxim Ag   int64_t f0f1_2  = f0_2 * (int64_t) f1;
53472c33676SMaxim Ag   int64_t f0f2_2  = f0_2 * (int64_t) f2;
53572c33676SMaxim Ag   int64_t f0f3_2  = f0_2 * (int64_t) f3;
53672c33676SMaxim Ag   int64_t f0f4_2  = f0_2 * (int64_t) f4;
53772c33676SMaxim Ag   int64_t f0f5_2  = f0_2 * (int64_t) f5;
53872c33676SMaxim Ag   int64_t f0f6_2  = f0_2 * (int64_t) f6;
53972c33676SMaxim Ag   int64_t f0f7_2  = f0_2 * (int64_t) f7;
54072c33676SMaxim Ag   int64_t f0f8_2  = f0_2 * (int64_t) f8;
54172c33676SMaxim Ag   int64_t f0f9_2  = f0_2 * (int64_t) f9;
54272c33676SMaxim Ag   int64_t f1f1_2  = f1_2 * (int64_t) f1;
54372c33676SMaxim Ag   int64_t f1f2_2  = f1_2 * (int64_t) f2;
54472c33676SMaxim Ag   int64_t f1f3_4  = f1_2 * (int64_t) f3_2;
54572c33676SMaxim Ag   int64_t f1f4_2  = f1_2 * (int64_t) f4;
54672c33676SMaxim Ag   int64_t f1f5_4  = f1_2 * (int64_t) f5_2;
54772c33676SMaxim Ag   int64_t f1f6_2  = f1_2 * (int64_t) f6;
54872c33676SMaxim Ag   int64_t f1f7_4  = f1_2 * (int64_t) f7_2;
54972c33676SMaxim Ag   int64_t f1f8_2  = f1_2 * (int64_t) f8;
55072c33676SMaxim Ag   int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
55172c33676SMaxim Ag   int64_t f2f2    = f2   * (int64_t) f2;
55272c33676SMaxim Ag   int64_t f2f3_2  = f2_2 * (int64_t) f3;
55372c33676SMaxim Ag   int64_t f2f4_2  = f2_2 * (int64_t) f4;
55472c33676SMaxim Ag   int64_t f2f5_2  = f2_2 * (int64_t) f5;
55572c33676SMaxim Ag   int64_t f2f6_2  = f2_2 * (int64_t) f6;
55672c33676SMaxim Ag   int64_t f2f7_2  = f2_2 * (int64_t) f7;
55772c33676SMaxim Ag   int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
55872c33676SMaxim Ag   int64_t f2f9_38 = f2   * (int64_t) f9_38;
55972c33676SMaxim Ag   int64_t f3f3_2  = f3_2 * (int64_t) f3;
56072c33676SMaxim Ag   int64_t f3f4_2  = f3_2 * (int64_t) f4;
56172c33676SMaxim Ag   int64_t f3f5_4  = f3_2 * (int64_t) f5_2;
56272c33676SMaxim Ag   int64_t f3f6_2  = f3_2 * (int64_t) f6;
56372c33676SMaxim Ag   int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
56472c33676SMaxim Ag   int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
56572c33676SMaxim Ag   int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
56672c33676SMaxim Ag   int64_t f4f4    = f4   * (int64_t) f4;
56772c33676SMaxim Ag   int64_t f4f5_2  = f4_2 * (int64_t) f5;
56872c33676SMaxim Ag   int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
56972c33676SMaxim Ag   int64_t f4f7_38 = f4   * (int64_t) f7_38;
57072c33676SMaxim Ag   int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
57172c33676SMaxim Ag   int64_t f4f9_38 = f4   * (int64_t) f9_38;
57272c33676SMaxim Ag   int64_t f5f5_38 = f5   * (int64_t) f5_38;
57372c33676SMaxim Ag   int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
57472c33676SMaxim Ag   int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
57572c33676SMaxim Ag   int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
57672c33676SMaxim Ag   int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
57772c33676SMaxim Ag   int64_t f6f6_19 = f6   * (int64_t) f6_19;
57872c33676SMaxim Ag   int64_t f6f7_38 = f6   * (int64_t) f7_38;
57972c33676SMaxim Ag   int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
58072c33676SMaxim Ag   int64_t f6f9_38 = f6   * (int64_t) f9_38;
58172c33676SMaxim Ag   int64_t f7f7_38 = f7   * (int64_t) f7_38;
58272c33676SMaxim Ag   int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
58372c33676SMaxim Ag   int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
58472c33676SMaxim Ag   int64_t f8f8_19 = f8   * (int64_t) f8_19;
58572c33676SMaxim Ag   int64_t f8f9_38 = f8   * (int64_t) f9_38;
58672c33676SMaxim Ag   int64_t f9f9_38 = f9   * (int64_t) f9_38;
58772c33676SMaxim Ag   int64_t h0 = f0f0  +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
58872c33676SMaxim Ag   int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
58972c33676SMaxim Ag   int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
59072c33676SMaxim Ag   int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
59172c33676SMaxim Ag   int64_t h4 = f0f4_2+f1f3_4 +f2f2   +f5f9_76+f6f8_38+f7f7_38;
59272c33676SMaxim Ag   int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
59372c33676SMaxim Ag   int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
59472c33676SMaxim Ag   int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
59572c33676SMaxim Ag   int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4   +f9f9_38;
59672c33676SMaxim Ag   int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
59772c33676SMaxim Ag   int64_t carry0;
59872c33676SMaxim Ag   int64_t carry1;
59972c33676SMaxim Ag   int64_t carry2;
60072c33676SMaxim Ag   int64_t carry3;
60172c33676SMaxim Ag   int64_t carry4;
60272c33676SMaxim Ag   int64_t carry5;
60372c33676SMaxim Ag   int64_t carry6;
60472c33676SMaxim Ag   int64_t carry7;
60572c33676SMaxim Ag   int64_t carry8;
60672c33676SMaxim Ag   int64_t carry9;
60772c33676SMaxim Ag 
60872c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
60972c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
61072c33676SMaxim Ag 
61172c33676SMaxim Ag   carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
61272c33676SMaxim Ag   carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
61372c33676SMaxim Ag 
61472c33676SMaxim Ag   carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
61572c33676SMaxim Ag   carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
61672c33676SMaxim Ag 
61772c33676SMaxim Ag   carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
61872c33676SMaxim Ag   carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
61972c33676SMaxim Ag 
62072c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
62172c33676SMaxim Ag   carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
62272c33676SMaxim Ag 
62372c33676SMaxim Ag   carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
62472c33676SMaxim Ag 
62572c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
62672c33676SMaxim Ag 
62772c33676SMaxim Ag   h[0] = h0;
62872c33676SMaxim Ag   h[1] = h1;
62972c33676SMaxim Ag   h[2] = h2;
63072c33676SMaxim Ag   h[3] = h3;
63172c33676SMaxim Ag   h[4] = h4;
63272c33676SMaxim Ag   h[5] = h5;
63372c33676SMaxim Ag   h[6] = h6;
63472c33676SMaxim Ag   h[7] = h7;
63572c33676SMaxim Ag   h[8] = h8;
63672c33676SMaxim Ag   h[9] = h9;
63772c33676SMaxim Ag }
63872c33676SMaxim Ag 
fe_invert(fe out,const fe z)63972c33676SMaxim Ag static void fe_invert(fe out, const fe z) {
64072c33676SMaxim Ag   fe t0;
64172c33676SMaxim Ag   fe t1;
64272c33676SMaxim Ag   fe t2;
64372c33676SMaxim Ag   fe t3;
64472c33676SMaxim Ag   int i;
64572c33676SMaxim Ag 
64672c33676SMaxim Ag   fe_sq(t0, z);
64772c33676SMaxim Ag   for (i = 1; i < 1; ++i) {
64872c33676SMaxim Ag     fe_sq(t0, t0);
64972c33676SMaxim Ag   }
65072c33676SMaxim Ag   fe_sq(t1, t0);
65172c33676SMaxim Ag   for (i = 1; i < 2; ++i) {
65272c33676SMaxim Ag     fe_sq(t1, t1);
65372c33676SMaxim Ag   }
65472c33676SMaxim Ag   fe_mul(t1, z, t1);
65572c33676SMaxim Ag   fe_mul(t0, t0, t1);
65672c33676SMaxim Ag   fe_sq(t2, t0);
65772c33676SMaxim Ag   for (i = 1; i < 1; ++i) {
65872c33676SMaxim Ag     fe_sq(t2, t2);
65972c33676SMaxim Ag   }
66072c33676SMaxim Ag   fe_mul(t1, t1, t2);
66172c33676SMaxim Ag   fe_sq(t2, t1);
66272c33676SMaxim Ag   for (i = 1; i < 5; ++i) {
66372c33676SMaxim Ag     fe_sq(t2, t2);
66472c33676SMaxim Ag   }
66572c33676SMaxim Ag   fe_mul(t1, t2, t1);
66672c33676SMaxim Ag   fe_sq(t2, t1);
66772c33676SMaxim Ag   for (i = 1; i < 10; ++i) {
66872c33676SMaxim Ag     fe_sq(t2, t2);
66972c33676SMaxim Ag   }
67072c33676SMaxim Ag   fe_mul(t2, t2, t1);
67172c33676SMaxim Ag   fe_sq(t3, t2);
67272c33676SMaxim Ag   for (i = 1; i < 20; ++i) {
67372c33676SMaxim Ag     fe_sq(t3, t3);
67472c33676SMaxim Ag   }
67572c33676SMaxim Ag   fe_mul(t2, t3, t2);
67672c33676SMaxim Ag   fe_sq(t2, t2);
67772c33676SMaxim Ag   for (i = 1; i < 10; ++i) {
67872c33676SMaxim Ag     fe_sq(t2, t2);
67972c33676SMaxim Ag   }
68072c33676SMaxim Ag   fe_mul(t1, t2, t1);
68172c33676SMaxim Ag   fe_sq(t2, t1);
68272c33676SMaxim Ag   for (i = 1; i < 50; ++i) {
68372c33676SMaxim Ag     fe_sq(t2, t2);
68472c33676SMaxim Ag   }
68572c33676SMaxim Ag   fe_mul(t2, t2, t1);
68672c33676SMaxim Ag   fe_sq(t3, t2);
68772c33676SMaxim Ag   for (i = 1; i < 100; ++i) {
68872c33676SMaxim Ag     fe_sq(t3, t3);
68972c33676SMaxim Ag   }
69072c33676SMaxim Ag   fe_mul(t2, t3, t2);
69172c33676SMaxim Ag   fe_sq(t2, t2);
69272c33676SMaxim Ag   for (i = 1; i < 50; ++i) {
69372c33676SMaxim Ag     fe_sq(t2, t2);
69472c33676SMaxim Ag   }
69572c33676SMaxim Ag   fe_mul(t1, t2, t1);
69672c33676SMaxim Ag   fe_sq(t1, t1);
69772c33676SMaxim Ag   for (i = 1; i < 5; ++i) {
69872c33676SMaxim Ag     fe_sq(t1, t1);
69972c33676SMaxim Ag   }
70072c33676SMaxim Ag   fe_mul(out, t1, t0);
70172c33676SMaxim Ag }
70272c33676SMaxim Ag 
70372c33676SMaxim Ag /* h = -f
70472c33676SMaxim Ag  *
70572c33676SMaxim Ag  * Preconditions:
70672c33676SMaxim Ag  *    |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
70772c33676SMaxim Ag  *
70872c33676SMaxim Ag  * Postconditions:
70972c33676SMaxim Ag  *    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */
fe_neg(fe h,const fe f)71072c33676SMaxim Ag static void fe_neg(fe h, const fe f) {
71172c33676SMaxim Ag   unsigned i;
71272c33676SMaxim Ag   for (i = 0; i < 10; i++) {
71372c33676SMaxim Ag     h[i] = -f[i];
71472c33676SMaxim Ag   }
71572c33676SMaxim Ag }
71672c33676SMaxim Ag 
71772c33676SMaxim Ag /* Replace (f,g) with (g,g) if b == 1;
71872c33676SMaxim Ag  * replace (f,g) with (f,g) if b == 0.
71972c33676SMaxim Ag  *
72072c33676SMaxim Ag  * Preconditions: b in {0,1}. */
fe_cmov(fe f,const fe g,unsigned b)72172c33676SMaxim Ag static void fe_cmov(fe f, const fe g, unsigned b) {
72272c33676SMaxim Ag   b = 0-b;
72372c33676SMaxim Ag   unsigned i;
72472c33676SMaxim Ag   for (i = 0; i < 10; i++) {
72572c33676SMaxim Ag     int32_t x = f[i] ^ g[i];
72672c33676SMaxim Ag     x &= b;
72772c33676SMaxim Ag     f[i] ^= x;
72872c33676SMaxim Ag   }
72972c33676SMaxim Ag }
73072c33676SMaxim Ag 
73172c33676SMaxim Ag /* return 0 if f == 0
73272c33676SMaxim Ag  * return 1 if f != 0
73372c33676SMaxim Ag  *
73472c33676SMaxim Ag  * Preconditions:
73572c33676SMaxim Ag  *    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
fe_isnonzero(const fe f)73672c33676SMaxim Ag static int fe_isnonzero(const fe f) {
73772c33676SMaxim Ag   uint8_t s[32];
73872c33676SMaxim Ag   fe_tobytes(s, f);
73972c33676SMaxim Ag 
74072c33676SMaxim Ag   static const uint8_t zero[32] = {0};
74172c33676SMaxim Ag   return timingsafe_memcmp(s, zero, sizeof(zero)) != 0;
74272c33676SMaxim Ag }
74372c33676SMaxim Ag 
74472c33676SMaxim Ag /* return 1 if f is in {1,3,5,...,q-2}
74572c33676SMaxim Ag  * return 0 if f is in {0,2,4,...,q-1}
74672c33676SMaxim Ag  *
74772c33676SMaxim Ag  * Preconditions:
74872c33676SMaxim Ag  *    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */
fe_isnegative(const fe f)74972c33676SMaxim Ag static int fe_isnegative(const fe f) {
75072c33676SMaxim Ag   uint8_t s[32];
75172c33676SMaxim Ag   fe_tobytes(s, f);
75272c33676SMaxim Ag   return s[0] & 1;
75372c33676SMaxim Ag }
75472c33676SMaxim Ag 
75572c33676SMaxim Ag /* h = 2 * f * f
75672c33676SMaxim Ag  * Can overlap h with f.
75772c33676SMaxim Ag  *
75872c33676SMaxim Ag  * Preconditions:
75972c33676SMaxim Ag  *    |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
76072c33676SMaxim Ag  *
76172c33676SMaxim Ag  * Postconditions:
76272c33676SMaxim Ag  *    |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
76372c33676SMaxim Ag  *
76472c33676SMaxim Ag  * See fe_mul.c for discussion of implementation strategy. */
fe_sq2(fe h,const fe f)76572c33676SMaxim Ag static void fe_sq2(fe h, const fe f) {
76672c33676SMaxim Ag   int32_t f0 = f[0];
76772c33676SMaxim Ag   int32_t f1 = f[1];
76872c33676SMaxim Ag   int32_t f2 = f[2];
76972c33676SMaxim Ag   int32_t f3 = f[3];
77072c33676SMaxim Ag   int32_t f4 = f[4];
77172c33676SMaxim Ag   int32_t f5 = f[5];
77272c33676SMaxim Ag   int32_t f6 = f[6];
77372c33676SMaxim Ag   int32_t f7 = f[7];
77472c33676SMaxim Ag   int32_t f8 = f[8];
77572c33676SMaxim Ag   int32_t f9 = f[9];
77672c33676SMaxim Ag   int32_t f0_2 = 2 * f0;
77772c33676SMaxim Ag   int32_t f1_2 = 2 * f1;
77872c33676SMaxim Ag   int32_t f2_2 = 2 * f2;
77972c33676SMaxim Ag   int32_t f3_2 = 2 * f3;
78072c33676SMaxim Ag   int32_t f4_2 = 2 * f4;
78172c33676SMaxim Ag   int32_t f5_2 = 2 * f5;
78272c33676SMaxim Ag   int32_t f6_2 = 2 * f6;
78372c33676SMaxim Ag   int32_t f7_2 = 2 * f7;
78472c33676SMaxim Ag   int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
78572c33676SMaxim Ag   int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
78672c33676SMaxim Ag   int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
78772c33676SMaxim Ag   int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
78872c33676SMaxim Ag   int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
78972c33676SMaxim Ag   int64_t f0f0    = f0   * (int64_t) f0;
79072c33676SMaxim Ag   int64_t f0f1_2  = f0_2 * (int64_t) f1;
79172c33676SMaxim Ag   int64_t f0f2_2  = f0_2 * (int64_t) f2;
79272c33676SMaxim Ag   int64_t f0f3_2  = f0_2 * (int64_t) f3;
79372c33676SMaxim Ag   int64_t f0f4_2  = f0_2 * (int64_t) f4;
79472c33676SMaxim Ag   int64_t f0f5_2  = f0_2 * (int64_t) f5;
79572c33676SMaxim Ag   int64_t f0f6_2  = f0_2 * (int64_t) f6;
79672c33676SMaxim Ag   int64_t f0f7_2  = f0_2 * (int64_t) f7;
79772c33676SMaxim Ag   int64_t f0f8_2  = f0_2 * (int64_t) f8;
79872c33676SMaxim Ag   int64_t f0f9_2  = f0_2 * (int64_t) f9;
79972c33676SMaxim Ag   int64_t f1f1_2  = f1_2 * (int64_t) f1;
80072c33676SMaxim Ag   int64_t f1f2_2  = f1_2 * (int64_t) f2;
80172c33676SMaxim Ag   int64_t f1f3_4  = f1_2 * (int64_t) f3_2;
80272c33676SMaxim Ag   int64_t f1f4_2  = f1_2 * (int64_t) f4;
80372c33676SMaxim Ag   int64_t f1f5_4  = f1_2 * (int64_t) f5_2;
80472c33676SMaxim Ag   int64_t f1f6_2  = f1_2 * (int64_t) f6;
80572c33676SMaxim Ag   int64_t f1f7_4  = f1_2 * (int64_t) f7_2;
80672c33676SMaxim Ag   int64_t f1f8_2  = f1_2 * (int64_t) f8;
80772c33676SMaxim Ag   int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
80872c33676SMaxim Ag   int64_t f2f2    = f2   * (int64_t) f2;
80972c33676SMaxim Ag   int64_t f2f3_2  = f2_2 * (int64_t) f3;
81072c33676SMaxim Ag   int64_t f2f4_2  = f2_2 * (int64_t) f4;
81172c33676SMaxim Ag   int64_t f2f5_2  = f2_2 * (int64_t) f5;
81272c33676SMaxim Ag   int64_t f2f6_2  = f2_2 * (int64_t) f6;
81372c33676SMaxim Ag   int64_t f2f7_2  = f2_2 * (int64_t) f7;
81472c33676SMaxim Ag   int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
81572c33676SMaxim Ag   int64_t f2f9_38 = f2   * (int64_t) f9_38;
81672c33676SMaxim Ag   int64_t f3f3_2  = f3_2 * (int64_t) f3;
81772c33676SMaxim Ag   int64_t f3f4_2  = f3_2 * (int64_t) f4;
81872c33676SMaxim Ag   int64_t f3f5_4  = f3_2 * (int64_t) f5_2;
81972c33676SMaxim Ag   int64_t f3f6_2  = f3_2 * (int64_t) f6;
82072c33676SMaxim Ag   int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
82172c33676SMaxim Ag   int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
82272c33676SMaxim Ag   int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
82372c33676SMaxim Ag   int64_t f4f4    = f4   * (int64_t) f4;
82472c33676SMaxim Ag   int64_t f4f5_2  = f4_2 * (int64_t) f5;
82572c33676SMaxim Ag   int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
82672c33676SMaxim Ag   int64_t f4f7_38 = f4   * (int64_t) f7_38;
82772c33676SMaxim Ag   int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
82872c33676SMaxim Ag   int64_t f4f9_38 = f4   * (int64_t) f9_38;
82972c33676SMaxim Ag   int64_t f5f5_38 = f5   * (int64_t) f5_38;
83072c33676SMaxim Ag   int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
83172c33676SMaxim Ag   int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
83272c33676SMaxim Ag   int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
83372c33676SMaxim Ag   int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
83472c33676SMaxim Ag   int64_t f6f6_19 = f6   * (int64_t) f6_19;
83572c33676SMaxim Ag   int64_t f6f7_38 = f6   * (int64_t) f7_38;
83672c33676SMaxim Ag   int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
83772c33676SMaxim Ag   int64_t f6f9_38 = f6   * (int64_t) f9_38;
83872c33676SMaxim Ag   int64_t f7f7_38 = f7   * (int64_t) f7_38;
83972c33676SMaxim Ag   int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
84072c33676SMaxim Ag   int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
84172c33676SMaxim Ag   int64_t f8f8_19 = f8   * (int64_t) f8_19;
84272c33676SMaxim Ag   int64_t f8f9_38 = f8   * (int64_t) f9_38;
84372c33676SMaxim Ag   int64_t f9f9_38 = f9   * (int64_t) f9_38;
84472c33676SMaxim Ag   int64_t h0 = f0f0  +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38;
84572c33676SMaxim Ag   int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38;
84672c33676SMaxim Ag   int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19;
84772c33676SMaxim Ag   int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38;
84872c33676SMaxim Ag   int64_t h4 = f0f4_2+f1f3_4 +f2f2   +f5f9_76+f6f8_38+f7f7_38;
84972c33676SMaxim Ag   int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38;
85072c33676SMaxim Ag   int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19;
85172c33676SMaxim Ag   int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38;
85272c33676SMaxim Ag   int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4   +f9f9_38;
85372c33676SMaxim Ag   int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2;
85472c33676SMaxim Ag   int64_t carry0;
85572c33676SMaxim Ag   int64_t carry1;
85672c33676SMaxim Ag   int64_t carry2;
85772c33676SMaxim Ag   int64_t carry3;
85872c33676SMaxim Ag   int64_t carry4;
85972c33676SMaxim Ag   int64_t carry5;
86072c33676SMaxim Ag   int64_t carry6;
86172c33676SMaxim Ag   int64_t carry7;
86272c33676SMaxim Ag   int64_t carry8;
86372c33676SMaxim Ag   int64_t carry9;
86472c33676SMaxim Ag 
86572c33676SMaxim Ag   h0 += h0;
86672c33676SMaxim Ag   h1 += h1;
86772c33676SMaxim Ag   h2 += h2;
86872c33676SMaxim Ag   h3 += h3;
86972c33676SMaxim Ag   h4 += h4;
87072c33676SMaxim Ag   h5 += h5;
87172c33676SMaxim Ag   h6 += h6;
87272c33676SMaxim Ag   h7 += h7;
87372c33676SMaxim Ag   h8 += h8;
87472c33676SMaxim Ag   h9 += h9;
87572c33676SMaxim Ag 
87672c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
87772c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
87872c33676SMaxim Ag 
87972c33676SMaxim Ag   carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
88072c33676SMaxim Ag   carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
88172c33676SMaxim Ag 
88272c33676SMaxim Ag   carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
88372c33676SMaxim Ag   carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
88472c33676SMaxim Ag 
88572c33676SMaxim Ag   carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
88672c33676SMaxim Ag   carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
88772c33676SMaxim Ag 
88872c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
88972c33676SMaxim Ag   carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
89072c33676SMaxim Ag 
89172c33676SMaxim Ag   carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
89272c33676SMaxim Ag 
89372c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
89472c33676SMaxim Ag 
89572c33676SMaxim Ag   h[0] = h0;
89672c33676SMaxim Ag   h[1] = h1;
89772c33676SMaxim Ag   h[2] = h2;
89872c33676SMaxim Ag   h[3] = h3;
89972c33676SMaxim Ag   h[4] = h4;
90072c33676SMaxim Ag   h[5] = h5;
90172c33676SMaxim Ag   h[6] = h6;
90272c33676SMaxim Ag   h[7] = h7;
90372c33676SMaxim Ag   h[8] = h8;
90472c33676SMaxim Ag   h[9] = h9;
90572c33676SMaxim Ag }
90672c33676SMaxim Ag 
fe_pow22523(fe out,const fe z)90772c33676SMaxim Ag static void fe_pow22523(fe out, const fe z) {
90872c33676SMaxim Ag   fe t0;
90972c33676SMaxim Ag   fe t1;
91072c33676SMaxim Ag   fe t2;
91172c33676SMaxim Ag   int i;
91272c33676SMaxim Ag 
91372c33676SMaxim Ag   fe_sq(t0, z);
91472c33676SMaxim Ag   for (i = 1; i < 1; ++i) {
91572c33676SMaxim Ag     fe_sq(t0, t0);
91672c33676SMaxim Ag   }
91772c33676SMaxim Ag   fe_sq(t1, t0);
91872c33676SMaxim Ag   for (i = 1; i < 2; ++i) {
91972c33676SMaxim Ag     fe_sq(t1, t1);
92072c33676SMaxim Ag   }
92172c33676SMaxim Ag   fe_mul(t1, z, t1);
92272c33676SMaxim Ag   fe_mul(t0, t0, t1);
92372c33676SMaxim Ag   fe_sq(t0, t0);
92472c33676SMaxim Ag   for (i = 1; i < 1; ++i) {
92572c33676SMaxim Ag     fe_sq(t0, t0);
92672c33676SMaxim Ag   }
92772c33676SMaxim Ag   fe_mul(t0, t1, t0);
92872c33676SMaxim Ag   fe_sq(t1, t0);
92972c33676SMaxim Ag   for (i = 1; i < 5; ++i) {
93072c33676SMaxim Ag     fe_sq(t1, t1);
93172c33676SMaxim Ag   }
93272c33676SMaxim Ag   fe_mul(t0, t1, t0);
93372c33676SMaxim Ag   fe_sq(t1, t0);
93472c33676SMaxim Ag   for (i = 1; i < 10; ++i) {
93572c33676SMaxim Ag     fe_sq(t1, t1);
93672c33676SMaxim Ag   }
93772c33676SMaxim Ag   fe_mul(t1, t1, t0);
93872c33676SMaxim Ag   fe_sq(t2, t1);
93972c33676SMaxim Ag   for (i = 1; i < 20; ++i) {
94072c33676SMaxim Ag     fe_sq(t2, t2);
94172c33676SMaxim Ag   }
94272c33676SMaxim Ag   fe_mul(t1, t2, t1);
94372c33676SMaxim Ag   fe_sq(t1, t1);
94472c33676SMaxim Ag   for (i = 1; i < 10; ++i) {
94572c33676SMaxim Ag     fe_sq(t1, t1);
94672c33676SMaxim Ag   }
94772c33676SMaxim Ag   fe_mul(t0, t1, t0);
94872c33676SMaxim Ag   fe_sq(t1, t0);
94972c33676SMaxim Ag   for (i = 1; i < 50; ++i) {
95072c33676SMaxim Ag     fe_sq(t1, t1);
95172c33676SMaxim Ag   }
95272c33676SMaxim Ag   fe_mul(t1, t1, t0);
95372c33676SMaxim Ag   fe_sq(t2, t1);
95472c33676SMaxim Ag   for (i = 1; i < 100; ++i) {
95572c33676SMaxim Ag     fe_sq(t2, t2);
95672c33676SMaxim Ag   }
95772c33676SMaxim Ag   fe_mul(t1, t2, t1);
95872c33676SMaxim Ag   fe_sq(t1, t1);
95972c33676SMaxim Ag   for (i = 1; i < 50; ++i) {
96072c33676SMaxim Ag     fe_sq(t1, t1);
96172c33676SMaxim Ag   }
96272c33676SMaxim Ag   fe_mul(t0, t1, t0);
96372c33676SMaxim Ag   fe_sq(t0, t0);
96472c33676SMaxim Ag   for (i = 1; i < 2; ++i) {
96572c33676SMaxim Ag     fe_sq(t0, t0);
96672c33676SMaxim Ag   }
96772c33676SMaxim Ag   fe_mul(out, t0, z);
96872c33676SMaxim Ag }
96972c33676SMaxim Ag 
x25519_ge_tobytes(uint8_t * s,const ge_p2 * h)97072c33676SMaxim Ag void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h) {
97172c33676SMaxim Ag   fe recip;
97272c33676SMaxim Ag   fe x;
97372c33676SMaxim Ag   fe y;
97472c33676SMaxim Ag 
97572c33676SMaxim Ag   fe_invert(recip, h->Z);
97672c33676SMaxim Ag   fe_mul(x, h->X, recip);
97772c33676SMaxim Ag   fe_mul(y, h->Y, recip);
97872c33676SMaxim Ag   fe_tobytes(s, y);
97972c33676SMaxim Ag   s[31] ^= fe_isnegative(x) << 7;
98072c33676SMaxim Ag }
98172c33676SMaxim Ag 
98272c33676SMaxim Ag #ifdef ED25519
ge_p3_tobytes(uint8_t * s,const ge_p3 * h)98372c33676SMaxim Ag static void ge_p3_tobytes(uint8_t *s, const ge_p3 *h) {
98472c33676SMaxim Ag   fe recip;
98572c33676SMaxim Ag   fe x;
98672c33676SMaxim Ag   fe y;
98772c33676SMaxim Ag 
98872c33676SMaxim Ag   fe_invert(recip, h->Z);
98972c33676SMaxim Ag   fe_mul(x, h->X, recip);
99072c33676SMaxim Ag   fe_mul(y, h->Y, recip);
99172c33676SMaxim Ag   fe_tobytes(s, y);
99272c33676SMaxim Ag   s[31] ^= fe_isnegative(x) << 7;
99372c33676SMaxim Ag }
99472c33676SMaxim Ag #endif
99572c33676SMaxim Ag 
99672c33676SMaxim Ag static const fe d = {-10913610, 13857413, -15372611, 6949391,   114729,
99772c33676SMaxim Ag                      -8787816,  -6275908, -3247719,  -18696448, -12055116};
99872c33676SMaxim Ag 
99972c33676SMaxim Ag static const fe sqrtm1 = {-32595792, -7943725,  9377950,  3500415, 12389472,
100072c33676SMaxim Ag                           -272473,   -25146209, -2005654, 326686,  11406482};
100172c33676SMaxim Ag 
x25519_ge_frombytes_vartime(ge_p3 * h,const uint8_t * s)100272c33676SMaxim Ag int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
100372c33676SMaxim Ag   fe u;
100472c33676SMaxim Ag   fe v;
100572c33676SMaxim Ag   fe v3;
100672c33676SMaxim Ag   fe vxx;
100772c33676SMaxim Ag   fe check;
100872c33676SMaxim Ag 
100972c33676SMaxim Ag   fe_frombytes(h->Y, s);
101072c33676SMaxim Ag   fe_1(h->Z);
101172c33676SMaxim Ag   fe_sq(u, h->Y);
101272c33676SMaxim Ag   fe_mul(v, u, d);
101372c33676SMaxim Ag   fe_sub(u, u, h->Z); /* u = y^2-1 */
101472c33676SMaxim Ag   fe_add(v, v, h->Z); /* v = dy^2+1 */
101572c33676SMaxim Ag 
101672c33676SMaxim Ag   fe_sq(v3, v);
101772c33676SMaxim Ag   fe_mul(v3, v3, v); /* v3 = v^3 */
101872c33676SMaxim Ag   fe_sq(h->X, v3);
101972c33676SMaxim Ag   fe_mul(h->X, h->X, v);
102072c33676SMaxim Ag   fe_mul(h->X, h->X, u); /* x = uv^7 */
102172c33676SMaxim Ag 
102272c33676SMaxim Ag   fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
102372c33676SMaxim Ag   fe_mul(h->X, h->X, v3);
102472c33676SMaxim Ag   fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
102572c33676SMaxim Ag 
102672c33676SMaxim Ag   fe_sq(vxx, h->X);
102772c33676SMaxim Ag   fe_mul(vxx, vxx, v);
102872c33676SMaxim Ag   fe_sub(check, vxx, u); /* vx^2-u */
102972c33676SMaxim Ag   if (fe_isnonzero(check)) {
103072c33676SMaxim Ag     fe_add(check, vxx, u); /* vx^2+u */
103172c33676SMaxim Ag     if (fe_isnonzero(check)) {
103272c33676SMaxim Ag       return -1;
103372c33676SMaxim Ag     }
103472c33676SMaxim Ag     fe_mul(h->X, h->X, sqrtm1);
103572c33676SMaxim Ag   }
103672c33676SMaxim Ag 
103772c33676SMaxim Ag   if (fe_isnegative(h->X) != (s[31] >> 7)) {
103872c33676SMaxim Ag     fe_neg(h->X, h->X);
103972c33676SMaxim Ag   }
104072c33676SMaxim Ag 
104172c33676SMaxim Ag   fe_mul(h->T, h->X, h->Y);
104272c33676SMaxim Ag   return 0;
104372c33676SMaxim Ag }
104472c33676SMaxim Ag 
ge_p2_0(ge_p2 * h)104572c33676SMaxim Ag static void ge_p2_0(ge_p2 *h) {
104672c33676SMaxim Ag   fe_0(h->X);
104772c33676SMaxim Ag   fe_1(h->Y);
104872c33676SMaxim Ag   fe_1(h->Z);
104972c33676SMaxim Ag }
105072c33676SMaxim Ag 
ge_p3_0(ge_p3 * h)105172c33676SMaxim Ag static void ge_p3_0(ge_p3 *h) {
105272c33676SMaxim Ag   fe_0(h->X);
105372c33676SMaxim Ag   fe_1(h->Y);
105472c33676SMaxim Ag   fe_1(h->Z);
105572c33676SMaxim Ag   fe_0(h->T);
105672c33676SMaxim Ag }
105772c33676SMaxim Ag 
ge_cached_0(ge_cached * h)105872c33676SMaxim Ag static void ge_cached_0(ge_cached *h) {
105972c33676SMaxim Ag   fe_1(h->YplusX);
106072c33676SMaxim Ag   fe_1(h->YminusX);
106172c33676SMaxim Ag   fe_1(h->Z);
106272c33676SMaxim Ag   fe_0(h->T2d);
106372c33676SMaxim Ag }
106472c33676SMaxim Ag 
ge_precomp_0(ge_precomp * h)106572c33676SMaxim Ag static void ge_precomp_0(ge_precomp *h) {
106672c33676SMaxim Ag   fe_1(h->yplusx);
106772c33676SMaxim Ag   fe_1(h->yminusx);
106872c33676SMaxim Ag   fe_0(h->xy2d);
106972c33676SMaxim Ag }
107072c33676SMaxim Ag 
107172c33676SMaxim Ag /* r = p */
ge_p3_to_p2(ge_p2 * r,const ge_p3 * p)107272c33676SMaxim Ag static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
107372c33676SMaxim Ag   fe_copy(r->X, p->X);
107472c33676SMaxim Ag   fe_copy(r->Y, p->Y);
107572c33676SMaxim Ag   fe_copy(r->Z, p->Z);
107672c33676SMaxim Ag }
107772c33676SMaxim Ag 
107872c33676SMaxim Ag static const fe d2 = {-21827239, -5839606,  -30745221, 13898782, 229458,
107972c33676SMaxim Ag                       15978800,  -12551817, -6495438,  29715968, 9444199};
108072c33676SMaxim Ag 
108172c33676SMaxim Ag /* r = p */
x25519_ge_p3_to_cached(ge_cached * r,const ge_p3 * p)108272c33676SMaxim Ag void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
108372c33676SMaxim Ag   fe_add(r->YplusX, p->Y, p->X);
108472c33676SMaxim Ag   fe_sub(r->YminusX, p->Y, p->X);
108572c33676SMaxim Ag   fe_copy(r->Z, p->Z);
108672c33676SMaxim Ag   fe_mul(r->T2d, p->T, d2);
108772c33676SMaxim Ag }
108872c33676SMaxim Ag 
108972c33676SMaxim Ag /* r = p */
x25519_ge_p1p1_to_p2(ge_p2 * r,const ge_p1p1 * p)109072c33676SMaxim Ag void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
109172c33676SMaxim Ag   fe_mul(r->X, p->X, p->T);
109272c33676SMaxim Ag   fe_mul(r->Y, p->Y, p->Z);
109372c33676SMaxim Ag   fe_mul(r->Z, p->Z, p->T);
109472c33676SMaxim Ag }
109572c33676SMaxim Ag 
109672c33676SMaxim Ag /* r = p */
x25519_ge_p1p1_to_p3(ge_p3 * r,const ge_p1p1 * p)109772c33676SMaxim Ag void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
109872c33676SMaxim Ag   fe_mul(r->X, p->X, p->T);
109972c33676SMaxim Ag   fe_mul(r->Y, p->Y, p->Z);
110072c33676SMaxim Ag   fe_mul(r->Z, p->Z, p->T);
110172c33676SMaxim Ag   fe_mul(r->T, p->X, p->Y);
110272c33676SMaxim Ag }
110372c33676SMaxim Ag 
110472c33676SMaxim Ag /* r = p */
ge_p1p1_to_cached(ge_cached * r,const ge_p1p1 * p)110572c33676SMaxim Ag static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) {
110672c33676SMaxim Ag   ge_p3 t;
110772c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&t, p);
110872c33676SMaxim Ag   x25519_ge_p3_to_cached(r, &t);
110972c33676SMaxim Ag }
111072c33676SMaxim Ag 
111172c33676SMaxim Ag /* r = 2 * p */
ge_p2_dbl(ge_p1p1 * r,const ge_p2 * p)111272c33676SMaxim Ag static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
111372c33676SMaxim Ag   fe t0;
111472c33676SMaxim Ag 
111572c33676SMaxim Ag   fe_sq(r->X, p->X);
111672c33676SMaxim Ag   fe_sq(r->Z, p->Y);
111772c33676SMaxim Ag   fe_sq2(r->T, p->Z);
111872c33676SMaxim Ag   fe_add(r->Y, p->X, p->Y);
111972c33676SMaxim Ag   fe_sq(t0, r->Y);
112072c33676SMaxim Ag   fe_add(r->Y, r->Z, r->X);
112172c33676SMaxim Ag   fe_sub(r->Z, r->Z, r->X);
112272c33676SMaxim Ag   fe_sub(r->X, t0, r->Y);
112372c33676SMaxim Ag   fe_sub(r->T, r->T, r->Z);
112472c33676SMaxim Ag }
112572c33676SMaxim Ag 
112672c33676SMaxim Ag /* r = 2 * p */
ge_p3_dbl(ge_p1p1 * r,const ge_p3 * p)112772c33676SMaxim Ag static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
112872c33676SMaxim Ag   ge_p2 q;
112972c33676SMaxim Ag   ge_p3_to_p2(&q, p);
113072c33676SMaxim Ag   ge_p2_dbl(r, &q);
113172c33676SMaxim Ag }
113272c33676SMaxim Ag 
113372c33676SMaxim Ag /* r = p + q */
ge_madd(ge_p1p1 * r,const ge_p3 * p,const ge_precomp * q)113472c33676SMaxim Ag static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
113572c33676SMaxim Ag   fe t0;
113672c33676SMaxim Ag 
113772c33676SMaxim Ag   fe_add(r->X, p->Y, p->X);
113872c33676SMaxim Ag   fe_sub(r->Y, p->Y, p->X);
113972c33676SMaxim Ag   fe_mul(r->Z, r->X, q->yplusx);
114072c33676SMaxim Ag   fe_mul(r->Y, r->Y, q->yminusx);
114172c33676SMaxim Ag   fe_mul(r->T, q->xy2d, p->T);
114272c33676SMaxim Ag   fe_add(t0, p->Z, p->Z);
114372c33676SMaxim Ag   fe_sub(r->X, r->Z, r->Y);
114472c33676SMaxim Ag   fe_add(r->Y, r->Z, r->Y);
114572c33676SMaxim Ag   fe_add(r->Z, t0, r->T);
114672c33676SMaxim Ag   fe_sub(r->T, t0, r->T);
114772c33676SMaxim Ag }
114872c33676SMaxim Ag 
114972c33676SMaxim Ag #ifdef ED25519
115072c33676SMaxim Ag /* r = p - q */
ge_msub(ge_p1p1 * r,const ge_p3 * p,const ge_precomp * q)115172c33676SMaxim Ag static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
115272c33676SMaxim Ag   fe t0;
115372c33676SMaxim Ag 
115472c33676SMaxim Ag   fe_add(r->X, p->Y, p->X);
115572c33676SMaxim Ag   fe_sub(r->Y, p->Y, p->X);
115672c33676SMaxim Ag   fe_mul(r->Z, r->X, q->yminusx);
115772c33676SMaxim Ag   fe_mul(r->Y, r->Y, q->yplusx);
115872c33676SMaxim Ag   fe_mul(r->T, q->xy2d, p->T);
115972c33676SMaxim Ag   fe_add(t0, p->Z, p->Z);
116072c33676SMaxim Ag   fe_sub(r->X, r->Z, r->Y);
116172c33676SMaxim Ag   fe_add(r->Y, r->Z, r->Y);
116272c33676SMaxim Ag   fe_sub(r->Z, t0, r->T);
116372c33676SMaxim Ag   fe_add(r->T, t0, r->T);
116472c33676SMaxim Ag }
116572c33676SMaxim Ag #endif
116672c33676SMaxim Ag 
116772c33676SMaxim Ag /* r = p + q */
x25519_ge_add(ge_p1p1 * r,const ge_p3 * p,const ge_cached * q)116872c33676SMaxim Ag void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
116972c33676SMaxim Ag   fe t0;
117072c33676SMaxim Ag 
117172c33676SMaxim Ag   fe_add(r->X, p->Y, p->X);
117272c33676SMaxim Ag   fe_sub(r->Y, p->Y, p->X);
117372c33676SMaxim Ag   fe_mul(r->Z, r->X, q->YplusX);
117472c33676SMaxim Ag   fe_mul(r->Y, r->Y, q->YminusX);
117572c33676SMaxim Ag   fe_mul(r->T, q->T2d, p->T);
117672c33676SMaxim Ag   fe_mul(r->X, p->Z, q->Z);
117772c33676SMaxim Ag   fe_add(t0, r->X, r->X);
117872c33676SMaxim Ag   fe_sub(r->X, r->Z, r->Y);
117972c33676SMaxim Ag   fe_add(r->Y, r->Z, r->Y);
118072c33676SMaxim Ag   fe_add(r->Z, t0, r->T);
118172c33676SMaxim Ag   fe_sub(r->T, t0, r->T);
118272c33676SMaxim Ag }
118372c33676SMaxim Ag 
118472c33676SMaxim Ag /* r = p - q */
x25519_ge_sub(ge_p1p1 * r,const ge_p3 * p,const ge_cached * q)118572c33676SMaxim Ag void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
118672c33676SMaxim Ag   fe t0;
118772c33676SMaxim Ag 
118872c33676SMaxim Ag   fe_add(r->X, p->Y, p->X);
118972c33676SMaxim Ag   fe_sub(r->Y, p->Y, p->X);
119072c33676SMaxim Ag   fe_mul(r->Z, r->X, q->YminusX);
119172c33676SMaxim Ag   fe_mul(r->Y, r->Y, q->YplusX);
119272c33676SMaxim Ag   fe_mul(r->T, q->T2d, p->T);
119372c33676SMaxim Ag   fe_mul(r->X, p->Z, q->Z);
119472c33676SMaxim Ag   fe_add(t0, r->X, r->X);
119572c33676SMaxim Ag   fe_sub(r->X, r->Z, r->Y);
119672c33676SMaxim Ag   fe_add(r->Y, r->Z, r->Y);
119772c33676SMaxim Ag   fe_sub(r->Z, t0, r->T);
119872c33676SMaxim Ag   fe_add(r->T, t0, r->T);
119972c33676SMaxim Ag }
120072c33676SMaxim Ag 
equal(signed char b,signed char c)120172c33676SMaxim Ag static uint8_t equal(signed char b, signed char c) {
120272c33676SMaxim Ag   uint8_t ub = b;
120372c33676SMaxim Ag   uint8_t uc = c;
120472c33676SMaxim Ag   uint8_t x = ub ^ uc; /* 0: yes; 1..255: no */
120572c33676SMaxim Ag   uint32_t y = x;      /* 0: yes; 1..255: no */
120672c33676SMaxim Ag   y -= 1;              /* 4294967295: yes; 0..254: no */
120772c33676SMaxim Ag   y >>= 31;            /* 1: yes; 0: no */
120872c33676SMaxim Ag   return y;
120972c33676SMaxim Ag }
121072c33676SMaxim Ag 
cmov(ge_precomp * t,const ge_precomp * u,uint8_t b)121172c33676SMaxim Ag static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) {
121272c33676SMaxim Ag   fe_cmov(t->yplusx, u->yplusx, b);
121372c33676SMaxim Ag   fe_cmov(t->yminusx, u->yminusx, b);
121472c33676SMaxim Ag   fe_cmov(t->xy2d, u->xy2d, b);
121572c33676SMaxim Ag }
121672c33676SMaxim Ag 
x25519_ge_scalarmult_small_precomp(ge_p3 * h,const uint8_t a[32],const uint8_t precomp_table[15* 2* 32])121772c33676SMaxim Ag void x25519_ge_scalarmult_small_precomp(
121872c33676SMaxim Ag     ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) {
121972c33676SMaxim Ag   /* precomp_table is first expanded into matching |ge_precomp|
122072c33676SMaxim Ag    * elements. */
122172c33676SMaxim Ag   ge_precomp multiples[15];
122272c33676SMaxim Ag 
122372c33676SMaxim Ag   unsigned i;
122472c33676SMaxim Ag   for (i = 0; i < 15; i++) {
122572c33676SMaxim Ag     const uint8_t *bytes = &precomp_table[i*(2 * 32)];
122672c33676SMaxim Ag     fe x, y;
122772c33676SMaxim Ag     fe_frombytes(x, bytes);
122872c33676SMaxim Ag     fe_frombytes(y, bytes + 32);
122972c33676SMaxim Ag 
123072c33676SMaxim Ag     ge_precomp *out = &multiples[i];
123172c33676SMaxim Ag     fe_add(out->yplusx, y, x);
123272c33676SMaxim Ag     fe_sub(out->yminusx, y, x);
123372c33676SMaxim Ag     fe_mul(out->xy2d, x, y);
123472c33676SMaxim Ag     fe_mul(out->xy2d, out->xy2d, d2);
123572c33676SMaxim Ag   }
123672c33676SMaxim Ag 
123772c33676SMaxim Ag   /* See the comment above |k25519SmallPrecomp| about the structure of the
123872c33676SMaxim Ag    * precomputed elements. This loop does 64 additions and 64 doublings to
123972c33676SMaxim Ag    * calculate the result. */
124072c33676SMaxim Ag   ge_p3_0(h);
124172c33676SMaxim Ag 
124272c33676SMaxim Ag   for (i = 63; i < 64; i--) {
124372c33676SMaxim Ag     unsigned j;
124472c33676SMaxim Ag     signed char index = 0;
124572c33676SMaxim Ag 
124672c33676SMaxim Ag     for (j = 0; j < 4; j++) {
124772c33676SMaxim Ag       const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
124872c33676SMaxim Ag       index |= (bit << j);
124972c33676SMaxim Ag     }
125072c33676SMaxim Ag 
125172c33676SMaxim Ag     ge_precomp e;
125272c33676SMaxim Ag     ge_precomp_0(&e);
125372c33676SMaxim Ag 
125472c33676SMaxim Ag     for (j = 1; j < 16; j++) {
125572c33676SMaxim Ag       cmov(&e, &multiples[j-1], equal(index, j));
125672c33676SMaxim Ag     }
125772c33676SMaxim Ag 
125872c33676SMaxim Ag     ge_cached cached;
125972c33676SMaxim Ag     ge_p1p1 r;
126072c33676SMaxim Ag     x25519_ge_p3_to_cached(&cached, h);
126172c33676SMaxim Ag     x25519_ge_add(&r, h, &cached);
126272c33676SMaxim Ag     x25519_ge_p1p1_to_p3(h, &r);
126372c33676SMaxim Ag 
126472c33676SMaxim Ag     ge_madd(&r, h, &e);
126572c33676SMaxim Ag     x25519_ge_p1p1_to_p3(h, &r);
126672c33676SMaxim Ag   }
126772c33676SMaxim Ag }
126872c33676SMaxim Ag 
126972c33676SMaxim Ag #if defined(OPENSSL_SMALL)
127072c33676SMaxim Ag 
127172c33676SMaxim Ag /* This block of code replaces the standard base-point table with a much smaller
127272c33676SMaxim Ag  * one. The standard table is 30,720 bytes while this one is just 960.
127372c33676SMaxim Ag  *
127472c33676SMaxim Ag  * This table contains 15 pairs of group elements, (x, y), where each field
127572c33676SMaxim Ag  * element is serialised with |fe_tobytes|. If |i| is the index of the group
127672c33676SMaxim Ag  * element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀
127772c33676SMaxim Ag  * is the most significant bit). The value of the group element is then:
127872c33676SMaxim Ag  * (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator. */
127972c33676SMaxim Ag static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {
128072c33676SMaxim Ag     0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
128172c33676SMaxim Ag     0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
128272c33676SMaxim Ag     0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21, 0x58, 0x66, 0x66, 0x66,
128372c33676SMaxim Ag     0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
128472c33676SMaxim Ag     0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
128572c33676SMaxim Ag     0x66, 0x66, 0x66, 0x66, 0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e,
128672c33676SMaxim Ag     0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4,
128772c33676SMaxim Ag     0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62,
128872c33676SMaxim Ag     0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba,
128972c33676SMaxim Ag     0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd,
129072c33676SMaxim Ag     0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03, 0xa2, 0xfb, 0xcc, 0x61,
129172c33676SMaxim Ag     0x67, 0x06, 0x70, 0x1a, 0xc4, 0x78, 0x3a, 0xff, 0x32, 0x62, 0xdd, 0x2c,
129272c33676SMaxim Ag     0xab, 0x50, 0x19, 0x3b, 0xf2, 0x9b, 0x7d, 0xb8, 0xfd, 0x4f, 0x29, 0x9c,
129372c33676SMaxim Ag     0xa7, 0x91, 0xba, 0x0e, 0x46, 0x5e, 0x51, 0xfe, 0x1d, 0xbf, 0xe5, 0xe5,
129472c33676SMaxim Ag     0x9b, 0x95, 0x0d, 0x67, 0xf8, 0xd1, 0xb5, 0x5a, 0xa1, 0x93, 0x2c, 0xc3,
129572c33676SMaxim Ag     0xde, 0x0e, 0x97, 0x85, 0x2d, 0x7f, 0xea, 0xab, 0x3e, 0x47, 0x30, 0x18,
129672c33676SMaxim Ag     0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2,
129772c33676SMaxim Ag     0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95,
129872c33676SMaxim Ag     0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c, 0x6b, 0xa6, 0xf5, 0x4b,
129972c33676SMaxim Ag     0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90,
130072c33676SMaxim Ag     0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52,
130172c33676SMaxim Ag     0xe6, 0x99, 0x2c, 0x5f, 0x9a, 0x96, 0x0c, 0x68, 0x29, 0xfd, 0xe2, 0xfb,
130272c33676SMaxim Ag     0xe6, 0xbc, 0xec, 0x31, 0x08, 0xec, 0xe6, 0xb0, 0x53, 0x60, 0xc3, 0x8c,
130372c33676SMaxim Ag     0xbe, 0xc1, 0xb3, 0x8a, 0x8f, 0xe4, 0x88, 0x2b, 0x55, 0xe5, 0x64, 0x6e,
130472c33676SMaxim Ag     0x9b, 0xd0, 0xaf, 0x7b, 0x64, 0x2a, 0x35, 0x25, 0x10, 0x52, 0xc5, 0x9e,
130572c33676SMaxim Ag     0x58, 0x11, 0x39, 0x36, 0x45, 0x51, 0xb8, 0x39, 0x93, 0xfc, 0x9d, 0x6a,
130672c33676SMaxim Ag     0xbe, 0x58, 0xcb, 0xa4, 0x0f, 0x51, 0x3c, 0x38, 0x05, 0xca, 0xab, 0x43,
130772c33676SMaxim Ag     0x63, 0x0e, 0xf3, 0x8b, 0x41, 0xa6, 0xf8, 0x9b, 0x53, 0x70, 0x80, 0x53,
130872c33676SMaxim Ag     0x86, 0x5e, 0x8f, 0xe3, 0xc3, 0x0d, 0x18, 0xc8, 0x4b, 0x34, 0x1f, 0xd8,
130972c33676SMaxim Ag     0x1d, 0xbc, 0xf2, 0x6d, 0x34, 0x3a, 0xbe, 0xdf, 0xd9, 0xf6, 0xf3, 0x89,
131072c33676SMaxim Ag     0xa1, 0xe1, 0x94, 0x9f, 0x5d, 0x4c, 0x5d, 0xe9, 0xa1, 0x49, 0x92, 0xef,
131172c33676SMaxim Ag     0x0e, 0x53, 0x81, 0x89, 0x58, 0x87, 0xa6, 0x37, 0xf1, 0xdd, 0x62, 0x60,
131272c33676SMaxim Ag     0x63, 0x5a, 0x9d, 0x1b, 0x8c, 0xc6, 0x7d, 0x52, 0xea, 0x70, 0x09, 0x6a,
131372c33676SMaxim Ag     0xe1, 0x32, 0xf3, 0x73, 0x21, 0x1f, 0x07, 0x7b, 0x7c, 0x9b, 0x49, 0xd8,
131472c33676SMaxim Ag     0xc0, 0xf3, 0x25, 0x72, 0x6f, 0x9d, 0xed, 0x31, 0x67, 0x36, 0x36, 0x54,
131572c33676SMaxim Ag     0x40, 0x92, 0x71, 0xe6, 0x11, 0x28, 0x11, 0xad, 0x93, 0x32, 0x85, 0x7b,
131672c33676SMaxim Ag     0x3e, 0xb7, 0x3b, 0x49, 0x13, 0x1c, 0x07, 0xb0, 0x2e, 0x93, 0xaa, 0xfd,
131772c33676SMaxim Ag     0xfd, 0x28, 0x47, 0x3d, 0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb,
131872c33676SMaxim Ag     0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c,
131972c33676SMaxim Ag     0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b,
132072c33676SMaxim Ag     0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63,
132172c33676SMaxim Ag     0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a,
132272c33676SMaxim Ag     0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61, 0x38, 0x68, 0xb0, 0x07,
132372c33676SMaxim Ag     0xa3, 0xfc, 0xcc, 0x85, 0x10, 0x7f, 0x4c, 0x65, 0x65, 0xb3, 0xfa, 0xfa,
132472c33676SMaxim Ag     0xa5, 0x53, 0x6f, 0xdb, 0x74, 0x4c, 0x56, 0x46, 0x03, 0xe2, 0xd5, 0x7a,
132572c33676SMaxim Ag     0x29, 0x1c, 0xc6, 0x02, 0xbc, 0x59, 0xf2, 0x04, 0x75, 0x63, 0xc0, 0x84,
132672c33676SMaxim Ag     0x2f, 0x60, 0x1c, 0x67, 0x76, 0xfd, 0x63, 0x86, 0xf3, 0xfa, 0xbf, 0xdc,
132772c33676SMaxim Ag     0xd2, 0x2d, 0x90, 0x91, 0xbd, 0x33, 0xa9, 0xe5, 0x66, 0x0c, 0xda, 0x42,
132872c33676SMaxim Ag     0x27, 0xca, 0xf4, 0x66, 0xc2, 0xec, 0x92, 0x14, 0x57, 0x06, 0x63, 0xd0,
132972c33676SMaxim Ag     0x4d, 0x15, 0x06, 0xeb, 0x69, 0x58, 0x4f, 0x77, 0xc5, 0x8b, 0xc7, 0xf0,
133072c33676SMaxim Ag     0x8e, 0xed, 0x64, 0xa0, 0xb3, 0x3c, 0x66, 0x71, 0xc6, 0x2d, 0xda, 0x0a,
133172c33676SMaxim Ag     0x0d, 0xfe, 0x70, 0x27, 0x64, 0xf8, 0x27, 0xfa, 0xf6, 0x5f, 0x30, 0xa5,
133272c33676SMaxim Ag     0x0d, 0x6c, 0xda, 0xf2, 0x62, 0x5e, 0x78, 0x47, 0xd3, 0x66, 0x00, 0x1c,
133372c33676SMaxim Ag     0xfd, 0x56, 0x1f, 0x5d, 0x3f, 0x6f, 0xf4, 0x4c, 0xd8, 0xfd, 0x0e, 0x27,
133472c33676SMaxim Ag     0xc9, 0x5c, 0x2b, 0xbc, 0xc0, 0xa4, 0xe7, 0x23, 0x29, 0x02, 0x9f, 0x31,
133572c33676SMaxim Ag     0xd6, 0xe9, 0xd7, 0x96, 0xf4, 0xe0, 0x5e, 0x0b, 0x0e, 0x13, 0xee, 0x3c,
133672c33676SMaxim Ag     0x09, 0xed, 0xf2, 0x3d, 0x76, 0x91, 0xc3, 0xa4, 0x97, 0xae, 0xd4, 0x87,
133772c33676SMaxim Ag     0xd0, 0x5d, 0xf6, 0x18, 0x47, 0x1f, 0x1d, 0x67, 0xf2, 0xcf, 0x63, 0xa0,
133872c33676SMaxim Ag     0x91, 0x27, 0xf8, 0x93, 0x45, 0x75, 0x23, 0x3f, 0xd1, 0xf1, 0xad, 0x23,
133972c33676SMaxim Ag     0xdd, 0x64, 0x93, 0x96, 0x41, 0x70, 0x7f, 0xf7, 0xf5, 0xa9, 0x89, 0xa2,
134072c33676SMaxim Ag     0x34, 0xb0, 0x8d, 0x1b, 0xae, 0x19, 0x15, 0x49, 0x58, 0x23, 0x6d, 0x87,
134172c33676SMaxim Ag     0x15, 0x4f, 0x81, 0x76, 0xfb, 0x23, 0xb5, 0xea, 0xcf, 0xac, 0x54, 0x8d,
134272c33676SMaxim Ag     0x4e, 0x42, 0x2f, 0xeb, 0x0f, 0x63, 0xdb, 0x68, 0x37, 0xa8, 0xcf, 0x8b,
134372c33676SMaxim Ag     0xab, 0xf5, 0xa4, 0x6e, 0x96, 0x2a, 0xb2, 0xd6, 0xbe, 0x9e, 0xbd, 0x0d,
134472c33676SMaxim Ag     0xb4, 0x42, 0xa9, 0xcf, 0x01, 0x83, 0x8a, 0x17, 0x47, 0x76, 0xc4, 0xc6,
134572c33676SMaxim Ag     0x83, 0x04, 0x95, 0x0b, 0xfc, 0x11, 0xc9, 0x62, 0xb8, 0x0c, 0x76, 0x84,
134672c33676SMaxim Ag     0xd9, 0xb9, 0x37, 0xfa, 0xfc, 0x7c, 0xc2, 0x6d, 0x58, 0x3e, 0xb3, 0x04,
134772c33676SMaxim Ag     0xbb, 0x8c, 0x8f, 0x48, 0xbc, 0x91, 0x27, 0xcc, 0xf9, 0xb7, 0x22, 0x19,
134872c33676SMaxim Ag     0x83, 0x2e, 0x09, 0xb5, 0x72, 0xd9, 0x54, 0x1c, 0x4d, 0xa1, 0xea, 0x0b,
134972c33676SMaxim Ag     0xf1, 0xc6, 0x08, 0x72, 0x46, 0x87, 0x7a, 0x6e, 0x80, 0x56, 0x0a, 0x8a,
135072c33676SMaxim Ag     0xc0, 0xdd, 0x11, 0x6b, 0xd6, 0xdd, 0x47, 0xdf, 0x10, 0xd9, 0xd8, 0xea,
135172c33676SMaxim Ag     0x7c, 0xb0, 0x8f, 0x03, 0x00, 0x2e, 0xc1, 0x8f, 0x44, 0xa8, 0xd3, 0x30,
135272c33676SMaxim Ag     0x06, 0x89, 0xa2, 0xf9, 0x34, 0xad, 0xdc, 0x03, 0x85, 0xed, 0x51, 0xa7,
135372c33676SMaxim Ag     0x82, 0x9c, 0xe7, 0x5d, 0x52, 0x93, 0x0c, 0x32, 0x9a, 0x5b, 0xe1, 0xaa,
135472c33676SMaxim Ag     0xca, 0xb8, 0x02, 0x6d, 0x3a, 0xd4, 0xb1, 0x3a, 0xf0, 0x5f, 0xbe, 0xb5,
135572c33676SMaxim Ag     0x0d, 0x10, 0x6b, 0x38, 0x32, 0xac, 0x76, 0x80, 0xbd, 0xca, 0x94, 0x71,
135672c33676SMaxim Ag     0x7a, 0xf2, 0xc9, 0x35, 0x2a, 0xde, 0x9f, 0x42, 0x49, 0x18, 0x01, 0xab,
135772c33676SMaxim Ag     0xbc, 0xef, 0x7c, 0x64, 0x3f, 0x58, 0x3d, 0x92, 0x59, 0xdb, 0x13, 0xdb,
135872c33676SMaxim Ag     0x58, 0x6e, 0x0a, 0xe0, 0xb7, 0x91, 0x4a, 0x08, 0x20, 0xd6, 0x2e, 0x3c,
135972c33676SMaxim Ag     0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25,
136072c33676SMaxim Ag };
136172c33676SMaxim Ag 
x25519_ge_scalarmult_base(ge_p3 * h,const uint8_t a[32])136272c33676SMaxim Ag void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
136372c33676SMaxim Ag   x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp);
136472c33676SMaxim Ag }
136572c33676SMaxim Ag 
136672c33676SMaxim Ag #else
136772c33676SMaxim Ag 
136872c33676SMaxim Ag /* k25519Precomp[i][j] = (j+1)*256^i*B */
136972c33676SMaxim Ag static const ge_precomp k25519Precomp[32][8] = {
137072c33676SMaxim Ag     {
137172c33676SMaxim Ag         {
137272c33676SMaxim Ag             {25967493, -14356035, 29566456, 3660896, -12694345, 4014787,
137372c33676SMaxim Ag              27544626, -11754271, -6079156, 2047605},
137472c33676SMaxim Ag             {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692,
137572c33676SMaxim Ag              5043384, 19500929, -15469378},
137672c33676SMaxim Ag             {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380,
137772c33676SMaxim Ag              29287919, 11864899, -24514362, -4438546},
137872c33676SMaxim Ag         },
137972c33676SMaxim Ag         {
138072c33676SMaxim Ag             {-12815894, -12976347, -21581243, 11784320, -25355658, -2750717,
138172c33676SMaxim Ag              -11717903, -3814571, -358445, -10211303},
138272c33676SMaxim Ag             {-21703237, 6903825, 27185491, 6451973, -29577724, -9554005,
138372c33676SMaxim Ag              -15616551, 11189268, -26829678, -5319081},
138472c33676SMaxim Ag             {26966642, 11152617, 32442495, 15396054, 14353839, -12752335,
138572c33676SMaxim Ag              -3128826, -9541118, -15472047, -4166697},
138672c33676SMaxim Ag         },
138772c33676SMaxim Ag         {
138872c33676SMaxim Ag             {15636291, -9688557, 24204773, -7912398, 616977, -16685262,
138972c33676SMaxim Ag              27787600, -14772189, 28944400, -1550024},
139072c33676SMaxim Ag             {16568933, 4717097, -11556148, -1102322, 15682896, -11807043,
139172c33676SMaxim Ag              16354577, -11775962, 7689662, 11199574},
139272c33676SMaxim Ag             {30464156, -5976125, -11779434, -15670865, 23220365, 15915852,
139372c33676SMaxim Ag              7512774, 10017326, -17749093, -9920357},
139472c33676SMaxim Ag         },
139572c33676SMaxim Ag         {
139672c33676SMaxim Ag             {-17036878, 13921892, 10945806, -6033431, 27105052, -16084379,
139772c33676SMaxim Ag              -28926210, 15006023, 3284568, -6276540},
139872c33676SMaxim Ag             {23599295, -8306047, -11193664, -7687416, 13236774, 10506355,
139972c33676SMaxim Ag              7464579, 9656445, 13059162, 10374397},
140072c33676SMaxim Ag             {7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664,
140172c33676SMaxim Ag              -3839045, -641708, -101325},
140272c33676SMaxim Ag         },
140372c33676SMaxim Ag         {
140472c33676SMaxim Ag             {10861363, 11473154, 27284546, 1981175, -30064349, 12577861,
140572c33676SMaxim Ag              32867885, 14515107, -15438304, 10819380},
140672c33676SMaxim Ag             {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668,
140772c33676SMaxim Ag              12483688, -12668491, 5581306},
140872c33676SMaxim Ag             {19563160, 16186464, -29386857, 4097519, 10237984, -4348115,
140972c33676SMaxim Ag              28542350, 13850243, -23678021, -15815942},
141072c33676SMaxim Ag         },
141172c33676SMaxim Ag         {
141272c33676SMaxim Ag             {-15371964, -12862754, 32573250, 4720197, -26436522, 5875511,
141372c33676SMaxim Ag              -19188627, -15224819, -9818940, -12085777},
141472c33676SMaxim Ag             {-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240,
141572c33676SMaxim Ag              -15689887, 1762328, 14866737},
141672c33676SMaxim Ag             {-18199695, -15951423, -10473290, 1707278, -17185920, 3916101,
141772c33676SMaxim Ag              -28236412, 3959421, 27914454, 4383652},
141872c33676SMaxim Ag         },
141972c33676SMaxim Ag         {
142072c33676SMaxim Ag             {5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852,
142172c33676SMaxim Ag              5230134, -23952439, -15175766},
142272c33676SMaxim Ag             {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722,
142372c33676SMaxim Ag              20654025, 16520125, 30598449, 7715701},
142472c33676SMaxim Ag             {28881845, 14381568, 9657904, 3680757, -20181635, 7843316,
142572c33676SMaxim Ag              -31400660, 1370708, 29794553, -1409300},
142672c33676SMaxim Ag         },
142772c33676SMaxim Ag         {
142872c33676SMaxim Ag             {14499471, -2729599, -33191113, -4254652, 28494862, 14271267,
142972c33676SMaxim Ag              30290735, 10876454, -33154098, 2381726},
143072c33676SMaxim Ag             {-7195431, -2655363, -14730155, 462251, -27724326, 3941372,
143172c33676SMaxim Ag              -6236617, 3696005, -32300832, 15351955},
143272c33676SMaxim Ag             {27431194, 8222322, 16448760, -3907995, -18707002, 11938355,
143372c33676SMaxim Ag              -32961401, -2970515, 29551813, 10109425},
143472c33676SMaxim Ag         },
143572c33676SMaxim Ag     },
143672c33676SMaxim Ag     {
143772c33676SMaxim Ag         {
143872c33676SMaxim Ag             {-13657040, -13155431, -31283750, 11777098, 21447386, 6519384,
143972c33676SMaxim Ag              -2378284, -1627556, 10092783, -4764171},
144072c33676SMaxim Ag             {27939166, 14210322, 4677035, 16277044, -22964462, -12398139,
144172c33676SMaxim Ag              -32508754, 12005538, -17810127, 12803510},
144272c33676SMaxim Ag             {17228999, -15661624, -1233527, 300140, -1224870, -11714777,
144372c33676SMaxim Ag              30364213, -9038194, 18016357, 4397660},
144472c33676SMaxim Ag         },
144572c33676SMaxim Ag         {
144672c33676SMaxim Ag             {-10958843, -7690207, 4776341, -14954238, 27850028, -15602212,
144772c33676SMaxim Ag              -26619106, 14544525, -17477504, 982639},
144872c33676SMaxim Ag             {29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899,
144972c33676SMaxim Ag              -4120128, -21047696, 9934963},
145072c33676SMaxim Ag             {5793303, 16271923, -24131614, -10116404, 29188560, 1206517,
145172c33676SMaxim Ag              -14747930, 4559895, -30123922, -10897950},
145272c33676SMaxim Ag         },
145372c33676SMaxim Ag         {
145472c33676SMaxim Ag             {-27643952, -11493006, 16282657, -11036493, 28414021, -15012264,
145572c33676SMaxim Ag              24191034, 4541697, -13338309, 5500568},
145672c33676SMaxim Ag             {12650548, -1497113, 9052871, 11355358, -17680037, -8400164,
145772c33676SMaxim Ag              -17430592, 12264343, 10874051, 13524335},
145872c33676SMaxim Ag             {25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038,
145972c33676SMaxim Ag              5080568, -22528059, 5376628},
146072c33676SMaxim Ag         },
146172c33676SMaxim Ag         {
146272c33676SMaxim Ag             {-26088264, -4011052, -17013699, -3537628, -6726793, 1920897,
146372c33676SMaxim Ag              -22321305, -9447443, 4535768, 1569007},
146472c33676SMaxim Ag             {-2255422, 14606630, -21692440, -8039818, 28430649, 8775819,
146572c33676SMaxim Ag              -30494562, 3044290, 31848280, 12543772},
146672c33676SMaxim Ag             {-22028579, 2943893, -31857513, 6777306, 13784462, -4292203,
146772c33676SMaxim Ag              -27377195, -2062731, 7718482, 14474653},
146872c33676SMaxim Ag         },
146972c33676SMaxim Ag         {
147072c33676SMaxim Ag             {2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965,
147172c33676SMaxim Ag              -7236665, 24316168, -5253567},
147272c33676SMaxim Ag             {13741529, 10911568, -33233417, -8603737, -20177830, -1033297,
147372c33676SMaxim Ag              33040651, -13424532, -20729456, 8321686},
147472c33676SMaxim Ag             {21060490, -2212744, 15712757, -4336099, 1639040, 10656336,
147572c33676SMaxim Ag              23845965, -11874838, -9984458, 608372},
147672c33676SMaxim Ag         },
147772c33676SMaxim Ag         {
147872c33676SMaxim Ag             {-13672732, -15087586, -10889693, -7557059, -6036909, 11305547,
147972c33676SMaxim Ag              1123968, -6780577, 27229399, 23887},
148072c33676SMaxim Ag             {-23244140, -294205, -11744728, 14712571, -29465699, -2029617,
148172c33676SMaxim Ag              12797024, -6440308, -1633405, 16678954},
148272c33676SMaxim Ag             {-29500620, 4770662, -16054387, 14001338, 7830047, 9564805,
148372c33676SMaxim Ag              -1508144, -4795045, -17169265, 4904953},
148472c33676SMaxim Ag         },
148572c33676SMaxim Ag         {
148672c33676SMaxim Ag             {24059557, 14617003, 19037157, -15039908, 19766093, -14906429,
148772c33676SMaxim Ag              5169211, 16191880, 2128236, -4326833},
148872c33676SMaxim Ag             {-16981152, 4124966, -8540610, -10653797, 30336522, -14105247,
148972c33676SMaxim Ag              -29806336, 916033, -6882542, -2986532},
149072c33676SMaxim Ag             {-22630907, 12419372, -7134229, -7473371, -16478904, 16739175,
149172c33676SMaxim Ag              285431, 2763829, 15736322, 4143876},
149272c33676SMaxim Ag         },
149372c33676SMaxim Ag         {
149472c33676SMaxim Ag             {2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801,
149572c33676SMaxim Ag              -14594663, 23527084, -16458268},
149672c33676SMaxim Ag             {33431127, -11130478, -17838966, -15626900, 8909499, 8376530,
149772c33676SMaxim Ag              -32625340, 4087881, -15188911, -14416214},
149872c33676SMaxim Ag             {1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055,
149972c33676SMaxim Ag              4357868, -4774191, -16323038},
150072c33676SMaxim Ag         },
150172c33676SMaxim Ag     },
150272c33676SMaxim Ag     {
150372c33676SMaxim Ag         {
150472c33676SMaxim Ag             {6721966, 13833823, -23523388, -1551314, 26354293, -11863321,
150572c33676SMaxim Ag              23365147, -3949732, 7390890, 2759800},
150672c33676SMaxim Ag             {4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353,
150772c33676SMaxim Ag              -4264057, 1244380, -12919645},
150872c33676SMaxim Ag             {-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413,
150972c33676SMaxim Ag              9208236, 15886429, 16489664},
151072c33676SMaxim Ag         },
151172c33676SMaxim Ag         {
151272c33676SMaxim Ag             {1996075, 10375649, 14346367, 13311202, -6874135, -16438411,
151372c33676SMaxim Ag              -13693198, 398369, -30606455, -712933},
151472c33676SMaxim Ag             {-25307465, 9795880, -2777414, 14878809, -33531835, 14780363,
151572c33676SMaxim Ag              13348553, 12076947, -30836462, 5113182},
151672c33676SMaxim Ag             {-17770784, 11797796, 31950843, 13929123, -25888302, 12288344,
151772c33676SMaxim Ag              -30341101, -7336386, 13847711, 5387222},
151872c33676SMaxim Ag         },
151972c33676SMaxim Ag         {
152072c33676SMaxim Ag             {-18582163, -3416217, 17824843, -2340966, 22744343, -10442611,
152172c33676SMaxim Ag              8763061, 3617786, -19600662, 10370991},
152272c33676SMaxim Ag             {20246567, -14369378, 22358229, -543712, 18507283, -10413996,
152372c33676SMaxim Ag              14554437, -8746092, 32232924, 16763880},
152472c33676SMaxim Ag             {9648505, 10094563, 26416693, 14745928, -30374318, -6472621,
152572c33676SMaxim Ag              11094161, 15689506, 3140038, -16510092},
152672c33676SMaxim Ag         },
152772c33676SMaxim Ag         {
152872c33676SMaxim Ag             {-16160072, 5472695, 31895588, 4744994, 8823515, 10365685,
152972c33676SMaxim Ag              -27224800, 9448613, -28774454, 366295},
153072c33676SMaxim Ag             {19153450, 11523972, -11096490, -6503142, -24647631, 5420647,
153172c33676SMaxim Ag              28344573, 8041113, 719605, 11671788},
153272c33676SMaxim Ag             {8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916,
153372c33676SMaxim Ag              -15266516, 27000813, -10195553},
153472c33676SMaxim Ag         },
153572c33676SMaxim Ag         {
153672c33676SMaxim Ag             {-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065,
153772c33676SMaxim Ag              5336097, 6750977, -14521026},
153872c33676SMaxim Ag             {11836410, -3979488, 26297894, 16080799, 23455045, 15735944,
153972c33676SMaxim Ag              1695823, -8819122, 8169720, 16220347},
154072c33676SMaxim Ag             {-18115838, 8653647, 17578566, -6092619, -8025777, -16012763,
154172c33676SMaxim Ag              -11144307, -2627664, -5990708, -14166033},
154272c33676SMaxim Ag         },
154372c33676SMaxim Ag         {
154472c33676SMaxim Ag             {-23308498, -10968312, 15213228, -10081214, -30853605, -11050004,
154572c33676SMaxim Ag              27884329, 2847284, 2655861, 1738395},
154672c33676SMaxim Ag             {-27537433, -14253021, -25336301, -8002780, -9370762, 8129821,
154772c33676SMaxim Ag              21651608, -3239336, -19087449, -11005278},
154872c33676SMaxim Ag             {1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092,
154972c33676SMaxim Ag              5821408, 10478196, 8544890},
155072c33676SMaxim Ag         },
155172c33676SMaxim Ag         {
155272c33676SMaxim Ag             {32173121, -16129311, 24896207, 3921497, 22579056, -3410854,
155372c33676SMaxim Ag              19270449, 12217473, 17789017, -3395995},
155472c33676SMaxim Ag             {-30552961, -2228401, -15578829, -10147201, 13243889, 517024,
155572c33676SMaxim Ag              15479401, -3853233, 30460520, 1052596},
155672c33676SMaxim Ag             {-11614875, 13323618, 32618793, 8175907, -15230173, 12596687,
155772c33676SMaxim Ag              27491595, -4612359, 3179268, -9478891},
155872c33676SMaxim Ag         },
155972c33676SMaxim Ag         {
156072c33676SMaxim Ag             {31947069, -14366651, -4640583, -15339921, -15125977, -6039709,
156172c33676SMaxim Ag              -14756777, -16411740, 19072640, -9511060},
156272c33676SMaxim Ag             {11685058, 11822410, 3158003, -13952594, 33402194, -4165066,
156372c33676SMaxim Ag              5977896, -5215017, 473099, 5040608},
156472c33676SMaxim Ag             {-20290863, 8198642, -27410132, 11602123, 1290375, -2799760,
156572c33676SMaxim Ag              28326862, 1721092, -19558642, -3131606},
156672c33676SMaxim Ag         },
156772c33676SMaxim Ag     },
156872c33676SMaxim Ag     {
156972c33676SMaxim Ag         {
157072c33676SMaxim Ag             {7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786,
157172c33676SMaxim Ag              8076149, -27868496, 11538389},
157272c33676SMaxim Ag             {-19935666, 3899861, 18283497, -6801568, -15728660, -11249211,
157372c33676SMaxim Ag              8754525, 7446702, -5676054, 5797016},
157472c33676SMaxim Ag             {-11295600, -3793569, -15782110, -7964573, 12708869, -8456199,
157572c33676SMaxim Ag              2014099, -9050574, -2369172, -5877341},
157672c33676SMaxim Ag         },
157772c33676SMaxim Ag         {
157872c33676SMaxim Ag             {-22472376, -11568741, -27682020, 1146375, 18956691, 16640559,
157972c33676SMaxim Ag              1192730, -3714199, 15123619, 10811505},
158072c33676SMaxim Ag             {14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363,
158172c33676SMaxim Ag              15776356, -28886779, -11974553},
158272c33676SMaxim Ag             {-28241164, -8072475, -4978962, -5315317, 29416931, 1847569,
158372c33676SMaxim Ag              -20654173, -16484855, 4714547, -9600655},
158472c33676SMaxim Ag         },
158572c33676SMaxim Ag         {
158672c33676SMaxim Ag             {15200332, 8368572, 19679101, 15970074, -31872674, 1959451,
158772c33676SMaxim Ag              24611599, -4543832, -11745876, 12340220},
158872c33676SMaxim Ag             {12876937, -10480056, 33134381, 6590940, -6307776, 14872440,
158972c33676SMaxim Ag              9613953, 8241152, 15370987, 9608631},
159072c33676SMaxim Ag             {-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868,
159172c33676SMaxim Ag              15866074, -28210621, -8814099},
159272c33676SMaxim Ag         },
159372c33676SMaxim Ag         {
159472c33676SMaxim Ag             {26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233,
159572c33676SMaxim Ag              858697, 20571223, 8420556},
159672c33676SMaxim Ag             {14620715, 13067227, -15447274, 8264467, 14106269, 15080814,
159772c33676SMaxim Ag              33531827, 12516406, -21574435, -12476749},
159872c33676SMaxim Ag             {236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519,
159972c33676SMaxim Ag              7256740, 8791136, 15069930},
160072c33676SMaxim Ag         },
160172c33676SMaxim Ag         {
160272c33676SMaxim Ag             {1276410, -9371918, 22949635, -16322807, -23493039, -5702186,
160372c33676SMaxim Ag              14711875, 4874229, -30663140, -2331391},
160472c33676SMaxim Ag             {5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175,
160572c33676SMaxim Ag              -7912378, -33069337, 9234253},
160672c33676SMaxim Ag             {20590503, -9018988, 31529744, -7352666, -2706834, 10650548,
160772c33676SMaxim Ag              31559055, -11609587, 18979186, 13396066},
160872c33676SMaxim Ag         },
160972c33676SMaxim Ag         {
161072c33676SMaxim Ag             {24474287, 4968103, 22267082, 4407354, 24063882, -8325180,
161172c33676SMaxim Ag              -18816887, 13594782, 33514650, 7021958},
161272c33676SMaxim Ag             {-11566906, -6565505, -21365085, 15928892, -26158305, 4315421,
161372c33676SMaxim Ag              -25948728, -3916677, -21480480, 12868082},
161472c33676SMaxim Ag             {-28635013, 13504661, 19988037, -2132761, 21078225, 6443208,
161572c33676SMaxim Ag              -21446107, 2244500, -12455797, -8089383},
161672c33676SMaxim Ag         },
161772c33676SMaxim Ag         {
161872c33676SMaxim Ag             {-30595528, 13793479, -5852820, 319136, -25723172, -6263899,
161972c33676SMaxim Ag              33086546, 8957937, -15233648, 5540521},
162072c33676SMaxim Ag             {-11630176, -11503902, -8119500, -7643073, 2620056, 1022908,
162172c33676SMaxim Ag              -23710744, -1568984, -16128528, -14962807},
162272c33676SMaxim Ag             {23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819,
162372c33676SMaxim Ag              892185, -11513277, -15205948},
162472c33676SMaxim Ag         },
162572c33676SMaxim Ag         {
162672c33676SMaxim Ag             {9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819,
162772c33676SMaxim Ag              4763127, -19179614, 5867134},
162872c33676SMaxim Ag             {-32765025, 1927590, 31726409, -4753295, 23962434, -16019500,
162972c33676SMaxim Ag              27846559, 5931263, -29749703, -16108455},
163072c33676SMaxim Ag             {27461885, -2977536, 22380810, 1815854, -23033753, -3031938,
163172c33676SMaxim Ag              7283490, -15148073, -19526700, 7734629},
163272c33676SMaxim Ag         },
163372c33676SMaxim Ag     },
163472c33676SMaxim Ag     {
163572c33676SMaxim Ag         {
163672c33676SMaxim Ag             {-8010264, -9590817, -11120403, 6196038, 29344158, -13430885,
163772c33676SMaxim Ag              7585295, -3176626, 18549497, 15302069},
163872c33676SMaxim Ag             {-32658337, -6171222, -7672793, -11051681, 6258878, 13504381,
163972c33676SMaxim Ag              10458790, -6418461, -8872242, 8424746},
164072c33676SMaxim Ag             {24687205, 8613276, -30667046, -3233545, 1863892, -1830544,
164172c33676SMaxim Ag              19206234, 7134917, -11284482, -828919},
164272c33676SMaxim Ag         },
164372c33676SMaxim Ag         {
164472c33676SMaxim Ag             {11334899, -9218022, 8025293, 12707519, 17523892, -10476071,
164572c33676SMaxim Ag              10243738, -14685461, -5066034, 16498837},
164672c33676SMaxim Ag             {8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925,
164772c33676SMaxim Ag              -14124238, 6536641, 10543906},
164872c33676SMaxim Ag             {-28946384, 15479763, -17466835, 568876, -1497683, 11223454,
164972c33676SMaxim Ag              -2669190, -16625574, -27235709, 8876771},
165072c33676SMaxim Ag         },
165172c33676SMaxim Ag         {
165272c33676SMaxim Ag             {-25742899, -12566864, -15649966, -846607, -33026686, -796288,
165372c33676SMaxim Ag              -33481822, 15824474, -604426, -9039817},
165472c33676SMaxim Ag             {10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697,
165572c33676SMaxim Ag              -4890037, 1657394, 3084098},
165672c33676SMaxim Ag             {10477963, -7470260, 12119566, -13250805, 29016247, -5365589,
165772c33676SMaxim Ag              31280319, 14396151, -30233575, 15272409},
165872c33676SMaxim Ag         },
165972c33676SMaxim Ag         {
166072c33676SMaxim Ag             {-12288309, 3169463, 28813183, 16658753, 25116432, -5630466,
166172c33676SMaxim Ag              -25173957, -12636138, -25014757, 1950504},
166272c33676SMaxim Ag             {-26180358, 9489187, 11053416, -14746161, -31053720, 5825630,
166372c33676SMaxim Ag              -8384306, -8767532, 15341279, 8373727},
166472c33676SMaxim Ag             {28685821, 7759505, -14378516, -12002860, -31971820, 4079242,
166572c33676SMaxim Ag              298136, -10232602, -2878207, 15190420},
166672c33676SMaxim Ag         },
166772c33676SMaxim Ag         {
166872c33676SMaxim Ag             {-32932876, 13806336, -14337485, -15794431, -24004620, 10940928,
166972c33676SMaxim Ag              8669718, 2742393, -26033313, -6875003},
167072c33676SMaxim Ag             {-1580388, -11729417, -25979658, -11445023, -17411874, -10912854,
167172c33676SMaxim Ag              9291594, -16247779, -12154742, 6048605},
167272c33676SMaxim Ag             {-30305315, 14843444, 1539301, 11864366, 20201677, 1900163,
167372c33676SMaxim Ag              13934231, 5128323, 11213262, 9168384},
167472c33676SMaxim Ag         },
167572c33676SMaxim Ag         {
167672c33676SMaxim Ag             {-26280513, 11007847, 19408960, -940758, -18592965, -4328580,
167772c33676SMaxim Ag              -5088060, -11105150, 20470157, -16398701},
167872c33676SMaxim Ag             {-23136053, 9282192, 14855179, -15390078, -7362815, -14408560,
167972c33676SMaxim Ag              -22783952, 14461608, 14042978, 5230683},
168072c33676SMaxim Ag             {29969567, -2741594, -16711867, -8552442, 9175486, -2468974,
168172c33676SMaxim Ag              21556951, 3506042, -5933891, -12449708},
168272c33676SMaxim Ag         },
168372c33676SMaxim Ag         {
168472c33676SMaxim Ag             {-3144746, 8744661, 19704003, 4581278, -20430686, 6830683,
168572c33676SMaxim Ag              -21284170, 8971513, -28539189, 15326563},
168672c33676SMaxim Ag             {-19464629, 10110288, -17262528, -3503892, -23500387, 1355669,
168772c33676SMaxim Ag              -15523050, 15300988, -20514118, 9168260},
168872c33676SMaxim Ag             {-5353335, 4488613, -23803248, 16314347, 7780487, -15638939,
168972c33676SMaxim Ag              -28948358, 9601605, 33087103, -9011387},
169072c33676SMaxim Ag         },
169172c33676SMaxim Ag         {
169272c33676SMaxim Ag             {-19443170, -15512900, -20797467, -12445323, -29824447, 10229461,
169372c33676SMaxim Ag              -27444329, -15000531, -5996870, 15664672},
169472c33676SMaxim Ag             {23294591, -16632613, -22650781, -8470978, 27844204, 11461195,
169572c33676SMaxim Ag              13099750, -2460356, 18151676, 13417686},
169672c33676SMaxim Ag             {-24722913, -4176517, -31150679, 5988919, -26858785, 6685065,
169772c33676SMaxim Ag              1661597, -12551441, 15271676, -15452665},
169872c33676SMaxim Ag         },
169972c33676SMaxim Ag     },
170072c33676SMaxim Ag     {
170172c33676SMaxim Ag         {
170272c33676SMaxim Ag             {11433042, -13228665, 8239631, -5279517, -1985436, -725718,
170372c33676SMaxim Ag              -18698764, 2167544, -6921301, -13440182},
170472c33676SMaxim Ag             {-31436171, 15575146, 30436815, 12192228, -22463353, 9395379,
170572c33676SMaxim Ag              -9917708, -8638997, 12215110, 12028277},
170672c33676SMaxim Ag             {14098400, 6555944, 23007258, 5757252, -15427832, -12950502,
170772c33676SMaxim Ag              30123440, 4617780, -16900089, -655628},
170872c33676SMaxim Ag         },
170972c33676SMaxim Ag         {
171072c33676SMaxim Ag             {-4026201, -15240835, 11893168, 13718664, -14809462, 1847385,
171172c33676SMaxim Ag              -15819999, 10154009, 23973261, -12684474},
171272c33676SMaxim Ag             {-26531820, -3695990, -1908898, 2534301, -31870557, -16550355,
171372c33676SMaxim Ag              18341390, -11419951, 32013174, -10103539},
171472c33676SMaxim Ag             {-25479301, 10876443, -11771086, -14625140, -12369567, 1838104,
171572c33676SMaxim Ag              21911214, 6354752, 4425632, -837822},
171672c33676SMaxim Ag         },
171772c33676SMaxim Ag         {
171872c33676SMaxim Ag             {-10433389, -14612966, 22229858, -3091047, -13191166, 776729,
171972c33676SMaxim Ag              -17415375, -12020462, 4725005, 14044970},
172072c33676SMaxim Ag             {19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390,
172172c33676SMaxim Ag              -1411784, -19522291, -16109756},
172272c33676SMaxim Ag             {-24864089, 12986008, -10898878, -5558584, -11312371, -148526,
172372c33676SMaxim Ag              19541418, 8180106, 9282262, 10282508},
172472c33676SMaxim Ag         },
172572c33676SMaxim Ag         {
172672c33676SMaxim Ag             {-26205082, 4428547, -8661196, -13194263, 4098402, -14165257,
172772c33676SMaxim Ag              15522535, 8372215, 5542595, -10702683},
172872c33676SMaxim Ag             {-10562541, 14895633, 26814552, -16673850, -17480754, -2489360,
172972c33676SMaxim Ag              -2781891, 6993761, -18093885, 10114655},
173072c33676SMaxim Ag             {-20107055, -929418, 31422704, 10427861, -7110749, 6150669,
173172c33676SMaxim Ag              -29091755, -11529146, 25953725, -106158},
173272c33676SMaxim Ag         },
173372c33676SMaxim Ag         {
173472c33676SMaxim Ag             {-4234397, -8039292, -9119125, 3046000, 2101609, -12607294,
173572c33676SMaxim Ag              19390020, 6094296, -3315279, 12831125},
173672c33676SMaxim Ag             {-15998678, 7578152, 5310217, 14408357, -33548620, -224739,
173772c33676SMaxim Ag              31575954, 6326196, 7381791, -2421839},
173872c33676SMaxim Ag             {-20902779, 3296811, 24736065, -16328389, 18374254, 7318640,
173972c33676SMaxim Ag              6295303, 8082724, -15362489, 12339664},
174072c33676SMaxim Ag         },
174172c33676SMaxim Ag         {
174272c33676SMaxim Ag             {27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414,
174372c33676SMaxim Ag              15768922, 25091167, 14856294},
174472c33676SMaxim Ag             {-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300,
174572c33676SMaxim Ag              -12695493, -22182473, -9012899},
174672c33676SMaxim Ag             {-11423429, -5421590, 11632845, 3405020, 30536730, -11674039,
174772c33676SMaxim Ag              -27260765, 13866390, 30146206, 9142070},
174872c33676SMaxim Ag         },
174972c33676SMaxim Ag         {
175072c33676SMaxim Ag             {3924129, -15307516, -13817122, -10054960, 12291820, -668366,
175172c33676SMaxim Ag              -27702774, 9326384, -8237858, 4171294},
175272c33676SMaxim Ag             {-15921940, 16037937, 6713787, 16606682, -21612135, 2790944,
175372c33676SMaxim Ag              26396185, 3731949, 345228, -5462949},
175472c33676SMaxim Ag             {-21327538, 13448259, 25284571, 1143661, 20614966, -8849387,
175572c33676SMaxim Ag              2031539, -12391231, -16253183, -13582083},
175672c33676SMaxim Ag         },
175772c33676SMaxim Ag         {
175872c33676SMaxim Ag             {31016211, -16722429, 26371392, -14451233, -5027349, 14854137,
175972c33676SMaxim Ag              17477601, 3842657, 28012650, -16405420},
176072c33676SMaxim Ag             {-5075835, 9368966, -8562079, -4600902, -15249953, 6970560,
176172c33676SMaxim Ag              -9189873, 16292057, -8867157, 3507940},
176272c33676SMaxim Ag             {29439664, 3537914, 23333589, 6997794, -17555561, -11018068,
176372c33676SMaxim Ag              -15209202, -15051267, -9164929, 6580396},
176472c33676SMaxim Ag         },
176572c33676SMaxim Ag     },
176672c33676SMaxim Ag     {
176772c33676SMaxim Ag         {
176872c33676SMaxim Ag             {-12185861, -7679788, 16438269, 10826160, -8696817, -6235611,
176972c33676SMaxim Ag              17860444, -9273846, -2095802, 9304567},
177072c33676SMaxim Ag             {20714564, -4336911, 29088195, 7406487, 11426967, -5095705,
177172c33676SMaxim Ag              14792667, -14608617, 5289421, -477127},
177272c33676SMaxim Ag             {-16665533, -10650790, -6160345, -13305760, 9192020, -1802462,
177372c33676SMaxim Ag              17271490, 12349094, 26939669, -3752294},
177472c33676SMaxim Ag         },
177572c33676SMaxim Ag         {
177672c33676SMaxim Ag             {-12889898, 9373458, 31595848, 16374215, 21471720, 13221525,
177772c33676SMaxim Ag              -27283495, -12348559, -3698806, 117887},
177872c33676SMaxim Ag             {22263325, -6560050, 3984570, -11174646, -15114008, -566785,
177972c33676SMaxim Ag              28311253, 5358056, -23319780, 541964},
178072c33676SMaxim Ag             {16259219, 3261970, 2309254, -15534474, -16885711, -4581916,
178172c33676SMaxim Ag              24134070, -16705829, -13337066, -13552195},
178272c33676SMaxim Ag         },
178372c33676SMaxim Ag         {
178472c33676SMaxim Ag             {9378160, -13140186, -22845982, -12745264, 28198281, -7244098,
178572c33676SMaxim Ag              -2399684, -717351, 690426, 14876244},
178672c33676SMaxim Ag             {24977353, -314384, -8223969, -13465086, 28432343, -1176353,
178772c33676SMaxim Ag              -13068804, -12297348, -22380984, 6618999},
178872c33676SMaxim Ag             {-1538174, 11685646, 12944378, 13682314, -24389511, -14413193,
178972c33676SMaxim Ag              8044829, -13817328, 32239829, -5652762},
179072c33676SMaxim Ag         },
179172c33676SMaxim Ag         {
179272c33676SMaxim Ag             {-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647,
179372c33676SMaxim Ag              -10350059, 32779359, 5095274},
179472c33676SMaxim Ag             {-33008130, -5214506, -32264887, -3685216, 9460461, -9327423,
179572c33676SMaxim Ag              -24601656, 14506724, 21639561, -2630236},
179672c33676SMaxim Ag             {-16400943, -13112215, 25239338, 15531969, 3987758, -4499318,
179772c33676SMaxim Ag              -1289502, -6863535, 17874574, 558605},
179872c33676SMaxim Ag         },
179972c33676SMaxim Ag         {
180072c33676SMaxim Ag             {-13600129, 10240081, 9171883, 16131053, -20869254, 9599700,
180172c33676SMaxim Ag              33499487, 5080151, 2085892, 5119761},
180272c33676SMaxim Ag             {-22205145, -2519528, -16381601, 414691, -25019550, 2170430,
180372c33676SMaxim Ag              30634760, -8363614, -31999993, -5759884},
180472c33676SMaxim Ag             {-6845704, 15791202, 8550074, -1312654, 29928809, -12092256,
180572c33676SMaxim Ag              27534430, -7192145, -22351378, 12961482},
180672c33676SMaxim Ag         },
180772c33676SMaxim Ag         {
180872c33676SMaxim Ag             {-24492060, -9570771, 10368194, 11582341, -23397293, -2245287,
180972c33676SMaxim Ag              16533930, 8206996, -30194652, -5159638},
181072c33676SMaxim Ag             {-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630,
181172c33676SMaxim Ag              7031275, 7589640, 8945490},
181272c33676SMaxim Ag             {-32152748, 8917967, 6661220, -11677616, -1192060, -15793393,
181372c33676SMaxim Ag              7251489, -11182180, 24099109, -14456170},
181472c33676SMaxim Ag         },
181572c33676SMaxim Ag         {
181672c33676SMaxim Ag             {5019558, -7907470, 4244127, -14714356, -26933272, 6453165,
181772c33676SMaxim Ag              -19118182, -13289025, -6231896, -10280736},
181872c33676SMaxim Ag             {10853594, 10721687, 26480089, 5861829, -22995819, 1972175,
181972c33676SMaxim Ag              -1866647, -10557898, -3363451, -6441124},
182072c33676SMaxim Ag             {-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661,
182172c33676SMaxim Ag              -2008168, -13866408, 7421392},
182272c33676SMaxim Ag         },
182372c33676SMaxim Ag         {
182472c33676SMaxim Ag             {8139927, -6546497, 32257646, -5890546, 30375719, 1886181,
182572c33676SMaxim Ag              -21175108, 15441252, 28826358, -4123029},
182672c33676SMaxim Ag             {6267086, 9695052, 7709135, -16603597, -32869068, -1886135,
182772c33676SMaxim Ag              14795160, -7840124, 13746021, -1742048},
182872c33676SMaxim Ag             {28584902, 7787108, -6732942, -15050729, 22846041, -7571236,
182972c33676SMaxim Ag              -3181936, -363524, 4771362, -8419958},
183072c33676SMaxim Ag         },
183172c33676SMaxim Ag     },
183272c33676SMaxim Ag     {
183372c33676SMaxim Ag         {
183472c33676SMaxim Ag             {24949256, 6376279, -27466481, -8174608, -18646154, -9930606,
183572c33676SMaxim Ag              33543569, -12141695, 3569627, 11342593},
183672c33676SMaxim Ag             {26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886,
183772c33676SMaxim Ag              4608608, 7325975, -14801071},
183872c33676SMaxim Ag             {-11618399, -14554430, -24321212, 7655128, -1369274, 5214312,
183972c33676SMaxim Ag              -27400540, 10258390, -17646694, -8186692},
184072c33676SMaxim Ag         },
184172c33676SMaxim Ag         {
184272c33676SMaxim Ag             {11431204, 15823007, 26570245, 14329124, 18029990, 4796082,
184372c33676SMaxim Ag              -31446179, 15580664, 9280358, -3973687},
184472c33676SMaxim Ag             {-160783, -10326257, -22855316, -4304997, -20861367, -13621002,
184572c33676SMaxim Ag              -32810901, -11181622, -15545091, 4387441},
184672c33676SMaxim Ag             {-20799378, 12194512, 3937617, -5805892, -27154820, 9340370,
184772c33676SMaxim Ag              -24513992, 8548137, 20617071, -7482001},
184872c33676SMaxim Ag         },
184972c33676SMaxim Ag         {
185072c33676SMaxim Ag             {-938825, -3930586, -8714311, 16124718, 24603125, -6225393,
185172c33676SMaxim Ag              -13775352, -11875822, 24345683, 10325460},
185272c33676SMaxim Ag             {-19855277, -1568885, -22202708, 8714034, 14007766, 6928528,
185372c33676SMaxim Ag              16318175, -1010689, 4766743, 3552007},
185472c33676SMaxim Ag             {-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514,
185572c33676SMaxim Ag              14481909, 10988822, -3994762},
185672c33676SMaxim Ag         },
185772c33676SMaxim Ag         {
185872c33676SMaxim Ag             {15564307, -14311570, 3101243, 5684148, 30446780, -8051356,
185972c33676SMaxim Ag              12677127, -6505343, -8295852, 13296005},
186072c33676SMaxim Ag             {-9442290, 6624296, -30298964, -11913677, -4670981, -2057379,
186172c33676SMaxim Ag              31521204, 9614054, -30000824, 12074674},
186272c33676SMaxim Ag             {4771191, -135239, 14290749, -13089852, 27992298, 14998318,
186372c33676SMaxim Ag              -1413936, -1556716, 29832613, -16391035},
186472c33676SMaxim Ag         },
186572c33676SMaxim Ag         {
186672c33676SMaxim Ag             {7064884, -7541174, -19161962, -5067537, -18891269, -2912736,
186772c33676SMaxim Ag              25825242, 5293297, -27122660, 13101590},
186872c33676SMaxim Ag             {-2298563, 2439670, -7466610, 1719965, -27267541, -16328445,
186972c33676SMaxim Ag              32512469, -5317593, -30356070, -4190957},
187072c33676SMaxim Ag             {-30006540, 10162316, -33180176, 3981723, -16482138, -13070044,
187172c33676SMaxim Ag              14413974, 9515896, 19568978, 9628812},
187272c33676SMaxim Ag         },
187372c33676SMaxim Ag         {
187472c33676SMaxim Ag             {33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894,
187572c33676SMaxim Ag              -6106839, -6291786, 3437740},
187672c33676SMaxim Ag             {-18978877, 3884493, 19469877, 12726490, 15913552, 13614290,
187772c33676SMaxim Ag              -22961733, 70104, 7463304, 4176122},
187872c33676SMaxim Ag             {-27124001, 10659917, 11482427, -16070381, 12771467, -6635117,
187972c33676SMaxim Ag              -32719404, -5322751, 24216882, 5944158},
188072c33676SMaxim Ag         },
188172c33676SMaxim Ag         {
188272c33676SMaxim Ag             {8894125, 7450974, -2664149, -9765752, -28080517, -12389115,
188372c33676SMaxim Ag              19345746, 14680796, 11632993, 5847885},
188472c33676SMaxim Ag             {26942781, -2315317, 9129564, -4906607, 26024105, 11769399,
188572c33676SMaxim Ag              -11518837, 6367194, -9727230, 4782140},
188672c33676SMaxim Ag             {19916461, -4828410, -22910704, -11414391, 25606324, -5972441,
188772c33676SMaxim Ag              33253853, 8220911, 6358847, -1873857},
188872c33676SMaxim Ag         },
188972c33676SMaxim Ag         {
189072c33676SMaxim Ag             {801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388,
189172c33676SMaxim Ag              -4480480, -13538503, 1387155},
189272c33676SMaxim Ag             {19646058, 5720633, -11416706, 12814209, 11607948, 12749789,
189372c33676SMaxim Ag              14147075, 15156355, -21866831, 11835260},
189472c33676SMaxim Ag             {19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523,
189572c33676SMaxim Ag              15467869, -26560550, 5052483},
189672c33676SMaxim Ag         },
189772c33676SMaxim Ag     },
189872c33676SMaxim Ag     {
189972c33676SMaxim Ag         {
190072c33676SMaxim Ag             {-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123,
190172c33676SMaxim Ag              -12618185, 12228557, -7003677},
190272c33676SMaxim Ag             {32944382, 14922211, -22844894, 5188528, 21913450, -8719943,
190372c33676SMaxim Ag              4001465, 13238564, -6114803, 8653815},
190472c33676SMaxim Ag             {22865569, -4652735, 27603668, -12545395, 14348958, 8234005,
190572c33676SMaxim Ag              24808405, 5719875, 28483275, 2841751},
190672c33676SMaxim Ag         },
190772c33676SMaxim Ag         {
190872c33676SMaxim Ag             {-16420968, -1113305, -327719, -12107856, 21886282, -15552774,
190972c33676SMaxim Ag              -1887966, -315658, 19932058, -12739203},
191072c33676SMaxim Ag             {-11656086, 10087521, -8864888, -5536143, -19278573, -3055912,
191172c33676SMaxim Ag              3999228, 13239134, -4777469, -13910208},
191272c33676SMaxim Ag             {1382174, -11694719, 17266790, 9194690, -13324356, 9720081,
191372c33676SMaxim Ag              20403944, 11284705, -14013818, 3093230},
191472c33676SMaxim Ag         },
191572c33676SMaxim Ag         {
191672c33676SMaxim Ag             {16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424,
191772c33676SMaxim Ag              16271225, -24049421, -6691850},
191872c33676SMaxim Ag             {-21911077, -5927941, -4611316, -5560156, -31744103, -10785293,
191972c33676SMaxim Ag              24123614, 15193618, -21652117, -16739389},
192072c33676SMaxim Ag             {-9935934, -4289447, -25279823, 4372842, 2087473, 10399484,
192172c33676SMaxim Ag              31870908, 14690798, 17361620, 11864968},
192272c33676SMaxim Ag         },
192372c33676SMaxim Ag         {
192472c33676SMaxim Ag             {-11307610, 6210372, 13206574, 5806320, -29017692, -13967200,
192572c33676SMaxim Ag              -12331205, -7486601, -25578460, -16240689},
192672c33676SMaxim Ag             {14668462, -12270235, 26039039, 15305210, 25515617, 4542480,
192772c33676SMaxim Ag              10453892, 6577524, 9145645, -6443880},
192872c33676SMaxim Ag             {5974874, 3053895, -9433049, -10385191, -31865124, 3225009,
192972c33676SMaxim Ag              -7972642, 3936128, -5652273, -3050304},
193072c33676SMaxim Ag         },
193172c33676SMaxim Ag         {
193272c33676SMaxim Ag             {30625386, -4729400, -25555961, -12792866, -20484575, 7695099,
193372c33676SMaxim Ag              17097188, -16303496, -27999779, 1803632},
193472c33676SMaxim Ag             {-3553091, 9865099, -5228566, 4272701, -5673832, -16689700,
193572c33676SMaxim Ag              14911344, 12196514, -21405489, 7047412},
193672c33676SMaxim Ag             {20093277, 9920966, -11138194, -5343857, 13161587, 12044805,
193772c33676SMaxim Ag              -32856851, 4124601, -32343828, -10257566},
193872c33676SMaxim Ag         },
193972c33676SMaxim Ag         {
194072c33676SMaxim Ag             {-20788824, 14084654, -13531713, 7842147, 19119038, -13822605,
194172c33676SMaxim Ag              4752377, -8714640, -21679658, 2288038},
194272c33676SMaxim Ag             {-26819236, -3283715, 29965059, 3039786, -14473765, 2540457,
194372c33676SMaxim Ag              29457502, 14625692, -24819617, 12570232},
194472c33676SMaxim Ag             {-1063558, -11551823, 16920318, 12494842, 1278292, -5869109,
194572c33676SMaxim Ag              -21159943, -3498680, -11974704, 4724943},
194672c33676SMaxim Ag         },
194772c33676SMaxim Ag         {
194872c33676SMaxim Ag             {17960970, -11775534, -4140968, -9702530, -8876562, -1410617,
194972c33676SMaxim Ag              -12907383, -8659932, -29576300, 1903856},
195072c33676SMaxim Ag             {23134274, -14279132, -10681997, -1611936, 20684485, 15770816,
195172c33676SMaxim Ag              -12989750, 3190296, 26955097, 14109738},
195272c33676SMaxim Ag             {15308788, 5320727, -30113809, -14318877, 22902008, 7767164,
195372c33676SMaxim Ag              29425325, -11277562, 31960942, 11934971},
195472c33676SMaxim Ag         },
195572c33676SMaxim Ag         {
195672c33676SMaxim Ag             {-27395711, 8435796, 4109644, 12222639, -24627868, 14818669,
195772c33676SMaxim Ag              20638173, 4875028, 10491392, 1379718},
195872c33676SMaxim Ag             {-13159415, 9197841, 3875503, -8936108, -1383712, -5879801,
195972c33676SMaxim Ag              33518459, 16176658, 21432314, 12180697},
196072c33676SMaxim Ag             {-11787308, 11500838, 13787581, -13832590, -22430679, 10140205,
196172c33676SMaxim Ag              1465425, 12689540, -10301319, -13872883},
196272c33676SMaxim Ag         },
196372c33676SMaxim Ag     },
196472c33676SMaxim Ag     {
196572c33676SMaxim Ag         {
196672c33676SMaxim Ag             {5414091, -15386041, -21007664, 9643570, 12834970, 1186149,
196772c33676SMaxim Ag              -2622916, -1342231, 26128231, 6032912},
196872c33676SMaxim Ag             {-26337395, -13766162, 32496025, -13653919, 17847801, -12669156,
196972c33676SMaxim Ag              3604025, 8316894, -25875034, -10437358},
197072c33676SMaxim Ag             {3296484, 6223048, 24680646, -12246460, -23052020, 5903205,
197172c33676SMaxim Ag              -8862297, -4639164, 12376617, 3188849},
197272c33676SMaxim Ag         },
197372c33676SMaxim Ag         {
197472c33676SMaxim Ag             {29190488, -14659046, 27549113, -1183516, 3520066, -10697301,
197572c33676SMaxim Ag              32049515, -7309113, -16109234, -9852307},
197672c33676SMaxim Ag             {-14744486, -9309156, 735818, -598978, -20407687, -5057904,
197772c33676SMaxim Ag              25246078, -15795669, 18640741, -960977},
197872c33676SMaxim Ag             {-6928835, -16430795, 10361374, 5642961, 4910474, 12345252,
197972c33676SMaxim Ag              -31638386, -494430, 10530747, 1053335},
198072c33676SMaxim Ag         },
198172c33676SMaxim Ag         {
198272c33676SMaxim Ag             {-29265967, -14186805, -13538216, -12117373, -19457059, -10655384,
198372c33676SMaxim Ag              -31462369, -2948985, 24018831, 15026644},
198472c33676SMaxim Ag             {-22592535, -3145277, -2289276, 5953843, -13440189, 9425631,
198572c33676SMaxim Ag              25310643, 13003497, -2314791, -15145616},
198672c33676SMaxim Ag             {-27419985, -603321, -8043984, -1669117, -26092265, 13987819,
198772c33676SMaxim Ag              -27297622, 187899, -23166419, -2531735},
198872c33676SMaxim Ag         },
198972c33676SMaxim Ag         {
199072c33676SMaxim Ag             {-21744398, -13810475, 1844840, 5021428, -10434399, -15911473,
199172c33676SMaxim Ag              9716667, 16266922, -5070217, 726099},
199272c33676SMaxim Ag             {29370922, -6053998, 7334071, -15342259, 9385287, 2247707,
199372c33676SMaxim Ag              -13661962, -4839461, 30007388, -15823341},
199472c33676SMaxim Ag             {-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109,
199572c33676SMaxim Ag              730663, 9835848, 4555336},
199672c33676SMaxim Ag         },
199772c33676SMaxim Ag         {
199872c33676SMaxim Ag             {-23376435, 1410446, -22253753, -12899614, 30867635, 15826977,
199972c33676SMaxim Ag              17693930, 544696, -11985298, 12422646},
200072c33676SMaxim Ag             {31117226, -12215734, -13502838, 6561947, -9876867, -12757670,
200172c33676SMaxim Ag              -5118685, -4096706, 29120153, 13924425},
200272c33676SMaxim Ag             {-17400879, -14233209, 19675799, -2734756, -11006962, -5858820,
200372c33676SMaxim Ag              -9383939, -11317700, 7240931, -237388},
200472c33676SMaxim Ag         },
200572c33676SMaxim Ag         {
200672c33676SMaxim Ag             {-31361739, -11346780, -15007447, -5856218, -22453340, -12152771,
200772c33676SMaxim Ag              1222336, 4389483, 3293637, -15551743},
200872c33676SMaxim Ag             {-16684801, -14444245, 11038544, 11054958, -13801175, -3338533,
200972c33676SMaxim Ag              -24319580, 7733547, 12796905, -6335822},
201072c33676SMaxim Ag             {-8759414, -10817836, -25418864, 10783769, -30615557, -9746811,
201172c33676SMaxim Ag              -28253339, 3647836, 3222231, -11160462},
201272c33676SMaxim Ag         },
201372c33676SMaxim Ag         {
201472c33676SMaxim Ag             {18606113, 1693100, -25448386, -15170272, 4112353, 10045021,
201572c33676SMaxim Ag              23603893, -2048234, -7550776, 2484985},
201672c33676SMaxim Ag             {9255317, -3131197, -12156162, -1004256, 13098013, -9214866,
201772c33676SMaxim Ag              16377220, -2102812, -19802075, -3034702},
201872c33676SMaxim Ag             {-22729289, 7496160, -5742199, 11329249, 19991973, -3347502,
201972c33676SMaxim Ag              -31718148, 9936966, -30097688, -10618797},
202072c33676SMaxim Ag         },
202172c33676SMaxim Ag         {
202272c33676SMaxim Ag             {21878590, -5001297, 4338336, 13643897, -3036865, 13160960,
202372c33676SMaxim Ag              19708896, 5415497, -7360503, -4109293},
202472c33676SMaxim Ag             {27736861, 10103576, 12500508, 8502413, -3413016, -9633558,
202572c33676SMaxim Ag              10436918, -1550276, -23659143, -8132100},
202672c33676SMaxim Ag             {19492550, -12104365, -29681976, -852630, -3208171, 12403437,
202772c33676SMaxim Ag              30066266, 8367329, 13243957, 8709688},
202872c33676SMaxim Ag         },
202972c33676SMaxim Ag     },
203072c33676SMaxim Ag     {
203172c33676SMaxim Ag         {
203272c33676SMaxim Ag             {12015105, 2801261, 28198131, 10151021, 24818120, -4743133,
203372c33676SMaxim Ag              -11194191, -5645734, 5150968, 7274186},
203472c33676SMaxim Ag             {2831366, -12492146, 1478975, 6122054, 23825128, -12733586,
203572c33676SMaxim Ag              31097299, 6083058, 31021603, -9793610},
203672c33676SMaxim Ag             {-2529932, -2229646, 445613, 10720828, -13849527, -11505937,
203772c33676SMaxim Ag              -23507731, 16354465, 15067285, -14147707},
203872c33676SMaxim Ag         },
203972c33676SMaxim Ag         {
204072c33676SMaxim Ag             {7840942, 14037873, -33364863, 15934016, -728213, -3642706,
204172c33676SMaxim Ag              21403988, 1057586, -19379462, -12403220},
204272c33676SMaxim Ag             {915865, -16469274, 15608285, -8789130, -24357026, 6060030,
204372c33676SMaxim Ag              -17371319, 8410997, -7220461, 16527025},
204472c33676SMaxim Ag             {32922597, -556987, 20336074, -16184568, 10903705, -5384487,
204572c33676SMaxim Ag              16957574, 52992, 23834301, 6588044},
204672c33676SMaxim Ag         },
204772c33676SMaxim Ag         {
204872c33676SMaxim Ag             {32752030, 11232950, 3381995, -8714866, 22652988, -10744103,
204972c33676SMaxim Ag              17159699, 16689107, -20314580, -1305992},
205072c33676SMaxim Ag             {-4689649, 9166776, -25710296, -10847306, 11576752, 12733943,
205172c33676SMaxim Ag              7924251, -2752281, 1976123, -7249027},
205272c33676SMaxim Ag             {21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041,
205372c33676SMaxim Ag              -3371252, 12331345, -8237197},
205472c33676SMaxim Ag         },
205572c33676SMaxim Ag         {
205672c33676SMaxim Ag             {8651614, -4477032, -16085636, -4996994, 13002507, 2950805,
205772c33676SMaxim Ag              29054427, -5106970, 10008136, -4667901},
205872c33676SMaxim Ag             {31486080, 15114593, -14261250, 12951354, 14369431, -7387845,
205972c33676SMaxim Ag              16347321, -13662089, 8684155, -10532952},
206072c33676SMaxim Ag             {19443825, 11385320, 24468943, -9659068, -23919258, 2187569,
206172c33676SMaxim Ag              -26263207, -6086921, 31316348, 14219878},
206272c33676SMaxim Ag         },
206372c33676SMaxim Ag         {
206472c33676SMaxim Ag             {-28594490, 1193785, 32245219, 11392485, 31092169, 15722801,
206572c33676SMaxim Ag              27146014, 6992409, 29126555, 9207390},
206672c33676SMaxim Ag             {32382935, 1110093, 18477781, 11028262, -27411763, -7548111,
206772c33676SMaxim Ag              -4980517, 10843782, -7957600, -14435730},
206872c33676SMaxim Ag             {2814918, 7836403, 27519878, -7868156, -20894015, -11553689,
206972c33676SMaxim Ag              -21494559, 8550130, 28346258, 1994730},
207072c33676SMaxim Ag         },
207172c33676SMaxim Ag         {
207272c33676SMaxim Ag             {-19578299, 8085545, -14000519, -3948622, 2785838, -16231307,
207372c33676SMaxim Ag              -19516951, 7174894, 22628102, 8115180},
207472c33676SMaxim Ag             {-30405132, 955511, -11133838, -15078069, -32447087, -13278079,
207572c33676SMaxim Ag              -25651578, 3317160, -9943017, 930272},
207672c33676SMaxim Ag             {-15303681, -6833769, 28856490, 1357446, 23421993, 1057177,
207772c33676SMaxim Ag              24091212, -1388970, -22765376, -10650715},
207872c33676SMaxim Ag         },
207972c33676SMaxim Ag         {
208072c33676SMaxim Ag             {-22751231, -5303997, -12907607, -12768866, -15811511, -7797053,
208172c33676SMaxim Ag              -14839018, -16554220, -1867018, 8398970},
208272c33676SMaxim Ag             {-31969310, 2106403, -4736360, 1362501, 12813763, 16200670,
208372c33676SMaxim Ag              22981545, -6291273, 18009408, -15772772},
208472c33676SMaxim Ag             {-17220923, -9545221, -27784654, 14166835, 29815394, 7444469,
208572c33676SMaxim Ag              29551787, -3727419, 19288549, 1325865},
208672c33676SMaxim Ag         },
208772c33676SMaxim Ag         {
208872c33676SMaxim Ag             {15100157, -15835752, -23923978, -1005098, -26450192, 15509408,
208972c33676SMaxim Ag              12376730, -3479146, 33166107, -8042750},
209072c33676SMaxim Ag             {20909231, 13023121, -9209752, 16251778, -5778415, -8094914,
209172c33676SMaxim Ag              12412151, 10018715, 2213263, -13878373},
209272c33676SMaxim Ag             {32529814, -11074689, 30361439, -16689753, -9135940, 1513226,
209372c33676SMaxim Ag              22922121, 6382134, -5766928, 8371348},
209472c33676SMaxim Ag         },
209572c33676SMaxim Ag     },
209672c33676SMaxim Ag     {
209772c33676SMaxim Ag         {
209872c33676SMaxim Ag             {9923462, 11271500, 12616794, 3544722, -29998368, -1721626,
209972c33676SMaxim Ag              12891687, -8193132, -26442943, 10486144},
210072c33676SMaxim Ag             {-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726,
210172c33676SMaxim Ag              2610596, -23921530, -11455195},
210272c33676SMaxim Ag             {5408411, -1136691, -4969122, 10561668, 24145918, 14240566,
210372c33676SMaxim Ag              31319731, -4235541, 19985175, -3436086},
210472c33676SMaxim Ag         },
210572c33676SMaxim Ag         {
210672c33676SMaxim Ag             {-13994457, 16616821, 14549246, 3341099, 32155958, 13648976,
210772c33676SMaxim Ag              -17577068, 8849297, 65030, 8370684},
210872c33676SMaxim Ag             {-8320926, -12049626, 31204563, 5839400, -20627288, -1057277,
210972c33676SMaxim Ag              -19442942, 6922164, 12743482, -9800518},
211072c33676SMaxim Ag             {-2361371, 12678785, 28815050, 4759974, -23893047, 4884717,
211172c33676SMaxim Ag              23783145, 11038569, 18800704, 255233},
211272c33676SMaxim Ag         },
211372c33676SMaxim Ag         {
211472c33676SMaxim Ag             {-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847,
211572c33676SMaxim Ag              9066957, 19258688, -14753793},
211672c33676SMaxim Ag             {-2936654, -10827535, -10432089, 14516793, -3640786, 4372541,
211772c33676SMaxim Ag              -31934921, 2209390, -1524053, 2055794},
211872c33676SMaxim Ag             {580882, 16705327, 5468415, -2683018, -30926419, -14696000,
211972c33676SMaxim Ag              -7203346, -8994389, -30021019, 7394435},
212072c33676SMaxim Ag         },
212172c33676SMaxim Ag         {
212272c33676SMaxim Ag             {23838809, 1822728, -15738443, 15242727, 8318092, -3733104,
212372c33676SMaxim Ag              -21672180, -3492205, -4821741, 14799921},
212472c33676SMaxim Ag             {13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804,
212572c33676SMaxim Ag              13496856, -9056018, 7402518},
212672c33676SMaxim Ag             {2286874, -4435931, -20042458, -2008336, -13696227, 5038122,
212772c33676SMaxim Ag              11006906, -15760352, 8205061, 1607563},
212872c33676SMaxim Ag         },
212972c33676SMaxim Ag         {
213072c33676SMaxim Ag             {14414086, -8002132, 3331830, -3208217, 22249151, -5594188,
213172c33676SMaxim Ag              18364661, -2906958, 30019587, -9029278},
213272c33676SMaxim Ag             {-27688051, 1585953, -10775053, 931069, -29120221, -11002319,
213372c33676SMaxim Ag              -14410829, 12029093, 9944378, 8024},
213472c33676SMaxim Ag             {4368715, -3709630, 29874200, -15022983, -20230386, -11410704,
213572c33676SMaxim Ag              -16114594, -999085, -8142388, 5640030},
213672c33676SMaxim Ag         },
213772c33676SMaxim Ag         {
213872c33676SMaxim Ag             {10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887,
213972c33676SMaxim Ag              -16694564, 15219798, -14327783},
214072c33676SMaxim Ag             {27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605,
214172c33676SMaxim Ag              -1173195, -18342183, 9742717},
214272c33676SMaxim Ag             {6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614,
214372c33676SMaxim Ag              7406442, 12420155, 1994844},
214472c33676SMaxim Ag         },
214572c33676SMaxim Ag         {
214672c33676SMaxim Ag             {14012521, -5024720, -18384453, -9578469, -26485342, -3936439,
214772c33676SMaxim Ag              -13033478, -10909803, 24319929, -6446333},
214872c33676SMaxim Ag             {16412690, -4507367, 10772641, 15929391, -17068788, -4658621,
214972c33676SMaxim Ag              10555945, -10484049, -30102368, -4739048},
215072c33676SMaxim Ag             {22397382, -7767684, -9293161, -12792868, 17166287, -9755136,
215172c33676SMaxim Ag              -27333065, 6199366, 21880021, -12250760},
215272c33676SMaxim Ag         },
215372c33676SMaxim Ag         {
215472c33676SMaxim Ag             {-4283307, 5368523, -31117018, 8163389, -30323063, 3209128,
215572c33676SMaxim Ag              16557151, 8890729, 8840445, 4957760},
215672c33676SMaxim Ag             {-15447727, 709327, -6919446, -10870178, -29777922, 6522332,
215772c33676SMaxim Ag              -21720181, 12130072, -14796503, 5005757},
215872c33676SMaxim Ag             {-2114751, -14308128, 23019042, 15765735, -25269683, 6002752,
215972c33676SMaxim Ag              10183197, -13239326, -16395286, -2176112},
216072c33676SMaxim Ag         },
216172c33676SMaxim Ag     },
216272c33676SMaxim Ag     {
216372c33676SMaxim Ag         {
216472c33676SMaxim Ag             {-19025756, 1632005, 13466291, -7995100, -23640451, 16573537,
216572c33676SMaxim Ag              -32013908, -3057104, 22208662, 2000468},
216672c33676SMaxim Ag             {3065073, -1412761, -25598674, -361432, -17683065, -5703415,
216772c33676SMaxim Ag              -8164212, 11248527, -3691214, -7414184},
216872c33676SMaxim Ag             {10379208, -6045554, 8877319, 1473647, -29291284, -12507580,
216972c33676SMaxim Ag              16690915, 2553332, -3132688, 16400289},
217072c33676SMaxim Ag         },
217172c33676SMaxim Ag         {
217272c33676SMaxim Ag             {15716668, 1254266, -18472690, 7446274, -8448918, 6344164,
217372c33676SMaxim Ag              -22097271, -7285580, 26894937, 9132066},
217472c33676SMaxim Ag             {24158887, 12938817, 11085297, -8177598, -28063478, -4457083,
217572c33676SMaxim Ag              -30576463, 64452, -6817084, -2692882},
217672c33676SMaxim Ag             {13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710,
217772c33676SMaxim Ag              -3418511, -4688006, 2364226},
217872c33676SMaxim Ag         },
217972c33676SMaxim Ag         {
218072c33676SMaxim Ag             {16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024,
218172c33676SMaxim Ag              -11697457, 15445875, -7798101},
218272c33676SMaxim Ag             {29004207, -7867081, 28661402, -640412, -12794003, -7943086,
218372c33676SMaxim Ag              31863255, -4135540, -278050, -15759279},
218472c33676SMaxim Ag             {-6122061, -14866665, -28614905, 14569919, -10857999, -3591829,
218572c33676SMaxim Ag              10343412, -6976290, -29828287, -10815811},
218672c33676SMaxim Ag         },
218772c33676SMaxim Ag         {
218872c33676SMaxim Ag             {27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636,
218972c33676SMaxim Ag              15372179, 17293797, 960709},
219072c33676SMaxim Ag             {20263915, 11434237, -5765435, 11236810, 13505955, -10857102,
219172c33676SMaxim Ag              -16111345, 6493122, -19384511, 7639714},
219272c33676SMaxim Ag             {-2830798, -14839232, 25403038, -8215196, -8317012, -16173699,
219372c33676SMaxim Ag              18006287, -16043750, 29994677, -15808121},
219472c33676SMaxim Ag         },
219572c33676SMaxim Ag         {
219672c33676SMaxim Ag             {9769828, 5202651, -24157398, -13631392, -28051003, -11561624,
219772c33676SMaxim Ag              -24613141, -13860782, -31184575, 709464},
219872c33676SMaxim Ag             {12286395, 13076066, -21775189, -1176622, -25003198, 4057652,
219972c33676SMaxim Ag              -32018128, -8890874, 16102007, 13205847},
220072c33676SMaxim Ag             {13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170,
220172c33676SMaxim Ag              8525972, 10151379, 10394400},
220272c33676SMaxim Ag         },
220372c33676SMaxim Ag         {
220472c33676SMaxim Ag             {4024660, -16137551, 22436262, 12276534, -9099015, -2686099,
220572c33676SMaxim Ag              19698229, 11743039, -33302334, 8934414},
220672c33676SMaxim Ag             {-15879800, -4525240, -8580747, -2934061, 14634845, -698278,
220772c33676SMaxim Ag              -9449077, 3137094, -11536886, 11721158},
220872c33676SMaxim Ag             {17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229,
220972c33676SMaxim Ag              8835153, -9205489, -1280045},
221072c33676SMaxim Ag         },
221172c33676SMaxim Ag         {
221272c33676SMaxim Ag             {-461409, -7830014, 20614118, 16688288, -7514766, -4807119,
221372c33676SMaxim Ag              22300304, 505429, 6108462, -6183415},
221472c33676SMaxim Ag             {-5070281, 12367917, -30663534, 3234473, 32617080, -8422642,
221572c33676SMaxim Ag              29880583, -13483331, -26898490, -7867459},
221672c33676SMaxim Ag             {-31975283, 5726539, 26934134, 10237677, -3173717, -605053,
221772c33676SMaxim Ag              24199304, 3795095, 7592688, -14992079},
221872c33676SMaxim Ag         },
221972c33676SMaxim Ag         {
222072c33676SMaxim Ag             {21594432, -14964228, 17466408, -4077222, 32537084, 2739898,
222172c33676SMaxim Ag              6407723, 12018833, -28256052, 4298412},
222272c33676SMaxim Ag             {-20650503, -11961496, -27236275, 570498, 3767144, -1717540,
222372c33676SMaxim Ag              13891942, -1569194, 13717174, 10805743},
222472c33676SMaxim Ag             {-14676630, -15644296, 15287174, 11927123, 24177847, -8175568,
222572c33676SMaxim Ag              -796431, 14860609, -26938930, -5863836},
222672c33676SMaxim Ag         },
222772c33676SMaxim Ag     },
222872c33676SMaxim Ag     {
222972c33676SMaxim Ag         {
223072c33676SMaxim Ag             {12962541, 5311799, -10060768, 11658280, 18855286, -7954201,
223172c33676SMaxim Ag              13286263, -12808704, -4381056, 9882022},
223272c33676SMaxim Ag             {18512079, 11319350, -20123124, 15090309, 18818594, 5271736,
223372c33676SMaxim Ag              -22727904, 3666879, -23967430, -3299429},
223472c33676SMaxim Ag             {-6789020, -3146043, 16192429, 13241070, 15898607, -14206114,
223572c33676SMaxim Ag              -10084880, -6661110, -2403099, 5276065},
223672c33676SMaxim Ag         },
223772c33676SMaxim Ag         {
223872c33676SMaxim Ag             {30169808, -5317648, 26306206, -11750859, 27814964, 7069267,
223972c33676SMaxim Ag              7152851, 3684982, 1449224, 13082861},
224072c33676SMaxim Ag             {10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382,
224172c33676SMaxim Ag              15056736, -21016438, -8202000},
224272c33676SMaxim Ag             {-33150110, 3261608, 22745853, 7948688, 19370557, -15177665,
224372c33676SMaxim Ag              -26171976, 6482814, -10300080, -11060101},
224472c33676SMaxim Ag         },
224572c33676SMaxim Ag         {
224672c33676SMaxim Ag             {32869458, -5408545, 25609743, 15678670, -10687769, -15471071,
224772c33676SMaxim Ag              26112421, 2521008, -22664288, 6904815},
224872c33676SMaxim Ag             {29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737,
224972c33676SMaxim Ag              3841096, -29003639, -6657642},
225072c33676SMaxim Ag             {10340844, -6630377, -18656632, -2278430, 12621151, -13339055,
225172c33676SMaxim Ag              30878497, -11824370, -25584551, 5181966},
225272c33676SMaxim Ag         },
225372c33676SMaxim Ag         {
225472c33676SMaxim Ag             {25940115, -12658025, 17324188, -10307374, -8671468, 15029094,
225572c33676SMaxim Ag              24396252, -16450922, -2322852, -12388574},
225672c33676SMaxim Ag             {-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390,
225772c33676SMaxim Ag              12641087, 20603771, -6561742},
225872c33676SMaxim Ag             {-18882287, -11673380, 24849422, 11501709, 13161720, -4768874,
225972c33676SMaxim Ag              1925523, 11914390, 4662781, 7820689},
226072c33676SMaxim Ag         },
226172c33676SMaxim Ag         {
226272c33676SMaxim Ag             {12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456,
226372c33676SMaxim Ag              12172924, 16136752, 15264020},
226472c33676SMaxim Ag             {-10349955, -14680563, -8211979, 2330220, -17662549, -14545780,
226572c33676SMaxim Ag              10658213, 6671822, 19012087, 3772772},
226672c33676SMaxim Ag             {3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732,
226772c33676SMaxim Ag              -15762884, 20527771, 12988982},
226872c33676SMaxim Ag         },
226972c33676SMaxim Ag         {
227072c33676SMaxim Ag             {-14822485, -5797269, -3707987, 12689773, -898983, -10914866,
227172c33676SMaxim Ag              -24183046, -10564943, 3299665, -12424953},
227272c33676SMaxim Ag             {-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197,
227372c33676SMaxim Ag              6461331, -25583147, 8991218},
227472c33676SMaxim Ag             {-17226263, 1816362, -1673288, -6086439, 31783888, -8175991,
227572c33676SMaxim Ag              -32948145, 7417950, -30242287, 1507265},
227672c33676SMaxim Ag         },
227772c33676SMaxim Ag         {
227872c33676SMaxim Ag             {29692663, 6829891, -10498800, 4334896, 20945975, -11906496,
227972c33676SMaxim Ag              -28887608, 8209391, 14606362, -10647073},
228072c33676SMaxim Ag             {-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695,
228172c33676SMaxim Ag              9761487, 4170404, -2085325},
228272c33676SMaxim Ag             {-11587470, 14855945, -4127778, -1531857, -26649089, 15084046,
228372c33676SMaxim Ag              22186522, 16002000, -14276837, -8400798},
228472c33676SMaxim Ag         },
228572c33676SMaxim Ag         {
228672c33676SMaxim Ag             {-4811456, 13761029, -31703877, -2483919, -3312471, 7869047,
228772c33676SMaxim Ag              -7113572, -9620092, 13240845, 10965870},
228872c33676SMaxim Ag             {-7742563, -8256762, -14768334, -13656260, -23232383, 12387166,
228972c33676SMaxim Ag              4498947, 14147411, 29514390, 4302863},
229072c33676SMaxim Ag             {-13413405, -12407859, 20757302, -13801832, 14785143, 8976368,
229172c33676SMaxim Ag              -5061276, -2144373, 17846988, -13971927},
229272c33676SMaxim Ag         },
229372c33676SMaxim Ag     },
229472c33676SMaxim Ag     {
229572c33676SMaxim Ag         {
229672c33676SMaxim Ag             {-2244452, -754728, -4597030, -1066309, -6247172, 1455299,
229772c33676SMaxim Ag              -21647728, -9214789, -5222701, 12650267},
229872c33676SMaxim Ag             {-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813,
229972c33676SMaxim Ag              13770293, -19134326, 10958663},
230072c33676SMaxim Ag             {22470984, 12369526, 23446014, -5441109, -21520802, -9698723,
230172c33676SMaxim Ag              -11772496, -11574455, -25083830, 4271862},
230272c33676SMaxim Ag         },
230372c33676SMaxim Ag         {
230472c33676SMaxim Ag             {-25169565, -10053642, -19909332, 15361595, -5984358, 2159192,
230572c33676SMaxim Ag              75375, -4278529, -32526221, 8469673},
230672c33676SMaxim Ag             {15854970, 4148314, -8893890, 7259002, 11666551, 13824734,
230772c33676SMaxim Ag              -30531198, 2697372, 24154791, -9460943},
230872c33676SMaxim Ag             {15446137, -15806644, 29759747, 14019369, 30811221, -9610191,
230972c33676SMaxim Ag              -31582008, 12840104, 24913809, 9815020},
231072c33676SMaxim Ag         },
231172c33676SMaxim Ag         {
231272c33676SMaxim Ag             {-4709286, -5614269, -31841498, -12288893, -14443537, 10799414,
231372c33676SMaxim Ag              -9103676, 13438769, 18735128, 9466238},
231472c33676SMaxim Ag             {11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821,
231572c33676SMaxim Ag              -10896103, -22728655, 16199064},
231672c33676SMaxim Ag             {14576810, 379472, -26786533, -8317236, -29426508, -10812974,
231772c33676SMaxim Ag              -102766, 1876699, 30801119, 2164795},
231872c33676SMaxim Ag         },
231972c33676SMaxim Ag         {
232072c33676SMaxim Ag             {15995086, 3199873, 13672555, 13712240, -19378835, -4647646,
232172c33676SMaxim Ag              -13081610, -15496269, -13492807, 1268052},
232272c33676SMaxim Ag             {-10290614, -3659039, -3286592, 10948818, 23037027, 3794475,
232372c33676SMaxim Ag              -3470338, -12600221, -17055369, 3565904},
232472c33676SMaxim Ag             {29210088, -9419337, -5919792, -4952785, 10834811, -13327726,
232572c33676SMaxim Ag              -16512102, -10820713, -27162222, -14030531},
232672c33676SMaxim Ag         },
232772c33676SMaxim Ag         {
232872c33676SMaxim Ag             {-13161890, 15508588, 16663704, -8156150, -28349942, 9019123,
232972c33676SMaxim Ag              -29183421, -3769423, 2244111, -14001979},
233072c33676SMaxim Ag             {-5152875, -3800936, -9306475, -6071583, 16243069, 14684434,
233172c33676SMaxim Ag              -25673088, -16180800, 13491506, 4641841},
233272c33676SMaxim Ag             {10813417, 643330, -19188515, -728916, 30292062, -16600078,
233372c33676SMaxim Ag              27548447, -7721242, 14476989, -12767431},
233472c33676SMaxim Ag         },
233572c33676SMaxim Ag         {
233672c33676SMaxim Ag             {10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937,
233772c33676SMaxim Ag              -1644259, -27912810, 12651324},
233872c33676SMaxim Ag             {-31185513, -813383, 22271204, 11835308, 10201545, 15351028,
233972c33676SMaxim Ag              17099662, 3988035, 21721536, -3148940},
234072c33676SMaxim Ag             {10202177, -6545839, -31373232, -9574638, -32150642, -8119683,
234172c33676SMaxim Ag              -12906320, 3852694, 13216206, 14842320},
234272c33676SMaxim Ag         },
234372c33676SMaxim Ag         {
234472c33676SMaxim Ag             {-15815640, -10601066, -6538952, -7258995, -6984659, -6581778,
234572c33676SMaxim Ag              -31500847, 13765824, -27434397, 9900184},
234672c33676SMaxim Ag             {14465505, -13833331, -32133984, -14738873, -27443187, 12990492,
234772c33676SMaxim Ag              33046193, 15796406, -7051866, -8040114},
234872c33676SMaxim Ag             {30924417, -8279620, 6359016, -12816335, 16508377, 9071735,
234972c33676SMaxim Ag              -25488601, 15413635, 9524356, -7018878},
235072c33676SMaxim Ag         },
235172c33676SMaxim Ag         {
235272c33676SMaxim Ag             {12274201, -13175547, 32627641, -1785326, 6736625, 13267305,
235372c33676SMaxim Ag              5237659, -5109483, 15663516, 4035784},
235472c33676SMaxim Ag             {-2951309, 8903985, 17349946, 601635, -16432815, -4612556,
235572c33676SMaxim Ag              -13732739, -15889334, -22258478, 4659091},
235672c33676SMaxim Ag             {-16916263, -4952973, -30393711, -15158821, 20774812, 15897498,
235772c33676SMaxim Ag              5736189, 15026997, -2178256, -13455585},
235872c33676SMaxim Ag         },
235972c33676SMaxim Ag     },
236072c33676SMaxim Ag     {
236172c33676SMaxim Ag         {
236272c33676SMaxim Ag             {-8858980, -2219056, 28571666, -10155518, -474467, -10105698,
236372c33676SMaxim Ag              -3801496, 278095, 23440562, -290208},
236472c33676SMaxim Ag             {10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275,
236572c33676SMaxim Ag              11551483, -16571960, -7442864},
236672c33676SMaxim Ag             {17932739, -12437276, -24039557, 10749060, 11316803, 7535897,
236772c33676SMaxim Ag              22503767, 5561594, -3646624, 3898661},
236872c33676SMaxim Ag         },
236972c33676SMaxim Ag         {
237072c33676SMaxim Ag             {7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531,
237172c33676SMaxim Ag              7152530, 21831162, 1245233},
237272c33676SMaxim Ag             {26958459, -14658026, 4314586, 8346991, -5677764, 11960072,
237372c33676SMaxim Ag              -32589295, -620035, -30402091, -16716212},
237472c33676SMaxim Ag             {-12165896, 9166947, 33491384, 13673479, 29787085, 13096535,
237572c33676SMaxim Ag              6280834, 14587357, -22338025, 13987525},
237672c33676SMaxim Ag         },
237772c33676SMaxim Ag         {
237872c33676SMaxim Ag             {-24349909, 7778775, 21116000, 15572597, -4833266, -5357778,
237972c33676SMaxim Ag              -4300898, -5124639, -7469781, -2858068},
238072c33676SMaxim Ag             {9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781,
238172c33676SMaxim Ag              6439245, -14581012, 4091397},
238272c33676SMaxim Ag             {-8426427, 1470727, -28109679, -1596990, 3978627, -5123623,
238372c33676SMaxim Ag              -19622683, 12092163, 29077877, -14741988},
238472c33676SMaxim Ag         },
238572c33676SMaxim Ag         {
238672c33676SMaxim Ag             {5269168, -6859726, -13230211, -8020715, 25932563, 1763552,
238772c33676SMaxim Ag              -5606110, -5505881, -20017847, 2357889},
238872c33676SMaxim Ag             {32264008, -15407652, -5387735, -1160093, -2091322, -3946900,
238972c33676SMaxim Ag              23104804, -12869908, 5727338, 189038},
239072c33676SMaxim Ag             {14609123, -8954470, -6000566, -16622781, -14577387, -7743898,
239172c33676SMaxim Ag              -26745169, 10942115, -25888931, -14884697},
239272c33676SMaxim Ag         },
239372c33676SMaxim Ag         {
239472c33676SMaxim Ag             {20513500, 5557931, -15604613, 7829531, 26413943, -2019404,
239572c33676SMaxim Ag              -21378968, 7471781, 13913677, -5137875},
239672c33676SMaxim Ag             {-25574376, 11967826, 29233242, 12948236, -6754465, 4713227,
239772c33676SMaxim Ag              -8940970, 14059180, 12878652, 8511905},
239872c33676SMaxim Ag             {-25656801, 3393631, -2955415, -7075526, -2250709, 9366908,
239972c33676SMaxim Ag              -30223418, 6812974, 5568676, -3127656},
240072c33676SMaxim Ag         },
240172c33676SMaxim Ag         {
240272c33676SMaxim Ag             {11630004, 12144454, 2116339, 13606037, 27378885, 15676917,
240372c33676SMaxim Ag              -17408753, -13504373, -14395196, 8070818},
240472c33676SMaxim Ag             {27117696, -10007378, -31282771, -5570088, 1127282, 12772488,
240572c33676SMaxim Ag              -29845906, 10483306, -11552749, -1028714},
240672c33676SMaxim Ag             {10637467, -5688064, 5674781, 1072708, -26343588, -6982302,
240772c33676SMaxim Ag              -1683975, 9177853, -27493162, 15431203},
240872c33676SMaxim Ag         },
240972c33676SMaxim Ag         {
241072c33676SMaxim Ag             {20525145, 10892566, -12742472, 12779443, -29493034, 16150075,
241172c33676SMaxim Ag              -28240519, 14943142, -15056790, -7935931},
241272c33676SMaxim Ag             {-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767,
241372c33676SMaxim Ag              -3239766, -3356550, 9594024},
241472c33676SMaxim Ag             {-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683,
241572c33676SMaxim Ag              -6492290, 13352335, -10977084},
241672c33676SMaxim Ag         },
241772c33676SMaxim Ag         {
241872c33676SMaxim Ag             {-1931799, -5407458, 3304649, -12884869, 17015806, -4877091,
241972c33676SMaxim Ag              -29783850, -7752482, -13215537, -319204},
242072c33676SMaxim Ag             {20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742,
242172c33676SMaxim Ag              15077870, -22750759, 14523817},
242272c33676SMaxim Ag             {27406042, -6041657, 27423596, -4497394, 4996214, 10002360,
242372c33676SMaxim Ag              -28842031, -4545494, -30172742, -4805667},
242472c33676SMaxim Ag         },
242572c33676SMaxim Ag     },
242672c33676SMaxim Ag     {
242772c33676SMaxim Ag         {
242872c33676SMaxim Ag             {11374242, 12660715, 17861383, -12540833, 10935568, 1099227,
242972c33676SMaxim Ag              -13886076, -9091740, -27727044, 11358504},
243072c33676SMaxim Ag             {-12730809, 10311867, 1510375, 10778093, -2119455, -9145702,
243172c33676SMaxim Ag              32676003, 11149336, -26123651, 4985768},
243272c33676SMaxim Ag             {-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043,
243372c33676SMaxim Ag              13794114, -19414307, -15621255},
243472c33676SMaxim Ag         },
243572c33676SMaxim Ag         {
243672c33676SMaxim Ag             {6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603,
243772c33676SMaxim Ag              6970005, -1691065, -9004790},
243872c33676SMaxim Ag             {1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622,
243972c33676SMaxim Ag              -5475723, -16796596, -5031438},
244072c33676SMaxim Ag             {-22273315, -13524424, -64685, -4334223, -18605636, -10921968,
244172c33676SMaxim Ag              -20571065, -7007978, -99853, -10237333},
244272c33676SMaxim Ag         },
244372c33676SMaxim Ag         {
244472c33676SMaxim Ag             {17747465, 10039260, 19368299, -4050591, -20630635, -16041286,
244572c33676SMaxim Ag              31992683, -15857976, -29260363, -5511971},
244672c33676SMaxim Ag             {31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999,
244772c33676SMaxim Ag              -3744247, 4882242, -10626905},
244872c33676SMaxim Ag             {29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198,
244972c33676SMaxim Ag              3272828, -5190932, -4162409},
245072c33676SMaxim Ag         },
245172c33676SMaxim Ag         {
245272c33676SMaxim Ag             {12501286, 4044383, -8612957, -13392385, -32430052, 5136599,
245372c33676SMaxim Ag              -19230378, -3529697, 330070, -3659409},
245472c33676SMaxim Ag             {6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522,
245572c33676SMaxim Ag              -8573892, -271295, 12071499},
245672c33676SMaxim Ag             {-8365515, -4042521, 25133448, -4517355, -6211027, 2265927,
245772c33676SMaxim Ag              -32769618, 1936675, -5159697, 3829363},
245872c33676SMaxim Ag         },
245972c33676SMaxim Ag         {
246072c33676SMaxim Ag             {28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550,
246172c33676SMaxim Ag              -6567787, 26333140, 14267664},
246272c33676SMaxim Ag             {-11067219, 11871231, 27385719, -10559544, -4585914, -11189312,
246372c33676SMaxim Ag              10004786, -8709488, -21761224, 8930324},
246472c33676SMaxim Ag             {-21197785, -16396035, 25654216, -1725397, 12282012, 11008919,
246572c33676SMaxim Ag              1541940, 4757911, -26491501, -16408940},
246672c33676SMaxim Ag         },
246772c33676SMaxim Ag         {
246872c33676SMaxim Ag             {13537262, -7759490, -20604840, 10961927, -5922820, -13218065,
246972c33676SMaxim Ag              -13156584, 6217254, -15943699, 13814990},
247072c33676SMaxim Ag             {-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681,
247172c33676SMaxim Ag              9257833, -1956526, -1776914},
247272c33676SMaxim Ag             {-25045300, -10191966, 15366585, 15166509, -13105086, 8423556,
247372c33676SMaxim Ag              -29171540, 12361135, -18685978, 4578290},
247472c33676SMaxim Ag         },
247572c33676SMaxim Ag         {
247672c33676SMaxim Ag             {24579768, 3711570, 1342322, -11180126, -27005135, 14124956,
247772c33676SMaxim Ag              -22544529, 14074919, 21964432, 8235257},
247872c33676SMaxim Ag             {-6528613, -2411497, 9442966, -5925588, 12025640, -1487420,
247972c33676SMaxim Ag              -2981514, -1669206, 13006806, 2355433},
248072c33676SMaxim Ag             {-16304899, -13605259, -6632427, -5142349, 16974359, -10911083,
248172c33676SMaxim Ag              27202044, 1719366, 1141648, -12796236},
248272c33676SMaxim Ag         },
248372c33676SMaxim Ag         {
248472c33676SMaxim Ag             {-12863944, -13219986, -8318266, -11018091, -6810145, -4843894,
248572c33676SMaxim Ag              13475066, -3133972, 32674895, 13715045},
248672c33676SMaxim Ag             {11423335, -5468059, 32344216, 8962751, 24989809, 9241752,
248772c33676SMaxim Ag              -13265253, 16086212, -28740881, -15642093},
248872c33676SMaxim Ag             {-1409668, 12530728, -6368726, 10847387, 19531186, -14132160,
248972c33676SMaxim Ag              -11709148, 7791794, -27245943, 4383347},
249072c33676SMaxim Ag         },
249172c33676SMaxim Ag     },
249272c33676SMaxim Ag     {
249372c33676SMaxim Ag         {
249472c33676SMaxim Ag             {-28970898, 5271447, -1266009, -9736989, -12455236, 16732599,
249572c33676SMaxim Ag              -4862407, -4906449, 27193557, 6245191},
249672c33676SMaxim Ag             {-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898,
249772c33676SMaxim Ag              3260492, 22510453, 8577507},
249872c33676SMaxim Ag             {-12632451, 11257346, -32692994, 13548177, -721004, 10879011,
249972c33676SMaxim Ag              31168030, 13952092, -29571492, -3635906},
250072c33676SMaxim Ag         },
250172c33676SMaxim Ag         {
250272c33676SMaxim Ag             {3877321, -9572739, 32416692, 5405324, -11004407, -13656635,
250372c33676SMaxim Ag              3759769, 11935320, 5611860, 8164018},
250472c33676SMaxim Ag             {-16275802, 14667797, 15906460, 12155291, -22111149, -9039718,
250572c33676SMaxim Ag              32003002, -8832289, 5773085, -8422109},
250672c33676SMaxim Ag             {-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725,
250772c33676SMaxim Ag              12376320, 31632953, 190926},
250872c33676SMaxim Ag         },
250972c33676SMaxim Ag         {
251072c33676SMaxim Ag             {-24593607, -16138885, -8423991, 13378746, 14162407, 6901328,
251172c33676SMaxim Ag              -8288749, 4508564, -25341555, -3627528},
251272c33676SMaxim Ag             {8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941,
251372c33676SMaxim Ag              -14786005, -1672488, 827625},
251472c33676SMaxim Ag             {-32720583, -16289296, -32503547, 7101210, 13354605, 2659080,
251572c33676SMaxim Ag              -1800575, -14108036, -24878478, 1541286},
251672c33676SMaxim Ag         },
251772c33676SMaxim Ag         {
251872c33676SMaxim Ag             {2901347, -1117687, 3880376, -10059388, -17620940, -3612781,
251972c33676SMaxim Ag              -21802117, -3567481, 20456845, -1885033},
252072c33676SMaxim Ag             {27019610, 12299467, -13658288, -1603234, -12861660, -4861471,
252172c33676SMaxim Ag              -19540150, -5016058, 29439641, 15138866},
252272c33676SMaxim Ag             {21536104, -6626420, -32447818, -10690208, -22408077, 5175814,
252372c33676SMaxim Ag              -5420040, -16361163, 7779328, 109896},
252472c33676SMaxim Ag         },
252572c33676SMaxim Ag         {
252672c33676SMaxim Ag             {30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390,
252772c33676SMaxim Ag              12180118, 23177719, -554075},
252872c33676SMaxim Ag             {26572847, 3405927, -31701700, 12890905, -19265668, 5335866,
252972c33676SMaxim Ag              -6493768, 2378492, 4439158, -13279347},
253072c33676SMaxim Ag             {-22716706, 3489070, -9225266, -332753, 18875722, -1140095,
253172c33676SMaxim Ag              14819434, -12731527, -17717757, -5461437},
253272c33676SMaxim Ag         },
253372c33676SMaxim Ag         {
253472c33676SMaxim Ag             {-5056483, 16566551, 15953661, 3767752, -10436499, 15627060,
253572c33676SMaxim Ag              -820954, 2177225, 8550082, -15114165},
253672c33676SMaxim Ag             {-18473302, 16596775, -381660, 15663611, 22860960, 15585581,
253772c33676SMaxim Ag              -27844109, -3582739, -23260460, -8428588},
253872c33676SMaxim Ag             {-32480551, 15707275, -8205912, -5652081, 29464558, 2713815,
253972c33676SMaxim Ag              -22725137, 15860482, -21902570, 1494193},
254072c33676SMaxim Ag         },
254172c33676SMaxim Ag         {
254272c33676SMaxim Ag             {-19562091, -14087393, -25583872, -9299552, 13127842, 759709,
254372c33676SMaxim Ag              21923482, 16529112, 8742704, 12967017},
254472c33676SMaxim Ag             {-28464899, 1553205, 32536856, -10473729, -24691605, -406174,
254572c33676SMaxim Ag              -8914625, -2933896, -29903758, 15553883},
254672c33676SMaxim Ag             {21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572,
254772c33676SMaxim Ag              14513274, 19375923, -12647961},
254872c33676SMaxim Ag         },
254972c33676SMaxim Ag         {
255072c33676SMaxim Ag             {8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818,
255172c33676SMaxim Ag              -6222716, 2862653, 9455043},
255272c33676SMaxim Ag             {29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124,
255372c33676SMaxim Ag              -2990080, 15511449, 4789663},
255472c33676SMaxim Ag             {-20679756, 7004547, 8824831, -9434977, -4045704, -3750736,
255572c33676SMaxim Ag              -5754762, 108893, 23513200, 16652362},
255672c33676SMaxim Ag         },
255772c33676SMaxim Ag     },
255872c33676SMaxim Ag     {
255972c33676SMaxim Ag         {
256072c33676SMaxim Ag             {-33256173, 4144782, -4476029, -6579123, 10770039, -7155542,
256172c33676SMaxim Ag              -6650416, -12936300, -18319198, 10212860},
256272c33676SMaxim Ag             {2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801,
256372c33676SMaxim Ag              2600940, -9988298, -12506466},
256472c33676SMaxim Ag             {-24645692, 13317462, -30449259, -15653928, 21365574, -10869657,
256572c33676SMaxim Ag              11344424, 864440, -2499677, -16710063},
256672c33676SMaxim Ag         },
256772c33676SMaxim Ag         {
256872c33676SMaxim Ag             {-26432803, 6148329, -17184412, -14474154, 18782929, -275997,
256972c33676SMaxim Ag              -22561534, 211300, 2719757, 4940997},
257072c33676SMaxim Ag             {-1323882, 3911313, -6948744, 14759765, -30027150, 7851207,
257172c33676SMaxim Ag              21690126, 8518463, 26699843, 5276295},
257272c33676SMaxim Ag             {-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586,
257372c33676SMaxim Ag              149635, -15452774, 7159369},
257472c33676SMaxim Ag         },
257572c33676SMaxim Ag         {
257672c33676SMaxim Ag             {9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009,
257772c33676SMaxim Ag              8312176, 22477218, -8403385},
257872c33676SMaxim Ag             {18155857, -16504990, 19744716, 9006923, 15154154, -10538976,
257972c33676SMaxim Ag              24256460, -4864995, -22548173, 9334109},
258072c33676SMaxim Ag             {2986088, -4911893, 10776628, -3473844, 10620590, -7083203,
258172c33676SMaxim Ag              -21413845, 14253545, -22587149, 536906},
258272c33676SMaxim Ag         },
258372c33676SMaxim Ag         {
258472c33676SMaxim Ag             {4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551,
258572c33676SMaxim Ag              10589625, 10838060, -15420424},
258672c33676SMaxim Ag             {-19342404, 867880, 9277171, -3218459, -14431572, -1986443,
258772c33676SMaxim Ag              19295826, -15796950, 6378260, 699185},
258872c33676SMaxim Ag             {7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039,
258972c33676SMaxim Ag              15693155, -5045064, -13373962},
259072c33676SMaxim Ag         },
259172c33676SMaxim Ag         {
259272c33676SMaxim Ag             {-7737563, -5869402, -14566319, -7406919, 11385654, 13201616,
259372c33676SMaxim Ag              31730678, -10962840, -3918636, -9669325},
259472c33676SMaxim Ag             {10188286, -15770834, -7336361, 13427543, 22223443, 14896287,
259572c33676SMaxim Ag              30743455, 7116568, -21786507, 5427593},
259672c33676SMaxim Ag             {696102, 13206899, 27047647, -10632082, 15285305, -9853179,
259772c33676SMaxim Ag              10798490, -4578720, 19236243, 12477404},
259872c33676SMaxim Ag         },
259972c33676SMaxim Ag         {
260072c33676SMaxim Ag             {-11229439, 11243796, -17054270, -8040865, -788228, -8167967,
260172c33676SMaxim Ag              -3897669, 11180504, -23169516, 7733644},
260272c33676SMaxim Ag             {17800790, -14036179, -27000429, -11766671, 23887827, 3149671,
260372c33676SMaxim Ag              23466177, -10538171, 10322027, 15313801},
260472c33676SMaxim Ag             {26246234, 11968874, 32263343, -5468728, 6830755, -13323031,
260572c33676SMaxim Ag              -15794704, -101982, -24449242, 10890804},
260672c33676SMaxim Ag         },
260772c33676SMaxim Ag         {
260872c33676SMaxim Ag             {-31365647, 10271363, -12660625, -6267268, 16690207, -13062544,
260972c33676SMaxim Ag              -14982212, 16484931, 25180797, -5334884},
261072c33676SMaxim Ag             {-586574, 10376444, -32586414, -11286356, 19801893, 10997610,
261172c33676SMaxim Ag              2276632, 9482883, 316878, 13820577},
261272c33676SMaxim Ag             {-9882808, -4510367, -2115506, 16457136, -11100081, 11674996,
261372c33676SMaxim Ag              30756178, -7515054, 30696930, -3712849},
261472c33676SMaxim Ag         },
261572c33676SMaxim Ag         {
261672c33676SMaxim Ag             {32988917, -9603412, 12499366, 7910787, -10617257, -11931514,
261772c33676SMaxim Ag              -7342816, -9985397, -32349517, 7392473},
261872c33676SMaxim Ag             {-8855661, 15927861, 9866406, -3649411, -2396914, -16655781,
261972c33676SMaxim Ag              -30409476, -9134995, 25112947, -2926644},
262072c33676SMaxim Ag             {-2504044, -436966, 25621774, -5678772, 15085042, -5479877,
262172c33676SMaxim Ag              -24884878, -13526194, 5537438, -13914319},
262272c33676SMaxim Ag         },
262372c33676SMaxim Ag     },
262472c33676SMaxim Ag     {
262572c33676SMaxim Ag         {
262672c33676SMaxim Ag             {-11225584, 2320285, -9584280, 10149187, -33444663, 5808648,
262772c33676SMaxim Ag              -14876251, -1729667, 31234590, 6090599},
262872c33676SMaxim Ag             {-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721,
262972c33676SMaxim Ag              15878753, -6970405, -9034768},
263072c33676SMaxim Ag             {-27757857, 247744, -15194774, -9002551, 23288161, -10011936,
263172c33676SMaxim Ag              -23869595, 6503646, 20650474, 1804084},
263272c33676SMaxim Ag         },
263372c33676SMaxim Ag         {
263472c33676SMaxim Ag             {-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995,
263572c33676SMaxim Ag              -10329713, 27842616, -202328},
263672c33676SMaxim Ag             {-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656,
263772c33676SMaxim Ag              5031932, -11375082, 12714369},
263872c33676SMaxim Ag             {20807691, -7270825, 29286141, 11421711, -27876523, -13868230,
263972c33676SMaxim Ag              -21227475, 1035546, -19733229, 12796920},
264072c33676SMaxim Ag         },
264172c33676SMaxim Ag         {
264272c33676SMaxim Ag             {12076899, -14301286, -8785001, -11848922, -25012791, 16400684,
264372c33676SMaxim Ag              -17591495, -12899438, 3480665, -15182815},
264472c33676SMaxim Ag             {-32361549, 5457597, 28548107, 7833186, 7303070, -11953545,
264572c33676SMaxim Ag              -24363064, -15921875, -33374054, 2771025},
264672c33676SMaxim Ag             {-21389266, 421932, 26597266, 6860826, 22486084, -6737172,
264772c33676SMaxim Ag              -17137485, -4210226, -24552282, 15673397},
264872c33676SMaxim Ag         },
264972c33676SMaxim Ag         {
265072c33676SMaxim Ag             {-20184622, 2338216, 19788685, -9620956, -4001265, -8740893,
265172c33676SMaxim Ag              -20271184, 4733254, 3727144, -12934448},
265272c33676SMaxim Ag             {6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594,
265372c33676SMaxim Ag              7975683, 31123697, -10958981},
265472c33676SMaxim Ag             {30069250, -11435332, 30434654, 2958439, 18399564, -976289,
265572c33676SMaxim Ag              12296869, 9204260, -16432438, 9648165},
265672c33676SMaxim Ag         },
265772c33676SMaxim Ag         {
265872c33676SMaxim Ag             {32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266,
265972c33676SMaxim Ag              5248604, -26008332, -11377501},
266072c33676SMaxim Ag             {17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711,
266172c33676SMaxim Ag              15298639, 2662509, -16297073},
266272c33676SMaxim Ag             {-1172927, -7558695, -4366770, -4287744, -21346413, -8434326,
266372c33676SMaxim Ag              32087529, -1222777, 32247248, -14389861},
266472c33676SMaxim Ag         },
266572c33676SMaxim Ag         {
266672c33676SMaxim Ag             {14312628, 1221556, 17395390, -8700143, -4945741, -8684635,
266772c33676SMaxim Ag              -28197744, -9637817, -16027623, -13378845},
266872c33676SMaxim Ag             {-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502,
266972c33676SMaxim Ag              9803137, 17597934, 2346211},
267072c33676SMaxim Ag             {18510800, 15337574, 26171504, 981392, -22241552, 7827556,
267172c33676SMaxim Ag              -23491134, -11323352, 3059833, -11782870},
267272c33676SMaxim Ag         },
267372c33676SMaxim Ag         {
267472c33676SMaxim Ag             {10141598, 6082907, 17829293, -1947643, 9830092, 13613136,
267572c33676SMaxim Ag              -25556636, -5544586, -33502212, 3592096},
267672c33676SMaxim Ag             {33114168, -15889352, -26525686, -13343397, 33076705, 8716171,
267772c33676SMaxim Ag              1151462, 1521897, -982665, -6837803},
267872c33676SMaxim Ag             {-32939165, -4255815, 23947181, -324178, -33072974, -12305637,
267972c33676SMaxim Ag              -16637686, 3891704, 26353178, 693168},
268072c33676SMaxim Ag         },
268172c33676SMaxim Ag         {
268272c33676SMaxim Ag             {30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294,
268372c33676SMaxim Ag              -400668, 31375464, 14369965},
268472c33676SMaxim Ag             {-14370654, -7772529, 1510301, 6434173, -18784789, -6262728,
268572c33676SMaxim Ag              32732230, -13108839, 17901441, 16011505},
268672c33676SMaxim Ag             {18171223, -11934626, -12500402, 15197122, -11038147, -15230035,
268772c33676SMaxim Ag              -19172240, -16046376, 8764035, 12309598},
268872c33676SMaxim Ag         },
268972c33676SMaxim Ag     },
269072c33676SMaxim Ag     {
269172c33676SMaxim Ag         {
269272c33676SMaxim Ag             {5975908, -5243188, -19459362, -9681747, -11541277, 14015782,
269372c33676SMaxim Ag              -23665757, 1228319, 17544096, -10593782},
269472c33676SMaxim Ag             {5811932, -1715293, 3442887, -2269310, -18367348, -8359541,
269572c33676SMaxim Ag              -18044043, -15410127, -5565381, 12348900},
269672c33676SMaxim Ag             {-31399660, 11407555, 25755363, 6891399, -3256938, 14872274,
269772c33676SMaxim Ag              -24849353, 8141295, -10632534, -585479},
269872c33676SMaxim Ag         },
269972c33676SMaxim Ag         {
270072c33676SMaxim Ag             {-12675304, 694026, -5076145, 13300344, 14015258, -14451394,
270172c33676SMaxim Ag              -9698672, -11329050, 30944593, 1130208},
270272c33676SMaxim Ag             {8247766, -6710942, -26562381, -7709309, -14401939, -14648910,
270372c33676SMaxim Ag              4652152, 2488540, 23550156, -271232},
270472c33676SMaxim Ag             {17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737,
270572c33676SMaxim Ag              -5908146, -408818, -137719},
270672c33676SMaxim Ag         },
270772c33676SMaxim Ag         {
270872c33676SMaxim Ag             {16091085, -16253926, 18599252, 7340678, 2137637, -1221657,
270972c33676SMaxim Ag              -3364161, 14550936, 3260525, -7166271},
271072c33676SMaxim Ag             {-4910104, -13332887, 18550887, 10864893, -16459325, -7291596,
271172c33676SMaxim Ag              -23028869, -13204905, -12748722, 2701326},
271272c33676SMaxim Ag             {-8574695, 16099415, 4629974, -16340524, -20786213, -6005432,
271372c33676SMaxim Ag              -10018363, 9276971, 11329923, 1862132},
271472c33676SMaxim Ag         },
271572c33676SMaxim Ag         {
271672c33676SMaxim Ag             {14763076, -15903608, -30918270, 3689867, 3511892, 10313526,
271772c33676SMaxim Ag              -21951088, 12219231, -9037963, -940300},
271872c33676SMaxim Ag             {8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216,
271972c33676SMaxim Ag              -2909717, -15438168, 11595570},
272072c33676SMaxim Ag             {15214962, 3537601, -26238722, -14058872, 4418657, -15230761,
272172c33676SMaxim Ag              13947276, 10730794, -13489462, -4363670},
272272c33676SMaxim Ag         },
272372c33676SMaxim Ag         {
272472c33676SMaxim Ag             {-2538306, 7682793, 32759013, 263109, -29984731, -7955452,
272572c33676SMaxim Ag              -22332124, -10188635, 977108, 699994},
272672c33676SMaxim Ag             {-12466472, 4195084, -9211532, 550904, -15565337, 12917920,
272772c33676SMaxim Ag              19118110, -439841, -30534533, -14337913},
272872c33676SMaxim Ag             {31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237,
272972c33676SMaxim Ag              -10051775, 12493932, -5409317},
273072c33676SMaxim Ag         },
273172c33676SMaxim Ag         {
273272c33676SMaxim Ag             {-25680606, 5260744, -19235809, -6284470, -3695942, 16566087,
273372c33676SMaxim Ag              27218280, 2607121, 29375955, 6024730},
273472c33676SMaxim Ag             {842132, -2794693, -4763381, -8722815, 26332018, -12405641,
273572c33676SMaxim Ag              11831880, 6985184, -9940361, 2854096},
273672c33676SMaxim Ag             {-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645,
273772c33676SMaxim Ag              960770, 12121869, 16648078},
273872c33676SMaxim Ag         },
273972c33676SMaxim Ag         {
274072c33676SMaxim Ag             {-15218652, 14667096, -13336229, 2013717, 30598287, -464137,
274172c33676SMaxim Ag              -31504922, -7882064, 20237806, 2838411},
274272c33676SMaxim Ag             {-19288047, 4453152, 15298546, -16178388, 22115043, -15972604,
274372c33676SMaxim Ag              12544294, -13470457, 1068881, -12499905},
274472c33676SMaxim Ag             {-9558883, -16518835, 33238498, 13506958, 30505848, -1114596,
274572c33676SMaxim Ag              -8486907, -2630053, 12521378, 4845654},
274672c33676SMaxim Ag         },
274772c33676SMaxim Ag         {
274872c33676SMaxim Ag             {-28198521, 10744108, -2958380, 10199664, 7759311, -13088600,
274972c33676SMaxim Ag              3409348, -873400, -6482306, -12885870},
275072c33676SMaxim Ag             {-23561822, 6230156, -20382013, 10655314, -24040585, -11621172,
275172c33676SMaxim Ag              10477734, -1240216, -3113227, 13974498},
275272c33676SMaxim Ag             {12966261, 15550616, -32038948, -1615346, 21025980, -629444,
275372c33676SMaxim Ag              5642325, 7188737, 18895762, 12629579},
275472c33676SMaxim Ag         },
275572c33676SMaxim Ag     },
275672c33676SMaxim Ag     {
275772c33676SMaxim Ag         {
275872c33676SMaxim Ag             {14741879, -14946887, 22177208, -11721237, 1279741, 8058600,
275972c33676SMaxim Ag              11758140, 789443, 32195181, 3895677},
276072c33676SMaxim Ag             {10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575,
276172c33676SMaxim Ag              -3566119, -8982069, 4429647},
276272c33676SMaxim Ag             {-2453894, 15725973, -20436342, -10410672, -5803908, -11040220,
276372c33676SMaxim Ag              -7135870, -11642895, 18047436, -15281743},
276472c33676SMaxim Ag         },
276572c33676SMaxim Ag         {
276672c33676SMaxim Ag             {-25173001, -11307165, 29759956, 11776784, -22262383, -15820455,
276772c33676SMaxim Ag              10993114, -12850837, -17620701, -9408468},
276872c33676SMaxim Ag             {21987233, 700364, -24505048, 14972008, -7774265, -5718395,
276972c33676SMaxim Ag              32155026, 2581431, -29958985, 8773375},
277072c33676SMaxim Ag             {-25568350, 454463, -13211935, 16126715, 25240068, 8594567,
277172c33676SMaxim Ag              20656846, 12017935, -7874389, -13920155},
277272c33676SMaxim Ag         },
277372c33676SMaxim Ag         {
277472c33676SMaxim Ag             {6028182, 6263078, -31011806, -11301710, -818919, 2461772,
277572c33676SMaxim Ag              -31841174, -5468042, -1721788, -2776725},
277672c33676SMaxim Ag             {-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845,
277772c33676SMaxim Ag              -4166698, 28408820, 6816612},
277872c33676SMaxim Ag             {-10358094, -8237829, 19549651, -12169222, 22082623, 16147817,
277972c33676SMaxim Ag              20613181, 13982702, -10339570, 5067943},
278072c33676SMaxim Ag         },
278172c33676SMaxim Ag         {
278272c33676SMaxim Ag             {-30505967, -3821767, 12074681, 13582412, -19877972, 2443951,
278372c33676SMaxim Ag              -19719286, 12746132, 5331210, -10105944},
278472c33676SMaxim Ag             {30528811, 3601899, -1957090, 4619785, -27361822, -15436388,
278572c33676SMaxim Ag              24180793, -12570394, 27679908, -1648928},
278672c33676SMaxim Ag             {9402404, -13957065, 32834043, 10838634, -26580150, -13237195,
278772c33676SMaxim Ag              26653274, -8685565, 22611444, -12715406},
278872c33676SMaxim Ag         },
278972c33676SMaxim Ag         {
279072c33676SMaxim Ag             {22190590, 1118029, 22736441, 15130463, -30460692, -5991321,
279172c33676SMaxim Ag              19189625, -4648942, 4854859, 6622139},
279272c33676SMaxim Ag             {-8310738, -2953450, -8262579, -3388049, -10401731, -271929,
279372c33676SMaxim Ag              13424426, -3567227, 26404409, 13001963},
279472c33676SMaxim Ag             {-31241838, -15415700, -2994250, 8939346, 11562230, -12840670,
279572c33676SMaxim Ag              -26064365, -11621720, -15405155, 11020693},
279672c33676SMaxim Ag         },
279772c33676SMaxim Ag         {
279872c33676SMaxim Ag             {1866042, -7949489, -7898649, -10301010, 12483315, 13477547,
279972c33676SMaxim Ag              3175636, -12424163, 28761762, 1406734},
280072c33676SMaxim Ag             {-448555, -1777666, 13018551, 3194501, -9580420, -11161737,
280172c33676SMaxim Ag              24760585, -4347088, 25577411, -13378680},
280272c33676SMaxim Ag             {-24290378, 4759345, -690653, -1852816, 2066747, 10693769,
280372c33676SMaxim Ag              -29595790, 9884936, -9368926, 4745410},
280472c33676SMaxim Ag         },
280572c33676SMaxim Ag         {
280672c33676SMaxim Ag             {-9141284, 6049714, -19531061, -4341411, -31260798, 9944276,
280772c33676SMaxim Ag              -15462008, -11311852, 10931924, -11931931},
280872c33676SMaxim Ag             {-16561513, 14112680, -8012645, 4817318, -8040464, -11414606,
280972c33676SMaxim Ag              -22853429, 10856641, -20470770, 13434654},
281072c33676SMaxim Ag             {22759489, -10073434, -16766264, -1871422, 13637442, -10168091,
281172c33676SMaxim Ag              1765144, -12654326, 28445307, -5364710},
281272c33676SMaxim Ag         },
281372c33676SMaxim Ag         {
281472c33676SMaxim Ag             {29875063, 12493613, 2795536, -3786330, 1710620, 15181182,
281572c33676SMaxim Ag              -10195717, -8788675, 9074234, 1167180},
281672c33676SMaxim Ag             {-26205683, 11014233, -9842651, -2635485, -26908120, 7532294,
281772c33676SMaxim Ag              -18716888, -9535498, 3843903, 9367684},
281872c33676SMaxim Ag             {-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123,
281972c33676SMaxim Ag              8601684, -139197, 4242895},
282072c33676SMaxim Ag         },
282172c33676SMaxim Ag     },
282272c33676SMaxim Ag     {
282372c33676SMaxim Ag         {
282472c33676SMaxim Ag             {22092954, -13191123, -2042793, -11968512, 32186753, -11517388,
282572c33676SMaxim Ag              -6574341, 2470660, -27417366, 16625501},
282672c33676SMaxim Ag             {-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857,
282772c33676SMaxim Ag              2602725, -27351616, 14247413},
282872c33676SMaxim Ag             {6314175, -10264892, -32772502, 15957557, -10157730, 168750,
282972c33676SMaxim Ag              -8618807, 14290061, 27108877, -1180880},
283072c33676SMaxim Ag         },
283172c33676SMaxim Ag         {
283272c33676SMaxim Ag             {-8586597, -7170966, 13241782, 10960156, -32991015, -13794596,
283372c33676SMaxim Ag              33547976, -11058889, -27148451, 981874},
283472c33676SMaxim Ag             {22833440, 9293594, -32649448, -13618667, -9136966, 14756819,
283572c33676SMaxim Ag              -22928859, -13970780, -10479804, -16197962},
283672c33676SMaxim Ag             {-7768587, 3326786, -28111797, 10783824, 19178761, 14905060,
283772c33676SMaxim Ag              22680049, 13906969, -15933690, 3797899},
283872c33676SMaxim Ag         },
283972c33676SMaxim Ag         {
284072c33676SMaxim Ag             {21721356, -4212746, -12206123, 9310182, -3882239, -13653110,
284172c33676SMaxim Ag              23740224, -2709232, 20491983, -8042152},
284272c33676SMaxim Ag             {9209270, -15135055, -13256557, -6167798, -731016, 15289673,
284372c33676SMaxim Ag              25947805, 15286587, 30997318, -6703063},
284472c33676SMaxim Ag             {7392032, 16618386, 23946583, -8039892, -13265164, -1533858,
284572c33676SMaxim Ag              -14197445, -2321576, 17649998, -250080},
284672c33676SMaxim Ag         },
284772c33676SMaxim Ag         {
284872c33676SMaxim Ag             {-9301088, -14193827, 30609526, -3049543, -25175069, -1283752,
284972c33676SMaxim Ag              -15241566, -9525724, -2233253, 7662146},
285072c33676SMaxim Ag             {-17558673, 1763594, -33114336, 15908610, -30040870, -12174295,
285172c33676SMaxim Ag              7335080, -8472199, -3174674, 3440183},
285272c33676SMaxim Ag             {-19889700, -5977008, -24111293, -9688870, 10799743, -16571957,
285372c33676SMaxim Ag              40450, -4431835, 4862400, 1133},
285472c33676SMaxim Ag         },
285572c33676SMaxim Ag         {
285672c33676SMaxim Ag             {-32856209, -7873957, -5422389, 14860950, -16319031, 7956142,
285772c33676SMaxim Ag              7258061, 311861, -30594991, -7379421},
285872c33676SMaxim Ag             {-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763,
285972c33676SMaxim Ag              16527196, 18278453, 15405622},
286072c33676SMaxim Ag             {-4381906, 8508652, -19898366, -3674424, -5984453, 15149970,
286172c33676SMaxim Ag              -13313598, 843523, -21875062, 13626197},
286272c33676SMaxim Ag         },
286372c33676SMaxim Ag         {
286472c33676SMaxim Ag             {2281448, -13487055, -10915418, -2609910, 1879358, 16164207,
286572c33676SMaxim Ag              -10783882, 3953792, 13340839, 15928663},
286672c33676SMaxim Ag             {31727126, -7179855, -18437503, -8283652, 2875793, -16390330,
286772c33676SMaxim Ag              -25269894, -7014826, -23452306, 5964753},
286872c33676SMaxim Ag             {4100420, -5959452, -17179337, 6017714, -18705837, 12227141,
286972c33676SMaxim Ag              -26684835, 11344144, 2538215, -7570755},
287072c33676SMaxim Ag         },
287172c33676SMaxim Ag         {
287272c33676SMaxim Ag             {-9433605, 6123113, 11159803, -2156608, 30016280, 14966241,
287372c33676SMaxim Ag              -20474983, 1485421, -629256, -15958862},
287472c33676SMaxim Ag             {-26804558, 4260919, 11851389, 9658551, -32017107, 16367492,
287572c33676SMaxim Ag              -20205425, -13191288, 11659922, -11115118},
287672c33676SMaxim Ag             {26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568,
287772c33676SMaxim Ag              -10170080, 33100372, -1306171},
287872c33676SMaxim Ag         },
287972c33676SMaxim Ag         {
288072c33676SMaxim Ag             {15121113, -5201871, -10389905, 15427821, -27509937, -15992507,
288172c33676SMaxim Ag              21670947, 4486675, -5931810, -14466380},
288272c33676SMaxim Ag             {16166486, -9483733, -11104130, 6023908, -31926798, -1364923,
288372c33676SMaxim Ag              2340060, -16254968, -10735770, -10039824},
288472c33676SMaxim Ag             {28042865, -3557089, -12126526, 12259706, -3717498, -6945899,
288572c33676SMaxim Ag              6766453, -8689599, 18036436, 5803270},
288672c33676SMaxim Ag         },
288772c33676SMaxim Ag     },
288872c33676SMaxim Ag     {
288972c33676SMaxim Ag         {
289072c33676SMaxim Ag             {-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391,
289172c33676SMaxim Ag              4598332, -6159431, -14117438},
289272c33676SMaxim Ag             {-31031306, -14256194, 17332029, -2383520, 31312682, -5967183,
289372c33676SMaxim Ag              696309, 50292, -20095739, 11763584},
289472c33676SMaxim Ag             {-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117,
289572c33676SMaxim Ag              -12613632, -19773211, -10713562},
289672c33676SMaxim Ag         },
289772c33676SMaxim Ag         {
289872c33676SMaxim Ag             {30464590, -11262872, -4127476, -12734478, 19835327, -7105613,
289972c33676SMaxim Ag              -24396175, 2075773, -17020157, 992471},
290072c33676SMaxim Ag             {18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841,
290172c33676SMaxim Ag              8080033, -11574335, -10601610},
290272c33676SMaxim Ag             {19598397, 10334610, 12555054, 2555664, 18821899, -10339780,
290372c33676SMaxim Ag              21873263, 16014234, 26224780, 16452269},
290472c33676SMaxim Ag         },
290572c33676SMaxim Ag         {
290672c33676SMaxim Ag             {-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804,
290772c33676SMaxim Ag              -7618186, -20533829, 3698650},
290872c33676SMaxim Ag             {14187449, 3448569, -10636236, -10810935, -22663880, -3433596,
290972c33676SMaxim Ag              7268410, -10890444, 27394301, 12015369},
291072c33676SMaxim Ag             {19695761, 16087646, 28032085, 12999827, 6817792, 11427614,
291172c33676SMaxim Ag              20244189, -1312777, -13259127, -3402461},
291272c33676SMaxim Ag         },
291372c33676SMaxim Ag         {
291472c33676SMaxim Ag             {30860103, 12735208, -1888245, -4699734, -16974906, 2256940,
291572c33676SMaxim Ag              -8166013, 12298312, -8550524, -10393462},
291672c33676SMaxim Ag             {-5719826, -11245325, -1910649, 15569035, 26642876, -7587760,
291772c33676SMaxim Ag              -5789354, -15118654, -4976164, 12651793},
291872c33676SMaxim Ag             {-2848395, 9953421, 11531313, -5282879, 26895123, -12697089,
291972c33676SMaxim Ag              -13118820, -16517902, 9768698, -2533218},
292072c33676SMaxim Ag         },
292172c33676SMaxim Ag         {
292272c33676SMaxim Ag             {-24719459, 1894651, -287698, -4704085, 15348719, -8156530,
292372c33676SMaxim Ag              32767513, 12765450, 4940095, 10678226},
292472c33676SMaxim Ag             {18860224, 15980149, -18987240, -1562570, -26233012, -11071856,
292572c33676SMaxim Ag              -7843882, 13944024, -24372348, 16582019},
292672c33676SMaxim Ag             {-15504260, 4970268, -29893044, 4175593, -20993212, -2199756,
292772c33676SMaxim Ag              -11704054, 15444560, -11003761, 7989037},
292872c33676SMaxim Ag         },
292972c33676SMaxim Ag         {
293072c33676SMaxim Ag             {31490452, 5568061, -2412803, 2182383, -32336847, 4531686,
293172c33676SMaxim Ag              -32078269, 6200206, -19686113, -14800171},
293272c33676SMaxim Ag             {-17308668, -15879940, -31522777, -2831, -32887382, 16375549,
293372c33676SMaxim Ag              8680158, -16371713, 28550068, -6857132},
293472c33676SMaxim Ag             {-28126887, -5688091, 16837845, -1820458, -6850681, 12700016,
293572c33676SMaxim Ag              -30039981, 4364038, 1155602, 5988841},
293672c33676SMaxim Ag         },
293772c33676SMaxim Ag         {
293872c33676SMaxim Ag             {21890435, -13272907, -12624011, 12154349, -7831873, 15300496,
293972c33676SMaxim Ag              23148983, -4470481, 24618407, 8283181},
294072c33676SMaxim Ag             {-33136107, -10512751, 9975416, 6841041, -31559793, 16356536,
294172c33676SMaxim Ag              3070187, -7025928, 1466169, 10740210},
294272c33676SMaxim Ag             {-1509399, -15488185, -13503385, -10655916, 32799044, 909394,
294372c33676SMaxim Ag              -13938903, -5779719, -32164649, -15327040},
294472c33676SMaxim Ag         },
294572c33676SMaxim Ag         {
294672c33676SMaxim Ag             {3960823, -14267803, -28026090, -15918051, -19404858, 13146868,
294772c33676SMaxim Ag              15567327, 951507, -3260321, -573935},
294872c33676SMaxim Ag             {24740841, 5052253, -30094131, 8961361, 25877428, 6165135,
294972c33676SMaxim Ag              -24368180, 14397372, -7380369, -6144105},
295072c33676SMaxim Ag             {-28888365, 3510803, -28103278, -1158478, -11238128, -10631454,
295172c33676SMaxim Ag              -15441463, -14453128, -1625486, -6494814},
295272c33676SMaxim Ag         },
295372c33676SMaxim Ag     },
295472c33676SMaxim Ag     {
295572c33676SMaxim Ag         {
295672c33676SMaxim Ag             {793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843,
295772c33676SMaxim Ag              -4885251, -9906200, -621852},
295872c33676SMaxim Ag             {5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374,
295972c33676SMaxim Ag              1468826, -6171428, -15186581},
296072c33676SMaxim Ag             {-4859255, -3779343, -2917758, -6748019, 7778750, 11688288,
296172c33676SMaxim Ag              -30404353, -9871238, -1558923, -9863646},
296272c33676SMaxim Ag         },
296372c33676SMaxim Ag         {
296472c33676SMaxim Ag             {10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958,
296572c33676SMaxim Ag              14783338, -30581476, -15757844},
296672c33676SMaxim Ag             {10566929, 12612572, -31944212, 11118703, -12633376, 12362879,
296772c33676SMaxim Ag              21752402, 8822496, 24003793, 14264025},
296872c33676SMaxim Ag             {27713862, -7355973, -11008240, 9227530, 27050101, 2504721,
296972c33676SMaxim Ag              23886875, -13117525, 13958495, -5732453},
297072c33676SMaxim Ag         },
297172c33676SMaxim Ag         {
297272c33676SMaxim Ag             {-23481610, 4867226, -27247128, 3900521, 29838369, -8212291,
297372c33676SMaxim Ag              -31889399, -10041781, 7340521, -15410068},
297472c33676SMaxim Ag             {4646514, -8011124, -22766023, -11532654, 23184553, 8566613,
297572c33676SMaxim Ag              31366726, -1381061, -15066784, -10375192},
297672c33676SMaxim Ag             {-17270517, 12723032, -16993061, 14878794, 21619651, -6197576,
297772c33676SMaxim Ag              27584817, 3093888, -8843694, 3849921},
297872c33676SMaxim Ag         },
297972c33676SMaxim Ag         {
298072c33676SMaxim Ag             {-9064912, 2103172, 25561640, -15125738, -5239824, 9582958,
298172c33676SMaxim Ag              32477045, -9017955, 5002294, -15550259},
298272c33676SMaxim Ag             {-12057553, -11177906, 21115585, -13365155, 8808712, -12030708,
298372c33676SMaxim Ag              16489530, 13378448, -25845716, 12741426},
298472c33676SMaxim Ag             {-5946367, 10645103, -30911586, 15390284, -3286982, -7118677,
298572c33676SMaxim Ag              24306472, 15852464, 28834118, -7646072},
298672c33676SMaxim Ag         },
298772c33676SMaxim Ag         {
298872c33676SMaxim Ag             {-17335748, -9107057, -24531279, 9434953, -8472084, -583362,
298972c33676SMaxim Ag              -13090771, 455841, 20461858, 5491305},
299072c33676SMaxim Ag             {13669248, -16095482, -12481974, -10203039, -14569770, -11893198,
299172c33676SMaxim Ag              -24995986, 11293807, -28588204, -9421832},
299272c33676SMaxim Ag             {28497928, 6272777, -33022994, 14470570, 8906179, -1225630,
299372c33676SMaxim Ag              18504674, -14165166, 29867745, -8795943},
299472c33676SMaxim Ag         },
299572c33676SMaxim Ag         {
299672c33676SMaxim Ag             {-16207023, 13517196, -27799630, -13697798, 24009064, -6373891,
299772c33676SMaxim Ag              -6367600, -13175392, 22853429, -4012011},
299872c33676SMaxim Ag             {24191378, 16712145, -13931797, 15217831, 14542237, 1646131,
299972c33676SMaxim Ag              18603514, -11037887, 12876623, -2112447},
300072c33676SMaxim Ag             {17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753,
300172c33676SMaxim Ag              608397, 16031844, 3723494},
300272c33676SMaxim Ag         },
300372c33676SMaxim Ag         {
300472c33676SMaxim Ag             {-28632773, 12763728, -20446446, 7577504, 33001348, -13017745,
300572c33676SMaxim Ag              17558842, -7872890, 23896954, -4314245},
300672c33676SMaxim Ag             {-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064,
300772c33676SMaxim Ag              7229064, -9919646, -8826859},
300872c33676SMaxim Ag             {28816045, 298879, -28165016, -15920938, 19000928, -1665890,
300972c33676SMaxim Ag              -12680833, -2949325, -18051778, -2082915},
301072c33676SMaxim Ag         },
301172c33676SMaxim Ag         {
301272c33676SMaxim Ag             {16000882, -344896, 3493092, -11447198, -29504595, -13159789,
301372c33676SMaxim Ag              12577740, 16041268, -19715240, 7847707},
301472c33676SMaxim Ag             {10151868, 10572098, 27312476, 7922682, 14825339, 4723128,
301572c33676SMaxim Ag              -32855931, -6519018, -10020567, 3852848},
301672c33676SMaxim Ag             {-11430470, 15697596, -21121557, -4420647, 5386314, 15063598,
301772c33676SMaxim Ag              16514493, -15932110, 29330899, -15076224},
301872c33676SMaxim Ag         },
301972c33676SMaxim Ag     },
302072c33676SMaxim Ag     {
302172c33676SMaxim Ag         {
302272c33676SMaxim Ag             {-25499735, -4378794, -15222908, -6901211, 16615731, 2051784,
302372c33676SMaxim Ag              3303702, 15490, -27548796, 12314391},
302472c33676SMaxim Ag             {15683520, -6003043, 18109120, -9980648, 15337968, -5997823,
302572c33676SMaxim Ag              -16717435, 15921866, 16103996, -3731215},
302672c33676SMaxim Ag             {-23169824, -10781249, 13588192, -1628807, -3798557, -1074929,
302772c33676SMaxim Ag              -19273607, 5402699, -29815713, -9841101},
302872c33676SMaxim Ag         },
302972c33676SMaxim Ag         {
303072c33676SMaxim Ag             {23190676, 2384583, -32714340, 3462154, -29903655, -1529132,
303172c33676SMaxim Ag              -11266856, 8911517, -25205859, 2739713},
303272c33676SMaxim Ag             {21374101, -3554250, -33524649, 9874411, 15377179, 11831242,
303372c33676SMaxim Ag              -33529904, 6134907, 4931255, 11987849},
303472c33676SMaxim Ag             {-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539,
303572c33676SMaxim Ag              13861388, -30076310, 10117930},
303672c33676SMaxim Ag         },
303772c33676SMaxim Ag         {
303872c33676SMaxim Ag             {-29501170, -10744872, -26163768, 13051539, -25625564, 5089643,
303972c33676SMaxim Ag              -6325503, 6704079, 12890019, 15728940},
304072c33676SMaxim Ag             {-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376,
304172c33676SMaxim Ag              -10428139, 12885167, 8311031},
304272c33676SMaxim Ag             {-17516482, 5352194, 10384213, -13811658, 7506451, 13453191,
304372c33676SMaxim Ag              26423267, 4384730, 1888765, -5435404},
304472c33676SMaxim Ag         },
304572c33676SMaxim Ag         {
304672c33676SMaxim Ag             {-25817338, -3107312, -13494599, -3182506, 30896459, -13921729,
304772c33676SMaxim Ag              -32251644, -12707869, -19464434, -3340243},
304872c33676SMaxim Ag             {-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245,
304972c33676SMaxim Ag              14845197, 17151279, -9854116},
305072c33676SMaxim Ag             {-24830458, -12733720, -15165978, 10367250, -29530908, -265356,
305172c33676SMaxim Ag              22825805, -7087279, -16866484, 16176525},
305272c33676SMaxim Ag         },
305372c33676SMaxim Ag         {
305472c33676SMaxim Ag             {-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182,
305572c33676SMaxim Ag              -10363426, -28746253, -10197509},
305672c33676SMaxim Ag             {-10626600, -4486402, -13320562, -5125317, 3432136, -6393229,
305772c33676SMaxim Ag              23632037, -1940610, 32808310, 1099883},
305872c33676SMaxim Ag             {15030977, 5768825, -27451236, -2887299, -6427378, -15361371,
305972c33676SMaxim Ag              -15277896, -6809350, 2051441, -15225865},
306072c33676SMaxim Ag         },
306172c33676SMaxim Ag         {
306272c33676SMaxim Ag             {-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398,
306372c33676SMaxim Ag              -14154188, -22686354, 16633660},
306472c33676SMaxim Ag             {4577086, -16752288, 13249841, -15304328, 19958763, -14537274,
306572c33676SMaxim Ag              18559670, -10759549, 8402478, -9864273},
306672c33676SMaxim Ag             {-28406330, -1051581, -26790155, -907698, -17212414, -11030789,
306772c33676SMaxim Ag              9453451, -14980072, 17983010, 9967138},
306872c33676SMaxim Ag         },
306972c33676SMaxim Ag         {
307072c33676SMaxim Ag             {-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990,
307172c33676SMaxim Ag              7806337, 17507396, 3651560},
307272c33676SMaxim Ag             {-10420457, -4118111, 14584639, 15971087, -15768321, 8861010,
307372c33676SMaxim Ag              26556809, -5574557, -18553322, -11357135},
307472c33676SMaxim Ag             {2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121,
307572c33676SMaxim Ag              8459447, -5605463, -7621941},
307672c33676SMaxim Ag         },
307772c33676SMaxim Ag         {
307872c33676SMaxim Ag             {-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813,
307972c33676SMaxim Ag              -849066, 17258084, -7977739},
308072c33676SMaxim Ag             {18164541, -10595176, -17154882, -1542417, 19237078, -9745295,
308172c33676SMaxim Ag              23357533, -15217008, 26908270, 12150756},
308272c33676SMaxim Ag             {-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168,
308372c33676SMaxim Ag              -5537701, -32302074, 16215819},
308472c33676SMaxim Ag         },
308572c33676SMaxim Ag     },
308672c33676SMaxim Ag     {
308772c33676SMaxim Ag         {
308872c33676SMaxim Ag             {-6898905, 9824394, -12304779, -4401089, -31397141, -6276835,
308972c33676SMaxim Ag              32574489, 12532905, -7503072, -8675347},
309072c33676SMaxim Ag             {-27343522, -16515468, -27151524, -10722951, 946346, 16291093,
309172c33676SMaxim Ag              254968, 7168080, 21676107, -1943028},
309272c33676SMaxim Ag             {21260961, -8424752, -16831886, -11920822, -23677961, 3968121,
309372c33676SMaxim Ag              -3651949, -6215466, -3556191, -7913075},
309472c33676SMaxim Ag         },
309572c33676SMaxim Ag         {
309672c33676SMaxim Ag             {16544754, 13250366, -16804428, 15546242, -4583003, 12757258,
309772c33676SMaxim Ag              -2462308, -8680336, -18907032, -9662799},
309872c33676SMaxim Ag             {-2415239, -15577728, 18312303, 4964443, -15272530, -12653564,
309972c33676SMaxim Ag              26820651, 16690659, 25459437, -4564609},
310072c33676SMaxim Ag             {-25144690, 11425020, 28423002, -11020557, -6144921, -15826224,
310172c33676SMaxim Ag              9142795, -2391602, -6432418, -1644817},
310272c33676SMaxim Ag         },
310372c33676SMaxim Ag         {
310472c33676SMaxim Ag             {-23104652, 6253476, 16964147, -3768872, -25113972, -12296437,
310572c33676SMaxim Ag              -27457225, -16344658, 6335692, 7249989},
310672c33676SMaxim Ag             {-30333227, 13979675, 7503222, -12368314, -11956721, -4621693,
310772c33676SMaxim Ag              -30272269, 2682242, 25993170, -12478523},
310872c33676SMaxim Ag             {4364628, 5930691, 32304656, -10044554, -8054781, 15091131,
310972c33676SMaxim Ag              22857016, -10598955, 31820368, 15075278},
311072c33676SMaxim Ag         },
311172c33676SMaxim Ag         {
311272c33676SMaxim Ag             {31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788,
311372c33676SMaxim Ag              -9650886, -17970238, 12833045},
311472c33676SMaxim Ag             {19073683, 14851414, -24403169, -11860168, 7625278, 11091125,
311572c33676SMaxim Ag              -19619190, 2074449, -9413939, 14905377},
311672c33676SMaxim Ag             {24483667, -11935567, -2518866, -11547418, -1553130, 15355506,
311772c33676SMaxim Ag              -25282080, 9253129, 27628530, -7555480},
311872c33676SMaxim Ag         },
311972c33676SMaxim Ag         {
312072c33676SMaxim Ag             {17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324,
312172c33676SMaxim Ag              -9157582, -14110875, 15297016},
312272c33676SMaxim Ag             {510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417,
312372c33676SMaxim Ag              -11864220, 8683221, 2921426},
312472c33676SMaxim Ag             {18606791, 11874196, 27155355, -5281482, -24031742, 6265446,
312572c33676SMaxim Ag              -25178240, -1278924, 4674690, 13890525},
312672c33676SMaxim Ag         },
312772c33676SMaxim Ag         {
312872c33676SMaxim Ag             {13609624, 13069022, -27372361, -13055908, 24360586, 9592974,
312972c33676SMaxim Ag              14977157, 9835105, 4389687, 288396},
313072c33676SMaxim Ag             {9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062,
313172c33676SMaxim Ag              8317628, 23388070, 16052080},
313272c33676SMaxim Ag             {12720016, 11937594, -31970060, -5028689, 26900120, 8561328,
313372c33676SMaxim Ag              -20155687, -11632979, -14754271, -10812892},
313472c33676SMaxim Ag         },
313572c33676SMaxim Ag         {
313672c33676SMaxim Ag             {15961858, 14150409, 26716931, -665832, -22794328, 13603569,
313772c33676SMaxim Ag              11829573, 7467844, -28822128, 929275},
313872c33676SMaxim Ag             {11038231, -11582396, -27310482, -7316562, -10498527, -16307831,
313972c33676SMaxim Ag              -23479533, -9371869, -21393143, 2465074},
314072c33676SMaxim Ag             {20017163, -4323226, 27915242, 1529148, 12396362, 15675764,
314172c33676SMaxim Ag              13817261, -9658066, 2463391, -4622140},
314272c33676SMaxim Ag         },
314372c33676SMaxim Ag         {
314472c33676SMaxim Ag             {-16358878, -12663911, -12065183, 4996454, -1256422, 1073572,
314572c33676SMaxim Ag              9583558, 12851107, 4003896, 12673717},
314672c33676SMaxim Ag             {-1731589, -15155870, -3262930, 16143082, 19294135, 13385325,
314772c33676SMaxim Ag              14741514, -9103726, 7903886, 2348101},
314872c33676SMaxim Ag             {24536016, -16515207, 12715592, -3862155, 1511293, 10047386,
314972c33676SMaxim Ag              -3842346, -7129159, -28377538, 10048127},
315072c33676SMaxim Ag         },
315172c33676SMaxim Ag     },
315272c33676SMaxim Ag     {
315372c33676SMaxim Ag         {
315472c33676SMaxim Ag             {-12622226, -6204820, 30718825, 2591312, -10617028, 12192840,
315572c33676SMaxim Ag              18873298, -7297090, -32297756, 15221632},
315672c33676SMaxim Ag             {-26478122, -11103864, 11546244, -1852483, 9180880, 7656409,
315772c33676SMaxim Ag              -21343950, 2095755, 29769758, 6593415},
315872c33676SMaxim Ag             {-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345,
315972c33676SMaxim Ag              -6118678, 30958054, 8292160},
316072c33676SMaxim Ag         },
316172c33676SMaxim Ag         {
316272c33676SMaxim Ag             {31429822, -13959116, 29173532, 15632448, 12174511, -2760094,
316372c33676SMaxim Ag              32808831, 3977186, 26143136, -3148876},
316472c33676SMaxim Ag             {22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633,
316572c33676SMaxim Ag              -1674433, -3758243, -2304625},
316672c33676SMaxim Ag             {-15491917, 8012313, -2514730, -12702462, -23965846, -10254029,
316772c33676SMaxim Ag              -1612713, -1535569, -16664475, 8194478},
316872c33676SMaxim Ag         },
316972c33676SMaxim Ag         {
317072c33676SMaxim Ag             {27338066, -7507420, -7414224, 10140405, -19026427, -6589889,
317172c33676SMaxim Ag              27277191, 8855376, 28572286, 3005164},
317272c33676SMaxim Ag             {26287124, 4821776, 25476601, -4145903, -3764513, -15788984,
317372c33676SMaxim Ag              -18008582, 1182479, -26094821, -13079595},
317472c33676SMaxim Ag             {-7171154, 3178080, 23970071, 6201893, -17195577, -4489192,
317572c33676SMaxim Ag              -21876275, -13982627, 32208683, -1198248},
317672c33676SMaxim Ag         },
317772c33676SMaxim Ag         {
317872c33676SMaxim Ag             {-16657702, 2817643, -10286362, 14811298, 6024667, 13349505,
317972c33676SMaxim Ag              -27315504, -10497842, -27672585, -11539858},
318072c33676SMaxim Ag             {15941029, -9405932, -21367050, 8062055, 31876073, -238629,
318172c33676SMaxim Ag              -15278393, -1444429, 15397331, -4130193},
318272c33676SMaxim Ag             {8934485, -13485467, -23286397, -13423241, -32446090, 14047986,
318372c33676SMaxim Ag              31170398, -1441021, -27505566, 15087184},
318472c33676SMaxim Ag         },
318572c33676SMaxim Ag         {
318672c33676SMaxim Ag             {-18357243, -2156491, 24524913, -16677868, 15520427, -6360776,
318772c33676SMaxim Ag              -15502406, 11461896, 16788528, -5868942},
318872c33676SMaxim Ag             {-1947386, 16013773, 21750665, 3714552, -17401782, -16055433,
318972c33676SMaxim Ag              -3770287, -10323320, 31322514, -11615635},
319072c33676SMaxim Ag             {21426655, -5650218, -13648287, -5347537, -28812189, -4920970,
319172c33676SMaxim Ag              -18275391, -14621414, 13040862, -12112948},
319272c33676SMaxim Ag         },
319372c33676SMaxim Ag         {
319472c33676SMaxim Ag             {11293895, 12478086, -27136401, 15083750, -29307421, 14748872,
319572c33676SMaxim Ag              14555558, -13417103, 1613711, 4896935},
319672c33676SMaxim Ag             {-25894883, 15323294, -8489791, -8057900, 25967126, -13425460,
319772c33676SMaxim Ag              2825960, -4897045, -23971776, -11267415},
319872c33676SMaxim Ag             {-15924766, -5229880, -17443532, 6410664, 3622847, 10243618,
319972c33676SMaxim Ag              20615400, 12405433, -23753030, -8436416},
320072c33676SMaxim Ag         },
320172c33676SMaxim Ag         {
320272c33676SMaxim Ag             {-7091295, 12556208, -20191352, 9025187, -17072479, 4333801,
320372c33676SMaxim Ag              4378436, 2432030, 23097949, -566018},
320472c33676SMaxim Ag             {4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264,
320572c33676SMaxim Ag              10103221, -18512313, 2424778},
320672c33676SMaxim Ag             {366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678,
320772c33676SMaxim Ag              1344109, -3642553, 12412659},
320872c33676SMaxim Ag         },
320972c33676SMaxim Ag         {
321072c33676SMaxim Ag             {-24001791, 7690286, 14929416, -168257, -32210835, -13412986,
321172c33676SMaxim Ag              24162697, -15326504, -3141501, 11179385},
321272c33676SMaxim Ag             {18289522, -14724954, 8056945, 16430056, -21729724, 7842514,
321372c33676SMaxim Ag              -6001441, -1486897, -18684645, -11443503},
321472c33676SMaxim Ag             {476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959,
321572c33676SMaxim Ag              13403813, 11052904, 5219329},
321672c33676SMaxim Ag         },
321772c33676SMaxim Ag     },
321872c33676SMaxim Ag     {
321972c33676SMaxim Ag         {
322072c33676SMaxim Ag             {20678546, -8375738, -32671898, 8849123, -5009758, 14574752,
322172c33676SMaxim Ag              31186971, -3973730, 9014762, -8579056},
322272c33676SMaxim Ag             {-13644050, -10350239, -15962508, 5075808, -1514661, -11534600,
322372c33676SMaxim Ag              -33102500, 9160280, 8473550, -3256838},
322472c33676SMaxim Ag             {24900749, 14435722, 17209120, -15292541, -22592275, 9878983,
322572c33676SMaxim Ag              -7689309, -16335821, -24568481, 11788948},
322672c33676SMaxim Ag         },
322772c33676SMaxim Ag         {
322872c33676SMaxim Ag             {-3118155, -11395194, -13802089, 14797441, 9652448, -6845904,
322972c33676SMaxim Ag              -20037437, 10410733, -24568470, -1458691},
323072c33676SMaxim Ag             {-15659161, 16736706, -22467150, 10215878, -9097177, 7563911,
323172c33676SMaxim Ag              11871841, -12505194, -18513325, 8464118},
323272c33676SMaxim Ag             {-23400612, 8348507, -14585951, -861714, -3950205, -6373419,
323372c33676SMaxim Ag              14325289, 8628612, 33313881, -8370517},
323472c33676SMaxim Ag         },
323572c33676SMaxim Ag         {
323672c33676SMaxim Ag             {-20186973, -4967935, 22367356, 5271547, -1097117, -4788838,
323772c33676SMaxim Ag              -24805667, -10236854, -8940735, -5818269},
323872c33676SMaxim Ag             {-6948785, -1795212, -32625683, -16021179, 32635414, -7374245,
323972c33676SMaxim Ag              15989197, -12838188, 28358192, -4253904},
324072c33676SMaxim Ag             {-23561781, -2799059, -32351682, -1661963, -9147719, 10429267,
324172c33676SMaxim Ag              -16637684, 4072016, -5351664, 5596589},
324272c33676SMaxim Ag         },
324372c33676SMaxim Ag         {
324472c33676SMaxim Ag             {-28236598, -3390048, 12312896, 6213178, 3117142, 16078565,
324572c33676SMaxim Ag              29266239, 2557221, 1768301, 15373193},
324672c33676SMaxim Ag             {-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902,
324772c33676SMaxim Ag              -4504991, -24660491, 3442910},
324872c33676SMaxim Ag             {-30210571, 5124043, 14181784, 8197961, 18964734, -11939093,
324972c33676SMaxim Ag              22597931, 7176455, -18585478, 13365930},
325072c33676SMaxim Ag         },
325172c33676SMaxim Ag         {
325272c33676SMaxim Ag             {-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107,
325372c33676SMaxim Ag              -8570186, -9689599, -3031667},
325472c33676SMaxim Ag             {25008904, -10771599, -4305031, -9638010, 16265036, 15721635,
325572c33676SMaxim Ag              683793, -11823784, 15723479, -15163481},
325672c33676SMaxim Ag             {-9660625, 12374379, -27006999, -7026148, -7724114, -12314514,
325772c33676SMaxim Ag              11879682, 5400171, 519526, -1235876},
325872c33676SMaxim Ag         },
325972c33676SMaxim Ag         {
326072c33676SMaxim Ag             {22258397, -16332233, -7869817, 14613016, -22520255, -2950923,
326172c33676SMaxim Ag              -20353881, 7315967, 16648397, 7605640},
326272c33676SMaxim Ag             {-8081308, -8464597, -8223311, 9719710, 19259459, -15348212,
326372c33676SMaxim Ag              23994942, -5281555, -9468848, 4763278},
326472c33676SMaxim Ag             {-21699244, 9220969, -15730624, 1084137, -25476107, -2852390,
326572c33676SMaxim Ag              31088447, -7764523, -11356529, 728112},
326672c33676SMaxim Ag         },
326772c33676SMaxim Ag         {
326872c33676SMaxim Ag             {26047220, -11751471, -6900323, -16521798, 24092068, 9158119,
326972c33676SMaxim Ag              -4273545, -12555558, -29365436, -5498272},
327072c33676SMaxim Ag             {17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007,
327172c33676SMaxim Ag              12327945, 10750447, 10014012},
327272c33676SMaxim Ag             {-10312768, 3936952, 9156313, -8897683, 16498692, -994647,
327372c33676SMaxim Ag              -27481051, -666732, 3424691, 7540221},
327472c33676SMaxim Ag         },
327572c33676SMaxim Ag         {
327672c33676SMaxim Ag             {30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422,
327772c33676SMaxim Ag              -16317219, -9244265, 15258046},
327872c33676SMaxim Ag             {13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406,
327972c33676SMaxim Ag              2711395, 1062915, -5136345},
328072c33676SMaxim Ag             {-19240248, -11254599, -29509029, -7499965, -5835763, 13005411,
328172c33676SMaxim Ag              -6066489, 12194497, 32960380, 1459310},
328272c33676SMaxim Ag         },
328372c33676SMaxim Ag     },
328472c33676SMaxim Ag     {
328572c33676SMaxim Ag         {
328672c33676SMaxim Ag             {19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197,
328772c33676SMaxim Ag              -6101885, 18638003, -11174937},
328872c33676SMaxim Ag             {31395534, 15098109, 26581030, 8030562, -16527914, -5007134,
328972c33676SMaxim Ag              9012486, -7584354, -6643087, -5442636},
329072c33676SMaxim Ag             {-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222,
329172c33676SMaxim Ag              9677543, -32294889, -6456008},
329272c33676SMaxim Ag         },
329372c33676SMaxim Ag         {
329472c33676SMaxim Ag             {-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579,
329572c33676SMaxim Ag              -7839692, -7852844, -8138429},
329672c33676SMaxim Ag             {-15236356, -15433509, 7766470, 746860, 26346930, -10221762,
329772c33676SMaxim Ag              -27333451, 10754588, -9431476, 5203576},
329872c33676SMaxim Ag             {31834314, 14135496, -770007, 5159118, 20917671, -16768096,
329972c33676SMaxim Ag              -7467973, -7337524, 31809243, 7347066},
330072c33676SMaxim Ag         },
330172c33676SMaxim Ag         {
330272c33676SMaxim Ag             {-9606723, -11874240, 20414459, 13033986, 13716524, -11691881,
330372c33676SMaxim Ag              19797970, -12211255, 15192876, -2087490},
330472c33676SMaxim Ag             {-12663563, -2181719, 1168162, -3804809, 26747877, -14138091,
330572c33676SMaxim Ag              10609330, 12694420, 33473243, -13382104},
330672c33676SMaxim Ag             {33184999, 11180355, 15832085, -11385430, -1633671, 225884,
330772c33676SMaxim Ag              15089336, -11023903, -6135662, 14480053},
330872c33676SMaxim Ag         },
330972c33676SMaxim Ag         {
331072c33676SMaxim Ag             {31308717, -5619998, 31030840, -1897099, 15674547, -6582883,
331172c33676SMaxim Ag              5496208, 13685227, 27595050, 8737275},
331272c33676SMaxim Ag             {-20318852, -15150239, 10933843, -16178022, 8335352, -7546022,
331372c33676SMaxim Ag              -31008351, -12610604, 26498114, 66511},
331472c33676SMaxim Ag             {22644454, -8761729, -16671776, 4884562, -3105614, -13559366,
331572c33676SMaxim Ag              30540766, -4286747, -13327787, -7515095},
331672c33676SMaxim Ag         },
331772c33676SMaxim Ag         {
331872c33676SMaxim Ag             {-28017847, 9834845, 18617207, -2681312, -3401956, -13307506,
331972c33676SMaxim Ag              8205540, 13585437, -17127465, 15115439},
332072c33676SMaxim Ag             {23711543, -672915, 31206561, -8362711, 6164647, -9709987,
332172c33676SMaxim Ag              -33535882, -1426096, 8236921, 16492939},
332272c33676SMaxim Ag             {-23910559, -13515526, -26299483, -4503841, 25005590, -7687270,
332372c33676SMaxim Ag              19574902, 10071562, 6708380, -6222424},
332472c33676SMaxim Ag         },
332572c33676SMaxim Ag         {
332672c33676SMaxim Ag             {2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017,
332772c33676SMaxim Ag              9328700, 29955601, -11678310},
332872c33676SMaxim Ag             {3096359, 9271816, -21620864, -15521844, -14847996, -7592937,
332972c33676SMaxim Ag              -25892142, -12635595, -9917575, 6216608},
333072c33676SMaxim Ag             {-32615849, 338663, -25195611, 2510422, -29213566, -13820213,
333172c33676SMaxim Ag              24822830, -6146567, -26767480, 7525079},
333272c33676SMaxim Ag         },
333372c33676SMaxim Ag         {
333472c33676SMaxim Ag             {-23066649, -13985623, 16133487, -7896178, -3389565, 778788,
333572c33676SMaxim Ag              -910336, -2782495, -19386633, 11994101},
333672c33676SMaxim Ag             {21691500, -13624626, -641331, -14367021, 3285881, -3483596,
333772c33676SMaxim Ag              -25064666, 9718258, -7477437, 13381418},
333872c33676SMaxim Ag             {18445390, -4202236, 14979846, 11622458, -1727110, -3582980,
333972c33676SMaxim Ag              23111648, -6375247, 28535282, 15779576},
334072c33676SMaxim Ag         },
334172c33676SMaxim Ag         {
334272c33676SMaxim Ag             {30098053, 3089662, -9234387, 16662135, -21306940, 11308411,
334372c33676SMaxim Ag              -14068454, 12021730, 9955285, -16303356},
334472c33676SMaxim Ag             {9734894, -14576830, -7473633, -9138735, 2060392, 11313496,
334572c33676SMaxim Ag              -18426029, 9924399, 20194861, 13380996},
334672c33676SMaxim Ag             {-26378102, -7965207, -22167821, 15789297, -18055342, -6168792,
334772c33676SMaxim Ag              -1984914, 15707771, 26342023, 10146099},
334872c33676SMaxim Ag         },
334972c33676SMaxim Ag     },
335072c33676SMaxim Ag     {
335172c33676SMaxim Ag         {
335272c33676SMaxim Ag             {-26016874, -219943, 21339191, -41388, 19745256, -2878700,
335372c33676SMaxim Ag              -29637280, 2227040, 21612326, -545728},
335472c33676SMaxim Ag             {-13077387, 1184228, 23562814, -5970442, -20351244, -6348714,
335572c33676SMaxim Ag              25764461, 12243797, -20856566, 11649658},
335672c33676SMaxim Ag             {-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944,
335772c33676SMaxim Ag              6114064, 33514190, 2333242},
335872c33676SMaxim Ag         },
335972c33676SMaxim Ag         {
336072c33676SMaxim Ag             {-21433588, -12421821, 8119782, 7219913, -21830522, -9016134,
336172c33676SMaxim Ag              -6679750, -12670638, 24350578, -13450001},
336272c33676SMaxim Ag             {-4116307, -11271533, -23886186, 4843615, -30088339, 690623,
336372c33676SMaxim Ag              -31536088, -10406836, 8317860, 12352766},
336472c33676SMaxim Ag             {18200138, -14475911, -33087759, -2696619, -23702521, -9102511,
336572c33676SMaxim Ag              -23552096, -2287550, 20712163, 6719373},
336672c33676SMaxim Ag         },
336772c33676SMaxim Ag         {
336872c33676SMaxim Ag             {26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530,
336972c33676SMaxim Ag              -3763210, 26224235, -3297458},
337072c33676SMaxim Ag             {-17168938, -14854097, -3395676, -16369877, -19954045, 14050420,
337172c33676SMaxim Ag              21728352, 9493610, 18620611, -16428628},
337272c33676SMaxim Ag             {-13323321, 13325349, 11432106, 5964811, 18609221, 6062965,
337372c33676SMaxim Ag              -5269471, -9725556, -30701573, -16479657},
337472c33676SMaxim Ag         },
337572c33676SMaxim Ag         {
337672c33676SMaxim Ag             {-23860538, -11233159, 26961357, 1640861, -32413112, -16737940,
337772c33676SMaxim Ag              12248509, -5240639, 13735342, 1934062},
337872c33676SMaxim Ag             {25089769, 6742589, 17081145, -13406266, 21909293, -16067981,
337972c33676SMaxim Ag              -15136294, -3765346, -21277997, 5473616},
338072c33676SMaxim Ag             {31883677, -7961101, 1083432, -11572403, 22828471, 13290673,
338172c33676SMaxim Ag              -7125085, 12469656, 29111212, -5451014},
338272c33676SMaxim Ag         },
338372c33676SMaxim Ag         {
338472c33676SMaxim Ag             {24244947, -15050407, -26262976, 2791540, -14997599, 16666678,
338572c33676SMaxim Ag              24367466, 6388839, -10295587, 452383},
338672c33676SMaxim Ag             {-25640782, -3417841, 5217916, 16224624, 19987036, -4082269,
338772c33676SMaxim Ag              -24236251, -5915248, 15766062, 8407814},
338872c33676SMaxim Ag             {-20406999, 13990231, 15495425, 16395525, 5377168, 15166495,
338972c33676SMaxim Ag              -8917023, -4388953, -8067909, 2276718},
339072c33676SMaxim Ag         },
339172c33676SMaxim Ag         {
339272c33676SMaxim Ag             {30157918, 12924066, -17712050, 9245753, 19895028, 3368142,
339372c33676SMaxim Ag              -23827587, 5096219, 22740376, -7303417},
339472c33676SMaxim Ag             {2041139, -14256350, 7783687, 13876377, -25946985, -13352459,
339572c33676SMaxim Ag              24051124, 13742383, -15637599, 13295222},
339672c33676SMaxim Ag             {33338237, -8505733, 12532113, 7977527, 9106186, -1715251,
339772c33676SMaxim Ag              -17720195, -4612972, -4451357, -14669444},
339872c33676SMaxim Ag         },
339972c33676SMaxim Ag         {
340072c33676SMaxim Ag             {-20045281, 5454097, -14346548, 6447146, 28862071, 1883651,
340172c33676SMaxim Ag              -2469266, -4141880, 7770569, 9620597},
340272c33676SMaxim Ag             {23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528,
340372c33676SMaxim Ag              -1694323, -33502340, -14767970},
340472c33676SMaxim Ag             {1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801,
340572c33676SMaxim Ag              1220118, 30494170, -11440799},
340672c33676SMaxim Ag         },
340772c33676SMaxim Ag         {
340872c33676SMaxim Ag             {-5037580, -13028295, -2970559, -3061767, 15640974, -6701666,
340972c33676SMaxim Ag              -26739026, 926050, -1684339, -13333647},
341072c33676SMaxim Ag             {13908495, -3549272, 30919928, -6273825, -21521863, 7989039,
341172c33676SMaxim Ag              9021034, 9078865, 3353509, 4033511},
341272c33676SMaxim Ag             {-29663431, -15113610, 32259991, -344482, 24295849, -12912123,
341372c33676SMaxim Ag              23161163, 8839127, 27485041, 7356032},
341472c33676SMaxim Ag         },
341572c33676SMaxim Ag     },
341672c33676SMaxim Ag     {
341772c33676SMaxim Ag         {
341872c33676SMaxim Ag             {9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142,
341972c33676SMaxim Ag              2625015, 28431036, -16771834},
342072c33676SMaxim Ag             {-23839233, -8311415, -25945511, 7480958, -17681669, -8354183,
342172c33676SMaxim Ag              -22545972, 14150565, 15970762, 4099461},
342272c33676SMaxim Ag             {29262576, 16756590, 26350592, -8793563, 8529671, -11208050,
342372c33676SMaxim Ag              13617293, -9937143, 11465739, 8317062},
342472c33676SMaxim Ag         },
342572c33676SMaxim Ag         {
342672c33676SMaxim Ag             {-25493081, -6962928, 32500200, -9419051, -23038724, -2302222,
342772c33676SMaxim Ag              14898637, 3848455, 20969334, -5157516},
342872c33676SMaxim Ag             {-20384450, -14347713, -18336405, 13884722, -33039454, 2842114,
342972c33676SMaxim Ag              -21610826, -3649888, 11177095, 14989547},
343072c33676SMaxim Ag             {-24496721, -11716016, 16959896, 2278463, 12066309, 10137771,
343172c33676SMaxim Ag              13515641, 2581286, -28487508, 9930240},
343272c33676SMaxim Ag         },
343372c33676SMaxim Ag         {
343472c33676SMaxim Ag             {-17751622, -2097826, 16544300, -13009300, -15914807, -14949081,
343572c33676SMaxim Ag              18345767, -13403753, 16291481, -5314038},
343672c33676SMaxim Ag             {-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774,
343772c33676SMaxim Ag              6957617, 4368891, 9788741},
343872c33676SMaxim Ag             {16660756, 7281060, -10830758, 12911820, 20108584, -8101676,
343972c33676SMaxim Ag              -21722536, -8613148, 16250552, -11111103},
344072c33676SMaxim Ag         },
344172c33676SMaxim Ag         {
344272c33676SMaxim Ag             {-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584,
344372c33676SMaxim Ag              10604807, -30190403, 4782747},
344472c33676SMaxim Ag             {-1354539, 14736941, -7367442, -13292886, 7710542, -14155590,
344572c33676SMaxim Ag              -9981571, 4383045, 22546403, 437323},
344672c33676SMaxim Ag             {31665577, -12180464, -16186830, 1491339, -18368625, 3294682,
344772c33676SMaxim Ag              27343084, 2786261, -30633590, -14097016},
344872c33676SMaxim Ag         },
344972c33676SMaxim Ag         {
345072c33676SMaxim Ag             {-14467279, -683715, -33374107, 7448552, 19294360, 14334329,
345172c33676SMaxim Ag              -19690631, 2355319, -19284671, -6114373},
345272c33676SMaxim Ag             {15121312, -15796162, 6377020, -6031361, -10798111, -12957845,
345372c33676SMaxim Ag              18952177, 15496498, -29380133, 11754228},
345472c33676SMaxim Ag             {-2637277, -13483075, 8488727, -14303896, 12728761, -1622493,
345572c33676SMaxim Ag              7141596, 11724556, 22761615, -10134141},
345672c33676SMaxim Ag         },
345772c33676SMaxim Ag         {
345872c33676SMaxim Ag             {16918416, 11729663, -18083579, 3022987, -31015732, -13339659,
345972c33676SMaxim Ag              -28741185, -12227393, 32851222, 11717399},
346072c33676SMaxim Ag             {11166634, 7338049, -6722523, 4531520, -29468672, -7302055,
346172c33676SMaxim Ag              31474879, 3483633, -1193175, -4030831},
346272c33676SMaxim Ag             {-185635, 9921305, 31456609, -13536438, -12013818, 13348923,
346372c33676SMaxim Ag              33142652, 6546660, -19985279, -3948376},
346472c33676SMaxim Ag         },
346572c33676SMaxim Ag         {
346672c33676SMaxim Ag             {-32460596, 11266712, -11197107, -7899103, 31703694, 3855903,
346772c33676SMaxim Ag              -8537131, -12833048, -30772034, -15486313},
346872c33676SMaxim Ag             {-18006477, 12709068, 3991746, -6479188, -21491523, -10550425,
346972c33676SMaxim Ag              -31135347, -16049879, 10928917, 3011958},
347072c33676SMaxim Ag             {-6957757, -15594337, 31696059, 334240, 29576716, 14796075,
347172c33676SMaxim Ag              -30831056, -12805180, 18008031, 10258577},
347272c33676SMaxim Ag         },
347372c33676SMaxim Ag         {
347472c33676SMaxim Ag             {-22448644, 15655569, 7018479, -4410003, -30314266, -1201591,
347572c33676SMaxim Ag              -1853465, 1367120, 25127874, 6671743},
347672c33676SMaxim Ag             {29701166, -14373934, -10878120, 9279288, -17568, 13127210,
347772c33676SMaxim Ag              21382910, 11042292, 25838796, 4642684},
347872c33676SMaxim Ag             {-20430234, 14955537, -24126347, 8124619, -5369288, -5990470,
347972c33676SMaxim Ag              30468147, -13900640, 18423289, 4177476},
348072c33676SMaxim Ag         },
348172c33676SMaxim Ag     },
348272c33676SMaxim Ag };
348372c33676SMaxim Ag 
negative(signed char b)348472c33676SMaxim Ag static uint8_t negative(signed char b) {
348572c33676SMaxim Ag   uint32_t x = b;
348672c33676SMaxim Ag   x >>= 31; /* 1: yes; 0: no */
348772c33676SMaxim Ag   return x;
348872c33676SMaxim Ag }
348972c33676SMaxim Ag 
table_select(ge_precomp * t,int pos,signed char b)349072c33676SMaxim Ag static void table_select(ge_precomp *t, int pos, signed char b) {
349172c33676SMaxim Ag   ge_precomp minust;
349272c33676SMaxim Ag   uint8_t bnegative = negative(b);
349372c33676SMaxim Ag   uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);
349472c33676SMaxim Ag 
349572c33676SMaxim Ag   ge_precomp_0(t);
349672c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][0], equal(babs, 1));
349772c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][1], equal(babs, 2));
349872c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][2], equal(babs, 3));
349972c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][3], equal(babs, 4));
350072c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][4], equal(babs, 5));
350172c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][5], equal(babs, 6));
350272c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][6], equal(babs, 7));
350372c33676SMaxim Ag   cmov(t, &k25519Precomp[pos][7], equal(babs, 8));
350472c33676SMaxim Ag   fe_copy(minust.yplusx, t->yminusx);
350572c33676SMaxim Ag   fe_copy(minust.yminusx, t->yplusx);
350672c33676SMaxim Ag   fe_neg(minust.xy2d, t->xy2d);
350772c33676SMaxim Ag   cmov(t, &minust, bnegative);
350872c33676SMaxim Ag }
350972c33676SMaxim Ag 
351072c33676SMaxim Ag /* h = a * B
351172c33676SMaxim Ag  * where a = a[0]+256*a[1]+...+256^31 a[31]
351272c33676SMaxim Ag  * B is the Ed25519 base point (x,4/5) with x positive.
351372c33676SMaxim Ag  *
351472c33676SMaxim Ag  * Preconditions:
351572c33676SMaxim Ag  *   a[31] <= 127 */
x25519_ge_scalarmult_base(ge_p3 * h,const uint8_t a[32])3516*de0e0e4dSAntonio Huete Jimenez void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
351772c33676SMaxim Ag   signed char e[64];
351872c33676SMaxim Ag   signed char carry;
351972c33676SMaxim Ag   ge_p1p1 r;
352072c33676SMaxim Ag   ge_p2 s;
352172c33676SMaxim Ag   ge_precomp t;
352272c33676SMaxim Ag   int i;
352372c33676SMaxim Ag 
352472c33676SMaxim Ag   for (i = 0; i < 32; ++i) {
352572c33676SMaxim Ag     e[2 * i + 0] = (a[i] >> 0) & 15;
352672c33676SMaxim Ag     e[2 * i + 1] = (a[i] >> 4) & 15;
352772c33676SMaxim Ag   }
352872c33676SMaxim Ag   /* each e[i] is between 0 and 15 */
352972c33676SMaxim Ag   /* e[63] is between 0 and 7 */
353072c33676SMaxim Ag 
353172c33676SMaxim Ag   carry = 0;
353272c33676SMaxim Ag   for (i = 0; i < 63; ++i) {
353372c33676SMaxim Ag     e[i] += carry;
353472c33676SMaxim Ag     carry = e[i] + 8;
353572c33676SMaxim Ag     carry >>= 4;
353672c33676SMaxim Ag     e[i] -= carry << 4;
353772c33676SMaxim Ag   }
353872c33676SMaxim Ag   e[63] += carry;
353972c33676SMaxim Ag   /* each e[i] is between -8 and 8 */
354072c33676SMaxim Ag 
354172c33676SMaxim Ag   ge_p3_0(h);
354272c33676SMaxim Ag   for (i = 1; i < 64; i += 2) {
354372c33676SMaxim Ag     table_select(&t, i / 2, e[i]);
354472c33676SMaxim Ag     ge_madd(&r, h, &t);
354572c33676SMaxim Ag     x25519_ge_p1p1_to_p3(h, &r);
354672c33676SMaxim Ag   }
354772c33676SMaxim Ag 
354872c33676SMaxim Ag   ge_p3_dbl(&r, h);
354972c33676SMaxim Ag   x25519_ge_p1p1_to_p2(&s, &r);
355072c33676SMaxim Ag   ge_p2_dbl(&r, &s);
355172c33676SMaxim Ag   x25519_ge_p1p1_to_p2(&s, &r);
355272c33676SMaxim Ag   ge_p2_dbl(&r, &s);
355372c33676SMaxim Ag   x25519_ge_p1p1_to_p2(&s, &r);
355472c33676SMaxim Ag   ge_p2_dbl(&r, &s);
355572c33676SMaxim Ag   x25519_ge_p1p1_to_p3(h, &r);
355672c33676SMaxim Ag 
355772c33676SMaxim Ag   for (i = 0; i < 64; i += 2) {
355872c33676SMaxim Ag     table_select(&t, i / 2, e[i]);
355972c33676SMaxim Ag     ge_madd(&r, h, &t);
356072c33676SMaxim Ag     x25519_ge_p1p1_to_p3(h, &r);
356172c33676SMaxim Ag   }
356272c33676SMaxim Ag }
356372c33676SMaxim Ag 
356472c33676SMaxim Ag #endif
356572c33676SMaxim Ag 
cmov_cached(ge_cached * t,ge_cached * u,uint8_t b)356672c33676SMaxim Ag static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) {
356772c33676SMaxim Ag   fe_cmov(t->YplusX, u->YplusX, b);
356872c33676SMaxim Ag   fe_cmov(t->YminusX, u->YminusX, b);
356972c33676SMaxim Ag   fe_cmov(t->Z, u->Z, b);
357072c33676SMaxim Ag   fe_cmov(t->T2d, u->T2d, b);
357172c33676SMaxim Ag }
357272c33676SMaxim Ag 
357372c33676SMaxim Ag /* r = scalar * A.
357472c33676SMaxim Ag  * where a = a[0]+256*a[1]+...+256^31 a[31]. */
x25519_ge_scalarmult(ge_p2 * r,const uint8_t * scalar,const ge_p3 * A)357572c33676SMaxim Ag void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A) {
357672c33676SMaxim Ag   ge_p2 Ai_p2[8];
357772c33676SMaxim Ag   ge_cached Ai[16];
357872c33676SMaxim Ag   ge_p1p1 t;
357972c33676SMaxim Ag 
358072c33676SMaxim Ag   ge_cached_0(&Ai[0]);
358172c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[1], A);
358272c33676SMaxim Ag   ge_p3_to_p2(&Ai_p2[1], A);
358372c33676SMaxim Ag 
358472c33676SMaxim Ag   unsigned i;
358572c33676SMaxim Ag   for (i = 2; i < 16; i += 2) {
358672c33676SMaxim Ag     ge_p2_dbl(&t, &Ai_p2[i / 2]);
358772c33676SMaxim Ag     ge_p1p1_to_cached(&Ai[i], &t);
358872c33676SMaxim Ag     if (i < 8) {
358972c33676SMaxim Ag       x25519_ge_p1p1_to_p2(&Ai_p2[i], &t);
359072c33676SMaxim Ag     }
359172c33676SMaxim Ag     x25519_ge_add(&t, A, &Ai[i]);
359272c33676SMaxim Ag     ge_p1p1_to_cached(&Ai[i + 1], &t);
359372c33676SMaxim Ag     if (i < 7) {
359472c33676SMaxim Ag       x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t);
359572c33676SMaxim Ag     }
359672c33676SMaxim Ag   }
359772c33676SMaxim Ag 
359872c33676SMaxim Ag   ge_p2_0(r);
359972c33676SMaxim Ag   ge_p3 u;
360072c33676SMaxim Ag 
360172c33676SMaxim Ag   for (i = 0; i < 256; i += 4) {
360272c33676SMaxim Ag     ge_p2_dbl(&t, r);
360372c33676SMaxim Ag     x25519_ge_p1p1_to_p2(r, &t);
360472c33676SMaxim Ag     ge_p2_dbl(&t, r);
360572c33676SMaxim Ag     x25519_ge_p1p1_to_p2(r, &t);
360672c33676SMaxim Ag     ge_p2_dbl(&t, r);
360772c33676SMaxim Ag     x25519_ge_p1p1_to_p2(r, &t);
360872c33676SMaxim Ag     ge_p2_dbl(&t, r);
360972c33676SMaxim Ag     x25519_ge_p1p1_to_p3(&u, &t);
361072c33676SMaxim Ag 
361172c33676SMaxim Ag     uint8_t index = scalar[31 - i/8];
361272c33676SMaxim Ag     index >>= 4 - (i & 4);
361372c33676SMaxim Ag     index &= 0xf;
361472c33676SMaxim Ag 
361572c33676SMaxim Ag     unsigned j;
361672c33676SMaxim Ag     ge_cached selected;
361772c33676SMaxim Ag     ge_cached_0(&selected);
361872c33676SMaxim Ag     for (j = 0; j < 16; j++) {
361972c33676SMaxim Ag       cmov_cached(&selected, &Ai[j], equal(j, index));
362072c33676SMaxim Ag     }
362172c33676SMaxim Ag 
362272c33676SMaxim Ag     x25519_ge_add(&t, &u, &selected);
362372c33676SMaxim Ag     x25519_ge_p1p1_to_p2(r, &t);
362472c33676SMaxim Ag   }
362572c33676SMaxim Ag }
362672c33676SMaxim Ag 
362772c33676SMaxim Ag #ifdef ED25519
slide(signed char * r,const uint8_t * a)362872c33676SMaxim Ag static void slide(signed char *r, const uint8_t *a) {
362972c33676SMaxim Ag   int i;
363072c33676SMaxim Ag   int b;
363172c33676SMaxim Ag   int k;
363272c33676SMaxim Ag 
363372c33676SMaxim Ag   for (i = 0; i < 256; ++i) {
363472c33676SMaxim Ag     r[i] = 1 & (a[i >> 3] >> (i & 7));
363572c33676SMaxim Ag   }
363672c33676SMaxim Ag 
363772c33676SMaxim Ag   for (i = 0; i < 256; ++i) {
363872c33676SMaxim Ag     if (r[i]) {
363972c33676SMaxim Ag       for (b = 1; b <= 6 && i + b < 256; ++b) {
364072c33676SMaxim Ag         if (r[i + b]) {
364172c33676SMaxim Ag           if (r[i] + (r[i + b] << b) <= 15) {
364272c33676SMaxim Ag             r[i] += r[i + b] << b;
364372c33676SMaxim Ag             r[i + b] = 0;
364472c33676SMaxim Ag           } else if (r[i] - (r[i + b] << b) >= -15) {
364572c33676SMaxim Ag             r[i] -= r[i + b] << b;
364672c33676SMaxim Ag             for (k = i + b; k < 256; ++k) {
364772c33676SMaxim Ag               if (!r[k]) {
364872c33676SMaxim Ag                 r[k] = 1;
364972c33676SMaxim Ag                 break;
365072c33676SMaxim Ag               }
365172c33676SMaxim Ag               r[k] = 0;
365272c33676SMaxim Ag             }
365372c33676SMaxim Ag           } else {
365472c33676SMaxim Ag             break;
365572c33676SMaxim Ag           }
365672c33676SMaxim Ag         }
365772c33676SMaxim Ag       }
365872c33676SMaxim Ag     }
365972c33676SMaxim Ag   }
366072c33676SMaxim Ag }
366172c33676SMaxim Ag 
366272c33676SMaxim Ag static const ge_precomp Bi[8] = {
366372c33676SMaxim Ag     {
366472c33676SMaxim Ag         {25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626,
366572c33676SMaxim Ag          -11754271, -6079156, 2047605},
366672c33676SMaxim Ag         {-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692,
366772c33676SMaxim Ag          5043384, 19500929, -15469378},
366872c33676SMaxim Ag         {-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919,
366972c33676SMaxim Ag          11864899, -24514362, -4438546},
367072c33676SMaxim Ag     },
367172c33676SMaxim Ag     {
367272c33676SMaxim Ag         {15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600,
367372c33676SMaxim Ag          -14772189, 28944400, -1550024},
367472c33676SMaxim Ag         {16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577,
367572c33676SMaxim Ag          -11775962, 7689662, 11199574},
367672c33676SMaxim Ag         {30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774,
367772c33676SMaxim Ag          10017326, -17749093, -9920357},
367872c33676SMaxim Ag     },
367972c33676SMaxim Ag     {
368072c33676SMaxim Ag         {10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885,
368172c33676SMaxim Ag          14515107, -15438304, 10819380},
368272c33676SMaxim Ag         {4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668,
368372c33676SMaxim Ag          12483688, -12668491, 5581306},
368472c33676SMaxim Ag         {19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350,
368572c33676SMaxim Ag          13850243, -23678021, -15815942},
368672c33676SMaxim Ag     },
368772c33676SMaxim Ag     {
368872c33676SMaxim Ag         {5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852,
368972c33676SMaxim Ag          5230134, -23952439, -15175766},
369072c33676SMaxim Ag         {-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025,
369172c33676SMaxim Ag          16520125, 30598449, 7715701},
369272c33676SMaxim Ag         {28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660,
369372c33676SMaxim Ag          1370708, 29794553, -1409300},
369472c33676SMaxim Ag     },
369572c33676SMaxim Ag     {
369672c33676SMaxim Ag         {-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211,
369772c33676SMaxim Ag          -1361450, -13062696, 13821877},
369872c33676SMaxim Ag         {-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028,
369972c33676SMaxim Ag          -7212327, 18853322, -14220951},
370072c33676SMaxim Ag         {4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358,
370172c33676SMaxim Ag          -10431137, 2207753, -3209784},
370272c33676SMaxim Ag     },
370372c33676SMaxim Ag     {
370472c33676SMaxim Ag         {-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364,
370572c33676SMaxim Ag          -663000, -31111463, -16132436},
370672c33676SMaxim Ag         {25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789,
370772c33676SMaxim Ag          15725684, 171356, 6466918},
370872c33676SMaxim Ag         {23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339,
370972c33676SMaxim Ag          -14088058, -30714912, 16193877},
371072c33676SMaxim Ag     },
371172c33676SMaxim Ag     {
371272c33676SMaxim Ag         {-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398,
371372c33676SMaxim Ag          4729455, -18074513, 9256800},
371472c33676SMaxim Ag         {-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405,
371572c33676SMaxim Ag          9761698, -19827198, 630305},
371672c33676SMaxim Ag         {-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551,
371772c33676SMaxim Ag          -15960994, -2449256, -14291300},
371872c33676SMaxim Ag     },
371972c33676SMaxim Ag     {
372072c33676SMaxim Ag         {-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575,
372172c33676SMaxim Ag          15033784, 25105118, -7894876},
372272c33676SMaxim Ag         {-24326370, 15950226, -31801215, -14592823, -11662737, -5090925,
372372c33676SMaxim Ag          1573892, -2625887, 2198790, -15804619},
372472c33676SMaxim Ag         {-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022,
372572c33676SMaxim Ag          -16236442, -32461234, -12290683},
372672c33676SMaxim Ag     },
372772c33676SMaxim Ag };
372872c33676SMaxim Ag 
372972c33676SMaxim Ag /* r = a * A + b * B
373072c33676SMaxim Ag  * where a = a[0]+256*a[1]+...+256^31 a[31].
373172c33676SMaxim Ag  * and b = b[0]+256*b[1]+...+256^31 b[31].
373272c33676SMaxim Ag  * B is the Ed25519 base point (x,4/5) with x positive. */
373372c33676SMaxim Ag static void
ge_double_scalarmult_vartime(ge_p2 * r,const uint8_t * a,const ge_p3 * A,const uint8_t * b)373472c33676SMaxim Ag ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
373572c33676SMaxim Ag     const ge_p3 *A, const uint8_t *b) {
373672c33676SMaxim Ag   signed char aslide[256];
373772c33676SMaxim Ag   signed char bslide[256];
373872c33676SMaxim Ag   ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
373972c33676SMaxim Ag   ge_p1p1 t;
374072c33676SMaxim Ag   ge_p3 u;
374172c33676SMaxim Ag   ge_p3 A2;
374272c33676SMaxim Ag   int i;
374372c33676SMaxim Ag 
374472c33676SMaxim Ag   slide(aslide, a);
374572c33676SMaxim Ag   slide(bslide, b);
374672c33676SMaxim Ag 
374772c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[0], A);
374872c33676SMaxim Ag   ge_p3_dbl(&t, A);
374972c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&A2, &t);
375072c33676SMaxim Ag   x25519_ge_add(&t, &A2, &Ai[0]);
375172c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&u, &t);
375272c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[1], &u);
375372c33676SMaxim Ag   x25519_ge_add(&t, &A2, &Ai[1]);
375472c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&u, &t);
375572c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[2], &u);
375672c33676SMaxim Ag   x25519_ge_add(&t, &A2, &Ai[2]);
375772c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&u, &t);
375872c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[3], &u);
375972c33676SMaxim Ag   x25519_ge_add(&t, &A2, &Ai[3]);
376072c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&u, &t);
376172c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[4], &u);
376272c33676SMaxim Ag   x25519_ge_add(&t, &A2, &Ai[4]);
376372c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&u, &t);
376472c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[5], &u);
376572c33676SMaxim Ag   x25519_ge_add(&t, &A2, &Ai[5]);
376672c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&u, &t);
376772c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[6], &u);
376872c33676SMaxim Ag   x25519_ge_add(&t, &A2, &Ai[6]);
376972c33676SMaxim Ag   x25519_ge_p1p1_to_p3(&u, &t);
377072c33676SMaxim Ag   x25519_ge_p3_to_cached(&Ai[7], &u);
377172c33676SMaxim Ag 
377272c33676SMaxim Ag   ge_p2_0(r);
377372c33676SMaxim Ag 
377472c33676SMaxim Ag   for (i = 255; i >= 0; --i) {
377572c33676SMaxim Ag     if (aslide[i] || bslide[i]) {
377672c33676SMaxim Ag       break;
377772c33676SMaxim Ag     }
377872c33676SMaxim Ag   }
377972c33676SMaxim Ag 
378072c33676SMaxim Ag   for (; i >= 0; --i) {
378172c33676SMaxim Ag     ge_p2_dbl(&t, r);
378272c33676SMaxim Ag 
378372c33676SMaxim Ag     if (aslide[i] > 0) {
378472c33676SMaxim Ag       x25519_ge_p1p1_to_p3(&u, &t);
378572c33676SMaxim Ag       x25519_ge_add(&t, &u, &Ai[aslide[i] / 2]);
378672c33676SMaxim Ag     } else if (aslide[i] < 0) {
378772c33676SMaxim Ag       x25519_ge_p1p1_to_p3(&u, &t);
378872c33676SMaxim Ag       x25519_ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
378972c33676SMaxim Ag     }
379072c33676SMaxim Ag 
379172c33676SMaxim Ag     if (bslide[i] > 0) {
379272c33676SMaxim Ag       x25519_ge_p1p1_to_p3(&u, &t);
379372c33676SMaxim Ag       ge_madd(&t, &u, &Bi[bslide[i] / 2]);
379472c33676SMaxim Ag     } else if (bslide[i] < 0) {
379572c33676SMaxim Ag       x25519_ge_p1p1_to_p3(&u, &t);
379672c33676SMaxim Ag       ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
379772c33676SMaxim Ag     }
379872c33676SMaxim Ag 
379972c33676SMaxim Ag     x25519_ge_p1p1_to_p2(r, &t);
380072c33676SMaxim Ag   }
380172c33676SMaxim Ag }
380272c33676SMaxim Ag #endif
380372c33676SMaxim Ag 
380472c33676SMaxim Ag /* The set of scalars is \Z/l
380572c33676SMaxim Ag  * where l = 2^252 + 27742317777372353535851937790883648493. */
380672c33676SMaxim Ag 
380772c33676SMaxim Ag /* Input:
380872c33676SMaxim Ag  *   s[0]+256*s[1]+...+256^63*s[63] = s
380972c33676SMaxim Ag  *
381072c33676SMaxim Ag  * Output:
381172c33676SMaxim Ag  *   s[0]+256*s[1]+...+256^31*s[31] = s mod l
381272c33676SMaxim Ag  *   where l = 2^252 + 27742317777372353535851937790883648493.
381372c33676SMaxim Ag  *   Overwrites s in place. */
381472c33676SMaxim Ag void
x25519_sc_reduce(uint8_t * s)381572c33676SMaxim Ag x25519_sc_reduce(uint8_t *s) {
381672c33676SMaxim Ag   int64_t s0 = 2097151 & load_3(s);
381772c33676SMaxim Ag   int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
381872c33676SMaxim Ag   int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
381972c33676SMaxim Ag   int64_t s3 = 2097151 & (load_4(s + 7) >> 7);
382072c33676SMaxim Ag   int64_t s4 = 2097151 & (load_4(s + 10) >> 4);
382172c33676SMaxim Ag   int64_t s5 = 2097151 & (load_3(s + 13) >> 1);
382272c33676SMaxim Ag   int64_t s6 = 2097151 & (load_4(s + 15) >> 6);
382372c33676SMaxim Ag   int64_t s7 = 2097151 & (load_3(s + 18) >> 3);
382472c33676SMaxim Ag   int64_t s8 = 2097151 & load_3(s + 21);
382572c33676SMaxim Ag   int64_t s9 = 2097151 & (load_4(s + 23) >> 5);
382672c33676SMaxim Ag   int64_t s10 = 2097151 & (load_3(s + 26) >> 2);
382772c33676SMaxim Ag   int64_t s11 = 2097151 & (load_4(s + 28) >> 7);
382872c33676SMaxim Ag   int64_t s12 = 2097151 & (load_4(s + 31) >> 4);
382972c33676SMaxim Ag   int64_t s13 = 2097151 & (load_3(s + 34) >> 1);
383072c33676SMaxim Ag   int64_t s14 = 2097151 & (load_4(s + 36) >> 6);
383172c33676SMaxim Ag   int64_t s15 = 2097151 & (load_3(s + 39) >> 3);
383272c33676SMaxim Ag   int64_t s16 = 2097151 & load_3(s + 42);
383372c33676SMaxim Ag   int64_t s17 = 2097151 & (load_4(s + 44) >> 5);
383472c33676SMaxim Ag   int64_t s18 = 2097151 & (load_3(s + 47) >> 2);
383572c33676SMaxim Ag   int64_t s19 = 2097151 & (load_4(s + 49) >> 7);
383672c33676SMaxim Ag   int64_t s20 = 2097151 & (load_4(s + 52) >> 4);
383772c33676SMaxim Ag   int64_t s21 = 2097151 & (load_3(s + 55) >> 1);
383872c33676SMaxim Ag   int64_t s22 = 2097151 & (load_4(s + 57) >> 6);
383972c33676SMaxim Ag   int64_t s23 = (load_4(s + 60) >> 3);
384072c33676SMaxim Ag   int64_t carry0;
384172c33676SMaxim Ag   int64_t carry1;
384272c33676SMaxim Ag   int64_t carry2;
384372c33676SMaxim Ag   int64_t carry3;
384472c33676SMaxim Ag   int64_t carry4;
384572c33676SMaxim Ag   int64_t carry5;
384672c33676SMaxim Ag   int64_t carry6;
384772c33676SMaxim Ag   int64_t carry7;
384872c33676SMaxim Ag   int64_t carry8;
384972c33676SMaxim Ag   int64_t carry9;
385072c33676SMaxim Ag   int64_t carry10;
385172c33676SMaxim Ag   int64_t carry11;
385272c33676SMaxim Ag   int64_t carry12;
385372c33676SMaxim Ag   int64_t carry13;
385472c33676SMaxim Ag   int64_t carry14;
385572c33676SMaxim Ag   int64_t carry15;
385672c33676SMaxim Ag   int64_t carry16;
385772c33676SMaxim Ag 
385872c33676SMaxim Ag   s11 += s23 * 666643;
385972c33676SMaxim Ag   s12 += s23 * 470296;
386072c33676SMaxim Ag   s13 += s23 * 654183;
386172c33676SMaxim Ag   s14 -= s23 * 997805;
386272c33676SMaxim Ag   s15 += s23 * 136657;
386372c33676SMaxim Ag   s16 -= s23 * 683901;
386472c33676SMaxim Ag   s23 = 0;
386572c33676SMaxim Ag 
386672c33676SMaxim Ag   s10 += s22 * 666643;
386772c33676SMaxim Ag   s11 += s22 * 470296;
386872c33676SMaxim Ag   s12 += s22 * 654183;
386972c33676SMaxim Ag   s13 -= s22 * 997805;
387072c33676SMaxim Ag   s14 += s22 * 136657;
387172c33676SMaxim Ag   s15 -= s22 * 683901;
387272c33676SMaxim Ag   s22 = 0;
387372c33676SMaxim Ag 
387472c33676SMaxim Ag   s9 += s21 * 666643;
387572c33676SMaxim Ag   s10 += s21 * 470296;
387672c33676SMaxim Ag   s11 += s21 * 654183;
387772c33676SMaxim Ag   s12 -= s21 * 997805;
387872c33676SMaxim Ag   s13 += s21 * 136657;
387972c33676SMaxim Ag   s14 -= s21 * 683901;
388072c33676SMaxim Ag   s21 = 0;
388172c33676SMaxim Ag 
388272c33676SMaxim Ag   s8 += s20 * 666643;
388372c33676SMaxim Ag   s9 += s20 * 470296;
388472c33676SMaxim Ag   s10 += s20 * 654183;
388572c33676SMaxim Ag   s11 -= s20 * 997805;
388672c33676SMaxim Ag   s12 += s20 * 136657;
388772c33676SMaxim Ag   s13 -= s20 * 683901;
388872c33676SMaxim Ag   s20 = 0;
388972c33676SMaxim Ag 
389072c33676SMaxim Ag   s7 += s19 * 666643;
389172c33676SMaxim Ag   s8 += s19 * 470296;
389272c33676SMaxim Ag   s9 += s19 * 654183;
389372c33676SMaxim Ag   s10 -= s19 * 997805;
389472c33676SMaxim Ag   s11 += s19 * 136657;
389572c33676SMaxim Ag   s12 -= s19 * 683901;
389672c33676SMaxim Ag   s19 = 0;
389772c33676SMaxim Ag 
389872c33676SMaxim Ag   s6 += s18 * 666643;
389972c33676SMaxim Ag   s7 += s18 * 470296;
390072c33676SMaxim Ag   s8 += s18 * 654183;
390172c33676SMaxim Ag   s9 -= s18 * 997805;
390272c33676SMaxim Ag   s10 += s18 * 136657;
390372c33676SMaxim Ag   s11 -= s18 * 683901;
390472c33676SMaxim Ag   s18 = 0;
390572c33676SMaxim Ag 
390672c33676SMaxim Ag   carry6 = (s6 + (1 << 20)) >> 21;
390772c33676SMaxim Ag   s7 += carry6;
390872c33676SMaxim Ag   s6 -= carry6 << 21;
390972c33676SMaxim Ag   carry8 = (s8 + (1 << 20)) >> 21;
391072c33676SMaxim Ag   s9 += carry8;
391172c33676SMaxim Ag   s8 -= carry8 << 21;
391272c33676SMaxim Ag   carry10 = (s10 + (1 << 20)) >> 21;
391372c33676SMaxim Ag   s11 += carry10;
391472c33676SMaxim Ag   s10 -= carry10 << 21;
391572c33676SMaxim Ag   carry12 = (s12 + (1 << 20)) >> 21;
391672c33676SMaxim Ag   s13 += carry12;
391772c33676SMaxim Ag   s12 -= carry12 << 21;
391872c33676SMaxim Ag   carry14 = (s14 + (1 << 20)) >> 21;
391972c33676SMaxim Ag   s15 += carry14;
392072c33676SMaxim Ag   s14 -= carry14 << 21;
392172c33676SMaxim Ag   carry16 = (s16 + (1 << 20)) >> 21;
392272c33676SMaxim Ag   s17 += carry16;
392372c33676SMaxim Ag   s16 -= carry16 << 21;
392472c33676SMaxim Ag 
392572c33676SMaxim Ag   carry7 = (s7 + (1 << 20)) >> 21;
392672c33676SMaxim Ag   s8 += carry7;
392772c33676SMaxim Ag   s7 -= carry7 << 21;
392872c33676SMaxim Ag   carry9 = (s9 + (1 << 20)) >> 21;
392972c33676SMaxim Ag   s10 += carry9;
393072c33676SMaxim Ag   s9 -= carry9 << 21;
393172c33676SMaxim Ag   carry11 = (s11 + (1 << 20)) >> 21;
393272c33676SMaxim Ag   s12 += carry11;
393372c33676SMaxim Ag   s11 -= carry11 << 21;
393472c33676SMaxim Ag   carry13 = (s13 + (1 << 20)) >> 21;
393572c33676SMaxim Ag   s14 += carry13;
393672c33676SMaxim Ag   s13 -= carry13 << 21;
393772c33676SMaxim Ag   carry15 = (s15 + (1 << 20)) >> 21;
393872c33676SMaxim Ag   s16 += carry15;
393972c33676SMaxim Ag   s15 -= carry15 << 21;
394072c33676SMaxim Ag 
394172c33676SMaxim Ag   s5 += s17 * 666643;
394272c33676SMaxim Ag   s6 += s17 * 470296;
394372c33676SMaxim Ag   s7 += s17 * 654183;
394472c33676SMaxim Ag   s8 -= s17 * 997805;
394572c33676SMaxim Ag   s9 += s17 * 136657;
394672c33676SMaxim Ag   s10 -= s17 * 683901;
394772c33676SMaxim Ag   s17 = 0;
394872c33676SMaxim Ag 
394972c33676SMaxim Ag   s4 += s16 * 666643;
395072c33676SMaxim Ag   s5 += s16 * 470296;
395172c33676SMaxim Ag   s6 += s16 * 654183;
395272c33676SMaxim Ag   s7 -= s16 * 997805;
395372c33676SMaxim Ag   s8 += s16 * 136657;
395472c33676SMaxim Ag   s9 -= s16 * 683901;
395572c33676SMaxim Ag   s16 = 0;
395672c33676SMaxim Ag 
395772c33676SMaxim Ag   s3 += s15 * 666643;
395872c33676SMaxim Ag   s4 += s15 * 470296;
395972c33676SMaxim Ag   s5 += s15 * 654183;
396072c33676SMaxim Ag   s6 -= s15 * 997805;
396172c33676SMaxim Ag   s7 += s15 * 136657;
396272c33676SMaxim Ag   s8 -= s15 * 683901;
396372c33676SMaxim Ag   s15 = 0;
396472c33676SMaxim Ag 
396572c33676SMaxim Ag   s2 += s14 * 666643;
396672c33676SMaxim Ag   s3 += s14 * 470296;
396772c33676SMaxim Ag   s4 += s14 * 654183;
396872c33676SMaxim Ag   s5 -= s14 * 997805;
396972c33676SMaxim Ag   s6 += s14 * 136657;
397072c33676SMaxim Ag   s7 -= s14 * 683901;
397172c33676SMaxim Ag   s14 = 0;
397272c33676SMaxim Ag 
397372c33676SMaxim Ag   s1 += s13 * 666643;
397472c33676SMaxim Ag   s2 += s13 * 470296;
397572c33676SMaxim Ag   s3 += s13 * 654183;
397672c33676SMaxim Ag   s4 -= s13 * 997805;
397772c33676SMaxim Ag   s5 += s13 * 136657;
397872c33676SMaxim Ag   s6 -= s13 * 683901;
397972c33676SMaxim Ag   s13 = 0;
398072c33676SMaxim Ag 
398172c33676SMaxim Ag   s0 += s12 * 666643;
398272c33676SMaxim Ag   s1 += s12 * 470296;
398372c33676SMaxim Ag   s2 += s12 * 654183;
398472c33676SMaxim Ag   s3 -= s12 * 997805;
398572c33676SMaxim Ag   s4 += s12 * 136657;
398672c33676SMaxim Ag   s5 -= s12 * 683901;
398772c33676SMaxim Ag   s12 = 0;
398872c33676SMaxim Ag 
398972c33676SMaxim Ag   carry0 = (s0 + (1 << 20)) >> 21;
399072c33676SMaxim Ag   s1 += carry0;
399172c33676SMaxim Ag   s0 -= carry0 << 21;
399272c33676SMaxim Ag   carry2 = (s2 + (1 << 20)) >> 21;
399372c33676SMaxim Ag   s3 += carry2;
399472c33676SMaxim Ag   s2 -= carry2 << 21;
399572c33676SMaxim Ag   carry4 = (s4 + (1 << 20)) >> 21;
399672c33676SMaxim Ag   s5 += carry4;
399772c33676SMaxim Ag   s4 -= carry4 << 21;
399872c33676SMaxim Ag   carry6 = (s6 + (1 << 20)) >> 21;
399972c33676SMaxim Ag   s7 += carry6;
400072c33676SMaxim Ag   s6 -= carry6 << 21;
400172c33676SMaxim Ag   carry8 = (s8 + (1 << 20)) >> 21;
400272c33676SMaxim Ag   s9 += carry8;
400372c33676SMaxim Ag   s8 -= carry8 << 21;
400472c33676SMaxim Ag   carry10 = (s10 + (1 << 20)) >> 21;
400572c33676SMaxim Ag   s11 += carry10;
400672c33676SMaxim Ag   s10 -= carry10 << 21;
400772c33676SMaxim Ag 
400872c33676SMaxim Ag   carry1 = (s1 + (1 << 20)) >> 21;
400972c33676SMaxim Ag   s2 += carry1;
401072c33676SMaxim Ag   s1 -= carry1 << 21;
401172c33676SMaxim Ag   carry3 = (s3 + (1 << 20)) >> 21;
401272c33676SMaxim Ag   s4 += carry3;
401372c33676SMaxim Ag   s3 -= carry3 << 21;
401472c33676SMaxim Ag   carry5 = (s5 + (1 << 20)) >> 21;
401572c33676SMaxim Ag   s6 += carry5;
401672c33676SMaxim Ag   s5 -= carry5 << 21;
401772c33676SMaxim Ag   carry7 = (s7 + (1 << 20)) >> 21;
401872c33676SMaxim Ag   s8 += carry7;
401972c33676SMaxim Ag   s7 -= carry7 << 21;
402072c33676SMaxim Ag   carry9 = (s9 + (1 << 20)) >> 21;
402172c33676SMaxim Ag   s10 += carry9;
402272c33676SMaxim Ag   s9 -= carry9 << 21;
402372c33676SMaxim Ag   carry11 = (s11 + (1 << 20)) >> 21;
402472c33676SMaxim Ag   s12 += carry11;
402572c33676SMaxim Ag   s11 -= carry11 << 21;
402672c33676SMaxim Ag 
402772c33676SMaxim Ag   s0 += s12 * 666643;
402872c33676SMaxim Ag   s1 += s12 * 470296;
402972c33676SMaxim Ag   s2 += s12 * 654183;
403072c33676SMaxim Ag   s3 -= s12 * 997805;
403172c33676SMaxim Ag   s4 += s12 * 136657;
403272c33676SMaxim Ag   s5 -= s12 * 683901;
403372c33676SMaxim Ag   s12 = 0;
403472c33676SMaxim Ag 
403572c33676SMaxim Ag   carry0 = s0 >> 21;
403672c33676SMaxim Ag   s1 += carry0;
403772c33676SMaxim Ag   s0 -= carry0 << 21;
403872c33676SMaxim Ag   carry1 = s1 >> 21;
403972c33676SMaxim Ag   s2 += carry1;
404072c33676SMaxim Ag   s1 -= carry1 << 21;
404172c33676SMaxim Ag   carry2 = s2 >> 21;
404272c33676SMaxim Ag   s3 += carry2;
404372c33676SMaxim Ag   s2 -= carry2 << 21;
404472c33676SMaxim Ag   carry3 = s3 >> 21;
404572c33676SMaxim Ag   s4 += carry3;
404672c33676SMaxim Ag   s3 -= carry3 << 21;
404772c33676SMaxim Ag   carry4 = s4 >> 21;
404872c33676SMaxim Ag   s5 += carry4;
404972c33676SMaxim Ag   s4 -= carry4 << 21;
405072c33676SMaxim Ag   carry5 = s5 >> 21;
405172c33676SMaxim Ag   s6 += carry5;
405272c33676SMaxim Ag   s5 -= carry5 << 21;
405372c33676SMaxim Ag   carry6 = s6 >> 21;
405472c33676SMaxim Ag   s7 += carry6;
405572c33676SMaxim Ag   s6 -= carry6 << 21;
405672c33676SMaxim Ag   carry7 = s7 >> 21;
405772c33676SMaxim Ag   s8 += carry7;
405872c33676SMaxim Ag   s7 -= carry7 << 21;
405972c33676SMaxim Ag   carry8 = s8 >> 21;
406072c33676SMaxim Ag   s9 += carry8;
406172c33676SMaxim Ag   s8 -= carry8 << 21;
406272c33676SMaxim Ag   carry9 = s9 >> 21;
406372c33676SMaxim Ag   s10 += carry9;
406472c33676SMaxim Ag   s9 -= carry9 << 21;
406572c33676SMaxim Ag   carry10 = s10 >> 21;
406672c33676SMaxim Ag   s11 += carry10;
406772c33676SMaxim Ag   s10 -= carry10 << 21;
406872c33676SMaxim Ag   carry11 = s11 >> 21;
406972c33676SMaxim Ag   s12 += carry11;
407072c33676SMaxim Ag   s11 -= carry11 << 21;
407172c33676SMaxim Ag 
407272c33676SMaxim Ag   s0 += s12 * 666643;
407372c33676SMaxim Ag   s1 += s12 * 470296;
407472c33676SMaxim Ag   s2 += s12 * 654183;
407572c33676SMaxim Ag   s3 -= s12 * 997805;
407672c33676SMaxim Ag   s4 += s12 * 136657;
407772c33676SMaxim Ag   s5 -= s12 * 683901;
407872c33676SMaxim Ag   s12 = 0;
407972c33676SMaxim Ag 
408072c33676SMaxim Ag   carry0 = s0 >> 21;
408172c33676SMaxim Ag   s1 += carry0;
408272c33676SMaxim Ag   s0 -= carry0 << 21;
408372c33676SMaxim Ag   carry1 = s1 >> 21;
408472c33676SMaxim Ag   s2 += carry1;
408572c33676SMaxim Ag   s1 -= carry1 << 21;
408672c33676SMaxim Ag   carry2 = s2 >> 21;
408772c33676SMaxim Ag   s3 += carry2;
408872c33676SMaxim Ag   s2 -= carry2 << 21;
408972c33676SMaxim Ag   carry3 = s3 >> 21;
409072c33676SMaxim Ag   s4 += carry3;
409172c33676SMaxim Ag   s3 -= carry3 << 21;
409272c33676SMaxim Ag   carry4 = s4 >> 21;
409372c33676SMaxim Ag   s5 += carry4;
409472c33676SMaxim Ag   s4 -= carry4 << 21;
409572c33676SMaxim Ag   carry5 = s5 >> 21;
409672c33676SMaxim Ag   s6 += carry5;
409772c33676SMaxim Ag   s5 -= carry5 << 21;
409872c33676SMaxim Ag   carry6 = s6 >> 21;
409972c33676SMaxim Ag   s7 += carry6;
410072c33676SMaxim Ag   s6 -= carry6 << 21;
410172c33676SMaxim Ag   carry7 = s7 >> 21;
410272c33676SMaxim Ag   s8 += carry7;
410372c33676SMaxim Ag   s7 -= carry7 << 21;
410472c33676SMaxim Ag   carry8 = s8 >> 21;
410572c33676SMaxim Ag   s9 += carry8;
410672c33676SMaxim Ag   s8 -= carry8 << 21;
410772c33676SMaxim Ag   carry9 = s9 >> 21;
410872c33676SMaxim Ag   s10 += carry9;
410972c33676SMaxim Ag   s9 -= carry9 << 21;
411072c33676SMaxim Ag   carry10 = s10 >> 21;
411172c33676SMaxim Ag   s11 += carry10;
411272c33676SMaxim Ag   s10 -= carry10 << 21;
411372c33676SMaxim Ag 
411472c33676SMaxim Ag   s[0] = s0 >> 0;
411572c33676SMaxim Ag   s[1] = s0 >> 8;
411672c33676SMaxim Ag   s[2] = (s0 >> 16) | (s1 << 5);
411772c33676SMaxim Ag   s[3] = s1 >> 3;
411872c33676SMaxim Ag   s[4] = s1 >> 11;
411972c33676SMaxim Ag   s[5] = (s1 >> 19) | (s2 << 2);
412072c33676SMaxim Ag   s[6] = s2 >> 6;
412172c33676SMaxim Ag   s[7] = (s2 >> 14) | (s3 << 7);
412272c33676SMaxim Ag   s[8] = s3 >> 1;
412372c33676SMaxim Ag   s[9] = s3 >> 9;
412472c33676SMaxim Ag   s[10] = (s3 >> 17) | (s4 << 4);
412572c33676SMaxim Ag   s[11] = s4 >> 4;
412672c33676SMaxim Ag   s[12] = s4 >> 12;
412772c33676SMaxim Ag   s[13] = (s4 >> 20) | (s5 << 1);
412872c33676SMaxim Ag   s[14] = s5 >> 7;
412972c33676SMaxim Ag   s[15] = (s5 >> 15) | (s6 << 6);
413072c33676SMaxim Ag   s[16] = s6 >> 2;
413172c33676SMaxim Ag   s[17] = s6 >> 10;
413272c33676SMaxim Ag   s[18] = (s6 >> 18) | (s7 << 3);
413372c33676SMaxim Ag   s[19] = s7 >> 5;
413472c33676SMaxim Ag   s[20] = s7 >> 13;
413572c33676SMaxim Ag   s[21] = s8 >> 0;
413672c33676SMaxim Ag   s[22] = s8 >> 8;
413772c33676SMaxim Ag   s[23] = (s8 >> 16) | (s9 << 5);
413872c33676SMaxim Ag   s[24] = s9 >> 3;
413972c33676SMaxim Ag   s[25] = s9 >> 11;
414072c33676SMaxim Ag   s[26] = (s9 >> 19) | (s10 << 2);
414172c33676SMaxim Ag   s[27] = s10 >> 6;
414272c33676SMaxim Ag   s[28] = (s10 >> 14) | (s11 << 7);
414372c33676SMaxim Ag   s[29] = s11 >> 1;
414472c33676SMaxim Ag   s[30] = s11 >> 9;
414572c33676SMaxim Ag   s[31] = s11 >> 17;
414672c33676SMaxim Ag }
414772c33676SMaxim Ag 
414872c33676SMaxim Ag #ifdef ED25519
414972c33676SMaxim Ag /* Input:
415072c33676SMaxim Ag  *   a[0]+256*a[1]+...+256^31*a[31] = a
415172c33676SMaxim Ag  *   b[0]+256*b[1]+...+256^31*b[31] = b
415272c33676SMaxim Ag  *   c[0]+256*c[1]+...+256^31*c[31] = c
415372c33676SMaxim Ag  *
415472c33676SMaxim Ag  * Output:
415572c33676SMaxim Ag  *   s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
415672c33676SMaxim Ag  *   where l = 2^252 + 27742317777372353535851937790883648493. */
415772c33676SMaxim Ag static void
sc_muladd(uint8_t * s,const uint8_t * a,const uint8_t * b,const uint8_t * c)415872c33676SMaxim Ag sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
415972c33676SMaxim Ag     const uint8_t *c)
416072c33676SMaxim Ag {
416172c33676SMaxim Ag   int64_t a0 = 2097151 & load_3(a);
416272c33676SMaxim Ag   int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
416372c33676SMaxim Ag   int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
416472c33676SMaxim Ag   int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
416572c33676SMaxim Ag   int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
416672c33676SMaxim Ag   int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
416772c33676SMaxim Ag   int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
416872c33676SMaxim Ag   int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
416972c33676SMaxim Ag   int64_t a8 = 2097151 & load_3(a + 21);
417072c33676SMaxim Ag   int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
417172c33676SMaxim Ag   int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
417272c33676SMaxim Ag   int64_t a11 = (load_4(a + 28) >> 7);
417372c33676SMaxim Ag   int64_t b0 = 2097151 & load_3(b);
417472c33676SMaxim Ag   int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
417572c33676SMaxim Ag   int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
417672c33676SMaxim Ag   int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
417772c33676SMaxim Ag   int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
417872c33676SMaxim Ag   int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
417972c33676SMaxim Ag   int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
418072c33676SMaxim Ag   int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
418172c33676SMaxim Ag   int64_t b8 = 2097151 & load_3(b + 21);
418272c33676SMaxim Ag   int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
418372c33676SMaxim Ag   int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
418472c33676SMaxim Ag   int64_t b11 = (load_4(b + 28) >> 7);
418572c33676SMaxim Ag   int64_t c0 = 2097151 & load_3(c);
418672c33676SMaxim Ag   int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
418772c33676SMaxim Ag   int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
418872c33676SMaxim Ag   int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
418972c33676SMaxim Ag   int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
419072c33676SMaxim Ag   int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
419172c33676SMaxim Ag   int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
419272c33676SMaxim Ag   int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
419372c33676SMaxim Ag   int64_t c8 = 2097151 & load_3(c + 21);
419472c33676SMaxim Ag   int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
419572c33676SMaxim Ag   int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
419672c33676SMaxim Ag   int64_t c11 = (load_4(c + 28) >> 7);
419772c33676SMaxim Ag   int64_t s0;
419872c33676SMaxim Ag   int64_t s1;
419972c33676SMaxim Ag   int64_t s2;
420072c33676SMaxim Ag   int64_t s3;
420172c33676SMaxim Ag   int64_t s4;
420272c33676SMaxim Ag   int64_t s5;
420372c33676SMaxim Ag   int64_t s6;
420472c33676SMaxim Ag   int64_t s7;
420572c33676SMaxim Ag   int64_t s8;
420672c33676SMaxim Ag   int64_t s9;
420772c33676SMaxim Ag   int64_t s10;
420872c33676SMaxim Ag   int64_t s11;
420972c33676SMaxim Ag   int64_t s12;
421072c33676SMaxim Ag   int64_t s13;
421172c33676SMaxim Ag   int64_t s14;
421272c33676SMaxim Ag   int64_t s15;
421372c33676SMaxim Ag   int64_t s16;
421472c33676SMaxim Ag   int64_t s17;
421572c33676SMaxim Ag   int64_t s18;
421672c33676SMaxim Ag   int64_t s19;
421772c33676SMaxim Ag   int64_t s20;
421872c33676SMaxim Ag   int64_t s21;
421972c33676SMaxim Ag   int64_t s22;
422072c33676SMaxim Ag   int64_t s23;
422172c33676SMaxim Ag   int64_t carry0;
422272c33676SMaxim Ag   int64_t carry1;
422372c33676SMaxim Ag   int64_t carry2;
422472c33676SMaxim Ag   int64_t carry3;
422572c33676SMaxim Ag   int64_t carry4;
422672c33676SMaxim Ag   int64_t carry5;
422772c33676SMaxim Ag   int64_t carry6;
422872c33676SMaxim Ag   int64_t carry7;
422972c33676SMaxim Ag   int64_t carry8;
423072c33676SMaxim Ag   int64_t carry9;
423172c33676SMaxim Ag   int64_t carry10;
423272c33676SMaxim Ag   int64_t carry11;
423372c33676SMaxim Ag   int64_t carry12;
423472c33676SMaxim Ag   int64_t carry13;
423572c33676SMaxim Ag   int64_t carry14;
423672c33676SMaxim Ag   int64_t carry15;
423772c33676SMaxim Ag   int64_t carry16;
423872c33676SMaxim Ag   int64_t carry17;
423972c33676SMaxim Ag   int64_t carry18;
424072c33676SMaxim Ag   int64_t carry19;
424172c33676SMaxim Ag   int64_t carry20;
424272c33676SMaxim Ag   int64_t carry21;
424372c33676SMaxim Ag   int64_t carry22;
424472c33676SMaxim Ag 
424572c33676SMaxim Ag   s0 = c0 + a0 * b0;
424672c33676SMaxim Ag   s1 = c1 + a0 * b1 + a1 * b0;
424772c33676SMaxim Ag   s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
424872c33676SMaxim Ag   s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
424972c33676SMaxim Ag   s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
425072c33676SMaxim Ag   s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
425172c33676SMaxim Ag   s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
425272c33676SMaxim Ag   s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
425372c33676SMaxim Ag        a6 * b1 + a7 * b0;
425472c33676SMaxim Ag   s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
425572c33676SMaxim Ag        a6 * b2 + a7 * b1 + a8 * b0;
425672c33676SMaxim Ag   s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
425772c33676SMaxim Ag        a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
425872c33676SMaxim Ag   s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
425972c33676SMaxim Ag         a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
426072c33676SMaxim Ag   s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
426172c33676SMaxim Ag         a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
426272c33676SMaxim Ag   s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 +
426372c33676SMaxim Ag         a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
426472c33676SMaxim Ag   s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 +
426572c33676SMaxim Ag         a9 * b4 + a10 * b3 + a11 * b2;
426672c33676SMaxim Ag   s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 +
426772c33676SMaxim Ag         a10 * b4 + a11 * b3;
426872c33676SMaxim Ag   s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 +
426972c33676SMaxim Ag         a11 * b4;
427072c33676SMaxim Ag   s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
427172c33676SMaxim Ag   s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
427272c33676SMaxim Ag   s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
427372c33676SMaxim Ag   s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
427472c33676SMaxim Ag   s20 = a9 * b11 + a10 * b10 + a11 * b9;
427572c33676SMaxim Ag   s21 = a10 * b11 + a11 * b10;
427672c33676SMaxim Ag   s22 = a11 * b11;
427772c33676SMaxim Ag   s23 = 0;
427872c33676SMaxim Ag 
427972c33676SMaxim Ag   carry0 = (s0 + (1 << 20)) >> 21;
428072c33676SMaxim Ag   s1 += carry0;
428172c33676SMaxim Ag   s0 -= carry0 << 21;
428272c33676SMaxim Ag   carry2 = (s2 + (1 << 20)) >> 21;
428372c33676SMaxim Ag   s3 += carry2;
428472c33676SMaxim Ag   s2 -= carry2 << 21;
428572c33676SMaxim Ag   carry4 = (s4 + (1 << 20)) >> 21;
428672c33676SMaxim Ag   s5 += carry4;
428772c33676SMaxim Ag   s4 -= carry4 << 21;
428872c33676SMaxim Ag   carry6 = (s6 + (1 << 20)) >> 21;
428972c33676SMaxim Ag   s7 += carry6;
429072c33676SMaxim Ag   s6 -= carry6 << 21;
429172c33676SMaxim Ag   carry8 = (s8 + (1 << 20)) >> 21;
429272c33676SMaxim Ag   s9 += carry8;
429372c33676SMaxim Ag   s8 -= carry8 << 21;
429472c33676SMaxim Ag   carry10 = (s10 + (1 << 20)) >> 21;
429572c33676SMaxim Ag   s11 += carry10;
429672c33676SMaxim Ag   s10 -= carry10 << 21;
429772c33676SMaxim Ag   carry12 = (s12 + (1 << 20)) >> 21;
429872c33676SMaxim Ag   s13 += carry12;
429972c33676SMaxim Ag   s12 -= carry12 << 21;
430072c33676SMaxim Ag   carry14 = (s14 + (1 << 20)) >> 21;
430172c33676SMaxim Ag   s15 += carry14;
430272c33676SMaxim Ag   s14 -= carry14 << 21;
430372c33676SMaxim Ag   carry16 = (s16 + (1 << 20)) >> 21;
430472c33676SMaxim Ag   s17 += carry16;
430572c33676SMaxim Ag   s16 -= carry16 << 21;
430672c33676SMaxim Ag   carry18 = (s18 + (1 << 20)) >> 21;
430772c33676SMaxim Ag   s19 += carry18;
430872c33676SMaxim Ag   s18 -= carry18 << 21;
430972c33676SMaxim Ag   carry20 = (s20 + (1 << 20)) >> 21;
431072c33676SMaxim Ag   s21 += carry20;
431172c33676SMaxim Ag   s20 -= carry20 << 21;
431272c33676SMaxim Ag   carry22 = (s22 + (1 << 20)) >> 21;
431372c33676SMaxim Ag   s23 += carry22;
431472c33676SMaxim Ag   s22 -= carry22 << 21;
431572c33676SMaxim Ag 
431672c33676SMaxim Ag   carry1 = (s1 + (1 << 20)) >> 21;
431772c33676SMaxim Ag   s2 += carry1;
431872c33676SMaxim Ag   s1 -= carry1 << 21;
431972c33676SMaxim Ag   carry3 = (s3 + (1 << 20)) >> 21;
432072c33676SMaxim Ag   s4 += carry3;
432172c33676SMaxim Ag   s3 -= carry3 << 21;
432272c33676SMaxim Ag   carry5 = (s5 + (1 << 20)) >> 21;
432372c33676SMaxim Ag   s6 += carry5;
432472c33676SMaxim Ag   s5 -= carry5 << 21;
432572c33676SMaxim Ag   carry7 = (s7 + (1 << 20)) >> 21;
432672c33676SMaxim Ag   s8 += carry7;
432772c33676SMaxim Ag   s7 -= carry7 << 21;
432872c33676SMaxim Ag   carry9 = (s9 + (1 << 20)) >> 21;
432972c33676SMaxim Ag   s10 += carry9;
433072c33676SMaxim Ag   s9 -= carry9 << 21;
433172c33676SMaxim Ag   carry11 = (s11 + (1 << 20)) >> 21;
433272c33676SMaxim Ag   s12 += carry11;
433372c33676SMaxim Ag   s11 -= carry11 << 21;
433472c33676SMaxim Ag   carry13 = (s13 + (1 << 20)) >> 21;
433572c33676SMaxim Ag   s14 += carry13;
433672c33676SMaxim Ag   s13 -= carry13 << 21;
433772c33676SMaxim Ag   carry15 = (s15 + (1 << 20)) >> 21;
433872c33676SMaxim Ag   s16 += carry15;
433972c33676SMaxim Ag   s15 -= carry15 << 21;
434072c33676SMaxim Ag   carry17 = (s17 + (1 << 20)) >> 21;
434172c33676SMaxim Ag   s18 += carry17;
434272c33676SMaxim Ag   s17 -= carry17 << 21;
434372c33676SMaxim Ag   carry19 = (s19 + (1 << 20)) >> 21;
434472c33676SMaxim Ag   s20 += carry19;
434572c33676SMaxim Ag   s19 -= carry19 << 21;
434672c33676SMaxim Ag   carry21 = (s21 + (1 << 20)) >> 21;
434772c33676SMaxim Ag   s22 += carry21;
434872c33676SMaxim Ag   s21 -= carry21 << 21;
434972c33676SMaxim Ag 
435072c33676SMaxim Ag   s11 += s23 * 666643;
435172c33676SMaxim Ag   s12 += s23 * 470296;
435272c33676SMaxim Ag   s13 += s23 * 654183;
435372c33676SMaxim Ag   s14 -= s23 * 997805;
435472c33676SMaxim Ag   s15 += s23 * 136657;
435572c33676SMaxim Ag   s16 -= s23 * 683901;
435672c33676SMaxim Ag   s23 = 0;
435772c33676SMaxim Ag 
435872c33676SMaxim Ag   s10 += s22 * 666643;
435972c33676SMaxim Ag   s11 += s22 * 470296;
436072c33676SMaxim Ag   s12 += s22 * 654183;
436172c33676SMaxim Ag   s13 -= s22 * 997805;
436272c33676SMaxim Ag   s14 += s22 * 136657;
436372c33676SMaxim Ag   s15 -= s22 * 683901;
436472c33676SMaxim Ag   s22 = 0;
436572c33676SMaxim Ag 
436672c33676SMaxim Ag   s9 += s21 * 666643;
436772c33676SMaxim Ag   s10 += s21 * 470296;
436872c33676SMaxim Ag   s11 += s21 * 654183;
436972c33676SMaxim Ag   s12 -= s21 * 997805;
437072c33676SMaxim Ag   s13 += s21 * 136657;
437172c33676SMaxim Ag   s14 -= s21 * 683901;
437272c33676SMaxim Ag   s21 = 0;
437372c33676SMaxim Ag 
437472c33676SMaxim Ag   s8 += s20 * 666643;
437572c33676SMaxim Ag   s9 += s20 * 470296;
437672c33676SMaxim Ag   s10 += s20 * 654183;
437772c33676SMaxim Ag   s11 -= s20 * 997805;
437872c33676SMaxim Ag   s12 += s20 * 136657;
437972c33676SMaxim Ag   s13 -= s20 * 683901;
438072c33676SMaxim Ag   s20 = 0;
438172c33676SMaxim Ag 
438272c33676SMaxim Ag   s7 += s19 * 666643;
438372c33676SMaxim Ag   s8 += s19 * 470296;
438472c33676SMaxim Ag   s9 += s19 * 654183;
438572c33676SMaxim Ag   s10 -= s19 * 997805;
438672c33676SMaxim Ag   s11 += s19 * 136657;
438772c33676SMaxim Ag   s12 -= s19 * 683901;
438872c33676SMaxim Ag   s19 = 0;
438972c33676SMaxim Ag 
439072c33676SMaxim Ag   s6 += s18 * 666643;
439172c33676SMaxim Ag   s7 += s18 * 470296;
439272c33676SMaxim Ag   s8 += s18 * 654183;
439372c33676SMaxim Ag   s9 -= s18 * 997805;
439472c33676SMaxim Ag   s10 += s18 * 136657;
439572c33676SMaxim Ag   s11 -= s18 * 683901;
439672c33676SMaxim Ag   s18 = 0;
439772c33676SMaxim Ag 
439872c33676SMaxim Ag   carry6 = (s6 + (1 << 20)) >> 21;
439972c33676SMaxim Ag   s7 += carry6;
440072c33676SMaxim Ag   s6 -= carry6 << 21;
440172c33676SMaxim Ag   carry8 = (s8 + (1 << 20)) >> 21;
440272c33676SMaxim Ag   s9 += carry8;
440372c33676SMaxim Ag   s8 -= carry8 << 21;
440472c33676SMaxim Ag   carry10 = (s10 + (1 << 20)) >> 21;
440572c33676SMaxim Ag   s11 += carry10;
440672c33676SMaxim Ag   s10 -= carry10 << 21;
440772c33676SMaxim Ag   carry12 = (s12 + (1 << 20)) >> 21;
440872c33676SMaxim Ag   s13 += carry12;
440972c33676SMaxim Ag   s12 -= carry12 << 21;
441072c33676SMaxim Ag   carry14 = (s14 + (1 << 20)) >> 21;
441172c33676SMaxim Ag   s15 += carry14;
441272c33676SMaxim Ag   s14 -= carry14 << 21;
441372c33676SMaxim Ag   carry16 = (s16 + (1 << 20)) >> 21;
441472c33676SMaxim Ag   s17 += carry16;
441572c33676SMaxim Ag   s16 -= carry16 << 21;
441672c33676SMaxim Ag 
441772c33676SMaxim Ag   carry7 = (s7 + (1 << 20)) >> 21;
441872c33676SMaxim Ag   s8 += carry7;
441972c33676SMaxim Ag   s7 -= carry7 << 21;
442072c33676SMaxim Ag   carry9 = (s9 + (1 << 20)) >> 21;
442172c33676SMaxim Ag   s10 += carry9;
442272c33676SMaxim Ag   s9 -= carry9 << 21;
442372c33676SMaxim Ag   carry11 = (s11 + (1 << 20)) >> 21;
442472c33676SMaxim Ag   s12 += carry11;
442572c33676SMaxim Ag   s11 -= carry11 << 21;
442672c33676SMaxim Ag   carry13 = (s13 + (1 << 20)) >> 21;
442772c33676SMaxim Ag   s14 += carry13;
442872c33676SMaxim Ag   s13 -= carry13 << 21;
442972c33676SMaxim Ag   carry15 = (s15 + (1 << 20)) >> 21;
443072c33676SMaxim Ag   s16 += carry15;
443172c33676SMaxim Ag   s15 -= carry15 << 21;
443272c33676SMaxim Ag 
443372c33676SMaxim Ag   s5 += s17 * 666643;
443472c33676SMaxim Ag   s6 += s17 * 470296;
443572c33676SMaxim Ag   s7 += s17 * 654183;
443672c33676SMaxim Ag   s8 -= s17 * 997805;
443772c33676SMaxim Ag   s9 += s17 * 136657;
443872c33676SMaxim Ag   s10 -= s17 * 683901;
443972c33676SMaxim Ag   s17 = 0;
444072c33676SMaxim Ag 
444172c33676SMaxim Ag   s4 += s16 * 666643;
444272c33676SMaxim Ag   s5 += s16 * 470296;
444372c33676SMaxim Ag   s6 += s16 * 654183;
444472c33676SMaxim Ag   s7 -= s16 * 997805;
444572c33676SMaxim Ag   s8 += s16 * 136657;
444672c33676SMaxim Ag   s9 -= s16 * 683901;
444772c33676SMaxim Ag   s16 = 0;
444872c33676SMaxim Ag 
444972c33676SMaxim Ag   s3 += s15 * 666643;
445072c33676SMaxim Ag   s4 += s15 * 470296;
445172c33676SMaxim Ag   s5 += s15 * 654183;
445272c33676SMaxim Ag   s6 -= s15 * 997805;
445372c33676SMaxim Ag   s7 += s15 * 136657;
445472c33676SMaxim Ag   s8 -= s15 * 683901;
445572c33676SMaxim Ag   s15 = 0;
445672c33676SMaxim Ag 
445772c33676SMaxim Ag   s2 += s14 * 666643;
445872c33676SMaxim Ag   s3 += s14 * 470296;
445972c33676SMaxim Ag   s4 += s14 * 654183;
446072c33676SMaxim Ag   s5 -= s14 * 997805;
446172c33676SMaxim Ag   s6 += s14 * 136657;
446272c33676SMaxim Ag   s7 -= s14 * 683901;
446372c33676SMaxim Ag   s14 = 0;
446472c33676SMaxim Ag 
446572c33676SMaxim Ag   s1 += s13 * 666643;
446672c33676SMaxim Ag   s2 += s13 * 470296;
446772c33676SMaxim Ag   s3 += s13 * 654183;
446872c33676SMaxim Ag   s4 -= s13 * 997805;
446972c33676SMaxim Ag   s5 += s13 * 136657;
447072c33676SMaxim Ag   s6 -= s13 * 683901;
447172c33676SMaxim Ag   s13 = 0;
447272c33676SMaxim Ag 
447372c33676SMaxim Ag   s0 += s12 * 666643;
447472c33676SMaxim Ag   s1 += s12 * 470296;
447572c33676SMaxim Ag   s2 += s12 * 654183;
447672c33676SMaxim Ag   s3 -= s12 * 997805;
447772c33676SMaxim Ag   s4 += s12 * 136657;
447872c33676SMaxim Ag   s5 -= s12 * 683901;
447972c33676SMaxim Ag   s12 = 0;
448072c33676SMaxim Ag 
448172c33676SMaxim Ag   carry0 = (s0 + (1 << 20)) >> 21;
448272c33676SMaxim Ag   s1 += carry0;
448372c33676SMaxim Ag   s0 -= carry0 << 21;
448472c33676SMaxim Ag   carry2 = (s2 + (1 << 20)) >> 21;
448572c33676SMaxim Ag   s3 += carry2;
448672c33676SMaxim Ag   s2 -= carry2 << 21;
448772c33676SMaxim Ag   carry4 = (s4 + (1 << 20)) >> 21;
448872c33676SMaxim Ag   s5 += carry4;
448972c33676SMaxim Ag   s4 -= carry4 << 21;
449072c33676SMaxim Ag   carry6 = (s6 + (1 << 20)) >> 21;
449172c33676SMaxim Ag   s7 += carry6;
449272c33676SMaxim Ag   s6 -= carry6 << 21;
449372c33676SMaxim Ag   carry8 = (s8 + (1 << 20)) >> 21;
449472c33676SMaxim Ag   s9 += carry8;
449572c33676SMaxim Ag   s8 -= carry8 << 21;
449672c33676SMaxim Ag   carry10 = (s10 + (1 << 20)) >> 21;
449772c33676SMaxim Ag   s11 += carry10;
449872c33676SMaxim Ag   s10 -= carry10 << 21;
449972c33676SMaxim Ag 
450072c33676SMaxim Ag   carry1 = (s1 + (1 << 20)) >> 21;
450172c33676SMaxim Ag   s2 += carry1;
450272c33676SMaxim Ag   s1 -= carry1 << 21;
450372c33676SMaxim Ag   carry3 = (s3 + (1 << 20)) >> 21;
450472c33676SMaxim Ag   s4 += carry3;
450572c33676SMaxim Ag   s3 -= carry3 << 21;
450672c33676SMaxim Ag   carry5 = (s5 + (1 << 20)) >> 21;
450772c33676SMaxim Ag   s6 += carry5;
450872c33676SMaxim Ag   s5 -= carry5 << 21;
450972c33676SMaxim Ag   carry7 = (s7 + (1 << 20)) >> 21;
451072c33676SMaxim Ag   s8 += carry7;
451172c33676SMaxim Ag   s7 -= carry7 << 21;
451272c33676SMaxim Ag   carry9 = (s9 + (1 << 20)) >> 21;
451372c33676SMaxim Ag   s10 += carry9;
451472c33676SMaxim Ag   s9 -= carry9 << 21;
451572c33676SMaxim Ag   carry11 = (s11 + (1 << 20)) >> 21;
451672c33676SMaxim Ag   s12 += carry11;
451772c33676SMaxim Ag   s11 -= carry11 << 21;
451872c33676SMaxim Ag 
451972c33676SMaxim Ag   s0 += s12 * 666643;
452072c33676SMaxim Ag   s1 += s12 * 470296;
452172c33676SMaxim Ag   s2 += s12 * 654183;
452272c33676SMaxim Ag   s3 -= s12 * 997805;
452372c33676SMaxim Ag   s4 += s12 * 136657;
452472c33676SMaxim Ag   s5 -= s12 * 683901;
452572c33676SMaxim Ag   s12 = 0;
452672c33676SMaxim Ag 
452772c33676SMaxim Ag   carry0 = s0 >> 21;
452872c33676SMaxim Ag   s1 += carry0;
452972c33676SMaxim Ag   s0 -= carry0 << 21;
453072c33676SMaxim Ag   carry1 = s1 >> 21;
453172c33676SMaxim Ag   s2 += carry1;
453272c33676SMaxim Ag   s1 -= carry1 << 21;
453372c33676SMaxim Ag   carry2 = s2 >> 21;
453472c33676SMaxim Ag   s3 += carry2;
453572c33676SMaxim Ag   s2 -= carry2 << 21;
453672c33676SMaxim Ag   carry3 = s3 >> 21;
453772c33676SMaxim Ag   s4 += carry3;
453872c33676SMaxim Ag   s3 -= carry3 << 21;
453972c33676SMaxim Ag   carry4 = s4 >> 21;
454072c33676SMaxim Ag   s5 += carry4;
454172c33676SMaxim Ag   s4 -= carry4 << 21;
454272c33676SMaxim Ag   carry5 = s5 >> 21;
454372c33676SMaxim Ag   s6 += carry5;
454472c33676SMaxim Ag   s5 -= carry5 << 21;
454572c33676SMaxim Ag   carry6 = s6 >> 21;
454672c33676SMaxim Ag   s7 += carry6;
454772c33676SMaxim Ag   s6 -= carry6 << 21;
454872c33676SMaxim Ag   carry7 = s7 >> 21;
454972c33676SMaxim Ag   s8 += carry7;
455072c33676SMaxim Ag   s7 -= carry7 << 21;
455172c33676SMaxim Ag   carry8 = s8 >> 21;
455272c33676SMaxim Ag   s9 += carry8;
455372c33676SMaxim Ag   s8 -= carry8 << 21;
455472c33676SMaxim Ag   carry9 = s9 >> 21;
455572c33676SMaxim Ag   s10 += carry9;
455672c33676SMaxim Ag   s9 -= carry9 << 21;
455772c33676SMaxim Ag   carry10 = s10 >> 21;
455872c33676SMaxim Ag   s11 += carry10;
455972c33676SMaxim Ag   s10 -= carry10 << 21;
456072c33676SMaxim Ag   carry11 = s11 >> 21;
456172c33676SMaxim Ag   s12 += carry11;
456272c33676SMaxim Ag   s11 -= carry11 << 21;
456372c33676SMaxim Ag 
456472c33676SMaxim Ag   s0 += s12 * 666643;
456572c33676SMaxim Ag   s1 += s12 * 470296;
456672c33676SMaxim Ag   s2 += s12 * 654183;
456772c33676SMaxim Ag   s3 -= s12 * 997805;
456872c33676SMaxim Ag   s4 += s12 * 136657;
456972c33676SMaxim Ag   s5 -= s12 * 683901;
457072c33676SMaxim Ag   s12 = 0;
457172c33676SMaxim Ag 
457272c33676SMaxim Ag   carry0 = s0 >> 21;
457372c33676SMaxim Ag   s1 += carry0;
457472c33676SMaxim Ag   s0 -= carry0 << 21;
457572c33676SMaxim Ag   carry1 = s1 >> 21;
457672c33676SMaxim Ag   s2 += carry1;
457772c33676SMaxim Ag   s1 -= carry1 << 21;
457872c33676SMaxim Ag   carry2 = s2 >> 21;
457972c33676SMaxim Ag   s3 += carry2;
458072c33676SMaxim Ag   s2 -= carry2 << 21;
458172c33676SMaxim Ag   carry3 = s3 >> 21;
458272c33676SMaxim Ag   s4 += carry3;
458372c33676SMaxim Ag   s3 -= carry3 << 21;
458472c33676SMaxim Ag   carry4 = s4 >> 21;
458572c33676SMaxim Ag   s5 += carry4;
458672c33676SMaxim Ag   s4 -= carry4 << 21;
458772c33676SMaxim Ag   carry5 = s5 >> 21;
458872c33676SMaxim Ag   s6 += carry5;
458972c33676SMaxim Ag   s5 -= carry5 << 21;
459072c33676SMaxim Ag   carry6 = s6 >> 21;
459172c33676SMaxim Ag   s7 += carry6;
459272c33676SMaxim Ag   s6 -= carry6 << 21;
459372c33676SMaxim Ag   carry7 = s7 >> 21;
459472c33676SMaxim Ag   s8 += carry7;
459572c33676SMaxim Ag   s7 -= carry7 << 21;
459672c33676SMaxim Ag   carry8 = s8 >> 21;
459772c33676SMaxim Ag   s9 += carry8;
459872c33676SMaxim Ag   s8 -= carry8 << 21;
459972c33676SMaxim Ag   carry9 = s9 >> 21;
460072c33676SMaxim Ag   s10 += carry9;
460172c33676SMaxim Ag   s9 -= carry9 << 21;
460272c33676SMaxim Ag   carry10 = s10 >> 21;
460372c33676SMaxim Ag   s11 += carry10;
460472c33676SMaxim Ag   s10 -= carry10 << 21;
460572c33676SMaxim Ag 
460672c33676SMaxim Ag   s[0] = s0 >> 0;
460772c33676SMaxim Ag   s[1] = s0 >> 8;
460872c33676SMaxim Ag   s[2] = (s0 >> 16) | (s1 << 5);
460972c33676SMaxim Ag   s[3] = s1 >> 3;
461072c33676SMaxim Ag   s[4] = s1 >> 11;
461172c33676SMaxim Ag   s[5] = (s1 >> 19) | (s2 << 2);
461272c33676SMaxim Ag   s[6] = s2 >> 6;
461372c33676SMaxim Ag   s[7] = (s2 >> 14) | (s3 << 7);
461472c33676SMaxim Ag   s[8] = s3 >> 1;
461572c33676SMaxim Ag   s[9] = s3 >> 9;
461672c33676SMaxim Ag   s[10] = (s3 >> 17) | (s4 << 4);
461772c33676SMaxim Ag   s[11] = s4 >> 4;
461872c33676SMaxim Ag   s[12] = s4 >> 12;
461972c33676SMaxim Ag   s[13] = (s4 >> 20) | (s5 << 1);
462072c33676SMaxim Ag   s[14] = s5 >> 7;
462172c33676SMaxim Ag   s[15] = (s5 >> 15) | (s6 << 6);
462272c33676SMaxim Ag   s[16] = s6 >> 2;
462372c33676SMaxim Ag   s[17] = s6 >> 10;
462472c33676SMaxim Ag   s[18] = (s6 >> 18) | (s7 << 3);
462572c33676SMaxim Ag   s[19] = s7 >> 5;
462672c33676SMaxim Ag   s[20] = s7 >> 13;
462772c33676SMaxim Ag   s[21] = s8 >> 0;
462872c33676SMaxim Ag   s[22] = s8 >> 8;
462972c33676SMaxim Ag   s[23] = (s8 >> 16) | (s9 << 5);
463072c33676SMaxim Ag   s[24] = s9 >> 3;
463172c33676SMaxim Ag   s[25] = s9 >> 11;
463272c33676SMaxim Ag   s[26] = (s9 >> 19) | (s10 << 2);
463372c33676SMaxim Ag   s[27] = s10 >> 6;
463472c33676SMaxim Ag   s[28] = (s10 >> 14) | (s11 << 7);
463572c33676SMaxim Ag   s[29] = s11 >> 1;
463672c33676SMaxim Ag   s[30] = s11 >> 9;
463772c33676SMaxim Ag   s[31] = s11 >> 17;
463872c33676SMaxim Ag }
463972c33676SMaxim Ag #endif
464072c33676SMaxim Ag 
464172c33676SMaxim Ag #ifdef ED25519
ED25519_keypair(uint8_t out_public_key[32],uint8_t out_private_key[64])464272c33676SMaxim Ag void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) {
464372c33676SMaxim Ag   uint8_t seed[32];
464472c33676SMaxim Ag   arc4random_buf(seed, 32);
464572c33676SMaxim Ag 
464672c33676SMaxim Ag   uint8_t az[SHA512_DIGEST_LENGTH];
464772c33676SMaxim Ag   SHA512(seed, 32, az);
464872c33676SMaxim Ag 
464972c33676SMaxim Ag   az[0] &= 248;
465072c33676SMaxim Ag   az[31] &= 63;
465172c33676SMaxim Ag   az[31] |= 64;
465272c33676SMaxim Ag 
465372c33676SMaxim Ag   ge_p3 A;
465472c33676SMaxim Ag   x25519_ge_scalarmult_base(&A, az);
465572c33676SMaxim Ag   ge_p3_tobytes(out_public_key, &A);
465672c33676SMaxim Ag 
465772c33676SMaxim Ag   memcpy(out_private_key, seed, 32);
465872c33676SMaxim Ag   memmove(out_private_key + 32, out_public_key, 32);
465972c33676SMaxim Ag }
466072c33676SMaxim Ag 
ED25519_sign(uint8_t * out_sig,const uint8_t * message,size_t message_len,const uint8_t private_key[64])466172c33676SMaxim Ag int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
466272c33676SMaxim Ag                  const uint8_t private_key[64]) {
466372c33676SMaxim Ag   uint8_t az[SHA512_DIGEST_LENGTH];
466472c33676SMaxim Ag   SHA512(private_key, 32, az);
466572c33676SMaxim Ag 
466672c33676SMaxim Ag   az[0] &= 248;
466772c33676SMaxim Ag   az[31] &= 63;
466872c33676SMaxim Ag   az[31] |= 64;
466972c33676SMaxim Ag 
467072c33676SMaxim Ag   SHA512_CTX hash_ctx;
467172c33676SMaxim Ag   SHA512_Init(&hash_ctx);
467272c33676SMaxim Ag   SHA512_Update(&hash_ctx, az + 32, 32);
467372c33676SMaxim Ag   SHA512_Update(&hash_ctx, message, message_len);
467472c33676SMaxim Ag   uint8_t nonce[SHA512_DIGEST_LENGTH];
467572c33676SMaxim Ag   SHA512_Final(nonce, &hash_ctx);
467672c33676SMaxim Ag 
467772c33676SMaxim Ag   x25519_sc_reduce(nonce);
467872c33676SMaxim Ag   ge_p3 R;
467972c33676SMaxim Ag   x25519_ge_scalarmult_base(&R, nonce);
468072c33676SMaxim Ag   ge_p3_tobytes(out_sig, &R);
468172c33676SMaxim Ag 
468272c33676SMaxim Ag   SHA512_Init(&hash_ctx);
468372c33676SMaxim Ag   SHA512_Update(&hash_ctx, out_sig, 32);
468472c33676SMaxim Ag   SHA512_Update(&hash_ctx, private_key + 32, 32);
468572c33676SMaxim Ag   SHA512_Update(&hash_ctx, message, message_len);
468672c33676SMaxim Ag   uint8_t hram[SHA512_DIGEST_LENGTH];
468772c33676SMaxim Ag   SHA512_Final(hram, &hash_ctx);
468872c33676SMaxim Ag 
468972c33676SMaxim Ag   x25519_sc_reduce(hram);
469072c33676SMaxim Ag   sc_muladd(out_sig + 32, hram, az, nonce);
469172c33676SMaxim Ag 
469272c33676SMaxim Ag   return 1;
469372c33676SMaxim Ag }
469472c33676SMaxim Ag 
ED25519_verify(const uint8_t * message,size_t message_len,const uint8_t signature[64],const uint8_t public_key[32])469572c33676SMaxim Ag int ED25519_verify(const uint8_t *message, size_t message_len,
469672c33676SMaxim Ag                    const uint8_t signature[64], const uint8_t public_key[32]) {
469772c33676SMaxim Ag   ge_p3 A;
469872c33676SMaxim Ag   if ((signature[63] & 224) != 0 ||
469972c33676SMaxim Ag       x25519_ge_frombytes_vartime(&A, public_key) != 0) {
470072c33676SMaxim Ag     return 0;
470172c33676SMaxim Ag   }
470272c33676SMaxim Ag 
470372c33676SMaxim Ag   fe_neg(A.X, A.X);
470472c33676SMaxim Ag   fe_neg(A.T, A.T);
470572c33676SMaxim Ag 
470672c33676SMaxim Ag   uint8_t pkcopy[32];
470772c33676SMaxim Ag   memcpy(pkcopy, public_key, 32);
470872c33676SMaxim Ag   uint8_t rcopy[32];
470972c33676SMaxim Ag   memcpy(rcopy, signature, 32);
471072c33676SMaxim Ag   uint8_t scopy[32];
471172c33676SMaxim Ag   memcpy(scopy, signature + 32, 32);
471272c33676SMaxim Ag 
471372c33676SMaxim Ag   SHA512_CTX hash_ctx;
471472c33676SMaxim Ag   SHA512_Init(&hash_ctx);
471572c33676SMaxim Ag   SHA512_Update(&hash_ctx, signature, 32);
471672c33676SMaxim Ag   SHA512_Update(&hash_ctx, public_key, 32);
471772c33676SMaxim Ag   SHA512_Update(&hash_ctx, message, message_len);
471872c33676SMaxim Ag   uint8_t h[SHA512_DIGEST_LENGTH];
471972c33676SMaxim Ag   SHA512_Final(h, &hash_ctx);
472072c33676SMaxim Ag 
472172c33676SMaxim Ag   x25519_sc_reduce(h);
472272c33676SMaxim Ag 
472372c33676SMaxim Ag   ge_p2 R;
472472c33676SMaxim Ag   ge_double_scalarmult_vartime(&R, h, &A, scopy);
472572c33676SMaxim Ag 
472672c33676SMaxim Ag   uint8_t rcheck[32];
472772c33676SMaxim Ag   x25519_ge_tobytes(rcheck, &R);
472872c33676SMaxim Ag 
472972c33676SMaxim Ag   return timingsafe_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
473072c33676SMaxim Ag }
473172c33676SMaxim Ag #endif
473272c33676SMaxim Ag 
473372c33676SMaxim Ag /* Replace (f,g) with (g,f) if b == 1;
473472c33676SMaxim Ag  * replace (f,g) with (f,g) if b == 0.
473572c33676SMaxim Ag  *
473672c33676SMaxim Ag  * Preconditions: b in {0,1}. */
fe_cswap(fe f,fe g,unsigned int b)473772c33676SMaxim Ag static void fe_cswap(fe f, fe g, unsigned int b) {
473872c33676SMaxim Ag   b = 0-b;
473972c33676SMaxim Ag   unsigned i;
474072c33676SMaxim Ag   for (i = 0; i < 10; i++) {
474172c33676SMaxim Ag     int32_t x = f[i] ^ g[i];
474272c33676SMaxim Ag     x &= b;
474372c33676SMaxim Ag     f[i] ^= x;
474472c33676SMaxim Ag     g[i] ^= x;
474572c33676SMaxim Ag   }
474672c33676SMaxim Ag }
474772c33676SMaxim Ag 
474872c33676SMaxim Ag /* h = f * 121666
474972c33676SMaxim Ag  * Can overlap h with f.
475072c33676SMaxim Ag  *
475172c33676SMaxim Ag  * Preconditions:
475272c33676SMaxim Ag  *    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
475372c33676SMaxim Ag  *
475472c33676SMaxim Ag  * Postconditions:
475572c33676SMaxim Ag  *    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. */
fe_mul121666(fe h,fe f)475672c33676SMaxim Ag static void fe_mul121666(fe h, fe f) {
475772c33676SMaxim Ag   int32_t f0 = f[0];
475872c33676SMaxim Ag   int32_t f1 = f[1];
475972c33676SMaxim Ag   int32_t f2 = f[2];
476072c33676SMaxim Ag   int32_t f3 = f[3];
476172c33676SMaxim Ag   int32_t f4 = f[4];
476272c33676SMaxim Ag   int32_t f5 = f[5];
476372c33676SMaxim Ag   int32_t f6 = f[6];
476472c33676SMaxim Ag   int32_t f7 = f[7];
476572c33676SMaxim Ag   int32_t f8 = f[8];
476672c33676SMaxim Ag   int32_t f9 = f[9];
476772c33676SMaxim Ag   int64_t h0 = f0 * (int64_t) 121666;
476872c33676SMaxim Ag   int64_t h1 = f1 * (int64_t) 121666;
476972c33676SMaxim Ag   int64_t h2 = f2 * (int64_t) 121666;
477072c33676SMaxim Ag   int64_t h3 = f3 * (int64_t) 121666;
477172c33676SMaxim Ag   int64_t h4 = f4 * (int64_t) 121666;
477272c33676SMaxim Ag   int64_t h5 = f5 * (int64_t) 121666;
477372c33676SMaxim Ag   int64_t h6 = f6 * (int64_t) 121666;
477472c33676SMaxim Ag   int64_t h7 = f7 * (int64_t) 121666;
477572c33676SMaxim Ag   int64_t h8 = f8 * (int64_t) 121666;
477672c33676SMaxim Ag   int64_t h9 = f9 * (int64_t) 121666;
477772c33676SMaxim Ag   int64_t carry0;
477872c33676SMaxim Ag   int64_t carry1;
477972c33676SMaxim Ag   int64_t carry2;
478072c33676SMaxim Ag   int64_t carry3;
478172c33676SMaxim Ag   int64_t carry4;
478272c33676SMaxim Ag   int64_t carry5;
478372c33676SMaxim Ag   int64_t carry6;
478472c33676SMaxim Ag   int64_t carry7;
478572c33676SMaxim Ag   int64_t carry8;
478672c33676SMaxim Ag   int64_t carry9;
478772c33676SMaxim Ag 
478872c33676SMaxim Ag   carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
478972c33676SMaxim Ag   carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
479072c33676SMaxim Ag   carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
479172c33676SMaxim Ag   carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
479272c33676SMaxim Ag   carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
479372c33676SMaxim Ag 
479472c33676SMaxim Ag   carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
479572c33676SMaxim Ag   carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
479672c33676SMaxim Ag   carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
479772c33676SMaxim Ag   carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
479872c33676SMaxim Ag   carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
479972c33676SMaxim Ag 
480072c33676SMaxim Ag   h[0] = h0;
480172c33676SMaxim Ag   h[1] = h1;
480272c33676SMaxim Ag   h[2] = h2;
480372c33676SMaxim Ag   h[3] = h3;
480472c33676SMaxim Ag   h[4] = h4;
480572c33676SMaxim Ag   h[5] = h5;
480672c33676SMaxim Ag   h[6] = h6;
480772c33676SMaxim Ag   h[7] = h7;
480872c33676SMaxim Ag   h[8] = h8;
480972c33676SMaxim Ag   h[9] = h9;
481072c33676SMaxim Ag }
481172c33676SMaxim Ag 
481272c33676SMaxim Ag void
x25519_scalar_mult_generic(uint8_t out[32],const uint8_t scalar[32],const uint8_t point[32])481372c33676SMaxim Ag x25519_scalar_mult_generic(uint8_t out[32], const uint8_t scalar[32],
481472c33676SMaxim Ag     const uint8_t point[32]) {
481572c33676SMaxim Ag   fe x1, x2, z2, x3, z3, tmp0, tmp1;
481672c33676SMaxim Ag 
481772c33676SMaxim Ag   uint8_t e[32];
481872c33676SMaxim Ag   memcpy(e, scalar, 32);
481972c33676SMaxim Ag   e[0] &= 248;
482072c33676SMaxim Ag   e[31] &= 127;
482172c33676SMaxim Ag   e[31] |= 64;
482272c33676SMaxim Ag   fe_frombytes(x1, point);
482372c33676SMaxim Ag   fe_1(x2);
482472c33676SMaxim Ag   fe_0(z2);
482572c33676SMaxim Ag   fe_copy(x3, x1);
482672c33676SMaxim Ag   fe_1(z3);
482772c33676SMaxim Ag 
482872c33676SMaxim Ag   unsigned swap = 0;
482972c33676SMaxim Ag   int pos;
483072c33676SMaxim Ag   for (pos = 254; pos >= 0; --pos) {
483172c33676SMaxim Ag     unsigned b = 1 & (e[pos / 8] >> (pos & 7));
483272c33676SMaxim Ag     swap ^= b;
483372c33676SMaxim Ag     fe_cswap(x2, x3, swap);
483472c33676SMaxim Ag     fe_cswap(z2, z3, swap);
483572c33676SMaxim Ag     swap = b;
483672c33676SMaxim Ag     fe_sub(tmp0, x3, z3);
483772c33676SMaxim Ag     fe_sub(tmp1, x2, z2);
483872c33676SMaxim Ag     fe_add(x2, x2, z2);
483972c33676SMaxim Ag     fe_add(z2, x3, z3);
484072c33676SMaxim Ag     fe_mul(z3, tmp0, x2);
484172c33676SMaxim Ag     fe_mul(z2, z2, tmp1);
484272c33676SMaxim Ag     fe_sq(tmp0, tmp1);
484372c33676SMaxim Ag     fe_sq(tmp1, x2);
484472c33676SMaxim Ag     fe_add(x3, z3, z2);
484572c33676SMaxim Ag     fe_sub(z2, z3, z2);
484672c33676SMaxim Ag     fe_mul(x2, tmp1, tmp0);
484772c33676SMaxim Ag     fe_sub(tmp1, tmp1, tmp0);
484872c33676SMaxim Ag     fe_sq(z2, z2);
484972c33676SMaxim Ag     fe_mul121666(z3, tmp1);
485072c33676SMaxim Ag     fe_sq(x3, x3);
485172c33676SMaxim Ag     fe_add(tmp0, tmp0, z3);
485272c33676SMaxim Ag     fe_mul(z3, x1, z2);
485372c33676SMaxim Ag     fe_mul(z2, tmp1, tmp0);
485472c33676SMaxim Ag   }
485572c33676SMaxim Ag   fe_cswap(x2, x3, swap);
485672c33676SMaxim Ag   fe_cswap(z2, z3, swap);
485772c33676SMaxim Ag 
485872c33676SMaxim Ag   fe_invert(z2, z2);
485972c33676SMaxim Ag   fe_mul(x2, x2, z2);
486072c33676SMaxim Ag   fe_tobytes(out, x2);
486172c33676SMaxim Ag }
486272c33676SMaxim Ag 
486372c33676SMaxim Ag #ifdef unused
486472c33676SMaxim Ag void
x25519_public_from_private_generic(uint8_t out_public_value[32],const uint8_t private_key[32])486572c33676SMaxim Ag x25519_public_from_private_generic(uint8_t out_public_value[32],
486672c33676SMaxim Ag     const uint8_t private_key[32])
486772c33676SMaxim Ag {
486872c33676SMaxim Ag   uint8_t e[32];
486972c33676SMaxim Ag 
487072c33676SMaxim Ag   memcpy(e, private_key, 32);
487172c33676SMaxim Ag   e[0] &= 248;
487272c33676SMaxim Ag   e[31] &= 127;
487372c33676SMaxim Ag   e[31] |= 64;
487472c33676SMaxim Ag 
487572c33676SMaxim Ag   ge_p3 A;
487672c33676SMaxim Ag   x25519_ge_scalarmult_base(&A, e);
487772c33676SMaxim Ag 
487872c33676SMaxim Ag   /* We only need the u-coordinate of the curve25519 point. The map is
487972c33676SMaxim Ag    * u=(y+1)/(1-y). Since y=Y/Z, this gives u=(Z+Y)/(Z-Y). */
488072c33676SMaxim Ag   fe zplusy, zminusy, zminusy_inv;
488172c33676SMaxim Ag   fe_add(zplusy, A.Z, A.Y);
488272c33676SMaxim Ag   fe_sub(zminusy, A.Z, A.Y);
488372c33676SMaxim Ag   fe_invert(zminusy_inv, zminusy);
488472c33676SMaxim Ag   fe_mul(zplusy, zplusy, zminusy_inv);
488572c33676SMaxim Ag   fe_tobytes(out_public_value, zplusy);
488672c33676SMaxim Ag }
488772c33676SMaxim Ag #endif
488872c33676SMaxim Ag 
488972c33676SMaxim Ag void
x25519_public_from_private(uint8_t out_public_value[32],const uint8_t private_key[32])489072c33676SMaxim Ag x25519_public_from_private(uint8_t out_public_value[32],
489172c33676SMaxim Ag     const uint8_t private_key[32])
489272c33676SMaxim Ag {
489372c33676SMaxim Ag   static const uint8_t kMongomeryBasePoint[32] = {9};
489472c33676SMaxim Ag 
489572c33676SMaxim Ag   x25519_scalar_mult(out_public_value, private_key, kMongomeryBasePoint);
489672c33676SMaxim Ag }
489772c33676SMaxim Ag 
489872c33676SMaxim Ag void
X25519_keypair(uint8_t out_public_value[X25519_KEY_LENGTH],uint8_t out_private_key[X25519_KEY_LENGTH])489972c33676SMaxim Ag X25519_keypair(uint8_t out_public_value[X25519_KEY_LENGTH],
490072c33676SMaxim Ag     uint8_t out_private_key[X25519_KEY_LENGTH])
490172c33676SMaxim Ag {
490272c33676SMaxim Ag   /* All X25519 implementations should decode scalars correctly (see
490372c33676SMaxim Ag    * https://tools.ietf.org/html/rfc7748#section-5). However, if an
490472c33676SMaxim Ag    * implementation doesn't then it might interoperate with random keys a
490572c33676SMaxim Ag    * fraction of the time because they'll, randomly, happen to be correctly
490672c33676SMaxim Ag    * formed.
490772c33676SMaxim Ag    *
490872c33676SMaxim Ag    * Thus we do the opposite of the masking here to make sure that our private
490972c33676SMaxim Ag    * keys are never correctly masked and so, hopefully, any incorrect
491072c33676SMaxim Ag    * implementations are deterministically broken.
491172c33676SMaxim Ag    *
491272c33676SMaxim Ag    * This does not affect security because, although we're throwing away
491372c33676SMaxim Ag    * entropy, a valid implementation of scalarmult should throw away the exact
491472c33676SMaxim Ag    * same bits anyway. */
491572c33676SMaxim Ag   arc4random_buf(out_private_key, 32);
491672c33676SMaxim Ag 
491772c33676SMaxim Ag   out_private_key[0] |= 7;
491872c33676SMaxim Ag   out_private_key[31] &= 63;
491972c33676SMaxim Ag   out_private_key[31] |= 128;
492072c33676SMaxim Ag 
492172c33676SMaxim Ag   x25519_public_from_private(out_public_value, out_private_key);
492272c33676SMaxim Ag }
492372c33676SMaxim Ag 
492472c33676SMaxim Ag int
X25519(uint8_t out_shared_key[X25519_KEY_LENGTH],const uint8_t private_key[X25519_KEY_LENGTH],const uint8_t peer_public_value[X25519_KEY_LENGTH])492572c33676SMaxim Ag X25519(uint8_t out_shared_key[X25519_KEY_LENGTH],
492672c33676SMaxim Ag     const uint8_t private_key[X25519_KEY_LENGTH],
492772c33676SMaxim Ag     const uint8_t peer_public_value[X25519_KEY_LENGTH])
492872c33676SMaxim Ag {
492972c33676SMaxim Ag   static const uint8_t kZeros[32] = {0};
493072c33676SMaxim Ag 
493172c33676SMaxim Ag   x25519_scalar_mult(out_shared_key, private_key, peer_public_value);
493272c33676SMaxim Ag 
493372c33676SMaxim Ag   /* The all-zero output results when the input is a point of small order. */
493472c33676SMaxim Ag   return timingsafe_memcmp(kZeros, out_shared_key, 32) != 0;
493572c33676SMaxim Ag }
4936