├── .github ├── actions │ └── setup │ │ └── action.yml ├── dependabot.yml └── workflows │ ├── lint-pr.yml │ ├── test-and-release.yml │ └── test.yml ├── .gitignore ├── .nvmrc ├── .releaserc ├── .vscode ├── extensions.json └── settings.json ├── LICENSE ├── README.md ├── assets ├── banner.gif ├── banner_alt-pixelated.gif ├── banner_alt-pixelated_bounce.gif ├── banner_taller.gif ├── grid-only_landscape.mp4 ├── grid-only_portrait.mp4 ├── grid-with-text_portrait.mp4 ├── meta.jpg └── meta_pixelated.jpg ├── benchmark └── results │ └── make-matrix-ci.json ├── biome.json ├── package.json ├── pnpm-lock.yaml ├── scripts ├── build.ts ├── run-benchmark.ts └── update-badges.ts ├── src ├── __tests__ │ ├── __snapshots__ │ │ └── index.test.ts.snap │ ├── index.test.ts │ └── types.test.ts ├── index.ts └── types.ts └── tsconfig.json /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: "Set up repository" 2 | description: "Sets up the repository for CI, by installing packages, and configuring the cache" 3 | 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Get Node Version from .nvmrc 8 | id: nvm 9 | run: echo "node_version=$(cat .nvmrc)" >> $GITHUB_OUTPUT 10 | shell: bash 11 | - uses: pnpm/action-setup@v4 12 | - name: Set up Node 13 | uses: actions/setup-node@v4 14 | with: 15 | node-version: "${{ steps.nvm.outputs.node_version }}" 16 | cache: "pnpm" 17 | - name: Load cached node modules 18 | uses: actions/cache@v4 19 | id: cache-node_modules 20 | with: 21 | path: node_modules 22 | key: ${{ runner.os }}-node_modules-${{ hashFiles('pnpm-lock.yaml') }} 23 | restore-keys: | 24 | ${{ runner.os }}-node_modules- 25 | - name: Install node_modules (on cache miss) 26 | if: steps.cache-node_modules.outputs.cache-hit != 'true' 27 | run: pnpm i 28 | shell: bash -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | commit-message: 8 | prefix: fix 9 | prefix-development: chore 10 | include: scope 11 | groups: 12 | dev-dependencies: 13 | dependency-type: "development" 14 | patterns: 15 | - "*" 16 | update-types: 17 | - "minor" 18 | - "patch" 19 | commitlint-monorepo: 20 | dependency-type: "development" 21 | patterns: 22 | - "@commitlint/*" 23 | update-types: 24 | - "major" 25 | - package-ecosystem: github-actions 26 | directory: "/" 27 | schedule: 28 | interval: "monthly" 29 | -------------------------------------------------------------------------------- /.github/workflows/lint-pr.yml: -------------------------------------------------------------------------------- 1 | name: "Lint PR" 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | permissions: 11 | pull-requests: read 12 | 13 | jobs: 14 | main: 15 | name: Validate PR title 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: amannn/action-semantic-pull-request@v5 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/test-and-release.yml: -------------------------------------------------------------------------------- 1 | name: Test & Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - "main" 7 | 8 | jobs: 9 | release: 10 | name: Test & Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 2 17 | - name: Set up repo 18 | uses: ./.github/actions/setup 19 | - name: Check 20 | run: pnpm run check 21 | - name: Typecheck 22 | run: pnpm run typecheck 23 | - name: Test 24 | run: pnpm run test 25 | - name: Validate current commit (last commit) with commitlint 26 | run: pnpm run commitlint -- --from HEAD~1 --to HEAD --verbose 27 | - name: Release 28 | run: npx semantic-release 29 | env: 30 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 31 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 32 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | 6 | jobs: 7 | test: 8 | name: Test 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | - name: Set up repo 14 | uses: ./.github/actions/setup 15 | - name: Check 16 | run: pnpm run check 17 | - name: Typecheck 18 | run: pnpm run typecheck 19 | - name: Test 20 | run: pnpm run test 21 | - name: Has src changed 22 | if: github.event_name == 'pull_request' 23 | id: src_changed 24 | uses: tj-actions/changed-files@v46 25 | with: 26 | files: src/index.ts 27 | - name: Benchmark against current release 28 | if: steps.src_changed.outputs.any_changed == 'true' 29 | id: benchmark 30 | run: pnpm run benchmark:diff:ci 31 | env: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | - name: Validate PR commits with commitlint 34 | run: pnpm run commitlint -- --from ${{ github.event.pull_request.head.sha }}~${{ github.event.pull_request.commits }} --to ${{ github.event.pull_request.head.sha }} --verbose 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | node_modules/ 3 | lib/ 4 | dist/ 5 | coverage/ 6 | .jest-cache/ 7 | benchmark/results/make-matrix-local.json 8 | .DS_Store -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v20.16.0 -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "main" 4 | ], 5 | "plugins": [ 6 | "@semantic-release/commit-analyzer", 7 | "@semantic-release/release-notes-generator", 8 | "@semantic-release/npm", 9 | [ 10 | "@semantic-release/github", 11 | { 12 | "assets": [ 13 | { 14 | "path": "dist/index.cjs", 15 | "label": "make-matrix.js" 16 | }, 17 | { 18 | "path": "dist/index.js", 19 | "label": "make-matrix.mjs" 20 | }, 21 | { 22 | "path": "dist/index.min.cjs", 23 | "label": "make-matrix.min.js" 24 | }, 25 | { 26 | "path": "dist/index.min.js", 27 | "label": "make-matrix.min.mjs" 28 | } 29 | ] 30 | } 31 | ], 32 | [ 33 | "@semantic-release/git", 34 | { 35 | "assets": [ 36 | "README.md", 37 | "package.json", 38 | "package-lock.json", 39 | "benchmark/results/make-matrix-ci.json" 40 | ], 41 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 42 | } 43 | ] 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["biomejs.biome"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "node_modules/typescript/lib", 3 | "biome.enabled": true, 4 | "editor.defaultFormatter": "biomejs.biome", 5 | "editor.formatOnSave": true, 6 | "editor.codeActionsOnSave": { 7 | "quickfix.biome": "explicit", 8 | "source.fixAll": "always", 9 | "source.organizeImports.biome": "explicit" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Neef Rehman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | make-matrix 2 | 3 | [![build](https://github.com/neefrehman/make-matrix/actions/workflows/test-and-release.yml/badge.svg?branch=main)](https://github.com/neefrehman/make-matrix/actions "View the build actions for this project") 4 | [![npm version](https://img.shields.io/badge/npm-v4.0.2-0074c1)](https://npmjs.org/package/make-matrix "View this project on npm") 5 | [![types included](https://img.shields.io/badge/types-included-0074c1)](https://npmjs.org/package/make-matrix "Types are included in this package") 6 | [![bundle size](https://img.shields.io/badge/minzipped_size-202_B-0074c1)](https://bundlephobia.com/result?p=make-matrix "View this project on bundlephobia") 7 | 8 | A simple, type-safe way to create multi-dimensional arrays 9 | 10 | ## Features 11 | 12 | - 🛸 Easily create multi-dimensional arrays, with as many dimensions as needed 13 | - 🎛 Define exact dimensions to create an array of specified size 14 | - 🔢 Initialise every point in the array to a custom or self-aware starting value 15 | - 📜 Comes with [TypeScript](https://www.typescriptlang.org) definitions and type-safe returns 16 | - 🔬 Tiny size, with no external dependencies 17 | 18 | ## Installation 19 | 20 | Install the package from NPM, and import it into your JavaScript or TypeScript file: 21 | 22 | ```bash 23 | npm install make-matrix 24 | ``` 25 | 26 | ```js 27 | import { makeMatrix } from "make-matrix"; 28 | ``` 29 | 30 | ## Usage 31 | 32 | ### Create a matrix 33 | 34 | To create a matrix, pass in an array with the desired dimensions. 35 | 36 | ```js 37 | // create an array of size 3x3x2 38 | const threeByThreeByTwoArray = makeMatrix([3, 3, 2]); 39 | ``` 40 | 41 | ### Initialise the matrix with set values 42 | 43 | By default each point in the matrix will be initialised to `null` (so that if reading a point returns `undefined`, you know that it exists outside the current bounds of the matrix). To fill each point with a custom initial value, pass that value as the function's second parameter, `initialValues`: 44 | 45 | ```js 46 | // create a 3x5 array, with each point equal to 0 47 | const twoDNumberArray = makeMatrix([3, 5], 0); 48 | 49 | // create a 2x6x5 array, with each point equal to "value" 50 | const threeDStringArray = makeMatrix([2, 6, 5], "value"); 51 | ``` 52 | 53 | ### Pass a callback for dynamic initial values 54 | 55 | The `initialValues` parameter can also be a callback, which you can use to dynamically create items for each position in the matrix. The callback can also accept an argument which will resolve to the current vector co-ordinates at each point in the matrix. This will allow you to populate your matrix in a "self-aware" fashion. 56 | 57 | ```js 58 | // create a 10x10x10 array, with each point a different random number between 0 and 9 59 | const twoDRandomNumberArray = makeMatrix([10, 10, 10], () => Math.floor(Math.random() * 10)); 60 | 61 | // create a 5x5 array, with each point self-described by a string 62 | const twoDVectorStringArray = makeMatrix([5, 5], (vector) => `I am at position ${vector.join()}`); 63 | 64 | // create a 7x3x8 array, with each point transformed into a vector object 65 | const twoDVectorObjectArray = makeMatrix([7, 3, 8], ([x, y, z]) => ({ x, y, z })); 66 | ``` 67 | 68 | ## With TypeScript 69 | 70 | This package comes with type definitions to provide type-safety when working with the returned arrays. 71 | 72 | Returned Matrices will be given a specific type dictated by `T` and the number of dimensions, where `T` is the type of the value passed to the functions `initialValues` parameter (or `unknown`, if not set). 73 | 74 | For example, a three-dimensional array of numbers will be of type `number[][][]`. Points within the matrix can then only be reassigned to numbers. TypeScript's compiler will present errors when any reassignments are of the wrong type, including if they are at an incorrect depth in the array. This type-safety also occurs when callbacks are used to dynamically populate your matrix. 75 | 76 | ```ts 77 | const threeDNumberArray = makeMatrix([2, 6, 5], 0); // return type of number[][][] 78 | 79 | threeDNumberArray[2][1][2] = 10; // ✅ OK 80 | 81 | threeDNumberArray[2][1][2] = false; // 🚨 error: Type 'boolean' is not assignable to type 'number' 82 | threeDNumberArray[2][1] = 10; // 🚨 error: Type 'number' is not assignable to type 'number[]' 83 | threeDNumberArray[2][1][2][0] = 10; // 🚨 error: Property '0' does not exist on type 'Number' 84 | ``` 85 | 86 | Please be aware that when using this function with a primitive instead of a literal type—such as when creating matrices of dynamic size—the exact return type cannot be determined and will instead resolve to `unknown[]`. This ensures an array of at least one dimension is returned, but is unable to provide any more safety than that. You must type the resulting matrix yourself, if you are able to provide more information than the compiler can infer. If not, then an explicit return type of `any[]` will provide the most 'relaxed' typing experience. 87 | 88 | ```ts 89 | const createDynamicMatrix = (dimensions: number[]) => makeMatrix(dimensions, 0); // return type of unknown[] 90 | ``` 91 | 92 | ## Example 93 | 94 | To easily create a 3D grid using [p5.js](https://github.com/processing/p5.js/), make-matrix can be used like below. The source code for the grid at the top of this readme [can be seen here](https://github.com/neefrehman/Generative/blob/master/src/sketches/20/05/120520.tsx), and an [interactive demo of it here](https://generative.neef.co/120520). 95 | 96 | ```js 97 | const res = 10; // 10px grid resolution 98 | const matrix = makeMatrix([5, 5, 5]); // A 5x5x5 cube grid 99 | 100 | for (let x = 0; x < matrix.length; x += res) { 101 | for (let y = 0; y < matrix[x].length; y += res) { 102 | for (let z = 0; z < matrix[x][y].length; z += res) { 103 | line(x, y, z, x + res, y, z); 104 | line(x, y, z, x, y + res, z); 105 | line(x, y, z, x, y, z + res); 106 | } 107 | } 108 | } 109 | ``` 110 | 111 | ## Complexity 112 | 113 | The `makeMatrix` algorithm is recursive and takes exponential time, or $O(2^n)$, to complete. This means that adding new dimensions dramatically increases the amount of time taken to create a matrix. While creating a matrix of 7 dimensions will happen in around a millisecond, doing the same with 10 dimensions will verge into the hundreds of milliseconds. Please bear this in mind when creating matrices. 114 | 115 | ## API 116 | 117 | ```ts 118 | makeMatrix( 119 | dimensions: VectorOfLength, 120 | initialValues?: T | ((vector: VectorOfLength) => T) = null 121 | ): Matrix; 122 | ``` 123 | 124 | ### Parameters 125 | 126 | | Name | Description | 127 | | --------------- | ----------- | 128 | | `dimensions` | The desired dimensions of the matrix. An array of numbers. | 129 | | `initialValues` | The value that each point in the matrix will initialise to. Can take any value. If a callback is passed, it will be run for each point in the matrix, which will be initialised to the callbacks returned value. (Optional — defaults to `null`). | 130 | 131 | ### Returns 132 | 133 | | Name | Description | 134 | | -------- | ----------- | 135 | | `Matrix` | A multidimensional array of your desired dimensions, with each point initialised to equal the `initialValues` parameter (or its returned value). | 136 | 137 | ## Contributing 138 | 139 | This project welcomes contributions. To get started, please [open an issue](https://github.com/neefrehman/make-matrix/issues) to do discuss the change you'd like to make. Then fork the repo, open it in your editor, and run `pnpm install` in your terminal. This will get everything set up for you to start making changes. 140 | 141 | ### Testing, linting and commit style 142 | 143 | This project uses [Biome](https://biomejs.dev/), [commitlint](https://github.com/conventional-changelog/commitlint) and [vitest](https://vitest.dev/) — in combination with [lint-staged](https://github.com/okonet/lint-staged) and [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks) — to enforce code quality, consistency and changelog style. These tools will check changed files, and cancel a commit with logging if any of the following are true: 144 | 145 | 1. Biome has found non-fixable issues in the code 146 | 2. The Vitest testing suites haven't all passed 147 | 3. The commit message doesn't meet the [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0/) (run `pnpm run commitizen` in terminal for help formatting your commit message) 148 | 149 | Open your git logs to debug commit errors. 150 | 151 | ## License 152 | 153 | This package is [MIT Licensed](https://github.com/neefrehman/make-matrix/blob/main/LICENSE). 154 | -------------------------------------------------------------------------------- /assets/banner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/banner.gif -------------------------------------------------------------------------------- /assets/banner_alt-pixelated.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/banner_alt-pixelated.gif -------------------------------------------------------------------------------- /assets/banner_alt-pixelated_bounce.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/banner_alt-pixelated_bounce.gif -------------------------------------------------------------------------------- /assets/banner_taller.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/banner_taller.gif -------------------------------------------------------------------------------- /assets/grid-only_landscape.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/grid-only_landscape.mp4 -------------------------------------------------------------------------------- /assets/grid-only_portrait.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/grid-only_portrait.mp4 -------------------------------------------------------------------------------- /assets/grid-with-text_portrait.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/grid-with-text_portrait.mp4 -------------------------------------------------------------------------------- /assets/meta.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/meta.jpg -------------------------------------------------------------------------------- /assets/meta_pixelated.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neefrehman/make-matrix/27a0c0f2f992bb84eaf1058d56e06f69267a6c9d/assets/meta_pixelated.jpg -------------------------------------------------------------------------------- /benchmark/results/make-matrix-ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "make-matrix", 3 | "date": "2025-05-22T21:02:45.710Z", 4 | "version": "4.0.2", 5 | "results": [ 6 | { 7 | "name": "base", 8 | "ops": 186481, 9 | "margin": 1.26, 10 | "percentSlower": 0 11 | }, 12 | { 13 | "name": "with callback", 14 | "ops": 37542, 15 | "margin": 0.73, 16 | "percentSlower": 79.87 17 | } 18 | ], 19 | "fastest": { 20 | "name": "base", 21 | "index": 0 22 | }, 23 | "slowest": { 24 | "name": "with callback", 25 | "index": 1 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json", 3 | "vcs": { 4 | "enabled": true, 5 | "clientKind": "git", 6 | "useIgnoreFile": true, 7 | "defaultBranch": "main" 8 | }, 9 | "formatter": { 10 | "enabled": true, 11 | "formatWithErrors": false, 12 | "indentStyle": "space", 13 | "indentWidth": 2, 14 | "lineEnding": "lf", 15 | "lineWidth": 90, 16 | "attributePosition": "auto", 17 | "bracketSpacing": true 18 | }, 19 | "organizeImports": { 20 | "enabled": true 21 | }, 22 | "linter": { 23 | "enabled": true, 24 | "rules": { 25 | "recommended": true, 26 | "correctness": { 27 | "noUnusedVariables": "error", 28 | "useArrayLiterals": "error" 29 | }, 30 | "style": { 31 | "noNamespace": "error", 32 | "useBlockStatements": "error" 33 | }, 34 | "suspicious": { 35 | "noConsole": "error" 36 | } 37 | } 38 | }, 39 | "javascript": { 40 | "formatter": { 41 | "jsxQuoteStyle": "double", 42 | "quoteProperties": "asNeeded", 43 | "trailingCommas": "es5", 44 | "semicolons": "always", 45 | "arrowParentheses": "asNeeded", 46 | "bracketSameLine": false, 47 | "quoteStyle": "double", 48 | "attributePosition": "auto", 49 | "bracketSpacing": true 50 | } 51 | }, 52 | "overrides": [ 53 | { 54 | "include": ["./scripts/run-benchmark.ts"], 55 | "linter": { "rules": { "suspicious": { "noConsole": "off" } } } 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "make-matrix", 3 | "version": "4.0.2", 4 | "license": "MIT", 5 | "description": "A simple, type-safe way to create multi-dimensional arrays", 6 | "author": "Neef Rehman", 7 | "keywords": [ 8 | "matrix", 9 | "nth dimension", 10 | "array", 11 | "multidimensional", 12 | "math", 13 | "typescript" 14 | ], 15 | "homepage": "https://github.com/neefrehman/make-matrix", 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/neefrehman/make-matrix.git" 19 | }, 20 | "bugs": { 21 | "url": "https://github.com/neefrehman/make-matrix/issues" 22 | }, 23 | "files": ["src/**/*", "dist/**/*"], 24 | "type": "module", 25 | "sideEffects": false, 26 | "exports": { 27 | ".": { 28 | "types": "./dist/index.d.ts", 29 | "require": "./dist/index.cjs", 30 | "import": "./dist/index.js", 31 | "development": "./src/index.ts" 32 | } 33 | }, 34 | "main": "./dist/index.cjs", 35 | "types": "./dist/index.d.ts", 36 | "scripts": { 37 | "check": "biome check", 38 | "check:fix": "biome check --write", 39 | "format:fix": "biome format --write", 40 | "typecheck": "tsc", 41 | "test": "vitest run", 42 | "build": "tsdown --config='scripts/build.ts'", 43 | "preversion": "pnpm run check", 44 | "version": "pnpm run build && pnpm run format:fix && git add -A src", 45 | "postversion": "pnpm run benchmark:ci && pnpm run updateBadges && git push && git push --tags", 46 | "updateBadges": "tsx scripts/update-badges.ts", 47 | "pre-commit": "lint-staged", 48 | "commit-msg": "commitlint -e", 49 | "commitizen": "cz", 50 | "commitlint": "commitlint", 51 | "benchmark": "tsx scripts/run-benchmark.ts current", 52 | "benchmark:ci": "tsx scripts/run-benchmark.ts current ci", 53 | "benchmark:diff": "tsx scripts/run-benchmark.ts diff", 54 | "benchmark:diff:ci": "tsx scripts/run-benchmark.ts diff ci" 55 | }, 56 | "devDependencies": { 57 | "@actions/github": "6.0.1", 58 | "@biomejs/biome": "1.9.4", 59 | "@commitlint/cli": "19.8.1", 60 | "@commitlint/config-conventional": "19.8.1", 61 | "@semantic-release/git": "10.0.1", 62 | "benny": "3.7.1", 63 | "commitizen": "4.3.1", 64 | "cz-conventional-changelog": "3.3.0", 65 | "lint-staged": "15.5.2", 66 | "semantic-release": "24.2.4", 67 | "simple-git-hooks": "2.13.0", 68 | "terser": "5.39.2", 69 | "tsdown": "0.12.2", 70 | "tsx": "^4.19.4", 71 | "typescript": "5.8.3", 72 | "vitest": "3.1.4" 73 | }, 74 | "lint-staged": { 75 | "*": [], 76 | "*.(js|ts|tsx)": ["biome check --write", "vitest related --run --passWithNoTests"] 77 | }, 78 | "simple-git-hooks": { 79 | "commit-msg": "npm run commit-msg", 80 | "pre-commit": "npm run pre-commit" 81 | }, 82 | "commitlint": { 83 | "extends": ["@commitlint/config-conventional"], 84 | "rules": { 85 | "body-max-line-length": [1, "always", 100] 86 | } 87 | }, 88 | "config": { 89 | "commitizen": { 90 | "path": "./node_modules/cz-conventional-changelog" 91 | } 92 | }, 93 | "packageManager": "pnpm@9.9.0" 94 | } 95 | -------------------------------------------------------------------------------- /scripts/build.ts: -------------------------------------------------------------------------------- 1 | import { type Options, defineConfig } from "tsdown"; 2 | 3 | const baseConfig: Options = { 4 | entry: ["src/index.ts"], 5 | format: ["cjs", "es"], 6 | platform: "neutral", 7 | }; 8 | 9 | export default defineConfig([ 10 | { 11 | ...baseConfig, 12 | sourcemap: true, 13 | }, 14 | { 15 | ...baseConfig, 16 | minify: true, 17 | outExtensions: ({ format }) => ({ 18 | js: format === "es" ? ".min.js" : `.min.${format}`, 19 | }), 20 | }, 21 | ]); 22 | -------------------------------------------------------------------------------- /scripts/run-benchmark.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "node:fs"; 2 | 3 | import { context, getOctokit } from "@actions/github"; 4 | import benny from "benny"; 5 | 6 | import packageJson from "../package.json" with { type: "json" }; 7 | import { makeMatrix } from "../src/index.js"; 8 | 9 | const { name: packageName, version } = packageJson; 10 | 11 | const isDiff = process.argv[2] === "diff"; 12 | const isInCI = process.argv[3] === "ci"; 13 | const file = `${packageName}-${isInCI ? "ci" : "local"}`; 14 | 15 | const directionEmojiMapping = { [-1]: "🚨", 0: "🔄", 1: "✅" }; 16 | const getEmoji = (diff: number) => directionEmojiMapping[Math.sign(diff)]; 17 | 18 | type Diff = { 19 | name: string; 20 | delta: number; 21 | old?: number | undefined; 22 | new?: number; 23 | }; 24 | 25 | benny 26 | .suite( 27 | "make-matrix", 28 | benny.add("base", () => { 29 | makeMatrix([2, 4, 2, 4, 2]); 30 | }), 31 | benny.add("with callback", () => { 32 | makeMatrix([2, 4, 2, 4, 2], vector => `my position is ${vector.join()}`); 33 | }), 34 | benny.cycle(), 35 | benny.complete(), 36 | isDiff ? { name: "skip" } : benny.save({ file, version }) 37 | ) 38 | .then(async ({ results }) => { 39 | if (!isDiff || !fs.existsSync(`./benchmark/results/${file}.json`)) { 40 | return; 41 | } 42 | 43 | const oldBenchmarkText = fs.readFileSync(`./benchmark/results/${file}.json`); 44 | const oldBenchmark = JSON.parse(oldBenchmarkText.toString()); 45 | const oldResults: typeof results = oldBenchmark.results; 46 | 47 | const diffs: Diff[] = results.map(result => { 48 | const oldRes = oldResults.find(oldResult => oldResult.name === result.name); 49 | const delta = oldRes ? ((result.ops - oldRes.ops) / oldRes.ops) * 100 : 0; 50 | return { name: result.name, delta, old: oldRes?.ops, new: result.ops }; 51 | }); 52 | 53 | const changed = diffs.filter(item => item.delta !== 0); 54 | const average = changed.reduce((a, b) => a + b.delta, 0) / changed.length; 55 | diffs.push({ name: "Average", delta: average }); 56 | 57 | const prettyDiffs = diffs.map(diff => ({ 58 | ...diff, 59 | new: diff.new ? `${diff.new.toLocaleString()} ops/s` : "", 60 | old: diff.old ? `${diff.old.toLocaleString()} ops/s` : "", 61 | delta: `${getEmoji(diff.delta)} ${diff.delta.toFixed(2)}% ${ 62 | diff.delta > 0 ? "faster" : diff.delta < 0 ? "slower" : "same" 63 | }`, 64 | })); 65 | 66 | console.log("\n"); 67 | console.log(`Benchmark against currently published version (${version}):\n`); 68 | console.table( 69 | prettyDiffs.reduce<{ [name: string]: Record }>( 70 | (acc, { name, ...diff }) => { 71 | acc[name] = diff; 72 | return acc; 73 | }, 74 | {} 75 | ), 76 | ["new", "old", "delta"] 77 | ); 78 | 79 | if (!isInCI || !process.env.GITHUB_TOKEN) { 80 | return; 81 | } 82 | 83 | const body = ["### Benchmark against currently published version:"]; 84 | body.push("| Key | Current PR | Published version | Difference |"); 85 | body.push("| :--- | :--------: | :---------------: | :--------: |"); 86 | for (const diff of prettyDiffs) { 87 | body.push(`| ${diff.name} | ${diff.new}| ${diff.old} | ${diff.delta} |`); 88 | } 89 | 90 | await getOctokit(process.env.GITHUB_TOKEN).rest.issues.createComment({ 91 | issue_number: context.issue.number, 92 | owner: context.repo.owner, 93 | repo: context.repo.repo, 94 | body: body.join("\n"), 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /scripts/update-badges.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Script that will get the current version number and minzipped size of the package, 3 | * And use them to update the badges in this repo's README. I'm doing this in response 4 | * to issues with the runtime-determined badges that I used to use: they weren't that 5 | * accurate and would often not load. Upfronting this badge generation to time of 6 | * versioning is more reliable. 7 | * 8 | * @remarks 9 | * This work was initially planned to be shell-only, but due to some issues getting `sed` 10 | * to work, performing the write in javascript was a more reliable option. 11 | */ 12 | 13 | import { exec } from "node:child_process"; 14 | import * as fs from "node:fs"; 15 | import { promisify } from "node:util"; 16 | 17 | const execAsync = promisify(exec); 18 | const getStdOut = async (sh: string) => (await execAsync(sh)).stdout.trim(); 19 | 20 | /* 21 | * With sed command that I couldn't quite get the regex working for: 22 | * grep -m 1 \"version\" package.json | awk -F: '{ print $2 }' | sed 's/[",]//g' | (read VERSION && sed -i '' "/v(\d+\.)?(\d+\.)?(\*|\d+)/v$VERSION/" README.md) 23 | */ 24 | const getVersionCommand = `grep -m 1 \"version\" package.json | awk -F: '{ print $2 }' | sed 's/[",]//g'`; 25 | 26 | /* 27 | * With sed command that I couldn't quite get the regex working for: 28 | * gzip dist/index.min.js -kf && wc -c < dist/index.min.js.gz | (read MINZIPPED_SIZE && sed -i '' "s/\d+_B/$MINZIPPED_SIZE\_B/" README.md) 29 | */ 30 | const getMinZippedSizeCommand = 31 | "gzip dist/index.min.js -kf && wc -c < dist/index.min.js.gz"; 32 | 33 | const main = async () => { 34 | const currentReadme = fs.readFileSync("./README.md", "utf-8"); 35 | 36 | const newVersion = await getStdOut(getVersionCommand); 37 | const newMinzippedSize = await getStdOut(getMinZippedSizeCommand); 38 | 39 | const newReadme = currentReadme 40 | .replace(/v(\d+\.)?(\d+\.)?(\*|\d+)/, `v${newVersion}`) 41 | .replace(/\d+_B/, `${newMinzippedSize}_B`); 42 | 43 | fs.writeFileSync("./README.md", newReadme); 44 | }; 45 | 46 | main(); 47 | -------------------------------------------------------------------------------- /src/__tests__/__snapshots__/index.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html 2 | 3 | exports[`makeMatrix > callback initial values — math > %p [ 1, 1 ] 1`] = ` 4 | [ 5 | [ 6 | 8, 7 | ], 8 | ] 9 | `; 10 | 11 | exports[`makeMatrix > callback initial values — math > %p [ 1, 4, 5, 2 ] 1`] = ` 12 | [ 13 | [ 14 | [ 15 | [ 16 | 8, 17 | 8, 18 | ], 19 | [ 20 | 8, 21 | 8, 22 | ], 23 | [ 24 | 8, 25 | 8, 26 | ], 27 | [ 28 | 8, 29 | 8, 30 | ], 31 | [ 32 | 8, 33 | 8, 34 | ], 35 | ], 36 | [ 37 | [ 38 | 8, 39 | 8, 40 | ], 41 | [ 42 | 8, 43 | 8, 44 | ], 45 | [ 46 | 8, 47 | 8, 48 | ], 49 | [ 50 | 8, 51 | 8, 52 | ], 53 | [ 54 | 8, 55 | 8, 56 | ], 57 | ], 58 | [ 59 | [ 60 | 8, 61 | 8, 62 | ], 63 | [ 64 | 8, 65 | 8, 66 | ], 67 | [ 68 | 8, 69 | 8, 70 | ], 71 | [ 72 | 8, 73 | 8, 74 | ], 75 | [ 76 | 8, 77 | 8, 78 | ], 79 | ], 80 | [ 81 | [ 82 | 8, 83 | 8, 84 | ], 85 | [ 86 | 8, 87 | 8, 88 | ], 89 | [ 90 | 8, 91 | 8, 92 | ], 93 | [ 94 | 8, 95 | 8, 96 | ], 97 | [ 98 | 8, 99 | 8, 100 | ], 101 | ], 102 | ], 103 | ] 104 | `; 105 | 106 | exports[`makeMatrix > callback initial values — math > %p [ 2, 4, 2, 4, 2 ] 1`] = ` 107 | [ 108 | [ 109 | [ 110 | [ 111 | [ 112 | 8, 113 | 8, 114 | ], 115 | [ 116 | 8, 117 | 8, 118 | ], 119 | [ 120 | 8, 121 | 8, 122 | ], 123 | [ 124 | 8, 125 | 8, 126 | ], 127 | ], 128 | [ 129 | [ 130 | 8, 131 | 8, 132 | ], 133 | [ 134 | 8, 135 | 8, 136 | ], 137 | [ 138 | 8, 139 | 8, 140 | ], 141 | [ 142 | 8, 143 | 8, 144 | ], 145 | ], 146 | ], 147 | [ 148 | [ 149 | [ 150 | 8, 151 | 8, 152 | ], 153 | [ 154 | 8, 155 | 8, 156 | ], 157 | [ 158 | 8, 159 | 8, 160 | ], 161 | [ 162 | 8, 163 | 8, 164 | ], 165 | ], 166 | [ 167 | [ 168 | 8, 169 | 8, 170 | ], 171 | [ 172 | 8, 173 | 8, 174 | ], 175 | [ 176 | 8, 177 | 8, 178 | ], 179 | [ 180 | 8, 181 | 8, 182 | ], 183 | ], 184 | ], 185 | [ 186 | [ 187 | [ 188 | 8, 189 | 8, 190 | ], 191 | [ 192 | 8, 193 | 8, 194 | ], 195 | [ 196 | 8, 197 | 8, 198 | ], 199 | [ 200 | 8, 201 | 8, 202 | ], 203 | ], 204 | [ 205 | [ 206 | 8, 207 | 8, 208 | ], 209 | [ 210 | 8, 211 | 8, 212 | ], 213 | [ 214 | 8, 215 | 8, 216 | ], 217 | [ 218 | 8, 219 | 8, 220 | ], 221 | ], 222 | ], 223 | [ 224 | [ 225 | [ 226 | 8, 227 | 8, 228 | ], 229 | [ 230 | 8, 231 | 8, 232 | ], 233 | [ 234 | 8, 235 | 8, 236 | ], 237 | [ 238 | 8, 239 | 8, 240 | ], 241 | ], 242 | [ 243 | [ 244 | 8, 245 | 8, 246 | ], 247 | [ 248 | 8, 249 | 8, 250 | ], 251 | [ 252 | 8, 253 | 8, 254 | ], 255 | [ 256 | 8, 257 | 8, 258 | ], 259 | ], 260 | ], 261 | ], 262 | [ 263 | [ 264 | [ 265 | [ 266 | 8, 267 | 8, 268 | ], 269 | [ 270 | 8, 271 | 8, 272 | ], 273 | [ 274 | 8, 275 | 8, 276 | ], 277 | [ 278 | 8, 279 | 8, 280 | ], 281 | ], 282 | [ 283 | [ 284 | 8, 285 | 8, 286 | ], 287 | [ 288 | 8, 289 | 8, 290 | ], 291 | [ 292 | 8, 293 | 8, 294 | ], 295 | [ 296 | 8, 297 | 8, 298 | ], 299 | ], 300 | ], 301 | [ 302 | [ 303 | [ 304 | 8, 305 | 8, 306 | ], 307 | [ 308 | 8, 309 | 8, 310 | ], 311 | [ 312 | 8, 313 | 8, 314 | ], 315 | [ 316 | 8, 317 | 8, 318 | ], 319 | ], 320 | [ 321 | [ 322 | 8, 323 | 8, 324 | ], 325 | [ 326 | 8, 327 | 8, 328 | ], 329 | [ 330 | 8, 331 | 8, 332 | ], 333 | [ 334 | 8, 335 | 8, 336 | ], 337 | ], 338 | ], 339 | [ 340 | [ 341 | [ 342 | 8, 343 | 8, 344 | ], 345 | [ 346 | 8, 347 | 8, 348 | ], 349 | [ 350 | 8, 351 | 8, 352 | ], 353 | [ 354 | 8, 355 | 8, 356 | ], 357 | ], 358 | [ 359 | [ 360 | 8, 361 | 8, 362 | ], 363 | [ 364 | 8, 365 | 8, 366 | ], 367 | [ 368 | 8, 369 | 8, 370 | ], 371 | [ 372 | 8, 373 | 8, 374 | ], 375 | ], 376 | ], 377 | [ 378 | [ 379 | [ 380 | 8, 381 | 8, 382 | ], 383 | [ 384 | 8, 385 | 8, 386 | ], 387 | [ 388 | 8, 389 | 8, 390 | ], 391 | [ 392 | 8, 393 | 8, 394 | ], 395 | ], 396 | [ 397 | [ 398 | 8, 399 | 8, 400 | ], 401 | [ 402 | 8, 403 | 8, 404 | ], 405 | [ 406 | 8, 407 | 8, 408 | ], 409 | [ 410 | 8, 411 | 8, 412 | ], 413 | ], 414 | ], 415 | ], 416 | ] 417 | `; 418 | 419 | exports[`makeMatrix > callback initial values — math > %p [ 3, 2, 3 ] 1`] = ` 420 | [ 421 | [ 422 | [ 423 | 8, 424 | 8, 425 | 8, 426 | ], 427 | [ 428 | 8, 429 | 8, 430 | 8, 431 | ], 432 | ], 433 | [ 434 | [ 435 | 8, 436 | 8, 437 | 8, 438 | ], 439 | [ 440 | 8, 441 | 8, 442 | 8, 443 | ], 444 | ], 445 | [ 446 | [ 447 | 8, 448 | 8, 449 | 8, 450 | ], 451 | [ 452 | 8, 453 | 8, 454 | 8, 455 | ], 456 | ], 457 | ] 458 | `; 459 | 460 | exports[`makeMatrix > callback initial values — math > %p [ 6 ] 1`] = ` 461 | [ 462 | 8, 463 | 8, 464 | 8, 465 | 8, 466 | 8, 467 | 8, 468 | ] 469 | `; 470 | 471 | exports[`makeMatrix > no initial values > %p [ 1, 1 ] 1`] = ` 472 | [ 473 | [ 474 | null, 475 | ], 476 | ] 477 | `; 478 | 479 | exports[`makeMatrix > no initial values > %p [ 1, 4, 5, 2 ] 1`] = ` 480 | [ 481 | [ 482 | [ 483 | [ 484 | null, 485 | null, 486 | ], 487 | [ 488 | null, 489 | null, 490 | ], 491 | [ 492 | null, 493 | null, 494 | ], 495 | [ 496 | null, 497 | null, 498 | ], 499 | [ 500 | null, 501 | null, 502 | ], 503 | ], 504 | [ 505 | [ 506 | null, 507 | null, 508 | ], 509 | [ 510 | null, 511 | null, 512 | ], 513 | [ 514 | null, 515 | null, 516 | ], 517 | [ 518 | null, 519 | null, 520 | ], 521 | [ 522 | null, 523 | null, 524 | ], 525 | ], 526 | [ 527 | [ 528 | null, 529 | null, 530 | ], 531 | [ 532 | null, 533 | null, 534 | ], 535 | [ 536 | null, 537 | null, 538 | ], 539 | [ 540 | null, 541 | null, 542 | ], 543 | [ 544 | null, 545 | null, 546 | ], 547 | ], 548 | [ 549 | [ 550 | null, 551 | null, 552 | ], 553 | [ 554 | null, 555 | null, 556 | ], 557 | [ 558 | null, 559 | null, 560 | ], 561 | [ 562 | null, 563 | null, 564 | ], 565 | [ 566 | null, 567 | null, 568 | ], 569 | ], 570 | ], 571 | ] 572 | `; 573 | 574 | exports[`makeMatrix > no initial values > %p [ 2, 4, 2, 4, 2 ] 1`] = ` 575 | [ 576 | [ 577 | [ 578 | [ 579 | [ 580 | null, 581 | null, 582 | ], 583 | [ 584 | null, 585 | null, 586 | ], 587 | [ 588 | null, 589 | null, 590 | ], 591 | [ 592 | null, 593 | null, 594 | ], 595 | ], 596 | [ 597 | [ 598 | null, 599 | null, 600 | ], 601 | [ 602 | null, 603 | null, 604 | ], 605 | [ 606 | null, 607 | null, 608 | ], 609 | [ 610 | null, 611 | null, 612 | ], 613 | ], 614 | ], 615 | [ 616 | [ 617 | [ 618 | null, 619 | null, 620 | ], 621 | [ 622 | null, 623 | null, 624 | ], 625 | [ 626 | null, 627 | null, 628 | ], 629 | [ 630 | null, 631 | null, 632 | ], 633 | ], 634 | [ 635 | [ 636 | null, 637 | null, 638 | ], 639 | [ 640 | null, 641 | null, 642 | ], 643 | [ 644 | null, 645 | null, 646 | ], 647 | [ 648 | null, 649 | null, 650 | ], 651 | ], 652 | ], 653 | [ 654 | [ 655 | [ 656 | null, 657 | null, 658 | ], 659 | [ 660 | null, 661 | null, 662 | ], 663 | [ 664 | null, 665 | null, 666 | ], 667 | [ 668 | null, 669 | null, 670 | ], 671 | ], 672 | [ 673 | [ 674 | null, 675 | null, 676 | ], 677 | [ 678 | null, 679 | null, 680 | ], 681 | [ 682 | null, 683 | null, 684 | ], 685 | [ 686 | null, 687 | null, 688 | ], 689 | ], 690 | ], 691 | [ 692 | [ 693 | [ 694 | null, 695 | null, 696 | ], 697 | [ 698 | null, 699 | null, 700 | ], 701 | [ 702 | null, 703 | null, 704 | ], 705 | [ 706 | null, 707 | null, 708 | ], 709 | ], 710 | [ 711 | [ 712 | null, 713 | null, 714 | ], 715 | [ 716 | null, 717 | null, 718 | ], 719 | [ 720 | null, 721 | null, 722 | ], 723 | [ 724 | null, 725 | null, 726 | ], 727 | ], 728 | ], 729 | ], 730 | [ 731 | [ 732 | [ 733 | [ 734 | null, 735 | null, 736 | ], 737 | [ 738 | null, 739 | null, 740 | ], 741 | [ 742 | null, 743 | null, 744 | ], 745 | [ 746 | null, 747 | null, 748 | ], 749 | ], 750 | [ 751 | [ 752 | null, 753 | null, 754 | ], 755 | [ 756 | null, 757 | null, 758 | ], 759 | [ 760 | null, 761 | null, 762 | ], 763 | [ 764 | null, 765 | null, 766 | ], 767 | ], 768 | ], 769 | [ 770 | [ 771 | [ 772 | null, 773 | null, 774 | ], 775 | [ 776 | null, 777 | null, 778 | ], 779 | [ 780 | null, 781 | null, 782 | ], 783 | [ 784 | null, 785 | null, 786 | ], 787 | ], 788 | [ 789 | [ 790 | null, 791 | null, 792 | ], 793 | [ 794 | null, 795 | null, 796 | ], 797 | [ 798 | null, 799 | null, 800 | ], 801 | [ 802 | null, 803 | null, 804 | ], 805 | ], 806 | ], 807 | [ 808 | [ 809 | [ 810 | null, 811 | null, 812 | ], 813 | [ 814 | null, 815 | null, 816 | ], 817 | [ 818 | null, 819 | null, 820 | ], 821 | [ 822 | null, 823 | null, 824 | ], 825 | ], 826 | [ 827 | [ 828 | null, 829 | null, 830 | ], 831 | [ 832 | null, 833 | null, 834 | ], 835 | [ 836 | null, 837 | null, 838 | ], 839 | [ 840 | null, 841 | null, 842 | ], 843 | ], 844 | ], 845 | [ 846 | [ 847 | [ 848 | null, 849 | null, 850 | ], 851 | [ 852 | null, 853 | null, 854 | ], 855 | [ 856 | null, 857 | null, 858 | ], 859 | [ 860 | null, 861 | null, 862 | ], 863 | ], 864 | [ 865 | [ 866 | null, 867 | null, 868 | ], 869 | [ 870 | null, 871 | null, 872 | ], 873 | [ 874 | null, 875 | null, 876 | ], 877 | [ 878 | null, 879 | null, 880 | ], 881 | ], 882 | ], 883 | ], 884 | ] 885 | `; 886 | 887 | exports[`makeMatrix > no initial values > %p [ 3, 2, 3 ] 1`] = ` 888 | [ 889 | [ 890 | [ 891 | null, 892 | null, 893 | null, 894 | ], 895 | [ 896 | null, 897 | null, 898 | null, 899 | ], 900 | ], 901 | [ 902 | [ 903 | null, 904 | null, 905 | null, 906 | ], 907 | [ 908 | null, 909 | null, 910 | null, 911 | ], 912 | ], 913 | [ 914 | [ 915 | null, 916 | null, 917 | null, 918 | ], 919 | [ 920 | null, 921 | null, 922 | null, 923 | ], 924 | ], 925 | ] 926 | `; 927 | 928 | exports[`makeMatrix > no initial values > %p [ 6 ] 1`] = ` 929 | [ 930 | null, 931 | null, 932 | null, 933 | null, 934 | null, 935 | null, 936 | ] 937 | `; 938 | 939 | exports[`makeMatrix > number initial values > %p [ 1, 1 ] 1`] = ` 940 | [ 941 | [ 942 | 0, 943 | ], 944 | ] 945 | `; 946 | 947 | exports[`makeMatrix > number initial values > %p [ 1, 4, 5, 2 ] 1`] = ` 948 | [ 949 | [ 950 | [ 951 | [ 952 | 0, 953 | 0, 954 | ], 955 | [ 956 | 0, 957 | 0, 958 | ], 959 | [ 960 | 0, 961 | 0, 962 | ], 963 | [ 964 | 0, 965 | 0, 966 | ], 967 | [ 968 | 0, 969 | 0, 970 | ], 971 | ], 972 | [ 973 | [ 974 | 0, 975 | 0, 976 | ], 977 | [ 978 | 0, 979 | 0, 980 | ], 981 | [ 982 | 0, 983 | 0, 984 | ], 985 | [ 986 | 0, 987 | 0, 988 | ], 989 | [ 990 | 0, 991 | 0, 992 | ], 993 | ], 994 | [ 995 | [ 996 | 0, 997 | 0, 998 | ], 999 | [ 1000 | 0, 1001 | 0, 1002 | ], 1003 | [ 1004 | 0, 1005 | 0, 1006 | ], 1007 | [ 1008 | 0, 1009 | 0, 1010 | ], 1011 | [ 1012 | 0, 1013 | 0, 1014 | ], 1015 | ], 1016 | [ 1017 | [ 1018 | 0, 1019 | 0, 1020 | ], 1021 | [ 1022 | 0, 1023 | 0, 1024 | ], 1025 | [ 1026 | 0, 1027 | 0, 1028 | ], 1029 | [ 1030 | 0, 1031 | 0, 1032 | ], 1033 | [ 1034 | 0, 1035 | 0, 1036 | ], 1037 | ], 1038 | ], 1039 | ] 1040 | `; 1041 | 1042 | exports[`makeMatrix > number initial values > %p [ 2, 4, 2, 4, 2 ] 1`] = ` 1043 | [ 1044 | [ 1045 | [ 1046 | [ 1047 | [ 1048 | 0, 1049 | 0, 1050 | ], 1051 | [ 1052 | 0, 1053 | 0, 1054 | ], 1055 | [ 1056 | 0, 1057 | 0, 1058 | ], 1059 | [ 1060 | 0, 1061 | 0, 1062 | ], 1063 | ], 1064 | [ 1065 | [ 1066 | 0, 1067 | 0, 1068 | ], 1069 | [ 1070 | 0, 1071 | 0, 1072 | ], 1073 | [ 1074 | 0, 1075 | 0, 1076 | ], 1077 | [ 1078 | 0, 1079 | 0, 1080 | ], 1081 | ], 1082 | ], 1083 | [ 1084 | [ 1085 | [ 1086 | 0, 1087 | 0, 1088 | ], 1089 | [ 1090 | 0, 1091 | 0, 1092 | ], 1093 | [ 1094 | 0, 1095 | 0, 1096 | ], 1097 | [ 1098 | 0, 1099 | 0, 1100 | ], 1101 | ], 1102 | [ 1103 | [ 1104 | 0, 1105 | 0, 1106 | ], 1107 | [ 1108 | 0, 1109 | 0, 1110 | ], 1111 | [ 1112 | 0, 1113 | 0, 1114 | ], 1115 | [ 1116 | 0, 1117 | 0, 1118 | ], 1119 | ], 1120 | ], 1121 | [ 1122 | [ 1123 | [ 1124 | 0, 1125 | 0, 1126 | ], 1127 | [ 1128 | 0, 1129 | 0, 1130 | ], 1131 | [ 1132 | 0, 1133 | 0, 1134 | ], 1135 | [ 1136 | 0, 1137 | 0, 1138 | ], 1139 | ], 1140 | [ 1141 | [ 1142 | 0, 1143 | 0, 1144 | ], 1145 | [ 1146 | 0, 1147 | 0, 1148 | ], 1149 | [ 1150 | 0, 1151 | 0, 1152 | ], 1153 | [ 1154 | 0, 1155 | 0, 1156 | ], 1157 | ], 1158 | ], 1159 | [ 1160 | [ 1161 | [ 1162 | 0, 1163 | 0, 1164 | ], 1165 | [ 1166 | 0, 1167 | 0, 1168 | ], 1169 | [ 1170 | 0, 1171 | 0, 1172 | ], 1173 | [ 1174 | 0, 1175 | 0, 1176 | ], 1177 | ], 1178 | [ 1179 | [ 1180 | 0, 1181 | 0, 1182 | ], 1183 | [ 1184 | 0, 1185 | 0, 1186 | ], 1187 | [ 1188 | 0, 1189 | 0, 1190 | ], 1191 | [ 1192 | 0, 1193 | 0, 1194 | ], 1195 | ], 1196 | ], 1197 | ], 1198 | [ 1199 | [ 1200 | [ 1201 | [ 1202 | 0, 1203 | 0, 1204 | ], 1205 | [ 1206 | 0, 1207 | 0, 1208 | ], 1209 | [ 1210 | 0, 1211 | 0, 1212 | ], 1213 | [ 1214 | 0, 1215 | 0, 1216 | ], 1217 | ], 1218 | [ 1219 | [ 1220 | 0, 1221 | 0, 1222 | ], 1223 | [ 1224 | 0, 1225 | 0, 1226 | ], 1227 | [ 1228 | 0, 1229 | 0, 1230 | ], 1231 | [ 1232 | 0, 1233 | 0, 1234 | ], 1235 | ], 1236 | ], 1237 | [ 1238 | [ 1239 | [ 1240 | 0, 1241 | 0, 1242 | ], 1243 | [ 1244 | 0, 1245 | 0, 1246 | ], 1247 | [ 1248 | 0, 1249 | 0, 1250 | ], 1251 | [ 1252 | 0, 1253 | 0, 1254 | ], 1255 | ], 1256 | [ 1257 | [ 1258 | 0, 1259 | 0, 1260 | ], 1261 | [ 1262 | 0, 1263 | 0, 1264 | ], 1265 | [ 1266 | 0, 1267 | 0, 1268 | ], 1269 | [ 1270 | 0, 1271 | 0, 1272 | ], 1273 | ], 1274 | ], 1275 | [ 1276 | [ 1277 | [ 1278 | 0, 1279 | 0, 1280 | ], 1281 | [ 1282 | 0, 1283 | 0, 1284 | ], 1285 | [ 1286 | 0, 1287 | 0, 1288 | ], 1289 | [ 1290 | 0, 1291 | 0, 1292 | ], 1293 | ], 1294 | [ 1295 | [ 1296 | 0, 1297 | 0, 1298 | ], 1299 | [ 1300 | 0, 1301 | 0, 1302 | ], 1303 | [ 1304 | 0, 1305 | 0, 1306 | ], 1307 | [ 1308 | 0, 1309 | 0, 1310 | ], 1311 | ], 1312 | ], 1313 | [ 1314 | [ 1315 | [ 1316 | 0, 1317 | 0, 1318 | ], 1319 | [ 1320 | 0, 1321 | 0, 1322 | ], 1323 | [ 1324 | 0, 1325 | 0, 1326 | ], 1327 | [ 1328 | 0, 1329 | 0, 1330 | ], 1331 | ], 1332 | [ 1333 | [ 1334 | 0, 1335 | 0, 1336 | ], 1337 | [ 1338 | 0, 1339 | 0, 1340 | ], 1341 | [ 1342 | 0, 1343 | 0, 1344 | ], 1345 | [ 1346 | 0, 1347 | 0, 1348 | ], 1349 | ], 1350 | ], 1351 | ], 1352 | ] 1353 | `; 1354 | 1355 | exports[`makeMatrix > number initial values > %p [ 3, 2, 3 ] 1`] = ` 1356 | [ 1357 | [ 1358 | [ 1359 | 0, 1360 | 0, 1361 | 0, 1362 | ], 1363 | [ 1364 | 0, 1365 | 0, 1366 | 0, 1367 | ], 1368 | ], 1369 | [ 1370 | [ 1371 | 0, 1372 | 0, 1373 | 0, 1374 | ], 1375 | [ 1376 | 0, 1377 | 0, 1378 | 0, 1379 | ], 1380 | ], 1381 | [ 1382 | [ 1383 | 0, 1384 | 0, 1385 | 0, 1386 | ], 1387 | [ 1388 | 0, 1389 | 0, 1390 | 0, 1391 | ], 1392 | ], 1393 | ] 1394 | `; 1395 | 1396 | exports[`makeMatrix > number initial values > %p [ 6 ] 1`] = ` 1397 | [ 1398 | 0, 1399 | 0, 1400 | 0, 1401 | 0, 1402 | 0, 1403 | 0, 1404 | ] 1405 | `; 1406 | 1407 | exports[`makeMatrix > self aware callback initial values > %p [ 1, 1 ] 1`] = ` 1408 | [ 1409 | [ 1410 | [ 1411 | 0, 1412 | 0, 1413 | ], 1414 | ], 1415 | ] 1416 | `; 1417 | 1418 | exports[`makeMatrix > self aware callback initial values > %p [ 1, 4, 5, 2 ] 1`] = ` 1419 | [ 1420 | [ 1421 | [ 1422 | [ 1423 | [ 1424 | 0, 1425 | 0, 1426 | 0, 1427 | 0, 1428 | ], 1429 | [ 1430 | 0, 1431 | 0, 1432 | 0, 1433 | 1, 1434 | ], 1435 | ], 1436 | [ 1437 | [ 1438 | 0, 1439 | 0, 1440 | 1, 1441 | 0, 1442 | ], 1443 | [ 1444 | 0, 1445 | 0, 1446 | 1, 1447 | 1, 1448 | ], 1449 | ], 1450 | [ 1451 | [ 1452 | 0, 1453 | 0, 1454 | 2, 1455 | 0, 1456 | ], 1457 | [ 1458 | 0, 1459 | 0, 1460 | 2, 1461 | 1, 1462 | ], 1463 | ], 1464 | [ 1465 | [ 1466 | 0, 1467 | 0, 1468 | 3, 1469 | 0, 1470 | ], 1471 | [ 1472 | 0, 1473 | 0, 1474 | 3, 1475 | 1, 1476 | ], 1477 | ], 1478 | [ 1479 | [ 1480 | 0, 1481 | 0, 1482 | 4, 1483 | 0, 1484 | ], 1485 | [ 1486 | 0, 1487 | 0, 1488 | 4, 1489 | 1, 1490 | ], 1491 | ], 1492 | ], 1493 | [ 1494 | [ 1495 | [ 1496 | 0, 1497 | 1, 1498 | 0, 1499 | 0, 1500 | ], 1501 | [ 1502 | 0, 1503 | 1, 1504 | 0, 1505 | 1, 1506 | ], 1507 | ], 1508 | [ 1509 | [ 1510 | 0, 1511 | 1, 1512 | 1, 1513 | 0, 1514 | ], 1515 | [ 1516 | 0, 1517 | 1, 1518 | 1, 1519 | 1, 1520 | ], 1521 | ], 1522 | [ 1523 | [ 1524 | 0, 1525 | 1, 1526 | 2, 1527 | 0, 1528 | ], 1529 | [ 1530 | 0, 1531 | 1, 1532 | 2, 1533 | 1, 1534 | ], 1535 | ], 1536 | [ 1537 | [ 1538 | 0, 1539 | 1, 1540 | 3, 1541 | 0, 1542 | ], 1543 | [ 1544 | 0, 1545 | 1, 1546 | 3, 1547 | 1, 1548 | ], 1549 | ], 1550 | [ 1551 | [ 1552 | 0, 1553 | 1, 1554 | 4, 1555 | 0, 1556 | ], 1557 | [ 1558 | 0, 1559 | 1, 1560 | 4, 1561 | 1, 1562 | ], 1563 | ], 1564 | ], 1565 | [ 1566 | [ 1567 | [ 1568 | 0, 1569 | 2, 1570 | 0, 1571 | 0, 1572 | ], 1573 | [ 1574 | 0, 1575 | 2, 1576 | 0, 1577 | 1, 1578 | ], 1579 | ], 1580 | [ 1581 | [ 1582 | 0, 1583 | 2, 1584 | 1, 1585 | 0, 1586 | ], 1587 | [ 1588 | 0, 1589 | 2, 1590 | 1, 1591 | 1, 1592 | ], 1593 | ], 1594 | [ 1595 | [ 1596 | 0, 1597 | 2, 1598 | 2, 1599 | 0, 1600 | ], 1601 | [ 1602 | 0, 1603 | 2, 1604 | 2, 1605 | 1, 1606 | ], 1607 | ], 1608 | [ 1609 | [ 1610 | 0, 1611 | 2, 1612 | 3, 1613 | 0, 1614 | ], 1615 | [ 1616 | 0, 1617 | 2, 1618 | 3, 1619 | 1, 1620 | ], 1621 | ], 1622 | [ 1623 | [ 1624 | 0, 1625 | 2, 1626 | 4, 1627 | 0, 1628 | ], 1629 | [ 1630 | 0, 1631 | 2, 1632 | 4, 1633 | 1, 1634 | ], 1635 | ], 1636 | ], 1637 | [ 1638 | [ 1639 | [ 1640 | 0, 1641 | 3, 1642 | 0, 1643 | 0, 1644 | ], 1645 | [ 1646 | 0, 1647 | 3, 1648 | 0, 1649 | 1, 1650 | ], 1651 | ], 1652 | [ 1653 | [ 1654 | 0, 1655 | 3, 1656 | 1, 1657 | 0, 1658 | ], 1659 | [ 1660 | 0, 1661 | 3, 1662 | 1, 1663 | 1, 1664 | ], 1665 | ], 1666 | [ 1667 | [ 1668 | 0, 1669 | 3, 1670 | 2, 1671 | 0, 1672 | ], 1673 | [ 1674 | 0, 1675 | 3, 1676 | 2, 1677 | 1, 1678 | ], 1679 | ], 1680 | [ 1681 | [ 1682 | 0, 1683 | 3, 1684 | 3, 1685 | 0, 1686 | ], 1687 | [ 1688 | 0, 1689 | 3, 1690 | 3, 1691 | 1, 1692 | ], 1693 | ], 1694 | [ 1695 | [ 1696 | 0, 1697 | 3, 1698 | 4, 1699 | 0, 1700 | ], 1701 | [ 1702 | 0, 1703 | 3, 1704 | 4, 1705 | 1, 1706 | ], 1707 | ], 1708 | ], 1709 | ], 1710 | ] 1711 | `; 1712 | 1713 | exports[`makeMatrix > self aware callback initial values > %p [ 2, 4, 2, 4, 2 ] 1`] = ` 1714 | [ 1715 | [ 1716 | [ 1717 | [ 1718 | [ 1719 | [ 1720 | 0, 1721 | 0, 1722 | 0, 1723 | 0, 1724 | 0, 1725 | ], 1726 | [ 1727 | 0, 1728 | 0, 1729 | 0, 1730 | 0, 1731 | 1, 1732 | ], 1733 | ], 1734 | [ 1735 | [ 1736 | 0, 1737 | 0, 1738 | 0, 1739 | 1, 1740 | 0, 1741 | ], 1742 | [ 1743 | 0, 1744 | 0, 1745 | 0, 1746 | 1, 1747 | 1, 1748 | ], 1749 | ], 1750 | [ 1751 | [ 1752 | 0, 1753 | 0, 1754 | 0, 1755 | 2, 1756 | 0, 1757 | ], 1758 | [ 1759 | 0, 1760 | 0, 1761 | 0, 1762 | 2, 1763 | 1, 1764 | ], 1765 | ], 1766 | [ 1767 | [ 1768 | 0, 1769 | 0, 1770 | 0, 1771 | 3, 1772 | 0, 1773 | ], 1774 | [ 1775 | 0, 1776 | 0, 1777 | 0, 1778 | 3, 1779 | 1, 1780 | ], 1781 | ], 1782 | ], 1783 | [ 1784 | [ 1785 | [ 1786 | 0, 1787 | 0, 1788 | 1, 1789 | 0, 1790 | 0, 1791 | ], 1792 | [ 1793 | 0, 1794 | 0, 1795 | 1, 1796 | 0, 1797 | 1, 1798 | ], 1799 | ], 1800 | [ 1801 | [ 1802 | 0, 1803 | 0, 1804 | 1, 1805 | 1, 1806 | 0, 1807 | ], 1808 | [ 1809 | 0, 1810 | 0, 1811 | 1, 1812 | 1, 1813 | 1, 1814 | ], 1815 | ], 1816 | [ 1817 | [ 1818 | 0, 1819 | 0, 1820 | 1, 1821 | 2, 1822 | 0, 1823 | ], 1824 | [ 1825 | 0, 1826 | 0, 1827 | 1, 1828 | 2, 1829 | 1, 1830 | ], 1831 | ], 1832 | [ 1833 | [ 1834 | 0, 1835 | 0, 1836 | 1, 1837 | 3, 1838 | 0, 1839 | ], 1840 | [ 1841 | 0, 1842 | 0, 1843 | 1, 1844 | 3, 1845 | 1, 1846 | ], 1847 | ], 1848 | ], 1849 | ], 1850 | [ 1851 | [ 1852 | [ 1853 | [ 1854 | 0, 1855 | 1, 1856 | 0, 1857 | 0, 1858 | 0, 1859 | ], 1860 | [ 1861 | 0, 1862 | 1, 1863 | 0, 1864 | 0, 1865 | 1, 1866 | ], 1867 | ], 1868 | [ 1869 | [ 1870 | 0, 1871 | 1, 1872 | 0, 1873 | 1, 1874 | 0, 1875 | ], 1876 | [ 1877 | 0, 1878 | 1, 1879 | 0, 1880 | 1, 1881 | 1, 1882 | ], 1883 | ], 1884 | [ 1885 | [ 1886 | 0, 1887 | 1, 1888 | 0, 1889 | 2, 1890 | 0, 1891 | ], 1892 | [ 1893 | 0, 1894 | 1, 1895 | 0, 1896 | 2, 1897 | 1, 1898 | ], 1899 | ], 1900 | [ 1901 | [ 1902 | 0, 1903 | 1, 1904 | 0, 1905 | 3, 1906 | 0, 1907 | ], 1908 | [ 1909 | 0, 1910 | 1, 1911 | 0, 1912 | 3, 1913 | 1, 1914 | ], 1915 | ], 1916 | ], 1917 | [ 1918 | [ 1919 | [ 1920 | 0, 1921 | 1, 1922 | 1, 1923 | 0, 1924 | 0, 1925 | ], 1926 | [ 1927 | 0, 1928 | 1, 1929 | 1, 1930 | 0, 1931 | 1, 1932 | ], 1933 | ], 1934 | [ 1935 | [ 1936 | 0, 1937 | 1, 1938 | 1, 1939 | 1, 1940 | 0, 1941 | ], 1942 | [ 1943 | 0, 1944 | 1, 1945 | 1, 1946 | 1, 1947 | 1, 1948 | ], 1949 | ], 1950 | [ 1951 | [ 1952 | 0, 1953 | 1, 1954 | 1, 1955 | 2, 1956 | 0, 1957 | ], 1958 | [ 1959 | 0, 1960 | 1, 1961 | 1, 1962 | 2, 1963 | 1, 1964 | ], 1965 | ], 1966 | [ 1967 | [ 1968 | 0, 1969 | 1, 1970 | 1, 1971 | 3, 1972 | 0, 1973 | ], 1974 | [ 1975 | 0, 1976 | 1, 1977 | 1, 1978 | 3, 1979 | 1, 1980 | ], 1981 | ], 1982 | ], 1983 | ], 1984 | [ 1985 | [ 1986 | [ 1987 | [ 1988 | 0, 1989 | 2, 1990 | 0, 1991 | 0, 1992 | 0, 1993 | ], 1994 | [ 1995 | 0, 1996 | 2, 1997 | 0, 1998 | 0, 1999 | 1, 2000 | ], 2001 | ], 2002 | [ 2003 | [ 2004 | 0, 2005 | 2, 2006 | 0, 2007 | 1, 2008 | 0, 2009 | ], 2010 | [ 2011 | 0, 2012 | 2, 2013 | 0, 2014 | 1, 2015 | 1, 2016 | ], 2017 | ], 2018 | [ 2019 | [ 2020 | 0, 2021 | 2, 2022 | 0, 2023 | 2, 2024 | 0, 2025 | ], 2026 | [ 2027 | 0, 2028 | 2, 2029 | 0, 2030 | 2, 2031 | 1, 2032 | ], 2033 | ], 2034 | [ 2035 | [ 2036 | 0, 2037 | 2, 2038 | 0, 2039 | 3, 2040 | 0, 2041 | ], 2042 | [ 2043 | 0, 2044 | 2, 2045 | 0, 2046 | 3, 2047 | 1, 2048 | ], 2049 | ], 2050 | ], 2051 | [ 2052 | [ 2053 | [ 2054 | 0, 2055 | 2, 2056 | 1, 2057 | 0, 2058 | 0, 2059 | ], 2060 | [ 2061 | 0, 2062 | 2, 2063 | 1, 2064 | 0, 2065 | 1, 2066 | ], 2067 | ], 2068 | [ 2069 | [ 2070 | 0, 2071 | 2, 2072 | 1, 2073 | 1, 2074 | 0, 2075 | ], 2076 | [ 2077 | 0, 2078 | 2, 2079 | 1, 2080 | 1, 2081 | 1, 2082 | ], 2083 | ], 2084 | [ 2085 | [ 2086 | 0, 2087 | 2, 2088 | 1, 2089 | 2, 2090 | 0, 2091 | ], 2092 | [ 2093 | 0, 2094 | 2, 2095 | 1, 2096 | 2, 2097 | 1, 2098 | ], 2099 | ], 2100 | [ 2101 | [ 2102 | 0, 2103 | 2, 2104 | 1, 2105 | 3, 2106 | 0, 2107 | ], 2108 | [ 2109 | 0, 2110 | 2, 2111 | 1, 2112 | 3, 2113 | 1, 2114 | ], 2115 | ], 2116 | ], 2117 | ], 2118 | [ 2119 | [ 2120 | [ 2121 | [ 2122 | 0, 2123 | 3, 2124 | 0, 2125 | 0, 2126 | 0, 2127 | ], 2128 | [ 2129 | 0, 2130 | 3, 2131 | 0, 2132 | 0, 2133 | 1, 2134 | ], 2135 | ], 2136 | [ 2137 | [ 2138 | 0, 2139 | 3, 2140 | 0, 2141 | 1, 2142 | 0, 2143 | ], 2144 | [ 2145 | 0, 2146 | 3, 2147 | 0, 2148 | 1, 2149 | 1, 2150 | ], 2151 | ], 2152 | [ 2153 | [ 2154 | 0, 2155 | 3, 2156 | 0, 2157 | 2, 2158 | 0, 2159 | ], 2160 | [ 2161 | 0, 2162 | 3, 2163 | 0, 2164 | 2, 2165 | 1, 2166 | ], 2167 | ], 2168 | [ 2169 | [ 2170 | 0, 2171 | 3, 2172 | 0, 2173 | 3, 2174 | 0, 2175 | ], 2176 | [ 2177 | 0, 2178 | 3, 2179 | 0, 2180 | 3, 2181 | 1, 2182 | ], 2183 | ], 2184 | ], 2185 | [ 2186 | [ 2187 | [ 2188 | 0, 2189 | 3, 2190 | 1, 2191 | 0, 2192 | 0, 2193 | ], 2194 | [ 2195 | 0, 2196 | 3, 2197 | 1, 2198 | 0, 2199 | 1, 2200 | ], 2201 | ], 2202 | [ 2203 | [ 2204 | 0, 2205 | 3, 2206 | 1, 2207 | 1, 2208 | 0, 2209 | ], 2210 | [ 2211 | 0, 2212 | 3, 2213 | 1, 2214 | 1, 2215 | 1, 2216 | ], 2217 | ], 2218 | [ 2219 | [ 2220 | 0, 2221 | 3, 2222 | 1, 2223 | 2, 2224 | 0, 2225 | ], 2226 | [ 2227 | 0, 2228 | 3, 2229 | 1, 2230 | 2, 2231 | 1, 2232 | ], 2233 | ], 2234 | [ 2235 | [ 2236 | 0, 2237 | 3, 2238 | 1, 2239 | 3, 2240 | 0, 2241 | ], 2242 | [ 2243 | 0, 2244 | 3, 2245 | 1, 2246 | 3, 2247 | 1, 2248 | ], 2249 | ], 2250 | ], 2251 | ], 2252 | ], 2253 | [ 2254 | [ 2255 | [ 2256 | [ 2257 | [ 2258 | 1, 2259 | 0, 2260 | 0, 2261 | 0, 2262 | 0, 2263 | ], 2264 | [ 2265 | 1, 2266 | 0, 2267 | 0, 2268 | 0, 2269 | 1, 2270 | ], 2271 | ], 2272 | [ 2273 | [ 2274 | 1, 2275 | 0, 2276 | 0, 2277 | 1, 2278 | 0, 2279 | ], 2280 | [ 2281 | 1, 2282 | 0, 2283 | 0, 2284 | 1, 2285 | 1, 2286 | ], 2287 | ], 2288 | [ 2289 | [ 2290 | 1, 2291 | 0, 2292 | 0, 2293 | 2, 2294 | 0, 2295 | ], 2296 | [ 2297 | 1, 2298 | 0, 2299 | 0, 2300 | 2, 2301 | 1, 2302 | ], 2303 | ], 2304 | [ 2305 | [ 2306 | 1, 2307 | 0, 2308 | 0, 2309 | 3, 2310 | 0, 2311 | ], 2312 | [ 2313 | 1, 2314 | 0, 2315 | 0, 2316 | 3, 2317 | 1, 2318 | ], 2319 | ], 2320 | ], 2321 | [ 2322 | [ 2323 | [ 2324 | 1, 2325 | 0, 2326 | 1, 2327 | 0, 2328 | 0, 2329 | ], 2330 | [ 2331 | 1, 2332 | 0, 2333 | 1, 2334 | 0, 2335 | 1, 2336 | ], 2337 | ], 2338 | [ 2339 | [ 2340 | 1, 2341 | 0, 2342 | 1, 2343 | 1, 2344 | 0, 2345 | ], 2346 | [ 2347 | 1, 2348 | 0, 2349 | 1, 2350 | 1, 2351 | 1, 2352 | ], 2353 | ], 2354 | [ 2355 | [ 2356 | 1, 2357 | 0, 2358 | 1, 2359 | 2, 2360 | 0, 2361 | ], 2362 | [ 2363 | 1, 2364 | 0, 2365 | 1, 2366 | 2, 2367 | 1, 2368 | ], 2369 | ], 2370 | [ 2371 | [ 2372 | 1, 2373 | 0, 2374 | 1, 2375 | 3, 2376 | 0, 2377 | ], 2378 | [ 2379 | 1, 2380 | 0, 2381 | 1, 2382 | 3, 2383 | 1, 2384 | ], 2385 | ], 2386 | ], 2387 | ], 2388 | [ 2389 | [ 2390 | [ 2391 | [ 2392 | 1, 2393 | 1, 2394 | 0, 2395 | 0, 2396 | 0, 2397 | ], 2398 | [ 2399 | 1, 2400 | 1, 2401 | 0, 2402 | 0, 2403 | 1, 2404 | ], 2405 | ], 2406 | [ 2407 | [ 2408 | 1, 2409 | 1, 2410 | 0, 2411 | 1, 2412 | 0, 2413 | ], 2414 | [ 2415 | 1, 2416 | 1, 2417 | 0, 2418 | 1, 2419 | 1, 2420 | ], 2421 | ], 2422 | [ 2423 | [ 2424 | 1, 2425 | 1, 2426 | 0, 2427 | 2, 2428 | 0, 2429 | ], 2430 | [ 2431 | 1, 2432 | 1, 2433 | 0, 2434 | 2, 2435 | 1, 2436 | ], 2437 | ], 2438 | [ 2439 | [ 2440 | 1, 2441 | 1, 2442 | 0, 2443 | 3, 2444 | 0, 2445 | ], 2446 | [ 2447 | 1, 2448 | 1, 2449 | 0, 2450 | 3, 2451 | 1, 2452 | ], 2453 | ], 2454 | ], 2455 | [ 2456 | [ 2457 | [ 2458 | 1, 2459 | 1, 2460 | 1, 2461 | 0, 2462 | 0, 2463 | ], 2464 | [ 2465 | 1, 2466 | 1, 2467 | 1, 2468 | 0, 2469 | 1, 2470 | ], 2471 | ], 2472 | [ 2473 | [ 2474 | 1, 2475 | 1, 2476 | 1, 2477 | 1, 2478 | 0, 2479 | ], 2480 | [ 2481 | 1, 2482 | 1, 2483 | 1, 2484 | 1, 2485 | 1, 2486 | ], 2487 | ], 2488 | [ 2489 | [ 2490 | 1, 2491 | 1, 2492 | 1, 2493 | 2, 2494 | 0, 2495 | ], 2496 | [ 2497 | 1, 2498 | 1, 2499 | 1, 2500 | 2, 2501 | 1, 2502 | ], 2503 | ], 2504 | [ 2505 | [ 2506 | 1, 2507 | 1, 2508 | 1, 2509 | 3, 2510 | 0, 2511 | ], 2512 | [ 2513 | 1, 2514 | 1, 2515 | 1, 2516 | 3, 2517 | 1, 2518 | ], 2519 | ], 2520 | ], 2521 | ], 2522 | [ 2523 | [ 2524 | [ 2525 | [ 2526 | 1, 2527 | 2, 2528 | 0, 2529 | 0, 2530 | 0, 2531 | ], 2532 | [ 2533 | 1, 2534 | 2, 2535 | 0, 2536 | 0, 2537 | 1, 2538 | ], 2539 | ], 2540 | [ 2541 | [ 2542 | 1, 2543 | 2, 2544 | 0, 2545 | 1, 2546 | 0, 2547 | ], 2548 | [ 2549 | 1, 2550 | 2, 2551 | 0, 2552 | 1, 2553 | 1, 2554 | ], 2555 | ], 2556 | [ 2557 | [ 2558 | 1, 2559 | 2, 2560 | 0, 2561 | 2, 2562 | 0, 2563 | ], 2564 | [ 2565 | 1, 2566 | 2, 2567 | 0, 2568 | 2, 2569 | 1, 2570 | ], 2571 | ], 2572 | [ 2573 | [ 2574 | 1, 2575 | 2, 2576 | 0, 2577 | 3, 2578 | 0, 2579 | ], 2580 | [ 2581 | 1, 2582 | 2, 2583 | 0, 2584 | 3, 2585 | 1, 2586 | ], 2587 | ], 2588 | ], 2589 | [ 2590 | [ 2591 | [ 2592 | 1, 2593 | 2, 2594 | 1, 2595 | 0, 2596 | 0, 2597 | ], 2598 | [ 2599 | 1, 2600 | 2, 2601 | 1, 2602 | 0, 2603 | 1, 2604 | ], 2605 | ], 2606 | [ 2607 | [ 2608 | 1, 2609 | 2, 2610 | 1, 2611 | 1, 2612 | 0, 2613 | ], 2614 | [ 2615 | 1, 2616 | 2, 2617 | 1, 2618 | 1, 2619 | 1, 2620 | ], 2621 | ], 2622 | [ 2623 | [ 2624 | 1, 2625 | 2, 2626 | 1, 2627 | 2, 2628 | 0, 2629 | ], 2630 | [ 2631 | 1, 2632 | 2, 2633 | 1, 2634 | 2, 2635 | 1, 2636 | ], 2637 | ], 2638 | [ 2639 | [ 2640 | 1, 2641 | 2, 2642 | 1, 2643 | 3, 2644 | 0, 2645 | ], 2646 | [ 2647 | 1, 2648 | 2, 2649 | 1, 2650 | 3, 2651 | 1, 2652 | ], 2653 | ], 2654 | ], 2655 | ], 2656 | [ 2657 | [ 2658 | [ 2659 | [ 2660 | 1, 2661 | 3, 2662 | 0, 2663 | 0, 2664 | 0, 2665 | ], 2666 | [ 2667 | 1, 2668 | 3, 2669 | 0, 2670 | 0, 2671 | 1, 2672 | ], 2673 | ], 2674 | [ 2675 | [ 2676 | 1, 2677 | 3, 2678 | 0, 2679 | 1, 2680 | 0, 2681 | ], 2682 | [ 2683 | 1, 2684 | 3, 2685 | 0, 2686 | 1, 2687 | 1, 2688 | ], 2689 | ], 2690 | [ 2691 | [ 2692 | 1, 2693 | 3, 2694 | 0, 2695 | 2, 2696 | 0, 2697 | ], 2698 | [ 2699 | 1, 2700 | 3, 2701 | 0, 2702 | 2, 2703 | 1, 2704 | ], 2705 | ], 2706 | [ 2707 | [ 2708 | 1, 2709 | 3, 2710 | 0, 2711 | 3, 2712 | 0, 2713 | ], 2714 | [ 2715 | 1, 2716 | 3, 2717 | 0, 2718 | 3, 2719 | 1, 2720 | ], 2721 | ], 2722 | ], 2723 | [ 2724 | [ 2725 | [ 2726 | 1, 2727 | 3, 2728 | 1, 2729 | 0, 2730 | 0, 2731 | ], 2732 | [ 2733 | 1, 2734 | 3, 2735 | 1, 2736 | 0, 2737 | 1, 2738 | ], 2739 | ], 2740 | [ 2741 | [ 2742 | 1, 2743 | 3, 2744 | 1, 2745 | 1, 2746 | 0, 2747 | ], 2748 | [ 2749 | 1, 2750 | 3, 2751 | 1, 2752 | 1, 2753 | 1, 2754 | ], 2755 | ], 2756 | [ 2757 | [ 2758 | 1, 2759 | 3, 2760 | 1, 2761 | 2, 2762 | 0, 2763 | ], 2764 | [ 2765 | 1, 2766 | 3, 2767 | 1, 2768 | 2, 2769 | 1, 2770 | ], 2771 | ], 2772 | [ 2773 | [ 2774 | 1, 2775 | 3, 2776 | 1, 2777 | 3, 2778 | 0, 2779 | ], 2780 | [ 2781 | 1, 2782 | 3, 2783 | 1, 2784 | 3, 2785 | 1, 2786 | ], 2787 | ], 2788 | ], 2789 | ], 2790 | ], 2791 | ] 2792 | `; 2793 | 2794 | exports[`makeMatrix > self aware callback initial values > %p [ 3, 2, 3 ] 1`] = ` 2795 | [ 2796 | [ 2797 | [ 2798 | [ 2799 | 0, 2800 | 0, 2801 | 0, 2802 | ], 2803 | [ 2804 | 0, 2805 | 0, 2806 | 1, 2807 | ], 2808 | [ 2809 | 0, 2810 | 0, 2811 | 2, 2812 | ], 2813 | ], 2814 | [ 2815 | [ 2816 | 0, 2817 | 1, 2818 | 0, 2819 | ], 2820 | [ 2821 | 0, 2822 | 1, 2823 | 1, 2824 | ], 2825 | [ 2826 | 0, 2827 | 1, 2828 | 2, 2829 | ], 2830 | ], 2831 | ], 2832 | [ 2833 | [ 2834 | [ 2835 | 1, 2836 | 0, 2837 | 0, 2838 | ], 2839 | [ 2840 | 1, 2841 | 0, 2842 | 1, 2843 | ], 2844 | [ 2845 | 1, 2846 | 0, 2847 | 2, 2848 | ], 2849 | ], 2850 | [ 2851 | [ 2852 | 1, 2853 | 1, 2854 | 0, 2855 | ], 2856 | [ 2857 | 1, 2858 | 1, 2859 | 1, 2860 | ], 2861 | [ 2862 | 1, 2863 | 1, 2864 | 2, 2865 | ], 2866 | ], 2867 | ], 2868 | [ 2869 | [ 2870 | [ 2871 | 2, 2872 | 0, 2873 | 0, 2874 | ], 2875 | [ 2876 | 2, 2877 | 0, 2878 | 1, 2879 | ], 2880 | [ 2881 | 2, 2882 | 0, 2883 | 2, 2884 | ], 2885 | ], 2886 | [ 2887 | [ 2888 | 2, 2889 | 1, 2890 | 0, 2891 | ], 2892 | [ 2893 | 2, 2894 | 1, 2895 | 1, 2896 | ], 2897 | [ 2898 | 2, 2899 | 1, 2900 | 2, 2901 | ], 2902 | ], 2903 | ], 2904 | ] 2905 | `; 2906 | 2907 | exports[`makeMatrix > self aware callback initial values > %p [ 6 ] 1`] = ` 2908 | [ 2909 | [ 2910 | 0, 2911 | ], 2912 | [ 2913 | 1, 2914 | ], 2915 | [ 2916 | 2, 2917 | ], 2918 | [ 2919 | 3, 2920 | ], 2921 | [ 2922 | 4, 2923 | ], 2924 | [ 2925 | 5, 2926 | ], 2927 | ] 2928 | `; 2929 | 2930 | exports[`makeMatrix > string initial values > %p [ 1, 1 ] 1`] = ` 2931 | [ 2932 | [ 2933 | "string", 2934 | ], 2935 | ] 2936 | `; 2937 | 2938 | exports[`makeMatrix > string initial values > %p [ 1, 4, 5, 2 ] 1`] = ` 2939 | [ 2940 | [ 2941 | [ 2942 | [ 2943 | "string", 2944 | "string", 2945 | ], 2946 | [ 2947 | "string", 2948 | "string", 2949 | ], 2950 | [ 2951 | "string", 2952 | "string", 2953 | ], 2954 | [ 2955 | "string", 2956 | "string", 2957 | ], 2958 | [ 2959 | "string", 2960 | "string", 2961 | ], 2962 | ], 2963 | [ 2964 | [ 2965 | "string", 2966 | "string", 2967 | ], 2968 | [ 2969 | "string", 2970 | "string", 2971 | ], 2972 | [ 2973 | "string", 2974 | "string", 2975 | ], 2976 | [ 2977 | "string", 2978 | "string", 2979 | ], 2980 | [ 2981 | "string", 2982 | "string", 2983 | ], 2984 | ], 2985 | [ 2986 | [ 2987 | "string", 2988 | "string", 2989 | ], 2990 | [ 2991 | "string", 2992 | "string", 2993 | ], 2994 | [ 2995 | "string", 2996 | "string", 2997 | ], 2998 | [ 2999 | "string", 3000 | "string", 3001 | ], 3002 | [ 3003 | "string", 3004 | "string", 3005 | ], 3006 | ], 3007 | [ 3008 | [ 3009 | "string", 3010 | "string", 3011 | ], 3012 | [ 3013 | "string", 3014 | "string", 3015 | ], 3016 | [ 3017 | "string", 3018 | "string", 3019 | ], 3020 | [ 3021 | "string", 3022 | "string", 3023 | ], 3024 | [ 3025 | "string", 3026 | "string", 3027 | ], 3028 | ], 3029 | ], 3030 | ] 3031 | `; 3032 | 3033 | exports[`makeMatrix > string initial values > %p [ 2, 4, 2, 4, 2 ] 1`] = ` 3034 | [ 3035 | [ 3036 | [ 3037 | [ 3038 | [ 3039 | "string", 3040 | "string", 3041 | ], 3042 | [ 3043 | "string", 3044 | "string", 3045 | ], 3046 | [ 3047 | "string", 3048 | "string", 3049 | ], 3050 | [ 3051 | "string", 3052 | "string", 3053 | ], 3054 | ], 3055 | [ 3056 | [ 3057 | "string", 3058 | "string", 3059 | ], 3060 | [ 3061 | "string", 3062 | "string", 3063 | ], 3064 | [ 3065 | "string", 3066 | "string", 3067 | ], 3068 | [ 3069 | "string", 3070 | "string", 3071 | ], 3072 | ], 3073 | ], 3074 | [ 3075 | [ 3076 | [ 3077 | "string", 3078 | "string", 3079 | ], 3080 | [ 3081 | "string", 3082 | "string", 3083 | ], 3084 | [ 3085 | "string", 3086 | "string", 3087 | ], 3088 | [ 3089 | "string", 3090 | "string", 3091 | ], 3092 | ], 3093 | [ 3094 | [ 3095 | "string", 3096 | "string", 3097 | ], 3098 | [ 3099 | "string", 3100 | "string", 3101 | ], 3102 | [ 3103 | "string", 3104 | "string", 3105 | ], 3106 | [ 3107 | "string", 3108 | "string", 3109 | ], 3110 | ], 3111 | ], 3112 | [ 3113 | [ 3114 | [ 3115 | "string", 3116 | "string", 3117 | ], 3118 | [ 3119 | "string", 3120 | "string", 3121 | ], 3122 | [ 3123 | "string", 3124 | "string", 3125 | ], 3126 | [ 3127 | "string", 3128 | "string", 3129 | ], 3130 | ], 3131 | [ 3132 | [ 3133 | "string", 3134 | "string", 3135 | ], 3136 | [ 3137 | "string", 3138 | "string", 3139 | ], 3140 | [ 3141 | "string", 3142 | "string", 3143 | ], 3144 | [ 3145 | "string", 3146 | "string", 3147 | ], 3148 | ], 3149 | ], 3150 | [ 3151 | [ 3152 | [ 3153 | "string", 3154 | "string", 3155 | ], 3156 | [ 3157 | "string", 3158 | "string", 3159 | ], 3160 | [ 3161 | "string", 3162 | "string", 3163 | ], 3164 | [ 3165 | "string", 3166 | "string", 3167 | ], 3168 | ], 3169 | [ 3170 | [ 3171 | "string", 3172 | "string", 3173 | ], 3174 | [ 3175 | "string", 3176 | "string", 3177 | ], 3178 | [ 3179 | "string", 3180 | "string", 3181 | ], 3182 | [ 3183 | "string", 3184 | "string", 3185 | ], 3186 | ], 3187 | ], 3188 | ], 3189 | [ 3190 | [ 3191 | [ 3192 | [ 3193 | "string", 3194 | "string", 3195 | ], 3196 | [ 3197 | "string", 3198 | "string", 3199 | ], 3200 | [ 3201 | "string", 3202 | "string", 3203 | ], 3204 | [ 3205 | "string", 3206 | "string", 3207 | ], 3208 | ], 3209 | [ 3210 | [ 3211 | "string", 3212 | "string", 3213 | ], 3214 | [ 3215 | "string", 3216 | "string", 3217 | ], 3218 | [ 3219 | "string", 3220 | "string", 3221 | ], 3222 | [ 3223 | "string", 3224 | "string", 3225 | ], 3226 | ], 3227 | ], 3228 | [ 3229 | [ 3230 | [ 3231 | "string", 3232 | "string", 3233 | ], 3234 | [ 3235 | "string", 3236 | "string", 3237 | ], 3238 | [ 3239 | "string", 3240 | "string", 3241 | ], 3242 | [ 3243 | "string", 3244 | "string", 3245 | ], 3246 | ], 3247 | [ 3248 | [ 3249 | "string", 3250 | "string", 3251 | ], 3252 | [ 3253 | "string", 3254 | "string", 3255 | ], 3256 | [ 3257 | "string", 3258 | "string", 3259 | ], 3260 | [ 3261 | "string", 3262 | "string", 3263 | ], 3264 | ], 3265 | ], 3266 | [ 3267 | [ 3268 | [ 3269 | "string", 3270 | "string", 3271 | ], 3272 | [ 3273 | "string", 3274 | "string", 3275 | ], 3276 | [ 3277 | "string", 3278 | "string", 3279 | ], 3280 | [ 3281 | "string", 3282 | "string", 3283 | ], 3284 | ], 3285 | [ 3286 | [ 3287 | "string", 3288 | "string", 3289 | ], 3290 | [ 3291 | "string", 3292 | "string", 3293 | ], 3294 | [ 3295 | "string", 3296 | "string", 3297 | ], 3298 | [ 3299 | "string", 3300 | "string", 3301 | ], 3302 | ], 3303 | ], 3304 | [ 3305 | [ 3306 | [ 3307 | "string", 3308 | "string", 3309 | ], 3310 | [ 3311 | "string", 3312 | "string", 3313 | ], 3314 | [ 3315 | "string", 3316 | "string", 3317 | ], 3318 | [ 3319 | "string", 3320 | "string", 3321 | ], 3322 | ], 3323 | [ 3324 | [ 3325 | "string", 3326 | "string", 3327 | ], 3328 | [ 3329 | "string", 3330 | "string", 3331 | ], 3332 | [ 3333 | "string", 3334 | "string", 3335 | ], 3336 | [ 3337 | "string", 3338 | "string", 3339 | ], 3340 | ], 3341 | ], 3342 | ], 3343 | ] 3344 | `; 3345 | 3346 | exports[`makeMatrix > string initial values > %p [ 3, 2, 3 ] 1`] = ` 3347 | [ 3348 | [ 3349 | [ 3350 | "string", 3351 | "string", 3352 | "string", 3353 | ], 3354 | [ 3355 | "string", 3356 | "string", 3357 | "string", 3358 | ], 3359 | ], 3360 | [ 3361 | [ 3362 | "string", 3363 | "string", 3364 | "string", 3365 | ], 3366 | [ 3367 | "string", 3368 | "string", 3369 | "string", 3370 | ], 3371 | ], 3372 | [ 3373 | [ 3374 | "string", 3375 | "string", 3376 | "string", 3377 | ], 3378 | [ 3379 | "string", 3380 | "string", 3381 | "string", 3382 | ], 3383 | ], 3384 | ] 3385 | `; 3386 | 3387 | exports[`makeMatrix > string initial values > %p [ 6 ] 1`] = ` 3388 | [ 3389 | "string", 3390 | "string", 3391 | "string", 3392 | "string", 3393 | "string", 3394 | "string", 3395 | ] 3396 | `; 3397 | -------------------------------------------------------------------------------- /src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from "vitest"; 2 | 3 | import { makeMatrix } from "../index"; 4 | 5 | const testCases = [[6], [1, 1], [3, 2, 3], [1, 4, 5, 2], [2, 4, 2, 4, 2]]; 6 | 7 | /** So cases can be used as both test titles and test values during a `test.each` run */ 8 | const iterativeTestCases = testCases.map(c => [c, c]); 9 | 10 | describe("makeMatrix", () => { 11 | describe("no initial values", () => { 12 | test.each(iterativeTestCases)("%p", dimensions => { 13 | expect(makeMatrix(dimensions)).toMatchSnapshot(); 14 | }); 15 | }); 16 | 17 | describe("string initial values", () => { 18 | test.each(iterativeTestCases)("%p", dimensions => { 19 | expect(makeMatrix(dimensions, "string")).toMatchSnapshot(); 20 | }); 21 | }); 22 | 23 | describe("number initial values", () => { 24 | test.each(iterativeTestCases)("%p", dimensions => { 25 | expect(makeMatrix(dimensions, 0)).toMatchSnapshot(); 26 | }); 27 | }); 28 | 29 | describe("callback initial values — math", () => { 30 | test.each(iterativeTestCases)("%p", dimensions => { 31 | expect(makeMatrix(dimensions, () => 10 - 2)).toMatchSnapshot(); 32 | }); 33 | }); 34 | 35 | describe("self aware callback initial values", () => { 36 | test.each(iterativeTestCases)("%p", dimensions => { 37 | expect(makeMatrix(dimensions, vector => vector)).toMatchSnapshot(); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /src/__tests__/types.test.ts: -------------------------------------------------------------------------------- 1 | import { assertType, describe, test } from "vitest"; 2 | 3 | import { makeMatrix } from "../index"; 4 | 5 | describe("assert types", () => { 6 | test("resolves to the correct type", () => { 7 | assertType(makeMatrix([1, 1, 1, 1], "hello")); 8 | assertType(makeMatrix([4, 5], ([a]) => a)); 9 | assertType(makeMatrix([4], v => v[0].toString())); 10 | assertType(makeMatrix([] as number[])); 11 | 12 | assertType<(0 | 1)[]>( 13 | makeMatrix([1], () => (Math.random() > 0.5 ? (0 as const) : (1 as const))) 14 | ); 15 | 16 | assertType<{ x: number; y: number; z: number }[][][]>( 17 | makeMatrix([4, 5, 6], ([x, y, z]) => ({ x, y, z })) 18 | ); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { Matrix, Vector } from "./types.js"; 2 | 3 | /** 4 | * Creates a matrix (multi-dimensional array) with your desired dimensions and values. 5 | * 6 | * @param dimensions The desired dimensions of the matrix. 7 | * @param initialValues The initial value for each point in the matrix. Can also take a callback function—with an argument that resolves to the current point's vector—to fill the matrix dynamically. Defaults to `null`. 8 | * 9 | * @example 10 | * const threeXThreeXTwoArray = makeMatrix([3, 3, 2]); // A 3x3x2 array 11 | * const twoDNumberArray = makeMatrix([3, 5], 0); // A 3x5 array containing 0 12 | * const twoDRandomNumberArray = makeMatrix([1, 4], () => Math.random()); // A 1x4 array containing random numbers 13 | * const twoDVectorArray = makeMatrix([3, 3], vector => vector.join()); // A 3x3 array containing each point's co-ordinate as a string 14 | */ 15 | const makeMatrix = ( 16 | dimensions: Vector, 17 | initialValues: T | ((currentPosition: Vector) => T) | null = null 18 | ): Matrix => { 19 | const initialPosition = Array(dimensions.length).fill(0) as Vector; 20 | return _makeMatrix(dimensions, initialValues, initialPosition); 21 | }; 22 | 23 | /** 24 | * Recursively creates a matrix (depth first), and keeps track of the current position's vector. 25 | */ 26 | function _makeMatrix( 27 | dimensions: Vector, 28 | initialValues: T | ((currentPosition: Vector) => T) | null, 29 | currentPosition: Vector 30 | ): Matrix { 31 | const [currentDimensionLength, ...remainingDimensions] = dimensions; 32 | const currentDimension = currentPosition.length - remainingDimensions.length - 1; 33 | 34 | return [...Array(currentDimensionLength)].map((_, i) => { 35 | currentPosition[currentDimension] = i; 36 | return remainingDimensions.length > 0 37 | ? _makeMatrix(remainingDimensions as Vector, initialValues, currentPosition) 38 | : initialValues instanceof Function 39 | ? initialValues(currentPosition.slice() as Vector) 40 | : initialValues; 41 | }) as Matrix; 42 | } 43 | 44 | export { makeMatrix, type Matrix }; 45 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A typed multidimensional array returned by `makeMatrix`. 3 | */ 4 | export type Matrix = Brand<_Matrix>; 5 | 6 | /** 7 | * Recursively constructs a `Matrix` type and keeps track of the number of recursions. 8 | * 9 | * @remarks 10 | * When a `_Matrix` is created without knowing it's exact size or number of dimensions, such 11 | * as when creating one dynamically, it's impossible recursively construct a type for it. 12 | * Instead, we short circuit the type to resolve to `unknown[]`. This ensures an array of at 13 | * least one dimension is returned, but is unable to provide any more safety than that. 14 | */ 15 | type _Matrix< 16 | D extends number, 17 | T = unknown, 18 | RecursionCountArray extends number[] = [], 19 | > = number extends D 20 | ? unknown[] 21 | : D extends RecursionCountArray["length"] 22 | ? T 23 | : _Matrix; 24 | 25 | /** 26 | * An array of numbers with defined length, corresponding to points in a `Matrix`. 27 | * 28 | * @see {@link https://github.com/microsoft/TypeScript/issues/26223} for discussion and other 29 | * implementations, though this seems to be the only one that works properly for `makeMatrix`'s use case. 30 | * 31 | * @remarks 32 | * When a `Vector` is created without knowing the exact number of dimensions, such as when 33 | * creating one dynamically, we short circuit the type to resolve to `number[]` so that 34 | * `makeMatrix` can accept a dynamically created `dimensions` parameter. 35 | */ 36 | export type Vector = Brand< 37 | number extends D ? number[] : [number, ...number[]] & { readonly length: D } 38 | >; 39 | 40 | /** 41 | * Stops intellisense from expanding types and exposing their more complicated internals to users. 42 | * 43 | * @see {@link https://github.com/microsoft/TypeScript/issues/31940} for discussion 44 | */ 45 | type Brand = D & {}; 46 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | // Taken from @total-typescript/tsconfig/bundler/no-dom/library, which doesn't work well with ts-node 4 | "compilerOptions": { 5 | /* Base Options: */ 6 | "esModuleInterop": true, 7 | "skipLibCheck": true, 8 | "target": "es2022", 9 | "allowJs": true, 10 | "resolveJsonModule": true, 11 | "moduleDetection": "force", 12 | "isolatedModules": true, 13 | "verbatimModuleSyntax": true, 14 | /* Strictness */ 15 | "strict": true, 16 | "noUncheckedIndexedAccess": true, 17 | "noImplicitOverride": true, 18 | /* If NOT transpiling with TypeScript: */ 19 | "module": "preserve", 20 | "noEmit": true, 21 | /* If your code doesn't run in the DOM: */ 22 | "lib": ["es2022"] 23 | }, 24 | "include": ["src"], 25 | "exclude": ["node_modules", "**/__tests__/*"] 26 | } 27 | --------------------------------------------------------------------------------