/** * @license * Copyright 2017 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('movingAverage', ALL_ENVS, () => { // Use the following tensorflow to generate reference values for // `zeroDebias` = `true`; // // ```python // import tensorflow as tf // from tensorflow.python.training.moving_averages import // assign_moving_average // // with tf.Session() as sess: // v = tf.get_variable("v1", shape=[2, 2], dtype=tf.float32, // initializer=tf.zeros_initializer) // x = tf.Variable([[1.0, 2.0], [3.0, 4.0]]) // inc_x = x.assign_add([[10.0, 10.0], [10.0, 10.0]]) // update = assign_moving_average(v, x, 0.6) // // sess.run(tf.global_variables_initializer()) // // sess.run(update) // print(sess.run(v)) // // sess.run(inc_x) // sess.run(update) // print(sess.run(v)) // ``` it('zeroDebias=true, decay and step are numbers', async () => { const v0 = tf.tensor2d([[0, 0], [0, 0]], [2, 2]); const x = tf.tensor2d([[1, 2], [3, 4]], [2, 2]); const decay = 0.6; const v1 = tf.movingAverage(v0, x, decay, 1); expectArraysClose(await v1.array(), [[1, 2], [3, 4]]); const y = tf.tensor2d([[11, 12], [13, 14]], [2, 2]); const v2 = tf.movingAverage(v1, y, decay, 2); expectArraysClose(await v2.array(), [[7.25, 8.25], [9.25, 10.25]]); }); it('zeroDebias=true, decay and step are scalars', async () => { const v0 = tf.tensor2d([[0, 0], [0, 0]], [2, 2]); const x = tf.tensor2d([[1, 2], [3, 4]], [2, 2]); const decay = tf.scalar(0.6); const v1 = tf.movingAverage(v0, x, decay, tf.scalar(1)); expectArraysClose(await v1.array(), [[1, 2], [3, 4]]); const y = tf.tensor2d([[11, 12], [13, 14]], [2, 2]); const v2 = tf.movingAverage(v1, y, decay, tf.scalar(2)); expectArraysClose(await v2.array(), [[7.25, 8.25], [9.25, 10.25]]); }); // Use the following tensorflow to generate reference values for // `zeroDebias` = `false`; // // ```python // import tensorflow as tf // from tensorflow.python.training.moving_averages import // assign_moving_average // // with tf.Session() as sess: // v = tf.get_variable("v1", shape=[2, 2], dtype=tf.float32, // initializer=tf.zeros_initializer) // x = tf.Variable([[1.0, 2.0], [3.0, 4.0]]) // inc_x = x.assign_add([[10.0, 10.0], [10.0, 10.0]]) // update = assign_moving_average(v, x, 0.6, zero_debias=False) // // sess.run(tf.global_variables_initializer()) // // sess.run(update) // print(sess.run(v)) // // sess.run(inc_x) // sess.run(update) // print(sess.run(v)) // ``` it('zeroDebias=false, decay and step are numbers', async () => { const v0 = tf.tensor2d([[0, 0], [0, 0]], [2, 2]); const x = tf.tensor2d([[1, 2], [3, 4]], [2, 2]); const decay = 0.6; const v1 = tf.movingAverage(v0, x, decay, null, false); expectArraysClose(await v1.array(), [[0.4, 0.8], [1.2, 1.6]]); const y = tf.tensor2d([[11, 12], [13, 14]], [2, 2]); const v2 = tf.movingAverage(v1, y, decay, null, false); expectArraysClose(await v2.array(), [[4.64, 5.28], [5.92, 6.56]]); }); it('zeroDebias=false, decay is scalar', async () => { const v0 = tf.tensor2d([[0, 0], [0, 0]], [2, 2]); const x = tf.tensor2d([[1, 2], [3, 4]], [2, 2]); const decay = tf.scalar(0.6); const v1 = tf.movingAverage(v0, x, decay, null, false); expectArraysClose(await v1.array(), [[0.4, 0.8], [1.2, 1.6]]); const y = tf.tensor2d([[11, 12], [13, 14]], [2, 2]); const v2 = tf.movingAverage(v1, y, decay, null, false); expectArraysClose(await v2.array(), [[4.64, 5.28], [5.92, 6.56]]); }); it('zeroDebias=true, no step throws error', () => { const v0 = tf.tensor2d([[0, 0], [0, 0]], [2, 2]); const x = tf.tensor2d([[1, 2], [3, 4]], [2, 2]); const decay = tf.scalar(0.6); expect(() => tf.movingAverage(v0, x, decay, null)).toThrowError(); }); it('shape mismatch in v and x throws error', () => { const v0 = tf.tensor2d([[0, 0], [0, 0]], [2, 2]); const x = tf.tensor2d([[1, 2]], [1, 2]); const decay = tf.scalar(0.6); expect(() => tf.movingAverage(v0, x, decay, null)).toThrowError(); }); it('throws when passed v as a non-tensor', () => { const x = tf.tensor2d([[1, 2], [3, 4]], [2, 2]); expect(() => tf.movingAverage({}, x, 1)) .toThrowError(/Argument 'v' passed to 'movingAverage' must be a Tensor/); }); it('throws when passed v as a non-tensor', () => { const v = tf.tensor2d([[0, 0], [0, 0]], [2, 2]); expect(() => tf.movingAverage(v, {}, 1)) .toThrowError(/Argument 'x' passed to 'movingAverage' must be a Tensor/); }); it('accepts a tensor-like object', async () => { const v0 = [[0, 0], [0, 0]]; // 2x2 const x = [[1, 2], [3, 4]]; // 2x2 const decay = 0.6; const v1 = tf.movingAverage(v0, x, decay, 1); expectArraysClose(await v1.array(), [[1, 2], [3, 4]]); }); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW92aW5nX2F2ZXJhZ2VfdGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3RmanMtY29yZS9zcmMvb3BzL21vdmluZ19hdmVyYWdlX3Rlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDL0IsT0FBTyxFQUFDLFFBQVEsRUFBRSxpQkFBaUIsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzVELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUUvQyxpQkFBaUIsQ0FBQyxlQUFlLEVBQUUsUUFBUSxFQUFFLEdBQUcsRUFBRTtJQUNoRCxnRUFBZ0U7SUFDaEUseUJBQXlCO0lBQ3pCLEVBQUU7SUFDRixZQUFZO0lBQ1osMEJBQTBCO0lBQzFCLHlEQUF5RDtJQUN6RCx3QkFBd0I7SUFDeEIsRUFBRTtJQUNGLDZCQUE2QjtJQUM3Qiw4REFBOEQ7SUFDOUQsMERBQTBEO0lBQzFELDhDQUE4QztJQUM5Qyx1REFBdUQ7SUFDdkQsOENBQThDO0lBQzlDLEVBQUU7SUFDRixnREFBZ0Q7SUFDaEQsRUFBRTtJQUNGLHFCQUFxQjtJQUNyQix1QkFBdUI7SUFDdkIsRUFBRTtJQUNGLG9CQUFvQjtJQUNwQixxQkFBcUI7SUFDckIsdUJBQXVCO0lBQ3ZCLE1BQU07SUFFTixFQUFFLENBQUMsNkNBQTZDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDM0QsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVB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Q0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRCxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN2RCxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyxtQ0FBbUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNqRCxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEQsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUU3QixNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN2RCxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztR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Q0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFaEQsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLEVBQWUsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNoRCxZQUFZLENBQ1QseURBQXlELENBQUMsQ0FBQztJQUNyRSxDQUFDLENBQUMsQ0FBQztJQUVILEVBQUUsQ0FBQyw4QkFBOEIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUM1QyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBRSxNQUFNO1FBQ3BDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFHLE1BQU07UUFDcEMsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDO1FBRWxCLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0MsaUJBQWlCLENBQUMsTUFBTSxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDE3IEdvb2dsZSBMTEMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gKi9cblxuaW1wb3J0ICogYXMgdGYgZnJvbSAnLi4vaW5kZXgnO1xuaW1wb3J0IHtBTExfRU5WUywgZGVzY3JpYmVXaXRoRmxhZ3N9IGZyb20gJy4uL2phc21pbmVfdXRpbCc7XG5pbXBvcnQge2V4cGVjdEFycmF5c0Nsb3NlfSBmcm9tICcuLi90ZXN0X3V0aWwnO1xuXG5kZXNjcmliZVdpdGhGbGFncygnbW92aW5nQXZlcmFnZScsIEFMTF9FTlZTLCAoKSA9PiB7XG4gIC8vIFVzZSB0aGUgZm9sbG93aW5nIHRlbnNvcmZsb3cgdG8gZ2VuZXJhdGUgcmVmZXJlbmNlIHZhbHVlcyBmb3JcbiAgLy8gYHplcm9EZWJpYXNgID0gYHRydWVgO1xuICAvL1xuICAvLyBgYGBweXRob25cbiAgLy8gaW1wb3J0IHRlbnNvcmZsb3cgYXMgdGZcbiAgLy8gZnJvbSB0ZW5zb3JmbG93LnB5dGhvbi50cmFpbmluZy5tb3ZpbmdfYXZlcmFnZXMgaW1wb3J0XG4gIC8vIGFzc2lnbl9tb3ZpbmdfYXZlcmFnZVxuICAvL1xuICAvLyB3aXRoIHRmLlNlc3Npb24oKSBhcyBzZXNzOlxuICAvLyAgIHYgPSB0Zi5nZXRfdmFyaWFibGUoXCJ2MVwiLCBzaGFwZT1bMiwgMl0sIGR0eXBlPXRmLmZsb2F0MzIsXG4gIC8vICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsaXplcj10Zi56ZXJvc19pbml0aWFsaXplcilcbiAgLy8gICB4ID0gdGYuVmFyaWFibGUoW1sxLjAsIDIuMF0sIFszLjAsIDQuMF1dKVxuICAvLyAgIGluY194ID0geC5hc3NpZ25fYWRkKFtbMTAuMCwgMTAuMF0sIFsxMC4wLCAxMC4wXV0pXG4gIC8vICAgdXBkYXRlID0gYXNzaWduX21vdmluZ19hdmVyYWdlKHYsIHgsIDAuNilcbiAgLy9cbiAgLy8gICBzZXNzLnJ1bih0Zi5nbG9iYWxfdmFyaWFibGVzX2luaXRpYWxpemVyKCkpXG4gIC8vXG4gIC8vICAgc2Vzcy5ydW4odXBkYXRlKVxuICAvLyAgIHByaW50KHNlc3MucnVuKHYpKVxuICAvL1xuICAvLyAgIHNlc3MucnVuKGluY194KVxuICAvLyAgIHNlc3MucnVuKHVwZGF0ZSlcbiAgLy8gICBwcmludChzZXNzLnJ1bih2KSlcbiAgLy8gYGBgXG5cbiAgaXQoJ3plcm9EZWJpYXM9dHJ1ZSwgZGVjYXkgYW5kIHN0ZXAgYXJlIG51bWJlcnMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdjAgPSB0Zi50ZW5zb3IyZChbWzAsIDBdLCBbMCwgMF1dLCBbMiwgMl0pO1xuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3IyZChbWzEsIDJdLCBbMywgNF1dLCBbMiwgMl0pO1xuICAgIGNvbnN0IGRlY2F5ID0gMC42O1xuXG4gICAgY29uc3QgdjEgPSB0Zi5tb3ZpbmdBdmVyYWdlKHYwLCB4LCBkZWNheSwgMSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgdjEuYXJyYXkoKSwgW1sxLCAyXSwgWzMsIDRdXSk7XG5cbiAgICBjb25zdCB5ID0gdGYudGVuc29yMmQoW1sxMSwgMTJdLCBbMTMsIDE0XV0sIFsyLCAyXSk7XG4gICAgY29uc3QgdjIgPSB0Zi5tb3ZpbmdBdmVyYWdlKHYxLCB5LCBkZWNheSwgMik7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgdjIuYXJyYXkoKSwgW1s3LjI1LCA4LjI1XSwgWzkuMjUsIDEwLjI1XV0pO1xuICB9KTtcblxuICBpdCgnemVyb0RlYmlhcz10cnVlLCBkZWNheSBhbmQgc3RlcCBhcmUgc2NhbGFycycsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB2MCA9IHRmLnRlbnNvcjJkKFtbMCwgMF0sIFswLCAwXV0sIFsyLCAyXSk7XG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjJkKFtbMSwgMl0sIFszLCA0XV0sIFsyLCAyXSk7XG4gICAgY29uc3QgZGVjYXkgPSB0Zi5zY2FsYXIoMC42KTtcblxuICAgIGNvbnN0IHYxID0gdGYubW92aW5nQXZlcmFnZSh2MCwgeCwgZGVjYXksIHRmLnNjYWxhcigxKSk7XG4gICAgZXhwZWN0QXJyYXlzQ2xvc2UoYXdhaXQgdjEuYXJyYXkoKSwgW1sxLCAyXSwgWzMsIDRdXSk7XG5cbiAgICBjb25zdCB5ID0gdGYudGVuc29yMmQoW1sxMSwgMTJdLCBbMTMsIDE0XV0sIFsyLCAyXSk7XG4gICAgY29uc3QgdjIgPSB0Zi5tb3ZpbmdBdmVyYWdlKHYxLCB5LCBkZWNheSwgdGYuc2NhbGFyKDIpKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCB2Mi5hcnJheSgpLCBbWzcuMjUsIDguMjVdLCBbOS4yNSwgMTAuMjVdXSk7XG4gIH0pO1xuXG4gIC8vIFVzZSB0aGUgZm9sbG93aW5nIHRlbnNvcmZsb3cgdG8gZ2VuZXJhdGUgcmVmZXJlbmNlIHZhbHVlcyBmb3JcbiAgLy8gYHplcm9EZWJpYXNgID0gYGZhbHNlYDtcbiAgLy9cbiAgLy8gYGBgcHl0aG9uXG4gIC8vIGltcG9ydCB0ZW5zb3JmbG93IGFzIHRmXG4gIC8vIGZyb20gdGVuc29yZmxvdy5weXRob24udHJhaW5pbmcubW92aW5nX2F2ZXJhZ2VzIGltcG9ydFxuICAvLyBhc3NpZ25fbW92aW5nX2F2ZXJhZ2VcbiAgLy9cbiAgLy8gd2l0aCB0Zi5TZXNzaW9uKCkgYXMgc2VzczpcbiAgLy8gICB2ID0gdGYuZ2V0X3ZhcmlhYmxlKFwidjFcIiwgc2hhcGU9WzIsIDJdLCBkdHlwZT10Zi5mbG9hdDMyLFxuICAvLyAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbGl6ZXI9dGYuemVyb3NfaW5pdGlhbGl6ZXIpXG4gIC8vICAgeCA9IHRmLlZhcmlhYmxlKFtbMS4wLCAyLjBdLCBbMy4wLCA0LjBdXSlcbiAgLy8gICBpbmNfeCA9IHguYXNzaWduX2FkZChbWzEwLjAsIDEwLjBdLCBbMTAuMCwgMTAuMF1dKVxuICAvLyAgIHVwZGF0ZSA9IGFzc2lnbl9tb3ZpbmdfYXZlcmFnZSh2LCB4LCAwLjYsIHplcm9fZGViaWFzPUZhbHNlKVxuICAvL1xuICAvLyAgIHNlc3MucnVuKHRmLmdsb2JhbF92YXJpYWJsZXNfaW5pdGlhbGl6ZXIoKSlcbiAgLy9cbiAgLy8gICBzZXNzLnJ1bih1cGRhdGUpXG4gIC8vICAgcHJpbnQoc2Vzcy5ydW4odikpXG4gIC8vXG4gIC8vICAgc2Vzcy5ydW4oaW5jX3gpXG4gIC8vICAgc2Vzcy5ydW4odXBkYXRlKVxuICAvLyAgIHByaW50KHNlc3MucnVuKHYpKVxuICAvLyBgYGBcblxuICBpdCgnemVyb0RlYmlhcz1mYWxzZSwgZGVjYXkgYW5kIHN0ZXAgYXJlIG51bWJlcnMnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdjAgPSB0Zi50ZW5zb3IyZChbWzAsIDBdLCBbMCwgMF1dLCBbMiwgMl0pO1xuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3IyZChbWzEsIDJdLCBbMywgNF1dLCBbMiwgMl0pO1xuICAgIGNvbnN0IGRlY2F5ID0gMC42O1xuXG4gICAgY29uc3QgdjEgPSB0Zi5tb3ZpbmdBdmVyYWdlKHYwLCB4LCBkZWNheSwgbnVsbCwgZmFsc2UpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHYxLmFycmF5KCksIFtbMC40LCAwLjhdLCBbMS4yLCAxLjZdXSk7XG5cbiAgICBjb25zdCB5ID0gdGYudGVuc29yMmQoW1sxMSwgMTJdLCBbMTMsIDE0XV0sIFsyLCAyXSk7XG4gICAgY29uc3QgdjIgPSB0Zi5tb3ZpbmdBdmVyYWdlKHYxLCB5LCBkZWNheSwgbnVsbCwgZmFsc2UpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHYyLmFycmF5KCksIFtbNC42NCwgNS4yOF0sIFs1LjkyLCA2LjU2XV0pO1xuICB9KTtcblxuICBpdCgnemVyb0RlYmlhcz1mYWxzZSwgZGVjYXkgaXMgc2NhbGFyJywgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHYwID0gdGYudGVuc29yMmQoW1swLCAwXSwgWzAsIDBdXSwgWzIsIDJdKTtcbiAgICBjb25zdCB4ID0gdGYudGVuc29yMmQoW1sxLCAyXSwgWzMsIDRdXSwgWzIsIDJdKTtcbiAgICBjb25zdCBkZWNheSA9IHRmLnNjYWxhcigwLjYpO1xuXG4gICAgY29uc3QgdjEgPSB0Zi5tb3ZpbmdBdmVyYWdlKHYwLCB4LCBkZWNheSwgbnVsbCwgZmFsc2UpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHYxLmFycmF5KCksIFtbMC40LCAwLjhdLCBbMS4yLCAxLjZdXSk7XG5cbiAgICBjb25zdCB5ID0gdGYudGVuc29yMmQoW1sxMSwgMTJdLCBbMTMsIDE0XV0sIFsyLCAyXSk7XG4gICAgY29uc3QgdjIgPSB0Zi5tb3ZpbmdBdmVyYWdlKHYxLCB5LCBkZWNheSwgbnVsbCwgZmFsc2UpO1xuICAgIGV4cGVjdEFycmF5c0Nsb3NlKGF3YWl0IHYyLmFycmF5KCksIFtbNC42NCwgNS4yOF0sIFs1LjkyLCA2LjU2XV0pO1xuICB9KTtcblxuICBpdCgnemVyb0RlYmlhcz10cnVlLCBubyBzdGVwIHRocm93cyBlcnJvcicsICgpID0+IHtcbiAgICBjb25zdCB2MCA9IHRmLnRlbnNvcjJkKFtbMCwgMF0sIFswLCAwXV0sIFsyLCAyXSk7XG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjJkKFtbMSwgMl0sIFszLCA0XV0sIFsyLCAyXSk7XG4gICAgY29uc3QgZGVjYXkgPSB0Zi5zY2FsYXIoMC42KTtcblxuICAgIGV4cGVjdCgoKSA9PiB0Zi5tb3ZpbmdBdmVyYWdlKHYwLCB4LCBkZWNheSwgbnVsbCkpLnRvVGhyb3dFcnJvcigpO1xuICB9KTtcblxuICBpdCgnc2hhcGUgbWlzbWF0Y2ggaW4gdiBhbmQgeCB0aHJvd3MgZXJyb3InLCAoKSA9PiB7XG4gICAgY29uc3QgdjAgPSB0Zi50ZW5zb3IyZChbWzAsIDBdLCBbMCwgMF1dLCBbMiwgMl0pO1xuICAgIGNvbnN0IHggPSB0Zi50ZW5zb3IyZChbWzEsIDJdXSwgWzEsIDJdKTtcbiAgICBjb25zdCBkZWNheSA9IHRmLnNjYWxhcigwLjYpO1xuXG4gICAgZXhwZWN0KCgpID0+IHRmLm1vdmluZ0F2ZXJhZ2UodjAsIHgsIGRlY2F5LCBudWxsKSkudG9UaHJvd0Vycm9yKCk7XG4gIH0pO1xuXG4gIGl0KCd0aHJvd3Mgd2hlbiBwYXNzZWQgdiBhcyBhIG5vbi10ZW5zb3InLCAoKSA9PiB7XG4gICAgY29uc3QgeCA9IHRmLnRlbnNvcjJkKFtbMSwgMl0sIFszLCA0XV0sIFsyLCAyXSk7XG5cbiAgICBleHBlY3QoKCkgPT4gdGYubW92aW5nQXZlcmFnZSh7fSBhcyB0Zi5UZW5zb3IsIHgsIDEpKVxuICAgICAgICAudG9UaHJvd0Vycm9yKFxuICAgICAgICAgICAgL0FyZ3VtZW50ICd2JyBwYXNzZWQgdG8gJ21vdmluZ0F2ZXJhZ2UnIG11c3QgYmUgYSBUZW5zb3IvKTtcbiAgfSk7XG4gIGl0KCd0aHJvd3Mgd2hlbiBwYXNzZWQgdiBhcyBhIG5vbi10ZW5zb3InLCAoKSA9PiB7XG4gICAgY29uc3QgdiA9IHRmLnRlbnNvcjJkKFtbMCwgMF0sIFswLCAwXV0sIFsyLCAyXSk7XG5cbiAgICBleHBlY3QoKCkgPT4gdGYubW92aW5nQXZlcmFnZSh2LCB7fSBhcyB0Zi5UZW5zb3IsIDEpKVxuICAgICAgICAudG9UaHJvd0Vycm9yKFxuICAgICAgICAgICAgL0FyZ3VtZW50ICd4JyBwYXNzZWQgdG8gJ21vdmluZ0F2ZXJhZ2UnIG11c3QgYmUgYSBUZW5zb3IvKTtcbiAgfSk7XG5cbiAgaXQoJ2FjY2VwdHMgYSB0ZW5zb3ItbGlrZSBvYmplY3QnLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdjAgPSBbWzAsIDBdLCBbMCwgMF1dOyAgLy8gMngyXG4gICAgY29uc3QgeCA9IFtbMSwgMl0sIFszLCA0XV07ICAgLy8gMngyXG4gICAgY29uc3QgZGVjYXkgPSAwLjY7XG5cbiAgICBjb25zdCB2MSA9IHRmLm1vdmluZ0F2ZXJhZ2UodjAsIHgsIGRlY2F5LCAxKTtcbiAgICBleHBlY3RBcnJheXNDbG9zZShhd2FpdCB2MS5hcnJheSgpLCBbWzEsIDJdLCBbMywgNF1dKTtcbiAgfSk7XG59KTtcbiJdfQ==