import { tester } from './core.mjs';
class NumberArray extends Array {}
class StringArray extends Array {}
class BooleanArray extends Array {}
let Any = x => x;
let lookup = new WeakMap();
/**
* @class
*/
export class Dtype {
#array;
/**
*
* @param {Function} type
* @param {class} array
* @param {string} name
*/
constructor(type = Any, array = Array, name = `${type}`) {
/** @member {string} */
this.name = name;
/** @member {Function} */
this.type = type;
this.#array = array;
lookup.set(type, name);
lookup.set(array, name);
}
new(size, data = null) {
let array = new this.#array(size);
if (data != null) {
if (array.set != undefined) {
array.set(data);
} else {
for (let i = 0; i < data.length; i++) {
array[i] = data[i];
}
}
}
return array;
}
toString() {
return `dtype('${this.name}')`;
}
valueOf() {
return this.type;
}
}
let dtypes = {
int8: new Dtype(Number, Int8Array, 'int8'),
uint8: new Dtype(Number, Uint8Array, 'uint8'),
int16: new Dtype(Number, Int16Array, 'int16'),
uint16: new Dtype(Number, Uint16Array, 'uint16'),
int32: new Dtype(Number, Int32Array, 'int32'),
uint32: new Dtype(Number, Uint32Array, 'uint32'),
float32: new Dtype(Number, Float32Array, 'float32'),
float64: new Dtype(Number, Float64Array, 'float64'),
// this is just a hinted container. no data conversion is involved.
boolean: new Dtype(Boolean, BooleanArray, 'boolean'),
number: new Dtype(Number, NumberArray, 'number'),
string: new Dtype(String, StringArray, 'string'),
object: new Dtype(Any, Array, 'object'),
};
Object.assign(dtypes, {
int: dtypes.number,
float: dtypes.number,
});
/**
* @param {Dtype|string|Function} dtype
* @param {function} array
* @param {string} name
* @returns {Dtype}
* @example
* dtype('number') == dtype(Number) // by string or value type function
* @example
* dtype('int8') == dtype(Int8Array) // by string or TypedArray constructor
* @example
* dtype('object') == dtype(Array) // default type and container
* @example
* dtype(dtype('object')) == dtype('object') // wraps dtype
* @example
* dtype() or dtype(null) // throws an error
*/
export function dtype(dtype = 'object', array = undefined, name = undefined) {
// dtype ??= 'object';
if (typeof dtype == 'string') {
if (!Object.hasOwn(dtypes, dtype)) {
throw new Error(`${dtype} is not supported`);
}
return dtypes[dtype];
}
if (dtype instanceof Dtype) return dtype;
if (lookup.has(dtype)) return dtypes[lookup.get(dtype)];
return (dtypes[name] = new Dtype(dtype, array, name));
}
export const dtype_ = dtype;
process.env.PRODUCTION ||
tester
.add(
dtype,
() => dtype('number'),
() => dtype('number')
)
.add(
dtype,
() => dtype(Number),
() => dtype('number')
)
.add(
dtype,
() => dtype(Int16Array),
() => dtype('int16')
);