Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6b0ea89
feat: implement broadcastSizes and broadcastTo functions for matrix o…
dvd101x Dec 9, 2025
cd83def
Included new functions in factories
dvd101x Dec 10, 2025
f2a2943
Fixed typed issues
dvd101x Dec 26, 2025
756aa83
format
dvd101x Dec 26, 2025
a804f9d
Added embedded docs
dvd101x Dec 26, 2025
cfe6490
Added tests for broadcastSizes
dvd101x Dec 28, 2025
5224a45
Added tests for broadcastMatrices and fixed an issue with broadcastAr…
dvd101x Dec 28, 2025
b212e6f
Merge branch 'develop' into broadcasting-functions
dvd101x Dec 28, 2025
4315651
Added test for broadcastTo
dvd101x Dec 28, 2025
c99c48a
Added more tests to broadcastTo
dvd101x Dec 28, 2025
d749405
Add types
dvd101x Dec 28, 2025
c267a8c
Fixed wrong example in jsdocs
dvd101x Dec 28, 2025
23bc583
Added hisotry
dvd101x Dec 29, 2025
26367b5
Format
dvd101x Dec 29, 2025
54338f5
Fix typos and grammar errors
dvd101x Jan 9, 2026
5e13b30
Merge branch 'develop' into broadcasting-functions
dvd101x Jan 9, 2026
d593869
Merge branch 'develop' into broadcasting-functions
dvd101x Jan 21, 2026
41d2db1
Merge branch 'develop' into broadcasting-functions
dvd101x Feb 18, 2026
bb50f2b
Improved syntax
dvd101x Apr 5, 2026
826d36e
Extended description of broadcastSizes
dvd101x Apr 5, 2026
9f761fc
Avoid matrix create shortcut.
dvd101x Apr 5, 2026
1b4afd9
Added references to broadcasting rules
dvd101x Apr 5, 2026
215502f
Merge branch 'develop' into broadcasting-functions
dvd101x Apr 5, 2026
3a19f48
Format
dvd101x Apr 5, 2026
714f1bf
Merge branch 'develop' into broadcasting-functions
dvd101x May 12, 2026
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
6 changes: 6 additions & 0 deletions src/expression/embeddedDocs/embeddedDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ import { partitionSelectDocs } from './function/matrix/partitionSelect.js'
import { rangeDocs } from './function/matrix/range.js'
import { reshapeDocs } from './function/matrix/reshape.js'
import { resizeDocs } from './function/matrix/resize.js'
import { broadcastMatricesDocs } from './function/matrix/broadcastMatrices.js'
import { broadcastToDocs } from './function/matrix/broadcastTo.js'
import { broadcastSizesDocs } from './function/matrix/broadcastSizes.js'
import { rotateDocs } from './function/matrix/rotate.js'
import { rotationMatrixDocs } from './function/matrix/rotationMatrix.js'
import { rowDocs } from './function/matrix/row.js'
Expand Down Expand Up @@ -481,6 +484,9 @@ export const embeddedDocs = {
partitionSelect: partitionSelectDocs,
range: rangeDocs,
resize: resizeDocs,
broadcastMatrices: broadcastMatricesDocs,
broadcastTo: broadcastToDocs,
broadcastSizes: broadcastSizesDocs,
reshape: reshapeDocs,
rotate: rotateDocs,
rotationMatrix: rotationMatrixDocs,
Expand Down
16 changes: 16 additions & 0 deletions src/expression/embeddedDocs/function/matrix/broadcastMatrices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const broadcastMatricesDocs = {
name: 'broadcastMatrices',
category: 'Matrix',
syntax: [
'broadcastMatrices(A, B)'
],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the syntax read 'broadcastMatrices(A, B, ...)' since any number of arguments are allowed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, yes you are right. Fixed

description: 'Broadcast any number of arrays or matrices against each other.',
examples: [
'broadcastMatrices([1, 2, 3], [[1], [2], [3]])',
'broadcastMatrices([1, 2; 3, 4], [5, 6; 7, 8])',
'broadcastMatrices([1, 2, 3], [5], [[10], [20], [30]])'
],
seealso: [
'size', 'reshape', 'broadcastSizes', 'broadcastTo'
]
}
16 changes: 16 additions & 0 deletions src/expression/embeddedDocs/function/matrix/broadcastSizes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const broadcastSizesDocs = {
name: 'broadcastSizes',
category: 'Matrix',
syntax: [
'broadcastSizes(sizeA, sizeB)'
],
description: 'Broadcast the sizes of matrices to a compatible size',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, I am concerned about at least the grammatical correctness here. It's not that any sizes are being broadcast here, per se, is it, but rather that the size resulting from a broadcast is being computed, right? So shouldn't the description be something more like "Compute the size that would result from broadcasting a list of matrices of the given sizes, if possible"? (Again, this function can throw an error if the sizes are incompatible, correct?)

This also observation also, for me, calls into question the name of the function. Would broadcastSize or sizeOfBroadcast be more descriptive, again since no sizes are being broadcast, per se?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The terminology used by numpy is

numpy.broadcast_shapes(*args)
Broadcast the input shapes into a single shape.

I think I understand where are you coming from, because the original sizes are kept intact. But maybe it's an implicit definition, because when one adds numbers, nothing happens to the numbers, we could say is to compute the result from adding numbers.

Yes this function will throw an error for incompatible sizes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I meant that it's the matrices that are broadcast, not their sizes. This function does not actually do any broadcasting. It just computes a size, and so it should be named accordingly, I think. Your thoughts?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any further thoughts here? I am recommending:

  • rename the function to either sizeOfBroadcast or broadcastSize, and
  • describe it as Compute the size of a matrix that would result from broadcasting matrices of the given sizes, if they are compatible

because, as a matter of the plain meanings of the words, a matrix/array can be broadcast, but a size cannot be broadcast.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, even though I had a response planned from the first comment I was debating myself on how to present the response.

Broadcasting, when applied to a matrix's shape, does not imply treating the shape itself as a data structure to be broadcasted. Much like the phrase 'running water' describes flow rather than the physical stride of a 'running person,' broadcasting a shape is a functional convention.

I don't know if the convention all comes from numpy, but it's a common trend stdlib: broadcast-shapes

I think the name of the function is ok as is, but it could be described as you suggest to avoid a circular definition.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, we should just strive for both the clearest name of the function and the clearest description of what it does. If you think that "broadcastSizes(s, t, u)" is clearer than "broadcastSize(s, t, u)", I am not going to quibble. But I do prefer a more explicit description, thanks.

examples: [
'broadcastSizes([3, 1, 3], [3, 3])',
'broadcastSizes([2, 1], [2, 2])',
'broadcastSizes([1, 3], [2, 3], [4, 2, 3])'
],
seealso: [
'size', 'reshape', 'broadcastTo', 'broadcastMatrices'
]
}
15 changes: 15 additions & 0 deletions src/expression/embeddedDocs/function/matrix/broadcastTo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const broadcastToDocs = {
name: 'broadcastTo',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry about the name of this function. It seems to me that since sizes look like matrices, visually, broadcastTo([3], [2, 2]) could look like it is supposed to broadcast the first matrix to be compatible with the second, i.e. produce [3,3] rather than [3, 3; 3, 3]. I would strongly recommend considering renaming the function to broadcastToSize([3], [2, 2]) to avoid this ambiguity.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand. Many of these are taken from numpy and have counterparts in jax / mlx / pytorch and maybe others.

numpy.broadcast_to(array, shape, subok=False)
Broadcast an array to a new shape.

I don't have a strong opinion on this, just please review if it makes sense to follow that convention.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am the one less familiar with the territory here. That's why this was couched as a suggestion. Please select the name you think is best, including leaving it be, unless @josdejong weighs in otherwise. Please just post your final decision here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, to land this PR we need a decision on the final name here. If you are on the fence, I recommend switching to broadcastToSize() in an effort to steer away from the ambiguity I raised. It seems to me a more fully specified name can't be harmful here. (And I don't think we need to worry too much about fidelity to numpy names, since after all to begin with what they call a "shape" we call a "size" so we're not adopting numpy terminology right from the start.)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree about the differences between shape and size. I'm considering broadcastToSize(), will review and resolve this comment.

category: 'Matrix',
syntax: [
'broadcastTo(A, size)'
],
description: 'Broadcast a matrix to a compatible size',
examples: [
'broadcastTo([1, 2, 3], [3, 3])',
'broadcastTo([1, 2; 3, 4], [2, 2])'
],
seealso: [
'size', 'reshape', 'broadcastSizes', 'broadcastMatrices'
]
}
3 changes: 3 additions & 0 deletions src/factoriesAny.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ export { createOnes } from './function/matrix/ones.js'
export { createRange } from './function/matrix/range.js'
export { createReshape } from './function/matrix/reshape.js'
export { createResize } from './function/matrix/resize.js'
export { createBroadcastMatrices } from './function/matrix/broadcastMatrices.js'
export { createBroadcastSizes } from './function/matrix/broadcastSizes.js'
export { createBroadcastTo } from './function/matrix/broadcastTo.js'
export { createRotate } from './function/matrix/rotate.js'
export { createRotationMatrix } from './function/matrix/rotationMatrix.js'
export { createRow } from './function/matrix/row.js'
Expand Down
45 changes: 45 additions & 0 deletions src/function/matrix/broadcastMatrices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { broadcastArrays } from '../../utils/array.js'
import { factory } from '../../utils/factory.js'
import { isMatrix } from '../../utils/is.js'

const name = 'broadcastMatrices'
const dependencies = ['typed']

export const createBroadcastMatrices = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => {
/**
* Broadcast any number of arrays or matrices against each other.
*
* Syntax:
*
* math.broadcastMatrices(x, y)
* math.broadcastMatrices(x, y, ...)
*
* Examples:
*
* math.broadcastMatrices([1, 2], [[3], [4]]) // returns [[[1, 2], [1, 2]], [[3, 3], [4, 4]]]
* math.broadcastMatrices([2, 3]) // returns [[2, 3]]
* math.broadcastMatrices([2, 3], [3, 1]) // returns [[2, 3], [3, 1]]
*
* See also:
*
* size, reshape, broadcastSizes, broadcastTo
*
* History:
*
* v15.1.1 created
* @param {...(Array|Matrix)} x One or more matrices or arrays
* @return {Array[Array|Matrix]} An array of matrices with the broadcasted sizes.
*/
return typed(name, {
'...Array|Matrix': collections => {
const areMatrices = collections.map(isMatrix)
if (areMatrices.includes(true)) {
const arrays = collections.map((c, i) => areMatrices[i] ? c.valueOf() : c)
const broadcastedArrays = broadcastArrays(...arrays)
const broadcastedCollections = broadcastedArrays.map((arr, i) => areMatrices[i] ? collections[i].create(arr) : arr)
return broadcastedCollections
}
return broadcastArrays(...collections)
}
})
})
36 changes: 36 additions & 0 deletions src/function/matrix/broadcastSizes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { broadcastSizes } from '../../utils/array.js'
import { factory } from '../../utils/factory.js'

