/** * @license * Copyright 2022 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, expectArraysEqual } from '../test_util'; async function runRaggedGather(indicesShape, indices, paramsNestedSplits, paramsDenseValuesShape, paramsDenseValues) { const paramsRaggedRank = paramsNestedSplits.length; const numSplits = paramsRaggedRank + indicesShape.length - 1; const paramsNestedSplitsTensors = paramsNestedSplits.map(values => tf.tensor1d(values, 'int32')); const paramsDenseValuesTensor = tf.tensor(paramsDenseValues, paramsDenseValuesShape); const indicesTensor = tf.tensor(indices, indicesShape, 'int32'); const output = tf.raggedGather(paramsNestedSplitsTensors, paramsDenseValuesTensor, indicesTensor, numSplits); tf.dispose(paramsNestedSplitsTensors); tf.dispose([paramsDenseValuesTensor, indicesTensor]); expect(output.outputDenseValues.dtype).toEqual('float32'); output.outputNestedSplits.forEach(splits => { expect(splits.dtype).toEqual('int32'); expect(splits.shape.length).toEqual(1); }); return { outputDenseValues: await output.outputDenseValues.data(), outputDenseValuesShape: output.outputDenseValues.shape, outputNestedSplits: await Promise.all(output.outputNestedSplits.map(splits => splits.data())), tensors: output.outputNestedSplits.concat([output.outputDenseValues]) }; } describeWithFlags('raggedGather ', ALL_ENVS, () => { it('RaggedGather', async () => { const result = await runRaggedGather([4], [2, 1, 0, 3], [[0, 3, 3, 7, 9]], [9], [.1, .2, .3, .4, .5, .6, .7, .8, .9]); expect(result.outputNestedSplits.length).toEqual(1); expectArraysClose(result.outputNestedSplits[0], [0, 4, 4, 7, 9]); expectArraysClose(result.outputDenseValues, [.4, .5, .6, .7, .1, .2, .3, .8, .9]); expectArraysEqual(result.outputDenseValuesShape, [9]); }); it('RaggedGather3DParams', async () => { const result = await runRaggedGather([5], [2, 1, 0, 2, 3], [[0, 1, 3, 3, 5, 6], [0, 0, 2, 3, 5, 8, 9]], [9], [.1, .2, .3, .4, .5, .6, .7, .8, .9]); expect(result.outputNestedSplits.length).toEqual(2); expectArraysClose(result.outputNestedSplits[0], [0, 0, 2, 3, 3, 5]); expectArraysClose(result.outputNestedSplits[1], [0, 2, 3, 3, 5, 8]); expectArraysClose(result.outputDenseValues, [.1, .2, .3, .4, .5, .6, .7, .8]); expectArraysEqual(result.outputDenseValuesShape, [8]); }); it('RaggedGather4DParams', async () => { const result = await runRaggedGather([4], [2, 1, 0, 2], [[0, 1, 3, 3], [0, 0, 3, 4]], [4, 2], [1, 2, 3, 4, 5, 6, 7, 8]); expect(result.outputNestedSplits.length).toEqual(2); expectArraysClose(result.outputNestedSplits[0], [0, 0, 2, 3, 3]); expectArraysClose(result.outputNestedSplits[1], [0, 3, 4, 4]); expectArraysClose(result.outputDenseValues, [1, 2, 3, 4, 5, 6, 7, 8]); expectArraysEqual(result.outputDenseValuesShape, [4, 2]); }); it('RaggedGather2DIndices', async () => { const result = await runRaggedGather([2, 2], [2, 1, 0, 3], [[0, 3, 3, 7, 9]], [9], [.1, .2, .3, .4, .5, .6, .7, .8, .9]); expect(result.outputNestedSplits.length).toEqual(2); expectArraysClose(result.outputNestedSplits[0], [0, 2, 4]); expectArraysClose(result.outputNestedSplits[1], [0, 4, 4, 7, 9]); expectArraysClose(result.outputDenseValues, [.4, .5, .6, .7, .1, .2, .3, .8, .9]); expectArraysEqual(result.outputDenseValuesShape, [9]); }); it('RaggedGatherScalarIndices', async () => { const result = await runRaggedGather([], [2], [[0, 3, 3, 7, 9]], [9], [.1, .2, .3, .4, .5, .6, .7, .8, .9]); expect(result.outputNestedSplits.length).toEqual(0); expectArraysClose(result.outputDenseValues, [.4, .5, .6, .7]); expectArraysEqual(result.outputDenseValuesShape, [4]); }); it('OutOfBounds', async () => { await expectAsync(runRaggedGather([2], [2, 10], [[0, 3, 3, 7, 9]], [9], [ .1, .2, .3, .4, .5, .6, .7, .8, .9 ])).toBeRejectedWithError('indices[1] = 10 is not in [0, 4)'); }); it('InvalidSplitsNotSorted', async () => { await expectAsync(runRaggedGather([2], [0, 2], [[0, 3, 5, 2, 9]], [9], [.1, .2, .3, .4, .5, .6, .7, .8, .9])) .toBeRejectedWithError('Ragged splits must be sorted in ascending order'); }); it('InvalidSplitsNegative', async () => { await expectAsync(runRaggedGather([2], [0, 2], [[-1, 3, 2, 7, 9]], [9], [ .1, .2, .3, .4, .5, .6, .7, .8, .9 ])).toBeRejectedWithError('Ragged splits must be non-negative'); }); it('InvalidSplitsEmpty', async () => { await expectAsync(runRaggedGather([0], [], [[]], [0], [])) .toBeRejectedWithError('Ragged splits may not be empty'); }); it('InvalidSplitsTooBig', async () => { await expectAsync(runRaggedGather([2], [0, 2], [[0, 20, 40, 80, 100]], [9], [.1, .2, .3, .4, .5, .6, .7, .8, .9])) .toBeRejectedWithError('Ragged splits must not point past values'); }); it('BadValuesShape', async () => { await expectAsync(runRaggedGather([0], [], [[0]], [], [.1])) .toBeRejectedWithError('params.rank must be nonzero'); }); it('does not have memory leak.', async () => { const beforeDataIds = tf.engine().backend.numDataIds(); const result = await runRaggedGather([4], [2, 1, 0, 3], [[0, 3, 3, 7, 9]], [9], [.1, .2, .3, .4, .5, .6, .7, .8, .9]); const afterResDataIds = tf.engine().backend.numDataIds(); expect(afterResDataIds).toEqual(beforeDataIds + 2); result.tensors.map(tensor => tensor.dispose()); const afterDisposeDataIds = tf.engine().backend.numDataIds(); expect(afterDisposeDataIds).toEqual(beforeDataIds); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFnZ2VkX2dhdGhlcl90ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGZqcy1jb3JlL3NyYy9vcHMvcmFnZ2VkX2dhdGhlcl90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQy9CLE9BQU8sRUFBQyxRQUFRLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RCxPQUFPLEVBQUMsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFFbEUsS0FBSyxVQUFVLGVBQWUsQ0FDMUIsWUFBc0IsRUFBRSxPQUFpQixFQUFFLGtCQUE4QixFQUN6RSxzQkFBZ0MsRUFBRSxpQkFBMkI7SUFDL0QsTUFBTSxnQkFBZ0IsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLENBQUM7SUFDbkQsTUFBTSxTQUFTLEdBQUcsZ0JBQWdCLEdBQUcsWUFBWSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFFN0QsTUFBTSx5QkFBeUIsR0FDM0Isa0JBQWtCLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNuRSxNQUFNLHVCQUF1QixHQUN6QixFQUFFLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLHNCQUFzQixDQUFDLENBQUM7SUFDekQsTUFBTSxhQUFhLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRWhFLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQzFCLHlCQUF5QixFQUFFLHVCQUF1QixFQUFFLGFBQWEsRUFDakUsU0FBUyxDQUFDLENBQUM7SUFFZixFQUFFLENBQUMsT0FBTyxDQUFDLHlCQUF5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QUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTFDLE1BQU0sZUFBZSxHQUFHLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDekQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxhQUFhLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFbkQsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUUvQyxNQUFNLG1CQUFtQixHQUFHLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDN0QsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3JELENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMiBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbmltcG9ydCAqIGFzIHRmIGZyb20gJy4uL2luZGV4JztcbmltcG9ydCB7QUxMX0VOVlMsIGRlc2NyaWJlV2l0aEZsYWdzfSBmcm9tICcuLi9qYXNtaW5lX3V0aWwnO1xuaW1wb3J0IHtleHBlY3RBcnJheXNDbG9zZSwgZXhwZWN0QXJyYXlzRXF1YWx9IGZyb20gJy4uL3Rlc3RfdXRpbCc7XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1blJhZ2dlZEdhdGhlcihcbiAgICBpbmRpY2VzU2hhcGU6IG51bWJlcltdLCBpbmRpY2VzOiBudW1iZXJbXSwgcGFyYW1zTmVzdGVkU3BsaXRzOiBudW1iZXJbXVtdLFxuICAgIHBhcmFtc0RlbnNlVmFsdWVzU2hhcGU6IG51bWJlcltdLCBwYXJhbXNEZW5zZVZhbHVlczogbnVtYmVyW10pIHtcbiAgY29uc3QgcGFyYW1zUmFnZ2VkUmFuayA9IHBhcmFtc05lc3RlZFNwbGl0cy5sZW5ndGg7XG4gIGNvbnN0IG51bVNwbGl0cyA9IHBhcmFtc1JhZ2dlZFJhbmsgKyBpbmRpY2VzU2hhcGUubGVuZ3RoIC0gMTtcblxuICBjb25zdCBwYXJhbXNOZXN0ZWRTcGxpdHNUZW5zb3JzID1cbiAgICAgIHBhcmFtc05lc3RlZFNwbGl0cy5tYXAodmFsdWVzID0+IHRmLnRlbnNvcjFkKHZhbHVlcywgJ2ludDMyJykpO1xuICBjb25zdCBwYXJhbXNEZW5zZVZhbHVlc1RlbnNvciA9XG4gICAgICB0Zi50ZW5zb3IocGFyYW1zRGVuc2VWYWx1ZXMsIHBhcmFtc0RlbnNlVmFsdWVzU2hhcGUpO1xuICBjb25zdCBpbmRpY2VzVGVuc29yID0gdGYudGVuc29yKGluZGljZXMsIGluZGljZXNTaGFwZSwgJ2ludDMyJyk7XG5cbiAgY29uc3Qgb3V0cHV0ID0gdGYucmFnZ2VkR2F0aGVyKFxuICAgICAgcGFyYW1zTmVzdGVkU3BsaXRzVGVuc29ycywgcGFyYW1zRGVuc2VWYWx1ZXNUZW5zb3IsIGluZGljZXNUZW5zb3IsXG4gICAgICBudW1TcGxpdHMpO1xuXG4gIHRmLmRpc3Bvc2UocGFyYW1zTmVzdGVkU3BsaXRzVGVuc29ycyk7XG4gIHRmLmRpc3Bvc2UoW3BhcmFtc0RlbnNlVmFsdWVzVGVuc29yLCBpbmRpY2VzVGVuc29yXSk7XG5cbiAgZXhwZWN0KG91dHB1dC5vdXRwdXREZW5zZVZhbHVlcy5kdHlwZSkudG9FcXVhbCgnZmxvYXQzMicpO1xuXG4gIG91dHB1dC5vdXRwdXROZXN0ZWRTcGxpdHMuZm9yRWFjaChzcGxpdHMgPT4ge1xuICAgIGV4cGVjdChzcGxpdHMuZHR5cGUpLnRvRXF1YWwoJ2ludDMyJyk7XG4gICAgZXhwZWN0KHNwbGl0cy5zaGFwZS5sZW5ndGgpLnRvRXF1YWwoMSk7XG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgb3V0cHV0RGVuc2VWYWx1ZXM6IGF3YWl0IG91dHB1dC5vdXRwdXREZW5zZVZhbHVlcy5kYXRhKCksXG4gICAgb3V0cHV0RGVuc2VWYWx1ZXNTaGFwZTogb3V0cHV0Lm91dHB1dERlbnNlVmFsdWVzLnNoYXBlLFxuICAgIG91dHB1dE5lc3RlZFNwbGl0czogYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIG91dHB1dC5vdXRwdXROZXN0ZWRTcGxpdHMubWFwKHNwbGl0cyA9PiBzcGxpdHMuZGF0YSgpKSksXG4gICAgdGVuc29yczogb3V0cHV0Lm91dHB1dE5lc3RlZFNwbGl0cy5jb25jYXQoW291dHB1dC5vdXRwdXREZW5zZVZhbHVlc10pXG4gIH07XG59XG5cbmRlc2NyaWJlV2l0aEZsYWdzKCdyYWdnZWRHYXRoZXIgJywgQUxMX0VOVlMsICgpID0+IHtcbiAgaXQoJ1JhZ2dlZEdhdGhlcicsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBydW5SYWdnZWRHYXRoZXIoXG4gICAgICAgIFs0XSwgWzIsIDEsIDAsIDNdLCBbWzAsIDMsIDMsIDcsIDldXSwgWzldLFxuICAgICAgICBbLjEsIC4yLCAuMywgLjQsIC41LCAuNiwgLjcsIC44LCAuOV0pO1xuXG4gICAgZXhwZWN0KHJlc3VsdC5vdXRwdXROZXN0ZWRTcGxpdHMubGVuZ3RoKS50b0VxdWFsKDEpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKHJlc3VsdC5vdXRwdXROZXN0ZWRTcGxpdHNbMF0sIFswLCA0LCA0LCA3LCA5XSk7XG5cbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgcmVzdWx0Lm91dHB1dERlbnNlVmFsdWVzLCBbLjQsIC41LCAuNiwgLjcsIC4xLCAuMiwgLjMsIC44LCAuOV0pO1xuICAgIGV4cGVjdEFycmF5c0VxdWFsKHJlc3VsdC5vdXRwdXREZW5zZVZhbHVlc1NoYXBlLCBbOV0pO1xuICB9KTtcblxuICBpdCgnUmFnZ2VkR2F0aGVyM0RQYXJhbXMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuUmFnZ2VkR2F0aGVyKFxuICAgICAgICBbNV0sIFsyLCAxLCAwLCAyLCAzXSwgW1swLCAxLCAzLCAzLCA1LCA2XSwgWzAsIDAsIDIsIDMsIDUsIDgsIDldXSwgWzldLFxuICAgICAgICBbLjEsIC4yLCAuMywgLjQsIC41LCAuNiwgLjcsIC44LCAuOV0pO1xuXG4gICAgZXhwZWN0KHJlc3VsdC5vdXRwdXROZXN0ZWRTcGxpdHMubGVuZ3RoKS50b0VxdWFsKDIpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKHJlc3VsdC5vdXRwdXROZXN0ZWRTcGxpdHNbMF0sIFswLCAwLCAyLCAzLCAzLCA1XSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UocmVzdWx0Lm91dHB1dE5lc3RlZFNwbGl0c1sxXSwgWzAsIDIsIDMsIDMsIDUsIDhdKTtcblxuICAgIGV4cGVjdEFycmF5c0Nsb3NlKFxuICAgICAgICByZXN1bHQub3V0cHV0RGVuc2VWYWx1ZXMsIFsuMSwgLjIsIC4zLCAuNCwgLjUsIC42LCAuNywgLjhdKTtcbiAgICBleHBlY3RBcnJheXNFcXVhbChyZXN1bHQub3V0cHV0RGVuc2VWYWx1ZXNTaGFwZSwgWzhdKTtcbiAgfSk7XG5cbiAgaXQoJ1JhZ2dlZEdhdGhlcjREUGFyYW1zJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJ1blJhZ2dlZEdhdGhlcihcbiAgICAgICAgWzRdLCBbMiwgMSwgMCwgMl0sIFtbMCwgMSwgMywgM10sIFswLCAwLCAzLCA0XV0sIFs0LCAyXSxcbiAgICAgICAgWzEsIDIsIDMsIDQsIDUsIDYsIDcsIDhdKTtcblxuICAgIGV4cGVjdChyZXN1bHQub3V0cHV0TmVzdGVkU3BsaXRzLmxlbmd0aCkudG9FcXVhbCgyKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShyZXN1bHQub3V0cHV0TmVzdGVkU3BsaXRzWzBdLCBbMCwgMCwgMiwgMywgM10pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKHJlc3VsdC5vdXRwdXROZXN0ZWRTcGxpdHNbMV0sIFswLCAzLCA0LCA0XSk7XG5cbiAgICBleHBlY3RBcnJheXNDbG9zZShyZXN1bHQub3V0cHV0RGVuc2VWYWx1ZXMsIFsxLCAyLCAzLCA0LCA1LCA2LCA3LCA4XSk7XG4gICAgZXhwZWN0QXJyYXlzRXF1YWwocmVzdWx0Lm91dHB1dERlbnNlVmFsdWVzU2hhcGUsIFs0LCAyXSk7XG4gIH0pO1xuXG4gIGl0KCdSYWdnZWRHYXRoZXIyREluZGljZXMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuUmFnZ2VkR2F0aGVyKFxuICAgICAgICBbMiwgMl0sIFsyLCAxLCAwLCAzXSwgW1swLCAzLCAzLCA3LCA5XV0sIFs5XSxcbiAgICAgICAgWy4xLCAuMiwgLjMsIC40LCAuNSwgLjYsIC43LCAuOCwgLjldKTtcblxuICAgIGV4cGVjdChyZXN1bHQub3V0cHV0TmVzdGVkU3BsaXRzLmxlbmd0aCkudG9FcXVhbCgyKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShyZXN1bHQub3V0cHV0TmVzdGVkU3BsaXRzWzBdLCBbMCwgMiwgNF0pO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKHJlc3VsdC5vdXRwdXROZXN0ZWRTcGxpdHNbMV0sIFswLCA0LCA0LCA3LCA5XSk7XG5cbiAgICBleHBlY3RBcnJheXNDbG9zZShcbiAgICAgICAgcmVzdWx0Lm91dHB1dERlbnNlVmFsdWVzLCBbLjQsIC41LCAuNiwgLjcsIC4xLCAuMiwgLjMsIC44LCAuOV0pO1xuICAgIGV4cGVjdEFycmF5c0VxdWFsKHJlc3VsdC5vdXRwdXREZW5zZVZhbHVlc1NoYXBlLCBbOV0pO1xuICB9KTtcblxuICBpdCgnUmFnZ2VkR2F0aGVyU2NhbGFySW5kaWNlcycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBydW5SYWdnZWRHYXRoZXIoXG4gICAgICAgIFtdLCBbMl0sIFtbMCwgMywgMywgNywgOV1dLCBbOV0sIFsuMSwgLjIsIC4zLCAuNCwgLjUsIC42LCAuNywgLjgsIC45XSk7XG5cbiAgICBleHBlY3QocmVzdWx0Lm91dHB1dE5lc3RlZFNwbGl0cy5sZW5ndGgpLnRvRXF1YWwoMCk7XG5cbiAgICBleHBlY3RBcnJheXNDbG9zZShyZXN1bHQub3V0cHV0RGVuc2VWYWx1ZXMsIFsuNCwgLjUsIC42LCAuN10pO1xuICAgIGV4cGVjdEFycmF5c0VxdWFsKHJlc3VsdC5vdXRwdXREZW5zZVZhbHVlc1NoYXBlLCBbNF0pO1xuICB9KTtcblxuICBpdCgnT3V0T2ZCb3VuZHMnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgZXhwZWN0QXN5bmMocnVuUmFnZ2VkR2F0aGVyKFsyXSwgWzIsIDEwXSwgW1swLCAzLCAzLCA3LCA5XV0sIFs5XSwgW1xuICAgICAgLjEsIC4yLCAuMywgLjQsIC41LCAuNiwgLjcsIC44LCAuOVxuICAgIF0pKS50b0JlUmVqZWN0ZWRXaXRoRXJyb3IoJ2luZGljZXNbMV0gPSAxMCBpcyBub3QgaW4gWzAsIDQpJyk7XG4gIH0pO1xuXG4gIGl0KCdJbnZhbGlkU3BsaXRzTm90U29ydGVkJywgYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IGV4cGVjdEFzeW5jKHJ1blJhZ2dlZEdhdGhlcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgWzJdLCBbMCwgMl0sIFtbMCwgMywgNSwgMiwgOV1dLCBbOV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFsuMSwgLjIsIC4zLCAuNCwgLjUsIC42LCAuNywgLjgsIC45XSkpXG4gICAgICAgIC50b0JlUmVqZWN0ZWRXaXRoRXJyb3IoXG4gICAgICAgICAgICAnUmFnZ2VkIHNwbGl0cyBtdXN0IGJlIHNvcnRlZCBpbiBhc2NlbmRpbmcgb3JkZXInKTtcbiAgfSk7XG5cbiAgaXQoJ0ludmFsaWRTcGxpdHNOZWdhdGl2ZScsIGFzeW5jICgpID0+IHtcbiAgICBhd2FpdCBleHBlY3RBc3luYyhydW5SYWdnZWRHYXRoZXIoWzJdLCBbMCwgMl0sIFtbLTEsIDMsIDIsIDcsIDldXSwgWzldLCBbXG4gICAgICAuMSwgLjIsIC4zLCAuNCwgLjUsIC42LCAuNywgLjgsIC45XG4gICAgXSkpLnRvQmVSZWplY3RlZFdpdGhFcnJvcignUmFnZ2VkIHNwbGl0cyBtdXN0IGJlIG5vbi1uZWdhdGl2ZScpO1xuICB9KTtcblxuICBpdCgnSW52YWxpZFNwbGl0c0VtcHR5JywgYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IGV4cGVjdEFzeW5jKHJ1blJhZ2dlZEdhdGhlcihbMF0sIFtdLCBbW11dLCBbMF0sIFtdKSlcbiAgICAgICAgLnRvQmVSZWplY3RlZFdpdGhFcnJvcignUmFnZ2VkIHNwbGl0cyBtYXkgbm90IGJlIGVtcHR5Jyk7XG4gIH0pO1xuXG4gIGl0KCdJbnZhbGlkU3BsaXRzVG9vQmlnJywgYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IGV4cGVjdEFzeW5jKHJ1blJhZ2dlZEdhdGhlcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgWzJdLCBbMCwgMl0sIFtbMCwgMjAsIDQwLCA4MCwgMTAwXV0sIFs5XSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgWy4xLCAuMiwgLjMsIC40LCAuNSwgLjYsIC43LCAuOCwgLjldKSlcbiAgICAgICAgLnRvQmVSZWplY3RlZFdpdGhFcnJvcignUmFnZ2VkIHNwbGl0cyBtdXN0IG5vdCBwb2ludCBwYXN0IHZhbHVlcycpO1xuICB9KTtcblxuICBpdCgnQmFkVmFsdWVzU2hhcGUnLCBhc3luYyAoKSA9PiB7XG4gICAgYXdhaXQgZXhwZWN0QXN5bmMocnVuUmFnZ2VkR2F0aGVyKFswXSwgW10sIFtbMF1dLCBbXSwgWy4xXSkpXG4gICAgICAgIC50b0JlUmVqZWN0ZWRXaXRoRXJyb3IoJ3BhcmFtcy5yYW5rIG11c3QgYmUgbm9uemVybycpO1xuICB9KTtcblxuICBpdCgnZG9lcyBub3QgaGF2ZSBtZW1vcnkgbGVhay4nLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgYmVmb3JlRGF0YUlkcyA9IHRmLmVuZ2luZSgpLmJhY2tlbmQubnVtRGF0YUlkcygpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuUmFnZ2VkR2F0aGVyKFxuICAgICAgICBbNF0sIFsyLCAxLCAwLCAzXSwgW1swLCAzLCAzLCA3LCA5XV0sIFs5XSxcbiAgICAgICAgWy4xLCAuMiwgLjMsIC40LCAuNSwgLjYsIC43LCAuOCwgLjldKTtcblxuICAgIGNvbnN0IGFmdGVyUmVzRGF0YUlkcyA9IHRmLmVuZ2luZSgpLmJhY2tlbmQubnVtRGF0YUlkcygpO1xuICAgIGV4cGVjdChhZnRlclJlc0RhdGFJZHMpLnRvRXF1YWwoYmVmb3JlRGF0YUlkcyArIDIpO1xuXG4gICAgcmVzdWx0LnRlbnNvcnMubWFwKHRlbnNvciA9PiB0ZW5zb3IuZGlzcG9zZSgpKTtcblxuICAgIGNvbnN0IGFmdGVyRGlzcG9zZURhdGFJZHMgPSB0Zi5lbmdpbmUoKS5iYWNrZW5kLm51bURhdGFJZHMoKTtcbiAgICBleHBlY3QoYWZ0ZXJEaXNwb3NlRGF0YUlkcykudG9FcXVhbChiZWZvcmVEYXRhSWRzKTtcbiAgfSk7XG59KTtcbiJdfQ==