import * as utils from "./utils.js";
import * as gc from "./gc.js";
import * as wa from "wasmarrays.js";
/**
* Wrapper around a matrix allocated on the Wasm heap.
* @hideconstructor
*/
export class ScranMatrix {
#id;
#matrix;
constructor(id, raw) {
this.#id = id;
this.#matrix = raw;
return;
}
/**
* Create a dense matrix from an existing Wasm-allocated buffer.
*
* @param {number} rows - Number of rows.
* @param {number} columns - Number of columns.
* @param {Float64WasmArray} contents - Array of matrix contents.
* @param {object} [options={}] - Optional parameters.
* @param {boolean} [options.columnMajor=true] - Whether the array in `contents` is column-major.
* @param {boolean} [options.copy=true] - Whether to copy `contents` when constructing the {@linkplain ScranMatrix}.
* If `false`, the returned {@linkplain ScranMatrix} will refer to the same allocation as `contents`,
* so callers should make sure that it does not outlive `contents`.
*
* @return {ScranMatrix} A {@linkplain ScranMatrix} containing the matrix contents.
*/
static createDenseMatrix(rows, columns, contents, { columnMajor = true , copy = true } = {}) {
if (!(contents instanceof wa.Float64WasmArray)) {
throw new Error("'contents' should be a Float64WasmArray");
}
if (contents.length != rows * columns) {
throw new Error("length of 'contents' should equal the product of 'rows' and 'columns'");
}
return gc.call(module => new module.NumericMatrix(rows, columns, contents.offset, columnMajor, copy), ScranMatrix);
}
/**
* @return {ScranMatrix} A clone of the current ScranMatrix instance.
* This can be freed independently of the current instance.
*/
clone() {
return gc.call(
module => this.#matrix.clone(),
ScranMatrix
);
}
// Internal use only, not documented.
get matrix() {
return this.#matrix;
}
/**
* @return {number} Number of rows in the matrix.
*/
numberOfRows() {
return this.#matrix.nrow();
}
/**
* @return {number} Number of columns in the matrix.
*/
numberOfColumns() {
return this.#matrix.ncol();
}
/**
* @param {number} i - Index of the row to extract.
* This should be a non-negative integer less than {@linkcode ScranMatrix#numberOfRows numberOfRows}.
* @param {object} [options={}] - Optional parameters.
* @param {?Float64WasmArray} [options.buffer=null] - Buffer for storing the extracted data.
* If supplied, this should have length equal to {@linkcode ScranMatrix#numberOfColumns numberOfColumns}.
*
* @return {Float64Array} An array containing the contents of row `i`.
*
* If `buffer` was supplied, the returned array is a view into it.
* Note that this may be invalidated on the next allocation on the Wasm heap.
*/
row(i, { buffer = null } = {}) {
if (buffer != null) {
this.#matrix.row(i, buffer.offset);
return buffer.array();
} else {
var output;
buffer = utils.createFloat64WasmArray(this.#matrix.ncol());
try {
this.#matrix.row(i, buffer.offset);
output = buffer.slice();
} finally {
buffer.free();
}
return output;
}
}
/**
* @param {number} i - Index of the column to extract.
* This should be a non-negative integer less than {@linkcode ScranMatrix#numberOfColumns numberOfColumns}.
* @param {object} [options={}] - Optional parameters.
* @param {?Float64WasmArray} [options.buffer=null] - Buffer for storing the extracted data.
* If supplied, this should have length equal to {@linkcode ScranMatrix#numberOfRows numberOfRows}.
*
* @return {Float64Array} An array containing the contents of column `i`.
*
* If `buffer` was supplied, the returned array is a view into it.
* Note that this may be invalidated on the next allocation on the Wasm heap.
*/
column(i, { buffer = null } = {}) {
if (buffer != null) {
this.#matrix.column(i, buffer.offset);
return buffer.array();
} else {
var output;
buffer = utils.createFloat64WasmArray(this.#matrix.nrow());
try {
this.#matrix.column(i, buffer.offset);
output = buffer.slice();
} finally {
buffer.free();
}
return output;
}
}
/**
* Free the memory on the Wasm heap for this.#matrix.
* This invalidates this object and all of its references.
*/
free() {
if (this.#matrix !== null) {
gc.release(this.#id);
this.#matrix = null;
}
return;
}
/**
* @return {boolean} Whether the matrix is sparse.
*/
isSparse() {
return this.#matrix.sparse();
}
}