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 | */
|
17 | import * as tf from '../../index';
|
18 | import { ALL_ENVS, describeWithFlags } from '../../jasmine_util';
|
19 | import { expectArraysClose } from '../../test_util';
|
20 | function TensorValue3x4() {
|
21 | return tf.tensor2d([[1, 2, 3, 4], [-1, -2, -3, -4], [5, 6, 7, 8]]);
|
22 | }
|
23 | function TensorValue10() {
|
24 | return tf.tensor1d(Array.from(Array(10), (_, i) => i + 1));
|
25 | }
|
26 | function TensorValue10x4() {
|
27 | return tf.tensor2d(Array.from(Array(40), (_, i) => i + 1), [10, 4]);
|
28 | }
|
29 | function TensorValue10x2x4() {
|
30 | return tf.tensor3d(Array.from(Array(80), (_, i) => i + 1), [10, 2, 4]);
|
31 | }
|
32 | describeWithFlags('sparseSegmentSum', ALL_ENVS, () => {
|
33 | it('two rows one segment', async () => {
|
34 | const result = tf.sparse.sparseSegmentSum(TensorValue3x4(), [0, 1], [0, 0]);
|
35 | expectArraysClose(await result.data(), [[0, 0, 0, 0]]);
|
36 | });
|
37 | it('two rows two segments', async () => {
|
38 | const result = tf.sparse.sparseSegmentSum(TensorValue3x4(), [0, 1], [0, 1]);
|
39 | expectArraysClose(await result.data(), [[1, 2, 3, 4], [-1, -2, -3, -4]]);
|
40 | });
|
41 | it('all rows one segment', async () => {
|
42 | const result = tf.sparse.sparseSegmentSum(TensorValue3x4(), [0, 1, 2], [0, 0, 1]);
|
43 | expectArraysClose(await result.data(), [[0, 0, 0, 0], [5, 6, 7, 8]]);
|
44 | });
|
45 | it('0 dimensional input invalid', async () => {
|
46 | expect(() => tf.sparse.sparseSegmentSum(tf.scalar(1), [], []))
|
47 | .toThrowError(/should be at least 1 dimensional/);
|
48 | });
|
49 | it('1 dimensional input', async () => {
|
50 | const result = tf.sparse.sparseSegmentSum(TensorValue10(), [8, 3, 0, 9], [0, 1, 2, 2]);
|
51 | expectArraysClose(await result.data(), [9, 4, 11]);
|
52 | });
|
53 | it('3 dimensional input', async () => {
|
54 | const result = tf.sparse.sparseSegmentSum(TensorValue10x2x4(), [8, 3, 0, 9], [0, 1, 2, 2]);
|
55 | expectArraysClose(await result.data(), [
|
56 | [[65, 66, 67, 68], [69, 70, 71, 72]],
|
57 | [[25, 26, 27, 28], [29, 30, 31, 32]], [[74, 76, 78, 80], [82, 84, 86, 88]]
|
58 | ]);
|
59 | });
|
60 | it('segment ids hole', async () => {
|
61 | const result = tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [0, 3, 3, 3]);
|
62 | expectArraysClose(await result.data(), [[33, 34, 35, 36], [0, 0, 0, 0], [0, 0, 0, 0], [51, 54, 57, 60]]);
|
63 | });
|
64 | it('segment ids > zero', async () => {
|
65 | const result = tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [2, 3, 3, 3]);
|
66 | expectArraysClose(await result.data(), [[0, 0, 0, 0], [0, 0, 0, 0], [33, 34, 35, 36], [51, 54, 57, 60]]);
|
67 | });
|
68 | it('baseline valid', async () => {
|
69 | // Baseline for the *invalid* tests below.
|
70 | const result = tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [0, 1, 2, 2]);
|
71 | expectArraysClose(await result.data(), [[33, 34, 35, 36], [13, 14, 15, 16], [38, 40, 42, 44]]);
|
72 | });
|
73 | it('does not have memory leak.', async () => {
|
74 | const beforeDataIds = tf.engine().backend.numDataIds();
|
75 | const data = TensorValue3x4();
|
76 | const indices = tf.tensor1d([0, 1], 'int32');
|
77 | const segmentIds = tf.tensor1d([0, 0], 'int32');
|
78 | const result = tf.sparse.sparseSegmentSum(data, indices, segmentIds);
|
79 | await result.data();
|
80 | const afterResDataIds = tf.engine().backend.numDataIds();
|
81 | expect(afterResDataIds).toEqual(beforeDataIds + 4);
|
82 | data.dispose();
|
83 | indices.dispose();
|
84 | segmentIds.dispose();
|
85 | result.dispose();
|
86 | const afterDisposeDataIds = tf.engine().backend.numDataIds();
|
87 | expect(afterDisposeDataIds).toEqual(beforeDataIds);
|
88 | });
|
89 | it('indices invalid 1', async () => {
|
90 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, -1, 0, 9], [
|
91 | 0, 1, 2, 2
|
92 | ])).toThrowError(/indices\[1\] == -1 out of range \[0, 10\)/);
|
93 | });
|
94 | it('indices invalid 2', async () => {
|
95 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 10], [
|
96 | 0, 1, 2, 2
|
97 | ])).toThrowError(/indices\[3\] == 10 out of range \[0, 10\)/);
|
98 | });
|
99 | it('segments invalid 2', async () => {
|
100 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [
|
101 | 0, 1, 0, 1
|
102 | ])).toThrowError('segment ids are not increasing');
|
103 | });
|
104 | it('segments invalid 3', async () => {
|
105 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [0, 1, 2, 0]))
|
106 | .toThrowError('Segment id 1 out of range [0, 1), possibly because segmentIds ' +
|
107 | 'input is not sorted.');
|
108 | });
|
109 | it('segments invalid 4', async () => {
|
110 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [-1, 0, 1, 1]))
|
111 | .toThrowError('Segment id -1 out of range [0, 2), possibly because segmentIds ' +
|
112 | 'input is not sorted.');
|
113 | });
|
114 | it('segments invalid 6', async () => {
|
115 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [
|
116 | 0, 0, 0, -1
|
117 | ])).toThrowError('segment ids must be >= 0');
|
118 | });
|
119 | it('segments invalid 7', async () => {
|
120 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [
|
121 | 0, 0, 0, -2
|
122 | ])).toThrowError('segment ids must be >= 0');
|
123 | });
|
124 | it('indices invalid rank', async () => {
|
125 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [[8, 3, 0, 9]], [
|
126 | 0, 0, 0, -2
|
127 | ])).toThrowError(/should be Tensor1D/);
|
128 | });
|
129 | it('segments invalid rank', async () => {
|
130 | expect(() => tf.sparse.sparseSegmentSum(TensorValue10x4(), [8, 3, 0, 9], [
|
131 | [0, 0, 0, -2]
|
132 | ])).toThrowError(/should be Tensor1D/);
|
133 | });
|
134 | });
|
135 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhcnNlX3NlZ21lbnRfc3VtX3Rlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWNvcmUvc3JjL29wcy9zcGFyc2Uvc3BhcnNlX3NlZ21lbnRfc3VtX3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQy9ELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRWxELFNBQVMsY0FBYztJQUNyQixPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNyRSxDQUFDO0FBRUQsU0FBUyxhQUFhO0lBQ3BCLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzdELENBQUM7QUFFRCxTQUFTLGVBQWU7SUFDdEIsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMs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Q0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRCxpQkFBaUIsQ0FDYixNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFDbkIsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNsQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUNyQyxlQUFlLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRCxpQkFBaUIsQ0FDYixNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFDbkIsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4RSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM5Qiww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QUFJLEVBQUU7UUFDckMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRTtZQUN2RSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1NBQ2QsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDekMsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDIxIEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0ICogYXMgdGYgZnJvbSAnLi4vLi4vaW5kZXgnO1xuaW1wb3J0IHtBTExfRU5WUywgZGVzY3JpYmVXaXRoRmxhZ3N9IGZyb20gJy4uLy4uL2phc21pbmVfdXRpbCc7XG5pbXBvcnQge2V4cGVjdEFycmF5c0Nsb3NlfSBmcm9tICcuLi8uLi90ZXN0X3V0aWwnO1xuXG5mdW5jdGlvbiBUZW5zb3JWYWx1ZTN4NCgpIHtcbiAgcmV0dXJuIHRmLnRlbnNvcjJkKFtbMSwgMiwgMywgNF0sIFstMSwgLTIsIC0zLCAtNF0sIFs1LCA2LCA3LCA4XV0pO1xufVxuXG5mdW5jdGlvbiBUZW5zb3JWYWx1ZTEwKCkge1xuICByZXR1cm4gdGYudGVuc29yMWQoQXJyYXkuZnJvbShBcnJheSgxMCksIChfLCBpKSA9PiBpICsgMSkpO1xufVxuXG5mdW5jdGlvbiBUZW5zb3JWYWx1ZTEweDQoKSB7XG4gIHJldHVybiB0Zi50ZW5zb3IyZChBcnJheS5mcm9tKEFycmF5KDQwKSwgKF8sIGkpID0+IGkgKyAxKSwgWzEwLCA0XSk7XG59XG5cbmZ1bmN0aW9uIFRlbnNvclZhbHVlMTB4Mng0KCkge1xuICByZXR1cm4gdGYudGVuc29yM2QoQXJyYXkuZnJvbShBcnJheSg4MCksIChfLCBpKSA9PiBpICsgMSksIFsxMCwgMiwgNF0pO1xufVxuXG5kZXNjcmliZVdpdGhGbGFncygnc3BhcnNlU2VnbWVudFN1bScsIEFMTF9FTlZTLCAoKSA9PiB7XG4gIGl0KCd0d28gcm93cyBvbmUgc2VnbWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudFN1bShUZW5zb3JWYWx1ZTN4NCgpLCBbMCwgMV0sIFswLCAwXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgW1swLCAwLCAwLCAwXV0pO1xuICB9KTtcblxuICBpdCgndHdvIHJvd3MgdHdvIHNlZ21lbnRzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKFRlbnNvclZhbHVlM3g0KCksIFswLCAxXSwgWzAsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBbWzEsIDIsIDMsIDRdLCBbLTEsIC0yLCAtMywgLTRdXSk7XG4gIH0pO1xuXG4gIGl0KCdhbGwgcm93cyBvbmUgc2VnbWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPVxuICAgICAgICB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudFN1bShUZW5zb3JWYWx1ZTN4NCgpLCBbMCwgMSwgMl0sIFswLCAwLCAxXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgW1swLCAwLCAwLCAwXSwgWzUsIDYsIDcsIDhdXSk7XG4gIH0pO1xuXG4gIGl0KCcwIGRpbWVuc2lvbmFsIGlucHV0IGludmFsaWQnLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKHRmLnNjYWxhcigxKSwgW10sIFtdKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcigvc2hvdWxkIGJlIGF0IGxlYXN0IDEgZGltZW5zaW9uYWwvKTtcbiAgfSk7XG5cbiAgaXQoJzEgZGltZW5zaW9uYWwgaW5wdXQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID1cbiAgICAgICAgdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oVGVuc29yVmFsdWUxMCgpLCBbOCwgMywgMCwgOV0sIFswLCAxLCAyLCAyXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgWzksIDQsIDExXSk7XG4gIH0pO1xuXG4gIGl0KCczIGRpbWVuc2lvbmFsIGlucHV0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKFxuICAgICAgICBUZW5zb3JWYWx1ZTEweDJ4NCgpLCBbOCwgMywgMCwgOV0sIFswLCAxLCAyLCAyXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgW1xuICAgICAgW1s2NSwgNjYsIDY3LCA2OF0sIFs2OSwgNzAsIDcxLCA3Ml1dLFxuICAgICAgW1syNSwgMjYsIDI3LCAyOF0sIFsyOSwgMzAsIDMxLCAzMl1dLCBbWzc0LCA3NiwgNzgsIDgwXSwgWzgyLCA4NCwgODYsIDg4XV1cbiAgICBdKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZ21lbnQgaWRzIGhvbGUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oXG4gICAgICAgIFRlbnNvclZhbHVlMTB4NCgpLCBbOCwgMywgMCwgOV0sIFswLCAzLCAzLCAzXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHJlc3VsdC5kYXRhKCksXG4gICAgICAgIFtbMzMsIDM0LCAzNSwgMzZdLCBbMCwgMCwgMCwgMF0sIFswLCAwLCAwLCAwXSwgWzUxLCA1NCwgNTcsIDYwXV0pO1xuICB9KTtcblxuICBpdCgnc2VnbWVudCBpZHMgPiB6ZXJvJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKFxuICAgICAgICBUZW5zb3JWYWx1ZTEweDQoKSwgWzgsIDMsIDAsIDldLCBbMiwgMywgMywgM10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCByZXN1bHQuZGF0YSgpLFxuICAgICAgICBbWzAsIDAsIDAsIDBdLCBbMCwgMCwgMCwgMF0sIFszMywgMzQsIDM1LCAzNl0sIFs1MSwgNTQsIDU3LCA2MF1dKTtcbiAgfSk7XG5cbiAgaXQoJ2Jhc2VsaW5lIHZhbGlkJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEJhc2VsaW5lIGZvciB0aGUgKmludmFsaWQqIHRlc3RzIGJlbG93LlxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKFxuICAgICAgICBUZW5zb3JWYWx1ZTEweDQoKSwgWzgsIDMsIDAsIDldLCBbMCwgMSwgMiwgMl0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCByZXN1bHQuZGF0YSgpLFxuICAgICAgICBbWzMzLCAzNCwgMzUsIDM2XSwgWzEzLCAxNCwgMTUsIDE2XSwgWzM4LCA0MCwgNDIsIDQ0XV0pO1xuICB9KTtcblxuICBpdCgnZG9lcyBub3QgaGF2ZSBtZW1vcnkgbGVhay4nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYmVmb3JlRGF0YUlkcyA9IHRmLmVuZ2luZSgpLmJhY2tlbmQubnVtRGF0YUlkcygpO1xuXG4gICAgY29uc3QgZGF0YSA9IFRlbnNvclZhbHVlM3g0KCk7XG4gICAgY29uc3QgaW5kaWNlcyA9IHRmLnRlbnNvcjFkKFswLCAxXSwgJ2ludDMyJyk7XG4gICAgY29uc3Qgc2VnbWVudElkcyA9IHRmLnRlbnNvcjFkKFswLCAwXSwgJ2ludDMyJyk7XG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oZGF0YSwgaW5kaWNlcywgc2VnbWVudElkcyk7XG5cbiAgICBhd2FpdCByZXN1bHQuZGF0YSgpO1xuXG4gICAgY29uc3QgYWZ0ZXJSZXNEYXRhSWRzID0gdGYuZW5naW5lKCkuYmFja2VuZC5udW1EYXRhSWRzKCk7XG4gICAgZXhwZWN0KGFmdGVyUmVzRGF0YUlkcykudG9FcXVhbChiZWZvcmVEYXRhSWRzICsgNCk7XG5cbiAgICBkYXRhLmRpc3Bvc2UoKTtcbiAgICBpbmRpY2VzLmRpc3Bvc2UoKTtcbiAgICBzZWdtZW50SWRzLmRpc3Bvc2UoKTtcbiAgICByZXN1bHQuZGlzcG9zZSgpO1xuXG4gICAgY29uc3QgYWZ0ZXJEaXNwb3NlRGF0YUlkcyA9IHRmLmVuZ2luZSgpLmJhY2tlbmQubnVtRGF0YUlkcygpO1xuICAgIGV4cGVjdChhZnRlckRpc3Bvc2VEYXRhSWRzKS50b0VxdWFsKGJlZm9yZURhdGFJZHMpO1xuICB9KTtcblxuICBpdCgnaW5kaWNlcyBpbnZhbGlkIDEnLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKFRlbnNvclZhbHVlMTB4NCgpLCBbOCwgLTEsIDAsIDldLCBbXG4gICAgICAwLCAxLCAyLCAyXG4gICAgXSkpLnRvVGhyb3dFcnJvcigvaW5kaWNlc1xcWzFcXF0gPT0gLTEgb3V0IG9mIHJhbmdlIFxcWzAsIDEwXFwpLyk7XG4gIH0pO1xuXG4gIGl0KCdpbmRpY2VzIGludmFsaWQgMicsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCAxMF0sIFtcbiAgICAgIDAsIDEsIDIsIDJcbiAgICBdKSkudG9UaHJvd0Vycm9yKC9pbmRpY2VzXFxbM1xcXSA9PSAxMCBvdXQgb2YgcmFuZ2UgXFxbMCwgMTBcXCkvKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZ21lbnRzIGludmFsaWQgMicsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgW1xuICAgICAgMCwgMSwgMCwgMVxuICAgIF0pKS50b1Rocm93RXJyb3IoJ3NlZ21lbnQgaWRzIGFyZSBub3QgaW5jcmVhc2luZycpO1xuICB9KTtcblxuICBpdCgnc2VnbWVudHMgaW52YWxpZCAzJywgYXN5bmMgKCkgPT4ge1xuICAgIGV4cGVjdChcbiAgICAgICAgKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oXG4gICAgICAgICAgICBUZW5zb3JWYWx1ZTEweDQoKSwgWzgsIDMsIDAsIDldLCBbMCwgMSwgMiwgMF0pKVxuICAgICAgICAudG9UaHJvd0Vycm9yKFxuICAgICAgICAgICAgJ1NlZ21lbnQgaWQgMSBvdXQgb2YgcmFuZ2UgWzAsIDEpLCBwb3NzaWJseSBiZWNhdXNlIHNlZ21lbnRJZHMgJyArXG4gICAgICAgICAgICAnaW5wdXQgaXMgbm90IHNvcnRlZC4nKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZ21lbnRzIGludmFsaWQgNCcsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoXG4gICAgICAgICgpID0+IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKFxuICAgICAgICAgICAgVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgWy0xLCAwLCAxLCAxXSkpXG4gICAgICAgIC50b1Rocm93RXJyb3IoXG4gICAgICAgICAgICAnU2VnbWVudCBpZCAtMSBvdXQgb2YgcmFuZ2UgWzAsIDIpLCBwb3NzaWJseSBiZWNhdXNlIHNlZ21lbnRJZHMgJyArXG4gICAgICAgICAgICAnaW5wdXQgaXMgbm90IHNvcnRlZC4nKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZ21lbnRzIGludmFsaWQgNicsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgW1xuICAgICAgMCwgMCwgMCwgLTFcbiAgICBdKSkudG9UaHJvd0Vycm9yKCdzZWdtZW50IGlkcyBtdXN0IGJlID49IDAnKTtcbiAgfSk7XG5cbiAgaXQoJ3NlZ21lbnRzIGludmFsaWQgNycsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRTdW0oVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgW1xuICAgICAgMCwgMCwgMCwgLTJcbiAgICBdKSkudG9UaHJvd0Vycm9yKCdzZWdtZW50IGlkcyBtdXN0IGJlID49IDAnKTtcbiAgfSk7XG5cbiAgaXQoJ2luZGljZXMgaW52YWxpZCByYW5rJywgYXN5bmMgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudFN1bShUZW5zb3JWYWx1ZTEweDQoKSwgW1s4LCAzLCAwLCA5XV0sIFtcbiAgICAgIDAsIDAsIDAsIC0yXG4gICAgXSkpLnRvVGhyb3dFcnJvcigvc2hvdWxkIGJlIFRlbnNvcjFELyk7XG4gIH0pO1xuXG4gIGl0KCdzZWdtZW50cyBpbnZhbGlkIHJhbmsnLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50U3VtKFRlbnNvclZhbHVlMTB4NCgpLCBbOCwgMywgMCwgOV0sIFtcbiAgICAgIFswLCAwLCAwLCAtMl1cbiAgICBdKSkudG9UaHJvd0Vycm9yKC9zaG91bGQgYmUgVGVuc29yMUQvKTtcbiAgfSk7XG59KTtcbiJdfQ== |
\ | No newline at end of file |