From 40e18c732c68bc087628442bd504a48152087d81 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Tue, 28 Jan 2025 18:05:28 -0800 Subject: [PATCH] fix: Update types and add tests as requested by review --- src/function/matrix/matrixFromFunction.js | 39 +++++++++++- test/typescript-tests/testTypes.ts | 20 ++++++ types/index.d.ts | 76 +++++++++++------------ 3 files changed, 94 insertions(+), 41 deletions(-) diff --git a/src/function/matrix/matrixFromFunction.js b/src/function/matrix/matrixFromFunction.js index 996e745b32..60b0fec11a 100644 --- a/src/function/matrix/matrixFromFunction.js +++ b/src/function/matrix/matrixFromFunction.js @@ -6,8 +6,10 @@ const dependencies = ['typed', 'matrix', 'isZero'] export const createMatrixFromFunction = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, isZero }) => { /** * Create a matrix by evaluating a generating function at each index. - * The simplest overload returns a multi-dimensional array as long as `size` is an array. - * Passing `size` as a Matrix or specifying a `format` will result in returning a Matrix. + * The simplest overload returns a multi-dimensional array as long as `size` + * is an array. + * Passing `size` as a Matrix or specifying a `format` will result in + * returning a Matrix. * * Syntax: * @@ -17,6 +19,37 @@ export const createMatrixFromFunction = /* #__PURE__ */ factory(name, dependenci * math.matrixFromFunction(size, format, fn) * math.matrixFromFunction(size, format, datatype, fn) * + * Where: + * + * - `size: (number[] | Matrix)` + * A vector giving the extent of the array to be created in each + * dimension. If size has one entry, a vector is created; if it + * has two, a rectangular array/Matrix is created; if three, a + * three-dimensional array/Matrix is created; and so on. + * - `fn: (index: number[]) => MathType` + * The callback function that will generate the entries of the + * matrix. It is called in turn with the index of each entry of + * the matrix. The index is always an ordinary array of numbers + * with the same length as _size_. So for vectors, you will get + * indices like `[0]` or `[1]`, whereas for matrices, you will + * get indices like `[2, 0]` or `[1,3]`. The return value may + * be any type that can go in an array or Matrix entry, although + * if you supply the _datatype_ argument, you must yourself ensure + * the type of the return value matches. Note that currently, + * your callback _fn_ will receive 0-based indices for the matrix + * entries, regardless of whether matrixFromFunction is invoked + * directly from JavaScript or via the mathjs expression language. + * - `format: 'dense'|'sparse'` + * Specifies the storage format for the resulting Matrix. Note that + * if this argument is given, the return value will always be a + * Matrix (rather than possibly an Array). + * - `datatype: string` + * Specifies the data type of entries of the new matrix. If given, + * it should be the name of a data type that mathjs supports, as + * returned by the math.typeOf function. It is up to the caller + * to make certain that all values returned by _fn_ are consistent + * with this datatype if specified. + * * Examples: * * math.matrixFromFunction([3,3], i => i[0] - i[1]) // an antisymmetric matrix @@ -25,7 +58,7 @@ export const createMatrixFromFunction = /* #__PURE__ */ factory(name, dependenci * * See also: * - * matrix, zeros + * matrix, typeOf, zeros * * @param {Array | Matrix} size The size of the matrix to be created * @param {function} fn Callback function invoked for every entry in the matrix diff --git a/test/typescript-tests/testTypes.ts b/test/typescript-tests/testTypes.ts index 8bb38dfb4e..622fff605b 100644 --- a/test/typescript-tests/testTypes.ts +++ b/test/typescript-tests/testTypes.ts @@ -1268,6 +1268,26 @@ Matrices examples const _c = math.multiply(a, b) const f: Matrix = math.matrix([1, 0]) const _d: Matrix = f.subset(math.index(1)) + const g: number[] = + math.matrixFromFunction([3], (i: number[]) => i[0] * i[0]) + assert.strictEqual(g[2], 4) + const h: Matrix = math.matrixFromFunction( + [2, 2], + (i: number[]) => math.fraction(i[0], i[1] + 1), + 'dense' + ) + const j: number[][] = math.matrixFromRows( + [1, 2, 3], + math.matrix([[4], [5], [6]]) + ) + assert.strictEqual(j[1][2], 6) + const _k: Matrix = math.matrixFromRows(f, math.row(h, 1)) + const l: number[][] = math.matrixFromColumns( + [1, 2, 3], + math.matrix([[4], [5], [6]]) + ) + assert.strictEqual(l[2][1], 6) + const _m: Matrix = math.matrixFromColumns(f, math.row(h, 1)) } // get a sub matrix diff --git a/types/index.d.ts b/types/index.d.ts index bdbb319b4a..63ab6973ce 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -23,10 +23,8 @@ export type MathExpression = string | string[] | MathCollection // add type for Matrix Callback Function and Matrix Storage Format export type MatrixStorageFormat = 'dense' | 'sparse' - -export interface MatrixFromFunctionCallback { - (value: T): number | BigNumber -} +export type MatrixFromFunctionCallback = + (index: number[]) => T // eslint-disable-next-line @typescript-eslint/no-explicit-any export type FactoryFunction = (scope: any) => T @@ -759,12 +757,12 @@ export interface MathJsInstance extends MathJsFactory { */ matrix( data: MathCollection | string[], - format?: 'sparse' | 'dense', + format?: MatrixStorageFormat, dataType?: string ): Matrix matrix( data: MathCollection, - format?: 'sparse' | 'dense', + format?: MatrixStorageFormat, dataType?: string ): Matrix @@ -1333,19 +1331,19 @@ export interface MathJsInstance extends MathJsFactory { * Create a dense matrix from vectors as individual rows. If you pass column vectors, they will be transposed (but not conjugated!) * @param rows - a multi-dimensional number array or matrix */ - matrixFromRows(...rows: T[]): T[] - matrixFromRows(rows: T): T[] + matrixFromRows(...rows: Matrix[]): Matrix + matrixFromRows( + ...rows: (T[] | [T][] | Matrix)[] + ): T[][] /** * Create a dense matrix from vectors as individual columns. If you pass row vectors, they will be transposed (but not conjugated!) * @param cols - a multi-dimensional number array or matrix */ - matrixFromColumns( - ...cols: T[] - ): T[] | Matrix - matrixFromColumns( - cols: T - ): T[] | Matrix + matrixFromColumns(...cols: Matrix[]): Matrix + matrixFromColumns( + ...cols: (T[] | [T][] | Matrix)[] + ): T[][] /** * Create a matrix by evaluating a generating function at each index. The simplest overload returns a multi-dimensional array as long as size is an array. Passing size as a Matrix or specifying a format will result in returning a Matrix. * @param size - the size of the matrix to be created @@ -1353,32 +1351,34 @@ export interface MathJsInstance extends MathJsFactory { * @param format - The Matrix storage format, either 'dense' or 'sparse' * @param datatype - Type of the values */ - matrixFromFunction( - size: T, - fn: MatrixFromFunctionCallback<(number | BigNumber)[]> - ): T[] | Matrix - matrixFromFunction( - size: T, - fn: MatrixFromFunctionCallback<(number | BigNumber)[]>, - format: MatrixStorageFormat - ): T[] | Matrix - matrixFromFunction( - size: T, - fn: MatrixFromFunctionCallback<(number | BigNumber)[]>, - format: MatrixStorageFormat, - datatype: string - ): T[] | Matrix - matrixFromFunction( - size: T, + matrixFromFunction( + size: [number], + fn: MatrixFromFunctionCallback + ): T[] + matrixFromFunction( + size: [number, number], + fn: MatrixFromFunctionCallback + ): T[][] + matrixFromFunction( + size: number[], + fn: MatrixFromFunctionCallback + ): MathArray + matrixFromFunction( + size: Matrix, + fn: MatrixFromFunctionCallback + ): Matrix + matrixFromFunction( + size: number[] | Matrix, + fn: MatrixFromFunctionCallback, format: MatrixStorageFormat, - fn: MatrixFromFunctionCallback<(number | BigNumber)[]> - ): T[] | Matrix - matrixFromFunction( - size: T, + datatype?: string + ): Matrix + matrixFromFunction( + size: number[] | Matrix, format: MatrixStorageFormat, - datatype: string, - fn: MatrixFromFunctionCallback<(number | BigNumber)[]> - ): T[] | Matrix + fn: MatrixFromFunctionCallback, + datatype?: string + ): Matrix /** * Calculate the least common multiple for two or more values or arrays. * lcm is defined as: lcm(a, b) = abs(a * b) / gcd(a, b) For matrices,