Implement optional type parameters (#360)

* Add a NATIVE<T> macro type to simplify use of a native WebAssembly type
* Add default type parameters for internal helpers for explicit loads and stores
* Unify loadUnsafe/loadUnsafeWithOffset etc. into one
* Renamed loadUnsafe etc. into just LOAD, like a macro
* Implement parsing of index signatures, but ignore them, for properly linting code
* Refactor TypedArray<T> to use macros
This commit is contained in:
Daniel Wirtz
2018-12-07 14:33:32 +01:00
committed by GitHub
parent d7f4874650
commit ebae7cbd73
39 changed files with 4698 additions and 4128 deletions

View File

@ -3,8 +3,8 @@ import {
HEADER_SIZE,
allocateUnsafe,
reallocateUnsafe,
loadUnsafe,
storeUnsafe
LOAD,
STORE
} from "./internal/arraybuffer";
import {
@ -32,6 +32,7 @@ import {
} from "./builtins";
export class Array<T> {
[key: number]: T; // compatibility only
/* @internal */ buffer_: ArrayBuffer;
/* @internal */ length_: i32;
@ -74,7 +75,7 @@ export class Array<T> {
every(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
if (!callbackfn(loadUnsafe<T,T>(buffer, index), index, this)) return false;
if (!callbackfn(LOAD<T>(buffer, index), index, this)) return false;
}
return true;
}
@ -82,7 +83,7 @@ export class Array<T> {
findIndex(predicate: (element: T, index: i32, array: Array<T>) => bool): i32 {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
if (predicate(loadUnsafe<T,T>(buffer, index), index, this)) return index;
if (predicate(LOAD<T>(buffer, index), index, this)) return index;
}
return -1;
}
@ -91,13 +92,13 @@ export class Array<T> {
private __get(index: i32): T {
var buffer = this.buffer_;
return <u32>index < <u32>(buffer.byteLength >>> alignof<T>())
? loadUnsafe<T,T>(buffer, index)
? LOAD<T>(buffer, index)
: <T>unreachable();
}
@operator("{}")
private __unchecked_get(index: i32): T {
return loadUnsafe<T,T>(this.buffer_, index);
return LOAD<T>(this.buffer_, index);
}
@operator("[]=")
@ -111,13 +112,13 @@ export class Array<T> {
this.buffer_ = buffer;
this.length_ = index + 1;
}
storeUnsafe<T,T>(buffer, index, value);
STORE<T>(buffer, index, value);
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(value)); // tslint:disable-line
}
@operator("{}=")
private __unchecked_set(index: i32, value: T): void {
storeUnsafe<T,T>(this.buffer_, index, value);
STORE<T>(this.buffer_, index, value);
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(value)); // tslint:disable-line
}
@ -138,7 +139,7 @@ export class Array<T> {
}
} else {
for (; start < end; ++start) {
storeUnsafe<T,T>(buffer, start, value);
STORE<T>(buffer, start, value);
}
}
return this;
@ -155,7 +156,7 @@ export class Array<T> {
if (fromIndex < 0) fromIndex = max(length + fromIndex, 0);
var buffer = this.buffer_;
while (fromIndex < length) {
if (loadUnsafe<T,T>(buffer, fromIndex) == searchElement) return fromIndex;
if (LOAD<T>(buffer, fromIndex) == searchElement) return fromIndex;
++fromIndex;
}
return -1;
@ -168,7 +169,7 @@ export class Array<T> {
else if (fromIndex >= length) fromIndex = length - 1;
var buffer = this.buffer_;
while (fromIndex >= 0) { // ^
if (loadUnsafe<T,T>(buffer, fromIndex) == searchElement) return fromIndex;
if (LOAD<T>(buffer, fromIndex) == searchElement) return fromIndex;
--fromIndex;
}
return -1;
@ -186,7 +187,7 @@ export class Array<T> {
this.buffer_ = buffer;
}
this.length_ = newLength;
storeUnsafe<T,T>(buffer, length, element);
STORE<T>(buffer, length, element);
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(element)); // tslint:disable-line
return newLength;
}
@ -228,7 +229,7 @@ export class Array<T> {
from += count - 1;
to += count - 1;
while (count) {
storeUnsafe<T,T>(buffer, to, loadUnsafe<T,T>(buffer, from));
STORE<T>(buffer, to, LOAD<T>(buffer, from));
--from, --to, --count;
}
} else {
@ -244,7 +245,7 @@ export class Array<T> {
pop(): T {
var length = this.length_;
if (length < 1) throw new RangeError("Array is empty");
var element = loadUnsafe<T,T>(this.buffer_, --length);
var element = LOAD<T>(this.buffer_, --length);
this.length_ = length;
return element;
}
@ -252,7 +253,7 @@ export class Array<T> {
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
callbackfn(loadUnsafe<T,T>(buffer, index), index, this);
callbackfn(LOAD<T>(buffer, index), index, this);
}
}
@ -262,7 +263,7 @@ export class Array<T> {
var result = new Array<U>(length);
var resultBuffer = result.buffer_;
for (let index = 0; index < length && index < this.length_; ++index) {
storeUnsafe<U,U>(resultBuffer, index, callbackfn(loadUnsafe<T,T>(buffer, index), index, this));
STORE<U>(resultBuffer, index, callbackfn(LOAD<T>(buffer, index), index, this));
}
return result;
}
@ -272,7 +273,7 @@ export class Array<T> {
var length = this.length_;
var result = new Array<T>();
for (let index = 0; index < length && index < this.length_; ++index) {
let value = loadUnsafe<T,T>(buffer, index);
let value = LOAD<T>(buffer, index);
if (callbackfn(value, index, this)) result.push(value);
}
return result;
@ -285,7 +286,7 @@ export class Array<T> {
var accum = initialValue;
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
accum = callbackfn(accum, loadUnsafe<T,T>(buffer, index), index, this);
accum = callbackfn(accum, LOAD<T>(buffer, index), index, this);
}
return accum;
}
@ -297,7 +298,7 @@ export class Array<T> {
var accum = initialValue;
var buffer = this.buffer_;
for (let index: i32 = this.length_ - 1; index >= 0; --index) {
accum = callbackfn(accum, loadUnsafe<T,T>(buffer, index), index, this);
accum = callbackfn(accum, LOAD<T>(buffer, index), index, this);
}
return accum;
}
@ -306,14 +307,14 @@ export class Array<T> {
var length = this.length_;
if (length < 1) throw new RangeError("Array is empty");
var buffer = this.buffer_;
var element = loadUnsafe<T,T>(buffer, 0);
var element = LOAD<T>(buffer, 0);
var lastIndex = length - 1;
memory.copy(
changetype<usize>(buffer) + HEADER_SIZE,
changetype<usize>(buffer) + HEADER_SIZE + sizeof<T>(),
<usize>lastIndex << alignof<T>()
);
storeUnsafe<T,T>(buffer, lastIndex, <T>null);
STORE<T>(buffer, lastIndex, <T>null);
this.length_ = lastIndex;
return element;
}
@ -321,7 +322,7 @@ export class Array<T> {
some(callbackfn: (element: T, index: i32, array: Array<T>) => bool): bool {
var buffer = this.buffer_;
for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) {
if (callbackfn(loadUnsafe<T,T>(buffer, index), index, this)) return true;
if (callbackfn(LOAD<T>(buffer, index), index, this)) return true;
}
return false;
}
@ -343,7 +344,7 @@ export class Array<T> {
changetype<usize>(buffer) + HEADER_SIZE,
<usize>(capacity - 1) << alignof<T>()
);
storeUnsafe<T,T>(buffer, 0, element);
STORE<T>(buffer, 0, element);
this.length_ = newLength;
if (isManaged<T>()) __gc_link(changetype<usize>(this), changetype<usize>(element)); // tslint:disable-line
return newLength;
@ -396,9 +397,9 @@ export class Array<T> {
reverse(): Array<T> {
var buffer = this.buffer_;
for (let front = 0, back = this.length_ - 1; front < back; ++front, --back) {
let temp = loadUnsafe<T,T>(buffer, front);
storeUnsafe<T,T>(buffer, front, loadUnsafe<T,T>(buffer, back));
storeUnsafe<T,T>(buffer, back, temp);
let temp = LOAD<T>(buffer, front);
STORE<T>(buffer, front, LOAD<T>(buffer, back));
STORE<T>(buffer, back, temp);
}
return this;
}
@ -411,11 +412,11 @@ export class Array<T> {
if (length <= 1) return this;
var buffer = this.buffer_;
if (length == 2) {
let a = loadUnsafe<T,T>(buffer, 1); // a = arr[1]
let b = loadUnsafe<T,T>(buffer, 0); // b = arr[0]
let a = LOAD<T>(buffer, 1); // a = arr[1]
let b = LOAD<T>(buffer, 0); // b = arr[0]
if (comparator(a, b) < 0) {
storeUnsafe<T,T>(buffer, 1, b); // arr[1] = b;
storeUnsafe<T,T>(buffer, 0, a); // arr[0] = a;
STORE<T>(buffer, 1, b); // arr[1] = b;
STORE<T>(buffer, 0, a); // arr[0] = a;
}
return this;
}
@ -444,14 +445,14 @@ export class Array<T> {
var hasSeparator = sepLen != 0;
if (value instanceof bool) {
if (!lastIndex) {
return select<string>("true", "false", loadUnsafe<T,bool>(buffer, 0));
return select<string>("true", "false", LOAD<T,bool>(buffer, 0));
}
let valueLen = 5; // max possible length of element len("false")
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,bool>(buffer, i);
value = LOAD<T,bool>(buffer, i);
valueLen = 4 + <i32>(!value);
copyUnsafeString(result, offset, select<string>("true", "false", value), 0, valueLen);
offset += valueLen;
@ -460,7 +461,7 @@ export class Array<T> {
offset += sepLen;
}
}
value = loadUnsafe<T,bool>(buffer, lastIndex);
value = LOAD<T,bool>(buffer, lastIndex);
valueLen = 4 + <i32>(!value);
copyUnsafeString(result, offset, select<string>("true", "false", value), 0, valueLen);
offset += valueLen;
@ -473,21 +474,21 @@ export class Array<T> {
return out;
} else if (isInteger<T>()) {
if (!lastIndex) {
return changetype<string>(itoa<T>(loadUnsafe<T,T>(buffer, 0)));
return changetype<string>(itoa<T>(LOAD<T>(buffer, 0)));
}
const valueLen = (sizeof<T>() <= 4 ? 10 : 20) + <i32>isSigned<T>();
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,T>(buffer, i);
value = LOAD<T>(buffer, i);
offset += itoa_stream<T>(changetype<usize>(result), offset, value);
if (hasSeparator) {
copyUnsafeString(result, offset, separator, 0, sepLen);
offset += sepLen;
}
}
value = loadUnsafe<T,T>(buffer, lastIndex);
value = LOAD<T>(buffer, lastIndex);
offset += itoa_stream<T>(changetype<usize>(result), offset, value);
let out = result;
if (estLen > offset) {
@ -497,21 +498,21 @@ export class Array<T> {
return out;
} else if (isFloat<T>()) {
if (!lastIndex) {
return changetype<string>(dtoa(loadUnsafe<T,f64>(buffer, 0)));
return changetype<string>(dtoa(LOAD<T,f64>(buffer, 0)));
}
const valueLen = MAX_DOUBLE_LENGTH;
let estLen = (valueLen + sepLen) * lastIndex + valueLen;
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,f64>(buffer, i);
value = LOAD<T,f64>(buffer, i);
offset += dtoa_stream(changetype<usize>(result), offset, value);
if (hasSeparator) {
copyUnsafeString(result, offset, separator, 0, sepLen);
offset += sepLen;
}
}
value = loadUnsafe<T,f64>(buffer, lastIndex);
value = LOAD<T,f64>(buffer, lastIndex);
offset += dtoa_stream(changetype<usize>(result), offset, value);
let out = result;
if (estLen > offset) {
@ -521,16 +522,16 @@ export class Array<T> {
return out;
} else if (isString<T>()) {
if (!lastIndex) {
return loadUnsafe<T,string>(buffer, 0);
return LOAD<string>(buffer, 0);
}
let estLen = 0;
for (let i = 0, len = lastIndex + 1; i < len; ++i) {
estLen += loadUnsafe<T,string>(buffer, i).length;
estLen += LOAD<string>(buffer, i).length;
}
let offset = 0;
let result = allocateUnsafeString(estLen + sepLen * lastIndex);
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,String>(buffer, i);
value = LOAD<string>(buffer, i);
if (value) {
let valueLen = value.length; // tslint:disable-line:no-unsafe-any
copyUnsafeString(result, offset, value, 0, valueLen); // tslint:disable-line:no-unsafe-any
@ -541,7 +542,7 @@ export class Array<T> {
offset += sepLen;
}
}
value = loadUnsafe<T,String>(buffer, lastIndex);
value = LOAD<string>(buffer, lastIndex);
if (value) {
let valueLen = value.length; // tslint:disable-line:no-unsafe-any
copyUnsafeString(result, offset, value, 0, valueLen); // tslint:disable-line:no-unsafe-any
@ -549,15 +550,15 @@ export class Array<T> {
return result;
} else if (isArray<T>()) {
if (!lastIndex) {
value = loadUnsafe<T,T>(buffer, 0);
value = LOAD<T>(buffer, 0);
return value ? value.join(separator) : ""; // tslint:disable-line:no-unsafe-any
}
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,T>(buffer, i);
value = LOAD<T>(buffer, i);
if (value) result += value.join(separator); // tslint:disable-line:no-unsafe-any
if (hasSeparator) result += separator;
}
value = loadUnsafe<T,T>(buffer, lastIndex);
value = LOAD<T>(buffer, lastIndex);
if (value) result += value.join(separator); // tslint:disable-line:no-unsafe-any
return result;
} else if (isReference<T>()) { // References
@ -567,7 +568,7 @@ export class Array<T> {
let result = allocateUnsafeString(estLen);
let offset = 0;
for (let i = 0; i < lastIndex; ++i) {
value = loadUnsafe<T,T>(buffer, i);
value = LOAD<T>(buffer, i);
if (value) {
copyUnsafeString(result, offset, changetype<String>("[object Object]"), 0, valueLen);
offset += valueLen;
@ -577,7 +578,7 @@ export class Array<T> {
offset += sepLen;
}
}
if (loadUnsafe<T,T>(buffer, lastIndex)) {
if (LOAD<T>(buffer, lastIndex)) {
copyUnsafeString(result, offset, changetype<String>("[object Object]"), 0, valueLen);
offset += valueLen;
}

View File

@ -365,6 +365,8 @@ declare namespace f64 {
/** Converts A string to an integer. */
export function parseInt(string: string, radix?: i32): f64;
}
/** Macro type evaluating to the underlying native WebAssembly type. */
declare type NATIVE<T> = T;
// User-defined diagnostic macros

View File

@ -1,6 +1,6 @@
import {
loadUnsafeWithOffset,
storeUnsafeWithOffset
LOAD,
STORE
} from "./arraybuffer";
import {
@ -52,15 +52,15 @@ export function insertionSort<T>(
comparator: (a: T, b: T) => i32
): void {
for (let i = 0; i < length; i++) {
let a = loadUnsafeWithOffset<T,T>(buffer, i, byteOffset); // a = arr[i]
let a = LOAD<T>(buffer, i, byteOffset); // a = arr[i]
let j = i - 1;
while (j >= 0) {
let b = loadUnsafeWithOffset<T,T>(buffer, j, byteOffset); // b = arr[j]
let b = LOAD<T>(buffer, j, byteOffset); // b = arr[j]
if (comparator(a, b) < 0) {
storeUnsafeWithOffset<T,T>(buffer, j-- + 1, b, byteOffset); // arr[j + 1] = b
STORE<T>(buffer, j-- + 1, b, byteOffset); // arr[j + 1] = b
} else break;
}
storeUnsafeWithOffset<T,T>(buffer, j + 1, a, byteOffset); // arr[j + 1] = a
STORE<T>(buffer, j + 1, a, byteOffset); // arr[j + 1] = a
}
}
@ -84,37 +84,37 @@ export function weakHeapSort<T>(
while ((j & 1) == (load<u32>(bitset + (j >> 6 << shift32)) >> (j >> 1 & 31) & 1)) j >>= 1;
let p = j >> 1;
let a = loadUnsafeWithOffset<T,T>(buffer, p, byteOffset); // a = arr[p]
let b = loadUnsafeWithOffset<T,T>(buffer, i, byteOffset); // b = arr[i]
let a = LOAD<T>(buffer, p, byteOffset); // a = arr[p]
let b = LOAD<T>(buffer, i, byteOffset); // b = arr[i]
if (comparator(a, b) < 0) {
store<u32>(
bitset + (i >> 5 << shift32),
load<u32>(bitset + (i >> 5 << shift32)) ^ (1 << (i & 31))
);
storeUnsafeWithOffset<T,T>(buffer, i, a, byteOffset); // arr[i] = a
storeUnsafeWithOffset<T,T>(buffer, p, b, byteOffset); // arr[p] = b
STORE<T>(buffer, i, a, byteOffset); // arr[i] = a
STORE<T>(buffer, p, b, byteOffset); // arr[p] = b
}
}
for (let i = length - 1; i >= 2; i--) {
let a = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset);
storeUnsafeWithOffset<T,T>(buffer, 0, loadUnsafeWithOffset<T,T>(buffer, i, byteOffset), byteOffset);
storeUnsafeWithOffset<T,T>(buffer, i, a, byteOffset);
let a = LOAD<T>(buffer, 0, byteOffset);
STORE<T>(buffer, 0, LOAD<T>(buffer, i, byteOffset), byteOffset);
STORE<T>(buffer, i, a, byteOffset);
let x = 1, y: i32;
while ((y = (x << 1) + ((load<u32>(bitset + (x >> 5 << shift32)) >> (x & 31)) & 1)) < i) x = y;
while (x > 0) {
a = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset); // a = arr[0]
let b = loadUnsafeWithOffset<T,T>(buffer, x, byteOffset); // b = arr[x]
a = LOAD<T>(buffer, 0, byteOffset); // a = arr[0]
let b = LOAD<T>(buffer, x, byteOffset); // b = arr[x]
if (comparator(a, b) < 0) {
store<u32>(
bitset + (x >> 5 << shift32),
load<u32>(bitset + (x >> 5 << shift32)) ^ (1 << (x & 31))
);
storeUnsafeWithOffset<T,T>(buffer, x, a, byteOffset); // arr[x] = a
storeUnsafeWithOffset<T,T>(buffer, 0, b, byteOffset); // arr[0] = b
STORE<T>(buffer, x, a, byteOffset); // arr[x] = a
STORE<T>(buffer, 0, b, byteOffset); // arr[0] = b
}
x >>= 1;
}
@ -122,7 +122,7 @@ export function weakHeapSort<T>(
memory.free(bitset);
var t = loadUnsafeWithOffset<T,T>(buffer, 1, byteOffset); // t = arr[1]
storeUnsafeWithOffset<T,T>(buffer, 1, loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset), byteOffset);
storeUnsafeWithOffset<T,T>(buffer, 0, t, byteOffset); // arr[0] = t
var t = LOAD<T>(buffer, 1, byteOffset); // t = arr[1]
STORE<T>(buffer, 1, LOAD<T>(buffer, 0, byteOffset), byteOffset);
STORE<T>(buffer, 0, t, byteOffset); // arr[0] = t
}

View File

@ -71,33 +71,13 @@ export function reallocateUnsafe(buffer: ArrayBuffer, newByteLength: i32): Array
// * `i32.load8` ^= `<i32>load<i8>(...)` that reads an i8 but returns an i32, or
// * `i64.load32_s` ^= `<i64>load<i32>(...)`) that reads a 32-bit as a 64-bit integer
//
// without having to emit an additional instruction for conversion purposes. This is useful for
// small integers only of course. When dealing with reference types like classes, both parameters
// are usually the same, even though it looks ugly.
//
// TODO: is there a better way to model this?
// without having to emit an additional instruction for conversion purposes. The second parameter
// can be omitted for references and other loads and stores that simply return the exact type.
@inline export function loadUnsafe<T,TOut>(buffer: ArrayBuffer, index: i32): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), HEADER_SIZE);
@inline export function LOAD<T,TOut = T>(buffer: ArrayBuffer, index: i32, byteOffset: i32 = 0): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()) + <usize>byteOffset, HEADER_SIZE);
}
@inline export function storeUnsafe<T,TIn>(buffer: ArrayBuffer, index: i32, value: TIn): void {
store<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()), value, HEADER_SIZE);
}
@inline export function loadUnsafeWithOffset<T,TOut>(
buffer: ArrayBuffer,
index: i32,
byteOffset: i32
): TOut {
return <TOut>load<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), HEADER_SIZE);
}
@inline export function storeUnsafeWithOffset<T,TIn>(
buffer: ArrayBuffer,
index: i32,
value: TIn,
byteOffset: i32
): void {
store<T>(changetype<usize>(buffer) + <usize>byteOffset + (<usize>index << alignof<T>()), value, HEADER_SIZE);
@inline export function STORE<T,TIn = T>(buffer: ArrayBuffer, index: i32, value: TIn, byteOffset: i32 = 0): void {
store<T>(changetype<usize>(buffer) + (<usize>index << alignof<T>()) + <usize>byteOffset, value, HEADER_SIZE);
}

View File

@ -7,7 +7,7 @@ import {
} from "./string";
import {
loadUnsafe
LOAD
} from "./arraybuffer";
export const MAX_DOUBLE_LENGTH = 28;
@ -124,7 +124,7 @@ export function decimalCount32(value: u32): u32 {
let t = l * 1233 >>> 12; // log10
let lutbuf = <ArrayBuffer>POWERS10().buffer_;
let power = loadUnsafe<u32,u32>(lutbuf, t);
let power = LOAD<u32>(lutbuf, t);
t -= <u32>(value < power);
return t + 1;
} else {
@ -154,7 +154,7 @@ export function decimalCount64(value: u64): u32 {
let t = l * 1233 >>> 12; // log10
let lutbuf = <ArrayBuffer>POWERS10().buffer_;
let power = loadUnsafe<u32,u64>(lutbuf, t - 10);
let power = LOAD<u32,u64>(lutbuf, t - 10);
t -= <u32>(value < 10000000000 * power);
return t + 1;
} else {
@ -188,8 +188,8 @@ function utoa32_lut(buffer: usize, num: u32, offset: usize): void {
let d1 = r / 100;
let d2 = r % 100;
let digits1 = loadUnsafe<u32,u64>(lutbuf, d1);
let digits2 = loadUnsafe<u32,u64>(lutbuf, d2);
let digits1 = LOAD<u32,u64>(lutbuf, d1);
let digits2 = LOAD<u32,u64>(lutbuf, d2);
offset -= 4;
store<u64>(buffer + (offset << 1), digits1 | (digits2 << 32), STRING_HEADER_SIZE);
@ -200,13 +200,13 @@ function utoa32_lut(buffer: usize, num: u32, offset: usize): void {
let d1 = num % 100;
num = t;
offset -= 2;
let digits = loadUnsafe<u32,u32>(lutbuf, d1);
let digits = LOAD<u32>(lutbuf, d1);
store<u32>(buffer + (offset << 1), digits, STRING_HEADER_SIZE);
}
if (num >= 10) {
offset -= 2;
let digits = loadUnsafe<u32,u32>(lutbuf, num);
let digits = LOAD<u32>(lutbuf, num);
store<u32>(buffer + (offset << 1), digits, STRING_HEADER_SIZE);
} else {
offset -= 1;
@ -231,14 +231,14 @@ function utoa64_lut(buffer: usize, num: u64, offset: usize): void {
let c1 = c / 100;
let c2 = c % 100;
let digits1 = loadUnsafe<u32,u64>(lutbuf, c1);
let digits2 = loadUnsafe<u32,u64>(lutbuf, c2);
let digits1 = LOAD<u32,u64>(lutbuf, c1);
let digits2 = LOAD<u32,u64>(lutbuf, c2);
offset -= 4;
store<u64>(buffer + (offset << 1), digits1 | (digits2 << 32), STRING_HEADER_SIZE);
digits1 = loadUnsafe<u32,u64>(lutbuf, b1);
digits2 = loadUnsafe<u32,u64>(lutbuf, b2);
digits1 = LOAD<u32,u64>(lutbuf, b1);
digits2 = LOAD<u32,u64>(lutbuf, b2);
offset -= 4;
store<u64>(buffer + (offset << 1), digits1 | (digits2 << 32), STRING_HEADER_SIZE);
@ -438,8 +438,8 @@ function getCachedPower(minExp: i32): void {
_K = 348 - (index << 3); // decimal exponent no need lookup table
var frcPowers = <ArrayBuffer>FRC_POWERS().buffer_;
var expPowers = <ArrayBuffer>EXP_POWERS().buffer_;
_frc_pow = loadUnsafe<u64,u64>(frcPowers, index);
_exp_pow = loadUnsafe<i16,i32>(expPowers, index);
_frc_pow = LOAD<u64>(frcPowers, index);
_exp_pow = LOAD<i16,i32>(expPowers, index);
}
@inline
@ -513,7 +513,7 @@ function genDigits(buffer: usize, w_frc: u64, w_exp: i32, mp_frc: u64, mp_exp: i
let tmp = ((<u64>p1) << one_exp) + p2;
if (tmp <= delta) {
_K += kappa;
grisuRound(buffer, len, delta, tmp, loadUnsafe<u32,u64>(powers10, kappa) << one_exp, wp_w_frc);
grisuRound(buffer, len, delta, tmp, LOAD<u32,u64>(powers10, kappa) << one_exp, wp_w_frc);
return len;
}
}
@ -529,7 +529,7 @@ function genDigits(buffer: usize, w_frc: u64, w_exp: i32, mp_frc: u64, mp_exp: i
--kappa;
if (p2 < delta) {
_K += kappa;
wp_w_frc *= loadUnsafe<u32,u64>(powers10, -kappa);
wp_w_frc *= LOAD<u32,u64>(powers10, -kappa);
grisuRound(buffer, len, delta, p2, one_frc, wp_w_frc);
return len;
}

View File

@ -2,21 +2,18 @@ import {
HEADER_SIZE as AB_HEADER_SIZE,
MAX_BLENGTH as AB_MAX_BLENGTH,
allocateUnsafe,
loadUnsafeWithOffset,
storeUnsafeWithOffset
LOAD,
STORE
} from "./arraybuffer";
import {
insertionSort,
weakHeapSort,
defaultComparator
weakHeapSort
} from "./array";
// The internal TypedArray class uses two type parameters for the same reason as `loadUnsafe` and
// `storeUnsafe` in 'internal/arraybuffer.ts'. See the documentation there for details.
/** Typed array base class. Not a global object. */
export abstract class TypedArray<T,TNative> {
export abstract class TypedArray<T> {
[key: number]: T; // compatibility only
readonly buffer: ArrayBuffer;
readonly byteOffset: i32;
@ -41,116 +38,142 @@ export abstract class TypedArray<T,TNative> {
@operator("[]")
protected __get(index: i32): T {
if (<u32>index >= <u32>(this.byteLength >>> alignof<T>())) throw new Error("Index out of bounds");
return loadUnsafeWithOffset<T,T>(this.buffer, index, this.byteOffset);
return LOAD<T>(this.buffer, index, this.byteOffset);
}
@inline @operator("{}")
protected __unchecked_get(index: i32): T {
return loadUnsafeWithOffset<T,T>(this.buffer, index, this.byteOffset);
return LOAD<T>(this.buffer, index, this.byteOffset);
}
@operator("[]=")
protected __set(index: i32, value: TNative): void {
protected __set(index: i32, value: NATIVE<T>): void {
if (<u32>index >= <u32>(this.byteLength >>> alignof<T>())) throw new Error("Index out of bounds");
storeUnsafeWithOffset<T,TNative>(this.buffer, index, value, this.byteOffset);
STORE<T,NATIVE<T>>(this.buffer, index, value, this.byteOffset);
}
@inline @operator("{}=")
protected __unchecked_set(index: i32, value: TNative): void {
storeUnsafeWithOffset<T,TNative>(this.buffer, index, value, this.byteOffset);
protected __unchecked_set(index: i32, value: NATIVE<T>): void {
STORE<T,NATIVE<T>>(this.buffer, index, value, this.byteOffset);
}
// copyWithin(target: i32, start: i32, end: i32 = this.length): this
}
fill(value: TNative, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
var buffer = this.buffer;
var byteOffset = this.byteOffset;
var len = this.length;
start = start < 0 ? max(len + start, 0) : min(start, len);
end = end < 0 ? max(len + end, 0) : min(end, len);
if (sizeof<T>() == 1) {
if (start < end) {
memory.fill(
changetype<usize>(buffer) + start + byteOffset + AB_HEADER_SIZE,
<u8>value,
<usize>(end - start)
);
}
} else {
for (; start < end; ++start) {
storeUnsafeWithOffset<T,TNative>(buffer, start, value, byteOffset);
}
}
return this;
}
@inline
subarray(begin: i32 = 0, end: i32 = i32.MAX_VALUE): TypedArray<T,TNative> {
var length = this.length;
if (begin < 0) begin = max(length + begin, 0);
else begin = min(begin, length);
if (end < 0) end = max(length + end, begin);
else end = max(min(end, length), begin);
var slice = memory.allocate(offsetof<this>());
store<usize>(slice, this.buffer, offsetof<this>("buffer"));
store<i32>(slice, this.byteOffset + (begin << alignof<T>()), offsetof<this>("byteOffset"));
store<i32>(slice, (end - begin) << alignof<T>(), offsetof<this>("byteLength"));
return changetype<this>(slice);
}
sort(comparator: (a: T, b: T) => i32 = defaultComparator<T>()): this {
var byteOffset = this.byteOffset;
var length = this.length;
if (length <= 1) return this;
var buffer = this.buffer;
if (length == 2) {
let a = loadUnsafeWithOffset<T,T>(buffer, 1, byteOffset);
let b = loadUnsafeWithOffset<T,T>(buffer, 0, byteOffset);
if (comparator(a, b) < 0) {
storeUnsafeWithOffset<T,T>(buffer, 1, b, byteOffset);
storeUnsafeWithOffset<T,T>(buffer, 0, a, byteOffset);
}
return this;
}
if (isReference<T>()) {
// TODO replace this to faster stable sort (TimSort) when it implemented
insertionSort<T>(buffer, byteOffset, length, comparator);
return this;
} else {
if (length < 256) {
insertionSort<T>(buffer, byteOffset, length, comparator);
} else {
weakHeapSort<T>(buffer, byteOffset, length, comparator);
}
return this;
}
}
/**
* TypedArray reduce implementation. This is a method that will be called from the parent,
* passing types down from the child class using the typed parameters TypedArrayType and
* ReturnType respectively. This implementation requires an initial value, and the direction.
* When direction is true, reduce will reduce from the right side.
*/
@inline
protected reduce_internal<TypedArrayType, ReturnType>(
callbackfn: (accumulator: ReturnType, value: T, index: i32, array: TypedArrayType) => ReturnType,
array: TypedArrayType,
initialValue: ReturnType,
direction: bool = false,
): ReturnType {
var index: i32 = direction ? this.length - 1 : 0;
var length: i32 = direction ? -1 : this.length;
while (index != length) {
initialValue = callbackfn(
initialValue,
this.__unchecked_get(index),
index,
array,
@inline
export function FILL<TArray extends TypedArray<T>, T>(
array: TArray,
value: NATIVE<T>,
start: i32,
end: i32
): TArray {
var buffer = array.buffer;
var byteOffset = array.byteOffset;
var len = array.length;
start = start < 0 ? max(len + start, 0) : min(start, len);
end = end < 0 ? max(len + end, 0) : min(end, len);
if (sizeof<T>() == 1) {
if (start < end) {
memory.fill(
changetype<usize>(buffer) + start + byteOffset + AB_HEADER_SIZE,
<u8>value,
<usize>(end - start)
);
index = direction ? index - 1 : index + 1;
}
return initialValue;
} else {
for (; start < end; ++start) {
STORE<T,NATIVE<T>>(buffer, start, value, byteOffset);
}
}
return array;
}
@inline
export function SORT<TArray extends TypedArray<T>, T>(
array: TArray,
comparator: (a: T, b: T) => i32
): TArray {
var byteOffset = array.byteOffset;
var length = array.length;
if (length <= 1) return array;
var buffer = array.buffer;
if (length == 2) {
let a = LOAD<T>(buffer, 1, byteOffset);
let b = LOAD<T>(buffer, 0, byteOffset);
if (comparator(a, b) < 0) {
STORE<T>(buffer, 1, b, byteOffset);
STORE<T>(buffer, 0, a, byteOffset);
}
return array;
}
if (isReference<T>()) {
// TODO replace this to faster stable sort (TimSort) when it implemented
insertionSort<T>(buffer, byteOffset, length, comparator);
return array;
} else {
if (length < 256) {
insertionSort<T>(buffer, byteOffset, length, comparator);
} else {
weakHeapSort<T>(buffer, byteOffset, length, comparator);
}
return array;
}
}
@inline
export function SUBARRAY<TArray extends TypedArray<T>, T>(
array: TArray,
begin: i32,
end: i32
): TArray {
var length = <i32>array.length;
if (begin < 0) begin = max(length + begin, 0);
else begin = min(begin, length);
if (end < 0) end = max(length + end, begin);
else end = max(min(end, length), begin);
var slice = memory.allocate(offsetof<TArray>());
store<usize>(slice, array.buffer, offsetof<TArray>("buffer"));
store<i32>(slice, <i32>array.byteOffset + (begin << alignof<T>()), offsetof<TArray>("byteOffset"));
store<i32>(slice, (end - begin) << alignof<T>(), offsetof<TArray>("byteLength"));
return changetype<TArray>(slice);
}
@inline
export function REDUCE<TArray extends TypedArray<T>, T, TRet>(
array: TArray,
callbackfn: (accumulator: TRet, value: T, index: i32, array: TArray) => TRet,
initialValue: TRet
): TRet {
var index = 0;
var length = <i32>array.length;
while (index != length) {
initialValue = callbackfn(
initialValue,
unchecked(array[index]),
index,
array,
);
++index;
}
return initialValue;
}
@inline
export function REDUCE_RIGHT<TArray extends TypedArray<T>, T, TRet>(
array: TArray,
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) {
initialValue = callbackfn(
initialValue,
unchecked(array[index]),
index,
array,
);
--index;
}
return initialValue;
}

View File

@ -11,7 +11,7 @@ import {
} from "./internal/string";
import {
storeUnsafe as storeUnsafeArray
STORE
} from "./internal/arraybuffer";
@sealed
@ -436,7 +436,7 @@ export class String {
),
HEADER_SIZE
);
storeUnsafeArray<String,String>(buffer, i, char);
STORE<String>(buffer, i, char);
}
return result;
} else if (!length) {

View File

@ -1,52 +1,77 @@
import {
TypedArray
TypedArray,
FILL,
SORT,
SUBARRAY,
REDUCE,
REDUCE_RIGHT
} from "./internal/typedarray";
export class Int8Array extends TypedArray<i8,i32> {
import {
defaultComparator
} from "./internal/array";
export class Int8Array extends TypedArray<i8> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i8>();
fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int8Array {
return FILL<Int8Array, i8>(this, value, start, end);
}
sort(comparator: (a: i8, b: i8) => i32 = defaultComparator<i8>()): Int8Array {
return SORT<Int8Array, i8>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int8Array {
return changetype<Int8Array>(super.subarray(begin, end));
return SUBARRAY<Int8Array, i8>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i8, index: i32, array: Int8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int8Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i8, index: i32, array: Int8Array) => T,
initialValue: T,
): T {
return REDUCE<Int8Array, i8, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i8, index: i32, array: Int8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int8Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i8, index: i32, array: Int8Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int8Array, i8, T>(this, callbackfn, initialValue);
}
}
export class Uint8Array extends TypedArray<u8,u32> {
export class Uint8Array extends TypedArray<u8> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u8>();
fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint8Array {
return FILL<Uint8Array, u8>(this, value, start, end);
}
sort(comparator: (a: u8, b: u8) => i32 = defaultComparator<u8>()): Uint8Array {
return SORT<Uint8Array, u8>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint8Array {
return changetype<Uint8Array>(super.subarray(begin, end));
return SUBARRAY<Uint8Array, u8>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u8, index: i32, array: Uint8Array) => T,
initialValue: T,
): T {
return REDUCE<Uint8Array, u8, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u8, index: i32, array: Uint8Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint8Array, u8, T>(this, callbackfn, initialValue);
}
}
export class Uint8ClampedArray extends TypedArray<u8,u32> {
export class Uint8ClampedArray extends Uint8Array {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u8>();
@inline @operator("[]=")
@ -58,202 +83,244 @@ export class Uint8ClampedArray extends TypedArray<u8,u32> {
protected __unchecked_set(index: i32, value: i32): void {
super.__unchecked_set(index, max(min(value, 255), 0));
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint8ClampedArray {
return changetype<Uint8ClampedArray>(super.subarray(begin, end));
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8ClampedArray) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8ClampedArray, ReturnType>(callbackfn, this, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u8, index: i32, array: Uint8ClampedArray) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint8ClampedArray, ReturnType>(callbackfn, this, initialValue, true);
}
}
export class Int16Array extends TypedArray<i16,i32> {
export class Int16Array extends TypedArray<i16> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i16>();
fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int16Array {
return FILL<Int16Array, i16>(this, value, start, end);
}
sort(comparator: (a: i16, b: i16) => i32 = defaultComparator<i16>()): Int16Array {
return SORT<Int16Array, i16>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int16Array {
return changetype<Int16Array>(super.subarray(begin, end));
return SUBARRAY<Int16Array, i16>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i16, index: i32, array: Int16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int16Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i16, index: i32, array: Int16Array) => T,
initialValue: T,
): T {
return REDUCE<Int16Array, i16, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i16, index: i32, array: Int16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int16Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i16, index: i32, array: Int16Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int16Array, i16, T>(this, callbackfn, initialValue);
}
}
export class Uint16Array extends TypedArray<u16,u32> {
export class Uint16Array extends TypedArray<u16> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u16>();
fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint16Array {
return FILL<Uint16Array, u16>(this, value, start, end);
}
sort(comparator: (a: u16, b: u16) => i32 = defaultComparator<u16>()): Uint16Array {
return SORT<Uint16Array, u16>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint16Array {
return changetype<Uint16Array>(super.subarray(begin, end));
return SUBARRAY<Uint16Array, u16>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u16, index: i32, array: Uint16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint16Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u16, index: i32, array: Uint16Array) => T,
initialValue: T,
): T {
return REDUCE<Uint16Array, u16, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u16, index: i32, array: Uint16Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint16Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u16, index: i32, array: Uint16Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint16Array, u16, T>(this, callbackfn, initialValue);
}
}
export class Int32Array extends TypedArray<i32,i32> {
export class Int32Array extends TypedArray<i32> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i32>();
fill(value: i32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int32Array {
return FILL<Int32Array, i32>(this, value, start, end);
}
sort(comparator: (a: i32, b: i32) => i32 = defaultComparator<i32>()): Int32Array {
return SORT<Int32Array, i32>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int32Array {
return changetype<Int32Array>(super.subarray(begin, end));
return SUBARRAY<Int32Array, i32>(this, begin, end);
}
/**
* @param callbackfn {function} - a function that reduces each value to a ReturnType
* @param initialValue {ReturnType} - the initial ReturnType value to be passed to the callbackfn
*/
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i32, index: i32, array: Int32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int32Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i32, index: i32, array: Int32Array) => T,
initialValue: T,
): T {
return REDUCE<Int32Array, i32, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i32, index: i32, array: Int32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int32Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i32, index: i32, array: Int32Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int32Array, i32, T>(this, callbackfn, initialValue);
}
}
export class Uint32Array extends TypedArray<u32,u32> {
export class Uint32Array extends TypedArray<u32> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u32>();
fill(value: u32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint32Array {
return FILL<Uint32Array, u32>(this, value, start, end);
}
sort(comparator: (a: u32, b: u32) => i32 = defaultComparator<u32>()): Uint32Array {
return SORT<Uint32Array, u32>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint32Array {
return changetype<Uint32Array>(super.subarray(begin, end));
return SUBARRAY<Uint32Array, u32>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u32, index: i32, array: Uint32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint32Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u32, index: i32, array: Uint32Array) => T,
initialValue: T,
): T {
return REDUCE<Uint32Array, u32, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u32, index: i32, array: Uint32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint32Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u32, index: i32, array: Uint32Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint32Array, u32, T>(this, callbackfn, initialValue);
}
}
export class Int64Array extends TypedArray<i64,i64> {
export class Int64Array extends TypedArray<i64> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<i64>();
fill(value: i64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Int64Array {
return FILL<Int64Array, i64>(this, value, start, end);
}
sort(comparator: (a: i64, b: i64) => i32 = defaultComparator<i64>()): Int64Array {
return SORT<Int64Array, i64>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Int64Array {
return changetype<Int64Array>(super.subarray(begin, end));
return SUBARRAY<Int64Array, i64>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i64, index: i32, array: Int64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int64Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: i64, index: i32, array: Int64Array) => T,
initialValue: T,
): T {
return REDUCE<Int64Array, i64, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: i64, index: i32, array: Int64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Int64Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: i64, index: i32, array: Int64Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Int64Array, i64, T>(this, callbackfn, initialValue);
}
}
export class Uint64Array extends TypedArray<u64,u64> {
export class Uint64Array extends TypedArray<u64> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<u64>();
fill(value: u64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Uint64Array {
return FILL<Uint64Array, u64>(this, value, start, end);
}
sort(comparator: (a: u64, b: u64) => i32 = defaultComparator<u64>()): Uint64Array {
return SORT<Uint64Array, u64>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Uint64Array {
return changetype<Uint64Array>(super.subarray(begin, end));
return SUBARRAY<Uint64Array, u64>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u64, index: i32, array: Uint64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint64Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: u64, index: i32, array: Uint64Array) => T,
initialValue: T,
): T {
return REDUCE<Uint64Array, u64, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: u64, index: i32, array: Uint64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Uint64Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: u64, index: i32, array: Uint64Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Uint64Array, u64, T>(this, callbackfn, initialValue);
}
}
export class Float32Array extends TypedArray<f32,f32> {
export class Float32Array extends TypedArray<f32> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<f32>();
fill(value: f32, start: i32 = 0, end: i32 = i32.MAX_VALUE): Float32Array {
return FILL<Float32Array, f32>(this, value, start, end);
}
sort(comparator: (a: f32, b: f32) => i32 = defaultComparator<f32>()): Float32Array {
return SORT<Float32Array, f32>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Float32Array {
return changetype<Float32Array>(super.subarray(begin, end));
return SUBARRAY<Float32Array, f32>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f32, index: i32, array: Float32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float32Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: f32, index: i32, array: Float32Array) => T,
initialValue: T,
): T {
return REDUCE<Float32Array, f32, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f32, index: i32, array: Float32Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float32Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: f32, index: i32, array: Float32Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Float32Array, f32, T>(this, callbackfn, initialValue);
}
}
export class Float64Array extends TypedArray<f64,f64> {
export class Float64Array extends TypedArray<f64> {
static readonly BYTES_PER_ELEMENT: usize = sizeof<f64>();
fill(value: f64, start: i32 = 0, end: i32 = i32.MAX_VALUE): Float64Array {
return FILL<Float64Array, f64>(this, value, start, end);
}
sort(comparator: (a: f64, b: f64) => i32 = defaultComparator<f64>()): Float64Array {
return SORT<Float64Array, f64>(this, comparator);
}
subarray(begin: i32 = 0, end: i32 = 0x7fffffff): Float64Array {
return changetype<Float64Array>(super.subarray(begin, end));
return SUBARRAY<Float64Array, f64>(this, begin, end);
}
reduce<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f64, index: i32, array: Float64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float64Array, ReturnType>(callbackfn, this, initialValue);
reduce<T>(
callbackfn: (accumulator: T, value: f64, index: i32, array: Float64Array) => T,
initialValue: T,
): T {
return REDUCE<Float64Array, f64, T>(this, callbackfn, initialValue);
}
reduceRight<ReturnType>(
callbackfn: (accumulator: ReturnType, value: f64, index: i32, array: Float64Array) => ReturnType,
initialValue: ReturnType,
): ReturnType {
return super.reduce_internal<Float64Array, ReturnType>(callbackfn, this, initialValue, true);
reduceRight<T>(
callbackfn: (accumulator: T, value: f64, index: i32, array: Float64Array) => T,
initialValue: T,
): T {
return REDUCE_RIGHT<Float64Array, f64, T>(this, callbackfn, initialValue);
}
}