Compare commits

..

4 Commits

Author SHA1 Message Date
8c06c8f36e feat: Add generic operation square and numeric unequal (#4)
Co-authored-by: Jos de Jong <wjosdejong@gmail.com>
Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Reviewed-on: #4
2022-12-22 16:12:36 +00:00
fbec410c42 feat: Implement complex arithmetic through sqrt
Together with any auxiliary functions needed for that goal. Also
  strives to ensure the same functions are being defined for
  number and for `Complex<T>`.
2022-12-22 00:14:58 -05:00
d55776655f refactor: Convenience type operator for specifying concrete signatures 2022-12-21 11:41:25 -05:00
1eb73be2fa refactor: entirely new scheme for specifying return types 2022-12-21 00:18:42 -05:00
30 changed files with 523 additions and 1652 deletions

5
.gitignore vendored
View File

@ -2,7 +2,7 @@
*~ *~
# Typescript # Typescript
# emitted code # emitted code
build obj
# ---> Node # ---> Node
# Logs # Logs
@ -129,9 +129,6 @@ dist
# Stores VSCode versions used for testing VSCode extensions # Stores VSCode versions used for testing VSCode extensions
.vscode-test .vscode-test
# Webstorm
.idea
# yarn v2 # yarn v2
.yarn/cache .yarn/cache
.yarn/unplugged .yarn/unplugged

1
.npmrc
View File

@ -1 +0,0 @@
shell-emulator=true

View File

@ -1,14 +1,3 @@
# typocomath # typocomath
A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state. A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state.
Convenience scripts:
* `pnpm build` -- compile the package
* `pnpm exec` -- run the compiled code produced by `pnpm build`
* `pnpm go` -- both of the above in sequence.
Important installation note:
after `pnpm install`, you must execute `npx ts-patch install` to activate the ts-macros compiler plugin.

View File

@ -1 +0,0 @@
{"type": "module"}

View File

@ -1,16 +1,11 @@
{ {
name: 'typocomath', name: 'typocomath',
version: '0.0.2', version: '0.0.1',
description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept', description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept',
main: 'index.ts', main: 'index.ts',
scripts: { scripts: {
test: 'echo "Error: no test specified" && exit 1', test: 'echo "Error: no test specified" && exit 1',
build: 'mkdirp build && cpy etc/package.json build --flat && tsc',
start: 'node build',
go: 'pnpm clean && pnpm build && pnpm start',
clean: 'del-cli build',
}, },
packageManager: 'pnpm',
keywords: [ keywords: [
'math', 'math',
'algebra', 'algebra',
@ -23,13 +18,6 @@
url: 'https://code.studioinfinity.org/glen/typocomath.git', url: 'https://code.studioinfinity.org/glen/typocomath.git',
}, },
devDependencies: { devDependencies: {
'@types/node': '20.8.4', typescript: '^4.9.3',
'cpy-cli': '5.0.0',
'del-cli': '5.1.0',
mkdirp: '3.0.1',
'source-map': '0.7.4',
'ts-macros': '2.6.0',
'ts-patch': '3.0.2',
typescript: '5.1.6',
}, },
} }

View File

@ -1,920 +1,15 @@
lockfileVersion: '6.0' lockfileVersion: 5.4
settings: specifiers:
autoInstallPeers: true typescript: ^4.9.3
excludeLinksFromLockfile: false
devDependencies: devDependencies:
'@types/node': typescript: 4.9.3
specifier: 20.8.4
version: 20.8.4
cpy-cli:
specifier: 5.0.0
version: 5.0.0
del-cli:
specifier: 5.1.0
version: 5.1.0
mkdirp:
specifier: 3.0.1
version: 3.0.1
source-map:
specifier: 0.7.4
version: 0.7.4
ts-macros:
specifier: 2.6.0
version: 2.6.0(typescript@5.1.6)
ts-patch:
specifier: 3.0.2
version: 3.0.2
typescript:
specifier: 5.1.6
version: 5.1.6
packages: packages:
/@babel/code-frame@7.22.13: /typescript/4.9.3:
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==}
engines: {node: '>=6.9.0'} engines: {node: '>=4.2.0'}
dependencies:
'@babel/highlight': 7.22.20
chalk: 2.4.2
dev: true
/@babel/helper-validator-identifier@7.22.20:
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/highlight@7.22.20:
resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.22.20
chalk: 2.4.2
js-tokens: 4.0.0
dev: true
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.stat': 2.0.5
run-parallel: 1.2.0
dev: true
/@nodelib/fs.stat@2.0.5:
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
engines: {node: '>= 8'}
dev: true
/@nodelib/fs.walk@1.2.8:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.15.0
dev: true
/@types/minimist@1.2.2:
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
dev: true
/@types/node@20.8.4:
resolution: {integrity: sha512-ZVPnqU58giiCjSxjVUESDtdPk4QR5WQhhINbc9UBrKLU68MX5BF6kbQzTrkwbolyr0X8ChBpXfavr5mZFKZQ5A==}
dependencies:
undici-types: 5.25.3
dev: true
/@types/normalize-package-data@2.4.1:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
dev: true
/aggregate-error@4.0.1:
resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==}
engines: {node: '>=12'}
dependencies:
clean-stack: 4.2.0
indent-string: 5.0.0
dev: true
/ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
dev: true
/ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
dependencies:
color-convert: 1.9.3
dev: true
/ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
dev: true
/arrify@1.0.1:
resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
engines: {node: '>=0.10.0'}
dev: true
/arrify@3.0.0:
resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==}
engines: {node: '>=12'}
dev: true
/balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: true
/brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
dev: true
/braces@3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
dependencies:
fill-range: 7.0.1
dev: true
/camelcase-keys@7.0.2:
resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==}
engines: {node: '>=12'}
dependencies:
camelcase: 6.3.0
map-obj: 4.3.0
quick-lru: 5.1.1
type-fest: 1.4.0
dev: true
/camelcase@6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
dev: true
/chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
dependencies:
ansi-styles: 3.2.1
escape-string-regexp: 1.0.5
supports-color: 5.5.0
dev: true
/chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
dev: true
/clean-stack@4.2.0:
resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==}
engines: {node: '>=12'}
dependencies:
escape-string-regexp: 5.0.0
dev: true
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
color-name: 1.1.3
dev: true
/color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
dev: true
/color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: true
/color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
dev: true
/concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: true
/cp-file@10.0.0:
resolution: {integrity: sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg==}
engines: {node: '>=14.16'}
dependencies:
graceful-fs: 4.2.11
nested-error-stacks: 2.1.1
p-event: 5.0.1
dev: true
/cpy-cli@5.0.0:
resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==}
engines: {node: '>=16'}
hasBin: true
dependencies:
cpy: 10.1.0
meow: 12.1.1
dev: true
/cpy@10.1.0:
resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==}
engines: {node: '>=16'}
dependencies:
arrify: 3.0.0
cp-file: 10.0.0
globby: 13.2.2
junk: 4.0.1
micromatch: 4.0.5
nested-error-stacks: 2.1.1
p-filter: 3.0.0
p-map: 6.0.0
dev: true
/decamelize-keys@1.1.1:
resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
engines: {node: '>=0.10.0'}
dependencies:
decamelize: 1.2.0
map-obj: 1.0.1
dev: true
/decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
dev: true
/decamelize@5.0.1:
resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==}
engines: {node: '>=10'}
dev: true
/del-cli@5.1.0:
resolution: {integrity: sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==}
engines: {node: '>=14.16'}
hasBin: true
dependencies:
del: 7.1.0
meow: 10.1.5
dev: true
/del@7.1.0:
resolution: {integrity: sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==}
engines: {node: '>=14.16'}
dependencies:
globby: 13.2.2
graceful-fs: 4.2.11
is-glob: 4.0.3
is-path-cwd: 3.0.0
is-path-inside: 4.0.0
p-map: 5.5.0
rimraf: 3.0.2
slash: 4.0.0
dev: true
/dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
dependencies:
path-type: 4.0.0
dev: true
/error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
dependencies:
is-arrayish: 0.2.1
dev: true
/escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
dev: true
/escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
dev: true
/fast-glob@3.3.1:
resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
engines: {node: '>=8.6.0'}
dependencies:
'@nodelib/fs.stat': 2.0.5
'@nodelib/fs.walk': 1.2.8
glob-parent: 5.1.2
merge2: 1.4.1
micromatch: 4.0.5
dev: true
/fastq@1.15.0:
resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
dependencies:
reusify: 1.0.4
dev: true
/fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
dependencies:
to-regex-range: 5.0.1
dev: true
/find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
dependencies:
locate-path: 6.0.0
path-exists: 4.0.0
dev: true
/fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
/function-bind@1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
/glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
dependencies:
is-glob: 4.0.3
dev: true
/glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
dev: true
/global-prefix@3.0.0:
resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==}
engines: {node: '>=6'}
dependencies:
ini: 1.3.8
kind-of: 6.0.3
which: 1.3.1
dev: true
/globby@13.2.2:
resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
dir-glob: 3.0.1
fast-glob: 3.3.1
ignore: 5.2.4
merge2: 1.4.1
slash: 4.0.0
dev: true
/graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
dev: true
/hard-rejection@2.1.0:
resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
engines: {node: '>=6'}
dev: true
/has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
dev: true
/has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
dev: true
/has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
dependencies:
function-bind: 1.1.1
dev: true
/hosted-git-info@4.1.0:
resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
engines: {node: '>=10'}
dependencies:
lru-cache: 6.0.0
dev: true
/ignore@5.2.4:
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
engines: {node: '>= 4'}
dev: true
/indent-string@5.0.0:
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
engines: {node: '>=12'}
dev: true
/inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
once: 1.4.0
wrappy: 1.0.2
dev: true
/inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
/ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
dev: true
/is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
dev: true
/is-core-module@2.13.0:
resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
dependencies:
has: 1.0.3
dev: true
/is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
dev: true
/is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
dependencies:
is-extglob: 2.1.1
dev: true
/is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
dev: true
/is-path-cwd@3.0.0:
resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: true
/is-path-inside@4.0.0:
resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==}
engines: {node: '>=12'}
dev: true
/is-plain-obj@1.1.0:
resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
engines: {node: '>=0.10.0'}
dev: true
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: true
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
/json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
dev: true
/junk@4.0.1:
resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==}
engines: {node: '>=12.20'}
dev: true
/kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
dev: true
/lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true
/locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
dependencies:
p-locate: 5.0.0
dev: true
/lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
dependencies:
yallist: 4.0.0
dev: true
/map-obj@1.0.1:
resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}
engines: {node: '>=0.10.0'}
dev: true
/map-obj@4.3.0:
resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
engines: {node: '>=8'}
dev: true
/meow@10.1.5:
resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
'@types/minimist': 1.2.2
camelcase-keys: 7.0.2
decamelize: 5.0.1
decamelize-keys: 1.1.1
hard-rejection: 2.1.0
minimist-options: 4.1.0
normalize-package-data: 3.0.3
read-pkg-up: 8.0.0
redent: 4.0.0
trim-newlines: 4.1.1
type-fest: 1.4.0
yargs-parser: 20.2.9
dev: true
/meow@12.1.1:
resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==}
engines: {node: '>=16.10'}
dev: true
/merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
dev: true
/micromatch@4.0.5:
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
engines: {node: '>=8.6'}
dependencies:
braces: 3.0.2
picomatch: 2.3.1
dev: true
/min-indent@1.0.1:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
dev: true
/minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies:
brace-expansion: 1.1.11
dev: true
/minimist-options@4.1.0:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
engines: {node: '>= 6'}
dependencies:
arrify: 1.0.1
is-plain-obj: 1.1.0
kind-of: 6.0.3
dev: true
/minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
dev: true
/mkdirp@3.0.1:
resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
engines: {node: '>=10'}
hasBin: true hasBin: true
dev: true dev: true
/nested-error-stacks@2.1.1:
resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==}
dev: true
/normalize-package-data@3.0.3:
resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==}
engines: {node: '>=10'}
dependencies:
hosted-git-info: 4.1.0
is-core-module: 2.13.0
semver: 7.5.4
validate-npm-package-license: 3.0.4
dev: true
/once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies:
wrappy: 1.0.2
dev: true
/p-event@5.0.1:
resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
p-timeout: 5.1.0
dev: true
/p-filter@3.0.0:
resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
p-map: 5.5.0
dev: true
/p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
dependencies:
yocto-queue: 0.1.0
dev: true
/p-locate@5.0.0:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
dependencies:
p-limit: 3.1.0
dev: true
/p-map@5.5.0:
resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==}
engines: {node: '>=12'}
dependencies:
aggregate-error: 4.0.1
dev: true
/p-map@6.0.0:
resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==}
engines: {node: '>=16'}
dev: true
/p-timeout@5.1.0:
resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==}
engines: {node: '>=12'}
dev: true
/parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
dependencies:
'@babel/code-frame': 7.22.13
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
dev: true
/path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
dev: true
/path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
dev: true
/path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
dev: true
/picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
dev: true
/queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true
/quick-lru@5.1.1:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
dev: true
/read-pkg-up@8.0.0:
resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==}
engines: {node: '>=12'}
dependencies:
find-up: 5.0.0
read-pkg: 6.0.0
type-fest: 1.4.0
dev: true
/read-pkg@6.0.0:
resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==}
engines: {node: '>=12'}
dependencies:
'@types/normalize-package-data': 2.4.1
normalize-package-data: 3.0.3
parse-json: 5.2.0
type-fest: 1.4.0
dev: true
/redent@4.0.0:
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
engines: {node: '>=12'}
dependencies:
indent-string: 5.0.0
strip-indent: 4.0.0
dev: true
/resolve@1.22.4:
resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==}
hasBin: true
dependencies:
is-core-module: 2.13.0
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
dev: true
/reusify@1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
dev: true
/rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
hasBin: true
dependencies:
glob: 7.2.3
dev: true
/run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies:
queue-microtask: 1.2.3
dev: true
/semver@7.5.4:
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
engines: {node: '>=10'}
hasBin: true
dependencies:
lru-cache: 6.0.0
dev: true
/slash@4.0.0:
resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==}
engines: {node: '>=12'}
dev: true
/source-map@0.7.4:
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
engines: {node: '>= 8'}
dev: true
/spdx-correct@3.2.0:
resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
dependencies:
spdx-expression-parse: 3.0.1
spdx-license-ids: 3.0.15
dev: true
/spdx-exceptions@2.3.0:
resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
dev: true
/spdx-expression-parse@3.0.1:
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
dependencies:
spdx-exceptions: 2.3.0
spdx-license-ids: 3.0.15
dev: true
/spdx-license-ids@3.0.15:
resolution: {integrity: sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==}
dev: true
/strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
dependencies:
ansi-regex: 5.0.1
dev: true
/strip-indent@4.0.0:
resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==}
engines: {node: '>=12'}
dependencies:
min-indent: 1.0.1
dev: true
/supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
dependencies:
has-flag: 3.0.0
dev: true
/supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
dev: true
/supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
dev: true
/to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
dependencies:
is-number: 7.0.0
dev: true
/trim-newlines@4.1.1:
resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==}
engines: {node: '>=12'}
dev: true
/ts-macros@2.6.0(typescript@5.1.6):
resolution: {integrity: sha512-X7c4rHPTpBYY+MJUkIDIQMbTPAcv1y1sylrnDMsTvcbImleT4Wlheg3wNbORwnX8Zvq2ldZnttNXcZ1a0VE2Kg==}
hasBin: true
peerDependencies:
typescript: 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x
dependencies:
typescript: 5.1.6
yargs-parser: 21.1.1
dev: true
/ts-patch@3.0.2:
resolution: {integrity: sha512-iTg8euqiNsNM1VDfOsVIsP0bM4kAVXU38n7TGQSkky7YQX/syh6sDPIRkvSS0HjT8ZOr0pq1h+5Le6jdB3hiJQ==}
hasBin: true
dependencies:
chalk: 4.1.2
global-prefix: 3.0.0
minimist: 1.2.8
resolve: 1.22.4
semver: 7.5.4
strip-ansi: 6.0.1
dev: true
/type-fest@1.4.0:
resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
engines: {node: '>=10'}
dev: true
/typescript@5.1.6:
resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==}
engines: {node: '>=14.17'}
hasBin: true
dev: true
/undici-types@5.25.3:
resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==}
dev: true
/validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
dev: true
/which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
dependencies:
isexe: 2.0.0
dev: true
/wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: true
/yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
dev: true
/yargs-parser@20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
dev: true
/yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
dev: true
/yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
dev: true

