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
/**
 * @license
 * Copyright 2021 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';
function TensorValue3x4Float() {
    return tf.tensor2d([[1, 2, 3, 4], [-1, -2, -3, -4], [6, 7, 8, 9]]);
}
function TensorValue3x4Integer() {
    return tf.tensor2d([[1, 2, 3, 4], [-1, -2, -3, -4], [6, 7, 8, 9]], [3, 4], 'int32');
}
function TensorValue10() {
    return tf.tensor1d(Array.from(Array(10), (_, i) => i + 1));
}
function TensorValue10x4() {
    return tf.tensor2d(Array.from(Array(40), (_, i) => i + 1), [10, 4]);
}
function TensorValue10x2x4() {
    return tf.tensor3d(Array.from(Array(80), (_, i) => i + 1), [10, 2, 4]);
}
describeWithFlags('sparseSegmentMean', ALL_ENVS, () => {
    it('two rows one segment', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue3x4Float(), [0, 1], [0, 0]);
        expectArraysClose(await result.data(), [[0, 0, 0, 0]]);
    });
    it('two rows two segments', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue3x4Float(), [0, 1], [0, 1]);
        expectArraysClose(await result.data(), [[1, 2, 3, 4], [-1, -2, -3, -4]]);
    });
    it('all rows two segments', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue3x4Float(), [0, 1, 2], [0, 1, 1]);
        expectArraysClose(await result.data(), [[1.0, 2.0, 3.0, 4.0], [2.5, 2.5, 2.5, 2.5]]);
    });
    it('integer data', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue3x4Integer(), [0, 1, 2], [0, 1, 1]);
        expectArraysClose(await result.data(), [[1, 2, 3, 4], [2, 2, 2, 2]]);
    });
    it('0 dimensional input invalid', async () => {
        expect(() => tf.sparse.sparseSegmentMean(tf.scalar(1), [], []))
            .toThrowError(/should be at least 1 dimensional/);
    });
    it('1 dimensional input', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue10(), [8, 3, 0, 9], [0, 1, 2, 2]);
        expectArraysClose(await result.data(), [9, 4, 5.5]);
    });
    it('3 dimensional input', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue10x2x4(), [8, 3, 0, 9], [0, 1, 2, 2]);
        expectArraysClose(await result.data(), [
            [[65, 66, 67, 68], [69, 70, 71, 72]],
            [[25, 26, 27, 28], [29, 30, 31, 32]], [[37, 38, 39, 40], [41, 42, 43, 44]]
        ]);
    });
    it('segment ids hole', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [0, 3, 3, 3]);
        expectArraysClose(await result.data(), [[33, 34, 35, 36], [0, 0, 0, 0], [0, 0, 0, 0], [17, 18, 19, 20]]);
    });
    it('segment ids > zero', async () => {
        const result = tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [2, 3, 3, 3]);
        expectArraysClose(await result.data(), [[0, 0, 0, 0], [0, 0, 0, 0], [33, 34, 35, 36], [17, 18, 19, 20]]);
    });
    it('baseline valid', async () => {
        // Baseline for the *invalid* tests below.
        const result = tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [0, 1, 2, 2]);
        expectArraysClose(await result.data(), [[33, 34, 35, 36], [13, 14, 15, 16], [19, 20, 21, 22]]);
    });
    it('does not have memory leak.', async () => {
        const beforeDataIds = tf.engine().backend.numDataIds();
        const data = TensorValue3x4Float();
        const indices = tf.tensor1d([0, 1], 'int32');
        const segmentIds = tf.tensor1d([0, 0], 'int32');
        const result = tf.sparse.sparseSegmentMean(data, indices, segmentIds);
        await result.data();
        const afterResDataIds = tf.engine().backend.numDataIds();
        expect(afterResDataIds).toEqual(beforeDataIds + 4);
        data.dispose();
        indices.dispose();
        segmentIds.dispose();
        result.dispose();
        const afterDisposeDataIds = tf.engine().backend.numDataIds();
        expect(afterDisposeDataIds).toEqual(beforeDataIds);
    });
    it('throw error if indices < 0', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, -1, 0, 9], [
            0, 1, 2, 2
        ])).toThrowError(/indices\[1\] == -1 out of range \[0, 10\)/);
    });
    it('throw error if indices >= max rows', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 10], [
            0, 1, 2, 2
        ])).toThrowError(/indices\[3\] == 10 out of range \[0, 10\)/);
    });
    it('throw error if segment ids are not increasing', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [
            0, 1, 0, 1
        ])).toThrowError('segment ids are not increasing');
    });
    it('throw error if segment id is out of range', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [0, 1, 2, 0]))
            .toThrowError('Segment id 1 out of range [0, 1), possibly because segmentIds ' +
            'input is not sorted.');
    });
    it('throw error if segment id is out of range and negative', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [-1, 0, 1, 1]))
            .toThrowError('Segment id -1 out of range [0, 2), possibly because segmentIds ' +
            'input is not sorted.');
    });
    it('throw error if segment id is negative', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [
            0, 0, 0, -1
        ])).toThrowError('segment ids must be >= 0');
    });
    it('throw error if segment id is negative and there is a hole', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [
            0, 0, 0, -2
        ])).toThrowError('segment ids must be >= 0');
    });
    it('throw error if indices has invalid rank', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [[8, 3, 0, 9]], [0, 0, 0, -2]))
            .toThrowError(/should be Tensor1D/);
    });
    it('throw error if segments has invalid rank', async () => {
        expect(() => tf.sparse.sparseSegmentMean(TensorValue10x4(), [8, 3, 0, 9], [
            [0, 0, 0, -2]
        ])).toThrowError(/should be Tensor1D/);
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhcnNlX3NlZ21lbnRfbWVhbl90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvc3BhcnNlL3NwYXJzZV9zZWdtZW50X21lYW5fdGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEVBQUMsUUFBUSxFQUFFLGlCQUFpQixFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDL0QsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFbEQsU0FBUyxtQkFBbUI7SUFDMUIsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDckUsQ0FBQztBQUVELFNBQVMscUJBQXFCO0lBQzVCLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FDZCxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUN2RSxDQUFDO0FBRUQsU0FBUyxhQUFhO0lBQ3BCLE9BQU8sRUFBRSxDQUFD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QUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3JELGlCQUFpQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3JDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3BDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7U0FDM0UsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsa0JBQWtCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDaEMsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FDdEMsZUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkQsaUJBQWlCLENBQ2IsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQ25CLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMs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QyxvQkFBb0IsQ0FBQyxDQUFDO0lBQ3pDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCAqIGFzIHRmIGZyb20gJy4uLy4uL2luZGV4JztcbmltcG9ydCB7QUxMX0VOVlMsIGRlc2NyaWJlV2l0aEZsYWdzfSBmcm9tICcuLi8uLi9qYXNtaW5lX3V0aWwnO1xuaW1wb3J0IHtleHBlY3RBcnJheXNDbG9zZX0gZnJvbSAnLi4vLi4vdGVzdF91dGlsJztcblxuZnVuY3Rpb24gVGVuc29yVmFsdWUzeDRGbG9hdCgpIHtcbiAgcmV0dXJuIHRmLnRlbnNvcjJkKFtbMSwgMiwgMywgNF0sIFstMSwgLTIsIC0zLCAtNF0sIFs2LCA3LCA4LCA5XV0pO1xufVxuXG5mdW5jdGlvbiBUZW5zb3JWYWx1ZTN4NEludGVnZXIoKSB7XG4gIHJldHVybiB0Zi50ZW5zb3IyZChcbiAgICAgIFtbMSwgMiwgMywgNF0sIFstMSwgLTIsIC0zLCAtNF0sIFs2LCA3LCA4LCA5XV0sIFszLCA0XSwgJ2ludDMyJyk7XG59XG5cbmZ1bmN0aW9uIFRlbnNvclZhbHVlMTAoKSB7XG4gIHJldHVybiB0Zi50ZW5zb3IxZChBcnJheS5mcm9tKEFycmF5KDEwKSwgKF8sIGkpID0+IGkgKyAxKSk7XG59XG5cbmZ1bmN0aW9uIFRlbnNvclZhbHVlMTB4NCgpIHtcbiAgcmV0dXJuIHRmLnRlbnNvcjJkKEFycmF5LmZyb20oQXJyYXkoNDApLCAoXywgaSkgPT4gaSArIDEpLCBbMTAsIDRdKTtcbn1cblxuZnVuY3Rpb24gVGVuc29yVmFsdWUxMHgyeDQoKSB7XG4gIHJldHVybiB0Zi50ZW5zb3IzZChBcnJheS5mcm9tKEFycmF5KDgwKSwgKF8sIGkpID0+IGkgKyAxKSwgWzEwLCAyLCA0XSk7XG59XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdzcGFyc2VTZWdtZW50TWVhbicsIEFMTF9FTlZTLCAoKSA9PiB7XG4gIGl0KCd0d28gcm93cyBvbmUgc2VnbWVudCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPVxuICAgICAgICB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudE1lYW4oVGVuc29yVmFsdWUzeDRGbG9hdCgpLCBbMCwgMV0sIFswLCAwXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgW1swLCAwLCAwLCAwXV0pO1xuICB9KTtcblxuICBpdCgndHdvIHJvd3MgdHdvIHNlZ21lbnRzJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9XG4gICAgICAgIHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihUZW5zb3JWYWx1ZTN4NEZsb2F0KCksIFswLCAxXSwgWzAsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBbWzEsIDIsIDMsIDRdLCBbLTEsIC0yLCAtMywgLTRdXSk7XG4gIH0pO1xuXG4gIGl0KCdhbGwgcm93cyB0d28gc2VnbWVudHMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRNZWFuKFxuICAgICAgICBUZW5zb3JWYWx1ZTN4NEZsb2F0KCksIFswLCAxLCAyXSwgWzAsIDEsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgcmVzdWx0LmRhdGEoKSwgW1sxLjAsIDIuMCwgMy4wLCA0LjBdLCBbMi41LCAyLjUsIDIuNSwgMi41XV0pO1xuICB9KTtcblxuICBpdCgnaW50ZWdlciBkYXRhJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihcbiAgICAgICAgVGVuc29yVmFsdWUzeDRJbnRlZ2VyKCksIFswLCAxLCAyXSwgWzAsIDEsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBbWzEsIDIsIDMsIDRdLCBbMiwgMiwgMiwgMl1dKTtcbiAgfSk7XG5cbiAgaXQoJzAgZGltZW5zaW9uYWwgaW5wdXQgaW52YWxpZCcsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRNZWFuKHRmLnNjYWxhcigxKSwgW10sIFtdKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcigvc2hvdWxkIGJlIGF0IGxlYXN0IDEgZGltZW5zaW9uYWwvKTtcbiAgfSk7XG5cbiAgaXQoJzEgZGltZW5zaW9uYWwgaW5wdXQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRNZWFuKFxuICAgICAgICBUZW5zb3JWYWx1ZTEwKCksIFs4LCAzLCAwLCA5XSwgWzAsIDEsIDIsIDJdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBbOSwgNCwgNS41XSk7XG4gIH0pO1xuXG4gIGl0KCczIGRpbWVuc2lvbmFsIGlucHV0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihcbiAgICAgICAgVGVuc29yVmFsdWUxMHgyeDQoKSwgWzgsIDMsIDAsIDldLCBbMCwgMSwgMiwgMl0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5kYXRhKCksIFtcbiAgICAgIFtbNjUsIDY2LCA2NywgNjhdLCBbNjksIDcwLCA3MSwgNzJdXSxcbiAgICAgIFtbMjUsIDI2LCAyNywgMjhdLCBbMjksIDMwLCAzMSwgMzJdXSwgW1szNywgMzgsIDM5LCA0MF0sIFs0MSwgNDIsIDQzLCA0NF1dXG4gICAgXSk7XG4gIH0pO1xuXG4gIGl0KCdzZWdtZW50IGlkcyBob2xlJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihcbiAgICAgICAgVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgWzAsIDMsIDMsIDNdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgcmVzdWx0LmRhdGEoKSxcbiAgICAgICAgW1szMywgMzQsIDM1LCAzNl0sIFswLCAwLCAwLCAwXSwgWzAsIDAsIDAsIDBdLCBbMTcsIDE4LCAxOSwgMjBdXSk7XG4gIH0pO1xuXG4gIGl0KCdzZWdtZW50IGlkcyA+IHplcm8nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRNZWFuKFxuICAgICAgICBUZW5zb3JWYWx1ZTEweDQoKSwgWzgsIDMsIDAsIDldLCBbMiwgMywgMywgM10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCByZXN1bHQuZGF0YSgpLFxuICAgICAgICBbWzAsIDAsIDAsIDBdLCBbMCwgMCwgMCwgMF0sIFszMywgMzQsIDM1LCAzNl0sIFsxNywgMTgsIDE5LCAyMF1dKTtcbiAgfSk7XG5cbiAgaXQoJ2Jhc2VsaW5lIHZhbGlkJywgYXN5bmMgKCkgPT4ge1xuICAgIC8vIEJhc2VsaW5lIGZvciB0aGUgKmludmFsaWQqIHRlc3RzIGJlbG93LlxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihcbiAgICAgICAgVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgWzAsIDEsIDIsIDJdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgcmVzdWx0LmRhdGEoKSxcbiAgICAgICAgW1szMywgMzQsIDM1LCAzNl0sIFsxMywgMTQsIDE1LCAxNl0sIFsxOSwgMjAsIDIxLCAyMl1dKTtcbiAgfSk7XG5cbiAgaXQoJ2RvZXMgbm90IGhhdmUgbWVtb3J5IGxlYWsuJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGJlZm9yZURhdGFJZHMgPSB0Zi5lbmdpbmUoKS5iYWNrZW5kLm51bURhdGFJZHMoKTtcblxuICAgIGNvbnN0IGRhdGEgPSBUZW5zb3JWYWx1ZTN4NEZsb2F0KCk7XG4gICAgY29uc3QgaW5kaWNlcyA9IHRmLnRlbnNvcjFkKFswLCAxXSwgJ2ludDMyJyk7XG4gICAgY29uc3Qgc2VnbWVudElkcyA9IHRmLnRlbnNvcjFkKFswLCAwXSwgJ2ludDMyJyk7XG4gICAgY29uc3QgcmVzdWx0ID0gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRNZWFuKGRhdGEsIGluZGljZXMsIHNlZ21lbnRJZHMpO1xuXG4gICAgYXdhaXQgcmVzdWx0LmRhdGEoKTtcblxuICAgIGNvbnN0IGFmdGVyUmVzRGF0YUlkcyA9IHRmLmVuZ2luZSgpLmJhY2tlbmQubnVtRGF0YUlkcygpO1xuICAgIGV4cGVjdChhZnRlclJlc0RhdGFJZHMpLnRvRXF1YWwoYmVmb3JlRGF0YUlkcyArIDQpO1xuXG4gICAgZGF0YS5kaXNwb3NlKCk7XG4gICAgaW5kaWNlcy5kaXNwb3NlKCk7XG4gICAgc2VnbWVudElkcy5kaXNwb3NlKCk7XG4gICAgcmVzdWx0LmRpc3Bvc2UoKTtcblxuICAgIGNvbnN0IGFmdGVyRGlzcG9zZURhdGFJZHMgPSB0Zi5lbmdpbmUoKS5iYWNrZW5kLm51bURhdGFJZHMoKTtcbiAgICBleHBlY3QoYWZ0ZXJEaXNwb3NlRGF0YUlkcykudG9FcXVhbChiZWZvcmVEYXRhSWRzKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93IGVycm9yIGlmIGluZGljZXMgPCAwJywgYXN5bmMgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudE1lYW4oVGVuc29yVmFsdWUxMHg0KCksIFs4LCAtMSwgMCwgOV0sIFtcbiAgICAgIDAsIDEsIDIsIDJcbiAgICBdKSkudG9UaHJvd0Vycm9yKC9pbmRpY2VzXFxbMVxcXSA9PSAtMSBvdXQgb2YgcmFuZ2UgXFxbMCwgMTBcXCkvKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93IGVycm9yIGlmIGluZGljZXMgPj0gbWF4IHJvd3MnLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihUZW5zb3JWYWx1ZTEweDQoKSwgWzgsIDMsIDAsIDEwXSwgW1xuICAgICAgMCwgMSwgMiwgMlxuICAgIF0pKS50b1Rocm93RXJyb3IoL2luZGljZXNcXFszXFxdID09IDEwIG91dCBvZiByYW5nZSBcXFswLCAxMFxcKS8pO1xuICB9KTtcblxuICBpdCgndGhyb3cgZXJyb3IgaWYgc2VnbWVudCBpZHMgYXJlIG5vdCBpbmNyZWFzaW5nJywgYXN5bmMgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudE1lYW4oVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgW1xuICAgICAgMCwgMSwgMCwgMVxuICAgIF0pKS50b1Rocm93RXJyb3IoJ3NlZ21lbnQgaWRzIGFyZSBub3QgaW5jcmVhc2luZycpO1xuICB9KTtcblxuICBpdCgndGhyb3cgZXJyb3IgaWYgc2VnbWVudCBpZCBpcyBvdXQgb2YgcmFuZ2UnLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudE1lYW4oXG4gICAgICAgICAgICBUZW5zb3JWYWx1ZTEweDQoKSwgWzgsIDMsIDAsIDldLCBbMCwgMSwgMiwgMF0pKVxuICAgICAgICAudG9UaHJvd0Vycm9yKFxuICAgICAgICAgICAgJ1NlZ21lbnQgaWQgMSBvdXQgb2YgcmFuZ2UgWzAsIDEpLCBwb3NzaWJseSBiZWNhdXNlIHNlZ21lbnRJZHMgJyArXG4gICAgICAgICAgICAnaW5wdXQgaXMgbm90IHNvcnRlZC4nKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93IGVycm9yIGlmIHNlZ21lbnQgaWQgaXMgb3V0IG9mIHJhbmdlIGFuZCBuZWdhdGl2ZScsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoXG4gICAgICAgICgpID0+IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihcbiAgICAgICAgICAgIFRlbnNvclZhbHVlMTB4NCgpLCBbOCwgMywgMCwgOV0sIFstMSwgMCwgMSwgMV0pKVxuICAgICAgICAudG9UaHJvd0Vycm9yKFxuICAgICAgICAgICAgJ1NlZ21lbnQgaWQgLTEgb3V0IG9mIHJhbmdlIFswLCAyKSwgcG9zc2libHkgYmVjYXVzZSBzZWdtZW50SWRzICcgK1xuICAgICAgICAgICAgJ2lucHV0IGlzIG5vdCBzb3J0ZWQuJyk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvdyBlcnJvciBpZiBzZWdtZW50IGlkIGlzIG5lZ2F0aXZlJywgYXN5bmMgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudE1lYW4oVGVuc29yVmFsdWUxMHg0KCksIFs4LCAzLCAwLCA5XSwgW1xuICAgICAgMCwgMCwgMCwgLTFcbiAgICBdKSkudG9UaHJvd0Vycm9yKCdzZWdtZW50IGlkcyBtdXN0IGJlID49IDAnKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93IGVycm9yIGlmIHNlZ21lbnQgaWQgaXMgbmVnYXRpdmUgYW5kIHRoZXJlIGlzIGEgaG9sZScsIGFzeW5jICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4gdGYuc3BhcnNlLnNwYXJzZVNlZ21lbnRNZWFuKFRlbnNvclZhbHVlMTB4NCgpLCBbOCwgMywgMCwgOV0sIFtcbiAgICAgIDAsIDAsIDAsIC0yXG4gICAgXSkpLnRvVGhyb3dFcnJvcignc2VnbWVudCBpZHMgbXVzdCBiZSA+PSAwJyk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvdyBlcnJvciBpZiBpbmRpY2VzIGhhcyBpbnZhbGlkIHJhbmsnLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5zcGFyc2Uuc3BhcnNlU2VnbWVudE1lYW4oXG4gICAgICAgICAgICBUZW5zb3JWYWx1ZTEweDQoKSwgW1s4LCAzLCAwLCA5XV0sIFswLCAwLCAwLCAtMl0pKVxuICAgICAgICAudG9UaHJvd0Vycm9yKC9zaG91bGQgYmUgVGVuc29yMUQvKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93IGVycm9yIGlmIHNlZ21lbnRzIGhhcyBpbnZhbGlkIHJhbmsnLCBhc3luYyAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IHRmLnNwYXJzZS5zcGFyc2VTZWdtZW50TWVhbihUZW5zb3JWYWx1ZTEweDQoKSwgWzgsIDMsIDAsIDldLCBbXG4gICAgICBbMCwgMCwgMCwgLTJdXG4gICAgXSkpLnRvVGhyb3dFcnJvcigvc2hvdWxkIGJlIFRlbnNvcjFELyk7XG4gIH0pO1xufSk7XG4iXX0=