const name = 'broadcastSizes'
const dependencies = ['typed']

export const createBroadcastSizes = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => {
/**
* Calculate the broadcasted size of one or more matrices or arrays.

@gwhitney gwhitney Jan 3, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per my comments on the internal docs, shouldn't this be something more like "Calculate the size that would result from broadcasting one or more matrices or arrays, given the sizes of the input collections."?

The same comments about having documentation on the operation of broadcasting either here or linked here apply to this function as well. Also mention of what happens with incompatible sizes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still needs further editing/documentation.

* Always returns an Array containing numbers.
*
* Syntax:
*
* math.broadcastSizes(x, y)
* math.broadcastSizes(x, y, ...)
*
* Examples:
*
* math.broadcastSizes([2, 3]) // returns [2, 3]
* math.broadcastSizes([2, 3], [3]) // returns [2, 3]
* math.broadcastSizes([1, 2, 3], [1, 2, 1]) // returns [1, 2, 3]
*
* See also:
*
* size, reshape, squeeze, broadcastTo
*
* History:
*
* v15.1.1 created
* @param {...(Array|Matrix)} x One or more matrices or arrays
* @return {Array} A vector with the broadcasted size.
*/
return typed(name, {
'...Array|Matrix': collections => broadcastSizes(...collections.map(collection => collection.valueOf()))
})
})
43 changes: 43 additions & 0 deletions src/function/matrix/broadcastTo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { broadcastTo } from '../../utils/array.js'
import { factory } from '../../utils/factory.js'

