diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs')
4 files changed, 1604 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deMath.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deMath.js new file mode 100644 index 0000000000..fbb2a61fd7 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deMath.js @@ -0,0 +1,1143 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program OpenGL ES Utilities + * ------------------------------------------------ + * + * Copyright 2014 The Android Open Source Project + * + * 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. + * + */ + +'use strict'; +goog.provide('framework.delibs.debase.deMath'); + +/** @typedef { (Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array) } */ +goog.TypedArray; + +/** @typedef { (Array<number>|Array<boolean>|goog.TypedArray) } */ +goog.NumberArray; + +goog.scope(function() { + +var deMath = framework.delibs.debase.deMath; + +var DE_ASSERT = function(x) { + if (!x) + throw new Error('Assert failed'); +}; + +/** @const */ deMath.INT32_SIZE = 4; + +deMath.deInRange32 = function(a, mn, mx) { + return (a >= mn) && (a <= mx); +}; + +deMath.deInBounds32 = function(a, mn, mx) { + return (a >= mn) && (a < mx); +}; + +/** + * @param {number} a + * @return {number} + */ +deMath.deFloatFrac = function(a) { return a - Math.floor(a); }; + +/** + * Transform a 64-bit float number into a 32-bit float number. + * Native dEQP uses 32-bit numbers, so sometimes 64-bit floating numbers in JS should be transformed into 32-bit ones to ensure the correctness of the result. + * @param {number} a + * @return {number} + */ +deMath.toFloat32 = (function() { + var FLOAT32ARRAY1 = new Float32Array(1); + return function(a) { + FLOAT32ARRAY1[0] = a; + return FLOAT32ARRAY1[0]; + }; +})(); + +/** @const */ deMath.INV_LOG_2_FLOAT32 = deMath.toFloat32(1.44269504089); /** 1.0 / log_e(2.0) */ + +/** + * Check if a value is a power-of-two. + * @param {number} a Input value. + * @return {boolean} return True if input is a power-of-two value, false otherwise. + * (Also returns true for zero). + */ +deMath.deIsPowerOfTwo32 = function(a) { + return ((a & (a - 1)) == 0); +}; + +/** + * Align an integer to given power-of-two size. + * @param {number} val The number to align. + * @param {number} align The size to align to. + * @return {number} The aligned value + */ +deMath.deAlign32 = function(val, align) { + if (!deMath.deIsPowerOfTwo32(align)) + throw new Error('Not a power of 2: ' + align); + return ((val + align - 1) & ~(align - 1)) & 0xFFFFFFFF; //0xFFFFFFFF make sure it returns a 32 bit calculation in 64 bit browsers. +}; + +/** + * Compute the bit population count of an integer. + * @param {number} a + * @return {number} The number of one bits in + */ +deMath.dePop32 = function(a) { + /** @type {number} */ var mask0 = 0x55555555; /* 1-bit values. */ + /** @type {number} */ var mask1 = 0x33333333; /* 2-bit values. */ + /** @type {number} */ var mask2 = 0x0f0f0f0f; /* 4-bit values. */ + /** @type {number} */ var mask3 = 0x00ff00ff; /* 8-bit values. */ + /** @type {number} */ var mask4 = 0x0000ffff; /* 16-bit values. */ + /** @type {number} */ var t = a & 0xFFFFFFFF; /* Crop to 32-bit value */ + t = (t & mask0) + ((t >> 1) & mask0); + t = (t & mask1) + ((t >> 2) & mask1); + t = (t & mask2) + ((t >> 4) & mask2); + t = (t & mask3) + ((t >> 8) & mask3); + t = (t & mask4) + (t >> 16); + return t; +}; + +deMath.clamp = function(val, minParm, maxParm) { + return Math.min(Math.max(val, minParm), maxParm); +}; + +/** + * @param {Array<number>} values + * @param {number} minParm + * @param {number} maxParm + * @return {Array<number>} + */ +deMath.clampVector = function(values, minParm, maxParm) { + var result = []; + for (var i = 0; i < values.length; i++) + result.push(deMath.clamp(values[i], minParm, maxParm)); + return result; +}; + +deMath.imod = function(a, b) { + var m = a % b; + return m < 0 ? m + b : m; +}; + +deMath.mirror = function(a) { + return a >= 0 ? a : -(1 + a); +}; + +/** + * @param {goog.NumberArray} a Source array + * @param {goog.NumberArray} indices + * @return {Array<number>} Swizzled array + */ +deMath.swizzle = function(a, indices) { + if (!indices.length) + throw new Error('Argument must be an array'); + var dst = []; + for (var i = 0; i < indices.length; i++) + dst.push(a[indices[i]]); + return dst; +}; + +/** + * Shift left elements of array a by elements of array b + * dst[n] a[n] << b[n] + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} Result array + */ +deMath.arrayShiftLeft = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] << b[i]); + return dst; +}; + +/** + * Multiply two vectors, element by element + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} Result array + */ + +deMath.multiply = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] * b[i]); + return dst; +}; + +/** + * Divide two vectors, element by element + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} Result array + * @throws {Error} + */ + +deMath.divide = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) { + if (b[i] === 0) + throw new Error('Division by 0'); + dst.push(a[i] / b[i]); + } + return dst; +}; + +/** + * Divide vector by a scalar + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} Result array + */ +deMath.divideScale = function(a, b) { + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] / b); + return dst; +}; + +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +deMath.mod = function(a, b) { + return a - b * Math.floor(a / b); +}; + +/** + * Modulus vector by a scalar + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} Result array + */ +deMath.modScale = function(a, b) { + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(deMath.mod(a[i], b)); + return dst; +}; + +/** + * Multiply vector by a scalar + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} Result array + */ +deMath.scale = function(a, b) { + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] * b); + return dst; +}; + +/** + * Add vector and scalar, element by element + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} Result array + */ +deMath.addScalar = function(a, b) { + if (!Array.isArray(a)) + throw new Error('First argument must be an array.'); + if (typeof b !== 'number') + throw new Error('Second argument must be a number.'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] + b); + return dst; +}; + +/** + * Add two vectors, element by element + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} Result array + */ +deMath.add = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] + b[i]); + return dst; +}; + +/** + * Subtract two vectors, element by element + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} Result array + */ + +deMath.subtract = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] - b[i]); + return dst; +}; + +/** + * Subtract vector and scalar, element by element + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} Result array + */ +deMath.subScalar = function(a, b) { + if (!Array.isArray(a)) + throw new Error('First argument must be an array.'); + if (typeof b !== 'number') + throw new Error('Second argument must be a number.'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] - b); + return dst; +}; + +/** + * Calculate absolute difference between two vectors + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} abs(diff(a - b)) + */ +deMath.absDiff = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(Math.abs(a[i] - b[i])); + return dst; +}; + +/** + * Calculate absolute value of a vector + * @param {goog.NumberArray} a + * @return {Array<number>} abs(a) + */ +deMath.abs = function(a) { + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(Math.abs(a[i])); + return dst; +}; + +/** + * Is a <= b (element by element)? + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<boolean>} Result array of booleans + */ +deMath.lessThanEqual = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i] <= b[i]); + return dst; +}; + +/** + * Is a === b (element by element)? + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {boolean} Result + */ +deMath.equal = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + for (var i = 0; i < a.length; i++) { + if (a[i] !== b[i]) + return false; + } + return true; +}; + +/** + * Are all values in the array true? + * @param {Array<boolean>} a + * @return {boolean} + */ +deMath.boolAll = function(a) { + for (var i = 0; i < a.length; i++) + if (a[i] == false) + return false; + return true; +}; + +/** + * deMath.assign(a, b) element by element + * @param {goog.NumberArray} a + * @return {Array<number>} + */ +deMath.assign = function(a) { + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(a[i]); + return dst; +}; + +/** + * deMath.max(a, b) element by element + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} + */ +deMath.max = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(Math.max(a[i], b[i])); + return dst; +}; + +/** + * deMath.min(a, b) element by element + * @param {goog.NumberArray} a + * @param {goog.NumberArray} b + * @return {Array<number>} + */ +deMath.min = function(a, b) { + if (a.length != b.length) + throw new Error('Arrays must have the same size'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(Math.min(a[i], b[i])); + return dst; +}; + +// Nearest-even rounding in case of tie (fractional part 0.5), otherwise ordinary rounding. +deMath.rint = function(a) { + var floorVal = Math.floor(a); + var fracVal = a - floorVal; + + if (fracVal != 0.5) + return Math.round(a); // Ordinary case. + + var roundUp = (floorVal % 2) != 0; + + return floorVal + (roundUp ? 1 : 0); +}; + +/** + * wrap the number, so that it fits in the range [minValue, maxValue] + * @param {number} v + * @param {number} minValue + * @param {number} maxValue + * @return {number} + */ +deMath.wrap = function(v, minValue, maxValue) { + var range = maxValue - minValue + 1; + + if (v < minValue) { + v += range * (Math.floor((minValue - v) / range) + 1); + } + return minValue + Math.floor((v - minValue) % range); +}; + +/** + * Round number to int by dropping fractional part + * it is equivalent of GLSL int() constructor + * @param {number} a + * @return {number} + */ +deMath.intCast = function(a) { + var v; + if (a >= 0) + v = Math.floor(a); + else + v = Math.ceil(a); + return deMath.wrap(v, -0x80000000, 0x7FFFFFFF); +}; + +/** + * Round number to uint by dropping fractional part + * it is equivalent of GLSL uint() constructor + * @param {number} a + * @return {number} + */ +deMath.uintCast = function(a) { + var v; + if (a >= 0) + v = Math.floor(a); + else + v = Math.ceil(a); + return deMath.wrap(v, 0, 0xFFFFFFFF); +}; + +/** + * @param {number} a + * @return {number} + */ +deMath.logToFloor = function(a) { + assertMsgOptions(a > 0, 'Value is less or equal than zero', false, true); + return 31 - deMath.clz32(a); +}; + +/** + * Find intersection of two rectangles + * @param {goog.NumberArray} a Array [x, y, width, height] + * @param {goog.NumberArray} b Array [x, y, width, height] + * @return {Array<number>} + */ +deMath.intersect = function(a, b) { + if (a.length != 4) + throw new Error('Array "a" must have length 4 but has length: ' + a.length); + if (b.length != 4) + throw new Error('Array "b" must have length 4 but has length: ' + b.length); + var x0 = Math.max(a[0], b[0]); + var y0 = Math.max(a[1], b[1]); + var x1 = Math.min(a[0] + a[2], b[0] + b[2]); + var y1 = Math.min(a[1] + a[3], b[1] + b[3]); + var w = Math.max(0, x1 - x0); + var h = Math.max(0, y1 - y0); + + return [x0, y0, w, h]; +}; + +/** deMath.deMathHash + * @param {number} a + * @return {number} + */ +deMath.deMathHash = function(a) { + var key = a; + key = (key ^ 61) ^ (key >> 16); + key = key + (key << 3); + key = key ^ (key >> 4); + key = key * 0x27d4eb2d; /* prime/odd constant */ + key = key ^ (key >> 15); + return key; +}; + +/** + * Converts a byte array to a number. Cannot convert numbers larger than 52 bits. + * @param {Uint8Array} array + * @return {number} + */ +deMath.arrayToNumber = function(array) { + DE_ASSERT(array.length <= 6 || (array.length == 6 && array[5] <= 127)); + /** @type {number} */ var result = 0; + + for (var ndx = 0; ndx < array.length; ndx++) { + result += array[ndx] * Math.pow(256, ndx); + } + + return result; +}; + +/** + * Fills a byte array with a number + * @param {Uint8Array} array Output array (already resized) + * @param {number} number + */ +deMath.numberToArray = function(array, number) { + DE_ASSERT(Number.isInteger(number)); + for (var byteNdx = 0; byteNdx < array.length; byteNdx++) { + /** @type {number} */ var acumzndx = !byteNdx ? number : Math.floor(number / Math.pow(256, byteNdx)); + array[byteNdx] = acumzndx & 0xFF; + } +}; + +/** + * Obtains the bit fragment from a number + * @param {number} x + * @param {number} firstNdx + * @param {number} lastNdx + * @return {number} + */ +deMath.getBitRange = function(x, firstNdx, lastNdx) { + DE_ASSERT(lastNdx - firstNdx <= 52); + var shifted = deMath.shiftRight(x, firstNdx); + var bitSize = lastNdx - firstNdx; + var mask; + if (bitSize < 32) + mask = (1 << bitSize) - 1; + else + mask = Math.pow(2, bitSize) - 1; + var masked = deMath.binaryAnd(shifted, mask); + return masked; +}; + +/** + * Obtains the bit fragment from a Uint32Array representing a number. + * (ArrayBuffer representations are used in tcuFloat.) + * + * Cannot return more than 52 bits ((lastNdx - firstNdx) <= 52). + * + * @param {Uint32Array} array + * @param {number} firstNdx + * @param {number} lastNdx + * @return {number} + */ +deMath.getArray32BitRange = function(array, firstNdx, lastNdx) { + DE_ASSERT(0 <= firstNdx && firstNdx < (array.length * 32)); + DE_ASSERT(0 < lastNdx && lastNdx <= (array.length * 32)); + DE_ASSERT((lastNdx - firstNdx) <= 52); + + // Example of how this works for a 64-bit number (Uint32Array of length 2). + // + // * Note that the shift operators in the code << and >>> are pointing in + // the opposite direction of this diagram, since LSB is shown on the left. + // + // [array[0], array[1] ] + // [00000011111111111111111111111111, 11111111111100000000000000000000] + // ^LSB MSB^ ^LSB MSB^ + // + // [00000011111111111111111111111111, 11111111111100000000000000000000] + // \ \ + // firstNdx = 6 (inclusive) lastNdx = 44 (exclusive) + // blockIndexA = 0 blockIndexB = 1 + // + // [00000011111111111111111111111111, 11111111111100000000000000000000] + // \-----\ \-------------------\ + // bitsToBeginningOfBlock = 6 bitsFromEndOfBlock = 20 + // + // -------------blockA------------- -------------blockB------------- + // [00000011111111111111111111111111, 11111111111100000000000000000000] + // ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^ + // blockATruncated blockBTruncated + // \--blockATruncatedLength--\ + // + // 11111111111111111111111111 111111111111 + // ^^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^ return value (38 bits) + + /** @type {number} */ var blockIndexA = Math.floor(firstNdx / 32); + /** @type {number} */ var bitsToBeginningOfBlock = firstNdx % 32; + /** @type {number} */ var blockIndexB = Math.floor((lastNdx - 1) / 32); + /** @type {number} */ var bitsFromEndOfBlock = 31 - ((lastNdx - 1) % 32); + + /** @type {number} */ var blockB = array[blockIndexB]; + // Chop off the most significant `bitsFromEndOfBlock` bits from blockB. + // Note: Initially this logic used a bitmask instead. But there are subtle + // corner cases in JS that caused results to sometimes come out negative. + // This truncation method is just used to avoid that complexity. + /** @type {number} */ var blockBTruncated = (blockB << bitsFromEndOfBlock) >>> bitsFromEndOfBlock; + + if (blockIndexA == blockIndexB) { + // firstNdx and lastNdx are in the same block. + // Chop off the least significant `bitsToBeginningOfBlock` bits from blockBTruncated. + return blockBTruncated >>> bitsToBeginningOfBlock; + } else { + // firstNdx and lastNdx are in different blocks. + /** @type {number} */ var blockA = array[blockIndexA]; + // Chop off the least significant `bitsToBeginningOfBlock` bits from blockA. + /** @type {number} */ var blockATruncated = blockA >>> bitsToBeginningOfBlock; + /** @type {number} */ var blockATruncatedLength = 32 - bitsToBeginningOfBlock; + + // Concatenate blockATruncated and blockBTruncated. + // Conceptually equivalent to: + // blockATruncated | (blockBTruncated << blockATruncatedLength) + // except that wouldn't work for numbers larger than 32 bits. + return blockATruncated + (blockBTruncated * Math.pow(2, blockATruncatedLength)); + } +}; + +/** + * Split a large signed number into low and high 32bit dwords. + * @param {number} x + * @return {Array<number>} + */ +deMath.split32 = function(x) { + var ret = []; + ret[1] = Math.floor(x / 0x100000000); + ret[0] = x - ret[1] * 0x100000000; + return ret; +}; + +/** + * Split a signed number's low 32bit dwords into low and high 16bit dwords. + * @param {number} x + * @return {Array<number>} + */ +deMath.split16 = function(x) { + var ret = []; + x = x & 0xffffffff; + ret[1] = Math.floor(x / 0x10000); + ret[0] = x - ret[1] * 0x10000; + return ret; +}; + +/** + * Recontruct a number from high and low 32 bit dwords + * @param {Array<number>} x + * @return {number} + */ +deMath.join32 = function(x) { + var v0 = x[0] >= 0 ? x[0] : 0x100000000 + x[0]; + var v1 = x[1]; + var val = v1 * 0x100000000 + v0; + return val; +}; + +//Bit operations with the help of arrays + +/** + * @enum + */ +deMath.BinaryOp = { + AND: 0, + OR: 1, + XOR: 2 +}; + +/** + * Performs a normal (native) binary operation + * @param {number} valueA First operand + * @param {number} valueB Second operand + * @param {deMath.BinaryOp} operation The desired operation to perform + * @return {number} + */ +deMath.doNativeBinaryOp = function(valueA, valueB, operation) { + switch (operation) { + case deMath.BinaryOp.AND: + return valueA & valueB; + case deMath.BinaryOp.OR: + return valueA | valueB; + case deMath.BinaryOp.XOR: + return valueA ^ valueB; + default: + throw new Error('Unknown operation: ' + operation); + } +}; + +/** + * Performs a binary operation between two operands + * with the help of arrays to avoid losing the internal binary representation. + * @param {number} valueA First operand + * @param {number} valueB Second operand + * @param {deMath.BinaryOp} binaryOpParm The desired operation to perform + * @return {number} + */ +deMath.binaryOp = function(valueA, valueB, binaryOpParm) { + //quick path if values fit in signed 32 bit range + if (deMath.deInRange32(valueA, -0x80000000, 0x7FFFFFFF) && deMath.deInRange32(valueB, -0x80000000, 0x7FFFFFFF)) + return deMath.doNativeBinaryOp(valueA, valueB, binaryOpParm); + + var x = deMath.split32(valueA); + var y = deMath.split32(valueB); + var z = []; + for (var i = 0; i < 2; i++) + z[i] = deMath.doNativeBinaryOp(x[i], y[i], binaryOpParm); + var ret = deMath.join32(z); + return ret; +}; + +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +deMath.binaryAnd = function(a, b) { + return deMath.binaryOp(a, b, deMath.BinaryOp.AND); +}; + +/** + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} + */ +deMath.binaryAndVecScalar = function(a, b) { + if (!Array.isArray(a)) + throw new Error('First argument must be an array.'); + if (typeof b !== 'number') + throw new Error('Second argument must be a number.'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(deMath.binaryOp(a[i], b, deMath.BinaryOp.AND)); + return dst; +}; + +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +deMath.binaryOr = function(a, b) { + return deMath.binaryOp(a, b, deMath.BinaryOp.OR); +}; + +/** + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} + */ +deMath.binaryOrVecScalar = function(a, b) { + if (!Array.isArray(a)) + throw new Error('First argument must be an array.'); + if (typeof b !== 'number') + throw new Error('Second argument must be a number.'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(deMath.binaryOp(a[i], b, deMath.BinaryOp.OR)); + return dst; +}; + +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +deMath.binaryXor = function(a, b) { + return deMath.binaryOp(a, b, deMath.BinaryOp.XOR); +}; + +/** + * @param {goog.NumberArray} a + * @param {number} b + * @return {Array<number>} + */ +deMath.binaryXorVecScalar = function(a, b) { + if (!Array.isArray(a)) + throw new Error('First argument must be an array.'); + if (typeof b !== 'number') + throw new Error('Second argument must be a number.'); + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(deMath.binaryOp(a[i], b, deMath.BinaryOp.XOR)); + return dst; +}; + +/** + * Performs a binary NOT operation on an operand + * @param {number} value Operand + * @return {number} + */ +deMath.binaryNot = function(value) { + //quick path if value fits in signed 32 bit range + if (deMath.deInRange32(value, -0x80000000, 0x7FFFFFFF)) + return ~value; + + var x = deMath.split32(value); + x[0] = ~x[0]; + x[1] = ~x[1]; + var ret = deMath.join32(x); + return ret; +}; + +/** + * Shifts the given value 'steps' bits to the left. Replaces << operator + * This function should be used if the expected value will be wider than 32-bits. + * @param {number} value + * @param {number} steps + * @return {number} + */ +deMath.shiftLeft = function(value, steps) { + //quick path + if (steps < 31) { + var v = value * (1 << steps); + if (deMath.deInRange32(v, -0x80000000, 0x7FFFFFFF)) + return v; + } + + if (steps == 0) + return value; + else if (steps < 32) { + var mask = (1 << 32 - steps) - 1; + var x = deMath.split32(value); + var highBits = x[0] & (~mask); + var y = highBits >> (32 - steps); + if (highBits < 0) { + var m = (1 << steps) - 1; + y &= m; + } + var result = []; + result[0] = x[0] << steps; + result[1] = x[1] << steps; + result[1] |= y; + + return deMath.join32(result); + } else { + var x = deMath.split32(value); + var result = []; + result[0] = 0; + result[1] = x[0] << steps - 32; + return deMath.join32(result); + } +}; + +/** + * @param {Array<number>} a + * @param {number} b + */ +deMath.shiftLeftVecScalar = function(a, b) { + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(deMath.shiftLeft(a[i], b)); + return dst; +}; + +/** + * Shifts the given value 'steps' bits to the right. Replaces >> operator + * This function should be used if the value is wider than 32-bits + * @param {number} value + * @param {number} steps + * @return {number} + */ +deMath.shiftRight = function(value, steps) { + //quick path + if (deMath.deInRange32(value, -0x80000000, 0x7FFFFFFF) && steps < 32) + return value >> steps; + + if (steps == 0) + return value; + else if (steps < 32) { + if (steps == 0) + return value; + var mask = (1 << steps) - 1; + var x = deMath.split32(value); + var lowBits = x[1] & mask; + var result = []; + var m = (1 << 32 - steps) - 1; + result[0] = (x[0] >> steps) & m; + result[1] = x[1] >> steps; + result[0] |= lowBits << 32 - steps; + return deMath.join32(result); + } else { + var x = deMath.split32(value); + var result = []; + result[0] = x[1] >> steps - 32; + result[1] = value < 0 ? -1 : 0; + return deMath.join32(result); + } +}; + +/** + * @param {Array<number>} a + * @param {number} b + */ +deMath.shiftRightVecScalar = function(a, b) { + var dst = []; + for (var i = 0; i < a.length; i++) + dst.push(deMath.shiftRight(a[i], b)); + return dst; +}; + +/** deMath.logicalAndBool over two arrays of booleans + * @param {Array<boolean>} a + * @param {Array<boolean>} b + * @return {Array<boolean>} + */ +deMath.logicalAndBool = function(a, b) { + if (!Array.isArray(a)) + throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a); + if (!Array.isArray(b)) + throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b); + if (a.length != b.length) + throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')'); + + /** @type {Array<boolean>} */ var result = []; + for (var i = 0; i < a.length; i++) { + if (a[i] & b[i]) + result.push(true); + else + result.push(false); + } + return result; +}; + +/** deMath.logicalOrBool over two arrays of booleans + * @param {Array<boolean>} a + * @param {Array<boolean>} b + * @return {Array<boolean>} + */ +deMath.logicalOrBool = function(a, b) { + if (!Array.isArray(a)) + throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a); + if (!Array.isArray(b)) + throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b); + if (a.length != b.length) + throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')'); + + /** @type {Array<boolean>} */ var result = []; + for (var i = 0; i < a.length; i++) { + if (a[i] | b[i]) + result.push(true); + else + result.push(false); + } + return result; +}; + +/** deMath.logicalNotBool over an array of booleans + * @param {Array<boolean>} a + * @return {Array<boolean>} + */ +deMath.logicalNotBool = function(a) { + if (!Array.isArray(a)) + throw new Error('The passed value is not an array: (' + typeof(a) + ')' + a); + + /** @type {Array<boolean>} */ var result = []; + for (var i = 0; i < a.length; i++) + result.push(!a[i]); + return result; +}; + +/** deMath.greaterThan over two arrays of booleans + * @param {Array<number>} a + * @param {Array<number>} b + * @return {Array<boolean>} + */ +deMath.greaterThan = function(a, b) { + if (!Array.isArray(a)) + throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a); + if (!Array.isArray(b)) + throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b); + if (a.length != b.length) + throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')'); + + /** @type {Array<boolean>} */ var result = []; + for (var i = 0; i < a.length; i++) + result.push(a[i] > b[i]); + return result; +}; + +/** deMath.greaterThan over two arrays of booleans + * @param {Array<number>} a + * @param {Array<number>} b + * @return {Array<boolean>} + */ +deMath.greaterThanEqual = function(a, b) { + if (!Array.isArray(a)) + throw new Error('The first parameter is not an array: (' + typeof(a) + ')' + a); + if (!Array.isArray(b)) + throw new Error('The second parameter is not an array: (' + typeof(b) + ')' + b); + if (a.length != b.length) + throw new Error('The lengths of the passed arrays are not equivalent. (' + a.length + ' != ' + b.length + ')'); + + /** @type {Array<boolean>} */ var result = []; + for (var i = 0; i < a.length; i++) + result.push(a[i] >= b[i]); + return result; +}; + +/** + * Array of float to array of int (0, 255) + * @param {Array<number>} a + * @return {Array<number>} + */ + +deMath.toIVec = function(a) { + /** @type {Array<number>} */ var res = []; + for (var i = 0; i < a.length; i++) + res.push(deMath.clamp(Math.floor(a[i] * 255), 0, 255)); + return res; +}; + +/** + * @param {number} a + * @return {number} + */ + deMath.clz32 = function(a) { + /** @type {number} */ var maxValue = 2147483648; // max 32 bit number + /** @type {number} */ var leadingZeros = 0; + while (a < maxValue) { + maxValue = maxValue >>> 1; + leadingZeros++; + } + return leadingZeros; +}; + +/** + * @param {number} a + * @param {number} exponent + * @return {number} + */ +deMath.deLdExp = function(a, exponent) { + return deMath.ldexp(a, exponent); +}; + +/** + * @param {number} a + * @param {number} exponent + * @return {number} + */ +deMath.deFloatLdExp = function(a, exponent) { + return deMath.ldexp(a, exponent); +}; + +/** + * @param {number} value + * @return {Array<number>} + */ +deMath.frexp = (function() { + var data = new DataView(new ArrayBuffer(8)); + + return function(value) { + if (value === 0) return [value, 0]; + data.setFloat64(0, value); + var bits = (data.getUint32(0) >>> 20) & 0x7FF; + if (bits === 0) { + data.setFloat64(0, value * Math.pow(2, 64)); + bits = ((data.getUint32(0) >>> 20) & 0x7FF) - 64; + } + var exponent = bits - 1022, + mantissa = deMath.ldexp(value, -exponent); + return [mantissa, exponent]; + } +})(); + +/** + * @param {number} mantissa + * @param {number} exponent + * @return {number} + */ +deMath.ldexp = function(mantissa, exponent) { + return exponent > 1023 ? // avoid multiplying by infinity + mantissa * Math.pow(2, 1023) * Math.pow(2, exponent - 1023) : + exponent < -1074 ? // avoid multiplying by zero + mantissa * Math.pow(2, -1074) * Math.pow(2, exponent + 1074) : + mantissa * Math.pow(2, exponent); +}; + +/** + * @param {number} a + * @return {number} + */ +deMath.deCbrt = function(a) { + return deMath.deSign(a) * Math.pow(Math.abs(a), 1.0 / 3.0); +}; + +/** + * @param {number} x + * @return {number} + */ +deMath.deSign = function(x) { + return isNaN(x) ? x : ((x > 0.0) - (x < 0.0)); +}; + +deMath.deFractExp = function(x) { + var result = { + significand: x, + exponent: 0 + }; + + if (isFinite(x)) { + var r = deMath.frexp(x); + result.exponent = r[1] - 1; + result.significand = r[0] * 2; + } + return result; +}; + +}); diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deRandom.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deRandom.js new file mode 100644 index 0000000000..2246a2e9d3 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deRandom.js @@ -0,0 +1,260 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program OpenGL ES Utilities + * ------------------------------------------------ + * + * Copyright 2014 The Android Open Source Project + * + * 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. + * + */ + +/** + * This class allows one to create a random integer, floating point number or boolean (TODO, deRandom.choose random items from a list and deRandom.shuffle an array) + */ +'use strict'; +goog.provide('framework.delibs.debase.deRandom'); + +goog.scope(function() { + +var deRandom = framework.delibs.debase.deRandom; + +/** + * Array of pseudo random numbers based on seed + * @constructor + * @struct + */ +deRandom.deRandom = function() { + /** @type {number} */ this.x = 0; + /** @type {number} */ this.y = 0; + /** @type {number} */ this.z = 0; + /** @type {number} */ this.w = 0; +}; + +/** + * deRandom.Random number generator init + * @param {deRandom.deRandom} rnd Array to store random numbers + * @param {number} seed Number for seed + */ +deRandom.deRandom_init = function(rnd, seed) { + rnd.x = (-seed ^ 123456789); + rnd.y = (362436069 * seed); + rnd.z = (521288629 ^ (seed >> 7)); + rnd.w = (88675123 ^ (seed << 3)); +}; + +/** + * Function to get random int + * @param {deRandom.deRandom} rnd Initialised array of random numbers + * @param {Array<number>=} opts Min and max for range + * @return {number} deRandom.Random int + */ +deRandom.deRandom_getInt = function(rnd, opts) { + if (opts != undefined && opts[0] != undefined && opts[1] != undefined) { + if (opts[0] == 0x80000000 && opts[1] == 0x7fffffff) { + return deRandom.deRandom_getInt(rnd); + } else { + return opts[0] + (deRandom.deRandom_getInt(rnd) % (opts[1] - opts[0] + 1)); + } + } + var w = rnd.w; + var t; + + t = rnd.x ^ (rnd.x << 11); + rnd.x = rnd.y; + rnd.y = rnd.z; + rnd.z = w; + rnd.w = w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); + return w; +}; + +/** + * Function to get random float + * @param {deRandom.deRandom} rnd Initialised array of random numbers + * @param {Array<number>=} opts Min and max for range + * @return {number} deRandom.Random float + */ +deRandom.deRandom_getFloat = function(rnd, opts) { + if (opts != undefined && opts[0] != undefined && opts[1] != undefined) { + if (opts[0] <= opts[1]) { + return opts[0] + (opts[1] - opts[0]) * deRandom.deRandom_getFloat(rnd); + } + } else { + return (deRandom.deRandom_getInt(rnd) & 0xFFFFFFF) / (0xFFFFFFF + 1); + } + throw new Error('Invalid arguments'); +}; + +/** + * Function to get random boolean + * @param {deRandom.deRandom} rnd Initialised array of random numbers + * @return {boolean} deRandom.Random boolean + */ +deRandom.deRandom_getBool = function(rnd) { + var val; + val = deRandom.deRandom_getInt(rnd); + return ((val & 0xFFFFFF) < 0x800000); +}; + +/** + * Function to get a common base seed + * @return {number} constant + */ +deRandom.getBaseSeed = function() { + return 42; +}; + +/** + * TODO Function to deRandom.choose random items from a list + * @template T + * @param {deRandom.deRandom} rnd Initialised array of random numbers + * @param {Array<T>} elements Array segment already defined + * @param {Array<T>=} resultOut Array where to store the elements in. If undefined, default to array of (num) elements. + * @param {number=} num Number of items to store in resultOut. If undefined, default to 1. + * @return {Array<T>} Even though result is stored in resultOut, return it here as well. + */ +deRandom.choose = function(rnd, elements, resultOut, num) { + var items = num || 1; + var temp = elements.slice(); + if (!resultOut) + resultOut = []; + + while (items-- > 0) { + var index = deRandom.deRandom_getInt(rnd, [0, temp.length - 1]); + resultOut.push(temp[index]); + temp.splice(index, 1); + } + return resultOut; +}; + +/** + * TODO Function to deRandom.choose weighted random items from a list + * @param {deRandom.deRandom} rnd Initialised randomizer + * @param {Array<number>} array Array to choose items from + * @param {Array<number>} weights Weights array + * @return {number} Result output + */ +deRandom.chooseWeighted = function(rnd, array, weights) { + // Compute weight sum + /** @type {number} */ var weightSum = 0.0; + /** @type {number} */ var ndx; + for (ndx = 0; ndx < array.length; ndx++) + weightSum += weights[ndx]; + + // Random point in 0..weightSum + /** @type {number} */ var p = deRandom.deRandom_getFloat(rnd, [0.0, weightSum]); + + // Find item in range + /** @type {number} */ var lastNonZero = array.length; + /** @type {number} */ var curWeight = 0.0; + for (ndx = 0; ndx != array.length; ndx++) { + /** @type {number} */ var w = weights[ndx]; + + curWeight += w; + + if (p < curWeight) + return array[ndx]; + else if (w > 0.0) + lastNonZero = ndx; + } + + assertMsgOptions(lastNonZero != array.length, 'Index went out of bounds', false, true); + return array[lastNonZero]; +}; + +/** + * TODO Function to deRandom.shuffle an array + * @param {deRandom.deRandom} rnd Initialised array of random numbers + * @param {Array} elements Array to deRandom.shuffle + * @return {Array} Shuffled array + */ +deRandom.shuffle = function(rnd, elements) { + var index = elements.length; + + while (index > 0) { + var random = deRandom.deRandom_getInt(rnd, [0, index - 1]); + index -= 1; + var elem = elements[index]; + elements[index] = elements[random]; + elements[random] = elem; + } + return elements; +}; + +/** + * This function is used to create the deRandom.Random object and + * initialise the random number with a seed. + * It contains functions for generating random numbers in a variety of formats + * @constructor + * @param {number} seed Number to use as a seed + */ +deRandom.Random = function(seed) { + /** + * Instance of array of pseudo random numbers based on seeds + */ + this.m_rnd = new deRandom.deRandom(); + + //initialise the random numbers based on seed + deRandom.deRandom_init(this.m_rnd, seed); +}; + +/** + * Function to get random boolean + * @return {boolean} deRandom.Random boolean + */ +deRandom.Random.prototype.getBool = function() { return deRandom.deRandom_getBool(this.m_rnd) == true; }; +/** + * Function to get random float + * @param {number=} min Min for range + * @param {number=} max Max for range + * @return {number} deRandom.Random float + */ +deRandom.Random.prototype.getFloat = function(min, max) { return deRandom.deRandom_getFloat(this.m_rnd, [min, max]) }; +/** + * Function to get random int + * @param {number=} min Min for range + * @param {number=} max Max for range + * @return {number} deRandom.Random int + */ +deRandom.Random.prototype.getInt = function(min, max) {return deRandom.deRandom_getInt(this.m_rnd, [min, max])}; +/** + * TODO Function to deRandom.choose random items from a list + * @template T + * @param {Array<T>} elements Array segment already defined + * @param {Array<T>=} resultOut Array where to store the elements in. If undefined, default to array of (num) elements. + * @param {number=} num Number of items to store in resultOut. If undefined, default to 1. + * @return {Array<T>} Even though result is stored in resultOut, return it here as well. + */ +deRandom.Random.prototype.choose = function(elements, resultOut, num) {return deRandom.choose(this.m_rnd, elements, resultOut, num)}; +/** + * choose weighted random items from a list + * @param {Array<number>} array Array to choose items from + * @param {Array<number>} weights Weights array + * @return {number} Result output + */ +deRandom.Random.prototype.chooseWeighted = function(array, weights) {return deRandom.chooseWeighted(this.m_rnd, array, weights)}; +/** + * TODO Function to deRandom.shuffle an array + * @param {Array} elements Array to deRandom.shuffle + * @return {Array} Shuffled array + */ +deRandom.Random.prototype.shuffle = function(elements) {return deRandom.shuffle(this.m_rnd, elements)}; + +/** + * Function to get a common base seed + * @return {number} constant + */ +deRandom.Random.prototype.getBaseSeed = function() { + return deRandom.getBaseSeed(); +}; + +}); diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deString.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deString.js new file mode 100644 index 0000000000..fc84a72327 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deString.js @@ -0,0 +1,111 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program OpenGL ES Utilities + * ------------------------------------------------ + * + * Copyright 2014 The Android Open Source Project + * + * 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. + * + */ + +/** + * This class allows one to create a random integer, floating point number or boolean (TODO, choose random items from a list and shuffle an array) + */ +'use strict'; +goog.provide('framework.delibs.debase.deString'); +goog.require('framework.delibs.debase.deMath'); + +goog.scope(function() { + +var deString = framework.delibs.debase.deString; +var deMath = framework.delibs.debase.deMath; + + var DE_ASSERT = function(x) { + if (!x) + throw new Error('Assert failed'); + }; + + /** + * Compute hash from string. + * @param {?string} str String to compute hash value for. + * @return {number} Computed hash value. + */ + deString.deStringHash = function(str) { + /* \note [pyry] This hash is used in DT_GNU_HASH and is proven + to be robust for symbol hashing. */ + /* \see http://sources.redhat.com/ml/binutils/2006-06/msg00418.html */ + /** @type {number} */ var hash = 5381; + /** @type {number} */ var c; + + DE_ASSERT(str != undefined); + if (str !== null) { + var i = 0; + while (i < str.length) { //(c = (unsigned int)*str++) != 0) + c = str.charCodeAt(i); //trunc to 8-bit + hash = (hash << 5) + hash + c; + i++; + } + } + return hash; + }; + + /** + * Checks if a JS string is either empty or undefined + * @param {string} str + * @return {boolean} + */ + deString.deIsStringEmpty = function(str) { + if (str === undefined || str.length == 0) + return true; + return false; + }; + + /** + * @private + * @param {Object} enumType + * @param {?} value + * @return {string} + */ + deString.getString = function(enumType, value) { + for (var p in enumType) + if (enumType[p] == value) + return p; + + if (typeof value === 'undefined') + return 'undefined'; + + if (!value) + return 'null'; + + return value.toString(10); + }; + + /** + * @param {Object} enumType + * @param {?} value + * @return {string} + */ + deString.enumToString = function(enumType, value) { + if (typeof deString.enumToString[enumType] === 'undefined') + deString.enumToString[enumType] = {}; + + var table = deString.enumToString[enumType]; + if (typeof table[value] === 'undefined') { + var v = deString.getString(enumType, value); + table[value] = v; + } + + return table[value]; + }; + +}); diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deUtil.js b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deUtil.js new file mode 100644 index 0000000000..56a90b6ff6 --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/deqp/framework/delibs/debase/deUtil.js @@ -0,0 +1,90 @@ +/*------------------------------------------------------------------------- + * drawElements Quality Program OpenGL ES Utilities + * ------------------------------------------------ + * + * Copyright 2014 The Android Open Source Project + * + * 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. + * + */ + +'use strict'; +goog.provide('framework.delibs.debase.deUtil'); +goog.require('framework.delibs.debase.deMath'); + +goog.scope(function() { + + var deUtil = framework.delibs.debase.deUtil; + var deMath = framework.delibs.debase.deMath; + + //! Get an element of an array with a specified size. + /** + * @param {Array} array + * @param {number} offset + * @return {*} + */ + deUtil.getArrayElement = function(array, offset) { + assertMsgOptions(deMath.deInBounds32(offset, 0, array.length), 'Array element out of bounds', false, true); + return array[offset]; + }; + + /** + * clone - If you need to pass/assign an object by value, call this + * @param {*} obj + * @return {*} + */ + deUtil.clone = function(obj) { + if (obj == null || typeof(obj) != 'object') + return obj; + + var temp = {}; + if (ArrayBuffer.isView(obj)) { + temp = new obj.constructor(obj); + } else if (obj instanceof Array) { + temp = new Array(obj.length); + for (var akey in obj) + temp[akey] = deUtil.clone(obj[akey]); + } else if (obj instanceof ArrayBuffer) { + temp = new ArrayBuffer(obj.byteLength); + var dst = new Uint8Array(temp); + var src = new Uint8Array(obj); + dst.set(src); + } else { + temp = Object.create(obj.constructor.prototype); + temp.constructor = obj.constructor; + for (var key in obj) + temp[key] = deUtil.clone(obj[key]); + } + return temp; + }; + + /** + * Add a push_unique function to Array. Will insert only if there is no equal element. + * @template T + * @param {Array<T>} array Any array + * @param {T} object Any object + */ + deUtil.dePushUniqueToArray = function(array, object) { + //Simplest implementation + for (var i = 0; i < array.length; i++) { + if (object.equals !== undefined) + if (object.equals(array[i])) + return undefined; + else if (object === array[i]) + return undefined; + } + + array.push(object); + }; + +}); |