mathjslab
Version:
MathJSLab - An interpreter with language syntax like MATLAB®/Octave, ISBN 978-65-00-82338-7.
2,052 lines • 83.8 kB
TypeScript
import type { TUnaryOperationLeftName, TBinaryOperationName } from './ComplexInterface';
import { ComplexType } from './Complex';
import { CharString } from './CharString';
import type { RuntimeDisplay, RuntimeEvaluationContext } from './RuntimeDisplay';
/**
* Object-like runtime values that may be stored directly inside a `MultiArray`.
*
* This structural type intentionally avoids importing concrete runtime classes
* such as function handles, class instances, class metadata, and bound methods.
* Array storage only needs the shared runtime value contract; behavior-specific
* dispatch remains in the corresponding runtime modules.
*/
type RuntimeObjectElement = object & {
type: number;
parent?: unknown;
copy?: () => unknown;
};
/**
* Scalar runtime values that may be stored directly inside a `MultiArray`.
*
* Nested `MultiArray` values are handled by `ElementType` because MATLAB cell
* arrays can contain arrays as elements, while numeric arrays generally store
* scalar `ComplexType` values.
*/
type Elements = ComplexType | CharString | RuntimeObjectElement;
/**
* Runtime value accepted in array slots and expression evaluation results.
*
* `null` and `undefined` are tolerated because parser/evaluator paths use empty
* slots while constructing MATLAB-like empty arrays, structure fields, and
* omitted values.
*/
type ElementType<ELEMENT = Elements> = MultiArray | ELEMENT | null | undefined;
/**
* Reduce factory function types.
*/
type ReduceComparisonType = 'lt' | 'gt';
type ReduceType = 'reduce' | 'cumulative' | 'cumcomparison' | 'comparison';
type ReduceElementType<ELEMENT = Elements> = ElementType<ELEMENT>;
type ReduceCallbackType = (prev: ReduceElementType, curr: ReduceElementType, index?: number) => ReduceElementType;
type ReduceCallbackOrComparisonType = ReduceCallbackType | ReduceComparisonType;
type ReduceInitialType = ReduceElementType;
type ReduceReduceHandlerType = (M: ReduceElementType, DIM?: ReduceElementType) => ReduceElementType;
type ReduceComparisonHandlerType<ELEMENT = Elements> = (...args: ElementType<ELEMENT>[]) => MultiArray<ELEMENT> | NodeReturnList | undefined;
type ReduceHandlerType = ReduceReduceHandlerType | ReduceComparisonHandlerType;
type ReturnHandlerResult = {
length: number;
} & Record<string, ElementType | number | undefined>;
type ReturnSelector = (evaluated: ReturnHandlerResult, index: number) => ElementType;
type ReturnHandler = (length: number) => ReturnHandlerResult;
type ReducedArrayLine = ElementType[];
type NodeReturnList = {
type: 'RETLIST';
selector: ReturnSelector;
handler?: ReturnHandler;
parent?: unknown;
};
type IndexAssignmentScope = {
resolveName(name: string): {
node?: unknown;
} | undefined;
defineName(name: string, node: ElementType): {
node?: unknown;
};
};
/**
* Runtime values accepted by native MATLAB/Octave array indexing.
*
* Parser nodes, structures, class objects, and arbitrary expression results
* must be reduced or rejected before they enter the low-level indexing engine.
*/
type IndexArgument = ComplexType | MultiArray;
/**
* MATLAB/Octave-like multidimensional array container.
*
* `dimension` stores MATLAB-style shape metadata: `[rows, columns, pages, ...]`.
* The backing `array` is a two-dimensional row-major page-flattened structure:
* rows for all pages are stacked into the first dimension, while columns remain
* the second dimension. Indexing helpers translate MATLAB column-major logical
* indexing semantics into this internal representation.
*
* `isCell` distinguishes ordinary arrays from cell arrays. Cell arrays preserve
* element identity and may contain nested arrays; ordinary arrays usually
* contain scalar numeric/logical/string/runtime values.
*/
declare class MultiArray<ELEMENT = Elements> {
/**
* MATLAB-style dimensions (`[rows, columns, pages, blocks, ...]`).
*/
dimension: number[];
/**
* Dimensions excluding the column axis (`[rows, pages, blocks, ...]`).
*/
get dimensionR(): number[];
/**
* Row-major page-flattened storage.
*/
array: ElementType<ELEMENT>[][];
/**
* Runtime type tag inferred from contained values.
*/
type: number;
/**
* Test whether an object is a `MultiArray` instance.
*
* @param obj Object to test.
* @returns `true` when `obj` is a `MultiArray`.
*/
static readonly isInstanceOf: (obj: unknown) => obj is MultiArray;
/**
* Test whether a runtime value can be consumed directly by native indexing.
*
* Valid subscripts are numeric/logical scalar values or numeric/logical
* arrays. Colon ranges are represented as numeric `MultiArray` instances
* before this boundary is reached.
*
* @param value Candidate subscript value.
* @returns True when `value` is a native array-index argument.
*/
static isIndexArgument(value: unknown): value is IndexArgument;
/**
* Validate a list of values before passing them into the indexing engine.
*
* Keeping this check in `MultiArray` makes every caller share the same
* supported-subscript contract while preserving specialized error handlers
* at higher interpreter layers.
*
* @param values Candidate subscript values.
* @param role Diagnostic label used in thrown errors.
* @returns The same values narrowed to native index arguments.
* @throws EvalError When any value is not a valid native subscript.
*/
static indexArguments(values: unknown[], role?: string): IndexArgument[];
/**
* Read an array element that must be a numeric scalar.
*
* Native numeric/logical array operations should only reach this helper for
* arrays whose storage is known to be numeric. The explicit guard keeps
* malformed runtime arrays from failing later through opaque method calls.
*
* @param value Candidate array element.
* @param role Diagnostic operation name.
* @returns Numeric scalar element.
*/
private static readonly numericElement;
/** Runtime tag for logical arrays. */
static readonly LOGICAL: number;
/** Runtime tag for real numeric arrays. */
static readonly REAL: number;
/** Runtime tag for complex numeric arrays. */
static readonly COMPLEX: number;
/** Runtime tag for string arrays. */
static readonly STRING = 3;
/** Runtime tag for structure arrays. */
static readonly STRUCTURE = 4;
/** Runtime tag for function-handle arrays. */
static readonly FUNCTION_HANDLE = 5;
/**
* Whether this array uses cell-array semantics.
*/
isCell: boolean;
/**
* Optional AST-style parent pointer used by generic value handling.
*/
parent?: unknown;
private static readonly invalidStructureReferenceMessage;
/**
* Create a multidimensional array.
*
* Scalar object fills are copied when they have value semantics (`MultiArray`,
* `Structure`, and value-class instances). Primitive/scalar immutable values
* are reused. Function fills receive MATLAB-style subscripts.
*
* @param shape Dimensions ([rows, columns, pages, blocks, ...]).
* @param fill Fill value, fill callback, or row-major storage.
* @param iscell Whether to create a cell array.
*/
constructor(shape?: number[], fill?: ElementType | ((...dims: number[]) => ElementType) | ElementType[][], iscell?: boolean);
/**
* Check if object is a scalar.
* @param obj Any object.
* @returns `true` if object is a scalar. false otherwise.
*/
static readonly isScalar: (obj: unknown) => boolean;
/**
* Check if object is a MultiArray and it is a row vector.
* @param obj Any object.
* @returns `true` if object is a row vector. false otherwise.
*/
static readonly isRowVector: (obj: unknown) => boolean;
/**
* Convert a flat value list into a 1-by-N row vector.
*
* @param vector Values to store in row order.
* @returns Row-vector `MultiArray`.
*/
static readonly toRowVector: (vector: ElementType[]) => MultiArray;
/**
* Return the first row of a row-vector array.
*
* @param vector Row-vector `MultiArray`.
* @returns Backing first row.
*/
static readonly fromRowVector: (vector: MultiArray) => ElementType[];
/**
* Check if object is a MultiArray and it is a row vector.
* @param obj Any object.
* @returns `true` if object is a row vector. false otherwise.
*/
static readonly isColumnVector: (obj: unknown) => boolean;
/**
* Convert a flat value list into an N-by-1 column vector.
*
* @param vector Values to store in column order.
* @returns Column-vector `MultiArray`.
*/
static readonly toColumnVector: (vector: ElementType[]) => MultiArray;
/**
* Return the first column of a column-vector array.
*
* @param vector Column-vector `MultiArray`.
* @returns Backing first column.
*/
static readonly fromColumnVector: (vector: MultiArray) => ElementType[];
/**
* Check if a MultiArray is a row vector or a column vector.
* @param array MultiArray to test.
* @returns `true` if `array` is a vector (column vector or row vector), otherwise `false`.
*/
static readonly arrayIsVector: (array: MultiArray) => boolean;
/**
* Check if object is a MultiArray and it is a row vector or a column vector.
* @param obj Any object.
* @returns `true` if object is a row vector or a column vector. false otherwise.
*/
static readonly isVector: (obj: unknown) => boolean;
/**
* Convert a flat value list into a square diagonal matrix.
*
* @param vector Diagonal values.
* @returns Square matrix with `vector` on the main diagonal.
*/
static readonly toDiagonalMatrix: (vector: ElementType[]) => MultiArray;
/**
* Check if object is a scalar or a 2-D MultiArray.
* @param obj Any object.
* @returns `true` if object is a row vector or a column vector. false otherwise.
*/
static readonly isMatrix: (obj: unknown) => boolean;
/**
* Returns `true` if `obj` any one of its dimensions is zero.
* Returns `false` otherwise.
* @param obj Any object.
* @returns `true` if object is an empty array.
*/
static readonly isEmpty: (obj: unknown) => boolean;
/**
* Test whether a temporary reduced-array slot stores collected elements.
* @param value Slot value produced by `reduceToArray`.
* @returns `true` when the slot contains a reduced element line.
*/
private static readonly isReducedArrayLine;
/**
* Test whether a reduced line contains numeric scalar values.
* @param value Reduced line produced by `reduceToArray`.
* @returns `true` when all collected values are complex scalars.
*/
private static readonly isReducedComplexArrayLine;
/**
* Check if object is a MultiArray and it is a cell array.
* @param obj Any object.
* @returns `true` if object is a cell array. false otherwise.
*/
static readonly isCellArray: (obj: unknown) => boolean;
/**
* Test whether any array element is a complex numeric value.
*
* @param M Array to scan.
* @returns `true` when at least one element has a nonzero imaginary part.
*/
static readonly isComplexMultiArray: (M: MultiArray) => boolean;
/**
* Set type property in place with maximum value of array items type.
* @param M MultiArray to set type property.
*/
static readonly setType: (M: MultiArray) => void;
/**
* Test if two array are equals.
* @param left Array<boolean | number | string>.
* @param right Array<boolean | number | string>.
* @returns true if two arrays are equals. false otherwise.
*/
static readonly arrayEquals: (a: (boolean | number | string)[], b: (boolean | number | string)[]) => boolean;
/**
* Returns a one-based range array ([1, 2, ..., length]).
* @param length Length or last value of range array.
* @returns Range array.
*/
static readonly rangeArray: (length: number) => number[];
/**
* Converts linear index to subscript.
* @param dimension Dimensions of multidimensional array ([line, column, page, block, ...]).
* @param index Zero-based linear index.
* @returns One-based subscript ([line, column, page, block, ...]).
*/
static readonly linearIndexToSubscript: (dimension: number[], index: number) => number[];
/**
* Converts subscript to linear index.
* @param dimension Dimensions of multidimensional array ([lines, columns, pages, blocks, ...]).
* @param subscript One-based subscript ([line, column, page, block, ...]).
* @returns Zero-based linear index.
*/
static readonly subscriptToLinearIndex: (dimension: number[], subscript: number[]) => number;
/**
* Converts linear index to MultiArray.array subscript.
* @param row Row dimension.
* @param column Column dimension.
* @param index Zero-based linear index.
* @returns MultiArray.array subscript ([row, column]).
*/
static readonly linearIndexToMultiArrayRowColumn: (row: number, column: number, index: number) => [number, number];
/**
* Converts MultiArray subscript to MultiArray.array subscript.
* @param dimension MultiArray dimension.
* @param subscript Subscript.
* @returns MultiArray.array subscript ([row, column]).
*/
static readonly subscriptToMultiArrayRowColumn: (dimension: number[], subscript: number[]) => [number, number];
/**
* Converts MultiArray raw row and column to MultiArray linear index.
* @param dimension MultiArray dimension (can be only the two first dimensions)
* @param i Raw row
* @param j Raw column
* @returns Linear index
*/
static readonly rowColumnToLinearIndex: (dimension: number[], i: number, j: number) => number;
/**
* Convert a physical storage row/column pair to MATLAB-style subscripts.
*
* @param dimension Logical array dimensions.
* @param i Physical row in the page-flattened backing storage.
* @param j Physical column in the backing storage.
* @returns One-based logical subscript list.
*/
static readonly rowColumnToSubscript: (dimension: number[], i: number, j: number) => number[];
/**
* Compute stride vector (column-major order).
* Example: [3,4,2] → [1, 3, 12]
*/
static readonly computeStrides: (dim: number[]) => number[];
/**
* Return the internal page stride after a dimension.
*
* @param M Source array.
* @param dim Zero-based dimension index.
* @returns Product of dimensions after `dim`.
*/
static readonly getStride: (M: MultiArray, dim: number) => number;
/**
* Return a 2-D page slice from an N-D array.
*
* @param M Source array.
* @param pageIndex Zero-based page index.
* @returns 2-D numeric page data.
*/
static readonly pageSlice: (M: MultiArray, pageIndex: number) => ComplexType[][];
/**
* Replace a 2-D page inside an N-D array.
*
* @param M Target array.
* @param pageIndex Zero-based page index.
* @param pageData Replacement page values.
*/
static readonly setPage: (M: MultiArray, pageIndex: number, pageData: ComplexType[][]) => void;
/**
* Flatten array content in MATLAB column-major logical order.
*
* @param arr Source array.
* @returns Linear element array with `prod(size(arr))` entries.
*/
static readonly toFlatArray: (arr: MultiArray) => ComplexType[];
/**
* Reconstruct backing storage from a MATLAB column-major linear vector.
*
* @param arr Target array whose dimensions define the output shape.
* @param flat Linear values to place into `arr`.
*/
static readonly fromFlatArray: (arr: MultiArray, flat: ComplexType[]) => void;
/**
* Check if two MultiArrays have the same shape, or if they are identical
* except for one dimension d where both have size 3.
*
* Returns true if either:
* - A.dimension equals B.dimension (exact match), or
* - there exists an index d such that A.dimension[d] === 3 and B.dimension[d] === 3
* and for every i !== d we have A.dimension[i] === B.dimension[i].
*
* This matches the requirement of cross(A,B) where the operation dimension
* must have length 3 while all other dimensions must match.
* @param A Left array.
* @param B Right array.
* @returns `true` when shapes match or only a length-3 operation dimension differs.
*/
static readonly sameSizeExcept: (A: MultiArray, B: MultiArray) => boolean;
/**
* Base method of the ind2sub function. Returns dimension.length + 1
* dimensions. If the index exceeds the dimensions, the last dimension
* will contain the multiplier of the other dimensions. Otherwise it will
* be 1.
* @param dimension Array of dimensions.
* @param index One-base linear index.
* @returns One-based subscript ([line, column, page, block, ...]).
*/
static readonly ind2subNumber: (dimension: number[], index: number) => number[];
/**
* Returns the number of elements in M.
* @param M Multidimensional array.
* @returns Number of elements in M.
*/
static readonly linearLength: (M: MultiArray) => number;
/**
* Get dimension at index d of MultiArray M
* @param M MultiArray.
* @param d Zero-based dimension index.
* @returns Dimension d.
*/
static readonly getDimension: (M: MultiArray, d: number) => number;
/**
* Remove singleton tail of dimension array in place.
* @param dimension Dimension array.
*/
static readonly removeSingletonTail: (dimension: number[]) => void;
/**
* Append singleton tail of dimension array in place.
* @param dimension Dimension array.
* @param length Resulting length of dimension array.
*/
static readonly appendSingletonTail: (dimension: number[], length: number) => void;
/**
* Find first non-single dimension.
* @param M MultiArray.
* @returns First non-single dimension of `M`.
*/
static readonly firstNonSingleDimension: (M: MultiArray) => number;
/**
* Creates a MultiArray object from the first row of elements (for
* parsing purposes).
* @param row Array of objects.
* @returns MultiArray with `row` parameter as first line.
*/
private static readonly linkArrayElementParent;
static readonly firstRow: <ELEMENT_1 = Elements>(row: ElementType<ELEMENT_1>[], iscell?: boolean) => MultiArray<ELEMENT_1>;
/**
* Append a row of elements to a MultiArray object (for parsing
* purposes).
* @param M MultiArray.
* @param row Array of objects to append as row of MultiArray.
* @returns MultiArray with row appended.
*/
static readonly appendRow: <ELEMENT_1 = Elements>(M: MultiArray<ELEMENT_1>, row: ElementType<ELEMENT_1>[]) => MultiArray<ELEMENT_1>;
/**
* Unparse MultiArray.
* @param M MultiArray object.
* @returns String of unparsed MultiArray.
*/
static readonly unparse: (M: MultiArray, interpreter: RuntimeDisplay, _parentPrecedence?: number) => string;
/**
* Create a compact dimension-only string representation.
*
* @returns Human-readable array shape.
*/
toString(): string;
/**
* Unparse MultiArray as MathML language.
* @param M MultiArray object.
* @returns String of unparsed MultiArray in MathML language.
*/
static readonly unparseMathML: (M: MultiArray, interpreter: RuntimeDisplay, _parentPrecedence?: number) => string;
/**
* Converts CharString to MultiArray.
* @param text CharString.
* @returns Numeric character-code scalar or row vector.
*/
static readonly fromCharString: (text: CharString) => ElementType;
/**
* Converts a runtime character string to a row vector of character scalars.
*
* This preserves text contents for MATLAB/Octave-style string indexing,
* unlike `fromCharString`, which converts characters to numeric codes.
*
* @param text Character string value.
* @returns Row vector containing one scalar `CharString` per character.
*/
static readonly characterVectorFromCharString: (text: CharString) => MultiArray;
/**
* Rebuild a character string from character-scalar indexing results.
*
* @param value Scalar or array result produced from a character vector.
* @param quote Quote style to preserve.
* @returns Joined character string.
*/
static readonly charStringFromCharacterVectorResult: (value: ElementType, quote: CharString["quote"]) => CharString;
/**
* Linearize MultiArray in an array of ElementType using row-major
* order.
* @param M Array to flatten.
* @returns Elements in column-major logical order.
*/
static readonly flatten: (M: MultiArray) => ElementType[];
/**
* Linearize a `MultiArray` in MATLAB/Octave column-major logical order.
*
* `MultiArray.array` stores the first two dimensions as a row/column grid
* and stacks later pages in the physical row dimension. This method walks
* that storage through the same mapping as
* `linearIndexToMultiArrayRowColumn`, preserving logical linear-index order
* without allocating one slice per page column.
*
* @param M Multidimensional array or scalar value.
* @returns Elements of `M` in logical linear-index order.
*/
static readonly linearize: (M: ElementType) => ElementType[];
/**
* Returns a empty array (0x0 matrix).
* @returns Empty array (0x0 matrix).
*/
static readonly emptyArray: <ELEMENT_1 = Elements>(iscell?: boolean) => MultiArray<ELEMENT_1>;
/** Test whether a structural candidate can expose runtime fields. */
private static readonly isObjectRecord;
/** Test whether a structural field bag can store concrete structure fields. */
private static readonly isElementRecord;
/** Test whether a value is structurally a scalar MATLAB/Octave structure. */
private static readonly isStructureScalar;
/**
* Return structure elements from a scalar structure or structure array.
*
* @param value Candidate scalar or array.
* @returns Structure elements, or an empty list for non-structure values.
*/
private static readonly structureElements;
/** Convert an optional structure-field assignment value to concrete storage. */
private static readonly structureFieldValue;
/** Return sorted field names for a structure scalar or array. */
private static readonly structureFieldNames;
/**
* Create and validate a runtime structure through the decoupled factory.
*
* @param field Field map or nested field path.
* @returns Validated structure scalar.
*/
private static readonly createStructureValue;
/** Test whether a linearized value list contains only character scalars. */
private static readonly isCharStringList;
/**
* Create an empty structure value that mirrors a reference field schema.
*
* @param reference Structure whose field names should be copied.
* @returns New structure with each field initialized to `[]`.
*/
private static readonly cloneStructureFields;
private static readonly structureHasField;
private static readonly structureCollectFieldPath;
private static readonly getStructureField;
private static readonly structureAssignFieldPath;
private static readonly setEmptyStructureField;
private static readonly blankValueForExpansion;
/**
* Convert scalar to MultiArray with aditional test if it is MultiArray.
* @param value Scalar or array candidate.
* @param test Whether an existing `MultiArray` should be preserved.
* @returns Existing array or scalar wrapped in a 1-by-1 array.
*/
private static readonly scalarToMultiArrayWithTest;
/**
* If value is a scalar then convert to a 1x1 MultiArray. If is cell array
* the cell is put in a 1x1 MultiArray too.
* @param value MultiArray or scalar.
* @returns MultiArray 1x1 if value is scalar.
*/
static readonly scalarToMultiArray: (value: ElementType) => MultiArray;
/**
* If value is a scalar then convert to a 1x1 MultiArray. If is common
* array or cell array returns `value` unchanged.
* @param value MultiArray or scalar.
* @returns MultiArray 1x1 if value is scalar.
*/
static readonly scalarOrCellToMultiArray: (value: ElementType) => MultiArray;
/**
* If `value` parameter is a MultiArray of size 1x1 then returns as scalar.
* @param value MultiArray or scalar.
* @returns Scalar value if `value` parameter has all dimensions as singular.
*/
static readonly MultiArrayToScalar: (value: ElementType) => ElementType;
/**
* If `value` parameter is a non empty MultiArray returns it's first element.
* Otherwise returns `value` parameter.
* @param value Scalar or array candidate.
* @returns First element of a non-empty array, otherwise `value`.
*/
static readonly firstElement: (value: ElementType) => ElementType;
/**
* If M is a line vector then return the line of M else return first column of M.
* @param M Scalar or array candidate.
* @returns First row for row vectors, first column otherwise.
*/
static readonly firstVector: (M: ElementType) => ElementType[];
/**
* Copy of MultiArray.
* @param M MultiArray.
* @returns Copy of MultiArray.
*/
static readonly copy: (M: MultiArray) => MultiArray;
/**
* Copy this array and its stored runtime values.
*
* @returns Copied array preserving generic element type.
*/
copy(): MultiArray<ELEMENT>;
/**
* Convert a `MultiArray` to the scalar truth value used by conditions.
*
* MATLAB/Octave conditions are true only when the array is non-empty and
* every element is logically true. Empty arrays therefore evaluate to
* false, not true by vacuity.
*
* @param M Array to test.
* @returns Logical scalar truth value.
*/
static readonly toLogical: (M: MultiArray) => ComplexType;
/**
* Convert this array to the scalar truth value used by conditions.
*
* @returns Logical scalar truth value.
*/
toLogical(): ComplexType;
/**
* Expand Multidimensional array dimensions if dimensions in `dim` is greater than dimensions of `M`.
* If a dimension of `M` is greater than corresponding dimension in `dim` it's unchanged.
* The array is filled with zeros and is expanded in place.
* @param M Multidimensional array.
* @param dim New dimensions.
*/
static readonly expand: (M: MultiArray, dim: number[], fill?: ElementType) => void;
/**
* Reshape an array acording dimensions in `dim`.
* @param M MultiArray.
* @param dim Result dimensions.
* @param d Undefined dimension index (optional).
* @returns
*/
static readonly reshape: (M: MultiArray, dim: number[], d?: number) => MultiArray;
/**
* Expand range.
* @param startNode Start of range.
* @param stopNode Stop of range.
* @param strideNode Optional stride value.
* @returns MultiArray of range expanded.
*/
static readonly expandRange: (start: ComplexType, stop: ComplexType, stride?: ComplexType | null) => MultiArray;
/**
* Expand colon to a column vector.
* @param length
* @returns
*/
static readonly expandColon: (length: number) => MultiArray;
/**
* Detect whether MultiArray `M` contains any non-zero imaginary part.
* @param M MultiArray to test.
* @returns `true` if any element has non-zero imaginary component.
* `false` otherwise.
*/
static readonly haveAnyComplex: (M: MultiArray) => boolean;
/**
* Check if subscript is a integer number, convert Complex to
* number.
* @param k Index as Complex.
* @param prefix Optional id reference of object.
* @returns k as number, if real part is integer greater than 1 and imaginary part is 0.
*/
static readonly testInteger: (k: ComplexType, prefix?: string, infix?: string, constraint?: number | [number, number]) => number;
/**
* Check if subscript is a integer number, convert Complex to
* number.
* @param k Index as Complex.
* @param input Optional id reference of object.
* @returns k as number, if real part is integer greater than 1 and imaginary part is 0.
*/
static readonly testIndex: (k: ComplexType, input?: string) => number;
/**
* Check if subscript is a integer number, convert Complex to
* number, then check if it's less than bound.
* @param k Index as Complex.
* @param bound Maximum acceptable value for the index
* @param dim Dimensions (to generate error message)
* @param input Optional string to generate error message.
* @returns Index as number.
*/
static readonly testIndexBound: (k: ComplexType, bound: number, dim: number[], input?: string) => number;
/**
* Converts subscript to linear index. Performs checks and throws
* comprehensive errors if dimension bounds are exceeded.
* @param dimension Dimension of multidimensional array ([line, column, page, block, ...]) as number[].
* @param subscript Subscript ([line, column, page, block, ...]) as a Complex[].
* @param input Input string to generate error messages (the id of array).
* @returns linear index.
*/
static readonly parseSubscript: (dimension: number[], subscript: ComplexType[], input?: string, interpreter?: RuntimeDisplay) => number;
/**
* Binary operation 'scalar `operation` array'.
* @param op Binary operation name.
* @param left Left operand (scalar).
* @param right Right operand (array).
* @returns Result of operation.
*/
static readonly scalarOpMultiArray: (op: TBinaryOperationName, left: ComplexType, right: MultiArray) => MultiArray;
/**
* Binary operation 'array `operation` scalar'.
* @param op Binary operation name.
* @param left Left operand (array).
* @param right Right operaand (scalar).
* @returns Result of operation.
*/
static readonly MultiArrayOpScalar: (op: TBinaryOperationName, left: MultiArray, right: ComplexType) => MultiArray;
/**
* Unary left operation.
* @param op Unary operation name.
* @param right Operand (array)
* @returns Result of operation.
*/
static readonly leftOperation: (op: TUnaryOperationLeftName, right: MultiArray) => MultiArray;
/**
* Binary element-wise operation with full MATLAB-compatible broadcasting.
* Supports N-D arrays and row/column vector expansion.
* @param op Binary operation.
* @param left Left operand.
* @param right Right operand.
* @returns Binary element-wise result.
*/
static readonly elementWiseOperation: (op: TBinaryOperationName, left: MultiArray, right: MultiArray) => MultiArray;
/**
* Calls a defined callback function on each element of an MultiArray,
* and returns an MultiArray that contains the results.
* @param M MultiArray.
* @param callback Callback function.
* @returns A new MultiArray with each element being the result of the callback function.
*/
static readonly rawMap: (M: MultiArray, callback: Function) => MultiArray;
/**
* Calls a defined callback function on each element of an MultiArray,
* and returns an MultiArray that contains the results. Pass indices
* to callback function. The index parameter is the array linear index
* of element parameter.
* @param M MultiArray
* @param callback Callback function.
* @returns A new MultiArray with each element being the result of the callback function.
*/
static readonly rawMapRowColumn: (M: MultiArray, callback: (element: ElementType, i: number, j: number) => ElementType) => MultiArray;
/**
* Calls a defined callback function on each element of an MultiArray,
* and returns an MultiArray that contains the results. Pass indices
* to callback function. The index parameter is the array linear index
* of element parameter.
* @param M MultiArray.
* @param callback Callback function.
* @returns A new MultiArray with each element being the result of the callback function.
*/
static readonly rawMapLinearIndex: (M: MultiArray, callback: (element: ElementType, index: number, i?: number, j?: number) => ElementType) => MultiArray;
/**
* Calls a defined callback function on each element of an MultiArray,
* along a specified dimension, and returns an MultiArray that contains
* the results. Pass dimension index and MultiArray row and column to
* callback function.
* @param dimension Dimension to map.
* @param M MultiArray
* @param callback Callback function.
* @returns A new MultiArray with each element being the result of the callback function.
*/
static readonly alongDimensionMap: (dimension: number, M: MultiArray, callback: (element: ElementType, d: number, i: number, j: number) => ElementType) => MultiArray;
/**
*
* @param M
* @param DIM
* @returns
*/
static readonly sizeAlongDimension: (M: MultiArray, DIM?: ElementType) => number;
/**
* Returns the element at the given index along the specified dimension.
* @param M MultiArray instance
* @param dimension Dimension index (0-based)
* @param index Index along the dimension (0-based)
* @returns ElementType
*/
static readonly getElementAlongDimension: (M: MultiArray, dimension: number, index: number) => ElementType;
/**
*
* @param elem
* @param scalar
* @returns
*/
static readonly divideElementByScalar: (elem: ElementType, scalar: ComplexType) => ElementType;
/**
*
* @param meanElem
* @param dim
* @param d
* @returns
*/
static readonly getMeanElementForPosition: (meanElem: ElementType, dim: number, d: number) => ElementType;
/**
* Reduce one dimension of MultiArray putting entire dimension in one
* element of resulting MultiArray as an Array. The resulting MultiArray
* cannot be unparsed or used as argument of any other method of
* MultiArray class.
* @param dimension Dimension to reduce to Array
* @param M MultiArray to be reduced.
* @returns MultiArray whose slots contain collected element lines.
*/
static readonly reduceToArray: (dimension: number, M: MultiArray) => MultiArray<ReducedArrayLine>;
/**
* Contract MultiArray along `dimension` calling callback. This method is
* analogous to the JavaScript Array.reduce function.
* @param dimension Dimension to operate callback and contract.
* @param M Multidimensional array.
* @param callback Reduce function.
* @param initial Optional initial value to set as previous in the first
* call of callback. If not set the previous will be set to the first
* element of dimension.
* @returns Multiarray with `dimension` reduced using `callback`.
*/
static readonly reduce: (dimension: number, M: MultiArray, callback: (previous: ElementType, current: ElementType, index?: number) => ElementType, initial?: ElementType) => ElementType;
/**
* Return the concatenation of N-D array objects, ARRAY1, ARRAY2, ...,
* ARRAYN along `dimension` parameter (zero-based).
* @param dimension Dimension of concatenation.
* @param fname Function name (for error messages).
* Empty arrays are neutral when at least one non-empty operand is present,
* matching MATLAB/Octave concatenation such as `[[], 1]`.
* @param ARRAY Arrays to concatenate.
* @returns Concatenated arrays along `dimension` parameter.
*/
static readonly concatenate: (dimension: number, fname: string, ...ARRAY: MultiArray[]) => MultiArray;
/**
* Split the MultiArray in the last dimension.
* @param M
* @returns
*/
private static readonly splitLastDimension;
/**
* Calls `splitLastDimension` and recursively calls `evaluate` for each
* result, concatenating on the last dimension, until the array is 2-D,
* then then concatenates the elements row by row horizontally, then
* concatenates the rows vertically.
* @param M MultiArray object.
* @param interpreter Runtime evaluation context.
* @param local Local context (function evaluation).
* @param fname Function name (context).
* @returns Evaluated MultiArray object.
*/
private static readonly evaluateRecursive;
/**
* Wrapper to not pass the null array to `MultiArray.interpreterRecursive`.
* @param M MultiArray object.
* @param interpreter Runtime evaluation context.
* @param local Local context (function evaluation).
* @param fname Function name (context).
* @returns Evaluated MultiArray object.
*/
static readonly evaluate: (M: MultiArray, interpreter?: RuntimeEvaluationContext | null | undefined, scope?: unknown) => ElementType;
/**
* # MATLAB/Octave Array Indexing - Complete Rules (Concise Specification)
*
* This document synthesizes the official rules of MATLAB/Octave array indexing,
* based on MathWorks documentation and related references. It defines how arrays
* are accessed, reshaped, and modified under all indexing modes.
*
* ## 1. Core Concepts
*
* - Arrays use **1-based indexing**.
* - Storage and traversal follow **column-major order**.
* - Indexing modes:
* - **Linear indexing** (single index)
* - **Subscript indexing** (multiple indices)
* - **Logical indexing**
*
* ## 2. Linear Indexing
*
* ```matlab
* A(k)
* ```
*
* - Treats `A` as a single column vector in column-major order.
* - Accesses elements sequentially down columns.
* - Result:
* - Same number of elements as index
* - Orientation follows index (row vs column)
*
* ### Special Case: `(:)`
*
* ```matlab
* A(:)
* ```
*
* - Returns all elements as a **column vector**
* - Equivalent to full linearization
*
* ## 3. Subscript (Multidimensional) Indexing
*
* ```matlab
* A(i,j,k,...)
* ```
*
* - Each index corresponds to one dimension.
* - Indices may be scalars, vectors, or `:`.
* - Result size:
*
* ```text
* size(A(i,j,k,...)) = [numel(i), numel(j), numel(k), ...]
* ```
*
* - Colon `:` selects all elements in that dimension.
*
* ## 4. Index Vectors and Shape Rules
*
* - For `A(id)`:
* - Result has same number of elements as `id`
* - Orientation follows `A` if both are vectors
*
* - For `A(id1,id2)`:
* - Result is a matrix of size:
*
* ```text
* [numel(id1), numel(id2)]
* ```
*
* - General case:
*
* ```text
* size = [numel(id1), numel(id2), ..., numel(idn)]
* ```
*
* ## 5. Fewer Indices Than Dimensions (Dimension Folding)
*
* If fewer indices are provided than dimensions:
*
* ```matlab
* A(i,j) % A is N-D
* ```
*
* - MATLAB **folds all remaining dimensions into the last index**.
* - Equivalent to reshaping:
*
* ```matlab
* reshape(A, dim1, dim2*dim3*...)
* ```
*
* ### Consequences
*
* - `A(:, :)` flattens higher dimensions into columns
* - `A(i,:)` traverses across all higher dimensions
* - `A(:,j)` does **not** traverse higher dimensions
*
* ## 6. Colon Operator (`:`)
*
* - Selects full dimension:
*
* ```matlab
* A(:,j)
* A(i,:)
* ```
*
* - Equivalent to `1:end` in that dimension
*
* - Also used to generate ranges:
*
* ```matlab
* a:b
* a:s:b
* ```
*
* ## 7. Logical Indexing
*
* ```matlab
* A(mask)
* ```
*
* - `mask` is evaluated in **linear order**
* - Must not exceed `numel(A)`
* - Result:
* - Column vector of selected elements
*
* ## 8. The `end` Keyword
*
* - Refers to last index of a dimension:
*
* ```matlab
* A(end)
* A(1:end)
* A(:,end)
* ```
*
* - Evaluated independently per dimension
*
* ## 9. Indexed Assignment
*
* ```matlab
* A(I) = B
* ```
*
* ### Rules
*
* - If `B` is scalar → scalar expansion
* - Otherwise:
*
* ```text
* numel(B) == numel(I)
* ```
*
* - Indices may be repeated (last assignment wins)
* - Colon selects full dimension
*
* ## 10. Deletion via Empty Array
*
* ```matlab
* A(I) = []
* ```
*
* ### Rules
*
* - Removes elements along **one dimension only**
* - Valid when indexing selects:
* - Entire rows
* - Entire columns
* - Entire slices of a single dimension
*
* - Invalid if assignment would produce irregular shape
*
* ## 11. Array Expansion
*
* ```matlab
* A(10) = 5
* ```
*
* - Array automatically grows
* - Missing elements filled with default values (e.g., `0`)
*
* ## 12. Linear vs Subscript Distinction
*
* ```matlab
* A(2) % linear
* A(2,:) % subscript
* ```
*
* - These operations are **fundamentally different**
* - Linear indexing ignores dimensions
* - Subscript indexing respects dimensional structure
*
* ## 13. Evaluation Order
*
* 1. Index expressions evaluated
* 2. Converted to subscripts or linear indices
* 3. Bounds checked
* 4. Elements accessed or assigned
*
* ## 14. Key Behavioral Summary
*
* - Column-major order governs all indexing
* - `(:)` always returns a column vector
* - Logical indexing returns column vectors
* - Subscript indexing defines output shape explicitly
* - Fewer indices ⇒ dimension folding
* - Assignment enforces size compatibility or scalar expansion
* - Deletion is restricted to one dimension
*
* ## 15. MathJSLab Engine Implementation Notes
*
* This section documents how the MathJSLab engine concretely implements
* the indexing semantics described above. While fully aligned with MATLAB
* behavior, the engine introduces a **unified linear-index pipeline**
* to simplify execution and ensure consistency across all operations.
*
* ### 15.1 Unified Index Resolution
*
* All indexing modes (linear, subscript, logical) are internally reduced to:
*
* ```text
* → a list of 0-based linear indices
* ```
*
* This is performed by:
*
* ```ts
* resolveLinearIndices(...)
* ```
*
* Responsibilities:
* - Detect logical vs numeric indexing
* - Normalize scalar logicals (`true` → `[1]`, `false` → `[]`)
* - Delegate numeric interpretation to:
* - `computeIndexingStructure`
* - `iterateWithLinearIndex`
*
* This guarantees a **single source of truth** for index resolution.
*
*
* ### 15.2 Index Normalization Pipeline
*
* The engine separates indexing into three distinct phases:
*
* 1. **Structure normalization**
* ```ts
* computeIndexingStructure(...)
* ```
* - Expands missing dimensions with `:`
* - Linearizes all index arguments
* - Computes total iteration size
*
* 2. **Index evaluation**
* ```ts
* iterateWithLinearIndex(...)
* ```
* - Resolves `end`
* - Converts subscripts → linear indices
* - Performs bounds validation via `parseSubscript`
*
* 3. **Collection**
* ```ts
* collectLinearIndices(...)
* ```
* - Produces final linear index list
*
*
* ### 15.3 Selection Pipeline
*
* Element access follows:
*
* ```text
* indices → applyLinearSelection → shape reconstruction
* ```
*
* - `applyLinearSelection(...)`
* - Retrieves elements using `getElementByLinearIndex`
*
* - Shape reconstruction:
* - Logical indexing → column vector (or mask-shaped vector)
* - Linear indexing:
* - `(:)` → column vector
* - otherwise → row vector
* - Subscript indexing:
* - Uses `computeIndexingStructure`
* - Uses `resolveIndexPlan`
* - Final adjustment via `collapseResult`
*
*
* ### 15.4 Assignment Pipeline
*
* Assignment is centralized via:
*
* ```ts
* applyLinearAssignment(...)
* ```
*
* Features:
* - Scalar expansion
* - Strict size validation
* - Field-aware assignment (structures supported)
* - Deterministic overwrite (last index wins)
*
* High-level flow:
*
* ```text
* resolve indices → expand target → assign values
* ```
*
* Expansion rules:
* - Linear growth allowed only for vectors
* - Multidimensional growth uses `expand(...)`
*
*
* ### 15.5 Deletion Semantics
*
* Deletion is handled in two layers:
*
* - High-level:
* ```ts
* deleteElements(...)
* ```
* - Enforces MATLAB rule:
* → exactly one non-colon dimension
*
* - Low-level:
* ```ts
* applyDeletionFromIndices(...)
* ```
* - Removes elements using linear filtering
* - Preserves vector orientation when applicable
*
*
* ### 15.6 Logical Indexing Implementation
*
* Logical indexing is treated as a specialization of linear indexing:
*
* ```text
* mask → logicalToLinearIndices → linear pipeline
* ```
*
* Rules:
* - Mask is always linearized
* - `true` selects index
* - `false` skips index
* - Scalar logical:
* - `true` → first element
* - `false` → empty result
*
* Output shape:
* - Always column vector unless mask is a vector (row preserved)
*
*
* ### 15.7 Shape Resolution Strategy
*
* Shape is **not derived from indices directly**, but from a plan:
*
* ```ts
* resolveIndexPlan(...)
* ```
*
* This determines:
* - Linear vs multidimensional behavior
* - Full slice detection (`:`)
* - Scalar vs vector indexing
* - Active dimensions
* - Whether collapse is required
*
* Final shape adjustments:
* - `collapseResult(...)`
* - Handles dimension folding
* - Preserves MATLAB-compatible edge cases:
* - `A(:,j)`
* - `A(i,:)`
* - N-D flattening
*
*
* ### 15.8 Design Principles
*
* The implementation follows strict architectural rules:
*
* - **Single responsibility**
* - Index resolution, selection, assignment, and shape are separated
*
* - **Linear-first execution model**
* - All operations operate on linear indices internally
*
* - **MATLAB compatibility as constraint**
* - Edge cases explicitly preserved
*
* - **Deterministic behavior**
* - No ambiguity in index interpretation
*
* - **Extensibility**
* - Logical, numeric, and future index types share the same pipeline
*
*
* ### 15.9 Summary
*
* The MathJSLab engine implements MATLAB indexing through:
*
* ```text
* Normalize → Resolve → Linearize → Apply → Reshape
* ```
*
* This unified model ensures:
* - Correctness
* - Maintainability
* - Full compatibility with MATLAB semantics
*
* while keeping the internal execution model simple and robust.
*
* ## Sources
*
* - [MathWorks - Matrix Indexing in MATLAB](https://www.mathworks.com/company/technical-articles/matrix-indexing-in-matlab.html)
* - [MathWorks - Array Indexing](https://www.mathworks.com/help/matlab/math/array-indexing.html)
* - [MathWorks - Detailed Rules About Array Indexing](https://www.mathworks.com/help/matlab/learn_matlab/array-indexing.html)
* - [MathWorks - Indexed Assignment](https://www.mathworks.com/help/matlab/math/detailed-rules-about-array-indexing.html)
* - [MathWorks - Learn MATLAB: Array Indexing](https://www.mathworks.com/help/matlab/math/indexed-assignment.html)
* - [TutorialsPoint - MATLAB Array Indexing](https://www.tutorialspoint.com/matlab/matlab_array_indexing.htm)
*/
private static colon;
/**
* Normalize an indexing expression into a canonical structure used by
* MultiArray get/set/delete operations.
*
* This function is the entry point for interpreting MATLAB-like indexing.
* It converts the raw `indexList` (which may contain scalars, vectors,
* or MultiArray objects) into a uniform representation that can be used
* by iteration and linear index resolution.
*
* Behavior:
* - Detects linear indexing when a single index argument is provided.
* - Expands missing dimensions with implicit colon (:) to match the
* number of dimensions of the target array.
* - Linearizes all index arguments into flat arrays.
* - Computes the total number of indexed elements (cartesian product).
*
* Notes:
* - This function does NOT validate bounds or apply indexing; it only
* prepares structural information.
* - Logical indexing is NOT handled here and must be intercepted before
* calling this function.
*
* @param dimension Shape of the target MultiArray (e.g. [m, n, ...]).
* @param indexList Raw index arguments as provided by the interpreter.
*
* @returns An object describing the normalized indexing plan:
* - isLinear: true if indexing uses a single argument (linear indexing)
* - originalIndexCount: number of indices provided by the user
* - args: array of linearized index arrays (one per dimension)
* - argsLength: length of each index array
* - total: total number of indexed elements (product of argsLength)
*
* @throws RangeError if indexList is empty
*/
private static readonly computeIndexingStructure;
/**
* Iterate over a normalized indexing structure and resolve each position
* into a linear index of the target MultiArray.
*
* This function bridges the gap between:
* - The cartesian product of index arguments (produced by computeIndexingStructure)
* - The actual linear indices used to access elements in memory
*
* Behavior:
* - Iterates over all combinations of indices (cartesian product)
* - Converts each iteration step `n` into a multi-dimensional subscript
* relative to the index arguments (not the target array)
* - Maps those subscripts into actual index values (subscriptArgs)
* - Resolves each subscriptArgs into a linear index using MATLAB rules
* (including support for `end` via parseSubscript)
* - Invokes the callback with:
* - subscriptArgs: the resolved indices per dimension (1-based)
* - linearIndex: the corresponding linear index in the target array (0-based)
* - n: the iteration counter (0-based)
*
* Notes:
* - This function assumes `idx` was produced by computeIndexingStructure.
* - Bounds checking and `end` resolution are delegated to parseSubscript.
* - The iteration order follows column-major semantics (MATLAB-compatible).
* - This function does NOT perform any read/write; it only drives iteration.
*
* @param idx Normalized indexing structure (args, argsLength, total).
* @param dimension Shape of the target MultiArray.
* @param callback Function invoked for each indexed element.
* @param input Optional input string (used for error reporting).
* @param interpreter Optional interpreter (used for resolving expressions like `end`).
*/
private static readonly iterateWithLinearIndex;
/**
* Resolve the structural "indexing plan" for a given indexing operation.
*
* This function analyzes the normalized indexing structure and extracts
* semantic information about how the result should be shaped and interpreted.
*
* It does NOT perform indexing itself. Instead, it provides metadata used by:
* - getElements → to shape the output (row/column/folding)
* - collapseResult → to decide dimensional reduction
*
* The plan captures both:
* 1. Legacy compatibility flags (MATLAB-like behavior)
* 2. Structural semantics per dimension (more expressive and future-proof)
*
* ------------------------------------------------------------
* CONCEPTUAL MODEL
* ------------------------------------------------------------
*
* Each dimension is classified as:
* - full slice → ":" (entire dimension selected)
* - scalar index → single position (dimension collapses)
* - partial → subset of elements
*
* From this, we derive:
* - activeDimensions → dimensions that are actually being restricted
* - isFullSlice → per-dimension ":" detection
* - isScalarIndex → per-dimension scalar selection
*
* ------------------------------------------------------------
* SPECIAL CASE: LINEAR INDEXING
* ------------------------------------------------------------
*
* When idx.isLinear === true:
* - The operation ignores multi-dimensional structure
* - The array is treated as a column-major linear vector
* - activeDimensions is reduced to a single conceptual dimension
*
* ------------------------------------------------------------
* COMPATIBILITY FLAGS (LEGACY BEHAVIOR)
* ------------------------------------------------------------
*
* These flags preserve MATLAB-like shaping behavior:
*
* - isColonOnly:
* True when linear indexing selects the entire array (A(:))
*
* - isRowSelection:
* Detects A(1,:) pattern → result should be a row vector
*
* - isColumnSelection:
* Detects A(:,1) pattern → result should be a column vector
*
* - requiresCollapse:
* True when fewer indices than dimensions were provided.
* This triggers dimensional folding (e.g., A(2,:) on 3D arrays)
*
* ------------------------------------------------------------
* NOTES
* ------------------------------------------------------------
*
* - Dimension padding with ":" is applied implicitly before classification.
* - This function is purely analytical (no data access or mutation).
* - The returned plan is consumed downstream by shape resolution logic.
*
* @param dimension Shape of the target MultiArray.
* @param idx Normalized indexing structure from computeIndexingStructure.
*
* @returns Indexing plan describing structural semantics of the operation.
*/
private static readonly resolveIndexPlan;
/**
* Retrieve an element from a MultiArray using a 0-based linear index.
*
* This method provides a unified access path for both plain values and
* structured field access. It converts the linear index into (row, column)
* coordinates assuming column-major order (MATLAB semantics), then retrieves
* the corresponding element.
*
* If a non-empty `field` path is provided, the access is delegated to
* Structure.getField, allowing nested field resolution (e.g., A(i).field.subfield).
*
* @param M Source MultiArray.
* @param linearIndex Zero-based linear index (column-major order).
* @param field Structure field access path. If empty, returns the raw element.
* @returns The selected element or nested field value.
*
* @throws RangeError If the linear index is out of bounds (indirectly via index conversion).
*
* @remarks
* - Assumes that `linearIndex` has already been validated.
* - This function is intentionally minimal and side-effect free.
* - Used as the core primitive by higher-level selection helpers such as
* `applyLinearSelection` and indexing pipelines.
*/
private static readonly getElementByLinearIndex;
/**
* Set element in a MultiArray using a linear index (column-major order).
*
* This function is the write counterpart of `getElementByLinearIndex` and
* centralizes all element assignment at the lowest level of the indexing pipeline.
*
* The linear index is assumed to be **0-based** and mapped to (row, column)
* coordinates according to MATLAB/Octave column-major semantics.
*
* If a field path is provided, the assignment is performed on a nested
* structure field instead of directly replacing the element.
*
* @param M Target MultiArray.
* @param linearIndex Zero-based linear index in column-major order.
* @param value Value to assign at the specified position.
* @param field Optional structure field access path.
*
* @throws RangeError If the linear index is out of bounds (indirectly via index conversion).
* @throws Error If field access is invalid for the target element.
*/
private static readonly setElementByLinearIndex;
/**
* Collapse an intermediate indexing result to its final shape according to MATLAB rules.
*
* After element selection, the intermediate result (`resultFull`) is typically constructed
* as a full N-dimensional array. This function applies MATLAB's post-processing rules
* to determine the final output shape, including dimension collapsing and vector orientation.
*
* Behavior:
*
* 1) No collapse required:
* - If the number of index arguments matches the array dimensionality,
* the result is returned as-is.
*
* 2) Special 2D cases (highest priority, MATLAB-compatible):
* - Column selection: A(:, j)
* → returns a column vector (n×1)
*
* - Row selection: A(i, :)
* → returns a row vector (1×n)
* → also applies to higher dimensions with implicit folding
*
* 3) General MATLAB folding rule:
* - When indexing reduces dimensionality (partial indexing),
* higher dimensions are folded into columns.
* - Result becomes a 2D matrix:
* rows = size along first dimension
* cols = total elements / rows
*
* - Elements are filled in column-major order (MATLAB layout).
*
* 4) Default:
* - If none of the above applies, the intermediate result is returned unchanged.
*
* Notes:
* - This function enforces MATLAB-compatible shape semantics after indexing.
* - It does not modify element values, only their arrangement.
* - The `plan` parameter encodes structural properties of the indexing operation,
* but only a subset is currently used for collapse decisions.
*
* @param resultFull Intermediate full result (before collapse).
* @param originalDimension Original dimensions of the source array.
* @param idx Indexing structure (argument counts and shapes).
* @param plan Precomputed indexing plan describing selection semantics.
*
* @returns Final MultiArray with correct MATLAB-compatible shape.
*/
private static readonly collapseResult;
/**
* Shape the result of linear indexing according to MATLAB/Octave rules.
*
* `A(:)` is always a column vector. For explicit `A(P)`, vector sources keep
* their own row/column orientation when `P` is also a vector; matrix-shaped
* sources or matrix-shaped `P` use the shape of `P`.
*/
private static readonly linearIndexResult;
/**
* Shape the result of logical indexing as the equivalent linear indexing by
* `find(mask)`.
*
* For vector sources and vector masks, MATLAB/Octave preserve the source
* orientation. For matrix-shaped sources with vector masks, the result follows
* the mask orientation. Matrix-shaped logical masks produce a column vector.
*/
private static readonly logicalIndexResult;
/**
* Normalize a scalar or array logical subscript to a `MultiArray` mask.
* @param arg Logical index argument.
* @returns Logical mask as a `MultiArray`.
*/
private static readonly logicalMaskFromIndexArgument;
/**
* Linearize and validate a logical mask as numeric/logical complex values.
* @param items Logical mask.
* @param id Optional identifier for diagnostics.
* @returns Linearized logical mask values.
*/
private static readonly linearizedLogicalMask;
/**
* Convert a logical mask into a list of linear indices (0-based).
*
* MATLAB semantics:
* - Logical indexing is interpreted in linear (column-major) order.
* - The mask is first linearized, then applied element-wise to the
* linearized target array.
* - Each `true` value selects the corresponding linear position.
* - `false` values are ignored.
*
* Validation rules:
* - The mask length must not exceed the number of elements in `M`.
* - If the mask is shorter than `M`, it is applied only to the
* corresponding leading elements (MATLAB-compatible behavior).
*
* Notes:
* - Returned indices are 0-based (internal engine convention).
* - The returned list may be empty (e.g., when mask is all false).
* - This function does NOT handle scalar logicals; those must be
* normalized beforehand by the caller (e.g., via `scalarToMultiArray`).
*
* @param M Target MultiArray being indexed.
* @param items Logical mask as a MultiArray.
* @param id Optional identifier (used for error messages).
* @returns Array of selected linear indices (0-based).
*
* @throws EvalError If the mask length exceeds the number of elements in `M`.
*/
private static readonly logicalToLinearIndices;
/**
* Normalize logical indexing input into a list of linear indices (0-based).
*
* This is a thin wrapper around {@link logicalToLinearIndices}, introduced to:
* - Provide a stable abstraction point for logical index resolution
* - Allow future extensions (e.g., scalar logical handling, special cases)
* - Keep dispatcher and high-level indexing code decoupled from low-level logic
*
* The logical mask is interpreted in linear (column-major) order, following
* MATLAB semantics:
* - True values select corresponding linear positions
* - False values are ignored
* - Mask length must not exceed the number of elements in `M`
*
* @param M Target MultiArray being indexed.
* @param items Logical mask as a MultiArray.
* @param id Identifier (used for error reporting).
* @returns Array of selected linear indices (0-based).
*/
private static logicalMaskToIndexList;
/**
* Determine whether an argument represents logical indexing.
*
* This function identifies both supported forms of logical indices:
*
* 1) Logical MultiArray
* - e.g., A([true false true])
*
* 2) Logical scalar (Complex)
* - e.g., A(true), A(false)
*
* This distinction is important because scalar logicals behave differently
* from numeric scalars:
* - A(true) → selects the first element (linear index 1 in MATLAB)
* - A(false) → selects no elements (returns empty array)
*
* Notes:
* - This function is used by indexing dispatchers to route execution
* into the logical indexing pipeline.
* - It does not validate shape or size compatibility; it only detects type.
* - Scalar logicals must be normalized (e.g., via scalarToMultiArray)
* before further processing.
*
* @param arg Index argument (scalar or MultiArray).
* @returns True if the argument should be treated as logical indexing.
*/
private static isLogicalIndex;
/**
* Apply linear selection on a MultiArray and return the extracted elements.
*
* This function performs the core data extraction step of the indexing pipeline:
* given a list of linear indices (0-based), it retrieves the corresponding
* elements from the source array in order.
*
* Selection follows MATLAB semantics:
* - Indices refer to positions in column-major (linearized) order
* - The output preserves the order of `indices`
* - No reshaping is performed here (result is always a flat array)
*
* If a field path is provided, each selected element is resolved through
* structure field access instead of returning the raw element.
*
* @param M Source MultiArray.
* @param indices Linear indices (0-based, column-major order).
* @param field Optional structure field access path.
* @returns Flat array of selected elements, in the same order as `indices`.
*
* @remarks
* - This function is side-effect free.
* - It assumes indices have already been validated.
* - Shape/orientation (row/column/matrix) is handled later in the pipeline
* (e.g., in getElements and collapseResult).
* - Acts as the core primitive for both numeric and logical indexing.
*/
private static applyLinearSelection;
/**
* Apply linear assignment on a MultiArray using a list of linear indices.
*
* This function performs the core write operation of the indexing pipeline.
* Given a set of linear indices (0-based), it assigns values to the corresponding
* positions in the target array, following MATLAB assignment semantics.
*
* Behavior:
*
* 1) Scalar expansion (broadcast):
* - If `values` contains a single element, it is assigned to all indices.
*
* 2) Element-wise assignment:
* - If `values.length > 1`, its length must match `indices.length`.
* - Each value is assigned to the corresponding index in order.
*
* 3) Structure field assignment:
* - If a non-empty `field` path is provided, assignment is delegated to
* nested structure fields instead of replacing the element itself.
*
* Validation:
* - Throws if the number of values does not match the number of indices
* (unless scalar expansion applies).
*
* @param M Target MultiArray.
* @param indices Linear indices (0-based, column-major order).
* @param values Linearized right-hand side values.
* @param field Optional structure field access path.
*
* @throws EvalError If dimensions are nonconformant.
*
* @remarks
* - This function does not handle deletion (A(I) = []); that is handled upstream.
* - Assumes indices are already validated and within bounds.
* - Does not perform resizing or expansion of `M`; that is also handled upstream.
* - Acts as the unified assignment primitive for both numeric and logical indexing.
*/
private static applyLinearAssignment;
/**
* Resolve an index list (logical or numeric) into linear indices (0-based).
*
* This function is the core of the indexing engine. It normalizes all supported
* indexing modes into a unified representation: a list of linear indices in
* column-major order.
*
* It does NOT perform element access or assignment — only index resolution.
*
* Supported indexing modes:
*
* 1) Logical indexing:
* - Triggered when a single logical argument is provided.
* - Accepts both logical MultiArray and logical scalar.
* - Scalar logicals are normalized:
* true → selects first element
* false → selects no elements
* - The mask is applied in linear (column-major) order.
*
* 2) Numeric indexing:
* - Supports linear indexing (single argument)
* - Supports multi-dimensional indexing (A(i,j,...))
* - Supports colon (:) and range expressions
* - Supports `end` keyword via interpreter
*
* Processing steps (numeric case):
* a) Normalize index structure via `computeIndexingStructure`
* b) Iterate over all index combinations
* c) Convert each subscript tuple into a linear index using `parseSubscript`
*
* Output:
* - A flat array of 0-based linear indices
* - Order matches MATLAB evaluation order (column-major traversal)
*
* @param M Target MultiArray being indexed.
* @param id Identifier (used for error reporting and `end` resolution).
* @param indexList Raw index arguments (scalars, arrays, or logical masks).
* @param interpreter Optional interpreter used to resolve dynamic expressions (e.g., `end`).
*
* @returns Array of linear indices (0-based).
*
* @throws EvalError or RangeError for invalid indices or out-of-bounds access.
*
* @remarks
* - This function unifies logical and numeric indexing into a single pipeline.
* - It is side-effect free.
* - It guarantees that downstream operations (selection or assignment)
* operate only on validated linear indices.
*
* - The returned indices may:
* * be empty (e.g., a(false))
* * contain duplicates (allowed in MATLAB)
* * be unordered (depending on index expressions)
*
* - Shape/orientation semantics are handled separately (e.g., in getElements
* and collapseResult).
*/
static resolveLinearIndices: (M: MultiArray, id: string, indexList: IndexArgument[], interpreter?: RuntimeDisplay) => number[];
/**
* Collect linear indices from a normalized indexing structure.
*
* This is a convenience wrapper around {@link iterateWithLinearIndex} that
* gathers all computed linear indices into a flat array.
*
* It is used in numeric indexing to convert a precomputed indexing structure
* (`idx`) into a list of linear indices (0-based), ready for selection or
* assignment.
*
* Behavior:
* - Iterates over all index combinations defined in `idx`
* - Converts each subscript tuple into a linear index
* - Preserves iteration order (column-major traversal)
*
* @param idx Normalized indexing structure (from computeIndexingStructure).
* @param dimension Target array dimensions.
* @param input Optional input string (used for error reporting).
* @param interpreter Optional interpreter (used to resolve dynamic expressions such as `end`).
*
* @returns Array of linear indices (0-based).
*
* @remarks
* - This function is side-effect free.
* - It does not perform validation; assumes `idx` is already normalized.
* - Equivalent to manually accumulating results from iterateWithLinearIndex.
* - Used to simplify and centralize index collection logic.
*/
private static collectLinearIndices;
/**
* Apply deletion on a MultiArray using a list of linear indices.
*
* This function performs linear deletion (A(I) = []) by removing the elements
* at the specified linear indices and compacting the remaining data.
*
* Behavior:
* - The array is first linearized (column-major order)
* - Elements at positions in `indices` are removed
* - The remaining elements are compacted into a new linear sequence
*
* Shape reconstruction:
* - If the original array is a vector:
* - Row vector: result remains a row vector
* - Column vector: result remains a column vector
*
* - If the original array is not a vector:
* - The result is converted to a column vector
* - This matches MATLAB behavior for ambiguous linear deletions
*
* Notes:
* - Indices are assumed to be 0-based and already validated
* - Duplicate indices are ignored (set semantics)
* - Order of remaining elements is preserved
*
* @param M Target MultiArray (modified in-place).
* @param indices Linear indices to remove (0-based).
*
* @remarks
* - This function implements the core of logical and linear deletion.
* - It does not validate index correctness or dimensional constraints;
* such checks must be performed upstream.
* - Multi-dimensional structural deletions (e.g., A(:,2) = []) are handled
* elsewhere (e.g., in deleteElements).
*/
private static applyDeletionFromIndices;
/**
* Retrieve elements from a MultiArray using MATLAB-like indexing semantics.
*
* This is the main entry point for element access (RHS indexing). It supports
* both logical and numeric indexing, including multi-dimensional access,
* linear indexing, colon expressions, and `end`.
*
* The indexing pipeline is divided into three stages:
*
* 1) Index resolution:
* - All index expressions are normalized into linear indices (0-based)
* - Performed by {@link resolveLinearIndices}
*
* 2) Element selection:
* - Elements are extracted in column-major order
* - Performed by {@link applyLinearSelection}
*
* 3) Shape reconstruction:
* - Result is reshaped according to MATLAB rules
* - Includes special handling for logical indexing and partial indexing
*
* Supported indexing modes:
*
* - Logical indexing:
* A(mask)
* • mask may be a logical array or scalar
* • scalar true → selects first element
* • scalar false → returns empty array
* • result shape follows mask orientation:
* - vector mask → preserves row/column orientation
* - matrix mask → result is a column vector
*
* - Linear indexing:
* A(I)
* • returns row vector unless I is ":" (full selection)
* • A(:) → column vector
*
* - Multi-dimensional indexing:
* A(i,j,...)
* • supports colon (:), ranges, and `end`
* • result shape determined by MATLAB collapsing rules
*
* @param M Source MultiArray.
* @param id Identifier (used for error reporting and `end` resolution).
* @param field Optional structure field access path.
* @param indexList Index arguments (numeric or logical).
* @param interpreter Optional interpreter (used for dynamic expressions such as `end`).
*
* @returns Resulting element(s), as a MultiArray or scalar.
*
* @throws EvalError or RangeError for invalid indexing operations.
*
* @remarks
* - This function is side-effect free.
* - Logical indexing is handled as a special case due to its distinct
* shape semantics.
* - Numeric indexing follows a unified pipeline using index structures
* and index plans.
*
* - Internally, all indexing is reduced to linear index operations,
* ensuring a consistent and extensible implementation.
*/
static readonly getElements: (M: MultiArray, id: string, field: string[], indexList: IndexArgument[], interpreter?: RuntimeDisplay) => ElementType;
/**
* Assign values to elements of a MultiArray using numerical (non-logical) indexing.
*
* This method implements MATLAB-compatible assignment semantics, including:
*
* • Linear indexing:
* A(I) = V
*
* • Subscript indexing:
* A(i, j, k, ...) = V
*
* • Scalar expansion (broadcasting):
* A(I) = scalar → scalar is replicated to match target size
*
* • Shape conformity:
* numel(V) must be either 1 or equal to the number of indexed elements
*
* • Automatic array expansion:
* - Vectors grow when indexed beyond current bounds
* - N-D arrays expand per-dimension when valid
*
* • Deletion via empty assignment:
* A(I) = []
* - Only allowed when exactly one index is non-colon
* - Delegated to deleteElements()
*
* Internal pipeline:
*
* 1. Linearize RHS → `linearizedRight`
* 2. Handle deletion case early
* 3. Normalize indexing via computeIndexingStructure()
* 4. Validate RHS conformity
* 5. Resolve or create target array (including expansion)
* 6. Collect linear indices via collectLinearIndices()
* → fully supports `end` and N-D indexing
* 7. Apply assignment via applyLinearAssignment()
*
* Notes:
*
* • Index validation and bounds checking are delegated to:
* - testIndex()
* - parseSubscript()
*
* • This function does NOT handle logical indexing.
* Logical indexing is resolved upstream via resolveLinearIndices().
*
* • Deletion logic is intentionally separated to preserve MATLAB constraints.
*
*
* @param scope Execution scope (symbol table)
* @param id Target variable name
* @param field Structure field access path (empty if none)
* @param indexList Raw index expressions (already evaluated)
* @param right Right-hand side MultiArray
* @param input Optional original expression (for error reporting / `end`)
* @param interpreter Interpreter instance (used for `end` resolution)
*
* @throws RangeError If indexing is invalid or nonconformant
* @throws EvalError If assignment dimensions are incompatible
*/
private static readonly setElementsNumerical;
/**
* Unified assignment entry point for MultiArray.
*
* Dispatches between logical indexing and numerical indexing semantics,
* implementing MATLAB-compatible behavior.
*
* Supported assignment modes:
* - Logical indexing: A(mask) = value
* - Linear indexing: A(I) = value
* - Subscript indexing: A(i,j,k,...) = value
*
* Logical indexing behavior:
* - The mask is interpreted in linear (column-major) order
* - Scalar logicals are promoted to a 1-element mask:
* - true → selects first element
* - false → selects no elements
* - Deletion is supported: A(mask) = []
* - Shape of the mask does not need to match M exactly (linear semantics)
*
* Numerical indexing behavior:
* - Delegated to setElementsNumerical
* - Supports:
* - multi-dimensional indexing
* - `end` keyword (via interpreter)
* - scalar expansion (broadcasting)
* - automatic array expansion
* - deletion via []
*
* Deletion semantics:
* - Logical deletion: handled here via linear filtering
* - Numerical deletion: delegated to deleteElements (MATLAB constraints apply)
*
* Structure field assignment:
* - If `field` is provided, assignment targets nested structure fields
*
* Error handling:
* - Invalid variable or non-MultiArray target → EvalError
* - Conformance and bounds errors are delegated to lower-level helpers
*
* @param scope Execution scope (variable resolution)
* @param id Target variable name
* @param field Structure field access path (empty for direct assignment)
* @param indexList Raw index expressions (logical or numeric)
* @param right Right-hand side value (MultiArray)
* @param input Optional source string (used for error reporting / `end`)
* @param interpreter Optional interpreter for dynamic expressions (e.g., `end`)
*/
static readonly setElements: (scope: IndexAssignmentScope, id: string, field: string[], indexList: IndexArgument[], right: MultiArray, input?: string, interpreter?: RuntimeDisplay) => void;
/**
* Delete elements from a MultiArray using MATLAB-compatible semantics.
*
* This function implements deletion via empty assignment:
* A(I) = []
*
* Supported modes:
*
* 1) Linear deletion
* - Triggered when a single index is provided (A(I))
* - Indices are resolved in column-major linear order
* - Result is a vector:
* - Preserves orientation if A is already a vector
* - Falls back to column vector otherwise
*
* 2) Dimension-based deletion (subscript indexing)
* Examples:
* A(:, j) → remove columns
* A(i, :) → remove rows
* A(:, :, k) → remove slices (N-D)
*
* Rules (MATLAB-compatible):
* - Exactly ONE dimension may differ from a full slice (:)
* - All other dimensions must be complete (i.e., ":" behavior)
* - The size of the affected dimension is reduced accordingly
*
* Behavior details:
* - Indices are first normalized via computeIndexingStructure
* - Subscripts (including "end") are resolved via parseSubscript
* - Linear indices are collected through iterateWithLinearIndex
* - Deletion is performed by filtering the linearized data and rebuilding
* the array with updated dimensions
*
* Error conditions:
* - Empty index list → RangeError
* - More than one non-colon dimension → RangeError
* - No effective deletion dimension → RangeError
*
* Notes:
* - Linear deletion is delegated to applyDeletionFromIndices
* - N-D deletion reconstructs the array in column-major order
* - Structure fields are preserved during deletion
*
* @param M Target MultiArray (modified in-place)
* @param indexList Raw index expressions (logical or numeric)
* @param input Optional original input string (used for error context)
* @param interpreter Optional interpreter (used to resolve expressions like "end")
*/
static readonly deleteElements: (M: MultiArray, indexList: IndexArgument[], input?: string, interpreter?: RuntimeDisplay) => void;
/**
* Factory function that creates MATLAB-compatible reduction functions
* (e.g., sum, prod, min, max, all, any) using MultiArray.reduce.
* @param callback Binary operation applied elementwise along dimension.
* @param type
* @param initial Optional initial value for reduction.
* @returns A function (M, DIM?) -> ElementType or MultiArray
*/
static readonly reduceFactory: (callback: ReduceCallbackOrComparisonType, type: ReduceType, initial?: ReduceInitialType) => ReduceHandlerType;
}
export { type ElementType, type IndexArgument, MultiArray };
declare const _default: {
MultiArray: typeof MultiArray;
};
export default _default;