View File

@ -1,6 +1,10 @@
import {ForType} from '../core/Dispatcher.js'
import {ComplexReturn} from './type.js'
import * as Complex from './native.js' import * as Complex from './native.js'
import * as complex from './arithmetic.js'
export { complex }
export {Complex} export {Complex}
declare module "../core/Dispatcher" {
interface ReturnTypes<Params>
extends ForType<'Complex', ComplexReturn<Params>> {}
}

View File

@ -1,104 +1,139 @@
import {Complex} from './type.js' import {Complex, UnderlyingReal, complex_binary} from './type.js'
import type { import {
Dependencies, Signature, Returns, RealType, AliasOf BBinary, Dependency, ConservativeUnary, ConservativeBinary, ImpType
} from '../interfaces/type.js' } from '../core/Dispatcher.js'
import {$reflect} from '../interfaces/type.js'
declare module "../interfaces/type" { declare module "./type" {
interface Signatures<T> { interface ComplexReturn<Params> {
addReal: AliasOf<'add', (a: T, b: RealType<T>) => T> add: ConservativeBinary<Params, Complex<any>>
divideReal: AliasOf<'divide', (a: T, b: RealType<T>) => T> addReal: Params extends [infer Z, infer R]
? [R] extends [UnderlyingReal<Z>] ? Z : never
: never
unaryMinus: ConservativeUnary<Params, Complex<any>>
conj: ConservativeUnary<Params, Complex<any>>
subtract: ConservativeBinary<Params, Complex<any>>
multiply: ConservativeBinary<Params, Complex<any>>
absquare: Params extends [infer Z]
? Z extends Complex<any> ? UnderlyingReal<Z> : never
: never
reciprocal: ConservativeUnary<Params, Complex<any>>
divide: ConservativeBinary<Params, Complex<any>>
divideByReal: Params extends [infer Z, infer R]
? [R] extends [UnderlyingReal<Z>] ? Z : never
: never
// square root that remains the same type
conservativeSqrt: ConservativeUnary<Params, Complex<any>>
// Same as conservativeSqrt for complex numbers:
sqrt: ConservativeUnary<Params, Complex<any>>
// complex square root of the real type of a complex:
complexSqrt: Params extends [infer T] ? Complex<T> : never
} }
} }
export const add = export const add =
<T>(dep: Dependencies<'add' | 'complex', T>): Signature<'add', Complex<T>> => <T>(dep: Dependency<'add', [T,T]>):
(w, z) => dep.complex(dep.add(w.re, z.re), dep.add(w.im, z.im)) ImpType<'add', [Complex<T>, Complex<T>]> =>
(w, z) => complex_binary(dep.add(w.re, z.re), dep.add(w.im, z.im))
export const addReal = export const addReal =
<T>(dep: Dependencies<'addReal' | 'complex', T>): <T>(dep: Dependency<'addReal', [T, UnderlyingReal<T>]>):
Signature<'addReal', Complex<T>> => ImpType<'addReal', [Complex<T>, UnderlyingReal<T>]> =>
(z, r) => dep.complex(dep.addReal(z.re, r), z.im) (z, r) => complex_binary(dep.addReal(z.re, r), z.im)
export const unaryMinus = export const unaryMinus =
<T>(dep: Dependencies<'unaryMinus' | 'complex', T>): <T>(dep: Dependency<'unaryMinus', [T]>):
Signature<'unaryMinus', Complex<T>> => ImpType<'unaryMinus', [Complex<T>]> =>
z => dep.complex(dep.unaryMinus(z.re), dep.unaryMinus(z.im)) z => complex_binary(dep.unaryMinus(z.re), dep.unaryMinus(z.im))
export const conj = export const conj =
<T>(dep: Dependencies<'unaryMinus' | 'conj' | 'complex', T>): <T>(dep: Dependency<'unaryMinus'|'conj', [T]>):
Signature<'conj', Complex<T>> => ImpType<'conj', [Complex<T>]> =>
z => dep.complex(dep.conj(z.re), dep.unaryMinus(z.im)) z => complex_binary(dep.conj(z.re), dep.unaryMinus(z.im))
export const subtract = export const subtract =
<T>(dep: Dependencies<'subtract' | 'complex', T>): <T>(dep: Dependency<'subtract', [T,T]>):
Signature<'subtract', Complex<T>> => ImpType<'subtract', [Complex<T>, Complex<T>]> =>
(w, z) => dep.complex(dep.subtract(w.re, z.re), dep.subtract(w.im, z.im)) (w, z) => complex_binary(dep.subtract(w.re, z.re), dep.subtract(w.im, z.im))
export const multiply = export const multiply =
<T>(dep: Dependencies< <T>(dep: Dependency<'add', [T,T]>
'add' | 'subtract' | 'multiply' | 'conj' | 'complex', T>): & Dependency<'subtract', [T,T]>
Signature<'multiply', Complex<T>> => & Dependency<'multiply', [T,T]>
& Dependency<'conj', [T]>):
ImpType<'multiply', [Complex<T>, Complex<T>]> =>
(w, z) => { (w, z) => {
const mult = dep.multiply const mult = dep.multiply
const realpart = dep.subtract( const realpart = dep.subtract(
mult( w.re, z.re), mult(dep.conj(w.im), z.im)) mult( w.re, z.re), mult(dep.conj(w.im), z.im))
const imagpart = dep.add( const imagpart = dep.add(
mult(dep.conj(w.re), z.im), mult( w.im, z.re)) mult(dep.conj(w.re), z.im), mult( w.im, z.re))
return dep.complex(realpart, imagpart) return complex_binary(realpart, imagpart)
} }
export const absquare = export const absquare =
<T>(dep: Dependencies<'absquare', T> <T>(dep: Dependency<'absquare', [T]>
& Dependencies<'add', Returns<'absquare', T>>): & Dependency<'add', BBinary<UnderlyingReal<T>>>):
Signature<'absquare', Complex<T>> => ImpType<'absquare', [Complex<T>]> =>
z => dep.add(dep.absquare(z.re), dep.absquare(z.im)) z => dep.add(dep.absquare(z.re), dep.absquare(z.im))
export const divideReal = export const divideByReal =
<T>(dep: Dependencies<'divideReal' | 'complex', T>): <T>(dep: Dependency<'divideByReal', [T, UnderlyingReal<T>]>):
Signature<'divideReal', Complex<T>> => ImpType<'divideByReal', [Complex<T>, UnderlyingReal<T>]> =>
(z, r) => dep.complex(dep.divideReal(z.re, r), dep.divideReal(z.im, r)) (z, r) => complex_binary(
dep.divideByReal(z.re, r), dep.divideByReal(z.im, r))
export const reciprocal = export const reciprocal =
<T>(dep: Dependencies<'conj' | 'absquare' | 'divideReal', Complex<T>>): <T>(dep: Dependency<'conj', [Complex<T>]>
Signature<'reciprocal', Complex<T>> => & Dependency<'absquare', [Complex<T>]>
z => dep.divideReal(dep.conj(z), dep.absquare(z)) & Dependency<'divideByReal', [Complex<T>, UnderlyingReal<T>]>):
ImpType<'reciprocal', [Complex<T>]> =>
z => dep.divideByReal(dep.conj(z), dep.absquare(z))
export const divide = export const divide =
<T>(dep: Dependencies<'multiply' | 'reciprocal', Complex<T>>): <T>(dep: Dependency<'multiply', [Complex<T>, Complex<T>]>
Signature<'divide', Complex<T>> => & Dependency<'reciprocal', [Complex<T>]>):
ImpType<'divide', [Complex<T>, Complex<T>]> =>
(w, z) => dep.multiply(w, dep.reciprocal(z)) (w, z) => dep.multiply(w, dep.reciprocal(z))
// The dependencies are slightly tricky here, because there are three types export const complexSqrt =
// involved: Complex<T>, T, and RealType<T>, all of which might be different, <T>(dep: Dependency<'conservativeSqrt', [T]>
// and we have to get it straight which operations we need on each type, and & Dependency<'isSquare', [T]>
// in fact, we need `addReal` on both T and Complex<T>, hence the dependency & Dependency<'complex', [T]>
// with a custom name, not generated via Dependencies<...> & Dependency<'unaryMinus', [T]>
export const sqrt = & Dependency<'zero', [T]>
<T>(dep: Dependencies<'equal' | 'conservativeSqrt' | 'unaryMinus', RealType<T>> & Dependency<'nan', [Complex<T>]>): ImpType<'complexSqrt', [T]> =>
& Dependencies<'zero' | 'complex', T> r => {
& Dependencies<'absquare' | 're' | 'divideReal', Complex<T>> if (dep.isSquare(r)) return dep.complex(dep.conservativeSqrt(r))
& { const negative = dep.unaryMinus(r)
addTR: Signature<'addReal', T>, if (dep.isSquare(negative)) {
addRR: Signature<'add', RealType<T>>, return complex_binary(
addCR: Signature<'addReal', Complex<T>> dep.zero(r), dep.conservativeSqrt(negative))
}): Signature<'sqrt', Complex<T>> =>
z => {
const myabs = dep.conservativeSqrt(dep.absquare(z))
const r = dep.re(z)
const negr = dep.unaryMinus(r)
if (dep.equal(myabs, negr)) {
// pure imaginary square root; z.im already zero
return dep.complex(
dep.zero(z.re), dep.addTR(z.im, dep.conservativeSqrt(negr)))
} }
const num = dep.addCR(z, myabs) // neither the real number or its negative is a square; could happen
const denomsq = dep.addRR(dep.addRR(myabs, myabs), dep.addRR(r, r)) // for example with bigint. So there is no square root. So we have to
const denom = dep.conservativeSqrt(denomsq) // return the NaN of the type.
return dep.divideReal(num, denom) return dep.nan(dep.complex(r))
} }
$reflect!([ export const sqrt =
add, addReal, unaryMinus, conj, subtract, multiply, absquare, divideReal, <T>(dep: Dependency<'isReal', [Complex<T>]>
reciprocal, divide, sqrt & Dependency<'complexSqrt', [T]>
]) & Dependency<'absquare', [Complex<T>]>
& Dependency<'conservativeSqrt', [UnderlyingReal<T>]>
& Dependency<'addReal', [Complex<T>,UnderlyingReal<T>]>
& Dependency<'re', [Complex<T>]>
& Dependency<'add', [UnderlyingReal<T>,UnderlyingReal<T>]>
& Dependency<'divideByReal', [Complex<T>,UnderlyingReal<T>]>
): ImpType<'sqrt', [Complex<T>]> =>
z => {
if (dep.isReal(z)) return dep.complexSqrt(z.re)
const myabs = dep.conservativeSqrt(dep.absquare(z))
const num = dep.addReal(z, myabs)
const r = dep.re(z)
const denomsq = dep.add(dep.add(myabs, myabs), dep.add(r, r))
const denom = dep.conservativeSqrt(denomsq)
return dep.divideByReal(num, denom)
}
export const conservativeSqrt = sqrt

