init
[convexer.git] / src / nbvtf / rgbcx.h
1 // rgbcx.h v1.12
2 // High-performance scalar BC1-5 encoders. Public Domain or MIT license (you choose - see below), written by Richard Geldreich 2020 <richgel99@gmail.com>.
3 //
4 // Influential references:
5 // http://sjbrown.co.uk/2006/01/19/dxt-compression-techniques/
6 // https://github.com/nothings/stb/blob/master/stb_dxt.h
7 // https://gist.github.com/castano/c92c7626f288f9e99e158520b14a61cf
8 // https://github.com/castano/icbc/blob/master/icbc.h
9 // http://www.humus.name/index.php?page=3D&ID=79
10 //
11 // This is a single header file library. Be sure to "#define RGBCX_IMPLEMENTATION" in one .cpp file somewhere.
12 //
13 // Instructions:
14 //
15 // The library MUST be initialized by calling this function at least once before using any encoder or decoder functions:
16 //
17 // void rgbcx::init(bc1_approx_mode mode = cBC1Ideal);
18 //
19 // This function manipulates global state, so it is not thread safe.
20 // You can call it multiple times to change the global BC1 approximation mode.
21 // Important: BC1/3 textures encoded using non-ideal BC1 approximation modes should only be sampled on parts from that vendor.
22 // If you encode for AMD, average error on AMD parts will go down, but average error on NVidia parts will go up and vice versa.
23 // If in doubt, encode in ideal BC1 mode.
24 //
25 // Call these functions to encode BC1-5:
26 // void rgbcx::encode_bc1(uint32_t level, void* pDst, const uint8_t* pPixels, bool allow_3color, bool use_transparent_texels_for_black);
27 // void rgbcx::encode_bc3(uint32_t level, void* pDst, const uint8_t* pPixels);
28 // void rgbcx::encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride = 4);
29 // void rgbcx::encode_bc5(void* pDst, const uint8_t* pPixels, uint32_t chan0 = 0, uint32_t chan1 = 1, uint32_t stride = 4);
30 //
31 // - level ranges from MIN_LEVEL to MAX_LEVEL. The higher the level, the slower the encoder goes, but the higher the average quality.
32 // levels [0,4] are fast and compete against stb_dxt (default and HIGHQUAL). The remaining levels compete against squish/NVTT/icbc and icbc HQ.
33 // If in doubt just use level 10, set allow_3color to true and use_transparent_texels_for_black to false, and adjust as needed.
34 //
35 // - pDst is a pointer to the 8-byte (BC1/4) or 16-byte (BC3/5) destination block.
36 //
37 // - pPixels is a pointer to the 32-bpp pixels, in either RGBX or RGBA format (R is first in memory).
38 // Alpha is always ignored by encode_bc1().
39 //
40 // - allow_3color: If true the encoder will use 3-color blocks. This flag is ignored unless level is >= 5 (because lower levels compete against stb_dxt and it doesn't support 3-color blocks).
41 // Do not enable on BC3-5 textures. 3-color block usage slows down encoding.
42 //
43 // - use_transparent_texels_for_black: If true the encoder will use 3-color block transparent black pixels to code very dark or black texels. Your engine/shader MUST ignore the sampled
44 // alpha value for textures encoded in this mode. This is how NVidia's classic "nvdxt" encoder (used by many original Xbox titles) used to work by default on DXT1C textures. It increases
45 // average quality substantially (because dark texels/black are very common) and is highly recommended.
46 // Do not enable on BC3-5 textures.
47 //
48 // - stride is the source pixel stride, in bytes. It's typically 4.
49 //
50 // - chan0 and chan1 are the source channels. Typically they will be 0 and 1.
51 //
52 // All encoding and decoding functions are threade-safe.
53 //
54 // To reduce the compiled size of the encoder, set #define RGBCX_USE_SMALLER_TABLES to 1 before including this header.
55 //
56 #ifndef RGBCX_INCLUDE_H
57 #define RGBCX_INCLUDE_H
58
59 #include <stdlib.h>
60 #include <stdint.h>
61 #include <algorithm>
62 #include <assert.h>
63 #include <limits.h>
64
65 // By default, the table used to accelerate cluster fit on 4 color blocks uses a 969x128 entry table.
66 // To reduce the executable size, set RGBCX_USE_SMALLER_TABLES to 1, which selects the smaller 969x32 entry table.
67 #ifndef RGBCX_USE_SMALLER_TABLES
68 #define RGBCX_USE_SMALLER_TABLES 1
69 #endif
70
71 namespace rgbcx
72 {
73 enum class bc1_approx_mode
74 {
75 // The default mode. No rounding for 4-color colors 2,3. My older tools/compressors use this mode.
76 // This matches the D3D10 docs on BC1.
77 cBC1Ideal = 0,
78
79 // NVidia GPU mode.
80 cBC1NVidia = 1,
81
82 // AMD GPU mode.
83 cBC1AMD = 2,
84
85 // This mode matches AMD Compressonator's output. It rounds 4-color colors 2,3 (not 3-color color 2).
86 // This matches the D3D9 docs on DXT1.
87 cBC1IdealRound4 = 3
88 };
89
90 // init() MUST be called once before using the BC1 encoder.
91 // This function may be called multiple times to change the BC1 approximation mode.
92 // This function initializes global state, so don't call it while other threads inside the encoder.
93 // Important: If you encode textures for a specific vendor's GPU's, beware that using that texture data on other GPU's may result in ugly artifacts.
94 // Encode to cBC1Ideal unless you know the texture data will only be deployed or used on a specific vendor's GPU.
95 void init(bc1_approx_mode mode = bc1_approx_mode::cBC1Ideal);
96
97 // Optimally encodes a solid color block to BC1 format.
98 void encode_bc1_solid_block(void* pDst, uint32_t fr, uint32_t fg, uint32_t fb, bool allow_3color);
99
100 // BC1 low-level API encoder flags. You can ignore this if you use the simple level API.
101 enum
102 {
103 // Try to improve quality using the most likely total orderings.
104 // The total_orderings_to_try parameter will then control the number of total orderings to try for 4 color blocks, and the
105 // total_orderings_to_try3 parameter will control the number of total orderings to try for 3 color blocks (if they are enabled).
106 cEncodeBC1UseLikelyTotalOrderings = 2,
107
108 // Use 2 least squares pass, instead of one (same as stb_dxt's HIGHQUAL option).
109 // Recommended if you're enabling cEncodeBC1UseLikelyTotalOrderings.
110 cEncodeBC1TwoLeastSquaresPasses = 4,
111
112 // cEncodeBC1Use3ColorBlocksForBlackPixels allows the BC1 encoder to use 3-color blocks for blocks containing black or very dark pixels.
113 // You shader/engine MUST ignore the alpha channel on textures encoded with this flag.
114 // Average quality goes up substantially for my 100 texture corpus (~.5 dB), so it's worth using if you can.
115 // Note the BC1 encoder does not actually support transparency in 3-color mode.
116 // Don't set when encoding to BC3.
117 cEncodeBC1Use3ColorBlocksForBlackPixels = 8,
118
119 // If cEncodeBC1Use3ColorBlocks is set, the encoder can use 3-color mode for a small but noticeable gain in average quality, but lower perf.
120 // If you also specify the cEncodeBC1UseLikelyTotalOrderings flag, set the total_orderings_to_try3 paramter to the number of total orderings to try.
121 // Don't set when encoding to BC3.
122 cEncodeBC1Use3ColorBlocks = 16,
123
124 // cEncodeBC1Iterative will greatly increase encode time, but is very slightly higher quality.
125 // Same as squish's iterative cluster fit option. Not really worth the tiny boost in quality, unless you just don't care about perf. at all.
126 cEncodeBC1Iterative = 32,
127
128 // cEncodeBC1BoundingBox enables a fast all-integer PCA approximation on 4-color blocks.
129 // At level 0 options (no other flags), this is ~15% faster, and higher *average* quality.
130 cEncodeBC1BoundingBox = 64,
131
132 // Use a slightly lower quality, but ~30% faster MSE evaluation function for 4-color blocks.
133 cEncodeBC1UseFasterMSEEval = 128,
134
135 // Examine all colors to compute selectors/MSE (slower than default)
136 cEncodeBC1UseFullMSEEval = 256,
137
138 // Use 2D least squares+inset+optimal rounding (the method used in Humus's GPU texture encoding demo), instead of PCA.
139 // Around 18% faster, very slightly lower average quality to better (depends on the content).
140 cEncodeBC1Use2DLS = 512,
141
142 // Use 6 power iterations vs. 4 for PCA.
143 cEncodeBC1Use6PowerIters = 2048,
144
145 // Check all total orderings - *very* slow. The encoder is not designed to be used in this way.
146 cEncodeBC1Exhaustive = 8192,
147
148 // Try 2 different ways of choosing the initial endpoints.
149 cEncodeBC1TryAllInitialEndponts = 16384,
150
151 // Same as cEncodeBC1BoundingBox, but implemented using integer math (faster, slightly less quality)
152 cEncodeBC1BoundingBoxInt = 32768,
153
154 // Try refining the final endpoints by examining nearby colors.
155 cEncodeBC1EndpointSearchRoundsShift = 22,
156 cEncodeBC1EndpointSearchRoundsMask = 1023U << cEncodeBC1EndpointSearchRoundsShift,
157 };
158
159 const uint32_t MIN_TOTAL_ORDERINGS = 1;
160 const uint32_t MAX_TOTAL_ORDERINGS3 = 32;
161
162 #if RGBCX_USE_SMALLER_TABLES
163 const uint32_t MAX_TOTAL_ORDERINGS4 = 32;
164 #else
165 const uint32_t MAX_TOTAL_ORDERINGS4 = 128;
166 #endif
167
168 // DEFAULT_TOTAL_ORDERINGS_TO_TRY is around 3x faster than libsquish at slightly higher average quality. 10-16 is a good range to start to compete against libsquish.
169 const uint32_t DEFAULT_TOTAL_ORDERINGS_TO_TRY = 10;
170
171 const uint32_t DEFAULT_TOTAL_ORDERINGS_TO_TRY3 = 1;
172
173 // Encodes a 4x4 block of RGBX (X=ignored) pixels to BC1 format.
174 // This is the simplified interface for BC1 encoding, which accepts a level parameter and converts that to the best overall flags.
175 // The pixels are in RGBA format, where R is first in memory. The BC1 encoder completely ignores the alpha channel (i.e. there is no punchthrough alpha support).
176 // This is the recommended function to use for BC1 encoding, becuase it configures the encoder for you in the best possible way (on average).
177 // Note that the 3 color modes won't be used at all until level 5 or higher.
178 // No transparency supported, however if you set use_transparent_texels_for_black to true the encocer will use transparent selectors on very dark/black texels to reduce MSE.
179 const uint32_t MIN_LEVEL = 0, MAX_LEVEL = 18;
180 void encode_bc1(uint32_t level, void* pDst, const uint8_t* pPixels, bool allow_3color, bool use_transparent_texels_for_black);
181
182 // Low-level interface for BC1 encoding.
183 // Always returns a 4 color block, unless cEncodeBC1Use3ColorBlocksForBlackPixels or cEncodeBC1Use3ColorBlock flags are specified.
184 // total_orderings_to_try controls the perf. vs. quality tradeoff on 4-color blocks when the cEncodeBC1UseLikelyTotalOrderings flag is used. It must range between [MIN_TOTAL_ORDERINGS, MAX_TOTAL_ORDERINGS4].
185 // total_orderings_to_try3 controls the perf. vs. quality tradeoff on 3-color bocks when the cEncodeBC1UseLikelyTotalOrderings and the cEncodeBC1Use3ColorBlocks flags are used. Valid range is [0,MAX_TOTAL_ORDERINGS3] (0=disabled).
186 void encode_bc1(void* pDst, const uint8_t* pPixels, uint32_t flags = 0, uint32_t total_orderings_to_try = DEFAULT_TOTAL_ORDERINGS_TO_TRY, uint32_t total_orderings_to_try3 = DEFAULT_TOTAL_ORDERINGS_TO_TRY3);
187
188 // Encodes a 4x4 block of RGBA pixels to BC3 format.
189 // There are two encode_bc3() functions.
190 // The first is the recommended function, which accepts a level parameter.
191 // The second is a low-level version that allows fine control over BC1 encoding.
192 void encode_bc3(uint32_t level, void* pDst, const uint8_t* pPixels);
193 void encode_bc3(void* pDst, const uint8_t* pPixels, uint32_t flags = 0, uint32_t total_orderings_to_try = DEFAULT_TOTAL_ORDERINGS_TO_TRY);
194
195 // Encodes a single channel to BC4.
196 // stride is the source pixel stride in bytes.
197 void encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride = 4);
198
199 // Encodes two channels to BC5.
200 // chan0/chan1 control which channels, stride is the source pixel stride in bytes.
201 void encode_bc5(void* pDst, const uint8_t* pPixels, uint32_t chan0 = 0, uint32_t chan1 = 1, uint32_t stride = 4);
202
203 // Decompression functions.
204
205 // Returns true if the block uses 3 color punchthrough alpha mode.
206 bool unpack_bc1(const void* pBlock_bits, void* pPixels, bool set_alpha = true, bc1_approx_mode mode = bc1_approx_mode::cBC1Ideal);
207
208 void unpack_bc4(const void* pBlock_bits, uint8_t* pPixels, uint32_t stride = 4);
209
210 // Returns true if the block uses 3 color punchthrough alpha mode.
211 bool unpack_bc3(const void* pBlock_bits, void* pPixels, bc1_approx_mode mode = bc1_approx_mode::cBC1Ideal);
212
213 void unpack_bc5(const void* pBlock_bits, void* pPixels, uint32_t chan0 = 0, uint32_t chan1 = 1, uint32_t stride = 4);
214 }
215 #endif // #ifndef RGBCX_INCLUDE_H
216
217 #ifdef RGBCX_IMPLEMENTATION
218 namespace rgbcx
219 {
220 const uint32_t NUM_UNIQUE_TOTAL_ORDERINGS4 = 969;
221
222 // All total orderings for 16 pixels 2-bit selectors.
223 // BC1 selector order 0, 2, 3, 1 (i.e. the selectors are reordered into linear order).
224 static uint8_t g_unique_total_orders4[NUM_UNIQUE_TOTAL_ORDERINGS4][4] =
225 {
226 {0,8,2,6},{4,3,9,0},{4,8,1,3},{12,0,3,1},{11,3,2,0},{6,4,6,0},{7,5,0,4},{6,0,8,2},{1,0,0,15},{3,0,8,5},{1,1,13,1},{13,1,2,0},{0,14,1,1},{0,15,1,0},{0,13,0,3},{16,0,0,0},{4,3,4,5},{8,6,0,2},{0,10,0,6},{10,0,4,2},{7,2,1,6},{4,7,5,0},{1,4,7,4},{0,14,2,0},{2,7,2,5},{9,0,5,2},{9,2,2,3},{10,0,5,1},{2,3,7,4},{4,9,0,3},{1,5,0,10},{1,1,6,8},
227 {6,6,4,0},{11,5,0,0},{11,2,0,3},{4,0,10,2},{2,3,10,1},{1,13,1,1},{0,14,0,2},{2,3,3,8},{12,3,1,0},{14,0,0,2},{9,1,3,3},{6,4,0,6},{1,1,5,9},{5,9,0,2},{2,10,1,3},{12,0,0,4},{4,6,6,0},{0,6,4,6},{3,7,4,2},{0,13,3,0},{3,10,0,3},{10,2,1,3},{1,12,1,2},{2,0,13,1},{11,0,5,0},{12,1,3,0},{6,4,5,1},{10,4,2,0},{3,6,1,6},{7,3,6,0},{10,4,0,2},{10,0,2,4},
228 {0,5,9,2},{0,9,3,4},{6,4,2,4},{3,4,7,2},{3,3,5,5},{4,2,9,1},{6,2,8,0},{3,5,3,5},{4,10,1,1},{10,1,3,2},{5,7,0,4},{5,3,7,1},{6,8,1,1},{8,8,0,0},{11,1,0,4},{14,1,0,1},{9,3,2,2},{8,2,1,5},{0,0,2,14},{3,3,9,1},{10,1,5,0},{8,3,1,4},{1,5,8,2},{6,1,9,0},{3,2,1,10},{3,11,1,1},{7,6,3,0},{9,0,3,4},{5,2,5,4},{0,2,3,11},{15,0,0,1},{0,6,6,4},
229 {3,4,9,0},{4,7,0,5},{0,4,4,8},{0,13,2,1},{2,4,1,9},{3,2,5,6},{10,6,0,0},{3,5,6,2},{8,0,4,4},{1,3,6,6},{7,7,0,2},{6,1,4,5},{0,11,1,4},{2,2,8,4},{0,1,2,13},{15,0,1,0},{7,2,6,1},{8,1,7,0},{1,8,4,3},{2,13,1,0},{1,0,7,8},{14,2,0,0},{1,8,1,6},{9,3,3,1},{0,0,7,9},{4,4,1,7},{9,0,6,1},{10,2,4,0},{1,7,3,5},{0,3,8,5},{5,2,4,5},{1,2,5,8},
230 {0,8,7,1},{10,3,2,1},{12,0,4,0},{2,1,4,9},{5,2,2,7},{1,9,3,3},{15,1,0,0},{6,3,4,3},{9,5,0,2},{1,6,9,0},{6,6,0,4},{13,2,1,0},{5,1,8,2},{0,5,11,0},{7,1,0,8},{1,2,12,1},{0,3,3,10},{7,4,2,3},{5,1,4,6},{7,0,3,6},{3,12,0,1},{3,4,5,4},{1,10,0,5},{7,4,3,2},{10,5,0,1},{13,3,0,0},{2,5,4,5},{3,10,1,2},{5,1,2,8},{14,0,1,1},{1,5,4,6},{1,4,5,6},
231 {2,3,11,0},{11,0,4,1},{11,2,2,1},{5,3,8,0},{1,3,10,2},{0,1,13,2},{3,1,4,8},{4,2,4,6},{1,5,6,4},{2,1,11,2},{1,2,9,4},{4,7,3,2},{6,2,5,3},{7,2,2,5},{8,1,4,3},{3,2,8,3},{12,1,0,3},{7,8,1,0},{7,0,2,7},{5,10,0,1},{0,2,14,0},{2,9,3,2},{7,0,0,9},{11,1,4,0},{10,4,1,1},{2,2,9,3},{5,7,2,2},{1,3,1,11},{13,2,0,1},{4,2,8,2},{2,3,1,10},{4,2,5,5},
232 {7,0,7,2},{10,0,0,6},{0,8,5,3},{4,4,0,8},{12,4,0,0},{0,1,14,1},{8,0,1,7},{5,1,5,5},{11,0,3,2},{0,4,1,11},{0,8,8,0},{0,2,5,9},{7,3,2,4},{7,8,0,1},{1,0,3,12},{7,4,5,0},{1,6,7,2},{7,6,1,2},{9,6,1,0},{12,2,0,2},{4,1,6,5},{4,0,1,11},{8,4,4,0},{13,0,1,2},{8,6,2,0},{4,12,0,0},{2,7,5,2},{2,0,5,9},{5,4,5,2},{3,8,5,0},{7,3,3,3},{4,4,8,0},
233 {2,1,3,10},{5,0,1,10},{6,4,3,3},{4,9,1,2},{1,4,0,11},{11,3,1,1},{4,0,12,0},{13,0,0,3},{6,1,6,3},{9,0,4,3},{8,0,0,8},{8,4,0,4},{0,12,1,3},{0,4,10,2},{3,4,8,1},{1,3,8,4},{9,2,5,0},{5,7,4,0},{1,0,11,4},{4,10,0,2},{1,3,12,0},{6,9,0,1},{5,0,9,2},{5,9,2,0},{13,1,0,2},{9,3,4,0},{9,4,0,3},{3,1,12,0},{2,4,3,7},{1,2,13,0},{2,2,4,8},{6,8,0,2},
234 {9,2,1,4},{9,5,1,1},{2,0,4,10},{5,4,0,7},{0,0,6,10},{1,2,0,13},{4,7,2,3},{6,5,5,0},{3,3,1,9},{1,6,1,8},{12,2,1,1},{4,4,5,3},{1,0,6,9},{0,6,10,0},{4,8,3,1},{4,3,2,7},{2,1,7,6},{1,9,1,5},{3,1,3,9},{8,7,1,0},{1,2,3,10},{14,1,1,0},{5,4,4,3},{3,7,0,6},{7,4,1,4},{3,7,5,1},{1,1,0,14},{0,10,3,3},{0,4,3,9},{1,7,7,1},{2,0,10,4},{5,8,0,3},
235 {6,7,3,0},{0,8,4,4},{5,7,3,1},{7,9,0,0},{7,6,2,1},{0,4,5,7},{6,3,5,2},{1,2,1,12},{5,2,0,9},{8,5,0,3},{4,6,1,5},{1,1,7,7},{10,5,1,0},{1,2,8,5},{1,8,2,5},{5,1,0,10},{6,9,1,0},{13,0,2,1},{8,3,5,0},{6,3,6,1},{2,11,3,0},{3,7,3,3},{1,5,2,8},{7,5,2,2},{0,6,7,3},{13,1,1,1},{5,3,4,4},{7,2,7,0},{5,8,3,0},{3,13,0,0},{0,7,9,0},{8,0,3,5},
236 {1,3,7,5},{4,0,2,10},{12,0,1,3},{1,7,6,2},{3,9,0,4},{7,2,0,7},{0,1,7,8},{2,1,8,5},{0,13,1,2},{0,8,1,7},{5,0,11,0},{5,6,2,3},{0,3,0,13},{2,3,4,7},{5,6,3,2},{4,2,10,0},{3,3,7,3},{7,2,5,2},{1,1,11,3},{12,3,0,1},{5,1,1,9},{1,15,0,0},{9,7,0,0},{9,1,2,4},{0,7,3,6},{3,0,13,0},{3,0,11,2},{0,6,5,5},{8,2,2,4},{6,10,0,0},{4,8,4,0},{0,0,3,13},
237 {0,4,12,0},{7,1,6,2},{3,5,0,8},{8,0,6,2},{6,2,3,5},{2,10,0,4},{4,11,0,1},{6,1,5,4},{5,1,3,7},{0,11,3,2},{4,6,0,6},{2,6,0,8},{3,1,7,5},{2,14,0,0},{2,9,2,3},{0,3,4,9},{11,0,1,4},{13,0,3,0},{8,3,0,5},{0,5,3,8},{5,11,0,0},{0,1,4,11},{2,1,9,4},{3,4,4,5},{7,1,2,6},{12,2,2,0},{9,4,1,2},{6,0,2,8},{4,6,2,4},{11,2,3,0},{3,2,2,9},{10,3,1,2},
238 {1,1,2,12},{0,5,2,9},{0,1,11,4},{6,2,4,4},{2,8,2,4},{0,9,4,3},{11,0,2,3},{0,2,11,3},{6,0,7,3},{0,3,6,7},{4,5,5,2},{1,2,6,7},{7,5,1,3},{9,0,2,5},{2,6,4,4},{4,1,9,2},{4,8,2,2},{1,12,3,0},{0,9,6,1},{0,10,6,0},{3,1,5,7},{2,13,0,1},{2,2,1,11},{3,6,0,7},{5,6,5,0},{5,5,4,2},{4,0,3,9},{3,4,1,8},{0,11,2,3},{2,12,1,1},{7,1,3,5},{7,0,9,0},
239 {8,0,8,0},{1,0,2,13},{3,3,10,0},{2,4,4,6},{2,3,8,3},{1,10,5,0},{7,3,0,6},{2,9,0,5},{1,4,6,5},{6,6,3,1},{5,6,0,5},{6,3,0,7},{3,10,2,1},{2,5,5,4},{3,8,4,1},{1,14,0,1},{10,3,3,0},{3,5,7,1},{1,1,3,11},{2,4,0,10},{9,3,1,3},{5,10,1,0},{3,0,6,7},{3,1,9,3},{11,2,1,2},{5,3,3,5},{0,5,1,10},{4,1,11,0},{10,2,0,4},{7,6,0,3},{2,7,0,7},{4,2,2,8},
240 {6,1,7,2},{4,9,2,1},{0,0,8,8},{3,7,2,4},{9,6,0,1},{0,12,4,0},{6,7,1,2},{0,7,2,7},{1,0,10,5},{0,0,14,2},{2,7,3,4},{5,0,0,11},{7,7,1,1},{6,2,7,1},{4,5,3,4},{3,5,1,7},{5,9,1,1},{6,2,1,7},{3,2,0,11},{0,11,0,5},{3,11,2,0},{10,1,4,1},{7,0,4,5},{11,4,0,1},{10,3,0,3},{0,2,4,10},{0,15,0,1},{0,11,5,0},{6,7,2,1},{1,12,2,1},{4,1,3,8},{1,0,13,2},
241 {1,8,5,2},{7,0,1,8},{3,12,1,0},{9,2,4,1},{1,7,4,4},{11,4,1,0},{4,3,8,1},{2,8,4,2},{1,11,3,1},{1,1,4,10},{4,10,2,0},{8,2,5,1},{1,0,9,6},{5,3,2,6},{0,9,7,0},{10,2,2,2},{5,8,1,2},{8,7,0,1},{0,3,12,1},{1,0,1,14},{4,8,0,4},{3,8,0,5},{4,6,5,1},{0,9,5,2},{10,2,3,1},{2,3,9,2},{1,0,12,3},{11,3,0,2},{4,5,2,5},{0,2,12,2},{9,1,0,6},{9,2,0,5},
242 {1,2,7,6},{4,7,4,1},{0,12,2,2},{0,0,0,16},{2,8,3,3},{3,6,2,5},{0,6,3,7},{7,5,4,0},{3,3,3,7},{3,3,0,10},{5,0,6,5},{0,0,10,6},{8,5,3,0},{8,1,5,2},{6,0,9,1},{11,1,2,2},{2,11,2,1},{9,5,2,0},{3,0,4,9},{2,2,12,0},{2,6,6,2},{2,1,13,0},{6,0,5,5},{2,0,14,0},{2,11,1,2},{4,4,7,1},{2,0,11,3},{3,1,1,11},{2,9,4,1},{3,7,6,0},{14,0,2,0},{1,10,4,1},
243 {8,0,7,1},{3,6,5,2},{0,3,11,2},{2,5,6,3},{11,1,3,1},{6,5,3,2},{3,8,1,4},{0,2,7,7},{2,10,2,2},{1,6,2,7},{11,0,0,5},{12,1,1,2},{12,1,2,1},{0,7,1,8},{0,3,9,4},{0,2,1,13},{7,1,4,4},{10,1,0,5},{4,0,8,4},{5,2,7,2},{0,2,0,14},{4,3,7,2},{2,7,1,6},{1,2,2,11},{6,3,3,4},{1,14,1,0},{2,4,6,4},{5,3,6,2},{5,3,5,3},{8,4,1,3},{1,3,0,12},{3,5,2,6},
244 {1,8,7,0},{0,7,4,5},{2,1,6,7},{4,11,1,0},{7,2,4,3},{6,1,3,6},{4,5,4,3},{2,11,0,3},{1,5,7,3},{12,0,2,2},{5,0,4,7},{1,13,0,2},{7,7,2,0},{4,1,7,4},{4,5,0,7},{5,0,5,6},{6,5,4,1},{2,4,2,8},{1,10,1,4},{6,3,1,6},{3,3,8,2},{0,7,7,2},{4,4,2,6},{1,1,8,6},{1,12,0,3},{2,1,12,1},{1,9,2,4},{1,11,0,4},{2,5,2,7},{10,0,3,3},{4,6,3,3},{3,7,1,5},
245 {1,9,0,6},{7,1,7,1},{1,6,5,4},{9,2,3,2},{6,2,2,6},{2,2,2,10},{8,3,3,2},{0,1,8,7},{2,0,8,6},{0,3,1,12},{9,4,2,1},{9,4,3,0},{6,2,6,2},{1,8,0,7},{5,1,10,0},{0,5,5,6},{8,2,4,2},{2,3,2,9},{6,0,3,7},{2,2,6,6},{2,6,2,6},{1,13,2,0},{9,3,0,4},{7,3,5,1},{6,5,2,3},{5,2,6,3},{2,0,12,2},{5,7,1,3},{8,1,3,4},{3,1,10,2},{1,0,15,0},{0,8,0,8},
246 {5,0,7,4},{4,4,6,2},{0,1,0,15},{10,0,1,5},{7,3,4,2},{4,9,3,0},{2,5,7,2},{3,4,2,7},{8,3,2,3},{5,1,6,4},{0,10,2,4},{6,6,1,3},{6,0,0,10},{4,4,3,5},{1,3,9,3},{7,5,3,1},{3,0,7,6},{1,8,6,1},{4,3,0,9},{3,11,0,2},{6,0,6,4},{0,1,3,12},{0,4,2,10},{5,5,6,0},{4,1,4,7},{8,1,6,1},{5,6,4,1},{8,4,2,2},{4,3,1,8},{3,0,2,11},{1,11,4,0},{0,8,3,5},
247 {5,1,7,3},{7,0,8,1},{4,3,5,4},{4,6,4,2},{3,2,4,7},{1,6,3,6},{0,7,8,1},{3,0,1,12},{9,1,4,2},{7,4,0,5},{1,7,0,8},{5,4,1,6},{9,1,5,1},{1,1,9,5},{4,1,1,10},{5,3,0,8},{2,2,5,7},{4,0,0,12},{9,0,7,0},{3,4,0,9},{0,2,6,8},{8,2,0,6},{3,2,6,5},{4,2,6,4},{3,6,4,3},{2,8,6,0},{5,0,3,8},{0,4,0,12},{0,16,0,0},{0,9,2,5},{4,0,11,1},{1,6,4,5},
248 {0,1,6,9},{3,4,6,3},{3,0,10,3},{7,0,6,3},{1,4,9,2},{1,5,3,7},{8,5,2,1},{0,12,0,4},{7,2,3,4},{0,5,6,5},{11,1,1,3},{6,5,0,5},{2,1,5,8},{1,4,11,0},{9,1,1,5},{0,0,13,3},{5,8,2,1},{2,12,0,2},{3,3,6,4},{4,1,10,1},{4,0,5,7},{8,1,0,7},{5,1,9,1},{4,3,3,6},{0,2,2,12},{6,3,2,5},{0,0,12,4},{1,5,1,9},{2,6,5,3},{3,6,3,4},{2,12,2,0},{1,6,8,1},
249 {10,1,1,4},{1,3,4,8},{7,4,4,1},{1,11,1,3},{1,2,10,3},{3,9,3,1},{8,5,1,2},{2,10,4,0},{4,2,0,10},{2,7,6,1},{8,2,3,3},{1,5,5,5},{3,1,0,12},{3,10,3,0},{8,0,5,3},{0,6,8,2},{0,3,13,0},{0,0,16,0},{1,9,4,2},{4,1,8,3},{1,6,6,3},{0,10,5,1},{0,1,12,3},{4,0,6,6},{3,8,3,2},{0,5,4,7},{1,0,14,1},{0,4,6,6},{3,9,1,3},{3,5,8,0},{3,6,6,1},{5,4,7,0},
250 {3,0,12,1},{8,6,1,1},{2,9,5,0},{6,1,1,8},{4,1,2,9},{3,9,4,0},{5,2,9,0},{0,12,3,1},{1,4,10,1},{4,0,7,5},{3,1,2,10},{5,4,2,5},{5,5,5,1},{4,2,3,7},{1,7,5,3},{2,8,0,6},{8,1,2,5},{3,8,2,3},{6,1,2,7},{3,9,2,2},{9,0,0,7},{0,8,6,2},{8,4,3,1},{0,2,8,6},{6,5,1,4},{2,3,5,6},{2,10,3,1},{0,7,0,9},{4,2,7,3},{2,4,8,2},{7,1,1,7},{2,4,7,3},
251 {2,4,10,0},{0,1,10,5},{4,7,1,4},{0,10,4,2},{9,0,1,6},{1,9,6,0},{3,3,4,6},{4,5,7,0},{5,5,2,4},{2,8,1,5},{2,3,6,5},{0,1,1,14},{3,2,3,8},{10,1,2,3},{9,1,6,0},{3,4,3,6},{2,2,0,12},{0,0,9,7},{4,0,9,3},{7,0,5,4},{4,5,6,1},{2,5,1,8},{2,5,9,0},{3,5,4,4},{1,3,11,1},{7,1,5,3},{3,2,7,4},{1,4,2,9},{1,11,2,2},{2,2,3,9},{5,0,10,1},{3,2,11,0},
252 {1,10,3,2},{8,3,4,1},{3,6,7,0},{0,7,5,4},{1,3,3,9},{2,2,10,2},{1,9,5,1},{0,5,0,11},{3,0,3,10},{0,4,8,4},{2,7,7,0},{2,0,2,12},{1,2,11,2},{6,3,7,0},{0,6,2,8},{0,10,1,5},{0,9,0,7},{6,4,4,2},{6,0,1,9},{1,5,10,0},{5,4,6,1},{5,5,3,3},{0,0,4,12},{0,3,2,11},{1,4,1,10},{3,0,9,4},{5,5,0,6},{1,7,8,0},{2,0,3,11},{6,4,1,5},{10,0,6,0},{0,6,0,10},
253 {0,4,11,1},{3,1,6,6},{2,5,8,1},{0,2,10,4},{3,1,11,1},{6,6,2,2},{1,1,10,4},{2,1,2,11},{6,1,8,1},{0,2,13,1},{0,7,6,3},{6,8,2,0},{3,0,0,13},{4,4,4,4},{6,2,0,8},{7,3,1,5},{0,11,4,1},{6,7,0,3},{2,6,3,5},{5,2,1,8},{7,1,8,0},{5,5,1,5},{1,8,3,4},{8,2,6,0},{6,0,10,0},{5,6,1,4},{1,4,4,7},{2,7,4,3},{1,4,8,3},{5,4,3,4},{1,10,2,3},{2,9,1,4},
254 {2,2,11,1},{2,5,0,9},{0,0,1,15},{0,0,11,5},{0,4,7,5},{0,1,15,0},{2,1,0,13},{0,3,10,3},{8,0,2,6},{3,3,2,8},{3,5,5,3},{1,7,1,7},{1,3,2,10},{4,0,4,8},{2,0,9,5},{1,1,1,13},{2,2,7,5},{2,1,10,3},{4,2,1,9},{4,3,6,3},{1,3,5,7},{2,5,3,6},{1,0,8,7},{5,0,2,9},{2,8,5,1},{1,6,0,9},{0,0,5,11},{0,4,9,3},{2,0,7,7},{1,7,2,6},{2,1,1,12},{2,4,9,1},
255 {0,5,7,4},{6,0,4,6},{3,2,10,1},{0,6,1,9},{2,6,1,7},{0,5,8,3},{4,1,0,11},{1,2,4,9},{4,1,5,6},{6,1,0,9},{1,4,3,8},{4,5,1,6},{1,0,5,10},{5,3,1,7},{0,9,1,6},{2,0,1,13},{2,0,6,8},{8,1,1,6},{1,5,9,1},{0,6,9,1},{0,3,5,8},{0,2,9,5},{5,2,8,1},{1,1,14,0},{3,2,9,2},{5,0,8,3},{0,5,10,1},{5,2,3,6},{2,6,7,1},{2,3,0,11},{0,1,9,6},{1,0,4,11},
256 {3,0,5,8},{0,0,15,1},{2,4,5,5},{0,3,7,6},{2,0,0,14},{1,1,12,2},{2,6,8,0},{3,1,8,4},{0,1,5,10}
257 };
258
259 // All total orderings for 16 pixels [0,2] 2-bit selectors.
260 // BC1 selector order: 0, 1, 2
261 // Note this is different from g_unique_total_orders4[], which reorders the selectors into linear order.
262 const uint32_t NUM_UNIQUE_TOTAL_ORDERINGS3 = 153;
263 static uint8_t g_unique_total_orders3[NUM_UNIQUE_TOTAL_ORDERINGS3][3] =
264 {
265 {6,0,10},{3,6,7},{3,0,13},{13,3,0},{12,4,0},{9,1,6},{2,13,1},{4,7,5},{7,5,4},{9,6,1},{7,4,5},{8,6,2},{16,0,0},{10,6,0},{2,7,7},
266 {0,0,16},{0,3,13},{1,15,0},{0,2,14},{1,4,11},{15,1,0},{1,12,3},{9,2,5},{14,1,1},{8,2,6},{3,3,10},{4,2,10},{14,0,2},{0,14,2},{1,7,8},{6,6,4},
267 {11,5,0},{6,4,6},{11,3,2},{4,3,9},{7,1,8},{10,4,2},{12,1,3},{11,0,5},{9,3,4},{1,0,15},{9,0,7},{2,6,8},{12,2,2},{6,2,8},{6,8,2},{15,0,1},
268 {4,8,4},{0,4,12},{8,5,3},{5,9,2},{11,2,3},{12,3,1},{6,3,7},{1,1,14},{2,9,5},{1,8,7},{4,10,2},{7,7,2},{13,1,2},{0,15,1},{3,2,11},{7,0,9},
269 {4,4,8},{3,8,5},{0,5,11},{13,2,1},{1,10,5},{4,11,1},{3,10,3},{5,10,1},{10,2,4},{0,6,10},{14,2,0},{11,4,1},{3,12,1},{1,13,2},{1,5,10},{5,11,0},
270 {12,0,4},{8,1,7},{6,10,0},{3,13,0},{7,2,7},{0,7,9},{5,8,3},{0,12,4},{11,1,4},{13,0,3},{0,16,0},{5,7,4},{10,3,3},{10,0,6},{0,13,3},{4,6,6},
271 {2,8,6},{2,5,9},{7,8,1},{2,1,13},{2,0,14},{7,3,6},{5,1,10},{3,11,2},{5,4,7},{8,3,5},{10,5,1},{6,9,1},{1,3,12},{4,5,7},{2,2,12},{4,1,11},
272 {0,8,8},{4,12,0},{6,5,5},{8,7,1},{5,5,6},{3,7,6},{7,9,0},{4,9,3},{0,10,6},{8,0,8},{5,3,8},{10,1,5},{6,1,9},{7,6,3},{9,5,2},{0,1,15},
273 {9,7,0},{2,14,0},{3,4,9},{8,4,4},{9,4,3},{0,9,7},{1,9,6},{3,9,4},{5,2,9},{2,3,11},{5,6,5},{1,14,1},{6,7,3},{2,4,10},{2,12,2},{8,8,0},
274 {2,10,4},{4,0,12},{0,11,5},{2,11,3},{1,11,4},{3,5,8},{5,0,11},{3,1,12},{1,2,13},{1,6,9}
275 };
276
277 // For each total ordering, this table indicates which other total orderings are likely to improve quality using a least squares pass. Each array is sorted by usefulness.
278 static uint16_t g_best_total_orderings4[NUM_UNIQUE_TOTAL_ORDERINGS4][MAX_TOTAL_ORDERINGS4] =
279 {
280 #if RGBCX_USE_SMALLER_TABLES
281 { 202,120,13,318,15,23,403,450,5,51,260,128,77,21,33,494,515,523,4,141,269,1,2,700,137,49,48,102,7,64,753,82 },
282 { 13,141,23,217,115,51,77,2,64,21,0,4,5,317,137,269,202,33,318,7,291,352,9,10,3,180,32,6,365,102,341,349 },
283 { 29,58,262,1,52,74,6,171,5,287,151,334,27,500,75,26,331,223,53,635,220,19,50,45,46,17,14,396,163,409,324,70 },
284 { 40,51,33,453,14,23,62,56,12,196,730,475,153,99,403,775,117,130,585,34,4,17,162,11,139,57,102,38,108,47,123,440 },
285 { 33,23,51,13,102,64,202,128,12,40,15,196,153,10,1,2,77,99,141,0,515,5,117,3,120,403,700,165,22,14,269,453 },
286 { 13,23,51,4,77,141,202,33,115,64,32,128,0,11,177,40,15,102,2,217,7,137,269,21,90,59,515,1,180,403,22,6 },
287 { 26,235,19,47,648,624,78,145,27,112,122,64,444,6,630,453,25,42,65,130,711,85,390,113,416,108,665,29,730,138,644,95 },
288 { 64,141,352,751,217,247,237,437,177,269,86,954,947,875,32,318,95,77,304,92,597,180,232,291,128,864,349,588,372,202,312,1 },
289 { 642,898,180,638,901,341,82,197,10,951,15,515,165,762,700,253,811,753,752,365,143,479,244,569,8,110,351,873,55,31,499,116 },
290 { 221,23,51,125,438,254,13,21,39,49,308,656,0,115,530,159,158,401,30,166,912,386,165,688,518,9,105,627,424,22,421,33 },
291 { 143,31,1,44,197,8,180,125,116,55,13,498,23,341,638,242,93,15,2,141,0,901,752,115,36,206,165,479,338,365,515,762 },
292 { 12,23,51,13,14,15,37,99,515,38,700,117,2,196,134,153,753,64,54,33,128,120,21,0,328,5,139,82,453,719,457,1 },
293 { 13,15,23,515,961,700,457,753,51,115,4,165,197,2,38,569,1,474,0,37,99,719,5,12,629,14,11,3,33,77,64,10 },
294 { 15,515,700,753,1,0,2,4,3,23,134,12,961,5,10,197,11,33,82,120,457,51,165,7,6,341,217,21,77,9,40,180 },
295 { 13,51,23,457,719,961,730,401,165,453,0,117,386,15,134,1,758,153,12,54,515,99,11,2,700,5,753,4,308,33,6,899 },
296 { 134,898,82,117,13,33,77,102,23,260,341,351,120,901,197,153,961,111,196,110,180,457,854,10,450,8,165,40,4,115,0,365 },
297 { 60,18,126,167,35,16,191,71,24,92,121,271,68,107,212,146,118,150,199,7,21,1,9,575,727,5,566,48,0,132,108,273 },
298 { 62,136,129,123,128,41,162,17,249,211,214,789,618,710,38,678,248,507,57,64,152,269,119,3,177,183,597,106,4,179,216,90 },
299 { 403,523,51,475,494,453,817,899,202,23,450,13,421,120,102,730,33,128,4,1,805,5,7,153,757,260,318,196,77,457,326,65 },
300 { 4,59,3,62,12,33,56,193,27,21,102,17,40,77,76,84,32,0,6,123,119,177,128,11,18,611,605,25,13,51,73,210 },
301 { 43,20,319,422,414,945,0,7,819,61,5,376,325,173,804,904,470,693,97,707,14,49,22,104,147,107,95,32,426,1,330,577 },
302 { 13,23,51,2,0,115,4,141,217,33,10,77,1,15,64,180,3,515,7,6,22,102,11,5,40,9,165,700,202,197,317,341 },
303 { 28,49,0,105,1,24,65,159,35,55,95,239,16,2,109,7,9,14,170,320,347,168,424,158,10,301,124,5,67,21,64,36 },
304 { 15,515,700,753,0,1,13,2,117,4,12,10,5,165,457,3,9,134,11,7,6,51,77,64,961,82,33,197,14,341,120,141 },
305 { 7,71,14,149,97,18,60,16,150,92,398,189,140,124,24,273,35,2,69,302,154,68,0,336,517,43,66,28,118,251,230,1 },
306 { 4,102,33,77,40,59,11,624,210,12,128,342,5,503,91,139,64,32,25,494,202,678,416,0,403,275,21,450,196,318,523,177 },
307 { 25,19,42,6,122,813,256,235,85,26,436,53,297,573,680,390,445,63,27,416,80,233,65,73,389,283,45,605,194,17,250,343 },
308 { 402,102,202,128,33,300,403,23,12,77,40,21,342,117,483,99,25,494,6,4,63,32,84,569,139,757,475,318,19,26,196,134 },
309 { 158,9,0,109,39,49,65,22,35,168,55,24,68,124,159,16,185,344,333,154,254,272,175,289,1,577,95,28,105,810,30,169 },
310 { 197,180,115,237,498,165,2,5,287,546,400,3,61,34,509,13,297,80,341,52,45,186,58,881,23,873,468,176,64,17,311,250 },
311 { 120,968,373,260,704,110,450,202,137,318,77,95,269,326,217,717,661,652,851,349,93,1,518,98,827,291,21,177,82,33,848,719 },
312 { 44,116,144,268,434,489,367,384,98,127,918,93,948,31,206,940,855,0,203,137,9,22,617,141,332,105,393,492,959,282,299,131 },
313 { 13,77,23,33,51,0,64,141,102,4,2,115,1,6,202,15,10,128,269,7,177,180,3,40,22,11,515,217,117,318,700,137 },
314 { 15,515,700,753,4,11,141,40,165,23,64,180,13,202,32,3,51,125,5,197,21,128,0,93,77,1,120,82,269,117,110,59 },
315 { 176,231,585,62,34,14,412,161,56,236,527,57,17,3,51,202,4,23,369,283,128,13,472,440,84,361,136,457,381,130,719,53 },
316 { 9,0,180,217,237,101,141,352,88,100,230,64,175,317,115,498,68,39,30,1,702,83,213,36,365,208,752,13,252,321,952,546 },
317 { 28,9,22,1,49,0,109,39,83,95,86,30,13,105,128,55,141,168,158,67,31,159,208,12,96,5,185,2,160,64,137,23 },
318 { 72,4,38,12,51,89,477,11,57,76,401,308,23,474,99,148,413,179,59,13,431,152,54,569,17,3,205,629,197,421,405,15 },
319 { 457,13,23,961,15,51,515,700,165,12,753,629,11,1,719,117,0,3,2,37,569,197,40,328,33,5,153,134,99,64,38,196 },
320 { 254,100,310,9,30,1,39,625,166,265,190,0,272,557,131,731,31,98,578,688,404,93,101,88,49,21,127,264,44,36,252,478 },
321 { 51,23,12,13,15,128,99,120,10,202,515,153,64,82,700,33,165,2,5,117,403,1,141,0,3,196,37,453,753,197,260,93 },
322 { 38,99,542,139,453,117,196,23,457,13,328,111,37,134,961,11,12,51,40,775,587,401,474,54,153,477,41,629,33,475,14,277 },
323 { 6,85,25,233,343,91,26,63,138,29,19,65,283,4,81,235,42,122,605,64,648,256,174,370,74,389,718,59,45,194,445,416 },
324 { 49,5,97,20,197,21,18,193,0,64,408,729,173,350,43,422,165,7,14,104,61,32,509,713,523,102,120,95,125,397,35,232 },
325 { 144,116,268,434,384,489,367,206,93,855,940,44,98,332,617,127,959,911,137,282,203,31,22,219,141,9,131,276,417,0,1,120 },
326 { 17,106,64,62,32,255,136,292,476,162,129,241,123,141,41,237,720,214,209,352,519,211,186,148,752,247,507,90,21,77,197,119 },
327 { 2,29,52,50,5,58,14,6,27,1,366,357,45,53,17,19,171,151,26,181,133,38,218,764,287,583,61,113,3,487,600,281 },
328 { 130,59,196,412,381,730,711,236,77,210,202,402,453,99,401,108,361,803,291,283,153,4,57,51,128,183,14,719,503,117,23,11 },
329 { 13,23,51,141,77,4,33,64,115,0,217,10,180,202,2,102,11,9,15,165,40,21,128,352,22,7,197,3,317,515,269,1 },
330 { 23,13,202,51,120,15,21,5,141,1,128,269,137,515,64,102,125,48,98,33,260,523,318,93,700,165,450,77,2,12,403,82 },
331 { 1,2,14,46,29,67,38,52,5,171,58,24,103,69,96,70,83,181,54,75,163,223,16,45,112,309,155,0,186,35,18,108 },
332 { 15,515,700,753,13,0,1,2,153,5,23,10,117,3,9,7,134,165,12,6,341,33,4,14,77,457,115,21,719,180,217,82 },
333 { 197,165,509,13,391,180,308,115,23,546,5,498,2,29,3,401,901,61,34,80,14,457,250,569,237,873,38,297,45,15,468,386 },
334 { 19,73,27,250,200,714,444,472,26,53,34,17,813,322,283,390,128,297,78,123,432,14,436,136,106,690,57,122,389,80,503,3 },
335 { 3,17,21,45,62,32,38,12,155,14,2,328,5,99,401,536,828,13,227,488,106,51,719,119,540,76,165,221,115,629,209,41 },
336 { 115,341,873,197,365,13,901,180,569,752,317,1,10,498,143,634,261,0,509,15,943,237,44,31,116,601,165,127,282,23,141,64 },
337 { 453,51,23,403,33,421,475,102,15,153,196,515,13,700,117,523,12,40,753,21,4,134,0,494,670,899,22,801,730,10,11,401 },
338 { 23,13,51,33,12,117,153,134,453,196,15,99,515,40,14,700,128,102,11,753,77,64,403,202,0,401,475,37,65,2,3,38 },
339 { 2,7,5,14,70,1,29,61,52,45,6,112,66,16,21,32,592,46,38,135,87,58,186,315,290,128,113,0,64,48,227,23 },
340 { 33,23,102,51,128,13,64,202,141,1,77,10,153,40,196,117,2,3,0,5,15,269,403,12,137,134,318,165,120,6,453,99 },
341 { 16,92,7,20,43,35,126,71,60,14,107,18,68,97,0,121,279,149,24,246,191,48,118,575,55,140,362,783,230,150,375,566 },
342 { 13,23,4,33,77,64,51,102,141,128,32,10,0,202,40,115,59,22,90,11,177,21,291,6,7,318,180,117,137,2,95,165 },
343 { 507,162,129,41,4,211,62,38,123,59,57,248,183,130,99,11,3,361,202,17,402,556,266,305,803,210,128,184,152,136,313,117 },
344 { 643,123,193,650,802,18,25,389,718,256,65,289,84,91,619,511,415,90,235,63,57,510,324,216,862,102,6,183,108,397,217,736 },
345 { 13,23,15,1,515,51,0,2,700,5,753,165,141,115,12,3,4,180,21,197,457,7,6,10,120,9,33,202,77,32,8,11 },
346 { 23,51,13,453,64,403,12,21,5,202,128,475,165,141,523,95,125,115,3,1,4,730,120,32,2,494,180,719,457,197,450,401 },
347 { 204,74,135,66,6,174,192,7,138,172,85,353,348,580,280,97,95,500,29,64,426,32,87,889,65,81,25,2,52,43,568,673 },
348 { 35,0,68,69,24,9,1,16,65,103,149,133,18,114,28,50,83,2,189,7,46,14,101,336,175,124,251,55,71,218,38,238 },
349 { 16,101,0,118,9,18,24,68,35,154,71,124,60,212,191,520,55,806,694,167,28,39,364,375,1,346,252,65,604,302,22,21 },
350 { 0,9,16,35,1,24,68,18,65,21,103,67,13,149,28,189,71,23,101,238,114,7,335,133,486,141,22,212,48,50,30,118 },
351 { 13,202,23,77,33,51,128,5,21,141,115,32,102,64,4,0,318,269,10,15,291,2,494,177,11,217,3,515,22,137,6,700 },
352 { 16,92,60,35,7,18,24,68,150,149,14,71,0,375,97,126,118,107,230,191,246,273,140,55,175,653,9,575,2,28,566,517 },
353 { 76,90,21,179,316,148,205,32,464,288,184,257,245,1,89,2,460,57,152,45,38,358,645,5,12,449,350,48,37,17,4,14 },
354 { 19,27,26,813,80,297,17,495,436,53,73,200,4,378,250,59,106,25,45,128,361,42,113,469,122,390,77,40,736,6,11,136 },
355 { 6,26,235,138,19,145,112,70,331,262,25,42,52,624,27,453,122,47,500,78,648,85,29,2,630,632,409,113,50,226,108,75 },
356 { 7,16,14,24,92,35,18,2,46,9,60,140,0,87,50,5,54,13,12,38,171,23,126,21,58,64,1,70,128,71,220,163 },
357 { 90,205,257,184,32,179,460,5,245,45,2,288,769,524,57,21,152,229,17,1,497,4,292,59,619,452,432,76,476,11,266,14 },
358 { 15,515,700,753,4,5,11,141,13,1,33,3,0,128,202,23,180,21,2,64,269,32,117,134,120,40,102,318,153,17,137,352 },
359 { 47,130,711,108,453,412,730,196,390,283,78,27,51,183,381,236,128,200,719,14,153,472,503,34,59,250,3,4,57,803,123,432 },
360 { 12,277,51,474,111,153,23,99,13,37,961,94,629,542,569,431,79,139,38,134,117,453,33,188,196,40,115,15,11,157,401,515 },
361 { 17,495,469,106,26,378,80,27,161,483,19,742,527,436,383,862,73,136,53,814,297,6,119,84,62,56,25,3,209,611,4,128 },
362 { 81,681,636,91,0,750,370,104,718,138,18,693,173,784,29,397,348,74,192,673,174,65,6,207,64,280,306,52,671,32,355,319 },
363 { 15,515,700,753,33,77,4,102,115,117,40,13,1,153,134,11,5,217,23,196,2,21,3,317,32,365,0,341,291,59,12,51 },
364 { 0,9,28,35,68,1,65,67,101,39,69,175,16,238,13,22,96,124,18,24,251,30,55,12,23,2,50,141,114,5,154,103 },
365 { 23,33,77,13,117,40,11,102,64,4,51,403,153,453,10,0,196,134,128,65,12,291,86,99,95,59,15,141,202,180,137,719 },
366 { 214,90,289,6,874,64,25,65,235,42,751,249,256,312,194,85,746,875,174,32,525,288,519,835,247,348,233,544,217,524,437,352 },
367 { 1,22,2,0,36,67,28,5,49,95,12,50,168,83,105,55,7,9,14,194,103,23,114,21,584,46,10,13,38,69,208,159 },
368 { 269,141,13,202,33,180,318,77,291,137,102,352,128,23,349,51,31,217,372,317,125,197,44,21,11,5,901,1,18,0,4,494 },
369 { 435,144,274,88,203,418,30,1,190,410,96,778,100,530,521,326,466,795,686,166,960,321,382,264,367,822,131,31,692,9,213,93 },
370 { 76,72,90,21,37,179,12,205,32,428,148,38,308,405,4,413,57,184,749,245,316,221,54,645,288,1,152,155,464,257,2,14 },
371 { 77,33,64,102,13,141,23,2,40,1,51,10,0,115,6,180,202,128,4,3,177,269,15,7,22,165,291,14,217,318,137,11 },
372 { 397,81,4,32,65,788,693,804,681,11,249,21,91,64,690,494,3,0,422,56,348,725,194,123,23,59,523,319,61,510,95,90 },
373 { 60,126,16,7,92,121,314,246,35,107,150,132,14,146,24,18,199,298,232,71,359,140,672,97,392,649,5,423,95,21,22,388 },
374 { 15,515,141,217,115,700,13,23,120,317,753,180,33,260,110,137,341,51,1,365,4,77,64,202,0,40,36,352,197,269,10,21 },
375 { 111,134,117,474,23,13,961,12,569,431,37,15,51,115,515,700,277,99,753,38,197,405,457,4,72,94,629,45,11,89,54,148 },
376 { 23,13,51,5,1,15,2,21,12,202,141,0,515,165,120,32,4,64,700,3,115,197,269,125,753,7,9,128,6,180,453,403 },
377 { 13,141,4,23,5,2,115,217,202,51,180,137,269,352,77,1,317,3,21,318,0,15,9,64,10,197,11,341,33,515,752,7 },
378 { 165,125,197,13,391,21,23,558,48,380,97,120,298,33,14,426,66,115,32,386,900,180,6,98,357,237,326,509,51,278,221,457 },
379 { 120,82,15,260,515,1,351,77,450,700,13,21,141,23,753,202,217,93,110,33,51,854,5,128,326,102,137,180,817,48,269,352 },
380 { 23,13,15,51,515,700,961,753,0,457,1,2,4,115,10,453,569,5,33,165,11,719,14,40,64,197,3,21,474,629,38,401 },
381 { 264,166,39,30,9,100,435,254,93,921,190,363,1,625,411,382,897,656,203,478,404,812,438,110,473,88,18,691,156,141,274,272 },
382 { 9,0,252,100,166,39,101,265,364,68,88,329,520,18,419,676,118,167,404,604,16,1,21,30,212,158,553,49,382,274,48,13 },
383 { 15,515,700,753,4,11,141,5,3,13,202,1,180,21,2,165,269,23,40,64,0,318,12,32,128,51,77,117,523,197,120,457 },
384 { 24,1,2,69,35,16,67,18,14,50,0,46,68,9,38,7,133,71,83,149,28,108,189,218,65,114,238,29,75,54,5,96 },
385 { 90,289,214,64,874,13,77,712,66,751,4,23,51,192,32,0,202,194,312,177,33,65,234,104,875,288,59,5,835,416,102,95 },
386 { 0,9,49,127,98,31,301,28,371,159,1,395,512,737,158,761,916,623,16,44,242,39,170,18,293,105,24,272,101,22,23,385 },
387 { 17,62,136,214,123,129,32,292,119,209,710,106,141,162,128,64,45,4,77,249,11,618,211,3,207,130,519,183,38,177,21,269 },
388 { 5,107,581,356,279,32,441,362,493,660,13,298,0,534,49,147,21,22,132,121,97,423,7,590,259,683,14,786,126,508,60,246 },
389 { 51,13,15,730,453,23,515,719,386,457,12,700,403,475,899,1,6,523,753,421,99,401,165,33,2,19,361,5,0,670,120,27 },
390 { 49,28,9,159,272,22,254,131,158,327,95,105,0,39,35,168,347,286,374,55,65,627,424,912,68,578,1,24,239,175,688,169 },
391 { 15,515,700,33,753,4,77,141,341,317,1,10,13,180,102,22,40,117,115,365,5,901,23,197,134,11,217,351,64,82,21,137 },
392 { 134,15,13,515,23,700,12,753,51,474,37,961,197,10,457,569,4,0,99,2,115,38,165,153,94,3,139,11,1,82,33,5 },
393 { 7,2,20,58,5,14,128,66,6,29,32,43,21,52,16,38,631,61,74,97,46,135,113,25,202,192,13,0,884,45,112,87 },
394 { 77,13,33,202,23,128,102,4,141,342,117,0,269,318,134,22,11,21,32,153,403,291,49,64,137,51,40,15,494,5,196,98 },
395 { 2,1,14,6,46,38,29,65,5,36,67,0,103,7,22,86,133,50,108,208,52,83,24,323,283,69,28,18,10,25,23,75 },
396 { 15,515,700,753,1,5,4,2,3,13,0,11,180,341,12,33,10,197,134,365,77,23,21,901,6,117,165,7,37,32,17,102 },
397 { 203,268,206,93,417,940,31,8,120,137,44,499,959,473,202,692,728,559,0,260,10,326,141,564,817,127,341,1,450,22,110,23 },
398 { 15,82,515,120,700,0,10,753,33,8,64,165,110,31,260,93,13,197,23,22,40,4,351,44,77,9,11,153,102,51,1,196 },
399 { 60,0,16,7,14,43,20,71,28,10,2,22,154,18,13,24,92,1,51,576,35,615,805,925,68,126,124,149,97,64,23,55 },
400 { 19,6,26,80,5,84,27,17,25,2,504,129,45,240,56,123,4,119,618,1,76,106,64,51,14,3,128,65,32,710,0,42 },
401 { 15,515,700,753,13,4,77,23,33,51,0,5,8,10,11,31,44,1,82,22,202,64,110,102,93,21,291,40,141,180,9,49 },
402 { 195,98,271,223,132,167,146,407,1,360,121,834,393,591,212,199,293,259,522,107,354,147,156,191,807,590,48,18,125,16,765,541 },
403 { 128,202,77,210,402,318,33,102,6,40,403,29,342,269,196,757,99,139,2,111,42,4,494,117,275,300,13,12,678,0,177,122 },
404 { 13,33,23,40,51,102,4,117,77,64,134,0,128,153,202,196,453,11,15,12,1,22,403,141,59,14,10,475,515,65,700,95 },
405 { 7,16,14,24,18,2,28,0,92,71,1,22,6,35,60,20,168,10,154,118,5,302,124,69,97,109,703,158,420,12,149,66 },
406 { 15,1,515,23,0,13,700,2,51,753,180,5,120,165,197,21,115,4,33,9,141,7,12,6,3,457,386,202,260,523,8,31 },
407 { 60,107,121,132,146,126,199,279,150,92,16,649,441,35,955,7,21,0,423,5,18,195,598,298,493,356,32,653,22,362,953,10 },
408 { 31,44,98,276,284,299,116,935,9,201,0,131,39,127,144,662,1,137,371,492,567,489,93,254,49,268,22,28,30,293,434,737 },
409 { 13,15,23,515,700,0,1,51,753,4,2,10,77,202,5,115,3,165,197,457,9,12,11,961,33,120,22,141,180,7,6,40 },
410 { 123,162,184,257,17,183,229,130,129,3,84,136,99,152,556,383,57,497,12,205,4,62,56,452,80,266,128,14,40,119,27,106 },
411 { 196,33,117,40,153,23,134,13,51,102,453,0,15,475,12,14,515,2,22,700,4,21,753,64,401,670,730,1,9,11,10,99 },
412 { 224,219,187,131,258,385,442,871,836,31,98,908,44,574,127,944,137,839,116,36,613,1,254,39,926,160,829,96,93,371,860,827 },
413 { 121,195,156,132,146,360,590,407,786,522,883,591,259,929,626,941,150,687,5,55,296,379,467,178,586,465,279,21,1,13,60,354 },
414 { 2,1,14,29,6,5,46,52,38,19,114,75,26,65,108,96,25,50,36,70,103,309,17,236,218,74,12,86,0,3,10,112 },
415 { 15,515,82,700,120,753,10,0,8,197,260,165,351,64,13,110,117,93,31,1,9,33,22,23,457,44,450,77,102,898,40,49 },
416 { 7,66,97,2,172,74,226,52,29,135,192,232,43,324,92,5,38,20,222,14,6,568,87,107,353,620,580,16,138,174,448,32 },
417 { 62,129,123,162,136,249,618,183,507,57,4,152,17,59,11,184,117,77,3,128,211,41,130,205,12,40,33,106,64,229,38,313 },
418 { 1,13,15,2,4,515,23,0,3,115,700,5,51,77,341,141,753,180,33,217,197,202,901,6,21,165,11,365,318,317,10,102 },
419 { 6,26,235,19,145,47,112,78,64,27,453,95,29,444,25,624,85,108,648,70,32,130,74,42,711,630,632,138,65,122,113,730 },
420 { 23,51,12,15,13,99,515,153,117,10,700,37,120,82,165,2,753,64,128,0,403,3,5,1,134,197,453,31,202,457,110,21 },
421 { 16,24,18,71,64,35,92,7,246,146,9,108,60,118,199,5,140,2,267,0,230,830,32,133,1,68,50,330,247,563,36,12 },
422 { 15,515,700,753,0,1,13,2,23,3,4,217,51,5,115,8,9,180,341,10,7,6,317,77,33,372,901,197,365,11,120,165 },
423 { 234,639,178,202,77,142,5,455,450,49,416,0,147,427,198,21,315,329,13,318,325,557,120,344,113,259,22,128,61,105,23,494 },
424 { 1,31,36,44,141,180,55,2,64,22,98,116,13,352,0,115,10,127,5,164,253,498,237,165,341,197,4,86,15,170,125,23 },
425 { 15,120,13,141,23,260,217,515,1,77,51,110,180,700,317,82,269,137,115,202,21,753,64,5,351,291,0,450,352,93,36,326 },
426 { 26,6,112,396,19,145,25,122,648,287,42,74,624,222,416,45,138,66,644,151,113,651,29,573,64,280,445,27,525,85,70,58 },
427 { 156,360,5,146,121,21,271,522,354,132,49,13,18,195,16,340,60,591,446,586,727,0,107,407,167,48,1,463,199,566,32,23 },
428 { 5,61,49,147,178,612,660,120,21,182,23,427,259,683,33,4,77,70,13,3,376,98,64,0,481,344,48,595,291,263,141,51 },
429 { 89,79,468,179,358,205,94,405,115,498,72,180,365,431,37,111,341,734,188,317,482,217,11,4,245,152,413,216,12,474,490,752 },
430 { 24,16,35,68,18,71,7,92,0,108,9,14,118,101,336,175,375,302,28,124,154,55,149,60,398,1,65,2,140,273,345,230 },
431 { 51,730,421,801,453,386,23,523,13,475,719,401,670,365,899,403,115,457,758,165,33,494,450,6,423,805,629,56,569,514,958,388 },
432 { 113,45,6,311,29,2,151,614,145,491,112,80,5,27,61,74,315,66,209,631,19,25,58,17,73,26,1,243,70,64,611,287 },
433 { 4,339,188,471,11,59,79,12,377,94,99,33,77,102,51,111,37,152,13,961,474,542,40,342,3,23,128,403,202,177,184,57 },
434 { 15,4,515,11,700,33,82,40,0,120,753,10,8,110,13,93,23,165,77,260,64,31,22,51,44,102,351,1,125,9,197,21 },
435 { 16,24,18,0,35,68,28,71,124,118,60,7,9,55,14,92,109,101,419,175,22,252,154,375,149,302,158,346,2,49,1,126 },
436 { 17,45,227,21,106,3,2,243,209,5,48,32,221,62,207,50,29,186,290,270,263,52,14,496,400,119,46,255,54,430,38,721 },
437 { 340,354,586,658,156,195,698,668,1,296,9,18,883,363,447,379,303,98,411,13,31,163,51,5,371,48,919,846,121,21,360,70 },
438 { 277,153,111,12,23,51,474,99,38,37,139,117,41,457,79,453,542,13,11,33,134,157,629,188,961,14,196,401,102,569,15,94 },
439 { 0,18,16,159,49,24,9,105,35,68,7,28,22,1,60,344,55,101,109,2,14,158,13,23,71,118,455,286,272,424,5,327 },
440 { 0,105,9,49,16,18,158,28,518,24,101,320,1,68,170,301,272,127,7,286,35,890,109,39,159,98,21,344,31,55,371,23 },
441 { 141,1,180,15,13,2,365,217,515,352,317,115,341,0,4,5,269,700,23,21,3,752,197,77,753,51,31,901,10,202,8,64 },
442 { 4,23,51,33,19,17,102,153,485,880,40,403,196,26,300,453,27,117,78,0,12,200,47,5,11,14,342,99,53,77,475,2 },
443 { 62,184,56,440,130,229,183,3,556,152,99,162,12,266,17,548,136,57,305,161,123,14,452,4,383,403,257,34,40,84,33,139 },
444 { 13,23,77,141,64,202,33,51,269,115,0,102,21,4,217,128,5,32,318,137,291,9,15,2,180,10,3,317,177,515,7,6 },
445 { 1,22,36,105,170,0,86,2,31,28,239,64,55,5,10,98,9,44,127,95,654,67,301,143,13,12,49,23,320,141,83,21 },
446 { 15,515,700,753,0,1,13,2,23,901,5,8,51,82,9,180,457,4,7,12,3,6,10,120,341,141,22,898,197,351,115,260 },
447 { 1,39,274,98,100,265,190,30,438,310,166,223,88,96,909,31,264,625,530,9,382,812,21,252,593,0,254,539,44,131,23,778 },
448 { 18,212,167,118,363,1,447,411,146,60,271,16,781,121,647,9,621,562,21,478,664,68,815,5,354,98,48,101,24,446,777,463 },
449 { 24,28,22,0,7,1,2,16,14,65,35,49,158,95,109,159,55,105,10,18,124,9,67,5,239,149,12,289,108,68,21,424 },
450 { 105,22,131,272,286,98,55,239,1,31,320,9,127,327,36,185,28,374,86,219,0,64,187,44,578,164,224,913,535,115,601,13 },
451 { 22,31,28,301,127,98,44,0,105,1,512,395,9,293,109,299,95,338,239,125,242,116,36,320,55,841,900,685,599,23,13,763 },
452 { 2,1,58,29,5,14,52,46,186,334,45,155,151,50,400,75,38,69,502,61,48,227,223,7,163,17,262,67,549,21,70,113 },
453 { 7,107,135,232,97,14,2,92,66,16,172,192,278,387,298,356,38,35,448,52,46,43,60,29,20,126,324,526,357,359,64,5 },
454 { 20,43,104,426,173,7,560,414,707,784,319,81,0,861,422,819,38,74,715,52,376,97,879,32,330,22,49,64,66,95,192,526 },
455 { 104,74,636,66,204,0,355,81,222,25,29,319,145,784,20,65,90,4,174,194,7,64,6,746,138,173,750,715,91,43,192,32 },
456 { 0,9,101,35,68,39,65,28,252,124,67,154,364,336,100,166,30,1,289,55,149,346,16,114,158,88,439,24,429,22,570,194 },
457 { 57,14,4,231,236,585,176,59,369,23,361,13,719,51,300,342,12,457,56,3,62,38,202,401,34,46,2,322,11,215,210,507 },
458 { 1,2,15,3,141,0,515,5,33,700,13,64,77,180,6,128,753,10,4,269,102,202,11,7,134,197,352,120,117,318,12,291 },
459 { 5,1,21,202,13,32,48,23,0,61,259,22,494,120,70,49,51,18,137,128,465,12,178,115,2,453,403,141,58,3,90,450 },
460 { 141,205,4,72,59,79,245,11,352,94,152,76,247,216,21,188,452,217,497,12,89,37,111,339,588,77,64,875,864,115,358,464 },
461 { 15,515,700,753,0,1,2,13,5,4,23,3,8,341,365,51,115,10,120,457,6,141,77,197,31,7,165,9,202,450,961,260 },
462 { 5,2,50,14,58,38,171,46,29,1,45,186,17,52,155,218,48,281,61,487,54,36,67,21,328,334,151,227,760,114,400,133 },
463 { 457,120,70,125,318,64,23,48,795,291,202,761,751,415,77,846,269,758,21,237,96,260,391,165,87,1,128,5,221,13,137,763 },
464 { 13,23,51,33,4,40,117,102,453,64,153,196,0,77,15,11,12,475,1,65,134,10,515,22,21,14,700,59,403,141,2,753 },
465 { 229,152,57,266,452,381,432,12,313,184,99,471,17,4,62,339,157,3,129,59,128,11,369,37,77,38,40,123,5,497,188,257 },
466 { 49,28,109,22,159,9,272,95,105,131,55,35,254,168,39,327,169,0,1,286,175,374,347,158,420,67,36,194,312,424,627,346 },
467 { 5,2,61,29,45,58,80,311,1,17,209,227,52,243,106,869,454,151,592,496,48,334,14,155,6,186,46,171,75,21,255,667 },
468 { 244,44,110,141,260,30,269,352,839,131,574,228,373,276,1,406,219,717,217,137,253,224,120,93,36,31,567,116,661,187,341,88 },
469 { 12,99,79,139,11,453,196,51,277,474,111,23,542,37,94,188,33,13,401,775,40,961,313,102,4,339,153,485,629,134,300,431 },
470 { 16,35,9,0,68,24,149,69,67,18,1,114,65,230,71,7,103,133,50,167,212,118,101,191,140,64,399,28,124,283,55,565 },
471 { 88,30,274,435,131,613,190,100,93,829,166,1,187,795,530,127,382,957,960,160,31,137,466,264,39,800,406,254,28,473,521,219 },
472 { 167,16,18,118,212,24,60,71,101,68,191,9,375,411,363,35,0,1,589,199,302,21,447,55,146,126,92,271,647,121,562,48 },
473 { 64,141,86,177,77,128,147,597,304,95,269,102,275,4,352,49,120,5,372,194,465,13,588,237,947,216,202,180,612,751,107,534 },
474 { 18,65,90,403,523,289,240,214,194,102,701,475,202,217,283,862,389,51,33,0,494,421,453,817,84,64,847,899,352,13,23,437 },
475 { 13,51,23,202,5,12,21,128,15,115,0,1,141,120,64,32,4,2,515,403,165,457,3,10,700,99,453,318,719,450,308,401 },
476 { 98,223,393,31,1,271,834,791,167,44,202,64,93,697,5,116,77,125,450,446,212,18,541,293,51,120,195,132,284,13,807,765 },
477 { 15,515,700,753,4,11,23,13,40,51,82,165,0,110,93,33,141,64,120,5,10,77,3,102,180,32,202,125,8,197,31,21 },
478 { 15,515,700,753,0,1,13,2,901,23,5,341,3,51,82,8,4,180,961,9,115,10,12,6,898,7,351,141,134,22,31,120 },
479 { 234,416,77,5,315,639,325,202,147,198,113,49,450,61,455,142,0,21,22,342,329,494,178,58,102,427,318,230,13,120,43,470 },
480 { 60,146,16,18,156,126,121,271,199,360,132,24,167,0,640,10,71,522,21,92,5,340,107,354,118,150,22,195,446,35,28,212 },
481 { 4,361,11,14,56,368,377,161,27,12,300,77,59,200,17,554,202,33,40,494,495,21,210,80,757,25,128,23,19,38,444,53 },
482 { 141,82,217,351,15,352,120,1,180,260,515,64,854,36,700,317,752,372,13,269,77,753,922,21,349,23,202,110,93,137,51,373 },
483 { 15,515,700,753,77,13,0,1,23,33,102,2,51,4,3,5,291,217,10,9,450,120,341,7,317,6,11,117,115,8,260,180 },
484 { 15,515,120,13,700,23,77,141,1,260,0,753,180,51,137,202,115,365,110,291,217,5,128,9,21,341,197,269,2,450,317,165 },
485 { 174,6,348,85,138,74,280,204,66,233,192,355,289,65,81,580,636,353,25,91,104,343,673,214,64,95,42,712,792,32,194,90 },
486 { 152,497,452,59,4,216,11,79,94,77,128,188,269,339,588,33,76,529,318,32,141,471,12,202,111,21,5,51,37,90,72,177 },
487 { 417,499,10,141,253,244,110,559,8,564,180,260,728,120,352,638,642,341,951,206,143,752,901,93,137,661,922,373,44,31,811,197 },
488 { 13,77,23,33,4,51,0,102,128,59,141,40,64,115,177,10,137,22,202,2,7,11,90,1,117,180,269,14,49,6,134,3 },
489 { 1,2,22,0,36,5,67,50,14,28,12,86,38,46,83,168,194,65,103,114,49,7,10,95,21,69,23,24,128,51,55,13 },
490 { 17,106,119,207,255,306,742,378,84,62,136,45,3,5,240,80,61,56,209,383,311,790,655,32,2,440,76,151,58,29,179,263 },
491 { 3,128,1,141,2,202,33,5,64,15,0,515,102,13,269,10,700,180,134,51,120,6,77,318,23,137,17,117,753,197,82,153 },
492 { 514,38,377,328,11,57,41,248,880,266,556,4,152,361,471,757,485,403,305,102,3,211,313,99,457,130,12,14,157,40,23,54 },
493 { 68,0,167,101,9,118,264,520,16,18,21,478,562,1,124,212,100,936,664,777,191,88,806,154,48,24,759,604,35,252,265,65 },
494 { 230,689,699,213,466,352,217,831,30,443,418,144,854,201,840,855,1,251,203,317,530,957,96,93,822,539,36,752,351,137,83,800 },
495 { 33,77,102,117,15,82,13,134,23,64,0,515,120,153,51,4,40,128,700,260,202,141,196,22,753,11,351,10,1,326,95,269 },
496 { 11,40,33,51,117,13,542,328,14,134,38,153,23,12,485,231,102,54,775,37,3,377,111,139,211,4,457,403,369,475,99,719 },
497 { 33,64,77,128,141,2,1,202,102,13,23,117,0,15,3,153,51,134,10,40,6,5,515,269,137,180,318,165,700,7,196,753 },
498 { 15,515,700,753,4,1,5,11,13,21,33,180,93,141,64,2,23,77,82,3,0,102,32,40,352,341,10,197,98,110,117,901 },
499 { 1,2,14,67,50,46,38,24,103,83,0,5,36,28,29,133,114,96,65,52,18,75,54,108,22,7,238,58,160,9,361,69 },
500 { 258,201,276,137,160,860,116,261,295,843,567,144,131,44,187,268,943,219,284,31,202,935,141,98,662,203,127,96,36,93,224,1 },
501 { 7,2,14,16,46,87,75,52,92,278,29,38,140,70,1,5,35,294,24,262,135,69,171,172,58,409,112,60,50,66,97,12 },
502 { 13,23,0,2,51,1,33,4,115,10,15,141,77,3,5,180,217,515,9,7,64,11,700,6,102,40,197,22,317,753,165,202 },
503 { 74,145,6,66,25,204,42,29,222,337,138,26,7,525,192,174,746,287,544,135,415,2,609,632,112,64,87,0,85,45,712,396 },
504 { 77,33,102,15,217,13,23,141,202,515,51,700,291,4,269,753,317,180,21,64,318,115,128,0,275,2,352,196,3,5,137,11 },
505 { 187,219,258,871,44,442,160,574,137,224,908,116,839,131,36,926,276,201,93,228,202,860,31,613,144,531,406,1,902,30,190,318 },
506 { 1,372,141,5,21,77,225,744,96,30,23,349,13,291,269,284,69,442,459,144,303,839,217,622,160,330,260,48,120,410,189,352 },
507 { 66,222,2,74,29,87,135,6,7,145,52,25,294,337,226,172,138,331,42,70,97,112,26,1,632,192,43,5,415,609,461,353 },
508 { 45,17,106,209,5,2,21,29,48,207,3,186,243,155,255,263,454,119,400,496,270,14,290,62,425,1,171,32,659,52,38,56 },
509 { 93,88,141,120,30,213,260,373,100,717,459,82,110,1,166,450,180,321,217,372,36,269,131,225,22,352,326,466,473,187,244,410 },
510 { 266,57,152,381,313,471,12,229,99,369,339,62,157,3,4,37,77,38,188,17,11,162,40,184,129,59,475,775,128,452,403,453 },
511 { 217,352,317,141,752,15,180,515,372,365,700,341,753,349,77,21,291,1,115,244,64,120,13,98,269,82,5,498,864,351,23,144 },
512 { 14,514,369,102,403,377,51,719,880,153,23,13,457,11,485,4,401,12,328,453,33,40,117,57,629,38,730,236,134,670,361,961 },
513 { 107,7,172,14,92,135,2,359,60,314,46,16,126,278,232,150,279,32,38,392,298,5,35,97,24,192,259,288,330,52,356,312 },
514 { 0,4,25,13,59,90,65,23,26,19,18,12,5,216,91,51,389,33,77,11,22,85,27,81,21,177,746,45,42,194,37,123 },
515 { 5,49,315,202,416,77,455,639,450,21,197,137,350,13,408,0,329,318,494,344,61,402,64,509,347,120,113,48,95,713,308,401 },
516 { 130,47,381,390,59,90,200,214,289,6,65,472,29,64,874,648,50,751,624,26,52,32,4,194,875,714,85,249,247,33,881,19 },
517 { 51,23,453,13,719,12,457,165,37,730,99,4,386,197,401,17,11,2,3,15,5,961,475,6,515,64,54,700,32,115,0,403 },
518 { 15,515,1,13,700,2,23,0,753,5,3,180,51,4,165,12,141,21,197,457,7,115,6,9,352,10,120,202,8,341,11,77 },
519 { 0,9,1,67,35,28,68,16,24,65,18,69,50,114,103,12,22,13,5,101,2,96,23,83,149,21,39,55,7,175,433,124 },
520 { 28,105,22,0,1,320,170,9,49,301,109,95,127,31,98,55,65,35,2,24,168,159,36,713,16,740,13,338,21,44,512,23 },
521 { 13,77,4,51,23,33,102,202,128,59,40,0,64,141,117,403,115,11,15,318,153,269,22,515,475,134,10,494,177,1,90,210 },
522 { 13,23,0,51,77,33,2,141,4,10,1,64,115,102,3,6,22,15,217,11,180,7,40,515,165,202,177,9,269,128,700,5 },
523 { 456,116,492,8,949,268,867,391,203,51,499,13,719,386,31,791,457,918,125,10,23,93,479,685,417,0,22,338,506,551,870,730 },
524 { 17,237,45,180,106,62,32,64,115,41,136,498,255,21,197,129,241,13,3,227,23,352,165,752,350,365,449,155,4,546,476,38 },
525 { 1,15,180,515,0,2,341,700,901,352,4,141,13,3,752,5,753,217,317,115,365,23,197,21,51,165,31,6,269,202,77,7 },
526 { 205,141,216,269,497,4,588,76,59,152,128,452,79,77,875,11,72,94,188,217,352,12,247,37,90,64,32,1,474,23,947,372 },
527 { 64,247,217,237,317,180,752,115,349,141,498,13,437,304,23,372,352,164,579,291,33,864,177,197,0,490,72,10,482,77,269,51 },
528 { 2,1,0,13,15,141,3,77,5,515,64,33,23,180,6,700,4,117,217,7,10,11,102,165,753,197,115,134,40,352,12,269 },
529 { 11,40,38,328,33,542,12,313,41,339,23,157,377,117,369,51,471,99,775,485,13,305,457,57,14,475,37,248,4,54,188,719 },
530 { 33,77,102,40,13,23,0,51,4,128,64,202,117,141,22,196,153,10,134,15,59,269,1,137,65,11,403,318,453,86,515,177 },
531 { 472,80,34,250,495,161,17,14,469,176,128,4,389,106,283,436,216,527,3,297,483,177,53,56,231,194,119,84,719,57,255,59 },
532 { 317,352,180,141,217,752,115,341,365,244,1,269,202,901,253,15,21,498,372,4,137,515,13,2,700,318,5,197,23,143,753,349 },
533 { 9,39,101,18,265,100,333,520,252,16,0,329,593,1,553,364,68,167,310,30,121,254,118,158,363,166,60,604,272,24,286,404 },
534 { 15,515,1,180,700,901,0,2,753,341,752,4,3,13,115,365,317,5,23,197,141,217,165,352,6,22,36,9,137,51,7,10 },
535 { 131,39,9,829,166,613,578,827,1,30,716,254,100,98,31,224,0,406,228,310,616,219,44,846,127,190,938,96,265,371,856,438 },
536 { 17,64,62,106,141,751,136,292,32,129,352,41,38,476,86,128,214,237,5,177,123,209,217,45,269,954,162,710,180,3,90,4 },
537 { 25,42,235,65,650,736,605,6,630,85,123,343,233,256,26,122,63,389,141,249,416,444,368,194,19,108,138,174,90,0,544,511 },
538 { 184,229,152,57,266,432,497,452,17,381,619,257,313,12,4,205,59,3,99,471,157,128,5,129,339,369,77,11,32,45,202,2 },
539 { 137,202,160,860,141,30,93,567,36,276,295,261,131,39,9,964,201,843,1,98,800,318,116,22,943,187,10,219,206,44,269,535 },
540 { 0,493,125,64,49,9,279,10,35,18,93,55,293,31,14,13,194,165,325,48,22,132,21,107,98,389,44,581,342,259,174,137 },
541 { 15,515,700,753,4,33,13,77,23,5,51,32,102,40,93,11,349,141,21,8,82,202,64,31,110,10,117,0,1,44,3,318 },
542 { 110,253,854,811,352,141,244,951,180,642,661,384,498,143,752,317,911,10,269,206,559,351,261,120,902,533,922,959,365,160,332,217 },
543 { 2,29,70,1,75,52,6,220,26,112,145,331,74,163,19,69,38,324,46,58,14,5,25,21,278,223,50,307,66,7,67,409 },
544 { 13,23,77,33,51,4,64,141,115,102,0,2,128,177,40,11,202,10,6,180,7,15,269,1,32,217,59,22,291,3,137,515 },
545 { 340,897,691,478,658,264,914,382,100,812,363,1,724,156,166,698,88,521,39,404,682,447,296,96,303,411,30,909,9,274,656,772 },
546 { 9,18,310,101,265,159,326,120,105,158,33,363,77,195,51,55,13,39,354,132,23,7,28,639,16,137,98,1,252,272,709,49 },
547 { 57,313,471,12,99,369,157,339,266,152,38,37,475,453,328,775,11,40,59,188,77,514,401,403,342,4,139,33,377,51,229,14 },
548 { 16,7,24,14,35,140,60,92,18,69,71,2,189,1,46,230,108,388,150,38,21,172,278,67,246,267,50,309,236,135,451,0 },
549 { 206,417,93,940,959,473,499,203,8,137,559,728,31,202,44,120,450,141,10,260,116,564,22,326,269,318,268,244,0,1,253,638 },
550 { 15,515,700,753,1,0,13,2,23,4,3,51,5,217,7,77,341,115,8,9,10,33,6,180,317,349,291,120,11,165,457,901 },
551 { 1,2,5,14,48,21,290,32,50,45,38,46,263,207,155,72,76,29,17,408,425,171,89,52,7,0,292,449,3,227,513,428 },
552 { 121,132,354,167,271,223,146,98,18,463,1,668,446,195,407,60,212,447,781,48,360,363,411,522,156,393,807,9,21,16,293,13 },
553 { 131,578,105,371,219,224,716,616,187,49,9,254,737,159,385,98,258,127,272,761,0,916,623,910,28,286,39,31,22,518,924,242 },
554 { 302,467,97,6,273,1,24,484,124,51,36,18,2,398,453,421,523,69,7,23,13,403,386,150,66,0,298,65,426,165,22,158 },
555 { 30,190,530,88,1,100,778,539,625,274,382,410,96,731,960,39,795,321,9,131,264,144,840,748,44,166,669,957,36,31,435,228 },
556 { 141,1,2,128,64,33,15,202,3,0,180,5,13,77,515,134,269,102,197,700,10,137,318,6,120,165,753,352,4,82,23,117 },
557 { 44,201,567,116,131,224,295,662,489,268,219,31,434,144,187,276,110,384,93,261,699,137,36,442,120,1,613,30,228,64,141,244 },
558 { 12,15,51,23,515,37,99,13,700,0,10,117,753,38,165,82,134,120,11,453,197,64,115,569,1,629,401,22,457,474,110,153 },
559 { 7,135,2,92,172,14,66,140,38,52,97,46,29,74,16,324,278,226,6,87,1,571,262,5,357,232,35,380,69,314,24,330 },
560 { 125,386,23,963,949,60,51,391,165,221,13,197,118,21,719,193,541,421,517,150,393,7,401,453,308,5,791,551,326,558,48,173 },
561 { 6,85,42,25,138,222,174,235,280,256,525,289,26,214,64,746,90,32,544,65,204,19,66,337,355,95,348,415,74,29,5,312 },
562 { 1,14,5,50,2,67,24,0,46,69,48,21,58,103,16,12,18,38,54,96,83,7,502,45,36,181,35,9,430,28,10,155 },
563 { 811,351,642,180,951,752,110,638,253,10,82,352,197,341,365,564,499,854,873,55,9,417,282,901,244,22,559,143,206,141,28,898 },
564 { 23,13,51,15,12,453,403,165,4,515,115,719,475,457,700,523,2,21,0,99,202,197,14,5,386,753,128,401,37,308,33,117 },
565 { 120,13,23,77,141,1,15,93,217,82,260,51,137,202,110,515,21,180,165,5,128,102,64,351,291,700,269,352,326,203,177,0 },
566 { 1,5,0,22,12,2,36,21,10,23,86,13,28,51,9,128,48,14,32,50,7,3,96,137,54,4,202,49,37,65,208,323 },
567 { 219,98,23,127,301,51,258,308,170,910,13,165,22,105,293,616,125,242,276,401,201,395,964,115,55,284,31,374,327,206,512,900 },
568 { 64,180,80,165,5,237,2,250,34,58,297,61,197,17,22,29,186,498,231,445,247,3,752,311,95,32,483,153,27,45,115,469 },
569 { 13,77,23,33,0,2,1,64,141,51,102,10,15,3,115,40,180,6,515,128,7,22,269,202,4,217,700,5,177,117,14,165 },
570 { 15,120,51,515,13,450,23,700,202,153,196,753,260,64,128,141,730,4,326,386,21,523,33,318,5,457,95,32,403,1,77,269 },
571 { 2,1,5,29,32,45,207,263,14,425,58,72,76,21,7,408,48,46,52,186,17,292,38,6,61,89,476,50,155,720,119,3 },
572 { 15,515,700,753,4,13,11,5,1,23,33,21,3,141,32,2,40,180,117,64,269,202,102,197,0,165,120,51,341,352,153,12 },
573 { 76,5,214,129,2,123,45,710,17,249,618,460,179,32,1,257,205,519,90,207,245,184,162,61,769,209,292,106,6,29,14,128 },
574 { 1,15,23,13,120,141,51,515,202,21,700,165,0,180,137,2,5,77,128,93,753,260,269,197,326,33,110,352,82,102,318,48 },
575 { 7,2,135,14,29,87,66,52,97,172,70,112,5,58,46,337,92,16,20,43,1,38,232,155,74,294,6,461,409,151,262,32 },
576 { 574,187,384,926,860,110,258,434,269,531,141,244,160,261,253,116,699,959,940,717,533,36,219,31,902,661,871,295,201,352,10,260 },
577 { 156,354,296,1,182,586,64,379,340,937,850,698,31,48,98,44,120,18,163,23,30,658,195,125,77,284,223,291,774,481,96,39 },
578 { 250,80,34,472,17,495,176,469,33,194,64,483,4,297,141,14,161,27,53,667,56,833,73,527,585,231,106,51,84,814,2,59 },
579 { 97,7,81,140,66,92,172,192,24,298,43,6,74,69,314,426,462,14,501,16,21,508,60,189,267,232,230,104,48,20,135,330 },
580 { 31,44,116,144,268,393,492,434,367,489,127,98,918,0,384,9,22,206,948,105,93,203,1,456,332,940,299,28,137,49,293,125 },
581 { 15,128,33,3,13,51,141,1,202,64,23,2,515,120,102,0,5,82,10,700,165,197,269,153,403,110,753,137,196,318,117,12 },
582 { 31,98,127,9,0,105,22,28,44,512,293,395,299,1,242,49,685,763,320,599,125,116,109,276,284,95,870,159,23,456,36,900 },
583 { 7,24,124,1,6,97,2,69,14,18,23,92,21,67,66,16,5,484,43,20,118,65,36,22,28,0,51,140,13,71,29,150 },
584 { 1,64,442,303,284,349,202,141,622,67,154,447,260,44,652,429,9,335,237,919,197,98,167,33,682,269,547,77,863,411,340,201 },
585 { 1,15,2,141,515,0,700,13,3,180,10,753,5,64,77,33,4,6,7,197,102,269,165,23,134,11,352,341,291,349,22,120 },
586 { 99,139,12,453,196,277,775,40,475,33,23,401,215,51,11,14,77,111,313,130,38,211,37,266,129,15,339,153,719,3,369,515 },
587 { 33,77,102,4,23,128,13,141,202,64,51,0,40,59,269,115,117,137,153,1,318,11,10,177,15,134,22,90,196,2,403,32 },
588 { 7,2,14,58,70,112,16,5,87,38,46,52,6,128,135,1,32,21,155,29,66,64,0,97,92,186,172,294,13,23,20,37 },
589 { 15,13,515,1,700,2,23,0,753,5,3,4,51,10,341,115,365,180,11,33,317,77,6,7,217,12,197,165,117,9,64,102 },
590 { 2,1,14,29,75,69,67,6,52,46,38,24,103,220,83,25,70,87,262,74,96,267,50,366,26,16,226,394,357,66,108,19 },
591 { 9,105,18,39,1,0,16,557,101,272,252,890,326,49,265,21,137,100,23,938,13,310,159,5,31,24,254,51,30,128,202,132 },
592 { 80,209,45,61,667,17,6,106,5,2,151,29,483,255,454,833,27,311,112,19,738,378,1,58,113,26,25,469,119,887,32,64 },
593 { 13,23,51,15,5,1,515,0,21,2,12,141,700,165,202,115,753,32,180,4,3,197,10,120,457,9,269,128,64,341,7,33 },
594 { 99,12,453,277,139,157,369,474,339,51,38,23,37,196,188,401,775,111,11,313,328,475,153,266,4,471,79,40,33,629,102,14 },
595 { 7,92,16,232,97,140,126,14,60,107,66,35,298,387,314,104,246,462,441,150,0,38,24,2,172,357,230,330,5,633,22,289 },
596 { 13,77,23,202,318,141,33,4,51,269,102,177,115,403,137,2,40,494,90,11,342,128,31,117,21,32,7,12,64,134,14,10 },
597 { 13,2,0,23,141,1,77,3,180,33,6,64,15,10,115,51,4,5,217,197,7,165,515,102,22,11,700,269,40,352,177,14 },
598 { 15,515,700,753,4,11,1,93,13,5,180,110,82,21,120,23,2,33,10,141,3,165,197,102,901,0,32,341,117,40,153,12 },
599 { 15,515,700,753,1,13,0,2,23,4,77,51,3,5,341,291,7,33,6,115,10,9,8,217,11,177,120,180,102,165,197,365 },
600 { 20,43,198,325,173,904,104,234,66,147,77,319,416,422,97,426,5,0,7,450,861,202,712,725,2,32,639,376,38,324,945,315 },
601 { 105,0,9,28,49,301,170,1,127,159,22,16,31,98,512,623,24,109,158,395,35,68,371,65,713,55,2,242,293,21,44,18 },
602 { 213,88,689,466,230,30,321,435,699,352,217,201,795,831,144,854,1,443,96,539,530,840,418,251,855,190,93,100,669,31,957,662 },
603 { 130,453,47,196,4,57,14,59,236,711,51,153,730,77,412,381,23,202,108,128,361,13,283,117,11,719,200,46,34,78,210,2 },
604 { 1,2,5,14,0,50,36,22,38,46,65,67,12,86,114,28,103,29,208,7,10,128,21,83,218,23,96,54,194,6,133,51 },
605 { 6,26,74,19,165,453,14,730,1,125,197,50,29,51,138,357,13,2,108,391,70,719,46,457,47,500,386,262,112,23,235,52 },
606 { 9,10,376,20,43,0,49,18,30,120,2,33,325,104,501,470,77,788,725,102,523,39,858,5,904,414,174,55,137,37,342,13 },
607 { 15,515,700,753,0,1,13,23,51,77,120,202,341,82,5,4,9,260,2,137,141,128,115,351,901,8,180,10,197,21,450,33 },
608 { 105,131,272,578,9,49,371,219,159,616,286,320,224,187,716,98,28,22,0,623,127,258,910,737,385,31,239,347,254,109,424,95 },
609 { 457,51,13,23,961,12,719,99,453,15,4,515,165,401,629,3,700,11,17,14,2,37,753,41,57,569,38,45,0,33,5,32 },
610 { 202,120,5,33,318,77,450,102,1,260,403,128,494,21,165,13,269,12,326,23,342,523,402,2,817,64,15,141,125,82,457,475 },
611 { 141,269,352,217,180,64,349,137,202,160,317,15,372,515,700,752,318,753,244,13,437,291,165,864,22,237,5,82,954,21,77,418 },
612 { 70,29,2,145,74,112,26,6,75,52,19,66,632,1,87,220,5,135,163,287,307,25,226,7,58,396,294,278,113,409,69,151 },
613 { 82,351,317,15,752,180,898,352,141,901,515,341,10,700,365,1,753,498,0,217,253,115,55,854,33,5,143,32,21,160,36,197 },
614 { 39,9,310,254,0,30,101,49,252,272,100,265,105,455,159,557,190,333,286,688,18,166,1,158,709,16,625,627,31,131,327,329 },
615 { 2,58,29,5,1,151,186,52,70,45,7,549,14,75,112,400,113,155,61,46,227,163,311,315,66,6,307,27,17,220,287,74 },
616 { 141,217,13,21,352,23,269,77,180,115,317,64,202,15,349,137,5,51,165,291,318,752,372,4,0,102,33,365,197,32,341,125 },
617 { 68,35,0,9,65,101,149,124,24,154,175,16,28,7,67,1,18,189,114,398,55,14,345,39,118,133,69,2,230,429,71,283 },
618 { 66,7,29,2,112,52,20,43,97,151,74,192,135,5,173,525,337,45,145,58,415,25,14,32,644,70,544,226,222,21,6,580 },
619 { 31,125,44,22,116,299,242,55,1,170,64,36,479,870,456,685,10,599,558,0,268,506,28,740,23,903,492,164,393,206,2,86 },
620 { 188,11,79,12,99,377,94,33,542,339,40,474,111,37,4,51,102,453,139,775,13,475,23,961,277,471,134,57,431,266,115,117 },
621 { 658,698,340,98,296,303,1,31,850,363,156,919,44,774,586,385,120,77,82,10,223,30,354,291,23,914,478,87,260,163,48,13 },
622 { 15,515,700,753,82,4,1,13,901,33,197,11,5,10,23,165,2,0,180,3,21,77,51,120,365,115,217,40,117,102,32,401 },
623 { 15,515,700,753,4,11,5,13,1,141,3,180,23,202,21,2,269,64,165,33,40,32,0,318,120,128,12,197,117,352,51,17 },
624 { 91,6,233,85,370,718,81,65,25,256,63,343,42,74,235,123,138,511,397,249,26,194,650,355,64,87,544,18,90,643,66,214 },
625 { 23,13,202,51,21,120,1,5,141,128,450,64,318,403,15,137,260,33,12,48,32,31,125,494,269,102,165,515,77,2,197,14 },
626 { 180,317,365,341,752,217,115,352,901,482,372,498,1,141,15,253,515,244,2,700,0,21,13,82,23,4,579,351,753,291,269,77 },
627 { 13,115,197,341,9,352,468,237,64,498,23,165,22,509,901,546,482,180,28,569,317,51,365,873,391,95,86,217,49,837,752,706 },
628 { 13,23,51,1,141,5,165,202,21,120,64,125,180,15,2,33,197,115,128,32,260,269,12,82,4,515,137,7,318,93,0,700 },
629 { 214,289,90,174,874,6,138,280,65,81,64,85,355,751,194,233,312,348,835,91,0,32,343,636,249,29,875,288,519,104,247,74 },
630 { 15,515,700,753,4,5,11,13,1,33,23,21,2,3,102,32,141,77,180,117,31,64,0,40,134,196,120,352,12,44,197,6 },
631 { 33,15,13,515,117,23,700,217,134,753,0,51,153,77,141,2,4,64,196,1,3,180,10,115,5,102,6,11,22,202,165,7 },
632 { 15,515,700,753,33,4,77,102,1,40,13,117,11,115,134,5,21,153,23,217,3,32,2,317,120,196,180,141,51,12,59,260 },
633 { 15,515,700,753,13,0,1,23,2,217,51,3,4,5,8,317,115,9,341,10,202,180,6,365,7,82,457,22,120,901,33,291 },
634 { 7,2,135,20,97,14,66,52,337,673,192,29,43,355,353,5,16,294,107,376,147,226,331,560,64,470,222,104,415,32,4,324 },
635 { 195,132,142,167,146,77,363,271,121,354,202,120,647,178,786,212,687,0,101,878,16,522,60,5,450,411,35,55,98,639,259,318 },
636 { 202,77,20,0,318,66,104,128,102,269,177,43,33,7,216,291,494,5,2,342,74,173,97,112,450,22,337,10,234,52,64,678 },
637 { 107,362,612,356,359,97,414,43,259,20,392,7,298,147,819,683,465,173,729,660,319,14,5,779,581,595,246,35,501,92,0,230 },
638 { 6,165,14,453,13,51,19,23,386,457,74,391,308,2,26,401,47,758,603,108,719,366,1,29,309,730,324,197,133,70,115,867 },
639 { 179,72,205,180,247,245,4,490,352,59,317,152,79,498,94,217,148,76,752,864,11,216,141,405,89,452,197,111,497,188,37,21 },
640 { 107,7,298,314,14,359,32,392,232,279,172,97,60,581,387,126,121,0,534,493,356,92,441,95,13,21,35,147,22,5,16,362 },
641 { 156,271,354,586,360,132,591,195,121,18,340,1,5,13,21,48,668,446,23,463,296,658,60,55,407,698,146,70,626,51,163,24 },
642 { 13,23,51,4,0,12,457,15,11,453,2,515,5,1,99,10,115,165,700,475,401,403,3,961,40,14,37,753,719,32,64,569 },
643 { 48,125,21,165,13,221,23,763,423,508,197,5,98,92,193,16,441,386,64,314,293,457,391,140,49,60,102,693,683,51,35,867 },
644 { 202,77,120,450,5,318,1,494,0,195,18,132,523,403,326,604,354,260,121,576,203,167,234,817,682,49,35,615,21,20,13,102 },
645 { 39,9,166,30,0,101,158,68,404,190,333,274,252,310,88,100,49,28,344,35,21,22,419,131,438,1,16,65,530,694,124,10 },
646 { 15,515,700,753,110,4,1,11,165,180,93,13,82,5,2,197,33,120,0,3,10,23,21,115,901,217,341,77,317,51,32,117 },
647 { 2,29,1,14,6,52,5,46,50,26,70,19,103,58,38,67,96,262,516,309,218,133,108,27,75,17,112,114,24,487,331,83 },
648 { 120,77,15,13,1,141,260,23,515,217,110,51,137,700,317,202,165,291,180,21,753,128,0,177,326,93,450,82,64,269,197,5 },
649 { 255,59,554,297,183,56,33,444,108,358,123,196,269,122,77,153,57,177,117,730,19,467,605,130,128,50,275,4,291,475,134,133 },
650 { 13,23,51,12,153,14,117,120,165,134,99,401,38,453,15,128,197,719,64,515,475,403,37,33,196,700,40,125,5,0,54,2 },
651 { 64,33,174,348,95,108,467,554,56,0,25,306,233,6,63,511,343,120,13,85,29,561,543,707,319,180,899,355,77,49,256,18 },
652 { 120,260,51,23,77,15,202,1,93,82,141,450,13,326,515,137,21,5,64,33,110,700,128,165,318,203,269,102,351,753,197,125 },
653 { 15,515,700,753,4,13,11,1,5,21,23,2,33,64,3,180,32,141,22,102,77,0,10,93,82,352,117,40,341,31,165,6 },
654 { 15,515,700,753,341,13,23,141,33,1,0,217,4,77,180,10,82,351,51,137,5,64,9,317,21,11,102,40,260,202,854,115 },
655 { 105,272,131,22,327,286,28,239,320,9,109,578,219,49,98,224,95,159,538,371,616,127,187,64,713,55,0,170,168,258,716,623 },
656 { 16,18,68,35,24,60,71,118,92,126,0,9,101,191,7,55,154,175,212,14,167,150,302,28,375,1,107,124,346,273,21,108 },
657 { 20,147,43,470,376,142,904,178,427,798,0,595,198,325,858,319,61,202,173,97,5,422,14,22,107,259,32,49,887,77,414,392 },
658 { 13,23,51,12,33,15,99,64,128,515,453,202,117,153,37,102,700,40,134,196,120,0,2,753,141,14,38,3,82,403,77,21 },
659 { 383,17,62,136,84,119,56,440,3,504,240,80,378,129,123,548,106,128,4,11,14,555,162,32,184,361,59,64,205,5,469,57 },
660 { 70,1,48,652,5,638,846,888,21,349,269,260,340,562,767,761,163,883,774,141,125,518,591,0,23,9,87,13,371,303,622,31 },
661 { 66,135,6,97,74,278,69,7,14,324,267,172,2,140,462,1,357,38,808,550,92,841,189,29,16,25,298,87,75,204,24,335 },
662 { 51,23,33,13,102,40,12,128,64,77,10,202,0,196,117,4,14,99,134,453,65,153,11,475,139,403,22,141,86,2,21,15 },
663 { 88,100,264,166,274,435,772,1,382,921,96,478,30,438,639,909,897,521,190,466,960,410,9,144,530,418,31,329,265,691,778,93 },
664 { 62,440,136,56,84,3,504,548,555,383,4,17,129,128,507,361,123,59,119,162,14,57,152,328,161,11,202,495,184,27,80,215 },
665 { 911,617,332,959,206,141,253,244,282,384,110,120,10,260,352,143,951,811,269,373,160,417,93,531,728,203,434,940,137,55,36,717 },
666 { 120,15,260,141,77,1,515,82,700,351,33,23,450,13,110,326,64,217,269,753,203,137,102,5,165,21,51,291,93,177,373,128 },
667 { 15,515,700,753,0,1,2,23,13,51,5,9,82,901,180,8,3,4,120,6,7,141,93,12,197,341,10,33,115,730,64,125 },
668 { 7,104,97,107,356,232,66,560,298,289,14,707,38,568,359,64,20,0,65,324,22,214,92,32,192,5,387,43,712,90,172,95 },
669 { 6,1,2,66,67,14,74,24,108,29,69,83,458,7,25,38,135,103,36,150,451,114,52,594,75,65,380,18,267,602,19,278 },
670 { 13,23,51,12,115,21,202,5,457,15,4,1,64,719,0,403,2,3,453,165,99,141,401,128,32,515,10,37,523,197,120,700 },
671 { 57,59,4,11,412,381,77,53,421,291,250,368,99,14,27,369,803,283,23,108,403,19,339,210,0,401,12,444,236,40,361,736 },
672 { 15,515,700,1,0,753,2,13,23,5,51,180,3,115,6,7,457,4,9,8,12,82,197,165,141,901,120,719,33,64,21,22 },
673 { 64,95,180,247,929,146,90,126,197,32,237,60,288,165,316,92,5,13,77,7,217,955,522,22,16,314,132,4,317,10,312,86 },
674 { 15,1,120,13,23,515,0,51,700,180,141,2,5,202,21,260,753,165,137,33,77,110,197,128,326,7,450,4,102,9,269,12 },
675 { 14,2,16,46,1,7,24,69,75,35,38,50,29,220,52,140,267,67,18,54,70,309,5,60,92,189,171,87,71,163,58,0 },
676 { 31,98,127,44,9,299,0,276,293,284,116,49,935,599,105,22,456,201,28,1,39,125,242,137,371,144,131,492,159,272,51,395 },
677 { 6,27,151,53,573,445,297,113,26,73,436,19,491,250,396,315,45,112,145,58,614,881,25,34,611,200,17,80,70,5,138,631 },
678 { 32,693,81,788,90,804,403,56,494,21,84,397,202,65,18,77,64,681,214,725,523,784,526,33,102,825,240,0,115,241,817,91 },
679 { 24,7,14,2,18,16,65,0,108,149,28,69,1,71,154,36,124,35,67,140,189,429,92,68,66,22,55,118,302,150,9,6 },
680 { 0,68,9,35,65,101,189,212,114,67,124,69,1,154,149,39,230,64,252,16,88,702,103,100,18,336,28,329,520,83,30,755 },
681 { 5,2,186,29,61,45,17,1,52,48,58,171,155,227,80,209,311,21,14,46,50,106,243,513,334,502,496,38,3,6,32,592 },
682 { 15,515,700,753,13,1,2,0,3,4,5,23,341,11,10,33,6,51,165,117,153,7,180,12,365,901,77,569,197,115,64,9 },
683 { 13,15,23,515,0,51,1,700,4,2,753,10,3,5,12,77,33,961,165,457,197,11,115,9,22,102,40,403,202,21,14,59 },
684 { 15,515,700,753,13,0,1,23,2,33,102,5,4,10,9,3,51,115,77,7,6,341,12,11,217,40,457,196,180,165,8,523 },
685 { 166,39,30,274,190,100,333,438,530,310,88,252,0,9,539,265,1,656,404,101,625,131,778,254,31,455,676,329,724,158,21,23 },
686 { 734,148,94,308,431,115,37,89,111,413,79,468,197,629,341,474,569,12,13,873,179,401,11,4,180,23,205,72,59,365,134,51 },
687 { 539,228,224,219,816,190,30,258,871,840,669,93,406,530,957,187,160,531,748,137,131,88,863,36,728,839,44,213,352,116,202,466 },
688 { 393,791,125,801,730,551,386,23,31,175,93,98,51,13,144,788,126,203,21,345,116,22,949,110,575,165,326,44,0,4,60,221 },
689 { 13,23,77,141,0,4,51,2,33,115,64,1,10,3,6,15,11,102,7,217,180,40,515,22,128,177,202,9,700,269,165,5 },
690 { 2,29,7,70,52,14,1,58,112,46,75,5,171,163,87,220,307,151,186,334,38,66,155,16,69,135,278,45,262,97,6,21 },
691 { 88,321,213,100,230,435,689,466,1,382,30,352,217,699,410,96,795,36,921,752,190,141,144,180,44,831,317,83,443,31,840,251 },
692 { 363,411,101,520,354,9,195,668,132,156,447,1,905,364,18,23,765,664,146,5,360,13,121,96,98,31,252,39,100,759,264,551 },
693 { 13,23,51,730,12,719,453,457,401,475,5,21,403,2,0,1,15,4,3,899,99,32,165,11,515,308,197,115,6,961,700,523 },
694 { 72,76,89,12,37,4,308,179,38,528,90,431,54,205,148,184,401,57,152,474,23,59,51,245,428,11,32,99,405,316,257,21 },
695 { 376,20,43,147,470,173,97,595,107,319,414,142,819,5,729,178,858,7,427,32,426,104,14,0,392,362,259,61,230,77,560,246 },
696 { 202,141,269,494,318,137,51,128,403,4,217,96,77,5,64,177,291,180,15,352,102,10,33,349,2,317,0,341,120,515,21,453 },
697 { 77,202,33,128,102,318,494,269,13,0,117,23,342,291,403,15,134,51,153,141,177,515,82,137,196,700,203,64,22,351,753,4 },
698 { 253,110,951,352,499,811,10,854,180,638,244,559,642,752,564,8,141,143,417,341,901,260,206,197,922,661,93,15,498,373,165,911 },
699 { 141,13,23,180,4,217,5,1,269,317,21,0,2,202,115,51,352,77,3,197,64,341,318,15,291,9,137,93,32,165,515,33 },
700 { 9,0,18,252,16,101,68,39,24,118,35,109,158,329,28,167,60,364,333,265,49,100,22,419,553,55,1,677,71,7,212,159 },
701 { 28,109,9,39,0,158,49,22,168,35,55,175,1,65,67,185,194,159,289,95,272,114,30,105,86,584,36,169,254,2,83,24 },
702 { 15,515,13,700,1,753,2,23,0,3,4,5,33,341,11,51,6,10,197,115,901,180,77,40,102,12,365,165,141,217,7,317 },
703 { 173,693,104,422,5,18,61,32,102,0,20,13,784,560,33,66,397,526,49,207,29,25,510,707,65,6,11,344,21,263,81,77 },
704 { 23,13,386,51,308,801,719,221,401,949,21,730,165,421,102,115,125,33,341,670,468,117,770,1,120,6,197,14,403,97,67,958 },
705 { 0,49,105,16,28,24,159,9,158,320,1,68,35,239,170,18,109,7,55,65,2,95,301,124,347,14,21,154,22,127,286,31 },
706 { 2,5,1,207,45,29,32,58,76,61,6,263,292,655,72,14,17,476,7,119,52,306,70,64,21,90,186,214,106,38,3,790 },
707 { 21,6,125,49,13,64,715,66,115,95,197,33,22,32,204,165,56,278,0,408,241,120,4,808,681,350,263,85,81,571,135,509 },
708 { 612,427,325,107,202,5,376,49,64,392,403,470,21,147,31,788,494,14,362,465,858,98,20,804,518,43,845,318,125,97,725,534 },
709 { 32,21,76,72,2,1,14,5,241,449,89,38,350,221,155,48,50,292,37,46,45,90,270,54,17,179,214,12,148,430,476,413 },
710 { 24,0,28,16,7,124,35,154,14,149,65,18,9,68,55,108,175,71,2,1,22,109,92,67,484,336,118,69,302,398,570,420 },
711 { 1,5,14,2,48,50,38,67,46,21,0,54,45,270,281,12,24,32,155,96,513,103,290,83,61,58,36,17,37,72,69,181 },
712 { 13,961,569,197,37,15,23,474,515,94,148,111,12,165,629,341,700,79,901,401,51,405,753,10,134,4,115,734,873,11,89,117 },
713 { 33,23,102,51,13,40,77,128,64,202,141,15,4,12,0,1,2,117,22,11,10,403,153,515,99,318,137,269,139,196,700,134 },
714 { 0,1,24,67,9,16,18,35,28,69,103,50,5,2,65,12,83,68,7,96,14,22,21,149,75,114,13,133,23,71,218,54 },
715 { 384,617,940,332,855,911,206,959,434,282,141,10,93,253,244,110,144,268,120,36,352,137,417,203,116,31,44,269,160,201,143,951 },
716 { 30,93,473,137,31,704,450,652,190,203,800,254,166,274,326,144,269,160,127,303,120,625,88,848,110,435,77,521,349,131,340,744 },
717 { 53,27,73,26,19,250,297,200,25,630,17,6,611,122,34,42,714,235,472,65,436,14,80,684,690,106,45,113,680,108,64,4 },
718 { 15,515,1,2,700,0,753,3,5,141,180,4,13,77,33,10,217,6,7,134,11,352,197,64,165,341,317,23,12,115,102,40 },
719 { 254,530,39,613,688,221,30,31,438,190,228,960,1,44,141,21,180,406,23,166,9,202,13,96,137,48,131,829,317,269,393,51 },
720 { 9,39,28,35,30,166,158,36,0,175,101,346,364,67,49,68,168,420,88,1,194,131,100,352,55,83,190,64,137,570,86,65 },
721 { 62,56,3,548,555,507,440,161,34,4,215,136,162,514,361,527,17,14,211,130,328,11,383,123,84,183,38,57,184,152,205,494 },
722 { 92,126,107,7,356,493,97,279,359,298,16,246,35,60,14,441,362,121,43,423,5,132,392,20,508,230,199,146,232,173,150,414 },
723 { 15,82,141,515,291,922,349,700,217,260,372,120,351,93,77,753,318,352,373,854,1,326,269,21,13,102,144,202,64,23,203,137 },
724 { 141,217,352,115,180,13,269,317,752,77,23,21,341,197,5,372,244,291,9,64,51,102,4,1,365,2,165,33,3,48,237,351 },
725 { 78,47,390,19,130,453,108,27,711,813,730,444,412,283,196,690,123,14,128,26,250,389,650,236,200,65,51,4,34,183,297,73 },
726 { 34,250,297,80,472,64,495,17,311,3,148,45,667,61,176,53,243,27,90,161,469,141,483,151,62,128,29,4,58,56,5,231 },
727 { 51,23,33,13,551,77,102,326,421,21,523,120,5,899,453,692,202,153,308,615,115,958,450,401,791,68,221,93,475,18,403,4 },
728 { 98,223,393,363,411,1,478,834,664,156,284,691,447,791,914,293,354,724,697,9,807,541,759,51,18,421,48,264,948,586,195,848 },
729 { 7,14,107,232,16,92,2,60,46,5,359,121,24,526,220,620,135,1,172,21,126,314,132,77,18,75,32,278,12,23,52,38 },
730 { 32,76,2,1,21,72,241,14,5,48,292,89,476,45,720,270,179,90,17,214,148,38,50,29,129,155,350,46,290,227,123,464 },
731 { 15,515,700,753,13,23,33,77,51,4,102,0,32,202,1,11,128,82,117,141,40,5,110,8,3,90,137,21,10,318,403,165 },
732 { 66,6,69,2,1,74,14,135,278,267,380,24,29,97,67,38,103,75,7,388,324,25,52,150,87,83,189,357,335,108,204,172 },
733 { 152,4,339,59,79,471,188,11,77,94,128,33,529,377,12,111,102,202,452,402,216,99,13,542,51,40,474,37,64,291,23,961 },
734 { 15,515,700,753,1,0,196,13,33,2,77,5,23,102,3,10,9,7,217,4,6,153,117,177,14,457,115,12,40,730,11,134 },
735 { 17,209,45,106,207,5,255,119,62,2,61,3,263,742,306,655,425,378,32,56,29,136,84,80,311,58,186,240,243,383,14,21 },
736 { 120,260,450,15,1,23,817,13,515,523,326,5,700,51,82,31,202,64,21,753,318,93,32,269,98,33,351,77,102,125,457,165 },
737 { 116,492,268,93,23,206,203,0,551,918,13,51,8,22,417,940,120,10,499,31,949,791,125,523,165,473,341,730,421,959,401,391 },
738 { 15,515,700,753,165,13,0,1,197,23,4,82,120,2,180,12,260,719,8,3,386,117,5,523,901,11,341,51,10,9,141,351 },
739 { 14,24,69,7,2,66,108,1,67,6,36,398,18,267,150,97,29,38,83,149,65,74,28,0,189,71,388,16,273,124,46,22 },
740 { 330,96,523,335,367,662,141,839,1,922,372,615,244,717,269,443,418,352,403,692,217,854,752,180,36,64,498,576,349,201,98,284 },
741 { 184,90,257,205,245,229,57,152,769,17,524,5,32,497,45,432,619,2,452,266,4,106,1,21,179,59,76,3,460,292,381,128 },
742 { 7,14,16,2,46,5,70,107,87,13,58,307,92,32,38,23,202,0,172,24,18,21,60,128,77,35,20,10,9,4,171,112 },
743 { 7,66,140,16,14,92,97,69,267,172,189,24,380,2,35,60,298,451,230,135,314,74,150,71,38,357,6,330,67,423,21,443 },
744 { 121,167,354,132,18,446,147,101,212,146,407,16,55,35,647,191,20,271,199,68,60,259,463,107,9,126,363,7,195,43,14,411 },
745 { 76,90,179,32,205,21,184,460,257,288,45,245,316,5,57,152,241,2,358,1,229,72,524,148,48,769,17,4,12,38,14,720 },
746 { 147,259,178,878,427,465,581,198,786,798,142,534,325,929,20,362,35,132,107,376,43,5,279,77,49,146,70,202,590,771,33,14 },
747 { 473,93,450,778,141,30,855,466,144,203,330,530,88,523,459,372,201,617,839,704,254,321,934,326,39,36,82,717,332,213,559,403 },
748 { 523,475,51,899,730,453,23,719,403,33,457,13,421,386,4,120,117,196,102,153,15,801,450,817,515,260,202,11,700,99,165,125 },
749 { 15,1,13,515,0,2,700,5,23,753,4,3,341,317,10,115,180,11,33,64,217,77,117,165,197,7,6,365,9,141,102,134 },
750 { 19,4,119,40,33,202,27,84,102,56,77,73,504,485,26,494,757,63,862,59,23,300,25,12,128,11,5,13,342,880,469,6 },
751 { 32,20,2,13,5,21,23,6,12,38,43,29,64,7,95,51,61,207,48,147,90,178,17,182,49,0,115,202,52,362,37,22 },
752 { 339,188,11,79,4,94,377,12,99,111,542,102,37,33,474,51,471,40,453,152,77,13,59,403,342,23,117,57,475,134,128,38 },
753 { 34,128,283,176,495,231,318,432,503,275,529,527,161,53,3,202,56,291,585,469,73,17,14,412,57,27,80,245,250,381,402,51 },
754 { 15,515,13,700,1,217,141,120,23,180,753,115,365,51,317,341,77,260,0,291,110,137,202,5,21,269,64,36,349,2,4,10 },
755 { 13,15,961,515,700,753,4,12,2,457,3,11,197,51,37,569,115,23,5,0,99,10,1,134,6,111,165,33,72,40,38,79 },
756 { 15,515,700,753,13,1,0,2,23,33,5,3,10,4,9,115,7,102,6,51,12,217,77,11,40,457,569,341,117,317,14,719 },
757 { 5,76,2,32,292,214,45,1,129,519,123,179,90,710,17,29,460,72,14,207,21,249,58,205,464,263,618,48,6,245,3,257 },
758 { 72,76,32,4,21,12,38,23,99,54,89,3,14,17,51,57,11,90,13,488,179,2,59,148,45,37,5,115,401,1,10,421 },
759 { 98,223,393,1,834,264,284,791,724,293,478,772,697,909,363,682,905,447,541,821,411,51,421,9,807,48,765,31,730,96,386,410 },
760 { 341,13,509,8,23,638,165,901,762,10,569,242,391,197,873,642,506,499,629,961,15,180,116,456,206,546,417,1,338,457,515,867 },
761 { 1,2,5,50,14,38,46,114,0,36,29,22,218,65,86,96,137,21,133,285,12,10,323,181,17,58,51,23,67,7,28,6 },
762 { 481,878,202,13,5,23,182,32,269,21,1,318,77,142,557,494,141,33,640,137,70,291,2,51,260,415,929,403,120,58,4,259 },
763 { 15,515,700,753,1,4,13,0,2,5,341,3,11,180,134,12,10,317,197,365,33,21,23,165,117,6,77,7,217,37,32,498 },
764 { 25,119,19,6,26,42,27,17,4,790,45,814,2,469,483,84,122,1,0,33,32,128,76,80,611,113,73,56,5,240,202,77 },
765 { 14,2,7,1,24,0,65,6,16,69,67,22,124,28,108,5,18,36,86,10,38,46,66,398,289,168,12,83,21,23,610,13 },
766 { 51,23,128,13,15,202,12,120,33,64,141,82,10,515,0,403,700,3,1,99,117,269,153,165,753,5,318,197,102,260,2,137 },
767 { 16,35,24,0,9,18,7,1,68,69,50,71,103,65,67,189,133,23,28,13,60,537,149,335,75,21,64,5,114,2,12,14 },
768 { 754,803,133,576,880,543,2,1,657,50,14,38,46,5,29,67,218,36,58,171,52,96,24,103,775,0,114,83,181,54,65,45 },
769 { 21,32,5,3,2,17,14,72,76,1,12,23,38,51,4,54,10,0,89,13,99,137,45,36,421,115,543,11,22,128,221,48 },
770 { 434,384,268,144,855,940,617,206,332,116,93,911,959,282,203,137,141,489,44,120,10,110,244,36,98,31,269,253,367,417,160,9 },
771 { 15,2,1,0,13,515,5,700,3,23,180,217,141,10,753,4,117,6,77,33,64,7,11,197,352,317,341,134,165,115,12,9 },
772 { 2,113,6,25,1,0,29,4,7,833,5,45,32,61,128,19,77,151,74,145,64,42,14,210,655,106,59,177,27,17,21,738 },
773 { 116,268,918,203,551,31,8,692,206,791,403,499,417,93,940,421,0,23,22,120,13,523,44,51,299,473,959,1,10,475,202,125 },
774 { 107,126,132,612,362,279,20,146,259,493,199,121,590,43,660,147,35,376,939,60,941,534,683,5,0,953,16,7,49,649,595,470 },
775 { 15,515,700,753,13,1,0,23,2,33,77,4,3,51,5,102,115,10,9,341,6,7,11,342,217,12,120,180,40,317,141,8 },
776 { 53,27,17,161,469,378,73,527,19,136,383,250,495,56,862,26,62,84,80,106,200,4,34,14,440,297,3,128,585,5,129,123 },
777 { 17,45,209,106,5,207,243,454,119,255,2,263,186,290,29,3,21,62,425,61,84,32,58,56,48,408,655,136,306,14,742,227 },
778 { 4,152,59,452,128,79,216,11,339,471,529,188,94,77,202,12,291,33,318,377,99,51,23,5,402,349,32,474,102,13,205,111 },
779 { 15,515,700,753,1,0,2,13,3,5,23,4,180,51,115,9,6,12,7,8,197,33,10,961,901,77,141,752,110,22,120,341 },
780 { 951,752,638,811,351,642,180,253,10,341,197,901,110,873,8,244,15,352,165,898,143,515,564,762,499,55,365,700,82,753,141,854 },
781 { 6,262,197,350,74,26,115,509,841,583,165,38,21,13,47,50,235,19,33,324,453,4,308,196,138,99,64,903,675,1,223,130 },
782 { 125,165,391,23,386,221,21,13,558,457,51,867,197,115,401,758,77,97,308,791,7,180,48,120,963,451,743,89,603,134,403,450 },
783 { 1,14,2,5,16,46,7,38,58,24,50,0,69,48,35,67,54,18,12,75,21,45,513,155,430,37,270,9,61,163,223,32 },
784 { 23,13,51,0,12,15,4,1,115,2,515,453,10,457,5,3,202,21,165,700,403,11,37,64,77,401,9,197,753,59,475,99 },
785 { 129,84,17,56,27,495,19,548,80,123,162,378,3,504,161,469,618,73,40,53,4,26,205,184,106,183,62,6,257,128,862,12 },
786 { 28,9,22,49,109,1,67,0,39,55,168,158,83,36,35,86,420,194,185,159,95,105,69,208,272,103,50,114,2,254,169,30 },
787 { 242,391,8,456,116,13,23,492,341,165,867,51,499,457,479,638,338,509,719,10,1,642,417,762,401,93,206,268,901,569,22,197 },
788 { 211,162,248,130,57,4,41,556,507,266,183,152,305,361,11,129,62,229,38,471,514,313,157,300,377,3,440,128,123,328,339,59 },
789 { 7,92,97,16,298,140,60,126,14,35,279,314,232,246,43,230,508,173,71,107,423,24,150,779,20,189,66,18,607,21,0,653 },
790 { 15,515,700,753,1,0,2,13,23,5,3,180,51,901,6,4,7,12,9,115,8,457,165,82,120,197,10,64,141,341,22,117 },
791 { 0,18,403,25,523,74,6,24,42,91,22,102,13,51,49,193,475,681,95,85,730,64,899,397,273,750,247,673,32,805,757,288 },
792 { 56,0,18,65,33,554,84,343,64,6,90,561,22,19,899,108,27,63,289,475,240,467,370,32,233,214,24,123,95,287,28,194 },
793 { 31,98,127,9,0,44,293,105,395,299,49,242,28,22,599,116,1,284,276,125,456,685,763,159,272,623,23,935,393,144,201,137 },
794 { 1,5,2,14,38,46,50,48,21,7,58,45,270,61,155,171,0,290,69,32,29,54,67,16,24,666,663,17,37,75,502,52 },
795 { 23,51,13,453,457,12,719,4,15,99,401,2,961,3,11,730,475,515,0,1,165,115,629,700,14,17,403,40,5,33,37,64 },
796 { 968,967,966,965,964,963,962,961,960,959,958,957,956,955,954,953,952,951,950,949,948,947,946,945,944,943,942,941,940,939,938,937 },
797 { 2,1,14,29,67,103,6,46,52,75,24,133,38,218,83,309,36,108,70,114,96,5,238,74,25,26,220,236,65,50,69,87 },
798 { 7,71,16,92,24,60,14,97,150,140,35,189,149,298,18,230,43,508,2,423,69,0,38,314,66,279,399,517,251,20,232,273 },
799 { 23,1,120,51,13,202,77,141,260,21,15,5,128,82,2,450,269,165,102,318,48,32,137,515,125,64,12,115,351,180,33,7 },
800 { 77,13,33,23,64,51,4,102,141,128,40,1,2,202,0,6,177,115,137,15,59,10,11,7,269,22,515,180,318,3,700,95 },
801 { 101,9,18,363,264,520,411,604,676,682,905,271,16,821,167,0,621,364,39,100,121,118,166,781,647,252,1,848,447,265,404,60 },
802 { 144,203,326,382,166,418,93,88,96,822,1,141,859,77,744,438,110,269,921,367,521,274,100,39,494,120,403,473,217,576,13,291 },
803 { 13,21,180,125,5,23,191,32,18,16,146,199,115,24,165,118,0,225,22,1,60,197,64,901,375,241,48,12,408,71,522,818 },
804 { 15,515,700,753,13,0,23,8,1,51,82,102,2,33,4,9,180,165,5,77,10,110,12,197,120,260,18,326,351,403,22,457 },
805 { 33,77,102,64,13,23,128,51,141,202,1,40,0,2,117,10,15,4,6,318,269,134,22,515,180,115,177,153,137,196,3,700 },
806 { 174,544,104,525,74,0,151,25,6,624,29,66,2,636,81,45,204,177,64,416,7,644,5,138,222,319,355,77,22,122,789,216 },
807 { 141,304,372,352,291,947,177,269,128,954,77,349,217,202,64,318,498,437,102,864,86,13,115,180,137,5,210,197,32,950,678,7 },
808 { 161,200,53,17,714,27,34,73,472,62,585,56,440,383,136,78,527,19,4,3,106,361,14,250,80,514,377,84,322,390,862,548 },
809 { 32,76,72,21,38,14,89,54,12,37,2,241,5,428,17,1,181,221,350,45,3,4,449,90,148,179,99,292,794,770,477,46 },
810 { 33,23,128,64,141,13,77,51,102,202,2,15,1,3,40,10,5,153,269,515,165,0,117,196,180,318,6,700,137,134,120,22 },
811 { 96,137,30,0,9,39,840,202,669,406,141,530,613,1,180,88,22,160,679,576,28,403,31,219,49,228,829,100,36,15,10,856 },
812 { 180,141,352,1,15,752,115,0,217,365,2,515,13,901,341,317,23,4,197,700,269,5,3,31,753,244,21,165,253,202,51,44 },
813 { 1,2,67,0,28,50,83,65,14,46,103,114,24,38,36,9,69,5,18,7,22,133,55,218,16,124,29,54,96,160,12,480 },
814 { 180,115,352,317,365,217,752,901,141,15,341,1,515,253,700,0,753,873,2,197,31,137,165,244,4,120,160,44,98,5,202,3 },
815 { 5,32,347,49,13,21,95,713,23,1,77,33,60,64,107,4,126,928,296,850,0,241,197,102,652,195,180,534,165,153,379,10 },
816 { 341,180,365,901,317,115,15,752,515,700,217,873,753,82,0,110,197,141,951,165,1,564,13,351,253,12,10,3,2,4,308,244 },
817 { 17,45,21,3,106,5,155,38,227,32,2,209,62,54,12,243,14,181,552,587,46,540,207,794,37,48,430,119,255,221,770,29 },
818 { 16,24,35,18,7,0,50,1,9,14,75,69,2,5,12,21,60,13,67,71,23,48,10,108,223,181,189,103,46,64,92,51 },
819 { 127,13,98,165,308,23,286,293,258,51,219,395,197,115,301,401,31,391,22,105,457,170,239,276,55,338,629,116,180,479,509,569 },
820 { 539,213,748,840,957,669,30,466,88,217,144,251,863,190,137,93,230,228,679,352,317,203,617,321,258,530,160,219,96,831,816,689 },
821 { 5,48,1,21,2,14,0,36,12,38,32,54,430,181,50,270,72,99,281,45,17,10,46,22,37,218,67,3,290,76,23,51 },
822 { 13,23,0,4,33,51,2,115,141,1,77,217,180,10,9,317,3,102,11,5,15,197,7,202,22,165,40,64,515,6,341,31 },
823 { 13,15,117,515,23,12,37,134,165,700,38,54,457,753,51,64,153,197,14,10,33,82,961,0,99,89,115,719,141,3,4,1 },
824 { 5,21,2,3,1,32,14,12,48,17,0,10,51,23,38,22,4,72,13,54,36,45,137,76,99,114,86,37,11,64,540,430 },
825 { 202,128,77,318,291,33,269,102,275,141,494,342,40,678,0,177,20,210,402,7,4,5,137,6,13,450,403,32,49,120,23,22 },
826 { 1,2,24,14,67,46,69,50,38,103,16,18,75,35,83,29,52,96,5,108,0,7,54,71,149,394,236,309,70,133,220,58 },
827 { 15,515,1,700,0,2,753,13,23,5,180,3,51,4,165,457,12,197,115,6,7,21,9,141,8,901,33,82,120,77,10,110 },
828 { 0,28,65,14,67,2,124,24,1,9,7,69,55,154,36,16,46,114,175,35,83,22,429,18,109,149,68,189,108,336,251,133 },
829 { 56,162,403,3,129,775,99,161,17,40,527,33,880,4,14,128,475,12,548,23,102,202,361,117,34,184,383,200,183,196,64,53 },
830 { 151,2,29,58,112,45,186,113,5,70,52,1,311,6,315,66,61,7,74,27,631,17,80,87,287,243,209,227,14,491,19,869 },
831 { 6,1,74,2,75,29,25,66,26,70,52,138,67,324,357,42,19,220,14,85,87,108,38,451,309,103,24,69,380,135,114,65 },
832 { 15,515,700,13,23,0,1,120,753,51,180,2,260,202,5,141,77,102,9,450,115,21,197,165,7,137,110,33,12,269,901,4 },
833 { 5,45,17,2,14,46,48,38,181,50,155,3,186,54,61,29,21,227,281,80,540,106,12,400,52,1,58,32,328,171,209,487 },
834 { 16,18,265,121,158,35,60,9,39,7,329,105,252,68,24,1,132,167,159,22,0,49,286,101,21,146,23,327,120,709,5,14 },
835 { 108,467,283,56,389,650,123,412,33,177,899,475,216,453,269,349,619,65,51,730,403,670,23,196,523,128,84,13,401,789,503,543 },
836 { 514,3,11,377,328,4,361,507,57,403,14,880,130,485,176,215,236,38,152,102,211,56,62,757,54,585,300,556,34,555,40,229 },
837 { 3,555,62,266,130,99,507,139,514,12,152,229,215,305,57,40,440,33,403,471,38,56,475,14,361,313,775,328,196,548,123,23 },
838 { 120,202,318,15,77,13,1,450,33,269,515,260,5,128,494,51,23,700,102,141,40,753,326,403,817,137,523,21,177,922,342,7 },
839 { 15,1,515,23,0,13,700,2,51,753,180,5,165,21,197,12,3,120,115,4,141,6,9,7,457,33,386,202,82,8,31,341 },
840 { 15,180,515,82,351,700,10,317,753,115,217,365,141,898,33,901,13,23,110,854,752,77,1,197,4,341,143,36,64,352,102,9 },
841 { 104,289,66,707,214,90,712,64,97,173,20,0,414,194,874,43,32,7,568,560,65,38,426,312,715,192,376,74,835,5,324,147 },
842 { 84,56,0,554,63,65,453,249,123,643,18,26,847,475,511,403,416,561,524,289,370,73,9,19,45,42,719,194,27,467,33,730 },
843 { 21,346,13,350,308,826,197,101,352,68,570,0,165,23,9,841,115,100,509,694,221,230,35,217,569,88,124,749,1,777,212,154 },
844 { 16,92,7,24,60,18,35,140,126,14,50,71,46,330,2,75,246,5,121,267,571,1,230,309,220,0,9,64,146,236,54,108 },
845 { 82,15,515,898,365,700,180,33,341,753,77,901,10,115,55,351,21,5,1,4,13,102,36,217,2,165,752,120,197,117,11,317 },
846 { 16,24,35,18,69,71,140,1,103,7,189,68,0,50,9,108,2,133,60,267,230,46,149,67,167,118,92,14,75,21,191,38 },
847 { 60,71,16,18,7,20,43,118,35,68,375,28,608,0,175,566,154,92,14,149,628,33,22,13,2,10,279,23,107,356,55,117 },
848 { 187,258,871,295,201,434,219,224,489,384,268,110,261,839,44,699,93,116,36,131,141,228,144,160,940,567,244,406,137,574,98,253 },
849 { 66,7,97,172,192,712,232,324,204,74,43,448,387,426,568,20,526,107,104,135,356,729,173,0,22,5,32,95,2,64,500,560 },
850 { 15,515,700,753,1,4,0,341,13,3,134,2,5,33,11,77,12,10,23,197,365,901,7,40,217,32,21,6,51,180,961,37 },
851 { 0,28,24,9,35,65,16,124,68,55,109,154,7,39,22,149,158,14,175,1,49,252,18,71,2,168,289,419,108,420,67,101 },
852 { 7,16,14,92,2,46,140,24,220,35,38,60,75,1,50,18,87,54,5,126,29,52,278,262,314,107,71,21,172,135,330,394 },
853 { 7,92,16,14,172,126,2,60,140,35,135,314,278,46,24,38,232,107,330,66,5,18,150,246,230,97,52,1,121,563,279,21 },
854 { 6,26,235,53,297,436,27,19,25,73,113,445,90,214,65,42,64,289,250,611,624,32,45,648,614,17,85,491,34,122,200,416 },
855 { 352,141,1,217,854,752,351,180,244,36,110,661,82,258,816,160,295,219,567,224,230,269,922,144,260,268,93,201,137,116,489,202 },
856 { 16,60,35,18,126,107,68,191,92,121,7,14,598,20,493,279,167,446,118,0,28,43,463,55,24,212,375,566,9,150,575,21 },
857 { 15,1,515,2,4,13,0,700,3,5,23,753,341,77,51,115,33,11,180,10,197,141,6,165,7,901,102,40,9,202,217,12 },
858 { 23,51,13,202,21,5,1,120,15,137,128,125,32,2,12,141,33,165,64,515,403,318,700,48,180,7,6,450,115,523,475,260 },
859 { 131,716,224,371,219,187,737,616,385,254,9,98,105,924,31,258,836,39,127,578,49,916,44,761,272,137,944,159,0,242,442,22 },
860 { 15,515,700,1,753,2,5,0,4,13,3,180,11,141,197,10,341,217,33,134,165,6,77,7,317,12,352,64,365,32,102,40 },
861 { 66,74,7,173,174,29,192,2,222,20,226,43,353,52,712,6,0,138,500,204,97,145,64,104,426,673,355,90,25,5,65,87 },
862 { 5,259,786,534,590,493,279,49,13,581,465,21,929,35,941,132,147,32,23,612,362,626,107,121,178,0,146,61,48,939,10,18 },
863 { 2,14,16,7,278,69,135,140,46,24,267,35,92,38,1,189,29,52,309,60,66,75,71,172,74,357,18,87,67,6,230,5 },
864 { 165,13,308,197,391,23,401,15,51,457,180,509,115,569,3,629,961,719,34,758,317,734,14,29,46,2,17,901,38,453,5,217 },
865 { 1,22,2,14,0,28,7,168,67,49,65,24,36,95,5,105,55,35,12,46,69,16,114,159,194,50,10,9,158,83,164,109 },
866 { 34,453,3,196,130,14,322,11,47,51,377,236,361,4,730,153,514,711,57,440,62,17,161,108,176,59,485,56,162,412,202,117 },
867 { 18,16,21,23,48,13,24,35,121,5,156,60,51,1,7,132,141,221,163,115,0,271,447,340,363,202,125,71,2,781,22,698 },
868 { 165,13,457,23,197,961,629,569,341,41,12,38,401,901,54,51,115,17,15,509,421,37,62,45,719,57,32,328,117,758,157,99 },
869 { 2,1,77,141,33,64,3,102,0,23,13,5,128,10,6,15,180,202,269,40,51,515,7,165,137,117,318,4,700,153,197,352 },
870 { 68,212,0,124,101,9,154,16,562,191,21,149,65,24,35,1,118,167,818,350,520,100,722,841,264,71,13,302,478,23,375,346 },
871 { 98,23,48,598,13,293,541,21,125,121,51,807,0,31,35,259,126,7,386,1,223,783,10,107,199,20,221,144,342,963,49,64 },
872 { 21,13,5,586,1,23,167,48,33,781,647,49,165,18,51,271,77,32,761,118,0,82,391,22,146,141,459,31,197,156,115,4 },
873 { 2,1,5,61,29,7,58,45,14,6,425,32,70,52,290,738,207,21,72,112,66,76,655,17,186,46,64,263,38,0,128,87 },
874 { 39,265,9,100,1,333,363,101,18,411,447,254,166,310,31,98,264,30,639,404,156,286,16,93,593,203,272,682,0,905,44,821 },
875 { 6,2,1,19,29,51,26,108,25,74,5,23,14,114,13,386,133,103,42,66,453,70,309,138,719,324,65,38,64,96,52,75 },
876 { 20,43,356,107,49,858,595,7,414,359,0,5,392,319,97,612,422,819,14,376,173,246,22,470,147,427,230,92,197,33,683,95 },
877 { 0,9,68,35,65,67,114,101,28,1,124,175,336,69,154,103,83,24,189,133,39,16,50,7,2,149,55,251,18,345,230,36 },
878 { 23,13,51,15,0,1,515,115,165,2,5,12,700,202,4,21,141,457,753,197,10,3,180,120,32,9,318,11,453,64,6,269 },
879 { 121,195,60,16,126,107,98,271,146,407,132,35,1,167,199,223,493,191,279,20,18,5,43,7,21,92,48,393,0,362,212,467 },
880 { 31,44,299,116,393,144,492,456,268,22,105,0,367,918,384,434,127,489,98,9,963,125,242,948,1,28,206,49,36,51,93,293 },
881 { 23,13,457,51,165,401,719,758,197,453,961,629,308,14,15,12,730,3,386,569,391,29,739,515,34,828,832,901,115,514,670,341 },
882 { 105,36,131,22,180,115,341,127,169,1,9,31,64,98,44,365,317,141,272,143,160,55,219,86,197,776,239,187,0,535,13,752 },
883 { 1,6,2,14,66,25,29,5,108,67,65,114,19,38,26,52,74,7,24,18,69,86,36,388,64,51,17,83,23,46,42,75 },
884 { 51,386,23,453,719,13,730,6,457,670,758,19,401,165,2,475,47,26,899,14,108,17,1,5,197,29,894,754,236,74,27,285 },
885 { 252,18,9,101,121,16,132,0,419,167,364,60,604,35,265,363,146,271,39,158,68,109,28,329,848,24,647,907,682,159,212,55 },
886 { 283,503,128,432,26,193,63,269,789,529,102,122,389,275,678,6,25,318,445,4,342,27,573,605,177,862,643,291,216,57,235,59 },
887 { 2,1,29,75,69,52,14,6,46,74,87,7,220,226,278,38,135,66,267,70,16,262,25,24,380,324,357,140,67,394,97,222 },
888 { 97,298,69,7,66,140,189,24,16,267,172,423,60,150,14,314,92,71,81,501,43,35,74,6,517,232,149,607,83,330,18,2 },
889 { 475,421,403,899,51,805,523,958,453,817,23,615,401,801,120,326,202,670,494,730,450,386,115,629,260,576,77,365,569,0,165,13 },
890 { 7,20,14,128,77,97,112,202,2,177,16,415,269,318,275,66,107,43,141,414,135,38,307,10,58,0,6,291,32,5,4,40 },
891 { 24,14,7,0,2,1,22,28,16,65,168,124,35,67,108,109,18,49,10,149,69,158,5,95,289,12,55,6,36,71,46,21 },
892 { 26,80,27,73,122,25,19,17,6,42,684,209,445,573,667,106,45,690,4,611,255,680,297,495,65,59,128,119,483,113,64,53 },
893 { 107,259,362,376,465,20,470,147,595,534,612,683,660,43,5,49,581,0,858,35,427,246,97,786,178,356,14,21,142,878,7,279 },
894 { 131,30,228,190,856,406,224,88,219,530,863,613,778,274,944,816,187,39,100,160,258,31,44,93,1,321,539,36,871,137,435,531 },
895 { 113,6,311,25,45,491,80,611,27,26,209,667,17,73,122,42,684,396,19,85,106,5,614,4,2,255,151,29,1,64,648,61 },
896 { 15,515,700,753,0,1,23,51,120,2,13,82,5,260,9,4,341,77,180,115,141,10,7,12,450,8,202,901,197,351,165,93 },
897 { 219,127,98,258,395,421,924,293,242,201,697,105,276,51,308,23,453,272,401,944,512,137,13,31,284,567,386,365,116,131,964,125 },
898 { 15,180,352,141,515,752,217,82,1,317,854,700,351,753,115,341,110,13,260,120,21,36,33,898,23,10,5,365,4,160,901,137 },
899 { 129,123,17,257,162,184,205,249,183,769,5,80,3,4,229,130,119,45,90,99,618,106,57,497,12,128,2,84,59,152,27,40 },
900 { 33,102,23,77,64,128,51,13,0,202,10,141,40,15,1,22,117,137,2,86,4,403,269,153,515,196,65,11,700,115,99,5 },
901 { 7,14,2,16,172,107,46,92,5,135,35,202,294,87,38,232,29,97,20,21,24,1,60,220,66,43,12,0,126,52,54,70 },
902 { 403,576,615,523,475,326,805,817,494,421,51,202,120,450,137,453,23,859,260,401,402,77,33,670,0,958,15,197,386,515,165,480 },
903 { 141,352,217,137,0,180,202,349,9,269,23,51,115,291,77,372,13,317,120,752,365,351,93,22,2,341,64,10,82,854,28,18 },
904 { 1,23,13,51,202,141,5,165,21,15,120,180,64,2,197,125,33,102,12,7,137,515,48,128,269,318,93,700,0,403,9,4 },
905 { 25,151,6,145,122,29,174,45,113,74,4,665,42,138,2,614,416,287,19,348,746,0,66,26,1,7,64,243,311,396,81,624 },
906 { 30,190,254,166,100,382,731,829,88,131,264,795,9,93,625,274,438,1,578,613,716,31,44,39,530,36,616,921,265,203,160,77 },
907 { 132,5,21,13,1,23,32,195,379,687,156,121,626,296,48,70,850,146,51,82,883,771,35,49,652,407,60,4,260,0,845,33 },
908 { 9,254,0,49,272,131,39,159,688,101,105,578,518,158,286,28,327,333,68,224,252,219,344,16,22,1,716,31,30,228,24,890 },
909 { 16,7,35,60,18,20,14,68,9,0,28,118,43,92,126,55,107,2,101,154,24,71,5,202,121,109,22,252,21,97,1,621 },
910 { 15,515,700,753,13,1,341,2,0,4,3,5,11,23,10,33,117,12,901,197,6,134,77,8,165,317,21,365,217,7,17,40 },
911 { 78,19,444,47,26,390,27,453,130,813,108,730,711,65,412,122,51,680,113,235,690,196,630,283,128,236,14,64,73,53,200,445 },
912 { 2,7,29,5,61,6,45,1,66,113,112,14,52,315,738,128,32,151,74,16,20,64,70,21,592,0,25,4,425,43,491,222 },
913 { 145,112,74,66,6,29,26,70,19,396,25,87,2,287,135,151,138,222,5,226,42,122,7,307,1,644,45,58,113,651,635,632 },
914 { 92,16,7,60,126,24,140,35,14,232,18,121,246,71,46,267,172,150,107,314,132,146,230,2,278,108,330,199,236,5,38,572 },
915 { 13,115,197,538,569,341,98,55,165,127,365,762,219,286,844,23,170,206,734,638,535,901,169,253,629,0,873,509,180,10,332,258 },
916 { 58,151,74,53,287,27,29,396,6,70,2,73,5,52,112,26,651,1,297,113,17,75,19,45,334,445,145,34,315,549,436,331 },
917 { 214,289,90,874,104,751,64,65,312,835,204,249,750,194,74,81,875,32,519,288,348,0,174,247,636,715,138,192,784,6,524,280 },
918 { 9,39,28,35,30,0,166,49,1,175,439,158,64,346,36,101,67,364,86,88,274,100,168,55,23,10,420,22,190,141,505,180 },
919 { 341,901,15,515,700,753,1,365,10,0,569,180,2,197,115,31,165,3,5,4,44,22,317,13,9,951,23,253,116,143,762,93 },
920 { 120,202,77,450,260,15,128,318,102,515,494,13,817,700,269,5,403,51,1,33,23,753,82,326,141,342,291,137,21,523,351,32 },
921 { 13,115,241,64,180,32,125,197,165,4,118,22,21,23,16,247,237,28,225,191,95,141,167,5,0,341,288,35,459,18,177,24 },
922 { 16,24,35,14,1,2,7,69,18,46,60,50,267,140,71,189,108,38,75,92,0,5,9,230,67,21,309,335,54,236,394,220 },
923 { 15,515,700,753,898,180,901,341,197,638,10,165,33,1,115,4,77,365,317,13,102,217,117,0,5,2,253,3,82,569,21,752 },
924 { 193,523,18,84,56,730,233,65,4,817,90,33,643,403,91,511,453,240,59,11,214,51,719,196,153,475,32,123,64,847,102,561 },
925 { 112,29,151,2,74,6,66,7,222,145,287,45,5,624,52,25,113,416,58,122,19,70,186,204,4,87,644,549,337,884,32,0 },
926 { 13,0,23,2,1,15,33,3,77,515,141,5,4,217,10,51,64,180,700,115,6,117,11,7,753,40,102,165,197,22,317,153 },
927 { 28,0,1,67,65,9,2,114,83,69,103,50,36,22,55,24,46,14,124,109,35,7,16,38,133,160,389,323,18,12,154,5 },
928 { 121,132,18,167,271,146,101,363,621,9,411,647,16,354,520,60,212,932,1,806,55,0,195,446,68,35,31,364,777,252,407,118 },
929 { 26,6,85,396,122,624,25,19,42,445,64,648,573,416,174,680,665,214,45,348,90,65,194,145,113,881,138,289,112,436,297,544 },
930 { 16,146,18,92,24,199,60,71,121,126,35,108,156,953,271,674,132,7,32,640,360,246,649,118,21,95,5,517,14,9,1,314 },
931 { 51,13,23,453,475,730,719,15,457,403,64,115,33,95,4,523,3,12,21,6,899,102,5,128,401,202,11,141,308,515,22,125 },
932 { 151,396,6,53,27,113,58,26,73,112,74,287,45,29,297,19,145,70,138,445,315,436,34,2,17,573,5,61,549,491,1,80 },
933 { 223,1,888,774,260,98,269,385,349,202,96,141,421,622,730,863,318,697,87,453,393,418,922,834,751,5,163,335,120,291,352,30 },
934 { 16,60,92,35,126,121,7,150,246,18,107,1,598,24,167,195,14,97,71,279,98,441,191,199,517,146,356,223,298,271,230,0 },
935 { 22,1,105,28,239,170,0,55,95,31,36,301,2,320,98,127,9,49,44,64,35,67,10,86,5,12,109,23,168,13,21,312 },
936 { 2,6,5,207,292,76,1,119,45,32,17,29,61,306,790,58,240,106,14,64,214,151,476,710,7,72,84,128,4,179,70,25 },
937 { 51,23,221,254,115,13,438,530,125,48,21,39,541,960,386,49,1,613,15,840,228,308,627,131,688,401,5,326,421,158,165,83 },
938 { 1,5,2,0,12,22,21,36,10,14,48,86,23,13,32,54,3,4,28,65,51,50,137,37,208,114,9,38,17,7,281,202 },
939 { 363,23,447,182,296,340,1,93,698,478,379,156,284,144,18,269,21,98,141,70,668,411,664,658,110,914,67,937,180,691,335,291 },
940 { 17,32,45,498,41,115,180,197,106,62,54,38,546,165,13,155,468,509,341,243,241,217,542,15,57,536,428,51,117,721,292,129 },
941 { 32,95,64,246,22,92,180,13,5,652,125,241,638,237,7,49,4,126,21,115,197,296,888,316,0,165,774,23,16,392,1,534 },
942 { 15,515,700,753,33,341,13,217,4,141,77,23,180,317,1,10,102,351,82,115,40,5,854,21,137,11,352,901,365,117,197,0 },
943 { 15,120,1,82,93,217,515,260,77,141,13,110,700,351,352,23,180,753,21,854,202,317,64,349,269,51,165,137,5,128,291,36 },
944 { 13,23,51,141,77,0,33,4,115,64,2,10,102,202,217,128,1,177,269,11,7,22,6,21,32,9,180,40,15,3,165,318 },
945 { 478,264,1,520,98,724,9,682,223,664,21,759,13,772,604,100,23,363,411,48,821,5,0,905,909,447,31,265,88,101,166,39 },
946 { 20,29,7,2,77,416,6,128,33,5,0,113,104,32,43,13,491,66,23,21,102,51,74,210,202,525,64,318,10,81,174,14 },
947 { 2,1,5,14,7,58,61,29,45,290,46,38,52,21,32,270,6,592,425,0,75,155,16,48,17,50,72,70,207,24,263,663 },
948 { 80,6,17,209,106,26,483,113,19,469,255,25,378,27,495,833,45,64,161,2,61,667,76,742,32,90,445,5,814,65,887,119 },
949 { 98,223,393,1,354,834,195,791,447,697,284,293,360,541,781,156,51,807,18,664,421,411,163,668,48,31,591,765,883,386,948,23 },
950 { 679,141,816,36,93,406,876,144,228,137,1,180,669,21,332,251,5,269,116,187,96,351,202,752,317,64,203,831,574,466,855,345 },
951 { 15,515,700,13,1,753,2,0,23,341,3,5,4,10,51,11,33,165,6,7,115,197,12,64,180,153,217,77,9,569,901,317 },
952 { 13,23,202,51,5,21,403,15,120,64,1,450,128,141,12,523,33,165,494,125,2,515,269,7,48,102,318,95,260,180,453,197 },
953 { 16,18,24,60,71,92,146,246,199,35,140,7,9,118,121,108,167,230,126,132,0,640,156,14,68,133,267,360,649,271,64,55 },
954 { 269,141,678,177,202,77,128,318,33,947,40,120,291,349,102,137,64,352,210,864,461,498,13,342,196,23,275,450,954,0,205,111 },
955 { 16,24,92,18,71,60,35,7,108,191,167,246,140,14,126,21,1,68,150,118,149,388,399,9,273,0,121,796,230,48,212,517 },
956 { 2,14,1,29,46,75,52,70,69,171,38,7,58,163,16,5,24,220,67,112,223,54,50,409,155,35,267,186,151,334,394,140 },
957 { 9,252,100,265,166,39,88,404,329,0,1,520,382,812,101,593,264,274,604,676,30,118,68,553,18,664,363,23,639,865,21,411 },
958 { 16,18,35,24,0,60,158,7,22,68,14,49,109,159,55,9,28,71,2,10,5,105,1,118,329,13,344,23,92,20,21,126 },
959 { 15,13,515,700,23,0,753,1,51,2,4,10,77,5,3,197,115,165,961,202,9,457,180,12,141,22,33,120,6,11,318,31 },
960 { 160,93,251,137,317,1,180,36,120,217,345,752,617,352,332,10,96,531,498,318,365,202,141,269,816,341,901,679,143,35,83,968 },
961 { 6,25,42,128,19,59,122,4,85,26,611,27,269,233,45,0,343,91,318,80,11,177,283,73,33,614,2,77,64,138,445,216 },
962 { 95,64,74,7,32,81,51,204,0,20,237,65,56,38,91,23,207,180,347,343,29,6,511,52,49,10,25,18,554,370,14,312 },
963 { 202,120,326,260,450,817,494,318,137,403,128,77,523,553,859,5,704,1,15,23,13,576,7,16,615,51,682,291,515,0,21,234 },
964 { 20,43,107,356,362,126,595,92,359,7,422,319,493,16,858,5,392,246,414,683,60,0,35,945,441,21,259,819,49,97,279,173 },
965 { 25,42,6,77,33,102,0,122,4,690,29,483,210,27,21,19,2,300,18,648,680,119,117,59,1,10,342,12,26,153,91,684 },
966 { 31,44,299,116,125,242,456,599,22,393,0,144,492,28,268,1,9,963,301,105,367,36,127,170,384,434,206,98,918,10,13,93 },
967 { 410,521,686,367,662,88,335,321,201,96,98,772,144,1,934,921,443,435,284,274,264,551,120,897,44,100,33,225,744,418,909,960 },
968 { 142,178,878,234,132,786,195,202,77,416,147,929,146,522,167,259,687,639,450,271,626,481,590,5,198,212,771,49,0,465,315,427 },
969 { 254,39,131,9,272,0,578,716,310,224,30,49,105,827,518,829,166,333,616,228,613,846,101,219,1,31,890,98,159,938,252,100 },
970 { 230,699,854,473,450,351,831,137,855,217,352,704,800,202,251,498,160,144,206,203,317,201,253,752,418,141,1,332,82,180,443,36 },
971 { 403,202,475,453,494,23,51,77,318,402,13,33,128,102,137,141,120,342,269,0,450,4,899,576,40,421,275,117,217,177,196,64 },
972 { 23,44,98,182,291,144,116,39,110,141,96,82,905,70,367,264,125,93,77,411,120,1,658,202,100,415,107,363,197,30,447,105 },
973 { 15,515,1,13,700,23,77,120,0,753,51,180,202,141,260,5,21,115,2,137,128,9,450,197,365,269,12,326,110,102,318,7 },
974 { 0,32,18,95,207,577,193,29,61,104,64,784,715,102,693,887,81,91,583,671,403,5,52,474,397,180,138,49,37,344,38,263 },
975 { 0,101,9,68,252,16,100,39,166,364,124,24,154,265,212,88,18,35,329,419,28,118,71,30,65,158,191,55,1,694,21,676 },
976 { 16,24,191,18,35,71,167,118,149,68,212,9,0,1,21,108,101,92,60,375,302,7,589,755,124,674,350,48,562,246,13,363 },
977 { 2,14,69,24,1,67,46,16,38,103,29,267,7,35,189,135,278,71,108,18,83,309,52,6,149,388,75,236,60,0,150,66 },
978 { 13,1,23,0,4,2,51,15,180,33,3,115,5,515,141,10,77,700,11,9,197,341,202,165,217,102,22,7,753,317,365,6 },
979 { 447,1,698,411,31,363,98,5,919,4,156,125,759,691,13,64,459,354,44,21,48,293,30,914,478,225,82,120,2,922,848,839 },
980 { 854,82,351,217,141,180,352,15,515,752,1,700,317,898,753,244,10,21,922,115,77,36,4,260,64,110,372,13,5,365,120,11 },
981 { 0,1,4,13,5,2,82,33,3,120,10,23,9,11,77,260,21,102,8,31,40,6,351,51,64,450,22,117,93,110,7,457 },
982 { 51,13,403,23,12,475,1,2,21,5,453,523,115,202,817,7,0,99,3,6,450,120,494,64,22,95,49,899,10,37,32,141 },
983 { 180,752,352,141,498,864,317,217,9,0,115,237,230,39,30,197,83,1,930,64,35,365,372,13,579,88,702,36,101,901,482,21 },
984 { 16,24,0,7,22,18,28,35,14,158,71,2,109,60,1,168,49,154,124,68,10,55,92,118,159,9,5,747,95,105,65,6 },
985 { 15,515,700,753,0,23,1,13,341,51,120,77,141,4,137,33,260,82,202,9,180,5,351,2,291,10,11,901,21,115,40,128 },
986 { 24,68,35,149,18,16,0,7,9,14,189,108,69,65,67,1,71,2,118,28,140,101,114,336,230,124,175,133,46,55,251,154 },
987 { 13,308,197,115,125,9,165,237,391,23,509,569,546,28,49,629,22,338,317,254,749,180,468,159,903,386,217,352,558,39,36,734 },
988 { 64,90,32,217,77,4,141,216,172,312,128,13,86,33,597,147,352,95,5,115,875,22,59,11,102,14,182,437,97,177,874,707 },
989 { 1,22,36,0,105,28,2,67,95,49,55,5,239,12,86,9,83,170,312,64,31,21,23,10,164,50,114,159,208,13,7,320 },
990 { 9,18,16,0,159,105,101,252,49,310,24,68,35,39,265,272,7,1,60,28,455,890,329,557,118,286,55,137,327,167,5,13 },
991 { 129,123,214,249,618,17,5,257,205,184,460,76,2,162,769,245,90,106,128,45,119,1,183,4,3,12,179,64,6,229,99,209 },
992 { 51,453,719,457,23,13,730,899,475,386,4,15,11,12,670,196,515,523,961,401,153,3,700,99,753,117,403,32,120,165,57,0 },
993 { 173,66,192,204,20,74,104,636,7,43,289,426,825,712,560,214,81,750,65,97,707,0,90,414,64,348,32,500,22,861,95,6 },
994 { 13,23,1,51,5,21,141,120,202,15,165,2,515,180,12,125,0,64,82,700,197,269,32,48,260,128,115,93,9,137,33,753 },
995 { 200,34,322,78,472,390,27,714,19,14,136,161,453,176,236,444,59,3,62,128,108,57,283,862,73,53,47,17,412,813,4,56 },
996 { 33,347,66,204,426,498,56,172,97,95,5,681,546,22,10,0,135,180,4,241,19,174,6,353,263,21,7,370,42,197,27,808 },
997 { 131,224,219,187,385,371,258,442,254,737,31,98,836,127,924,944,44,871,908,716,39,827,201,574,116,137,36,1,276,242,578,616 },
998 { 1,15,2,180,4,141,13,515,0,5,3,115,700,901,341,23,217,352,753,51,197,77,317,33,365,752,165,21,6,7,269,93 },
999 { 370,91,718,74,81,510,397,66,636,240,355,84,138,511,18,278,6,681,701,289,90,5,214,582,64,104,0,643,192,65,750,32 },
1000 { 15,515,700,753,13,120,1,0,165,2,197,23,260,180,4,82,51,386,8,5,12,10,3,141,351,341,326,9,450,7,64,6 },
1001 { 32,2,76,5,1,292,72,45,476,214,21,241,29,14,17,48,129,90,179,460,464,123,290,148,519,205,3,263,249,38,710,89 },
1002 { 13,165,115,17,197,569,23,509,457,45,32,41,106,180,62,38,659,734,155,536,341,629,961,873,587,54,431,37,391,99,405,428 },
1003 { 68,24,35,16,0,101,9,124,154,71,149,65,18,175,28,118,7,55,302,108,92,14,22,346,1,39,429,252,375,364,10,67 },
1004 { 0,9,1,68,230,65,35,69,83,23,101,13,141,67,217,352,21,39,16,88,28,124,212,100,115,154,51,64,30,36,10,317 },
1005 { 100,265,88,909,410,382,812,593,1,213,321,30,252,230,352,264,9,166,689,39,676,98,21,466,724,639,478,217,13,48,553,101 },
1006 { 113,61,198,904,43,0,5,37,899,325,20,59,33,523,204,725,817,389,470,329,222,40,174,58,22,453,690,848,122,104,788,105 },
1007 { 16,24,141,18,7,0,71,140,35,269,75,352,12,9,108,217,5,330,60,64,199,70,22,13,486,246,318,133,65,50,23,498 },
1008 { 271,167,121,60,18,191,146,199,16,1,446,132,575,212,463,354,126,35,598,566,727,98,107,21,608,955,640,407,5,24,223,68 },
1009 { 15,515,115,217,700,13,317,753,141,180,33,23,110,120,4,341,82,10,1,260,365,36,64,854,351,21,51,352,137,77,40,0 },
1010 { 173,7,97,356,43,107,20,387,729,104,426,232,560,595,359,392,414,707,885,81,5,0,66,858,612,49,861,14,22,32,819,230 },
1011 { 15,515,700,753,13,23,51,82,0,33,165,120,196,4,1,2,197,453,260,351,180,12,40,8,386,110,5,326,9,141,217,457 },
1012 { 9,100,120,30,77,795,137,82,202,39,264,827,578,127,0,166,373,318,18,326,141,260,1,450,731,31,33,395,217,291,341,254 },
1013 { 14,2,67,1,24,69,0,28,65,7,46,18,114,108,36,83,38,398,9,16,124,133,103,154,50,55,22,267,29,160,35,547 },
1014 { 14,7,69,24,66,16,2,267,189,67,71,150,140,97,18,60,172,35,6,1,38,149,388,92,83,135,108,74,462,380,29,36 },
1015 { 15,515,700,753,1,13,2,0,4,341,5,3,23,365,11,117,180,10,12,33,134,115,77,197,217,165,6,7,317,102,21,9 },
1016 { 1,22,0,12,5,2,36,28,21,10,86,13,23,49,128,9,95,51,55,96,208,141,48,202,4,137,37,64,105,3,50,7 },
1017 { 605,630,63,123,736,650,65,108,444,368,561,389,19,25,42,619,122,194,183,27,53,33,84,26,297,813,114,73,256,235,249,216 },
1018 { 127,39,9,0,31,371,98,254,1,385,395,44,30,836,187,131,100,116,284,578,299,166,28,21,737,16,276,272,23,49,137,935 },
1019 { 2,61,6,29,45,151,1,655,7,207,32,5,112,425,17,76,833,4,14,64,58,106,119,25,113,128,72,52,70,21,292,790 },
1020 { 2,5,17,14,3,29,23,27,13,401,46,6,51,58,1,453,45,53,34,52,133,19,236,26,181,114,99,366,151,108,218,38 },
1021 { 31,22,170,1,301,44,127,98,36,28,55,105,239,0,338,116,512,299,293,125,86,10,242,395,2,13,9,64,841,23,95,685 },
1022 { 1,21,2,14,5,32,48,50,38,270,46,76,290,72,45,54,17,0,155,221,263,207,37,281,430,3,89,12,181,408,36,67 },
1023 { 17,106,119,378,84,240,62,80,383,136,306,3,56,790,742,5,207,504,64,440,32,128,45,2,123,209,14,4,61,57,297,667 },
1024 { 13,15,1,515,23,2,0,700,4,115,3,51,5,10,753,180,33,341,217,11,165,317,365,197,6,77,40,64,22,9,7,117 },
1025 { 772,335,96,744,1,367,662,686,652,897,303,264,521,31,225,410,141,520,260,116,64,44,321,98,144,88,919,966,340,269,349,284 },
1026 { 1,0,5,28,36,2,12,22,83,67,65,50,24,14,9,96,21,218,18,114,48,281,54,10,7,160,181,103,37,23,133,99 },
1027 { 25,6,145,42,138,81,174,348,525,544,26,74,85,280,287,648,746,91,66,0,29,396,204,64,636,90,122,194,355,104,65,233 },
1028 { 16,24,0,18,28,158,7,35,49,22,68,159,55,1,14,109,105,2,9,71,65,154,124,95,424,344,60,239,118,577,21,10 },
1029 { 352,854,699,230,93,689,137,144,217,160,251,36,669,202,351,120,617,855,752,203,332,82,450,180,141,748,831,30,258,201,1,816 },
1030 { 15,13,515,700,1,2,0,753,23,5,4,3,51,33,10,115,11,317,217,77,180,341,117,165,6,134,197,153,64,9,102,7 },
1031 { 104,20,43,173,66,319,0,77,202,7,198,5,97,580,355,74,2,204,174,52,712,234,426,155,102,192,32,4,500,337,226,904 },
1032 { 13,23,15,51,1,515,0,2,5,700,141,4,753,165,115,12,3,21,457,10,180,269,32,6,197,202,9,7,120,11,77,33 },
1033 { 15,515,700,753,0,1,13,2,23,115,4,317,8,3,5,51,9,341,10,217,22,365,33,457,6,180,77,901,197,120,18,7 },
1034 { 15,515,700,753,1,0,2,3,4,13,5,141,23,16,82,217,457,10,365,180,9,317,51,21,269,898,64,202,11,12,318,341 },
1035 { 2,5,1,14,50,38,29,17,114,46,133,3,45,21,58,171,181,36,218,12,6,52,0,48,137,65,361,23,155,4,285,51 },
1036 { 0,68,9,65,101,124,35,212,16,149,154,100,24,1,114,336,67,589,252,39,71,189,69,562,18,13,30,398,118,88,265,264 },
1037 { 1,2,14,22,0,7,67,65,28,36,24,46,168,5,86,69,38,16,49,12,289,10,194,50,83,114,95,6,18,23,55,158 },
1038 { 13,23,15,51,515,0,700,4,1,753,2,10,115,961,457,12,33,11,3,5,197,9,165,77,102,403,453,40,64,22,37,59 },
1039 { 15,515,700,753,0,1,2,13,23,5,51,901,8,9,180,3,7,82,4,120,12,10,719,341,6,31,141,457,197,22,115,93 },
1040 { 100,252,88,101,0,265,9,724,48,1,21,352,213,676,410,382,321,230,30,329,593,909,39,812,553,217,23,689,520,264,166,419 },
1041 { 2,5,1,58,171,14,46,50,29,52,45,38,186,155,67,54,151,281,334,61,48,96,17,181,103,400,502,227,21,223,12,69 },
1042 { 23,120,13,1,202,141,51,21,165,128,260,15,5,269,137,64,33,180,82,318,93,197,77,326,515,125,110,700,450,2,32,48 },
1043 { 341,197,10,901,13,15,8,638,569,515,479,23,180,873,700,165,143,642,0,961,753,951,1,115,509,499,116,12,498,242,82,206 },
1044 { 15,1,23,13,515,21,120,51,2,141,202,700,5,180,165,0,753,197,12,7,33,260,352,137,269,4,82,128,48,9,110,6 },
1045 { 2,29,50,58,1,6,5,52,14,262,17,46,27,53,151,34,171,74,324,26,38,309,45,113,19,96,287,396,223,67,73,583 },
1046 { 13,23,141,51,4,202,0,115,77,2,33,217,5,317,180,64,10,269,3,9,15,21,1,128,102,137,318,11,352,515,22,31 },
1047 { 1,67,0,24,50,5,14,18,16,69,2,9,103,35,83,12,96,28,54,7,58,223,21,46,281,48,65,181,22,38,36,108 },
1048 { 13,23,141,51,77,64,202,115,33,102,128,4,0,269,10,21,217,32,180,318,9,137,2,11,22,291,7,177,16,31,165,197 },
1049 { 317,115,180,365,873,498,217,341,13,752,482,197,569,352,1,901,36,23,457,468,165,346,546,143,509,134,579,876,868,2,332,21 },
1050 { 184,257,205,229,152,17,57,497,266,432,452,524,5,619,381,32,4,90,2,12,313,128,45,59,245,106,3,471,129,769,339,214 },
1051 { 13,23,1,0,15,2,4,515,51,3,10,33,5,700,115,180,753,77,11,365,341,217,9,6,197,7,102,165,317,40,22,64 },
1052 { 626,70,771,687,379,846,767,761,518,878,82,481,31,786,49,591,178,163,407,44,87,13,845,125,590,371,195,120,98,557,937,351 },
1053 { 264,1,410,909,772,897,686,521,335,478,98,96,691,639,100,44,284,382,31,321,744,88,914,724,662,765,223,9,682,363,0,367 },
1054 { 13,23,1,2,0,15,51,515,5,10,4,33,115,77,180,700,3,141,217,40,6,753,317,197,64,165,7,11,102,9,341,22 },
1055 { 141,77,13,64,269,23,115,21,318,217,5,202,102,33,137,2,15,291,177,51,48,180,32,4,515,352,128,7,0,10,96,11 },
1056 { 13,15,23,515,51,0,700,753,1,2,4,10,33,11,961,453,115,40,457,14,12,3,9,5,165,401,197,77,22,21,64,102 },
1057 { 1,22,0,36,2,31,5,12,13,105,28,9,49,86,141,21,23,95,128,55,44,115,170,10,164,98,180,4,137,239,83,51 },
1058 { 100,101,88,0,252,9,265,30,21,39,759,724,213,329,321,13,419,68,562,382,676,352,694,35,553,410,1,166,909,593,230,23 },
1059 { 539,88,30,190,321,530,840,144,669,435,957,748,778,100,96,418,203,213,1,131,410,228,466,274,36,382,219,863,613,83,822,352 },
1060 { 7,97,92,173,298,107,43,314,232,140,16,356,20,387,729,362,126,359,246,14,230,501,426,441,0,5,560,66,104,779,35,60 },
1061 { 2,14,7,1,58,5,46,16,38,70,75,45,24,155,29,0,21,52,61,163,220,50,69,270,35,48,32,171,18,6,64,54 },
1062 { 447,411,363,664,647,98,621,1,354,271,223,478,18,777,781,936,360,759,167,132,121,48,21,156,9,195,118,293,23,691,13,264 },
1063 { 2,1,14,65,36,67,0,7,46,22,69,5,38,24,28,6,83,29,86,114,168,50,124,208,12,18,108,10,194,484,103,16 },
1064 { 421,386,51,791,730,958,165,801,23,453,697,403,615,13,221,523,24,899,401,326,551,670,576,102,18,33,125,77,566,115,203,197 },
1065 { 104,319,422,945,0,81,20,43,715,32,784,693,879,7,397,74,306,207,52,681,671,2,61,173,6,636,904,95,887,5,18,192 },
1066 { 2,29,1,46,14,52,70,262,6,26,50,67,75,96,309,38,103,112,58,19,5,163,145,83,74,220,223,357,24,69,331,25 },
1067 { 786,929,590,771,687,626,941,178,465,259,70,5,13,21,35,534,107,518,132,49,878,48,146,121,379,279,31,767,147,195,108,125 },
1068 { 5,2,186,45,17,29,48,50,14,61,46,155,400,1,227,171,52,58,38,54,430,209,80,281,3,106,536,311,181,243,21,502 },
1069 { 0,32,64,95,817,494,342,403,207,202,194,389,453,365,312,180,316,5,690,237,848,577,450,61,102,523,475,289,49,241,65,482 },
1070 { 23,13,51,15,202,515,1,0,2,12,115,4,700,5,165,753,77,457,21,141,128,10,3,64,403,32,197,318,9,11,33,117 },
1071 { 119,2,6,76,5,17,45,292,306,240,32,1,19,84,64,61,4,209,710,80,26,0,106,27,214,25,128,129,29,179,3,113 },
1072 { 15,515,700,1,753,0,13,23,180,120,51,2,5,33,165,197,9,450,7,260,115,523,4,12,202,141,82,77,21,102,8,6 },
1073 { 6,138,74,280,222,85,66,226,25,42,87,204,64,337,29,135,95,174,235,26,145,65,19,32,792,294,112,52,256,2,5,22 },
1074 { 39,9,0,101,333,158,49,252,310,254,272,68,16,18,159,286,344,455,30,109,627,327,24,105,419,100,364,22,35,1,329,709 },
1075 { 21,5,32,14,2,1,38,72,76,54,17,3,48,221,270,0,45,46,12,181,37,89,36,50,540,290,430,10,4,741,99,23 },
1076 { 120,137,202,269,141,260,318,450,922,494,77,291,82,15,5,351,128,1,515,326,64,854,700,352,342,21,753,678,349,32,523,90 },
1077 { 16,24,68,35,71,18,149,118,191,167,9,0,212,124,65,246,7,67,140,189,399,101,133,60,1,108,267,114,69,92,695,154 },
1078 { 28,0,9,67,1,22,109,36,55,65,194,114,39,83,49,69,2,35,103,50,158,208,86,420,168,289,505,24,7,185,5,323 },
1079 { 147,325,198,427,142,178,202,798,5,376,20,318,259,43,120,450,77,234,534,904,470,465,878,725,329,14,315,0,260,858,70,61 },
1080 { 28,0,65,9,109,1,55,67,35,22,24,39,289,7,175,14,114,2,158,124,420,194,68,16,336,36,49,69,168,570,154,505 },
1081 { 141,180,13,115,1,23,4,269,2,202,0,317,217,51,15,5,21,352,77,318,3,752,197,10,165,365,137,341,9,515,33,64 },
1082 { 15,515,700,0,753,1,2,13,23,9,51,5,4,901,33,7,8,3,12,93,180,120,197,6,82,341,10,141,22,260,457,115 },
1083 { 6,74,66,1,25,75,324,380,278,26,138,85,135,500,87,42,220,841,97,350,29,19,70,226,38,21,52,606,235,889,2,14 },
1084 { 13,23,51,12,4,15,453,0,457,1,403,165,115,3,11,2,64,5,401,10,515,37,202,33,40,32,99,475,197,700,308,17 },
1085 { 788,180,5,83,693,319,314,4,32,21,17,11,817,3,510,498,33,12,24,104,814,120,64,117,306,804,523,450,288,160,102,43 },
1086 { 15,1,515,13,2,700,23,0,4,753,3,341,5,51,33,11,10,6,77,7,115,102,180,165,141,9,197,217,901,40,12,64 },
1087 { 101,18,9,167,520,16,0,118,60,212,604,364,694,24,55,252,68,917,264,35,1,121,146,363,39,100,806,5,21,166,191,28 },
1088 { 13,23,0,33,51,141,77,4,64,2,115,217,9,102,7,202,21,10,180,3,15,128,5,269,6,32,11,16,165,352,22,317 },
1089 { 66,135,97,74,172,6,278,7,204,324,138,174,29,85,2,87,25,140,92,192,52,38,802,69,448,500,808,620,22,1,280,232 },
1090 { 2,24,69,6,97,7,1,0,14,298,423,66,67,29,150,25,189,267,124,74,607,18,36,81,172,33,83,38,52,273,71,809 },
1091 { 0,9,158,39,68,49,109,16,24,333,35,344,101,22,159,254,272,30,124,65,28,18,793,154,310,252,327,105,627,419,286,55 },
1092 { 15,515,700,10,753,33,77,180,4,341,1,197,13,115,365,23,901,317,5,102,11,217,165,117,141,40,2,3,253,21,134,55 },
1093 { 100,166,382,478,265,264,88,39,98,1,404,274,9,593,724,921,639,438,363,682,411,31,30,812,96,447,821,905,252,0,223,435 },
1094 { 19,283,436,53,297,26,813,432,27,128,42,25,390,503,122,736,73,123,605,63,389,529,630,250,690,65,381,444,6,269,108,216 },
1095 { 33,202,13,128,494,0,51,141,269,1,4,2,102,180,15,137,65,95,6,450,77,40,117,59,457,36,196,817,134,86,49,515 },
1096 { 18,16,60,68,101,167,191,118,35,121,9,212,55,0,126,1,24,647,199,146,520,107,628,621,363,71,21,28,346,92,806,727 },
1097 { 352,230,217,531,160,93,36,669,748,854,689,258,137,871,728,699,752,251,574,202,373,351,228,120,717,260,144,219,268,82,816,1 },
1098 { 15,515,700,753,13,23,0,51,8,1,4,82,165,77,110,33,10,180,5,202,11,22,120,12,9,197,115,93,403,141,40,351 },
1099 { 0,9,101,217,35,88,352,100,39,175,30,68,562,752,13,317,252,115,180,197,64,1,83,141,65,213,165,230,194,36,28,265 },
1100 { 32,64,5,470,288,90,21,147,0,95,356,22,20,519,835,312,819,18,247,182,11,97,13,4,387,49,43,298,316,48,107,7 },
1101 { 16,14,24,1,7,2,35,0,5,50,18,69,46,12,58,75,9,67,70,163,21,54,38,48,223,502,281,37,140,60,28,10 },
1102 { 18,265,9,252,39,195,354,411,1,16,132,101,121,682,167,203,5,363,146,593,35,333,21,271,60,13,100,0,156,327,7,520 },
1103 { 4,13,1,115,141,23,2,180,5,0,51,3,217,202,77,15,33,269,341,318,317,21,165,515,11,10,197,365,9,137,64,352 },
1104 { 7,24,16,14,71,35,18,92,140,189,108,149,68,60,69,150,2,230,97,66,0,458,67,1,65,251,38,314,388,267,36,46 },
1105 { 1,22,31,36,0,2,44,5,141,105,180,170,12,64,13,98,86,55,23,21,28,164,115,127,10,125,128,4,9,239,352,197 },
1106 { 66,7,97,2,192,20,52,43,135,74,560,107,104,0,750,147,414,29,580,173,324,376,226,194,77,174,204,38,356,64,16,470 },
1107 { 0,101,9,68,35,124,24,65,39,16,252,100,154,166,28,364,149,694,30,88,55,346,1,419,71,439,265,289,22,21,175,158 },
1108 { 39,9,100,30,127,0,737,856,31,836,827,254,98,931,166,88,93,1,44,190,131,228,120,395,625,385,863,264,219,373,110,28 },
1109 { 5,17,2,3,21,45,14,155,48,32,38,1,328,181,186,46,23,51,12,61,227,29,106,54,99,133,62,832,13,37,514,543 },
1110 { 131,613,30,224,228,716,274,100,827,406,219,856,39,190,31,88,1,166,9,44,829,863,931,93,0,187,625,924,127,98,137,254 },
1111 { 352,217,64,141,752,269,180,864,437,372,954,115,498,177,77,349,317,318,579,291,947,197,247,0,23,717,237,304,128,457,776,678 },
1112 { 141,217,180,317,352,115,15,341,1,23,13,365,515,752,2,64,0,5,498,700,372,165,51,237,753,77,244,197,137,4,21,253 },
1113 { 5,2,17,14,1,45,3,38,21,29,181,58,46,48,50,133,114,171,61,155,32,6,186,281,361,12,36,54,4,13,52,514 },
1114 { 6,2,119,25,790,4,45,483,655,113,1,29,76,26,32,19,887,17,128,0,292,833,59,61,106,64,77,814,14,151,84,42 },
1115 { 13,23,2,0,51,4,1,115,141,3,5,180,33,217,77,9,202,11,7,15,10,6,317,64,21,197,515,165,102,128,22,269 },
1116 { 13,23,51,202,21,5,1,15,141,165,120,2,115,12,32,0,515,128,318,64,125,700,4,403,197,453,180,457,3,7,10,6 },
1117 { 9,39,31,30,0,127,1,44,100,131,98,187,385,276,88,442,219,908,254,116,49,166,935,28,201,36,141,827,137,299,284,21 },
1118 { 22,49,28,109,9,185,105,95,1,131,159,272,36,67,86,254,39,55,35,0,505,31,83,169,208,327,286,98,168,535,312,708 },
1119 { 5,1,2,21,0,12,48,22,10,14,36,3,32,17,23,54,86,38,4,51,13,37,137,50,65,281,114,45,28,99,58,202 },
1120 { 141,269,352,82,217,351,180,854,372,922,752,1,15,260,317,318,515,202,64,700,120,349,954,753,77,35,67,717,898,137,365,115 },
1121 { 144,203,613,418,326,406,96,669,137,679,1,228,494,822,840,317,36,83,855,160,817,859,856,816,217,831,345,93,876,77,44,251 },
1122 { 15,13,515,23,700,753,51,1,33,0,202,21,2,5,180,141,120,165,217,82,12,117,4,352,269,197,115,32,3,9,134,260 },
1123 { 13,23,115,1,0,51,4,77,2,33,15,141,10,5,341,180,515,3,217,202,9,365,317,64,700,102,11,165,197,22,753,7 },
1124 { 531,943,373,160,728,93,206,260,261,559,964,269,717,535,332,384,365,295,110,533,141,10,180,352,244,137,120,55,959,564,36,253 },
1125 { 1,31,36,170,22,55,44,10,86,64,127,0,2,98,301,164,740,338,237,143,5,125,116,13,242,141,299,180,23,169,105,12 },
1126 { 13,23,141,77,51,4,64,32,33,202,115,269,102,128,21,0,177,180,318,90,40,10,7,5,137,15,217,352,9,291,59,22 },
1127 { 202,120,260,318,77,15,450,269,1,82,33,23,141,13,51,515,351,128,700,5,64,326,137,21,102,110,753,494,93,523,817,165 },
1128 { 523,899,102,33,730,15,23,403,719,117,153,13,515,51,475,4,700,5,453,817,196,753,494,40,202,120,1,2,450,457,17,421 },
1129 { 202,403,494,450,120,817,523,475,318,453,33,402,128,77,13,51,260,576,342,102,15,23,515,4,700,5,82,753,326,210,137,615 },
1130 { 2,29,112,66,7,52,70,151,58,87,135,5,74,226,307,6,14,186,1,45,549,172,644,25,113,287,46,155,334,64,294,97 },
1131 { 1,77,349,291,260,120,652,102,5,39,64,269,9,33,340,342,13,98,888,698,23,296,100,318,51,202,87,137,638,128,50,850 },
1132 { 1,13,15,2,0,4,23,515,5,141,180,3,700,341,115,51,753,269,77,901,197,352,217,33,21,11,365,6,165,202,7,317 },
1133 { 7,14,16,2,46,5,70,58,1,38,24,35,92,163,0,75,21,18,50,54,140,12,87,220,155,69,171,23,60,9,13,307 },
1134 { 2,29,66,226,135,7,87,74,52,278,6,75,222,220,294,70,97,1,145,25,172,262,324,38,69,112,331,92,5,14,140,26 },
1135 { 15,515,700,753,33,77,117,4,1,102,134,40,153,11,13,196,217,21,5,51,23,115,32,3,2,202,141,137,128,291,48,177 },
1136 { 15,217,82,515,351,141,317,1,13,700,260,77,110,120,115,854,23,753,180,51,21,36,137,922,5,64,365,352,291,202,93,341 },
1137 { 31,190,30,373,120,110,863,88,44,127,908,856,260,318,82,98,93,187,836,717,935,39,442,131,141,254,228,219,1,968,77,116 },
1138 { 23,13,308,9,165,115,51,21,401,125,49,39,197,391,159,254,217,743,28,438,773,629,558,386,341,95,32,317,876,679,109,166 },
1139 { 49,5,43,165,7,0,21,104,125,22,173,422,64,13,623,102,20,18,314,95,91,141,23,31,193,51,391,900,779,558,92,232 },
1140 { 1,4,13,2,15,0,23,515,77,3,341,33,5,700,115,51,202,753,141,180,11,10,102,217,6,901,40,7,197,318,317,365 },
1141 { 93,843,295,120,36,160,206,261,10,137,567,110,384,141,943,268,201,332,258,55,1,180,64,116,44,144,699,203,282,31,260,373 },
1142 { 81,7,192,426,43,173,172,104,879,91,5,712,715,526,6,97,568,95,448,66,33,861,560,32,49,20,0,636,232,825,2,22 },
1143 { 475,403,51,453,33,102,13,23,494,202,0,196,15,77,153,18,4,117,515,450,318,22,730,128,700,421,65,753,269,402,134,817 },
1144 { 141,269,260,318,202,120,352,349,82,351,1,5,854,137,64,291,15,922,180,851,32,77,515,372,21,700,7,217,13,947,33,753 },
1145 { 15,515,700,753,1,13,0,2,4,23,3,5,180,115,197,12,51,165,217,10,961,9,6,141,352,21,8,7,33,77,457,120 },
1146 { 39,166,9,30,0,101,274,404,252,333,190,100,158,438,310,88,68,265,656,21,1,530,329,344,49,539,625,254,13,131,48,419 },
1147 { 0,1,28,9,22,12,65,83,67,36,5,2,50,55,96,109,16,13,24,23,21,238,49,18,285,160,128,39,69,114,7,323 },
1148 { 15,515,700,1,0,753,23,2,13,51,5,180,115,6,3,9,197,12,457,120,7,165,901,82,4,21,8,141,31,33,719,341 },
1149 { 9,39,30,0,28,166,22,49,180,1,352,35,317,158,88,141,498,131,115,345,752,128,228,217,100,83,219,930,13,251,365,36 },
1150 { 5,61,45,2,80,29,311,209,6,17,58,1,151,106,454,667,243,70,52,496,287,592,255,738,64,74,483,14,27,32,112,19 },
1151 { 31,125,22,44,299,456,685,242,599,116,170,28,0,1,492,393,506,144,558,10,268,301,239,23,13,36,963,367,55,206,105,95 },
1152 { 187,258,926,574,839,93,228,860,406,219,871,160,137,531,224,116,120,902,669,201,36,131,44,144,843,533,318,384,442,1,434,268 },
1153 { 7,107,75,16,87,9,64,177,24,18,291,77,349,141,60,232,23,0,51,269,132,14,5,21,70,32,678,112,126,121,71,947 },
1154 { 15,515,700,753,1,0,2,13,5,3,23,180,4,115,901,51,6,8,961,9,7,10,12,82,197,22,141,341,33,120,365,457 },
1155 { 13,23,51,1,5,202,2,12,15,21,165,141,0,115,3,4,32,515,197,10,180,318,128,120,64,700,6,7,403,269,457,137 },
1156 { 1,2,0,77,64,3,141,13,33,15,23,10,6,102,5,515,180,4,117,7,700,165,11,217,269,40,753,115,128,17,197,134 },
1157 { 345,531,332,269,260,317,717,752,373,351,180,352,728,82,10,365,160,533,217,143,498,251,244,93,341,901,36,1,141,898,55,864 },
1158 { 16,7,33,189,92,77,388,60,140,35,102,24,14,1,230,21,150,117,733,314,18,915,71,13,108,134,5,64,69,2,98,22 },
1159 { 142,202,234,178,5,786,77,49,70,0,416,450,639,878,1,48,21,929,147,259,315,455,198,120,12,481,163,113,846,329,318,22 },
1160 { 81,715,192,0,173,712,681,104,636,91,74,20,750,370,7,718,95,879,22,43,825,560,422,64,207,49,172,18,397,10,426,319 },
1161 { 13,23,15,51,515,0,700,753,4,1,961,2,10,115,457,11,33,453,3,5,9,40,12,197,165,77,401,475,64,102,22,569 },
1162 { 64,297,5,445,95,61,250,311,80,34,17,312,45,2,86,472,58,14,180,53,22,151,869,738,247,237,29,1,128,165,21,288 },
1163 { 16,24,18,71,7,35,118,92,14,154,60,68,0,149,28,302,124,150,55,175,2,9,97,1,429,20,108,273,22,65,43,126 },
1164 { 195,360,156,771,132,163,626,687,591,371,883,146,121,846,70,586,379,13,293,98,407,48,761,296,354,18,31,1,55,49,21,105 },
1165 { 202,13,77,23,318,33,51,0,4,141,5,21,217,32,291,102,64,128,15,10,9,494,269,137,515,403,1,31,117,700,120,317 },
1166 { 7,192,97,81,172,66,426,173,43,715,712,232,861,879,104,330,568,298,74,893,885,526,387,825,92,140,91,14,636,6,5,448 },
1167 { 2,1,14,6,67,7,65,69,24,36,66,124,108,83,38,29,22,86,0,18,484,5,28,46,12,10,25,302,150,16,650,74 },
1168 { 33,77,13,202,102,4,0,23,128,51,141,64,318,22,403,269,137,10,15,40,494,117,32,59,11,153,1,21,177,196,515,115 },
1169 { 269,141,318,77,349,291,217,202,33,15,372,304,515,22,102,177,351,700,352,120,5,137,10,317,260,753,64,851,854,403,49,21 },
1170 { 6,74,66,85,138,25,87,42,135,26,226,222,280,29,75,500,220,278,792,70,19,2,1,294,204,64,32,145,853,112,52,174 },
1171 { 9,0,105,39,16,18,1,101,272,31,127,98,24,518,333,252,310,28,68,737,846,371,158,916,938,49,30,7,286,35,301,455 },
1172 { 2,1,14,67,24,46,83,108,69,29,38,103,114,36,6,133,18,0,28,7,65,52,236,75,50,398,5,309,135,16,278,160 },
1173 { 22,1,28,105,49,95,0,2,67,55,36,239,168,159,65,35,14,170,320,164,9,7,10,5,114,12,83,64,194,109,24,301 },
1174 { 7,66,172,97,92,140,232,568,298,14,192,314,16,380,135,324,2,330,74,38,357,448,126,69,35,5,107,6,387,60,204,572 },
1175 { 2,29,1,14,5,6,46,133,114,50,52,26,218,108,19,13,366,236,27,45,70,17,58,23,86,51,137,65,112,38,25,12 },
1176 { 6,1,74,25,2,26,29,66,42,19,75,14,388,67,108,70,52,85,103,65,38,138,357,133,114,594,324,516,603,96,309,69 },
1177 { 22,9,28,1,36,49,109,105,86,95,131,31,169,39,0,141,272,159,44,55,98,180,13,30,185,115,83,128,352,137,64,208 },
1178 { 203,822,326,23,77,859,403,494,576,39,473,182,33,1,691,100,18,217,13,817,411,447,363,102,93,966,96,478,291,704,310,120 },
1179 { 15,515,700,753,33,77,117,4,102,134,115,153,13,1,40,217,11,196,341,2,5,3,23,317,365,0,21,291,32,51,12,569 },
1180 { 15,515,700,753,13,0,23,1,8,82,51,165,197,120,180,2,9,33,4,110,5,12,10,260,351,386,141,7,457,475,93,901 },
1181 { 1,23,13,15,51,0,21,2,515,5,141,180,120,165,700,202,197,4,753,12,33,9,7,82,115,93,3,352,260,6,110,48 },
1182 { 15,515,700,753,0,1,2,5,3,4,8,13,180,341,10,23,7,6,9,51,77,197,961,115,165,82,120,31,22,202,457,217 },
1183 { 559,661,922,564,141,533,10,317,373,110,143,269,244,260,332,261,93,642,752,295,351,876,531,843,180,206,728,384,352,1,434,120 },
1184 { 15,515,1,0,700,2,13,23,753,5,51,180,3,165,12,6,197,115,4,9,7,21,719,8,457,82,141,120,33,22,901,10 },
1185 { 198,234,0,325,5,77,202,416,20,147,32,43,639,315,49,61,450,455,142,21,113,230,22,318,725,342,207,13,95,904,494,10 },
1186 { 447,264,363,9,411,676,682,1,156,664,821,478,166,354,812,39,100,905,382,897,98,18,759,404,31,101,724,5,265,223,88,13 },
1187 { 24,14,69,16,35,18,2,7,108,189,71,67,267,149,1,46,68,83,38,140,0,236,251,9,388,60,133,103,65,28,29,50 },
1188 { 16,7,35,20,14,18,109,2,43,120,107,60,1,121,326,907,553,77,13,147,23,82,68,260,0,403,5,24,202,126,265,199 },
1189 { 30,131,187,276,31,44,613,442,39,9,190,228,1,839,116,935,908,219,127,88,244,224,110,137,93,201,98,141,36,567,0,856 },
1190 { 98,223,1,393,812,265,100,421,593,834,697,48,51,410,791,382,21,88,31,284,9,125,96,293,230,23,213,217,656,689,541,5 },
1191 { 98,51,127,219,616,258,105,293,395,421,924,512,31,308,23,201,116,44,301,272,763,276,125,13,453,170,401,295,261,944,115,567 },
1192 { 253,110,951,352,811,206,332,180,141,244,282,10,854,417,642,638,559,752,143,911,260,55,93,533,499,498,661,120,351,959,564,341 },
1193 { 49,9,159,254,272,158,0,131,28,39,627,105,327,286,22,518,688,578,68,347,374,101,224,424,95,35,219,24,16,364,65,344 },
1194 { 105,22,131,272,98,286,327,109,374,239,28,95,320,219,9,224,55,127,187,36,578,169,64,185,538,1,159,10,371,634,49,616 },
1195 { 691,478,340,1,658,914,724,363,744,698,156,772,411,296,682,447,9,284,335,98,264,303,909,21,354,410,225,13,664,686,88,919 },
1196 { 16,24,35,18,71,7,140,108,189,267,92,60,14,230,68,69,9,1,149,46,246,191,388,167,2,0,118,236,133,21,674,5 },
1197 { 9,0,127,31,98,371,395,39,737,49,1,44,385,272,512,28,293,242,836,761,254,299,101,16,187,22,116,158,159,131,18,21 },
1198 { 16,18,68,0,60,35,9,101,252,28,118,24,419,55,7,109,604,71,39,121,22,364,14,158,191,167,925,126,329,21,92,49 },
1199 { 116,268,203,93,206,692,551,31,417,940,499,8,473,44,202,523,959,0,120,137,559,22,450,403,576,10,728,299,13,326,51,1 },
1200 { 225,459,744,1,919,914,691,330,622,21,141,223,5,284,934,335,88,538,340,82,385,839,363,120,478,98,48,30,64,32,686,166 },
1201 { 5,1,2,0,14,36,21,281,12,48,50,67,22,28,54,83,24,218,38,10,181,9,32,18,65,58,45,114,430,17,99,37 },
1202 { 137,450,202,704,120,260,326,318,968,269,851,403,291,77,23,141,182,310,494,373,351,457,82,890,349,110,60,128,817,678,105,96 },
1203 { 15,515,700,753,4,33,13,23,77,5,40,11,102,93,1,21,110,51,82,117,141,2,10,8,32,64,120,31,202,3,217,115 },
1204 { 15,13,1,23,515,0,51,2,700,5,753,21,180,141,165,3,12,115,197,4,7,6,457,9,352,202,33,8,719,120,77,341 },
1205 { 219,127,258,98,276,201,131,395,944,293,116,284,567,31,242,105,137,935,295,44,403,860,51,224,576,456,9,371,578,475,202,512 },
1206 { 16,7,18,35,60,0,14,20,118,28,68,22,2,24,1,92,158,107,5,49,154,126,109,12,43,10,55,6,677,71,21,168 },
1207 { 93,728,531,160,559,373,574,120,295,860,533,269,717,260,926,902,258,318,36,201,261,434,851,137,617,141,187,352,843,384,332,251 },
1208 { 28,0,1,9,22,109,83,39,49,12,36,67,55,5,96,2,128,30,158,69,21,23,160,208,35,13,65,323,50,141,194,238 },
1209 { 23,13,51,1,5,15,141,21,0,2,165,515,202,700,12,197,180,120,32,115,4,753,64,9,7,269,6,3,125,386,48,453 },
1210 { 5,21,13,49,14,20,7,23,43,32,1,0,652,48,713,22,38,2,16,132,955,107,12,279,24,888,197,640,70,303,18,638 },
1211 { 9,0,28,39,1,30,35,101,22,67,83,141,49,175,36,68,55,88,13,251,10,69,23,158,180,115,64,100,217,65,345,166 },
1212 { 260,120,82,269,5,450,351,1,202,141,854,13,77,922,32,33,137,4,23,125,291,21,15,515,165,349,177,700,318,326,180,753 },
1213 { 121,16,18,35,363,101,60,20,107,14,68,259,621,55,604,43,7,252,9,364,126,0,167,191,5,407,132,28,199,419,146,10 },
1214 { 13,23,51,1,15,0,2,141,5,515,12,21,700,115,165,180,4,753,3,197,202,32,9,120,7,8,6,11,37,10,457,269 },
1215 { 201,144,206,443,418,203,435,96,335,459,187,1,88,332,330,321,269,934,30,372,822,521,268,326,44,523,382,141,410,264,494,473 },
1216 { 31,44,276,201,116,131,284,662,567,144,9,489,98,295,268,434,0,30,137,39,93,1,187,22,219,918,110,299,141,36,224,384 },
1217 { 520,478,664,1,264,604,9,167,777,759,411,0,806,724,48,21,101,68,647,936,363,223,118,682,410,18,100,16,252,98,265,13 },
1218 { 23,70,21,87,60,75,120,182,163,379,92,18,7,937,71,121,446,132,24,98,931,126,107,77,795,195,115,44,411,146,51,850 },
1219 { 39,9,0,737,127,31,846,98,1,827,105,310,371,30,254,100,44,18,395,242,272,101,385,916,836,16,265,131,938,93,166,557 },
1220 { 279,20,43,126,107,7,92,16,356,362,60,595,246,359,598,35,0,683,939,653,121,97,125,441,399,392,150,199,48,230,14,649 },
1221 { 206,417,93,959,499,728,8,559,120,473,137,141,10,564,31,260,44,450,203,341,253,244,373,116,143,638,268,180,352,110,318,940 },
1222 { 259,465,147,132,590,687,534,199,581,146,941,427,107,640,279,178,121,5,195,150,522,955,198,35,786,929,798,142,1,21,325,626 },
1223 { 523,15,120,450,202,515,403,51,817,700,13,753,23,457,33,899,128,64,730,102,494,342,115,719,453,196,49,99,318,421,308,5 },
1224 { 141,559,10,244,365,564,661,180,253,143,752,110,55,317,533,341,901,93,373,206,535,160,82,922,260,36,531,964,352,332,261,197 },
1225 { 219,258,98,127,276,964,943,137,843,535,201,935,131,860,261,295,284,567,206,44,116,31,253,492,203,332,160,615,36,93,55,692 },
1226 { 0,319,422,207,945,693,577,887,32,804,95,344,104,904,61,20,5,43,7,725,113,510,306,102,49,263,153,426,33,83,22,9 },
1227 { 1,22,0,5,12,2,36,21,28,86,49,105,9,10,23,13,141,95,31,55,128,37,51,4,83,202,3,64,96,7,32,44 },
1228 { 15,515,13,700,1,0,753,2,23,3,4,5,51,10,115,197,6,33,12,9,165,7,8,77,11,961,180,269,141,22,120,457 },
1229 { 15,1,23,120,77,13,515,51,141,202,700,180,110,137,260,753,326,5,128,102,0,21,2,165,269,33,197,450,318,217,93,115 },
1230 { 15,515,1,700,0,753,13,2,23,180,51,5,120,4,9,115,197,12,7,165,21,33,6,82,3,8,523,901,31,141,457,260 },
1231 { 16,18,24,7,92,35,60,75,9,13,71,14,0,108,50,21,126,121,1,140,23,5,132,146,2,12,128,10,64,141,70,87 },
1232 { 180,341,901,15,515,1,365,700,0,2,197,753,115,4,10,13,752,5,3,8,165,317,141,23,143,873,44,31,569,55,93,6 },
1233 { 9,0,175,35,101,28,39,67,68,1,65,83,30,69,364,336,22,114,55,124,194,158,100,289,252,166,64,345,103,36,50,88 },
1234 { 64,165,180,197,115,247,217,237,21,13,32,316,22,141,352,72,288,304,95,225,76,391,386,16,468,90,49,35,365,640,372,23 },
1235 { 15,515,700,13,753,1,0,2,23,4,5,3,115,51,141,197,12,10,180,961,7,9,21,33,217,6,8,165,457,11,77,341 },
1236 { 132,121,199,146,60,279,493,640,407,598,126,195,534,581,955,590,107,5,150,35,522,49,259,16,18,360,156,0,147,362,21,167 },
1237 { 0,1,28,9,22,5,36,12,65,24,67,96,2,83,18,50,114,55,21,16,7,10,23,14,13,160,137,51,48,218,103,69 },
1238 { 93,120,957,77,30,968,459,110,137,160,613,102,202,352,373,141,31,372,217,330,190,318,269,260,203,44,28,473,228,177,863,704 },
1239 { 15,515,700,0,753,1,13,23,2,51,5,9,120,82,4,7,901,197,10,8,260,180,341,12,33,6,3,523,165,102,115,141 },
1240 { 206,417,8,141,499,44,244,93,31,10,137,253,559,116,728,144,120,564,269,638,203,352,143,260,341,752,268,717,951,180,160,110 },
1241 { 530,254,228,1,96,21,406,39,827,31,669,840,613,829,137,679,166,98,23,51,960,438,131,93,48,224,219,317,310,36,876,190 },
1242 { 15,515,700,753,13,457,0,197,719,1,165,82,23,8,120,730,2,10,12,180,134,5,9,141,260,4,351,51,115,3,341,899 },
1243 { 0,16,68,9,24,28,18,35,252,109,39,419,124,158,154,55,101,71,22,118,60,7,49,65,333,14,1,10,329,364,677,346 },
1244 { 1,15,13,23,515,51,120,0,700,180,2,165,5,753,141,197,21,33,202,102,260,4,9,12,7,326,137,450,115,6,82,110 },
1245 { 535,253,352,564,110,365,82,180,341,10,854,533,55,898,244,901,873,141,752,143,642,559,498,317,36,951,115,964,638,282,661,197 },
1246 { 31,44,125,338,116,64,242,36,1,10,55,22,456,237,180,13,299,164,506,86,23,165,558,143,0,762,492,479,844,546,93,8 },
1247 { 13,23,4,1,202,2,0,51,115,77,141,180,5,15,217,3,33,11,515,317,9,10,102,21,700,341,365,318,269,64,32,128 },
1248 { 9,39,0,166,68,101,28,364,30,158,562,35,175,65,333,154,49,404,706,124,21,252,274,168,190,289,100,570,16,1,310,346 },
1249 { 15,515,700,753,341,13,0,23,1,33,141,4,260,82,77,51,351,180,9,5,115,137,10,217,11,120,102,40,349,269,202,854 }
1250 #else
1251 #include "rgbcx_table4.h"
1252 #endif
1253 };
1254
1255 static uint8_t g_best_total_orderings3[NUM_UNIQUE_TOTAL_ORDERINGS3][32] =
1256 {
1257 { 12,1,3,5,27,2,4,38,8,7,16,18,6,10,41,79,40,23,46,9,20,88,22,37,14,19,24,126,99,119,35,11 },
1258 { 7,64,116,14,94,30,8,42,1,108,47,55,137,10,134,95,96,115,69,32,63,29,90,113,11,148,16,103,19,9,34,25 },
1259 { 12,1,0,5,3,7,4,27,8,6,38,40,41,16,18,46,9,10,20,23,79,62,14,22,88,99,37,126,92,19,120,11 },
1260 { 16,88,27,18,46,48,126,107,79,19,59,38,37,65,23,66,0,2,3,43,12,151,28,25,5,87,72,40,1,20,52,92 },
1261 { 79,48,88,16,27,65,18,38,46,19,37,4,72,33,126,41,52,0,12,92,5,1,2,107,3,77,23,91,43,51,22,74 },
1262 { 1,8,41,122,10,22,2,0,87,24,37,120,38,7,39,4,5,3,9,92,62,59,23,16,104,11,27,79,19,26,25,32 },
1263 { 2,76,99,28,40,86,93,21,138,60,6,0,17,128,145,119,98,144,141,82,147,54,67,75,5,12,27,132,146,1,38,14 },
1264 { 47,7,64,90,1,118,116,85,57,14,30,94,50,45,137,134,8,42,69,139,55,68,58,108,95,29,10,115,0,32,2,11 },
1265 { 49,8,10,30,124,11,32,113,130,58,125,9,100,53,104,115,131,103,24,7,1,39,45,36,139,0,137,22,90,44,114,105 },
1266 { 9,38,72,125,49,41,84,11,13,5,27,0,16,92,8,2,65,105,10,18,48,29,127,131,36,14,1,46,111,79,130,12 },
1267 { 130,8,10,100,104,131,49,32,53,39,30,36,113,24,11,22,124,44,83,58,7,103,1,4,9,125,5,0,91,33,115,74 },
1268 { 114,11,58,8,120,49,9,124,142,111,41,30,10,0,97,130,62,84,38,5,72,125,92,127,100,27,139,113,13,132,32,1 },
1269 { 60,46,28,27,40,20,0,17,18,2,126,16,6,38,86,23,79,54,1,93,5,88,41,14,21,111,7,48,3,84,72,62 },
1270 { 72,92,38,65,84,48,41,79,27,16,29,111,88,5,18,46,1,0,152,14,37,19,77,42,132,7,22,13,119,56,12,2 },
1271 { 7,55,1,95,29,56,64,116,143,8,14,30,47,94,152,90,65,67,10,133,42,72,146,84,16,48,6,0,25,108,77,21 },
1272 { 27,23,20,5,0,79,38,2,3,1,59,46,4,41,33,86,37,87,88,92,7,126,43,8,22,152,151,150,149,148,147,146 },
1273 { 12,0,1,2,7,6,3,5,28,4,8,14,60,40,17,19,21,86,126,93,10,18,9,29,48,99,65,25,84,119,72,41 },
1274 { 60,40,99,2,54,12,0,1,19,28,98,93,6,138,21,5,27,17,151,14,76,46,16,18,38,29,86,144,107,7,25,41 },
1275 { 12,0,1,2,3,5,6,7,4,28,8,60,14,40,16,17,21,10,19,9,86,38,126,41,93,27,29,48,62,84,79,99 },
1276 { 0,1,2,10,5,8,3,25,4,29,32,34,63,7,77,26,16,48,65,56,14,22,129,103,72,24,18,152,140,53,96,42 },
1277 { 46,126,18,54,12,16,1,0,5,2,27,98,20,23,6,3,88,48,28,7,19,8,4,60,151,38,37,21,79,14,65,40 },
1278 { 76,6,141,86,119,2,138,67,28,145,0,93,17,1,40,60,146,99,147,14,21,144,132,7,5,29,55,27,16,75,19,12 },
1279 { 71,5,51,39,22,80,0,43,10,122,8,62,41,24,104,87,35,37,2,91,33,120,36,38,1,131,9,100,130,66,3,4 },
1280 { 126,18,46,27,20,16,88,23,12,79,54,59,48,0,73,1,37,151,5,19,28,38,2,66,60,3,65,98,14,26,6,43 },
1281 { 22,10,8,5,0,71,35,80,104,39,24,51,100,1,62,32,2,130,11,41,7,9,53,43,49,83,122,120,30,44,37,38 },
1282 { 1,34,14,129,53,63,42,26,121,148,7,44,96,10,0,24,100,32,64,116,140,22,5,19,29,103,135,108,8,61,39,83 },
1283 { 1,7,34,63,44,25,135,14,24,108,22,0,83,94,5,129,35,101,47,121,2,19,42,53,6,110,103,8,148,10,16,123 },
1284 { 12,28,16,60,18,1,6,21,14,0,86,19,2,48,93,17,38,29,7,5,65,126,46,72,41,79,84,119,40,56,54,88 },
1285 { 0,2,12,27,5,46,38,40,41,79,88,99,3,23,1,62,20,4,22,37,92,35,18,8,16,24,10,60,7,120,98,54 },
1286 { 1,7,14,56,8,0,84,67,10,2,133,72,42,111,5,30,21,4,9,3,25,94,16,116,47,11,65,18,132,90,55,64 },
1287 { 30,8,124,139,45,11,58,90,113,137,7,115,10,32,1,49,94,85,9,47,108,103,0,97,63,14,50,114,53,106,100,25 },
1288 { 65,38,48,27,16,79,72,18,88,19,46,77,84,92,37,41,0,29,1,14,12,111,2,5,31,36,87,74,105,40,28,51 },
1289 { 10,8,30,113,130,100,53,32,115,103,104,7,1,121,39,49,131,44,24,36,63,137,34,45,22,90,108,83,26,11,94,139 },
1290 { 51,52,43,33,5,74,16,37,71,91,38,3,36,87,48,22,4,0,122,41,39,18,66,27,79,24,65,88,59,23,62,92 },
1291 { 1,7,63,53,108,121,94,44,103,100,14,10,129,47,32,26,24,25,148,42,135,22,0,61,83,8,39,104,5,64,115,34 },
1292 { 1,8,10,7,5,0,80,32,62,2,24,44,53,83,9,41,30,22,100,11,14,25,120,4,26,6,3,16,122,34,19,35 },
1293 { 74,4,36,48,33,91,39,79,22,16,65,5,131,38,24,71,27,52,0,105,51,18,88,104,3,31,10,37,72,19,41,130 },
1294 { 59,43,38,79,23,27,92,51,0,16,46,5,18,88,41,37,66,3,87,20,48,2,122,4,22,12,1,126,19,65,33,24 },
1295 { 12,28,1,27,0,16,2,46,65,60,21,3,5,18,6,19,48,14,4,7,79,88,86,29,22,72,93,40,23,8,17,41 },
1296 { 22,91,39,33,24,71,5,131,36,10,51,0,130,8,104,2,35,125,9,43,52,49,83,80,100,41,122,3,37,38,4,16 },
1297 { 12,0,1,2,5,3,4,8,7,27,18,38,10,6,16,46,9,20,41,23,126,79,22,14,19,99,88,54,37,48,62,35 },
1298 { 12,27,1,2,3,0,46,4,38,16,8,28,7,79,18,5,84,6,88,10,14,21,23,20,40,22,60,19,9,29,72,65 },
1299 { 1,14,7,55,95,29,8,94,30,56,10,108,77,116,152,64,32,48,63,42,143,148,16,25,137,65,11,0,115,9,19,72 },
1300 { 37,79,66,38,16,52,48,59,43,27,87,33,41,4,23,51,3,5,88,18,92,46,73,122,22,71,20,0,65,19,2,120 },
1301 { 24,32,83,22,53,1,8,10,7,30,35,5,103,0,100,101,121,113,34,123,63,2,44,25,71,115,80,14,26,108,51,39 },
1302 { 97,45,111,58,85,139,0,90,47,7,120,106,142,30,50,132,41,62,84,1,119,114,14,56,117,8,38,29,2,64,116,5 },
1303 { 12,28,16,18,1,60,6,14,2,21,0,86,126,19,48,93,7,27,17,29,5,65,54,38,72,79,84,88,119,145,8,111 },
1304 { 118,47,64,116,57,85,7,14,50,1,42,0,45,68,86,69,2,111,134,28,90,55,16,29,56,48,84,144,60,30,112,41 },
1305 { 12,1,2,0,7,6,28,5,3,4,8,14,60,21,18,40,17,86,10,9,16,29,19,93,126,79,38,84,72,27,111,119 },
1306 { 11,8,49,130,10,125,9,124,100,114,131,30,58,104,32,39,24,113,36,105,0,41,22,120,5,53,111,38,142,44,83,35 },
1307 { 50,70,47,118,85,57,106,0,45,7,64,90,81,14,2,134,28,62,86,55,69,1,78,119,68,56,18,67,16,60,29,21 },
1308 { 43,37,33,87,51,41,66,5,122,38,22,59,92,0,23,91,27,16,71,79,18,52,120,4,3,24,46,20,73,39,62,36 },
1309 { 79,48,4,16,27,88,43,33,18,38,65,37,46,3,19,51,52,22,66,87,74,5,41,91,23,59,0,71,122,72,20,92 },
1310 { 32,100,10,8,30,104,24,44,39,113,83,103,1,7,22,53,115,63,135,121,26,35,34,5,0,108,137,90,91,45,2,130 },
1311 { 0,1,2,5,16,12,6,7,14,3,19,18,29,20,4,21,40,8,17,35,23,48,126,22,25,56,26,10,98,27,38,65 },
1312 { 143,67,56,146,1,7,133,55,64,141,134,69,6,47,14,29,84,21,111,147,57,16,95,72,118,132,50,0,2,18,119,42 },
1313 { 1,7,67,14,133,111,8,84,0,21,2,47,64,132,55,10,95,147,119,42,16,5,72,56,4,3,6,29,9,25,18,30 },
1314 { 68,57,69,112,144,86,102,2,134,55,0,70,118,64,75,47,14,28,93,143,67,7,50,149,1,21,29,56,119,95,60,78 },
1315 { 58,97,114,30,124,45,11,139,8,90,0,142,7,10,41,113,84,62,49,111,85,1,9,5,137,120,32,14,2,117,47,38 },
1316 { 23,66,18,79,38,20,43,27,16,88,46,59,126,37,87,12,73,92,3,5,48,0,19,54,2,51,28,1,41,65,122,22 },
1317 { 0,12,2,27,5,40,46,38,1,41,3,79,88,23,99,4,20,62,22,54,92,18,8,37,16,35,10,7,19,120,144,24 },
1318 { 1,14,25,26,0,7,44,34,129,42,24,5,135,22,19,148,6,96,83,2,29,16,63,35,101,64,140,136,116,110,3,10 },
1319 { 12,1,2,27,3,4,38,5,7,8,18,16,46,6,0,40,41,10,79,23,88,9,20,22,14,19,37,92,48,126,28,21 },
1320 { 7,1,10,32,108,103,94,47,8,53,25,14,34,115,100,129,121,130,148,42,64,116,63,26,44,0,24,30,113,4,104,22 },
1321 { 47,134,7,14,55,69,64,95,1,29,85,118,56,116,45,57,102,143,50,90,42,30,16,94,0,8,67,75,133,2,18,48 },
1322 { 12,1,2,0,7,6,28,8,14,5,3,4,40,21,17,18,60,86,16,93,126,10,9,29,99,38,119,25,19,54,27,84 },
1323 { 59,16,27,18,23,88,79,37,46,66,38,20,73,126,3,43,48,87,92,51,41,12,19,5,52,107,65,0,151,122,54,2 },
1324 { 1,21,147,7,119,14,76,132,55,0,86,145,2,6,69,67,16,143,111,138,17,28,29,60,18,93,8,19,40,56,84,5 },
1325 { 144,86,112,2,68,102,69,0,149,93,75,28,57,55,145,60,21,67,99,134,143,40,146,119,82,110,62,6,29,26,78,14 },
1326 { 102,57,55,69,143,75,146,67,56,68,134,2,29,141,0,21,6,14,133,118,64,1,7,95,47,84,111,28,147,82,72,119 },
1327 { 0,70,57,119,50,145,2,86,28,118,69,78,149,47,60,68,67,55,93,81,134,21,14,62,64,7,5,1,132,85,41,16 },
1328 { 51,5,43,71,122,87,41,37,91,39,0,22,33,36,38,24,66,120,62,2,80,16,92,10,59,4,27,23,35,79,8,3 },
1329 { 12,1,2,0,7,6,28,5,8,14,3,21,40,4,60,17,86,18,16,93,10,9,126,119,99,29,19,41,38,27,25,92 },
1330 { 27,18,46,126,23,16,88,79,20,151,59,73,48,38,0,54,12,2,37,1,19,5,28,60,66,41,3,109,86,65,40,6 },
1331 { 48,79,4,33,16,74,65,38,88,27,91,52,18,36,22,19,46,0,37,3,51,5,71,39,72,43,24,41,92,87,2,10 },
1332 { 86,2,144,93,28,112,141,6,102,21,99,60,75,0,68,82,69,146,67,149,55,40,145,76,111,147,56,119,110,143,26,132 },
1333 { 6,138,2,99,86,17,40,93,28,21,145,141,0,60,119,147,128,76,67,54,1,12,5,27,144,14,38,98,146,41,29,19 },
1334 { 1,8,0,10,2,29,7,5,3,56,4,25,14,152,63,32,65,72,96,42,34,108,48,9,26,16,84,103,67,148,22,129 },
1335 { 149,145,0,86,2,28,93,144,62,60,119,101,21,41,5,35,78,99,26,40,12,68,57,67,110,120,69,18,55,76,132,70 },
1336 { 12,28,16,1,48,19,6,60,2,14,18,21,0,27,46,65,86,29,5,7,72,93,40,3,17,84,56,88,126,4,38,8 },
1337 { 1,8,5,10,7,24,2,62,0,41,22,122,120,9,4,3,32,87,11,37,38,83,100,44,25,104,16,26,39,80,14,6 },
1338 { 0,119,62,86,145,149,28,132,93,2,120,67,60,41,35,5,144,21,123,38,111,81,84,56,12,44,24,50,92,55,40,22 },
1339 { 2,93,99,28,40,144,60,0,86,150,76,21,149,98,6,25,1,61,82,26,12,5,54,141,7,18,145,16,27,138,110,38 },
1340 { 24,8,10,22,32,35,100,5,1,53,0,7,71,80,30,123,83,104,51,11,2,39,44,113,9,62,25,103,34,101,43,41 },
1341 { 12,1,2,0,7,6,28,5,40,60,8,16,3,18,14,4,86,21,17,93,41,10,9,99,27,119,38,19,126,22,48,145 },
1342 { 45,47,50,7,85,90,97,1,64,139,116,118,30,58,14,106,70,111,0,57,94,42,137,142,29,120,8,56,18,134,84,41 },
1343 { 12,0,2,5,27,38,1,46,41,40,79,144,3,22,88,23,28,60,99,62,6,24,26,7,4,16,10,35,37,18,14,20 },
1344 { 37,38,59,92,0,5,23,51,79,41,27,22,2,3,87,16,46,4,1,43,20,33,18,88,24,71,8,10,48,19,126,122 },
1345 { 12,28,16,60,1,18,6,21,19,14,48,0,2,86,93,5,46,29,17,27,65,7,3,72,38,126,119,40,84,37,56,4 },
1346 { 0,2,5,1,16,6,27,28,18,38,60,7,14,21,46,40,86,41,19,48,93,8,3,79,22,4,10,37,62,23,24,111 },
1347 { 85,7,90,30,47,139,45,50,94,58,137,1,8,64,14,116,118,115,113,11,124,108,0,10,97,57,32,70,42,106,29,114 },
1348 { 33,36,22,71,51,5,91,39,0,52,43,24,131,74,16,37,38,122,41,3,87,48,4,104,35,80,10,2,105,62,27,18 },
1349 { 12,1,27,2,0,16,3,28,46,18,4,6,5,72,21,79,38,7,14,60,88,8,65,19,48,29,23,40,22,20,86,126 },
1350 { 0,12,2,27,5,38,46,41,1,40,79,3,88,23,22,99,20,37,62,4,18,6,16,35,60,28,24,7,92,8,14,10 },
1351 { 7,47,1,30,137,8,116,94,90,64,14,115,108,118,57,10,148,113,42,85,32,11,63,50,103,45,124,134,55,9,69,34 },
1352 { 55,7,1,29,56,143,64,47,67,133,14,146,95,72,84,8,116,111,6,134,141,21,65,0,69,30,16,45,85,42,50,10 },
1353 { 14,1,42,8,10,29,108,63,55,148,95,32,7,19,25,115,103,34,56,129,77,0,16,152,94,30,113,26,2,5,48,4 },
1354 { 111,120,142,97,58,0,41,45,62,132,114,84,139,30,5,8,38,2,7,85,119,90,117,1,124,11,56,47,28,27,35,72 },
1355 { 1,0,14,2,6,5,16,19,7,29,42,18,3,25,12,35,21,8,26,17,40,4,20,48,109,99,22,96,55,101,10,61 },
1356 { 12,0,1,5,3,2,4,7,27,8,38,6,40,18,16,10,20,46,9,41,23,22,79,14,62,19,37,126,88,11,92,48 },
1357 { 10,8,104,39,24,32,22,83,44,100,30,130,53,91,113,5,11,1,35,33,7,49,0,2,103,71,36,124,9,80,131,34 },
1358 { 1,7,0,14,8,34,5,25,35,26,6,63,10,123,2,16,103,19,44,32,135,121,108,80,62,30,115,94,149,144,53,18 },
1359 { 75,68,146,141,102,67,2,21,6,57,69,143,0,55,82,86,28,144,147,29,93,112,56,119,133,14,76,60,84,134,111,145 },
1360 { 10,32,115,7,8,53,1,108,30,113,94,137,100,63,90,34,130,103,121,47,44,25,104,39,24,26,85,14,49,36,22,131 },
1361 { 39,24,10,22,8,130,91,104,83,49,5,33,100,11,0,35,32,131,71,36,9,44,53,2,80,51,30,1,41,7,43,62 },
1362 { 38,36,65,105,27,72,31,79,41,131,5,48,125,39,0,16,92,46,22,13,18,84,24,37,88,2,33,74,91,71,130,49 },
1363 { 0,106,62,50,45,119,85,81,132,28,2,86,41,47,38,60,35,117,5,29,7,30,145,90,55,70,14,111,18,67,93,56 },
1364 { 0,2,5,1,3,25,19,26,4,34,29,10,22,16,8,7,24,14,48,65,53,18,6,77,44,56,72,61,121,21,136,40 },
1365 { 7,1,94,8,47,115,10,32,113,103,30,108,137,63,14,64,116,148,129,42,90,25,34,118,53,57,11,49,85,9,96,50 },
1366 { 14,0,1,26,19,5,42,2,25,24,29,22,6,44,61,16,7,96,136,3,140,34,35,55,135,18,48,77,83,4,8,10 },
1367 { 1,7,14,0,25,6,34,5,26,16,63,2,19,8,35,101,108,29,94,10,18,42,123,144,129,47,61,21,3,62,149,4 },
1368 { 12,0,2,1,28,5,6,120,7,60,40,16,18,86,27,14,21,93,8,62,41,38,3,17,4,119,99,48,19,126,10,9 },
1369 { 86,144,93,2,28,149,0,60,99,112,110,145,40,21,102,26,75,62,69,1,12,101,119,25,76,67,7,68,55,5,6,14 },
1370 { 8,30,10,32,113,49,115,137,124,103,45,90,7,139,11,1,58,53,130,94,108,100,9,63,85,125,34,47,0,24,44,104 },
1371 { 120,142,111,41,58,114,97,0,11,62,84,124,5,30,8,38,132,127,27,139,92,10,72,45,49,9,28,2,29,56,16,1 },
1372 { 8,113,30,137,7,32,10,90,94,115,1,103,108,63,47,85,49,53,11,45,34,50,14,25,9,124,100,130,139,121,42,26 },
1373 { 64,7,14,47,134,55,1,42,95,69,116,90,94,30,8,29,56,137,45,108,85,10,57,16,102,143,118,19,63,32,11,50 },
1374 { 62,132,0,119,120,41,111,86,35,28,5,84,56,38,2,93,145,60,67,12,92,27,29,72,55,117,21,24,133,149,22,45 },
1375 { 57,68,69,118,134,64,50,47,55,14,7,2,102,144,0,112,70,86,85,1,95,29,116,143,42,75,16,56,28,45,21,48 },
1376 { 0,12,2,1,5,28,6,40,60,27,7,38,16,14,86,18,93,41,62,46,99,35,8,23,3,17,22,21,10,19,79,20 },
1377 { 12,1,2,27,16,3,38,111,4,0,18,5,7,46,40,8,79,6,14,28,88,10,48,41,19,84,21,9,22,23,20,72 },
1378 { 53,103,32,7,1,100,22,63,71,44,10,115,108,24,92,104,26,30,122,94,8,39,83,34,137,135,90,91,121,5,87,47 },
1379 { 87,37,41,0,22,38,2,92,1,24,4,8,3,59,10,5,39,23,71,79,122,27,16,46,33,7,91,20,18,51,9,120 },
1380 { 1,7,8,10,0,5,35,32,53,44,14,30,2,80,25,34,6,62,26,103,16,19,63,9,149,24,121,41,22,11,113,83 },
1381 { 11,58,8,30,124,49,10,113,9,114,139,45,97,32,7,137,90,1,0,130,115,125,100,24,5,94,53,41,14,13,35,38 },
1382 { 125,105,9,36,131,49,8,130,39,11,10,5,22,38,41,104,0,31,13,24,27,16,2,72,65,91,48,32,84,18,100,74 },
1383 { 12,1,0,2,6,3,7,5,4,8,14,28,16,60,18,10,21,17,19,9,40,27,86,93,29,38,54,11,25,48,46,41 },
1384 { 84,41,38,72,92,29,111,5,65,120,79,0,27,56,48,14,132,16,119,22,86,88,46,28,62,12,1,2,93,18,24,127 },
1385 { 99,28,40,60,2,93,138,0,98,17,86,54,76,12,27,1,21,144,128,38,5,14,46,18,25,16,109,6,41,145,7,29 },
1386 { 1,63,10,32,148,14,103,34,42,7,8,108,116,53,64,96,25,121,26,94,140,0,29,19,55,24,100,136,5,4,44,115 },
1387 { 131,100,130,49,10,8,36,104,39,0,48,41,11,38,4,24,27,22,16,44,79,5,33,2,53,9,125,74,91,120,32,83 },
1388 { 36,39,131,74,4,91,22,33,125,104,130,48,10,24,16,5,49,8,100,105,79,0,9,65,71,2,18,83,31,11,19,44 },
1389 { 0,12,2,1,6,5,7,28,40,60,16,14,18,62,86,27,93,8,17,38,21,41,35,99,3,19,10,23,22,4,9,48 },
1390 { 1,7,67,14,21,147,111,55,132,119,0,8,2,76,64,16,47,84,6,18,86,95,145,10,42,29,133,5,56,134,17,72 },
1391 { 69,55,47,134,102,143,7,57,118,95,14,64,29,56,1,50,75,67,146,2,0,133,68,16,21,6,141,85,116,18,72,65 },
1392 { 1,44,7,24,83,63,34,103,22,121,53,32,25,35,0,115,108,5,14,8,10,101,94,30,2,123,110,26,137,47,90,19 },
1393 { 14,1,25,42,34,0,26,96,19,29,140,5,53,10,2,121,3,24,44,22,55,77,129,7,63,16,8,4,6,61,100,48 },
1394 { 30,90,7,8,137,94,85,1,47,113,115,108,45,139,124,11,10,32,50,58,103,14,63,64,9,116,49,42,25,148,0,53 },
1395 { 40,99,2,60,28,17,0,54,93,98,86,138,6,12,21,76,1,5,27,144,128,38,19,46,14,41,145,7,16,67,3,109 },
1396 { 45,58,30,139,90,7,85,137,97,8,124,47,1,11,106,114,50,94,0,113,10,115,14,32,9,64,108,41,49,29,62,116 },
1397 { 14,42,10,1,63,96,32,25,34,8,129,29,0,103,55,19,26,53,77,5,95,2,4,7,3,16,148,56,18,24,121,108 },
1398 { 21,2,75,86,6,76,144,28,119,99,93,147,141,67,102,145,60,132,146,128,0,82,40,138,55,111,143,17,133,112,69,14 },
1399 { 111,120,41,62,84,132,0,5,38,119,56,92,72,142,27,28,29,35,58,80,2,86,65,79,12,14,1,24,145,16,21,48 },
1400 { 146,67,141,69,133,21,6,143,57,55,111,147,56,1,14,132,7,2,134,102,0,119,29,84,76,64,86,72,28,68,47,75 },
1401 { 12,1,0,5,27,3,7,4,38,8,6,41,16,40,46,10,18,79,2,9,23,86,20,22,62,14,37,88,92,19,24,11 },
1402 { 0,12,2,1,27,5,38,28,60,6,40,7,16,46,18,14,41,99,93,62,3,79,86,23,149,8,22,35,88,17,19,10 },
1403 { 141,6,21,67,147,102,146,2,76,119,132,69,55,111,86,75,28,133,143,0,1,145,14,128,56,99,17,60,29,93,84,68 },
1404 { 21,76,1,119,86,145,2,0,14,7,6,138,146,55,17,28,132,93,67,40,60,143,29,147,111,16,69,141,5,56,19,133 },
1405 { 1,8,108,14,7,116,64,42,10,63,94,32,115,103,113,96,30,34,55,47,95,148,29,140,129,25,134,53,69,26,19,11 },
1406 { 12,1,3,5,4,2,0,7,8,38,27,16,18,6,10,20,41,40,79,46,9,23,22,88,92,37,14,24,62,19,48,99 },
1407 { 1,14,7,0,6,25,5,16,19,2,42,26,29,35,61,8,18,129,101,21,3,110,34,148,96,10,17,4,22,40,12,20 },
1408 { 0,2,5,1,3,19,22,26,16,24,29,7,14,6,4,25,18,44,8,48,12,61,20,21,10,35,65,56,23,40,17,107 },
1409 { 1,7,8,29,56,0,10,14,2,42,72,5,4,65,3,30,84,94,67,9,25,133,111,11,32,108,16,63,21,96,26,48 }
1410 };
1411
1412 static inline uint32_t iabs(int32_t i) { return (i < 0) ? static_cast<uint32_t>(-i) : static_cast<uint32_t>(i); }
1413 static inline uint64_t iabs(int64_t i) { return (i < 0) ? static_cast<uint64_t>(-i) : static_cast<uint64_t>(i); }
1414
1415 static inline uint8_t to_5(uint32_t v) { v = v * 31 + 128; return (uint8_t)((v + (v >> 8)) >> 8); }
1416 static inline uint8_t to_6(uint32_t v) { v = v * 63 + 128; return (uint8_t)((v + (v >> 8)) >> 8); }
1417
1418 template <typename S> inline S maximum(S a, S b) { return (a > b) ? a : b; }
1419 template <typename S> inline S maximum(S a, S b, S c) { return maximum(maximum(a, b), c); }
1420 template <typename S> inline S maximum(S a, S b, S c, S d) { return maximum(maximum(maximum(a, b), c), d); }
1421
1422 template <typename S> inline S minimum(S a, S b) { return (a < b) ? a : b; }
1423 template <typename S> inline S minimum(S a, S b, S c) { return minimum(minimum(a, b), c); }
1424 template <typename S> inline S minimum(S a, S b, S c, S d) { return minimum(minimum(minimum(a, b), c), d); }
1425
1426 template<typename T> inline T square(T a) { return a * a; }
1427
1428 static inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; }
1429 static inline uint8_t clamp255(int32_t i) { return (uint8_t)((i & 0xFFFFFF00U) ? (~(i >> 31)) : i); }
1430
1431 template <typename S> inline S clamp(S value, S low, S high) { return (value < low) ? low : ((value > high) ? high : value); }
1432 static inline int32_t clampi(int32_t value, int32_t low, int32_t high) { if (value < low) value = low; else if (value > high) value = high; return value; }
1433
1434 static inline int squarei(int a) { return a * a; }
1435 static inline int absi(int a) { return (a < 0) ? -a : a; }
1436
1437 template<typename F> inline F lerp(F a, F b, F s) { return a + (b - a) * s; }
1438
1439 enum class eNoClamp { cNoClamp };
1440
1441 struct color32
1442 {
1443 union
1444 {
1445 struct
1446 {
1447 uint8_t r;
1448 uint8_t g;
1449 uint8_t b;
1450 uint8_t a;
1451 };
1452
1453 uint8_t c[4];
1454
1455 uint32_t m;
1456 };
1457
1458 color32() { }
1459
1460 color32(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { set(vr, vg, vb, va); }
1461 color32(eNoClamp unused, uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { (void)unused; set_noclamp_rgba(vr, vg, vb, va); }
1462
1463 void set(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { c[0] = static_cast<uint8_t>(vr); c[1] = static_cast<uint8_t>(vg); c[2] = static_cast<uint8_t>(vb); c[3] = static_cast<uint8_t>(va); }
1464
1465 void set_noclamp_rgb(uint32_t vr, uint32_t vg, uint32_t vb) { c[0] = static_cast<uint8_t>(vr); c[1] = static_cast<uint8_t>(vg); c[2] = static_cast<uint8_t>(vb); }
1466 void set_noclamp_rgba(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { set(vr, vg, vb, va); }
1467
1468 void set_clamped(int vr, int vg, int vb, int va) { c[0] = clamp255(vr); c[1] = clamp255(vg); c[2] = clamp255(vb); c[3] = clamp255(va); }
1469
1470 uint8_t operator[] (uint32_t idx) const { assert(idx < 4); return c[idx]; }
1471 uint8_t &operator[] (uint32_t idx) { assert(idx < 4); return c[idx]; }
1472
1473 bool operator== (const color32&rhs) const { return m == rhs.m; }
1474
1475 void set_rgb(const color32& other) { c[0] = static_cast<uint8_t>(other.c[0]); c[1] = static_cast<uint8_t>(other.c[1]); c[2] = static_cast<uint8_t>(other.c[2]); }
1476
1477 static color32 comp_min(const color32& a, const color32& b) { return color32(eNoClamp::cNoClamp, std::min(a[0], b[0]), std::min(a[1], b[1]), std::min(a[2], b[2]), std::min(a[3], b[3])); }
1478 static color32 comp_max(const color32& a, const color32& b) { return color32(eNoClamp::cNoClamp, std::max(a[0], b[0]), std::max(a[1], b[1]), std::max(a[2], b[2]), std::max(a[3], b[3])); }
1479 };
1480
1481 enum dxt_constants
1482 {
1483 cDXT1SelectorBits = 2U, cDXT1SelectorValues = 1U << cDXT1SelectorBits, cDXT1SelectorMask = cDXT1SelectorValues - 1U,
1484 cDXT5SelectorBits = 3U, cDXT5SelectorValues = 1U << cDXT5SelectorBits, cDXT5SelectorMask = cDXT5SelectorValues - 1U,
1485 };
1486
1487 struct bc1_block
1488 {
1489 enum { cTotalEndpointBytes = 2, cTotalSelectorBytes = 4 };
1490
1491 uint8_t m_low_color[cTotalEndpointBytes];
1492 uint8_t m_high_color[cTotalEndpointBytes];
1493 uint8_t m_selectors[cTotalSelectorBytes];
1494
1495 inline uint32_t get_low_color() const { return m_low_color[0] | (m_low_color[1] << 8U); }
1496 inline uint32_t get_high_color() const { return m_high_color[0] | (m_high_color[1] << 8U); }
1497 inline bool is_3color() const { return get_low_color() <= get_high_color(); }
1498 inline void set_low_color(uint16_t c) { m_low_color[0] = static_cast<uint8_t>(c & 0xFF); m_low_color[1] = static_cast<uint8_t>((c >> 8) & 0xFF); }
1499 inline void set_high_color(uint16_t c) { m_high_color[0] = static_cast<uint8_t>(c & 0xFF); m_high_color[1] = static_cast<uint8_t>((c >> 8) & 0xFF); }
1500 inline uint32_t get_selector(uint32_t x, uint32_t y) const { assert((x < 4U) && (y < 4U)); return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask; }
1501 inline void set_selector(uint32_t x, uint32_t y, uint32_t val) { assert((x < 4U) && (y < 4U) && (val < 4U)); m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits))); m_selectors[y] |= (val << (x * cDXT1SelectorBits)); }
1502
1503 static inline uint16_t pack_color(const color32& color, bool scaled, uint32_t bias = 127U)
1504 {
1505 uint32_t r = color.r, g = color.g, b = color.b;
1506 if (scaled)
1507 {
1508 r = (r * 31U + bias) / 255U;
1509 g = (g * 63U + bias) / 255U;
1510 b = (b * 31U + bias) / 255U;
1511 }
1512 return static_cast<uint16_t>(minimum(b, 31U) | (minimum(g, 63U) << 5U) | (minimum(r, 31U) << 11U));
1513 }
1514
1515 static inline uint16_t pack_unscaled_color(uint32_t r, uint32_t g, uint32_t b) { return static_cast<uint16_t>(b | (g << 5U) | (r << 11U)); }
1516
1517 static inline void unpack_color(uint32_t c, uint32_t& r, uint32_t& g, uint32_t& b)
1518 {
1519 r = (c >> 11) & 31;
1520 g = (c >> 5) & 63;
1521 b = c & 31;
1522
1523 r = (r << 3) | (r >> 2);
1524 g = (g << 2) | (g >> 4);
1525 b = (b << 3) | (b >> 2);
1526 }
1527
1528 static inline void unpack_color_unscaled(uint32_t c, uint32_t& r, uint32_t& g, uint32_t& b)
1529 {
1530 r = (c >> 11) & 31;
1531 g = (c >> 5) & 63;
1532 b = c & 31;
1533 }
1534 };
1535
1536 static const uint32_t TOTAL_ORDER_4_0_16 = 15;
1537 static const uint32_t TOTAL_ORDER_4_1_16 = 700;
1538 static const uint32_t TOTAL_ORDER_4_2_16 = 753;
1539 static const uint32_t TOTAL_ORDER_4_3_16 = 515;
1540 static uint16_t g_total_ordering4_hash[4096];
1541 static float g_selector_factors4[NUM_UNIQUE_TOTAL_ORDERINGS4][3];
1542
1543 static const uint32_t TOTAL_ORDER_3_0_16 = 12;
1544 static const uint32_t TOTAL_ORDER_3_1_16 = 15;
1545 static const uint32_t TOTAL_ORDER_3_2_16 = 89;
1546 static uint16_t g_total_ordering3_hash[256];
1547 static float g_selector_factors3[NUM_UNIQUE_TOTAL_ORDERINGS3][3];
1548
1549 struct hist4
1550 {
1551 uint8_t m_hist[4];
1552
1553 hist4()
1554 {
1555 memset(m_hist, 0, sizeof(m_hist));
1556 }
1557
1558 hist4(uint32_t i, uint32_t j, uint32_t k, uint32_t l)
1559 {
1560 m_hist[0] = (uint8_t)i;
1561 m_hist[1] = (uint8_t)j;
1562 m_hist[2] = (uint8_t)k;
1563 m_hist[3] = (uint8_t)l;
1564 }
1565
1566 inline bool operator== (const hist4 &h) const
1567 {
1568 if (m_hist[0] != h.m_hist[0]) return false;
1569 if (m_hist[1] != h.m_hist[1]) return false;
1570 if (m_hist[2] != h.m_hist[2]) return false;
1571 if (m_hist[3] != h.m_hist[3]) return false;
1572 return true;
1573 }
1574
1575 inline bool any_16() const
1576 {
1577 return (m_hist[0] == 16) || (m_hist[1] == 16) || (m_hist[2] == 16) || (m_hist[3] == 16);
1578 }
1579
1580 inline uint32_t lookup_total_ordering_index() const
1581 {
1582 if (m_hist[0] == 16)
1583 return TOTAL_ORDER_4_0_16;
1584 else if (m_hist[1] == 16)
1585 return TOTAL_ORDER_4_1_16;
1586 else if (m_hist[2] == 16)
1587 return TOTAL_ORDER_4_2_16;
1588 else if (m_hist[3] == 16)
1589 return TOTAL_ORDER_4_3_16;
1590
1591 // Must sum to 16, so m_hist[3] isn't needed.
1592 return g_total_ordering4_hash[m_hist[0] | (m_hist[1] << 4) | (m_hist[2] << 8)];
1593 }
1594 };
1595
1596 struct hist3
1597 {
1598 uint8_t m_hist[3];
1599
1600 hist3()
1601 {
1602 memset(m_hist, 0, sizeof(m_hist));
1603 }
1604
1605 hist3(uint32_t i, uint32_t j, uint32_t k)
1606 {
1607 m_hist[0] = (uint8_t)i;
1608 m_hist[1] = (uint8_t)j;
1609 m_hist[2] = (uint8_t)k;
1610 }
1611
1612 inline bool operator== (const hist3 &h) const
1613 {
1614 if (m_hist[0] != h.m_hist[0]) return false;
1615 if (m_hist[1] != h.m_hist[1]) return false;
1616 if (m_hist[2] != h.m_hist[2]) return false;
1617 return true;
1618 }
1619
1620 inline bool any_16() const
1621 {
1622 return (m_hist[0] == 16) || (m_hist[1] == 16) || (m_hist[2] == 16);
1623 }
1624
1625 inline uint32_t lookup_total_ordering_index() const
1626 {
1627 if (m_hist[0] == 16)
1628 return TOTAL_ORDER_3_0_16;
1629 else if (m_hist[1] == 16)
1630 return TOTAL_ORDER_3_1_16;
1631 else if (m_hist[2] == 16)
1632 return TOTAL_ORDER_3_2_16;
1633
1634 // Must sum to 16, so m_hist[2] isn't needed.
1635 return g_total_ordering3_hash[m_hist[0] | (m_hist[1] << 4)];
1636 }
1637 };
1638
1639 struct bc1_match_entry
1640 {
1641 uint8_t m_hi;
1642 uint8_t m_lo;
1643 uint8_t m_e;
1644 };
1645
1646 static bc1_approx_mode g_bc1_approx_mode;
1647 static bc1_match_entry g_bc1_match5_equals_1[256], g_bc1_match6_equals_1[256];
1648 static bc1_match_entry g_bc1_match5_half[256], g_bc1_match6_half[256];
1649
1650 static inline int scale_5_to_8(int v) { return (v << 3) | (v >> 2); }
1651 static inline int scale_6_to_8(int v) { return (v << 2) | (v >> 4); }
1652
1653 // v0, v1 = unexpanded DXT1 endpoint values (5/6-bits)
1654 // c0, c1 = expanded DXT1 endpoint values (8-bits)
1655 static inline int interp_5_6_ideal(int c0, int c1) { assert(c0 < 256 && c1 < 256); return (c0 * 2 + c1) / 3; }
1656 static inline int interp_5_6_ideal_round(int c0, int c1) { assert(c0 < 256 && c1 < 256); return (c0 * 2 + c1 + 1) / 3; }
1657 static inline int interp_half_5_6_ideal(int c0, int c1) { assert(c0 < 256 && c1 < 256); return (c0 + c1) / 2; }
1658
1659 static inline int interp_5_nv(int v0, int v1) { assert(v0 < 32 && v1 < 32); return ((2 * v0 + v1) * 22) / 8; }
1660 static inline int interp_6_nv(int c0, int c1) { assert(c0 < 256 && c1 < 256); const int gdiff = c1 - c0; return (256 * c0 + (gdiff / 4) + 128 + gdiff * 80) / 256; }
1661
1662 static inline int interp_half_5_nv(int v0, int v1) { assert(v0 < 32 && v1 < 32); return ((v0 + v1) * 33) / 8; }
1663 static inline int interp_half_6_nv(int c0, int c1) { assert(c0 < 256 && c1 < 256); const int gdiff = c1 - c0; return (256 * c0 + gdiff/4 + 128 + gdiff * 128) / 256; }
1664
1665 static inline int interp_5_6_amd(int c0, int c1) { assert(c0 < 256 && c1 < 256); return (c0 * 43 + c1 * 21 + 32) >> 6; }
1666 static inline int interp_half_5_6_amd(int c0, int c1) { assert(c0 < 256 && c1 < 256); return (c0 + c1 + 1) >> 1; }
1667
1668 static inline int interp_5(int v0, int v1, int c0, int c1, bc1_approx_mode mode)
1669 {
1670 assert(scale_5_to_8(v0) == c0 && scale_5_to_8(v1) == c1);
1671 switch (mode)
1672 {
1673 case bc1_approx_mode::cBC1NVidia: return interp_5_nv(v0, v1);
1674 case bc1_approx_mode::cBC1AMD: return interp_5_6_amd(c0, c1);
1675 default:
1676 case bc1_approx_mode::cBC1Ideal: return interp_5_6_ideal(c0, c1);
1677 case bc1_approx_mode::cBC1IdealRound4: return interp_5_6_ideal_round(c0, c1);
1678 }
1679 }
1680
1681 static inline int interp_6(int v0, int v1, int c0, int c1, bc1_approx_mode mode)
1682 {
1683 (void)v0; (void)v1;
1684 assert(scale_6_to_8(v0) == c0 && scale_6_to_8(v1) == c1);
1685 switch (mode)
1686 {
1687 case bc1_approx_mode::cBC1NVidia: return interp_6_nv(c0, c1);
1688 case bc1_approx_mode::cBC1AMD: return interp_5_6_amd(c0, c1);
1689 default:
1690 case bc1_approx_mode::cBC1Ideal: return interp_5_6_ideal(c0, c1);
1691 case bc1_approx_mode::cBC1IdealRound4: return interp_5_6_ideal_round(c0, c1);
1692 }
1693 }
1694
1695 static inline int interp_half_5(int v0, int v1, int c0, int c1, bc1_approx_mode mode)
1696 {
1697 assert(scale_5_to_8(v0) == c0 && scale_5_to_8(v1) == c1);
1698 switch (mode)
1699 {
1700 case bc1_approx_mode::cBC1NVidia: return interp_half_5_nv(v0, v1);
1701 case bc1_approx_mode::cBC1AMD: return interp_half_5_6_amd(c0, c1);
1702 case bc1_approx_mode::cBC1Ideal:
1703 case bc1_approx_mode::cBC1IdealRound4:
1704 default:
1705 return interp_half_5_6_ideal(c0, c1);
1706 }
1707 }
1708
1709 static inline int interp_half_6(int v0, int v1, int c0, int c1, bc1_approx_mode mode)
1710 {
1711 (void)v0; (void)v1;
1712 assert(scale_6_to_8(v0) == c0 && scale_6_to_8(v1) == c1);
1713 switch (mode)
1714 {
1715 case bc1_approx_mode::cBC1NVidia: return interp_half_6_nv(c0, c1);
1716 case bc1_approx_mode::cBC1AMD: return interp_half_5_6_amd(c0, c1);
1717 case bc1_approx_mode::cBC1Ideal:
1718 case bc1_approx_mode::cBC1IdealRound4:
1719 default:
1720 return interp_half_5_6_ideal(c0, c1);
1721 }
1722 }
1723
1724 static void prepare_bc1_single_color_table_half(bc1_match_entry* pTable, const uint8_t* pExpand, int size, bc1_approx_mode mode)
1725 {
1726 for (int i = 0; i < 256; i++)
1727 {
1728 int lowest_e = 256;
1729 for (int lo = 0; lo < size; lo++)
1730 {
1731 const int lo_e = pExpand[lo];
1732
1733 for (int hi = 0; hi < size; hi++)
1734 {
1735 const int hi_e = pExpand[hi];
1736
1737 const int v = (size == 32) ? interp_half_5(hi, lo, hi_e, lo_e, mode) : interp_half_6(hi, lo, hi_e, lo_e, mode);
1738
1739 int e = iabs(v - i);
1740
1741 // We only need to factor in 3% error in BC1 ideal mode.
1742 if ((mode == bc1_approx_mode::cBC1Ideal) || (mode == bc1_approx_mode::cBC1IdealRound4))
1743 e += (iabs(hi_e - lo_e) * 3) / 100;
1744
1745 // Favor equal endpoints, for lower error on actual GPU's which approximate the interpolation.
1746 if ((e < lowest_e) || ((e == lowest_e) && (lo == hi)))
1747 {
1748 pTable[i].m_hi = static_cast<uint8_t>(hi);
1749 pTable[i].m_lo = static_cast<uint8_t>(lo);
1750
1751 assert(e <= UINT8_MAX);
1752 pTable[i].m_e = static_cast<uint8_t>(e);
1753
1754 lowest_e = e;
1755 }
1756
1757 } // hi
1758 } // lo
1759 }
1760 }
1761
1762 static void prepare_bc1_single_color_table(bc1_match_entry* pTable, const uint8_t* pExpand, int size, bc1_approx_mode mode)
1763 {
1764 for (int i = 0; i < 256; i++)
1765 {
1766 int lowest_e = 256;
1767 for (int lo = 0; lo < size; lo++)
1768 {
1769 const int lo_e = pExpand[lo];
1770
1771 for (int hi = 0; hi < size; hi++)
1772 {
1773 const int hi_e = pExpand[hi];
1774
1775 const int v = (size == 32) ? interp_5(hi, lo, hi_e, lo_e, mode) : interp_6(hi, lo, hi_e, lo_e, mode);
1776
1777 int e = iabs(v - i);
1778
1779 if ((mode == bc1_approx_mode::cBC1Ideal) || (mode == bc1_approx_mode::cBC1IdealRound4))
1780 e += (iabs(hi_e - lo_e) * 3) / 100;
1781
1782 // Favor equal endpoints, for lower error on actual GPU's which approximate the interpolation.
1783 if ((e < lowest_e) || ((e == lowest_e) && (lo == hi)))
1784 {
1785 pTable[i].m_hi = static_cast<uint8_t>(hi);
1786 pTable[i].m_lo = static_cast<uint8_t>(lo);
1787
1788 assert(e <= UINT8_MAX);
1789 pTable[i].m_e = static_cast<uint8_t>(e);
1790
1791 lowest_e = e;
1792 }
1793
1794 } // hi
1795 } // lo
1796 }
1797 }
1798
1799 // This table is: 9 * (w * w), 9 * ((1.0f - w) * w), 9 * ((1.0f - w) * (1.0f - w))
1800 // where w is [0,1/3,2/3,1]. 9 is the perfect multiplier.
1801 static const uint32_t g_weight_vals4[4] = { 0x000009, 0x010204, 0x040201, 0x090000 };
1802
1803 // multiplier is 4 for 3-color
1804 static const uint32_t g_weight_vals3[3] = { 0x000004, 0x040000, 0x010101 };
1805
1806 static inline void compute_selector_factors4(const hist4 &h, float &iz00, float &iz10, float &iz11)
1807 {
1808 uint32_t weight_accum = 0;
1809 for (uint32_t sel = 0; sel < 4; sel++)
1810 weight_accum += g_weight_vals4[sel] * h.m_hist[sel];
1811
1812 float z00 = (float)((weight_accum >> 16) & 0xFF);
1813 float z10 = (float)((weight_accum >> 8) & 0xFF);
1814 float z11 = (float)(weight_accum & 0xFF);
1815 float z01 = z10;
1816
1817 float det = z00 * z11 - z01 * z10;
1818 if (fabs(det) < 1e-8f)
1819 det = 0.0f;
1820 else
1821 det = (3.0f / 255.0f) / det;
1822
1823 iz00 = z11 * det;
1824 iz10 = -z10 * det;
1825 iz11 = z00 * det;
1826 }
1827
1828 static inline void compute_selector_factors3(const hist3 &h, float &iz00, float &iz10, float &iz11)
1829 {
1830 uint32_t weight_accum = 0;
1831 for (uint32_t sel = 0; sel < 3; sel++)
1832 weight_accum += g_weight_vals3[sel] * h.m_hist[sel];
1833
1834 float z00 = (float)((weight_accum >> 16) & 0xFF);
1835 float z10 = (float)((weight_accum >> 8) & 0xFF);
1836 float z11 = (float)(weight_accum & 0xFF);
1837 float z01 = z10;
1838
1839 float det = z00 * z11 - z01 * z10;
1840 if (fabs(det) < 1e-8f)
1841 det = 0.0f;
1842 else
1843 det = (2.0f / 255.0f) / det;
1844
1845 iz00 = z11 * det;
1846 iz10 = -z10 * det;
1847 iz11 = z00 * det;
1848 }
1849
1850 static bool g_initialized;
1851
1852 void init(bc1_approx_mode mode)
1853 {
1854 g_bc1_approx_mode = mode;
1855
1856 uint8_t bc1_expand5[32];
1857 for (int i = 0; i < 32; i++)
1858 bc1_expand5[i] = static_cast<uint8_t>((i << 3) | (i >> 2));
1859 prepare_bc1_single_color_table(g_bc1_match5_equals_1, bc1_expand5, 32, mode);
1860 prepare_bc1_single_color_table_half(g_bc1_match5_half, bc1_expand5, 32, mode);
1861
1862 uint8_t bc1_expand6[64];
1863 for (int i = 0; i < 64; i++)
1864 bc1_expand6[i] = static_cast<uint8_t>((i << 2) | (i >> 4));
1865 prepare_bc1_single_color_table(g_bc1_match6_equals_1, bc1_expand6, 64, mode);
1866 prepare_bc1_single_color_table_half(g_bc1_match6_half, bc1_expand6, 64, mode);
1867
1868 for (uint32_t i = 0; i < NUM_UNIQUE_TOTAL_ORDERINGS4; i++)
1869 {
1870 hist4 h;
1871 h.m_hist[0] = (uint8_t)g_unique_total_orders4[i][0];
1872 h.m_hist[1] = (uint8_t)g_unique_total_orders4[i][1];
1873 h.m_hist[2] = (uint8_t)g_unique_total_orders4[i][2];
1874 h.m_hist[3] = (uint8_t)g_unique_total_orders4[i][3];
1875
1876 if (!h.any_16())
1877 {
1878 const uint32_t index = h.m_hist[0] | (h.m_hist[1] << 4) | (h.m_hist[2] << 8);
1879 assert(index < 4096);
1880 g_total_ordering4_hash[index] = (uint16_t)i;
1881 }
1882
1883 compute_selector_factors4(h, g_selector_factors4[i][0], g_selector_factors4[i][1], g_selector_factors4[i][2]);
1884 }
1885
1886 for (uint32_t i = 0; i < NUM_UNIQUE_TOTAL_ORDERINGS3; i++)
1887 {
1888 hist3 h;
1889 h.m_hist[0] = (uint8_t)g_unique_total_orders3[i][0];
1890 h.m_hist[1] = (uint8_t)g_unique_total_orders3[i][1];
1891 h.m_hist[2] = (uint8_t)g_unique_total_orders3[i][2];
1892
1893 if (!h.any_16())
1894 {
1895 const uint32_t index = h.m_hist[0] | (h.m_hist[1] << 4);
1896 assert(index < 256);
1897 g_total_ordering3_hash[index] = (uint16_t)i;
1898 }
1899
1900 compute_selector_factors3(h, g_selector_factors3[i][0], g_selector_factors3[i][1], g_selector_factors3[i][2]);
1901 }
1902
1903 g_initialized = true;
1904 }
1905
1906 void encode_bc1_solid_block(void* pDst, uint32_t fr, uint32_t fg, uint32_t fb, bool allow_3color)
1907 {
1908 bc1_block* pDst_block = static_cast<bc1_block*>(pDst);
1909
1910 uint32_t mask = 0xAA;
1911 int max16 = -1, min16 = 0;
1912
1913 if (allow_3color)
1914 {
1915 const uint32_t err4 = g_bc1_match5_equals_1[fr].m_e + g_bc1_match6_equals_1[fg].m_e + g_bc1_match5_equals_1[fb].m_e;
1916 const uint32_t err3 = g_bc1_match5_half[fr].m_e + g_bc1_match6_half[fg].m_e + g_bc1_match5_half[fb].m_e;
1917
1918 if (err3 < err4)
1919 {
1920 max16 = (g_bc1_match5_half[fr].m_hi << 11) | (g_bc1_match6_half[fg].m_hi << 5) | g_bc1_match5_half[fb].m_hi;
1921 min16 = (g_bc1_match5_half[fr].m_lo << 11) | (g_bc1_match6_half[fg].m_lo << 5) | g_bc1_match5_half[fb].m_lo;
1922
1923 if (max16 > min16)
1924 std::swap(max16, min16);
1925 }
1926 }
1927
1928 if (max16 == -1)
1929 {
1930 max16 = (g_bc1_match5_equals_1[fr].m_hi << 11) | (g_bc1_match6_equals_1[fg].m_hi << 5) | g_bc1_match5_equals_1[fb].m_hi;
1931 min16 = (g_bc1_match5_equals_1[fr].m_lo << 11) | (g_bc1_match6_equals_1[fg].m_lo << 5) | g_bc1_match5_equals_1[fb].m_lo;
1932
1933 if (min16 == max16)
1934 {
1935 // Always forbid 3 color blocks
1936 // This is to guarantee that BC3 blocks never use punchthrough alpha (3 color) mode, which isn't supported on some (all?) GPU's.
1937 mask = 0;
1938
1939 // Make l > h
1940 if (min16 > 0)
1941 min16--;
1942 else
1943 {
1944 // l = h = 0
1945 assert(min16 == max16 && max16 == 0);
1946
1947 max16 = 1;
1948 min16 = 0;
1949 mask = 0x55;
1950 }
1951
1952 assert(max16 > min16);
1953 }
1954
1955 if (max16 < min16)
1956 {
1957 std::swap(max16, min16);
1958 mask ^= 0x55;
1959 }
1960 }
1961
1962 pDst_block->set_low_color(static_cast<uint16_t>(max16));
1963 pDst_block->set_high_color(static_cast<uint16_t>(min16));
1964 pDst_block->m_selectors[0] = static_cast<uint8_t>(mask);
1965 pDst_block->m_selectors[1] = static_cast<uint8_t>(mask);
1966 pDst_block->m_selectors[2] = static_cast<uint8_t>(mask);
1967 pDst_block->m_selectors[3] = static_cast<uint8_t>(mask);
1968 }
1969
1970 static const float g_midpoint5[32] = { .015686f, .047059f, .078431f, .111765f, .145098f, .176471f, .207843f, .241176f, .274510f, .305882f, .337255f, .370588f, .403922f, .435294f, .466667f, .5f, .533333f, .564706f, .596078f, .629412f, .662745f, .694118f, .725490f, .758824f, .792157f, .823529f, .854902f, .888235f, .921569f, .952941f, .984314f, 1e+37f };
1971 static const float g_midpoint6[64] = { .007843f, .023529f, .039216f, .054902f, .070588f, .086275f, .101961f, .117647f, .133333f, .149020f, .164706f, .180392f, .196078f, .211765f, .227451f, .245098f, .262745f, .278431f, .294118f, .309804f, .325490f, .341176f, .356863f, .372549f, .388235f, .403922f, .419608f, .435294f, .450980f, .466667f, .482353f, .500000f, .517647f, .533333f, .549020f, .564706f, .580392f, .596078f, .611765f, .627451f, .643137f, .658824f, .674510f, .690196f, .705882f, .721569f, .737255f, .754902f, .772549f, .788235f, .803922f, .819608f, .835294f, .850980f, .866667f, .882353f, .898039f, .913725f, .929412f, .945098f, .960784f, .976471f, .992157f, 1e+37f };
1972
1973 struct vec3F { float c[3]; };
1974
1975 static inline void compute_least_squares_endpoints4_rgb(
1976 vec3F* pXl, vec3F* pXh,
1977 int total_r, int total_g, int total_b,
1978 float iz00, float iz10, float iz11,
1979 uint32_t s, const uint32_t r_sum[17], const uint32_t g_sum[17], const uint32_t b_sum[17])
1980 {
1981 const float iz01 = iz10;
1982
1983 const uint32_t f1 = g_unique_total_orders4[s][0];
1984 const uint32_t f2 = g_unique_total_orders4[s][0] + g_unique_total_orders4[s][1];
1985 const uint32_t f3 = g_unique_total_orders4[s][0] + g_unique_total_orders4[s][1] + g_unique_total_orders4[s][2];
1986 uint32_t uq00_r = (r_sum[f2] - r_sum[f1]) + (r_sum[f3] - r_sum[f2]) * 2 + (r_sum[16] - r_sum[f3]) * 3;
1987 uint32_t uq00_g = (g_sum[f2] - g_sum[f1]) + (g_sum[f3] - g_sum[f2]) * 2 + (g_sum[16] - g_sum[f3]) * 3;
1988 uint32_t uq00_b = (b_sum[f2] - b_sum[f1]) + (b_sum[f3] - b_sum[f2]) * 2 + (b_sum[16] - b_sum[f3]) * 3;
1989
1990 float q10_r = (float)(total_r * 3 - uq00_r);
1991 float q10_g = (float)(total_g * 3 - uq00_g);
1992 float q10_b = (float)(total_b * 3 - uq00_b);
1993
1994 pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r;
1995 pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r;
1996
1997 pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g;
1998 pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g;
1999
2000 pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b;
2001 pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b;
2002 }
2003
2004 static inline bool compute_least_squares_endpoints4_rgb(const color32* pColors, const uint8_t* pSelectors, vec3F* pXl, vec3F* pXh, int total_r, int total_g, int total_b)
2005 {
2006 uint32_t uq00_r = 0, uq00_g = 0, uq00_b = 0;
2007 uint32_t weight_accum = 0;
2008 for (uint32_t i = 0; i < 16; i++)
2009 {
2010 const uint8_t r = pColors[i].c[0], g = pColors[i].c[1], b = pColors[i].c[2];
2011 const uint8_t sel = pSelectors[i];
2012
2013 weight_accum += g_weight_vals4[sel];
2014 uq00_r += sel * r;
2015 uq00_g += sel * g;
2016 uq00_b += sel * b;
2017 }
2018
2019 int q10_r = total_r * 3 - uq00_r;
2020 int q10_g = total_g * 3 - uq00_g;
2021 int q10_b = total_b * 3 - uq00_b;
2022
2023 float z00 = (float)((weight_accum >> 16) & 0xFF);
2024 float z10 = (float)((weight_accum >> 8) & 0xFF);
2025 float z11 = (float)(weight_accum & 0xFF);
2026 float z01 = z10;
2027
2028 float det = z00 * z11 - z01 * z10;
2029 if (fabs(det) < 1e-8f)
2030 return false;
2031
2032 det = (3.0f / 255.0f) / det;
2033
2034 float iz00, iz01, iz10, iz11;
2035 iz00 = z11 * det;
2036 iz01 = -z01 * det;
2037 iz10 = -z10 * det;
2038 iz11 = z00 * det;
2039
2040 pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r;
2041 pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r;
2042
2043 pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g;
2044 pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g;
2045
2046 pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b;
2047 pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b;
2048
2049 return true;
2050 }
2051
2052 static inline void compute_least_squares_endpoints3_rgb(
2053 vec3F* pXl, vec3F* pXh,
2054 int total_r, int total_g, int total_b,
2055 float iz00, float iz10, float iz11,
2056 uint32_t s, const uint32_t r_sum[17], const uint32_t g_sum[17], const uint32_t b_sum[17])
2057 {
2058 const float iz01 = iz10;
2059
2060 // Compensates for BC1 3-color ordering, which is selector 0, 2, 1
2061 const uint32_t f1 = g_unique_total_orders3[s][0];
2062 const uint32_t f2 = g_unique_total_orders3[s][0] + g_unique_total_orders3[s][2];
2063 uint32_t uq00_r = (r_sum[16] - r_sum[f2]) * 2 + (r_sum[f2] - r_sum[f1]);
2064 uint32_t uq00_g = (g_sum[16] - g_sum[f2]) * 2 + (g_sum[f2] - g_sum[f1]);
2065 uint32_t uq00_b = (b_sum[16] - b_sum[f2]) * 2 + (b_sum[f2] - b_sum[f1]);
2066
2067 float q10_r = (float)(total_r * 2 - uq00_r);
2068 float q10_g = (float)(total_g * 2 - uq00_g);
2069 float q10_b = (float)(total_b * 2 - uq00_b);
2070
2071 pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r;
2072 pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r;
2073
2074 pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g;
2075 pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g;
2076
2077 pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b;
2078 pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b;
2079 }
2080
2081 static inline bool compute_least_squares_endpoints3_rgb(bool use_black, const color32* pColors, const uint8_t* pSelectors, vec3F* pXl, vec3F* pXh)
2082 {
2083 int uq00_r = 0, uq00_g = 0, uq00_b = 0;
2084 uint32_t weight_accum = 0;
2085 int total_r = 0, total_g = 0, total_b = 0;
2086 for (uint32_t i = 0; i < 16; i++)
2087 {
2088 const uint8_t r = pColors[i].c[0], g = pColors[i].c[1], b = pColors[i].c[2];
2089 if (use_black)
2090 {
2091 if ((r | g | b) < 4)
2092 continue;
2093 }
2094
2095 const uint8_t sel = pSelectors[i];
2096 assert(sel <= 3);
2097 if (sel == 3)
2098 continue;
2099
2100 weight_accum += g_weight_vals3[sel];
2101
2102 static const uint8_t s_tran[3] = { 0, 2, 1 };
2103 const uint8_t tsel = s_tran[sel];
2104 uq00_r += tsel * r;
2105 uq00_g += tsel * g;
2106 uq00_b += tsel * b;
2107
2108 total_r += r;
2109 total_g += g;
2110 total_b += b;
2111 }
2112
2113 int q10_r = total_r * 2 - uq00_r;
2114 int q10_g = total_g * 2 - uq00_g;
2115 int q10_b = total_b * 2 - uq00_b;
2116
2117 float z00 = (float)((weight_accum >> 16) & 0xFF);
2118 float z10 = (float)((weight_accum >> 8) & 0xFF);
2119 float z11 = (float)(weight_accum & 0xFF);
2120 float z01 = z10;
2121
2122 float det = z00 * z11 - z01 * z10;
2123 if (fabs(det) < 1e-8f)
2124 return false;
2125
2126 det = (2.0f / 255.0f) / det;
2127
2128 float iz00, iz01, iz10, iz11;
2129 iz00 = z11 * det;
2130 iz01 = -z01 * det;
2131 iz10 = -z10 * det;
2132 iz11 = z00 * det;
2133
2134 pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r;
2135 pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r;
2136
2137 pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g;
2138 pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g;
2139
2140 pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b;
2141 pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b;
2142
2143 return true;
2144 }
2145
2146 static inline void bc1_get_block_colors4(uint32_t block_r[4], uint32_t block_g[4], uint32_t block_b[4], uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb)
2147 {
2148 block_r[0] = (lr << 3) | (lr >> 2); block_g[0] = (lg << 2) | (lg >> 4); block_b[0] = (lb << 3) | (lb >> 2);
2149 block_r[3] = (hr << 3) | (hr >> 2); block_g[3] = (hg << 2) | (hg >> 4); block_b[3] = (hb << 3) | (hb >> 2);
2150
2151 if (g_bc1_approx_mode == bc1_approx_mode::cBC1Ideal)
2152 {
2153 block_r[1] = (block_r[0] * 2 + block_r[3]) / 3; block_g[1] = (block_g[0] * 2 + block_g[3]) / 3; block_b[1] = (block_b[0] * 2 + block_b[3]) / 3;
2154 block_r[2] = (block_r[3] * 2 + block_r[0]) / 3; block_g[2] = (block_g[3] * 2 + block_g[0]) / 3; block_b[2] = (block_b[3] * 2 + block_b[0]) / 3;
2155 }
2156 else if (g_bc1_approx_mode == bc1_approx_mode::cBC1IdealRound4)
2157 {
2158 block_r[1] = (block_r[0] * 2 + block_r[3] + 1) / 3; block_g[1] = (block_g[0] * 2 + block_g[3] + 1) / 3; block_b[1] = (block_b[0] * 2 + block_b[3] + 1) / 3;
2159 block_r[2] = (block_r[3] * 2 + block_r[0] + 1) / 3; block_g[2] = (block_g[3] * 2 + block_g[0] + 1) / 3; block_b[2] = (block_b[3] * 2 + block_b[0] + 1) / 3;
2160 }
2161 else if (g_bc1_approx_mode == bc1_approx_mode::cBC1AMD)
2162 {
2163 block_r[1] = interp_5_6_amd(block_r[0], block_r[3]); block_g[1] = interp_5_6_amd(block_g[0], block_g[3]); block_b[1] = interp_5_6_amd(block_b[0], block_b[3]);
2164 block_r[2] = interp_5_6_amd(block_r[3], block_r[0]); block_g[2] = interp_5_6_amd(block_g[3], block_g[0]); block_b[2] = interp_5_6_amd(block_b[3], block_b[0]);
2165 }
2166 else
2167 {
2168 block_r[1] = interp_5_nv(lr, hr); block_g[1] = interp_6_nv(block_g[0], block_g[3]); block_b[1] = interp_5_nv(lb, hb);
2169 block_r[2] = interp_5_nv(hr, lr); block_g[2] = interp_6_nv(block_g[3], block_g[0]); block_b[2] = interp_5_nv(hb, lb);
2170 }
2171 }
2172
2173 static inline void bc1_get_block_colors3(uint32_t block_r[3], uint32_t block_g[3], uint32_t block_b[3], uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb)
2174 {
2175 block_r[0] = (lr << 3) | (lr >> 2); block_g[0] = (lg << 2) | (lg >> 4); block_b[0] = (lb << 3) | (lb >> 2);
2176 block_r[1] = (hr << 3) | (hr >> 2); block_g[1] = (hg << 2) | (hg >> 4); block_b[1] = (hb << 3) | (hb >> 2);
2177
2178 if ((g_bc1_approx_mode == bc1_approx_mode::cBC1Ideal) || (g_bc1_approx_mode == bc1_approx_mode::cBC1IdealRound4))
2179 {
2180 block_r[2] = (block_r[0] + block_r[1]) / 2; block_g[2] = (block_g[0] + block_g[1]) / 2; block_b[2] = (block_b[0] + block_b[1]) / 2;
2181 }
2182 else if (g_bc1_approx_mode == bc1_approx_mode::cBC1AMD)
2183 {
2184 block_r[2] = interp_half_5_6_amd(block_r[0], block_r[1]); block_g[2] = interp_half_5_6_amd(block_g[0], block_g[1]); block_b[2] = interp_half_5_6_amd(block_b[0], block_b[1]);
2185 }
2186 else
2187 {
2188 block_r[2] = interp_half_5_nv(lr, hr); block_g[2] = interp_half_6_nv(block_g[0], block_g[1]); block_b[2] = interp_half_5_nv(lb, hb);
2189 }
2190 }
2191
2192 static inline void bc1_find_sels4_noerr(const color32* pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16])
2193 {
2194 uint32_t block_r[4], block_g[4], block_b[4];
2195 bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb);
2196
2197 int ar = block_r[3] - block_r[0], ag = block_g[3] - block_g[0], ab = block_b[3] - block_b[0];
2198
2199 int dots[4];
2200 for (uint32_t i = 0; i < 4; i++)
2201 dots[i] = (int)block_r[i] * ar + (int)block_g[i] * ag + (int)block_b[i] * ab;
2202
2203 int t0 = dots[0] + dots[1], t1 = dots[1] + dots[2], t2 = dots[2] + dots[3];
2204
2205 ar *= 2; ag *= 2; ab *= 2;
2206
2207 static const uint8_t s_sels[4] = { 3, 2, 1, 0 };
2208
2209 for (uint32_t i = 0; i < 16; i += 4)
2210 {
2211 const int d0 = pSrc_pixels[i+0].r * ar + pSrc_pixels[i+0].g * ag + pSrc_pixels[i+0].b * ab;
2212 const int d1 = pSrc_pixels[i+1].r * ar + pSrc_pixels[i+1].g * ag + pSrc_pixels[i+1].b * ab;
2213 const int d2 = pSrc_pixels[i+2].r * ar + pSrc_pixels[i+2].g * ag + pSrc_pixels[i+2].b * ab;
2214 const int d3 = pSrc_pixels[i+3].r * ar + pSrc_pixels[i+3].g * ag + pSrc_pixels[i+3].b * ab;
2215
2216 sels[i+0] = s_sels[(d0 <= t0) + (d0 < t1) + (d0 < t2)];
2217 sels[i+1] = s_sels[(d1 <= t0) + (d1 < t1) + (d1 < t2)];
2218 sels[i+2] = s_sels[(d2 <= t0) + (d2 < t1) + (d2 < t2)];
2219 sels[i+3] = s_sels[(d3 <= t0) + (d3 < t1) + (d3 < t2)];
2220 }
2221 }
2222
2223 static inline uint32_t bc1_find_sels4_fasterr(const color32* pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16], uint32_t cur_err)
2224 {
2225 uint32_t block_r[4], block_g[4], block_b[4];
2226 bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb);
2227
2228 int ar = block_r[3] - block_r[0], ag = block_g[3] - block_g[0], ab = block_b[3] - block_b[0];
2229
2230 int dots[4];
2231 for (uint32_t i = 0; i < 4; i++)
2232 dots[i] = (int)block_r[i] * ar + (int)block_g[i] * ag + (int)block_b[i] * ab;
2233
2234 int t0 = dots[0] + dots[1], t1 = dots[1] + dots[2], t2 = dots[2] + dots[3];
2235
2236 ar *= 2; ag *= 2; ab *= 2;
2237
2238 static const uint8_t s_sels[4] = { 3, 2, 1, 0 };
2239
2240 uint32_t total_err = 0;
2241
2242 for (uint32_t i = 0; i < 16; i += 4)
2243 {
2244 const int d0 = pSrc_pixels[i+0].r * ar + pSrc_pixels[i+0].g * ag + pSrc_pixels[i+0].b * ab;
2245 const int d1 = pSrc_pixels[i+1].r * ar + pSrc_pixels[i+1].g * ag + pSrc_pixels[i+1].b * ab;
2246 const int d2 = pSrc_pixels[i+2].r * ar + pSrc_pixels[i+2].g * ag + pSrc_pixels[i+2].b * ab;
2247 const int d3 = pSrc_pixels[i+3].r * ar + pSrc_pixels[i+3].g * ag + pSrc_pixels[i+3].b * ab;
2248
2249 uint8_t sel0 = s_sels[(d0 <= t0) + (d0 < t1) + (d0 < t2)];
2250 uint8_t sel1 = s_sels[(d1 <= t0) + (d1 < t1) + (d1 < t2)];
2251 uint8_t sel2 = s_sels[(d2 <= t0) + (d2 < t1) + (d2 < t2)];
2252 uint8_t sel3 = s_sels[(d3 <= t0) + (d3 < t1) + (d3 < t2)];
2253
2254 sels[i+0] = sel0;
2255 sels[i+1] = sel1;
2256 sels[i+2] = sel2;
2257 sels[i+3] = sel3;
2258
2259 total_err += squarei(pSrc_pixels[i+0].r - block_r[sel0]) + squarei(pSrc_pixels[i+0].g - block_g[sel0]) + squarei(pSrc_pixels[i+0].b - block_b[sel0]);
2260 total_err += squarei(pSrc_pixels[i+1].r - block_r[sel1]) + squarei(pSrc_pixels[i+1].g - block_g[sel1]) + squarei(pSrc_pixels[i+1].b - block_b[sel1]);
2261 total_err += squarei(pSrc_pixels[i+2].r - block_r[sel2]) + squarei(pSrc_pixels[i+2].g - block_g[sel2]) + squarei(pSrc_pixels[i+2].b - block_b[sel2]);
2262 total_err += squarei(pSrc_pixels[i+3].r - block_r[sel3]) + squarei(pSrc_pixels[i+3].g - block_g[sel3]) + squarei(pSrc_pixels[i+3].b - block_b[sel3]);
2263
2264 if (total_err >= cur_err)
2265 break;
2266 }
2267
2268 return total_err;
2269 }
2270
2271 static inline uint32_t bc1_find_sels4_check2_err(const color32* pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16], uint32_t cur_err)
2272 {
2273 uint32_t block_r[4], block_g[4], block_b[4];
2274 bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb);
2275
2276 int dr = block_r[3] - block_r[0], dg = block_g[3] - block_g[0], db = block_b[3] - block_b[0];
2277
2278 const float f = 4.0f / (float)(squarei(dr) + squarei(dg) + squarei(db) + .00000125f);
2279
2280 uint32_t total_err = 0;
2281
2282 for (uint32_t i = 0; i < 16; i++)
2283 {
2284 const int r = pSrc_pixels[i].r;
2285 const int g = pSrc_pixels[i].g;
2286 const int b = pSrc_pixels[i].b;
2287
2288 int sel = (int)((float)((r - (int)block_r[0]) * dr + (g - (int)block_g[0]) * dg + (b - (int)block_b[0]) * db) * f + .5f);
2289 sel = clampi(sel, 1, 3);
2290
2291 uint32_t err0 = squarei((int)block_r[sel - 1] - (int)r) + squarei((int)block_g[sel - 1] - (int)g) + squarei((int)block_b[sel - 1] - (int)b);
2292 uint32_t err1 = squarei((int)block_r[sel] - (int)r) + squarei((int)block_g[sel] - (int)g) + squarei((int)block_b[sel] - (int)b);
2293
2294 int best_sel = sel;
2295 uint32_t best_err = err1;
2296 if (err0 == err1)
2297 {
2298 // Prefer non-interpolation
2299 if ((best_sel - 1) == 0)
2300 best_sel = 0;
2301 }
2302 else if (err0 < best_err)
2303 {
2304 best_sel = sel - 1;
2305 best_err = err0;
2306 }
2307
2308 total_err += best_err;
2309
2310 if (total_err >= cur_err)
2311 break;
2312
2313 sels[i] = (uint8_t)best_sel;
2314 }
2315 return total_err;
2316 }
2317
2318 static inline uint32_t bc1_find_sels4_fullerr(const color32* pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16], uint32_t cur_err)
2319 {
2320 uint32_t block_r[4], block_g[4], block_b[4];
2321 bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb);
2322
2323 uint32_t total_err = 0;
2324
2325 for (uint32_t i = 0; i < 16; i++)
2326 {
2327 const int r = pSrc_pixels[i].r;
2328 const int g = pSrc_pixels[i].g;
2329 const int b = pSrc_pixels[i].b;
2330
2331 uint32_t best_err = squarei((int)block_r[0] - (int)r) + squarei((int)block_g[0] - (int)g) + squarei((int)block_b[0] - (int)b);
2332 uint8_t best_sel = 0;
2333
2334 for (uint32_t j = 1; (j < 4) && best_err; j++)
2335 {
2336 uint32_t err = squarei((int)block_r[j] - (int)r) + squarei((int)block_g[j] - (int)g) + squarei((int)block_b[j] - (int)b);
2337 if ( (err < best_err) || ((err == best_err) && (j == 3)) )
2338 {
2339 best_err = err;
2340 best_sel = (uint8_t)j;
2341 }
2342 }
2343
2344 total_err += best_err;
2345
2346 if (total_err >= cur_err)
2347 break;
2348
2349 sels[i] = (uint8_t)best_sel;
2350 }
2351 return total_err;
2352 }
2353
2354 static inline uint32_t bc1_find_sels4(uint32_t flags, const color32* pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16], uint32_t cur_err)
2355 {
2356 uint32_t err;
2357
2358 if (flags & cEncodeBC1UseFasterMSEEval)
2359 err = bc1_find_sels4_fasterr(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels, cur_err);
2360 else if (flags & cEncodeBC1UseFullMSEEval)
2361 err = bc1_find_sels4_fullerr(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels, cur_err);
2362 else
2363 err = bc1_find_sels4_check2_err(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels, cur_err);
2364
2365 return err;
2366 }
2367
2368 static inline uint32_t bc1_find_sels3_fullerr(bool use_black, const color32* pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16], uint32_t cur_err)
2369 {
2370 uint32_t block_r[3], block_g[3], block_b[3];
2371 bc1_get_block_colors3(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb);
2372
2373 uint32_t total_err = 0;
2374
2375 for (uint32_t i = 0; i < 16; i++)
2376 {
2377 const int r = pSrc_pixels[i].r;
2378 const int g = pSrc_pixels[i].g;
2379 const int b = pSrc_pixels[i].b;
2380
2381 uint32_t best_err = squarei((int)block_r[0] - (int)r) + squarei((int)block_g[0] - (int)g) + squarei((int)block_b[0] - (int)b);
2382 uint32_t best_sel = 0;
2383
2384 uint32_t err1 = squarei((int)block_r[1] - (int)r) + squarei((int)block_g[1] - (int)g) + squarei((int)block_b[1] - (int)b);
2385 if (err1 < best_err)
2386 {
2387 best_err = err1;
2388 best_sel = 1;
2389 }
2390
2391 uint32_t err2 = squarei((int)block_r[2] - (int)r) + squarei((int)block_g[2] - (int)g) + squarei((int)block_b[2] - (int)b);
2392 if (err2 < best_err)
2393 {
2394 best_err = err2;
2395 best_sel = 2;
2396 }
2397
2398 if (use_black)
2399 {
2400 uint32_t err3 = squarei(r) + squarei(g) + squarei(b);
2401 if (err3 < best_err)
2402 {
2403 best_err = err3;
2404 best_sel = 3;
2405 }
2406 }
2407
2408 total_err += best_err;
2409 if (total_err >= cur_err)
2410 return total_err;
2411
2412 sels[i] = (uint8_t)best_sel;
2413 }
2414
2415 return total_err;
2416 }
2417
2418 static inline void precise_round_565(const vec3F &xl, const vec3F &xh,
2419 int &trial_lr, int &trial_lg, int &trial_lb,
2420 int &trial_hr, int &trial_hg, int &trial_hb)
2421 {
2422 trial_lr = (int)(xl.c[0] * 31.0f);
2423 trial_lg = (int)(xl.c[1] * 63.0f);
2424 trial_lb = (int)(xl.c[2] * 31.0f);
2425
2426 trial_hr = (int)(xh.c[0] * 31.0f);
2427 trial_hg = (int)(xh.c[1] * 63.0f);
2428 trial_hb = (int)(xh.c[2] * 31.0f);
2429
2430 if ((uint32_t)(trial_lr | trial_lb | trial_hr | trial_hb) > 31U)
2431 {
2432 trial_lr = ((uint32_t)trial_lr > 31U) ? (~trial_lr >> 31) & 31 : trial_lr;
2433 trial_hr = ((uint32_t)trial_hr > 31U) ? (~trial_hr >> 31) & 31 : trial_hr;
2434
2435 trial_lb = ((uint32_t)trial_lb > 31U) ? (~trial_lb >> 31) & 31 : trial_lb;
2436 trial_hb = ((uint32_t)trial_hb > 31U) ? (~trial_hb >> 31) & 31 : trial_hb;
2437 }
2438
2439 if ((uint32_t)(trial_lg | trial_hg) > 63U)
2440 {
2441 trial_lg = ((uint32_t)trial_lg > 63U) ? (~trial_lg >> 31) & 63 : trial_lg;
2442 trial_hg = ((uint32_t)trial_hg > 63U) ? (~trial_hg >> 31) & 63 : trial_hg;
2443 }
2444
2445 trial_lr = (trial_lr + (xl.c[0] > g_midpoint5[trial_lr])) & 31;
2446 trial_lg = (trial_lg + (xl.c[1] > g_midpoint6[trial_lg])) & 63;
2447 trial_lb = (trial_lb + (xl.c[2] > g_midpoint5[trial_lb])) & 31;
2448
2449 trial_hr = (trial_hr + (xh.c[0] > g_midpoint5[trial_hr])) & 31;
2450 trial_hg = (trial_hg + (xh.c[1] > g_midpoint6[trial_hg])) & 63;
2451 trial_hb = (trial_hb + (xh.c[2] > g_midpoint5[trial_hb])) & 31;
2452 }
2453
2454 static inline void precise_round_565_noscale(vec3F xl, vec3F xh,
2455 int &trial_lr, int &trial_lg, int &trial_lb,
2456 int &trial_hr, int &trial_hg, int &trial_hb)
2457 {
2458 xl.c[0] *= 1.0f/255.0f;
2459 xl.c[1] *= 1.0f/255.0f;
2460 xl.c[2] *= 1.0f/255.0f;
2461
2462 xh.c[0] *= 1.0f/255.0f;
2463 xh.c[1] *= 1.0f/255.0f;
2464 xh.c[2] *= 1.0f/255.0f;
2465
2466 precise_round_565(xl, xh, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb);
2467 }
2468
2469 static inline void bc1_encode4(bc1_block *pDst_block, int lr, int lg, int lb, int hr, int hg, int hb, const uint8_t sels[16])
2470 {
2471 uint32_t lc16 = bc1_block::pack_unscaled_color(lr, lg, lb);
2472 uint32_t hc16 = bc1_block::pack_unscaled_color(hr, hg, hb);
2473
2474 // Always forbid 3 color blocks
2475 if (lc16 == hc16)
2476 {
2477 uint8_t mask = 0;
2478
2479 // Make l > h
2480 if (hc16 > 0)
2481 hc16--;
2482 else
2483 {
2484 // lc16 = hc16 = 0
2485 assert(lc16 == hc16 && hc16 == 0);
2486
2487 hc16 = 0;
2488 lc16 = 1;
2489 mask = 0x55; // select hc16
2490 }
2491
2492 assert(lc16 > hc16);
2493 pDst_block->set_low_color(static_cast<uint16_t>(lc16));
2494 pDst_block->set_high_color(static_cast<uint16_t>(hc16));
2495
2496 pDst_block->m_selectors[0] = mask;
2497 pDst_block->m_selectors[1] = mask;
2498 pDst_block->m_selectors[2] = mask;
2499 pDst_block->m_selectors[3] = mask;
2500 }
2501 else
2502 {
2503 uint8_t invert_mask = 0;
2504 if (lc16 < hc16)
2505 {
2506 std::swap(lc16, hc16);
2507 invert_mask = 0x55;
2508 }
2509
2510 assert(lc16 > hc16);
2511 pDst_block->set_low_color((uint16_t)lc16);
2512 pDst_block->set_high_color((uint16_t)hc16);
2513
2514 uint32_t packed_sels = 0;
2515 static const uint8_t s_sel_trans[4] = { 0, 2, 3, 1 };
2516 for (uint32_t i = 0; i < 16; i++)
2517 packed_sels |= ((uint32_t)s_sel_trans[sels[i]] << (i * 2));
2518
2519 pDst_block->m_selectors[0] = (uint8_t)packed_sels ^ invert_mask;
2520 pDst_block->m_selectors[1] = (uint8_t)(packed_sels >> 8) ^ invert_mask;
2521 pDst_block->m_selectors[2] = (uint8_t)(packed_sels >> 16) ^ invert_mask;
2522 pDst_block->m_selectors[3] = (uint8_t)(packed_sels >> 24) ^ invert_mask;
2523 }
2524 }
2525
2526 static inline void bc1_encode3(bc1_block *pDst_block, int lr, int lg, int lb, int hr, int hg, int hb, const uint8_t sels[16])
2527 {
2528 uint32_t lc16 = bc1_block::pack_unscaled_color(lr, lg, lb);
2529 uint32_t hc16 = bc1_block::pack_unscaled_color(hr, hg, hb);
2530
2531 bool invert_flag = false;
2532 if (lc16 > hc16)
2533 {
2534 std::swap(lc16, hc16);
2535 invert_flag = true;
2536 }
2537
2538 assert(lc16 <= hc16);
2539
2540 pDst_block->set_low_color((uint16_t)lc16);
2541 pDst_block->set_high_color((uint16_t)hc16);
2542
2543 uint32_t packed_sels = 0;
2544
2545 if (invert_flag)
2546 {
2547 static const uint8_t s_sel_trans_inv[4] = { 1, 0, 2, 3 };
2548
2549 for (uint32_t i = 0; i < 16; i++)
2550 packed_sels |= ((uint32_t)s_sel_trans_inv[sels[i]] << (i * 2));
2551 }
2552 else
2553 {
2554 for (uint32_t i = 0; i < 16; i++)
2555 packed_sels |= ((uint32_t)sels[i] << (i * 2));
2556 }
2557
2558 pDst_block->m_selectors[0] = (uint8_t)packed_sels;
2559 pDst_block->m_selectors[1] = (uint8_t)(packed_sels >> 8);
2560 pDst_block->m_selectors[2] = (uint8_t)(packed_sels >> 16);
2561 pDst_block->m_selectors[3] = (uint8_t)(packed_sels >> 24);
2562 }
2563
2564 struct bc1_encode_results
2565 {
2566 int lr, lg, lb;
2567 int hr, hg, hb;
2568 uint8_t sels[16];
2569 bool m_3color;
2570 };
2571
2572 static bool try_3color_block_useblack(const color32* pSrc_pixels, uint32_t flags, uint32_t &cur_err, bc1_encode_results &results)
2573 {
2574 int total_r = 0, total_g = 0, total_b = 0;
2575 int max_r = 0, max_g = 0, max_b = 0;
2576 int min_r = 255, min_g = 255, min_b = 255;
2577 int total_pixels = 0;
2578 for (uint32_t i = 0; i < 16; i++)
2579 {
2580 const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
2581 if ((r | g | b) < 4)
2582 continue;
2583
2584 max_r = std::max(max_r, r); max_g = std::max(max_g, g); max_b = std::max(max_b, b);
2585 min_r = std::min(min_r, r); min_g = std::min(min_g, g); min_b = std::min(min_b, b);
2586 total_r += r; total_g += g; total_b += b;
2587
2588 total_pixels++;
2589 }
2590
2591 if (!total_pixels)
2592 return false;
2593
2594 int half_total_pixels = total_pixels >> 1;
2595 int avg_r = (total_r + half_total_pixels) / total_pixels;
2596 int avg_g = (total_g + half_total_pixels) / total_pixels;
2597 int avg_b = (total_b + half_total_pixels) / total_pixels;
2598
2599 uint32_t low_c = 0, high_c = 0;
2600
2601 int icov[6] = { 0, 0, 0, 0, 0, 0 };
2602 for (uint32_t i = 0; i < 16; i++)
2603 {
2604 int r = (int)pSrc_pixels[i].r;
2605 int g = (int)pSrc_pixels[i].g;
2606 int b = (int)pSrc_pixels[i].b;
2607
2608 if ((r | g | b) < 4)
2609 continue;
2610
2611 r -= avg_r;
2612 g -= avg_g;
2613 b -= avg_b;
2614
2615 icov[0] += r * r;
2616 icov[1] += r * g;
2617 icov[2] += r * b;
2618 icov[3] += g * g;
2619 icov[4] += g * b;
2620 icov[5] += b * b;
2621 }
2622
2623 float cov[6];
2624 for (uint32_t i = 0; i < 6; i++)
2625 cov[i] = (float)(icov[i]) * (1.0f / 255.0f);
2626
2627 float xr = (float)(max_r - min_r);
2628 float xg = (float)(max_g - min_g);
2629 float xb = (float)(max_b - min_b);
2630
2631 if (icov[2] < 0)
2632 xr = -xr;
2633
2634 if (icov[4] < 0)
2635 xg = -xg;
2636
2637 for (uint32_t power_iter = 0; power_iter < 4; power_iter++)
2638 {
2639 float r = xr * cov[0] + xg * cov[1] + xb * cov[2];
2640 float g = xr * cov[1] + xg * cov[3] + xb * cov[4];
2641 float b = xr * cov[2] + xg * cov[4] + xb * cov[5];
2642 xr = r; xg = g; xb = b;
2643 }
2644
2645 float k = maximum(fabsf(xr), fabsf(xg), fabsf(xb));
2646 int saxis_r = 306, saxis_g = 601, saxis_b = 117;
2647 if (k >= 2)
2648 {
2649 float m = 1024.0f / k;
2650 saxis_r = (int)(xr * m);
2651 saxis_g = (int)(xg * m);
2652 saxis_b = (int)(xb * m);
2653 }
2654
2655 int low_dot = INT_MAX, high_dot = INT_MIN;
2656 for (uint32_t i = 0; i < 16; i++)
2657 {
2658 int r = (int)pSrc_pixels[i].r, g = (int)pSrc_pixels[i].g, b = (int)pSrc_pixels[i].b;
2659
2660 if ((r | g | b) < 4)
2661 continue;
2662
2663 int dot = r * saxis_r + g * saxis_g + b * saxis_b;
2664 if (dot < low_dot)
2665 {
2666 low_dot = dot;
2667 low_c = i;
2668 }
2669 if (dot > high_dot)
2670 {
2671 high_dot = dot;
2672 high_c = i;
2673 }
2674 }
2675
2676 int lr = to_5(pSrc_pixels[low_c].r);
2677 int lg = to_6(pSrc_pixels[low_c].g);
2678 int lb = to_5(pSrc_pixels[low_c].b);
2679
2680 int hr = to_5(pSrc_pixels[high_c].r);
2681 int hg = to_6(pSrc_pixels[high_c].g);
2682 int hb = to_5(pSrc_pixels[high_c].b);
2683
2684 uint8_t trial_sels[16];
2685 uint32_t trial_err = bc1_find_sels3_fullerr(true, pSrc_pixels, lr, lg, lb, hr, hg, hb, trial_sels, UINT32_MAX);
2686
2687 if (trial_err)
2688 {
2689 const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1;
2690 for (uint32_t trials = 0; trials < total_ls_passes; trials++)
2691 {
2692 vec3F xl, xh;
2693 int lr2, lg2, lb2, hr2, hg2, hb2;
2694 if (!compute_least_squares_endpoints3_rgb(true, pSrc_pixels, trial_sels, &xl, &xh))
2695 {
2696 lr2 = g_bc1_match5_half[avg_r].m_hi;
2697 lg2 = g_bc1_match6_half[avg_g].m_hi;
2698 lb2 = g_bc1_match5_half[avg_b].m_hi;
2699
2700 hr2 = g_bc1_match5_half[avg_r].m_lo;
2701 hg2 = g_bc1_match6_half[avg_g].m_lo;
2702 hb2 = g_bc1_match5_half[avg_b].m_lo;
2703 }
2704 else
2705 {
2706 precise_round_565(xl, xh, hr2, hg2, hb2, lr2, lg2, lb2);
2707 }
2708
2709 if ((lr == lr2) && (lg == lg2) && (lb == lb2) && (hr == hr2) && (hg == hg2) && (hb == hb2))
2710 break;
2711
2712 uint8_t trial_sels2[16];
2713 uint32_t trial_err2 = bc1_find_sels3_fullerr(true, pSrc_pixels, lr2, lg2, lb2, hr2, hg2, hb2, trial_sels2, trial_err);
2714
2715 if (trial_err2 < trial_err)
2716 {
2717 trial_err = trial_err2;
2718 lr = lr2; lg = lg2; lb = lb2;
2719 hr = hr2; hg = hg2; hb = hb2;
2720 memcpy(trial_sels, trial_sels2, sizeof(trial_sels));
2721 }
2722 else
2723 break;
2724 }
2725 }
2726
2727 if (trial_err < cur_err)
2728 {
2729 results.m_3color = true;
2730 results.lr = lr;
2731 results.lg = lg;
2732 results.lb = lb;
2733 results.hr = hr;
2734 results.hg = hg;
2735 results.hb = hb;
2736 memcpy(results.sels, trial_sels, 16);
2737
2738 cur_err = trial_err;
2739
2740 return true;
2741 }
2742
2743 return false;
2744 }
2745
2746 static bool try_3color_block(const color32* pSrc_pixels, uint32_t flags, uint32_t &cur_err,
2747 int avg_r, int avg_g, int avg_b, int lr, int lg, int lb, int hr, int hg, int hb, int total_r, int total_g, int total_b, uint32_t total_orderings_to_try,
2748 bc1_encode_results &results)
2749 {
2750 uint8_t trial_sels[16];
2751 uint32_t trial_err = bc1_find_sels3_fullerr(false, pSrc_pixels, lr, lg, lb, hr, hg, hb, trial_sels, UINT32_MAX);
2752
2753 if (trial_err)
2754 {
2755 const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1;
2756 for (uint32_t trials = 0; trials < total_ls_passes; trials++)
2757 {
2758 vec3F xl, xh;
2759 int lr2, lg2, lb2, hr2, hg2, hb2;
2760 if (!compute_least_squares_endpoints3_rgb(false, pSrc_pixels, trial_sels, &xl, &xh))
2761 {
2762 lr2 = g_bc1_match5_half[avg_r].m_hi;
2763 lg2 = g_bc1_match6_half[avg_g].m_hi;
2764 lb2 = g_bc1_match5_half[avg_b].m_hi;
2765
2766 hr2 = g_bc1_match5_half[avg_r].m_lo;
2767 hg2 = g_bc1_match6_half[avg_g].m_lo;
2768 hb2 = g_bc1_match5_half[avg_b].m_lo;
2769 }
2770 else
2771 {
2772 precise_round_565(xl, xh, hr2, hg2, hb2, lr2, lg2, lb2);
2773 }
2774
2775 if ((lr == lr2) && (lg == lg2) && (lb == lb2) && (hr == hr2) && (hg == hg2) && (hb == hb2))
2776 break;
2777
2778 uint8_t trial_sels2[16];
2779 uint32_t trial_err2 = bc1_find_sels3_fullerr(false, pSrc_pixels, lr2, lg2, lb2, hr2, hg2, hb2, trial_sels2, trial_err);
2780
2781 if (trial_err2 < trial_err)
2782 {
2783 trial_err = trial_err2;
2784 lr = lr2; lg = lg2; lb = lb2;
2785 hr = hr2; hg = hg2; hb = hb2;
2786 memcpy(trial_sels, trial_sels2, sizeof(trial_sels));
2787 }
2788 else
2789 break;
2790 }
2791 }
2792
2793 if ((trial_err) && (flags & cEncodeBC1UseLikelyTotalOrderings) && (total_orderings_to_try))
2794 {
2795 hist3 h;
2796 for (uint32_t i = 0; i < 16; i++)
2797 {
2798 assert(trial_sels[i] < 3);
2799 h.m_hist[trial_sels[i]]++;
2800 }
2801
2802 const uint32_t orig_total_order_index = h.lookup_total_ordering_index();
2803
2804 int r0, g0, b0, r3, g3, b3;
2805 r0 = (lr << 3) | (lr >> 2); g0 = (lg << 2) | (lg >> 4); b0 = (lb << 3) | (lb >> 2);
2806 r3 = (hr << 3) | (hr >> 2); g3 = (hg << 2) | (hg >> 4); b3 = (hb << 3) | (hb >> 2);
2807
2808 int ar = r3 - r0, ag = g3 - g0, ab = b3 - b0;
2809
2810 int dots[16];
2811 for (uint32_t i = 0; i < 16; i++)
2812 {
2813 int r = pSrc_pixels[i].r;
2814 int g = pSrc_pixels[i].g;
2815 int b = pSrc_pixels[i].b;
2816 int d = 0x1000000 + (r * ar + g * ag + b * ab);
2817 assert(d >= 0);
2818 dots[i] = (d << 4) + i;
2819 }
2820
2821 std::sort(dots, dots + 16);
2822
2823 uint32_t r_sum[17], g_sum[17], b_sum[17];
2824 uint32_t r = 0, g = 0, b = 0;
2825 for (uint32_t i = 0; i < 16; i++)
2826 {
2827 const uint32_t p = dots[i] & 15;
2828
2829 r_sum[i] = r;
2830 g_sum[i] = g;
2831 b_sum[i] = b;
2832
2833 r += pSrc_pixels[p].r;
2834 g += pSrc_pixels[p].g;
2835 b += pSrc_pixels[p].b;
2836 }
2837
2838 r_sum[16] = total_r;
2839 g_sum[16] = total_g;
2840 b_sum[16] = total_b;
2841
2842 const uint32_t q_total = (flags & cEncodeBC1Exhaustive) ? NUM_UNIQUE_TOTAL_ORDERINGS3 : std::min(total_orderings_to_try, MAX_TOTAL_ORDERINGS3);
2843 for (uint32_t q = 0; q < q_total; q++)
2844 {
2845 const uint32_t s = (flags & cEncodeBC1Exhaustive) ? q : g_best_total_orderings3[orig_total_order_index][q];
2846
2847 int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb;
2848
2849 vec3F xl, xh;
2850
2851 if ((s == TOTAL_ORDER_3_0_16) || (s == TOTAL_ORDER_3_1_16) || (s == TOTAL_ORDER_3_2_16))
2852 {
2853 trial_lr = g_bc1_match5_half[avg_r].m_hi;
2854 trial_lg = g_bc1_match6_half[avg_g].m_hi;
2855 trial_lb = g_bc1_match5_half[avg_b].m_hi;
2856
2857 trial_hr = g_bc1_match5_half[avg_r].m_lo;
2858 trial_hg = g_bc1_match6_half[avg_g].m_lo;
2859 trial_hb = g_bc1_match5_half[avg_b].m_lo;
2860 }
2861 else
2862 {
2863 compute_least_squares_endpoints3_rgb(&xl, &xh, total_r, total_g, total_b,
2864 g_selector_factors3[s][0], g_selector_factors3[s][1], g_selector_factors3[s][2], s, r_sum, g_sum, b_sum);
2865
2866 precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb);
2867 }
2868
2869 uint8_t trial_sels2[16];
2870 uint32_t trial_err2 = bc1_find_sels3_fullerr(false, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels2, UINT32_MAX);
2871
2872 if (trial_err2 < trial_err)
2873 {
2874 trial_err = trial_err2;
2875
2876 lr = trial_lr;
2877 lg = trial_lg;
2878 lb = trial_lb;
2879
2880 hr = trial_hr;
2881 hg = trial_hg;
2882 hb = trial_hb;
2883
2884 memcpy(trial_sels, trial_sels2, sizeof(trial_sels));
2885 }
2886
2887 } // s
2888 }
2889
2890 if (trial_err < cur_err)
2891 {
2892 results.m_3color = true;
2893 results.lr = lr;
2894 results.lg = lg;
2895 results.lb = lb;
2896 results.hr = hr;
2897 results.hg = hg;
2898 results.hb = hb;
2899 memcpy(results.sels, trial_sels, 16);
2900
2901 cur_err = trial_err;
2902
2903 return true;
2904 }
2905
2906 return false;
2907 }
2908
2909 void encode_bc1(uint32_t level, void* pDst, const uint8_t* pPixels, bool allow_3color, bool allow_transparent_texels_for_black)
2910 {
2911 uint32_t flags = 0, total_orderings4 = 1, total_orderings3 = 1;
2912
2913 static_assert(MAX_TOTAL_ORDERINGS3 >= 32, "MAX_TOTAL_ORDERINGS3 >= 32");
2914 static_assert(MAX_TOTAL_ORDERINGS4 >= 32, "MAX_TOTAL_ORDERINGS4 >= 32");
2915
2916 switch (level)
2917 {
2918 case 0:
2919 // Faster/higher quality than stb_dxt default.
2920 flags = cEncodeBC1BoundingBoxInt;
2921 break;
2922 case 1:
2923 // Faster/higher quality than stb_dxt default. A bit higher average quality vs. mode 0.
2924 flags = cEncodeBC1Use2DLS;
2925 break;
2926 case 2:
2927 // On average mode 2 is a little weaker than modes 0/1, but it's stronger on outliers (very tough textures).
2928 // Slightly stronger than stb_dxt.
2929 flags = 0;
2930 break;
2931 case 3:
2932 // Slightly stronger than stb_dxt HIGHQUAL.
2933 flags = cEncodeBC1TwoLeastSquaresPasses;
2934 break;
2935 case 4:
2936 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1Use6PowerIters;
2937 break;
2938 default:
2939 case 5:
2940 // stb_dxt HIGHQUAL + permit 3 color (if it's enabled).
2941 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval;
2942 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2943 break;
2944 case 6:
2945 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval | cEncodeBC1UseLikelyTotalOrderings;
2946 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2947 break;
2948 case 7:
2949 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval | cEncodeBC1UseLikelyTotalOrderings;
2950 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2951 total_orderings4 = 4;
2952 break;
2953 case 8:
2954 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval | cEncodeBC1UseLikelyTotalOrderings;
2955 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2956 total_orderings4 = 8;
2957 break;
2958 case 9:
2959 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings;
2960 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2961 total_orderings4 = 11;
2962 total_orderings3 = 3;
2963 break;
2964 case 10:
2965 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings;
2966 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2967 total_orderings4 = 20;
2968 total_orderings3 = 8;
2969 break;
2970 case 11:
2971 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings;
2972 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2973 total_orderings4 = 28;
2974 total_orderings3 = 16;
2975 break;
2976 case 12:
2977 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings;
2978 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2979 total_orderings4 = 32;
2980 total_orderings3 = 32;
2981 break;
2982 case 13:
2983 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | (20 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts;
2984 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2985 total_orderings4 = 32;
2986 total_orderings3 = 32;
2987 break;
2988 case 14:
2989 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | (32 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts;
2990 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2991 total_orderings4 = 32;
2992 total_orderings3 = 32;
2993 break;
2994 case 15:
2995 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | (32 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts;
2996 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
2997 total_orderings4 = ((((32 + MAX_TOTAL_ORDERINGS4) / 2) + 32) / 2);
2998 total_orderings3 = 32;
2999 break;
3000 case 16:
3001 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts;
3002 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
3003 total_orderings4 = (32 + MAX_TOTAL_ORDERINGS4) / 2;
3004 total_orderings3 = 32;
3005 break;
3006 case 17:
3007 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts;
3008 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
3009 total_orderings4 = MAX_TOTAL_ORDERINGS4;
3010 total_orderings3 = 32;
3011 break;
3012 case 18:
3013 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | cEncodeBC1Iterative | (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts;
3014 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
3015 total_orderings4 = MAX_TOTAL_ORDERINGS4;
3016 total_orderings3 = 32;
3017 break;
3018 case 19:
3019 // This hidden mode is *extremely* slow and abuses the encoder. It's just for testing/training.
3020 flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | cEncodeBC1Exhaustive | cEncodeBC1Iterative | (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts;
3021 flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0);
3022 total_orderings4 = 32;
3023 total_orderings3 = 32;
3024 break;
3025 }
3026
3027 encode_bc1(pDst, pPixels, flags, total_orderings4, total_orderings3);
3028 }
3029
3030 static inline void encode_bc1_pick_initial(const color32 *pSrc_pixels, uint32_t flags, bool grayscale_flag,
3031 int min_r, int min_g, int min_b, int max_r, int max_g, int max_b,
3032 int avg_r, int avg_g, int avg_b, int total_r, int total_g, int total_b,
3033 int &lr, int &lg, int &lb, int &hr, int &hg, int &hb)
3034 {
3035 if (grayscale_flag)
3036 {
3037 const int fr = pSrc_pixels[0].r;
3038
3039 // Grayscale blocks are a common enough case to specialize.
3040 if ((max_r - min_r) < 2)
3041 {
3042 lr = lb = hr = hb = to_5(fr);
3043 lg = hg = to_6(fr);
3044 }
3045 else
3046 {
3047 lr = lb = to_5(min_r);
3048 lg = to_6(min_r);
3049
3050 hr = hb = to_5(max_r);
3051 hg = to_6(max_r);
3052 }
3053 }
3054 else if (flags & cEncodeBC1Use2DLS)
3055 {
3056 // 2D Least Squares approach from Humus's example, with added inset and optimal rounding.
3057 int big_chan = 0, min_chan_val = min_r, max_chan_val = max_r;
3058 if ((max_g - min_g) > (max_chan_val - min_chan_val))
3059 big_chan = 1, min_chan_val = min_g, max_chan_val = max_g;
3060
3061 if ((max_b - min_b) > (max_chan_val - min_chan_val))
3062 big_chan = 2, min_chan_val = min_b, max_chan_val = max_b;
3063
3064 int sum_xy_r = 0, sum_xy_g = 0, sum_xy_b = 0;
3065 vec3F l, h;
3066 if (big_chan == 0)
3067 {
3068 for (uint32_t i = 0; i < 16; i++)
3069 {
3070 const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
3071 sum_xy_r += r * r, sum_xy_g += r * g, sum_xy_b += r * b;
3072 }
3073
3074 int sum_x = total_r;
3075 int sum_x2 = sum_xy_r;
3076
3077 float div = (float)(16 * sum_x2 - sum_x * sum_x);
3078 float b_y = 0.0f, b_z = 0.0f;
3079 if (fabs(div) > 1e-8f)
3080 {
3081 div = 1.0f / div;
3082 b_y = (16 * sum_xy_g - sum_x * total_g) * div;
3083 b_z = (16 * sum_xy_b - sum_x * total_b) * div;
3084 }
3085
3086 float a_y = (total_g - b_y * sum_x) / 16.0f;
3087 float a_z = (total_b - b_z * sum_x) / 16.0f;
3088
3089 l.c[1] = a_y + b_y * min_chan_val;
3090 l.c[2] = a_z + b_z * min_chan_val;
3091
3092 h.c[1] = a_y + b_y * max_chan_val;
3093 h.c[2] = a_z + b_z * max_chan_val;
3094
3095 float dg = (h.c[1] - l.c[1]);
3096 float db = (h.c[2] - l.c[2]);
3097
3098 h.c[1] = l.c[1] + dg * (15.0f/16.0f);
3099 h.c[2] = l.c[2] + db * (15.0f/16.0f);
3100
3101 l.c[1] = l.c[1] + dg * (1.0f/16.0f);
3102 l.c[2] = l.c[2] + db * (1.0f/16.0f);
3103
3104 float d = (float)(max_chan_val - min_chan_val);
3105 float fmin_chan_val = min_chan_val + d * (1.0f/16.0f);
3106 float fmax_chan_val = min_chan_val + d * (15.0f/16.0f);
3107
3108 l.c[0] = fmin_chan_val;
3109 h.c[0] = fmax_chan_val;
3110 }
3111 else if (big_chan == 1)
3112 {
3113 for (uint32_t i = 0; i < 16; i++)
3114 {
3115 const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
3116 sum_xy_r += g * r, sum_xy_g += g * g, sum_xy_b += g * b;
3117 }
3118
3119 int sum_x = total_g;
3120 int sum_x2 = sum_xy_g;
3121
3122 float div = (float)(16 * sum_x2 - sum_x * sum_x);
3123 float b_x = 0.0f, b_z = 0.0f;
3124 if (fabs(div) > 1e-8f)
3125 {
3126 div = 1.0f / div;
3127 b_x = (16 * sum_xy_r - sum_x * total_r) * div;
3128 b_z = (16 * sum_xy_b - sum_x * total_b) * div;
3129 }
3130
3131 float a_x = (total_r - b_x * sum_x) / 16.0f;
3132 float a_z = (total_b - b_z * sum_x) / 16.0f;
3133
3134 l.c[0] = a_x + b_x * min_chan_val;
3135 l.c[2] = a_z + b_z * min_chan_val;
3136
3137 h.c[0] = a_x + b_x * max_chan_val;
3138 h.c[2] = a_z + b_z * max_chan_val;
3139
3140 float dr = (h.c[0] - l.c[0]);
3141 float db = (h.c[2] - l.c[2]);
3142
3143 h.c[0] = l.c[0] + dr * (15.0f/16.0f);
3144 h.c[2] = l.c[2] + db * (15.0f/16.0f);
3145
3146 l.c[0] = l.c[0] + dr * (1.0f/16.0f);
3147 l.c[2] = l.c[2] + db * (1.0f/16.0f);
3148
3149 float d = (float)(max_chan_val - min_chan_val);
3150 float fmin_chan_val = min_chan_val + d * (1.0f/16.0f);
3151 float fmax_chan_val = min_chan_val + d * (15.0f/16.0f);
3152
3153 l.c[1] = fmin_chan_val;
3154 h.c[1] = fmax_chan_val;
3155 }
3156 else
3157 {
3158 for (uint32_t i = 0; i < 16; i++)
3159 {
3160 const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
3161 sum_xy_r += b * r, sum_xy_g += b * g, sum_xy_b += b * b;
3162 }
3163
3164 int sum_x = total_b;
3165 int sum_x2 = sum_xy_b;
3166
3167 float div = (float)(16 * sum_x2 - sum_x * sum_x);
3168 float b_x = 0.0f, b_y = 0.0f;
3169 if (fabs(div) > 1e-8f)
3170 {
3171 div = 1.0f / div;
3172 b_x = (16 * sum_xy_r - sum_x * total_r) * div;
3173 b_y = (16 * sum_xy_g - sum_x * total_g) * div;
3174 }
3175
3176 float a_x = (total_r - b_x * sum_x) / 16.0f;
3177 float a_y = (total_g - b_y * sum_x) / 16.0f;
3178
3179 l.c[0] = a_x + b_x * min_chan_val;
3180 l.c[1] = a_y + b_y * min_chan_val;
3181
3182 h.c[0] = a_x + b_x * max_chan_val;
3183 h.c[1] = a_y + b_y * max_chan_val;
3184
3185 float dr = (h.c[0] - l.c[0]);
3186 float dg = (h.c[1] - l.c[1]);
3187
3188 h.c[0] = l.c[0] + dr * (15.0f/16.0f);
3189 h.c[1] = l.c[1] + dg * (15.0f/16.0f);
3190
3191 l.c[0] = l.c[0] + dr * (1.0f/16.0f);
3192 l.c[1] = l.c[1] + dg * (1.0f/16.0f);
3193
3194 float d = (float)(max_chan_val - min_chan_val);
3195 float fmin_chan_val = min_chan_val + d * (1.0f/16.0f);
3196 float fmax_chan_val = min_chan_val + d * (15.0f/16.0f);
3197
3198 l.c[2] = fmin_chan_val;
3199 h.c[2] = fmax_chan_val;
3200 }
3201
3202 precise_round_565_noscale(l, h, lr, lg, lb, hr, hg, hb);
3203 }
3204 else if (flags & cEncodeBC1BoundingBox)
3205 {
3206 // Algorithm from icbc.h compress_dxt1_fast()
3207 vec3F l, h;
3208 l.c[0] = min_r * (1.0f/255.0f);
3209 l.c[1] = min_g * (1.0f/255.0f);
3210 l.c[2] = min_b * (1.0f/255.0f);
3211
3212 h.c[0] = max_r * (1.0f/255.0f);
3213 h.c[1] = max_g * (1.0f/255.0f);
3214 h.c[2] = max_b * (1.0f/255.0f);
3215
3216 const float bias = 8.0f / 255.0f;
3217 float inset_r = (h.c[0] - l.c[0] - bias) * (1.0f/16.0f);
3218 float inset_g = (h.c[1] - l.c[1] - bias) * (1.0f/16.0f);
3219 float inset_b = (h.c[2] - l.c[2] - bias) * (1.0f/16.0f);
3220
3221 l.c[0] = clampf(l.c[0] + inset_r, 0.0f, 1.0f);
3222 l.c[1] = clampf(l.c[1] + inset_g, 0.0f, 1.0f);
3223 l.c[2] = clampf(l.c[2] + inset_b, 0.0f, 1.0f);
3224
3225 h.c[0] = clampf(h.c[0] - inset_r, 0.0f, 1.0f);
3226 h.c[1] = clampf(h.c[1] - inset_g, 0.0f, 1.0f);
3227 h.c[2] = clampf(h.c[2] - inset_b, 0.0f, 1.0f);
3228
3229 int icov_xz = 0, icov_yz = 0;
3230 for (uint32_t i = 0; i < 16; i++)
3231 {
3232 int r = (int)pSrc_pixels[i].r - avg_r;
3233 int g = (int)pSrc_pixels[i].g - avg_g;
3234 int b = (int)pSrc_pixels[i].b - avg_b;
3235 icov_xz += r * b;
3236 icov_yz += g * b;
3237 }
3238
3239 if (icov_xz < 0)
3240 std::swap(l.c[0], h.c[0]);
3241
3242 if (icov_yz < 0)
3243 std::swap(l.c[1], h.c[1]);
3244
3245 precise_round_565(l, h, lr, lg, lb, hr, hg, hb);
3246 }
3247 else if (flags & cEncodeBC1BoundingBoxInt)
3248 {
3249 // Algorithm from icbc.h compress_dxt1_fast(), but converted to integer.
3250 int inset_r = (max_r - min_r - 8) >> 4;
3251 int inset_g = (max_g - min_g - 8) >> 4;
3252 int inset_b = (max_b - min_b - 8) >> 4;
3253
3254 min_r += inset_r;
3255 min_g += inset_g;
3256 min_b += inset_b;
3257 if ((uint32_t)(min_r | min_g | min_b) > 255U)
3258 {
3259 min_r = clampi(min_r, 0, 255);
3260 min_g = clampi(min_g, 0, 255);
3261 min_b = clampi(min_b, 0, 255);
3262 }
3263
3264 max_r -= inset_r;
3265 max_g -= inset_g;
3266 max_b -= inset_b;
3267 if ((uint32_t)(max_r | max_g | max_b) > 255U)
3268 {
3269 max_r = clampi(max_r, 0, 255);
3270 max_g = clampi(max_g, 0, 255);
3271 max_b = clampi(max_b, 0, 255);
3272 }
3273
3274 int icov_xz = 0, icov_yz = 0;
3275 for (uint32_t i = 0; i < 16; i++)
3276 {
3277 int r = (int)pSrc_pixels[i].r - avg_r;
3278 int g = (int)pSrc_pixels[i].g - avg_g;
3279 int b = (int)pSrc_pixels[i].b - avg_b;
3280 icov_xz += r * b;
3281 icov_yz += g * b;
3282 }
3283
3284 int x0 = min_r;
3285 int y0 = min_g;
3286 int x1 = max_r;
3287 int y1 = max_g;
3288
3289 if (icov_xz < 0)
3290 std::swap(x0, x1);
3291
3292 if (icov_yz < 0)
3293 std::swap(y0, y1);
3294
3295 lr = to_5(x0);
3296 lg = to_6(y0);
3297 lb = to_5(min_b);
3298
3299 hr = to_5(x1);
3300 hg = to_6(y1);
3301 hb = to_5(max_b);
3302 }
3303 else
3304 {
3305 // Select 2 colors along the principle axis. (There must be a faster/simpler way.)
3306 uint32_t low_c = 0, high_c = 0;
3307
3308 int icov[6] = { 0, 0, 0, 0, 0, 0 };
3309 for (uint32_t i = 0; i < 16; i++)
3310 {
3311 int r = (int)pSrc_pixels[i].r - avg_r;
3312 int g = (int)pSrc_pixels[i].g - avg_g;
3313 int b = (int)pSrc_pixels[i].b - avg_b;
3314 icov[0] += r * r;
3315 icov[1] += r * g;
3316 icov[2] += r * b;
3317 icov[3] += g * g;
3318 icov[4] += g * b;
3319 icov[5] += b * b;
3320 }
3321
3322 int saxis_r = 306, saxis_g = 601, saxis_b = 117;
3323
3324 float xr = (float)(max_r - min_r);
3325 float xg = (float)(max_g - min_g);
3326 float xb = (float)(max_b - min_b);
3327
3328 if (icov[2] < 0)
3329 xr = -xr;
3330
3331 if (icov[4] < 0)
3332 xg = -xg;
3333
3334 float cov[6];
3335 for (uint32_t i = 0; i < 6; i++)
3336 cov[i] = (float)(icov[i]) * (1.0f / 255.0f);
3337
3338 const uint32_t total_power_iters = (flags & cEncodeBC1Use6PowerIters) ? 6 : 4;
3339 for (uint32_t power_iter = 0; power_iter < total_power_iters; power_iter++)
3340 {
3341 float r = xr * cov[0] + xg * cov[1] + xb * cov[2];
3342 float g = xr * cov[1] + xg * cov[3] + xb * cov[4];
3343 float b = xr * cov[2] + xg * cov[4] + xb * cov[5];
3344 xr = r; xg = g; xb = b;
3345 }
3346
3347 float k = maximum(fabsf(xr), fabsf(xg), fabsf(xb));
3348 if (k >= 2)
3349 {
3350 float m = 2048.0f / k;
3351 saxis_r = (int)(xr * m);
3352 saxis_g = (int)(xg * m);
3353 saxis_b = (int)(xb * m);
3354 }
3355
3356 int low_dot = INT_MAX, high_dot = INT_MIN;
3357
3358 saxis_r = (int)((uint32_t)saxis_r << 4U);
3359 saxis_g = (int)((uint32_t)saxis_g << 4U);
3360 saxis_b = (int)((uint32_t)saxis_b << 4U);
3361
3362 for (uint32_t i = 0; i < 16; i += 4)
3363 {
3364 int dot0 = ((pSrc_pixels[i].r * saxis_r + pSrc_pixels[i].g * saxis_g + pSrc_pixels[i].b * saxis_b) & ~0xF) + i;
3365 int dot1 = ((pSrc_pixels[i + 1].r * saxis_r + pSrc_pixels[i + 1].g * saxis_g + pSrc_pixels[i + 1].b * saxis_b) & ~0xF) + i + 1;
3366 int dot2 = ((pSrc_pixels[i + 2].r * saxis_r + pSrc_pixels[i + 2].g * saxis_g + pSrc_pixels[i + 2].b * saxis_b) & ~0xF) + i + 2;
3367 int dot3 = ((pSrc_pixels[i + 3].r * saxis_r + pSrc_pixels[i + 3].g * saxis_g + pSrc_pixels[i + 3].b * saxis_b) & ~0xF) + i + 3;
3368
3369 int min_d01 = std::min(dot0, dot1);
3370 int max_d01 = std::max(dot0, dot1);
3371
3372 int min_d23 = std::min(dot2, dot3);
3373 int max_d23 = std::max(dot2, dot3);
3374
3375 int min_d = std::min(min_d01, min_d23);
3376 int max_d = std::max(max_d01, max_d23);
3377
3378 low_dot = std::min(low_dot, min_d);
3379 high_dot = std::max(high_dot, max_d);
3380 }
3381 low_c = low_dot & 15;
3382 high_c = high_dot & 15;
3383
3384 lr = to_5(pSrc_pixels[low_c].r);
3385 lg = to_6(pSrc_pixels[low_c].g);
3386 lb = to_5(pSrc_pixels[low_c].b);
3387
3388 hr = to_5(pSrc_pixels[high_c].r);
3389 hg = to_6(pSrc_pixels[high_c].g);
3390 hb = to_5(pSrc_pixels[high_c].b);
3391 }
3392 }
3393
3394 static const int8_t s_adjacent_voxels[16][4] =
3395 {
3396 { 1,0,0, 3 }, // 0
3397 { 0,1,0, 4 }, // 1
3398 { 0,0,1, 5 }, // 2
3399 { -1,0,0, 0 }, // 3
3400 { 0,-1,0, 1 }, // 4
3401 { 0,0,-1, 2 }, // 5
3402 { 1,1,0, 9 }, // 6
3403 { 1,0,1, 10 }, // 7
3404 { 0,1,1, 11 }, // 8
3405 { -1,-1,0, 6 }, // 9
3406 { -1,0,-1, 7 }, // 10
3407 { 0,-1,-1, 8 }, // 11
3408 { -1,1,0, 13 }, // 12
3409 { 1,-1,0, 12 }, // 13
3410 { 0,-1,1, 15 }, // 14
3411 { 0,1,-1, 14 }, // 15
3412 };
3413
3414 // From icbc's high quality mode.
3415 static inline void encode_bc1_endpoint_search(const color32 *pSrc_pixels, bool any_black_pixels,
3416 uint32_t flags, bc1_encode_results &results, uint32_t cur_err)
3417 {
3418 int &lr = results.lr, &lg = results.lg, &lb = results.lb, &hr = results.hr, &hg = results.hg, &hb = results.hb;
3419 uint8_t *sels = results.sels;
3420
3421 int prev_improvement_index = 0, forbidden_direction = -1;
3422
3423 const int endpoint_search_rounds = (flags & cEncodeBC1EndpointSearchRoundsMask) >> cEncodeBC1EndpointSearchRoundsShift;
3424 for (int i = 0; i < endpoint_search_rounds; i++)
3425 {
3426 assert(s_adjacent_voxels[ s_adjacent_voxels[i & 15][3] ][3] == (i & 15));
3427
3428 if (forbidden_direction == (i & 31))
3429 continue;
3430
3431 const int8_t delta[3] = { s_adjacent_voxels[i & 15][0], s_adjacent_voxels[i & 15][1], s_adjacent_voxels[i & 15][2] };
3432
3433 int trial_lr = lr, trial_lg = lg, trial_lb = lb, trial_hr = hr, trial_hg = hg, trial_hb = hb;
3434
3435 if ((i >> 4) & 1)
3436 {
3437 trial_lr = clampi(trial_lr + delta[0], 0, 31);
3438 trial_lg = clampi(trial_lg + delta[1], 0, 63);
3439 trial_lb = clampi(trial_lb + delta[2], 0, 31);
3440 }
3441 else
3442 {
3443 trial_hr = clampi(trial_hr + delta[0], 0, 31);
3444 trial_hg = clampi(trial_hg + delta[1], 0, 63);
3445 trial_hb = clampi(trial_hb + delta[2], 0, 31);
3446 }
3447
3448 uint8_t trial_sels[16];
3449
3450 uint32_t trial_err;
3451 if (results.m_3color)
3452 {
3453 trial_err = bc1_find_sels3_fullerr(
3454 ((any_black_pixels) && ((flags & cEncodeBC1Use3ColorBlocksForBlackPixels) != 0)),
3455 pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, cur_err);
3456 }
3457 else
3458 {
3459 trial_err = bc1_find_sels4(flags, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, cur_err);
3460 }
3461
3462 if (trial_err < cur_err)
3463 {
3464 cur_err = trial_err;
3465
3466 forbidden_direction = s_adjacent_voxels[i & 15][3] | (i & 16);
3467
3468 lr = trial_lr, lg = trial_lg, lb = trial_lb, hr = trial_hr, hg = trial_hg, hb = trial_hb;
3469
3470 memcpy(sels, trial_sels, 16);
3471
3472 prev_improvement_index = i;
3473 }
3474
3475 if (i - prev_improvement_index > 32)
3476 break;
3477 }
3478 }
3479
3480 void encode_bc1(void* pDst, const uint8_t* pPixels, uint32_t flags, uint32_t total_orderings_to_try, uint32_t total_orderings_to_try3)
3481 {
3482 assert(g_initialized);
3483
3484 const color32* pSrc_pixels = (const color32*)pPixels;
3485 bc1_block* pDst_block = static_cast<bc1_block*>(pDst);
3486
3487 int avg_r, avg_g, avg_b, min_r, min_g, min_b, max_r, max_g, max_b;
3488
3489 const uint32_t fr = pSrc_pixels[0].r, fg = pSrc_pixels[0].g, fb = pSrc_pixels[0].b;
3490
3491 uint32_t j;
3492 for (j = 15; j >= 1; --j)
3493 if ((pSrc_pixels[j].r != fr) || (pSrc_pixels[j].g != fg) || (pSrc_pixels[j].b != fb))
3494 break;
3495
3496 if (j == 0)
3497 {
3498 encode_bc1_solid_block(pDst, fr, fg, fb, (flags & (cEncodeBC1Use3ColorBlocks | cEncodeBC1Use3ColorBlocksForBlackPixels)) != 0);
3499 return;
3500 }
3501
3502 int total_r = fr, total_g = fg, total_b = fb;
3503
3504 max_r = fr, max_g = fg, max_b = fb;
3505 min_r = fr, min_g = fg, min_b = fb;
3506
3507 uint32_t grayscale_flag = (fr == fg) && (fr == fb);
3508 uint32_t any_black_pixels = (fr | fg | fb) < 4;
3509
3510 for (uint32_t i = 1; i < 16; i++)
3511 {
3512 const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b;
3513
3514 grayscale_flag &= ((r == g) && (r == b));
3515 any_black_pixels |= ((r | g | b) < 4);
3516
3517 max_r = std::max(max_r, r); max_g = std::max(max_g, g); max_b = std::max(max_b, b);
3518 min_r = std::min(min_r, r); min_g = std::min(min_g, g); min_b = std::min(min_b, b);
3519 total_r += r; total_g += g; total_b += b;
3520 }
3521
3522 avg_r = (total_r + 8) >> 4, avg_g = (total_g + 8) >> 4, avg_b = (total_b + 8) >> 4;
3523
3524 bc1_encode_results results;
3525 results.m_3color = false;
3526
3527 uint8_t *sels = results.sels;
3528 int &lr = results.lr, &lg = results.lg, &lb = results.lb, &hr = results.hr, &hg = results.hg, &hb = results.hb;
3529 int orig_lr = 0, orig_lg = 0, orig_lb = 0, orig_hr = 0, orig_hg = 0, orig_hb = 0;
3530
3531 lr = 0, lg = 0, lb = 0, hr = 0, hg = 0, hb = 0;
3532
3533 const bool needs_block_error = ((flags & (cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use3ColorBlocks | cEncodeBC1UseFullMSEEval | cEncodeBC1EndpointSearchRoundsMask)) != 0) ||
3534 (any_black_pixels && ((flags & cEncodeBC1Use3ColorBlocksForBlackPixels) != 0));
3535
3536 uint32_t cur_err = UINT32_MAX;
3537
3538 if (!needs_block_error)
3539 {
3540 assert((flags & cEncodeBC1TryAllInitialEndponts) == 0);
3541
3542 encode_bc1_pick_initial(pSrc_pixels, flags, grayscale_flag != 0,
3543 min_r, min_g, min_b, max_r, max_g, max_b,
3544 avg_r, avg_g, avg_b, total_r, total_g, total_b,
3545 lr, lg, lb, hr, hg, hb);
3546
3547 orig_lr = lr, orig_lg = lg, orig_lb = lb, orig_hr = hr, orig_hg = hg, orig_hb = hb;
3548
3549 bc1_find_sels4_noerr(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels);
3550
3551 const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1;
3552 for (uint32_t ls_pass = 0; ls_pass < total_ls_passes; ls_pass++)
3553 {
3554 int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb;
3555
3556 vec3F xl, xh;
3557 if (!compute_least_squares_endpoints4_rgb(pSrc_pixels, sels, &xl, &xh, total_r, total_g, total_b))
3558 {
3559 // All selectors equal - treat it as a solid block which should always be equal or better.
3560 trial_lr = g_bc1_match5_equals_1[avg_r].m_hi;
3561 trial_lg = g_bc1_match6_equals_1[avg_g].m_hi;
3562 trial_lb = g_bc1_match5_equals_1[avg_b].m_hi;
3563
3564 trial_hr = g_bc1_match5_equals_1[avg_r].m_lo;
3565 trial_hg = g_bc1_match6_equals_1[avg_g].m_lo;
3566 trial_hb = g_bc1_match5_equals_1[avg_b].m_lo;
3567
3568 // In high/higher quality mode, let it try again in case the optimal tables have caused the sels to diverge.
3569 }
3570 else
3571 {
3572 precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb);
3573 }
3574
3575 if ((lr == trial_lr) && (lg == trial_lg) && (lb == trial_lb) && (hr == trial_hr) && (hg == trial_hg) && (hb == trial_hb))
3576 break;
3577
3578 bc1_find_sels4_noerr(pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, sels);
3579
3580 lr = trial_lr;
3581 lg = trial_lg;
3582 lb = trial_lb;
3583 hr = trial_hr;
3584 hg = trial_hg;
3585 hb = trial_hb;
3586
3587 } // ls_pass
3588 }
3589 else
3590 {
3591 const uint32_t total_rounds = (flags & cEncodeBC1TryAllInitialEndponts) ? 2 : 1;
3592 for (uint32_t round = 0; round < total_rounds; round++)
3593 {
3594 uint32_t modified_flags = flags;
3595 if (round == 1)
3596 {
3597 modified_flags &= ~(cEncodeBC1Use2DLS | cEncodeBC1BoundingBox);
3598 modified_flags |= cEncodeBC1BoundingBox;
3599 }
3600
3601 int round_lr, round_lg, round_lb, round_hr, round_hg, round_hb;
3602 uint8_t round_sels[16];
3603
3604 encode_bc1_pick_initial(pSrc_pixels, modified_flags, grayscale_flag != 0,
3605 min_r, min_g, min_b, max_r, max_g, max_b,
3606 avg_r, avg_g, avg_b, total_r, total_g, total_b,
3607 round_lr, round_lg, round_lb, round_hr, round_hg, round_hb);
3608
3609 int orig_round_lr = round_lr, orig_round_lg = round_lg, orig_round_lb = round_lb, orig_round_hr = round_hr, orig_round_hg = round_hg, orig_round_hb = round_hb;
3610
3611 uint32_t round_err = bc1_find_sels4(flags, pSrc_pixels, round_lr, round_lg, round_lb, round_hr, round_hg, round_hb, round_sels, UINT32_MAX);
3612
3613 const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1;
3614 for (uint32_t ls_pass = 0; ls_pass < total_ls_passes; ls_pass++)
3615 {
3616 int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb;
3617
3618 vec3F xl, xh;
3619 if (!compute_least_squares_endpoints4_rgb(pSrc_pixels, round_sels, &xl, &xh, total_r, total_g, total_b))
3620 {
3621 // All selectors equal - treat it as a solid block which should always be equal or better.
3622 trial_lr = g_bc1_match5_equals_1[avg_r].m_hi;
3623 trial_lg = g_bc1_match6_equals_1[avg_g].m_hi;
3624 trial_lb = g_bc1_match5_equals_1[avg_b].m_hi;
3625
3626 trial_hr = g_bc1_match5_equals_1[avg_r].m_lo;
3627 trial_hg = g_bc1_match6_equals_1[avg_g].m_lo;
3628 trial_hb = g_bc1_match5_equals_1[avg_b].m_lo;
3629
3630 // In high/higher quality mode, let it try again in case the optimal tables have caused the sels to diverge.
3631 }
3632 else
3633 {
3634 precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb);
3635 }
3636
3637 if ((round_lr == trial_lr) && (round_lg == trial_lg) && (round_lb == trial_lb) && (round_hr == trial_hr) && (round_hg == trial_hg) && (round_hb == trial_hb))
3638 break;
3639
3640 uint8_t trial_sels[16];
3641 uint32_t trial_err = bc1_find_sels4(flags, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, round_err);
3642
3643 if (trial_err < round_err)
3644 {
3645 round_lr = trial_lr;
3646 round_lg = trial_lg;
3647 round_lb = trial_lb;
3648
3649 round_hr = trial_hr;
3650 round_hg = trial_hg;
3651 round_hb = trial_hb;
3652
3653 round_err = trial_err;
3654 memcpy(round_sels, trial_sels, 16);
3655 }
3656 else
3657 break;
3658
3659 } // ls_pass
3660
3661 if (round_err <= cur_err)
3662 {
3663 cur_err = round_err;
3664
3665 lr = round_lr;
3666 lg = round_lg;
3667 lb = round_lb;
3668 hr = round_hr;
3669 hg = round_hg;
3670 hb = round_hb;
3671
3672 orig_lr = orig_round_lr;
3673 orig_lg = orig_round_lg;
3674 orig_lb = orig_round_lb;
3675 orig_hr = orig_round_hr;
3676 orig_hg = orig_round_hg;
3677 orig_hb = orig_round_hb;
3678
3679 memcpy(sels, round_sels, 16);
3680 }
3681
3682 } // round
3683 }
3684
3685 if ((cur_err) && (flags & cEncodeBC1UseLikelyTotalOrderings))
3686 {
3687 assert(needs_block_error);
3688
3689 const uint32_t total_iters = (flags & cEncodeBC1Iterative) ? 2 : 1;
3690 for (uint32_t iter_index = 0; iter_index < total_iters; iter_index++)
3691 {
3692 const uint32_t orig_err = cur_err;
3693
3694 hist4 h;
3695 for (uint32_t i = 0; i < 16; i++)
3696 {
3697 assert(sels[i] < 4);
3698 h.m_hist[sels[i]]++;
3699 }
3700
3701 const uint32_t orig_total_order_index = h.lookup_total_ordering_index();
3702
3703 int r0, g0, b0, r3, g3, b3;
3704 r0 = (lr << 3) | (lr >> 2); g0 = (lg << 2) | (lg >> 4); b0 = (lb << 3) | (lb >> 2);
3705 r3 = (hr << 3) | (hr >> 2); g3 = (hg << 2) | (hg >> 4); b3 = (hb << 3) | (hb >> 2);
3706
3707 int ar = r3 - r0, ag = g3 - g0, ab = b3 - b0;
3708
3709 int dots[16];
3710 for (uint32_t i = 0; i < 16; i++)
3711 {
3712 int r = pSrc_pixels[i].r;
3713 int g = pSrc_pixels[i].g;
3714 int b = pSrc_pixels[i].b;
3715 int d = 0x1000000 + (r * ar + g * ag + b * ab);
3716 assert(d >= 0);
3717 dots[i] = (d << 4) + i;
3718 }
3719
3720 std::sort(dots, dots + 16);
3721
3722 uint32_t r_sum[17], g_sum[17], b_sum[17];
3723 uint32_t r = 0, g = 0, b = 0;
3724 for (uint32_t i = 0; i < 16; i++)
3725 {
3726 const uint32_t p = dots[i] & 15;
3727
3728 r_sum[i] = r;
3729 g_sum[i] = g;
3730 b_sum[i] = b;
3731
3732 r += pSrc_pixels[p].r;
3733 g += pSrc_pixels[p].g;
3734 b += pSrc_pixels[p].b;
3735 }
3736
3737 r_sum[16] = total_r;
3738 g_sum[16] = total_g;
3739 b_sum[16] = total_b;
3740
3741 const uint32_t q_total = (flags & cEncodeBC1Exhaustive) ? NUM_UNIQUE_TOTAL_ORDERINGS4 : clampi(total_orderings_to_try, MIN_TOTAL_ORDERINGS, MAX_TOTAL_ORDERINGS4);
3742 for (uint32_t q = 0; q < q_total; q++)
3743 {
3744 const uint32_t s = (flags & cEncodeBC1Exhaustive) ? q : g_best_total_orderings4[orig_total_order_index][q];
3745
3746 int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb;
3747
3748 vec3F xl, xh;
3749
3750 if ((s == TOTAL_ORDER_4_0_16) || (s == TOTAL_ORDER_4_1_16) || (s == TOTAL_ORDER_4_2_16) || (s == TOTAL_ORDER_4_3_16))
3751 {
3752 trial_lr = g_bc1_match5_equals_1[avg_r].m_hi;
3753 trial_lg = g_bc1_match6_equals_1[avg_g].m_hi;
3754 trial_lb = g_bc1_match5_equals_1[avg_b].m_hi;
3755
3756 trial_hr = g_bc1_match5_equals_1[avg_r].m_lo;
3757 trial_hg = g_bc1_match6_equals_1[avg_g].m_lo;
3758 trial_hb = g_bc1_match5_equals_1[avg_b].m_lo;
3759 }
3760 else
3761 {
3762 compute_least_squares_endpoints4_rgb(&xl, &xh, total_r, total_g, total_b,
3763 g_selector_factors4[s][0], g_selector_factors4[s][1], g_selector_factors4[s][2], s, r_sum, g_sum, b_sum);
3764
3765 precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb);
3766 }
3767
3768 uint8_t trial_sels[16];
3769
3770 uint32_t trial_err = bc1_find_sels4(flags, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, cur_err);
3771
3772 if (trial_err < cur_err)
3773 {
3774 cur_err = trial_err;
3775
3776 lr = trial_lr;
3777 lg = trial_lg;
3778 lb = trial_lb;
3779
3780 hr = trial_hr;
3781 hg = trial_hg;
3782 hb = trial_hb;
3783
3784 memcpy(sels, trial_sels, 16);
3785 }
3786
3787 } // s
3788
3789 if ((!cur_err) || (cur_err == orig_err))
3790 break;
3791
3792 } // iter_index
3793 }
3794
3795 if ( ((flags & (cEncodeBC1Use3ColorBlocks | cEncodeBC1Use3ColorBlocksForBlackPixels)) != 0) && (cur_err) )
3796 {
3797 if (flags & cEncodeBC1Use3ColorBlocks)
3798 {
3799 assert(needs_block_error);
3800 try_3color_block(pSrc_pixels, flags, cur_err, avg_r, avg_g, avg_b, orig_lr, orig_lg, orig_lb, orig_hr, orig_hg, orig_hb, total_r, total_g, total_b, total_orderings_to_try3, results);
3801 }
3802
3803 if ((any_black_pixels) && ((flags & cEncodeBC1Use3ColorBlocksForBlackPixels) != 0))
3804 {
3805 assert(needs_block_error);
3806 try_3color_block_useblack(pSrc_pixels, flags, cur_err, results);
3807 }
3808 }
3809
3810 if ( (flags & cEncodeBC1EndpointSearchRoundsMask) && (cur_err) )
3811 {
3812 assert(needs_block_error);
3813
3814 encode_bc1_endpoint_search(pSrc_pixels, any_black_pixels != 0, flags, results, cur_err);
3815 }
3816
3817 if (results.m_3color)
3818 bc1_encode3(pDst_block, results.lr, results.lg, results.lb, results.hr, results.hg, results.hb, results.sels);
3819 else
3820 bc1_encode4(pDst_block, results.lr, results.lg, results.lb, results.hr, results.hg, results.hb, results.sels);
3821 }
3822
3823 // BC3-5
3824
3825 struct bc4_block
3826 {
3827 enum { cBC4SelectorBits = 3, cTotalSelectorBytes = 6, cMaxSelectorValues = 8 };
3828 uint8_t m_endpoints[2];
3829
3830 uint8_t m_selectors[cTotalSelectorBytes];
3831
3832 inline uint32_t get_low_alpha() const { return m_endpoints[0]; }
3833 inline uint32_t get_high_alpha() const { return m_endpoints[1]; }
3834 inline bool is_alpha6_block() const { return get_low_alpha() <= get_high_alpha(); }
3835
3836 inline uint64_t get_selector_bits() const
3837 {
3838 return ((uint64_t)((uint32_t)m_selectors[0] | ((uint32_t)m_selectors[1] << 8U) | ((uint32_t)m_selectors[2] << 16U) | ((uint32_t)m_selectors[3] << 24U))) |
3839 (((uint64_t)m_selectors[4]) << 32U) |
3840 (((uint64_t)m_selectors[5]) << 40U);
3841 }
3842
3843 inline uint32_t get_selector(uint32_t x, uint32_t y, uint64_t selector_bits) const
3844 {
3845 assert((x < 4U) && (y < 4U));
3846 return (selector_bits >> (((y * 4) + x) * cBC4SelectorBits))& (cMaxSelectorValues - 1);
3847 }
3848
3849 static inline uint32_t get_block_values6(uint8_t* pDst, uint32_t l, uint32_t h)
3850 {
3851 pDst[0] = static_cast<uint8_t>(l);
3852 pDst[1] = static_cast<uint8_t>(h);
3853 pDst[2] = static_cast<uint8_t>((l * 4 + h) / 5);
3854 pDst[3] = static_cast<uint8_t>((l * 3 + h * 2) / 5);
3855 pDst[4] = static_cast<uint8_t>((l * 2 + h * 3) / 5);
3856 pDst[5] = static_cast<uint8_t>((l + h * 4) / 5);
3857 pDst[6] = 0;
3858 pDst[7] = 255;
3859 return 6;
3860 }
3861
3862 static inline uint32_t get_block_values8(uint8_t* pDst, uint32_t l, uint32_t h)
3863 {
3864 pDst[0] = static_cast<uint8_t>(l);
3865 pDst[1] = static_cast<uint8_t>(h);
3866 pDst[2] = static_cast<uint8_t>((l * 6 + h) / 7);
3867 pDst[3] = static_cast<uint8_t>((l * 5 + h * 2) / 7);
3868 pDst[4] = static_cast<uint8_t>((l * 4 + h * 3) / 7);
3869 pDst[5] = static_cast<uint8_t>((l * 3 + h * 4) / 7);
3870 pDst[6] = static_cast<uint8_t>((l * 2 + h * 5) / 7);
3871 pDst[7] = static_cast<uint8_t>((l + h * 6) / 7);
3872 return 8;
3873 }
3874
3875 static inline uint32_t get_block_values(uint8_t* pDst, uint32_t l, uint32_t h)
3876 {
3877 if (l > h)
3878 return get_block_values8(pDst, l, h);
3879 else
3880 return get_block_values6(pDst, l, h);
3881 }
3882 };
3883
3884 void encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride)
3885 {
3886 assert(g_initialized);
3887
3888 uint32_t min0_v, max0_v, min1_v, max1_v, min2_v, max2_v, min3_v, max3_v;
3889
3890 {
3891 min0_v = max0_v = pPixels[0 * stride];
3892 min1_v = max1_v = pPixels[1 * stride];
3893 min2_v = max2_v = pPixels[2 * stride];
3894 min3_v = max3_v = pPixels[3 * stride];
3895 }
3896
3897 {
3898 uint32_t v0 = pPixels[4 * stride]; min0_v = std::min(min0_v, v0); max0_v = std::max(max0_v, v0);
3899 uint32_t v1 = pPixels[5 * stride]; min1_v = std::min(min1_v, v1); max1_v = std::max(max1_v, v1);
3900 uint32_t v2 = pPixels[6 * stride]; min2_v = std::min(min2_v, v2); max2_v = std::max(max2_v, v2);
3901 uint32_t v3 = pPixels[7 * stride]; min3_v = std::min(min3_v, v3); max3_v = std::max(max3_v, v3);
3902 }
3903
3904 {
3905 uint32_t v0 = pPixels[8 * stride]; min0_v = std::min(min0_v, v0); max0_v = std::max(max0_v, v0);
3906 uint32_t v1 = pPixels[9 * stride]; min1_v = std::min(min1_v, v1); max1_v = std::max(max1_v, v1);
3907 uint32_t v2 = pPixels[10 * stride]; min2_v = std::min(min2_v, v2); max2_v = std::max(max2_v, v2);
3908 uint32_t v3 = pPixels[11 * stride]; min3_v = std::min(min3_v, v3); max3_v = std::max(max3_v, v3);
3909 }
3910
3911 {
3912 uint32_t v0 = pPixels[12 * stride]; min0_v = std::min(min0_v, v0); max0_v = std::max(max0_v, v0);
3913 uint32_t v1 = pPixels[13 * stride]; min1_v = std::min(min1_v, v1); max1_v = std::max(max1_v, v1);
3914 uint32_t v2 = pPixels[14 * stride]; min2_v = std::min(min2_v, v2); max2_v = std::max(max2_v, v2);
3915 uint32_t v3 = pPixels[15 * stride]; min3_v = std::min(min3_v, v3); max3_v = std::max(max3_v, v3);
3916 }
3917
3918 const uint32_t min_v = minimum(min0_v, min1_v, min2_v, min3_v);
3919 const uint32_t max_v = maximum(max0_v, max1_v, max2_v, max3_v);
3920
3921 uint8_t* pDst_bytes = static_cast<uint8_t*>(pDst);
3922 pDst_bytes[0] = (uint8_t)max_v;
3923 pDst_bytes[1] = (uint8_t)min_v;
3924
3925 if (max_v == min_v)
3926 {
3927 memset(pDst_bytes + 2, 0, 6);
3928 return;
3929 }
3930
3931 const uint32_t delta = max_v - min_v;
3932
3933 // min_v is now 0. Compute thresholds between values by scaling max_v. It's x14 because we're adding two x7 scale factors.
3934 const int t0 = delta * 13;
3935 const int t1 = delta * 11;
3936 const int t2 = delta * 9;
3937 const int t3 = delta * 7;
3938 const int t4 = delta * 5;
3939 const int t5 = delta * 3;
3940 const int t6 = delta * 1;
3941
3942 // BC4 floors in its divisions, which we compensate for with the 4 bias.
3943 // This function is optimal for all possible inputs (i.e. it outputs the same results as checking all 8 values and choosing the closest one).
3944 const int bias = 4 - min_v * 14;
3945
3946 static const uint32_t s_tran0[8] = { 1U , 7U , 6U , 5U , 4U , 3U , 2U , 0U };
3947 static const uint32_t s_tran1[8] = { 1U << 3U, 7U << 3U, 6U << 3U, 5U << 3U, 4U << 3U, 3U << 3U, 2U << 3U, 0U << 3U };
3948 static const uint32_t s_tran2[8] = { 1U << 6U, 7U << 6U, 6U << 6U, 5U << 6U, 4U << 6U, 3U << 6U, 2U << 6U, 0U << 6U };
3949 static const uint32_t s_tran3[8] = { 1U << 9U, 7U << 9U, 6U << 9U, 5U << 9U, 4U << 9U, 3U << 9U, 2U << 9U, 0U << 9U };
3950
3951 uint64_t a0, a1, a2, a3;
3952 {
3953 const int v0 = pPixels[0 * stride] * 14 + bias;
3954 const int v1 = pPixels[1 * stride] * 14 + bias;
3955 const int v2 = pPixels[2 * stride] * 14 + bias;
3956 const int v3 = pPixels[3 * stride] * 14 + bias;
3957 a0 = s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)];
3958 a1 = s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)];
3959 a2 = s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)];
3960 a3 = s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)];
3961 }
3962
3963 {
3964 const int v0 = pPixels[4 * stride] * 14 + bias;
3965 const int v1 = pPixels[5 * stride] * 14 + bias;
3966 const int v2 = pPixels[6 * stride] * 14 + bias;
3967 const int v3 = pPixels[7 * stride] * 14 + bias;
3968 a0 |= (uint64_t)(s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)] << 12U);
3969 a1 |= (uint64_t)(s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)] << 12U);
3970 a2 |= (uint64_t)(s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)] << 12U);
3971 a3 |= (uint64_t)(s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)] << 12U);
3972 }
3973
3974 {
3975 const int v0 = pPixels[8 * stride] * 14 + bias;
3976 const int v1 = pPixels[9 * stride] * 14 + bias;
3977 const int v2 = pPixels[10 * stride] * 14 + bias;
3978 const int v3 = pPixels[11 * stride] * 14 + bias;
3979 a0 |= (((uint64_t)s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]) << 24U);
3980 a1 |= (((uint64_t)s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]) << 24U);
3981 a2 |= (((uint64_t)s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]) << 24U);
3982 a3 |= (((uint64_t)s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]) << 24U);
3983 }
3984
3985 {
3986 const int v0 = pPixels[12 * stride] * 14 + bias;
3987 const int v1 = pPixels[13 * stride] * 14 + bias;
3988 const int v2 = pPixels[14 * stride] * 14 + bias;
3989 const int v3 = pPixels[15 * stride] * 14 + bias;
3990 a0 |= (((uint64_t)s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]) << 36U);
3991 a1 |= (((uint64_t)s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]) << 36U);
3992 a2 |= (((uint64_t)s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]) << 36U);
3993 a3 |= (((uint64_t)s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]) << 36U);
3994 }
3995
3996 const uint64_t f = a0 | a1 | a2 | a3;
3997
3998 pDst_bytes[2] = (uint8_t)f;
3999 pDst_bytes[3] = (uint8_t)(f >> 8U);
4000 pDst_bytes[4] = (uint8_t)(f >> 16U);
4001 pDst_bytes[5] = (uint8_t)(f >> 24U);
4002 pDst_bytes[6] = (uint8_t)(f >> 32U);
4003 pDst_bytes[7] = (uint8_t)(f >> 40U);
4004 }
4005
4006 void encode_bc3(void* pDst, const uint8_t* pPixels, uint32_t flags, uint32_t total_orderings_to_try)
4007 {
4008 assert(g_initialized);
4009
4010 // 3-color blocks are not allowed with BC3 (on most GPU's).
4011 flags &= ~(cEncodeBC1Use3ColorBlocksForBlackPixels | cEncodeBC1Use3ColorBlocks);
4012
4013 encode_bc4(pDst, pPixels + 3, 4);
4014 encode_bc1(static_cast<uint8_t*>(pDst) + 8, pPixels, flags, total_orderings_to_try);
4015 }
4016
4017 void encode_bc3(uint32_t level, void* pDst, const uint8_t* pPixels)
4018 {
4019 assert(g_initialized);
4020
4021 encode_bc4(pDst, pPixels + 3, 4);
4022 encode_bc1(level, static_cast<uint8_t*>(pDst) + 8, pPixels, false, false);
4023 }
4024
4025 void encode_bc5(void* pDst, const uint8_t* pPixels, uint32_t chan0, uint32_t chan1, uint32_t stride)
4026 {
4027 assert(g_initialized);
4028
4029 encode_bc4(pDst, pPixels + chan0, stride);
4030 encode_bc4(static_cast<uint8_t*>(pDst) + 8, pPixels + chan1, stride);
4031 }
4032
4033 // Returns true if the block uses 3 color punchthrough alpha mode.
4034 bool unpack_bc1(const void* pBlock_bits, void* pPixels, bool set_alpha, bc1_approx_mode mode)
4035 {
4036 color32* pDst_pixels = static_cast<color32*>(pPixels);
4037
4038 static_assert(sizeof(bc1_block) == 8, "sizeof(bc1_block) == 8");
4039 static_assert(sizeof(bc4_block) == 8, "sizeof(bc4_block) == 8");
4040
4041 const bc1_block* pBlock = static_cast<const bc1_block*>(pBlock_bits);
4042
4043 const uint32_t l = pBlock->get_low_color();
4044 const uint32_t h = pBlock->get_high_color();
4045
4046 color32 c[4];
4047
4048 const int cr0 = (l >> 11) & 31;
4049 const int cg0 = (l >> 5) & 63;
4050 const int cb0 = l & 31;
4051 const int r0 = (cr0 << 3) | (cr0 >> 2);
4052 const int g0 = (cg0 << 2) | (cg0 >> 4);
4053 const int b0 = (cb0 << 3) | (cb0 >> 2);
4054
4055 const int cr1 = (h >> 11) & 31;
4056 const int cg1 = (h >> 5) & 63;
4057 const int cb1 = h & 31;
4058 const int r1 = (cr1 << 3) | (cr1 >> 2);
4059 const int g1 = (cg1 << 2) | (cg1 >> 4);
4060 const int b1 = (cb1 << 3) | (cb1 >> 2);
4061
4062 bool used_punchthrough = false;
4063
4064 if (l > h)
4065 {
4066 c[0].set_noclamp_rgba(r0, g0, b0, 255);
4067 c[1].set_noclamp_rgba(r1, g1, b1, 255);
4068 switch (mode)
4069 {
4070 case bc1_approx_mode::cBC1Ideal:
4071 c[2].set_noclamp_rgba((r0 * 2 + r1) / 3, (g0 * 2 + g1) / 3, (b0 * 2 + b1) / 3, 255);
4072 c[3].set_noclamp_rgba((r1 * 2 + r0) / 3, (g1 * 2 + g0) / 3, (b1 * 2 + b0) / 3, 255);
4073 break;
4074 case bc1_approx_mode::cBC1IdealRound4:
4075 c[2].set_noclamp_rgba((r0 * 2 + r1 + 1) / 3, (g0 * 2 + g1 + 1) / 3, (b0 * 2 + b1 + 1) / 3, 255);
4076 c[3].set_noclamp_rgba((r1 * 2 + r0 + 1) / 3, (g1 * 2 + g0 + 1) / 3, (b1 * 2 + b0 + 1) / 3, 255);
4077 break;
4078 case bc1_approx_mode::cBC1NVidia:
4079 c[2].set_noclamp_rgba(interp_5_nv(cr0, cr1), interp_6_nv(g0, g1), interp_5_nv(cb0, cb1), 255);
4080 c[3].set_noclamp_rgba(interp_5_nv(cr1, cr0), interp_6_nv(g1, g0), interp_5_nv(cb1, cb0), 255);
4081 break;
4082 case bc1_approx_mode::cBC1AMD:
4083 c[2].set_noclamp_rgba(interp_5_6_amd(r0, r1), interp_5_6_amd(g0, g1), interp_5_6_amd(b0, b1), 255);
4084 c[3].set_noclamp_rgba(interp_5_6_amd(r1, r0), interp_5_6_amd(g1, g0), interp_5_6_amd(b1, b0), 255);
4085 break;
4086 }
4087 }
4088 else
4089 {
4090 c[0].set_noclamp_rgba(r0, g0, b0, 255);
4091 c[1].set_noclamp_rgba(r1, g1, b1, 255);
4092 switch (mode)
4093 {
4094 case bc1_approx_mode::cBC1Ideal:
4095 case bc1_approx_mode::cBC1IdealRound4:
4096 c[2].set_noclamp_rgba((r0 + r1) / 2, (g0 + g1) / 2, (b0 + b1) / 2, 255);
4097 break;
4098 case bc1_approx_mode::cBC1NVidia:
4099 c[2].set_noclamp_rgba(interp_half_5_nv(cr0, cr1), interp_half_6_nv(g0, g1), interp_half_5_nv(cb0, cb1), 255);
4100 break;
4101 case bc1_approx_mode::cBC1AMD:
4102 c[2].set_noclamp_rgba(interp_half_5_6_amd(r0, r1), interp_half_5_6_amd(g0, g1), interp_half_5_6_amd(b0, b1), 255);
4103 break;
4104 }
4105
4106 c[3].set_noclamp_rgba(0, 0, 0, 0);
4107 used_punchthrough = true;
4108 }
4109
4110 if (set_alpha)
4111 {
4112 for (uint32_t y = 0; y < 4; y++, pDst_pixels += 4)
4113 {
4114 pDst_pixels[0] = c[pBlock->get_selector(0, y)];
4115 pDst_pixels[1] = c[pBlock->get_selector(1, y)];
4116 pDst_pixels[2] = c[pBlock->get_selector(2, y)];
4117 pDst_pixels[3] = c[pBlock->get_selector(3, y)];
4118 }
4119 }
4120 else
4121 {
4122 for (uint32_t y = 0; y < 4; y++, pDst_pixels += 4)
4123 {
4124 pDst_pixels[0].set_rgb(c[pBlock->get_selector(0, y)]);
4125 pDst_pixels[1].set_rgb(c[pBlock->get_selector(1, y)]);
4126 pDst_pixels[2].set_rgb(c[pBlock->get_selector(2, y)]);
4127 pDst_pixels[3].set_rgb(c[pBlock->get_selector(3, y)]);
4128 }
4129 }
4130
4131 return used_punchthrough;
4132 }
4133
4134 void unpack_bc4(const void* pBlock_bits, uint8_t* pPixels, uint32_t stride)
4135 {
4136 static_assert(sizeof(bc4_block) == 8, "sizeof(bc4_block) == 8");
4137
4138 const bc4_block* pBlock = static_cast<const bc4_block*>(pBlock_bits);
4139
4140 uint8_t sel_values[8];
4141 bc4_block::get_block_values(sel_values, pBlock->get_low_alpha(), pBlock->get_high_alpha());
4142
4143 const uint64_t selector_bits = pBlock->get_selector_bits();
4144
4145 for (uint32_t y = 0; y < 4; y++, pPixels += (stride * 4U))
4146 {
4147 pPixels[0] = sel_values[pBlock->get_selector(0, y, selector_bits)];
4148 pPixels[stride * 1] = sel_values[pBlock->get_selector(1, y, selector_bits)];
4149 pPixels[stride * 2] = sel_values[pBlock->get_selector(2, y, selector_bits)];
4150 pPixels[stride * 3] = sel_values[pBlock->get_selector(3, y, selector_bits)];
4151 }
4152 }
4153
4154 // Returns false if the block uses 3-color punchthrough alpha mode, which isn't supported on some GPU's for BC3.
4155 bool unpack_bc3(const void* pBlock_bits, void* pPixels, bc1_approx_mode mode)
4156 {
4157 color32* pDst_pixels = static_cast<color32*>(pPixels);
4158
4159 bool success = true;
4160
4161 if (unpack_bc1((const uint8_t*)pBlock_bits + sizeof(bc4_block), pDst_pixels, true, mode))
4162 success = false;
4163
4164 unpack_bc4(pBlock_bits, &pDst_pixels[0].a, sizeof(color32));
4165
4166 return success;
4167 }
4168
4169 // writes RG
4170 void unpack_bc5(const void* pBlock_bits, void* pPixels, uint32_t chan0, uint32_t chan1, uint32_t stride)
4171 {
4172 unpack_bc4(pBlock_bits, (uint8_t *)pPixels + chan0, stride);
4173 unpack_bc4((const uint8_t*)pBlock_bits + sizeof(bc4_block), (uint8_t *)pPixels + chan1, stride);
4174 }
4175
4176 } // namespace rgbcx
4177
4178 #endif //#ifdef RGBCX_IMPLEMENTATION
4179
4180 /*
4181 ------------------------------------------------------------------------------
4182 This software is available under 2 licenses -- choose whichever you prefer.
4183 ------------------------------------------------------------------------------
4184 ALTERNATIVE A - MIT License
4185 Copyright(c) 2020 Richard Geldreich, Jr.
4186 Permission is hereby granted, free of charge, to any person obtaining a copy of
4187 this software and associated documentation files(the "Software"), to deal in
4188 the Software without restriction, including without limitation the rights to
4189 use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies
4190 of the Software, and to permit persons to whom the Software is furnished to do
4191 so, subject to the following conditions :
4192 The above copyright notice and this permission notice shall be included in all
4193 copies or substantial portions of the Software.
4194 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4195 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4196 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
4197 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4198 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4199 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
4200 SOFTWARE.
4201 ------------------------------------------------------------------------------
4202 ALTERNATIVE B - Public Domain(www.unlicense.org)
4203 This is free and unencumbered software released into the public domain.
4204 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
4205 software, either in source code form or as a compiled binary, for any purpose,
4206 commercial or non - commercial, and by any means.
4207 In jurisdictions that recognize copyright laws, the author or authors of this
4208 software dedicate any and all copyright interest in the software to the public
4209 domain.We make this dedication for the benefit of the public at large and to
4210 the detriment of our heirs and successors.We intend this dedication to be an
4211 overt act of relinquishment in perpetuity of all present and future rights to
4212 this software under copyright law.
4213 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4214 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4215 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
4216 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
4217 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
4218 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4219 ------------------------------------------------------------------------------
4220 */
4221