const name = 'broadcastTo'
const dependencies = ['typed']

export const createBroadcastTo = /* #__PURE__ */ factory(name, dependencies, ({ typed }) => {
/**
* Broadcast an array to a specified size.
*

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically the same documentation comments: needs to be clear (how to find out) what broadcasting is, and there should be mention of what happens with incompatible size. Presumably that also means that (for all three functions) there should be an example with incompatible size.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still needs further editing/documentation.

* Syntax:
*
* math.broadcastTo(x, size)
*
* Examples:
*
* math.broadcastTo([1, 2, 3], [2, 3]) // returns [[1, 2, 3], [1, 2, 3]]
* math.broadcastTo([2, 3], [2, 2]) // returns [[2, 3], [2, 3]]
*
* See also:
*
* size, reshape, squeeze, broadcastSizes
*
* History:
*
* v15.1.1 created
*
* @param {Array|Matrix} x The array or matrix to broadcast
* @param {Array|Matrix} size The target size
* @return {Array} The broadcasted array
*/
return typed(name, {
'Array, Array': broadcastTo,
'Array, Matrix': (arr, size) => broadcastTo(arr, size.valueOf()),
'Matrix, Array|Matrix': (M, size) => {
const result = M.create()
result._size = size.valueOf()
result._data = broadcastTo(M.valueOf(), size.valueOf())
result._datatype = M.datatype()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to be breaking encapsulation of the internal format of matrices here. In particular, this implementation is supposed to work with an arbitrary Matrix implementation, based on its typed-function signature. Hence it can't delve into the internal fields, as they are assuming M is a DenseMatrix, which it might not be.

Therefore, this should be M.create(broadcastTo(M.valueOf(), size.valueOf()), M.datatype()). I understand your concern about unnecessarily recomputing the size. If you really want to get around that, there are some options:

  • Decide that broadcasting always returns a DenseMatrix, and use DenseMatrix creation methods that take your word for the size, if there are any such methods. This plan might not be wise at a time when you/we are contemplating adding other general-purpose matrix implementations besides DenseMatrix, creating a world in which we would not want operations to capriciously convert back into DenseMatrix.
  • Extend the interface of M.create() to optionally take a guaranteed size and/or other validation-short-circuiting options. That might require a number of coordinated changes in the Matrix classes.

Of course I am open to other ideas. But we don't want DenseMatrix-internals-specific code here. This observation also suggests there should be unit tests for the broadcasting functions on SparseMatrix arguments. Please add some if they aren't there.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this case I think it can be left as you mention M.create(broadcastTo(M.valueOf(), size.valueOf()), M.datatype()). Maybe for the future some options could be added to the create matrix to skipCloning, skipValidation, skipPreProcess, etc.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed as you suggested. For the future maybe some flags could be used.

return result
}
})
})
2 changes: 1 addition & 1 deletion src/utils/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ export function broadcastArrays (...arrays) {
throw new Error('Insufficient number of arguments in function broadcastArrays')
}
if (arrays.length === 1) {
return arrays[0]
return arrays
}
const sizes = arrays.map(function (array) { return arraySize(array) })
const broadcastedSize = broadcastSizes(...sizes)
Expand Down
35 changes: 35 additions & 0 deletions test/unit-tests/function/matrix/broadcastMatrices.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import assert from 'assert'
import math from '../../../../src/defaultInstance.js'