View File

@ -1,13 +1,19 @@
import {Complex} from './type.js' import {Complex} from './type.js'
import type {Dependencies, Signature} from '../interfaces/type.js' import {Signature, Dependency, ImpType} from '../core/Dispatcher.js'
import {$reflect} from '../interfaces/type.js'
declare module "./type" {
interface ComplexReturn<Params> {
isReal: Signature<Params, [Complex<any>], boolean>
isSquare: Signature<Params, [Complex<any>], boolean>
}
}
export const isReal = export const isReal =
<T>(dep: Dependencies<'add' | 'equal' | 'isReal', T>): <T>(dep: Dependency<'equal', [T,T]>
Signature<'isReal', Complex<T>> => & Dependency<'add', [T,T]>
& Dependency<'isReal', [T]>
): ImpType<'isReal', [Complex<T>]> =>
z => dep.isReal(z.re) && dep.equal(z.re, dep.add(z.re, z.im)) z => dep.isReal(z.re) && dep.equal(z.re, dep.add(z.re, z.im))
export const isSquare = (): Signature<'isSquare', Complex<unknown>> => export const isSquare: ImpType<'isSquare', [Complex<any>]> =
z => true // FIXME: not correct for Complex<bigint> once we get there z => true // FIXME: not correct for Complex<bigint> once we get there
$reflect!([isReal, isSquare])

