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
/**
 * @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('clipByValue', ALL_ENVS, () => {
    it('basic', async () => {
        const a = tf.tensor1d([3, -1, 0, 100, -7, 2]);
        const min = -1;
        const max = 50;
        const result = tf.clipByValue(a, min, max);
        expectArraysClose(await result.data(), [3, -1, 0, 50, -1, 2]);
    });
    it('basic vec4', async () => {
        const a = tf.tensor1d([3, -1, 0, 100, -7, 2, 5, NaN]);
        const min = -1;
        const max = 50;
        const result = tf.clipByValue(a, min, max);
        expectArraysClose(await result.data(), [3, -1, 0, 50, -1, 2, 5, NaN]);
    });
    it('propagates NaNs', async () => {
        const a = tf.tensor1d([3, -1, 0, 100, -7, 2, NaN]);
        const min = -1;
        const max = 50;
        const result = tf.clipByValue(a, min, max);
        expectArraysClose(await result.data(), [3, -1, 0, 50, -1, 2, NaN]);
    });
    it('min greater than max', () => {
        const a = tf.tensor1d([3, -1, 0, 100, -7, 2]);
        const min = 1;
        const max = -1;
        const f = () => {
            tf.clipByValue(a, min, max);
        };
        expect(f).toThrowError();
    });
    it('gradient: 1D tensor', async () => {
        const min = -1;
        const max = 2;
        const x = tf.tensor1d([3, -2, 1]); // Only 1 is not clipped.
        const dy = tf.tensor1d([5, 50, 500]);
        const gradients = tf.grad(x => x.clipByValue(min, max))(x, dy);
        expect(gradients.shape).toEqual(x.shape);
        expect(gradients.dtype).toEqual('float32');
        expectArraysClose(await gradients.data(), [0, 0, 500]);
    });
    it('gradient: 1D tensor with max or min value', async () => {
        const min = -1;
        const max = 2;
        const x = tf.tensor1d([-1, 1, 2, 3]);
        const dy = tf.tensor1d([1, 10, 100, 1000]);
        const gradients = tf.grad(x => x.clipByValue(min, max))(x, dy);
        expect(gradients.shape).toEqual(x.shape);
        expect(gradients.dtype).toEqual('float32');
        expectArraysClose(await gradients.data(), [1, 10, 100, 0]);
    });
    it('gradient: scalar', async () => {
        const min = -1;
        const max = 2;
        const x = tf.scalar(-10); // Clipped.
        const dy = tf.scalar(5);
        const gradients = tf.grad(x => x.clipByValue(min, max))(x, dy);
        expect(gradients.shape).toEqual(x.shape);
        expect(gradients.dtype).toEqual('float32');
        expectArraysClose(await gradients.data(), [0]);
    });
    it('gradient with clones', async () => {
        const min = -1;
        const max = 2;
        const x = tf.scalar(-10); // Clipped.
        const dy = tf.scalar(5);
        const gradients = tf.grad(x => x.clone().clipByValue(min, max).clone())(x, dy);
        expect(gradients.shape).toEqual(x.shape);
        expect(gradients.dtype).toEqual('float32');
        expectArraysClose(await gradients.data(), [0]);
    });
    it('gradient with primitive as input', async () => {
        const min = -1;
        const max = 2;
        const x = -10;
        const dy = tf.scalar(5);
        const gradients = tf.grad(x => x.clipByValue(min, max))(x, dy);
        expect(gradients.shape).toEqual([]);
        expect(gradients.dtype).toEqual('float32');
        expectArraysClose(await gradients.data(), [0]);
    });
    it('throws when passed a non-tensor', () => {
        expect(() => tf.clipByValue({}, 0, 1))
            .toThrowError(/Argument 'x' passed to 'clipByValue' must be a Tensor/);
    });
    it('accepts a tensor-like object', async () => {
        const min = -1;
        const max = 50;
        const result = tf.clipByValue([3, -1, 0, 100, -7, 2], min, max);
        expectArraysClose(await result.data(), [3, -1, 0, 50, -1, 2]);
    });
    it('clip(x, eps, 1-eps) never returns 0 or 1', async () => {
        const min = tf.backend().epsilon();
        const max = 0.5;
        const res = await tf.clipByValue([0, 1], min, max).data();
        expect(res[0]).toBeGreaterThan(0);
        expect(res[1]).toBeCloseTo(max);
    });
    it('clip min = max', async () => {
        const min = 2;
        const max = 2;
        const tensor = tf.tensor([1, 2, 3, 4, 5], [5], 'float32');
        const result = tf.clipByValue(tensor, min, max);
        expectArraysClose(await result.data(), [2, 2, 2, 2, 2]);
    });
    it('throws for string tensor', () => {
        expect(() => tf.clipByValue('q', 0, 1))
            .toThrowError(/Argument 'x' passed to 'clipByValue' must be numeric/);
    });
    it('clip int32 tensor', async () => {
        const min = -1;
        const max = 50;
        const tensor = tf.tensor([2, 3, 4], [3], 'int32');
        const result = tf.clipByValue(tensor, min, max);
        expectArraysClose(await result.data(), [2, 3, 4]);
        expect(result.dtype).toEqual('int32');
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpcF9ieV92YWx1ZV90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvY2xpcF9ieV92YWx1ZV90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQy9CLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFFL0MsaUJBQWlCLENBQUMsYUFBYSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7SUFDOUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxLQUFLLElBQUksRUFBRTtRQUNyQixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNmLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUVmLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUUzQyxpQkFBaUIsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsWUFBWSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzFCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDdEQsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDZixNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFFZixNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFM0MsaUJBQWlCLENBQUMsTUFBTSxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDL0IsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ25ELE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2YsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBRWYsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBRTNDLGlCQUFpQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDckUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsc0JBQXNCLEVBQUUsR0FBRyxFQUFFO1FBQzlCLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlDLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNkLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRWYsTUFBTSxDQUFDLEdBQUcsR0FBRyxFQUFFO1lBQ2IsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQzlCLENBQUMsQ0FBQztRQUNGLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMzQixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNuQyxNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNmLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNkLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFFLHlCQUF5QjtRQUM3RCxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUUvRCxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDM0MsaUJBQWlCLENBQUMsTUFBTSxTQUFTLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDekQsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsMkNBQTJDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDekQsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDZixNQUFNLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDZCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUUvRCxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDekMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDM0MsaUJBQWlCLENBQUMsTUFBTSxTQUFTLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzdELENBQUMsQ0FBQyxDQUFD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QUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbEQsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ2hELGlCQUFpQixDQUFDLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xELE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3hDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCAqIGFzIHRmIGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7QUxMX0VOVlMsIGRlc2NyaWJlV2l0aEZsYWdzfSBmcm9tICcuLi9qYXNtaW5lX3V0aWwnO1xuaW1wb3J0IHtleHBlY3RBcnJheXNDbG9zZX0gZnJvbSAnLi4vdGVzdF91dGlsJztcblxuZGVzY3JpYmVXaXRoRmxhZ3MoJ2NsaXBCeVZhbHVlJywgQUxMX0VOVlMsICgpID0+IHtcbiAgaXQoJ2Jhc2ljJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSB0Zi50ZW5zb3IxZChbMywgLTEsIDAsIDEwMCwgLTcsIDJdKTtcbiAgICBjb25zdCBtaW4gPSAtMTtcbiAgICBjb25zdCBtYXggPSA1MDtcblxuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmNsaXBCeVZhbHVlKGEsIG1pbiwgbWF4KTtcblxuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5kYXRhKCksIFszLCAtMSwgMCwgNTAsIC0xLCAyXSk7XG4gIH0pO1xuXG4gIGl0KCdiYXNpYyB2ZWM0JywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSB0Zi50ZW5zb3IxZChbMywgLTEsIDAsIDEwMCwgLTcsIDIsIDUsIE5hTl0pO1xuICAgIGNvbnN0IG1pbiA9IC0xO1xuICAgIGNvbnN0IG1heCA9IDUwO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuY2xpcEJ5VmFsdWUoYSwgbWluLCBtYXgpO1xuXG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgWzMsIC0xLCAwLCA1MCwgLTEsIDIsIDUsIE5hTl0pO1xuICB9KTtcblxuICBpdCgncHJvcGFnYXRlcyBOYU5zJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGEgPSB0Zi50ZW5zb3IxZChbMywgLTEsIDAsIDEwMCwgLTcsIDIsIE5hTl0pO1xuICAgIGNvbnN0IG1pbiA9IC0xO1xuICAgIGNvbnN0IG1heCA9IDUwO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gdGYuY2xpcEJ5VmFsdWUoYSwgbWluLCBtYXgpO1xuXG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgWzMsIC0xLCAwLCA1MCwgLTEsIDIsIE5hTl0pO1xuICB9KTtcblxuICBpdCgnbWluIGdyZWF0ZXIgdGhhbiBtYXgnLCAoKSA9PiB7XG4gICAgY29uc3QgYSA9IHRmLnRlbnNvcjFkKFszLCAtMSwgMCwgMTAwLCAtNywgMl0pO1xuICAgIGNvbnN0IG1pbiA9IDE7XG4gICAgY29uc3QgbWF4ID0gLTE7XG5cbiAgICBjb25zdCBmID0gKCkgPT4ge1xuICAgICAgdGYuY2xpcEJ5VmFsdWUoYSwgbWluLCBtYXgpO1xuICAgIH07XG4gICAgZXhwZWN0KGYpLnRvVGhyb3dFcnJvcigpO1xuICB9KTtcblxuICBpdCgnZ3JhZGllbnQ6IDFEIHRlbnNvcicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAtMTtcbiAgICBjb25zdCBtYXggPSAyO1xuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3IxZChbMywgLTIsIDFdKTsgIC8vIE9ubHkgMSBpcyBub3QgY2xpcHBlZC5cbiAgICBjb25zdCBkeSA9IHRmLnRlbnNvcjFkKFs1LCA1MCwgNTAwXSk7XG4gICAgY29uc3QgZ3JhZGllbnRzID0gdGYuZ3JhZCh4ID0+IHguY2xpcEJ5VmFsdWUobWluLCBtYXgpKSh4LCBkeSk7XG5cbiAgICBleHBlY3QoZ3JhZGllbnRzLnNoYXBlKS50b0VxdWFsKHguc2hhcGUpO1xuICAgIGV4cGVjdChncmFkaWVudHMuZHR5cGUpLnRvRXF1YWwoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBncmFkaWVudHMuZGF0YSgpLCBbMCwgMCwgNTAwXSk7XG4gIH0pO1xuXG4gIGl0KCdncmFkaWVudDogMUQgdGVuc29yIHdpdGggbWF4IG9yIG1pbiB2YWx1ZScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAtMTtcbiAgICBjb25zdCBtYXggPSAyO1xuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3IxZChbLTEsIDEsIDIsIDNdKTtcbiAgICBjb25zdCBkeSA9IHRmLnRlbnNvcjFkKFsxLCAxMCwgMTAwLCAxMDAwXSk7XG4gICAgY29uc3QgZ3JhZGllbnRzID0gdGYuZ3JhZCh4ID0+IHguY2xpcEJ5VmFsdWUobWluLCBtYXgpKSh4LCBkeSk7XG5cbiAgICBleHBlY3QoZ3JhZGllbnRzLnNoYXBlKS50b0VxdWFsKHguc2hhcGUpO1xuICAgIGV4cGVjdChncmFkaWVudHMuZHR5cGUpLnRvRXF1YWwoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBncmFkaWVudHMuZGF0YSgpLCBbMSwgMTAsIDEwMCwgMF0pO1xuICB9KTtcblxuICBpdCgnZ3JhZGllbnQ6IHNjYWxhcicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAtMTtcbiAgICBjb25zdCBtYXggPSAyO1xuICAgIGNvbnN0IHggPSB0Zi5zY2FsYXIoLTEwKTsgIC8vIENsaXBwZWQuXG4gICAgY29uc3QgZHkgPSB0Zi5zY2FsYXIoNSk7XG4gICAgY29uc3QgZ3JhZGllbnRzID0gdGYuZ3JhZCh4ID0+IHguY2xpcEJ5VmFsdWUobWluLCBtYXgpKSh4LCBkeSk7XG5cbiAgICBleHBlY3QoZ3JhZGllbnRzLnNoYXBlKS50b0VxdWFsKHguc2hhcGUpO1xuICAgIGV4cGVjdChncmFkaWVudHMuZHR5cGUpLnRvRXF1YWwoJ2Zsb2F0MzInKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCBncmFkaWVudHMuZGF0YSgpLCBbMF0pO1xuICB9KTtcblxuICBpdCgnZ3JhZGllbnQgd2l0aCBjbG9uZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbWluID0gLTE7XG4gICAgY29uc3QgbWF4ID0gMjtcbiAgICBjb25zdCB4ID0gdGYuc2NhbGFyKC0xMCk7ICAvLyBDbGlwcGVkLlxuICAgIGNvbnN0IGR5ID0gdGYuc2NhbGFyKDUpO1xuICAgIGNvbnN0IGdyYWRpZW50cyA9XG4gICAgICAgIHRmLmdyYWQoeCA9PiB4LmNsb25lKCkuY2xpcEJ5VmFsdWUobWluLCBtYXgpLmNsb25lKCkpKHgsIGR5KTtcblxuICAgIGV4cGVjdChncmFkaWVudHMuc2hhcGUpLnRvRXF1YWwoeC5zaGFwZSk7XG4gICAgZXhwZWN0KGdyYWRpZW50cy5kdHlwZSkudG9FcXVhbCgnZmxvYXQzMicpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IGdyYWRpZW50cy5kYXRhKCksIFswXSk7XG4gIH0pO1xuXG4gIGl0KCdncmFkaWVudCB3aXRoIHByaW1pdGl2ZSBhcyBpbnB1dCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAtMTtcbiAgICBjb25zdCBtYXggPSAyO1xuICAgIGNvbnN0IHggPSAtMTA7XG4gICAgY29uc3QgZHkgPSB0Zi5zY2FsYXIoNSk7XG4gICAgY29uc3QgZ3JhZGllbnRzID0gdGYuZ3JhZCh4ID0+IHguY2xpcEJ5VmFsdWUobWluLCBtYXgpKSh4LCBkeSk7XG4gICAgZXhwZWN0KGdyYWRpZW50cy5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0KGdyYWRpZW50cy5kdHlwZSkudG9FcXVhbCgnZmxvYXQzMicpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IGdyYWRpZW50cy5kYXRhKCksIFswXSk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvd3Mgd2hlbiBwYXNzZWQgYSBub24tdGVuc29yJywgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5jbGlwQnlWYWx1ZSh7fSBhcyB0Zi5UZW5zb3IsIDAsIDEpKVxuICAgICAgICAudG9UaHJvd0Vycm9yKC9Bcmd1bWVudCAneCcgcGFzc2VkIHRvICdjbGlwQnlWYWx1ZScgbXVzdCBiZSBhIFRlbnNvci8pO1xuICB9KTtcblxuICBpdCgnYWNjZXB0cyBhIHRlbnNvci1saWtlIG9iamVjdCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAtMTtcbiAgICBjb25zdCBtYXggPSA1MDtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5jbGlwQnlWYWx1ZShbMywgLTEsIDAsIDEwMCwgLTcsIDJdLCBtaW4sIG1heCk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgcmVzdWx0LmRhdGEoKSwgWzMsIC0xLCAwLCA1MCwgLTEsIDJdKTtcbiAgfSk7XG5cbiAgaXQoJ2NsaXAoeCwgZXBzLCAxLWVwcykgbmV2ZXIgcmV0dXJucyAwIG9yIDEnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbWluID0gdGYuYmFja2VuZCgpLmVwc2lsb24oKTtcbiAgICBjb25zdCBtYXggPSAwLjU7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgdGYuY2xpcEJ5VmFsdWUoWzAsIDFdLCBtaW4sIG1heCkuZGF0YSgpO1xuICAgIGV4cGVjdChyZXNbMF0pLnRvQmVHcmVhdGVyVGhhbigwKTtcbiAgICBleHBlY3QocmVzWzFdKS50b0JlQ2xvc2VUbyhtYXgpO1xuICB9KTtcblxuICBpdCgnY2xpcCBtaW4gPSBtYXgnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgbWluID0gMjtcbiAgICBjb25zdCBtYXggPSAyO1xuICAgIGNvbnN0IHRlbnNvciA9IHRmLnRlbnNvcihbMSwgMiwgMywgNCwgNV0sIFs1XSwgJ2Zsb2F0MzInKTtcbiAgICBjb25zdCByZXN1bHQgPSB0Zi5jbGlwQnlWYWx1ZSh0ZW5zb3IsIG1pbiwgbWF4KTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCByZXN1bHQuZGF0YSgpLCBbMiwgMiwgMiwgMiwgMl0pO1xuICB9KTtcblxuICBpdCgndGhyb3dzIGZvciBzdHJpbmcgdGVuc29yJywgKCkgPT4ge1xuICAgIGV4cGVjdCgoKSA9PiB0Zi5jbGlwQnlWYWx1ZSgncScsIDAsIDEpKVxuICAgICAgICAudG9UaHJvd0Vycm9yKC9Bcmd1bWVudCAneCcgcGFzc2VkIHRvICdjbGlwQnlWYWx1ZScgbXVzdCBiZSBudW1lcmljLyk7XG4gIH0pO1xuXG4gIGl0KCdjbGlwIGludDMyIHRlbnNvcicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtaW4gPSAtMTtcbiAgICBjb25zdCBtYXggPSA1MDtcbiAgICBjb25zdCB0ZW5zb3IgPSB0Zi50ZW5zb3IoWzIsIDMsIDRdLCBbM10sICdpbnQzMicpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRmLmNsaXBCeVZhbHVlKHRlbnNvciwgbWluLCBtYXgpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHJlc3VsdC5kYXRhKCksIFsyLCAzLCA0XSk7XG4gICAgZXhwZWN0KHJlc3VsdC5kdHlwZSkudG9FcXVhbCgnaW50MzInKTtcbiAgfSk7XG59KTtcbiJdfQ==