[js/common] allow creating (u)int64 tensors in 2 ways (#16541)

### Description
allow creating (u)int64 tensors from either a number array or a bigint
array.

before:

```js
// TypeScript think is good, but actually does not work
// runtime error: Uncaught TypeError: Cannot convert 1 to a BigInt
const myTensor1 = new Tensor('int64', [1, 2, 3, 4], [2, 2]);

// runtime good, but TypeScript thinks myTensor2 is a string tensor
const myTensor2 = new Tensor('int64', [1n, 2n, 3n, 4n], [2, 2]);
```

after:
```js
// both work at runtime and TypeScript populates the correct types
const myTensor1 = new Tensor('int64', [1, 2, 3, 4], [2, 2]);
const myTensor2 = new Tensor('int64', [1n, 2n, 3n, 4n], [2, 2]);
```
This commit is contained in:
Yulong Wang 2023-07-11 21:07:36 -07:00 committed by GitHub
parent 8e393e0b8c
commit ecca11340a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 23 deletions

View file

@ -103,11 +103,24 @@ export class Tensor implements TensorInterface {
// Throw error here because when user try to use number array as data,
// e.g. new Tensor('float16', [1, 2, 3, 4], dims)), it will actually call
// Uint16Array.from(arg1) which generates wrong data.
throw new TypeError(`Unsupported tensor type: ${arg0}.`);
throw new TypeError(
'Creating a float16 tensor from number array is not supported. Please use Uint16Array as data.');
} else if (arg0 === 'uint64' || arg0 === 'int64') {
// use 'as any' here because:
// 1. TypeScript's check on type of 'Array.isArray()' does not work with readonly arrays.
// see https://github.com/microsoft/TypeScript/issues/17002
// 2. TypeScript's check on union type of '(BigInt64ArrayConstructor|BigUint64ArrayConstructor).from()' does
// not accept parameter mapFn.
// 3. parameters of 'SupportedTypedArrayConstructors.from()' does not match the requirement of the union
// type.
// assume 'arg1' is of type "readonly number[]|readonly bigint[]" here.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data = (typedArrayConstructor as any).from(arg1, BigInt);
} else {
// use 'as any' here because TypeScript's check on type of 'SupportedTypedArrayConstructors.from()' produces
// incorrect results.
// 'typedArrayConstructor' should be one of the typed array prototype objects.
// assume 'arg1' is of type "readonly number[]" here.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data = (typedArrayConstructor as any).from(arg1);
}

View file

@ -88,7 +88,7 @@ export interface TensorConstructor {
* Construct a new string tensor object from the given type, data and dims.
*
* @param type - Specify the element type.
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(type: 'string', data: Tensor.DataTypeMap['string']|readonly string[],
@ -98,19 +98,30 @@ export interface TensorConstructor {
* Construct a new bool tensor object from the given type, data and dims.
*
* @param type - Specify the element type.
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(type: 'bool', data: Tensor.DataTypeMap['bool']|readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>;
/**
* Construct a new 64-bit integer typed tensor object from the given type, data and dims.
*
* @param type - Specify the element type.
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new<T extends 'uint64'|'int64'>(
type: T, data: Tensor.DataTypeMap[T]|readonly bigint[]|readonly number[],
dims?: readonly number[]): TypedTensor<T>;
/**
* Construct a new numeric tensor object from the given type, data and dims.
*
* @param type - Specify the element type.
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new<T extends Exclude<Tensor.Type, 'string'|'bool'>>(
new<T extends Exclude<Tensor.Type, 'string'|'bool'|'uint64'|'int64'>>(
type: T, data: Tensor.DataTypeMap[T]|readonly number[], dims?: readonly number[]): TypedTensor<T>;
// #endregion
@ -119,7 +130,7 @@ export interface TensorConstructor {
/**
* Construct a new float32 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Float32Array, dims?: readonly number[]): TypedTensor<'float32'>;
@ -127,7 +138,7 @@ export interface TensorConstructor {
/**
* Construct a new int8 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Int8Array, dims?: readonly number[]): TypedTensor<'int8'>;
@ -135,7 +146,7 @@ export interface TensorConstructor {
/**
* Construct a new uint8 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Uint8Array, dims?: readonly number[]): TypedTensor<'uint8'>;
@ -143,7 +154,7 @@ export interface TensorConstructor {
/**
* Construct a new uint16 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Uint16Array, dims?: readonly number[]): TypedTensor<'uint16'>;
@ -151,7 +162,7 @@ export interface TensorConstructor {
/**
* Construct a new int16 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Int16Array, dims?: readonly number[]): TypedTensor<'int16'>;
@ -159,7 +170,7 @@ export interface TensorConstructor {
/**
* Construct a new int32 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Int32Array, dims?: readonly number[]): TypedTensor<'int32'>;
@ -167,7 +178,7 @@ export interface TensorConstructor {
/**
* Construct a new int64 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: BigInt64Array, dims?: readonly number[]): TypedTensor<'int64'>;
@ -175,7 +186,7 @@ export interface TensorConstructor {
/**
* Construct a new string tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: readonly string[], dims?: readonly number[]): TypedTensor<'string'>;
@ -183,7 +194,7 @@ export interface TensorConstructor {
/**
* Construct a new bool tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: readonly boolean[], dims?: readonly number[]): TypedTensor<'bool'>;
@ -191,7 +202,7 @@ export interface TensorConstructor {
/**
* Construct a new float64 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Float64Array, dims?: readonly number[]): TypedTensor<'float64'>;
@ -199,7 +210,7 @@ export interface TensorConstructor {
/**
* Construct a new uint32 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Uint32Array, dims?: readonly number[]): TypedTensor<'uint32'>;
@ -207,7 +218,7 @@ export interface TensorConstructor {
/**
* Construct a new uint64 tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: BigUint64Array, dims?: readonly number[]): TypedTensor<'uint64'>;
@ -220,15 +231,16 @@ export interface TensorConstructor {
* Construct a new tensor object from the given type, data and dims.
*
* @param type - Specify the element type.
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(type: Tensor.Type, data: Tensor.DataType|readonly number[]|readonly boolean[], dims?: readonly number[]): Tensor;
new(type: Tensor.Type, data: Tensor.DataType|readonly number[]|readonly string[]|readonly bigint[]|readonly boolean[],
dims?: readonly number[]): Tensor;
/**
* Construct a new tensor object from the given data and dims.
*
* @param data - Specify the tensor data
* @param data - Specify the tensor data.
* @param dims - Specify the dimension of the tensor. If omitted, a 1-D tensor is assumed.
*/
new(data: Tensor.DataType, dims?: readonly number[]): Tensor;