/** * @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('absoluteDifference', ALL_ENVS, () => { it('1D', async () => { const predictions = tf.tensor1d([1, 2, 3]); const label = tf.tensor1d([0.3, -0.6, -0.1]); const y = tf.losses.absoluteDifference(label, predictions); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (Math.abs(1 - 0.3) + Math.abs(2 - (-0.6)) + Math.abs(3 - (-0.1))) / 3); }); it('1D - weighted - Reduction.SUM_BY_NONZERO_WEIGHTS', async () => { const predictions = tf.tensor1d([1, 2, 3]); const label = tf.tensor1d([0.3, -0.6, -0.1]); const weights = tf.tensor1d([0.1, 0.2, 0.3]); const y = tf.losses.absoluteDifference(label, predictions, weights); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (Math.abs(1 - 0.3) * 0.1 + Math.abs(2 - (-0.6)) * 0.2 + Math.abs(3 - (-0.1)) * 0.3) / 3); }); it('1D - weighted - Reduction.NONE', async () => { const predictions = tf.tensor1d([1, 2, 3]); const label = tf.tensor1d([0.3, -0.6, -0.1]); const weights = tf.tensor1d([0.1, 0.2, 0.3]); const y = tf.losses.absoluteDifference(label, predictions, weights, tf.Reduction.NONE); expect(y.shape).toEqual([3]); expectArraysClose(await y.data(), [ Math.abs(1 - 0.3) * 0.1, Math.abs(2 - (-0.6)) * 0.2, Math.abs(3 - (-0.1)) * 0.3 ]); }); it('1D - Reduction.MEAN', async () => { const predictions = tf.tensor1d([1, 2, 3]); const label = tf.tensor1d([0.3, -0.6, -0.1]); const y = tf.losses.absoluteDifference(label, predictions, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (Math.abs(1 - 0.3) + Math.abs(2 - (-0.6)) + Math.abs(3 - (-0.1))) / 3); }); it('1D - weighted - Reduction.MEAN', async () => { const predictions = tf.tensor1d([1, 2, 3]); const label = tf.tensor1d([0.3, -0.6, -0.1]); const weights = tf.tensor1d([0.1, 0.2, 0.3]); const y = tf.losses.absoluteDifference(label, predictions, weights, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), ((Math.abs(1 - 0.3) * 0.1) + (Math.abs(2 - (-0.6)) * 0.2) + (Math.abs(3 - (-0.1)) * 0.3)) / 0.6); }); it('2D', async () => { const predictions = tf.tensor2d([4, 8, 12, 8, 1, 3], [2, 3]); const label = tf.tensor2d([1, 9, 2, -5, -2, 6], [2, 3]); const y = tf.losses.absoluteDifference(label, predictions); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (Math.abs(4 - 1) + Math.abs(8 - 9) + Math.abs(12 - 2) + Math.abs(8 - (-5)) + Math.abs(1 - (-2)) + Math.abs(3 - 6)) / 6); }); it('2D - weighted - Reduction.SUM_BY_NONZERO_WEIGHTS', async () => { const predictions = tf.tensor2d([4, 8, 12, 8, 1, 3], [2, 3]); const label = tf.tensor2d([1, 9, 2, -5, -2, 6], [2, 3]); const weights = tf.tensor2d([3, 0, 5, 0, 4, 2], [2, 3]); const y = tf.losses.absoluteDifference(label, predictions, weights); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (Math.abs(4 - 1) * 3 + Math.abs(8 - 9) * 0 + Math.abs(12 - 2) * 5 + Math.abs(8 - (-5)) * 0 + Math.abs(1 - (-2)) * 4 + Math.abs(3 - 6) * 2) / 4); }); it('2D - weighted - Reduction.NONE', async () => { const predictions = tf.tensor2d([4, 8, 12, 8, 1, 3], [2, 3]); const label = tf.tensor2d([1, 9, 2, -5, -2, 6], [2, 3]); const weights = tf.tensor2d([3, 6, 5, 0, 4, 2], [2, 3]); const y = tf.losses.absoluteDifference(label, predictions, weights, tf.Reduction.NONE); expect(y.shape).toEqual([2, 3]); expectArraysClose(await y.data(), [ Math.abs(4 - 1) * 3, Math.abs(8 - 9) * 6, Math.abs(12 - 2) * 5, Math.abs(8 - (-5)) * 0, Math.abs(1 - (-2)) * 4, Math.abs(3 - 6) * 2 ]); }); it('2D - Reduction.MEAN', async () => { const predictions = tf.tensor2d([4, 8, 12, 8, 1, 3], [2, 3]); const label = tf.tensor2d([1, 9, 2, -5, -2, 6], [2, 3]); const y = tf.losses.absoluteDifference(label, predictions, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (Math.abs(4 - 1) + Math.abs(8 - 9) + Math.abs(12 - 2) + Math.abs(8 - (-5)) + Math.abs(1 - (-2)) + Math.abs(3 - 6)) / 6); }); it('2D - weighted - Reduction.MEAN', async () => { const predictions = tf.tensor2d([4, 8, 12, 8, 1, 3], [2, 3]); const label = tf.tensor2d([1, 9, 2, -5, -2, 6], [2, 3]); const weights = tf.tensor2d([3, 6, 5, 0, 4, 2], [2, 3]); const y = tf.losses.absoluteDifference(label, predictions, weights, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (Math.abs(4 - 1) * 3 + Math.abs(8 - 9) * 6 + Math.abs(12 - 2) * 5 + Math.abs(8 - (-5)) * 0 + Math.abs(1 - (-2)) * 4 + Math.abs(3 - 6) * 2) / 20); }); it('throws when passed label as a non-tensor', () => { const predictions = tf.tensor2d([4, 8, 12, 8, 1, 3], [2, 3]); const weights = tf.tensor2d([3, 6, 5, 0, 4, 2], [2, 3]); const e = /Argument 'labels' passed to 'absoluteDifference' must be a Tensor/; expect(() => tf.losses.absoluteDifference({}, predictions, weights, tf.Reduction.MEAN)) .toThrowError(e); }); it('throws when passed label as a non-tensor', () => { const label = tf.tensor2d([1, 9, 2, -5, -2, 6], [2, 3]); const weights = tf.tensor2d([3, 6, 5, 0, 4, 2], [2, 3]); const e = new RegExp('Argument \'predictions\' passed to \'absoluteDifference\' ' + 'must be a Tensor'); expect(() => tf.losses.absoluteDifference(label, {}, weights, tf.Reduction.MEAN)) .toThrowError(e); }); it('throws when passed weights as a non-tensor', () => { const predictions = tf.tensor2d([4, 8, 12, 8, 1, 3], [2, 3]); const label = tf.tensor2d([1, 9, 2, -5, -2, 6], [2, 3]); const e = /Argument 'weights' passed to 'absoluteDifference' must be a Tensor/; expect(() => tf.losses.absoluteDifference(label, predictions, {}, tf.Reduction.MEAN)) .toThrowError(e); }); it('accepts a tensor-like object', async () => { const predictions = [1, 2, 3]; const label = [0.3, -0.6, -0.1]; const weights = [0.1, 0.2, 0.3]; const y = tf.losses.absoluteDifference(label, predictions, weights, tf.Reduction.NONE); expect(y.shape).toEqual([3]); expectArraysClose(await y.data(), [ Math.abs(1 - 0.3) * 0.1, Math.abs(2 - (-0.6)) * 0.2, Math.abs(3 - (-0.1)) * 0.3 ]); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzb2x1dGVfZGlmZmVyZW5jZV90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvbG9zc2VzL2Fic29sdXRlX2RpZmZlcmVuY2VfdGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEVBQUMsUUFBUSxFQUFFLGlCQUFpQixFQUFDLE1BQU0sb0JBQW9CLENBQUM7QUFDL0QsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFFbEQsaUJBQWlCLENBQUMsb0JBQW9CLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRTtJQUNyRCxFQUFFLENBQUMsSUFBSSxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2xCLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFN0MsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFFM0QsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsaUJBQWlCLENBQ2IsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQ2QsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFD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LENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsaUJBQWlCLENBQ2IsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQ2QsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDcEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDdkQsQ0FBQyxDQUFDLENBQUM7SUFDYixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxrREFBa0QsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNoRSxNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdELE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFD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QWUsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQzNELFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QixDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw4QkFBOEIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM1QyxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDOUIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNoQyxNQUFNLE9BQU8sR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFaEMsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FDbEMsS0FBSyxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVwRCxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDaEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUc7WUFDbkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRztTQUMzQixDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjAgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi8uLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7ZXhwZWN0QXJyYXlzQ2xvc2V9IGZyb20gJy4uLy4uL3Rlc3RfdXRpbCc7XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdhYnNvbHV0ZURpZmZlcmVuY2UnLCBBTExfRU5WUywgKCkgPT4ge1xuICBpdCgnMUQnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMWQoWzAuMywgLTAuNiwgLTAuMV0pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5hYnNvbHV0ZURpZmZlcmVuY2UobGFiZWwsIHByZWRpY3Rpb25zKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFtdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgeS5kYXRhKCksXG4gICAgICAgIChNYXRoLmFicygxIC0gMC4zKSArIE1hdGguYWJzKDIgLSAoLTAuNikpICsgTWF0aC5hYnMoMyAtICgtMC4xKSkpIC8gMyk7XG4gIH0pO1xuXG4gIGl0KCcxRCAtIHdlaWdodGVkIC0gUmVkdWN0aW9uLlNVTV9CWV9OT05aRVJPX1dFSUdIVFMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMWQoWzAuMywgLTAuNiwgLTAuMV0pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi50ZW5zb3IxZChbMC4xLCAwLjIsIDAuM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5hYnNvbHV0ZURpZmZlcmVuY2UobGFiZWwsIHByZWRpY3Rpb25zLCB3ZWlnaHRzKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFtdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgeS5kYXRhKCksXG4gICAgICAgIChNYXRoLmFicygxIC0gMC4zKSAqIDAuMSArIE1hdGguYWJzKDIgLSAoLTAuNikpICogMC4yICtcbiAgICAgICAgIE1hdGguYWJzKDMgLSAoLTAuMSkpICogMC4zKSAvXG4gICAgICAgICAgICAzKTtcbiAgfSk7XG5cbiAgaXQoJzFEIC0gd2VpZ2h0ZWQgLSBSZWR1Y3Rpb24uTk9ORScsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IxZChbMC4zLCAtMC42LCAtMC4xXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjFkKFswLjEsIDAuMiwgMC4zXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmFic29sdXRlRGlmZmVyZW5jZShcbiAgICAgICAgbGFiZWwsIHByZWRpY3Rpb25zLCB3ZWlnaHRzLCB0Zi5SZWR1Y3Rpb24uTk9ORSk7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbM10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHkuZGF0YSgpLCBbXG4gICAgICBNYXRoLmFicygxIC0gMC4zKSAqIDAuMSwgTWF0aC5hYnMoMiAtICgtMC42KSkgKiAwLjIsXG4gICAgICBNYXRoLmFicygzIC0gKC0wLjEpKSAqIDAuM1xuICAgIF0pO1xuICB9KTtcblxuICBpdCgnMUQgLSBSZWR1Y3Rpb24uTUVBTicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IxZChbMC4zLCAtMC42LCAtMC4xXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmFic29sdXRlRGlmZmVyZW5jZShcbiAgICAgICAgbGFiZWwsIHByZWRpY3Rpb25zLCB1bmRlZmluZWQsIHRmLlJlZHVjdGlvbi5NRUFOKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFtdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgeS5kYXRhKCksXG4gICAgICAgIChNYXRoLmFicygxIC0gMC4zKSArIE1hdGguYWJzKDIgLSAoLTAuNikpICsgTWF0aC5hYnMoMyAtICgtMC4xKSkpIC8gMyk7XG4gIH0pO1xuXG4gIGl0KCcxRCAtIHdlaWdodGVkIC0gUmVkdWN0aW9uLk1FQU4nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMWQoWzAuMywgLTAuNiwgLTAuMV0pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi50ZW5zb3IxZChbMC4xLCAwLjIsIDAuM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5hYnNvbHV0ZURpZmZlcmVuY2UoXG4gICAgICAgIGxhYmVsLCBwcmVkaWN0aW9ucywgd2VpZ2h0cywgdGYuUmVkdWN0aW9uLk1FQU4pO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LmRhdGEoKSxcbiAgICAgICAgKChNYXRoLmFicygxIC0gMC4zKSAqIDAuMSkgKyAoTWF0aC5hYnMoMiAtICgtMC42KSkgKiAwLjIpICtcbiAgICAgICAgIChNYXRoLmFicygzIC0gKC0wLjEpKSAqIDAuMykpIC9cbiAgICAgICAgICAgIDAuNik7XG4gIH0pO1xuXG4gIGl0KCcyRCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFs0LCA4LCAxMiwgOCwgMSwgM10sIFsyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IyZChbMSwgOSwgMiwgLTUsIC0yLCA2XSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuYWJzb2x1dGVEaWZmZXJlbmNlKGxhYmVsLCBwcmVkaWN0aW9ucyk7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHkuZGF0YSgpLFxuICAgICAgICAoTWF0aC5hYnMoNCAtIDEpICsgTWF0aC5hYnMoOCAtIDkpICsgTWF0aC5hYnMoMTIgLSAyKSArXG4gICAgICAgICBNYXRoLmFicyg4IC0gKC01KSkgKyBNYXRoLmFicygxIC0gKC0yKSkgKyBNYXRoLmFicygzIC0gNikpIC9cbiAgICAgICAgICAgIDYpO1xuICB9KTtcblxuICBpdCgnMkQgLSB3ZWlnaHRlZCAtIFJlZHVjdGlvbi5TVU1fQllfTk9OWkVST19XRUlHSFRTJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMmQoWzQsIDgsIDEyLCA4LCAxLCAzXSwgWzIsIDNdKTtcbiAgICBjb25zdCBsYWJlbCA9IHRmLnRlbnNvcjJkKFsxLCA5LCAyLCAtNSwgLTIsIDZdLCBbMiwgM10pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi50ZW5zb3IyZChbMywgMCwgNSwgMCwgNCwgMl0sIFsyLCAzXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmFic29sdXRlRGlmZmVyZW5jZShsYWJlbCwgcHJlZGljdGlvbnMsIHdlaWdodHMpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LmRhdGEoKSxcbiAgICAgICAgKE1hdGguYWJzKDQgLSAxKSAqIDMgKyBNYXRoLmFicyg4IC0gOSkgKiAwICsgTWF0aC5hYnMoMTIgLSAyKSAqIDUgK1xuICAgICAgICAgTWF0aC5hYnMoOCAtICgtNSkpICogMCArIE1hdGguYWJzKDEgLSAoLTIpKSAqIDQgK1xuICAgICAgICAgTWF0aC5hYnMoMyAtIDYpICogMikgL1xuICAgICAgICAgICAgNCk7XG4gIH0pO1xuXG4gIGl0KCcyRCAtIHdlaWdodGVkIC0gUmVkdWN0aW9uLk5PTkUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IyZChbNCwgOCwgMTIsIDgsIDEsIDNdLCBbMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMmQoWzEsIDksIDIsIC01LCAtMiwgNl0sIFsyLCAzXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjJkKFszLCA2LCA1LCAwLCA0LCAyXSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuYWJzb2x1dGVEaWZmZXJlbmNlKFxuICAgICAgICBsYWJlbCwgcHJlZGljdGlvbnMsIHdlaWdodHMsIHRmLlJlZHVjdGlvbi5OT05FKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFsyLCAzXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIFtcbiAgICAgIE1hdGguYWJzKDQgLSAxKSAqIDMsIE1hdGguYWJzKDggLSA5KSAqIDYsIE1hdGguYWJzKDEyIC0gMikgKiA1LFxuICAgICAgTWF0aC5hYnMoOCAtICgtNSkpICogMCwgTWF0aC5hYnMoMSAtICgtMikpICogNCwgTWF0aC5hYnMoMyAtIDYpICogMlxuICAgIF0pO1xuICB9KTtcblxuICBpdCgnMkQgLSBSZWR1Y3Rpb24uTUVBTicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFs0LCA4LCAxMiwgOCwgMSwgM10sIFsyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IyZChbMSwgOSwgMiwgLTUsIC0yLCA2XSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuYWJzb2x1dGVEaWZmZXJlbmNlKFxuICAgICAgICBsYWJlbCwgcHJlZGljdGlvbnMsIHVuZGVmaW5lZCwgdGYuUmVkdWN0aW9uLk1FQU4pO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LmRhdGEoKSxcbiAgICAgICAgKE1hdGguYWJzKDQgLSAxKSArIE1hdGguYWJzKDggLSA5KSArIE1hdGguYWJzKDEyIC0gMikgK1xuICAgICAgICAgTWF0aC5hYnMoOCAtICgtNSkpICsgTWF0aC5hYnMoMSAtICgtMikpICsgTWF0aC5hYnMoMyAtIDYpKSAvXG4gICAgICAgICAgICA2KTtcbiAgfSk7XG5cbiAgaXQoJzJEIC0gd2VpZ2h0ZWQgLSBSZWR1Y3Rpb24uTUVBTicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFs0LCA4LCAxMiwgOCwgMSwgM10sIFsyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IyZChbMSwgOSwgMiwgLTUsIC0yLCA2XSwgWzIsIDNdKTtcbiAgICBjb25zdCB3ZWlnaHRzID0gdGYudGVuc29yMmQoWzMsIDYsIDUsIDAsIDQsIDJdLCBbMiwgM10pO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5hYnNvbHV0ZURpZmZlcmVuY2UoXG4gICAgICAgIGxhYmVsLCBwcmVkaWN0aW9ucywgd2VpZ2h0cywgdGYuUmVkdWN0aW9uLk1FQU4pO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LmRhdGEoKSxcbiAgICAgICAgKE1hdGguYWJzKDQgLSAxKSAqIDMgKyBNYXRoLmFicyg4IC0gOSkgKiA2ICsgTWF0aC5hYnMoMTIgLSAyKSAqIDUgK1xuICAgICAgICAgTWF0aC5hYnMoOCAtICgtNSkpICogMCArIE1hdGguYWJzKDEgLSAoLTIpKSAqIDQgK1xuICAgICAgICAgTWF0aC5hYnMoMyAtIDYpICogMikgL1xuICAgICAgICAgICAgMjApO1xuICB9KTtcblxuICBpdCgndGhyb3dzIHdoZW4gcGFzc2VkIGxhYmVsIGFzIGEgbm9uLXRlbnNvcicsICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFs0LCA4LCAxMiwgOCwgMSwgM10sIFsyLCAzXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjJkKFszLCA2LCA1LCAwLCA0LCAyXSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IGUgPVxuICAgICAgICAvQXJndW1lbnQgJ2xhYmVscycgcGFzc2VkIHRvICdhYnNvbHV0ZURpZmZlcmVuY2UnIG11c3QgYmUgYSBUZW5zb3IvO1xuICAgIGV4cGVjdChcbiAgICAgICAgKCkgPT4gdGYubG9zc2VzLmFic29sdXRlRGlmZmVyZW5jZShcbiAgICAgICAgICAgIHt9IGFzIHRmLlRlbnNvciwgcHJlZGljdGlvbnMsIHdlaWdodHMsIHRmLlJlZHVjdGlvbi5NRUFOKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcihlKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIHBhc3NlZCBsYWJlbCBhcyBhIG5vbi10ZW5zb3InLCAoKSA9PiB7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IyZChbMSwgOSwgMiwgLTUsIC0yLCA2XSwgWzIsIDNdKTtcbiAgICBjb25zdCB3ZWlnaHRzID0gdGYudGVuc29yMmQoWzMsIDYsIDUsIDAsIDQsIDJdLCBbMiwgM10pO1xuXG4gICAgY29uc3QgZSA9IG5ldyBSZWdFeHAoXG4gICAgICAgICdBcmd1bWVudCBcXCdwcmVkaWN0aW9uc1xcJyBwYXNzZWQgdG8gXFwnYWJzb2x1dGVEaWZmZXJlbmNlXFwnICcgK1xuICAgICAgICAnbXVzdCBiZSBhIFRlbnNvcicpO1xuICAgIGV4cGVjdChcbiAgICAgICAgKCkgPT4gdGYubG9zc2VzLmFic29sdXRlRGlmZmVyZW5jZShcbiAgICAgICAgICAgIGxhYmVsLCB7fSBhcyB0Zi5UZW5zb3IsIHdlaWdodHMsIHRmLlJlZHVjdGlvbi5NRUFOKSlcbiAgICAgICAgLnRvVGhyb3dFcnJvcihlKTtcbiAgfSk7XG5cbiAgaXQoJ3Rocm93cyB3aGVuIHBhc3NlZCB3ZWlnaHRzIGFzIGEgbm9uLXRlbnNvcicsICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFs0LCA4LCAxMiwgOCwgMSwgM10sIFsyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IyZChbMSwgOSwgMiwgLTUsIC0yLCA2XSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IGUgPVxuICAgICAgICAvQXJndW1lbnQgJ3dlaWdodHMnIHBhc3NlZCB0byAnYWJzb2x1dGVEaWZmZXJlbmNlJyBtdXN0IGJlIGEgVGVuc29yLztcbiAgICBleHBlY3QoXG4gICAgICAgICgpID0+IHRmLmxvc3Nlcy5hYnNvbHV0ZURpZmZlcmVuY2UoXG4gICAgICAgICAgICBsYWJlbCwgcHJlZGljdGlvbnMsIHt9IGFzIHRmLlRlbnNvciwgdGYuUmVkdWN0aW9uLk1FQU4pKVxuICAgICAgICAudG9UaHJvd0Vycm9yKGUpO1xuICB9KTtcblxuICBpdCgnYWNjZXB0cyBhIHRlbnNvci1saWtlIG9iamVjdCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IFsxLCAyLCAzXTtcbiAgICBjb25zdCBsYWJlbCA9IFswLjMsIC0wLjYsIC0wLjFdO1xuICAgIGNvbnN0IHdlaWdodHMgPSBbMC4xLCAwLjIsIDAuM107XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmFic29sdXRlRGlmZmVyZW5jZShcbiAgICAgICAgbGFiZWwsIHByZWRpY3Rpb25zLCB3ZWlnaHRzLCB0Zi5SZWR1Y3Rpb24uTk9ORSk7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbM10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHkuZGF0YSgpLCBbXG4gICAgICBNYXRoLmFicygxIC0gMC4zKSAqIDAuMSwgTWF0aC5hYnMoMiAtICgtMC42KSkgKiAwLjIsXG4gICAgICBNYXRoLmFicygzIC0gKC0wLjEpKSAqIDAuM1xuICAgIF0pO1xuICB9KTtcbn0pO1xuIl19