diff --git a/documentation/BUILTIN.md b/documentation/BUILTIN.md index 9674763b..7b712a61 100644 --- a/documentation/BUILTIN.md +++ b/documentation/BUILTIN.md @@ -372,6 +372,9 @@ Attach a tracking ID to the interval. ### trackingIds(*interval*) Obtain an array of the tracking IDs attached to the interval. +### transpose(*matrix*) +Transpose a matrix. For modal transposition see rotate(). + ### trunc(*interval*) Truncate value towards zero to the nearest integer. diff --git a/src/parser/__tests__/vector-broadcasting.spec.ts b/src/parser/__tests__/vector-broadcasting.spec.ts index ee08501b..fa8b3799 100644 --- a/src/parser/__tests__/vector-broadcasting.spec.ts +++ b/src/parser/__tests__/vector-broadcasting.spec.ts @@ -481,4 +481,12 @@ describe('SonicWeave vector broadcasting', () => { ], ]); }); + + it('can transpose a matrix', () => { + const mat = sw2D`transpose([[1, 2], [3, 4], [5, 6]])`; + expect(mat).toEqual([ + [1, 3, 5], + [2, 4, 6], + ]); + }); }); diff --git a/src/stdlib/builtin.ts b/src/stdlib/builtin.ts index 58e6b544..42c79230 100644 --- a/src/stdlib/builtin.ts +++ b/src/stdlib/builtin.ts @@ -1631,6 +1631,27 @@ valFromPrimeArray.__doc__ = 'Convert an array of prime mapping entries to a val.'; valFromPrimeArray.__node__ = builtinNode(valFromPrimeArray); +function transpose(matrix: SonicWeaveValue[][]) { + if (!Array.isArray(matrix)) { + return matrix; + } + if (!Array.isArray(matrix[0])) { + return [...matrix]; + } + const width = matrix.reduce((w, row) => Math.max(w, row.length), 0); + const result: SonicWeaveValue[][] = []; + for (let i = 0; i < width; ++i) { + const row: SonicWeaveValue[] = []; + for (let j = 0; j < matrix.length; ++j) { + row.push(matrix[j][i] ?? fromInteger(0)); + } + result.push(row); + } + return result; +} +transpose.__doc__ = 'Transpose a matrix. For modal transposition see rotate().'; +transpose.__node__ = builtinNode(transpose); + function hasConstantStructure_(this: ExpressionVisitor, scale?: Interval[]) { scale ??= this.currentScale; this.spendGas(scale.length * scale.length); @@ -2508,6 +2529,7 @@ export const BUILTIN_CONTEXT: Record = { toPrimeArray, monzoFromPrimeArray, valFromPrimeArray, + transpose, hasConstantStructure: hasConstantStructure_, stepString: stepString_, str,