Branch data Line data Source code
1 : : /*
2 : : * This file is part of libplacebo.
3 : : *
4 : : * libplacebo is free software; you can redistribute it and/or
5 : : * modify it under the terms of the GNU Lesser General Public
6 : : * License as published by the Free Software Foundation; either
7 : : * version 2.1 of the License, or (at your option) any later version.
8 : : *
9 : : * libplacebo is distributed in the hope that it will be useful,
10 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : * GNU Lesser General Public License for more details.
13 : : *
14 : : * You should have received a copy of the GNU Lesser General Public
15 : : * License along with libplacebo. If not, see <http://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #include "shaders.h"
19 : : #include "shaders/film_grain.h"
20 : :
21 : : static const int8_t Gaussian_LUT[2048+4];
22 : : static const uint32_t Seed_LUT[256];
23 : : static const int8_t R64T[64][64];
24 : :
25 : : static void prng_shift(uint32_t *state)
26 : : {
27 : : // Primitive polynomial x^31 + x^3 + 1 (modulo 2)
28 : : uint32_t x = *state;
29 : 219024 : uint8_t feedback = 1u ^ (x >> 2) ^ (x >> 30);
30 : 219024 : *state = (x << 1) | (feedback & 1u);
31 : : }
32 : :
33 : :
34 : 676 : static void generate_slice(float *out, size_t out_width, uint8_t h, uint8_t v,
35 : : int8_t grain[64][64], int16_t tmp[64][64])
36 : : {
37 : 676 : const uint8_t freq_h = ((h + 3) << 2) - 1;
38 : 676 : const uint8_t freq_v = ((v + 3) << 2) - 1;
39 : 676 : uint32_t seed = Seed_LUT[h + v * 13];
40 : :
41 : : // Initialize with random gaussian values, using the output array as a
42 : : // temporary buffer for these intermediate values.
43 : : //
44 : : // Note: To make the subsequent matrix multiplication cache friendlier, we
45 : : // store each *column* of the starting image in a *row* of `grain`
46 [ + + ]: 25012 : for (int y = 0; y <= freq_v; y++) {
47 [ + + ]: 243360 : for (int x = 0; x <= freq_h; x += 4) {
48 : 219024 : uint16_t offset = seed % 2048;
49 : 219024 : grain[x + 0][y] = Gaussian_LUT[offset + 0];
50 : 219024 : grain[x + 1][y] = Gaussian_LUT[offset + 1];
51 : 219024 : grain[x + 2][y] = Gaussian_LUT[offset + 2];
52 : 219024 : grain[x + 3][y] = Gaussian_LUT[offset + 3];
53 : : prng_shift(&seed);
54 : : }
55 : : }
56 : :
57 : 676 : grain[0][0] = 0;
58 : :
59 : : // 64x64 inverse integer transform
60 [ + + ]: 43940 : for (int y = 0; y < 64; y++) {
61 [ + + ]: 1600768 : for (int x = 0; x <= freq_h; x++) {
62 : : int32_t sum = 0;
63 [ + + ]: 57627648 : for (int p = 0; p <= freq_v; p++)
64 : 56070144 : sum += R64T[y][p] * grain[x][p];
65 : 1557504 : tmp[y][x] = (sum + 128) >> 8;
66 : : }
67 : : }
68 : :
69 [ + + ]: 43940 : for (int y = 0; y < 64; y++) {
70 [ + + ]: 2812160 : for (int x = 0; x < 64; x++) {
71 : : int32_t sum = 0;
72 [ + + ]: 102449152 : for (int p = 0; p <= freq_h; p++)
73 : 99680256 : sum += tmp[y][p] * R64T[x][p]; // R64T^T = R64
74 : 2768896 : sum = (sum + 128) >> 8;
75 : 2768896 : grain[y][x] = PL_CLAMP(sum, -127, 127);
76 : : }
77 : : }
78 : :
79 : : static const uint8_t deblock_factors[13] = {
80 : : 64, 71, 77, 84, 90, 96, 103, 109, 116, 122, 128, 128, 128
81 : : };
82 : :
83 : : // Deblock horizontal edges by simple attentuation of values
84 : 676 : const uint8_t deblock_coeff = deblock_factors[v];
85 [ + + ]: 43940 : for (int y = 0; y < 64; y++) {
86 [ + + ]: 43264 : switch (y % 8) {
87 : : case 0: case 7:
88 : : // Deblock
89 [ + + ]: 703040 : for (int x = 0; x < 64; x++)
90 : 692224 : out[x] = ((grain[y][x] * deblock_coeff) >> 7) / 255.0;
91 : : break;
92 : :
93 : : case 1: case 2:
94 : : case 3: case 4:
95 : : case 5: case 6:
96 : : // No deblock
97 [ + + ]: 2109120 : for (int x = 0; x < 64; x++)
98 : 2076672 : out[x] = grain[y][x] / 255.0;
99 : : break;
100 : :
101 : : default: pl_unreachable();
102 : : }
103 : :
104 : 43264 : out += out_width;
105 : : }
106 : 676 : }
107 : :
108 : 4 : static void fill_grain_lut(void *data, const struct sh_lut_params *params)
109 : : {
110 : : struct {
111 : : int8_t grain[64][64];
112 : : int16_t tmp[64][64];
113 : 4 : } *tmp = pl_alloc_ptr(NULL, tmp);
114 : :
115 : : float *out = data;
116 [ + - ]: 4 : assert(params->var_type == PL_VAR_FLOAT);
117 : :
118 [ + + ]: 56 : for (int h = 0; h < 13; h++) {
119 [ + + ]: 728 : for (int v = 0; v < 13; v++) {
120 : 676 : float *slice = out + (h * 64) * params->width + (v * 64);
121 : 676 : generate_slice(slice, params->width, h, v, tmp->grain, tmp->tmp);
122 : : }
123 : : }
124 : :
125 : 4 : pl_free(tmp);
126 : 4 : }
127 : :
128 : 14 : bool pl_needs_fg_h274(const struct pl_film_grain_params *params)
129 : : {
130 : : const struct pl_h274_grain_data *data = ¶ms->data.params.h274;
131 [ - + ]: 14 : if (data->model_id != 0)
132 : : return false;
133 : :
134 [ - + ]: 14 : for (int i = 0; i < 3; i++) {
135 : 14 : enum pl_channel channel = channel_map(i, params);
136 [ - + ]: 14 : if (channel < 0 || channel >= 3)
137 : 0 : continue;
138 [ - + ]: 14 : if (data->component_model_present[channel])
139 : : return true;
140 : : }
141 : :
142 : : return false;
143 : : }
144 : :
145 : 6 : bool pl_shader_fg_h274(pl_shader sh, pl_shader_obj *grain_state,
146 : : const struct pl_film_grain_params *params)
147 : : {
148 [ - + ]: 6 : if (!sh_require(sh, PL_SHADER_SIG_NONE, params->tex->params.w, params->tex->params.h))
149 : : return false;
150 : :
151 : : size_t shmem_req = 0;
152 : : ident_t group_sum = NULL_IDENT;
153 : :
154 : 6 : const struct pl_glsl_version glsl = sh_glsl(sh);
155 [ + - ]: 6 : if (glsl.subgroup_size < 8*8) {
156 : 6 : group_sum = sh_fresh(sh, "group_sum");
157 : : shmem_req += sizeof(int);
158 : 6 : GLSLH("shared int "$"; \n", group_sum);
159 : 6 : GLSL($" = 0; barrier(); \n", group_sum);
160 : : }
161 : :
162 [ + + ]: 6 : if (!sh_try_compute(sh, 8, 8, false, shmem_req)) {
163 : 2 : SH_FAIL(sh, "H.274 film grain synthesis requires compute shaders!");
164 : 2 : return false;
165 : : }
166 : :
167 : 4 : ident_t db = sh_lut(sh, sh_lut_params(
168 : : .object = grain_state,
169 : : .var_type = PL_VAR_FLOAT,
170 : : .lut_type = SH_LUT_TEXTURE,
171 : : .width = 13 * 64,
172 : : .height = 13 * 64,
173 : : .comps = 1,
174 : : .fill = fill_grain_lut,
175 : : .signature = CACHE_KEY_H274, // doesn't depend on anything
176 : : .cache = SH_CACHE(sh),
177 : : ));
178 : :
179 : 4 : sh_describe(sh, "H.274 film grain");
180 : 4 : GLSL("vec4 color; \n"
181 : : "// pl_shader_film_grain (H.274) \n"
182 : : "{ \n");
183 : :
184 : : // Load the color value of the tex itself
185 : 4 : ident_t tex = sh_desc(sh, (struct pl_shader_desc) {
186 : 4 : .binding.object = params->tex,
187 : : .desc = (struct pl_desc) {
188 : : .name = "tex",
189 : : .type = PL_DESC_SAMPLED_TEX,
190 : : },
191 : : });
192 : :
193 : 4 : GLSL("ivec2 pos = ivec2(gl_GlobalInvocationID); \n"
194 : : "color = vec4("$") * texelFetch("$", pos, 0); \n",
195 : : SH_FLOAT(pl_color_repr_normalize(params->repr)), tex);
196 : :
197 : : const struct pl_h274_grain_data *data = ¶ms->data.params.h274;
198 : 8 : ident_t scale_factor = sh_var(sh, (struct pl_shader_var) {
199 : 4 : .var = pl_var_float("scale_factor"),
200 : 4 : .data = &(float){ 1.0 / (1 << (data->log2_scale_factor + 6)) },
201 : : });
202 : :
203 : : // pcg3d (http://www.jcgt.org/published/0009/03/02/)
204 : 4 : GLSL("uvec3 pcg = uvec3("$", gl_WorkGroupID.xy / 2u); \n"
205 : : "pcg = pcg * 1664525u + 1013904223u; \n"
206 : : "pcg.x += pcg.y * pcg.z; \n"
207 : : "pcg.y += pcg.z * pcg.x; \n"
208 : : "pcg.z += pcg.x * pcg.y; \n"
209 : : "pcg ^= pcg >> 16u; \n"
210 : : "pcg.x += pcg.y * pcg.z; \n"
211 : : "pcg.y += pcg.z * pcg.x; \n"
212 : : "pcg.z += pcg.x * pcg.y; \n",
213 : : sh_var(sh, (struct pl_shader_var) {
214 : : .var = pl_var_uint("seed"),
215 : : .data = &(unsigned int){ params->data.seed },
216 : : }));
217 : :
218 [ + + ]: 12 : for (int idx = 0; idx < params->components; idx++) {
219 : 8 : enum pl_channel c = channel_map(idx, params);
220 [ - + ]: 8 : if (c == PL_CHANNEL_NONE)
221 : 0 : continue;
222 [ + + ]: 8 : if (!data->component_model_present[c])
223 : 4 : continue;
224 : :
225 : 4 : GLSL("// component %d\n{\n", c);
226 : :
227 : : // Compute the local 8x8 average
228 : 4 : GLSL("float avg = color[%d] / 64.0; \n", c);
229 : :
230 : : const int precision = 10000000;
231 [ + + ]: 4 : if (glsl.subgroup_size) {
232 : 2 : GLSL("avg = subgroupAdd(avg); \n");
233 : :
234 [ + - ]: 2 : if (glsl.subgroup_size < 8*8) {
235 : 2 : GLSL("if (subgroupElect()) \n"
236 : : " atomicAdd("$", int(avg * %d.0)); \n"
237 : : "barrier(); \n"
238 : : "avg = float("$") / %d.0; \n",
239 : : group_sum, precision, group_sum, precision);
240 : : }
241 : : } else {
242 : 2 : GLSL("atomicAdd("$", int(avg * %d.0)); \n"
243 : : "barrier(); \n"
244 : : "avg = float("$") / %d.0; \n",
245 : : group_sum, precision, group_sum, precision);
246 : : }
247 : :
248 : : // Hard-coded unrolled loop, to avoid having to load a dynamically
249 : : // sized array into the shader - and to optimize for the very common
250 : : // case of there only being a single intensity interval
251 : 4 : GLSL("uint val; \n");
252 [ + + ]: 8 : for (int i = 0; i < data->num_intensity_intervals[c]; i++) {
253 : 8 : ident_t bounds = sh_var(sh, (struct pl_shader_var) {
254 : 4 : .var = pl_var_vec2("bounds"),
255 : 4 : .data = &(float[2]) {
256 : 4 : data->intensity_interval_lower_bound[c][i] / 255.0,
257 : 4 : data->intensity_interval_upper_bound[c][i] / 255.0,
258 : : },
259 : : });
260 : :
261 : 4 : const uint8_t num_values = data->num_model_values[c];
262 [ + - ]: 4 : uint8_t h = num_values > 1 ? data->comp_model_value[c][i][1] : 8;
263 [ + - ]: 4 : uint8_t v = num_values > 2 ? data->comp_model_value[c][i][2] : h;
264 [ + - ]: 4 : h = PL_CLAMP(h, 2, 14) - 2;
265 [ + - ]: 4 : v = PL_CLAMP(v, 2, 14) - 2;
266 : : // FIXME: double h/v for subsampled planes!
267 : :
268 : : // Reduce scale for chroma planes
269 : 4 : int16_t scale = data->comp_model_value[c][i][0];
270 [ + - - - ]: 4 : if (c > 0 && pl_color_system_is_ycbcr_like(params->repr->sys))
271 : 0 : scale >>= 1;
272 : :
273 : : pl_static_assert(sizeof(unsigned int) >= sizeof(uint32_t));
274 : 8 : ident_t values = sh_var(sh, (struct pl_shader_var) {
275 : 4 : .var = pl_var_uint("comp_model_value"),
276 : 4 : .data = &(unsigned int) {
277 : 4 : (uint16_t) scale << 16 | h << 8 | v,
278 : : },
279 : : });
280 : :
281 : 4 : GLSL("if (avg >= "$".x && avg <= "$".y) \n"
282 : : " val = "$"; else \n",
283 : : bounds, bounds, values);
284 : : }
285 : 4 : GLSL(" val = 0u; \n");
286 : :
287 : : // Extract the grain parameters from comp_model_value
288 : 4 : GLSL("uvec2 offset = uvec2((val & 0xFF00u) >> 2, \n"
289 : : " (val & 0xFFu) << 6); \n"
290 : : "float scale = "$" * float(int(val >> 16)); \n"
291 : : // Add randomness
292 : : "uint rand = pcg[%d]; \n"
293 : : "offset.x += (rand >> 16u) %% 52u; \n"
294 : : "offset.y += (rand & 0xFFFFu) %% 56u; \n"
295 : : "offset.x &= 0xFFFCu; \n"
296 : : "offset.y &= 0xFFF8u; \n"
297 : : "if ((rand & 1u) == 1u) scale = -scale; \n"
298 : : // Add local offset and compute grain
299 : : "offset += 8u * (gl_WorkGroupID.xy %% 2u); \n"
300 : : "offset += gl_LocalInvocationID.xy; \n"
301 : : "float grain = "$"(offset); \n"
302 : : "color[%d] += scale * grain; \n",
303 : : scale_factor, c, db, c);
304 : :
305 : : // TODO: Deblocking?
306 : :
307 : 4 : GLSL("}\n");
308 : : }
309 : :
310 : 4 : GLSL("} \n");
311 : 4 : return true;
312 : : }
313 : :
314 : : // These tables are all taken from the SMPTE RDD 5-2006 specification
315 : : static const int8_t Gaussian_LUT[2048+4] = {
316 : : -11, 12, 103, -11, 42, -35, 12, 59, 77, 98, -87, 3, 65, -78, 45, 56, -51, 21,
317 : : 13, -11, -20, -19, 33, -127, 17, -6, -105, 18, 19, 71, 48, -10, -38, 42,
318 : : -2, 75, -67, 52, -90, 33, -47, 21, -3, -56, 49, 1, -57, -42, -1, 120, -127,
319 : : -108, -49, 9, 14, 127, 122, 109, 52, 127, 2, 7, 114, 19, 30, 12, 77, 112,
320 : : 82, -61, -127, 111, -52, -29, 2, -49, -24, 58, -29, -73, 12, 112, 67, 79,
321 : : -3, -114, -87, -6, -5, 40, 58, -81, 49, -27, -31, -34, -105, 50, 16, -24,
322 : : -35, -14, -15, -127, -55, -22, -55, -127, -112, 5, -26, -72, 127, 127, -2,
323 : : 41, 87, -65, -16, 55, 19, 91, -81, -65, -64, 35, -7, -54, 99, -7, 88, 125,
324 : : -26, 91, 0, 63, 60, -14, -23, 113, -33, 116, 14, 26, 51, -16, 107, -8, 53,
325 : : 38, -34, 17, -7, 4, -91, 6, 63, 63, -15, 39, -36, 19, 55, 17, -51, 40, 33,
326 : : -37, 126, -39, -118, 17, -30, 0, 19, 98, 60, 101, -12, -73, -17, -52, 98,
327 : : 3, 3, 60, 33, -3, -2, 10, -42, -106, -38, 14, 127, 16, -127, -31, -86, -39,
328 : : -56, 46, -41, 75, 23, -19, -22, -70, 74, -54, -2, 32, -45, 17, -92, 59,
329 : : -64, -67, 56, -102, -29, -87, -34, -92, 68, 5, -74, -61, 93, -43, 14, -26,
330 : : -38, -126, -17, 16, -127, 64, 34, 31, 93, 17, -51, -59, 71, 77, 81, 127,
331 : : 127, 61, 33, -106, -93, 0, 0, 75, -69, 71, 127, -19, -111, 30, 23, 15, 2,
332 : : 39, 92, 5, 42, 2, -6, 38, 15, 114, -30, -37, 50, 44, 106, 27, 119, 7, -80,
333 : : 25, -68, -21, 92, -11, -1, 18, 41, -50, 79, -127, -43, 127, 18, 11, -21,
334 : : 32, -52, 27, -88, -90, -39, -19, -10, 24, -118, 72, -24, -44, 2, 12, 86,
335 : : -107, 39, -33, -127, 47, 51, -24, -22, 46, 0, 15, -35, -69, -2, -74, 24,
336 : : -6, 0, 29, -3, 45, 32, -32, 117, -45, 79, -24, -17, -109, -10, -70, 88,
337 : : -48, 24, -91, 120, -37, 50, -127, 58, 32, -82, -10, -17, -7, 46, -127, -15,
338 : : 89, 127, 17, 98, -39, -33, 37, 42, -40, -32, -21, 105, -19, 19, 19, -59,
339 : : -9, 30, 0, -127, 34, 127, -84, 75, 24, -40, -49, -127, -107, -14, 45, -75,
340 : : 1, 30, -20, 41, -68, -40, 12, 127, -3, 5, 20, -73, -59, -127, -3, -3, -53,
341 : : -6, -119, 93, 120, -80, -50, 0, 20, -46, 67, 78, -12, -22, -127, 36, -41,
342 : : 56, 119, -5, -116, -22, 68, -14, -90, 24, -82, -44, -127, 107, -25, -37,
343 : : 40, -7, -7, -82, 5, -87, 44, -34, 9, -127, 39, 70, 49, -63, 74, -49, 109,
344 : : -27, -89, -47, -39, 44, 49, -4, 60, -42, 80, 9, -127, -9, -56, -49, 125,
345 : : -66, 47, 36, 117, 15, -11, -96, 109, 94, -17, -56, 70, 8, -14, -5, 50, 37,
346 : : -45, 120, -30, -76, 40, -46, 6, 3, 69, 17, -78, 1, -79, 6, 127, 43, 26,
347 : : 127, -127, 28, -55, -26, 55, 112, 48, 107, -1, -77, -1, 53, -9, -22, -43,
348 : : 123, 108, 127, 102, 68, 46, 5, 1, 123, -13, -55, -34, -49, 89, 65, -105,
349 : : -5, 94, -53, 62, 45, 30, 46, 18, -35, 15, 41, 47, -98, -24, 94, -75, 127,
350 : : -114, 127, -68, 1, -17, 51, -95, 47, 12, 34, -45, -75, 89, -107, -9, -58,
351 : : -29, -109, -24, 127, -61, -13, 77, -45, 17, 19, 83, -24, 9, 127, -66, 54,
352 : : 4, 26, 13, 111, 43, -113, -22, 10, -24, 83, 67, -14, 75, -123, 59, 127,
353 : : -12, 99, -19, 64, -38, 54, 9, 7, 61, -56, 3, -57, 113, -104, -59, 3, -9,
354 : : -47, 74, 85, -55, -34, 12, 118, 28, 93, -72, 13, -99, -72, -20, 30, 72,
355 : : -94, 19, -54, 64, -12, -63, -25, 65, 72, -10, 127, 0, -127, 103, -20, -73,
356 : : -112, -103, -6, 28, -42, -21, -59, -29, -26, 19, -4, -51, 94, -58, -95,
357 : : -37, 35, 20, -69, 127, -19, -127, -22, -120, -53, 37, 74, -127, -1, -12,
358 : : -119, -53, -28, 38, 69, 17, 16, -114, 89, 62, 24, 37, -23, 49, -101, -32,
359 : : -9, -95, -53, 5, 93, -23, -49, -8, 51, 3, -75, -90, -10, -39, 127, -86,
360 : : -22, 20, 20, 113, 75, 52, -31, 92, -63, 7, -12, 46, 36, 101, -43, -17, -53,
361 : : -7, -38, -76, -31, -21, 62, 31, 62, 20, -127, 31, 64, 36, 102, -85, -10,
362 : : 77, 80, 58, -79, -8, 35, 8, 80, -24, -9, 3, -17, 72, 127, 83, -87, 55, 18,
363 : : -119, -123, 36, 10, 127, 56, -55, 113, 13, 26, 32, -13, -48, 22, -13, 5,
364 : : 58, 27, 24, 26, -11, -36, 37, -92, 78, 81, 9, 51, 14, 67, -13, 0, 32, 45,
365 : : -76, 32, -39, -22, -49, -127, -27, 31, -9, 36, 14, 71, 13, 57, 12, -53,
366 : : -86, 53, -44, -35, 2, 127, 12, -66, -44, 46, -115, 3, 10, 56, -35, 119,
367 : : -19, -61, 52, -59, -127, -49, -23, 4, -5, 17, -82, -6, 127, 25, 79, 67, 64,
368 : : -25, 14, -64, -37, -127, -28, 21, -63, 66, -53, -41, 109, -62, 15, -22, 13,
369 : : 29, -63, 20, 27, 95, -44, -59, -116, -10, 79, -49, 22, -43, -16, 46, -47,
370 : : -120, -36, -29, -52, -44, 29, 127, -13, 49, -9, -127, 75, -28, -23, 88, 59,
371 : : 11, -95, 81, -59, 58, 60, -26, 40, -92, -3, -22, -58, -45, -59, -22, -53,
372 : : 71, -29, 66, -32, -23, 14, -17, -66, -24, -28, -62, 47, 38, 17, 16, -37,
373 : : -24, -11, 8, -27, -19, 59, 45, -49, -47, -4, -22, -81, 30, -67, -127, 74,
374 : : 102, 5, -18, 98, 34, -66, 42, -52, 7, -59, 24, -58, -19, -24, -118, -73,
375 : : 91, 15, -16, 79, -32, -79, -127, -36, 41, 77, -83, 2, 56, 22, -75, 127,
376 : : -16, -21, 12, 31, 56, -113, -127, 90, 55, 61, 12, 55, -14, -113, -14, 32,
377 : : 49, -67, -17, 91, -10, 1, 21, 69, -70, 99, -19, -112, 66, -90, -10, -9,
378 : : -71, 127, 50, -81, -49, 24, 61, -61, -111, 7, -41, 127, 88, -66, 108, -127,
379 : : -6, 36, -14, 41, -50, 14, 14, 73, -101, -28, 77, 127, -8, -100, 88, 38,
380 : : 121, 88, -125, -60, 13, -94, -115, 20, -67, -87, -94, -119, 44, -28, -30,
381 : : 18, 5, -53, -61, 20, -43, 11, -77, -60, 13, 29, 3, 6, -72, 38, -60, -11,
382 : : 108, -53, 41, 66, -12, -127, -127, -49, 24, 29, 46, 36, 91, 34, -33, 116,
383 : : -51, -34, -52, 91, 7, -83, 73, -26, -103, 24, -10, 76, 84, 5, 68, -80, -13,
384 : : -17, -32, -48, 20, 50, 26, 10, 63, -104, -14, 37, 127, 114, 97, 35, 1, -33,
385 : : -55, 127, -124, -33, 61, -7, 119, -32, -127, -53, -42, 63, 3, -5, -26, 70,
386 : : -58, -33, -44, -43, 34, -56, -127, 127, 25, -35, -11, 16, -81, 29, -58, 40,
387 : : -127, -127, 20, -47, -11, -36, -63, -52, -32, -82, 78, -76, -73, 8, 27,
388 : : -72, -9, -74, -85, -86, -57, 25, 78, -10, -97, 35, -65, 8, -59, 14, 1, -42,
389 : : 32, -88, -44, 17, -3, -9, 59, 40, 12, -108, -40, 24, 34, 18, -28, 2, 51,
390 : : -110, -4, 100, 1, 65, 22, 0, 127, 61, 45, 25, -31, 6, 9, -7, -48, 99, 16,
391 : : 44, -2, -40, 32, -39, -52, 10, -110, -19, 56, -127, 69, 26, 51, 92, 40, 61,
392 : : -52, 45, -38, 13, 85, 122, 27, 66, 45, -111, -83, -3, 31, 37, 19, -36, 58,
393 : : 71, 39, -78, -47, 58, -78, 8, -62, -36, -14, 61, 42, -127, 71, -4, 24, -54,
394 : : 52, -127, 67, -4, -42, 30, -63, 59, -3, -1, -18, -46, -92, -81, -96, -14,
395 : : -53, -10, -11, -77, 13, 1, 8, -67, -127, 127, -28, 26, -14, 18, -13, -26,
396 : : 2, 10, -46, -32, -15, 27, -31, -59, 59, 77, -121, 28, 40, -54, -62, -31,
397 : : -21, -37, -32, -6, -127, -25, -60, 70, -127, 112, -127, 127, 88, -7, 116,
398 : : 110, 53, 87, -127, 3, 16, 23, 74, -106, -51, 3, 74, -82, -112, -74, 65, 81,
399 : : 25, 53, 127, -45, -50, -103, -41, -65, -29, 79, -67, 64, -33, -30, -8, 127,
400 : : 0, -13, -51, 67, -14, 5, -92, 29, -35, -8, -90, -57, -3, 36, 43, 44, -31,
401 : : -69, -7, 36, 39, -51, 43, -81, 58, 6, 127, 12, 57, 66, 46, 59, -43, -42,
402 : : 41, -15, -120, 24, 3, -11, 19, -13, 51, 28, 3, 55, -48, -12, -1, 2, 97,
403 : : -19, 29, 42, 13, 43, 78, -44, 56, -108, -43, -19, 127, 15, -11, -18, -81,
404 : : 83, -37, 77, -109, 15, 65, -50, 43, 12, 13, 27, 28, 61, 57, 30, 26, 106,
405 : : -18, 56, 13, 97, 4, -8, -62, -103, 94, 108, -44, 52, 27, -47, -9, 105, -53,
406 : : 46, 89, 103, -33, 38, -34, 55, 51, 70, -94, -35, -87, -107, -19, -31, 9,
407 : : -19, 79, -14, 77, 5, -19, -107, 85, 21, -45, -39, -42, 9, -29, 74, 47, -75,
408 : : 60, -127, 120, -112, -57, -32, 41, 7, 79, 76, 66, 57, 41, -25, 31, 37, -47,
409 : : -36, 43, -73, -37, 63, 127, -69, -52, 90, -33, -61, 60, -55, 44, 15, 4,
410 : : -67, 13, -92, 64, 29, -39, -3, 83, -2, -38, -85, -86, 58, 35, -69, -61, 29,
411 : : -37, -95, -78, 4, 30, -4, -32, -80, -22, -9, -77, 46, 7, -93, -71, 65, 9,
412 : : -50, 127, -70, 26, -12, -39, -114, 63, -127, -100, 4, -32, 111, 22, -60,
413 : : 65, -101, 26, -42, 21, -59, -27, -74, 2, -94, 6, 126, 5, 76, -88, -9, -43,
414 : : -101, 127, 1, 125, 92, -63, 52, 56, 4, 81, -127, 127, 80, 127, -29, 30,
415 : : 116, -74, -17, -57, 105, 48, 45, 25, -72, 48, -38, -108, 31, -34, 4, -11,
416 : : 41, -127, 52, -104, -43, -37, 52, 2, 47, 87, -9, 77, 27, -41, -25, 90, 86,
417 : : -56, 75, 10, 33, 78, 58, 127, 127, -7, -73, 49, -33, -106, -35, 38, 57, 53,
418 : : -17, -4, 83, 52, -108, 54, -125, 28, 23, 56, -43, -88, -17, -6, 47, 23, -9,
419 : : 0, -13, 111, 75, 27, -52, -38, -34, 39, 30, 66, 39, 38, -64, 38, 3, 21,
420 : : -32, -51, -28, 54, -38, -87, 20, 52, 115, 18, -81, -70, 0, -14, -46, -46,
421 : : -3, 125, 16, -14, 23, -82, -84, -69, -20, -65, -127, 9, 81, -49, 61, 7,
422 : : -36, -45, -42, 57, -26, 47, 20, -85, 46, -13, 41, -37, -75, -60, 86, -78,
423 : : -127, 12, 50, 2, -3, 13, 47, 5, 19, -78, -55, -27, 65, -71, 12, -108, 20,
424 : : -16, 11, -31, 63, -55, 37, 75, -17, 127, -73, -33, -28, -120, 105, 68, 106,
425 : : -103, -106, 71, 61, 2, 23, -3, 33, -5, -15, -67, -15, -23, -54, 15, -63,
426 : : 76, 58, -110, 1, 83, -27, 22, 75, -39, -17, -11, 64, -17, -127, -54, -66,
427 : : 31, 96, 116, 3, -114, -7, -108, -63, 97, 9, 50, 8, 75, -28, 72, 112, -36,
428 : : -112, 95, -50, 23, -13, -19, 55, 21, 23, 92, 91, 22, -49, 16, -75, 23, 9,
429 : : -49, -97, -37, 49, -36, 36, -127, -86, 43, 127, -24, -24, 84, 83, -35, -34,
430 : : -12, 109, 102, -38, 51, -68, 34, 19, -22, 49, -32, 127, 40, 24, -93, -4,
431 : : -3, 105, 3, -58, -18, 8, 127, -18, 125, 68, 69, -62, 30, -36, 54, -57, -24,
432 : : 17, 43, -36, -27, -57, -67, -21, -10, -49, 68, 12, 65, 4, 48, 55, 127, -75,
433 : : 44, 89, -66, -13, -78, -82, -91, 22, 30, 33, -40, -87, -34, 96, -91, 39,
434 : : 10, -64, -3, -12, 127, -50, -37, -56, 23, -35, -36, -54, 90, -91, 2, 50,
435 : : 77, -6, -127, 16, 46, -5, -73, 0, -56, -18, -72, 28, 93, 60, 49, 20, 18,
436 : : 111, -111, 32, -83, 47, 47, -10, 35, -88, 43, 57, -98, 127, -17, 0, 1, -39,
437 : : -127, -2, 0, 63, 93, 0, 36, -66, -61, -19, 39, -127, 58, 50, -17, 127, 88,
438 : : -43, -108, -51, -16, 7, -36, 68, 46, -14, 107, 40, 57, 7, 19, 8, 3, 88,
439 : : -90, -92, -18, -21, -24, 13, 7, -4, -78, -91, -4, 8, -35, -5, 19, 2, -111,
440 : : 4, -66, -81, 122, -20, -34, -37, -84, 127, 68, 46, 17, 47,
441 : :
442 : : // Repeat the beginning of the array to allow wrapping reads
443 : : -11, 12, 103, -11,
444 : : };
445 : :
446 : : static const uint32_t Seed_LUT[256] = {
447 : : 747538460, 1088979410, 1744950180, 1767011913, 1403382928,
448 : : 521866116, 1060417601, 2110622736, 1557184770, 105289385, 585624216,
449 : : 1827676546, 1191843873, 1018104344, 1123590530, 663361569, 2023850500,
450 : : 76561770, 1226763489, 80325252, 1992581442, 502705249, 740409860,
451 : : 516219202, 557974537, 1883843076, 720112066, 1640137737, 1820967556,
452 : : 40667586, 155354121, 1820967557, 1115949072, 1631803309, 98284748,
453 : : 287433856, 2119719977, 988742797, 1827432592, 579378475, 1017745956,
454 : : 1309377032, 1316535465, 2074315269, 1923385360, 209722667, 1546228260,
455 : : 168102420, 135274561, 355958469, 248291472, 2127839491, 146920100,
456 : : 585982612, 1611702337, 696506029, 1386498192, 1258072451, 1212240548,
457 : : 1043171860, 1217404993, 1090770605, 1386498193, 169093201, 541098240,
458 : : 1468005469, 456510673, 1578687785, 1838217424, 2010752065, 2089828354,
459 : : 1362717428, 970073673, 854129835, 714793201, 1266069081, 1047060864,
460 : : 1991471829, 1098097741, 913883585, 1669598224, 1337918685, 1219264706,
461 : : 1799741108, 1834116681, 683417731, 1120274457, 1073098457, 1648396544,
462 : : 176642749, 31171789, 718317889, 1266977808, 1400892508, 549749008,
463 : : 1808010512, 67112961, 1005669825, 903663673, 1771104465, 1277749632,
464 : : 1229754427, 950632997, 1979371465, 2074373264, 305357524, 1049387408,
465 : : 1171033360, 1686114305, 2147468765, 1941195985, 117709841, 809550080,
466 : : 991480851, 1816248997, 1561503561, 329575568, 780651196, 1659144592,
467 : : 1910793616, 604016641, 1665084765, 1530186961, 1870928913, 809550081,
468 : : 2079346113, 71307521, 876663040, 1073807360, 832356664, 1573927377,
469 : : 204073344, 2026918147, 1702476788, 2043881033, 57949587, 2001393952,
470 : : 1197426649, 1186508931, 332056865, 950043140, 890043474, 349099312,
471 : : 148914948, 236204097, 2022643605, 1441981517, 498130129, 1443421481,
472 : : 924216797, 1817491777, 1913146664, 1411989632, 929068432, 495735097,
473 : : 1684636033, 1284520017, 432816184, 1344884865, 210843729, 676364544,
474 : : 234449232, 12112337, 1350619139, 1753272996, 2037118872, 1408560528,
475 : : 533334916, 1043640385, 357326099, 201376421, 110375493, 541106497,
476 : : 416159637, 242512193, 777294080, 1614872576, 1535546636, 870600145,
477 : : 910810409, 1821440209, 1605432464, 1145147393, 951695441, 1758494976,
478 : : 1506656568, 1557150160, 608221521, 1073840384, 217672017, 684818688,
479 : : 1750138880, 16777217, 677990609, 953274371, 1770050213, 1359128393,
480 : : 1797602707, 1984616737, 1865815816, 2120835200, 2051677060, 1772234061,
481 : : 1579794881, 1652821009, 1742099468, 1887260865, 46468113, 1011925248,
482 : : 1134107920, 881643832, 1354774993, 472508800, 1892499769, 1752793472,
483 : : 1962502272, 687898625, 883538000, 1354355153, 1761673473, 944820481,
484 : : 2020102353, 22020353, 961597696, 1342242816, 964808962, 1355809701,
485 : : 17016649, 1386540177, 647682692, 1849012289, 751668241, 1557184768,
486 : : 127374604, 1927564752, 1045744913, 1614921984, 43588881, 1016185088,
487 : : 1544617984, 1090519041, 136122424, 215038417, 1563027841, 2026918145,
488 : : 1688778833, 701530369, 1372639488, 1342242817, 2036945104, 953274369,
489 : : 1750192384, 16842753, 964808960, 1359020032, 1358954497
490 : : };
491 : :
492 : : // Note: This is pre-transposed, i.e. stored column-major order
493 : : static const int8_t R64T[64][64] = {
494 : : {
495 : : 32, 45, 45, 45, 45, 45, 45, 45, 44, 44, 44, 44, 43, 43, 43, 42,
496 : : 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 36, 36, 35, 34, 34, 33,
497 : : 32, 31, 30, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18,
498 : : 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1,
499 : : }, {
500 : : 32, 45, 45, 44, 43, 42, 41, 39, 38, 36, 34, 31, 29, 26, 23, 20,
501 : : 17, 14, 11, 8, 4, 1, -2, -6, -9, -12, -15, -18, -21, -24, -27, -30,
502 : : -32, -34, -36, -38, -40, -41, -43, -44, -44, -45, -45, -45, -45, -45, -44, -43,
503 : : -42, -40, -39, -37, -35, -33, -30, -28, -25, -22, -19, -16, -13, -10, -7, -3,
504 : : }, {
505 : : 32, 45, 44, 42, 40, 37, 34, 30, 25, 20, 15, 10, 4, -1, -7, -12,
506 : : -17, -22, -27, -31, -35, -38, -41, -43, -44, -45, -45, -45, -43, -41, -39, -36,
507 : : -32, -28, -23, -18, -13, -8, -2, 3, 9, 14, 19, 24, 29, 33, 36, 39,
508 : : 42, 44, 45, 45, 45, 44, 43, 40, 38, 34, 30, 26, 21, 16, 11, 6,
509 : : }, {
510 : : 32, 45, 43, 39, 35, 30, 23, 16, 9, 1, -7, -14, -21, -28, -34, -38,
511 : : -42, -44, -45, -45, -43, -40, -36, -31, -25, -18, -11, -3, 4, 12, 19, 26,
512 : : 32, 37, 41, 44, 45, 45, 44, 41, 38, 33, 27, 20, 13, 6, -2, -10,
513 : : -17, -24, -30, -36, -40, -43, -45, -45, -44, -42, -39, -34, -29, -22, -15, -8,
514 : : }, {
515 : : 32, 44, 41, 36, 29, 20, 11, 1, -9, -18, -27, -34, -40, -44, -45, -45,
516 : : -42, -37, -30, -22, -13, -3, 7, 16, 25, 33, 39, 43, 45, 45, 43, 38,
517 : : 32, 24, 15, 6, -4, -14, -23, -31, -38, -42, -45, -45, -43, -39, -34, -26,
518 : : -17, -8, 2, 12, 21, 30, 36, 41, 44, 45, 44, 40, 35, 28, 19, 10,
519 : : }, {
520 : : 32, 44, 39, 31, 21, 10, -2, -14, -25, -34, -41, -45, -45, -42, -36, -28,
521 : : -17, -6, 7, 18, 29, 37, 43, 45, 44, 40, 34, 24, 13, 1, -11, -22,
522 : : -32, -39, -44, -45, -43, -38, -30, -20, -9, 3, 15, 26, 35, 41, 45, 45,
523 : : 42, 36, 27, 16, 4, -8, -19, -30, -38, -43, -45, -44, -40, -33, -23, -12,
524 : : }, {
525 : : 32, 43, 36, 26, 13, -1, -15, -28, -38, -44, -45, -42, -35, -24, -11, 3,
526 : : 17, 30, 39, 44, 45, 41, 34, 22, 9, -6, -19, -31, -40, -45, -45, -40,
527 : : -32, -20, -7, 8, 21, 33, 41, 45, 44, 39, 30, 18, 4, -10, -23, -34,
528 : : -42, -45, -44, -38, -29, -16, -2, 12, 25, 36, 43, 45, 43, 37, 27, 14,
529 : : }, {
530 : : 32, 42, 34, 20, 4, -12, -27, -38, -44, -45, -39, -28, -13, 3, 19, 33,
531 : : 42, 45, 43, 34, 21, 6, -11, -26, -38, -44, -45, -39, -29, -14, 2, 18,
532 : : 32, 41, 45, 43, 35, 22, 7, -10, -25, -37, -44, -45, -40, -30, -15, 1,
533 : : 17, 31, 41, 45, 43, 36, 23, 8, -9, -24, -36, -44, -45, -40, -30, -16,
534 : : }, {
535 : : 32, 41, 30, 14, -4, -22, -36, -44, -44, -37, -23, -6, 13, 30, 41, 45,
536 : : 42, 31, 15, -3, -21, -36, -44, -45, -38, -24, -7, 12, 29, 40, 45, 42,
537 : : 32, 16, -2, -20, -35, -44, -45, -38, -25, -8, 11, 28, 40, 45, 43, 33,
538 : : 17, -1, -19, -34, -43, -45, -39, -26, -9, 10, 27, 39, 45, 43, 34, 18,
539 : : }, {
540 : : 32, 40, 27, 8, -13, -31, -43, -45, -38, -22, -2, 18, 35, 44, 44, 34,
541 : : 17, -3, -23, -38, -45, -42, -30, -12, 9, 28, 41, 45, 40, 26, 7, -14,
542 : : -32, -43, -45, -37, -21, -1, 19, 36, 44, 44, 34, 16, -4, -24, -39, -45,
543 : : -42, -30, -11, 10, 29, 41, 45, 39, 25, 6, -15, -33, -43, -45, -36, -20,
544 : : }, {
545 : : 32, 39, 23, 1, -21, -38, -45, -40, -25, -3, 19, 37, 45, 41, 27, 6,
546 : : -17, -36, -45, -42, -29, -8, 15, 34, 44, 43, 30, 10, -13, -33, -44, -44,
547 : : -32, -12, 11, 31, 43, 44, 34, 14, -9, -30, -43, -45, -35, -16, 7, 28,
548 : : 42, 45, 36, 18, -4, -26, -41, -45, -38, -20, 2, 24, 40, 45, 39, 22,
549 : : }, {
550 : : 32, 38, 19, -6, -29, -43, -44, -31, -9, 16, 36, 45, 40, 22, -2, -26,
551 : : -42, -45, -34, -12, 13, 34, 45, 41, 25, 1, -23, -40, -45, -36, -15, 10,
552 : : 32, 44, 43, 28, 4, -20, -39, -45, -38, -18, 7, 30, 43, 44, 30, 8,
553 : : -17, -37, -45, -39, -21, 3, 27, 42, 44, 33, 11, -14, -35, -45, -41, -24,
554 : : }, {
555 : : 32, 37, 15, -12, -35, -45, -39, -18, 9, 33, 45, 40, 21, -6, -30, -44,
556 : : -42, -24, 2, 28, 43, 43, 27, 1, -25, -42, -44, -30, -4, 22, 41, 45,
557 : : 32, 8, -19, -39, -45, -34, -11, 16, 38, 45, 36, 14, -13, -36, -45, -38,
558 : : -17, 10, 34, 45, 40, 20, -7, -31, -44, -41, -23, 3, 29, 44, 43, 26,
559 : : }, {
560 : : 32, 36, 11, -18, -40, -45, -30, -3, 25, 43, 43, 24, -4, -31, -45, -39,
561 : : -17, 12, 36, 45, 35, 10, -19, -40, -44, -30, -2, 26, 43, 42, 23, -6,
562 : : -32, -45, -39, -16, 13, 37, 45, 34, 9, -20, -41, -44, -29, -1, 27, 44,
563 : : 42, 22, -7, -33, -45, -38, -15, 14, 38, 45, 34, 8, -21, -41, -44, -28,
564 : : }, {
565 : : 32, 34, 7, -24, -43, -41, -19, 12, 38, 45, 30, 1, -29, -45, -39, -14,
566 : : 17, 40, 44, 26, -4, -33, -45, -36, -9, 22, 43, 42, 21, -10, -36, -45,
567 : : -32, -3, 27, 44, 40, 16, -15, -39, -44, -28, 2, 31, 45, 37, 11, -20,
568 : : -42, -43, -23, 8, 35, 45, 34, 6, -25, -44, -41, -18, 13, 38, 45, 30,
569 : : }, {
570 : : 32, 33, 2, -30, -45, -36, -7, 26, 44, 38, 11, -22, -43, -40, -15, 18,
571 : : 42, 42, 19, -14, -40, -44, -23, 10, 38, 45, 27, -6, -35, -45, -30, 1,
572 : : 32, 45, 34, 3, -29, -45, -36, -8, 25, 44, 39, 12, -21, -43, -41, -16,
573 : : 17, 41, 43, 20, -13, -39, -44, -24, 9, 37, 45, 28, -4, -34, -45, -31,
574 : : }, {
575 : : 32, 31, -2, -34, -45, -28, 7, 37, 44, 24, -11, -39, -43, -20, 15, 41,
576 : : 42, 16, -19, -43, -40, -12, 23, 44, 38, 8, -27, -45, -35, -3, 30, 45,
577 : : 32, -1, -34, -45, -29, 6, 36, 45, 25, -10, -39, -44, -21, 14, 41, 42,
578 : : 17, -18, -43, -40, -13, 22, 44, 38, 9, -26, -45, -36, -4, 30, 45, 33,
579 : : }, {
580 : : 32, 30, -7, -38, -43, -18, 19, 44, 38, 6, -30, -45, -29, 8, 39, 43,
581 : : 17, -20, -44, -37, -4, 31, 45, 28, -9, -39, -43, -16, 21, 44, 36, 3,
582 : : -32, -45, -27, 10, 40, 42, 15, -22, -44, -36, -2, 33, 45, 26, -11, -40,
583 : : -42, -14, 23, 45, 35, 1, -34, -45, -25, 12, 41, 41, 13, -24, -45, -34,
584 : : }, {
585 : : 32, 28, -11, -41, -40, -8, 30, 45, 25, -14, -43, -38, -4, 33, 45, 22,
586 : : -17, -44, -36, -1, 35, 44, 19, -20, -44, -34, 2, 37, 43, 16, -23, -45,
587 : : -32, 6, 39, 42, 13, -26, -45, -30, 9, 40, 41, 10, -29, -45, -27, 12,
588 : : 42, 39, 7, -31, -45, -24, 15, 43, 38, 3, -34, -45, -21, 18, 44, 36,
589 : : }, {
590 : : 32, 26, -15, -44, -35, 3, 39, 41, 9, -31, -45, -20, 21, 45, 30, -10,
591 : : -42, -38, -2, 36, 43, 14, -27, -45, -25, 16, 44, 34, -4, -39, -41, -8,
592 : : 32, 45, 19, -22, -45, -30, 11, 42, 38, 1, -36, -43, -13, 28, 45, 24,
593 : : -17, -44, -34, 6, 40, 40, 7, -33, -44, -18, 23, 45, 29, -12, -43, -37,
594 : : }, {
595 : : 32, 24, -19, -45, -29, 14, 44, 33, -9, -42, -36, 3, 40, 39, 2, -37,
596 : : -42, -8, 34, 44, 13, -30, -45, -18, 25, 45, 23, -20, -45, -28, 15, 44,
597 : : 32, -10, -43, -36, 4, 40, 39, 1, -38, -41, -7, 34, 43, 12, -30, -45,
598 : : -17, 26, 45, 22, -21, -45, -27, 16, 44, 31, -11, -43, -35, 6, 41, 38,
599 : : }, {
600 : : 32, 22, -23, -45, -21, 24, 45, 20, -25, -45, -19, 26, 45, 18, -27, -45,
601 : : -17, 28, 45, 16, -29, -45, -15, 30, 44, 14, -30, -44, -13, 31, 44, 12,
602 : : -32, -44, -11, 33, 43, 10, -34, -43, -9, 34, 43, 8, -35, -42, -7, 36,
603 : : 42, 6, -36, -41, -4, 37, 41, 3, -38, -40, -2, 38, 40, 1, -39, -39,
604 : : }, {
605 : : 32, 20, -27, -45, -13, 33, 43, 6, -38, -39, 2, 41, 35, -10, -44, -30,
606 : : 17, 45, 23, -24, -45, -16, 30, 44, 9, -36, -41, -1, 40, 37, -7, -43,
607 : : -32, 14, 45, 26, -21, -45, -19, 28, 44, 12, -34, -42, -4, 38, 39, -3,
608 : : -42, -34, 11, 44, 29, -18, -45, -22, 25, 45, 15, -31, -43, -8, 36, 40,
609 : : }, {
610 : : 32, 18, -30, -43, -4, 39, 36, -10, -44, -26, 23, 45, 13, -34, -41, 1,
611 : : 42, 33, -15, -45, -21, 28, 44, 8, -38, -38, 7, 44, 29, -20, -45, -16,
612 : : 32, 42, 2, -40, -35, 12, 45, 24, -25, -45, -11, 36, 40, -3, -43, -31,
613 : : 17, 45, 19, -30, -43, -6, 39, 37, -9, -44, -27, 22, 45, 14, -34, -41,
614 : : }, {
615 : : 32, 16, -34, -40, 4, 44, 27, -24, -44, -8, 39, 36, -13, -45, -19, 31,
616 : : 42, -1, -43, -30, 21, 45, 11, -37, -38, 10, 45, 22, -29, -43, -2, 41,
617 : : 32, -18, -45, -14, 35, 39, -7, -44, -25, 26, 44, 6, -40, -34, 15, 45,
618 : : 17, -33, -41, 3, 43, 28, -23, -45, -9, 38, 36, -12, -45, -20, 30, 42,
619 : : }, {
620 : : 32, 14, -36, -37, 13, 45, 15, -36, -38, 12, 45, 16, -35, -38, 11, 45,
621 : : 17, -34, -39, 10, 45, 18, -34, -39, 9, 45, 19, -33, -40, 8, 45, 20,
622 : : -32, -40, 7, 45, 21, -31, -41, 6, 44, 22, -30, -41, 4, 44, 23, -30,
623 : : -42, 3, 44, 24, -29, -42, 2, 44, 25, -28, -43, 1, 43, 26, -27, -43,
624 : : }, {
625 : : 32, 12, -39, -33, 21, 44, 2, -43, -25, 30, 41, -8, -45, -16, 36, 36,
626 : : -17, -45, -7, 41, 29, -26, -43, 3, 44, 20, -34, -38, 13, 45, 11, -39,
627 : : -32, 22, 44, 1, -43, -24, 30, 40, -9, -45, -15, 37, 35, -18, -45, -6,
628 : : 42, 28, -27, -42, 4, 45, 19, -34, -38, 14, 45, 10, -40, -31, 23, 44,
629 : : }, {
630 : : 32, 10, -41, -28, 29, 40, -11, -45, -9, 41, 27, -30, -40, 12, 45, 8,
631 : : -42, -26, 30, 39, -13, -45, -7, 42, 25, -31, -39, 14, 45, 6, -43, -24,
632 : : 32, 38, -15, -45, -4, 43, 23, -33, -38, 16, 45, 3, -43, -22, 34, 37,
633 : : -17, -45, -2, 44, 21, -34, -36, 18, 44, 1, -44, -20, 35, 36, -19, -44,
634 : : }, {
635 : : 32, 8, -43, -22, 35, 34, -23, -42, 9, 45, 7, -43, -21, 36, 34, -24,
636 : : -42, 10, 45, 6, -43, -20, 36, 33, -25, -41, 11, 45, 4, -44, -19, 37,
637 : : 32, -26, -41, 12, 45, 3, -44, -18, 38, 31, -27, -40, 13, 45, 2, -44,
638 : : -17, 38, 30, -28, -40, 14, 45, 1, -44, -16, 39, 30, -29, -39, 15, 45,
639 : : }, {
640 : : 32, 6, -44, -16, 40, 26, -34, -34, 25, 40, -15, -44, 4, 45, 7, -44,
641 : : -17, 39, 27, -33, -35, 24, 41, -14, -44, 3, 45, 8, -43, -18, 39, 28,
642 : : -32, -36, 23, 41, -13, -45, 2, 45, 9, -43, -19, 38, 29, -31, -36, 22,
643 : : 42, -12, -45, 1, 45, 10, -43, -20, 38, 30, -30, -37, 21, 42, -11, -45,
644 : : }, {
645 : : 32, 3, -45, -10, 43, 16, -41, -22, 38, 28, -34, -33, 29, 37, -23, -40,
646 : : 17, 43, -11, -45, 4, 45, 2, -45, -9, 44, 15, -41, -21, 38, 27, -34,
647 : : -32, 30, 36, -24, -40, 18, 43, -12, -44, 6, 45, 1, -45, -8, 44, 14,
648 : : -42, -20, 39, 26, -35, -31, 30, 36, -25, -39, 19, 42, -13, -44, 7, 45,
649 : : }, {
650 : : 32, 1, -45, -3, 45, 6, -45, -8, 44, 10, -44, -12, 43, 14, -43, -16,
651 : : 42, 18, -41, -20, 40, 22, -39, -24, 38, 26, -36, -28, 35, 30, -34, -31,
652 : : 32, 33, -30, -34, 29, 36, -27, -37, 25, 38, -23, -39, 21, 40, -19, -41,
653 : : 17, 42, -15, -43, 13, 44, -11, -44, 9, 45, -7, -45, 4, 45, -2, -45,
654 : : }, {
655 : : 32, -1, -45, 3, 45, -6, -45, 8, 44, -10, -44, 12, 43, -14, -43, 16,
656 : : 42, -18, -41, 20, 40, -22, -39, 24, 38, -26, -36, 28, 35, -30, -34, 31,
657 : : 32, -33, -30, 34, 29, -36, -27, 37, 25, -38, -23, 39, 21, -40, -19, 41,
658 : : 17, -42, -15, 43, 13, -44, -11, 44, 9, -45, -7, 45, 4, -45, -2, 45,
659 : : }, {
660 : : 32, -3, -45, 10, 43, -16, -41, 22, 38, -28, -34, 33, 29, -37, -23, 40,
661 : : 17, -43, -11, 45, 4, -45, 2, 45, -9, -44, 15, 41, -21, -38, 27, 34,
662 : : -32, -30, 36, 24, -40, -18, 43, 12, -44, -6, 45, -1, -45, 8, 44, -14,
663 : : -42, 20, 39, -26, -35, 31, 30, -36, -25, 39, 19, -42, -13, 44, 7, -45,
664 : : }, {
665 : : 32, -6, -44, 16, 40, -26, -34, 34, 25, -40, -15, 44, 4, -45, 7, 44,
666 : : -17, -39, 27, 33, -35, -24, 41, 14, -44, -3, 45, -8, -43, 18, 39, -28,
667 : : -32, 36, 23, -41, -13, 45, 2, -45, 9, 43, -19, -38, 29, 31, -36, -22,
668 : : 42, 12, -45, -1, 45, -10, -43, 20, 38, -30, -30, 37, 21, -42, -11, 45,
669 : : }, {
670 : : 32, -8, -43, 22, 35, -34, -23, 42, 9, -45, 7, 43, -21, -36, 34, 24,
671 : : -42, -10, 45, -6, -43, 20, 36, -33, -25, 41, 11, -45, 4, 44, -19, -37,
672 : : 32, 26, -41, -12, 45, -3, -44, 18, 38, -31, -27, 40, 13, -45, 2, 44,
673 : : -17, -38, 30, 28, -40, -14, 45, -1, -44, 16, 39, -30, -29, 39, 15, -45,
674 : : }, {
675 : : 32, -10, -41, 28, 29, -40, -11, 45, -9, -41, 27, 30, -40, -12, 45, -8,
676 : : -42, 26, 30, -39, -13, 45, -7, -42, 25, 31, -39, -14, 45, -6, -43, 24,
677 : : 32, -38, -15, 45, -4, -43, 23, 33, -38, -16, 45, -3, -43, 22, 34, -37,
678 : : -17, 45, -2, -44, 21, 34, -36, -18, 44, -1, -44, 20, 35, -36, -19, 44,
679 : : }, {
680 : : 32, -12, -39, 33, 21, -44, 2, 43, -25, -30, 41, 8, -45, 16, 36, -36,
681 : : -17, 45, -7, -41, 29, 26, -43, -3, 44, -20, -34, 38, 13, -45, 11, 39,
682 : : -32, -22, 44, -1, -43, 24, 30, -40, -9, 45, -15, -37, 35, 18, -45, 6,
683 : : 42, -28, -27, 42, 4, -45, 19, 34, -38, -14, 45, -10, -40, 31, 23, -44,
684 : : }, {
685 : : 32, -14, -36, 37, 13, -45, 15, 36, -38, -12, 45, -16, -35, 38, 11, -45,
686 : : 17, 34, -39, -10, 45, -18, -34, 39, 9, -45, 19, 33, -40, -8, 45, -20,
687 : : -32, 40, 7, -45, 21, 31, -41, -6, 44, -22, -30, 41, 4, -44, 23, 30,
688 : : -42, -3, 44, -24, -29, 42, 2, -44, 25, 28, -43, -1, 43, -26, -27, 43,
689 : : }, {
690 : : 32, -16, -34, 40, 4, -44, 27, 24, -44, 8, 39, -36, -13, 45, -19, -31,
691 : : 42, 1, -43, 30, 21, -45, 11, 37, -38, -10, 45, -22, -29, 43, -2, -41,
692 : : 32, 18, -45, 14, 35, -39, -7, 44, -25, -26, 44, -6, -40, 34, 15, -45,
693 : : 17, 33, -41, -3, 43, -28, -23, 45, -9, -38, 36, 12, -45, 20, 30, -42,
694 : : }, {
695 : : 32, -18, -30, 43, -4, -39, 36, 10, -44, 26, 23, -45, 13, 34, -41, -1,
696 : : 42, -33, -15, 45, -21, -28, 44, -8, -38, 38, 7, -44, 29, 20, -45, 16,
697 : : 32, -42, 2, 40, -35, -12, 45, -24, -25, 45, -11, -36, 40, 3, -43, 31,
698 : : 17, -45, 19, 30, -43, 6, 39, -37, -9, 44, -27, -22, 45, -14, -34, 41,
699 : : }, {
700 : : 32, -20, -27, 45, -13, -33, 43, -6, -38, 39, 2, -41, 35, 10, -44, 30,
701 : : 17, -45, 23, 24, -45, 16, 30, -44, 9, 36, -41, 1, 40, -37, -7, 43,
702 : : -32, -14, 45, -26, -21, 45, -19, -28, 44, -12, -34, 42, -4, -38, 39, 3,
703 : : -42, 34, 11, -44, 29, 18, -45, 22, 25, -45, 15, 31, -43, 8, 36, -40,
704 : : }, {
705 : : 32, -22, -23, 45, -21, -24, 45, -20, -25, 45, -19, -26, 45, -18, -27, 45,
706 : : -17, -28, 45, -16, -29, 45, -15, -30, 44, -14, -30, 44, -13, -31, 44, -12,
707 : : -32, 44, -11, -33, 43, -10, -34, 43, -9, -34, 43, -8, -35, 42, -7, -36,
708 : : 42, -6, -36, 41, -4, -37, 41, -3, -38, 40, -2, -38, 40, -1, -39, 39,
709 : : }, {
710 : : 32, -24, -19, 45, -29, -14, 44, -33, -9, 42, -36, -3, 40, -39, 2, 37,
711 : : -42, 8, 34, -44, 13, 30, -45, 18, 25, -45, 23, 20, -45, 28, 15, -44,
712 : : 32, 10, -43, 36, 4, -40, 39, -1, -38, 41, -7, -34, 43, -12, -30, 45,
713 : : -17, -26, 45, -22, -21, 45, -27, -16, 44, -31, -11, 43, -35, -6, 41, -38,
714 : : }, {
715 : : 32, -26, -15, 44, -35, -3, 39, -41, 9, 31, -45, 20, 21, -45, 30, 10,
716 : : -42, 38, -2, -36, 43, -14, -27, 45, -25, -16, 44, -34, -4, 39, -41, 8,
717 : : 32, -45, 19, 22, -45, 30, 11, -42, 38, -1, -36, 43, -13, -28, 45, -24,
718 : : -17, 44, -34, -6, 40, -40, 7, 33, -44, 18, 23, -45, 29, 12, -43, 37,
719 : : }, {
720 : : 32, -28, -11, 41, -40, 8, 30, -45, 25, 14, -43, 38, -4, -33, 45, -22,
721 : : -17, 44, -36, 1, 35, -44, 19, 20, -44, 34, 2, -37, 43, -16, -23, 45,
722 : : -32, -6, 39, -42, 13, 26, -45, 30, 9, -40, 41, -10, -29, 45, -27, -12,
723 : : 42, -39, 7, 31, -45, 24, 15, -43, 38, -3, -34, 45, -21, -18, 44, -36,
724 : : }, {
725 : : 32, -30, -7, 38, -43, 18, 19, -44, 38, -6, -30, 45, -29, -8, 39, -43,
726 : : 17, 20, -44, 37, -4, -31, 45, -28, -9, 39, -43, 16, 21, -44, 36, -3,
727 : : -32, 45, -27, -10, 40, -42, 15, 22, -44, 36, -2, -33, 45, -26, -11, 40,
728 : : -42, 14, 23, -45, 35, -1, -34, 45, -25, -12, 41, -41, 13, 24, -45, 34,
729 : : }, {
730 : : 32, -31, -2, 34, -45, 28, 7, -37, 44, -24, -11, 39, -43, 20, 15, -41,
731 : : 42, -16, -19, 43, -40, 12, 23, -44, 38, -8, -27, 45, -35, 3, 30, -45,
732 : : 32, 1, -34, 45, -29, -6, 36, -45, 25, 10, -39, 44, -21, -14, 41, -42,
733 : : 17, 18, -43, 40, -13, -22, 44, -38, 9, 26, -45, 36, -4, -30, 45, -33,
734 : : }, {
735 : : 32, -33, 2, 30, -45, 36, -7, -26, 44, -38, 11, 22, -43, 40, -15, -18,
736 : : 42, -42, 19, 14, -40, 44, -23, -10, 38, -45, 27, 6, -35, 45, -30, -1,
737 : : 32, -45, 34, -3, -29, 45, -36, 8, 25, -44, 39, -12, -21, 43, -41, 16,
738 : : 17, -41, 43, -20, -13, 39, -44, 24, 9, -37, 45, -28, -4, 34, -45, 31,
739 : : }, {
740 : : 32, -34, 7, 24, -43, 41, -19, -12, 38, -45, 30, -1, -29, 45, -39, 14,
741 : : 17, -40, 44, -26, -4, 33, -45, 36, -9, -22, 43, -42, 21, 10, -36, 45,
742 : : -32, 3, 27, -44, 40, -16, -15, 39, -44, 28, 2, -31, 45, -37, 11, 20,
743 : : -42, 43, -23, -8, 35, -45, 34, -6, -25, 44, -41, 18, 13, -38, 45, -30,
744 : : }, {
745 : : 32, -36, 11, 18, -40, 45, -30, 3, 25, -43, 43, -24, -4, 31, -45, 39,
746 : : -17, -12, 36, -45, 35, -10, -19, 40, -44, 30, -2, -26, 43, -42, 23, 6,
747 : : -32, 45, -39, 16, 13, -37, 45, -34, 9, 20, -41, 44, -29, 1, 27, -44,
748 : : 42, -22, -7, 33, -45, 38, -15, -14, 38, -45, 34, -8, -21, 41, -44, 28,
749 : : }, {
750 : : 32, -37, 15, 12, -35, 45, -39, 18, 9, -33, 45, -40, 21, 6, -30, 44,
751 : : -42, 24, 2, -28, 43, -43, 27, -1, -25, 42, -44, 30, -4, -22, 41, -45,
752 : : 32, -8, -19, 39, -45, 34, -11, -16, 38, -45, 36, -14, -13, 36, -45, 38,
753 : : -17, -10, 34, -45, 40, -20, -7, 31, -44, 41, -23, -3, 29, -44, 43, -26,
754 : : }, {
755 : : 32, -38, 19, 6, -29, 43, -44, 31, -9, -16, 36, -45, 40, -22, -2, 26,
756 : : -42, 45, -34, 12, 13, -34, 45, -41, 25, -1, -23, 40, -45, 36, -15, -10,
757 : : 32, -44, 43, -28, 4, 20, -39, 45, -38, 18, 7, -30, 43, -44, 30, -8,
758 : : -17, 37, -45, 39, -21, -3, 27, -42, 44, -33, 11, 14, -35, 45, -41, 24,
759 : : }, {
760 : : 32, -39, 23, -1, -21, 38, -45, 40, -25, 3, 19, -37, 45, -41, 27, -6,
761 : : -17, 36, -45, 42, -29, 8, 15, -34, 44, -43, 30, -10, -13, 33, -44, 44,
762 : : -32, 12, 11, -31, 43, -44, 34, -14, -9, 30, -43, 45, -35, 16, 7, -28,
763 : : 42, -45, 36, -18, -4, 26, -41, 45, -38, 20, 2, -24, 40, -45, 39, -22,
764 : : }, {
765 : : 32, -40, 27, -8, -13, 31, -43, 45, -38, 22, -2, -18, 35, -44, 44, -34,
766 : : 17, 3, -23, 38, -45, 42, -30, 12, 9, -28, 41, -45, 40, -26, 7, 14,
767 : : -32, 43, -45, 37, -21, 1, 19, -36, 44, -44, 34, -16, -4, 24, -39, 45,
768 : : -42, 30, -11, -10, 29, -41, 45, -39, 25, -6, -15, 33, -43, 45, -36, 20,
769 : : }, {
770 : : 32, -41, 30, -14, -4, 22, -36, 44, -44, 37, -23, 6, 13, -30, 41, -45,
771 : : 42, -31, 15, 3, -21, 36, -44, 45, -38, 24, -7, -12, 29, -40, 45, -42,
772 : : 32, -16, -2, 20, -35, 44, -45, 38, -25, 8, 11, -28, 40, -45, 43, -33,
773 : : 17, 1, -19, 34, -43, 45, -39, 26, -9, -10, 27, -39, 45, -43, 34, -18,
774 : : }, {
775 : : 32, -42, 34, -20, 4, 12, -27, 38, -44, 45, -39, 28, -13, -3, 19, -33,
776 : : 42, -45, 43, -34, 21, -6, -11, 26, -38, 44, -45, 39, -29, 14, 2, -18,
777 : : 32, -41, 45, -43, 35, -22, 7, 10, -25, 37, -44, 45, -40, 30, -15, -1,
778 : : 17, -31, 41, -45, 43, -36, 23, -8, -9, 24, -36, 44, -45, 40, -30, 16,
779 : : }, {
780 : : 32, -43, 36, -26, 13, 1, -15, 28, -38, 44, -45, 42, -35, 24, -11, -3,
781 : : 17, -30, 39, -44, 45, -41, 34, -22, 9, 6, -19, 31, -40, 45, -45, 40,
782 : : -32, 20, -7, -8, 21, -33, 41, -45, 44, -39, 30, -18, 4, 10, -23, 34,
783 : : -42, 45, -44, 38, -29, 16, -2, -12, 25, -36, 43, -45, 43, -37, 27, -14,
784 : : }, {
785 : : 32, -44, 39, -31, 21, -10, -2, 14, -25, 34, -41, 45, -45, 42, -36, 28,
786 : : -17, 6, 7, -18, 29, -37, 43, -45, 44, -40, 34, -24, 13, -1, -11, 22,
787 : : -32, 39, -44, 45, -43, 38, -30, 20, -9, -3, 15, -26, 35, -41, 45, -45,
788 : : 42, -36, 27, -16, 4, 8, -19, 30, -38, 43, -45, 44, -40, 33, -23, 12,
789 : : }, {
790 : : 32, -44, 41, -36, 29, -20, 11, -1, -9, 18, -27, 34, -40, 44, -45, 45,
791 : : -42, 37, -30, 22, -13, 3, 7, -16, 25, -33, 39, -43, 45, -45, 43, -38,
792 : : 32, -24, 15, -6, -4, 14, -23, 31, -38, 42, -45, 45, -43, 39, -34, 26,
793 : : -17, 8, 2, -12, 21, -30, 36, -41, 44, -45, 44, -40, 35, -28, 19, -10,
794 : : }, {
795 : : 32, -45, 43, -39, 35, -30, 23, -16, 9, -1, -7, 14, -21, 28, -34, 38,
796 : : -42, 44, -45, 45, -43, 40, -36, 31, -25, 18, -11, 3, 4, -12, 19, -26,
797 : : 32, -37, 41, -44, 45, -45, 44, -41, 38, -33, 27, -20, 13, -6, -2, 10,
798 : : -17, 24, -30, 36, -40, 43, -45, 45, -44, 42, -39, 34, -29, 22, -15, 8,
799 : : }, {
800 : : 32, -45, 44, -42, 40, -37, 34, -30, 25, -20, 15, -10, 4, 1, -7, 12,
801 : : -17, 22, -27, 31, -35, 38, -41, 43, -44, 45, -45, 45, -43, 41, -39, 36,
802 : : -32, 28, -23, 18, -13, 8, -2, -3, 9, -14, 19, -24, 29, -33, 36, -39,
803 : : 42, -44, 45, -45, 45, -44, 43, -40, 38, -34, 30, -26, 21, -16, 11, -6,
804 : : }, {
805 : : 32, -45, 45, -44, 43, -42, 41, -39, 38, -36, 34, -31, 29, -26, 23, -20,
806 : : 17, -14, 11, -8, 4, -1, -2, 6, -9, 12, -15, 18, -21, 24, -27, 30,
807 : : -32, 34, -36, 38, -40, 41, -43, 44, -44, 45, -45, 45, -45, 45, -44, 43,
808 : : -42, 40, -39, 37, -35, 33, -30, 28, -25, 22, -19, 16, -13, 10, -7, 3,
809 : : }, {
810 : : 32, -45, 45, -45, 45, -45, 45, -45, 44, -44, 44, -44, 43, -43, 43, -42,
811 : : 42, -41, 41, -40, 40, -39, 39, -38, 38, -37, 36, -36, 35, -34, 34, -33,
812 : : 32, -31, 30, -30, 29, -28, 27, -26, 25, -24, 23, -22, 21, -20, 19, -18,
813 : : 17, -16, 15, -14, 13, -12, 11, -10, 9, -8, 7, -6, 4, -3, 2, -1,
814 : : }
815 : : };
|