View File

@ -1,8 +1,15 @@
import {Complex} from './type.js' import {Complex} from './type.js'
import {Dependencies, Signature} from '../interfaces/type.js' import {BBinary, ImpType, Dependency} from '../core/Dispatcher.js'
import {$reflect} from '../interfaces/type.js'
declare module "./type" {
interface ComplexReturn<Params> {
equal: Params extends BBinary<infer B>
? B extends Complex<any> ? boolean : never
: never
}
}
export const equal = export const equal =
<T>(dep: Dependencies<'equal', T>): Signature<'equal', Complex<T>> => <T>(dep: Dependency<'equal', [T,T]>):
ImpType<'equal', [Complex<T>, Complex<T>]> =>
(w, z) => dep.equal(w.re, z.re) && dep.equal(w.im, z.im) (w, z) => dep.equal(w.re, z.re) && dep.equal(w.im, z.im)
$reflect!([equal])

View File

@ -1,67 +1,87 @@
import {joinTypes, typeOfDependency} from '../core/Dispatcher.js' import {
import type { joinTypes, typeOfDependency, Dependency, BBinary, ImpType, ImpReturns
ZeroType, OneType, NaNType, Dependencies, Signature, Returns } from '../core/Dispatcher.js'
} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export type Complex<T> = { re: T; im: T; } export type Complex<T> = {re: T; im: T;}
export type UnderlyingReal<T> =
T extends Complex<infer U> ? UnderlyingReal<U> : T
export const Complex_type = { export const Complex_type = {
name: 'Complex', // just until we have reflection to tell us test: <T>(dep: {testT: (z: unknown) => z is T}) =>
test: <T>(dep: { testT: (z: unknown) => z is T }) =>
(z: unknown): z is Complex<T> => (z: unknown): z is Complex<T> =>
typeof z === 'object' && z != null && 're' in z && 'im' in z typeof z === 'object' && 're' in z && 'im' in z
&& dep.testT(z['re']) && dep.testT(z['im']), && dep.testT(z.re) && dep.testT(z.im),
infer: (dep: typeOfDependency) => infer: (dep: typeOfDependency) =>
(z: Complex<unknown>) => joinTypes(dep.typeOf(z.re), dep.typeOf(z.im)), (z: Complex<unknown>) => joinTypes(dep.typeOf(z.re), dep.typeOf(z.im)),
from: { from: {
T: <T>(dep: Dependencies<'zero', T>) => (t: T) => T: <T>(dep: Dependency<'zero', [T]>) => (t: T) =>
({ re: t, im: dep.zero(t) }), ({re: t, im: dep.zero(t)}),
Complex: <U, T>(dep: { convert: (from: U) => T }) => Complex: <U,T>(dep: {convert: (from: U) => T}) =>
(z: Complex<U>) => ({ re: dep.convert(z.re), im: dep.convert(z.im) }) (z: Complex<U>) => ({re: dep.convert(z.re), im: dep.convert(z.im)})
} }
} }
declare module "../interfaces/type" { export interface ComplexReturn<Params> {
interface AssociatedTypes<T> { // Sadly, I can't think of a way to make some nice abbreviation operators
Complex: T extends Complex<infer R> ? { // for these generic type specifications because TypeScript generics
type: Complex<R> // can't take and use generic parameters, only fully instantiated types.
zero: Complex<ZeroType<R>> complex: Params extends [infer U] ? Complex<U> // unary case
one: Complex<OneType<R> | ZeroType<R>> : Params extends BBinary<infer B> ? Complex<B> // binary case
nan: Complex<NaNType<R>> : never
real: RealType<R>
} : never
}
interface Signatures<T> { // alternatively if it seems better; each definition is simpler, but at
complex: ((re: T) => Complex<T>) | ((re: T, im: T) => Complex<T>) // the cost of having two keys here:
} // complex_unary: Params extends [infer R] ? Complex<R> : never
// complex_binary: Params extends BBinary<infer R> ? Complex<R> : never
// There is actually a subtlety here that complex_unary really only works
// on real types that include their own zero value, so it should really be
// complex_unary: Params extends [infer R]
// ? ImpReturns<'zero', [R]> extends R ? Complex<R> : never
// : never
// and that might actually simplify some of the typings of other operations,
// but we'll leave such fine tuning til later, if we adopt this scheme
zero: Params extends [infer Z] // unary
? Z extends Complex<infer T> // of a Complex parameter
? ImpReturns<'zero', T> extends T ? Z : never // that has its real 0
: never
: never
one: Params extends [infer Z] // unary
? Z extends Complex<infer T> // of a Complex parameter
? ImpReturns<'one'|'zero', T> extends T ? Z : never // has real 1, 0
: never
: never
nan: Params extends [infer Z] // unary
? Z extends Complex<infer T> // of a Complex parameter
? ImpReturns<'nan', T> extends T ? Z : never // has real NaN
: never
: never
re: Params extends [infer Z]
? Z extends Complex<infer T> ? UnderlyingReal<T> : never
: never
} }
export const complex = export const complex_unary =
<T>(dep: Dependencies<'zero', T>): Signature<'complex', T> => <T>(dep: Dependency<'zero', [T]>): ImpType<'complex', [T]> =>
(a, b) => ({re: a, im: b || dep.zero(a)}) t => ({re: t, im: dep.zero(t)})
export const complex_binary = <T>(t: T, u: T): ImpReturns<'complex', [T,T]> =>
({re: t, im: u})
export const zero = export const zero =
<T>(dep: Dependencies<'zero', T> <T>(dep: Dependency<'zero', [T]>): ImpType<'zero', [Complex<T>]> =>
& Dependencies<'complex', Returns<'zero', T>>): z => complex_binary(dep.zero(z.re), dep.zero(z.im))
Signature<'zero', Complex<T>> =>
z => dep.complex(dep.zero(z.re), dep.zero(z.im))
export const one = export const one =
<T>(dep: Dependencies<'one' | 'zero', T> <T>(dep: Dependency<'zero' | 'one', [T]>): ImpType<'one', [Complex<T>]> =>
& Dependencies<'complex', Returns<'one' | 'zero', T>>): z => // Must provide parameter T, else TS narrows to return type of dep.one
Signature<'one', Complex<T>> => complex_binary<T>(dep.one(z.re), dep.zero(z.im))
z => dep.complex(dep.one(z.re), dep.zero(z.im))
export const nan = export const nan =
<T>(dep: Dependencies<'nan', T> <T>(dep: Dependency<'nan', [T]>): ImpType<'nan', [Complex<T>]> =>
& Dependencies<'complex', Returns<'nan', T>>): z => complex_binary(dep.nan(z.re), dep.nan(z.im))
Signature<'nan', Complex<T>> =>
z => dep.complex(dep.nan(z.re), dep.nan(z.im))
export const re = export const re =
<T>(dep: Dependencies<'re', T>): Signature<'re', Complex<T>> => <T>(dep: Dependency<'re', [T]>): ImpType<'re', [Complex<T>]> =>
z => dep.re(z.re) z => dep.re(z.re)
$reflect!([complex, zero, one, nan, re])