describe('broadcastMatrices', function () {
const matrix = math.matrix
const broadcastMatrices = math.broadcastMatrices
const A = [[1], [2], [3]]
const B = [[10, 20, 30]]
const C = [100]
const broadcastedA = [[1, 1, 1], [2, 2, 2], [3, 3, 3]]
const broadcastedB = [[10, 20, 30], [10, 20, 30], [10, 20, 30]]
const broadcastedC = [[100, 100, 100], [100, 100, 100], [100, 100, 100]]

it('should broadcast matrices', function () {
assert.deepStrictEqual(broadcastMatrices(matrix(A), matrix(B)), [matrix(broadcastedA), matrix(broadcastedB)])
assert.deepStrictEqual(broadcastMatrices(matrix(A), matrix(C)), [matrix(A), matrix([[100], [100], [100]])])
assert.deepStrictEqual(broadcastMatrices(matrix(B), matrix(A)), [matrix(broadcastedB), matrix(broadcastedA)])
assert.deepStrictEqual(broadcastMatrices(matrix(A), matrix(B), matrix(C)), [matrix(broadcastedA), matrix(broadcastedB), matrix(broadcastedC)])
})

it('should broadcast arrays', function () {
assert.deepStrictEqual(broadcastMatrices(A, B), [broadcastedA, broadcastedB])
assert.deepStrictEqual(broadcastMatrices(B, A), [broadcastedB, broadcastedA])
assert.deepStrictEqual(broadcastMatrices(A, B, C), [broadcastedA, broadcastedB, broadcastedC])
assert.deepStrictEqual(broadcastMatrices(A), [A])
assert.deepStrictEqual(broadcastMatrices(B, C, A), [broadcastedB, broadcastedC, broadcastedA])
})

it('should throw an error if sizes are not compatible', function () {
assert.throws(function () { broadcastMatrices(matrix([[1, 2], [3, 4]]), matrix([[1, 2, 3]])) }, /Error: shape mismatch: /)
assert.throws(function () { broadcastMatrices([[1, 2], [3, 4]], matrix([[1, 2, 3]])) }, /Error: shape mismatch: /)
assert.throws(function () { broadcastMatrices(matrix([[1, 2], [3, 4]]), [[1, 2, 3]]) }, /Error: shape mismatch: /)
assert.throws(function () { broadcastMatrices([[1, 2], [3, 4]], [[1, 2, 3]]) }, /Error: shape mismatch: /)
})
})
27 changes: 27 additions & 0 deletions test/unit-tests/function/matrix/broadcastSizes.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import assert from 'assert'
import math from '../../../../src/defaultInstance.js'

