@tensorflow/tfjs-layers
Version:
TensorFlow layers API in JavaScript
307 lines • 24.7 kB
JavaScript
import * as losses from './losses';
import * as metrics from './metrics';
/**
* Binary accuracy metric function.
*
* `yTrue` and `yPred` can have 0-1 values. Example:
* ```js
* const x = tf.tensor2d([[1, 1, 1, 1], [0, 0, 0, 0]], [2, 4]);
* const y = tf.tensor2d([[1, 0, 1, 0], [0, 0, 0, 1]], [2, 4]);
* const accuracy = tf.metrics.binaryAccuracy(x, y);
* accuracy.print();
* ```
*
* `yTrue` and `yPred` can also have floating-number values between 0 and 1, in
* which case the values will be thresholded at 0.5 to yield 0-1 values (i.e.,
* a value >= 0.5 and <= 1.0 is interpreted as 1).
*
* Example:
* ```js
* const x = tf.tensor1d([1, 1, 1, 1, 0, 0, 0, 0]);
* const y = tf.tensor1d([0.2, 0.4, 0.6, 0.8, 0.2, 0.3, 0.4, 0.7]);
* const accuracy = tf.metrics.binaryAccuracy(x, y);
* accuracy.print();
* ```
*
* @param yTrue Binary Tensor of truth.
* @param yPred Binary Tensor of prediction.
* @return Accuracy Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function binaryAccuracy(yTrue, yPred) {
return metrics.binaryAccuracy(yTrue, yPred);
}
/**
* Binary crossentropy metric function.
*
* Example:
* ```js
* const x = tf.tensor2d([[0], [1], [1], [1]]);
* const y = tf.tensor2d([[0], [0], [0.5], [1]]);
* const crossentropy = tf.metrics.binaryCrossentropy(x, y);
* crossentropy.print();
* ```
*
* @param yTrue Binary Tensor of truth.
* @param yPred Binary Tensor of prediction, probabilities for the `1` case.
* @return Accuracy Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function binaryCrossentropy(yTrue, yPred) {
return metrics.binaryCrossentropy(yTrue, yPred);
}
/**
* Sparse categorical accuracy metric function.
*
* Example:
* ```js
*
* const yTrue = tf.tensor1d([1, 1, 2, 2, 0]);
* const yPred = tf.tensor2d(
* [[0, 1, 0], [1, 0, 0], [0, 0.4, 0.6], [0, 0.6, 0.4], [0.7, 0.3, 0]]);
* const crossentropy = tf.metrics.sparseCategoricalAccuracy(yTrue, yPred);
* crossentropy.print();
* ```
*
* @param yTrue True labels: indices.
* @param yPred Predicted probabilities or logits.
* @returns Accuracy tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function sparseCategoricalAccuracy(yTrue, yPred) {
return metrics.sparseCategoricalAccuracy(yTrue, yPred);
}
/**
* Categorical accuracy metric function.
*
* Example:
* ```js
* const x = tf.tensor2d([[0, 0, 0, 1], [0, 0, 0, 1]]);
* const y = tf.tensor2d([[0.1, 0.8, 0.05, 0.05], [0.1, 0.05, 0.05, 0.8]]);
* const accuracy = tf.metrics.categoricalAccuracy(x, y);
* accuracy.print();
* ```
*
* @param yTrue Binary Tensor of truth: one-hot encoding of categories.
* @param yPred Binary Tensor of prediction: probabilities or logits for the
* same categories as in `yTrue`.
* @return Accuracy Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function categoricalAccuracy(yTrue, yPred) {
return metrics.categoricalAccuracy(yTrue, yPred);
}
/**
* Categorical crossentropy between an output tensor and a target tensor.
*
* @param target A tensor of the same shape as `output`.
* @param output A tensor resulting from a softmax (unless `fromLogits` is
* `true`, in which case `output` is expected to be the logits).
* @param fromLogits Boolean, whether `output` is the result of a softmax, or is
* a tensor of logits.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function categoricalCrossentropy(yTrue, yPred) {
return metrics.categoricalCrossentropy(yTrue, yPred);
}
/**
* Computes the precision of the predictions with respect to the labels.
*
* Example:
* ```js
* const x = tf.tensor2d(
* [
* [0, 0, 0, 1],
* [0, 1, 0, 0],
* [0, 0, 0, 1],
* [1, 0, 0, 0],
* [0, 0, 1, 0]
* ]
* );
*
* const y = tf.tensor2d(
* [
* [0, 0, 1, 0],
* [0, 1, 0, 0],
* [0, 0, 0, 1],
* [0, 1, 0, 0],
* [0, 1, 0, 0]
* ]
* );
*
* const precision = tf.metrics.precision(x, y);
* precision.print();
* ```
*
* @param yTrue The ground truth values. Expected to contain only 0-1 values.
* @param yPred The predicted values. Expected to contain only 0-1 values.
* @return Precision Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function precision(yTrue, yPred) {
return metrics.precision(yTrue, yPred);
}
/**
* Computes the recall of the predictions with respect to the labels.
*
* Example:
* ```js
* const x = tf.tensor2d(
* [
* [0, 0, 0, 1],
* [0, 1, 0, 0],
* [0, 0, 0, 1],
* [1, 0, 0, 0],
* [0, 0, 1, 0]
* ]
* );
*
* const y = tf.tensor2d(
* [
* [0, 0, 1, 0],
* [0, 1, 0, 0],
* [0, 0, 0, 1],
* [0, 1, 0, 0],
* [0, 1, 0, 0]
* ]
* );
*
* const recall = tf.metrics.recall(x, y);
* recall.print();
* ```
*
* @param yTrue The ground truth values. Expected to contain only 0-1 values.
* @param yPred The predicted values. Expected to contain only 0-1 values.
* @return Recall Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function recall(yTrue, yPred) {
return metrics.recall(yTrue, yPred);
}
/**
* Loss or metric function: Cosine proximity.
*
* Mathematically, cosine proximity is defined as:
* `-sum(l2Normalize(yTrue) * l2Normalize(yPred))`,
* wherein `l2Normalize()` normalizes the L2 norm of the input to 1 and `*`
* represents element-wise multiplication.
*
* ```js
* const yTrue = tf.tensor2d([[1, 0], [1, 0]]);
* const yPred = tf.tensor2d([[1 / Math.sqrt(2), 1 / Math.sqrt(2)], [0, 1]]);
* const proximity = tf.metrics.cosineProximity(yTrue, yPred);
* proximity.print();
* ```
*
* @param yTrue Truth Tensor.
* @param yPred Prediction Tensor.
* @return Cosine proximity Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function cosineProximity(yTrue, yPred) {
return losses.cosineProximity(yTrue, yPred);
}
/**
* Loss or metric function: Mean absolute error.
*
* Mathematically, mean absolute error is defined as:
* `mean(abs(yPred - yTrue))`,
* wherein the `mean` is applied over feature dimensions.
*
* ```js
* const yTrue = tf.tensor2d([[0, 1], [0, 0], [2, 3]]);
* const yPred = tf.tensor2d([[0, 1], [0, 1], [-2, -3]]);
* const mse = tf.metrics.meanAbsoluteError(yTrue, yPred);
* mse.print();
* ```
*
* @param yTrue Truth Tensor.
* @param yPred Prediction Tensor.
* @return Mean absolute error Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function meanAbsoluteError(yTrue, yPred) {
return losses.meanAbsoluteError(yTrue, yPred);
}
/**
* Loss or metric function: Mean absolute percentage error.
*
* ```js
* const yTrue = tf.tensor2d([[0, 1], [10, 20]]);
* const yPred = tf.tensor2d([[0, 1], [11, 24]]);
* const mse = tf.metrics.meanAbsolutePercentageError(yTrue, yPred);
* mse.print();
* ```
*
* Aliases: `tf.metrics.MAPE`, `tf.metrics.mape`.
*
* @param yTrue Truth Tensor.
* @param yPred Prediction Tensor.
* @return Mean absolute percentage error Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function meanAbsolutePercentageError(yTrue, yPred) {
return losses.meanAbsolutePercentageError(yTrue, yPred);
}
export function MAPE(yTrue, yPred) {
return losses.meanAbsolutePercentageError(yTrue, yPred);
}
export function mape(yTrue, yPred) {
return losses.meanAbsolutePercentageError(yTrue, yPred);
}
/**
* Loss or metric function: Mean squared error.
*
* ```js
* const yTrue = tf.tensor2d([[0, 1], [3, 4]]);
* const yPred = tf.tensor2d([[0, 1], [-3, -4]]);
* const mse = tf.metrics.meanSquaredError(yTrue, yPred);
* mse.print();
* ```
*
* Aliases: `tf.metrics.MSE`, `tf.metrics.mse`.
*
* @param yTrue Truth Tensor.
* @param yPred Prediction Tensor.
* @return Mean squared error Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function meanSquaredError(yTrue, yPred) {
return losses.meanSquaredError(yTrue, yPred);
}
export function MSE(yTrue, yPred) {
return losses.meanSquaredError(yTrue, yPred);
}
export function mse(yTrue, yPred) {
return losses.meanSquaredError(yTrue, yPred);
}
/**
* Computes R2 score.
*
* ```js
* const yTrue = tf.tensor2d([[0, 1], [3, 4]]);
* const yPred = tf.tensor2d([[0, 1], [-3, -4]]);
* const r2Score = tf.metrics.r2Score(yTrue, yPred);
* r2Score.print();
* ```
* @param yTrue Truth Tensor.
* @param yPred Prediction Tensor.
* @return R2 score Tensor.
*
* @doc {heading: 'Metrics', namespace: 'metrics'}
*/
export function r2Score(yTrue, yPred) {
return metrics.r2Score(yTrue, yPred);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwb3J0c19tZXRyaWNzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vdGZqcy1sYXllcnMvc3JjL2V4cG9ydHNfbWV0cmljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFXQSxPQUFPLEtBQUssTUFBTSxNQUFNLFVBQVUsQ0FBQztBQUNuQyxPQUFPLEtBQUssT0FBTyxNQUFNLFdBQVcsQ0FBQztBQUVyQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDekQsT0FBTyxPQUFPLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztBQUM5QyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDN0QsT0FBTyxPQUFPLENBQUMsa0JBQWtCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBQ0gsTUFBTSxVQUFVLHlCQUF5QixDQUNyQyxLQUFhLEVBQUUsS0FBYTtJQUM5QixPQUFPLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDekQsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUM5RCxPQUFPLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDbkQsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsdUJBQXVCLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDbEUsT0FBTyxPQUFPLENBQUMsdUJBQXVCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ3ZELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtDRztBQUNILE1BQU0sVUFBVSxTQUFTLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDcEQsT0FBTyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQ0c7QUFDSCxNQUFNLFVBQVUsTUFBTSxDQUFDLEtBQWEsRUFBRSxLQUFhO0lBQ2pELE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDdEMsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9CRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDMUQsT0FBTyxNQUFNLENBQUMsZUFBZSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztBQUM5QyxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDNUQsT0FBTyxNQUFNLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLFVBQVUsMkJBQTJCLENBQ3ZDLEtBQWEsRUFBRSxLQUFhO0lBQzlCLE9BQU8sTUFBTSxDQUFDLDJCQUEyQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBRUQsTUFBTSxVQUFVLElBQUksQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUMvQyxPQUFPLE1BQU0sQ0FBQywyQkFBMkIsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDMUQsQ0FBQztBQUVELE1BQU0sVUFBVSxJQUFJLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDL0MsT0FBTyxNQUFNLENBQUMsMkJBQTJCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsS0FBYSxFQUFFLEtBQWE7SUFDM0QsT0FBTyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRCxNQUFNLFVBQVUsR0FBRyxDQUFDLEtBQWEsRUFBRSxLQUFhO0lBQzlDLE9BQU8sTUFBTSxDQUFDLGdCQUFnQixDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztBQUMvQyxDQUFDO0FBRUQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUM5QyxPQUFPLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsTUFBTSxVQUFVLE9BQU8sQ0FBQyxLQUFhLEVBQUUsS0FBYTtJQUNsRCxPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ3ZDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOCBHb29nbGUgTExDXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlXG4gKiBsaWNlbnNlIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgb3IgYXRcbiAqIGh0dHBzOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvTUlULlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJ0B0ZW5zb3JmbG93L3RmanMtY29yZSc7XG5cbmltcG9ydCAqIGFzIGxvc3NlcyBmcm9tICcuL2xvc3Nlcyc7XG5pbXBvcnQgKiBhcyBtZXRyaWNzIGZyb20gJy4vbWV0cmljcyc7XG5cbi8qKlxuICogQmluYXJ5IGFjY3VyYWN5IG1ldHJpYyBmdW5jdGlvbi5cbiAqXG4gKiBgeVRydWVgIGFuZCBgeVByZWRgIGNhbiBoYXZlIDAtMSB2YWx1ZXMuIEV4YW1wbGU6XG4gKiBgYGBqc1xuICogY29uc3QgeCA9IHRmLnRlbnNvcjJkKFtbMSwgMSwgMSwgMV0sIFswLCAwLCAwLCAwXV0sIFsyLCA0XSk7XG4gKiBjb25zdCB5ID0gdGYudGVuc29yMmQoW1sxLCAwLCAxLCAwXSwgWzAsIDAsIDAsIDFdXSwgWzIsIDRdKTtcbiAqIGNvbnN0IGFjY3VyYWN5ID0gdGYubWV0cmljcy5iaW5hcnlBY2N1cmFjeSh4LCB5KTtcbiAqIGFjY3VyYWN5LnByaW50KCk7XG4gKiBgYGBcbiAqXG4gKiBgeVRydWVgIGFuZCBgeVByZWRgIGNhbiBhbHNvIGhhdmUgZmxvYXRpbmctbnVtYmVyIHZhbHVlcyBiZXR3ZWVuIDAgYW5kIDEsIGluXG4gKiB3aGljaCBjYXNlIHRoZSB2YWx1ZXMgd2lsbCBiZSB0aHJlc2hvbGRlZCBhdCAwLjUgdG8geWllbGQgMC0xIHZhbHVlcyAoaS5lLixcbiAqIGEgdmFsdWUgPj0gMC41IGFuZCA8PSAxLjAgaXMgaW50ZXJwcmV0ZWQgYXMgMSkuXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYGpzXG4gKiBjb25zdCB4ID0gdGYudGVuc29yMWQoWzEsIDEsIDEsIDEsIDAsIDAsIDAsIDBdKTtcbiAqIGNvbnN0IHkgPSB0Zi50ZW5zb3IxZChbMC4yLCAwLjQsIDAuNiwgMC44LCAwLjIsIDAuMywgMC40LCAwLjddKTtcbiAqIGNvbnN0IGFjY3VyYWN5ID0gdGYubWV0cmljcy5iaW5hcnlBY2N1cmFjeSh4LCB5KTtcbiAqIGFjY3VyYWN5LnByaW50KCk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0geVRydWUgQmluYXJ5IFRlbnNvciBvZiB0cnV0aC5cbiAqIEBwYXJhbSB5UHJlZCBCaW5hcnkgVGVuc29yIG9mIHByZWRpY3Rpb24uXG4gKiBAcmV0dXJuIEFjY3VyYWN5IFRlbnNvci5cbiAqXG4gKiBAZG9jIHtoZWFkaW5nOiAnTWV0cmljcycsIG5hbWVzcGFjZTogJ21ldHJpY3MnfVxuICovXG5leHBvcnQgZnVuY3Rpb24gYmluYXJ5QWNjdXJhY3koeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiBtZXRyaWNzLmJpbmFyeUFjY3VyYWN5KHlUcnVlLCB5UHJlZCk7XG59XG5cbi8qKlxuICogQmluYXJ5IGNyb3NzZW50cm9weSBtZXRyaWMgZnVuY3Rpb24uXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYGpzXG4gKiBjb25zdCB4ID0gdGYudGVuc29yMmQoW1swXSwgWzFdLCBbMV0sIFsxXV0pO1xuICogY29uc3QgeSA9IHRmLnRlbnNvcjJkKFtbMF0sIFswXSwgWzAuNV0sIFsxXV0pO1xuICogY29uc3QgY3Jvc3NlbnRyb3B5ID0gdGYubWV0cmljcy5iaW5hcnlDcm9zc2VudHJvcHkoeCwgeSk7XG4gKiBjcm9zc2VudHJvcHkucHJpbnQoKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB5VHJ1ZSBCaW5hcnkgVGVuc29yIG9mIHRydXRoLlxuICogQHBhcmFtIHlQcmVkIEJpbmFyeSBUZW5zb3Igb2YgcHJlZGljdGlvbiwgcHJvYmFiaWxpdGllcyBmb3IgdGhlIGAxYCBjYXNlLlxuICogQHJldHVybiBBY2N1cmFjeSBUZW5zb3IuXG4gKlxuICogQGRvYyB7aGVhZGluZzogJ01ldHJpY3MnLCBuYW1lc3BhY2U6ICdtZXRyaWNzJ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJpbmFyeUNyb3NzZW50cm9weSh5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIG1ldHJpY3MuYmluYXJ5Q3Jvc3NlbnRyb3B5KHlUcnVlLCB5UHJlZCk7XG59XG5cbi8qKlxuICogU3BhcnNlIGNhdGVnb3JpY2FsIGFjY3VyYWN5IG1ldHJpYyBmdW5jdGlvbi5cbiAqXG4gKiBFeGFtcGxlOlxuICogYGBganNcbiAqXG4gKiBjb25zdCB5VHJ1ZSA9IHRmLnRlbnNvcjFkKFsxLCAxLCAyLCAyLCAwXSk7XG4gKiBjb25zdCB5UHJlZCA9IHRmLnRlbnNvcjJkKFxuICogICAgICBbWzAsIDEsIDBdLCBbMSwgMCwgMF0sIFswLCAwLjQsIDAuNl0sIFswLCAwLjYsIDAuNF0sIFswLjcsIDAuMywgMF1dKTtcbiAqIGNvbnN0IGNyb3NzZW50cm9weSA9IHRmLm1ldHJpY3Muc3BhcnNlQ2F0ZWdvcmljYWxBY2N1cmFjeSh5VHJ1ZSwgeVByZWQpO1xuICogY3Jvc3NlbnRyb3B5LnByaW50KCk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0geVRydWUgVHJ1ZSBsYWJlbHM6IGluZGljZXMuXG4gKiBAcGFyYW0geVByZWQgUHJlZGljdGVkIHByb2JhYmlsaXRpZXMgb3IgbG9naXRzLlxuICogQHJldHVybnMgQWNjdXJhY3kgdGVuc29yLlxuICpcbiAqIEBkb2Mge2hlYWRpbmc6ICdNZXRyaWNzJywgbmFtZXNwYWNlOiAnbWV0cmljcyd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGFyc2VDYXRlZ29yaWNhbEFjY3VyYWN5KFxuICAgIHlUcnVlOiBUZW5zb3IsIHlQcmVkOiBUZW5zb3IpOiBUZW5zb3Ige1xuICByZXR1cm4gbWV0cmljcy5zcGFyc2VDYXRlZ29yaWNhbEFjY3VyYWN5KHlUcnVlLCB5UHJlZCk7XG59XG5cbi8qKlxuICogQ2F0ZWdvcmljYWwgYWNjdXJhY3kgbWV0cmljIGZ1bmN0aW9uLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGBqc1xuICogY29uc3QgeCA9IHRmLnRlbnNvcjJkKFtbMCwgMCwgMCwgMV0sIFswLCAwLCAwLCAxXV0pO1xuICogY29uc3QgeSA9IHRmLnRlbnNvcjJkKFtbMC4xLCAwLjgsIDAuMDUsIDAuMDVdLCBbMC4xLCAwLjA1LCAwLjA1LCAwLjhdXSk7XG4gKiBjb25zdCBhY2N1cmFjeSA9IHRmLm1ldHJpY3MuY2F0ZWdvcmljYWxBY2N1cmFjeSh4LCB5KTtcbiAqIGFjY3VyYWN5LnByaW50KCk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0geVRydWUgQmluYXJ5IFRlbnNvciBvZiB0cnV0aDogb25lLWhvdCBlbmNvZGluZyBvZiBjYXRlZ29yaWVzLlxuICogQHBhcmFtIHlQcmVkIEJpbmFyeSBUZW5zb3Igb2YgcHJlZGljdGlvbjogcHJvYmFiaWxpdGllcyBvciBsb2dpdHMgZm9yIHRoZVxuICogICBzYW1lIGNhdGVnb3JpZXMgYXMgaW4gYHlUcnVlYC5cbiAqIEByZXR1cm4gQWNjdXJhY3kgVGVuc29yLlxuICpcbiAqIEBkb2Mge2hlYWRpbmc6ICdNZXRyaWNzJywgbmFtZXNwYWNlOiAnbWV0cmljcyd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYXRlZ29yaWNhbEFjY3VyYWN5KHlUcnVlOiBUZW5zb3IsIHlQcmVkOiBUZW5zb3IpOiBUZW5zb3Ige1xuICByZXR1cm4gbWV0cmljcy5jYXRlZ29yaWNhbEFjY3VyYWN5KHlUcnVlLCB5UHJlZCk7XG59XG5cbi8qKlxuICogQ2F0ZWdvcmljYWwgY3Jvc3NlbnRyb3B5IGJldHdlZW4gYW4gb3V0cHV0IHRlbnNvciBhbmQgYSB0YXJnZXQgdGVuc29yLlxuICpcbiAqIEBwYXJhbSB0YXJnZXQgQSB0ZW5zb3Igb2YgdGhlIHNhbWUgc2hhcGUgYXMgYG91dHB1dGAuXG4gKiBAcGFyYW0gb3V0cHV0IEEgdGVuc29yIHJlc3VsdGluZyBmcm9tIGEgc29mdG1heCAodW5sZXNzIGBmcm9tTG9naXRzYCBpc1xuICogIGB0cnVlYCwgaW4gd2hpY2ggY2FzZSBgb3V0cHV0YCBpcyBleHBlY3RlZCB0byBiZSB0aGUgbG9naXRzKS5cbiAqIEBwYXJhbSBmcm9tTG9naXRzIEJvb2xlYW4sIHdoZXRoZXIgYG91dHB1dGAgaXMgdGhlIHJlc3VsdCBvZiBhIHNvZnRtYXgsIG9yIGlzXG4gKiAgIGEgdGVuc29yIG9mIGxvZ2l0cy5cbiAqXG4gKiBAZG9jIHtoZWFkaW5nOiAnTWV0cmljcycsIG5hbWVzcGFjZTogJ21ldHJpY3MnfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY2F0ZWdvcmljYWxDcm9zc2VudHJvcHkoeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiBtZXRyaWNzLmNhdGVnb3JpY2FsQ3Jvc3NlbnRyb3B5KHlUcnVlLCB5UHJlZCk7XG59XG5cbi8qKlxuICogQ29tcHV0ZXMgdGhlIHByZWNpc2lvbiBvZiB0aGUgcHJlZGljdGlvbnMgd2l0aCByZXNwZWN0IHRvIHRoZSBsYWJlbHMuXG4gKlxuICogRXhhbXBsZTpcbiAqIGBgYGpzXG4gKiBjb25zdCB4ID0gdGYudGVuc29yMmQoXG4gKiAgICBbXG4gKiAgICAgIFswLCAwLCAwLCAxXSxcbiAqICAgICAgWzAsIDEsIDAsIDBdLFxuICogICAgICBbMCwgMCwgMCwgMV0sXG4gKiAgICAgIFsxLCAwLCAwLCAwXSxcbiAqICAgICAgWzAsIDAsIDEsIDBdXG4gKiAgICBdXG4gKiApO1xuICpcbiAqIGNvbnN0IHkgPSB0Zi50ZW5zb3IyZChcbiAqICAgIFtcbiAqICAgICAgWzAsIDAsIDEsIDBdLFxuICogICAgICBbMCwgMSwgMCwgMF0sXG4gKiAgICAgIFswLCAwLCAwLCAxXSxcbiAqICAgICAgWzAsIDEsIDAsIDBdLFxuICogICAgICBbMCwgMSwgMCwgMF1cbiAqICAgIF1cbiAqICk7XG4gKlxuICogY29uc3QgcHJlY2lzaW9uID0gdGYubWV0cmljcy5wcmVjaXNpb24oeCwgeSk7XG4gKiBwcmVjaXNpb24ucHJpbnQoKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB5VHJ1ZSBUaGUgZ3JvdW5kIHRydXRoIHZhbHVlcy4gRXhwZWN0ZWQgdG8gY29udGFpbiBvbmx5IDAtMSB2YWx1ZXMuXG4gKiBAcGFyYW0geVByZWQgVGhlIHByZWRpY3RlZCB2YWx1ZXMuIEV4cGVjdGVkIHRvIGNvbnRhaW4gb25seSAwLTEgdmFsdWVzLlxuICogQHJldHVybiBQcmVjaXNpb24gVGVuc29yLlxuICpcbiAqIEBkb2Mge2hlYWRpbmc6ICdNZXRyaWNzJywgbmFtZXNwYWNlOiAnbWV0cmljcyd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcmVjaXNpb24oeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiBtZXRyaWNzLnByZWNpc2lvbih5VHJ1ZSwgeVByZWQpO1xufVxuXG4vKipcbiAqIENvbXB1dGVzIHRoZSByZWNhbGwgb2YgdGhlIHByZWRpY3Rpb25zIHdpdGggcmVzcGVjdCB0byB0aGUgbGFiZWxzLlxuICpcbiAqIEV4YW1wbGU6XG4gKiBgYGBqc1xuICogY29uc3QgeCA9IHRmLnRlbnNvcjJkKFxuICogICAgW1xuICogICAgICBbMCwgMCwgMCwgMV0sXG4gKiAgICAgIFswLCAxLCAwLCAwXSxcbiAqICAgICAgWzAsIDAsIDAsIDFdLFxuICogICAgICBbMSwgMCwgMCwgMF0sXG4gKiAgICAgIFswLCAwLCAxLCAwXVxuICogICAgXVxuICogKTtcbiAqXG4gKiBjb25zdCB5ID0gdGYudGVuc29yMmQoXG4gKiAgICBbXG4gKiAgICAgIFswLCAwLCAxLCAwXSxcbiAqICAgICAgWzAsIDEsIDAsIDBdLFxuICogICAgICBbMCwgMCwgMCwgMV0sXG4gKiAgICAgIFswLCAxLCAwLCAwXSxcbiAqICAgICAgWzAsIDEsIDAsIDBdXG4gKiAgICBdXG4gKiApO1xuICpcbiAqIGNvbnN0IHJlY2FsbCA9IHRmLm1ldHJpY3MucmVjYWxsKHgsIHkpO1xuICogcmVjYWxsLnByaW50KCk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0geVRydWUgVGhlIGdyb3VuZCB0cnV0aCB2YWx1ZXMuIEV4cGVjdGVkIHRvIGNvbnRhaW4gb25seSAwLTEgdmFsdWVzLlxuICogQHBhcmFtIHlQcmVkIFRoZSBwcmVkaWN0ZWQgdmFsdWVzLiBFeHBlY3RlZCB0byBjb250YWluIG9ubHkgMC0xIHZhbHVlcy5cbiAqIEByZXR1cm4gUmVjYWxsIFRlbnNvci5cbiAqXG4gKiBAZG9jIHtoZWFkaW5nOiAnTWV0cmljcycsIG5hbWVzcGFjZTogJ21ldHJpY3MnfVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVjYWxsKHlUcnVlOiBUZW5zb3IsIHlQcmVkOiBUZW5zb3IpOiBUZW5zb3Ige1xuICByZXR1cm4gbWV0cmljcy5yZWNhbGwoeVRydWUsIHlQcmVkKTtcbn1cblxuLyoqXG4gKiBMb3NzIG9yIG1ldHJpYyBmdW5jdGlvbjogQ29zaW5lIHByb3hpbWl0eS5cbiAqXG4gKiBNYXRoZW1hdGljYWxseSwgY29zaW5lIHByb3hpbWl0eSBpcyBkZWZpbmVkIGFzOlxuICogICBgLXN1bShsMk5vcm1hbGl6ZSh5VHJ1ZSkgKiBsMk5vcm1hbGl6ZSh5UHJlZCkpYCxcbiAqIHdoZXJlaW4gYGwyTm9ybWFsaXplKClgIG5vcm1hbGl6ZXMgdGhlIEwyIG5vcm0gb2YgdGhlIGlucHV0IHRvIDEgYW5kIGAqYFxuICogcmVwcmVzZW50cyBlbGVtZW50LXdpc2UgbXVsdGlwbGljYXRpb24uXG4gKlxuICogYGBganNcbiAqIGNvbnN0IHlUcnVlID0gdGYudGVuc29yMmQoW1sxLCAwXSwgWzEsIDBdXSk7XG4gKiBjb25zdCB5UHJlZCA9IHRmLnRlbnNvcjJkKFtbMSAvIE1hdGguc3FydCgyKSwgMSAvIE1hdGguc3FydCgyKV0sIFswLCAxXV0pO1xuICogY29uc3QgcHJveGltaXR5ID0gdGYubWV0cmljcy5jb3NpbmVQcm94aW1pdHkoeVRydWUsIHlQcmVkKTtcbiAqIHByb3hpbWl0eS5wcmludCgpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIHlUcnVlIFRydXRoIFRlbnNvci5cbiAqIEBwYXJhbSB5UHJlZCBQcmVkaWN0aW9uIFRlbnNvci5cbiAqIEByZXR1cm4gQ29zaW5lIHByb3hpbWl0eSBUZW5zb3IuXG4gKlxuICogQGRvYyB7aGVhZGluZzogJ01ldHJpY3MnLCBuYW1lc3BhY2U6ICdtZXRyaWNzJ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvc2luZVByb3hpbWl0eSh5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIGxvc3Nlcy5jb3NpbmVQcm94aW1pdHkoeVRydWUsIHlQcmVkKTtcbn1cblxuLyoqXG4gKiBMb3NzIG9yIG1ldHJpYyBmdW5jdGlvbjogTWVhbiBhYnNvbHV0ZSBlcnJvci5cbiAqXG4gKiBNYXRoZW1hdGljYWxseSwgbWVhbiBhYnNvbHV0ZSBlcnJvciBpcyBkZWZpbmVkIGFzOlxuICogICBgbWVhbihhYnMoeVByZWQgLSB5VHJ1ZSkpYCxcbiAqIHdoZXJlaW4gdGhlIGBtZWFuYCBpcyBhcHBsaWVkIG92ZXIgZmVhdHVyZSBkaW1lbnNpb25zLlxuICpcbiAqIGBgYGpzXG4gKiBjb25zdCB5VHJ1ZSA9IHRmLnRlbnNvcjJkKFtbMCwgMV0sIFswLCAwXSwgWzIsIDNdXSk7XG4gKiBjb25zdCB5UHJlZCA9IHRmLnRlbnNvcjJkKFtbMCwgMV0sIFswLCAxXSwgWy0yLCAtM11dKTtcbiAqIGNvbnN0IG1zZSA9IHRmLm1ldHJpY3MubWVhbkFic29sdXRlRXJyb3IoeVRydWUsIHlQcmVkKTtcbiAqIG1zZS5wcmludCgpO1xuICogYGBgXG4gKlxuICogQHBhcmFtIHlUcnVlIFRydXRoIFRlbnNvci5cbiAqIEBwYXJhbSB5UHJlZCBQcmVkaWN0aW9uIFRlbnNvci5cbiAqIEByZXR1cm4gTWVhbiBhYnNvbHV0ZSBlcnJvciBUZW5zb3IuXG4gKlxuICogQGRvYyB7aGVhZGluZzogJ01ldHJpY3MnLCBuYW1lc3BhY2U6ICdtZXRyaWNzJ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lYW5BYnNvbHV0ZUVycm9yKHlUcnVlOiBUZW5zb3IsIHlQcmVkOiBUZW5zb3IpOiBUZW5zb3Ige1xuICByZXR1cm4gbG9zc2VzLm1lYW5BYnNvbHV0ZUVycm9yKHlUcnVlLCB5UHJlZCk7XG59XG5cbi8qKlxuICogTG9zcyBvciBtZXRyaWMgZnVuY3Rpb246IE1lYW4gYWJzb2x1dGUgcGVyY2VudGFnZSBlcnJvci5cbiAqXG4gKiBgYGBqc1xuICogY29uc3QgeVRydWUgPSB0Zi50ZW5zb3IyZChbWzAsIDFdLCBbMTAsIDIwXV0pO1xuICogY29uc3QgeVByZWQgPSB0Zi50ZW5zb3IyZChbWzAsIDFdLCBbMTEsIDI0XV0pO1xuICogY29uc3QgbXNlID0gdGYubWV0cmljcy5tZWFuQWJzb2x1dGVQZXJjZW50YWdlRXJyb3IoeVRydWUsIHlQcmVkKTtcbiAqIG1zZS5wcmludCgpO1xuICogYGBgXG4gKlxuICogQWxpYXNlczogYHRmLm1ldHJpY3MuTUFQRWAsIGB0Zi5tZXRyaWNzLm1hcGVgLlxuICpcbiAqIEBwYXJhbSB5VHJ1ZSBUcnV0aCBUZW5zb3IuXG4gKiBAcGFyYW0geVByZWQgUHJlZGljdGlvbiBUZW5zb3IuXG4gKiBAcmV0dXJuIE1lYW4gYWJzb2x1dGUgcGVyY2VudGFnZSBlcnJvciBUZW5zb3IuXG4gKlxuICogQGRvYyB7aGVhZGluZzogJ01ldHJpY3MnLCBuYW1lc3BhY2U6ICdtZXRyaWNzJ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lYW5BYnNvbHV0ZVBlcmNlbnRhZ2VFcnJvcihcbiAgICB5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIGxvc3Nlcy5tZWFuQWJzb2x1dGVQZXJjZW50YWdlRXJyb3IoeVRydWUsIHlQcmVkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIE1BUEUoeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiBsb3NzZXMubWVhbkFic29sdXRlUGVyY2VudGFnZUVycm9yKHlUcnVlLCB5UHJlZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXBlKHlUcnVlOiBUZW5zb3IsIHlQcmVkOiBUZW5zb3IpOiBUZW5zb3Ige1xuICByZXR1cm4gbG9zc2VzLm1lYW5BYnNvbHV0ZVBlcmNlbnRhZ2VFcnJvcih5VHJ1ZSwgeVByZWQpO1xufVxuXG4vKipcbiAqIExvc3Mgb3IgbWV0cmljIGZ1bmN0aW9uOiBNZWFuIHNxdWFyZWQgZXJyb3IuXG4gKlxuICogYGBganNcbiAqIGNvbnN0IHlUcnVlID0gdGYudGVuc29yMmQoW1swLCAxXSwgWzMsIDRdXSk7XG4gKiBjb25zdCB5UHJlZCA9IHRmLnRlbnNvcjJkKFtbMCwgMV0sIFstMywgLTRdXSk7XG4gKiBjb25zdCBtc2UgPSB0Zi5tZXRyaWNzLm1lYW5TcXVhcmVkRXJyb3IoeVRydWUsIHlQcmVkKTtcbiAqIG1zZS5wcmludCgpO1xuICogYGBgXG4gKlxuICogQWxpYXNlczogYHRmLm1ldHJpY3MuTVNFYCwgYHRmLm1ldHJpY3MubXNlYC5cbiAqXG4gKiBAcGFyYW0geVRydWUgVHJ1dGggVGVuc29yLlxuICogQHBhcmFtIHlQcmVkIFByZWRpY3Rpb24gVGVuc29yLlxuICogQHJldHVybiBNZWFuIHNxdWFyZWQgZXJyb3IgVGVuc29yLlxuICpcbiAqIEBkb2Mge2hlYWRpbmc6ICdNZXRyaWNzJywgbmFtZXNwYWNlOiAnbWV0cmljcyd9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZWFuU3F1YXJlZEVycm9yKHlUcnVlOiBUZW5zb3IsIHlQcmVkOiBUZW5zb3IpOiBUZW5zb3Ige1xuICByZXR1cm4gbG9zc2VzLm1lYW5TcXVhcmVkRXJyb3IoeVRydWUsIHlQcmVkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIE1TRSh5VHJ1ZTogVGVuc29yLCB5UHJlZDogVGVuc29yKTogVGVuc29yIHtcbiAgcmV0dXJuIGxvc3Nlcy5tZWFuU3F1YXJlZEVycm9yKHlUcnVlLCB5UHJlZCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtc2UoeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiBsb3NzZXMubWVhblNxdWFyZWRFcnJvcih5VHJ1ZSwgeVByZWQpO1xufVxuXG4vKipcbiAqIENvbXB1dGVzIFIyIHNjb3JlLlxuICpcbiAqIGBgYGpzXG4gKiBjb25zdCB5VHJ1ZSA9IHRmLnRlbnNvcjJkKFtbMCwgMV0sIFszLCA0XV0pO1xuICogY29uc3QgeVByZWQgPSB0Zi50ZW5zb3IyZChbWzAsIDFdLCBbLTMsIC00XV0pO1xuICogY29uc3QgcjJTY29yZSA9IHRmLm1ldHJpY3MucjJTY29yZSh5VHJ1ZSwgeVByZWQpO1xuICogcjJTY29yZS5wcmludCgpO1xuICogYGBgXG4gKiBAcGFyYW0geVRydWUgVHJ1dGggVGVuc29yLlxuICogQHBhcmFtIHlQcmVkIFByZWRpY3Rpb24gVGVuc29yLlxuICogQHJldHVybiBSMiBzY29yZSBUZW5zb3IuXG4gKlxuICogQGRvYyB7aGVhZGluZzogJ01ldHJpY3MnLCBuYW1lc3BhY2U6ICdtZXRyaWNzJ31cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHIyU2NvcmUoeVRydWU6IFRlbnNvciwgeVByZWQ6IFRlbnNvcik6IFRlbnNvciB7XG4gIHJldHVybiBtZXRyaWNzLnIyU2NvcmUoeVRydWUsIHlQcmVkKTtcbn1cbiJdfQ==