UNPKG

29.8 kBJavaScriptView Raw
1/**
2 * @license
3 * Copyright 2021 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';
20function sparseTensorValue5x6() {
21 const ind = tf.tensor2d([[0, 0], [1, 0], [1, 3], [1, 4], [3, 2], [3, 3]], [6, 2], 'int32');
22 const val = [0, 10, 13, 14, 32, 33];
23 const shape = [5, 6];
24 return { ind, val, shape };
25}
26function sparseTensorValue2x3x4() {
27 const ind = tf.tensor2d([
28 [0, 0, 1], [0, 1, 0], [0, 1, 2], [1, 0, 3], [1, 1, 1], [1, 1, 3],
29 [1, 2, 2]
30 ], [7, 3], 'int32');
31 const val = [1, 10, 12, 103, 111, 113, 122];
32 const shape = [2, 3, 4];
33 return { ind, val, shape };
34}
35describeWithFlags('sparseReshape', ALL_ENVS, () => {
36 it('preserve static shape info', async () => {
37 const sparseTensor = sparseTensorValue5x6();
38 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [1, 5, 2, 3]);
39 expectArraysClose(await result.outputShape.data(), [1, 5, 2, 3]);
40 });
41 it('preserve shape info with inferred dim', async () => {
42 const sparseTensor = sparseTensorValue2x3x4();
43 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [2, -1]);
44 expectArraysClose(await result.outputShape.data(), [2, 3 * 4]);
45 });
46 it('does not have memory leak.', async () => {
47 const beforeDataIds = tf.engine().backend.numDataIds();
48 const sparseTensor = sparseTensorValue5x6();
49 const indices = sparseTensor.ind;
50 const shape = tf.tensor1d(sparseTensor.shape, 'int32');
51 const newShape = tf.tensor1d([1, 5, 2, 3], 'int32');
52 const result = tf.sparse.sparseReshape(indices, shape, newShape);
53 await result.outputIndices.data();
54 await result.outputShape.data();
55 const afterResDataIds = tf.engine().backend.numDataIds();
56 expect(afterResDataIds).toEqual(beforeDataIds + 5);
57 indices.dispose();
58 shape.dispose();
59 newShape.dispose();
60 result.outputIndices.dispose();
61 result.outputShape.dispose();
62 const afterDisposeDataIds = tf.engine().backend.numDataIds();
63 expect(afterDisposeDataIds).toEqual(beforeDataIds);
64 });
65 it('throw error if more than one inferred dim', async () => {
66 const sparseTensor = sparseTensorValue2x3x4();
67 expect(() => tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [
68 -1, 2, -1
69 ])).toThrowError(/only one output dimension may be -1/);
70 });
71 it('throw error if impossible new shape', async () => {
72 const sparseTensor = sparseTensorValue2x3x4();
73 expect(() => tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [
74 -1, 7
75 ])).toThrowError(/multiple of 7/);
76 });
77 it('throw error if negative output dim', async () => {
78 const sparseTensor = sparseTensorValue2x3x4();
79 expect(() => tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [
80 1, -7
81 ])).toThrowError('size 1 must be non-negative, not -7');
82 });
83 it('throw error if negative output dim', async () => {
84 const sparseTensor = sparseTensorValue2x3x4();
85 expect(() => tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [
86 -1, 0
87 ])).toThrowError(/unless all specified input sizes are non-zero/);
88 });
89 it('same shape', async () => {
90 const sparseTensor = sparseTensorValue5x6();
91 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [5, 6]);
92 expectArraysClose(await result.outputIndices.data(), await sparseTensor.ind.data());
93 expectArraysClose(await result.outputShape.data(), sparseTensor.shape);
94 });
95 it('same shape with inferred dim', async () => {
96 const sparseTensor = sparseTensorValue5x6();
97 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [-1, 6]);
98 expectArraysClose(await result.outputIndices.data(), await sparseTensor.ind.data());
99 expectArraysClose(await result.outputShape.data(), sparseTensor.shape);
100 });
101 it('new shape with same rank', async () => {
102 const sparseTensor = sparseTensorValue5x6();
103 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [3, 10]);
104 expectArraysClose(await result.outputIndices.data(), [[0, 0], [0, 6], [0, 9], [1, 0], [2, 0], [2, 1]]);
105 expectArraysClose(await result.outputShape.data(), [3, 10]);
106 });
107 it('new shape with same rank with inferred dim', async () => {
108 const sparseTensor = sparseTensorValue5x6();
109 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [3, -1]);
110 expectArraysClose(await result.outputIndices.data(), [[0, 0], [0, 6], [0, 9], [1, 0], [2, 0], [2, 1]]);
111 expectArraysClose(await result.outputShape.data(), [3, 10]);
112 });
113 it('up rank', async () => {
114 const sparseTensor = sparseTensorValue5x6();
115 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [2, 3, 5]);
116 expectArraysClose(await result.outputIndices.data(), [[0, 0, 0], [0, 1, 1], [0, 1, 4], [0, 2, 0], [1, 1, 0], [1, 1, 1]]);
117 expectArraysClose(await result.outputShape.data(), [2, 3, 5]);
118 });
119 it('up rank with inferred dim', async () => {
120 const sparseTensor = sparseTensorValue5x6();
121 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [2, -1, 5]);
122 expectArraysClose(await result.outputIndices.data(), [[0, 0, 0], [0, 1, 1], [0, 1, 4], [0, 2, 0], [1, 1, 0], [1, 1, 1]]);
123 expectArraysClose(await result.outputShape.data(), [2, 3, 5]);
124 });
125 it('down rank', async () => {
126 const sparseTensor = sparseTensorValue2x3x4();
127 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [6, 4]);
128 expectArraysClose(await result.outputIndices.data(), [[0, 1], [1, 0], [1, 2], [3, 3], [4, 1], [4, 3], [5, 2]]);
129 expectArraysClose(await result.outputShape.data(), [6, 4]);
130 });
131 it('down rank with inferred dim', async () => {
132 const sparseTensor = sparseTensorValue2x3x4();
133 const result = tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [6, -1]);
134 expectArraysClose(await result.outputIndices.data(), [[0, 1], [1, 0], [1, 2], [3, 3], [4, 1], [4, 3], [5, 2]]);
135 expectArraysClose(await result.outputShape.data(), [6, 4]);
136 });
137 it('throw error if mismatch size', async () => {
138 const sparseTensor = sparseTensorValue5x6();
139 expect(() => tf.sparse.sparseReshape(sparseTensor.ind, sparseTensor.shape, [
140 4, 7
141 ])).toThrowError(/Input to reshape is a tensor with 30 dense values/);
142 });
143});
144//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhcnNlX3Jlc2hhcGVfdGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3RmanMtY29yZS9zcmMvb3BzL3NwYXJzZS9zcGFyc2VfcmVzaGFwZV90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUVsRCxTQUFTLG9CQUFvQjtJQUMzQixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUNuQixDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdkUsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3BDLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3JCLE9BQU8sRUFBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBQyxDQUFDO0FBQzNCLENBQUM7QUFFRCxTQUFTLHNCQUFzQjtJQUM3QixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUNuQjtRQUNFLENBQUMsQ0FBQyxF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RUFBRSxFQUNqQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0RCxpQkFBaUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw0Q0FBNEMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMxRCxNQUFNLFlBQVksR0FBRyxvQkFBb0IsRUFBRSxDQUFDO1FBQzVDLE1BQU0sTUFBTSxHQUNSLEVBQUUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsaUJBQWlCLENBQ2IsTUFBTSxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxFQUNqQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0RCxpQkFBaUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJ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UUFDOUQsaUJBQWlCLENBQUMsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0QsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNkJBQTZCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDM0MsTUFBTSxZQUFZLEdBQUcsc0JBQXNCLEVBQUUsQ0FBQztRQUM5QyxNQUFNLE1BQU0sR0FDUixFQUFFLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNFLGlCQUFpQixDQUNiLE1BQU0sTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsRUFDakMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUQsaUJBQWlCLENBQUMsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0QsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsOEJBQThCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDNUMsTUFBTSxZQUFZLEdBQUcsb0JBQW9CLEVBQUUsQ0FBQztRQUM1QyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsS0FBSyxFQUFFO1lBQ3pFLENBQUMsRUFBRSxDQUFDO1NBQ0wsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLG1EQUFtRCxDQUFDLENBQUM7SUFDeEUsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0ICogYXMgdGYgZnJvbSAnLi4vLi4vaW5kZXgnO1xuaW1wb3J0IHtBTExfRU5WUywgZGVzY3JpYmVXaXRoRmxhZ3N9IGZyb20gJy4uLy4uL2phc21pbmVfdXRpbCc7XG5pbXBvcnQge2V4cGVjdEFycmF5c0Nsb3NlfSBmcm9tICcuLi8uLi90ZXN0X3V0aWwnO1xuXG5mdW5jdGlvbiBzcGFyc2VUZW5zb3JWYWx1ZTV4NigpIHtcbiAgY29uc3QgaW5kID0gdGYudGVuc29yMmQoXG4gICAgICBbWzAsIDBdLCBbMSwgMF0sIFsxLCAzXSwgWzEsIDRdLCBbMywgMl0sIFszLCAzXV0sIFs2LCAyXSwgJ2ludDMyJyk7XG4gIGNvbnN0IHZhbCA9IFswLCAxMCwgMTMsIDE0LCAzMiwgMzNdO1xuICBjb25zdCBzaGFwZSA9IFs1LCA2XTtcbiAgcmV0dXJuIHtpbmQsIHZhbCwgc2hhcGV9O1xufVxuXG5mdW5jdGlvbiBzcGFyc2VUZW5zb3JWYWx1ZTJ4M3g0KCkge1xuICBjb25zdCBpbmQgPSB0Zi50ZW5zb3IyZChcbiAgICAgIFtcbiAgICAgICAgWzAsIDAsIDFdLCBbMCwgMSwgMF0sIFswLCAxLCAyXSwgWzEsIDAsIDNdLCBbMSwgMSwgMV0sIFsxLCAxLCAzXSxcbiAgICAgICAgWzEsIDIsIDJdXG4gICAgICBdLFxuICAgICAgWzcsIDNdLCAnaW50MzInKTtcbiAgY29uc3QgdmFsID0gWzEsIDEwLCAxMiwgMTAzLCAxMTEsIDExMywgMTIyXTtcbiAgY29uc3Qgc2hhcGUgPSBbMiwgMywgNF07XG4gIHJldHVybiB7aW5kLCB2YWwsIHNoYXBlfTtcbn1cbmRlc2NyaWJlV2l0aEZsYWdzKCdzcGFyc2VSZXNoYXBlJywgQUxMX0VOVlMsICgpID0+IHtcbiAgaXQoJ3ByZXNlcnZlIHN0YXRpYyBzaGFwZSBpbmZvJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNwYXJzZVRlbnNvciA9IHNwYXJzZVRlbnNvclZhbHVlNXg2KCk7XG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3BhcnNlLnNwYXJzZVJlc2hhcGUoXG4gICAgICAgIHNwYXJzZVRlbnNvci5pbmQsIHNwYXJzZVRlbnNvci5zaGFwZSwgWzEsIDUsIDIsIDNdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQub3V0cHV0U2hhcGUuZGF0YSgpLCBbMSwgNSwgMiwgM10pO1xuICB9KTtcblxuICBpdCgncHJlc2VydmUgc2hhcGUgaW5mbyB3aXRoIGluZmVycmVkIGRpbScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzcGFyc2VUZW5zb3IgPSBzcGFyc2VUZW5zb3JWYWx1ZTJ4M3g0KCk7XG4gICAgY29uc3QgcmVzdWx0ID1cbiAgICAgICAgdGYuc3BhcnNlLnNwYXJzZVJlc2hhcGUoc3BhcnNlVGVuc29yLmluZCwgc3BhcnNlVGVuc29yLnNoYXBlLCBbMiwgLTFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQub3V0cHV0U2hhcGUuZGF0YSgpLCBbMiwgMyAqIDRdKTtcbiAgfSk7XG5cbiAgaXQoJ2RvZXMgbm90IGhhdmUgbWVtb3J5IGxlYWsuJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGJlZm9yZURhdGFJZHMgPSB0Zi5lbmdpbmUoKS5iYWNrZW5kLm51bURhdGFJZHMoKTtcblxuICAgIGNvbnN0IHNwYXJzZVRlbnNvciA9IHNwYXJzZVRlbnNvclZhbHVlNXg2KCk7XG4gICAgY29uc3QgaW5kaWNlcyA9IHNwYXJzZVRlbnNvci5pbmQ7XG4gICAgY29uc3Qgc2hhcGUgPSB0Zi50ZW5zb3IxZChzcGFyc2VUZW5zb3Iuc2hhcGUsICdpbnQzMicpO1xuICAgIGNvbnN0IG5ld1NoYXBlID0gdGYudGVuc29yMWQoWzEsIDUsIDIsIDNdLCAnaW50MzInKTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5zcGFyc2Uuc3BhcnNlUmVzaGFwZShpbmRpY2VzLCBzaGFwZSwgbmV3U2hhcGUpO1xuXG4gICAgYXdhaXQgcmVzdWx0Lm91dHB1dEluZGljZXMuZGF0YSgpO1xuICAgIGF3YWl0IHJlc3VsdC5vdXRwdXRTaGFwZS5kYXRhKCk7XG5cbiAgICBjb25zdCBhZnRlclJlc0RhdGFJZHMgPSB0Zi5lbmdpbmUoKS5iYWNrZW5kLm51bURhdGFJZHMoKTtcbiAgICBleHBlY3QoYWZ0ZXJSZXNEYXRhSWRzKS50b0VxdWFsKGJlZm9yZURhdGFJZHMgKyA1KTtcblxuICAgIGluZGljZXMuZGlzcG9zZSgpO1xuICAgIHNoYXBlLmRpc3Bvc2UoKTtcbiAgICBuZXdTaGFwZS5kaXNwb3NlKCk7XG4gICAgcmVzdWx0Lm91dHB1dEluZGljZXMuZGlzcG9zZSgpO1xuICAgIHJlc3VsdC5vdXRwdXRTaGFwZS5kaXNwb3NlKCk7XG5cbiAgICBjb25zdCBhZnRlckRpc3Bvc2VEYXRhSWRzID0gdGYuZW5naW5lKCkuYmFja2VuZC5udW1EYXRhSWRzKCk7XG4gICAgZXhwZWN0KGFmdGVyRGlzcG9zZURhdGFJZHMpLnRvRXF1YWwoYmVmb3JlRGF0YUlkcyk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvdyBlcnJvciBpZiBtb3JlIHRoYW4gb25lIGluZmVycmVkIGRpbScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzcGFyc2VUZW5zb3IgPSBzcGFyc2VUZW5zb3JWYWx1ZTJ4M3g0KCk7XG4gICAgZXhwZWN0KCgpID0+IHRmLnNwYXJzZS5zcGFyc2VSZXNoYXBlKHNwYXJzZVRlbnNvci5pbmQsIHNwYXJzZVRlbnNvci5zaGFwZSwgW1xuICAgICAgLTEsIDIsIC0xXG4gICAgXSkpLnRvVGhyb3dFcnJvcigvb25seSBvbmUgb3V0cHV0IGRpbWVuc2lvbiBtYXkgYmUgLTEvKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93IGVycm9yIGlmIGltcG9zc2libGUgbmV3IHNoYXBlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNwYXJzZVRlbnNvciA9IHNwYXJzZVRlbnNvclZhbHVlMngzeDQoKTtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVJlc2hhcGUoc3BhcnNlVGVuc29yLmluZCwgc3BhcnNlVGVuc29yLnNoYXBlLCBbXG4gICAgICAtMSwgN1xuICAgIF0pKS50b1Rocm93RXJyb3IoL211bHRpcGxlIG9mIDcvKTtcbiAgfSk7XG4gIGl0KCd0aHJvdyBlcnJvciBpZiBuZWdhdGl2ZSBvdXRwdXQgZGltJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNwYXJzZVRlbnNvciA9IHNwYXJzZVRlbnNvclZhbHVlMngzeDQoKTtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVJlc2hhcGUoc3BhcnNlVGVuc29yLmluZCwgc3BhcnNlVGVuc29yLnNoYXBlLCBbXG4gICAgICAxLCAtN1xuICAgIF0pKS50b1Rocm93RXJyb3IoJ3NpemUgMSBtdXN0IGJlIG5vbi1uZWdhdGl2ZSwgbm90IC03Jyk7XG4gIH0pO1xuICBpdCgndGhyb3cgZXJyb3IgaWYgbmVnYXRpdmUgb3V0cHV0IGRpbScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzcGFyc2VUZW5zb3IgPSBzcGFyc2VUZW5zb3JWYWx1ZTJ4M3g0KCk7XG4gICAgZXhwZWN0KCgpID0+IHRmLnNwYXJzZS5zcGFyc2VSZXNoYXBlKHNwYXJzZVRlbnNvci5pbmQsIHNwYXJzZVRlbnNvci5zaGFwZSwgW1xuICAgICAgLTEsIDBcbiAgICBdKSkudG9UaHJvd0Vycm9yKC91bmxlc3MgYWxsIHNwZWNpZmllZCBpbnB1dCBzaXplcyBhcmUgbm9uLXplcm8vKTtcbiAgfSk7XG4gIGl0KCdzYW1lIHNoYXBlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNwYXJzZVRlbnNvciA9IHNwYXJzZVRlbnNvclZhbHVlNXg2KCk7XG4gICAgY29uc3QgcmVzdWx0ID1cbiAgICAgICAgdGYuc3BhcnNlLnNwYXJzZVJlc2hhcGUoc3BhcnNlVGVuc29yLmluZCwgc3BhcnNlVGVuc29yLnNoYXBlLCBbNSwgNl0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCByZXN1bHQub3V0cHV0SW5kaWNlcy5kYXRhKCksIGF3YWl0IHNwYXJzZVRlbnNvci5pbmQuZGF0YSgpKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQub3V0cHV0U2hhcGUuZGF0YSgpLCBzcGFyc2VUZW5zb3Iuc2hhcGUpO1xuICB9KTtcblxuICBpdCgnc2FtZSBzaGFwZSB3aXRoIGluZmVycmVkIGRpbScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzcGFyc2VUZW5zb3IgPSBzcGFyc2VUZW5zb3JWYWx1ZTV4NigpO1xuICAgIGNvbnN0IHJlc3VsdCA9XG4gICAgICAgIHRmLnNwYXJzZS5zcGFyc2VSZXNoYXBlKHNwYXJzZVRlbnNvci5pbmQsIHNwYXJzZVRlbnNvci5zaGFwZSwgWy0xLCA2XSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHJlc3VsdC5vdXRwdXRJbmRpY2VzLmRhdGEoKSwgYXdhaXQgc3BhcnNlVGVuc29yLmluZC5kYXRhKCkpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5vdXRwdXRTaGFwZS5kYXRhKCksIHNwYXJzZVRlbnNvci5zaGFwZSk7XG4gIH0pO1xuXG4gIGl0KCduZXcgc2hhcGUgd2l0aCBzYW1lIHJhbmsnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc3BhcnNlVGVuc29yID0gc3BhcnNlVGVuc29yVmFsdWU1eDYoKTtcbiAgICBjb25zdCByZXN1bHQgPVxuICAgICAgICB0Zi5zcGFyc2Uuc3BhcnNlUmVzaGFwZShzcGFyc2VUZW5zb3IuaW5kLCBzcGFyc2VUZW5zb3Iuc2hhcGUsIFszLCAxMF0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCByZXN1bHQub3V0cHV0SW5kaWNlcy5kYXRhKCksXG4gICAgICAgIFtbMCwgMF0sIFswLCA2XSwgWzAsIDldLCBbMSwgMF0sIFsyLCAwXSwgWzIsIDFdXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0Lm91dHB1dFNoYXBlLmRhdGEoKSwgWzMsIDEwXSk7XG4gIH0pO1xuXG4gIGl0KCduZXcgc2hhcGUgd2l0aCBzYW1lIHJhbmsgd2l0aCBpbmZlcnJlZCBkaW0nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc3BhcnNlVGVuc29yID0gc3BhcnNlVGVuc29yVmFsdWU1eDYoKTtcbiAgICBjb25zdCByZXN1bHQgPVxuICAgICAgICB0Zi5zcGFyc2Uuc3BhcnNlUmVzaGFwZShzcGFyc2VUZW5zb3IuaW5kLCBzcGFyc2VUZW5zb3Iuc2hhcGUsIFszLCAtMV0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCByZXN1bHQub3V0cHV0SW5kaWNlcy5kYXRhKCksXG4gICAgICAgIFtbMCwgMF0sIFswLCA2XSwgWzAsIDldLCBbMSwgMF0sIFsyLCAwXSwgWzIsIDFdXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0Lm91dHB1dFNoYXBlLmRhdGEoKSwgWzMsIDEwXSk7XG4gIH0pO1xuICBpdCgndXAgcmFuaycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzcGFyc2VUZW5zb3IgPSBzcGFyc2VUZW5zb3JWYWx1ZTV4NigpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VSZXNoYXBlKFxuICAgICAgICBzcGFyc2VUZW5zb3IuaW5kLCBzcGFyc2VUZW5zb3Iuc2hhcGUsIFsyLCAzLCA1XSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHJlc3VsdC5vdXRwdXRJbmRpY2VzLmRhdGEoKSxcbiAgICAgICAgW1swLCAwLCAwXSwgWzAsIDEsIDFdLCBbMCwgMSwgNF0sIFswLCAyLCAwXSwgWzEsIDEsIDBdLCBbMSwgMSwgMV1dKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQub3V0cHV0U2hhcGUuZGF0YSgpLCBbMiwgMywgNV0pO1xuICB9KTtcbiAgaXQoJ3VwIHJhbmsgd2l0aCBpbmZlcnJlZCBkaW0nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc3BhcnNlVGVuc29yID0gc3BhcnNlVGVuc29yVmFsdWU1eDYoKTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5zcGFyc2Uuc3BhcnNlUmVzaGFwZShcbiAgICAgICAgc3BhcnNlVGVuc29yLmluZCwgc3BhcnNlVGVuc29yLnNoYXBlLCBbMiwgLTEsIDVdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgcmVzdWx0Lm91dHB1dEluZGljZXMuZGF0YSgpLFxuICAgICAgICBbWzAsIDAsIDBdLCBbMCwgMSwgMV0sIFswLCAxLCA0XSwgWzAsIDIsIDBdLCBbMSwgMSwgMF0sIFsxLCAxLCAxXV0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5vdXRwdXRTaGFwZS5kYXRhKCksIFsyLCAzLCA1XSk7XG4gIH0pO1xuXG4gIGl0KCdkb3duIHJhbmsnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc3BhcnNlVGVuc29yID0gc3BhcnNlVGVuc29yVmFsdWUyeDN4NCgpO1xuICAgIGNvbnN0IHJlc3VsdCA9XG4gICAgICAgIHRmLnNwYXJzZS5zcGFyc2VSZXNoYXBlKHNwYXJzZVRlbnNvci5pbmQsIHNwYXJzZVRlbnNvci5zaGFwZSwgWzYsIDRdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgcmVzdWx0Lm91dHB1dEluZGljZXMuZGF0YSgpLFxuICAgICAgICBbWzAsIDFdLCBbMSwgMF0sIFsxLCAyXSwgWzMsIDNdLCBbNCwgMV0sIFs0LCAzXSwgWzUsIDJdXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0Lm91dHB1dFNoYXBlLmRhdGEoKSwgWzYsIDRdKTtcbiAgfSk7XG5cbiAgaXQoJ2Rvd24gcmFuayB3aXRoIGluZmVycmVkIGRpbScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzcGFyc2VUZW5zb3IgPSBzcGFyc2VUZW5zb3JWYWx1ZTJ4M3g0KCk7XG4gICAgY29uc3QgcmVzdWx0ID1cbiAgICAgICAgdGYuc3BhcnNlLnNwYXJzZVJlc2hhcGUoc3BhcnNlVGVuc29yLmluZCwgc3BhcnNlVGVuc29yLnNoYXBlLCBbNiwgLTFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgcmVzdWx0Lm91dHB1dEluZGljZXMuZGF0YSgpLFxuICAgICAgICBbWzAsIDFdLCBbMSwgMF0sIFsxLCAyXSwgWzMsIDNdLCBbNCwgMV0sIFs0LCAzXSwgWzUsIDJdXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0Lm91dHB1dFNoYXBlLmRhdGEoKSwgWzYsIDRdKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93IGVycm9yIGlmIG1pc21hdGNoIHNpemUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc3BhcnNlVGVuc29yID0gc3BhcnNlVGVuc29yVmFsdWU1eDYoKTtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVJlc2hhcGUoc3BhcnNlVGVuc29yLmluZCwgc3BhcnNlVGVuc29yLnNoYXBlLCBbXG4gICAgICA0LCA3XG4gICAgXSkpLnRvVGhyb3dFcnJvcigvSW5wdXQgdG8gcmVzaGFwZSBpcyBhIHRlbnNvciB3aXRoIDMwIGRlbnNlIHZhbHVlcy8pO1xuICB9KTtcbn0pO1xuIl19
\No newline at end of file