Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Rename apply to mapSlices #3357

Merged
merged 4 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/core/extension.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ where:
created again when there is a change in the configuration. This is for
example used for the constants like `pi`, which is different depending
on the configsetting `number` which can be numbers or BigNumbers.
- `formerly: string`. If present, the created function will also be
accessible on the instance under the name given by the value of
`formerly` as a (deprecated) synonym for the specified `name`. This
facility should only be used when a function is renamed, to allow
temporary use of the previous name, for backward compatibility.

Here an example of a factory function which depends on `multiply`:

Expand Down
19 changes: 15 additions & 4 deletions src/core/function/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,27 +294,38 @@ export function importFactory (typed, load, math, importedFactories) {
}
}

const former = factory.meta?.formerly ?? ''
const needsTransform = isTransformFunctionFactory(factory) ||
factoryAllowedInExpressions(factory)
const withTransform = math.expression.mathWithTransform

// TODO: add unit test with non-lazy factory
if (!factory.meta || factory.meta.lazy !== false) {
lazy(namespace, name, resolver)
if (former) lazy(namespace, former, resolver)

// FIXME: remove the `if (existing &&` condition again. Can we make sure subset is loaded before subset.transform? (Name collision, and no dependencies between the two)
if (existing && existingTransform) {
_deleteTransform(name)
if (former) _deleteTransform(former)
} else {
if (isTransformFunctionFactory(factory) || factoryAllowedInExpressions(factory)) {
lazy(math.expression.mathWithTransform, name, () => namespace[name])
if (needsTransform) {
lazy(withTransform, name, () => namespace[name])
if (former) lazy(withTransform, former, () => namespace[name])
}
}
} else {
namespace[name] = resolver()
if (former) namespace[former] = namespace[name]

// FIXME: remove the `if (existing &&` condition again. Can we make sure subset is loaded before subset.transform? (Name collision, and no dependencies between the two)
if (existing && existingTransform) {
_deleteTransform(name)
if (former) _deleteTransform(former)
} else {
if (isTransformFunctionFactory(factory) || factoryAllowedInExpressions(factory)) {
lazy(math.expression.mathWithTransform, name, () => namespace[name])
if (needsTransform) {
lazy(withTransform, name, () => namespace[name])
if (former) lazy(withTransform, former, () => namespace[name])
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/expression/embeddedDocs/embeddedDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ import { andDocs } from './function/logical/and.js'
import { notDocs } from './function/logical/not.js'
import { orDocs } from './function/logical/or.js'
import { xorDocs } from './function/logical/xor.js'
import { mapSlicesDocs } from './function/matrix/mapSlices.js'
import { columnDocs } from './function/matrix/column.js'
import { concatDocs } from './function/matrix/concat.js'
import { countDocs } from './function/matrix/count.js'
Expand Down Expand Up @@ -440,6 +441,7 @@ export const embeddedDocs = {
xor: xorDocs,

// functions - matrix
mapSlices: mapSlicesDocs,
concat: concatDocs,
count: countDocs,
cross: crossDocs,
Expand Down
14 changes: 14 additions & 0 deletions src/expression/embeddedDocs/function/matrix/mapSlices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const mapSlicesDocs = {
name: 'mapSlices',
category: 'Matrix',
syntax: ['mapSlices(A, dim, callback)'],
description:
'Generate a matrix one dimension less than A by applying callback to ' +
'each slice of A along dimension dim.',
examples: [
'A = [[1, 2], [3, 4]]',
'mapSlices(A, 1, sum)', // returns [4, 6]
'mapSlices(A, 2, product)' // returns [2, 12]
],
seealso: ['map', 'forEach']
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { errorTransform } from './utils/errorTransform.js'
import { factory } from '../../utils/factory.js'
import { createApply } from '../../function/matrix/apply.js'
import { createMapSlices } from '../../function/matrix/mapSlices.js'
import { isBigNumber, isNumber } from '../../utils/is.js'

const name = 'apply'
const name = 'mapSlices'
const dependencies = ['typed', 'isInteger']

/**
* Attach a transform function to math.apply
* Attach a transform function to math.mapSlices
* Adds a property transform containing the transform function.
*
* This transform changed the last `dim` parameter of function apply
* This transform changed the last `dim` parameter of function mapSlices
* from one-based to zero based
*/
export const createApplyTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, isInteger }) => {
const apply = createApply({ typed, isInteger })
export const createMapSlicesTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, isInteger }) => {
const mapSlices = createMapSlices({ typed, isInteger })

// @see: comment of concat itself
return typed('apply', {
return typed('mapSlices', {
'...any': function (args) {
// change dim from one-based to zero-based
const dim = args[1]
Expand All @@ -29,10 +29,10 @@ export const createApplyTransform = /* #__PURE__ */ factory(name, dependencies,
}

try {
return apply.apply(null, args)
return mapSlices.apply(null, args)
} catch (err) {
throw errorTransform(err)
}
}
})
}, { isTransformFunction: true })
}, { isTransformFunction: true, ...createMapSlices.meta })
6 changes: 3 additions & 3 deletions src/expression/transform/quantileSeq.transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createQuantileSeq } from '../../function/statistics/quantileSeq.js'
import { lastDimToZeroBase } from './utils/lastDimToZeroBase.js'

const name = 'quantileSeq'
const dependencies = ['typed', 'bignumber', 'add', 'subtract', 'divide', 'multiply', 'partitionSelect', 'compare', 'isInteger', 'smaller', 'smallerEq', 'larger']
const dependencies = ['typed', 'bignumber', 'add', 'subtract', 'divide', 'multiply', 'partitionSelect', 'compare', 'isInteger', 'smaller', 'smallerEq', 'larger', 'mapSlices']

/**
* Attach a transform function to math.quantileSeq
Expand All @@ -12,8 +12,8 @@ const dependencies = ['typed', 'bignumber', 'add', 'subtract', 'divide', 'multip
* This transform changed the `dim` parameter of function std
* from one-based to zero based
*/
export const createQuantileSeqTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, bignumber, add, subtract, divide, multiply, partitionSelect, compare, isInteger, smaller, smallerEq, larger }) => {
const quantileSeq = createQuantileSeq({ typed, bignumber, add, subtract, divide, multiply, partitionSelect, compare, isInteger, smaller, smallerEq, larger })
export const createQuantileSeqTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, bignumber, add, subtract, divide, multiply, partitionSelect, compare, isInteger, smaller, smallerEq, larger, mapSlices }) => {
const quantileSeq = createQuantileSeq({ typed, bignumber, add, subtract, divide, multiply, partitionSelect, compare, isInteger, smaller, smallerEq, larger, mapSlices })

return typed('quantileSeq', {
'Array | Matrix, number | BigNumber': quantileSeq,
Expand Down
6 changes: 3 additions & 3 deletions src/expression/transform/variance.transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createVariance } from '../../function/statistics/variance.js'
import { lastDimToZeroBase } from './utils/lastDimToZeroBase.js'

const name = 'variance'
const dependencies = ['typed', 'add', 'subtract', 'multiply', 'divide', 'apply', 'isNaN']
const dependencies = ['typed', 'add', 'subtract', 'multiply', 'divide', 'mapSlices', 'isNaN']

/**
* Attach a transform function to math.var
Expand All @@ -13,8 +13,8 @@ const dependencies = ['typed', 'add', 'subtract', 'multiply', 'divide', 'apply',
* This transform changed the `dim` parameter of function var
* from one-based to zero based
*/
export const createVarianceTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, add, subtract, multiply, divide, apply, isNaN }) => {
const variance = createVariance({ typed, add, subtract, multiply, divide, apply, isNaN })
export const createVarianceTransform = /* #__PURE__ */ factory(name, dependencies, ({ typed, add, subtract, multiply, divide, mapSlices, isNaN }) => {
const variance = createVariance({ typed, add, subtract, multiply, divide, mapSlices, isNaN })

return typed(name, {
'...any': function (args) {
Expand Down
4 changes: 2 additions & 2 deletions src/factoriesAny.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export { createSplitUnit } from './type/unit/function/splitUnit.js'
export { createUnaryMinus } from './function/arithmetic/unaryMinus.js'
export { createUnaryPlus } from './function/arithmetic/unaryPlus.js'
export { createAbs } from './function/arithmetic/abs.js'
export { createApply } from './function/matrix/apply.js'
export { createMapSlices } from './function/matrix/mapSlices.js'
export { createAddScalar } from './function/arithmetic/addScalar.js'
export { createSubtractScalar } from './function/arithmetic/subtractScalar.js'
export { createCbrt } from './function/arithmetic/cbrt.js'
Expand Down Expand Up @@ -340,7 +340,7 @@ export {
createWeakMixingAngle,
createWienDisplacement
} from './type/unit/physicalConstants.js'
export { createApplyTransform } from './expression/transform/apply.transform.js'
export { createMapSlicesTransform } from './expression/transform/mapSlices.transform.js'
export { createColumnTransform } from './expression/transform/column.transform.js'
export { createFilterTransform } from './expression/transform/filter.transform.js'
export { createForEachTransform } from './expression/transform/forEach.transform.js'
Expand Down
4 changes: 2 additions & 2 deletions src/factoriesNumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export const createOr = /* #__PURE__ */ createNumberFactory('or', orNumber)
export const createXor = /* #__PURE__ */ createNumberFactory('xor', xorNumber)

// matrix
export { createApply } from './function/matrix/apply.js'
export { createMapSlices } from './function/matrix/mapSlices.js'
export { createFilter } from './function/matrix/filter.js'
export { createForEach } from './function/matrix/forEach.js'
export { createMap } from './function/matrix/map.js'
Expand Down Expand Up @@ -299,7 +299,7 @@ export const createTan = /* #__PURE__ */ createNumberFactory('tan', tanNumber)
export const createTanh = /* #__PURE__ */ createNumberFactory('tanh', tanhNumber)

// transforms
export { createApplyTransform } from './expression/transform/apply.transform.js'
export { createMapSlicesTransform } from './expression/transform/mapSlices.transform.js'
export { createFilterTransform } from './expression/transform/filter.transform.js'
export { createForEachTransform } from './expression/transform/forEach.transform.js'
export { createMapTransform } from './expression/transform/map.transform.js'
Expand Down
2 changes: 1 addition & 1 deletion src/function/matrix/ctranspose.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const createCtranspose = /* #__PURE__ */ factory(name, dependencies, ({ t
* Examples:
*
* const A = [[1, 2, 3], [4, 5, math.complex(6,7)]]
* math.ctranspose(A) // returns [[1, 4], [2, 5], [3, {re:6,im:7}]]
* math.ctranspose(A) // returns [[1, 4], [2, 5], [3, {re:6,im:-7}]]
*
* See also:
*
Expand Down
29 changes: 17 additions & 12 deletions src/function/matrix/apply.js → src/function/matrix/mapSlices.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import { arraySize } from '../../utils/array.js'
import { isMatrix } from '../../utils/is.js'
import { IndexError } from '../../error/IndexError.js'

const name = 'apply'
const name = 'mapSlices'
const dependencies = ['typed', 'isInteger']

export const createApply = /* #__PURE__ */ factory(name, dependencies, ({ typed, isInteger }) => {
export const createMapSlices = /* #__PURE__ */ factory(name, dependencies, ({ typed, isInteger }) => {
/**
* Apply a function that maps an array to a scalar
* along a given axis of a matrix or array.
* Returns a new matrix or array with one less dimension than the input.
*
* Syntax:
*
* math.apply(A, dim, callback)
* math.mapSlices(A, dim, callback)
*
* Where:
*
Expand All @@ -25,19 +25,24 @@ export const createApply = /* #__PURE__ */ factory(name, dependencies, ({ typed,
* const A = [[1, 2], [3, 4]]
* const sum = math.sum
*
* math.apply(A, 0, sum) // returns [4, 6]
* math.apply(A, 1, sum) // returns [3, 7]
* math.mapSlices(A, 0, sum) // returns [4, 6]
* math.mapSlices(A, 1, sum) // returns [3, 7]
*
* See also:
*
* map, filter, forEach
*
* Note:
*
* `mapSlices()` is also currently available via its deprecated
* synonym `apply()`.
*
* @param {Array | Matrix} array The input Matrix
* @param {number} dim The dimension along which the callback is applied
* @param {Function} callback The callback function that is applied. This Function
* should take an array or 1-d matrix as an input and
* return a number.
* @return {Array | Matrix} res The residual matrix with the function applied over some dimension.
* @return {Array | Matrix} res The residual matrix with the function mapped on the slices over some dimension.
*/
return typed(name, {
'Array | Matrix, number | BigNumber, function': function (mat, dim, callback) {
Expand All @@ -51,13 +56,13 @@ export const createApply = /* #__PURE__ */ factory(name, dependencies, ({ typed,
}

if (isMatrix(mat)) {
return mat.create(_apply(mat.valueOf(), dim, callback), mat.datatype())
return mat.create(_mapSlices(mat.valueOf(), dim, callback), mat.datatype())
} else {
return _apply(mat, dim, callback)
return _mapSlices(mat, dim, callback)
}
}
})
})
}, { formerly: 'apply' })

/**
* Recursively reduce a matrix
Expand All @@ -67,7 +72,7 @@ export const createApply = /* #__PURE__ */ factory(name, dependencies, ({ typed,
* @returns {Array} ret
* @private
*/
function _apply (mat, dim, callback) {
function _mapSlices (mat, dim, callback) {
let i, ret, tran

if (dim <= 0) {
Expand All @@ -77,14 +82,14 @@ function _apply (mat, dim, callback) {
tran = _switch(mat)
ret = []
for (i = 0; i < tran.length; i++) {
ret[i] = _apply(tran[i], dim - 1, callback)
ret[i] = _mapSlices(tran[i], dim - 1, callback)
}
return ret
}
} else {
ret = []
for (i = 0; i < mat.length; i++) {
ret[i] = _apply(mat[i], dim - 1, callback)
ret[i] = _mapSlices(mat[i], dim - 1, callback)
}
return ret
}
Expand Down
9 changes: 3 additions & 6 deletions src/function/statistics/quantileSeq.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { isNumber } from '../../utils/is.js'
import { flatten } from '../../utils/array.js'
import { factory } from '../../utils/factory.js'
import { createApply } from '../matrix/apply.js'

const name = 'quantileSeq'
const dependencies = ['typed', '?bignumber', 'add', 'subtract', 'divide', 'multiply', 'partitionSelect', 'compare', 'isInteger', 'smaller', 'smallerEq', 'larger']

export const createQuantileSeq = /* #__PURE__ */ factory(name, dependencies, ({ typed, bignumber, add, subtract, divide, multiply, partitionSelect, compare, isInteger, smaller, smallerEq, larger }) => {
const apply = createApply({ typed, isInteger })
const dependencies = ['typed', '?bignumber', 'add', 'subtract', 'divide', 'multiply', 'partitionSelect', 'compare', 'isInteger', 'smaller', 'smallerEq', 'larger', 'mapSlices']

export const createQuantileSeq = /* #__PURE__ */ factory(name, dependencies, ({ typed, bignumber, add, subtract, divide, multiply, partitionSelect, compare, isInteger, smaller, smallerEq, larger, mapSlices }) => {
/**
* Compute the prob order quantile of a matrix or a list with values.
* The sequence is sorted and the middle value is returned.
Expand Down Expand Up @@ -55,7 +52,7 @@ export const createQuantileSeq = /* #__PURE__ */ factory(name, dependencies, ({
})

function _quantileSeqDim (data, prob, sorted, dim, fn) {
return apply(data, dim, x => fn(x, prob, sorted))
return mapSlices(data, dim, x => fn(x, prob, sorted))
}

function _quantileSeqProbNumber (data, probOrN, sorted) {
Expand Down
6 changes: 3 additions & 3 deletions src/function/statistics/variance.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { improveErrorMessage } from './utils/improveErrorMessage.js'
const DEFAULT_NORMALIZATION = 'unbiased'

const name = 'variance'
const dependencies = ['typed', 'add', 'subtract', 'multiply', 'divide', 'apply', 'isNaN']
const dependencies = ['typed', 'add', 'subtract', 'multiply', 'divide', 'mapSlices', 'isNaN']

export const createVariance = /* #__PURE__ */ factory(name, dependencies, ({ typed, add, subtract, multiply, divide, apply, isNaN }) => {
export const createVariance = /* #__PURE__ */ factory(name, dependencies, ({ typed, add, subtract, multiply, divide, mapSlices, isNaN }) => {
/**
* Compute the variance of a matrix or a list with values.
* In case of a multidimensional array or matrix, the variance over all
Expand Down Expand Up @@ -152,7 +152,7 @@ export const createVariance = /* #__PURE__ */ factory(name, dependencies, ({ typ
if (array.length === 0) {
throw new SyntaxError('Function variance requires one or more parameters (0 provided)')
}
return apply(array, dim, (x) => _var(x, normalization))
return mapSlices(array, dim, (x) => _var(x, normalization))
} catch (err) {
throw improveErrorMessage(err, 'variance')
}
Expand Down
2 changes: 1 addition & 1 deletion src/function/string/hex.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const dependencies = ['typed', 'format']
*
* Examples:
*
* math.hex(240) // returns "0xF0"
* math.hex(240) // returns "0xf0"
*
* See also:
*
Expand Down
2 changes: 1 addition & 1 deletion src/function/trigonometry/acoth.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const createAcoth = /* #__PURE__ */ factory(name, dependencies, ({ typed,
*
* Examples:
*
* math.acoth(0.5) // returns 0.8047189562170503
* math.acoth(0.5) // returns 0.5493061443340548 - 1.5707963267948966i
*
* See also:
*
Expand Down
2 changes: 1 addition & 1 deletion src/function/trigonometry/acsc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const createAcsc = /* #__PURE__ */ factory(name, dependencies, ({ typed,
*
* math.acsc(2) // returns 0.5235987755982989
* math.acsc(0.5) // returns Complex 1.5707963267948966 -1.3169578969248166i
* math.acsc(math.csc(1.5)) // returns number ~1.5
* math.acsc(math.csc(1.5)) // returns number 1.5
*
* See also:
*
Expand Down
2 changes: 1 addition & 1 deletion src/function/trigonometry/asin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const createAsin = /* #__PURE__ */ factory(name, dependencies, ({ typed,
* Examples:
*
* math.asin(0.5) // returns number 0.5235987755982989
* math.asin(math.sin(1.5)) // returns number ~1.5
* math.asin(math.sin(1.5)) // returns number 1.5
*
* math.asin(2) // returns Complex 1.5707963267948966 -1.3169578969248166i
*
Expand Down
Loading