gx
chenyc
2025-02-12 ea42ff3ebee1eeb3fb29423aa848a249441db81c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/**
 * @license
 * Copyright 2020 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */
import * as tf from '../index';
import { ALL_ENVS, describeWithFlags } from '../jasmine_util';
import { expectArraysClose } from '../test_util';
describeWithFlags('slice2d', ALL_ENVS, () => {
    it('slicing a 1x1 from a 1x1 returns a 1x1', () => {
        const a = tf.tensor2d([0], [1, 1]);
        const b = tf.slice2d(a, [0, 0], [1, 1]);
        expect(b.shape).toEqual([1, 1]);
    });
    it('returns a tensor of slice size', () => {
        const a = tf.zeros([100, 100]);
        const b = tf.slice2d(a, [0, 0], [12, 34]);
        expect(b.shape).toEqual([12, 34]);
    });
    it('returns the upper-left submatrix when begin is [0, 0]', async () => {
        const a = tf.randomUniform([10, 10], -1, 1);
        const b = tf.slice2d(a, [0, 0], [2, 2]);
        const aValues = await a.data();
        expectArraysClose(await b.data(), [aValues[0], aValues[1], aValues[10], aValues[11]]);
    });
    it('returns the rectangle specified', async () => {
        const a = tf.tensor2d([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [4, 3]);
        const b = tf.slice2d(a, [1, 1], [3, 2]);
        expectArraysClose(await b.data(), [5, 6, 8, 9, 11, 12]);
    });
    it('throws when requesting out of bounds slice', () => {
        const a = tf.tensor2d([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], [4, 3]);
        expect(() => tf.slice2d(a, [1, 1], [10, 10])).toThrowError();
    });
    it('grad', async () => {
        const a = tf.tensor2d([[1, 2, 3], [4, 5, 6]]);
        const dy = tf.tensor2d([[20], [50]]);
        const da = tf.grad((x) => tf.slice2d(a, [0, 1], [2, 1]))(a, dy);
        expect(da.shape).toEqual([2, 3]);
        expectArraysClose(await da.data(), [0, 20, 0, 0, 50, 0]);
    });
    it('accepts a tensor-like object', () => {
        const a = [[0]]; // 1x1
        const b = tf.slice2d(a, [0, 0], [1, 1]);
        expect(b.shape).toEqual([1, 1]);
    });
    it('slice an already sliced tensor, first was not continous', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [0, 1]);
        const c = tf.slice(b, [1, 1], [1, 1]);
        expect(c.shape).toEqual([1, 1]);
        expectArraysClose(await c.data(), [7]);
    });
    it('slice an already sliced tensor, first was continous', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [1, 0]);
        const c = tf.slice(b, [1, 0]);
        expect(c.shape).toEqual([1, 4]);
        expectArraysClose(await c.data(), [9, 10, 11, 12]);
    });
    it('slice an already sliced tensor and do async read', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [0, 1]);
        const c = tf.slice(b, [1, 1], [1, 1]);
        expect(c.shape).toEqual([1, 1]);
        expectArraysClose(await c.data(), new Float32Array([7]));
    });
    it('square a sliced texture, followed by non-sliced texture of same shape', async () => {
        // Make a 2x3 tensor, upload to gpu and reshape to 3x2.
        const input = tf.tensor([[1, 2, 3], [4, 5, 6]]).abs().as2D(3, 2);
        const slicedInput = tf.slice(input, [0, 0], [3, 2]);
        // First square program takes the sliced input.
        const a = slicedInput.square();
        expectArraysClose(await a.data(), [1, 4, 9, 16, 25, 36]);
        // Second square program takes the non-sliced input.
        const b = tf.square(input);
        expectArraysClose(await b.data(), [1, 4, 9, 16, 25, 36]);
    });
    it('square a non-sliced texture, followed by a sliced texture of same shape', async () => {
        // Make a 2x3 tensor, upload to gpu and reshape to 3x2.
        const input = tf.tensor([[1, 2, 3], [4, 5, 6]]).abs().as2D(3, 2);
        // Make a sliced version of the same tensor with the same shape.
        const slicedInput = tf.slice(input, [0, 0], [3, 2]);
        // First square program takes the non-sliced input.
        const a = input.square();
        expectArraysClose(await a.data(), [1, 4, 9, 16, 25, 36]);
        // Second square program takes the sliced input.
        const b = tf.square(slicedInput);
        expectArraysClose(await b.data(), [1, 4, 9, 16, 25, 36]);
    });
    it('slice a tensor and do async read', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [0, 1], [3, 2]);
        expect(b.shape).toEqual([3, 2]);
        const vals = await b.data();
        expectArraysClose(vals, new Float32Array([2, 3, 6, 7, 10, 11]));
    });
    it('flatten a sliced tensor that was continuous in memory', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [1, 0]).flatten();
        expect(b.shape).toEqual([8]);
        expectArraysClose(await b.data(), [5, 6, 7, 8, 9, 10, 11, 12]);
    });
    it('slice a tensor that was not continuous in memory', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [0, 1]);
        expect(b.shape).toEqual([3, 3]);
        expectArraysClose(await b.data(), [2, 3, 4, 6, 7, 8, 10, 11, 12]);
    });
    it('flatten a sliced tensor that was not continuous in memory', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [0, 1]).flatten();
        expect(b.shape).toEqual([9]);
        expectArraysClose(await b.data(), [2, 3, 4, 6, 7, 8, 10, 11, 12]);
    });
    it('flatten a sliced tensor not continuous in memory and run program', async () => {
        const a = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
        ]; // 3x4.
        const b = tf.slice(a, [0, 1]).flatten();
        const c = tf.square(b);
        expectArraysClose(await c.data(), [4, 9, 16, 36, 49, 64, 100, 121, 144]);
    });
    it('reshape a sliced 1d into a 2d tensor', async () => {
        const a = [1, 2, 3, 4, 5];
        const b = tf.slice(a, 1).as2D(2, 2);
        expect(b.shape).toEqual([2, 2]);
        expectArraysClose(await b.data(), [2, 3, 4, 5]);
    });
    it('reshape a sliced 1d into a 2d tensor and run program', async () => {
        const a = [1, 2, 3, 4, 5];
        const b = tf.slice(a, 1).as2D(2, 2).square();
        expect(b.shape).toEqual([2, 2]);
        expectArraysClose(await b.data(), [4, 9, 16, 25]);
    });
    it('broadcast the original with the sliced tensor', async () => {
        const a = [[1, 2], [3, 4]];
        const b = tf.slice(a, [0, 1]);
        const c = tf.add(a, b);
        expect(c.shape).toEqual([2, 2]);
        expectArraysClose(await c.data(), [3, 4, 7, 8]);
    });
    it('zero-sized slice out of a non-zero sized tensor', async () => {
        const a = tf.zeros([4, 2]);
        const res = tf.slice(a, [0, 0], [0, 2]);
        expect(res.shape).toEqual([0, 2]);
        expectArraysClose(await res.data(), []);
    });
    it('zero-sized slice out of a zero-sized tensor', async () => {
        const a = tf.zeros([0, 4]);
        const res = tf.slice(a, [0, 1], [0, 3]);
        expect(res.shape).toEqual([0, 3]);
        expectArraysClose(await res.data(), []);
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpY2UyZF90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvc2xpY2UyZF90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQy9CLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFHL0MsaUJBQWlCLENBQUMsU0FBUyxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7SUFDMUMsRUFBRSxDQUFDLHdDQUF3QyxFQUFFLEdBQUcsRUFBRTtRQUNoRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsZ0NBQWdDLEVBQUUsR0FBRyxFQUFFO1FBQ3hDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQVUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN4QyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDcEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsdURBQXVELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDckUsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBVSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNyRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRS9CLGlCQUFpQixDQUNiLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxRSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxpQ0FBaUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMvQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDMUQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsNENBQTRDLEVBQUUsR0FBRyxFQUFFO1FBQ3BELE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkUsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMvRCxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDcEIsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMs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LEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQyxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUMxQyxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7ZXhwZWN0QXJyYXlzQ2xvc2V9IGZyb20gJy4uL3Rlc3RfdXRpbCc7XG5pbXBvcnQge1Jhbmt9IGZyb20gJy4uL3R5cGVzJztcblxuZGVzY3JpYmVXaXRoRmxhZ3MoJ3NsaWNlMmQnLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgnc2xpY2luZyBhIDF4MSBmcm9tIGEgMXgxIHJldHVybnMgYSAxeDEnLCAoKSA9PiB7XG4gICAgY29uc3QgYSA9IHRmLnRlbnNvcjJkKFswXSwgWzEsIDFdKTtcbiAgICBjb25zdCBiID0gdGYuc2xpY2UyZChhLCBbMCwgMF0sIFsxLCAxXSk7XG4gICAgZXhwZWN0KGIuc2hhcGUpLnRvRXF1YWwoWzEsIDFdKTtcbiAgfSk7XG5cbiAgaXQoJ3JldHVybnMgYSB0ZW5zb3Igb2Ygc2xpY2Ugc2l6ZScsICgpID0+IHtcbiAgICBjb25zdCBhID0gdGYuemVyb3M8UmFuay5SMj4oWzEwMCwgMTAwXSk7XG4gICAgY29uc3QgYiA9IHRmLnNsaWNlMmQoYSwgWzAsIDBdLCBbMTIsIDM0XSk7XG4gICAgZXhwZWN0KGIuc2hhcGUpLnRvRXF1YWwoWzEyLCAzNF0pO1xuICB9KTtcblxuICBpdCgncmV0dXJucyB0aGUgdXBwZXItbGVmdCBzdWJtYXRyaXggd2hlbiBiZWdpbiBpcyBbMCwgMF0nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYSA9IHRmLnJhbmRvbVVuaWZvcm08UmFuay5SMj4oWzEwLCAxMF0sIC0xLCAxKTtcbiAgICBjb25zdCBiID0gdGYuc2xpY2UyZChhLCBbMCwgMF0sIFsyLCAyXSk7XG4gICAgY29uc3QgYVZhbHVlcyA9IGF3YWl0IGEuZGF0YSgpO1xuXG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IGIuZGF0YSgpLCBbYVZhbHVlc1swXSwgYVZhbHVlc1sxXSwgYVZhbHVlc1sxMF0sIGFWYWx1ZXNbMTFdXSk7XG4gIH0pO1xuXG4gIGl0KCdyZXR1cm5zIHRoZSByZWN0YW5nbGUgc3BlY2lmaWVkJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSB0Zi50ZW5zb3IyZChbMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMl0sIFs0LCAzXSk7XG4gICAgY29uc3QgYiA9IHRmLnNsaWNlMmQoYSwgWzEsIDFdLCBbMywgMl0pO1xuXG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgYi5kYXRhKCksIFs1LCA2LCA4LCA5LCAxMSwgMTJdKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIHJlcXVlc3Rpbmcgb3V0IG9mIGJvdW5kcyBzbGljZScsICgpID0+IHtcbiAgICBjb25zdCBhID0gdGYudGVuc29yMmQoWzEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTJdLCBbNCwgM10pO1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5zbGljZTJkKGEsIFsxLCAxXSwgWzEwLCAxMF0pKS50b1Rocm93RXJyb3IoKTtcbiAgfSk7XG5cbiAgaXQoJ2dyYWQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYSA9IHRmLnRlbnNvcjJkKFtbMSwgMiwgM10sIFs0LCA1LCA2XV0pO1xuICAgIGNvbnN0IGR5ID0gdGYudGVuc29yMmQoW1syMF0sIFs1MF1dKTtcbiAgICBjb25zdCBkYSA9XG4gICAgICAgIHRmLmdyYWQoKHg6IHRmLlRlbnNvcjJEKSA9PiB0Zi5zbGljZTJkKGEsIFswLCAxXSwgWzIsIDFdKSkoYSwgZHkpO1xuICAgIGV4cGVjdChkYS5zaGFwZSkudG9FcXVhbChbMiwgM10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IGRhLmRhdGEoKSwgWzAsIDIwLCAwLCAwLCA1MCwgMF0pO1xuICB9KTtcblxuICBpdCgnYWNjZXB0cyBhIHRlbnNvci1saWtlIG9iamVjdCcsICgpID0+IHtcbiAgICBjb25zdCBhID0gW1swXV07ICAvLyAxeDFcbiAgICBjb25zdCBiID0gdGYuc2xpY2UyZChhLCBbMCwgMF0sIFsxLCAxXSk7XG4gICAgZXhwZWN0KGIuc2hhcGUpLnRvRXF1YWwoWzEsIDFdKTtcbiAgfSk7XG5cbiAgaXQoJ3NsaWNlIGFuIGFscmVhZHkgc2xpY2VkIHRlbnNvciwgZmlyc3Qgd2FzIG5vdCBjb250aW5vdXMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYSA9IFtcbiAgICAgIFsxLCAyLCAzLCA0XSxcbiAgICAgIFs1LCA2LCA3LCA4XSxcbiAgICAgIFs5LCAxMCwgMTEsIDEyXSxcbiAgICBdOyAgLy8gM3g0LlxuICAgIGNvbnN0IGIgPSB0Zi5zbGljZShhLCBbMCwgMV0pO1xuICAgIGNvbnN0IGMgPSB0Zi5zbGljZShiLCBbMSwgMV0sIFsxLCAxXSk7XG4gICAgZXhwZWN0KGMuc2hhcGUpLnRvRXF1YWwoWzEsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBjLmRhdGEoKSwgWzddKTtcbiAgfSk7XG5cbiAgaXQoJ3NsaWNlIGFuIGFscmVhZHkgc2xpY2VkIHRlbnNvciwgZmlyc3Qgd2FzIGNvbnRpbm91cycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBhID0gW1xuICAgICAgWzEsIDIsIDMsIDRdLFxuICAgICAgWzUsIDYsIDcsIDhdLFxuICAgICAgWzksIDEwLCAxMSwgMTJdLFxuICAgIF07ICAvLyAzeDQuXG4gICAgY29uc3QgYiA9IHRmLnNsaWNlKGEsIFsxLCAwXSk7XG4gICAgY29uc3QgYyA9IHRmLnNsaWNlKGIsIFsxLCAwXSk7XG4gICAgZXhwZWN0KGMuc2hhcGUpLnRvRXF1YWwoWzEsIDRdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBjLmRhdGEoKSwgWzksIDEwLCAxMSwgMTJdKTtcbiAgfSk7XG5cbiAgaXQoJ3NsaWNlIGFuIGFscmVhZHkgc2xpY2VkIHRlbnNvciBhbmQgZG8gYXN5bmMgcmVhZCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBhID0gW1xuICAgICAgWzEsIDIsIDMsIDRdLFxuICAgICAgWzUsIDYsIDcsIDhdLFxuICAgICAgWzksIDEwLCAxMSwgMTJdLFxuICAgIF07ICAvLyAzeDQuXG4gICAgY29uc3QgYiA9IHRmLnNsaWNlKGEsIFswLCAxXSk7XG4gICAgY29uc3QgYyA9IHRmLnNsaWNlKGIsIFsxLCAxXSwgWzEsIDFdKTtcbiAgICBleHBlY3QoYy5zaGFwZSkudG9FcXVhbChbMSwgMV0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IGMuZGF0YSgpLCBuZXcgRmxvYXQzMkFycmF5KFs3XSkpO1xuICB9KTtcblxuICBpdCgnc3F1YXJlIGEgc2xpY2VkIHRleHR1cmUsIGZvbGxvd2VkIGJ5IG5vbi1zbGljZWQgdGV4dHVyZSBvZiBzYW1lIHNoYXBlJyxcbiAgICAgYXN5bmMgKCkgPT4geyAgLy8gVGVzdHMgY29sbGlzaW9ucyBpbiB0aGUgc2hhZGVyIGNhY2hlLlxuICAgICAgIC8vIE1ha2UgYSAyeDMgdGVuc29yLCB1cGxvYWQgdG8gZ3B1IGFuZCByZXNoYXBlIHRvIDN4Mi5cbiAgICAgICBjb25zdCBpbnB1dCA9IHRmLnRlbnNvcihbWzEsIDIsIDNdLCBbNCwgNSwgNl1dKS5hYnMoKS5hczJEKDMsIDIpO1xuICAgICAgIGNvbnN0IHNsaWNlZElucHV0ID0gdGYuc2xpY2UoaW5wdXQsIFswLCAwXSwgWzMsIDJdKTtcbiAgICAgICAvLyBGaXJzdCBzcXVhcmUgcHJvZ3JhbSB0YWtlcyB0aGUgc2xpY2VkIGlucHV0LlxuICAgICAgIGNvbnN0IGEgPSBzbGljZWRJbnB1dC5zcXVhcmUoKTtcbiAgICAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBhLmRhdGEoKSwgWzEsIDQsIDksIDE2LCAyNSwgMzZdKTtcbiAgICAgICAvLyBTZWNvbmQgc3F1YXJlIHByb2dyYW0gdGFrZXMgdGhlIG5vbi1zbGljZWQgaW5wdXQuXG4gICAgICAgY29uc3QgYiA9IHRmLnNxdWFyZShpbnB1dCk7XG4gICAgICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgYi5kYXRhKCksIFsxLCA0LCA5LCAxNiwgMjUsIDM2XSk7XG4gICAgIH0pO1xuXG4gIGl0KCdzcXVhcmUgYSBub24tc2xpY2VkIHRleHR1cmUsIGZvbGxvd2VkIGJ5IGEgc2xpY2VkIHRleHR1cmUgb2Ygc2FtZSBzaGFwZScsXG4gICAgIGFzeW5jICgpID0+IHsgIC8vIFRlc3RzIGNvbGxpc2lvbnMgaW4gdGhlIHNoYWRlciBjYWNoZS5cbiAgICAgICAvLyBNYWtlIGEgMngzIHRlbnNvciwgdXBsb2FkIHRvIGdwdSBhbmQgcmVzaGFwZSB0byAzeDIuXG4gICAgICAgY29uc3QgaW5wdXQgPSB0Zi50ZW5zb3IoW1sxLCAyLCAzXSwgWzQsIDUsIDZdXSkuYWJzKCkuYXMyRCgzLCAyKTtcbiAgICAgICAvLyBNYWtlIGEgc2xpY2VkIHZlcnNpb24gb2YgdGhlIHNhbWUgdGVuc29yIHdpdGggdGhlIHNhbWUgc2hhcGUuXG4gICAgICAgY29uc3Qgc2xpY2VkSW5wdXQgPSB0Zi5zbGljZShpbnB1dCwgWzAsIDBdLCBbMywgMl0pO1xuICAgICAgIC8vIEZpcnN0IHNxdWFyZSBwcm9ncmFtIHRha2VzIHRoZSBub24tc2xpY2VkIGlucHV0LlxuICAgICAgIGNvbnN0IGEgPSBpbnB1dC5zcXVhcmUoKTtcbiAgICAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBhLmRhdGEoKSwgWzEsIDQsIDksIDE2LCAyNSwgMzZdKTtcbiAgICAgICAvLyBTZWNvbmQgc3F1YXJlIHByb2dyYW0gdGFrZXMgdGhlIHNsaWNlZCBpbnB1dC5cbiAgICAgICBjb25zdCBiID0gdGYuc3F1YXJlKHNsaWNlZElucHV0KTtcbiAgICAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBiLmRhdGEoKSwgWzEsIDQsIDksIDE2LCAyNSwgMzZdKTtcbiAgICAgfSk7XG5cbiAgaXQoJ3NsaWNlIGEgdGVuc29yIGFuZCBkbyBhc3luYyByZWFkJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSBbXG4gICAgICBbMSwgMiwgMywgNF0sXG4gICAgICBbNSwgNiwgNywgOF0sXG4gICAgICBbOSwgMTAsIDExLCAxMl0sXG4gICAgXTsgIC8vIDN4NC5cbiAgICBjb25zdCBiID0gdGYuc2xpY2UoYSwgWzAsIDFdLCBbMywgMl0pO1xuICAgIGV4cGVjdChiLnNoYXBlKS50b0VxdWFsKFszLCAyXSk7XG4gICAgY29uc3QgdmFscyA9IGF3YWl0IGIuZGF0YSgpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKHZhbHMsIG5ldyBGbG9hdDMyQXJyYXkoWzIsIDMsIDYsIDcsIDEwLCAxMV0pKTtcbiAgfSk7XG5cbiAgaXQoJ2ZsYXR0ZW4gYSBzbGljZWQgdGVuc29yIHRoYXQgd2FzIGNvbnRpbnVvdXMgaW4gbWVtb3J5JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSBbXG4gICAgICBbMSwgMiwgMywgNF0sXG4gICAgICBbNSwgNiwgNywgOF0sXG4gICAgICBbOSwgMTAsIDExLCAxMl0sXG4gICAgXTsgIC8vIDN4NC5cbiAgICBjb25zdCBiID0gdGYuc2xpY2UoYSwgWzEsIDBdKS5mbGF0dGVuKCk7XG4gICAgZXhwZWN0KGIuc2hhcGUpLnRvRXF1YWwoWzhdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBiLmRhdGEoKSwgWzUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTJdKTtcbiAgfSk7XG5cbiAgaXQoJ3NsaWNlIGEgdGVuc29yIHRoYXQgd2FzIG5vdCBjb250aW51b3VzIGluIG1lbW9yeScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBhID0gW1xuICAgICAgWzEsIDIsIDMsIDRdLFxuICAgICAgWzUsIDYsIDcsIDhdLFxuICAgICAgWzksIDEwLCAxMSwgMTJdLFxuICAgIF07ICAvLyAzeDQuXG4gICAgY29uc3QgYiA9IHRmLnNsaWNlKGEsIFswLCAxXSk7XG4gICAgZXhwZWN0KGIuc2hhcGUpLnRvRXF1YWwoWzMsIDNdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBiLmRhdGEoKSwgWzIsIDMsIDQsIDYsIDcsIDgsIDEwLCAxMSwgMTJdKTtcbiAgfSk7XG5cbiAgaXQoJ2ZsYXR0ZW4gYSBzbGljZWQgdGVuc29yIHRoYXQgd2FzIG5vdCBjb250aW51b3VzIGluIG1lbW9yeScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBhID0gW1xuICAgICAgWzEsIDIsIDMsIDRdLFxuICAgICAgWzUsIDYsIDcsIDhdLFxuICAgICAgWzksIDEwLCAxMSwgMTJdLFxuICAgIF07ICAvLyAzeDQuXG4gICAgY29uc3QgYiA9IHRmLnNsaWNlKGEsIFswLCAxXSkuZmxhdHRlbigpO1xuICAgIGV4cGVjdChiLnNoYXBlKS50b0VxdWFsKFs5XSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgYi5kYXRhKCksIFsyLCAzLCA0LCA2LCA3LCA4LCAxMCwgMTEsIDEyXSk7XG4gIH0pO1xuXG4gIGl0KCdmbGF0dGVuIGEgc2xpY2VkIHRlbnNvciBub3QgY29udGludW91cyBpbiBtZW1vcnkgYW5kIHJ1biBwcm9ncmFtJyxcbiAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgIGNvbnN0IGEgPSBbXG4gICAgICAgICBbMSwgMiwgMywgNF0sXG4gICAgICAgICBbNSwgNiwgNywgOF0sXG4gICAgICAgICBbOSwgMTAsIDExLCAxMl0sXG4gICAgICAgXTsgIC8vIDN4NC5cbiAgICAgICBjb25zdCBiID0gdGYuc2xpY2UoYSwgWzAsIDFdKS5mbGF0dGVuKCk7XG4gICAgICAgY29uc3QgYyA9IHRmLnNxdWFyZShiKTtcbiAgICAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBjLmRhdGEoKSwgWzQsIDksIDE2LCAzNiwgNDksIDY0LCAxMDAsIDEyMSwgMTQ0XSk7XG4gICAgIH0pO1xuXG4gIGl0KCdyZXNoYXBlIGEgc2xpY2VkIDFkIGludG8gYSAyZCB0ZW5zb3InLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYSA9IFsxLCAyLCAzLCA0LCA1XTtcbiAgICBjb25zdCBiID0gdGYuc2xpY2UoYSwgMSkuYXMyRCgyLCAyKTtcbiAgICBleHBlY3QoYi5zaGFwZSkudG9FcXVhbChbMiwgMl0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IGIuZGF0YSgpLCBbMiwgMywgNCwgNV0pO1xuICB9KTtcblxuICBpdCgncmVzaGFwZSBhIHNsaWNlZCAxZCBpbnRvIGEgMmQgdGVuc29yIGFuZCBydW4gcHJvZ3JhbScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBhID0gWzEsIDIsIDMsIDQsIDVdO1xuICAgIGNvbnN0IGIgPSB0Zi5zbGljZShhLCAxKS5hczJEKDIsIDIpLnNxdWFyZSgpO1xuICAgIGV4cGVjdChiLnNoYXBlKS50b0VxdWFsKFsyLCAyXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgYi5kYXRhKCksIFs0LCA5LCAxNiwgMjVdKTtcbiAgfSk7XG5cbiAgaXQoJ2Jyb2FkY2FzdCB0aGUgb3JpZ2luYWwgd2l0aCB0aGUgc2xpY2VkIHRlbnNvcicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBhID0gW1sxLCAyXSwgWzMsIDRdXTtcbiAgICBjb25zdCBiID0gdGYuc2xpY2UoYSwgWzAsIDFdKTtcbiAgICBjb25zdCBjID0gdGYuYWRkKGEsIGIpO1xuICAgIGV4cGVjdChjLnNoYXBlKS50b0VxdWFsKFsyLCAyXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgYy5kYXRhKCksIFszLCA0LCA3LCA4XSk7XG4gIH0pO1xuXG4gIGl0KCd6ZXJvLXNpemVkIHNsaWNlIG91dCBvZiBhIG5vbi16ZXJvIHNpemVkIHRlbnNvcicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBhID0gdGYuemVyb3MoWzQsIDJdKTtcbiAgICBjb25zdCByZXMgPSB0Zi5zbGljZShhLCBbMCwgMF0sIFswLCAyXSk7XG4gICAgZXhwZWN0KHJlcy5zaGFwZSkudG9FcXVhbChbMCwgMl0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlcy5kYXRhKCksIFtdKTtcbiAgfSk7XG5cbiAgaXQoJ3plcm8tc2l6ZWQgc2xpY2Ugb3V0IG9mIGEgemVyby1zaXplZCB0ZW5zb3InLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYSA9IHRmLnplcm9zKFswLCA0XSk7XG4gICAgY29uc3QgcmVzID0gdGYuc2xpY2UoYSwgWzAsIDFdLCBbMCwgM10pO1xuICAgIGV4cGVjdChyZXMuc2hhcGUpLnRvRXF1YWwoWzAsIDNdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXMuZGF0YSgpLCBbXSk7XG4gIH0pO1xufSk7XG4iXX0=