xref: /third_party/ffmpeg/libavcodec/h274.c (revision cabdff1a)
1/*
2 * H.274 film grain synthesis
3 * Copyright (c) 2021 Niklas Haas <ffmpeg@haasn.xyz>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22/**
23 * @file
24 * H.274 film grain synthesis.
25 * @author Niklas Haas <ffmpeg@haasn.xyz>
26 */
27
28#include "libavutil/avassert.h"
29#include "libavutil/imgutils.h"
30
31#include "h274.h"
32
33static const int8_t Gaussian_LUT[2048+4];
34static const uint32_t Seed_LUT[256];
35static const int8_t R64T[64][64];
36
37static void prng_shift(uint32_t *state)
38{
39    // Primitive polynomial x^31 + x^3 + 1 (modulo 2)
40    uint32_t x = *state;
41    uint8_t feedback = (x >> 2) ^ (x >> 30);
42    *state = (x << 1) | (feedback & 1u);
43}
44
45static void init_slice_c(int8_t out[64][64], uint8_t h, uint8_t v,
46                         int16_t tmp[64][64])
47{
48    static const uint8_t deblock_factors[13] = {
49        64, 71, 77, 84, 90, 96, 103, 109, 116, 122, 128, 128, 128
50    };
51
52    const uint8_t deblock_coeff = deblock_factors[v];
53    const uint8_t freq_h = ((h + 3) << 2) - 1;
54    const uint8_t freq_v = ((v + 3) << 2) - 1;
55    uint32_t seed = Seed_LUT[h + v * 13];
56
57    // Initialize with random gaussian values, using the output array as a
58    // temporary buffer for these intermediate values.
59    //
60    // Note: To make the subsequent matrix multiplication cache friendlier, we
61    // store each *column* of the starting image in a *row* of `out`
62    for (int y = 0; y <= freq_v; y++) {
63        for (int x = 0; x <= freq_h; x += 4) {
64            uint16_t offset = seed % 2048;
65            out[x + 0][y] = Gaussian_LUT[offset + 0];
66            out[x + 1][y] = Gaussian_LUT[offset + 1];
67            out[x + 2][y] = Gaussian_LUT[offset + 2];
68            out[x + 3][y] = Gaussian_LUT[offset + 3];
69            prng_shift(&seed);
70        }
71    }
72
73    out[0][0] = 0;
74
75    // 64x64 inverse integer transform
76    for (int y = 0; y < 64; y++) {
77        for (int x = 0; x <= freq_h; x++) {
78            int32_t sum = 0;
79            for (int p = 0; p <= freq_v; p++)
80                sum += R64T[y][p] * out[x][p];
81            tmp[y][x] = (sum + 128) >> 8;
82        }
83    }
84
85    for (int y = 0; y < 64; y++) {
86        for (int x = 0; x < 64; x++) {
87            int32_t sum = 0;
88            for (int p = 0; p <= freq_h; p++)
89                sum += tmp[y][p] * R64T[x][p]; // R64T^T = R64
90            // Renormalize and clip to [-127, 127]
91            out[y][x] = av_clip((sum + 128) >> 8, -127, 127);
92        }
93    }
94
95    // Deblock horizontal edges by simple attentuation of values
96    for (int y = 0; y < 64; y += 8) {
97        for (int x = 0; x < 64; x++) {
98            out[y + 0][x] = (out[y + 0][x] * deblock_coeff) >> 7;
99            out[y + 7][x] = (out[y + 7][x] * deblock_coeff) >> 7;
100        }
101    }
102}
103
104static void init_slice(H274FilmGrainDatabase *database, uint8_t h, uint8_t v)
105{
106    if (database->residency[h] & (1 << v))
107        return;
108
109    database->residency[h] |= (1 << v);
110    init_slice_c(database->db[h][v], h, v, database->slice_tmp);
111}
112
113// Computes the average of an 8x8 block, right-shifted by 6
114static uint16_t avg_8x8_c(const uint8_t *in, int in_stride)
115{
116    uint16_t avg[8] = {0}; // summing over an array vectorizes better
117
118    for (int y = 0; y < 8; y++) {
119        for (int x = 0; x < 8; x++)
120            avg[x] += in[x];
121        in += in_stride;
122    }
123
124    return (avg[0] + avg[1] + avg[2] + avg[3] +
125            avg[4] + avg[5] + avg[6] + avg[7]) >> 6;
126}
127
128// Synthesize an 8x8 block of film grain by copying the pattern from `db`
129static void synth_grain_8x8_c(int8_t *out, const int out_stride,
130                              const int16_t scale, const uint8_t shift,
131                              const int8_t *db)
132{
133    for (int y = 0; y < 8; y++) {
134        for (int x = 0; x < 8; x++)
135            out[x] = (scale * db[x]) >> shift;
136
137        out += out_stride;
138        db += 64;
139    }
140}
141
142// Deblock vertical edges of an 8x8 block, mixing with the previous block
143static void deblock_8x8_c(int8_t *out, const int out_stride)
144{
145    for (int y = 0; y < 8; y++) {
146        const int8_t l1 = out[-2], l0 = out[-1];
147        const int8_t r0 = out[0], r1 = out[1];
148        out[0]  = (l0 + r0 * 2 + r1) >> 2;
149        out[-1] = (r0 + l0 * 2 + l1) >> 2;
150        out += out_stride;
151    }
152}
153
154// Generates a single 8x8 block of grain, optionally also applying the
155// deblocking step (note that this implies writing to the previous block).
156static av_always_inline void generate(int8_t *out, int out_stride,
157                                      const uint8_t *in, int in_stride,
158                                      H274FilmGrainDatabase *database,
159                                      const AVFilmGrainH274Params *h274,
160                                      int c, int invert, int deblock,
161                                      int y_offset, int x_offset)
162{
163    const uint8_t shift = h274->log2_scale_factor + 6;
164    const uint16_t avg = avg_8x8_c(in, in_stride);
165    int16_t scale;
166    uint8_t h, v;
167    int8_t s = -1;
168
169    // FIXME: This logic only generates grain with a single
170    // intensity interval. Strictly speaking, the H.274 specification allows
171    // for overlapping intensity intervals, however SMPTE RDD 5-2006 (which
172    // concerns the implementation of H.274 for H.264) forbids this as it
173    // requires a nontrivial grain synthesis process (FFT).
174    //
175    // In principle, we should detect this possibility ahead of time and warn
176    // the user that the output is unlikely to be correct, or alternatively
177    // return an AVERROR_PATCHWELCOME.
178    for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
179        if (avg >= h274->intensity_interval_lower_bound[c][i] &&
180            avg <= h274->intensity_interval_upper_bound[c][i])
181        {
182            s = i;
183            break;
184        }
185    }
186
187    if (s < 0) {
188        // No matching intensity interval, synthesize blank film grain
189        for (int y = 0; y < 8; y++)
190            memset(out + y * out_stride, 0, sizeof(int8_t[8]));
191        return;
192    }
193
194    h = av_clip(h274->comp_model_value[c][s][1], 2, 14) - 2;
195    v = av_clip(h274->comp_model_value[c][s][2], 2, 14) - 2;
196    init_slice(database, h, v);
197
198    scale = h274->comp_model_value[c][s][0];
199    if (invert)
200        scale = -scale;
201
202    synth_grain_8x8_c(out, out_stride, scale, shift,
203                      &database->db[h][v][y_offset][x_offset]);
204
205    if (deblock)
206        deblock_8x8_c(out, out_stride);
207}
208
209// Saturating 8-bit sum of a+b
210static void add_8x8_clip_c(uint8_t *out, const uint8_t *a, const int8_t *b,
211                           int n)
212{
213    for (int i = 0; i < n; i++)
214        out[i] = av_clip_uint8(a[i] + b[i]);
215}
216
217int ff_h274_apply_film_grain(AVFrame *out_frame, const AVFrame *in_frame,
218                             H274FilmGrainDatabase *database,
219                             const AVFilmGrainParams *params)
220{
221    AVFilmGrainH274Params h274 = params->codec.h274;
222    av_assert1(params->type == AV_FILM_GRAIN_PARAMS_H274);
223    if (h274.model_id != 0)
224        return AVERROR_PATCHWELCOME;
225
226    av_assert1(out_frame->format == in_frame->format);
227    if (in_frame->format != AV_PIX_FMT_YUV420P)
228        return AVERROR_PATCHWELCOME;
229
230    for (int c = 0; c < 3; c++) {
231        static const uint8_t color_offset[3] = { 0, 85, 170 };
232        uint32_t seed = Seed_LUT[(params->seed + color_offset[c]) % 256];
233        const int width = c > 0 ? AV_CEIL_RSHIFT(out_frame->width, 1) : out_frame->width;
234        const int height = c > 0 ? AV_CEIL_RSHIFT(out_frame->height, 1) : out_frame->height;
235
236        uint8_t * const out = out_frame->data[c];
237        const int out_stride = out_frame->linesize[c];
238        int8_t * const grain = out_frame->data[c]; // re-use output buffer for grain
239        const int grain_stride = out_stride;
240        const uint8_t * const in = in_frame->data[c];
241        const int in_stride = in_frame->linesize[c];
242
243        if (!h274.component_model_present[c]) {
244            av_image_copy_plane(out, out_stride, in, in_stride,
245                                width * sizeof(uint8_t), height);
246            continue;
247        }
248
249        if (c > 0) {
250            // Adaptation for 4:2:0 chroma subsampling
251            for (int i = 0; i < h274.num_intensity_intervals[c]; i++) {
252                h274.comp_model_value[c][i][0] >>= 1;
253                h274.comp_model_value[c][i][1] *= 2;
254                h274.comp_model_value[c][i][2] *= 2;
255            }
256        }
257
258        // Film grain synthesis is done in 8x8 blocks, but the PRNG state is
259        // only advanced in 16x16 blocks, so use a nested loop
260        for (int y = 0; y < height; y += 16) {
261            for (int x = 0; x < width; x += 16) {
262                uint16_t y_offset = (seed >> 16) % 52;
263                uint16_t x_offset = (seed & 0xFFFF) % 56;
264                const int invert = (seed & 0x1);
265                y_offset &= 0xFFFC;
266                x_offset &= 0xFFF8;
267                prng_shift(&seed);
268
269                for (int yy = 0; yy < 16 && y+yy < height; yy += 8) {
270                    for (int xx = 0; xx < 16 && x+xx < width; xx += 8) {
271                        generate(grain + (y+yy) * grain_stride + (x+xx), grain_stride,
272                                 in + (y+yy) * in_stride + (x+xx), in_stride,
273                                 database, &h274, c, invert, (x+xx) > 0,
274                                 y_offset + yy, x_offset + xx);
275                    }
276                }
277            }
278        }
279
280        // Final output blend pass, done after grain synthesis is complete
281        // because deblocking depends on previous grain values
282        for (int y = 0; y < height; y++) {
283            add_8x8_clip_c(out + y * out_stride, in + y * in_stride,
284                           grain + y * grain_stride, width);
285        }
286    }
287
288    return 0;
289}
290
291// These tables are all taken from the SMPTE RDD 5-2006 specification
292static const int8_t Gaussian_LUT[2048+4] = {
293    -11, 12, 103, -11, 42, -35, 12, 59, 77, 98, -87, 3, 65, -78, 45, 56, -51, 21,
294    13, -11, -20, -19, 33, -127, 17, -6, -105, 18, 19, 71, 48, -10, -38, 42,
295    -2, 75, -67, 52, -90, 33, -47, 21, -3, -56, 49, 1, -57, -42, -1, 120, -127,
296    -108, -49, 9, 14, 127, 122, 109, 52, 127, 2, 7, 114, 19, 30, 12, 77, 112,
297    82, -61, -127, 111, -52, -29, 2, -49, -24, 58, -29, -73, 12, 112, 67, 79,
298    -3, -114, -87, -6, -5, 40, 58, -81, 49, -27, -31, -34, -105, 50, 16, -24,
299    -35, -14, -15, -127, -55, -22, -55, -127, -112, 5, -26, -72, 127, 127, -2,
300    41, 87, -65, -16, 55, 19, 91, -81, -65, -64, 35, -7, -54, 99, -7, 88, 125,
301    -26, 91, 0, 63, 60, -14, -23, 113, -33, 116, 14, 26, 51, -16, 107, -8, 53,
302    38, -34, 17, -7, 4, -91, 6, 63, 63, -15, 39, -36, 19, 55, 17, -51, 40, 33,
303    -37, 126, -39, -118, 17, -30, 0, 19, 98, 60, 101, -12, -73, -17, -52, 98,
304    3, 3, 60, 33, -3, -2, 10, -42, -106, -38, 14, 127, 16, -127, -31, -86, -39,
305    -56, 46, -41, 75, 23, -19, -22, -70, 74, -54, -2, 32, -45, 17, -92, 59,
306    -64, -67, 56, -102, -29, -87, -34, -92, 68, 5, -74, -61, 93, -43, 14, -26,
307    -38, -126, -17, 16, -127, 64, 34, 31, 93, 17, -51, -59, 71, 77, 81, 127,
308    127, 61, 33, -106, -93, 0, 0, 75, -69, 71, 127, -19, -111, 30, 23, 15, 2,
309    39, 92, 5, 42, 2, -6, 38, 15, 114, -30, -37, 50, 44, 106, 27, 119, 7, -80,
310    25, -68, -21, 92, -11, -1, 18, 41, -50, 79, -127, -43, 127, 18, 11, -21,
311    32, -52, 27, -88, -90, -39, -19, -10, 24, -118, 72, -24, -44, 2, 12, 86,
312    -107, 39, -33, -127, 47, 51, -24, -22, 46, 0, 15, -35, -69, -2, -74, 24,
313    -6, 0, 29, -3, 45, 32, -32, 117, -45, 79, -24, -17, -109, -10, -70, 88,
314    -48, 24, -91, 120, -37, 50, -127, 58, 32, -82, -10, -17, -7, 46, -127, -15,
315    89, 127, 17, 98, -39, -33, 37, 42, -40, -32, -21, 105, -19, 19, 19, -59,
316    -9, 30, 0, -127, 34, 127, -84, 75, 24, -40, -49, -127, -107, -14, 45, -75,
317    1, 30, -20, 41, -68, -40, 12, 127, -3, 5, 20, -73, -59, -127, -3, -3, -53,
318    -6, -119, 93, 120, -80, -50, 0, 20, -46, 67, 78, -12, -22, -127, 36, -41,
319    56, 119, -5, -116, -22, 68, -14, -90, 24, -82, -44, -127, 107, -25, -37,
320    40, -7, -7, -82, 5, -87, 44, -34, 9, -127, 39, 70, 49, -63, 74, -49, 109,
321    -27, -89, -47, -39, 44, 49, -4, 60, -42, 80, 9, -127, -9, -56, -49, 125,
322    -66, 47, 36, 117, 15, -11, -96, 109, 94, -17, -56, 70, 8, -14, -5, 50, 37,
323    -45, 120, -30, -76, 40, -46, 6, 3, 69, 17, -78, 1, -79, 6, 127, 43, 26,
324    127, -127, 28, -55, -26, 55, 112, 48, 107, -1, -77, -1, 53, -9, -22, -43,
325    123, 108, 127, 102, 68, 46, 5, 1, 123, -13, -55, -34, -49, 89, 65, -105,
326    -5, 94, -53, 62, 45, 30, 46, 18, -35, 15, 41, 47, -98, -24, 94, -75, 127,
327    -114, 127, -68, 1, -17, 51, -95, 47, 12, 34, -45, -75, 89, -107, -9, -58,
328    -29, -109, -24, 127, -61, -13, 77, -45, 17, 19, 83, -24, 9, 127, -66, 54,
329    4, 26, 13, 111, 43, -113, -22, 10, -24, 83, 67, -14, 75, -123, 59, 127,
330    -12, 99, -19, 64, -38, 54, 9, 7, 61, -56, 3, -57, 113, -104, -59, 3, -9,
331    -47, 74, 85, -55, -34, 12, 118, 28, 93, -72, 13, -99, -72, -20, 30, 72,
332    -94, 19, -54, 64, -12, -63, -25, 65, 72, -10, 127, 0, -127, 103, -20, -73,
333    -112, -103, -6, 28, -42, -21, -59, -29, -26, 19, -4, -51, 94, -58, -95,
334    -37, 35, 20, -69, 127, -19, -127, -22, -120, -53, 37, 74, -127, -1, -12,
335    -119, -53, -28, 38, 69, 17, 16, -114, 89, 62, 24, 37, -23, 49, -101, -32,
336    -9, -95, -53, 5, 93, -23, -49, -8, 51, 3, -75, -90, -10, -39, 127, -86,
337    -22, 20, 20, 113, 75, 52, -31, 92, -63, 7, -12, 46, 36, 101, -43, -17, -53,
338    -7, -38, -76, -31, -21, 62, 31, 62, 20, -127, 31, 64, 36, 102, -85, -10,
339    77, 80, 58, -79, -8, 35, 8, 80, -24, -9, 3, -17, 72, 127, 83, -87, 55, 18,
340    -119, -123, 36, 10, 127, 56, -55, 113, 13, 26, 32, -13, -48, 22, -13, 5,
341    58, 27, 24, 26, -11, -36, 37, -92, 78, 81, 9, 51, 14, 67, -13, 0, 32, 45,
342    -76, 32, -39, -22, -49, -127, -27, 31, -9, 36, 14, 71, 13, 57, 12, -53,
343    -86, 53, -44, -35, 2, 127, 12, -66, -44, 46, -115, 3, 10, 56, -35, 119,
344    -19, -61, 52, -59, -127, -49, -23, 4, -5, 17, -82, -6, 127, 25, 79, 67, 64,
345    -25, 14, -64, -37, -127, -28, 21, -63, 66, -53, -41, 109, -62, 15, -22, 13,
346    29, -63, 20, 27, 95, -44, -59, -116, -10, 79, -49, 22, -43, -16, 46, -47,
347    -120, -36, -29, -52, -44, 29, 127, -13, 49, -9, -127, 75, -28, -23, 88, 59,
348    11, -95, 81, -59, 58, 60, -26, 40, -92, -3, -22, -58, -45, -59, -22, -53,
349    71, -29, 66, -32, -23, 14, -17, -66, -24, -28, -62, 47, 38, 17, 16, -37,
350    -24, -11, 8, -27, -19, 59, 45, -49, -47, -4, -22, -81, 30, -67, -127, 74,
351    102, 5, -18, 98, 34, -66, 42, -52, 7, -59, 24, -58, -19, -24, -118, -73,
352    91, 15, -16, 79, -32, -79, -127, -36, 41, 77, -83, 2, 56, 22, -75, 127,
353    -16, -21, 12, 31, 56, -113, -127, 90, 55, 61, 12, 55, -14, -113, -14, 32,
354    49, -67, -17, 91, -10, 1, 21, 69, -70, 99, -19, -112, 66, -90, -10, -9,
355    -71, 127, 50, -81, -49, 24, 61, -61, -111, 7, -41, 127, 88, -66, 108, -127,
356    -6, 36, -14, 41, -50, 14, 14, 73, -101, -28, 77, 127, -8, -100, 88, 38,
357    121, 88, -125, -60, 13, -94, -115, 20, -67, -87, -94, -119, 44, -28, -30,
358    18, 5, -53, -61, 20, -43, 11, -77, -60, 13, 29, 3, 6, -72, 38, -60, -11,
359    108, -53, 41, 66, -12, -127, -127, -49, 24, 29, 46, 36, 91, 34, -33, 116,
360    -51, -34, -52, 91, 7, -83, 73, -26, -103, 24, -10, 76, 84, 5, 68, -80, -13,
361    -17, -32, -48, 20, 50, 26, 10, 63, -104, -14, 37, 127, 114, 97, 35, 1, -33,
362    -55, 127, -124, -33, 61, -7, 119, -32, -127, -53, -42, 63, 3, -5, -26, 70,
363    -58, -33, -44, -43, 34, -56, -127, 127, 25, -35, -11, 16, -81, 29, -58, 40,
364    -127, -127, 20, -47, -11, -36, -63, -52, -32, -82, 78, -76, -73, 8, 27,
365    -72, -9, -74, -85, -86, -57, 25, 78, -10, -97, 35, -65, 8, -59, 14, 1, -42,
366    32, -88, -44, 17, -3, -9, 59, 40, 12, -108, -40, 24, 34, 18, -28, 2, 51,
367    -110, -4, 100, 1, 65, 22, 0, 127, 61, 45, 25, -31, 6, 9, -7, -48, 99, 16,
368    44, -2, -40, 32, -39, -52, 10, -110, -19, 56, -127, 69, 26, 51, 92, 40, 61,
369    -52, 45, -38, 13, 85, 122, 27, 66, 45, -111, -83, -3, 31, 37, 19, -36, 58,
370    71, 39, -78, -47, 58, -78, 8, -62, -36, -14, 61, 42, -127, 71, -4, 24, -54,
371    52, -127, 67, -4, -42, 30, -63, 59, -3, -1, -18, -46, -92, -81, -96, -14,
372    -53, -10, -11, -77, 13, 1, 8, -67, -127, 127, -28, 26, -14, 18, -13, -26,
373    2, 10, -46, -32, -15, 27, -31, -59, 59, 77, -121, 28, 40, -54, -62, -31,
374    -21, -37, -32, -6, -127, -25, -60, 70, -127, 112, -127, 127, 88, -7, 116,
375    110, 53, 87, -127, 3, 16, 23, 74, -106, -51, 3, 74, -82, -112, -74, 65, 81,
376    25, 53, 127, -45, -50, -103, -41, -65, -29, 79, -67, 64, -33, -30, -8, 127,
377    0, -13, -51, 67, -14, 5, -92, 29, -35, -8, -90, -57, -3, 36, 43, 44, -31,
378    -69, -7, 36, 39, -51, 43, -81, 58, 6, 127, 12, 57, 66, 46, 59, -43, -42,
379    41, -15, -120, 24, 3, -11, 19, -13, 51, 28, 3, 55, -48, -12, -1, 2, 97,
380    -19, 29, 42, 13, 43, 78, -44, 56, -108, -43, -19, 127, 15, -11, -18, -81,
381    83, -37, 77, -109, 15, 65, -50, 43, 12, 13, 27, 28, 61, 57, 30, 26, 106,
382    -18, 56, 13, 97, 4, -8, -62, -103, 94, 108, -44, 52, 27, -47, -9, 105, -53,
383    46, 89, 103, -33, 38, -34, 55, 51, 70, -94, -35, -87, -107, -19, -31, 9,
384    -19, 79, -14, 77, 5, -19, -107, 85, 21, -45, -39, -42, 9, -29, 74, 47, -75,
385    60, -127, 120, -112, -57, -32, 41, 7, 79, 76, 66, 57, 41, -25, 31, 37, -47,
386    -36, 43, -73, -37, 63, 127, -69, -52, 90, -33, -61, 60, -55, 44, 15, 4,
387    -67, 13, -92, 64, 29, -39, -3, 83, -2, -38, -85, -86, 58, 35, -69, -61, 29,
388    -37, -95, -78, 4, 30, -4, -32, -80, -22, -9, -77, 46, 7, -93, -71, 65, 9,
389    -50, 127, -70, 26, -12, -39, -114, 63, -127, -100, 4, -32, 111, 22, -60,
390    65, -101, 26, -42, 21, -59, -27, -74, 2, -94, 6, 126, 5, 76, -88, -9, -43,
391    -101, 127, 1, 125, 92, -63, 52, 56, 4, 81, -127, 127, 80, 127, -29, 30,
392    116, -74, -17, -57, 105, 48, 45, 25, -72, 48, -38, -108, 31, -34, 4, -11,
393    41, -127, 52, -104, -43, -37, 52, 2, 47, 87, -9, 77, 27, -41, -25, 90, 86,
394    -56, 75, 10, 33, 78, 58, 127, 127, -7, -73, 49, -33, -106, -35, 38, 57, 53,
395    -17, -4, 83, 52, -108, 54, -125, 28, 23, 56, -43, -88, -17, -6, 47, 23, -9,
396    0, -13, 111, 75, 27, -52, -38, -34, 39, 30, 66, 39, 38, -64, 38, 3, 21,
397    -32, -51, -28, 54, -38, -87, 20, 52, 115, 18, -81, -70, 0, -14, -46, -46,
398    -3, 125, 16, -14, 23, -82, -84, -69, -20, -65, -127, 9, 81, -49, 61, 7,
399    -36, -45, -42, 57, -26, 47, 20, -85, 46, -13, 41, -37, -75, -60, 86, -78,
400    -127, 12, 50, 2, -3, 13, 47, 5, 19, -78, -55, -27, 65, -71, 12, -108, 20,
401    -16, 11, -31, 63, -55, 37, 75, -17, 127, -73, -33, -28, -120, 105, 68, 106,
402    -103, -106, 71, 61, 2, 23, -3, 33, -5, -15, -67, -15, -23, -54, 15, -63,
403    76, 58, -110, 1, 83, -27, 22, 75, -39, -17, -11, 64, -17, -127, -54, -66,
404    31, 96, 116, 3, -114, -7, -108, -63, 97, 9, 50, 8, 75, -28, 72, 112, -36,
405    -112, 95, -50, 23, -13, -19, 55, 21, 23, 92, 91, 22, -49, 16, -75, 23, 9,
406    -49, -97, -37, 49, -36, 36, -127, -86, 43, 127, -24, -24, 84, 83, -35, -34,
407    -12, 109, 102, -38, 51, -68, 34, 19, -22, 49, -32, 127, 40, 24, -93, -4,
408    -3, 105, 3, -58, -18, 8, 127, -18, 125, 68, 69, -62, 30, -36, 54, -57, -24,
409    17, 43, -36, -27, -57, -67, -21, -10, -49, 68, 12, 65, 4, 48, 55, 127, -75,
410    44, 89, -66, -13, -78, -82, -91, 22, 30, 33, -40, -87, -34, 96, -91, 39,
411    10, -64, -3, -12, 127, -50, -37, -56, 23, -35, -36, -54, 90, -91, 2, 50,
412    77, -6, -127, 16, 46, -5, -73, 0, -56, -18, -72, 28, 93, 60, 49, 20, 18,
413    111, -111, 32, -83, 47, 47, -10, 35, -88, 43, 57, -98, 127, -17, 0, 1, -39,
414    -127, -2, 0, 63, 93, 0, 36, -66, -61, -19, 39, -127, 58, 50, -17, 127, 88,
415    -43, -108, -51, -16, 7, -36, 68, 46, -14, 107, 40, 57, 7, 19, 8, 3, 88,
416    -90, -92, -18, -21, -24, 13, 7, -4, -78, -91, -4, 8, -35, -5, 19, 2, -111,
417    4, -66, -81, 122, -20, -34, -37, -84, 127, 68, 46, 17, 47,
418
419    // Repeat the beginning of the array to allow wrapping reads
420    -11, 12, 103, -11,
421};
422
423static const uint32_t Seed_LUT[256] = {
424    747538460, 1088979410, 1744950180, 1767011913, 1403382928,
425    521866116, 1060417601, 2110622736, 1557184770, 105289385, 585624216,
426    1827676546, 1191843873, 1018104344, 1123590530, 663361569, 2023850500,
427    76561770, 1226763489, 80325252, 1992581442, 502705249, 740409860,
428    516219202, 557974537, 1883843076, 720112066, 1640137737, 1820967556,
429    40667586, 155354121, 1820967557, 1115949072, 1631803309, 98284748,
430    287433856, 2119719977, 988742797, 1827432592, 579378475, 1017745956,
431    1309377032, 1316535465, 2074315269, 1923385360, 209722667, 1546228260,
432    168102420, 135274561, 355958469, 248291472, 2127839491, 146920100,
433    585982612, 1611702337, 696506029, 1386498192, 1258072451, 1212240548,
434    1043171860, 1217404993, 1090770605, 1386498193, 169093201, 541098240,
435    1468005469, 456510673, 1578687785, 1838217424, 2010752065, 2089828354,
436    1362717428, 970073673, 854129835, 714793201, 1266069081, 1047060864,
437    1991471829, 1098097741, 913883585, 1669598224, 1337918685, 1219264706,
438    1799741108, 1834116681, 683417731, 1120274457, 1073098457, 1648396544,
439    176642749, 31171789, 718317889, 1266977808, 1400892508, 549749008,
440    1808010512, 67112961, 1005669825, 903663673, 1771104465, 1277749632,
441    1229754427, 950632997, 1979371465, 2074373264, 305357524, 1049387408,
442    1171033360, 1686114305, 2147468765, 1941195985, 117709841, 809550080,
443    991480851, 1816248997, 1561503561, 329575568, 780651196, 1659144592,
444    1910793616, 604016641, 1665084765, 1530186961, 1870928913, 809550081,
445    2079346113, 71307521, 876663040, 1073807360, 832356664, 1573927377,
446    204073344, 2026918147, 1702476788, 2043881033, 57949587, 2001393952,
447    1197426649, 1186508931, 332056865, 950043140, 890043474, 349099312,
448    148914948, 236204097, 2022643605, 1441981517, 498130129, 1443421481,
449    924216797, 1817491777, 1913146664, 1411989632, 929068432, 495735097,
450    1684636033, 1284520017, 432816184, 1344884865, 210843729, 676364544,
451    234449232, 12112337, 1350619139, 1753272996, 2037118872, 1408560528,
452    533334916, 1043640385, 357326099, 201376421, 110375493, 541106497,
453    416159637, 242512193, 777294080, 1614872576, 1535546636, 870600145,
454    910810409, 1821440209, 1605432464, 1145147393, 951695441, 1758494976,
455    1506656568, 1557150160, 608221521, 1073840384, 217672017, 684818688,
456    1750138880, 16777217, 677990609, 953274371, 1770050213, 1359128393,
457    1797602707, 1984616737, 1865815816, 2120835200, 2051677060, 1772234061,
458    1579794881, 1652821009, 1742099468, 1887260865, 46468113, 1011925248,
459    1134107920, 881643832, 1354774993, 472508800, 1892499769, 1752793472,
460    1962502272, 687898625, 883538000, 1354355153, 1761673473, 944820481,
461    2020102353, 22020353, 961597696, 1342242816, 964808962, 1355809701,
462    17016649, 1386540177, 647682692, 1849012289, 751668241, 1557184768,
463    127374604, 1927564752, 1045744913, 1614921984, 43588881, 1016185088,
464    1544617984, 1090519041, 136122424, 215038417, 1563027841, 2026918145,
465    1688778833, 701530369, 1372639488, 1342242817, 2036945104, 953274369,
466    1750192384, 16842753, 964808960, 1359020032, 1358954497
467};
468
469// Note: This is pre-transposed, i.e. stored column-major order
470static const int8_t R64T[64][64] = {
471    {
472         32,  45,  45,  45,  45,  45,  45,  45,  44,  44,  44,  44,  43,  43,  43,  42,
473         42,  41,  41,  40,  40,  39,  39,  38,  38,  37,  36,  36,  35,  34,  34,  33,
474         32,  31,  30,  30,  29,  28,  27,  26,  25,  24,  23,  22,  21,  20,  19,  18,
475         17,  16,  15,  14,  13,  12,  11,  10,   9,   8,   7,   6,   4,   3,   2,   1,
476    }, {
477         32,  45,  45,  44,  43,  42,  41,  39,  38,  36,  34,  31,  29,  26,  23,  20,
478         17,  14,  11,   8,   4,   1,  -2,  -6,  -9, -12, -15, -18, -21, -24, -27, -30,
479        -32, -34, -36, -38, -40, -41, -43, -44, -44, -45, -45, -45, -45, -45, -44, -43,
480        -42, -40, -39, -37, -35, -33, -30, -28, -25, -22, -19, -16, -13, -10,  -7,  -3,
481    }, {
482         32,  45,  44,  42,  40,  37,  34,  30,  25,  20,  15,  10,   4,  -1,  -7, -12,
483        -17, -22, -27, -31, -35, -38, -41, -43, -44, -45, -45, -45, -43, -41, -39, -36,
484        -32, -28, -23, -18, -13,  -8,  -2,   3,   9,  14,  19,  24,  29,  33,  36,  39,
485         42,  44,  45,  45,  45,  44,  43,  40,  38,  34,  30,  26,  21,  16,  11,   6,
486    }, {
487         32,  45,  43,  39,  35,  30,  23,  16,   9,   1,  -7, -14, -21, -28, -34, -38,
488        -42, -44, -45, -45, -43, -40, -36, -31, -25, -18, -11,  -3,   4,  12,  19,  26,
489         32,  37,  41,  44,  45,  45,  44,  41,  38,  33,  27,  20,  13,   6,  -2, -10,
490        -17, -24, -30, -36, -40, -43, -45, -45, -44, -42, -39, -34, -29, -22, -15,  -8,
491    }, {
492         32,  44,  41,  36,  29,  20,  11,   1,  -9, -18, -27, -34, -40, -44, -45, -45,
493        -42, -37, -30, -22, -13,  -3,   7,  16,  25,  33,  39,  43,  45,  45,  43,  38,
494         32,  24,  15,   6,  -4, -14, -23, -31, -38, -42, -45, -45, -43, -39, -34, -26,
495        -17,  -8,   2,  12,  21,  30,  36,  41,  44,  45,  44,  40,  35,  28,  19,  10,
496    }, {
497         32,  44,  39,  31,  21,  10,  -2, -14, -25, -34, -41, -45, -45, -42, -36, -28,
498        -17,  -6,   7,  18,  29,  37,  43,  45,  44,  40,  34,  24,  13,   1, -11, -22,
499        -32, -39, -44, -45, -43, -38, -30, -20,  -9,   3,  15,  26,  35,  41,  45,  45,
500         42,  36,  27,  16,   4,  -8, -19, -30, -38, -43, -45, -44, -40, -33, -23, -12,
501    }, {
502         32,  43,  36,  26,  13,  -1, -15, -28, -38, -44, -45, -42, -35, -24, -11,   3,
503         17,  30,  39,  44,  45,  41,  34,  22,   9,  -6, -19, -31, -40, -45, -45, -40,
504        -32, -20,  -7,   8,  21,  33,  41,  45,  44,  39,  30,  18,   4, -10, -23, -34,
505        -42, -45, -44, -38, -29, -16,  -2,  12,  25,  36,  43,  45,  43,  37,  27,  14,
506    }, {
507         32,  42,  34,  20,   4, -12, -27, -38, -44, -45, -39, -28, -13,   3,  19,  33,
508         42,  45,  43,  34,  21,   6, -11, -26, -38, -44, -45, -39, -29, -14,   2,  18,
509         32,  41,  45,  43,  35,  22,   7, -10, -25, -37, -44, -45, -40, -30, -15,   1,
510         17,  31,  41,  45,  43,  36,  23,   8,  -9, -24, -36, -44, -45, -40, -30, -16,
511    }, {
512         32,  41,  30,  14,  -4, -22, -36, -44, -44, -37, -23,  -6,  13,  30,  41,  45,
513         42,  31,  15,  -3, -21, -36, -44, -45, -38, -24,  -7,  12,  29,  40,  45,  42,
514         32,  16,  -2, -20, -35, -44, -45, -38, -25,  -8,  11,  28,  40,  45,  43,  33,
515         17,  -1, -19, -34, -43, -45, -39, -26,  -9,  10,  27,  39,  45,  43,  34,  18,
516    }, {
517         32,  40,  27,   8, -13, -31, -43, -45, -38, -22,  -2,  18,  35,  44,  44,  34,
518         17,  -3, -23, -38, -45, -42, -30, -12,   9,  28,  41,  45,  40,  26,   7, -14,
519        -32, -43, -45, -37, -21,  -1,  19,  36,  44,  44,  34,  16,  -4, -24, -39, -45,
520        -42, -30, -11,  10,  29,  41,  45,  39,  25,   6, -15, -33, -43, -45, -36, -20,
521    }, {
522         32,  39,  23,   1, -21, -38, -45, -40, -25,  -3,  19,  37,  45,  41,  27,   6,
523        -17, -36, -45, -42, -29,  -8,  15,  34,  44,  43,  30,  10, -13, -33, -44, -44,
524        -32, -12,  11,  31,  43,  44,  34,  14,  -9, -30, -43, -45, -35, -16,   7,  28,
525         42,  45,  36,  18,  -4, -26, -41, -45, -38, -20,   2,  24,  40,  45,  39,  22,
526    }, {
527         32,  38,  19,  -6, -29, -43, -44, -31,  -9,  16,  36,  45,  40,  22,  -2, -26,
528        -42, -45, -34, -12,  13,  34,  45,  41,  25,   1, -23, -40, -45, -36, -15,  10,
529         32,  44,  43,  28,   4, -20, -39, -45, -38, -18,   7,  30,  43,  44,  30,   8,
530        -17, -37, -45, -39, -21,   3,  27,  42,  44,  33,  11, -14, -35, -45, -41, -24,
531    }, {
532         32,  37,  15, -12, -35, -45, -39, -18,   9,  33,  45,  40,  21,  -6, -30, -44,
533        -42, -24,   2,  28,  43,  43,  27,   1, -25, -42, -44, -30,  -4,  22,  41,  45,
534         32,   8, -19, -39, -45, -34, -11,  16,  38,  45,  36,  14, -13, -36, -45, -38,
535        -17,  10,  34,  45,  40,  20,  -7, -31, -44, -41, -23,   3,  29,  44,  43,  26,
536    }, {
537         32,  36,  11, -18, -40, -45, -30,  -3,  25,  43,  43,  24,  -4, -31, -45, -39,
538        -17,  12,  36,  45,  35,  10, -19, -40, -44, -30,  -2,  26,  43,  42,  23,  -6,
539        -32, -45, -39, -16,  13,  37,  45,  34,   9, -20, -41, -44, -29,  -1,  27,  44,
540         42,  22,  -7, -33, -45, -38, -15,  14,  38,  45,  34,   8, -21, -41, -44, -28,
541    }, {
542         32,  34,   7, -24, -43, -41, -19,  12,  38,  45,  30,   1, -29, -45, -39, -14,
543         17,  40,  44,  26,  -4, -33, -45, -36,  -9,  22,  43,  42,  21, -10, -36, -45,
544        -32,  -3,  27,  44,  40,  16, -15, -39, -44, -28,   2,  31,  45,  37,  11, -20,
545        -42, -43, -23,   8,  35,  45,  34,   6, -25, -44, -41, -18,  13,  38,  45,  30,
546    }, {
547         32,  33,   2, -30, -45, -36,  -7,  26,  44,  38,  11, -22, -43, -40, -15,  18,
548         42,  42,  19, -14, -40, -44, -23,  10,  38,  45,  27,  -6, -35, -45, -30,   1,
549         32,  45,  34,   3, -29, -45, -36,  -8,  25,  44,  39,  12, -21, -43, -41, -16,
550         17,  41,  43,  20, -13, -39, -44, -24,   9,  37,  45,  28,  -4, -34, -45, -31,
551    }, {
552         32,  31,  -2, -34, -45, -28,   7,  37,  44,  24, -11, -39, -43, -20,  15,  41,
553         42,  16, -19, -43, -40, -12,  23,  44,  38,   8, -27, -45, -35,  -3,  30,  45,
554         32,  -1, -34, -45, -29,   6,  36,  45,  25, -10, -39, -44, -21,  14,  41,  42,
555         17, -18, -43, -40, -13,  22,  44,  38,   9, -26, -45, -36,  -4,  30,  45,  33,
556    }, {
557         32,  30,  -7, -38, -43, -18,  19,  44,  38,   6, -30, -45, -29,   8,  39,  43,
558         17, -20, -44, -37,  -4,  31,  45,  28,  -9, -39, -43, -16,  21,  44,  36,   3,
559        -32, -45, -27,  10,  40,  42,  15, -22, -44, -36,  -2,  33,  45,  26, -11, -40,
560        -42, -14,  23,  45,  35,   1, -34, -45, -25,  12,  41,  41,  13, -24, -45, -34,
561    }, {
562         32,  28, -11, -41, -40,  -8,  30,  45,  25, -14, -43, -38,  -4,  33,  45,  22,
563        -17, -44, -36,  -1,  35,  44,  19, -20, -44, -34,   2,  37,  43,  16, -23, -45,
564        -32,   6,  39,  42,  13, -26, -45, -30,   9,  40,  41,  10, -29, -45, -27,  12,
565         42,  39,   7, -31, -45, -24,  15,  43,  38,   3, -34, -45, -21,  18,  44,  36,
566    }, {
567         32,  26, -15, -44, -35,   3,  39,  41,   9, -31, -45, -20,  21,  45,  30, -10,
568        -42, -38,  -2,  36,  43,  14, -27, -45, -25,  16,  44,  34,  -4, -39, -41,  -8,
569         32,  45,  19, -22, -45, -30,  11,  42,  38,   1, -36, -43, -13,  28,  45,  24,
570        -17, -44, -34,   6,  40,  40,   7, -33, -44, -18,  23,  45,  29, -12, -43, -37,
571    }, {
572         32,  24, -19, -45, -29,  14,  44,  33,  -9, -42, -36,   3,  40,  39,   2, -37,
573        -42,  -8,  34,  44,  13, -30, -45, -18,  25,  45,  23, -20, -45, -28,  15,  44,
574         32, -10, -43, -36,   4,  40,  39,   1, -38, -41,  -7,  34,  43,  12, -30, -45,
575        -17,  26,  45,  22, -21, -45, -27,  16,  44,  31, -11, -43, -35,   6,  41,  38,
576    }, {
577         32,  22, -23, -45, -21,  24,  45,  20, -25, -45, -19,  26,  45,  18, -27, -45,
578        -17,  28,  45,  16, -29, -45, -15,  30,  44,  14, -30, -44, -13,  31,  44,  12,
579        -32, -44, -11,  33,  43,  10, -34, -43,  -9,  34,  43,   8, -35, -42,  -7,  36,
580         42,   6, -36, -41,  -4,  37,  41,   3, -38, -40,  -2,  38,  40,   1, -39, -39,
581    }, {
582         32,  20, -27, -45, -13,  33,  43,   6, -38, -39,   2,  41,  35, -10, -44, -30,
583         17,  45,  23, -24, -45, -16,  30,  44,   9, -36, -41,  -1,  40,  37,  -7, -43,
584        -32,  14,  45,  26, -21, -45, -19,  28,  44,  12, -34, -42,  -4,  38,  39,  -3,
585        -42, -34,  11,  44,  29, -18, -45, -22,  25,  45,  15, -31, -43,  -8,  36,  40,
586    }, {
587         32,  18, -30, -43,  -4,  39,  36, -10, -44, -26,  23,  45,  13, -34, -41,   1,
588         42,  33, -15, -45, -21,  28,  44,   8, -38, -38,   7,  44,  29, -20, -45, -16,
589         32,  42,   2, -40, -35,  12,  45,  24, -25, -45, -11,  36,  40,  -3, -43, -31,
590         17,  45,  19, -30, -43,  -6,  39,  37,  -9, -44, -27,  22,  45,  14, -34, -41,
591    }, {
592         32,  16, -34, -40,   4,  44,  27, -24, -44,  -8,  39,  36, -13, -45, -19,  31,
593         42,  -1, -43, -30,  21,  45,  11, -37, -38,  10,  45,  22, -29, -43,  -2,  41,
594         32, -18, -45, -14,  35,  39,  -7, -44, -25,  26,  44,   6, -40, -34,  15,  45,
595         17, -33, -41,   3,  43,  28, -23, -45,  -9,  38,  36, -12, -45, -20,  30,  42,
596    }, {
597         32,  14, -36, -37,  13,  45,  15, -36, -38,  12,  45,  16, -35, -38,  11,  45,
598         17, -34, -39,  10,  45,  18, -34, -39,   9,  45,  19, -33, -40,   8,  45,  20,
599        -32, -40,   7,  45,  21, -31, -41,   6,  44,  22, -30, -41,   4,  44,  23, -30,
600        -42,   3,  44,  24, -29, -42,   2,  44,  25, -28, -43,   1,  43,  26, -27, -43,
601    }, {
602         32,  12, -39, -33,  21,  44,   2, -43, -25,  30,  41,  -8, -45, -16,  36,  36,
603        -17, -45,  -7,  41,  29, -26, -43,   3,  44,  20, -34, -38,  13,  45,  11, -39,
604        -32,  22,  44,   1, -43, -24,  30,  40,  -9, -45, -15,  37,  35, -18, -45,  -6,
605         42,  28, -27, -42,   4,  45,  19, -34, -38,  14,  45,  10, -40, -31,  23,  44,
606    }, {
607         32,  10, -41, -28,  29,  40, -11, -45,  -9,  41,  27, -30, -40,  12,  45,   8,
608        -42, -26,  30,  39, -13, -45,  -7,  42,  25, -31, -39,  14,  45,   6, -43, -24,
609         32,  38, -15, -45,  -4,  43,  23, -33, -38,  16,  45,   3, -43, -22,  34,  37,
610        -17, -45,  -2,  44,  21, -34, -36,  18,  44,   1, -44, -20,  35,  36, -19, -44,
611    }, {
612         32,   8, -43, -22,  35,  34, -23, -42,   9,  45,   7, -43, -21,  36,  34, -24,
613        -42,  10,  45,   6, -43, -20,  36,  33, -25, -41,  11,  45,   4, -44, -19,  37,
614         32, -26, -41,  12,  45,   3, -44, -18,  38,  31, -27, -40,  13,  45,   2, -44,
615        -17,  38,  30, -28, -40,  14,  45,   1, -44, -16,  39,  30, -29, -39,  15,  45,
616    }, {
617         32,   6, -44, -16,  40,  26, -34, -34,  25,  40, -15, -44,   4,  45,   7, -44,
618        -17,  39,  27, -33, -35,  24,  41, -14, -44,   3,  45,   8, -43, -18,  39,  28,
619        -32, -36,  23,  41, -13, -45,   2,  45,   9, -43, -19,  38,  29, -31, -36,  22,
620         42, -12, -45,   1,  45,  10, -43, -20,  38,  30, -30, -37,  21,  42, -11, -45,
621    }, {
622         32,   3, -45, -10,  43,  16, -41, -22,  38,  28, -34, -33,  29,  37, -23, -40,
623         17,  43, -11, -45,   4,  45,   2, -45,  -9,  44,  15, -41, -21,  38,  27, -34,
624        -32,  30,  36, -24, -40,  18,  43, -12, -44,   6,  45,   1, -45,  -8,  44,  14,
625        -42, -20,  39,  26, -35, -31,  30,  36, -25, -39,  19,  42, -13, -44,   7,  45,
626    }, {
627         32,   1, -45,  -3,  45,   6, -45,  -8,  44,  10, -44, -12,  43,  14, -43, -16,
628         42,  18, -41, -20,  40,  22, -39, -24,  38,  26, -36, -28,  35,  30, -34, -31,
629         32,  33, -30, -34,  29,  36, -27, -37,  25,  38, -23, -39,  21,  40, -19, -41,
630         17,  42, -15, -43,  13,  44, -11, -44,   9,  45,  -7, -45,   4,  45,  -2, -45,
631    }, {
632         32,  -1, -45,   3,  45,  -6, -45,   8,  44, -10, -44,  12,  43, -14, -43,  16,
633         42, -18, -41,  20,  40, -22, -39,  24,  38, -26, -36,  28,  35, -30, -34,  31,
634         32, -33, -30,  34,  29, -36, -27,  37,  25, -38, -23,  39,  21, -40, -19,  41,
635         17, -42, -15,  43,  13, -44, -11,  44,   9, -45,  -7,  45,   4, -45,  -2,  45,
636    }, {
637         32,  -3, -45,  10,  43, -16, -41,  22,  38, -28, -34,  33,  29, -37, -23,  40,
638         17, -43, -11,  45,   4, -45,   2,  45,  -9, -44,  15,  41, -21, -38,  27,  34,
639        -32, -30,  36,  24, -40, -18,  43,  12, -44,  -6,  45,  -1, -45,   8,  44, -14,
640        -42,  20,  39, -26, -35,  31,  30, -36, -25,  39,  19, -42, -13,  44,   7, -45,
641    }, {
642         32,  -6, -44,  16,  40, -26, -34,  34,  25, -40, -15,  44,   4, -45,   7,  44,
643        -17, -39,  27,  33, -35, -24,  41,  14, -44,  -3,  45,  -8, -43,  18,  39, -28,
644        -32,  36,  23, -41, -13,  45,   2, -45,   9,  43, -19, -38,  29,  31, -36, -22,
645         42,  12, -45,  -1,  45, -10, -43,  20,  38, -30, -30,  37,  21, -42, -11,  45,
646    }, {
647         32,  -8, -43,  22,  35, -34, -23,  42,   9, -45,   7,  43, -21, -36,  34,  24,
648        -42, -10,  45,  -6, -43,  20,  36, -33, -25,  41,  11, -45,   4,  44, -19, -37,
649         32,  26, -41, -12,  45,  -3, -44,  18,  38, -31, -27,  40,  13, -45,   2,  44,
650        -17, -38,  30,  28, -40, -14,  45,  -1, -44,  16,  39, -30, -29,  39,  15, -45,
651    }, {
652         32, -10, -41,  28,  29, -40, -11,  45,  -9, -41,  27,  30, -40, -12,  45,  -8,
653        -42,  26,  30, -39, -13,  45,  -7, -42,  25,  31, -39, -14,  45,  -6, -43,  24,
654         32, -38, -15,  45,  -4, -43,  23,  33, -38, -16,  45,  -3, -43,  22,  34, -37,
655        -17,  45,  -2, -44,  21,  34, -36, -18,  44,  -1, -44,  20,  35, -36, -19,  44,
656    }, {
657         32, -12, -39,  33,  21, -44,   2,  43, -25, -30,  41,   8, -45,  16,  36, -36,
658        -17,  45,  -7, -41,  29,  26, -43,  -3,  44, -20, -34,  38,  13, -45,  11,  39,
659        -32, -22,  44,  -1, -43,  24,  30, -40,  -9,  45, -15, -37,  35,  18, -45,   6,
660         42, -28, -27,  42,   4, -45,  19,  34, -38, -14,  45, -10, -40,  31,  23, -44,
661    }, {
662         32, -14, -36,  37,  13, -45,  15,  36, -38, -12,  45, -16, -35,  38,  11, -45,
663         17,  34, -39, -10,  45, -18, -34,  39,   9, -45,  19,  33, -40,  -8,  45, -20,
664        -32,  40,   7, -45,  21,  31, -41,  -6,  44, -22, -30,  41,   4, -44,  23,  30,
665        -42,  -3,  44, -24, -29,  42,   2, -44,  25,  28, -43,  -1,  43, -26, -27,  43,
666    }, {
667         32, -16, -34,  40,   4, -44,  27,  24, -44,   8,  39, -36, -13,  45, -19, -31,
668         42,   1, -43,  30,  21, -45,  11,  37, -38, -10,  45, -22, -29,  43,  -2, -41,
669         32,  18, -45,  14,  35, -39,  -7,  44, -25, -26,  44,  -6, -40,  34,  15, -45,
670         17,  33, -41,  -3,  43, -28, -23,  45,  -9, -38,  36,  12, -45,  20,  30, -42,
671    }, {
672         32, -18, -30,  43,  -4, -39,  36,  10, -44,  26,  23, -45,  13,  34, -41,  -1,
673         42, -33, -15,  45, -21, -28,  44,  -8, -38,  38,   7, -44,  29,  20, -45,  16,
674         32, -42,   2,  40, -35, -12,  45, -24, -25,  45, -11, -36,  40,   3, -43,  31,
675         17, -45,  19,  30, -43,   6,  39, -37,  -9,  44, -27, -22,  45, -14, -34,  41,
676    }, {
677         32, -20, -27,  45, -13, -33,  43,  -6, -38,  39,   2, -41,  35,  10, -44,  30,
678         17, -45,  23,  24, -45,  16,  30, -44,   9,  36, -41,   1,  40, -37,  -7,  43,
679        -32, -14,  45, -26, -21,  45, -19, -28,  44, -12, -34,  42,  -4, -38,  39,   3,
680        -42,  34,  11, -44,  29,  18, -45,  22,  25, -45,  15,  31, -43,   8,  36, -40,
681    }, {
682         32, -22, -23,  45, -21, -24,  45, -20, -25,  45, -19, -26,  45, -18, -27,  45,
683        -17, -28,  45, -16, -29,  45, -15, -30,  44, -14, -30,  44, -13, -31,  44, -12,
684        -32,  44, -11, -33,  43, -10, -34,  43,  -9, -34,  43,  -8, -35,  42,  -7, -36,
685         42,  -6, -36,  41,  -4, -37,  41,  -3, -38,  40,  -2, -38,  40,  -1, -39,  39,
686    }, {
687         32, -24, -19,  45, -29, -14,  44, -33,  -9,  42, -36,  -3,  40, -39,   2,  37,
688        -42,   8,  34, -44,  13,  30, -45,  18,  25, -45,  23,  20, -45,  28,  15, -44,
689         32,  10, -43,  36,   4, -40,  39,  -1, -38,  41,  -7, -34,  43, -12, -30,  45,
690        -17, -26,  45, -22, -21,  45, -27, -16,  44, -31, -11,  43, -35,  -6,  41, -38,
691    }, {
692         32, -26, -15,  44, -35,  -3,  39, -41,   9,  31, -45,  20,  21, -45,  30,  10,
693        -42,  38,  -2, -36,  43, -14, -27,  45, -25, -16,  44, -34,  -4,  39, -41,   8,
694         32, -45,  19,  22, -45,  30,  11, -42,  38,  -1, -36,  43, -13, -28,  45, -24,
695        -17,  44, -34,  -6,  40, -40,   7,  33, -44,  18,  23, -45,  29,  12, -43,  37,
696    }, {
697         32, -28, -11,  41, -40,   8,  30, -45,  25,  14, -43,  38,  -4, -33,  45, -22,
698        -17,  44, -36,   1,  35, -44,  19,  20, -44,  34,   2, -37,  43, -16, -23,  45,
699        -32,  -6,  39, -42,  13,  26, -45,  30,   9, -40,  41, -10, -29,  45, -27, -12,
700         42, -39,   7,  31, -45,  24,  15, -43,  38,  -3, -34,  45, -21, -18,  44, -36,
701    }, {
702         32, -30,  -7,  38, -43,  18,  19, -44,  38,  -6, -30,  45, -29,  -8,  39, -43,
703         17,  20, -44,  37,  -4, -31,  45, -28,  -9,  39, -43,  16,  21, -44,  36,  -3,
704        -32,  45, -27, -10,  40, -42,  15,  22, -44,  36,  -2, -33,  45, -26, -11,  40,
705        -42,  14,  23, -45,  35,  -1, -34,  45, -25, -12,  41, -41,  13,  24, -45,  34,
706    }, {
707         32, -31,  -2,  34, -45,  28,   7, -37,  44, -24, -11,  39, -43,  20,  15, -41,
708         42, -16, -19,  43, -40,  12,  23, -44,  38,  -8, -27,  45, -35,   3,  30, -45,
709         32,   1, -34,  45, -29,  -6,  36, -45,  25,  10, -39,  44, -21, -14,  41, -42,
710         17,  18, -43,  40, -13, -22,  44, -38,   9,  26, -45,  36,  -4, -30,  45, -33,
711    }, {
712         32, -33,   2,  30, -45,  36,  -7, -26,  44, -38,  11,  22, -43,  40, -15, -18,
713         42, -42,  19,  14, -40,  44, -23, -10,  38, -45,  27,   6, -35,  45, -30,  -1,
714         32, -45,  34,  -3, -29,  45, -36,   8,  25, -44,  39, -12, -21,  43, -41,  16,
715         17, -41,  43, -20, -13,  39, -44,  24,   9, -37,  45, -28,  -4,  34, -45,  31,
716    }, {
717         32, -34,   7,  24, -43,  41, -19, -12,  38, -45,  30,  -1, -29,  45, -39,  14,
718         17, -40,  44, -26,  -4,  33, -45,  36,  -9, -22,  43, -42,  21,  10, -36,  45,
719        -32,   3,  27, -44,  40, -16, -15,  39, -44,  28,   2, -31,  45, -37,  11,  20,
720        -42,  43, -23,  -8,  35, -45,  34,  -6, -25,  44, -41,  18,  13, -38,  45, -30,
721    }, {
722         32, -36,  11,  18, -40,  45, -30,   3,  25, -43,  43, -24,  -4,  31, -45,  39,
723        -17, -12,  36, -45,  35, -10, -19,  40, -44,  30,  -2, -26,  43, -42,  23,   6,
724        -32,  45, -39,  16,  13, -37,  45, -34,   9,  20, -41,  44, -29,   1,  27, -44,
725         42, -22,  -7,  33, -45,  38, -15, -14,  38, -45,  34,  -8, -21,  41, -44,  28,
726    }, {
727         32, -37,  15,  12, -35,  45, -39,  18,   9, -33,  45, -40,  21,   6, -30,  44,
728        -42,  24,   2, -28,  43, -43,  27,  -1, -25,  42, -44,  30,  -4, -22,  41, -45,
729         32,  -8, -19,  39, -45,  34, -11, -16,  38, -45,  36, -14, -13,  36, -45,  38,
730        -17, -10,  34, -45,  40, -20,  -7,  31, -44,  41, -23,  -3,  29, -44,  43, -26,
731    }, {
732         32, -38,  19,   6, -29,  43, -44,  31,  -9, -16,  36, -45,  40, -22,  -2,  26,
733        -42,  45, -34,  12,  13, -34,  45, -41,  25,  -1, -23,  40, -45,  36, -15, -10,
734         32, -44,  43, -28,   4,  20, -39,  45, -38,  18,   7, -30,  43, -44,  30,  -8,
735        -17,  37, -45,  39, -21,  -3,  27, -42,  44, -33,  11,  14, -35,  45, -41,  24,
736    }, {
737         32, -39,  23,  -1, -21,  38, -45,  40, -25,   3,  19, -37,  45, -41,  27,  -6,
738        -17,  36, -45,  42, -29,   8,  15, -34,  44, -43,  30, -10, -13,  33, -44,  44,
739        -32,  12,  11, -31,  43, -44,  34, -14,  -9,  30, -43,  45, -35,  16,   7, -28,
740         42, -45,  36, -18,  -4,  26, -41,  45, -38,  20,   2, -24,  40, -45,  39, -22,
741    }, {
742         32, -40,  27,  -8, -13,  31, -43,  45, -38,  22,  -2, -18,  35, -44,  44, -34,
743         17,   3, -23,  38, -45,  42, -30,  12,   9, -28,  41, -45,  40, -26,   7,  14,
744        -32,  43, -45,  37, -21,   1,  19, -36,  44, -44,  34, -16,  -4,  24, -39,  45,
745        -42,  30, -11, -10,  29, -41,  45, -39,  25,  -6, -15,  33, -43,  45, -36,  20,
746    }, {
747         32, -41,  30, -14,  -4,  22, -36,  44, -44,  37, -23,   6,  13, -30,  41, -45,
748         42, -31,  15,   3, -21,  36, -44,  45, -38,  24,  -7, -12,  29, -40,  45, -42,
749         32, -16,  -2,  20, -35,  44, -45,  38, -25,   8,  11, -28,  40, -45,  43, -33,
750         17,   1, -19,  34, -43,  45, -39,  26,  -9, -10,  27, -39,  45, -43,  34, -18,
751    }, {
752         32, -42,  34, -20,   4,  12, -27,  38, -44,  45, -39,  28, -13,  -3,  19, -33,
753         42, -45,  43, -34,  21,  -6, -11,  26, -38,  44, -45,  39, -29,  14,   2, -18,
754         32, -41,  45, -43,  35, -22,   7,  10, -25,  37, -44,  45, -40,  30, -15,  -1,
755         17, -31,  41, -45,  43, -36,  23,  -8,  -9,  24, -36,  44, -45,  40, -30,  16,
756    }, {
757         32, -43,  36, -26,  13,   1, -15,  28, -38,  44, -45,  42, -35,  24, -11,  -3,
758         17, -30,  39, -44,  45, -41,  34, -22,   9,   6, -19,  31, -40,  45, -45,  40,
759        -32,  20,  -7,  -8,  21, -33,  41, -45,  44, -39,  30, -18,   4,  10, -23,  34,
760        -42,  45, -44,  38, -29,  16,  -2, -12,  25, -36,  43, -45,  43, -37,  27, -14,
761    }, {
762         32, -44,  39, -31,  21, -10,  -2,  14, -25,  34, -41,  45, -45,  42, -36,  28,
763        -17,   6,   7, -18,  29, -37,  43, -45,  44, -40,  34, -24,  13,  -1, -11,  22,
764        -32,  39, -44,  45, -43,  38, -30,  20,  -9,  -3,  15, -26,  35, -41,  45, -45,
765         42, -36,  27, -16,   4,   8, -19,  30, -38,  43, -45,  44, -40,  33, -23,  12,
766    }, {
767         32, -44,  41, -36,  29, -20,  11,  -1,  -9,  18, -27,  34, -40,  44, -45,  45,
768        -42,  37, -30,  22, -13,   3,   7, -16,  25, -33,  39, -43,  45, -45,  43, -38,
769         32, -24,  15,  -6,  -4,  14, -23,  31, -38,  42, -45,  45, -43,  39, -34,  26,
770        -17,   8,   2, -12,  21, -30,  36, -41,  44, -45,  44, -40,  35, -28,  19, -10,
771    }, {
772         32, -45,  43, -39,  35, -30,  23, -16,   9,  -1,  -7,  14, -21,  28, -34,  38,
773        -42,  44, -45,  45, -43,  40, -36,  31, -25,  18, -11,   3,   4, -12,  19, -26,
774         32, -37,  41, -44,  45, -45,  44, -41,  38, -33,  27, -20,  13,  -6,  -2,  10,
775        -17,  24, -30,  36, -40,  43, -45,  45, -44,  42, -39,  34, -29,  22, -15,   8,
776    }, {
777         32, -45,  44, -42,  40, -37,  34, -30,  25, -20,  15, -10,   4,   1,  -7,  12,
778        -17,  22, -27,  31, -35,  38, -41,  43, -44,  45, -45,  45, -43,  41, -39,  36,
779        -32,  28, -23,  18, -13,   8,  -2,  -3,   9, -14,  19, -24,  29, -33,  36, -39,
780         42, -44,  45, -45,  45, -44,  43, -40,  38, -34,  30, -26,  21, -16,  11,  -6,
781    }, {
782         32, -45,  45, -44,  43, -42,  41, -39,  38, -36,  34, -31,  29, -26,  23, -20,
783         17, -14,  11,  -8,   4,  -1,  -2,   6,  -9,  12, -15,  18, -21,  24, -27,  30,
784        -32,  34, -36,  38, -40,  41, -43,  44, -44,  45, -45,  45, -45,  45, -44,  43,
785        -42,  40, -39,  37, -35,  33, -30,  28, -25,  22, -19,  16, -13,  10,  -7,   3,
786    }, {
787         32, -45,  45, -45,  45, -45,  45, -45,  44, -44,  44, -44,  43, -43,  43, -42,
788         42, -41,  41, -40,  40, -39,  39, -38,  38, -37,  36, -36,  35, -34,  34, -33,
789         32, -31,  30, -30,  29, -28,  27, -26,  25, -24,  23, -22,  21, -20,  19, -18,
790         17, -16,  15, -14,  13, -12,  11, -10,   9,  -8,   7,  -6,   4,  -3,   2,  -1,
791    }
792};
793