/** * @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('cosineDistance', 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.cosineDistance(label, predictions, 0); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), 1 - (1 * 0.3 + 2 * -0.6 + 3 * -0.1)); }); 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.scalar(0.1); const y = tf.losses.cosineDistance(label, predictions, 0, weights); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (1 - (1 * 0.3 + 2 * -0.6 + 3 * -0.1)) * 0.1); }); 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.scalar(0.1); const y = tf.losses.cosineDistance(label, predictions, 0, weights, tf.Reduction.NONE); expect(y.shape).toEqual([1]); expectArraysClose(await y.data(), [(1 - (1 * 0.3 + 2 * -0.6 + 3 * -0.1)) * 0.1]); }); 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.cosineDistance(label, predictions, 0, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), (1 - (1 * 0.3 + 2 * -0.6 + 3 * -0.1))); }); 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.scalar(0.1); const y = tf.losses.cosineDistance(label, predictions, 0, weights, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), ((1 - (1 * 0.3 + 2 * -0.6 + 3 * -0.1)) * 0.1) / 0.1); }); 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.cosineDistance(label, predictions, 1); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), ((1 - (4 * 1 + 8 * 9 + 12 * 2)) + (1 - (8 * -5 + 1 * -2 + 3 * 6))) / 2); }); 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], [2, 1]); const y = tf.losses.cosineDistance(label, predictions, 1, weights); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), ((1 - (4 * 1 + 8 * 9 + 12 * 2)) * 3 + (1 - (8 * -5 + 1 * -2 + 3 * 6)) * 0) / 1); }); 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, 0], [2, 1]); const y = tf.losses.cosineDistance(label, predictions, 1, weights, tf.Reduction.NONE); expect(y.shape).toEqual([2, 1]); expectArraysClose(await y.data(), [ (1 - (4 * 1 + 8 * 9 + 12 * 2)) * 3, (1 - (8 * -5 + 1 * -2 + 3 * 6)) * 0 ]); }); 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.cosineDistance(label, predictions, 1, undefined, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), ((1 - (4 * 1 + 8 * 9 + 12 * 2)) + (1 - (8 * -5 + 1 * -2 + 3 * 6))) / 2); }); 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, 0], [2, 1]); const y = tf.losses.cosineDistance(label, predictions, 1, weights, tf.Reduction.MEAN); expect(y.shape).toEqual([]); expectArraysClose(await y.data(), ((1 - (4 * 1 + 8 * 9 + 12 * 2)) * 3 + (1 - (8 * -5 + 1 * -2 + 3 * 6)) * 0) / 3); }); 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 'cosineDistance' must be a Tensor/; expect(() => tf.losses.cosineDistance({}, predictions, 0, 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 \'cosineDistance\' ' + 'must be a Tensor'); expect(() => tf.losses.cosineDistance(label, {}, 0, 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 'cosineDistance' must be a Tensor/; expect(() => tf.losses.cosineDistance(label, predictions, 0, {}, 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; const y = tf.losses.cosineDistance(label, predictions, 0, weights, tf.Reduction.NONE); expect(y.shape).toEqual([1]); expectArraysClose(await y.data(), [(1 - (1 * 0.3 + 2 * -0.6 + 3 * -0.1)) * 0.1]); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zaW5lX2Rpc3RhbmNlX3Rlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi90ZmpzLWNvcmUvc3JjL29wcy9sb3NzZXMvY29zaW5lX2Rpc3RhbmNlX3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQy9ELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBRWxELGlCQUFpQixDQUFDLGdCQUFnQixFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUU7SUFDakQsRUFBRSxDQUFDLElBQUksRUFBRSxLQUFLLElBQUksRUFBRTtRQUNsQixNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBRTdDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFMUQsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDNUIsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN6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QUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RCxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUV4RCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTFELE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzVCLGlCQUFpQixDQUNiLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUNkLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDOUUsQ0FBQyxDQUFDLENBQUM7SUFFSCxFQUFFLENBQUMsa0RBQWtELEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDaEUsTUFBTSxXQUFXLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3RCxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMs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QUFFLE9BQU8sRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXZELE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixpQkFBaUIsQ0FDYixNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5pbXBvcnQgKiBhcyB0ZiBmcm9tICcuLi8uLi9pbmRleCc7XG5pbXBvcnQge0FMTF9FTlZTLCBkZXNjcmliZVdpdGhGbGFnc30gZnJvbSAnLi4vLi4vamFzbWluZV91dGlsJztcbmltcG9ydCB7ZXhwZWN0QXJyYXlzQ2xvc2V9IGZyb20gJy4uLy4uL3Rlc3RfdXRpbCc7XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdjb3NpbmVEaXN0YW5jZScsIEFMTF9FTlZTLCAoKSA9PiB7XG4gIGl0KCcxRCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IxZChbMC4zLCAtMC42LCAtMC4xXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmNvc2luZURpc3RhbmNlKGxhYmVsLCBwcmVkaWN0aW9ucywgMCk7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksIDEgLSAoMSAqIDAuMyArIDIgKiAtMC42ICsgMyAqIC0wLjEpKTtcbiAgfSk7XG5cbiAgaXQoJzFEIC0gd2VpZ2h0ZWQgLSBSZWR1Y3Rpb24uU1VNX0JZX05PTlpFUk9fV0VJR0hUUycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjFkKFsxLCAyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IxZChbMC4zLCAtMC42LCAtMC4xXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnNjYWxhcigwLjEpO1xuXG4gICAgY29uc3QgeSA9IHRmLmxvc3Nlcy5jb3NpbmVEaXN0YW5jZShsYWJlbCwgcHJlZGljdGlvbnMsIDAsIHdlaWdodHMpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LmRhdGEoKSwgKDEgLSAoMSAqIDAuMyArIDIgKiAtMC42ICsgMyAqIC0wLjEpKSAqIDAuMSk7XG4gIH0pO1xuXG4gIGl0KCcxRCAtIHdlaWdodGVkIC0gUmVkdWN0aW9uLk5PTkUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IxZChbMSwgMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMWQoWzAuMywgLTAuNiwgLTAuMV0pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi5zY2FsYXIoMC4xKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuY29zaW5lRGlzdGFuY2UoXG4gICAgICAgIGxhYmVsLCBwcmVkaWN0aW9ucywgMCwgd2VpZ2h0cywgdGYuUmVkdWN0aW9uLk5PTkUpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoWzFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgeS5kYXRhKCksIFsoMSAtICgxICogMC4zICsgMiAqIC0wLjYgKyAzICogLTAuMSkpICogMC4xXSk7XG4gIH0pO1xuXG4gIGl0KCcxRCAtIFJlZHVjdGlvbi5NRUFOJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMWQoWzEsIDIsIDNdKTtcbiAgICBjb25zdCBsYWJlbCA9IHRmLnRlbnNvcjFkKFswLjMsIC0wLjYsIC0wLjFdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuY29zaW5lRGlzdGFuY2UoXG4gICAgICAgIGxhYmVsLCBwcmVkaWN0aW9ucywgMCwgdW5kZWZpbmVkLCB0Zi5SZWR1Y3Rpb24uTUVBTik7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgeS5kYXRhKCksICgxIC0gKDEgKiAwLjMgKyAyICogLTAuNiArIDMgKiAtMC4xKSkpO1xuICB9KTtcblxuICBpdCgnMUQgLSB3ZWlnaHRlZCAtIFJlZHVjdGlvbi5NRUFOJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMWQoWzEsIDIsIDNdKTtcbiAgICBjb25zdCBsYWJlbCA9IHRmLnRlbnNvcjFkKFswLjMsIC0wLjYsIC0wLjFdKTtcbiAgICBjb25zdCB3ZWlnaHRzID0gdGYuc2NhbGFyKDAuMSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmNvc2luZURpc3RhbmNlKFxuICAgICAgICBsYWJlbCwgcHJlZGljdGlvbnMsIDAsIHdlaWdodHMsIHRmLlJlZHVjdGlvbi5NRUFOKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFtdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgeS5kYXRhKCksICgoMSAtICgxICogMC4zICsgMiAqIC0wLjYgKyAzICogLTAuMSkpICogMC4xKSAvIDAuMSk7XG4gIH0pO1xuXG4gIGl0KCcyRCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFs0LCA4LCAxMiwgOCwgMSwgM10sIFsyLCAzXSk7XG4gICAgY29uc3QgbGFiZWwgPSB0Zi50ZW5zb3IyZChbMSwgOSwgMiwgLTUsIC0yLCA2XSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuY29zaW5lRGlzdGFuY2UobGFiZWwsIHByZWRpY3Rpb25zLCAxKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFtdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgYXdhaXQgeS5kYXRhKCksXG4gICAgICAgICgoMSAtICg0ICogMSArIDggKiA5ICsgMTIgKiAyKSkgKyAoMSAtICg4ICogLTUgKyAxICogLTIgKyAzICogNikpKSAvIDIpO1xuICB9KTtcblxuICBpdCgnMkQgLSB3ZWlnaHRlZCAtIFJlZHVjdGlvbi5TVU1fQllfTk9OWkVST19XRUlHSFRTJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMmQoWzQsIDgsIDEyLCA4LCAxLCAzXSwgWzIsIDNdKTtcbiAgICBjb25zdCBsYWJlbCA9IHRmLnRlbnNvcjJkKFsxLCA5LCAyLCAtNSwgLTIsIDZdLCBbMiwgM10pO1xuICAgIGNvbnN0IHdlaWdodHMgPSB0Zi50ZW5zb3IyZChbMywgMF0sIFsyLCAxXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmNvc2luZURpc3RhbmNlKGxhYmVsLCBwcmVkaWN0aW9ucywgMSwgd2VpZ2h0cyk7XG5cbiAgICBleHBlY3QoeS5zaGFwZSkudG9FcXVhbChbXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHkuZGF0YSgpLFxuICAgICAgICAoKDEgLSAoNCAqIDEgKyA4ICogOSArIDEyICogMikpICogMyArXG4gICAgICAgICAoMSAtICg4ICogLTUgKyAxICogLTIgKyAzICogNikpICogMCkgL1xuICAgICAgICAgICAgMSk7XG4gIH0pO1xuXG4gIGl0KCcyRCAtIHdlaWdodGVkIC0gUmVkdWN0aW9uLk5PTkUnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IyZChbNCwgOCwgMTIsIDgsIDEsIDNdLCBbMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMmQoWzEsIDksIDIsIC01LCAtMiwgNl0sIFsyLCAzXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjJkKFszLCAwXSwgWzIsIDFdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuY29zaW5lRGlzdGFuY2UoXG4gICAgICAgIGxhYmVsLCBwcmVkaWN0aW9ucywgMSwgd2VpZ2h0cywgdGYuUmVkdWN0aW9uLk5PTkUpO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoWzIsIDFdKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCB5LmRhdGEoKSwgW1xuICAgICAgKDEgLSAoNCAqIDEgKyA4ICogOSArIDEyICogMikpICogMywgKDEgLSAoOCAqIC01ICsgMSAqIC0yICsgMyAqIDYpKSAqIDBcbiAgICBdKTtcbiAgfSk7XG5cbiAgaXQoJzJEIC0gUmVkdWN0aW9uLk1FQU4nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IyZChbNCwgOCwgMTIsIDgsIDEsIDNdLCBbMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMmQoWzEsIDksIDIsIC01LCAtMiwgNl0sIFsyLCAzXSk7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmNvc2luZURpc3RhbmNlKFxuICAgICAgICBsYWJlbCwgcHJlZGljdGlvbnMsIDEsIHVuZGVmaW5lZCwgdGYuUmVkdWN0aW9uLk1FQU4pO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LmRhdGEoKSxcbiAgICAgICAgKCgxIC0gKDQgKiAxICsgOCAqIDkgKyAxMiAqIDIpKSArICgxIC0gKDggKiAtNSArIDEgKiAtMiArIDMgKiA2KSkpIC8gMik7XG4gIH0pO1xuXG4gIGl0KCcyRCAtIHdlaWdodGVkIC0gUmVkdWN0aW9uLk1FQU4nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcHJlZGljdGlvbnMgPSB0Zi50ZW5zb3IyZChbNCwgOCwgMTIsIDgsIDEsIDNdLCBbMiwgM10pO1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMmQoWzEsIDksIDIsIC01LCAtMiwgNl0sIFsyLCAzXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjJkKFszLCAwXSwgWzIsIDFdKTtcblxuICAgIGNvbnN0IHkgPSB0Zi5sb3NzZXMuY29zaW5lRGlzdGFuY2UoXG4gICAgICAgIGxhYmVsLCBwcmVkaWN0aW9ucywgMSwgd2VpZ2h0cywgdGYuUmVkdWN0aW9uLk1FQU4pO1xuXG4gICAgZXhwZWN0KHkuc2hhcGUpLnRvRXF1YWwoW10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICBhd2FpdCB5LmRhdGEoKSxcbiAgICAgICAgKCgxIC0gKDQgKiAxICsgOCAqIDkgKyAxMiAqIDIpKSAqIDMgK1xuICAgICAgICAgKDEgLSAoOCAqIC01ICsgMSAqIC0yICsgMyAqIDYpKSAqIDApIC9cbiAgICAgICAgICAgIDMpO1xuICB9KTtcblxuICBpdCgndGhyb3dzIHdoZW4gcGFzc2VkIGxhYmVsIGFzIGEgbm9uLXRlbnNvcicsICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IHRmLnRlbnNvcjJkKFs0LCA4LCAxMiwgOCwgMSwgM10sIFsyLCAzXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjJkKFszLCA2LCA1LCAwLCA0LCAyXSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IGUgPSAvQXJndW1lbnQgJ2xhYmVscycgcGFzc2VkIHRvICdjb3NpbmVEaXN0YW5jZScgbXVzdCBiZSBhIFRlbnNvci87XG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5sb3NzZXMuY29zaW5lRGlzdGFuY2UoXG4gICAgICAgICAgICB7fSBhcyB0Zi5UZW5zb3IsIHByZWRpY3Rpb25zLCAwLCB3ZWlnaHRzLCB0Zi5SZWR1Y3Rpb24uTUVBTikpXG4gICAgICAgIC50b1Rocm93RXJyb3IoZSk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvd3Mgd2hlbiBwYXNzZWQgbGFiZWwgYXMgYSBub24tdGVuc29yJywgKCkgPT4ge1xuICAgIGNvbnN0IGxhYmVsID0gdGYudGVuc29yMmQoWzEsIDksIDIsIC01LCAtMiwgNl0sIFsyLCAzXSk7XG4gICAgY29uc3Qgd2VpZ2h0cyA9IHRmLnRlbnNvcjJkKFszLCA2LCA1LCAwLCA0LCAyXSwgWzIsIDNdKTtcblxuICAgIGNvbnN0IGUgPSBuZXcgUmVnRXhwKFxuICAgICAgICAnQXJndW1lbnQgXFwncHJlZGljdGlvbnNcXCcgcGFzc2VkIHRvIFxcJ2Nvc2luZURpc3RhbmNlXFwnICcgK1xuICAgICAgICAnbXVzdCBiZSBhIFRlbnNvcicpO1xuICAgIGV4cGVjdChcbiAgICAgICAgKCkgPT4gdGYubG9zc2VzLmNvc2luZURpc3RhbmNlKFxuICAgICAgICAgICAgbGFiZWwsIHt9IGFzIHRmLlRlbnNvciwgMCwgd2VpZ2h0cywgdGYuUmVkdWN0aW9uLk1FQU4pKVxuICAgICAgICAudG9UaHJvd0Vycm9yKGUpO1xuICB9KTtcblxuICBpdCgndGhyb3dzIHdoZW4gcGFzc2VkIHdlaWdodHMgYXMgYSBub24tdGVuc29yJywgKCkgPT4ge1xuICAgIGNvbnN0IHByZWRpY3Rpb25zID0gdGYudGVuc29yMmQoWzQsIDgsIDEyLCA4LCAxLCAzXSwgWzIsIDNdKTtcbiAgICBjb25zdCBsYWJlbCA9IHRmLnRlbnNvcjJkKFsxLCA5LCAyLCAtNSwgLTIsIDZdLCBbMiwgM10pO1xuXG4gICAgY29uc3QgZSA9IC9Bcmd1bWVudCAnd2VpZ2h0cycgcGFzc2VkIHRvICdjb3NpbmVEaXN0YW5jZScgbXVzdCBiZSBhIFRlbnNvci87XG4gICAgZXhwZWN0KFxuICAgICAgICAoKSA9PiB0Zi5sb3NzZXMuY29zaW5lRGlzdGFuY2UoXG4gICAgICAgICAgICBsYWJlbCwgcHJlZGljdGlvbnMsIDAsIHt9IGFzIHRmLlRlbnNvciwgdGYuUmVkdWN0aW9uLk1FQU4pKVxuICAgICAgICAudG9UaHJvd0Vycm9yKGUpO1xuICB9KTtcblxuICBpdCgnYWNjZXB0cyBhIHRlbnNvci1saWtlIG9iamVjdCcsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwcmVkaWN0aW9ucyA9IFsxLCAyLCAzXTtcbiAgICBjb25zdCBsYWJlbCA9IFswLjMsIC0wLjYsIC0wLjFdO1xuICAgIGNvbnN0IHdlaWdodHMgPSAwLjE7XG5cbiAgICBjb25zdCB5ID0gdGYubG9zc2VzLmNvc2luZURpc3RhbmNlKFxuICAgICAgICBsYWJlbCwgcHJlZGljdGlvbnMsIDAsIHdlaWdodHMsIHRmLlJlZHVjdGlvbi5OT05FKTtcblxuICAgIGV4cGVjdCh5LnNoYXBlKS50b0VxdWFsKFsxXSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoXG4gICAgICAgIGF3YWl0IHkuZGF0YSgpLCBbKDEgLSAoMSAqIDAuMyArIDIgKiAtMC42ICsgMyAqIC0wLjEpKSAqIDAuMV0pO1xuICB9KTtcbn0pO1xuIl19