UNPKG

26.2 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 TensorValue3x4() {
21 return tf.tensor2d([[1, 2, 3, 4], [-1, -2, -3, -4], [5, 6, 7, 8]]);
22}
23function TensorValue10() {
24 return tf.tensor1d(Array.from(Array(10), (_, i) => i + 1));
25}
26function TensorValue10x4() {
27 return tf.tensor2d(Array.from(Array(40), (_, i) => i + 1), [10, 4]);
28}
29function TensorValue10x2x4() {
30 return tf.tensor3d(Array.from(Array(80), (_, i) => i + 1), [10, 2, 4]);
31}
32describeWithFlags('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