Implement TypedArray#every/some/findIndex and improve map/reduce/reduceRight (#433)

This commit is contained in:
jtenner 2019-01-24 02:33:22 -05:00 committed by Daniel Wirtz
parent d3715688fc
commit 3b1852bc37
6 changed files with 10339 additions and 2005 deletions

View File

@ -591,6 +591,18 @@ declare abstract class TypedArray<T> implements ArrayBufferView<T> {
callbackfn: (accumulator: W, value: T, index: i32, self: this) => W,
initialValue: W,
): W;
/** The some() method tests whether some element in the typed array passes the test implemented by the provided function. This method has the same algorithm as Array.prototype.some().*/
some(callbackfn: (value: T, index: i32, self: this) => bool): bool;
/** The map() method creates a new typed array with the results of calling a provided function on every element in this typed array. This method has the same algorithm as Array.prototype.map().*/
map(callbackfn: (value: T, index: i32, self: this) => T): this;
/** The sort() method sorts the elements of a typed array numerically in place and returns the typed array. This method has the same algorithm as Array.prototype.sort(), except that sorts the values numerically instead of as strings. TypedArray is one of the typed array types here. */
sort(callback?: (a: T, b: T) => i32): this;
/** The fill() method fills all the elements of a typed array from a start index to an end index with a static value. This method has the same algorithm as Array.prototype.fill(). */
fill(value: T, start?: i32, end?: i32): this;
/** The findIndex() method returns an index in the typed array, if an element in the typed array satisfies the provided testing function. Otherwise -1 is returned. See also the find() [not implemented] method, which returns the value of a found element in the typed array instead of its index. */
findIndex(callbackfn: (value: T, index: i32, self: this) => bool): i32;
/** The every() method tests whether all elements in the typed array pass the test implemented by the provided function. This method has the same algorithm as Array.prototype.every(). */
every(callbackfn: (value: T, index: i32, self: this) => bool): i32;
}
/** An array of twos-complement 8-bit signed integers. */

View File

