UNPKG

88 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright 2017 Google LLC. All Rights Reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 * =============================================================================
16 */
17import * as tf from '../index';
18import { ALL_ENVS, describeWithFlags } from '../jasmine_util';
19import { expectArraysClose } from '../test_util';
20describeWithFlags('conv2dTranspose', ALL_ENVS, () => {
21 it('input=2x2x1,d2=1,f=2,s=1,p=0', async () => {
22 const origInputDepth = 1;
23 const origOutputDepth = 1;
24 const inputShape = [1, 1, origOutputDepth];
25 const fSize = 2;
26 const origPad = 0;
27 const origStride = 1;
28 const x = tf.tensor3d([2], inputShape);
29 const w = tf.tensor4d([3, 1, 5, 0], [fSize, fSize, origInputDepth, origOutputDepth]);
30 const result = tf.conv2dTranspose(x, w, [2, 2, 1], origStride, origPad);
31 const expected = [6, 2, 10, 0];
32 expect(result.shape).toEqual([2, 2, 1]);
33 expectArraysClose(await result.data(), expected);
34 });
35 it('input=3x3x1,d2=1,f=2,s=2,p=same', async () => {
36 const origInputDepth = 1;
37 const origOutputDepth = 4;
38 const inputShape = [1, 2, 2, origOutputDepth];
39 const fSize = 2;
40 const origPad = 'same';
41 const origStride = 2;
42 const x = tf.tensor4d([
43 1.24, 1.66, 0.9, 1.39, 0.16, 0.27, 0.42, 0.61, 0.04, 0.17, 0.34, 0.28,
44 0., 0.06, 0.14, 0.24
45 ], inputShape);
46 const w = tf.tensor4d([0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.], [fSize, fSize, origInputDepth, origOutputDepth]);
47 const result = tf.conv2dTranspose(x, w, [1, 3, 3, 1], origStride, origPad);
48 const expected = [7.63, 28.39, 2.94, 49.15, 69.91, 14.62, 1.69, 5.01, 1.06];
49 expect(result.shape).toEqual([1, 3, 3, 1]);
50 expectArraysClose(await result.data(), expected);
51 });
52 it('input=3x3x1,d2=1,f=2,s=2,p=explicit', async () => {
53 const origInputDepth = 1;
54 const origOutputDepth = 4;
55 const inputShape = [1, 2, 2, origOutputDepth];
56 const fSize = 2;
57 const origPad = [[0, 0], [0, 1], [0, 1], [0, 0]];
58 const origStride = 2;
59 const x = tf.tensor4d([
60 1.24, 1.66, 0.9, 1.39, 0.16, 0.27, 0.42, 0.61, 0.04, 0.17, 0.34, 0.28,
61 0., 0.06, 0.14, 0.24
62 ], inputShape);
63 const w = tf.tensor4d([0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.], [fSize, fSize, origInputDepth, origOutputDepth]);
64 const result = tf.conv2dTranspose(x, w, [1, 3, 3, 1], origStride, origPad);
65 const expected = [7.63, 28.39, 2.94, 49.15, 69.91, 14.62, 1.69, 5.01, 1.06];
66 expect(result.shape).toEqual([1, 3, 3, 1]);
67 expectArraysClose(await result.data(), expected);
68 });
69 it('input=2x2x1,d2=1,f=2,s=1,p=0, batch=2', async () => {
70 const origInputDepth = 1;
71 const origOutputDepth = 1;
72 const inputShape = [2, 1, 1, origOutputDepth];
73 const fSize = 2;
74 const origPad = 0;
75 const origStride = 1;
76 const x = tf.tensor4d([2, 3], inputShape);
77 const w = tf.tensor4d([3, 1, 5, 0], [fSize, fSize, origInputDepth, origOutputDepth]);
78 const result = tf.conv2dTranspose(x, w, [2, 2, 2, 1], origStride, origPad);
79 const expected = [6, 2, 10, 0, 9, 3, 15, 0];
80 expect(result.shape).toEqual([2, 2, 2, 1]);
81 expectArraysClose(await result.data(), expected);
82 });
83 it('input=2x2x2,output=3x3x2,f=2,s=2,inDepth=2,p=same', async () => {
84 const origInputDepth = 2;
85 const origOutputDepth = 2;
86 const inputShape = [1, 2, 2, origOutputDepth];
87 const fSize = 2;
88 const origPad = 'same';
89 const origStride = 2;
90 const x = tf.tensor4d([0., 1., 2., 3., 4., 5., 6., 7.], inputShape);
91 const w = tf.tensor4d([0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.], [fSize, fSize, origInputDepth, origOutputDepth]);
92 const result = tf.conv2dTranspose(x, w, [1, 3, 3, origInputDepth], origStride, origPad);
93 const expected = [1, 3, 5, 7, 3, 13, 9, 11, 13, 15, 43, 53, 5, 23, 41, 59, 7, 33.];
94 expect(result.shape).toEqual([1, 3, 3, origInputDepth]);
95 expectArraysClose(await result.data(), expected);
96 });
97 it('throws when dimRoundingMode is set and pad is same', async () => {
98 const origInputDepth = 1;
99 const origOutputDepth = 4;
100 const inputShape = [1, 2, 2, origOutputDepth];
101 const fSize = 2;
102 const origPad = 'same';
103 const origStride = 2;
104 const dimRoundingMode = 'round';
105 const x = tf.tensor4d([
106 1.24, 1.66, 0.9, 1.39, 0.16, 0.27, 0.42, 0.61, 0.04, 0.17, 0.34, 0.28,
107 0., 0.06, 0.14, 0.24
108 ], inputShape);
109 const w = tf.tensor4d([0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.], [fSize, fSize, origInputDepth, origOutputDepth]);
110 expect(() => tf.conv2dTranspose(x, w, [1, 3, 3, 1], origStride, origPad, dimRoundingMode))
111 .toThrowError();
112 });
113 it('throws when dimRoundingMode is set and pad is valid', async () => {
114 const origInputDepth = 1;
115 const origOutputDepth = 4;
116 const inputShape = [1, 2, 2, origOutputDepth];
117 const fSize = 2;
118 const origPad = 'valid';
119 const origStride = 2;
120 const dimRoundingMode = 'round';
121 const x = tf.tensor4d([
122 1.24, 1.66, 0.9, 1.39, 0.16, 0.27, 0.42, 0.61, 0.04, 0.17, 0.34, 0.28,
123 0., 0.06, 0.14, 0.24
124 ], inputShape);
125 const w = tf.tensor4d([0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13., 14., 15.], [fSize, fSize, origInputDepth, origOutputDepth]);
126 expect(() => tf.conv2dTranspose(x, w, [1, 3, 3, 1], origStride, origPad, dimRoundingMode))
127 .toThrowError();
128 });
129 it('throws when dimRoundingMode is set and pad is a non-integer number', async () => {
130 const origInputDepth = 1;
131 const origOutputDepth = 4;
132 const inputShape = [1, 2, 2, origOutputDepth];
133 const fSize = 2;
134 const origPad = 1.2;
135 const origStride = 2;
136 const dimRoundingMode = 'round';
137 const x = tf.tensor4d([
138 1.24, 1.66, 0.9, 1.39, 0.16, 0.27, 0.42, 0.61, 0.04, 0.17, 0.34,
139 0.28, 0., 0.06, 0.14, 0.24
140 ], inputShape);
141 const w = tf.tensor4d([
142 0., 1., 2., 3., 4., 5., 6., 7., 8.,
143 9., 10., 11., 12., 13., 14., 15.
144 ], [fSize, fSize, origInputDepth, origOutputDepth]);
145 expect(() => tf.conv2dTranspose(x, w, [1, 3, 3, 1], origStride, origPad, dimRoundingMode))
146 .toThrowError();
147 });
148 it('throws when dimRoundingMode is set and pad is explicit by non-integer ' +
149 'number', async () => {
150 const origInputDepth = 1;
151 const origOutputDepth = 4;
152 const inputShape = [1, 2, 2, origOutputDepth];
153 const fSize = 2;
154 const origPad = [[0, 0], [0, 1.1], [0, 1], [0, 0]];
155 const origStride = 2;
156 const dimRoundingMode = 'round';
157 const x = tf.tensor4d([
158 1.24, 1.66, 0.9, 1.39, 0.16, 0.27, 0.42, 0.61, 0.04, 0.17, 0.34,
159 0.28, 0., 0.06, 0.14, 0.24
160 ], inputShape);
161 const w = tf.tensor4d([
162 0., 1., 2., 3., 4., 5., 6., 7., 8.,
163 9., 10., 11., 12., 13., 14., 15.
164 ], [fSize, fSize, origInputDepth, origOutputDepth]);
165 expect(() => tf.conv2dTranspose(x, w, [1, 3, 3, 1], origStride, origPad, dimRoundingMode))
166 .toThrowError();
167 });
168 // Reference (Python) TensorFlow code:
169 //
170 // ```py
171 // import numpy as np
172 // import tensorflow as tf
173 //
174 // tf.enable_eager_execution()
175 //
176 // x = tf.constant(np.array([[
177 // [[-0.14656299], [0.32942239], [-1.90302866]],
178 // [[-0.06487813], [-2.02637842], [-1.83669377]],
179 // [[0.82650784], [-0.89249092], [0.01207666]]
180 // ]]).astype(np.float32))
181 // filt = tf.constant(np.array([
182 // [[[-0.48280062], [1.26770487]], [[-0.83083738], [0.54341856]]],
183 // [[[-0.274904], [0.73111374]], [[2.01885189], [-2.68975237]]]
184 // ]).astype(np.float32))
185 //
186 // with tf.GradientTape() as g:
187 // g.watch(x)
188 // g.watch(filt)
189 // y = tf.keras.backend.conv2d_transpose(x, filt, [1, 4, 4, 2])
190 // print(y)
191 // (x_grad, filt_grad) = g.gradient(y, [x, filt])
192 //
193 // print("x_grad = %s" % x_grad)
194 // print("filt_grad = %s" % filt_grad)
195 // ```
196 it('gradient with clones input=[1,3,3,1] f=[2,2,2,1] s=1 padding=valid', async () => {
197 const inputDepth = 1;
198 const outputDepth = 2;
199 const inputShape = [1, 3, 3, inputDepth];
200 const filterSize = 2;
201 const stride = 1;
202 const pad = 'valid';
203 const filterShape = [filterSize, filterSize, outputDepth, inputDepth];
204 const x = tf.tensor4d([[
205 [[-0.14656299], [0.32942239], [-1.90302866]],
206 [[-0.06487813], [-2.02637842], [-1.83669377]],
207 [[0.82650784], [-0.89249092], [0.01207666]]
208 ]], inputShape);
209 const filt = tf.tensor4d([
210 [[[-0.48280062], [1.26770487]], [[-0.83083738], [0.54341856]]],
211 [[[-0.274904], [0.73111374]], [[2.01885189], [-2.68975237]]]
212 ], filterShape);
213 const grads = tf.grads((x, filter) => tf.conv2dTranspose(x.clone(), filter.clone(), [1, 4, 4, outputDepth], stride, pad)
214 .clone());
215 const dy = tf.ones([1, 4, 4, outputDepth]);
216 const [xGrad, filtGrad] = grads([x, filt], dy);
217 const expectedXGrad = tf.ones([1, 3, 3, 1]).mul(tf.scalar(0.2827947));
218 expectArraysClose(await xGrad.data(), await expectedXGrad.data());
219 const expectedFiltGrad = tf.ones([2, 2, 2, 1]).mul(tf.scalar(-5.70202599));
220 expectArraysClose(await filtGrad.data(), await expectedFiltGrad.data());
221 });
222 // Reference (Python) TensorFlow code:
223 //
224 // ```py
225 // import numpy as np
226 // import tensorflow as tf
227 //
228 // tf.enable_eager_execution()
229 //
230 // x = tf.constant(np.array([
231 // [[[-0.36541713], [-0.53973116]], [[0.01731674], [0.90227772]]]
232 // ]).astype(np.float32))
233 // filt = tf.constant(np.array([
234 // [[[-0.01423461], [-1.00267384]], [[1.61163029], [0.66302646]]],
235 // [[[-0.46900087], [-0.78649444]], [[0.87780536], [-0.84551637]]]
236 // ]).astype(np.float32))
237 //
238 // with tf.GradientTape() as g:
239 // g.watch(x)
240 // g.watch(filt)
241 // y = tf.keras.backend.conv2d_transpose(x, filt, [1, 4, 4, 2], strides=(2,
242 // 2)) print(y)
243 // (x_grad, filt_grad) = g.gradient(y, [x, filt])
244 //
245 // print("x_grad = %s" % -x_grad)
246 // print("filt_grad = %s" % -filt_grad)
247 // ```
248 it('gradient input=[1,2,2,1] f=[2,2,2,1] s=[2,2] padding=valid', async () => {
249 const inputDepth = 1;
250 const outputDepth = 2;
251 const inputShape = [1, 2, 2, inputDepth];
252 const filterSize = 2;
253 const stride = [2, 2];
254 const pad = 'valid';
255 const filterShape = [filterSize, filterSize, outputDepth, inputDepth];
256 const x = tf.tensor4d([[[[-0.36541713], [-0.53973116]], [[0.01731674], [0.90227772]]]], inputShape);
257 const filt = tf.tensor4d([
258 [[[-0.01423461], [-1.00267384]], [[1.61163029], [0.66302646]]],
259 [[[-0.46900087], [-0.78649444]], [[0.87780536], [-0.84551637]]]
260 ], filterShape);
261 const grads = tf.grads((x, filter) => tf.conv2dTranspose(x, filter, [1, 4, 4, outputDepth], stride, pad));
262 const dy = tf.ones([1, 4, 4, outputDepth]).mul(tf.scalar(-1));
263 const [xGrad, filtGrad] = grads([x, filt], dy);
264 const expectedXGrad = tf.ones([1, 2, 2, 1]).mul(tf.scalar(-0.03454196));
265 expectArraysClose(await xGrad.data(), await expectedXGrad.data());
266 expect(xGrad.shape).toEqual([1, 2, 2, 1]);
267 const expectedFiltGrad = tf.ones([2, 2, 2, 1]).mul(tf.scalar(-0.01444618));
268 expectArraysClose(await filtGrad.data(), await expectedFiltGrad.data());
269 expect(filtGrad.shape).toEqual([2, 2, 2, 1]);
270 });
271 // Reference (Python) TensorFlow code:
272 //
273 // ```py
274 // import numpy as np
275 // import tensorflow as tf
276 //
277 // tf.enable_eager_execution()
278 //
279 // x = tf.constant(np.array([[
280 // [[1.52433065], [-0.77053435], [-0.64562341]],
281 // [[0.77962889], [1.58413887], [-0.25581856]],
282 // [[-0.58966221], [0.05411662], [0.70749138]]
283 // ]]).astype(np.float32))
284 // filt = tf.constant(np.array([
285 // [[[0.11178388], [-0.96654977]], [[1.21021296], [0.84121729]]],
286 // [[[0.34968338], [-0.42306114]], [[1.27395733], [-1.09014535]]]
287 // ]).astype(np.float32))
288 //
289 // with tf.GradientTape() as g:
290 // g.watch(x)
291 // g.watch(filt)
292 // y = tf.keras.backend.conv2d_transpose(
293 // x, filt, [1, 3, 3, 2], strides=(1, 1), padding='same')
294 // (x_grad, filt_grad) = g.gradient(y, [x, filt])
295 //
296 // print("x_grad = %s" % x_grad)
297 // print("filt_grad = %s" % filt_grad)
298 // ```
299 it('gradient input=[1,3,3,1] f=[2,2,2,1] s=[1,1] padding=same', async () => {
300 const inputDepth = 1;
301 const outputDepth = 2;
302 const inputShape = [1, 3, 3, inputDepth];
303 const filterSize = 2;
304 const stride = [1, 1];
305 const pad = 'same';
306 const filterShape = [filterSize, filterSize, outputDepth, inputDepth];
307 const x = tf.tensor4d([[
308 [[1.52433065], [-0.77053435], [-0.64562341]],
309 [[0.77962889], [1.58413887], [-0.25581856]],
310 [[-0.58966221], [0.05411662], [0.70749138]]
311 ]], inputShape);
312 const filt = tf.tensor4d([
313 [[[0.11178388], [-0.96654977]], [[1.21021296], [0.84121729]]],
314 [[[0.34968338], [-0.42306114]], [[1.27395733], [-1.09014535]]]
315 ], filterShape);
316 const grads = tf.grads((x, filter) => tf.conv2dTranspose(x, filter, [1, 3, 3, outputDepth], stride, pad));
317 const dy = tf.ones([1, 3, 3, outputDepth]);
318 const [xGrad, filtGrad] = grads([x, filt], dy);
319 expectArraysClose(await xGrad.array(), [[
320 [[1.30709858], [1.30709858], [-0.92814366]],
321 [[1.30709858], [1.30709858], [-0.92814366]],
322 [[1.19666437], [1.19666437], [-0.85476589]]
323 ]]);
324 expectArraysClose(await filtGrad.array(), [
325 [[[2.38806788], [2.38806788]], [[2.58201847], [2.58201847]]],
326 [[[2.2161221], [2.2161221]], [[3.11756406], [3.11756406]]]
327 ]);
328 });
329 it('gradient input=[1,3,3,1] f=[2,2,2,1] s=[1,1] p=explicit', async () => {
330 const inputDepth = 1;
331 const outputDepth = 2;
332 const inputShape = [1, 3, 3, inputDepth];
333 const filterSize = 2;
334 const stride = [1, 1];
335 const pad = [[0, 0], [0, 1], [0, 1], [0, 0]];
336 const filterShape = [filterSize, filterSize, outputDepth, inputDepth];
337 const x = tf.tensor4d([[
338 [[1.52433065], [-0.77053435], [-0.64562341]],
339 [[0.77962889], [1.58413887], [-0.25581856]],
340 [[-0.58966221], [0.05411662], [0.70749138]]
341 ]], inputShape);
342 const filt = tf.tensor4d([
343 [[[0.11178388], [-0.96654977]], [[1.21021296], [0.84121729]]],
344 [[[0.34968338], [-0.42306114]], [[1.27395733], [-1.09014535]]]
345 ], filterShape);
346 const grads = tf.grads((x, filter) => tf.conv2dTranspose(x, filter, [1, 3, 3, outputDepth], stride, pad));
347 const dy = tf.ones([1, 3, 3, outputDepth]);
348 const [xGrad, filtGrad] = grads([x, filt], dy);
349 expectArraysClose(await xGrad.array(), [[
350 [[1.30709858], [1.30709858], [-0.92814366]],
351 [[1.30709858], [1.30709858], [-0.92814366]],
352 [[1.19666437], [1.19666437], [-0.85476589]]
353 ]]);
354 expectArraysClose(await filtGrad.array(), [
355 [[[2.38806788], [2.38806788]], [[2.58201847], [2.58201847]]],
356 [[[2.2161221], [2.2161221]], [[3.11756406], [3.11756406]]]
357 ]);
358 });
359 // Reference (Python) TensorFlow code:
360 //
361 // ```py
362 // import numpy as np
363 // import tensorflow as tf
364 //
365 // tf.enable_eager_execution()
366 //
367 // x = tf.constant(np.array([[
368 // [[1.52433065], [-0.77053435]], [[0.77962889], [1.58413887]],
369 // ]]).astype(np.float32))
370 // filt = tf.constant(np.array([
371 // [[[0.11178388], [-0.96654977]], [[1.21021296], [0.84121729]]],
372 // [[[0.34968338], [-0.42306114]], [[1.27395733], [-1.09014535]]]
373 // ]).astype(np.float32))
374 //
375 // with tf.GradientTape() as g:
376 // g.watch(x)
377 // g.watch(filt)
378 // y = tf.keras.backend.conv2d_transpose(
379 // x, filt, [1, 3, 3, 2], strides=(2, 2), padding='same')
380 // print(y.shape)
381 // (x_grad, filt_grad) = g.gradient(y, [x, filt])
382 //
383 // print("x_grad = %s" % x_grad)
384 // print("filt_grad = %s" % filt_grad)
385 // ```
386 it('gradient input=[1,2,2,2] f=[2,2,2,1] s=[2,2] padding=same', async () => {
387 const inputDepth = 2;
388 const outputDepth = 2;
389 const inputShape = [1, 2, 2, inputDepth];
390 const filterSize = 2;
391 const stride = [2, 2];
392 const pad = 'same';
393 const filterShape = [filterSize, filterSize, outputDepth, inputDepth];
394 const x = tf.tensor4d([[
395 [[-1.81506593, 1.00900095], [-0.05199118, 0.26311377]],
396 [[-1.18469792, -0.34780521], [2.04971242, -0.65154692]]
397 ]], inputShape);
398 const filt = tf.tensor4d([
399 [
400 [[0.19529686, -0.79594708], [0.70314057, -0.06081263]],
401 [[0.28724744, 0.88522715], [-0.51824096, -0.97120989]]
402 ],
403 [
404 [[0.51872197, -1.17569193], [1.28316791, -0.81225092]],
405 [[-0.44221532, 0.70058174], [-0.4849217, 0.03806348]]
406 ]
407 ], filterShape);
408 const grads = tf.grads((x, filter) => tf.conv2dTranspose(x, filter, [1, 3, 3, outputDepth], stride, pad));
409 const dy = tf.ones([1, 3, 3, outputDepth]);
410 const [xGrad, filtGrad] = grads([x, filt], dy);
411 expectArraysClose(await xGrad.data(), [
412 1.54219678, -2.19204008, 2.70032732, -2.84470257, 0.66744391, -0.94274245,
413 0.89843743, -0.85675972
414 ]);
415 expect(xGrad.shape).toEqual([1, 2, 2, 2]);
416 expectArraysClose(await filtGrad.data(), [
417 -1.00204261, 0.27276259, -1.00204261, 0.27276259, -2.99976385, 0.66119574,
418 -2.99976385, 0.66119574, -1.86705711, 1.27211472, -1.86705711, 1.27211472,
419 -1.81506593, 1.00900095, -1.81506593, 1.00900095
420 ]);
421 expect(filtGrad.shape).toEqual([2, 2, 2, 2]);
422 });
423 it('throws when x is not rank 3', () => {
424 const origInputDepth = 1;
425 const origOutputDepth = 1;
426 const fSize = 2;
427 const origPad = 0;
428 const origStride = 1;
429 // tslint:disable-next-line:no-any
430 const x = tf.tensor2d([2, 2], [2, 1]);
431 const w = tf.tensor4d([3, 1, 5, 0], [fSize, fSize, origInputDepth, origOutputDepth]);
432 expect(() => tf.conv2dTranspose(x, w, [2, 2, 1], origStride, origPad))
433 .toThrowError();
434 });
435 it('throws when weights is not rank 4', () => {
436 const origInputDepth = 1;
437 const origOutputDepth = 1;
438 const inputShape = [1, 1, origOutputDepth];
439 const fSize = 2;
440 const origPad = 0;
441 const origStride = 1;
442 const x = tf.tensor3d([2], inputShape);
443 // tslint:disable-next-line:no-any
444 const w = tf.tensor3d([3, 1, 5, 0], [fSize, fSize, origInputDepth]);
445 expect(() => tf.conv2dTranspose(x, w, [2, 2, 1], origStride, origPad))
446 .toThrowError();
447 });
448 it('throws when x depth does not match weights original output depth', () => {
449 const origInputDepth = 1;
450 const origOutputDepth = 2;
451 const wrongOrigOutputDepth = 3;
452 const inputShape = [1, 1, origOutputDepth];
453 const fSize = 2;
454 const origPad = 0;
455 const origStride = 1;
456 const x = tf.tensor3d([2, 2], inputShape);
457 const w = tf.randomNormal([fSize, fSize, origInputDepth, wrongOrigOutputDepth]);
458 expect(() => tf.conv2dTranspose(x, w, [2, 2, 2], origStride, origPad))
459 .toThrowError();
460 });
461 it('throws when passed x as a non-tensor', () => {
462 const origInputDepth = 1;
463 const origOutputDepth = 1;
464 const fSize = 2;
465 const origPad = 0;
466 const origStride = 1;
467 const w = tf.tensor4d([3, 1, 5, 0], [fSize, fSize, origInputDepth, origOutputDepth]);
468 expect(() => tf.conv2dTranspose({}, w, [2, 2, 1], origStride, origPad))
469 .toThrowError(/Argument 'x' passed to 'conv2dTranspose' must be a Tensor/);
470 });
471 it('throws when passed filter as a non-tensor', () => {
472 const origOutputDepth = 1;
473 const inputShape = [1, 1, origOutputDepth];
474 const origPad = 0;
475 const origStride = 1;
476 const x = tf.tensor3d([2], inputShape);
477 expect(() => tf.conv2dTranspose(x, {}, [2, 2, 1], origStride, origPad))
478 .toThrowError(/Argument 'filter' passed to 'conv2dTranspose' must be a Tensor/);
479 });
480 it('accepts a tensor-like object', async () => {
481 const origPad = 0;
482 const origStride = 1;
483 const x = [[[2]]]; // 1x1x1
484 const w = [[[[3]], [[1]]], [[[5]], [[0]]]]; // 2x2x1x1
485 const result = tf.conv2dTranspose(x, w, [2, 2, 1], origStride, origPad);
486 const expected = [6, 2, 10, 0];
487 expect(result.shape).toEqual([2, 2, 1]);
488 expectArraysClose(await result.data(), expected);
489 });
490});
491//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udjJkX3RyYW5zcG9zZV90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvY29udjJkX3RyYW5zcG9zZV90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQy9CLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFHL0MsaUJBQWlCLENBQUMsaUJBQWlCLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRTtJQUNsRCxFQUFFLENBQUMsOEJBQThCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDNUMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxDQUFDO1FBQ3pCLE1BQU0sZUFBZSxHQUFHLENBQUMsQ0FBQztRQUMxQixNQUFNLFVBQVUsR0FBNkIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3JFLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQztRQUNoQixNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFDbEIsTUFBTSxVQUFVLEdBQUcsQ0FBQyxDQUFDO1FBRXJCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUN2QyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUNqQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxjQUFjLEVBQUUsZUFBZSxDQUFDLENBQUMsQ0FBQztRQUVuRSxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsRUFB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Q0FBQyxDQUFDO2FBQ3pELFlBQVksQ0FDVCxnRUFBZ0UsQ0FBQyxDQUFDO0lBQzVFLENBQUMsQ0FBQyxDQUFDO0lBRUgsRUFBRSxDQUFDLDhCQUE4QixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzVDLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQztRQUNsQixNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFFckIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQTJCLFFBQVE7UUFDckQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBRSxVQUFVO1FBRXZELE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxlQUFlLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hFLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFL0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEMsaUJBQWlCLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0ICogYXMgdGYgZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHtBTExfRU5WUywgZGVzY3JpYmVXaXRoRmxhZ3N9IGZyb20gJy4uL2phc21pbmVfdXRpbCc7XG5pbXBvcnQge2V4cGVjdEFycmF5c0Nsb3NlfSBmcm9tICcuLi90ZXN0X3V0aWwnO1xuaW1wb3J0IHtSYW5rfSBmcm9tICcuLi90eXBlcyc7XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdjb252MmRUcmFuc3Bvc2UnLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgnaW5wdXQ9MngyeDEsZDI9MSxmPTIscz0xLHA9MCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvcmlnSW5wdXREZXB0aCA9IDE7XG4gICAgY29uc3Qgb3JpZ091dHB1dERlcHRoID0gMTtcbiAgICBjb25zdCBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBbMSwgMSwgb3JpZ091dHB1dERlcHRoXTtcbiAgICBjb25zdCBmU2l6ZSA9IDI7XG4gICAgY29uc3Qgb3JpZ1BhZCA9IDA7XG4gICAgY29uc3Qgb3JpZ1N0cmlkZSA9IDE7XG5cbiAgICBjb25zdCB4ID0gdGYudGVuc29yM2QoWzJdLCBpbnB1dFNoYXBlKTtcbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFszLCAxLCA1LCAwXSwgW2ZTaXplLCBmU2l6ZSwgb3JpZ0lucHV0RGVwdGgsIG9yaWdPdXRwdXREZXB0aF0pO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuY29udjJkVHJhbnNwb3NlKHgsIHcsIFsyLCAyLCAxXSwgb3JpZ1N0cmlkZSwgb3JpZ1BhZCk7XG4gICAgY29uc3QgZXhwZWN0ZWQgPSBbNiwgMiwgMTAsIDBdO1xuXG4gICAgZXhwZWN0KHJlc3VsdC5zaGFwZSkudG9FcXVhbChbMiwgMiwgMV0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5kYXRhKCksIGV4cGVjdGVkKTtcbiAgfSk7XG5cbiAgaXQoJ2lucHV0PTN4M3gxLGQyPTEsZj0yLHM9MixwPXNhbWUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgb3JpZ0lucHV0RGVwdGggPSAxO1xuICAgIGNvbnN0IG9yaWdPdXRwdXREZXB0aCA9IDQ7XG4gICAgY29uc3QgaW5wdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPVxuICAgICAgICBbMSwgMiwgMiwgb3JpZ091dHB1dERlcHRoXTtcbiAgICBjb25zdCBmU2l6ZSA9IDI7XG4gICAgY29uc3Qgb3JpZ1BhZCA9ICdzYW1lJztcbiAgICBjb25zdCBvcmlnU3RyaWRlID0gMjtcblxuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgW1xuICAgICAgICAgIDEuMjQsIDEuNjYsIDAuOSwgMS4zOSwgMC4xNiwgMC4yNywgMC40MiwgMC42MSwgMC4wNCwgMC4xNywgMC4zNCwgMC4yOCxcbiAgICAgICAgICAwLiwgMC4wNiwgMC4xNCwgMC4yNFxuICAgICAgICBdLFxuICAgICAgICBpbnB1dFNoYXBlKTtcbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFswLiwgMS4sIDIuLCAzLiwgNC4sIDUuLCA2LiwgNy4sIDguLCA5LiwgMTAuLCAxMS4sIDEyLiwgMTMuLCAxNC4sIDE1Ll0sXG4gICAgICAgIFtmU2l6ZSwgZlNpemUsIG9yaWdJbnB1dERlcHRoLCBvcmlnT3V0cHV0RGVwdGhdKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmNvbnYyZFRyYW5zcG9zZSh4LCB3LCBbMSwgMywgMywgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQpO1xuICAgIGNvbnN0IGV4cGVjdGVkID0gWzcuNjMsIDI4LjM5LCAyLjk0LCA0OS4xNSwgNjkuOTEsIDE0LjYyLCAxLjY5LCA1LjAxLCAxLjA2XTtcblxuICAgIGV4cGVjdChyZXN1bHQuc2hhcGUpLnRvRXF1YWwoWzEsIDMsIDMsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBleHBlY3RlZCk7XG4gIH0pO1xuXG4gIGl0KCdpbnB1dD0zeDN4MSxkMj0xLGY9MixzPTIscD1leHBsaWNpdCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvcmlnSW5wdXREZXB0aCA9IDE7XG4gICAgY29uc3Qgb3JpZ091dHB1dERlcHRoID0gNDtcbiAgICBjb25zdCBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9XG4gICAgICAgIFsxLCAyLCAyLCBvcmlnT3V0cHV0RGVwdGhdO1xuICAgIGNvbnN0IGZTaXplID0gMjtcbiAgICBjb25zdCBvcmlnUGFkID1cbiAgICAgICAgW1swLCAwXSwgWzAsIDFdLCBbMCwgMV0sIFswLCAwXV0gYXMgdGYuYmFja2VuZF91dGlsLkV4cGxpY2l0UGFkZGluZztcbiAgICBjb25zdCBvcmlnU3RyaWRlID0gMjtcblxuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgW1xuICAgICAgICAgIDEuMjQsIDEuNjYsIDAuOSwgMS4zOSwgMC4xNiwgMC4yNywgMC40MiwgMC42MSwgMC4wNCwgMC4xNywgMC4zNCwgMC4yOCxcbiAgICAgICAgICAwLiwgMC4wNiwgMC4xNCwgMC4yNFxuICAgICAgICBdLFxuICAgICAgICBpbnB1dFNoYXBlKTtcbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFswLiwgMS4sIDIuLCAzLiwgNC4sIDUuLCA2LiwgNy4sIDguLCA5LiwgMTAuLCAxMS4sIDEyLiwgMTMuLCAxNC4sIDE1Ll0sXG4gICAgICAgIFtmU2l6ZSwgZlNpemUsIG9yaWdJbnB1dERlcHRoLCBvcmlnT3V0cHV0RGVwdGhdKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmNvbnYyZFRyYW5zcG9zZSh4LCB3LCBbMSwgMywgMywgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQpO1xuICAgIGNvbnN0IGV4cGVjdGVkID0gWzcuNjMsIDI4LjM5LCAyLjk0LCA0OS4xNSwgNjkuOTEsIDE0LjYyLCAxLjY5LCA1LjAxLCAxLjA2XTtcblxuICAgIGV4cGVjdChyZXN1bHQuc2hhcGUpLnRvRXF1YWwoWzEsIDMsIDMsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBleHBlY3RlZCk7XG4gIH0pO1xuXG4gIGl0KCdpbnB1dD0yeDJ4MSxkMj0xLGY9MixzPTEscD0wLCBiYXRjaD0yJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG9yaWdJbnB1dERlcHRoID0gMTtcbiAgICBjb25zdCBvcmlnT3V0cHV0RGVwdGggPSAxO1xuICAgIGNvbnN0IGlucHV0U2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID1cbiAgICAgICAgWzIsIDEsIDEsIG9yaWdPdXRwdXREZXB0aF07XG4gICAgY29uc3QgZlNpemUgPSAyO1xuICAgIGNvbnN0IG9yaWdQYWQgPSAwO1xuICAgIGNvbnN0IG9yaWdTdHJpZGUgPSAxO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFsyLCAzXSwgaW5wdXRTaGFwZSk7XG4gICAgY29uc3QgdyA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbMywgMSwgNSwgMF0sIFtmU2l6ZSwgZlNpemUsIG9yaWdJbnB1dERlcHRoLCBvcmlnT3V0cHV0RGVwdGhdKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmNvbnYyZFRyYW5zcG9zZSh4LCB3LCBbMiwgMiwgMiwgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQpO1xuICAgIGNvbnN0IGV4cGVjdGVkID0gWzYsIDIsIDEwLCAwLCA5LCAzLCAxNSwgMF07XG5cbiAgICBleHBlY3QocmVzdWx0LnNoYXBlKS50b0VxdWFsKFsyLCAyLCAyLCAxXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgZXhwZWN0ZWQpO1xuICB9KTtcblxuICBpdCgnaW5wdXQ9MngyeDIsb3V0cHV0PTN4M3gyLGY9MixzPTIsaW5EZXB0aD0yLHA9c2FtZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvcmlnSW5wdXREZXB0aCA9IDI7XG4gICAgY29uc3Qgb3JpZ091dHB1dERlcHRoID0gMjtcbiAgICBjb25zdCBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9XG4gICAgICAgIFsxLCAyLCAyLCBvcmlnT3V0cHV0RGVwdGhdO1xuICAgIGNvbnN0IGZTaXplID0gMjtcbiAgICBjb25zdCBvcmlnUGFkID0gJ3NhbWUnO1xuICAgIGNvbnN0IG9yaWdTdHJpZGUgPSAyO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFswLiwgMS4sIDIuLCAzLiwgNC4sIDUuLCA2LiwgNy5dLCBpbnB1dFNoYXBlKTtcbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFswLiwgMS4sIDIuLCAzLiwgNC4sIDUuLCA2LiwgNy4sIDguLCA5LiwgMTAuLCAxMS4sIDEyLiwgMTMuLCAxNC4sIDE1Ll0sXG4gICAgICAgIFtmU2l6ZSwgZlNpemUsIG9yaWdJbnB1dERlcHRoLCBvcmlnT3V0cHV0RGVwdGhdKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmNvbnYyZFRyYW5zcG9zZShcbiAgICAgICAgeCwgdywgWzEsIDMsIDMsIG9yaWdJbnB1dERlcHRoXSwgb3JpZ1N0cmlkZSwgb3JpZ1BhZCk7XG4gICAgY29uc3QgZXhwZWN0ZWQgPVxuICAgICAgICBbMSwgMywgNSwgNywgMywgMTMsIDksIDExLCAxMywgMTUsIDQzLCA1MywgNSwgMjMsIDQxLCA1OSwgNywgMzMuXTtcblxuICAgIGV4cGVjdChyZXN1bHQuc2hhcGUpLnRvRXF1YWwoWzEsIDMsIDMsIG9yaWdJbnB1dERlcHRoXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgZXhwZWN0ZWQpO1xuICB9KTtcblxuICBpdCgndGhyb3dzIHdoZW4gZGltUm91bmRpbmdNb2RlIGlzIHNldCBhbmQgcGFkIGlzIHNhbWUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgb3JpZ0lucHV0RGVwdGggPSAxO1xuICAgIGNvbnN0IG9yaWdPdXRwdXREZXB0aCA9IDQ7XG4gICAgY29uc3QgaW5wdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPVxuICAgICAgICBbMSwgMiwgMiwgb3JpZ091dHB1dERlcHRoXTtcbiAgICBjb25zdCBmU2l6ZSA9IDI7XG4gICAgY29uc3Qgb3JpZ1BhZCA9ICdzYW1lJztcbiAgICBjb25zdCBvcmlnU3RyaWRlID0gMjtcbiAgICBjb25zdCBkaW1Sb3VuZGluZ01vZGUgPSAncm91bmQnO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbXG4gICAgICAgICAgMS4yNCwgMS42NiwgMC45LCAxLjM5LCAwLjE2LCAwLjI3LCAwLjQyLCAwLjYxLCAwLjA0LCAwLjE3LCAwLjM0LCAwLjI4LFxuICAgICAgICAgIDAuLCAwLjA2LCAwLjE0LCAwLjI0XG4gICAgICAgIF0sXG4gICAgICAgIGlucHV0U2hhcGUpO1xuICAgIGNvbnN0IHcgPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgWzAuLCAxLiwgMi4sIDMuLCA0LiwgNS4sIDYuLCA3LiwgOC4sIDkuLCAxMC4sIDExLiwgMTIuLCAxMy4sIDE0LiwgMTUuXSxcbiAgICAgICAgW2ZTaXplLCBmU2l6ZSwgb3JpZ0lucHV0RGVwdGgsIG9yaWdPdXRwdXREZXB0aF0pO1xuXG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5jb252MmRUcmFuc3Bvc2UoXG4gICAgICAgICAgICB4LCB3LCBbMSwgMywgMywgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQsIGRpbVJvdW5kaW5nTW9kZSkpXG4gICAgICAgIC50b1Rocm93RXJyb3IoKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIGRpbVJvdW5kaW5nTW9kZSBpcyBzZXQgYW5kIHBhZCBpcyB2YWxpZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBvcmlnSW5wdXREZXB0aCA9IDE7XG4gICAgY29uc3Qgb3JpZ091dHB1dERlcHRoID0gNDtcbiAgICBjb25zdCBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9XG4gICAgICAgIFsxLCAyLCAyLCBvcmlnT3V0cHV0RGVwdGhdO1xuICAgIGNvbnN0IGZTaXplID0gMjtcbiAgICBjb25zdCBvcmlnUGFkID0gJ3ZhbGlkJztcbiAgICBjb25zdCBvcmlnU3RyaWRlID0gMjtcbiAgICBjb25zdCBkaW1Sb3VuZGluZ01vZGUgPSAncm91bmQnO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbXG4gICAgICAgICAgMS4yNCwgMS42NiwgMC45LCAxLjM5LCAwLjE2LCAwLjI3LCAwLjQyLCAwLjYxLCAwLjA0LCAwLjE3LCAwLjM0LCAwLjI4LFxuICAgICAgICAgIDAuLCAwLjA2LCAwLjE0LCAwLjI0XG4gICAgICAgIF0sXG4gICAgICAgIGlucHV0U2hhcGUpO1xuICAgIGNvbnN0IHcgPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgWzAuLCAxLiwgMi4sIDMuLCA0LiwgNS4sIDYuLCA3LiwgOC4sIDkuLCAxMC4sIDExLiwgMTIuLCAxMy4sIDE0LiwgMTUuXSxcbiAgICAgICAgW2ZTaXplLCBmU2l6ZSwgb3JpZ0lucHV0RGVwdGgsIG9yaWdPdXRwdXREZXB0aF0pO1xuXG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5jb252MmRUcmFuc3Bvc2UoXG4gICAgICAgICAgICB4LCB3LCBbMSwgMywgMywgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQsIGRpbVJvdW5kaW5nTW9kZSkpXG4gICAgICAgIC50b1Rocm93RXJyb3IoKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIGRpbVJvdW5kaW5nTW9kZSBpcyBzZXQgYW5kIHBhZCBpcyBhIG5vbi1pbnRlZ2VyIG51bWJlcicsXG4gICAgIGFzeW5jICgpID0+IHtcbiAgICAgICBjb25zdCBvcmlnSW5wdXREZXB0aCA9IDE7XG4gICAgICAgY29uc3Qgb3JpZ091dHB1dERlcHRoID0gNDtcbiAgICAgICBjb25zdCBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9XG4gICAgICAgICAgIFsxLCAyLCAyLCBvcmlnT3V0cHV0RGVwdGhdO1xuICAgICAgIGNvbnN0IGZTaXplID0gMjtcbiAgICAgICBjb25zdCBvcmlnUGFkID0gMS4yO1xuICAgICAgIGNvbnN0IG9yaWdTdHJpZGUgPSAyO1xuICAgICAgIGNvbnN0IGRpbVJvdW5kaW5nTW9kZSA9ICdyb3VuZCc7XG5cbiAgICAgICBjb25zdCB4ID0gdGYudGVuc29yNGQoXG4gICAgICAgICAgIFtcbiAgICAgICAgICAgICAxLjI0LCAxLjY2LCAwLjksIDEuMzksIDAuMTYsIDAuMjcsIDAuNDIsIDAuNjEsIDAuMDQsIDAuMTcsIDAuMzQsXG4gICAgICAgICAgICAgMC4yOCwgMC4sIDAuMDYsIDAuMTQsIDAuMjRcbiAgICAgICAgICAgXSxcbiAgICAgICAgICAgaW5wdXRTaGFwZSk7XG4gICAgICAgY29uc3QgdyA9IHRmLnRlbnNvcjRkKFxuICAgICAgICAgICBbXG4gICAgICAgICAgICAgMC4sIDEuLCAyLiwgMy4sIDQuLCA1LiwgNi4sIDcuLCA4LixcbiAgICAgICAgICAgICA5LiwgMTAuLCAxMS4sIDEyLiwgMTMuLCAxNC4sIDE1LlxuICAgICAgICAgICBdLFxuICAgICAgICAgICBbZlNpemUsIGZTaXplLCBvcmlnSW5wdXREZXB0aCwgb3JpZ091dHB1dERlcHRoXSk7XG5cbiAgICAgICBleHBlY3QoXG4gICAgICAgICAgICgpID0+IHRmLmNvbnYyZFRyYW5zcG9zZShcbiAgICAgICAgICAgICAgeCwgdywgWzEsIDMsIDMsIDFdLCBvcmlnU3RyaWRlLCBvcmlnUGFkLCBkaW1Sb3VuZGluZ01vZGUpKVxuICAgICAgICAgICAudG9UaHJvd0Vycm9yKCk7XG4gICAgIH0pO1xuXG4gIGl0KCd0aHJvd3Mgd2hlbiBkaW1Sb3VuZGluZ01vZGUgaXMgc2V0IGFuZCBwYWQgaXMgZXhwbGljaXQgYnkgbm9uLWludGVnZXIgJyArXG4gICAgICAgICAnbnVtYmVyJyxcbiAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgIGNvbnN0IG9yaWdJbnB1dERlcHRoID0gMTtcbiAgICAgICBjb25zdCBvcmlnT3V0cHV0RGVwdGggPSA0O1xuICAgICAgIGNvbnN0IGlucHV0U2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID1cbiAgICAgICAgICAgWzEsIDIsIDIsIG9yaWdPdXRwdXREZXB0aF07XG4gICAgICAgY29uc3QgZlNpemUgPSAyO1xuICAgICAgIGNvbnN0IG9yaWdQYWQgPSBbWzAsIDBdLCBbMCwgMS4xXSwgWzAsIDFdLCBbMCwgMF1dIGFzXG4gICAgICAgICAgIHRmLmJhY2tlbmRfdXRpbC5FeHBsaWNpdFBhZGRpbmc7XG4gICAgICAgY29uc3Qgb3JpZ1N0cmlkZSA9IDI7XG4gICAgICAgY29uc3QgZGltUm91bmRpbmdNb2RlID0gJ3JvdW5kJztcblxuICAgICAgIGNvbnN0IHggPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgICAgW1xuICAgICAgICAgICAgIDEuMjQsIDEuNjYsIDAuOSwgMS4zOSwgMC4xNiwgMC4yNywgMC40MiwgMC42MSwgMC4wNCwgMC4xNywgMC4zNCxcbiAgICAgICAgICAgICAwLjI4LCAwLiwgMC4wNiwgMC4xNCwgMC4yNFxuICAgICAgICAgICBdLFxuICAgICAgICAgICBpbnB1dFNoYXBlKTtcbiAgICAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgICAgIFtcbiAgICAgICAgICAgICAwLiwgMS4sIDIuLCAzLiwgNC4sIDUuLCA2LiwgNy4sIDguLFxuICAgICAgICAgICAgIDkuLCAxMC4sIDExLiwgMTIuLCAxMy4sIDE0LiwgMTUuXG4gICAgICAgICAgIF0sXG4gICAgICAgICAgIFtmU2l6ZSwgZlNpemUsIG9yaWdJbnB1dERlcHRoLCBvcmlnT3V0cHV0RGVwdGhdKTtcblxuICAgICAgIGV4cGVjdChcbiAgICAgICAgICAgKCkgPT4gdGYuY29udjJkVHJhbnNwb3NlKFxuICAgICAgICAgICAgICB4LCB3LCBbMSwgMywgMywgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQsIGRpbVJvdW5kaW5nTW9kZSkpXG4gICAgICAgICAgIC50b1Rocm93RXJyb3IoKTtcbiAgICAgfSk7XG5cbiAgLy8gUmVmZXJlbmNlIChQeXRob24pIFRlbnNvckZsb3cgY29kZTpcbiAgLy9cbiAgLy8gYGBgcHlcbiAgLy8gaW1wb3J0IG51bXB5IGFzIG5wXG4gIC8vIGltcG9ydCB0ZW5zb3JmbG93IGFzIHRmXG4gIC8vXG4gIC8vIHRmLmVuYWJsZV9lYWdlcl9leGVjdXRpb24oKVxuICAvL1xuICAvLyB4ID0gdGYuY29uc3RhbnQobnAuYXJyYXkoW1tcbiAgLy8gICAgIFtbLTAuMTQ2NTYyOTldLCBbMC4zMjk0MjIzOV0sIFstMS45MDMwMjg2Nl1dLFxuICAvLyAgICAgW1stMC4wNjQ4NzgxM10sIFstMi4wMjYzNzg0Ml0sIFstMS44MzY2OTM3N11dLFxuICAvLyAgICAgW1swLjgyNjUwNzg0XSwgWy0wLjg5MjQ5MDkyXSwgWzAuMDEyMDc2NjZdXVxuICAvLyBdXSkuYXN0eXBlKG5wLmZsb2F0MzIpKVxuICAvLyBmaWx0ID0gdGYuY29uc3RhbnQobnAuYXJyYXkoW1xuICAvLyAgICAgW1tbLTAuNDgyODAwNjJdLCBbMS4yNjc3MDQ4N11dLCBbWy0wLjgzMDgzNzM4XSwgWzAuNTQzNDE4NTZdXV0sXG4gIC8vICAgICBbW1stMC4yNzQ5MDRdLCBbMC43MzExMTM3NF1dLCBbWzIuMDE4ODUxODldLCBbLTIuNjg5NzUyMzddXV1cbiAgLy8gXSkuYXN0eXBlKG5wLmZsb2F0MzIpKVxuICAvL1xuICAvLyB3aXRoIHRmLkdyYWRpZW50VGFwZSgpIGFzIGc6XG4gIC8vICAgZy53YXRjaCh4KVxuICAvLyAgIGcud2F0Y2goZmlsdClcbiAgLy8gICB5ID0gdGYua2VyYXMuYmFja2VuZC5jb252MmRfdHJhbnNwb3NlKHgsIGZpbHQsIFsxLCA0LCA0LCAyXSlcbiAgLy8gICBwcmludCh5KVxuICAvLyAoeF9ncmFkLCBmaWx0X2dyYWQpID0gZy5ncmFkaWVudCh5LCBbeCwgZmlsdF0pXG4gIC8vXG4gIC8vIHByaW50KFwieF9ncmFkID0gJXNcIiAlIHhfZ3JhZClcbiAgLy8gcHJpbnQoXCJmaWx0X2dyYWQgPSAlc1wiICUgZmlsdF9ncmFkKVxuICAvLyBgYGBcbiAgaXQoJ2dyYWRpZW50IHdpdGggY2xvbmVzIGlucHV0PVsxLDMsMywxXSBmPVsyLDIsMiwxXSBzPTEgcGFkZGluZz12YWxpZCcsXG4gICAgIGFzeW5jICgpID0+IHtcbiAgICAgICBjb25zdCBpbnB1dERlcHRoID0gMTtcbiAgICAgICBjb25zdCBvdXRwdXREZXB0aCA9IDI7XG4gICAgICAgY29uc3QgaW5wdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPVxuICAgICAgICAgICBbMSwgMywgMywgaW5wdXREZXB0aF07XG4gICAgICAgY29uc3QgZmlsdGVyU2l6ZSA9IDI7XG4gICAgICAgY29uc3Qgc3RyaWRlID0gMTtcbiAgICAgICBjb25zdCBwYWQgPSAndmFsaWQnO1xuXG4gICAgICAgY29uc3QgZmlsdGVyU2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID1cbiAgICAgICAgICAgW2ZpbHRlclNpemUsIGZpbHRlclNpemUsIG91dHB1dERlcHRoLCBpbnB1dERlcHRoXTtcblxuICAgICAgIGNvbnN0IHggPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgICAgW1tcbiAgICAgICAgICAgICBbWy0wLjE0NjU2Mjk5XSwgWzAuMzI5NDIyMzldLCBbLTEuOTAzMDI4NjZdXSxcbiAgICAgICAgICAgICBbWy0wLjA2NDg3ODEzXSwgWy0yLjAyNjM3ODQyXSwgWy0xLjgzNjY5Mzc3XV0sXG4gICAgICAgICAgICAgW1swLjgyNjUwNzg0XSwgWy0wLjg5MjQ5MDkyXSwgWzAuMDEyMDc2NjZdXVxuICAgICAgICAgICBdXSxcbiAgICAgICAgICAgaW5wdXRTaGFwZSk7XG4gICAgICAgY29uc3QgZmlsdCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICAgICBbXG4gICAgICAgICAgICAgW1tbLTAuNDgyODAwNjJdLCBbMS4yNjc3MDQ4N11dLCBbWy0wLjgzMDgzNzM4XSwgWzAuNTQzNDE4NTZdXV0sXG4gICAgICAgICAgICAgW1tbLTAuMjc0OTA0XSwgWzAuNzMxMTEzNzRdXSwgW1syLjAxODg1MTg5XSwgWy0yLjY4OTc1MjM3XV1dXG4gICAgICAgICAgIF0sXG4gICAgICAgICAgIGZpbHRlclNoYXBlKTtcblxuICAgICAgIGNvbnN0IGdyYWRzID0gdGYuZ3JhZHMoXG4gICAgICAgICAgICh4OiB0Zi5UZW5zb3I0RCwgZmlsdGVyOiB0Zi5UZW5zb3I0RCkgPT5cbiAgICAgICAgICAgICAgIHRmLmNvbnYyZFRyYW5zcG9zZShcbiAgICAgICAgICAgICAgICAgICAgIHguY2xvbmUoKSwgZmlsdGVyLmNsb25lKCksIFsxLCA0LCA0LCBvdXRwdXREZXB0aF0sIHN0cmlkZSxcbiAgICAgICAgICAgICAgICAgICAgIHBhZClcbiAgICAgICAgICAgICAgICAgICAuY2xvbmUoKSk7XG4gICAgICAgY29uc3QgZHkgPSB0Zi5vbmVzKFsxLCA0LCA0LCBvdXRwdXREZXB0aF0pO1xuICAgICAgIGNvbnN0IFt4R3JhZCwgZmlsdEdyYWRdID0gZ3JhZHMoW3gsIGZpbHRdLCBkeSk7XG5cbiAgICAgICBjb25zdCBleHBlY3RlZFhHcmFkID0gdGYub25lcyhbMSwgMywgMywgMV0pLm11bCh0Zi5zY2FsYXIoMC4yODI3OTQ3KSk7XG4gICAgICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeEdyYWQuZGF0YSgpLCBhd2FpdCBleHBlY3RlZFhHcmFkLmRhdGEoKSk7XG4gICAgICAgY29uc3QgZXhwZWN0ZWRGaWx0R3JhZCA9XG4gICAgICAgICAgIHRmLm9uZXMoWzIsIDIsIDIsIDFdKS5tdWwodGYuc2NhbGFyKC01LjcwMjAyNTk5KSk7XG4gICAgICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgZmlsdEdyYWQuZGF0YSgpLCBhd2FpdCBleHBlY3RlZEZpbHRHcmFkLmRhdGEoKSk7XG4gICAgIH0pO1xuXG4gIC8vIFJlZmVyZW5jZSAoUHl0aG9uKSBUZW5zb3JGbG93IGNvZGU6XG4gIC8vXG4gIC8vIGBgYHB5XG4gIC8vIGltcG9ydCBudW1weSBhcyBucFxuICAvLyBpbXBvcnQgdGVuc29yZmxvdyBhcyB0ZlxuICAvL1xuICAvLyB0Zi5lbmFibGVfZWFnZXJfZXhlY3V0aW9uKClcbiAgLy9cbiAgLy8geCA9IHRmLmNvbnN0YW50KG5wLmFycmF5KFtcbiAgLy8gICAgIFtbWy0wLjM2NTQxNzEzXSwgWy0wLjUzOTczMTE2XV0sIFtbMC4wMTczMTY3NF0sIFswLjkwMjI3NzcyXV1dXG4gIC8vIF0pLmFzdHlwZShucC5mbG9hdDMyKSlcbiAgLy8gZmlsdCA9IHRmLmNvbnN0YW50KG5wLmFycmF5KFtcbiAgLy8gICAgIFtbWy0wLjAxNDIzNDYxXSwgWy0xLjAwMjY3Mzg0XV0sIFtbMS42MTE2MzAyOV0sIFswLjY2MzAyNjQ2XV1dLFxuICAvLyAgICAgW1tbLTAuNDY5MDAwODddLCBbLTAuNzg2NDk0NDRdXSwgW1swLjg3NzgwNTM2XSwgWy0wLjg0NTUxNjM3XV1dXG4gIC8vIF0pLmFzdHlwZShucC5mbG9hdDMyKSlcbiAgLy9cbiAgLy8gd2l0aCB0Zi5HcmFkaWVudFRhcGUoKSBhcyBnOlxuICAvLyAgIGcud2F0Y2goeClcbiAgLy8gICBnLndhdGNoKGZpbHQpXG4gIC8vICAgeSA9IHRmLmtlcmFzLmJhY2tlbmQuY29udjJkX3RyYW5zcG9zZSh4LCBmaWx0LCBbMSwgNCwgNCwgMl0sIHN0cmlkZXM9KDIsXG4gIC8vICAgMikpIHByaW50KHkpXG4gIC8vICh4X2dyYWQsIGZpbHRfZ3JhZCkgPSBnLmdyYWRpZW50KHksIFt4LCBmaWx0XSlcbiAgLy9cbiAgLy8gcHJpbnQoXCJ4X2dyYWQgPSAlc1wiICUgLXhfZ3JhZClcbiAgLy8gcHJpbnQoXCJmaWx0X2dyYWQgPSAlc1wiICUgLWZpbHRfZ3JhZClcbiAgLy8gYGBgXG4gIGl0KCdncmFkaWVudCBpbnB1dD1bMSwyLDIsMV0gZj1bMiwyLDIsMV0gcz1bMiwyXSBwYWRkaW5nPXZhbGlkJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGlucHV0RGVwdGggPSAxO1xuICAgIGNvbnN0IG91dHB1dERlcHRoID0gMjtcbiAgICBjb25zdCBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFsxLCAyLCAyLCBpbnB1dERlcHRoXTtcbiAgICBjb25zdCBmaWx0ZXJTaXplID0gMjtcbiAgICBjb25zdCBzdHJpZGU6IFtudW1iZXIsIG51bWJlcl0gPSBbMiwgMl07XG4gICAgY29uc3QgcGFkID0gJ3ZhbGlkJztcblxuICAgIGNvbnN0IGZpbHRlclNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9XG4gICAgICAgIFtmaWx0ZXJTaXplLCBmaWx0ZXJTaXplLCBvdXRwdXREZXB0aCwgaW5wdXREZXB0aF07XG5cbiAgICBjb25zdCB4ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFtbW1stMC4zNjU0MTcxM10sIFstMC41Mzk3MzExNl1dLCBbWzAuMDE3MzE2NzRdLCBbMC45MDIyNzc3Ml1dXV0sXG4gICAgICAgIGlucHV0U2hhcGUpO1xuICAgIGNvbnN0IGZpbHQgPSB0Zi50ZW5zb3I0ZChcbiAgICAgICAgW1xuICAgICAgICAgIFtbWy0wLjAxNDIzNDYxXSwgWy0xLjAwMjY3Mzg0XV0sIFtbMS42MTE2MzAyOV0sIFswLjY2MzAyNjQ2XV1dLFxuICAgICAgICAgIFtbWy0wLjQ2OTAwMDg3XSwgWy0wLjc4NjQ5NDQ0XV0sIFtbMC44Nzc4MDUzNl0sIFstMC44NDU1MTYzN11dXVxuICAgICAgICBdLFxuICAgICAgICBmaWx0ZXJTaGFwZSk7XG5cbiAgICBjb25zdCBncmFkcyA9IHRmLmdyYWRzKFxuICAgICAgICAoeDogdGYuVGVuc29yNEQsIGZpbHRlcjogdGYuVGVuc29yNEQpID0+XG4gICAgICAgICAgICB0Zi5jb252MmRUcmFuc3Bvc2UoeCwgZmlsdGVyLCBbMSwgNCwgNCwgb3V0cHV0RGVwdGhdLCBzdHJpZGUsIHBhZCkpO1xuICAgIGNvbnN0IGR5ID0gdGYub25lcyhbMSwgNCwgNCwgb3V0cHV0RGVwdGhdKS5tdWwodGYuc2NhbGFyKC0xKSk7XG4gICAgY29uc3QgW3hHcmFkLCBmaWx0R3JhZF0gPSBncmFkcyhbeCwgZmlsdF0sIGR5KTtcblxuICAgIGNvbnN0IGV4cGVjdGVkWEdyYWQgPSB0Zi5vbmVzKFsxLCAyLCAyLCAxXSkubXVsKHRmLnNjYWxhcigtMC4wMzQ1NDE5NikpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHhHcmFkLmRhdGEoKSwgYXdhaXQgZXhwZWN0ZWRYR3JhZC5kYXRhKCkpO1xuICAgIGV4cGVjdCh4R3JhZC5zaGFwZSkudG9FcXVhbChbMSwgMiwgMiwgMV0pO1xuXG4gICAgY29uc3QgZXhwZWN0ZWRGaWx0R3JhZCA9IHRmLm9uZXMoWzIsIDIsIDIsIDFdKS5tdWwodGYuc2NhbGFyKC0wLjAxNDQ0NjE4KSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgZmlsdEdyYWQuZGF0YSgpLCBhd2FpdCBleHBlY3RlZEZpbHRHcmFkLmRhdGEoKSk7XG4gICAgZXhwZWN0KGZpbHRHcmFkLnNoYXBlKS50b0VxdWFsKFsyLCAyLCAyLCAxXSk7XG4gIH0pO1xuXG4gIC8vIFJlZmVyZW5jZSAoUHl0aG9uKSBUZW5zb3JGbG93IGNvZGU6XG4gIC8vXG4gIC8vIGBgYHB5XG4gIC8vIGltcG9ydCBudW1weSBhcyBucFxuICAvLyBpbXBvcnQgdGVuc29yZmxvdyBhcyB0ZlxuICAvL1xuICAvLyB0Zi5lbmFibGVfZWFnZXJfZXhlY3V0aW9uKClcbiAgLy9cbiAgLy8geCA9IHRmLmNvbnN0YW50KG5wLmFycmF5KFtbXG4gIC8vICAgICBbWzEuNTI0MzMwNjVdLCBbLTAuNzcwNTM0MzVdLCBbLTAuNjQ1NjIzNDFdXSxcbiAgLy8gICAgIFtbMC43Nzk2Mjg4OV0sIFsxLjU4NDEzODg3XSwgWy0wLjI1NTgxODU2XV0sXG4gIC8vICAgICBbWy0wLjU4OTY2MjIxXSwgWzAuMDU0MTE2NjJdLCBbMC43MDc0OTEzOF1dXG4gIC8vIF1dKS5hc3R5cGUobnAuZmxvYXQzMikpXG4gIC8vIGZpbHQgPSB0Zi5jb25zdGFudChucC5hcnJheShbXG4gIC8vICAgICBbW1swLjExMTc4Mzg4XSwgWy0wLjk2NjU0OTc3XV0sIFtbMS4yMTAyMTI5Nl0sIFswLjg0MTIxNzI5XV1dLFxuICAvLyAgICAgW1tbMC4zNDk2ODMzOF0sIFstMC40MjMwNjExNF1dLCBbWzEuMjczOTU3MzNdLCBbLTEuMDkwMTQ1MzVdXV1cbiAgLy8gXSkuYXN0eXBlKG5wLmZsb2F0MzIpKVxuICAvL1xuICAvLyB3aXRoIHRmLkdyYWRpZW50VGFwZSgpIGFzIGc6XG4gIC8vICAgZy53YXRjaCh4KVxuICAvLyAgIGcud2F0Y2goZmlsdClcbiAgLy8gICB5ID0gdGYua2VyYXMuYmFja2VuZC5jb252MmRfdHJhbnNwb3NlKFxuICAvLyAgICAgICB4LCBmaWx0LCBbMSwgMywgMywgMl0sIHN0cmlkZXM9KDEsIDEpLCBwYWRkaW5nPSdzYW1lJylcbiAgLy8gKHhfZ3JhZCwgZmlsdF9ncmFkKSA9IGcuZ3JhZGllbnQoeSwgW3gsIGZpbHRdKVxuICAvL1xuICAvLyBwcmludChcInhfZ3JhZCA9ICVzXCIgJSB4X2dyYWQpXG4gIC8vIHByaW50KFwiZmlsdF9ncmFkID0gJXNcIiAlIGZpbHRfZ3JhZClcbiAgLy8gYGBgXG4gIGl0KCdncmFkaWVudCBpbnB1dD1bMSwzLDMsMV0gZj1bMiwyLDIsMV0gcz1bMSwxXSBwYWRkaW5nPXNhbWUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgaW5wdXREZXB0aCA9IDE7XG4gICAgY29uc3Qgb3V0cHV0RGVwdGggPSAyO1xuICAgIGNvbnN0IGlucHV0U2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzEsIDMsIDMsIGlucHV0RGVwdGhdO1xuICAgIGNvbnN0IGZpbHRlclNpemUgPSAyO1xuICAgIGNvbnN0IHN0cmlkZTogW251bWJlciwgbnVtYmVyXSA9IFsxLCAxXTtcbiAgICBjb25zdCBwYWQgPSAnc2FtZSc7XG5cbiAgICBjb25zdCBmaWx0ZXJTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPVxuICAgICAgICBbZmlsdGVyU2l6ZSwgZmlsdGVyU2l6ZSwgb3V0cHV0RGVwdGgsIGlucHV0RGVwdGhdO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbW1xuICAgICAgICAgIFtbMS41MjQzMzA2NV0sIFstMC43NzA1MzQzNV0sIFstMC42NDU2MjM0MV1dLFxuICAgICAgICAgIFtbMC43Nzk2Mjg4OV0sIFsxLjU4NDEzODg3XSwgWy0wLjI1NTgxODU2XV0sXG4gICAgICAgICAgW1stMC41ODk2NjIyMV0sIFswLjA1NDExNjYyXSwgWzAuNzA3NDkxMzhdXVxuICAgICAgICBdXSxcbiAgICAgICAgaW5wdXRTaGFwZSk7XG4gICAgY29uc3QgZmlsdCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbXG4gICAgICAgICAgW1tbMC4xMTE3ODM4OF0sIFstMC45NjY1NDk3N11dLCBbWzEuMjEwMjEyOTZdLCBbMC44NDEyMTcyOV1dXSxcbiAgICAgICAgICBbW1swLjM0OTY4MzM4XSwgWy0wLjQyMzA2MTE0XV0sIFtbMS4yNzM5NTczM10sIFstMS4wOTAxNDUzNV1dXVxuICAgICAgICBdLFxuICAgICAgICBmaWx0ZXJTaGFwZSk7XG5cbiAgICBjb25zdCBncmFkcyA9IHRmLmdyYWRzKFxuICAgICAgICAoeDogdGYuVGVuc29yNEQsIGZpbHRlcjogdGYuVGVuc29yNEQpID0+XG4gICAgICAgICAgICB0Zi5jb252MmRUcmFuc3Bvc2UoeCwgZmlsdGVyLCBbMSwgMywgMywgb3V0cHV0RGVwdGhdLCBzdHJpZGUsIHBhZCkpO1xuICAgIGNvbnN0IGR5ID0gdGYub25lcyhbMSwgMywgMywgb3V0cHV0RGVwdGhdKTtcbiAgICBjb25zdCBbeEdyYWQsIGZpbHRHcmFkXSA9IGdyYWRzKFt4LCBmaWx0XSwgZHkpO1xuXG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeEdyYWQuYXJyYXkoKSwgW1tcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMS4zMDcwOTg1OF0sIFsxLjMwNzA5ODU4XSwgWy0wLjkyODE0MzY2XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzEuMzA3MDk4NThdLCBbMS4zMDcwOTg1OF0sIFstMC45MjgxNDM2Nl1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sxLjE5NjY2NDM3XSwgWzEuMTk2NjY0MzddLCBbLTAuODU0NzY1ODldXVxuICAgICAgICAgICAgICAgICAgICAgIF1dKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBmaWx0R3JhZC5hcnJheSgpLCBbXG4gICAgICBbW1syLjM4ODA2Nzg4XSwgWzIuMzg4MDY3ODhdXSwgW1syLjU4MjAxODQ3XSwgWzIuNTgyMDE4NDddXV0sXG4gICAgICBbW1syLjIxNjEyMjFdLCBbMi4yMTYxMjIxXV0sIFtbMy4xMTc1NjQwNl0sIFszLjExNzU2NDA2XV1dXG4gICAgXSk7XG4gIH0pO1xuXG4gIGl0KCdncmFkaWVudCBpbnB1dD1bMSwzLDMsMV0gZj1bMiwyLDIsMV0gcz1bMSwxXSBwPWV4cGxpY2l0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGlucHV0RGVwdGggPSAxO1xuICAgIGNvbnN0IG91dHB1dERlcHRoID0gMjtcbiAgICBjb25zdCBpbnB1dFNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFsxLCAzLCAzLCBpbnB1dERlcHRoXTtcbiAgICBjb25zdCBmaWx0ZXJTaXplID0gMjtcbiAgICBjb25zdCBzdHJpZGU6IFtudW1iZXIsIG51bWJlcl0gPSBbMSwgMV07XG4gICAgY29uc3QgcGFkID1cbiAgICAgICAgW1swLCAwXSwgWzAsIDFdLCBbMCwgMV0sIFswLCAwXV0gYXMgdGYuYmFja2VuZF91dGlsLkV4cGxpY2l0UGFkZGluZztcblxuICAgIGNvbnN0IGZpbHRlclNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9XG4gICAgICAgIFtmaWx0ZXJTaXplLCBmaWx0ZXJTaXplLCBvdXRwdXREZXB0aCwgaW5wdXREZXB0aF07XG5cbiAgICBjb25zdCB4ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFtbXG4gICAgICAgICAgW1sxLjUyNDMzMDY1XSwgWy0wLjc3MDUzNDM1XSwgWy0wLjY0NTYyMzQxXV0sXG4gICAgICAgICAgW1swLjc3OTYyODg5XSwgWzEuNTg0MTM4ODddLCBbLTAuMjU1ODE4NTZdXSxcbiAgICAgICAgICBbWy0wLjU4OTY2MjIxXSwgWzAuMDU0MTE2NjJdLCBbMC43MDc0OTEzOF1dXG4gICAgICAgIF1dLFxuICAgICAgICBpbnB1dFNoYXBlKTtcbiAgICBjb25zdCBmaWx0ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFtcbiAgICAgICAgICBbW1swLjExMTc4Mzg4XSwgWy0wLjk2NjU0OTc3XV0sIFtbMS4yMTAyMTI5Nl0sIFswLjg0MTIxNzI5XV1dLFxuICAgICAgICAgIFtbWzAuMzQ5NjgzMzhdLCBbLTAuNDIzMDYxMTRdXSwgW1sxLjI3Mzk1NzMzXSwgWy0xLjA5MDE0NTM1XV1dXG4gICAgICAgIF0sXG4gICAgICAgIGZpbHRlclNoYXBlKTtcblxuICAgIGNvbnN0IGdyYWRzID0gdGYuZ3JhZHMoXG4gICAgICAgICh4OiB0Zi5UZW5zb3I0RCwgZmlsdGVyOiB0Zi5UZW5zb3I0RCkgPT5cbiAgICAgICAgICAgIHRmLmNvbnYyZFRyYW5zcG9zZSh4LCBmaWx0ZXIsIFsxLCAzLCAzLCBvdXRwdXREZXB0aF0sIHN0cmlkZSwgcGFkKSk7XG4gICAgY29uc3QgZHkgPSB0Zi5vbmVzKFsxLCAzLCAzLCBvdXRwdXREZXB0aF0pO1xuICAgIGNvbnN0IFt4R3JhZCwgZmlsdEdyYWRdID0gZ3JhZHMoW3gsIGZpbHRdLCBkeSk7XG5cbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCB4R3JhZC5hcnJheSgpLCBbW1xuICAgICAgICAgICAgICAgICAgICAgICAgW1sxLjMwNzA5ODU4XSwgWzEuMzA3MDk4NThdLCBbLTAuOTI4MTQzNjZdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMS4zMDcwOTg1OF0sIFsxLjMwNzA5ODU4XSwgWy0wLjkyODE0MzY2XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzEuMTk2NjY0MzddLCBbMS4xOTY2NjQzN10sIFstMC44NTQ3NjU4OV1dXG4gICAgICAgICAgICAgICAgICAgICAgXV0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IGZpbHRHcmFkLmFycmF5KCksIFtcbiAgICAgIFtbWzIuMzg4MDY3ODhdLCBbMi4zODgwNjc4OF1dLCBbWzIuNTgyMDE4NDddLCBbMi41ODIwMTg0N11dXSxcbiAgICAgIFtbWzIuMjE2MTIyMV0sIFsyLjIxNjEyMjFdXSwgW1szLjExNzU2NDA2XSwgWzMuMTE3NTY0MDZdXV1cbiAgICBdKTtcbiAgfSk7XG5cbiAgLy8gUmVmZXJlbmNlIChQeXRob24pIFRlbnNvckZsb3cgY29kZTpcbiAgLy9cbiAgLy8gYGBgcHlcbiAgLy8gaW1wb3J0IG51bXB5IGFzIG5wXG4gIC8vIGltcG9ydCB0ZW5zb3JmbG93IGFzIHRmXG4gIC8vXG4gIC8vIHRmLmVuYWJsZV9lYWdlcl9leGVjdXRpb24oKVxuICAvL1xuICAvLyB4ID0gdGYuY29uc3RhbnQobnAuYXJyYXkoW1tcbiAgLy8gICAgIFtbMS41MjQzMzA2NV0sIFstMC43NzA1MzQzNV1dLCBbWzAuNzc5NjI4ODldLCBbMS41ODQxMzg4N11dLFxuICAvLyBdXSkuYXN0eXBlKG5wLmZsb2F0MzIpKVxuICAvLyBmaWx0ID0gdGYuY29uc3RhbnQobnAuYXJyYXkoW1xuICAvLyAgICAgW1tbMC4xMTE3ODM4OF0sIFstMC45NjY1NDk3N11dLCBbWzEuMjEwMjEyOTZdLCBbMC44NDEyMTcyOV1dXSxcbiAgLy8gICAgIFtbWzAuMzQ5NjgzMzhdLCBbLTAuNDIzMDYxMTRdXSwgW1sxLjI3Mzk1NzMzXSwgWy0xLjA5MDE0NTM1XV1dXG4gIC8vIF0pLmFzdHlwZShucC5mbG9hdDMyKSlcbiAgLy9cbiAgLy8gd2l0aCB0Zi5HcmFkaWVudFRhcGUoKSBhcyBnOlxuICAvLyAgIGcud2F0Y2goeClcbiAgLy8gICBnLndhdGNoKGZpbHQpXG4gIC8vICAgeSA9IHRmLmtlcmFzLmJhY2tlbmQuY29udjJkX3RyYW5zcG9zZShcbiAgLy8gICAgICAgeCwgZmlsdCwgWzEsIDMsIDMsIDJdLCBzdHJpZGVzPSgyLCAyKSwgcGFkZGluZz0nc2FtZScpXG4gIC8vICAgcHJpbnQoeS5zaGFwZSlcbiAgLy8gKHhfZ3JhZCwgZmlsdF9ncmFkKSA9IGcuZ3JhZGllbnQoeSwgW3gsIGZpbHRdKVxuICAvL1xuICAvLyBwcmludChcInhfZ3JhZCA9ICVzXCIgJSB4X2dyYWQpXG4gIC8vIHByaW50KFwiZmlsdF9ncmFkID0gJXNcIiAlIGZpbHRfZ3JhZClcbiAgLy8gYGBgXG4gIGl0KCdncmFkaWVudCBpbnB1dD1bMSwyLDIsMl0gZj1bMiwyLDIsMV0gcz1bMiwyXSBwYWRkaW5nPXNhbWUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgaW5wdXREZXB0aCA9IDI7XG4gICAgY29uc3Qgb3V0cHV0RGVwdGggPSAyO1xuICAgIGNvbnN0IGlucHV0U2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzEsIDIsIDIsIGlucHV0RGVwdGhdO1xuICAgIGNvbnN0IGZpbHRlclNpemUgPSAyO1xuICAgIGNvbnN0IHN0cmlkZTogW251bWJlciwgbnVtYmVyXSA9IFsyLCAyXTtcbiAgICBjb25zdCBwYWQgPSAnc2FtZSc7XG5cbiAgICBjb25zdCBmaWx0ZXJTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPVxuICAgICAgICBbZmlsdGVyU2l6ZSwgZmlsdGVyU2l6ZSwgb3V0cHV0RGVwdGgsIGlucHV0RGVwdGhdO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjRkKFxuICAgICAgICBbW1xuICAgICAgICAgIFtbLTEuODE1MDY1OTMsIDEuMDA5MDAwOTVdLCBbLTAuMDUxOTkxMTgsIDAuMjYzMTEzNzddXSxcbiAgICAgICAgICBbWy0xLjE4NDY5NzkyLCAtMC4zNDc4MDUyMV0sIFsyLjA0OTcxMjQyLCAtMC42NTE1NDY5Ml1dXG4gICAgICAgIF1dLFxuICAgICAgICBpbnB1dFNoYXBlKTtcbiAgICBjb25zdCBmaWx0ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFtcbiAgICAgICAgICBbXG4gICAgICAgICAgICBbWzAuMTk1Mjk2ODYsIC0wLjc5NTk0NzA4XSwgWzAuNzAzMTQwNTcsIC0wLjA2MDgxMjYzXV0sXG4gICAgICAgICAgICBbWzAuMjg3MjQ3NDQsIDAuODg1MjI3MTVdLCBbLTAuNTE4MjQwOTYsIC0wLjk3MTIwOTg5XV1cbiAgICAgICAgICBdLFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIFtbMC41MTg3MjE5NywgLTEuMTc1NjkxOTNdLCBbMS4yODMxNjc5MSwgLTAuODEyMjUwOTJdXSxcbiAgICAgICAgICAgIFtbLTAuNDQyMjE1MzIsIDAuNzAwNTgxNzRdLCBbLTAuNDg0OTIxNywgMC4wMzgwNjM0OF1dXG4gICAgICAgICAgXVxuICAgICAgICBdLFxuICAgICAgICBmaWx0ZXJTaGFwZSk7XG5cbiAgICBjb25zdCBncmFkcyA9IHRmLmdyYWRzKFxuICAgICAgICAoeDogdGYuVGVuc29yNEQsIGZpbHRlcjogdGYuVGVuc29yNEQpID0+XG4gICAgICAgICAgICB0Zi5jb252MmRUcmFuc3Bvc2UoeCwgZmlsdGVyLCBbMSwgMywgMywgb3V0cHV0RGVwdGhdLCBzdHJpZGUsIHBhZCkpO1xuICAgIGNvbnN0IGR5ID0gdGYub25lcyhbMSwgMywgMywgb3V0cHV0RGVwdGhdKTtcbiAgICBjb25zdCBbeEdyYWQsIGZpbHRHcmFkXSA9IGdyYWRzKFt4LCBmaWx0XSwgZHkpO1xuXG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeEdyYWQuZGF0YSgpLCBbXG4gICAgICAxLjU0MjE5Njc4LCAtMi4xOTIwNDAwOCwgMi43MDAzMjczMiwgLTIuODQ0NzAyNTcsIDAuNjY3NDQzOTEsIC0wLjk0Mjc0MjQ1LFxuICAgICAgMC44OTg0Mzc0MywgLTAuODU2NzU5NzJcbiAgICBdKTtcbiAgICBleHBlY3QoeEdyYWQuc2hhcGUpLnRvRXF1YWwoWzEsIDIsIDIsIDJdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBmaWx0R3JhZC5kYXRhKCksIFtcbiAgICAgIC0xLjAwMjA0MjYxLCAwLjI3Mjc2MjU5LCAtMS4wMDIwNDI2MSwgMC4yNzI3NjI1OSwgLTIuOTk5NzYzODUsIDAuNjYxMTk1NzQsXG4gICAgICAtMi45OTk3NjM4NSwgMC42NjExOTU3NCwgLTEuODY3MDU3MTEsIDEuMjcyMTE0NzIsIC0xLjg2NzA1NzExLCAxLjI3MjExNDcyLFxuICAgICAgLTEuODE1MDY1OTMsIDEuMDA5MDAwOTUsIC0xLjgxNTA2NTkzLCAxLjAwOTAwMDk1XG4gICAgXSk7XG4gICAgZXhwZWN0KGZpbHRHcmFkLnNoYXBlKS50b0VxdWFsKFsyLCAyLCAyLCAyXSk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvd3Mgd2hlbiB4IGlzIG5vdCByYW5rIDMnLCAoKSA9PiB7XG4gICAgY29uc3Qgb3JpZ0lucHV0RGVwdGggPSAxO1xuICAgIGNvbnN0IG9yaWdPdXRwdXREZXB0aCA9IDE7XG4gICAgY29uc3QgZlNpemUgPSAyO1xuICAgIGNvbnN0IG9yaWdQYWQgPSAwO1xuICAgIGNvbnN0IG9yaWdTdHJpZGUgPSAxO1xuXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICAgIGNvbnN0IHg6IGFueSA9IHRmLnRlbnNvcjJkKFsyLCAyXSwgWzIsIDFdKTtcbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFszLCAxLCA1LCAwXSwgW2ZTaXplLCBmU2l6ZSwgb3JpZ0lucHV0RGVwdGgsIG9yaWdPdXRwdXREZXB0aF0pO1xuXG4gICAgZXhwZWN0KCgpID0+IHRmLmNvbnYyZFRyYW5zcG9zZSh4LCB3LCBbMiwgMiwgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQpKVxuICAgICAgICAudG9UaHJvd0Vycm9yKCk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvd3Mgd2hlbiB3ZWlnaHRzIGlzIG5vdCByYW5rIDQnLCAoKSA9PiB7XG4gICAgY29uc3Qgb3JpZ0lucHV0RGVwdGggPSAxO1xuICAgIGNvbnN0IG9yaWdPdXRwdXREZXB0aCA9IDE7XG4gICAgY29uc3QgaW5wdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzEsIDEsIG9yaWdPdXRwdXREZXB0aF07XG4gICAgY29uc3QgZlNpemUgPSAyO1xuICAgIGNvbnN0IG9yaWdQYWQgPSAwO1xuICAgIGNvbnN0IG9yaWdTdHJpZGUgPSAxO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjNkKFsyXSwgaW5wdXRTaGFwZSk7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICAgIGNvbnN0IHc6IGFueSA9IHRmLnRlbnNvcjNkKFszLCAxLCA1LCAwXSwgW2ZTaXplLCBmU2l6ZSwgb3JpZ0lucHV0RGVwdGhdKTtcblxuICAgIGV4cGVjdCgoKSA9PiB0Zi5jb252MmRUcmFuc3Bvc2UoeCwgdywgWzIsIDIsIDFdLCBvcmlnU3RyaWRlLCBvcmlnUGFkKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcigpO1xuICB9KTtcblxuICBpdCgndGhyb3dzIHdoZW4geCBkZXB0aCBkb2VzIG5vdCBtYXRjaCB3ZWlnaHRzIG9yaWdpbmFsIG91dHB1dCBkZXB0aCcsICgpID0+IHtcbiAgICBjb25zdCBvcmlnSW5wdXREZXB0aCA9IDE7XG4gICAgY29uc3Qgb3JpZ091dHB1dERlcHRoID0gMjtcbiAgICBjb25zdCB3cm9uZ09yaWdPdXRwdXREZXB0aCA9IDM7XG4gICAgY29uc3QgaW5wdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzEsIDEsIG9yaWdPdXRwdXREZXB0aF07XG4gICAgY29uc3QgZlNpemUgPSAyO1xuICAgIGNvbnN0IG9yaWdQYWQgPSAwO1xuICAgIGNvbnN0IG9yaWdTdHJpZGUgPSAxO1xuXG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjNkKFsyLCAyXSwgaW5wdXRTaGFwZSk7XG4gICAgY29uc3QgdyA9IHRmLnJhbmRvbU5vcm1hbDxSYW5rLlI0PihcbiAgICAgICAgW2ZTaXplLCBmU2l6ZSwgb3JpZ0lucHV0RGVwdGgsIHdyb25nT3JpZ091dHB1dERlcHRoXSk7XG5cbiAgICBleHBlY3QoKCkgPT4gdGYuY29udjJkVHJhbnNwb3NlKHgsIHcsIFsyLCAyLCAyXSwgb3JpZ1N0cmlkZSwgb3JpZ1BhZCkpXG4gICAgICAgIC50b1Rocm93RXJyb3IoKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIHBhc3NlZCB4IGFzIGEgbm9uLXRlbnNvcicsICgpID0+IHtcbiAgICBjb25zdCBvcmlnSW5wdXREZXB0aCA9IDE7XG4gICAgY29uc3Qgb3JpZ091dHB1dERlcHRoID0gMTtcbiAgICBjb25zdCBmU2l6ZSA9IDI7XG4gICAgY29uc3Qgb3JpZ1BhZCA9IDA7XG4gICAgY29uc3Qgb3JpZ1N0cmlkZSA9IDE7XG5cbiAgICBjb25zdCB3ID0gdGYudGVuc29yNGQoXG4gICAgICAgIFszLCAxLCA1LCAwXSwgW2ZTaXplLCBmU2l6ZSwgb3JpZ0lucHV0RGVwdGgsIG9yaWdPdXRwdXREZXB0aF0pO1xuXG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5jb252MmRUcmFuc3Bvc2UoXG4gICAgICAgICAgICB7fSBhcyB0Zi5UZW5zb3IzRCwgdywgWzIsIDIsIDFdLCBvcmlnU3RyaWRlLCBvcmlnUGFkKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcihcbiAgICAgICAgICAgIC9Bcmd1bWVudCAneCcgcGFzc2VkIHRvICdjb252MmRUcmFuc3Bvc2UnIG11c3QgYmUgYSBUZW5zb3IvKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIHBhc3NlZCBmaWx0ZXIgYXMgYSBub24tdGVuc29yJywgKCkgPT4ge1xuICAgIGNvbnN0IG9yaWdPdXRwdXREZXB0aCA9IDE7XG4gICAgY29uc3QgaW5wdXRTaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0gWzEsIDEsIG9yaWdPdXRwdXREZXB0aF07XG4gICAgY29uc3Qgb3JpZ1BhZCA9IDA7XG4gICAgY29uc3Qgb3JpZ1N0cmlkZSA9IDE7XG5cbiAgICBjb25zdCB4ID0gdGYudGVuc29yM2QoWzJdLCBpbnB1dFNoYXBlKTtcblxuICAgIGV4cGVjdChcbiAgICAgICAgKCkgPT4gdGYuY29udjJkVHJhbnNwb3NlKFxuICAgICAgICAgICAgeCwge30gYXMgdGYuVGVuc29yNEQsIFsyLCAyLCAxXSwgb3JpZ1N0cmlkZSwgb3JpZ1BhZCkpXG4gICAgICAgIC50b1Rocm93RXJyb3IoXG4gICAgICAgICAgICAvQXJndW1lbnQgJ2ZpbHRlcicgcGFzc2VkIHRvICdjb252MmRUcmFuc3Bvc2UnIG11c3QgYmUgYSBUZW5zb3IvKTtcbiAgfSk7XG5cbiAgaXQoJ2FjY2VwdHMgYSB0ZW5zb3ItbGlrZSBvYmplY3QnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgb3JpZ1BhZCA9IDA7XG4gICAgY29uc3Qgb3JpZ1N0cmlkZSA9IDE7XG5cbiAgICBjb25zdCB4ID0gW1tbMl1dXTsgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAxeDF4MVxuICAgIGNvbnN0IHcgPSBbW1tbM11dLCBbWzFdXV0sIFtbWzVdXSwgW1swXV1dXTsgIC8vIDJ4MngxeDFcblxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmNvbnYyZFRyYW5zcG9zZSh4LCB3LCBbMiwgMiwgMV0sIG9yaWdTdHJpZGUsIG9yaWdQYWQpO1xuICAgIGNvbnN0IGV4cGVjdGVkID0gWzYsIDIsIDEwLCAwXTtcblxuICAgIGV4cGVjdChyZXN1bHQuc2hhcGUpLnRvRXF1YWwoWzIsIDIsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBleHBlY3RlZCk7XG4gIH0pO1xufSk7XG4iXX0=
\No newline at end of file