describe('broadcastSizes', function () {
const broadcastSizes = math.broadcastSizes
const matrix = math.matrix

it('should broadcast sizes', function () {
assert.deepStrictEqual(broadcastSizes([2, 3]), [2, 3])
assert.deepStrictEqual(broadcastSizes([3, 3], [3, 1]), [3, 3])
assert.deepStrictEqual(broadcastSizes([2, 1], [1, 3]), [2, 3])
assert.deepStrictEqual(broadcastSizes([5, 4, 3], [1, 4, 1]), [5, 4, 3])
assert.deepStrictEqual(broadcastSizes([3], [2, 3]), [2, 3])
assert.deepStrictEqual(broadcastSizes([1, 3], [2, 1]), [2, 3])
})

it('should throw an error if sizes are not compatible', function () {
assert.throws(function () { broadcastSizes([2, 3], [3, 2]) }, /Error: shape mismatch: /)
assert.throws(function () { broadcastSizes([2, 3], [2, 3, 4]) }, /Error: shape mismatch: /)
})

it('should broadcast sizes of mixed arrays and matrices', function () {
assert.deepStrictEqual(broadcastSizes([3, 3], matrix([3, 1])), [3, 3])
assert.deepStrictEqual(broadcastSizes(matrix([2, 1]), [1, 3]), [2, 3])
assert.deepStrictEqual(broadcastSizes(matrix([5, 4, 3]), matrix([1, 4, 1])), [5, 4, 3])
})
})
29 changes: 29 additions & 0 deletions test/unit-tests/function/matrix/broadcastTo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import assert from 'assert'
import math from '../../../../src/defaultInstance.js'