@ -60,7 +60,7 @@ export abstract class TypedArray<T> {
}
@inline
export function FILL<TArray extends TypedArray<T>, T>(
export function FILL<TArray extends TypedArray<T>, T extends number>(
array: TArray,
value: NATIVE<T>,
start: i32,
@ -133,16 +133,16 @@ export function REDUCE<TArray extends TypedArray<T>, T, TRet>(
callbackfn: (accumulator: TRet, value: T, index: i32, array: TArray) => TRet,
initialValue: TRet
): TRet {
var index = 0;
var length = <i32>array.length;
while (index != length) {
var length = array.length;
var buffer = array.buffer;
var byteOffset = array.byteOffset;
for (let i = 0; i < length; i++) {
initialValue = callbackfn(
initialValue,
unchecked(array[index]),
index,
LOAD<T>(buffer, i, byteOffset),
i,
array,
);
++index;
}
return initialValue;
}
@ -153,16 +153,15 @@ export function REDUCE_RIGHT<TArray extends TypedArray<T>, T, TRet>(
callbackfn: (accumulator: TRet, value: T, index: i32, array: TArray) => TRet,
initialValue: TRet
): TRet {
var index = <i32>array.length - 1;
var length = -1;
while (index != length) {
var buffer = array.buffer;
var byteOffset = array.byteOffset;
for (let i = array.length - 1; i >= 0; i--) {
initialValue = callbackfn(
initialValue,
unchecked(array[index]),
index,
LOAD<T>(buffer, i, byteOffset),
i,
array,
);
--index;
}
return initialValue;
}
@ -172,12 +171,63 @@ export function MAP<TArray extends TypedArray<T>, T>(
array: TArray,
callbackfn: (value: T, index: i32, self: TArray) => T,
): TArray {
var length: i32 = array.length;
var length = array.length;
var buffer = array.buffer;
var byteOffset = array.byteOffset;
var result = instantiate<TArray>(length);
var i: i32 = 0;
while (i < length) {
unchecked(result[i] = callbackfn(array[i], i, <TArray>array));
++i;
var resultBuffer = result.buffer;
for (let i = 0; i < length; i++) {
STORE<T, NATIVE<T>>(resultBuffer, i, <NATIVE<T>>callbackfn(LOAD<T>(buffer, i, byteOffset), i, array));
}
return result;
}
@inline
export function FIND_INDEX<TArray extends TypedArray<T>, T>(
array: TArray,
callbackfn: (value: T, index: i32, array: TArray) => bool,
): i32 {
var length = array.length;
var buffer = array.buffer;
var byteOffset = array.byteOffset;
for (let i = 0; i < length; i++) {
if (callbackfn(LOAD<T>(buffer, i, byteOffset), i, array)) {
return i;
}
}
return -1;
}
@inline
export function SOME<TArray extends TypedArray<T>, T>(
array: TArray,
callbackfn: (value: T, index: i32, array: TArray) => bool,
): bool {
var length = array.length;
var buffer = array.buffer;
var byteOffset = array.byteOffset;
for (let i = 0; i < length; i++) {
if (callbackfn(LOAD<T>(buffer, i, byteOffset), i, array)) {
return true;
}
}
return false;
}
@inline
export function EVERY<TArray extends TypedArray<T>, T>(
array: TArray,
callbackfn: (value: T, index: i32, array: TArray) => bool,
): bool {
var length = array.length;
var buffer = array.buffer;
var byteOffset = array.byteOffset;
for (let i = 0; i < length; i++) {
if (callbackfn(LOAD<T>(buffer, i, byteOffset), i, array)) {
continue;
}
return false;
}
return true;
}

View File

@ -6,6 +6,9 @@ import {
REDUCE,
REDUCE_RIGHT,
MAP,
FIND_INDEX,
SOME,
EVERY,
} from "./internal/typedarray";
import {
@ -44,6 +47,18 @@ export class Int8Array extends TypedArray<i8> {
map(callbackfn: (value: i8, index: i32, self: Int8Array) => i8): Int8Array {
return MAP<Int8Array, i8>(this, callbackfn);
}
findIndex(callbackfn: (value: i8, index: i32, self: Int8Array) => bool): i32 {
return FIND_INDEX<Int8Array, i8>(this, callbackfn);
}
some(callbackfn: (value: i8, index: i32, self: Int8Array) => bool): bool {
return SOME<Int8Array, i8>(this, callbackfn);
}
every(callbackfn: (value: i8, index: i32, self: Int8Array) => bool): bool {
return EVERY<Int8Array, i8>(this, callbackfn);
}
}
export class Uint8Array extends TypedArray<u8> {
@ -78,6 +93,18 @@ export class Uint8Array extends TypedArray<u8> {
map(callbackfn: (value: u8, index: i32, self: Uint8Array) => u8): Uint8Array {
return MAP<Uint8Array, u8>(this, callbackfn);
}
findIndex(callbackfn: (value: u8, index: i32, self: Uint8Array) => bool): i32 {
return FIND_INDEX<Uint8Array, u8>(this, callbackfn);
}
some(callbackfn: (value: u8, index: i32, self: Uint8Array) => bool): bool {
return SOME<Uint8Array, u8>(this, callbackfn);
}
every(callbackfn: (value: u8, index: i32, self: Uint8Array) => bool): bool {
return EVERY<Uint8Array, u8>(this, callbackfn);
}
}
export class Uint8ClampedArray extends Uint8Array {
@ -108,6 +135,18 @@ export class Uint8ClampedArray extends Uint8Array {
map(callbackfn: (value: u8, index: i32, self: Uint8ClampedArray) => u8): Uint8ClampedArray {
return MAP<Uint8ClampedArray, u8>(this, callbackfn);
}
findIndex(callbackfn: (value: u8, index: i32, self: Uint8ClampedArray) => bool): i32 {
return FIND_INDEX<Uint8ClampedArray, u8>(this, callbackfn);
}
some(callbackfn: (value: u8, index: i32, self: Uint8ClampedArray) => bool): bool {
return SOME<Uint8ClampedArray, u8>(this, callbackfn);
}
every(callbackfn: (value: u8, index: i32, self: Uint8ClampedArray) => bool): bool {
return EVERY<Uint8ClampedArray, u8>(this, callbackfn);
}
}
export class Int16Array extends TypedArray<i16> {
@ -142,6 +181,18 @@ export class Int16Array extends TypedArray<i16> {
map(callbackfn: (value: i16, index: i32, self: Int16Array) => i16): Int16Array {
return MAP<Int16Array, i16>(this, callbackfn);
}
findIndex(callbackfn: (value: i16, index: i32, self: Int16Array) => bool): i32 {
return FIND_INDEX<Int16Array, i16>(this, callbackfn);
}
some(callbackfn: (value: i16, index: i32, self: Int16Array) => bool): bool {
return SOME<Int16Array, i16>(this, callbackfn);
}
every(callbackfn: (value: i16, index: i32, self: Int16Array) => bool): bool {
return EVERY<Int16Array, i16>(this, callbackfn);
}
}
export class Uint16Array extends TypedArray<u16> {
@ -176,6 +227,18 @@ export class Uint16Array extends TypedArray<u16> {
map(callbackfn: (value: u16, index: i32, self: Uint16Array) => u16): Uint16Array {
return MAP<Uint16Array, u16>(this, callbackfn);
}
findIndex(callbackfn: (value: u16, index: i32, self: Uint16Array) => bool): i32 {
return FIND_INDEX<Uint16Array, u16>(this, callbackfn);
}
some(callbackfn: (value: u16, index: i32, self: Uint16Array) => bool): bool {
return SOME<Uint16Array, u16>(this, callbackfn);
}
every(callbackfn: (value: u16, index: i32, self: Uint16Array) => bool): bool {
return EVERY<Uint16Array, u16>(this, callbackfn);
}
}
export class Int32Array extends TypedArray<i32> {
@ -210,6 +273,18 @@ export class Int32Array extends TypedArray<i32> {
map(callbackfn: (value: i32, index: i32, self: Int32Array) => i32): Int32Array {
return MAP<Int32Array, i32>(this, callbackfn);
}
findIndex(callbackfn: (value: i32, index: i32, self: Int32Array) => bool): i32 {
return FIND_INDEX<Int32Array, i32>(this, callbackfn);
}
some(callbackfn: (value: i32, index: i32, self: Int32Array) => bool): bool {
return SOME<Int32Array, i32>(this, callbackfn);
}
every(callbackfn: (value: i32, index: i32, self: Int32Array) => bool): bool {
return EVERY<Int32Array, i32>(this, callbackfn);
}
}
export class Uint32Array extends TypedArray<u32> {
@ -244,6 +319,18 @@ export class Uint32Array extends TypedArray<u32> {
map(callbackfn: (value: u32, index: i32, self: Uint32Array) => u32): Uint32Array {
return MAP<Uint32Array, u32>(this, callbackfn);
}
findIndex(callbackfn: (value: u32, index: i32, self: Uint32Array) => bool): i32 {
return FIND_INDEX<Uint32Array, u32>(this, callbackfn);
}
some(callbackfn: (value: u32, index: i32, self: Uint32Array) => bool): bool {
return SOME<Uint32Array, u32>(this, callbackfn);
}
every(callbackfn: (value: u32, index: i32, self: Uint32Array) => bool): bool {
return EVERY<Uint32Array, u32>(this, callbackfn);
}
}
export class Int64Array extends TypedArray<i64> {
@ -278,6 +365,18 @@ export class Int64Array extends TypedArray<i64> {
map(callbackfn: (value: i64, index: i32, self: Int64Array) => i64): Int64Array {
return MAP<Int64Array, i64>(this, callbackfn);
}
findIndex(callbackfn: (value: i64, index: i32, self: Int64Array) => bool): i32 {
return FIND_INDEX<Int64Array, i64>(this, callbackfn);
}
some(callbackfn: (value: i64, index: i32, self: Int64Array) => bool): bool {
return SOME<Int64Array, i64>(this, callbackfn);
}
every(callbackfn: (value: i64, index: i32, self: Int64Array) => bool): bool {
return EVERY<Int64Array, i64>(this, callbackfn);
}
}
export class Uint64Array extends TypedArray<u64> {
@ -312,6 +411,18 @@ export class Uint64Array extends TypedArray<u64> {
map(callbackfn: (value: u64, index: i32, self: Uint64Array) => u64): Uint64Array {
return MAP<Uint64Array, u64>(this, callbackfn);
}
findIndex(callbackfn: (value: u64, index: i32, self: Uint64Array) => bool): i32 {
return FIND_INDEX<Uint64Array, u64>(this, callbackfn);
}
some(callbackfn: (value: u64, index: i32, self: Uint64Array) => bool): bool {
return SOME<Uint64Array, u64>(this, callbackfn);
}
every(callbackfn: (value: u64, index: i32, self: Uint64Array) => bool): bool {
return EVERY<Uint64Array, u64>(this, callbackfn);
}
}
export class Float32Array extends TypedArray<f32> {
@ -346,6 +457,18 @@ export class Float32Array extends TypedArray<f32> {
map(callbackfn: (value: f32, index: i32, self: Float32Array) => f32): Float32Array {
return MAP<Float32Array, f32>(this, callbackfn);
}
findIndex(callbackfn: (value: f32, index: i32, self: Float32Array) => bool): i32 {
return FIND_INDEX<Float32Array, f32>(this, callbackfn);
}
some(callbackfn: (value: f32, index: i32, self: Float32Array) => bool): bool {
return SOME<Float32Array, f32>(this, callbackfn);
}
every(callbackfn: (value: f32, index: i32, self: Float32Array) => bool): bool {
return EVERY<Float32Array, f32>(this, callbackfn);
}
}
export class Float64Array extends TypedArray<f64> {
@ -380,4 +503,16 @@ export class Float64Array extends TypedArray<f64> {
map(callbackfn: (value: f64, index: i32, self: Float64Array) => f64): Float64Array {
return MAP<Float64Array, f64>(this, callbackfn);
}
findIndex(callbackfn: (value: f64, index: i32, self: Float64Array) => bool): i32 {
return FIND_INDEX<Float64Array, f64>(this, callbackfn);
}
some(callbackfn: (value: f64, index: i32, self: Float64Array) => bool): bool {
return SOME<Float64Array, f64>(this, callbackfn);
}
every(callbackfn: (value: f64, index: i32, self: Float64Array) => bool): bool {
return EVERY<Float64Array, f64>(this, callbackfn);
}
}

File diff suppressed because one or more lines are too long

View File

@ -237,7 +237,7 @@ assert(multisubarr3.byteLength === 3);
* tests work.
*/
function testReduce<ArrayType, T>(): void {
function testReduce<ArrayType extends TypedArray<T>, T extends number>(): void {
var array: ArrayType = instantiate<ArrayType>(3);
array[0] = <T>1;
array[1] = <T>2;
@ -247,8 +247,8 @@ function testReduce<ArrayType, T>(): void {
// assert(testindex == index);
// assert(array == self);
// --testindex;
return acc + val;
}, 0);
return <T>(acc + val);
}, <T>0);
assert(result == <T>6);
}
@ -264,7 +264,7 @@ testReduce<Uint64Array, u64>();
testReduce<Float32Array, f32>();
testReduce<Float64Array, f64>();
function testReduceRight<ArrayType, T>(): void {
function testReduceRight<ArrayType extends TypedArray<T>, T extends number>(): void {
var array: ArrayType = instantiate<ArrayType>(3);
array[0] = <T>1;
array[1] = <T>2;
@ -274,8 +274,8 @@ function testReduceRight<ArrayType, T>(): void {
// assert(testindex == index);
// assert(array == self);
// --testindex;
return acc + val;
}, 0);
return <T>(acc + val);
}, <T>0);
assert(result == <T>6);
}
@ -291,7 +291,7 @@ testReduceRight<Uint64Array, u64>();
testReduceRight<Float32Array, f32>();
testReduceRight<Float64Array, f64>();
function testArrayMap<ArrayType extends TypedArray<T>, T>(): void {
function testArrayMap<ArrayType extends TypedArray<T>, T extends number>(): void {
var source: ArrayType = instantiate<ArrayType>(3);
source[0] = <T>1;
source[1] = <T>2;
@ -301,7 +301,7 @@ function testArrayMap<ArrayType extends TypedArray<T>, T>(): void {
// assert(self == source);
// assert(testIndex == testIndex);
// testIndex++;
return value * value;
return <T>(value * value);
});
assert(result[0] == <T>1);
assert(result[1] == <T>4);
@ -319,3 +319,93 @@ testArrayMap<Int64Array, i64>();
testArrayMap<Uint64Array, u64>();
testArrayMap<Float32Array, f32>();
testArrayMap<Float64Array, f64>();
function testArraySome<ArrayType extends TypedArray<T>, T extends number>(): void {
var source: ArrayType = instantiate<ArrayType>(3);
source[0] = <T>2;
source[1] = <T>4;
source[2] = <T>6;
// var testIndex: i32 = 0;
var result: bool = source.some((value: T, index: i32, self: ArrayType): bool => {
// assert(self == source);
// assert(testIndex == testIndex);
// testIndex++;
return value == <T>2;
});
assert(result);
var failResult = source.some((value: T, index: i32, self: ArrayType): bool => value == <T>0);
assert(!failResult);
}
testArraySome<Int8Array, i8>();
testArraySome<Uint8Array, u8>();
testArraySome<Uint8ClampedArray, u8>();
testArraySome<Int16Array, i16>();
testArraySome<Uint16Array, u16>();
testArraySome<Int32Array, i32>();
testArraySome<Uint32Array, u32>();
testArraySome<Int64Array, i64>();
testArraySome<Uint64Array, u64>();
testArraySome<Float32Array, f32>();
testArraySome<Float64Array, f64>();
function testArrayFindIndex<ArrayType extends TypedArray<T>, T extends number>(): void {
var source: ArrayType = instantiate<ArrayType>(3);
source[0] = <T>1;
source[1] = <T>2;
source[2] = <T>3;
// var testIndex: i32 = 0;
var result = source.findIndex((value: T, index: i32, self: ArrayType): bool => {
// assert(self == source);
// assert(testIndex == testIndex);
// testIndex++;
return value == <T>2;
});
assert(result == 1);
var failResult = source.findIndex((value: T, index: i32, self: ArrayType): bool => value == <T>4);
assert(failResult == -1);
}
testArrayFindIndex<Int8Array, i8>();
testArrayFindIndex<Uint8Array, u8>();
testArrayFindIndex<Uint8ClampedArray, u8>();
testArrayFindIndex<Int16Array, i16>();
testArrayFindIndex<Uint16Array, u16>();
testArrayFindIndex<Int32Array, i32>();
testArrayFindIndex<Uint32Array, u32>();
testArrayFindIndex<Int64Array, i64>();
testArrayFindIndex<Uint64Array, u64>();
testArrayFindIndex<Float32Array, f32>();
testArrayFindIndex<Float64Array, f64>();
function testArrayEvery<ArrayType extends TypedArray<T>, T extends number>(): void {
var source: ArrayType = instantiate<ArrayType>(3);
source[0] = <T>2;
source[1] = <T>4;
source[2] = <T>6;
// var testIndex: i32 = 0;
var result: bool = source.every((value: T, index: i32, self: ArrayType): bool => {
// assert(self == source);
// assert(testIndex == testIndex);
// testIndex++;
return (value % <T>2) == <T>0;
});
assert(result);
var failResult = source.every((value: T, index: i32, self: ArrayType): bool => value == <T>2);
assert(!failResult);
}
testArrayEvery<Int8Array, i8>();
testArrayEvery<Uint8Array, u8>();
testArrayEvery<Uint8ClampedArray, u8>();
testArrayEvery<Int16Array, i16>();
testArrayEvery<Uint16Array, u16>();
testArrayEvery<Int32Array, i32>();
testArrayEvery<Uint32Array, u32>();
testArrayEvery<Int64Array, i64>();
testArrayEvery<Uint64Array, u64>();
testArrayEvery<Float32Array, f32>();
testArrayEvery<Float64Array, f64>();

File diff suppressed because one or more lines are too long