View File

@ -5,29 +5,122 @@
* for specific types (including their own). * for specific types (including their own).
*/ */
import {parseReflectedType, ImplementationDef} from './parseReflectedType.js'
// First helper types and functions for the Dispatcher // First helper types and functions for the Dispatcher
type TypeName = string type TypeName = string
type Parameter = TypeName type Parameter = TypeName
type Signature = Parameter[] type InputSignature = Parameter[]
type DependenciesType = Record<string, Function> type DependenciesType = Record<string, Function>
// A "canned" dependency for a builtin function:
export type typeOfDependency = {typeOf: (x: unknown) => TypeName} export type typeOfDependency = {typeOf: (x: unknown) => TypeName}
// Utility needed in type definitions // All of the implementations must publish descriptions of their
// return types into the following interface, using the format
// described just below:
export interface ReturnTypes<Params> {}
/*****
To describe one implementation for a hypothetical operation `foo`, there
should be a property of the interface whose name starts with `foo` and whose
next character, if any, is an underscore. The type of this property
must be the return type of that implementation when Params matches the
parameter types of the implementation, and `never` otherwise.
Thus to describe an implementation that takes a number and a string and
returns a boolean, for example, you could write
```
declare module "Dispatcher" {
interface ReturnTypes<Params> {
foo_example: Params extends [number, string] ? boolean : never
}
}
```
If there is another, generic implementation that takes one argument
of any type and returns a Vector of that type, you can say
```
...
foo_generic: Params extends [infer T] ? Vector<T> : never
...
```
In practice, each subdirectory corresponding to a type, like Complex,
defines an interface, like `ComplexReturn<Params>` for the implementations
in that subdirectory, which can mostly be defined without suffixes because
there's typically just a single implementation within that domain.
Then the module responsible for collating all of the implementations for
that type inserts all of the properties of that interface into `ReturnTypes`
suitably suffixed to avoid collisions.
One might think that simply defining an implementation for `foo`
of type `(n: number, s: string) => boolean` would provide all of the same
information as the type of the key `foo_example` in the ReturnTypes
interface above, but in practice TypeScript has challenges in extracting
types relating to functions. (In particular, there is no
way to get the specialized return type of a generic function when it is
called on aguments whose specific types match the generic parameters.)
Hence the need for this additional mechanism to specify return types, in
a way readily suited for TypeScript type computations.
*****/
// Helpers for specifying signatures
// A basic signature with concrete types
export type Signature<CandidateParams, ActualParams, Returns> =
CandidateParams extends ActualParams ? Returns : never
// A homogeneous binary parameter tuple (comes up a lot, needs a better name?)
// Typical usage: `foo_impl: Params extends BBinary<infer B> ? B : never`
// says that this implementation takes two arguments, both of type B, and
// returns the same type.
export type BBinary<B> = [B, B]
// A unary signature that preserves the type of its argument, which must
// extend the given Bound:
export type ConservativeUnary<CandidateParams, Bound> =
CandidateParams extends [infer T] ? T extends Bound ? T : never : never
// A homogeneous binary signature that preserves the common type of its
// arguments, which must extend the given Bound:
export type ConservativeBinary<CandidateParams, Bound> =
CandidateParams extends BBinary<infer B>
? B extends Bound ? B : never
: never
// Helper for collecting return types
// (Really just adds the literal string Suffix onto the keys of interface IFace)
export type ForType<Suffix extends string, IFace> = keyof IFace extends string
? {[K in keyof IFace as `${K}_${Suffix}`]: IFace[K]}
: never
//dummy implementation for now //dummy implementation for now
export function joinTypes(a: TypeName, b: TypeName) { export function joinTypes(a: TypeName, b: TypeName) {
if (a === b) return a if (a === b) return a
return 'any' return 'any'
} }
// Used to filter keys that match a given operation name
type BeginsWith<Name extends string> = Name | `${Name}_${string}`
// Look up the return type of an implementation based on its name
// and the parameters it takes
export type ImpReturns<Name extends string, Params> =
{[K in keyof ReturnTypes<Params>]: K extends BeginsWith<Name>
? ReturnTypes<Params>[K] : never}[keyof ReturnTypes<Params>]
// The type of an implementation (with dependencies satisfied,
// based on its name and the parameters it takes
export type ImpType<Name extends string, Params extends unknown[]> =
(...args: Params) => ImpReturns<Name, Params>
// The type of a dependency on an implementation based on its name
// and the parameters it takes (just a simple object with one property
// named the same as the operation, of value type equal to the type of
// that implementation. These can be `&`ed together in case of multiple
// dependencies:
export type Dependency<Name extends string, Params extends unknown[]> =
{[N in Name]: ImpType<N, Params>}
// Now types used in the Dispatcher class itself // Now types used in the Dispatcher class itself
type TypeSpecification = { type TypeSpecification = {
name: string, // just until we get reflection, then we can remove this property
before?: TypeName[], before?: TypeName[],
test: ((x: unknown) => boolean) test: ((x: unknown) => boolean)
| ((d: DependenciesType) => (x: unknown) => boolean), | ((d: DependenciesType) => (x: unknown) => boolean),
@ -41,44 +134,38 @@ type SpecificationsGroup = Record<string, SpecObject>
export class Dispatcher { export class Dispatcher {
installSpecification( installSpecification(
name: string, name: string,
defn: ImplementationDef, signature: InputSignature,
returns: TypeName,
dependencies: Record<string, InputSignature>,
behavior: Function // possible todo: constrain this type based behavior: Function // possible todo: constrain this type based
// on the signature, return type, and dependencies. Not sure if // on the signature, return type, and dependencies. Not sure if
// that's really possible, though. // that's really possible, though.
) { ) {
console.log('Pretending to install', name, 'with signatures') console.log('Pretending to install', name, signature, '=>', returns)
for (const signature of defn.fn.signatures) {
console.log(' ', signature.args, '=>', signature.returns)
}
if (defn.fn.aliasOf) {
console.log(' As an alias of', defn.fn.aliasOf)
}
//TODO: implement me //TODO: implement me
} }
installType(name: TypeName, typespec: TypeSpecification) { installType(name: TypeName, typespec: TypeSpecification) {
console.log('Pretending to install type', name, typespec) console.log('Pretending to install type', name, typespec)
//TODO: implement me //TODO: implement me
} }
constructor(collection: SpecificationsGroup) { constructor(collection: SpecificationsGroup) {
const implementations = []
for (const key in collection) { for (const key in collection) {
console.log('Working on', key) console.log('Working on', key)
for (const identifier in collection[key]) { for (const identifier in collection[key]) {
const item = collection[key][identifier] console.log('Handling', key, ':', identifier)
if (typeof item === 'function') { const parts = identifier.split('_')
implementations.push([key, identifier, item]) if (parts[parts.length - 1] === 'type') {
} else { parts.pop()
console.log('Handling type', key, ':', identifier) const name = parts.join('_')
this.installType( this.installType(
item.name, collection[key][identifier] as TypeSpecification) name, collection[key][identifier] as TypeSpecification)
} else {
const name = parts[0]
this.installSpecification(
name, ['dunno'], 'unsure', {},
collection[key][identifier] as Function)
} }
} }
} }
for (const trio of implementations) {
const [k, id, imp] = trio
console.log('Handling implementation', id, 'from', k)
this.installSpecification(
id, parseReflectedType(id, imp.reflectedType), imp)
}
} }
} }

View File

@ -1,279 +0,0 @@
export type FunctionDef = {
name: string,
aliasOf?: string,
signatures: Array<{
args: Array<{ name: string, type: string }>
returns: string
}>
}
export type ImplementationDef = {
fn: FunctionDef,
dependencies: Record<string, FunctionDef>
genericParameter: string | null
}
/**
* Parse a reflected type coming out of TypeScript into a structured object, for example:
*
* '<T>(dep: configDependency & { complex: ((re: number) => Complex<number>) | ((re: number, im: number) => Complex<number>); }) => (a: number) => number | Complex<number>'
*/
export function parseReflectedType(name: string, reflectedType: string): ImplementationDef {
console.log('For', name, 'parsing', reflectedType)
const [factoryArgs, fnsClause] = split(reflectedType, '=>', 2).map(trim)
const fn = parseAlias(name, fnsClause)
// extract the generic parameter like '<T>' at the start of the type
const genericParameter = factoryArgs.trim().startsWith('<')
? findBlockContents(factoryArgs, '<', '>')?.innerText || null
: null
const factoryArgsInner = findBlockContents(factoryArgs, '(', ')')
const depArg = split(factoryArgsInner.innerText, ':').map(trim)[1]
const depArgBlocks: string[] = depArg ? split(depArg, '&').map(trim) : []
const deps = depArgBlocks
.filter(depArgBlock => {
if (depArgBlock.startsWith('{') || depArgBlock === 'configDependency') {
return true
} else {
throw new SyntaxError(`Cannot parse dependency "${depArgBlock}"`)
}
})
.flatMap(parseDependencies)
const dependencies: Record<string, FunctionDef> = groupBy(deps, 'name')
return {fn, dependencies, genericParameter }
}
function parseDependencies(deps: string): FunctionDef[] {
if (deps === 'configDependency') {
return [{name: 'config', signatures: [{args: [], returns: 'Config'}]}]
}
const inner = findBlockContents(deps, '{', '}').innerText
return split(inner, ';')
.map(trim)
.filter(notEmpty)
.map(parseDependency)
}
// parse a dependency like "complex: ((re: number) => Complex<number>) | ((re: number, im: number) => Complex<number>)"
function parseDependency(dep: string): FunctionDef {
const [name, def] = split(dep, ':').map(trim)
return parseAlias(name, def)
}
// Parse a possibly aliased function
function parseAlias(name: string, alias: string): FunctionDef {
const { aliasOf, innerSignature } = parseAliasOf(alias)
return { name, signatures: parseSignatures(innerSignature), aliasOf }
}
// parse function signatures like ((re: number) => Complex<number>) | ((re: number, im: number) => Complex<number>)
// But also have to succeed on (a: number) => number | Complex<number>
// That's why we only split on an alternation bar `|` that's followed by
// a parenthesis; that way we avoid splitting a union return type. Note
// this is not necessarily foolproof, as there could be a return type that
// is a union with a complicated piece that has to be enclosed in parens;
// but so far it seems to work in practice.
function parseSignatures(sigs: string) {
return split(sigs, /[|]\s*(?=[(])/)
.map(trim)
.map(stripParenthesis)
.map(signature => {
const [argsBlock, returns] = split(signature, '=>').map(trim)
if (!returns) {
throw new SyntaxError(`Failed to find return type in '${signature}'`)
}
return {
args: parseArgs(argsBlock),
returns
}
})
}
// parse args like "(re: number, im: number)"
function parseArgs(argsBlock: string) : Array<{name: string, type: string}> {
const args = findBlockContents(argsBlock, '(', ')').innerText
return split(args, ',')
.map(trim)
.map(arg => {
const [name, type] = split(arg, ':').map(trim)
return { name, type}
})
}
// parse "AliasOf<"divide", (a: Complex<T>, b: RealType<Complex<T>>) => Complex<T>>"
function parseAliasOf(signature: string) : { innerSignature: string, aliasOf: string | undefined } {
if (!signature.startsWith('AliasOf')) {
return {
innerSignature: signature,
aliasOf: undefined
}
}
const inner = findBlockContents(signature, '<', '>').innerText.trim()
const [aliasOfWithQuotes, innerSignature] = split(inner, ',').map(trim)
return {
innerSignature,
aliasOf: aliasOfWithQuotes.substring(1, aliasOfWithQuotes.length - 1) // remove double quotes
}
}
// remove the outer parenthesis, for example "((re: number) => Complex<number>)" returns "(re: number) => Complex<number>"
function stripParenthesis(text: string) : string {
return text.startsWith('(') && text.endsWith(')')
? text.substring(1, text.length - 1)
: text
}
function findBlockContents(text: string, blockStart: string, blockEnd: string, startIndex = 0) : { start: number, end: number, innerText: string } | undefined {
let i = startIndex
while (!matchSubString(text, blockStart, i) && i < text.length) {
i++
}
if (i >= text.length) {
return undefined
}
i++
const start = i
while (!matchSubString(text, blockEnd, i) || matchSubString(text, '=>', i - 1)) {
i = skipBrackets(text, i)
i++
}
if (i >= text.length) {
return undefined
}
const end = i
return {
start,
end,
innerText: text.substring(start, end)
}
}
/**
* Given a string, generate a string source for a regexp that will match
* exactly the given string.
* Uses the fact that the only characters that need to be escaped in
* a character class are \, ], and ^
*/
function regexpQuote(s: string) {
const special = '\\]^'
let re = ''
for (const char of s) {
if (special.includes(char)) re += `\\${char}`
else re += `[${char}]`
}
return re
}
/**
* Split a string by a delimiter, but ignore all occurrences of the delimiter
* that are inside bracket pairs <> () [] {}
*/
export function split(
text: string, delimiter: string | RegExp, pieces = 0): string[] {
const delim: RegExp = typeof delimiter === 'string'
? new RegExp(regexpQuote(delimiter), 'y')
: new RegExp(delimiter.source, 'y')
const parts: string[] = []
let i = 0
let n = 1
let start = 0
while (i < text.length && (pieces === 0 || n < pieces)) {
i = skipBrackets(text, i)
delim.lastIndex = i
const result = delim.exec(text)
if (result) {
parts.push(text.substring(start, i))
n += 1
i += result[0].length
start = i
}
i++
}
parts.push(text.substring(start))
return parts
}
function skipBrackets(text: string, startIndex: number) : number {
let level = 0
let i = startIndex
do {
if (isBracketOpen(text, i)) {
level++
}
if (isBracketClose(text, i) && level > 0) {
level--
}
if (level === 0) {
break
}
i++
} while(i < text.length)
return i
}
function isBracketOpen(text: string, index: number) {
const char = text[index]
return char === '(' || char === '<' || char === '[' || char === '{'
}
function isBracketClose(text: string, index: number) {
const char = text[index]
// we need to take care of not matching the ">" of the operator "=>"
return char === ')' || (char === '>' && text[index - 1] !== '=') || char === ']' || char === '}'
}
function matchSubString(text: string, search: string, index: number) : boolean {
for (let i = 0; i < search.length; i++) {
if (text[i + index] !== search[i]) {
return false
}
}
return true
}
function trim(text: string) : string {
return text.trim()
}
function notEmpty(text: string) : boolean {
return text.length > 0
}
function groupBy<T>(items: T[], key: string) : Record<string, T> {
const obj: Record<string, T> = {}
items.forEach((item) => {
obj[item[key]] = item
})
return obj
}

View File

@ -1 +1,10 @@
export * as generic from './native.js' import { ForType } from '../core/Dispatcher.js'
import { GenericReturn } from './type.js'
import * as generic from './arithmetic.js'
export { generic }
declare module "../core/Dispatcher" {
interface ReturnTypes<Params>
extends ForType<'generic', GenericReturn<Params>> { }
}

View File

@ -1,9 +1,39 @@
import type {Dependencies, Signature} from '../interfaces/type.js' import {Dependency, ImpType, ImpReturns} from "../core/Dispatcher";
import {$reflect} from '../interfaces/type.js'
declare module "./type" {
interface GenericReturn<Params> {
// Jos: not sure how to define this or why it is needed
// square: Signature<Params, [T], T>
// square: ConservativeUnary<Params, T>
// square: Params extends [infer R]
// ? R extends number ? UnderlyingReal<R> : never
// : never
// The type of `square` in this interface, instantiated with the type
// Params of a parameter list, needs to be the return type of the
// operation `square` on those parameters. In other words, `square` gives
// a type transformer from the tuple type of its parameters to its return
// type.
// That's how Dispatcher knows what the return type will be in
// `Dependency<'square', [bigint]>`, for example: it instantiates
// GenericReturn with Params equal to [bigint] and then grabs the
// type of the `square` property. Hence we write:
square: Params extends [infer T] // square only takes 1 arbitrary parameter
? ImpReturns<'multiply', [T, T]> // and returns whatever multiply does
: never; // otherwise if not a single argument, this implementation
// doesn't handle it
// If square had more than one implementation in this collection, we could
// either add more conditional clauses to the above type transformer
// as I did in Complex/type.ts for `complex`, or we could have two
// different keys that both start with `square_` and Dispatcher will
// check both (as I have now done in comments in Complex/type.ts and
// verified that also works).
}
}
export const square = export const square =
<T>(dep: Dependencies<'multiply', T>): Signature<'square', T> => <T>(dep: Dependency<'multiply', [T, T]>):
z => dep.multiply(z, z) ImpType<'square', [T]> =>
// z => dep.fooBar(z, z) // fails as desired z => dep.multiply(z, z)
// z => dep.multiply(z, 'foo') // still fails as desired
$reflect!([square])

View File

@ -1,2 +0,0 @@
export * from './arithmetic.js'
export * from './relational.js'

View File

@ -1,7 +0,0 @@
import {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const unequal =
<T>(dep: Dependencies<'equal', T>): Signature<'unequal', T> =>
(x, y) => !dep.equal(x, y)
$reflect!([unequal])

3
src/generic/type.ts Normal file
View File

@ -0,0 +1,3 @@
export interface GenericReturn<Params> {
}

View File

@ -1,53 +1,4 @@
import {inspect} from 'node:util'
import {Dispatcher} from './core/Dispatcher.js' import {Dispatcher} from './core/Dispatcher.js'
import * as Specifications from './all.js' import * as Specifications from './all.js'
export default new Dispatcher(Specifications) export default new Dispatcher(Specifications)
import {Complex} from './Complex/type.js'
import {absquare as absquare_complex} from './Complex/arithmetic.js'
import {parseReflectedType} from './core/parseReflectedType.js'
const mockRealAdd = (a: number, b: number) => a+b
const mockComplexAbsquare = (z: Complex<number>) => z.re*z.re + z.im*z.im
const mockComplex = (re: number, im: number) => ({ re, im })
const config = {
predictable: false,
epsilon: 1e-14
}
const quatAbsquare = absquare_complex({
add: mockRealAdd,
absquare: mockComplexAbsquare
})
const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}})
const typeTest: typeof myabs = 7 // check myabs is just a number
console.log('Result is myabs=', myabs)
const sqrt = Specifications.numbers.sqrt({
config,
complex: mockComplex
})
console.log('Result of sqrt(16)=', sqrt(16))
console.log('Result of sqrt(-4)=', sqrt(-4))
console.log()
console.log('1) NUMBER SQRT')
console.log(`1.1) REFLECTED TYPE: "${Specifications.numbers.sqrt.reflectedType}"`)
console.log(
'1.2) PARSED TYPE:',
inspect(
parseReflectedType('sqrt', Specifications.numbers.sqrt.reflectedType),
{ depth: null, colors: true }))
console.log()
console.log('2) GENERIC SQUARE')
console.log(`1.1) REFLECTED TYPE: "${Specifications.generic.square.reflectedType}"`)
console.log('2.2) PARSED TYPE:', inspect(parseReflectedType('square', Specifications.generic.square.reflectedType), { depth: null, colors: true }))
console.log()
console.log('3) COMPLEX SQRT')
console.log(`1.1) REFLECTED TYPE: "${Specifications.complex.sqrt.reflectedType}"`)
console.log('3.2) PARSED TYPE:', inspect(parseReflectedType('sqrt', Specifications.complex.sqrt.reflectedType), { depth: null, colors: true }))

View File

@ -1,18 +0,0 @@
import type {Complex} from '../Complex/type.js'
import type {RealType} from './type.js'
declare module "./type" {
interface Signatures<T> {
add: (a: T, b: T) => T
unaryMinus: (a: T) => T
conj: (a: T) => T
subtract: (a: T, b: T) => T
multiply: (a: T, b: T) => T
square: (a: T) => T
absquare: (a: T) => RealType<T>
reciprocal: (a: T) => T
divide: (a: T, b: T) => T
conservativeSqrt: (a: T) => T
sqrt: (a: T)=> T extends Complex<unknown> ? T : T | Complex<T>
}
}

View File

@ -1,10 +0,0 @@
// Warning: a module must have something besides just a "declare module"
// section; otherwise it is ignored.
export type UnaryPredicate<T> = (a: T) => boolean
declare module "./type" {
interface Signatures<T> {
isReal: (a: T) => boolean
isSquare: (a: T) => boolean
}
}

View File

@ -1,9 +0,0 @@
// Warning: a module must have something besides just a "declare module"
// section; otherwise it is ignored.
export type BinaryPredicate<T> = (a: T, b: T) => T
declare module "./type" {
interface Signatures<T> {
equal: (a: T, b: T) => boolean
unequal: (a: T, b: T) => boolean
}
}

View File

@ -1,90 +0,0 @@
import {$$typeToString} from 'ts-macros'
/*****
* Every typocomath type has some associated types; they need
* to be published in the following interface. The key is the
* name of the type, and within the subinterface for that key,
* the type of the 'type' property is the actual TypeScript type
* we are associating the other properties to. Note the interface
* is generic with one parameter, corresponding to the fact that
* typocomath currently only allows generic types with a single
* generic parameter. This way, AssociatedTypes<SubType> can give the
* associated types for a generic type instantiated with SubType.
* That's not necessary for the 'undefined' type (or if you look in the
* `numbers` subdirectory, the 'number' type) or any concrete type,
* but that's OK, the generic parameter doesn't hurt in those cases.
****/
type ValueIntersectionByKeyUnion<T, TKey extends keyof T> = {
[P in TKey]: (k: T[P])=>void
} [TKey] extends ((k: infer I)=>void) ? I : never
export interface AssociatedTypes<T> {
undefined: {
type: undefined
zero: undefined
one: undefined
nan: undefined
real: undefined
}
}
type AssociatedTypeNames = keyof AssociatedTypes<unknown>['undefined']
type ALookup<T, Name extends AssociatedTypeNames> = ValueIntersectionByKeyUnion<{
[K in keyof AssociatedTypes<T>]:
T extends AssociatedTypes<T>[K]['type'] ? AssociatedTypes<T>[K][Name] : unknown},
keyof AssociatedTypes<T>>
// For everything to compile, zero and one must be subtypes of T:
export type ZeroType<T> = ALookup<T, 'zero'> & T
export type OneType<T> = ALookup<T, 'one'> & T
// But I believe 'nan' really might not be, like I think we will have to use
// 'undefined' for the nan of 'bigint', as it has nothing at all like NaN,
// so don't force it:
export type NaNType<T> = ALookup<T, 'nan'>
export type RealType<T> = ALookup<T, 'real'>
/*****
* The global signature patterns for all operations need to be published in the
* following interface. Each key is the name of an operation (but note that
* the Dispatcher will automatically merge operations that have the same
* name when the first underscore `_` and everything thereafter is stripped).
* The type of each key should be an interface with two properties: 'params'
* whose type is the type of the parameter list for the operation, and
* 'returns' whose type is the return type of the operation on those
* parameters. These types are generic in a parameter type T which should
* be interpreted as the type that the operation is supposed to "primarily"
* operate on, although note that some of the parameters and/or return types
* may depend on T rather than be exactly T.
* So note that the example 're' below provides essentially the same
* information that e.g.
* `type ReOp<T> = (t: T) => RealType<T>`
* would, but in a way that is much easier to manipulate in TypeScript,
* and it records the name of the operation as 're' also by virtue of the
* key 're' in the interface.
****/
export interface Signatures<T> {
zero: (a: T) => ZeroType<T>
one: (a: T) => OneType<T>
// nan needs to be able to operate on its own output for everything
// else to compile. That's why its parameter type is widened:
nan: (a: T | NaNType<T>) => NaNType<T>
re: (a: T) => RealType<T>
}
type SignatureKey<T> = keyof Signatures<T>
export type Signature<Name extends SignatureKey<T>, T> = Signatures<T>[Name]
export type Returns<Name extends SignatureKey<T>, T> =
ReturnType<Signatures<T>[Name]>
type Deps<T> = T extends unknown ? { [K in keyof T]: T[K] } : never;
export type Dependencies<Name extends SignatureKey<T>, T> =
Deps<{[K in Name]: Signature<K, T>}>
export type AliasOf<Name extends string, T> = T & {aliasOf?: Name}
// For defining implementations with type reflection
export function $reflect<ImplTuple>(tup: ImplTuple) {
+[[tup], <T>(elt: T) =>
elt.reflectedType = $$typeToString!<T>(true, false, true)]
}

View File

@ -1,3 +1,10 @@
import {ForType} from '../core/Dispatcher.js'
import {NumbersReturn} from './type.js'
import * as numbers from './native.js' import * as numbers from './native.js'
export {numbers} export {numbers}
declare module "../core/Dispatcher" {
interface ReturnTypes<Params>
extends ForType<'numbers', NumbersReturn<Params>> {}
}

View File

@ -1,35 +1,72 @@
import type {configDependency} from '../core/Config.js' import {configDependency} from '../core/Config.js'
import type {Dependencies, Signature} from '../interfaces/type.js' import {
import {$reflect} from '../interfaces/type.js' Signature, ConservativeBinary, ConservativeUnary, Dependency, ImpType
} from '../core/Dispatcher.js'
import type {Complex, UnderlyingReal} from '../Complex/type.js'
export const add = (): Signature<'add', number> => (a, b) => a + b declare module "./type" {
const unaMinus = (a: number) => -a interface NumbersReturn<Params> {
export const unaryMinus = (): Signature<'unaryMinus', number> => unaMinus // This description loses information: some subtypes like NumInt or
export const conj = (): Signature<'conj', number> => a => a // Positive are closed under addition, but this says that the result
export const subtract = (): Signature<'subtract', number> => (a, b) => a - b // of add is just a number, not still of the reduced type
export const multiply = (): Signature<'multiply', number> => (a, b) => a * b // add: Signature<Params, [number, number], number>
export const absquare = (): Signature<'absquare', number> => a => a * a
export const reciprocal = (): Signature<'reciprocal', number> => a => 1 / a
export const divide = (): Signature<'divide', number> => (a, b) => a / b
const basicSqrt = (a: number) => isNaN(a) ? NaN : Math.sqrt(a) // Whereas this one preserves information, but lies
export const conservativeSqrt = (): Signature<'conservativeSqrt', number> => // because it claims all subtypes of number are closed under addition,
basicSqrt // which is not true for `1 | 2 | 3`, for example. But because in
// generics that use add we often need to assign the result of add
// to something of the exact generic type, generics using add won't
// compile unless we lie in this way and assert that add returns
// the subtype.
add: ConservativeBinary<Params, number>
// Not sure how this will need to go when we introduce NumInt.
addReal: Params extends [infer R, infer S]
? R extends number ? S extends R ? R : never : never
: never
unaryMinus: ConservativeUnary<Params, number>
conj: ConservativeUnary<Params, number>
subtract: ConservativeBinary<Params, number>
multiply: ConservativeBinary<Params, number>
absquare: Params extends [infer R]
? R extends number ? UnderlyingReal<R> : never
: never
reciprocal: ConservativeUnary<Params, number>
divide: ConservativeBinary<Params, number>
divideByReal: Params extends [infer R, infer S]
? R extends number ? S extends R ? R : never : never
: never
// best square root that remains the same type
conservativeSqrt: ConservativeUnary<Params, number>
// Best we can do for sqrt at compile time, since actual return
// type depends on config. Not sure how this will play out
// when we make a number-only bundle, but at least the import type
// above for Complex<> does not lead to any emitted JavaScript.
sqrt: Signature<Params, [number], number | Complex<number>>
}
}
export const add: ImpType<'add', [number, number]> = (a, b) => a + b
export const addReal = add
export const unaryMinus: ImpType<'unaryMinus', [number]> = a => -a
export const conj: ImpType<'conj', [number]> = a => a
export const subtract: ImpType<'subtract', [number, number]> = (a, b) => a - b
export const multiply: ImpType<'multiply', [number, number]> = (a, b) => a * b
export const absquare: ImpType<'absquare', [number]> = a => a*a
export const reciprocal: ImpType<'reciprocal', [number]> = a => 1/a
export const divide: ImpType<'divide', [number, number]> = (a, b) => a / b
export const divideByReal: ImpType<'divideByReal', [number, number]> = divide
export const conservativeSqrt: ImpType<'conservativeSqrt', [number]> =
a => isNaN(a) ? NaN : Math.sqrt(a)
export const sqrt = export const sqrt =
(dep: configDependency (dep: configDependency
& Dependencies<'complex', number>): Signature<'sqrt', number> => { & Dependency<'complex', [number, number]>): ImpType<'sqrt', [number]> => {
if (dep.config.predictable || !dep.complex) { if (dep.config.predictable || !dep.complex) return conservativeSqrt
return basicSqrt return a => {
if (isNaN(a)) return NaN
if (a >= 0) return Math.sqrt(a)
return dep.complex(0, Math.sqrt(unaryMinus(a)))
}
} }
return a => {
if (isNaN(a)) return NaN
if (a >= 0) return Math.sqrt(a)
return dep.complex(0, Math.sqrt(unaMinus(a)))
}
}
$reflect!([
add, unaryMinus, conj, subtract, multiply, absquare, reciprocal, divide,
conservativeSqrt, sqrt
])

View File

@ -1,4 +1,2 @@
export * from './type.js' export * from './type.js'
export * from './arithmetic.js' export * from './arithmetic.js'
export * from './predicate.js'
export * from './relational.js'

View File

@ -1,7 +1,11 @@
import type {Signature} from '../interfaces/type.js' import {Signature, ImpType} from '../core/Dispatcher.js'
import {$reflect} from '../interfaces/type.js'
export const isReal = (): Signature<'isReal', number> => (a) => true declare module "./type" {
export const isSquare = (): Signature<'isSquare', number> => (a) => a >= 0 interface NumbersReturn<Params> {
isReal: Signature<Params, [number], true>
isSquare: Signature<Params, [number], boolean>
}
}
$reflect!([isReal, isSquare]) export const isReal: ImpType<'isReal', [number]> = a => true
export const isSquare: ImpType<'isSquare', [number]> = a => a >= 0

View File

@ -1,23 +1,34 @@
import {configDependency} from '../core/Config.js' import {configDependency} from '../core/Config.js'
import {Signature} from '../interfaces/type.js' import {Signature, ImpType, Dependency} from '../core/Dispatcher.js'
import {$reflect} from '../interfaces/type.js'
const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16 const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16
export const equal = declare module "./type" {
(dep: configDependency): Signature<'equal', number> => interface NumbersReturn<Params> {
(x, y) => { equal: Signature<Params, [number, number], boolean>
const eps = dep.config.epsilon unequal: Signature<Params, [number, number], boolean>
if (eps === null || eps === undefined) return x === y }
if (x === y) return true }
if (isNaN(x) || isNaN(y)) return false
if (isFinite(x) && isFinite(y)) { export const equal =
const diff = Math.abs(x - y) (dep: configDependency): ImpType<'equal', [number, number]> =>
if (diff < DBL_EPSILON) return true (x, y) => {
return diff <= Math.max(Math.abs(x), Math.abs(y)) * eps const eps = dep.config.epsilon
if (eps === null || eps === undefined) return x === y
if (x === y) return true
if (isNaN(x) || isNaN(y)) return false
if (isFinite(x) && isFinite(y)) {
const diff = Math.abs(x - y)
if (diff < DBL_EPSILON) return true
return diff <= Math.max(Math.abs(x), Math.abs(y)) * eps
}
return false
} }
return false export const unequal = (dep: Dependency<'equal', [number, number]>):
ImpType<'unequal', [number, number]> =>
(x, y) => {
return !dep.equal(x, y)
} }
$reflect!([equal])

View File

@ -1,29 +1,44 @@
import type { Signature } from '../interfaces/type.js' import {ImpType} from '../core/Dispatcher.js'
import {$reflect} from '../interfaces/type.js' import type {UnderlyingReal} from '../Complex/type.js'
export const number_type = { export const number_type = {
name: 'number', // just until we have reflection to tell us
before: ['Complex'], before: ['Complex'],
test: (n: unknown): n is number => typeof n === 'number', test: (n: unknown): n is number => typeof n === 'number',
from: { string: (s: string) => +s } from: {string: s => +s}
} }
declare module "../interfaces/type" {
interface AssociatedTypes<T> { export interface NumbersReturn<Params> {
number: { // The following description of the return type of `zero` on a single
type: number // number argument has ended up unfortunately rather complicated. However,
zero: 0 // it illustrates the typing is really working: Suppose we have a
one: 1 // `type Small = 1 | 2 | 3`. Then Small indeed extends number, but we
nan: typeof NaN // can't use the operation `zero(s: Small)` because zero is supposed to
real: number // return something of the same type as its argument, but there is no
} // zero in Small. Anyhow, in plain language the below says that given
} // one parameter of a subtype of number, as long as that subtype includes 0,
// the zero operation returns a member of the type `0` (so we know even
// at compile time that its value will be 0).
zero: Params extends [infer T]
? T extends number ? 0 extends T ? 0 : never : never
: never
// Note that in any case the simple
// zero: Signature<Params, [number], 0>
// makes complex fail to compile, because it worries that you might be
// making `Complex<Small>` where zero would not return the right type.
one: Params extends [infer T]
? T extends number ? 1 extends T ? 1 : never : never
: never
nan: Params extends [infer T]
? T extends number ? typeof NaN extends T ? typeof NaN : never : never
: never
re: Params extends [infer T]
? T extends number ? UnderlyingReal<T> : never
: never
} }
// I don't like the redundancy of repeating 'zero'; any way to eliminate that? export const zero: ImpType<'zero', [number]> = a => 0
export const zero = (): Signature<'zero', number> => (a) => 0 export const one: ImpType<'one', [number]> = a => 1
export const one = (): Signature<'one', number> => (a) => 1 export const nan: ImpType<'nan', [number]> = a => NaN
export const nan = (): Signature<'nan', number> => (a) => NaN export const re: ImpType<'re', [number]> = a => a
export const re = (): Signature<'re', number> => (a) => a
$reflect!([zero, one, nan, re])

View File

@ -1,12 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "ES2022",
"rootDir": "./src", "rootDir": "./src",
"outDir": "./build", "outDir": "./obj"
"moduleResolution": "nodenext",
"plugins": [ {
"transform": "ts-macros/dist/type-resolve",
"transformProgram": true
} ]
} }
} }