UNPKG

@tensorflow/tfjs-core

Version:

Hardware-accelerated JavaScript library for machine intelligence

133 lines 5 kB
/** * @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 { ENGINE } from './engine'; import { inferShape } from './tensor_util_env'; import { arraysEqual, encodeString, flatten, isString, isTypedArray } from './util'; const TEST_EPSILON_FLOAT32 = 1e-3; export const TEST_EPSILON_FLOAT16 = 1e-1; export function expectArraysClose(actual, expected, epsilon) { if (epsilon == null) { epsilon = testEpsilon(); } return expectArraysPredicate(actual, expected, (a, b) => areClose(a, b, epsilon)); } export function testEpsilon() { return ENGINE.backend.floatPrecision() === 32 ? TEST_EPSILON_FLOAT32 : TEST_EPSILON_FLOAT16; } function expectArraysPredicate(actual, expected, predicate) { let checkClassType = true; if (isTypedArray(actual) || isTypedArray(expected)) { checkClassType = false; } if (isTypedArray(actual) && isTypedArray(expected)) { checkClassType = true; } if (checkClassType) { const aType = actual.constructor.name; const bType = expected.constructor.name; if (aType !== bType) { throw new Error(`Arrays are of different type. Actual: ${aType}. ` + `Expected: ${bType}`); } } if (Array.isArray(actual) && Array.isArray(expected)) { const actualShape = inferShape(actual); const expectedShape = inferShape(expected); if (!arraysEqual(actualShape, expectedShape)) { throw new Error(`Arrays have different shapes. ` + `Actual: [${actualShape}]. Expected: [${expectedShape}]`); } } const actualFlat = isTypedArray(actual) ? actual : flatten(actual); const expectedFlat = isTypedArray(expected) ? expected : flatten(expected); if (actualFlat.length !== expectedFlat.length) { throw new Error(`Arrays have different lengths actual: ${actualFlat.length} vs ` + `expected: ${expectedFlat.length}.\n` + `Actual: ${actualFlat}.\n` + `Expected: ${expectedFlat}.`); } for (let i = 0; i < expectedFlat.length; ++i) { const a = actualFlat[i]; const e = expectedFlat[i]; if (!predicate(a, e)) { throw new Error(`Arrays differ: actual[${i}] = ${a}, expected[${i}] = ${e}.\n` + `Actual: ${actualFlat}.\n` + `Expected: ${expectedFlat}.`); } } } export function expectPromiseToFail(fn, done) { fn().then(() => done.fail(), () => done()); } export function expectArraysEqual(actual, expected) { const exp = typeof expected === 'string' || typeof expected === 'number' || typeof expected === 'boolean' ? [expected] : expected; if (isString(actual) || isString(actual[0]) || isString(expected) || isString(expected[0])) { // tslint:disable-next-line: triple-equals return expectArraysPredicate(actual, exp, (a, b) => a == b); } return expectArraysPredicate(actual, expected, (a, b) => areClose(a, b, 0)); } export function expectNumbersClose(a, e, epsilon) { if (epsilon == null) { epsilon = testEpsilon(); } if (!areClose(a, e, epsilon)) { throw new Error(`Numbers differ: actual === ${a}, expected === ${e}`); } } function areClose(a, e, epsilon) { if (!isFinite(a) && !isFinite(e)) { return true; } if (isNaN(a) || isNaN(e) || Math.abs(a - e) > epsilon) { return false; } return true; } export function expectValuesInRange(actual, low, high) { for (let i = 0; i < actual.length; i++) { if (actual[i] < low || actual[i] > high) { throw new Error(`Value out of range:${actual[i]} low: ${low}, high: ${high}`); } } } export function expectArrayBuffersEqual(actual, expected) { // Safari & Jasmine don't like comparing ArrayBuffers directly. Wrapping in // a Float32Array solves this issue. expect(new Float32Array(actual)).toEqual(new Float32Array(expected)); } /** Encodes strings into utf-8 bytes. */ export function encodeStrings(a) { for (let i = 0; i < a.length; i++) { const val = a[i]; if (Array.isArray(val)) { encodeStrings(val); } else { a[i] = encodeString(val); } } return a; } //# sourceMappingURL=test_util.js.map