describe('broadcastTo', function () {
const broadcastTo = math.broadcastTo
const matrix = math.matrix

it('should broadcast arrays to a given size', function () {
assert.deepStrictEqual(broadcastTo([1, 2, 3], [2, 3]), [[1, 2, 3], [1, 2, 3]])
assert.deepStrictEqual(broadcastTo([2, 3], [2, 2]), [[2, 3], [2, 3]])
})

it('should broadcast matrices to a given size', function () {
assert.deepStrictEqual(broadcastTo(matrix([1, 2, 3]), [2, 3]), matrix([[1, 2, 3], [1, 2, 3]]))
assert.deepStrictEqual(broadcastTo(matrix([2, 3]), [2, 2]), matrix([[2, 3], [2, 3]]))
})

it('should broadcast mixed arrays and matrices to a given size', function () {
assert.deepStrictEqual(broadcastTo([1, 2, 3], matrix([2, 3])), [[1, 2, 3], [1, 2, 3]])
assert.deepStrictEqual(broadcastTo(matrix([2, 3]), [2, 2]), matrix([[2, 3], [2, 3]]))
assert.deepStrictEqual(broadcastTo(matrix([1, 2, 3]), matrix([2, 3])), matrix([[1, 2, 3], [1, 2, 3]]))
assert.deepStrictEqual(broadcastTo([2, 3], matrix([2, 2])), [[2, 3], [2, 3]])
})

it('should throw an error if sizes are not compatible', function () {
assert.throws(function () { broadcastTo([1, 2], [2, 3]) }, /Error: shape mismatch: /)
assert.throws(function () { broadcastTo(matrix([1, 2]), [2, 3]) }, /Error: shape mismatch: /)
})
})
12 changes: 6 additions & 6 deletions test/unit-tests/utils/array.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -701,19 +701,19 @@ describe('util.array', function () {
assert.deepStrictEqual(broadcastArrays([1, 2], [[3], [4]], [5, 6]), [[[1, 2], [1, 2]], [[3, 3], [4, 4]], [[5, 6], [5, 6]]])
})

it('should broadcast leave arrays as such when only one is supplied', function () {
assert.deepStrictEqual(broadcastArrays([1, 2]), [1, 2], [3, 4])
assert.deepStrictEqual(broadcastArrays([[3], [4]]), [[3], [4]])
assert.deepStrictEqual(broadcastArrays([[5, 6]]), [[5, 6]])
it('should broadcast a single array, returning the array itself in an array', function () {
assert.deepStrictEqual(broadcastArrays([1, 2])[0], [1, 2])
assert.deepStrictEqual(broadcastArrays([[3], [4]])[0], [[3], [4]])
assert.deepStrictEqual(broadcastArrays([[5, 6]])[0], [[5, 6]])
})

it('should throw an arryor when the broadcasting rules don\'t apply', function () {
it('should throw an error when the broadcasting rules don\'t apply', function () {
assert.throws(function () { broadcastArrays([1, 2], [1, 2, 3]) })
assert.throws(function () { broadcastArrays([1, 2], [1, 2, 3], [4, 5]) })
assert.throws(function () { broadcastArrays([[1, 2], [1, 2]], [[1, 2, 3]]) })
})

it('should throw an arryor when not enough arguments are supplied', function () {
it('should throw an error when not enough arguments are supplied', function () {
assert.throws(function () { broadcastArrays() })
})
})
Expand Down
Loading