diff --git a/aljabar-projek/.gitignore b/aljabar-projek/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/aljabar-projek/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/aljabar-projek/README.md b/aljabar-projek/README.md
new file mode 100644
index 0000000..c3c21da
--- /dev/null
+++ b/aljabar-projek/README.md
@@ -0,0 +1,75 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
+
+## React Compiler
+
+The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.
+
+Note: This will impact Vite dev & build performances.
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
+
+```js
+export default defineConfig([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ // Other configs...
+
+ // Remove tseslint.configs.recommended and replace with this
+ tseslint.configs.recommendedTypeChecked,
+ // Alternatively, use this for stricter rules
+ tseslint.configs.strictTypeChecked,
+ // Optionally, add this for stylistic rules
+ tseslint.configs.stylisticTypeChecked,
+
+ // Other configs...
+ ],
+ languageOptions: {
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ // other options...
+ },
+ },
+])
+```
+
+You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
+
+```js
+// eslint.config.js
+import reactX from 'eslint-plugin-react-x'
+import reactDom from 'eslint-plugin-react-dom'
+
+export default defineConfig([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ // Other configs...
+ // Enable lint rules for React
+ reactX.configs['recommended-typescript'],
+ // Enable lint rules for React DOM
+ reactDom.configs.recommended,
+ ],
+ languageOptions: {
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ // other options...
+ },
+ },
+])
+```
diff --git a/aljabar-projek/eslint.config.js b/aljabar-projek/eslint.config.js
new file mode 100644
index 0000000..5e6b472
--- /dev/null
+++ b/aljabar-projek/eslint.config.js
@@ -0,0 +1,23 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+import { defineConfig, globalIgnores } from 'eslint/config'
+
+export default defineConfig([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ js.configs.recommended,
+ tseslint.configs.recommended,
+ reactHooks.configs.flat.recommended,
+ reactRefresh.configs.vite,
+ ],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ },
+])
diff --git a/aljabar-projek/index.html b/aljabar-projek/index.html
new file mode 100644
index 0000000..704a8da
--- /dev/null
+++ b/aljabar-projek/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ aljabar-projek
+
+
+
+
+
+
diff --git a/aljabar-projek/package-lock.json b/aljabar-projek/package-lock.json
new file mode 100644
index 0000000..e8ff7ff
--- /dev/null
+++ b/aljabar-projek/package-lock.json
@@ -0,0 +1,3386 @@
+{
+ "name": "aljabar-projek",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "aljabar-projek",
+ "version": "0.0.0",
+ "dependencies": {
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.29.0",
+ "@eslint/js": "^9.39.4",
+ "@rolldown/plugin-babel": "^0.2.1",
+ "@types/babel__core": "^7.20.5",
+ "@types/node": "^24.12.0",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^6.0.1",
+ "babel-plugin-react-compiler": "^1.0.0",
+ "eslint": "^9.39.4",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.5.2",
+ "globals": "^17.4.0",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "^8.57.0",
+ "vite": "^8.0.1"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.29.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@emnapi/core": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz",
+ "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.2.0",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz",
+ "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz",
+ "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
+ "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.5"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
+ "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.14.0",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.5",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
+ "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz",
+ "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tybys/wasm-util": "^0.10.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ },
+ "peerDependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1"
+ }
+ },
+ "node_modules/@oxc-project/types": {
+ "version": "0.123.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.123.0.tgz",
+ "integrity": "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.13.tgz",
+ "integrity": "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.13.tgz",
+ "integrity": "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.13.tgz",
+ "integrity": "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.13.tgz",
+ "integrity": "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.13.tgz",
+ "integrity": "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.13.tgz",
+ "integrity": "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.13.tgz",
+ "integrity": "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.13.tgz",
+ "integrity": "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.13.tgz",
+ "integrity": "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.13.tgz",
+ "integrity": "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.13.tgz",
+ "integrity": "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.13.tgz",
+ "integrity": "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-wasm32-wasi": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.13.tgz",
+ "integrity": "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@emnapi/core": "1.9.1",
+ "@emnapi/runtime": "1.9.1",
+ "@napi-rs/wasm-runtime": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.13.tgz",
+ "integrity": "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.13.tgz",
+ "integrity": "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@rolldown/plugin-babel": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/plugin-babel/-/plugin-babel-0.2.2.tgz",
+ "integrity": "sha512-q9pE8+47bQNHb5eWVcE6oXppA+JTSwvnrhH53m0ZuHuK5MLvwsLoWrWzBTFQqQ06BVxz1gp0HblLsch8o6pvZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=22.12.0 || ^24.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.29.0 || ^8.0.0-rc.1",
+ "@babel/plugin-transform-runtime": "^7.29.0 || ^8.0.0-rc.1",
+ "@babel/runtime": "^7.27.0 || ^8.0.0-rc.1",
+ "rolldown": "^1.0.0-rc.5",
+ "vite": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/plugin-transform-runtime": {
+ "optional": true
+ },
+ "@babel/runtime": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.7",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz",
+ "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
+ "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/node": {
+ "version": "24.12.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
+ "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/react": {
+ "version": "19.2.14",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "csstype": "^3.2.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.2.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.0.tgz",
+ "integrity": "sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.12.2",
+ "@typescript-eslint/scope-manager": "8.58.0",
+ "@typescript-eslint/type-utils": "8.58.0",
+ "@typescript-eslint/utils": "8.58.0",
+ "@typescript-eslint/visitor-keys": "8.58.0",
+ "ignore": "^7.0.5",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.58.0",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.58.0.tgz",
+ "integrity": "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.58.0",
+ "@typescript-eslint/types": "8.58.0",
+ "@typescript-eslint/typescript-estree": "8.58.0",
+ "@typescript-eslint/visitor-keys": "8.58.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.0.tgz",
+ "integrity": "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.58.0",
+ "@typescript-eslint/types": "^8.58.0",
+ "debug": "^4.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.0.tgz",
+ "integrity": "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.58.0",
+ "@typescript-eslint/visitor-keys": "8.58.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.0.tgz",
+ "integrity": "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.58.0.tgz",
+ "integrity": "sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.58.0",
+ "@typescript-eslint/typescript-estree": "8.58.0",
+ "@typescript-eslint/utils": "8.58.0",
+ "debug": "^4.4.3",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.0.tgz",
+ "integrity": "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.0.tgz",
+ "integrity": "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.58.0",
+ "@typescript-eslint/tsconfig-utils": "8.58.0",
+ "@typescript-eslint/types": "8.58.0",
+ "@typescript-eslint/visitor-keys": "8.58.0",
+ "debug": "^4.4.3",
+ "minimatch": "^10.2.2",
+ "semver": "^7.7.3",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.5.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+ "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz",
+ "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "10.2.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
+ "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "brace-expansion": "^5.0.5"
+ },
+ "engines": {
+ "node": "18 || 20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.0.tgz",
+ "integrity": "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.9.1",
+ "@typescript-eslint/scope-manager": "8.58.0",
+ "@typescript-eslint/types": "8.58.0",
+ "@typescript-eslint/typescript-estree": "8.58.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.0.tgz",
+ "integrity": "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.58.0",
+ "eslint-visitor-keys": "^5.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz",
+ "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@rolldown/pluginutils": "1.0.0-rc.7"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "peerDependencies": {
+ "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
+ "babel-plugin-react-compiler": "^1.0.0",
+ "vite": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rolldown/plugin-babel": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
+ "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/babel-plugin-react-compiler": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz",
+ "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.26.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.15",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.15.tgz",
+ "integrity": "sha512-1nfKCq9wuAZFTkA2ey/3OXXx7GzFjLdkTiFVNwlJ9WqdI706CZRIhEqjuwanjMIja+84jDLa9rcyZDPDiVkASQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
+ "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.12",
+ "caniuse-lite": "^1.0.30001782",
+ "electron-to-chromium": "^1.5.328",
+ "node-releases": "^2.0.36",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001785",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001785.tgz",
+ "integrity": "sha512-blhOL/WNR+Km1RI/LCVAvA73xplXA7ZbjzI4YkMK9pa6T/P3F2GxjNpEkyw5repTw9IvkyrjyHpwjnhZ5FOvYQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.331",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.331.tgz",
+ "integrity": "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
+ "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz",
+ "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": "^9 || ^10"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "17.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz",
+ "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lightningcss": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
+ "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==",
+ "dev": true,
+ "license": "MPL-2.0",
+ "dependencies": {
+ "detect-libc": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "lightningcss-android-arm64": "1.32.0",
+ "lightningcss-darwin-arm64": "1.32.0",
+ "lightningcss-darwin-x64": "1.32.0",
+ "lightningcss-freebsd-x64": "1.32.0",
+ "lightningcss-linux-arm-gnueabihf": "1.32.0",
+ "lightningcss-linux-arm64-gnu": "1.32.0",
+ "lightningcss-linux-arm64-musl": "1.32.0",
+ "lightningcss-linux-x64-gnu": "1.32.0",
+ "lightningcss-linux-x64-musl": "1.32.0",
+ "lightningcss-win32-arm64-msvc": "1.32.0",
+ "lightningcss-win32-x64-msvc": "1.32.0"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz",
+ "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-arm64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz",
+ "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-darwin-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz",
+ "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-freebsd-x64": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz",
+ "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm-gnueabihf": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz",
+ "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz",
+ "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-arm64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz",
+ "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-gnu": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz",
+ "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-linux-x64-musl": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz",
+ "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-arm64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz",
+ "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/lightningcss-win32-x64-msvc": {
+ "version": "1.32.0",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz",
+ "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.37",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz",
+ "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.8",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
+ "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.2.4",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
+ "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+ "license": "MIT",
+ "dependencies": {
+ "scheduler": "^0.27.0"
+ },
+ "peerDependencies": {
+ "react": "^19.2.4"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/rolldown": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.13.tgz",
+ "integrity": "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@oxc-project/types": "=0.123.0",
+ "@rolldown/pluginutils": "1.0.0-rc.13"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.0.0-rc.13",
+ "@rolldown/binding-darwin-arm64": "1.0.0-rc.13",
+ "@rolldown/binding-darwin-x64": "1.0.0-rc.13",
+ "@rolldown/binding-freebsd-x64": "1.0.0-rc.13",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13",
+ "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13",
+ "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13",
+ "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13",
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13",
+ "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13",
+ "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13",
+ "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13",
+ "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13"
+ }
+ },
+ "node_modules/rolldown/node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.13",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.13.tgz",
+ "integrity": "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/scheduler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
+ "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "dev": true,
+ "license": "0BSD",
+ "optional": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-eslint": {
+ "version": "8.58.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.58.0.tgz",
+ "integrity": "sha512-e2TQzKfaI85fO+F3QywtX+tCTsu/D3WW5LVU6nz8hTFKFZ8yBJ6mSYRpXqdR3mFjPWmO0eWsTa5f+UpAOe/FMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.58.0",
+ "@typescript-eslint/parser": "8.58.0",
+ "@typescript-eslint/typescript-estree": "8.58.0",
+ "@typescript-eslint/utils": "8.58.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "typescript": ">=4.8.4 <6.1.0"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz",
+ "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "lightningcss": "^1.32.0",
+ "picomatch": "^4.0.4",
+ "postcss": "^8.5.8",
+ "rolldown": "1.0.0-rc.12",
+ "tinyglobby": "^0.2.15"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "@vitejs/devtools": "^0.1.0",
+ "esbuild": "^0.27.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "@vitejs/devtools": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite/node_modules/@oxc-project/types": {
+ "version": "0.122.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz",
+ "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-android-arm64": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz",
+ "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-darwin-arm64": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz",
+ "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-darwin-x64": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz",
+ "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-freebsd-x64": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz",
+ "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-linux-arm-gnueabihf": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz",
+ "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-gnu": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz",
+ "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-musl": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz",
+ "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-linux-ppc64-gnu": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz",
+ "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-linux-s390x-gnu": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz",
+ "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-linux-x64-gnu": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz",
+ "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-linux-x64-musl": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz",
+ "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-openharmony-arm64": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz",
+ "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-wasm32-wasi": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz",
+ "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-win32-arm64-msvc": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz",
+ "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/binding-win32-x64-msvc": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz",
+ "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/vite/node_modules/@rolldown/pluginutils": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz",
+ "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vite/node_modules/rolldown": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz",
+ "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oxc-project/types": "=0.122.0",
+ "@rolldown/pluginutils": "1.0.0-rc.12"
+ },
+ "bin": {
+ "rolldown": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "optionalDependencies": {
+ "@rolldown/binding-android-arm64": "1.0.0-rc.12",
+ "@rolldown/binding-darwin-arm64": "1.0.0-rc.12",
+ "@rolldown/binding-darwin-x64": "1.0.0-rc.12",
+ "@rolldown/binding-freebsd-x64": "1.0.0-rc.12",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12",
+ "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12",
+ "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12",
+ "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12",
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12",
+ "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12",
+ "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12",
+ "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12",
+ "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
+ "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-validation-error": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+ "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ }
+ }
+ }
+}
diff --git a/aljabar-projek/package.json b/aljabar-projek/package.json
new file mode 100644
index 0000000..4b007a7
--- /dev/null
+++ b/aljabar-projek/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "aljabar-projek",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "react": "^19.2.4",
+ "react-dom": "^19.2.4"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.29.0",
+ "@eslint/js": "^9.39.4",
+ "@rolldown/plugin-babel": "^0.2.1",
+ "@types/babel__core": "^7.20.5",
+ "@types/node": "^24.12.0",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^6.0.1",
+ "babel-plugin-react-compiler": "^1.0.0",
+ "eslint": "^9.39.4",
+ "eslint-plugin-react-hooks": "^7.0.1",
+ "eslint-plugin-react-refresh": "^0.5.2",
+ "globals": "^17.4.0",
+ "typescript": "~5.9.3",
+ "typescript-eslint": "^8.57.0",
+ "vite": "^8.0.1"
+ }
+}
diff --git a/aljabar-projek/public/favicon.svg b/aljabar-projek/public/favicon.svg
new file mode 100644
index 0000000..6893eb1
--- /dev/null
+++ b/aljabar-projek/public/favicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/aljabar-projek/public/icons.svg b/aljabar-projek/public/icons.svg
new file mode 100644
index 0000000..e952219
--- /dev/null
+++ b/aljabar-projek/public/icons.svg
@@ -0,0 +1,24 @@
+
diff --git a/aljabar-projek/src/App.css b/aljabar-projek/src/App.css
new file mode 100644
index 0000000..f90339d
--- /dev/null
+++ b/aljabar-projek/src/App.css
@@ -0,0 +1,184 @@
+.counter {
+ font-size: 16px;
+ padding: 5px 10px;
+ border-radius: 5px;
+ color: var(--accent);
+ background: var(--accent-bg);
+ border: 2px solid transparent;
+ transition: border-color 0.3s;
+ margin-bottom: 24px;
+
+ &:hover {
+ border-color: var(--accent-border);
+ }
+ &:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+ }
+}
+
+.hero {
+ position: relative;
+
+ .base,
+ .framework,
+ .vite {
+ inset-inline: 0;
+ margin: 0 auto;
+ }
+
+ .base {
+ width: 170px;
+ position: relative;
+ z-index: 0;
+ }
+
+ .framework,
+ .vite {
+ position: absolute;
+ }
+
+ .framework {
+ z-index: 1;
+ top: 34px;
+ height: 28px;
+ transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
+ scale(1.4);
+ }
+
+ .vite {
+ z-index: 0;
+ top: 107px;
+ height: 26px;
+ width: auto;
+ transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
+ scale(0.8);
+ }
+}
+
+#center {
+ display: flex;
+ flex-direction: column;
+ gap: 25px;
+ place-content: center;
+ place-items: center;
+ flex-grow: 1;
+
+ @media (max-width: 1024px) {
+ padding: 32px 20px 24px;
+ gap: 18px;
+ }
+}
+
+#next-steps {
+ display: flex;
+ border-top: 1px solid var(--border);
+ text-align: left;
+
+ & > div {
+ flex: 1 1 0;
+ padding: 32px;
+ @media (max-width: 1024px) {
+ padding: 24px 20px;
+ }
+ }
+
+ .icon {
+ margin-bottom: 16px;
+ width: 22px;
+ height: 22px;
+ }
+
+ @media (max-width: 1024px) {
+ flex-direction: column;
+ text-align: center;
+ }
+}
+
+#docs {
+ border-right: 1px solid var(--border);
+
+ @media (max-width: 1024px) {
+ border-right: none;
+ border-bottom: 1px solid var(--border);
+ }
+}
+
+#next-steps ul {
+ list-style: none;
+ padding: 0;
+ display: flex;
+ gap: 8px;
+ margin: 32px 0 0;
+
+ .logo {
+ height: 18px;
+ }
+
+ a {
+ color: var(--text-h);
+ font-size: 16px;
+ border-radius: 6px;
+ background: var(--social-bg);
+ display: flex;
+ padding: 6px 12px;
+ align-items: center;
+ gap: 8px;
+ text-decoration: none;
+ transition: box-shadow 0.3s;
+
+ &:hover {
+ box-shadow: var(--shadow);
+ }
+ .button-icon {
+ height: 18px;
+ width: 18px;
+ }
+ }
+
+ @media (max-width: 1024px) {
+ margin-top: 20px;
+ flex-wrap: wrap;
+ justify-content: center;
+
+ li {
+ flex: 1 1 calc(50% - 8px);
+ }
+
+ a {
+ width: 100%;
+ justify-content: center;
+ box-sizing: border-box;
+ }
+ }
+}
+
+#spacer {
+ height: 88px;
+ border-top: 1px solid var(--border);
+ @media (max-width: 1024px) {
+ height: 48px;
+ }
+}
+
+.ticks {
+ position: relative;
+ width: 100%;
+
+ &::before,
+ &::after {
+ content: '';
+ position: absolute;
+ top: -4.5px;
+ border: 5px solid transparent;
+ }
+
+ &::before {
+ left: 0;
+ border-left-color: var(--border);
+ }
+ &::after {
+ right: 0;
+ border-right-color: var(--border);
+ }
+}
diff --git a/aljabar-projek/src/App.tsx b/aljabar-projek/src/App.tsx
new file mode 100644
index 0000000..46a5992
--- /dev/null
+++ b/aljabar-projek/src/App.tsx
@@ -0,0 +1,121 @@
+import { useState } from 'react'
+import reactLogo from './assets/react.svg'
+import viteLogo from './assets/vite.svg'
+import heroImg from './assets/hero.png'
+import './App.css'
+
+function App() {
+ const [count, setCount] = useState(0)
+
+ return (
+ <>
+
+
+
+
Get started
+
+ Edit src/App.tsx and save to test HMR
+
+
+
+
+
+
+
+
+
+
+
Documentation
+
Your questions, answered
+
+
+
+
+
Connect with us
+
Join the Vite community
+
+
+
+
+
+
+ >
+ )
+}
+
+export default App
diff --git a/aljabar-projek/src/assets/hero.png b/aljabar-projek/src/assets/hero.png
new file mode 100644
index 0000000..cc51a3d
Binary files /dev/null and b/aljabar-projek/src/assets/hero.png differ
diff --git a/aljabar-projek/src/assets/react.svg b/aljabar-projek/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/aljabar-projek/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/aljabar-projek/src/assets/vite.svg b/aljabar-projek/src/assets/vite.svg
new file mode 100644
index 0000000..5101b67
--- /dev/null
+++ b/aljabar-projek/src/assets/vite.svg
@@ -0,0 +1 @@
+
diff --git a/aljabar-projek/src/index.css b/aljabar-projek/src/index.css
new file mode 100644
index 0000000..5fb3313
--- /dev/null
+++ b/aljabar-projek/src/index.css
@@ -0,0 +1,111 @@
+:root {
+ --text: #6b6375;
+ --text-h: #08060d;
+ --bg: #fff;
+ --border: #e5e4e7;
+ --code-bg: #f4f3ec;
+ --accent: #aa3bff;
+ --accent-bg: rgba(170, 59, 255, 0.1);
+ --accent-border: rgba(170, 59, 255, 0.5);
+ --social-bg: rgba(244, 243, 236, 0.5);
+ --shadow:
+ rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
+
+ --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
+ --heading: system-ui, 'Segoe UI', Roboto, sans-serif;
+ --mono: ui-monospace, Consolas, monospace;
+
+ font: 18px/145% var(--sans);
+ letter-spacing: 0.18px;
+ color-scheme: light dark;
+ color: var(--text);
+ background: var(--bg);
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+
+ @media (max-width: 1024px) {
+ font-size: 16px;
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --text: #9ca3af;
+ --text-h: #f3f4f6;
+ --bg: #16171d;
+ --border: #2e303a;
+ --code-bg: #1f2028;
+ --accent: #c084fc;
+ --accent-bg: rgba(192, 132, 252, 0.15);
+ --accent-border: rgba(192, 132, 252, 0.5);
+ --social-bg: rgba(47, 48, 58, 0.5);
+ --shadow:
+ rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
+ }
+
+ #social .button-icon {
+ filter: invert(1) brightness(2);
+ }
+}
+
+#root {
+ width: 1126px;
+ max-width: 100%;
+ margin: 0 auto;
+ text-align: center;
+ border-inline: 1px solid var(--border);
+ min-height: 100svh;
+ display: flex;
+ flex-direction: column;
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+}
+
+h1,
+h2 {
+ font-family: var(--heading);
+ font-weight: 500;
+ color: var(--text-h);
+}
+
+h1 {
+ font-size: 56px;
+ letter-spacing: -1.68px;
+ margin: 32px 0;
+ @media (max-width: 1024px) {
+ font-size: 36px;
+ margin: 20px 0;
+ }
+}
+h2 {
+ font-size: 24px;
+ line-height: 118%;
+ letter-spacing: -0.24px;
+ margin: 0 0 8px;
+ @media (max-width: 1024px) {
+ font-size: 20px;
+ }
+}
+p {
+ margin: 0;
+}
+
+code,
+.counter {
+ font-family: var(--mono);
+ display: inline-flex;
+ border-radius: 4px;
+ color: var(--text-h);
+}
+
+code {
+ font-size: 15px;
+ line-height: 135%;
+ padding: 4px 8px;
+ background: var(--code-bg);
+}
diff --git a/aljabar-projek/src/main.tsx b/aljabar-projek/src/main.tsx
new file mode 100644
index 0000000..bef5202
--- /dev/null
+++ b/aljabar-projek/src/main.tsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import './index.css'
+import App from './App.tsx'
+
+createRoot(document.getElementById('root')!).render(
+
+
+ ,
+)
diff --git a/aljabar-projek/tsconfig.app.json b/aljabar-projek/tsconfig.app.json
new file mode 100644
index 0000000..af516fc
--- /dev/null
+++ b/aljabar-projek/tsconfig.app.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2023",
+ "useDefineForClassFields": true,
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "types": ["vite/client"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/aljabar-projek/tsconfig.json b/aljabar-projek/tsconfig.json
new file mode 100644
index 0000000..1ffef60
--- /dev/null
+++ b/aljabar-projek/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/aljabar-projek/tsconfig.node.json b/aljabar-projek/tsconfig.node.json
new file mode 100644
index 0000000..8a67f62
--- /dev/null
+++ b/aljabar-projek/tsconfig.node.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2023",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "types": ["node"],
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/aljabar-projek/vite.config.ts b/aljabar-projek/vite.config.ts
new file mode 100644
index 0000000..d1203cd
--- /dev/null
+++ b/aljabar-projek/vite.config.ts
@@ -0,0 +1,11 @@
+import { defineConfig } from 'vite'
+import react, { reactCompilerPreset } from '@vitejs/plugin-react'
+import babel from '@rolldown/plugin-babel'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [
+ react(),
+ babel({ presets: [reactCompilerPreset()] })
+ ],
+})
diff --git a/frontend/aljabar.html b/frontend/aljabar.html
index 782c214..c7cf4d8 100644
--- a/frontend/aljabar.html
+++ b/frontend/aljabar.html
@@ -17,7 +17,7 @@
Masukkan soal (contoh: (x+2)^2 atau x^2-9):
-
+
diff --git a/node_modules/algebrite/package.json b/node_modules/algebrite/package.json
new file mode 100644
index 0000000..1957fd2
--- /dev/null
+++ b/node_modules/algebrite/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "algebrite",
+ "//": "also change the version in the Algebrite variable at the top of defs file",
+ "version": "1.4.0",
+ "description": "Computer Algebra System in Coffeescript",
+ "main": "dist/algebrite.js",
+ "directories": {
+ "test": "tests"
+ },
+ "scripts": {
+ "microtest": "cat runtime/defs.coffee sources/*.coffee runtime/alloc.coffee runtime/find.coffee runtime/init.coffee runtime/mcmp.coffee runtime/otherCFunctions.coffee runtime/count.coffee runtime/run.coffee runtime/stack.coffee runtime/symbol.coffee runtime/zombocom.coffee runtime/freeze.coffee test-harness.coffee run-micro-tests.coffee | coffee -cs | node",
+ "test": "cat runtime/defs.coffee sources/*.coffee runtime/alloc.coffee runtime/find.coffee runtime/init.coffee runtime/mcmp.coffee runtime/otherCFunctions.coffee runtime/count.coffee runtime/run.coffee runtime/stack.coffee runtime/symbol.coffee runtime/zombocom.coffee runtime/freeze.coffee tests/*.coffee test-harness.coffee run-tests.coffee | coffee -cs | node",
+ "build": "cat runtime/defs.coffee sources/*.coffee runtime/alloc.coffee runtime/find.coffee runtime/init.coffee runtime/mcmp.coffee runtime/otherCFunctions.coffee runtime/count.coffee runtime/run.coffee runtime/stack.coffee runtime/symbol.coffee runtime/zombocom.coffee runtime/freeze.coffee | coffee -sc > dist/algebrite.js",
+ "build-for-browser": "cat runtime/defs.coffee sources/*.coffee runtime/alloc.coffee runtime/find.coffee runtime/init.coffee runtime/mcmp.coffee runtime/otherCFunctions.coffee runtime/count.coffee runtime/run.coffee runtime/stack.coffee runtime/symbol.coffee runtime/zombocom.coffee runtime/freeze.coffee | coffee -sc > dist/algebrite.js; browserify ./sources/mainForWebPage.js -o ./dist/algebrite.bundle-for-browser.js",
+ "//": "this one is useful to check things quickly in the sandbox. Use after build-for-browser.",
+ "browser-tests": "cat runtime/defs.coffee sources/*.coffee runtime/alloc.coffee runtime/find.coffee runtime/init.coffee runtime/mcmp.coffee runtime/otherCFunctions.coffee runtime/count.coffee runtime/run.coffee runtime/stack.coffee runtime/symbol.coffee runtime/zombocom.coffee runtime/freeze.coffee tests/*.coffee test-harness.coffee run-tests.coffee | coffee -sc > dist/algebrite.js; browserify ./sources/mainForWebPage.js -o ./dist/algebrite.bundle-for-browser.js",
+ "copy-to-sandbox": "[ -d \"../Algebrite-website/\" ] && cp ./dist/algebrite.bundle-for-browser.js ../Algebrite-website/dist/ || echo \"Error: Algebrite-website directory not found, check the path in the package.json file\""
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/davidedc/Algebrite.git"
+ },
+ "keywords": [
+ "cas",
+ "algebra",
+ "computer",
+ "algebra",
+ "system",
+ "eigenmath",
+ "math",
+ "symbolic"
+ ],
+ "author": "Davide Della Casa",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/davidedc/Algebrite/issues"
+ },
+ "homepage": "https://github.com/davidedc/Algebrite#readme",
+ "dependencies": {
+ "big-integer": "^1.6.32"
+ }
+}
diff --git a/node_modules/algebrite/run-micro-tests.coffee b/node_modules/algebrite/run-micro-tests.coffee
new file mode 100644
index 0000000..4c2141e
--- /dev/null
+++ b/node_modules/algebrite/run-micro-tests.coffee
@@ -0,0 +1,13 @@
+
+
+# quick and dirty way to run a few tests
+
+run_test [
+
+ "1+1",
+ "2",
+
+]
+
+
+# alert "passed tests: " + ok_tests + " / failed tests: " + ko_tests
diff --git a/node_modules/algebrite/run-tests.coffee b/node_modules/algebrite/run-tests.coffee
new file mode 100644
index 0000000..4c88793
--- /dev/null
+++ b/node_modules/algebrite/run-tests.coffee
@@ -0,0 +1,130 @@
+# self test functions
+
+test_low_level = ->
+ run("clearall"); # to initialize stack and memory
+
+ if exec("factor","(x^2-1)").toString() == "(x-1)*(x+1)"
+ console.log "exec text ok"
+ else
+ console.log "exec text failed"
+
+ test_clearall()
+ test_inv()
+ test_printlatex()
+ test_mixedprint()
+ test_inner()
+ test_transpose()
+ test_signs_in_rationals()
+ test_madd()
+ test_msub()
+ test_mmul()
+ test_mdiv()
+ test_mmod()
+ test_mprime()
+ test_mgcd()
+ test_mpow()
+ test_mroot()
+ test_dependencies()
+ test_assignments()
+ test_strings()
+ test_test()
+ test_check()
+
+# use the window.selftest version
+# for running the tests from the
+# browser console ("run npm build-for-browser")
+#window.selftest = ->
+selftest = ->
+ test_low_level()
+ test_pattern()
+ test_abs()
+ test_sum()
+ test_product()
+ test_for()
+ test_exp()
+ test_expand()
+ test_factorpoly()
+ test_subst()
+ test_simplify()
+
+ test_multiply()
+ test_scan()
+ test_power()
+ test_factor_number(); # long
+ test_tensor()
+ test_bake()
+ test_adj()
+ test_arg()
+ test_approxratio()
+ test_besselj()
+ test_bessely()
+ test_ceiling()
+ test_choose()
+ test_circexp()
+ test_clock()
+ test_cofactor()
+ test_condense()
+ test_contract()
+ test_defint(); # very long
+ test_denominator()
+ test_derivative()
+ test_dirac()
+ test_erf()
+ test_erfc()
+ test_expcos()
+ test_expsin()
+ test_float()
+ test_floor()
+ test_gamma()
+ test_gcd()
+ test_imag()
+ test_lcm()
+ test_log()
+ test_mod()
+ test_nroots()
+ test_numerator()
+ test_outer()
+ test_polar()
+ test_quotient()
+ test_rationalize()
+ test_real()
+ test_rect()
+ test_round()
+ test_sgn()
+ test_taylor()
+ test_zero()
+ test_hermite()
+ test_laguerre()
+ test_legendre()
+ test_binomial()
+ test_divisors()
+ test_coeff()
+ test_sin()
+ test_cos()
+ test_tan()
+ test_sinh()
+ test_cosh()
+ test_tanh()
+ test_arcsin()
+ test_arcsinh()
+ test_arccos()
+ test_arccosh()
+ test_arctan()
+ test_arctanh()
+ test_index()
+ test_isprime()
+ test_eigen()
+ test_shape()
+ mini_test()
+ test_quickfactor()
+ test_integral()
+ test_roots()
+
+
+ # alert "passed tests: " + ok_tests + " / failed tests: " + ko_tests
+ return
+
+# remove this selftest()
+# for running the tests from the
+# browser console ("run npm build-for-browser")
+selftest()
diff --git a/node_modules/algebrite/runtime/alloc.coffee b/node_modules/algebrite/runtime/alloc.coffee
new file mode 100644
index 0000000..6701f3f
--- /dev/null
+++ b/node_modules/algebrite/runtime/alloc.coffee
@@ -0,0 +1,194 @@
+
+
+###
+// up to 100 blocks of 100,000 atoms
+
+#define M 100
+#define N 100000
+
+U *mem[M]
+int mcount
+
+U *free_list
+int free_count
+
+U *
+alloc(void)
+{
+ U *p
+ if (free_count == 0) {
+ if (mcount == 0)
+ alloc_mem()
+ else {
+ gc()
+ if (free_count < N * mcount / 2)
+ alloc_mem()
+ }
+ if (free_count == 0)
+ stop("atom space exhausted")
+ }
+ p = free_list
+ free_list = free_list->u.cons.cdr
+ free_count--
+ return p
+}
+###
+
+allocatedId = 0
+alloc_tensor = (nelem) ->
+ i = 0
+ p = new U()
+ p.k = TENSOR
+ p.tensor = new tensor()
+
+ p.tensor.nelem = nelem
+ for i in [0...nelem]
+ p.tensor.elem[i] = zero
+
+ p.tensor.allocatedId = allocatedId
+ #if allocatedId == 9
+ # debugger
+ allocatedId++
+
+ check_tensor_dimensions p
+
+ return p
+
+###
+// garbage collector
+
+void
+gc(void)
+{
+ int i, j
+ U *p
+
+ // tag everything
+
+ for (i = 0; i < mcount; i++) {
+ p = mem[i]
+ for (j = 0; j < N; j++)
+ p[j].tag = 1
+ }
+
+ // untag what's used
+
+ untag(p0)
+ untag(p1)
+ untag(p2)
+ untag(p3)
+ untag(p4)
+ untag(p5)
+ untag(p6)
+ untag(p7)
+ untag(p8)
+ untag(p9)
+
+ untag(one)
+ untag(zero)
+ untag(imaginaryunit)
+
+ for (i = 0; i < NSYM; i++) {
+ untag(binding[i])
+ untag(arglist[i])
+ }
+
+ for (i = 0; i < tos; i++)
+ untag(stack[i])
+
+ for (i = (int) (frame - stack); i < TOS; i++)
+ untag(stack[i])
+
+ // collect everything that's still tagged
+
+ free_count = 0
+
+ for (i = 0; i < mcount; i++) {
+ p = mem[i]
+ for (j = 0; j < N; j++) {
+ if (p[j].tag == 0)
+ continue
+ // still tagged so it's unused, put on free list
+ switch (p[j].k) {
+ case TENSOR:
+ free(p[j].u.tensor)
+ break
+ case STR:
+ free(p[j].u.str)
+ break
+ case NUM:
+ mfree(p[j].u.q.a)
+ mfree(p[j].u.q.b)
+ break
+ }
+ p[j].k = CONS; // so no double free occurs above
+ p[j].u.cons.cdr = free_list
+ free_list = p + j
+ free_count++
+ }
+ }
+}
+
+void
+untag(U *p)
+{
+ int i
+
+ if (iscons(p)) {
+ do {
+ if (p->tag == 0)
+ return
+ p->tag = 0
+ untag(p->u.cons.car)
+ p = p->u.cons.cdr
+ } while (iscons(p))
+ untag(p)
+ return
+ }
+
+ if (p->tag) {
+ p->tag = 0
+ if (istensor(p)) {
+ for (i = 0; i < p->u.tensor->nelem; i++)
+ untag(p->u.tensor->elem[i])
+ }
+ }
+}
+
+// get memory for 100,000 atoms
+
+void
+alloc_mem(void)
+{
+ int i
+ U *p
+ if (mcount == M)
+ return
+ p = (U *) malloc(N * sizeof (struct U))
+ if (p == NULL)
+ return
+ mem[mcount++] = p
+ for (i = 0; i < N; i++) {
+ p[i].k = CONS; // so no free in gc
+ p[i].u.cons.cdr = p + i + 1
+ }
+ p[N - 1].u.cons.cdr = free_list
+ free_list = p
+ free_count += N
+}
+
+void
+print_mem_info(void)
+{
+ char buf[100]
+
+ sprintf(buf, "%d blocks (%d bytes/block)\n", N * mcount, (int) sizeof (U))
+ printstr(buf)
+
+ sprintf(buf, "%d free\n", free_count)
+ printstr(buf)
+
+ sprintf(buf, "%d used\n", N * mcount - free_count)
+ printstr(buf)
+}
+###
diff --git a/node_modules/algebrite/runtime/count.coffee b/node_modules/algebrite/runtime/count.coffee
new file mode 100644
index 0000000..d51fff2
--- /dev/null
+++ b/node_modules/algebrite/runtime/count.coffee
@@ -0,0 +1,43 @@
+count = (p) ->
+ if (iscons(p))
+ n = 0
+ while (iscons(p))
+ n += count(car(p)) + 1
+ p = cdr(p)
+ else
+ n = 1
+ return n
+
+# this probably works out to be
+# more general than just counting symbols, it can
+# probably count instances of anything you pass as
+# first argument but didn't try it.
+countOccurrencesOfSymbol = (needle,p) ->
+ n = 0
+ if (iscons(p))
+ while (iscons(p))
+ n += countOccurrencesOfSymbol(needle,car(p))
+ p = cdr(p)
+ else
+ if equal(needle,p)
+ n = 1
+ return n
+
+
+# returns the total number of elements
+# in an expression
+countsize = (p) ->
+ n = 0
+
+ if (istensor(p))
+ for i in [0...p.tensor.nelem]
+ n += p.tensor.elem[i]
+ else if (iscons(p))
+ while (iscons(p))
+ n += count(car(p)) + 1
+ p = cdr(p)
+ else
+ n = 1
+
+ return n
+
diff --git a/node_modules/algebrite/runtime/defs.coffee b/node_modules/algebrite/runtime/defs.coffee
new file mode 100644
index 0000000..c8717f5
--- /dev/null
+++ b/node_modules/algebrite/runtime/defs.coffee
@@ -0,0 +1,630 @@
+bigInt = require('big-integer')
+
+# also change the version in the package.json file
+version = "1.4.0"
+
+SELFTEST = 1
+
+
+# size of the symbol table
+NSYM = 1000
+
+DEBUG = false
+PRINTOUTRESULT = false
+
+# printing-related constants
+PRINTMODE_LATEX = "PRINTMODE_LATEX"
+PRINTMODE_2DASCII = "PRINTMODE_2DASCII"
+PRINTMODE_COMPUTER = "PRINTMODE_COMPUTER"
+PRINTMODE_HUMAN = "PRINTMODE_HUMAN"
+PRINTMODE_LIST = "PRINTMODE_LIST"
+
+# when the user uses the generic "print" statement
+# this setting kicks-in.
+printMode = PRINTMODE_COMPUTER
+
+dontCreateNewRadicalsInDenominatorWhenEvalingMultiplication = true
+recursionLevelNestedRadicalsRemoval = 0
+do_simplify_nested_radicals = true
+avoidCalculatingPowersIntoArctans = true
+
+# Symbolic expressions are built by connecting U structs.
+#
+# For example, (a b + c) is built like this:
+#
+# _______ _______ _______
+# |CONS |--->|CONS |----------------------------->|CONS |
+# | | | | | |
+# |_______| |_______| |_______|
+# | | |
+# ___v___ ___v___ _______ _______ ___v___
+# |ADD | |CONS |--->|CONS |--->|CONS | |SYM c |
+# | | | | | | | | | |
+# |_______| |_______| |_______| |_______| |_______|
+# | | |
+# ___v___ ___v___ ___v___
+# |MUL | |SYM a | |SYM b |
+# | | | | | |
+# |_______| |_______| |_______|
+
+
+
+class rational
+ a: null # a bigInteger
+ b: null # a bigInteger
+
+class U
+ cons: null # will have a car and cdr
+ printname: ""
+ str: ""
+ tensor: null
+ # rational number a over b
+ q: null # will point to a rational
+ d: 0.0 # a double
+ k: 0
+ tag: 0
+
+ toString: -> print_expr(this)
+ toLatexString: -> collectLatexStringFromReturnValue(this)
+
+ constructor: ->
+ @cons = {}
+ @cons.car = null
+ @cons.cdr = null
+ @q = new rational()
+
+
+errorMessage = ""
+
+
+# the following enum is for struct U, member k
+
+CONS = 0
+NUM = 1
+DOUBLE = 2
+STR = 3
+TENSOR = 4
+SYM = 5
+
+# the following enum is for indexing the symbol table
+
+# standard functions first, then nil, then everything else
+
+counter = 0
+ABS = counter++
+ADD = counter++
+ADJ = counter++
+AND = counter++
+APPROXRATIO = counter++
+ARCCOS = counter++
+ARCCOSH = counter++
+ARCSIN = counter++
+ARCSINH = counter++
+ARCTAN = counter++
+ARCTANH = counter++
+ARG = counter++
+ATOMIZE = counter++
+BESSELJ = counter++
+BESSELY = counter++
+BINDING = counter++
+BINOMIAL = counter++
+CEILING = counter++
+CHECK = counter++
+CHOOSE = counter++
+CIRCEXP = counter++
+CLEAR = counter++
+CLEARALL = counter++
+CLEARPATTERNS = counter++
+CLOCK = counter++
+COEFF = counter++
+COFACTOR = counter++
+CONDENSE = counter++
+CONJ = counter++
+CONTRACT = counter++
+COS = counter++
+COSH = counter++
+DECOMP = counter++
+DEFINT = counter++
+DEGREE = counter++
+DENOMINATOR = counter++
+DERIVATIVE = counter++
+DET = counter++
+DIM = counter++
+DIRAC = counter++
+DIVISORS = counter++
+DO = counter++
+DOT = counter++
+DRAW = counter++
+DSOLVE = counter++
+EIGEN = counter++
+EIGENVAL = counter++
+EIGENVEC = counter++
+ERF = counter++
+ERFC = counter++
+EVAL = counter++
+EXP = counter++
+EXPAND = counter++
+EXPCOS = counter++
+EXPSIN = counter++
+FACTOR = counter++
+FACTORIAL = counter++
+FACTORPOLY = counter++
+FILTER = counter++
+FLOATF = counter++
+FLOOR = counter++
+FOR = counter++
+FUNCTION = counter++
+GAMMA = counter++
+GCD = counter++
+HERMITE = counter++
+HILBERT = counter++
+IMAG = counter++
+INDEX = counter++
+INNER = counter++
+INTEGRAL = counter++
+INV = counter++
+INVG = counter++
+ISINTEGER = counter++
+ISPRIME = counter++
+LAGUERRE = counter++
+# LAPLACE = counter++
+LCM = counter++
+LEADING = counter++
+LEGENDRE = counter++
+LOG = counter++
+LOOKUP = counter++
+MOD = counter++
+MULTIPLY = counter++
+NOT = counter++
+NROOTS = counter++
+NUMBER = counter++
+NUMERATOR = counter++
+OPERATOR = counter++
+OR = counter++
+OUTER = counter++
+PATTERN = counter++
+PATTERNSINFO = counter++
+POLAR = counter++
+POWER = counter++
+PRIME = counter++
+PRINT_LEAVE_E_ALONE = counter++
+PRINT_LEAVE_X_ALONE = counter++
+PRINT = counter++
+PRINT2DASCII = counter++
+PRINTFULL = counter++
+PRINTLATEX = counter++
+PRINTLIST = counter++
+PRINTPLAIN = counter++
+PRODUCT = counter++
+QUOTE = counter++
+QUOTIENT = counter++
+RANK = counter++
+RATIONALIZE = counter++
+REAL = counter++
+ROUND = counter++
+YYRECT = counter++
+ROOTS = counter++
+SETQ = counter++
+SGN = counter++
+SILENTPATTERN = counter++
+SIMPLIFY = counter++
+SIN = counter++
+SINH = counter++
+SHAPE = counter++
+SQRT = counter++
+STOP = counter++
+SUBST = counter++
+SUM = counter++
+SYMBOLSINFO = counter++
+TAN = counter++
+TANH = counter++
+TAYLOR = counter++
+TEST = counter++
+TESTEQ = counter++
+TESTGE = counter++
+TESTGT = counter++
+TESTLE = counter++
+TESTLT = counter++
+TRANSPOSE = counter++
+UNIT = counter++
+ZERO = counter++
+
+# ALL THE SYMBOLS ABOVE NIL ARE KEYWORDS,
+# WHICH MEANS THAT USER CANNOT REDEFINE THEM
+NIL = counter++ # nil goes here, after standard functions
+LAST = counter++
+
+LAST_PRINT = counter++
+LAST_2DASCII_PRINT = counter++
+LAST_FULL_PRINT = counter++
+LAST_LATEX_PRINT = counter++
+LAST_LIST_PRINT = counter++
+LAST_PLAIN_PRINT = counter++
+
+AUTOEXPAND = counter++
+BAKE = counter++
+ASSUME_REAL_VARIABLES = counter++
+TRACE = counter++
+FORCE_FIXED_PRINTOUT = counter++
+MAX_FIXED_PRINTOUT_DIGITS = counter++
+
+YYE = counter++
+
+DRAWX = counter++ # special purpose internal symbols
+METAA = counter++
+METAB = counter++
+METAX = counter++
+SECRETX = counter++
+
+VERSION = counter++
+
+PI = counter++
+SYMBOL_A = counter++
+SYMBOL_B = counter++
+SYMBOL_C = counter++
+SYMBOL_D = counter++
+SYMBOL_I = counter++
+SYMBOL_J = counter++
+SYMBOL_N = counter++
+SYMBOL_R = counter++
+SYMBOL_S = counter++
+SYMBOL_T = counter++
+SYMBOL_X = counter++
+SYMBOL_Y = counter++
+SYMBOL_Z = counter++
+SYMBOL_IDENTITY_MATRIX = counter++
+
+SYMBOL_A_UNDERSCORE = counter++
+SYMBOL_B_UNDERSCORE = counter++
+SYMBOL_X_UNDERSCORE = counter++
+
+C1 = counter++
+C2 = counter++
+C3 = counter++
+C4 = counter++
+C5 = counter++
+C6 = counter++
+
+USR_SYMBOLS = counter++ # this must be last
+
+E = YYE
+
+# TOS cannot be arbitrarily large because the OS seg faults on deep recursion.
+# For example, a circular evaluation like x=x+1 can cause a seg fault.
+# At this setting (100,000) the evaluation stack overruns before seg fault.
+
+TOS = 100000
+
+BUF = 10000
+
+MAX_PROGRAM_SIZE = 100001
+MAXPRIMETAB = 10000
+MAX_CONSECUTIVE_APPLICATIONS_OF_ALL_RULES = 5
+MAX_CONSECUTIVE_APPLICATIONS_OF_SINGLE_RULE = 10
+
+#define _USE_MATH_DEFINES // for MS C++
+
+MAXDIM = 24
+
+# needed for the mechanism to
+# find all dependencies between variables
+# in a script
+symbolsDependencies = {}
+symbolsHavingReassignments = []
+symbolsInExpressionsWithoutAssignments = []
+patternHasBeenFound = false
+
+predefinedSymbolsInGlobalScope_doNotTrackInDependencies = [
+ "rationalize"
+ "abs"
+ "e"
+ "i"
+ "pi"
+ "sin"
+ "ceiling"
+ "cos"
+ "roots"
+ "integral"
+ "derivative"
+ "defint"
+ "sqrt"
+ "eig"
+ "cov"
+ "deig"
+ "dcov"
+ "float"
+ "floor"
+ "product"
+ "root"
+ "round"
+ "sum"
+ "test"
+ "unit"
+]
+
+# you can do some little simplifications
+# at parse time, such as calculating away
+# immediately simple operations on
+# constants, removing 1s from products
+# etc.
+parse_time_simplifications = true
+
+chainOfUserSymbolsNotFunctionsBeingEvaluated = []
+
+stringsEmittedByUserPrintouts = ""
+
+# flag use to potentially switch on/off some quirks "deep"
+# in the code due to call from Algebra block.
+# Currently not used.
+called_from_Algebra_block = false
+
+
+class tensor
+ ndim: 0 # number of dimensions
+ dim: null # dimension length, for each dimension
+ nelem: 0 # total number of elements
+ elem: null # an array containing all the data
+
+ constructor: ->
+ @dim = (0 for [0..MAXDIM])
+ @elem = []
+
+
+class display
+ h: 0
+ w: 0
+ n: 0
+ a: [] # will contain an array of c,x,y (color,x,y)
+
+
+class text_metric
+ ascent: 0
+ descent: 0
+ width: 0
+
+
+tos = 0 # top of stack
+expanding = 0
+evaluatingAsFloats = 0
+evaluatingPolar = 0
+fmt_x = 0
+fmt_index = 0
+fmt_level = 0
+verbosing = 0
+
+
+
+primetab = do ->
+ primes = [2]
+ i = 3
+ while primes.length < MAXPRIMETAB
+ j = 0
+ ceil = Math.sqrt(i)
+ while j < primes.length and primes[j] <= ceil
+ if i % primes[j] == 0
+ j = -1
+ break
+ j++
+ if j != -1
+ primes.push(i)
+ i += 2
+ primes[MAXPRIMETAB] = 0
+ return primes
+
+
+
+esc_flag = 0
+draw_flag = 0
+mtotal = 0
+trigmode = 0
+logbuf = ""
+program_buf = ""
+
+# will contain the variable names
+symtab = []
+# will contain the contents of the variable
+# in the corresponding position in symtab array
+binding = []
+isSymbolReclaimable = []
+
+arglist = [] # will contain U
+stack = [] # will contain *U
+frame = 0
+p0 = null # will contain U
+p1 = null # will contain U
+p2 = null # will contain U
+p3 = null # will contain U
+p4 = null # will contain U
+p5 = null # will contain U
+p6 = null # will contain U
+p7 = null # will contain U
+p8 = null # will contain U
+p9 = null # will contain U
+
+zero = null # will contain U
+one = null # will contain U
+one_as_double = null
+imaginaryunit = null # will contain U
+
+out_buf = ""
+out_count = 0
+test_flag = 0
+codeGen = false
+draw_stop_return = null # extern jmp_buf ?????
+userSimplificationsInListForm = []
+userSimplificationsInStringForm = []
+
+transpose_unicode = 7488
+dotprod_unicode = 183
+
+symbol = (x) -> (symtab[x])
+iscons = (p) -> (p.k == CONS)
+isrational = (p) -> (p.k == NUM)
+isdouble = (p) -> (p.k == DOUBLE)
+isNumericAtom = (p) -> (isrational(p) || isdouble(p))
+isstr = (p) -> (p.k == STR)
+istensor = (p) -> (if !p? then debugger else p.k == TENSOR)
+
+
+# because of recursion, we consider a scalar to be
+# a tensor, so a numeric scalar will return true
+isNumericAtomOrTensor = (p) ->
+ if isNumericAtom(p) or p == symbol(SYMBOL_IDENTITY_MATRIX)
+ return 1
+
+ if !istensor(p) and !isNumericAtom(p)
+ #console.log "p not an atom nor a tensor: " + p
+ return 0
+
+ n = p.tensor.nelem
+ a = p.tensor.elem
+
+ for i in [0...n]
+ if !isNumericAtomOrTensor(a[i])
+ #console.log "non-numeric element: " + a[i]
+ return 0
+ return 1
+
+issymbol = (p) -> (p.k == SYM)
+iskeyword = (p) -> (issymbol(p) && symnum(p) < NIL)
+
+car = (p) -> if iscons(p) then p.cons.car else symbol(NIL)
+cdr = (p) -> if iscons(p) then p.cons.cdr else symbol(NIL)
+caar = (p) -> car(car(p))
+cadr = (p) -> car(cdr(p))
+cdar = (p) -> cdr(car(p))
+cddr = (p) -> cdr(cdr(p))
+caadr = (p) -> car(car(cdr(p)))
+caddr = (p) -> car(cdr(cdr(p)))
+cadar = (p) -> car(cdr(car(p)))
+cdadr = (p) -> cdr(car(cdr(p)))
+cddar = (p) -> cdr(cdr(car(p)))
+cdddr = (p) -> cdr(cdr(cdr(p)))
+caaddr = (p) -> car(car(cdr(cdr(p))))
+cadadr = (p) -> car(cdr(car(cdr(p))))
+caddar = (p) -> car(cdr(cdr(car(p))))
+cdaddr = (p) -> cdr(car(cdr(cdr(p))))
+cadddr = (p) -> car(cdr(cdr(cdr(p))))
+cddddr = (p) -> cdr(cdr(cdr(cdr(p))))
+caddddr = (p) -> car(cdr(cdr(cdr(cdr(p)))))
+cadaddr = (p) -> car(cdr(car(cdr(cdr(p)))))
+cddaddr = (p) -> cdr(cdr(car(cdr(cdr(p)))))
+caddadr = (p) -> car(cdr(cdr(car(cdr(p)))))
+cdddaddr = (p) -> cdr(cdr(cdr(car(cdr(cdr(p))))))
+caddaddr = (p) -> car(cdr(cdr(car(cdr(cdr(p))))))
+
+# not used yet
+listLength = (p) ->
+ startCount = -1
+
+ while iscons(p)
+ p = cdr(p)
+ startCount++
+
+ return startCount
+
+# not used yet
+nthCadr = (p,n) ->
+ startCount = 0
+
+ while startCount <= n
+ p = cdr(p)
+ startCount++
+
+ return car(p)
+
+isadd = (p) -> (car(p) == symbol(ADD))
+ismultiply = (p) -> (car(p) == symbol(MULTIPLY))
+ispower = (p) -> (car(p) == symbol(POWER))
+isfactorial = (p) -> (car(p) == symbol(FACTORIAL))
+isinnerordot = (p) -> ((car(p) == symbol(INNER)) or (car(p) == symbol(DOT)))
+istranspose = (p) -> (car(p) == symbol(TRANSPOSE))
+isinv = (p) -> (car(p) == symbol(INV))
+# TODO this is a bit of a shallow check, we should
+# check when we are passed an actual tensor and possibly
+# cache the test result.
+isidentitymatrix = (p) -> (p == symbol(SYMBOL_IDENTITY_MATRIX))
+
+MSIGN = (p) ->
+ if p.isPositive()
+ return 1
+ else if p.isZero()
+ return 0
+ else
+ return -1
+
+MLENGTH = (p) -> p.toString().length
+
+MZERO = (p) -> p.isZero()
+MEQUAL = (p, n) ->
+ if !p?
+ debugger
+ p.equals(n)
+
+
+reset_after_error = ->
+ moveTos 0
+ esc_flag = 0
+ draw_flag = 0
+ frame = TOS
+ evaluatingAsFloats = 0
+ evaluatingPolar = 0
+
+
+$ = (exports ? this)
+
+$.version = version
+
+$.isadd = isadd
+$.ismultiply = ismultiply
+$.ispower = ispower
+$.isfactorial = isfactorial
+
+
+
+$.car = car
+$.cdr = cdr
+$.caar = caar
+$.cadr = cadr
+$.cdar = cdar
+$.cddr = cddr
+$.caadr = caadr
+$.caddr = caddr
+$.cadar = cadar
+$.cdadr = cdadr
+$.cddar = cddar
+$.cdddr = cdddr
+$.caaddr = caaddr
+$.cadadr = cadadr
+$.caddar = caddar
+$.cdaddr = cdaddr
+$.cadddr = cadddr
+$.cddddr = cddddr
+$.caddddr = caddddr
+$.cadaddr = cadaddr
+$.cddaddr = cddaddr
+$.caddadr = caddadr
+$.cdddaddr = cdddaddr
+$.caddaddr = caddaddr
+
+
+
+$.symbol = symbol
+$.iscons = iscons
+$.isrational = isrational
+$.isdouble = isdouble
+$.isNumericAtom = isNumericAtom
+$.isstr = isstr
+$.istensor = istensor
+$.issymbol = issymbol
+$.iskeyword = iskeyword
+
+
+
+
+$.CONS = CONS
+$.NUM = NUM
+$.DOUBLE = DOUBLE
+$.STR = STR
+$.TENSOR = TENSOR
+$.SYM = SYM
diff --git a/node_modules/algebrite/runtime/find.coffee b/node_modules/algebrite/runtime/find.coffee
new file mode 100644
index 0000000..d4c950c
--- /dev/null
+++ b/node_modules/algebrite/runtime/find.coffee
@@ -0,0 +1,76 @@
+# returns 1 if expr p contains expr q, otherweise returns 0
+
+
+
+Find = (p, q) ->
+
+ i = 0
+ if (equal(p, q))
+ return 1
+
+ if (istensor(p))
+ for i in [0...p.tensor.nelem]
+ if (Find(p.tensor.elem[i], q))
+ return 1
+ return 0
+
+ while (iscons(p))
+ if (Find(car(p), q))
+ return 1
+ p = cdr(p)
+
+ return 0
+
+# find stuff like (-1)^(something (but disregard
+# imaginary units which are in the form (-1)^(1/2))
+findPossibleClockForm = (p) ->
+
+ i = 0
+
+ if isimaginaryunit(p)
+ return 0
+
+ if (car(p) == symbol(POWER) and !isinteger(caddr(p1)))
+ if Find(cadr(p), imaginaryunit)
+ #console.log "found i^fraction " + p
+ return 1
+
+ if (car(p) == symbol(POWER) && equaln(cadr(p), -1) && !isinteger(caddr(p1)))
+ #console.log "found -1^fraction in " + p
+ return 1
+
+ if (istensor(p))
+ for i in [0...p.tensor.nelem]
+ if (findPossibleClockForm(p.tensor.elem[i]))
+ return 1
+ return 0
+
+ while (iscons(p))
+ if (findPossibleClockForm(car(p)))
+ return 1
+ p = cdr(p)
+
+ return 0
+
+# find stuff like (e)^(i something)
+findPossibleExponentialForm = (p) ->
+
+ i = 0
+
+ if car(p) == symbol(POWER) && cadr(p)== symbol(E)
+ return Find(caddr(p),imaginaryunit)
+
+ if (istensor(p))
+ for i in [0...p.tensor.nelem]
+ if (findPossibleExponentialForm(p.tensor.elem[i]))
+ return 1
+ return 0
+
+ while (iscons(p))
+ if (findPossibleExponentialForm(car(p)))
+ return 1
+ p = cdr(p)
+
+ return 0
+
+$.Find = Find
\ No newline at end of file
diff --git a/node_modules/algebrite/runtime/freeze.coffee b/node_modules/algebrite/runtime/freeze.coffee
new file mode 100644
index 0000000..dfe3fc4
--- /dev/null
+++ b/node_modules/algebrite/runtime/freeze.coffee
@@ -0,0 +1,65 @@
+
+freeze = ->
+
+ frozenSymbols = []
+ frozenContents = []
+ frozenPatterns = []
+ frozenHash = ""
+
+ for i in [0...symtab.length]
+ #if symtab[i].printname == ""
+ # if isSymbolReclaimable[i] == false
+ # break
+ # else
+ # continue
+ if isSymbolReclaimable[i] == false
+ frozenSymbols.push symtab[i]
+ frozenContents.push binding[i]
+
+ # just clone them
+ frozenPatterns= userSimplificationsInListForm.slice(0)
+
+ return [frozenSymbols, frozenContents, frozenPatterns, zero, one, imaginaryunit, getStateHash()]
+
+unfreeze = (frozen) ->
+ [frozenSymbols, frozenContents, frozenPatterns, zero, one, imaginaryunit ] = frozen
+
+ #clear_symbols()
+
+ for i in [0...frozenSymbols.length]
+ symtab[i] = frozenSymbols[i]
+ binding[i] = frozenContents[i]
+
+ userSimplificationsInListForm = frozenPatterns.slice(0)
+
+
+compareState = (previousHash) ->
+
+ frozenHash = getStateHash()
+
+ if frozenHash == previousHash
+ return true
+ else
+ return false
+
+getStateHash = ->
+ frozenHash = ""
+
+ for i in [NIL+1...symtab.length]
+ if symtab[i].printname == ""
+ if isSymbolReclaimable[i] == false
+ break
+ else
+ continue
+
+ symtabi = print_list(symtab[i])
+ bindingi = print_list(binding[i])
+
+ frozenHash += " //" + symtabi + " : " + bindingi
+
+ for i in userSimplificationsInListForm
+ frozenHash += " pattern: " + i
+
+
+ if DEBUG then console.log "frozenHash: " + frozenHash
+ return frozenHash
diff --git a/node_modules/algebrite/runtime/init.coffee b/node_modules/algebrite/runtime/init.coffee
new file mode 100644
index 0000000..63f4ef1
--- /dev/null
+++ b/node_modules/algebrite/runtime/init.coffee
@@ -0,0 +1,334 @@
+
+
+init = ->
+ #debugger
+ #console.log "DOING AN INIT ========================================================================"
+ i = 0
+ flag = 0
+
+ reset_after_error()
+ chainOfUserSymbolsNotFunctionsBeingEvaluated = []
+
+ if (flag)
+ return # already initted
+
+ flag = 1
+
+
+ # total clearout of symbol table
+ for i in [0...NSYM]
+ symtab[i] = new U()
+ symtab[i].k = SYM
+ binding[i] = symtab[i]
+ isSymbolReclaimable[i] = false
+
+ defn()
+
+### cross =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept, script_defined
+
+Parameters
+----------
+u,v
+
+General description
+-------------------
+Returns the cross product of vectors u and v.
+
+###
+
+### curl =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept, script_defined
+
+Parameters
+----------
+u
+
+General description
+-------------------
+Returns the curl of vector u.
+
+###
+
+defn_str = [
+ "version=\"" + version + "\"",
+ "e=exp(1)",
+ "i=sqrt(-1)",
+ "autoexpand=1",
+ "assumeRealVariables=1",
+ "trange=[-pi,pi]",
+ "xrange=[-10,10]",
+ "yrange=[-10,10]",
+ "last=0",
+ "trace=0",
+ "forceFixedPrintout=1",
+ "maxFixedPrintoutDigits=6",
+ "printLeaveEAlone=1",
+ "printLeaveXAlone=0",
+ # cross definition
+ "cross(u,v)=[u[2]*v[3]-u[3]*v[2],u[3]*v[1]-u[1]*v[3],u[1]*v[2]-u[2]*v[1]]",
+ # curl definition
+ "curl(v)=[d(v[3],y)-d(v[2],z),d(v[1],z)-d(v[3],x),d(v[2],x)-d(v[1],y)]",
+ # div definition
+ "div(v)=d(v[1],x)+d(v[2],y)+d(v[3],z)",
+ # Note that we use the mathematics / Javascript / Mathematica
+ # convention that "log" is indeed the natural logarithm.
+ #
+ # In engineering, biology, astronomy, "log" can stand instead
+ # for the "common" logarithm i.e. base 10. Also note that Google
+ # calculations use log for the common logarithm.
+ "ln(x)=log(x)",
+]
+
+defn = ->
+ p0 = symbol(NIL)
+ p1 = symbol(NIL)
+ p2 = symbol(NIL)
+ p3 = symbol(NIL)
+ p4 = symbol(NIL)
+ p5 = symbol(NIL)
+ p6 = symbol(NIL)
+ p7 = symbol(NIL)
+ p8 = symbol(NIL)
+ p9 = symbol(NIL)
+
+ std_symbol("abs", ABS)
+ std_symbol("add", ADD)
+ std_symbol("adj", ADJ)
+ std_symbol("and", AND)
+ std_symbol("approxratio", APPROXRATIO)
+ std_symbol("arccos", ARCCOS)
+ std_symbol("arccosh", ARCCOSH)
+ std_symbol("arcsin", ARCSIN)
+ std_symbol("arcsinh", ARCSINH)
+ std_symbol("arctan", ARCTAN)
+ std_symbol("arctanh", ARCTANH)
+ std_symbol("arg", ARG)
+ std_symbol("atomize", ATOMIZE)
+ std_symbol("besselj", BESSELJ)
+ std_symbol("bessely", BESSELY)
+ std_symbol("binding", BINDING)
+ std_symbol("binomial", BINOMIAL)
+ std_symbol("ceiling", CEILING)
+ std_symbol("check", CHECK)
+ std_symbol("choose", CHOOSE)
+ std_symbol("circexp", CIRCEXP)
+ std_symbol("clear", CLEAR)
+ std_symbol("clearall", CLEARALL)
+ std_symbol("clearpatterns", CLEARPATTERNS)
+ std_symbol("clock", CLOCK)
+ std_symbol("coeff", COEFF)
+ std_symbol("cofactor", COFACTOR)
+ std_symbol("condense", CONDENSE)
+ std_symbol("conj", CONJ)
+ std_symbol("contract", CONTRACT)
+ std_symbol("cos", COS)
+ std_symbol("cosh", COSH)
+ std_symbol("decomp", DECOMP)
+ std_symbol("defint", DEFINT)
+ std_symbol("deg", DEGREE)
+ std_symbol("denominator", DENOMINATOR)
+ std_symbol("det", DET)
+ std_symbol("derivative", DERIVATIVE)
+ std_symbol("dim", DIM)
+ std_symbol("dirac", DIRAC)
+ std_symbol("divisors", DIVISORS)
+ std_symbol("do", DO)
+ std_symbol("dot", DOT)
+ std_symbol("draw", DRAW)
+ std_symbol("dsolve", DSOLVE)
+ std_symbol("erf", ERF)
+ std_symbol("erfc", ERFC)
+ std_symbol("eigen", EIGEN)
+ std_symbol("eigenval", EIGENVAL)
+ std_symbol("eigenvec", EIGENVEC)
+ std_symbol("eval", EVAL)
+ std_symbol("exp", EXP)
+ std_symbol("expand", EXPAND)
+ std_symbol("expcos", EXPCOS)
+ std_symbol("expsin", EXPSIN)
+ std_symbol("factor", FACTOR)
+ std_symbol("factorial", FACTORIAL)
+ std_symbol("factorpoly", FACTORPOLY)
+ std_symbol("filter", FILTER)
+ std_symbol("float", FLOATF)
+ std_symbol("floor", FLOOR)
+ std_symbol("for", FOR)
+ std_symbol("function", FUNCTION)
+ std_symbol("Gamma", GAMMA)
+ std_symbol("gcd", GCD)
+ std_symbol("hermite", HERMITE)
+ std_symbol("hilbert", HILBERT)
+ std_symbol("imag", IMAG)
+ std_symbol("component", INDEX)
+ std_symbol("inner", INNER)
+ std_symbol("integral", INTEGRAL)
+ std_symbol("inv", INV)
+ std_symbol("invg", INVG)
+ std_symbol("isinteger", ISINTEGER)
+ std_symbol("isprime", ISPRIME)
+ std_symbol("laguerre", LAGUERRE)
+ # std_symbol("laplace", LAPLACE)
+ std_symbol("lcm", LCM)
+ std_symbol("leading", LEADING)
+ std_symbol("legendre", LEGENDRE)
+ std_symbol("log", LOG)
+ std_symbol("lookup", LOOKUP)
+ std_symbol("mod", MOD)
+ std_symbol("multiply", MULTIPLY)
+ std_symbol("not", NOT)
+ std_symbol("nroots", NROOTS)
+ std_symbol("number", NUMBER)
+ std_symbol("numerator", NUMERATOR)
+ std_symbol("operator", OPERATOR)
+ std_symbol("or", OR)
+ std_symbol("outer", OUTER)
+ std_symbol("pattern", PATTERN)
+ std_symbol("patternsinfo", PATTERNSINFO)
+ std_symbol("polar", POLAR)
+ std_symbol("power", POWER)
+ std_symbol("prime", PRIME)
+ std_symbol("print", PRINT)
+ std_symbol("print2dascii", PRINT2DASCII)
+ std_symbol("printcomputer", PRINTFULL)
+ std_symbol("printlatex", PRINTLATEX)
+ std_symbol("printlist", PRINTLIST)
+ std_symbol("printhuman", PRINTPLAIN)
+ std_symbol("printLeaveEAlone", PRINT_LEAVE_E_ALONE)
+ std_symbol("printLeaveXAlone", PRINT_LEAVE_X_ALONE)
+ std_symbol("product", PRODUCT)
+ std_symbol("quote", QUOTE)
+ std_symbol("quotient", QUOTIENT)
+ std_symbol("rank", RANK)
+ std_symbol("rationalize", RATIONALIZE)
+ std_symbol("real", REAL)
+ std_symbol("rect", YYRECT)
+ std_symbol("roots", ROOTS)
+ std_symbol("round", ROUND)
+ std_symbol("equals", SETQ)
+ std_symbol("sgn", SGN)
+ std_symbol("silentpattern", SILENTPATTERN)
+ std_symbol("simplify", SIMPLIFY)
+ std_symbol("sin", SIN)
+ std_symbol("sinh", SINH)
+ std_symbol("shape", SHAPE)
+ std_symbol("sqrt", SQRT)
+ std_symbol("stop", STOP)
+ std_symbol("subst", SUBST)
+ std_symbol("sum", SUM)
+ std_symbol("symbolsinfo", SYMBOLSINFO)
+ std_symbol("tan", TAN)
+ std_symbol("tanh", TANH)
+ std_symbol("taylor", TAYLOR)
+ std_symbol("test", TEST)
+ std_symbol("testeq", TESTEQ)
+ std_symbol("testge", TESTGE)
+ std_symbol("testgt", TESTGT)
+ std_symbol("testle", TESTLE)
+ std_symbol("testlt", TESTLT)
+ std_symbol("transpose", TRANSPOSE)
+ std_symbol("unit", UNIT)
+ std_symbol("zero", ZERO)
+
+ std_symbol("nil", NIL)
+
+ std_symbol("autoexpand", AUTOEXPAND)
+ std_symbol("bake", BAKE)
+ std_symbol("assumeRealVariables", ASSUME_REAL_VARIABLES)
+
+
+ std_symbol("last", LAST)
+
+ std_symbol("lastprint", LAST_PRINT)
+ std_symbol("last2dasciiprint", LAST_2DASCII_PRINT)
+ std_symbol("lastfullprint", LAST_FULL_PRINT)
+ std_symbol("lastlatexprint", LAST_LATEX_PRINT)
+ std_symbol("lastlistprint", LAST_LIST_PRINT)
+ std_symbol("lastplainprint", LAST_PLAIN_PRINT)
+
+ std_symbol("trace", TRACE)
+
+ std_symbol("forceFixedPrintout", FORCE_FIXED_PRINTOUT)
+ std_symbol("maxFixedPrintoutDigits", MAX_FIXED_PRINTOUT_DIGITS)
+
+ std_symbol("~", YYE) # tilde so sort puts it after other symbols
+
+ std_symbol("$DRAWX", DRAWX) # special purpose internal symbols
+ std_symbol("$METAA", METAA)
+ std_symbol("$METAB", METAB)
+ std_symbol("$METAX", METAX)
+ std_symbol("$SECRETX", SECRETX)
+
+ std_symbol("version", VERSION)
+
+ std_symbol("pi", PI)
+ std_symbol("a", SYMBOL_A)
+ std_symbol("b", SYMBOL_B)
+ std_symbol("c", SYMBOL_C)
+ std_symbol("d", SYMBOL_D)
+ std_symbol("i", SYMBOL_I)
+ std_symbol("j", SYMBOL_J)
+ std_symbol("n", SYMBOL_N)
+ std_symbol("r", SYMBOL_R)
+ std_symbol("s", SYMBOL_S)
+ std_symbol("t", SYMBOL_T)
+ std_symbol("x", SYMBOL_X)
+ std_symbol("y", SYMBOL_Y)
+ std_symbol("z", SYMBOL_Z)
+ std_symbol("I", SYMBOL_IDENTITY_MATRIX)
+
+ std_symbol("a_", SYMBOL_A_UNDERSCORE)
+ std_symbol("b_", SYMBOL_B_UNDERSCORE)
+ std_symbol("x_", SYMBOL_X_UNDERSCORE)
+
+ std_symbol("$C1", C1)
+ std_symbol("$C2", C2)
+ std_symbol("$C3", C3)
+ std_symbol("$C4", C4)
+ std_symbol("$C5", C5)
+ std_symbol("$C6", C6)
+
+ defineSomeHandyConstants()
+
+
+ # don't add all these functions to the
+ # symbolsDependencies, clone the original
+ originalCodeGen = codeGen
+ codeGen = false
+
+ for defn_i in [0...defn_str.length]
+ definitionOfInterest = defn_str[defn_i]
+ scan(definitionOfInterest)
+ if DEBUG
+ console.log "... evaling " + definitionOfInterest
+ console.log("top of stack:")
+ console.log print_list(stack[tos-1])
+ Eval()
+ pop()
+
+ # restore the symbol dependencies as they were before.
+ codeGen = originalCodeGen
+
+defineSomeHandyConstants = ->
+ zero = new_integer 0
+ one = new_integer 1
+
+ push_double(1.0)
+ one_as_double = pop()
+
+ # i is the square root of -1 i.e. -1 ^ 1/2
+ push_symbol(POWER)
+ if DEBUG then console.log print_list(stack[tos-1])
+ push_integer(-1)
+ if DEBUG then console.log print_list(stack[tos-1])
+ push_rational(1, 2)
+ if DEBUG then console.log print_list(stack[tos-1])
+ list(3)
+ if DEBUG then console.log print_list(stack[tos-1])
+ imaginaryunit = pop() # must be untagged in gc
diff --git a/node_modules/algebrite/runtime/mcmp.coffee b/node_modules/algebrite/runtime/mcmp.coffee
new file mode 100644
index 0000000..8a49619
--- /dev/null
+++ b/node_modules/algebrite/runtime/mcmp.coffee
@@ -0,0 +1,21 @@
+# Bignum compare
+#
+# returns
+#
+# -1 a < b
+#
+# 0 a = b
+#
+# 1 a > b
+
+
+
+mcmp = (a,b) ->
+ return a.compare b
+
+# a is a bigint, n is a normal int
+mcmpint = (a,n) ->
+ b = bigInt(n)
+ t = mcmp(a, b)
+ return t
+
diff --git a/node_modules/algebrite/runtime/otherCFunctions.coffee b/node_modules/algebrite/runtime/otherCFunctions.coffee
new file mode 100644
index 0000000..f1b1d4f
--- /dev/null
+++ b/node_modules/algebrite/runtime/otherCFunctions.coffee
@@ -0,0 +1,93 @@
+
+strcmp = (str1, str2) ->
+ if str1 == str2 then 0 else if str1 > str2 then 1 else -1
+
+
+doubleToReasonableString = (d) ->
+
+ # when generating code, print out
+ # the standard JS Number printout
+ if codeGen
+ return "" + d
+
+
+ if (isZeroAtomOrTensor(get_binding(symbol(FORCE_FIXED_PRINTOUT))))
+ stringRepresentation = "" + d
+ # manipulate the string so that it can be parsed by
+ # Algebrite (something like 1.23e-123 wouldn't cut it because
+ # that would be parsed as 1.23*e - 123)
+
+ if printMode == PRINTMODE_LATEX
+ # 1.0\mathrm{e}{-10} looks much better than the plain 1.0e-10
+ if /\d*\.\d*e.*/gm.test(stringRepresentation)
+ stringRepresentation = stringRepresentation.replace(/e(.*)/gm, "\\mathrm{e}{$1}");
+ else
+ # if there is no dot in the mantissa, add it so we see it's
+ # a double and not a perfect number
+ # e.g. 1e-10 becomes 1.0\mathrm{e}{-10}
+ stringRepresentation = stringRepresentation.replace(/(\d+)e(.*)/gm, "$1.0\\mathrm{e}{$2}");
+ else
+ if /\d*\.\d*e.*/gm.test(stringRepresentation)
+ stringRepresentation = stringRepresentation.replace(/e(.*)/gm, "*10^($1)");
+ else
+ # if there is no dot in the mantissa, add it so we see it's
+ # a double and not a perfect number
+ # e.g. 1e-10 becomes 1.0e-10
+ stringRepresentation = stringRepresentation.replace(/(\d+)e(.*)/gm, "$1.0*10^($2)");
+
+ else
+ push(get_binding(symbol(MAX_FIXED_PRINTOUT_DIGITS)))
+ maxFixedPrintoutDigits = pop_integer()
+ #console.log "maxFixedPrintoutDigits: " + maxFixedPrintoutDigits
+ #console.log "type: " + typeof(maxFixedPrintoutDigits)
+ #console.log "toFixed: " + d.toFixed(maxFixedPrintoutDigits)
+
+ stringRepresentation = "" + d.toFixed(maxFixedPrintoutDigits)
+
+ # remove any trailing zeroes after the dot
+ # see https://stackoverflow.com/questions/26299160/using-regex-how-do-i-remove-the-trailing-zeros-from-a-decimal-number
+ stringRepresentation = stringRepresentation.replace(/(\.\d*?[1-9])0+$/gm, "$1")
+ # in case there are only zeroes after the dot, removes the dot too
+ stringRepresentation = stringRepresentation.replace(/\.0+$/gm, "")
+
+ # we actually want to give a hint to user that
+ # it's a double, so add a trailing ".0" if there
+ # is no decimal point
+ if stringRepresentation.indexOf(".") == -1
+ stringRepresentation += ".0"
+
+ if parseFloat(stringRepresentation) != d
+ stringRepresentation = d.toFixed(maxFixedPrintoutDigits) + "..."
+
+
+ return stringRepresentation
+
+# does nothing
+clear_term = ->
+
+# s is a string here anyways
+isspace = (s) ->
+ if !s? then return false
+ return s == ' ' or s == '\t' or s == '\n' or s == '\v' or s == '\f' or s == '\r'
+
+isdigit = (str) ->
+ if !str? then return false
+ return /^\d+$/.test(str)
+
+isalpha = (str) ->
+ if !str? then return false
+ #Check for non-alphabetic characters and space
+ return (str.search(/[^A-Za-z]/) == -1)
+
+isalphaOrUnderscore = (str) ->
+ if !str? then return false
+ #Check for non-alphabetic characters and space
+ return (str.search(/[^A-Za-z_]/) == -1)
+
+isunderscore = (str) ->
+ if !str? then return false
+ return (str.search(/_/) == -1)
+
+isalnumorunderscore = (str) ->
+ if !str? then return false
+ return (isalphaOrUnderscore(str) or isdigit(str))
diff --git a/node_modules/algebrite/runtime/run.coffee b/node_modules/algebrite/runtime/run.coffee
new file mode 100644
index 0000000..5cf939b
--- /dev/null
+++ b/node_modules/algebrite/runtime/run.coffee
@@ -0,0 +1,795 @@
+
+
+#jmp_buf stop_return, draw_stop_return
+
+# s is a string here
+stop = (s) ->
+ #if (draw_flag == 2)
+ # longjmp(draw_stop_return, 1)
+ #else
+ errorMessage += "Stop: "
+ errorMessage += s
+ #debugger
+ message = errorMessage
+
+ errorMessage = ''
+ moveTos 0
+
+ throw new Error(message)
+
+ #longjmp(stop_return, 1)
+
+# Figuring out dependencies is key to automatically
+# generating a method signature when generating JS code
+# from algebrite scripts.
+# This is important because the user can keep using normal Algebrite
+# scripting without special notations.
+# Basically the process consists of figuring out
+# the "ground variables" that are needed to compute each variable.
+# Now there are two ways of doing this:
+# * at parse time
+# * after running the scripts
+# Doing it at parse time means that we can't track simplifications
+# canceling-out some variables for example. But on the other side
+# it's very quick and the user can somehow see what the signature is
+# going to look like (assuming tha code is rather simple), or anyways
+# is going to easily make sense of the generated signature.
+# Doing it after execution on the other hand would allow us to see
+# if some variable cancel-out. But if variables cancel out then
+# they might do so according to some run-time behaviour that the user
+# might struggle to keep track of.
+# So the effort for the user to make sense of the signature in the first case
+# is similar to the effort of keeping tab of types in a typed language.
+# While in the second case the effort is similar to running the
+# code and simplifications in her head.
+#
+# If we just want to compute the dependencies, we don't need to do
+# anything costly, we don't "run" the code and we don't simplify
+# the code. Just finding the plain dependencies
+# TODO change the name of this function, as it doesn't just find the
+# dependencies. It also runs it and generates the JS code.
+findDependenciesInScript = (stringToBeParsed, dontGenerateCode) ->
+
+ if DEBUG then console.log "stringToBeParsed: " + stringToBeParsed
+
+ timeStartFromAlgebra = new Date().getTime()
+
+ inited = true
+ codeGen = true
+ symbolsDependencies = {}
+ symbolsHavingReassignments = []
+ symbolsInExpressionsWithoutAssignments = []
+ patternHasBeenFound = false
+ indexOfPartRemainingToBeParsed = 0
+
+ allReturnedPlainStrings = ""
+ allReturnedLatexStrings = ""
+
+ n = 0
+
+ # we are going to store the dependencies _of the block as a whole_
+ # so all affected variables in the whole block are lumped
+ # together, and same for the variable that affect those, we
+ # lump them all together.
+ dependencyInfo =
+ affectsVariables: []
+ affectedBy: []
+
+
+ stringToBeRun = stringToBeParsed
+
+
+ # parse the input. This collects the
+ # dependency information
+ while (1)
+ try
+ errorMessage = ""
+ check_stack()
+ if DEBUG then console.log "findDependenciesInScript: scanning"
+ n = scan(stringToBeParsed.substring(indexOfPartRemainingToBeParsed))
+ if DEBUG then console.log "scanned"
+ pop()
+ check_stack()
+ catch error
+ if PRINTOUTRESULT then console.log error
+ errorMessage = error + ""
+ #debugger
+ reset_after_error()
+ break
+
+ if (n == 0)
+ break
+
+ indexOfPartRemainingToBeParsed += n
+
+ testableString = ""
+
+ # print out all local dependencies as collected by this
+ # parsing pass
+ if DEBUG then console.log "all local dependencies ----------------"
+ testableString += "All local dependencies: "
+ for key, value of symbolsDependencies
+ if DEBUG then console.log "variable " + key + " depends on: "
+ dependencyInfo.affectsVariables.push key
+ testableString += " variable " + key + " depends on: "
+ for i in value
+ if DEBUG then console.log " " + i
+ if i[0] != "'"
+ dependencyInfo.affectedBy.push i
+ testableString += i + ", "
+ testableString += "; "
+ testableString += ". "
+
+ # print out the symbols with re-assignments:
+ if DEBUG then console.log "Symbols with reassignments ----------------"
+ testableString += "Symbols with reassignments: "
+ for key in symbolsHavingReassignments
+ if dependencyInfo.affectedBy.indexOf(key) == -1
+ dependencyInfo.affectedBy.push key
+ testableString += key + ", "
+ testableString += ". "
+
+ # print out the symbols that appear in expressions without assignments
+ if DEBUG then console.log "Symbols in expressions without assignments ----------------"
+ testableString += "Symbols in expressions without assignments: "
+ for key in symbolsInExpressionsWithoutAssignments
+ if dependencyInfo.affectedBy.indexOf(key) == -1
+ dependencyInfo.affectedBy.push key
+ testableString += key + ", "
+ testableString += ". "
+
+ # ALL Algebrite code is affected by any pattern changing
+ dependencyInfo.affectedBy.push "PATTERN_DEPENDENCY"
+
+ if patternHasBeenFound
+ dependencyInfo.affectsVariables.push "PATTERN_DEPENDENCY"
+ testableString += " - PATTERN_DEPENDENCY inserted - "
+
+ # print out all global dependencies as collected by this
+ # parsing pass
+ if DEBUG then console.log "All dependencies recursively ----------------"
+ testableString += "All dependencies recursively: "
+
+ scriptEvaluation = ["",""]
+ generatedCode = ""
+ readableSummaryOfGeneratedCode = ""
+
+ if errorMessage == "" and !dontGenerateCode
+
+ try
+ allReturnedPlainStrings = ""
+ allReturnedLatexStrings = ""
+ scriptEvaluation = run(stringToBeParsed, true)
+ allReturnedPlainStrings = ""
+ allReturnedLatexStrings = ""
+ catch error
+ if PRINTOUTRESULT then console.log error
+ errorMessage = error + ""
+ #debugger
+ init()
+
+ if errorMessage == ""
+ for key of symbolsDependencies
+
+
+ codeGen = true
+ if DEBUG then console.log " variable " + key + " is: " + get_binding(usr_symbol(key)).toString()
+ codeGen = false
+ if DEBUG then console.log " variable " + key + " depends on: "
+ testableString += " variable " + key + " depends on: "
+
+ recursedDependencies = []
+ variablesWithCycles = []
+ cyclesDescriptions = []
+
+ recursiveDependencies key, recursedDependencies, [], variablesWithCycles, [], cyclesDescriptions
+
+ for i in variablesWithCycles
+ if DEBUG then console.log " --> cycle through " + i
+
+ for i in recursedDependencies
+ if DEBUG then console.log " " + i
+ testableString += i + ", "
+ testableString += "; "
+
+ for i in cyclesDescriptions
+ testableString += " " + i + ", "
+
+ if DEBUG then console.log " code generation:" + key + " is: " + get_binding(usr_symbol(key)).toString()
+
+ # we really want to make an extra effort
+ # to generate simplified code, so
+ # run a "simplify" on the content of each
+ # variable that we are generating code for.
+ # Note that the variable
+ # will still point to un-simplified structures,
+ # we only simplify the generated code.
+ push get_binding(usr_symbol(key))
+
+ # Since we go and simplify all variables we meet,
+ # we have to replace each variable passed as a parameter
+ # with something entirely new, so that there is no chance
+ # that it might evoke previous values in the external scope
+ # as in this case:
+ # a = 2
+ # f(a) = a+1+b
+ # we don't want 'a' in the body of f to be simplified to 2
+ # There are two cases: 1) the variable actually was already in
+ # the symbol table, in which case there is going to be this new
+ # one prepended with AVOID_BINDING_TO_EXTERNAL_SCOPE_VALUE, and
+ # we'll have to remove up this variable later.
+ # OR 2) the variable wasn't already in the symbol table, in which
+ # case we directly create this one, which means that we'll have
+ # to rename it later to the correct name without the prepended
+ # part.
+
+ replacementsFrom = []
+ replacementsTo = []
+
+ for eachDependency in recursedDependencies
+ if eachDependency[0] == "'"
+ deQuotedDep = eachDependency.substring(1)
+ originalUserSymbol = usr_symbol(deQuotedDep)
+ newUserSymbol = usr_symbol("AVOID_BINDING_TO_EXTERNAL_SCOPE_VALUE"+deQuotedDep)
+ replacementsFrom.push originalUserSymbol
+ replacementsTo.push newUserSymbol
+ push(originalUserSymbol)
+ push(newUserSymbol)
+ subst()
+ if DEBUG then console.log "after substitution: " + stack[tos-1]
+
+ try
+ simplifyForCodeGeneration()
+ catch error
+ if PRINTOUTRESULT then console.log error
+ errorMessage = error + ""
+ #debugger
+ init()
+
+ for indexOfEachReplacement in [0...replacementsFrom.length]
+ #console.log "replacing back " + replacementsTo[indexOfEachReplacement] + " into: " + replacementsFrom[indexOfEachReplacement]
+ push(replacementsTo[indexOfEachReplacement])
+ push(replacementsFrom[indexOfEachReplacement])
+ subst()
+
+ clearRenamedVariablesToAvoidBindingToExternalScope()
+
+ if errorMessage == ""
+ toBePrinted = pop()
+
+ # we have to get all the variables used on the right side
+ # here. I.e. to print the arguments it's better to look at the
+ # actual method body after simplification.
+ userVariablesMentioned = []
+ collectUserSymbols(toBePrinted, userVariablesMentioned)
+
+ allReturnedPlainStrings = ""
+ allReturnedLatexStrings = ""
+ codeGen = true
+ generatedBody = toBePrinted.toString()
+ codeGen = false
+
+ origPrintMode = printMode
+ printMode = PRINTMODE_LATEX
+
+ bodyForReadableSummaryOfGeneratedCode = toBePrinted.toString()
+
+ printMode = origPrintMode
+
+ if variablesWithCycles.indexOf(key) != -1
+ generatedCode += "// " + key + " is part of a cyclic dependency, no code generated."
+ readableSummaryOfGeneratedCode += "#" + key + " is part of a cyclic dependency, no code generated."
+ else
+
+ ###
+ # using this paragraph instead of the following one
+ # creates methods signatures that
+ # are slightly less efficient
+ # i.e. variables compare even if they are
+ # simplified away.
+ # In theory these signatures are more stable, but
+ # in practice signatures vary quite a bit anyways
+ # depending on previous assignments for example,
+ # so it's unclear whether going for stability
+ # is sensible at all..
+ if recursedDependencies.length != 0
+ parameters = "("
+ for i in recursedDependencies
+ if i.indexOf("'") != 0
+ parameters += i + ", "
+ else
+ if recursedDependencies.indexOf(i.substring(1)) == -1
+ parameters += i.substring(1) + ", "
+ ###
+
+
+ # remove all native functions from the
+ # parameters as well.
+ userVariablesMentioned = userVariablesMentioned.filter (x) ->
+ predefinedSymbolsInGlobalScope_doNotTrackInDependencies.indexOf(x + "") == -1
+
+ # remove the variable that are not in the dependency list
+ # i.e. only allow the variables that are in the dependency list
+ userVariablesMentioned = userVariablesMentioned.filter (x) ->
+ recursedDependencies.indexOf(x + "") != -1 or
+ recursedDependencies.indexOf("\'" + x + "") != -1
+
+ if userVariablesMentioned.length != 0
+ parameters = "("
+ for i in userVariablesMentioned
+ if i.printname != key
+ parameters += i.printname + ", "
+
+ # eliminate the last ", " for printout clarity
+ parameters = parameters.replace /, $/gm , ""
+ parameters += ")"
+ generatedCode += key + " = function " + parameters + " { return ( " + generatedBody + " ); }"
+ readableSummaryOfGeneratedCode += key + parameters + " = " + bodyForReadableSummaryOfGeneratedCode
+ else
+ generatedCode += key + " = " + generatedBody + ";"
+ readableSummaryOfGeneratedCode += key + " = " + bodyForReadableSummaryOfGeneratedCode
+
+ generatedCode += "\n"
+ readableSummaryOfGeneratedCode += "\n"
+
+ if DEBUG then console.log " " + generatedCode
+
+ # eliminate the last new line
+ generatedCode = generatedCode.replace /\n$/gm , ""
+ readableSummaryOfGeneratedCode = readableSummaryOfGeneratedCode.replace /\n$/gm , ""
+
+
+ # cleanup
+ symbolsDependencies = {}
+ symbolsHavingReassignments = []
+ patternHasBeenFound = false
+ symbolsInExpressionsWithoutAssignments = []
+
+ if DEBUG then console.log "testable string: " + testableString
+
+ if TIMING_DEBUGS
+ console.log "findDependenciesInScript time for: " + stringToBeRun + " : "+ ((new Date().getTime()) - timeStartFromAlgebra) + "ms"
+
+ return [testableString, scriptEvaluation[0], generatedCode, readableSummaryOfGeneratedCode, scriptEvaluation[1], errorMessage, dependencyInfo]
+
+recursiveDependencies = (variableToBeChecked, arrayWhereDependenciesWillBeAdded, variablesAlreadyFleshedOut, variablesWithCycles, chainBeingChecked, cyclesDescriptions) ->
+ variablesAlreadyFleshedOut.push variableToBeChecked
+
+ # recursive dependencies can only be descended if the variable is not bound to a parameter
+ if symbolsDependencies[chainBeingChecked[chainBeingChecked.length-1]]?
+ if symbolsDependencies[chainBeingChecked[chainBeingChecked.length-1]].indexOf("'"+variableToBeChecked) != -1
+ if DEBUG then console.log "can't keep following the chain of " + variableToBeChecked + " because it's actually a variable bound to a parameter"
+ if arrayWhereDependenciesWillBeAdded.indexOf("'"+variableToBeChecked) == -1 and arrayWhereDependenciesWillBeAdded.indexOf(variableToBeChecked) == -1
+ arrayWhereDependenciesWillBeAdded.push variableToBeChecked
+ return arrayWhereDependenciesWillBeAdded
+
+ chainBeingChecked.push variableToBeChecked
+
+ if !symbolsDependencies[variableToBeChecked]?
+ # end case: the passed variable has no dependencies
+ # so there is nothing else to do
+ if arrayWhereDependenciesWillBeAdded.indexOf(variableToBeChecked) == -1
+ arrayWhereDependenciesWillBeAdded.push variableToBeChecked
+ return arrayWhereDependenciesWillBeAdded
+ else
+ # recursion case: we have to dig deeper
+ for i in symbolsDependencies[variableToBeChecked]
+
+ # check that there is no recursion in dependencies
+ # we do that by keeping a list of variables that
+ # have already been "fleshed-out". If we encounter
+ # any of those "fleshed-out" variables while
+ # fleshing out, then there is a cycle
+
+ if chainBeingChecked.indexOf(i) != -1
+ if DEBUG then console.log " found cycle:"
+ cyclesDescription = ""
+ for k in chainBeingChecked
+ if variablesWithCycles.indexOf(k) == -1
+ variablesWithCycles.push k
+ if DEBUG then console.log k + " --> "
+ cyclesDescription += k + " --> "
+ if DEBUG then console.log " ... then " + i + " again"
+ cyclesDescription += " ... then " + i + " again"
+ cyclesDescriptions.push cyclesDescription
+ #if DEBUG then console.log " --> cycle through " + i
+ # we want to flesh-out i but it's already been
+ # fleshed-out, just add it to the variables
+ # with cycles and move on
+ # todo refactor this, there are two copies of these two lines
+ if variablesWithCycles.indexOf(i) == -1
+ variablesWithCycles.push i
+ else
+ # flesh-out i recursively
+ recursiveDependencies i, arrayWhereDependenciesWillBeAdded, variablesAlreadyFleshedOut, variablesWithCycles, chainBeingChecked, cyclesDescriptions
+ chainBeingChecked.pop()
+ #variablesAlreadyFleshedOut.pop()
+
+ return arrayWhereDependenciesWillBeAdded
+
+
+
+# parses and runs one statement/expression at a time
+inited = false
+
+latexErrorSign = "\\rlap{\\large\\color{red}\\bigtriangleup}{\\ \\ \\tiny\\color{red}!}"
+turnErrorMessageToLatex = (theErrorMessage) ->
+ theErrorMessage = theErrorMessage.replace(/\n/g,"")
+ theErrorMessage = theErrorMessage.replace(/_/g, "} \\_ \\text{");
+ theErrorMessage = theErrorMessage.replace(new RegExp(String.fromCharCode(transpose_unicode), 'g'), "}{}^{T}\\text{");
+ theErrorMessage = theErrorMessage.replace(new RegExp(String.fromCharCode(dotprod_unicode), 'g'),"}\\cdot \\text{");
+ theErrorMessage = theErrorMessage.replace("Stop:","} \\quad \\text{Stop:");
+ theErrorMessage = theErrorMessage.replace("->","} \\rightarrow \\text{");
+ theErrorMessage = theErrorMessage.replace("?","}\\enspace " + latexErrorSign + " \\enspace \\text{");
+ theErrorMessage = "$$\\text{" + theErrorMessage.replace(/\n/g,"") + "}$$"
+ #console.log "theErrorMessage: " + theErrorMessage
+ return theErrorMessage
+
+# there are around a dozen different unicodes that
+# represent some sort of middle dot, let's catch the most
+# common and turn them into what we can process
+normaliseDots = (stringToNormalise) ->
+ stringToNormalise = stringToNormalise.replace(new RegExp(String.fromCharCode(8901), 'g'), String.fromCharCode(dotprod_unicode));
+ stringToNormalise = stringToNormalise.replace(new RegExp(String.fromCharCode(8226), 'g'), String.fromCharCode(dotprod_unicode));
+ stringToNormalise = stringToNormalise.replace(new RegExp(String.fromCharCode(12539), 'g'), String.fromCharCode(dotprod_unicode));
+ stringToNormalise = stringToNormalise.replace(new RegExp(String.fromCharCode(55296), 'g'), String.fromCharCode(dotprod_unicode));
+ stringToNormalise = stringToNormalise.replace(new RegExp(String.fromCharCode(65381), 'g'), String.fromCharCode(dotprod_unicode));
+ return stringToNormalise
+
+
+TIMING_DEBUGS = false
+
+run = (stringToBeRun, generateLatex = false) ->
+
+ timeStart = new Date().getTime()
+
+ #stringToBeRun = stringToBeRun + "\n"
+ stringToBeRun = normaliseDots stringToBeRun
+
+ #console.log "run running: " + stringToBeRun
+
+ if stringToBeRun == "selftest"
+ selftest()
+ return
+
+ #if (setjmp(stop_return))
+ # return
+
+ if !inited
+ inited = true
+ init()
+
+ i = 0
+ n = 0
+ indexOfPartRemainingToBeParsed = 0
+
+ allReturnedPlainStrings = ""
+ allReturnedLatexStrings = ""
+
+ while (1)
+ # while we can keep scanning commands out of the
+ # passed input AND we can execute them...
+
+ try
+ errorMessage = ""
+ check_stack()
+ n = scan(stringToBeRun.substring(indexOfPartRemainingToBeParsed))
+ p1 = pop()
+ check_stack()
+ catch error
+ if PRINTOUTRESULT then console.log error
+ #debugger
+ allReturnedPlainStrings += error.message
+ if generateLatex
+ #debugger
+ theErrorMessage = turnErrorMessageToLatex error.message
+ allReturnedLatexStrings += theErrorMessage
+ reset_after_error()
+
+ break
+
+
+
+ if (n == 0)
+ break
+
+ # if debug mode then print the source text
+
+ #if (equaln(get_binding(symbol(TRACE)), 1)) {
+ # for (i = 0 i < n i++)
+ # if (s[i] != '\r')
+ # printchar(s[i])
+ # if (s[n - 1] != '\n') # n is not zero, see above
+ # printchar('\n')
+ #}
+
+ indexOfPartRemainingToBeParsed += n
+
+ push(p1)
+ #debugger
+ errorWhileExecution = false
+ try
+ stringsEmittedByUserPrintouts = ""
+ top_level_eval()
+ #console.log "emitted string after top_level_eval(): >" + stringsEmittedByUserPrintouts + "<"
+ #console.log "allReturnedPlainStrings string after top_level_eval(): >" + allReturnedPlainStrings + "<"
+
+ p2 = pop()
+ check_stack()
+
+ if (isstr(p2))
+ if DEBUG then console.log(p2.str)
+ if DEBUG then console.log("\n")
+
+ # if the return value is nil there isn't much point
+ # in adding "nil" to the printout
+ if (p2 == symbol(NIL))
+ #collectedPlainResult = stringsEmittedByUserPrintouts
+ collectedPlainResult = stringsEmittedByUserPrintouts
+ if generateLatex
+ collectedLatexResult = "$$" + stringsEmittedByUserPrintouts + "$$"
+ else
+ #console.log "emitted string before collectPlainStringFromReturnValue: >" + stringsEmittedByUserPrintouts + "<"
+ #console.log "allReturnedPlainStrings string before collectPlainStringFromReturnValue: >" + allReturnedPlainStrings + "<"
+ collectedPlainResult = print_expr(p2)
+ collectedPlainResult += "\n"
+ #console.log "collectedPlainResult: >" + collectedPlainResult + "<"
+ if generateLatex
+ collectedLatexResult = "$$" + collectLatexStringFromReturnValue(p2) + "$$"
+ if DEBUG then console.log "collectedLatexResult: " + collectedLatexResult
+
+ allReturnedPlainStrings += collectedPlainResult
+ if generateLatex then allReturnedLatexStrings += collectedLatexResult
+
+ if PRINTOUTRESULT
+ if DEBUG then console.log "printline"
+ if DEBUG then console.log collectedPlainResult
+ #alert collectedPlainResult
+ if PRINTOUTRESULT
+ if DEBUG then console.log "display:"
+ print2dascii(p2)
+
+ if generateLatex then allReturnedLatexStrings += "\n"
+
+ catch error
+ errorWhileExecution = true
+ collectedPlainResult = error.message
+ if generateLatex then collectedLatexResult = turnErrorMessageToLatex error.message
+
+ if PRINTOUTRESULT then console.log collectedPlainResult
+
+ allReturnedPlainStrings += collectedPlainResult
+ if collectedPlainResult != ""
+ allReturnedPlainStrings += "\n"
+
+ if generateLatex
+ allReturnedLatexStrings += collectedLatexResult
+ allReturnedLatexStrings += "\n"
+
+ init()
+
+ if allReturnedPlainStrings[allReturnedPlainStrings.length-1] == "\n"
+ allReturnedPlainStrings = allReturnedPlainStrings.substring(0,allReturnedPlainStrings.length-1)
+
+ if generateLatex
+ if allReturnedLatexStrings[allReturnedLatexStrings.length-1] == "\n"
+ allReturnedLatexStrings = allReturnedLatexStrings.substring(0,allReturnedLatexStrings.length-1)
+
+ if generateLatex
+ if DEBUG then console.log "allReturnedLatexStrings: " + allReturnedLatexStrings
+ stringToBeReturned = [allReturnedPlainStrings, allReturnedLatexStrings]
+ else
+ stringToBeReturned = allReturnedPlainStrings
+
+ if TIMING_DEBUGS
+ timingDebugWrite = "run time on: " + stringToBeRun + " : " + (new Date().getTime() - timeStart) + "ms"
+ console.log timingDebugWrite
+
+ allReturnedPlainStrings = ""
+ allReturnedLatexStrings = ""
+ return stringToBeReturned
+
+check_stack = ->
+ if (tos != 0)
+ debugger
+ stop("stack error")
+ if (frame != TOS)
+ debugger
+ stop("frame error")
+ if chainOfUserSymbolsNotFunctionsBeingEvaluated.length != 0
+ debugger
+ stop("symbols evaluation still ongoing?")
+ if evaluatingAsFloats != 0
+ debugger
+ stop("numeric evaluation still ongoing?")
+ if evaluatingPolar != 0
+ debugger
+ stop("evaluation of polar still ongoing?")
+
+# cannot reference symbols yet
+
+# returns nil on stack if no result to print
+
+top_level_eval = ->
+ if DEBUG then console.log "#### top level eval"
+
+ trigmode = 0
+
+ shouldAutoexpand = symbol(AUTOEXPAND)
+
+ if (isZeroAtomOrTensor(get_binding(shouldAutoexpand)))
+ expanding = 0
+ else
+ expanding = 1
+
+ originalArgument = top()
+ Eval()
+ evalledArgument = top()
+
+ # "draw", "for" and "setq" return "nil", there is no result to print
+ if (evalledArgument == symbol(NIL))
+ return
+
+ # update "last" to contain the last result
+ set_binding(symbol(LAST), evalledArgument)
+
+ if (!isZeroAtomOrTensor(get_binding(symbol(BAKE))))
+ bake()
+ evalledArgument = top()
+
+ # If user asked explicitly asked to evaluate "i" or "j" and
+ # they represent the imaginary unit (-1)^(1/2), then
+ # show (-1)^(1/2).
+ if ((originalArgument == symbol(SYMBOL_I) || originalArgument == symbol(SYMBOL_J)) && isimaginaryunit(evalledArgument))
+ return
+ # In all other cases, replace all instances of (-1)^(1/2) in the result
+ # with the symbol "i" or "j" depending on which one
+ # represents the imaginary unit
+ else if (isimaginaryunit(get_binding(symbol(SYMBOL_J))))
+ push(imaginaryunit)
+ push_symbol(SYMBOL_J)
+ subst()
+ else if (isimaginaryunit(get_binding(symbol(SYMBOL_I))))
+ push(imaginaryunit)
+ push_symbol(SYMBOL_I)
+ subst()
+
+
+check_esc_flag = ->
+ if (esc_flag)
+ stop("esc key")
+
+# this is called when the whole notebook is re-run
+# so we get the chance of clearing the whole state from
+# scratch.
+# In practice, the state we need to clear that persists
+# across blocks are only the patterns, so
+# just eject those.
+clearAlgebraEnvironment = ->
+ #console.log "CLEARING clearAlgebraEnvironment ============================================================="
+ do_clearall()
+
+computeDependenciesFromAlgebra = (codeFromAlgebraBlock) ->
+ if DEBUG then console.log "computeDependenciesFromAlgebra!!!"
+ # return findDependenciesInScript(codeFromAlgebraBlock, true)[6]
+
+ # TODO this part below is duplicated from computeResultsAndJavaScriptFromAlgebra
+ # ...should refactor.
+ originalcodeFromAlgebraBlock = codeFromAlgebraBlock
+ keepState = true
+ called_from_Algebra_block = true
+
+ #console.log "codeFromAlgebraBlock: " + codeFromAlgebraBlock
+
+ codeFromAlgebraBlock = normaliseDots codeFromAlgebraBlock
+
+ if !keepState
+ userSimplificationsInListForm = []
+ userSimplificationsInProgramForm = ""
+ for i in userSimplificationsInListForm
+ #console.log "silentpattern(" + car(i) + ","+cdr(i)+")"
+ userSimplificationsInProgramForm += "silentpattern(" + car(i) + ","+ car(cdr(i)) + "," + car(cdr(cdr(i))) + ")\n"
+
+ do_clearall()
+ codeFromAlgebraBlock = userSimplificationsInProgramForm + codeFromAlgebraBlock
+ if DEBUG then console.log "codeFromAlgebraBlock including patterns: " + codeFromAlgebraBlock
+
+ if DEBUG
+ console.log "computeDependenciesFromAlgebra: patterns in the list --------------- "
+ for i in userSimplificationsInListForm
+ console.log car(i) + ","+cdr(i)+")"
+ console.log "...end of list --------------- "
+
+
+ called_from_Algebra_block = false
+
+ return findDependenciesInScript(codeFromAlgebraBlock, true)[6]
+
+computeResultsAndJavaScriptFromAlgebra = (codeFromAlgebraBlock) ->
+
+
+ originalcodeFromAlgebraBlock = codeFromAlgebraBlock
+ keepState = true
+ called_from_Algebra_block = true
+
+ timeStartFromAlgebra = new Date().getTime()
+
+ if TIMING_DEBUGS
+ console.log " --------- computeResultsAndJavaScriptFromAlgebra input: " + codeFromAlgebraBlock + " at: " + (new Date())
+
+ # we start "clean" each time:
+ # clear all the symbols and then re-define
+ # the "starting" symbols.
+
+ #console.log "codeFromAlgebraBlock: " + codeFromAlgebraBlock
+
+ codeFromAlgebraBlock = normaliseDots codeFromAlgebraBlock
+
+
+
+ stringToBeRun = codeFromAlgebraBlock
+
+ if DEBUG
+ console.log "computeResultsAndJavaScriptFromAlgebra: patterns in the list --------------- "
+ for i in userSimplificationsInListForm
+ console.log car(i) + ","+cdr(i)+")"
+ console.log "...end of list --------------- "
+
+ if !keepState
+ userSimplificationsInListForm = []
+ userSimplificationsInProgramForm = ""
+ for i in userSimplificationsInListForm
+ #console.log "silentpattern(" + car(i) + ","+cdr(i)+")"
+ userSimplificationsInProgramForm += "silentpattern(" + car(i) + ","+ car(cdr(i)) + "," + car(cdr(cdr(i))) + ")\n"
+
+ do_clearall()
+ codeFromAlgebraBlock = userSimplificationsInProgramForm + codeFromAlgebraBlock
+ if DEBUG then console.log "codeFromAlgebraBlock including patterns: " + codeFromAlgebraBlock
+
+ #debugger
+ [testableStringIsIgnoredHere,result,code,readableSummaryOfCode, latexResult, errorMessage, dependencyInfo] =
+ findDependenciesInScript(codeFromAlgebraBlock)
+
+ called_from_Algebra_block = false
+
+ if readableSummaryOfCode != "" or errorMessage != ""
+ result += "\n" + readableSummaryOfCode
+ if errorMessage != ""
+ result += "\n" + errorMessage
+ result = result.replace /\n/g,"\n\n"
+
+ latexResult += "\n" + "$$" + readableSummaryOfCode + "$$"
+ if errorMessage != ""
+ latexResult += turnErrorMessageToLatex errorMessage
+ latexResult = latexResult.replace /\n/g,"\n\n"
+
+ # remove empty results altogether from latex output, which happens
+ # for example for assignments to variables or
+ # functions definitions
+ latexResult = latexResult.replace /\n*/,""
+ latexResult = latexResult.replace /\$\$\$\$\n*/g,""
+
+ code = code.replace /Math\./g,""
+ code = code.replace /\n/g,"\n\n"
+
+ #console.log "code: " + code
+ #console.log "result: " + result
+ #console.log "latexResult: " + latexResult
+
+ if TIMING_DEBUGS
+ console.log "computeResultsAndJavaScriptFromAlgebra time (total time from notebook and back) for: " + stringToBeRun + " : "+ ((new Date().getTime()) - timeStartFromAlgebra) + "ms"
+
+ #code: "// no code generated yet\n//try again later"
+ #code: "console.log('some passed code is run'); window.something = 1;"
+ code: code
+
+ # TODO temporarily pass latex in place of standard result too
+ result: latexResult
+ latexResult: latexResult
+ dependencyInfo: dependencyInfo
+
+(exports ? this).run = run
+(exports ? this).findDependenciesInScript = findDependenciesInScript
+(exports ? this).computeDependenciesFromAlgebra = computeDependenciesFromAlgebra
+(exports ? this).computeResultsAndJavaScriptFromAlgebra = computeResultsAndJavaScriptFromAlgebra
+(exports ? this).clearAlgebraEnvironment = clearAlgebraEnvironment
diff --git a/node_modules/algebrite/runtime/stack.coffee b/node_modules/algebrite/runtime/stack.coffee
new file mode 100644
index 0000000..5b16032
--- /dev/null
+++ b/node_modules/algebrite/runtime/stack.coffee
@@ -0,0 +1,155 @@
+# _______
+# | | <- stack
+# | |
+# |_______|
+# | | <- stack + tos
+# | |
+# | |
+# |_______|
+# | | <- frame
+# |_______|
+# <- stack + TOS
+#
+# The stack grows from low memory towards high memory. This is so that
+# multiple expressions can be pushed on the stack and then accessed as an
+# array.
+#
+# The frame area holds local variables and grows from high memory towards
+# low memory. The frame area makes local variables visible to the garbage
+# collector.
+
+
+
+tos = 0
+
+# p is a U
+nil_symbols = 0
+push = (p) ->
+ if !p?
+ debugger
+ if p.isZero?
+ debugger
+
+ #console.log "pushing "
+ #console.log print_list(p)
+
+ if p == symbol(NIL)
+ nil_symbols++
+ if DEBUG then console.log "pushing symbol(NIL) #" + nil_symbols
+ #if nil_symbols == 111
+ # debugger
+ if (tos >= frame)
+ stop("stack overflow")
+ stack[tos++] = p
+
+# returns a U
+
+moveTos = (stackPos) ->
+ if tos <= stackPos
+ # we are moving the stack pointer
+ # "up" the stack (as if we were doing a push)
+ tos = stackPos
+ return
+ # we are moving the stack pointer
+ # "down" the stack i.e. as if we were
+ # doing a pop, we can zero-
+ # out all the elements that we pass
+ # so we can reclaim the memory
+ while tos > stackPos
+ stack[tos] = null
+ tos--
+ return
+
+top = ->
+ stack[tos-1]
+
+pop = ->
+ #popsNum++
+ #console.log "pop #" + popsNum
+ if (tos == 0)
+ debugger
+ stop("stack underflow")
+ if !stack[tos-1]?
+ debugger
+ elementToBeReturned = stack[--tos]
+
+ # give a chance to the garbage
+ # collection to reclaim space
+ # This is JS-specific, it would
+ # actually make the C garbage
+ # collector useless.
+ stack[tos] = null
+
+ return elementToBeReturned
+
+# n is an integer
+push_frame = (n) ->
+ i = 0
+ frame -= n
+ if (frame < tos)
+ debugger
+ stop("frame overflow, circular reference?")
+ for i in [0...n]
+ stack[frame + i] = symbol(NIL)
+
+# n is an integer
+pop_frame = (n) ->
+ frame += n
+ if (frame > TOS)
+ stop("frame underflow")
+
+save = ->
+ frame -= 10
+ if (frame < tos)
+ debugger
+ stop("frame overflow, circular reference?")
+ stack[frame + 0] = p0
+ stack[frame + 1] = p1
+ stack[frame + 2] = p2
+ stack[frame + 3] = p3
+ stack[frame + 4] = p4
+ stack[frame + 5] = p5
+ stack[frame + 6] = p6
+ stack[frame + 7] = p7
+ stack[frame + 8] = p8
+ stack[frame + 9] = p9
+
+restore = ->
+ if (frame > TOS - 10)
+ stop("frame underflow")
+ p0 = stack[frame + 0]
+ p1 = stack[frame + 1]
+ p2 = stack[frame + 2]
+ p3 = stack[frame + 3]
+ p4 = stack[frame + 4]
+ p5 = stack[frame + 5]
+ p6 = stack[frame + 6]
+ p7 = stack[frame + 7]
+ p8 = stack[frame + 8]
+ p9 = stack[frame + 9]
+ frame += 10
+
+# Local U * is OK here because there is no functional path to the garbage collector.
+
+swap = ->
+ #U *p, *q
+ # p and q are both Us
+ p = pop()
+ q = pop()
+ push(p)
+ push(q)
+
+# Local U * is OK here because there is no functional path to the garbage collector.
+
+dupl = ->
+ #U *p
+ p = pop()
+ push(p)
+ push(p)
+
+$.dupl = dupl
+$.swap = swap
+$.restore = restore
+$.save = save
+$.push = push
+$.pop = pop
diff --git a/node_modules/algebrite/runtime/symbol.coffee b/node_modules/algebrite/runtime/symbol.coffee
new file mode 100644
index 0000000..feb6eb4
--- /dev/null
+++ b/node_modules/algebrite/runtime/symbol.coffee
@@ -0,0 +1,259 @@
+# The symbol table is a simple array of struct U.
+
+
+
+# put symbol at index n
+Eval_symbolsinfo = ->
+ symbolsinfoToBePrinted = symbolsinfo()
+
+ if symbolsinfoToBePrinted != ""
+ push new_string(symbolsinfoToBePrinted)
+ else
+ push_symbol(NIL)
+
+symbolsinfo = ->
+ symbolsinfoToBePrinted = ""
+ for i in [NIL+1...symtab.length]
+ if symtab[i].printname == ""
+ if isSymbolReclaimable[i] == false
+ break
+ else
+ continue
+ symtabi = symtab[i] + ""
+ bindingi = (binding[i] + "").substring(0,4)
+ symbolsinfoToBePrinted += "symbol: " + symtabi + " size: " + countsize(binding[i]) + " value: " + bindingi + "...\n"
+ return symbolsinfoToBePrinted
+
+
+
+# s is a string, n is an int
+# TODO: elsewhere when we create a symbol we
+# rather prefer to create a new entry. Here we just
+# reuse the existing one. If that can never be a problem
+# then explain why, otherwise do create a new entry.
+std_symbol = (s, n, latexPrint) ->
+ p = symtab[n]
+ if !p?
+ debugger
+ p.printname = s
+ if latexPrint?
+ p.latexPrint = latexPrint
+ else
+ p.latexPrint = s
+
+# symbol lookup, or symbol creation if symbol doesn't exist yet
+# this happens often from the scanner. When the scanner sees something
+# like myVar = 2, it create a tree (SETQ ("myVar" symbol as created/looked up here (2)))
+# user-defined functions also have a usr symbol.
+#
+# Note that some symbols like, say, "abs",
+# are picked up by the scanner directly as keywords,
+# so they are not looked up via this.
+# So in fact you could redefine abs to be abs(x) = x
+# but still abs would be picked up by the scanner as a particular
+# node type and calls to abs() will be always to the "native" abs
+#
+# Also note that some symbols such as "zero" are (strangely) not picked up by
+# the scanner as special nodes, rather they are identified as keywords
+# (e.g. not redefinable) at time of symbol lookup (in Eval_sym) and
+# evalled, where eval has a case for ZERO.
+#
+# Also note that there are a number of symbols, such as a,b,c,x,y,z,...
+# that are actually created by std_symbols.
+# They are not special node types (like abs), they are normal symbols
+# that are looked up, but the advantage is that since they are often
+# used internally by algebrite, we create the symbol in advance and
+# we can reference the symbol entry in a clean way
+# (e.g. symbol(SYMBOL_X)) rather than
+# by looking up a string.
+
+# s is a string
+usr_symbol = (s) ->
+
+ #console.log "usr_symbol of " + s
+ #if s == "aaa"
+ # debugger
+
+ # find either the existing symbol, or if we
+ # reach an empty symbol (printname == "") then
+ # re-use that location.
+ i = 0
+ for i in [0...NSYM]
+ if (s == symtab[i].printname)
+ # found the symbol
+ return symtab[i]
+ if (symtab[i].printname == "")
+ # found an entry in the symbol table
+ # with no printname, exit the loop
+ # and re-use this location
+ break
+ if (i == NSYM)
+ stop("symbol table overflow")
+
+
+ symtab[i] = new U()
+ symtab[i].k = SYM
+ symtab[i].printname = s
+ # say that we just created the symbol
+ # then, binding[the new symbol entry]
+ # by default points to the symbol.
+ # So the value of an unassigned symbol will
+ # be just its name.
+ binding[i] = symtab[i]
+ isSymbolReclaimable[i] = false
+
+ return symtab[i]
+
+# get the symbol's printname
+
+# p is a U
+get_printname = (p) ->
+ if (p.k != SYM)
+ stop("symbol error")
+ return p.printname
+
+
+# p and q are both U
+# there are two Us at play here. One belongs to the
+# symtab array and is the variable name.
+# The other one is the U with the content, and that
+# one will go in the corresponding "binding" array entry.
+set_binding = (p, q) ->
+ if (p.k != SYM)
+ stop("symbol error")
+
+
+ #console.log "setting binding of " + p.toString() + " to: " + q.toString()
+ #if p.toString() == "aaa"
+ # debugger
+
+ indexFound = symtab.indexOf(p)
+ ###
+ if indexFound == -1
+ debugger
+ for i in [0...symtab.length]
+ if p.printname == symtab[i].printname
+ indexFound = i
+ console.log "remedied an index not found!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+ break
+ ###
+
+ if symtab.indexOf(p, indexFound + 1) != -1
+ console.log("ops, more than one element!")
+ debugger
+ if DEBUG then console.log("lookup >> set_binding lookup " + indexFound)
+ isSymbolReclaimable[indexFound] = false
+ binding[indexFound] = q
+
+# p is a U
+get_binding = (p) ->
+ if (p.k != SYM)
+ stop("symbol error")
+
+ #console.log "getting binding of " + p.toString()
+ #if p.toString() == "aaa"
+ # debugger
+
+ indexFound = symtab.indexOf(p)
+ ###
+ if indexFound == -1
+ debugger
+ for i in [0...symtab.length]
+ if p.printname == symtab[i].printname
+ indexFound = i
+ console.log "remedied an index not found!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
+ break
+ ###
+
+ if symtab.indexOf(p, indexFound + 1) != -1
+ console.log("ops, more than one element!")
+ debugger
+ if DEBUG then console.log("lookup >> get_binding lookup " + indexFound)
+ #if indexFound == 139
+ # debugger
+ #if indexFound == 137
+ # debugger
+ return binding[indexFound]
+
+# the concept of user symbol is a little fuzzy
+# beucase mathematics is full of symbols that actually
+# have a special meaning, e.g. e,i,I in some cases j...
+is_usr_symbol = (p) ->
+ if (p.k != SYM)
+ return false
+ theSymnum = symnum(p)
+ # see "defs" file for the naming of the symbols
+ if theSymnum > PI and theSymnum != SYMBOL_I and theSymnum != SYMBOL_IDENTITY_MATRIX
+ return true
+ return false
+
+# get symbol's number from ptr
+# p is U
+lookupsTotal = 0
+symnum = (p) ->
+ lookupsTotal++
+ if (p.k != SYM)
+ stop("symbol error")
+ indexFound = symtab.indexOf(p)
+ if symtab.indexOf(p, indexFound + 1) != -1
+ console.log("ops, more than one element!")
+ debugger
+ if DEBUG then console.log("lookup >> symnum lookup " + indexFound + " lookup # " + lookupsTotal)
+ #if lookupsTotal == 21
+ # debugger
+ #if indexFound == 79
+ # debugger
+ return indexFound
+
+# push indexed symbol
+
+# k is an int
+push_symbol = (k) ->
+ push(symtab[k])
+
+clear_symbols = ->
+ # we can clear just what's assignable.
+ # everything before NIL is not assignable,
+ # so there is no need to clear it.
+ for i in [NIL+1...NSYM]
+
+ # stop at the first empty
+ # entry that is not reclaimable
+ if symtab[i].printname == ""
+ if isSymbolReclaimable[i] == false
+ break
+ else
+ continue
+
+ symtab[i] = new U()
+ symtab[i].k = SYM
+ binding[i] = symtab[i]
+ isSymbolReclaimable[i] = false
+ #symtab[i].printname = ""
+ #binding[i] = symtab[i]
+
+
+# collect all the variables in a tree
+collectUserSymbols = (p, accumulator = []) ->
+
+ if is_usr_symbol(p)
+ if accumulator.indexOf(p) == -1
+ accumulator.push p
+ return
+
+ if (istensor(p))
+ for i in [0...p.tensor.nelem]
+ collectUserSymbols p.tensor.elem[i], accumulator
+ return
+
+ while (iscons(p))
+ collectUserSymbols(car(p), accumulator)
+ p = cdr(p)
+
+ return
+
+$.get_binding = get_binding
+$.set_binding = set_binding
+$.usr_symbol = usr_symbol
+$.symbolsinfo = symbolsinfo
+$.collectUserSymbols = collectUserSymbols
diff --git a/node_modules/algebrite/runtime/zombocom.coffee b/node_modules/algebrite/runtime/zombocom.coffee
new file mode 100644
index 0000000..77bc00c
--- /dev/null
+++ b/node_modules/algebrite/runtime/zombocom.coffee
@@ -0,0 +1,70 @@
+
+
+if !inited
+ inited = true
+ init()
+
+
+$.init = init
+
+parse_internal = (argu) ->
+ if typeof argu == 'string'
+ scan(argu)
+ # now its in the stack
+ else if typeof argu == 'number'
+ if argu % 1 == 0
+ push_integer(argu)
+ else
+ push_double(argu)
+ else if argu instanceof U
+ # hey look its a U
+ push(argu)
+ else
+ console.warn('unknown argument type', argu)
+ push(symbol(NIL))
+
+parse = (argu) ->
+ try
+ parse_internal(argu)
+ data = pop()
+ check_stack()
+ catch error
+ reset_after_error()
+ throw error
+ return data
+
+# exec handles the running ia JS of all the algebrite
+# functions. The function name is passed in "name" and
+# the corresponding function is pushed at the top of the stack
+exec = (name, argus...) ->
+ fn = get_binding(usr_symbol(name))
+ check_stack()
+ push(fn)
+
+ for argu in argus
+ parse_internal(argu)
+
+ list(1 + argus.length)
+
+ p1 = pop()
+ push(p1)
+
+ try
+ top_level_eval()
+ result = pop()
+ check_stack()
+ catch error
+ reset_after_error()
+ throw error
+
+ return result
+
+
+$.exec = exec
+$.parse = parse
+
+do ->
+ builtin_fns = ["abs", "add", "adj", "and", "approxratio", "arccos", "arccosh", "arcsin", "arcsinh", "arctan", "arctanh", "arg", "atomize", "besselj", "bessely", "binding", "binomial", "ceiling", "check", "choose", "circexp", "clear", "clearall", "clearpatterns", "clock", "coeff", "cofactor", "condense", "conj", "contract", "cos", "cosh", "decomp", "defint", "deg", "denominator", "det", "derivative", "dim", "dirac", "divisors", "do", "dot", "draw", "dsolve", "eigen", "eigenval", "eigenvec", "erf", "erfc", "eval", "exp", "expand", "expcos", "expsin", "factor", "factorial", "factorpoly", "filter", "float", "floor", "for", "Gamma", "gcd", "hermite", "hilbert", "imag", "component", "inner", "integral", "inv", "invg", "isinteger", "isprime", "laguerre", "lcm", "leading", "legendre", "log", "mod", "multiply", "not", "nroots", "number", "numerator", "operator", "or", "outer", "pattern", "patternsinfo", "polar", "power", "prime", "print", "print2dascii", "printcomputer", "printlatex", "printlist", "printhuman", "product", "quote", "quotient", "rank", "rationalize", "real", "rect", "roots", "round", "equals", "shape", "sgn", "silentpattern", "simplify", "sin", "sinh", "sqrt", "stop", "subst", "sum", "symbolsinfo", "tan", "tanh", "taylor", "test", "testeq", "testge", "testgt", "testle", "testlt", "transpose", "unit", "zero"]
+
+ for fn in builtin_fns
+ $[fn] = exec.bind(this, fn)
diff --git a/node_modules/algebrite/sources/abs.coffee b/node_modules/algebrite/sources/abs.coffee
new file mode 100644
index 0000000..5d9ae09
--- /dev/null
+++ b/node_modules/algebrite/sources/abs.coffee
@@ -0,0 +1,285 @@
+#(docs are generated from top-level comments, keep an eye on the formatting!)
+
+### abs =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the absolute value of a real number, the magnitude of a complex number, or the vector length.
+
+###
+
+###
+ Absolute value of a number,or magnitude of complex z, or norm of a vector
+
+ z abs(z)
+ - ------
+
+ a a
+
+ -a a
+
+ (-1)^a 1
+
+ exp(a + i b) exp(a)
+
+ a b abs(a) abs(b)
+
+ a + i b sqrt(a^2 + b^2)
+
+Notes
+
+ 1. Handles mixed polar and rectangular forms, e.g. 1 + exp(i pi/3)
+
+ 2. jean-francois.debroux reports that when z=(a+i*b)/(c+i*d) then
+
+ abs(numerator(z)) / abs(denominator(z))
+
+ must be used to get the correct answer. Now the operation is
+ automatic.
+###
+
+
+DEBUG_ABS = false
+
+Eval_abs = ->
+ push(cadr(p1))
+ Eval()
+ abs()
+
+absValFloat = ->
+ Eval()
+ absval()
+ Eval(); # normalize
+ zzfloat()
+ # zzfloat of an abs doesn't necessarily result in a double
+ # , for example if there are variables. But
+ # in many of the tests there should be indeed
+ # a float, these two lines come handy to highlight
+ # when that doesn't happen for those tests.
+ #if !isdouble(stack[tos-1])
+ # stop("absValFloat should return a double and instead got: " + stack[tos-1])
+
+abs = ->
+ theArgument = top()
+ if DEBUG_ABS then console.trace ">>>> ABS of " + theArgument
+ numerator()
+ if DEBUG_ABS then console.log "ABS numerator " + stack[tos-1]
+ absval()
+ if DEBUG_ABS then console.log "ABSVAL numerator: " + stack[tos-1]
+
+ push(theArgument)
+ denominator()
+ if DEBUG_ABS then console.log "ABS denominator: " + stack[tos-1]
+ absval()
+ if DEBUG_ABS then console.log "ABSVAL denominator: " + stack[tos-1]
+
+ divide()
+ if DEBUG_ABS then console.log "ABSVAL divided: " + stack[tos-1]
+
+ if DEBUG_ABS then console.log "<<<<<<< ABS"
+
+absval = ->
+ save()
+ p1 = pop()
+ input = p1
+
+ if DEBUG_ABS then console.log "ABS of " + p1
+
+
+ # handle all the "number" cases first -----------------------------------------
+ if (isZeroAtomOrTensor(p1))
+ if DEBUG_ABS then console.log " abs: " + p1 + " just zero"
+ push(zero)
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ if (isnegativenumber(p1))
+ if DEBUG_ABS then console.log " abs: " + p1 + " just a negative"
+ push(p1)
+ negate()
+ restore()
+ return
+
+ if (ispositivenumber(p1))
+ if DEBUG_ABS then console.log " abs: " + p1 + " just a positive"
+ push(p1)
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ if (p1 == symbol(PI))
+ if DEBUG_ABS then console.log " abs: " + p1 + " of PI"
+ push(p1)
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ # ??? should there be a shortcut case here for the imaginary unit?
+
+ # now handle decomposition cases ----------------------------------------------
+
+ # we catch the "add", "power", "multiply" cases first,
+ # before falling back to the
+ # negative/positive cases because there are some
+ # simplification thay we might be able to do.
+ # Note that for this routine to give a correct result, this
+ # must be a sum where a complex number appears.
+ # If we apply this to "a+b", we get an incorrect result.
+ if (car(p1) == symbol(ADD) and (
+ findPossibleClockForm(p1) or
+ findPossibleExponentialForm(p1) or
+ Find(p1,imaginaryunit))
+ )
+ if DEBUG_ABS then console.log " abs: " + p1 + " is a sum"
+ if DEBUG_ABS then console.log "abs of a sum"
+ # sum
+ push(p1)
+ rect() # convert polar terms, if any
+ p1 = pop()
+ push(p1)
+ real()
+ push_integer(2)
+ power()
+ push(p1)
+ imag()
+ push_integer(2)
+ power()
+ add()
+ push_rational(1, 2)
+ power()
+ simplify_trig()
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ if (car(p1) == symbol(POWER) && equaln(cadr(p1), -1))
+ if DEBUG_ABS then console.log " abs: " + p1 + " is -1 to any power"
+ # -1 to any power
+ if evaluatingAsFloats
+ if DEBUG_ABS then console.log " abs: numeric, so result is 1.0"
+ push_double(1.0)
+ else
+ if DEBUG_ABS then console.log " abs: symbolic, so result is 1"
+ push_integer(1)
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ # abs(a^b) is equal to abs(a)^b IF b is positive
+ if (car(p1) == symbol(POWER) && ispositivenumber(caddr(p1)))
+ if DEBUG_ABS then console.log " abs: " + p1 + " is something to the power of a positive number"
+ push cadr(p1)
+ abs()
+ push caddr(p1)
+ power()
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ # abs(e^something)
+ if (car(p1) == symbol(POWER) && cadr(p1) == symbol(E))
+ if DEBUG_ABS then console.log " abs: " + p1 + " is an exponential"
+ # exponential
+ push(caddr(p1))
+ real()
+ exponential()
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ if (car(p1) == symbol(MULTIPLY))
+ if DEBUG_ABS then console.log " abs: " + p1 + " is a product"
+ # product
+ anyFactorsYet = false
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ absval()
+ if anyFactorsYet
+ multiply()
+ anyFactorsYet = true
+ p1 = cdr(p1)
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ if (car(p1) == symbol(ABS))
+ if DEBUG_ABS then console.log " abs: " + p1 + " is abs of a abs"
+ # abs of a abs
+ push_symbol(ABS)
+ push cadr(p1)
+ list(2)
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+
+ ###
+ # Evaluation via zzfloat()
+ # ...while this is in theory a powerful mechanism, I've commented it
+ # out because I've refined this method enough to not need this.
+ # Evaling via zzfloat() is in principle more problematic because it could
+ # require further evaluations which could end up in further "abs" which
+ # would end up in infinite loops. Better not use it if not necessary.
+
+ # we look directly at the float evaluation of the argument
+ # to see if we end up with a number, which would mean that there
+ # is no imaginary component and we can just return the input
+ # (or its negation) as the result.
+ push p1
+ zzfloat()
+ floatEvaluation = pop()
+
+ if (isnegativenumber(floatEvaluation))
+ if DEBUG_ABS then console.log " abs: " + p1 + " just a negative"
+ push(p1)
+ negate()
+ restore()
+ return
+
+ if (ispositivenumber(floatEvaluation))
+ if DEBUG_ABS then console.log " abs: " + p1 + " just a positive"
+ push(p1)
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+ return
+ ###
+
+ if (istensor(p1))
+ absval_tensor()
+ restore()
+ return
+
+ if (isnegativeterm(p1) || (car(p1) == symbol(ADD) && isnegativeterm(cadr(p1))))
+ push(p1)
+ negate()
+ p1 = pop()
+
+ if DEBUG_ABS then console.log " abs: " + p1 + " is nothing decomposable"
+ push_symbol(ABS)
+ push(p1)
+ list(2)
+
+ if DEBUG_ABS then console.log " --> ABS of " + input + " : " + stack[tos-1]
+ restore()
+
+# also called the "norm" of a vector
+absval_tensor = ->
+ if (p1.tensor.ndim != 1)
+ stop("abs(tensor) with tensor rank > 1")
+ push(p1)
+ push(p1)
+ conjugate()
+ inner()
+ push_rational(1, 2)
+ power()
+ simplify()
+ Eval()
diff --git a/node_modules/algebrite/sources/add.coffee b/node_modules/algebrite/sources/add.coffee
new file mode 100644
index 0000000..62dd9e2
--- /dev/null
+++ b/node_modules/algebrite/sources/add.coffee
@@ -0,0 +1,335 @@
+###
+ Symbolic addition
+
+ Terms in a sum are combined if they are identical modulo rational
+ coefficients.
+
+ For example, A + 2A becomes 3A.
+
+ However, the sum A + sqrt(2) A is not modified.
+
+ Combining terms can lead to second-order effects.
+
+ For example, consider the case of
+
+ 1/sqrt(2) A + 3/sqrt(2) A + sqrt(2) A
+
+ The first two terms are combined to yield 2 sqrt(2) A.
+
+ This result can now be combined with the third term to yield
+
+ 3 sqrt(2) A
+###
+
+
+
+flag = 0
+
+Eval_add = ->
+ h = tos
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ p2 = pop()
+ push_terms(p2)
+ p1 = cdr(p1)
+ add_terms(tos - h)
+
+# Add n terms, returns one expression on the stack.
+
+stackAddsCount = 0
+add_terms = (n) ->
+ stackAddsCount++
+ i = 0
+
+ h = tos - n
+
+ s = h
+
+ # ensure no infinite loop, use "for"
+
+ if DEBUG then console.log "stack before adding terms #" + stackAddsCount
+ #if stackAddsCount == 137
+ # debugger
+
+ if DEBUG
+ for i in [0...tos]
+ console.log print_list stack[i]
+
+ for i in [0...10]
+
+ if (n < 2)
+ break
+
+ flag = 0
+
+
+ #qsort(s, n, sizeof (U *), cmp_terms)
+ subsetOfStack = stack.slice(h,h+n)
+ subsetOfStack.sort(cmp_terms)
+ stack = stack.slice(0,h).concat(subsetOfStack).concat(stack.slice(h+n))
+
+ if (flag == 0)
+ break
+
+ n = combine_terms(h, n)
+
+ moveTos h + n
+
+ switch (n)
+ when 0
+ if evaluatingAsFloats then push_double(0.0) else push(zero)
+ when 1
+ else
+ list(n)
+ p1 = pop()
+ push_symbol(ADD)
+ push(p1)
+ cons()
+
+ if DEBUG then console.log "stack after adding terms #" + stackAddsCount
+ #if stackAddsCount == 5
+ # debugger
+
+ if DEBUG
+ for i in [0...tos]
+ console.log print_list stack[i]
+
+# Compare terms for order, clobbers p1 and p2.
+
+cmp_terms_count = 0
+cmp_terms = (p1, p2) ->
+ cmp_terms_count++
+ #if cmp_terms_count == 52
+ # debugger
+
+ i = 0
+ # numbers can be combined
+
+ if (isNumericAtom(p1) && isNumericAtom(p2))
+ flag = 1
+ #if DEBUG then console.log "cmp_terms #" + cmp_terms_count + " returns 0"
+ return 0
+
+ # congruent tensors can be combined
+
+ if (istensor(p1) && istensor(p2))
+ if (p1.tensor.ndim < p2.tensor.ndim)
+ #if DEBUG then console.log "cmp_terms #" + cmp_terms_count + " returns -1"
+ return -1
+ if (p1.tensor.ndim > p2.tensor.ndim)
+ #if DEBUG then console.log "cmp_terms #" + cmp_terms_count + " returns 1"
+ return 1
+ for i in [0...p1.tensor.ndim]
+ if (p1.tensor.dim[i] < p2.tensor.dim[i])
+ #if DEBUG then console.log "cmp_terms #" + cmp_terms_count + " returns -1"
+ return -1
+ if (p1.tensor.dim[i] > p2.tensor.dim[i])
+ #if DEBUG then console.log "cmp_terms #" + cmp_terms_count + " returns 1"
+ return 1
+ flag = 1
+ #if DEBUG then console.log "cmp_terms #" + cmp_terms_count + " returns 0"
+ return 0
+
+ if (car(p1) == symbol(MULTIPLY))
+ p1 = cdr(p1)
+ if (isNumericAtom(car(p1)))
+ p1 = cdr(p1)
+ if (cdr(p1) == symbol(NIL))
+ p1 = car(p1)
+
+ if (car(p2) == symbol(MULTIPLY))
+ p2 = cdr(p2)
+ if (isNumericAtom(car(p2)))
+ p2 = cdr(p2)
+ if (cdr(p2) == symbol(NIL))
+ p2 = car(p2)
+
+ t = cmp_expr(p1, p2)
+
+ if (t == 0)
+ flag = 1
+
+ #if DEBUG then console.log "cmp_terms #" + cmp_terms_count + " returns " + t
+ return t
+
+###
+ Compare adjacent terms in s[] and combine if possible.
+
+ Returns the number of terms remaining in s[].
+
+ n number of terms in s[] initially
+###
+
+combine_terms = (s, n) ->
+
+ #debugger
+
+ # I had to turn the coffeescript for loop into
+ # a more mundane while loop because the i
+ # variable was changed from within the body,
+ # which is something that is not supposed to
+ # happen in the coffeescript 'vector' form.
+ # Also this means I had to add a 'i++' jus before
+ # the end of the body and before the "continue"s
+ i=0
+ while i < (n-1)
+ check_esc_flag()
+
+ p3 = stack[s+i]
+ p4 = stack[s+i + 1]
+
+ if (istensor(p3) && istensor(p4))
+ push(p3)
+ push(p4)
+ tensor_plus_tensor()
+ p1 = pop()
+ if (p1 != symbol(NIL))
+ stack[s+i] = p1
+ for j in [(i + 1)...(n - 1)]
+ stack[s+j] = stack[s+j + 1]
+ n--
+ i--
+
+ i++
+ continue
+
+ if (istensor(p3) || istensor(p4))
+
+ i++
+ continue
+
+ if (isNumericAtom(p3) && isNumericAtom(p4))
+ push(p3)
+ push(p4)
+ add_numbers()
+ p1 = pop()
+ if (isZeroAtomOrTensor(p1))
+ for j in [i...(n - 2)]
+ stack[s+j] = stack[s+j + 2]
+ n -= 2
+ else
+ stack[s+i] = p1
+ for j in [(i + 1)...(n - 1)]
+ stack[s+j] = stack[s+j + 1]
+ n--
+ i--
+
+ i++
+ continue
+
+ if (isNumericAtom(p3) || isNumericAtom(p4))
+
+ i++
+ continue
+
+ if evaluatingAsFloats
+ p1 = one_as_double
+ p2 = one_as_double
+ else
+ p1 = one
+ p2 = one
+
+ t = 0
+
+ if (car(p3) == symbol(MULTIPLY))
+ p3 = cdr(p3)
+ t = 1; # p3 is now denormal
+ if (isNumericAtom(car(p3)))
+ p1 = car(p3)
+ p3 = cdr(p3)
+ if (cdr(p3) == symbol(NIL))
+ p3 = car(p3)
+ t = 0
+
+ if (car(p4) == symbol(MULTIPLY))
+ p4 = cdr(p4)
+ if (isNumericAtom(car(p4)))
+ p2 = car(p4)
+ p4 = cdr(p4)
+ if (cdr(p4) == symbol(NIL))
+ p4 = car(p4)
+
+ if (!equal(p3, p4))
+
+ i++
+ continue
+
+ push(p1)
+ push(p2)
+ add_numbers()
+
+ p1 = pop()
+
+ if (isZeroAtomOrTensor(p1))
+ for j in [i...(n - 2)]
+ stack[s+j] = stack[s+j + 2]
+ n -= 2
+ i--
+
+ i++
+ continue
+
+ push(p1)
+
+ if (t)
+ push(symbol(MULTIPLY))
+ push(p3)
+ cons()
+ else
+ push(p3)
+
+ multiply()
+
+ stack[s+i] = pop()
+
+ for j in [(i + 1)...(n - 1)]
+ stack[s+j] = stack[s+j + 1]
+
+ n--
+ i--
+
+ # this i++ is to match the while
+ i++
+
+ return n
+
+push_terms = (p) ->
+ if (car(p) == symbol(ADD))
+ p = cdr(p)
+ while (iscons(p))
+ push(car(p))
+ p = cdr(p)
+ # omit zeroes
+ else if (!isZeroAtom(p))
+ push(p)
+
+# add two expressions
+
+add = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ h = tos
+ push_terms(p1)
+ push_terms(p2)
+ add_terms(tos - h)
+ restore()
+
+add_all = (k) ->
+ i = 0
+ save()
+ s = tos - k
+ h = tos
+ for i in [0...k]
+ push_terms(stack[s+i])
+ add_terms(tos - h)
+ p1 = pop()
+ moveTos tos - k
+ push(p1)
+ restore()
+
+subtract = ->
+ negate()
+ add()
diff --git a/node_modules/algebrite/sources/adj.coffee b/node_modules/algebrite/sources/adj.coffee
new file mode 100644
index 0000000..e704c4a
--- /dev/null
+++ b/node_modules/algebrite/sources/adj.coffee
@@ -0,0 +1,54 @@
+### adj =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+m
+
+General description
+-------------------
+Returns the adjunct of matrix m. The inverse of m is equal to adj(m) divided by det(m).
+
+###
+
+
+Eval_adj = ->
+ push(cadr(p1))
+ Eval()
+ adj()
+
+adj = ->
+ i = 0
+ j = 0
+ n = 0
+
+ save()
+
+ p1 = pop()
+
+ if (istensor(p1) && p1.tensor.ndim == 2 && p1.tensor.dim[0] == p1.tensor.dim[1])
+ doNothing = 1
+ else
+ stop("adj: square matrix expected")
+
+ n = p1.tensor.dim[0]
+
+ p2 = alloc_tensor(n * n)
+
+ p2.tensor.ndim = 2
+ p2.tensor.dim[0] = n
+ p2.tensor.dim[1] = n
+
+ for i in [0...n]
+ for j in [0...n]
+ cofactor(p1, n, i, j)
+ p2.tensor.elem[n * j + i] = pop(); # transpose
+
+ push(p2)
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/approxratio.coffee b/node_modules/algebrite/sources/approxratio.coffee
new file mode 100644
index 0000000..4ae8fa2
--- /dev/null
+++ b/node_modules/algebrite/sources/approxratio.coffee
@@ -0,0 +1,1047 @@
+###
+ Guesses a rational for each float in the passed expression
+###
+
+
+Eval_approxratio = ->
+ theArgument = cadr(p1)
+ push(theArgument)
+ approxratioRecursive()
+
+approxratioRecursive = ->
+ i = 0
+ save()
+ p1 = pop(); # expr
+ if (istensor(p1))
+ p4 = alloc_tensor(p1.tensor.nelem)
+ p4.tensor.ndim = p1.tensor.ndim
+ for i in [0...p1.tensor.ndim]
+ p4.tensor.dim[i] = p1.tensor.dim[i]
+ for i in [0...p1.tensor.nelem]
+ push(p1.tensor.elem[i])
+ approxratioRecursive()
+ p4.tensor.elem[i] = pop()
+
+ check_tensor_dimensions p4
+
+ push(p4)
+ else if p1.k == DOUBLE
+ push(p1)
+ approxOneRatioOnly()
+ else if (iscons(p1))
+ push(car(p1))
+ approxratioRecursive()
+ push(cdr(p1))
+ approxratioRecursive()
+ cons()
+ else
+ push(p1)
+ restore()
+
+approxOneRatioOnly = ->
+ zzfloat()
+ supposedlyTheFloat = pop()
+ if supposedlyTheFloat.k == DOUBLE
+ theFloat = supposedlyTheFloat.d
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ theRatio = floatToRatioRoutine(theFloat,precision)
+ push_rational(theRatio[0], theRatio[1])
+ else
+ push_integer(theFloat)
+ return
+
+ # we didn't manage, just leave unexpressed
+ push_symbol(APPROXRATIO)
+ push(theArgument)
+ list(2)
+
+# original routine by John Kennedy, see
+# https://web.archive.org/web/20111027100847/http://homepage.smc.edu/kennedy_john/DEC2FRAC.PDF
+# courtesy of Michael Borcherds
+# who ported this to JavaScript under MIT licence
+# also see
+# https://github.com/geogebra/geogebra/blob/master/common/src/main/java/org/geogebra/common/kernel/algos/AlgoFractionText.java
+# potential other ways to do this:
+# https://rosettacode.org/wiki/Convert_decimal_number_to_rational
+# http://www.homeschoolmath.net/teaching/rational_numbers.php
+# http://stackoverflow.com/questions/95727/how-to-convert-floats-to-human-readable-fractions
+
+floatToRatioRoutine = (decimal, AccuracyFactor) ->
+ FractionNumerator = undefined
+ FractionDenominator = undefined
+ DecimalSign = undefined
+ Z = undefined
+ PreviousDenominator = undefined
+ ScratchValue = undefined
+ ret = [
+ 0
+ 0
+ ]
+ if isNaN(decimal)
+ return ret
+ # return 0/0
+ if decimal == Infinity
+ ret[0] = 1
+ ret[1] = 0
+ # 1/0
+ return ret
+ if decimal == -Infinity
+ ret[0] = -1
+ ret[1] = 0
+ # -1/0
+ return ret
+ if decimal < 0.0
+ DecimalSign = -1.0
+ else
+ DecimalSign = 1.0
+ decimal = Math.abs(decimal)
+ if Math.abs(decimal - Math.floor(decimal)) < AccuracyFactor
+ # handles exact integers including 0
+ FractionNumerator = decimal * DecimalSign
+ FractionDenominator = 1.0
+ ret[0] = FractionNumerator
+ ret[1] = FractionDenominator
+ return ret
+ if decimal < 1.0e-19
+ # X = 0 already taken care of
+ FractionNumerator = DecimalSign
+ FractionDenominator = 9999999999999999999.0
+ ret[0] = FractionNumerator
+ ret[1] = FractionDenominator
+ return ret
+ if decimal > 1.0e19
+ FractionNumerator = 9999999999999999999.0 * DecimalSign
+ FractionDenominator = 1.0
+ ret[0] = FractionNumerator
+ ret[1] = FractionDenominator
+ return ret
+ Z = decimal
+ PreviousDenominator = 0.0
+ FractionDenominator = 1.0
+ loop
+ Z = 1.0 / (Z - Math.floor(Z))
+ ScratchValue = FractionDenominator
+ FractionDenominator = FractionDenominator * Math.floor(Z) + PreviousDenominator
+ PreviousDenominator = ScratchValue
+ FractionNumerator = Math.floor(decimal * FractionDenominator + 0.5)
+ # Rounding Function
+ unless Math.abs(decimal - (FractionNumerator / FractionDenominator)) > AccuracyFactor and Z != Math.floor(Z)
+ break
+ FractionNumerator = DecimalSign * FractionNumerator
+ ret[0] = FractionNumerator
+ ret[1] = FractionDenominator
+ ret
+
+approx_just_an_integer = 0
+approx_sine_of_rational = 1
+approx_sine_of_pi_times_rational = 2
+approx_rationalOfPi = 3
+approx_radicalOfRatio = 4
+approx_nothingUseful = 5
+approx_ratioOfRadical = 6
+approx_rationalOfE = 7
+approx_logarithmsOfRationals = 8
+approx_rationalsOfLogarithms = 9
+
+approxRationalsOfRadicals = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ # simple radicals.
+
+ bestResultSoFar = null
+ minimumComplexity = Number.MAX_VALUE
+
+ for i in [2,3,5,6,7,8,10]
+ for j in [1..10]
+ #console.log "i,j: " + i + "," + j
+ hypothesis = Math.sqrt(i)/j
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+ if error < 2 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * sqrt( " + i + " ) / " + j
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_ratioOfRadical, likelyMultiplier, i, j]
+
+ return bestResultSoFar
+
+approxRadicalsOfRationals = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ # simple radicals.
+
+ bestResultSoFar = null
+ minimumComplexity = Number.MAX_VALUE
+
+ # this one catches things like Math.sqrt(3/4), but
+ # things like Math.sqrt(1/2) are caught by the paragraph
+ # above (and in a better form)
+ for i in [1,2,3,5,6,7,8,10]
+ for j in [1,2,3,5,6,7,8,10]
+ #console.log "i,j: " + i + "," + j
+ hypothesis = Math.sqrt(i/j)
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+ if error < 2 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * (sqrt( " + i + " / " + j + " )"
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_radicalOfRatio, likelyMultiplier, i, j]
+
+ return bestResultSoFar
+
+approxRadicals = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ # simple radicals.
+
+ # we always prefer a rational of a radical of an integer
+ # to a radical of a rational. Radicals of rationals generate
+ # radicals at the denominator which we'd rather avoid
+
+ approxRationalsOfRadicalsResult = approxRationalsOfRadicals theFloat
+ if approxRationalsOfRadicalsResult?
+ return approxRationalsOfRadicalsResult
+
+ approxRadicalsOfRationalsResult = approxRadicalsOfRationals theFloat
+ if approxRadicalsOfRationalsResult?
+ return approxRadicalsOfRationalsResult
+
+ return null
+
+approxLogs = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ # we always prefer a rational of a log to a log of
+ # a rational
+
+ approxRationalsOfLogsResult = approxRationalsOfLogs theFloat
+ if approxRationalsOfLogsResult?
+ return approxRationalsOfLogsResult
+
+ approxLogsOfRationalsResult = approxLogsOfRationals theFloat
+ if approxLogsOfRationalsResult?
+ return approxLogsOfRationalsResult
+
+ return null
+
+approxRationalsOfLogs = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ bestResultSoFar = null
+ minimumComplexity = Number.MAX_VALUE
+
+ # simple rationals of logs
+ for i in [2..5]
+ for j in [1..5]
+ #console.log "i,j: " + i + "," + j
+ hypothesis = Math.log(i)/j
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+
+ # it does happen that due to roundings
+ # a "higher multiple" is picked, which is obviously
+ # unintended.
+ # E.g. 1 * log(1 / 3 ) doesn't match log( 3 ) BUT
+ # it matches -5 * log( 3 ) / 5
+ # so we avoid any case where the multiplier is a multiple
+ # of the divisor.
+ if likelyMultiplier != 1 and Math.abs(Math.floor(likelyMultiplier/j)) == Math.abs(likelyMultiplier/j)
+ continue
+
+ if error < 2.2 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * log( " + i + " ) / " + j
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_rationalsOfLogarithms, likelyMultiplier, i, j]
+
+ return bestResultSoFar
+
+approxLogsOfRationals = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ bestResultSoFar = null
+ minimumComplexity = Number.MAX_VALUE
+
+ # simple logs of rationals
+ for i in [1..5]
+ for j in [1..5]
+ #console.log "i,j: " + i + "," + j
+ hypothesis = Math.log(i/j)
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+ if error < 1.96 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * log( " + i + " / " + j + " )"
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_logarithmsOfRationals, likelyMultiplier, i, j]
+
+ return bestResultSoFar
+
+approxRationalsOfPowersOfE = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ bestResultSoFar = null
+ minimumComplexity = Number.MAX_VALUE
+
+ # simple rationals of a few powers of e
+ for i in [1..2]
+ for j in [1..12]
+ #console.log "i,j: " + i + "," + j
+ hypothesis = Math.pow(Math.E,i)/j
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+ if error < 2 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * (e ^ " + i + " ) / " + j
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_rationalOfE, likelyMultiplier, i, j]
+
+ return bestResultSoFar
+
+approxRationalsOfPowersOfPI = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+ bestResultSoFar = null
+
+ # here we do somethng a little special: since
+ # the powers of pi can get quite big, there might
+ # be multiple hypothesis where more of the
+ # magnitude is shifted to the multiplier, and some
+ # where more of the magnitude is shifted towards the
+ # exponent of pi. So we prefer the hypotheses with the
+ # lower multiplier since it's likely to insert more
+ # information.
+ minimumComplexity = Number.MAX_VALUE
+
+ # simple rationals of a few powers of PI
+ for i in [1..5]
+ for j in [1..12]
+ #console.log "i,j: " + i + "," + j
+ hypothesis = Math.pow(Math.PI,i)/j
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+ if error < 2 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * (pi ^ " + i + " ) / " + j + " )"
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_rationalOfPi, likelyMultiplier, i, j]
+
+ #console.log "approxRationalsOfPowersOfPI returning: " + bestResultSoFar
+ return bestResultSoFar
+
+approxTrigonometric = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ # we always prefer a sin of a rational without the PI
+
+ approxSineOfRationalsResult = approxSineOfRationals theFloat
+ if approxSineOfRationalsResult?
+ return approxSineOfRationalsResult
+
+ approxSineOfRationalMultiplesOfPIResult = approxSineOfRationalMultiplesOfPI theFloat
+ if approxSineOfRationalMultiplesOfPIResult?
+ return approxSineOfRationalMultiplesOfPIResult
+
+ return null
+
+approxSineOfRationals = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ bestResultSoFar = null
+ minimumComplexity = Number.MAX_VALUE
+
+ # we only check very simple rationals because they begin to get tricky
+ # quickly, also they collide often with the "rational of pi" hypothesis.
+ # For example sin(11) is veeery close to 1 (-0.99999020655)
+ # (see: http://mathworld.wolfram.com/AlmostInteger.html )
+ # we stop at rationals that mention up to 10
+ for i in [1..4]
+ for j in [1..4]
+ #console.log "i,j: " + i + "," + j
+ fraction = i/j
+ hypothesis = Math.sin(fraction)
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+ if error < 2 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * sin( " + i + "/" + j + " )"
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_sine_of_rational, likelyMultiplier, i, j]
+
+ return bestResultSoFar
+
+approxSineOfRationalMultiplesOfPI = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ bestResultSoFar = null
+ minimumComplexity = Number.MAX_VALUE
+
+ # check rational multiples of pi
+ for i in [1..13]
+ for j in [1..13]
+ #console.log "i,j: " + i + "," + j
+ fraction = i/j
+ hypothesis = Math.sin(Math.PI * fraction)
+ #console.log "hypothesis: " + hypothesis
+ if Math.abs(hypothesis) > 1e-10
+ ratio = theFloat/hypothesis
+ likelyMultiplier = Math.round(ratio)
+ #console.log "ratio: " + ratio
+ error = Math.abs(1 - ratio/likelyMultiplier)
+ else
+ ratio = 1
+ likelyMultiplier = 1
+ error = Math.abs(theFloat - hypothesis)
+ #console.log "error: " + error
+ # magic number 23 comes from the case sin(pi/10)
+ if error < 23 * precision
+ complexity = simpleComplexityMeasure likelyMultiplier, i, j
+ if complexity < minimumComplexity
+ #console.log "MINIMUM MULTIPLIER SO FAR"
+ minimumComplexity = complexity
+ result = likelyMultiplier + " * sin( " + i + "/" + j + " * pi )"
+ #console.log result + " error: " + error
+ bestResultSoFar = [result, approx_sine_of_pi_times_rational, likelyMultiplier, i, j]
+
+ return bestResultSoFar
+
+approxAll = (theFloat) ->
+ splitBeforeAndAfterDot = theFloat.toString().split(".")
+
+ if splitBeforeAndAfterDot.length == 2
+ numberOfDigitsAfterTheDot = splitBeforeAndAfterDot[1].length
+ precision = 1/Math.pow(10,numberOfDigitsAfterTheDot)
+ else
+ return ["" + Math.floor(theFloat), approx_just_an_integer, Math.floor(theFloat), 1, 2]
+
+ console.log "precision: " + precision
+
+ constantsSumMin = Number.MAX_VALUE
+ constantsSum = 0
+ bestApproxSoFar = null
+
+ LOG_EXPLANATIONS = true
+
+ approxRadicalsResult = approxRadicals theFloat
+ if approxRadicalsResult?
+ constantsSum = simpleComplexityMeasure approxRadicalsResult
+ if constantsSum < constantsSumMin
+ if LOG_EXPLANATIONS then console.log "better explanation by approxRadicals: " + approxRadicalsResult + " complexity: " + constantsSum
+ constantsSumMin = constantsSum
+ bestApproxSoFar = approxRadicalsResult
+ else
+ if LOG_EXPLANATIONS then console.log "subpar explanation by approxRadicals: " + approxRadicalsResult + " complexity: " + constantsSum
+
+ approxLogsResult = approxLogs(theFloat)
+ if approxLogsResult?
+ constantsSum = simpleComplexityMeasure approxLogsResult
+ if constantsSum < constantsSumMin
+ if LOG_EXPLANATIONS then console.log "better explanation by approxLogs: " + approxLogsResult + " complexity: " + constantsSum
+ constantsSumMin = constantsSum
+ bestApproxSoFar = approxLogsResult
+ else
+ if LOG_EXPLANATIONS then console.log "subpar explanation by approxLogs: " + approxLogsResult + " complexity: " + constantsSum
+
+ approxRationalsOfPowersOfEResult = approxRationalsOfPowersOfE(theFloat)
+ if approxRationalsOfPowersOfEResult?
+ constantsSum = simpleComplexityMeasure approxRationalsOfPowersOfEResult
+ if constantsSum < constantsSumMin
+ if LOG_EXPLANATIONS then console.log "better explanation by approxRationalsOfPowersOfE: " + approxRationalsOfPowersOfEResult + " complexity: " + constantsSum
+ constantsSumMin = constantsSum
+ bestApproxSoFar = approxRationalsOfPowersOfEResult
+ else
+ if LOG_EXPLANATIONS then console.log "subpar explanation by approxRationalsOfPowersOfE: " + approxRationalsOfPowersOfEResult + " complexity: " + constantsSum
+
+ approxRationalsOfPowersOfPIResult = approxRationalsOfPowersOfPI(theFloat)
+ if approxRationalsOfPowersOfPIResult?
+ constantsSum = simpleComplexityMeasure approxRationalsOfPowersOfPIResult
+ if constantsSum < constantsSumMin
+ if LOG_EXPLANATIONS then console.log "better explanation by approxRationalsOfPowersOfPI: " + approxRationalsOfPowersOfPIResult + " complexity: " + constantsSum
+ constantsSumMin = constantsSum
+ bestApproxSoFar = approxRationalsOfPowersOfPIResult
+ else
+ if LOG_EXPLANATIONS then console.log "subpar explanation by approxRationalsOfPowersOfPI: " + approxRationalsOfPowersOfPIResult + " complexity: " + constantsSum
+
+ approxTrigonometricResult = approxTrigonometric(theFloat)
+ if approxTrigonometricResult?
+ constantsSum = simpleComplexityMeasure approxTrigonometricResult
+ if constantsSum < constantsSumMin
+ if LOG_EXPLANATIONS then console.log "better explanation by approxTrigonometric: " + approxTrigonometricResult + " complexity: " + constantsSum
+ constantsSumMin = constantsSum
+ bestApproxSoFar = approxTrigonometricResult
+ else
+ if LOG_EXPLANATIONS then console.log "subpar explanation by approxTrigonometric: " + approxTrigonometricResult + " complexity: " + constantsSum
+
+
+ return bestApproxSoFar
+
+simpleComplexityMeasure = (aResult, b, c) ->
+
+ theSum = null
+
+ if aResult instanceof Array
+
+ # we want PI and E to somewhat increase the
+ # complexity of the expression, so basically they count
+ # more than any integer lower than 3, i.e. we consider
+ # 1,2,3 to be more fundamental than PI or E.
+ switch aResult[1]
+ when approx_sine_of_pi_times_rational
+ theSum = 4
+ # exponents of PI and E need to be penalised as well
+ # otherwise they come to explain any big number
+ # so we count them just as much as the multiplier
+ when approx_rationalOfPi
+ theSum = Math.pow(4,Math.abs(aResult[3])) * Math.abs(aResult[2])
+ when approx_rationalOfE
+ theSum = Math.pow(3,Math.abs(aResult[3])) * Math.abs(aResult[2])
+ else theSum = 0
+
+ theSum += Math.abs(aResult[2]) * (Math.abs(aResult[3]) + Math.abs(aResult[4]))
+ else
+ theSum += Math.abs(aResult) * (Math.abs(b) + Math.abs(c))
+
+ # heavily discount unit constants
+
+ if aResult[2] == 1
+ theSum -= 1
+ else
+ theSum += 1
+
+ if aResult[3] == 1
+ theSum -= 1
+ else
+ theSum += 1
+
+ if aResult[4] == 1
+ theSum -= 1
+ else
+ theSum += 1
+
+ if theSum < 0
+ theSum = 0
+
+ return theSum
+
+
+testApprox = () ->
+
+ for i in [2,3,5,6,7,8,10]
+ for j in [2,3,5,6,7,8,10]
+ if i == j then continue # this is just 1
+ console.log "testapproxRadicals testing: " + "1 * sqrt( " + i + " ) / " + j
+ fraction = i/j
+ value = Math.sqrt(i)/j
+ returned = approxRadicals(value)
+ returnedValue = returned[2] * Math.sqrt(returned[3])/returned[4]
+ if Math.abs(value - returnedValue) > 1e-15
+ console.log "fail testapproxRadicals: " + "1 * sqrt( " + i + " ) / " + j + " . obtained: " + returned
+
+ for i in [2,3,5,6,7,8,10]
+ for j in [2,3,5,6,7,8,10]
+ if i == j then continue # this is just 1
+ console.log "testapproxRadicals testing with 4 digits: " + "1 * sqrt( " + i + " ) / " + j
+ fraction = i/j
+ originalValue = Math.sqrt(i)/j
+ value = originalValue.toFixed(4)
+ returned = approxRadicals(value)
+ returnedValue = returned[2] * Math.sqrt(returned[3])/returned[4]
+ if Math.abs(originalValue - returnedValue) > 1e-15
+ console.log "fail testapproxRadicals with 4 digits: " + "1 * sqrt( " + i + " ) / " + j + " . obtained: " + returned
+
+ for i in [2,3,5,6,7,8,10]
+ for j in [2,3,5,6,7,8,10]
+ if i == j then continue # this is just 1
+ console.log "testapproxRadicals testing: " + "1 * sqrt( " + i + " / " + j + " )"
+ fraction = i/j
+ value = Math.sqrt(i/j)
+ returned = approxRadicals(value)
+ if returned?
+ returnedValue = returned[2] * Math.sqrt(returned[3]/returned[4])
+ if returned[1] == approx_radicalOfRatio and Math.abs(value - returnedValue) > 1e-15
+ console.log "fail testapproxRadicals: " + "1 * sqrt( " + i + " / " + j + " ) . obtained: " + returned
+
+ for i in [1,2,3,5,6,7,8,10]
+ for j in [1,2,3,5,6,7,8,10]
+ if i == 1 and j == 1 then continue
+ console.log "testapproxRadicals testing with 4 digits:: " + "1 * sqrt( " + i + " / " + j + " )"
+ fraction = i/j
+ originalValue = Math.sqrt(i/j)
+ value = originalValue.toFixed(4)
+ returned = approxRadicals(value)
+ returnedValue = returned[2] * Math.sqrt(returned[3]/returned[4])
+ if returned[1] == approx_radicalOfRatio and Math.abs(originalValue - returnedValue) > 1e-15
+ console.log "fail testapproxRadicals with 4 digits:: " + "1 * sqrt( " + i + " / " + j + " ) . obtained: " + returned
+
+ for i in [1..5]
+ for j in [1..5]
+ console.log "testApproxAll testing: " + "1 * log(" + i + " ) / " + j
+ fraction = i/j
+ value = Math.log(i)/j
+ returned = approxAll(value)
+ returnedValue = returned[2] * Math.log(returned[3])/returned[4]
+ if Math.abs(value - returnedValue) > 1e-15
+ console.log "fail testApproxAll: " + "1 * log(" + i + " ) / " + j + " . obtained: " + returned
+
+ for i in [1..5]
+ for j in [1..5]
+ console.log "testApproxAll testing with 4 digits: " + "1 * log(" + i + " ) / " + j
+ fraction = i/j
+ originalValue = Math.log(i)/j
+ value = originalValue.toFixed(4)
+ returned = approxAll(value)
+ returnedValue = returned[2] * Math.log(returned[3])/returned[4]
+ if Math.abs(originalValue - returnedValue) > 1e-15
+ console.log "fail testApproxAll with 4 digits: " + "1 * log(" + i + " ) / " + j + " . obtained: " + returned
+
+ for i in [1..5]
+ for j in [1..5]
+ console.log "testApproxAll testing: " + "1 * log(" + i + " / " + j + " )"
+ fraction = i/j
+ value = Math.log(i/j)
+ returned = approxAll(value)
+ returnedValue = returned[2] * Math.log(returned[3]/returned[4])
+ if Math.abs(value - returnedValue) > 1e-15
+ console.log "fail testApproxAll: " + "1 * log(" + i + " / " + j + " )" + " . obtained: " + returned
+
+ for i in [1..5]
+ for j in [1..5]
+ console.log "testApproxAll testing with 4 digits: " + "1 * log(" + i + " / " + j + " )"
+ fraction = i/j
+ originalValue = Math.log(i/j)
+ value = originalValue.toFixed(4)
+ returned = approxAll(value)
+ returnedValue = returned[2] * Math.log(returned[3]/returned[4])
+ if Math.abs(originalValue - returnedValue) > 1e-15
+ console.log "fail testApproxAll with 4 digits: " + "1 * log(" + i + " / " + j + " )" + " . obtained: " + returned
+
+ for i in [1..2]
+ for j in [1..12]
+ console.log "testApproxAll testing: " + "1 * (e ^ " + i + " ) / " + j
+ fraction = i/j
+ value = Math.pow(Math.E,i)/j
+ returned = approxAll(value)
+ returnedValue = returned[2] * Math.pow(Math.E,returned[3])/returned[4]
+ if Math.abs(value - returnedValue) > 1e-15
+ console.log "fail testApproxAll: " + "1 * (e ^ " + i + " ) / " + j + " . obtained: " + returned
+
+ for i in [1..2]
+ for j in [1..12]
+ console.log "approxRationalsOfPowersOfE testing with 4 digits: " + "1 * (e ^ " + i + " ) / " + j
+ fraction = i/j
+ originalValue = Math.pow(Math.E,i)/j
+ value = originalValue.toFixed(4)
+ returned = approxRationalsOfPowersOfE(value)
+ returnedValue = returned[2] * Math.pow(Math.E,returned[3])/returned[4]
+ if Math.abs(originalValue - returnedValue) > 1e-15
+ console.log "fail approxRationalsOfPowersOfE with 4 digits: " + "1 * (e ^ " + i + " ) / " + j + " . obtained: " + returned
+
+ for i in [1..2]
+ for j in [1..12]
+ console.log "testApproxAll testing: " + "1 * pi ^ " + i + " / " + j
+ fraction = i/j
+ value = Math.pow(Math.PI,i)/j
+ returned = approxAll(value)
+ returnedValue = returned[2] * Math.pow(Math.PI,returned[3])/returned[4]
+ if Math.abs(value - returnedValue) > 1e-15
+ console.log "fail testApproxAll: " + "1 * pi ^ " + i + " / " + j + " ) . obtained: " + returned
+
+ for i in [1..2]
+ for j in [1..12]
+ console.log "approxRationalsOfPowersOfPI testing with 4 digits: " + "1 * pi ^ " + i + " / " + j
+ fraction = i/j
+ originalValue = Math.pow(Math.PI,i)/j
+ value = originalValue.toFixed(4)
+ returned = approxRationalsOfPowersOfPI(value)
+ returnedValue = returned[2] * Math.pow(Math.PI,returned[3])/returned[4]
+ if Math.abs(originalValue - returnedValue) > 1e-15
+ console.log "fail approxRationalsOfPowersOfPI with 4 digits: " + "1 * pi ^ " + i + " / " + j + " ) . obtained: " + returned
+
+ for i in [1..4]
+ for j in [1..4]
+ console.log "testApproxAll testing: " + "1 * sin( " + i + "/" + j + " )"
+ fraction = i/j
+ value = Math.sin(fraction)
+ returned = approxAll(value)
+ returnedFraction = returned[3]/returned[4]
+ returnedValue = returned[2] * Math.sin(returnedFraction)
+ if Math.abs(value - returnedValue) > 1e-15
+ console.log "fail testApproxAll: " + "1 * sin( " + i + "/" + j + " ) . obtained: " + returned
+
+ # 5 digits create no problem
+ for i in [1..4]
+ for j in [1..4]
+ console.log "testApproxAll testing with 5 digits: " + "1 * sin( " + i + "/" + j + " )"
+ fraction = i/j
+ originalValue = Math.sin(fraction)
+ value = originalValue.toFixed(5)
+ returned = approxAll(value)
+ if !returned?
+ console.log "fail testApproxAll with 5 digits: " + "1 * sin( " + i + "/" + j + " ) . obtained: undefined "
+ returnedFraction = returned[3]/returned[4]
+ returnedValue = returned[2] * Math.sin(returnedFraction)
+ error = Math.abs(originalValue - returnedValue)
+ if error > 1e-14
+ console.log "fail testApproxAll with 5 digits: " + "1 * sin( " + i + "/" + j + " ) . obtained: " + returned + " error: " + error
+
+ # 4 digits create two collisions
+ for i in [1..4]
+ for j in [1..4]
+
+ console.log "testApproxAll testing with 4 digits: " + "1 * sin( " + i + "/" + j + " )"
+ fraction = i/j
+ originalValue = Math.sin(fraction)
+ value = originalValue.toFixed(4)
+ returned = approxAll(value)
+ if !returned?
+ console.log "fail testApproxAll with 4 digits: " + "1 * sin( " + i + "/" + j + " ) . obtained: undefined "
+ returnedFraction = returned[3]/returned[4]
+ returnedValue = returned[2] * Math.sin(returnedFraction)
+ error = Math.abs(originalValue - returnedValue)
+ if error > 1e-14
+ console.log "fail testApproxAll with 4 digits: " + "1 * sin( " + i + "/" + j + " ) . obtained: " + returned + " error: " + error
+
+ value = 0
+ if approxAll(value)[0] != "0" then console.log "fail testApproxAll: 0"
+
+ value = 0.0
+ if approxAll(value)[0] != "0" then console.log "fail testApproxAll: 0.0"
+
+ value = 0.00
+ if approxAll(value)[0] != "0" then console.log "fail testApproxAll: 0.00"
+
+ value = 0.000
+ if approxAll(value)[0] != "0" then console.log "fail testApproxAll: 0.000"
+
+ value = 0.0000
+ if approxAll(value)[0] != "0" then console.log "fail testApproxAll: 0.0000"
+
+ value = 1
+ if approxAll(value)[0] != "1" then console.log "fail testApproxAll: 1"
+
+ value = 1.0
+ if approxAll(value)[0] != "1" then console.log "fail testApproxAll: 1.0"
+
+ value = 1.00
+ if approxAll(value)[0] != "1" then console.log "fail testApproxAll: 1.00"
+
+ value = 1.000
+ if approxAll(value)[0] != "1" then console.log "fail testApproxAll: 1.000"
+
+ value = 1.0000
+ if approxAll(value)[0] != "1" then console.log "fail testApproxAll: 1.0000"
+
+ value = 1.00000
+ if approxAll(value)[0] != "1" then console.log "fail testApproxAll: 1.00000"
+
+ value = Math.sqrt(2)
+ if approxAll(value)[0] != "1 * sqrt( 2 ) / 1" then console.log "fail testApproxAll: Math.sqrt(2)"
+
+ value = 1.41
+ if approxAll(value)[0] != "1 * sqrt( 2 ) / 1" then console.log "fail testApproxAll: 1.41"
+
+ # if we narrow down to a particular family then we can get
+ # an OK guess even with few digits, expecially for really "famous" numbers
+
+ value = 1.4
+ if approxRadicals(value)[0] != "1 * sqrt( 2 ) / 1" then console.log "fail approxRadicals: 1.4"
+
+ value = 0.6
+ if approxLogs(value)[0] != "1 * log( 2 ) / 1" then console.log "fail approxLogs: 0.6"
+
+ value = 0.69
+ if approxLogs(value)[0] != "1 * log( 2 ) / 1" then console.log "fail approxLogs: 0.69"
+
+ value = 0.7
+ if approxLogs(value)[0] != "1 * log( 2 ) / 1" then console.log "fail approxLogs: 0.7"
+
+ value = 1.09
+ if approxLogs(value)[0] != "1 * log( 3 ) / 1" then console.log "fail approxLogs: 1.09"
+
+ value = 1.09
+ if approxAll(value)[0] != "1 * log( 3 ) / 1" then console.log "fail approxAll: 1.09"
+
+ value = 1.098
+ if approxAll(value)[0] != "1 * log( 3 ) / 1" then console.log "fail approxAll: 1.098"
+
+ value = 1.1
+ if approxAll(value)[0] != "1 * log( 3 ) / 1" then console.log "fail approxAll: 1.1"
+
+ value = 1.11
+ if approxAll(value)[0] != "1 * log( 3 ) / 1" then console.log "fail approxAll: 1.11"
+
+ value = Math.sqrt(3)
+ if approxAll(value)[0] != "1 * sqrt( 3 ) / 1" then console.log "fail testApproxAll: Math.sqrt(3)"
+
+ value = 1.0000
+ if approxAll(value)[0] != "1" then console.log "fail testApproxAll: 1.0000"
+
+
+ value = 3.141592
+ if approxAll(value)[0] != "1 * (pi ^ 1 ) / 1 )" then console.log "fail testApproxAll: 3.141592"
+
+ value = 31.41592
+ if approxAll(value)[0] != "10 * (pi ^ 1 ) / 1 )" then console.log "fail testApproxAll: 31.41592"
+
+ value = 314.1592
+ if approxAll(value)[0] != "100 * (pi ^ 1 ) / 1 )" then console.log "fail testApproxAll: 314.1592"
+
+ value = 31415926.53589793
+ if approxAll(value)[0] != "10000000 * (pi ^ 1 ) / 1 )" then console.log "fail testApproxAll: 31415926.53589793"
+
+ value = Math.sqrt(2)
+ if approxTrigonometric(value)[0] != "2 * sin( 1/4 * pi )" then console.log "fail approxTrigonometric: Math.sqrt(2)"
+
+ value = Math.sqrt(3)
+ if approxTrigonometric(value)[0] != "2 * sin( 1/3 * pi )" then console.log "fail approxTrigonometric: Math.sqrt(3)"
+
+ value = (Math.sqrt(6) - Math.sqrt(2))/4
+ if approxAll(value)[0] != "1 * sin( 1/12 * pi )" then console.log "fail testApproxAll: (Math.sqrt(6) - Math.sqrt(2))/4"
+
+ value = Math.sqrt(2 - Math.sqrt(2))/2
+ if approxAll(value)[0] != "1 * sin( 1/8 * pi )" then console.log "fail testApproxAll: Math.sqrt(2 - Math.sqrt(2))/2"
+
+ value = (Math.sqrt(6) + Math.sqrt(2))/4
+ if approxAll(value)[0] != "1 * sin( 5/12 * pi )" then console.log "fail testApproxAll: (Math.sqrt(6) + Math.sqrt(2))/4"
+
+ value = Math.sqrt(2 + Math.sqrt(3))/2
+ if approxAll(value)[0] != "1 * sin( 5/12 * pi )" then console.log "fail testApproxAll: Math.sqrt(2 + Math.sqrt(3))/2"
+
+ value = (Math.sqrt(5) - 1)/4
+ if approxAll(value)[0] != "1 * sin( 1/10 * pi )" then console.log "fail testApproxAll: (Math.sqrt(5) - 1)/4"
+
+ value = Math.sqrt(10 - 2*Math.sqrt(5))/4
+ if approxAll(value)[0] != "1 * sin( 1/5 * pi )" then console.log "fail testApproxAll: Math.sqrt(10 - 2*Math.sqrt(5))/4"
+
+ # this has a radical form but it's too long to write
+ value = Math.sin(Math.PI/7)
+ if approxAll(value)[0] != "1 * sin( 1/7 * pi )" then console.log "fail testApproxAll: Math.sin(Math.PI/7)"
+
+ # this has a radical form but it's too long to write
+ value = Math.sin(Math.PI/9)
+ if approxAll(value)[0] != "1 * sin( 1/9 * pi )" then console.log "fail testApproxAll: Math.sin(Math.PI/9)"
+
+ value = 1836.15267
+ if approxRationalsOfPowersOfPI(value)[0] != "6 * (pi ^ 5 ) / 1 )" then console.log "fail approxRationalsOfPowersOfPI: 1836.15267"
+
+
+ for i in [1..13]
+ for j in [1..13]
+ console.log "approxTrigonometric testing: " + "1 * sin( " + i + "/" + j + " * pi )"
+ fraction = i/j
+ value = Math.sin(Math.PI * fraction)
+ # we specifically search for sines of rational multiples of PI
+ # because too many of them would be picked up as simple
+ # rationals.
+ returned = approxTrigonometric(value)
+ returnedFraction = returned[3]/returned[4]
+ returnedValue = returned[2] * Math.sin(Math.PI * returnedFraction)
+ if Math.abs(value - returnedValue) > 1e-15
+ console.log "fail approxTrigonometric: " + "1 * sin( " + i + "/" + j + " * pi ) . obtained: " + returned
+
+ for i in [1..13]
+ for j in [1..13]
+
+ # with four digits, there are two collisions with the
+ # "simple fraction" argument hypotesis, which we prefer since
+ # it's a simpler expression, so let's skip those
+ # two tests
+ if i == 5 and j == 11 or
+ i == 6 and j == 11
+ continue
+
+ console.log "approxTrigonometric testing with 4 digits: " + "1 * sin( " + i + "/" + j + " * pi )"
+ fraction = i/j
+ originalValue = Math.sin(Math.PI * fraction)
+ value = originalValue.toFixed(4)
+ # we specifically search for sines of rational multiples of PI
+ # because too many of them would be picked up as simple
+ # rationals.
+ returned = approxTrigonometric(value)
+ returnedFraction = returned[3]/returned[4]
+ returnedValue = returned[2] * Math.sin(Math.PI * returnedFraction)
+ error = Math.abs(originalValue - returnedValue)
+ if error > 1e-14
+ console.log "fail approxTrigonometric with 4 digits: " + "1 * sin( " + i + "/" + j + " * pi ) . obtained: " + returned + " error: " + error
+
+ console.log "testApprox done"
+
+$.approxRadicals = approxRadicals
+$.approxRationalsOfLogs = approxRationalsOfLogs
+$.approxAll = approxAll
+$.testApprox = testApprox
diff --git a/node_modules/algebrite/sources/arccos.coffee b/node_modules/algebrite/sources/arccos.coffee
new file mode 100644
index 0000000..75c1f15
--- /dev/null
+++ b/node_modules/algebrite/sources/arccos.coffee
@@ -0,0 +1,152 @@
+### arccos =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the inverse cosine of x.
+
+###
+
+
+Eval_arccos = ->
+ push(cadr(p1))
+ Eval()
+ arccos()
+
+arccos = ->
+ n = 0
+ d = 0.0
+
+ save()
+
+ p1 = pop()
+
+ if (car(p1) == symbol(COS))
+ push(cadr(p1))
+ restore()
+ return
+
+ if (isdouble(p1))
+ errno = 0
+ d = Math.acos(p1.d)
+ if (errno)
+ stop("arccos function argument is not in the interval [-1,1]")
+ push_double(d)
+ restore()
+ return
+
+ # if p1 == 1/sqrt(2) then return 1/4*pi (45 degrees)
+ # second if catches the other way of saying it, sqrt(2)/2
+
+ if (isoneoversqrttwo(p1)) or
+ (car(p1) == symbol(MULTIPLY) && equalq(car(cdr(p1)), 1,2) and car(car(cdr(cdr(p1)))) == symbol(POWER) && equaln(car(cdr(car(cdr(cdr(p1))))),2) && equalq(car(cdr(cdr(car(cdr(cdr(p1)))))), 1, 2))
+ if evaluatingAsFloats
+ push_double(Math.PI / 4.0)
+ else
+ push_rational(1, 4)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ # if p1 == -1/sqrt(2) then return 3/4*pi (135 degrees)
+ # second if catches the other way of saying it, -sqrt(2)/2
+
+ if (isminusoneoversqrttwo(p1)) or
+ (car(p1) == symbol(MULTIPLY) && equalq(car(cdr(p1)), -1,2) and car(car(cdr(cdr(p1)))) == symbol(POWER) && equaln(car(cdr(car(cdr(cdr(p1))))),2) && equalq(car(cdr(cdr(car(cdr(cdr(p1)))))), 1, 2))
+ if evaluatingAsFloats
+ push_double(Math.PI * 3.0 / 4.0)
+ else
+ push_rational(3, 4)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ # if p1 == sqrt(3)/2 then return 1/6*pi (30 degrees)
+ if (issqrtthreeovertwo(p1))
+ if evaluatingAsFloats
+ push_double(Math.PI / 6.0)
+ else
+ push_rational(1, 6)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ # if p1 == -sqrt(3)/2 then return 5/6*pi (150 degrees)
+ if (isminussqrtthreeovertwo(p1))
+ if evaluatingAsFloats
+ push_double(5.0 * Math.PI / 6.0)
+ else
+ push_rational(5, 6)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ if (!isrational(p1))
+ push_symbol(ARCCOS)
+ push(p1)
+ list(2)
+ restore()
+ return
+
+ push(p1)
+ push_integer(2)
+ multiply()
+ n = pop_integer()
+
+ switch (n)
+
+ when -2
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+
+ when -1
+ if evaluatingAsFloats
+ push_double(Math.PI * 2.0 / 3.0)
+ else
+ push_rational(2, 3)
+ push_symbol(PI)
+ multiply()
+
+ when 0
+ if evaluatingAsFloats
+ push_double(Math.PI / 2.0)
+ else
+ push_rational(1, 2)
+ push_symbol(PI)
+ multiply()
+
+ when 1
+ if evaluatingAsFloats
+ push_double(Math.PI / 3.0)
+ else
+ push_rational(1, 3)
+ push_symbol(PI)
+ multiply()
+
+ when 2
+ if evaluatingAsFloats
+ push_double(0.0)
+ else
+ push(zero)
+
+ else
+ push_symbol(ARCCOS)
+ push(p1)
+ list(2)
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/arccosh.coffee b/node_modules/algebrite/sources/arccosh.coffee
new file mode 100644
index 0000000..ff52eb9
--- /dev/null
+++ b/node_modules/algebrite/sources/arccosh.coffee
@@ -0,0 +1,50 @@
+### arccosh =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the inverse hyperbolic cosine of x.
+
+###
+
+Eval_arccosh = ->
+ push(cadr(p1))
+ Eval()
+ arccosh()
+
+arccosh = ->
+ d = 0.0
+ save()
+ p1 = pop()
+ if (car(p1) == symbol(COSH))
+ push(cadr(p1))
+ restore()
+ return
+
+ if (isdouble(p1))
+ d = p1.d
+ if (d < 1.0)
+ stop("arccosh function argument is less than 1.0")
+ d = Math.log(d + Math.sqrt(d * d - 1.0))
+ push_double(d)
+ restore()
+ return
+
+ if (isplusone(p1))
+ push(zero)
+ restore()
+ return
+
+ push_symbol(ARCCOSH)
+ push(p1)
+ list(2)
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/arcsin.coffee b/node_modules/algebrite/sources/arcsin.coffee
new file mode 100644
index 0000000..c5a6061
--- /dev/null
+++ b/node_modules/algebrite/sources/arcsin.coffee
@@ -0,0 +1,151 @@
+### arcsin =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the inverse sine of x.
+
+###
+
+Eval_arcsin = ->
+ push(cadr(p1))
+ Eval()
+ arcsin()
+
+arcsin = ->
+ n = 0
+ d = 0
+
+ save()
+
+ p1 = pop()
+
+ if (car(p1) == symbol(SIN))
+ push(cadr(p1))
+ restore()
+ return
+
+ if (isdouble(p1))
+ errno = 0
+ d = Math.asin(p1.d)
+ if (errno)
+ stop("arcsin function argument is not in the interval [-1,1]")
+ push_double(d)
+ restore()
+ return
+
+ # if p1 == 1/sqrt(2) then return 1/4*pi (45 degrees)
+ # second if catches the other way of saying it, sqrt(2)/2
+
+ if (isoneoversqrttwo(p1)) or
+ (car(p1) == symbol(MULTIPLY) && equalq(car(cdr(p1)), 1,2) and car(car(cdr(cdr(p1)))) == symbol(POWER) && equaln(car(cdr(car(cdr(cdr(p1))))),2) && equalq(car(cdr(cdr(car(cdr(cdr(p1)))))), 1, 2))
+ push_rational(1, 4)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ # if p1 == -1/sqrt(2) then return -1/4*pi (-45 degrees)
+ # second if catches the other way of saying it, -sqrt(2)/2
+
+ if (isminusoneoversqrttwo(p1)) or
+ (car(p1) == symbol(MULTIPLY) && equalq(car(cdr(p1)), -1,2) and car(car(cdr(cdr(p1)))) == symbol(POWER) && equaln(car(cdr(car(cdr(cdr(p1))))),2) && equalq(car(cdr(cdr(car(cdr(cdr(p1)))))), 1, 2))
+ if evaluatingAsFloats
+ push_double(-Math.PI / 4.0)
+ else
+ push_rational(-1, 4)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ # if p1 == sqrt(3)/2 then return 1/3*pi (60 degrees)
+ if (issqrtthreeovertwo(p1))
+ if evaluatingAsFloats
+ push_double(Math.PI / 3.0)
+ else
+ push_rational(1, 3)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ # if p1 == -sqrt(3)/2 then return -1/3*pi (-60 degrees)
+ if (isminussqrtthreeovertwo(p1))
+ if evaluatingAsFloats
+ push_double(-Math.PI / 3.0)
+ else
+ push_rational(-1, 3)
+ push_symbol(PI)
+ multiply()
+ restore()
+ return
+
+ if (!isrational(p1))
+ push_symbol(ARCSIN)
+ push(p1)
+ list(2)
+ restore()
+ return
+
+ push(p1)
+ push_integer(2)
+ multiply()
+ n = pop_integer()
+
+ switch (n)
+
+ when -2
+ if evaluatingAsFloats
+ push_double(-Math.PI / 2.0)
+ else
+ push_rational(-1, 2)
+ push_symbol(PI)
+ multiply()
+
+ when -1
+ if evaluatingAsFloats
+ push_double(-Math.PI / 6.0)
+ else
+ push_rational(-1, 6)
+ push_symbol(PI)
+ multiply()
+
+ when 0
+ if evaluatingAsFloats
+ push_double(0.0)
+ else
+ push(zero)
+
+ when 1
+ if evaluatingAsFloats
+ push_double(Math.PI / 6.0)
+ else
+ push_rational(1, 6)
+ push_symbol(PI)
+ multiply()
+
+ when 2
+ if evaluatingAsFloats
+ push_double(Math.PI / 2.0)
+ else
+ push_rational(1, 2)
+ push_symbol(PI)
+ multiply()
+
+ else
+ push_symbol(ARCSIN)
+ push(p1)
+ list(2)
+
+ restore()
+
+
+
diff --git a/node_modules/algebrite/sources/arcsinh.coffee b/node_modules/algebrite/sources/arcsinh.coffee
new file mode 100644
index 0000000..c6b3cd5
--- /dev/null
+++ b/node_modules/algebrite/sources/arcsinh.coffee
@@ -0,0 +1,48 @@
+### arcsinh =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the inverse hyperbolic sine of x.
+
+###
+
+Eval_arcsinh = ->
+ push(cadr(p1))
+ Eval()
+ arcsinh()
+
+arcsinh = ->
+ d = 0.0
+ save()
+ p1 = pop()
+ if (car(p1) == symbol(SINH))
+ push(cadr(p1))
+ restore()
+ return
+
+ if (isdouble(p1))
+ d = p1.d
+ d = Math.log(d + Math.sqrt(d * d + 1.0))
+ push_double(d)
+ restore()
+ return
+
+ if (isZeroAtomOrTensor(p1))
+ push(zero)
+ restore()
+ return
+
+ push_symbol(ARCSINH)
+ push(p1)
+ list(2)
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/arctan.coffee b/node_modules/algebrite/sources/arctan.coffee
new file mode 100644
index 0000000..bab6756
--- /dev/null
+++ b/node_modules/algebrite/sources/arctan.coffee
@@ -0,0 +1,114 @@
+### arctan =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the inverse tangent of x.
+
+###
+
+Eval_arctan = ->
+ push(cadr(p1))
+ Eval()
+ arctan()
+
+arctan = ->
+ d = 0
+
+ save()
+
+ p1 = pop()
+
+ if (car(p1) == symbol(TAN))
+ push(cadr(p1))
+ restore()
+ return
+
+ if (isdouble(p1))
+ errno = 0
+ d = Math.atan(p1.d)
+ if (errno)
+ stop("arctan function error")
+ push_double(d)
+ restore()
+ return
+
+ if (isZeroAtomOrTensor(p1))
+ push(zero)
+ restore()
+ return
+
+ if (isnegative(p1))
+ push(p1)
+ negate()
+ arctan()
+ negate()
+ restore()
+ return
+
+ # arctan(sin(a) / cos(a)) ?
+
+ if (Find(p1, symbol(SIN)) && Find(p1, symbol(COS)))
+ push(p1)
+ numerator()
+ p2 = pop()
+ push(p1)
+ denominator()
+ p3 = pop()
+ if (car(p2) == symbol(SIN) && car(p3) == symbol(COS) && equal(cadr(p2), cadr(p3)))
+ push(cadr(p2))
+ restore()
+ return
+
+ # arctan(1/sqrt(3)) -> pi/6
+ # second if catches the other way of saying it, sqrt(3)/3
+
+ if (car(p1) == symbol(POWER) && equaln(cadr(p1), 3) && equalq(caddr(p1), -1, 2)) or
+ (car(p1) == symbol(MULTIPLY) && equalq(car(cdr(p1)), 1,3) and car(car(cdr(cdr(p1)))) == symbol(POWER) && equaln(car(cdr(car(cdr(cdr(p1))))),3) && equalq(car(cdr(cdr(car(cdr(cdr(p1)))))), 1, 2))
+ push_rational(1, 6)
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push(symbol(PI))
+ multiply()
+ restore()
+ return
+
+ # arctan(1) -> pi/4
+
+ if (equaln(p1, 1))
+ push_rational(1, 4)
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push(symbol(PI))
+ multiply()
+ restore()
+ return
+
+ # arctan(sqrt(3)) -> pi/3
+
+ if (car(p1) == symbol(POWER) && equaln(cadr(p1), 3) && equalq(caddr(p1), 1, 2))
+ push_rational(1, 3)
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push(symbol(PI))
+ multiply()
+ restore()
+ return
+
+ push_symbol(ARCTAN)
+ push(p1)
+ list(2)
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/arctanh.coffee b/node_modules/algebrite/sources/arctanh.coffee
new file mode 100644
index 0000000..d915931
--- /dev/null
+++ b/node_modules/algebrite/sources/arctanh.coffee
@@ -0,0 +1,51 @@
+### arctanh =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the inverse hyperbolic tangent of x.
+
+###
+
+Eval_arctanh = ->
+ push(cadr(p1))
+ Eval()
+ arctanh()
+
+arctanh = ->
+ d = 0.0
+ save()
+ p1 = pop()
+ if (car(p1) == symbol(TANH))
+ push(cadr(p1))
+ restore()
+ return
+
+ if (isdouble(p1))
+ d = p1.d
+ if (d < -1.0 || d > 1.0)
+ stop("arctanh function argument is not in the interval [-1,1]")
+ d = Math.log((1.0 + d) / (1.0 - d)) / 2.0
+ push_double(d)
+ restore()
+ return
+
+ if (isZeroAtomOrTensor(p1))
+ push(zero)
+ restore()
+ return
+
+ push_symbol(ARCTANH)
+ push(p1)
+ list(2)
+ restore()
+
+
+
diff --git a/node_modules/algebrite/sources/arg.coffee b/node_modules/algebrite/sources/arg.coffee
new file mode 100644
index 0000000..114b29f
--- /dev/null
+++ b/node_modules/algebrite/sources/arg.coffee
@@ -0,0 +1,192 @@
+### arg =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+z
+
+General description
+-------------------
+Returns the angle of complex z.
+
+###
+
+###
+ Argument (angle) of complex z
+
+ z arg(z)
+ - ------
+
+ a 0
+
+ -a -pi See note 3 below
+
+ (-1)^a a pi
+
+ exp(a + i b) b
+
+ a b arg(a) + arg(b)
+
+ a + i b arctan(b/a)
+
+Result by quadrant
+
+ z arg(z)
+ - ------
+
+ 1 + i 1/4 pi
+
+ 1 - i -1/4 pi
+
+ -1 + i 3/4 pi
+
+ -1 - i -3/4 pi
+
+Notes
+
+ 1. Handles mixed polar and rectangular forms, e.g. 1 + exp(i pi/3)
+
+ 2. Symbols in z are assumed to be positive and real.
+
+ 3. Negative direction adds -pi to angle.
+
+ Example: z = (-1)^(1/3), abs(z) = 1/3 pi, abs(-z) = -2/3 pi
+
+ 4. jean-francois.debroux reports that when z=(a+i*b)/(c+i*d) then
+
+ arg(numerator(z)) - arg(denominator(z))
+
+ must be used to get the correct answer. Now the operation is
+ automatic.
+###
+
+DEBUG_ARG = false
+
+Eval_arg = ->
+ push(cadr(p1))
+ Eval()
+ arg()
+
+arg = ->
+ save()
+ p1 = pop()
+ push(p1)
+ numerator()
+ yyarg()
+ push(p1)
+ denominator()
+ yyarg()
+ subtract()
+ restore()
+
+#define RE p2
+#define IM p3
+
+yyarg = ->
+ save()
+ p1 = pop()
+
+ # case of plain number
+ if (ispositivenumber(p1) or p1 == symbol(PI))
+ if isdouble(p1) or evaluatingAsFloats
+ push_double(0)
+ else
+ push_integer(0)
+ else if (isnegativenumber(p1))
+ if isdouble(p1) or evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push(symbol(PI))
+ negate()
+
+ # you'd think that something like
+ # arg(a) is always 0 when a is real but no,
+ # arg(a) is pi when a is negative so we have
+ # to leave unexpressed
+ else if (issymbol(p1))
+ push_symbol(ARG)
+ push(p1)
+ list(2)
+
+ else if (car(p1) == symbol(POWER) && equaln(cadr(p1), -1))
+ # -1 to a power
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push(symbol(PI))
+ push(caddr(p1))
+ multiply()
+ else if (car(p1) == symbol(POWER) && cadr(p1) == symbol(E))
+ # exponential
+ push(caddr(p1))
+ imag()
+ # arg(a^(1/2)) is always equal to 1/2 * arg(a)
+ # this can obviously be made more generic TODO
+ else if (car(p1) == symbol(POWER) && isoneovertwo(caddr(p1)))
+ if DEBUG_ARG then console.log "arg of a sqrt: " + p1
+ if DEBUG_ARG then debugger
+ push(cadr(p1))
+ arg()
+ if DEBUG_ARG then console.log " = 1/2 * " + stack[tos-1]
+ push(caddr(p1))
+ multiply()
+ else if (car(p1) == symbol(MULTIPLY))
+ # product of factors
+ push_integer(0)
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ arg()
+ add()
+ p1 = cdr(p1)
+ else if (car(p1) == symbol(ADD))
+ # sum of terms
+ push(p1)
+ rect()
+ p1 = pop()
+ push(p1)
+ real()
+ p2 = pop()
+ push(p1)
+ imag()
+ p3 = pop()
+ if (isZeroAtomOrTensor(p2))
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push(symbol(PI))
+ if (isnegative(p3))
+ negate()
+ else
+ push(p3)
+ push(p2)
+ divide()
+ arctan()
+ if (isnegative(p2))
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ if (isnegative(p3))
+ subtract(); # quadrant 1 -> 3
+ else
+ add(); # quadrant 4 -> 2
+ else
+
+ if (!isZeroAtomOrTensor(get_binding(symbol(ASSUME_REAL_VARIABLES))))
+ # if we assume all passed values are real
+ push_integer(0)
+ else
+ # if we don't assume all passed values are real, all
+ # we con do is to leave unexpressed
+ push_symbol(ARG)
+ push(p1)
+ list(2)
+
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/bake.coffee b/node_modules/algebrite/sources/bake.coffee
new file mode 100644
index 0000000..ce126e3
--- /dev/null
+++ b/node_modules/algebrite/sources/bake.coffee
@@ -0,0 +1,159 @@
+# pretty print
+
+
+
+bake = ->
+ h = 0
+ s = 0
+ t = 0
+ x = 0
+ y = 0
+ z = 0
+
+ expanding++
+
+ save()
+
+ p1 = pop()
+
+ s = ispolyexpandedform(p1, symbol(SYMBOL_S))
+ t = ispolyexpandedform(p1, symbol(SYMBOL_T))
+ x = ispolyexpandedform(p1, symbol(SYMBOL_X))
+ y = ispolyexpandedform(p1, symbol(SYMBOL_Y))
+ z = ispolyexpandedform(p1, symbol(SYMBOL_Z))
+
+ if (s == 1 && t == 0 && x == 0 && y == 0 && z == 0)
+ p2 = symbol(SYMBOL_S)
+ bake_poly()
+ else if (s == 0 && t == 1 && x == 0 && y == 0 && z == 0)
+ p2 = symbol(SYMBOL_T)
+ bake_poly()
+ else if (s == 0 && t == 0 && x == 1 && y == 0 && z == 0)
+ p2 = symbol(SYMBOL_X)
+ bake_poly()
+ else if (s == 0 && t == 0 && x == 0 && y == 1 && z == 0)
+ p2 = symbol(SYMBOL_Y)
+ bake_poly()
+ else if (s == 0 && t == 0 && x == 0 && y == 0 && z == 1)
+ p2 = symbol(SYMBOL_Z)
+ bake_poly()
+ # don't bake the contents of some constructs such as "for"
+ # because we don't want to evaluate the body of
+ # such constructs "statically", i.e. without fully running
+ # the loops.
+ else if (iscons(p1)) and car(p1) != symbol(FOR)
+ h = tos
+ push(car(p1))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ bake()
+ p1 = cdr(p1)
+ list(tos - h)
+ else
+ push(p1)
+
+ restore()
+
+ expanding--
+
+polyform = ->
+ h = 0
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if (ispolyexpandedform(p1, p2))
+ bake_poly()
+ else if (iscons(p1))
+ h = tos
+ push(car(p1))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ polyform()
+ p1 = cdr(p1)
+ list(tos - h)
+ else
+ push(p1)
+
+ restore()
+
+bake_poly = ->
+ h = 0
+ i = 0
+ k = 0
+ n = 0
+ #U **a
+ a = tos
+ k = coeff(p2, p1)
+ h = tos
+ for i in[(k - 1)..0] by -1
+ p1 = stack[a+i]
+ bake_poly_term(i)
+ n = tos - h
+ if (n > 1)
+ list(n)
+ push(symbol(ADD))
+ swap()
+ cons()
+ p1 = pop()
+ moveTos tos - k
+ push(p1)
+
+# p1 points to coefficient of p2 ^ k
+
+# k is an int
+bake_poly_term = (k) ->
+ h = 0
+ n = 0
+
+ if (isZeroAtomOrTensor(p1))
+ return
+
+ # constant term?
+
+ if (k == 0)
+ if (car(p1) == symbol(ADD))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ p1 = cdr(p1)
+ else
+ push(p1)
+ return
+
+ h = tos
+
+ # coefficient
+
+ if (car(p1) == symbol(MULTIPLY))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ p1 = cdr(p1)
+ else if (!equaln(p1, 1))
+ push(p1)
+
+ # x ^ k
+
+ if (k == 1)
+ push(p2)
+ else
+ push(symbol(POWER))
+ push(p2)
+ push_integer(k)
+ list(3)
+
+ n = tos - h
+
+ if (n > 1)
+ list(n)
+ push(symbol(MULTIPLY))
+ swap()
+ cons()
+
+
diff --git a/node_modules/algebrite/sources/besselj.coffee b/node_modules/algebrite/sources/besselj.coffee
new file mode 100644
index 0000000..9eda8bb
--- /dev/null
+++ b/node_modules/algebrite/sources/besselj.coffee
@@ -0,0 +1,193 @@
+### besselj =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x,n
+
+General description
+-------------------
+
+Returns a solution to the Bessel differential equation (Bessel function of first kind).
+
+Recurrence relation:
+
+ besselj(x,n) = (2/x) (n-1) besselj(x,n-1) - besselj(x,n-2)
+
+ besselj(x,1/2) = sqrt(2/pi/x) sin(x)
+
+ besselj(x,-1/2) = sqrt(2/pi/x) cos(x)
+
+For negative n, reorder the recurrence relation as:
+
+ besselj(x,n-2) = (2/x) (n-1) besselj(x,n-1) - besselj(x,n)
+
+Substitute n+2 for n to obtain
+
+ besselj(x,n) = (2/x) (n+1) besselj(x,n+1) - besselj(x,n+2)
+
+Examples:
+
+ besselj(x,3/2) = (1/x) besselj(x,1/2) - besselj(x,-1/2)
+
+ besselj(x,-3/2) = -(1/x) besselj(x,-1/2) - besselj(x,1/2)
+
+###
+
+
+
+Eval_besselj = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ besselj()
+
+besselj = ->
+ save()
+ yybesselj()
+ restore()
+
+#define X p1
+#define N p2
+#define SGN p3
+
+yybesselj = ->
+ d = 0.0
+ n = 0
+
+ p2 = pop()
+ p1 = pop()
+
+ push(p2)
+ n = pop_integer()
+
+ # numerical result
+
+ if (isdouble(p1) && !isNaN(n))
+ d = jn(n, p1.d)
+ push_double(d)
+ return
+
+ # bessej(0,0) = 1
+
+ if (isZeroAtomOrTensor(p1) && isZeroAtomOrTensor(p2))
+ push_integer(1)
+ return
+
+ # besselj(0,n) = 0
+
+ if (isZeroAtomOrTensor(p1) && !isNaN(n))
+ push_integer(0)
+ return
+
+ # half arguments
+
+ if (p2.k == NUM && MEQUAL(p2.q.b, 2))
+
+ # n = 1/2
+
+ if (MEQUAL(p2.q.a, 1))
+ if evaluatingAsFloats
+ push_double(2.0 / Math.PI)
+ else
+ push_integer(2)
+ push_symbol(PI)
+ divide()
+ push(p1)
+ divide()
+ push_rational(1, 2)
+ power()
+ push(p1)
+ sine()
+ multiply()
+ return
+
+ # n = -1/2
+
+ if (MEQUAL(p2.q.a, -1))
+ if evaluatingAsFloats
+ push_double(2.0 / Math.PI)
+ else
+ push_integer(2)
+ push_symbol(PI)
+ divide()
+ push(p1)
+ divide()
+ push_rational(1, 2)
+ power()
+ push(p1)
+ cosine()
+ multiply()
+ return
+
+ # besselj(x,n) = (2/x) (n-sgn(n)) besselj(x,n-sgn(n)) - besselj(x,n-2*sgn(n))
+
+ push_integer(MSIGN(p2.q.a))
+ p3 = pop()
+
+ push_integer(2)
+ push(p1)
+ divide()
+ push(p2)
+ push(p3)
+ subtract()
+ multiply()
+ push(p1)
+ push(p2)
+ push(p3)
+ subtract()
+ besselj()
+ multiply()
+ push(p1)
+ push(p2)
+ push_integer(2)
+ push(p3)
+ multiply()
+ subtract()
+ besselj()
+ subtract()
+
+ return
+
+ #if 0 # test cases needed
+ if (isnegativeterm(p1))
+ push(p1)
+ negate()
+ push(p2)
+ power()
+ push(p1)
+ push(p2)
+ negate()
+ power()
+ multiply()
+ push_symbol(BESSELJ)
+ push(p1)
+ negate()
+ push(p2)
+ list(3)
+ multiply()
+ return
+
+ if (isnegativeterm(p2))
+ push_integer(-1)
+ push(p2)
+ power()
+ push_symbol(BESSELJ)
+ push(p1)
+ push(p2)
+ negate()
+ list(3)
+ multiply()
+ return
+ #endif
+
+ push(symbol(BESSELJ))
+ push(p1)
+ push(p2)
+ list(3)
+
+
diff --git a/node_modules/algebrite/sources/bessely.coffee b/node_modules/algebrite/sources/bessely.coffee
new file mode 100644
index 0000000..61d4e9d
--- /dev/null
+++ b/node_modules/algebrite/sources/bessely.coffee
@@ -0,0 +1,66 @@
+### bessely =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x,n
+
+General description
+-------------------
+
+Bessel function of second kind.
+
+###
+
+
+Eval_bessely = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ bessely()
+
+bessely = ->
+ save()
+ yybessely()
+ restore()
+
+#define X p1
+#define N p2
+
+yybessely = ->
+ d = 0.0
+ n = 0
+
+ p2 = pop()
+ p1 = pop()
+
+ push(p2)
+ n = pop_integer()
+
+ if (isdouble(p1) && !isNaN(n))
+ d = yn(n, p1.d)
+ push_double(d)
+ return
+
+ if (isnegativeterm(p2))
+ push_integer(-1)
+ push(p2)
+ power()
+ push_symbol(BESSELY)
+ push(p1)
+ push(p2)
+ negate()
+ list(3)
+ multiply()
+ return
+
+ push_symbol(BESSELY)
+ push(p1)
+ push(p2)
+ list(3)
+ return
+
diff --git a/node_modules/algebrite/sources/bignum.coffee b/node_modules/algebrite/sources/bignum.coffee
new file mode 100644
index 0000000..89d2ada
--- /dev/null
+++ b/node_modules/algebrite/sources/bignum.coffee
@@ -0,0 +1,712 @@
+
+
+
+#double convert_rational_to_double(U *)
+#double convert_bignum_to_double(unsigned int *)
+#int ge(unsigned int *, unsigned int *, int)
+
+
+
+mint = (a) ->
+ return bigInt a
+
+isSmall = (a) ->
+ a.geq(Number.MIN_SAFE_INTEGER) && a.leq(Number.MAX_SAFE_INTEGER)
+
+# b is +1 or -1, a is a bigint
+setSignTo = (a,b) ->
+ if a.isPositive()
+ if b < 0
+ return a.multiply bigInt -1
+ else
+ # a is negative
+ if b > 0
+ return a.multiply bigInt -1
+ return a
+
+
+makeSignSameAs = (a,b) ->
+ if a.isPositive()
+ if b.isNegative()
+ return a.multiply bigInt -1
+ else
+ # a is negative
+ if b.isPositive()
+ return a.multiply bigInt -1
+ return a
+
+makePositive = (a) ->
+ if a.isNegative()
+ return a.multiply bigInt -1
+ return a
+
+# n is an int
+###
+mtotal = 0
+MP_MIN_SIZE = 2
+MP_MAX_FREE = 1000
+
+mnew = (n) ->
+ if (n < MP_MIN_SIZE)
+ n = MP_MIN_SIZE
+ if (n == MP_MIN_SIZE && mfreecount)
+ p = free_stack[--mfreecount]
+ else
+ p = [] #(unsigned int *) malloc((n + 3) * sizeof (int))
+ #if (p == 0)
+ # stop("malloc failure")
+ p[0] = n
+ mtotal += n
+ return p[3]
+###
+
+# p is the index of array of ints
+# !!! array wasn't passed here
+###
+free_stack = []
+
+mfree = (array, p) ->
+ p -= 3
+ mtotal -= array[p]
+ if (array[p] == MP_MIN_SIZE && mfreecount < MP_MAX_FREE)
+ free_stack[mfreecount++] = p
+ else
+ free(p)
+###
+
+# convert int to bignum
+
+# n is an int
+###
+mint = (n) ->
+ p = mnew(1)
+ if (n < 0)
+ # !!! this is FU
+ # MSIGN(p) = -1
+ fu = true
+ else
+ # !!! this is FU
+ #MSIGN(p) = 1
+ fu = true
+ # !!! this is FU
+ #MLENGTH(p) = 1
+ p[0] = Math.abs(n)
+ return p
+###
+
+# copy bignum
+
+# a is an array of ints
+###
+mcopy = (a) ->
+ #unsigned int *b
+
+ b = mnew(MLENGTH(a))
+
+ # !!! fu
+ #MSIGN(b) = MSIGN(a)
+ #MLENGTH(b) = MLENGTH(a)
+
+ for i in [0...MLENGTH(a)]
+ b[i] = a[i]
+
+ return b
+###
+
+
+###
+#
+# ge not invoked from anywhere - is you need ge
+# just use the bigNum's ge implementation
+# leaving it here just in case I decide to backport to C
+#
+# a >= b ?
+# and and b arrays of ints, len is an int
+ge = (a, b, len) ->
+ i = 0
+ for i in [0...len]
+ if (a[i] == b[i])
+ continue
+ else
+ break
+ if (a[i] >= b[i])
+ return 1
+ else
+ return 0
+###
+
+add_numbers = ->
+ a = 1.0
+ b = 1.0
+
+ #if DEBUG then console.log("add_numbers adding numbers: " + print_list(stack[tos - 1]) + " and " + print_list(stack[tos - 2]))
+
+ if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
+ qadd()
+ return
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if (isdouble(p1))
+ a = p1.d
+ else
+ a = convert_rational_to_double(p1)
+
+ if (isdouble(p2))
+ b = p2.d
+ else
+ b = convert_rational_to_double(p2)
+
+ theResult = a+b
+ push_double(theResult)
+
+ restore()
+
+subtract_numbers = ->
+ a = 0.0
+ b = 0.0
+
+ if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
+ qsub()
+ return
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if (isdouble(p1))
+ a = p1.d
+ else
+ a = convert_rational_to_double(p1)
+
+ if (isdouble(p2))
+ b = p2.d
+ else
+ b = convert_rational_to_double(p2)
+
+ push_double(a - b)
+
+ restore()
+
+multiply_numbers = ->
+ a = 0.0
+ b = 0.0
+
+ if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
+ qmul()
+ return
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if (isdouble(p1))
+ a = p1.d
+ else
+ a = convert_rational_to_double(p1)
+
+ if (isdouble(p2))
+ b = p2.d
+ else
+ b = convert_rational_to_double(p2)
+
+ push_double(a * b)
+
+ restore()
+
+divide_numbers = ->
+ a = 0.0
+ b = 0.0
+
+ if (isrational(stack[tos - 1]) && isrational(stack[tos - 2]))
+ qdiv()
+ return
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if (isZeroAtomOrTensor(p2))
+ stop("divide by zero")
+
+ if (isdouble(p1))
+ a = p1.d
+ else
+ a = convert_rational_to_double(p1)
+
+ if (isdouble(p2))
+ b = p2.d
+ else
+ b = convert_rational_to_double(p2)
+
+ push_double(a / b)
+
+ restore()
+
+invert_number = ->
+ #unsigned int *a, *b
+
+ save()
+
+ p1 = pop()
+
+ if (isZeroAtomOrTensor(p1))
+ stop("divide by zero")
+
+ if (isdouble(p1))
+ push_double(1 / p1.d)
+ restore()
+ return
+
+ a = bigInt(p1.q.a)
+ b = bigInt(p1.q.b)
+
+ b = makeSignSameAs(b,a)
+ a = setSignTo(a,1)
+
+ p1 = new U()
+ p1.k = NUM
+ p1.q.a = b
+ p1.q.b = a
+
+ push(p1)
+
+ restore()
+
+# a and b are Us
+compare_rationals = (a, b) ->
+ t = 0
+ #unsigned int *ab, *ba
+ ab = mmul(a.q.a, b.q.b)
+ ba = mmul(a.q.b, b.q.a)
+ t = mcmp(ab, ba)
+ return t
+
+# a and b are Us
+compare_numbers = (a,b) ->
+ x = 0.0
+ y = 0.0
+ if (isrational(a) && isrational(b))
+ return compare_rationals(a, b)
+ if (isdouble(a))
+ x = a.d
+ else
+ x = convert_rational_to_double(a)
+ if (isdouble(b))
+ y = b.d
+ else
+ y = convert_rational_to_double(b)
+ if (x < y)
+ return -1
+ if (x > y)
+ return 1
+ return 0
+
+negate_number = ->
+ save()
+ p1 = pop()
+ if (isZeroAtomOrTensor(p1))
+ push(p1)
+ restore()
+ return
+
+ switch (p1.k)
+ when NUM
+ p2 = new U()
+ p2.k = NUM
+ p2.q.a = bigInt(p1.q.a.multiply(bigInt.minusOne))
+ p2.q.b = bigInt(p1.q.b)
+ push(p2)
+ when DOUBLE
+ push_double(-p1.d)
+ else
+ stop("bug caught in mp_negate_number")
+ restore()
+
+bignum_truncate = ->
+ #unsigned int *a
+
+ save()
+
+ p1 = pop()
+
+ a = mdiv(p1.q.a, p1.q.b)
+
+ p1 = new U()
+
+ p1.k = NUM
+
+ p1.q.a = a
+ p1.q.b = bigInt(1)
+
+ push(p1)
+
+ restore()
+
+mp_numerator = ->
+ save()
+
+ p1 = pop()
+
+ if (p1.k != NUM)
+ push(one)
+ restore()
+ return
+
+ p2 = new U()
+
+ p2.k = NUM
+
+ p2.q.a = bigInt(p1.q.a)
+ p2.q.b = bigInt(1)
+
+ push(p2)
+
+ restore()
+
+mp_denominator = ->
+ save()
+
+ p1 = pop()
+
+ if (p1.k != NUM)
+ push(one)
+ restore()
+ return
+
+ p2 = new U()
+ p2.k = NUM
+ p2.q.a = bigInt(p1.q.b)
+ p2.q.b = bigInt(1)
+
+ push(p2)
+
+ restore()
+
+# expo is an integer
+bignum_power_number = (expo) ->
+ #unsigned int *a, *b, *t
+
+ save()
+
+ p1 = pop()
+
+ a = mpow(p1.q.a, Math.abs(expo))
+ b = mpow(p1.q.b, Math.abs(expo))
+
+ if (expo < 0)
+ # swap a and b
+ t = a
+ a = b
+ b = t
+
+ a = makeSignSameAs(a,b)
+ b = setSignTo(b,1)
+
+ p1 = new U()
+
+ p1.k = NUM
+
+ p1.q.a = a
+ p1.q.b = b
+
+ push(p1)
+
+ restore()
+
+# p an array of ints
+convert_bignum_to_double = (p) ->
+ return p.toJSNumber()
+
+# p is a U
+convert_rational_to_double = (p) ->
+ if !p.q?
+ debugger
+ quotientAndRemainder = p.q.a.divmod(p.q.b)
+ result = quotientAndRemainder.quotient + quotientAndRemainder.remainder / p.q.b.toJSNumber()
+
+ return result
+
+# n an integer
+new_integer = (n) ->
+ theNewInteger = new U()
+ theNewInteger.k = NUM
+ theNewInteger.q.a = bigInt(n)
+ theNewInteger.q.b = bigInt(1)
+ return theNewInteger
+
+# n an integer
+push_integer = (n) ->
+ if DEBUG then console.log "pushing integer " + n
+ push new_integer(n)
+
+# d a double
+push_double = (d) ->
+ save()
+ p1 = new U()
+ p1.k = DOUBLE
+ p1.d = d
+ push(p1)
+ restore()
+
+# a,b parts of a rational
+push_rational = (a,b) ->
+ ###
+ save()
+ p1 = new U()
+ p1.k = NUM
+ p1.q.a = bigInt(a)
+ p1.q.b = bigInt(b)
+ ## FIXME -- normalize ##
+ push(p1)
+ restore()
+ ###
+
+ p = new U()
+ p.k = NUM
+ p.q.a = bigInt(a)
+ p.q.b = bigInt(b)
+ push(p)
+
+pop_integer = ->
+ n = NaN
+
+ save()
+
+ p1 = pop()
+
+ switch (p1.k)
+
+ when NUM
+ if (isinteger(p1) && isSmall(p1.q.a))
+ n = p1.q.a.toJSNumber()
+
+ when DOUBLE
+ if DEBUG
+ console.log "popping integer but double is found"
+ if Math.floor(p1.d) == p1.d
+ if DEBUG
+ console.log "...altough it's an integer"
+ n = p1.d
+
+ restore()
+ return n
+
+# p is a U, flag is an int
+print_double = (p,flag) ->
+ accumulator = ""
+ buf = doubleToReasonableString(p.d)
+ if (flag == 1 && buf == '-')
+ accumulator += print_str(buf + 1)
+ else
+ accumulator += print_str(buf)
+ return accumulator
+
+# s is a string
+bignum_scan_integer = (s) ->
+ #unsigned int *a
+ #char sign
+
+ save()
+ scounter = 0
+
+ sign_ = s[scounter]
+
+ if (sign_ == '+' || sign_ == '-')
+ scounter++
+
+ # !!!! some mess in here, added an argument
+ a = bigInt(s.substring(scounter))
+
+ p1 = new U()
+
+ p1.k = NUM
+
+ p1.q.a = a
+ p1.q.b = bigInt(1)
+
+ push(p1)
+
+ if (sign_ == '-')
+ negate()
+
+ restore()
+
+# s a string
+bignum_scan_float = (s) ->
+ push_double(parseFloat(s))
+
+# gives the capability of printing the unsigned
+# value. This is handy because printing of the sign
+# might be taken care of "upstream"
+# e.g. when printing a base elevated to a negative exponent
+# prints the inverse of the base powered to the unsigned
+# exponent.
+# p is a U
+print_number = (p, signed) ->
+ accumulator = ""
+
+ denominatorString = ""
+ buf = ""
+ switch (p.k)
+ when NUM
+ aAsString = p.q.a.toString()
+ if !signed
+ if aAsString[0] == "-"
+ aAsString = aAsString.substring(1)
+
+ if (printMode == PRINTMODE_LATEX and isfraction(p))
+ aAsString = "\\frac{"+aAsString+"}{"
+
+ accumulator += aAsString
+
+ if (isfraction(p))
+ if printMode != PRINTMODE_LATEX
+ accumulator += ("/")
+ denominatorString = p.q.b.toString()
+ if printMode == PRINTMODE_LATEX then denominatorString += "}"
+
+ accumulator += denominatorString
+
+ when DOUBLE
+ aAsString = doubleToReasonableString(p.d)
+ if !signed
+ if aAsString[0] == "-"
+ aAsString = aAsString.substring(1)
+
+ accumulator += aAsString
+
+ return accumulator
+
+gcd_numbers = ->
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+# if (!isinteger(p1) || !isinteger(p2))
+# stop("integer args expected for gcd")
+
+ p3 = new U()
+
+ p3.k = NUM
+
+ p3.q.a = mgcd(p1.q.a, p2.q.a)
+ p3.q.b = mgcd(p1.q.b, p2.q.b)
+
+ p3.q.a = setSignTo(p3.q.a,1)
+
+ push(p3)
+
+ restore()
+
+pop_double = ->
+ d = 0.0
+ save()
+ p1 = pop()
+ switch (p1.k)
+ when NUM
+ d = convert_rational_to_double(p1)
+ when DOUBLE
+ d = p1.d
+ else
+ d = 0.0
+ restore()
+ return d
+
+bignum_float = ->
+ d = 0.0
+ d = convert_rational_to_double(pop())
+ push_double(d)
+
+#static unsigned int *__factorial(int)
+
+# n is an int
+bignum_factorial = (n) ->
+ save()
+ p1 = new U()
+ p1.k = NUM
+ p1.q.a = __factorial(n)
+ p1.q.b = bigInt(1)
+ push(p1)
+ restore()
+
+# n is an int
+__factorial = (n) ->
+ i = 0
+ #unsigned int *a, *b, *t
+
+ if (n == 0 || n == 1)
+ a = bigInt(1)
+ return a
+
+ a = bigInt(2)
+
+ b = bigInt(0)
+
+ if 3 <= n
+ for i in [3..n]
+ b = bigInt(i)
+ t = mmul(a, b)
+ a = t
+
+
+ return a
+
+mask = [
+ 0x00000001,
+ 0x00000002,
+ 0x00000004,
+ 0x00000008,
+ 0x00000010,
+ 0x00000020,
+ 0x00000040,
+ 0x00000080,
+ 0x00000100,
+ 0x00000200,
+ 0x00000400,
+ 0x00000800,
+ 0x00001000,
+ 0x00002000,
+ 0x00004000,
+ 0x00008000,
+ 0x00010000,
+ 0x00020000,
+ 0x00040000,
+ 0x00080000,
+ 0x00100000,
+ 0x00200000,
+ 0x00400000,
+ 0x00800000,
+ 0x01000000,
+ 0x02000000,
+ 0x04000000,
+ 0x08000000,
+ 0x10000000,
+ 0x20000000,
+ 0x40000000,
+ 0x80000000,
+]
+
+# unsigned int *x, unsigned int k
+mp_set_bit = (x, k) ->
+ console.log "not implemented yet"
+ debugger
+ x[k / 32] |= mask[k % 32]
+
+# unsigned int *x, unsigned int k
+mp_clr_bit = (x,k) ->
+ console.log "not implemented yet"
+ debugger
+ x[k / 32] &= ~mask[k % 32]
+
+# unsigned int *a
+mshiftright = (a) ->
+ a = a.shiftRight()
+
diff --git a/node_modules/algebrite/sources/binomial.coffee b/node_modules/algebrite/sources/binomial.coffee
new file mode 100644
index 0000000..d59dc77
--- /dev/null
+++ b/node_modules/algebrite/sources/binomial.coffee
@@ -0,0 +1,63 @@
+# Binomial coefficient
+#
+# Input: tos-2 n
+#
+# tos-1 k
+#
+# Output: Binomial coefficient on stack
+#
+# binomial(n, k) = n! / k! / (n - k)!
+#
+# The binomial coefficient vanishes for k < 0 or k > n. (A=B, p. 19)
+
+
+
+
+Eval_binomial = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ binomial()
+
+binomial = ->
+ save()
+ ybinomial()
+ restore()
+
+#define N p1
+#define K p2
+
+ybinomial = ->
+ p2 = pop()
+ p1 = pop()
+
+ if (BINOM_check_args() == 0)
+ push(zero)
+ return
+
+ push(p1)
+ factorial()
+
+ push(p2)
+ factorial()
+
+ divide()
+
+ push(p1)
+ push(p2)
+ subtract()
+ factorial()
+
+ divide()
+
+BINOM_check_args = ->
+ if (isNumericAtom(p1) && lessp(p1, zero))
+ return 0
+ else if (isNumericAtom(p2) && lessp(p2, zero))
+ return 0
+ else if (isNumericAtom(p1) && isNumericAtom(p2) && lessp(p1, p2))
+ return 0
+ else
+ return 1
+
diff --git a/node_modules/algebrite/sources/ceiling.coffee b/node_modules/algebrite/sources/ceiling.coffee
new file mode 100644
index 0000000..224b7c5
--- /dev/null
+++ b/node_modules/algebrite/sources/ceiling.coffee
@@ -0,0 +1,61 @@
+### ceiling =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+
+Returns the smallest integer not less than x.
+
+###
+
+
+Eval_ceiling = ->
+ push(cadr(p1))
+ Eval()
+ ceiling()
+
+ceiling = ->
+ save()
+ yyceiling()
+ restore()
+
+yyceiling = ->
+ d = 0.0
+
+ p1 = pop()
+
+ if (!isNumericAtom(p1))
+ push_symbol(CEILING)
+ push(p1)
+ list(2)
+ return
+
+ if (isdouble(p1))
+ d = Math.ceil(p1.d)
+ push_double(d)
+ return
+
+ if (isinteger(p1))
+ push(p1)
+ return
+
+ p3 = new U()
+ p3.k = NUM
+ p3.q.a = mdiv(p1.q.a, p1.q.b)
+ p3.q.b = mint(1)
+ push(p3)
+
+ if (isnegativenumber(p1))
+ doNothing = 1
+ else
+ push_integer(1)
+ add()
+
+
diff --git a/node_modules/algebrite/sources/choose.coffee b/node_modules/algebrite/sources/choose.coffee
new file mode 100644
index 0000000..1308010
--- /dev/null
+++ b/node_modules/algebrite/sources/choose.coffee
@@ -0,0 +1,76 @@
+### choose =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+n,k
+
+General description
+-------------------
+
+Returns the number of combinations of n items taken k at a time.
+
+For example, the number of five card hands is choose(52,5)
+
+```
+ n!
+ choose(n,k) = -------------
+ k! (n - k)!
+```
+###
+
+
+Eval_choose = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ choose()
+
+# Result vanishes for k < 0 or k > n. (A=B, p. 19)
+
+#define N p1
+#define K p2
+
+choose = ->
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if (choose_check_args() == 0)
+ push_integer(0)
+ restore()
+ return
+
+ push(p1)
+ factorial()
+
+ push(p2)
+ factorial()
+
+ divide()
+
+ push(p1)
+ push(p2)
+ subtract()
+ factorial()
+
+ divide()
+
+ restore()
+
+choose_check_args = ->
+ if (isNumericAtom(p1) && lessp(p1, zero))
+ return 0
+ else if (isNumericAtom(p2) && lessp(p2, zero))
+ return 0
+ else if (isNumericAtom(p1) && isNumericAtom(p2) && lessp(p1, p2))
+ return 0
+ else
+ return 1
+
+
diff --git a/node_modules/algebrite/sources/circexp.coffee b/node_modules/algebrite/sources/circexp.coffee
new file mode 100644
index 0000000..704dd91
--- /dev/null
+++ b/node_modules/algebrite/sources/circexp.coffee
@@ -0,0 +1,140 @@
+### circexp =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+
+Returns expression x with circular and hyperbolic functions converted to exponential forms. Sometimes this will simplify an expression.
+
+###
+
+
+Eval_circexp = ->
+ push(cadr(p1))
+ Eval()
+
+ circexp()
+
+ # normalize
+
+ Eval()
+
+circexp = ->
+ i = 0
+ h = 0
+ save()
+ p1 = pop()
+
+ if (car(p1) == symbol(COS))
+ push(cadr(p1))
+ expcos()
+ restore()
+ return
+
+ if (car(p1) == symbol(SIN))
+ push(cadr(p1))
+ expsin()
+ restore()
+ return
+
+ if (car(p1) == symbol(TAN))
+ p1 = cadr(p1)
+ push(imaginaryunit)
+ push(p1)
+ multiply()
+ exponential()
+ p2 = pop()
+ push(imaginaryunit)
+ push(p1)
+ multiply()
+ negate()
+ exponential()
+ p3 = pop()
+ push(p3)
+ push(p2)
+ subtract()
+ push(imaginaryunit)
+ multiply()
+ push(p2)
+ push(p3)
+ add()
+ divide()
+ restore()
+ return
+
+ if (car(p1) == symbol(COSH))
+ p1 = cadr(p1)
+ push(p1)
+ exponential()
+ push(p1)
+ negate()
+ exponential()
+ add()
+ push_rational(1, 2)
+ multiply()
+ restore()
+ return
+
+ if (car(p1) == symbol(SINH))
+ p1 = cadr(p1)
+ push(p1)
+ exponential()
+ push(p1)
+ negate()
+ exponential()
+ subtract()
+ push_rational(1, 2)
+ multiply()
+ restore()
+ return
+
+ if (car(p1) == symbol(TANH))
+ p1 = cadr(p1)
+ push(p1)
+ push_integer(2)
+ multiply()
+ exponential()
+ p1 = pop()
+ push(p1)
+ push_integer(1)
+ subtract()
+ push(p1)
+ push_integer(1)
+ add()
+ divide()
+ restore()
+ return
+
+ if (iscons(p1))
+ h = tos
+ while (iscons(p1))
+ push(car(p1))
+ circexp()
+ p1 = cdr(p1)
+ list(tos - h)
+ restore()
+ return
+
+ if (p1.k == TENSOR)
+ push(p1)
+ copy_tensor()
+ p1 = pop()
+ for i in [0...p1.tensor.nelem]
+ push(p1.tensor.elem[i])
+ circexp()
+ p1.tensor.elem[i] = pop()
+ push(p1)
+ restore()
+ return
+
+ push(p1)
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/clear.coffee b/node_modules/algebrite/sources/clear.coffee
new file mode 100644
index 0000000..5045029
--- /dev/null
+++ b/node_modules/algebrite/sources/clear.coffee
@@ -0,0 +1,87 @@
+### clearall =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+
+General description
+-------------------
+
+Completely wipes all variables from the environment.
+
+
+###
+
+
+Eval_clearall = ->
+ do_clearall()
+ push(symbol(NIL))
+
+do_clearall = ->
+ if (test_flag == 0)
+ clear_term()
+
+ do_clearPatterns()
+ clear_symbols()
+ defn()
+ codeGen = false
+
+# clearall from application GUI code
+clearall = ->
+ run("clearall")
+
+# this transformation is done in run.coffee, see there
+# for more info.
+clearRenamedVariablesToAvoidBindingToExternalScope = ->
+ for i in [0...symtab.length]
+ if symtab[i].printname.indexOf("AVOID_BINDING_TO_EXTERNAL_SCOPE_VALUE") != -1
+ # just clear it
+ symtab[i].k = SYM
+ symtab[i].printname = ""
+ binding[i] = symtab[i]
+ isSymbolReclaimable[i] = true
+
+### clear =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+
+Completely wipes a variable from the environment (while doing x = quote(x) just unassigns it).
+
+###
+
+
+Eval_clear = ->
+ p2 = cdr(p1)
+
+ while (iscons(p2))
+ variableToBeCleared = car(p2)
+ #console.log variableToBeCleared + ""
+
+
+ if (variableToBeCleared.k != SYM)
+ stop("symbol error")
+
+ #console.log "getting binding of " + p.toString()
+ #if p.toString() == "aaa"
+ # debugger
+
+ indexFound = symtab.indexOf(variableToBeCleared)
+ symtab[indexFound].k = SYM
+ symtab[indexFound].printname = ""
+ binding[indexFound] = symtab[indexFound]
+ isSymbolReclaimable[indexFound] = true
+
+
+ p2 = cdr(p2)
+
+ push(symbol(NIL))
diff --git a/node_modules/algebrite/sources/clock.coffee b/node_modules/algebrite/sources/clock.coffee
new file mode 100644
index 0000000..45cac5f
--- /dev/null
+++ b/node_modules/algebrite/sources/clock.coffee
@@ -0,0 +1,78 @@
+###
+ Convert complex z to clock form
+
+ Input: push z
+
+ Output: Result on stack
+
+ clock(z) = abs(z) * (-1) ^ (arg(z) / pi)
+
+ For example, clock(exp(i pi/3)) gives the result (-1)^(1/3)
+###
+
+# P.S. I couldn't find independent definition/aknowledgment
+# of the naming "clock form" anywhere on the web, seems like a
+# naming specific to eigenmath.
+# Clock form is another way to express a complex number, and
+# it has three advantages
+# 1) it's uniform with how for example
+# i is expressed i.e. (-1)^(1/2)
+# 2) it's very compact
+# 3) it's a straighforward notation for roots of 1 and -1
+
+
+DEBUG_CLOCKFORM = false
+
+Eval_clock = ->
+ push(cadr(p1))
+ Eval()
+ clockform()
+
+clockform = ->
+ save()
+ #if 1
+ p1 = pop()
+ push(p1)
+ abs()
+ if DEBUG_CLOCKFORM then console.log "clockform: abs of " + p1 + " : " + stack[tos-1]
+
+ # pushing the expression (-1)^... but note
+ # that we can't use "power", as "power" evaluates
+ # clock forms into rectangular form (see "-1 ^ rational"
+ # section in power)
+ push_symbol(POWER)
+
+ push_integer(-1)
+
+ push(p1)
+ arg()
+ if DEBUG_CLOCKFORM then console.log "clockform: arg of " + p1 + " : " + stack[tos-1]
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push(symbol(PI))
+ divide()
+ if DEBUG_CLOCKFORM then console.log "clockform: divide : " + stack[tos-1]
+ list(3)
+
+ if DEBUG_CLOCKFORM then console.log "clockform: power : " + stack[tos-1]
+ multiply()
+ if DEBUG_CLOCKFORM then console.log "clockform: multiply : " + stack[tos-1]
+ #else
+ ###
+ p1 = pop()
+ push(p1)
+ abs()
+ push(symbol(E))
+ push(p1)
+ arg()
+ push(imaginaryunit)
+ multiply()
+ power()
+ multiply()
+ ###
+ #endif
+ restore()
+
+
+
diff --git a/node_modules/algebrite/sources/coeff.coffee b/node_modules/algebrite/sources/coeff.coffee
new file mode 100644
index 0000000..2ffb59f
--- /dev/null
+++ b/node_modules/algebrite/sources/coeff.coffee
@@ -0,0 +1,111 @@
+### coeff =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+p,x,n
+
+General description
+-------------------
+Returns the coefficient of x^n in polynomial p. The x argument can be omitted for polynomials in x.
+
+###
+
+
+
+#define P p1
+#define X p2
+#define N p3
+
+Eval_coeff = ->
+ push(cadr(p1)); # 1st arg, p
+ Eval()
+
+ push(caddr(p1)); # 2nd arg, x
+ Eval()
+
+ push(cadddr(p1)); # 3rd arg, n
+ Eval()
+
+ p3 = pop(); # p3 is N
+ p2 = pop(); # p2 is X
+ p1 = pop(); # p1 is P
+
+ if (p3 == symbol(NIL)) # p3 is N # only 2 args?
+ p3 = p2; # p2 is X # p3 is N
+ p2 = symbol(SYMBOL_X); # p2 is X
+
+ push(p1); # p1 is P # divide p by x^n
+ push(p2); # p2 is X
+ push(p3); # p3 is N
+ power()
+ divide()
+
+ push(p2); # p2 is X # keep the constant part
+ filter()
+
+#-----------------------------------------------------------------------------
+#
+# Put polynomial coefficients on the stack
+#
+# Input: as per params
+#
+# Output: Returns number of coefficients on stack
+#
+# tos-n Coefficient of x^0
+#
+# tos-1 Coefficient of x^(n-1)
+#
+#-----------------------------------------------------------------------------
+
+coeff = (variable, polynomial)->
+
+ if DEBUG then console.log "coeff: " + variable + " " + polynomial
+
+ # works like this:
+ # 1) find the constant (by just evaluating the pol setting the variable to zero)
+ # 2) set aside the found constant: it's one of the coefficients to return
+ # 3) take the polynomial and remove the constant
+ # 4) divide that by variable, lowering the degree by one
+ # 5) go back to 1) until degree is zero
+
+ coeffsCount = 0
+
+ while true
+
+ push(polynomial)
+ push(variable)
+ push(zero)
+ subst()
+ Eval()
+
+ constant = pop()
+
+ # this will be a coefficient that will be returned
+ push(constant)
+ coeffsCount++
+
+ push(polynomial)
+ push(constant)
+ subtract()
+
+ polynomialWithoutConstant = pop()
+
+ if (equal(polynomialWithoutConstant, zero))
+ if DEBUG then console.log "coeff: result: " + coeffsCount
+ return coeffsCount
+
+ push(polynomialWithoutConstant)
+ push(variable)
+ prev_expanding = expanding
+ expanding = 1
+ divide()
+ expanding = prev_expanding
+ #console.log("just divided: " + stack[tos-1].toString())
+ # this is now the new polynomial with degree decreased by 1
+ polynomial = pop()
+
+
diff --git a/node_modules/algebrite/sources/cofactor.coffee b/node_modules/algebrite/sources/cofactor.coffee
new file mode 100644
index 0000000..78b0293
--- /dev/null
+++ b/node_modules/algebrite/sources/cofactor.coffee
@@ -0,0 +1,57 @@
+### cofactor =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+m,i,j
+
+General description
+-------------------
+Cofactor of a matrix component.
+Let c be the cofactor matrix of matrix m, i.e. tranpose(c) = adj(m).
+This function returns c[i,j].
+
+###
+
+
+Eval_cofactor = ->
+
+ i = 0
+ j = 0
+ n = 0
+ push(cadr(p1))
+ Eval()
+ p2 = pop()
+ if (istensor(p2) && p2.tensor.ndim == 2 && p2.tensor.dim[0] == p2.tensor.dim[1])
+ doNothing = 1
+ else
+ stop("cofactor: 1st arg: square matrix expected")
+ n = p2.tensor.dim[0]
+ push(caddr(p1))
+ Eval()
+ i = pop_integer()
+ if (i < 1 || i > n)
+ stop("cofactor: 2nd arg: row index expected")
+ push(cadddr(p1))
+ Eval()
+ j = pop_integer()
+ if (j < 1 || j > n)
+ stop("cofactor: 3rd arg: column index expected")
+ cofactor(p2, n, i - 1, j - 1)
+
+cofactor = (p, n, row, col) ->
+ i = 0
+ j = 0
+ for i in [0...n]
+ for j in [0...n]
+ if (i != row && j != col)
+ push(p.tensor.elem[n * i + j])
+ determinant(n - 1)
+ if ((row + col) % 2)
+ negate()
+
+
+
diff --git a/node_modules/algebrite/sources/condense.coffee b/node_modules/algebrite/sources/condense.coffee
new file mode 100644
index 0000000..9ff34bc
--- /dev/null
+++ b/node_modules/algebrite/sources/condense.coffee
@@ -0,0 +1,66 @@
+# Condense an expression by factoring common terms.
+
+
+Eval_condense = ->
+ push(cadr(p1))
+ Eval()
+ Condense()
+
+Condense = ->
+ prev_expanding = expanding
+ expanding = 0
+ save()
+ yycondense()
+ restore()
+ expanding = prev_expanding
+
+yycondense = ->
+ #expanding = 0
+
+ p1 = pop()
+
+ if (car(p1) != symbol(ADD))
+ push(p1)
+ return
+
+ # get gcd of all terms
+
+ p3 = cdr(p1)
+ push(car(p3))
+ p3 = cdr(p3)
+ while (iscons(p3))
+ push(car(p3))
+ if DEBUG then console.log "calculating gcd between: " + stack[tos - 1] + " and " + stack[tos - 2]
+ gcd()
+ if DEBUG then console.log "partial gcd: " + stack[tos - 1]
+ p3 = cdr(p3)
+
+ if DEBUG then console.log "condense: this is the gcd of all the terms: " + stack[tos - 1]
+
+ # divide each term by gcd
+
+ inverse()
+ p2 = pop()
+ push(zero)
+ p3 = cdr(p1)
+ while (iscons(p3))
+ push(p2)
+ push(car(p3))
+ #multiply()
+ multiply_noexpand()
+ add()
+ p3 = cdr(p3)
+
+ # We multiplied above w/o expanding so some factors cancelled.
+
+ # Now we expand which normalizes the result and, in some cases,
+ # simplifies it too (see test case H).
+
+ yyexpand()
+
+ # multiply result by gcd
+
+ push(p2)
+ divide()
+
+
diff --git a/node_modules/algebrite/sources/conj.coffee b/node_modules/algebrite/sources/conj.coffee
new file mode 100644
index 0000000..68fa700
--- /dev/null
+++ b/node_modules/algebrite/sources/conj.coffee
@@ -0,0 +1,38 @@
+### conj =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+z
+
+General description
+-------------------
+Returns the complex conjugate of z.
+
+###
+
+
+Eval_conj = ->
+ push(cadr(p1))
+ Eval()
+ p1 = pop()
+ push(p1)
+ if (!Find(p1, imaginaryunit)) # example: (-1)^(1/3)
+ polar()
+ conjugate()
+ clockform()
+ else
+ conjugate()
+
+
+# careful is you pass this one an expression with
+# i (instead of (-1)^(1/2)) then this doesn't work!
+conjugate = ->
+ push(imaginaryunit)
+ push(imaginaryunit)
+ negate()
+ subst()
+ Eval()
diff --git a/node_modules/algebrite/sources/cons.coffee b/node_modules/algebrite/sources/cons.coffee
new file mode 100644
index 0000000..62c2522
--- /dev/null
+++ b/node_modules/algebrite/sources/cons.coffee
@@ -0,0 +1,29 @@
+# Cons two things on the stack.
+
+
+
+consCount = 0
+cons = ->
+ consCount++
+ if DEBUG then console.log "cons tos: " + tos + " # " + consCount
+ #if consCount == 444
+ # debugger
+ # auto var ok, no opportunity for garbage collection after p = alloc()
+ p = new U()
+ p.k = CONS
+ p.cons.cdr = pop()
+ if p == p.cons.cdr
+ debugger
+ console.log "something wrong p == its cdr"
+
+ p.cons.car = pop()
+
+
+ ###
+ console.log "cons new cdr.k = " + p.cons.cdr.k + "\nor more in detail:"
+ console.log print_list p.cons.cdr
+ console.log "cons new car.k = " + p.cons.car.k + "\nor more in detail:"
+ console.log print_list p.cons.car
+ ###
+
+ push(p)
diff --git a/node_modules/algebrite/sources/contract.coffee b/node_modules/algebrite/sources/contract.coffee
new file mode 100644
index 0000000..b9d9f00
--- /dev/null
+++ b/node_modules/algebrite/sources/contract.coffee
@@ -0,0 +1,134 @@
+### contract =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+a,i,j
+
+General description
+-------------------
+Contract across tensor indices i.e. returns "a" summed over indices i and j.
+If i and j are omitted then 1 and 2 are used.
+contract(m) is equivalent to the trace of matrix m.
+
+###
+
+
+
+Eval_contract = ->
+ push(cadr(p1))
+ Eval()
+ if (cddr(p1) == symbol(NIL))
+ push_integer(1)
+ push_integer(2)
+ else
+ push(caddr(p1))
+ Eval()
+ push(cadddr(p1))
+ Eval()
+ contract()
+
+contract = ->
+ save()
+ yycontract()
+ restore()
+
+yycontract = ->
+ h = 0
+ i = 0
+ j = 0
+ k = 0
+ l = 0
+ m = 0
+ n = 0
+ ndim = 0
+ nelem = 0
+ ai = []
+ an = []
+
+ p3 = pop()
+ p2 = pop()
+ p1 = pop()
+
+ if (!istensor(p1))
+ if (!isZeroAtomOrTensor(p1))
+ stop("contract: tensor expected, 1st arg is not a tensor")
+ push(zero)
+ return
+
+ push(p2)
+ l = pop_integer()
+
+ push(p3)
+ m = pop_integer()
+
+ ndim = p1.tensor.ndim
+
+ if (l < 1 || l > ndim || m < 1 || m > ndim || l == m \
+ || p1.tensor.dim[l - 1] != p1.tensor.dim[m - 1])
+ stop("contract: index out of range")
+
+ l--
+ m--
+
+ n = p1.tensor.dim[l]
+
+ # nelem is the number of elements in "b"
+
+ nelem = 1
+ for i in [0...ndim]
+ if (i != l && i != m)
+ nelem *= p1.tensor.dim[i]
+
+ #console.log "nelem:" + nelem
+ p2 = alloc_tensor(nelem)
+ #console.log "p2:" + p2
+
+ p2.tensor.ndim = ndim - 2
+
+ j = 0
+ for i in [0...ndim]
+ if (i != l && i != m)
+ p2.tensor.dim[j++] = p1.tensor.dim[i]
+
+
+ a = p1.tensor.elem
+ b = p2.tensor.elem
+
+ #console.log "a: " + a
+ #console.log "b: " + b
+
+ for i in [0...ndim]
+ ai[i] = 0
+ an[i] = p1.tensor.dim[i]
+
+ for i in [0...nelem]
+ push(zero)
+ for j in [0...n]
+ ai[l] = j
+ ai[m] = j
+ h = 0
+ for k in [0...ndim]
+ h = (h * an[k]) + ai[k]
+ push(a[h])
+ #console.log "a[h]: " + a[h]
+ add()
+ #console.log "tos: " + stack[tos-1]
+ b[i] = pop()
+ #console.log "b[i]: " + b[i]
+ for j in [(ndim - 1)..0]
+ if (j == l || j == m)
+ continue
+ if (++ai[j] < an[j])
+ break
+ ai[j] = 0
+
+ if (nelem == 1)
+ push(b[0])
+ else
+ push(p2)
+
+ #console.log "returning: " + stack[tos-1]
diff --git a/node_modules/algebrite/sources/cos.coffee b/node_modules/algebrite/sources/cos.coffee
new file mode 100644
index 0000000..2cf553c
--- /dev/null
+++ b/node_modules/algebrite/sources/cos.coffee
@@ -0,0 +1,166 @@
+### cos =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the cosine of x.
+
+###
+
+
+Eval_cos = ->
+ push(cadr(p1))
+ Eval()
+ cosine()
+
+cosine = ->
+ save()
+ p1 = pop()
+ if (car(p1) == symbol(ADD))
+ cosine_of_angle_sum()
+ else
+ cosine_of_angle()
+ restore()
+
+# Use angle sum formula for special angles.
+
+#define A p3
+#define B p4
+
+cosine_of_angle_sum = ->
+ p2 = cdr(p1)
+ while (iscons(p2))
+ p4 = car(p2); # p4 is B
+ if (isnpi(p4)) # p4 is B
+ push(p1)
+ push(p4); # p4 is B
+ subtract()
+ p3 = pop(); # p3 is A
+ push(p3); # p3 is A
+ cosine()
+ push(p4); # p4 is B
+ cosine()
+ multiply()
+ push(p3); # p3 is A
+ sine()
+ push(p4); # p4 is B
+ sine()
+ multiply()
+ subtract()
+ return
+ p2 = cdr(p2)
+ cosine_of_angle()
+
+cosine_of_angle = ->
+
+ if (car(p1) == symbol(ARCCOS))
+ push(cadr(p1))
+ return
+
+ if (isdouble(p1))
+ d = Math.cos(p1.d)
+ if (Math.abs(d) < 1e-10)
+ d = 0.0
+ push_double(d)
+ return
+
+ # cosine function is symmetric, cos(-x) = cos(x)
+
+ if (isnegative(p1))
+ push(p1)
+ negate()
+ p1 = pop()
+
+ # cos(arctan(x)) = 1 / sqrt(1 + x^2)
+
+ # see p. 173 of the CRC Handbook of Mathematical Sciences
+
+ if (car(p1) == symbol(ARCTAN))
+ push_integer(1)
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ add()
+ push_rational(-1, 2)
+ power()
+ return
+
+ # multiply by 180/pi to go from radians to degrees.
+ # we go from radians to degrees because it's much
+ # easier to calculate symbolic results of most (not all) "classic"
+ # angles (e.g. 30,45,60...) if we calculate the degrees
+ # and the we do a switch on that.
+ # Alternatively, we could look at the fraction of pi
+ # (e.g. 60 degrees is 1/3 pi) but that's more
+ # convoluted as we'd need to look at both numerator and
+ # denominator.
+
+ push(p1)
+ push_integer(180)
+ multiply()
+
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+
+ divide()
+
+ n = pop_integer()
+
+ # most "good" (i.e. compact) trigonometric results
+ # happen for a round number of degrees. There are some exceptions
+ # though, e.g. 22.5 degrees, which we don't capture here.
+ if (n < 0 || isNaN(n))
+ push(symbol(COS))
+ push(p1)
+ list(2)
+ return
+
+ switch (n % 360)
+ when 90, 270
+ push_integer(0)
+ when 60, 300
+ push_rational(1, 2)
+ when 120, 240
+ push_rational(-1, 2)
+ when 45, 315
+ push_rational(1, 2)
+ push_integer(2)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 135, 225
+ push_rational(-1, 2)
+ push_integer(2)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 30, 330
+ push_rational(1, 2)
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 150, 210
+ push_rational(-1, 2)
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 0
+ push_integer(1)
+ when 180
+ push_integer(-1)
+ else
+ push(symbol(COS))
+ push(p1)
+ list(2)
+
diff --git a/node_modules/algebrite/sources/cosh.coffee b/node_modules/algebrite/sources/cosh.coffee
new file mode 100644
index 0000000..2d9d35c
--- /dev/null
+++ b/node_modules/algebrite/sources/cosh.coffee
@@ -0,0 +1,51 @@
+### cosh =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the hyperbolic cosine of x
+
+```
+ exp(x) + exp(-x)
+ cosh(x) = ----------------
+ 2
+```
+
+###
+
+Eval_cosh = ->
+ push(cadr(p1))
+ Eval()
+ ycosh()
+
+ycosh = ->
+ save()
+ yycosh()
+ restore()
+
+yycosh = ->
+ d = 0.0
+ p1 = pop()
+ if (car(p1) == symbol(ARCCOSH))
+ push(cadr(p1))
+ return
+ if (isdouble(p1))
+ d = Math.cosh(p1.d)
+ if (Math.abs(d) < 1e-10)
+ d = 0.0
+ push_double(d)
+ return
+ if (isZeroAtomOrTensor(p1))
+ push(one)
+ return
+ push_symbol(COSH)
+ push(p1)
+ list(2)
+
diff --git a/node_modules/algebrite/sources/decomp.coffee b/node_modules/algebrite/sources/decomp.coffee
new file mode 100644
index 0000000..bb22efd
--- /dev/null
+++ b/node_modules/algebrite/sources/decomp.coffee
@@ -0,0 +1,176 @@
+# this function extract parts subtrees from a tree.
+# It is used in two
+# places that have to do with pattern matching.
+# One is for integrals, where an expression or its
+# subparts are matched against cases in an
+# integrals table.
+# Another one is for applyging tranformation patterns
+# defined via PATTERN, again patterns are applied to
+# either the whole expression or any of its parts.
+
+
+
+# unclear to me at the moment
+# why this is exposed as something that can
+# be evalled. Never called.
+
+Eval_decomp = ->
+ save()
+ console.log "Eval_decomp is being called!!!!!!!!!!!!!!!!!!!!"
+ h = tos
+ push(symbol(NIL))
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ p1 = pop()
+ if (p1 == symbol(NIL))
+ guess()
+ else
+ push(p1)
+ decomp(false)
+ list(tos - h)
+ restore()
+
+
+pushTryNotToDuplicate = (toBePushed) ->
+ if tos > 0
+ if DEBUG then console.log "comparing " + toBePushed + " to: " + stack[tos-1]
+ if equal(toBePushed, stack[tos-1])
+ if DEBUG then console.log "skipping " + toBePushed + " because it's already on stack "
+ return
+ push(toBePushed)
+
+
+# returns constant expressions on the stack
+
+decomp = (generalTransform) ->
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if DEBUG then console.log "DECOMPOSING " + p1
+
+ # is the entire expression constant?
+
+ if generalTransform
+ if !iscons(p1)
+ if DEBUG then console.log " ground thing: " + p1
+ pushTryNotToDuplicate p1
+ restore()
+ return
+ else
+ if (Find(p1, p2) == 0)
+ if DEBUG then console.log " entire expression is constant"
+ pushTryNotToDuplicate(p1)
+ #push(p1); # may need later for pushing both +a, -a
+ #negate()
+ restore()
+ return
+
+ # sum?
+
+ if (isadd(p1))
+ decomp_sum(generalTransform)
+ restore()
+ return
+
+ # product?
+
+ if (ismultiply(p1))
+ decomp_product(generalTransform)
+ restore()
+ return
+
+ # naive decomp if not sum or product
+
+ if DEBUG then console.log " naive decomp"
+ p3 = cdr(p1)
+ if DEBUG then console.log "startig p3: " + p3
+ while (iscons(p3))
+
+ # for a general transformations,
+ # we want to match any part of the tree so
+ # we need to push the subtree as well
+ # as recurse to its parts
+ if generalTransform
+ push(car(p3))
+
+ if DEBUG then console.log "recursive decomposition"
+ push(car(p3))
+
+ if DEBUG then console.log "car(p3): " + car(p3)
+ push(p2)
+ if DEBUG then console.log "p2: " + p2
+ decomp(generalTransform)
+ p3 = cdr(p3)
+
+ restore()
+
+decomp_sum = (generalTransform) ->
+ if DEBUG then console.log " decomposing the sum "
+ h = 0
+
+
+ # decomp terms involving x
+
+ p3 = cdr(p1)
+
+ while (iscons(p3))
+ if (Find(car(p3), p2) or generalTransform)
+ push(car(p3))
+ push(p2)
+ decomp(generalTransform)
+ p3 = cdr(p3)
+
+ # add together all constant terms
+
+ h = tos
+
+ p3 = cdr(p1)
+
+ while (iscons(p3))
+ if (Find(car(p3), p2) == 0)
+ pushTryNotToDuplicate(car(p3))
+ p3 = cdr(p3)
+
+ if (tos - h)
+ add_all(tos - h)
+ p3 = pop()
+ pushTryNotToDuplicate(p3)
+ push(p3)
+ negate(); # need both +a, -a for some integrals
+
+decomp_product = (generalTransform) ->
+ if DEBUG then console.log " decomposing the product "
+ h = 0
+
+ # decomp factors involving x
+
+ p3 = cdr(p1)
+
+ while (iscons(p3))
+ if (Find(car(p3), p2) or generalTransform)
+ push(car(p3))
+ push(p2)
+ decomp(generalTransform)
+ p3 = cdr(p3)
+
+ # multiply together all constant factors
+
+ h = tos
+
+ p3 = cdr(p1)
+
+ while (iscons(p3))
+ if (Find(car(p3), p2) == 0)
+ pushTryNotToDuplicate(car(p3))
+ p3 = cdr(p3)
+
+ if (tos - h)
+ multiply_all(tos - h)
+ #p3 = pop(); # may need later for pushing both +a, -a
+ #push(p3)
+ #push(p3)
+ #negate()
diff --git a/node_modules/algebrite/sources/define.coffee b/node_modules/algebrite/sources/define.coffee
new file mode 100644
index 0000000..d969bbe
--- /dev/null
+++ b/node_modules/algebrite/sources/define.coffee
@@ -0,0 +1,80 @@
+# Store a function definition
+#
+# Example:
+#
+# f(x,y)=x^y
+#
+# For this definition, p1 points to the following structure.
+#
+# p1
+# |
+# ___v__ ______ ______
+# |CONS |->|CONS |--------------------->|CONS |
+# |______| |______| |______|
+# | | |
+# ___v__ ___v__ ______ ______ ___v__ ______ ______
+# |SETQ | |CONS |->|CONS |->|CONS | |CONS |->|CONS |->|CONS |
+# |______| |______| |______| |______| |______| |______| |______|
+# | | | | | |
+# ___v__ ___v__ ___v__ ___v__ ___v__ ___v__
+# |SYM f | |SYM x | |SYM y | |POWER | |SYM x | |SYM y |
+# |______| |______| |______| |______| |______| |______|
+#
+# the result (in f) is a FUNCTION node
+# that contains both the body and the argument list.
+#
+# We have
+#
+# caadr(p1) points to the function name i.e. f
+# cdadr(p1) points to the arguments i.e. the list (x y)
+# caddr(p1) points to the function body i.e. (power x y)
+
+
+
+#define F p3 # F points to the function name
+#define A p4 # A points to the argument list
+#define B p5 # B points to the function body
+
+define_user_function = ->
+ p3 = caadr(p1); # p3 is F
+ p4 = cdadr(p1); # p4 is A
+ p5 = caddr(p1); # p5 is B
+
+ if (!issymbol(p3)) # p3 is F
+ stop("function name?")
+
+ # evaluate function body (maybe)
+
+ if (car(p5) == symbol(EVAL)) # p5 is B
+ push(cadr(p5)); # p5 is B
+ Eval()
+ p5 = pop(); # p5 is B
+
+ # note how, unless explicitly forced by an eval,
+ # (handled by the if just above)
+ # we don't eval/simplify
+ # the body.
+ # Why? because it's the easiest way
+ # to solve scope problems i.e.
+ # x = 0
+ # f(x) = x + 1
+ # f(4) # would reply 1
+ # which would need to otherwise
+ # be solved by some scope device
+ # somehow
+ push_symbol(FUNCTION)
+ push p5
+ push p4
+ list(3)
+ p5 = pop()
+
+
+ set_binding(p3, p5); # p3 is F (function name) # p4 is A # p5 is B
+
+ # return value is nil
+
+ push_symbol(NIL)
+
+Eval_function_reference = ->
+ push p1
+
diff --git a/node_modules/algebrite/sources/defint.coffee b/node_modules/algebrite/sources/defint.coffee
new file mode 100644
index 0000000..21d8679
--- /dev/null
+++ b/node_modules/algebrite/sources/defint.coffee
@@ -0,0 +1,91 @@
+### defint =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+f,x,a,b[,y,c,d...]
+
+General description
+-------------------
+Returns the definite integral of f with respect to x evaluated from "a" to b.
+The argument list can be extended for multiple integrals (or "iterated
+integrals"), for example a double integral (which can represent for
+example a volume under a surface), or a triple integral, etc. For
+example, defint(f,x,a,b,y,c,d).
+
+###
+
+
+
+#define F p2
+#define X p3
+#define A p4
+#define B p5
+
+Eval_defint = ->
+ push(cadr(p1))
+ Eval()
+ p2 = pop() # p2 is F
+
+ p1 = cddr(p1)
+
+ # defint can handle multiple
+ # integrals, so we loop over the
+ # multiple integrals here
+ while (iscons(p1))
+
+ push(car(p1))
+ p1 = cdr(p1)
+ Eval()
+ p3 = pop() # p3 is X
+
+ push(car(p1))
+ p1 = cdr(p1)
+ Eval()
+ p4 = pop() # p4 is A
+
+ push(car(p1))
+ p1 = cdr(p1)
+ Eval()
+ p5 = pop() # p5 is B
+
+ # obtain the primitive of F against the
+ # specified variable X
+ # note that the primitive changes over
+ # the calculation of the multiple
+ # integrals.
+ push(p2)
+ push(p3)
+ integral()
+ p2 = pop() # contains the antiderivative of F
+
+ # evaluate the integral in A
+ push(p2)
+ push(p3)
+ push(p5)
+ subst()
+ Eval()
+
+ # evaluate the integral in B
+ push(p2)
+ push(p3)
+ push(p4)
+ subst()
+ Eval()
+
+ # integral between B and A is the
+ # subtraction. Note that this could
+ # be a number but also a function.
+ # and we might have to integrate this
+ # number/function again doing the while
+ # loop again if this is a multiple
+ # integral.
+ subtract()
+ p2 = pop()
+
+ push(p2)
+
+
diff --git a/node_modules/algebrite/sources/degree.coffee b/node_modules/algebrite/sources/degree.coffee
new file mode 100644
index 0000000..69c9b5b
--- /dev/null
+++ b/node_modules/algebrite/sources/degree.coffee
@@ -0,0 +1,69 @@
+### deg =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+p,x
+
+General description
+-------------------
+Returns the degree of polynomial p(x).
+
+###
+
+
+Eval_degree = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ p1 = pop()
+ if (p1 == symbol(NIL))
+ guess()
+ else
+ push(p1)
+ degree()
+
+#-----------------------------------------------------------------------------
+#
+# Find the degree of a polynomial
+#
+# Input: tos-2 p(x)
+#
+# tos-1 x
+#
+# Output: Result on stack
+#
+# Note: Finds the largest numerical power of x. Does not check for
+# weirdness in p(x).
+#
+#-----------------------------------------------------------------------------
+
+#define POLY p1
+#define X p2
+#define DEGREE p3
+
+degree = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ p3 = zero
+ yydegree(p1)
+ push(p3)
+ restore()
+
+yydegree = (p) ->
+ if (equal(p, p2))
+ if (isZeroAtomOrTensor(p3))
+ p3 = one
+ else if (car(p) == symbol(POWER))
+ if (equal(cadr(p), p2) && isNumericAtom(caddr(p)) && lessp(p3, caddr(p)))
+ p3 = caddr(p)
+ else if (iscons(p))
+ p = cdr(p)
+ while (iscons(p))
+ yydegree(car(p))
+ p = cdr(p)
diff --git a/node_modules/algebrite/sources/denominator.coffee b/node_modules/algebrite/sources/denominator.coffee
new file mode 100644
index 0000000..cd87a6e
--- /dev/null
+++ b/node_modules/algebrite/sources/denominator.coffee
@@ -0,0 +1,50 @@
+### denominator =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Returns the denominator of expression x.
+
+###
+
+
+Eval_denominator = ->
+ push(cadr(p1))
+ Eval()
+ denominator()
+
+denominator = ->
+ h = 0
+
+ theArgument = pop()
+ #console.trace "denominator of: " + theArgument
+
+ if (car(theArgument) == symbol(ADD))
+ push(theArgument)
+ rationalize()
+ theArgument = pop()
+
+ if (car(theArgument) == symbol(MULTIPLY) and !isplusone(car(cdr(theArgument))))
+ h = tos
+ theArgument = cdr(theArgument)
+ while (iscons(theArgument))
+ push(car(theArgument))
+ denominator()
+ theArgument = cdr(theArgument)
+ multiply_all(tos - h)
+ else if (isrational(theArgument))
+ push(theArgument)
+ mp_denominator()
+ else if (car(theArgument) == symbol(POWER) && isnegativeterm(caddr(theArgument)))
+ push(theArgument)
+ reciprocate()
+ else
+ push(one)
+
diff --git a/node_modules/algebrite/sources/derivative.coffee b/node_modules/algebrite/sources/derivative.coffee
new file mode 100644
index 0000000..7573e71
--- /dev/null
+++ b/node_modules/algebrite/sources/derivative.coffee
@@ -0,0 +1,684 @@
+# derivative
+
+
+
+#define F p3
+#define X p4
+#define N p5
+
+Eval_derivative = ->
+
+ # evaluate 1st arg to get function F
+
+ i = 0
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+
+ # evaluate 2nd arg and then...
+
+ # example result of 2nd arg what to do
+ #
+ # d(f) nil guess X, N = nil
+ # d(f,2) 2 guess X, N = 2
+ # d(f,x) x X = x, N = nil
+ # d(f,x,2) x X = x, N = 2
+ # d(f,x,y) x X = x, N = y
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ guess()
+ push(symbol(NIL))
+ else if (isNumericAtom(p2))
+ guess()
+ push(p2)
+ else
+ push(p2)
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+
+ p5 = pop(); # p5 is N
+ p4 = pop(); # p4 is X
+ p3 = pop(); # p3 is F
+
+ while (1)
+
+ # p5 (N) might be a symbol instead of a number
+
+ if (isNumericAtom(p5)) # p5 is N
+ push(p5); # p5 is N
+ n = pop_integer()
+ if (isNaN(n))
+ stop("nth derivative: check n")
+ else
+ n = 1
+
+ push(p3); # p3 is F
+
+ if (n >= 0)
+ for i in [0...n]
+ push(p4); # p4 is X
+ derivative()
+ else
+ n = -n
+ for i in [0...n]
+ push(p4); # p4 is X
+ integral()
+
+ p3 = pop(); # p3 is F
+
+ # if p5 (N) is nil then arglist is exhausted
+
+ if (p5 == symbol(NIL)) # p5 is N
+ break
+
+ # otherwise...
+
+ # N arg1 what to do
+ #
+ # number nil break
+ # number number N = arg1, continue
+ # number symbol X = arg1, N = arg2, continue
+ #
+ # symbol nil X = N, N = nil, continue
+ # symbol number X = N, N = arg1, continue
+ # symbol symbol X = N, N = arg1, continue
+
+ if (isNumericAtom(p5)) # p5 is N
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p5 = pop(); # p5 is N
+ if (p5 == symbol(NIL)) # p5 is N
+ break; # arglist exhausted
+ if (isNumericAtom(p5)) # p5 is N
+ doNothing = 1 # N = arg1
+ else
+ p4 = p5; # p5 is N # p4 is X # X = arg1
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p5 = pop(); # p5 is N # N = arg2
+ else
+ p4 = p5; # p5 is N # p4 is X # X = N
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p5 = pop(); # p5 is N # N = arg1
+
+ push(p3); # p3 is F # final result
+
+derivative = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ if (isNumericAtom(p2))
+ stop("undefined function")
+ if (istensor(p1))
+ if (istensor(p2))
+ d_tensor_tensor()
+ else
+ d_tensor_scalar()
+ else
+ if (istensor(p2))
+ d_scalar_tensor()
+ else
+ d_scalar_scalar()
+ restore()
+
+d_scalar_scalar = ->
+ if (issymbol(p2))
+ d_scalar_scalar_1()
+ else
+ # Example: d(sin(cos(x)),cos(x))
+ # Replace cos(x) <- X, find derivative, then do X <- cos(x)
+ push(p1); # sin(cos(x))
+ push(p2); # cos(x)
+ push(symbol(SECRETX)); # X
+ subst(); # sin(cos(x)) -> sin(X)
+ push(symbol(SECRETX)); # X
+ derivative()
+ push(symbol(SECRETX)); # X
+ push(p2); # cos(x)
+ subst(); # cos(X) -> cos(cos(x))
+
+d_scalar_scalar_1 = ->
+ # d(x,x)?
+
+ if (equal(p1, p2))
+ push(one)
+ return
+
+ # d(a,x)?
+
+ if (!iscons(p1))
+ push(zero)
+ return
+
+ if (isadd(p1))
+ dsum()
+ return
+
+ if (car(p1) == symbol(MULTIPLY))
+ dproduct()
+ return
+
+ if (car(p1) == symbol(POWER))
+ dpower()
+ return
+
+ if (car(p1) == symbol(DERIVATIVE))
+ dd()
+ return
+
+ if (car(p1) == symbol(LOG))
+ dlog()
+ return
+
+ if (car(p1) == symbol(SIN))
+ dsin()
+ return
+
+ if (car(p1) == symbol(COS))
+ dcos()
+ return
+
+ if (car(p1) == symbol(TAN))
+ dtan()
+ return
+
+ if (car(p1) == symbol(ARCSIN))
+ darcsin()
+ return
+
+ if (car(p1) == symbol(ARCCOS))
+ darccos()
+ return
+
+ if (car(p1) == symbol(ARCTAN))
+ darctan()
+ return
+
+ if (car(p1) == symbol(SINH))
+ dsinh()
+ return
+
+ if (car(p1) == symbol(COSH))
+ dcosh()
+ return
+
+ if (car(p1) == symbol(TANH))
+ dtanh()
+ return
+
+ if (car(p1) == symbol(ARCSINH))
+ darcsinh()
+ return
+
+ if (car(p1) == symbol(ARCCOSH))
+ darccosh()
+ return
+
+ if (car(p1) == symbol(ARCTANH))
+ darctanh()
+ return
+
+ if (car(p1) == symbol(ABS))
+ dabs()
+ return
+
+ if (car(p1) == symbol(SGN))
+ dsgn()
+ return
+
+ if (car(p1) == symbol(HERMITE))
+ dhermite()
+ return
+
+ if (car(p1) == symbol(ERF))
+ derf()
+ return
+
+ if (car(p1) == symbol(ERFC))
+ derfc()
+ return
+
+ if (car(p1) == symbol(BESSELJ))
+ if (isZeroAtomOrTensor(caddr(p1)))
+ dbesselj0()
+ else
+ dbesseljn()
+ return
+
+ if (car(p1) == symbol(BESSELY))
+ if (isZeroAtomOrTensor(caddr(p1)))
+ dbessely0()
+ else
+ dbesselyn()
+ return
+
+ if (car(p1) == symbol(INTEGRAL) && caddr(p1) == p2)
+ derivative_of_integral()
+ return
+
+ dfunction()
+
+dsum = ->
+ h = tos
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ derivative()
+ p1 = cdr(p1)
+ add_all(tos - h)
+
+dproduct = ->
+ i = 0
+ j = 0
+ n = 0
+ n = length(p1) - 1
+ for i in [0...n]
+ p3 = cdr(p1)
+ for j in [0...n]
+ push(car(p3))
+ if (i == j)
+ push(p2)
+ derivative()
+ p3 = cdr(p3)
+ multiply_all(n)
+ add_all(n)
+
+#-----------------------------------------------------------------------------
+#
+# v
+# y = u
+#
+# log y = v log u
+#
+# 1 dy v du dv
+# - -- = - -- + (log u) --
+# y dx u dx dx
+#
+# dy v v du dv
+# -- = u (- -- + (log u) --)
+# dx u dx dx
+#
+#-----------------------------------------------------------------------------
+
+dpower = ->
+ push(caddr(p1)); # v/u
+ push(cadr(p1))
+ divide()
+
+ push(cadr(p1)); # du/dx
+ push(p2)
+ derivative()
+
+ multiply()
+
+ push(cadr(p1)); # log u
+ logarithm()
+
+ push(caddr(p1)); # dv/dx
+ push(p2)
+ derivative()
+
+ multiply()
+
+ add()
+
+ push(p1); # u^v
+
+ multiply()
+
+dlog = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ divide()
+
+# derivative of derivative
+#
+# example: d(d(f(x,y),y),x)
+#
+# p1 = d(f(x,y),y)
+#
+# p2 = x
+#
+# cadr(p1) = f(x,y)
+#
+# caddr(p1) = y
+
+dd = ->
+ # d(f(x,y),x)
+
+ push(cadr(p1))
+ push(p2)
+ derivative()
+
+ p3 = pop()
+
+ if (car(p3) == symbol(DERIVATIVE))
+
+ # sort dx terms
+
+ push_symbol(DERIVATIVE)
+ push_symbol(DERIVATIVE)
+ push(cadr(p3))
+
+ if (lessp(caddr(p3), caddr(p1)))
+ push(caddr(p3))
+ list(3)
+ push(caddr(p1))
+ else
+ push(caddr(p1))
+ list(3)
+ push(caddr(p3))
+
+ list(3)
+
+ else
+ push(p3)
+ push(caddr(p1))
+ derivative()
+
+# derivative of a generic function
+
+dfunction = ->
+ p3 = cdr(p1); # p3 is the argument list for the function
+
+ if (p3 == symbol(NIL) || Find(p3, p2))
+ push_symbol(DERIVATIVE)
+ push(p1)
+ push(p2)
+ list(3)
+ else
+ push(zero)
+
+dsin = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ cosine()
+ multiply()
+
+dcos = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ sine()
+ multiply()
+ negate()
+
+dtan = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ cosine()
+ push_integer(-2)
+ power()
+ multiply()
+
+darcsin = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push_integer(1)
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ subtract()
+ push_rational(-1, 2)
+ power()
+ multiply()
+
+darccos = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push_integer(1)
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ subtract()
+ push_rational(-1, 2)
+ power()
+ multiply()
+ negate()
+
+# Without simplify With simplify
+#
+# d(arctan(y/x),x) -y/(x^2*(y^2/x^2+1)) -y/(x^2+y^2)
+#
+# d(arctan(y/x),y) 1/(x*(y^2/x^2+1)) x/(x^2+y^2)
+
+darctan = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push_integer(1)
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ add()
+ inverse()
+ multiply()
+ simplify()
+
+dsinh = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ ycosh()
+ multiply()
+
+dcosh = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ ysinh()
+ multiply()
+
+dtanh = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ ycosh()
+ push_integer(-2)
+ power()
+ multiply()
+
+darcsinh = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ push_integer(1)
+ add()
+ push_rational(-1, 2)
+ power()
+ multiply()
+
+darccosh = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ push_integer(-1)
+ add()
+ push_rational(-1, 2)
+ power()
+ multiply()
+
+darctanh = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push_integer(1)
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ subtract()
+ inverse()
+ multiply()
+
+dabs = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ sgn()
+ multiply()
+
+dsgn = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ dirac()
+ multiply()
+ push_integer(2)
+ multiply()
+
+dhermite = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push_integer(2)
+ push(caddr(p1))
+ multiply()
+ multiply()
+ push(cadr(p1))
+ push(caddr(p1))
+ push_integer(-1)
+ add()
+ hermite()
+ multiply()
+
+derf = ->
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ push_integer(-1)
+ multiply()
+ exponential()
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ push_rational(-1,2)
+ power()
+ multiply()
+ push_integer(2)
+ multiply()
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ multiply()
+
+derfc = ->
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ push_integer(-1)
+ multiply()
+ exponential()
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ push_rational(-1,2)
+ power()
+ multiply()
+ push_integer(-2)
+ multiply()
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ multiply()
+
+dbesselj0 = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ push_integer(1)
+ besselj()
+ multiply()
+ push_integer(-1)
+ multiply()
+
+dbesseljn = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ push(caddr(p1))
+ push_integer(-1)
+ add()
+ besselj()
+ push(caddr(p1))
+ push_integer(-1)
+ multiply()
+ push(cadr(p1))
+ divide()
+ push(cadr(p1))
+ push(caddr(p1))
+ besselj()
+ multiply()
+ add()
+ multiply()
+
+dbessely0 = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ push_integer(1)
+ besselj()
+ multiply()
+ push_integer(-1)
+ multiply()
+
+dbesselyn = ->
+ push(cadr(p1))
+ push(p2)
+ derivative()
+ push(cadr(p1))
+ push(caddr(p1))
+ push_integer(-1)
+ add()
+ bessely()
+ push(caddr(p1))
+ push_integer(-1)
+ multiply()
+ push(cadr(p1))
+ divide()
+ push(cadr(p1))
+ push(caddr(p1))
+ bessely()
+ multiply()
+ add()
+ multiply()
+
+derivative_of_integral = ->
+ push(cadr(p1))
+
+
diff --git a/node_modules/algebrite/sources/det.coffee b/node_modules/algebrite/sources/det.coffee
new file mode 100644
index 0000000..416963e
--- /dev/null
+++ b/node_modules/algebrite/sources/det.coffee
@@ -0,0 +1,289 @@
+### det =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+m
+
+General description
+-------------------
+Returns the determinant of matrix m.
+Uses Gaussian elimination for numerical matrices.
+
+Example:
+
+ det(((1,2),(3,4)))
+ > -2
+
+###
+
+
+DET_check_arg = ->
+ if (!istensor(p1))
+ return 0
+ else if (p1.tensor.ndim != 2)
+ return 0
+ else if (p1.tensor.dim[0] != p1.tensor.dim[1])
+ return 0
+ else
+ return 1
+
+det = ->
+ i = 0
+ n = 0
+ #U **a
+
+ save()
+
+ p1 = pop()
+
+ if (DET_check_arg() == 0)
+ push_symbol(DET)
+ push(p1)
+ list(2)
+ restore()
+ return
+
+ n = p1.tensor.nelem
+
+ a = p1.tensor.elem
+
+ for i in [0...n]
+ if (!isNumericAtom(a[i]))
+ break
+
+ if (i == n)
+ yydetg()
+ else
+ for i in [0...p1.tensor.nelem]
+ push(p1.tensor.elem[i])
+ determinant(p1.tensor.dim[0])
+
+ restore()
+
+# determinant of n * n matrix elements on the stack
+
+determinant = (n) ->
+ h = 0
+ i = 0
+ j = 0
+ k = 0
+ q = 0
+ s = 0
+ sign_ = 0
+ t = 0
+
+ a = []
+ #int *a, *c, *d
+
+ h = tos - n * n
+
+ #a = (int *) malloc(3 * n * sizeof (int))
+
+ #if (a == NULL)
+ # out_of_memory()
+
+ for i in [0...n]
+ a[i] = i
+ a[i+n] = 0
+ a[i+n+n] = 1
+
+ sign_ = 1
+
+ push(zero)
+
+ while 1
+
+ if (sign_ == 1)
+ push_integer(1)
+ else
+ push_integer(-1)
+
+ for i in [0...n]
+ k = n * a[i] + i
+ push(stack[h + k])
+ multiply(); # FIXME -- problem here
+
+ add()
+
+ # next permutation (Knuth's algorithm P)
+
+ j = n - 1
+ s = 0
+
+ breakFromOutherWhile = false
+ while 1
+ q = a[n+j] + a[n+n+j]
+ if (q < 0)
+ a[n+n+j] = -a[n+n+j]
+ j--
+ continue
+ if (q == j + 1)
+ if (j == 0)
+ breakFromOutherWhile = true
+ break
+ s++
+ a[n+n+j] = -a[n+n+j]
+ j--
+ continue
+ break
+
+ if breakFromOutherWhile
+ break
+
+ t = a[j - a[n+j] + s]
+ a[j - a[n+j] + s] = a[j - q + s]
+ a[j - q + s] = t
+ a[n+j] = q
+
+ sign_ = -sign_
+
+
+ stack[h] = stack[tos - 1]
+
+ moveTos h + 1
+
+#-----------------------------------------------------------------------------
+#
+# Input: Matrix on stack
+#
+# Output: Determinant on stack
+#
+# Note:
+#
+# Uses Gaussian elimination which is faster for numerical matrices.
+#
+# Gaussian Elimination works by walking down the diagonal and clearing
+# out the columns below it.
+#
+#-----------------------------------------------------------------------------
+
+detg = ->
+ save()
+
+ p1 = pop()
+
+ if (DET_check_arg() == 0)
+ push_symbol(DET)
+ push(p1)
+ list(2)
+ restore()
+ return
+
+ yydetg()
+
+ restore()
+
+yydetg = ->
+ i = 0
+ n = 0
+
+ n = p1.tensor.dim[0]
+
+ for i in [0...(n * n)]
+ push(p1.tensor.elem[i])
+
+ lu_decomp(n)
+
+ moveTos tos - n * n
+
+ push(p1)
+
+#-----------------------------------------------------------------------------
+#
+# Input: n * n matrix elements on stack
+#
+# Output: p1 determinant
+#
+# p2 mangled
+#
+# upper diagonal matrix on stack
+#
+#-----------------------------------------------------------------------------
+
+M = (h,n,i, j) ->
+ stack[h + n * (i) + (j)]
+
+setM = (h,n,i,j,value) ->
+ stack[h + n * (i) + (j)] = value
+
+lu_decomp = (n) ->
+ d = 0
+ h = 0
+ i = 0
+ j = 0
+
+ h = tos - n * n
+
+ p1 = one
+
+ for d in [0...(n - 1)]
+
+ # diagonal element zero?
+
+ if (equal(M(h,n,d, d), zero))
+
+ # find a new row
+
+ for i in [(d + 1)...n]
+ if (!equal(M(h,n,i, d), zero))
+ break
+
+ if (i == n)
+ p1 = zero
+ break
+
+ # exchange rows
+
+ for j in [d...n]
+ p2 = M(h,n,d, j)
+ setM(h,n,d, j, M(h,n,i, j))
+ setM(h,n,i, j, p2)
+
+ # negate det
+
+ push(p1)
+ negate()
+ p1 = pop()
+
+ # update det
+
+ push(p1)
+ push(M(h,n,d, d))
+ multiply()
+ p1 = pop()
+
+ # update lower diagonal matrix
+
+ for i in [(d + 1)...n]
+
+ # multiplier
+
+ push(M(h,n,i, d))
+ push(M(h,n,d, d))
+ divide()
+ negate()
+
+ p2 = pop()
+
+ # update one row
+
+ setM(h,n,i, d, zero); # clear column below pivot d
+
+ for j in [(d + 1)...n]
+ push(M(h,n,d, j))
+ push(p2)
+ multiply()
+ push(M(h,n,i, j))
+ add()
+ setM(h,n,i, j, pop())
+
+ # last diagonal element
+
+ push(p1)
+ push(M(h,n,n - 1, n - 1))
+ multiply()
+ p1 = pop()
diff --git a/node_modules/algebrite/sources/dirac.coffee b/node_modules/algebrite/sources/dirac.coffee
new file mode 100644
index 0000000..ddd3cb3
--- /dev/null
+++ b/node_modules/algebrite/sources/dirac.coffee
@@ -0,0 +1,69 @@
+#-----------------------------------------------------------------------------
+#
+# Author : philippe.billet@noos.fr
+#
+# Dirac function dirac(x)
+# dirac(-x)=dirac(x)
+# dirac(b-a)=dirac(a-b)
+#-----------------------------------------------------------------------------
+
+
+
+Eval_dirac = ->
+ push(cadr(p1))
+ Eval()
+ dirac()
+
+dirac = ->
+ save()
+ ydirac()
+ restore()
+
+#define p1 p1
+
+ydirac = ->
+
+ p1 = pop()
+
+
+
+ if (isdouble(p1))
+ if (p1.d == 0)
+ push_integer(1)
+ return
+ else
+ push_integer(0)
+ return
+
+ if (isrational(p1))
+ if (MZERO(mmul(p1.q.a,p1.q.b)))
+ push_integer(1)
+ return
+ else
+ push_integer(0)
+ return
+
+
+ if (car(p1) == symbol(POWER))
+ push_symbol(DIRAC)
+ push(cadr(p1))
+ list(2)
+ return
+
+ if (isnegativeterm(p1))
+ push_symbol(DIRAC)
+ push(p1)
+ negate()
+ list(2)
+ return
+
+ if (isnegativeterm(p1) || (car(p1) == symbol(ADD) && isnegativeterm(cadr(p1))))
+ push(p1)
+ negate()
+ p1 = pop()
+
+
+ push_symbol(DIRAC)
+ push(p1)
+ list(2)
+
diff --git a/node_modules/algebrite/sources/divisors.coffee b/node_modules/algebrite/sources/divisors.coffee
new file mode 100644
index 0000000..a3ccfc4
--- /dev/null
+++ b/node_modules/algebrite/sources/divisors.coffee
@@ -0,0 +1,236 @@
+#-----------------------------------------------------------------------------
+#
+# Generate all divisors of a term
+#
+# Input: Term on stack (factor * factor * ...)
+#
+# Output: Divisors on stack
+#
+#-----------------------------------------------------------------------------
+
+
+
+
+divisors = ->
+ i = 0
+ h = 0
+ n = 0
+ save()
+ h = tos - 1
+ divisors_onstack()
+ n = tos - h
+
+ #qsort(stack + h, n, sizeof (U *), __cmp)
+ subsetOfStack = stack.slice(h,h+n)
+ subsetOfStack.sort(cmp_expr)
+ stack = stack.slice(0,h).concat(subsetOfStack).concat(stack.slice(h+n))
+
+ p1 = alloc_tensor(n)
+ p1.tensor.ndim = 1
+ p1.tensor.dim[0] = n
+ for i in [0...n]
+ p1.tensor.elem[i] = stack[h + i]
+ moveTos h
+ push(p1)
+ restore()
+
+divisors_onstack = ->
+ h = 0
+ i = 0
+ k = 0
+ n = 0
+
+ save()
+
+ p1 = pop()
+
+ h = tos
+
+ # push all of the term's factors
+
+ if (isNumericAtom(p1))
+ push(p1)
+ factor_small_number()
+ else if (car(p1) == symbol(ADD))
+ push(p1)
+ __factor_add()
+ #printf(">>>\n")
+ #for (i = h; i < tos; i++)
+ #print(stdout, stack[i])
+ #printf("<<<\n")
+ else if (car(p1) == symbol(MULTIPLY))
+ p1 = cdr(p1)
+ if (isNumericAtom(car(p1)))
+ push(car(p1))
+ factor_small_number()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ p2 = car(p1)
+ if (car(p2) == symbol(POWER))
+ push(cadr(p2))
+ push(caddr(p2))
+ else
+ push(p2)
+ push(one)
+ p1 = cdr(p1)
+ else if (car(p1) == symbol(POWER))
+ push(cadr(p1))
+ push(caddr(p1))
+ else
+ push(p1)
+ push(one)
+
+ k = tos
+
+ # contruct divisors by recursive descent
+
+ push(one)
+
+ gen(h, k)
+
+ # move
+
+ n = tos - k
+
+ for i in [0...n]
+ stack[h + i] = stack[k + i]
+
+ moveTos h + n
+
+ restore()
+
+#-----------------------------------------------------------------------------
+#
+# Generate divisors
+#
+# Input: Base-exponent pairs on stack
+#
+# h first pair
+#
+# k just past last pair
+#
+# Output: Divisors on stack
+#
+# For example, factor list 2 2 3 1 results in 6 divisors,
+#
+# 1
+# 3
+# 2
+# 6
+# 4
+# 12
+#
+#-----------------------------------------------------------------------------
+
+#define ACCUM p1
+#define BASE p2
+#define EXPO p3
+
+gen = (h,k) ->
+ expo = 0
+ i = 0
+
+ save()
+
+ p1 = pop()
+
+ if (h == k)
+ push(p1)
+ restore()
+ return
+
+ p2 = stack[h + 0]
+ p3 = stack[h + 1]
+
+ push(p3)
+ expo = pop_integer()
+
+ if (!isNaN(expo))
+ for i in [0..Math.abs(expo)]
+ push(p1)
+ push(p2)
+ push_integer(sign(expo) * i)
+ power()
+ multiply()
+ gen(h + 2, k)
+
+ restore()
+
+#-----------------------------------------------------------------------------
+#
+# Factor ADD expression
+#
+# Input: Expression on stack
+#
+# Output: Factors on stack
+#
+# Each factor consists of two expressions, the factor itself followed
+# by the exponent.
+#
+#-----------------------------------------------------------------------------
+
+__factor_add = ->
+ save()
+
+ p1 = pop()
+
+ # get gcd of all terms
+
+ p3 = cdr(p1)
+ push(car(p3))
+ p3 = cdr(p3)
+ while (iscons(p3))
+ push(car(p3))
+ gcd()
+ p3 = cdr(p3)
+
+ # check gcd
+
+ p2 = pop()
+ if (isplusone(p2))
+ push(p1)
+ push(one)
+ restore()
+ return
+
+ # push factored gcd
+
+ if (isNumericAtom(p2))
+ push(p2)
+ factor_small_number()
+ else if (car(p2) == symbol(MULTIPLY))
+ p3 = cdr(p2)
+ if (isNumericAtom(car(p3)))
+ push(car(p3))
+ factor_small_number()
+ else
+ push(car(p3))
+ push(one)
+ p3 = cdr(p3)
+ while (iscons(p3))
+ push(car(p3))
+ push(one)
+ p3 = cdr(p3)
+ else
+ push(p2)
+ push(one)
+
+ # divide each term by gcd
+
+ push(p2)
+ inverse()
+ p2 = pop()
+
+ push(zero)
+ p3 = cdr(p1)
+ while (iscons(p3))
+ push(p2)
+ push(car(p3))
+ multiply()
+ add()
+ p3 = cdr(p3)
+
+ push(one)
+
+ restore()
+
diff --git a/node_modules/algebrite/sources/dpow.coffee b/node_modules/algebrite/sources/dpow.coffee
new file mode 100644
index 0000000..0fb43c0
--- /dev/null
+++ b/node_modules/algebrite/sources/dpow.coffee
@@ -0,0 +1,45 @@
+# power function for double precision floating point
+
+
+
+dpow = ->
+ a = 0.0
+ b = 0.0
+ base = 0.0
+ expo = 0.0
+ result = 0.0
+ theta = 0.0
+
+ expo = pop_double()
+ base = pop_double()
+
+ # divide by zero?
+
+ if (base == 0.0 && expo < 0.0)
+ stop("divide by zero")
+
+ # nonnegative base or integer power?
+
+ if (base >= 0.0 || (expo % 1.0) == 0.0)
+ result = Math.pow(base, expo)
+ push_double(result)
+ return
+
+ result = Math.pow(Math.abs(base), expo)
+
+ theta = Math.PI * expo
+
+ # this ensures the real part is 0.0 instead of a tiny fraction
+
+ if ((expo % 0.5) == 0.0)
+ a = 0.0
+ b = Math.sin(theta)
+ else
+ a = Math.cos(theta)
+ b = Math.sin(theta)
+
+ push_double(a * result)
+ push_double(b * result)
+ push(imaginaryunit)
+ multiply()
+ add()
diff --git a/node_modules/algebrite/sources/eigen.coffee b/node_modules/algebrite/sources/eigen.coffee
new file mode 100644
index 0000000..3d6885c
--- /dev/null
+++ b/node_modules/algebrite/sources/eigen.coffee
@@ -0,0 +1,541 @@
+### eigen =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+m
+
+General description
+-------------------
+Compute eigenvalues and eigenvectors. Matrix m must be both numerical and symmetric.
+The eigenval function returns a matrix with the eigenvalues along the diagonal.
+The eigenvec function returns a matrix with the eigenvectors arranged as row vectors.
+The eigen function does not return anything but stores the eigenvalue matrix in D
+and the eigenvector matrix in Q.
+
+Input: stack[tos - 1] symmetric matrix
+
+Output: D diagnonal matrix
+ Q eigenvector matrix
+
+D and Q have the property that
+
+ A == dot(transpose(Q),D,Q)
+
+where A is the original matrix.
+
+The eigenvalues are on the diagonal of D.
+The eigenvectors are row vectors in Q.
+
+The eigenvalue relation:
+
+ A X = lambda X
+
+can be checked as follows:
+
+ lambda = D[1,1]
+ X = Q[1]
+ dot(A,X) - lambda X
+
+Example 1. Check the relation AX = lambda X where lambda is an eigenvalue and X is the associated eigenvector.
+
+Enter:
+
+ A = hilbert(3)
+
+ eigen(A)
+
+ lambda = D[1,1]
+
+ X = Q[1]
+
+ dot(A,X) - lambda X
+
+Result:
+
+ -1.16435e-14
+
+ -6.46705e-15
+
+ -4.55191e-15
+
+Example 2: Check the relation A = QTDQ.
+
+Enter:
+
+ A - dot(transpose(Q),D,Q)
+
+Result:
+
+ 6.27365e-12 -1.58236e-11 1.81902e-11
+
+ -1.58236e-11 -1.95365e-11 2.56514e-12
+
+ 1.81902e-11 2.56514e-12 1.32627e-11
+
+###
+
+
+
+#define D(i, j) yydd[EIG_N * (i) + (j)]
+#define Q(i, j) yyqq[EIG_N * (i) + (j)]
+
+EIG_N = 0
+EIG_yydd = []
+EIG_yyqq = []
+
+Eval_eigen = ->
+ if (EIG_check_arg() == 0)
+ stop("eigen: argument is not a square matrix")
+
+ eigen(EIGEN)
+
+ p1 = usr_symbol("D")
+ set_binding(p1, p2)
+
+ p1 = usr_symbol("Q")
+ set_binding(p1, p3)
+
+ push(symbol(NIL))
+
+### eigenval =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+m
+
+General description
+-------------------
+Compute eigenvalues of m. See "eigen" for more info.
+
+###
+
+Eval_eigenval = ->
+ if (EIG_check_arg() == 0)
+ push_symbol(EIGENVAL)
+ push(p1)
+ list(2)
+ return
+
+ eigen(EIGENVAL)
+
+ push(p2)
+
+### eigenvec =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+m
+
+General description
+-------------------
+Compute eigenvectors of m. See "eigen" for more info.
+
+###
+
+Eval_eigenvec = ->
+ if (EIG_check_arg() == 0)
+ push_symbol(EIGENVEC)
+ push(p1)
+ list(2)
+ return
+
+ eigen(EIGENVEC)
+
+ push(p3)
+
+EIG_check_arg = ->
+ i = 0
+ j = 0
+
+ push(cadr(p1))
+ Eval()
+ yyfloat()
+ Eval()
+ p1 = pop()
+
+ if (!istensor(p1))
+ return 0
+
+ if (p1.tensor.ndim != 2 || p1.tensor.dim[0] != p1.tensor.dim[1])
+ stop("eigen: argument is not a square matrix")
+
+ EIG_N = p1.tensor.dim[0]
+
+ for i in [0...EIG_N]
+ for j in [0...EIG_N]
+ if (!isdouble(p1.tensor.elem[EIG_N * i + j]))
+ stop("eigen: matrix is not numerical")
+
+ for i in [0...(EIG_N-1)]
+ for j in [(i+1)...EIG_N]
+ if (Math.abs(p1.tensor.elem[EIG_N * i + j].d - p1.tensor.elem[EIG_N * j + i].d) > 1e-10)
+ stop("eigen: matrix is not symmetrical")
+
+ return 1
+
+#-----------------------------------------------------------------------------
+#
+# Input: p1 matrix
+#
+# Output: p2 eigenvalues
+#
+# p3 eigenvectors
+#
+#-----------------------------------------------------------------------------
+
+eigen = (op) ->
+ i = 0
+ j = 0
+
+ # malloc working vars
+
+ #EIG_yydd = (double *) malloc(n * n * sizeof (double))
+ for i in [0...(EIG_N*EIG_N)]
+ EIG_yydd[i] = 0.0
+
+ #if (EIG_yydd == NULL)
+ # stop("malloc failure")
+
+ #EIG_yyqq = (double *) malloc(n * n * sizeof (double))
+ for i in [0...(EIG_N*EIG_N)]
+ EIG_yyqq[i] = 0.0
+
+ #if (EIG_yyqq == NULL)
+ # stop("malloc failure")
+
+ # initialize D
+
+ for i in [0...EIG_N]
+ EIG_yydd[EIG_N * (i) + (i)] = p1.tensor.elem[EIG_N * i + i].d
+ for j in [(i+1)...EIG_N]
+ EIG_yydd[EIG_N * (i) + (j)] = p1.tensor.elem[EIG_N * i + j].d
+ EIG_yydd[EIG_N * (j) + (i)] = p1.tensor.elem[EIG_N * i + j].d
+
+ # initialize Q
+
+ for i in [0...EIG_N]
+ EIG_yyqq[EIG_N * (i) + (i)] = 1.0
+ for j in [(i+1)...EIG_N]
+ EIG_yyqq[EIG_N * (i) + (j)] = 0.0
+ EIG_yyqq[EIG_N * (j) + (i)] = 0.0
+
+ # step up to 100 times
+
+ for i in [0...100]
+ if (step() == 0)
+ break
+
+ if (i == 100)
+ printstr("\nnote: eigen did not converge\n")
+
+ # p2 = D
+
+ if (op == EIGEN || op == EIGENVAL)
+
+ push(p1)
+ copy_tensor()
+ p2 = pop()
+
+ for i in [0...EIG_N]
+ for j in [0...EIG_N]
+ push_double(EIG_yydd[EIG_N * (i) + (j)])
+ p2.tensor.elem[EIG_N * i + j] = pop()
+
+ # p3 = Q
+
+ if (op == EIGEN || op == EIGENVEC)
+
+ push(p1)
+ copy_tensor()
+ p3 = pop()
+
+ for i in [0...EIG_N]
+ for j in [0...EIG_N]
+ push_double(EIG_yyqq[EIG_N * (i) + (j)])
+ p3.tensor.elem[EIG_N * i + j] = pop()
+
+ # free working vars
+
+
+#-----------------------------------------------------------------------------
+#
+# Example: p = 1, q = 3
+#
+# c 0 s 0
+#
+# 0 1 0 0
+# G =
+# -s 0 c 0
+#
+# 0 0 0 1
+#
+# The effect of multiplying G times A is...
+#
+# row 1 of A = c (row 1 of A ) + s (row 3 of A )
+# n+1 n n
+#
+# row 3 of A = c (row 3 of A ) - s (row 1 of A )
+# n+1 n n
+#
+# In terms of components the overall effect is...
+#
+# row 1 = c row 1 + s row 3
+#
+# A[1,1] = c A[1,1] + s A[3,1]
+#
+# A[1,2] = c A[1,2] + s A[3,2]
+#
+# A[1,3] = c A[1,3] + s A[3,3]
+#
+# A[1,4] = c A[1,4] + s A[3,4]
+#
+# row 3 = c row 3 - s row 1
+#
+# A[3,1] = c A[3,1] - s A[1,1]
+#
+# A[3,2] = c A[3,2] - s A[1,2]
+#
+# A[3,3] = c A[3,3] - s A[1,3]
+#
+# A[3,4] = c A[3,4] - s A[1,4]
+#
+# T
+# The effect of multiplying A times G is...
+#
+# col 1 of A = c (col 1 of A ) + s (col 3 of A )
+# n+1 n n
+#
+# col 3 of A = c (col 3 of A ) - s (col 1 of A )
+# n+1 n n
+#
+# In terms of components the overall effect is...
+#
+# col 1 = c col 1 + s col 3
+#
+# A[1,1] = c A[1,1] + s A[1,3]
+#
+# A[2,1] = c A[2,1] + s A[2,3]
+#
+# A[3,1] = c A[3,1] + s A[3,3]
+#
+# A[4,1] = c A[4,1] + s A[4,3]
+#
+# col 3 = c col 3 - s col 1
+#
+# A[1,3] = c A[1,3] - s A[1,1]
+#
+# A[2,3] = c A[2,3] - s A[2,1]
+#
+# A[3,3] = c A[3,3] - s A[3,1]
+#
+# A[4,3] = c A[4,3] - s A[4,1]
+#
+# What we want to do is just compute the upper triangle of A since we
+# know the lower triangle is identical.
+#
+# In other words, we just want to update components A[i,j] where i < j.
+#
+#-----------------------------------------------------------------------------
+#
+# Example: p = 2, q = 5
+#
+# p q
+#
+# j=1 j=2 j=3 j=4 j=5 j=6
+#
+# i=1 . A[1,2] . . A[1,5] .
+#
+# p i=2 A[2,1] A[2,2] A[2,3] A[2,4] A[2,5] A[2,6]
+#
+# i=3 . A[3,2] . . A[3,5] .
+#
+# i=4 . A[4,2] . . A[4,5] .
+#
+# q i=5 A[5,1] A[5,2] A[5,3] A[5,4] A[5,5] A[5,6]
+#
+# i=6 . A[6,2] . . A[6,5] .
+#
+#-----------------------------------------------------------------------------
+#
+# This is what B = GA does:
+#
+# row 2 = c row 2 + s row 5
+#
+# B[2,1] = c * A[2,1] + s * A[5,1]
+# B[2,2] = c * A[2,2] + s * A[5,2]
+# B[2,3] = c * A[2,3] + s * A[5,3]
+# B[2,4] = c * A[2,4] + s * A[5,4]
+# B[2,5] = c * A[2,5] + s * A[5,5]
+# B[2,6] = c * A[2,6] + s * A[5,6]
+#
+# row 5 = c row 5 - s row 2
+#
+# B[5,1] = c * A[5,1] + s * A[2,1]
+# B[5,2] = c * A[5,2] + s * A[2,2]
+# B[5,3] = c * A[5,3] + s * A[2,3]
+# B[5,4] = c * A[5,4] + s * A[2,4]
+# B[5,5] = c * A[5,5] + s * A[2,5]
+# B[5,6] = c * A[5,6] + s * A[2,6]
+#
+# T
+# This is what BG does:
+#
+# col 2 = c col 2 + s col 5
+#
+# B[1,2] = c * A[1,2] + s * A[1,5]
+# B[2,2] = c * A[2,2] + s * A[2,5]
+# B[3,2] = c * A[3,2] + s * A[3,5]
+# B[4,2] = c * A[4,2] + s * A[4,5]
+# B[5,2] = c * A[5,2] + s * A[5,5]
+# B[6,2] = c * A[6,2] + s * A[6,5]
+#
+# col 5 = c col 5 - s col 2
+#
+# B[1,5] = c * A[1,5] - s * A[1,2]
+# B[2,5] = c * A[2,5] - s * A[2,2]
+# B[3,5] = c * A[3,5] - s * A[3,2]
+# B[4,5] = c * A[4,5] - s * A[4,2]
+# B[5,5] = c * A[5,5] - s * A[5,2]
+# B[6,5] = c * A[6,5] - s * A[6,2]
+#
+#-----------------------------------------------------------------------------
+#
+# Step 1: Just do upper triangle (i < j), B[2,5] = 0
+#
+# B[1,2] = c * A[1,2] + s * A[1,5]
+#
+# B[2,3] = c * A[2,3] + s * A[5,3]
+# B[2,4] = c * A[2,4] + s * A[5,4]
+# B[2,6] = c * A[2,6] + s * A[5,6]
+#
+# B[1,5] = c * A[1,5] - s * A[1,2]
+# B[3,5] = c * A[3,5] - s * A[3,2]
+# B[4,5] = c * A[4,5] - s * A[4,2]
+#
+# B[5,6] = c * A[5,6] + s * A[2,6]
+#
+#-----------------------------------------------------------------------------
+#
+# Step 2: Transpose where i > j since A[i,j] == A[j,i]
+#
+# B[1,2] = c * A[1,2] + s * A[1,5]
+#
+# B[2,3] = c * A[2,3] + s * A[3,5]
+# B[2,4] = c * A[2,4] + s * A[4,5]
+# B[2,6] = c * A[2,6] + s * A[5,6]
+#
+# B[1,5] = c * A[1,5] - s * A[1,2]
+# B[3,5] = c * A[3,5] - s * A[2,3]
+# B[4,5] = c * A[4,5] - s * A[2,4]
+#
+# B[5,6] = c * A[5,6] + s * A[2,6]
+#
+#-----------------------------------------------------------------------------
+#
+# Step 3: Same as above except reorder
+#
+# k < p (k = 1)
+#
+# A[1,2] = c * A[1,2] + s * A[1,5]
+# A[1,5] = c * A[1,5] - s * A[1,2]
+#
+# p < k < q (k = 3..4)
+#
+# A[2,3] = c * A[2,3] + s * A[3,5]
+# A[3,5] = c * A[3,5] - s * A[2,3]
+#
+# A[2,4] = c * A[2,4] + s * A[4,5]
+# A[4,5] = c * A[4,5] - s * A[2,4]
+#
+# q < k (k = 6)
+#
+# A[2,6] = c * A[2,6] + s * A[5,6]
+# A[5,6] = c * A[5,6] - s * A[2,6]
+#
+#-----------------------------------------------------------------------------
+
+step = ->
+ i = 0
+ j = 0
+ count = 0
+
+ # for each upper triangle "off-diagonal" component do step2
+
+ for i in [0...(EIG_N-1)]
+ for j in [(i+1)...EIG_N]
+ if (EIG_yydd[EIG_N * (i) + (j)] != 0.0)
+ step2(i, j)
+ count++
+
+ return count
+
+step2 = (p,q) ->
+ k = 0
+ t = 0.0
+ theta = 0.0
+ c = 0.0
+ cc = 0.0
+ s = 0.0
+ ss = 0.0
+
+ # compute c and s
+
+ # from Numerical Recipes (except they have a_qq - a_pp)
+
+ theta = 0.5 * (EIG_yydd[EIG_N * (p) + (p)] - EIG_yydd[EIG_N * (q) + (q)]) / EIG_yydd[EIG_N * (p) + (q)]
+
+ t = 1.0 / (Math.abs(theta) + Math.sqrt(theta * theta + 1.0))
+
+ if (theta < 0.0)
+ t = -t
+
+ c = 1.0 / Math.sqrt(t * t + 1.0)
+
+ s = t * c
+
+ # D = GD
+
+ # which means "add rows"
+
+ for k in [0...EIG_N]
+ cc = EIG_yydd[EIG_N * (p) + (k)]
+ ss = EIG_yydd[EIG_N * (q) + (k)]
+ EIG_yydd[EIG_N * (p) + (k)] = c * cc + s * ss
+ EIG_yydd[EIG_N * (q) + (k)] = c * ss - s * cc
+
+ # D = D transpose(G)
+
+ # which means "add columns"
+
+ for k in [0...EIG_N]
+ cc = EIG_yydd[EIG_N * (k) + (p)]
+ ss = EIG_yydd[EIG_N * (k) + (q)]
+ EIG_yydd[EIG_N * (k) + (p)] = c * cc + s * ss
+ EIG_yydd[EIG_N * (k) + (q)] = c * ss - s * cc
+
+ # Q = GQ
+
+ # which means "add rows"
+
+ for k in [0...EIG_N]
+ cc = EIG_yyqq[EIG_N * (p) + (k)]
+ ss = EIG_yyqq[EIG_N * (q) + (k)]
+ EIG_yyqq[EIG_N * (p) + (k)] = c * cc + s * ss
+ EIG_yyqq[EIG_N * (q) + (k)] = c * ss - s * cc
+
+ EIG_yydd[EIG_N * (p) + (q)] = 0.0
+ EIG_yydd[EIG_N * (q) + (p)] = 0.0
+
+
diff --git a/node_modules/algebrite/sources/erf.coffee b/node_modules/algebrite/sources/erf.coffee
new file mode 100644
index 0000000..d61ec44
--- /dev/null
+++ b/node_modules/algebrite/sources/erf.coffee
@@ -0,0 +1,60 @@
+### erf =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Authors
+-------
+philippe.billet@noos.fr
+
+Parameters
+----------
+x
+
+General description
+-------------------
+Error function erf(x).
+erf(-x)=erf(x)
+
+###
+
+
+
+Eval_erf = ->
+ push(cadr(p1))
+ Eval()
+ yerf()
+
+yerf = ->
+ save()
+ yyerf()
+ restore()
+
+yyerf = ->
+ d = 0.0
+
+ p1 = pop()
+
+ if (isdouble(p1))
+ d = 1.0 - erfc(p1.d)
+ push_double(d)
+ return
+
+ if isZeroAtomOrTensor(p1)
+ push(zero)
+ return
+
+ if (isnegativeterm(p1))
+ push_symbol(ERF)
+ push(p1)
+ negate()
+ list(2)
+ negate()
+ return
+
+ push_symbol(ERF)
+ push(p1)
+ list(2)
+ return
+
diff --git a/node_modules/algebrite/sources/erfc.coffee b/node_modules/algebrite/sources/erfc.coffee
new file mode 100644
index 0000000..80b2bfa
--- /dev/null
+++ b/node_modules/algebrite/sources/erfc.coffee
@@ -0,0 +1,61 @@
+#-----------------------------------------------------------------------------
+#
+# Author : philippe.billet@noos.fr
+#
+# erfc(x)
+#
+# GW Added erfc() from Numerical Recipes in C
+#
+#-----------------------------------------------------------------------------
+
+
+
+Eval_erfc = ->
+ push(cadr(p1))
+ Eval()
+ yerfc()
+
+yerfc = ->
+ save()
+ yyerfc()
+ restore()
+
+yyerfc = ->
+ d = 0.0
+
+ p1 = pop()
+
+ if (isdouble(p1))
+ d = erfc(p1.d)
+ push_double(d)
+ return
+
+ if isZeroAtomOrTensor(p1)
+ push(one)
+ return
+
+ push_symbol(ERFC)
+ push(p1)
+ list(2)
+ return
+
+# from Numerical Recipes in C
+erfc = (x) ->
+ if x == 0
+ return 1.0
+
+ t = 0.0
+ z = 0.0
+ ans = 0.0
+
+ z = Math.abs(x)
+ t = 1.0 / (1.0 + 0.5 * z)
+
+ ans=t*Math.exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+
+ t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+
+ t*(-0.82215223+t*0.17087277)))))))))
+
+ if x >= 0.0
+ return ans
+ else
+ return 2.0-ans
diff --git a/node_modules/algebrite/sources/eval.coffee b/node_modules/algebrite/sources/eval.coffee
new file mode 100644
index 0000000..9b54c0e
--- /dev/null
+++ b/node_modules/algebrite/sources/eval.coffee
@@ -0,0 +1,716 @@
+# Evaluate an expression, for example...
+#
+# push(p1)
+# Eval()
+# p2 = pop()
+
+
+
+Eval = ->
+ check_esc_flag()
+ save()
+ p1 = pop()
+ if !p1?
+ debugger
+
+ if !evaluatingAsFloats and isfloating(p1)
+ willEvaluateAsFloats = true
+ evaluatingAsFloats++
+
+ switch (p1.k)
+ when CONS
+ Eval_cons()
+ when NUM
+ if evaluatingAsFloats
+ push_double(convert_rational_to_double(p1))
+ else
+ push(p1)
+ when DOUBLE, STR
+ push(p1)
+ when TENSOR
+ Eval_tensor()
+ when SYM
+ Eval_sym()
+ else
+ stop("atom?")
+
+ if willEvaluateAsFloats
+ evaluatingAsFloats--
+
+ restore()
+
+Eval_sym = ->
+
+ # note that function calls are not processed here
+ # because, since they have an argument (at least an empty one)
+ # they are actually CONs, which is a branch of the
+ # switch before the one that calls this function
+
+ # bare keyword?
+ # If it's a keyword, then we don't look
+ # at the binding array, because keywords
+ # are not redefinable.
+ if (iskeyword(p1))
+ push(p1)
+ push(symbol(LAST))
+ list(2)
+ Eval()
+ return
+ else if (p1 == symbol(PI) and evaluatingAsFloats)
+ push_double(Math.PI)
+ return
+
+ # Evaluate symbol's binding
+ p2 = get_binding(p1)
+ if DEBUG then console.log "looked up: " + p1 + " which contains: " + p2
+
+ push(p2)
+
+
+ # differently from standard Lisp,
+ # here the evaluation is not
+ # one-step only, rather it keeps evaluating
+ # "all the way" until a symbol is
+ # defined as itself.
+ # Uncomment these two lines to get Lisp
+ # behaviour (and break most tests)
+ if (p1 != p2)
+
+ # detect recursive lookup of symbols, which would otherwise
+ # cause a stack overflow.
+ # Note that recursive functions will still work because
+ # as mentioned at the top, this method doesn't look
+ # up and evaluate function calls.
+ positionIfSymbolAlreadyBeingEvaluated = chainOfUserSymbolsNotFunctionsBeingEvaluated.indexOf(p1)
+ if positionIfSymbolAlreadyBeingEvaluated != -1
+ cycleString = ""
+ for i in [positionIfSymbolAlreadyBeingEvaluated...chainOfUserSymbolsNotFunctionsBeingEvaluated.length]
+ cycleString += chainOfUserSymbolsNotFunctionsBeingEvaluated[i].printname + " -> "
+ cycleString += p1.printname
+
+ stop("recursive evaluation of symbols: " + cycleString)
+ return
+
+ chainOfUserSymbolsNotFunctionsBeingEvaluated.push(p1)
+
+
+ Eval()
+
+ chainOfUserSymbolsNotFunctionsBeingEvaluated.pop()
+
+Eval_cons = ->
+
+ cons_head = car(p1)
+
+ # normally the cons_head is a symbol,
+ # but sometimes in the case of
+ # functions we don't have a symbol,
+ # we have to evaluate something to get to the
+ # symbol. For example if a function is inside
+ # a tensor, then we need to evaluate an index
+ # access first to get to the function.
+ # In those cases, we find an EVAL here,
+ # so we proceed to EVAL
+ if car(cons_head) == symbol(EVAL)
+ Eval_user_function()
+ return
+
+ # If we didn't fall in the EVAL case above
+ # then at this point we must have a symbol.
+ if (!issymbol(cons_head))
+ stop("cons?")
+
+ switch (symnum(cons_head))
+ when ABS then Eval_abs()
+ when ADD then Eval_add()
+ when ADJ then Eval_adj()
+ when AND then Eval_and()
+ when ARCCOS then Eval_arccos()
+ when ARCCOSH then Eval_arccosh()
+ when ARCSIN then Eval_arcsin()
+ when ARCSINH then Eval_arcsinh()
+ when ARCTAN then Eval_arctan()
+ when ARCTANH then Eval_arctanh()
+ when ARG then Eval_arg()
+ when ATOMIZE then Eval_atomize()
+ when BESSELJ then Eval_besselj()
+ when BESSELY then Eval_bessely()
+ when BINDING then Eval_binding()
+ when BINOMIAL then Eval_binomial()
+ when CEILING then Eval_ceiling()
+ when CHECK then Eval_check()
+ when CHOOSE then Eval_choose()
+ when CIRCEXP then Eval_circexp()
+ when CLEAR then Eval_clear()
+ when CLEARALL then Eval_clearall()
+ when CLEARPATTERNS then Eval_clearpatterns()
+ when CLOCK then Eval_clock()
+ when COEFF then Eval_coeff()
+ when COFACTOR then Eval_cofactor()
+ when CONDENSE then Eval_condense()
+ when CONJ then Eval_conj()
+ when CONTRACT then Eval_contract()
+ when COS then Eval_cos()
+ when COSH then Eval_cosh()
+ when DECOMP then Eval_decomp()
+ when DEGREE then Eval_degree()
+ when DEFINT then Eval_defint()
+ when DENOMINATOR then Eval_denominator()
+ when DERIVATIVE then Eval_derivative()
+ when DET then Eval_det()
+ when DIM then Eval_dim()
+ when DIRAC then Eval_dirac()
+ when DIVISORS then Eval_divisors()
+ when DO then Eval_do()
+ when DOT then Eval_inner()
+ when DRAW then Eval_draw()
+ when DSOLVE then Eval_dsolve()
+ when EIGEN then Eval_eigen()
+ when EIGENVAL then Eval_eigenval()
+ when EIGENVEC then Eval_eigenvec()
+ when ERF then Eval_erf()
+ when ERFC then Eval_erfc()
+ when EVAL then Eval_Eval()
+ when EXP then Eval_exp()
+ when EXPAND then Eval_expand()
+ when EXPCOS then Eval_expcos()
+ when EXPSIN then Eval_expsin()
+ when FACTOR then Eval_factor()
+ when FACTORIAL then Eval_factorial()
+ when FACTORPOLY then Eval_factorpoly()
+ when FILTER then Eval_filter()
+ when FLOATF then Eval_float()
+ when APPROXRATIO then Eval_approxratio()
+ when FLOOR then Eval_floor()
+ when FOR then Eval_for()
+ # this is invoked only when we
+ # evaluate a function that is NOT being called
+ # e.g. when f is a function as we do
+ # g = f
+ when FUNCTION then Eval_function_reference()
+ when GAMMA then Eval_gamma()
+ when GCD then Eval_gcd()
+ when HERMITE then Eval_hermite()
+ when HILBERT then Eval_hilbert()
+ when IMAG then Eval_imag()
+ when INDEX then Eval_index()
+ when INNER then Eval_inner()
+ when INTEGRAL then Eval_integral()
+ when INV then Eval_inv()
+ when INVG then Eval_invg()
+ when ISINTEGER then Eval_isinteger()
+ when ISPRIME then Eval_isprime()
+ when LAGUERRE then Eval_laguerre()
+ # when LAPLACE then Eval_laplace()
+ when LCM then Eval_lcm()
+ when LEADING then Eval_leading()
+ when LEGENDRE then Eval_legendre()
+ when LOG then Eval_log()
+ when LOOKUP then Eval_lookup()
+ when MOD then Eval_mod()
+ when MULTIPLY then Eval_multiply()
+ when NOT then Eval_not()
+ when NROOTS then Eval_nroots()
+ when NUMBER then Eval_number()
+ when NUMERATOR then Eval_numerator()
+ when OPERATOR then Eval_operator()
+ when OR then Eval_or()
+ when OUTER then Eval_outer()
+ when PATTERN then Eval_pattern()
+ when PATTERNSINFO then Eval_patternsinfo()
+ when POLAR then Eval_polar()
+ when POWER then Eval_power()
+ when PRIME then Eval_prime()
+ when PRINT then Eval_print()
+ when PRINT2DASCII then Eval_print2dascii()
+ when PRINTFULL then Eval_printcomputer()
+ when PRINTLATEX then Eval_printlatex()
+ when PRINTLIST then Eval_printlist()
+ when PRINTPLAIN then Eval_printhuman()
+ when PRODUCT then Eval_product()
+ when QUOTE then Eval_quote()
+ when QUOTIENT then Eval_quotient()
+ when RANK then Eval_rank()
+ when RATIONALIZE then Eval_rationalize()
+ when REAL then Eval_real()
+ when ROUND then Eval_round()
+ when YYRECT then Eval_rect()
+ when ROOTS then Eval_roots()
+ when SETQ then Eval_setq()
+ when SGN then Eval_sgn()
+ when SILENTPATTERN then Eval_silentpattern()
+ when SIMPLIFY then Eval_simplify()
+ when SIN then Eval_sin()
+ when SINH then Eval_sinh()
+ when SHAPE then Eval_shape()
+ when SQRT then Eval_sqrt()
+ when STOP then Eval_stop()
+ when SUBST then Eval_subst()
+ when SUM then Eval_sum()
+ when SYMBOLSINFO then Eval_symbolsinfo()
+ when TAN then Eval_tan()
+ when TANH then Eval_tanh()
+ when TAYLOR then Eval_taylor()
+ when TEST then Eval_test()
+ when TESTEQ then Eval_testeq()
+ when TESTGE then Eval_testge()
+ when TESTGT then Eval_testgt()
+ when TESTLE then Eval_testle()
+ when TESTLT then Eval_testlt()
+ when TRANSPOSE then Eval_transpose()
+ when UNIT then Eval_unit()
+ when ZERO then Eval_zero()
+ else
+ Eval_user_function()
+
+Eval_binding = ->
+ push(get_binding(cadr(p1)))
+
+### check =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+p
+
+General description
+-------------------
+Returns whether the predicate p is true/false or unknown:
+0 if false, 1 if true or remains unevaluated if unknown.
+Note that if "check" is passed an assignment, it turns it into a test,
+i.e. check(a = b) is turned into check(a==b)
+so "a" is not assigned anything.
+Like in many programming languages, "check" also gives truthyness/falsyness
+for numeric values. In which case, "true" is returned for non-zero values.
+Potential improvements: "check" can't evaluate strings yet.
+
+###
+
+Eval_check = ->
+ # check the argument
+ checkResult = isZeroLikeOrNonZeroLikeOrUndetermined cadr(p1)
+
+ if !checkResult?
+ # returned null: unknown result
+ # leave the whole check unevalled
+ push p1
+ else
+ # returned 1 or 0
+ push_integer(checkResult)
+
+
+Eval_det = ->
+ push(cadr(p1))
+ Eval()
+ det()
+
+
+### dim =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+m,n
+
+General description
+-------------------
+Returns the cardinality of the nth index of tensor "m".
+
+###
+
+Eval_dim = ->
+ #int n
+ push(cadr(p1))
+ Eval()
+ p2 = pop()
+ if (iscons(cddr(p1)))
+ push(caddr(p1))
+ Eval()
+ n = pop_integer()
+ else
+ n = 1
+ if (!istensor(p2))
+ push_integer(1) # dim of scalar is 1
+ else if (n < 1 || n > p2.tensor.ndim)
+ push(p1)
+ else
+ push_integer(p2.tensor.dim[n - 1])
+
+Eval_divisors = ->
+ push(cadr(p1))
+ Eval()
+ divisors()
+
+### do =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+a,b,...
+
+General description
+-------------------
+Evaluates each argument from left to right. Returns the result of the last argument.
+
+###
+
+Eval_do = ->
+ push(car(p1))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ pop()
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+
+Eval_dsolve = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ push(cadddr(p1))
+ Eval()
+ dsolve()
+
+# for example, Eval(f,x,2)
+
+Eval_Eval = ->
+ push(cadr(p1))
+ Eval()
+ p1 = cddr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ push(cadr(p1))
+ Eval()
+ subst()
+ p1 = cddr(p1)
+ Eval()
+
+# exp evaluation: it replaces itself with
+# a POWER(E,something) node and evals that one
+Eval_exp = ->
+ push(cadr(p1))
+ Eval()
+ exponential()
+
+Eval_factorial = ->
+ push(cadr(p1))
+ Eval()
+ factorial()
+
+Eval_factorpoly = ->
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ factorpoly()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ factorpoly()
+ p1 = cdr(p1)
+
+Eval_hermite = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ hermite()
+
+Eval_hilbert = ->
+ push(cadr(p1))
+ Eval()
+ hilbert()
+
+Eval_index = ->
+ h = tos
+ orig = p1
+
+ # look into the head of the list,
+ # when evaluated it should be a tensor
+ p1 = cdr(p1)
+ push car(p1)
+ Eval()
+ theTensor = stack[tos-1]
+
+ if isNumericAtom(theTensor)
+ stop("trying to access a scalar as a tensor")
+
+ if !istensor(theTensor)
+ # the tensor is not allocated yet, so
+ # leaving the expression unevalled
+ moveTos h
+ push orig
+ return
+
+ # we examined the head of the list which
+ # was the tensor, now look into
+ # the indexes
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ if !isintegerorintegerfloat(stack[tos-1])
+ # index with something other than
+ # an integer
+ moveTos h
+ push orig
+ return
+ p1 = cdr(p1)
+ index_function(tos - h)
+
+Eval_inv = ->
+ push(cadr(p1))
+ Eval()
+ inv()
+
+Eval_invg = ->
+ push(cadr(p1))
+ Eval()
+ invg()
+
+Eval_isinteger = ->
+ push(cadr(p1))
+ Eval()
+ p1 = pop()
+ if (isrational(p1))
+ if (isinteger(p1))
+ push(one)
+ else
+ push(zero)
+ return
+ if (isdouble(p1))
+ n = Math.floor(p1.d)
+ if (n == p1.d)
+ push(one)
+ else
+ push(zero)
+ return
+ push_symbol(ISINTEGER)
+ push(p1)
+ list(2)
+
+Eval_number = ->
+ push(cadr(p1))
+ Eval()
+ p1 = pop()
+ if (p1.k == NUM || p1.k == DOUBLE)
+ push_integer(1)
+ else
+ push_integer(0)
+
+Eval_operator = ->
+ h = tos
+ push_symbol(OPERATOR)
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ list(tos - h)
+
+# quote definition
+Eval_quote = ->
+ push(cadr(p1))
+
+# rank definition
+Eval_rank = ->
+ push(cadr(p1))
+ Eval()
+ p1 = pop()
+ if (istensor(p1))
+ push_integer(p1.tensor.ndim)
+ else
+ push(zero)
+
+# Evaluates the right side and assigns the
+# result of the evaluation to the left side.
+# It's called setq because it stands for "set quoted" from Lisp,
+# see:
+# http://stackoverflow.com/questions/869529/difference-between-set-setq-and-setf-in-common-lisp
+# Note that this also takes case of assigning to a tensor
+# element, which is something that setq wouldn't do
+# in list, see comments further down below.
+
+# Example:
+# f = x
+# // f evaluates to x, so x is assigned to g really
+# // rather than actually f being assigned to g
+# g = f
+# f = y
+# g
+# > x
+
+Eval_setq = ->
+ # case of tensor
+ if (caadr(p1) == symbol(INDEX))
+ setq_indexed()
+ return
+
+ # case of function definition
+ if (iscons(cadr(p1)))
+ define_user_function()
+ return
+
+ if (!issymbol(cadr(p1)))
+ stop("symbol assignment: error in symbol")
+
+ push(caddr(p1))
+ Eval()
+ p2 = pop()
+ set_binding(cadr(p1), p2)
+
+ # An assignment returns nothing.
+ # This is unlike most programming languages
+ # where an assignment does return the
+ # assigned value.
+ # TODO Could be changed.
+ push(symbol(NIL))
+
+# Here "setq" is a misnomer because
+# setq wouldn't work in Lisp to set array elements
+# since setq stands for "set quoted" and you wouldn't
+# quote an array element access.
+# You'd rather use setf, which is a macro that can
+# assign a value to anything.
+# (setf (aref YourArray 2) "blue")
+# see
+# http://stackoverflow.com/questions/18062016/common-lisp-how-to-set-an-element-in-a-2d-array
+#-----------------------------------------------------------------------------
+#
+# Example: a[1] = b
+#
+# p1 *-------*-----------------------*
+# | | |
+# setq *-------*-------* b
+# | | |
+# index a 1
+#
+# cadadr(p1) -> a
+#
+#-----------------------------------------------------------------------------
+
+setq_indexed = ->
+ p4 = cadadr(p1)
+ # console.log "p4: " + p4
+ if (!issymbol(p4))
+ # this is likely to happen when one tries to
+ # do assignments like these
+ # 1[2] = 3
+ # or
+ # f(x)[1] = 2
+ # or
+ # [[1,2],[3,4]][5] = 6
+ #
+ # In other words, one can only do
+ # a straight assignment like
+ # existingMatrix[index] = something
+ stop("indexed assignment: expected a symbol name")
+ h = tos
+ push(caddr(p1))
+ Eval()
+ p2 = cdadr(p1)
+ while (iscons(p2))
+ push(car(p2))
+ Eval()
+ p2 = cdr(p2)
+ set_component(tos - h)
+ p3 = pop()
+ set_binding(p4, p3)
+ push(symbol(NIL))
+
+
+Eval_sqrt = ->
+ push(cadr(p1))
+ Eval()
+ push_rational(1, 2)
+ power()
+
+Eval_stop = ->
+ stop("user stop")
+
+Eval_subst = ->
+ push(cadddr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ push(cadr(p1))
+ Eval()
+ subst()
+ Eval() # normalize
+
+# always returns a matrix with rank 2
+# i.e. two dimensions,
+# the passed parameter is the size
+Eval_unit = ->
+ i = 0
+ n = 0
+ push(cadr(p1))
+ Eval()
+ n = pop_integer()
+
+ if isNaN(n)
+ push(p1)
+ return
+
+ if (n < 1)
+ push(p1)
+ return
+
+ p1 = alloc_tensor(n * n)
+ p1.tensor.ndim = 2
+ p1.tensor.dim[0] = n
+ p1.tensor.dim[1] = n
+ for i in [0...n]
+ p1.tensor.elem[n * i + i] = one
+ check_tensor_dimensions p1
+ push(p1)
+
+Eval_noexpand = ->
+ prev_expanding = expanding
+ expanding = 0
+ Eval()
+ expanding = prev_expanding
+
+# like Eval() except "=" (assignment) is treated
+# as "==" (equality test)
+# This is because
+# * this allows users to be lazy and just
+# use "=" instead of "==" as per more common
+# mathematical notation
+# * in many places we don't expect an assignment
+# e.g. we don't expect to test the zero-ness
+# of an assignment or the truth value of
+# an assignment
+# Note that these are questionable assumptions
+# as for example in most programming languages one
+# can indeed test the value of an assignment (the
+# value is just the evaluation of the right side)
+
+Eval_predicate = ->
+ save()
+ p1 = top()
+ if (car(p1) == symbol(SETQ))
+ # replace the assignment in the
+ # head with an equality test
+ pop()
+ push_symbol(TESTEQ)
+ push cadr(p1)
+ push caddr(p1)
+ list 3
+
+ Eval()
+ restore()
diff --git a/node_modules/algebrite/sources/expand.coffee b/node_modules/algebrite/sources/expand.coffee
new file mode 100644
index 0000000..a948a68
--- /dev/null
+++ b/node_modules/algebrite/sources/expand.coffee
@@ -0,0 +1,533 @@
+# Partial fraction expansion
+#
+# Example
+#
+# expand(1/(x^3+x^2),x)
+#
+# 1 1 1
+# ---- - --- + -------
+# 2 x x + 1
+# x
+
+
+
+Eval_expand = ->
+
+ # 1st arg
+
+ push(cadr(p1))
+ Eval()
+
+ # 2nd arg
+
+ push(caddr(p1))
+ Eval()
+
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ guess()
+ else
+ push(p2)
+
+ expand()
+
+#define A p2
+#define B p3
+#define C p4
+#define F p5
+#define P p6
+#define Q p7
+#define T p8
+#define X p9
+
+expand = ->
+
+ save()
+
+ p9 = pop()
+ p5 = pop()
+
+ if (istensor(p5))
+ expand_tensor()
+ restore()
+ return
+
+ # if sum of terms then sum over the expansion of each term
+
+ if (car(p5) == symbol(ADD))
+ push_integer(0)
+ p1 = cdr(p5)
+ while (iscons(p1))
+ push(car(p1))
+ push(p9)
+ expand()
+ add()
+ p1 = cdr(p1)
+ restore()
+ return
+
+ # B = numerator
+
+ push(p5)
+ numerator()
+ p3 = pop()
+
+ # A = denominator
+
+ push(p5)
+ denominator()
+ p2 = pop()
+
+ remove_negative_exponents()
+
+ # Q = quotient
+
+ push(p3)
+ push(p2)
+ push(p9)
+
+ # if the denominator is one then always bail out
+ # also bail out if the denominator is not one but
+ # it's not anything recognizable as a polynomial.
+ if isone(p3) || isone(p2)
+ if !ispolyexpandedform(p2,p9) || isone(p2)
+ pop()
+ pop()
+ pop()
+ push(p5)
+ # p5 is the original input, leave unchanged
+ restore()
+ return
+
+ divpoly()
+ p7 = pop()
+
+ # remainder B = B - A * Q
+
+ push(p3)
+ push(p2)
+ push(p7)
+ multiply()
+ subtract()
+ p3 = pop()
+
+ # if the remainder is zero then we're done
+
+ if (isZeroAtomOrTensor(p3))
+ push(p7)
+ restore()
+ return
+
+ # A = factor(A)
+
+ #console.log("expand - to be factored: " + p2)
+ push(p2)
+ push(p9)
+ factorpoly()
+ p2 = pop()
+ #console.log("expand - factored to: " + p2)
+
+ expand_get_C()
+ expand_get_B()
+ expand_get_A()
+
+ if (istensor(p4))
+ push(p4)
+ prev_expanding = expanding
+ expanding = 1
+ inv()
+ expanding = prev_expanding
+ push(p3)
+ inner()
+ push(p2)
+ inner()
+ else
+ push(p3)
+ push(p4)
+ prev_expanding = expanding
+ expanding = 1
+ divide()
+ expanding = prev_expanding
+ push(p2)
+ multiply()
+
+ push(p7)
+ add()
+
+ restore()
+
+expand_tensor = ->
+ i = 0
+ push(p5)
+ copy_tensor()
+ p5 = pop()
+ for i in [0...p5.tensor.nelem]
+ push(p5.tensor.elem[i])
+ push(p9)
+ expand()
+ p5.tensor.elem[i] = pop()
+ push(p5)
+
+remove_negative_exponents = ->
+ h = 0
+ i = 0
+ j = 0
+ k = 0
+ n = 0
+
+ h = tos
+ factors(p2)
+ factors(p3)
+ n = tos - h
+
+ # find the smallest exponent
+
+ j = 0
+ for i in [0...n]
+ p1 = stack[h + i]
+ if (car(p1) != symbol(POWER))
+ continue
+ if (cadr(p1) != p9)
+ continue
+ push(caddr(p1))
+ k = pop_integer()
+ if (isNaN(k))
+ continue
+ if (k < j)
+ j = k
+
+ moveTos h
+
+ if (j == 0)
+ return
+
+ # A = A / X^j
+
+ push(p2)
+ push(p9)
+ push_integer(-j)
+ power()
+ multiply()
+ p2 = pop()
+
+ # B = B / X^j
+
+ push(p3)
+ push(p9)
+ push_integer(-j)
+ power()
+ multiply()
+ p3 = pop()
+
+# Returns the expansion coefficient matrix C.
+#
+# Example:
+#
+# B 1
+# --- = -----------
+# A 2
+# x (x + 1)
+#
+# We have
+#
+# B Y1 Y2 Y3
+# --- = ---- + ---- + -------
+# A 2 x x + 1
+# x
+#
+# Our task is to solve for the unknowns Y1, Y2, and Y3.
+#
+# Multiplying both sides by A yields
+#
+# AY1 AY2 AY3
+# B = ----- + ----- + -------
+# 2 x x + 1
+# x
+#
+# Let
+#
+# A A A
+# W1 = ---- W2 = --- W3 = -------
+# 2 x x + 1
+# x
+#
+# Then the coefficient matrix C is
+#
+# coeff(W1,x,0) coeff(W2,x,0) coeff(W3,x,0)
+#
+# C = coeff(W1,x,1) coeff(W2,x,1) coeff(W3,x,1)
+#
+# coeff(W1,x,2) coeff(W2,x,2) coeff(W3,x,2)
+#
+# It follows that
+#
+# coeff(B,x,0) Y1
+#
+# coeff(B,x,1) = C Y2
+#
+# coeff(B,x,2) = Y3
+#
+# Hence
+#
+# Y1 coeff(B,x,0)
+# -1
+# Y2 = C coeff(B,x,1)
+#
+# Y3 coeff(B,x,2)
+
+expand_get_C = ->
+ h = 0
+ i = 0
+ j = 0
+ n = 0
+ #U **a
+ h = tos
+ if (car(p2) == symbol(MULTIPLY))
+ p1 = cdr(p2)
+ while (iscons(p1))
+ p5 = car(p1)
+ expand_get_CF()
+ p1 = cdr(p1)
+ else
+ p5 = p2
+ expand_get_CF()
+ n = tos - h
+ if (n == 1)
+ p4 = pop()
+ return
+ p4 = alloc_tensor(n * n)
+ p4.tensor.ndim = 2
+ p4.tensor.dim[0] = n
+ p4.tensor.dim[1] = n
+ a = h
+ for i in [0...n]
+ for j in [0...n]
+ push(stack[a+j])
+ push(p9)
+ push_integer(i)
+ power()
+ prev_expanding = expanding
+ expanding = 1
+ divide()
+ expanding = prev_expanding
+ push(p9)
+ filter()
+ p4.tensor.elem[n * i + j] = pop()
+ moveTos tos - n
+
+# The following table shows the push order for simple roots, repeated roots,
+# and inrreducible factors.
+#
+# Factor F Push 1st Push 2nd Push 3rd Push 4th
+#
+#
+# A
+# x ---
+# x
+#
+#
+# 2 A A
+# x ---- ---
+# 2 x
+# x
+#
+#
+# A
+# x + 1 -------
+# x + 1
+#
+#
+# 2 A A
+# (x + 1) ---------- -------
+# 2 x + 1
+# (x + 1)
+#
+#
+# 2 A Ax
+# x + x + 1 ------------ ------------
+# 2 2
+# x + x + 1 x + x + 1
+#
+#
+# 2 2 A Ax A Ax
+# (x + x + 1) --------------- --------------- ------------ ------------
+# 2 2 2 2 2 2
+# (x + x + 1) (x + x + 1) x + x + 1 x + x + 1
+#
+#
+# For T = A/F and F = P^N we have
+#
+#
+# Factor F Push 1st Push 2nd Push 3rd Push 4th
+#
+# x T
+#
+# 2
+# x T TP
+#
+#
+# x + 1 T
+#
+# 2
+# (x + 1) T TP
+#
+# 2
+# x + x + 1 T TX
+#
+# 2 2
+# (x + x + 1) T TX TP TPX
+#
+#
+# Hence we want to push in the order
+#
+# T * (P ^ i) * (X ^ j)
+#
+# for all i, j such that
+#
+# i = 0, 1, ..., N - 1
+#
+# j = 0, 1, ..., deg(P) - 1
+#
+# where index j runs first.
+
+expand_get_CF = ->
+ d = 0
+ i = 0
+ j = 0
+ n = 0
+
+ if (!Find(p5, p9))
+ return
+ prev_expanding = expanding
+ expanding = 1
+ trivial_divide()
+ expanding = prev_expanding
+ if (car(p5) == symbol(POWER))
+ push(caddr(p5))
+ n = pop_integer()
+ p6 = cadr(p5)
+ else
+ n = 1
+ p6 = p5
+
+ push(p6)
+ push(p9)
+ degree()
+ d = pop_integer()
+ for i in [0...n]
+ for j in [0...d]
+ push(p8)
+ push(p6)
+ push_integer(i)
+ power()
+ prev_expanding = expanding
+ expanding = 1
+ multiply()
+ expanding = prev_expanding
+ push(p9)
+ push_integer(j)
+ power()
+ prev_expanding = expanding
+ expanding = 1
+ multiply()
+ expanding = prev_expanding
+
+# Returns T = A/F where F is a factor of A.
+
+trivial_divide = ->
+ h = 0
+ if (car(p2) == symbol(MULTIPLY))
+ h = tos
+ p0 = cdr(p2)
+ while (iscons(p0))
+ if (!equal(car(p0), p5))
+ push(car(p0))
+ Eval(); # force expansion of (x+1)^2, f.e.
+ p0 = cdr(p0)
+ multiply_all(tos - h)
+ else
+ push_integer(1)
+ p8 = pop()
+
+# Returns the expansion coefficient vector B.
+
+expand_get_B = ->
+ i = 0
+ n = 0
+ if (!istensor(p4))
+ return
+ n = p4.tensor.dim[0]
+ p8 = alloc_tensor(n)
+ p8.tensor.ndim = 1
+ p8.tensor.dim[0] = n
+ for i in [0...n]
+ push(p3)
+ push(p9)
+ push_integer(i)
+ power()
+ prev_expanding = expanding
+ expanding = 1
+ divide()
+ expanding = prev_expanding
+ push(p9)
+ filter()
+ p8.tensor.elem[i] = pop()
+ p3 = p8
+
+# Returns the expansion fractions in A.
+
+expand_get_A = ->
+ h = 0
+ i = 0
+ n = 0
+ if (!istensor(p4))
+ push(p2)
+ reciprocate()
+ p2 = pop()
+ return
+ h = tos
+ if (car(p2) == symbol(MULTIPLY))
+ p8 = cdr(p2)
+ while (iscons(p8))
+ p5 = car(p8)
+ expand_get_AF()
+ p8 = cdr(p8)
+ else
+ p5 = p2
+ expand_get_AF()
+ n = tos - h
+ p8 = alloc_tensor(n)
+ p8.tensor.ndim = 1
+ p8.tensor.dim[0] = n
+ for i in [0...n]
+ p8.tensor.elem[i] = stack[h + i]
+ moveTos h
+ p2 = p8
+
+expand_get_AF = ->
+ d = 0
+ i = 0
+ j = 0
+ n = 1
+ if (!Find(p5, p9))
+ return
+ if (car(p5) == symbol(POWER))
+ push(caddr(p5))
+ n = pop_integer()
+ p5 = cadr(p5)
+ push(p5)
+ push(p9)
+ degree()
+ d = pop_integer()
+ for i in [n...0]
+ for j in [0...d]
+ push(p5)
+ push_integer(i)
+ power()
+ reciprocate()
+ push(p9)
+ push_integer(j)
+ power()
+ multiply()
+
+
diff --git a/node_modules/algebrite/sources/expcos.coffee b/node_modules/algebrite/sources/expcos.coffee
new file mode 100644
index 0000000..1809864
--- /dev/null
+++ b/node_modules/algebrite/sources/expcos.coffee
@@ -0,0 +1,34 @@
+# Do the exponential cosine function.
+
+
+
+Eval_expcos = ->
+ push(cadr(p1))
+ Eval()
+ expcos()
+
+expcos = ->
+ save()
+
+ p1 = pop()
+
+ push(imaginaryunit)
+ push(p1)
+ multiply()
+ exponential()
+ push_rational(1, 2)
+ multiply()
+
+ push(imaginaryunit)
+ negate()
+ push(p1)
+ multiply()
+ exponential()
+ push_rational(1, 2)
+ multiply()
+
+ add()
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/expsin.coffee b/node_modules/algebrite/sources/expsin.coffee
new file mode 100644
index 0000000..576af35
--- /dev/null
+++ b/node_modules/algebrite/sources/expsin.coffee
@@ -0,0 +1,38 @@
+# Do the exponential sine function.
+
+
+
+Eval_expsin = ->
+ push(cadr(p1))
+ Eval()
+ expsin()
+
+expsin = ->
+ save()
+
+ p1 = pop()
+
+ push(imaginaryunit)
+ push(p1)
+ multiply()
+ exponential()
+ push(imaginaryunit)
+ divide()
+ push_rational(1, 2)
+ multiply()
+
+ push(imaginaryunit)
+ negate()
+ push(p1)
+ multiply()
+ exponential()
+ push(imaginaryunit)
+ divide()
+ push_rational(1, 2)
+ multiply()
+
+ subtract()
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/factor.coffee b/node_modules/algebrite/sources/factor.coffee
new file mode 100644
index 0000000..cabd9bd
--- /dev/null
+++ b/node_modules/algebrite/sources/factor.coffee
@@ -0,0 +1,121 @@
+# factor a polynomial or integer
+
+
+
+Eval_factor = ->
+ push(cadr(p1))
+ Eval()
+
+ push(caddr(p1))
+ Eval()
+
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ guess()
+ else
+ push(p2)
+
+ factor()
+
+ # more factoring?
+
+ p1 = cdddr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ factor_again()
+ p1 = cdr(p1)
+
+factor_again = ->
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ h = tos
+
+ if (car(p1) == symbol(MULTIPLY))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ factor_term()
+ p1 = cdr(p1)
+ else
+ push(p1)
+ push(p2)
+ factor_term()
+
+ n = tos - h
+
+ if (n > 1)
+ multiply_all_noexpand(n)
+
+ restore()
+
+factor_term = ->
+ save()
+ factorpoly()
+ p1 = pop()
+ if (car(p1) == symbol(MULTIPLY))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ p1 = cdr(p1)
+ else
+ push(p1)
+ restore()
+
+factor = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ if (isinteger(p1))
+ push(p1)
+ factor_number(); # see pollard.cpp
+ else
+ push(p1)
+ push(p2)
+ factorpoly()
+ restore()
+
+# for factoring small integers (2^32 or less)
+
+factor_small_number = ->
+
+ i = 0
+ save()
+
+ n = pop_integer()
+
+ if (isNaN(n))
+ stop("number too big to factor")
+
+ if (n < 0)
+ n = -n
+
+ for i in [0...MAXPRIMETAB]
+
+ d = primetab[i]
+
+ if (d > n / d)
+ break
+
+ expo = 0
+
+ while (n % d == 0)
+ n /= d
+ expo++
+
+ if (expo)
+ push_integer(d)
+ push_integer(expo)
+
+ if (n > 1)
+ push_integer(n)
+ push_integer(1)
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/factorial.coffee b/node_modules/algebrite/sources/factorial.coffee
new file mode 100644
index 0000000..6972ef1
--- /dev/null
+++ b/node_modules/algebrite/sources/factorial.coffee
@@ -0,0 +1,170 @@
+
+
+
+factorial = ->
+ n = 0
+ save()
+ p1 = pop()
+ push(p1)
+ n = pop_integer()
+ if (n < 0 || isNaN(n))
+ push_symbol(FACTORIAL)
+ push(p1)
+ list(2)
+ restore()
+ return
+ bignum_factorial(n)
+ restore()
+
+
+# simplification rules for factorials (m < n)
+#
+# (e + 1) * factorial(e) -> factorial(e + 1)
+#
+# factorial(e) / e -> factorial(e - 1)
+#
+# e / factorial(e) -> 1 / factorial(e - 1)
+#
+# factorial(e + n)
+# ---------------- -> (e + m + 1)(e + m + 2)...(e + n)
+# factorial(e + m)
+#
+# factorial(e + m) 1
+# ---------------- -> --------------------------------
+# factorial(e + n) (e + m + 1)(e + m + 2)...(e + n)
+
+# this function is not actually used, but
+# all these simplifications
+# do happen automatically via simplify
+simplifyfactorials = ->
+ x = 0
+
+ save()
+
+ x = expanding
+ expanding = 0
+
+ p1 = pop()
+
+ if (car(p1) == symbol(ADD))
+ push(zero)
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ simplifyfactorials()
+ add()
+ p1 = cdr(p1)
+ expanding = x
+ restore()
+ return
+
+ if (car(p1) == symbol(MULTIPLY))
+ sfac_product()
+ expanding = x
+ restore()
+ return
+
+ push(p1)
+
+ expanding = x
+ restore()
+
+sfac_product = ->
+ i = 0
+ j = 0
+ n = 0
+
+ s = tos
+
+ p1 = cdr(p1)
+ n = 0
+ while (iscons(p1))
+ push(car(p1))
+ p1 = cdr(p1)
+ n++
+
+ for i in [0...(n - 1)]
+ if (stack[s + i] == symbol(NIL))
+ continue
+ for j in [(i + 1)...n]
+ if (stack[s + j] == symbol(NIL))
+ continue
+ sfac_product_f(s, i, j)
+
+ push(one)
+
+ for i in [0...n]
+ if (stack[s+i] == symbol(NIL))
+ continue
+ push(stack[s+i])
+ multiply()
+
+ p1 = pop()
+
+ moveTos tos - n
+
+ push(p1)
+
+sfac_product_f = (s,a,b) ->
+ i = 0
+ n = 0
+
+ p1 = stack[s + a]
+ p2 = stack[s + b]
+
+ if (ispower(p1))
+ p3 = caddr(p1)
+ p1 = cadr(p1)
+ else
+ p3 = one
+
+ if (ispower(p2))
+ p4 = caddr(p2)
+ p2 = cadr(p2)
+ else
+ p4 = one
+
+ if (isfactorial(p1) && isfactorial(p2))
+
+ # Determine if the powers cancel.
+
+ push(p3)
+ push(p4)
+ add()
+ yyexpand()
+ n = pop_integer()
+ if (n != 0)
+ return
+
+ # Find the difference between the two factorial args.
+
+ # For example, the difference between (a + 2)! and a! is 2.
+
+ push(cadr(p1))
+ push(cadr(p2))
+ subtract()
+ yyexpand(); # to simplify
+
+ n = pop_integer()
+ if (n == 0 || isNaN(n))
+ return
+ if (n < 0)
+ n = -n
+ p5 = p1
+ p1 = p2
+ p2 = p5
+ p5 = p3
+ p3 = p4
+ p4 = p5
+
+ push(one)
+
+ for i in [1..n]
+ push(cadr(p2))
+ push_integer(i)
+ add()
+ push(p3)
+ power()
+ multiply()
+ stack[s+a] = pop()
+ stack[s+b] = symbol(NIL)
diff --git a/node_modules/algebrite/sources/factorpoly.coffee b/node_modules/algebrite/sources/factorpoly.coffee
new file mode 100644
index 0000000..145fad3
--- /dev/null
+++ b/node_modules/algebrite/sources/factorpoly.coffee
@@ -0,0 +1,582 @@
+# Factor a polynomial
+
+factorpoly = ->
+ if DEBUG then console.log "factorpoly: " + stack[tos-1].toString() + " " + stack[tos-2].toString()
+
+ save()
+
+ variable = pop()
+ polynomial = pop()
+
+ if !Find(polynomial, variable) or
+ !ispolyexpandedform(polynomial, variable) or
+ !issymbol(variable)
+ push(polynomial)
+
+ else
+ yyfactorpoly(variable, polynomial)
+
+ restore()
+
+#-----------------------------------------------------------------------------
+#
+# Input: tos-2 true polynomial
+#
+# tos-1 free variable
+#
+# Output: factored polynomial on stack
+#
+#-----------------------------------------------------------------------------
+
+yyfactorpoly = (variable, polynomial) ->
+
+ if DEBUG
+ firstParam = variable
+ secondParam = polynomial
+ console.log "yyfactorpoly: " + firstParam + " " + secondParam
+
+
+ save()
+
+ h = tos
+
+ if (isfloating(polynomial))
+ stop("floating point numbers in polynomial")
+
+ polycoeff = tos
+
+ factpoly_expo = coeff(variable, polynomial) - 1
+
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " factpoly_expo before rationalize_coefficients: " + factpoly_expo
+ partOfPolynomialFactoredSoFar = rationalize_coefficients(h)
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " factpoly_expo after rationalize_coefficients: " + factpoly_expo
+
+ # for univariate polynomials we could do factpoly_expo > 1
+
+ whichRootsAreWeFinding = "real"
+ remainingPoly = null
+ while (factpoly_expo > 0)
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " factpoly_expo inside while loop: " + factpoly_expo
+
+ if (isZeroAtomOrTensor(stack[polycoeff+0]))
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " isZeroAtomOrTensor"
+ A = one
+ B = zero
+ else
+ #console.log("trying to find a " + whichRootsAreWeFinding + " root")
+ if whichRootsAreWeFinding == "real"
+ [foundRealRoot,A,B] = get_factor_from_real_root(variable, factpoly_expo, polycoeff)
+ else if whichRootsAreWeFinding == "complex"
+ [foundComplexRoot,A] = get_factor_from_complex_root(remainingPoly, factpoly_expo, polycoeff)
+
+ if whichRootsAreWeFinding == "real"
+ if foundRealRoot == 0
+ whichRootsAreWeFinding = "complex"
+ continue
+ else
+ # build the 1-degree polynomial out of the
+ # real solution that was just found.
+ push(A) # A
+ push(variable) # x
+ multiply()
+ push(B) # B
+ add()
+ AxPlusB = pop()
+
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " success\nFACTOR=" + AxPlusB
+
+ # factor out negative sign (not req'd because A > 1)
+ #if 0
+ ###
+ if (isnegativeterm(A))
+ push(AxPlusB)
+ negate()
+ AxPlusB = pop()
+ push(partOfPolynomialFactoredSoFar)
+ negate_noexpand()
+ partOfPolynomialFactoredSoFar = pop()
+ ###
+ #endif
+
+ # partOfPolynomialFactoredSoFar is the part of the polynomial that was factored so far,
+ # add the newly found factor to it. Note that we are not actually
+ # multiplying the polynomials fully, we are just leaving them
+ # expressed as (P1)*(P2), we are not expanding the product.
+ push(partOfPolynomialFactoredSoFar)
+ push(AxPlusB)
+ multiply_noexpand()
+ partOfPolynomialFactoredSoFar = pop()
+
+ # ok now on stack we have the coefficients of the
+ # remaining part of the polynomial still to factor.
+ # Divide it by the newly-found factor so that
+ # the stack then contains the coefficients of the
+ # polynomial part still left to factor.
+ yydivpoly(factpoly_expo, polycoeff, A, B)
+
+ while (factpoly_expo and isZeroAtomOrTensor(stack[polycoeff+factpoly_expo]))
+ factpoly_expo--
+
+ push(zero)
+ for i in [0..factpoly_expo]
+ push(stack[polycoeff+i])
+ push(variable) # the free variable
+ push_integer(i)
+ power()
+ multiply()
+ add()
+ remainingPoly = pop()
+ #console.log("real branch remainingPoly: " + remainingPoly)
+
+ else if whichRootsAreWeFinding == "complex"
+ if foundComplexRoot == 0
+ break
+ else
+ # build the 2-degree polynomial out of the
+ # real solution that was just found.
+ push(A) # A
+ push(variable) # x
+ subtract()
+ #console.log("first factor: " + stack[tos-1].toString())
+
+ push(A) # A
+ conjugate()
+ push(variable) # x
+ subtract()
+ #console.log("second factor: " + stack[tos-1].toString())
+
+ multiply()
+
+ #if (factpoly_expo > 0 && isnegativeterm(stack[polycoeff+factpoly_expo]))
+ # negate()
+ # negate_noexpand()
+
+ secondDegreePloly = pop()
+
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " success\nFACTOR=" + secondDegreePloly
+
+ # factor out negative sign (not req'd because A > 1)
+ #if 0
+ ###
+ if (isnegativeterm(A))
+ push(secondDegreePloly)
+ negate()
+ secondDegreePloly = pop()
+ push(partOfPolynomialFactoredSoFar)
+ negate_noexpand()
+ partOfPolynomialFactoredSoFar = pop()
+ ###
+ #endif
+
+ # partOfPolynomialFactoredSoFar is the part of the polynomial that was factored so far,
+ # add the newly found factor to it. Note that we are not actually
+ # multiplying the polynomials fully, we are just leaving them
+ # expressed as (P1)*(P2), we are not expanding the product.
+
+ push(partOfPolynomialFactoredSoFar)
+ previousFactorisation = pop()
+
+ #console.log("previousFactorisation: " + previousFactorisation)
+
+ push(partOfPolynomialFactoredSoFar)
+ push(secondDegreePloly)
+ multiply_noexpand()
+ partOfPolynomialFactoredSoFar = pop()
+
+ #console.log("new prospective factorisation: " + partOfPolynomialFactoredSoFar)
+
+
+ # build the polynomial of the unfactored part
+ #console.log("build the polynomial of the unfactored part factpoly_expo: " + factpoly_expo)
+
+ if !remainingPoly?
+ push(zero)
+ for i in [0..factpoly_expo]
+ push(stack[polycoeff+i])
+ push(variable) # the free variable
+ push_integer(i)
+ power()
+ multiply()
+ add()
+ remainingPoly = pop()
+ #console.log("original polynomial (dividend): " + remainingPoly)
+
+ dividend = remainingPoly
+ #push(dividend)
+ #degree()
+ #startingDegree = pop()
+ push(dividend)
+
+ #console.log("dividing " + stack[tos-1].toString() + " by " + secondDegreePloly)
+ push(secondDegreePloly) # divisor
+ push(variable) # X
+ divpoly()
+ remainingPoly = pop()
+
+ push(remainingPoly)
+ push(secondDegreePloly) # divisor
+ multiply()
+ checkingTheDivision = pop()
+
+ if !equal(checkingTheDivision, dividend)
+
+ #push(dividend)
+ #gcd_sum()
+ #console.log("gcd top of stack: " + stack[tos-1].toString())
+
+
+ if DEBUG then console.log("we found a polynomial based on complex root and its conj but it doesn't divide the poly, quitting")
+ if DEBUG then console.log("so just returning previousFactorisation times dividend: " + previousFactorisation + " * " + dividend)
+ push(previousFactorisation)
+ push(dividend)
+
+ prev_expanding = expanding
+ expanding = 0
+ yycondense()
+ expanding = prev_expanding
+
+ multiply_noexpand()
+ partOfPolynomialFactoredSoFar = pop()
+ stack[h] = partOfPolynomialFactoredSoFar
+ moveTos h + 1
+ restore()
+ return
+
+ #console.log("result: (still to be factored) " + remainingPoly)
+
+ #push(remainingPoly)
+ #degree()
+ #remainingDegree = pop()
+
+ ###
+ if compare_numbers(startingDegree, remainingDegree)
+ # ok even if we found a complex root that
+ # together with the conjugate generates a poly in Z,
+ # that doesn't mean that the division would end up in Z.
+ # Example: 1+x^2+x^4+x^6 has +i and -i as one of its roots
+ # so a factor is 1+x^2 ( = (x+i)*(x-i))
+ # BUT
+ ###
+
+
+ for i in [0..factpoly_expo]
+ pop()
+
+ coeff(variable, remainingPoly)
+
+
+ factpoly_expo -= 2
+ #console.log("factpoly_expo: " + factpoly_expo)
+
+
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " building the remaining unfactored part of the polynomial"
+
+ push(zero)
+ for i in [0..factpoly_expo]
+ push(stack[polycoeff+i])
+ push(variable) # the free variable
+ push_integer(i)
+ power()
+ multiply()
+ add()
+ polynomial = pop()
+
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " remaining unfactored part of the polynomial: " + polynomial.toString()
+
+ push(polynomial)
+
+ prev_expanding = expanding
+ expanding = 0
+ yycondense()
+ expanding = prev_expanding
+
+ polynomial = pop()
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " new poly with extracted common factor: " + polynomial.toString()
+ #debugger
+
+ # factor out negative sign
+
+ if (factpoly_expo > 0 && isnegativeterm(stack[polycoeff+factpoly_expo]))
+ push(polynomial)
+ #prev_expanding = expanding
+ #expanding = 1
+ negate()
+ #expanding = prev_expanding
+ polynomial = pop()
+ push(partOfPolynomialFactoredSoFar)
+ negate_noexpand()
+ partOfPolynomialFactoredSoFar = pop()
+
+ push(partOfPolynomialFactoredSoFar)
+ push(polynomial)
+ multiply_noexpand()
+ partOfPolynomialFactoredSoFar = pop()
+
+ if DEBUG then console.log "yyfactorpoly: " + firstParam + " " + secondParam + " result: " + partOfPolynomialFactoredSoFar
+
+ stack[h] = partOfPolynomialFactoredSoFar
+
+ moveTos h + 1
+
+ restore()
+
+rationalize_coefficients = (h) ->
+
+ # LCM of all polynomial coefficients
+
+ ratio = one
+ for i in [h...tos]
+ push(stack[i])
+ denominator()
+ push(ratio)
+ lcm()
+ ratio = pop()
+
+ # multiply each coefficient by RESULT
+
+ for i in [h...tos]
+ push(ratio)
+ push(stack[i])
+ multiply()
+ stack[i] = pop()
+
+ # reciprocate RESULT
+
+ push(ratio)
+ reciprocate()
+ ratioInverse = pop()
+ if DEBUG then console.log "rationalize_coefficients result: " + ratioInverse.toString()
+ return ratioInverse
+
+get_factor_from_real_root = (variable, factpoly_expo, polycoeff)->
+
+ if DEBUG then console.log "get_factor_from_real_root"
+
+ i = 0
+ j = 0
+ h = 0
+ a0 = 0
+ an = 0
+ na0 = 0
+ nan = 0
+
+ if DEBUG
+ push(zero)
+ for i in [0..factpoly_expo]
+ push(stack[polycoeff+i])
+ push(variable)
+ push_integer(i)
+ power()
+ multiply()
+ add()
+ polynomial = pop()
+ console.log("POLY=" + polynomial)
+
+ h = tos
+
+ an = tos
+ push(stack[polycoeff+factpoly_expo])
+
+ divisors_onstack()
+
+ nan = tos - an
+
+ a0 = tos
+ push(stack[polycoeff+0])
+ divisors_onstack()
+ na0 = tos - a0
+
+ if DEBUG
+ console.log("divisors of base term")
+ for i in [0...na0]
+ console.log(", " + stack[a0 + i])
+ console.log("divisors of leading term")
+ for i in [0...nan]
+ console.log(", " + stack[an + i])
+
+ # try roots
+
+ for rootsTries_i in [0...nan]
+ for rootsTries_j in [0...na0]
+
+ #if DEBUG then console.log "nan: " + nan + " na0: " + na0 + " i: " + rootsTries_i + " j: " + rootsTries_j
+
+ testNumerator = stack[an + rootsTries_i]
+ testDenominator = stack[a0 + rootsTries_j]
+
+ push(testDenominator)
+ push(testNumerator)
+ divide()
+ negate()
+ testValue = pop()
+
+ evalPolyResult = Evalpoly(factpoly_expo, polycoeff, testValue)
+
+ if DEBUG
+ console.log("try A=" + testNumerator)
+ console.log(", B=" + testDenominator)
+ console.log(", root " + variable)
+ console.log("=-B/A=" + testValue)
+ console.log(", POLY(" + testValue)
+ console.log(")=" + evalPolyResult)
+
+ if (isZeroAtomOrTensor(evalPolyResult))
+ moveTos h
+ if DEBUG then console.log "get_factor_from_real_root returning 1"
+ return [1, testNumerator, testDenominator]
+
+ push(testDenominator)
+ negate()
+ testDenominator = pop()
+
+ push(testValue)
+ negate()
+ testValue = pop()
+
+ evalPolyResult = Evalpoly(factpoly_expo, polycoeff, testValue)
+
+ if DEBUG
+ console.log("try A=" + testNumerator)
+ console.log(", B=" + testDenominator)
+ console.log(", root " + variable)
+ console.log("=-B/A=" + testValue)
+ console.log(", POLY(" + testValue)
+ console.log(")=" + evalPolyResult)
+
+ if (isZeroAtomOrTensor(evalPolyResult))
+ moveTos h
+ if DEBUG then console.log "get_factor_from_real_root returning 1"
+ return [1, testNumerator, testDenominator]
+
+ moveTos h
+
+ if DEBUG then console.log "get_factor_from_real_root returning"
+ return [0, null, null]
+
+get_factor_from_complex_root = (remainingPoly, factpoly_expo, polycoeff) ->
+
+ i = 0
+ j = 0
+ h = 0
+ a0 = 0
+ an = 0
+ na0 = 0
+ nan = 0
+
+ if factpoly_expo <= 2
+ if DEBUG then console.log("no more factoring via complex roots to be found in polynomial of degree <= 2")
+ return [0,null]
+
+ if DEBUG then console.log("complex root finding for POLY=" + remainingPoly)
+
+ h = tos
+ an = tos
+
+ # trying -1^(2/3) which generates a polynomial in Z
+ # generates x^2 + 2x + 1
+ push_integer(-1)
+ push_rational(2,3)
+ power()
+ rect()
+ testValue = pop()
+ if DEBUG then console.log("complex root finding: trying with " + testValue)
+ push(testValue)
+ evalPolyResult = Evalpoly(factpoly_expo, polycoeff, testValue)
+ if DEBUG then console.log("complex root finding result: " + evalPolyResult)
+ if (isZeroAtomOrTensor(evalPolyResult))
+ moveTos h
+ if DEBUG then console.log "get_factor_from_complex_root returning 1"
+ return [1,testValue]
+
+ # trying 1^(2/3) which generates a polynomial in Z
+ # http://www.wolframalpha.com/input/?i=(1)%5E(2%2F3)
+ # generates x^2 - 2x + 1
+ push_integer(1)
+ push_rational(2,3)
+ power()
+ rect()
+ testValue = pop()
+ if DEBUG then console.log("complex root finding: trying with " + testValue)
+ push(testValue)
+ evalPolyResult = Evalpoly(factpoly_expo, polycoeff, testValue)
+ if DEBUG then console.log("complex root finding result: " + evalPolyResult)
+ if (isZeroAtomOrTensor(evalPolyResult))
+ moveTos h
+ if DEBUG then console.log "get_factor_from_complex_root returning 1"
+ return [1,testValue]
+
+
+ # trying some simple complex numbers. All of these
+ # generate polynomials in Z
+ for rootsTries_i in [-10..10]
+ for rootsTries_j in [1..5]
+ push_integer(rootsTries_i)
+ push_integer(rootsTries_j)
+ push(imaginaryunit)
+ multiply()
+ add()
+ rect()
+ testValue = pop()
+ if DEBUG then console.log("complex root finding: trying simple complex combination " + testValue)
+
+
+ push(testValue)
+
+ evalPolyResult = Evalpoly(factpoly_expo, polycoeff, testValue)
+
+ #console.log("complex root finding result: " + evalPolyResult)
+ if (isZeroAtomOrTensor(evalPolyResult))
+ moveTos h
+ if DEBUG then console.log "found complex root: " + evalPolyResult
+ return [1,testValue]
+
+ moveTos h
+
+ if DEBUG then console.log "get_factor_from_complex_root returning 0"
+ return [0,null]
+
+#-----------------------------------------------------------------------------
+#
+# Divide a polynomial by Ax+B
+#
+# Input: on stack: polycoeff Dividend coefficients
+#
+# factpoly_expo as parameter
+#
+# A as parameter
+#
+# B as parameter
+#
+# Output: on stack: polycoeff Contains quotient coefficients
+#
+#-----------------------------------------------------------------------------
+
+yydivpoly = (factpoly_expo, polycoeff, A, B) ->
+ Q = zero
+ for i in [factpoly_expo...0]
+ push(stack[polycoeff+i])
+ stack[polycoeff+i] = Q
+ push(A)
+ divide()
+ Q = pop()
+ push(stack[polycoeff+i - 1])
+ push(Q)
+ push(B)
+ multiply()
+ subtract()
+ stack[polycoeff+i - 1] = pop()
+ stack[polycoeff+0] = Q
+ if DEBUG then console.log "yydivpoly Q: " + Q.toString()
+
+Evalpoly = (factpoly_expo, polycoeff, evaluateAt) ->
+ push(zero)
+ for i in [factpoly_expo..0]
+ push(evaluateAt)
+ multiply()
+ push(stack[polycoeff+i])
+ #if DEBUG
+ # console.log("Evalpoly top of stack:")
+ # console.log stack[tos-i].toString()
+ add()
+ return pop()
+
diff --git a/node_modules/algebrite/sources/factors.coffee b/node_modules/algebrite/sources/factors.coffee
new file mode 100644
index 0000000..4b9737b
--- /dev/null
+++ b/node_modules/algebrite/sources/factors.coffee
@@ -0,0 +1,42 @@
+# Push expression factors onto the stack. For example...
+#
+# Input
+#
+# 2
+# 3x + 2x + 1
+#
+# Output on stack
+#
+# [ 3 ]
+# [ x^2 ]
+# [ 2 ]
+# [ x ]
+# [ 1 ]
+#
+# but not necessarily in that order. Returns the number of factors.
+
+
+
+# Local U *p is OK here because no functional path to garbage collector.
+
+factors = (p) ->
+ h = tos
+ if (car(p) == symbol(ADD))
+ p = cdr(p)
+ while (iscons(p))
+ push_term_factors(car(p))
+ p = cdr(p)
+ else
+ push_term_factors(p)
+ return tos - h
+
+# Local U *p is OK here because no functional path to garbage collector.
+
+push_term_factors = (p) ->
+ if (car(p) == symbol(MULTIPLY))
+ p = cdr(p)
+ while (iscons(p))
+ push(car(p))
+ p = cdr(p)
+ else
+ push(p)
diff --git a/node_modules/algebrite/sources/filter.coffee b/node_modules/algebrite/sources/filter.coffee
new file mode 100644
index 0000000..dc0effb
--- /dev/null
+++ b/node_modules/algebrite/sources/filter.coffee
@@ -0,0 +1,71 @@
+###
+Remove terms that involve a given symbol or expression. For example...
+
+ filter(x^2 + x + 1, x) => 1
+
+ filter(x^2 + x + 1, x^2) => x + 1
+###
+
+
+
+Eval_filter = ->
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ filter()
+ p1 = cdr(p1)
+
+###
+ For example...
+
+ push(F)
+ push(X)
+ filter()
+ F = pop()
+###
+
+filter = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ filter_main()
+ restore()
+
+filter_main = ->
+ if (car(p1) == symbol(ADD))
+ filter_sum()
+ else if (istensor(p1))
+ filter_tensor()
+ else if (Find(p1, p2))
+ push_integer(0)
+ else
+ push(p1)
+
+filter_sum = ->
+ push_integer(0)
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ filter()
+ add()
+ p1 = cdr(p1)
+
+filter_tensor = ->
+ i = 0
+ n = 0
+ n = p1.tensor.nelem
+ p3 = alloc_tensor(n)
+ p3.tensor.ndim = p1.tensor.ndim
+ for i in [0...p1.tensor.ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+ for i in [0...n]
+ push(p1.tensor.elem[i])
+ push(p2)
+ filter()
+ p3.tensor.elem[i] = pop()
+ push(p3)
diff --git a/node_modules/algebrite/sources/float.coffee b/node_modules/algebrite/sources/float.coffee
new file mode 100644
index 0000000..9838e52
--- /dev/null
+++ b/node_modules/algebrite/sources/float.coffee
@@ -0,0 +1,77 @@
+
+
+Eval_float = ->
+ evaluatingAsFloats++
+ push(cadr(p1))
+ Eval()
+ yyfloat()
+ Eval(); # normalize
+ evaluatingAsFloats--
+
+checkFloatHasWorkedOutCompletely = (nodeToCheck) ->
+ numberOfPowers = countOccurrencesOfSymbol(symbol(POWER),nodeToCheck)
+ numberOfPIs = countOccurrencesOfSymbol(symbol(PI),nodeToCheck)
+ numberOfEs = countOccurrencesOfSymbol(symbol(E),nodeToCheck)
+ numberOfMults = countOccurrencesOfSymbol(symbol(MULTIPLY),nodeToCheck)
+ numberOfSums = countOccurrencesOfSymbol(symbol(ADD),nodeToCheck)
+ if DEBUG
+ console.log " ... numberOfPowers: " + numberOfPowers
+ console.log " ... numberOfPIs: " + numberOfPIs
+ console.log " ... numberOfEs: " + numberOfEs
+ console.log " ... numberOfMults: " + numberOfMults
+ console.log " ... numberOfSums: " + numberOfSums
+ if numberOfPowers > 1 or numberOfPIs > 0 or numberOfEs > 0 or numberOfMults > 1 or numberOfSums > 1
+ stop("float: some unevalued parts in " + nodeToCheck)
+
+zzfloat = ->
+ save()
+ evaluatingAsFloats++
+ #p1 = pop()
+ #push(cadr(p1))
+ #push(p1)
+ Eval()
+ yyfloat()
+ Eval(); # normalize
+ evaluatingAsFloats--
+ restore()
+ # zzfloat doesn't necessarily result in a double
+ # , for example if there are variables. But
+ # in many of the tests there should be indeed
+ # a float, this line comes handy to highlight
+ # when that doesn't happen for those tests.
+ #checkFloatHasWorkedOutCompletely(stack[tos-1])
+
+yyfloat = ->
+ i = 0
+ h = 0
+ evaluatingAsFloats++
+ save()
+ p1 = pop()
+ if (iscons(p1))
+ h = tos
+ while (iscons(p1))
+ push(car(p1))
+ yyfloat()
+ p1 = cdr(p1)
+ list(tos - h)
+ else if (p1.k == TENSOR)
+ push(p1)
+ copy_tensor()
+ p1 = pop()
+ for i in [0...p1.tensor.nelem]
+ push(p1.tensor.elem[i])
+ yyfloat()
+ p1.tensor.elem[i] = pop()
+ push(p1)
+ else if (p1.k == NUM)
+ push(p1)
+ bignum_float()
+ else if (p1 == symbol(PI))
+ push_double(Math.PI)
+ else if (p1 == symbol(E))
+ push_double(Math.E)
+ else
+ push(p1)
+ restore()
+ evaluatingAsFloats--
+
diff --git a/node_modules/algebrite/sources/floor.coffee b/node_modules/algebrite/sources/floor.coffee
new file mode 100644
index 0000000..5c2d6d9
--- /dev/null
+++ b/node_modules/algebrite/sources/floor.coffee
@@ -0,0 +1,43 @@
+
+
+Eval_floor = ->
+ push(cadr(p1))
+ Eval()
+ yfloor()
+
+yfloor = ->
+ save()
+ yyfloor()
+ restore()
+
+yyfloor = ->
+ d = 0.0
+
+ p1 = pop()
+
+ if (!isNumericAtom(p1))
+ push_symbol(FLOOR)
+ push(p1)
+ list(2)
+ return
+
+ if (isdouble(p1))
+ d = Math.floor(p1.d)
+ push_double(d)
+ return
+
+ if (isinteger(p1))
+ push(p1)
+ return
+
+ p3 = new U()
+ p3.k = NUM
+ p3.q.a = mdiv(p1.q.a, p1.q.b)
+ p3.q.b = mint(1)
+ push(p3)
+
+ if (isnegativenumber(p1))
+ push_integer(-1)
+ add()
+
+
diff --git a/node_modules/algebrite/sources/for.coffee b/node_modules/algebrite/sources/for.coffee
new file mode 100644
index 0000000..f660937
--- /dev/null
+++ b/node_modules/algebrite/sources/for.coffee
@@ -0,0 +1,66 @@
+# 'for' function
+
+###
+x=0
+y=2
+for(do(x=sqrt(2+x),y=2*y/x),k,1,9)
+float(y)
+
+X: k
+B: 1...9
+
+1st parameter is the body
+2nd parameter is the variable to loop with
+3rd and 4th are the limits
+
+
+###
+
+#define A p3
+#define B p4
+#define I p5
+#define X p6
+
+Eval_for = ->
+ i = 0
+ j = 0
+ k = 0
+
+ loopingVariable = caddr(p1)
+ if (!issymbol(loopingVariable))
+ stop("for: 2nd arg should be the variable to loop over")
+
+ push(cadddr(p1))
+ Eval()
+ j = pop_integer()
+ if (isNaN(j))
+ push p1
+ return
+
+ push(caddddr(p1))
+ Eval()
+ k = pop_integer()
+ if (isNaN(k))
+ push p1
+ return
+
+
+ # remember contents of the index
+ # variable so we can put it back after the loop
+ p4 = get_binding(loopingVariable)
+
+ for i in [j..k]
+ push_integer(i)
+ p5 = pop()
+ set_binding(loopingVariable, p5)
+ push(cadr(p1))
+ Eval()
+ pop()
+
+ # put back the index variable to original content
+ set_binding(loopingVariable, p4)
+
+ # return value
+
+ push_symbol(NIL)
+
diff --git a/node_modules/algebrite/sources/gamma.coffee b/node_modules/algebrite/sources/gamma.coffee
new file mode 100644
index 0000000..9c2616b
--- /dev/null
+++ b/node_modules/algebrite/sources/gamma.coffee
@@ -0,0 +1,107 @@
+#-----------------------------------------------------------------------------
+#
+# Author : philippe.billet@noos.fr
+#
+# Gamma function gamma(x)
+#
+#-----------------------------------------------------------------------------
+
+
+
+
+Eval_gamma = ->
+ push(cadr(p1))
+ Eval()
+ gamma()
+
+gamma = ->
+ save()
+ gammaf()
+ restore()
+
+gammaf = ->
+ # double d
+
+ p1 = pop()
+
+ if (isrational(p1) && MEQUAL(p1.q.a, 1) && MEQUAL(p1.q.b, 2))
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ push_rational(1,2)
+ power()
+ return
+
+ if (isrational(p1) && MEQUAL(p1.q.a, 3) && MEQUAL(p1.q.b, 2))
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ push_rational(1,2)
+ power()
+ push_rational(1,2)
+ multiply()
+ return
+
+ # if (p1->k == DOUBLE) {
+ # d = exp(lgamma(p1.d))
+ # push_double(d)
+ # return
+ # }
+
+ if (isnegativeterm(p1))
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ push_integer(-1)
+ multiply()
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ push(p1)
+ multiply()
+ sine()
+ push(p1)
+ multiply()
+ push(p1)
+ negate()
+ gamma()
+ multiply()
+ divide()
+ return
+
+ if (car(p1) == symbol(ADD))
+ gamma_of_sum()
+ return
+
+
+ push_symbol(GAMMA)
+ push(p1)
+ list(2)
+ return
+
+gamma_of_sum = ->
+ p3 = cdr(p1)
+ if (isrational(car(p3)) && MEQUAL(car(p3).q.a, 1) && MEQUAL(car(p3).q.b, 1))
+ push(cadr(p3))
+ push(cadr(p3))
+ gamma()
+ multiply()
+ else
+ if (isrational(car(p3)) && MEQUAL(car(p3).q.a, -1) && MEQUAL(car(p3).q.b, 1))
+ push(cadr(p3))
+ gamma()
+ push(cadr(p3))
+ push_integer(-1)
+ add()
+ divide()
+ else
+ push_symbol(GAMMA)
+ push(p1)
+ list(2)
+ return
+
+
diff --git a/node_modules/algebrite/sources/gcd.coffee b/node_modules/algebrite/sources/gcd.coffee
new file mode 100644
index 0000000..9da4f16
--- /dev/null
+++ b/node_modules/algebrite/sources/gcd.coffee
@@ -0,0 +1,306 @@
+# Greatest common denominator
+# can also be run on polynomials, however
+# it works only on the integers and it works
+# by factoring the polynomials (not Euclidean algorithm)
+
+Eval_gcd = ->
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ gcd()
+ p1 = cdr(p1)
+
+gcd = ->
+ prev_expanding = expanding
+ save()
+ gcd_main()
+ restore()
+ expanding = prev_expanding
+
+gcd_main = ->
+ expanding = 1
+
+ p2 = pop()
+ p1 = pop()
+
+ if DEBUG then console.log "gcd_main: p1: " + p1 + " p2: " + p2
+
+ if (equal(p1, p2))
+ push(p1)
+ return
+
+ if (isrational(p1) && isrational(p2))
+ push(p1)
+ push(p2)
+ gcd_numbers()
+ return
+
+
+ if (polyVar = areunivarpolysfactoredorexpandedform(p1, p2))
+ gcd_polys(polyVar)
+ return
+
+
+ if (car(p1) == symbol(ADD) && car(p2) == symbol(ADD))
+ gcd_sum_sum()
+ return
+
+ if (car(p1) == symbol(ADD))
+ gcd_sum(p1)
+ p1 = pop()
+
+ if (car(p2) == symbol(ADD))
+ gcd_sum(p2)
+ p2 = pop()
+
+ if (car(p1) == symbol(MULTIPLY))
+ gcd_sum_product()
+ return
+
+ if (car(p2) == symbol(MULTIPLY))
+ gcd_product_sum()
+ return
+
+ if (car(p1) == symbol(MULTIPLY) && car(p2) == symbol(MULTIPLY))
+ gcd_product_product()
+ return
+
+ gcd_powers_with_same_base()
+
+
+areunivarpolysfactoredorexpandedform = (p1, p2) ->
+ if DEBUG then console.log "areunivarpolysfactoredorexpandedform: p1: " + p1 + " p2: " + p2
+ if polyVar = isunivarpolyfactoredorexpandedform(p1)
+ if isunivarpolyfactoredorexpandedform(p2,polyVar)
+ return polyVar
+ return false
+
+gcd_polys = (polyVar) ->
+ if DEBUG then console.log "gcd_polys: p1: " + p1 + " polyVar: " + polyVar
+ # gcd of factors
+ push(p1)
+ push polyVar
+ factorpoly()
+ p1 = pop()
+ push(p2)
+ push polyVar
+ factorpoly()
+ p2 = pop()
+ if DEBUG then console.log "GCD: factored polys:"
+ if DEBUG then console.log " p1:" + p1.toString()
+ if DEBUG then console.log " p2:" + p2.toString()
+
+ # In case one of two polynomials can be factored,
+ # (and only in that case), then
+ # we'll need to run gcd_factors on the two polynomials.
+ # (In case neither of them can be factored there is no gcd).
+ # However, gcd_factors expects two _products_ , and
+ # in case _one_ of the polynomials can't be factored it will look
+ # like a sum instead of a product.
+ # So, we'll have to make that sum to look like a factor:
+ # let's just turn it into a product with 1.
+
+ # in case one of the two polys has been factored...
+ if car(p1) == symbol(MULTIPLY) or car(p2) == symbol(MULTIPLY)
+
+ # then make sure that if one of them is a single
+ # factor, we take the sum and wrap it into a
+ # multiplication by 1
+
+ if car(p1) != symbol(MULTIPLY)
+ push_symbol(MULTIPLY);
+ push(p1);
+ push(one);
+ list(3);
+ p1 = pop()
+
+ if car(p2) != symbol(MULTIPLY)
+ push_symbol(MULTIPLY);
+ push(p2);
+ push(one);
+ list(3);
+ p2 = pop()
+
+ if (car(p1) == symbol(MULTIPLY) && car(p2) == symbol(MULTIPLY))
+ gcd_product_product()
+ return
+
+ gcd_powers_with_same_base()
+
+ return true
+
+
+gcd_product_product = ->
+ push(one)
+ p3 = cdr(p1)
+ while (iscons(p3))
+ p4 = cdr(p2)
+ while (iscons(p4))
+ push(car(p3))
+ push(car(p4))
+ gcd()
+ multiply()
+ p4 = cdr(p4)
+ p3 = cdr(p3)
+
+
+gcd_powers_with_same_base = ->
+
+ if (car(p1) == symbol(POWER))
+ p3 = caddr(p1) # exponent
+ p1 = cadr(p1) # base
+ else
+ p3 = one
+
+ if (car(p2) == symbol(POWER))
+ p4 = caddr(p2) # exponent
+ p2 = cadr(p2) # base
+ else
+ p4 = one
+
+ if (!equal(p1, p2))
+ push(one)
+ return
+
+ # are both exponents numerical?
+
+ if (isNumericAtom(p3) && isNumericAtom(p4))
+ push(p1)
+ if (lessp(p3, p4))
+ push(p3)
+ else
+ push(p4)
+ power()
+ return
+
+ # are the exponents multiples of eah other?
+
+ push(p3)
+ push(p4)
+ divide()
+
+ p5 = pop()
+
+ if (isNumericAtom(p5))
+
+ push(p1)
+
+ # choose the smallest exponent
+
+ if (car(p3) == symbol(MULTIPLY) && isNumericAtom(cadr(p3)))
+ p5 = cadr(p3)
+ else
+ p5 = one
+
+ if (car(p4) == symbol(MULTIPLY) && isNumericAtom(cadr(p4)))
+ p6 = cadr(p4)
+ else
+ p6 = one
+
+ if (lessp(p5, p6))
+ push(p3)
+ else
+ push(p4)
+
+ power()
+ return
+
+ push(p3)
+ push(p4)
+ subtract()
+
+ p5 = pop()
+
+ if (!isNumericAtom(p5))
+ push(one)
+ return
+
+ # can't be equal because of test near beginning
+
+ push(p1)
+
+ if (isnegativenumber(p5))
+ push(p3)
+ else
+ push(p4)
+
+ power()
+
+# in this case gcd is used as a composite function, i.e. gcd(gcd(gcd...
+
+gcd_sum_sum = ->
+ if (length(p1) != length(p2))
+ push(one)
+ return
+
+ p3 = cdr(p1)
+ push(car(p3))
+ p3 = cdr(p3)
+ while (iscons(p3))
+ push(car(p3))
+ gcd()
+ p3 = cdr(p3)
+ p3 = pop()
+
+ p4 = cdr(p2)
+ push(car(p4))
+ p4 = cdr(p4)
+ while (iscons(p4))
+ push(car(p4))
+ gcd()
+ p4 = cdr(p4)
+ p4 = pop()
+
+ push(p1)
+ push(p3)
+ divide()
+ p5 = pop()
+
+ push(p2)
+ push(p4)
+ divide()
+ p6 = pop()
+
+ if (equal(p5, p6))
+ push(p5)
+ push(p3)
+ push(p4)
+ gcd()
+ multiply()
+ else
+ push(one)
+
+gcd_sum = (p) ->
+ p = cdr(p)
+ push(car(p))
+ p = cdr(p)
+ while (iscons(p))
+ push(car(p))
+ gcd()
+ p = cdr(p)
+
+gcd_sum_product = ->
+ push(one)
+ p3 = cdr(p1)
+ while (iscons(p3))
+ push(car(p3))
+ push(p2)
+ gcd()
+ multiply()
+ p3 = cdr(p3)
+
+gcd_product_sum = ->
+ push(one)
+ p4 = cdr(p2)
+ while (iscons(p4))
+ push(p1)
+ push(car(p4))
+ gcd()
+ multiply()
+ p4 = cdr(p4)
+
+
diff --git a/node_modules/algebrite/sources/guess.coffee b/node_modules/algebrite/sources/guess.coffee
new file mode 100644
index 0000000..52c9d62
--- /dev/null
+++ b/node_modules/algebrite/sources/guess.coffee
@@ -0,0 +1,19 @@
+# Guess which symbol to use for derivative, integral, etc.
+
+
+
+guess = ->
+ p = pop()
+ push(p)
+ if (Find(p, symbol(SYMBOL_X)))
+ push_symbol(SYMBOL_X)
+ else if (Find(p, symbol(SYMBOL_Y)))
+ push_symbol(SYMBOL_Y)
+ else if (Find(p, symbol(SYMBOL_Z)))
+ push_symbol(SYMBOL_Z)
+ else if (Find(p, symbol(SYMBOL_T)))
+ push_symbol(SYMBOL_T)
+ else if (Find(p, symbol(SYMBOL_S)))
+ push_symbol(SYMBOL_S)
+ else
+ push_symbol(SYMBOL_X)
diff --git a/node_modules/algebrite/sources/hermite.coffee b/node_modules/algebrite/sources/hermite.coffee
new file mode 100644
index 0000000..492b532
--- /dev/null
+++ b/node_modules/algebrite/sources/hermite.coffee
@@ -0,0 +1,83 @@
+#-----------------------------------------------------------------------------
+#
+# Hermite polynomial
+#
+# Input: tos-2 x (can be a symbol or expr)
+#
+# tos-1 n
+#
+# Output: Result on stack
+#
+#-----------------------------------------------------------------------------
+
+
+
+hermite = ->
+ save()
+ yyhermite()
+ restore()
+
+# uses the recurrence relation H(x,n+1)=2*x*H(x,n)-2*n*H(x,n-1)
+
+#define X p1
+#define N p2
+#define Y p3
+#define Y1 p4
+#define Y0 p5
+
+yyhermite = ->
+
+ n = 0
+
+ p2 = pop()
+ p1 = pop()
+
+ push(p2)
+ n = pop_integer()
+
+ if (n < 0 || isNaN(n))
+ push_symbol(HERMITE)
+ push(p1)
+ push(p2)
+ list(3)
+ return
+
+ if (issymbol(p1))
+ yyhermite2(n)
+ else
+ p3 = p1; # do this when X is an expr
+ p1 = symbol(SECRETX)
+ yyhermite2(n)
+ p1 = p3
+ push(symbol(SECRETX))
+ push(p1)
+ subst()
+ Eval()
+
+yyhermite2 = (n) ->
+ i = 0
+
+ push_integer(1)
+ push_integer(0)
+
+ p4 = pop()
+
+ for i in [0...n]
+
+ p5 = p4
+
+ p4 = pop()
+
+ push(p1)
+ push(p4)
+ multiply()
+
+ push_integer(i)
+ push(p5)
+ multiply()
+
+ subtract()
+
+ push_integer(2)
+ multiply()
+
diff --git a/node_modules/algebrite/sources/hilbert.coffee b/node_modules/algebrite/sources/hilbert.coffee
new file mode 100644
index 0000000..79dc7ad
--- /dev/null
+++ b/node_modules/algebrite/sources/hilbert.coffee
@@ -0,0 +1,45 @@
+#-----------------------------------------------------------------------------
+#
+# Create a Hilbert matrix
+#
+# Input: Dimension on stack
+#
+# Output: Hilbert matrix on stack
+#
+# Example:
+#
+# > hilbert(5)
+# ((1,1/2,1/3,1/4),(1/2,1/3,1/4,1/5),(1/3,1/4,1/5,1/6),(1/4,1/5,1/6,1/7))
+#
+#-----------------------------------------------------------------------------
+
+
+
+#define A p1
+#define N p2
+
+#define AELEM(i, j) A->u.tensor->elem[i * n + j]
+
+hilbert = ->
+ i = 0
+ j = 0
+ n = 0
+ save()
+ p2 = pop()
+ push(p2)
+ n = pop_integer()
+ if (n < 2)
+ push_symbol(HILBERT)
+ push(p2)
+ list(2)
+ restore()
+ return
+ push_zero_matrix(n, n)
+ p1 = pop()
+ for i in [0...n]
+ for j in [0...n]
+ push_integer(i + j + 1)
+ inverse()
+ p1.tensor.elem[i * n + j] = pop()
+ push(p1)
+ restore()
diff --git a/node_modules/algebrite/sources/imag.coffee b/node_modules/algebrite/sources/imag.coffee
new file mode 100644
index 0000000..3a668a2
--- /dev/null
+++ b/node_modules/algebrite/sources/imag.coffee
@@ -0,0 +1,39 @@
+###
+ Returns the coefficient of the imaginary part of complex z
+
+ z imag(z)
+ - -------
+
+ a + i b b
+
+ exp(i a) sin(a)
+###
+
+DEBUG_IMAG = false
+
+Eval_imag = ->
+ push(cadr(p1))
+ Eval()
+ imag()
+
+imag = ->
+ save()
+ rect()
+ p1 = pop()
+
+ if DEBUG_IMAG then console.log "IMAGE of " + p1
+
+ push(p1)
+ push(p1)
+ conjugate()
+ if DEBUG_IMAG then console.log " image: conjugate result: " + stack[tos-1]
+
+ subtract()
+ push_integer(2)
+ divide()
+ if DEBUG_IMAG then console.log " image: 1st divide result: " + stack[tos-1]
+ push(imaginaryunit)
+ divide()
+ if DEBUG_IMAG then console.log " image: 2nd divide result: " + stack[tos-1]
+ restore()
+
diff --git a/node_modules/algebrite/sources/index.coffee b/node_modules/algebrite/sources/index.coffee
new file mode 100644
index 0000000..25185b2
--- /dev/null
+++ b/node_modules/algebrite/sources/index.coffee
@@ -0,0 +1,186 @@
+
+
+# n is the total number of things on the stack. The first thing on the stack
+# is the object to be indexed, followed by the indices themselves.
+
+# called by Eval_index
+index_function = (n) ->
+ i = 0
+ k = 0
+ m = 0
+ ndim = 0
+ nelem = 0
+ t = 0
+
+ save()
+ s = tos - n
+ p1 = stack[s]
+
+
+ ndim = p1.tensor.ndim
+
+ m = n - 1
+
+ if (m > ndim)
+ stop("too many indices for tensor")
+
+ k = 0
+
+ for i in [0...m]
+ push(stack[s + i + 1])
+ t = pop_integer()
+ if (t < 1 || t > p1.tensor.dim[i])
+ stop("index out of range")
+ k = k * p1.tensor.dim[i] + t - 1
+
+ if (ndim == m)
+ moveTos tos - n
+ push(p1.tensor.elem[k])
+ restore()
+ return
+
+ for i in [m...ndim]
+ k = k * p1.tensor.dim[i] + 0
+
+ nelem = 1
+
+ for i in [m...ndim]
+ nelem *= p1.tensor.dim[i]
+
+ p2 = alloc_tensor(nelem)
+
+ p2.tensor.ndim = ndim - m
+
+ for i in [m...ndim]
+ p2.tensor.dim[i - m] = p1.tensor.dim[i]
+
+ for i in [0...nelem]
+ p2.tensor.elem[i] = p1.tensor.elem[k + i]
+
+ check_tensor_dimensions p1
+ check_tensor_dimensions p2
+
+ moveTos tos - n
+ push(p2)
+ restore()
+
+#-----------------------------------------------------------------------------
+#
+# Input: n Number of args on stack
+#
+# tos-n Right-hand value
+#
+# tos-n+1 Left-hand value
+#
+# tos-n+2 First index
+#
+# .
+# .
+# .
+#
+# tos-1 Last index
+#
+# Output: Result on stack
+#
+#-----------------------------------------------------------------------------
+
+#define LVALUE p1
+#define RVALUE p2
+#define TMP p3
+
+set_component = (n) ->
+ i = 0
+ k = 0
+ m = 0
+ ndim = 0
+ t = 0
+
+ save()
+
+ if (n < 3)
+ stop("error in indexed assign")
+
+ s = tos - n
+
+ p2 = stack[s]; # p2 is RVALUE
+
+ p1 = stack[s+1]; # p1 is LVALUE
+
+ if (!istensor(p1)) # p1 is LVALUE
+ stop("error in indexed assign: assigning to something that is not a tensor")
+
+ ndim = p1.tensor.ndim; # p1 is LVALUE
+
+ m = n - 2
+
+ if (m > ndim)
+ stop("error in indexed assign")
+
+ k = 0
+
+ for i in [0...m]
+ push(stack[ s + i + 2])
+ t = pop_integer()
+ if (t < 1 || t > p1.tensor.dim[i]) # p1 is LVALUE
+ stop("error in indexed assign\n")
+ k = k * p1.tensor.dim[i] + t - 1
+
+ for i in [m...ndim]
+ k = k * p1.tensor.dim[i] + 0
+
+ # copy
+
+ p3 = alloc_tensor(p1.tensor.nelem); # p1 is LVALUE # p3 is TMP
+
+ p3.tensor.ndim = p1.tensor.ndim; # p1 is LVALUE # p3 is TMP
+
+ for i in [0...p1.tensor.ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]; # p1 is LVALUE # p3 is TMP
+
+ for i in [0...p1.tensor.nelem]
+ p3.tensor.elem[i] = p1.tensor.elem[i]; # p1 is LVALUE # p3 is TMP
+
+ check_tensor_dimensions p1
+ check_tensor_dimensions p3
+
+ p1 = p3; # p1 is LVALUE # p3 is TMP
+
+ if (ndim == m)
+ if (istensor(p2)) # p2 is RVALUE
+ stop("error in indexed assign")
+ p1.tensor.elem[k] = p2; # p1 is LVALUE # p2 is RVALUE
+
+ check_tensor_dimensions p1
+
+ moveTos tos - n
+ push(p1); # p1 is LVALUE
+ restore()
+ return
+
+
+ # see if the rvalue matches
+
+ if (!istensor(p2)) # p2 is RVALUE
+ stop("error in indexed assign")
+
+ if (ndim - m != p2.tensor.ndim) # p2 is RVALUE
+ stop("error in indexed assign")
+
+ for i in [0...p2.tensor.ndim] # p2 is RVALUE
+ if (p1.tensor.dim[m + i] != p2.tensor.dim[i]) # p1 is LVALUE # p2 is RVALUE
+ stop("error in indexed assign")
+
+ # copy rvalue
+
+ for i in [0...p2.tensor.nelem] # p2 is RVALUE
+ p1.tensor.elem[k + i] = p2.tensor.elem[i]; # p1 is LVALUE # p2 is RVALUE
+
+ check_tensor_dimensions p1
+ check_tensor_dimensions p2
+
+ moveTos tos - n
+
+ push(p1); # p1 is LVALUE
+
+ restore()
+
diff --git a/node_modules/algebrite/sources/inner.coffee b/node_modules/algebrite/sources/inner.coffee
new file mode 100644
index 0000000..9a66027
--- /dev/null
+++ b/node_modules/algebrite/sources/inner.coffee
@@ -0,0 +1,473 @@
+### dot =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+a,b,...
+
+General description
+-------------------
+
+The inner (or dot) operator gives products of vectors,
+matrices, and tensors.
+
+Note that for Algebrite, the elements of a vector/matrix
+can only be scalars. This allows for example to flesh out
+matrix multiplication using the usual multiplication.
+So for example block-representations are not allowed.
+
+There is an aweful lot of confusion between sw packages on
+what dot and inner do.
+
+First off, the "dot" operator is different from the
+mathematical notion of dot product, which can be
+slightly confusing.
+
+The mathematical notion of dot product is here:
+ http://mathworld.wolfram.com/DotProduct.html
+
+However, "dot" does that and a bunch of other things,
+i.e. in Algebrite
+dot/inner does what the dot of Mathematica does, i.e.:
+
+scalar product of vectors:
+
+ inner((a, b, c), (x, y, z))
+ > a x + b y + c z
+
+products of matrices and vectors:
+
+ inner(((a, b), (c,d)), (x, y))
+ > (a x + b y,c x + d y)
+
+ inner((x, y), ((a, b), (c,d)))
+ > (a x + c y,b x + d y)
+
+ inner((x, y), ((a, b), (c,d)), (r, s))
+ > a r x + b s x + c r y + d s y
+
+matrix product:
+
+ inner(((a,b),(c,d)),((r,s),(t,u)))
+ > ((a r + b t,a s + b u),(c r + d t,c s + d u))
+
+the "dot/inner" operator is associative and
+distributive but not commutative.
+
+In Mathematica, Inner is a generalisation of Dot where
+the user can specify the multiplication and the addition
+operators.
+But here in Algebrite they do the same thing.
+
+ https://reference.wolfram.com/language/ref/Dot.html
+ https://reference.wolfram.com/language/ref/Inner.html
+
+ http://uk.mathworks.com/help/matlab/ref/dot.html
+ http://uk.mathworks.com/help/matlab/ref/mtimes.html
+
+###
+
+
+
+Eval_inner = ->
+
+
+ # if there are more than two arguments then
+ # reduce it to a more standard version
+ # of two arguments, which means we need to
+ # transform the arguments into a tree of
+ # inner products e.g.
+ # inner(a,b,c) becomes inner(a,inner(b,c))
+ # this is so we can get to a standard binary-tree
+ # version that is simpler to manipulate.
+ theArguments = []
+ theArguments.push car(cdr(p1))
+ secondArgument = car(cdr(cdr(p1)))
+ if secondArgument == symbol(NIL)
+ stop("pattern needs at least a template and a transformed version")
+
+ moretheArguments = cdr(cdr(p1))
+ while moretheArguments != symbol(NIL)
+ theArguments.push car(moretheArguments)
+ moretheArguments = cdr(moretheArguments)
+
+ # make it so e.g. inner(a,b,c) becomes inner(a,inner(b,c))
+ if theArguments.length > 2
+ push_symbol(INNER)
+ push theArguments[theArguments.length-2]
+ push theArguments[theArguments.length-1]
+ list(3)
+ for i in [2...theArguments.length]
+ push_symbol(INNER)
+ swap()
+ push theArguments[theArguments.length-i-1]
+ swap()
+ list(3)
+ p1 = pop()
+ Eval_inner()
+ return
+
+
+
+
+ # TODO we have to take a look at the whole
+ # sequence of operands and make simplifications
+ # on that...
+ operands = []
+ get_innerprod_factors(p1, operands)
+
+ #console.log "printing operands --------"
+ #for i in [0...operands.length]
+ # console.log "operand " + i + " : " + operands[i]
+
+ refinedOperands = []
+ # removing all identity matrices
+ for i in [0...operands.length]
+ if operands[i] == symbol(SYMBOL_IDENTITY_MATRIX)
+ continue
+ else refinedOperands.push operands[i]
+ operands = refinedOperands
+
+ refinedOperands = []
+ if operands.length > 1
+ # removing all consecutive pairs of inverses
+ # so we can answer that inv(a)·a results in the
+ # identity matrix. We want to catch symbolic inverses
+ # not numeric inverses, those will just take care
+ # of themselves when multiplied
+ shift = 0
+ for i in [0...operands.length]
+ #console.log "comparing if " + operands[i+shift] + " and " + operands[i+shift+1] + " are inverses of each other"
+ if (i+shift+1) <= (operands.length - 1)
+ #console.log "isNumericAtomOrTensor " + operands[i+shift] + " : " + isNumericAtomOrTensor(operands[i+shift])
+ #console.log "isNumericAtomOrTensor " + operands[i+shift+1] + " : " + isNumericAtomOrTensor(operands[i+shift+1])
+ if !(isNumericAtomOrTensor(operands[i+shift]) or isNumericAtomOrTensor(operands[i+shift+1]))
+ push operands[i+shift]
+ Eval()
+ inv()
+ push operands[i+shift+1]
+ Eval()
+ subtract()
+ difference = pop()
+ #console.log "result: " + difference
+ if (isZeroAtomOrTensor(difference))
+ shift+=1
+ else
+ refinedOperands.push operands[i+shift]
+ else
+ refinedOperands.push operands[i+shift]
+
+ else
+ break
+
+ #console.log "i: " + i + " shift: " + shift + " operands.length: " + operands.length
+
+ if i+shift == operands.length - 2
+ #console.log "adding last operand 2 "
+ refinedOperands.push operands[operands.length-1]
+ if i+shift >= operands.length - 1
+ break
+ operands = refinedOperands
+
+ #console.log "refined operands --------"
+ #for i in [0...refinedOperands.length]
+ # console.log "refined operand " + i + " : " + refinedOperands[i]
+
+
+ #console.log "stack[tos-1]: " + stack[tos-1]
+
+ # now rebuild the arguments, just using the
+ # refined operands
+ push symbol(INNER)
+ #console.log "rebuilding the argument ----"
+
+ if operands.length > 0
+ for i in [0...operands.length]
+ #console.log "pushing " + operands[i]
+ push operands[i]
+ else
+ pop()
+ push symbol(SYMBOL_IDENTITY_MATRIX)
+ return
+ #console.log "list(operands.length): " + (operands.length+1)
+ list(operands.length + 1)
+ p1 = pop()
+
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ inner()
+ p1 = cdr(p1)
+
+# inner definition
+inner = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+
+ # more in general, when a and b are scalars,
+ # inner(a*M1, b*M2) is equal to
+ # a*b*inner(M1,M2), but of course we can only
+ # "bring out" in a and b the scalars, because
+ # it's the only commutative part.
+ # that's going to be trickier to do in general
+ # but let's start with just the signs.
+ if isnegativeterm(p2) and isnegativeterm(p1)
+ push p2
+ negate()
+ p2 = pop()
+ push p1
+ negate()
+ p1 = pop()
+
+ # since inner is associative,
+ # put it in a canonical form i.e.
+ # inner(inner(a,b),c) ->
+ # inner(a,inner(b,c))
+ # so that we can recognise when they
+ # are equal.
+ if isinnerordot(p1)
+ arg1 = car(cdr(p1)) #a
+ arg2 = car(cdr(cdr(p1))) #b
+ arg3 = p2
+ p1 = arg1
+ push arg2
+ push arg3
+ inner()
+ p2 = pop()
+
+ # Check if one of the operands is the identity matrix
+ # we could maybe use Eval_testeq here but
+ # this seems to suffice?
+ if p1 == symbol(SYMBOL_IDENTITY_MATRIX)
+ push p2
+ restore()
+ return
+ else if p2 == symbol(SYMBOL_IDENTITY_MATRIX)
+ push p1
+ restore()
+ return
+
+
+ if (istensor(p1) && istensor(p2))
+ inner_f()
+ else
+
+ # simple check if the two consecutive elements are one the
+ # (symbolic) inv of the other. If they are, the answer is
+ # the identity matrix
+ if !(isNumericAtomOrTensor(p1) or isNumericAtomOrTensor(p2))
+ push p1
+ push p2
+ inv()
+ subtract()
+ subtractionResult = pop()
+ if (isZeroAtomOrTensor(subtractionResult))
+ push_symbol(SYMBOL_IDENTITY_MATRIX)
+ restore()
+ return
+
+
+ # if either operand is a sum then distribute
+ # (if we are in expanding mode)
+ if (expanding && isadd(p1))
+ p1 = cdr(p1)
+ push(zero)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ inner()
+ add()
+ p1 = cdr(p1)
+ restore()
+ return
+
+ if (expanding && isadd(p2))
+ p2 = cdr(p2)
+ push(zero)
+ while (iscons(p2))
+ push(p1)
+ push(car(p2))
+ inner()
+ add()
+ p2 = cdr(p2)
+ restore()
+ return
+
+ push(p1)
+ push(p2)
+
+
+ # there are 8 remaining cases here, since each of the
+ # two arguments can only be a scalar/tensor/unknown
+ # and the tensor - tensor case was caught
+ # upper in the code
+ if (istensor(p1) and isNumericAtom(p2))
+ # one case covered by this branch:
+ # tensor - scalar
+ tensor_times_scalar()
+ else if (isNumericAtom(p1) and istensor(p2))
+ # one case covered by this branch:
+ # scalar - tensor
+ scalar_times_tensor()
+ else
+ if (isNumericAtom(p1) or isNumericAtom(p2))
+ # three cases covered by this branch:
+ # unknown - scalar
+ # scalar - unknown
+ # scalar - scalar
+ # in these cases a normal multiplication
+ # will be OK
+ multiply()
+ else
+ # three cases covered by this branch:
+ # unknown - unknown
+ # unknown - tensor
+ # tensor - unknown
+ # in this case we can't use normal
+ # multiplication.
+ pop()
+ pop()
+ push_symbol(INNER)
+ push(p1)
+ push(p2)
+ list(3)
+ restore()
+ return
+
+
+ restore()
+
+# inner product of tensors p1 and p2
+inner_f = ->
+
+ i = 0
+ n = p1.tensor.dim[p1.tensor.ndim - 1]
+
+ if (n != p2.tensor.dim[0])
+ debugger
+ stop("inner: tensor dimension check")
+
+ ndim = p1.tensor.ndim + p2.tensor.ndim - 2
+
+ if (ndim > MAXDIM)
+ stop("inner: rank of result exceeds maximum")
+
+ a = p1.tensor.elem
+ b = p2.tensor.elem
+
+ #---------------------------------------------------------------------
+ #
+ # ak is the number of rows in tensor A
+ #
+ # bk is the number of columns in tensor B
+ #
+ # Example:
+ #
+ # A[3][3][4] B[4][4][3]
+ #
+ # 3 3 ak = 3 * 3 = 9
+ #
+ # 4 3 bk = 4 * 3 = 12
+ #
+ #---------------------------------------------------------------------
+
+ ak = 1
+ for i in [0...(p1.tensor.ndim - 1)]
+ ak *= p1.tensor.dim[i]
+
+ bk = 1
+ for i in [1...p2.tensor.ndim]
+ bk *= p2.tensor.dim[i]
+
+ p3 = alloc_tensor(ak * bk)
+
+ c = p3.tensor.elem
+
+ # new method copied from ginac http://www.ginac.de/
+ for i in [0...ak]
+ for j in [0...n]
+ if (isZeroAtomOrTensor(a[i * n + j]))
+ continue
+ for k in [0...bk]
+ push(a[i * n + j])
+ push(b[j * bk + k])
+ multiply()
+ push(c[i * bk + k])
+ add()
+ c[i * bk + k] = pop()
+
+ #---------------------------------------------------------------------
+ #
+ # Note on understanding "k * bk + j"
+ #
+ # k * bk because each element of a column is bk locations apart
+ #
+ # + j because the beginnings of all columns are in the first bk
+ # locations
+ #
+ # Example: n = 2, bk = 6
+ #
+ # b111 <- 1st element of 1st column
+ # b112 <- 1st element of 2nd column
+ # b113 <- 1st element of 3rd column
+ # b121 <- 1st element of 4th column
+ # b122 <- 1st element of 5th column
+ # b123 <- 1st element of 6th column
+ #
+ # b211 <- 2nd element of 1st column
+ # b212 <- 2nd element of 2nd column
+ # b213 <- 2nd element of 3rd column
+ # b221 <- 2nd element of 4th column
+ # b222 <- 2nd element of 5th column
+ # b223 <- 2nd element of 6th column
+ #
+ #---------------------------------------------------------------------
+
+ if (ndim == 0)
+ push(p3.tensor.elem[0])
+ else
+ p3.tensor.ndim = ndim
+ j = 0
+ for i in [0...(p1.tensor.ndim - 1)]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+ j = p1.tensor.ndim - 1
+ for i in [0...(p2.tensor.ndim - 1)]
+ p3.tensor.dim[j + i] = p2.tensor.dim[i + 1]
+ push(p3)
+
+# Algebrite.run('c·(b+a)ᵀ·inv((a+b)ᵀ)·d').toString();
+# Algebrite.run('c*(b+a)ᵀ·inv((a+b)ᵀ)·d').toString();
+# Algebrite.run('(c·(b+a)ᵀ)·(inv((a+b)ᵀ)·d)').toString();
+get_innerprod_factors = (tree, factors_accumulator) ->
+ # console.log "extracting inner prod. factors from " + tree
+
+ if !iscons(tree)
+ add_factor_to_accumulator(tree, factors_accumulator)
+ return
+
+ if cdr(tree) == symbol(NIL)
+ tree = get_innerprod_factors(car(tree), factors_accumulator)
+ return
+
+ if isinnerordot(tree)
+ # console.log "there is inner at top, recursing on the operands"
+ get_innerprod_factors(car(cdr(tree)),factors_accumulator)
+ get_innerprod_factors(cdr(cdr(tree)),factors_accumulator)
+ return
+
+ add_factor_to_accumulator(tree, factors_accumulator)
+
+add_factor_to_accumulator = (tree, factors_accumulator) ->
+ if tree != symbol(NIL)
+ # console.log ">> adding to factors_accumulator: " + tree
+ factors_accumulator.push(tree)
+
diff --git a/node_modules/algebrite/sources/integral.coffee b/node_modules/algebrite/sources/integral.coffee
new file mode 100644
index 0000000..366f340
--- /dev/null
+++ b/node_modules/algebrite/sources/integral.coffee
@@ -0,0 +1,1071 @@
+###
+ Table of integrals
+
+The symbol f is just a dummy symbol for creating a list f(A,B,C,C,...) where
+
+ A is the template expression
+
+ B is the result expression
+
+ C is an optional list of conditional expressions
+###
+
+itab = [
+ # 1
+ "f(a,a*x)",
+ # 9 (need a caveat for 7 so we can put 9 after 7)
+ "f(1/x,log(x))",
+ # 7
+ "f(x^a,x^(a+1)/(a+1))",
+ # five specialisations of case 7 for speed.
+ # Covers often-occurring exponents: each of
+ # these case ends up in a dedicated entry, so we
+ # only have to do one sure-shot match.
+ "f(x^(-2),-x^(-1))",
+ "f(x^(-1/2),2*x^(1/2))",
+ "f(x^(1/2),2/3*x^(3/2))",
+ "f(x,x^2/2)",
+ "f(x^2,x^3/3)",
+ # 12
+ "f(exp(a*x),1/a*exp(a*x))",
+ "f(exp(a*x+b),1/a*exp(a*x+b))",
+ "f(x*exp(a*x^2),exp(a*x^2)/(2*a))",
+ "f(x*exp(a*x^2+b),exp(a*x^2+b)/(2*a))",
+ # 14
+ "f(log(a*x),x*log(a*x)-x)",
+ # 15
+ "f(a^x,a^x/log(a),or(not(number(a)),a>0))",
+ # 16
+ "f(1/(a+x^2),1/sqrt(a)*arctan(x/sqrt(a)),or(not(number(a)),a>0))",
+ # 17
+ "f(1/(a-x^2),1/sqrt(a)*arctanh(x/sqrt(a)))",
+ # 19
+ "f(1/sqrt(a-x^2),arcsin(x/(sqrt(a))))",
+ # 20
+ "f(1/sqrt(a+x^2),log(x+sqrt(a+x^2)))",
+ # 27
+ "f(1/(a+b*x),1/b*log(a+b*x))",
+ # 28
+ "f(1/(a+b*x)^2,-1/(b*(a+b*x)))",
+ # 29
+ "f(1/(a+b*x)^3,-1/(2*b)*1/(a+b*x)^2)",
+ # 30
+ "f(x/(a+b*x),x/b-a*log(a+b*x)/b/b)",
+ # 31
+ "f(x/(a+b*x)^2,1/b^2*(log(a+b*x)+a/(a+b*x)))",
+ # 33
+ "f(x^2/(a+b*x),1/b^2*(1/2*(a+b*x)^2-2*a*(a+b*x)+a^2*log(a+b*x)))",
+ # 34
+ "f(x^2/(a+b*x)^2,1/b^3*(a+b*x-2*a*log(a+b*x)-a^2/(a+b*x)))",
+ # 35
+ "f(x^2/(a+b*x)^3,1/b^3*(log(a+b*x)+2*a/(a+b*x)-1/2*a^2/(a+b*x)^2))",
+ # 37
+ "f(1/x*1/(a+b*x),-1/a*log((a+b*x)/x))",
+ # 38
+ "f(1/x*1/(a+b*x)^2,1/a*1/(a+b*x)-1/a^2*log((a+b*x)/x))",
+ # 39
+ "f(1/x*1/(a+b*x)^3,1/a^3*(1/2*((2*a+b*x)/(a+b*x))^2+log(x/(a+b*x))))",
+ # 40
+ "f(1/x^2*1/(a+b*x),-1/(a*x)+b/a^2*log((a+b*x)/x))",
+ # 41
+ "f(1/x^3*1/(a+b*x),(2*b*x-a)/(2*a^2*x^2)+b^2/a^3*log(x/(a+b*x)))",
+ # 42
+ "f(1/x^2*1/(a+b*x)^2,-(a+2*b*x)/(a^2*x*(a+b*x))+2*b/a^3*log((a+b*x)/x))",
+ # 60
+ "f(1/(a+b*x^2),1/sqrt(a*b)*arctan(x*sqrt(a*b)/a),or(not(number(a*b)),a*b>0))",
+ # 61
+ "f(1/(a+b*x^2),1/(2*sqrt(-a*b))*log((a+x*sqrt(-a*b))/(a-x*sqrt(-a*b))),or(not(number(a*b)),a*b<0))",
+ # 62 is the same as 60
+ # 63
+ "f(x/(a+b*x^2),1/2*1/b*log(a+b*x^2))",
+ #64
+ "f(x^2/(a+b*x^2),x/b-a/b*integral(1/(a+b*x^2),x))",
+ #65
+ "f(1/(a+b*x^2)^2,x/(2*a*(a+b*x^2))+1/2*1/a*integral(1/(a+b*x^2),x))",
+ #66 is covered by 61
+ #70
+ "f(1/x*1/(a+b*x^2),1/2*1/a*log(x^2/(a+b*x^2)))",
+ #71
+ "f(1/x^2*1/(a+b*x^2),-1/(a*x)-b/a*integral(1/(a+b*x^2),x))",
+ #74
+ "f(1/(a+b*x^3),1/3*1/a*(a/b)^(1/3)*(1/2*log(((a/b)^(1/3)+x)^3/(a+b*x^3))+sqrt(3)*arctan((2*x-(a/b)^(1/3))*(a/b)^(-1/3)/sqrt(3))))",
+ #76
+ "f(x^2/(a+b*x^3),1/3*1/b*log(a+b*x^3))",
+ # float(defint(1/(2+3*X^4),X,0,pi)) gave wrong result.
+ # Also, the tests related to the indefinite integral
+ # fail since we rationalise expressions "better", so I'm thinking
+ # to take this out completely as it seemed to give the
+ # wrong results in the first place.
+ #77
+ #"f(1/(a+b*x^4),1/2*1/a*(a/b/4)^(1/4)*(1/2*log((x^2+2*(a/b/4)^(1/4)*x+2*(a/b/4)^(1/2))/(x^2-2*(a/b/4)^(1/4)*x+2*(a/b/4)^(1/2)))+arctan(2*(a/b/4)^(1/4)*x/(2*(a/b/4)^(1/2)-x^2))),or(not(number(a*b)),a*b>0))",
+ #78
+ #"f(1/(a+b*x^4),1/2*(-a/b)^(1/4)/a*(1/2*log((x+(-a/b)^(1/4))/(x-(-a/b)^(1/4)))+arctan(x*(-a/b)^(-1/4))),or(not(number(a*b)),a*b<0))",
+ #79
+ "f(x/(a+b*x^4),1/2*sqrt(b/a)/b*arctan(x^2*sqrt(b/a)),or(not(number(a*b)),a*b>0))",
+ #80
+ "f(x/(a+b*x^4),1/4*sqrt(-b/a)/b*log((x^2-sqrt(-a/b))/(x^2+sqrt(-a/b))),or(not(number(a*b)),a*b<0))",
+
+ # float(defint(X^2/(2+3*X^4),X,0,pi)) gave wrong result.
+ # Also, the tests related to the indefinite integral
+ # fail since we rationalise expressions "better", so I'm thinking
+ # to take this out completely as it seemed to give the
+ # wrong results in the first place.
+ #81
+ #"f(x^2/(a+b*x^4),1/4*1/b*(a/b/4)^(-1/4)*(1/2*log((x^2-2*(a/b/4)^(1/4)*x+2*sqrt(a/b/4))/(x^2+2*(a/b/4)^(1/4)*x+2*sqrt(a/b/4)))+arctan(2*(a/b/4)^(1/4)*x/(2*sqrt(a/b/4)-x^2))),or(not(number(a*b)),a*b>0))",
+ #82
+ #"f(x^2/(a+b*x^4),1/4*1/b*(-a/b)^(-1/4)*(log((x-(-a/b)^(1/4))/(x+(-a/b)^(1/4)))+2*arctan(x*(-a/b)^(-1/4))),or(not(number(a*b)),a*b<0))",
+ #83
+ "f(x^3/(a+b*x^4),1/4*1/b*log(a+b*x^4))",
+ #124
+ "f(sqrt(a+b*x),2/3*1/b*sqrt((a+b*x)^3))",
+ #125
+ "f(x*sqrt(a+b*x),-2*(2*a-3*b*x)*sqrt((a+b*x)^3)/15/b^2)",
+ #126
+ "f(x^2*sqrt(a+b*x),2*(8*a^2-12*a*b*x+15*b^2*x^2)*sqrt((a+b*x)^3)/105/b^3)",
+ #128
+ "f(sqrt(a+b*x)/x,2*sqrt(a+b*x)+a*integral(1/x*1/sqrt(a+b*x),x))",
+ #129
+ "f(sqrt(a+b*x)/x^2,-sqrt(a+b*x)/x+b/2*integral(1/x*1/sqrt(a+b*x),x))",
+ #131
+ "f(1/sqrt(a+b*x),2*sqrt(a+b*x)/b)",
+ #132
+ "f(x/sqrt(a+b*x),-2/3*(2*a-b*x)*sqrt(a+b*x)/b^2)",
+ #133
+ "f(x^2/sqrt(a+b*x),2/15*(8*a^2-4*a*b*x+3*b^2*x^2)*sqrt(a+b*x)/b^3)",
+ #135
+ "f(1/x*1/sqrt(a+b*x),1/sqrt(a)*log((sqrt(a+b*x)-sqrt(a))/(sqrt(a+b*x)+sqrt(a))),or(not(number(a)),a>0))",
+ #136
+ "f(1/x*1/sqrt(a+b*x),2/sqrt(-a)*arctan(sqrt(-(a+b*x)/a)),or(not(number(a)),a<0))",
+ #137
+ "f(1/x^2*1/sqrt(a+b*x),-sqrt(a+b*x)/a/x-1/2*b/a*integral(1/x*1/sqrt(a+b*x),x))",
+ #156
+ "f(sqrt(x^2+a),1/2*(x*sqrt(x^2+a)+a*log(x+sqrt(x^2+a))))",
+ #157
+ "f(1/sqrt(x^2+a),log(x+sqrt(x^2+a)))",
+ #158
+ "f(1/x*1/sqrt(x^2+a),arcsec(x/sqrt(-a))/sqrt(-a),or(not(number(a)),a<0))",
+ #159
+ "f(1/x*1/sqrt(x^2+a),-1/sqrt(a)*log((sqrt(a)+sqrt(x^2+a))/x),or(not(number(a)),a>0))",
+ #160
+ "f(sqrt(x^2+a)/x,sqrt(x^2+a)-sqrt(a)*log((sqrt(a)+sqrt(x^2+a))/x),or(not(number(a)),a>0))",
+ #161
+ "f(sqrt(x^2+a)/x,sqrt(x^2+a)-sqrt(-a)*arcsec(x/sqrt(-a)),or(not(number(a)),a<0))",
+ #162
+ "f(x/sqrt(x^2+a),sqrt(x^2+a))",
+ #163
+ "f(x*sqrt(x^2+a),1/3*sqrt((x^2+a)^3))",
+ #164 need an unexpanded version?
+ "f(sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/4*(x*sqrt((x^2+a^(1/3))^3)+3/2*a^(1/3)*x*sqrt(x^2+a^(1/3))+3/2*a^(2/3)*log(x+sqrt(x^2+a^(1/3)))))",
+ # match doesn't work for the following
+ "f(sqrt(-a+x^6-3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/4*(x*sqrt((x^2-a^(1/3))^3)-3/2*a^(1/3)*x*sqrt(x^2-a^(1/3))+3/2*a^(2/3)*log(x+sqrt(x^2-a^(1/3)))))",
+ #165
+ "f(1/sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),x/a^(1/3)/sqrt(x^2+a^(1/3)))",
+ #166
+ "f(x/sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),-1/sqrt(x^2+a^(1/3)))",
+ #167
+ "f(x*sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/5*sqrt((x^2+a^(1/3))^5))",
+ #168
+ "f(x^2*sqrt(x^2+a),1/4*x*sqrt((x^2+a)^3)-1/8*a*x*sqrt(x^2+a)-1/8*a^2*log(x+sqrt(x^2+a)))",
+ #169
+ "f(x^3*sqrt(x^2+a),(1/5*x^2-2/15*a)*sqrt((x^2+a)^3),and(number(a),a>0))",
+ #170
+ "f(x^3*sqrt(x^2+a),sqrt((x^2+a)^5)/5-a*sqrt((x^2+a)^3)/3,and(number(a),a<0))",
+ #171
+ "f(x^2/sqrt(x^2+a),1/2*x*sqrt(x^2+a)-1/2*a*log(x+sqrt(x^2+a)))",
+ #172
+ "f(x^3/sqrt(x^2+a),1/3*sqrt((x^2+a)^3)-a*sqrt(x^2+a))",
+ #173
+ "f(1/x^2*1/sqrt(x^2+a),-sqrt(x^2+a)/a/x)",
+ #174
+ "f(1/x^3*1/sqrt(x^2+a),-1/2*sqrt(x^2+a)/a/x^2+1/2*log((sqrt(a)+sqrt(x^2+a))/x)/a^(3/2),or(not(number(a)),a>0))",
+ #175
+ "f(1/x^3*1/sqrt(x^2-a),1/2*sqrt(x^2-a)/a/x^2+1/2*1/(a^(3/2))*arcsec(x/(a^(1/2))),or(not(number(a)),a>0))",
+ #176+
+ "f(x^2*sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/6*x*sqrt((x^2+a^(1/3))^5)-1/24*a^(1/3)*x*sqrt((x^2+a^(1/3))^3)-1/16*a^(2/3)*x*sqrt(x^2+a^(1/3))-1/16*a*log(x+sqrt(x^2+a^(1/3))),or(not(number(a)),a>0))",
+ #176-
+ "f(x^2*sqrt(-a-3*a^(1/3)*x^4+3*a^(2/3)*x^2+x^6),1/6*x*sqrt((x^2-a^(1/3))^5)+1/24*a^(1/3)*x*sqrt((x^2-a^(1/3))^3)-1/16*a^(2/3)*x*sqrt(x^2-a^(1/3))+1/16*a*log(x+sqrt(x^2-a^(1/3))),or(not(number(a)),a>0))",
+ #177+
+ "f(x^3*sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/7*sqrt((x^2+a^(1/3))^7)-1/5*a^(1/3)*sqrt((x^2+a^(1/3))^5),or(not(number(a)),a>0))",
+ #177-
+ "f(x^3*sqrt(-a-3*a^(1/3)*x^4+3*a^(2/3)*x^2+x^6),1/7*sqrt((x^2-a^(1/3))^7)+1/5*a^(1/3)*sqrt((x^2-a^(1/3))^5),or(not(number(a)),a>0))",
+ #196
+ "f(1/(x-a)/sqrt(x^2-a^2),-sqrt(x^2-a^2)/a/(x-a))",
+ #197
+ "f(1/(x+a)/sqrt(x^2-a^2),sqrt(x^2-a^2)/a/(x+a))",
+ #200+
+ "f(sqrt(a-x^2),1/2*(x*sqrt(a-x^2)+a*arcsin(x/sqrt(abs(a)))))",
+ #201 (seems to be handled somewhere else)
+ #202
+ "f(1/x*1/sqrt(a-x^2),-1/sqrt(a)*log((sqrt(a)+sqrt(a-x^2))/x),or(not(number(a)),a>0))",
+ #203
+ "f(sqrt(a-x^2)/x,sqrt(a-x^2)-sqrt(a)*log((sqrt(a)+sqrt(a-x^2))/x),or(not(number(a)),a>0))",
+ #204
+ "f(x/sqrt(a-x^2),-sqrt(a-x^2))",
+ #205
+ "f(x*sqrt(a-x^2),-1/3*sqrt((a-x^2)^3))",
+ #210
+ "f(x^2*sqrt(a-x^2),-x/4*sqrt((a-x^2)^3)+1/8*a*(x*sqrt(a-x^2)+a*arcsin(x/sqrt(a))),or(not(number(a)),a>0))",
+ #211
+ "f(x^3*sqrt(a-x^2),(-1/5*x^2-2/15*a)*sqrt((a-x^2)^3),or(not(number(a)),a>0))",
+ #214
+ "f(x^2/sqrt(a-x^2),-x/2*sqrt(a-x^2)+a/2*arcsin(x/sqrt(a)),or(not(number(a)),a>0))",
+ #215
+ "f(1/x^2*1/sqrt(a-x^2),-sqrt(a-x^2)/a/x,or(not(number(a)),a>0))",
+ #216
+ "f(sqrt(a-x^2)/x^2,-sqrt(a-x^2)/x-arcsin(x/sqrt(a)),or(not(number(a)),a>0))",
+ #217
+ "f(sqrt(a-x^2)/x^3,-1/2*sqrt(a-x^2)/x^2+1/2*log((sqrt(a)+sqrt(a-x^2))/x)/sqrt(a),or(not(number(a)),a>0))",
+ #218
+ "f(sqrt(a-x^2)/x^4,-1/3*sqrt((a-x^2)^3)/a/x^3,or(not(number(a)),a>0))",
+ # 273
+ "f(sqrt(a*x^2+b),x*sqrt(a*x^2+b)/2+b*log(x*sqrt(a)+sqrt(a*x^2+b))/2/sqrt(a),and(number(a),a>0))",
+ # 274
+ "f(sqrt(a*x^2+b),x*sqrt(a*x^2+b)/2+b*arcsin(x*sqrt(-a/b))/2/sqrt(-a),and(number(a),a<0))",
+ # 290
+ "f(sin(a*x),-cos(a*x)/a)",
+ # 291
+ "f(cos(a*x),sin(a*x)/a)",
+ # 292
+ "f(tan(a*x),-log(cos(a*x))/a)",
+ # 293
+ "f(1/tan(a*x),log(sin(a*x))/a)",
+ # 294
+ "f(1/cos(a*x),log(tan(pi/4+a*x/2))/a)",
+ # 295
+ "f(1/sin(a*x),log(tan(a*x/2))/a)",
+ # 296
+ "f(sin(a*x)^2,x/2-sin(2*a*x)/(4*a))",
+ # 297
+ "f(sin(a*x)^3,-cos(a*x)*(sin(a*x)^2+2)/(3*a))",
+ # 298
+ "f(sin(a*x)^4,3/8*x-sin(2*a*x)/(4*a)+sin(4*a*x)/(32*a))",
+ # 302
+ "f(cos(a*x)^2,x/2+sin(2*a*x)/(4*a))",
+ # 303
+ "f(cos(a*x)^3,sin(a*x)*(cos(a*x)^2+2)/(3*a))",
+ # 304
+ "f(cos(a*x)^4,3/8*x+sin(2*a*x)/(4*a)+sin(4*a*x)/(32*a))",
+ # 308
+ "f(1/sin(a*x)^2,-1/(a*tan(a*x)))",
+ # 312
+ "f(1/cos(a*x)^2,tan(a*x)/a)",
+ # 318
+ "f(sin(a*x)*cos(a*x),sin(a*x)^2/(2*a))",
+ # 320
+ "f(sin(a*x)^2*cos(a*x)^2,-sin(4*a*x)/(32*a)+x/8)",
+ # 326
+ "f(sin(a*x)/cos(a*x)^2,1/(a*cos(a*x)))",
+ # 327
+ "f(sin(a*x)^2/cos(a*x),(log(tan(pi/4+a*x/2))-sin(a*x))/a)",
+ # 328
+ "f(cos(a*x)/sin(a*x)^2,-1/(a*sin(a*x)))",
+ # 329
+ "f(1/(sin(a*x)*cos(a*x)),log(tan(a*x))/a)",
+ # 330
+ "f(1/(sin(a*x)*cos(a*x)^2),(1/cos(a*x)+log(tan(a*x/2)))/a)",
+ # 331
+ "f(1/(sin(a*x)^2*cos(a*x)),(log(tan(pi/4+a*x/2))-1/sin(a*x))/a)",
+ # 333
+ "f(1/(sin(a*x)^2*cos(a*x)^2),-2/(a*tan(2*a*x)))",
+ # 335
+ "f(sin(a+b*x),-cos(a+b*x)/b)",
+ # 336
+ "f(cos(a+b*x),sin(a+b*x)/b)",
+ # 337+ (with the addition of b)
+ "f(1/(b+b*sin(a*x)),-tan(pi/4-a*x/2)/a/b)",
+ # 337- (with the addition of b)
+ "f(1/(b-b*sin(a*x)),tan(pi/4+a*x/2)/a/b)",
+ # 338 (with the addition of b)
+ "f(1/(b+b*cos(a*x)),tan(a*x/2)/a/b)",
+ # 339 (with the addition of b)
+ "f(1/(b-b*cos(a*x)),-1/tan(a*x/2)/a/b)",
+ # 340
+ "f(1/(a+b*sin(x)),1/sqrt(b^2-a^2)*log((a*tan(x/2)+b-sqrt(b^2-a^2))/(a*tan(x/2)+b+sqrt(b^2-a^2))),b^2-a^2)", # check that b^2-a^2 is not zero
+ # 341
+ "f(1/(a+b*cos(x)),1/sqrt(b^2-a^2)*log((sqrt(b^2-a^2)*tan(x/2)+a+b)/(sqrt(b^2-a^2)*tan(x/2)-a-b)),b^2-a^2)", # check that b^2-a^2 is not zero
+ # 389
+ "f(x*sin(a*x),sin(a*x)/a^2-x*cos(a*x)/a)",
+ # 390
+ "f(x^2*sin(a*x),2*x*sin(a*x)/a^2-(a^2*x^2-2)*cos(a*x)/a^3)",
+ # 393
+ "f(x*cos(a*x),cos(a*x)/a^2+x*sin(a*x)/a)",
+ # 394
+ "f(x^2*cos(a*x),2*x*cos(a*x)/a^2+(a^2*x^2-2)*sin(a*x)/a^3)",
+ # 441
+ "f(arcsin(a*x),x*arcsin(a*x)+sqrt(1-a^2*x^2)/a)",
+ # 442
+ "f(arccos(a*x),x*arccos(a*x)-sqrt(1-a^2*x^2)/a)",
+ # 443
+ "f(arctan(a*x),x*arctan(a*x)-1/2*log(1+a^2*x^2)/a)",
+ # 485 (with addition of a)
+ # however commenting out since it's a duplicate of 14
+ # "f(log(a*x),x*log(a*x)-x)",
+ # 486 (with addition of a)
+ "f(x*log(a*x),x^2*log(a*x)/2-x^2/4)",
+ # 487 (with addition of a)
+ "f(x^2*log(a*x),x^3*log(a*x)/3-1/9*x^3)",
+ # 489
+ "f(log(x)^2,x*log(x)^2-2*x*log(x)+2*x)",
+ # 493 (with addition of a)
+ "f(1/x*1/(a+log(x)),log(a+log(x)))",
+ # 499
+ "f(log(a*x+b),(a*x+b)*log(a*x+b)/a-x)",
+ # 500
+ "f(log(a*x+b)/x^2,a/b*log(x)-(a*x+b)*log(a*x+b)/b/x)",
+ # 554
+ "f(sinh(x),cosh(x))",
+ # 555
+ "f(cosh(x),sinh(x))",
+ # 556
+ "f(tanh(x),log(cosh(x)))",
+ # 560
+ "f(x*sinh(x),x*cosh(x)-sinh(x))",
+ # 562
+ "f(x*cosh(x),x*sinh(x)-cosh(x))",
+ # 566
+ "f(sinh(x)^2,sinh(2*x)/4-x/2)",
+ # 569
+ "f(tanh(x)^2,x-tanh(x))",
+ # 572
+ "f(cosh(x)^2,sinh(2*x)/4+x/2)",
+ # ?
+ "f(x^3*exp(a*x^2),exp(a*x^2)*(x^2/a-1/(a^2))/2)",
+ # ?
+ "f(x^3*exp(a*x^2+b),exp(a*x^2)*exp(b)*(x^2/a-1/(a^2))/2)",
+ # ?
+ "f(exp(a*x^2),-i*sqrt(pi)*erf(i*sqrt(a)*x)/sqrt(a)/2)",
+ # ?
+ "f(erf(a*x),x*erf(a*x)+exp(-a^2*x^2)/a/sqrt(pi))",
+
+ # these are needed for the surface integral in the manual
+
+ "f(x^2*(1-x^2)^(3/2),(x*sqrt(1-x^2)*(-8*x^4+14*x^2-3)+3*arcsin(x))/48)",
+ "f(x^2*(1-x^2)^(5/2),(x*sqrt(1-x^2)*(48*x^6-136*x^4+118*x^2-15)+15*arcsin(x))/384)",
+ "f(x^4*(1-x^2)^(3/2),(-x*sqrt(1-x^2)*(16*x^6-24*x^4+2*x^2+3)+3*arcsin(x))/128)",
+
+ "f(x*exp(a*x),exp(a*x)*(a*x-1)/(a^2))",
+ "f(x*exp(a*x+b),exp(a*x+b)*(a*x-1)/(a^2))",
+
+ "f(x^2*exp(a*x),exp(a*x)*(a^2*x^2-2*a*x+2)/(a^3))",
+ "f(x^2*exp(a*x+b),exp(a*x+b)*(a^2*x^2-2*a*x+2)/(a^3))",
+
+ "f(x^3*exp(a*x),exp(a*x)*x^3/a-3/a*integral(x^2*exp(a*x),x))",
+ "f(x^3*exp(a*x+b),exp(a*x+b)*x^3/a-3/a*integral(x^2*exp(a*x+b),x))",
+ 0
+
+]
+
+
+#define F p3
+#define X p4
+#define N p5
+
+Eval_integral = ->
+ i = 0
+ n = 0
+
+ # evaluate 1st arg to get function F
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+
+ # evaluate 2nd arg and then...
+
+ # example result of 2nd arg what to do
+ #
+ # integral(f) nil guess X, N = nil
+ # integral(f,2) 2 guess X, N = 2
+ # integral(f,x) x X = x, N = nil
+ # integral(f,x,2) x X = x, N = 2
+ # integral(f,x,y) x X = x, N = y
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ guess()
+ push(symbol(NIL))
+ else if (isNumericAtom(p2))
+ guess()
+ push(p2)
+ else
+ push(p2)
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+
+ p5 = pop()
+ p4 = pop()
+ p3 = pop()
+
+ while (1)
+
+ # N might be a symbol instead of a number
+
+ if (isNumericAtom(p5))
+ push(p5)
+ n = pop_integer()
+ if (isNaN(n))
+ stop("nth integral: check n")
+ else
+ n = 1
+
+ push(p3)
+
+ if (n >= 0)
+ for i in [0...n]
+ push(p4)
+ integral()
+ else
+ n = -n
+ for i in [0...n]
+ push(p4)
+ derivative()
+
+ p3 = pop()
+
+ # if N is nil then arglist is exhausted
+
+ if (p5 == symbol(NIL))
+ break
+
+ # otherwise...
+
+ # N arg1 what to do
+ #
+ # number nil break
+ # number number N = arg1, continue
+ # number symbol X = arg1, N = arg2, continue
+ #
+ # symbol nil X = N, N = nil, continue
+ # symbol number X = N, N = arg1, continue
+ # symbol symbol X = N, N = arg1, continue
+
+ if (isNumericAtom(p5))
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p5 = pop()
+ if (p5 == symbol(NIL))
+ break; # arglist exhausted
+ if (isNumericAtom(p5))
+ doNothing = 1 # N = arg1
+ else
+ p4 = p5; # X = arg1
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p5 = pop(); # N = arg2
+ else
+ p4 = p5; # X = N
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p5 = pop(); # N = arg1
+
+ push(p3); # final result
+
+integral = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ if (car(p1) == symbol(ADD))
+ integral_of_sum()
+ else if (car(p1) == symbol(MULTIPLY))
+ integral_of_product()
+ else
+ integral_of_form()
+ p1 = pop()
+ if (Find(p1, symbol(INTEGRAL)))
+ stop("integral: sorry, could not find a solution")
+ push(p1)
+ simplify(); # polish the result
+ Eval(); # normalize the result
+ restore()
+
+integral_of_sum = ->
+ p1 = cdr(p1)
+ push(car(p1))
+ push(p2)
+ integral()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ integral()
+ add()
+ p1 = cdr(p1)
+
+integral_of_product = ->
+ push(p1)
+ push(p2)
+ partition()
+ p1 = pop(); # pop variable part
+ integral_of_form()
+ multiply(); # multiply constant part
+
+integral_of_form = ->
+ hc = italu_hashcode(p1, p2).toFixed(6)
+ tab = hashed_itab[hc]
+ # console.log('hashcode('+p1+', '+p2+') = ' + hc + ' '+!!tab);
+ if (!tab)
+ # debugger
+ # italu_hashcode(p1, p2)
+ push_symbol(INTEGRAL)
+ push(p1)
+ push(p2)
+ list(3)
+ return
+ push(p1) # free variable
+ push(p2) # input expression
+ transform(tab, false)
+ p3 = pop()
+ if (p3 == symbol(NIL))
+ push_symbol(INTEGRAL)
+ push(p1)
+ push(p2)
+ list(3)
+ else
+ push(p3)
+
+
+# Implementation of hash codes based on ITALU (An Integral Table Look-Up)
+# https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19680004891.pdf
+# see Appendix A, page 153
+
+# The first two values are from the ITALU paper.
+# The others are just arbitrary constants.
+hashcode_values =
+ 'x':0.95532,
+ 'constexp':1.43762,
+ 'constant':1.14416593629414332,
+ 'constbase':1.20364122304218824,
+ 'sin': 1.73305482518303221,
+ 'arcsin': 1.6483368529465804,
+ 'cos': 1.058672123686340116,
+ 'arccos': 1.8405225918106694,
+ 'tan': 1.12249437762925064,
+ 'arctan': 1.1297397925394962,
+ 'sinh':1.8176164926060078,
+ 'cosh':1.9404934661708022,
+ 'tanh':1.6421307715103121,
+ 'log':1.47744370135492387,
+ 'erf':1.0825269225702916,
+
+italu_hashcode = (u, x) ->
+ if (issymbol(u))
+ if (equal(u, x))
+ return hashcode_values.x
+ else
+ return hashcode_values.constant
+ else if (iscons(u))
+ switch (symnum(car(u)))
+ when ADD then return hash_addition(cdr(u),x)
+ when MULTIPLY then return hash_multiplication(cdr(u), x)
+ when POWER then return hash_power(cadr(u), caddr(u), x)
+ when EXP then return hash_power(symbol(E), cadr(u), x)
+ when SQRT
+ push_double(0.5)
+ half = pop()
+ return hash_power(cadr(u), half, x)
+ else return hash_function(u, x)
+
+ return hashcode_values.constant
+
+hash_function = (u, x) ->
+ if !Find(cadr(u), x)
+ return hashcode_values.constant
+ name = car(u)
+ arg_hash = italu_hashcode(cadr(u), x)
+ base = hashcode_values[name.printname]
+ if (!base)
+ throw new Error('Unsupported function ' + name.printname)
+ return Math.pow(base, arg_hash)
+
+hash_addition = (terms, x) ->
+ term_set = {}
+ while (iscons(terms))
+ term = car(terms)
+ terms = cdr(terms)
+ term_hash = 0
+ if Find(term, x)
+ term_hash = italu_hashcode(term, x)
+ else
+ # The original algorithm would skip this,
+ # but recording that it was present helps
+ # prevent collisions.
+ term_hash = hashcode_values.constant
+ term_set[term_hash.toFixed(6)] = true
+ sum = 0
+ for own k,v of term_set
+ sum = sum + parseFloat(k,10)
+ return sum
+
+hash_multiplication = (terms, x) ->
+ product = 1
+ while (iscons(terms))
+ term = car(terms)
+ terms = cdr(terms)
+ if (Find(term, x))
+ product = product * italu_hashcode(term, x)
+ return product
+
+hash_power = (base, power, x) ->
+ base_hash = hashcode_values.constant
+ exp_hash = hashcode_values.constexp
+ if (Find(base, x))
+ base_hash = italu_hashcode(base, x)
+ if (Find(power, x))
+ exp_hash = italu_hashcode(power, x)
+ else
+ # constant to constant = constant
+ if base_hash == hashcode_values.constant
+ return hashcode_values.constant
+ if isminusone(power)
+ exp_hash = -1
+ else if isoneovertwo(power)
+ exp_hash = 0.5
+ else if isminusoneovertwo(power)
+ exp_hash = -0.5
+ else if equalq(power, 2, 1)
+ exp_hash = 2
+ else if equalq(power, -2, 1)
+ exp_hash = -2
+ return Math.pow(base_hash, exp_hash)
+
+make_hashed_itab = () ->
+ tab = {}
+ for s in itab
+ if !s
+ break
+ scan_meta(s)
+ f = pop()
+ u = cadr(f)
+ h = italu_hashcode(u, symbol(METAX))
+ key = h.toFixed(6)
+ if (!tab[key])
+ tab[key]=[]
+ tab[key].push(s)
+ console.log('hashed_itab = '+JSON.stringify(tab, null, 2))
+ return tab
+
+$.make_hashed_itab = make_hashed_itab
+
+# pre-calculated hashed integral table.
+# in case the integral table is changed, use this
+# Algebrite.make_hashed_itab()
+# and copy the resulting JSON in here.
+hashed_itab = {
+ "1.144166": [
+ "f(a,a*x)"
+ ],
+ "1.046770": [
+ "f(1/x,log(x))"
+ ],
+ "0.936400": [
+ "f(x^a,x^(a+1)/(a+1))"
+ ],
+ "1.095727": [
+ "f(x^(-2),-x^(-1))"
+ ],
+ "1.023118": [
+ "f(x^(-1/2),2*x^(1/2))"
+ ],
+ "0.977405": [
+ "f(x^(1/2),2/3*x^(3/2))"
+ ],
+ "0.955320": [
+ "f(x,x^2/2)"
+ ],
+ "0.912636": [
+ "f(x^2,x^3/3)"
+ ],
+ "1.137302": [
+ "f(exp(a*x),1/a*exp(a*x))",
+ "f(a^x,a^x/log(a),or(not(number(a)),a>0))"
+ ],
+ "1.326774": [
+ "f(exp(a*x+b),1/a*exp(a*x+b))"
+ ],
+ "1.080259": [
+ "f(x*exp(a*x^2),exp(a*x^2)/(2*a))"
+ ],
+ "1.260228": [
+ "f(x*exp(a*x^2+b),exp(a*x^2+b)/(2*a))"
+ ],
+ "1.451902": [
+ "f(log(a*x),x*log(a*x)-x)"
+ ],
+ "0.486192": [
+ "f(1/(a+x^2),1/sqrt(a)*arctan(x/sqrt(a)),or(not(number(a)),a>0))",
+ "f(1/(a-x^2),1/sqrt(a)*arctanh(x/sqrt(a)))",
+ "f(1/(a+b*x^2),1/sqrt(a*b)*arctan(x*sqrt(a*b)/a),or(not(number(a*b)),a*b>0))",
+ "f(1/(a+b*x^2),1/(2*sqrt(-a*b))*log((a+x*sqrt(-a*b))/(a-x*sqrt(-a*b))),or(not(number(a*b)),a*b<0))"
+ ],
+ "0.697274": [
+ "f(1/sqrt(a-x^2),arcsin(x/(sqrt(a))))",
+ "f(1/sqrt(a+x^2),log(x+sqrt(a+x^2)))",
+ "f(1/sqrt(x^2+a),log(x+sqrt(x^2+a)))"
+ ],
+ "0.476307": [
+ "f(1/(a+b*x),1/b*log(a+b*x))"
+ ],
+ "0.226868": [
+ "f(1/(a+b*x)^2,-1/(b*(a+b*x)))"
+ ],
+ "2.904531": [
+ "f(1/(a+b*x)^3,-1/(2*b)*1/(a+b*x)^2)"
+ ],
+ "0.455026": [
+ "f(x/(a+b*x),x/b-a*log(a+b*x)/b/b)"
+ ],
+ "0.216732": [
+ "f(x/(a+b*x)^2,1/b^2*(log(a+b*x)+a/(a+b*x)))"
+ ],
+ "0.434695": [
+ "f(x^2/(a+b*x),1/b^2*(1/2*(a+b*x)^2-2*a*(a+b*x)+a^2*log(a+b*x)))"
+ ],
+ "0.207048": [
+ "f(x^2/(a+b*x)^2,1/b^3*(a+b*x-2*a*log(a+b*x)-a^2/(a+b*x)))"
+ ],
+ "2.650781": [
+ "f(x^2/(a+b*x)^3,1/b^3*(log(a+b*x)+2*a/(a+b*x)-1/2*a^2/(a+b*x)^2))"
+ ],
+ "0.498584": [
+ "f(1/x*1/(a+b*x),-1/a*log((a+b*x)/x))"
+ ],
+ "0.237479": [
+ "f(1/x*1/(a+b*x)^2,1/a*1/(a+b*x)-1/a^2*log((a+b*x)/x))"
+ ],
+ "3.040375": [
+ "f(1/x*1/(a+b*x)^3,1/a^3*(1/2*((2*a+b*x)/(a+b*x))^2+log(x/(a+b*x))))"
+ ],
+ "0.521902": [
+ "f(1/x^2*1/(a+b*x),-1/(a*x)+b/a^2*log((a+b*x)/x))"
+ ],
+ "0.446014": [
+ "f(1/x^3*1/(a+b*x),(2*b*x-a)/(2*a^2*x^2)+b^2/a^3*log(x/(a+b*x)))"
+ ],
+ "0.248586": [
+ "f(1/x^2*1/(a+b*x)^2,-(a+2*b*x)/(a^2*x*(a+b*x))+2*b/a^3*log((a+b*x)/x))"
+ ],
+ "0.464469": [
+ "f(x/(a+b*x^2),1/2*1/b*log(a+b*x^2))"
+ ],
+ "0.443716": [
+ "f(x^2/(a+b*x^2),x/b-a/b*integral(1/(a+b*x^2),x))"
+ ],
+ "0.236382": [
+ "f(1/(a+b*x^2)^2,x/(2*a*(a+b*x^2))+1/2*1/a*integral(1/(a+b*x^2),x))"
+ ],
+ "0.508931": [
+ "f(1/x*1/(a+b*x^2),1/2*1/a*log(x^2/(a+b*x^2)))"
+ ],
+ "0.532733": [
+ "f(1/x^2*1/(a+b*x^2),-1/(a*x)-b/a*integral(1/(a+b*x^2),x))"
+ ],
+ "0.480638": [
+ "f(1/(a+b*x^3),1/3*1/a*(a/b)^(1/3)*(1/2*log(((a/b)^(1/3)+x)^3/(a+b*x^3))+sqrt(3)*arctan((2*x-(a/b)^(1/3))*(a/b)^(-1/3)/sqrt(3))))"
+ ],
+ "0.438648": [
+ "f(x^2/(a+b*x^3),1/3*1/b*log(a+b*x^3))"
+ ],
+ "0.459164": [
+ "f(x/(a+b*x^4),1/2*sqrt(b/a)/b*arctan(x^2*sqrt(b/a)),or(not(number(a*b)),a*b>0))",
+ "f(x/(a+b*x^4),1/4*sqrt(-b/a)/b*log((x^2-sqrt(-a/b))/(x^2+sqrt(-a/b))),or(not(number(a*b)),a*b<0))"
+ ],
+ "0.450070": [
+ "f(x^3/(a+b*x^4),1/4*1/b*log(a+b*x^4))"
+ ],
+ "1.448960": [
+ "f(sqrt(a+b*x),2/3*1/b*sqrt((a+b*x)^3))"
+ ],
+ "1.384221": [
+ "f(x*sqrt(a+b*x),-2*(2*a-3*b*x)*sqrt((a+b*x)^3)/15/b^2)"
+ ],
+ "1.322374": [
+ "f(x^2*sqrt(a+b*x),2*(8*a^2-12*a*b*x+15*b^2*x^2)*sqrt((a+b*x)^3)/105/b^3)"
+ ],
+ "1.516728": [
+ "f(sqrt(a+b*x)/x,2*sqrt(a+b*x)+a*integral(1/x*1/sqrt(a+b*x),x))"
+ ],
+ "1.587665": [
+ "f(sqrt(a+b*x)/x^2,-sqrt(a+b*x)/x+b/2*integral(1/x*1/sqrt(a+b*x),x))"
+ ],
+ "0.690150": [
+ "f(1/sqrt(a+b*x),2*sqrt(a+b*x)/b)"
+ ],
+ "0.659314": [
+ "f(x/sqrt(a+b*x),-2/3*(2*a-b*x)*sqrt(a+b*x)/b^2)"
+ ],
+ "0.629856": [
+ "f(x^2/sqrt(a+b*x),2/15*(8*a^2-4*a*b*x+3*b^2*x^2)*sqrt(a+b*x)/b^3)"
+ ],
+ "0.722428": [
+ "f(1/x*1/sqrt(a+b*x),1/sqrt(a)*log((sqrt(a+b*x)-sqrt(a))/(sqrt(a+b*x)+sqrt(a))),or(not(number(a)),a>0))",
+ "f(1/x*1/sqrt(a+b*x),2/sqrt(-a)*arctan(sqrt(-(a+b*x)/a)),or(not(number(a)),a<0))"
+ ],
+ "0.756216": [
+ "f(1/x^2*1/sqrt(a+b*x),-sqrt(a+b*x)/a/x-1/2*b/a*integral(1/x*1/sqrt(a+b*x),x))"
+ ],
+ "1.434156": [
+ "f(sqrt(x^2+a),1/2*(x*sqrt(x^2+a)+a*log(x+sqrt(x^2+a))))",
+ "f(sqrt(a-x^2),1/2*(x*sqrt(a-x^2)+a*arcsin(x/sqrt(abs(a)))))",
+ "f(sqrt(a*x^2+b),x*sqrt(a*x^2+b)/2+b*log(x*sqrt(a)+sqrt(a*x^2+b))/2/sqrt(a),and(number(a),a>0))",
+ "f(sqrt(a*x^2+b),x*sqrt(a*x^2+b)/2+b*arcsin(x*sqrt(-a/b))/2/sqrt(-a),and(number(a),a<0))"
+ ],
+ "0.729886": [
+ "f(1/x*1/sqrt(x^2+a),arcsec(x/sqrt(-a))/sqrt(-a),or(not(number(a)),a<0))",
+ "f(1/x*1/sqrt(x^2+a),-1/sqrt(a)*log((sqrt(a)+sqrt(x^2+a))/x),or(not(number(a)),a>0))",
+ "f(1/x*1/sqrt(a-x^2),-1/sqrt(a)*log((sqrt(a)+sqrt(a-x^2))/x),or(not(number(a)),a>0))"
+ ],
+ "1.501230": [
+ "f(sqrt(x^2+a)/x,sqrt(x^2+a)-sqrt(a)*log((sqrt(a)+sqrt(x^2+a))/x),or(not(number(a)),a>0))",
+ "f(sqrt(x^2+a)/x,sqrt(x^2+a)-sqrt(-a)*arcsec(x/sqrt(-a)),or(not(number(a)),a<0))",
+ "f(sqrt(a-x^2)/x,sqrt(a-x^2)-sqrt(a)*log((sqrt(a)+sqrt(a-x^2))/x),or(not(number(a)),a>0))"
+ ],
+ "0.666120": [
+ "f(x/sqrt(x^2+a),sqrt(x^2+a))",
+ "f(x/sqrt(a-x^2),-sqrt(a-x^2))"
+ ],
+ "1.370077": [
+ "f(x*sqrt(x^2+a),1/3*sqrt((x^2+a)^3))",
+ "f(x*sqrt(a-x^2),-1/3*sqrt((a-x^2)^3))"
+ ],
+ "1.730087": [
+ "f(sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/4*(x*sqrt((x^2+a^(1/3))^3)+3/2*a^(1/3)*x*sqrt(x^2+a^(1/3))+3/2*a^(2/3)*log(x+sqrt(x^2+a^(1/3)))))",
+ "f(sqrt(-a+x^6-3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/4*(x*sqrt((x^2-a^(1/3))^3)-3/2*a^(1/3)*x*sqrt(x^2-a^(1/3))+3/2*a^(2/3)*log(x+sqrt(x^2-a^(1/3)))))"
+ ],
+ "0.578006": [
+ "f(1/sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),x/a^(1/3)/sqrt(x^2+a^(1/3)))"
+ ],
+ "0.552180": [
+ "f(x/sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),-1/sqrt(x^2+a^(1/3)))"
+ ],
+ "1.652787": [
+ "f(x*sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/5*sqrt((x^2+a^(1/3))^5))"
+ ],
+ "1.308862": [
+ "f(x^2*sqrt(x^2+a),1/4*x*sqrt((x^2+a)^3)-1/8*a*x*sqrt(x^2+a)-1/8*a^2*log(x+sqrt(x^2+a)))",
+ "f(x^2*sqrt(a-x^2),-x/4*sqrt((a-x^2)^3)+1/8*a*(x*sqrt(a-x^2)+a*arcsin(x/sqrt(a))),or(not(number(a)),a>0))"
+ ],
+ "1.342944": [
+ "f(x^3*sqrt(x^2+a),(1/5*x^2-2/15*a)*sqrt((x^2+a)^3),and(number(a),a>0))",
+ "f(x^3*sqrt(x^2+a),sqrt((x^2+a)^5)/5-a*sqrt((x^2+a)^3)/3,and(number(a),a<0))",
+ "f(x^3*sqrt(a-x^2),(-1/5*x^2-2/15*a)*sqrt((a-x^2)^3),or(not(number(a)),a>0))",
+ "f(sqrt(a-x^2)/x^3,-1/2*sqrt(a-x^2)/x^2+1/2*log((sqrt(a)+sqrt(a-x^2))/x)/sqrt(a),or(not(number(a)),a>0))",
+ "f(sqrt(a-x^2)/x^4,-1/3*sqrt((a-x^2)^3)/a/x^3,or(not(number(a)),a>0))"
+ ],
+ "0.636358": [
+ "f(x^2/sqrt(x^2+a),1/2*x*sqrt(x^2+a)-1/2*a*log(x+sqrt(x^2+a)))",
+ "f(x^2/sqrt(a-x^2),-x/2*sqrt(a-x^2)+a/2*arcsin(x/sqrt(a)),or(not(number(a)),a>0))"
+ ],
+ "0.652928": [
+ "f(x^3/sqrt(x^2+a),1/3*sqrt((x^2+a)^3)-a*sqrt(x^2+a))",
+ "f(1/x^3*1/sqrt(x^2+a),-1/2*sqrt(x^2+a)/a/x^2+1/2*log((sqrt(a)+sqrt(x^2+a))/x)/a^(3/2),or(not(number(a)),a>0))",
+ "f(1/x^3*1/sqrt(x^2-a),1/2*sqrt(x^2-a)/a/x^2+1/2*1/(a^(3/2))*arcsec(x/(a^(1/2))),or(not(number(a)),a>0))"
+ ],
+ "0.764022": [
+ "f(1/x^2*1/sqrt(x^2+a),-sqrt(x^2+a)/a/x)",
+ "f(1/x^2*1/sqrt(a-x^2),-sqrt(a-x^2)/a/x,or(not(number(a)),a>0))"
+ ],
+ "1.578940": [
+ "f(x^2*sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/6*x*sqrt((x^2+a^(1/3))^5)-1/24*a^(1/3)*x*sqrt((x^2+a^(1/3))^3)-1/16*a^(2/3)*x*sqrt(x^2+a^(1/3))-1/16*a*log(x+sqrt(x^2+a^(1/3))),or(not(number(a)),a>0))",
+ "f(x^2*sqrt(-a-3*a^(1/3)*x^4+3*a^(2/3)*x^2+x^6),1/6*x*sqrt((x^2-a^(1/3))^5)+1/24*a^(1/3)*x*sqrt((x^2-a^(1/3))^3)-1/16*a^(2/3)*x*sqrt(x^2-a^(1/3))+1/16*a*log(x+sqrt(x^2-a^(1/3))),or(not(number(a)),a>0))"
+ ],
+ "1.620055": [
+ "f(x^3*sqrt(a+x^6+3*a^(1/3)*x^4+3*a^(2/3)*x^2),1/7*sqrt((x^2+a^(1/3))^7)-1/5*a^(1/3)*sqrt((x^2+a^(1/3))^5),or(not(number(a)),a>0))",
+ "f(x^3*sqrt(-a-3*a^(1/3)*x^4+3*a^(2/3)*x^2+x^6),1/7*sqrt((x^2-a^(1/3))^7)+1/5*a^(1/3)*sqrt((x^2-a^(1/3))^5),or(not(number(a)),a>0))"
+ ],
+ "0.332117": [
+ "f(1/(x-a)/sqrt(x^2-a^2),-sqrt(x^2-a^2)/a/(x-a))",
+ "f(1/(x+a)/sqrt(x^2-a^2),sqrt(x^2-a^2)/a/(x+a))"
+ ],
+ "1.571443": [
+ "f(sqrt(a-x^2)/x^2,-sqrt(a-x^2)/x-arcsin(x/sqrt(a)),or(not(number(a)),a>0))"
+ ],
+ "1.690994": [
+ "f(sin(a*x),-cos(a*x)/a)"
+ ],
+ "1.055979": [
+ "f(cos(a*x),sin(a*x)/a)"
+ ],
+ "1.116714": [
+ "f(tan(a*x),-log(cos(a*x))/a)"
+ ],
+ "0.895484": [
+ "f(1/tan(a*x),log(sin(a*x))/a)"
+ ],
+ "0.946989": [
+ "f(1/cos(a*x),log(tan(pi/4+a*x/2))/a)"
+ ],
+ "0.591368": [
+ "f(1/sin(a*x),log(tan(a*x/2))/a)"
+ ],
+ "2.859462": [
+ "f(sin(a*x)^2,x/2-sin(2*a*x)/(4*a))"
+ ],
+ "2.128050": [
+ "f(sin(a*x)^3,-cos(a*x)*(sin(a*x)^2+2)/(3*a))",
+ "f(sin(a*x)^4,3/8*x-sin(2*a*x)/(4*a)+sin(4*a*x)/(32*a))"
+ ],
+ "1.115091": [
+ "f(cos(a*x)^2,x/2+sin(2*a*x)/(4*a))"
+ ],
+ "1.081452": [
+ "f(cos(a*x)^3,sin(a*x)*(cos(a*x)^2+2)/(3*a))",
+ "f(cos(a*x)^4,3/8*x+sin(2*a*x)/(4*a)+sin(4*a*x)/(32*a))"
+ ],
+ "0.349716": [
+ "f(1/sin(a*x)^2,-1/(a*tan(a*x)))"
+ ],
+ "0.896788": [
+ "f(1/cos(a*x)^2,tan(a*x)/a)"
+ ],
+ "1.785654": [
+ "f(sin(a*x)*cos(a*x),sin(a*x)^2/(2*a))"
+ ],
+ "3.188560": [
+ "f(sin(a*x)^2*cos(a*x)^2,-sin(4*a*x)/(32*a)+x/8)"
+ ],
+ "1.516463": [
+ "f(sin(a*x)/cos(a*x)^2,1/(a*cos(a*x)))"
+ ],
+ "2.707879": [
+ "f(sin(a*x)^2/cos(a*x),(log(tan(pi/4+a*x/2))-sin(a*x))/a)"
+ ],
+ "0.369293": [
+ "f(cos(a*x)/sin(a*x)^2,-1/(a*sin(a*x)))"
+ ],
+ "0.560019": [
+ "f(1/(sin(a*x)*cos(a*x)),log(tan(a*x))/a)"
+ ],
+ "0.530332": [
+ "f(1/(sin(a*x)*cos(a*x)^2),(1/cos(a*x)+log(tan(a*x/2)))/a)"
+ ],
+ "0.331177": [
+ "f(1/(sin(a*x)^2*cos(a*x)),(log(tan(pi/4+a*x/2))-1/sin(a*x))/a)"
+ ],
+ "0.313621": [
+ "f(1/(sin(a*x)^2*cos(a*x)^2),-2/(a*tan(2*a*x)))"
+ ],
+ "3.172365": [
+ "f(sin(a+b*x),-cos(a+b*x)/b)"
+ ],
+ "1.127162": [
+ "f(cos(a+b*x),sin(a+b*x)/b)"
+ ],
+ "0.352714": [
+ "f(1/(b+b*sin(a*x)),-tan(pi/4-a*x/2)/a/b)",
+ "f(1/(b-b*sin(a*x)),tan(pi/4+a*x/2)/a/b)",
+ "f(1/(a+b*sin(x)),1/sqrt(b^2-a^2)*log((a*tan(x/2)+b-sqrt(b^2-a^2))/(a*tan(x/2)+b+sqrt(b^2-a^2))),b^2-a^2)"
+ ],
+ "0.454515": [
+ "f(1/(b+b*cos(a*x)),tan(a*x/2)/a/b)",
+ "f(1/(b-b*cos(a*x)),-1/tan(a*x/2)/a/b)",
+ "f(1/(a+b*cos(x)),1/sqrt(b^2-a^2)*log((sqrt(b^2-a^2)*tan(x/2)+a+b)/(sqrt(b^2-a^2)*tan(x/2)-a-b)),b^2-a^2)"
+ ],
+ "1.615441": [
+ "f(x*sin(a*x),sin(a*x)/a^2-x*cos(a*x)/a)"
+ ],
+ "1.543263": [
+ "f(x^2*sin(a*x),2*x*sin(a*x)/a^2-(a^2*x^2-2)*cos(a*x)/a^3)"
+ ],
+ "1.008798": [
+ "f(x*cos(a*x),cos(a*x)/a^2+x*sin(a*x)/a)"
+ ],
+ "0.963724": [
+ "f(x^2*cos(a*x),2*x*cos(a*x)/a^2+(a^2*x^2-2)*sin(a*x)/a^3)"
+ ],
+ "1.611938": [
+ "f(arcsin(a*x),x*arcsin(a*x)+sqrt(1-a^2*x^2)/a)"
+ ],
+ "1.791033": [
+ "f(arccos(a*x),x*arccos(a*x)-sqrt(1-a^2*x^2)/a)"
+ ],
+ "1.123599": [
+ "f(arctan(a*x),x*arctan(a*x)-1/2*log(1+a^2*x^2)/a)"
+ ],
+ "1.387031": [
+ "f(x*log(a*x),x^2*log(a*x)/2-x^2/4)"
+ ],
+ "1.325058": [
+ "f(x^2*log(a*x),x^3*log(a*x)/3-1/9*x^3)"
+ ],
+ "2.108018": [
+ "f(log(x)^2,x*log(x)^2-2*x*log(x)+2*x)"
+ ],
+ "0.403214": [
+ "f(1/x*1/(a+log(x)),log(a+log(x)))"
+ ],
+ "2.269268": [
+ "f(log(a*x+b),(a*x+b)*log(a*x+b)/a-x)"
+ ],
+ "2.486498": [
+ "f(log(a*x+b)/x^2,a/b*log(x)-(a*x+b)*log(a*x+b)/b/x)"
+ ],
+ "1.769733": [
+ "f(sinh(x),cosh(x))"
+ ],
+ "1.883858": [
+ "f(cosh(x),sinh(x))"
+ ],
+ "1.606140": [
+ "f(tanh(x),log(cosh(x)))"
+ ],
+ "1.690661": [
+ "f(x*sinh(x),x*cosh(x)-sinh(x))"
+ ],
+ "1.799688": [
+ "f(x*cosh(x),x*sinh(x)-cosh(x))"
+ ],
+ "3.131954": [
+ "f(sinh(x)^2,sinh(2*x)/4-x/2)"
+ ],
+ "2.579685": [
+ "f(tanh(x)^2,x-tanh(x))"
+ ],
+ "3.548923": [
+ "f(cosh(x)^2,sinh(2*x)/4+x/2)"
+ ],
+ "1.058866": [
+ "f(x^3*exp(a*x^2),exp(a*x^2)*(x^2/a-1/(a^2))/2)"
+ ],
+ "1.235270": [
+ "f(x^3*exp(a*x^2+b),exp(a*x^2)*exp(b)*(x^2/a-1/(a^2))/2)"
+ ],
+ "1.130783": [
+ "f(exp(a*x^2),-i*sqrt(pi)*erf(i*sqrt(a)*x)/sqrt(a)/2)"
+ ],
+ "1.078698": [
+ "f(erf(a*x),x*erf(a*x)+exp(-a^2*x^2)/a/sqrt(pi))"
+ ],
+ "2.573650": [
+ "f(x^2*(1-x^2)^(3/2),(x*sqrt(1-x^2)*(-8*x^4+14*x^2-3)+3*arcsin(x))/48)",
+ "f(x^2*(1-x^2)^(5/2),(x*sqrt(1-x^2)*(48*x^6-136*x^4+118*x^2-15)+15*arcsin(x))/384)"
+ ],
+ "2.640666": [
+ "f(x^4*(1-x^2)^(3/2),(-x*sqrt(1-x^2)*(16*x^6-24*x^4+2*x^2+3)+3*arcsin(x))/128)"
+ ],
+ "1.086487": [
+ "f(x*exp(a*x),exp(a*x)*(a*x-1)/(a^2))"
+ ],
+ "1.267493": [
+ "f(x*exp(a*x+b),exp(a*x+b)*(a*x-1)/(a^2))"
+ ],
+ "1.037943": [
+ "f(x^2*exp(a*x),exp(a*x)*(a^2*x^2-2*a*x+2)/(a^3))"
+ ],
+ "1.210862": [
+ "f(x^2*exp(a*x+b),exp(a*x+b)*(a^2*x^2-2*a*x+2)/(a^3))"
+ ],
+ "1.064970": [
+ "f(x^3*exp(a*x),exp(a*x)*x^3/a-3/a*integral(x^2*exp(a*x),x))"
+ ],
+ "1.242392": [
+ "f(x^3*exp(a*x+b),exp(a*x+b)*x^3/a-3/a*integral(x^2*exp(a*x+b),x))"
+ ]
+}
diff --git a/node_modules/algebrite/sources/inv.coffee b/node_modules/algebrite/sources/inv.coffee
new file mode 100644
index 0000000..d5fadf4
--- /dev/null
+++ b/node_modules/algebrite/sources/inv.coffee
@@ -0,0 +1,257 @@
+#-----------------------------------------------------------------------------
+#
+# Input: Matrix on stack (must have two dimensions but
+# it can be non-numerical)
+#
+# Output: Inverse on stack
+#
+# Example:
+#
+# > inv(((1,2),(3,4))
+# ((-2,1),(3/2,-1/2))
+#
+# > inv(((a,b),(c,d))
+# ((d / (a d - b c),-b / (a d - b c)),(-c / (a d - b c),a / (a d - b c)))
+#
+# Note:
+#
+# THIS IS DIFFERENT FROM INVERSE OF AN EXPRESSION (inv)
+# Uses Gaussian elimination for numerical matrices.
+#
+#-----------------------------------------------------------------------------
+
+
+
+INV_check_arg = ->
+ if (!istensor(p1))
+ return 0
+ else if (p1.tensor.ndim != 2)
+ return 0
+ else if (p1.tensor.dim[0] != p1.tensor.dim[1])
+ return 0
+ else
+ return 1
+
+inv = ->
+ i = 0
+ n = 0
+ #U **a
+
+ save()
+
+ p1 = pop()
+
+ # an inv just goes away when
+ # applied to another inv
+ if (isinv(p1))
+ push car(cdr(p1))
+ restore()
+ return
+
+ # inverse goes away in case
+ # of identity matrix
+ if isidentitymatrix(p1)
+ push p1
+ restore()
+ return
+
+ # distribute the inverse of a dot
+ # if in expanding mode
+ # note that the distribution happens
+ # in reverse.
+ # The dot operator is not
+ # commutative, so, it matters.
+ if (expanding && isinnerordot(p1))
+ p1 = cdr(p1)
+ accumulator = []
+ while (iscons(p1))
+ accumulator.push car(p1)
+ p1 = cdr(p1)
+
+ for eachEntry in [accumulator.length-1..0]
+ push(accumulator[eachEntry])
+ inv()
+ if eachEntry != accumulator.length-1
+ inner()
+
+ restore()
+ return
+
+
+ if (INV_check_arg() == 0)
+ push_symbol(INV)
+ push(p1)
+ list(2)
+ restore()
+ return
+
+
+ if isNumericAtomOrTensor p1
+ yyinvg()
+ else
+ push(p1)
+ adj()
+ push(p1)
+ det()
+ p2 = pop()
+ if (isZeroAtomOrTensor(p2))
+ stop("inverse of singular matrix")
+ push(p2)
+ divide()
+
+ restore()
+
+invg = ->
+ save()
+
+ p1 = pop()
+
+ if (INV_check_arg() == 0)
+ push_symbol(INVG)
+ push(p1)
+ list(2)
+ restore()
+ return
+
+ yyinvg()
+
+ restore()
+
+# inverse using gaussian elimination
+
+yyinvg = ->
+ h = 0
+ i = 0
+ j = 0
+ n = 0
+
+ n = p1.tensor.dim[0]
+
+ h = tos
+
+ for i in [0...n]
+ for j in [0...n]
+ if (i == j)
+ push(one)
+ else
+ push(zero)
+
+ for i in [0...(n * n)]
+ push(p1.tensor.elem[i])
+
+ INV_decomp(n)
+
+ p1 = alloc_tensor(n * n)
+
+ p1.tensor.ndim = 2
+ p1.tensor.dim[0] = n
+ p1.tensor.dim[1] = n
+
+ for i in [0...(n * n)]
+ p1.tensor.elem[i] = stack[h + i]
+
+ moveTos tos - 2 * n * n
+
+ push(p1)
+
+#-----------------------------------------------------------------------------
+#
+# Input: n * n unit matrix on stack
+#
+# n * n operand on stack
+#
+# Output: n * n inverse matrix on stack
+#
+# n * n garbage on stack
+#
+# p2 mangled
+#
+#-----------------------------------------------------------------------------
+
+#define A(i, j) stack[a + n * (i) + (j)]
+#define U(i, j) stack[u + n * (i) + (j)]
+
+INV_decomp = (n) ->
+ a = 0
+ d = 0
+ i = 0
+ j = 0
+ u = 0
+
+ a = tos - n * n
+
+ u = a - n * n
+
+ for d in [0...n]
+
+ # diagonal element zero?
+
+ if (equal( (stack[a + n * (d) + (d)]) , zero))
+
+ # find a new row
+
+ for i in [(d + 1)...n]
+ if (!equal( (stack[a + n * (i) + (d)]) , zero))
+ break
+
+ if (i == n)
+ stop("inverse of singular matrix")
+
+ # exchange rows
+
+ for j in [0...n]
+
+ p2 = stack[a + n * (d) + (j)]
+ stack[a + n * (d) + (j)] = stack[a + n * (i) + (j)]
+ stack[a + n * (i) + (j)] = p2
+
+ p2 = stack[u + n * (d) + (j)]
+ stack[u + n * (d) + (j)] = stack[u + n * (i) + (j)]
+ stack[u + n * (i) + (j)] = p2
+
+ # multiply the pivot row by 1 / pivot
+
+ p2 = stack[a + n * (d) + (d)]
+
+ for j in [0...n]
+
+ if (j > d)
+ push(stack[a + n * (d) + (j)])
+ push(p2)
+ divide()
+ stack[a + n * (d) + (j)] = pop()
+
+ push(stack[u + n * (d) + (j)])
+ push(p2)
+ divide()
+ stack[u + n * (d) + (j)] = pop()
+
+ # clear out the column above and below the pivot
+
+ for i in [0...n]
+
+ if (i == d)
+ continue
+
+ # multiplier
+
+ p2 = stack[a + n * (i) + (d)]
+
+ # add pivot row to i-th row
+
+ for j in [0...n]
+
+ if (j > d)
+ push(stack[a + n * (i) + (j)])
+ push(stack[a + n * (d) + (j)])
+ push(p2)
+ multiply()
+ subtract()
+ stack[a + n * (i) + (j)] = pop()
+
+ push(stack[u + n * (i) + (j)])
+ push(stack[u + n * (d) + (j)])
+ push(p2)
+ multiply()
+ subtract()
+ stack[u + n * (i) + (j)] = pop()
diff --git a/node_modules/algebrite/sources/is.coffee b/node_modules/algebrite/sources/is.coffee
new file mode 100644
index 0000000..a964486
--- /dev/null
+++ b/node_modules/algebrite/sources/is.coffee
@@ -0,0 +1,628 @@
+
+
+DEBUG_IS = false
+
+# jsBoolToToInt = (p) ->
+# if p then 1 else 0
+
+# p is a U
+# this routine is a simple check on whether we have
+# a basic zero in our hands. It doesn't perform any
+# calculations or simplifications.
+isZeroAtom = (p) ->
+ switch (p.k)
+ when NUM
+ MZERO(p.q.a)
+ when DOUBLE
+ p.d == 0.0
+ else
+ false
+
+# p is a U
+# this routine is a simple check on whether we have
+# a basic zero in our hands. It doesn't perform any
+# calculations or simplifications.
+isZeroTensor = (p) ->
+ if p.k != TENSOR
+ return 0
+
+ for i in [0...p.tensor.nelem]
+ if (!isZeroAtomOrTensor(p.tensor.elem[i]))
+ return 0
+ return 1
+
+# p is a U
+# this routine is a simple check on whether we have
+# a basic zero in our hands. It doesn't perform any
+# calculations or simplifications.
+isZeroAtomOrTensor = (p) ->
+ isZeroAtom(p) or isZeroTensor(p)
+
+# This is a key routine to try to determine whether
+# the argument looks like zero/false, or non-zero/true,
+# or undetermined.
+# This is useful in two instances:
+# * to determine if a predicate is true/false
+# * to determine if particular quantity is zero
+# Note that if one wants to check if we have a simple
+# zero atom or tensor in our hands, then the isZeroAtomOrTensor
+# routine is sufficient.
+isZeroLikeOrNonZeroLikeOrUndetermined = (valueOrPredicate) ->
+ # push the argument
+ push(valueOrPredicate)
+
+ # just like Eval but turns assignments into
+ # equality checks
+ Eval_predicate()
+ evalledArgument = pop()
+
+ # OK first check if we already have
+ # a simple zero (or simple zero tensor)
+ if isZeroAtomOrTensor evalledArgument
+ return 0
+
+ # also check if we have a simple numeric value, or a tensor
+ # full of simple numeric values (i.e. straight doubles or fractions).
+ # In such cases, since we
+ # just excluded they are zero, then we take it as
+ # a "true"
+ if isNumericAtomOrTensor evalledArgument
+ return 1
+
+ # if we are here we are in the case of value that
+ # is not a zero and not a simple numeric value.
+ # e.g. stuff like
+ # 'sqrt(2)', or 'sin(45)' or '1+i', or 'a'
+ # so in such cases let's try to do a float()
+ # so we might get down to a simple numeric value
+ # in some of those cases
+
+ push evalledArgument
+ zzfloat()
+ evalledArgument = pop()
+
+ # anything that could be calculated down to a simple
+ # numeric value is now indeed either a
+ # double OR a double with an imaginary component
+ # e.g. 2.0 or 2.4 + i*5.6
+ # (Everything else are things that don't have a numeric
+ # value e.g. 'a+b')
+
+ # So, let's take care of the case where we have
+ # a simple numeric value with NO imaginary component,
+ # things like sqrt(2) or sin(PI)
+ # by doing the simple numeric
+ # values checks again
+
+ if isZeroAtomOrTensor evalledArgument
+ return 0
+
+ if isNumericAtomOrTensor evalledArgument
+ return 1
+
+ # here we still have cases of simple numeric values
+ # WITH an imaginary component e.g. '1+i',
+ # or things that don't have a numeric value e.g. 'a'
+
+ # so now let's take care of the imaginary numbers:
+ # since we JUST have to spot "zeros" we can just
+ # calculate the absolute value and re-do all the checks
+ # we just did
+
+ if Find(evalledArgument, imaginaryunit)
+ push evalledArgument
+ absValFloat()
+
+ Eval_predicate()
+ evalledArgument = pop()
+
+ # re-do the simple-number checks...
+
+ if isZeroAtomOrTensor evalledArgument
+ return 0
+
+ if isNumericAtomOrTensor evalledArgument
+ return 1
+
+ # here we have stuff that is not reconducible to any
+ # numeric value (or tensor with numeric values) e.g.
+ # 'a+b', so it just means that we just don't know the
+ # truth value, so we have
+ # to leave the whole thing unevalled
+ return null
+
+
+# p is a U
+isnegativenumber = (p) ->
+ switch (p.k)
+ when NUM
+ if (MSIGN(p.q.a) == -1)
+ return 1
+ when DOUBLE
+ if (p.d < 0.0)
+ return 1
+ return 0
+
+# p is a U
+ispositivenumber = (p) ->
+ switch (p.k)
+ when NUM
+ if (MSIGN(p.q.a) == 1)
+ return 1
+ when DOUBLE
+ if (p.d > 0.0)
+ return 1
+ return 0
+
+# p is a U
+isplustwo = (p) ->
+ switch (p.k)
+ when NUM
+ if (MEQUAL(p.q.a, 2) && MEQUAL(p.q.b, 1))
+ return 1
+ when DOUBLE
+ if (p.d == 2.0)
+ return 1
+ return 0
+
+# p is a U
+isplusone = (p) ->
+ switch (p.k)
+ when NUM
+ if (MEQUAL(p.q.a, 1) && MEQUAL(p.q.b, 1))
+ return 1
+ when DOUBLE
+ if (p.d == 1.0)
+ return 1
+ return 0
+
+isminusone = (p) ->
+ switch (p.k)
+ when NUM
+ if (MEQUAL(p.q.a, -1) && MEQUAL(p.q.b, 1))
+ return 1
+ when DOUBLE
+ if (p.d == -1.0)
+ return 1
+ return 0
+
+isone = (p) ->
+ return isplusone(p) or isminusone(p)
+
+isinteger = (p) ->
+ if (p.k == NUM && MEQUAL(p.q.b, 1))
+ return 1
+ else
+ return 0
+
+isintegerorintegerfloat = (p) ->
+ if p.k == DOUBLE
+ if (p.d == Math.round(p.d))
+ return 1
+ return 0
+ return isinteger(p)
+
+isnonnegativeinteger = (p) ->
+ if (isrational(p) && MEQUAL(p.q.b, 1) && MSIGN(p.q.a) == 1)
+ return 1
+ else
+ return 0
+
+isposint = (p) ->
+ if (isinteger(p) && MSIGN(p.q.a) == 1)
+ return 1
+ else
+ return 0
+
+# --------------------------------------
+
+isunivarpolyfactoredorexpandedform = (p,x) ->
+ if DEBUG then console.log "isunivarpolyfactoredorexpandedform: p: " + p + " x: " + x
+
+ if !x?
+ push p
+ guess()
+ x = pop()
+ pop()
+
+ if ispolyfactoredorexpandedform(p,x) and (Find(p, symbol(SYMBOL_X)) + Find(p, symbol(SYMBOL_Y)) + Find(p, symbol(SYMBOL_Z)) == 1)
+ return x
+ else
+ return 0
+
+# --------------------------------------
+# sometimes we want to check if we have a poly in our
+# hands, however it's in factored form and we don't
+# want to expand it.
+
+ispolyfactoredorexpandedform = (p,x) ->
+ return ispolyfactoredorexpandedform_factor(p, x)
+
+ispolyfactoredorexpandedform_factor = (p,x) ->
+ if (car(p) == symbol(MULTIPLY))
+ p = cdr(p)
+ while (iscons(p))
+ if DEBUG then console.log "ispolyfactoredorexpandedform_factor testing " + car(p)
+ if (!ispolyfactoredorexpandedform_power(car(p), x))
+ if DEBUG then console.log "... tested negative:" + car(p)
+ return 0
+ p = cdr(p)
+ return 1
+ else
+ return ispolyfactoredorexpandedform_power(p, x)
+
+ispolyfactoredorexpandedform_power = (p,x) ->
+ if (car(p) == symbol(POWER))
+ if DEBUG then console.log "ispolyfactoredorexpandedform_power (isposint(caddr(p)) " + (isposint(caddr(p))
+ if DEBUG then console.log "ispolyfactoredorexpandedform_power ispolyexpandedform_expr(cadr(p), x)) " + ispolyexpandedform_expr(cadr(p), x))
+ return (isposint(caddr(p)) and ispolyexpandedform_expr(cadr(p), x))
+ else
+ if DEBUG then console.log "ispolyfactoredorexpandedform_power not a power, testing if this is exp form: " + p
+ return ispolyexpandedform_expr(p, x)
+
+# --------------------------------------
+
+ispolyexpandedform = (p,x) ->
+ if (Find(p, x))
+ return ispolyexpandedform_expr(p, x)
+ else
+ return 0
+
+
+ispolyexpandedform_expr = (p,x) ->
+ if (car(p) == symbol(ADD))
+ p = cdr(p)
+ while (iscons(p))
+ if (!ispolyexpandedform_term(car(p), x))
+ return 0
+ p = cdr(p)
+ return 1
+ else
+ return ispolyexpandedform_term(p, x)
+
+ispolyexpandedform_term = (p,x) ->
+ if (car(p) == symbol(MULTIPLY))
+ p = cdr(p)
+ while (iscons(p))
+ if (!ispolyexpandedform_factor(car(p), x))
+ return 0
+ p = cdr(p)
+ return 1
+ else
+ return ispolyexpandedform_factor(p, x)
+
+ispolyexpandedform_factor = (p,x) ->
+ if (equal(p, x))
+ return 1
+ if (car(p) == symbol(POWER) && equal(cadr(p), x))
+ if (isposint(caddr(p)))
+ return 1
+ else
+ return 0
+ if (Find(p, x))
+ return 0
+ else
+ return 1
+
+# --------------------------------------
+
+isnegativeterm = (p) ->
+ if (isnegativenumber(p))
+ return 1
+ else if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p)))
+ return 1
+ else
+ return 0
+
+hasNegativeRationalExponent = (p) ->
+ if (car(p) == symbol(POWER) \
+ && isrational(car(cdr(cdr(p)))) \
+ && isnegativenumber(car(cdr(p))))
+ if DEBUG_IS then console.log "hasNegativeRationalExponent: " + p.toString() + " has imaginary component"
+ return 1
+ else
+ if DEBUG_IS then console.log "hasNegativeRationalExponent: " + p.toString() + " has NO imaginary component"
+ return 0
+
+isimaginarynumberdouble = (p) ->
+ if ((car(p) == symbol(MULTIPLY) \
+ && length(p) == 3 \
+ && isdouble(cadr(p)) \
+ && hasNegativeRationalExponent(caddr(p))) \
+ || equal(p, imaginaryunit))
+ return 1
+ else
+ return 0
+
+isimaginarynumber = (p) ->
+ if ((car(p) == symbol(MULTIPLY) \
+ && length(p) == 3 \
+ && isNumericAtom(cadr(p)) \
+ && equal(caddr(p), imaginaryunit)) \
+ || equal(p, imaginaryunit) \
+ || hasNegativeRationalExponent(caddr(p))
+ )
+ if DEBUG_IS then console.log "isimaginarynumber: " + p.toString() + " is imaginary number"
+ return 1
+ else
+ if DEBUG_IS then console.log "isimaginarynumber: " + p.toString() + " isn't an imaginary number"
+ return 0
+
+iscomplexnumberdouble = (p) ->
+ if ((car(p) == symbol(ADD) \
+ && length(p) == 3 \
+ && isdouble(cadr(p)) \
+ && isimaginarynumberdouble(caddr(p))) \
+ || isimaginarynumberdouble(p))
+ return 1
+ else
+ return 0
+
+iscomplexnumber = (p) ->
+ if DEBUG_IS then debugger
+ if ((car(p) == symbol(ADD) \
+ && length(p) == 3 \
+ && isNumericAtom(cadr(p)) \
+ && isimaginarynumber(caddr(p))) \
+ || isimaginarynumber(p))
+ if DEBUG then console.log "iscomplexnumber: " + p.toString() + " is imaginary number"
+ return 1
+ else
+ if DEBUG then console.log "iscomplexnumber: " + p.toString() + " is imaginary number"
+ return 0
+
+iseveninteger = (p) ->
+ if isinteger(p) && p.q.a.isEven()
+ return 1
+ else
+ return 0
+
+isnegative = (p) ->
+ if (car(p) == symbol(ADD) && isnegativeterm(cadr(p)))
+ return 1
+ else if (isnegativeterm(p))
+ return 1
+ else
+ return 0
+
+# returns 1 if there's a symbol somewhere.
+# not used anywhere.
+# NOTE: PI and POWER are symbols,
+# so for example 2^3 would be symbolic
+# while -1^(1/2) i.e. 'i' is not, so this can
+# be tricky to use.
+issymbolic = (p) ->
+ if (issymbol(p))
+ return 1
+ else
+ while (iscons(p))
+ if (issymbolic(car(p)))
+ return 1
+ p = cdr(p)
+ return 0
+
+# i.e. 2, 2^3, etc.
+isintegerfactor = (p) ->
+ isinteger(p) || # note that and takes precedence over or
+ car(p) == symbol(POWER) and
+ isinteger(cadr(p)) and
+ isinteger(caddr(p))
+
+isNumberOneOverSomething = (p) ->
+ isfraction(p) and
+ MEQUAL(p.q.a.abs(), 1)
+
+
+isoneover = (p) ->
+ car(p) == symbol(POWER) and
+ isminusone(caddr(p))
+
+isfraction = (p) ->
+ p.k == NUM && !MEQUAL(p.q.b, 1)
+
+# p is a U, n an int
+equaln = (p,n) ->
+ switch (p.k)
+ when NUM
+ MEQUAL(p.q.a, n) && MEQUAL(p.q.b, 1)
+ when DOUBLE
+ p.d == n
+ else
+ false
+
+# p is a U, a and b ints
+equalq = (p, a, b) ->
+ switch (p.k)
+ when NUM
+ MEQUAL(p.q.a, a) && MEQUAL(p.q.b, b)
+ when DOUBLE
+ p.d == a / b
+ else
+ false
+
+# 1/2 ?
+isoneovertwo = (p) ->
+ equalq(p, 1, 2)
+
+# -1/2 ?
+isminusoneovertwo = (p) ->
+ equalq(p, -1, 2)
+
+# 1/sqrt(2) ?
+isoneoversqrttwo = (p) ->
+ car(p) == symbol(POWER) and
+ equaln(cadr(p), 2) and
+ equalq(caddr(p), -1, 2)
+
+# -1/sqrt(2) ?
+isminusoneoversqrttwo = (p) ->
+ car(p) == symbol(MULTIPLY) and
+ equaln(cadr(p), -1) and
+ isoneoversqrttwo(caddr(p)) and
+ length(p) == 3
+
+# sqrt(3)/2 ?
+issqrtthreeovertwo = (p) ->
+ car(p) == symbol(MULTIPLY) and
+ isoneovertwo(cadr(p)) and
+ issqrtthree(caddr(p)) and
+ length(p) == 3
+
+# -sqrt(3)/2 ?
+isminussqrtthreeovertwo = (p) ->
+ car(p) == symbol(MULTIPLY) and
+ isminusoneovertwo(cadr(p)) and
+ issqrtthree(caddr(p)) and
+ length(p) == 3
+
+# p == sqrt(3) ?
+issqrtthree = (p) ->
+ car(p) == symbol(POWER) and
+ equaln(cadr(p), 3) and
+ isoneovertwo(caddr(p))
+
+isfloating = (p) ->
+ if p.k == DOUBLE or p == symbol(FLOATF)
+ return 1
+ while (iscons(p))
+ if (isfloating(car(p)))
+ return 1
+ p = cdr(p)
+ return 0
+
+isimaginaryunit = (p) ->
+ if (equal(p, imaginaryunit))
+ return 1
+ else
+ return 0
+
+# n/2 * i * pi ?
+
+# return value:
+
+# 0 no
+
+# 1 1
+
+# 2 -1
+
+# 3 i
+
+# 4 -i
+
+isquarterturn = (p) ->
+ n = 0
+ minussign = 0
+
+ if (car(p) != symbol(MULTIPLY))
+ return 0
+
+ if (equal(cadr(p), imaginaryunit))
+
+ if (caddr(p) != symbol(PI))
+ return 0
+
+ if (length(p) != 3)
+ return 0
+
+ return 2
+
+ if (!isNumericAtom(cadr(p)))
+ return 0
+
+ if (!equal(caddr(p), imaginaryunit))
+ return 0
+
+ if (cadddr(p) != symbol(PI))
+ return 0
+
+ if (length(p) != 4)
+ return 0
+
+ push(cadr(p))
+ push_integer(2)
+ multiply()
+
+ n = pop_integer()
+
+ if (isNaN(n))
+ return 0
+
+ if (n < 1)
+ minussign = 1
+ n = -n
+
+ switch (n % 4)
+ when 0
+ n = 1
+ when 1
+ if (minussign)
+ n = 4
+ else
+ n = 3
+ when 2
+ n = 2
+ when 3
+ if (minussign)
+ n = 3
+ else
+ n = 4
+
+ return n
+
+# special multiple of pi?
+
+# returns for the following multiples of pi...
+
+# -4/2 -3/2 -2/2 -1/2 1/2 2/2 3/2 4/2
+
+# 4 1 2 3 1 2 3 4
+
+isnpi = (p) ->
+ n = 0
+ if (p == symbol(PI))
+ return 2
+ if (car(p) == symbol(MULTIPLY) \
+ && isNumericAtom(cadr(p)) \
+ && caddr(p) == symbol(PI) \
+ && length(p) == 3)
+ doNothing = 0
+ else
+ return 0
+ push(cadr(p))
+ push_integer(2)
+ multiply()
+ n = pop_integer()
+ if (isNaN(n))
+ return 0
+ if (n < 0)
+ n = 4 - (-n) % 4
+ else
+ n = 1 + (n - 1) % 4
+ return n
+
+
+
+$.isZeroAtomOrTensor = isZeroAtomOrTensor
+$.isnegativenumber = isnegativenumber
+$.isplusone = isplusone
+$.isminusone = isminusone
+$.isinteger = isinteger
+$.isnonnegativeinteger = isnonnegativeinteger
+$.isposint = isposint
+$.isnegativeterm = isnegativeterm
+$.isimaginarynumber = isimaginarynumber
+$.iscomplexnumber = iscomplexnumber
+$.iseveninteger = iseveninteger
+$.isnegative = isnegative
+$.issymbolic = issymbolic
+$.isintegerfactor = isintegerfactor
+$.isoneover = isoneover
+$.isfraction = isfraction
+$.isoneoversqrttwo = isoneoversqrttwo
+$.isminusoneoversqrttwo = isminusoneoversqrttwo
+$.isfloating = isfloating
+$.isimaginaryunit = isimaginaryunit
+$.isquarterturn = isquarterturn
+$.isnpi = isnpi
+
diff --git a/node_modules/algebrite/sources/isprime.coffee b/node_modules/algebrite/sources/isprime.coffee
new file mode 100644
index 0000000..bd02636
--- /dev/null
+++ b/node_modules/algebrite/sources/isprime.coffee
@@ -0,0 +1,11 @@
+
+
+Eval_isprime = ->
+ push(cadr(p1))
+ Eval()
+ p1 = pop()
+ if (isnonnegativeinteger(p1) && mprime(p1.q.a))
+ push_integer(1)
+ else
+ push_integer(0)
+
diff --git a/node_modules/algebrite/sources/laguerre.coffee b/node_modules/algebrite/sources/laguerre.coffee
new file mode 100644
index 0000000..3a15611
--- /dev/null
+++ b/node_modules/algebrite/sources/laguerre.coffee
@@ -0,0 +1,127 @@
+###
+ Laguerre function
+
+Example
+
+ laguerre(x,3)
+
+Result
+
+ 1 3 3 2
+ - --- x + --- x - 3 x + 1
+ 6 2
+
+The computation uses the following recurrence relation.
+
+ L(x,0,k) = 1
+
+ L(x,1,k) = -x + k + 1
+
+ n*L(x,n,k) = (2*(n-1)+1-x+k)*L(x,n-1,k) - (n-1+k)*L(x,n-2,k)
+
+In the "for" loop i = n-1 so the recurrence relation becomes
+
+ (i+1)*L(x,n,k) = (2*i+1-x+k)*L(x,n-1,k) - (i+k)*L(x,n-2,k)
+###
+
+
+
+Eval_laguerre = ->
+ # 1st arg
+
+ push(cadr(p1))
+ Eval()
+
+ # 2nd arg
+
+ push(caddr(p1))
+ Eval()
+
+ # 3rd arg
+
+ push(cadddr(p1))
+ Eval()
+
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ push_integer(0)
+ else
+ push(p2)
+
+ laguerre()
+
+#define X p1
+#define N p2
+#define K p3
+#define Y p4
+#define Y0 p5
+#define Y1 p6
+
+laguerre = ->
+ n = 0
+ save()
+
+ p3 = pop()
+ p2 = pop()
+ p1 = pop()
+
+ push(p2)
+ n = pop_integer()
+
+ if (n < 0 || isNaN(n))
+ push_symbol(LAGUERRE)
+ push(p1)
+ push(p2)
+ push(p3)
+ list(4)
+ restore()
+ return
+
+ if (issymbol(p1))
+ laguerre2(n)
+ else
+ p4 = p1; # do this when p1 is an expr
+ p1 = symbol(SECRETX)
+ laguerre2(n)
+ p1 = p4
+ push(symbol(SECRETX))
+ push(p1)
+ subst()
+ Eval()
+
+ restore()
+
+laguerre2 = (n) ->
+ i = 0
+
+ push_integer(1)
+ push_integer(0)
+
+ p6 = pop()
+
+ for i in [0...n]
+
+ p5 = p6
+
+ p6 = pop()
+
+ push_integer(2 * i + 1)
+ push(p1)
+ subtract()
+ push(p3)
+ add()
+ push(p6)
+ multiply()
+
+ push_integer(i)
+ push(p3)
+ add()
+ push(p5)
+ multiply()
+
+ subtract()
+
+ push_integer(i + 1)
+ divide()
+
+
diff --git a/node_modules/algebrite/sources/lcm.coffee b/node_modules/algebrite/sources/lcm.coffee
new file mode 100644
index 0000000..901947b
--- /dev/null
+++ b/node_modules/algebrite/sources/lcm.coffee
@@ -0,0 +1,40 @@
+# Find the least common multiple of two expressions.
+
+
+
+Eval_lcm = ->
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ lcm()
+ p1 = cdr(p1)
+
+lcm = ->
+ prev_expanding = expanding
+ save()
+ yylcm()
+ restore()
+ expanding = prev_expanding
+
+yylcm = ->
+ expanding = 1
+
+ p2 = pop()
+ p1 = pop()
+
+ push(p1)
+ push(p2)
+ gcd()
+
+ push(p1)
+ divide()
+
+ push(p2)
+ divide()
+
+ inverse()
+
diff --git a/node_modules/algebrite/sources/leading.coffee b/node_modules/algebrite/sources/leading.coffee
new file mode 100644
index 0000000..b2d2fa6
--- /dev/null
+++ b/node_modules/algebrite/sources/leading.coffee
@@ -0,0 +1,51 @@
+###
+ Return the leading coefficient of a polynomial.
+
+Example
+
+ leading(5x^2+x+1,x)
+
+Result
+
+ 5
+
+The result is undefined if P is not a polynomial.
+###
+
+Eval_leading = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ p1 = pop()
+ if (p1 == symbol(NIL))
+ guess()
+ else
+ push(p1)
+ leading()
+
+#define P p1
+#define X p2
+#define N p3
+
+leading = ->
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ push(p1) # N = degree of P
+ push(p2)
+ degree()
+ p3 = pop()
+
+ push(p1) # divide through by X ^ N
+ push(p2)
+ push(p3)
+ power()
+ divide()
+
+ push(p2) # remove terms that depend on X
+ filter()
+
+ restore()
diff --git a/node_modules/algebrite/sources/legendre.coffee b/node_modules/algebrite/sources/legendre.coffee
new file mode 100644
index 0000000..4ac8925
--- /dev/null
+++ b/node_modules/algebrite/sources/legendre.coffee
@@ -0,0 +1,179 @@
+###
+ Legendre function
+
+Example
+
+ legendre(x,3,0)
+
+Result
+
+ 5 3 3
+ --- x - --- x
+ 2 2
+
+The computation uses the following recurrence relation.
+
+ P(x,0) = 1
+
+ P(x,1) = x
+
+ n*P(x,n) = (2*(n-1)+1)*x*P(x,n-1) - (n-1)*P(x,n-2)
+
+In the "for" loop we have i = n-1 so the recurrence relation becomes
+
+ (i+1)*P(x,n) = (2*i+1)*x*P(x,n-1) - i*P(x,n-2)
+
+For m > 0
+
+ P(x,n,m) = (-1)^m * (1-x^2)^(m/2) * d^m/dx^m P(x,n)
+###
+
+
+
+Eval_legendre = ->
+ # 1st arg
+
+ push(cadr(p1))
+ Eval()
+
+ # 2nd arg
+
+ push(caddr(p1))
+ Eval()
+
+ # 3rd arg (optional)
+
+ push(cadddr(p1))
+ Eval()
+
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ push_integer(0)
+ else
+ push(p2)
+
+ legendre()
+
+#define X p1
+#define N p2
+#define M p3
+#define Y p4
+#define Y0 p5
+#define Y1 p6
+
+
+legendre = ->
+ save()
+ __legendre()
+ restore()
+
+__legendre = ->
+ m = 0
+ n = 0
+
+ p3 = pop()
+ p2 = pop()
+ p1 = pop()
+
+ push(p2)
+ n = pop_integer()
+
+ push(p3)
+ m = pop_integer()
+
+ if (n < 0 || isNaN(n) || m < 0 || isNaN(m))
+ push_symbol(LEGENDRE)
+ push(p1)
+ push(p2)
+ push(p3)
+ list(4)
+ return
+
+ if (issymbol(p1))
+ __legendre2(n, m)
+ else
+ p4 = p1; # do this when X is an expr
+ p1 = symbol(SECRETX)
+ __legendre2(n, m)
+ p1 = p4
+ push(symbol(SECRETX))
+ push(p1)
+ subst()
+ Eval()
+
+ __legendre3(m)
+
+__legendre2 = (n, m) ->
+ i = 0
+
+ push_integer(1)
+ push_integer(0)
+
+ p6 = pop()
+
+ # i=1 p5 = 0
+ # p6 = 1
+ # ((2*i+1)*x*p6 - i*p5) / i = x
+ #
+ # i=2 p5 = 1
+ # p6 = x
+ # ((2*i+1)*x*p6 - i*p5) / i = -1/2 + 3/2*x^2
+ #
+ # i=3 p5 = x
+ # p6 = -1/2 + 3/2*x^2
+ # ((2*i+1)*x*p6 - i*p5) / i = -3/2*x + 5/2*x^3
+
+ for i in [0...n]
+
+ p5 = p6
+
+ p6 = pop()
+
+ push_integer(2 * i + 1)
+ push(p1)
+ multiply()
+ push(p6)
+ multiply()
+
+ push_integer(i)
+ push(p5)
+ multiply()
+
+ subtract()
+
+ push_integer(i + 1)
+ divide()
+
+ for i in [0...m]
+ push(p1)
+ derivative()
+
+# moveTos tos * (-1)^m * (1-x^2)^(m/2)
+
+__legendre3 = (m) ->
+ if (m == 0)
+ return
+
+ if (car(p1) == symbol(COS))
+ push(cadr(p1))
+ sine()
+ square()
+ else if (car(p1) == symbol(SIN))
+ push(cadr(p1))
+ cosine()
+ square()
+ else
+ push_integer(1)
+ push(p1)
+ square()
+ subtract()
+
+ push_integer(m)
+ push_rational(1, 2)
+ multiply()
+ power()
+ multiply()
+
+ if (m % 2)
+ negate()
+
diff --git a/node_modules/algebrite/sources/list.coffee b/node_modules/algebrite/sources/list.coffee
new file mode 100644
index 0000000..0c62c1d
--- /dev/null
+++ b/node_modules/algebrite/sources/list.coffee
@@ -0,0 +1,10 @@
+# Create a list from n things on the stack.
+
+
+
+# n is an integer
+list = (n) ->
+ listIterator = 0
+ push(symbol(NIL))
+ for listIterator in [0...n]
+ cons()
diff --git a/node_modules/algebrite/sources/log.coffee b/node_modules/algebrite/sources/log.coffee
new file mode 100644
index 0000000..9c9fc49
--- /dev/null
+++ b/node_modules/algebrite/sources/log.coffee
@@ -0,0 +1,88 @@
+# Natural logarithm.
+#
+# Note that we use the mathematics / Javascript / Mathematica
+# convention that "log" is indeed the natural logarithm.
+#
+# In engineering, biology, astronomy, "log" can stand instead
+# for the "common" logarithm i.e. base 10. Also note that Google
+# calculations use log for the common logarithm.
+
+
+Eval_log = ->
+ push(cadr(p1))
+ Eval()
+ logarithm()
+
+logarithm = ->
+ save()
+ yylog()
+ restore()
+
+yylog = ->
+ d = 0.0
+
+ p1 = pop()
+
+ if (p1 == symbol(E))
+ push_integer(1)
+ return
+
+ if (equaln(p1, 1))
+ push_integer(0)
+ return
+
+ if (isnegativenumber(p1))
+ push(p1)
+ negate()
+ logarithm()
+ push(imaginaryunit)
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ multiply()
+ add()
+ return
+
+ if (isdouble(p1))
+ d = Math.log(p1.d)
+ push_double(d)
+ return
+
+ # rational number and not an integer?
+
+ if (isfraction(p1))
+ push(p1)
+ numerator()
+ logarithm()
+ push(p1)
+ denominator()
+ logarithm()
+ subtract()
+ return
+
+ # log(a ^ b) --> b log(a)
+
+ if (car(p1) == symbol(POWER))
+ push(caddr(p1))
+ push(cadr(p1))
+ logarithm()
+ multiply()
+ return
+
+ # log(a * b) --> log(a) + log(b)
+
+ if (car(p1) == symbol(MULTIPLY))
+ push_integer(0)
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ logarithm()
+ add()
+ p1 = cdr(p1)
+ return
+
+ push_symbol(LOG)
+ push(p1)
+ list(2)
+
diff --git a/node_modules/algebrite/sources/lookup.coffee b/node_modules/algebrite/sources/lookup.coffee
new file mode 100644
index 0000000..7f1d33b
--- /dev/null
+++ b/node_modules/algebrite/sources/lookup.coffee
@@ -0,0 +1,119 @@
+# now this might be a little confusing, so a
+# clarification is in order.
+# First off, at the scripting level most things
+# as they are handled get evalled.
+# That means that they are recursively "calculated"
+# as much as possible, i.e. variables are recursively
+# looked up for their values, operators are applied,
+# functions are ivoked, etc.
+# I.e. while scripting, most things are
+# evalled all the times.
+# e.g. if I type
+# x = 1+1
+# then x is actually assigned 2, not 1+1
+# Something that helps a little is "quote", e.g.
+# If I assign
+# x = quote(1+1)
+# then x actually contains 1+1, not 2.
+# But then x is evaluated as soon as I type
+# x // gives "2" as x is evaluated
+#
+# Evaluation is great, but sometimes one wants
+# to look at the actual structure of an expression
+# or a content of a variable, without those
+# being evaluated first.
+#
+# for example I might type
+# x = a + b
+# a = 1
+# b = 2
+# and from this point on printing the actual
+# structure of x is impossible, because from
+# now on any evaluation of x will give "3"
+# You might say "but you have x defined up there,
+# what's the point of printing it out?", to which
+# the answer is that one might do further
+# substitutions or transformations of special kind
+# to x. One might want to look at the structure
+# and it might be complex or impossible.
+#
+# So this function does that.
+# If it's passed a variable, then it
+# DOES NOT eval the variable, RATHER
+# it prints the content of the variable without
+# evaluating it.
+# In the other cases it works like "quote" e.g.
+# it just gives the argument as is, again without
+# evaluating it.
+#
+# In the following examples, for brevity, I just
+# use
+# x = quote(1+2)
+# instead of this:
+# x = a + b
+# a = 1
+# b = 2
+# to put a structure in x that is easy to see whether
+# it's avaulated or not.
+#
+# So lookup allows this:
+# x = quote(1+2)
+# print(lookup(x)) # gives 1+2
+#
+# Note that there would be potentially a way
+# to achieve a similar result, you could do:
+# x = quote(quote(1+2))
+# print(x)
+# but you can't always control x to contain
+# two quotes like that...
+# note how two "quotes" are needed because
+# if you just put one, then
+# x would indeed contain 1+2 instead of 3,
+# but then print would evaluate that to 3:
+# x = quote(1+2) # now x contains 1+2, not 3
+# print(x) # but x evaluated here to 3
+#
+# Other workarounds would not work:
+# x = quote(1+2)
+# print(quote(x))
+# would not work because quote(x) literally means 'x'
+# so 'x' is printed instead of its content.
+#
+# Note also that lookup allows you to copy
+# the structure of a variable to another:
+# x = a + b
+# a = 1
+# b = 2
+# now:
+# y = x # y contains the number 3 and prints to 3
+# y = lookup(x) # y contains "a+b" and prints to 3
+# y = quote(x) # y contains "x" and prints to 3
+# note that in the first and second case y is
+# independent from x, i.e. changing x doesn't change y
+# while in the last case it is.
+#
+# Another similar simple example is when doing something
+# like this:
+# x = y
+# y = z
+# x
+# => gives z
+# lookup(x)
+# => gives y
+# i.e. lookup allows you to see the immediate
+# content of x, rather than the evaluation which
+# would end up in x -> y -> z
+# Note that if you invert the order of the assignments i.e.
+# y = z
+# x = y
+# Then at this point x immediately contains z, since the
+# assignment x = y is not quoted, hence y is evaluated to z
+# when assigned to x.
+# lookup(x)
+# => gives z
+
+Eval_lookup = ->
+ p1 = cadr(p1)
+ if !iscons(p1) and cadr(p1).k == SYM
+ p1 = get_binding(p1)
+ push p1
\ No newline at end of file
diff --git a/node_modules/algebrite/sources/madd.coffee b/node_modules/algebrite/sources/madd.coffee
new file mode 100644
index 0000000..40742bf
--- /dev/null
+++ b/node_modules/algebrite/sources/madd.coffee
@@ -0,0 +1,27 @@
+# Bignum addition and subtraction
+
+
+
+#static unsigned int *addf(unsigned int *, unsigned int *)
+#static unsigned int *subf(unsigned int *, unsigned int *)
+#static int ucmp(unsigned int *, unsigned int *)
+
+madd = (a, b) ->
+
+ return a.add b
+
+msub = (a, b) ->
+ return a.subtract b
+
+addf = (a, b) ->
+
+ return a.add b
+
+subf = (a, b) ->
+ return a.subtract b
+
+# unsigned compare
+
+ucmp = (a,b) ->
+ return a.compareAbs b
+
diff --git a/node_modules/algebrite/sources/mainForWebPage.js b/node_modules/algebrite/sources/mainForWebPage.js
new file mode 100644
index 0000000..99fa227
--- /dev/null
+++ b/node_modules/algebrite/sources/mainForWebPage.js
@@ -0,0 +1 @@
+window.Algebrite = require('../dist/algebrite')
\ No newline at end of file
diff --git a/node_modules/algebrite/sources/mgcd.coffee b/node_modules/algebrite/sources/mgcd.coffee
new file mode 100644
index 0000000..fc77071
--- /dev/null
+++ b/node_modules/algebrite/sources/mgcd.coffee
@@ -0,0 +1,25 @@
+#-----------------------------------------------------------------------------
+#
+# Bignum GCD
+#
+# Uses the binary GCD algorithm.
+#
+# See "The Art of Computer Programming" p. 338.
+#
+# mgcd always returns a positive value
+#
+# mgcd(0, 0) = 0
+#
+# mgcd(u, 0) = |u|
+#
+# mgcd(0, v) = |v|
+#
+#-----------------------------------------------------------------------------
+
+
+
+mgcd = (u,v) ->
+ return bigInt.gcd(u,v)
+
+#if SELFTEST
+
diff --git a/node_modules/algebrite/sources/misc.coffee b/node_modules/algebrite/sources/misc.coffee
new file mode 100644
index 0000000..0a32a8a
--- /dev/null
+++ b/node_modules/algebrite/sources/misc.coffee
@@ -0,0 +1,199 @@
+
+
+# s is a string
+new_string = (s) ->
+ theNewString = new U()
+ theNewString.k = STR
+ theNewString.str = s
+ return theNewString
+
+out_of_memory = ->
+ stop("out of memory")
+
+# both ints
+push_zero_matrix = (i,j) ->
+ push(alloc_tensor(i * j))
+ stack[tos - 1].tensor.ndim = 2
+ stack[tos - 1].tensor.dim[0] = i
+ stack[tos - 1].tensor.dim[1] = j
+
+push_identity_matrix = (n) ->
+ push_zero_matrix(n, n)
+ for i in [0...n]
+ stack[tos - 1].tensor.elem[i * n + i] = one
+
+ check_tensor_dimensions stack[tos - 1]
+
+push_cars = (p) ->
+ while (iscons(p))
+ push(car(p))
+ p = cdr(p)
+
+# see cmp_expr definition, this
+# function alone just does simple structure comparison
+# or compares numbers (either rationals or integers or doubles)
+# but can't be used alone to test
+# more complex mathematical equalities...
+equal = (p1,p2) ->
+ if (cmp_expr(p1, p2) == 0)
+ return 1
+ else
+ return 0
+
+lessp = (p1,p2) ->
+ if (cmp_expr(p1, p2) < 0)
+ return 1
+ else
+ return 0
+
+sign = (n) ->
+ if (n < 0)
+ return -1
+ else if (n > 0)
+ return 1
+ else
+ return 0
+
+# compares whether two expressions
+# have the same structure.
+# For example this method alone
+# would compare "1+1" and "2"
+# as different.
+# It just so happens though that one oftens
+# evaluates the two sides before passing them
+# to this function, so chances are that the two
+# sides have the same normal form.
+# Even a simple evaluation might not cut it
+# though... a simplification of both sides
+# would then help. And even that might not
+# cut it in some cases...
+cmp_expr = (p1, p2) ->
+ n = 0
+
+ if (p1 == p2)
+ return 0
+
+ if (p1 == symbol(NIL))
+ return -1
+
+ if (p2 == symbol(NIL))
+ return 1
+
+ if (isNumericAtom(p1) && isNumericAtom(p2))
+ return sign(compare_numbers(p1, p2))
+
+ if (isNumericAtom(p1))
+ return -1
+
+ if (isNumericAtom(p2))
+ return 1
+
+ if (isstr(p1) && isstr(p2))
+ return sign(strcmp(p1.str,p2.str))
+
+ if (isstr(p1))
+ return -1
+
+ if (isstr(p2))
+ return 1
+
+ if (issymbol(p1) && issymbol(p2))
+ return sign(strcmp(get_printname(p1),get_printname(p2)))
+
+ if (issymbol(p1))
+ return -1
+
+ if (issymbol(p2))
+ return 1
+
+ if (istensor(p1) && istensor(p2))
+ return compare_tensors(p1, p2)
+
+ if (istensor(p1))
+ return -1
+
+ if (istensor(p2))
+ return 1
+
+ # recursion here
+ while (iscons(p1) && iscons(p2))
+ n = cmp_expr(car(p1), car(p2))
+ if (n != 0)
+ return n
+ p1 = cdr(p1)
+ p2 = cdr(p2)
+
+ if (iscons(p2))
+ return -1
+
+ if (iscons(p1))
+ return 1
+
+ return 0
+
+length = (p) ->
+ n = 0
+ while (iscons(p))
+ p = cdr(p)
+ n++
+ return n
+
+unique = (p) ->
+ save()
+ p1 = symbol(NIL)
+ p2 = symbol(NIL)
+ unique_f(p)
+ if (p2 != symbol(NIL))
+ p1 = symbol(NIL)
+ p = p1
+ restore()
+ return p
+
+unique_f = (p) ->
+ if (isstr(p))
+ if (p1 == symbol(NIL))
+ p1 = p
+ else if (p != p1)
+ p2 = p
+ return
+ while (iscons(p))
+ unique_f(car(p))
+ if (p2 != symbol(NIL))
+ return
+ p = cdr(p)
+
+
+ssqrt = ->
+ push_rational(1, 2)
+ power()
+
+yyexpand = ->
+ prev_expanding = expanding
+ expanding = 1
+ Eval()
+ expanding = prev_expanding
+
+exponential = ->
+ push_symbol(E)
+ swap()
+ power()
+
+square = ->
+ push_integer(2)
+ power()
+
+#__cmp = (p1, p2) ->
+# return cmp_expr(p1, p2)
+
+# n an integer
+sort_stack = (n) ->
+ #qsort(stack + tos - n, n, sizeof (U *), __cmp)
+
+ h = tos - n
+ subsetOfStack = stack.slice(h,h+n)
+ subsetOfStack.sort(cmp_expr)
+ stack = stack.slice(0,h).concat(subsetOfStack).concat(stack.slice(h+n))
+
+
+$.equal = equal
+$.length = length
diff --git a/node_modules/algebrite/sources/mmul.coffee b/node_modules/algebrite/sources/mmul.coffee
new file mode 100644
index 0000000..42b7aff
--- /dev/null
+++ b/node_modules/algebrite/sources/mmul.coffee
@@ -0,0 +1,75 @@
+# Bignum multiplication and division
+
+
+
+
+
+mmul = (a, b) ->
+ return a.multiply b
+
+
+mdiv = (a, b) ->
+ return a.divide b
+
+# a = a + b
+
+###
+static void
+addf(unsigned int *a, unsigned int *b, int len)
+{
+ int i
+ long long t = 0; # can be signed or unsigned
+ for (i = 0; i < len; i++) {
+ t += (long long) a[i] + b[i]
+ a[i] = (unsigned int) t
+ t >>= 32
+ }
+}
+
+// a = a - b
+
+static void
+subf(unsigned int *a, unsigned int *b, int len)
+{
+ int i
+ long long t = 0; # must be signed
+ for (i = 0; i < len; i++) {
+ t += (long long) a[i] - b[i]
+ a[i] = (unsigned int) t
+ t >>= 32
+ }
+}
+
+// a = b * c
+
+// 0xffffffff + 0xffffffff * 0xffffffff == 0xffffffff00000000
+
+static void
+mulf(unsigned int *a, unsigned int *b, int len, unsigned int c)
+{
+ int i
+ unsigned long long t = 0; # must be unsigned
+ for (i = 0; i < len; i++) {
+ t += (unsigned long long) b[i] * c
+ a[i] = (unsigned int) t
+ t >>= 32
+ }
+ a[i] = (unsigned int) t
+}
+###
+
+mmod = (a,b) ->
+ return a.mod b
+
+# return both quotient and remainder of a/b
+# we'd have this method as divmod(number)
+# but obviously doesn't change the passed parameters
+
+mdivrem = (a,b) ->
+ toReturn = a.divmod b
+ return [toReturn.quotient, toReturn.remainder]
+
+#if SELFTEST
+
+# small integer tests
+
diff --git a/node_modules/algebrite/sources/mod.coffee b/node_modules/algebrite/sources/mod.coffee
new file mode 100644
index 0000000..fd27965
--- /dev/null
+++ b/node_modules/algebrite/sources/mod.coffee
@@ -0,0 +1,55 @@
+
+
+Eval_mod = ->
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ mod()
+
+mod = ->
+ n = 0
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ if (isZeroAtomOrTensor(p2))
+ stop("mod function: divide by zero")
+
+ if (!isNumericAtom(p1) || !isNumericAtom(p2))
+ push_symbol(MOD)
+ push(p1)
+ push(p2)
+ list(3)
+ restore()
+ return
+
+ if (isdouble(p1))
+ push(p1)
+ n = pop_integer()
+ if (isNaN(n))
+ stop("mod function: cannot convert float value to integer")
+ push_integer(n)
+ p1 = pop()
+
+ if (isdouble(p2))
+ push(p2)
+ n = pop_integer()
+ if (isNaN(n))
+ stop("mod function: cannot convert float value to integer")
+ push_integer(n)
+ p2 = pop()
+
+ if (!isinteger(p1) || !isinteger(p2))
+ stop("mod function: integer arguments expected")
+
+ p3 = new U()
+ p3.k = NUM
+ p3.q.a = mmod(p1.q.a, p2.q.a)
+ p3.q.b = mint(1)
+ push(p3)
+
+ restore()
+
diff --git a/node_modules/algebrite/sources/mpow.coffee b/node_modules/algebrite/sources/mpow.coffee
new file mode 100644
index 0000000..3a9799f
--- /dev/null
+++ b/node_modules/algebrite/sources/mpow.coffee
@@ -0,0 +1,11 @@
+# Bignum power
+
+
+
+# a is a bigint, n is a small normal int
+mpow = (a,n) ->
+
+ return a.pow n
+
+#if SELFTEST
+
diff --git a/node_modules/algebrite/sources/mprime.coffee b/node_modules/algebrite/sources/mprime.coffee
new file mode 100644
index 0000000..fd3a32a
--- /dev/null
+++ b/node_modules/algebrite/sources/mprime.coffee
@@ -0,0 +1,13 @@
+# Bignum prime test (returns 1 if prime, 0 if not)
+
+# Uses Algorithm P (probabilistic primality test) from p. 395 of
+# "The Art of Computer Programming, Volume 2" by Donald E. Knuth.
+
+
+
+
+mprime = (n) ->
+ return n.isProbablePrime()
+
+#if SELFTEST
+
diff --git a/node_modules/algebrite/sources/mroot.coffee b/node_modules/algebrite/sources/mroot.coffee
new file mode 100644
index 0000000..6a6c1b4
--- /dev/null
+++ b/node_modules/algebrite/sources/mroot.coffee
@@ -0,0 +1,63 @@
+#-----------------------------------------------------------------------------
+#
+# Bignum root
+#
+# Returns null pointer if not perfect root.
+#
+# The sign of the radicand is ignored.
+#
+#-----------------------------------------------------------------------------
+
+
+mroot = (n, index) ->
+ # this doesn't quite work
+ #return n.pow(1/index + 0.0000000000000001)
+
+ # sign of radicand ignored
+ n = n.abs()
+
+ i = 0
+ j = 0
+ k = 0
+
+ if (index == 0)
+ stop("root index is zero")
+
+ # count number of bits
+ k = 0
+ while n.shiftRight(k) > 0
+ k++
+
+ if (k == 0)
+ return mint(0)
+
+ # initial guess
+
+ k = Math.floor((k - 1) / index)
+
+ j = Math.floor(k / 32 + 1)
+ x = bigInt(j)
+
+ for i in [0...j]
+ # zero-out the ith bit
+ x = x.and(bigInt(1).shiftLeft(i).not())
+
+ while (k >= 0)
+ # set the kth bit
+ x = x.or(bigInt(1).shiftLeft(k))
+
+ y = mpow(x, index)
+ switch (mcmp(y, n))
+ when 0
+ return x
+ when 1
+ #mp_clr_bit(x, k)
+ # clear the kth bit
+ x = x.and(bigInt(1).shiftLeft(k).not())
+ k--
+
+ return 0
+
+
+#if SELFTEST
+
diff --git a/node_modules/algebrite/sources/multiply.coffee b/node_modules/algebrite/sources/multiply.coffee
new file mode 100644
index 0000000..074763e
--- /dev/null
+++ b/node_modules/algebrite/sources/multiply.coffee
@@ -0,0 +1,619 @@
+# Symbolic multiplication
+
+# multiplication is commutative, so it can't be used
+# e.g. on two matrices.
+# But it can be used, say, on a scalar and a matrix.,
+# so the output of a multiplication is not
+# always a scalar.
+
+#extern void append(void)
+#static void parse_p1(void)
+#static void parse_p2(void)
+#static void __normalize_radical_factors(int)
+
+DEBUG_MULTIPLY = false
+
+Eval_multiply = ->
+ push(cadr(p1))
+ Eval()
+ p1 = cddr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ multiply()
+ p1 = cdr(p1)
+
+# this one doesn't eval the factors,
+# so you pass i*(-1)^(1/2), it wouldnt't
+# give -1, because i is not evalled
+multiply = ->
+ if (esc_flag)
+ stop("escape key stop")
+ if (isNumericAtom(stack[tos - 2]) && isNumericAtom(stack[tos - 1]))
+ multiply_numbers()
+ else
+ save()
+ yymultiply()
+ restore()
+
+yymultiply = ->
+ h = 0
+ i = 0
+ n = 0
+
+ # pop operands
+
+ p2 = pop()
+ p1 = pop()
+
+ h = tos
+
+ # is either operand zero?
+
+ if (isZeroAtom(p1) || isZeroAtom(p2))
+ if evaluatingAsFloats then push_double(0.0) else push(zero)
+ return
+
+ # is either operand a sum?
+
+ #console.log("yymultiply: expanding: " + expanding)
+ if (expanding && isadd(p1))
+ p1 = cdr(p1)
+ if evaluatingAsFloats then push_double(0.0) else push(zero)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ multiply()
+ add()
+ p1 = cdr(p1)
+ return
+
+ if (expanding && isadd(p2))
+ p2 = cdr(p2)
+ if evaluatingAsFloats then push_double(0.0) else push(zero)
+ while (iscons(p2))
+ push(p1)
+ push(car(p2))
+ multiply()
+ add()
+ p2 = cdr(p2)
+ return
+
+ # scalar times tensor?
+
+ if (!istensor(p1) && istensor(p2))
+ push(p1)
+ push(p2)
+ scalar_times_tensor()
+ return
+
+ # tensor times scalar?
+
+ if (istensor(p1) && !istensor(p2))
+ push(p1)
+ push(p2)
+ tensor_times_scalar()
+ return
+
+ # adjust operands
+
+ if (car(p1) == symbol(MULTIPLY))
+ p1 = cdr(p1)
+ else
+ push(p1)
+ list(1)
+ p1 = pop()
+
+ if (car(p2) == symbol(MULTIPLY))
+ p2 = cdr(p2)
+ else
+ push(p2)
+ list(1)
+ p2 = pop()
+
+ # handle numerical coefficients
+
+ if (isNumericAtom(car(p1)) && isNumericAtom(car(p2)))
+ push(car(p1))
+ push(car(p2))
+ multiply_numbers()
+ p1 = cdr(p1)
+ p2 = cdr(p2)
+ else if (isNumericAtom(car(p1)))
+ push(car(p1))
+ p1 = cdr(p1)
+ else if (isNumericAtom(car(p2)))
+ push(car(p2))
+ p2 = cdr(p2)
+ else
+ if evaluatingAsFloats then push_double(1.0) else push(one)
+
+ parse_p1()
+ parse_p2()
+
+ while (iscons(p1) && iscons(p2))
+
+ # if (car(p1)->gamma && car(p2)->gamma) {
+ # combine_gammas(h)
+ # p1 = cdr(p1)
+ # p2 = cdr(p2)
+ # parse_p1()
+ # parse_p2()
+ # continue
+ # }
+
+ if (caar(p1) == symbol(OPERATOR) && caar(p2) == symbol(OPERATOR))
+ push_symbol(OPERATOR)
+ push(cdar(p1))
+ push(cdar(p2))
+ append()
+ cons()
+ p1 = cdr(p1)
+ p2 = cdr(p2)
+ parse_p1()
+ parse_p2()
+ continue
+
+ switch (cmp_expr(p3, p4))
+ when -1
+ push(car(p1))
+ p1 = cdr(p1)
+ parse_p1()
+ when 1
+ push(car(p2))
+ p2 = cdr(p2)
+ parse_p2()
+ when 0
+ combine_factors(h)
+ p1 = cdr(p1)
+ p2 = cdr(p2)
+ parse_p1()
+ parse_p2()
+ else
+ stop("internal error 2")
+
+ # push remaining factors, if any
+
+ while (iscons(p1))
+ push(car(p1))
+ p1 = cdr(p1)
+
+ while (iscons(p2))
+ push(car(p2))
+ p2 = cdr(p2)
+
+ # normalize radical factors
+
+ # example: 2*2(-1/2) -> 2^(1/2)
+
+ # must be done after merge because merge may produce radical
+
+ # example: 2^(1/2-a)*2^a -> 2^(1/2)
+
+ __normalize_radical_factors(h)
+
+ # this hack should not be necessary, unless power returns a multiply
+
+ #for (i = h; i < tos; i++) {
+ # if (car(stack[i]) == symbol(MULTIPLY)) {
+ # multiply_all(tos - h)
+ # return
+ # }
+ #}
+
+ if (expanding)
+ for i in [h...tos]
+ if (isadd(stack[i]))
+ multiply_all(tos - h)
+ return
+
+ # n is the number of result factors on the stack
+
+ n = tos - h
+
+ if (n == 1)
+ return
+
+ # discard integer 1
+
+ if (isrational(stack[h]) && equaln(stack[h], 1))
+ if (n == 2)
+ p7 = pop()
+ pop()
+ push(p7)
+ else
+ stack[h] = symbol(MULTIPLY)
+ list(n)
+ return
+
+ list(n)
+ p7 = pop()
+ push_symbol(MULTIPLY)
+ push(p7)
+ cons()
+
+# Decompose a factor into base and power.
+#
+# input: car(p1) factor
+#
+# output: p3 factor's base
+#
+# p5 factor's power (possibly 1)
+
+parse_p1 = ->
+ p3 = car(p1)
+ p5 = if evaluatingAsFloats then one_as_double else one
+ if (car(p3) == symbol(POWER))
+ p5 = caddr(p3)
+ p3 = cadr(p3)
+
+# Decompose a factor into base and power.
+#
+# input: car(p2) factor
+#
+# output: p4 factor's base
+#
+# p6 factor's power (possibly 1)
+
+parse_p2 = ->
+ p4 = car(p2)
+ p6 = if evaluatingAsFloats then one_as_double else one
+ if (car(p4) == symbol(POWER))
+ p6 = caddr(p4)
+ p4 = cadr(p4)
+
+# h an integer
+combine_factors = (h) ->
+ push(p4)
+ push(p5)
+ push(p6)
+ add()
+ power()
+ p7 = pop()
+ if (isNumericAtom(p7))
+ push(stack[h])
+ push(p7)
+ multiply_numbers()
+ stack[h] = pop()
+ else if (car(p7) == symbol(MULTIPLY))
+ # power can return number * factor (i.e. -1 * i)
+ if (isNumericAtom(cadr(p7)) && cdddr(p7) == symbol(NIL))
+ push(stack[h])
+ push(cadr(p7))
+ multiply_numbers()
+ stack[h] = pop()
+ push(caddr(p7))
+ else
+ push(p7)
+ else
+ push(p7)
+
+gp = [
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+ [0,0,1,-6,-7,-8,-3,-4,-5,13,14,15,-16,9,10,11,-12],
+ [0,0,6,-1,-11,10,-2,-15,14,12,-5,4,-9,16,-8,7,-13],
+ [0,0,7,11,-1,-9,15,-2,-13,5,12,-3,-10,8,16,-6,-14],
+ [0,0,8,-10,9,-1,-14,13,-2,-4,3,12,-11,-7,6,16,-15],
+ [0,0,3,2,15,-14,1,11,-10,16,-8,7,13,12,-5,4,9],
+ [0,0,4,-15,2,13,-11,1,9,8,16,-6,14,5,12,-3,10],
+ [0,0,5,14,-13,2,10,-9,1,-7,6,16,15,-4,3,12,11],
+ [0,0,13,12,-5,4,16,-8,7,-1,-11,10,-3,-2,-15,14,-6],
+ [0,0,14,5,12,-3,8,16,-6,11,-1,-9,-4,15,-2,-13,-7],
+ [0,0,15,-4,3,12,-7,6,16,-10,9,-1,-5,-14,13,-2,-8],
+ [0,0,16,-9,-10,-11,-13,-14,-15,-3,-4,-5,1,-6,-7,-8,2],
+ [0,0,9,-16,8,-7,-12,5,-4,-2,-15,14,6,-1,-11,10,3],
+ [0,0,10,-8,-16,6,-5,-12,3,15,-2,-13,7,11,-1,-9,4],
+ [0,0,11,7,-6,-16,4,-3,-12,-14,13,-2,8,-10,9,-1,5],
+ [0,0,12,13,14,15,9,10,11,-6,-7,-8,-2,-3,-4,-5,-1]
+]
+
+#if 0
+
+# h an int
+combine_gammas = (h) ->
+ n = gp[Math.floor(p1.gamma)][Math.floor(p2.gamma)]
+ if (n < 0)
+ n = -n
+ push(stack[h])
+ negate()
+ stack[h] = pop()
+ if (n > 1)
+ push(_gamma[n])
+
+# this is useful for example when you are just adding/removing
+# factors from an already factored quantity.
+# e.g. if you factored x^2 + 3x + 2 into (x+1)(x+2)
+# and you want to divide by (x+1) , i.e. you multiply by (x-1)^-1,
+# then there is no need to expand.
+
+multiply_noexpand = ->
+ prev_expanding = expanding
+ expanding = 0
+ multiply()
+ expanding = prev_expanding
+
+# multiply n factors on stack
+
+# n an integer
+multiply_all = (n) ->
+ i = 0
+ if (n == 1)
+ return
+ if (n == 0)
+ push if evaluatingAsFloats then one_as_double else one
+ return
+ h = tos - n
+ push(stack[h])
+ for i in [1...n]
+ push(stack[h + i])
+ multiply()
+ stack[h] = pop()
+ moveTos h + 1
+
+# n an integer
+multiply_all_noexpand = (n) ->
+ prev_expanding = expanding
+ expanding = 0
+ multiply_all(n)
+ expanding = prev_expanding
+
+#-----------------------------------------------------------------------------
+#
+# Symbolic division, or numeric division if doubles are found.
+#
+# Input: Dividend and divisor on stack
+#
+# Output: Quotient on stack
+#
+#-----------------------------------------------------------------------------
+
+divide = ->
+ if (isNumericAtom(stack[tos - 2]) && isNumericAtom(stack[tos - 1]))
+ divide_numbers()
+ else
+ inverse()
+ multiply()
+
+# this is different from inverse of a matrix (inv)!
+inverse = ->
+ if (isNumericAtom(stack[tos - 1]))
+ invert_number()
+ else
+ push_integer(-1)
+ power()
+
+reciprocate = ->
+ inverse()
+
+negate = ->
+ if (isNumericAtom(stack[tos - 1]))
+ negate_number()
+ else
+ if evaluatingAsFloats then push_double(-1.0) else push_integer(-1)
+ multiply()
+
+negate_expand = ->
+ prev_expanding = expanding
+ expanding = 1
+ negate()
+ expanding = prev_expanding
+
+negate_noexpand = ->
+ prev_expanding = expanding
+ expanding = 0
+ negate()
+ expanding = prev_expanding
+
+#-----------------------------------------------------------------------------
+#
+# Normalize radical factors
+#
+# Input: stack[h] Coefficient factor, possibly 1
+#
+# stack[h + 1] Second factor
+#
+# stack[tos - 1] Last factor
+#
+# Output: Reduced coefficent and normalized radicals (maybe)
+#
+# Example: 2*2^(-1/2) -> 2^(1/2)
+#
+# (power number number) is guaranteed to have the following properties:
+#
+# 1. Base is an integer
+#
+# 2. Absolute value of exponent < 1
+#
+# These properties are assured by the power function.
+#
+#-----------------------------------------------------------------------------
+
+#define A p1
+#define B p2
+
+#define BASE p3
+#define EXPO p4
+
+#define TMP p5
+
+
+# h is an int
+__normalize_radical_factors = (h) ->
+
+ i = 0
+ # if coeff is 1 or floating then don't bother
+
+ if (isplusone(stack[h]) || isminusone(stack[h]) || isdouble(stack[h]))
+ return
+
+ # if no radicals then don't bother
+
+ for i in [(h + 1)...tos]
+ if (__is_radical_number(stack[i]))
+ break
+
+ if (i == tos)
+ return
+
+ # ok, try to simplify
+
+ save()
+
+ # numerator
+
+ push(stack[h])
+ mp_numerator()
+ if DEBUG_MULTIPLY then console.log("__normalize_radical_factors numerator: " + stack[tos-1])
+ p1 = pop(); # p1 is A
+
+ for i in [(h + 1)...tos]
+
+ if (isplusone(p1) || isminusone(p1)) # p1 is A
+ break
+
+ if (!__is_radical_number(stack[i]))
+ continue
+
+ p3 = cadr(stack[i]); #p3 is BASE
+ p4 = caddr(stack[i]); #p4 is EXPO
+
+ # exponent must be negative
+
+ if (!isnegativenumber(p4)) #p4 is EXPO
+ continue
+
+ # numerator divisible by p3 (base)?
+
+ push(p1); # p1 is A
+ push(p3); #p3 is BASE
+ divide()
+
+ p5 = pop(); #p5 is TMP
+
+ if (!isinteger(p5)) #p5 is TMP
+ continue
+
+ # reduce numerator
+
+ p1 = p5; # p1 is A #p5 is TMP
+
+ # invert radical
+
+ push_symbol(POWER)
+ push(p3); #p3 is BASE
+ push if evaluatingAsFloats then one_as_double else one
+ push(p4); #p4 is EXPO
+ add()
+ list(3)
+ stack[i] = pop()
+
+ # denominator
+
+ push(stack[h])
+ mp_denominator()
+ if DEBUG_MULTIPLY then console.log("__normalize_radical_factors denominator: " + stack[tos-1])
+ p2 = pop(); # p2 is B
+
+ for i in [(h + 1)...tos]
+
+ if (isplusone(p2)) # p2 is B
+ break
+
+ if (!__is_radical_number(stack[i]))
+ continue
+
+ p3 = cadr(stack[i]); #p3 is BASE
+ p4 = caddr(stack[i]); #p4 is EXPO
+
+ # exponent must be positive
+
+ if (isnegativenumber(p4)) #p4 is EXPO
+ continue
+
+ # denominator divisible by p3? #p3 is BASE
+
+ push(p2); # p2 is B
+ push(p3); #p3 is BASE
+ divide()
+
+ p5 = pop(); #p5 is TMP
+
+ if (!isinteger(p5)) #p5 is TMP
+ continue
+ if DEBUG_MULTIPLY then console.log("__new radical p5: " + p5.toString())
+ if DEBUG_MULTIPLY then console.log("__new radical top stack: " + stack[tos-1])
+
+ # reduce denominator
+
+ p2 = p5; # p2 is B #p5 is TMP
+
+ # invert radical
+
+ push_symbol(POWER)
+ push(p3); #p3 is BASE
+ push(p4); #p4 is EXPO
+ if DEBUG_MULTIPLY then console.log("__new radical p3: " + p3.toString())
+ if DEBUG_MULTIPLY then console.log("__new radical p4: " + p4.toString())
+ push(one)
+ subtract()
+
+ if dontCreateNewRadicalsInDenominatorWhenEvalingMultiplication
+ if (isinteger(p3) and !isinteger(stack[tos-1]) and isnegativenumber(stack[tos - 1]))
+ # bail out,
+ # we want to avoid going ahead with the subtraction of
+ # the exponents, because that would turn a perfectly good
+ # integer exponent in the denominator into a fractional one
+ # i.e. a radical.
+ # Note that this only prevents new radicals ending up
+ # in the denominator, it doesn't fix existing ones.
+ pop()
+ pop()
+ pop()
+
+ push(p1); # p1 is A
+ push(p3); #p3 is BASE
+ divide()
+ p1 = pop()
+
+ break
+ if DEBUG_MULTIPLY then console.log("__new radical exponent: " + stack[tos-1])
+
+ list(3)
+ stack[i] = pop()
+
+ # reconstitute the coefficient
+
+ push(p1); # p1 is A
+ push(p2); # p2 is B
+ divide()
+ stack[h] = pop()
+
+ restore()
+
+# don't include i
+# p is a U
+# TODO should this be in is.coffee ?
+__is_radical_number = (p) ->
+ # don't use i
+ car(p) == symbol(POWER) && isNumericAtom(cadr(p)) && isfraction(caddr(p)) && !isminusone(cadr(p))
+
+#-----------------------------------------------------------------------------
+#
+# > a*hilbert(2)
+# ((a,1/2*a),(1/2*a,1/3*a))
+#
+# Note that "a" is presumed to be a scalar. Is this correct?
+#
+# Yes, because "*" has no meaning if "a" is a tensor.
+# To multiply tensors, "dot" or "outer" should be used.
+#
+# > dot(a,hilbert(2))
+# dot(a,((1,1/2),(1/2,1/3)))
+#
+# In this case "a" could be a scalar or tensor so the result is not
+# expanded.
+#
+#-----------------------------------------------------------------------------
+
+
diff --git a/node_modules/algebrite/sources/nroots.coffee b/node_modules/algebrite/sources/nroots.coffee
new file mode 100644
index 0000000..768e0a4
--- /dev/null
+++ b/node_modules/algebrite/sources/nroots.coffee
@@ -0,0 +1,260 @@
+# find the roots of a polynomial numerically
+
+
+
+NROOTS_YMAX = 101
+NROOTS_DELTA = 1.0e-6
+NROOTS_EPSILON = 1.0e-9
+NROOTS_ABS = (z) ->
+ return Math.sqrt((z).r * (z).r + (z).i * (z).i)
+
+# random between -2 and 2
+theRandom = 0.0
+
+NROOTS_RANDOM = ->
+ #theRandom += 0.2
+ #return theRandom
+ return 4.0 * Math.random() - 2.0
+
+class numericRootOfPolynomial
+ r: 0.0
+ i: 0.0
+
+nroots_a = new numericRootOfPolynomial()
+nroots_b = new numericRootOfPolynomial()
+nroots_x = new numericRootOfPolynomial()
+nroots_y = new numericRootOfPolynomial()
+nroots_fa = new numericRootOfPolynomial()
+nroots_fb = new numericRootOfPolynomial()
+nroots_dx = new numericRootOfPolynomial()
+nroots_df = new numericRootOfPolynomial()
+nroots_c = []
+for initNRoots in [0...NROOTS_YMAX]
+ nroots_c[initNRoots] = new numericRootOfPolynomial()
+
+Eval_nroots = ->
+ h = 0
+ i = 0
+ k = 0
+ n = 0
+
+ push(cadr(p1))
+ Eval()
+
+ push(caddr(p1))
+ Eval()
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ guess()
+ else
+ push(p2)
+
+ p2 = pop()
+ p1 = pop()
+
+ if (!ispolyexpandedform(p1, p2))
+ stop("nroots: polynomial?")
+
+ # mark the stack
+
+ h = tos
+
+ # get the coefficients
+
+ n = coeff(p2, p1)
+ if (n > NROOTS_YMAX)
+ stop("nroots: degree?")
+
+ # convert the coefficients to real and imaginary doubles
+
+ for i in [0...n]
+ push(stack[h + i])
+ real()
+ yyfloat()
+ Eval()
+ p1 = pop()
+ push(stack[h + i])
+ imag()
+ yyfloat()
+ Eval()
+ p2 = pop()
+ if (!isdouble(p1) || !isdouble(p2))
+ stop("nroots: coefficients?")
+ nroots_c[i].r = p1.d
+ nroots_c[i].i = p2.d
+
+ # pop the coefficients
+
+ moveTos h
+
+ # n is the number of coefficients, n = deg(p) + 1
+
+ monic(n)
+
+ for k in [n...1] by -1
+ findroot(k)
+ if (Math.abs(nroots_a.r) < NROOTS_DELTA)
+ nroots_a.r = 0.0
+ if (Math.abs(nroots_a.i) < NROOTS_DELTA)
+ nroots_a.i = 0.0
+ push_double(nroots_a.r)
+ push_double(nroots_a.i)
+ push(imaginaryunit)
+ multiply()
+ add()
+ NROOTS_divpoly(k)
+
+ # now make n equal to the number of roots
+
+ n = tos - h
+
+ if (n > 1)
+ sort_stack(n)
+ p1 = alloc_tensor(n)
+ p1.tensor.ndim = 1
+ p1.tensor.dim[0] = n
+ for i in [0...n]
+ p1.tensor.elem[i] = stack[h + i]
+ moveTos h
+ push(p1)
+
+# divide the polynomial by its leading coefficient
+
+monic = (n) ->
+ k = 0
+ t = 0.0
+ nroots_y.r = nroots_c[n - 1].r
+ nroots_y.i = nroots_c[n - 1].i
+ t = nroots_y.r * nroots_y.r + nroots_y.i * nroots_y.i
+ for k in [0...(n - 1)]
+ nroots_c[k].r = (nroots_c[k].r * nroots_y.r + nroots_c[k].i * nroots_y.i) / t
+ nroots_c[k].i = (nroots_c[k].i * nroots_y.r - nroots_c[k].r * nroots_y.i) / t
+ nroots_c[n - 1].r = 1.0
+ nroots_c[n - 1].i = 0.0
+
+# uses the secant method
+
+findroot = (n) ->
+ j = 0
+ k = 0
+ t = 0.0
+
+ if (NROOTS_ABS(nroots_c[0]) < NROOTS_DELTA)
+ nroots_a.r = 0.0
+ nroots_a.i = 0.0
+ return
+
+ for j in [0...100]
+
+ nroots_a.r = NROOTS_RANDOM()
+ nroots_a.i = NROOTS_RANDOM()
+
+ compute_fa(n)
+
+ nroots_b.r = nroots_a.r
+ nroots_b.i = nroots_a.i
+
+ nroots_fb.r = nroots_fa.r
+ nroots_fb.i = nroots_fa.i
+
+ nroots_a.r = NROOTS_RANDOM()
+ nroots_a.i = NROOTS_RANDOM()
+
+ for k in [0...1000]
+
+ compute_fa(n)
+
+ nrabs = NROOTS_ABS(nroots_fa)
+ if DEBUG then console.log "nrabs: " + nrabs
+ if ( nrabs < NROOTS_EPSILON)
+ return
+
+ if (NROOTS_ABS(nroots_fa) < NROOTS_ABS(nroots_fb))
+ nroots_x.r = nroots_a.r
+ nroots_x.i = nroots_a.i
+
+ nroots_a.r = nroots_b.r
+ nroots_a.i = nroots_b.i
+
+ nroots_b.r = nroots_x.r
+ nroots_b.i = nroots_x.i
+
+ nroots_x.r = nroots_fa.r
+ nroots_x.i = nroots_fa.i
+
+ nroots_fa.r = nroots_fb.r
+ nroots_fa.i = nroots_fb.i
+
+ nroots_fb.r = nroots_x.r
+ nroots_fb.i = nroots_x.i
+
+ # dx = nroots_b - nroots_a
+
+ nroots_dx.r = nroots_b.r - nroots_a.r
+ nroots_dx.i = nroots_b.i - nroots_a.i
+
+ # df = fb - fa
+
+ nroots_df.r = nroots_fb.r - nroots_fa.r
+ nroots_df.i = nroots_fb.i - nroots_fa.i
+
+ # y = dx / df
+
+ t = nroots_df.r * nroots_df.r + nroots_df.i * nroots_df.i
+
+ if (t == 0.0)
+ break
+
+ nroots_y.r = (nroots_dx.r * nroots_df.r + nroots_dx.i * nroots_df.i) / t
+ nroots_y.i = (nroots_dx.i * nroots_df.r - nroots_dx.r * nroots_df.i) / t
+
+ # a = b - y * fb
+
+ nroots_a.r = nroots_b.r - (nroots_y.r * nroots_fb.r - nroots_y.i * nroots_fb.i)
+ nroots_a.i = nroots_b.i - (nroots_y.r * nroots_fb.i + nroots_y.i * nroots_fb.r)
+
+ stop("nroots: convergence error")
+
+compute_fa = (n) ->
+ k = 0
+ t = 0.0
+
+ # x = a
+
+ nroots_x.r = nroots_a.r
+ nroots_x.i = nroots_a.i
+
+ # fa = c0 + c1 * x
+
+ nroots_fa.r = nroots_c[0].r + nroots_c[1].r * nroots_x.r - nroots_c[1].i * nroots_x.i
+ nroots_fa.i = nroots_c[0].i + nroots_c[1].r * nroots_x.i + nroots_c[1].i * nroots_x.r
+
+ for k in [2...n]
+
+ # x = a * x
+
+ t = nroots_a.r * nroots_x.r - nroots_a.i * nroots_x.i
+ nroots_x.i = nroots_a.r * nroots_x.i + nroots_a.i * nroots_x.r
+ nroots_x.r = t
+
+ # fa += c[k] * x
+
+ nroots_fa.r += nroots_c[k].r * nroots_x.r - nroots_c[k].i * nroots_x.i
+ nroots_fa.i += nroots_c[k].r * nroots_x.i + nroots_c[k].i * nroots_x.r
+
+# divide the polynomial by x - a
+
+NROOTS_divpoly = (n) ->
+ k = 0
+ for k in [(n - 1)...0]
+ nroots_c[k - 1].r += nroots_c[k].r * nroots_a.r - nroots_c[k].i * nroots_a.i
+ nroots_c[k - 1].i += nroots_c[k].i * nroots_a.r + nroots_c[k].r * nroots_a.i
+
+ if (NROOTS_ABS(nroots_c[0]) > NROOTS_DELTA)
+ stop("nroots: residual error")
+
+ for k in [0...(n - 1)]
+ nroots_c[k].r = nroots_c[k + 1].r
+ nroots_c[k].i = nroots_c[k + 1].i
+
+
diff --git a/node_modules/algebrite/sources/numerator.coffee b/node_modules/algebrite/sources/numerator.coffee
new file mode 100644
index 0000000..93ab3f5
--- /dev/null
+++ b/node_modules/algebrite/sources/numerator.coffee
@@ -0,0 +1,38 @@
+
+
+Eval_numerator = ->
+ push(cadr(p1))
+ Eval()
+ numerator()
+
+numerator = ->
+ h = 0
+
+ theArgument = pop()
+
+
+ if (car(theArgument) == symbol(ADD))
+ push(theArgument)
+ #console.trace "rationalising "
+ rationalize()
+ theArgument = pop()
+ #console.log "rationalised: " + theArgument
+
+ if (car(theArgument) == symbol(MULTIPLY) and !isplusone(car(cdr(theArgument))))
+ h = tos
+ theArgument = cdr(theArgument)
+ #console.log "theArgument inside multiply: " + theArgument
+ #console.log "first term: " + car(theArgument)
+
+ while (iscons(theArgument))
+ push(car(theArgument))
+ numerator()
+ theArgument = cdr(theArgument)
+ multiply_all(tos - h)
+ else if (isrational(theArgument))
+ push(theArgument)
+ mp_numerator()
+ else if (car(theArgument) == symbol(POWER) && isnegativeterm(caddr(theArgument)))
+ push(one)
+ else
+ push(theArgument)
diff --git a/node_modules/algebrite/sources/outer.coffee b/node_modules/algebrite/sources/outer.coffee
new file mode 100644
index 0000000..71be3a1
--- /dev/null
+++ b/node_modules/algebrite/sources/outer.coffee
@@ -0,0 +1,70 @@
+# Outer product of tensors
+
+
+
+Eval_outer = ->
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ outer()
+ p1 = cdr(p1)
+
+outer = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ if (istensor(p1) && istensor(p2))
+ yyouter()
+ else
+ push(p1)
+ push(p2)
+ if (istensor(p1))
+ tensor_times_scalar()
+ else if (istensor(p2))
+ scalar_times_tensor()
+ else
+ multiply()
+ restore()
+
+yyouter = ->
+ i = 0
+ j = 0
+ k = 0
+ ndim = 0
+ nelem = 0
+
+ ndim = p1.tensor.ndim + p2.tensor.ndim
+
+ if (ndim > MAXDIM)
+ stop("outer: rank of result exceeds maximum")
+
+ nelem = p1.tensor.nelem * p2.tensor.nelem
+
+ p3 = alloc_tensor(nelem)
+
+ p3.tensor.ndim = ndim
+
+ for i in [0...p1.tensor.ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+
+ j = i
+
+ for i in [0...p2.tensor.ndim]
+ p3.tensor.dim[j + i] = p2.tensor.dim[i]
+
+ k = 0
+
+ for i in [0...p1.tensor.nelem]
+ for j in [0...p2.tensor.nelem]
+ push(p1.tensor.elem[i])
+ push(p2.tensor.elem[j])
+ multiply()
+ p3.tensor.elem[k++] = pop()
+
+ push(p3)
+
+
diff --git a/node_modules/algebrite/sources/partition.coffee b/node_modules/algebrite/sources/partition.coffee
new file mode 100644
index 0000000..ccbcad3
--- /dev/null
+++ b/node_modules/algebrite/sources/partition.coffee
@@ -0,0 +1,48 @@
+###
+ Partition a term
+
+ Input stack:
+
+ term (factor or product of factors)
+
+ free variable
+
+ Output stack:
+
+ constant expression
+
+ variable expression
+###
+
+
+
+partition = ->
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ push_integer(1)
+
+ p3 = pop()
+ p4 = p3
+
+ p1 = cdr(p1)
+
+ while (iscons(p1))
+ if (Find(car(p1), p2))
+ push(p4)
+ push(car(p1))
+ multiply()
+ p4 = pop()
+ else
+ push(p3)
+ push(car(p1))
+ multiply()
+ p3 = pop()
+ p1 = cdr(p1)
+
+ push(p3)
+ push(p4)
+
+ restore()
diff --git a/node_modules/algebrite/sources/pattern.coffee b/node_modules/algebrite/sources/pattern.coffee
new file mode 100644
index 0000000..23e4969
--- /dev/null
+++ b/node_modules/algebrite/sources/pattern.coffee
@@ -0,0 +1,91 @@
+###
+ Add a pattern i.e. a substitution rule.
+ Substitution rule needs a template as first argument
+ and what to transform it to as second argument.
+ Optional third argument is a boolean test which
+ adds conditions to when the rule is applied.
+###
+
+# same as Eval_pattern but only leaves
+# NIL on stack at return, hence gives no
+# printout
+Eval_silentpattern = ->
+ Eval_pattern()
+ pop()
+ push_symbol(NIL)
+
+Eval_pattern = ->
+ # check that the parameters are allright
+ if !iscons(cdr(p1))
+ stop("pattern needs at least a template and a transformed version")
+ firstArgument = car(cdr(p1))
+ secondArgument = car(cdr(cdr(p1)))
+ if secondArgument == symbol(NIL)
+ stop("pattern needs at least a template and a transformed version")
+ # third argument is optional and contains the tests
+ if !iscons(cdr(cdr(p1)))
+ thirdArgument = symbol(NIL)
+ else
+ thirdArgument = car(cdr(cdr(cdr(p1))))
+
+ if equal(firstArgument, secondArgument)
+ stop("recursive pattern")
+
+ # console.log "Eval_pattern of " + cdr(p1)
+ # this is likely to create garbage collection
+ # problems in the C version as it's an
+ # untracked reference
+ stringKey = "template: " + print_list(firstArgument)
+ stringKey += " tests: " + print_list(thirdArgument)
+ if DEBUG then console.log "pattern stringkey: " + stringKey
+
+ patternPosition = userSimplificationsInStringForm.indexOf stringKey
+ # if pattern is not there yet, add it, otherwise replace it
+ if patternPosition == -1
+ #console.log "adding pattern because it doesn't exist: " + cdr(p1)
+ userSimplificationsInStringForm.push(stringKey)
+ userSimplificationsInListForm.push(cdr(p1))
+ else
+ if DEBUG then console.log "pattern already exists, replacing. " + cdr(p1)
+ userSimplificationsInStringForm[patternPosition] = stringKey
+ userSimplificationsInListForm[patternPosition] = cdr(p1)
+
+ # return the pattern node itself so we can
+ # give some printout feedback
+ push_symbol(PATTERN)
+ push cdr(p1)
+ list(2)
+
+
+###
+ Clear all patterns
+###
+
+
+do_clearPatterns = ->
+ userSimplificationsInListForm = []
+ userSimplificationsInStringForm = []
+
+Eval_clearpatterns = ->
+ # this is likely to create garbage collection
+ # problems in the C version as it's an
+ # untracked reference
+ do_clearPatterns()
+
+ # return nothing
+ push_symbol(NIL)
+
+
+Eval_patternsinfo = ->
+ patternsinfoToBePrinted = patternsinfo()
+
+ if patternsinfoToBePrinted != ""
+ push new_string(patternsinfoToBePrinted)
+ else
+ push_symbol(NIL)
+
+patternsinfo = ->
+ patternsinfoToBePrinted = ""
+ for i in userSimplificationsInListForm
+ patternsinfoToBePrinted += userSimplificationsInListForm + "\n"
+ return patternsinfoToBePrinted
diff --git a/node_modules/algebrite/sources/polar.coffee b/node_modules/algebrite/sources/polar.coffee
new file mode 100644
index 0000000..95b86ff
--- /dev/null
+++ b/node_modules/algebrite/sources/polar.coffee
@@ -0,0 +1,37 @@
+###
+Convert complex z to polar form
+
+ Input: push z
+
+ Output: Result on stack
+
+ polar(z) = abs(z) * exp(i * arg(z))
+###
+
+
+
+Eval_polar = ->
+ push(cadr(p1))
+ Eval()
+ polar()
+
+polar = ->
+ # there are points where we turn polar
+ # representations into rect, we set a "stack flag"
+ # here to avoid that, so we don't undo the
+ # work that we are trying to do.
+ evaluatingPolar++
+ save()
+ p1 = pop()
+ push(p1)
+ abs()
+ push(imaginaryunit)
+ push(p1)
+ arg()
+ multiply()
+ exponential()
+ multiply()
+ evaluatingPolar--
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/pollard.coffee b/node_modules/algebrite/sources/pollard.coffee
new file mode 100644
index 0000000..3a5f63e
--- /dev/null
+++ b/node_modules/algebrite/sources/pollard.coffee
@@ -0,0 +1,175 @@
+# Factor using the Pollard rho method
+
+
+
+n_factor_number = 0
+
+factor_number = ->
+ h = 0
+
+ save()
+
+ p1 = pop()
+
+ # 0 or 1?
+
+ if (equaln(p1, 0) || equaln(p1, 1) || equaln(p1, -1))
+ push(p1)
+ restore()
+ return
+
+ n_factor_number = p1.q.a
+
+ h = tos
+
+ factor_a()
+
+ if (tos - h > 1)
+ list(tos - h)
+ push_symbol(MULTIPLY)
+ swap()
+ cons()
+
+ restore()
+
+# factor using table look-up, then switch to rho method if necessary
+
+# From TAOCP Vol. 2 by Knuth, p. 380 (Algorithm A)
+
+factor_a = ->
+ k = 0
+
+ if (n_factor_number.isNegative())
+ n_factor_number = setSignTo(n_factor_number, 1)
+ push_integer(-1)
+
+ for k in [0...10000]
+
+ try_kth_prime(k)
+
+ # if n_factor_number is 1 then we're done
+
+ if (n_factor_number.compare(1) == 0)
+ return
+
+ factor_b()
+
+try_kth_prime = (k) ->
+ count = 0
+
+ d = mint(primetab[k])
+
+ count = 0
+
+ while (1)
+
+ # if n_factor_number is 1 then we're done
+
+ if (n_factor_number.compare(1) == 0)
+ if (count)
+ push_factor(d, count)
+ return
+
+ [q,r] = mdivrem(n_factor_number, d)
+
+ # continue looping while remainder is zero
+
+ if (r.isZero())
+ count++
+ n_factor_number = q
+ else
+ break
+
+ if (count)
+ push_factor(d, count)
+
+ # q = n_factor_number/d, hence if q < d then
+ # n_factor_number < d^2 so n_factor_number is prime
+
+ if (mcmp(q, d) == -1)
+ push_factor(n_factor_number, 1)
+ n_factor_number = mint(1)
+
+
+# From TAOCP Vol. 2 by Knuth, p. 385 (Algorithm B)
+
+factor_b = ->
+ k = 0
+ l = 0
+
+ bigint_one = mint(1)
+ x = mint(5)
+ xprime = mint(2)
+
+ k = 1
+ l = 1
+
+ while (1)
+
+ if (mprime(n_factor_number))
+ push_factor(n_factor_number, 1)
+ return 0
+
+ while (1)
+
+ if (esc_flag)
+ stop("esc")
+
+ # g = gcd(x' - x, n_factor_number)
+
+ t = msub(xprime, x)
+ t = setSignTo(t,1)
+ g = mgcd(t, n_factor_number)
+
+ if (MEQUAL(g, 1))
+ if (--k == 0)
+ xprime = x
+ l *= 2
+ k = l
+
+ # x = (x ^ 2 + 1) mod n_factor_number
+
+ t = mmul(x, x)
+ x = madd(t, bigint_one)
+ t = mmod(x, n_factor_number)
+ x = t
+
+ continue
+
+ push_factor(g, 1)
+
+ if (mcmp(g, n_factor_number) == 0)
+ return -1
+
+ # n_factor_number = n_factor_number / g
+
+ t = mdiv(n_factor_number, g)
+ n_factor_number = t
+
+ # x = x mod n_factor_number
+
+ t = mmod(x, n_factor_number)
+ x = t
+
+ # xprime = xprime mod n_factor_number
+
+ t = mmod(xprime, n_factor_number)
+ xprime = t
+
+ break
+
+push_factor = (d, count) ->
+ p1 = new U()
+ p1.k = NUM
+ p1.q.a = d
+ p1.q.b = mint(1)
+ push(p1)
+ if (count > 1)
+ push_symbol(POWER)
+ swap()
+ p1 = new U()
+ p1.k = NUM
+ p1.q.a = mint(count)
+ p1.q.b = mint(1)
+ push(p1)
+ list(3)
diff --git a/node_modules/algebrite/sources/power.coffee b/node_modules/algebrite/sources/power.coffee
new file mode 100644
index 0000000..4471025
--- /dev/null
+++ b/node_modules/algebrite/sources/power.coffee
@@ -0,0 +1,566 @@
+### Power function
+
+ Input: push Base
+
+ push Exponent
+
+ Output: Result on stack
+###
+
+DEBUG_POWER = false
+
+Eval_power = ->
+ if DEBUG_POWER then debugger
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ power()
+
+power = ->
+ save()
+ yypower()
+ restore()
+
+yypower = ->
+ if DEBUG_POWER then debugger
+ n = 0
+
+ p2 = pop() # exponent
+ p1 = pop() # base
+
+ inputExp = p2
+ inputBase = p1
+ #debugger
+
+ if DEBUG_POWER
+ console.log("POWER: " + p1 + " ^ " + p2)
+
+ # first, some very basic simplifications right away
+
+ # 1 ^ a -> 1
+ # a ^ 0 -> 1
+ if (equal(p1, one) || isZeroAtomOrTensor(p2))
+ if evaluatingAsFloats then push_double(1.0) else push(one)
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # a ^ 1 -> a
+ if (equal(p2, one))
+ push(p1)
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # -1 ^ -1 -> -1
+ if (isminusone(p1) and isminusone(p2))
+ if evaluatingAsFloats then push_double(1.0) else push(one)
+ negate()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # -1 ^ 1/2 -> i
+ if (isminusone(p1) and (isoneovertwo(p2)))
+ push(imaginaryunit)
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # -1 ^ -1/2 -> -i
+ if (isminusone(p1) and isminusoneovertwo(p2))
+ push(imaginaryunit)
+ negate()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # -1 ^ rational
+ if (isminusone(p1) and !isdouble(p1) and isrational(p2) and !isinteger(p2) and ispositivenumber(p2) and !evaluatingAsFloats)
+ if DEBUG_POWER then console.log(" power: -1 ^ rational")
+ if DEBUG_POWER then console.log " trick: p2.q.a , p2.q.b " + p2.q.a + " , " + p2.q.b
+ if p2.q.a < p2.q.b
+ push_symbol(POWER)
+ push(p1)
+ push(p2)
+ list(3)
+ else
+ push_symbol(MULTIPLY)
+
+ push(p1)
+
+ push_symbol(POWER)
+ push(p1)
+ push_rational(p2.q.a.mod(p2.q.b), p2.q.b)
+ list(3)
+
+ list(3)
+ if DEBUG_POWER then console.log " trick applied : " + stack[tos-1]
+
+ # evaluates clock form into
+ # rectangular form. This seems to give
+ # slightly better form to some test results.
+ rect()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+
+ # both base and exponent are rational numbers?
+
+ if (isrational(p1) && isrational(p2))
+ if DEBUG_POWER then console.log(" power: isrational(p1) && isrational(p2)")
+ push(p1)
+ push(p2)
+ qpow()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # both base and exponent are either rational or double?
+ if (isNumericAtom(p1) && isNumericAtom(p2))
+ if DEBUG_POWER then console.log " power: both base and exponent are either rational or double "
+ if DEBUG_POWER then console.log("POWER - isNumericAtom(p1) && isNumericAtom(p2)")
+ push(p1)
+ push(p2)
+ dpow()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ if (istensor(p1))
+ if DEBUG_POWER then console.log " power: istensor(p1) "
+ power_tensor()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # if we only assume variables to be real, then |a|^2 = a^2
+ # (if x is complex this doesn't hold e.g. i, which makes 1 and -1
+ if (car(p1) == symbol(ABS) && iseveninteger(p2) and !isZeroAtomOrTensor(get_binding(symbol(ASSUME_REAL_VARIABLES))))
+ if DEBUG_POWER then console.log " power: even power of absolute of real value "
+ push(cadr(p1))
+ push(p2)
+ power()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # e^log(...)
+ if (p1 == symbol(E) && car(p2) == symbol(LOG))
+ push(cadr(p2))
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # e^some_float
+ if (p1 == symbol(E) && isdouble(p2))
+ if DEBUG_POWER then console.log " power: p1 == symbol(E) && isdouble(p2) "
+ push_double(Math.exp(p2.d))
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # complex number in exponential form, get it to rectangular
+ # but only if we are not in the process of calculating a polar form,
+ # otherwise we'd just undo the work we want to do
+ if (p1 == symbol(E) && Find(p2, imaginaryunit) != 0 and Find(p2, symbol(PI))!= 0 and !evaluatingPolar)
+ push_symbol(POWER)
+ push(p1)
+ push(p2)
+ list(3)
+ if DEBUG_POWER then console.log " power: turning complex exponential to rect: " + stack[tos-1]
+ rect()
+
+ hopefullySimplified = pop(); # put new (hopefully simplified expr) in p2
+ if Find(hopefullySimplified, symbol(PI)) == 0
+ if DEBUG_POWER then console.log " power: turned complex exponential to rect: " + hopefullySimplified
+ push hopefullySimplified
+ return
+
+
+ # (a * b) ^ c -> (a ^ c) * (b ^ c)
+ # note that we can't in general do this, for example
+ # sqrt(x*y) != x^(1/2) y^(1/2) (counterexample" x = -1 and y = -1)
+ # BUT we can carve-out here some cases where this
+ # transformation is correct
+
+ if (car(p1) == symbol(MULTIPLY) && isinteger(p2))
+ if DEBUG_POWER then console.log " power: (a * b) ^ c -> (a ^ c) * (b ^ c) "
+ p1 = cdr(p1)
+ push(car(p1))
+ push(p2)
+ power()
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ power()
+ multiply()
+ p1 = cdr(p1)
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # (a ^ b) ^ c -> a ^ (b * c)
+ # note that we can't in general do this, for example
+ # sqrt(x^y) != x^(1/2 y) (counterexample x = -1)
+ # BUT we can carve-out here some cases where this
+ # transformation is correct
+
+
+ # simple numeric check to see if a is a number > 0
+ is_a_moreThanZero = false
+ if isNumericAtom(cadr(p1))
+ is_a_moreThanZero = sign(compare_numbers(cadr(p1), zero))
+
+ if (car(p1) == symbol(POWER) && (
+ isinteger(p2) or # when c is an integer
+ is_a_moreThanZero # when a is >= 0
+ ))
+ push(cadr(p1))
+ push(caddr(p1))
+ push(p2)
+ multiply()
+ power()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ b_isEven_and_c_isItsInverse = false
+ if iseveninteger(caddr(p1))
+ push caddr(p1)
+ push p2
+ multiply()
+
+ isThisOne = pop()
+ if isone(isThisOne)
+ b_isEven_and_c_isItsInverse = true
+
+ if (car(p1) == symbol(POWER) && b_isEven_and_c_isItsInverse)
+ if DEBUG_POWER then console.log " power: car(p1) == symbol(POWER) && b_isEven_and_c_isItsInverse "
+ push(cadr(p1))
+ abs()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+
+ # when expanding,
+ # (a + b) ^ n -> (a + b) * (a + b) ...
+
+ if (expanding && isadd(p1) && isNumericAtom(p2))
+ push(p2)
+ n = pop_integer()
+ if (n > 1 && !isNaN(n))
+ if DEBUG_POWER then console.log " power: expanding && isadd(p1) && isNumericAtom(p2) "
+ power_sum(n)
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # sin(x) ^ 2n -> (1 - cos(x) ^ 2) ^ n
+
+ if (trigmode == 1 && car(p1) == symbol(SIN) && iseveninteger(p2))
+ if DEBUG_POWER then console.log " power: trigmode == 1 && car(p1) == symbol(SIN) && iseveninteger(p2) "
+ push_integer(1)
+ push(cadr(p1))
+ cosine()
+ push_integer(2)
+ power()
+ subtract()
+ push(p2)
+ push_rational(1, 2)
+ multiply()
+ power()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # cos(x) ^ 2n -> (1 - sin(x) ^ 2) ^ n
+
+ if (trigmode == 2 && car(p1) == symbol(COS) && iseveninteger(p2))
+ if DEBUG_POWER then console.log " power: trigmode == 2 && car(p1) == symbol(COS) && iseveninteger(p2) "
+ push_integer(1)
+ push(cadr(p1))
+ sine()
+ push_integer(2)
+ power()
+ subtract()
+ push(p2)
+ push_rational(1, 2)
+ multiply()
+ power()
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+
+ # complex number? (just number, not expression)
+
+
+ if (iscomplexnumber(p1))
+
+ if DEBUG_POWER then console.log " power - handling the case (a + ib) ^ n"
+ # integer power?
+
+ # n will be negative here, positive n already handled
+
+ if (isinteger(p2))
+
+ # / \ n
+ # -n | a - ib |
+ # (a + ib) = | -------- |
+ # | 2 2 |
+ # \ a + b /
+
+ push(p1)
+ conjugate()
+ p3 = pop()
+ push(p3)
+
+ # gets the denominator
+ push(p3)
+ push(p1)
+ multiply()
+
+ divide()
+
+ if !isone(p2)
+ push(p2)
+ negate()
+ power()
+
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ # noninteger or floating power?
+
+ if (isNumericAtom(p2))
+ push(p1)
+ abs()
+ push(p2)
+ power()
+ push_integer(-1)
+ push(p1)
+ arg()
+ push(p2)
+ multiply()
+ if evaluatingAsFloats or (iscomplexnumberdouble(p1) and isdouble(p2))
+ # remember that the "double" type is
+ # toxic, i.e. it propagates, so we do
+ # need to evaluate PI to its actual double
+ # value
+ push_double(Math.PI)
+ else
+ #console.log("power pushing PI when p1 is: " + p1 + " and p2 is:" + p2)
+ push(symbol(PI))
+ divide()
+ power()
+ multiply()
+
+ # if we calculate the power making use of arctan:
+ # * it prevents nested radicals from being simplified
+ # * results become really hard to manipulate afterwards
+ # * we can't go back to other forms.
+ # so leave the power as it is.
+ if avoidCalculatingPowersIntoArctans
+ if Find(stack[tos-1], symbol(ARCTAN))
+ pop()
+ push_symbol(POWER)
+ push(p1)
+ push(p2)
+ list(3)
+
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+ return
+
+ #
+ #push(p1)
+ #abs()
+ #push(p2)
+ #power()
+ #push(symbol(E))
+ #push(p1)
+ #arg()
+ #push(p2)
+ #multiply()
+ #push(imaginaryunit)
+ #multiply()
+ #power()
+ #multiply()
+ #
+
+ if (simplify_polar())
+ if DEBUG_POWER then console.log " power: using simplify_polar"
+ return
+
+
+
+ if DEBUG_POWER then console.log " power: nothing can be done "
+ push_symbol(POWER)
+ push(p1)
+ push(p2)
+ list(3)
+ if DEBUG_POWER then console.log " power of " + inputBase + " ^ " + inputExp + ": " + stack[tos-1]
+
+#-----------------------------------------------------------------------------
+#
+# Compute the power of a sum
+#
+# Input: p1 sum
+#
+# n exponent
+#
+# Output: Result on stack
+#
+# Note:
+#
+# Uses the multinomial series (see Math World)
+#
+# n n! n1 n2 nk
+# (a1 + a2 + ... + ak) = sum (--------------- a1 a2 ... ak )
+# n1! n2! ... nk!
+#
+# The sum is over all n1 ... nk such that n1 + n2 + ... + nk = n.
+#
+#-----------------------------------------------------------------------------
+
+# first index is the term number 0..k-1, second index is the exponent 0..n
+
+#define A(i, j) frame[(i) * (n + 1) + (j)]
+
+power_sum = (n) ->
+ a = []
+ i = 0
+ j = 0
+ k = 0
+
+ # number of terms in the sum
+
+ k = length(p1) - 1
+
+ # local frame
+
+ push_frame(k * (n + 1))
+
+ # array of powers
+
+ p1 = cdr(p1)
+ for i in [0...k]
+ for j in [0..n]
+ push(car(p1))
+ push_integer(j)
+ power()
+ stack[frame + (i) * (n + 1) + (j)] = pop()
+ p1 = cdr(p1)
+
+ push_integer(n)
+ factorial()
+ p1 = pop()
+
+ for i in [0...k]
+ a[i] = 0
+
+ push(zero)
+
+ multinomial_sum(k, n, a, 0, n)
+
+ pop_frame(k * (n + 1))
+
+#-----------------------------------------------------------------------------
+#
+# Compute multinomial sum
+#
+# Input: k number of factors
+#
+# n overall exponent
+#
+# a partition array
+#
+# i partition array index
+#
+# m partition remainder
+#
+# p1 n!
+#
+# A factor array
+#
+# Output: Result on stack
+#
+# Note:
+#
+# Uses recursive descent to fill the partition array.
+#
+#-----------------------------------------------------------------------------
+
+#int k, int n, int *a, int i, int m
+multinomial_sum = (k,n,a,i,m) ->
+ j = 0
+
+ if (i < k - 1)
+ for j in [0..m]
+ a[i] = j
+ multinomial_sum(k, n, a, i + 1, m - j)
+ return
+
+ a[i] = m
+
+ # coefficient
+
+ push(p1)
+
+ for j in [0...k]
+ push_integer(a[j])
+ factorial()
+ divide()
+
+ # factors
+
+ for j in [0...k]
+ push(stack[frame + (j) * (n + 1) + a[j]])
+ multiply()
+
+ add()
+
+# exp(n/2 i pi) ?
+
+# p2 is the exponent expression
+
+# clobbers p3
+
+simplify_polar = ->
+ n = 0
+
+ n = isquarterturn(p2)
+
+ switch(n)
+ when 0
+ doNothing = 1
+ when 1
+ push_integer(1)
+ return 1
+ when 2
+ push_integer(-1)
+ return 1
+ when 3
+ push(imaginaryunit)
+ return 1
+ when 4
+ push(imaginaryunit)
+ negate()
+ return 1
+
+ if (car(p2) == symbol(ADD))
+ p3 = cdr(p2)
+ while (iscons(p3))
+ n = isquarterturn(car(p3))
+ if (n)
+ break
+ p3 = cdr(p3)
+ switch (n)
+ when 0
+ return 0
+ when 1
+ push_integer(1)
+ when 2
+ push_integer(-1)
+ when 3
+ push(imaginaryunit)
+ when 4
+ push(imaginaryunit)
+ negate()
+ push(p2)
+ push(car(p3))
+ subtract()
+ exponential()
+ multiply()
+ return 1
+
+ return 0
+
+
+
diff --git a/node_modules/algebrite/sources/prime.coffee b/node_modules/algebrite/sources/prime.coffee
new file mode 100644
index 0000000..7da9a0b
--- /dev/null
+++ b/node_modules/algebrite/sources/prime.coffee
@@ -0,0 +1,22 @@
+#-----------------------------------------------------------------------------
+#
+# Look up the nth prime
+#
+# Input: n on stack (0 < n < 10001)
+#
+# Output: nth prime on stack
+#
+#-----------------------------------------------------------------------------
+
+Eval_prime = ->
+ push(cadr(p1))
+ Eval()
+ prime()
+
+prime = ->
+ n = 0
+ n = pop_integer()
+ if (n < 1 || n > MAXPRIMETAB)
+ stop("prime: Argument out of range.")
+ n = primetab[n - 1]
+ push_integer(n)
diff --git a/node_modules/algebrite/sources/print.coffee b/node_modules/algebrite/sources/print.coffee
new file mode 100644
index 0000000..877e000
--- /dev/null
+++ b/node_modules/algebrite/sources/print.coffee
@@ -0,0 +1,1492 @@
+power_str = "^"
+codeGen = false
+
+# this is only invoked when user invokes
+# "print" explicitly
+Eval_print = ->
+ stringsEmittedByUserPrintouts += _print(cdr(p1), printMode)
+ push(symbol(NIL));
+
+# this is only invoked when user invokes
+# "print2dascii" explicitly
+Eval_print2dascii = ->
+ stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_2DASCII)
+ push(symbol(NIL));
+
+# this is only invoked when user invokes
+# "printcomputer" explicitly
+Eval_printcomputer = ->
+ stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_COMPUTER)
+ push(symbol(NIL));
+
+# this is only invoked when user invokes
+# "printlatex" explicitly
+Eval_printlatex = ->
+ stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_LATEX)
+ push(symbol(NIL));
+
+# this is only invoked when user invokes
+# "printhuman" explicitly
+Eval_printhuman = ->
+ # test flag needs to be suspended
+ # because otherwise "printcomputer" mode
+ # will happen.
+ original_test_flag = test_flag
+ test_flag = 0
+ stringsEmittedByUserPrintouts +=_print(cdr(p1),PRINTMODE_HUMAN)
+ test_flag = original_test_flag
+ push(symbol(NIL));
+
+# this is only invoked when user invokes
+# "printlist" explicitly
+Eval_printlist = ->
+ beenPrinted = _print(cdr(p1),PRINTMODE_LIST)
+ stringsEmittedByUserPrintouts += beenPrinted
+ push(symbol(NIL))
+
+
+_print = (p, passedPrintMode) ->
+ accumulator = ""
+
+ while (iscons(p))
+
+ push(car(p));
+ Eval();
+ p2 = pop();
+
+ # display single symbol as "symbol = result"
+
+ # but don't display "symbol = symbol"
+
+ ###
+ if (issymbol(car(p)) && car(p) != p2)
+ push_symbol(SETQ);
+ push(car(p));
+ push(p2);
+ list(3);
+ p2 = pop();
+ ###
+
+ origPrintMode = printMode
+ if passedPrintMode == PRINTMODE_COMPUTER
+ printMode = PRINTMODE_COMPUTER
+ accumulator = printline(p2);
+ rememberPrint(accumulator, LAST_FULL_PRINT)
+ else if passedPrintMode == PRINTMODE_HUMAN
+ printMode = PRINTMODE_HUMAN
+ accumulator = printline(p2);
+ rememberPrint(accumulator, LAST_PLAIN_PRINT)
+ else if passedPrintMode == PRINTMODE_2DASCII
+ printMode = PRINTMODE_2DASCII
+ accumulator = print2dascii(p2);
+ rememberPrint(accumulator, LAST_2DASCII_PRINT)
+ else if passedPrintMode == PRINTMODE_LATEX
+ printMode = PRINTMODE_LATEX
+ accumulator = printline(p2);
+ rememberPrint(accumulator, LAST_LATEX_PRINT)
+ else if passedPrintMode == PRINTMODE_LIST
+ printMode = PRINTMODE_LIST
+ accumulator = print_list(p2);
+ rememberPrint(accumulator, LAST_LIST_PRINT)
+ printMode = origPrintMode
+
+
+ p = cdr(p);
+
+ if DEBUG then console.log "emttedString from display: " + stringsEmittedByUserPrintouts
+ return accumulator
+
+rememberPrint = (theString, theTypeOfPrint) ->
+ scan('"' + theString + '"')
+ parsedString = pop()
+ set_binding(symbol(theTypeOfPrint), parsedString)
+
+print_str = (s) ->
+ if DEBUG then console.log "emttedString from print_str: " + stringsEmittedByUserPrintouts
+ return s
+
+print_char = (c) ->
+ return c
+
+collectLatexStringFromReturnValue = (p) ->
+ origPrintMode = printMode
+ printMode = PRINTMODE_LATEX
+ originalCodeGen = codeGen
+ codeGen = false
+ returnedString = print_expr(p)
+ # some variables might contain underscores, escape those
+ returnedString = returnedString.replace(/_/g, "\\_");
+ printMode = origPrintMode
+ codeGen = originalCodeGen
+ if DEBUG then console.log "emttedString from collectLatexStringFromReturnValue: " + stringsEmittedByUserPrintouts
+ return returnedString
+
+printline = (p) ->
+ accumulator = ""
+ accumulator += print_expr(p)
+ return accumulator
+
+
+print_base_of_denom = (p1) ->
+ accumulator = ""
+ if (isfraction(p1) || car(p1) == symbol(ADD) || car(p1) == symbol(MULTIPLY) || car(p1) == symbol(POWER) || lessp(p1, zero)) # p1 is BASE
+ accumulator += print_char('(')
+ accumulator += print_expr(p1); # p1 is BASE
+ accumulator += print_char(')')
+ else
+ accumulator += print_expr(p1); # p1 is BASE
+ return accumulator
+
+print_expo_of_denom = (p2) ->
+ accumulator = ""
+ if (isfraction(p2) || car(p2) == symbol(ADD) || car(p2) == symbol(MULTIPLY) || car(p2) == symbol(POWER)) # p2 is EXPO
+ accumulator += print_char('(')
+ accumulator += print_expr(p2); # p2 is EXPO
+ accumulator += print_char(')')
+ else
+ accumulator += print_expr(p2); # p2 is EXPO
+ return accumulator
+
+# prints stuff after the divide symbol "/"
+
+# d is the number of denominators
+
+#define BASE p1
+#define EXPO p2
+
+print_denom = (p, d) ->
+ accumulator = ""
+ save()
+
+ p1 = cadr(p); # p1 is BASE
+ p2 = caddr(p); # p2 is EXPO
+
+ # i.e. 1 / (2^(1/3))
+
+ # get the cases like BASE^(-1) out of
+ # the way, they just become 1/BASE
+ if (isminusone(p2)) # p2 is EXPO
+ accumulator += print_base_of_denom p1
+ restore()
+ return accumulator
+
+ if (d == 1) # p2 is EXPO
+ accumulator += print_char('(')
+
+ # prepare the exponent
+ # (needs to be negated)
+ # before printing it out
+ push(p2); # p2 is EXPO
+ negate()
+ p2 = pop(); # p2 is EXPO
+ accumulator += print_power(p1,p2)
+ if (d == 1)
+ accumulator += print_char(')')
+ restore()
+ return accumulator
+
+
+#define A p3
+#define B p4
+
+print_a_over_b = (p) ->
+ accumulator = ""
+ flag = 0
+ n = 0
+ d = 0
+
+ save()
+
+ # count numerators and denominators
+
+ n = 0
+ d = 0
+
+ p1 = cdr(p)
+ p2 = car(p1)
+
+ if (isrational(p2))
+ push(p2)
+ mp_numerator()
+ absval()
+ p3 = pop(); # p3 is A
+ push(p2)
+ mp_denominator()
+ p4 = pop(); # p4 is B
+ if (!isplusone(p3)) # p3 is A
+ n++
+ if (!isplusone(p4)) # p4 is B
+ d++
+ p1 = cdr(p1)
+ else
+ p3 = one; # p3 is A
+ p4 = one; # p4 is B
+
+ while (iscons(p1))
+ p2 = car(p1)
+ if (is_denominator(p2))
+ d++
+ else
+ n++
+ p1 = cdr(p1)
+
+ #debugger
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str('\\frac{')
+
+ if (n == 0)
+ accumulator += print_char('1')
+ else
+ flag = 0
+ p1 = cdr(p)
+ if (isrational(car(p1)))
+ p1 = cdr(p1)
+ if (!isplusone(p3)) # p3 is A
+ accumulator += print_factor(p3); # p3 is A
+ flag = 1
+ while (iscons(p1))
+ p2 = car(p1)
+ if (is_denominator(p2))
+ doNothing = 1
+ else
+ if (flag)
+ accumulator += print_multiply_sign()
+ accumulator += print_factor(p2)
+ flag = 1
+ p1 = cdr(p1)
+
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str('}{')
+ else if printMode == PRINTMODE_HUMAN and !test_flag
+ accumulator += print_str(" / ")
+ else
+ accumulator += print_str("/")
+
+ if (d > 1 and printMode != PRINTMODE_LATEX)
+ accumulator += print_char('(')
+
+
+ flag = 0
+ p1 = cdr(p)
+
+ if (isrational(car(p1)))
+ p1 = cdr(p1)
+
+ if (!isplusone(p4)) # p4 is B
+ accumulator += print_factor(p4); # p4 is B
+ flag = 1
+
+ while (iscons(p1))
+ p2 = car(p1)
+ if (is_denominator(p2))
+ if (flag)
+ accumulator += print_multiply_sign()
+ accumulator += print_denom(p2, d)
+ flag = 1
+ p1 = cdr(p1)
+
+ if (d > 1 and printMode != PRINTMODE_LATEX)
+ accumulator += print_char(')')
+
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str('}')
+
+ restore()
+ return accumulator
+
+
+print_expr = (p) ->
+ accumulator = ""
+ if (isadd(p))
+ p = cdr(p)
+ if (sign_of_term(car(p)) == '-')
+ accumulator += print_str("-")
+ accumulator += print_term(car(p))
+ p = cdr(p)
+ while (iscons(p))
+ if (sign_of_term(car(p)) == '+')
+ if printMode == PRINTMODE_HUMAN and !test_flag
+ accumulator += print_str(" + ")
+ else
+ accumulator += print_str("+")
+ else
+ if printMode == PRINTMODE_HUMAN and !test_flag
+ accumulator += print_str(" - ")
+ else
+ accumulator += print_str("-")
+ accumulator += print_term(car(p))
+ p = cdr(p)
+ else
+ if (sign_of_term(p) == '-')
+ accumulator += print_str("-")
+ accumulator += print_term(p)
+ return accumulator
+
+sign_of_term = (p) ->
+ accumulator = ""
+ if (car(p) == symbol(MULTIPLY) && isNumericAtom(cadr(p)) && lessp(cadr(p), zero))
+ accumulator += '-'
+ else if (isNumericAtom(p) && lessp(p, zero))
+ accumulator += '-'
+ else
+ accumulator += '+'
+ return accumulator
+
+print_term = (p) ->
+ accumulator = ""
+ if (car(p) == symbol(MULTIPLY) && any_denominators(p))
+ accumulator += print_a_over_b(p)
+ return accumulator
+
+ if (car(p) == symbol(MULTIPLY))
+ p = cdr(p)
+
+ # coeff -1?
+
+ if (isminusone(car(p)))
+ # print_char('-')
+ p = cdr(p)
+
+
+ previousFactorWasANumber = false
+
+ # print the first factor ------------
+ if isNumericAtom(car(p))
+ previousFactorWasANumber = true
+
+ # this numberOneOverSomething thing is so that
+ # we show things of the form
+ # numericFractionOfForm1/something * somethingElse
+ # as
+ # somethingElse / something
+ # so for example 1/2 * sqrt(2) is rendered as
+ # sqrt(2)/2
+ # rather than the first form, which looks confusing.
+ # NOTE that you might want to avoid this
+ # when printing polynomials, as it could be nicer
+ # to show the numeric coefficients well separated from
+ # the variable, but we'll see when we'll
+ # come to it if it's an issue.
+ numberOneOverSomething = false
+ if printMode == PRINTMODE_LATEX and iscons(cdr(p)) and isNumberOneOverSomething(car(p))
+ numberOneOverSomething = true
+ denom = car(p).q.b.toString()
+
+
+ if numberOneOverSomething
+ origAccumulator = accumulator
+ accumulator = ""
+ else
+ accumulator += print_factor(car(p))
+
+ p = cdr(p)
+
+ # print all the other factors -------
+ while (iscons(p))
+ # check if we end up having a case where two numbers
+ # are next to each other. In those cases, latex needs
+ # to insert a \cdot otherwise they end up
+ # right next to each other and read like one big number
+ if printMode == PRINTMODE_LATEX
+ if previousFactorWasANumber
+ # if what comes next is a power and the base
+ # is a number, then we are in the case
+ # of consecutive numbers.
+ # Note that sqrt() i.e when exponent is 1/2
+ # doesn't count because the radical gives
+ # a nice graphical separation already.
+ if caar(p) == symbol(POWER)
+ if isNumericAtom(car(cdr(car(p))))
+ # rule out square root
+ if !isfraction(car(cdr(cdr(car(p)))))
+ accumulator += " \\cdot "
+ accumulator += print_multiply_sign()
+ accumulator += print_factor(car(p),false,true)
+
+ previousFactorWasANumber = false
+ if isNumericAtom(car(p))
+ previousFactorWasANumber = true
+
+ p = cdr(p)
+
+ if numberOneOverSomething
+ accumulator = origAccumulator + "\\frac{" + accumulator + "}{" + denom + "}"
+
+ else
+ accumulator += print_factor(p)
+ return accumulator
+
+print_subexpr = (p) ->
+ accumulator = ""
+ accumulator += print_char('(')
+ accumulator += print_expr(p)
+ accumulator += print_char(')')
+ return accumulator
+
+print_factorial_function = (p) ->
+ accumulator = ""
+ p = cadr(p)
+ if (isfraction(p) || car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY) || car(p) == symbol(POWER) || car(p) == symbol(FACTORIAL))
+ accumulator += print_subexpr(p)
+ else
+ accumulator += print_expr(p)
+ accumulator += print_char('!')
+ return accumulator
+
+print_ABS_latex = (p) ->
+ accumulator = ""
+ accumulator += print_str("\\left |")
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str(" \\right |")
+ return accumulator
+
+print_BINOMIAL_latex = (p) ->
+ accumulator = ""
+ accumulator += print_str("\\binom{")
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str("}{")
+ accumulator += print_expr(caddr(p))
+ accumulator += print_str("} ")
+ return accumulator
+
+print_DOT_latex = (p) ->
+ accumulator = ""
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str(" \\cdot ")
+ accumulator += print_expr(caddr(p))
+ return accumulator
+
+print_DOT_codegen = (p) ->
+ accumulator = "dot("
+ accumulator += print_expr(cadr(p))
+ accumulator += ", "
+ accumulator += print_expr(caddr(p))
+ accumulator += ")"
+ return accumulator
+
+print_SIN_codegen = (p) ->
+ accumulator = "Math.sin("
+ accumulator += print_expr(cadr(p))
+ accumulator += ")"
+ return accumulator
+
+print_COS_codegen = (p) ->
+ accumulator = "Math.cos("
+ accumulator += print_expr(cadr(p))
+ accumulator += ")"
+ return accumulator
+
+print_TAN_codegen = (p) ->
+ accumulator = "Math.tan("
+ accumulator += print_expr(cadr(p))
+ accumulator += ")"
+ return accumulator
+
+print_ARCSIN_codegen = (p) ->
+ accumulator = "Math.asin("
+ accumulator += print_expr(cadr(p))
+ accumulator += ")"
+ return accumulator
+
+print_ARCCOS_codegen = (p) ->
+ accumulator = "Math.acos("
+ accumulator += print_expr(cadr(p))
+ accumulator += ")"
+ return accumulator
+
+print_ARCTAN_codegen = (p) ->
+ accumulator = "Math.atan("
+ accumulator += print_expr(cadr(p))
+ accumulator += ")"
+ return accumulator
+
+print_SQRT_latex = (p) ->
+ accumulator = ""
+ accumulator += print_str("\\sqrt{")
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str("} ")
+ return accumulator
+
+print_TRANSPOSE_latex = (p) ->
+ accumulator = ""
+ accumulator += print_str("{")
+ if iscons(cadr(p))
+ accumulator += print_str('(')
+ accumulator += print_expr(cadr(p))
+ if iscons(cadr(p))
+ accumulator += print_str(')')
+ accumulator += print_str("}")
+ accumulator += print_str("^T")
+ return accumulator
+
+print_TRANSPOSE_codegen = (p) ->
+ accumulator = ""
+ accumulator += print_str("transpose(")
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str(')')
+ return accumulator
+
+print_UNIT_codegen = (p) ->
+ accumulator = ""
+ accumulator += print_str("identity(")
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str(')')
+ return accumulator
+
+print_INV_latex = (p) ->
+ accumulator = ""
+ accumulator += print_str("{")
+ if iscons(cadr(p))
+ accumulator += print_str('(')
+ accumulator += print_expr(cadr(p))
+ if iscons(cadr(p))
+ accumulator += print_str(')')
+ accumulator += print_str("}")
+ accumulator += print_str("^{-1}")
+ return accumulator
+
+print_INV_codegen = (p) ->
+ accumulator = ""
+ accumulator += print_str("inv(")
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str(')')
+ return accumulator
+
+print_DEFINT_latex = (p) ->
+ accumulator = ""
+ functionBody = car(cdr(p))
+
+ p = cdr(p)
+ originalIntegral = p
+ numberOfIntegrals = 0
+
+ while iscons(cdr(cdr(p)))
+ numberOfIntegrals++
+ theIntegral = cdr(cdr(p))
+
+ accumulator += print_str("\\int^{")
+ accumulator += print_expr(car(cdr(theIntegral)))
+ accumulator += print_str("}_{")
+ accumulator += print_expr(car(theIntegral))
+ accumulator += print_str("} \\! ")
+ p = cdr(theIntegral)
+
+ accumulator += print_expr(functionBody)
+ accumulator += print_str(" \\,")
+
+ p = originalIntegral
+
+ for i in [1..numberOfIntegrals]
+ theVariable = cdr(p)
+ accumulator += print_str(" \\mathrm{d} ")
+ accumulator += print_expr(car(theVariable))
+ if i < numberOfIntegrals
+ accumulator += print_str(" \\, ")
+ p = cdr(cdr(theVariable))
+ return accumulator
+
+
+
+print_tensor = (p) ->
+ accumulator = ""
+ accumulator += print_tensor_inner(p, 0, 0)[1]
+ return accumulator
+
+# j scans the dimensions
+# k is an increment for all the printed elements
+# since they are all together in sequence in one array
+print_tensor_inner = (p, j, k) ->
+ accumulator = ""
+
+ accumulator += print_str("[")
+
+ # only the last dimension prints the actual elements
+ # e.g. in a matrix, the first dimension contains
+ # vectors, not elements, and the second dimension
+ # actually contains the elements
+
+ # if not the last dimension, we are just printing wrappers
+ # and recursing down i.e. we print the next dimension
+ if (j < p.tensor.ndim - 1)
+ for i in [0...p.tensor.dim[j]]
+ [k, retString] = print_tensor_inner(p, j + 1, k)
+ accumulator += retString
+ # add separator between elements dimensions
+ # "above" the inner-most dimension
+ if i != p.tensor.dim[j] - 1
+ accumulator += print_str(",")
+ # if we reached the last dimension, we print the actual
+ # elements
+ else
+ for i in [0...p.tensor.dim[j]]
+ accumulator += print_expr(p.tensor.elem[k])
+ # add separator between elements in the
+ # inner-most dimension
+ if i != p.tensor.dim[j] - 1
+ accumulator += print_str(",")
+ k++
+
+ accumulator += print_str("]")
+ return [k, accumulator]
+
+print_tensor_latex = (p) ->
+ accumulator = ""
+ if p.tensor.ndim <= 2
+ accumulator += print_tensor_inner_latex(true, p, 0, 0)[1]
+ return accumulator
+
+# firstLevel is needed because printing a matrix
+# is not exactly an elegant recursive procedure:
+# the vector on the first level prints the latex
+# "wrap", while the vectors that make up the
+# rows don't. so it's a bit asymmetric and this
+# flag helps.
+# j scans the dimensions
+# k is an increment for all the printed elements
+# since they are all together in sequence in one array
+print_tensor_inner_latex = (firstLevel, p, j, k) ->
+ accumulator = ""
+
+ # open the outer latex wrap
+ if firstLevel
+ accumulator += "\\begin{bmatrix} "
+
+ # only the last dimension prints the actual elements
+ # e.g. in a matrix, the first dimension contains
+ # vectors, not elements, and the second dimension
+ # actually contains the elements
+
+ # if not the last dimension, we are just printing wrappers
+ # and recursing down i.e. we print the next dimension
+ if (j < p.tensor.ndim - 1)
+ for i in [0...p.tensor.dim[j]]
+ [k, retString] = print_tensor_inner_latex(0, p, j + 1, k)
+ accumulator += retString
+ if i != p.tensor.dim[j] - 1
+ # add separator between rows
+ accumulator += print_str(" \\\\ ")
+ # if we reached the last dimension, we print the actual
+ # elements
+ else
+ for i in [0...p.tensor.dim[j]]
+ accumulator += print_expr(p.tensor.elem[k])
+ # separator between elements in each row
+ if i != p.tensor.dim[j] - 1
+ accumulator += print_str(" & ")
+ k++
+
+
+ # close the outer latex wrap
+ if firstLevel
+ accumulator += " \\end{bmatrix}"
+
+ return [k, accumulator]
+
+print_SUM_latex = (p) ->
+ accumulator = "\\sum_{"
+ accumulator += print_expr(caddr(p))
+ accumulator += "="
+ accumulator += print_expr(cadddr(p))
+ accumulator += "}^{"
+ accumulator += print_expr(caddddr(p))
+ accumulator += "}{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "}"
+ return accumulator
+
+print_SUM_codegen = (p) ->
+
+ body = cadr(p)
+ variable = caddr(p)
+ lowerlimit = cadddr(p)
+ upperlimit = caddddr(p)
+
+ accumulator =
+ "(function(){" +
+ " var " + variable + "; " +
+ " var holderSum = 0; " +
+ " var lowerlimit = " + print_expr(lowerlimit) + "; " +
+ " var upperlimit = " + print_expr(upperlimit) + "; " +
+ " for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
+ " holderSum += " + print_expr(body) + ";" +
+ " } "+
+ " return holderSum;" +
+ "})()"
+
+ return accumulator
+
+print_TEST_latex = (p) ->
+ accumulator = "\\left\\{ \\begin{array}{ll}"
+
+ p = cdr(p)
+ while (iscons(p))
+
+ # odd number of parameters means that the
+ # last argument becomes the default case
+ # i.e. the one without a test.
+ if (cdr(p) == symbol(NIL))
+ accumulator += "{"
+ accumulator += print_expr(car(p))
+ accumulator += "} & otherwise "
+ accumulator += " \\\\\\\\"
+ break
+
+ accumulator += "{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "} & if & "
+ accumulator += print_expr(car(p))
+ accumulator += " \\\\\\\\"
+
+ # test unsuccessful, continue to the
+ # next pair of test,value
+ p = cddr(p)
+ accumulator = accumulator.substring(0, accumulator.length - 4);
+ accumulator += "\\end{array} \\right."
+
+print_TEST_codegen = (p) ->
+
+ accumulator = "(function(){"
+
+ p = cdr(p)
+ howManyIfs = 0
+ while (iscons(p))
+
+ # odd number of parameters means that the
+ # last argument becomes the default case
+ # i.e. the one without a test.
+ if (cdr(p) == symbol(NIL))
+ accumulator += "else {"
+ accumulator += "return (" + print_expr(car(p)) + ");"
+ accumulator += "}"
+ break
+
+ if howManyIfs
+ accumulator += " else "
+
+ accumulator += "if (" + print_expr(car(p)) + "){"
+ accumulator += "return (" + print_expr(cadr(p)) + ");"
+ accumulator += "}"
+
+ # test unsuccessful, continue to the
+ # next pair of test,value
+ howManyIfs++
+ p = cddr(p)
+
+ accumulator += "})()"
+
+ return accumulator
+
+
+print_TESTLT_latex = (p) ->
+ accumulator = "{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "}"
+ accumulator += " < "
+ accumulator += "{"
+ accumulator += print_expr(caddr(p))
+ accumulator += "}"
+
+print_TESTLE_latex = (p) ->
+ accumulator = "{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "}"
+ accumulator += " \\leq "
+ accumulator += "{"
+ accumulator += print_expr(caddr(p))
+ accumulator += "}"
+
+print_TESTGT_latex = (p) ->
+ accumulator = "{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "}"
+ accumulator += " > "
+ accumulator += "{"
+ accumulator += print_expr(caddr(p))
+ accumulator += "}"
+
+print_TESTGE_latex = (p) ->
+ accumulator = "{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "}"
+ accumulator += " \\geq "
+ accumulator += "{"
+ accumulator += print_expr(caddr(p))
+ accumulator += "}"
+
+print_TESTEQ_latex = (p) ->
+ accumulator = "{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "}"
+ accumulator += " = "
+ accumulator += "{"
+ accumulator += print_expr(caddr(p))
+ accumulator += "}"
+
+print_FOR_codegen = (p) ->
+ body = cadr(p)
+ variable = caddr(p)
+ lowerlimit = cadddr(p)
+ upperlimit = caddddr(p)
+
+ accumulator =
+ "(function(){" +
+ " var " + variable + "; " +
+ " var lowerlimit = " + print_expr(lowerlimit) + "; " +
+ " var upperlimit = " + print_expr(upperlimit) + "; " +
+ " for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
+ " " + print_expr(body) +
+ " } "+
+ "})()"
+
+ return accumulator
+
+print_DO_codegen = (p) ->
+ accumulator = ""
+
+ p = cdr(p)
+ while iscons(p)
+ accumulator += print_expr(car(p))
+ p = cdr(p)
+
+ return accumulator
+
+print_SETQ_codegen = (p) ->
+ accumulator = ""
+ accumulator += print_expr(cadr(p))
+ accumulator += " = "
+ accumulator += print_expr(caddr(p))
+ accumulator += "; "
+ return accumulator
+
+
+print_PRODUCT_latex = (p) ->
+ accumulator = "\\prod_{"
+ accumulator += print_expr(caddr(p))
+ accumulator += "="
+ accumulator += print_expr(cadddr(p))
+ accumulator += "}^{"
+ accumulator += print_expr(caddddr(p))
+ accumulator += "}{"
+ accumulator += print_expr(cadr(p))
+ accumulator += "}"
+ return accumulator
+
+print_PRODUCT_codegen = (p) ->
+
+ body = cadr(p)
+ variable = caddr(p)
+ lowerlimit = cadddr(p)
+ upperlimit = caddddr(p)
+
+ accumulator =
+ "(function(){" +
+ " var " + variable + "; " +
+ " var holderProduct = 1; " +
+ " var lowerlimit = " + print_expr(lowerlimit) + "; " +
+ " var upperlimit = " + print_expr(upperlimit) + "; " +
+ " for (" + variable + " = lowerlimit; " + variable + " < upperlimit; " + variable + "++) { " +
+ " holderProduct *= " + print_expr(body) + ";" +
+ " } "+
+ " return holderProduct;" +
+ "})()"
+
+ return accumulator
+
+
+print_base = (p) ->
+ accumulator = ""
+ if (isadd(cadr(p)) || caadr(p) == symbol(MULTIPLY) || caadr(p) == symbol(POWER) || isnegativenumber(cadr(p)))
+ accumulator += print_str('(')
+ accumulator += print_expr(cadr(p))
+ accumulator += print_str(')')
+ else if (isNumericAtom(cadr(p)) && (lessp(cadr(p), zero) || isfraction(cadr(p))))
+ accumulator += print_str('(')
+ accumulator += print_factor(cadr(p))
+ accumulator += print_str(')')
+ else
+ accumulator += print_factor(cadr(p))
+ return accumulator
+
+print_exponent = (p) ->
+ accumulator = ""
+ if (iscons(caddr(p)) || isfraction(caddr(p)) || (isNumericAtom(caddr(p)) && lessp(caddr(p), zero)))
+ accumulator += print_str('(')
+ accumulator += print_expr(caddr(p))
+ accumulator += print_str(')')
+ else
+ accumulator += print_factor(caddr(p))
+ return accumulator
+
+print_power = (base, exponent) ->
+ accumulator = ""
+
+ #debugger
+ if DEBUG then console.log "power base: " + base + " " + " exponent: " + exponent
+
+ # quick check is this is actually a square root.
+ if isoneovertwo(exponent)
+ if equaln(base, 2)
+ if codeGen
+ accumulator += print_str("Math.SQRT2")
+ return accumulator
+ else
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str("\\sqrt{")
+ accumulator += print_expr(base)
+ accumulator += print_str("}")
+ return accumulator
+ else if codeGen
+ accumulator += print_str("Math.sqrt(")
+ accumulator += print_expr(base)
+ accumulator += print_str(')')
+ return accumulator
+
+
+ if ((equaln(get_binding(symbol(PRINT_LEAVE_E_ALONE)), 1)) and base == symbol(E))
+ if codeGen
+ accumulator += print_str("Math.exp(")
+ accumulator += print_expo_of_denom exponent
+ accumulator += print_str(')')
+ return accumulator
+
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str("e^{")
+ accumulator += print_expr(exponent)
+ accumulator += print_str("}")
+ else
+ accumulator += print_str("exp(")
+ accumulator += print_expr(exponent)
+ accumulator += print_str(')')
+ return accumulator
+
+ if codeGen
+ accumulator += print_str("Math.pow(")
+ accumulator += print_base_of_denom base
+ accumulator += print_str(", ")
+ accumulator += print_expo_of_denom exponent
+ accumulator += print_str(')')
+ return accumulator
+
+
+ if ((equaln(get_binding(symbol(PRINT_LEAVE_X_ALONE)), 0)) or base.printname != "x")
+ # if the exponent is negative then
+ # we invert the base BUT we don't do
+ # that if the base is "e", because for
+ # example when trigonometric functions are
+ # expressed in terms of exponential functions
+ # that would be really confusing, one wants to
+ # keep "e" as the base and the negative exponent
+ if (base != symbol(E))
+ if (isminusone(exponent))
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str("\\frac{1}{")
+ else if printMode == PRINTMODE_HUMAN and !test_flag
+ accumulator += print_str("1 / ")
+ else
+ accumulator += print_str("1/")
+
+ if (iscons(base) and printMode != PRINTMODE_LATEX)
+ accumulator += print_str('(')
+ accumulator += print_expr(base)
+ accumulator += print_str(')')
+ else
+ accumulator += print_expr(base)
+
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str("}")
+
+ return accumulator
+
+ if (isnegativeterm(exponent))
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str("\\frac{1}{")
+ else if printMode == PRINTMODE_HUMAN and !test_flag
+ accumulator += print_str("1 / ")
+ else
+ accumulator += print_str("1/")
+
+ push(exponent)
+ push_integer(-1)
+ multiply()
+ newExponent = pop()
+
+ if (iscons(base) and printMode != PRINTMODE_LATEX)
+ accumulator += print_str('(')
+ accumulator += print_power(base, newExponent)
+ accumulator += print_str(')')
+ else
+ accumulator += print_power(base, newExponent)
+
+
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str("}")
+
+ return accumulator
+
+
+ if (isfraction(exponent) and printMode == PRINTMODE_LATEX)
+ accumulator += print_str("\\sqrt")
+ push(exponent)
+ denominator()
+ denomExponent = pop()
+ # we omit the "2" on the radical
+ if !isplustwo(denomExponent)
+ accumulator += print_str("[")
+ accumulator += print_expr(denomExponent)
+ accumulator += print_str("]")
+ accumulator += print_str("{")
+ push(exponent)
+ numerator()
+ numExponent = pop()
+ exponent = numExponent
+ accumulator += print_power(base, exponent)
+ accumulator += print_str("}")
+ return accumulator
+
+ if printMode == PRINTMODE_LATEX and isplusone(exponent)
+ # if we are in latex mode we turn many
+ # radicals into a radix sign with a power
+ # underneath, and the power is often one
+ # (e.g. square root turns into a radical
+ # with a power one underneath) so handle
+ # this case simply here, just print the base
+ accumulator += print_expr(base)
+ else
+ # print the base,
+ # determining if it needs to be
+ # wrapped in parentheses or not
+ if (isadd(base) || isnegativenumber(base))
+ accumulator += print_str('(')
+ accumulator += print_expr(base)
+ accumulator += print_str(')')
+ else if ( car(base) == symbol(MULTIPLY) || car(base) == symbol(POWER))
+ if printMode != PRINTMODE_LATEX then accumulator += print_str('(')
+ accumulator += print_factor(base, true)
+ if printMode != PRINTMODE_LATEX then accumulator += print_str(')')
+ else if (isNumericAtom(base) && (lessp(base, zero) || isfraction(base)))
+ accumulator += print_str('(')
+ accumulator += print_factor(base)
+ accumulator += print_str(')')
+ else
+ accumulator += print_factor(base)
+
+ # print the power symbol
+ #debugger
+ if printMode == PRINTMODE_HUMAN and !test_flag
+ #print_str(" ^ ")
+ accumulator += print_str(power_str)
+ else
+ accumulator += print_str("^")
+
+ # print the exponent
+ if printMode == PRINTMODE_LATEX
+ # in latex mode, one can omit the curly braces
+ # wrapping the exponent if the exponent is only
+ # one character long
+ if print_expr(exponent).length > 1
+ accumulator += print_str("{")
+ accumulator += print_expr(exponent)
+ accumulator += print_str("}")
+ else
+ accumulator += print_expr(exponent)
+ else if (iscons(exponent) || isfraction(exponent) || (isNumericAtom(exponent) && lessp(exponent, zero)))
+ accumulator += print_str('(')
+ accumulator += print_expr(exponent)
+ accumulator += print_str(')')
+ else
+ accumulator += print_factor(exponent)
+ return accumulator
+
+print_index_function = (p) ->
+ accumulator = ""
+ p = cdr(p);
+ if (caar(p) == symbol(ADD) || caar(p) == symbol(MULTIPLY) || caar(p) == symbol(POWER) || caar(p) == symbol(FACTORIAL))
+ accumulator += print_subexpr(car(p));
+ else
+ accumulator += print_expr(car(p));
+ accumulator += print_str('[');
+ p = cdr(p);
+ if (iscons(p))
+ accumulator += print_expr(car(p));
+ p = cdr(p);
+ while(iscons(p))
+ accumulator += print_str(',');
+ accumulator += print_expr(car(p));
+ p = cdr(p);
+ accumulator += print_str(']');
+ return accumulator
+
+
+print_factor = (p, omitParens, pastFirstFactor) ->
+ # debugger
+ accumulator = ""
+ if (isNumericAtom(p))
+ # in an evaluated term, all the numeric parts
+ # are at the beginning of the term.
+ # When printing the EXPRESSION,
+ # we peek into the first factor of the term and we
+ # look at whether it's a number less then zero.
+ # if it is, we print the "-" as the "leading" part of the
+ # print of the EXPRESSION, and then we proceed printint the factors
+ # of the term. This means that when we come here, we must
+ # skip printing the minus if the number is negative,
+ # because it's already been printed.
+ if pastFirstFactor and lessp(p, zero)
+ accumulator += '('
+ accumulator += print_number(p, pastFirstFactor)
+ if pastFirstFactor and lessp(p, zero)
+ accumulator += ')'
+ return accumulator
+
+ if (isstr(p))
+ accumulator += print_str("\"")
+ accumulator += print_str(p.str)
+ accumulator += print_str("\"")
+ return accumulator
+
+ if (istensor(p))
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_tensor_latex(p)
+ else
+ accumulator += print_tensor(p)
+ return accumulator
+
+ if (car(p) == symbol(MULTIPLY))
+ if !omitParens
+ if (sign_of_term(p) == '-' or printMode != PRINTMODE_LATEX)
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str(" \\left (")
+ else
+ accumulator += print_str('(')
+ accumulator += print_expr(p)
+ if !omitParens
+ if (sign_of_term(p) == '-' or printMode != PRINTMODE_LATEX)
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str(" \\right ) ")
+ else
+ accumulator += print_str(')')
+ return accumulator
+ else if (isadd(p))
+ if !omitParens then accumulator += print_str('(')
+ accumulator += print_expr(p)
+ if !omitParens then accumulator += print_str(')')
+ return accumulator
+
+ if (car(p) == symbol(POWER))
+ base = cadr(p)
+ exponent = caddr(p)
+ accumulator += print_power(base, exponent)
+ return accumulator
+
+ # if (car(p) == _list) {
+ # print_str("{")
+ # p = cdr(p)
+ # if (iscons(p)) {
+ # print_expr(car(p))
+ # p = cdr(p)
+ # }
+ # while (iscons(p)) {
+ # print_str(",")
+ # print_expr(car(p))
+ # p = cdr(p)
+ # }
+ # print_str("}")
+ # return
+ # }
+
+ if (car(p) == symbol(FUNCTION))
+ fbody = cadr(p)
+
+ if !codeGen
+ parameters = caddr(p)
+ accumulator += print_str "function "
+ if DEBUG then console.log "emittedString from print_factor " + stringsEmittedByUserPrintouts
+ returned = print_list parameters
+ accumulator += returned
+ accumulator += print_str " -> "
+ accumulator += print_expr fbody
+ return accumulator
+
+ if (car(p) == symbol(PATTERN))
+
+ accumulator += print_expr(caadr(p))
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str(" \\rightarrow ")
+ else
+ if printMode == PRINTMODE_HUMAN and !test_flag
+ accumulator += print_str(" -> ")
+ else
+ accumulator += print_str("->")
+
+ accumulator += print_expr car(cdr(cadr(p)))
+ return accumulator
+
+
+ if (car(p) == symbol(INDEX) && issymbol(cadr(p)))
+ accumulator += print_index_function(p)
+ return accumulator
+
+ if (car(p) == symbol(FACTORIAL))
+ accumulator += print_factorial_function(p)
+ return accumulator
+ else if (car(p) == symbol(ABS) && printMode == PRINTMODE_LATEX)
+ accumulator += print_ABS_latex(p)
+ return accumulator
+ else if (car(p) == symbol(SQRT) && printMode == PRINTMODE_LATEX)
+ #debugger
+ accumulator += print_SQRT_latex(p)
+ return accumulator
+ else if car(p) == symbol(TRANSPOSE)
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_TRANSPOSE_latex(p)
+ return accumulator
+ else if codeGen
+ accumulator += print_TRANSPOSE_codegen(p)
+ return accumulator
+ else if car(p) == symbol(UNIT)
+ if codeGen
+ accumulator += print_UNIT_codegen(p)
+ return accumulator
+ else if car(p) == symbol(INV)
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_INV_latex(p)
+ return accumulator
+ else if codeGen
+ accumulator += print_INV_codegen(p)
+ return accumulator
+ else if (car(p) == symbol(BINOMIAL) && printMode == PRINTMODE_LATEX)
+ accumulator += print_BINOMIAL_latex(p)
+ return accumulator
+ else if (car(p) == symbol(DEFINT) && printMode == PRINTMODE_LATEX)
+ accumulator += print_DEFINT_latex(p)
+ return accumulator
+ else if isinnerordot(p)
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_DOT_latex(p)
+ return accumulator
+ else if codeGen
+ accumulator += print_DOT_codegen(p)
+ return accumulator
+ else if car(p) == symbol(SIN)
+ if codeGen
+ accumulator += print_SIN_codegen(p)
+ return accumulator
+ else if car(p) == symbol(COS)
+ if codeGen
+ accumulator += print_COS_codegen(p)
+ return accumulator
+ else if car(p) == symbol(TAN)
+ if codeGen
+ accumulator += print_TAN_codegen(p)
+ return accumulator
+ else if car(p) == symbol(ARCSIN)
+ if codeGen
+ accumulator += print_ARCSIN_codegen(p)
+ return accumulator
+ else if car(p) == symbol(ARCCOS)
+ if codeGen
+ accumulator += print_ARCCOS_codegen(p)
+ return accumulator
+ else if car(p) == symbol(ARCTAN)
+ if codeGen
+ accumulator += print_ARCTAN_codegen(p)
+ return accumulator
+ else if car(p) == symbol(SUM)
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_SUM_latex(p)
+ return accumulator
+ else if codeGen
+ accumulator += print_SUM_codegen(p)
+ return accumulator
+ #else if car(p) == symbol(QUOTE)
+ # if printMode == PRINTMODE_LATEX
+ # print_expr(cadr(p))
+ # return accumulator
+ else if car(p) == symbol(PRODUCT)
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_PRODUCT_latex(p)
+ return accumulator
+ else if codeGen
+ accumulator += print_PRODUCT_codegen(p)
+ return accumulator
+ else if car(p) == symbol(FOR)
+ if codeGen
+ accumulator += print_FOR_codegen(p)
+ return accumulator
+ else if car(p) == symbol(DO)
+ if codeGen
+ accumulator += print_DO_codegen(p)
+ return accumulator
+ else if car(p) == symbol(TEST)
+ if codeGen
+ accumulator += print_TEST_codegen(p)
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_TEST_latex(p)
+ return accumulator
+ else if car(p) == symbol(TESTLT)
+ if codeGen
+ accumulator += "(("+print_expr(cadr(p))+") < ("+print_expr(caddr(p))+"))"
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_TESTLT_latex(p)
+ return accumulator
+ else if car(p) == symbol(TESTLE)
+ if codeGen
+ accumulator += "(("+print_expr(cadr(p))+") <= ("+print_expr(caddr(p))+"))"
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_TESTLE_latex(p)
+ return accumulator
+ else if car(p) == symbol(TESTGT)
+ if codeGen
+ accumulator += "(("+print_expr(cadr(p))+") > ("+print_expr(caddr(p))+"))"
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_TESTGT_latex(p)
+ return accumulator
+ else if car(p) == symbol(TESTGE)
+ if codeGen
+ accumulator += "(("+print_expr(cadr(p))+") >= ("+print_expr(caddr(p))+"))"
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_TESTGE_latex(p)
+ return accumulator
+ else if car(p) == symbol(TESTEQ)
+ if codeGen
+ accumulator += "(("+print_expr(cadr(p))+") === ("+print_expr(caddr(p))+"))"
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_TESTEQ_latex(p)
+ return accumulator
+ else if car(p) == symbol(FLOOR)
+ if codeGen
+ accumulator += "Math.floor("+print_expr(cadr(p))+")"
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += " \\lfloor {" + print_expr(cadr(p)) + "} \\rfloor "
+ return accumulator
+ else if car(p) == symbol(CEILING)
+ if codeGen
+ accumulator += "Math.ceiling("+print_expr(cadr(p))+")"
+ return accumulator
+ if printMode == PRINTMODE_LATEX
+ accumulator += " \\lceil {" + print_expr(cadr(p)) + "} \\rceil "
+ return accumulator
+ else if car(p) == symbol(ROUND)
+ if codeGen
+ accumulator += "Math.round("+print_expr(cadr(p))+")"
+ return accumulator
+ else if car(p) == symbol(SETQ)
+ if codeGen
+ accumulator += print_SETQ_codegen(p)
+ return accumulator
+ else
+ accumulator += print_expr cadr p
+ accumulator += print_str("=")
+ accumulator += print_expr caddr p
+ return accumulator
+
+
+ if (iscons(p))
+ #if (car(p) == symbol(FORMAL) && cadr(p)->k == SYM) {
+ # print_str(((struct symbol *) cadr(p))->name)
+ # return
+ #}
+ accumulator += print_factor(car(p))
+ p = cdr(p)
+ if !omitParens then accumulator += print_str('(')
+ if (iscons(p))
+ accumulator += print_expr(car(p))
+ p = cdr(p)
+ while (iscons(p))
+ accumulator += print_str(",")
+ accumulator += print_expr(car(p))
+ p = cdr(p)
+ if !omitParens then accumulator += print_str(')')
+ return accumulator
+
+ if (p == symbol(DERIVATIVE))
+ accumulator += print_char('d')
+ else if (p == symbol(E))
+ if codeGen
+ accumulator += print_str("Math.E")
+ else
+ accumulator += print_str("e")
+ else if (p == symbol(PI))
+ if printMode == PRINTMODE_LATEX
+ accumulator += print_str("\\pi")
+ else
+ accumulator += print_str("pi")
+ else
+ accumulator += print_str(get_printname(p))
+ return accumulator
+
+
+print_list = (p) ->
+ accumulator = ""
+ switch (p.k)
+ when CONS
+ accumulator += ('(')
+ accumulator += print_list(car(p))
+ if p == cdr(p) and p != symbol(NIL)
+ console.log "oh no recursive!"
+ debugger
+ p = cdr(p)
+ while (iscons(p))
+ accumulator += (" ")
+ accumulator += print_list(car(p))
+ p = cdr(p)
+ if p == cdr(p) and p != symbol(NIL)
+ console.log "oh no recursive!"
+ debugger
+ if (p != symbol(NIL))
+ accumulator += (" . ")
+ accumulator += print_list(p)
+ accumulator += (')')
+ when STR
+ #print_str("\"")
+ accumulator += (p.str)
+ #print_str("\"")
+ when NUM, DOUBLE
+ accumulator += print_number(p, true)
+ when SYM
+ accumulator += get_printname(p)
+ else
+ accumulator += ("")
+ return accumulator
+
+print_multiply_sign = ->
+ accumulator = ""
+ if printMode == PRINTMODE_LATEX
+ if printMode == PRINTMODE_HUMAN and !test_flag
+ accumulator += print_str(" ")
+ else
+ return accumulator
+
+ if printMode == PRINTMODE_HUMAN and !test_flag and !codeGen
+ accumulator += print_str(" ")
+ else
+ accumulator += print_str("*")
+ return accumulator
+
+is_denominator = (p) ->
+ if (car(p) == symbol(POWER) && cadr(p) != symbol(E) && isnegativeterm(caddr(p)))
+ return 1
+ else
+ return 0
+
+# don't consider the leading fraction
+# we want 2/3*a*b*c instead of 2*a*b*c/3
+
+any_denominators = (p) ->
+ p = cdr(p)
+ # if (isfraction(car(p)))
+ # return 1
+ while (iscons(p))
+ q = car(p)
+ if (is_denominator(q))
+ return 1
+ p = cdr(p)
+ return 0
+
diff --git a/node_modules/algebrite/sources/print2d.coffee b/node_modules/algebrite/sources/print2d.coffee
new file mode 100644
index 0000000..f94a3ae
--- /dev/null
+++ b/node_modules/algebrite/sources/print2d.coffee
@@ -0,0 +1,1111 @@
+###
+
+Prints in "2d", e.g. instead of 1/(x+1)^2 :
+
+ 1
+ ----------
+ 2
+ (1 + x)
+
+ Note that although this looks more natural, a) it's not parsable and
+ b) it can be occasionally be ambiguous, such as:
+
+ 1
+ ----
+ 2
+ x
+
+is 1/x^2 but it also looks a little like x^(1/2)
+
+###
+
+#-----------------------------------------------------------------------------
+#
+# Examples:
+#
+# 012345678
+# -2 .........
+# -1 .........
+# 0 ..hello.. x=2, y=0, h=1, w=5
+# 1 .........
+# 2 .........
+#
+# 012345678
+# -2 .........
+# -1 ..355....
+# 0 ..---.... x=2, y=-1, h=3, w=3
+# 1 ..113....
+# 2 .........
+#
+#-----------------------------------------------------------------------------
+
+
+
+YMAX = 10000
+class glyph
+ c: 0
+ x: 0
+ y: 0
+
+# will contain glyphs
+chartab = []
+for charTabIndex in [0...YMAX]
+ chartab[charTabIndex] = new glyph()
+
+
+yindex = 0
+level = 0
+emit_x = 0
+expr_level = 0
+display_flag = 0
+
+
+# this is not really the translated version,
+# the original is in window.cpp and is
+# rather more complex
+printchar_nowrap = (character) ->
+ accumulator = ""
+ accumulator += character
+ return accumulator
+
+printchar = (character) ->
+ return printchar_nowrap character
+
+print2dascii = (p) ->
+ h = 0
+ w = 0
+ y = 0
+
+ save()
+
+ yindex = 0
+ level = 0
+ emit_x = 0
+ emit_top_expr(p)
+
+ # if too wide then print flat
+
+ [h,w,y] = get_size(0, yindex)
+
+ if (w > 100)
+ printline(p)
+ restore()
+ return
+
+ beenPrinted = print_glyphs()
+
+ restore()
+ return beenPrinted
+
+emit_top_expr = (p) ->
+ if (car(p) == symbol(SETQ))
+ emit_expr(cadr(p))
+ __emit_str(" = ")
+ emit_expr(caddr(p))
+ return
+
+ if (istensor(p))
+ emit_tensor(p)
+ else
+ emit_expr(p)
+
+will_be_displayed_as_fraction = (p) ->
+ if (level > 0)
+ return 0
+ if (isfraction(p))
+ return 1
+ if (car(p) != symbol(MULTIPLY))
+ return 0
+ if (isfraction(cadr(p)))
+ return 1
+ while (iscons(p))
+ if (isdenominator(car(p)))
+ return 1
+ p = cdr(p)
+ return 0
+
+emit_expr = (p) ->
+ # if (level > 0) {
+ # printexpr(p)
+ # return
+ # }
+ expr_level++
+ if (car(p) == symbol(ADD))
+ p = cdr(p)
+ if (__is_negative(car(p)))
+ __emit_char('-')
+ if (will_be_displayed_as_fraction(car(p)))
+ __emit_char(' ')
+ emit_term(car(p))
+ p = cdr(p)
+ while (iscons(p))
+ if (__is_negative(car(p)))
+ __emit_char(' ')
+ __emit_char('-')
+ __emit_char(' ')
+ else
+ __emit_char(' ')
+ __emit_char('+')
+ __emit_char(' ')
+
+ emit_term(car(p))
+ p = cdr(p)
+ else
+ if (__is_negative(p))
+ __emit_char('-')
+ if (will_be_displayed_as_fraction(p))
+ __emit_char(' ')
+ emit_term(p)
+ expr_level--
+
+emit_unsigned_expr = (p) ->
+ if (car(p) == symbol(ADD))
+ p = cdr(p)
+ # if (__is_negative(car(p)))
+ # __emit_char('-')
+ emit_term(car(p))
+ p = cdr(p)
+ while (iscons(p))
+ if (__is_negative(car(p)))
+ __emit_char(' ')
+ __emit_char('-')
+ __emit_char(' ')
+ else
+ __emit_char(' ')
+ __emit_char('+')
+ __emit_char(' ')
+ emit_term(car(p))
+ p = cdr(p)
+ else
+ # if (__is_negative(p))
+ # __emit_char('-')
+ emit_term(p)
+
+__is_negative = (p) ->
+ if (isnegativenumber(p))
+ return 1
+ if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p)))
+ return 1
+ return 0
+
+emit_term = (p) ->
+ if (car(p) == symbol(MULTIPLY))
+ n = count_denominators(p)
+ if (n && level == 0)
+ emit_fraction(p, n)
+ else
+ emit_multiply(p, n)
+ else
+ emit_factor(p)
+
+isdenominator = (p) ->
+ if (car(p) == symbol(POWER) && cadr(p) != symbol(E) && __is_negative(caddr(p)))
+ return 1
+ else
+ return 0
+
+count_denominators = (p) ->
+ count = 0
+ p = cdr(p)
+ # if (isfraction(car(p))) {
+ # count++
+ # p = cdr(p)
+ # }
+ while (iscons(p))
+ q = car(p)
+ if (isdenominator(q))
+ count++
+ p = cdr(p)
+ return count
+
+# n is the number of denominators, not counting a fraction like 1/2
+emit_multiply = (p, n) ->
+ if (n == 0)
+ p = cdr(p)
+ if (isplusone(car(p)) || isminusone(car(p)))
+ p = cdr(p)
+ emit_factor(car(p))
+ p = cdr(p)
+ while (iscons(p))
+ __emit_char(' ')
+ emit_factor(car(p))
+ p = cdr(p)
+ else
+ emit_numerators(p)
+ __emit_char('/')
+ # need grouping if more than one denominator
+ if (n > 1 || isfraction(cadr(p)))
+ __emit_char('(')
+ emit_denominators(p)
+ __emit_char(')')
+ else
+ emit_denominators(p)
+
+#define A p3
+#define B p4
+
+# sign of term has already been emitted
+
+emit_fraction = (p, d) ->
+ count = 0
+ k1 = 0
+ k2 = 0
+ n = 0
+ x = 0
+
+ save()
+
+ p3 = one; # p3 is A
+ p4 = one; # p4 is B
+
+ # handle numerical coefficient
+
+ if (isrational(cadr(p)))
+ push(cadr(p))
+ mp_numerator()
+ absval()
+ p3 = pop(); # p3 is A
+ push(cadr(p))
+ mp_denominator()
+ p4 = pop(); # p4 is B
+
+ if (isdouble(cadr(p)))
+ push(cadr(p))
+ absval()
+ p3 = pop(); # p3 is A
+
+ # count numerators
+
+ if (isplusone(p3)) # p3 is A
+ n = 0
+ else
+ n = 1
+ p1 = cdr(p)
+ if (isNumericAtom(car(p1)))
+ p1 = cdr(p1)
+ while (iscons(p1))
+ p2 = car(p1)
+ if (isdenominator(p2))
+ doNothing = 1
+ else
+ n++
+ p1 = cdr(p1)
+
+ # emit numerators
+
+ x = emit_x
+
+ k1 = yindex
+
+ count = 0
+
+ # emit numerical coefficient
+
+ if (!isplusone(p3)) # p3 is A
+ emit_number(p3, 0); # p3 is A
+ count++
+
+ # skip over "multiply"
+
+ p1 = cdr(p)
+
+ # skip over numerical coefficient, already handled
+
+ if (isNumericAtom(car(p1)))
+ p1 = cdr(p1)
+
+ while (iscons(p1))
+ p2 = car(p1)
+ if (isdenominator(p2))
+ doNothing = 1
+ else
+ if (count > 0)
+ __emit_char(' ')
+ if (n == 1)
+ emit_expr(p2)
+ else
+ emit_factor(p2)
+ count++
+ p1 = cdr(p1)
+
+ if (count == 0)
+ __emit_char('1')
+
+ # emit denominators
+
+ k2 = yindex
+
+ count = 0
+
+ if (!isplusone(p4)) # p4 is B
+ emit_number(p4, 0); # p4 is B
+ count++
+ d++
+
+ p1 = cdr(p)
+
+ if (isrational(car(p1)))
+ p1 = cdr(p1)
+
+ while (iscons(p1))
+ p2 = car(p1)
+ if (isdenominator(p2))
+ if (count > 0)
+ __emit_char(' ')
+ emit_denominator(p2, d)
+ count++
+ p1 = cdr(p1)
+
+ fixup_fraction(x, k1, k2)
+
+ restore()
+
+# p points to a multiply
+
+emit_numerators = (p) ->
+ save()
+
+ n = 0
+
+ p1 = one
+
+ p = cdr(p)
+
+ if (isrational(car(p)))
+ push(car(p))
+ mp_numerator()
+ absval()
+ p1 = pop()
+ p = cdr(p)
+ else if (isdouble(car(p)))
+ push(car(p))
+ absval()
+ p1 = pop()
+ p = cdr(p)
+
+ n = 0
+
+ if (!isplusone(p1))
+ emit_number(p1, 0)
+ n++
+
+ while (iscons(p))
+ if (isdenominator(car(p)))
+ doNothing = 1
+ else
+ if (n > 0)
+ __emit_char(' ')
+ emit_factor(car(p))
+ n++
+ p = cdr(p)
+
+ if (n == 0)
+ __emit_char('1')
+
+ restore()
+
+# p points to a multiply
+
+emit_denominators = (p) ->
+
+ save()
+
+ n = 0
+
+ p = cdr(p)
+
+ if (isfraction(car(p)))
+ push(car(p))
+ mp_denominator()
+ p1 = pop()
+ emit_number(p1, 0)
+ n++
+ p = cdr(p)
+
+ while (iscons(p))
+ if (isdenominator(car(p)))
+ if (n > 0)
+ __emit_char(' ')
+ emit_denominator(car(p), 0)
+ n++
+ p = cdr(p)
+
+ restore()
+
+emit_factor = (p) ->
+ if (istensor(p))
+ if (level == 0)
+ #emit_tensor(p)
+ emit_flat_tensor(p)
+ else
+ emit_flat_tensor(p)
+ return
+
+ if (isdouble(p))
+ emit_number(p, 0)
+ return
+
+ if (car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY))
+ emit_subexpr(p)
+ return
+
+ if (car(p) == symbol(POWER))
+ emit_power(p)
+ return
+
+ if (iscons(p))
+ #if (car(p) == symbol(FORMAL) && cadr(p).k == SYM)
+ # emit_symbol(cadr(p))
+ #else
+ emit_function(p)
+ return
+
+ if (isNumericAtom(p))
+ if (level == 0)
+ emit_numerical_fraction(p)
+ else
+ emit_number(p, 0)
+ return
+
+ if (issymbol(p))
+ emit_symbol(p)
+ return
+
+ if (isstr(p))
+ emit_string(p)
+ return
+
+emit_numerical_fraction = (p) ->
+ k1 = 0
+ k2 = 0
+ x = 0
+
+ save()
+
+ push(p)
+ mp_numerator()
+ absval()
+ p3 = pop(); # p3 is A
+
+ push(p)
+ mp_denominator()
+ p4 = pop(); # p4 is B
+
+ if (isplusone(p4)) # p4 is B
+ emit_number(p3, 0); # p3 is A
+ restore()
+ return
+
+ x = emit_x
+
+ k1 = yindex
+
+ emit_number(p3, 0); # p3 is A
+
+ k2 = yindex
+
+ emit_number(p4, 0) # p4 is B
+
+ fixup_fraction(x, k1, k2)
+
+ restore()
+
+# if it's a factor then it doesn't need parens around it, i.e. 1/sin(theta)^2
+
+isfactor = (p) ->
+ if (iscons(p) && car(p) != symbol(ADD) && car(p) != symbol(MULTIPLY) && car(p) != symbol(POWER))
+ return 1
+ if (issymbol(p))
+ return 1
+ if (isfraction(p))
+ return 0
+ if (isnegativenumber(p))
+ return 0
+ if (isNumericAtom(p))
+ return 1
+ return 0
+
+emit_power = (p) ->
+ k1 = 0
+ k2 = 0
+ x = 0
+
+ if (cadr(p) == symbol(E))
+ __emit_str("exp(")
+ emit_expr(caddr(p))
+ __emit_char(')')
+ return
+
+ if (level > 0)
+ if (isminusone(caddr(p)))
+ __emit_char('1')
+ __emit_char('/')
+ if (isfactor(cadr(p)))
+ emit_factor(cadr(p))
+ else
+ emit_subexpr(cadr(p))
+ else
+ if (isfactor(cadr(p)))
+ emit_factor(cadr(p))
+ else
+ emit_subexpr(cadr(p))
+ __emit_char('^')
+ if (isfactor(caddr(p)))
+ emit_factor(caddr(p))
+ else
+ emit_subexpr(caddr(p))
+ return
+
+ # special case: 1 over something
+
+ if (__is_negative(caddr(p)))
+ x = emit_x
+ k1 = yindex
+ __emit_char('1')
+ k2 = yindex
+ #level++
+ emit_denominator(p, 1)
+ #level--
+ fixup_fraction(x, k1, k2)
+ return
+
+ k1 = yindex
+ if (isfactor(cadr(p)))
+ emit_factor(cadr(p))
+ else
+ emit_subexpr(cadr(p))
+ k2 = yindex
+ level++
+ emit_expr(caddr(p))
+ level--
+ fixup_power(k1, k2)
+
+# if n == 1 then emit as expr (no parens)
+
+# p is a power
+
+emit_denominator = (p, n) ->
+ k1 = 0
+ k2 = 0
+
+ # special case: 1 over something
+
+ if (isminusone(caddr(p)))
+ if (n == 1)
+ emit_expr(cadr(p))
+ else
+ emit_factor(cadr(p))
+ return
+
+ k1 = yindex
+
+ # emit base
+
+ if (isfactor(cadr(p)))
+ emit_factor(cadr(p))
+ else
+ emit_subexpr(cadr(p))
+
+ k2 = yindex
+
+ # emit exponent, don't emit minus sign
+
+ level++
+
+ emit_unsigned_expr(caddr(p))
+
+ level--
+
+ fixup_power(k1, k2)
+
+emit_function = (p) ->
+ if (car(p) == symbol(INDEX) && issymbol(cadr(p)))
+ emit_index_function(p)
+ return
+
+ if (car(p) == symbol(FACTORIAL))
+ emit_factorial_function(p)
+ return
+
+ if (car(p) == symbol(DERIVATIVE))
+ __emit_char('d')
+ else
+ emit_symbol(car(p))
+ __emit_char('(')
+ p = cdr(p)
+ if (iscons(p))
+ emit_expr(car(p))
+ p = cdr(p)
+ while (iscons(p))
+ __emit_char(',')
+ #__emit_char(' ')
+ emit_expr(car(p))
+ p = cdr(p)
+ __emit_char(')')
+
+emit_index_function = (p) ->
+ p = cdr(p)
+ if (caar(p) == symbol(ADD) || caar(p) == symbol(MULTIPLY) || caar(p) == symbol(POWER) || caar(p) == symbol(FACTORIAL))
+ emit_subexpr(car(p))
+ else
+ emit_expr(car(p))
+ __emit_char('[')
+ p = cdr(p)
+ if (iscons(p))
+ emit_expr(car(p))
+ p = cdr(p)
+ while(iscons(p))
+ __emit_char(',')
+ emit_expr(car(p))
+ p = cdr(p)
+ __emit_char(']')
+
+emit_factorial_function = (p) ->
+ p = cadr(p)
+ if (isfraction(p) || car(p) == symbol(ADD) || car(p) == symbol(MULTIPLY) || car(p) == symbol(POWER) || car(p) == symbol(FACTORIAL))
+ emit_subexpr(p)
+ else
+ emit_expr(p)
+ __emit_char('!')
+
+emit_subexpr = (p) ->
+ __emit_char('(')
+ emit_expr(p)
+ __emit_char(')')
+
+emit_symbol = (p) ->
+
+ i = 0
+ if (p == symbol(E))
+ __emit_str("exp(1)")
+ return
+
+ pPrintName = get_printname(p)
+ for i in [0...pPrintName.length]
+ __emit_char(pPrintName[i])
+
+emit_string = (p) ->
+ i = 0
+ pString = p.str
+ __emit_char('"')
+ for i in [0...pString.length]
+ __emit_char(pString[i])
+ __emit_char('"')
+
+fixup_fraction = (x, k1, k2) ->
+ dx = 0
+ dy = 0
+ i = 0
+ w = 0
+ y = 0
+ h1 = 0
+ w1 = 0
+ y1 = 0
+ h2 = 0
+ w2 = 0
+ y2 = 0
+
+ [h1,w1,y1] = get_size(k1, k2)
+ [h2,w2,y2] = get_size(k2, yindex)
+
+ if (w2 > w1)
+ dx = (w2 - w1) / 2; # shift numerator right
+ else
+ dx = 0
+
+ dx++
+ # this is how much is below the baseline
+
+ y = y1 + h1 - 1
+
+ dy = -y - 1
+
+ move(k1, k2, dx, dy)
+
+ if (w2 > w1)
+ dx = -w1
+ else
+ dx = -w1 + (w1 - w2) / 2
+
+ dx++
+ dy = -y2 + 1
+
+ move(k2, yindex, dx, dy)
+
+ if (w2 > w1)
+ w = w2
+ else
+ w = w1
+
+ w+=2
+ emit_x = x
+
+ for i in [0...w]
+ __emit_char('-')
+
+fixup_power = (k1, k2) ->
+ dy = 0
+ h1 = 0
+ w1 = 0
+ y1 = 0
+ h2 = 0
+ w2 = 0
+ y2 = 0
+
+ [h1,w1,y1] = get_size(k1, k2)
+ [h2,w2,y2] = get_size(k2, yindex)
+
+ # move superscript to baseline
+
+ dy = -y2 - h2 + 1
+
+ # now move above base
+
+ dy += y1 - 1
+
+ move(k2, yindex, 0, dy)
+
+move = (j, k, dx, dy) ->
+ i = 0
+ for i in [j...k]
+ chartab[i].x += dx
+ chartab[i].y += dy
+
+# finds the bounding rectangle and vertical position
+
+get_size = (j, k)->
+ i = 0
+ min_x = chartab[j].x
+ max_x = chartab[j].x
+ min_y = chartab[j].y
+ max_y = chartab[j].y
+ for i in [(j + 1)...k]
+ if (chartab[i].x < min_x)
+ min_x = chartab[i].x
+ if (chartab[i].x > max_x)
+ max_x = chartab[i].x
+ if (chartab[i].y < min_y)
+ min_y = chartab[i].y
+ if (chartab[i].y > max_y)
+ max_y = chartab[i].y
+ h = max_y - min_y + 1
+ w = max_x - min_x + 1
+ y = min_y
+ return [h,w,y]
+
+displaychar = (c) ->
+ __emit_char(c)
+
+__emit_char = (c) ->
+ if (yindex == YMAX)
+ return
+ if !chartab[yindex]?
+ debugger
+ chartab[yindex].c = c
+ chartab[yindex].x = emit_x
+ chartab[yindex].y = 0
+ yindex++
+ emit_x++
+
+__emit_str = (s) ->
+ i = 0
+ for i in [0...s.length]
+ __emit_char(s[i])
+
+emit_number = (p, emit_sign) ->
+ tmpString = ""
+ i = 0
+ switch (p.k)
+ when NUM
+ tmpString = p.q.a.toString()
+ if (tmpString[0] == '-' && emit_sign == 0)
+ tmpString = tmpString.substring(1)
+ for i in [0...tmpString.length]
+ __emit_char(tmpString[i])
+ tmpString = p.q.b.toString()
+ if (tmpString == "1")
+ break
+ __emit_char('/')
+ for i in [0...tmpString.length]
+ __emit_char(tmpString[i])
+
+ when DOUBLE
+ tmpString = doubleToReasonableString(p.d)
+ if (tmpString[0] == '-' && emit_sign == 0)
+ tmpString = tmpString.substring(1)
+ for i in [0...tmpString.length]
+ __emit_char(tmpString[i])
+
+# a and b are glyphs
+cmpGlyphs = (a, b) ->
+
+ if (a.y < b.y)
+ return -1
+
+ if (a.y > b.y)
+ return 1
+
+ if (a.x < b.x)
+ return -1
+
+ if (a.x > b.x)
+ return 1
+
+ return 0
+
+print_glyphs = ->
+
+ i = 0
+ accumulator = ""
+
+ # now sort the glyphs by their vertical positions,
+ # since we are going to build a string where obviously the
+ # "upper" line has to printed out first, followed by
+ # a new line, followed by the other lines.
+ #qsort(chartab, yindex, sizeof (struct glyph), __cmp)
+ subsetOfStack = chartab.slice(0,yindex)
+ subsetOfStack.sort(cmpGlyphs)
+ chartab = [].concat(subsetOfStack).concat(chartab.slice(yindex))
+
+ x = 0
+
+ y = chartab[0].y
+
+ for i in [0...yindex]
+
+ while (chartab[i].y > y)
+ accumulator += printchar('\n')
+ x = 0
+ y++
+
+ while (chartab[i].x > x)
+ accumulator += printchar_nowrap(' ')
+ x++
+
+ accumulator += printchar_nowrap(chartab[i].c)
+
+ x++
+
+ return accumulator
+
+buffer = ""
+
+getdisplaystr = ->
+ yindex = 0
+ level = 0
+ emit_x = 0
+ emit_expr(pop())
+ fill_buf()
+ return buffer
+
+fill_buf = ->
+ tmpBuffer = buffer
+ sIndex = 0
+ i = 0
+
+ #qsort(chartab, yindex, sizeof (struct glyph), __cmp)
+ subsetOfStack = chartab.slice(0,yindex)
+ subsetOfStack.sort(cmpGlyphs)
+ chartab = [].concat(subsetOfStack).concat(chartab.slice(yindex))
+
+ x = 0
+
+ y = chartab[0].y
+
+ for i in [0...yindex]
+
+ while (chartab[i].y > y)
+ tmpBuffer[sIndex++] = '\n'
+ x = 0
+ y++
+
+ while (chartab[i].x > x)
+ tmpBuffer[sIndex++] = ' '
+ x++
+
+ tmpBuffer[sIndex++] = chartab[i].c
+
+ x++
+
+ tmpBuffer[sIndex++] = '\n'
+
+
+N = 100
+
+class oneElement
+ x: 0
+ y: 0
+ h: 0
+ w: 0
+ index: 0
+ count: 0
+
+elem = []
+for elelmIndex in [0...10000]
+ elem[elelmIndex] = new oneElement
+
+SPACE_BETWEEN_COLUMNS = 3
+SPACE_BETWEEN_ROWS = 1
+
+emit_tensor = (p) ->
+ i = 0
+ n = 0
+ nrow = 0
+ ncol = 0
+ x = 0
+ y = 0
+ h = 0
+ w = 0
+ dx = 0
+ dy = 0
+ eh = 0
+ ew = 0
+ row = 0
+ col = 0
+
+ if (p.tensor.ndim > 2)
+ emit_flat_tensor(p)
+ return
+
+ nrow = p.tensor.dim[0]
+
+ if (p.tensor.ndim == 2)
+ ncol = p.tensor.dim[1]
+ else
+ ncol = 1
+
+ n = nrow * ncol
+
+ if (n > N)
+ emit_flat_tensor(p)
+ return
+
+ # horizontal coordinate of the matrix
+
+ #if 0
+ #emit_x += 2; # make space for left paren
+ #endif
+
+ x = emit_x
+
+ # emit each element
+
+ for i in [0...n]
+ elem[i].index = yindex
+ elem[i].x = emit_x
+ emit_expr(p.tensor.elem[i])
+ elem[i].count = yindex - elem[i].index
+ [elem[i].h, elem[i].w, elem[i].y] = get_size(elem[i].index, yindex)
+
+ # find element height and width
+
+ eh = 0
+ ew = 0
+
+ for i in [0...n]
+ if (elem[i].h > eh)
+ eh = elem[i].h
+ if (elem[i].w > ew)
+ ew = elem[i].w
+
+ # this is the overall height of the matrix
+
+ h = nrow * eh + (nrow - 1) * SPACE_BETWEEN_ROWS
+
+ # this is the overall width of the matrix
+
+ w = ncol * ew + (ncol - 1) * SPACE_BETWEEN_COLUMNS
+
+ # this is the vertical coordinate of the matrix
+
+ y = -(h / 2)
+
+ # move elements around
+
+ for row in [0...nrow]
+ for col in [0...ncol]
+
+ i = row * ncol + col
+
+ # first move to upper left corner of matrix
+
+ dx = x - elem[i].x
+ dy = y - elem[i].y
+
+ move(elem[i].index, elem[i].index + elem[i].count, dx, dy)
+
+ # now move to official position
+
+ dx = 0
+
+ if (col > 0)
+ dx = col * (ew + SPACE_BETWEEN_COLUMNS)
+
+ dy = 0
+
+ if (row > 0)
+ dy = row * (eh + SPACE_BETWEEN_ROWS)
+
+ # small correction for horizontal centering
+
+ dx += (ew - elem[i].w) / 2
+
+ # small correction for vertical centering
+
+ dy += (eh - elem[i].h) / 2
+
+ move(elem[i].index, elem[i].index + elem[i].count, dx, dy)
+
+ emit_x = x + w
+
+ ###
+ if 0
+
+ # left brace
+
+ for (i = 0; i < h; i++) {
+ if (yindex == YMAX)
+ break
+ chartab[yindex].c = '|'
+ chartab[yindex].x = x - 2
+ chartab[yindex].y = y + i
+ yindex++
+ }
+
+ # right brace
+
+ emit_x++
+
+ for (i = 0; i < h; i++) {
+ if (yindex == YMAX)
+ break
+ chartab[yindex].c = '|'
+ chartab[yindex].x = emit_x
+ chartab[yindex].y = y + i
+ yindex++
+ }
+
+ emit_x++
+
+ endif
+ ###
+
+
+emit_flat_tensor = (p) ->
+ emit_tensor_inner(p, 0, 0)
+
+emit_tensor_inner = (p, j, k) ->
+ i = 0
+ __emit_char('(')
+ for i in [0...p.tensor.dim[j]]
+ if (j + 1 == p.tensor.ndim)
+ emit_expr(p.tensor.elem[k])
+ k = k + 1
+ else
+ k = emit_tensor_inner(p, j + 1, k)
+ if (i + 1 < p.tensor.dim[j])
+ __emit_char(',')
+ __emit_char(')')
+ return k
+
+
diff --git a/node_modules/algebrite/sources/product.coffee b/node_modules/algebrite/sources/product.coffee
new file mode 100644
index 0000000..58ec7ab
--- /dev/null
+++ b/node_modules/algebrite/sources/product.coffee
@@ -0,0 +1,59 @@
+# 'product' function
+
+#define A p3
+#define B p4
+#define I p5
+#define X p6
+
+# leaves the product at the top of the stack
+
+Eval_product = ->
+ i = 0
+ j = 0
+ k = 0
+
+ # 1st arg
+ body = cadr(p1)
+
+ # 2nd arg (index)
+ indexVariable = caddr(p1)
+ if (!issymbol(indexVariable))
+ stop("sum: 2nd arg?")
+
+ # 3rd arg (lower limit)
+ push(cadddr(p1))
+ Eval()
+ j = pop_integer()
+ if (isNaN(j))
+ push p1
+ return
+
+ # 4th arg (upper limit)
+ push(caddddr(p1))
+ Eval()
+ k = pop_integer()
+ if (isNaN(k))
+ push p1
+ return
+
+ # remember contents of the index
+ # variable so we can put it back after the loop
+ oldIndexVariableValue = get_binding(indexVariable)
+
+ push_integer(1)
+
+ for i in [j..k]
+ push_integer(i)
+ p5 = pop()
+ set_binding(indexVariable, p5)
+ push(body)
+ Eval()
+ if DEBUG
+ console.log "product - factor 1: " + stack[tos-1].toString()
+ console.log "product - factor 2: " + stack[tos-2].toString()
+ multiply()
+ if DEBUG
+ console.log "product - result: " + stack[tos-1].toString()
+
+ # put back the index variable to original content
+ set_binding(indexVariable, oldIndexVariableValue)
diff --git a/node_modules/algebrite/sources/qadd.coffee b/node_modules/algebrite/sources/qadd.coffee
new file mode 100644
index 0000000..cdc07b9
--- /dev/null
+++ b/node_modules/algebrite/sources/qadd.coffee
@@ -0,0 +1,61 @@
+# Add rational numbers
+#
+# Input: tos-2 addend
+#
+# tos-1 addend
+#
+# Output: sum on stack
+
+
+
+qadd = ->
+ # a, qadd_ab, b, qadd_ba, c are all bigNum
+ # we are adding the fractions qadd_frac1 + qadd_frac2 i.e.
+ # qadd_frac1.q.a/qadd_frac1.q.b + qadd_frac2.q.a/qadd_frac2.q.b
+
+ qadd_frac2 = pop()
+ qadd_frac1 = pop()
+
+ qadd_ab = mmul(qadd_frac1.q.a, qadd_frac2.q.b)
+ qadd_ba = mmul(qadd_frac1.q.b, qadd_frac2.q.a)
+
+ qadd_numerator = madd(qadd_ab, qadd_ba)
+
+ #mfree(qadd_ab)
+ #mfree(qadd_ba)
+
+ # zero?
+
+ if (MZERO(qadd_numerator))
+ #console.log "qadd IS ZERO"
+ #mfree(qadd_numerator)
+ push(zero)
+ return
+
+ qadd_denominator = mmul(qadd_frac1.q.b, qadd_frac2.q.b)
+
+ gcdBetweenNumeratorAndDenominator = mgcd(qadd_numerator, qadd_denominator)
+ #console.log "gcd("+qadd_numerator+","+qadd_denominator+"): " + gcdBetweenNumeratorAndDenominator
+
+ gcdBetweenNumeratorAndDenominator = makeSignSameAs(gcdBetweenNumeratorAndDenominator,qadd_denominator)
+
+ #console.log "qadd qadd_denominator: " + qadd_denominator
+ #console.log "qadd gcdBetweenNumeratorAndDenominator: " + gcdBetweenNumeratorAndDenominator
+
+ resultSum = new U()
+
+ resultSum.k = NUM
+
+ resultSum.q.a = mdiv(qadd_numerator, gcdBetweenNumeratorAndDenominator)
+ resultSum.q.b = mdiv(qadd_denominator, gcdBetweenNumeratorAndDenominator)
+
+ #console.log "qadd resultSum.q.a: " + resultSum.q.a
+ #console.log "qadd resultSum.q.b: " + resultSum.q.b
+
+ #mfree(qadd_numerator)
+ #mfree(qadd_denominator)
+ #mfree(gcdBetweenNumeratorAndDenominator)
+
+ push(resultSum)
+ #console.log "qadd result: " + resultSum
+
diff --git a/node_modules/algebrite/sources/qdiv.coffee b/node_modules/algebrite/sources/qdiv.coffee
new file mode 100644
index 0000000..0fe01b2
--- /dev/null
+++ b/node_modules/algebrite/sources/qdiv.coffee
@@ -0,0 +1,44 @@
+# Divide rational numbers
+#
+# Input: tos-2 dividend
+#
+# tos-1 divisor
+#
+# Output: quotient on stack
+
+
+
+qdiv = ->
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ # zero?
+
+ if (MZERO(p2.q.a))
+ stop("divide by zero")
+
+ if (MZERO(p1.q.a))
+ push(zero)
+ restore()
+ return
+
+ aa = mmul(p1.q.a, p2.q.b)
+ bb = mmul(p1.q.b, p2.q.a)
+
+ c = mgcd(aa, bb)
+
+ c = makeSignSameAs(c,bb)
+
+ p1 = new U()
+
+ p1.k = NUM
+
+ p1.q.a = mdiv(aa, c)
+ p1.q.b = mdiv(bb, c)
+
+
+ push(p1)
+
+ restore()
diff --git a/node_modules/algebrite/sources/qmul.coffee b/node_modules/algebrite/sources/qmul.coffee
new file mode 100644
index 0000000..2677b8a
--- /dev/null
+++ b/node_modules/algebrite/sources/qmul.coffee
@@ -0,0 +1,43 @@
+# Multiply rational numbers
+#
+# Input: tos-2 multiplicand
+#
+# tos-1 multiplier
+#
+# Output: product on stack
+
+
+
+qmul = ->
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ # zero?
+
+ if (MZERO(p1.q.a) || MZERO(p2.q.a))
+ push(zero)
+ restore()
+ return
+
+ aa = mmul(p1.q.a, p2.q.a)
+ bb = mmul(p1.q.b, p2.q.b)
+
+ c = mgcd(aa, bb)
+
+ c = makeSignSameAs(c,bb)
+
+ p1 = new U()
+
+ p1.k = NUM
+
+ p1.q.a = mdiv(aa, c)
+ p1.q.b = mdiv(bb, c)
+
+ #mfree(aa)
+ #mfree(bb)
+
+ push(p1)
+
+ restore()
diff --git a/node_modules/algebrite/sources/qpow.coffee b/node_modules/algebrite/sources/qpow.coffee
new file mode 100644
index 0000000..7867cca
--- /dev/null
+++ b/node_modules/algebrite/sources/qpow.coffee
@@ -0,0 +1,236 @@
+# Rational power function
+
+
+
+qpow = ->
+ save()
+ qpowf()
+ restore()
+
+#define BASE p1
+#define EXPO p2
+
+qpowf = ->
+ expo = 0
+ #unsigned int a, b, *t, *x, *y
+
+ p2 = pop(); # p2 is EXPO
+ p1 = pop(); # p1 is BASE
+
+ # if base is 1 or exponent is 0 then return 1
+ if (isplusone(p1) || isZeroAtomOrTensor(p2)) # p1 is BASE # p2 is EXPO
+ push_integer(1)
+ return
+
+ # if (-1)^(1/2) -> leave it as is
+ if (isminusone(p1) and isoneovertwo(p2)) # p1 is BASE # p2 is EXPO
+ push(imaginaryunit)
+ return
+
+ # if base is zero then return 0
+ if (isZeroAtomOrTensor(p1)) # p1 is BASE
+ if (isnegativenumber(p2)) # p2 is EXPO
+ stop("divide by zero")
+ push(zero)
+ return
+
+ # if exponent is 1 then return base
+ if (isplusone(p2)) # p2 is EXPO
+ push(p1); # p1 is BASE
+ return
+
+ # if exponent is integer then power
+ if (isinteger(p2)) # p2 is EXPO
+ push(p2); # p2 is EXPO
+ expo = pop_integer()
+ if isNaN(expo)
+ # expo greater than 32 bits
+ push_symbol(POWER)
+ push(p1); # p1 is BASE
+ push(p2); # p2 is EXPO
+ list(3)
+ return
+
+ x = mpow(p1.q.a, Math.abs(expo)); # p1 is BASE
+ y = mpow(p1.q.b, Math.abs(expo)); # p1 is BASE
+ if (expo < 0)
+ t = x
+ x = y
+ y = t
+ x = makeSignSameAs(x,y)
+ y = makePositive(y)
+
+ p3 = new U()
+ p3.k = NUM
+ p3.q.a = x
+ p3.q.b = y
+ push(p3)
+ return
+
+ # from here on out the exponent is NOT an integer
+
+ # if base is -1 then normalize polar angle
+ if (isminusone(p1)) # p1 is BASE
+ push(p2); # p2 is EXPO
+ normalize_angle()
+ return
+
+ # if base is negative then (-N)^M -> N^M * (-1)^M
+ if (isnegativenumber(p1)) # p1 is BASE
+ push(p1); # p1 is BASE
+ negate()
+ push(p2); # p2 is EXPO
+ qpow()
+
+ push_integer(-1)
+ push(p2); # p2 is EXPO
+ qpow()
+
+ multiply()
+ return
+
+ # if p1 (BASE) is not an integer then power numerator and denominator
+ if (!isinteger(p1)) # p1 is BASE
+ push(p1); # p1 is BASE
+ mp_numerator()
+ push(p2); # p2 is EXPO
+ qpow()
+ push(p1); # p1 is BASE
+ mp_denominator()
+ push(p2); # p2 is EXPO
+ negate()
+ qpow()
+ multiply()
+ return
+
+ # At this point p1 (BASE) is a positive integer.
+
+ # If p1 (BASE) is small then factor it.
+ if (is_small_integer(p1)) # p1 is BASE
+ push(p1); # p1 is BASE
+ push(p2); # p2 is EXPO
+ quickfactor()
+ return
+
+ # At this point p1 (BASE) is a positive integer and p2 (EXPO) is not an integer.
+
+ if ( !isSmall(p2.q.a) || !isSmall(p2.q.b) ) # p2 is EXPO
+ push_symbol(POWER)
+ push(p1) # p1 is BASE
+ push(p2); # p2 is EXPO
+ list(3)
+ return
+
+ a = p2.q.a; # p2 is EXPO
+ b = p2.q.b; # p2 is EXPO
+
+ x = mroot(p1.q.a, b); # p1 is BASE
+
+ if (x == 0)
+ push_symbol(POWER)
+ push(p1); # p1 is BASE
+ push(p2); # p2 is EXPO
+ list(3)
+ return
+
+ y = mpow(x, a)
+
+ #mfree(x)
+
+ p3 = new U()
+
+ p3.k = NUM
+
+ if (p2.q.a.isNegative()) # p2 is EXPO
+ p3.q.a = bigInt(1)
+ p3.q.b = y
+ else
+ p3.q.a = y
+ p3.q.b = bigInt(1)
+
+ push(p3)
+
+#-----------------------------------------------------------------------------
+#
+# Normalize the angle of unit imaginary, i.e. (-1) ^ N
+#
+# Input: N on stack (must be rational, not float)
+#
+# Output: Result on stack
+#
+# Note:
+#
+# n = q * d + r
+#
+# Example:
+# n d q r
+#
+# (-1)^(8/3) -> (-1)^(2/3) 8 3 2 2
+# (-1)^(7/3) -> (-1)^(1/3) 7 3 2 1
+# (-1)^(5/3) -> -(-1)^(2/3) 5 3 1 2
+# (-1)^(4/3) -> -(-1)^(1/3) 4 3 1 1
+# (-1)^(2/3) -> (-1)^(2/3) 2 3 0 2
+# (-1)^(1/3) -> (-1)^(1/3) 1 3 0 1
+#
+# (-1)^(-1/3) -> -(-1)^(2/3) -1 3 -1 2
+# (-1)^(-2/3) -> -(-1)^(1/3) -2 3 -1 1
+# (-1)^(-4/3) -> (-1)^(2/3) -4 3 -2 2
+# (-1)^(-5/3) -> (-1)^(1/3) -5 3 -2 1
+# (-1)^(-7/3) -> -(-1)^(2/3) -7 3 -3 2
+# (-1)^(-8/3) -> -(-1)^(1/3) -8 3 -3 1
+#
+#-----------------------------------------------------------------------------
+
+#define A p1
+#define Q p2
+#define R p3
+
+normalize_angle = ->
+ save()
+
+ p1 = pop(); # p1 is A
+
+ # integer exponent?
+
+ if (isinteger(p1)) # p1 is A
+ if (p1.q.a.isOdd()) # p1 is A
+ push_integer(-1); # odd exponent
+ else
+ push_integer(1); # even exponent
+ restore()
+ return
+
+ # floor
+
+ push(p1); # p1 is A
+ bignum_truncate()
+ p2 = pop(); # p2 is Q
+
+ if (isnegativenumber(p1)) # p1 is A
+ push(p2) # p2 is Q
+ push_integer(-1)
+ add()
+ p2 = pop(); # p2 is Q
+
+ # remainder (always positive)
+
+ push(p1); # p1 is A
+ push(p2); # p2 is Q
+ subtract()
+ p3 = pop(); # p3 is R
+
+ # remainder becomes new angle
+ push_symbol(POWER)
+ push_integer(-1)
+ push(p3) # p3 is R
+ list(3)
+
+ # negate if quotient is odd
+
+ if (p2.q.a.isOdd()) # p2 is Q
+ negate()
+
+ restore()
+
+is_small_integer = (p) ->
+ return isSmall(p.q.a)
diff --git a/node_modules/algebrite/sources/quickfactor.coffee b/node_modules/algebrite/sources/quickfactor.coffee
new file mode 100644
index 0000000..08a3deb
--- /dev/null
+++ b/node_modules/algebrite/sources/quickfactor.coffee
@@ -0,0 +1,107 @@
+#-----------------------------------------------------------------------------
+#
+# Factor small numerical powers
+#
+# Input: tos-2 Base (positive integer < 2^31 - 1)
+#
+# tos-1 Exponent
+#
+# Output: Expr on stack
+#
+#-----------------------------------------------------------------------------
+
+
+
+#define BASE p1
+#define EXPO p2
+
+
+quickfactor = ->
+ i = 0
+ save()
+
+ p2 = pop(); # p2 is EXPO
+ p1 = pop(); # p1 is BASE
+
+ h = tos
+
+ push(p1); # p1 is BASE
+
+ factor_small_number()
+
+ n = tos - h
+
+ stackIndex = h
+
+ for i in [0...n] by 2
+ push(stack[stackIndex+i]); # factored base
+ push(stack[stackIndex + i + 1]); # factored exponent
+ push(p2); # p2 is EXPO
+ multiply()
+ quickpower()
+
+ # stack has n results from factor_number_raw()
+
+ # on top of that are all the expressions from quickpower()
+
+ # multiply the quickpower() results
+
+ multiply_all(tos - h - n)
+
+ p1 = pop()
+
+ moveTos h
+
+ push(p1)
+
+ restore()
+
+# p1 (BASE) is a prime number so power is simpler
+
+quickpower = ->
+ expo = 0
+
+ save()
+
+ p2 = pop(); # p2 is EXPO
+ p1 = pop(); # p1 is BASE
+
+ push(p2); # p2 is EXPO
+ bignum_truncate()
+ p3 = pop()
+
+ push(p2); # p2 is EXPO
+ push(p3)
+ subtract()
+ p4 = pop()
+
+ # fractional part of p2 (EXPO)
+
+ if (!isZeroAtomOrTensor(p4))
+ push_symbol(POWER)
+ push(p1); # p1 is BASE
+ push(p4)
+ list(3)
+
+ push(p3)
+ expo = pop_integer()
+
+ if (isNaN(expo))
+ push_symbol(POWER)
+ push(p1); # p1 is BASE
+ push(p3)
+ list(3)
+ restore()
+ return
+
+ if (expo == 0)
+ restore()
+ return
+
+ push(p1); # p1 is BASE
+ bignum_power_number(expo)
+
+ restore()
+
+#if SELFTEST
+
diff --git a/node_modules/algebrite/sources/quotient.coffee b/node_modules/algebrite/sources/quotient.coffee
new file mode 100644
index 0000000..3922250
--- /dev/null
+++ b/node_modules/algebrite/sources/quotient.coffee
@@ -0,0 +1,105 @@
+# Divide polynomials
+
+
+
+Eval_quotient = ->
+ push(cadr(p1)); # 1st arg, p(x)
+ Eval()
+
+ push(caddr(p1)); # 2nd arg, q(x)
+ Eval()
+
+ push(cadddr(p1)); # 3rd arg, x
+ Eval()
+
+ p1 = pop(); # default x
+ if (p1 == symbol(NIL))
+ p1 = symbol(SYMBOL_X)
+ push(p1)
+
+ divpoly()
+
+#-----------------------------------------------------------------------------
+#
+# Divide polynomials
+#
+# Input: tos-3 Dividend
+#
+# tos-2 Divisor
+#
+# tos-1 x
+#
+# Output: tos-1 Quotient
+#
+#-----------------------------------------------------------------------------
+
+#define DIVIDEND p1
+#define DIVISOR p2
+#define X p3
+#define Q p4
+#define QUOTIENT p5
+
+divpoly = ->
+ h = 0
+ i = 0
+ m = 0
+ n = 0
+ x = 0
+ #U **dividend, **divisor
+
+ save()
+
+ p3 = pop()
+ p2 = pop()
+ p1 = pop()
+
+ h = tos
+
+ dividend = tos
+
+ m = coeff(p3, p1) - 1; # m is dividend's power
+
+ divisor = tos
+
+ n = coeff(p3, p2) - 1; # n is divisor's power
+
+ x = m - n
+
+ push_integer(0)
+ p5 = pop()
+
+ while (x >= 0)
+
+ push(stack[dividend+m])
+ push(stack[divisor+n])
+ divide()
+ p4 = pop()
+
+ for i in [0..n]
+ push(stack[dividend+x + i])
+ push(stack[divisor+i])
+ push(p4)
+ multiply()
+ subtract()
+ stack[dividend+x + i] = pop()
+
+ push(p5)
+ push(p4)
+ push(p3)
+ push_integer(x)
+ power()
+ multiply()
+ add()
+ p5 = pop()
+
+ m--
+ x--
+
+ moveTos h
+
+ push(p5)
+
+ restore()
+
+
+
diff --git a/node_modules/algebrite/sources/rationalize.coffee b/node_modules/algebrite/sources/rationalize.coffee
new file mode 100644
index 0000000..8df6df8
--- /dev/null
+++ b/node_modules/algebrite/sources/rationalize.coffee
@@ -0,0 +1,148 @@
+
+DEBUG_RATIONALIZE = false
+
+Eval_rationalize = ->
+ push(cadr(p1))
+ Eval()
+ rationalize()
+
+rationalize = ->
+ x = expanding
+ yyrationalize()
+ expanding = x
+
+yyrationalize = ->
+ theArgument = pop()
+
+ if (istensor(theArgument))
+ __rationalize_tensor(theArgument)
+ return
+
+ expanding = 0
+
+ if (car(theArgument) != symbol(ADD))
+ push(theArgument)
+ return
+
+ if DEBUG_RATIONALIZE then console.log("rationalize: this is the input expr: " + theArgument)
+
+ # get new denominator
+
+ push(one)
+ multiply_denominators(theArgument)
+ commonDenominator = pop()
+
+ if DEBUG_RATIONALIZE then console.log("rationalize: this is the new denominator: " + commonDenominator)
+
+ # multiply each term by new denominator
+
+ push(zero)
+ eachTerm = cdr(theArgument)
+ while (iscons(eachTerm))
+ if DEBUG_RATIONALIZE then console.log("term: " + car(eachTerm))
+ push(commonDenominator)
+ push(car(eachTerm))
+ multiply()
+ add()
+ eachTerm = cdr(eachTerm)
+
+ if DEBUG_RATIONALIZE then console.log("rationalize: original terms times new denominator: " + stack[tos - 1])
+
+ # collect common factors
+
+ Condense()
+
+ if DEBUG_RATIONALIZE then console.log("rationalize: after factoring: " + stack[tos - 1])
+
+ # divide by common denominator
+
+ push(commonDenominator)
+ divide()
+
+ if DEBUG_RATIONALIZE then console.log("rationalize: after dividing by new denom. (and we're done): " + stack[tos - 1])
+
+multiply_denominators = (p) ->
+ if (car(p) == symbol(ADD))
+ p = cdr(p)
+ while (iscons(p))
+ multiply_denominators_term(car(p))
+ p = cdr(p)
+ else
+ multiply_denominators_term(p)
+
+multiply_denominators_term = (p) ->
+ if (car(p) == symbol(MULTIPLY))
+ p = cdr(p)
+ while (iscons(p))
+ multiply_denominators_factor(car(p))
+ p = cdr(p)
+ else
+ multiply_denominators_factor(p)
+
+multiply_denominators_factor = (p) ->
+ if (car(p) != symbol(POWER))
+ return
+
+ push(p)
+
+ p = caddr(p)
+
+ # like x^(-2) ?
+
+ if (isnegativenumber(p))
+ inverse()
+ __lcm()
+ return
+
+ # like x^(-a) ?
+
+ if (car(p) == symbol(MULTIPLY) && isnegativenumber(cadr(p)))
+ inverse()
+ __lcm()
+ return
+
+ # no match
+
+ pop()
+
+__rationalize_tensor = (theTensor) ->
+
+ i = 0
+ push(theTensor)
+
+ Eval(); # makes a copy
+
+ theTensor = pop()
+
+ if (!istensor(theTensor)) # might be zero
+ push(theTensor)
+ return
+
+ n = theTensor.tensor.nelem
+
+ for i in [0...n]
+ push(theTensor.tensor.elem[i])
+ rationalize()
+ theTensor.tensor.elem[i] = pop()
+
+ check_tensor_dimensions theTensor
+
+ push(theTensor)
+
+
+
+__lcm = ->
+ save()
+
+ p1 = pop()
+ p2 = pop()
+
+ push(p1)
+ push(p2)
+ multiply()
+ push(p1)
+ push(p2)
+ gcd()
+ divide()
+
+ restore()
diff --git a/node_modules/algebrite/sources/real.coffee b/node_modules/algebrite/sources/real.coffee
new file mode 100644
index 0000000..7c2cd26
--- /dev/null
+++ b/node_modules/algebrite/sources/real.coffee
@@ -0,0 +1,30 @@
+###
+ Returns the real part of complex z
+
+ z real(z)
+ - -------
+
+ a + i b a
+
+ exp(i a) cos(a)
+###
+
+
+
+Eval_real = ->
+ push(cadr(p1))
+ Eval()
+ real()
+
+real = ->
+ save()
+ rect()
+ p1 = pop()
+ push(p1)
+ push(p1)
+ conjugate()
+ add()
+ push_integer(2)
+ divide()
+ restore()
+
diff --git a/node_modules/algebrite/sources/rect.coffee b/node_modules/algebrite/sources/rect.coffee
new file mode 100644
index 0000000..6672b6a
--- /dev/null
+++ b/node_modules/algebrite/sources/rect.coffee
@@ -0,0 +1,100 @@
+###
+Convert complex z to rectangular form
+
+ Input: push z
+
+ Output: Result on stack
+###
+
+
+DEBUG_RECT = false
+
+Eval_rect = ->
+ push(cadr(p1))
+ Eval()
+ rect()
+
+rect = ->
+ save()
+ p1 = pop()
+ input = p1
+
+ if DEBUG_RECT then console.log "RECT of " + input
+
+ if DEBUG_RECT then console.log "any clock forms in : " + input + " ? " + findPossibleClockForm(input)
+
+
+ # if we assume real variables, then the
+ # rect of any symbol is the symbol itself
+ # (note that 'i' is not a symbol, it's made of (-1)^(1/2))
+ # otherwise we have to leave unevalled
+ if issymbol(p1)
+ if DEBUG_RECT then console.log " rect: simple symbol: " + input
+ if !isZeroAtomOrTensor(get_binding(symbol(ASSUME_REAL_VARIABLES)))
+ push(p1)
+ else
+ push_symbol(YYRECT)
+ push(p1)
+ list(2)
+
+ # TODO this is quite dirty, ideally we don't need this
+ # but removing this creates a few failings in the tests
+ # that I can't investigate right now.
+ # --
+ # if we assume all variables are real AND
+ # it's not an exponential nor a polar nor a clock form
+ # THEN rect(_) = _
+ # note that these matches can be quite sloppy, one can find expressions
+ # which shouldn't match but do
+ #
+ else if !isZeroAtomOrTensor(get_binding(symbol(ASSUME_REAL_VARIABLES))) and
+ !findPossibleExponentialForm(p1) and # no exp form?
+ !findPossibleClockForm(p1) and # no clock form?
+ !(Find(p1, symbol(SIN)) and Find(p1, symbol(COS)) and Find(p1, imaginaryunit)) # no polar form?
+ if DEBUG_RECT then console.log " rect: simple symbol: " + input
+ push(p1)
+
+ # ib
+ else if (car(p1) == symbol(MULTIPLY) and isimaginaryunit(cadr(p1)) and !isZeroAtomOrTensor(get_binding(symbol(ASSUME_REAL_VARIABLES))))
+ push(p1)
+
+ # sum
+ else if (car(p1) == symbol(ADD))
+ if DEBUG_RECT then console.log " rect - " + input + " is a sum "
+ push_integer(0)
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ rect()
+ add()
+ p1 = cdr(p1)
+
+ else
+ # try to get to the rectangular form by doing
+ # abs(p1) * (cos (theta) + i * sin(theta))
+ # where theta is arg(p1)
+ if DEBUG_RECT then console.log " rect - " + input + " is NOT a sum "
+
+ push(p1); # abs(z) * (cos(arg(z)) + i sin(arg(z)))
+ abs()
+
+ if DEBUG_RECT then console.log " rect - " + input + " abs: " + stack[tos-1].toString()
+ push(p1)
+ arg()
+ if DEBUG_RECT then console.log " rect - " + input + " arg of " + p1 + " : " + stack[tos-1].toString()
+ p1 = pop()
+ push(p1)
+ cosine()
+ if DEBUG_RECT then console.log " rect - " + input + " cosine: " + stack[tos-1].toString()
+ push(imaginaryunit)
+ push(p1)
+ sine()
+ if DEBUG_RECT then console.log " rect - " + input + " sine: " + stack[tos-1].toString()
+ multiply()
+ if DEBUG_RECT then console.log " rect - " + input + " i * sine: " + stack[tos-1].toString()
+ add()
+ if DEBUG_RECT then console.log " rect - " + input + " cos + i * sine: " + stack[tos-1].toString()
+ multiply()
+ restore()
+ if DEBUG_RECT then console.log "rect of " + input + " : " + stack[tos-1]
+
diff --git a/node_modules/algebrite/sources/roots.coffee b/node_modules/algebrite/sources/roots.coffee
new file mode 100644
index 0000000..0b19cf2
--- /dev/null
+++ b/node_modules/algebrite/sources/roots.coffee
@@ -0,0 +1,1830 @@
+
+
+
+#define POLY p1
+#define X p2
+#define A p3
+#define B p4
+#define C p5
+#define Y p6
+
+show_power_debug = false
+performing_roots = false
+
+Eval_roots = ->
+
+ # this transforms simple "equation" forms into
+ # something that can be processed. E.g., say, y = 3x - 2
+ # A == B -> A - B
+ # A = B -> A - B
+ p2 = cadr(p1)
+ if (car(p2) == symbol(SETQ) || car(p2) == symbol(TESTEQ))
+ push(cadr(p2))
+ Eval()
+ push(caddr(p2))
+ Eval()
+ subtract()
+ else
+ push(p2)
+ Eval()
+ p2 = pop()
+ if (car(p2) == symbol(SETQ) || car(p2) == symbol(TESTEQ))
+ push(cadr(p2))
+ Eval()
+ push(caddr(p2))
+ Eval()
+ subtract()
+ else
+ push(p2)
+
+ # 2nd arg, x
+
+ push(caddr(p1))
+ Eval()
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ guess()
+ else
+ push(p2)
+
+ p2 = pop()
+ p1 = pop()
+
+ if (!ispolyexpandedform(p1, p2))
+ stop("roots: 1st argument is not a polynomial in the variable " + p2)
+
+ push(p1)
+ push(p2)
+
+ roots()
+
+
+hasImaginaryCoeff = (k) ->
+
+ #polycoeff = tos
+
+
+ imaginaryCoefficients = false
+ h = tos
+ for i in [k...0] by -1
+ #console.log "hasImaginaryCoeff - coeff.:" + stack[tos-i].toString()
+ if iscomplexnumber(stack[tos-i])
+ imaginaryCoefficients = true
+ break
+ return imaginaryCoefficients
+
+isSimpleRoot = (k) ->
+
+ #polycoeff = tos
+
+
+ #tos-n Coefficient of x^0
+ #tos-1 Coefficient of x^(n-1)
+
+ if k > 2
+ isSimpleRootPolynomial = true
+ h = tos
+
+ if isZeroAtomOrTensor(stack[tos-k])
+ isSimpleRootPolynomial = false
+
+ for i in [(k-1)...1] by -1
+ #console.log "hasImaginaryCoeff - coeff.:" + stack[tos-i].toString()
+ if !isZeroAtomOrTensor(stack[tos-i])
+ isSimpleRootPolynomial = false
+ break
+ else
+ isSimpleRootPolynomial = false
+
+ return isSimpleRootPolynomial
+
+
+normalisedCoeff = (variable, polynomial) ->
+ k = coeff(variable, polynomial)
+ #console.log("->" + tos)
+ divideBy = stack[tos-1]
+ miniStack = []
+ for i in [1..k]
+ miniStack.push(pop())
+ #console.log(tos)
+
+ for i in [(k-1)..0]
+ push(miniStack[i])
+ push(divideBy)
+ divide()
+ #console.log(tos)
+ return k
+
+
+
+# takes the polynomial and the
+# variable on the stack
+
+roots = ->
+ h = 0
+ i = 0
+ n = 0
+
+ if DEBUG then console.log "roots: " + stack[tos-1].toString() + " " + stack[tos-2].toString()
+
+ save()
+
+ # the simplification of nested radicals uses
+ # "roots", which in turn uses simplification
+ # of nested radicals. Usually there is no problem,
+ # one level of recursion does the job. Beyond that,
+ # we probably got stuck in a strange case of infinite
+ # recursion, so bail out and return NIL.
+ if recursionLevelNestedRadicalsRemoval > 1
+ pop()
+ pop()
+ push(symbol(NIL))
+ restore()
+ return
+
+ performing_roots = true
+ h = tos - 2
+
+ if DEBUG then console.log("roots checking if " + stack[tos-1].toString() + " is a case of simple roots")
+
+ p2 = pop()
+ p1 = pop()
+
+ push(p1)
+ push(p2)
+
+ k = normalisedCoeff(p2, p1)
+
+ if isSimpleRoot(k)
+ if DEBUG then console.log("yes, " + stack[tos-1].toString() + " is a case of simple roots")
+ lastCoeff = stack[tos-k]
+ leadingCoeff = stack[tos-1]
+ moveTos tos - k
+ pop()
+ pop()
+ getSimpleRoots(k, leadingCoeff, lastCoeff)
+ else
+ moveTos tos - k
+ roots2()
+
+ n = tos - h
+ if (n == 0)
+ stop("roots: the polynomial is not factorable, try nroots")
+ if (n == 1)
+ performing_roots = false
+ restore()
+ return
+ sort_stack(n)
+ p1 = alloc_tensor(n)
+ p1.tensor.ndim = 1
+ p1.tensor.dim[0] = n
+ for i in [0...n]
+ p1.tensor.elem[i] = stack[h + i]
+ moveTos h
+ push(p1)
+ restore()
+ performing_roots = false
+
+# ok to generate these roots take a look at their form
+# in the case of even and odd exponents here:
+# http://www.wolframalpha.com/input/?i=roots+x%5E14+%2B+1
+# http://www.wolframalpha.com/input/?i=roots+ax%5E14+%2B+b
+# http://www.wolframalpha.com/input/?i=roots+x%5E15+%2B+1
+# http://www.wolframalpha.com/input/?i=roots+a*x%5E15+%2B+b
+getSimpleRoots = (n, leadingCoeff, lastCoeff) ->
+ if DEBUG then console.log("getSimpleRoots")
+ save()
+
+ #tos-n Coefficient of x^0
+ #tos-1 Coefficient of x^(n-1)
+
+ n = n-1
+
+ push(lastCoeff)
+ push_rational(1,n)
+ power()
+
+ push(leadingCoeff)
+ push_rational(1,n)
+ power()
+ divide()
+
+ commonPart = pop()
+
+ if n % 2 == 0
+ for rootsOfOne in [1..n] by 2
+ push(commonPart)
+ push_integer(-1)
+ push_rational(rootsOfOne,n)
+ power()
+ multiply()
+ aSol = pop()
+ push(aSol)
+ push(aSol)
+ negate()
+ else
+ for rootsOfOne in [1..n]
+ push(commonPart)
+ push_integer(-1)
+ push_rational(rootsOfOne,n)
+ power()
+ multiply()
+ if rootsOfOne % 2 == 0
+ negate()
+
+
+ restore()
+
+roots2 = ->
+ save()
+
+ if DEBUG then console.log "roots2: " + stack[tos-1].toString() + " " + stack[tos-2].toString()
+
+ p2 = pop() # the polynomial variable
+ p1 = pop() # the polynomial
+
+ push(p1)
+ push(p2)
+
+ k = normalisedCoeff(p2, p1)
+
+ if !hasImaginaryCoeff(k)
+ moveTos tos - k
+ factorpoly()
+ p1 = pop()
+ else
+ moveTos tos - k
+ pop()
+ pop()
+
+
+ if (car(p1) == symbol(MULTIPLY))
+ p1 = cdr(p1)
+ # scan through all the factors
+ # and find the roots of each of them
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ roots3()
+ p1 = cdr(p1)
+ else
+ push(p1)
+ push(p2)
+ roots3()
+
+ restore()
+
+roots3 = ->
+ save()
+ p2 = pop()
+ p1 = pop()
+ if (car(p1) == symbol(POWER) && ispolyexpandedform(cadr(p1), p2) && isposint(caddr(p1)))
+ n = normalisedCoeff(p2, cadr(p1))
+ mini_solve(n)
+ else if (ispolyexpandedform(p1, p2))
+ n = normalisedCoeff(p2, p1)
+ mini_solve(n)
+ restore()
+
+#-----------------------------------------------------------------------------
+#
+# Input: stack[tos - 2] polynomial
+#
+# stack[tos - 1] dependent symbol
+#
+# Output: stack roots on stack
+#
+# (input args are popped first)
+#
+#-----------------------------------------------------------------------------
+
+# note that for many quadratic, cubic and quartic polynomials we don't
+# actually end up using the quadratic/cubic/quartic formulas in here,
+# since there is a chance we factored the polynomial and in so
+# doing we found some solutions and lowered the degree.
+mini_solve = (n) ->
+ #console.log "mini_solve >>>>>>>>>>>>>>>>>>>>>>>> tos:" + tos
+
+ save()
+
+ # AX + B, X = -B/A
+
+ if (n == 2)
+ #console.log "mini_solve >>>>>>>>> 1st degree"
+ p3 = pop()
+ p4 = pop()
+ push(p4)
+ push(p3)
+ divide()
+ negate()
+ restore()
+ return
+
+ # AX^2 + BX + C, X = (-B +/- (B^2 - 4AC)^(1/2)) / (2A)
+
+ if (n == 3)
+ #console.log "mini_solve >>>>>>>>> 2nd degree"
+ p3 = pop() # A
+ p4 = pop() # B
+ p5 = pop() # C
+
+ # B^2
+ push(p4)
+ push_integer(2)
+ power()
+
+ # 4AC
+ push_integer(4)
+ push(p3)
+ multiply()
+ push(p5)
+ multiply()
+
+ # B^2 - 4AC
+ subtract()
+
+ #(B^2 - 4AC)^(1/2)
+ push_rational(1, 2)
+ power()
+
+ #p6 is (B^2 - 4AC)^(1/2)
+ p6 = pop()
+ push(p6);
+
+ # B
+ push(p4)
+ subtract() # -B + (B^2 - 4AC)^(1/2)
+
+ # 1/2A
+ push(p3)
+ push_integer(2)
+ multiply()
+ divide()
+ #simplify()
+ #rationalize()
+ # tos - 1 now is 1st root: (-B + (B^2 - 4AC)^(1/2)) / (2A)
+
+ push(p6);
+ # tos - 1 now is (B^2 - 4AC)^(1/2)
+ # tos - 2: 1st root: (-B + (B^2 - 4AC)^(1/2)) / (2A)
+
+ # add B to tos
+ push(p4)
+ add()
+ # tos - 1 now is B + (B^2 - 4AC)^(1/2)
+ # tos - 2: 1st root: (-B + (B^2 - 4AC)^(1/2)) / (2A)
+
+ negate()
+ # tos - 1 now is -B -(B^2 - 4AC)^(1/2)
+ # tos - 2: 1st root: (-B + (B^2 - 4AC)^(1/2)) / (2A)
+
+ # 1/2A again
+ push(p3)
+ divide()
+ push_rational(1, 2)
+ multiply()
+ #simplify()
+ #rationalize()
+ # tos - 1: 2nd root: (-B - (B^2 - 4AC)^(1/2)) / (2A)
+ # tos - 2: 1st root: (-B + (B^2 - 4AC)^(1/2)) / (2A)
+
+ restore()
+ return
+
+ #if (n == 4)
+ if (n == 4 or n == 5)
+
+ p3 = pop() # A
+ p4 = pop() # B
+ p5 = pop() # C
+ p6 = pop() # D
+
+ # C - only related calculations
+ push(p5)
+ push(p5)
+ multiply()
+ R_c2 = pop()
+
+ push(R_c2)
+ push(p5)
+ multiply()
+ R_c3 = pop()
+
+ # B - only related calculations
+ push(p4)
+ push(p4)
+ multiply()
+ R_b2 = pop()
+
+ push(R_b2)
+ push(p4)
+ multiply()
+ R_b3 = pop()
+
+ push(R_b3)
+ push(p6)
+ multiply()
+ R_b3_d = pop()
+
+ push(R_b3_d)
+ push_integer(-4)
+ multiply()
+ R_m4_b3_d = pop()
+
+
+ push(R_b3)
+ push_integer(2)
+ multiply()
+ R_2_b3 = pop()
+
+ # A - only related calculations
+ push(p3)
+ push(p3)
+ multiply()
+ R_a2 = pop()
+
+ push(R_a2)
+ push(p3)
+ multiply()
+ R_a3 = pop()
+
+ push_integer(3)
+ push(p3)
+ multiply()
+ R_3_a = pop()
+
+ push(R_a2)
+ push(p6)
+ multiply()
+ R_a2_d = pop()
+
+ push(R_a2_d)
+ push(p6)
+ multiply()
+ R_a2_d2 = pop()
+
+ push(R_a2_d)
+ push_integer(27)
+ multiply()
+ R_27_a2_d = pop()
+
+ push(R_a2_d2)
+ push_integer(-27)
+ multiply()
+ R_m27_a2_d2 = pop()
+
+ push(R_3_a)
+ push_integer(2)
+ multiply()
+ R_6_a = pop()
+
+ # mixed calculations
+ push(p3)
+ push(p5)
+ multiply()
+ R_a_c = pop()
+
+ push(R_a_c)
+ push(p4)
+ multiply()
+ R_a_b_c = pop()
+
+ push(R_a_b_c)
+ push(p6)
+ multiply()
+ R_a_b_c_d = pop()
+
+ push(R_a_c)
+ push_integer(3)
+ multiply()
+ R_3_a_c = pop()
+
+ push_integer(-4)
+ push(p3)
+ push(R_c3)
+ multiply()
+ multiply()
+ R_m4_a_c3 = pop()
+
+ push(R_a_b_c)
+ push_integer(9)
+ multiply()
+ negate()
+ R_m9_a_b_c = pop()
+
+ push(R_a_b_c_d)
+ push_integer(18)
+ multiply()
+ R_18_a_b_c_d = pop()
+
+ push(R_b2)
+ push(R_3_a_c)
+ subtract()
+ R_DELTA0 = pop()
+
+ push(R_b2)
+ push(R_c2)
+ multiply()
+ R_b2_c2 = pop()
+
+ push(p4)
+ negate()
+ push(R_3_a)
+ divide()
+ R_m_b_over_3a = pop()
+
+
+ if (n == 4)
+ if DEBUG then console.log ">>>>>>>>>>>>>>>> actually using cubic formula <<<<<<<<<<<<<<< "
+
+ #console.log ">>>> A:" + p3.toString()
+ #console.log ">>>> B:" + p4.toString()
+ #console.log ">>>> C:" + p5.toString()
+ #console.log ">>>> D:" + p6.toString()
+
+
+ if DEBUG then console.log "cubic: D0: " + R_DELTA0.toString()
+
+ push(R_DELTA0)
+ push_integer(3)
+ power()
+ push_integer(4)
+ multiply()
+ R_4_DELTA03 = pop()
+
+ push(R_DELTA0)
+ simplify()
+ absValFloat()
+ R_DELTA0_toBeCheckedIfZero = pop()
+ if DEBUG then console.log "cubic: D0 as float: " + R_DELTA0_toBeCheckedIfZero.toString()
+ #if isZeroAtomOrTensor(R_DELTA0_toBeCheckedIfZero)
+ # console.log " *********************************** D0 IS ZERO"
+
+
+ # DETERMINANT
+ push(R_18_a_b_c_d)
+ push(R_m4_b3_d)
+ push(R_b2_c2)
+ push(R_m4_a_c3)
+ push(R_m27_a2_d2)
+ add()
+ add()
+ add()
+ add()
+ simplify()
+ absValFloat()
+ R_determinant = pop()
+ if DEBUG then console.log "cubic: DETERMINANT: " + R_determinant.toString()
+
+ # R_DELTA1
+ push(R_2_b3)
+ push(R_m9_a_b_c)
+ push(R_27_a2_d)
+ add()
+ add()
+ R_DELTA1 = pop()
+ if DEBUG then console.log "cubic: D1: " + R_DELTA1.toString()
+
+ # R_Q
+ push(R_DELTA1)
+ push_integer(2)
+ power()
+ push(R_4_DELTA03)
+ subtract()
+ push_rational(1, 2)
+ power()
+ simplify()
+ R_Q = pop()
+
+
+ if isZeroAtomOrTensor(R_determinant)
+ if isZeroAtomOrTensor(R_DELTA0_toBeCheckedIfZero)
+ if DEBUG then console.log " cubic: DETERMINANT IS ZERO and delta0 is zero"
+ push(R_m_b_over_3a) # just same solution three times
+ restore()
+ return
+ else
+ if DEBUG then console.log " cubic: DETERMINANT IS ZERO and delta0 is not zero"
+ push(p3)
+ push(p6)
+ push_integer(9)
+ multiply()
+ multiply()
+ push(p4)
+ push(p5)
+ multiply()
+ subtract()
+ push(R_DELTA0)
+ push_integer(2)
+ multiply()
+ divide() # first solution
+ root_solution = pop()
+ push(root_solution) # pushing two of them on the stack
+ push(root_solution)
+
+ # second solution here
+ # 4abc
+ push(R_a_b_c)
+ push_integer(4)
+ multiply()
+
+ # -9a*a*d
+ push(p3)
+ push(p3)
+ push(p6)
+ push_integer(9)
+ multiply()
+ multiply()
+ multiply()
+ negate()
+
+ # -9*b^3
+ push(R_b3)
+ negate()
+
+ # sum the three terms
+ add()
+ add()
+
+ # denominator is a*delta0
+ push(p3)
+ push(R_DELTA0)
+ multiply()
+
+ # build the fraction
+ divide()
+
+ restore()
+ return
+
+
+
+ C_CHECKED_AS_NOT_ZERO = false
+ flipSignOFQSoCIsNotZero = false
+
+ # C will go as denominator, we have to check
+ # that is not zero
+ while !C_CHECKED_AS_NOT_ZERO
+
+ # R_C
+ push(R_Q)
+ if flipSignOFQSoCIsNotZero
+ negate()
+ push(R_DELTA1)
+ add()
+ push_rational(1, 2)
+ multiply()
+ push_rational(1, 3)
+ power()
+ simplify()
+ R_C = pop()
+ if DEBUG then console.log "cubic: C: " + R_C.toString()
+
+ push(R_C)
+ simplify()
+ absValFloat()
+ R_C_simplified_toCheckIfZero = pop()
+ if DEBUG then console.log "cubic: C as absval and float: " + R_C_simplified_toCheckIfZero.toString()
+
+ if isZeroAtomOrTensor(R_C_simplified_toCheckIfZero)
+ if DEBUG then console.log " cubic: C IS ZERO flipping the sign"
+ flipSignOFQSoCIsNotZero = true
+ else
+ C_CHECKED_AS_NOT_ZERO = true
+
+
+ push(R_C)
+ push(R_3_a)
+ multiply()
+ R_3_a_C = pop()
+
+ push(R_3_a_C)
+ push_integer(2)
+ multiply()
+ R_6_a_C = pop()
+
+
+ # imaginary parts calculations
+ push(imaginaryunit)
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ multiply()
+ i_sqrt3 = pop()
+ push_integer(1)
+ push(i_sqrt3)
+ add()
+ one_plus_i_sqrt3 = pop()
+ push_integer(1)
+ push(i_sqrt3)
+ subtract()
+ one_minus_i_sqrt3 = pop()
+
+
+ push(R_C)
+ push(R_3_a)
+ divide()
+ R_C_over_3a = pop()
+
+ # first solution
+ push(R_m_b_over_3a) # first term
+ push(R_C_over_3a)
+ negate() # second term
+ push(R_DELTA0)
+ push(R_3_a_C)
+ divide()
+ negate() # third term
+ # now add the three terms together
+ add()
+ add()
+ simplify()
+
+ # second solution
+ push(R_m_b_over_3a) # first term
+ push(R_C_over_3a)
+ push(one_plus_i_sqrt3)
+ multiply()
+ push_integer(2)
+ divide() # second term
+ push(one_minus_i_sqrt3)
+ push(R_DELTA0)
+ multiply()
+ push(R_6_a_C)
+ divide() # third term
+ # now add the three terms together
+ add()
+ add()
+ simplify()
+
+ # third solution
+ push(R_m_b_over_3a) # first term
+ push(R_C_over_3a)
+ push(one_minus_i_sqrt3)
+ multiply()
+ push_integer(2)
+ divide() # second term
+ push(one_plus_i_sqrt3)
+ push(R_DELTA0)
+ multiply()
+ push(R_6_a_C)
+ divide() # third term
+ # now add the three terms together
+ add()
+ add()
+ simplify()
+
+ restore()
+ return
+
+ # See http://www.sscc.edu/home/jdavidso/Math/Catalog/Polynomials/Fourth/Fourth.html
+ # for a description of general shapes and properties of fourth degree polynomials
+ if (n == 5)
+ if DEBUG then console.log ">>>>>>>>>>>>>>>> actually using quartic formula <<<<<<<<<<<<<<< "
+ p7 = pop() # E
+
+ if isZeroAtomOrTensor(p4) and isZeroAtomOrTensor(p6) and !isZeroAtomOrTensor(p5) and !isZeroAtomOrTensor(p7)
+ if DEBUG then console.log("biquadratic case")
+ push(p3)
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+ multiply()
+
+ push(p5)
+ push(symbol(SECRETX))
+ multiply()
+
+ push(p7)
+
+ add()
+ add()
+
+ push(symbol(SECRETX))
+ roots()
+
+ biquadraticSolutions = pop()
+
+ for eachSolution in biquadraticSolutions.tensor.elem
+ push(eachSolution)
+ push_rational(1,2)
+ power()
+ simplify()
+
+ push(eachSolution)
+ push_rational(1,2)
+ power()
+ negate()
+ simplify()
+
+ restore()
+ return
+
+
+
+
+
+ # D - only related calculations
+ push(p6)
+ push(p6)
+ multiply()
+ R_d2 = pop()
+
+ # E - only related calculations
+ push(p7)
+ push(p7)
+ multiply()
+ R_e2 = pop()
+
+ push(R_e2)
+ push(p7)
+ multiply()
+ R_e3 = pop()
+
+ # DETERMINANT
+
+ push_integer(256)
+ push(R_a3)
+ push(R_e3)
+ multiply()
+ multiply() # first term 256 a^3 e^3
+
+ push_integer(-192)
+ push(R_a2_d)
+ push(R_e2)
+ push(p4)
+ multiply()
+ multiply()
+ multiply() # second term -192 a^3 b d e^2
+
+ push_integer(-128)
+ push(R_a2)
+ push(R_c2)
+ push(R_e2)
+ multiply()
+ multiply()
+ multiply() # third term -128 a^2 c^2 e^2
+
+ push_integer(144)
+ push(R_a2_d2)
+ push(p5)
+ push(p7)
+ multiply()
+ multiply()
+ multiply() # fourth term 144 a^2 c d^2 e
+
+ push(R_m27_a2_d2)
+ push(R_d2)
+ multiply() # fifth term -27 a^2 d^4
+
+ push_integer(144)
+ push(R_a_b_c)
+ push(p4)
+ push(R_e2)
+ multiply()
+ multiply()
+ multiply() # sixth term 144 a b^2 c e^2
+
+ push_integer(-6)
+ push(p3)
+ push(R_b2)
+ push(R_d2)
+ push(p7)
+ multiply()
+ multiply()
+ multiply()
+ multiply() # seventh term -6 a b^2 d^2 e
+
+ push_integer(-80)
+ push(R_a_b_c_d)
+ push(p5)
+ push(p7)
+ multiply()
+ multiply()
+ multiply() # eigth term -80 a b c^2 d e
+
+ push_integer(18)
+ push(R_a_b_c_d)
+ push(R_d2)
+ multiply()
+ multiply() # ninth term 18 a b c d^3
+
+ push_integer(16)
+ push(R_a_c)
+ push(R_c3)
+ push(p7)
+ multiply()
+ multiply()
+ multiply() # tenth term 16 a c^4 e
+
+ push_integer(-4)
+ push(R_a_c)
+ push(R_c2)
+ push(R_d2)
+ multiply()
+ multiply()
+ multiply() # eleventh term -4 a c^3 d^2
+
+ push_integer(-27)
+ push(R_b3)
+ push(p4)
+ push(R_e2)
+ multiply()
+ multiply()
+ multiply() # twelveth term -27 b^4 e^2
+
+ push_integer(18)
+ push(R_b3_d)
+ push(p5)
+ push(p7)
+ multiply()
+ multiply()
+ multiply() # thirteenth term 18 b^3 c d e
+
+ push(R_m4_b3_d)
+ push(R_d2)
+ multiply() # fourteenth term -4 b^3 d^3
+
+ push_integer(-4)
+ push(R_b2_c2)
+ push(p5)
+ push(p7)
+ multiply()
+ multiply()
+ multiply() # fifteenth term -4 b^2 c^3 e
+
+ push(R_b2_c2)
+ push(R_d2)
+ multiply() # sixteenth term b^2 c^2 d^2
+
+ # add together the sixteen terms by doing
+ # fifteen adds
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+ add()
+
+ R_determinant = pop()
+ if DEBUG then console.log("R_determinant: " + R_determinant.toString())
+
+ # DELTA0
+ push(R_c2) # term one of DELTA0
+
+ push_integer(-3)
+ push(p4)
+ push(p6)
+ multiply()
+ multiply() # term two of DELTA0
+
+ push_integer(12)
+ push(p3)
+ push(p7)
+ multiply()
+ multiply() # term three of DELTA0
+
+ # add the three terms together
+ add()
+ add()
+
+ R_DELTA0 = pop()
+ if DEBUG then console.log("R_DELTA0: " + R_DELTA0.toString())
+
+ # DELTA1
+ push_integer(2)
+ push(R_c3)
+ multiply()
+
+ push_integer(-9)
+ push(p4)
+ push(p5)
+ push(p6)
+ multiply()
+ multiply()
+ multiply()
+
+ push_integer(27)
+ push(R_b2)
+ push(p7)
+ multiply()
+ multiply()
+
+ push_integer(27)
+ push(p3)
+ push(R_d2)
+ multiply()
+ multiply()
+
+ push_integer(-72)
+ push(R_a_c)
+ push(p7)
+ multiply()
+ multiply()
+
+ # add the five terms together
+ add()
+ add()
+ add()
+ add()
+
+ R_DELTA1 = pop()
+ if DEBUG then console.log("R_DELTA1: " + R_DELTA1.toString())
+
+ # p
+ push_integer(8)
+ push(R_a_c)
+ multiply()
+
+ push_integer(-3)
+ push(R_b2)
+ multiply()
+
+ add()
+
+ push_integer(8)
+ push(R_a2)
+ multiply()
+
+ divide()
+
+ R_p = pop()
+ if DEBUG then console.log("p: " + R_p.toString())
+
+ # q
+ push(R_b3)
+
+ push_integer(-4)
+ push(R_a_b_c)
+ multiply()
+
+ push_integer(8)
+ push(R_a2_d)
+ multiply()
+
+ add()
+ add()
+
+ push_integer(8)
+ push(R_a3)
+ multiply()
+
+ divide()
+
+ R_q = pop()
+ if DEBUG then console.log("q: " + R_q.toString())
+
+ if DEBUG then console.log("tos 1 " + tos)
+ if !isZeroAtomOrTensor(p4)
+ if DEBUG then console.log("tos 2 " + tos)
+
+ push_integer(8)
+ push(p5)
+ push(p3)
+ multiply()
+ multiply()
+
+ push_integer(-3)
+ push(p4)
+ push_integer(2)
+ power()
+ multiply()
+
+ add()
+
+ push_integer(8)
+ push(p3)
+ push_integer(2)
+ power()
+ multiply()
+
+ divide()
+
+ R_p = pop()
+ if DEBUG then console.log("p for depressed quartic: " + R_p.toString())
+
+ push(p4)
+ push_integer(3)
+ power()
+
+ push_integer(-4)
+ push(p3)
+ push(p4)
+ push(p5)
+ multiply()
+ multiply()
+ multiply()
+
+ push_integer(8)
+ push(p6)
+ push(p3)
+ push_integer(2)
+ power()
+ multiply()
+ multiply()
+
+ add()
+ add()
+
+
+ push_integer(8)
+ push(p3)
+ push_integer(3)
+ power()
+ multiply()
+
+ divide()
+
+ R_q = pop()
+ if DEBUG then console.log("q for depressed quartic: " + R_q.toString())
+
+
+ # convert to depressed quartic
+ push(p4)
+ push_integer(4)
+ power()
+ push_integer(-3)
+ multiply()
+
+ push_integer(256)
+ push(R_a3)
+ push(p7)
+ multiply()
+ multiply()
+
+ push_integer(-64)
+ push(R_a2_d)
+ push(p4)
+ multiply()
+ multiply()
+
+ push_integer(16)
+ push(R_b2)
+ push(p3)
+ push(p5)
+ multiply()
+ multiply()
+ multiply()
+
+ add()
+ add()
+ add()
+
+ push_integer(256)
+ push(p3)
+ push_integer(4)
+ power()
+ multiply()
+ divide()
+
+ R_r = pop()
+ if DEBUG then console.log("r for depressed quartic: " + R_r.toString())
+
+ if DEBUG then console.log("tos 4 " + tos)
+
+ push(symbol(SECRETX))
+ push_integer(4)
+ power()
+ if DEBUG then console.log("4 * x^4: " + stack[tos-1].toString())
+
+ push(R_p)
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+ multiply()
+ if DEBUG then console.log("R_p * x^2: " + stack[tos-1].toString())
+
+ push(R_q)
+ push(symbol(SECRETX))
+ multiply()
+ if DEBUG then console.log("R_q * x: " + stack[tos-1].toString())
+
+ push(R_r)
+ if DEBUG then console.log("R_r: " + stack[tos-1].toString())
+
+ add()
+ add()
+ add()
+
+ simplify()
+ if DEBUG then console.log("solving depressed quartic: " + stack[tos-1].toString())
+
+ push(symbol(SECRETX))
+
+ roots()
+
+ depressedSolutions = pop()
+ if DEBUG then console.log("depressedSolutions: " + depressedSolutions)
+
+ for eachSolution in depressedSolutions.tensor.elem
+ push(eachSolution)
+ push(p4)
+ push_integer(4)
+ push(p3)
+ multiply()
+ divide()
+ subtract()
+ simplify()
+ if DEBUG then console.log("solution from depressed: " + stack[tos-1].toString())
+
+ restore()
+ return
+
+ else
+ R_p = p5
+ R_q = p6
+ R_r = p7
+
+ ###
+ # Descartes' solution
+ # https://en.wikipedia.org/wiki/Quartic_function#Descartes.27_solution
+ # finding the "u" in the depressed equation
+
+ push_integer(2)
+ push(R_p)
+ multiply()
+ coeff2 = pop()
+
+ push_integer(-4)
+ push(R_p)
+ push_integer(2)
+ power()
+ multiply()
+ push(R_r)
+ multiply()
+ coeff3 = pop()
+
+ push(R_q)
+ push_integer(2)
+ power()
+ negate()
+ coeff4 = pop()
+
+ # now build the polynomial
+ push(symbol(SECRETX))
+ push_integer(3)
+ power()
+
+ push(coeff2)
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+ multiply()
+
+ push(coeff3)
+ push(symbol(SECRETX))
+ multiply()
+
+ push(coeff4)
+
+ add()
+ add()
+ add()
+
+ console.log("Descarte's resolventCubic: " + stack[tos-1].toString())
+ push(symbol(SECRETX))
+
+ roots()
+
+ resolventCubicSolutions = pop()
+ console.log("Descarte's resolventCubic solutions: " + resolventCubicSolutions)
+ console.log("tos: " + tos)
+
+ R_u = null
+ #R_u = resolventCubicSolutions.tensor.elem[1]
+ for eachSolution in resolventCubicSolutions.tensor.elem
+ console.log("examining solution: " + eachSolution)
+ push(eachSolution)
+ push_integer(2)
+ multiply()
+ push(R_p)
+ add()
+
+ absValFloat()
+ toBeCheckedIFZero = pop()
+ console.log("abs value is: " + eachSolution)
+ if !isZeroAtomOrTensor(toBeCheckedIFZero)
+ R_u = eachSolution
+ break
+
+ console.log("chosen solution: " + R_u)
+
+ push(R_u)
+ negate()
+ R_s = pop()
+
+ push(R_p)
+ push(R_u)
+ push_integer(2)
+ power()
+ push(R_q)
+ push(R_u)
+ divide()
+ add()
+ add()
+ push_integer(2)
+ divide()
+ R_t = pop()
+
+ push(R_p)
+ push(R_u)
+ push_integer(2)
+ power()
+ push(R_q)
+ push(R_u)
+ divide()
+ subtract()
+ add()
+ push_integer(2)
+ divide()
+ R_v = pop()
+
+ # factoring the quartic into two quadratics:
+
+ # now build the polynomial
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+
+ push(R_s)
+ push(symbol(SECRETX))
+ multiply()
+
+ push(R_t)
+
+ add()
+ add()
+
+ console.log("factored quartic 1: " + stack[tos-1].toString())
+
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+
+ push(R_u)
+ push(symbol(SECRETX))
+ multiply()
+
+ push(R_v)
+
+ add()
+ add()
+
+ console.log("factored quartic 2: " + stack[tos-1].toString())
+ pop()
+
+ restore()
+ return
+ ###
+
+ # Ferrari's solution
+ # https://en.wikipedia.org/wiki/Quartic_function#Ferrari.27s_solution
+ # finding the "m" in the depressed equation
+ push_rational(5,2)
+ push(R_p)
+ multiply()
+ coeff2 = pop()
+
+ push_integer(2)
+ push(R_p)
+ push_integer(2)
+ power()
+ multiply()
+ push(R_r)
+ subtract()
+ coeff3 = pop()
+
+ push(R_p)
+ push_integer(3)
+ power()
+ push_integer(2)
+ divide()
+
+ push_rational(-1,2)
+ push(R_p)
+ push(R_r)
+ multiply()
+ multiply()
+
+ push_rational(-1,8)
+ push(R_q)
+ push_integer(2)
+ power()
+ multiply()
+
+ add()
+ add()
+
+ coeff4 = pop()
+
+ push(symbol(SECRETX))
+ push_integer(3)
+ power()
+
+ push(coeff2)
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+ multiply()
+
+ push(coeff3)
+ push(symbol(SECRETX))
+ multiply()
+
+ push(coeff4)
+
+ add()
+ add()
+ add()
+
+ if DEBUG then console.log("resolventCubic: " + stack[tos-1].toString())
+ push(symbol(SECRETX))
+
+ roots()
+
+ resolventCubicSolutions = pop()
+ if DEBUG then console.log("resolventCubicSolutions: " + resolventCubicSolutions)
+
+ R_m = null
+ #R_m = resolventCubicSolutions.tensor.elem[1]
+ for eachSolution in resolventCubicSolutions.tensor.elem
+ if DEBUG then console.log("examining solution: " + eachSolution)
+ push(eachSolution)
+ push_integer(2)
+ multiply()
+ push(R_p)
+ add()
+
+ absValFloat()
+ toBeCheckedIFZero = pop()
+ if DEBUG then console.log("abs value is: " + eachSolution)
+ if !isZeroAtomOrTensor(toBeCheckedIFZero)
+ R_m = eachSolution
+ break
+
+ if DEBUG then console.log("chosen solution: " + R_m)
+ push(R_m)
+ push_integer(2)
+ multiply()
+ push(R_p)
+ add()
+ push_rational(1,2)
+ power()
+ simplify()
+ sqrtPPlus2M = pop()
+
+ push(R_q)
+ push_integer(2)
+ multiply()
+ push(sqrtPPlus2M)
+ divide()
+ simplify()
+ TwoQOversqrtPPlus2M = pop()
+
+ push(R_p)
+ push_integer(3)
+ multiply()
+ push(R_m)
+ push_integer(2)
+ multiply()
+ add()
+ ThreePPlus2M = pop()
+
+ # solution1
+ push(sqrtPPlus2M)
+ push(ThreePPlus2M)
+ push(TwoQOversqrtPPlus2M)
+ add()
+ negate()
+ push_rational(1,2)
+ power()
+ simplify()
+ add()
+ push_integer(2)
+ divide()
+ # solution2
+ push(sqrtPPlus2M)
+ push(ThreePPlus2M)
+ push(TwoQOversqrtPPlus2M)
+ add()
+ negate()
+ push_rational(1,2)
+ power()
+ simplify()
+ subtract()
+ push_integer(2)
+ divide()
+ # solution3
+ push(sqrtPPlus2M)
+ negate()
+ push(ThreePPlus2M)
+ push(TwoQOversqrtPPlus2M)
+ subtract()
+ negate()
+ push_rational(1,2)
+ power()
+ simplify()
+ add()
+ push_integer(2)
+ divide()
+ # solution4
+ push(sqrtPPlus2M)
+ negate()
+ push(ThreePPlus2M)
+ push(TwoQOversqrtPPlus2M)
+ subtract()
+ negate()
+ push_rational(1,2)
+ power()
+ simplify()
+ subtract()
+ push_integer(2)
+ divide()
+
+ restore()
+ return
+
+
+
+
+
+
+ # Q ---------------------------
+
+ push(R_determinant)
+ simplify()
+ absValFloat()
+ R_determinant_simplified_toCheckIfZero = pop()
+
+ push(R_DELTA0)
+ simplify()
+ absValFloat()
+ R_DELTA0_simplified_toCheckIfZero = pop()
+
+ S_CHECKED_AS_NOT_ZERO = false
+ choiceOfRadicalInQSoSIsNotZero = 0
+
+ while !S_CHECKED_AS_NOT_ZERO
+
+ Q_CHECKED_AS_NOT_ZERO = false
+ flipSignOFRadicalSoQIsNotZero = false
+
+ # Q will go as denominator to calculate S
+ # so we have to check
+ # that is not zero
+ while !Q_CHECKED_AS_NOT_ZERO
+
+ # D1 under the outer radical
+ push(R_DELTA1)
+
+ # D1^2 under the inner radical
+ push(R_DELTA1)
+ push_integer(2)
+ power()
+
+ # 4*D0^3 under the inner radical
+ push_integer(-4)
+ push(R_DELTA0)
+ push_integer(3)
+ power()
+ multiply()
+
+ # addition under the inner radical
+ add()
+
+ # the second radical
+ push_rational(1,2)
+ power()
+
+ if flipSignOFRadicalSoQIsNotZero
+ negate()
+
+ # the addition under the outer radical
+ add()
+
+ # content of outer radical divided by two
+ push_integer(2)
+ divide()
+
+ if DEBUG then console.log("content of cubic root: " + stack[tos-1].toString())
+
+ # outer radical calculation: cubic root
+ # now we actually have to find all the roots
+ # because we have to pick the one that makes S != 0
+ push_rational(1,3)
+ power()
+ simplify()
+ R_principalCubicRoot = pop()
+ if DEBUG then console.log("principal cubic root: " + R_principalCubicRoot.toString())
+
+ if DEBUG then console.log("tos : " + tos)
+
+ if choiceOfRadicalInQSoSIsNotZero == 0
+ if DEBUG then console.log("chosing principal cubic root")
+ push(R_principalCubicRoot)
+ else if choiceOfRadicalInQSoSIsNotZero == 1
+ if DEBUG then console.log("chosing cubic root beyond principal")
+ push(R_principalCubicRoot)
+ push_rational(-1,2)
+ multiply()
+
+ push_integer(3)
+ push_rational(1,2)
+ power()
+ push(imaginaryunit)
+ multiply()
+ push_rational(-1,2)
+ multiply()
+ push(R_principalCubicRoot)
+ multiply()
+ add()
+ else if choiceOfRadicalInQSoSIsNotZero == 1
+ if DEBUG then console.log("chosing cubic root beyond beyond principal")
+ push(R_principalCubicRoot)
+ push_rational(-1,2)
+ multiply()
+
+ push_integer(3)
+ push_rational(1,2)
+ power()
+ push(imaginaryunit)
+ multiply()
+ push_rational(1,2)
+ multiply()
+ push(R_principalCubicRoot)
+ multiply()
+ add()
+
+
+
+
+ simplify()
+ R_Q = pop()
+ if DEBUG then console.log "Q " + R_Q.toString()
+ if DEBUG then console.log("tos: " + tos)
+
+
+ push(R_Q)
+ simplify()
+ absValFloat()
+
+ R_Q_simplified_toCheckIfZero = pop()
+ if DEBUG then console.log "Q simplified and abs" + R_Q_simplified_toCheckIfZero.toString()
+ if isZeroAtomOrTensor(R_Q_simplified_toCheckIfZero) and (!isZeroAtomOrTensor(R_determinant_simplified_toCheckIfZero) and isZeroAtomOrTensor(R_DELTA0_simplified_toCheckIfZero))
+ if DEBUG then console.log " *********************************** Q IS ZERO and it matters, flipping the sign"
+ flipSignOFRadicalSoQIsNotZero = true
+ else
+ Q_CHECKED_AS_NOT_ZERO = true
+
+
+ if DEBUG then console.log("tos: " + tos)
+
+ # S
+ push_rational(-2,3)
+ push(R_p)
+ multiply()
+
+ push(R_Q)
+
+ push(R_DELTA0)
+ push(R_Q)
+ divide()
+
+ add()
+ #rationalize()
+ #console.log("rationalised: " + stack[tos-1].toString())
+ #simplify()
+
+ push(R_3_a)
+ divide()
+
+ add()
+
+ push_rational(1,2)
+ power()
+
+ push_integer(2)
+ divide()
+
+ show_power_debug = true
+ simplify()
+ R_S = pop()
+ if DEBUG then console.log "S " + R_S.toString()
+
+ # now check if S is zero
+ push(R_S)
+ simplify()
+ absValFloat()
+
+ R_S_simplified_toCheckIfZero = pop()
+ if DEBUG then console.log "S " + R_S_simplified_toCheckIfZero.toString()
+ if isZeroAtomOrTensor(R_S_simplified_toCheckIfZero)
+ if DEBUG then console.log " *********************************** S IS ZERO chosing another cubic root"
+ choiceOfRadicalInQSoSIsNotZero++
+ else
+ S_CHECKED_AS_NOT_ZERO = true
+
+ if DEBUG then console.log("tos: " + tos)
+
+
+ # ----------------------------
+
+ if DEBUG then console.log("tos: " + tos)
+
+ push(p4)
+ negate()
+ push(p3)
+ push_integer(4)
+ multiply()
+ divide()
+ R_minus_b_over_4a = pop()
+
+ push_integer(-4)
+ push(R_S)
+ push_integer(2)
+ power()
+ multiply()
+ push_integer(2)
+ push(R_p)
+ multiply()
+ subtract()
+ R_minus_4S2_minus_2p = pop()
+
+ push(R_q)
+ push(R_S)
+ divide()
+ R_q_over_S = pop()
+
+ if DEBUG then console.log("tos before putting together the 4 solutions: " + tos)
+
+ # first solution
+ push(R_minus_b_over_4a) # first term
+ push(R_S)
+ subtract()
+ push(R_minus_4S2_minus_2p)
+ push(R_q_over_S)
+ add()
+ push_rational(1,2)
+ power()
+ push_integer(2)
+ divide()
+ add()
+ simplify()
+
+ # second solution
+ push(R_minus_b_over_4a) # first term
+ push(R_S)
+ subtract()
+ push(R_minus_4S2_minus_2p)
+ push(R_q_over_S)
+ add()
+ push_rational(1,2)
+ power()
+ push_integer(2)
+ divide()
+ subtract()
+ simplify()
+
+ # third solution
+ push(R_minus_b_over_4a) # first term
+ push(R_S)
+ add()
+ push(R_minus_4S2_minus_2p)
+ push(R_q_over_S)
+ subtract()
+ push_rational(1,2)
+ power()
+ push_integer(2)
+ divide()
+ add()
+ simplify()
+
+ # fourth solution
+ push(R_minus_b_over_4a) # first term
+ push(R_S)
+ add()
+ push(R_minus_4S2_minus_2p)
+ push(R_q_over_S)
+ subtract()
+ push_rational(1,2)
+ power()
+ push_integer(2)
+ divide()
+ subtract()
+ simplify()
+
+ restore()
+ return
+
+ moveTos tos - n
+
+ restore()
+
diff --git a/node_modules/algebrite/sources/round.coffee b/node_modules/algebrite/sources/round.coffee
new file mode 100644
index 0000000..a57757b
--- /dev/null
+++ b/node_modules/algebrite/sources/round.coffee
@@ -0,0 +1,39 @@
+
+
+Eval_round = ->
+ push(cadr(p1))
+ Eval()
+ yround()
+
+yround = ->
+ save()
+ yyround()
+ restore()
+
+yyround = ->
+ d = 0.0
+
+ p1 = pop()
+
+ if (!isNumericAtom(p1))
+ push_symbol(ROUND)
+ push(p1)
+ list(2)
+ return
+
+ if (isdouble(p1))
+ d = Math.round(p1.d)
+ push_double(d)
+ return
+
+ if (isinteger(p1))
+ push(p1)
+ return
+
+ push p1
+ yyfloat()
+ p1 = pop()
+ push_integer Math.round(p1.d)
+
+
+
diff --git a/node_modules/algebrite/sources/scan.coffee b/node_modules/algebrite/sources/scan.coffee
new file mode 100644
index 0000000..1d07eb2
--- /dev/null
+++ b/node_modules/algebrite/sources/scan.coffee
@@ -0,0 +1,829 @@
+# This scanner uses the recursive descent method.
+#
+# The char pointers token_str and scan_str are pointers to the input string as
+# in the following example.
+#
+# | g | a | m | m | a | | a | l | p | h | a |
+# ^ ^
+# token_str scan_str
+#
+# The char pointer token_buf points to a malloc buffer.
+#
+# | g | a | m | m | a | \0 |
+# ^
+# token_buf
+#
+# In the sequence of method invocations for scanning,
+# first we do the calls for scanning the operands
+# of the operators of least precedence.
+# So, since precedence in maths goes something like
+# (form high to low) exponents, mult/div, plus/minus
+# so we scan first for terms, then factors, then powers.
+# That's the general idea, but of course we also have to deal
+# with things like parens, non-commutative
+# dot (or inner) product, assignments and tests,
+# function calls etc.
+# Note that a^1/2 is, correctly, a/2, not, incorrectly, sqrt(a),
+# see comment in related test in power.coffee for more about this.
+
+# Notes:
+#
+# Formerly add() and multiply() were used to construct expressions but
+# this preevaluation caused problems.
+#
+# For example, suppose A has the floating point value inf.
+#
+# Before, the expression A/A resulted in 1 because the scanner would
+# divide the symbols.
+#
+# After removing add() and multiply(), A/A results in nan which is the
+# correct result.
+#
+# The functions negate() and inverse() are used but they do not cause
+# problems with preevaluation of symbols.
+
+
+T_INTEGER = 1001
+T_DOUBLE = 1002
+T_SYMBOL = 1003
+T_FUNCTION = 1004
+T_NEWLINE = 1006
+T_STRING = 1007
+T_GTEQ = 1008
+T_LTEQ = 1009
+T_EQ = 1010
+T_NEQ = 1011
+T_QUOTASSIGN = 1012
+
+token = ""
+newline_flag = 0
+meta_mode = 0
+
+input_str = 0
+scan_str = 0
+token_str = 0
+token_buf = 0
+
+lastFoundSymbol = null
+symbolsRightOfAssignment = null
+symbolsLeftOfAssignment = null
+isSymbolLeftOfAssignment = null
+scanningParameters = null
+functionInvokationsScanningStack = null
+skipRootVariableToBeSolved = false
+assignmentFound = null
+
+
+# Returns number of chars scanned and expr on stack.
+
+# Returns zero when nothing left to scan.
+
+# takes a string
+
+scanned = ""
+scan = (s) ->
+ if DEBUG then console.log "#### scanning " + s
+ #if s=="y=x"
+ # debugger
+ #if s=="y"
+ # debugger
+ #if s=="i=sqrt(-1)"
+ # debugger
+
+ lastFoundSymbol = null
+ symbolsRightOfAssignment = []
+ symbolsLeftOfAssignment = []
+ isSymbolLeftOfAssignment = true
+ scanningParameters = []
+ functionInvokationsScanningStack = [""]
+ assignmentFound = false
+
+
+ scanned = s
+ meta_mode = 0
+ expanding++
+ input_str = 0
+ scan_str = 0
+ get_next_token()
+ if (token == "")
+ push(symbol(NIL))
+ expanding--
+ return 0
+ scan_stmt()
+ expanding--
+
+ if !assignmentFound
+ symbolsInExpressionsWithoutAssignments = symbolsInExpressionsWithoutAssignments.concat symbolsLeftOfAssignment
+
+ return token_str - input_str
+
+# takes a string
+scan_meta = (s) ->
+ scanned = s
+ meta_mode = 1
+ expanding++
+ input_str = 0
+ scan_str = 0
+ get_next_token()
+ if (token == "")
+ push(symbol(NIL))
+ expanding--
+ return 0
+ scan_stmt()
+ expanding--
+ return token_str - input_str
+
+scan_stmt = ->
+ scan_relation()
+
+ assignmentIsOfQuotedType = false
+
+ if token == T_QUOTASSIGN
+ assignmentIsOfQuotedType = true
+
+ if (token == T_QUOTASSIGN or token == '=')
+ symbolLeftOfAssignment = lastFoundSymbol
+ if DEBUG then console.log("assignment!")
+ assignmentFound = true
+ isSymbolLeftOfAssignment = false
+
+ get_next_token()
+ push_symbol(SETQ)
+ swap()
+
+ # if it's a := then add a quote
+ if (assignmentIsOfQuotedType)
+ push_symbol(QUOTE)
+
+ scan_relation()
+
+ # if it's a := then you have to list
+ # together the quote and its argument
+ if assignmentIsOfQuotedType
+ list(2)
+
+ list(3)
+
+ isSymbolLeftOfAssignment = true
+
+ if codeGen
+
+ # in case of re-assignment, the symbol on the
+ # left will also be in the set of the symbols
+ # on the right. In that case just remove it from
+ # the symbols on the right.
+ indexOfSymbolLeftOfAssignment = symbolsRightOfAssignment.indexOf(symbolLeftOfAssignment)
+ if indexOfSymbolLeftOfAssignment != -1
+ symbolsRightOfAssignment.splice(indexOfSymbolLeftOfAssignment, 1)
+ symbolsHavingReassignments.push symbolLeftOfAssignment
+
+ # print out the immediate dependencies
+ if DEBUG
+ console.log "locally, " + symbolLeftOfAssignment + " depends on: "
+ for i in symbolsRightOfAssignment
+ console.log " " + i
+
+ # ok add the local dependencies to the existing
+ # dependencies of this left-value symbol
+
+ # create the exiting dependencies list if it doesn't exist
+ symbolsDependencies[symbolLeftOfAssignment] ?= []
+ existingDependencies = symbolsDependencies[symbolLeftOfAssignment]
+
+ # copy over the new dependencies to the existing
+ # dependencies avoiding repetitions
+ for i in symbolsRightOfAssignment
+ if existingDependencies.indexOf(i) == -1
+ existingDependencies.push i
+
+ symbolsRightOfAssignment = []
+
+scan_relation = ->
+ scan_expression()
+ switch (token)
+ when T_EQ
+ push_symbol(TESTEQ)
+ swap()
+ get_next_token()
+ scan_expression()
+ list(3)
+ when T_NEQ
+ push_symbol(NOT)
+ swap()
+ push_symbol(TESTEQ)
+ swap()
+ get_next_token()
+ scan_expression()
+ list(3)
+ list(2)
+ when T_LTEQ
+ push_symbol(TESTLE)
+ swap()
+ get_next_token()
+ scan_expression()
+ list(3)
+ when T_GTEQ
+ push_symbol(TESTGE)
+ swap()
+ get_next_token()
+ scan_expression()
+ list(3)
+ when '<'
+ push_symbol(TESTLT)
+ swap()
+ get_next_token()
+ scan_expression()
+ list(3)
+ when '>'
+ push_symbol(TESTGT)
+ swap()
+ get_next_token()
+ scan_expression()
+ list(3)
+
+scan_expression = ->
+ h = tos
+ switch token
+ when '+'
+ get_next_token()
+ scan_term()
+ when '-'
+ get_next_token()
+ scan_term()
+ negate()
+ else
+ scan_term()
+
+ while (newline_flag == 0 && (token == '+' || token == '-'))
+ if (token == '+')
+ get_next_token()
+ scan_term()
+ else
+ get_next_token()
+ scan_term()
+ negate()
+
+ if (tos - h > 1)
+ list(tos - h)
+ push_symbol(ADD)
+ swap()
+ cons()
+
+is_factor = ->
+
+ if token.charCodeAt?(0) == dotprod_unicode
+ return 1
+
+ switch (token)
+ when '*', '/'
+ return 1
+ when '(', T_SYMBOL, T_FUNCTION, T_INTEGER, T_DOUBLE, T_STRING
+ if (newline_flag) # implicit mul can't cross line
+ scan_str = token_str # better error display
+ return 0
+ else
+ return 1
+ return 0
+
+
+simplify_1_in_products = (tos,h) ->
+ if (tos > h && isrational(stack[tos - 1]) && equaln(stack[tos - 1], 1))
+ pop()
+
+# calculate away consecutive constants
+multiply_consecutive_constants = (tos,h)->
+ if (tos > h + 1 && isNumericAtom(stack[tos - 2]) && isNumericAtom(stack[tos - 1]))
+ multiply()
+
+
+scan_term = ->
+ h = tos
+
+ scan_factor()
+
+ if parse_time_simplifications
+ simplify_1_in_products(tos,h)
+
+ while (is_factor())
+ if (token == '*')
+ get_next_token()
+ scan_factor()
+ else if (token == '/')
+ # in case of 1/... then
+ # we scanned the 1, we get rid
+ # of it because otherwise it becomes
+ # an extra factor that wasn't there and
+ # things like
+ # 1/(2*a) become 1*(1/(2*a))
+ simplify_1_in_products(tos,h)
+ get_next_token()
+ scan_factor()
+ inverse()
+ else if (token.charCodeAt?(0) == dotprod_unicode)
+ get_next_token()
+ push_symbol(INNER)
+ swap()
+ scan_factor()
+ list(3)
+
+ else
+ scan_factor()
+
+ if parse_time_simplifications
+ multiply_consecutive_constants(tos,h)
+ simplify_1_in_products(tos,h)
+
+ if (h == tos)
+ push_integer(1)
+ else if (tos - h > 1)
+ list(tos - h)
+ push_symbol(MULTIPLY)
+ swap()
+ cons()
+
+scan_power = ->
+ if (token == '^')
+ get_next_token()
+ push_symbol(POWER)
+ swap()
+ scan_factor()
+ list(3)
+
+scan_index = (h) ->
+ #console.log "[ as index"
+ get_next_token()
+ push_symbol(INDEX)
+ swap()
+ scan_expression()
+ while (token == ',')
+ get_next_token()
+ scan_expression()
+ if (token != ']')
+ scan_error("] expected")
+ get_next_token()
+ list(tos - h)
+
+
+scan_factor = ->
+
+ h = tos
+
+ #console.log "scan_factor token: " + token
+
+ firstFactorIsNumber = false
+
+ if (token == '(')
+ scan_subexpr()
+ else if (token == T_SYMBOL)
+ scan_symbol()
+ else if (token == T_FUNCTION)
+ scan_function_call_with_function_name()
+ else if token == '['
+ #console.log "[ as tensor"
+ #debugger
+ scan_tensor()
+ else if (token == T_INTEGER)
+ firstFactorIsNumber = true
+ bignum_scan_integer(token_buf)
+ get_next_token()
+ else if (token == T_DOUBLE)
+ firstFactorIsNumber = true
+ bignum_scan_float(token_buf)
+ get_next_token()
+ else if (token == T_STRING)
+ scan_string()
+ else
+ scan_error("syntax error")
+
+
+ # after the main initial part of the factor that
+ # we just scanned above,
+ # we can get an arbitrary about of appendages
+ # of the form ...[...](...)...
+ # If the main part is not a number, then these are all, respectively,
+ # - index references (as opposed to tensor definition) and
+ # - function calls without an explicit function name
+ # (instead of subexpressions or parameters of function
+ # definitions or function calls with an explicit function
+ # name), respectively
+ while token == '[' or token == '(' and newline_flag == 0 and !firstFactorIsNumber
+ if token == '['
+ scan_index(h)
+ else if token == '('
+ #console.log "( as function call without function name "
+ scan_function_call_without_function_name()
+
+
+
+ while (token == '!')
+ get_next_token()
+ push_symbol(FACTORIAL)
+ swap()
+ list(2)
+
+ # in theory we could already count the
+ # number of transposes and simplify them
+ # away, but it's not that clean to have
+ # multiple places where that happens, and
+ # the parser is not the place.
+ while (token.charCodeAt?(0) == transpose_unicode)
+ get_next_token()
+ push_symbol(TRANSPOSE)
+ swap()
+ list(2)
+
+ scan_power()
+
+
+addSymbolRightOfAssignment = (theSymbol) ->
+ if predefinedSymbolsInGlobalScope_doNotTrackInDependencies.indexOf(theSymbol) == -1 and
+ symbolsRightOfAssignment.indexOf(theSymbol) == -1 and
+ symbolsRightOfAssignment.indexOf("'"+theSymbol) == -1 and
+ !skipRootVariableToBeSolved
+ if DEBUG then console.log("... adding symbol: " + theSymbol + " to the set of the symbols right of assignment")
+ prefixVar = ""
+ for i in [1...functionInvokationsScanningStack.length]
+ if functionInvokationsScanningStack[i] != ""
+ prefixVar += functionInvokationsScanningStack[i] + "_" + i + "_"
+
+ theSymbol = prefixVar + theSymbol
+ symbolsRightOfAssignment.push theSymbol
+
+addSymbolLeftOfAssignment = (theSymbol) ->
+ if predefinedSymbolsInGlobalScope_doNotTrackInDependencies.indexOf(theSymbol) == -1 and
+ symbolsLeftOfAssignment.indexOf(theSymbol) == -1 and
+ symbolsLeftOfAssignment.indexOf("'"+theSymbol) == -1 and
+ !skipRootVariableToBeSolved
+ if DEBUG then console.log("... adding symbol: " + theSymbol + " to the set of the symbols left of assignment")
+ prefixVar = ""
+ for i in [1...functionInvokationsScanningStack.length]
+ if functionInvokationsScanningStack[i] != ""
+ prefixVar += functionInvokationsScanningStack[i] + "_" + i + "_"
+
+ theSymbol = prefixVar + theSymbol
+ symbolsLeftOfAssignment.push theSymbol
+
+scan_symbol = ->
+ if (token != T_SYMBOL)
+ scan_error("symbol expected")
+ if (meta_mode && token_buf.length == 1)
+ switch (token_buf[0])
+ when 'a'
+ push(symbol(METAA))
+ when 'b'
+ push(symbol(METAB))
+ when 'x'
+ push(symbol(METAX))
+ else
+ push(usr_symbol(token_buf))
+ else
+ push(usr_symbol(token_buf))
+ #console.log "found symbol: " + token_buf
+
+ if scanningParameters.length == 0
+ if DEBUG then console.log "out of scanning parameters, processing " + token_buf
+ lastFoundSymbol = token_buf
+ if isSymbolLeftOfAssignment
+ addSymbolLeftOfAssignment token_buf
+ else
+ if DEBUG then console.log "still scanning parameters, skipping " + token_buf
+ if isSymbolLeftOfAssignment
+ addSymbolRightOfAssignment "'" + token_buf
+
+ if DEBUG then console.log("found symbol: " + token_buf + " left of assignment: " + isSymbolLeftOfAssignment)
+
+ # if we were looking at the right part of an assignment while we
+ # found the symbol, then add it to the "symbolsRightOfAssignment"
+ # set (we check for duplications)
+ if !isSymbolLeftOfAssignment
+ addSymbolRightOfAssignment token_buf
+ get_next_token()
+
+scan_string = ->
+ push new_string(token_buf)
+ get_next_token()
+
+scan_function_call_with_function_name = ->
+ if DEBUG then console.log "-- scan_function_call_with_function_name start"
+ n = 1 # the parameter number as we scan parameters
+ p = new U()
+ p = usr_symbol(token_buf)
+
+ push(p)
+ functionName = token_buf
+ if functionName == "roots" or functionName == "defint" or functionName == "sum" or functionName == "product" or functionName == "for"
+ functionInvokationsScanningStack.push token_buf
+ lastFoundSymbol = token_buf
+ if !isSymbolLeftOfAssignment
+ addSymbolRightOfAssignment token_buf
+
+ get_next_token() # open parens
+ get_next_token() # 1st parameter
+ scanningParameters.push true
+ if (token != ')')
+ scan_stmt()
+ n++
+ while (token == ',')
+ get_next_token()
+ # roots' disappearing variable, if there, is the second one
+ if n == 2 and functionInvokationsScanningStack[functionInvokationsScanningStack.length - 1].indexOf("roots") != -1
+ symbolsRightOfAssignment = symbolsRightOfAssignment.filter (x) -> !(new RegExp("roots_" + (functionInvokationsScanningStack.length - 1) + "_" + token_buf)).test(x)
+ skipRootVariableToBeSolved = true
+ # sums' disappearing variable, is alsways the second one
+ if n == 2 and functionInvokationsScanningStack[functionInvokationsScanningStack.length - 1].indexOf("sum") != -1
+ symbolsRightOfAssignment = symbolsRightOfAssignment.filter (x) -> !(new RegExp("sum_" + (functionInvokationsScanningStack.length - 1) + "_" + token_buf)).test(x)
+ skipRootVariableToBeSolved = true
+ # product's disappearing variable, is alsways the second one
+ if n == 2 and functionInvokationsScanningStack[functionInvokationsScanningStack.length - 1].indexOf("product") != -1
+ symbolsRightOfAssignment = symbolsRightOfAssignment.filter (x) -> !(new RegExp("product_" + (functionInvokationsScanningStack.length - 1) + "_" + token_buf)).test(x)
+ skipRootVariableToBeSolved = true
+ # for's disappearing variable, is alsways the second one
+ if n == 2 and functionInvokationsScanningStack[functionInvokationsScanningStack.length - 1].indexOf("for") != -1
+ symbolsRightOfAssignment = symbolsRightOfAssignment.filter (x) -> !(new RegExp("for_" + (functionInvokationsScanningStack.length - 1) + "_" + token_buf)).test(x)
+ skipRootVariableToBeSolved = true
+ # defint's disappearing variables can be in positions 2,5,8...
+ if functionInvokationsScanningStack[functionInvokationsScanningStack.length - 1].indexOf("defint") != -1 and
+ (n == 2 or (n>2 and ((n-2) % 3 == 0)))
+ symbolsRightOfAssignment = symbolsRightOfAssignment.filter (x) -> !(new RegExp("defint_" + (functionInvokationsScanningStack.length - 1) + "_" + token_buf)).test(x)
+ skipRootVariableToBeSolved = true
+
+ scan_stmt()
+ skipRootVariableToBeSolved = false
+ n++
+
+ # todo refactor this, there are two copies
+ # this catches the case where the "roots" variable is not specified
+ if n == 2 and functionInvokationsScanningStack[functionInvokationsScanningStack.length - 1].indexOf("roots") != -1
+ symbolsRightOfAssignment = symbolsRightOfAssignment.filter (x) -> !(new RegExp("roots_" + (functionInvokationsScanningStack.length - 1) + "_" + "x")).test(x)
+
+ scanningParameters.pop()
+
+ for i in [0..symbolsRightOfAssignment.length]
+ if symbolsRightOfAssignment[i]?
+ if functionName == "roots"
+ symbolsRightOfAssignment[i] = symbolsRightOfAssignment[i].replace(new RegExp("roots_" + (functionInvokationsScanningStack.length - 1) + "_"),"")
+ if functionName == "defint"
+ symbolsRightOfAssignment[i] = symbolsRightOfAssignment[i].replace(new RegExp("defint_" + (functionInvokationsScanningStack.length - 1) + "_"),"")
+ if functionName == "sum"
+ symbolsRightOfAssignment[i] = symbolsRightOfAssignment[i].replace(new RegExp("sum_" + (functionInvokationsScanningStack.length - 1) + "_"),"")
+ if functionName == "product"
+ symbolsRightOfAssignment[i] = symbolsRightOfAssignment[i].replace(new RegExp("product_" + (functionInvokationsScanningStack.length - 1) + "_"),"")
+ if functionName == "for"
+ symbolsRightOfAssignment[i] = symbolsRightOfAssignment[i].replace(new RegExp("for_" + (functionInvokationsScanningStack.length - 1) + "_"),"")
+
+ if (token != ')')
+ scan_error(") expected")
+
+ get_next_token()
+ list(n)
+ if functionName == "roots" or functionName == "defint" or functionName == "sum" or functionName == "product" or functionName == "for"
+ functionInvokationsScanningStack.pop()
+ if functionName == symbol(PATTERN).printname
+ patternHasBeenFound = true
+
+ if DEBUG then console.log "-- scan_function_call_with_function_name end"
+
+scan_function_call_without_function_name = ->
+ if DEBUG then console.log "-- scan_function_call_without_function_name start"
+
+ # the function will have to be looked up
+ # at runtime (i.e. we need to evaulate something to find it
+ # e.g. it might be inside a tensor, so we'd need to evaluate
+ # a tensor element access in that case)
+ push_symbol(EVAL)
+ swap()
+ list(2)
+
+ n = 1 # the parameter number as we scan parameters
+ get_next_token() # left paren
+ scanningParameters.push true
+ if (token != ')')
+ scan_stmt()
+ n++
+ while (token == ',')
+ get_next_token()
+ scan_stmt()
+ n++
+
+ scanningParameters.pop()
+
+
+ if (token != ')')
+ scan_error(") expected")
+
+ get_next_token()
+ list(n)
+
+ if DEBUG then console.log "-- scan_function_call_without_function_name end: " + stack[tos-1]
+
+# scan subexpression
+
+scan_subexpr = ->
+ n = 0
+ if (token != '(')
+ scan_error("( expected")
+ get_next_token()
+ scan_stmt()
+ if (token != ')')
+ scan_error(") expected")
+ get_next_token()
+
+scan_tensor = ->
+ n = 0
+ if (token != '[')
+ scan_error("[ expected")
+
+ get_next_token()
+
+ #console.log "scanning the next statement"
+ scan_stmt()
+
+ n = 1
+ while (token == ',')
+ get_next_token()
+ scan_stmt()
+ n++
+
+ #console.log "building tensor with elements number: " + n
+ build_tensor(n)
+
+ if (token != ']')
+ scan_error("] expected")
+ get_next_token()
+
+scan_error = (errmsg) ->
+ errorMessage = ""
+
+ # try not to put question mark on orphan line
+
+ while (input_str != scan_str)
+ if ((scanned[input_str] == '\n' || scanned[input_str] == '\r') && input_str + 1 == scan_str)
+ break
+ errorMessage += scanned[input_str++]
+
+ errorMessage += " ? "
+
+ while (scanned[input_str] && (scanned[input_str] != '\n' && scanned[input_str] != '\r'))
+ errorMessage += scanned[input_str++]
+
+ errorMessage += '\n'
+
+ stop(errmsg)
+
+# There are n expressions on the stack, possibly tensors.
+#
+# This function assembles the stack expressions into a single tensor.
+#
+# For example, at the top level of the expression ((a,b),(c,d)), the vectors
+# (a,b) and (c,d) would be on the stack.
+
+# takes an integer
+build_tensor = (n) ->
+ # int i, j, k, ndim, nelem
+
+ i = 0
+
+ save()
+
+ p2 = alloc_tensor(n)
+ p2.tensor.ndim = 1
+ p2.tensor.dim[0] = n
+ for i in [0...n]
+ p2.tensor.elem[i] = stack[tos-n+i]
+
+ check_tensor_dimensions p2
+
+ moveTos tos - n
+
+ push(p2)
+
+ restore()
+
+get_next_token = ->
+ newline_flag = 0
+ while (1)
+ get_token()
+ if (token != T_NEWLINE)
+ break
+ newline_flag = 1
+ if DEBUG then console.log "get_next_token token: " + token
+ #if token == ')'
+ # debugger
+
+get_token = ->
+ # skip spaces
+ while (isspace(scanned[scan_str]))
+ if (scanned[scan_str] == '\n' || scanned[scan_str] == '\r')
+ token = T_NEWLINE
+ scan_str++
+ return
+ scan_str++
+
+ token_str = scan_str
+
+ # end of string?
+
+ if (scan_str == scanned.length)
+ token = ""
+ return
+
+ # number?
+
+ if (isdigit(scanned[scan_str]) || scanned[scan_str] == '.')
+ while (isdigit(scanned[scan_str]))
+ scan_str++
+ if (scanned[scan_str] == '.')
+ scan_str++
+ while (isdigit(scanned[scan_str]))
+ scan_str++
+ if (scanned[scan_str] == 'e' && (scanned[scan_str+1] == '+' || scanned[scan_str+1] == '-' || isdigit(scanned[scan_str+1])))
+ scan_str += 2
+ while (isdigit(scanned[scan_str]))
+ scan_str++
+ token = T_DOUBLE
+ else
+ token = T_INTEGER
+ update_token_buf(token_str, scan_str)
+ return
+
+ # symbol?
+
+ if (isalpha(scanned[scan_str]))
+ while (isalnumorunderscore(scanned[scan_str]))
+ scan_str++
+ if (scanned[scan_str] == '(')
+ token = T_FUNCTION
+ else
+ token = T_SYMBOL
+ update_token_buf(token_str, scan_str)
+ return
+
+ # string ?
+
+ if (scanned[scan_str] == '"')
+ scan_str++
+ while (scanned[scan_str] != '"')
+ #if (scan_str == scanned.length || scanned[scan_str] == '\n' || scanned[scan_str] == '\r')
+ if (scan_str == scanned.length - 1)
+ scan_str++
+ scan_error("runaway string")
+ scan_str--
+ scan_str++
+ scan_str++
+ token = T_STRING
+ update_token_buf(token_str + 1, scan_str - 1)
+ return
+
+ # comment?
+
+ if (scanned[scan_str] == '#' || scanned[scan_str] == '-' && scanned[scan_str+1] == '-')
+ while (scanned[scan_str] && scanned[scan_str] != '\n' && scanned[scan_str] != '\r')
+ scan_str++
+ if (scanned[scan_str])
+ scan_str++
+ token = T_NEWLINE
+ return
+
+ # quote-assignment
+ if (scanned[scan_str] == ':' && scanned[scan_str+1] == '=')
+ scan_str += 2
+ token = T_QUOTASSIGN
+ return
+
+ # relational operator?
+ if (scanned[scan_str] == '=' && scanned[scan_str+1] == '=')
+ scan_str += 2
+ token = T_EQ
+ return
+
+ # != operator. It's a little odd because
+ # "!" is not a "not", which would make things consistent.
+ # (it's used for factorial).
+ # An alternative would be to use "<>" but it's not used
+ # a lot in other languages...
+ if (scanned[scan_str] == '!' && scanned[scan_str+1] == '=')
+ scan_str += 2
+ token = T_NEQ
+ return
+
+ if (scanned[scan_str] == '<' && scanned[scan_str+1] == '=')
+ scan_str += 2
+ token = T_LTEQ
+ return
+
+ if (scanned[scan_str] == '>' && scanned[scan_str+1] == '=')
+ scan_str += 2
+ token = T_GTEQ
+ return
+
+ # single char token
+
+ token = scanned[scan_str++]
+
+# both strings
+update_token_buf = (a,b) ->
+
+ token_buf = scanned.substring(a,b)
+
+
+$.scan = scan
diff --git a/node_modules/algebrite/sources/sgn.coffee b/node_modules/algebrite/sources/sgn.coffee
new file mode 100644
index 0000000..07d7bcb
--- /dev/null
+++ b/node_modules/algebrite/sources/sgn.coffee
@@ -0,0 +1,85 @@
+#-----------------------------------------------------------------------------
+#
+# Author : philippe.billet@noos.fr
+#
+# sgn sign function
+#
+#
+#-----------------------------------------------------------------------------
+
+
+
+Eval_sgn = ->
+ push(cadr(p1))
+ Eval()
+ sgn()
+
+sgn = ->
+ save()
+ yysgn()
+ restore()
+
+#define X p1
+
+yysgn = ->
+
+ p1 = pop()
+
+
+ if (isdouble(p1))
+ if (p1.d > 0)
+ push_integer(1)
+ return
+ else
+ if (p1.d == 0)
+ push_integer(1)
+ return
+ else
+ push_integer(-1)
+ return
+
+ if (isrational(p1))
+ if (MSIGN(mmul(p1.q.a,p1.q.b)) == -1)
+ push_integer(-1)
+ return
+ else
+ if (MZERO(mmul(p1.q.a,p1.q.b)))
+ push_integer(0)
+ return
+ else
+ push_integer(1)
+ return
+
+ if (iscomplexnumber(p1))
+ push_integer(-1)
+ push(p1)
+ absval()
+ power()
+ push(p1)
+ multiply()
+ return
+
+
+ if (isnegativeterm(p1))
+ push_symbol(SGN)
+ push(p1)
+ negate()
+ list(2)
+ push_integer(-1)
+ multiply()
+ return
+
+ ###
+ push_integer(2)
+ push(p1)
+ heaviside()
+ multiply()
+ push_integer(-1)
+ add()
+ ###
+
+ push_symbol(SGN)
+ push(p1)
+ list(2)
+
+
diff --git a/node_modules/algebrite/sources/shape.coffee b/node_modules/algebrite/sources/shape.coffee
new file mode 100644
index 0000000..5484daa
--- /dev/null
+++ b/node_modules/algebrite/sources/shape.coffee
@@ -0,0 +1,50 @@
+# shape of tensor
+
+
+
+Eval_shape = ->
+ push(cadr(p1))
+ Eval()
+ shape()
+
+shape = ->
+ i = 0
+ ndim = 0
+ t = 0
+ ai = []
+ an = []
+ for i in [0...MAXDIM]
+ ai[i] = 0
+ an[i] = 0
+
+ #U **a, **b
+
+ save()
+
+ p1 = pop()
+
+ if (!istensor(p1))
+ if (!isZeroAtomOrTensor(p1))
+ stop("transpose: tensor expected, 1st arg is not a tensor")
+ push(zero)
+ restore()
+ return
+
+ ndim = p1.tensor.ndim
+
+
+ p2 = alloc_tensor(ndim)
+
+ p2.tensor.ndim = 1
+ p2.tensor.dim[0] = ndim
+
+
+
+ for i in [0...ndim]
+ push_integer(p1.tensor.dim[i])
+ p2.tensor.elem[i] = pop()
+
+ push(p2)
+
+ restore()
+
diff --git a/node_modules/algebrite/sources/simfac.coffee b/node_modules/algebrite/sources/simfac.coffee
new file mode 100644
index 0000000..91df3ec
--- /dev/null
+++ b/node_modules/algebrite/sources/simfac.coffee
@@ -0,0 +1,238 @@
+###
+ Simplify factorials
+
+The following script
+
+ F(n,k) = k binomial(n,k)
+ (F(n,k) + F(n,k-1)) / F(n+1,k)
+
+generates
+
+ k! n! n! (1 - k + n)! k! n!
+ -------------------- + -------------------- - ----------------------
+ (-1 + k)! (1 + n)! (1 + n)! (-k + n)! k (-1 + k)! (1 + n)!
+
+Simplify each term to get
+
+ k 1 - k + n 1
+ ------- + ----------- - -------
+ 1 + n 1 + n 1 + n
+
+Then simplify the sum to get
+
+ n
+ -------
+ 1 + n
+
+###
+
+
+
+# simplify factorials term-by-term
+
+Eval_simfac = ->
+ push(cadr(p1))
+ Eval()
+ simfac()
+
+#if 1
+
+simfac = ->
+ h = 0
+ save()
+ p1 = pop()
+ if (car(p1) == symbol(ADD))
+ h = tos
+ p1 = cdr(p1)
+ while (p1 != symbol(NIL))
+ push(car(p1))
+ simfac_term()
+ p1 = cdr(p1)
+ add_all(tos - h)
+ else
+ push(p1)
+ simfac_term()
+ restore()
+
+
+#else
+###
+void
+simfac(void)
+{
+ int h
+ save()
+ p1 = pop()
+ if (car(p1) == symbol(ADD)) {
+ h = tos
+ p1 = cdr(p1)
+ while (p1 != symbol(NIL)) {
+ push(car(p1))
+ simfac_term()
+ p1 = cdr(p1)
+ }
+ addk(tos - h)
+ p1 = pop()
+ if (find(p1, symbol(FACTORIAL))) {
+ push(p1)
+ if (car(p1) == symbol(ADD)) {
+ Condense()
+ simfac_term()
+ }
+ }
+ } else {
+ push(p1)
+ simfac_term()
+ }
+ restore()
+}
+
+#endif
+###
+
+simfac_term = ->
+ h = 0
+
+ save()
+
+ p1 = pop()
+
+ # if not a product of factors then done
+
+ if (car(p1) != symbol(MULTIPLY))
+ push(p1)
+ restore()
+ return
+
+ # push all factors
+
+ h = tos
+ p1 = cdr(p1)
+ while (p1 != symbol(NIL))
+ push(car(p1))
+ p1 = cdr(p1)
+
+ # keep trying until no more to do
+
+ while (yysimfac(h))
+ doNothing = 1
+
+ multiply_all_noexpand(tos - h)
+
+ restore()
+
+# try all pairs of factors
+
+yysimfac = (h) ->
+ i = 0
+ j = 0
+
+ for i in [h...tos]
+ p1 = stack[i]
+ for j in [h...tos]
+ if (i == j)
+ continue
+ p2 = stack[j]
+
+ # n! / n -> (n - 1)!
+
+ if (car(p1) == symbol(FACTORIAL)\
+ && car(p2) == symbol(POWER)\
+ && isminusone(caddr(p2))\
+ && equal(cadr(p1), cadr(p2)))
+ push(cadr(p1))
+ push(one)
+ subtract()
+ factorial()
+ stack[i] = pop()
+ stack[j] = one
+ return 1
+
+ # n / n! -> 1 / (n - 1)!
+
+ if (car(p2) == symbol(POWER)\
+ && isminusone(caddr(p2))\
+ && caadr(p2) == symbol(FACTORIAL)\
+ && equal(p1, cadadr(p2)))
+ push(p1)
+ push_integer(-1)
+ add()
+ factorial()
+ reciprocate()
+ stack[i] = pop()
+ stack[j] = one
+ return 1
+
+ # (n + 1) n! -> (n + 1)!
+
+ if (car(p2) == symbol(FACTORIAL))
+ push(p1)
+ push(cadr(p2))
+ subtract()
+ p3 = pop()
+ if (isplusone(p3))
+ push(p1)
+ factorial()
+ stack[i] = pop()
+ stack[j] = one
+ return 1
+
+ # 1 / ((n + 1) n!) -> 1 / (n + 1)!
+
+ if (car(p1) == symbol(POWER)\
+ && isminusone(caddr(p1))\
+ && car(p2) == symbol(POWER)\
+ && isminusone(caddr(p2))\
+ && caadr(p2) == symbol(FACTORIAL))
+ push(cadr(p1))
+ push(cadr(cadr(p2)))
+ subtract()
+ p3 = pop()
+ if (isplusone(p3))
+ push(cadr(p1))
+ factorial()
+ reciprocate()
+ stack[i] = pop()
+ stack[j] = one
+ return 1
+
+ # (n + 1)! / n! -> n + 1
+
+ # n! / (n + 1)! -> 1 / (n + 1)
+
+ if (car(p1) == symbol(FACTORIAL)\
+ && car(p2) == symbol(POWER)\
+ && isminusone(caddr(p2))\
+ && caadr(p2) == symbol(FACTORIAL))
+ push(cadr(p1))
+ push(cadr(cadr(p2)))
+ subtract()
+ p3 = pop()
+ if (isplusone(p3))
+ stack[i] = cadr(p1)
+ stack[j] = one
+ return 1
+ if (isminusone(p3))
+ push(cadr(cadr(p2)))
+ reciprocate()
+ stack[i] = pop()
+ stack[j] = one
+ return 1
+ if (equaln(p3, 2))
+ stack[i] = cadr(p1)
+ push(cadr(p1))
+ push_integer(-1)
+ add()
+ stack[j] = pop()
+ return 1
+ if (equaln(p3, -2))
+ push(cadr(cadr(p2)))
+ reciprocate()
+ stack[i] = pop()
+ push(cadr(cadr(p2)))
+ push_integer(-1)
+ add()
+ reciprocate()
+ stack[j] = pop()
+ return 1
+ return 0
diff --git a/node_modules/algebrite/sources/simplify.coffee b/node_modules/algebrite/sources/simplify.coffee
new file mode 100644
index 0000000..1997999
--- /dev/null
+++ b/node_modules/algebrite/sources/simplify.coffee
@@ -0,0 +1,952 @@
+
+DEBUG_SIMPLIFY = false
+
+Eval_simplify = ->
+ push(cadr(p1))
+ runUserDefinedSimplifications()
+ Eval()
+ simplify()
+
+runUserDefinedSimplifications = ->
+ # -----------------------
+ # unfortunately for the time being user
+ # specified simplifications are only
+ # run in things which don't contain
+ # integrals.
+ # Doesn't work yet, could be because of
+ # some clobbering as "transform" is called
+ # recursively?
+ if userSimplificationsInListForm.length != 0 and !Find(cadr(p1), symbol(INTEGRAL))
+ originalexpanding = expanding
+ expanding = false
+ if DEBUG_SIMPLIFY then console.log("runUserDefinedSimplifications passed: " + stack[tos-1].toString())
+ Eval()
+ if DEBUG_SIMPLIFY then console.log("runUserDefinedSimplifications after eval no expanding: " + stack[tos-1].toString())
+ expanding = originalexpanding
+
+
+ p1 = stack[tos-1]
+
+ if DEBUG_SIMPLIFY then console.log "patterns to be checked: "
+ for eachSimplification in userSimplificationsInListForm
+ if DEBUG_SIMPLIFY then console.log "..." + eachSimplification
+
+ atLeastOneSuccessInRouldOfRulesApplications = true
+ numberOfRulesApplications = 0
+
+
+ while atLeastOneSuccessInRouldOfRulesApplications and numberOfRulesApplications < MAX_CONSECUTIVE_APPLICATIONS_OF_ALL_RULES
+ atLeastOneSuccessInRouldOfRulesApplications = false
+ numberOfRulesApplications++
+ for eachSimplification in userSimplificationsInListForm
+ success = true
+ eachConsecutiveRuleApplication = 0
+ while success and eachConsecutiveRuleApplication < MAX_CONSECUTIVE_APPLICATIONS_OF_SINGLE_RULE
+ eachConsecutiveRuleApplication++
+ if DEBUG_SIMPLIFY then console.log "simplify - tos: " + tos + " checking pattern: " + eachSimplification + " on: " + p1
+ push_symbol(NIL)
+ success = transform(eachSimplification, true)
+ if success
+ atLeastOneSuccessInRouldOfRulesApplications = true
+ p1 = stack[tos-1]
+ if DEBUG_SIMPLIFY then console.log "p1 at this stage of simplification: " + p1
+ if eachConsecutiveRuleApplication == MAX_CONSECUTIVE_APPLICATIONS_OF_SINGLE_RULE
+ stop("maximum application of single transformation rule exceeded: " + eachSimplification)
+
+ if numberOfRulesApplications == MAX_CONSECUTIVE_APPLICATIONS_OF_ALL_RULES
+ stop("maximum application of all transformation rules exceeded ")
+
+ if DEBUG_SIMPLIFY then console.log "METAX = " + get_binding(symbol(METAX))
+ if DEBUG_SIMPLIFY then console.log "METAA = " + get_binding(symbol(METAA))
+ if DEBUG_SIMPLIFY then console.log "METAB = " + get_binding(symbol(METAB))
+
+ # ------------------------
+
+simplifyForCodeGeneration = ->
+ save()
+ runUserDefinedSimplifications()
+ codeGen = true
+ # in "codeGen" mode we completely
+ # eval and simplify the function bodies
+ # because we really want to resolve all
+ # the variables indirections and apply
+ # all the simplifications we can.
+ simplify_main()
+ codeGen = false
+ restore()
+
+simplify = ->
+ save()
+ simplify_main()
+ restore()
+
+simplify_main = ->
+ p1 = pop()
+
+ # when we do code generation, we proceed to
+ # fully evaluate and simplify the body of
+ # a function, so we resolve all variables
+ # indirections and we simplify everything
+ # we can given the current assignments.
+ if codeGen and car(p1) == symbol(FUNCTION)
+ fbody = cadr(p1)
+ push fbody
+ # let's simplify the body so we give it a
+ # compact form
+ eval()
+ simplify()
+ p3 = pop()
+
+ # replace the evaled body
+ args = caddr(p1); # p5 is B
+
+ push_symbol(FUNCTION)
+ push p3
+ push args
+ list(3)
+ p1 = pop()
+
+ if (istensor(p1))
+ simplify_tensor()
+ return
+
+ if (Find(p1, symbol(FACTORIAL)))
+ push(p1)
+ simfac()
+ p2 = pop()
+ push(p1)
+ rationalize()
+ simfac()
+ p3 = pop()
+ if (count(p2) < count(p3))
+ p1 = p2
+ else
+ p1 = p3
+
+ f10()
+ if DEBUG_SIMPLIFY then console.log "f10: " + p1.toString()
+ f1()
+ if DEBUG_SIMPLIFY then console.log "f1: " + p1.toString()
+ f2()
+ if DEBUG_SIMPLIFY then console.log "f2: " + p1.toString()
+ f3()
+ if DEBUG_SIMPLIFY then console.log "f3: " + p1.toString()
+ f4()
+ if DEBUG_SIMPLIFY then console.log "f4: " + p1.toString()
+ f5()
+ if DEBUG_SIMPLIFY then console.log "f5: " + p1.toString()
+ f9()
+ if DEBUG_SIMPLIFY then console.log "f9: " + p1.toString()
+ simplify_polarRect()
+ if do_simplify_nested_radicals
+ # if there is some de-nesting then
+ # re-run a simplification because
+ # the shape of the expression might
+ # have changed significantly.
+ # e.g. simplify(14^(1/2) - (16 - 4*7^(1/2))^(1/2))
+ # needs some more semplification after the de-nesting.
+ if simplify_nested_radicals()
+ if DEBUG_SIMPLIFY then console.log("de-nesting successful into: " + p1.toString())
+ push(p1)
+ simplify()
+ return
+
+ simplify_rectToClock()
+ simplify_rational_expressions()
+
+ push(p1)
+
+simplify_tensor = ->
+ i = 0
+ p2 = alloc_tensor(p1.tensor.nelem)
+ p2.tensor.ndim = p1.tensor.ndim
+ for i in [0...p1.tensor.ndim]
+ p2.tensor.dim[i] = p1.tensor.dim[i]
+ for i in [0...p1.tensor.nelem]
+ push(p1.tensor.elem[i])
+ simplify()
+ p2.tensor.elem[i] = pop()
+
+ check_tensor_dimensions p2
+
+ if (isZeroAtomOrTensor(p2))
+ p2 = zero; # null tensor becomes scalar zero
+ push(p2)
+
+
+# try rationalizing
+
+f1 = ->
+ if (car(p1) != symbol(ADD))
+ return
+ push(p1)
+ rationalize()
+ p2 = pop()
+ if (count(p2) < count(p1))
+ p1 = p2
+
+# try condensing
+
+f2 = ->
+ if (car(p1) != symbol(ADD))
+ return
+ push(p1)
+ Condense()
+ p2 = pop()
+ if (count(p2) <= count(p1))
+ p1 = p2
+
+# this simplifies forms like (A-B) / (B-A)
+
+f3 = ->
+ push(p1)
+ rationalize()
+ negate()
+ rationalize()
+ negate()
+ rationalize()
+ p2 = pop()
+ if (count(p2) < count(p1))
+ p1 = p2
+
+
+f10 = ->
+
+ carp1 = car(p1)
+ miao = cdr(p1)
+ if ( carp1 == symbol(MULTIPLY) || isinnerordot(p1))
+ # both operands a transpose?
+
+ if (car(car(cdr(p1))) == symbol(TRANSPOSE)) and (car(car(cdr(cdr(p1)))) == symbol(TRANSPOSE))
+ if DEBUG_SIMPLIFY then console.log "maybe collecting a transpose " + p1
+ a = cadr(car(cdr(p1)))
+ b = cadr(car(cdr(cdr(p1))))
+ if carp1 == symbol(MULTIPLY)
+ push(a)
+ push(b)
+ multiply()
+ else if isinnerordot(p1)
+ push(b)
+ push(a)
+ inner()
+ push_integer(1)
+ push_integer(2)
+ originalexpanding = expanding
+ expanding = false
+ transpose()
+ expanding = originalexpanding
+
+ p2 = pop()
+ if (count(p2) < count(p1))
+ p1 = p2
+ if DEBUG_SIMPLIFY then console.log "collecting a transpose " + p2
+
+# try expanding denominators
+
+f4 = ->
+ if (isZeroAtomOrTensor(p1))
+ return
+ push(p1)
+ rationalize()
+ inverse()
+ rationalize()
+ inverse()
+ rationalize()
+ p2 = pop()
+ if (count(p2) < count(p1))
+ p1 = p2
+
+# simplifies trig forms
+
+simplify_trig = ->
+ save()
+ p1 = pop()
+ f5()
+ push(p1)
+ restore()
+
+f5 = ->
+ if (Find(p1, symbol(SIN)) == 0 && Find(p1, symbol(COS)) == 0)
+ return
+
+ p2 = p1
+
+ trigmode = 1
+ push(p2)
+ Eval()
+ p3 = pop()
+
+ trigmode = 2
+ push(p2)
+ Eval()
+ p4 = pop()
+
+ trigmode = 0
+
+ if (count(p4) < count(p3) || nterms(p4) < nterms(p3))
+ p3 = p4
+
+ if (count(p3) < count(p1) || nterms(p3) < nterms(p1))
+ p1 = p3
+
+# if it's a sum then try to simplify each term
+
+f9 = ->
+ if (car(p1) != symbol(ADD))
+ return
+ push_integer(0)
+ p2 = cdr(p1)
+ while (iscons(p2))
+ push(car(p2))
+ simplify()
+ add()
+
+ oldp1 = p1
+ oldp2 = p2
+ p1 = pop()
+ simplify_rational_expressions()
+ push(p1)
+ p1 = oldp1
+ p2 = oldp2
+
+ p2 = cdr(p2)
+ p2 = pop()
+ if (count(p2) < count(p1))
+ p1 = p2
+
+
+simplify_rational_expressions = ->
+ push p1
+ denominator()
+ denom = pop()
+
+ if isone(denom)
+ return
+
+ push p1
+ numerator()
+ num = pop()
+
+ if isone(num)
+ return
+
+ if !(polyVar = areunivarpolysfactoredorexpandedform(num, denom))
+ return
+
+ push num
+ push denom
+ gcd()
+
+ push(polyVar)
+ factor()
+
+ theGCD = pop()
+
+ # if there are no common factors then
+ # bail
+ if isone(theGCD)
+ return
+
+ push num
+ push(polyVar)
+ factor()
+ push theGCD
+ #divide()
+ inverse()
+ multiply_noexpand()
+ simplify()
+ sasa = stack[tos-1].toString()
+
+ push denom
+ push(polyVar)
+ factor()
+ push theGCD
+ #divide()
+ inverse()
+ multiply_noexpand()
+ simplify()
+ sasa = stack[tos-1].toString()
+
+ divide()
+ #simplify()
+ Condense()
+ sasa = stack[tos-1].toString()
+
+ p2 = pop()
+ if (count(p2) < count(p1))
+ p1 = p2
+
+
+# things like 6*(cos(2/9*pi)+i*sin(2/9*pi))
+# where we have sin and cos, those might start to
+# look better in clock form i.e. 6*(-1)^(2/9)
+simplify_rectToClock = ->
+ #debugger
+
+ if (Find(p1, symbol(SIN)) == 0 && Find(p1, symbol(COS)) == 0)
+ return
+
+ push(p1)
+ Eval()
+ clockform()
+
+ p2 = pop(); # put new (hopefully simplified expr) in p2
+ if DEBUG_SIMPLIFY then console.log "before simplification clockform: " + p1 + " after: " + p2
+
+ if (count(p2) < count(p1))
+ p1 = p2
+
+simplify_polarRect = ->
+ push(p1)
+
+ polarRectAMinusOneBase()
+ Eval()
+
+ p2 = pop(); # put new (hopefully simplified expr) in p2
+
+ if (count(p2) < count(p1))
+ p1 = p2
+
+polarRectAMinusOneBase = ->
+ save()
+ p1 = pop()
+
+ if isimaginaryunit(p1)
+ push(p1)
+ restore()
+ return
+
+ if (equal(car(p1), symbol(POWER)) and isminusone(cadr(p1)) )
+
+ # base we just said is minus 1
+ push(one)
+ negate()
+
+ # exponent
+ push(caddr(p1))
+ polarRectAMinusOneBase()
+
+ power()
+ # try to simplify it using polar and rect
+ polar()
+ rect()
+
+ else if (iscons(p1))
+ h = tos
+ while (iscons(p1))
+ #console.log("recursing on: " + car(p1).toString())
+ push(car(p1))
+ polarRectAMinusOneBase()
+ #console.log("...transformed into: " + stack[tos-1].toString())
+ p1 = cdr(p1)
+ list(tos - h)
+ else
+ push(p1)
+
+ restore()
+ return
+
+nterms = (p) ->
+ if (car(p) != symbol(ADD))
+ return 1
+ else
+ return length(p) - 1
+
+simplify_nested_radicals = ->
+ if recursionLevelNestedRadicalsRemoval > 0
+ if DEBUG_SIMPLIFY then console.log("denesting bailing out because of too much recursion")
+ return false
+
+ push(p1)
+ somethingSimplified = take_care_of_nested_radicals()
+
+
+ # in this paragraph we check whether we can collect
+ # common factors without complicating the expression
+ # in particular we want to avoid
+ # collecting radicals like in this case where
+ # we collect sqrt(2):
+ # 2-2^(1/2) into 2^(1/2)*(-1+2^(1/2))
+ # but we do like to collect other non-radicals e.g.
+ # 17/2+3/2*5^(1/2) into 1/2*(17+3*5^(1/2))
+ # so what we do is we count the powers and we check
+ # which version has the least number of them.
+ simplificationWithoutCondense = stack[tos-1]
+
+ prev_expanding = expanding
+ expanding = 0
+ yycondense()
+ expanding = prev_expanding
+
+ simplificationWithCondense = pop()
+ #console.log("occurrences of powers in " + simplificationWithoutCondense + " :" + countOccurrencesOfSymbol(symbol(POWER),simplificationWithoutCondense))
+ #console.log("occurrences of powers in " + simplificationWithCondense + " :" + countOccurrencesOfSymbol(symbol(POWER),simplificationWithCondense))
+
+ if (countOccurrencesOfSymbol(symbol(POWER),simplificationWithoutCondense) < countOccurrencesOfSymbol(symbol(POWER),simplificationWithCondense))
+ push(simplificationWithoutCondense)
+ else
+ push(simplificationWithCondense)
+
+
+ # we got out result, wrap up
+ p1 = pop()
+ return somethingSimplified
+
+take_care_of_nested_radicals = ->
+ if recursionLevelNestedRadicalsRemoval > 0
+ if DEBUG_SIMPLIFY then console.log("denesting bailing out because of too much recursion")
+ return false
+
+
+ save()
+ p1 = pop()
+ #console.log("take_care_of_nested_radicals p1: " + p1.toString())
+
+ if equal(car(p1), symbol(POWER))
+
+ #console.log("ok it's a power ")
+ base = cadr(p1)
+ exponent = caddr(p1)
+ #console.log("possible double radical base: " + base)
+ #console.log("possible double radical exponent: " + exponent)
+
+ if !isminusone(exponent) and equal(car(base), symbol(ADD)) and isfraction(exponent) and (equalq(exponent,1,3) or equalq(exponent,1,2))
+
+ #console.log("ok there is a radix with a term inside")
+ firstTerm = cadr(base)
+ push(firstTerm)
+ take_care_of_nested_radicals()
+ pop()
+ secondTerm = caddr(base)
+ push(secondTerm)
+ take_care_of_nested_radicals()
+ pop()
+
+ #console.log("possible double radical term1: " + firstTerm)
+ #console.log("possible double radical term2: " + secondTerm)
+
+ numberOfTerms = 0
+ countingTerms = base
+ while (cdr(countingTerms) != symbol(NIL))
+ numberOfTerms++
+ countingTerms = cdr(countingTerms)
+ #console.log("number of terms: " + numberOfTerms)
+ if numberOfTerms > 2
+ #console.log("too many terms under outer radix ")
+ push(p1)
+ restore()
+ return false
+
+
+ # list here all the factors
+ commonInnerExponent = null
+ commonBases = []
+ termsThatAreNotPowers = []
+ if (car(secondTerm) == symbol(MULTIPLY))
+ # product of factors
+ secondTermFactor = cdr(secondTerm)
+ if iscons(secondTermFactor)
+ while (iscons(secondTermFactor))
+ #console.log("second term factor BIS: " + car(secondTermFactor).toString())
+ potentialPower = car(secondTermFactor)
+ if (car(potentialPower) == symbol(POWER))
+ innerbase = cadr(potentialPower)
+ innerexponent = caddr(potentialPower)
+ if equalq(innerexponent,1,2)
+ #console.log("tackling double radical 1: " + p1.toString())
+ if !commonInnerExponent?
+ commonInnerExponent = innerexponent
+ commonBases.push(innerbase)
+ else
+ if equal(innerexponent, commonInnerExponent)
+ #console.log("common base: " + innerbase.toString())
+ commonBases.push(innerbase)
+ else
+ #console.log("no common bases here ")
+ #console.log("this one is a power base: " + innerbase + " , exponent: " + innerexponent)
+ else
+ termsThatAreNotPowers.push(potentialPower)
+ secondTermFactor = cdr(secondTermFactor)
+ else if (car(secondTerm) == symbol(POWER))
+ innerbase = cadr(secondTerm)
+ innerexponent = caddr(secondTerm)
+ if !commonInnerExponent? and equalq(innerexponent,1,2)
+ #console.log("tackling double radical 2: " + p1.toString())
+ commonInnerExponent = innerexponent
+ commonBases.push(innerbase)
+
+
+ if commonBases.length == 0
+ push(p1)
+ restore()
+ return false
+
+ A = firstTerm
+ #console.log("A: " + A.toString())
+
+ push_integer(1)
+ for i in commonBases
+ push(i)
+ multiply()
+ #console.log("basis with common exponent: " + i.toString())
+ C = pop()
+ #console.log("C: " + C.toString())
+
+ push_integer(1)
+ for i in termsThatAreNotPowers
+ push(i)
+ multiply()
+ #console.log("terms that are not powers: " + i.toString())
+ B = pop()
+ #console.log("B: " + B.toString())
+
+
+ if equalq(exponent,1,3)
+ push(A)
+ negate()
+ push(C)
+ multiply()
+ push(B)
+ divide() # 4th coeff
+ #console.log("constant coeff " + stack[tos-1].toString())
+ checkSize = pop()
+ push(checkSize)
+ real()
+ yyfloat()
+ if Math.abs(pop().d) > Math.pow(2, 32)
+ push(p1)
+ restore()
+ return false
+ push(checkSize)
+
+ push_integer(3)
+ push(C)
+ multiply() # 3rd coeff
+ #console.log("next coeff " + stack[tos-1].toString())
+ checkSize = pop()
+ push(checkSize)
+ real()
+ yyfloat()
+ if Math.abs(pop().d) > Math.pow(2, 32)
+ pop()
+ push(p1)
+ restore()
+ return false
+ push(checkSize)
+
+ push(symbol(SECRETX))
+ multiply()
+
+
+ push_integer(-3)
+ push(A)
+ multiply()
+ push(B)
+ divide() # 2nd coeff
+ checkSize = pop()
+ push(checkSize)
+ real()
+ yyfloat()
+ if Math.abs(pop().d) > Math.pow(2, 32)
+ pop()
+ pop()
+ push(p1)
+ restore()
+ return false
+ push(checkSize)
+
+ #console.log("next coeff " + stack[tos-1].toString())
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+ multiply()
+
+ push_integer(1) # 1st coeff
+ #console.log("next coeff " + stack[tos-1].toString())
+ push(symbol(SECRETX))
+ push_integer(3)
+ power()
+ multiply()
+
+ add()
+ add()
+ add()
+
+ else if equalq(exponent,1,2)
+ push(C) # 3th coeff
+ checkSize = pop()
+ push(checkSize)
+ real()
+ yyfloat()
+ if Math.abs(pop().d) > Math.pow(2, 32)
+ push(p1)
+ restore()
+ return false
+ push(checkSize)
+ #console.log("constant coeff " + stack[tos-1].toString())
+
+ push_integer(-2)
+ push(A)
+ multiply()
+ push(B)
+ divide() # 2nd coeff
+ checkSize = pop()
+ push(checkSize)
+ real()
+ yyfloat()
+ if Math.abs(pop().d) > Math.pow(2, 32)
+ pop()
+ push(p1)
+ restore()
+ return false
+ push(checkSize)
+
+ #console.log("next coeff " + stack[tos-1].toString())
+ push(symbol(SECRETX))
+ multiply()
+
+
+ push_integer(1) # 1st coeff
+ #console.log("next coeff " + stack[tos-1].toString())
+ push(symbol(SECRETX))
+ push_integer(2)
+ power()
+ multiply()
+
+ add()
+ add()
+
+ #console.log("whole polynomial: " + stack[tos-1].toString())
+
+ push(symbol(SECRETX))
+
+
+ recursionLevelNestedRadicalsRemoval++
+ #console.log("invoking roots at recursion level: " + recursionLevelNestedRadicalsRemoval)
+ roots()
+ recursionLevelNestedRadicalsRemoval--
+ if equal(stack[tos-1], symbol(NIL))
+ if DEBUG_SIMPLIFY then console.log("roots bailed out because of too much recursion")
+ pop()
+ push(p1)
+ restore()
+ return false
+
+ #console.log("all solutions: " + stack[tos-1].toString())
+
+ # exclude the solutions with radicals
+ possibleSolutions = []
+ for eachSolution in stack[tos-1].tensor.elem
+ if !Find(eachSolution, symbol(POWER))
+ possibleSolutions.push(eachSolution)
+
+ pop() # popping the tensor with the solutions
+
+ #console.log("possible solutions: " + possibleSolutions.toString())
+ if possibleSolutions.length == 0
+ push(p1)
+ restore()
+ return false
+
+ possibleRationalSolutions = []
+ realOfpossibleRationalSolutions = []
+ #console.log("checking the one with maximum real part ")
+ for i in possibleSolutions
+ push(i)
+ real()
+ yyfloat()
+ possibleRationalSolutions.push(i)
+ realOfpossibleRationalSolutions.push(pop().d)
+
+ whichRationalSolution = realOfpossibleRationalSolutions.indexOf(Math.max.apply(Math, realOfpossibleRationalSolutions))
+ SOLUTION = possibleRationalSolutions[whichRationalSolution]
+ #console.log("picked solution: " + SOLUTION)
+
+
+ ###
+ #possibleNewExpressions = []
+ #realOfPossibleNewExpressions = []
+ # pick the solution which cubic root has no radicals
+ lowercase_b = null
+ for SOLUTION in possibleSolutions
+ console.log("testing solution: " + SOLUTION.toString())
+
+ debugger
+ if equalq(exponent,1,3)
+ push(A)
+ push(SOLUTION)
+ push_integer(3)
+ power()
+ push_integer(3)
+ push(C)
+ multiply()
+ push(SOLUTION)
+ multiply()
+ add()
+ divide()
+ console.log("argument of cubic root: " + stack[tos-1].toString())
+ push_rational(1,3)
+ power()
+ else if equalq(exponent,1,2)
+ push(A)
+ push(SOLUTION)
+ push_integer(2)
+ power()
+ push(C)
+ add()
+ divide()
+ console.log("argument of cubic root: " + stack[tos-1].toString())
+ push_rational(1,2)
+ power()
+ console.log("b is: " + stack[tos-1].toString())
+
+ lowercase_b = pop()
+
+ if !Find(lowercase_b, symbol(POWER))
+ break
+ ###
+
+ if equalq(exponent,1,3)
+ push(A)
+ push(SOLUTION)
+ push_integer(3)
+ power()
+ push_integer(3)
+ push(C)
+ multiply()
+ push(SOLUTION)
+ multiply()
+ add()
+ divide()
+ #console.log("argument of cubic root: " + stack[tos-1].toString())
+ push_rational(1,3)
+ power()
+ else if equalq(exponent,1,2)
+ push(A)
+ push(SOLUTION)
+ push_integer(2)
+ power()
+ push(C)
+ add()
+ divide()
+ #console.log("argument of cubic root: " + stack[tos-1].toString())
+ push_rational(1,2)
+ power()
+ #console.log("b is: " + stack[tos-1].toString())
+
+ lowercase_b = pop()
+
+
+ if !lowercase_b?
+ push(p1)
+ restore()
+ return false
+
+ push(lowercase_b)
+ push(SOLUTION)
+ multiply()
+
+
+ if equalq(exponent,1,3)
+ #console.log("a is: " + stack[tos-1].toString())
+
+ lowercase_a = pop()
+
+ push(lowercase_b)
+ push(C)
+ push_rational(1,2)
+ power()
+ multiply()
+
+ push(lowercase_a)
+ add()
+ simplify()
+ else if equalq(exponent,1,2)
+ #console.log("a could be: " + stack[tos-1].toString())
+
+ lowercase_a = pop()
+
+ push(lowercase_b)
+ push(C)
+ push_rational(1,2)
+ power()
+ multiply()
+
+ push(lowercase_a)
+ add()
+ simplify()
+ possibleNewExpression = pop()
+ #console.log("verifying if " + possibleNewExpression + " is positive")
+ push(possibleNewExpression)
+ real()
+ yyfloat()
+ possibleNewExpressionValue = pop()
+ if !isnegativenumber(possibleNewExpressionValue)
+ #console.log("... it is positive")
+ push(possibleNewExpression)
+ else
+ #console.log("... it is NOT positive")
+ push(lowercase_b)
+ negate()
+ lowercase_b = pop()
+
+ push(lowercase_a)
+ negate()
+ lowercase_a = pop()
+
+
+ push(lowercase_b)
+ push(C)
+ push_rational(1,2)
+ power()
+ multiply()
+
+ push(lowercase_a)
+ add()
+ simplify()
+ # possibleNewExpression is now at top of stack
+
+
+ #console.log("potential new expression: " + stack[tos-1].toString())
+ p1 = pop()
+ #newExpression = pop()
+ #debugger
+ #push(newExpression)
+ #real()
+ #yyfloat()
+ #possibleNewExpressions.push(newExpression)
+ #realOfPossibleNewExpressions.push(pop().d)
+
+ #whichExpression = realOfPossibleNewExpressions.indexOf(Math.max.apply(Math, realOfPossibleNewExpressions))
+ #p1 = possibleNewExpressions[whichExpression]
+ #console.log("final new expression: " + p1.toString())
+
+ push(p1)
+ restore()
+ return true
+
+
+
+ else
+ push(p1)
+ restore()
+ return false
+
+ else if (iscons(p1))
+ h = tos
+ anyRadicalSimplificationWorked = false
+ while (iscons(p1))
+ #console.log("recursing on: " + car(p1).toString())
+ push(car(p1))
+ anyRadicalSimplificationWorked = anyRadicalSimplificationWorked or take_care_of_nested_radicals()
+ #console.log("...transformed into: " + stack[tos-1].toString())
+ p1 = cdr(p1)
+ list(tos - h)
+ restore()
+ return anyRadicalSimplificationWorked
+ else
+ push(p1)
+ restore()
+ return false
+
+ throw new Error("control flow should never reach here")
diff --git a/node_modules/algebrite/sources/sin.coffee b/node_modules/algebrite/sources/sin.coffee
new file mode 100644
index 0000000..50b2867
--- /dev/null
+++ b/node_modules/algebrite/sources/sin.coffee
@@ -0,0 +1,170 @@
+# Sine function of numerical and symbolic arguments
+
+
+
+Eval_sin = ->
+ #console.log "sin ---- "
+ push(cadr(p1))
+ Eval()
+ sine()
+ #console.log "sin end ---- "
+
+sine = ->
+ #console.log "sine ---- "
+ save()
+ p1 = pop()
+ if (car(p1) == symbol(ADD))
+ # sin of a sum can be further decomposed into
+ #sin(alpha+beta) = sin(alpha)*cos(beta)+sin(beta)*cos(alpha)
+ sine_of_angle_sum()
+ else
+ sine_of_angle()
+ restore()
+ #console.log "sine end ---- "
+
+# Use angle sum formula for special angles.
+
+#define A p3
+#define B p4
+
+# decompose sum sin(alpha+beta) into
+# sin(alpha)*cos(beta)+sin(beta)*cos(alpha)
+sine_of_angle_sum = ->
+ #console.log "sin of angle sum ---- "
+ p2 = cdr(p1)
+ while (iscons(p2))
+ p4 = car(p2); # p4 is B
+ if (isnpi(p4)) # p4 is B
+ push(p1)
+ push(p4); # p4 is B
+ subtract()
+ p3 = pop(); # p3 is A
+ push(p3); # p3 is A
+ sine()
+ push(p4); # p4 is B
+ cosine()
+ multiply()
+ push(p3); # p3 is A
+ cosine()
+ push(p4); # p4 is B
+ sine()
+ multiply()
+ add()
+ #console.log "sin of angle sum end ---- "
+ return
+ p2 = cdr(p2)
+ sine_of_angle()
+ #console.log "sin of angle sum end ---- "
+
+sine_of_angle = ->
+
+ if (car(p1) == symbol(ARCSIN))
+ push(cadr(p1))
+ return
+
+ if isdouble(p1)
+ d = Math.sin(p1.d)
+ if (Math.abs(d) < 1e-10)
+ d = 0.0
+ push_double(d)
+ return
+
+ # sine function is antisymmetric, sin(-x) = -sin(x)
+
+ if (isnegative(p1))
+ push(p1)
+ negate()
+ sine()
+ negate()
+ return
+
+ # sin(arctan(x)) = x / sqrt(1 + x^2)
+
+ # see p. 173 of the CRC Handbook of Mathematical Sciences
+
+ if (car(p1) == symbol(ARCTAN))
+ push(cadr(p1))
+ push_integer(1)
+ push(cadr(p1))
+ push_integer(2)
+ power()
+ add()
+ push_rational(-1, 2)
+ power()
+ multiply()
+ return
+
+ # multiply by 180/pi to go from radians to degrees.
+ # we go from radians to degrees because it's much
+ # easier to calculate symbolic results of most (not all) "classic"
+ # angles (e.g. 30,45,60...) if we calculate the degrees
+ # and the we do a switch on that.
+ # Alternatively, we could look at the fraction of pi
+ # (e.g. 60 degrees is 1/3 pi) but that's more
+ # convoluted as we'd need to look at both numerator and
+ # denominator.
+
+ push(p1)
+ push_integer(180)
+ multiply()
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ divide()
+
+ n = pop_integer()
+
+ # most "good" (i.e. compact) trigonometric results
+ # happen for a round number of degrees. There are some exceptions
+ # though, e.g. 22.5 degrees, which we don't capture here.
+ if (n < 0 || isNaN(n))
+ push(symbol(SIN))
+ push(p1)
+ list(2)
+ return
+
+ # values of some famous angles. Many more here:
+ # https://en.wikipedia.org/wiki/Trigonometric_constants_expressed_in_real_radicals
+
+ switch (n % 360)
+ when 0, 180
+ push_integer(0)
+ when 30, 150
+ push_rational(1, 2)
+ when 210, 330
+ push_rational(-1, 2)
+ when 45, 135
+ push_rational(1, 2)
+ push_integer(2)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 225, 315
+ push_rational(-1, 2)
+ push_integer(2)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 60, 120
+ push_rational(1, 2)
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 240, 300
+ push_rational(-1, 2)
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 90
+ push_integer(1)
+ when 270
+ push_integer(-1)
+ else
+ push(symbol(SIN))
+ push(p1)
+ list(2)
+
+
diff --git a/node_modules/algebrite/sources/sinh.coffee b/node_modules/algebrite/sources/sinh.coffee
new file mode 100644
index 0000000..c64d7a6
--- /dev/null
+++ b/node_modules/algebrite/sources/sinh.coffee
@@ -0,0 +1,36 @@
+# exp(x) - exp(-x)
+# sinh(x) = ----------------
+# 2
+
+
+
+Eval_sinh = ->
+ push(cadr(p1))
+ Eval()
+ ysinh()
+
+ysinh = ->
+ save()
+ yysinh()
+ restore()
+
+yysinh = ->
+ d = 0.0
+ p1 = pop()
+ if (car(p1) == symbol(ARCSINH))
+ push(cadr(p1))
+ return
+ if (isdouble(p1))
+ d = Math.sinh(p1.d)
+ if (Math.abs(d) < 1e-10)
+ d = 0.0
+ push_double(d)
+ return
+ if (isZeroAtomOrTensor(p1))
+ push(zero)
+ return
+ push_symbol(SINH)
+ push(p1)
+ list(2)
+
+
diff --git a/node_modules/algebrite/sources/subst.coffee b/node_modules/algebrite/sources/subst.coffee
new file mode 100644
index 0000000..b95419c
--- /dev/null
+++ b/node_modules/algebrite/sources/subst.coffee
@@ -0,0 +1,52 @@
+###
+ Substitute new expr for old expr in expr.
+
+ Input: push expr
+
+ push old expr
+
+ push new expr
+
+ Output: Result on stack
+###
+
+
+
+subst = ->
+ save()
+ newExpr = pop(); # new expr
+ oldExpr = pop(); # old expr
+ if (oldExpr == symbol(NIL) || newExpr == symbol(NIL))
+ restore()
+ return
+ expr = pop(); # expr
+ if (istensor(expr))
+ newTensor = alloc_tensor(expr.tensor.nelem)
+ newTensor.tensor.ndim = expr.tensor.ndim
+ for i in [0...expr.tensor.ndim]
+ newTensor.tensor.dim[i] = expr.tensor.dim[i]
+ for i in [0...expr.tensor.nelem]
+ push(expr.tensor.elem[i])
+ push(oldExpr)
+ push(newExpr)
+ subst()
+ newTensor.tensor.elem[i] = pop()
+
+ check_tensor_dimensions newTensor
+
+ push(newTensor)
+ else if (equal(expr, oldExpr))
+ push(newExpr)
+ else if (iscons(expr))
+ push(car(expr))
+ push(oldExpr)
+ push(newExpr)
+ subst()
+ push(cdr(expr))
+ push(oldExpr)
+ push(newExpr)
+ subst()
+ cons()
+ else
+ push(expr)
+ restore()
diff --git a/node_modules/algebrite/sources/sum.coffee b/node_modules/algebrite/sources/sum.coffee
new file mode 100644
index 0000000..259b759
--- /dev/null
+++ b/node_modules/algebrite/sources/sum.coffee
@@ -0,0 +1,56 @@
+# 'sum' function
+
+#define A p3
+#define B p4
+#define I p5
+#define X p6
+
+# leaves the sum at the top of the stack
+
+Eval_sum = ->
+ i = 0
+ j = 0
+ k = 0
+
+
+ # 1st arg
+ body = cadr(p1)
+
+ # 2nd arg (index)
+ indexVariable = caddr(p1)
+ if (!issymbol(indexVariable))
+ stop("sum: 2nd arg?")
+
+ # 3rd arg (lower limit)
+ push(cadddr(p1))
+ Eval()
+ j = pop_integer()
+ if (isNaN(j))
+ push p1
+ return
+
+ # 4th arg (upper limit)
+ push(caddddr(p1))
+ Eval()
+ k = pop_integer()
+ if (isNaN(k))
+ push p1
+ return
+
+
+ # remember contents of the index
+ # variable so we can put it back after the loop
+ p4 = get_binding(indexVariable)
+
+ push_integer(0)
+
+ for i in [j..k]
+ push_integer(i)
+ p5 = pop()
+ set_binding(indexVariable, p5)
+ push(body)
+ Eval()
+ add()
+
+ # put back the index variable to original content
+ set_binding(indexVariable, p4)
diff --git a/node_modules/algebrite/sources/tan.coffee b/node_modules/algebrite/sources/tan.coffee
new file mode 100644
index 0000000..7544f87
--- /dev/null
+++ b/node_modules/algebrite/sources/tan.coffee
@@ -0,0 +1,104 @@
+# Tangent function of numerical and symbolic arguments
+
+
+
+Eval_tan = ->
+ push(cadr(p1))
+ Eval()
+ tangent()
+
+tangent = ->
+ save()
+ yytangent()
+ restore()
+
+yytangent = ->
+ n = 0
+ d = 0.0
+
+ p1 = pop()
+
+ if (car(p1) == symbol(ARCTAN))
+ push(cadr(p1))
+ return
+
+ if (isdouble(p1))
+ d = Math.tan(p1.d)
+ if (Math.abs(d) < 1e-10)
+ d = 0.0
+ push_double(d)
+ return
+
+ # tan function is antisymmetric, tan(-x) = -tan(x)
+
+ if (isnegative(p1))
+ push(p1)
+ negate()
+ tangent()
+ negate()
+ return
+
+ # multiply by 180/pi to go from radians to degrees.
+ # we go from radians to degrees because it's much
+ # easier to calculate symbolic results of most (not all) "classic"
+ # angles (e.g. 30,45,60...) if we calculate the degrees
+ # and the we do a switch on that.
+ # Alternatively, we could look at the fraction of pi
+ # (e.g. 60 degrees is 1/3 pi) but that's more
+ # convoluted as we'd need to look at both numerator and
+ # denominator.
+
+ push(p1)
+ push_integer(180)
+ multiply()
+ if evaluatingAsFloats
+ push_double(Math.PI)
+ else
+ push_symbol(PI)
+ divide()
+
+ n = pop_integer()
+
+ # most "good" (i.e. compact) trigonometric results
+ # happen for a round number of degrees. There are some exceptions
+ # though, e.g. 22.5 degrees, which we don't capture here.
+ if (n < 0 || isNaN(n))
+ push(symbol(TAN))
+ push(p1)
+ list(2)
+ return
+
+ switch (n % 360)
+ when 0, 180
+ push_integer(0)
+ when 30, 210
+ push_rational(1, 3)
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 150, 330
+ push_rational(-1, 3)
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ multiply()
+ when 45, 225
+ push_integer(1)
+ when 135, 315
+ push_integer(-1)
+ when 60, 240
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ when 120, 300
+ push_integer(3)
+ push_rational(1, 2)
+ power()
+ negate()
+ else
+ push(symbol(TAN))
+ push(p1)
+ list(2)
+
+
diff --git a/node_modules/algebrite/sources/tanh.coffee b/node_modules/algebrite/sources/tanh.coffee
new file mode 100644
index 0000000..0758e24
--- /dev/null
+++ b/node_modules/algebrite/sources/tanh.coffee
@@ -0,0 +1,27 @@
+# exp(2 x) - 1
+# tanh(x) = --------------
+# exp(2 x) + 1
+
+
+
+Eval_tanh = ->
+ d = 0.0
+ push(cadr(p1))
+ Eval()
+ p1 = pop()
+ if (car(p1) == symbol(ARCTANH))
+ push(cadr(p1))
+ return
+ if (isdouble(p1))
+ d = Math.tanh(p1.d)
+ if (Math.abs(d) < 1e-10)
+ d = 0.0
+ push_double(d)
+ return
+ if (isZeroAtomOrTensor(p1))
+ push(zero)
+ return
+ push_symbol(TANH)
+ push(p1)
+ list(2)
+
diff --git a/node_modules/algebrite/sources/taylor.coffee b/node_modules/algebrite/sources/taylor.coffee
new file mode 100644
index 0000000..cfbcc55
--- /dev/null
+++ b/node_modules/algebrite/sources/taylor.coffee
@@ -0,0 +1,126 @@
+###
+Taylor expansion of a function
+
+ push(F)
+ push(X)
+ push(N)
+ push(A)
+ taylor()
+###
+
+
+
+Eval_taylor = ->
+ # 1st arg
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+
+ # 2nd arg
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ guess()
+ else
+ push(p2)
+
+ # 3rd arg
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ push_integer(24); # default number of terms
+ else
+ push(p2)
+
+ # 4th arg
+
+ p1 = cdr(p1)
+ push(car(p1))
+ Eval()
+ p2 = pop()
+ if (p2 == symbol(NIL))
+ push_integer(0); # default expansion point
+ else
+ push(p2)
+
+ taylor()
+
+#define F p1
+#define X p2
+#define N p3
+#define A p4
+#define C p5
+
+taylor = ->
+ i = 0
+ k = 0
+
+ save()
+
+ p4 = pop()
+ p3 = pop()
+ p2 = pop()
+ p1 = pop()
+
+ push(p3)
+ k = pop_integer()
+ if (isNaN(k))
+ push_symbol(TAYLOR)
+ push(p1)
+ push(p2)
+ push(p3)
+ push(p4)
+ list(5)
+ restore()
+ return
+
+ push(p1); # f(a)
+ push(p2)
+ push(p4)
+ subst()
+ Eval()
+
+ push_integer(1)
+ p5 = pop()
+
+ for i in [1..k]
+
+ push(p1); # f = f'
+ push(p2)
+ derivative()
+ p1 = pop()
+
+ if (isZeroAtomOrTensor(p1))
+ break
+
+ push(p5); # c = c * (x - a)
+ push(p2)
+ push(p4)
+ subtract()
+ multiply()
+ p5 = pop()
+
+ push(p1); # f(a)
+ push(p2)
+ push(p4)
+ subst()
+ Eval()
+
+ push(p5)
+ multiply()
+ push_integer(i)
+ factorial()
+ divide()
+
+ add()
+
+ restore()
+
+
diff --git a/node_modules/algebrite/sources/tensor.coffee b/node_modules/algebrite/sources/tensor.coffee
new file mode 100644
index 0000000..58fb738
--- /dev/null
+++ b/node_modules/algebrite/sources/tensor.coffee
@@ -0,0 +1,556 @@
+#(docs are generated from top-level comments, keep an eye on the formatting!)
+
+### tensor =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+General description
+-------------------
+Tensors are a strange in-between of matrices and "computer"
+rectangular data structures.
+
+Tensors, unlike matrices, and like rectangular data structures,
+can have an arbitrary number of dimensions (rank), although a tensor with
+rank zero is just a scalar.
+
+Tensors, like matrices and unlike many computer rectangular data structures,
+must be "contiguous" i.e. have no empty spaces within its size, and "uniform",
+i.e. each element must have the same shape and hence the same rank.
+
+Also tensors have necessarily to make a distinction between row vectors,
+column vectors (which have a rank of 2) and uni-dimensional vectors (rank 1).
+They look very similar but they are fundamentally different.
+
+Tensors are 1-indexed, as per general math notation, and like Fortran,
+Lua, Mathematica, SASL, MATLAB, Julia, Erlang and APL.
+
+Tensors with elements that are also tensors get promoted to a higher rank
+, this is so we can represent and get the rank of a matrix correctly.
+Example:
+Start with a tensor of rank 1 with 2 elements (i.e. shape: 2)
+if you put in both its elements another 2 tensors
+of rank 1 with 2 elements (i.e. shape: 2)
+then the result is a tensor of rank 2 with shape 2,2
+i.e. the dimension of a tensor at all times must be
+the number of nested tensors in it.
+Also, all tensors must be "uniform" i.e. they must be accessed
+uniformly, which means that all existing elements of a tensor
+must be contiguous and have the same shape.
+Implication of it all is that you can't put arbitrary
+tensors inside tensors (like you would do to represent block matrices)
+Rather, all tensors inside tensors must have same shape (and hence, rank)
+
+Limitations
+-----------
+n.a.
+
+Implementation info
+-------------------
+Tensors are implemented...
+
+###
+
+# Called from the "eval" module to evaluate tensor elements.
+# p1 points to the tensor operand.
+Eval_tensor = ->
+ i = 0
+ ndim = 0
+ nelem = 0
+ #U **a, **b
+
+ #---------------------------------------------------------------------
+ #
+ # create a new tensor for the result
+ #
+ #---------------------------------------------------------------------
+
+ check_tensor_dimensions p1
+
+ nelem = p1.tensor.nelem
+
+ ndim = p1.tensor.ndim
+
+ p2 = alloc_tensor(nelem)
+
+ p2.tensor.ndim = ndim
+
+ for i in [0...ndim]
+ p2.tensor.dim[i] = p1.tensor.dim[i]
+
+ #---------------------------------------------------------------------
+ #
+ # b = Eval(a)
+ #
+ #---------------------------------------------------------------------
+
+ a = p1.tensor.elem
+ b = p2.tensor.elem
+
+ check_tensor_dimensions p2
+
+ for i in [0...nelem]
+ #console.log "push/pop: pushing element a of " + i
+ push(a[i])
+ Eval()
+ #console.log "push/pop: popping into element b of " + i
+ b[i] = pop()
+
+ check_tensor_dimensions p1
+ check_tensor_dimensions p2
+ #---------------------------------------------------------------------
+ #
+ # push the result
+ #
+ #---------------------------------------------------------------------
+
+ push(p2)
+
+ promote_tensor()
+
+#-----------------------------------------------------------------------------
+#
+# Add tensors
+#
+# Input: Operands on stack
+#
+# Output: Result on stack
+#
+#-----------------------------------------------------------------------------
+
+tensor_plus_tensor = ->
+ i = 0
+ ndim = 0
+ nelem = 0
+ #U **a, **b, **c
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ # are the dimension lists equal?
+
+ ndim = p1.tensor.ndim
+
+ if (ndim != p2.tensor.ndim)
+ push(symbol(NIL))
+ restore()
+ return
+
+ for i in [0...ndim]
+ if (p1.tensor.dim[i] != p2.tensor.dim[i])
+ push(symbol(NIL))
+ restore()
+ return
+
+ # create a new tensor for the result
+
+ nelem = p1.tensor.nelem
+
+ p3 = alloc_tensor(nelem)
+
+ p3.tensor.ndim = ndim
+
+ for i in [0...ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+
+ # c = a + b
+
+ a = p1.tensor.elem
+ b = p2.tensor.elem
+ c = p3.tensor.elem
+
+ for i in [0...nelem]
+ push(a[i])
+ push(b[i])
+ add()
+ c[i] = pop()
+
+ # push the result
+
+ push(p3)
+
+ restore()
+
+#-----------------------------------------------------------------------------
+#
+# careful not to reorder factors
+#
+#-----------------------------------------------------------------------------
+
+tensor_times_scalar = ->
+ i = 0
+ ndim = 0
+ nelem = 0
+ #U **a, **b
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ ndim = p1.tensor.ndim
+ nelem = p1.tensor.nelem
+
+ p3 = alloc_tensor(nelem)
+
+ p3.tensor.ndim = ndim
+
+ for i in [0...ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+
+ a = p1.tensor.elem
+ b = p3.tensor.elem
+
+ for i in [0...nelem]
+ push(a[i])
+ push(p2)
+ multiply()
+ b[i] = pop()
+
+ push(p3)
+ restore()
+
+scalar_times_tensor = ->
+ i = 0
+ ndim = 0
+ nelem = 0
+ #U **a, **b
+
+ save()
+
+ p2 = pop()
+ p1 = pop()
+
+ ndim = p2.tensor.ndim
+ nelem = p2.tensor.nelem
+
+ p3 = alloc_tensor(nelem)
+
+ p3.tensor.ndim = ndim
+
+ for i in [0...ndim]
+ p3.tensor.dim[i] = p2.tensor.dim[i]
+
+ a = p2.tensor.elem
+ b = p3.tensor.elem
+
+ for i in [0...nelem]
+ push(p1)
+ push(a[i])
+ multiply()
+ b[i] = pop()
+
+ push(p3)
+
+ restore()
+
+check_tensor_dimensions = (p) ->
+ if p.tensor.nelem != p.tensor.elem.length
+ console.log "something wrong in tensor dimensions"
+ debugger
+
+is_square_matrix = (p) ->
+ if (istensor(p) && p.tensor.ndim == 2 && p.tensor.dim[0] == p.tensor.dim[1])
+ return 1
+ else
+ return 0
+
+#-----------------------------------------------------------------------------
+#
+# gradient of tensor
+#
+#-----------------------------------------------------------------------------
+
+d_tensor_tensor = ->
+ i = 0
+ j = 0
+ ndim = 0
+ nelem = 0
+ #U **a, **b, **c
+
+ ndim = p1.tensor.ndim
+ nelem = p1.tensor.nelem
+
+ if (ndim + 1 >= MAXDIM)
+ push_symbol(DERIVATIVE)
+ push(p1)
+ push(p2)
+ list(3)
+ return
+
+ p3 = alloc_tensor(nelem * p2.tensor.nelem)
+
+ p3.tensor.ndim = ndim + 1
+
+ for i in [0...ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+
+ p3.tensor.dim[ndim] = p2.tensor.dim[0]
+
+ a = p1.tensor.elem
+ b = p2.tensor.elem
+ c = p3.tensor.elem
+
+ for i in [0...nelem]
+ for j in [0...p2.tensor.nelem]
+ push(a[i])
+ push(b[j])
+ derivative()
+ c[i * p2.tensor.nelem + j] = pop()
+
+ push(p3)
+
+
+#-----------------------------------------------------------------------------
+#
+# gradient of scalar
+#
+#-----------------------------------------------------------------------------
+
+d_scalar_tensor = ->
+ #U **a, **b
+
+ p3 = alloc_tensor(p2.tensor.nelem)
+
+ p3.tensor.ndim = 1
+
+ p3.tensor.dim[0] = p2.tensor.dim[0]
+
+ a = p2.tensor.elem
+ b = p3.tensor.elem
+
+ for i in [0...p2.tensor.nelem]
+ push(p1)
+ push(a[i])
+ derivative()
+ b[i] = pop()
+
+ push(p3)
+
+#-----------------------------------------------------------------------------
+#
+# Derivative of tensor
+#
+#-----------------------------------------------------------------------------
+
+d_tensor_scalar = ->
+ i = 0
+ #U **a, **b
+
+ p3 = alloc_tensor(p1.tensor.nelem)
+
+ p3.tensor.ndim = p1.tensor.ndim
+
+ for i in [0...p1.tensor.ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+
+ a = p1.tensor.elem
+ b = p3.tensor.elem
+
+ for i in [0...p1.tensor.nelem]
+ push(a[i])
+ push(p2)
+ derivative()
+ b[i] = pop()
+
+ push(p3)
+
+compare_tensors = (p1, p2) ->
+
+ i = 0
+ if (p1.tensor.ndim < p2.tensor.ndim)
+ return -1
+
+ if (p1.tensor.ndim > p2.tensor.ndim)
+ return 1
+
+ for i in [0...p1.tensor.ndim]
+ if (p1.tensor.dim[i] < p2.tensor.dim[i])
+ return -1
+ if (p1.tensor.dim[i] > p2.tensor.dim[i])
+ return 1
+
+ for i in [0...p1.tensor.nelem]
+ if (equal(p1.tensor.elem[i], p2.tensor.elem[i]))
+ continue
+ if (lessp(p1.tensor.elem[i], p2.tensor.elem[i]))
+ return -1
+ else
+ return 1
+
+ return 0
+
+#-----------------------------------------------------------------------------
+#
+# Raise a tensor to a power
+#
+# Input: p1 tensor
+#
+# p2 exponent
+#
+# Output: Result on stack
+#
+#-----------------------------------------------------------------------------
+
+power_tensor = ->
+ i = 0
+ k = 0
+ n = 0
+
+ # first and last dims must be equal
+
+ k = p1.tensor.ndim - 1
+
+ if (p1.tensor.dim[0] != p1.tensor.dim[k])
+ push_symbol(POWER)
+ push(p1)
+ push(p2)
+ list(3)
+ return
+
+ push(p2)
+
+ n = pop_integer()
+
+ if (isNaN(n))
+ push_symbol(POWER)
+ push(p1)
+ push(p2)
+ list(3)
+ return
+
+ if (n == 0)
+ if (p1.tensor.ndim != 2)
+ stop("power(tensor,0) with tensor rank not equal to 2")
+ n = p1.tensor.dim[0]
+ p1 = alloc_tensor(n * n)
+ p1.tensor.ndim = 2
+ p1.tensor.dim[0] = n
+ p1.tensor.dim[1] = n
+ for i in [0...n]
+ p1.tensor.elem[n * i + i] = one
+
+ check_tensor_dimensions p1
+
+ push(p1)
+ return
+
+ if (n < 0)
+ n = -n
+ push(p1)
+ inv()
+ p1 = pop()
+
+ push(p1)
+
+ for i in [1...n]
+ push(p1)
+ inner()
+ if (isZeroAtomOrTensor(stack[tos - 1]))
+ break
+
+copy_tensor = ->
+ i = 0
+
+ save()
+
+ p1 = pop()
+
+ p2 = alloc_tensor(p1.tensor.nelem)
+
+ p2.tensor.ndim = p1.tensor.ndim
+
+ for i in [0...p1.tensor.ndim]
+ p2.tensor.dim[i] = p1.tensor.dim[i]
+
+ for i in [0...p1.tensor.nelem]
+ p2.tensor.elem[i] = p1.tensor.elem[i]
+
+ check_tensor_dimensions p1
+ check_tensor_dimensions p2
+
+ push(p2)
+
+ restore()
+
+# Tensors with elements that are also tensors get promoted to a higher rank.
+
+promote_tensor = ->
+ i = 0
+ j = 0
+ k = 0
+ nelem = 0
+ ndim = 0
+
+ save()
+
+ p1 = pop()
+
+ if (!istensor(p1))
+ push(p1)
+ restore()
+ return
+
+ p2 = p1.tensor.elem[0]
+
+ for i in [1...p1.tensor.nelem]
+ if (!compatible(p2, p1.tensor.elem[i]))
+ stop("Cannot promote tensor due to inconsistent tensor components.")
+
+ if (!istensor(p2))
+ push(p1)
+ restore()
+ return
+
+ ndim = p1.tensor.ndim + p2.tensor.ndim
+
+ if (ndim > MAXDIM)
+ stop("tensor rank > " + MAXDIM)
+
+ nelem = p1.tensor.nelem * p2.tensor.nelem
+
+ p3 = alloc_tensor(nelem)
+
+ p3.tensor.ndim = ndim
+
+ for i in [0...p1.tensor.ndim]
+ p3.tensor.dim[i] = p1.tensor.dim[i]
+
+ for j in [0...p2.tensor.ndim]
+ p3.tensor.dim[i + j] = p2.tensor.dim[j]
+
+ k = 0
+
+ for i in [0...p1.tensor.nelem]
+ p2 = p1.tensor.elem[i]
+ for j in [0...p2.tensor.nelem]
+ p3.tensor.elem[k++] = p2.tensor.elem[j]
+
+ check_tensor_dimensions p2
+ check_tensor_dimensions p3
+
+ push(p3)
+
+ restore()
+
+compatible = (p,q) ->
+
+ if (!istensor(p) && !istensor(q))
+ return 1
+
+ if (!istensor(p) || !istensor(q))
+ return 0
+
+ if (p.tensor.ndim != q.tensor.ndim)
+ return 0
+
+ for i in [0...p.tensor.ndim]
+ if (p.tensor.dim[i] != q.tensor.dim[i])
+ return 0
+
+ return 1
+
+
diff --git a/node_modules/algebrite/sources/test.coffee b/node_modules/algebrite/sources/test.coffee
new file mode 100644
index 0000000..ae35ceb
--- /dev/null
+++ b/node_modules/algebrite/sources/test.coffee
@@ -0,0 +1,315 @@
+# If the number of args is odd then the last arg is the default result.
+# Works like a switch statement. Could also be used for piecewise
+# functions? TODO should probably be called "switch"?
+
+Eval_test = ->
+ orig = p1
+ p1 = cdr(p1)
+ while (iscons(p1))
+
+ # odd number of parameters means that the
+ # last argument becomes the default case
+ # i.e. the one without a test.
+ if (cdr(p1) == symbol(NIL))
+ push(car(p1)); # default case
+ Eval()
+ return
+
+ checkResult = isZeroLikeOrNonZeroLikeOrUndetermined car(p1)
+ if !checkResult?
+ # we couldn't determine the result
+ # of a test. This means we can't conclude
+ # anything about the result of the
+ # overall test, so we must bail
+ # with the unevalled test
+ push orig
+ return
+ else if checkResult
+ # test succesful, we found out output
+ push(cadr(p1))
+ Eval()
+ return
+ else
+ # test unsuccessful, continue to the
+ # next pair of test,value
+ p1 = cddr(p1)
+
+
+ # no test matched and there was no
+ # catch-all case, so we return zero.
+ push_integer 0
+
+# we test A==B by first subtracting and checking if we symbolically
+# get zero. If not, we evaluate to float and check if we get a zero.
+# If we get another NUMBER then we know they are different.
+# If we get something else, then we don't know and we return the
+# unaveluated test, which is the same as saying "maybe".
+Eval_testeq = ->
+ # first try without simplifyng both sides
+ orig = p1
+ push(cadr(p1))
+ Eval()
+ push(caddr(p1))
+ Eval()
+ subtract()
+ subtractionResult = pop()
+
+ # OK so we are doing something tricky here
+ # we are using isZeroLikeOrNonZeroLikeOrUndetermined to check if the result
+ # is zero or not zero or unknown.
+ # isZeroLikeOrNonZeroLikeOrUndetermined has some routines
+ # to determine the zero-ness/non-zero-ness or
+ # undeterminate-ness of things so we use
+ # that here and down below.
+ checkResult = isZeroLikeOrNonZeroLikeOrUndetermined subtractionResult
+ if checkResult
+ push_integer(0)
+ return
+ else if checkResult? and !checkResult
+ push_integer(1)
+ return
+
+ # we didn't get a simple numeric result but
+ # let's try again after doing
+ # a simplification on both sides
+ push(cadr(p1))
+ Eval()
+ simplify()
+ push(caddr(p1))
+ Eval()
+ simplify()
+ subtract()
+ subtractionResult = pop()
+
+ checkResult = isZeroLikeOrNonZeroLikeOrUndetermined subtractionResult
+ if checkResult
+ push_integer(0)
+ return
+ else if checkResult? and !checkResult
+ push_integer(1)
+ return
+
+ # if we didn't get to a number then we
+ # don't know whether the quantities are
+ # different so do nothing
+ push orig
+
+# Relational operators expect a numeric result for operand difference.
+
+Eval_testge = ->
+ orig = p1
+ comparison = cmp_args()
+
+ if !comparison?
+ push orig
+ return
+
+ if ( comparison >= 0)
+ push_integer(1)
+ else
+ push_integer(0)
+
+Eval_testgt = ->
+ orig = p1
+ comparison = cmp_args()
+
+ if !comparison?
+ push orig
+ return
+
+ if ( comparison > 0)
+ push_integer(1)
+ else
+ push_integer(0)
+
+Eval_testle = ->
+ orig = p1
+ comparison = cmp_args()
+
+ if !comparison?
+ push orig
+ return
+
+ if ( comparison <= 0)
+ push_integer(1)
+ else
+ push_integer(0)
+
+Eval_testlt = ->
+ orig = p1
+ comparison = cmp_args()
+
+ if !comparison?
+ push orig
+ return
+
+ if ( comparison < 0)
+ push_integer(1)
+ else
+ push_integer(0)
+
+# not definition
+Eval_not = ->
+ wholeAndExpression = p1
+ checkResult = isZeroLikeOrNonZeroLikeOrUndetermined cadr(p1)
+ if !checkResult?
+ # inconclusive test on predicate
+ push wholeAndExpression
+ else if checkResult
+ # true -> false
+ push_integer(0)
+ else
+ # false -> true
+ push_integer(1)
+
+### and =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+a,b,...
+
+General description
+-------------------
+Logical-and of predicate expressions.
+
+###
+
+# and definition
+Eval_and = ->
+ wholeAndExpression = p1
+ andPredicates = cdr(wholeAndExpression)
+ somePredicateUnknown = false
+ while (iscons(andPredicates))
+ # eval each predicate
+ checkResult = isZeroLikeOrNonZeroLikeOrUndetermined car(andPredicates)
+
+ if !checkResult?
+ # here we have stuff that is not reconducible to any
+ # numeric value (or tensor with numeric values) e.g.
+ # 'a+b', so it just means that we just don't know the
+ # truth value of this particular predicate.
+ # We'll track the fact that we found an unknown
+ # predicate and we continue with the other predicates.
+ # (note that in case some subsequent predicate will be false,
+ # it won't matter that we found some unknowns and
+ # the whole test will be immediately zero).
+ somePredicateUnknown = true
+ andPredicates = cdr(andPredicates)
+
+ else if checkResult
+ # found a true, move on to the next predicate
+ andPredicates = cdr(andPredicates)
+
+ else if !checkResult
+ # found a false, enough to falsify everything and return
+ push_integer(0)
+ return
+
+ # We checked all the predicates and none of them
+ # was false. So they were all either true or unknown.
+ # Now, if even just one was unknown, we'll have to call this
+ # test as inconclusive and return the whole test expression.
+ # If all the predicates were known, then we can conclude
+ # that the test returns true.
+ if somePredicateUnknown
+ push wholeAndExpression
+ else
+ push_integer(1)
+
+# or definition
+Eval_or = ->
+ wholeOrExpression = p1
+ orPredicates = cdr(wholeOrExpression)
+ somePredicateUnknown = false
+ while (iscons(orPredicates))
+ # eval each predicate
+ checkResult = isZeroLikeOrNonZeroLikeOrUndetermined car(orPredicates)
+
+ if !checkResult?
+ # here we have stuff that is not reconducible to any
+ # numeric value (or tensor with numeric values) e.g.
+ # 'a+b', so it just means that we just don't know the
+ # truth value of this particular predicate.
+ # We'll track the fact that we found an unknown
+ # predicate and we continue with the other predicates.
+ # (note that in case some subsequent predicate will be false,
+ # it won't matter that we found some unknowns and
+ # the whole test will be immediately zero).
+ somePredicateUnknown = true
+ orPredicates = cdr(orPredicates)
+
+ else if checkResult
+ # found a true, enough to return true
+ push_integer(1)
+ return
+
+ else if !checkResult
+ # found a false, move on to the next predicate
+ orPredicates = cdr(orPredicates)
+
+ # We checked all the predicates and none of them
+ # was true. So they were all either false or unknown.
+ # Now, if even just one was unknown, we'll have to call this
+ # test as inconclusive and return the whole test expression.
+ # If all the predicates were known, then we can conclude
+ # that the test returns false.
+ if somePredicateUnknown
+ push wholeOrExpression
+ else
+ push_integer(0)
+
+# use subtract for cases like A < A + 1
+
+# TODO you could be smarter here and
+# simplify both sides only in the case
+# of "relational operator: cannot determine..."
+# a bit like we do in Eval_testeq
+cmp_args = ->
+ t = 0
+
+ push(cadr(p1))
+ Eval()
+ simplify()
+ push(caddr(p1))
+ Eval()
+ simplify()
+ subtract()
+ p1 = pop()
+
+ # try floating point if necessary
+
+ if (p1.k != NUM && p1.k != DOUBLE)
+ push(p1)
+ yyfloat()
+ Eval()
+ p1 = pop()
+
+ #console.log "comparison: " + p1.toString()
+
+ if (isZeroAtomOrTensor(p1))
+ #console.log "comparison isZero "
+ return 0
+
+ switch (p1.k)
+ when NUM
+ if (MSIGN(p1.q.a) == -1)
+ t = -1
+ else
+ t = 1
+ when DOUBLE
+ #console.log "comparison p1.d: " + p1.d
+ if (p1.d < 0.0)
+ t = -1
+ else
+ t = 1
+ else
+ #console.log "comparison is null"
+ t = null
+
+ return t
+
+
diff --git a/node_modules/algebrite/sources/transform.coffee b/node_modules/algebrite/sources/transform.coffee
new file mode 100644
index 0000000..2ecfe79
--- /dev/null
+++ b/node_modules/algebrite/sources/transform.coffee
@@ -0,0 +1,317 @@
+###
+Transform an expression using a pattern. The
+pattern can come from the integrals table or
+the user-defined patterns.
+
+The expression and free variable are on the stack.
+
+The argument s is a null terminated list of transform rules.
+
+For example, see the itab (integrals table)
+
+Internally, the following symbols are used:
+
+ F input expression
+
+ X free variable, i.e. F of X
+
+ A template expression
+
+ B result expression
+
+ C list of conditional expressions
+
+Puts the final expression on top of stack
+(whether it's transformed or not) and returns
+true is successful, false if not.
+
+
+###
+
+
+
+# p1 and p2 are tmps
+
+#define F p3
+#define X p4
+#define A p5
+#define B p6
+#define C p7
+
+transform = (s, generalTransform) ->
+ transform_h = 0
+
+ save()
+
+ p1 = null
+
+ p4 = pop() # X i.e. free variable
+ p3 = pop() # F i.e. input expression
+
+ if DEBUG
+ console.log " !!!!!!!!! transform on: " + p3
+
+
+ saveMetaBindings()
+
+ set_binding(symbol(METAX), p4)
+
+ # put constants in F(X) on the stack
+
+ transform_h = tos
+ push_integer(1)
+ push(p3)
+ push(p4)
+ polyform(); # collect coefficients of x, x^2, etc.
+ push(p4)
+
+ bookmarkTosToPrintDecomps = tos - 2
+ decomp(generalTransform)
+ numberOfDecomps = tos - bookmarkTosToPrintDecomps
+
+ if DEBUG
+ console.log " " + numberOfDecomps + " decomposed elements ====== "
+ for i in [0...numberOfDecomps]
+ console.log " decomposition element " + i + ": " + stack[tos-1-i]
+
+ transformationSuccessful = false
+
+ if generalTransform
+ # "general tranform" mode is supposed to be more generic than
+ # "integrals" mode.
+ # In general transform mode we get only one transformation
+ # in s
+
+ # simple numbers can end up matching complicated templates,
+ # which we don't want.
+ # for example "1" ends up matching "inner(transpose(a_),a_)"
+ # since "1" is decomposed to "1" and replacing "a_" with "1"
+ # there is a match.
+ # Although this match is OK at some fundamental level, we want to
+ # avoid it because that's not what the spirit of this match
+ # is: "1" does not have any structural resemblance with
+ # "inner(transpose(a_),a_)". There are probably better ways
+ # to so this, for example we might notice that "inner" is an
+ # anchor since it "sits above" any meta variables, so we
+ # might want to mandate it to be matched at the top
+ # of the tree. For the time
+ # being let's just skip matching on simple numbers.
+ if !isNumericAtom(p3)
+
+ theTransform = s
+ if DEBUG then console.log "applying transform: " + theTransform
+ if DEBUG then console.log "scanning table entry " + theTransform
+
+ push theTransform
+
+ # replacements of meta variables. Note that we don't
+ # use scan_meta because the pattern is not a string
+ # that we have to parse, it's a tree already.
+ # replace a_ with METAA in the passed transformation
+ push symbol(SYMBOL_A_UNDERSCORE)
+ push symbol(METAA)
+ subst()
+
+ # replace b_ with METAB in the passed transformation
+ push symbol(SYMBOL_B_UNDERSCORE)
+ push symbol(METAB)
+ subst()
+
+ # replace x_ with METAX in the passed transformation
+ push symbol(SYMBOL_X_UNDERSCORE)
+ push symbol(METAX)
+ subst()
+
+ p1 = pop()
+
+ p5 = car(p1)
+ if DEBUG then console.log "template expression: " + p5
+ p6 = cadr(p1)
+ p7 = cddr(p1)
+
+ ###
+ p5 = p1.tensor.elem[0]
+ p6 = p1.tensor.elem[1]
+ for i in [2..(p1.tensor.elem.length-1)]
+ push p1.tensor.elem[i]
+ list(p1.tensor.elem.length - 2)
+ p7 = pop()
+ ###
+
+
+
+ if (f_equals_a(transform_h, generalTransform))
+ # successful transformation,
+ # transformed result is in p6
+ transformationSuccessful = true
+ else
+ # the match failed but perhaps we can match
+ # something lower down in the tree, so
+ # let's recurse the tree
+
+ if DEBUG then console.log "p3 at this point: " + p3
+
+ transformedTerms = []
+
+ if DEBUG then console.log "car(p3): " + car(p3)
+ restTerm = p3
+
+ if iscons(restTerm)
+ transformedTerms.push car(p3)
+ restTerm = cdr(p3)
+
+ while (iscons(restTerm))
+ secondTerm = car(restTerm)
+ restTerm = cdr(restTerm)
+
+ if DEBUG then console.log "tos before recursive transform: " + tos
+
+ push(secondTerm)
+ push_symbol(NIL)
+ if DEBUG then console.log "testing: " + secondTerm
+ #if (secondTerm+"") == "eig(A x,transpose(A x))()"
+ # debugger
+ if DEBUG then console.log "about to try to simplify other term: " + secondTerm
+ success = transform(s, generalTransform)
+ transformationSuccessful = transformationSuccessful or success
+
+ transformedTerms.push pop()
+
+ if DEBUG then console.log "tried to simplify other term: " + secondTerm + " ...successful?: " + success + " ...transformed: " + transformedTerms[transformedTerms.length-1]
+
+
+ # recreate the tree we were passed,
+ # but with all the terms being transformed
+ if transformedTerms.length != 0
+ for i in transformedTerms
+ push i
+ list(transformedTerms.length)
+ p6 = pop()
+
+
+
+ else # "integrals" mode
+ for eachTransformEntry in s
+ if DEBUG
+ console.log "scanning table entry " + eachTransformEntry
+ if (eachTransformEntry + "").indexOf("f(sqrt(a+b*x),2/3*1/b*sqrt((a+b*x)^3))") != -1
+ debugger
+ if eachTransformEntry
+ scan_meta(eachTransformEntry)
+ p1 = pop()
+
+ p5 = cadr(p1)
+ p6 = caddr(p1)
+ p7 = cdddr(p1)
+
+ ###
+ p5 = p1.tensor.elem[0]
+ p6 = p1.tensor.elem[1]
+ for i in [2..(p1.tensor.elem.length-1)]
+ push p1.tensor.elem[i]
+ list(p1.tensor.elem.length - 2)
+ p7 = pop()
+ ###
+
+
+ if (f_equals_a(transform_h, generalTransform))
+ # there is a successful transformation,
+ # transformed result is in p6
+ transformationSuccessful = true
+ break
+
+
+
+
+ moveTos transform_h
+
+
+ if transformationSuccessful
+ #console.log "transformation successful"
+ # a transformation was successful
+ push(p6)
+ Eval()
+ p1 = pop()
+ #console.log "...into: " + p1
+ transformationSuccessful = true
+ else
+ # transformations failed
+ if generalTransform
+ # result = original expression
+ p1 = p3
+ else
+ p1 = symbol(NIL)
+
+ restoreMetaBindings()
+
+ push(p1)
+
+ restore()
+ return transformationSuccessful
+
+saveMetaBindings = ->
+ push(get_binding(symbol(METAA)))
+ push(get_binding(symbol(METAB)))
+ push(get_binding(symbol(METAX)))
+
+
+restoreMetaBindings = ->
+ set_binding(symbol(METAX), pop())
+ set_binding(symbol(METAB), pop())
+ set_binding(symbol(METAA), pop())
+
+# search for a METAA and METAB such that F = A
+
+f_equals_a = (h, generalTransform) ->
+ fea_i = 0
+ fea_j = 0
+ for fea_i in [h...tos]
+
+ set_binding(symbol(METAA), stack[fea_i])
+ if DEBUG
+ console.log " binding METAA to " + get_binding(symbol(METAA))
+ for fea_j in [h...tos]
+
+ set_binding(symbol(METAB), stack[fea_j])
+ if DEBUG
+ console.log " binding METAB to " + get_binding(symbol(METAB))
+
+ # now test all the conditions (it's an and between them)
+ p1 = p7
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ p2 = pop()
+ if (isZeroAtomOrTensor(p2))
+ break
+ p1 = cdr(p1)
+
+ if (iscons(p1))
+ # conditions are not met,
+ # skip to the next binding of metas
+ continue
+ push(p3); # F = A?
+ if DEBUG
+ console.log "about to evaluate template expression: " + p5 +
+ " binding METAA to " + get_binding(symbol(METAA)) +
+ " and binding METAB to " + get_binding(symbol(METAB)) +
+ " and binding METAX to " + get_binding(symbol(METAX))
+ push(p5)
+ if generalTransform
+ originalexpanding = expanding
+ expanding = false
+ Eval()
+ if generalTransform
+ expanding = originalexpanding
+ if DEBUG
+ console.log " comparing " + stack[tos-1] + " to: " + stack[tos-2]
+ subtract()
+ p1 = pop()
+ if (isZeroAtomOrTensor(p1))
+ if DEBUG
+ console.log "binding METAA to " + get_binding(symbol(METAA))
+ console.log "binding METAB to " + get_binding(symbol(METAB))
+ console.log "binding METAX to " + get_binding(symbol(METAX))
+ console.log "comparing " + p3 + " to: " + p5
+ return 1; # yes
+ return 0; # no
diff --git a/node_modules/algebrite/sources/transpose.coffee b/node_modules/algebrite/sources/transpose.coffee
new file mode 100644
index 0000000..180f9b8
--- /dev/null
+++ b/node_modules/algebrite/sources/transpose.coffee
@@ -0,0 +1,241 @@
+# Transpose tensor indices
+
+
+
+Eval_transpose = ->
+ push(cadr(p1))
+ Eval()
+
+ # add default params if they
+ # have not been passed
+ if (cddr(p1) == symbol(NIL))
+ push_integer(1)
+ push_integer(2)
+ else
+ push(caddr(p1))
+ Eval()
+ push(cadddr(p1))
+ Eval()
+ transpose()
+
+transpose = ->
+ i = 0
+ j = 0
+ k = 0
+ l = 0
+ m = 0
+ ndim = 0
+ nelem = 0
+ t = 0
+ ai = []
+ an = []
+ for i in [0...MAXDIM]
+ ai[i] = 0
+ an[i] = 0
+
+ #U **a, **b
+
+ save()
+
+ # by default p3 is 2 and p2 is 1
+ p3 = pop() # index to be transposed
+ p2 = pop() # other index to be transposed
+ p1 = pop() # what needs to be transposed
+
+ # a transposition just goes away when
+ # applied to a scalar
+ if (isNumericAtom(p1))
+ push p1
+ restore()
+ return
+
+ # transposition goes away for identity matrix
+ if ((isplusone(p2) and isplustwo(p3)) or (isplusone(p3) and isplustwo(p2)))
+ if isidentitymatrix(p1)
+ push p1
+ restore()
+ return
+
+ # a transposition just goes away when
+ # applied to another transposition with
+ # the same columns to be switched
+ if (istranspose(p1))
+ innerTranspSwitch1 = car(cdr(cdr(p1)))
+ innerTranspSwitch2 = car(cdr(cdr(cdr(p1))))
+
+ if ( equal(innerTranspSwitch1,p3) and equal(innerTranspSwitch2,p2) ) or
+ ( equal(innerTranspSwitch2,p3) and equal(innerTranspSwitch1,p2) ) or
+ (( equal(innerTranspSwitch1,symbol(NIL)) and equal(innerTranspSwitch2,symbol(NIL)) ) and ((isplusone(p3) and isplustwo(p2)) or ((isplusone(p2) and isplustwo(p3)))))
+ push car(cdr(p1))
+ restore()
+ return
+
+ # if operand is a sum then distribute
+ # (if we are in expanding mode)
+ if (expanding && isadd(p1))
+ p1 = cdr(p1)
+ push(zero)
+ while (iscons(p1))
+ push(car(p1))
+ # add the dimensions to switch but only if
+ # they are not the default ones.
+ push(p2)
+ push(p3)
+ transpose()
+ add()
+ p1 = cdr(p1)
+ restore()
+ return
+
+ # if operand is a multiplication then distribute
+ # (if we are in expanding mode)
+ if (expanding && ismultiply(p1))
+ p1 = cdr(p1)
+ push(one)
+ while (iscons(p1))
+ push(car(p1))
+ # add the dimensions to switch but only if
+ # they are not the default ones.
+ push(p2)
+ push(p3)
+ transpose()
+ multiply()
+ p1 = cdr(p1)
+ restore()
+ return
+
+ # distribute the transpose of a dot
+ # if in expanding mode
+ # note that the distribution happens
+ # in reverse as per tranpose rules.
+ # The dot operator is not
+ # commutative, so, it matters.
+ if (expanding && isinnerordot(p1))
+ p1 = cdr(p1)
+ accumulator = []
+ while (iscons(p1))
+ accumulator.push [car(p1),p2,p3]
+ p1 = cdr(p1)
+
+ for eachEntry in [accumulator.length-1..0]
+ push(accumulator[eachEntry][0])
+ push(accumulator[eachEntry][1])
+ push(accumulator[eachEntry][2])
+ transpose()
+ if eachEntry != accumulator.length-1
+ inner()
+
+ restore()
+ return
+
+
+ if (!istensor(p1))
+ if (!isZeroAtomOrTensor(p1))
+ #stop("transpose: tensor expected, 1st arg is not a tensor")
+ push_symbol(TRANSPOSE)
+ push(p1)
+ # remove the default "dimensions to be switched"
+ # parameters
+ if (!isplusone(p2) or !isplustwo(p3)) and (!isplusone(p3) or !isplustwo(p2))
+ push(p2)
+ push(p3)
+ list(4)
+ else
+ list(2)
+ restore()
+ return
+ push(zero)
+ restore()
+ return
+
+ ndim = p1.tensor.ndim
+ nelem = p1.tensor.nelem
+
+ # is it a vector?
+ # so here it's something curious - note how vectors are
+ # not really special two-dimensional matrices, but rather
+ # 1-dimension objects (like tensors can be). So since
+ # they have one dimension, transposition has no effect.
+ # (as opposed as if they were special two-dimensional
+ # matrices)
+ # see also Ran Pan, Tensor Transpose and Its Properties. CoRR abs/1411.1503 (2014)
+
+ if (ndim == 1)
+ push(p1)
+ restore()
+ return
+
+ push(p2)
+ l = pop_integer()
+
+ push(p3)
+ m = pop_integer()
+
+ if (l < 1 || l > ndim || m < 1 || m > ndim)
+ stop("transpose: index out of range")
+
+ l--
+ m--
+
+ p2 = alloc_tensor(nelem)
+
+ p2.tensor.ndim = ndim
+
+ for i in [0...ndim]
+ p2.tensor.dim[i] = p1.tensor.dim[i]
+
+ p2.tensor.dim[l] = p1.tensor.dim[m]
+ p2.tensor.dim[m] = p1.tensor.dim[l]
+
+ a = p1.tensor.elem
+ b = p2.tensor.elem
+
+ # init tensor index
+
+ for i in [0...ndim]
+ ai[i] = 0
+ an[i] = p1.tensor.dim[i]
+
+ # copy components from a to b
+
+ for i in [0...nelem]
+
+ # swap indices l and m
+
+ t = ai[l]; ai[l] = ai[m]; ai[m] = t;
+ t = an[l]; an[l] = an[m]; an[m] = t;
+
+ # convert tensor index to linear index k
+
+ k = 0
+ for j in [0...ndim]
+ k = (k * an[j]) + ai[j]
+
+ # swap indices back
+
+ t = ai[l]; ai[l] = ai[m]; ai[m] = t;
+ t = an[l]; an[l] = an[m]; an[m] = t;
+
+ # copy one element
+
+ b[k] = a[i]
+
+ # increment tensor index
+
+ # Suppose the tensor dimensions are 2 and 3.
+ # Then the tensor index ai increments as follows:
+ # 00 -> 01
+ # 01 -> 02
+ # 02 -> 10
+ # 10 -> 11
+ # 11 -> 12
+ # 12 -> 00
+
+ for j in [(ndim - 1)..0]
+ if (++ai[j] < an[j])
+ break
+ ai[j] = 0
+
+ push(p2)
+ restore()
+
diff --git a/node_modules/algebrite/sources/userfunc.coffee b/node_modules/algebrite/sources/userfunc.coffee
new file mode 100644
index 0000000..7500832
--- /dev/null
+++ b/node_modules/algebrite/sources/userfunc.coffee
@@ -0,0 +1,222 @@
+# Evaluate a user defined function
+
+
+#define F p3 # F is the function body
+#define A p4 # A is the formal argument list
+#define B p5 # B is the calling argument list
+#define S p6 # S is the argument substitution list
+
+# we got here because there was a function invocation and
+# it's not been parsed (and consequently tagged) as any
+# system function.
+# So we are dealing with another function.
+# The function could be actually defined, or not yet,
+# so we'll deal with both cases.
+
+### d =====================================================================
+
+Tags
+----
+scripting, JS, internal, treenode, general concept
+
+Parameters
+----------
+f,x
+
+General description
+-------------------
+Returns the partial derivative of f with respect to x. x can be a vector e.g. [x,y].
+
+###
+
+Eval_user_function = ->
+
+ # Use "derivative" instead of "d" if there is no user function "d"
+
+ if DEBUG then console.log "Eval_user_function evaluating: " + car(p1)
+ if (car(p1) == symbol(SYMBOL_D) && get_binding(symbol(SYMBOL_D)) == symbol(SYMBOL_D))
+ Eval_derivative()
+ return
+
+ # normally car(p1) is a symbol with the function name
+ # but it could be something that has to be
+ # evaluated to get to the function definition instead
+ # (e.g. the function is an element of an array)
+ # so we do an eval to sort it all out.
+ push(car(p1))
+ Eval()
+
+ # we expect to find either the body and
+ # formula arguments, OR, if the function
+ # has not been defined yet, then the
+ # function will just contain its own name, as
+ # all undefined variables do.
+ bodyAndFormalArguments = pop()
+
+ if isNumericAtom(bodyAndFormalArguments)
+ stop("expected function invocation, found multiplication instead. Use '*' symbol explicitly for multiplication.")
+ else if istensor(bodyAndFormalArguments)
+ stop("expected function invocation, found tensor product instead. Use 'dot/inner' explicitly.")
+ else if isstr(bodyAndFormalArguments)
+ stop("expected function, found string instead.")
+
+ p3 = car(cdr(bodyAndFormalArguments)) # p3 is function body F
+ # p4 is the formal argument list
+ # that is also contained here in the FUNCTION node
+ p4 = car(cdr(cdr(bodyAndFormalArguments)))
+
+ p5 = cdr(p1); # p5 is the calling argument list
+
+ # example:
+ # f(x) = x+2
+ # then:
+ # p3.toString() = "x + 2"
+ # p4 = x
+ # p5 = 2
+
+ # first check is whether we don't obtain a function
+ if (car(bodyAndFormalArguments) != symbol(FUNCTION)) or
+ # next check is whether evaluation did nothing, so the function is undefined
+ (bodyAndFormalArguments == car(p1)) # p3 is F
+ # leave everything as it was and return
+ h = tos
+ push(bodyAndFormalArguments); # p3 is F
+ p1 = p5; # p5 is B
+ while (iscons(p1))
+ push(car(p1))
+ Eval()
+ p1 = cdr(p1)
+ list(tos - h)
+ return
+
+ # Create the argument substitution list p6(S)
+
+ p1 = p4; # p4 is A
+ p2 = p5; # p5 is B
+ h = tos
+ while (iscons(p1) && iscons(p2))
+ push(car(p1))
+ push(car(p2))
+ # why explicitly Eval the parameters when
+ # the body of the function is
+ # evalled anyways? Commenting it out. All tests pass...
+ #Eval()
+ p1 = cdr(p1)
+ p2 = cdr(p2)
+
+ list(tos - h)
+ p6 = pop(); # p6 is S
+
+ # Evaluate the function body
+
+ push(p3); # p3 is F
+ if (iscons(p6)) # p6 is S
+ push(p6); # p6 is S
+ rewrite_args()
+ #console.log "rewritten body: " + stack[tos-1]
+ Eval()
+
+# Rewrite by expanding symbols that contain args
+
+rewrite_args = ->
+ n = 0
+ save()
+
+ # subst. list which is a list
+ # where each consecutive pair
+ # is what needs to be substituted and with what
+ p2 = pop();
+ #console.log "subst. list " + p2
+
+ # expr to substitute in i.e. the
+ # function body
+ p1 = pop();
+ #console.log "expr: " + p1
+
+ if (istensor(p1))
+ n = rewrite_args_tensor()
+ restore()
+ return n
+
+ if (iscons(p1))
+ h = tos
+ if (car(p1) == car(p2))
+ # rewrite a function in
+ # the body with the one
+ # passed from the paramaters
+ push_symbol(EVAL)
+ push(car(cdr(p2)));
+ list(2)
+ else
+ # if there is no match
+ # then no substitution necessary
+ push(car(p1));
+
+ # continue recursively to
+ # rewrite the rest of the body
+ p1 = cdr(p1)
+ while (iscons(p1))
+ push(car(p1))
+ push(p2)
+ n += rewrite_args()
+ p1 = cdr(p1)
+ list(tos - h)
+ restore()
+ return n
+
+ # ground cases here
+ # (apart from function name which has
+ # already been substituted as it's in the head
+ # of the cons)
+ # -----------------
+
+ # If not a symbol then no
+ # substitution to be done
+ if (!issymbol(p1))
+ push(p1)
+ restore()
+ return 0
+
+ # Here we are in a symbol case
+ # so we need to substitute
+
+ # Check if there is a direct match
+ # of symbols right away
+ p3 = p2
+ while (iscons(p3))
+ if (p1 == car(p3))
+ push(cadr(p3))
+ restore()
+ return 1
+ p3 = cddr(p3)
+
+ # Get the symbol's content, if _that_
+ # matches then do the substitution
+ p3 = get_binding(p1)
+ push(p3)
+ if (p1 != p3)
+ push(p2); # subst. list
+ n = rewrite_args()
+ if (n == 0)
+ pop()
+ push(p1); # restore if not rewritten with arg
+
+ restore()
+ return n
+
+rewrite_args_tensor = ->
+ n = 0
+ i = 0
+ push(p1)
+ copy_tensor()
+ p1 = pop()
+ for i in [0...p1.tensor.nelem]
+ push(p1.tensor.elem[i])
+ push(p2)
+ n += rewrite_args()
+ p1.tensor.elem[i] = pop()
+
+ check_tensor_dimensions p1
+
+ push(p1)
+ return n
diff --git a/node_modules/algebrite/sources/zero.coffee b/node_modules/algebrite/sources/zero.coffee
new file mode 100644
index 0000000..4123a9f
--- /dev/null
+++ b/node_modules/algebrite/sources/zero.coffee
@@ -0,0 +1,36 @@
+
+
+Eval_zero = ->
+ i = 0
+ k = []
+ m = 0
+ n = 0
+
+ for i in [0...MAXDIM]
+ k[i] = 0
+
+ m = 1
+ n = 0
+ p2 = cdr(p1)
+
+ while (iscons(p2))
+ push(car(p2))
+ Eval()
+ i = pop_integer()
+ if (i < 1 || isNaN(i))
+ # if the input is nonsensical
+ # just return 0
+ push(zero)
+ return
+ m *= i
+ k[n++] = i
+ p2 = cdr(p2)
+ if (n == 0)
+ push(zero)
+ return
+ p1 = alloc_tensor(m)
+ p1.tensor.ndim = n
+ for i in [0...n]
+ p1.tensor.dim[i] = k[i]
+ push(p1)
+
diff --git a/node_modules/algebrite/test-harness.coffee b/node_modules/algebrite/test-harness.coffee
new file mode 100644
index 0000000..120312b
--- /dev/null
+++ b/node_modules/algebrite/test-harness.coffee
@@ -0,0 +1,56 @@
+ok_tests = 0
+ko_tests = 0
+
+logout = (s) ->
+ console.log s
+
+
+run_test = (s) ->
+ i = 0
+ t = ""
+
+ test_flag = 1
+
+ run("clearall")
+
+ run("e=quote(e)")
+
+ for i in [0...s.length] by 2
+
+ console.log("starting example: " + s[i])
+ #alert("starting example: " + s[i])
+ # document.write("starting example: " + s[i] )
+
+
+ out_count = 0
+
+ try
+ resultFromRun = run(s[i])
+ catch error
+ console.log error
+ init()
+
+
+ if (resultFromRun == s[i+1])
+ # document.write(" ...ok")
+ console.log("ok example: " + s[i])
+ # alert("ok example: " + s[i])
+ ok_tests++
+ continue
+
+ ko_tests++
+ # document.write(" ...fail")
+ console.log("\n")
+ console.log("test failed: " + s[i])
+
+ console.log("expected: " + s[i+1])
+
+ console.log("obtained: " + resultFromRun)
+ console.log("\n")
+
+ # alert "test failed: " + s[i] + " expected: " + s[i+1] + " obtained: " + resultFromRun
+
+
+ test_flag = 0
+
+# these tests do not use "run" but still need a "stop" context
\ No newline at end of file
diff --git a/node_modules/algebrite/tests/abs.coffee b/node_modules/algebrite/tests/abs.coffee
new file mode 100644
index 0000000..0ba3214
--- /dev/null
+++ b/node_modules/algebrite/tests/abs.coffee
@@ -0,0 +1,175 @@
+test_abs = ->
+ run_test [
+
+ "abs(a+i*b)",
+ "(a^2+b^2)^(1/2)",
+
+ "abs(a+b+i*c)",
+ "(2*a*b+a^2+b^2+c^2)^(1/2)",
+
+ "abs(exp(a+i*b))",
+ "exp(a)",
+
+ "abs(((-1)^(1/3)+1)^(1/2))",
+ "3^(1/4)",
+
+ "abs((-2*(-1)^(1/6)/(3^(1/2)))^(1/4))",
+ "(2/(3^(1/2)))^(1/4)",
+
+ "abs((-2*(-1)^(1/6)/(3^(1/2))+1)^(1/4))",
+ "1/3^(1/8)",
+
+ "abs((2*(-1)^(5/6)/(3^(1/2)))^(1/4))",
+ "(2/(3^(1/2)))^(1/4)",
+
+ "abs(1+1.0*(-1)^(1/2))",
+ "1.414214...",
+
+ "abs(1-1.0*(-1)^(1/2))",
+ "1.414214...",
+
+ "abs(1+2.0*(-1)^(1/2))",
+ "2.236068...",
+
+ "abs(1-2.0*(-1)^(1/2))",
+ "2.236068...",
+
+ "abs(1)",
+ "1",
+
+ "abs(x)",
+ "abs(x)",
+
+ # true only if x is real,
+ # counterexample: i, which makes 1 and -1
+ "abs(x)^2",
+ "x^2",
+
+ "abs(-x)",
+ "abs(x)",
+
+ "abs(abs(-x))",
+ "abs(x)",
+
+ "abs(abs(abs(-x)))",
+ "abs(x)",
+
+ "abs(a+b)",
+ "abs(a+b)",
+
+ "abs(a*b)",
+ "abs(a)*abs(b)",
+
+ "abs(-1)",
+ "1",
+
+ "abs(1+exp(i*pi/3))",
+ "3^(1/2)",
+
+ "abs((a+i*b)/(c+i*d))",
+ "(a^2+b^2)^(1/2)/((c^2+d^2)^(1/2))",
+
+ "abs(((-1)^(1/2) / (3^(1/2)))^(1/2))",
+ "1/3^(1/4)",
+
+ "abs(exp(i theta))",
+ "1",
+
+ "abs(exp(-i theta))",
+ "1",
+
+ "abs((-1)^theta)",
+ "1",
+
+ "abs((-1)^(-theta))",
+ "1",
+
+ "abs(3*(-1)^theta)",
+ "3",
+
+ "abs(3*(-1)^(-theta))",
+ "3",
+
+ "abs(-3*(-1)^theta)",
+ "3",
+
+ "abs(-3*(-1)^(-theta))",
+ "3",
+
+ "abs(-5 i pi / a)",
+ "5*pi/abs(a)",
+
+ "abs(1 / a)",
+ "1/(abs(a))",
+
+ # ---------- old abs tests
+
+ "abs(2)",
+ "2",
+
+ "abs(2.0)",
+ "2.0",
+
+ "abs(-2)",
+ "2",
+
+ "abs(-2.0)",
+ "2.0",
+
+ "abs(a)",
+ "abs(a)",
+
+ "abs(-a)",
+ "abs(a)",
+
+ "abs(2*a)",
+ "2*abs(a)",
+
+ "abs(-2*a)",
+ "2*abs(a)",
+
+ "abs(2.0*a)",
+ "2.0*abs(a)",
+
+ "abs(-2.0*a)",
+ "2.0*abs(a)",
+
+ "abs(a-b)+abs(b-a)",
+ "2*abs(a-b)",
+
+ "abs(3 + 4 i)",
+ "5",
+
+ "abs([2,3,4])",
+ "29^(1/2)",
+
+ "abs(a*b)",
+ "abs(a)*abs(b)",
+
+ "abs(a/b)",
+ "abs(a)/abs(b)",
+
+ "abs(1/a^b)",
+ "1/(abs(a^b))",
+
+ # Check that vector length is simplified
+
+ "P=[u*cos(v),u*sin(v),v]",
+ "",
+
+ "abs(cross(d(P,u),d(P,v)))",
+ "(1+u^2)^(1/2)",
+
+ "abs((-1)^(-0.666667+0.0291367/pi))",
+ "1.0",
+
+ "abs((-1)^(9/3))",
+ "1",
+
+ "abs((1)^(9/3))",
+ "1",
+
+ "abs((-1.0)^(9/3))",
+ "1.0",
+
+ ]
diff --git a/node_modules/algebrite/tests/adj.coffee b/node_modules/algebrite/tests/adj.coffee
new file mode 100644
index 0000000..861d6c0
--- /dev/null
+++ b/node_modules/algebrite/tests/adj.coffee
@@ -0,0 +1,13 @@
+test_adj = ->
+ run_test [
+
+ "adj([[a,b],[c,d]])",
+ "[[d,-b],[-c,a]]",
+
+ "adj([[1,2],[3,4]])",
+ "[[4,-2],[-3,1]]",
+
+ "adj([[2,3,-2,5],[6,-2,1,4],[5,10,3,-2],[-1,2,2,3]])",
+ "[[-4,-177,-73,194],[-117,117,-99,-27],[310,-129,-44,-374],[-130,-51,71,-211]]",
+ ]
+
diff --git a/node_modules/algebrite/tests/approxratio.coffee b/node_modules/algebrite/tests/approxratio.coffee
new file mode 100644
index 0000000..afab14c
--- /dev/null
+++ b/node_modules/algebrite/tests/approxratio.coffee
@@ -0,0 +1,91 @@
+test_approxratio = ->
+ run_test [
+ "approxratio(0.9054054)",
+ "67/74",
+
+ "approxratio(0.0102)",
+ "1/98",
+
+ "approxratio(0.518518)",
+ "14/27",
+
+ "approxratio(0.3333)",
+ "1/3",
+
+ "approxratio(0.5)",
+ "1/2",
+
+ "approxratio(3.14159)",
+ "355/113",
+
+ "approxratio(a*3.14)",
+ "a*22/7",
+
+ "approxratio(a*b)",
+ "a*b",
+
+ "approxratio((0.5*4)^(1/3))",
+ "2^(1/3)",
+
+ "approxratio(3.14)",
+ "22/7",
+
+ # see http://davidbau.com/archives/2010/03/14/the_mystery_of_355113.html
+ "approxratio(3.14159)",
+ "355/113",
+
+ "approxratio(-3.14159)",
+ "-355/113",
+
+ "approxratio(0)",
+ "0",
+
+ "approxratio(0.0)",
+ "0",
+
+ "approxratio(2)",
+ "2",
+
+ "approxratio(2.0)",
+ "2",
+
+ # -------------------------------
+ # checking some "long primes"
+ # also called long period primes, or maximal period primes
+ # i.e. those numbers whose reciprocal give
+ # long repeating sequences
+ # (long prime p gives repetition of p-1 digits).
+ # big list here: https://oeis.org/A001913/b001913.txt
+ # also see: https://oeis.org/A001913
+ # -------------------------------
+
+ # 1st long prime
+ "approxratio(0.14)",
+ "1/7",
+
+ # 9th long prime, the biggest 2-digits long prime.
+ # Often asked to
+ # mental calculators to check their abilities.
+ "approxratio(0.0103)",
+ "1/97",
+
+ # 60th long prime, the biggest 3-digits long prime.
+ # Often asked to
+ # mental calculators to check their abilities.
+ "approxratio(0.001017)",
+ "1/983",
+
+ # 467th long prime, the biggest 4-digits long prime.
+ "approxratio(0.00010033)",
+ "1/9967",
+
+ # 3617th long prime, the biggest 5-digits long prime.
+ "approxratio(0.0000100011)",
+ "1/99989",
+
+ # 10000th long prime.
+ "approxratio(0.00000323701)",
+ "1/308927",
+
+ ]
+
diff --git a/node_modules/algebrite/tests/arccos.coffee b/node_modules/algebrite/tests/arccos.coffee
new file mode 100644
index 0000000..7d75438
--- /dev/null
+++ b/node_modules/algebrite/tests/arccos.coffee
@@ -0,0 +1,54 @@
+test_arccos = ->
+ run_test [
+
+ "arccos(1)",
+ "0",
+
+ "arccos(1/2)",
+ "1/3*pi",
+
+ "arccos(0)",
+ "1/2*pi",
+
+ "arccos(-1/2)",
+ "2/3*pi",
+
+ "arccos(-1)",
+ "pi",
+
+ "arccos(cos(0))",
+ "0",
+
+ "arccos(cos(1/3*pi))",
+ "1/3*pi",
+
+ "arccos(cos(1/2*pi))",
+ "1/2*pi",
+
+ "arccos(cos(2/3*pi))",
+ "2/3*pi",
+
+ "arccos(cos(pi))",
+ "pi",
+
+ "arccos(cos(x))",
+ "x",
+
+ "arccos(1/sqrt(2))",
+ "1/4*pi",
+
+ "arccos(-1/sqrt(2))",
+ "3/4*pi",
+
+ "arccos(cos(1/4*pi))",
+ "1/4*pi",
+
+ "arccos(cos(3/4*pi))",
+ "3/4*pi",
+
+ "arccos(sqrt(3)/2)",
+ "1/6*pi",
+
+ "arccos(-sqrt(3)/2)",
+ "5/6*pi",
+ ]
diff --git a/node_modules/algebrite/tests/arccosh.coffee b/node_modules/algebrite/tests/arccosh.coffee
new file mode 100644
index 0000000..cbaeadd
--- /dev/null
+++ b/node_modules/algebrite/tests/arccosh.coffee
@@ -0,0 +1,14 @@
+test_arccosh = ->
+ run_test [
+
+ "arccosh(1.0)",
+ "0.0",
+
+ "arccosh(1)",
+ "0",
+
+ "arccosh(cosh(x))",
+ "x",
+ ]
+
+
diff --git a/node_modules/algebrite/tests/arcsin.coffee b/node_modules/algebrite/tests/arcsin.coffee
new file mode 100644
index 0000000..144e7c2
--- /dev/null
+++ b/node_modules/algebrite/tests/arcsin.coffee
@@ -0,0 +1,53 @@
+test_arcsin = ->
+ run_test [
+ "arcsin(-1)",
+ "-1/2*pi",
+
+ "arcsin(-1/2)",
+ "-1/6*pi",
+
+ "arcsin(0)",
+ "0",
+
+ "arcsin(1/2)",
+ "1/6*pi",
+
+ "arcsin(1)",
+ "1/2*pi",
+
+ "arcsin(sin(-1/2*pi))",
+ "-1/2*pi",
+
+ "arcsin(sin(-1/6*pi))",
+ "-1/6*pi",
+
+ "arcsin(sin(0))",
+ "0",
+
+ "arcsin(sin(1/6*pi))",
+ "1/6*pi",
+
+ "arcsin(sin(1/2*pi))",
+ "1/2*pi",
+
+ "arcsin(sin(x))",
+ "x",
+
+ "arcsin(1/sqrt(2))",
+ "1/4*pi",
+
+ "arcsin(-1/sqrt(2))",
+ "-1/4*pi",
+
+ "arcsin(sin(1/4*pi))",
+ "1/4*pi",
+
+ "arcsin(sin(-1/4*pi))",
+ "-1/4*pi",
+
+ "arcsin(sqrt(3)/2)",
+ "1/3*pi",
+
+ "arcsin(-sqrt(3)/2)",
+ "-1/3*pi",
+ ]
diff --git a/node_modules/algebrite/tests/arcsinh.coffee b/node_modules/algebrite/tests/arcsinh.coffee
new file mode 100644
index 0000000..f9777a8
--- /dev/null
+++ b/node_modules/algebrite/tests/arcsinh.coffee
@@ -0,0 +1,12 @@
+test_arcsinh = ->
+ run_test [
+
+ "arcsinh(0.0)",
+ "0.0",
+
+ "arcsinh(0)",
+ "0",
+
+ "arcsinh(sinh(x))",
+ "x",
+ ]
diff --git a/node_modules/algebrite/tests/arctan.coffee b/node_modules/algebrite/tests/arctan.coffee
new file mode 100644
index 0000000..140732c
--- /dev/null
+++ b/node_modules/algebrite/tests/arctan.coffee
@@ -0,0 +1,33 @@
+test_arctan = ->
+ run_test [
+
+ "arctan(x)",
+ "arctan(x)",
+
+ "arctan(-x)",
+ "-arctan(x)",
+
+ "arctan(0)",
+ "0",
+
+ "arctan(tan(x))",
+ "x",
+
+ "arctan(1/sqrt(3))-pi/6", # 30 degrees
+ "0",
+
+ "arctan(1)-pi/4", # 45 degrees
+ "0",
+
+ "arctan(sqrt(3))-pi/3", # 60 degrees
+ "0",
+
+ "arctan(a-b)",
+ "arctan(a-b)",
+
+ "arctan(b-a)",
+ "-arctan(a-b)",
+
+ "arctan(tan(x))",
+ "x",
+ ]
diff --git a/node_modules/algebrite/tests/arctanh.coffee b/node_modules/algebrite/tests/arctanh.coffee
new file mode 100644
index 0000000..e917483
--- /dev/null
+++ b/node_modules/algebrite/tests/arctanh.coffee
@@ -0,0 +1,11 @@
+test_arctanh = ->
+ run_test [
+ "arctanh(0.0)",
+ "0.0",
+
+ "arctanh(0)",
+ "0",
+
+ "arctanh(tanh(x))",
+ "x",
+ ]
diff --git a/node_modules/algebrite/tests/arg.coffee b/node_modules/algebrite/tests/arg.coffee
new file mode 100644
index 0000000..b96bf89
--- /dev/null
+++ b/node_modules/algebrite/tests/arg.coffee
@@ -0,0 +1,102 @@
+test_arg = ->
+ run_test [
+
+ # wrong
+ #"arg(-1)",
+ #"-pi",
+
+ "arg(pi)",
+ "0",
+
+ "arg(1+i)",
+ "1/4*pi",
+
+ "arg(1-i)",
+ "-1/4*pi",
+
+ "arg(-1+i)",
+ "3/4*pi",
+
+ "arg(-1-i)",
+ "-3/4*pi",
+
+ "arg((-1)^(1/3))",
+ "1/3*pi",
+
+ "arg(1+exp(i*pi/3))",
+ "1/6*pi",
+
+ "arg((-1)^(1/6)*exp(i*pi/6))",
+ "1/3*pi",
+
+ # check when not assuming real variables ----------
+ "assumeRealVariables = 0",
+ "",
+
+ "arg(a)",
+ "arg(a)",
+
+ # TODO this is wrong
+ #"arg(a*exp(b+i*pi/5))",
+ #"1/5*pi",
+
+ # this is wrong
+ #"arg(-1)",
+ #"-pi",
+
+ # this is also highly debatable
+ # take the example
+ # a = -1-i
+ # then arg(a) - arg(-a) should give pi
+ # but arg(1+i) - arg(-1-i) gives -pi instead
+ # "arg(-a)",
+ # "-pi+arg(a)",
+
+ "assumeRealVariables = 1",
+ "",
+ # --------------------------------------------------
+
+ # TODO this is wrong.
+ #"arg(a*exp(b+i*pi/5))",
+ #"1/5*pi",
+
+ # referencing the test above, if
+ # a is positive:
+ "arg(abs(a)*exp(b+i*pi/5))",
+ "1/5*pi",
+
+ # otherwise, if negative, we get:
+ "arg((-8)*exp(b+i*pi/5))",
+ "-4/5*pi",
+
+ # if a is positive, zero
+ # if a is negative, -pi, so
+ # we can't say much
+ "arg(a)",
+ "arg(a)",
+
+ # this is also wrong, this should
+ # be either zero or pi
+ #"arg(-a)",
+ #"-pi+arg(a)",
+
+ "arg(-(-1)^(1/3))",
+ "-2/3*pi",
+
+ "arg(-exp(i*pi/3))",
+ "-2/3*pi",
+
+ "arg(-i)",
+ "-1/2*pi",
+
+ "arg((a+b*i)/(c+d*i))",
+ "arctan(b/a)-arctan(d/c)",
+
+ "arg(((-1)^(1/2) / (3^(1/2)))^(1/2))",
+ "1/4*pi",
+
+ "arg((-1)^(1/6))",
+ "1/6*pi",
+
+
+ ]
diff --git a/node_modules/algebrite/tests/assignments.coffee b/node_modules/algebrite/tests/assignments.coffee
new file mode 100644
index 0000000..a12a248
--- /dev/null
+++ b/node_modules/algebrite/tests/assignments.coffee
@@ -0,0 +1,293 @@
+test_assignments = ->
+ run_test [
+
+ # it used to return exp(1)
+ "e",
+ "e",
+
+ # normally sqrt(-1) is shown as i or j
+ # but if user really wants to look inside
+ # i/j then we are going to show sqrt(-1)
+ "i",
+ "(-1)^(1/2)",
+
+ "j",
+ "j",
+
+ # degenerate assignments give an error ----
+
+ "0=0",
+ "Stop: symbol assignment: error in symbol",
+
+ "1=2",
+ "Stop: symbol assignment: error in symbol",
+
+ "3=a",
+ "Stop: symbol assignment: error in symbol",
+
+ # ------------------------------------------
+
+ # f is not defined, so everything left as is
+ "f(a)",
+ "f(a)",
+
+ # this is parsed as a function call, the (f-f) is evaluated and
+ # returns zero, which is not a valid function, so here
+ # we can say that the user probably meant to use
+ # the multiplication
+ "(f-f)(a)",
+ "Stop: expected function invocation, found multiplication instead. Use '*' symbol explicitly for multiplication.",
+
+ # tensor instead of function
+ "([1,2])(a)",
+ "Stop: expected function invocation, found tensor product instead. Use 'dot/inner' explicitly.",
+
+ "[1,2](a)",
+ "Stop: expected function invocation, found tensor product instead. Use 'dot/inner' explicitly.",
+
+ # string instead of function
+ "(\"hey\")(a)",
+ "Stop: expected function, found string instead.",
+
+ "\"hey\"(a)",
+ "Stop: expected function, found string instead.",
+
+ # this is parsed as a function call, (f(a)) is evaluated and
+ # returns something that is not fully evaluated, so we have to
+ # leave it all as it was
+ "(f(a))(b)",
+ "f(a)(b)",
+
+ # this is parsed as a function call, the (f-1) is evaluated and
+ # returns something that is not fully evaluated, so again
+ # little that we can do
+ "(f-1)(a)",
+ "(-1+f)(a)",
+
+ # similar to the case above
+ "(x-2)(x-1)",
+ "(-2+x)(x-1)",
+
+ # similar to the case above, just with a space
+ "(x-2) (x-1)",
+ "(-2+x)(x-1)",
+
+ # ------------------------------------------
+
+ "1[2] = 3"
+ "Stop: indexed assignment: expected a symbol name"
+
+ "undefinedVar[1] = 2"
+ "Stop: error in indexed assign: assigning to something that is not a tensor"
+
+ "[[1,2],[3,4]][5] = 6"
+ "Stop: indexed assignment: expected a symbol name"
+
+ # ------------------------------------------
+
+ "f(x) = x + 1",
+ "",
+
+ "g = f",
+ "",
+
+ "lookup(f)",
+ "function (x) -> x+1",
+
+ "lookup(g)",
+ "function (x) -> x+1",
+
+ "f(x,y) = x + 2",
+ "",
+
+ "lookup(f)",
+ "function (x y) -> x+2",
+
+ "g(3)",
+ "4",
+
+ "f(3,0)",
+ "5",
+
+ "f = quote(1+1)",
+ "",
+
+ "g = f",
+ "",
+
+ "g",
+ "2",
+
+ "g = quote(f)",
+ "",
+
+ "g",
+ "2",
+
+ "lookup(g)",
+ "f",
+
+ "g = lookup(f)",
+ "",
+
+ "g",
+ "2",
+
+ "lookup(g)",
+ "1+1",
+
+ # test the abbreviated form :=
+ # of assignment with quote
+ "f := 1+1",
+ "",
+
+ "lookup(f)",
+ "1+1",
+
+ # a function returning a function
+
+ "f(x) = x + 1",
+ "",
+
+ "g() = f",
+ "",
+
+ "g()(2)",
+ "3",
+
+ # a function returning a function
+ # variant in which g has an (unneeded) parameter
+
+ "f(x) = x + 1",
+ "",
+
+ "g(y) = f",
+ "",
+
+ "g()(2)",
+ "3",
+
+
+ # a function returning a function
+ # variant in which g has an (unneeded) parameter
+ # with the same name of the parameter that f uses
+
+ "f(x) = x + 1",
+ "",
+
+ "g(x) = f",
+ "",
+
+ "g()(2)",
+ "3",
+
+ # passing functions as parameters
+
+ "f(x) = x + 1",
+ "",
+
+ "g(x) = x * x",
+ "",
+
+ "h(l, x) = l(x)",
+ "",
+
+ "h(f, 2)",
+ "3",
+
+ "h(g, 3)",
+ "9",
+
+
+ # passing function as parameter
+ # but doing nothing with it because
+ # the function in the body is already
+ # defined
+
+ "f(x) = x + 1",
+ "",
+
+ "g(x) = x * x",
+ "",
+
+ "h(l, x) = f(x)",
+ "",
+
+ "h(f, 2)",
+ "3",
+
+ "h(g, 3)",
+ "4",
+
+
+ # clean up -----------------
+
+ "f=quote(f)",
+ "",
+
+ "g=quote(g)",
+ "",
+
+ "h=quote(h)",
+ "",
+
+ # ----------------------
+ "a = a+1",
+ "",
+
+ "a",
+ "Stop: recursive evaluation of symbols: a -> a",
+
+ # ----------------------
+ "a := b",
+ "",
+
+ "b := c",
+ "",
+
+ "c := a",
+ "",
+
+ "b",
+ "Stop: recursive evaluation of symbols: b -> c -> a -> b",
+
+ # ----------------------
+ # note how this case actually doesn't generate a recursion
+ # as in Algebrite it's not a problem when a variable
+ # just contain itself, actually that's the default of
+ # unassigned variables.
+
+ "a = b",
+ "",
+
+ "b = a",
+ "",
+
+ "a",
+ "b",
+
+ "b",
+ "b",
+
+ # ----------------------
+ # note how these assignments actually don't generate
+ # a recursion as in Algebrite it's not a problem when
+ # a variable just contain itself, actually that's the
+ # default for unassigned variables.
+
+ "a=a",
+ "",
+
+ "a := a",
+ "",
+
+ "a",
+ "a",
+
+ # clean up -----------------
+
+ "clearall",
+ "",
+
+
+ ]
diff --git a/node_modules/algebrite/tests/bake.coffee b/node_modules/algebrite/tests/bake.coffee
new file mode 100644
index 0000000..9e89d9b
--- /dev/null
+++ b/node_modules/algebrite/tests/bake.coffee
@@ -0,0 +1,22 @@
+test_bake = ->
+ run_test [
+
+ "bake = 0",
+ "",
+
+ "(x+3)^3",
+ "27+27*x+9*x^2+x^3",
+
+ "factor",
+ "(3+x)^3",
+
+ "bake = 1",
+ "",
+
+ "(x+3)^3",
+ "x^3+9*x^2+27*x+27",
+
+ "factor",
+ "(x+3)^3",
+
+ ]
diff --git a/node_modules/algebrite/tests/besselj.coffee b/node_modules/algebrite/tests/besselj.coffee
new file mode 100644
index 0000000..ef862e0
--- /dev/null
+++ b/node_modules/algebrite/tests/besselj.coffee
@@ -0,0 +1,54 @@
+test_besselj = ->
+ run_test [
+
+ "besselj(x,n)",
+ "besselj(x,n)",
+
+ "besselj(0,0)",
+ "1",
+
+ "besselj(0,1)",
+ "0",
+
+ "besselj(0,-1)",
+ "0",
+
+ "besselj(x,1/2)-sqrt(2/pi/x)*sin(x)",
+ "0",
+
+ "besselj(x,-1/2)-sqrt(2/pi/x)*cos(x)",
+ "0",
+
+ "besselj(x,3/2)-sqrt(2/pi/x)*(sin(x)/x-cos(x))",
+ "0",
+
+ "besselj(x,-3/2)-sqrt(2/pi/x)*(-cos(x)/x-sin(x))",
+ "0",
+
+ "besselj(x,5/2)-sqrt(2/pi/x)*((3/x^2-1)*sin(x)-3/x*cos(x))",
+ "0",
+
+ "besselj(x,-5/2)-sqrt(2/pi/x)*((3/x^2-1)*cos(x)+3/x*sin(x))",
+ "0",
+
+ # From the note above
+
+ "besselj(x,3/2)-(1/x)*besselj(x,1/2)+besselj(x,-1/2)",
+ "0",
+
+ "besselj(x,-3/2)+(1/x)*besselj(x,-1/2)+besselj(x,1/2)",
+ "0",
+
+ # this should simplify
+
+ "y=besselj(x,5/2)",
+ "",
+
+ "x^2*d(y,x,x)+x*d(y,x)+(x^2-(5/2)^2)*y",
+ "0",
+
+ "y=quote(y)",
+ "",
+ ]
+
+
diff --git a/node_modules/algebrite/tests/bessely.coffee b/node_modules/algebrite/tests/bessely.coffee
new file mode 100644
index 0000000..525942f
--- /dev/null
+++ b/node_modules/algebrite/tests/bessely.coffee
@@ -0,0 +1,7 @@
+test_bessely = ->
+ run_test [
+
+ "bessely(x,n)",
+ "bessely(x,n)",
+ ]
+
diff --git a/node_modules/algebrite/tests/bignum.coffee b/node_modules/algebrite/tests/bignum.coffee
new file mode 100644
index 0000000..8ca8e52
--- /dev/null
+++ b/node_modules/algebrite/tests/bignum.coffee
@@ -0,0 +1,20 @@
+test_signs_in_rationals = ->
+ run_test [
+
+ # I found out about basic mistakes in
+ # these very very late, better to
+ # have those tests early on.
+
+ "1/1",
+ "1",
+
+ "-1/1",
+ "-1",
+
+ "1/(-1)",
+ "-1",
+
+ "(-1)/(-1)",
+ "1",
+
+ ]
diff --git a/node_modules/algebrite/tests/binomial.coffee b/node_modules/algebrite/tests/binomial.coffee
new file mode 100644
index 0000000..e1e0bc3
--- /dev/null
+++ b/node_modules/algebrite/tests/binomial.coffee
@@ -0,0 +1,24 @@
+test_binomial = ->
+ run_test [
+ "binomial(12,6)",
+ "924",
+
+ "binomial(n,k)",
+ # "1/(factorial(k))*factorial(n)*1/(factorial(-k+n))",
+ # "factorial(n)/(factorial(k)*factorial(-k+n))",
+ "n!/(k!*(-k+n)!)",
+
+ "binomial(0,k)",
+ # "1/(factorial(k))*1/(factorial(-k))",
+ # "1/(factorial(k)*factorial(-k))",
+ "1/(k!*(-k)!)",
+
+ "binomial(n,0)",
+ "1",
+
+ "binomial(-1,k)",
+ "0",
+
+ "binomial(n,-1)",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/ceiling.coffee b/node_modules/algebrite/tests/ceiling.coffee
new file mode 100644
index 0000000..6f346f0
--- /dev/null
+++ b/node_modules/algebrite/tests/ceiling.coffee
@@ -0,0 +1,76 @@
+test_ceiling = ->
+ run_test [
+ "ceiling(a)",
+ "ceiling(a)",
+
+ "ceiling(a+b)",
+ "ceiling(a+b)",
+
+ "ceiling(5/2)",
+ "3",
+
+ "ceiling(4/2)",
+ "2",
+
+ "ceiling(3/2)",
+ "2",
+
+ "ceiling(2/2)",
+ "1",
+
+ "ceiling(1/2)",
+ "1",
+
+ "ceiling(0/2)",
+ "0",
+
+ "ceiling(-1/2)",
+ "0",
+
+ "ceiling(-2/2)",
+ "-1",
+
+ "ceiling(-3/2)",
+ "-1",
+
+ "ceiling(-4/2)",
+ "-2",
+
+ "ceiling(-5/2)",
+ "-2",
+
+ "ceiling(5/2.0)",
+ "3.0",
+
+ "ceiling(4/2.0)",
+ "2.0",
+
+ "ceiling(3/2.0)",
+ "2.0",
+
+ "ceiling(2/2.0)",
+ "1.0",
+
+ "ceiling(1/2.0)",
+ "1.0",
+
+ "ceiling(0.0)",
+ "0.0",
+
+ "ceiling(-1/2.0)",
+ "0.0",
+
+ "ceiling(-2/2.0)",
+ "-1.0",
+
+ "ceiling(-3/2.0)",
+ "-1.0",
+
+ "ceiling(-4/2.0)",
+ "-2.0",
+
+ "ceiling(-5/2.0)",
+ "-2.0",
+ ]
+
+
diff --git a/node_modules/algebrite/tests/check.coffee b/node_modules/algebrite/tests/check.coffee
new file mode 100644
index 0000000..66177c8
--- /dev/null
+++ b/node_modules/algebrite/tests/check.coffee
@@ -0,0 +1,87 @@
+test_check = ->
+ if DEBUG then console.log "test_check ----------------------------"
+
+ run_test [
+
+ # note how check can turn an assignment
+ # into a test, so in this case a is not
+ # assigned anything
+
+ "check(a=b)",
+ "check(a=b)",
+
+ "a",
+ "a",
+
+ "check(a)",
+ "check(a)",
+
+ "check(a=a)",
+ "1",
+
+ "check(a==a)",
+ "1",
+
+ "check(a===a)",
+ "check(a=== ? a)\nStop: syntax error",
+
+ "check(a+1=a)",
+ "0",
+
+ "check(a+1==a)",
+ "0",
+
+ "check(a+1===a)",
+ "check(a+1=== ? a)\nStop: syntax error",
+
+ "check(1)",
+ "1",
+
+ "check(0)",
+ "0",
+
+ "check(and(1,0))",
+ "0",
+
+ "check(and(1,1))",
+ "1",
+
+ # if passed a value, check if non-zero
+ "check(pi)",
+ "1",
+
+ "check(2)",
+ "1",
+
+ "check(-2)",
+ "1",
+
+ "check(sqrt(2))",
+ "1",
+
+ "check(sqrt(-1))",
+ "1",
+
+ "check(sqrt(pi/4)-sqrt(i))",
+ "1",
+
+ "check(1+i)",
+ "1",
+
+
+ "check([0,0])",
+ "0",
+
+ "check([1,2])",
+ "1",
+
+ "check([1+i,2])",
+ "1",
+
+ "check([a,2])",
+ "check([a,2])",
+
+ "check(1-i)",
+ "1",
+
+ ]
diff --git a/node_modules/algebrite/tests/choose.coffee b/node_modules/algebrite/tests/choose.coffee
new file mode 100644
index 0000000..d9d7c42
--- /dev/null
+++ b/node_modules/algebrite/tests/choose.coffee
@@ -0,0 +1,21 @@
+test_choose = ->
+ run_test [
+ "choose(52,5)",
+ "2598960",
+
+ "choose(n,k)",
+ "n!/(k!*(-k+n)!)",
+
+ "choose(0,k)",
+ "1/(k!*(-k)!)",
+
+ "choose(n,0)",
+ "1",
+
+ "choose(-1,k)",
+ "0",
+
+ "choose(n,-1)",
+ "0",
+ ]
+
diff --git a/node_modules/algebrite/tests/circexp.coffee b/node_modules/algebrite/tests/circexp.coffee
new file mode 100644
index 0000000..73f771c
--- /dev/null
+++ b/node_modules/algebrite/tests/circexp.coffee
@@ -0,0 +1,30 @@
+test_circexp = ->
+ run_test [
+
+ "circexp(cos(x))",
+ "1/2*exp(-i*x)+1/2*exp(i*x)",
+
+ "circexp(sin(x))",
+ "1/2*i*exp(-i*x)-1/2*i*exp(i*x)",
+
+ "circexp(tan(x))",
+ "i*exp(-i*x)/(exp(-i*x)+exp(i*x))-i*exp(i*x)/(exp(-i*x)+exp(i*x))",
+
+ "circexp(cosh(x))",
+ "1/2*exp(x)+1/2*exp(-x)",
+
+ "circexp(sinh(x))",
+ "1/2*exp(x)-1/2*exp(-x)",
+
+ "circexp(tanh(x))",
+ "-1/(1+exp(2*x))+exp(2*x)/(1+exp(2*x))",
+
+ "circexp([cos(x),sin(x)])",
+ "[1/2*exp(-i*x)+1/2*exp(i*x),1/2*i*exp(-i*x)-1/2*i*exp(i*x)]",
+
+ "circexp(cos(x)*sin(x))-expcos(x)*expsin(x)",
+ "0",
+
+ "circexp(i*2^(1/4)*sin(1/8*pi)+2^(1/4)*cos(1/8*pi))",
+ "2^(1/4)*exp(1/8*i*pi)",
+ ]
diff --git a/node_modules/algebrite/tests/clearall.coffee b/node_modules/algebrite/tests/clearall.coffee
new file mode 100644
index 0000000..ae47e62
--- /dev/null
+++ b/node_modules/algebrite/tests/clearall.coffee
@@ -0,0 +1,15 @@
+test_clearall = ->
+ run_test [
+
+ "a = 1",
+ "",
+
+ "a",
+ "1",
+
+ "clearall",
+ "",
+
+ "a",
+ "a",
+ ]
diff --git a/node_modules/algebrite/tests/clock.coffee b/node_modules/algebrite/tests/clock.coffee
new file mode 100644
index 0000000..367f12c
--- /dev/null
+++ b/node_modules/algebrite/tests/clock.coffee
@@ -0,0 +1,31 @@
+test_clock = ->
+ run_test [
+
+ "clock(exp(i pi/3))",
+ "(-1)^(1/3)",
+
+ "clock(exp(-i pi/3))",
+ #"-(-1)^(2/3)",
+ "1/(-1)^(1/3)",
+
+ "rect(clock(3+4*i))", # needs sin(arctan(x)) and cos(arctan(x))
+ "3+4*i",
+
+ "clock((-108+108*(-1)^(1/2)*3^(1/2))^(1/3))",
+ "6*(-1)^(2/9)",
+
+ # TODO
+ # the changes to abs/mag of Jan 2017
+ # make it so a ends up as absolute value
+ # (-1)^(1/5)*abs(a)
+ # Rather, clock should somehow recognize
+ # that this is already very close to clock
+ # form and just replace the exponential with
+ # the power of -1
+ # Note that this was working before the Jan 2017
+ # changes because abs/mag were blissfully
+ # transforming abs(any_variable) -> any_variable
+ #"clock(exp(1/5*i*pi)*a)",
+ #"(-1)^(1/5)*a",
+
+ ]
diff --git a/node_modules/algebrite/tests/coeff.coffee b/node_modules/algebrite/tests/coeff.coffee
new file mode 100644
index 0000000..2767375
--- /dev/null
+++ b/node_modules/algebrite/tests/coeff.coffee
@@ -0,0 +1,27 @@
+test_coeff = ->
+ run_test [
+
+ "coeff(40*x^3+30*x^2+20*x+10,3)",
+ "40",
+
+ "coeff(40*x^3+30*x^2+20*x+10,2)",
+ "30",
+
+ "coeff(40*x^3+30*x^2+20*x+10,1)",
+ "20",
+
+ "coeff(40*x^3+30*x^2+20*x+10,0)",
+ "10",
+
+ "coeff(a*t^3+b*t^2+c*t+d,t,3)",
+ "a",
+
+ "coeff(a*t^3+b*t^2+c*t+d,t,2)",
+ "b",
+
+ "coeff(a*t^3+b*t^2+c*t+d,t,1)",
+ "c",
+
+ "coeff(a*t^3+b*t^2+c*t+d,t,0)",
+ "d",
+ ]
diff --git a/node_modules/algebrite/tests/cofactor.coffee b/node_modules/algebrite/tests/cofactor.coffee
new file mode 100644
index 0000000..9286cbb
--- /dev/null
+++ b/node_modules/algebrite/tests/cofactor.coffee
@@ -0,0 +1,18 @@
+test_cofactor = ->
+ run_test [
+
+ "cofactor([[1,2],[3,4]],1,1)",
+ "4",
+
+ "cofactor([[1,2],[3,4]],1,2)",
+ "-3",
+
+ "cofactor([[1,2],[3,4]],2,1)",
+ "-2",
+
+ "cofactor([[1,2],[3,4]],2,2)",
+ "1",
+
+ "cofactor([[1,2,3],[4,5,6],[7,8,9]],1,2)",
+ "6",
+ ]
diff --git a/node_modules/algebrite/tests/condense.coffee b/node_modules/algebrite/tests/condense.coffee
new file mode 100644
index 0000000..a1bf535
--- /dev/null
+++ b/node_modules/algebrite/tests/condense.coffee
@@ -0,0 +1,28 @@
+test_condense = ->
+ run_test [
+
+ "condense(a/(a+b)+b/(a+b))",
+ "1",
+
+ "psi(n) = exp(-r/n) laguerre(2r/n,n-1,1)",
+ "",
+
+ "psi(3)",
+ "3*exp(-1/3*r)-2*r*exp(-1/3*r)+2/9*r^2*exp(-1/3*r)",
+
+ "condense(last)",
+ "exp(-1/3*r)*(3-2*r+2/9*r^2)",
+
+ "psi()=psi",
+ "",
+
+ # test case H
+
+ "condense(-3 exp(-1/3 r + i phi) cos(theta) - 6 exp(-1/3 r + i phi) cos(theta) sin(theta)^2 + 12 exp(-1/3 r + i phi) cos(theta)^3)",
+ "3*exp(-1/3*r+i*phi)*(-1+4*cos(theta)^2-2*sin(theta)^2)*cos(theta)",
+
+ "condense(7208+2736*5^(1/2))",
+ "8*(901+342*5^(1/2))",
+
+
+ ]
diff --git a/node_modules/algebrite/tests/contract.coffee b/node_modules/algebrite/tests/contract.coffee
new file mode 100644
index 0000000..357e314
--- /dev/null
+++ b/node_modules/algebrite/tests/contract.coffee
@@ -0,0 +1,46 @@
+test_contract = ->
+ run_test [
+ "contract(0)",
+ "0",
+
+ "contract(0.0)",
+ "0",
+
+ # this is same as contract(hilbertmatrix(20))
+ # we are testing this because some versions of bigInt library
+ # seemed to give problems with some gcds involved in these
+ # additions of fractions
+ "409741429887649/166966608033225 + 1/39",
+ "414022624965424/166966608033225",
+
+ # this is same as contract(hilbertmatrix(21))
+ # we are testing this because some versions of bigInt library
+ # seemed to give problems with some gcds involved in these
+ # additions of fractions
+ "414022624965424/166966608033225 + 1/41",
+ "17141894231615609/6845630929362225",
+
+ "contract(hilbert(50))",
+ "3200355699626285671281379375916142064964/1089380862964257455695840764614254743075",
+
+ "contract([[a,b],[c,d]])",
+ "a+d",
+
+ "contract([[1,2],[3,4]],1,2)",
+ "5",
+
+ "A=[[a11,a12],[a21,a22]]",
+ "",
+
+ "B=[[b11,b12],[b21,b22]]",
+ "",
+
+ "contract(outer(A,B),2,3)",
+ "[[a11*b11+a12*b21,a11*b12+a12*b22],[a21*b11+a22*b21,a21*b12+a22*b22]]",
+
+ "A=quote(A)",
+ "",
+
+ "B=quote(B)",
+ "",
+ ]
diff --git a/node_modules/algebrite/tests/cos.coffee b/node_modules/algebrite/tests/cos.coffee
new file mode 100644
index 0000000..dfb8684
--- /dev/null
+++ b/node_modules/algebrite/tests/cos.coffee
@@ -0,0 +1,228 @@
+test_cos = ->
+ run_test [
+
+ "cos(x)",
+ "cos(x)",
+
+ "cos(-x)",
+ "cos(x)",
+
+ "cos(b-a)",
+ "cos(a-b)",
+
+ # check against the floating point math library
+
+ "f(a,x)=1+cos(float(a/360*2*pi))-float(x)+cos(a/360*2*pi)-x",
+ "",
+
+ "f(0,1)", # 0
+ "1.0",
+
+ "f(90,0)", # 90
+ "1.0",
+
+ "f(180,-1)", # 180
+ "1.0",
+
+ "f(270,0)", # 270
+ "1.0",
+
+ "f(360,1)", # 360
+ "1.0",
+
+ "f(-90,0)", # -90
+ "1.0",
+
+ "f(-180,-1)", # -180
+ "1.0",
+
+ "f(-270,0)", # -270
+ "1.0",
+
+ "f(-360,1)", # -360
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(45,sqrt(2)/2)", # 45
+ "1.000000...",
+
+ "f(135,-sqrt(2)/2)", # 135
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(225,-sqrt(2)/2)", # 225
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(315,sqrt(2)/2)", # 315
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-45,sqrt(2)/2)", # -45
+ "1.000000...",
+
+ "f(-135,-sqrt(2)/2)", # -135
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-225,-sqrt(2)/2)", # -225
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-315,sqrt(2)/2)", # -315
+ "1.000000...",
+
+ "f(30,sqrt(3)/2)", # 30
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(150,-sqrt(3)/2)", # 150
+ "1.000000...",
+
+ "f(210,-sqrt(3)/2)", # 210
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(330,sqrt(3)/2)", # 330
+ "1.000000...",
+
+ "f(-30,sqrt(3)/2)", # -30
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-150,-sqrt(3)/2)", # -150
+ "1.000000...",
+
+ "f(-210,-sqrt(3)/2)", # -210
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-330,sqrt(3)/2)", # -330
+ "1.000000...",
+
+ "f(60,1/2)", # 60
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(120,-1/2)", # 120
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(240,-1/2)", # 240
+ "1.000000...",
+
+ "f(300,1/2)", # 300
+ "1.0",
+
+ "f(-60,1/2)", # -60
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-120,-1/2)", # -120
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-240,-1/2)", # -240
+ "1.000000...",
+
+ "f(-300,1/2)", # -300
+ "1.0",
+
+ "f=quote(f)",
+ "",
+
+ "cos(arccos(x))",
+ "x",
+
+ # bug fix for version 119
+
+ "cos(1/12*pi)",
+ "cos(1/12*pi)",
+
+ "cos(arctan(4/3))",
+ "3/5",
+
+ "cos(-arctan(4/3))",
+ "3/5",
+
+ # phase
+
+ "cos(x-8/2*pi)",
+ "cos(x)",
+
+ "cos(x-7/2*pi)",
+ "-sin(x)",
+
+ "cos(x-6/2*pi)",
+ "-cos(x)",
+
+ "cos(x-5/2*pi)",
+ "sin(x)",
+
+ "cos(x-4/2*pi)",
+ "cos(x)",
+
+ "cos(x-3/2*pi)",
+ "-sin(x)",
+
+ "cos(x-2/2*pi)",
+ "-cos(x)",
+
+ "cos(x-1/2*pi)",
+ "sin(x)",
+
+ "cos(x+0/2*pi)",
+ "cos(x)",
+
+ "cos(x+1/2*pi)",
+ "-sin(x)",
+
+ "cos(x+2/2*pi)",
+ "-cos(x)",
+
+ "cos(x+3/2*pi)",
+ "sin(x)",
+
+ "cos(x+4/2*pi)",
+ "cos(x)",
+
+ "cos(x+5/2*pi)",
+ "-sin(x)",
+
+ "cos(x+6/2*pi)",
+ "-cos(x)",
+
+ "cos(x+7/2*pi)",
+ "sin(x)",
+
+ "cos(x+8/2*pi)",
+ "cos(x)",
+ ]
diff --git a/node_modules/algebrite/tests/cosh.coffee b/node_modules/algebrite/tests/cosh.coffee
new file mode 100644
index 0000000..9cbadc0
--- /dev/null
+++ b/node_modules/algebrite/tests/cosh.coffee
@@ -0,0 +1,11 @@
+test_cosh = ->
+ run_test [
+ "cosh(x)",
+ "cosh(x)",
+
+ "cosh(0)",
+ "1",
+
+ "cosh(arccosh(x))",
+ "x",
+ ]
diff --git a/node_modules/algebrite/tests/defint.coffee b/node_modules/algebrite/tests/defint.coffee
new file mode 100644
index 0000000..3c11b2d
--- /dev/null
+++ b/node_modules/algebrite/tests/defint.coffee
@@ -0,0 +1,55 @@
+test_defint = ->
+ run_test [
+ "defint(x^2,y,0,sqrt(1-x^2),x,-1,1)",
+ "1/8*pi",
+
+ # from the eigenmath manual
+
+ "z=2",
+ "",
+
+ "P=[x,y,z]",
+ "",
+
+ "a=abs(cross(d(P,x),d(P,y)))",
+ "",
+
+ "defint(a,y,-sqrt(1-x^2),sqrt(1-x^2),x,-1,1)",
+ "pi",
+
+ # from the eigenmath manual
+
+ "z=x^2+2y",
+ "",
+
+ "P=[x,y,z]",
+ "",
+
+ "a=abs(cross(d(P,x),d(P,y)))",
+ "",
+
+ "defint(a,x,0,1,y,0,1)",
+ "3/2+5/8*log(5)",
+
+ # from the eigenmath manual
+
+ "x=u*cos(v)",
+ "",
+
+ "y=u*sin(v)",
+ "",
+
+ "z=v",
+ "",
+
+ "S=[x,y,z]",
+ "",
+
+ "a=abs(cross(d(S,u),d(S,v)))",
+ "",
+
+ "defint(a,u,0,1,v,0,3pi)",
+ "3/2*pi*log(1+2^(1/2))+3*pi/(2^(1/2))",
+ ]
+
+
diff --git a/node_modules/algebrite/tests/denominator.coffee b/node_modules/algebrite/tests/denominator.coffee
new file mode 100644
index 0000000..51805c3
--- /dev/null
+++ b/node_modules/algebrite/tests/denominator.coffee
@@ -0,0 +1,23 @@
+test_denominator = ->
+ run_test [
+
+ "denominator(2/3)",
+ "3",
+
+ "denominator(x)",
+ "1",
+
+ "denominator(1/x)",
+ "x",
+
+ "denominator(a+b)",
+ "1",
+
+ "denominator(1/a+1/b)",
+ "a*b",
+
+ # denominator function expands
+
+ "denominator(1/(x-1)/(x-2))",
+ "x^2-3*x+2",
+ ]
diff --git a/node_modules/algebrite/tests/dependencies.coffee b/node_modules/algebrite/tests/dependencies.coffee
new file mode 100644
index 0000000..f4796b5
--- /dev/null
+++ b/node_modules/algebrite/tests/dependencies.coffee
@@ -0,0 +1,781 @@
+test_dependencies = ->
+ do_clearall()
+
+ testResult = findDependenciesInScript('1')
+ if testResult[0] == "All local dependencies: . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: " and
+ testResult[1] == "1" and
+ testResult[2] == ""
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 1 expected: " + testResult
+
+ do_clearall()
+
+ # check that floats in code are expressed with maximum precision -------------------
+ testResult = findDependenciesInScript('a = float(1/3)')
+ if testResult[0] == "All local dependencies: variable a depends on: ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = 0.3333333333333333;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 2 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('a = float(10^50)')
+ if testResult[0] == "All local dependencies: variable a depends on: ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = 1e+50;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 3 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = x+1\n g = f\n h = g\n f = g')
+ if testResult[0] == "All local dependencies: variable f depends on: x, g, ; variable g depends on: f, ; variable h depends on: g, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: x, ; f --> g --> ... then f again, variable g depends on: x, ; g --> f --> ... then g again, variable h depends on: x, ; h --> g --> f --> ... then g again, " and
+ testResult[1] == "" and
+ testResult[2] == "// f is part of a cyclic dependency, no code generated.\n// g is part of a cyclic dependency, no code generated.\n// h is part of a cyclic dependency, no code generated."
+ else
+ console.log "fail dependency test 4 expected: " + testResult
+
+ do_clearall()
+
+ if findDependenciesInScript('f = x+1\n g = f + y\n h = g')[0] == "All local dependencies: variable f depends on: x, ; variable g depends on: f, y, ; variable h depends on: g, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: x, ; variable g depends on: x, y, ; variable h depends on: x, y, ; "
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 5"
+
+ do_clearall()
+
+ if findDependenciesInScript('g = h(x,y)')[0] == "All local dependencies: variable g depends on: h, x, y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable g depends on: h, x, y, ; "
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 6"
+
+ do_clearall()
+
+ if findDependenciesInScript('f(x,y) = k')[0] == "All local dependencies: variable f depends on: 'x, 'y, k, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: 'x, 'y, k, ; "
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 7"
+
+ do_clearall()
+
+ if findDependenciesInScript('x = z\n f(x,y) = k')[0] == "All local dependencies: variable x depends on: z, ; variable f depends on: 'x, 'y, k, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: z, ; variable f depends on: 'x, 'y, k, ; "
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 8"
+
+ do_clearall()
+
+ if findDependenciesInScript('x = z\n g = f(x,y)')[0] == "All local dependencies: variable x depends on: z, ; variable g depends on: f, x, y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: z, ; variable g depends on: f, z, y, ; "
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 9"
+
+ do_clearall()
+
+ if findDependenciesInScript('x = 1\n x = y\n x = z')[0] == "All local dependencies: variable x depends on: y, z, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: y, z, ; "
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 10"
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = y*y')
+ if testResult[0] == "All local dependencies: variable x depends on: y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: y, ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = function (y) { return ( Math.pow(y, 2) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 11 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = e*e')
+ if testResult[0] == "All local dependencies: variable x depends on: ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = Math.exp(2);"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 12 expected: " + testResult
+
+ testResult = findDependenciesInScript('x = e')
+ if testResult[0] == "All local dependencies: variable x depends on: ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = Math.E;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 13 expected: " + testResult
+
+ testResult = findDependenciesInScript('x = -sqrt(2)/2')
+ if testResult[0] == "All local dependencies: variable x depends on: ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = -1/2*Math.SQRT2;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 14 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = 2^(1/2-a)*2^a/10')
+ if testResult[0] == "All local dependencies: variable x depends on: a, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: a, ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = 1/10*Math.SQRT2;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 15 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = rationalize(t*y/(t+y)+2*t^2*y*(2*t+y)^(-2))')
+ if testResult[0] == "All local dependencies: variable x depends on: t, y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: t, y, ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = function (t, y) { return ( t*y*(6*Math.pow(t, 2)+Math.pow(y, 2)+6*t*y)/((t+y)*Math.pow((2*t+y), 2)) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 16 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = abs((a+i*b)/(c+i*d))')
+ if testResult[0] == "All local dependencies: variable x depends on: a, b, c, d, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: a, b, c, d, ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = function (a, b, c, d) { return ( Math.sqrt(Math.pow(a, 2)+Math.pow(b, 2))/(Math.sqrt(Math.pow(c, 2)+Math.pow(d, 2))) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 17 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = sin(1/10)^2 + cos(1/10)^2 + y')
+ if testResult[0] == "All local dependencies: variable x depends on: y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: y, ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = function (y) { return ( 1+y ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 18 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = y + cos(1) + sin(1)')
+ if testResult[0] == "All local dependencies: variable x depends on: y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: y, ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = function (y) { return ( y+Math.cos(1)+Math.sin(1) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 19 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = a + arccos(b) + arcsin(c)')
+ if testResult[0] == "All local dependencies: variable x depends on: a, arccos, b, arcsin, c, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: a, arccos, b, arcsin, c, ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = function (a, b, c) { return ( a+Math.acos(b)+Math.asin(c) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 20 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('x = sin(1/10)^2 + cos(1/10)^2')
+ if testResult[0] == "All local dependencies: variable x depends on: ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable x depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "x = 1;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 21 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('a = unit(b) + c')
+ if testResult[0] == "All local dependencies: variable a depends on: b, c, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: b, c, ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = function (c, b) { return ( c+identity(b) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 22 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f(x) = x * x')
+ if testResult[0] == "All local dependencies: variable f depends on: 'x, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: 'x, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (x) { return ( x*x ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 23 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f(x) = x * x + g(y)')
+ if testResult[0] == "All local dependencies: variable f depends on: 'x, g, y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: 'x, g, y, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (g, y, x) { return ( g(y)+Math.pow(x, 2) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 24 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('y = 2\nf(x) = x * x + g(y)')
+ if testResult[0] == "All local dependencies: variable y depends on: ; variable f depends on: 'x, g, y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable y depends on: ; variable f depends on: 'x, g, ; " and
+ testResult[1] == "" and
+ testResult[2] == "y = 2;\nf = function (g, x) { return ( g(2)+Math.pow(x, 2) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 25 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('g(x) = x + 2\ny = 2\nf(x) = x * x + g(y)')
+ if testResult[0] == "All local dependencies: variable g depends on: 'x, ; variable y depends on: ; variable f depends on: 'x, g, y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable g depends on: 'x, ; variable y depends on: ; variable f depends on: 'x, ; " and
+ testResult[1] == "" and
+ testResult[2] == "g = function (x) { return ( 2+x ); }\ny = 2;\nf = function (x) { return ( 4+Math.pow(x, 2) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 26 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('g(x) = x + 2\nf(x) = x * x + g(y)')
+ if testResult[0] == "All local dependencies: variable g depends on: 'x, ; variable f depends on: 'x, g, y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable g depends on: 'x, ; variable f depends on: 'x, y, ; " and
+ testResult[1] == "" and
+ testResult[2] == "g = function (x) { return ( 2+x ); }\nf = function (y, x) { return ( 2+y+Math.pow(x, 2) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 27 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ ###
+ testResult = findDependenciesInScript('g(x) = f(x)\nf(x)=g(x)')
+ if testResult[0] == "All local dependencies: variable g depends on: 'x, f, x, ; variable f depends on: 'x, g, x, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable g depends on: 'x, ; g --> f --> ... then g again, variable f depends on: 'x, x, ; f --> g --> ... then f again, " and
+ testResult[1] == "" and
+ testResult[2] == "// g is part of a cyclic dependency, no code generated.\n// f is part of a cyclic dependency, no code generated."
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 28 expected: " + testResult
+
+ do_clearall()
+ ###
+
+ testResult = findDependenciesInScript('piApprox = sum((-1)^k * (1/(2*k + 1)),k,0,iterations)*4')
+ if testResult[0] == "All local dependencies: variable piApprox depends on: iterations, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable piApprox depends on: iterations, ; " and
+ testResult[1] == "" and
+ testResult[2] == "piApprox = function (iterations) { return ( 4*(function(){ var k; var holderSum = 0; var lowerlimit = 0; var upperlimit = iterations; for (k = lowerlimit; k < upperlimit; k++) { holderSum += Math.pow((-1), k)/(2*k+1); } return holderSum;})() ); }" and
+ testResult[3] == "piApprox(iterations) = 4\\sum_{k=0}^{iterations}{\\frac{(-1)^k}{(2k+1)}}"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 29 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+ console.log "testResult[3]: " + testResult[3]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('piApprox = 2*product(4*k^2/(4*k^2-1),k,1,iterations)')
+ if testResult[0] == "All local dependencies: variable piApprox depends on: iterations, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable piApprox depends on: iterations, ; " and
+ testResult[1] == "" and
+ testResult[2] == "piApprox = function (iterations) { return ( 2*(function(){ var k; var holderProduct = 1; var lowerlimit = 1; var upperlimit = iterations; for (k = lowerlimit; k < upperlimit; k++) { holderProduct *= 4*Math.pow(k, 2)/(4*Math.pow(k, 2)-1); } return holderProduct;})() ); }" and
+ testResult[3] == "piApprox(iterations) = 2\\prod_{k=1}^{iterations}{\\frac{4k^2}{(4k^2-1)}}"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 30 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+ console.log "testResult[3]: " + testResult[3]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = roots(a*x^2 + b*x + c, x)')
+ if testResult[0] == "All local dependencies: variable f depends on: a, b, c, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: a, b, c, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (a, b, c) { return ( [-1/2*(Math.sqrt(Math.pow(b, 2)/(Math.pow(a, 2))-4*c/a)+b/a),1/2*(Math.sqrt(Math.pow(b, 2)/(Math.pow(a, 2))-4*c/a)-b/a)] ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 31 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = roots(a*x^2 + b*x + c)')
+ if testResult[0] == "All local dependencies: variable f depends on: a, b, c, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: a, b, c, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (a, b, c) { return ( [-1/2*(Math.sqrt(Math.pow(b, 2)/(Math.pow(a, 2))-4*c/a)+b/a),1/2*(Math.sqrt(Math.pow(b, 2)/(Math.pow(a, 2))-4*c/a)-b/a)] ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 32 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = roots(integral(a*x + b))')
+ if testResult[0] == "All local dependencies: variable f depends on: a, b, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: a, b, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (a, b) { return ( [0,-2*b/a] ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 33 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = roots(defint(a*x + y,y,0,1))')
+ if testResult[0] == "All local dependencies: variable f depends on: a, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: a, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (a) { return ( -1/(2*a) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 34 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = roots(defint(a*x + y + z,y,0,1, z, 0, 1))')
+ if testResult[0] == "All local dependencies: variable f depends on: a, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: a, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (a) { return ( -1/a ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 35 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = defint(2*x - 3*y,x,0,2*y)')
+ if testResult[0] == "All local dependencies: variable f depends on: y, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: y, ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = function (y) { return ( -2*Math.pow(y, 2) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 36 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('f = defint(12 - x^2 - (y^2)/2,x,0,2,y,0,3)')
+ if testResult[0] == "All local dependencies: variable f depends on: ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable f depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "f = 55;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 37 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ # this example checks that functions are not meddled with,
+ # in particular that in the function body, the variables
+ # bound by the parameters remain "separate" from previous
+ # variables with the same name.
+ testResult = findDependenciesInScript('a = 2\nf(a) = a+1+b')
+ if testResult[0] == "All local dependencies: variable a depends on: ; variable f depends on: 'a, b, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: ; variable f depends on: 'a, b, ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = 2;\nf = function (a, b) { return ( 1+a+b ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 38 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ # similar as test above but this time we are not
+ # defining a function, so things are a bit different.
+ testResult = findDependenciesInScript('a = 2\nf = a+1')
+ if testResult[0] == "All local dependencies: variable a depends on: ; variable f depends on: a, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: ; variable f depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = 2;\nf = 3;"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 39 expected: " + testResult
+
+ do_clearall()
+
+ # similar as test above but this time we do a
+ # trick with the quote to see whether we
+ # get confused with the indirection
+ testResult = findDependenciesInScript('a := b\nf = a+1')
+ if testResult[0] == "All local dependencies: variable a depends on: b, ; variable f depends on: a, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: b, ; variable f depends on: b, ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = function (b) { return ( b ); }\nf = function (b) { return ( 1+b ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 40 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ # another tricky case of indirection through quote
+ testResult = findDependenciesInScript('a := b\nf(a) = a+1')
+ if testResult[0] == "All local dependencies: variable a depends on: b, ; variable f depends on: 'a, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: b, ; variable f depends on: 'a, ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = function (b) { return ( b ); }\nf = function (a) { return ( 1+a ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 41 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ # reassignment
+ testResult = findDependenciesInScript('b = 1\nb=a+b+c')
+ if testResult[0] == "All local dependencies: variable b depends on: a, c, ; . Symbols with reassignments: b, . Symbols in expressions without assignments: . All dependencies recursively: variable b depends on: a, c, ; " and
+ testResult[1] == "" and
+ testResult[2] == "b = function (a, c) { return ( 1+a+c ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 42 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ # reassignment
+ testResult = findDependenciesInScript('a = a+1')
+ if testResult[0] == "All local dependencies: variable a depends on: ; . Symbols with reassignments: a, . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: ; " and
+ testResult[1] == "" and
+ testResult[2] == "" and
+ testResult[5] == "Error: Stop: recursive evaluation of symbols: a -> a"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 43 expected: " + testResult
+
+ do_clearall()
+
+ # reassignment
+ testResult = computeDependenciesFromAlgebra('pattern(a,b)\nc= d\na=a+1')
+ if testResult.affectsVariables.length is 3 and
+ testResult.affectsVariables.indexOf("c") != -1 and
+ testResult.affectsVariables.indexOf("a") != -1 and
+ testResult.affectsVariables.indexOf("PATTERN_DEPENDENCY") != -1 and
+ testResult.affectedBy.length is 3 and
+ testResult.affectedBy.indexOf("d") != -1 and
+ testResult.affectedBy.indexOf("a") != -1 and
+ testResult.affectedBy.indexOf("PATTERN_DEPENDENCY") != -1
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 44 expected: " + testResult
+
+ do_clearall()
+
+ testResult = computeDependenciesFromAlgebra('PCA(M) = eig(Mᵀ⋅M)')
+ if testResult.affectsVariables.length is 1 and
+ testResult.affectsVariables.indexOf("PCA") != -1 and
+ testResult.affectsVariables.indexOf("PATTERN_DEPENDENCY") == -1 and
+ testResult.affectedBy.length is 1 and
+ testResult.affectedBy.indexOf("PATTERN_DEPENDENCY") != -1
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 45 expected: " + testResult
+
+ do_clearall()
+
+ testResult = computeDependenciesFromAlgebra('pattern(a_ᵀ⋅a_, cov(a_))')
+ if testResult.affectsVariables.length is 1 and
+ testResult.affectsVariables.indexOf("PATTERN_DEPENDENCY") != -1 and
+ testResult.affectedBy.length is 1 and
+ testResult.affectedBy.indexOf("PATTERN_DEPENDENCY") != -1
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 46 expected: " + testResult
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('a = b\nf = a+1')
+ if testResult[0] == "All local dependencies: variable a depends on: b, ; variable f depends on: a, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable a depends on: b, ; variable f depends on: b, ; " and
+ testResult[1] == "" and
+ testResult[2] == "a = function (b) { return ( b ); }\nf = function (b) { return ( 1+b ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 47 obtained: "
+ console.log "testResult[0]: " + testResult[0]
+ console.log "testResult[1]: " + testResult[1]
+ console.log "testResult[2]: " + testResult[2]
+
+ do_clearall()
+
+ testResult = findDependenciesInScript('PCA(M) = eig(cov(M))')
+ if testResult[0] == "All local dependencies: variable PCA depends on: 'M, ; . Symbols with reassignments: . Symbols in expressions without assignments: . All dependencies recursively: variable PCA depends on: 'M, ; " and
+ testResult[1] == "" and
+ testResult[2] == "PCA = function (M) { return ( eig(cov(M)) ); }"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency test 48 expected: " + testResult
+
+ do_clearall()
+
+ computeResultsAndJavaScriptFromAlgebra('PCA(M) = eig(Mᵀ⋅M)')
+ testResult = run('symbolsinfo')
+ if testResult.indexOf('AVOID_BINDING_TO_EXTERNAL_SCOPE_VALUE') != -1
+ console.log "fail dependency tests 49 found AVOID_BINDING_TO_EXTERNAL_SCOPE_VALUE"
+ else
+ console.log "ok dependency test"
+
+ do_clearall()
+
+ # this checks error handling in case of pattern and syntax error
+ # picked up during scanning.
+ computeResultsAndJavaScriptFromAlgebra('pattern(a_ᵀ⋅a_, cov(a_))')
+ computeResultsAndJavaScriptFromAlgebra('simplify(')
+ testResult = computeResultsAndJavaScriptFromAlgebra('PCA = Mᵀ·M')
+
+ if testResult.code == "PCA = function (M) { return ( cov(M) ); }" and
+ testResult.latexResult == "$$PCA(M) = cov(M)$$" and
+ testResult.result == "$$PCA(M) = cov(M)$$" and
+ testResult.dependencyInfo.affectedBy[0] == "M" and
+ testResult.dependencyInfo.affectedBy[1] == "PATTERN_DEPENDENCY" and
+ testResult.dependencyInfo.affectsVariables.length == 1 and
+ testResult.dependencyInfo.affectsVariables[0] == "PCA"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 50 Error handling 1"
+ console.log testResult
+ return
+
+ do_clearall()
+
+ testResult = computeResultsAndJavaScriptFromAlgebra('x + x + x')
+
+ if testResult.code == "" and
+ testResult.latexResult == "$$3x$$" and
+ testResult.result == "$$3x$$" and
+ testResult.dependencyInfo.affectedBy.length == 2 and
+ testResult.dependencyInfo.affectedBy[0] == "x" and
+ testResult.dependencyInfo.affectedBy[1] == "PATTERN_DEPENDENCY" and
+ testResult.dependencyInfo.affectsVariables.length == 0
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 51"
+
+ do_clearall()
+
+ computeResultsAndJavaScriptFromAlgebra('x = y + 2')
+ testResult = computeResultsAndJavaScriptFromAlgebra('x + x + x')
+
+ if testResult.code == "" and
+ testResult.latexResult == "$$3y+6$$" and
+ testResult.result == "$$3y+6$$" and
+ testResult.dependencyInfo.affectedBy.length == 2 and
+ testResult.dependencyInfo.affectedBy[0] == "x" and
+ testResult.dependencyInfo.affectedBy[1] == "PATTERN_DEPENDENCY" and
+ testResult.dependencyInfo.affectsVariables.length == 0
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 52"
+
+ do_clearall()
+
+ testResult = computeResultsAndJavaScriptFromAlgebra('[[0,1],[1,0]]')
+
+ if testResult.latexResult == "$$\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$$" and
+ testResult.result == "$$\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$$" and
+ testResult.dependencyInfo.affectsVariables.length == 0
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 53"
+
+ do_clearall()
+
+ testResult = computeResultsAndJavaScriptFromAlgebra('x = [[0,1],[1,0]]')
+
+ if testResult.code == "x = [[0,1],[1,0]];" and
+ testResult.latexResult == "$$x = \\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$$" and
+ testResult.result == "$$x = \\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}$$" and
+ testResult.dependencyInfo.affectedBy.length == 1 and
+ testResult.dependencyInfo.affectedBy[0] == "PATTERN_DEPENDENCY" and
+ testResult.dependencyInfo.affectsVariables.length == 1 and
+ testResult.dependencyInfo.affectsVariables[0] == "x"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 54"
+
+ do_clearall()
+
+ # a simple array lookup like this is turned into
+ # a function, which is slighly silly but
+ # it's orthogonal, this works also if instead of
+ # b we have an arbitrary non-trivial function
+ # on b, maybe even symbolic e.g. the round
+ # of the root of by = 6, i.e. round(root(by-6,y))
+ testResult = computeResultsAndJavaScriptFromAlgebra('x = a[b]')
+
+ if testResult.code == "x = function (a, b) { return ( a[b] ); }" and
+ testResult.latexResult == "$$x(a, b) = a[b]$$" and
+ testResult.result == "$$x(a, b) = a[b]$$" and
+ testResult.dependencyInfo.affectedBy.length == 3 and
+ testResult.dependencyInfo.affectedBy[0] == "a" and
+ testResult.dependencyInfo.affectedBy[1] == "b" and
+ testResult.dependencyInfo.affectedBy[2] == "PATTERN_DEPENDENCY" and
+ testResult.dependencyInfo.affectsVariables.length == 1 and
+ testResult.dependencyInfo.affectsVariables[0] == "x"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 55"
+
+ do_clearall()
+
+ testResult = computeResultsAndJavaScriptFromAlgebra('x = a ⋅ b')
+
+ if testResult.code == "x = function (a, b) { return ( dot(a, b) ); }" and
+ testResult.latexResult == "$$x(a, b) = a \\cdot b$$" and
+ testResult.result == "$$x(a, b) = a \\cdot b$$" and
+ testResult.dependencyInfo.affectedBy.length == 3 and
+ testResult.dependencyInfo.affectedBy[0] == "a" and
+ testResult.dependencyInfo.affectedBy[1] == "b" and
+ testResult.dependencyInfo.affectedBy[2] == "PATTERN_DEPENDENCY" and
+ testResult.dependencyInfo.affectsVariables.length == 1 and
+ testResult.dependencyInfo.affectsVariables[0] == "x"
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 56"
+
+ do_clearall()
+
+ # Here we test an actual sequence of invokations form the
+ # notebook.
+
+ code1 = 'pattern(a_ᵀ⋅a_, cov(a_))'
+ code2 = 'PCA = Mᵀ·M'
+
+ # invokation sequence, we check that the
+ # full evaluation of the last piece of code
+ # gives the correct result.
+ computeDependenciesFromAlgebra code1
+ computeDependenciesFromAlgebra code2
+ computeResultsAndJavaScriptFromAlgebra code1
+ computeDependenciesFromAlgebra code1
+ computeDependenciesFromAlgebra code2
+ res = computeResultsAndJavaScriptFromAlgebra code2
+
+ if res.code == 'PCA = function (M) { return ( cov(M) ); }' and
+ res.latexResult == '$$PCA(M) = cov(M)$$' and
+ res.dependencyInfo.affectsVariables.length == 1 and
+ res.dependencyInfo.affectsVariables[0] == 'PCA' and
+ res.dependencyInfo.affectedBy.length == 2 and
+ res.dependencyInfo.affectedBy[0] == 'M' and
+ res.dependencyInfo.affectedBy[1] == 'PATTERN_DEPENDENCY'
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 57"
+
+
+
+ do_clearall()
+
+ # overwriting a pattern, as seen from the notebook
+
+ code1 = 'pattern(a_ + a_, 42 * a_)'
+ code2 = 'pattern(a_ + a_, 21 * a_)'
+ code3 = 'f = x + x'
+
+ computeResultsAndJavaScriptFromAlgebra code1
+ computeResultsAndJavaScriptFromAlgebra code2
+ res = computeResultsAndJavaScriptFromAlgebra code3
+
+ if res.code == 'f = function (x) { return ( 21*x ); }' and
+ res.latexResult == '$$f(x) = 21x$$' and
+ res.dependencyInfo.affectsVariables.length == 1 and
+ res.dependencyInfo.affectsVariables[0] == 'f' and
+ res.dependencyInfo.affectedBy.length == 2 and
+ res.dependencyInfo.affectedBy[0] == 'x' and
+ res.dependencyInfo.affectedBy[1] == 'PATTERN_DEPENDENCY'
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 58"
+
+
+
+ do_clearall()
+
+ # tests
+
+ res = computeResultsAndJavaScriptFromAlgebra "f=test(x<1,-x-4,3<=x,x*x+7,120/x+5)"
+
+ if res.code == 'f = function (x) { return ( (function(){if (((x) < (1))){return (-x-4);} else if (((3) <= (x))){return (x*x+7);}else {return (120/x+5);}})() ); }' and
+ res.latexResult == '$$f(x) = \\left\\{ \\begin{array}{ll}{-x-4} & if & {x} < {1} \\\\\\\\{xx+7} & if & {3} \\leq {x} \\\\\\\\{\\frac{120}{x}+5} & otherwise \\end{array} \\right.$$' and
+ res.dependencyInfo.affectsVariables.length == 1 and
+ res.dependencyInfo.affectsVariables[0] == 'f' and
+ res.dependencyInfo.affectedBy.length == 2 and
+ res.dependencyInfo.affectedBy[0] == 'x' and
+ res.dependencyInfo.affectedBy[1] == 'PATTERN_DEPENDENCY'
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 59"
+
+
+ do_clearall()
+
+ # tests
+
+ res = computeResultsAndJavaScriptFromAlgebra "f=floor(x) + ceiling(x) + round(x)"
+
+ if res.code == 'f = function (x) { return ( ceiling(x)+floor(x)+round(x) ); }' and
+ res.latexResult == '$$f(x) = \\lceil {x} \\rceil + \\lfloor {x} \\rfloor +round(x)$$' and
+ res.dependencyInfo.affectsVariables.length == 1 and
+ res.dependencyInfo.affectsVariables[0] == 'f' and
+ res.dependencyInfo.affectedBy.length == 2 and
+ res.dependencyInfo.affectedBy[0] == 'x' and
+ res.dependencyInfo.affectedBy[1] == 'PATTERN_DEPENDENCY'
+ console.log "ok dependency test"
+ else
+ console.log "fail dependency tests 60"
+
+
+ do_clearall()
+
+ console.log "-- done dependency tests"
diff --git a/node_modules/algebrite/tests/derivative.coffee b/node_modules/algebrite/tests/derivative.coffee
new file mode 100644
index 0000000..271bd4d
--- /dev/null
+++ b/node_modules/algebrite/tests/derivative.coffee
@@ -0,0 +1,184 @@
+test_derivative = ->
+ run_test [
+
+ "x=quote(x)",
+ "",
+
+ "f=quote(f)",
+ "",
+
+ "g=quote(g)",
+ "",
+
+ "d(a,x)",
+ "0",
+
+ "d(x,x)",
+ "1",
+
+ "d(x^2,x)",
+ "2*x",
+
+ "d(log(x),x)",
+ "1/x",
+
+ "d(exp(x),x)",
+ "exp(x)",
+
+ "d(a^x,x)",
+ "a^x*log(a)",
+
+ "d(x^x,x)-(x^x+x^x*log(x))",
+ "0",
+
+ "d(log(x^2+5),x)-(2*x/(5+x^2))",
+ "0",
+
+ "d(d(f(x),x),y)",
+ "0",
+
+ "d(d(f(x),y),x)",
+ "0",
+
+ "d(d(f(y),x),y)",
+ "0",
+
+ "d(d(f(y),y),x)",
+ "0",
+
+ "d([x*y*z,y,x+z],[x,y,z])",
+ "[[y*z,x*z,x*y],[0,1,0],[1,0,1]]",
+
+ "d(x+z,[x,y,z])",
+ "[1,0,1]",
+
+ "d(cos(theta)^2,cos(theta))",
+ "2*cos(theta)",
+
+ "d(f())",
+ "d(f(),x)",
+
+ "d(x^2)",
+ "2*x",
+
+ "d(t^2)",
+ "2*t",
+
+ "d(t^2 x^2)",
+ "2*t^2*x",
+
+ # trig functions
+
+ "d(sin(x),x)-cos(x)",
+ "0",
+
+ "d(cos(x),x)+sin(x)",
+ "0",
+
+ "d(tan(x),x)-cos(x)^(-2)",
+ "0",
+
+ "d(arcsin(x),x)-1/sqrt(1-x^2)",
+ "0",
+
+ "d(arccos(x),x)+1/sqrt(1-x^2)",
+ "0",
+
+ "d(arctan(x),x)-1/(1+x^2)",
+ "0",
+
+ "d(arctan(y/x),x)",
+ "-y/(x^2+y^2)",
+
+ "d(arctan(y/x),y)",
+ "x/(x^2+y^2)",
+
+ # hyp functions
+
+ "d(sinh(x),x)-cosh(x)",
+ "0",
+
+ "d(cosh(x),x)-sinh(x)",
+ "0",
+
+ "d(tanh(x),x)-cosh(x)^(-2)",
+ "0",
+
+ "d(arcsinh(x),x)-1/sqrt(x^2+1)",
+ "0",
+
+ "d(arccosh(x),x)-1/sqrt(x^2-1)",
+ "0",
+
+ "d(arctanh(x),x)-1/(1-x^2)",
+ "0",
+
+ "d(sin(cos(x)),x)+cos(cos(x))*sin(x)",
+ "0",
+
+ "d(sin(x)^2,x)-2*sin(x)*cos(x)",
+ "0",
+
+ "d(sin(cos(x)),cos(x))-cos(cos(x))",
+ "0",
+
+ "d(abs(x),x)",
+ "sgn(x)",
+
+ "d(sgn(x),x)",
+ "2*dirac(x)",
+
+ # generic functions
+
+ "d(f(),x)",
+ "d(f(),x)",
+
+ "d(f(x),x)",
+ "d(f(x),x)",
+
+ "d(f(y),x)",
+ "0",
+
+ "d(g(f(x)),f(x))",
+ "d(g(f(x)),f(x))",
+
+ "d(g(f(x)),x)",
+ "d(g(f(x)),x)",
+
+ # other functions
+
+ "d(erf(x))-2*exp(-x^2)/sqrt(pi)",
+ "0",
+
+ # arg lists
+
+ "f=x^5*y^7",
+ "",
+
+ "d(f)",
+ "5*x^4*y^7",
+
+ "d(f,x)",
+ "5*x^4*y^7",
+
+ "d(f,x,0)",
+ "x^5*y^7",
+
+ "d(f,x,1)",
+ "5*x^4*y^7",
+
+ "d(f,x,2)",
+ "20*x^3*y^7",
+
+ "d(f,2)",
+ "20*x^3*y^7",
+
+ "d(f,2,y)",
+ "140*x^3*y^6",
+
+ "d(f,x,x,y,y)",
+ "840*x^3*y^5",
+
+ "f=quote(f)",
+ "",
+ ]
diff --git a/node_modules/algebrite/tests/dirac.coffee b/node_modules/algebrite/tests/dirac.coffee
new file mode 100644
index 0000000..c65386d
--- /dev/null
+++ b/node_modules/algebrite/tests/dirac.coffee
@@ -0,0 +1,5 @@
+test_dirac = ->
+ run_test [
+ "dirac(-x)",
+ "dirac(x)",
+ ]
diff --git a/node_modules/algebrite/tests/divisors.coffee b/node_modules/algebrite/tests/divisors.coffee
new file mode 100644
index 0000000..8159eae
--- /dev/null
+++ b/node_modules/algebrite/tests/divisors.coffee
@@ -0,0 +1,27 @@
+test_divisors = ->
+ run_test [
+
+ "divisors(12)",
+ "[1,2,3,4,6,12]",
+
+ "divisors(-12)",
+ "[1,2,3,4,6,12]",
+
+ "divisors(a)",
+ "[1,a]",
+
+ "divisors(-a)",
+ "[1,a]",
+
+ "divisors(+3*x+3)",
+ "[1,3,1+x,3+3*x]",
+
+ "divisors(+3*x-3)",
+ "[1,3,-3+3*x,-1+x]",
+
+ "divisors(-3*x+3)",
+ "[1,3,1-x,3-3*x]",
+
+ "divisors(-3*x-3)",
+ "[1,3,1+x,3+3*x]",
+ ]
diff --git a/node_modules/algebrite/tests/eigen.coffee b/node_modules/algebrite/tests/eigen.coffee
new file mode 100644
index 0000000..ef6e777
--- /dev/null
+++ b/node_modules/algebrite/tests/eigen.coffee
@@ -0,0 +1,63 @@
+test_eigen = ->
+ run_test [
+ "eigen(A)",
+ "Stop: eigen: argument is not a square matrix",
+
+ "eigenval(A)",
+ "eigenval(A)",
+
+ "eigenvec(A)",
+ "eigenvec(A)",
+
+ "eigen([1,2])",
+ "Stop: eigen: argument is not a square matrix",
+
+ "eigen([[1,2],[1,2]])",
+ "Stop: eigen: matrix is not symmetrical",
+
+ "eigenval([[1,1,1,1],[1,2,3,4],[1,3,6,10],[1,4,10,20]])",
+ "[[0.038016...,0.0,0.0,0.0],[0.0,0.453835...,0.0,0.0],[0.0,0.0,2.203446...,0.0],[0.0,0.0,0.0,26.304703...]]",
+
+ "eigenvec([[1,1,1,1],[1,2,3,4],[1,3,6,10],[1,4,10,20]])",
+ "[[0.308686...,-0.723090...,0.594551...,-0.168412...],[0.787275...,-0.163234...,-0.532107...,0.265358...],[0.530366...,0.640332...,0.391832...,-0.393897...],[0.060187...,0.201173...,0.458082...,0.863752...]]",
+ "eigen(hilbert(20))",
+ "",
+
+ # "contract" is the trace, but "trace" is a debugging flag in
+ # Algebrite/Eigenmath
+ # this one takes quite some time to finish because of the
+ # "dot(transpose(Q),D,Q))" calculation. Note that since
+ # D and Q are matrices of doubles, the whole result is a double.
+ # also note that the result gives "-0.000000...", that's why I put the abs there
+ # Note that this should be really "0" however, because of calculation errors,
+ # it doesn't test equal to "0", so we get to this result
+ "abs(contract(hilbert(20))-contract(dot(transpose(Q),D,Q)))",
+ "0.000000...",
+
+ "D=quote(D)",
+ "",
+
+ "Q=quote(Q)",
+ "",
+
+ "A=hilbert(3)",
+ "",
+
+ "eigen(A)",
+ "",
+
+ "D-eigenval(A)",
+ "[[0,0,0],[0,0,0],[0,0,0]]",
+
+ "Q-eigenvec(A)",
+ "[[0,0,0],[0,0,0],[0,0,0]]",
+
+ "A=quote(A)",
+ "",
+
+ "D=quote(D)",
+ "",
+
+ "Q=quote(Q)",
+ "",
+ ]
diff --git a/node_modules/algebrite/tests/erf.coffee b/node_modules/algebrite/tests/erf.coffee
new file mode 100644
index 0000000..766db29
--- /dev/null
+++ b/node_modules/algebrite/tests/erf.coffee
@@ -0,0 +1,32 @@
+test_erf = ->
+ run_test [
+
+ "erf(a)",
+ "erf(a)",
+
+ "erf(0.0) + 1",
+ "1.0",
+
+ "float(erf(0))",
+ "0.0",
+
+ "erf(0.0)",
+ "0.0",
+
+ "erf(-0.0)",
+ "0.0",
+
+ "erf(0)",
+ "0",
+
+ "erf(-0)",
+ "0",
+
+ "float(erf(0)) + 1",
+ "1.0",
+
+ "float(erf(1))",
+ "0.842701...",
+
+ ]
+
diff --git a/node_modules/algebrite/tests/erfc.coffee b/node_modules/algebrite/tests/erfc.coffee
new file mode 100644
index 0000000..2a9c150
--- /dev/null
+++ b/node_modules/algebrite/tests/erfc.coffee
@@ -0,0 +1,28 @@
+test_erfc = ->
+ run_test [
+
+ "erfc(a)",
+ "erfc(a)",
+
+ "erfc(0.0)",
+ "1.0",
+
+ "float(erfc(0))",
+ "1.0",
+
+ "erfc(0.0)",
+ "1.0",
+
+ "erfc(-0.0)",
+ "1.0",
+
+ "erfc(0)",
+ "1",
+
+ "erfc(-0)",
+ "1",
+
+ "float(erfc(1))",
+ "0.157299...",
+
+ ]
diff --git a/node_modules/algebrite/tests/exp.coffee b/node_modules/algebrite/tests/exp.coffee
new file mode 100644
index 0000000..51ef50d
--- /dev/null
+++ b/node_modules/algebrite/tests/exp.coffee
@@ -0,0 +1,13 @@
+test_exp = ->
+ run_test [
+
+ "exp(-3/4*i*pi)",
+ #"exp(-3/4*i*pi)",
+ "-1/2*2^(1/2)-1/2*i*2^(1/2)",
+
+ "simplify(exp(-3/4*i*pi))",
+ #"exp(-3/4*i*pi)",
+ #"-1/2*2^(1/2)-1/2*i*2^(1/2)",
+ "-(1+i)/(2^(1/2))",
+
+ ]
diff --git a/node_modules/algebrite/tests/expand.coffee b/node_modules/algebrite/tests/expand.coffee
new file mode 100644
index 0000000..7393f58
--- /dev/null
+++ b/node_modules/algebrite/tests/expand.coffee
@@ -0,0 +1,92 @@
+test_expand = ->
+ run_test [
+
+ # general cases
+
+ "expand(1/(x+1)/(x+2))",
+ "1/(x+1)-1/(x+2)",
+
+ "expand((2x^3-x+2)/(x^2-2x+1))",
+ "4+2*x+5/(x-1)+3/(x^2-2*x+1)",
+
+ "expand(1/x^2/(x-1))",
+ "-1/(x^2)-1/x+1/(x-1)",
+
+ "p=5s+2",
+ "",
+
+ "q=(s+1)*(s+2)^2",
+ "",
+
+ "expand(p/q)",
+ "-3/(s+1)+3/(s+2)+8/(s^2+4*s+4)",
+
+ # ensure denominators are expanded (result seems preferable that way)
+
+ "q=(x-1)*(x-2)^3",
+ "",
+
+ "expand(1/q)",
+ "1/(x^3-6*x^2+12*x-8)+1/(x-2)-1/(x-1)-1/(x^2-4*x+4)",
+
+ # fractional poles
+
+ "expand(1/(x+1/2)/(x+1/3))",
+ "-12/(2*x+1)+18/(3*x+1)",
+
+ # expand tensor
+
+ "f=1/(x+1)/(x+2)",
+ "",
+
+ "g=1/(x+1)-1/(x+2)",
+ "",
+
+ "expand([[f,f],[f,f]])-[[g,g],[g,g]]",
+ "[[0,0],[0,0]]",
+
+ # denominator normalized?
+
+ "expand(1/(1+1/x))",
+ "1-1/(x+1)",
+
+ # poles at zero
+
+ "expand(1/x/(x+1))",
+ "1/x-1/(x+1)",
+
+ "expand(1/x^2/(x+1))",
+ #"x^(-2)-1/x+1/(x+1)",
+ "1/x^2-1/x+1/(x+1)",
+
+ # other corner cases
+
+ "expand(1/x)",
+ "1/x",
+
+ "expand(1/x^2)",
+ #"x^(-2)",
+ "1/x^2",
+
+ "expand(1/(x^2-4x+4))",
+ "1/(x^2-4*x+4)",
+
+ # cases where nothing can be done
+
+ "expand(sin(x))",
+ "sin(x)",
+
+ "expand(x)",
+ "x",
+
+ "expand(1/sin(x))",
+ # unclear why the extra parens are added but no biggie
+ "1/(sin(x))",
+
+ # note that expand isn't needed to execute the
+ # multiplications, expand does something
+ # different.
+ "expand(expand((sin(x)+1)^2))",
+ "1+sin(x)^2+2*sin(x)",
+
+ ]
diff --git a/node_modules/algebrite/tests/expcos.coffee b/node_modules/algebrite/tests/expcos.coffee
new file mode 100644
index 0000000..794313a
--- /dev/null
+++ b/node_modules/algebrite/tests/expcos.coffee
@@ -0,0 +1,6 @@
+test_expcos = ->
+ run_test [
+
+ "expcos(x)",
+ "1/2*exp(-i*x)+1/2*exp(i*x)",
+ ]
diff --git a/node_modules/algebrite/tests/expsin.coffee b/node_modules/algebrite/tests/expsin.coffee
new file mode 100644
index 0000000..ae43033
--- /dev/null
+++ b/node_modules/algebrite/tests/expsin.coffee
@@ -0,0 +1,6 @@
+test_expsin = ->
+ run_test [
+
+ "expsin(x)",
+ "1/2*i*exp(-i*x)-1/2*i*exp(i*x)",
+ ]
diff --git a/node_modules/algebrite/tests/factor.coffee b/node_modules/algebrite/tests/factor.coffee
new file mode 100644
index 0000000..5592e01
--- /dev/null
+++ b/node_modules/algebrite/tests/factor.coffee
@@ -0,0 +1,137 @@
+test_factor_number = ->
+ run_test [
+
+ "factor(0)",
+ "0",
+
+ "factor(1)",
+ "1",
+
+ "factor(2)",
+ "2",
+
+ "factor(3)",
+ "3",
+
+ "factor(4)",
+ "2^2",
+
+ "factor(5)",
+ "5",
+
+ "factor(6)",
+ "2*3",
+
+ "factor(7)",
+ "7",
+
+ "factor(8)",
+ "2^3",
+
+ "factor(9)",
+ "3^2",
+
+ "factor(10)",
+ "2*5",
+
+ "factor(100!)",
+ "2^97*3^48*5^24*7^16*11^9*13^7*17^5*19^5*23^4*29^3*31^3*37^2*41^2*43^2*47^2*53*59*61*67*71*73*79*83*89*97",
+
+ "factor(2*(2^30-35))",
+ "2*1073741789",
+
+ # x is the 10,000th prime
+
+ # Prime factors greater than x^2 are found using the Pollard rho method
+
+ "a=104729",
+ "",
+
+ "factor(2*(a^2+6))",
+ "2*10968163447",
+
+ "factor((a^2+6)^2)",
+ "10968163447*10968163447", # FIXME should be 10968163447^2
+
+ "factor((a^2+6)*(a^2+60))",
+ "10968163501*10968163447", # FIXME sort order
+
+ "f=(x+1)*(x+2)*(y+3)*(y+4)",
+ "",
+
+ "factor(f,x,y)",
+ "(x+1)*(x+2)*(y+3)*(y+4)",
+
+ "factor(f,y,x)",
+ "(x+1)*(x+2)*(y+3)*(y+4)",
+
+ "f=(x+1)*(x+1)*(y+2)*(y+2)",
+ "",
+
+ "factor(f,x,y)",
+ "(x+1)^2*(y+2)^2",
+
+ "factor(f,y,x)",
+ "(x+1)^2*(y+2)^2",
+
+ "factor((x+1)*(-x^2+x+1),x)",
+ "-(x^2-x-1)*(x+1)",
+
+ "factor((x+1)*(x^2-x-1),x)",
+ "(x^2-x-1)*(x+1)",
+
+ "factor(5*x^3-5)",
+ "5*(x-1)*(x^2+x+1)",
+
+ "factor((x+1)*(2x+4))",
+ "2*(x+1)*(x+2)",
+
+ "factor(x^8 - 1)",
+ "(x-1)*(x+1)*(x^2+1)*(x^4+1)",
+
+ "factor((x-1)*(x+1)*(x^2+1)*(2*x^4+2))",
+ "2*(x-1)*(x+1)*(x^2+1)*(x^4+1)",
+
+ "factor((x-1)*(x+1)*(2*x^2+2)*(x^4+1))",
+ "2*(x-1)*(x+1)*(x^2+1)*(x^4+1)",
+
+ "factor(x^1 - 1)",
+ "x-1",
+
+ "factor(x^2 - 1)",
+ "(x-1)*(x+1)",
+
+ "factor(x^3 - 1)",
+ "(x-1)*(x^2+x+1)",
+
+ "factor(x^4 - 1)",
+ "(x-1)*(x+1)*(x^2+1)",
+
+ "factor(x^5 - 1)",
+ "(x-1)*(x^4+x^3+x^2+x+1)",
+
+ "factor(x^6 - 1)",
+ "(x-1)*(x+1)*(x^2+x+1)*(x^2+1)",
+
+ "factor(x^7 - 1)",
+ "(x-1)*(x^6+x^5+x^4+x^3+x^2+x+1)",
+
+ # irreducible in Z
+ "factor(1+x+x^2+x^3+x^4)",
+ "x^4+x^3+x^2+x+1",
+
+ "factor(x^4 - 1*x^3 + 4*x^2 + 3*x + 5)",
+ "(x^2+x+1)*(x^2-2*x+5)",
+
+ # https://github.com/davidedc/Algebrite/issues/113
+ "factor((x^3+x^2+x)*(y^3+y^2),x,y)",
+ "x*y^2*(x^2+x+1)*(y+1)",
+
+ # clean up
+ "a = quote(a)",
+ "",
+
+ "f = quote(f)",
+ "",
+
+ ]
diff --git a/node_modules/algebrite/tests/factorpoly.coffee b/node_modules/algebrite/tests/factorpoly.coffee
new file mode 100644
index 0000000..c475c32
--- /dev/null
+++ b/node_modules/algebrite/tests/factorpoly.coffee
@@ -0,0 +1,366 @@
+test_factorpoly = ->
+ run_test [
+
+ "bake=0",
+ "",
+
+ "factor((x+1)*(x+2)*(x+3),x)",
+ "(1+x)*(2+x)*(3+x)",
+
+ "factor((x+a)*(x^2+x+1),x)",
+ "(1+x+x^2)*(a+x)",
+
+ "factor(x*(x+1)*(x+2),x)",
+ "x*(1+x)*(2+x)",
+
+ "factor((x+1)*(x+2)*(y+3)*(y+4))",
+ "(1+x)*(2+x)*(12+7*y+y^2)",
+
+ "factor((x+1)*(x+2)*(y+3)*(y+4),x,y)",
+ "(1+x)*(2+x)*(3+y)*(4+y)",
+
+ "factor((-2*x+3)*(x+4),x)",
+ "-(-3+2*x)*(4+x)",
+
+ "(-2*x+3)*(x+4)+(-3+2*x)*(4+x)",
+ "0",
+
+ # make sure sign of remaining poly is factored
+
+ "factor((x+1)*(-x^2+x+1),x)",
+ "-(-1-x+x^2)*(1+x)",
+
+ # sign handling
+
+ #++++++
+
+ "factor((x+1/2)*(+x+1/3)*(+x+1/4),x)",
+ "1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+
+ "(x+1/2)*(+x+1/3)*(+x+1/4)-1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+ "0",
+
+ #+++++-
+
+ "factor((x+1/2)*(+x+1/3)*(+x-1/4),x)",
+ "1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+
+ "(x+1/2)*(+x+1/3)*(+x-1/4)-1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+ "0",
+
+ #++++-+
+
+ "factor((x+1/2)*(+x+1/3)*(-x+1/4),x)",
+ "-1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+
+ "(x+1/2)*(+x+1/3)*(-x+1/4)+1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+ "0",
+
+ #++++--
+
+ "factor((x+1/2)*(+x+1/3)*(-x-1/4),x)",
+ "-1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+
+ "(x+1/2)*(+x+1/3)*(-x-1/4)+1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+ "0",
+
+ #+++-++
+
+ "factor((x+1/2)*(+x-1/3)*(+x+1/4),x)",
+ "1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+
+ "(x+1/2)*(+x-1/3)*(+x+1/4)-1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+ "0",
+
+ #+++-+-
+
+ "factor((x+1/2)*(+x-1/3)*(+x-1/4),x)",
+ "1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+
+ "(x+1/2)*(+x-1/3)*(+x-1/4)-1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+ "0",
+
+ #+++--+
+
+ "factor((x+1/2)*(+x-1/3)*(-x+1/4),x)",
+ "-1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+
+ "(x+1/2)*(+x-1/3)*(-x+1/4)+1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+ "0",
+
+ #+++---
+
+ "factor((x+1/2)*(+x-1/3)*(-x-1/4),x)",
+ "-1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+
+ "(x+1/2)*(+x-1/3)*(-x-1/4)+1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+ "0",
+
+ #++-+++
+
+ "factor((x+1/2)*(-x+1/3)*(+x+1/4),x)",
+ "-1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+
+ "(x+1/2)*(-x+1/3)*(+x+1/4)+1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+ "0",
+
+ #++-++-
+
+ "factor((x+1/2)*(-x+1/3)*(+x-1/4),x)",
+ "-1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+
+ "(x+1/2)*(-x+1/3)*(+x-1/4)+1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+ "0",
+
+ #++-+-+
+
+ "factor((x+1/2)*(-x+1/3)*(-x+1/4),x)",
+ "1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+
+ "(x+1/2)*(-x+1/3)*(-x+1/4)-1/24*(-1+3*x)*(-1+4*x)*(1+2*x)",
+ "0",
+
+ #++-+--
+
+ "factor((x+1/2)*(-x+1/3)*(-x-1/4),x)",
+ "1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+
+ "(x+1/2)*(-x+1/3)*(-x-1/4)-1/24*(-1+3*x)*(1+2*x)*(1+4*x)",
+ "0",
+
+ #++--++
+
+ "factor((x+1/2)*(-x-1/3)*(+x+1/4),x)",
+ "-1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+
+ "(x+1/2)*(-x-1/3)*(+x+1/4)+1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+ "0",
+
+ #++--+-
+
+ "factor((x+1/2)*(-x-1/3)*(+x-1/4),x)",
+ "-1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+
+ "(x+1/2)*(-x-1/3)*(+x-1/4)+1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+ "0",
+
+ #++---+
+
+ "factor((x+1/2)*(-x-1/3)*(-x+1/4),x)",
+ "1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+
+ "(x+1/2)*(-x-1/3)*(-x+1/4)-1/24*(-1+4*x)*(1+2*x)*(1+3*x)",
+ "0",
+
+ #++----
+
+ "factor((x+1/2)*(-x-1/3)*(-x-1/4),x)",
+ "1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+
+ "(x+1/2)*(-x-1/3)*(-x-1/4)-1/24*(1+2*x)*(1+3*x)*(1+4*x)",
+ "0",
+
+ #++++++
+
+ "factor((+x+a)*(+x+b)*(+x+c),x)",
+ "(a+x)*(b+x)*(c+x)",
+
+ "(a+x)*(b+x)*(c+x)-(a+x)*(b+x)*(c+x)",
+ "0",
+
+ #+++++-
+
+ "factor((+x+a)*(+x+b)*(+x-c),x)",
+ "(a+x)*(b+x)*(-c+x)",
+
+ "(+x+a)*(+x+b)*(+x-c)-(a+x)*(b+x)*(-c+x)",
+ "0",
+
+ #++++-+
+
+ "factor((+x+a)*(+x+b)*(-x+c),x)",
+ "-(a+x)*(b+x)*(-c+x)",
+
+ "(+x+a)*(+x+b)*(-x+c)+(a+x)*(b+x)*(-c+x)",
+ "0",
+
+ #++++--
+
+ "factor((+x+a)*(+x+b)*(-x-c),x)",
+ "-(a+x)*(b+x)*(c+x)",
+
+ "(+x+a)*(+x+b)*(-x-c)+(a+x)*(b+x)*(c+x)",
+ "0",
+
+ #++++
+
+ "factor((+a*x+b)*(+c*x+d),x)",
+ "(b+a*x)*(d+c*x)",
+
+ "(+a*x+b)*(+c*x+d)-(b+a*x)*(d+c*x)",
+ "0",
+
+ #+++-
+
+ "factor((+a*x+b)*(+c*x-d),x)",
+ "(b+a*x)*(-d+c*x)",
+
+ "(+a*x+b)*(+c*x-d)-(b+a*x)*(-d+c*x)",
+ "0",
+
+ #++-+
+
+ "factor((+a*x+b)*(-c*x+d),x)",
+ "-(b+a*x)*(-d+c*x)",
+
+ "(+a*x+b)*(-c*x+d)+(b+a*x)*(-d+c*x)",
+ "0",
+
+ #++--
+
+ "factor((+a*x+b)*(-c*x-d),x)",
+ "-(b+a*x)*(d+c*x)",
+
+ "(+a*x+b)*(-c*x-d)+(b+a*x)*(d+c*x)",
+ "0",
+
+ #+-++
+
+ "factor((+a*x-b)*(+c*x+d),x)",
+ "(d+c*x)*(-b+a*x)",
+
+ "(+a*x-b)*(+c*x+d)-(d+c*x)*(-b+a*x)",
+ "0",
+
+ #+-+-
+
+ "factor((+a*x-b)*(+c*x-d),x)",
+ "(-b+a*x)*(-d+c*x)",
+
+ "(+a*x-b)*(+c*x-d)-(-b+a*x)*(-d+c*x)",
+ "0",
+
+ #+--+
+
+ "factor((+a*x-b)*(-c*x+d),x)",
+ "-(-b+a*x)*(-d+c*x)",
+
+ "(+a*x-b)*(-c*x+d)+(-b+a*x)*(-d+c*x)",
+ "0",
+
+ #+---
+
+ "factor((+a*x-b)*(-c*x-d),x)",
+ "-(d+c*x)*(-b+a*x)",
+
+ "(+a*x-b)*(-c*x-d)+(d+c*x)*(-b+a*x)",
+ "0",
+
+ #-+++
+
+ "factor((-a*x+b)*(+c*x+d),x)",
+ "-(d+c*x)*(-b+a*x)",
+
+ "(-a*x+b)*(+c*x+d)+(d+c*x)*(-b+a*x)",
+ "0",
+
+ #-++-
+
+ "factor((-a*x+b)*(+c*x-d),x)",
+ "-(-b+a*x)*(-d+c*x)",
+
+ "(-a*x+b)*(+c*x-d)+(-b+a*x)*(-d+c*x)",
+ "0",
+
+ #-+-+
+
+ "factor((-a*x+b)*(-c*x+d),x)",
+ "(-b+a*x)*(-d+c*x)",
+
+ "(-a*x+b)*(-c*x+d)-(-b+a*x)*(-d+c*x)",
+ "0",
+
+ #-+--
+
+ "factor((-a*x+b)*(-c*x-d),x)",
+ "(d+c*x)*(-b+a*x)",
+
+ "(-a*x+b)*(-c*x-d)-(d+c*x)*(-b+a*x)",
+ "0",
+
+ #--++
+
+ "factor((-a*x-b)*(+c*x+d),x)",
+ "-(b+a*x)*(d+c*x)",
+
+ "(-a*x-b)*(+c*x+d)+(b+a*x)*(d+c*x)",
+ "0",
+
+ #--+-
+
+ "factor((-a*x-b)*(+c*x-d),x)",
+ "-(b+a*x)*(-d+c*x)",
+
+ "(-a*x-b)*(+c*x-d)+(b+a*x)*(-d+c*x)",
+ "0",
+
+ #---+
+
+ "factor((-a*x-b)*(-c*x+d),x)",
+ "(b+a*x)*(-d+c*x)",
+
+ "(-a*x-b)*(-c*x+d)-(b+a*x)*(-d+c*x)",
+ "0",
+
+ #----
+
+ "factor((-a*x-b)*(-c*x-d),x)",
+ "(b+a*x)*(d+c*x)",
+
+ "(-a*x-b)*(-c*x-d)-(b+a*x)*(d+c*x)",
+ "0",
+
+ # this used to cause divide by zero
+
+ # fixed by calling ispolyexpandedform before calling coeff
+
+ # "factor(1/x+1)",
+ # "(1+x)/x",
+
+ # see if poly gets rationalized
+
+ # "(x+1)(x+2)(x+3)/x^3",
+ # "1+6/(x^3)+11/(x^2)+6/x",
+
+ # "factor(last)",
+ # "(1+x)*(2+x)*(3+x)/(x^3)",
+
+ # this used to fail
+
+ "factor(x,x)",
+ "x",
+
+ "factor(x^2,x)",
+ "x^2",
+
+ "factor(x^3,x)",
+ "x^3",
+
+ "bake=1",
+ "",
+
+ "y=(x+1)*(x+2)",
+ "",
+
+ "factor(y,z)",
+ "x^2+3*x+2",
+
+ "factor(y,y)",
+ "x^2+3*x+2",
+
+ "y=x^2+exp(x)",
+ "",
+
+ "factor(y)",
+ "x^2+exp(x)",
+ ]
diff --git a/node_modules/algebrite/tests/float.coffee b/node_modules/algebrite/tests/float.coffee
new file mode 100644
index 0000000..41a7a11
--- /dev/null
+++ b/node_modules/algebrite/tests/float.coffee
@@ -0,0 +1,73 @@
+test_float = ->
+ run_test [
+
+ "1.0+0",
+ "1.0",
+
+ "1+0.0",
+ "1.0",
+
+ "1+0.0-0.0",
+ "1.0",
+
+ "float(0)",
+ "0.0",
+
+ "1-float(0)",
+ "1.0",
+
+ "float(x)",
+ "x",
+
+ "float(1/2)",
+ "0.5",
+
+ "float(pi)",
+ "3.141593...",
+
+ "float(exp(1))",
+ "2.718282...",
+
+ "float(sin(2))",
+ "0.909297...",
+
+ "float(cos(2))",
+ "-0.416147...",
+
+ "x=[1/2,1/4]",
+ "",
+
+ "float(x)",
+ "[0.5,0.25]",
+
+ "x",
+ "[1/2,1/4]",
+
+ "x=quote(x)",
+ "",
+
+ "float((1+2*i)^(1/2))",
+ "1.272020...+0.786151...*i",
+
+ "float((1+2*(-1)^(1/2))^(1/2))",
+ "1.272020...+0.786151...*i",
+
+ "float((-1)^(-0.666667+0.0291367/pi))",
+ "-0.474559...-0.880224...*i",
+
+ "abs(float((-1)^(-0.666667+0.0291367/pi)))",
+ "1.0",
+
+ # using float with an array
+ "a = [2,3,4]",
+ "",
+
+ "float(a[1])",
+ "2.0",
+
+ "a=quote(a)",
+ "",
+
+
+ ]
+
diff --git a/node_modules/algebrite/tests/floor.coffee b/node_modules/algebrite/tests/floor.coffee
new file mode 100644
index 0000000..bcfe769
--- /dev/null
+++ b/node_modules/algebrite/tests/floor.coffee
@@ -0,0 +1,74 @@
+test_floor = ->
+ run_test [
+ "floor(a)",
+ "floor(a)",
+
+ "floor(a+b)",
+ "floor(a+b)",
+
+ "floor(5/2)",
+ "2",
+
+ "floor(4/2)",
+ "2",
+
+ "floor(3/2)",
+ "1",
+
+ "floor(2/2)",
+ "1",
+
+ "floor(1/2)",
+ "0",
+
+ "floor(0/2)",
+ "0",
+
+ "floor(-1/2)",
+ "-1",
+
+ "floor(-2/2)",
+ "-1",
+
+ "floor(-3/2)",
+ "-2",
+
+ "floor(-4/2)",
+ "-2",
+
+ "floor(-5/2)",
+ "-3",
+
+ "floor(5/2.0)",
+ "2.0",
+
+ "floor(4/2.0)",
+ "2.0",
+
+ "floor(3/2.0)",
+ "1.0",
+
+ "floor(2/2.0)",
+ "1.0",
+
+ "floor(1/2.0)",
+ "0.0",
+
+ "floor(0.0)",
+ "0.0",
+
+ "floor(-1/2.0)",
+ "-1.0",
+
+ "floor(-2/2.0)",
+ "-1.0",
+
+ "floor(-3/2.0)",
+ "-2.0",
+
+ "floor(-4/2.0)",
+ "-2.0",
+
+ "floor(-5/2.0)",
+ "-3.0",
+ ]
diff --git a/node_modules/algebrite/tests/for.coffee b/node_modules/algebrite/tests/for.coffee
new file mode 100644
index 0000000..c8edb2a
--- /dev/null
+++ b/node_modules/algebrite/tests/for.coffee
@@ -0,0 +1,10 @@
+test_for = ->
+ run_test [
+
+ "x=0\ny=2\nfor(do(x=sqrt(2+x),y=2*y/x), k,1,9)\nfloat(y)",
+ "3.141588...",
+
+ "for(do(x=sqrt(2+x),y=2*y/x),k,1,iterations)",
+ "for(do(x=sqrt(2+x),y=2*y/x),k,1,iterations)",
+
+ ]
diff --git a/node_modules/algebrite/tests/gamma.coffee b/node_modules/algebrite/tests/gamma.coffee
new file mode 100644
index 0000000..2236705
--- /dev/null
+++ b/node_modules/algebrite/tests/gamma.coffee
@@ -0,0 +1,21 @@
+test_gamma = ->
+ run_test [
+ "Gamma(a)",
+ "Gamma(a)",
+
+ # "float(gamma(10))",
+ # "362880",
+
+ "Gamma(x+1)",
+ "x*Gamma(x)",
+
+ "Gamma(1/2)",
+ "pi^(1/2)",
+
+ "Gamma(x-1)-Gamma(x)/(-1+x)",
+ "0",
+
+ "Gamma(-x)",
+ "-pi/(x*Gamma(x)*sin(pi*x))",
+
+ ]
diff --git a/node_modules/algebrite/tests/gcd.coffee b/node_modules/algebrite/tests/gcd.coffee
new file mode 100644
index 0000000..9b6ab8b
--- /dev/null
+++ b/node_modules/algebrite/tests/gcd.coffee
@@ -0,0 +1,115 @@
+test_gcd = ->
+
+ gcdTests = []
+
+ GCD_TESTS_DONT_TEST_FACTOR = 1
+
+ addGcdTest = (arg1, arg2, result, dontTestFactor) ->
+ gcdTests.push "gcd(" + arg1 + "," + arg2 + ")"
+ gcdTests.push result
+
+ gcdTests.push "gcd(" + arg2 + "," + arg1 + ")"
+ gcdTests.push result
+
+ if !dontTestFactor?
+ gcdTests.push "gcd(factor(" + arg1 + ")," + arg2 + ")"
+ gcdTests.push result
+
+ if !dontTestFactor?
+ gcdTests.push "gcd(factor(" + arg2 + ")," + arg1 + ")"
+ gcdTests.push result
+
+ if !dontTestFactor?
+ gcdTests.push "gcd(" + arg1 + ",factor(" + arg2 + "))"
+ gcdTests.push result
+
+ if !dontTestFactor?
+ gcdTests.push "gcd(" + arg2 + ",factor(" + arg1 + "))"
+ gcdTests.push result
+
+ if !dontTestFactor?
+ gcdTests.push "gcd(factor(" + arg1 + "),factor(" + arg2 + "))"
+ gcdTests.push result
+
+ if !dontTestFactor?
+ gcdTests.push "gcd(factor(" + arg2 + "),factor(" + arg1 + "))"
+ gcdTests.push result
+
+
+ addGcdTest "30","42","6"
+ addGcdTest "-30","42","6"
+ addGcdTest "30","-42","6"
+ addGcdTest "-30","-42","6", GCD_TESTS_DONT_TEST_FACTOR
+
+ addGcdTest "x","x","x"
+ addGcdTest "-x","x","x"
+ addGcdTest "-x","-x","-x"
+
+ addGcdTest "x^2","x^3","x^2"
+ addGcdTest "x","y","1"
+ addGcdTest "x*y","y","y"
+ addGcdTest "x*y","y^2","y"
+ addGcdTest "x^2*y^2","x^3*y^3","x^2*y^2"
+ addGcdTest "x^2","x^3","x^2"
+
+ # gcd of expr
+ addGcdTest "x+y","x+z","1"
+ addGcdTest "x+y","x+y","x+y"
+ addGcdTest "x+y","2*x+2*y","x+y", GCD_TESTS_DONT_TEST_FACTOR
+ addGcdTest "-x-y","x+y","x+y", GCD_TESTS_DONT_TEST_FACTOR
+ addGcdTest "4*x+4*y","6*x+6*y","2*x+2*y", GCD_TESTS_DONT_TEST_FACTOR
+ addGcdTest "4*x+4*y+4","6*x+6*y+6","2+2*x+2*y", GCD_TESTS_DONT_TEST_FACTOR
+ # TODO this is not really correct, it should give 2
+ # however this was failing before all the gcd changes
+ # of May 2019, so just leaving it in with a note
+ addGcdTest "4*x+4*y+4","6*x+6*y+12","1", GCD_TESTS_DONT_TEST_FACTOR
+ addGcdTest "27*t^3+y^3+9*t*y^2+27*t^2*y","t+y","1"
+
+ # gcd expr factor
+ addGcdTest "2*a^2*x^2+a*x+a*b","a","a"
+ addGcdTest "2*a^2*x^2+a*x+a*b","a^2","a"
+ addGcdTest "2*a^2*x^2+2*a*x+2*a*b","a","a"
+
+ # gcd expr term
+ addGcdTest "2*a^2*x^2+2*a*x+2*a*b","2*a","2*a"
+ addGcdTest "2*a^2*x^2+2*a*x+2*a*b","3*a","a"
+ addGcdTest "2*a^2*x^2+2*a*x+2*a*b","4*a","2*a"
+
+ # gcd factor factor
+ addGcdTest "x","x^2","x"
+ addGcdTest "x","x^a","1"
+
+
+ # polynomials
+ addGcdTest "(x+1)*(x+1)","x+1","x+1"
+ addGcdTest "x*(x+1)","x","x"
+ addGcdTest "x^2+7x+6","x^2-5x-6","x+1",
+ addGcdTest "x*(x+1)^2","x+1","x+1"
+ addGcdTest "x*(x+1)","x+1","x+1"
+ addGcdTest "x^2+3x","x^2+5x","x"
+ addGcdTest "6x+20","2x+10","2"
+ addGcdTest "x^3-3x^2","4x^2-5x","x"
+ addGcdTest "x^2-9","x^2+5x+6","x+3"
+ addGcdTest "x^2-3x+2","x^2-1","x-1"
+ addGcdTest "x^2-2x-15","x^2+x-6","x+3"
+ addGcdTest "10x^3","2x^2-18x","2*x"
+ addGcdTest "6x^2","12x^4-9x^3","3*x^2"
+ addGcdTest "(3-x)*(x-1)","(x-3)*(x+1)","x-3"
+ addGcdTest "(x-2)*(x-5)","(2-x)*(x+5)","x-2"
+ addGcdTest "15-10x","8x^3-12x^2","2*x-3"
+ addGcdTest "3x","15x^2-6x","3*x"
+ addGcdTest "3x^3-15x^2+12x","3x-3","3*x-3"
+ addGcdTest "6x^2-12x","6x-3x^2","3*x^2-6*x"
+ addGcdTest "2x^2+13x+20","2x^2+17x+30","2*x+5"
+ addGcdTest "x^4+8x^2+7","3x^5-3x","x^2+1"
+ addGcdTest "x^2+8x*k+16*k^2","x^2-16k^2","x+4*k"
+
+
+ run_test gcdTests
+
+ # multiple arguments
+ run_test [
+ "gcd(12,18,9)",
+ "3",
+ ]
+
diff --git a/node_modules/algebrite/tests/hermite.coffee b/node_modules/algebrite/tests/hermite.coffee
new file mode 100644
index 0000000..77021ae
--- /dev/null
+++ b/node_modules/algebrite/tests/hermite.coffee
@@ -0,0 +1,41 @@
+test_hermite = ->
+ run_test [
+ "hermite(x,n)",
+ "hermite(x,n)",
+
+ "hermite(x,0)-1",
+ "0",
+
+ "hermite(x,1)-2*x",
+ "0",
+
+ "hermite(x,2)-(4*x^2-2)",
+ "0",
+
+ "hermite(x,3)-(8*x^3-12*x)",
+ "0",
+
+ "hermite(x,4)-(16*x^4-48*x^2+12)",
+ "0",
+
+ "hermite(x,5)-(32*x^5-160*x^3+120*x)",
+ "0",
+
+ "hermite(x,6)-(64*x^6-480*x^4+720*x^2-120)",
+ "0",
+
+ "hermite(x,7)-(128*x^7-1344*x^5+3360*x^3-1680*x)",
+ "0",
+
+ "hermite(x,8)-(256*x^8-3584*x^6+13440*x^4-13440*x^2+1680)",
+ "0",
+
+ "hermite(x,9)-(512*x^9-9216*x^7+48384*x^5-80640*x^3+30240*x)",
+ "0",
+
+ "hermite(x,10)-(1024*x^10-23040*x^8+161280*x^6-403200*x^4+302400*x^2-30240)",
+ "0",
+
+ "hermite(a-b,10)-eval(subst(a-b,x,hermite(x,10)))",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/imag.coffee b/node_modules/algebrite/tests/imag.coffee
new file mode 100644
index 0000000..4b0b487
--- /dev/null
+++ b/node_modules/algebrite/tests/imag.coffee
@@ -0,0 +1,18 @@
+test_imag = ->
+ run_test [
+
+ "imag(a+i*b)",
+ "b",
+
+ "imag(1+exp(i*pi/3))",
+ "1/2*3^(1/2)",
+
+ "imag(i)",
+ "1",
+
+ "imag((-1)^(1/3))",
+ "1/2*3^(1/2)",
+
+ "imag(-i)",
+ "-1",
+ ]
diff --git a/node_modules/algebrite/tests/index.coffee b/node_modules/algebrite/tests/index.coffee
new file mode 100644
index 0000000..89aee1d
--- /dev/null
+++ b/node_modules/algebrite/tests/index.coffee
@@ -0,0 +1,79 @@
+test_index = ->
+ run_test [
+
+ "A=[[A11,A12],[A21,A22]]",
+ "",
+
+ "A[1,1]",
+ "A11",
+
+ "A[1,2]",
+ "A12",
+
+ "A[2,1]",
+ "A21",
+
+ "A[2,2]",
+ "A22",
+
+ "A[1]",
+ "[A11,A12]",
+
+ "A[1][2]",
+ "A12",
+
+ "A[2]",
+ "[A21,A22]",
+
+ "A[1]=[B11,B12]",
+ "",
+
+ "A",
+ "[[B11,B12],[A21,A22]]",
+
+ "A[2]=[B21,B22]",
+ "",
+
+ "A",
+ "[[B11,B12],[B21,B22]]",
+
+ "A=[[0,0],[0,0]]",
+ "",
+
+ "A[1,1]",
+ "0",
+
+ # index of scalar should throw an error
+
+ "1[2]",
+ "Stop: trying to access a scalar as a tensor",
+
+ # clean up -----------------
+
+ "clearall",
+ "",
+
+ # index of a non-allocated tensor
+ # or index with a symbol instead of
+ # a number
+
+ "a[0]",
+ "a[0]",
+
+ "a[0,2]",
+ "a[0,2]",
+
+
+ "a[b]",
+ "a[b]",
+
+ "a[b,c]",
+ "a[b,c]",
+
+ "a = [1,2,3]",
+ "",
+
+ "a[b]",
+ "a[b]",
+
+ ]
diff --git a/node_modules/algebrite/tests/inner.coffee b/node_modules/algebrite/tests/inner.coffee
new file mode 100644
index 0000000..969f6e6
--- /dev/null
+++ b/node_modules/algebrite/tests/inner.coffee
@@ -0,0 +1,217 @@
+test_inner = ->
+ run_test [
+
+ # since we don't know anything about
+ # a and b, we have to leave this unevaluated
+ # turning this into a normal multiplication (which is
+ # commutative) would not be OK
+ "inner(a,b)",
+ "inner(a,b)",
+
+ # this shouldn't ever go wrong
+ # but one never knows
+ "inner(b,a)",
+ "inner(b,a)",
+
+ "inner(2,a)",
+ "2*a",
+
+ "inner(a,2)",
+ "2*a",
+
+ "inner(a,[b1,b2])",
+ "inner(a,[b1,b2])",
+
+ "inner([a1,a2],b)",
+ "inner([a1,a2],b)",
+
+ "inner(2,[b1,b2])",
+ "[2*b1,2*b2]",
+
+ "inner([b1,b2],2)",
+ "[2*b1,2*b2]",
+
+ "inner([[a11,a12],[a21,a22]],[x1,x2])",
+ "[a11*x1+a12*x2,a21*x1+a22*x2]",
+
+ "inner([1,2],[3,4])",
+ "11",
+
+ # non-invertible matrix
+ "inner([[2,2],[2,2]],[[0],[1]])",
+ "[[2],[2]]",
+
+ "inner(inner([1,2],[[3,4],[5,6]]),[7,8])",
+ "219",
+
+ "inner([1,2],inner([[3,4],[5,6]],[7,8]))",
+ "219",
+
+ "inner([1,2],[[3,4],[5,6]],[7,8])",
+ "219",
+
+ "inner(c,a1+b1)",
+ "inner(c,a1)+inner(c,b1)",
+
+ "inner(b1+c1,a)",
+ "inner(b1,a)+inner(c1,a)",
+
+ "inner(inner(a,b),c)",
+ "inner(a,inner(b,c))",
+
+ "inner(inner(a,b),c) - inner(a,inner(b,c))",
+ "0",
+
+ "inner(inner(a,b),c,d) - inner(a,b,inner(c,d))",
+ "0",
+
+ # trying some associativity and distributivity together
+ "inner(inner(a,b),c,d+f) - ( (inner(a,inner(b,c),d)) + inner(inner(a,b),c,f) )",
+ "0",
+
+ # bring it to a canonical form
+ # using associativity
+ "inner(a,b,c)",
+ "inner(a,inner(b,c))",
+
+ "inner(a,b+c,d)",
+ "inner(a,inner(b,d))+inner(a,inner(c,d))",
+
+ "inner(inner(a,b),inner(c,d))",
+ "inner(a,inner(b,inner(c,d)))",
+
+ # scalar product of vectors:
+ "inner([a, b, c], [x, y, z])",
+ "a*x+b*y+c*z",
+
+ # products of matrices and vectors:
+ "inner([[a, b], [c,d]], [x, y])",
+ "[a*x+b*y,c*x+d*y]",
+
+ "inner([x, y], [[a, b], [c,d]])",
+ "[a*x+c*y,b*x+d*y]",
+
+ "inner([x, y], [[a, b], [c,d]], [r, s])",
+ "a*r*x+b*s*x+c*r*y+d*s*y",
+
+ # matrix product:
+
+ "inner([[a,b],[c,d]],[[r,s],[t,u]])",
+ "[[a*r+b*t,a*s+b*u],[c*r+d*t,c*s+d*u]]",
+
+ # ---------------------------------------
+ # using the dot
+ # ---------------------------------------
+
+ "a·b",
+ "inner(a,b)",
+
+ "a·b·c",
+ "inner(a,inner(b,c))",
+
+ "a·b*c",
+ "c*inner(a,b)",
+
+ # note how we use associativity to bring it all
+ # to a canonical form
+ "((a·b)·c)·d",
+ "inner(a,inner(b,inner(c,d)))",
+
+ "a*b·c",
+ "a*inner(b,c)",
+
+ "2*a·b",
+ "2*inner(a,b)",
+
+ "inv(a)·a",
+ "I",
+
+ "a·inv(a)",
+ "I",
+
+ "b·a·inv(a)·c",
+ "inner(b,c)",
+
+ "b·aᵀ·inv(aᵀ)·c",
+ "inner(b,c)",
+
+ "b·inv(aᵀ)·aᵀ·c",
+ "inner(b,c)",
+
+ "b·inv((a+b)ᵀ)·(b+a)ᵀ·c",
+ "inner(b,c)",
+
+ "(-a)·(-b)",
+ "inner(a,b)",
+
+ "I·I",
+ "I",
+
+ "I·Iᵀ",
+ "I",
+
+ "(-I)·(-I)",
+ "I",
+
+ "(-Iᵀ)·(-I)",
+ "I",
+
+ "c·(b+a)ᵀ·inv((a+b)ᵀ)·d",
+ "inner(c,d)",
+
+ "c·inv((b+a)ᵀ)·(a+b)ᵀ·d",
+ "inner(c,d)",
+
+ "c·(b+a)ᵀ·inv((a+b)ᵀ)·inv(c)",
+ "I",
+
+ "c·inv((b+a)ᵀ)·(a+b)ᵀ·inv(c)",
+ "I",
+
+ "inv(c)·(b+a)ᵀ·inv((a+b)ᵀ)·c",
+ "I",
+
+ "inv(c)·inv((b+a)ᵀ)·(a+b)ᵀ·c",
+ "I",
+
+
+ "c·d·(b+a)ᵀ·inv((a+b)ᵀ)",
+ "inner(c,d)",
+
+ "d·(b+a)ᵀ·inv((a+b)ᵀ)",
+ "d",
+
+ "(b+a)ᵀ·inv((a+b)ᵀ)",
+ "I",
+
+ "c·d·(b+a)ᵀ·inv((a+b)ᵀ)·inv(d)",
+ "c",
+
+ "c·d·(b+a)ᵀ·inv((a+b)ᵀ)·inv(d)·inv(c)",
+ "I",
+
+ "c·d·(b+a)ᵀ·inv((a+b)ᵀ)·inv(c·d)",
+ "I",
+
+ "c·d·(a+b)ᵀ·inv(c·d·(b+a)ᵀ)",
+ "I",
+
+ "inv(c)·c",
+ "I",
+
+ "inv(c·a)·c·a",
+ "I",
+
+ "inv(c·b·a)·c·b·a",
+ "I",
+
+ "inv(c)·d·(a+b)ᵀ·inv(inv(c)·d·(b+a)ᵀ)",
+ "I",
+
+ "inv(c+f)·d·(a+b)ᵀ·inv(inv(f+c)·d·(b+a)ᵀ)",
+ "I",
+
+ "c·d·inv(a)·inv(c·d·inv(a))",
+ "I",
+
+ ]
diff --git a/node_modules/algebrite/tests/integral.coffee b/node_modules/algebrite/tests/integral.coffee
new file mode 100644
index 0000000..d4b77de
--- /dev/null
+++ b/node_modules/algebrite/tests/integral.coffee
@@ -0,0 +1,738 @@
+test_integral = ->
+ run_test [
+
+ "clearall",
+ "",
+
+ "tty=1",
+ "",
+
+ "integral(x^2+x)-(1/2*x^2+1/3*x^3)",
+ "0",
+
+ #1
+ "integral(A,X)",
+ "A*X",
+
+ #4
+ "integral(A+B,X)-(A*X+B*X)",
+ "0",
+
+ #9
+ "integral(1/X,X)",
+ "log(X)",
+
+ #11
+ "integral(exp(X),X)",
+ "exp(X)",
+
+ #12
+ "integral(exp(A*X),X)-exp(A*X)/A",
+ "0",
+
+ #14
+ "integral(log(X),X)-X*log(X)+X",
+ "0",
+
+ #15
+ "integral(3^X*log(3),X)",
+ "3^X",
+
+ #16
+ "integral(1/(3+x^2),x)-3^(-1/2)*arctan(3^(-1/2)*x)",
+ "0",
+
+ #17
+ "integral(1/(a-x^2),x)-a^(-1/2)*arctanh(a^(-1/2)*x)",
+ "0",
+
+ #19
+ "integral(1/sqrt(a-x^2),x)-arcsin(a^(-1/2)*x)",
+ "0",
+
+ #20
+ "integral(1/sqrt(a+x^2),x)-(log(x+(a+x^2)^(1/2)))",
+ "0",
+
+ #27
+ "integral(1/(a+b*x),x)-(log(a+b*x)/b)",
+ "0",
+
+ #28
+ "integral(1/(A+B*X)^2,X)+1/B*1/(A+B*X)",
+ "0",
+
+ #29
+ "integral(1/(a+b*x)^3,x)+1/2*1/b*(a+b*x)^(-2)",
+ "0",
+
+ #30
+ "integral(X/(A+B*X),X)+A*B^(-2)*log(A+B*X)-X/B",
+ "0",
+
+ #31
+ "integral(X/(A+B*X)^2,X)-1/B^2*(log(A+B*X)+A/(A+B*X))",
+ "0",
+
+ #33
+ "integral(X^2/(A+B*X),X)-1/B^2*(1/2*(A+B*X)^2-2*A*(A+B*X)+A^2*log(A+B*X))",
+ "0",
+
+ #34
+ "integral(X^2/(A+B*X)^2,X)-1/B^3*(A+B*X-2*A*log(A+B*X)-A^2/(A+B*X))",
+ "0",
+
+ #35
+ "integral(X^2/(A+B*X)^3,X)-1/B^3*(log(A+B*X)+2*A/(A+B*X)-1/2*A^2/(A+B*X)^2)",
+ "0",
+
+ #37
+ "integral(1/X*1/(A+B*X),X)+1/A*log((A+B*X)/X)",
+ "0",
+
+ #38
+ "integral(1/X*1/(A+B*X)^2,X)-1/A*1/(A+B*X)+1/A^2*log((A+B*X)/X)",
+ "0",
+
+ #39
+ "integral(1/X*1/(A+B*X)^3,X)-1/A^3*(1/2*((2*A+B*X)/(A+B*X))^2+log(X/(A+B*X)))",
+ "0",
+
+ #40
+ "integral(1/X^2*1/(A+B*X),X)+1/(A*X)-B/A^2*log((A+B*X)/X)",
+ "0",
+
+ #41
+ "integral(1/X^3*1/(A+B*X),X)-(2*B*X-A)/(2*A^2*X^2)-B^2/A^3*log(X/(A+B*X))",
+ "0",
+
+ #42
+ "integral(1/X^2*1/(A+B*X)^2,X)+(A+2*B*X)/(A^2*X*(A+B*X))-2*B/A^3*log((A+B*X)/X)",
+ "0",
+
+ #60
+ "integral(1/(2+3*X^2),X)-1/sqrt(6)*arctan(1/2*X*sqrt(6))",
+ "0",
+ "integral(1/(-2-3*X^2),X)-1/sqrt(6)*arctan(-1/2*X*sqrt(6))",
+ "0",
+
+ #61
+ "integral(1/(2-3*X^2),X)-1/2*1/sqrt(6)*log((2+X*sqrt(6))/(2-X*sqrt(6)))",
+ "0",
+ "integral(1/(-2+3*X^2),X)-1/2*1/sqrt(6)*log((-2+X*sqrt(6))/(-2-X*sqrt(6)))",
+ "0",
+
+ #63
+ "integral(X/(A+B*X^2),X)-1/2*1/B*log(A+B*X^2)",
+ "0",
+
+ #64
+ "integral(X^2/(A+B*X^2),X)-X/B+A/B*integral(1/(A+B*X^2),X)",
+ "0",
+
+ #65
+ "integral(1/(A+B*X^2)^2,X)-X/(2*A*(A+B*X^2))-1/2*1/A*integral(1/(A+B*X^2),X)",
+ "0",
+
+ #70
+ "integral(1/X*1/(A+B*X^2),X)-1/2*1/A*log(X^2/(A+B*X^2))",
+ "0",
+
+ #71
+ "integral(1/X^2*1/(A+B*X^2),X)+1/(A*X)+B/A*integral(1/(A+B*X^2),X)",
+ "0",
+
+ #74
+ "integral(1/(A+B*X^3),X)-1/3*1/A*(A/B)^(1/3)*(1/2*log(((A/B)^(1/3)+X)^3/(A+B*X^3))+sqrt(3)*arctan((2*X-(A/B)^(1/3))*(A/B)^(-1/3)/sqrt(3)))",
+ "0",
+
+ #76
+ "integral(X^2/(A+B*X^3),X)-1/3*1/B*log(A+B*X^3)",
+ "0",
+
+ # commenting this out because the definite integral of this one
+ # between 0 and pi was incorrect AND the indefinite integral
+ # became incorrect after I avoided having roots in the denominator
+ # when doing multiplications. The two things combined made me
+ # think to eliminate this test.
+ #77
+ #"integral(1/(2+3*X^4),X)-1/2*1/2*(2/3/4)^(1/4)*(1/2*log((X^2+2*(2/3/4)^(1/4)*X+2*(2/3/4)^(1/2))/(X^2-2*(2/3/4)^(1/4)*X+2*(2/3/4)^(1/2)))+arctan(2*(2/3/4)^(1/4)*X/(2*(2/3/4)^(1/2)-X^2)))",
+ #"0",
+
+ # commenting this out because the definite integral of this one
+ # between 0 and pi was incorrect AND the indefinite integral
+ # became incorrect after I avoided having roots in the denominator
+ # when doing multiplications. The two things combined made me
+ # think to eliminate this test.
+ #78
+ #"integral(1/(2-3*X^4),X)-1/2*(2/3)^(1/4)/2*(1/2*log((X+(2/3)^(1/4))/(X-(2/3)^(1/4)))+arctan(X*(2/3)^(-1/4)))",
+ #"0",
+
+ #79
+ "integral(X/(2+3*X^4),X)-1/2*1/3*1/sqrt(2/3)*arctan(X^2/sqrt(2/3))",
+ "0",
+
+ #80
+ "integral(X/(2-3*X^4),X)+1/4*1/3*sqrt(3/2)*log((X^2-sqrt(2/3))/(X^2+sqrt(2/3)))",
+ "0",
+
+ # commenting this out because the definite integral of this one
+ # between 0 and pi was incorrect AND the indefinite integral
+ # became incorrect after I avoided having roots in the denominator
+ # when doing multiplications. The two things combined made me
+ # think to eliminate this test.
+ #81
+ #"integral(X^2/(2+3*X^4),X)-1/4*1/3*(2/3/4)^(-1/4)*(1/2*log((X^2-2*(2/3/4)^(1/4)*X+2*sqrt(2/3/4))/(X^2+2*(2/3/4)^(1/4)*X+2*sqrt(2/3/4)))+arctan(2*(2/3/4)^(1/4)*X/(2*sqrt(2/3/4)-X^2)))",
+ #"0",
+
+ # commenting this out because the definite integral of this one
+ # between 0 and pi was incorrect AND the indefinite integral
+ # became incorrect after I avoided having roots in the denominator
+ # when doing multiplications. The two things combined made me
+ # think to eliminate this test.
+ #82
+ #"integral(X^2/(2-3*X^4),X)+1/4*1/3*(2/3)^(-1/4)*(log((X-(2/3)^(1/4))/(X+(2/3)^(1/4)))+2*arctan(X*(2/3)^(-1/4)))",
+ #"0",
+
+ #83
+ "integral(X^3/(A+B*X^4),X)-1/4*1/B*log(A+B*X^4)",
+ "0",
+
+ #124
+ "integral(sqrt(A+B*X),X)-2/3/B*sqrt((A+B*X)^3)",
+ "0",
+
+ #125
+ "integral(X*sqrt(A+B*X),X)+2*(2*A-3*B*X)*sqrt((A+B*X)^3)/15*B^(-2)",
+ "0",
+
+ #126
+ "integral(X^2*sqrt(A+B*X),X)-2*(8*A^2-12*A*B*X+15*B^2*X^2)*sqrt((A+B*X)^3)/105*B^(-3)",
+ "0",
+
+ #128
+ "integral(sqrt(A+B*X)/X,X)-2*sqrt(A+B*X)-A*integral(1/X*1/sqrt(A+B*X),X)",
+ "0",
+
+ #129
+ "integral(sqrt(A+B*X)/X^2,X)+sqrt(A+B*X)/X-B/2*integral(1/X*1/sqrt(A+B*X),X)",
+ "0",
+
+ #131
+ "integral(1/sqrt(A+B*X),X)-2*sqrt(A+B*X)/B",
+ "0",
+
+ #132
+ "integral(X/sqrt(A+B*X),X)+2/3*(2*A-B*X)*sqrt(A+B*X)/B^2",
+ "0",
+
+ #133
+ "integral(X^2/sqrt(A+B*X),X)-2/15*(8*A^2-4*A*B*X+3*B^2*X^2)*sqrt(A+B*X)/B^3",
+ "0",
+
+ #134
+ "integral(1/X*1/sqrt(2+B*X),X)-1/sqrt(2)*log((sqrt(2+B*X)-sqrt(2))/(sqrt(2+B*X)+sqrt(2)))",
+ "0",
+
+ #136
+ "integral(1/X*1/sqrt(-2+B*X),X)-2/sqrt(2)*arctan(sqrt((-2+B*X)/2))",
+ "0",
+
+ #137
+ "integral(1/X^2*1/sqrt(A+B*X),X)+sqrt(A+B*X)/A/X+1/2*B/A*integral(1/X*1/sqrt(A+B*X),X)",
+ "0",
+
+ #156
+ "integral(sqrt(X^2+A),X)-1/2*(X*sqrt(X^2+A)+A*log(X+sqrt(X^2+A)))",
+ "0",
+
+ #157
+ "integral(1/sqrt(X^2+A),X)-log(X+sqrt(X^2+A))",
+ "0",
+
+ #158
+ "integral(1/X*1/sqrt(X^2-2),X)-arcsec(X/sqrt(2))/sqrt(2)",
+ "0",
+
+ #159
+ "integral(1/X*1/sqrt(X^2+2),X)+1/sqrt(2)*log((sqrt(2)+sqrt(X^2+2))/X)",
+ "0",
+
+ #160
+ "integral(sqrt(X^2+2)/X,X)-sqrt(X^2+2)+sqrt(2)*log((sqrt(2)+sqrt(X^2+2))/X)",
+ "0",
+
+ #161
+ "integral(sqrt(X^2-2)/X,X)-sqrt(X^2-2)+sqrt(2)*arcsec(X/sqrt(2))",
+ "0",
+
+ #162
+ "integral(X/sqrt(X^2+A),X)-sqrt(X^2+A)",
+ "0",
+
+ #163
+ "integral(X*sqrt(X^2+A),X)-1/3*sqrt((X^2+A)^3)",
+ "0",
+
+ #164 fails after Jan 2017 changes to abs/mag
+ #"integral(sqrt((X^2+A)^3),X)-1/4*(X*sqrt((X^2+A)^3)+3/2*A*X*sqrt(X^2+A)+3/2*A^2*log(X+sqrt(X^2+A)))",
+ #"0",
+
+ #"integral(sqrt((X^2-A)^3),X)-1/4*(X*sqrt((X^2-A)^3)-3/2*A*X*sqrt(X^2-A)+3/2*A^2*log(X+sqrt(X^2-A)))",
+ #"0",
+
+ #165 fails after Jan 2017 changes to abs/mag
+ #"integral(1/sqrt((X^2+A)^3),X)-X/A/sqrt(X^2+A)",
+ #"0",
+
+ #166 fails after Jan 2017 changes to abs/mag
+ #"integral(X/sqrt((X^2+A)^3),X)+1/sqrt(X^2+A)",
+ #"0",
+
+ #167 fails after Jan 2017 changes to abs/mag
+ #"integral(X*sqrt((X^2+A)^3),X)-1/5*sqrt((X^2+A)^5)",
+ #"0",
+
+ #168
+ "integral(X^2*sqrt(X^2+A),X)-1/4*X*sqrt((X^2+A)^3)+1/8*A*X*sqrt(X^2+A)+1/8*A^2*log(X+sqrt(X^2+A))",
+ "0",
+
+ #169
+ "integral(X^3*sqrt(X^2+7),X)-(1/5*X^2-2/15*7)*sqrt((X^2+7)^3)",
+ "0",
+
+ #170
+ "integral(X^3*sqrt(X^2-7),X)-(sqrt((X^2-7)^5)/5+7*sqrt((X^2-7)^3)/3)",
+ "0",
+
+ #171
+ "integral(X^2/sqrt(X^2+A),X)-1/2*X*sqrt(X^2+A)+1/2*A*log(X+sqrt(X^2+A))",
+ "0",
+
+ #172
+ "integral(X^3/sqrt(X^2+A),X)-1/3*sqrt((X^2+A)^3)+A*sqrt(X^2+A)",
+ "0",
+
+ #173
+ "integral(1/X^2*1/sqrt(X^2+A),X)+sqrt(X^2+A)/A/X",
+ "0",
+
+ #174
+ "integral(1/X^3*1/sqrt(X^2+2),X)+1/2*sqrt(X^2+2)/2/X^2-1/2*log((sqrt(2)+sqrt(X^2+2))/X)/(sqrt(2)^3)",
+ "0",
+
+ #175
+ "integral(1/X^3*1/sqrt(X^2-2),X)-1/2*sqrt(X^2-2)/2/X^2-1/2*1/(2^(3/2))*arcsec(X/(2^(1/2)))",
+ "0",
+
+ #176+
+ "integral(X^2*sqrt((X^2+2^2)^3),X)\
+ -1/6*X*sqrt((X^2+2^2)^5)\
+ +1/24*(2^2)*X*sqrt((X^2+2^2)^3)\
+ +1/16*(2^4)X*sqrt(X^2+2^2)\
+ +1/16*(2^6)*log(X+sqrt(X^2+2^2))",
+ "0",
+
+ #176-
+ "integral(X^2*sqrt((X^2-2^2)^3),X)\
+ -1/6*X*sqrt((X^2-2^2)^5)\
+ -1/24*(2^2)*X*sqrt((X^2-2^2)^3)\
+ +1/16*(2^4)X*sqrt(X^2-2^2)\
+ -1/16*(2^6)*log(X+sqrt(X^2-2^2))",
+ "0",
+
+ #177+
+ "integral(X^3*sqrt((X^2+7^2)^3),X)\
+ -1/7*sqrt((X^2+7^2)^7)\
+ +1/5*(7^2)*sqrt((X^2+7^2)^5)",
+ "0",
+
+ #177-
+ "integral(X^3*sqrt((X^2-7^2)^3),X)\
+ -1/7*sqrt((X^2-7^2)^7)\
+ -1/5*(7^2)*sqrt((X^2-7^2)^5)",
+ "0",
+
+ #196
+ "simplify(integral(1/(X-A)/sqrt(X^2-A^2),X)+sqrt(X^2-A^2)/A/(X-A))",
+ "0",
+ "simplify(1/(X-A)/sqrt(X^2-A^2)-d(integral(1/(X-A)/sqrt(X^2-A^2),X),X))",
+ "0",
+
+ #197
+ "integral(1/(X+A)/sqrt(X^2-A^2),X)-sqrt(X^2-A^2)/A/(X+A)",
+ "0",
+ "simplify(1/(X+A)/sqrt(X^2-A^2)-d(integral(1/(X+A)/sqrt(X^2-A^2),X),X))",
+ "0",
+
+ #200
+ "integral(sqrt(7-X^2),X)-1/2*(X*sqrt(7-X^2)+7*arcsin(X/sqrt(7)))",
+ "0",
+
+ #201
+ "integral(1/sqrt(7-X^2),X)-arcsin(X/sqrt(7))",
+ "0",
+
+ #202
+ "integral(1/X*1/sqrt(7-X^2),X)+1/sqrt(7)*log((sqrt(7)+sqrt(7-X^2))/X)",
+ "0",
+
+ #203
+ "integral(sqrt(7-X^2)/X,X)\
+ -sqrt(7-X^2)+sqrt(7)*log((sqrt(7)+sqrt(7-X^2))/X)",
+ "0",
+
+ #204
+ "integral(X/sqrt(A-X^2),X)\
+ +sqrt(A-X^2)",
+ "0",
+
+ #205
+ "integral(X*sqrt(A-X^2),X)\
+ +1/3*sqrt((A-X^2)^3)",
+ "0",
+
+ #210
+ "integral(X^2*sqrt(7-X^2),X)\
+ +1/4*X*sqrt((7-X^2)^3)\
+ -7/8*(X*sqrt(7-X^2)+7*arcsin(X/sqrt(7)))",
+ "0",
+
+ #211
+ "integral(X^3*sqrt(7-X^2),X)\
+ -(-1/5*X^2-2/15*7)*sqrt((7-X^2)^3)",
+ "0",
+
+ #214
+ "integral(X^2/sqrt(7-X^2),X)\
+ +X/2*sqrt(7-X^2)\
+ -7/2*arcsin(X/sqrt(7))",
+ "0",
+
+ #215
+ "integral(1/X^2*1/sqrt(7-X^2),X)\
+ +sqrt(7-X^2)/7/X",
+ "0",
+
+ #216
+ "integral(sqrt(7-X^2)/X^2,X)\
+ +sqrt(7-X^2)/X\
+ +arcsin(X/sqrt(7))",
+ "0",
+
+ #217
+ "integral(sqrt(7-X^2)/X^3,X)\
+ +1/2*sqrt(7-X^2)/X^2\
+ -1/2*log((sqrt(7)+sqrt(7-X^2))/X)/sqrt(7)",
+ "0",
+
+ #218
+ "integral(sqrt(7-X^2)/X^4,X)\
+ +1/3*sqrt((7-X^2)^3)/7/X^3",
+ "0",
+
+ #273
+ "integral(sqrt(7*X^2+C),X)-X*sqrt(7*X^2+C)/2-C*log(X*sqrt(7)+sqrt(7*X^2+C))/2/sqrt(7)",
+ "0",
+
+ #274
+ "integral(sqrt(-7*X^2+C),X)-X*sqrt(-7*X^2+C)/2-C*arcsin(X*sqrt(7/C))/2/sqrt(7)",
+ "0",
+
+ #290
+ "integral(sin(A*X),X)+cos(A*X)/A",
+ "0",
+
+ #291
+ "integral(cos(A*X),X)-sin(A*X)/A",
+ "0",
+
+ #292
+ "integral(tan(A*X),X)+log(cos(A*X))/A",
+ "0",
+
+ #293
+ "integral(1/tan(A*X),X)-log(sin(A*X))/A",
+ "0",
+
+ #294
+ "integral(1/cos(A*X),X)-log(tan(pi/4+A*X/2))/A",
+ "0",
+
+ #295
+ "integral(1/sin(A*X),X)-log(tan(A*X/2))/A",
+ "0",
+
+ #296
+ "integral(sin(A*X)^2,X)-X/2+sin(2*A*X)/(4*A)",
+ "0",
+
+ #297
+ "integral(sin(A*X)^3,X)+cos(A*X)*(sin(A*X)^2+2)/(3*A)",
+ "0",
+
+ #298
+ "integral(sin(A*X)^4,X)-3/8*X+sin(2*A*X)/(4*A)-sin(4*A*X)/(32*A)",
+ "0",
+
+ #302
+ "integral(cos(A*X)^2,X)-X/2-sin(2*A*X)/(4*A)",
+ "0",
+
+ #303
+ "integral(cos(A*X)^3,X)-sin(A*X)*(cos(A*X)^2+2)/(3*A)",
+ "0",
+
+ #304
+ "integral(cos(A*X)^4,X)-3/8*X-sin(2*A*X)/(4*A)-sin(4*A*X)/(32*A)",
+ "0",
+
+ #308
+ "integral((1/sin(A*X))^2,X)+1/A*1/tan(A*X)",
+ "0",
+
+ #312
+ "integral((1/cos(A*X))^2,X)-tan(A*X)/A",
+ "0",
+
+ #318
+ "integral(sin(A*X)*cos(A*X),X)-sin(A*X)^2/(2*A)",
+ "0",
+
+ #320
+ "integral(sin(A*X)^2*cos(A*X)^2,X)+sin(4*A*X)/(32*A)-X/8",
+ "0",
+
+ #326
+ "integral(sin(A*X)/cos(A*X)/cos(A*X),X)-1/(A*cos(A*X))",
+ "0",
+
+ #327
+ "integral(sin(A*X)^2/cos(A*X),X)+sin(A*X)/A-log(tan(pi/4+A*X/2))/A",
+ "0",
+
+ #328
+ "integral(cos(A*X)/sin(A*X)^2,X)+1/(A*sin(A*X))",
+ "0",
+
+ #329
+ "integral(1/sin(A*X)/cos(A*X),X)-log(tan(A*X))/A",
+ "0",
+
+ #330
+ "integral(1/sin(A*X)/cos(A*X)^2,X)-(1/cos(A*X)+log(tan(A*X/2)))/A",
+ "0",
+
+ #332
+ "integral(1/sin(A*X)^2/cos(A*X),X)-(log(tan(pi/4+A*X/2))-1/sin(A*X))/A",
+ "0",
+
+ #333
+ "integral(1/sin(A*X)^2/cos(A*X)^2,X)+2/(A*tan(2*A*X))",
+ "0",
+
+ #335
+ "integral(sin(A+B*X),X)+cos(A+B*X)/B",
+ "0",
+
+ #336
+ "integral(cos(A+B*X),X)-sin(A+B*X)/B",
+ "0",
+
+ #337+
+ "integral(1/(1+sin(A*X)),X)+tan(pi/4-A*X/2)/A",
+ "0",
+
+ #337b+
+ "integral(1/(B+B*sin(A*X)),X)+tan(pi/4-A*X/2)/A/B",
+ "0",
+
+ #337-
+ "integral(1/(1-sin(A*X)),X)-tan(pi/4+A*X/2)/A",
+ "0",
+
+ #337b-
+ "integral(1/(B-B*sin(A*X)),X)-tan(pi/4+A*X/2)/A/B",
+ "0",
+
+ #338
+ "integral(1/(1+cos(A*X)),X)-tan(A*X/2)/A",
+ "0",
+
+ #339
+ "integral(1/(1-cos(A*X)),X)+1/(A*tan(A*X/2))",
+ "0",
+
+ #340
+ "integral(1/(A+B*sin(X)),X)-1/sqrt(B^2-A^2)*log((A*tan(X/2)+B-sqrt(B^2-A^2))/(A*tan(X/2)+B+sqrt(B^2-A^2)))",
+ "0",
+
+ #341
+ "integral(1/(A+B*cos(X)),X)-1/sqrt(B^2-A^2)*log((sqrt(B^2-A^2)*tan(X/2)+A+B)/(sqrt(B^2-A^2)*tan(X/2)-A-B))",
+ "0",
+
+ #389
+ "x*sin(A*x)-d(integral(x*sin(A*x)))",
+ "0",
+
+ #390
+ "x^2*sin(A*x)-d(integral(x^2*sin(A*x)))",
+ "0",
+
+ #393
+ "x*cos(A*x)-d(integral(x*cos(A*x)))",
+ "0",
+
+ #394
+ "x^2*cos(A*x)-d(integral(x^2*cos(A*x)))",
+ "0",
+
+ #441
+ "integral(arcsin(A*X),X)-X*arcsin(A*X)-sqrt(1-A^2*X^2)/A",
+ "0",
+
+ #442
+ "integral(arccos(A*X),X)-X*arccos(A*X)+sqrt(1-A^2*X^2)/A",
+ "0",
+
+ #443
+ "integral(arctan(A*X),X)-X*arctan(A*X)+log(1+A^2*X^2)/(2*A)",
+ "0",
+
+ #485
+ "integral(log(X),X)-X*log(X)+X",
+ "0",
+
+ #485a
+ "integral(log(A*X),X)-X*log(A*X)+X",
+ "0",
+
+ #486
+ "integral(X*log(X),X)-1/2*X^2*log(X)+1/4*X^2",
+ "0",
+
+ #486a
+ "integral(X*log(A*X),X)-1/2*X^2*log(A*X)+1/4*X^2",
+ "0",
+
+ #487
+ "integral(X^2*log(A*X),X)-1/3*X^3*log(A*X)+X^3/9",
+ "0",
+
+ #489
+ "integral(log(X)^2,X)-X*log(X)^2+2*X*log(X)-2*X",
+ "0",
+
+ #493
+ "integral(1/X*1/log(A*X),X)-log(log(A*X))",
+ "0",
+
+ #499
+ "integral(log(A*X+B),X)-(A*X+B)*log(A*X+B)/A+X",
+ "0",
+
+ #500
+ "integral(log(A*X+B)/X^2,X)-A*log(X)/B+(A*X+B)*log(A*X+B)/B/X",
+ "0",
+
+ #554
+ "integral(sinh(X),X)-cosh(X)",
+ "0",
+
+ #555
+ "integral(cosh(X),X)-sinh(X)",
+ "0",
+
+ #556
+ "integral(tanh(X),X)-log(cosh(X))",
+ "0",
+
+ #560
+ "integral(X*sinh(X),X)-X*cosh(X)+sinh(X)",
+ "0",
+
+ #562
+ "integral(X*cosh(X),X)-X*sinh(X)+cosh(X)",
+ "0",
+
+ #566
+ "integral(sinh(X)^2,X)-sinh(2*X)/4+X/2",
+ "0",
+
+ #569
+ "integral(tanh(X)^2,X)-X+tanh(X)",
+ "0",
+
+ #572
+ "integral(cosh(X)^2,X)-sinh(2*X)/4-X/2",
+ "0",
+
+ # test integral(exp(a*x^2))
+
+ "integral(exp(a*x^2))+i*sqrt(pi)*erf(i*sqrt(a)*x)/sqrt(a)/2",
+ "0",
+
+ "integral(exp(-x^2))-sqrt(pi)*erf(x)/2",
+ "0",
+
+ # before abs/mag changes of Jan 2017
+ # this integral gave the more compact result of:
+ # sqrt(pi/3)*erf(sqrt(3)*x)/2
+ # but the new given one is still correct
+ "integral(exp(-3*x^2))-pi^(1/2)*erf(3^(1/2)*x)/(2*3^(1/2))",
+ "0",
+
+ "integral(1/x*1/(a+log(x)),x)-log(a+log(x))",
+ "0",
+
+ "integral(exp(a*x+b*x))",
+ "exp((a+b)*x)/(a+b)",
+
+ "integral(x*exp(a*x))",
+ "-exp(a*x)/(a^2)+x*exp(a*x)/a",
+ "derivative",
+ "x*exp(a*x)",
+
+ "integral(x*exp(a*x+b))",
+ "-exp(a*x+b)/(a^2)+x*exp(a*x+b)/a",
+ "derivative",
+ "x*exp(a*x+b)",
+
+ "integral(x*exp(-a*x+b))",
+ "-exp(-a*x+b)/(a^2)-x*exp(-a*x+b)/a",
+ "derivative",
+ "x*exp(-a*x+b)",
+
+ "integral(x^2*exp(a*x))",
+ "2*exp(a*x)/(a^3)-2*x*exp(a*x)/(a^2)+x^2*exp(a*x)/a",
+ "derivative",
+ "x^2*exp(a*x)",
+
+ "integral(x^2*exp(a*x+b))",
+ "2*exp(a*x+b)/(a^3)-2*x*exp(a*x+b)/(a^2)+x^2*exp(a*x+b)/a",
+ "derivative",
+ "x^2*exp(a*x+b)",
+
+ "integral(x^3*exp(a*x))",
+ "-6*exp(a*x)/(a^4)+6*x*exp(a*x)/(a^3)-3*x^2*exp(a*x)/(a^2)+x^3*exp(a*x)/a",
+ "derivative",
+ "x^3*exp(a*x)",
+
+ "integral(x^3*exp(a*x+b))",
+ "-6*exp(a*x+b)/(a^4)+6*x*exp(a*x+b)/(a^3)-3*x^2*exp(a*x+b)/(a^2)+x^3*exp(a*x+b)/a",
+ "derivative",
+ "x^3*exp(a*x+b)",
+
+ # here
+ "integral(sqrt(a*x^2+b))",
+ "Stop: integral: sorry, could not find a solution",
+
+ "integral(x^2*(1-x^2)^(3/2))-(x*sqrt(1-x^2)*(-8*x^4+14*x^2-3)+3*arcsin(x))/48",
+ "0",
+
+ "integral(x^4*(1-x^2)^(3/2))-(-x*sqrt(1-x^2)*(16*x^6-24*x^4+2*x^2+3)+3*arcsin(x))/128",
+ "0",
+
+ "integral(x^2*(1-x^2)^(5/2))-(x*sqrt(1-x^2)*(48*x^6-136*x^4+118*x^2-15)+15*arcsin(x))/384",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/inv.coffee b/node_modules/algebrite/tests/inv.coffee
new file mode 100644
index 0000000..7189fbd
--- /dev/null
+++ b/node_modules/algebrite/tests/inv.coffee
@@ -0,0 +1,24 @@
+test_inv = ->
+ run_test [
+
+ "inv(a)",
+ "inv(a)",
+
+ "inv(inv(a))",
+ "a",
+
+ "inv(inv(inv(a)))",
+ "inv(a)",
+
+ "inv(inv(inv(inv(a))))",
+ "a",
+
+ "inv(a·b·c)",
+ "inner(inv(c),inner(inv(b),inv(a)))",
+
+ "inv(I)",
+ "I",
+
+ ]
+
+
diff --git a/node_modules/algebrite/tests/isprime.coffee b/node_modules/algebrite/tests/isprime.coffee
new file mode 100644
index 0000000..fcfaacb
--- /dev/null
+++ b/node_modules/algebrite/tests/isprime.coffee
@@ -0,0 +1,35 @@
+test_isprime = ->
+ run_test [
+ # 0 and 1 are not prime numbers
+
+ "isprime(0)",
+ "0",
+
+ "isprime(1)",
+ "0",
+
+ "isprime(13)",
+ "1",
+
+ "isprime(14)",
+ "0",
+
+ # from the Prime Curios web page
+
+ "isprime(9007199254740991)",
+ "0",
+
+ # The largest prime that JavaScript supports
+
+ "isprime(2^53 - 111)",
+ "1",
+
+ # misc. primes
+
+ "isprime(2^50-71)",
+ "1",
+
+ "isprime(2^40-87)",
+ "1",
+
+ ]
diff --git a/node_modules/algebrite/tests/laguerre.coffee b/node_modules/algebrite/tests/laguerre.coffee
new file mode 100644
index 0000000..2c49b9d
--- /dev/null
+++ b/node_modules/algebrite/tests/laguerre.coffee
@@ -0,0 +1,35 @@
+test_laguerre = ->
+ run_test [
+ "laguerre(x,n)",
+ "laguerre(x,n,0)",
+
+ "laguerre(x,n,k)",
+ "laguerre(x,n,k)",
+
+ "laguerre(x,0)-1",
+ "0",
+
+ "laguerre(x,1)-(-x+1)",
+ "0",
+
+ "laguerre(x,2)-1/2*(x^2-4*x+2)",
+ "0",
+
+ "laguerre(x,3)-1/6*(-x^3+9*x^2-18*x+6)",
+ "0",
+
+ "laguerre(x,0,k)-1",
+ "0",
+
+ "laguerre(x,1,k)-(-x+k+1)",
+ "0",
+
+ "laguerre(x,2,k)-1/2*(x^2-2*(k+2)*x+(k+1)*(k+2))",
+ "0",
+
+ "laguerre(x,3,k)-1/6*(-x^3+3*(k+3)*x^2-3*(k+2)*(k+3)*x+(k+1)*(k+2)*(k+3))",
+ "0",
+
+ "laguerre(a-b,10)-eval(subst(a-b,x,laguerre(x,10)))",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/lcm.coffee b/node_modules/algebrite/tests/lcm.coffee
new file mode 100644
index 0000000..e664562
--- /dev/null
+++ b/node_modules/algebrite/tests/lcm.coffee
@@ -0,0 +1,14 @@
+test_lcm = ->
+ run_test [
+
+ "lcm(4,6)",
+ "12",
+
+ "lcm(4*x,6*x*y)",
+ "12*x*y",
+
+ # multiple arguments
+
+ "lcm(2,3,4)",
+ "12",
+ ]
diff --git a/node_modules/algebrite/tests/legendre.coffee b/node_modules/algebrite/tests/legendre.coffee
new file mode 100644
index 0000000..9c041b3
--- /dev/null
+++ b/node_modules/algebrite/tests/legendre.coffee
@@ -0,0 +1,110 @@
+test_legendre = ->
+ run_test [
+ "legendre(x,n)",
+ "legendre(x,n,0)",
+
+ "legendre(x,n,m)",
+ "legendre(x,n,m)",
+
+ "legendre(x,0)-1",
+ "0",
+
+ "legendre(x,1)-x",
+ "0",
+
+ "legendre(x,2)-1/2*(3*x^2-1)",
+ "0",
+
+ "legendre(x,3)-1/2*(5*x^3-3*x)",
+ "0",
+
+ "legendre(x,4)-1/8*(35*x^4-30*x^2+3)",
+ "0",
+
+ "legendre(x,5)-1/8*(63*x^5-70*x^3+15*x)",
+ "0",
+
+ "legendre(x,6)-1/16*(231*x^6-315*x^4+105*x^2-5)",
+ "0",
+
+ "legendre(x,0,0)-1",
+ "0",
+
+ "legendre(x,1,0)-x",
+ "0",
+
+ "legendre(x,1,1)+(1-x^2)^(1/2)",
+ "0",
+
+ "legendre(x,2,0)-1/2*(3*x^2-1)",
+ "0",
+
+ "legendre(x,2,1)+3*x*(1-x^2)^(1/2)",
+ "0",
+
+ "legendre(x,2,2)-3*(1-x^2)",
+ "0",
+
+ "legendre(x,3,0)-1/2*x*(5*x^2-3)",
+ "0",
+
+ "legendre(x,3,1)-3/2*(1-5*x^2)*(1-x^2)^(1/2)",
+ "0",
+
+ "legendre(x,3,2)-15*x*(1-x^2)",
+ "0",
+
+ "legendre(x,3,3)+15*(1-x^2)^(3/2)",
+ "0",
+
+ "legendre(x,4,0)-1/8*(35*x^4-30*x^2+3)",
+ "0",
+
+ "legendre(x,4,1)-5/2*x*(3-7*x^2)*(1-x^2)^(1/2)",
+ "0",
+
+ "legendre(x,4,2)-15/2*(7*x^2-1)*(1-x^2)",
+ "0",
+
+ "legendre(x,4,3)+105*x*(1-x^2)^(3/2)",
+ "0",
+
+ "legendre(x,4,4)-105*(1-x^2)^2",
+ "0",
+
+ "legendre(x,5,0)-1/8*x*(63*x^4-70*x^2+15)",
+ "0",
+
+ "legendre(cos(theta),0,0)-1",
+ "0",
+
+ "legendre(cos(theta),1,0)-cos(theta)",
+ "0",
+
+ "legendre(cos(theta),1,1)+abs(sin(theta))",
+ "0",
+
+ "legendre(cos(theta),2,0)-1/2*(3*cos(theta)^2-1)",
+ "0",
+
+ "legendre(cos(theta),2,1)+3*cos(theta)*abs(sin(theta))",
+ "0",
+
+ "legendre(cos(theta),2,2)-3*sin(theta)^2",
+ "0",
+
+ "legendre(cos(theta),3,0)-1/2*cos(theta)*(5*cos(theta)^2-3)",
+ "0",
+
+ "legendre(cos(theta),3,1)- (3/2*abs(sin(theta))-15/2*cos(theta)^2*abs(sin(theta)))",
+ "0",
+
+ "legendre(cos(theta),3,2)-15*cos(theta)*sin(theta)^2",
+ "0",
+
+ "legendre(cos(theta),3,3)+15*(sin(theta)^2)^(3/2)",
+ "0",
+
+ "legendre(a-b,10)-eval(subst(a-b,x,legendre(x,10)))",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/log.coffee b/node_modules/algebrite/tests/log.coffee
new file mode 100644
index 0000000..60c9a1c
--- /dev/null
+++ b/node_modules/algebrite/tests/log.coffee
@@ -0,0 +1,45 @@
+test_log = ->
+ run_test [
+
+ "log(1)",
+ "0",
+
+ "log(exp(1))",
+ "1",
+
+ "log(exp(x))",
+ "x",
+
+ "exp(log(x))",
+ "x",
+
+ "log(x^2)",
+ "2*log(x)",
+
+ "log(1/x)",
+ "-log(x)",
+
+ "log(a^b)",
+ "b*log(a)",
+
+ "log(2)",
+ "log(2)",
+
+ "log(2.0)",
+ "0.693147...",
+
+ "float(log(2))",
+ "0.693147...",
+
+ "log(a*b)",
+ "log(a)+log(b)",
+
+ "log(1/3)+log(3)",
+ "0",
+
+ "log(-1)",
+ "i*pi",
+
+ "log(-1.0)",
+ "3.141593...*i",
+ ]
diff --git a/node_modules/algebrite/tests/madd.coffee b/node_modules/algebrite/tests/madd.coffee
new file mode 100644
index 0000000..baff043
--- /dev/null
+++ b/node_modules/algebrite/tests/madd.coffee
@@ -0,0 +1,62 @@
+test_madd = ->
+ i = 0
+ if DEBUG then console.log("test madd")
+ m = mtotal
+ for i in [-100...100]
+ for j in [-100...100]
+ test_maddf(i, j, i + j)
+ #if (m != mtotal)
+ # logout("memory leak\n")
+ # errout()
+ logout("ok\n")
+
+test_maddf = (na, nb, nc) ->
+
+ a = mint(na)
+ b = mint(nb)
+ c = mint(nc)
+
+ d = madd(a, b)
+
+ if (mcmp(c, d) == 0)
+ return
+ else
+ throw new Error("test_maddf")
+
+ #sprintf(logbuf, "%d %d %d %d\n", na, nb, nc, *d * MSIGN(d))
+ logout(logbuf)
+ errout()
+
+test_msub = ->
+ i = 0
+ logout("test msub\n")
+ m = mtotal
+ for i in [-100..100]
+ for j in [-100..100]
+ test_msubf(i, j, i - j)
+ if (m != mtotal)
+ logout("memory leak\n")
+ errout()
+ logout("ok\n")
+
+test_msubf = (na, nb, nc) ->
+ #unsigned int *a, *b, *c, *d
+
+ a = mint(na)
+ b = mint(nb)
+ c = mint(nc)
+
+ d = msub(a, b)
+
+ if (mcmp(c, d) == 0)
+ #mfree(a)
+ #mfree(b)
+ #mfree(c)
+ #mfree(d)
+ return
+
+ #sprintf(logbuf, "%d %d %d %d\n", na, nb, nc, *d * MSIGN(d))
+ logout(logbuf)
+ errout()
+
+#endif
diff --git a/node_modules/algebrite/tests/mgcd.coffee b/node_modules/algebrite/tests/mgcd.coffee
new file mode 100644
index 0000000..321f2b3
--- /dev/null
+++ b/node_modules/algebrite/tests/mgcd.coffee
@@ -0,0 +1,31 @@
+test_mgcd = ->
+ logout("testing mgcd\n")
+ for i in [1...100]
+ a = mint(i)
+ for j in [1...100]
+ b = mint(j)
+ c = mgcd(a, b)
+ d = egcd(a, b)
+ if (mcmp(c, d) != 0)
+ throw new Error("test_mgcd failed")
+ logout("ok\n")
+
+# Euclid's algorithm
+
+egcd = (a, b) ->
+ sign_ = 0
+ if (MZERO(b))
+ stop("divide by zero")
+ #b = mcopy(b)
+ if (MZERO(a))
+ return b
+ sign_ = MSIGN(b)
+ #a = mcopy(a)
+ while (!MZERO(b))
+ c = mmod(a, b)
+ #mfree(a)
+ a = b
+ b = c
+ a = setSignTo(a,sign_)
+ return a
+
diff --git a/node_modules/algebrite/tests/mini-test.coffee b/node_modules/algebrite/tests/mini-test.coffee
new file mode 100644
index 0000000..6ba8353
--- /dev/null
+++ b/node_modules/algebrite/tests/mini-test.coffee
@@ -0,0 +1,236 @@
+# mini test for distribution builds
+
+mini_test = ->
+
+ run_test [
+ # static spherical metric
+
+ "clearall",
+ "",
+
+ "gdd=[[-exp(2*Phi(r)),0,0,0],[0,exp(2*Lambda(r)),0,0],[0,0,r^2,0],[0,0,0,r^2*sin(theta)^2]]",
+ "",
+
+ "X=[t,r,theta,phi]",
+ "",
+
+ "guu=inv(gdd)",
+ "",
+
+ "gddd=d(gdd,X)",
+ "",
+
+ "GAMDDD=1/2*(gddd+transpose(gddd,2,3)-transpose(transpose(gddd,2,3),1,2))",
+ "",
+
+ "GAMUDD=contract(outer(guu,GAMDDD),2,3)",
+ "",
+
+ "T1=d(GAMUDD,X)",
+ "",
+
+ "T2=contract(outer(GAMUDD,GAMUDD),2,4)",
+ "",
+
+ "RUDDD=transpose(T1,3,4)-T1+transpose(T2,2,3)-transpose(transpose(T2,2,3),3,4)",
+ "",
+
+ "RDD=contract(RUDDD,1,3)",
+ "",
+
+ "R=contract(contract(outer(guu,RDD),2,3),1,2)",
+ "",
+
+ "GDD=RDD-1/2*gdd*R",
+ "",
+
+ "Gtt=1/r^2*exp(2 Phi(r)) d(r*(1 - exp(-2 Lambda(r))),r)",
+ "",
+
+ "Grr=-1/r^2*exp(2*Lambda(r))*(1-exp(-2*Lambda(r)))+2/r*d(Phi(r),r)",
+ "",
+
+ "Gthetatheta=r^2*exp(-2*Lambda(r))*(d(d(Phi(r),r),r)+d(Phi(r),r)^2+d(Phi(r),r)/r-d(Phi(r),r)*d(Lambda(r),r)-d(Lambda(r),r)/r)",
+ "",
+
+ "Gphiphi=sin(theta)^2*Gthetatheta",
+ "",
+
+ "T=[[Gtt,0,0,0],[0,Grr,0,0],[0,0,Gthetatheta,0],[0,0,0,Gphiphi]]",
+ "",
+
+ "GDD-T",
+ "[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]",
+
+ # surface integral example from the manual
+
+ "clearall",
+ "",
+
+ "z=1-x^2-y^2",
+ "",
+
+ "F=[x*y^2*z,-2*x^3,y*z^2]",
+ "",
+
+ "S=[x,y,z]",
+ "",
+
+ "s=dot(F,cross(d(S,x),d(S,y)))",
+ "",
+
+ "defint(s,y,-sqrt(1-x^2),sqrt(1-x^2),x,-1,1)",
+ "1/48*pi",
+
+ # hydrogen wavefunction example
+
+ "clearall",
+ "",
+
+ "laplacian(f)=1/r^2*d(r^2*d(f,r),r)+1/(r^2*sin(theta))*d(sin(theta)*d(f,theta),theta)+1/(r*sin(theta))^2*d(f,phi,phi)",
+ "",
+
+ "n=7",
+ "",
+
+ "l=3",
+ "",
+
+ "m=1",
+ "",
+
+ "R=r^l*exp(-r/n)*laguerre(2*r/n,n-l-1,2*l+1)",
+ "",
+
+ "Y=legendre(cos(theta),l,abs(m))*exp(i*m*phi)",
+ "",
+
+ "psi=R*Y",
+ "",
+
+ "E=psi/n^2",
+ "",
+
+ "K=laplacian(psi)",
+ "",
+
+ "V=2*psi/r",
+ "",
+
+ # after the changes to abs and mag of Jan 2017
+ # , some abs/mag are introduced in the results of legendre
+ # (correctly, I believe),
+ # which makes this expression != 0.
+ # TODO this can work only after all the absolute values
+ # have been removed
+ #"circexp(sin(theta)*(E-K-V))",
+ #"0",
+
+ # Green's theorem (surface integral)
+
+ "clearall",
+ "",
+
+ "P=2x^3-y^3",
+ "",
+
+ "Q=x^3+y^3",
+ "",
+
+ "f=d(Q,x)-d(P,y)",
+ "",
+
+ "x=r*cos(theta)",
+ "",
+
+ "y=r*sin(theta)",
+ "",
+
+ "defint(f*r,r,0,1,theta,0,2pi)",
+ "3/2*pi",
+
+ # Green's theorem (line integral)
+
+ "clearall",
+ "",
+
+ "x=cos(t)",
+ "",
+
+ "y=sin(t)",
+ "",
+
+ "P=2x^3-y^3",
+ "",
+
+ "Q=x^3+y^3",
+ "",
+
+ "f=P*d(x,t)+Q*d(y,t)",
+ "",
+
+ "f=circexp(f)",
+ "",
+
+ "defint(f,t,0,2pi)",
+ "3/2*pi",
+
+ # Stokes' theorem (surface integral)
+
+ "clearall",
+ "",
+
+ "z=9-x^2-y^2",
+ "",
+
+ "F=[3y,4z,-6x]",
+ "",
+
+ "S=[x,y,z]",
+ "",
+
+ "f=dot(curl(F),cross(d(S,x),d(S,y)))",
+ "",
+
+ "x=r*cos(theta)",
+ "",
+
+ "y=r*sin(theta)",
+ "",
+
+ "defint(f*r,r,0,3,theta,0,2pi)",
+ "-27*pi",
+
+ # Stokes' theorem (line integral)
+
+ "clearall",
+ "",
+
+ "x=3*cos(t)",
+ "",
+
+ "y=3*sin(t)",
+ "",
+
+ "z=9-x^2-y^2",
+ "",
+
+ "P=3y",
+ "",
+
+ "Q=4z",
+ "",
+
+ "R=-6x",
+ "",
+
+ "f=P*d(x,t)+Q*d(y,t)+R*d(z,t)",
+ "",
+
+ "f=circexp(f)",
+ "",
+
+ "defint(f,t,0,2pi)",
+ "-27*pi",
+ ]
+
diff --git a/node_modules/algebrite/tests/mixedprint.coffee b/node_modules/algebrite/tests/mixedprint.coffee
new file mode 100644
index 0000000..83da531
--- /dev/null
+++ b/node_modules/algebrite/tests/mixedprint.coffee
@@ -0,0 +1,220 @@
+test_mixedprint = ->
+ run_test [
+
+ "1.0",
+ "1.0",
+
+ "1111 * 1111.0",
+ "1234321.0",
+
+ "1111.0 * 1111",
+ "1234321.0",
+
+ "1111.0 * 1111.0",
+ "1234321.0",
+
+ "11111111 * 11111111.0",
+ "123456787654321.0",
+
+ "11111111.0 * 11111111",
+ "123456787654321.0",
+
+ "11111111.0 * 11111111.0",
+ "123456787654321.0",
+
+ # unfortunately using Numbers
+ # at some point we hit the precision
+ "111111111 * 111111111.0",
+ "12345678987654320.0",
+
+ # unfortunately using Numbers
+ # at some point we hit the precision
+ "111111111.0 * 111111111",
+ "12345678987654320.0",
+
+ # unfortunately using Numbers
+ # at some point we hit the precision
+ "111111111.0 * 111111111.0",
+ "12345678987654320.0",
+
+ "1.0*10^(-6)",
+ "0.000001",
+
+ # check that this doesn't return 0.0
+ "1.0*10^(-7)",
+ "0.000000...",
+
+ # ------------------------------------------
+ "maxFixedPrintoutDigits",
+ "6",
+
+ "maxFixedPrintoutDigits=20",
+ "",
+
+ "maxFixedPrintoutDigits",
+ "20",
+
+ "1.0*10^(-15)",
+ "0.000000000000001",
+
+ "printhuman",
+ "0.000000000000001",
+
+ "printcomputer",
+ "0.000000000000001",
+
+ "printlatex",
+ "0.000000000000001",
+
+ "printlist",
+ "0.000000000000001",
+
+ "print2dascii",
+ "0.000000000000001",
+
+ "forceFixedPrintout=0",
+ "",
+
+ "1.0*10^(-15)",
+ "1.0*10^(-15)",
+
+ "printhuman",
+ "1.0*10^(-15)",
+
+ "printcomputer",
+ "1.0*10^(-15)",
+
+ "printlatex",
+ "1.0\\mathrm{e}{-15}",
+
+ "printlist",
+ "1.0*10^(-15)",
+
+ "print2dascii",
+ "1.0*10^(-15)",
+
+ "forceFixedPrintout=1",
+ "",
+
+ "maxFixedPrintoutDigits=6",
+ "",
+
+ # ------------------------------------------
+
+ "float(pi)",
+ "3.141593...",
+
+ "print(\"hello\")",
+ "\"hello\"",
+
+ "-sqrt(2)/2",
+ "-1/2*2^(1/2)",
+
+ # we can't get rid of the multiplication sign
+ # in general, because expressions like
+ # (x+1)(x-1) actually represent a function call
+ # We could get rid of the multiplication sign
+ # in these special cases where there are numeric
+ # constants but we don't do that yet.
+ "printhuman",
+ "-1/2 2^(1/2)",
+
+ "printcomputer",
+ "-1/2*2^(1/2)",
+
+ "printlatex",
+ "-\\frac{\\sqrt{2}}{2}",
+
+ "printlist",
+ "(multiply -1/2 (power 2 1/2))",
+
+ "printlist(a+b)\nprintlist(c+d)",
+ "(add a b)(add c d)",
+
+ "print2dascii",
+ " 1 1/2\n- --- 2\n 2",
+
+ "last2dasciiprint",
+ "\" 1 1/2\n- --- 2\n 2\"",
+
+ # checks that no extra newlines are
+ # inserted
+ "x=0\ny=2\nfor(do(x=sqrt(2+x),y=2*y/x,printcomputer(y)),k,1,2)",
+ "2*2^(1/2)4*2^(1/2)/((2+2^(1/2))^(1/2))",
+
+ "clearall",
+ "",
+
+ "print2dascii([[a,b],[c,d]])",
+ "a b\n\nc d",
+
+ "print2dascii(1/sqrt(-15))",
+ " 1/2\n (-1)\n- -----------\n 1/2 1/2\n 3 5",
+
+ "print2dascii(x^(1/a))",
+ " 1/a\nx",
+
+ "print2dascii(x^(a/b))",
+ " a/b\nx",
+
+ "print2dascii(x^(a/2))",
+ " 1/2 a\nx",
+
+ "print2dascii(x^(1/(a+b)))",
+ " 1/(a + b)\nx",
+
+ # ------------------------------------------
+
+ "(5/3)!",
+ "(5/3)!",
+
+ "printhuman",
+ "(5/3)!",
+
+ "printcomputer",
+ "(5/3)!",
+
+ "printlatex",
+ "(\\frac{5}{3})!",
+
+ "printlist",
+ "(factorial 5/3)",
+
+ "print2dascii",
+ " 5\n(---)!\n 3",
+
+ # bug #106 ---------------------------------
+ # printing terms that are not "normalised"
+ # following an eval, one can't assume that
+ # the numbers are all leading, hence some
+ # checks had to be refined when printing
+ # the signs
+
+ "clearall",
+ "",
+
+ "print(quote(k*(-2)))",
+ "k*(-2)",
+
+ "print(quote(k*(-1/2)))",
+ "k*(-1/2)",
+
+ "print(quote(k*2))",
+ "k*2",
+
+ "print(quote(k*1/2))",
+ "k*1/2",
+
+ "print(k*(-2))",
+ "-2*k",
+
+ "print(k*(-1/2))",
+ "-1/2*k",
+
+ "print(k*2)",
+ "2*k",
+
+ "print(k*1/2)",
+ "1/2*k",
+
+ ]
diff --git a/node_modules/algebrite/tests/mmul.coffee b/node_modules/algebrite/tests/mmul.coffee
new file mode 100644
index 0000000..e2b4bd1
--- /dev/null
+++ b/node_modules/algebrite/tests/mmul.coffee
@@ -0,0 +1,79 @@
+test_mmul = ->
+ i = 0
+ j = 0
+ m = 0
+ logout("test mmul\n")
+ for i in [-100..100]
+ for j in [-100..100]
+ test_mmulf(i, j, i * j)
+ logout("ok\n")
+
+test_mmulf = (na, nb, nc) ->
+
+ a = mint(na)
+ b = mint(nb)
+ c = mint(nc)
+
+ d = mmul(a, b)
+
+ if (mcmp(c, d) == 0)
+ return
+ else
+ throw new Error("test_mmulf error")
+
+test_mdiv = ->
+ i = 0
+ j = 0
+ m = 0
+ logout("test mdiv\n")
+ for i in [-100..100]
+ for j in [-100..100]
+ if (j)
+ if i/j > 0
+ expectedResult = Math.floor(i / j)
+ else
+ expectedResult = Math.ceil(i / j)
+ test_mdivf(i, j, expectedResult)
+ logout("ok\n")
+
+test_mdivf = (na, nb, nc) ->
+
+ a = mint(na)
+ b = mint(nb)
+ c = mint(nc)
+
+ d = mdiv(a, b)
+
+ if (mcmp(c, d) == 0)
+ return
+ else
+ debugger
+ throw new Error("test_mdivf error")
+
+
+test_mmod = ->
+ i = 0
+ j = 0
+ m = 0
+ logout("test mmod\n")
+ for i in [-100..100]
+ for j in [-100..100]
+ if (j)
+ test_mmodf(i, j, i % j)
+ logout("ok\n")
+
+test_mmodf = (na,nb,nc) ->
+
+ a = mint(na)
+ b = mint(nb)
+ c = mint(nc)
+
+ d = mmod(a, b)
+
+ if (mcmp(c, d) == 0)
+ return
+ else
+ throw new Error("test_mmodf error")
+
+
+
diff --git a/node_modules/algebrite/tests/mod.coffee b/node_modules/algebrite/tests/mod.coffee
new file mode 100644
index 0000000..b2112ad
--- /dev/null
+++ b/node_modules/algebrite/tests/mod.coffee
@@ -0,0 +1,44 @@
+test_mod = ->
+ run_test [
+ "mod(2.0,3.0)",
+ "2",
+
+ "mod(-2.0,3.0)",
+ "-2",
+
+ "mod(2.0,-3.0)",
+ "2",
+
+ "mod(-2.0,-3.0)",
+ "-2",
+
+ "mod(2,3)",
+ "2",
+
+ "mod(-2,3)",
+ "-2",
+
+ "mod(2,-3)",
+ "2",
+
+ "mod(-2,-3)",
+ "-2",
+
+ "mod(a,b)",
+ "mod(a,b)",
+
+ "mod(2.0,0.0)",
+ "Stop: mod function: divide by zero",
+
+ "mod(2,0)",
+ "Stop: mod function: divide by zero",
+
+ "mod(1.2,2)",
+ "Stop: mod function: cannot convert float value to integer",
+
+ "mod(1/2,3)",
+ "Stop: mod function: integer arguments expected",
+
+ "mod(15,8.0)",
+ "7",
+ ]
diff --git a/node_modules/algebrite/tests/mpow.coffee b/node_modules/algebrite/tests/mpow.coffee
new file mode 100644
index 0000000..a7a4c16
--- /dev/null
+++ b/node_modules/algebrite/tests/mpow.coffee
@@ -0,0 +1,20 @@
+test_mpow = ->
+ logout("testing mpow\n")
+
+
+ # small numbers
+
+ for i in [-10...10]
+ a = mint(i)
+ x = 1
+ for j in [0...10]
+ b = mpow(a, j)
+ c = mint(x)
+ if (mcmp(b, c) != 0)
+ throw new Error("failed test_mpow")
+ x *= i
+
+
+ logout("ok\n")
+
+#endif
diff --git a/node_modules/algebrite/tests/mprime.coffee b/node_modules/algebrite/tests/mprime.coffee
new file mode 100644
index 0000000..1e01a74
--- /dev/null
+++ b/node_modules/algebrite/tests/mprime.coffee
@@ -0,0 +1,19 @@
+test_mprime = ->
+ i = 0
+ k = 0
+ m = 0
+ t = 0
+ logout("test mprime\n")
+ k = 0
+ for i in [0...10000]
+ n = mint(i)
+ t = mprime(n)
+ if (i == primetab[k])
+ if (t == 0)
+ throw new Error("failed for prime number " + i)
+ k++
+ else if (t == 1)
+ throw new Error("failed for composite number " + i)
+ logout("ok\n")
+
+#endif
diff --git a/node_modules/algebrite/tests/mroot.coffee b/node_modules/algebrite/tests/mroot.coffee
new file mode 100644
index 0000000..997559d
--- /dev/null
+++ b/node_modules/algebrite/tests/mroot.coffee
@@ -0,0 +1,34 @@
+test_mroot = ->
+ i = 0
+ j = 0
+ mem = 0
+
+ logout("testing mroot\n")
+
+
+ # small numbers
+
+ for i in [0...10]
+ a = mint(i)
+ for j in [1...10]
+ #logout(i + " " + j)
+ b = mpow(a, j)
+ c = mroot(b, j)
+ if (c == 0 || mcmp(a, c) != 0)
+ debugger
+ throw new Error("failed test_mroot")
+
+ logout(" ...mroot small numbers ok\n")
+
+ a = mint(12345)
+
+ for i in [1...10]
+ #logout(i)
+ b = mpow(a, i)
+ c = mroot(b, i)
+ if (c == 0 || mcmp(a, c) != 0)
+ throw new Error("failed")
+
+
+ logout(" ...mroot big numbers ok\n")
+ logout("ok")
diff --git a/node_modules/algebrite/tests/multiply.coffee b/node_modules/algebrite/tests/multiply.coffee
new file mode 100644
index 0000000..57320b4
--- /dev/null
+++ b/node_modules/algebrite/tests/multiply.coffee
@@ -0,0 +1,124 @@
+test_multiply = ->
+ if DEBUG then console.log "test_multiply ----------------------------"
+ run_test [
+
+ "0*a",
+ "0",
+
+ "a*0",
+ "0",
+
+ "1*a",
+ "a",
+
+ "a*1",
+ "a",
+
+ "0.0*a",
+ "0.0",
+
+ "a*0.0",
+ "0.0",
+
+ "1.0*a",
+ "1.0*a",
+
+ "a*1.0",
+ "1.0*a",
+
+ "a*a",
+ "a^2",
+
+ "a^2*a",
+ "a^3",
+
+ "a*a^2",
+ "a^3",
+
+ "a^2*a^2",
+ "a^4",
+
+ "2^a*2^(3-a)", # symbolic exponents cancel
+ "8",
+
+ "sqrt(2)/2",
+ # leave the roots nice and
+ # clean in numerator, avoid these
+ # forms
+ #"2^(-1/2)",
+ "1/2*2^(1/2)",
+
+ "2/sqrt(2)",
+ "2^(1/2)",
+
+ "-sqrt(2)/2",
+ # avoid having roots in denominator
+ #"-1/(2^(1/2))",
+ "-1/2*2^(1/2)",
+
+ "2^(1/2-a)*2^a/10",
+ # avoid roots in denominator
+ #"1/(5*2^(1/2))",
+ "1/10*2^(1/2)",
+
+ "i/4",
+ "1/4*i",
+
+ "1/(4 i)",
+ "-1/4*i",
+
+ # ensure 1.0 is not discarded
+
+ "1.0 pi 1/2",
+ "1.570796...",
+
+ "1.0 1/2 pi",
+ "1.570796...",
+
+ # https://github.com/davidedc/Algebrite/issues/121
+
+ "1 - 1/2*0^2",
+ "1",
+
+ "1 - 3/2*0^2",
+ "1",
+
+ "1 - 1/2*0^1",
+ "1",
+
+
+ "1 - 1/2*(-0^2)",
+ "1",
+
+ "1 - 1/2*5^2",
+ "-23/2",
+
+ "1 + 1/2*0^2",
+ "1",
+
+ "1 + (-1/2*0^2)",
+ "1",
+
+ "-1/2*0^2",
+ "0",
+
+ "1 - 1/2*0*0",
+ "1",
+
+ "1 - 1/x*0^2",
+ "1",
+
+ "1 - 10/2*0^2",
+ "1",
+
+ "1 - 2*0^2",
+ "1",
+
+ "1 - 0^2",
+ "1",
+
+ "1 - 0^2*(1/2)",
+ "1",
+
+
+ ]
diff --git a/node_modules/algebrite/tests/nroots.coffee b/node_modules/algebrite/tests/nroots.coffee
new file mode 100644
index 0000000..52f0f77
--- /dev/null
+++ b/node_modules/algebrite/tests/nroots.coffee
@@ -0,0 +1,14 @@
+test_nroots = ->
+ run_test [
+ "nroots(x)",
+ "0",
+
+ "nroots((1+i)*x^2+1)",
+ "[-0.171780...-0.727673...*i,0.171780...+0.727673...*i]",
+
+ "nroots(sqrt(2)*exp(i*pi/4)*x^2+1)",
+ "[-0.171780...-0.727673...*i,0.171780...+0.727673...*i]",
+
+ # "nroots(x^4+1)",
+ # "(-0.707107+0.707107*i,-0.707107-0.707107*i,0.707107+0.707107*i,0.707107-0.707107*i)",
+ ]
diff --git a/node_modules/algebrite/tests/numerator.coffee b/node_modules/algebrite/tests/numerator.coffee
new file mode 100644
index 0000000..6eb0e99
--- /dev/null
+++ b/node_modules/algebrite/tests/numerator.coffee
@@ -0,0 +1,18 @@
+test_numerator = ->
+ run_test [
+
+ "numerator(2/3)",
+ "2",
+
+ "numerator(x)",
+ "x",
+
+ "numerator(1/x)",
+ "1",
+
+ "numerator(a+b)",
+ "a+b",
+
+ "numerator(1/a+1/b)",
+ "a+b",
+ ]
diff --git a/node_modules/algebrite/tests/outer.coffee b/node_modules/algebrite/tests/outer.coffee
new file mode 100644
index 0000000..428e121
--- /dev/null
+++ b/node_modules/algebrite/tests/outer.coffee
@@ -0,0 +1,32 @@
+test_outer = ->
+ run_test [
+ "outer(a,b)",
+ "a*b",
+
+ "outer(a,[b1,b2])",
+ "[a*b1,a*b2]",
+
+ "outer([a1,a2],b)",
+ "[a1*b,a2*b]",
+
+ "H33=hilbert(3)",
+ "",
+
+ "H44=hilbert(4)",
+ "",
+
+ "H55=hilbert(5)",
+ "",
+
+ "H3344=outer(H33,H44)",
+ "",
+
+ "H4455=outer(H44,H55)",
+ "",
+
+ "H33444455=outer(H33,H44,H44,H55)",
+ "",
+
+ "simplify(inner(H3344,H4455)-contract(H33444455,4,5))",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/pattern.coffee b/node_modules/algebrite/tests/pattern.coffee
new file mode 100644
index 0000000..c52563b
--- /dev/null
+++ b/node_modules/algebrite/tests/pattern.coffee
@@ -0,0 +1,367 @@
+test_pattern = ->
+ run_test [
+
+ "pattern(dot(transpose(a_),a_), cov(a_))",
+ "dot(transpose(a_),a_)->cov(a_)",
+
+ "pattern(dot(a_,transpose(a_)), cov(a_))",
+ "dot(a_,transpose(a_))->cov(a_)",
+
+ #"pattern(cov(transpose(a_)), cov(a_))",
+ #"",
+
+ "simplify(1 + eig(dot(transpose(A+B),B+transpose(transpose(A)))))",
+ "1+eig(cov(A+B))",
+
+ "simplify(1 + eig(dot(x*transpose(transpose(A)), transpose(x*A))))",
+ "1+eig(cov(transpose(A)*transpose(x)))",
+
+ # ideally this but we need to make simplifications work better
+ # "1+eig(cov(A*x))",
+
+ "simplify(1 + eig(dot(x*transpose(transpose(A)), transpose(A*x))))",
+ "1+eig(cov(transpose(A)*transpose(x)))",
+
+ "simplify(1 + eig(dot(x*Aᵀᵀ, (A*x)ᵀ)))",
+ "1+eig(cov(transpose(A)*transpose(x)))",
+
+ # ideally this but we need to make simplifications work better
+ # "1+eig(cov(A*x))",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+
+
+ "simplify(integral(1/(X-A)/sqrt(X^2-A^2),X)+sqrt(X^2-A^2)/A/(X-A))",
+ "0",
+
+
+ # ------------------------------------------------------------------
+
+
+ "pattern(dot(transpose(a_),a_), cov(a_))",
+ "dot(transpose(a_),a_)->cov(a_)",
+
+ "simplify(integral(1/(X-A)/sqrt(X^2-A^2),X)+sqrt(X^2-A^2)/A/(X-A))",
+ "0",
+
+
+ # ------------------------------------------------------------------
+
+
+ "simplify(eig(dot(transpose(A+B),B+transpose(transpose(A)))))",
+ "eig(cov(A+B))",
+
+ "simplify(eig(dot(x*transpose(transpose(A)), transpose(A*x))))",
+ "eig(cov(transpose(A)*transpose(x)))",
+
+ "simplify(eig(dot(x*transpose(transpose(A)), transpose(x*A))))",
+ "eig(cov(transpose(A)*transpose(x)))",
+
+
+ # ------------------------------------------------------------------
+
+
+ "pattern(dot(a_,transpose(a_)), cov(a_))",
+ "dot(a_,transpose(a_))->cov(a_)",
+
+ "simplify(eig(dot(transpose(A+B),B+transpose(transpose(A)))))",
+ "eig(cov(A+B))",
+
+ "simplify(eig(dot(x*transpose(transpose(A)), transpose(x*A))))",
+ "eig(cov(transpose(A)*transpose(x)))",
+
+ "simplify(eig(dot(x*transpose(transpose(A)), transpose(A*x))))",
+ "eig(cov(transpose(A)*transpose(x)))",
+
+ "clearpatterns()",
+ "",
+
+
+ # ------------------------------------------------------------------
+
+
+
+ "simplify(eig(dot(transpose(A+B),B+transpose(transpose(A)))))",
+ "eig(inner(transpose(A),A)+inner(transpose(A),B)+inner(transpose(B),A)+inner(transpose(B),B))",
+
+
+ # ------------------------------------------------------------------
+
+
+ "pattern(dot(transpose(a_),a_), cov(a_), not(number(a_)))",
+ "dot(transpose(a_),a_)->cov(a_)",
+
+ "pattern(dot(transpose(a_),a_), cov(a_), number(a_),a_>0 )",
+ "dot(transpose(a_),a_)->cov(a_)",
+
+ "simplify(eig(dot(transpose(3),transpose(transpose(3)))))",
+ "eig(9)",
+
+ "simplify(eig(dot(transpose(-3),transpose(transpose(-3)))))",
+ "eig(9)",
+
+ "simplify(eig(dot(transpose(-x),transpose(transpose(-x)))))",
+ "eig(cov(-x))",
+
+ "clearpatterns()",
+ "",
+
+
+ # ------------------------------------------------------------------
+
+
+
+ "pattern(something(a_,b_),b_*somethingElse(a_))",
+ "something(a_,b_)->b_*somethingElse(a_)",
+
+ "simplify(something(x,y))",
+ "somethingElse(x)*y",
+
+ "clearpatterns()",
+ "",
+
+
+ # ------------------------------------------------------------------
+
+
+
+ "pattern(something(a_,b_),b_*somethingElse(a_))",
+ "something(a_,b_)->b_*somethingElse(a_)",
+
+ "indirection(h,k) = something(h,k)",
+ "",
+
+ "simplify(indirection(x,y))",
+ "somethingElse(x)*y",
+
+ "clearpatterns()",
+ "",
+
+
+ # ------------------------------------------------------------------
+
+
+ "pattern(dot(a_,transpose(a_)), cov(a_))",
+ "dot(a_,transpose(a_))->cov(a_)",
+
+ "simplify(1 + eig(dot(transpose(A)+transpose(B),B+transpose(transpose(A)))))",
+ "1+eig(inner(transpose(A),A)+inner(transpose(A),B)+inner(transpose(B),A)+inner(transpose(B),B))",
+
+ # catches if a guard works against substituting bare native functions
+ "simplify(1 + eig(dot(transpose(A)+transpose(B),B+transpose(transpose(A)))))",
+ "1+eig(inner(transpose(A),A)+inner(transpose(A),B)+inner(transpose(B),A)+inner(transpose(B),B))",
+
+ "clearpatterns()",
+ "",
+
+
+ # ------------------------------------------------------------------
+
+
+ "pattern(dot(transpose(a_),a_), cov(a_))",
+ "dot(transpose(a_),a_)->cov(a_)",
+
+ # picks up that transpose(abs(k))
+ # is a substitution that works
+ "simplify(1 + eig(dot(abs(k),transpose(abs(k)))))",
+ "1+eig(cov(transpose(abs(k))))",
+
+ # picks up that transpose(b(2))
+ # is a substitution that works
+ "simplify(1 + eig(dot(b(2),transpose(b(2)))))",
+ "1+eig(cov(transpose(b(2))))",
+
+ "clearpatterns()",
+ "",
+
+
+ # ------------------------------------------------------------------
+
+ "pattern(a_ + b_, dot(cov(b_),cov(a_)))",
+ "a_+b_->dot(cov(b_),cov(a_))",
+
+ "simplify(something + somethingelse)",
+ "inner(cov(somethingelse),cov(something))",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "simplify(aFunction(someArg))",
+ "anotherFunction(someArg)",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "simplify(1 + aFunction(someArg))",
+ "1+anotherFunction(someArg)",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "simplify(aFunction(someArg)+aFunction(someOtherArg))",
+ "anotherFunction(someArg)+anotherFunction(someOtherArg)",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "simplify( a + aFunction(someArg) + b + aFunction(someOtherArg))",
+ "a+b+anotherFunction(someArg)+anotherFunction(someOtherArg)",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "simplify(aFunction(aFunction(someOtherArg)))",
+ "anotherFunction(anotherFunction(someOtherArg))",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "pattern(aFunction(a_), anotherFunctionBBBB(a_))",
+ "aFunction(a_)->anotherFunctionBBBB(a_)",
+
+ "simplify(aFunction(aFunction(someOtherArg)))",
+ "anotherFunctionBBBB(anotherFunctionBBBB(someOtherArg))",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunctionBBBB(a_))",
+ "aFunction(a_)->anotherFunctionBBBB(a_)",
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "simplify(aFunction(aFunction(someOtherArg)))",
+ "anotherFunction(anotherFunction(someOtherArg))",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "pattern(anotherFunction(a_), YETanotherFunction(a_))",
+ "anotherFunction(a_)->YETanotherFunction(a_)",
+
+ "simplify(aFunction(aFunction(someOtherArg)))",
+ "YETanotherFunction(YETanotherFunction(someOtherArg))",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+ # this one tests if multiple rounds of ruleS applications are
+ # done while there are still trasformations succeeding.
+
+ "pattern(anotherFunction(a_), YETanotherFunction(a_))",
+ "anotherFunction(a_)->YETanotherFunction(a_)",
+
+ "pattern(aFunction(a_), anotherFunction(a_))",
+ "aFunction(a_)->anotherFunction(a_)",
+
+ "simplify(aFunction(aFunction(someOtherArg)))",
+ "YETanotherFunction(YETanotherFunction(someOtherArg))",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+ # you can use transformation rules to calculate factorials
+ # you shouldn't, but you can
+
+ "pattern(fact(0), 1)",
+ "fact(0)->1",
+
+ # TODO would be nice to print out the constraints
+ # as well.
+ "pattern(fact(a_), a_*fact(a_-1), not(a_ == 0))",
+ "fact(a_)->a_*fact(a_-1)",
+
+ "simplify(fact(3))",
+ "6",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(f(a_,b_),f(b_,a_))",
+ "f(a_,b_)->f(b_,a_)",
+
+ # TODO would be nice to print out the constraints
+ # as well.
+ "simplify(f(1,2))",
+ "Stop: maximum application of single transformation rule exceeded: f(a_,b_)(f(b_,a_))",
+
+ "clearpatterns()",
+ "",
+
+ # overwriting a pattern ---------------------------------------------
+
+ "pattern(a_ + a_ ,42 * a_)",
+ "a_+a_->42*a_",
+
+ "pattern(a_ + a_ ,21 * a_)",
+ "a_+a_->21*a_",
+
+ "simplify(x+x)",
+ "21*x",
+
+ "clearpatterns()",
+ "",
+
+ # ------------------------------------------------------------------
+
+ "pattern(f(a_,b_))",
+ "Stop: pattern needs at least a template and a transformed version",
+
+ # ------------------------------------------------------------------
+
+ "pattern()",
+ "Stop: pattern needs at least a template and a transformed version",
+
+ # ------------------------------------------------------------------
+
+ "pattern(f(a_,b_), f(a_,b_))",
+ "Stop: recursive pattern",
+
+
+ ]
diff --git a/node_modules/algebrite/tests/polar.coffee b/node_modules/algebrite/tests/polar.coffee
new file mode 100644
index 0000000..8986f87
--- /dev/null
+++ b/node_modules/algebrite/tests/polar.coffee
@@ -0,0 +1,66 @@
+test_polar = ->
+ run_test [
+ "polar(1+i)",
+ "2^(1/2)*exp(1/4*i*pi)",
+
+ "polar(-1+i)",
+ "2^(1/2)*exp(3/4*i*pi)",
+
+ "polar(-1-i)",
+ "2^(1/2)*exp(-3/4*i*pi)",
+
+ "polar(1-i)",
+ "2^(1/2)*exp(-1/4*i*pi)",
+
+ "rect(polar(3+4*i))",
+ "3+4*i",
+
+ "rect(polar(-3+4*i))",
+ "-3+4*i",
+
+ "rect(polar(3-4*i))",
+ "3-4*i",
+
+ "rect(polar(-3-4*i))",
+ "-3-4*i",
+
+ "rect(polar((-1)^(1/2)))",
+ "i",
+
+ "rect(polar((-1)^(-5/6)))",
+ "-1/2*i-1/2*3^(1/2)",
+
+ "rect(polar((-1)^(-5/a)))",
+ "cos(5*pi/a)-i*sin(5*pi/a)",
+
+ "rect(polar((-1)^(a)))",
+ "cos(a*pi)+i*sin(a*pi)",
+
+ "-i*(-2*rect(polar((-1)^(1/6)))/rect(polar((3^(1/2))))+2*rect(polar((-1)^(5/6)))/rect(polar((3^(1/2)))))^(1/4)*(2*rect(polar((-1)^(1/6)))/rect(polar((3^(1/2))))-2*rect(polar((-1)^(5/6)))/rect(polar((3^(1/2)))))^(1/4)/(2^(1/2))",
+ #"-(-1)^(3/4)",
+ "1/2^(1/2)-i/(2^(1/2))",
+
+ # this is also "-(-1)^(3/4)" but we get to that after the simplification after
+ # this test
+ "-i*(-2*polar((-1)^(1/6))/polar((3^(1/2)))+2*polar((-1)^(5/6))/polar((3^(1/2))))^(1/4)*(2*polar((-1)^(1/6))/polar((3^(1/2)))-2*polar((-1)^(5/6))/polar((3^(1/2))))^(1/4)/(2^(1/2))",
+ "-i*(-2*exp(1/6*i*pi)/(3^(1/2))+2*exp(5/6*i*pi)/(3^(1/2)))^(1/4)*(2*exp(1/6*i*pi)/(3^(1/2))-2*exp(5/6*i*pi)/(3^(1/2)))^(1/4)/(2^(1/2))",
+
+ "simplify",
+ "(1-i)/(2^(1/2))",
+
+ "-i*(-2*rect(exp(1/6*i*pi))/(3^(1/2))+2*rect(exp(5/6*i*pi))/(3^(1/2)))^(1/4)*(2*rect(exp(1/6*i*pi))/(3^(1/2))-2*rect(exp(5/6*i*pi))/(3^(1/2)))^(1/4)/(2^(1/2))",
+ #"-(-1)^(3/4)",
+ "1/2^(1/2)-i/(2^(1/2))",
+
+ "polar(-(-1)^(3/4))",
+ "exp(-1/4*i*pi)",
+
+ "polar(-i*(-2*(-1)^(1/6)/(3^(1/2))+2*(-1)^(5/6)/(3^(1/2)))^(1/4)*(2*(-1)^(1/6)/(3^(1/2))-2*(-1)^(5/6)/(3^(1/2)))^(1/4)/(2^(1/2)))",
+ "exp(-1/4*i*pi)",
+
+ # nothing to do for polar since we end
+ # up with a real
+ "polar((-1)^(1/6) - (-1)^(5/6))",
+ "3^(1/2)",
+
+ ]
diff --git a/node_modules/algebrite/tests/power.coffee b/node_modules/algebrite/tests/power.coffee
new file mode 100644
index 0000000..bbd6925
--- /dev/null
+++ b/node_modules/algebrite/tests/power.coffee
@@ -0,0 +1,296 @@
+test_power = ->
+ run_test [
+
+ # according to the notorious
+ # "PEMDAS" mnemonic, the power
+ # operator has the most precedence.
+ # Strangely, Mathematica parses
+ # a^1/2 as sqrt(a), not following PEMDAS,
+ # probably because of some fancy
+ # euristics, since, contrarily to the
+ # case above, it also parses
+ # a^b/2 as (a^b)/2.
+ # I think this more standard/uniform handling
+ # a-la-sympy is ok.
+ "a^1/2 + a^1/2",
+ "a",
+
+ "2^(1/2)",
+ "2^(1/2)",
+
+ "2^(3/2)",
+ "2*2^(1/2)",
+
+ "(-2)^(1/2)",
+ "i*2^(1/2)",
+
+ "3^(4/3)",
+ "3*3^(1/3)",
+
+ "3^(-4/3)",
+ "1/(3*3^(1/3))",
+
+ "3^(5/3)",
+ "3*3^(2/3)",
+
+ "3^(2/3)-9^(1/3)",
+ "0",
+
+ "3^(10/3)",
+ "27*3^(1/3)",
+
+ "3^(-10/3)",
+ "1/(27*3^(1/3))",
+
+ "(1/3)^(10/3)",
+ "1/(27*3^(1/3))",
+
+ "(1/3)^(-10/3)",
+ "27*3^(1/3)",
+
+ "27^(2/3)",
+ "9",
+
+ "27^(-2/3)",
+ "1/9",
+
+ "102^(1/2)",
+ "2^(1/2)*3^(1/2)*17^(1/2)",
+
+ "32^(1/3)",
+ "2*2^(2/3)",
+
+ "9999^(1/2)",
+ "3*11^(1/2)*101^(1/2)",
+
+ "8^(1/2)",
+ "2*2^(1/2)",
+
+ "10000^(1/3)",
+ "10*2^(1/3)*5^(1/3)",
+
+ # we could take out a "18" from the radix but
+ # we only handle this for small numbers in
+ # "quickfactor" routine. TODO
+ "8204861575751304355842204^(1/2)",
+ "8204861575751304355842204^(1/2)",
+
+ # see above
+ "simplify(8204861575751304355842204^(1/2))",
+ "8204861575751304355842204^(1/2)",
+
+ "sqrt(-1/2 -1/2 * x)",
+ "(-1/2*x-1/2)^(1/2)",
+
+ "sqrt(x*y)",
+ "(x*y)^(1/2)",
+
+ "sqrt(1/x)",
+ "(1/x)^(1/2)",
+
+ "sqrt(x^y)",
+ "(x^y)^(1/2)",
+
+ "sqrt(x)^2",
+ "x",
+
+ "sqrt(x^2)",
+ "abs(x)",
+
+ # always true, whether x is real or not
+ "sqrt(x^2)^2",
+ "x^2",
+
+ "3^(1/2)*i/9",
+ "1/9*i*3^(1/2)",
+
+ "(-4.0)^(1.5)",
+ "-8.0*i",
+
+ "(-4.0)^(3/2)",
+ "-8.0*i",
+
+ # usually the rectangular form is returned.
+ "(-1)^(1/3)",
+ #"(-1)^(1/3)",
+ "1/2+1/2*i*3^(1/2)",
+
+ # note how the "double" type
+ # is toxic i.e. it propagates through
+ # everything it touches.
+ # also, that -0.500000... _really_ is 0.5
+ # however we get some error in the calculations
+ # so it doesn't end up being exactly equal to -0.5
+ "(-1.0)^(2/3)",
+ "-0.500000...+0.866025...*i",
+
+ # this also has a nested radical
+ # form but we are not calculating
+ # that.
+ "(-1)^(1/3)*2^(1/4)",
+ #"(-1)^(1/3)*2^(1/4)",
+ "1/2*2^(1/4)+1/2*i*2^(1/4)*3^(1/2)",
+
+ "(-1)^(1/2)",
+ "i",
+
+ "sqrt(1000000)",
+ "1000",
+
+ "sqrt(-1000000)",
+ "1000*i",
+
+ "sqrt(2^60)",
+ "1073741824",
+
+ # this is why we factor irrationals
+
+ "6^(1/3) 3^(2/3)",
+ "3*2^(1/3)",
+
+ # inverse of complex numbers
+
+ "1/(2+3*i)",
+ "2/13-3/13*i",
+
+ "1/(2+3*i)^2",
+ "-5/169-12/169*i",
+
+ "(-1+3i)/(2-i)",
+ "-1+i",
+
+ # other
+
+ "(0.0)^(0.0)",
+ "1.0",
+
+ "(-4.0)^(0.5)",
+ "2.0*i",
+
+ "(-4.0)^(-0.5)",
+ "-0.5*i",
+
+ "(-4.0)^(-1.5)",
+ "0.125*i",
+
+ # more complex number cases
+
+ "(1+i)^2",
+ "2*i",
+
+ "(1+i)^(-2)",
+ "-1/2*i",
+
+ "(1+i)^(1/2)",
+ #"(-1)^(1/8)*2^(1/4)",
+ "i*2^(1/4)*sin(1/8*pi)+2^(1/4)*cos(1/8*pi)",
+
+ "(1+i)^(-1/2)",
+ "-(-1)^(7/8)/(2^(1/4))",
+
+ "(1+i)^(0.5)",
+ "1.098684...+0.455090...*i",
+
+ "(1+i)^(-0.5)",
+ "0.776887...-0.321797...*i",
+
+ # test cases for simplification of polar forms, counterclockwise
+
+ "exp(i*pi/2)",
+ "i",
+
+ "exp(i*pi)",
+ "-1",
+
+ "exp(i*3*pi/2)",
+ "-i",
+
+ "exp(i*2*pi)",
+ "1",
+
+ "exp(i*5*pi/2)",
+ "i",
+
+ "exp(i*3*pi)",
+ "-1",
+
+ "exp(i*7*pi/2)",
+ "-i",
+
+ "exp(i*4*pi)",
+ "1",
+
+ "exp(A+i*pi/2)",
+ "i*exp(A)",
+
+ "exp(A+i*pi)",
+ "-exp(A)",
+
+ "exp(A+i*3*pi/2)",
+ "-i*exp(A)",
+
+ "exp(A+i*2*pi)",
+ "exp(A)",
+
+ "exp(A+i*5*pi/2)",
+ "i*exp(A)",
+
+ "exp(A+i*3*pi)",
+ "-exp(A)",
+
+ "exp(A+i*7*pi/2)",
+ "-i*exp(A)",
+
+ "exp(A+i*4*pi)",
+ "exp(A)",
+
+ # test cases for simplification of polar forms, clockwise
+
+ "exp(-i*pi/2)",
+ "-i",
+
+ "exp(-i*pi)",
+ "-1",
+
+ "exp(-i*3*pi/2)",
+ "i",
+
+ "exp(-i*2*pi)",
+ "1",
+
+ "exp(-i*5*pi/2)",
+ "-i",
+
+ "exp(-i*3*pi)",
+ "-1",
+
+ "exp(-i*7*pi/2)",
+ "i",
+
+ "exp(-i*4*pi)",
+ "1",
+
+ "exp(A-i*pi/2)",
+ "-i*exp(A)",
+
+ "exp(A-i*pi)",
+ "-exp(A)",
+
+ "exp(A-i*3*pi/2)",
+ "i*exp(A)",
+
+ "exp(A-i*2*pi)",
+ "exp(A)",
+
+ "exp(A-i*5*pi/2)",
+ "-i*exp(A)",
+
+ "exp(A-i*3*pi)",
+ "-exp(A)",
+
+ "exp(A-i*7*pi/2)",
+ "i*exp(A)",
+
+ "exp(A-i*4*pi)",
+ "exp(A)",
+ ]
diff --git a/node_modules/algebrite/tests/printlatex.coffee b/node_modules/algebrite/tests/printlatex.coffee
new file mode 100644
index 0000000..ad87835
--- /dev/null
+++ b/node_modules/algebrite/tests/printlatex.coffee
@@ -0,0 +1,116 @@
+test_printlatex = ->
+ run_test [
+
+ "printlatex(pi/2)",
+ "\\frac{\\pi}{2}",
+
+ "printlatex(-pi/2)",
+ "-\\frac{\\pi}{2}",
+
+ "printlatex(pi/(-2))",
+ "-\\frac{\\pi}{2}",
+
+ "printlatex(-pi/(-2))",
+ "\\frac{\\pi}{2}",
+
+ "printlatex((1/2)*pi)",
+ "\\frac{\\pi}{2}",
+
+ "printlatex((1/(-2))*pi)",
+ "-\\frac{\\pi}{2}",
+
+ # note that these two are different:
+ # pi^(1/2) != pi^1/2
+ "printlatex(pi^(1/2))",
+ "\\sqrt{\\pi}",
+
+ "printlatex(1/x+x^3+1+1)",
+ "2+\\frac{1}{x}+x^3",
+
+ "lastlatexprint == \"2+\\frac{1}{x}+x^3\"",
+ "1",
+
+ "printlatex(quote(1/x+1+1))",
+ "\\frac{1}{x}+1+1",
+
+ "printlatex(quote(defint(a,y,-sqrt(1-x^2),sqrt(1-x^2))))",
+ "\\int^{\\sqrt{1-x^2} }_{-\\sqrt{1-x^2} } \\! a \\, \\mathrm{d} y",
+
+ "printlatex(1/(x+1))",
+ "\\frac{1}{1+x}",
+
+ "printlatex(1/(x+1)^2)",
+ "\\frac{1}{(1+x)^2}",
+
+ "printlatex(quote(1/(2*a*(x+1))))",
+ "\\frac{1}{2a(x+1)}",
+
+ "printlatex(j^k^l^m)",
+ "j^{k^{l^m}}",
+
+ "printlatex(dot(a,b))",
+ "a \\cdot b",
+
+ "printlatex(inner(a,b))",
+ "a \\cdot b",
+
+ "printlatex(inv(a))",
+ "{a}^{-1}",
+
+ "printlatex(inv(a+1))",
+ "{(1+a)}^{-1}",
+
+ "printlatex(12x^11)",
+ "12x^{11}",
+
+ # tricky when there are two consecutive
+ # numbers, can't just leave a space there.
+ "printlatex(5^2 * 3^y)",
+ "25 \\cdot 3^y",
+
+ "printlatex(5^2 * 3^(1/2))",
+ "25\\sqrt{3}",
+
+ "printlatex(5^2 * 3^(2/3))",
+ "25\\sqrt[3]{3^2}",
+
+ "printlatex([[0,1],[1,0]])",
+ "\\begin{bmatrix} 0 & 1 \\\\ 1 & 0 \\end{bmatrix}",
+
+ "printlatex([0,1])",
+ "\\begin{bmatrix} 0 & 1 \\end{bmatrix}",
+
+ "printlatex([[0,1,2],[3,4,5]])",
+ "\\begin{bmatrix} 0 & 1 & 2 \\\\ 3 & 4 & 5 \\end{bmatrix}",
+
+ "printlatex([[a]])",
+ "\\begin{bmatrix} a \\end{bmatrix}",
+
+ "printlatex([[0],[1]])",
+ "\\begin{bmatrix} 0 \\\\ 1 \\end{bmatrix}",
+
+ "printlatex(quote(sum((-1)^k * (1/(2*k + 1)),k,0,100)*4))",
+ "\\sum_{k=0}^{100}{\\frac{(-1)^k}{(2k+1)}}4",
+
+ "printlatex(quote(2*product(4*k^2/(4*k^2-1),k,1,100)))",
+ "2\\prod_{k=1}^{100}{\\frac{4k^2}{(4k^2-1)}}",
+
+ "printlatex(quote(a==b))",
+ "{a} = {b}",
+
+ "printlatex(quote(ab))",
+ "{a} > {b}",
+
+ "printlatex(quote(a>=b))",
+ "{a} \\geq {b}",
+
+ "printlatex(quote(f(x)=test(x<3,-x-4,3<=x,x*x+7,120/x+5)))",
+ "f(x)=\\left\\{ \\begin{array}{ll}{-x-4} & if & {x} < {3} \\\\\\\\{xx+7} & if & {3} \\leq {x} \\\\\\\\{\\frac{120}{x}+5} & otherwise \\end{array} \\right.",
+
+ ]
diff --git a/node_modules/algebrite/tests/product.coffee b/node_modules/algebrite/tests/product.coffee
new file mode 100644
index 0000000..91a99c4
--- /dev/null
+++ b/node_modules/algebrite/tests/product.coffee
@@ -0,0 +1,38 @@
+test_product = ->
+ run_test [
+
+ # compute pi using Viete's formula ------------
+
+ # note that this is not an array, this
+ # defines a recursive function
+ "a(n)=test(n=0,0,sqrt(2+a(n-1)))",
+ "",
+
+ # not very efficient because evaluation of
+ # a(n) is not memoized, so there
+ # is quadratic cost as n increases.
+ "float(2*product(2/a(k),k,1,9))",
+ "3.141588...",
+
+
+ # Wallis' product
+ "2*product(float(4*k^2/(4*k^2-1)),k,1,100)",
+ "3.133787...",
+
+ # ---------------------------
+ "f(a,b)=product(k,k,a,b)",
+ "",
+
+ "f(1,2)",
+ "2",
+
+ # --- cleanup
+
+ "a = quote(a)",
+ "",
+
+ "f = quote(f)",
+ "",
+
+
+ ]
diff --git a/node_modules/algebrite/tests/quickfactor.coffee b/node_modules/algebrite/tests/quickfactor.coffee
new file mode 100644
index 0000000..2751af7
--- /dev/null
+++ b/node_modules/algebrite/tests/quickfactor.coffee
@@ -0,0 +1,34 @@
+test_quickfactor = ->
+ i = 0
+ logout("testing quickfactor\n")
+ for i in [2...10001]
+ if i % 1000 == 0
+ console.log i
+ base = i
+ push_integer(base)
+ push_integer(1)
+ quickfactor()
+ h = tos
+ j = 0
+ while (base > 1)
+ expo = 0
+ while (base % primetab[j] == 0)
+ base /= primetab[j]
+ expo++
+ if (expo)
+ push_integer(primetab[j])
+ push_integer(expo)
+ quickpower()
+ j++
+ multiply_all(tos - h)
+ p2 = pop()
+ p1 = pop()
+ if (!equal(p1, p2))
+ logout("failed\n")
+ print_lisp(p1)
+ print_lisp(p2)
+ errout()
+ console.log "quickfactor is ok"
+ logout("ok\n")
+
+#endif
diff --git a/node_modules/algebrite/tests/quotient.coffee b/node_modules/algebrite/tests/quotient.coffee
new file mode 100644
index 0000000..5a11aae
--- /dev/null
+++ b/node_modules/algebrite/tests/quotient.coffee
@@ -0,0 +1,8 @@
+test_quotient = ->
+ run_test [
+ "quotient(x^2+1,x+1)-x+1",
+ "0",
+
+ "quotient(a*x^2+b*x+c,d*x+e)-(-a*e/(d^2)+a*x/d+b/d)",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/rationalize.coffee b/node_modules/algebrite/tests/rationalize.coffee
new file mode 100644
index 0000000..8ae7f5a
--- /dev/null
+++ b/node_modules/algebrite/tests/rationalize.coffee
@@ -0,0 +1,19 @@
+test_rationalize = ->
+ run_test [
+
+ "rationalize(a/b+c/d)",
+ "(a*d+b*c)/(b*d)",
+
+ "rationalize(t*y/(t+y)+2*t^2*y*(2*t+y)^(-2))",
+ "t*y*(6*t^2+y^2+6*t*y)/((t+y)*(2*t+y)^2)",
+
+ "rationalize(x^(-2*a)+x^(-4*a))",
+ "(1+x^(2*a))/(x^(4*a))",
+
+ "rationalize(x^(1/3)+x^(2/3))",
+ "x^(1/3)*(1+x^(1/3))",
+
+ "rationalize(rect(-(-1)^(3/4)))",
+ "(1-i)/(2^(1/2))",
+
+ ]
diff --git a/node_modules/algebrite/tests/real.coffee b/node_modules/algebrite/tests/real.coffee
new file mode 100644
index 0000000..ef477df
--- /dev/null
+++ b/node_modules/algebrite/tests/real.coffee
@@ -0,0 +1,15 @@
+test_real = ->
+ run_test [
+
+ "real(a+i*b)",
+ "a",
+
+ "real(1+exp(i*pi/3))",
+ "3/2",
+
+ "real(i)",
+ "0",
+
+ "real((-1)^(1/3))",
+ "1/2",
+ ]
diff --git a/node_modules/algebrite/tests/rect.coffee b/node_modules/algebrite/tests/rect.coffee
new file mode 100644
index 0000000..8f77a26
--- /dev/null
+++ b/node_modules/algebrite/tests/rect.coffee
@@ -0,0 +1,65 @@
+test_rect = ->
+ run_test [
+
+ # check when not assuming real variables ----------
+ "assumeRealVariables = 0",
+ "",
+
+ "rect(a)",
+ "rect(a)",
+
+ # same as rect(a) + i*rect(b)
+ # where rect(b) is abs(b)*(cos(arg(b)) + i*sin(arg(b)))
+ "rect(a+i*b)",
+ "rect(a)-abs(b)*sin(arg(b))+i*abs(b)*cos(arg(b))",
+
+ "assumeRealVariables = 1",
+ "",
+ # --------------------------------------------------
+
+ "rect(a)",
+ "a",
+
+ "rect(a+i*b)",
+ "a+i*b",
+
+ "rect(exp(a+i*b))",
+ "i*exp(a)*sin(b)+exp(a)*cos(b)",
+
+ "rect(1+exp(i*pi/3))",
+ "3/2+1/2*i*3^(1/2)",
+
+ "z=(a+b*i)/(c+d*i)",
+ "",
+
+ "rect(z)-real(z)-i*imag(z)",
+ "0",
+
+ "z=quote(z)",
+ "",
+
+ "rect((-1)^(2/3))",
+ "-1/2+1/2*i*3^(1/2)",
+
+ "rect(exp(-3/4*i*pi))",
+ "-1/2*2^(1/2)-1/2*i*2^(1/2)",
+
+ "rect(exp(-1/4*i*pi))",
+ "1/2*2^(1/2)-1/2*i*2^(1/2)",
+
+ "rect(exp(-2/4*i*pi))",
+ "-i",
+
+ "rect(exp(-3/4*i*pi))",
+ "-1/2*2^(1/2)-1/2*i*2^(1/2)",
+
+ "rect(exp(-4/4*i*pi))",
+ "-1",
+
+ "rect(((-1)^(1/2)/(3^(1/2)))^(1/2))",
+ "i*2^(1/2)/(2*3^(1/4))+2^(1/2)/(2*3^(1/4))",
+
+ "rect((-1)^(1/6) - (-1)^(5/6))",
+ "3^(1/2)",
+
+ ]
diff --git a/node_modules/algebrite/tests/roots.coffee b/node_modules/algebrite/tests/roots.coffee
new file mode 100644
index 0000000..50ba912
--- /dev/null
+++ b/node_modules/algebrite/tests/roots.coffee
@@ -0,0 +1,759 @@
+test_roots = ->
+ run_test [
+
+ "roots(x)",
+ "0",
+
+ "roots(2^x-y,y)",
+ "2^x",
+
+ "roots(x^2)",
+ "0",
+
+ "roots(x^3)",
+ "0",
+
+ "roots(2 x)",
+ "0",
+
+ "roots(2 x^2)",
+ "0",
+
+ "roots(i*x^2-13*i*x+36*i)",
+ "[4,9]",
+
+ "roots(2 x^3)",
+ "0",
+
+ "roots(6+11*x+6*x^2+x^3)",
+ "[-3,-2,-1]",
+
+ "roots(a*x^2+b*x+c)",
+ #"[-b/(2*a)-(-4*a*c+b^2)^(1/2)/(2*a),-b/(2*a)+(-4*a*c+b^2)^(1/2)/(2*a)]",
+ "[-1/2*(b^2/(a^2)-4*c/a)^(1/2)-b/(2*a),1/2*(b^2/(a^2)-4*c/a)^(1/2)-b/(2*a)]",
+
+ "roots(3+7*x+5*x^2+x^3)",
+ "[-3,-1]",
+
+ "roots(x^3+x^2+x+1)",
+ "[-1,-i,i]",
+
+ "roots(x^2==1)",
+ "[-1,1]",
+
+ "roots(3 x + 12 == 24)",
+ "4",
+
+ "y=roots(x^2+b*x+c/k)[1]",
+ "",
+
+ "y^2+b*y+c/k",
+ "0",
+
+ "y=roots(x^2+b*x+c/k)[2]",
+ "",
+
+ "y^2+b*y+c/k",
+ "0",
+
+ "y=roots(a*x^2+b*x+c/4)[1]",
+ "",
+
+ "a*y^2+b*y+c/4",
+ "0",
+
+ "y=roots(a*x^2+b*x+c/4)[2]",
+ "",
+
+ "a*y^2+b*y+c/4",
+ "0",
+
+ "y=quote(y)",
+ "",
+
+ # --------------------------------------------
+ # examples covering https://github.com/davidedc/Algebrite/issues/130
+
+ "roots(-2*z+x^2+y^2,z)",
+ "1/2*x^2+1/2*y^2",
+
+ "roots(-2*z+x^2+y^2,z)",
+ "1/2*x^2+1/2*y^2",
+
+ "roots(x+y+z)",
+ "-y-z",
+
+ "roots(x+y+z,z)",
+ "-x-y",
+
+ "roots(x+y+a,z)",
+ "Stop: roots: 1st argument is not a polynomial in the variable z",
+
+ "clearall",
+ "",
+
+ # --------------------------------------------
+ # some more tests with 3rd degree polynomials
+ # including use of cubic formula.
+ # Only the ones marked "DOES use cubic formula"
+ # actually do so, all other examples manage to
+ # be reduced via factoring.
+ # --------------------------------------------
+
+ "roots(x^3 + x^2 + x + 1)",
+ "[-1,-i,i]",
+
+ "roots(2*x^3 + 3*x^2 - 11*x - 6)",
+ "[-3,-1/2,2]",
+
+ "roots(x^3 - 7*x^2 + 4*x + 12)",
+ "[-1,2,6]",
+
+ "roots(x^3 + 1)",
+ "[-1,1/2-1/2*i*3^(1/2),1/2+1/2*i*3^(1/2)]",
+ # also: "[-1,-(-1)^(2/3),(-1)^(1/3))",
+
+ "roots(x^3 - 1)",
+ "[1,-1/2-1/2*i*3^(1/2),-1/2+1/2*i*3^(1/2)]",
+ # also: "[1,-(-1)^(1/3),(-1)^(2/3))",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = x^3 + d",
+ "",
+
+ "roots(thePoly)",
+ # also OK:
+ # "[-d^(1/3),1/2*d^(1/3)*(1-i*3^(1/2)),1/2*d^(1/3)*(1+i*3^(1/2)))",
+ # or "[-(-1)^(2/3)*d^(1/3),-d^(1/3),(-1)^(1/3)*d^(1/3))",
+ "[1/2*d^(1/3)-1/2*i*3^(1/2)*d^(1/3),1/2*d^(1/3)+1/2*i*3^(1/2)*d^(1/3),-d^(1/3)]",
+
+ "and((simplify(subst(last[1],x,thePoly)) == 0),(simplify(subst(last[2],x,thePoly)) == 0),(simplify(subst(last[3],x,thePoly)) == 0))",
+ "1",
+
+ # DOES use cubic formula
+ # the actual format of this solution might change, the important thing
+ # is that the next few tests work, where we plug in the
+ # symbolic solutions in the polynomial again and we check that we
+ # get the zeroes.
+
+ "clearall",
+ "",
+
+ "thePoly = a*x^3 + b*x^2 + c*x + d",
+ "",
+
+ "roots(thePoly)",
+ "[-1/3*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(1/3)-b^2/(3*a^2*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(1/3))-b/(3*a)+c/(a*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(1/3)),(-1/3*a*b*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(1/3)-1/2*a*c+1/6*b^2-1/2*i*3^(1/2)*a*c-1/6*i*3^(1/2)*a^2*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(2/3)+1/6*i*3^(1/2)*b^2+1/6*a^2*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(2/3))/(a^2*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(1/3)),(-1/3*a*b*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(1/3)-1/2*a*c+1/6*b^2+1/2*i*3^(1/2)*a*c+1/6*i*3^(1/2)*a^2*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(2/3)-1/6*i*3^(1/2)*b^2+1/6*a^2*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(2/3))/(a^2*(1/2*(-27*b^2*c^2/(a^4)+108*b^3*d/(a^4)-486*b*c*d/(a^3)+108*c^3/(a^3)+729*d^2/(a^2))^(1/2)+b^3/(a^3)-9*b*c/(2*a^2)+27*d/(2*a))^(1/3))]",
+
+ "and((simplify(subst(last[1],x,thePoly)) == 0),(simplify(subst(last[2],x,thePoly)) == 0),(simplify(subst(last[3],x,thePoly)) == 0))",
+ "1",
+
+ "roots(x^3 + 6x - 20)",
+ "[2,-1-3*i,-1+3*i]",
+
+ "roots(x^3 - 6x - 40)",
+ "[4,-2-i*2^(1/2)*3^(1/2),-2+i*2^(1/2)*3^(1/2)]",
+
+ "roots(x^3 + x^2 - 5x - 5)",
+ "[-1,-5^(1/2),5^(1/2)]",
+
+ "roots(x^3 - 8x + 3)",
+ "[-3,3/2-1/2*5^(1/2),3/2+1/2*5^(1/2)]",
+
+ "roots(x^3 - 8x - 3)",
+ "[3,-3/2-1/2*5^(1/2),-3/2+1/2*5^(1/2)]",
+
+ "roots(x^3 - 18x + 35)",
+ "[-5,5/2-1/2*i*3^(1/2),5/2+1/2*i*3^(1/2)]",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = x^3 - 3x + 1",
+ "",
+
+ "roots(thePoly)",
+ "[-(-1)^(1/9)+(-1)^(8/9),1/2*cos(1/9*pi)-1/2*cos(8/9*pi)+1/2*i*sin(1/9*pi)-1/2*i*sin(8/9*pi)-3^(1/2)*cos(11/18*pi),1/2*cos(1/9*pi)-1/2*cos(8/9*pi)+1/2*i*sin(1/9*pi)-1/2*i*sin(8/9*pi)+3^(1/2)*cos(11/18*pi)]",
+ # also: "[(3+1/3*(27/2+27/2*i*3^(1/2))^(2/3)-3*i*3^(1/2)+1/3*i*3^(1/2)*(27/2+27/2*i*3^(1/2))^(2/3))/(2*(27/2+27/2*i*3^(1/2))^(1/3)),(3+1/3*(27/2+27/2*i*3^(1/2))^(2/3)+3*i*3^(1/2)-1/3*i*3^(1/2)*(27/2+27/2*i*3^(1/2))^(2/3))/(2*(27/2+27/2*i*3^(1/2))^(1/3)),(-3-1/3*(27/2+27/2*i*3^(1/2))^(2/3))/((27/2+27/2*i*3^(1/2))^(1/3)))",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = x^3 - 3x - 1",
+ "",
+
+ "roots(thePoly)",
+ "[-(-1)^(2/9)+(-1)^(7/9),1/2*cos(2/9*pi)-1/2*cos(7/9*pi)+1/2*i*sin(2/9*pi)-1/2*i*sin(7/9*pi)-3^(1/2)*cos(13/18*pi),1/2*cos(2/9*pi)-1/2*cos(7/9*pi)+1/2*i*sin(2/9*pi)-1/2*i*sin(7/9*pi)+3^(1/2)*cos(13/18*pi)]",
+ # also: "[(3+1/3*(-27/2+27/2*i*3^(1/2))^(2/3)-3*i*3^(1/2)+1/3*i*3^(1/2)*(-27/2+27/2*i*3^(1/2))^(2/3))/(2*(-27/2+27/2*i*3^(1/2))^(1/3)),(3+1/3*(-27/2+27/2*i*3^(1/2))^(2/3)+3*i*3^(1/2)-1/3*i*3^(1/2)*(-27/2+27/2*i*3^(1/2))^(2/3))/(2*(-27/2+27/2*i*3^(1/2))^(1/3)),(-3-1/3*(-27/2+27/2*i*3^(1/2))^(2/3))/((-27/2+27/2*i*3^(1/2))^(1/3)))",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+ "roots(x^3 - 15x - 4)",
+ "[4,-2-3^(1/2),-2+3^(1/2)]",
+
+ "roots(2*x^3 - 4x^2 - 22*x + 24)",
+ "[-3,1,4]",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 3*x^3 - 10*x^2 - 14*x + 27",
+ "",
+
+ "roots(thePoly)",
+ "[1/3*(10/3-226/(9*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3))-(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3)),1/3*(10/3+113/(9*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3))+1/2*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3)-113*i*3^(1/2)/(9*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3))+1/2*i*3^(1/2)*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3)),1/3*(10/3+113/(9*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3))+1/2*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3)+113*i*3^(1/2)/(9*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3))-1/2*i*3^(1/2)*(781/54+i*97^(1/2)*1933^(1/2)/(2*3^(1/2)))^(1/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(10^(-13))),(abs(float(subst(float(last[2]),x,thePoly))) < float(10^(-13))), (abs(float(subst(float(last[3]),x,thePoly))) < float(10^(-13))))",
+ "1",
+
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 1*x^3 + 6*x^2 - 12*x + 8",
+ "",
+
+ "roots(thePoly)",
+ "[-2+2^(1/3)+2^(2/3)-i*2^(1/3)*3^(1/2)+i*2^(2/3)*3^(1/2),-2+2^(1/3)+2^(2/3)+i*2^(1/3)*3^(1/2)-i*2^(2/3)*3^(1/2),-2*(1+2^(1/3)+2^(2/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-14))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-14))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-14))))",
+ "1",
+
+
+ "roots(1*x^3 + 6*x^2 + 12*x + 8)",
+ "-2",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 1*x^3 + 0*x^2 + 12*x - 10",
+ "",
+
+ "roots(thePoly)",
+ "[(-6+1/6*(-135+27*89^(1/2))^(2/3)-6*i*3^(1/2)-1/6*i*3^(1/2)*(-135+27*89^(1/2))^(2/3))/((-135+27*89^(1/2))^(1/3)),(-6+1/6*(-135+27*89^(1/2))^(2/3)+6*i*3^(1/2)+1/6*i*3^(1/2)*(-135+27*89^(1/2))^(2/3))/((-135+27*89^(1/2))^(1/3)),(12-1/3*(-135+27*89^(1/2))^(2/3))/((-135+27*89^(1/2))^(1/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-14))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-14))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-14))))",
+ "1",
+
+ "roots(1*x^3 + 0*x^2 - 18*x + 35)",
+ "[-5,5/2-1/2*i*3^(1/2),5/2+1/2*i*3^(1/2)]",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 1*x^3 + 0*x^2 - 3*x - 6",
+ "",
+
+ "roots(thePoly)",
+ "[(3+1/3*(-81+54*2^(1/2))^(2/3)-3*i*3^(1/2)+1/3*i*3^(1/2)*(-81+54*2^(1/2))^(2/3))/(2*(-81+54*2^(1/2))^(1/3)),(3+1/3*(-81+54*2^(1/2))^(2/3)+3*i*3^(1/2)-1/3*i*3^(1/2)*(-81+54*2^(1/2))^(2/3))/(2*(-81+54*2^(1/2))^(1/3)),(-3-1/3*(-81+54*2^(1/2))^(2/3))/((-81+54*2^(1/2))^(1/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-14))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-14))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-14))))",
+ "1",
+
+ "roots(2*x^3 - 30*x^2 + 162*x - 350)",
+ "[7,4-3*i,4+3*i]",
+
+ "roots(1*x^3 - 4*x^2 - 6*x + 5)",
+ "[5,-1/2-1/2*5^(1/2),-1/2+1/2*5^(1/2)]",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 3*x^3 + 6*x^2 + 4*x + 9",
+ "",
+
+ "roots(thePoly)",
+ "[1/3*(-2-73^(1/3)),1/3*(-2+1/2*73^(1/3)-1/2*i*3^(1/2)*73^(1/3)),1/3*(-2+1/2*73^(1/3)+1/2*i*3^(1/2)*73^(1/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-14))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-14))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-14))))",
+ "1",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 3*x^3 + 21*x^2 + 2*x + 3",
+ "",
+
+ "roots(thePoly)",
+ "[1/3*(-7-47/((671/2+1/2*34949^(1/2))^(1/3))-(671/2+1/2*34949^(1/2))^(1/3)),1/3*(-7+47/(2*(671/2+1/2*34949^(1/2))^(1/3))+1/2*(671/2+1/2*34949^(1/2))^(1/3)-47*i*3^(1/2)/(2*(671/2+1/2*34949^(1/2))^(1/3))+1/2*i*3^(1/2)*(671/2+1/2*34949^(1/2))^(1/3)),1/3*(-7+47/(2*(671/2+1/2*34949^(1/2))^(1/3))+1/2*(671/2+1/2*34949^(1/2))^(1/3)+47*i*3^(1/2)/(2*(671/2+1/2*34949^(1/2))^(1/3))-1/2*i*3^(1/2)*(671/2+1/2*34949^(1/2))^(1/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 3*x^3 - 6*x^2 + 4*x - 5",
+ "",
+
+ "roots(thePoly)",
+ # also these ones could be sort of OK:
+ # "[2/3-1/3*(-1)^(1/3)*37^(1/3),2/3+1/6*(-1)^(1/3)*37^(1/3)-(-1)^(5/6)*37^(1/3)/(2*3^(1/2)),2/3+1/6*(-1)^(1/3)*37^(1/3)+(-1)^(5/6)*37^(1/3)/(2*3^(1/2)))",
+ # "[2/3-1/3*(-1)^(1/3)*37^(1/3),2/3-1/6*37^(1/3)+i*37^(1/3)/(2*3^(1/2)),2/3+1/3*37^(1/3))",
+ # "[1/3*(2-(-1)^(1/3)*37^(1/3)),1/3*(2-1/2*37^(1/3)+1/2*i*3^(1/2)*37^(1/3)),1/3*(2+37^(1/3)))",
+ "[2/3-1/3*(-1)^(1/3)*37^(1/3),1/3*(2-1/2*37^(1/3)+1/2*i*3^(1/2)*37^(1/3)),1/3*(2+37^(1/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-14))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-14))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-14))))",
+ "1",
+
+ "roots(8*x^3 - 36*x^2 + 54*x - 27)",
+ "3/2",
+
+ "roots(3*x^3 - 5*x^2 - 1*x - 2)",
+ "[2,-1/6-1/6*i*11^(1/2),-1/6+1/6*i*11^(1/2)]",
+
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = 3*x^3 - 6*x^2 + 4*x - i",
+ "",
+
+ "roots(thePoly)",
+ "[1/3*(2-(8-9*i)^(1/3)),1/3*(2+1/2*(8-9*i)^(1/3)-1/2*i*3^(1/2)*(8-9*i)^(1/3)),1/3*(2+1/2*(8-9*i)^(1/3)+1/2*i*3^(1/2)*(8-9*i)^(1/3))]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = x^3+i",
+ "",
+
+ "roots(thePoly)",
+ # also these could be OK:
+ # "[1/2*(-1)^(1/6)-1/2*(-1)^(2/3)*3^(1/2),-(-1)^(1/6),1/2*(-1)^(1/6)*(1+i*3^(1/2)))",
+ # "[-1/2*i+1/2*3^(1/2),-(-1)^(1/6),i)",
+ # "[-(-1)^(1/6),-(-1)^(5/6),i)",
+ "[-1/2*i-1/2*3^(1/2),-1/2*i+1/2*3^(1/2),i]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+
+ "clearall",
+ "",
+
+ # DOES use cubic formula
+ "thePoly = x^3-i",
+ "",
+
+ "roots(thePoly)",
+ # "[-i,1/2*(i-3^(1/2)),1/2*(i+3^(1/2)))",
+ # "[-i,(-1)^(1/6),(-1)^(5/6))",
+ "[-3/4*i-1/2*(-1)^(5/6)-1/4*3^(1/2),3/4*i-1/2*(-1)^(5/6)+1/4*3^(1/2),(-1)^(5/6)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+ # some quartics
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 + 1",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ # "[-(-1)^(1/4),-(-1)^(3/4),(-1)^(1/4),(-1)^(3/4))",
+ "[-1/2*2^(1/2)-1/2*i*2^(1/2),-1/2*2^(1/2)+1/2*i*2^(1/2),1/2*2^(1/2)-1/2*i*2^(1/2),1/2*2^(1/2)+1/2*i*2^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = 4*x^4 - 1*x^3 + 4*x^2 + 3*x + 5",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[1/16-1/2*(-125/96-447/(256*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2))-265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)-265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2)+1/2*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2),1/16-1/2*(-125/96+447/(256*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2))-265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)-265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2)-1/2*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2),1/16+1/2*(-125/96-447/(256*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2))-265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)-265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2)+1/2*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2),1/16+1/2*(-125/96+447/(256*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2))-265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)-265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2)-1/2*(-125/192+265/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))+1/3*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3)+265*i*3^(1/2)/(192*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))-1/3*i*3^(1/2)*(4417/1024+9/1024*i*461^(1/2)*1471^(1/2))^(1/3))^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^5 + 1",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ # "[-1,-(-1)^(2/5),-(-1)^(4/5),(-1)^(1/5),(-1)^(3/5))",
+ "[-1,cos(1/5*pi)+i*sin(1/5*pi),cos(3/5*pi)+i*sin(3/5*pi),-cos(2/5*pi)-i*sin(2/5*pi),-cos(4/5*pi)-i*sin(4/5*pi)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[5]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = a*x^5 + k",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots[1] = simplify(theRoots[1])",
+ "",
+
+ "theRoots[1]",
+ "-(-1)^(2/5)*((k/a)^(2/5))^(1/2)",
+
+ "theRoots[2] = simplify(theRoots[2])",
+ "",
+
+ "theRoots[2]",
+ "-(-1)^(4/5)*((k/a)^(2/5))^(1/2)",
+
+ "theRoots[3] = circexp(theRoots[3])",
+ "",
+
+ "theRoots[3]",
+ "exp(1/5*i*pi)*(k/a)^(1/5)",
+
+ "theRoots[4] = circexp(theRoots[4])",
+ "",
+
+ "theRoots[4]",
+ "exp(3/5*i*pi)*(k/a)^(1/5)",
+
+ "theRoots[5] = simplify(theRoots[5])",
+ "",
+
+ "theRoots[5]",
+ "-(k/a)^(1/5)",
+
+ # unfortunately the comparison here doesn't work,
+ # due to rounding errors float() produces expressions that still hve
+ # a and k, albeit with really small
+ # coefficients, and hence the "<" comparison finds variables with
+ # undefined values and
+ # fails.
+
+ #"and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[5]),x,thePoly))) < float(2*10^(-12))))",
+ #"1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^3 - 7*x^2 + 41*x - 87",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[3,2-5*i,2+5*i]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = 398683376+1720835*x+2320*x^2+x^3",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ # root 1 ~= -961.79, root 2 ~= -895.12, root 3 ~= -463.09
+ # all three of them have a very small "error" imaginary part ~= 10^-13
+ "theRoots",
+ "[-2320/3-219895/(3*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3))-1/3*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3),-2320/3+219895/(6*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3))+1/6*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3)-219895*i*3^(1/2)/(6*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3))+1/6*i*3^(1/2)*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3),-2320/3+219895/(6*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3))+1/6*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3)+219895*i*3^(1/2)/(6*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3))-1/6*i*3^(1/2)*(-96123824+9*i*7^(1/2)*79^(1/2)*2297^(1/2)*13538519^(1/2))^(1/3)]",
+
+ # the error here is particularly high because of the big coefficients
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-7))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-7))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-7))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 - 1*x^3 + 4*x^2 + 3*x + 5",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-1/2-1/2*i*3^(1/2),-1/2+1/2*i*3^(1/2),1-2*i,1+2*i]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 - 2*x^3 - 7*x^2 + 8*x + 12",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-2,-1,2,3]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^4+8*x^2+3",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-(-4-13^(1/2))^(1/2),-(-4+13^(1/2))^(1/2),(-4-13^(1/2))^(1/2),(-4+13^(1/2))^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = -1*x^3-1*x^2+10*x - 8",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-4,1,2]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = -3-9*x+3*x^2+x^3",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ # these solutions are slightly verbose but they are essentially good,
+ # take into account that ((108+108*i*3^(1/2))^(1/3)) is
+ # really just a compact version (in terms of number of nodes)
+ # for 3*2^(2/3)*(1+i*sqrt(3))^(1/3)
+ # (just take out 108 from the radical, and 108 is 2x2x3x3x3)
+ # so essentially these are written a little redundantly but
+ # they actually are in pretty good form.
+ "theRoots",
+ # "[-1-12/((108+108*i*3^(1/2))^(1/3))-1/3*(108+108*i*3^(1/2))^(1/3),-1+6/((108+108*i*3^(1/2))^(1/3))+1/6*(108+108*i*3^(1/2))^(1/3)-6*i*3^(1/2)/((108+108*i*3^(1/2))^(1/3))+1/6*i*3^(1/2)*(108+108*i*3^(1/2))^(1/3),-1+6/((108+108*i*3^(1/2))^(1/3))+1/6*(108+108*i*3^(1/2))^(1/3)+6*i*3^(1/2)/((108+108*i*3^(1/2))^(1/3))-1/6*i*3^(1/2)*(108+108*i*3^(1/2))^(1/3))",
+ "[-1+cos(1/9*pi)-cos(8/9*pi)+i*sin(1/9*pi)-i*sin(8/9*pi)-2*3^(1/2)*cos(11/18*pi),-1+cos(1/9*pi)-cos(8/9*pi)+i*sin(1/9*pi)-i*sin(8/9*pi)+2*3^(1/2)*cos(11/18*pi),-1-2*cos(1/9*pi)+2*cos(8/9*pi)-2*i*sin(1/9*pi)+2*i*sin(8/9*pi)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 + 8*x^3 + 12*x^2 + (2*30^(1/2) -16)*x + 4*30^(1/2)-28",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-2-1/2*(18-4*5^(1/2))^(1/2)+3^(1/2)/(2^(1/2)),-2-1/2*(18+4*5^(1/2))^(1/2)-1/2*2^(1/2)*3^(1/2),-2+1/2*(18-4*5^(1/2))^(1/2)+3^(1/2)/(2^(1/2)),-2+1/2*(18+4*5^(1/2))^(1/2)-1/2*2^(1/2)*3^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^3 + x - 2",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[1,-1/2-1/2*i*7^(1/2),-1/2+1/2*i*7^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+
+ "clearall",
+ "",
+
+ "thePoly = x^3 + x^2 - 7",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ # note how we can't use "last" here because the assignment returns nothing
+ "and(abs(float(subst(theRoots[1],x,thePoly))) < float(2*10^(-12)),abs(float(subst(theRoots[2],x,thePoly))) < float(2*10^(-12)),abs(float(subst(theRoots[3],x,thePoly))) < float(2*10^(-12)))",
+ "1",
+
+ # some quartics
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 + 8*x^2 + 3",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-(-4-13^(1/2))^(1/2),-(-4+13^(1/2))^(1/2),(-4-13^(1/2))^(1/2),(-4+13^(1/2))^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(8*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(8*10^(-15))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 - 10*x^3 + 21*x^2 + 40*x - 100",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-2,2,5]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = 2*x^4 - 8*x^3 + 2*x^2 + 24*x - 14",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 - 4*x^3 + x^2 + 12*x - 7",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-1/2-1/2*5^(1/2),-1/2+1/2*5^(1/2),5/2-1/2*i*3^(1/2),5/2+1/2*i*3^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = 2*x^4 - 8*x^3 + 2*x^2 + 24*x - 14",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-1/2-1/2*5^(1/2),-1/2+1/2*5^(1/2),5/2-1/2*i*3^(1/2),5/2+1/2*i*3^(1/2)]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 - 9*x^3 + 22*x^2 + 28*x - 120",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-2,3,4-2*i,4+2*i]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ "1",
+
+
+ #"thePoly = 4* x^4 - 9*x^3 + 22*x^2 + 28*x - 120",
+ #"",
+ #
+ # these are really ugly - sympy or wolfram alpha don't give clean symbolic solutions either
+ #"theRoots = roots(thePoly)",
+ #"",
+ #
+ #"and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ #"1",
+ #
+ #"thePoly = -20*x^4 + 5*x^3 + 17*x^2 - 29*x + 87",
+ #"",
+ #
+ # these are really ugly - sympy or wolfram alpha don't give clean symbolic solutions either
+ #"theRoots = roots(thePoly)",
+ #"",
+ #
+ #"and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-12))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-12))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-12))))",
+ #"1",
+ #
+
+ "clearall",
+ "",
+
+ "thePoly = x^4 + 2*x^3 - 41*x^2 - 42*x + 360",
+ "",
+
+ "theRoots = roots(thePoly)",
+ "",
+
+ "theRoots",
+ "[-6,-4,3,5]",
+
+ "and((abs(float(subst(float(last[1]),x,thePoly))) < float(2*10^(-15))),(abs(float(subst(float(last[2]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[3]),x,thePoly))) < float(2*10^(-15))), (abs(float(subst(float(last[4]),x,thePoly))) < float(2*10^(-15))))",
+ "1",
+
+
+
+ # clean up
+ "thePoly = quote(thePoly)",
+ "",
+
+ "theRoots = quote(theRoots)",
+ "",
+
+ ]
diff --git a/node_modules/algebrite/tests/round.coffee b/node_modules/algebrite/tests/round.coffee
new file mode 100644
index 0000000..fbae2e4
--- /dev/null
+++ b/node_modules/algebrite/tests/round.coffee
@@ -0,0 +1,80 @@
+test_round = ->
+ run_test [
+ "round(a)",
+ "round(a)",
+
+ "round(a+b)",
+ "round(a+b)",
+
+ "round(5/2)",
+ "3",
+
+ "round(5/2 - 1/10)",
+ "2",
+
+ "round(4/2)",
+ "2",
+
+ "round(3/2)",
+ "2",
+
+ "round(2/2)",
+ "1",
+
+ "round(1/2)",
+ "1",
+
+ "round(0/2)",
+ "0",
+
+ "round(-1/2)",
+ "0",
+
+ "round(-2/2)",
+ "-1",
+
+ "round(-3/2)",
+ "-1",
+
+ "round(-4/2)",
+ "-2",
+
+ "round(-5/2)",
+ "-2",
+
+ "round(-5/2 + 1/10)",
+ "-2",
+
+ "round(5/2) - round(5/2.0)",
+ "0.0",
+
+ "round(4/2) - round(4/2.0)",
+ "0.0",
+
+ "round(3/2) - round(3/2.0)",
+ "0.0",
+
+ "round(2/2) - round(2/2.0)",
+ "0.0",
+
+ "round(1/2) - round(1/2.0)",
+ "0.0",
+
+ "round(0.0)",
+ "0.0",
+
+ "round(-1/2) - round(-1/2.0)",
+ "0.0",
+
+ "round(-2/2) - round(-2/2.0)",
+ "0.0",
+
+ "round(-3/2) - round(-3/2.0)",
+ "0.0",
+
+ "round(-4/2) - round(-4/2.0)",
+ "0.0",
+
+ "round(-5/2) - round(-5/2.0)",
+ "0.0",
+ ]
diff --git a/node_modules/algebrite/tests/scan.coffee b/node_modules/algebrite/tests/scan.coffee
new file mode 100644
index 0000000..5b51896
--- /dev/null
+++ b/node_modules/algebrite/tests/scan.coffee
@@ -0,0 +1,77 @@
+test_scan = ->
+ if DEBUG then console.log "test_scan ----------------------------"
+
+ run_test [
+
+ "a^^b",
+ "a^^ ? b\nStop: syntax error",
+
+ "(a+b",
+ "(a+b ? \nStop: ) expected",
+
+ "quote(1/(x*log(a*x)))", # test case A
+ "1/(x*log(a*x))",
+
+ "\"hello",
+ "\"hello ? \nStop: runaway string",
+
+ # make sure question mark can appear after newlines
+
+ "a+\nb+\nc+",
+ "a+\nb+\nc+ ? \nStop: syntax error",
+
+ # this bug fixed in version 30 (used to give one result, 14)
+
+ "(1+1)",
+ "2",
+
+ "2+2\n(3+3)",
+ "4\n6",
+
+ # plus and minus cannot cross newline
+
+ "1\n-1",
+ "1\n-1",
+
+ "1\n+1",
+ "1\n1",
+
+ # implicit multiplication is parsed fine in
+ # in the obvious cases where the first factor
+ # is a "naked" number. Note that
+ # (2)(a) doesn't work (yet) instead.
+ # In many other cases such as a(b) it's in
+ # principle impossible at parse time to turn that
+ # into a multiplication because the first factor
+ # could be a function, so that'd be a function
+ # call.
+
+ "2(a) * 2a",
+ "4*a^2",
+
+ "2a3b",
+ "2*a3b",
+
+ "2a 3b",
+ "6*a*b",
+
+ "2 a 3b",
+ "6*a*b",
+
+ "2 a 3 b",
+ "6*a*b",
+
+ "2(a)3(b)",
+ "6*a*b",
+
+ "2(a)b*3",
+ "6*a*b",
+
+ "(a)2 * 2a",
+ "4*a^2",
+
+ "3 (2 x^3 + x^2 - 23 x + 20)",
+ "6*x^3+3*x^2-69*x+60",
+
+ ]
+
diff --git a/node_modules/algebrite/tests/sgn.coffee b/node_modules/algebrite/tests/sgn.coffee
new file mode 100644
index 0000000..5497e43
--- /dev/null
+++ b/node_modules/algebrite/tests/sgn.coffee
@@ -0,0 +1,14 @@
+test_sgn = ->
+ run_test [
+
+ "sgn(-3)",
+ "-1",
+
+
+ "sgn(0)",
+ "0",
+
+ "sgn(3)",
+ "1",
+
+ ]
diff --git a/node_modules/algebrite/tests/shape.coffee b/node_modules/algebrite/tests/shape.coffee
new file mode 100644
index 0000000..b3f794c
--- /dev/null
+++ b/node_modules/algebrite/tests/shape.coffee
@@ -0,0 +1,27 @@
+test_shape = ->
+ run_test [
+
+ # see transpose function source to see why
+ # transposition has no effect on vectors
+ # of dimension (rank) 1
+
+ "shape([A,B,C])",
+ "[3]",
+
+ "shape(transpose([A,B,C]))",
+ "[3]",
+
+ "shape([[A],[B],[C]])",
+ "[3,1]",
+
+ "shape(transpose([[A],[B],[C]]))",
+ "[1,3]",
+
+ "shape([[A,B],[C,D],[E,F]])",
+ "[3,2]",
+
+ "shape(transpose([[A,B],[C,D],[E,F]]))",
+ "[2,3]",
+
+ ]
+
diff --git a/node_modules/algebrite/tests/simplify.coffee b/node_modules/algebrite/tests/simplify.coffee
new file mode 100644
index 0000000..ba04d69
--- /dev/null
+++ b/node_modules/algebrite/tests/simplify.coffee
@@ -0,0 +1,623 @@
+test_simplify = ->
+ run_test [
+
+ # the system normally tries to
+ # arrange polynomials in a normal
+ # form, without the need for simplify
+ "x+a*x",
+ "(1+a)*x",
+
+ "simplify(A)",
+ "A",
+
+ "simplify(A+B)",
+ "A+B",
+
+ "simplify(A B)",
+ "A*B",
+
+ "simplify(A^B)",
+ "A^B",
+
+ "simplify(A/(A+B)+B/(A+B))",
+ "1",
+
+ "simplify((A-B)/(B-A))",
+ "-1",
+
+ "A=[[A11,A12],[A21,A22]]",
+ "",
+
+ "simplify(det(A) inv(A) - adj(A))",
+ "0",
+
+ "A=quote(A)",
+ "",
+
+ "simplify(-3 exp(-1/3 r + i phi) cos(theta) / sin(theta)\
+ + 3 exp(-1/3 r + i phi) cos(theta) sin(theta)\
+ + 3 exp(-1/3 r + i phi) cos(theta)^3 / sin(theta))",
+ "0",
+
+ "simplify((A^2 C^2 + A^2 D^2 + B^2 C^2 + B^2 D^2)/(A^2+B^2)/(C^2+D^2))",
+ "1",
+
+ "simplify(d(arctan(y/x),y))",
+ "x/(x^2+y^2)",
+
+ "simplify(d(arctan(y/x),x))",
+ "-y/(x^2+y^2)",
+
+ "simplify(1-sin(x)^2)",
+ "cos(x)^2",
+
+ "simplify(1-cos(x)^2)",
+ "sin(x)^2",
+
+ "simplify(sin(x)^2-1)",
+ "-cos(x)^2",
+
+ "simplify(cos(x)^2-1)",
+ "-sin(x)^2",
+
+ # tries to get rid of sin and cos if there are more
+ # compact clockforms or exponential forms
+ "simplify(-cos(2/5*pi)*(k/a)^(1/5)-i*(k/a)^(1/5)*sin(2/5*pi))",
+ "((k/a)^(2/5))^(1/2)/((-1)^(3/5))",
+
+ #"simfac(n!/n)-(n-1)!",
+ #"0",
+
+ #"simfac(n/n!)-1/(n-1)!",
+ #"0",
+
+ #"simfac(rationalize((n+k+1)/(n+k+1)!))-1/(n+k)!",
+ #"0",
+
+ #"simfac(condense((n+1)*n!))-(n+1)!",
+ #"0",
+
+ #"simfac(1/((n+1)*n!))-1/(n+1)!",
+ #"0",
+
+ #"simfac((n+1)!/n!)-n-1",
+ #"0",
+
+ #"simfac(n!/(n+1)!)-1/(n+1)",
+ #"0",
+
+ #"simfac(binomial(n+1,k)/binomial(n,k))",
+ #"(1+n)/(1-k+n)",
+
+ #"simfac(binomial(n,k)/binomial(n+1,k))",
+ #"(1-k+n)/(1+n)",
+
+ #"F(nn,kk)=kk*binomial(nn,kk)",
+ #"",
+
+ #"simplify(simfac((F(n,k)+F(n,k-1))/F(n+1,k))-n/(n+1))",
+ #"0",
+
+ #"F=quote(F)",
+ #"",
+
+ "simplify(n!/n)-(n-1)!",
+ "0",
+
+ "simplify(n/n!)-1/(n-1)!",
+ "0",
+
+ "simplify(rationalize((n+k+1)/(n+k+1)!))-1/(n+k)!",
+ "0",
+
+ "simplify(condense((n+1)*n!))-(n+1)!",
+ "0",
+
+ "simplify(1/((n+1)*n!))-1/(n+1)!",
+ "0",
+
+ "simplify((n+1)!/n!)-n-1",
+ "0",
+
+ "simplify(n!/(n+1)!)-1/(n+1)",
+ "0",
+
+ "simplify(binomial(n+1,k)/binomial(n,k))",
+ "(1+n)/(1-k+n)",
+
+ "simplify(binomial(n,k)/binomial(n+1,k))",
+ "(1-k+n)/(1+n)",
+
+ "F(nn,kk)=kk*binomial(nn,kk)",
+ "",
+
+ "simplify((F(n,k)+F(n,k-1))/F(n+1,k))-n/(n+1)",
+ "0",
+
+ "F=quote(F)",
+ "",
+
+ "simplify((n+1)/(n+1)!)-1/n!",
+ "0",
+
+ "simplify(a*b+a*c)",
+ "a*(b+c)",
+
+ # Symbol's binding is evaluated, undoing simplify
+
+ "x=simplify(a*b+a*c)",
+ "",
+
+ "x",
+ "a*b+a*c",
+
+ "x=quote(x)",
+ "",
+
+ "simplify((6 - 4*2^(1/2))^(1/2))",
+ "2-2^(1/2)",
+
+ "4-4*(-1)^(1/3)+4*(-1)^(2/3)",
+ "0",
+
+ "simplify(4-4*(-1)^(1/3)+4*(-1)^(2/3))",
+ "0",
+
+ # this requires some simplification to be
+ # further done after the de-nesting
+ "simplify(14^(1/2) - (16 - 4*7^(1/2))^(1/2))",
+ "2^(1/2)",
+
+
+ "simplify(-(2^(1/2)*(-1+7^(1/2)))+2^(1/2)*7^(1/2))",
+ "2^(1/2)",
+
+
+ "simplify((9 + 6*2^(1/2))^(1/2))",
+ "3^(1/2)*(1+2^(1/2))",
+
+
+ "simplify((7 + 13^(1/2))^(1/2))",
+ "(1+13^(1/2))/(2^(1/2))",
+
+ # two nested radicals at the same time
+ "simplify((17 + 12*2^(1/2))^(1/2) + (17 - 12*2^(1/2))^(1/2))",
+ "6",
+
+ "simplify((2 + 3^(1/2))^(1/2))",
+ "(1+3^(1/2))/(2^(1/2))",
+
+ "simplify((1/2 + (39^(1/2)/16))^(1/2))",
+ "(3^(1/2)+13^(1/2))/(4*2^(1/2))",
+
+ # there would be a slightly better presentation for this,
+ # where 108 is factored and some parts get out of the
+ # radical but there is no way to de-nest this.
+ "simplify((-108+108*(-1)^(1/2)*3^(1/2))^(1/3))",
+ "6*(-1)^(2/9)",
+ # also: "(-108+108*i*3^(1/2))^(1/3)" is a possible result
+
+ # you can take that 4 out of the radical
+ # but other than that there is no
+ # "sum or radicals" form of this
+ "simplify((-4+4*(-1)^(1/2)*3^(1/2))^(1/3))",
+ "2*(-1)^(2/9)",
+ # also: "(-4+4*i*3^(1/2))^(1/3)" is a possible result
+
+
+ # scrambling the order of things a little
+ # and checking whether the nested radical
+ # still gets simplified.
+ "simplify((((-3)^(1/2) + 1)/2)^(1/2))",
+ #"(-1)^(1/6)",
+ "1/2*(i+3^(1/2))",
+
+ "simplify((1/2 + (-3)^(1/2)/2)^(1/2))",
+ #"(-1)^(1/6)",
+ "1/2*(i+3^(1/2))",
+
+ # no possible de-nesting, should
+ # leave unchanged.
+ "simplify((2 +2^(1/2))^(1/2))",
+ "(2+2^(1/2))^(1/2)",
+
+ "simplify((1 +3^(1/2)/2)^(1/2) + (1 -3^(1/2)/2)^(1/2))",
+ "3^(1/2)",
+
+ "simplify((1 +3^(1/2)/2)^(1/2))",
+ "1/2*(1+3^(1/2))",
+
+ # not quite perfect as there is a radical at the
+ # denominator, but the de-nesting happens.
+ "simplify(((1 +39^(1/2)/8)/2)^(1/2))",
+ "(3^(1/2)+13^(1/2))/(4*2^(1/2))",
+
+ "simplify((5 +24^(1/2))^(1/2))",
+ "2^(1/2)+3^(1/2)",
+
+ "simplify((3 +4*i)^(1/2))",
+ "2+i",
+
+ "simplify((3 -4*i)^(1/2))",
+ "2-i",
+
+ "simplify((-2 +2*3^(1/2)*i)^(1/2))",
+ #"2*(-1)^(1/3)",
+ "1+i*3^(1/2)",
+
+ "simplify((9 - 4*5^(1/2))^(1/2))",
+ "-2+5^(1/2)",
+
+ "simplify((61 - 24*5^(1/2))^(1/2))",
+ "-4+3*5^(1/2)",
+
+ "simplify((-352+936*(-1)^(1/2))^(1/3))",
+ "2*(4+3*i)",
+
+
+ "simplify((3 - 2*2^(1/2))^(1/2))",
+ "-1+2^(1/2)",
+
+ "simplify((27/2+27/2*(-1)^(1/2)*3^(1/2))^(1/3))",
+ "3*(-1)^(1/9)",
+ # also good: (27/2+27/2*i*3^(1/2))^(1/3)
+
+ # this nested radical is also equal to
+ # (-1)^(1/9)
+ # but there is no "sum of radicals" form
+ # for this.
+ "simplify((1/2+1/2*(-1)^(1/2)*3^(1/2))^(1/3))",
+ "(-1)^(1/9)",
+ # also good: (1/2+1/2*i*3^(1/2))^(1/3)
+
+ "simplify((2 + 5^(1/2))^(1/3))",
+ "1/2*(1+5^(1/2))",
+
+ "simplify((-3 + 10*3^(1/2)*i/9)^(1/3))",
+ "1+2/3*i*3^(1/2)",
+
+ "simplify((1-3*x^2+3*x^4-x^6)^(1/2))",
+ "(-x^6+3*x^4-3*x^2+1)^(1/2)",
+
+ "simplify(subst((-1)^(1/2),i,(-3 + 10*3^(1/2)*i/9)^(1/3)))",
+ "1+2/3*i*3^(1/2)",
+
+ "simplify(rationalize(-3 + 10*3^(1/2)*i/9)^(1/3))",
+ "1+2/3*i*3^(1/2)",
+
+ # note that sympy doesn't give a straight symbolic answer to
+ # this one, the result to this is numeric instead, and with
+ # a near-zero imaginary part.
+ # In Sympy one can get to the answer obliquely with minpoly instead,
+ # as minpoly((-1)^(1/6) - (-1)^(5/6)) -> x^2−3
+ "simplify((-1)^(1/6) - (-1)^(5/6))",
+ "3^(1/2)",
+
+ "simplify((7208+2736*5^(1/2))^(1/3))",
+ "17+3*5^(1/2)",
+
+ "simplify((901+342*5^(1/2))^(1/3))",
+ "1/2*(17+3*5^(1/2))",
+
+ "-i*(-2*(-1)^(1/6)/(3^(1/2))+2*(-1)^(5/6)/(3^(1/2)))^(1/4)*(2*(-1)^(1/6)/(3^(1/2))-2*(-1)^(5/6)/(3^(1/2)))^(1/4)/(2^(1/2))",
+ "1/2^(1/2)-i/(2^(1/2))",
+
+ "simplify(-i*(-2*(-1)^(1/6)/(3^(1/2))+2*(-1)^(5/6)/(3^(1/2)))^(1/4)*(2*(-1)^(1/6)/(3^(1/2))-2*(-1)^(5/6)/(3^(1/2)))^(1/4)/(2^(1/2)))",
+ # this one simplifies to any of these two, these are all the same:
+ "(1-i)/(2^(1/2))",
+ # -(-1)^(3/4)
+ #"-(-1)^(3/4)",
+
+ "(-1)^(-5/a)",
+ #"(-1)^(-5/a)",
+ "1/(-1)^(5/a)",
+
+
+ # -----------------------
+ "simplify((-1)^(-5))",
+ "-1",
+
+ "simplify((-1)^(5))",
+ "-1",
+
+ "simplify((1)^(-5))",
+ "1",
+
+ "simplify((1)^(5))",
+ "1",
+
+ # seems here that the simplification
+ # has more nodes than the result but
+ # it's not the case: the 1/... inversion
+ # is just done at the print level for
+ # legibility
+ "simplify((-1)^(-5/a))",
+ #"(-1)^(-5/a)",
+ "1/(-1)^(5/a)",
+
+ "simplify((-1)^(5/a))",
+ "(-1)^(5/a)",
+
+ "simplify((1)^(-5/a))",
+ "1",
+
+ "simplify((1)^(5/a))",
+ "1",
+
+ # -----------------------
+ "simplify((-1)^(-6))",
+ "1",
+
+ "simplify((-1)^(6))",
+ "1",
+
+ "simplify((1)^(-6))",
+ "1",
+
+ "simplify((1)^(6))",
+ "1",
+
+ # clockform can be much more compact than the
+ # rectangular format so we return that one,
+ # the user can always do a rect or a circexp on
+ # the result if she desires other forms
+ "simplify(i*2^(1/4)*sin(1/8*pi)+2^(1/4)*cos(1/8*pi))",
+ "(-1)^(1/8)*2^(1/4)",
+ # the circexp of the above is
+ # 2^(1/4) exp(1/8 i pi), which is less compact
+
+
+ # seems here that the simplification
+ # has more nodes than the result but
+ # it's not the case: the 1/... inversion
+ # is just done at the print level for
+ "simplify((-1)^(-6/a))",
+ #"(-1)^(-6/a)",
+ "1/(-1)^(6/a)",
+
+ "simplify((-1)^(6/a))",
+ "(-1)^(6/a)",
+
+ "simplify((1)^(-6/a))",
+ "1",
+
+ "simplify((1)^(6/a))",
+ "1",
+
+ "simplify(transpose(A)*transpose(x))",
+ "transpose(A*x)",
+
+ "simplify(inner(transpose(A),transpose(x)))",
+ "transpose(inner(x,A))",
+
+ # ---------------------------------------------
+ # checking that simplify doesn't make incorrect
+ # simplifications
+
+ "simplify(sqrt(-1/2 -1/2 * x))",
+ "(-1/2*x-1/2)^(1/2)",
+
+ "simplify(sqrt(x*y))",
+ "(x*y)^(1/2)",
+
+ "simplify(sqrt(1/x))",
+ "(1/x)^(1/2)",
+
+ "simplify(sqrt(x^y))",
+ "(x^y)^(1/2)",
+
+ "simplify(sqrt(x)^2)",
+ "x",
+
+ "simplify(sqrt(x^2))",
+ "abs(x)",
+
+ # simplifying rational expressions
+
+ "simplify((x+1)*(x+1)/(x+1))",
+ "x+1",
+
+ "simplify(x*(x+1)/x)",
+ "x+1",
+
+ "simplify((x^2+7x+6)/(x^2-5x-6))",
+ "(x+6)/(x-6)",
+
+ "simplify(x*(x+1)/(x+1)+1)",
+ "x+1",
+
+ "simplify(x*(x+1)/(x+1))",
+ "x",
+
+ "simplify((x^2+3x)/(x^2+5x))",
+ "(x+3)/(x+5)",
+
+ "simplify((6x+20)/(2x+10))",
+ "(3*x+10)/(x+5)",
+
+ "simplify((x^3-3x^2)/(4x^2-5x))",
+ "x*(x-3)/(4*x-5)",
+
+ "simplify((x^2-9)/(x^2+5x+6))",
+ "(x-3)/(x+2)",
+
+ "simplify((x^2-3x+2)/(x^2-1))",
+ "(x-2)/(x+1)",
+
+ "simplify((x^2-2x-15)/(x^2+x-6))",
+ "(x-5)/(x-2)",
+
+ "simplify(10x^3/(2x^2-18x))",
+ "5*x^2/(x-9)",
+
+ "simplify(6x^2/(12x^4-9x^3))",
+ "1/(x*(2*x-3/2))",
+
+ "simplify(((3-x)*(x-1))/((x-3)*(x+1)))",
+ "(-x+1)/(x+1)",
+
+ "simplify(((x-2)*(x-5))/((2-x)*(x+5)))",
+ "(-x+5)/(x+5)",
+
+ "simplify((15-10x)/(8x^3-12x^2))",
+ "-5/(4*x^2)",
+
+ "simplify(3x/(15x^2-6x))",
+ "1/(5*x-2)",
+
+ "simplify((3x^3-15x^2+12x)/(3x-3))",
+ "x*(x-4)",
+
+ "simplify((6x^2-12x)/(6x-3x^2))",
+ "-2",
+
+ "simplify((2x^2+13x+20)/(2x^2+17x+30))",
+ "(x+4)/(x+6)",
+
+ "simplify((x^4+8x^2+7)/(3x^5-3x))",
+ "(x^2+7)/(3*x*(x^2-1))",
+
+ "simplify((x^2+8x*k+16*k^2)/(x^2-16k^2))",
+ "(x+4*k)/(x-4*k)",
+
+ "simplify((x^2-2x-8)/(x^2-9x+20))",
+ "(x+2)/(x-5)",
+
+ "simplify((x^2-25)/(5x-x^2))",
+ "-1-5/x",
+
+ "simplify((x^7+2x^6+x^5)/(x^3*(x+1)^8))",
+ "x^2/((x+1)^6)",
+
+ "simplify((x^2+2*x+1)/((x+1)^8))",
+ "1/((x+1)^6)",
+
+ "simplify(((x^2-5x-14)/(x^2-3x+2))*((x^2-4)/(x^2-14x+49)))",
+ "(x+2)^2/((x-7)*(x-1))",
+
+ "simplify(((x^2-9)/(x^2+5x+6))/((3-x)/(x+2)))",
+ "-1",
+
+ "simplify((x^2+5x+4)/((x^2-1)/(x+5)))",
+ "(x^2+9*x+20)/(x-1)",
+
+ "simplify((x^2-6x-7)/(x^2-10x+21))",
+ "(x+1)/(x-3)",
+
+ "simplify((x^2+6x+9)/(x^2-9))",
+ "(x+3)/(x-3)",
+
+ "simplify((2x^2-x-28)/(20-x-x^2))",
+ "(-2*x-7)/(x+5)",
+
+ "simplify(((x^2+5x-24)/(x^2+6x+8))*((x^2+4x+4)/(x^2-3x)))",
+ "(10+x+16/x)/(x+4)",
+
+ "simplify(((x^2-49)/(2x^2-3x-5))/((x^2-x-42)/(x^2+7x+6)))",
+ "(x+7)/(2*x-5)",
+
+ "simplify(((x^2-2x-8)/(2x^2-8x-24))/((x^2-9x+20)/(x^2-11x+30)))",
+ "1/2",
+
+ "simplify((3/(x+1))/((x+4)/(x^2+11x+10)))",
+ "3*(x+10)/(x+4)",
+
+ "simplify((x^3+10x^2)/(x^2+6x-40))",
+ "x^2/(x-4)",
+
+ "simplify((x^2+18x+72)/(2x^2+11x-6))",
+ "(x+12)/(2*x-1)",
+
+ "simplify((x^2-3x-28)/(49-x^2))",
+ "(-x-4)/(x+7)",
+
+ "simplify((6x^2+13x+5)/(3x^2+26x+35))",
+ "(2*x+1)/(x+7)",
+
+ "simplify((-x^2+10x-9)/(-x^2+6x+27))",
+ "(x-1)/(x+3)",
+
+ "simplify((x-6)*(x^3+x^2-20x)/(x^4-12x^3+36x^2))",
+ "(1+x-20/x)/(x-6)",
+
+ # somewhat strange simplification but it's correct
+ "simplify(((4x^3-x^2-3x)/(x^2-10x+25))*((10+3x-x^2)/(x^4-x^3)))",
+ "(-4-6/(x^2)-11/x)/(x-5)",
+
+ "simplify(((x^2+5x-24)/(x^2-5x+4))/((x^2+x-12)/(x-1)))",
+ "(x+8)/(x^2-16)",
+
+ "simplify(((6x^2+x^3-x^4)/(x^2-4))/((3x^3-9x^2)/(x^2+6x-16)))",
+ "1/3*(-x-8)",
+
+ "simplify(((3x^2+23x+14)/(x^2+4x+3))/((6x^2+13x+6)/(x^2+2x+1)))",
+ "(x^2+8*x+7)/((x+3)*(2*x+3))",
+
+ "simplify((5x^2-18x-8)/((x-4)/(x+6)))",
+ "5*x^2+32*x+12",
+
+ "simplify((2/(x+4))/((6x^3+17x^2)/(x^2+3x-4)))",
+ "(x-1)/(x^2*(3*x+17/2))",
+
+ # sum of rational expressions
+ "simplify(((x^2+1)/(2x^2-4x+2))+((x)/((x-1)^2))+((-x-1)/(x^2-2x+1)))",
+ "(x+1)/(2*(x-1))",
+
+ "simplify((4/(6x^2))-(1/(3x^5))+(5/(2x^3)))",
+ "(2/3*x^3+5/2*x^2-1/3)/(x^5)",
+
+ "simplify((x/(x^2-2x+1))-(2/(x-1))+(3/(x+2)))",
+ "(2*x^2-6*x+7)/(x^3-3*x+2)",
+
+ "simplify((2x/(x^2-9))-(1/(x+3))-(2/(x-3)))",
+ "-1/(x-3)",
+
+ "simplify((4/(x+2)-(1/x)+1)*(x+2)*x)",
+ "x^2+5*x-2",
+
+ "simplify(((3/(x-4))+x/(2x+7))*(x-4)*(2x+7))",
+ "x^2+2*x+21",
+
+ "simplify((x/(x^2+12x+36))-((x-8)/(x+6)))",
+ "(-x^2+3*x+48)/((x+6)^2)",
+
+ "simplify(((x^2+14x+40)/(x^2+2x-8))*((x^2+5x-14)/(x^2+7x-30)))",
+ "(x+7)/(x-3)",
+
+ # could be cleaner but it's correct
+ "simplify(1/(x^2-13x+42)+(x+1)/(x-6)-x^2/(x-7))",
+ "1/(x-7)+x/(x-6)-x^2/(x-7)",
+
+ "simplify((x+10)/((3x+8)^3)+x/((3x+8)^2))",
+ "(3*x^2+9*x+10)/((3*x+8)^3)",
+
+ "simplify(2/(3x^2)-1/(4x^7)+7/(6x^3))",
+ "(2/3*x^5+7/6*x^4-1/4)/(x^7)",
+
+ "simplify(2x/(x+9)-(x-1)/(x))",
+ "-1+1/x+2*x/(x+9)",
+
+ "simplify((x+1)/(x-1)+6/(x-7))",
+ "(x^2-13)/((x-7)*(x-1))",
+
+ "simplify(9/(x^2-4)-7x/(x^2-4x+4))",
+ "(-7*x^2-5*x-18)/((x-2)^2*(x+2))",
+
+ "simplify((2x+1)/(4x^2-3x-7)-(x+3)/(x+1)+x/(4x-7))",
+ "x/(4*x-7)-x/(x+1)+2*(-5*x+11)/((4*x-7)*(x+1))",
+
+ "simplify(simplify((2x+1)/(4x^2-3x-7)-(x+3)/(x+1)+x/(4x-7))*(x+1)*(4x-7))",
+ "-3*x^2-2*x+22",
+
+ # could be cleaner but it's correct
+ "simplify(3/(6x-x^2)-x/(x^2-5x-6))",
+ "(-3-x-3/x)/((x-6)*(x+1))",
+
+ # could be cleaner but it's correct
+ "simplify(3/(x^2)+(x+9)/(x^2+5x)-2/(x^2+10x+25))",
+ "(15+x+75/(x^2)+75/x)/((x+5)^2)",
+
+ "simplify(1/(x+1)-2/((x+1)^2)-3/((x+1)^3))",
+ "(x^2-4)/((x+1)^3)",
+
+ ]
diff --git a/node_modules/algebrite/tests/sin.coffee b/node_modules/algebrite/tests/sin.coffee
new file mode 100644
index 0000000..cbcc049
--- /dev/null
+++ b/node_modules/algebrite/tests/sin.coffee
@@ -0,0 +1,219 @@
+test_sin = ->
+ run_test [
+
+ "sin(x)",
+ "sin(x)",
+
+ "sin(-x)",
+ "-sin(x)",
+
+ "sin(b-a)",
+ "-sin(a-b)",
+
+ # check against the floating point math library
+
+ "f(a,x)=1+sin(float(a/360*2*pi))-float(x)+sin(a/360*2*pi)-x",
+ "",
+
+ "f(0,0)", # 0
+ "1.0",
+
+ "f(90,1)", # 90
+ "1.0",
+
+ "f(180,0)", # 180
+ "1.0",
+
+ "f(270,-1)", # 270
+ "1.0",
+
+ "f(360,0)", # 360
+ "1.0",
+
+ "f(-90,-1)", # -90
+ "1.0",
+
+ "f(-180,0)", # -180
+ "1.0",
+
+ "f(-270,1)", # -270
+ "1.0",
+
+ "f(-360,0)", # -360
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(45,sqrt(2)/2)", # 45
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(135,sqrt(2)/2)", # 135
+ "1.000000...",
+
+ "f(225,-sqrt(2)/2)", # 225
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(315,-sqrt(2)/2)", # 315
+ "1.000000...",
+
+ "f(-45,-sqrt(2)/2)", # -45
+ "1.0",
+
+ "f(-135,-sqrt(2)/2)", # -135
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-225,sqrt(2)/2)", # -225
+ "1.000000...",
+
+ "f(-315,sqrt(2)/2)", # -315
+ "1.0",
+
+ "f(30,1/2)", # 30
+ "1.0",
+
+ "f(150,1/2)", # 150
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(210,-1/2)", # 210
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(330,-1/2)", # 330
+ "1.000000...",
+
+ "f(-30,-1/2)", # -30
+ "1.0",
+
+ "f(-150,-1/2)", # -150
+ "1.0",
+
+ "f(-210,1/2)", # -210
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-330,1/2)", # -330
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(60,sqrt(3)/2)", # 60
+ "1.000000...",
+
+ "f(120,sqrt(3)/2)", # 120
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(240,-sqrt(3)/2)", # 240
+ "1.000000...",
+
+ "f(300,-sqrt(3)/2)", # 300
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-60,-sqrt(3)/2)", # -60
+ "1.000000...",
+
+ "f(-120,-sqrt(3)/2)", # -120
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-240,sqrt(3)/2)", # -240
+ "1.000000...",
+
+ "f(-300,sqrt(3)/2)", # -300
+ "1.0",
+
+ "f=quote(f)",
+ "",
+
+ "sin(arcsin(x))",
+ "x",
+
+ # check the default case
+
+ "sin(1/12*pi)",
+ "sin(1/12*pi)",
+
+ "sin(arctan(4/3))",
+ "4/5",
+
+ "sin(-arctan(4/3))",
+ "-4/5",
+
+ # phase
+
+ "sin(x-8/2*pi)",
+ "sin(x)",
+
+ "sin(x-7/2*pi)",
+ "cos(x)",
+
+ "sin(x-6/2*pi)",
+ "-sin(x)",
+
+ "sin(x-5/2*pi)",
+ "-cos(x)",
+
+ "sin(x-4/2*pi)",
+ "sin(x)",
+
+ "sin(x-3/2*pi)",
+ "cos(x)",
+
+ "sin(x-2/2*pi)",
+ "-sin(x)",
+
+ "sin(x-1/2*pi)",
+ "-cos(x)",
+
+ "sin(x+0/2*pi)",
+ "sin(x)",
+
+ "sin(x+1/2*pi)",
+ "cos(x)",
+
+ "sin(x+2/2*pi)",
+ "-sin(x)",
+
+ "sin(x+3/2*pi)",
+ "-cos(x)",
+
+ "sin(x+4/2*pi)",
+ "sin(x)",
+
+ "sin(x+5/2*pi)",
+ "cos(x)",
+
+ "sin(x+6/2*pi)",
+ "-sin(x)",
+
+ "sin(x+7/2*pi)",
+ "-cos(x)",
+
+ "sin(x+8/2*pi)",
+ "sin(x)",
+ ]
diff --git a/node_modules/algebrite/tests/sinh.coffee b/node_modules/algebrite/tests/sinh.coffee
new file mode 100644
index 0000000..4eae177
--- /dev/null
+++ b/node_modules/algebrite/tests/sinh.coffee
@@ -0,0 +1,11 @@
+test_sinh = ->
+ run_test [
+ "sinh(x)",
+ "sinh(x)",
+
+ "sinh(0)",
+ "0",
+
+ "sinh(arcsinh(x))",
+ "x",
+ ]
diff --git a/node_modules/algebrite/tests/strings.coffee b/node_modules/algebrite/tests/strings.coffee
new file mode 100644
index 0000000..1d97fb9
--- /dev/null
+++ b/node_modules/algebrite/tests/strings.coffee
@@ -0,0 +1,22 @@
+test_strings = ->
+ run_test [
+
+ "\"hey\" + \"you\"",
+ "\"hey\"+\"you\"",
+
+ "\"hey\" + \"hey\"",
+ "2*\"hey\"",
+
+ "\"hey\" / \"hey\"",
+ "1",
+
+ "\"hey\" - \"hey\"",
+ "0",
+
+ "\"hey\" * \"hey\"",
+ "\"hey\"^2",
+
+ "\"aaaaaaaaaa\nbbbbbbbbbb\"",
+ "\"aaaaaaaaaa\nbbbbbbbbbb\"",
+
+ ]
diff --git a/node_modules/algebrite/tests/subst.coffee b/node_modules/algebrite/tests/subst.coffee
new file mode 100644
index 0000000..b5f99ad
--- /dev/null
+++ b/node_modules/algebrite/tests/subst.coffee
@@ -0,0 +1,7 @@
+test_subst = ->
+ run_test [
+
+ "subst((-1)^(1/2),i,-3 + 10*3^(1/2)*i/9)",
+ "-3+10/9*i*3^(1/2)",
+
+ ]
diff --git a/node_modules/algebrite/tests/sum.coffee b/node_modules/algebrite/tests/sum.coffee
new file mode 100644
index 0000000..9c3ff05
--- /dev/null
+++ b/node_modules/algebrite/tests/sum.coffee
@@ -0,0 +1,32 @@
+test_sum = ->
+ run_test [
+
+ # no evaluation in case there are
+ # symbolic variables
+ "sum(body + k,k,b,c)",
+ "sum(body+k,k,b,c)",
+
+ "f=sum(a^k,k,0,9)",
+ "",
+
+ "eval(f,a,-1/2)",
+ "341/512",
+
+ # Leibniz formula for π as a series
+ "sum(float((-1)^k * (1/(2*k + 1))),k,0,100)*4",
+ "3.151493...",
+
+ # -------------------
+
+ "f(a,b)=sum(k,k,a,b)",
+ "",
+
+ "f(0,1)",
+ "1",
+
+ # --- cleanup
+
+ "f = quote(f)",
+ "",
+
+ ]
diff --git a/node_modules/algebrite/tests/tan.coffee b/node_modules/algebrite/tests/tan.coffee
new file mode 100644
index 0000000..ba07c9e
--- /dev/null
+++ b/node_modules/algebrite/tests/tan.coffee
@@ -0,0 +1,168 @@
+test_tan = ->
+ run_test [
+ "tan(x)",
+ "tan(x)",
+
+ "tan(-x)",
+ "-tan(x)",
+
+ "tan(b-a)",
+ "-tan(a-b)",
+
+ # check against the floating point math library
+
+ "f(a,x)=1+tan(float(a/360*2*pi))-float(x)+tan(a/360*2*pi)-x",
+ "",
+
+ "f(0,0)", # 0
+ "1.0",
+
+ "f(180,0)", # 180
+ "1.0",
+
+ "f(360,0)", # 360
+ "1.0",
+
+ "f(-180,0)", # -180
+ "1.0",
+
+ "f(-360,0)", # -360
+ "1.0",
+
+ "f(45,1)", # 45
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(135,-1)", # 135
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(225,1)", # 225
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(315,-1)", # 315
+ "1.000000...",
+
+ "f(-45,-1)", # -45
+ "1.0",
+
+ "f(-135,1)", # -135
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-225,-1)", # -225
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-315,1)", # -315
+ "1.000000...",
+
+ "f(30,sqrt(3)/3)", # 30
+ "1.0",
+
+ "f(150,-sqrt(3)/3)", # 150
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(210,sqrt(3)/3)", # 210
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(330,-sqrt(3)/3)", # 330
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-30,-sqrt(3)/3)", # -30
+ "1.000000...",
+
+ "f(-150,sqrt(3)/3)", # -150
+ "1.0",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-210,-sqrt(3)/3)", # -210
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-330,sqrt(3)/3)", # -330
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(60,sqrt(3))", # 60
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(120,-sqrt(3))", # 120
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(240,sqrt(3))", # 240
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(300,-sqrt(3))", # 300
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-60,-sqrt(3))", # -60
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-120,sqrt(3))", # -120
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-240,-sqrt(3))", # -240
+ "1.000000...",
+
+ # this should really be 1.0 , however
+ # we have errors doing the calculations so
+ # we don't get to that exact 1.0 float
+ "f(-300,sqrt(3))", # -300
+ "1.000000...",
+
+ "f=quote(f)",
+ "",
+
+ "tan(arctan(x))",
+ "x",
+
+ # check the default case
+
+ "tan(1/12*pi)",
+ "tan(1/12*pi)",
+ ]
diff --git a/node_modules/algebrite/tests/tanh.coffee b/node_modules/algebrite/tests/tanh.coffee
new file mode 100644
index 0000000..9b06eea
--- /dev/null
+++ b/node_modules/algebrite/tests/tanh.coffee
@@ -0,0 +1,11 @@
+test_tanh = ->
+ run_test [
+ "tanh(x)",
+ "tanh(x)",
+
+ "tanh(0)",
+ "0",
+
+ "tanh(arctanh(x))",
+ "x",
+ ]
diff --git a/node_modules/algebrite/tests/taylor.coffee b/node_modules/algebrite/tests/taylor.coffee
new file mode 100644
index 0000000..7830bd8
--- /dev/null
+++ b/node_modules/algebrite/tests/taylor.coffee
@@ -0,0 +1,8 @@
+test_taylor = ->
+ run_test [
+ "taylor(1/(5+4*cos(x)),x,6,0)-(1/9+2/81*x^2+5/1458*x^4+49/131220*x^6)",
+ "0",
+
+ "taylor(1/(5+4*cos(x)),x,6)-(1/9+2/81*x^2+5/1458*x^4+49/131220*x^6)",
+ "0",
+ ]
diff --git a/node_modules/algebrite/tests/tensor.coffee b/node_modules/algebrite/tests/tensor.coffee
new file mode 100644
index 0000000..17b8868
--- /dev/null
+++ b/node_modules/algebrite/tests/tensor.coffee
@@ -0,0 +1,233 @@
+test_tensor = ->
+ run_test [
+
+ "[[a]]",
+ "[[a]]",
+
+ # ---------------------------------
+ # basic parsing, promotion and printout
+ # ---------------------------------
+
+ "[[1,0],[0,0]]",
+ "[[1,0],[0,0]]",
+
+ # ---------------------------------
+ # basic rank and shape checks
+ # ---------------------------------
+
+ # in general, the trick to count
+ # rank (i.e. dimensions) is to count the
+ # number of nested brackets
+ # and the trick to determine the shape
+ # is to count the commas proceeding
+ # from the outermost to the
+ # inner-most brackets.
+
+ "rank(a)",
+ "0",
+
+ "rank([a,b,c])",
+ "1",
+
+ "shape([a,b,c])",
+ "[3]",
+
+ "rank([[a,b,c]])",
+ "2",
+
+ # traditional matrix 1x3
+ # i.e. one row three columns
+ # i.e. row vector
+ "shape([[a,b,c]])",
+ "[1,3]",
+
+ "rank([[a],[b],[c]])",
+ "2",
+
+ # traditional matrix 3x1
+ # i.e. one columns three rows
+ # i.e. column vector
+ "shape([[a],[b],[c]])",
+ "[3,1]",
+
+ "rank([[[a,b,c]]])",
+ "3",
+
+ "shape([[[a,b,c]]])",
+ "[1,1,3]",
+
+ "rank([[[a],[b],[c]]])",
+ "3",
+
+ "shape([[[a],[b],[c]]])",
+ "[1,3,1]",
+
+ "rank([[[a]],[[b]],[[c]]])",
+ "3",
+
+ "shape([[[a]],[[b]],[[c]]])",
+ "[3,1,1]",
+
+
+ # ---------------------------------
+ # check tensor promotion
+ # ---------------------------------
+
+ "a=[1,2,3]",
+ "",
+
+ "rank(a)",
+ "1",
+
+ "b=[4,5,6]",
+ "",
+
+ "c=[7,8,9]",
+ "",
+
+ "rank([a,b,c])",
+ "2",
+
+ "[a,b,c]",
+ "[[1,2,3],[4,5,6],[7,8,9]]",
+
+
+ # -------------------------------------------------------
+ # parsing, assigments and invokations calisthenics
+ # mixes [] used for a) tensor building and b) tensor indexing
+ # and mixes () used for a) function declarations
+ # b) function invokation and c) precedence
+ # Nests functions and matrices inside one another.
+ # -------------------------------------------------------
+
+ # --------------------
+
+ "f(x) = x + 1",
+ "",
+
+ "a=[1,f,3]",
+ "",
+
+ "a[2]",
+ "function (x) -> x+1",
+
+ "a[f(1)]",
+ "function (x) -> x+1",
+
+ "a[a[f(1)](1)]",
+ "function (x) -> x+1",
+
+ "a[2](9)",
+ "10",
+
+ "a[f(1)](f(8))",
+ "10",
+
+ "a[a[f(1)](1)](a[f(1)](8))",
+ "10",
+
+ # --------------------
+
+ "g(x) = x + 1",
+ "",
+
+ "f() = [1,g,3]",
+ "",
+
+ "a=[1,f,3]",
+ "",
+
+ "a[2]()[2](7)",
+ "8",
+
+ # --------------------
+
+ "g(x) = x + 1",
+ "",
+
+ "f() = [[1,g,3],[0,0,0],[0,0,0]]",
+ "",
+
+ "a=[1,f,3]",
+ "",
+
+ "a[2]()[1][2](8)",
+ "9",
+
+ "(a[2]())[1][2](8)",
+ "9",
+
+ "((a[2]())[1])[2](8)",
+ "9",
+
+ "(((a[2]())[1])[2])(8)",
+ "9",
+
+ "(((a[a[1]+a[1]]())[a[1]])[a[1]+a[1]])(8)",
+ "9",
+
+ "f()[1][2](8)",
+ "9",
+
+ "f()[a[1]][a[1]+a[1]](8)",
+ "9",
+
+ # --------------------
+
+ "g(x) = transpose(x)",
+ "",
+
+ "f() = [[1,g,3],[0,0,0],[0,0,0]]",
+ "",
+
+ "a=[1,f,3]",
+ "",
+
+ "a[2]()[1][2]([[1,2,3,4]])",
+ "[[1],[2],[3],[4]]",
+
+ # --------------------
+
+ "unit(x)",
+ "unit(x)",
+
+ "unit(3)",
+ "[[1,0,0],[0,1,0],[0,0,1]]",
+
+ "unit(1)",
+ "[[1]]",
+
+ # cleanup
+
+ "a=quote(a)",
+ "",
+
+ "b=quote(b)",
+ "",
+
+ "c=quote(c)",
+ "",
+
+ "f=quote(f)",
+ "",
+
+ "g=quote(g)",
+ "",
+
+ # -------------------------------------------------------
+ # handling of zero matrices
+ # -------------------------------------------------------
+
+ "-[0,0]",
+ "[0,0]",
+
+ "zero(2,2)-zero(2,2)",
+ "[[0,0],[0,0]]",
+
+ "-[0]",
+ "[0]",
+
+ "[[0,0],[1,1]]-[[0,0],[1,1]]",
+ "[[0,0],[0,0]]",
+
+ ]
diff --git a/node_modules/algebrite/tests/test.coffee b/node_modules/algebrite/tests/test.coffee
new file mode 100644
index 0000000..6afd4ea
--- /dev/null
+++ b/node_modules/algebrite/tests/test.coffee
@@ -0,0 +1,655 @@
+test_test = ->
+ run_test [
+ "a=1",
+ "1",
+
+ "1>=2",
+ "0",
+
+ "2>=1",
+ "1",
+
+ "1>1",
+ "0",
+
+ "1>2",
+ "0",
+
+ "2>1",
+ "1",
+
+ "1<=1",
+ "1",
+
+ "1<=2",
+ "1",
+
+ "2<=1",
+ "0",
+
+ "1<1",
+ "0",
+
+ "1<2",
+ "1",
+
+ "2<1",
+ "0",
+
+ "-1<-2",
+ "0",
+
+ "-2<-1",
+ "1",
+
+ "test(0,A,B)",
+ "B",
+
+ "test(1,A,B)",
+ "A",
+
+ "test(0,A,0,B)",
+ "0",
+
+ "test(0,A,0,B,C)",
+ "C",
+
+ "test(x<3,-x-4,3<=x,x*x+7,120/x+5)",
+ "test(testlt(x,3),-x-4,testle(3,x),x^2+7,120/x+5)",
+
+ "x = -1",
+ "",
+
+ "test(x<1,-x-4,3<=x,x*x+7,120/x+5)",
+ "-3",
+
+ "x = 3",
+ "",
+
+ "test(x<1,-x-4,3<=x,x*x+7,120/x+5)",
+ "16",
+
+ "x = 2",
+ "",
+
+ "test(x<1,-x-4,3<=x,x*x+7,120/x+5)",
+ "65",
+
+ "x=quote(x)",
+ "",
+
+ # not ---------------------------------
+
+ "not(a=b)",
+ "not(a=b)",
+
+ "a",
+ "a",
+
+ "not(a)",
+ "not(a)",
+
+ "not(not(a))",
+ "not(not(a))",
+
+ "not(a=a)",
+ "0",
+
+ "not(not(a=a))",
+ "1",
+
+ "not(a==a)",
+ "0",
+
+ "not(a===a)",
+ "not(a=== ? a)\nStop: syntax error",
+
+ "not(a+1=a)",
+ "1",
+
+ "not(a+1==a)",
+ "1",
+
+ "not(a+1===a)",
+ "not(a+1=== ? a)\nStop: syntax error",
+
+ "not(1)",
+ "0",
+
+ "not(0)",
+ "1",
+
+ "not(and(1,0))",
+ "1",
+
+ "not(and(1,1))",
+ "0",
+
+ # if passed a value, check if non-zero
+ "not(pi)",
+ "0",
+
+ "not(2)",
+ "0",
+
+ "not(-2)",
+ "0",
+
+ "not(sqrt(2))",
+ "0",
+
+ "not(sqrt(-1))",
+ "0",
+
+ "not(sqrt(pi/4)-sqrt(i))",
+ "0",
+
+ "not(1+i)",
+ "0",
+
+ "not([0,0])",
+ "1",
+
+ "not([1,2])",
+ "0",
+
+ "not([1+i,2])",
+ "0",
+
+ "not([a,2])",
+ "not([a,2])",
+
+ "not(1-i)",
+ "0",
+
+
+ # and ---------------------------------
+
+ # and with the first predicate being true
+
+ "and(1,1)",
+ "1",
+
+ "and(1,a=a,b=b)",
+ "1",
+
+ "and(1,0)",
+ "0",
+
+ "and(1,2)",
+ "1",
+
+ "and(1,-2)",
+ "1",
+
+ "and(1,sqrt(2))",
+ "1",
+
+ "and(1,sqrt(-1))",
+ "1",
+
+ "and(1,sqrt(pi/4)-sqrt(i))",
+ "1",
+
+ "and(1,1+i)",
+ "1",
+
+
+ "and(1,a)",
+ "and(1,a)",
+
+
+ "and(1,[0,0])",
+ "0",
+
+ "and(1,[1,2])",
+ "1",
+
+ "and(1,[1+i,2])",
+ "1",
+
+ "and(1,[a,2])",
+ "and(1,[a,2])",
+
+ "and(1,1-i)",
+ "1",
+
+ # and with the first predicate being false
+
+ "and(0,1)",
+ "0",
+
+ "and(0,a=a,b=b)",
+ "0",
+
+ "and(0,0)",
+ "0",
+
+ "and(0,2)",
+ "0",
+
+ "and(0,-2)",
+ "0",
+
+ "and(0,sqrt(2))",
+ "0",
+
+ "and(0,sqrt(-1))",
+ "0",
+
+ "and(0,sqrt(pi/4)-sqrt(i))",
+ "0",
+
+ "and(0,1+i)",
+ "0",
+
+ "and(0,a)",
+ "0",
+
+ "and(0,[0,0])",
+ "0",
+
+ "and(0,[1,2])",
+ "0",
+
+ "and(0,[1+i,2])",
+ "0",
+
+ "and(0,[a,2])",
+ "0",
+
+ "and(0,1-i)",
+ "0",
+
+ # and with last predicate being true
+
+ "and(1,1)",
+ "1",
+
+ "and(a=a,b=b,1)",
+ "1",
+
+ "and(0,1)",
+ "0",
+
+ "and(2,1)",
+ "1",
+
+ "and(-2,1)",
+ "1",
+
+ "and(sqrt(2),1)",
+ "1",
+
+ "and(sqrt(-1),1)",
+ "1",
+
+ "and(sqrt(pi/4)-sqrt(i),1)",
+ "1",
+
+ "and(1+i,1)",
+ "1",
+
+
+ "and(a,1)",
+ "and(a,1)",
+
+
+ "and([0,0],1)",
+ "0",
+
+ "and([1,2],1)",
+ "1",
+
+ "and([1+i,2],1)",
+ "1",
+
+ "and([a,2],1)",
+ "and([a,2],1)",
+
+ "and(1-i,1)",
+ "1",
+
+ # and with last predicate being false
+
+ "and(1,0)",
+ "0",
+
+ "and(a=a,b=b,0)",
+ "0",
+
+ "and(0,0)",
+ "0",
+
+ "and(2,0)",
+ "0",
+
+ "and(-2,0)",
+ "0",
+
+ "and(sqrt(2),0)",
+ "0",
+
+ "and(sqrt(-1),0)",
+ "0",
+
+ "and(sqrt(pi/4)-sqrt(i),0)",
+ "0",
+
+ "and(1+i,0)",
+ "0",
+
+ "and(a,0)",
+ "0",
+
+
+ "and([0,0],0)",
+ "0",
+
+ "and([1,2],0)",
+ "0",
+
+ "and([1+i,2],0)",
+ "0",
+
+ "and([a,2],0)",
+ "0",
+
+ "and(1-i,0)",
+ "0",
+
+ # or ----------------------------------------------
+
+ # or with the first predicate being true
+
+ "or(1,1)",
+ "1",
+
+ "or(1,a=a,b=b)",
+ "1",
+
+ "or(1,0)",
+ "1",
+
+ "or(1,2)",
+ "1",
+
+ "or(1,-2)",
+ "1",
+
+ "or(1,sqrt(2))",
+ "1",
+
+ "or(1,sqrt(-1))",
+ "1",
+
+ "or(1,sqrt(pi/4)-sqrt(i))",
+ "1",
+
+ "or(1,1+i)",
+ "1",
+
+ "or(1,a)",
+ "1",
+
+ "or(1,[0,0])",
+ "1",
+
+ "or(1,[1,2])",
+ "1",
+
+ "or(1,[1+i,2])",
+ "1",
+
+ "or(1,[a,2])",
+ "1",
+
+ "or(1,1-i)",
+ "1",
+
+ # or with the first predicate being false
+
+ "or(0,1)",
+ "1",
+
+ "or(0,a=a,b=b)",
+ "1",
+
+ "or(0,0)",
+ "0",
+
+ "or(0,2)",
+ "1",
+
+ "or(0,-2)",
+ "1",
+
+ "or(0,sqrt(2))",
+ "1",
+
+ "or(0,sqrt(-1))",
+ "1",
+
+ "or(0,sqrt(pi/4)-sqrt(i))",
+ "1",
+
+ "or(0,1+i)",
+ "1",
+
+ "or(0,a)",
+ "or(0,a)",
+
+ "or(0,[0,0])",
+ "0",
+
+ "or(0,[1,2])",
+ "1",
+
+ "or(0,[1+i,2])",
+ "1",
+
+ "or(0,[a,2])",
+ "or(0,[a,2])",
+
+ "or(0,1-i)",
+ "1",
+
+ # or with last predicate being true
+
+ "or(1,1)",
+ "1",
+
+ "or(a=a,b=b,1)",
+ "1",
+
+ "or(0,1)",
+ "1",
+
+ "or(2,1)",
+ "1",
+
+ "or(-2,1)",
+ "1",
+
+ "or(sqrt(2),1)",
+ "1",
+
+ "or(sqrt(-1),1)",
+ "1",
+
+ "or(sqrt(pi/4)-sqrt(i),1)",
+ "1",
+
+ "or(1+i,1)",
+ "1",
+
+ "or(a,1)",
+ "1",
+
+ "or([0,0],1)",
+ "1",
+
+ "or([1,2],1)",
+ "1",
+
+ "or([1+i,2],1)",
+ "1",
+
+ "or([a,2],1)",
+ "1",
+
+ "or(1-i,1)",
+ "1",
+
+ # or with last predicate being false
+
+ "or(1,0)",
+ "1",
+
+ "or(a=a,b=b,0)",
+ "1",
+
+ "or(0,0)",
+ "0",
+
+ "or(2,0)",
+ "1",
+
+ "or(-2,0)",
+ "1",
+
+ "or(sqrt(2),0)",
+ "1",
+
+ "or(sqrt(-1),0)",
+ "1",
+
+ "or(sqrt(pi/4)-sqrt(i),0)",
+ "1",
+
+ "or(1+i,0)",
+ "1",
+
+ "or(a,0)",
+ "or(a,0)",
+
+
+ "or([0,0],0)",
+ "0",
+
+ "or([1,2],0)",
+ "1",
+
+ "or([1+i,2],0)",
+ "1",
+
+ "or([a,2],0)",
+ "or([a,2],0)",
+
+ "or(1-i,0)",
+ "1",
+
+ # ------------------------------------------------
+
+ # zero and all zero vectors are considered equal.
+ # The reason being that the test checks whether
+ # [0,0]-0 is zero. Since anything minus zero is
+ # equal to itself, we effectively check if [0,0]
+ # is zero, which it is.
+ "[0,0]==0",
+ "1",
+
+ "[1,2]==[1,2]",
+ "1",
+
+ "[1,2]==[a,2]",
+ "testeq([1,2],[a,2])",
+
+ "[1,2]==[3,4]",
+ "0",
+
+ "[1,2]==[cos(x)^2 + sin(x)^2,2]",
+ "1",
+
+ "1= 1",
+ "1",
+
+ "cos(x)^2 + sin(x)^2 <= 1",
+ "1",
+
+ "cos(x)^2 + sin(x)^2 < 1",
+ "0",
+
+ "cos(x)^2 + sin(x)^2 + 1 > 1",
+ "1",
+
+ "x + x > x",
+ "testgt(2*x,x)",
+
+ "a > x",
+ "testgt(a,x)",
+
+ "a >= x",
+ "testge(a,x)",
+
+ "a == x",
+ "testeq(a,x)",
+
+ "a < x",
+ "testlt(a,x)",
+
+ "a <= x",
+ "testle(a,x)",
+
+ # clean up -----------------
+
+ "a=quote(a)",
+ "",
+
+ "x=quote(x)",
+ "",
+
+ "b=quote(b)",
+ "",
+
+ "A=quote(A)",
+ "",
+
+ "B=quote(B)",
+ "",
+
+ "C=quote(C)",
+ "",
+
+ ]
+
diff --git a/node_modules/algebrite/tests/transpose.coffee b/node_modules/algebrite/tests/transpose.coffee
new file mode 100644
index 0000000..b92a140
--- /dev/null
+++ b/node_modules/algebrite/tests/transpose.coffee
@@ -0,0 +1,181 @@
+test_transpose = ->
+ run_test [
+
+ "transpose(0)",
+ "0",
+
+ "transpose([[1,2,3,4]])",
+ "[[1],[2],[3],[4]]",
+
+ "transpose([[1],[2],[3],[4]])",
+ "[[1,2,3,4]]",
+
+ "transpose(0.0)",
+ "0.0",
+
+ "transpose([[a,b],[c,d]])",
+ "[[a,c],[b,d]]",
+
+ "transpose([[a,b],[c,d]],1,2)",
+ "[[a,c],[b,d]]",
+
+ "transpose([[a,b,c],[d,e,f]],1,2)",
+ "[[a,d],[b,e],[c,f]]",
+
+ "transpose([[a,d],[b,e],[c,f]],1,2)",
+ "[[a,b,c],[d,e,f]]",
+
+ # not how one-dimensional vectors
+ # don't have a transposition.
+ "transpose([a,b,c])",
+ "[a,b,c]",
+
+
+ "transpose(a)",
+ "transpose(a)",
+
+ "transpose(a,1,2)",
+ "transpose(a)",
+
+ "transpose(a,2,1)",
+ "transpose(a)",
+
+ "transpose(1+10)",
+ "11",
+
+ "transpose(1+10,2,3)",
+ "11",
+
+ "transpose(a*b)",
+ "transpose(a)*transpose(b)",
+
+ "transpose(a*b,3,4)",
+ "transpose(a,3,4)*transpose(b,3,4)",
+
+ "transpose(b*2*a)",
+ "2*transpose(a)*transpose(b)",
+
+ "transpose(b*2*a,3,4)",
+ "2*transpose(a,3,4)*transpose(b,3,4)",
+
+ "transpose(b+a)",
+ "transpose(a)+transpose(b)",
+
+ "transpose(b+a,3,4)",
+ "transpose(a,3,4)+transpose(b,3,4)",
+
+ "transpose(inner(a,b))",
+ "inner(transpose(b),transpose(a))",
+
+ "transpose(inner(a,b),3,4)",
+ "inner(transpose(b,3,4),transpose(a,3,4))",
+
+ "transpose(transpose(a))",
+ "a",
+
+ "transpose(transpose(transpose(a)))",
+ "transpose(a)",
+
+ "transpose(transpose(transpose(transpose(a))))",
+ "a",
+
+ "transpose(transpose(a),3,4)",
+ "transpose(transpose(a),3,4)",
+
+ "transpose(transpose(transpose(a),3,4))",
+ "transpose(transpose(transpose(a),3,4))",
+
+ "transpose(transpose(transpose(a),3,4))",
+ "transpose(transpose(transpose(a),3,4))",
+
+ "transpose(transpose(transpose(a),1,2))",
+ "transpose(a)",
+
+ "transpose(transpose(transpose(a),2,1))",
+ "transpose(a)",
+
+ "transpose(transpose(a,3,4),4,3)",
+ "a",
+
+ "transpose(transpose(a,3,4),5,6)",
+ "transpose(transpose(a,3,4),5,6)",
+
+ "transpose(a) - transpose(a)",
+ "0",
+
+ "transpose(a,1,2) - transpose(a,1,2)",
+ "0",
+
+ "transpose(a,3,4) - transpose(a,3,4)",
+ "0",
+
+ "aᵀ^b",
+ "transpose(a)^b",
+
+ "a^ᵀb",
+ "a^ᵀ ? b\nStop: syntax error",
+
+ "aᵀ^2^3",
+ "transpose(a)^8",
+
+ "aᵀ",
+ "transpose(a)",
+
+ "aᵀᵀ",
+ "a",
+
+ "aᵀᵀᵀ",
+ "transpose(a)",
+
+ "aᵀᵀᵀᵀ",
+ "a",
+
+ "aᵀ+b",
+ "b+transpose(a)",
+
+ "aᵀ*b",
+ "b*transpose(a)",
+
+ # this output could be written out more
+ # cleanly without extra parens
+ "aᵀ^bᵀ",
+ "transpose(a)^(transpose(b))",
+
+ "aᵀ*bᵀ",
+ "transpose(a)*transpose(b)",
+
+ "a^bᵀ",
+ "a^(transpose(b))",
+
+ "(a^b)ᵀ",
+ "transpose(a^b)",
+
+ "(a*b)ᵀ",
+ "transpose(a)*transpose(b)",
+
+ "inner(a,b)ᵀ",
+ "inner(transpose(b),transpose(a))",
+
+ "dot(a,b)ᵀ",
+ "inner(transpose(b),transpose(a))",
+
+ "(a·b·c)ᵀ",
+ "inner(transpose(c),inner(transpose(b),transpose(a)))",
+
+ "Iᵀᵀᵀ",
+ "I",
+
+ # Note that we are using the
+ # standard commutative multiplication here,
+ # not the dot product.
+ # So, one of the two arguments should
+ # be a scalar, but we don't know
+ # which one, so we have to transpose
+ # both. Note that we
+ # don't invert the order because
+ # we know it's a normal
+ # multiplication.
+ "transpose(A)*transpose(x)",
+ "transpose(A)*transpose(x)",
+
+ ]
diff --git a/node_modules/algebrite/tests/zero.coffee b/node_modules/algebrite/tests/zero.coffee
new file mode 100644
index 0000000..353240b
--- /dev/null
+++ b/node_modules/algebrite/tests/zero.coffee
@@ -0,0 +1,39 @@
+test_zero = ->
+ run_test [
+ "zero(2,2)",
+ "[[0,0],[0,0]]",
+
+ "zero(1,1)",
+ "[[0]]",
+
+ "zero(1)",
+ "[0]",
+
+ "zero(2)",
+ "[0,0]",
+
+ "zero(1,2)",
+ "[[0,0]]",
+
+ "zero(2,1)",
+ "[[0],[0]]",
+
+ "zero(0)",
+ "0",
+
+ "zero(0,0)",
+ "0",
+
+ # it's relevant to handle the case of tensor
+ # being passed because if you type
+ # 2
+ # zero
+ # > (0,0)
+ # zero # now the last result is passed to zero
+ # > 0 # (0,0) being passed, but it's handled!
+ # before some adjustments this used to crash.
+ # And it happened to me, so it can happen.
+ "zero([2,3])",
+ "0",
+
+ ]
diff --git a/node_modules/array-flatten/LICENSE b/node_modules/array-flatten/LICENSE
new file mode 100644
index 0000000..983fbe8
--- /dev/null
+++ b/node_modules/array-flatten/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/array-flatten/README.md b/node_modules/array-flatten/README.md
new file mode 100644
index 0000000..91fa5b6
--- /dev/null
+++ b/node_modules/array-flatten/README.md
@@ -0,0 +1,43 @@
+# Array Flatten
+
+[![NPM version][npm-image]][npm-url]
+[![NPM downloads][downloads-image]][downloads-url]
+[![Build status][travis-image]][travis-url]
+[![Test coverage][coveralls-image]][coveralls-url]
+
+> Flatten an array of nested arrays into a single flat array. Accepts an optional depth.
+
+## Installation
+
+```
+npm install array-flatten --save
+```
+
+## Usage
+
+```javascript
+var flatten = require('array-flatten')
+
+flatten([1, [2, [3, [4, [5], 6], 7], 8], 9])
+//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
+
+flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2)
+//=> [1, 2, 3, [4, [5], 6], 7, 8, 9]
+
+(function () {
+ flatten(arguments) //=> [1, 2, 3]
+})(1, [2, 3])
+```
+
+## License
+
+MIT
+
+[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat
+[npm-url]: https://npmjs.org/package/array-flatten
+[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat
+[downloads-url]: https://npmjs.org/package/array-flatten
+[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat
+[travis-url]: https://travis-ci.org/blakeembrey/array-flatten
+[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat
+[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master
diff --git a/node_modules/array-flatten/array-flatten.js b/node_modules/array-flatten/array-flatten.js
new file mode 100644
index 0000000..089117b
--- /dev/null
+++ b/node_modules/array-flatten/array-flatten.js
@@ -0,0 +1,64 @@
+'use strict'
+
+/**
+ * Expose `arrayFlatten`.
+ */
+module.exports = arrayFlatten
+
+/**
+ * Recursive flatten function with depth.
+ *
+ * @param {Array} array
+ * @param {Array} result
+ * @param {Number} depth
+ * @return {Array}
+ */
+function flattenWithDepth (array, result, depth) {
+ for (var i = 0; i < array.length; i++) {
+ var value = array[i]
+
+ if (depth > 0 && Array.isArray(value)) {
+ flattenWithDepth(value, result, depth - 1)
+ } else {
+ result.push(value)
+ }
+ }
+
+ return result
+}
+
+/**
+ * Recursive flatten function. Omitting depth is slightly faster.
+ *
+ * @param {Array} array
+ * @param {Array} result
+ * @return {Array}
+ */
+function flattenForever (array, result) {
+ for (var i = 0; i < array.length; i++) {
+ var value = array[i]
+
+ if (Array.isArray(value)) {
+ flattenForever(value, result)
+ } else {
+ result.push(value)
+ }
+ }
+
+ return result
+}
+
+/**
+ * Flatten an array, with the ability to define a depth.
+ *
+ * @param {Array} array
+ * @param {Number} depth
+ * @return {Array}
+ */
+function arrayFlatten (array, depth) {
+ if (depth == null) {
+ return flattenForever(array, [])
+ }
+
+ return flattenWithDepth(array, [], depth)
+}
diff --git a/node_modules/array-flatten/package.json b/node_modules/array-flatten/package.json
new file mode 100644
index 0000000..1a24e2a
--- /dev/null
+++ b/node_modules/array-flatten/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "array-flatten",
+ "version": "1.1.1",
+ "description": "Flatten an array of nested arrays into a single flat array",
+ "main": "array-flatten.js",
+ "files": [
+ "array-flatten.js",
+ "LICENSE"
+ ],
+ "scripts": {
+ "test": "istanbul cover _mocha -- -R spec"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/blakeembrey/array-flatten.git"
+ },
+ "keywords": [
+ "array",
+ "flatten",
+ "arguments",
+ "depth"
+ ],
+ "author": {
+ "name": "Blake Embrey",
+ "email": "hello@blakeembrey.com",
+ "url": "http://blakeembrey.me"
+ },
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/blakeembrey/array-flatten/issues"
+ },
+ "homepage": "https://github.com/blakeembrey/array-flatten",
+ "devDependencies": {
+ "istanbul": "^0.3.13",
+ "mocha": "^2.2.4",
+ "pre-commit": "^1.0.7",
+ "standard": "^3.7.3"
+ }
+}
diff --git a/node_modules/big-integer/BigInteger.d.ts b/node_modules/big-integer/BigInteger.d.ts
new file mode 100644
index 0000000..168ba5f
--- /dev/null
+++ b/node_modules/big-integer/BigInteger.d.ts
@@ -0,0 +1,2393 @@
+/**
+ * Type definitions for BigInteger.js
+ * Definitions by: Tommy Frazier
+ */
+export = bigInt;
+export as namespace bigInt;
+
+declare var bigInt: bigInt.BigIntegerStatic;
+
+declare namespace bigInt {
+ type BigNumber = number | bigint | string | BigInteger;
+
+ interface BigIntegerStatic {
+ /**
+ * Equivalent to bigInt(0).
+ */
+ (): BigInteger;
+
+ /**
+ * Parse a Javascript number into a bigInt.
+ */
+ (number: number): BigInteger;
+
+ /**
+ * Parse a Javascript native bigint into a bigInt.
+ */
+ (number: bigint): BigInteger;
+
+ /**
+ * Parse a string into a bigInt.
+ * Default base is 10.
+ * Default alphabet is "0123456789abcdefghijklmnopqrstuvwxyz".
+ * caseSensitive defaults to false.
+ */
+ (string: string, base?: BigNumber, alphabet?: string, caseSensitive?: boolean): BigInteger;
+
+ /**
+ * no-op.
+ */
+ (bigInt: BigInteger): BigInteger;
+
+ /**
+ * Constructs a bigInt from an array of digits in specified base.
+ * The optional isNegative flag will make the number negative.
+ */
+ fromArray: (digits: BigNumber[], base?: BigNumber, isNegative?: boolean) => BigInteger;
+
+ /**
+ * Finds the greatest common denominator of a and b.
+ */
+ gcd: (a: BigNumber, b: BigNumber) => BigInteger;
+
+
+ /**
+ * Returns true if x is a BigInteger, false otherwise.
+ */
+ isInstance: (x: any) => x is BigInteger;
+
+ /**
+ * Finds the least common multiple of a and b.
+ */
+ lcm: (a: BigNumber, b: BigNumber) => BigInteger;
+
+ /**
+ * Returns the largest of a and b.
+ */
+ max: (a: BigNumber, b: BigNumber) => BigInteger;
+
+ /**
+ * Returns the smallest of a and b.
+ */
+ min: (a: BigNumber, b: BigNumber) => BigInteger;
+
+ /**
+ * Equivalent to bigInt(-1).
+ */
+ minusOne: BigInteger;
+
+ /**
+ * Equivalent to bigInt(1).
+ */
+ one: BigInteger;
+
+ /**
+ * Returns a random number between min and max.
+ */
+ randBetween: (min: BigNumber, max: BigNumber, rng?: () => number) => BigInteger;
+
+ /**
+ * Equivalent to bigInt(0).
+ */
+ zero: BigInteger;
+ }
+
+ interface BigInteger {
+ /**
+ * Returns the absolute value of a bigInt.
+ */
+ abs(): BigInteger;
+
+ /**
+ * Performs addition.
+ */
+ add(number: BigNumber): BigInteger;
+
+ /**
+ * Performs the bitwise AND operation.
+ */
+ and(number: BigNumber): BigInteger;
+
+ /**
+ * Returns the number of digits required to represent a bigInt in binary.
+ */
+ bitLength(): BigInteger;
+
+ /**
+ * Performs a comparison between two numbers. If the numbers are equal, it returns 0.
+ * If the first number is greater, it returns 1. If the first number is lesser, it returns -1.
+ */
+ compare(number: BigNumber): number;
+
+ /**
+ * Performs a comparison between the absolute value of two numbers.
+ */
+ compareAbs(number: BigNumber): number;
+
+ /**
+ * Alias for the compare method.
+ */
+ compareTo(number: BigNumber): number;
+
+ /**
+ * Performs integer division, disregarding the remainder.
+ */
+ divide(number: BigNumber): BigInteger;
+
+ /**
+ * Performs division and returns an object with two properties: quotient and remainder.
+ * The sign of the remainder will match the sign of the dividend.
+ */
+ divmod(number: BigNumber): { quotient: BigInteger, remainder: BigInteger };
+
+ /**
+ * Alias for the equals method.
+ */
+ eq(number: BigNumber): boolean;
+
+ /**
+ * Checks if two numbers are equal.
+ */
+ equals(number: BigNumber): boolean;
+
+ /**
+ * Alias for the greaterOrEquals method.
+ */
+ geq(number: BigNumber): boolean;
+
+ /**
+ * Checks if the first number is greater than the second.
+ */
+ greater(number: BigNumber): boolean;
+
+ /**
+ * Checks if the first number is greater than or equal to the second.
+ */
+ greaterOrEquals(number: BigNumber): boolean;
+
+ /**
+ * Alias for the greater method.
+ */
+ gt(number: BigNumber): boolean;
+
+ /**
+ * Returns true if the first number is divisible by the second number, false otherwise.
+ */
+ isDivisibleBy(number: BigNumber): boolean;
+
+ /**
+ * Returns true if the number is even, false otherwise.
+ */
+ isEven(): boolean;
+
+ /**
+ * Returns true if the number is negative, false otherwise.
+ * Returns false for 0 and true for -0.
+ */
+ isNegative(): boolean;
+
+ /**
+ * Returns true if the number is odd, false otherwise.
+ */
+ isOdd(): boolean;
+
+ /**
+ * Return true if the number is positive, false otherwise.
+ * Returns true for 0 and false for -0.
+ */
+ isPositive(): boolean;
+
+ /**
+ * Returns true if the number is prime, false otherwise.
+ */
+ isPrime(strict?: boolean): boolean;
+
+ /**
+ * Returns true if the number is very likely to be prime, false otherwise.
+ */
+ isProbablePrime(iterations?: number, rng?: () => number): boolean;
+
+ /**
+ * Returns true if the number is 1 or -1, false otherwise.
+ */
+ isUnit(): boolean;
+
+ /**
+ * Return true if the number is 0 or -0, false otherwise.
+ */
+ isZero(): boolean;
+
+ /**
+ * Alias for the lesserOrEquals method.
+ */
+ leq(number: BigNumber): boolean;
+
+ /**
+ * Checks if the first number is lesser than the second.
+ */
+ lesser(number: BigNumber): boolean;
+
+ /**
+ * Checks if the first number is less than or equal to the second.
+ */
+ lesserOrEquals(number: BigNumber): boolean;
+
+ /**
+ * Alias for the lesser method.
+ */
+ lt(number: BigNumber): boolean;
+
+ /**
+ * Alias for the subtract method.
+ */
+ minus(number: BigNumber): BigInteger;
+
+ /**
+ * Performs division and returns the remainder, disregarding the quotient.
+ * The sign of the remainder will match the sign of the dividend.
+ */
+ mod(number: BigNumber): BigInteger;
+
+ /**
+ * Finds the multiplicative inverse of the number modulo mod.
+ */
+ modInv(number: BigNumber): BigInteger;
+
+ /**
+ * Takes the number to the power exp modulo mod.
+ */
+ modPow(exp: BigNumber, mod: BigNumber): BigInteger;
+
+ /**
+ * Performs multiplication.
+ */
+ multiply(number: BigNumber): BigInteger;
+
+ /**
+ * Reverses the sign of the number.
+ */
+ negate(): BigInteger;
+
+ /**
+ * Alias for the notEquals method.
+ */
+ neq(number: BigNumber): boolean;
+
+ /**
+ * Adds one to the number.
+ */
+ next(): BigInteger;
+
+ /**
+ * Performs the bitwise NOT operation.
+ */
+ not(): BigInteger;
+
+ /**
+ * Checks if two numbers are not equal.
+ */
+ notEquals(number: BigNumber): boolean;
+
+ /**
+ * Performs the bitwise OR operation.
+ */
+ or(number: BigNumber): BigInteger;
+
+ /**
+ * Alias for the divide method.
+ */
+ over(number: BigNumber): BigInteger;
+
+ /**
+ * Alias for the add method.
+ */
+ plus(number: BigNumber): BigInteger;
+
+ /**
+ * Performs exponentiation. If the exponent is less than 0, pow returns 0.
+ * bigInt.zero.pow(0) returns 1.
+ */
+ pow(number: BigNumber): BigInteger;
+
+ /**
+ * Subtracts one from the number.
+ */
+ prev(): BigInteger;
+
+ /**
+ * Alias for the mod method.
+ */
+ remainder(number: BigNumber): BigInteger;
+
+ /**
+ * Shifts the number left by n places in its binary representation.
+ * If a negative number is provided, it will shift right.
+ *
+ * Throws an error if number is outside of the range [-9007199254740992, 9007199254740992].
+ */
+ shiftLeft(number: BigNumber): BigInteger;
+
+ /**
+ * Shifts the number right by n places in its binary representation.
+ * If a negative number is provided, it will shift left.
+ *
+ * Throws an error if number is outside of the range [-9007199254740992, 9007199254740992].
+ */
+ shiftRight(number: BigNumber): BigInteger;
+
+ /**
+ * Squares the number.
+ */
+ square(): BigInteger;
+
+ /**
+ * Performs subtraction.
+ */
+ subtract(number: BigNumber): BigInteger;
+
+ /**
+ * Alias for the multiply method.
+ */
+ times(number: BigNumber): BigInteger;
+
+ /**
+ *
+ * Converts a bigInt to an object representing it as an array of integers module the given radix.
+ */
+ toArray(radix: number): BaseArray;
+
+ /**
+ * Converts a bigInt into a native Javascript number. Loses precision for numbers outside the range.
+ */
+ toJSNumber(): number;
+
+ /**
+ * Converts a bigInt to a string.
+ */
+ toString(radix?: number, alphabet?: string): string;
+
+ /**
+ * Converts a bigInt to a string. This method is called behind the scenes in JSON.stringify.
+ */
+ toJSON(): string;
+
+ /**
+ * Converts a bigInt to a native Javascript number. This override allows you to use native
+ * arithmetic operators without explicit conversion.
+ */
+ valueOf(): number;
+
+ /**
+ * Performs the bitwise XOR operation.
+ */
+ xor(number: BigNumber): BigInteger;
+ }
+
+ // Array constant accessors
+ interface BigIntegerStatic {
+ '-999': BigInteger;
+ '-998': BigInteger;
+ '-997': BigInteger;
+ '-996': BigInteger;
+ '-995': BigInteger;
+ '-994': BigInteger;
+ '-993': BigInteger;
+ '-992': BigInteger;
+ '-991': BigInteger;
+ '-990': BigInteger;
+ '-989': BigInteger;
+ '-988': BigInteger;
+ '-987': BigInteger;
+ '-986': BigInteger;
+ '-985': BigInteger;
+ '-984': BigInteger;
+ '-983': BigInteger;
+ '-982': BigInteger;
+ '-981': BigInteger;
+ '-980': BigInteger;
+ '-979': BigInteger;
+ '-978': BigInteger;
+ '-977': BigInteger;
+ '-976': BigInteger;
+ '-975': BigInteger;
+ '-974': BigInteger;
+ '-973': BigInteger;
+ '-972': BigInteger;
+ '-971': BigInteger;
+ '-970': BigInteger;
+ '-969': BigInteger;
+ '-968': BigInteger;
+ '-967': BigInteger;
+ '-966': BigInteger;
+ '-965': BigInteger;
+ '-964': BigInteger;
+ '-963': BigInteger;
+ '-962': BigInteger;
+ '-961': BigInteger;
+ '-960': BigInteger;
+ '-959': BigInteger;
+ '-958': BigInteger;
+ '-957': BigInteger;
+ '-956': BigInteger;
+ '-955': BigInteger;
+ '-954': BigInteger;
+ '-953': BigInteger;
+ '-952': BigInteger;
+ '-951': BigInteger;
+ '-950': BigInteger;
+ '-949': BigInteger;
+ '-948': BigInteger;
+ '-947': BigInteger;
+ '-946': BigInteger;
+ '-945': BigInteger;
+ '-944': BigInteger;
+ '-943': BigInteger;
+ '-942': BigInteger;
+ '-941': BigInteger;
+ '-940': BigInteger;
+ '-939': BigInteger;
+ '-938': BigInteger;
+ '-937': BigInteger;
+ '-936': BigInteger;
+ '-935': BigInteger;
+ '-934': BigInteger;
+ '-933': BigInteger;
+ '-932': BigInteger;
+ '-931': BigInteger;
+ '-930': BigInteger;
+ '-929': BigInteger;
+ '-928': BigInteger;
+ '-927': BigInteger;
+ '-926': BigInteger;
+ '-925': BigInteger;
+ '-924': BigInteger;
+ '-923': BigInteger;
+ '-922': BigInteger;
+ '-921': BigInteger;
+ '-920': BigInteger;
+ '-919': BigInteger;
+ '-918': BigInteger;
+ '-917': BigInteger;
+ '-916': BigInteger;
+ '-915': BigInteger;
+ '-914': BigInteger;
+ '-913': BigInteger;
+ '-912': BigInteger;
+ '-911': BigInteger;
+ '-910': BigInteger;
+ '-909': BigInteger;
+ '-908': BigInteger;
+ '-907': BigInteger;
+ '-906': BigInteger;
+ '-905': BigInteger;
+ '-904': BigInteger;
+ '-903': BigInteger;
+ '-902': BigInteger;
+ '-901': BigInteger;
+ '-900': BigInteger;
+ '-899': BigInteger;
+ '-898': BigInteger;
+ '-897': BigInteger;
+ '-896': BigInteger;
+ '-895': BigInteger;
+ '-894': BigInteger;
+ '-893': BigInteger;
+ '-892': BigInteger;
+ '-891': BigInteger;
+ '-890': BigInteger;
+ '-889': BigInteger;
+ '-888': BigInteger;
+ '-887': BigInteger;
+ '-886': BigInteger;
+ '-885': BigInteger;
+ '-884': BigInteger;
+ '-883': BigInteger;
+ '-882': BigInteger;
+ '-881': BigInteger;
+ '-880': BigInteger;
+ '-879': BigInteger;
+ '-878': BigInteger;
+ '-877': BigInteger;
+ '-876': BigInteger;
+ '-875': BigInteger;
+ '-874': BigInteger;
+ '-873': BigInteger;
+ '-872': BigInteger;
+ '-871': BigInteger;
+ '-870': BigInteger;
+ '-869': BigInteger;
+ '-868': BigInteger;
+ '-867': BigInteger;
+ '-866': BigInteger;
+ '-865': BigInteger;
+ '-864': BigInteger;
+ '-863': BigInteger;
+ '-862': BigInteger;
+ '-861': BigInteger;
+ '-860': BigInteger;
+ '-859': BigInteger;
+ '-858': BigInteger;
+ '-857': BigInteger;
+ '-856': BigInteger;
+ '-855': BigInteger;
+ '-854': BigInteger;
+ '-853': BigInteger;
+ '-852': BigInteger;
+ '-851': BigInteger;
+ '-850': BigInteger;
+ '-849': BigInteger;
+ '-848': BigInteger;
+ '-847': BigInteger;
+ '-846': BigInteger;
+ '-845': BigInteger;
+ '-844': BigInteger;
+ '-843': BigInteger;
+ '-842': BigInteger;
+ '-841': BigInteger;
+ '-840': BigInteger;
+ '-839': BigInteger;
+ '-838': BigInteger;
+ '-837': BigInteger;
+ '-836': BigInteger;
+ '-835': BigInteger;
+ '-834': BigInteger;
+ '-833': BigInteger;
+ '-832': BigInteger;
+ '-831': BigInteger;
+ '-830': BigInteger;
+ '-829': BigInteger;
+ '-828': BigInteger;
+ '-827': BigInteger;
+ '-826': BigInteger;
+ '-825': BigInteger;
+ '-824': BigInteger;
+ '-823': BigInteger;
+ '-822': BigInteger;
+ '-821': BigInteger;
+ '-820': BigInteger;
+ '-819': BigInteger;
+ '-818': BigInteger;
+ '-817': BigInteger;
+ '-816': BigInteger;
+ '-815': BigInteger;
+ '-814': BigInteger;
+ '-813': BigInteger;
+ '-812': BigInteger;
+ '-811': BigInteger;
+ '-810': BigInteger;
+ '-809': BigInteger;
+ '-808': BigInteger;
+ '-807': BigInteger;
+ '-806': BigInteger;
+ '-805': BigInteger;
+ '-804': BigInteger;
+ '-803': BigInteger;
+ '-802': BigInteger;
+ '-801': BigInteger;
+ '-800': BigInteger;
+ '-799': BigInteger;
+ '-798': BigInteger;
+ '-797': BigInteger;
+ '-796': BigInteger;
+ '-795': BigInteger;
+ '-794': BigInteger;
+ '-793': BigInteger;
+ '-792': BigInteger;
+ '-791': BigInteger;
+ '-790': BigInteger;
+ '-789': BigInteger;
+ '-788': BigInteger;
+ '-787': BigInteger;
+ '-786': BigInteger;
+ '-785': BigInteger;
+ '-784': BigInteger;
+ '-783': BigInteger;
+ '-782': BigInteger;
+ '-781': BigInteger;
+ '-780': BigInteger;
+ '-779': BigInteger;
+ '-778': BigInteger;
+ '-777': BigInteger;
+ '-776': BigInteger;
+ '-775': BigInteger;
+ '-774': BigInteger;
+ '-773': BigInteger;
+ '-772': BigInteger;
+ '-771': BigInteger;
+ '-770': BigInteger;
+ '-769': BigInteger;
+ '-768': BigInteger;
+ '-767': BigInteger;
+ '-766': BigInteger;
+ '-765': BigInteger;
+ '-764': BigInteger;
+ '-763': BigInteger;
+ '-762': BigInteger;
+ '-761': BigInteger;
+ '-760': BigInteger;
+ '-759': BigInteger;
+ '-758': BigInteger;
+ '-757': BigInteger;
+ '-756': BigInteger;
+ '-755': BigInteger;
+ '-754': BigInteger;
+ '-753': BigInteger;
+ '-752': BigInteger;
+ '-751': BigInteger;
+ '-750': BigInteger;
+ '-749': BigInteger;
+ '-748': BigInteger;
+ '-747': BigInteger;
+ '-746': BigInteger;
+ '-745': BigInteger;
+ '-744': BigInteger;
+ '-743': BigInteger;
+ '-742': BigInteger;
+ '-741': BigInteger;
+ '-740': BigInteger;
+ '-739': BigInteger;
+ '-738': BigInteger;
+ '-737': BigInteger;
+ '-736': BigInteger;
+ '-735': BigInteger;
+ '-734': BigInteger;
+ '-733': BigInteger;
+ '-732': BigInteger;
+ '-731': BigInteger;
+ '-730': BigInteger;
+ '-729': BigInteger;
+ '-728': BigInteger;
+ '-727': BigInteger;
+ '-726': BigInteger;
+ '-725': BigInteger;
+ '-724': BigInteger;
+ '-723': BigInteger;
+ '-722': BigInteger;
+ '-721': BigInteger;
+ '-720': BigInteger;
+ '-719': BigInteger;
+ '-718': BigInteger;
+ '-717': BigInteger;
+ '-716': BigInteger;
+ '-715': BigInteger;
+ '-714': BigInteger;
+ '-713': BigInteger;
+ '-712': BigInteger;
+ '-711': BigInteger;
+ '-710': BigInteger;
+ '-709': BigInteger;
+ '-708': BigInteger;
+ '-707': BigInteger;
+ '-706': BigInteger;
+ '-705': BigInteger;
+ '-704': BigInteger;
+ '-703': BigInteger;
+ '-702': BigInteger;
+ '-701': BigInteger;
+ '-700': BigInteger;
+ '-699': BigInteger;
+ '-698': BigInteger;
+ '-697': BigInteger;
+ '-696': BigInteger;
+ '-695': BigInteger;
+ '-694': BigInteger;
+ '-693': BigInteger;
+ '-692': BigInteger;
+ '-691': BigInteger;
+ '-690': BigInteger;
+ '-689': BigInteger;
+ '-688': BigInteger;
+ '-687': BigInteger;
+ '-686': BigInteger;
+ '-685': BigInteger;
+ '-684': BigInteger;
+ '-683': BigInteger;
+ '-682': BigInteger;
+ '-681': BigInteger;
+ '-680': BigInteger;
+ '-679': BigInteger;
+ '-678': BigInteger;
+ '-677': BigInteger;
+ '-676': BigInteger;
+ '-675': BigInteger;
+ '-674': BigInteger;
+ '-673': BigInteger;
+ '-672': BigInteger;
+ '-671': BigInteger;
+ '-670': BigInteger;
+ '-669': BigInteger;
+ '-668': BigInteger;
+ '-667': BigInteger;
+ '-666': BigInteger;
+ '-665': BigInteger;
+ '-664': BigInteger;
+ '-663': BigInteger;
+ '-662': BigInteger;
+ '-661': BigInteger;
+ '-660': BigInteger;
+ '-659': BigInteger;
+ '-658': BigInteger;
+ '-657': BigInteger;
+ '-656': BigInteger;
+ '-655': BigInteger;
+ '-654': BigInteger;
+ '-653': BigInteger;
+ '-652': BigInteger;
+ '-651': BigInteger;
+ '-650': BigInteger;
+ '-649': BigInteger;
+ '-648': BigInteger;
+ '-647': BigInteger;
+ '-646': BigInteger;
+ '-645': BigInteger;
+ '-644': BigInteger;
+ '-643': BigInteger;
+ '-642': BigInteger;
+ '-641': BigInteger;
+ '-640': BigInteger;
+ '-639': BigInteger;
+ '-638': BigInteger;
+ '-637': BigInteger;
+ '-636': BigInteger;
+ '-635': BigInteger;
+ '-634': BigInteger;
+ '-633': BigInteger;
+ '-632': BigInteger;
+ '-631': BigInteger;
+ '-630': BigInteger;
+ '-629': BigInteger;
+ '-628': BigInteger;
+ '-627': BigInteger;
+ '-626': BigInteger;
+ '-625': BigInteger;
+ '-624': BigInteger;
+ '-623': BigInteger;
+ '-622': BigInteger;
+ '-621': BigInteger;
+ '-620': BigInteger;
+ '-619': BigInteger;
+ '-618': BigInteger;
+ '-617': BigInteger;
+ '-616': BigInteger;
+ '-615': BigInteger;
+ '-614': BigInteger;
+ '-613': BigInteger;
+ '-612': BigInteger;
+ '-611': BigInteger;
+ '-610': BigInteger;
+ '-609': BigInteger;
+ '-608': BigInteger;
+ '-607': BigInteger;
+ '-606': BigInteger;
+ '-605': BigInteger;
+ '-604': BigInteger;
+ '-603': BigInteger;
+ '-602': BigInteger;
+ '-601': BigInteger;
+ '-600': BigInteger;
+ '-599': BigInteger;
+ '-598': BigInteger;
+ '-597': BigInteger;
+ '-596': BigInteger;
+ '-595': BigInteger;
+ '-594': BigInteger;
+ '-593': BigInteger;
+ '-592': BigInteger;
+ '-591': BigInteger;
+ '-590': BigInteger;
+ '-589': BigInteger;
+ '-588': BigInteger;
+ '-587': BigInteger;
+ '-586': BigInteger;
+ '-585': BigInteger;
+ '-584': BigInteger;
+ '-583': BigInteger;
+ '-582': BigInteger;
+ '-581': BigInteger;
+ '-580': BigInteger;
+ '-579': BigInteger;
+ '-578': BigInteger;
+ '-577': BigInteger;
+ '-576': BigInteger;
+ '-575': BigInteger;
+ '-574': BigInteger;
+ '-573': BigInteger;
+ '-572': BigInteger;
+ '-571': BigInteger;
+ '-570': BigInteger;
+ '-569': BigInteger;
+ '-568': BigInteger;
+ '-567': BigInteger;
+ '-566': BigInteger;
+ '-565': BigInteger;
+ '-564': BigInteger;
+ '-563': BigInteger;
+ '-562': BigInteger;
+ '-561': BigInteger;
+ '-560': BigInteger;
+ '-559': BigInteger;
+ '-558': BigInteger;
+ '-557': BigInteger;
+ '-556': BigInteger;
+ '-555': BigInteger;
+ '-554': BigInteger;
+ '-553': BigInteger;
+ '-552': BigInteger;
+ '-551': BigInteger;
+ '-550': BigInteger;
+ '-549': BigInteger;
+ '-548': BigInteger;
+ '-547': BigInteger;
+ '-546': BigInteger;
+ '-545': BigInteger;
+ '-544': BigInteger;
+ '-543': BigInteger;
+ '-542': BigInteger;
+ '-541': BigInteger;
+ '-540': BigInteger;
+ '-539': BigInteger;
+ '-538': BigInteger;
+ '-537': BigInteger;
+ '-536': BigInteger;
+ '-535': BigInteger;
+ '-534': BigInteger;
+ '-533': BigInteger;
+ '-532': BigInteger;
+ '-531': BigInteger;
+ '-530': BigInteger;
+ '-529': BigInteger;
+ '-528': BigInteger;
+ '-527': BigInteger;
+ '-526': BigInteger;
+ '-525': BigInteger;
+ '-524': BigInteger;
+ '-523': BigInteger;
+ '-522': BigInteger;
+ '-521': BigInteger;
+ '-520': BigInteger;
+ '-519': BigInteger;
+ '-518': BigInteger;
+ '-517': BigInteger;
+ '-516': BigInteger;
+ '-515': BigInteger;
+ '-514': BigInteger;
+ '-513': BigInteger;
+ '-512': BigInteger;
+ '-511': BigInteger;
+ '-510': BigInteger;
+ '-509': BigInteger;
+ '-508': BigInteger;
+ '-507': BigInteger;
+ '-506': BigInteger;
+ '-505': BigInteger;
+ '-504': BigInteger;
+ '-503': BigInteger;
+ '-502': BigInteger;
+ '-501': BigInteger;
+ '-500': BigInteger;
+ '-499': BigInteger;
+ '-498': BigInteger;
+ '-497': BigInteger;
+ '-496': BigInteger;
+ '-495': BigInteger;
+ '-494': BigInteger;
+ '-493': BigInteger;
+ '-492': BigInteger;
+ '-491': BigInteger;
+ '-490': BigInteger;
+ '-489': BigInteger;
+ '-488': BigInteger;
+ '-487': BigInteger;
+ '-486': BigInteger;
+ '-485': BigInteger;
+ '-484': BigInteger;
+ '-483': BigInteger;
+ '-482': BigInteger;
+ '-481': BigInteger;
+ '-480': BigInteger;
+ '-479': BigInteger;
+ '-478': BigInteger;
+ '-477': BigInteger;
+ '-476': BigInteger;
+ '-475': BigInteger;
+ '-474': BigInteger;
+ '-473': BigInteger;
+ '-472': BigInteger;
+ '-471': BigInteger;
+ '-470': BigInteger;
+ '-469': BigInteger;
+ '-468': BigInteger;
+ '-467': BigInteger;
+ '-466': BigInteger;
+ '-465': BigInteger;
+ '-464': BigInteger;
+ '-463': BigInteger;
+ '-462': BigInteger;
+ '-461': BigInteger;
+ '-460': BigInteger;
+ '-459': BigInteger;
+ '-458': BigInteger;
+ '-457': BigInteger;
+ '-456': BigInteger;
+ '-455': BigInteger;
+ '-454': BigInteger;
+ '-453': BigInteger;
+ '-452': BigInteger;
+ '-451': BigInteger;
+ '-450': BigInteger;
+ '-449': BigInteger;
+ '-448': BigInteger;
+ '-447': BigInteger;
+ '-446': BigInteger;
+ '-445': BigInteger;
+ '-444': BigInteger;
+ '-443': BigInteger;
+ '-442': BigInteger;
+ '-441': BigInteger;
+ '-440': BigInteger;
+ '-439': BigInteger;
+ '-438': BigInteger;
+ '-437': BigInteger;
+ '-436': BigInteger;
+ '-435': BigInteger;
+ '-434': BigInteger;
+ '-433': BigInteger;
+ '-432': BigInteger;
+ '-431': BigInteger;
+ '-430': BigInteger;
+ '-429': BigInteger;
+ '-428': BigInteger;
+ '-427': BigInteger;
+ '-426': BigInteger;
+ '-425': BigInteger;
+ '-424': BigInteger;
+ '-423': BigInteger;
+ '-422': BigInteger;
+ '-421': BigInteger;
+ '-420': BigInteger;
+ '-419': BigInteger;
+ '-418': BigInteger;
+ '-417': BigInteger;
+ '-416': BigInteger;
+ '-415': BigInteger;
+ '-414': BigInteger;
+ '-413': BigInteger;
+ '-412': BigInteger;
+ '-411': BigInteger;
+ '-410': BigInteger;
+ '-409': BigInteger;
+ '-408': BigInteger;
+ '-407': BigInteger;
+ '-406': BigInteger;
+ '-405': BigInteger;
+ '-404': BigInteger;
+ '-403': BigInteger;
+ '-402': BigInteger;
+ '-401': BigInteger;
+ '-400': BigInteger;
+ '-399': BigInteger;
+ '-398': BigInteger;
+ '-397': BigInteger;
+ '-396': BigInteger;
+ '-395': BigInteger;
+ '-394': BigInteger;
+ '-393': BigInteger;
+ '-392': BigInteger;
+ '-391': BigInteger;
+ '-390': BigInteger;
+ '-389': BigInteger;
+ '-388': BigInteger;
+ '-387': BigInteger;
+ '-386': BigInteger;
+ '-385': BigInteger;
+ '-384': BigInteger;
+ '-383': BigInteger;
+ '-382': BigInteger;
+ '-381': BigInteger;
+ '-380': BigInteger;
+ '-379': BigInteger;
+ '-378': BigInteger;
+ '-377': BigInteger;
+ '-376': BigInteger;
+ '-375': BigInteger;
+ '-374': BigInteger;
+ '-373': BigInteger;
+ '-372': BigInteger;
+ '-371': BigInteger;
+ '-370': BigInteger;
+ '-369': BigInteger;
+ '-368': BigInteger;
+ '-367': BigInteger;
+ '-366': BigInteger;
+ '-365': BigInteger;
+ '-364': BigInteger;
+ '-363': BigInteger;
+ '-362': BigInteger;
+ '-361': BigInteger;
+ '-360': BigInteger;
+ '-359': BigInteger;
+ '-358': BigInteger;
+ '-357': BigInteger;
+ '-356': BigInteger;
+ '-355': BigInteger;
+ '-354': BigInteger;
+ '-353': BigInteger;
+ '-352': BigInteger;
+ '-351': BigInteger;
+ '-350': BigInteger;
+ '-349': BigInteger;
+ '-348': BigInteger;
+ '-347': BigInteger;
+ '-346': BigInteger;
+ '-345': BigInteger;
+ '-344': BigInteger;
+ '-343': BigInteger;
+ '-342': BigInteger;
+ '-341': BigInteger;
+ '-340': BigInteger;
+ '-339': BigInteger;
+ '-338': BigInteger;
+ '-337': BigInteger;
+ '-336': BigInteger;
+ '-335': BigInteger;
+ '-334': BigInteger;
+ '-333': BigInteger;
+ '-332': BigInteger;
+ '-331': BigInteger;
+ '-330': BigInteger;
+ '-329': BigInteger;
+ '-328': BigInteger;
+ '-327': BigInteger;
+ '-326': BigInteger;
+ '-325': BigInteger;
+ '-324': BigInteger;
+ '-323': BigInteger;
+ '-322': BigInteger;
+ '-321': BigInteger;
+ '-320': BigInteger;
+ '-319': BigInteger;
+ '-318': BigInteger;
+ '-317': BigInteger;
+ '-316': BigInteger;
+ '-315': BigInteger;
+ '-314': BigInteger;
+ '-313': BigInteger;
+ '-312': BigInteger;
+ '-311': BigInteger;
+ '-310': BigInteger;
+ '-309': BigInteger;
+ '-308': BigInteger;
+ '-307': BigInteger;
+ '-306': BigInteger;
+ '-305': BigInteger;
+ '-304': BigInteger;
+ '-303': BigInteger;
+ '-302': BigInteger;
+ '-301': BigInteger;
+ '-300': BigInteger;
+ '-299': BigInteger;
+ '-298': BigInteger;
+ '-297': BigInteger;
+ '-296': BigInteger;
+ '-295': BigInteger;
+ '-294': BigInteger;
+ '-293': BigInteger;
+ '-292': BigInteger;
+ '-291': BigInteger;
+ '-290': BigInteger;
+ '-289': BigInteger;
+ '-288': BigInteger;
+ '-287': BigInteger;
+ '-286': BigInteger;
+ '-285': BigInteger;
+ '-284': BigInteger;
+ '-283': BigInteger;
+ '-282': BigInteger;
+ '-281': BigInteger;
+ '-280': BigInteger;
+ '-279': BigInteger;
+ '-278': BigInteger;
+ '-277': BigInteger;
+ '-276': BigInteger;
+ '-275': BigInteger;
+ '-274': BigInteger;
+ '-273': BigInteger;
+ '-272': BigInteger;
+ '-271': BigInteger;
+ '-270': BigInteger;
+ '-269': BigInteger;
+ '-268': BigInteger;
+ '-267': BigInteger;
+ '-266': BigInteger;
+ '-265': BigInteger;
+ '-264': BigInteger;
+ '-263': BigInteger;
+ '-262': BigInteger;
+ '-261': BigInteger;
+ '-260': BigInteger;
+ '-259': BigInteger;
+ '-258': BigInteger;
+ '-257': BigInteger;
+ '-256': BigInteger;
+ '-255': BigInteger;
+ '-254': BigInteger;
+ '-253': BigInteger;
+ '-252': BigInteger;
+ '-251': BigInteger;
+ '-250': BigInteger;
+ '-249': BigInteger;
+ '-248': BigInteger;
+ '-247': BigInteger;
+ '-246': BigInteger;
+ '-245': BigInteger;
+ '-244': BigInteger;
+ '-243': BigInteger;
+ '-242': BigInteger;
+ '-241': BigInteger;
+ '-240': BigInteger;
+ '-239': BigInteger;
+ '-238': BigInteger;
+ '-237': BigInteger;
+ '-236': BigInteger;
+ '-235': BigInteger;
+ '-234': BigInteger;
+ '-233': BigInteger;
+ '-232': BigInteger;
+ '-231': BigInteger;
+ '-230': BigInteger;
+ '-229': BigInteger;
+ '-228': BigInteger;
+ '-227': BigInteger;
+ '-226': BigInteger;
+ '-225': BigInteger;
+ '-224': BigInteger;
+ '-223': BigInteger;
+ '-222': BigInteger;
+ '-221': BigInteger;
+ '-220': BigInteger;
+ '-219': BigInteger;
+ '-218': BigInteger;
+ '-217': BigInteger;
+ '-216': BigInteger;
+ '-215': BigInteger;
+ '-214': BigInteger;
+ '-213': BigInteger;
+ '-212': BigInteger;
+ '-211': BigInteger;
+ '-210': BigInteger;
+ '-209': BigInteger;
+ '-208': BigInteger;
+ '-207': BigInteger;
+ '-206': BigInteger;
+ '-205': BigInteger;
+ '-204': BigInteger;
+ '-203': BigInteger;
+ '-202': BigInteger;
+ '-201': BigInteger;
+ '-200': BigInteger;
+ '-199': BigInteger;
+ '-198': BigInteger;
+ '-197': BigInteger;
+ '-196': BigInteger;
+ '-195': BigInteger;
+ '-194': BigInteger;
+ '-193': BigInteger;
+ '-192': BigInteger;
+ '-191': BigInteger;
+ '-190': BigInteger;
+ '-189': BigInteger;
+ '-188': BigInteger;
+ '-187': BigInteger;
+ '-186': BigInteger;
+ '-185': BigInteger;
+ '-184': BigInteger;
+ '-183': BigInteger;
+ '-182': BigInteger;
+ '-181': BigInteger;
+ '-180': BigInteger;
+ '-179': BigInteger;
+ '-178': BigInteger;
+ '-177': BigInteger;
+ '-176': BigInteger;
+ '-175': BigInteger;
+ '-174': BigInteger;
+ '-173': BigInteger;
+ '-172': BigInteger;
+ '-171': BigInteger;
+ '-170': BigInteger;
+ '-169': BigInteger;
+ '-168': BigInteger;
+ '-167': BigInteger;
+ '-166': BigInteger;
+ '-165': BigInteger;
+ '-164': BigInteger;
+ '-163': BigInteger;
+ '-162': BigInteger;
+ '-161': BigInteger;
+ '-160': BigInteger;
+ '-159': BigInteger;
+ '-158': BigInteger;
+ '-157': BigInteger;
+ '-156': BigInteger;
+ '-155': BigInteger;
+ '-154': BigInteger;
+ '-153': BigInteger;
+ '-152': BigInteger;
+ '-151': BigInteger;
+ '-150': BigInteger;
+ '-149': BigInteger;
+ '-148': BigInteger;
+ '-147': BigInteger;
+ '-146': BigInteger;
+ '-145': BigInteger;
+ '-144': BigInteger;
+ '-143': BigInteger;
+ '-142': BigInteger;
+ '-141': BigInteger;
+ '-140': BigInteger;
+ '-139': BigInteger;
+ '-138': BigInteger;
+ '-137': BigInteger;
+ '-136': BigInteger;
+ '-135': BigInteger;
+ '-134': BigInteger;
+ '-133': BigInteger;
+ '-132': BigInteger;
+ '-131': BigInteger;
+ '-130': BigInteger;
+ '-129': BigInteger;
+ '-128': BigInteger;
+ '-127': BigInteger;
+ '-126': BigInteger;
+ '-125': BigInteger;
+ '-124': BigInteger;
+ '-123': BigInteger;
+ '-122': BigInteger;
+ '-121': BigInteger;
+ '-120': BigInteger;
+ '-119': BigInteger;
+ '-118': BigInteger;
+ '-117': BigInteger;
+ '-116': BigInteger;
+ '-115': BigInteger;
+ '-114': BigInteger;
+ '-113': BigInteger;
+ '-112': BigInteger;
+ '-111': BigInteger;
+ '-110': BigInteger;
+ '-109': BigInteger;
+ '-108': BigInteger;
+ '-107': BigInteger;
+ '-106': BigInteger;
+ '-105': BigInteger;
+ '-104': BigInteger;
+ '-103': BigInteger;
+ '-102': BigInteger;
+ '-101': BigInteger;
+ '-100': BigInteger;
+ '-99': BigInteger;
+ '-98': BigInteger;
+ '-97': BigInteger;
+ '-96': BigInteger;
+ '-95': BigInteger;
+ '-94': BigInteger;
+ '-93': BigInteger;
+ '-92': BigInteger;
+ '-91': BigInteger;
+ '-90': BigInteger;
+ '-89': BigInteger;
+ '-88': BigInteger;
+ '-87': BigInteger;
+ '-86': BigInteger;
+ '-85': BigInteger;
+ '-84': BigInteger;
+ '-83': BigInteger;
+ '-82': BigInteger;
+ '-81': BigInteger;
+ '-80': BigInteger;
+ '-79': BigInteger;
+ '-78': BigInteger;
+ '-77': BigInteger;
+ '-76': BigInteger;
+ '-75': BigInteger;
+ '-74': BigInteger;
+ '-73': BigInteger;
+ '-72': BigInteger;
+ '-71': BigInteger;
+ '-70': BigInteger;
+ '-69': BigInteger;
+ '-68': BigInteger;
+ '-67': BigInteger;
+ '-66': BigInteger;
+ '-65': BigInteger;
+ '-64': BigInteger;
+ '-63': BigInteger;
+ '-62': BigInteger;
+ '-61': BigInteger;
+ '-60': BigInteger;
+ '-59': BigInteger;
+ '-58': BigInteger;
+ '-57': BigInteger;
+ '-56': BigInteger;
+ '-55': BigInteger;
+ '-54': BigInteger;
+ '-53': BigInteger;
+ '-52': BigInteger;
+ '-51': BigInteger;
+ '-50': BigInteger;
+ '-49': BigInteger;
+ '-48': BigInteger;
+ '-47': BigInteger;
+ '-46': BigInteger;
+ '-45': BigInteger;
+ '-44': BigInteger;
+ '-43': BigInteger;
+ '-42': BigInteger;
+ '-41': BigInteger;
+ '-40': BigInteger;
+ '-39': BigInteger;
+ '-38': BigInteger;
+ '-37': BigInteger;
+ '-36': BigInteger;
+ '-35': BigInteger;
+ '-34': BigInteger;
+ '-33': BigInteger;
+ '-32': BigInteger;
+ '-31': BigInteger;
+ '-30': BigInteger;
+ '-29': BigInteger;
+ '-28': BigInteger;
+ '-27': BigInteger;
+ '-26': BigInteger;
+ '-25': BigInteger;
+ '-24': BigInteger;
+ '-23': BigInteger;
+ '-22': BigInteger;
+ '-21': BigInteger;
+ '-20': BigInteger;
+ '-19': BigInteger;
+ '-18': BigInteger;
+ '-17': BigInteger;
+ '-16': BigInteger;
+ '-15': BigInteger;
+ '-14': BigInteger;
+ '-13': BigInteger;
+ '-12': BigInteger;
+ '-11': BigInteger;
+ '-10': BigInteger;
+ '-9': BigInteger;
+ '-8': BigInteger;
+ '-7': BigInteger;
+ '-6': BigInteger;
+ '-5': BigInteger;
+ '-4': BigInteger;
+ '-3': BigInteger;
+ '-2': BigInteger;
+ '-1': BigInteger;
+ '0': BigInteger;
+ '1': BigInteger;
+ '2': BigInteger;
+ '3': BigInteger;
+ '4': BigInteger;
+ '5': BigInteger;
+ '6': BigInteger;
+ '7': BigInteger;
+ '8': BigInteger;
+ '9': BigInteger;
+ '10': BigInteger;
+ '11': BigInteger;
+ '12': BigInteger;
+ '13': BigInteger;
+ '14': BigInteger;
+ '15': BigInteger;
+ '16': BigInteger;
+ '17': BigInteger;
+ '18': BigInteger;
+ '19': BigInteger;
+ '20': BigInteger;
+ '21': BigInteger;
+ '22': BigInteger;
+ '23': BigInteger;
+ '24': BigInteger;
+ '25': BigInteger;
+ '26': BigInteger;
+ '27': BigInteger;
+ '28': BigInteger;
+ '29': BigInteger;
+ '30': BigInteger;
+ '31': BigInteger;
+ '32': BigInteger;
+ '33': BigInteger;
+ '34': BigInteger;
+ '35': BigInteger;
+ '36': BigInteger;
+ '37': BigInteger;
+ '38': BigInteger;
+ '39': BigInteger;
+ '40': BigInteger;
+ '41': BigInteger;
+ '42': BigInteger;
+ '43': BigInteger;
+ '44': BigInteger;
+ '45': BigInteger;
+ '46': BigInteger;
+ '47': BigInteger;
+ '48': BigInteger;
+ '49': BigInteger;
+ '50': BigInteger;
+ '51': BigInteger;
+ '52': BigInteger;
+ '53': BigInteger;
+ '54': BigInteger;
+ '55': BigInteger;
+ '56': BigInteger;
+ '57': BigInteger;
+ '58': BigInteger;
+ '59': BigInteger;
+ '60': BigInteger;
+ '61': BigInteger;
+ '62': BigInteger;
+ '63': BigInteger;
+ '64': BigInteger;
+ '65': BigInteger;
+ '66': BigInteger;
+ '67': BigInteger;
+ '68': BigInteger;
+ '69': BigInteger;
+ '70': BigInteger;
+ '71': BigInteger;
+ '72': BigInteger;
+ '73': BigInteger;
+ '74': BigInteger;
+ '75': BigInteger;
+ '76': BigInteger;
+ '77': BigInteger;
+ '78': BigInteger;
+ '79': BigInteger;
+ '80': BigInteger;
+ '81': BigInteger;
+ '82': BigInteger;
+ '83': BigInteger;
+ '84': BigInteger;
+ '85': BigInteger;
+ '86': BigInteger;
+ '87': BigInteger;
+ '88': BigInteger;
+ '89': BigInteger;
+ '90': BigInteger;
+ '91': BigInteger;
+ '92': BigInteger;
+ '93': BigInteger;
+ '94': BigInteger;
+ '95': BigInteger;
+ '96': BigInteger;
+ '97': BigInteger;
+ '98': BigInteger;
+ '99': BigInteger;
+ '100': BigInteger;
+ '101': BigInteger;
+ '102': BigInteger;
+ '103': BigInteger;
+ '104': BigInteger;
+ '105': BigInteger;
+ '106': BigInteger;
+ '107': BigInteger;
+ '108': BigInteger;
+ '109': BigInteger;
+ '110': BigInteger;
+ '111': BigInteger;
+ '112': BigInteger;
+ '113': BigInteger;
+ '114': BigInteger;
+ '115': BigInteger;
+ '116': BigInteger;
+ '117': BigInteger;
+ '118': BigInteger;
+ '119': BigInteger;
+ '120': BigInteger;
+ '121': BigInteger;
+ '122': BigInteger;
+ '123': BigInteger;
+ '124': BigInteger;
+ '125': BigInteger;
+ '126': BigInteger;
+ '127': BigInteger;
+ '128': BigInteger;
+ '129': BigInteger;
+ '130': BigInteger;
+ '131': BigInteger;
+ '132': BigInteger;
+ '133': BigInteger;
+ '134': BigInteger;
+ '135': BigInteger;
+ '136': BigInteger;
+ '137': BigInteger;
+ '138': BigInteger;
+ '139': BigInteger;
+ '140': BigInteger;
+ '141': BigInteger;
+ '142': BigInteger;
+ '143': BigInteger;
+ '144': BigInteger;
+ '145': BigInteger;
+ '146': BigInteger;
+ '147': BigInteger;
+ '148': BigInteger;
+ '149': BigInteger;
+ '150': BigInteger;
+ '151': BigInteger;
+ '152': BigInteger;
+ '153': BigInteger;
+ '154': BigInteger;
+ '155': BigInteger;
+ '156': BigInteger;
+ '157': BigInteger;
+ '158': BigInteger;
+ '159': BigInteger;
+ '160': BigInteger;
+ '161': BigInteger;
+ '162': BigInteger;
+ '163': BigInteger;
+ '164': BigInteger;
+ '165': BigInteger;
+ '166': BigInteger;
+ '167': BigInteger;
+ '168': BigInteger;
+ '169': BigInteger;
+ '170': BigInteger;
+ '171': BigInteger;
+ '172': BigInteger;
+ '173': BigInteger;
+ '174': BigInteger;
+ '175': BigInteger;
+ '176': BigInteger;
+ '177': BigInteger;
+ '178': BigInteger;
+ '179': BigInteger;
+ '180': BigInteger;
+ '181': BigInteger;
+ '182': BigInteger;
+ '183': BigInteger;
+ '184': BigInteger;
+ '185': BigInteger;
+ '186': BigInteger;
+ '187': BigInteger;
+ '188': BigInteger;
+ '189': BigInteger;
+ '190': BigInteger;
+ '191': BigInteger;
+ '192': BigInteger;
+ '193': BigInteger;
+ '194': BigInteger;
+ '195': BigInteger;
+ '196': BigInteger;
+ '197': BigInteger;
+ '198': BigInteger;
+ '199': BigInteger;
+ '200': BigInteger;
+ '201': BigInteger;
+ '202': BigInteger;
+ '203': BigInteger;
+ '204': BigInteger;
+ '205': BigInteger;
+ '206': BigInteger;
+ '207': BigInteger;
+ '208': BigInteger;
+ '209': BigInteger;
+ '210': BigInteger;
+ '211': BigInteger;
+ '212': BigInteger;
+ '213': BigInteger;
+ '214': BigInteger;
+ '215': BigInteger;
+ '216': BigInteger;
+ '217': BigInteger;
+ '218': BigInteger;
+ '219': BigInteger;
+ '220': BigInteger;
+ '221': BigInteger;
+ '222': BigInteger;
+ '223': BigInteger;
+ '224': BigInteger;
+ '225': BigInteger;
+ '226': BigInteger;
+ '227': BigInteger;
+ '228': BigInteger;
+ '229': BigInteger;
+ '230': BigInteger;
+ '231': BigInteger;
+ '232': BigInteger;
+ '233': BigInteger;
+ '234': BigInteger;
+ '235': BigInteger;
+ '236': BigInteger;
+ '237': BigInteger;
+ '238': BigInteger;
+ '239': BigInteger;
+ '240': BigInteger;
+ '241': BigInteger;
+ '242': BigInteger;
+ '243': BigInteger;
+ '244': BigInteger;
+ '245': BigInteger;
+ '246': BigInteger;
+ '247': BigInteger;
+ '248': BigInteger;
+ '249': BigInteger;
+ '250': BigInteger;
+ '251': BigInteger;
+ '252': BigInteger;
+ '253': BigInteger;
+ '254': BigInteger;
+ '255': BigInteger;
+ '256': BigInteger;
+ '257': BigInteger;
+ '258': BigInteger;
+ '259': BigInteger;
+ '260': BigInteger;
+ '261': BigInteger;
+ '262': BigInteger;
+ '263': BigInteger;
+ '264': BigInteger;
+ '265': BigInteger;
+ '266': BigInteger;
+ '267': BigInteger;
+ '268': BigInteger;
+ '269': BigInteger;
+ '270': BigInteger;
+ '271': BigInteger;
+ '272': BigInteger;
+ '273': BigInteger;
+ '274': BigInteger;
+ '275': BigInteger;
+ '276': BigInteger;
+ '277': BigInteger;
+ '278': BigInteger;
+ '279': BigInteger;
+ '280': BigInteger;
+ '281': BigInteger;
+ '282': BigInteger;
+ '283': BigInteger;
+ '284': BigInteger;
+ '285': BigInteger;
+ '286': BigInteger;
+ '287': BigInteger;
+ '288': BigInteger;
+ '289': BigInteger;
+ '290': BigInteger;
+ '291': BigInteger;
+ '292': BigInteger;
+ '293': BigInteger;
+ '294': BigInteger;
+ '295': BigInteger;
+ '296': BigInteger;
+ '297': BigInteger;
+ '298': BigInteger;
+ '299': BigInteger;
+ '300': BigInteger;
+ '301': BigInteger;
+ '302': BigInteger;
+ '303': BigInteger;
+ '304': BigInteger;
+ '305': BigInteger;
+ '306': BigInteger;
+ '307': BigInteger;
+ '308': BigInteger;
+ '309': BigInteger;
+ '310': BigInteger;
+ '311': BigInteger;
+ '312': BigInteger;
+ '313': BigInteger;
+ '314': BigInteger;
+ '315': BigInteger;
+ '316': BigInteger;
+ '317': BigInteger;
+ '318': BigInteger;
+ '319': BigInteger;
+ '320': BigInteger;
+ '321': BigInteger;
+ '322': BigInteger;
+ '323': BigInteger;
+ '324': BigInteger;
+ '325': BigInteger;
+ '326': BigInteger;
+ '327': BigInteger;
+ '328': BigInteger;
+ '329': BigInteger;
+ '330': BigInteger;
+ '331': BigInteger;
+ '332': BigInteger;
+ '333': BigInteger;
+ '334': BigInteger;
+ '335': BigInteger;
+ '336': BigInteger;
+ '337': BigInteger;
+ '338': BigInteger;
+ '339': BigInteger;
+ '340': BigInteger;
+ '341': BigInteger;
+ '342': BigInteger;
+ '343': BigInteger;
+ '344': BigInteger;
+ '345': BigInteger;
+ '346': BigInteger;
+ '347': BigInteger;
+ '348': BigInteger;
+ '349': BigInteger;
+ '350': BigInteger;
+ '351': BigInteger;
+ '352': BigInteger;
+ '353': BigInteger;
+ '354': BigInteger;
+ '355': BigInteger;
+ '356': BigInteger;
+ '357': BigInteger;
+ '358': BigInteger;
+ '359': BigInteger;
+ '360': BigInteger;
+ '361': BigInteger;
+ '362': BigInteger;
+ '363': BigInteger;
+ '364': BigInteger;
+ '365': BigInteger;
+ '366': BigInteger;
+ '367': BigInteger;
+ '368': BigInteger;
+ '369': BigInteger;
+ '370': BigInteger;
+ '371': BigInteger;
+ '372': BigInteger;
+ '373': BigInteger;
+ '374': BigInteger;
+ '375': BigInteger;
+ '376': BigInteger;
+ '377': BigInteger;
+ '378': BigInteger;
+ '379': BigInteger;
+ '380': BigInteger;
+ '381': BigInteger;
+ '382': BigInteger;
+ '383': BigInteger;
+ '384': BigInteger;
+ '385': BigInteger;
+ '386': BigInteger;
+ '387': BigInteger;
+ '388': BigInteger;
+ '389': BigInteger;
+ '390': BigInteger;
+ '391': BigInteger;
+ '392': BigInteger;
+ '393': BigInteger;
+ '394': BigInteger;
+ '395': BigInteger;
+ '396': BigInteger;
+ '397': BigInteger;
+ '398': BigInteger;
+ '399': BigInteger;
+ '400': BigInteger;
+ '401': BigInteger;
+ '402': BigInteger;
+ '403': BigInteger;
+ '404': BigInteger;
+ '405': BigInteger;
+ '406': BigInteger;
+ '407': BigInteger;
+ '408': BigInteger;
+ '409': BigInteger;
+ '410': BigInteger;
+ '411': BigInteger;
+ '412': BigInteger;
+ '413': BigInteger;
+ '414': BigInteger;
+ '415': BigInteger;
+ '416': BigInteger;
+ '417': BigInteger;
+ '418': BigInteger;
+ '419': BigInteger;
+ '420': BigInteger;
+ '421': BigInteger;
+ '422': BigInteger;
+ '423': BigInteger;
+ '424': BigInteger;
+ '425': BigInteger;
+ '426': BigInteger;
+ '427': BigInteger;
+ '428': BigInteger;
+ '429': BigInteger;
+ '430': BigInteger;
+ '431': BigInteger;
+ '432': BigInteger;
+ '433': BigInteger;
+ '434': BigInteger;
+ '435': BigInteger;
+ '436': BigInteger;
+ '437': BigInteger;
+ '438': BigInteger;
+ '439': BigInteger;
+ '440': BigInteger;
+ '441': BigInteger;
+ '442': BigInteger;
+ '443': BigInteger;
+ '444': BigInteger;
+ '445': BigInteger;
+ '446': BigInteger;
+ '447': BigInteger;
+ '448': BigInteger;
+ '449': BigInteger;
+ '450': BigInteger;
+ '451': BigInteger;
+ '452': BigInteger;
+ '453': BigInteger;
+ '454': BigInteger;
+ '455': BigInteger;
+ '456': BigInteger;
+ '457': BigInteger;
+ '458': BigInteger;
+ '459': BigInteger;
+ '460': BigInteger;
+ '461': BigInteger;
+ '462': BigInteger;
+ '463': BigInteger;
+ '464': BigInteger;
+ '465': BigInteger;
+ '466': BigInteger;
+ '467': BigInteger;
+ '468': BigInteger;
+ '469': BigInteger;
+ '470': BigInteger;
+ '471': BigInteger;
+ '472': BigInteger;
+ '473': BigInteger;
+ '474': BigInteger;
+ '475': BigInteger;
+ '476': BigInteger;
+ '477': BigInteger;
+ '478': BigInteger;
+ '479': BigInteger;
+ '480': BigInteger;
+ '481': BigInteger;
+ '482': BigInteger;
+ '483': BigInteger;
+ '484': BigInteger;
+ '485': BigInteger;
+ '486': BigInteger;
+ '487': BigInteger;
+ '488': BigInteger;
+ '489': BigInteger;
+ '490': BigInteger;
+ '491': BigInteger;
+ '492': BigInteger;
+ '493': BigInteger;
+ '494': BigInteger;
+ '495': BigInteger;
+ '496': BigInteger;
+ '497': BigInteger;
+ '498': BigInteger;
+ '499': BigInteger;
+ '500': BigInteger;
+ '501': BigInteger;
+ '502': BigInteger;
+ '503': BigInteger;
+ '504': BigInteger;
+ '505': BigInteger;
+ '506': BigInteger;
+ '507': BigInteger;
+ '508': BigInteger;
+ '509': BigInteger;
+ '510': BigInteger;
+ '511': BigInteger;
+ '512': BigInteger;
+ '513': BigInteger;
+ '514': BigInteger;
+ '515': BigInteger;
+ '516': BigInteger;
+ '517': BigInteger;
+ '518': BigInteger;
+ '519': BigInteger;
+ '520': BigInteger;
+ '521': BigInteger;
+ '522': BigInteger;
+ '523': BigInteger;
+ '524': BigInteger;
+ '525': BigInteger;
+ '526': BigInteger;
+ '527': BigInteger;
+ '528': BigInteger;
+ '529': BigInteger;
+ '530': BigInteger;
+ '531': BigInteger;
+ '532': BigInteger;
+ '533': BigInteger;
+ '534': BigInteger;
+ '535': BigInteger;
+ '536': BigInteger;
+ '537': BigInteger;
+ '538': BigInteger;
+ '539': BigInteger;
+ '540': BigInteger;
+ '541': BigInteger;
+ '542': BigInteger;
+ '543': BigInteger;
+ '544': BigInteger;
+ '545': BigInteger;
+ '546': BigInteger;
+ '547': BigInteger;
+ '548': BigInteger;
+ '549': BigInteger;
+ '550': BigInteger;
+ '551': BigInteger;
+ '552': BigInteger;
+ '553': BigInteger;
+ '554': BigInteger;
+ '555': BigInteger;
+ '556': BigInteger;
+ '557': BigInteger;
+ '558': BigInteger;
+ '559': BigInteger;
+ '560': BigInteger;
+ '561': BigInteger;
+ '562': BigInteger;
+ '563': BigInteger;
+ '564': BigInteger;
+ '565': BigInteger;
+ '566': BigInteger;
+ '567': BigInteger;
+ '568': BigInteger;
+ '569': BigInteger;
+ '570': BigInteger;
+ '571': BigInteger;
+ '572': BigInteger;
+ '573': BigInteger;
+ '574': BigInteger;
+ '575': BigInteger;
+ '576': BigInteger;
+ '577': BigInteger;
+ '578': BigInteger;
+ '579': BigInteger;
+ '580': BigInteger;
+ '581': BigInteger;
+ '582': BigInteger;
+ '583': BigInteger;
+ '584': BigInteger;
+ '585': BigInteger;
+ '586': BigInteger;
+ '587': BigInteger;
+ '588': BigInteger;
+ '589': BigInteger;
+ '590': BigInteger;
+ '591': BigInteger;
+ '592': BigInteger;
+ '593': BigInteger;
+ '594': BigInteger;
+ '595': BigInteger;
+ '596': BigInteger;
+ '597': BigInteger;
+ '598': BigInteger;
+ '599': BigInteger;
+ '600': BigInteger;
+ '601': BigInteger;
+ '602': BigInteger;
+ '603': BigInteger;
+ '604': BigInteger;
+ '605': BigInteger;
+ '606': BigInteger;
+ '607': BigInteger;
+ '608': BigInteger;
+ '609': BigInteger;
+ '610': BigInteger;
+ '611': BigInteger;
+ '612': BigInteger;
+ '613': BigInteger;
+ '614': BigInteger;
+ '615': BigInteger;
+ '616': BigInteger;
+ '617': BigInteger;
+ '618': BigInteger;
+ '619': BigInteger;
+ '620': BigInteger;
+ '621': BigInteger;
+ '622': BigInteger;
+ '623': BigInteger;
+ '624': BigInteger;
+ '625': BigInteger;
+ '626': BigInteger;
+ '627': BigInteger;
+ '628': BigInteger;
+ '629': BigInteger;
+ '630': BigInteger;
+ '631': BigInteger;
+ '632': BigInteger;
+ '633': BigInteger;
+ '634': BigInteger;
+ '635': BigInteger;
+ '636': BigInteger;
+ '637': BigInteger;
+ '638': BigInteger;
+ '639': BigInteger;
+ '640': BigInteger;
+ '641': BigInteger;
+ '642': BigInteger;
+ '643': BigInteger;
+ '644': BigInteger;
+ '645': BigInteger;
+ '646': BigInteger;
+ '647': BigInteger;
+ '648': BigInteger;
+ '649': BigInteger;
+ '650': BigInteger;
+ '651': BigInteger;
+ '652': BigInteger;
+ '653': BigInteger;
+ '654': BigInteger;
+ '655': BigInteger;
+ '656': BigInteger;
+ '657': BigInteger;
+ '658': BigInteger;
+ '659': BigInteger;
+ '660': BigInteger;
+ '661': BigInteger;
+ '662': BigInteger;
+ '663': BigInteger;
+ '664': BigInteger;
+ '665': BigInteger;
+ '666': BigInteger;
+ '667': BigInteger;
+ '668': BigInteger;
+ '669': BigInteger;
+ '670': BigInteger;
+ '671': BigInteger;
+ '672': BigInteger;
+ '673': BigInteger;
+ '674': BigInteger;
+ '675': BigInteger;
+ '676': BigInteger;
+ '677': BigInteger;
+ '678': BigInteger;
+ '679': BigInteger;
+ '680': BigInteger;
+ '681': BigInteger;
+ '682': BigInteger;
+ '683': BigInteger;
+ '684': BigInteger;
+ '685': BigInteger;
+ '686': BigInteger;
+ '687': BigInteger;
+ '688': BigInteger;
+ '689': BigInteger;
+ '690': BigInteger;
+ '691': BigInteger;
+ '692': BigInteger;
+ '693': BigInteger;
+ '694': BigInteger;
+ '695': BigInteger;
+ '696': BigInteger;
+ '697': BigInteger;
+ '698': BigInteger;
+ '699': BigInteger;
+ '700': BigInteger;
+ '701': BigInteger;
+ '702': BigInteger;
+ '703': BigInteger;
+ '704': BigInteger;
+ '705': BigInteger;
+ '706': BigInteger;
+ '707': BigInteger;
+ '708': BigInteger;
+ '709': BigInteger;
+ '710': BigInteger;
+ '711': BigInteger;
+ '712': BigInteger;
+ '713': BigInteger;
+ '714': BigInteger;
+ '715': BigInteger;
+ '716': BigInteger;
+ '717': BigInteger;
+ '718': BigInteger;
+ '719': BigInteger;
+ '720': BigInteger;
+ '721': BigInteger;
+ '722': BigInteger;
+ '723': BigInteger;
+ '724': BigInteger;
+ '725': BigInteger;
+ '726': BigInteger;
+ '727': BigInteger;
+ '728': BigInteger;
+ '729': BigInteger;
+ '730': BigInteger;
+ '731': BigInteger;
+ '732': BigInteger;
+ '733': BigInteger;
+ '734': BigInteger;
+ '735': BigInteger;
+ '736': BigInteger;
+ '737': BigInteger;
+ '738': BigInteger;
+ '739': BigInteger;
+ '740': BigInteger;
+ '741': BigInteger;
+ '742': BigInteger;
+ '743': BigInteger;
+ '744': BigInteger;
+ '745': BigInteger;
+ '746': BigInteger;
+ '747': BigInteger;
+ '748': BigInteger;
+ '749': BigInteger;
+ '750': BigInteger;
+ '751': BigInteger;
+ '752': BigInteger;
+ '753': BigInteger;
+ '754': BigInteger;
+ '755': BigInteger;
+ '756': BigInteger;
+ '757': BigInteger;
+ '758': BigInteger;
+ '759': BigInteger;
+ '760': BigInteger;
+ '761': BigInteger;
+ '762': BigInteger;
+ '763': BigInteger;
+ '764': BigInteger;
+ '765': BigInteger;
+ '766': BigInteger;
+ '767': BigInteger;
+ '768': BigInteger;
+ '769': BigInteger;
+ '770': BigInteger;
+ '771': BigInteger;
+ '772': BigInteger;
+ '773': BigInteger;
+ '774': BigInteger;
+ '775': BigInteger;
+ '776': BigInteger;
+ '777': BigInteger;
+ '778': BigInteger;
+ '779': BigInteger;
+ '780': BigInteger;
+ '781': BigInteger;
+ '782': BigInteger;
+ '783': BigInteger;
+ '784': BigInteger;
+ '785': BigInteger;
+ '786': BigInteger;
+ '787': BigInteger;
+ '788': BigInteger;
+ '789': BigInteger;
+ '790': BigInteger;
+ '791': BigInteger;
+ '792': BigInteger;
+ '793': BigInteger;
+ '794': BigInteger;
+ '795': BigInteger;
+ '796': BigInteger;
+ '797': BigInteger;
+ '798': BigInteger;
+ '799': BigInteger;
+ '800': BigInteger;
+ '801': BigInteger;
+ '802': BigInteger;
+ '803': BigInteger;
+ '804': BigInteger;
+ '805': BigInteger;
+ '806': BigInteger;
+ '807': BigInteger;
+ '808': BigInteger;
+ '809': BigInteger;
+ '810': BigInteger;
+ '811': BigInteger;
+ '812': BigInteger;
+ '813': BigInteger;
+ '814': BigInteger;
+ '815': BigInteger;
+ '816': BigInteger;
+ '817': BigInteger;
+ '818': BigInteger;
+ '819': BigInteger;
+ '820': BigInteger;
+ '821': BigInteger;
+ '822': BigInteger;
+ '823': BigInteger;
+ '824': BigInteger;
+ '825': BigInteger;
+ '826': BigInteger;
+ '827': BigInteger;
+ '828': BigInteger;
+ '829': BigInteger;
+ '830': BigInteger;
+ '831': BigInteger;
+ '832': BigInteger;
+ '833': BigInteger;
+ '834': BigInteger;
+ '835': BigInteger;
+ '836': BigInteger;
+ '837': BigInteger;
+ '838': BigInteger;
+ '839': BigInteger;
+ '840': BigInteger;
+ '841': BigInteger;
+ '842': BigInteger;
+ '843': BigInteger;
+ '844': BigInteger;
+ '845': BigInteger;
+ '846': BigInteger;
+ '847': BigInteger;
+ '848': BigInteger;
+ '849': BigInteger;
+ '850': BigInteger;
+ '851': BigInteger;
+ '852': BigInteger;
+ '853': BigInteger;
+ '854': BigInteger;
+ '855': BigInteger;
+ '856': BigInteger;
+ '857': BigInteger;
+ '858': BigInteger;
+ '859': BigInteger;
+ '860': BigInteger;
+ '861': BigInteger;
+ '862': BigInteger;
+ '863': BigInteger;
+ '864': BigInteger;
+ '865': BigInteger;
+ '866': BigInteger;
+ '867': BigInteger;
+ '868': BigInteger;
+ '869': BigInteger;
+ '870': BigInteger;
+ '871': BigInteger;
+ '872': BigInteger;
+ '873': BigInteger;
+ '874': BigInteger;
+ '875': BigInteger;
+ '876': BigInteger;
+ '877': BigInteger;
+ '878': BigInteger;
+ '879': BigInteger;
+ '880': BigInteger;
+ '881': BigInteger;
+ '882': BigInteger;
+ '883': BigInteger;
+ '884': BigInteger;
+ '885': BigInteger;
+ '886': BigInteger;
+ '887': BigInteger;
+ '888': BigInteger;
+ '889': BigInteger;
+ '890': BigInteger;
+ '891': BigInteger;
+ '892': BigInteger;
+ '893': BigInteger;
+ '894': BigInteger;
+ '895': BigInteger;
+ '896': BigInteger;
+ '897': BigInteger;
+ '898': BigInteger;
+ '899': BigInteger;
+ '900': BigInteger;
+ '901': BigInteger;
+ '902': BigInteger;
+ '903': BigInteger;
+ '904': BigInteger;
+ '905': BigInteger;
+ '906': BigInteger;
+ '907': BigInteger;
+ '908': BigInteger;
+ '909': BigInteger;
+ '910': BigInteger;
+ '911': BigInteger;
+ '912': BigInteger;
+ '913': BigInteger;
+ '914': BigInteger;
+ '915': BigInteger;
+ '916': BigInteger;
+ '917': BigInteger;
+ '918': BigInteger;
+ '919': BigInteger;
+ '920': BigInteger;
+ '921': BigInteger;
+ '922': BigInteger;
+ '923': BigInteger;
+ '924': BigInteger;
+ '925': BigInteger;
+ '926': BigInteger;
+ '927': BigInteger;
+ '928': BigInteger;
+ '929': BigInteger;
+ '930': BigInteger;
+ '931': BigInteger;
+ '932': BigInteger;
+ '933': BigInteger;
+ '934': BigInteger;
+ '935': BigInteger;
+ '936': BigInteger;
+ '937': BigInteger;
+ '938': BigInteger;
+ '939': BigInteger;
+ '940': BigInteger;
+ '941': BigInteger;
+ '942': BigInteger;
+ '943': BigInteger;
+ '944': BigInteger;
+ '945': BigInteger;
+ '946': BigInteger;
+ '947': BigInteger;
+ '948': BigInteger;
+ '949': BigInteger;
+ '950': BigInteger;
+ '951': BigInteger;
+ '952': BigInteger;
+ '953': BigInteger;
+ '954': BigInteger;
+ '955': BigInteger;
+ '956': BigInteger;
+ '957': BigInteger;
+ '958': BigInteger;
+ '959': BigInteger;
+ '960': BigInteger;
+ '961': BigInteger;
+ '962': BigInteger;
+ '963': BigInteger;
+ '964': BigInteger;
+ '965': BigInteger;
+ '966': BigInteger;
+ '967': BigInteger;
+ '968': BigInteger;
+ '969': BigInteger;
+ '970': BigInteger;
+ '971': BigInteger;
+ '972': BigInteger;
+ '973': BigInteger;
+ '974': BigInteger;
+ '975': BigInteger;
+ '976': BigInteger;
+ '977': BigInteger;
+ '978': BigInteger;
+ '979': BigInteger;
+ '980': BigInteger;
+ '981': BigInteger;
+ '982': BigInteger;
+ '983': BigInteger;
+ '984': BigInteger;
+ '985': BigInteger;
+ '986': BigInteger;
+ '987': BigInteger;
+ '988': BigInteger;
+ '989': BigInteger;
+ '990': BigInteger;
+ '991': BigInteger;
+ '992': BigInteger;
+ '993': BigInteger;
+ '994': BigInteger;
+ '995': BigInteger;
+ '996': BigInteger;
+ '997': BigInteger;
+ '998': BigInteger;
+ '999': BigInteger;
+ }
+
+ interface BaseArray {
+ value: number[],
+ isNegative: boolean
+ }
+}
diff --git a/node_modules/big-integer/BigInteger.js b/node_modules/big-integer/BigInteger.js
new file mode 100644
index 0000000..e8658dc
--- /dev/null
+++ b/node_modules/big-integer/BigInteger.js
@@ -0,0 +1,1453 @@
+var bigInt = (function (undefined) {
+ "use strict";
+
+ var BASE = 1e7,
+ LOG_BASE = 7,
+ MAX_INT = 9007199254740992,
+ MAX_INT_ARR = smallToArray(MAX_INT),
+ DEFAULT_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+ var supportsNativeBigInt = typeof BigInt === "function";
+
+ function Integer(v, radix, alphabet, caseSensitive) {
+ if (typeof v === "undefined") return Integer[0];
+ if (typeof radix !== "undefined") return +radix === 10 && !alphabet ? parseValue(v) : parseBase(v, radix, alphabet, caseSensitive);
+ return parseValue(v);
+ }
+
+ function BigInteger(value, sign) {
+ this.value = value;
+ this.sign = sign;
+ this.isSmall = false;
+ }
+ BigInteger.prototype = Object.create(Integer.prototype);
+
+ function SmallInteger(value) {
+ this.value = value;
+ this.sign = value < 0;
+ this.isSmall = true;
+ }
+ SmallInteger.prototype = Object.create(Integer.prototype);
+
+ function NativeBigInt(value) {
+ this.value = value;
+ }
+ NativeBigInt.prototype = Object.create(Integer.prototype);
+
+ function isPrecise(n) {
+ return -MAX_INT < n && n < MAX_INT;
+ }
+
+ function smallToArray(n) { // For performance reasons doesn't reference BASE, need to change this function if BASE changes
+ if (n < 1e7)
+ return [n];
+ if (n < 1e14)
+ return [n % 1e7, Math.floor(n / 1e7)];
+ return [n % 1e7, Math.floor(n / 1e7) % 1e7, Math.floor(n / 1e14)];
+ }
+
+ function arrayToSmall(arr) { // If BASE changes this function may need to change
+ trim(arr);
+ var length = arr.length;
+ if (length < 4 && compareAbs(arr, MAX_INT_ARR) < 0) {
+ switch (length) {
+ case 0: return 0;
+ case 1: return arr[0];
+ case 2: return arr[0] + arr[1] * BASE;
+ default: return arr[0] + (arr[1] + arr[2] * BASE) * BASE;
+ }
+ }
+ return arr;
+ }
+
+ function trim(v) {
+ var i = v.length;
+ while (v[--i] === 0);
+ v.length = i + 1;
+ }
+
+ function createArray(length) { // function shamelessly stolen from Yaffle's library https://github.com/Yaffle/BigInteger
+ var x = new Array(length);
+ var i = -1;
+ while (++i < length) {
+ x[i] = 0;
+ }
+ return x;
+ }
+
+ function truncate(n) {
+ if (n > 0) return Math.floor(n);
+ return Math.ceil(n);
+ }
+
+ function add(a, b) { // assumes a and b are arrays with a.length >= b.length
+ var l_a = a.length,
+ l_b = b.length,
+ r = new Array(l_a),
+ carry = 0,
+ base = BASE,
+ sum, i;
+ for (i = 0; i < l_b; i++) {
+ sum = a[i] + b[i] + carry;
+ carry = sum >= base ? 1 : 0;
+ r[i] = sum - carry * base;
+ }
+ while (i < l_a) {
+ sum = a[i] + carry;
+ carry = sum === base ? 1 : 0;
+ r[i++] = sum - carry * base;
+ }
+ if (carry > 0) r.push(carry);
+ return r;
+ }
+
+ function addAny(a, b) {
+ if (a.length >= b.length) return add(a, b);
+ return add(b, a);
+ }
+
+ function addSmall(a, carry) { // assumes a is array, carry is number with 0 <= carry < MAX_INT
+ var l = a.length,
+ r = new Array(l),
+ base = BASE,
+ sum, i;
+ for (i = 0; i < l; i++) {
+ sum = a[i] - base + carry;
+ carry = Math.floor(sum / base);
+ r[i] = sum - carry * base;
+ carry += 1;
+ }
+ while (carry > 0) {
+ r[i++] = carry % base;
+ carry = Math.floor(carry / base);
+ }
+ return r;
+ }
+
+ BigInteger.prototype.add = function (v) {
+ var n = parseValue(v);
+ if (this.sign !== n.sign) {
+ return this.subtract(n.negate());
+ }
+ var a = this.value, b = n.value;
+ if (n.isSmall) {
+ return new BigInteger(addSmall(a, Math.abs(b)), this.sign);
+ }
+ return new BigInteger(addAny(a, b), this.sign);
+ };
+ BigInteger.prototype.plus = BigInteger.prototype.add;
+
+ SmallInteger.prototype.add = function (v) {
+ var n = parseValue(v);
+ var a = this.value;
+ if (a < 0 !== n.sign) {
+ return this.subtract(n.negate());
+ }
+ var b = n.value;
+ if (n.isSmall) {
+ if (isPrecise(a + b)) return new SmallInteger(a + b);
+ b = smallToArray(Math.abs(b));
+ }
+ return new BigInteger(addSmall(b, Math.abs(a)), a < 0);
+ };
+ SmallInteger.prototype.plus = SmallInteger.prototype.add;
+
+ NativeBigInt.prototype.add = function (v) {
+ return new NativeBigInt(this.value + parseValue(v).value);
+ }
+ NativeBigInt.prototype.plus = NativeBigInt.prototype.add;
+
+ function subtract(a, b) { // assumes a and b are arrays with a >= b
+ var a_l = a.length,
+ b_l = b.length,
+ r = new Array(a_l),
+ borrow = 0,
+ base = BASE,
+ i, difference;
+ for (i = 0; i < b_l; i++) {
+ difference = a[i] - borrow - b[i];
+ if (difference < 0) {
+ difference += base;
+ borrow = 1;
+ } else borrow = 0;
+ r[i] = difference;
+ }
+ for (i = b_l; i < a_l; i++) {
+ difference = a[i] - borrow;
+ if (difference < 0) difference += base;
+ else {
+ r[i++] = difference;
+ break;
+ }
+ r[i] = difference;
+ }
+ for (; i < a_l; i++) {
+ r[i] = a[i];
+ }
+ trim(r);
+ return r;
+ }
+
+ function subtractAny(a, b, sign) {
+ var value;
+ if (compareAbs(a, b) >= 0) {
+ value = subtract(a, b);
+ } else {
+ value = subtract(b, a);
+ sign = !sign;
+ }
+ value = arrayToSmall(value);
+ if (typeof value === "number") {
+ if (sign) value = -value;
+ return new SmallInteger(value);
+ }
+ return new BigInteger(value, sign);
+ }
+
+ function subtractSmall(a, b, sign) { // assumes a is array, b is number with 0 <= b < MAX_INT
+ var l = a.length,
+ r = new Array(l),
+ carry = -b,
+ base = BASE,
+ i, difference;
+ for (i = 0; i < l; i++) {
+ difference = a[i] + carry;
+ carry = Math.floor(difference / base);
+ difference %= base;
+ r[i] = difference < 0 ? difference + base : difference;
+ }
+ r = arrayToSmall(r);
+ if (typeof r === "number") {
+ if (sign) r = -r;
+ return new SmallInteger(r);
+ } return new BigInteger(r, sign);
+ }
+
+ BigInteger.prototype.subtract = function (v) {
+ var n = parseValue(v);
+ if (this.sign !== n.sign) {
+ return this.add(n.negate());
+ }
+ var a = this.value, b = n.value;
+ if (n.isSmall)
+ return subtractSmall(a, Math.abs(b), this.sign);
+ return subtractAny(a, b, this.sign);
+ };
+ BigInteger.prototype.minus = BigInteger.prototype.subtract;
+
+ SmallInteger.prototype.subtract = function (v) {
+ var n = parseValue(v);
+ var a = this.value;
+ if (a < 0 !== n.sign) {
+ return this.add(n.negate());
+ }
+ var b = n.value;
+ if (n.isSmall) {
+ return new SmallInteger(a - b);
+ }
+ return subtractSmall(b, Math.abs(a), a >= 0);
+ };
+ SmallInteger.prototype.minus = SmallInteger.prototype.subtract;
+
+ NativeBigInt.prototype.subtract = function (v) {
+ return new NativeBigInt(this.value - parseValue(v).value);
+ }
+ NativeBigInt.prototype.minus = NativeBigInt.prototype.subtract;
+
+ BigInteger.prototype.negate = function () {
+ return new BigInteger(this.value, !this.sign);
+ };
+ SmallInteger.prototype.negate = function () {
+ var sign = this.sign;
+ var small = new SmallInteger(-this.value);
+ small.sign = !sign;
+ return small;
+ };
+ NativeBigInt.prototype.negate = function () {
+ return new NativeBigInt(-this.value);
+ }
+
+ BigInteger.prototype.abs = function () {
+ return new BigInteger(this.value, false);
+ };
+ SmallInteger.prototype.abs = function () {
+ return new SmallInteger(Math.abs(this.value));
+ };
+ NativeBigInt.prototype.abs = function () {
+ return new NativeBigInt(this.value >= 0 ? this.value : -this.value);
+ }
+
+
+ function multiplyLong(a, b) {
+ var a_l = a.length,
+ b_l = b.length,
+ l = a_l + b_l,
+ r = createArray(l),
+ base = BASE,
+ product, carry, i, a_i, b_j;
+ for (i = 0; i < a_l; ++i) {
+ a_i = a[i];
+ for (var j = 0; j < b_l; ++j) {
+ b_j = b[j];
+ product = a_i * b_j + r[i + j];
+ carry = Math.floor(product / base);
+ r[i + j] = product - carry * base;
+ r[i + j + 1] += carry;
+ }
+ }
+ trim(r);
+ return r;
+ }
+
+ function multiplySmall(a, b) { // assumes a is array, b is number with |b| < BASE
+ var l = a.length,
+ r = new Array(l),
+ base = BASE,
+ carry = 0,
+ product, i;
+ for (i = 0; i < l; i++) {
+ product = a[i] * b + carry;
+ carry = Math.floor(product / base);
+ r[i] = product - carry * base;
+ }
+ while (carry > 0) {
+ r[i++] = carry % base;
+ carry = Math.floor(carry / base);
+ }
+ return r;
+ }
+
+ function shiftLeft(x, n) {
+ var r = [];
+ while (n-- > 0) r.push(0);
+ return r.concat(x);
+ }
+
+ function multiplyKaratsuba(x, y) {
+ var n = Math.max(x.length, y.length);
+
+ if (n <= 30) return multiplyLong(x, y);
+ n = Math.ceil(n / 2);
+
+ var b = x.slice(n),
+ a = x.slice(0, n),
+ d = y.slice(n),
+ c = y.slice(0, n);
+
+ var ac = multiplyKaratsuba(a, c),
+ bd = multiplyKaratsuba(b, d),
+ abcd = multiplyKaratsuba(addAny(a, b), addAny(c, d));
+
+ var product = addAny(addAny(ac, shiftLeft(subtract(subtract(abcd, ac), bd), n)), shiftLeft(bd, 2 * n));
+ trim(product);
+ return product;
+ }
+
+ // The following function is derived from a surface fit of a graph plotting the performance difference
+ // between long multiplication and karatsuba multiplication versus the lengths of the two arrays.
+ function useKaratsuba(l1, l2) {
+ return -0.012 * l1 - 0.012 * l2 + 0.000015 * l1 * l2 > 0;
+ }
+
+ BigInteger.prototype.multiply = function (v) {
+ var n = parseValue(v),
+ a = this.value, b = n.value,
+ sign = this.sign !== n.sign,
+ abs;
+ if (n.isSmall) {
+ if (b === 0) return Integer[0];
+ if (b === 1) return this;
+ if (b === -1) return this.negate();
+ abs = Math.abs(b);
+ if (abs < BASE) {
+ return new BigInteger(multiplySmall(a, abs), sign);
+ }
+ b = smallToArray(abs);
+ }
+ if (useKaratsuba(a.length, b.length)) // Karatsuba is only faster for certain array sizes
+ return new BigInteger(multiplyKaratsuba(a, b), sign);
+ return new BigInteger(multiplyLong(a, b), sign);
+ };
+
+ BigInteger.prototype.times = BigInteger.prototype.multiply;
+
+ function multiplySmallAndArray(a, b, sign) { // a >= 0
+ if (a < BASE) {
+ return new BigInteger(multiplySmall(b, a), sign);
+ }
+ return new BigInteger(multiplyLong(b, smallToArray(a)), sign);
+ }
+ SmallInteger.prototype._multiplyBySmall = function (a) {
+ if (isPrecise(a.value * this.value)) {
+ return new SmallInteger(a.value * this.value);
+ }
+ return multiplySmallAndArray(Math.abs(a.value), smallToArray(Math.abs(this.value)), this.sign !== a.sign);
+ };
+ BigInteger.prototype._multiplyBySmall = function (a) {
+ if (a.value === 0) return Integer[0];
+ if (a.value === 1) return this;
+ if (a.value === -1) return this.negate();
+ return multiplySmallAndArray(Math.abs(a.value), this.value, this.sign !== a.sign);
+ };
+ SmallInteger.prototype.multiply = function (v) {
+ return parseValue(v)._multiplyBySmall(this);
+ };
+ SmallInteger.prototype.times = SmallInteger.prototype.multiply;
+
+ NativeBigInt.prototype.multiply = function (v) {
+ return new NativeBigInt(this.value * parseValue(v).value);
+ }
+ NativeBigInt.prototype.times = NativeBigInt.prototype.multiply;
+
+ function square(a) {
+ //console.assert(2 * BASE * BASE < MAX_INT);
+ var l = a.length,
+ r = createArray(l + l),
+ base = BASE,
+ product, carry, i, a_i, a_j;
+ for (i = 0; i < l; i++) {
+ a_i = a[i];
+ carry = 0 - a_i * a_i;
+ for (var j = i; j < l; j++) {
+ a_j = a[j];
+ product = 2 * (a_i * a_j) + r[i + j] + carry;
+ carry = Math.floor(product / base);
+ r[i + j] = product - carry * base;
+ }
+ r[i + l] = carry;
+ }
+ trim(r);
+ return r;
+ }
+
+ BigInteger.prototype.square = function () {
+ return new BigInteger(square(this.value), false);
+ };
+
+ SmallInteger.prototype.square = function () {
+ var value = this.value * this.value;
+ if (isPrecise(value)) return new SmallInteger(value);
+ return new BigInteger(square(smallToArray(Math.abs(this.value))), false);
+ };
+
+ NativeBigInt.prototype.square = function (v) {
+ return new NativeBigInt(this.value * this.value);
+ }
+
+ function divMod1(a, b) { // Left over from previous version. Performs faster than divMod2 on smaller input sizes.
+ var a_l = a.length,
+ b_l = b.length,
+ base = BASE,
+ result = createArray(b.length),
+ divisorMostSignificantDigit = b[b_l - 1],
+ // normalization
+ lambda = Math.ceil(base / (2 * divisorMostSignificantDigit)),
+ remainder = multiplySmall(a, lambda),
+ divisor = multiplySmall(b, lambda),
+ quotientDigit, shift, carry, borrow, i, l, q;
+ if (remainder.length <= a_l) remainder.push(0);
+ divisor.push(0);
+ divisorMostSignificantDigit = divisor[b_l - 1];
+ for (shift = a_l - b_l; shift >= 0; shift--) {
+ quotientDigit = base - 1;
+ if (remainder[shift + b_l] !== divisorMostSignificantDigit) {
+ quotientDigit = Math.floor((remainder[shift + b_l] * base + remainder[shift + b_l - 1]) / divisorMostSignificantDigit);
+ }
+ // quotientDigit <= base - 1
+ carry = 0;
+ borrow = 0;
+ l = divisor.length;
+ for (i = 0; i < l; i++) {
+ carry += quotientDigit * divisor[i];
+ q = Math.floor(carry / base);
+ borrow += remainder[shift + i] - (carry - q * base);
+ carry = q;
+ if (borrow < 0) {
+ remainder[shift + i] = borrow + base;
+ borrow = -1;
+ } else {
+ remainder[shift + i] = borrow;
+ borrow = 0;
+ }
+ }
+ while (borrow !== 0) {
+ quotientDigit -= 1;
+ carry = 0;
+ for (i = 0; i < l; i++) {
+ carry += remainder[shift + i] - base + divisor[i];
+ if (carry < 0) {
+ remainder[shift + i] = carry + base;
+ carry = 0;
+ } else {
+ remainder[shift + i] = carry;
+ carry = 1;
+ }
+ }
+ borrow += carry;
+ }
+ result[shift] = quotientDigit;
+ }
+ // denormalization
+ remainder = divModSmall(remainder, lambda)[0];
+ return [arrayToSmall(result), arrayToSmall(remainder)];
+ }
+
+ function divMod2(a, b) { // Implementation idea shamelessly stolen from Silent Matt's library http://silentmatt.com/biginteger/
+ // Performs faster than divMod1 on larger input sizes.
+ var a_l = a.length,
+ b_l = b.length,
+ result = [],
+ part = [],
+ base = BASE,
+ guess, xlen, highx, highy, check;
+ while (a_l) {
+ part.unshift(a[--a_l]);
+ trim(part);
+ if (compareAbs(part, b) < 0) {
+ result.push(0);
+ continue;
+ }
+ xlen = part.length;
+ highx = part[xlen - 1] * base + part[xlen - 2];
+ highy = b[b_l - 1] * base + b[b_l - 2];
+ if (xlen > b_l) {
+ highx = (highx + 1) * base;
+ }
+ guess = Math.ceil(highx / highy);
+ do {
+ check = multiplySmall(b, guess);
+ if (compareAbs(check, part) <= 0) break;
+ guess--;
+ } while (guess);
+ result.push(guess);
+ part = subtract(part, check);
+ }
+ result.reverse();
+ return [arrayToSmall(result), arrayToSmall(part)];
+ }
+
+ function divModSmall(value, lambda) {
+ var length = value.length,
+ quotient = createArray(length),
+ base = BASE,
+ i, q, remainder, divisor;
+ remainder = 0;
+ for (i = length - 1; i >= 0; --i) {
+ divisor = remainder * base + value[i];
+ q = truncate(divisor / lambda);
+ remainder = divisor - q * lambda;
+ quotient[i] = q | 0;
+ }
+ return [quotient, remainder | 0];
+ }
+
+ function divModAny(self, v) {
+ var value, n = parseValue(v);
+ if (supportsNativeBigInt) {
+ return [new NativeBigInt(self.value / n.value), new NativeBigInt(self.value % n.value)];
+ }
+ var a = self.value, b = n.value;
+ var quotient;
+ if (b === 0) throw new Error("Cannot divide by zero");
+ if (self.isSmall) {
+ if (n.isSmall) {
+ return [new SmallInteger(truncate(a / b)), new SmallInteger(a % b)];
+ }
+ return [Integer[0], self];
+ }
+ if (n.isSmall) {
+ if (b === 1) return [self, Integer[0]];
+ if (b == -1) return [self.negate(), Integer[0]];
+ var abs = Math.abs(b);
+ if (abs < BASE) {
+ value = divModSmall(a, abs);
+ quotient = arrayToSmall(value[0]);
+ var remainder = value[1];
+ if (self.sign) remainder = -remainder;
+ if (typeof quotient === "number") {
+ if (self.sign !== n.sign) quotient = -quotient;
+ return [new SmallInteger(quotient), new SmallInteger(remainder)];
+ }
+ return [new BigInteger(quotient, self.sign !== n.sign), new SmallInteger(remainder)];
+ }
+ b = smallToArray(abs);
+ }
+ var comparison = compareAbs(a, b);
+ if (comparison === -1) return [Integer[0], self];
+ if (comparison === 0) return [Integer[self.sign === n.sign ? 1 : -1], Integer[0]];
+
+ // divMod1 is faster on smaller input sizes
+ if (a.length + b.length <= 200)
+ value = divMod1(a, b);
+ else value = divMod2(a, b);
+
+ quotient = value[0];
+ var qSign = self.sign !== n.sign,
+ mod = value[1],
+ mSign = self.sign;
+ if (typeof quotient === "number") {
+ if (qSign) quotient = -quotient;
+ quotient = new SmallInteger(quotient);
+ } else quotient = new BigInteger(quotient, qSign);
+ if (typeof mod === "number") {
+ if (mSign) mod = -mod;
+ mod = new SmallInteger(mod);
+ } else mod = new BigInteger(mod, mSign);
+ return [quotient, mod];
+ }
+
+ BigInteger.prototype.divmod = function (v) {
+ var result = divModAny(this, v);
+ return {
+ quotient: result[0],
+ remainder: result[1]
+ };
+ };
+ NativeBigInt.prototype.divmod = SmallInteger.prototype.divmod = BigInteger.prototype.divmod;
+
+
+ BigInteger.prototype.divide = function (v) {
+ return divModAny(this, v)[0];
+ };
+ NativeBigInt.prototype.over = NativeBigInt.prototype.divide = function (v) {
+ return new NativeBigInt(this.value / parseValue(v).value);
+ };
+ SmallInteger.prototype.over = SmallInteger.prototype.divide = BigInteger.prototype.over = BigInteger.prototype.divide;
+
+ BigInteger.prototype.mod = function (v) {
+ return divModAny(this, v)[1];
+ };
+ NativeBigInt.prototype.mod = NativeBigInt.prototype.remainder = function (v) {
+ return new NativeBigInt(this.value % parseValue(v).value);
+ };
+ SmallInteger.prototype.remainder = SmallInteger.prototype.mod = BigInteger.prototype.remainder = BigInteger.prototype.mod;
+
+ BigInteger.prototype.pow = function (v) {
+ var n = parseValue(v),
+ a = this.value,
+ b = n.value,
+ value, x, y;
+ if (b === 0) return Integer[1];
+ if (a === 0) return Integer[0];
+ if (a === 1) return Integer[1];
+ if (a === -1) return n.isEven() ? Integer[1] : Integer[-1];
+ if (n.sign) {
+ return Integer[0];
+ }
+ if (!n.isSmall) throw new Error("The exponent " + n.toString() + " is too large.");
+ if (this.isSmall) {
+ if (isPrecise(value = Math.pow(a, b)))
+ return new SmallInteger(truncate(value));
+ }
+ x = this;
+ y = Integer[1];
+ while (true) {
+ if (b & 1 === 1) {
+ y = y.times(x);
+ --b;
+ }
+ if (b === 0) break;
+ b /= 2;
+ x = x.square();
+ }
+ return y;
+ };
+ SmallInteger.prototype.pow = BigInteger.prototype.pow;
+
+ NativeBigInt.prototype.pow = function (v) {
+ var n = parseValue(v);
+ var a = this.value, b = n.value;
+ var _0 = BigInt(0), _1 = BigInt(1), _2 = BigInt(2);
+ if (b === _0) return Integer[1];
+ if (a === _0) return Integer[0];
+ if (a === _1) return Integer[1];
+ if (a === BigInt(-1)) return n.isEven() ? Integer[1] : Integer[-1];
+ if (n.isNegative()) return new NativeBigInt(_0);
+ var x = this;
+ var y = Integer[1];
+ while (true) {
+ if ((b & _1) === _1) {
+ y = y.times(x);
+ --b;
+ }
+ if (b === _0) break;
+ b /= _2;
+ x = x.square();
+ }
+ return y;
+ }
+
+ BigInteger.prototype.modPow = function (exp, mod) {
+ exp = parseValue(exp);
+ mod = parseValue(mod);
+ if (mod.isZero()) throw new Error("Cannot take modPow with modulus 0");
+ var r = Integer[1],
+ base = this.mod(mod);
+ if (exp.isNegative()) {
+ exp = exp.multiply(Integer[-1]);
+ base = base.modInv(mod);
+ }
+ while (exp.isPositive()) {
+ if (base.isZero()) return Integer[0];
+ if (exp.isOdd()) r = r.multiply(base).mod(mod);
+ exp = exp.divide(2);
+ base = base.square().mod(mod);
+ }
+ return r;
+ };
+ NativeBigInt.prototype.modPow = SmallInteger.prototype.modPow = BigInteger.prototype.modPow;
+
+ function compareAbs(a, b) {
+ if (a.length !== b.length) {
+ return a.length > b.length ? 1 : -1;
+ }
+ for (var i = a.length - 1; i >= 0; i--) {
+ if (a[i] !== b[i]) return a[i] > b[i] ? 1 : -1;
+ }
+ return 0;
+ }
+
+ BigInteger.prototype.compareAbs = function (v) {
+ var n = parseValue(v),
+ a = this.value,
+ b = n.value;
+ if (n.isSmall) return 1;
+ return compareAbs(a, b);
+ };
+ SmallInteger.prototype.compareAbs = function (v) {
+ var n = parseValue(v),
+ a = Math.abs(this.value),
+ b = n.value;
+ if (n.isSmall) {
+ b = Math.abs(b);
+ return a === b ? 0 : a > b ? 1 : -1;
+ }
+ return -1;
+ };
+ NativeBigInt.prototype.compareAbs = function (v) {
+ var a = this.value;
+ var b = parseValue(v).value;
+ a = a >= 0 ? a : -a;
+ b = b >= 0 ? b : -b;
+ return a === b ? 0 : a > b ? 1 : -1;
+ }
+
+ BigInteger.prototype.compare = function (v) {
+ // See discussion about comparison with Infinity:
+ // https://github.com/peterolson/BigInteger.js/issues/61
+ if (v === Infinity) {
+ return -1;
+ }
+ if (v === -Infinity) {
+ return 1;
+ }
+
+ var n = parseValue(v),
+ a = this.value,
+ b = n.value;
+ if (this.sign !== n.sign) {
+ return n.sign ? 1 : -1;
+ }
+ if (n.isSmall) {
+ return this.sign ? -1 : 1;
+ }
+ return compareAbs(a, b) * (this.sign ? -1 : 1);
+ };
+ BigInteger.prototype.compareTo = BigInteger.prototype.compare;
+
+ SmallInteger.prototype.compare = function (v) {
+ if (v === Infinity) {
+ return -1;
+ }
+ if (v === -Infinity) {
+ return 1;
+ }
+
+ var n = parseValue(v),
+ a = this.value,
+ b = n.value;
+ if (n.isSmall) {
+ return a == b ? 0 : a > b ? 1 : -1;
+ }
+ if (a < 0 !== n.sign) {
+ return a < 0 ? -1 : 1;
+ }
+ return a < 0 ? 1 : -1;
+ };
+ SmallInteger.prototype.compareTo = SmallInteger.prototype.compare;
+
+ NativeBigInt.prototype.compare = function (v) {
+ if (v === Infinity) {
+ return -1;
+ }
+ if (v === -Infinity) {
+ return 1;
+ }
+ var a = this.value;
+ var b = parseValue(v).value;
+ return a === b ? 0 : a > b ? 1 : -1;
+ }
+ NativeBigInt.prototype.compareTo = NativeBigInt.prototype.compare;
+
+ BigInteger.prototype.equals = function (v) {
+ return this.compare(v) === 0;
+ };
+ NativeBigInt.prototype.eq = NativeBigInt.prototype.equals = SmallInteger.prototype.eq = SmallInteger.prototype.equals = BigInteger.prototype.eq = BigInteger.prototype.equals;
+
+ BigInteger.prototype.notEquals = function (v) {
+ return this.compare(v) !== 0;
+ };
+ NativeBigInt.prototype.neq = NativeBigInt.prototype.notEquals = SmallInteger.prototype.neq = SmallInteger.prototype.notEquals = BigInteger.prototype.neq = BigInteger.prototype.notEquals;
+
+ BigInteger.prototype.greater = function (v) {
+ return this.compare(v) > 0;
+ };
+ NativeBigInt.prototype.gt = NativeBigInt.prototype.greater = SmallInteger.prototype.gt = SmallInteger.prototype.greater = BigInteger.prototype.gt = BigInteger.prototype.greater;
+
+ BigInteger.prototype.lesser = function (v) {
+ return this.compare(v) < 0;
+ };
+ NativeBigInt.prototype.lt = NativeBigInt.prototype.lesser = SmallInteger.prototype.lt = SmallInteger.prototype.lesser = BigInteger.prototype.lt = BigInteger.prototype.lesser;
+
+ BigInteger.prototype.greaterOrEquals = function (v) {
+ return this.compare(v) >= 0;
+ };
+ NativeBigInt.prototype.geq = NativeBigInt.prototype.greaterOrEquals = SmallInteger.prototype.geq = SmallInteger.prototype.greaterOrEquals = BigInteger.prototype.geq = BigInteger.prototype.greaterOrEquals;
+
+ BigInteger.prototype.lesserOrEquals = function (v) {
+ return this.compare(v) <= 0;
+ };
+ NativeBigInt.prototype.leq = NativeBigInt.prototype.lesserOrEquals = SmallInteger.prototype.leq = SmallInteger.prototype.lesserOrEquals = BigInteger.prototype.leq = BigInteger.prototype.lesserOrEquals;
+
+ BigInteger.prototype.isEven = function () {
+ return (this.value[0] & 1) === 0;
+ };
+ SmallInteger.prototype.isEven = function () {
+ return (this.value & 1) === 0;
+ };
+ NativeBigInt.prototype.isEven = function () {
+ return (this.value & BigInt(1)) === BigInt(0);
+ }
+
+ BigInteger.prototype.isOdd = function () {
+ return (this.value[0] & 1) === 1;
+ };
+ SmallInteger.prototype.isOdd = function () {
+ return (this.value & 1) === 1;
+ };
+ NativeBigInt.prototype.isOdd = function () {
+ return (this.value & BigInt(1)) === BigInt(1);
+ }
+
+ BigInteger.prototype.isPositive = function () {
+ return !this.sign;
+ };
+ SmallInteger.prototype.isPositive = function () {
+ return this.value > 0;
+ };
+ NativeBigInt.prototype.isPositive = SmallInteger.prototype.isPositive;
+
+ BigInteger.prototype.isNegative = function () {
+ return this.sign;
+ };
+ SmallInteger.prototype.isNegative = function () {
+ return this.value < 0;
+ };
+ NativeBigInt.prototype.isNegative = SmallInteger.prototype.isNegative;
+
+ BigInteger.prototype.isUnit = function () {
+ return false;
+ };
+ SmallInteger.prototype.isUnit = function () {
+ return Math.abs(this.value) === 1;
+ };
+ NativeBigInt.prototype.isUnit = function () {
+ return this.abs().value === BigInt(1);
+ }
+
+ BigInteger.prototype.isZero = function () {
+ return false;
+ };
+ SmallInteger.prototype.isZero = function () {
+ return this.value === 0;
+ };
+ NativeBigInt.prototype.isZero = function () {
+ return this.value === BigInt(0);
+ }
+
+ BigInteger.prototype.isDivisibleBy = function (v) {
+ var n = parseValue(v);
+ if (n.isZero()) return false;
+ if (n.isUnit()) return true;
+ if (n.compareAbs(2) === 0) return this.isEven();
+ return this.mod(n).isZero();
+ };
+ NativeBigInt.prototype.isDivisibleBy = SmallInteger.prototype.isDivisibleBy = BigInteger.prototype.isDivisibleBy;
+
+ function isBasicPrime(v) {
+ var n = v.abs();
+ if (n.isUnit()) return false;
+ if (n.equals(2) || n.equals(3) || n.equals(5)) return true;
+ if (n.isEven() || n.isDivisibleBy(3) || n.isDivisibleBy(5)) return false;
+ if (n.lesser(49)) return true;
+ // we don't know if it's prime: let the other functions figure it out
+ }
+
+ function millerRabinTest(n, a) {
+ var nPrev = n.prev(),
+ b = nPrev,
+ r = 0,
+ d, t, i, x;
+ while (b.isEven()) b = b.divide(2), r++;
+ next: for (i = 0; i < a.length; i++) {
+ if (n.lesser(a[i])) continue;
+ x = bigInt(a[i]).modPow(b, n);
+ if (x.isUnit() || x.equals(nPrev)) continue;
+ for (d = r - 1; d != 0; d--) {
+ x = x.square().mod(n);
+ if (x.isUnit()) return false;
+ if (x.equals(nPrev)) continue next;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ // Set "strict" to true to force GRH-supported lower bound of 2*log(N)^2
+ BigInteger.prototype.isPrime = function (strict) {
+ var isPrime = isBasicPrime(this);
+ if (isPrime !== undefined) return isPrime;
+ var n = this.abs();
+ var bits = n.bitLength();
+ if (bits <= 64)
+ return millerRabinTest(n, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]);
+ var logN = Math.log(2) * bits.toJSNumber();
+ var t = Math.ceil((strict === true) ? (2 * Math.pow(logN, 2)) : logN);
+ for (var a = [], i = 0; i < t; i++) {
+ a.push(bigInt(i + 2));
+ }
+ return millerRabinTest(n, a);
+ };
+ NativeBigInt.prototype.isPrime = SmallInteger.prototype.isPrime = BigInteger.prototype.isPrime;
+
+ BigInteger.prototype.isProbablePrime = function (iterations, rng) {
+ var isPrime = isBasicPrime(this);
+ if (isPrime !== undefined) return isPrime;
+ var n = this.abs();
+ var t = iterations === undefined ? 5 : iterations;
+ for (var a = [], i = 0; i < t; i++) {
+ a.push(bigInt.randBetween(2, n.minus(2), rng));
+ }
+ return millerRabinTest(n, a);
+ };
+ NativeBigInt.prototype.isProbablePrime = SmallInteger.prototype.isProbablePrime = BigInteger.prototype.isProbablePrime;
+
+ BigInteger.prototype.modInv = function (n) {
+ var t = bigInt.zero, newT = bigInt.one, r = parseValue(n), newR = this.abs(), q, lastT, lastR;
+ while (!newR.isZero()) {
+ q = r.divide(newR);
+ lastT = t;
+ lastR = r;
+ t = newT;
+ r = newR;
+ newT = lastT.subtract(q.multiply(newT));
+ newR = lastR.subtract(q.multiply(newR));
+ }
+ if (!r.isUnit()) throw new Error(this.toString() + " and " + n.toString() + " are not co-prime");
+ if (t.compare(0) === -1) {
+ t = t.add(n);
+ }
+ if (this.isNegative()) {
+ return t.negate();
+ }
+ return t;
+ };
+
+ NativeBigInt.prototype.modInv = SmallInteger.prototype.modInv = BigInteger.prototype.modInv;
+
+ BigInteger.prototype.next = function () {
+ var value = this.value;
+ if (this.sign) {
+ return subtractSmall(value, 1, this.sign);
+ }
+ return new BigInteger(addSmall(value, 1), this.sign);
+ };
+ SmallInteger.prototype.next = function () {
+ var value = this.value;
+ if (value + 1 < MAX_INT) return new SmallInteger(value + 1);
+ return new BigInteger(MAX_INT_ARR, false);
+ };
+ NativeBigInt.prototype.next = function () {
+ return new NativeBigInt(this.value + BigInt(1));
+ }
+
+ BigInteger.prototype.prev = function () {
+ var value = this.value;
+ if (this.sign) {
+ return new BigInteger(addSmall(value, 1), true);
+ }
+ return subtractSmall(value, 1, this.sign);
+ };
+ SmallInteger.prototype.prev = function () {
+ var value = this.value;
+ if (value - 1 > -MAX_INT) return new SmallInteger(value - 1);
+ return new BigInteger(MAX_INT_ARR, true);
+ };
+ NativeBigInt.prototype.prev = function () {
+ return new NativeBigInt(this.value - BigInt(1));
+ }
+
+ var powersOfTwo = [1];
+ while (2 * powersOfTwo[powersOfTwo.length - 1] <= BASE) powersOfTwo.push(2 * powersOfTwo[powersOfTwo.length - 1]);
+ var powers2Length = powersOfTwo.length, highestPower2 = powersOfTwo[powers2Length - 1];
+
+ function shift_isSmall(n) {
+ return Math.abs(n) <= BASE;
+ }
+
+ BigInteger.prototype.shiftLeft = function (v) {
+ var n = parseValue(v).toJSNumber();
+ if (!shift_isSmall(n)) {
+ throw new Error(String(n) + " is too large for shifting.");
+ }
+ if (n < 0) return this.shiftRight(-n);
+ var result = this;
+ if (result.isZero()) return result;
+ while (n >= powers2Length) {
+ result = result.multiply(highestPower2);
+ n -= powers2Length - 1;
+ }
+ return result.multiply(powersOfTwo[n]);
+ };
+ NativeBigInt.prototype.shiftLeft = SmallInteger.prototype.shiftLeft = BigInteger.prototype.shiftLeft;
+
+ BigInteger.prototype.shiftRight = function (v) {
+ var remQuo;
+ var n = parseValue(v).toJSNumber();
+ if (!shift_isSmall(n)) {
+ throw new Error(String(n) + " is too large for shifting.");
+ }
+ if (n < 0) return this.shiftLeft(-n);
+ var result = this;
+ while (n >= powers2Length) {
+ if (result.isZero() || (result.isNegative() && result.isUnit())) return result;
+ remQuo = divModAny(result, highestPower2);
+ result = remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0];
+ n -= powers2Length - 1;
+ }
+ remQuo = divModAny(result, powersOfTwo[n]);
+ return remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0];
+ };
+ NativeBigInt.prototype.shiftRight = SmallInteger.prototype.shiftRight = BigInteger.prototype.shiftRight;
+
+ function bitwise(x, y, fn) {
+ y = parseValue(y);
+ var xSign = x.isNegative(), ySign = y.isNegative();
+ var xRem = xSign ? x.not() : x,
+ yRem = ySign ? y.not() : y;
+ var xDigit = 0, yDigit = 0;
+ var xDivMod = null, yDivMod = null;
+ var result = [];
+ while (!xRem.isZero() || !yRem.isZero()) {
+ xDivMod = divModAny(xRem, highestPower2);
+ xDigit = xDivMod[1].toJSNumber();
+ if (xSign) {
+ xDigit = highestPower2 - 1 - xDigit; // two's complement for negative numbers
+ }
+
+ yDivMod = divModAny(yRem, highestPower2);
+ yDigit = yDivMod[1].toJSNumber();
+ if (ySign) {
+ yDigit = highestPower2 - 1 - yDigit; // two's complement for negative numbers
+ }
+
+ xRem = xDivMod[0];
+ yRem = yDivMod[0];
+ result.push(fn(xDigit, yDigit));
+ }
+ var sum = fn(xSign ? 1 : 0, ySign ? 1 : 0) !== 0 ? bigInt(-1) : bigInt(0);
+ for (var i = result.length - 1; i >= 0; i -= 1) {
+ sum = sum.multiply(highestPower2).add(bigInt(result[i]));
+ }
+ return sum;
+ }
+
+ BigInteger.prototype.not = function () {
+ return this.negate().prev();
+ };
+ NativeBigInt.prototype.not = SmallInteger.prototype.not = BigInteger.prototype.not;
+
+ BigInteger.prototype.and = function (n) {
+ return bitwise(this, n, function (a, b) { return a & b; });
+ };
+ NativeBigInt.prototype.and = SmallInteger.prototype.and = BigInteger.prototype.and;
+
+ BigInteger.prototype.or = function (n) {
+ return bitwise(this, n, function (a, b) { return a | b; });
+ };
+ NativeBigInt.prototype.or = SmallInteger.prototype.or = BigInteger.prototype.or;
+
+ BigInteger.prototype.xor = function (n) {
+ return bitwise(this, n, function (a, b) { return a ^ b; });
+ };
+ NativeBigInt.prototype.xor = SmallInteger.prototype.xor = BigInteger.prototype.xor;
+
+ var LOBMASK_I = 1 << 30, LOBMASK_BI = (BASE & -BASE) * (BASE & -BASE) | LOBMASK_I;
+ function roughLOB(n) { // get lowestOneBit (rough)
+ // SmallInteger: return Min(lowestOneBit(n), 1 << 30)
+ // BigInteger: return Min(lowestOneBit(n), 1 << 14) [BASE=1e7]
+ var v = n.value,
+ x = typeof v === "number" ? v | LOBMASK_I :
+ typeof v === "bigint" ? v | BigInt(LOBMASK_I) :
+ v[0] + v[1] * BASE | LOBMASK_BI;
+ return x & -x;
+ }
+
+ function integerLogarithm(value, base) {
+ if (base.compareTo(value) <= 0) {
+ var tmp = integerLogarithm(value, base.square(base));
+ var p = tmp.p;
+ var e = tmp.e;
+ var t = p.multiply(base);
+ return t.compareTo(value) <= 0 ? { p: t, e: e * 2 + 1 } : { p: p, e: e * 2 };
+ }
+ return { p: bigInt(1), e: 0 };
+ }
+
+ BigInteger.prototype.bitLength = function () {
+ var n = this;
+ if (n.compareTo(bigInt(0)) < 0) {
+ n = n.negate().subtract(bigInt(1));
+ }
+ if (n.compareTo(bigInt(0)) === 0) {
+ return bigInt(0);
+ }
+ return bigInt(integerLogarithm(n, bigInt(2)).e).add(bigInt(1));
+ }
+ NativeBigInt.prototype.bitLength = SmallInteger.prototype.bitLength = BigInteger.prototype.bitLength;
+
+ function max(a, b) {
+ a = parseValue(a);
+ b = parseValue(b);
+ return a.greater(b) ? a : b;
+ }
+ function min(a, b) {
+ a = parseValue(a);
+ b = parseValue(b);
+ return a.lesser(b) ? a : b;
+ }
+ function gcd(a, b) {
+ a = parseValue(a).abs();
+ b = parseValue(b).abs();
+ if (a.equals(b)) return a;
+ if (a.isZero()) return b;
+ if (b.isZero()) return a;
+ var c = Integer[1], d, t;
+ while (a.isEven() && b.isEven()) {
+ d = min(roughLOB(a), roughLOB(b));
+ a = a.divide(d);
+ b = b.divide(d);
+ c = c.multiply(d);
+ }
+ while (a.isEven()) {
+ a = a.divide(roughLOB(a));
+ }
+ do {
+ while (b.isEven()) {
+ b = b.divide(roughLOB(b));
+ }
+ if (a.greater(b)) {
+ t = b; b = a; a = t;
+ }
+ b = b.subtract(a);
+ } while (!b.isZero());
+ return c.isUnit() ? a : a.multiply(c);
+ }
+ function lcm(a, b) {
+ a = parseValue(a).abs();
+ b = parseValue(b).abs();
+ return a.divide(gcd(a, b)).multiply(b);
+ }
+ function randBetween(a, b, rng) {
+ a = parseValue(a);
+ b = parseValue(b);
+ var usedRNG = rng || Math.random;
+ var low = min(a, b), high = max(a, b);
+ var range = high.subtract(low).add(1);
+ if (range.isSmall) return low.add(Math.floor(usedRNG() * range));
+ var digits = toBase(range, BASE).value;
+ var result = [], restricted = true;
+ for (var i = 0; i < digits.length; i++) {
+ var top = restricted ? digits[i] + (i + 1 < digits.length ? digits[i + 1] / BASE : 0) : BASE;
+ var digit = truncate(usedRNG() * top);
+ result.push(digit);
+ if (digit < digits[i]) restricted = false;
+ }
+ return low.add(Integer.fromArray(result, BASE, false));
+ }
+
+ var parseBase = function (text, base, alphabet, caseSensitive) {
+ alphabet = alphabet || DEFAULT_ALPHABET;
+ text = String(text);
+ if (!caseSensitive) {
+ text = text.toLowerCase();
+ alphabet = alphabet.toLowerCase();
+ }
+ var length = text.length;
+ var i;
+ var absBase = Math.abs(base);
+ var alphabetValues = {};
+ for (i = 0; i < alphabet.length; i++) {
+ alphabetValues[alphabet[i]] = i;
+ }
+ for (i = 0; i < length; i++) {
+ var c = text[i];
+ if (c === "-") continue;
+ if (c in alphabetValues) {
+ if (alphabetValues[c] >= absBase) {
+ if (c === "1" && absBase === 1) continue;
+ throw new Error(c + " is not a valid digit in base " + base + ".");
+ }
+ }
+ }
+ base = parseValue(base);
+ var digits = [];
+ var isNegative = text[0] === "-";
+ for (i = isNegative ? 1 : 0; i < text.length; i++) {
+ var c = text[i];
+ if (c in alphabetValues) digits.push(parseValue(alphabetValues[c]));
+ else if (c === "<") {
+ var start = i;
+ do { i++; } while (text[i] !== ">" && i < text.length);
+ digits.push(parseValue(text.slice(start + 1, i)));
+ }
+ else throw new Error(c + " is not a valid character");
+ }
+ return parseBaseFromArray(digits, base, isNegative);
+ };
+
+ function parseBaseFromArray(digits, base, isNegative) {
+ var val = Integer[0], pow = Integer[1], i;
+ for (i = digits.length - 1; i >= 0; i--) {
+ val = val.add(digits[i].times(pow));
+ pow = pow.times(base);
+ }
+ return isNegative ? val.negate() : val;
+ }
+
+ function stringify(digit, alphabet) {
+ alphabet = alphabet || DEFAULT_ALPHABET;
+ if (digit < alphabet.length) {
+ return alphabet[digit];
+ }
+ return "<" + digit + ">";
+ }
+
+ function toBase(n, base) {
+ base = bigInt(base);
+ if (base.isZero()) {
+ if (n.isZero()) return { value: [0], isNegative: false };
+ throw new Error("Cannot convert nonzero numbers to base 0.");
+ }
+ if (base.equals(-1)) {
+ if (n.isZero()) return { value: [0], isNegative: false };
+ if (n.isNegative())
+ return {
+ value: [].concat.apply([], Array.apply(null, Array(-n.toJSNumber()))
+ .map(Array.prototype.valueOf, [1, 0])
+ ),
+ isNegative: false
+ };
+
+ var arr = Array.apply(null, Array(n.toJSNumber() - 1))
+ .map(Array.prototype.valueOf, [0, 1]);
+ arr.unshift([1]);
+ return {
+ value: [].concat.apply([], arr),
+ isNegative: false
+ };
+ }
+
+ var neg = false;
+ if (n.isNegative() && base.isPositive()) {
+ neg = true;
+ n = n.abs();
+ }
+ if (base.isUnit()) {
+ if (n.isZero()) return { value: [0], isNegative: false };
+
+ return {
+ value: Array.apply(null, Array(n.toJSNumber()))
+ .map(Number.prototype.valueOf, 1),
+ isNegative: neg
+ };
+ }
+ var out = [];
+ var left = n, divmod;
+ while (left.isNegative() || left.compareAbs(base) >= 0) {
+ divmod = left.divmod(base);
+ left = divmod.quotient;
+ var digit = divmod.remainder;
+ if (digit.isNegative()) {
+ digit = base.minus(digit).abs();
+ left = left.next();
+ }
+ out.push(digit.toJSNumber());
+ }
+ out.push(left.toJSNumber());
+ return { value: out.reverse(), isNegative: neg };
+ }
+
+ function toBaseString(n, base, alphabet) {
+ var arr = toBase(n, base);
+ return (arr.isNegative ? "-" : "") + arr.value.map(function (x) {
+ return stringify(x, alphabet);
+ }).join('');
+ }
+
+ BigInteger.prototype.toArray = function (radix) {
+ return toBase(this, radix);
+ };
+
+ SmallInteger.prototype.toArray = function (radix) {
+ return toBase(this, radix);
+ };
+
+ NativeBigInt.prototype.toArray = function (radix) {
+ return toBase(this, radix);
+ };
+
+ BigInteger.prototype.toString = function (radix, alphabet) {
+ if (radix === undefined) radix = 10;
+ if (radix !== 10 || alphabet) return toBaseString(this, radix, alphabet);
+ var v = this.value, l = v.length, str = String(v[--l]), zeros = "0000000", digit;
+ while (--l >= 0) {
+ digit = String(v[l]);
+ str += zeros.slice(digit.length) + digit;
+ }
+ var sign = this.sign ? "-" : "";
+ return sign + str;
+ };
+
+ SmallInteger.prototype.toString = function (radix, alphabet) {
+ if (radix === undefined) radix = 10;
+ if (radix != 10 || alphabet) return toBaseString(this, radix, alphabet);
+ return String(this.value);
+ };
+
+ NativeBigInt.prototype.toString = SmallInteger.prototype.toString;
+
+ NativeBigInt.prototype.toJSON = BigInteger.prototype.toJSON = SmallInteger.prototype.toJSON = function () { return this.toString(); }
+
+ BigInteger.prototype.valueOf = function () {
+ return parseInt(this.toString(), 10);
+ };
+ BigInteger.prototype.toJSNumber = BigInteger.prototype.valueOf;
+
+ SmallInteger.prototype.valueOf = function () {
+ return this.value;
+ };
+ SmallInteger.prototype.toJSNumber = SmallInteger.prototype.valueOf;
+ NativeBigInt.prototype.valueOf = NativeBigInt.prototype.toJSNumber = function () {
+ return parseInt(this.toString(), 10);
+ }
+
+ function parseStringValue(v) {
+ if (isPrecise(+v)) {
+ var x = +v;
+ if (x === truncate(x))
+ return supportsNativeBigInt ? new NativeBigInt(BigInt(x)) : new SmallInteger(x);
+ throw new Error("Invalid integer: " + v);
+ }
+ var sign = v[0] === "-";
+ if (sign) v = v.slice(1);
+ var split = v.split(/e/i);
+ if (split.length > 2) throw new Error("Invalid integer: " + split.join("e"));
+ if (split.length === 2) {
+ var exp = split[1];
+ if (exp[0] === "+") exp = exp.slice(1);
+ exp = +exp;
+ if (exp !== truncate(exp) || !isPrecise(exp)) throw new Error("Invalid integer: " + exp + " is not a valid exponent.");
+ var text = split[0];
+ var decimalPlace = text.indexOf(".");
+ if (decimalPlace >= 0) {
+ exp -= text.length - decimalPlace - 1;
+ text = text.slice(0, decimalPlace) + text.slice(decimalPlace + 1);
+ }
+ if (exp < 0) throw new Error("Cannot include negative exponent part for integers");
+ text += (new Array(exp + 1)).join("0");
+ v = text;
+ }
+ var isValid = /^([0-9][0-9]*)$/.test(v);
+ if (!isValid) throw new Error("Invalid integer: " + v);
+ if (supportsNativeBigInt) {
+ return new NativeBigInt(BigInt(sign ? "-" + v : v));
+ }
+ var r = [], max = v.length, l = LOG_BASE, min = max - l;
+ while (max > 0) {
+ r.push(+v.slice(min, max));
+ min -= l;
+ if (min < 0) min = 0;
+ max -= l;
+ }
+ trim(r);
+ return new BigInteger(r, sign);
+ }
+
+ function parseNumberValue(v) {
+ if (supportsNativeBigInt) {
+ return new NativeBigInt(BigInt(v));
+ }
+ if (isPrecise(v)) {
+ if (v !== truncate(v)) throw new Error(v + " is not an integer.");
+ return new SmallInteger(v);
+ }
+ return parseStringValue(v.toString());
+ }
+
+ function parseValue(v) {
+ if (typeof v === "number") {
+ return parseNumberValue(v);
+ }
+ if (typeof v === "string") {
+ return parseStringValue(v);
+ }
+ if (typeof v === "bigint") {
+ return new NativeBigInt(v);
+ }
+ return v;
+ }
+ // Pre-define numbers in range [-999,999]
+ for (var i = 0; i < 1000; i++) {
+ Integer[i] = parseValue(i);
+ if (i > 0) Integer[-i] = parseValue(-i);
+ }
+ // Backwards compatibility
+ Integer.one = Integer[1];
+ Integer.zero = Integer[0];
+ Integer.minusOne = Integer[-1];
+ Integer.max = max;
+ Integer.min = min;
+ Integer.gcd = gcd;
+ Integer.lcm = lcm;
+ Integer.isInstance = function (x) { return x instanceof BigInteger || x instanceof SmallInteger || x instanceof NativeBigInt; };
+ Integer.randBetween = randBetween;
+
+ Integer.fromArray = function (digits, base, isNegative) {
+ return parseBaseFromArray(digits.map(parseValue), parseValue(base || 10), isNegative);
+ };
+
+ return Integer;
+})();
+
+// Node.js check
+if (typeof module !== "undefined" && module.hasOwnProperty("exports")) {
+ module.exports = bigInt;
+}
+
+//amd check
+if (typeof define === "function" && define.amd) {
+ define( function () {
+ return bigInt;
+ });
+}
diff --git a/node_modules/big-integer/BigInteger.min.js b/node_modules/big-integer/BigInteger.min.js
new file mode 100644
index 0000000..a960fa6
--- /dev/null
+++ b/node_modules/big-integer/BigInteger.min.js
@@ -0,0 +1 @@
+var bigInt=function(undefined){"use strict";var BASE=1e7,LOG_BASE=7,MAX_INT=9007199254740992,MAX_INT_ARR=smallToArray(MAX_INT),DEFAULT_ALPHABET="0123456789abcdefghijklmnopqrstuvwxyz";var supportsNativeBigInt=typeof BigInt==="function";function Integer(v,radix,alphabet,caseSensitive){if(typeof v==="undefined")return Integer[0];if(typeof radix!=="undefined")return+radix===10&&!alphabet?parseValue(v):parseBase(v,radix,alphabet,caseSensitive);return parseValue(v)}function BigInteger(value,sign){this.value=value;this.sign=sign;this.isSmall=false}BigInteger.prototype=Object.create(Integer.prototype);function SmallInteger(value){this.value=value;this.sign=value<0;this.isSmall=true}SmallInteger.prototype=Object.create(Integer.prototype);function NativeBigInt(value){this.value=value}NativeBigInt.prototype=Object.create(Integer.prototype);function isPrecise(n){return-MAX_INT0)return Math.floor(n);return Math.ceil(n)}function add(a,b){var l_a=a.length,l_b=b.length,r=new Array(l_a),carry=0,base=BASE,sum,i;for(i=0;i=base?1:0;r[i]=sum-carry*base}while(i0)r.push(carry);return r}function addAny(a,b){if(a.length>=b.length)return add(a,b);return add(b,a)}function addSmall(a,carry){var l=a.length,r=new Array(l),base=BASE,sum,i;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}BigInteger.prototype.add=function(v){var n=parseValue(v);if(this.sign!==n.sign){return this.subtract(n.negate())}var a=this.value,b=n.value;if(n.isSmall){return new BigInteger(addSmall(a,Math.abs(b)),this.sign)}return new BigInteger(addAny(a,b),this.sign)};BigInteger.prototype.plus=BigInteger.prototype.add;SmallInteger.prototype.add=function(v){var n=parseValue(v);var a=this.value;if(a<0!==n.sign){return this.subtract(n.negate())}var b=n.value;if(n.isSmall){if(isPrecise(a+b))return new SmallInteger(a+b);b=smallToArray(Math.abs(b))}return new BigInteger(addSmall(b,Math.abs(a)),a<0)};SmallInteger.prototype.plus=SmallInteger.prototype.add;NativeBigInt.prototype.add=function(v){return new NativeBigInt(this.value+parseValue(v).value)};NativeBigInt.prototype.plus=NativeBigInt.prototype.add;function subtract(a,b){var a_l=a.length,b_l=b.length,r=new Array(a_l),borrow=0,base=BASE,i,difference;for(i=0;i=0){value=subtract(a,b)}else{value=subtract(b,a);sign=!sign}value=arrayToSmall(value);if(typeof value==="number"){if(sign)value=-value;return new SmallInteger(value)}return new BigInteger(value,sign)}function subtractSmall(a,b,sign){var l=a.length,r=new Array(l),carry=-b,base=BASE,i,difference;for(i=0;i=0)};SmallInteger.prototype.minus=SmallInteger.prototype.subtract;NativeBigInt.prototype.subtract=function(v){return new NativeBigInt(this.value-parseValue(v).value)};NativeBigInt.prototype.minus=NativeBigInt.prototype.subtract;BigInteger.prototype.negate=function(){return new BigInteger(this.value,!this.sign)};SmallInteger.prototype.negate=function(){var sign=this.sign;var small=new SmallInteger(-this.value);small.sign=!sign;return small};NativeBigInt.prototype.negate=function(){return new NativeBigInt(-this.value)};BigInteger.prototype.abs=function(){return new BigInteger(this.value,false)};SmallInteger.prototype.abs=function(){return new SmallInteger(Math.abs(this.value))};NativeBigInt.prototype.abs=function(){return new NativeBigInt(this.value>=0?this.value:-this.value)};function multiplyLong(a,b){var a_l=a.length,b_l=b.length,l=a_l+b_l,r=createArray(l),base=BASE,product,carry,i,a_i,b_j;for(i=0;i0){r[i++]=carry%base;carry=Math.floor(carry/base)}return r}function shiftLeft(x,n){var r=[];while(n-- >0)r.push(0);return r.concat(x)}function multiplyKaratsuba(x,y){var n=Math.max(x.length,y.length);if(n<=30)return multiplyLong(x,y);n=Math.ceil(n/2);var b=x.slice(n),a=x.slice(0,n),d=y.slice(n),c=y.slice(0,n);var ac=multiplyKaratsuba(a,c),bd=multiplyKaratsuba(b,d),abcd=multiplyKaratsuba(addAny(a,b),addAny(c,d));var product=addAny(addAny(ac,shiftLeft(subtract(subtract(abcd,ac),bd),n)),shiftLeft(bd,2*n));trim(product);return product}function useKaratsuba(l1,l2){return-.012*l1-.012*l2+15e-6*l1*l2>0}BigInteger.prototype.multiply=function(v){var n=parseValue(v),a=this.value,b=n.value,sign=this.sign!==n.sign,abs;if(n.isSmall){if(b===0)return Integer[0];if(b===1)return this;if(b===-1)return this.negate();abs=Math.abs(b);if(abs=0;shift--){quotientDigit=base-1;if(remainder[shift+b_l]!==divisorMostSignificantDigit){quotientDigit=Math.floor((remainder[shift+b_l]*base+remainder[shift+b_l-1])/divisorMostSignificantDigit)}carry=0;borrow=0;l=divisor.length;for(i=0;ib_l){highx=(highx+1)*base}guess=Math.ceil(highx/highy);do{check=multiplySmall(b,guess);if(compareAbs(check,part)<=0)break;guess--}while(guess);result.push(guess);part=subtract(part,check)}result.reverse();return[arrayToSmall(result),arrayToSmall(part)]}function divModSmall(value,lambda){var length=value.length,quotient=createArray(length),base=BASE,i,q,remainder,divisor;remainder=0;for(i=length-1;i>=0;--i){divisor=remainder*base+value[i];q=truncate(divisor/lambda);remainder=divisor-q*lambda;quotient[i]=q|0}return[quotient,remainder|0]}function divModAny(self,v){var value,n=parseValue(v);if(supportsNativeBigInt){return[new NativeBigInt(self.value/n.value),new NativeBigInt(self.value%n.value)]}var a=self.value,b=n.value;var quotient;if(b===0)throw new Error("Cannot divide by zero");if(self.isSmall){if(n.isSmall){return[new SmallInteger(truncate(a/b)),new SmallInteger(a%b)]}return[Integer[0],self]}if(n.isSmall){if(b===1)return[self,Integer[0]];if(b==-1)return[self.negate(),Integer[0]];var abs=Math.abs(b);if(absb.length?1:-1}for(var i=a.length-1;i>=0;i--){if(a[i]!==b[i])return a[i]>b[i]?1:-1}return 0}BigInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall)return 1;return compareAbs(a,b)};SmallInteger.prototype.compareAbs=function(v){var n=parseValue(v),a=Math.abs(this.value),b=n.value;if(n.isSmall){b=Math.abs(b);return a===b?0:a>b?1:-1}return-1};NativeBigInt.prototype.compareAbs=function(v){var a=this.value;var b=parseValue(v).value;a=a>=0?a:-a;b=b>=0?b:-b;return a===b?0:a>b?1:-1};BigInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(this.sign!==n.sign){return n.sign?1:-1}if(n.isSmall){return this.sign?-1:1}return compareAbs(a,b)*(this.sign?-1:1)};BigInteger.prototype.compareTo=BigInteger.prototype.compare;SmallInteger.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var n=parseValue(v),a=this.value,b=n.value;if(n.isSmall){return a==b?0:a>b?1:-1}if(a<0!==n.sign){return a<0?-1:1}return a<0?1:-1};SmallInteger.prototype.compareTo=SmallInteger.prototype.compare;NativeBigInt.prototype.compare=function(v){if(v===Infinity){return-1}if(v===-Infinity){return 1}var a=this.value;var b=parseValue(v).value;return a===b?0:a>b?1:-1};NativeBigInt.prototype.compareTo=NativeBigInt.prototype.compare;BigInteger.prototype.equals=function(v){return this.compare(v)===0};NativeBigInt.prototype.eq=NativeBigInt.prototype.equals=SmallInteger.prototype.eq=SmallInteger.prototype.equals=BigInteger.prototype.eq=BigInteger.prototype.equals;BigInteger.prototype.notEquals=function(v){return this.compare(v)!==0};NativeBigInt.prototype.neq=NativeBigInt.prototype.notEquals=SmallInteger.prototype.neq=SmallInteger.prototype.notEquals=BigInteger.prototype.neq=BigInteger.prototype.notEquals;BigInteger.prototype.greater=function(v){return this.compare(v)>0};NativeBigInt.prototype.gt=NativeBigInt.prototype.greater=SmallInteger.prototype.gt=SmallInteger.prototype.greater=BigInteger.prototype.gt=BigInteger.prototype.greater;BigInteger.prototype.lesser=function(v){return this.compare(v)<0};NativeBigInt.prototype.lt=NativeBigInt.prototype.lesser=SmallInteger.prototype.lt=SmallInteger.prototype.lesser=BigInteger.prototype.lt=BigInteger.prototype.lesser;BigInteger.prototype.greaterOrEquals=function(v){return this.compare(v)>=0};NativeBigInt.prototype.geq=NativeBigInt.prototype.greaterOrEquals=SmallInteger.prototype.geq=SmallInteger.prototype.greaterOrEquals=BigInteger.prototype.geq=BigInteger.prototype.greaterOrEquals;BigInteger.prototype.lesserOrEquals=function(v){return this.compare(v)<=0};NativeBigInt.prototype.leq=NativeBigInt.prototype.lesserOrEquals=SmallInteger.prototype.leq=SmallInteger.prototype.lesserOrEquals=BigInteger.prototype.leq=BigInteger.prototype.lesserOrEquals;BigInteger.prototype.isEven=function(){return(this.value[0]&1)===0};SmallInteger.prototype.isEven=function(){return(this.value&1)===0};NativeBigInt.prototype.isEven=function(){return(this.value&BigInt(1))===BigInt(0)};BigInteger.prototype.isOdd=function(){return(this.value[0]&1)===1};SmallInteger.prototype.isOdd=function(){return(this.value&1)===1};NativeBigInt.prototype.isOdd=function(){return(this.value&BigInt(1))===BigInt(1)};BigInteger.prototype.isPositive=function(){return!this.sign};SmallInteger.prototype.isPositive=function(){return this.value>0};NativeBigInt.prototype.isPositive=SmallInteger.prototype.isPositive;BigInteger.prototype.isNegative=function(){return this.sign};SmallInteger.prototype.isNegative=function(){return this.value<0};NativeBigInt.prototype.isNegative=SmallInteger.prototype.isNegative;BigInteger.prototype.isUnit=function(){return false};SmallInteger.prototype.isUnit=function(){return Math.abs(this.value)===1};NativeBigInt.prototype.isUnit=function(){return this.abs().value===BigInt(1)};BigInteger.prototype.isZero=function(){return false};SmallInteger.prototype.isZero=function(){return this.value===0};NativeBigInt.prototype.isZero=function(){return this.value===BigInt(0)};BigInteger.prototype.isDivisibleBy=function(v){var n=parseValue(v);if(n.isZero())return false;if(n.isUnit())return true;if(n.compareAbs(2)===0)return this.isEven();return this.mod(n).isZero()};NativeBigInt.prototype.isDivisibleBy=SmallInteger.prototype.isDivisibleBy=BigInteger.prototype.isDivisibleBy;function isBasicPrime(v){var n=v.abs();if(n.isUnit())return false;if(n.equals(2)||n.equals(3)||n.equals(5))return true;if(n.isEven()||n.isDivisibleBy(3)||n.isDivisibleBy(5))return false;if(n.lesser(49))return true}function millerRabinTest(n,a){var nPrev=n.prev(),b=nPrev,r=0,d,t,i,x;while(b.isEven())b=b.divide(2),r++;next:for(i=0;i-MAX_INT)return new SmallInteger(value-1);return new BigInteger(MAX_INT_ARR,true)};NativeBigInt.prototype.prev=function(){return new NativeBigInt(this.value-BigInt(1))};var powersOfTwo=[1];while(2*powersOfTwo[powersOfTwo.length-1]<=BASE)powersOfTwo.push(2*powersOfTwo[powersOfTwo.length-1]);var powers2Length=powersOfTwo.length,highestPower2=powersOfTwo[powers2Length-1];function shift_isSmall(n){return Math.abs(n)<=BASE}BigInteger.prototype.shiftLeft=function(v){var n=parseValue(v).toJSNumber();if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}if(n<0)return this.shiftRight(-n);var result=this;if(result.isZero())return result;while(n>=powers2Length){result=result.multiply(highestPower2);n-=powers2Length-1}return result.multiply(powersOfTwo[n])};NativeBigInt.prototype.shiftLeft=SmallInteger.prototype.shiftLeft=BigInteger.prototype.shiftLeft;BigInteger.prototype.shiftRight=function(v){var remQuo;var n=parseValue(v).toJSNumber();if(!shift_isSmall(n)){throw new Error(String(n)+" is too large for shifting.")}if(n<0)return this.shiftLeft(-n);var result=this;while(n>=powers2Length){if(result.isZero()||result.isNegative()&&result.isUnit())return result;remQuo=divModAny(result,highestPower2);result=remQuo[1].isNegative()?remQuo[0].prev():remQuo[0];n-=powers2Length-1}remQuo=divModAny(result,powersOfTwo[n]);return remQuo[1].isNegative()?remQuo[0].prev():remQuo[0]};NativeBigInt.prototype.shiftRight=SmallInteger.prototype.shiftRight=BigInteger.prototype.shiftRight;function bitwise(x,y,fn){y=parseValue(y);var xSign=x.isNegative(),ySign=y.isNegative();var xRem=xSign?x.not():x,yRem=ySign?y.not():y;var xDigit=0,yDigit=0;var xDivMod=null,yDivMod=null;var result=[];while(!xRem.isZero()||!yRem.isZero()){xDivMod=divModAny(xRem,highestPower2);xDigit=xDivMod[1].toJSNumber();if(xSign){xDigit=highestPower2-1-xDigit}yDivMod=divModAny(yRem,highestPower2);yDigit=yDivMod[1].toJSNumber();if(ySign){yDigit=highestPower2-1-yDigit}xRem=xDivMod[0];yRem=yDivMod[0];result.push(fn(xDigit,yDigit))}var sum=fn(xSign?1:0,ySign?1:0)!==0?bigInt(-1):bigInt(0);for(var i=result.length-1;i>=0;i-=1){sum=sum.multiply(highestPower2).add(bigInt(result[i]))}return sum}BigInteger.prototype.not=function(){return this.negate().prev()};NativeBigInt.prototype.not=SmallInteger.prototype.not=BigInteger.prototype.not;BigInteger.prototype.and=function(n){return bitwise(this,n,function(a,b){return a&b})};NativeBigInt.prototype.and=SmallInteger.prototype.and=BigInteger.prototype.and;BigInteger.prototype.or=function(n){return bitwise(this,n,function(a,b){return a|b})};NativeBigInt.prototype.or=SmallInteger.prototype.or=BigInteger.prototype.or;BigInteger.prototype.xor=function(n){return bitwise(this,n,function(a,b){return a^b})};NativeBigInt.prototype.xor=SmallInteger.prototype.xor=BigInteger.prototype.xor;var LOBMASK_I=1<<30,LOBMASK_BI=(BASE&-BASE)*(BASE&-BASE)|LOBMASK_I;function roughLOB(n){var v=n.value,x=typeof v==="number"?v|LOBMASK_I:typeof v==="bigint"?v|BigInt(LOBMASK_I):v[0]+v[1]*BASE|LOBMASK_BI;return x&-x}function integerLogarithm(value,base){if(base.compareTo(value)<=0){var tmp=integerLogarithm(value,base.square(base));var p=tmp.p;var e=tmp.e;var t=p.multiply(base);return t.compareTo(value)<=0?{p:t,e:e*2+1}:{p:p,e:e*2}}return{p:bigInt(1),e:0}}BigInteger.prototype.bitLength=function(){var n=this;if(n.compareTo(bigInt(0))<0){n=n.negate().subtract(bigInt(1))}if(n.compareTo(bigInt(0))===0){return bigInt(0)}return bigInt(integerLogarithm(n,bigInt(2)).e).add(bigInt(1))};NativeBigInt.prototype.bitLength=SmallInteger.prototype.bitLength=BigInteger.prototype.bitLength;function max(a,b){a=parseValue(a);b=parseValue(b);return a.greater(b)?a:b}function min(a,b){a=parseValue(a);b=parseValue(b);return a.lesser(b)?a:b}function gcd(a,b){a=parseValue(a).abs();b=parseValue(b).abs();if(a.equals(b))return a;if(a.isZero())return b;if(b.isZero())return a;var c=Integer[1],d,t;while(a.isEven()&&b.isEven()){d=min(roughLOB(a),roughLOB(b));a=a.divide(d);b=b.divide(d);c=c.multiply(d)}while(a.isEven()){a=a.divide(roughLOB(a))}do{while(b.isEven()){b=b.divide(roughLOB(b))}if(a.greater(b)){t=b;b=a;a=t}b=b.subtract(a)}while(!b.isZero());return c.isUnit()?a:a.multiply(c)}function lcm(a,b){a=parseValue(a).abs();b=parseValue(b).abs();return a.divide(gcd(a,b)).multiply(b)}function randBetween(a,b,rng){a=parseValue(a);b=parseValue(b);var usedRNG=rng||Math.random;var low=min(a,b),high=max(a,b);var range=high.subtract(low).add(1);if(range.isSmall)return low.add(Math.floor(usedRNG()*range));var digits=toBase(range,BASE).value;var result=[],restricted=true;for(var i=0;i=absBase){if(c==="1"&&absBase===1)continue;throw new Error(c+" is not a valid digit in base "+base+".")}}}base=parseValue(base);var digits=[];var isNegative=text[0]==="-";for(i=isNegative?1:0;i"&&i=0;i--){val=val.add(digits[i].times(pow));pow=pow.times(base)}return isNegative?val.negate():val}function stringify(digit,alphabet){alphabet=alphabet||DEFAULT_ALPHABET;if(digit"}function toBase(n,base){base=bigInt(base);if(base.isZero()){if(n.isZero())return{value:[0],isNegative:false};throw new Error("Cannot convert nonzero numbers to base 0.")}if(base.equals(-1)){if(n.isZero())return{value:[0],isNegative:false};if(n.isNegative())return{value:[].concat.apply([],Array.apply(null,Array(-n.toJSNumber())).map(Array.prototype.valueOf,[1,0])),isNegative:false};var arr=Array.apply(null,Array(n.toJSNumber()-1)).map(Array.prototype.valueOf,[0,1]);arr.unshift([1]);return{value:[].concat.apply([],arr),isNegative:false}}var neg=false;if(n.isNegative()&&base.isPositive()){neg=true;n=n.abs()}if(base.isUnit()){if(n.isZero())return{value:[0],isNegative:false};return{value:Array.apply(null,Array(n.toJSNumber())).map(Number.prototype.valueOf,1),isNegative:neg}}var out=[];var left=n,divmod;while(left.isNegative()||left.compareAbs(base)>=0){divmod=left.divmod(base);left=divmod.quotient;var digit=divmod.remainder;if(digit.isNegative()){digit=base.minus(digit).abs();left=left.next()}out.push(digit.toJSNumber())}out.push(left.toJSNumber());return{value:out.reverse(),isNegative:neg}}function toBaseString(n,base,alphabet){var arr=toBase(n,base);return(arr.isNegative?"-":"")+arr.value.map(function(x){return stringify(x,alphabet)}).join("")}BigInteger.prototype.toArray=function(radix){return toBase(this,radix)};SmallInteger.prototype.toArray=function(radix){return toBase(this,radix)};NativeBigInt.prototype.toArray=function(radix){return toBase(this,radix)};BigInteger.prototype.toString=function(radix,alphabet){if(radix===undefined)radix=10;if(radix!==10||alphabet)return toBaseString(this,radix,alphabet);var v=this.value,l=v.length,str=String(v[--l]),zeros="0000000",digit;while(--l>=0){digit=String(v[l]);str+=zeros.slice(digit.length)+digit}var sign=this.sign?"-":"";return sign+str};SmallInteger.prototype.toString=function(radix,alphabet){if(radix===undefined)radix=10;if(radix!=10||alphabet)return toBaseString(this,radix,alphabet);return String(this.value)};NativeBigInt.prototype.toString=SmallInteger.prototype.toString;NativeBigInt.prototype.toJSON=BigInteger.prototype.toJSON=SmallInteger.prototype.toJSON=function(){return this.toString()};BigInteger.prototype.valueOf=function(){return parseInt(this.toString(),10)};BigInteger.prototype.toJSNumber=BigInteger.prototype.valueOf;SmallInteger.prototype.valueOf=function(){return this.value};SmallInteger.prototype.toJSNumber=SmallInteger.prototype.valueOf;NativeBigInt.prototype.valueOf=NativeBigInt.prototype.toJSNumber=function(){return parseInt(this.toString(),10)};function parseStringValue(v){if(isPrecise(+v)){var x=+v;if(x===truncate(x))return supportsNativeBigInt?new NativeBigInt(BigInt(x)):new SmallInteger(x);throw new Error("Invalid integer: "+v)}var sign=v[0]==="-";if(sign)v=v.slice(1);var split=v.split(/e/i);if(split.length>2)throw new Error("Invalid integer: "+split.join("e"));if(split.length===2){var exp=split[1];if(exp[0]==="+")exp=exp.slice(1);exp=+exp;if(exp!==truncate(exp)||!isPrecise(exp))throw new Error("Invalid integer: "+exp+" is not a valid exponent.");var text=split[0];var decimalPlace=text.indexOf(".");if(decimalPlace>=0){exp-=text.length-decimalPlace-1;text=text.slice(0,decimalPlace)+text.slice(decimalPlace+1)}if(exp<0)throw new Error("Cannot include negative exponent part for integers");text+=new Array(exp+1).join("0");v=text}var isValid=/^([0-9][0-9]*)$/.test(v);if(!isValid)throw new Error("Invalid integer: "+v);if(supportsNativeBigInt){return new NativeBigInt(BigInt(sign?"-"+v:v))}var r=[],max=v.length,l=LOG_BASE,min=max-l;while(max>0){r.push(+v.slice(min,max));min-=l;if(min<0)min=0;max-=l}trim(r);return new BigInteger(r,sign)}function parseNumberValue(v){if(supportsNativeBigInt){return new NativeBigInt(BigInt(v))}if(isPrecise(v)){if(v!==truncate(v))throw new Error(v+" is not an integer.");return new SmallInteger(v)}return parseStringValue(v.toString())}function parseValue(v){if(typeof v==="number"){return parseNumberValue(v)}if(typeof v==="string"){return parseStringValue(v)}if(typeof v==="bigint"){return new NativeBigInt(v)}return v}for(var i=0;i<1e3;i++){Integer[i]=parseValue(i);if(i>0)Integer[-i]=parseValue(-i)}Integer.one=Integer[1];Integer.zero=Integer[0];Integer.minusOne=Integer[-1];Integer.max=max;Integer.min=min;Integer.gcd=gcd;Integer.lcm=lcm;Integer.isInstance=function(x){return x instanceof BigInteger||x instanceof SmallInteger||x instanceof NativeBigInt};Integer.randBetween=randBetween;Integer.fromArray=function(digits,base,isNegative){return parseBaseFromArray(digits.map(parseValue),parseValue(base||10),isNegative)};return Integer}();if(typeof module!=="undefined"&&module.hasOwnProperty("exports")){module.exports=bigInt}if(typeof define==="function"&&define.amd){define(function(){return bigInt})}
\ No newline at end of file
diff --git a/node_modules/big-integer/LICENSE b/node_modules/big-integer/LICENSE
new file mode 100644
index 0000000..cf1ab25
--- /dev/null
+++ b/node_modules/big-integer/LICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
diff --git a/node_modules/big-integer/README.md b/node_modules/big-integer/README.md
new file mode 100644
index 0000000..d72420f
--- /dev/null
+++ b/node_modules/big-integer/README.md
@@ -0,0 +1,589 @@
+# BigInteger.js [![Build Status][travis-img]][travis-url] [![Coverage Status][coveralls-img]][coveralls-url] [![Monthly Downloads][downloads-img]][downloads-url]
+
+[travis-url]: https://travis-ci.org/peterolson/BigInteger.js
+[travis-img]: https://travis-ci.org/peterolson/BigInteger.js.svg?branch=master
+[coveralls-url]: https://coveralls.io/github/peterolson/BigInteger.js?branch=master
+[coveralls-img]: https://coveralls.io/repos/peterolson/BigInteger.js/badge.svg?branch=master&service=github
+[downloads-url]: https://www.npmjs.com/package/big-integer
+[downloads-img]: https://img.shields.io/npm/dm/big-integer.svg
+
+**BigInteger.js** is an arbitrary-length integer library for Javascript, allowing arithmetic operations on integers of unlimited size, notwithstanding memory and time limitations.
+
+**Update (December 2, 2018):** [`BigInt` is being added as a native feature of JavaScript](https://tc39.github.io/proposal-bigint/). This library now works as a polyfill: if the environment supports the native `BigInt`, this library acts as a thin wrapper over the native implementation.
+
+## Installation
+
+If you are using a browser, you can download [BigInteger.js from GitHub](http://peterolson.github.com/BigInteger.js/BigInteger.min.js) or just hotlink to it:
+
+
+
+If you are using node, you can install BigInteger with [npm](https://npmjs.org/).
+
+ npm install big-integer
+
+Then you can include it in your code:
+
+ var bigInt = require("big-integer");
+
+
+## Usage
+### `bigInt(number, [base], [alphabet], [caseSensitive])`
+
+You can create a bigInt by calling the `bigInt` function. You can pass in
+
+ - a string, which it will parse as an bigInt and throw an `"Invalid integer"` error if the parsing fails.
+ - a Javascript number, which it will parse as an bigInt and throw an `"Invalid integer"` error if the parsing fails.
+ - another bigInt.
+ - nothing, and it will return `bigInt.zero`.
+
+ If you provide a second parameter, then it will parse `number` as a number in base `base`. Note that `base` can be any bigInt (even negative or zero). The letters "a-z" and "A-Z" will be interpreted as the numbers 10 to 35. Higher digits can be specified in angle brackets (`<` and `>`). The default `base` is `10`.
+
+ You can specify a custom alphabet for base conversion with the third parameter. The default `alphabet` is `"0123456789abcdefghijklmnopqrstuvwxyz"`.
+
+ The fourth parameter specifies whether or not the number string should be case-sensitive, i.e. whether `a` and `A` should be treated as different digits. By default `caseSensitive` is `false`.
+
+Examples:
+
+ var zero = bigInt();
+ var ninetyThree = bigInt(93);
+ var largeNumber = bigInt("75643564363473453456342378564387956906736546456235345");
+ var googol = bigInt("1e100");
+ var bigNumber = bigInt(largeNumber);
+
+ var maximumByte = bigInt("FF", 16);
+ var fiftyFiveGoogol = bigInt("<55>0", googol);
+
+Note that Javascript numbers larger than `9007199254740992` and smaller than `-9007199254740992` are not precisely represented numbers and will not produce exact results. If you are dealing with numbers outside that range, it is better to pass in strings.
+
+### Method Chaining
+
+Note that bigInt operations return bigInts, which allows you to chain methods, for example:
+
+ var salary = bigInt(dollarsPerHour).times(hoursWorked).plus(randomBonuses)
+
+### Constants
+
+There are three named constants already stored that you do not have to construct with the `bigInt` function yourself:
+
+ - `bigInt.one`, equivalent to `bigInt(1)`
+ - `bigInt.zero`, equivalent to `bigInt(0)`
+ - `bigInt.minusOne`, equivalent to `bigInt(-1)`
+
+The numbers from -999 to 999 are also already prestored and can be accessed using `bigInt[index]`, for example:
+
+ - `bigInt[-999]`, equivalent to `bigInt(-999)`
+ - `bigInt[256]`, equivalent to `bigInt(256)`
+
+### Methods
+
+#### `abs()`
+
+Returns the absolute value of a bigInt.
+
+ - `bigInt(-45).abs()` => `45`
+ - `bigInt(45).abs()` => `45`
+
+#### `add(number)`
+
+Performs addition.
+
+ - `bigInt(5).add(7)` => `12`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Addition)
+
+#### `and(number)`
+
+Performs the bitwise AND operation. The operands are treated as if they were represented using [two's complement representation](http://en.wikipedia.org/wiki/Two%27s_complement).
+
+ - `bigInt(6).and(3)` => `2`
+ - `bigInt(6).and(-3)` => `4`
+
+#### `bitLength()`
+
+Returns the number of digits required to represent a bigInt in binary.
+
+ - `bigInt(5)` => `3` (since 5 is `101` in binary, which is three digits long)
+
+#### `compare(number)`
+
+Performs a comparison between two numbers. If the numbers are equal, it returns `0`. If the first number is greater, it returns `1`. If the first number is lesser, it returns `-1`.
+
+ - `bigInt(5).compare(5)` => `0`
+ - `bigInt(5).compare(4)` => `1`
+ - `bigInt(4).compare(5)` => `-1`
+
+#### `compareAbs(number)`
+
+Performs a comparison between the absolute value of two numbers.
+
+ - `bigInt(5).compareAbs(-5)` => `0`
+ - `bigInt(5).compareAbs(4)` => `1`
+ - `bigInt(4).compareAbs(-5)` => `-1`
+
+#### `compareTo(number)`
+
+Alias for the `compare` method.
+
+#### `divide(number)`
+
+Performs integer division, disregarding the remainder.
+
+ - `bigInt(59).divide(5)` => `11`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Division)
+
+#### `divmod(number)`
+
+Performs division and returns an object with two properties: `quotient` and `remainder`. The sign of the remainder will match the sign of the dividend.
+
+ - `bigInt(59).divmod(5)` => `{quotient: bigInt(11), remainder: bigInt(4) }`
+ - `bigInt(-5).divmod(2)` => `{quotient: bigInt(-2), remainder: bigInt(-1) }`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Division)
+
+#### `eq(number)`
+
+Alias for the `equals` method.
+
+#### `equals(number)`
+
+Checks if two numbers are equal.
+
+ - `bigInt(5).equals(5)` => `true`
+ - `bigInt(4).equals(7)` => `false`
+
+#### `geq(number)`
+
+Alias for the `greaterOrEquals` method.
+
+
+#### `greater(number)`
+
+Checks if the first number is greater than the second.
+
+ - `bigInt(5).greater(6)` => `false`
+ - `bigInt(5).greater(5)` => `false`
+ - `bigInt(5).greater(4)` => `true`
+
+#### `greaterOrEquals(number)`
+
+Checks if the first number is greater than or equal to the second.
+
+ - `bigInt(5).greaterOrEquals(6)` => `false`
+ - `bigInt(5).greaterOrEquals(5)` => `true`
+ - `bigInt(5).greaterOrEquals(4)` => `true`
+
+#### `gt(number)`
+
+Alias for the `greater` method.
+
+#### `isDivisibleBy(number)`
+
+Returns `true` if the first number is divisible by the second number, `false` otherwise.
+
+ - `bigInt(999).isDivisibleBy(333)` => `true`
+ - `bigInt(99).isDivisibleBy(5)` => `false`
+
+#### `isEven()`
+
+Returns `true` if the number is even, `false` otherwise.
+
+ - `bigInt(6).isEven()` => `true`
+ - `bigInt(3).isEven()` => `false`
+
+#### `isNegative()`
+
+Returns `true` if the number is negative, `false` otherwise.
+Returns `false` for `0` and `-0`.
+
+ - `bigInt(-23).isNegative()` => `true`
+ - `bigInt(50).isNegative()` => `false`
+
+#### `isOdd()`
+
+Returns `true` if the number is odd, `false` otherwise.
+
+ - `bigInt(13).isOdd()` => `true`
+ - `bigInt(40).isOdd()` => `false`
+
+#### `isPositive()`
+
+Return `true` if the number is positive, `false` otherwise.
+Returns `false` for `0` and `-0`.
+
+ - `bigInt(54).isPositive()` => `true`
+ - `bigInt(-1).isPositive()` => `false`
+
+#### `isPrime(strict?)`
+
+Returns `true` if the number is prime, `false` otherwise.
+Set "strict" boolean to true to force GRH-supported lower bound of 2*log(N)^2.
+
+ - `bigInt(5).isPrime()` => `true`
+ - `bigInt(6).isPrime()` => `false`
+
+#### `isProbablePrime([iterations], [rng])`
+
+Returns `true` if the number is very likely to be prime, `false` otherwise.
+Supplying `iterations` is optional - it determines the number of iterations of the test (default: `5`). The more iterations, the lower chance of getting a false positive.
+This uses the [Miller Rabin test](https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test).
+
+ - `bigInt(5).isProbablePrime()` => `true`
+ - `bigInt(49).isProbablePrime()` => `false`
+ - `bigInt(1729).isProbablePrime()` => `false`
+
+Note that this function is not deterministic, since it relies on random sampling of factors, so the result for some numbers is not always the same - unless you pass a predictable random number generator as `rng`. The behavior and requirements are the same as with `randBetween`.
+
+ - `bigInt(1729).isProbablePrime(1, () => 0.1)` => `false`
+ - `bigInt(1729).isProbablePrime(1, () => 0.2)` => `true`
+
+If the number is composite then the Miller–Rabin primality test declares the number probably prime with a probability at most `4` to the power `−iterations`.
+If the number is prime, this function always returns `true`.
+
+#### `isUnit()`
+
+Returns `true` if the number is `1` or `-1`, `false` otherwise.
+
+ - `bigInt.one.isUnit()` => `true`
+ - `bigInt.minusOne.isUnit()` => `true`
+ - `bigInt(5).isUnit()` => `false`
+
+#### `isZero()`
+
+Return `true` if the number is `0` or `-0`, `false` otherwise.
+
+ - `bigInt.zero.isZero()` => `true`
+ - `bigInt("-0").isZero()` => `true`
+ - `bigInt(50).isZero()` => `false`
+
+#### `leq(number)`
+
+Alias for the `lesserOrEquals` method.
+
+#### `lesser(number)`
+
+Checks if the first number is lesser than the second.
+
+ - `bigInt(5).lesser(6)` => `true`
+ - `bigInt(5).lesser(5)` => `false`
+ - `bigInt(5).lesser(4)` => `false`
+
+#### `lesserOrEquals(number)`
+
+Checks if the first number is less than or equal to the second.
+
+ - `bigInt(5).lesserOrEquals(6)` => `true`
+ - `bigInt(5).lesserOrEquals(5)` => `true`
+ - `bigInt(5).lesserOrEquals(4)` => `false`
+
+#### `lt(number)`
+
+Alias for the `lesser` method.
+
+#### `minus(number)`
+
+Alias for the `subtract` method.
+
+ - `bigInt(3).minus(5)` => `-2`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Subtraction)
+
+#### `mod(number)`
+
+Performs division and returns the remainder, disregarding the quotient. The sign of the remainder will match the sign of the dividend.
+
+ - `bigInt(59).mod(5)` => `4`
+ - `bigInt(-5).mod(2)` => `-1`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Division)
+
+#### `modInv(mod)`
+
+Finds the [multiplicative inverse](https://en.wikipedia.org/wiki/Modular_multiplicative_inverse) of the number modulo `mod`.
+
+ - `bigInt(3).modInv(11)` => `4`
+ - `bigInt(42).modInv(2017)` => `1969`
+
+#### `modPow(exp, mod)`
+
+Takes the number to the power `exp` modulo `mod`.
+
+ - `bigInt(10).modPow(3, 30)` => `10`
+
+#### `multiply(number)`
+
+Performs multiplication.
+
+ - `bigInt(111).multiply(111)` => `12321`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Multiplication)
+
+#### `neq(number)`
+
+Alias for the `notEquals` method.
+
+#### `next()`
+
+Adds one to the number.
+
+ - `bigInt(6).next()` => `7`
+
+#### `not()`
+
+Performs the bitwise NOT operation. The operands are treated as if they were represented using [two's complement representation](http://en.wikipedia.org/wiki/Two%27s_complement).
+
+ - `bigInt(10).not()` => `-11`
+ - `bigInt(0).not()` => `-1`
+
+#### `notEquals(number)`
+
+Checks if two numbers are not equal.
+
+ - `bigInt(5).notEquals(5)` => `false`
+ - `bigInt(4).notEquals(7)` => `true`
+
+#### `or(number)`
+
+Performs the bitwise OR operation. The operands are treated as if they were represented using [two's complement representation](http://en.wikipedia.org/wiki/Two%27s_complement).
+
+ - `bigInt(13).or(10)` => `15`
+ - `bigInt(13).or(-8)` => `-3`
+
+#### `over(number)`
+
+Alias for the `divide` method.
+
+ - `bigInt(59).over(5)` => `11`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Division)
+
+#### `plus(number)`
+
+Alias for the `add` method.
+
+ - `bigInt(5).plus(7)` => `12`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Addition)
+
+#### `pow(number)`
+
+Performs exponentiation. If the exponent is less than `0`, `pow` returns `0`. `bigInt.zero.pow(0)` returns `1`.
+
+ - `bigInt(16).pow(16)` => `18446744073709551616`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Exponentiation)
+
+#### `prev(number)`
+
+Subtracts one from the number.
+
+ - `bigInt(6).prev()` => `5`
+
+#### `remainder(number)`
+
+Alias for the `mod` method.
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Division)
+
+#### `shiftLeft(n)`
+
+Shifts the number left by `n` places in its binary representation. If a negative number is provided, it will shift right. Throws an error if `n` is outside of the range `[-9007199254740992, 9007199254740992]`.
+
+ - `bigInt(8).shiftLeft(2)` => `32`
+ - `bigInt(8).shiftLeft(-2)` => `2`
+
+#### `shiftRight(n)`
+
+Shifts the number right by `n` places in its binary representation. If a negative number is provided, it will shift left. Throws an error if `n` is outside of the range `[-9007199254740992, 9007199254740992]`.
+
+ - `bigInt(8).shiftRight(2)` => `2`
+ - `bigInt(8).shiftRight(-2)` => `32`
+
+#### `square()`
+
+Squares the number
+
+ - `bigInt(3).square()` => `9`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Squaring)
+
+#### `subtract(number)`
+
+Performs subtraction.
+
+ - `bigInt(3).subtract(5)` => `-2`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Subtraction)
+
+#### `times(number)`
+
+Alias for the `multiply` method.
+
+ - `bigInt(111).times(111)` => `12321`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#Multiplication)
+
+#### `toArray(radix)`
+
+Converts a bigInt into an object with the properties "value" and "isNegative." "Value" is an array of integers modulo the given radix. "isNegative" is a boolean that represents the sign of the result.
+
+ - `bigInt("1e9").toArray(10)` => {
+ value: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ isNegative: false
+ }
+ - `bigInt("1e9").toArray(16)` => {
+ value: [3, 11, 9, 10, 12, 10, 0, 0],
+ isNegative: false
+ }
+ - `bigInt(567890).toArray(100)` => {
+ value: [56, 78, 90],
+ isNegative: false
+ }
+
+Negative bases are supported.
+
+ - `bigInt(12345).toArray(-10)` => {
+ value: [2, 8, 4, 6, 5],
+ isNegative: false
+ }
+
+Base 1 and base -1 are also supported.
+
+ - `bigInt(-15).toArray(1)` => {
+ value: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
+ isNegative: true
+ }
+ - `bigInt(-15).toArray(-1)` => {
+ value: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
+ isNegative: false
+ }
+
+Base 0 is only allowed for the number zero.
+
+ - `bigInt(0).toArray(0)` => {
+ value: [0],
+ isNegative: false
+ }
+ - `bigInt(1).toArray(0)` => `Error: Cannot convert nonzero numbers to base 0.`
+
+#### `toJSNumber()`
+
+Converts a bigInt into a native Javascript number. Loses precision for numbers outside the range `[-9007199254740992, 9007199254740992]`.
+
+ - `bigInt("18446744073709551616").toJSNumber()` => `18446744073709552000`
+
+#### `xor(number)`
+
+Performs the bitwise XOR operation. The operands are treated as if they were represented using [two's complement representation](http://en.wikipedia.org/wiki/Two%27s_complement).
+
+ - `bigInt(12).xor(5)` => `9`
+ - `bigInt(12).xor(-5)` => `-9`
+
+### Static Methods
+
+#### `fromArray(digits, base = 10, isNegative?)`
+
+Constructs a bigInt from an array of digits in base `base`. The optional `isNegative` flag will make the number negative.
+
+ - `bigInt.fromArray([1, 2, 3, 4, 5], 10)` => `12345`
+ - `bigInt.fromArray([1, 0, 0], 2, true)` => `-4`
+
+#### `gcd(a, b)`
+
+Finds the greatest common denominator of `a` and `b`.
+
+ - `bigInt.gcd(42,56)` => `14`
+
+#### `isInstance(x)`
+
+Returns `true` if `x` is a BigInteger, `false` otherwise.
+
+ - `bigInt.isInstance(bigInt(14))` => `true`
+ - `bigInt.isInstance(14)` => `false`
+
+#### `lcm(a,b)`
+
+Finds the least common multiple of `a` and `b`.
+
+ - `bigInt.lcm(21, 6)` => `42`
+
+#### `max(a,b)`
+
+Returns the largest of `a` and `b`.
+
+ - `bigInt.max(77, 432)` => `432`
+
+#### `min(a,b)`
+
+Returns the smallest of `a` and `b`.
+
+ - `bigInt.min(77, 432)` => `77`
+
+#### `randBetween(min, max, [rng])`
+
+Returns a random number between `min` and `max`, optionally using `rng` to generate randomness.
+
+ - `bigInt.randBetween("-1e100", "1e100")` => (for example) `8494907165436643479673097939554427056789510374838494147955756275846226209006506706784609314471378745`
+
+`rng` should take no arguments and return a `number` between 0 and 1. It defaults to `Math.random`.
+
+ - `bigInt.randBetween("-1e100", "1e100", () => 0.5)` => (always) `50000005000000500000050000005000000500000050000005000000500000050000005000000500000050000005000000`
+
+
+### Override Methods
+
+#### `toString(radix = 10, [alphabet])`
+
+Converts a bigInt to a string. There is an optional radix parameter (which defaults to 10) that converts the number to the given radix. Digits in the range `10-35` will use the letters `a-z`.
+
+ - `bigInt("1e9").toString()` => `"1000000000"`
+ - `bigInt("1e9").toString(16)` => `"3b9aca00"`
+
+ You can use a custom base alphabet with the second parameter. The default `alphabet` is `"0123456789abcdefghijklmnopqrstuvwxyz"`.
+
+ - `bigInt("5").toString(2, "aA")` => `"AaA"`
+
+**Note that arithmetical operators will trigger the `valueOf` function rather than the `toString` function.** When converting a bigInteger to a string, you should use the `toString` method or the `String` function instead of adding the empty string.
+
+ - `bigInt("999999999999999999").toString()` => `"999999999999999999"`
+ - `String(bigInt("999999999999999999"))` => `"999999999999999999"`
+ - `bigInt("999999999999999999") + ""` => `1000000000000000000`
+
+Bases larger than 36 are supported. If a digit is greater than or equal to 36, it will be enclosed in angle brackets.
+
+ - `bigInt(567890).toString(100)` => `"<56><78><90>"`
+
+Negative bases are also supported.
+
+ - `bigInt(12345).toString(-10)` => `"28465"`
+
+Base 1 and base -1 are also supported.
+
+ - `bigInt(-15).toString(1)` => `"-111111111111111"`
+ - `bigInt(-15).toString(-1)` => `"101010101010101010101010101010"`
+
+Base 0 is only allowed for the number zero.
+
+ - `bigInt(0).toString(0)` => `0`
+ - `bigInt(1).toString(0)` => `Error: Cannot convert nonzero numbers to base 0.`
+
+[View benchmarks for this method](http://peterolson.github.io/BigInteger.js/benchmark/#toString)
+
+#### `valueOf()`
+
+Converts a bigInt to a native Javascript number. This override allows you to use native arithmetic operators without explicit conversion:
+
+ - `bigInt("100") + bigInt("200") === 300; //true`
+
+## Contributors
+
+To contribute, just fork the project, make some changes, and submit a pull request. Please verify that the unit tests pass before submitting.
+
+The unit tests are contained in the `spec/spec.js` file. You can run them locally by opening the `spec/SpecRunner.html` or file or running `npm test`. You can also [run the tests online from GitHub](http://peterolson.github.io/BigInteger.js/spec/SpecRunner.html).
+
+There are performance benchmarks that can be viewed from the `benchmarks/index.html` page. You can [run them online from GitHub](http://peterolson.github.io/BigInteger.js/benchmark/).
+
+## License
+
+This project is public domain. For more details, read about the [Unlicense](http://unlicense.org/).
diff --git a/node_modules/big-integer/bower.json b/node_modules/big-integer/bower.json
new file mode 100644
index 0000000..22dc58f
--- /dev/null
+++ b/node_modules/big-integer/bower.json
@@ -0,0 +1,29 @@
+{
+ "name": "big-integer",
+ "description": "An arbitrary length integer library for Javascript",
+ "main": "./BigInteger.js",
+ "authors": [
+ "Peter Olson"
+ ],
+ "license": "Unlicense",
+ "keywords": [
+ "math",
+ "big",
+ "bignum",
+ "bigint",
+ "biginteger",
+ "integer",
+ "arbitrary",
+ "precision",
+ "arithmetic"
+ ],
+ "homepage": "https://github.com/peterolson/BigInteger.js",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "test",
+ "coverage",
+ "tests"
+ ]
+}
diff --git a/node_modules/big-integer/package.json b/node_modules/big-integer/package.json
new file mode 100644
index 0000000..742570a
--- /dev/null
+++ b/node_modules/big-integer/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "big-integer",
+ "version": "1.6.52",
+ "author": "Peter Olson ",
+ "description": "An arbitrary length integer library for Javascript",
+ "contributors": [],
+ "bin": {},
+ "scripts": {
+ "test": "tsc && karma start my.conf.js && node spec/tsDefinitions.js",
+ "minify": "uglifyjs BigInteger.js -o BigInteger.min.js"
+ },
+ "main": "./BigInteger",
+ "repository": {
+ "type": "git",
+ "url": "git@github.com:peterolson/BigInteger.js.git"
+ },
+ "keywords": [
+ "math",
+ "big",
+ "bignum",
+ "bigint",
+ "biginteger",
+ "integer",
+ "arbitrary",
+ "precision",
+ "arithmetic"
+ ],
+ "devDependencies": {
+ "@types/lodash": "^4.14.175",
+ "@types/node": "^7.10.2",
+ "coveralls": "^3.0.6",
+ "jasmine": "3.5.0",
+ "jasmine-core": "^3.5.0",
+ "karma": "^6.3.4",
+ "karma-cli": "^2.0.0",
+ "karma-coverage": "^2.0.3",
+ "karma-jasmine": "^4.0.1",
+ "karma-phantomjs-launcher": "^1.0.4",
+ "lodash": "^4.17.21",
+ "typescript": "^5.3.2",
+ "uglify-js": "^3.17.4"
+ },
+ "license": "Unlicense",
+ "engines": {
+ "node": ">=0.6"
+ },
+ "typings": "./BigInteger.d.ts"
+}
diff --git a/node_modules/big-integer/tsconfig.json b/node_modules/big-integer/tsconfig.json
new file mode 100644
index 0000000..bb8e6cf
--- /dev/null
+++ b/node_modules/big-integer/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "target": "esnext",
+ "module": "commonjs",
+ "lib": [
+ "es6"
+ ],
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "strictNullChecks": false,
+ "baseUrl": "./",
+ "moduleResolution": "node",
+ "allowJs": true,
+ "typeRoots": [
+ "./"
+ ],
+ "types": [],
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "BigInteger.d.ts",
+ "spec/tsDefinitions.ts"
+ ]
+}
diff --git a/node_modules/body-parser/HISTORY.md b/node_modules/body-parser/HISTORY.md
new file mode 100644
index 0000000..c9b0b5b
--- /dev/null
+++ b/node_modules/body-parser/HISTORY.md
@@ -0,0 +1,680 @@
+1.20.4 / 2025-12-01
+===================
+
+ * deps: qs@~6.14.0
+ * deps: use tilde notation for dependencies
+ * deps: http-errors@~2.0.1
+ * deps: raw-body@~2.5.3
+
+1.20.3 / 2024-09-10
+===================
+
+ * deps: qs@6.13.0
+ * add `depth` option to customize the depth level in the parser
+ * IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`)
+
+1.20.2 / 2023-02-21
+===================
+
+ * Fix strict json error message on Node.js 19+
+ * deps: content-type@~1.0.5
+ - perf: skip value escaping when unnecessary
+ * deps: raw-body@2.5.2
+
+1.20.1 / 2022-10-06
+===================
+
+ * deps: qs@6.11.0
+ * perf: remove unnecessary object clone
+
+1.20.0 / 2022-04-02
+===================
+
+ * Fix error message for json parse whitespace in `strict`
+ * Fix internal error when inflated body exceeds limit
+ * Prevent loss of async hooks context
+ * Prevent hanging when request already read
+ * deps: depd@2.0.0
+ - Replace internal `eval` usage with `Function` constructor
+ - Use instance methods on `process` to check for listeners
+ * deps: http-errors@2.0.0
+ - deps: depd@2.0.0
+ - deps: statuses@2.0.1
+ * deps: on-finished@2.4.1
+ * deps: qs@6.10.3
+ * deps: raw-body@2.5.1
+ - deps: http-errors@2.0.0
+
+1.19.2 / 2022-02-15
+===================
+
+ * deps: bytes@3.1.2
+ * deps: qs@6.9.7
+ * Fix handling of `__proto__` keys
+ * deps: raw-body@2.4.3
+ - deps: bytes@3.1.2
+
+1.19.1 / 2021-12-10
+===================
+
+ * deps: bytes@3.1.1
+ * deps: http-errors@1.8.1
+ - deps: inherits@2.0.4
+ - deps: toidentifier@1.0.1
+ - deps: setprototypeof@1.2.0
+ * deps: qs@6.9.6
+ * deps: raw-body@2.4.2
+ - deps: bytes@3.1.1
+ - deps: http-errors@1.8.1
+ * deps: safe-buffer@5.2.1
+ * deps: type-is@~1.6.18
+
+1.19.0 / 2019-04-25
+===================
+
+ * deps: bytes@3.1.0
+ - Add petabyte (`pb`) support
+ * deps: http-errors@1.7.2
+ - Set constructor name when possible
+ - deps: setprototypeof@1.1.1
+ - deps: statuses@'>= 1.5.0 < 2'
+ * deps: iconv-lite@0.4.24
+ - Added encoding MIK
+ * deps: qs@6.7.0
+ - Fix parsing array brackets after index
+ * deps: raw-body@2.4.0
+ - deps: bytes@3.1.0
+ - deps: http-errors@1.7.2
+ - deps: iconv-lite@0.4.24
+ * deps: type-is@~1.6.17
+ - deps: mime-types@~2.1.24
+ - perf: prevent internal `throw` on invalid type
+
+1.18.3 / 2018-05-14
+===================
+
+ * Fix stack trace for strict json parse error
+ * deps: depd@~1.1.2
+ - perf: remove argument reassignment
+ * deps: http-errors@~1.6.3
+ - deps: depd@~1.1.2
+ - deps: setprototypeof@1.1.0
+ - deps: statuses@'>= 1.3.1 < 2'
+ * deps: iconv-lite@0.4.23
+ - Fix loading encoding with year appended
+ - Fix deprecation warnings on Node.js 10+
+ * deps: qs@6.5.2
+ * deps: raw-body@2.3.3
+ - deps: http-errors@1.6.3
+ - deps: iconv-lite@0.4.23
+ * deps: type-is@~1.6.16
+ - deps: mime-types@~2.1.18
+
+1.18.2 / 2017-09-22
+===================
+
+ * deps: debug@2.6.9
+ * perf: remove argument reassignment
+
+1.18.1 / 2017-09-12
+===================
+
+ * deps: content-type@~1.0.4
+ - perf: remove argument reassignment
+ - perf: skip parameter parsing when no parameters
+ * deps: iconv-lite@0.4.19
+ - Fix ISO-8859-1 regression
+ - Update Windows-1255
+ * deps: qs@6.5.1
+ - Fix parsing & compacting very deep objects
+ * deps: raw-body@2.3.2
+ - deps: iconv-lite@0.4.19
+
+1.18.0 / 2017-09-08
+===================
+
+ * Fix JSON strict violation error to match native parse error
+ * Include the `body` property on verify errors
+ * Include the `type` property on all generated errors
+ * Use `http-errors` to set status code on errors
+ * deps: bytes@3.0.0
+ * deps: debug@2.6.8
+ * deps: depd@~1.1.1
+ - Remove unnecessary `Buffer` loading
+ * deps: http-errors@~1.6.2
+ - deps: depd@1.1.1
+ * deps: iconv-lite@0.4.18
+ - Add support for React Native
+ - Add a warning if not loaded as utf-8
+ - Fix CESU-8 decoding in Node.js 8
+ - Improve speed of ISO-8859-1 encoding
+ * deps: qs@6.5.0
+ * deps: raw-body@2.3.1
+ - Use `http-errors` for standard emitted errors
+ - deps: bytes@3.0.0
+ - deps: iconv-lite@0.4.18
+ - perf: skip buffer decoding on overage chunk
+ * perf: prevent internal `throw` when missing charset
+
+1.17.2 / 2017-05-17
+===================
+
+ * deps: debug@2.6.7
+ - Fix `DEBUG_MAX_ARRAY_LENGTH`
+ - deps: ms@2.0.0
+ * deps: type-is@~1.6.15
+ - deps: mime-types@~2.1.15
+
+1.17.1 / 2017-03-06
+===================
+
+ * deps: qs@6.4.0
+ - Fix regression parsing keys starting with `[`
+
+1.17.0 / 2017-03-01
+===================
+
+ * deps: http-errors@~1.6.1
+ - Make `message` property enumerable for `HttpError`s
+ - deps: setprototypeof@1.0.3
+ * deps: qs@6.3.1
+ - Fix compacting nested arrays
+
+1.16.1 / 2017-02-10
+===================
+
+ * deps: debug@2.6.1
+ - Fix deprecation messages in WebStorm and other editors
+ - Undeprecate `DEBUG_FD` set to `1` or `2`
+
+1.16.0 / 2017-01-17
+===================
+
+ * deps: debug@2.6.0
+ - Allow colors in workers
+ - Deprecated `DEBUG_FD` environment variable
+ - Fix error when running under React Native
+ - Use same color for same namespace
+ - deps: ms@0.7.2
+ * deps: http-errors@~1.5.1
+ - deps: inherits@2.0.3
+ - deps: setprototypeof@1.0.2
+ - deps: statuses@'>= 1.3.1 < 2'
+ * deps: iconv-lite@0.4.15
+ - Added encoding MS-31J
+ - Added encoding MS-932
+ - Added encoding MS-936
+ - Added encoding MS-949
+ - Added encoding MS-950
+ - Fix GBK/GB18030 handling of Euro character
+ * deps: qs@6.2.1
+ - Fix array parsing from skipping empty values
+ * deps: raw-body@~2.2.0
+ - deps: iconv-lite@0.4.15
+ * deps: type-is@~1.6.14
+ - deps: mime-types@~2.1.13
+
+1.15.2 / 2016-06-19
+===================
+
+ * deps: bytes@2.4.0
+ * deps: content-type@~1.0.2
+ - perf: enable strict mode
+ * deps: http-errors@~1.5.0
+ - Use `setprototypeof` module to replace `__proto__` setting
+ - deps: statuses@'>= 1.3.0 < 2'
+ - perf: enable strict mode
+ * deps: qs@6.2.0
+ * deps: raw-body@~2.1.7
+ - deps: bytes@2.4.0
+ - perf: remove double-cleanup on happy path
+ * deps: type-is@~1.6.13
+ - deps: mime-types@~2.1.11
+
+1.15.1 / 2016-05-05
+===================
+
+ * deps: bytes@2.3.0
+ - Drop partial bytes on all parsed units
+ - Fix parsing byte string that looks like hex
+ * deps: raw-body@~2.1.6
+ - deps: bytes@2.3.0
+ * deps: type-is@~1.6.12
+ - deps: mime-types@~2.1.10
+
+1.15.0 / 2016-02-10
+===================
+
+ * deps: http-errors@~1.4.0
+ - Add `HttpError` export, for `err instanceof createError.HttpError`
+ - deps: inherits@2.0.1
+ - deps: statuses@'>= 1.2.1 < 2'
+ * deps: qs@6.1.0
+ * deps: type-is@~1.6.11
+ - deps: mime-types@~2.1.9
+
+1.14.2 / 2015-12-16
+===================
+
+ * deps: bytes@2.2.0
+ * deps: iconv-lite@0.4.13
+ * deps: qs@5.2.0
+ * deps: raw-body@~2.1.5
+ - deps: bytes@2.2.0
+ - deps: iconv-lite@0.4.13
+ * deps: type-is@~1.6.10
+ - deps: mime-types@~2.1.8
+
+1.14.1 / 2015-09-27
+===================
+
+ * Fix issue where invalid charset results in 400 when `verify` used
+ * deps: iconv-lite@0.4.12
+ - Fix CESU-8 decoding in Node.js 4.x
+ * deps: raw-body@~2.1.4
+ - Fix masking critical errors from `iconv-lite`
+ - deps: iconv-lite@0.4.12
+ * deps: type-is@~1.6.9
+ - deps: mime-types@~2.1.7
+
+1.14.0 / 2015-09-16
+===================
+
+ * Fix JSON strict parse error to match syntax errors
+ * Provide static `require` analysis in `urlencoded` parser
+ * deps: depd@~1.1.0
+ - Support web browser loading
+ * deps: qs@5.1.0
+ * deps: raw-body@~2.1.3
+ - Fix sync callback when attaching data listener causes sync read
+ * deps: type-is@~1.6.8
+ - Fix type error when given invalid type to match against
+ - deps: mime-types@~2.1.6
+
+1.13.3 / 2015-07-31
+===================
+
+ * deps: type-is@~1.6.6
+ - deps: mime-types@~2.1.4
+
+1.13.2 / 2015-07-05
+===================
+
+ * deps: iconv-lite@0.4.11
+ * deps: qs@4.0.0
+ - Fix dropping parameters like `hasOwnProperty`
+ - Fix user-visible incompatibilities from 3.1.0
+ - Fix various parsing edge cases
+ * deps: raw-body@~2.1.2
+ - Fix error stack traces to skip `makeError`
+ - deps: iconv-lite@0.4.11
+ * deps: type-is@~1.6.4
+ - deps: mime-types@~2.1.2
+ - perf: enable strict mode
+ - perf: remove argument reassignment
+
+1.13.1 / 2015-06-16
+===================
+
+ * deps: qs@2.4.2
+ - Downgraded from 3.1.0 because of user-visible incompatibilities
+
+1.13.0 / 2015-06-14
+===================
+
+ * Add `statusCode` property on `Error`s, in addition to `status`
+ * Change `type` default to `application/json` for JSON parser
+ * Change `type` default to `application/x-www-form-urlencoded` for urlencoded parser
+ * Provide static `require` analysis
+ * Use the `http-errors` module to generate errors
+ * deps: bytes@2.1.0
+ - Slight optimizations
+ * deps: iconv-lite@0.4.10
+ - The encoding UTF-16 without BOM now defaults to UTF-16LE when detection fails
+ - Leading BOM is now removed when decoding
+ * deps: on-finished@~2.3.0
+ - Add defined behavior for HTTP `CONNECT` requests
+ - Add defined behavior for HTTP `Upgrade` requests
+ - deps: ee-first@1.1.1
+ * deps: qs@3.1.0
+ - Fix dropping parameters like `hasOwnProperty`
+ - Fix various parsing edge cases
+ - Parsed object now has `null` prototype
+ * deps: raw-body@~2.1.1
+ - Use `unpipe` module for unpiping requests
+ - deps: iconv-lite@0.4.10
+ * deps: type-is@~1.6.3
+ - deps: mime-types@~2.1.1
+ - perf: reduce try block size
+ - perf: remove bitwise operations
+ * perf: enable strict mode
+ * perf: remove argument reassignment
+ * perf: remove delete call
+
+1.12.4 / 2015-05-10
+===================
+
+ * deps: debug@~2.2.0
+ * deps: qs@2.4.2
+ - Fix allowing parameters like `constructor`
+ * deps: on-finished@~2.2.1
+ * deps: raw-body@~2.0.1
+ - Fix a false-positive when unpiping in Node.js 0.8
+ - deps: bytes@2.0.1
+ * deps: type-is@~1.6.2
+ - deps: mime-types@~2.0.11
+
+1.12.3 / 2015-04-15
+===================
+
+ * Slight efficiency improvement when not debugging
+ * deps: depd@~1.0.1
+ * deps: iconv-lite@0.4.8
+ - Add encoding alias UNICODE-1-1-UTF-7
+ * deps: raw-body@1.3.4
+ - Fix hanging callback if request aborts during read
+ - deps: iconv-lite@0.4.8
+
+1.12.2 / 2015-03-16
+===================
+
+ * deps: qs@2.4.1
+ - Fix error when parameter `hasOwnProperty` is present
+
+1.12.1 / 2015-03-15
+===================
+
+ * deps: debug@~2.1.3
+ - Fix high intensity foreground color for bold
+ - deps: ms@0.7.0
+ * deps: type-is@~1.6.1
+ - deps: mime-types@~2.0.10
+
+1.12.0 / 2015-02-13
+===================
+
+ * add `debug` messages
+ * accept a function for the `type` option
+ * use `content-type` to parse `Content-Type` headers
+ * deps: iconv-lite@0.4.7
+ - Gracefully support enumerables on `Object.prototype`
+ * deps: raw-body@1.3.3
+ - deps: iconv-lite@0.4.7
+ * deps: type-is@~1.6.0
+ - fix argument reassignment
+ - fix false-positives in `hasBody` `Transfer-Encoding` check
+ - support wildcard for both type and subtype (`*/*`)
+ - deps: mime-types@~2.0.9
+
+1.11.0 / 2015-01-30
+===================
+
+ * make internal `extended: true` depth limit infinity
+ * deps: type-is@~1.5.6
+ - deps: mime-types@~2.0.8
+
+1.10.2 / 2015-01-20
+===================
+
+ * deps: iconv-lite@0.4.6
+ - Fix rare aliases of single-byte encodings
+ * deps: raw-body@1.3.2
+ - deps: iconv-lite@0.4.6
+
+1.10.1 / 2015-01-01
+===================
+
+ * deps: on-finished@~2.2.0
+ * deps: type-is@~1.5.5
+ - deps: mime-types@~2.0.7
+
+1.10.0 / 2014-12-02
+===================
+
+ * make internal `extended: true` array limit dynamic
+
+1.9.3 / 2014-11-21
+==================
+
+ * deps: iconv-lite@0.4.5
+ - Fix Windows-31J and X-SJIS encoding support
+ * deps: qs@2.3.3
+ - Fix `arrayLimit` behavior
+ * deps: raw-body@1.3.1
+ - deps: iconv-lite@0.4.5
+ * deps: type-is@~1.5.3
+ - deps: mime-types@~2.0.3
+
+1.9.2 / 2014-10-27
+==================
+
+ * deps: qs@2.3.2
+ - Fix parsing of mixed objects and values
+
+1.9.1 / 2014-10-22
+==================
+
+ * deps: on-finished@~2.1.1
+ - Fix handling of pipelined requests
+ * deps: qs@2.3.0
+ - Fix parsing of mixed implicit and explicit arrays
+ * deps: type-is@~1.5.2
+ - deps: mime-types@~2.0.2
+
+1.9.0 / 2014-09-24
+==================
+
+ * include the charset in "unsupported charset" error message
+ * include the encoding in "unsupported content encoding" error message
+ * deps: depd@~1.0.0
+
+1.8.4 / 2014-09-23
+==================
+
+ * fix content encoding to be case-insensitive
+
+1.8.3 / 2014-09-19
+==================
+
+ * deps: qs@2.2.4
+ - Fix issue with object keys starting with numbers truncated
+
+1.8.2 / 2014-09-15
+==================
+
+ * deps: depd@0.4.5
+
+1.8.1 / 2014-09-07
+==================
+
+ * deps: media-typer@0.3.0
+ * deps: type-is@~1.5.1
+
+1.8.0 / 2014-09-05
+==================
+
+ * make empty-body-handling consistent between chunked requests
+ - empty `json` produces `{}`
+ - empty `raw` produces `new Buffer(0)`
+ - empty `text` produces `''`
+ - empty `urlencoded` produces `{}`
+ * deps: qs@2.2.3
+ - Fix issue where first empty value in array is discarded
+ * deps: type-is@~1.5.0
+ - fix `hasbody` to be true for `content-length: 0`
+
+1.7.0 / 2014-09-01
+==================
+
+ * add `parameterLimit` option to `urlencoded` parser
+ * change `urlencoded` extended array limit to 100
+ * respond with 413 when over `parameterLimit` in `urlencoded`
+
+1.6.7 / 2014-08-29
+==================
+
+ * deps: qs@2.2.2
+ - Remove unnecessary cloning
+
+1.6.6 / 2014-08-27
+==================
+
+ * deps: qs@2.2.0
+ - Array parsing fix
+ - Performance improvements
+
+1.6.5 / 2014-08-16
+==================
+
+ * deps: on-finished@2.1.0
+
+1.6.4 / 2014-08-14
+==================
+
+ * deps: qs@1.2.2
+
+1.6.3 / 2014-08-10
+==================
+
+ * deps: qs@1.2.1
+
+1.6.2 / 2014-08-07
+==================
+
+ * deps: qs@1.2.0
+ - Fix parsing array of objects
+
+1.6.1 / 2014-08-06
+==================
+
+ * deps: qs@1.1.0
+ - Accept urlencoded square brackets
+ - Accept empty values in implicit array notation
+
+1.6.0 / 2014-08-05
+==================
+
+ * deps: qs@1.0.2
+ - Complete rewrite
+ - Limits array length to 20
+ - Limits object depth to 5
+ - Limits parameters to 1,000
+
+1.5.2 / 2014-07-27
+==================
+
+ * deps: depd@0.4.4
+ - Work-around v8 generating empty stack traces
+
+1.5.1 / 2014-07-26
+==================
+
+ * deps: depd@0.4.3
+ - Fix exception when global `Error.stackTraceLimit` is too low
+
+1.5.0 / 2014-07-20
+==================
+
+ * deps: depd@0.4.2
+ - Add `TRACE_DEPRECATION` environment variable
+ - Remove non-standard grey color from color output
+ - Support `--no-deprecation` argument
+ - Support `--trace-deprecation` argument
+ * deps: iconv-lite@0.4.4
+ - Added encoding UTF-7
+ * deps: raw-body@1.3.0
+ - deps: iconv-lite@0.4.4
+ - Added encoding UTF-7
+ - Fix `Cannot switch to old mode now` error on Node.js 0.10+
+ * deps: type-is@~1.3.2
+
+1.4.3 / 2014-06-19
+==================
+
+ * deps: type-is@1.3.1
+ - fix global variable leak
+
+1.4.2 / 2014-06-19
+==================
+
+ * deps: type-is@1.3.0
+ - improve type parsing
+
+1.4.1 / 2014-06-19
+==================
+
+ * fix urlencoded extended deprecation message
+
+1.4.0 / 2014-06-19
+==================
+
+ * add `text` parser
+ * add `raw` parser
+ * check accepted charset in content-type (accepts utf-8)
+ * check accepted encoding in content-encoding (accepts identity)
+ * deprecate `bodyParser()` middleware; use `.json()` and `.urlencoded()` as needed
+ * deprecate `urlencoded()` without provided `extended` option
+ * lazy-load urlencoded parsers
+ * parsers split into files for reduced mem usage
+ * support gzip and deflate bodies
+ - set `inflate: false` to turn off
+ * deps: raw-body@1.2.2
+ - Support all encodings from `iconv-lite`
+
+1.3.1 / 2014-06-11
+==================
+
+ * deps: type-is@1.2.1
+ - Switch dependency from mime to mime-types@1.0.0
+
+1.3.0 / 2014-05-31
+==================
+
+ * add `extended` option to urlencoded parser
+
+1.2.2 / 2014-05-27
+==================
+
+ * deps: raw-body@1.1.6
+ - assert stream encoding on node.js 0.8
+ - assert stream encoding on node.js < 0.10.6
+ - deps: bytes@1
+
+1.2.1 / 2014-05-26
+==================
+
+ * invoke `next(err)` after request fully read
+ - prevents hung responses and socket hang ups
+
+1.2.0 / 2014-05-11
+==================
+
+ * add `verify` option
+ * deps: type-is@1.2.0
+ - support suffix matching
+
+1.1.2 / 2014-05-11
+==================
+
+ * improve json parser speed
+
+1.1.1 / 2014-05-11
+==================
+
+ * fix repeated limit parsing with every request
+
+1.1.0 / 2014-05-10
+==================
+
+ * add `type` option
+ * deps: pin for safety and consistency
+
+1.0.2 / 2014-04-14
+==================
+
+ * use `type-is` module
+
+1.0.1 / 2014-03-20
+==================
+
+ * lower default limits to 100kb
diff --git a/node_modules/body-parser/README.md b/node_modules/body-parser/README.md
index 39d320f..f6661b7 100644
--- a/node_modules/body-parser/README.md
+++ b/node_modules/body-parser/README.md
@@ -17,18 +17,18 @@ before trusting. For example, `req.body.foo.toString()` may fail in multiple
ways, for example the `foo` property may not be there or may not be a string,
and `toString` may not be a function and instead a string or other user input.
-[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/learn/http/anatomy-of-an-http-transaction).
+[Learn about the anatomy of an HTTP transaction in Node.js](https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/).
_This does not handle multipart bodies_, due to their complex and typically
large nature. For multipart bodies, you may be interested in the following
modules:
- * [busboy](https://www.npmjs.com/package/busboy#readme) and
- [connect-busboy](https://www.npmjs.com/package/connect-busboy#readme)
- * [multiparty](https://www.npmjs.com/package/multiparty#readme) and
- [connect-multiparty](https://www.npmjs.com/package/connect-multiparty#readme)
- * [formidable](https://www.npmjs.com/package/formidable#readme)
- * [multer](https://www.npmjs.com/package/multer#readme)
+ * [busboy](https://www.npmjs.org/package/busboy#readme) and
+ [connect-busboy](https://www.npmjs.org/package/connect-busboy#readme)
+ * [multiparty](https://www.npmjs.org/package/multiparty#readme) and
+ [connect-multiparty](https://www.npmjs.org/package/connect-multiparty#readme)
+ * [formidable](https://www.npmjs.org/package/formidable#readme)
+ * [multer](https://www.npmjs.org/package/multer#readme)
This module provides the following parsers:
@@ -39,8 +39,8 @@ This module provides the following parsers:
Other body parsers you might be interested in:
-- [body](https://www.npmjs.com/package/body#readme)
-- [co-body](https://www.npmjs.com/package/co-body#readme)
+- [body](https://www.npmjs.org/package/body#readme)
+- [co-body](https://www.npmjs.org/package/co-body#readme)
## Installation
@@ -51,12 +51,14 @@ $ npm install body-parser
## API
```js
-const bodyParser = require('body-parser')
+var bodyParser = require('body-parser')
```
The `bodyParser` object exposes various factories to create middlewares. All
middlewares will populate the `req.body` property with the parsed body when
-the `Content-Type` request header matches the `type` option.
+the `Content-Type` request header matches the `type` option, or an empty
+object (`{}`) if there was no body to parse, the `Content-Type` was not matched,
+or an error occurred.
The various errors returned by this module are described in the
[errors section](#errors).
@@ -65,8 +67,8 @@ The various errors returned by this module are described in the
Returns middleware that only parses `json` and only looks at requests where
the `Content-Type` header matches the `type` option. This parser accepts any
-Unicode encoding of the body and supports automatic inflation of `gzip`,
-`br` (brotli) and `deflate` encodings.
+Unicode encoding of the body and supports automatic inflation of `gzip` and
+`deflate` encodings.
A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`).
@@ -76,11 +78,6 @@ object after the middleware (i.e. `req.body`).
The `json` function takes an optional `options` object that may contain any of
the following keys:
-##### defaultCharset
-
-Specify the default character set for the json content if the charset is not
-specified in the `Content-Type` header of the request. Defaults to `utf-8`.
-
##### inflate
When set to `true`, then deflated (compressed) bodies will be inflated; when
@@ -109,7 +106,7 @@ accept anything `JSON.parse` accepts. Defaults to `true`.
The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function. If not a
function, `type` option is passed directly to the
-[type-is](https://www.npmjs.com/package/type-is#readme) library and this can
+[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
be an extension name (like `json`), a mime type (like `application/json`), or
a mime type with a wildcard (like `*/*` or `*/json`). If a function, the `type`
option is called as `fn(req)` and the request is parsed if it returns a truthy
@@ -125,8 +122,7 @@ encoding of the request. The parsing can be aborted by throwing an error.
Returns middleware that parses all bodies as a `Buffer` and only looks at
requests where the `Content-Type` header matches the `type` option. This
-parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate`
-encodings.
+parser supports automatic inflation of `gzip` and `deflate` encodings.
A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a `Buffer` object
@@ -154,7 +150,7 @@ to `'100kb'`.
The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function.
If not a function, `type` option is passed directly to the
-[type-is](https://www.npmjs.com/package/type-is#readme) library and this
+[type-is](https://www.npmjs.org/package/type-is#readme) library and this
can be an extension name (like `bin`), a mime type (like
`application/octet-stream`), or a mime type with a wildcard (like `*/*` or
`application/*`). If a function, the `type` option is called as `fn(req)`
@@ -171,8 +167,7 @@ encoding of the request. The parsing can be aborted by throwing an error.
Returns middleware that parses all bodies as a string and only looks at
requests where the `Content-Type` header matches the `type` option. This
-parser supports automatic inflation of `gzip`, `br` (brotli) and `deflate`
-encodings.
+parser supports automatic inflation of `gzip` and `deflate` encodings.
A new `body` string containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This will be a string of the
@@ -205,7 +200,7 @@ to `'100kb'`.
The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function. If not
a function, `type` option is passed directly to the
-[type-is](https://www.npmjs.com/package/type-is#readme) library and this can
+[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
be an extension name (like `txt`), a mime type (like `text/plain`), or a mime
type with a wildcard (like `*/*` or `text/*`). If a function, the `type`
option is called as `fn(req)` and the request is parsed if it returns a
@@ -221,8 +216,8 @@ encoding of the request. The parsing can be aborted by throwing an error.
Returns middleware that only parses `urlencoded` bodies and only looks at
requests where the `Content-Type` header matches the `type` option. This
-parser accepts only UTF-8 and ISO-8859-1 encodings of the body and supports
-automatic inflation of `gzip`, `br` (brotli) and `deflate` encodings.
+parser accepts only UTF-8 encoding of the body and supports automatic
+inflation of `gzip` and `deflate` encodings.
A new `body` object containing the parsed data is populated on the `request`
object after the middleware (i.e. `req.body`). This object will contain
@@ -236,12 +231,16 @@ any of the following keys:
##### extended
-The "extended" syntax allows for rich objects and arrays to be encoded into the
-URL-encoded format, allowing for a JSON-like experience with URL-encoded. For
-more information, please [see the qs
-library](https://www.npmjs.com/package/qs#readme).
+The `extended` option allows to choose between parsing the URL-encoded data
+with the `querystring` library (when `false`) or the `qs` library (when
+`true`). The "extended" syntax allows for rich objects and arrays to be
+encoded into the URL-encoded format, allowing for a JSON-like experience
+with URL-encoded. For more information, please
+[see the qs library](https://www.npmjs.org/package/qs#readme).
-Defaults to `false`.
+Defaults to `true`, but using the default has been deprecated. Please
+research into the difference between `qs` and `querystring` and choose the
+appropriate setting.
##### inflate
@@ -266,7 +265,7 @@ than this value, a 413 will be returned to the client. Defaults to `1000`.
The `type` option is used to determine what media type the middleware will
parse. This option can be a string, array of strings, or a function. If not
a function, `type` option is passed directly to the
-[type-is](https://www.npmjs.com/package/type-is#readme) library and this can
+[type-is](https://www.npmjs.org/package/type-is#readme) library and this can
be an extension name (like `urlencoded`), a mime type (like
`application/x-www-form-urlencoded`), or a mime type with a wildcard (like
`*/x-www-form-urlencoded`). If a function, the `type` option is called as
@@ -279,24 +278,7 @@ The `verify` option, if supplied, is called as `verify(req, res, buf, encoding)`
where `buf` is a `Buffer` of the raw request body and `encoding` is the
encoding of the request. The parsing can be aborted by throwing an error.
-##### defaultCharset
-
-The default charset to parse as, if not specified in content-type. Must be
-either `utf-8` or `iso-8859-1`. Defaults to `utf-8`.
-
-##### charsetSentinel
-
-Whether to let the value of the `utf8` parameter take precedence as the charset
-selector. It requires the form to contain a parameter named `utf8` with a value
-of `✓`. Defaults to `false`.
-
-##### interpretNumericEntities
-
-Whether to decode numeric entities such as `☺` when parsing an iso-8859-1
-form. Defaults to `false`.
-
-
-##### depth
+#### depth
The `depth` option is used to configure the maximum depth of the `qs` library when `extended` is `true`. This allows you to limit the amount of keys that are parsed and can be useful to prevent certain types of abuse. Defaults to `32`. It is recommended to keep this value as low as possible.
@@ -409,13 +391,13 @@ top-level middleware, which will parse the bodies of all incoming requests.
This is the simplest setup.
```js
-const express = require('express')
-const bodyParser = require('body-parser')
+var express = require('express')
+var bodyParser = require('body-parser')
-const app = express()
+var app = express()
// parse application/x-www-form-urlencoded
-app.use(bodyParser.urlencoded())
+app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
@@ -423,7 +405,7 @@ app.use(bodyParser.json())
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
- res.end(String(JSON.stringify(req.body, null, 2)))
+ res.end(JSON.stringify(req.body, null, 2))
})
```
@@ -434,26 +416,24 @@ need them. In general, this is the most recommended way to use body-parser with
Express.
```js
-const express = require('express')
-const bodyParser = require('body-parser')
+var express = require('express')
+var bodyParser = require('body-parser')
-const app = express()
+var app = express()
// create application/json parser
-const jsonParser = bodyParser.json()
+var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
-const urlencodedParser = bodyParser.urlencoded()
+var urlencodedParser = bodyParser.urlencoded({ extended: false })
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
- if (!req.body || !req.body.username) res.sendStatus(400)
res.send('welcome, ' + req.body.username)
})
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
- if (!req.body) res.sendStatus(400)
// create user in req.body
})
```
@@ -464,10 +444,10 @@ All the parsers accept a `type` option which allows you to change the
`Content-Type` that the middleware will parse.
```js
-const express = require('express')
-const bodyParser = require('body-parser')
+var express = require('express')
+var bodyParser = require('body-parser')
-const app = express()
+var app = express()
// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }))
@@ -483,12 +463,14 @@ app.use(bodyParser.text({ type: 'text/html' }))
[MIT](LICENSE)
-[ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/body-parser/ci.yml?branch=master&label=ci
+[ci-image]: https://badgen.net/github/checks/expressjs/body-parser/master?label=ci
[ci-url]: https://github.com/expressjs/body-parser/actions/workflows/ci.yml
-[coveralls-image]: https://img.shields.io/coverallsCoverage/github/expressjs/body-parser?branch=master
+[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/body-parser/master
[coveralls-url]: https://coveralls.io/r/expressjs/body-parser?branch=master
-[npm-downloads-image]: https://img.shields.io/npm/dm/body-parser
-[npm-url]: https://npmjs.com/package/body-parser
-[npm-version-image]: https://img.shields.io/npm/v/body-parser
+[node-version-image]: https://badgen.net/npm/node/body-parser
+[node-version-url]: https://nodejs.org/en/download
+[npm-downloads-image]: https://badgen.net/npm/dm/body-parser
+[npm-url]: https://npmjs.org/package/body-parser
+[npm-version-image]: https://badgen.net/npm/v/body-parser
[ossf-scorecard-badge]: https://api.scorecard.dev/projects/github.com/expressjs/body-parser/badge
-[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/body-parser
+[ossf-scorecard-visualizer]: https://ossf.github.io/scorecard-visualizer/#/projects/github.com/expressjs/body-parser
\ No newline at end of file
diff --git a/node_modules/body-parser/index.js b/node_modules/body-parser/index.js
index 013ce5c..bb24d73 100644
--- a/node_modules/body-parser/index.js
+++ b/node_modules/body-parser/index.js
@@ -7,65 +7,150 @@
'use strict'
/**
- * @typedef {Object} Parsers
- * @property {Function} json JSON parser
- * @property {Function} raw Raw parser
- * @property {Function} text Text parser
- * @property {Function} urlencoded URL-encoded parser
+ * Module dependencies.
+ * @private
+ */
+
+var deprecate = require('depd')('body-parser')
+
+/**
+ * Cache of loaded parsers.
+ * @private
+ */
+
+var parsers = Object.create(null)
+
+/**
+ * @typedef Parsers
+ * @type {function}
+ * @property {function} json
+ * @property {function} raw
+ * @property {function} text
+ * @property {function} urlencoded
*/
/**
* Module exports.
- * @type {Function & Parsers}
+ * @type {Parsers}
*/
-exports = module.exports = bodyParser
+
+exports = module.exports = deprecate.function(bodyParser,
+ 'bodyParser: use individual json/urlencoded middlewares')
/**
* JSON parser.
* @public
*/
+
Object.defineProperty(exports, 'json', {
configurable: true,
enumerable: true,
- get: () => require('./lib/types/json')
+ get: createParserGetter('json')
})
/**
* Raw parser.
* @public
*/
+
Object.defineProperty(exports, 'raw', {
configurable: true,
enumerable: true,
- get: () => require('./lib/types/raw')
+ get: createParserGetter('raw')
})
/**
* Text parser.
* @public
*/
+
Object.defineProperty(exports, 'text', {
configurable: true,
enumerable: true,
- get: () => require('./lib/types/text')
+ get: createParserGetter('text')
})
/**
* URL-encoded parser.
* @public
*/
+
Object.defineProperty(exports, 'urlencoded', {
configurable: true,
enumerable: true,
- get: () => require('./lib/types/urlencoded')
+ get: createParserGetter('urlencoded')
})
/**
* Create a middleware to parse json and urlencoded bodies.
*
+ * @param {object} [options]
+ * @return {function}
* @deprecated
* @public
*/
-function bodyParser () {
- throw new Error('The bodyParser() generic has been split into individual middleware to use instead.')
+
+function bodyParser (options) {
+ // use default type for parsers
+ var opts = Object.create(options || null, {
+ type: {
+ configurable: true,
+ enumerable: true,
+ value: undefined,
+ writable: true
+ }
+ })
+
+ var _urlencoded = exports.urlencoded(opts)
+ var _json = exports.json(opts)
+
+ return function bodyParser (req, res, next) {
+ _json(req, res, function (err) {
+ if (err) return next(err)
+ _urlencoded(req, res, next)
+ })
+ }
+}
+
+/**
+ * Create a getter for loading a parser.
+ * @private
+ */
+
+function createParserGetter (name) {
+ return function get () {
+ return loadParser(name)
+ }
+}
+
+/**
+ * Load a parser module.
+ * @private
+ */
+
+function loadParser (parserName) {
+ var parser = parsers[parserName]
+
+ if (parser !== undefined) {
+ return parser
+ }
+
+ // this uses a switch for static require analysis
+ switch (parserName) {
+ case 'json':
+ parser = require('./lib/types/json')
+ break
+ case 'raw':
+ parser = require('./lib/types/raw')
+ break
+ case 'text':
+ parser = require('./lib/types/text')
+ break
+ case 'urlencoded':
+ parser = require('./lib/types/urlencoded')
+ break
+ }
+
+ // store to prevent invoking require()
+ return (parsers[parserName] = parser)
}
diff --git a/node_modules/body-parser/lib/read.js b/node_modules/body-parser/lib/read.js
index d1f3f48..fce6283 100644
--- a/node_modules/body-parser/lib/read.js
+++ b/node_modules/body-parser/lib/read.js
@@ -12,12 +12,12 @@
*/
var createError = require('http-errors')
+var destroy = require('destroy')
var getBody = require('raw-body')
var iconv = require('iconv-lite')
var onFinished = require('on-finished')
-var zlib = require('node:zlib')
-var hasBody = require('type-is').hasBody
-var { getCharset } = require('./utils')
+var unpipe = require('unpipe')
+var zlib = require('zlib')
/**
* Module exports.
@@ -28,61 +28,27 @@ module.exports = read
/**
* Read a request into a buffer and parse.
*
- * @param {Object} req
- * @param {Object} res
- * @param {Function} next
- * @param {Function} parse
- * @param {Function} debug
- * @param {Object} options
+ * @param {object} req
+ * @param {object} res
+ * @param {function} next
+ * @param {function} parse
+ * @param {function} debug
+ * @param {object} options
* @private
*/
+
function read (req, res, next, parse, debug, options) {
- if (onFinished.isFinished(req)) {
- debug('body already parsed')
- next()
- return
- }
-
- if (!('body' in req)) {
- req.body = undefined
- }
-
- // skip requests without bodies
- if (!hasBody(req)) {
- debug('skip empty body')
- next()
- return
- }
-
- debug('content-type %j', req.headers['content-type'])
-
- // determine if request should be parsed
- if (!options.shouldParse(req)) {
- debug('skip parsing')
- next()
- return
- }
-
- var encoding = null
- if (options?.skipCharset !== true) {
- encoding = getCharset(req) || options.defaultCharset
-
- // validate charset
- if (!!options?.isValidCharset && !options.isValidCharset(encoding)) {
- debug('invalid charset')
- next(createError(415, 'unsupported charset "' + encoding.toUpperCase() + '"', {
- charset: encoding,
- type: 'charset.unsupported'
- }))
- return
- }
- }
-
var length
var opts = options
var stream
+ // flag as parsed
+ req._body = true
+
// read options
+ var encoding = opts.encoding !== null
+ ? opts.encoding
+ : null
var verify = opts.verify
try {
@@ -127,8 +93,8 @@ function read (req, res, next, parse, debug, options) {
// unpipe from stream and destroy
if (stream !== req) {
- req.unpipe()
- stream.destroy()
+ unpipe(req)
+ destroy(stream, true)
}
// read off entire request
@@ -159,7 +125,7 @@ function read (req, res, next, parse, debug, options) {
str = typeof body !== 'string' && encoding !== null
? iconv.decode(body, encoding)
: body
- req.body = parse(str, encoding)
+ req.body = parse(str)
} catch (err) {
next(createError(400, err, {
body: str,
@@ -175,15 +141,17 @@ function read (req, res, next, parse, debug, options) {
/**
* Get the content stream of the request.
*
- * @param {Object} req
- * @param {Function} debug
- * @param {boolean} inflate
- * @returns {Object}
- * @private
+ * @param {object} req
+ * @param {function} debug
+ * @param {boolean} [inflate=true]
+ * @return {object}
+ * @api private
*/
+
function contentstream (req, debug, inflate) {
var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()
var length = req.headers['content-length']
+ var stream
debug('content-encoding "%s"', encoding)
@@ -194,49 +162,39 @@ function contentstream (req, debug, inflate) {
})
}
- if (encoding === 'identity') {
- req.length = length
- return req
- }
-
- var stream = createDecompressionStream(encoding, debug)
- req.pipe(stream)
- return stream
-}
-
-/**
- * Create a decompression stream for the given encoding.
- * @param {string} encoding
- * @param {Function} debug
- * @returns {Object}
- * @private
- */
-function createDecompressionStream (encoding, debug) {
switch (encoding) {
case 'deflate':
+ stream = zlib.createInflate()
debug('inflate body')
- return zlib.createInflate()
+ req.pipe(stream)
+ break
case 'gzip':
+ stream = zlib.createGunzip()
debug('gunzip body')
- return zlib.createGunzip()
- case 'br':
- debug('brotli decompress body')
- return zlib.createBrotliDecompress()
+ req.pipe(stream)
+ break
+ case 'identity':
+ stream = req
+ stream.length = length
+ break
default:
throw createError(415, 'unsupported content encoding "' + encoding + '"', {
encoding: encoding,
type: 'encoding.unsupported'
})
}
+
+ return stream
}
/**
* Dump the contents of a request.
*
- * @param {Object} req
- * @param {Function} callback
- * @private
+ * @param {object} req
+ * @param {function} callback
+ * @api private
*/
+
function dump (req, callback) {
if (onFinished.isFinished(req)) {
callback(null)
diff --git a/node_modules/body-parser/lib/types/json.js b/node_modules/body-parser/lib/types/json.js
index 23c7357..59f3f7e 100644
--- a/node_modules/body-parser/lib/types/json.js
+++ b/node_modules/body-parser/lib/types/json.js
@@ -12,9 +12,12 @@
* @private
*/
+var bytes = require('bytes')
+var contentType = require('content-type')
+var createError = require('http-errors')
var debug = require('debug')('body-parser:json')
var read = require('../read')
-var { normalizeOptions } = require('../utils')
+var typeis = require('type-is')
/**
* Module exports.
@@ -33,6 +36,7 @@ module.exports = json
* %x0A / ; Line feed or New line
* %x0D ) ; Carriage return
*/
+
var FIRST_CHAR_REGEXP = /^[\x20\x09\x0a\x0d]*([^\x20\x09\x0a\x0d])/ // eslint-disable-line no-control-regex
var JSON_SYNTAX_CHAR = '#'
@@ -41,15 +45,31 @@ var JSON_SYNTAX_REGEXP = /#+/g
/**
* Create a middleware to parse JSON bodies.
*
- * @param {Object} [options]
- * @returns {Function}
+ * @param {object} [options]
+ * @return {function}
* @public
*/
-function json (options) {
- const normalizedOptions = normalizeOptions(options, 'application/json')
- var reviver = options?.reviver
- var strict = options?.strict !== false
+function json (options) {
+ var opts = options || {}
+
+ var limit = typeof opts.limit !== 'number'
+ ? bytes.parse(opts.limit || '100kb')
+ : opts.limit
+ var inflate = opts.inflate !== false
+ var reviver = opts.reviver
+ var strict = opts.strict !== false
+ var type = opts.type || 'application/json'
+ var verify = opts.verify || false
+
+ if (verify !== false && typeof verify !== 'function') {
+ throw new TypeError('option verify must be function')
+ }
+
+ // create the appropriate type checking function
+ var shouldParse = typeof type !== 'function'
+ ? typeChecker(type)
+ : type
function parse (body) {
if (body.length === 0) {
@@ -78,14 +98,49 @@ function json (options) {
}
}
- const readOptions = {
- ...normalizedOptions,
- // assert charset per RFC 7159 sec 8.1
- isValidCharset: (charset) => charset.slice(0, 4) === 'utf-'
- }
-
return function jsonParser (req, res, next) {
- read(req, res, next, parse, debug, readOptions)
+ if (req._body) {
+ debug('body already parsed')
+ next()
+ return
+ }
+
+ req.body = req.body || {}
+
+ // skip requests without bodies
+ if (!typeis.hasBody(req)) {
+ debug('skip empty body')
+ next()
+ return
+ }
+
+ debug('content-type %j', req.headers['content-type'])
+
+ // determine if request should be parsed
+ if (!shouldParse(req)) {
+ debug('skip parsing')
+ next()
+ return
+ }
+
+ // assert charset per RFC 7159 sec 8.1
+ var charset = getCharset(req) || 'utf-8'
+ if (charset.slice(0, 4) !== 'utf-') {
+ debug('invalid charset')
+ next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
+ charset: charset,
+ type: 'charset.unsupported'
+ }))
+ return
+ }
+
+ // read
+ read(req, res, next, parse, debug, {
+ encoding: charset,
+ inflate: inflate,
+ limit: limit,
+ verify: verify
+ })
}
}
@@ -94,15 +149,20 @@ function json (options) {
*
* @param {string} str
* @param {string} char
- * @returns {Error}
+ * @return {Error}
* @private
*/
+
function createStrictSyntaxError (str, char) {
var index = str.indexOf(char)
var partial = ''
if (index !== -1) {
- partial = str.substring(0, index) + JSON_SYNTAX_CHAR.repeat(str.length - index)
+ partial = str.substring(0, index) + JSON_SYNTAX_CHAR
+
+ for (var i = index + 1; i < str.length; i++) {
+ partial += JSON_SYNTAX_CHAR
+ }
}
try {
@@ -121,9 +181,10 @@ function createStrictSyntaxError (str, char) {
* Get the first non-whitespace character in a string.
*
* @param {string} str
- * @returns {string|undefined}
+ * @return {function}
* @private
*/
+
function firstchar (str) {
var match = FIRST_CHAR_REGEXP.exec(str)
@@ -132,14 +193,29 @@ function firstchar (str) {
: undefined
}
+/**
+ * Get the charset of a request.
+ *
+ * @param {object} req
+ * @api private
+ */
+
+function getCharset (req) {
+ try {
+ return (contentType.parse(req).parameters.charset || '').toLowerCase()
+ } catch (e) {
+ return undefined
+ }
+}
+
/**
* Normalize a SyntaxError for JSON.parse.
*
* @param {SyntaxError} error
- * @param {Object} obj
- * @returns {SyntaxError}
- * @private
+ * @param {object} obj
+ * @return {SyntaxError}
*/
+
function normalizeJsonSyntaxError (error, obj) {
var keys = Object.getOwnPropertyNames(error)
@@ -156,3 +232,16 @@ function normalizeJsonSyntaxError (error, obj) {
return error
}
+
+/**
+ * Get the simple type checker.
+ *
+ * @param {string} type
+ * @return {function}
+ */
+
+function typeChecker (type) {
+ return function checkType (req) {
+ return Boolean(typeis(req, type))
+ }
+}
diff --git a/node_modules/body-parser/lib/types/raw.js b/node_modules/body-parser/lib/types/raw.js
index ad4854d..f5d1b67 100644
--- a/node_modules/body-parser/lib/types/raw.js
+++ b/node_modules/body-parser/lib/types/raw.js
@@ -10,9 +10,10 @@
* Module dependencies.
*/
+var bytes = require('bytes')
var debug = require('debug')('body-parser:raw')
var read = require('../read')
-var { normalizeOptions, passthrough } = require('../utils')
+var typeis = require('type-is')
/**
* Module exports.
@@ -23,20 +24,78 @@ module.exports = raw
/**
* Create a middleware to parse raw bodies.
*
- * @param {Object} [options]
- * @returns {Function}
- * @public
+ * @param {object} [options]
+ * @return {function}
+ * @api public
*/
-function raw (options) {
- const normalizedOptions = normalizeOptions(options, 'application/octet-stream')
- const readOptions = {
- ...normalizedOptions,
- // Skip charset validation and parse the body as is
- skipCharset: true
+function raw (options) {
+ var opts = options || {}
+
+ var inflate = opts.inflate !== false
+ var limit = typeof opts.limit !== 'number'
+ ? bytes.parse(opts.limit || '100kb')
+ : opts.limit
+ var type = opts.type || 'application/octet-stream'
+ var verify = opts.verify || false
+
+ if (verify !== false && typeof verify !== 'function') {
+ throw new TypeError('option verify must be function')
+ }
+
+ // create the appropriate type checking function
+ var shouldParse = typeof type !== 'function'
+ ? typeChecker(type)
+ : type
+
+ function parse (buf) {
+ return buf
}
return function rawParser (req, res, next) {
- read(req, res, next, passthrough, debug, readOptions)
+ if (req._body) {
+ debug('body already parsed')
+ next()
+ return
+ }
+
+ req.body = req.body || {}
+
+ // skip requests without bodies
+ if (!typeis.hasBody(req)) {
+ debug('skip empty body')
+ next()
+ return
+ }
+
+ debug('content-type %j', req.headers['content-type'])
+
+ // determine if request should be parsed
+ if (!shouldParse(req)) {
+ debug('skip parsing')
+ next()
+ return
+ }
+
+ // read
+ read(req, res, next, parse, debug, {
+ encoding: null,
+ inflate: inflate,
+ limit: limit,
+ verify: verify
+ })
+ }
+}
+
+/**
+ * Get the simple type checker.
+ *
+ * @param {string} type
+ * @return {function}
+ */
+
+function typeChecker (type) {
+ return function checkType (req) {
+ return Boolean(typeis(req, type))
}
}
diff --git a/node_modules/body-parser/lib/types/text.js b/node_modules/body-parser/lib/types/text.js
index 9df73be..083a009 100644
--- a/node_modules/body-parser/lib/types/text.js
+++ b/node_modules/body-parser/lib/types/text.js
@@ -10,9 +10,11 @@
* Module dependencies.
*/
+var bytes = require('bytes')
+var contentType = require('content-type')
var debug = require('debug')('body-parser:text')
var read = require('../read')
-var { normalizeOptions, passthrough } = require('../utils')
+var typeis = require('type-is')
/**
* Module exports.
@@ -23,14 +25,97 @@ module.exports = text
/**
* Create a middleware to parse text bodies.
*
- * @param {Object} [options]
- * @returns {Function}
- * @public
+ * @param {object} [options]
+ * @return {function}
+ * @api public
*/
+
function text (options) {
- const normalizedOptions = normalizeOptions(options, 'text/plain')
+ var opts = options || {}
+
+ var defaultCharset = opts.defaultCharset || 'utf-8'
+ var inflate = opts.inflate !== false
+ var limit = typeof opts.limit !== 'number'
+ ? bytes.parse(opts.limit || '100kb')
+ : opts.limit
+ var type = opts.type || 'text/plain'
+ var verify = opts.verify || false
+
+ if (verify !== false && typeof verify !== 'function') {
+ throw new TypeError('option verify must be function')
+ }
+
+ // create the appropriate type checking function
+ var shouldParse = typeof type !== 'function'
+ ? typeChecker(type)
+ : type
+
+ function parse (buf) {
+ return buf
+ }
return function textParser (req, res, next) {
- read(req, res, next, passthrough, debug, normalizedOptions)
+ if (req._body) {
+ debug('body already parsed')
+ next()
+ return
+ }
+
+ req.body = req.body || {}
+
+ // skip requests without bodies
+ if (!typeis.hasBody(req)) {
+ debug('skip empty body')
+ next()
+ return
+ }
+
+ debug('content-type %j', req.headers['content-type'])
+
+ // determine if request should be parsed
+ if (!shouldParse(req)) {
+ debug('skip parsing')
+ next()
+ return
+ }
+
+ // get charset
+ var charset = getCharset(req) || defaultCharset
+
+ // read
+ read(req, res, next, parse, debug, {
+ encoding: charset,
+ inflate: inflate,
+ limit: limit,
+ verify: verify
+ })
+ }
+}
+
+/**
+ * Get the charset of a request.
+ *
+ * @param {object} req
+ * @api private
+ */
+
+function getCharset (req) {
+ try {
+ return (contentType.parse(req).parameters.charset || '').toLowerCase()
+ } catch (e) {
+ return undefined
+ }
+}
+
+/**
+ * Get the simple type checker.
+ *
+ * @param {string} type
+ * @return {function}
+ */
+
+function typeChecker (type) {
+ return function checkType (req) {
+ return Boolean(typeis(req, type))
}
}
diff --git a/node_modules/body-parser/lib/types/urlencoded.js b/node_modules/body-parser/lib/types/urlencoded.js
index 4a3227c..832992c 100644
--- a/node_modules/body-parser/lib/types/urlencoded.js
+++ b/node_modules/body-parser/lib/types/urlencoded.js
@@ -12,11 +12,13 @@
* @private
*/
+var bytes = require('bytes')
+var contentType = require('content-type')
var createError = require('http-errors')
var debug = require('debug')('body-parser:urlencoded')
+var deprecate = require('depd')('body-parser')
var read = require('../read')
-var qs = require('qs')
-var { normalizeOptions } = require('../utils')
+var typeis = require('type-is')
/**
* Module exports.
@@ -24,55 +26,115 @@ var { normalizeOptions } = require('../utils')
module.exports = urlencoded
+/**
+ * Cache of parser modules.
+ */
+
+var parsers = Object.create(null)
+
/**
* Create a middleware to parse urlencoded bodies.
*
- * @param {Object} [options]
- * @returns {Function}
+ * @param {object} [options]
+ * @return {function}
* @public
*/
-function urlencoded (options) {
- const normalizedOptions = normalizeOptions(options, 'application/x-www-form-urlencoded')
- if (normalizedOptions.defaultCharset !== 'utf-8' && normalizedOptions.defaultCharset !== 'iso-8859-1') {
- throw new TypeError('option defaultCharset must be either utf-8 or iso-8859-1')
+function urlencoded (options) {
+ var opts = options || {}
+
+ // notice because option default will flip in next major
+ if (opts.extended === undefined) {
+ deprecate('undefined extended: provide extended option')
+ }
+
+ var extended = opts.extended !== false
+ var inflate = opts.inflate !== false
+ var limit = typeof opts.limit !== 'number'
+ ? bytes.parse(opts.limit || '100kb')
+ : opts.limit
+ var type = opts.type || 'application/x-www-form-urlencoded'
+ var verify = opts.verify || false
+
+ if (verify !== false && typeof verify !== 'function') {
+ throw new TypeError('option verify must be function')
}
// create the appropriate query parser
- var queryparse = createQueryParser(options)
+ var queryparse = extended
+ ? extendedparser(opts)
+ : simpleparser(opts)
- function parse (body, encoding) {
+ // create the appropriate type checking function
+ var shouldParse = typeof type !== 'function'
+ ? typeChecker(type)
+ : type
+
+ function parse (body) {
return body.length
- ? queryparse(body, encoding)
+ ? queryparse(body)
: {}
}
- const readOptions = {
- ...normalizedOptions,
- // assert charset
- isValidCharset: (charset) => charset === 'utf-8' || charset === 'iso-8859-1'
- }
-
return function urlencodedParser (req, res, next) {
- read(req, res, next, parse, debug, readOptions)
+ if (req._body) {
+ debug('body already parsed')
+ next()
+ return
+ }
+
+ req.body = req.body || {}
+
+ // skip requests without bodies
+ if (!typeis.hasBody(req)) {
+ debug('skip empty body')
+ next()
+ return
+ }
+
+ debug('content-type %j', req.headers['content-type'])
+
+ // determine if request should be parsed
+ if (!shouldParse(req)) {
+ debug('skip parsing')
+ next()
+ return
+ }
+
+ // assert charset
+ var charset = getCharset(req) || 'utf-8'
+ if (charset !== 'utf-8') {
+ debug('invalid charset')
+ next(createError(415, 'unsupported charset "' + charset.toUpperCase() + '"', {
+ charset: charset,
+ type: 'charset.unsupported'
+ }))
+ return
+ }
+
+ // read
+ read(req, res, next, parse, debug, {
+ debug: debug,
+ encoding: charset,
+ inflate: inflate,
+ limit: limit,
+ verify: verify
+ })
}
}
/**
* Get the extended query parser.
*
- * @param {Object} options
- * @returns {Function}
- * @private
+ * @param {object} options
*/
-function createQueryParser (options) {
- var extended = Boolean(options?.extended)
- var parameterLimit = options?.parameterLimit !== undefined
- ? options?.parameterLimit
+
+function extendedparser (options) {
+ var parameterLimit = options.parameterLimit !== undefined
+ ? options.parameterLimit
: 1000
- var charsetSentinel = options?.charsetSentinel
- var interpretNumericEntities = options?.interpretNumericEntities
- var depth = extended ? (options?.depth !== undefined ? options?.depth : 32) : 0
+ var depth = options.depth !== undefined ? options.depth : 32
+ var parse = parser('qs')
if (isNaN(parameterLimit) || parameterLimit < 1) {
throw new TypeError('option parameterLimit must be a positive number')
@@ -86,7 +148,7 @@ function createQueryParser (options) {
parameterLimit = parameterLimit | 0
}
- return function queryparse (body, encoding) {
+ return function queryparse (body) {
var paramCount = parameterCount(body, parameterLimit)
if (paramCount === undefined) {
@@ -96,19 +158,16 @@ function createQueryParser (options) {
})
}
- var arrayLimit = extended ? Math.max(100, paramCount) : paramCount
+ var arrayLimit = Math.max(100, paramCount)
- debug('parse ' + (extended ? 'extended ' : '') + 'urlencoding')
+ debug('parse extended urlencoding')
try {
- return qs.parse(body, {
+ return parse(body, {
allowPrototypes: true,
arrayLimit: arrayLimit,
depth: depth,
- charsetSentinel: charsetSentinel,
- interpretNumericEntities: interpretNumericEntities,
- charset: encoding,
- parameterLimit: parameterLimit,
- strictDepth: true
+ strictDepth: true,
+ parameterLimit: parameterLimit
})
} catch (err) {
if (err instanceof RangeError) {
@@ -122,21 +181,120 @@ function createQueryParser (options) {
}
}
+/**
+ * Get the charset of a request.
+ *
+ * @param {object} req
+ * @api private
+ */
+
+function getCharset (req) {
+ try {
+ return (contentType.parse(req).parameters.charset || '').toLowerCase()
+ } catch (e) {
+ return undefined
+ }
+}
+
/**
* Count the number of parameters, stopping once limit reached
*
* @param {string} body
* @param {number} limit
- * @returns {number|undefined} Returns undefined if limit exceeded
- * @private
+ * @api private
*/
+
function parameterCount (body, limit) {
- let count = 0
- let index = -1
- do {
+ var count = 0
+ var index = 0
+
+ while ((index = body.indexOf('&', index)) !== -1) {
count++
- if (count > limit) return undefined // Early exit if limit exceeded
- index = body.indexOf('&', index + 1)
- } while (index !== -1)
+ index++
+
+ if (count === limit) {
+ return undefined
+ }
+ }
+
return count
}
+
+/**
+ * Get parser for module name dynamically.
+ *
+ * @param {string} name
+ * @return {function}
+ * @api private
+ */
+
+function parser (name) {
+ var mod = parsers[name]
+
+ if (mod !== undefined) {
+ return mod.parse
+ }
+
+ // this uses a switch for static require analysis
+ switch (name) {
+ case 'qs':
+ mod = require('qs')
+ break
+ case 'querystring':
+ mod = require('querystring')
+ break
+ }
+
+ // store to prevent invoking require()
+ parsers[name] = mod
+
+ return mod.parse
+}
+
+/**
+ * Get the simple query parser.
+ *
+ * @param {object} options
+ */
+
+function simpleparser (options) {
+ var parameterLimit = options.parameterLimit !== undefined
+ ? options.parameterLimit
+ : 1000
+ var parse = parser('querystring')
+
+ if (isNaN(parameterLimit) || parameterLimit < 1) {
+ throw new TypeError('option parameterLimit must be a positive number')
+ }
+
+ if (isFinite(parameterLimit)) {
+ parameterLimit = parameterLimit | 0
+ }
+
+ return function queryparse (body) {
+ var paramCount = parameterCount(body, parameterLimit)
+
+ if (paramCount === undefined) {
+ debug('too many parameters')
+ throw createError(413, 'too many parameters', {
+ type: 'parameters.too.many'
+ })
+ }
+
+ debug('parse urlencoding')
+ return parse(body, undefined, undefined, { maxKeys: parameterLimit })
+ }
+}
+
+/**
+ * Get the simple type checker.
+ *
+ * @param {string} type
+ * @return {function}
+ */
+
+function typeChecker (type) {
+ return function checkType (req) {
+ return Boolean(typeis(req, type))
+ }
+}
diff --git a/node_modules/body-parser/lib/utils.js b/node_modules/body-parser/lib/utils.js
deleted file mode 100644
index e0bf974..0000000
--- a/node_modules/body-parser/lib/utils.js
+++ /dev/null
@@ -1,98 +0,0 @@
-'use strict'
-
-/**
- * Module dependencies.
- */
-
-var bytes = require('bytes')
-var contentType = require('content-type')
-var typeis = require('type-is')
-
-/**
- * Module exports.
- */
-module.exports = {
- getCharset,
- normalizeOptions,
- passthrough
-}
-
-/**
- * Get the charset of a request.
- *
- * @param {Object} req
- * @returns {string | undefined}
- * @private
- */
-function getCharset (req) {
- try {
- return (contentType.parse(req).parameters.charset || '').toLowerCase()
- } catch {
- return undefined
- }
-}
-
-/**
- * Get the simple type checker.
- *
- * @param {string | string[]} type
- * @returns {Function}
- * @private
- */
-function typeChecker (type) {
- return function checkType (req) {
- return Boolean(typeis(req, type))
- }
-}
-
-/**
- * Normalizes the common options for all parsers.
- *
- * @param {Object} options options to normalize
- * @param {string | string[] | Function} defaultType default content type(s) or a function to determine it
- * @returns {Object}
- * @private
- */
-function normalizeOptions (options, defaultType) {
- if (!defaultType) {
- // Parsers must define a default content type
- throw new TypeError('defaultType must be provided')
- }
-
- var inflate = options?.inflate !== false
- var limit = typeof options?.limit !== 'number'
- ? bytes.parse(options?.limit || '100kb')
- : options?.limit
- var type = options?.type || defaultType
- var verify = options?.verify || false
- var defaultCharset = options?.defaultCharset || 'utf-8'
-
- if (verify !== false && typeof verify !== 'function') {
- throw new TypeError('option verify must be function')
- }
-
- // create the appropriate type checking function
- var shouldParse = typeof type !== 'function'
- ? typeChecker(type)
- : type
-
- return {
- inflate,
- limit,
- verify,
- defaultCharset,
- shouldParse
- }
-}
-
-/**
- * Passthrough function that returns input unchanged.
- * Used by parsers that don't need to transform the data.
- *
- * @param {*} value
- * @returns {*}
- * @private
- */
-function passthrough (value) {
- return value
-}
diff --git a/node_modules/body-parser/package.json b/node_modules/body-parser/package.json
index 486878a..c8e61c1 100644
--- a/node_modules/body-parser/package.json
+++ b/node_modules/body-parser/package.json
@@ -1,52 +1,55 @@
{
"name": "body-parser",
"description": "Node.js body parsing middleware",
- "version": "2.2.2",
+ "version": "1.20.4",
"contributors": [
"Douglas Christopher Wilson ",
"Jonathan Ong (http://jongleberry.com)"
],
"license": "MIT",
"repository": "expressjs/body-parser",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- },
"dependencies": {
- "bytes": "^3.1.2",
- "content-type": "^1.0.5",
- "debug": "^4.4.3",
- "http-errors": "^2.0.0",
- "iconv-lite": "^0.7.0",
- "on-finished": "^2.4.1",
- "qs": "^6.14.1",
- "raw-body": "^3.0.1",
- "type-is": "^2.0.1"
+ "bytes": "~3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "~1.2.0",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "on-finished": "~2.4.1",
+ "qs": "~6.14.0",
+ "raw-body": "~2.5.3",
+ "type-is": "~1.6.18",
+ "unpipe": "~1.0.0"
},
"devDependencies": {
- "eslint": "^8.57.1",
- "eslint-config-standard": "^14.1.1",
- "eslint-plugin-import": "^2.31.0",
- "eslint-plugin-markdown": "^3.0.1",
- "eslint-plugin-node": "^11.1.0",
- "eslint-plugin-promise": "^6.6.0",
- "eslint-plugin-standard": "^4.1.0",
- "mocha": "^11.1.0",
- "nyc": "^17.1.0",
- "supertest": "^7.0.0"
+ "eslint": "8.34.0",
+ "eslint-config-standard": "14.1.1",
+ "eslint-plugin-import": "2.27.5",
+ "eslint-plugin-markdown": "3.0.0",
+ "eslint-plugin-node": "11.1.0",
+ "eslint-plugin-promise": "6.1.1",
+ "eslint-plugin-standard": "4.1.0",
+ "methods": "1.1.2",
+ "mocha": "10.2.0",
+ "nyc": "15.1.0",
+ "safe-buffer": "5.2.1",
+ "supertest": "6.3.3"
},
"files": [
"lib/",
"LICENSE",
+ "HISTORY.md",
"index.js"
],
"engines": {
- "node": ">=18"
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
},
"scripts": {
"lint": "eslint .",
- "test": "mocha --reporter spec --check-leaks test/",
- "test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
+ "test": "mocha --require test/support/env --reporter spec --check-leaks --bail test/",
+ "test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test"
}
}
diff --git a/node_modules/complex.js/LICENSE b/node_modules/complex.js/LICENSE
deleted file mode 100644
index 8741015..0000000
--- a/node_modules/complex.js/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2025 Robert Eisele
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/node_modules/complex.js/README.md b/node_modules/complex.js/README.md
deleted file mode 100644
index 8e3e2ec..0000000
--- a/node_modules/complex.js/README.md
+++ /dev/null
@@ -1,373 +0,0 @@
-# Complex.js - ℂ in JavaScript
-
-[](https://npmjs.org/package/complex.js "View this project on npm")
-[](http://opensource.org/licenses/MIT)
-
-Complex.js is a well tested JavaScript library to work with [complex number arithmetic](https://raw.org/book/analysis/complex-numbers/) in JavaScript. It implements every elementary complex number manipulation function and the API is intentionally similar to [Fraction.js](https://github.com/rawify/Fraction.js). Furthermore, it's the basis of [Polynomial.js](https://github.com/rawify/Polynomial.js) and [Math.js](https://github.com/josdejong/mathjs).
-
-
-## Examples
-
-
-```js
-let Complex = require('complex.js');
-
-let c = new Complex("99.3+8i");
-c.mul({re: 3, im: 9}).div(4.9).sub(3, 2);
-```
-
-A classical use case for complex numbers is solving quadratic equations `ax² + bx + c = 0` for all `a, b, c ∈ ℝ`:
-
-```js
-
-function quadraticRoot(a, b, c) {
- let sqrt = Complex(b * b - 4 * a * c).sqrt()
- let x1 = Complex(-b).add(sqrt).div(2 * a)
- let x2 = Complex(-b).sub(sqrt).div(2 * a)
- return {x1, x2}
-}
-
-// quadraticRoot(1, 4, 5) -> -2 ± i
-```
-
-For cubic roots have a look at [RootFinder](https://github.com/rawify/RootFinder.js) which uses Complex.js.
-
-## Parser
-
-
-Any function (see below) as well as the constructor of the *Complex* class parses its input like this.
-
-You can pass either Objects, Doubles or Strings.
-
-### Objects
-
-```javascript
-new Complex({re: real, im: imaginary});
-new Complex({arg: angle, abs: radius});
-new Complex({phi: angle, r: radius});
-new Complex([real, imaginary]); // Vector/Array syntax
-```
-If there are other attributes on the passed object, they're not getting preserved and have to be merged manually.
-
-**Note:** Object attributes have to be of type Number to avoid undefined behavior.
-
-### Doubles
-
-```javascript
-new Complex(55.4);
-```
-
-### Strings
-
-```javascript
-new Complex("123.45");
-new Complex("15+3i");
-new Complex("i");
-```
-
-### Two arguments
-
-```javascript
-new Complex(3, 2); // 3+2i
-```
-
-## Attributes
-
-
-Every complex number object exposes its real and imaginary part as attribute `re` and `im`:
-
-```javascript
-let c = new Complex(3, 2);
-
-console.log("Real part:", c.re); // 3
-console.log("Imaginary part:", c.im); // 2
-```
-
-## Functions
-
-
-Complex sign()
----
-Returns the complex sign, defined as the complex number normalized by it's absolute value
-
-Complex add(n)
----
-Adds another complex number
-
-Complex sub(n)
----
-Subtracts another complex number
-
-Complex mul(n)
----
-Multiplies the number with another complex number
-
-Complex div(n)
----
-Divides the number by another complex number
-
-Complex pow(exp)
----
-Returns the number raised to the complex exponent (Note: `Complex.ZERO.pow(0) = Complex.ONE` by convention)
-
-Complex sqrt()
----
-Returns the complex square root of the number
-
-Complex exp(n)
----
-Returns `e^n` with complex exponent `n`.
-
-Complex log()
----
-Returns the natural logarithm (base `E`) of the actual complex number
-
-_Note:_ The logarithm to a different base can be calculated with `z.log().div(Math.log(base))`.
-
-double abs()
----
-Calculates the magnitude of the complex number
-
-double arg()
----
-Calculates the angle of the complex number
-
-Complex inverse()
----
-Calculates the multiplicative inverse of the complex number (1 / z)
-
-Complex conjugate()
----
-Calculates the conjugate of the complex number (multiplies the imaginary part with -1)
-
-Complex neg()
----
-Negates the number (multiplies both the real and imaginary part with -1) in order to get the additive inverse
-
-Complex floor([places=0])
----
-Floors the complex number parts towards zero
-
-Complex ceil([places=0])
----
-Ceils the complex number parts off zero
-
-Complex round([places=0])
----
-Rounds the complex number parts
-
-boolean equals(n)
----
-Checks if both numbers are exactly the same, if both numbers are infinite they
-are considered **not** equal.
-
-boolean isNaN()
----
-Checks if the given number is not a number
-
-boolean isFinite()
----
-Checks if the given number is finite
-
-Complex clone()
----
-Returns a new Complex instance with the same real and imaginary properties
-
-Array toVector()
----
-Returns a Vector of the actual complex number with two components
-
-String toString()
----
-Returns a string representation of the actual number. As of v1.9.0 the output is a bit more human readable
-
-```javascript
-new Complex(1, 2).toString(); // 1 + 2i
-new Complex(0, 1).toString(); // i
-new Complex(9, 0).toString(); // 9
-new Complex(1, 1).toString(); // 1 + i
-```
-
-double valueOf()
----
-Returns the real part of the number if imaginary part is zero. Otherwise `null`
-
-
-## Trigonometric functions
-
-The following trigonometric functions are defined on Complex.js:
-
-| Trig | Arcus | Hyperbolic | Area-Hyperbolic |
-|------|-------|------------|------------------|
-| sin() | asin() | sinh() | asinh() |
-| cos() | acos() | cosh() | acosh() |
-| tan() | atan() | tanh() | atanh() |
-| cot() | acot() | coth() | acoth() |
-| sec() | asec() | sech() | asech() |
-| csc() | acsc() | csch() | acsch() |
-
-**Notes on branches & ranges.** Inverse trig on ℂ needs a branch choice. For `acot` there are two real-axis conventions:
-
-* **(Chosen) Textbook range (0, π) on ℝ.**
- Gives familiar real values (`acot(1)=π/4`, `acot(0)=π/2`, `acot(-1)=3π/4`). With the principal complex branch this **necessarily causes a π jump across the negative real axis** (e.g., near `-1±i0` → `-π/4`, but on `-1` → `3π/4`).
- **We implement this with `atan2(1, x)`** to select the correct quadrant and handle `x=0`.
-
-* **Alternative range (−π/2, π/2] on ℝ.**
- Makes `acot(-1) = -π/4` and can avoid that specific jump **only if the entire complex branch is changed to match**. Using plain `atan(1/x)` silently adopts this convention, changes real outputs, is undefined at `x=0`, and still wouldn’t resolve the complex behavior without a broader policy change.
-
-We therefore prefer predictable, textbook real values and robust quadrant handling—hence `atan2(1, x)`-accepting the implied branch cut on ℝ⁻ by design.
-
-
-## Geometric Equivalence
-
-
-Complex numbers can also be seen as a vector in the 2D space. Here is a simple overview of basic operations and how to implement them with complex.js:
-
-New vector
----
-```js
-let v1 = new Complex(1, 0);
-let v2 = new Complex(1, 1);
-```
-
-Scale vector
----
-```js
-scale(v1, factor):= v1.mul(factor)
-```
-
-Vector norm
----
-```js
-norm(v):= v.abs()
-```
-
-Translate vector
----
-```js
-translate(v1, v2):= v1.add(v2)
-```
-
-Rotate vector around center
----
-```js
-rotate(v, angle):= v.mul({abs: 1, arg: angle})
-```
-
-Rotate vector around a point
----
-```js
-rotate(v, p, angle):= v.sub(p).mul({abs: 1, arg: angle}).add(p)
-```
-
-Distance to another vector
----
-```js
-distance(v1, v2):= v1.sub(v2).abs()
-```
-
-## Constants
-
-
-Complex.ZERO
----
-A complex zero value (south pole on the Riemann Sphere)
-
-Complex.ONE
----
-A complex one instance
-
-Complex.INFINITY
----
-A complex infinity value (north pole on the Riemann Sphere)
-
-Complex.NAN
----
-A complex NaN value (not on the Riemann Sphere)
-
-Complex.I
----
-An imaginary number i instance
-
-Complex.PI
----
-A complex PI instance
-
-Complex.E
----
-A complex euler number instance
-
-Complex.EPSILON
----
-A small epsilon value used for `equals()` comparison in order to circumvent double imprecision.
-
-
-## Installation
-
-You can install `Complex.js` via npm:
-
-```bash
-npm install complex.js
-```
-
-Or with yarn:
-
-```bash
-yarn add complex.js
-```
-
-Alternatively, download or clone the repository:
-
-```bash
-git clone https://github.com/rawify/Complex.js
-```
-
-## Usage
-
-Include the `complex.min.js` file in your project:
-
-```html
-
-
-```
-
-Or in a Node.js project:
-
-```javascript
-const Complex = require('complex.js');
-```
-
-or
-
-```javascript
-import Complex from 'complex.js';
-```
-
-
-## Coding Style
-
-As every library I publish, Complex.js is also built to be as small as possible after compressing it with Google Closure Compiler in advanced mode. Thus the coding style orientates a little on maxing-out the compression rate. Please make sure you keep this style if you plan to extend the library.
-
-## Building the library
-
-After cloning the Git repository run:
-
-```
-npm install
-npm run build
-```
-
-## Run a test
-
-Testing the source against the shipped test suite is as easy as
-
-```
-npm run test
-```
-
-## Copyright and Licensing
-
-Copyright (c) 2025, [Robert Eisele](https://raw.org/)
-Licensed under the MIT license.
diff --git a/node_modules/complex.js/complex.d.ts b/node_modules/complex.js/complex.d.ts
deleted file mode 100644
index 37003f1..0000000
--- a/node_modules/complex.js/complex.d.ts
+++ /dev/null
@@ -1,323 +0,0 @@
-type AValue =
- | Complex
- | { im: number; re: number }
- | { abs: number; arg: number }
- | { r: number; phi: number }
- | [number, number]
- | string
- | number
- | null
- | undefined;
-type BValue = number | undefined;
-
-export function Complex(a: AValue, b?: BValue): Complex;
-
-export default Complex;
-
-/**
- *
- * This class allows the manipulation of complex numbers.
- * You can pass a complex number in different formats. Either as object, double, string or two integer parameters.
- *
- * Object form
- * { re: , im: }
- * { arg: , abs: }
- * { phi: , r: }
- *
- * Array / Vector form
- * [ real, imaginary ]
- *
- * Double form
- * 99.3 - Single double value
- *
- * String form
- * '23.1337' - Simple real number
- * '15+3i' - a simple complex number
- * '3-i' - a simple complex number
- *
- * Example:
- *
- * var c = new Complex('99.3+8i');
- * c.mul({r: 3, i: 9}).div(4.9).sub(3, 2);
- *
- */
-export class Complex {
- re: number;
- im: number;
-
- constructor(a: AValue, b?: BValue);
-
- /**
- * Calculates the sign of a complex number, which is a normalized complex
- *
- */
- sign(): Complex;
- /**
- * Adds two complex numbers
- *
- */
- add(a: AValue, b?: BValue): Complex;
- /**
- * Subtracts two complex numbers
- *
- */
- sub(a: AValue, b?: BValue): Complex;
- /**
- * Multiplies two complex numbers
- *
- */
- mul(a: AValue, b?: BValue): Complex;
- /**
- * Divides two complex numbers
- *
- */
- div(a: AValue, b?: BValue): Complex;
- /**
- * Calculate the power of two complex numbers
- *
- */
- pow(a: AValue, b?: BValue): Complex;
- /**
- * Calculate the complex square root
- *
- */
- sqrt(): Complex;
- /**
- * Calculate the complex exponent
- *
- */
- exp(): Complex;
- /**
- * Calculate the complex exponent and subtracts one.
- *
- * This may be more accurate than `Complex(x).exp().sub(1)` if
- * `x` is small.
- *
- */
- expm1(): Complex;
- /**
- * Calculate the natural log
- *
- */
- log(): Complex;
- /**
- * Calculate the magnitude of the complex number
- *
- */
- abs(): number;
- /**
- * Calculate the angle of the complex number
- *
- */
- arg(): number;
- /**
- * Calculate the sine of the complex number
- *
- */
- sin(): Complex;
- /**
- * Calculate the cosine
- *
- */
- cos(): Complex;
- /**
- * Calculate the tangent
- *
- */
- tan(): Complex;
- /**
- * Calculate the cotangent
- *
- */
- cot(): Complex;
- /**
- * Calculate the secant
- *
- */
- sec(): Complex;
- /**
- * Calculate the cosecans
- *
- */
- csc(): Complex;
- /**
- * Calculate the complex arcus sinus
- *
- */
- asin(): Complex;
- /**
- * Calculate the complex arcus cosinus
- *
- */
- acos(): Complex;
- /**
- * Calculate the complex arcus tangent
- *
- */
- atan(): Complex;
- /**
- * Calculate the complex arcus cotangent
- *
- */
- acot(): Complex;
- /**
- * Calculate the complex arcus secant
- *
- */
- asec(): Complex;
- /**
- * Calculate the complex arcus cosecans
- *
- */
- acsc(): Complex;
- /**
- * Calculate the complex sinh
- *
- */
- sinh(): Complex;
- /**
- * Calculate the complex cosh
- *
- */
- cosh(): Complex;
- /**
- * Calculate the complex tanh
- *
- */
- tanh(): Complex;
- /**
- * Calculate the complex coth
- *
- */
- coth(): Complex;
- /**
- * Calculate the complex coth
- *
- */
- csch(): Complex;
- /**
- * Calculate the complex sech
- *
- */
- sech(): Complex;
- /**
- * Calculate the complex asinh
- *
- */
- asinh(): Complex;
- /**
- * Calculate the complex acosh
- *
- */
- acosh(): Complex;
- /**
- * Calculate the complex atanh
- *
- */
- atanh(): Complex;
- /**
- * Calculate the complex acoth
- *
- */
- acoth(): Complex;
- /**
- * Calculate the complex acsch
- *
- */
- acsch(): Complex;
- /**
- * Calculate the complex asech
- *
- */
- asech(): Complex;
- /**
- * Calculate the complex inverse 1/z
- *
- */
- inverse(): Complex;
- /**
- * Returns the complex conjugate
- *
- */
- conjugate(): Complex;
- /**
- * Gets the negated complex number
- *
- */
- neg(): Complex;
- /**
- * Ceils the actual complex number
- *
- */
- ceil(places: number): Complex;
- /**
- * Floors the actual complex number
- *
- */
- floor(places: number): Complex;
- /**
- * Ceils the actual complex number
- *
- */
- round(places: number): Complex;
- /**
- * Compares two complex numbers
- *
- * **Note:** new Complex(Infinity).equals(Infinity) === false
- *
- */
- equals(a: AValue, b?: BValue): boolean;
- /**
- * Clones the actual object
- *
- */
- clone(): Complex;
- /**
- * Gets a string of the actual complex number
- *
- */
- toString(): string;
- /**
- * Returns the actual number as a vector
- *
- */
- toVector(): number[];
- /**
- * Returns the actual real value of the current object
- *
- * @returns {number|null}
- */
- valueOf(): number | null;
- /**
- * Determines whether a complex number is not on the Riemann sphere.
- *
- */
- isNaN(): boolean;
- /**
- * Determines whether or not a complex number is at the zero pole of the
- * Riemann sphere.
- *
- */
- isZero(): boolean;
- /**
- * Determines whether a complex number is not at the infinity pole of the
- * Riemann sphere.
- *
- */
- isFinite(): boolean;
- /**
- * Determines whether or not a complex number is at the infinity pole of the
- * Riemann sphere.
- *
- */
- isInfinite(): boolean;
-
- static ZERO: Complex;
- static ONE: Complex;
- static I: Complex;
- static PI: Complex;
- static E: Complex;
- static INFINITY: Complex;
- static NAN: Complex;
- static EPSILON: number;
-}
diff --git a/node_modules/complex.js/dist/complex.js b/node_modules/complex.js/dist/complex.js
deleted file mode 100644
index 11ff7ec..0000000
--- a/node_modules/complex.js/dist/complex.js
+++ /dev/null
@@ -1,1476 +0,0 @@
-'use strict';
-
-/**
- *
- * This class allows the manipulation of complex numbers.
- * You can pass a complex number in different formats. Either as object, double, string or two integer parameters.
- *
- * Object form
- * { re: , im: }
- * { arg: , abs: }
- * { phi: , r: }
- *
- * Array / Vector form
- * [ real, imaginary ]
- *
- * Double form
- * 99.3 - Single double value
- *
- * String form
- * '23.1337' - Simple real number
- * '15+3i' - a simple complex number
- * '3-i' - a simple complex number
- *
- * Example:
- *
- * const c = new Complex('99.3+8i');
- * c.mul({r: 3, i: 9}).div(4.9).sub(3, 2);
- *
- */
-
-
-const cosh = Math.cosh || function (x) {
- return Math.abs(x) < 1e-9 ? 1 - x : (Math.exp(x) + Math.exp(-x)) * 0.5;
-};
-
-const sinh = Math.sinh || function (x) {
- return Math.abs(x) < 1e-9 ? x : (Math.exp(x) - Math.exp(-x)) * 0.5;
-};
-
-/**
- * Calculates cos(x) - 1 using Taylor series if x is small (-¼π ≤ x ≤ ¼π).
- *
- * @param {number} x
- * @returns {number} cos(x) - 1
- */
-const cosm1 = x => {
- // cos(x) - 1 = − 2sin^2(x / 2)
- const s = Math.sin(0.5 * x);
- return -2 * s * s;
-};
-
-const hypot = function (x, y) {
-
- x = Math.abs(x);
- y = Math.abs(y);
-
- // Ensure `x` is the larger value
- if (x < y) [x, y] = [y, x];
-
- // If both are below the threshold, use straightforward Pythagoras
- if (x < 1e8) return Math.sqrt(x * x + y * y);
-
- // For larger values, scale to avoid overflow
- y /= x;
- return x * Math.sqrt(1 + y * y);
-};
-
-const parser_exit = function () {
- throw SyntaxError('Invalid Param');
-};
-
-/**
- * Calculates log(sqrt(a^2+b^2)) in a way to avoid overflows
- *
- * @param {number} a
- * @param {number} b
- * @returns {number}
- */
-function logHypot(a, b) {
-
- const _a = Math.abs(a);
- const _b = Math.abs(b);
-
- if (a === 0) {
- return Math.log(_b);
- }
-
- if (b === 0) {
- return Math.log(_a);
- }
-
- if (_a < 3000 && _b < 3000) {
- return Math.log(a * a + b * b) * 0.5;
- }
-
- /* I got 4 ideas to compute this property without overflow:
- *
- * Testing 1000000 times with random samples for a,b ∈ [1, 1000000000] against a big decimal library to get an error estimate
- *
- * 1. Only eliminate the square root: (OVERALL ERROR: 3.9122483030951116e-11)
-
- Math.log(a * a + b * b) / 2
-
- *
- *
- * 2. Try to use the non-overflowing pythagoras: (OVERALL ERROR: 8.889760039210159e-10)
-
- const fn = function(a, b) {
- a = Math.abs(a);
- b = Math.abs(b);
- let t = Math.min(a, b);
- a = Math.max(a, b);
- t = t / a;
-
- return Math.log(a) + Math.log(1 + t * t) / 2;
- };
-
- * 3. Abuse the identity cos(atan(y/x) = x / sqrt(x^2+y^2): (OVERALL ERROR: 3.4780178737037204e-10)
-
- Math.log(a / Math.cos(Math.atan2(b, a)))
-
- * 4. Use 3. and apply log rules: (OVERALL ERROR: 1.2014087502620896e-9)
-
- Math.log(a) - Math.log(Math.cos(Math.atan2(b, a)))
-
- */
-
- a = a * 0.5;
- b = b * 0.5;
-
- return 0.5 * Math.log(a * a + b * b) + Math.LN2;
-}
-
-const P = { 're': 0, 'im': 0 };
-const parse = function (a, b) {
-
- const z = P;
-
- if (a === undefined || a === null) {
- z['re'] =
- z['im'] = 0;
- } else if (b !== undefined) {
- z['re'] = a;
- z['im'] = b;
- } else
- switch (typeof a) {
-
- case 'object':
-
- if ('im' in a && 're' in a) {
- z['re'] = a['re'];
- z['im'] = a['im'];
- } else if ('abs' in a && 'arg' in a) {
- if (!isFinite(a['abs']) && isFinite(a['arg'])) {
- return Complex['INFINITY'];
- }
- z['re'] = a['abs'] * Math.cos(a['arg']);
- z['im'] = a['abs'] * Math.sin(a['arg']);
- } else if ('r' in a && 'phi' in a) {
- if (!isFinite(a['r']) && isFinite(a['phi'])) {
- return Complex['INFINITY'];
- }
- z['re'] = a['r'] * Math.cos(a['phi']);
- z['im'] = a['r'] * Math.sin(a['phi']);
- } else if (a.length === 2) { // Quick array check
- z['re'] = a[0];
- z['im'] = a[1];
- } else {
- parser_exit();
- }
- break;
-
- case 'string':
-
- z['im'] = /* void */
- z['re'] = 0;
-
- const tokens = a.replace(/_/g, '')
- .match(/\d+\.?\d*e[+-]?\d+|\d+\.?\d*|\.\d+|./g);
- let plus = 1;
- let minus = 0;
-
- if (tokens === null) {
- parser_exit();
- }
-
- for (let i = 0; i < tokens.length; i++) {
-
- const c = tokens[i];
-
- if (c === ' ' || c === '\t' || c === '\n') {
- /* void */
- } else if (c === '+') {
- plus++;
- } else if (c === '-') {
- minus++;
- } else if (c === 'i' || c === 'I') {
-
- if (plus + minus === 0) {
- parser_exit();
- }
-
- if (tokens[i + 1] !== ' ' && !isNaN(tokens[i + 1])) {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + tokens[i + 1]);
- i++;
- } else {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + '1');
- }
- plus = minus = 0;
-
- } else {
-
- if (plus + minus === 0 || isNaN(c)) {
- parser_exit();
- }
-
- if (tokens[i + 1] === 'i' || tokens[i + 1] === 'I') {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + c);
- i++;
- } else {
- z['re'] += parseFloat((minus % 2 ? '-' : '') + c);
- }
- plus = minus = 0;
- }
- }
-
- // Still something on the stack
- if (plus + minus > 0) {
- parser_exit();
- }
- break;
-
- case 'number':
- z['im'] = 0;
- z['re'] = a;
- break;
-
- default:
- parser_exit();
- }
-
- if (isNaN(z['re']) || isNaN(z['im'])) {
- // If a calculation is NaN, we treat it as NaN and don't throw
- //parser_exit();
- }
-
- return z;
-};
-
-/**
- * @constructor
- * @returns {Complex}
- */
-function Complex(a, b) {
-
- if (!(this instanceof Complex)) {
- return new Complex(a, b);
- }
-
- const z = parse(a, b);
-
- this['re'] = z['re'];
- this['im'] = z['im'];
-}
-
-Complex.prototype = {
-
- 're': 0,
- 'im': 0,
-
- /**
- * Calculates the sign of a complex number, which is a normalized complex
- *
- * @returns {Complex}
- */
- 'sign': function () {
-
- const abs = hypot(this['re'], this['im']);
-
- return new Complex(
- this['re'] / abs,
- this['im'] / abs);
- },
-
- /**
- * Adds two complex numbers
- *
- * @returns {Complex}
- */
- 'add': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
-
- if (tInfin || zInfin) {
-
- if (tInfin && zInfin) {
- // Infinity + Infinity = NaN
- return Complex['NAN'];
- }
- // Infinity + z = Infinity { where z != Infinity }
- return Complex['INFINITY'];
- }
-
- return new Complex(
- this['re'] + z['re'],
- this['im'] + z['im']);
- },
-
- /**
- * Subtracts two complex numbers
- *
- * @returns {Complex}
- */
- 'sub': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
-
- if (tInfin || zInfin) {
-
- if (tInfin && zInfin) {
- // Infinity - Infinity = NaN
- return Complex['NAN'];
- }
- // Infinity - z = Infinity { where z != Infinity }
- return Complex['INFINITY'];
- }
-
- return new Complex(
- this['re'] - z['re'],
- this['im'] - z['im']);
- },
-
- /**
- * Multiplies two complex numbers
- *
- * @returns {Complex}
- */
- 'mul': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- // Infinity * 0 = NaN
- if (tInfin && zIsZero || zInfin && tIsZero) {
- return Complex['NAN'];
- }
-
- // Infinity * z = Infinity { where z != 0 }
- if (tInfin || zInfin) {
- return Complex['INFINITY'];
- }
-
- // Shortcut for real values
- if (z['im'] === 0 && this['im'] === 0) {
- return new Complex(this['re'] * z['re'], 0);
- }
-
- return new Complex(
- this['re'] * z['re'] - this['im'] * z['im'],
- this['re'] * z['im'] + this['im'] * z['re']);
- },
-
- /**
- * Divides two complex numbers
- *
- * @returns {Complex}
- */
- 'div': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- // 0 / 0 = NaN and Infinity / Infinity = NaN
- if (tIsZero && zIsZero || tInfin && zInfin) {
- return Complex['NAN'];
- }
-
- // Infinity / 0 = Infinity
- if (zIsZero || tInfin) {
- return Complex['INFINITY'];
- }
-
- // 0 / Infinity = 0
- if (tIsZero || zInfin) {
- return Complex['ZERO'];
- }
-
- if (0 === z['im']) {
- // Divisor is real
- return new Complex(this['re'] / z['re'], this['im'] / z['re']);
- }
-
- if (Math.abs(z['re']) < Math.abs(z['im'])) {
-
- const x = z['re'] / z['im'];
- const t = z['re'] * x + z['im'];
-
- return new Complex(
- (this['re'] * x + this['im']) / t,
- (this['im'] * x - this['re']) / t);
-
- } else {
-
- const x = z['im'] / z['re'];
- const t = z['im'] * x + z['re'];
-
- return new Complex(
- (this['re'] + this['im'] * x) / t,
- (this['im'] - this['re'] * x) / t);
- }
- },
-
- /**
- * Calculate the power of two complex numbers
- *
- * @returns {Complex}
- */
- 'pow': function (a, b) {
-
- const z = parse(a, b);
-
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- if (zIsZero) {
- return Complex['ONE'];
- }
-
- // If the exponent is real
- if (z['im'] === 0) {
-
- if (this['im'] === 0 && this['re'] > 0) {
-
- return new Complex(Math.pow(this['re'], z['re']), 0);
-
- } else if (this['re'] === 0) { // If base is fully imaginary
-
- switch ((z['re'] % 4 + 4) % 4) {
- case 0:
- return new Complex(Math.pow(this['im'], z['re']), 0);
- case 1:
- return new Complex(0, Math.pow(this['im'], z['re']));
- case 2:
- return new Complex(-Math.pow(this['im'], z['re']), 0);
- case 3:
- return new Complex(0, -Math.pow(this['im'], z['re']));
- }
- }
- }
-
- /* I couldn't find a good formula, so here is a derivation and optimization
- *
- * z_1^z_2 = (a + bi)^(c + di)
- * = exp((c + di) * log(a + bi)
- * = pow(a^2 + b^2, (c + di) / 2) * exp(i(c + di)atan2(b, a))
- * =>...
- * Re = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * cos(d * log(a^2 + b^2) / 2 + c * atan2(b, a))
- * Im = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * sin(d * log(a^2 + b^2) / 2 + c * atan2(b, a))
- *
- * =>...
- * Re = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * cos(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a))
- * Im = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * sin(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a))
- *
- * =>
- * Re = exp(c * logsq2 - d * arg(z_1)) * cos(d * logsq2 + c * arg(z_1))
- * Im = exp(c * logsq2 - d * arg(z_1)) * sin(d * logsq2 + c * arg(z_1))
- *
- */
-
- if (tIsZero && z['re'] > 0) { // Same behavior as Wolframalpha, Zero if real part is zero
- return Complex['ZERO'];
- }
-
- const arg = Math.atan2(this['im'], this['re']);
- const loh = logHypot(this['re'], this['im']);
-
- let re = Math.exp(z['re'] * loh - z['im'] * arg);
- let im = z['im'] * loh + z['re'] * arg;
- return new Complex(
- re * Math.cos(im),
- re * Math.sin(im));
- },
-
- /**
- * Calculate the complex square root
- *
- * @returns {Complex}
- */
- 'sqrt': function () {
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
- // Real number case
- if (a >= 0) {
- return new Complex(Math.sqrt(a), 0);
- } else {
- return new Complex(0, Math.sqrt(-a));
- }
- }
-
- const r = hypot(a, b);
-
- let re = Math.sqrt(0.5 * (r + Math.abs(a))); // sqrt(2x) / 2 = sqrt(x / 2)
- let im = Math.abs(b) / (2 * re);
-
- if (a >= 0) {
- return new Complex(re, b < 0 ? -im : im);
- } else {
- return new Complex(im, b < 0 ? -re : re);
- }
- },
-
- /**
- * Calculate the complex exponent
- *
- * @returns {Complex}
- */
- 'exp': function () {
-
- const er = Math.exp(this['re']);
-
- if (this['im'] === 0) {
- return new Complex(er, 0);
- }
- return new Complex(
- er * Math.cos(this['im']),
- er * Math.sin(this['im']));
- },
-
- /**
- * Calculate the complex exponent and subtracts one.
- *
- * This may be more accurate than `Complex(x).exp().sub(1)` if
- * `x` is small.
- *
- * @returns {Complex}
- */
- 'expm1': function () {
-
- /**
- * exp(a + i*b) - 1
- = exp(a) * (cos(b) + j*sin(b)) - 1
- = expm1(a)*cos(b) + cosm1(b) + j*exp(a)*sin(b)
- */
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.expm1(a) * Math.cos(b) + cosm1(b),
- Math.exp(a) * Math.sin(b));
- },
-
- /**
- * Calculate the natural log
- *
- * @returns {Complex}
- */
- 'log': function () {
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0 && a > 0) {
- return new Complex(Math.log(a), 0);
- }
-
- return new Complex(
- logHypot(a, b),
- Math.atan2(b, a));
- },
-
- /**
- * Calculate the magnitude of the complex number
- *
- * @returns {number}
- */
- 'abs': function () {
-
- return hypot(this['re'], this['im']);
- },
-
- /**
- * Calculate the angle of the complex number
- *
- * @returns {number}
- */
- 'arg': function () {
-
- return Math.atan2(this['im'], this['re']);
- },
-
- /**
- * Calculate the sine of the complex number
- *
- * @returns {Complex}
- */
- 'sin': function () {
-
- // sin(z) = ( e^iz - e^-iz ) / 2i
- // = sin(a)cosh(b) + i cos(a)sinh(b)
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.sin(a) * cosh(b),
- Math.cos(a) * sinh(b));
- },
-
- /**
- * Calculate the cosine
- *
- * @returns {Complex}
- */
- 'cos': function () {
-
- // cos(z) = ( e^iz + e^-iz ) / 2
- // = cos(a)cosh(b) - i sin(a)sinh(b)
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.cos(a) * cosh(b),
- -Math.sin(a) * sinh(b));
- },
-
- /**
- * Calculate the tangent
- *
- * @returns {Complex}
- */
- 'tan': function () {
-
- // tan(z) = sin(z) / cos(z)
- // = ( e^iz - e^-iz ) / ( i( e^iz + e^-iz ) )
- // = ( e^2iz - 1 ) / i( e^2iz + 1 )
- // = ( sin(2a) + i sinh(2b) ) / ( cos(2a) + cosh(2b) )
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = Math.cos(a) + cosh(b);
-
- return new Complex(
- Math.sin(a) / d,
- sinh(b) / d);
- },
-
- /**
- * Calculate the cotangent
- *
- * @returns {Complex}
- */
- 'cot': function () {
-
- // cot(c) = i(e^(ci) + e^(-ci)) / (e^(ci) - e^(-ci))
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = Math.cos(a) - cosh(b);
-
- return new Complex(
- -Math.sin(a) / d,
- sinh(b) / d);
- },
-
- /**
- * Calculate the secant
- *
- * @returns {Complex}
- */
- 'sec': function () {
-
- // sec(c) = 2 / (e^(ci) + e^(-ci))
-
- const a = this['re'];
- const b = this['im'];
- const d = 0.5 * cosh(2 * b) + 0.5 * Math.cos(2 * a);
-
- return new Complex(
- Math.cos(a) * cosh(b) / d,
- Math.sin(a) * sinh(b) / d);
- },
-
- /**
- * Calculate the cosecans
- *
- * @returns {Complex}
- */
- 'csc': function () {
-
- // csc(c) = 2i / (e^(ci) - e^(-ci))
-
- const a = this['re'];
- const b = this['im'];
- const d = 0.5 * cosh(2 * b) - 0.5 * Math.cos(2 * a);
-
- return new Complex(
- Math.sin(a) * cosh(b) / d,
- -Math.cos(a) * sinh(b) / d);
- },
-
- /**
- * Calculate the complex arcus sinus
- *
- * @returns {Complex}
- */
- 'asin': function () {
-
- // asin(c) = -i * log(ci + sqrt(1 - c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- const t1 = new Complex(
- b * b - a * a + 1,
- -2 * a * b)['sqrt']();
-
- const t2 = new Complex(
- t1['re'] - b,
- t1['im'] + a)['log']();
-
- return new Complex(t2['im'], -t2['re']);
- },
-
- /**
- * Calculate the complex arcus cosinus
- *
- * @returns {Complex}
- */
- 'acos': function () {
-
- // acos(c) = i * log(c - i * sqrt(1 - c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- const t1 = new Complex(
- b * b - a * a + 1,
- -2 * a * b)['sqrt']();
-
- const t2 = new Complex(
- t1['re'] - b,
- t1['im'] + a)['log']();
-
- return new Complex(Math.PI / 2 - t2['im'], t2['re']);
- },
-
- /**
- * Calculate the complex arcus tangent
- *
- * @returns {Complex}
- */
- 'atan': function () {
-
- // atan(c) = i / 2 log((i + x) / (i - x))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0) {
-
- if (b === 1) {
- return new Complex(0, Infinity);
- }
-
- if (b === -1) {
- return new Complex(0, -Infinity);
- }
- }
-
- const d = a * a + (1.0 - b) * (1.0 - b);
-
- const t1 = new Complex(
- (1 - b * b - a * a) / d,
- -2 * a / d).log();
-
- return new Complex(-0.5 * t1['im'], 0.5 * t1['re']);
- },
-
- /**
- * Calculate the complex arcus cotangent
- *
- * @returns {Complex}
- */
- 'acot': function () {
-
- // acot(c) = i / 2 log((c - i) / (c + i))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
- return new Complex(Math.atan2(1, a), 0);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).atan()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).atan();
- },
-
- /**
- * Calculate the complex arcus secant
- *
- * @returns {Complex}
- */
- 'asec': function () {
-
- // asec(c) = -i * log(1 / c + sqrt(1 - i / c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0 && b === 0) {
- return new Complex(0, Infinity);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).acos()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).acos();
- },
-
- /**
- * Calculate the complex arcus cosecans
- *
- * @returns {Complex}
- */
- 'acsc': function () {
-
- // acsc(c) = -i * log(i / c + sqrt(1 - 1 / c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0 && b === 0) {
- return new Complex(Math.PI / 2, Infinity);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).asin()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).asin();
- },
-
- /**
- * Calculate the complex sinh
- *
- * @returns {Complex}
- */
- 'sinh': function () {
-
- // sinh(c) = (e^c - e^-c) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- sinh(a) * Math.cos(b),
- cosh(a) * Math.sin(b));
- },
-
- /**
- * Calculate the complex cosh
- *
- * @returns {Complex}
- */
- 'cosh': function () {
-
- // cosh(c) = (e^c + e^-c) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- cosh(a) * Math.cos(b),
- sinh(a) * Math.sin(b));
- },
-
- /**
- * Calculate the complex tanh
- *
- * @returns {Complex}
- */
- 'tanh': function () {
-
- // tanh(c) = (e^c - e^-c) / (e^c + e^-c)
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = cosh(a) + Math.cos(b);
-
- return new Complex(
- sinh(a) / d,
- Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex coth
- *
- * @returns {Complex}
- */
- 'coth': function () {
-
- // coth(c) = (e^c + e^-c) / (e^c - e^-c)
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = cosh(a) - Math.cos(b);
-
- return new Complex(
- sinh(a) / d,
- -Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex csch
- *
- * @returns {Complex}
- */
- 'csch': function () {
-
- // csch(c) = 2 / (e^c - e^-c)
-
- const a = this['re'];
- const b = this['im'];
- const d = Math.cos(2 * b) - cosh(2 * a);
-
- return new Complex(
- -2 * sinh(a) * Math.cos(b) / d,
- 2 * cosh(a) * Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex sech
- *
- * @returns {Complex}
- */
- 'sech': function () {
-
- // sech(c) = 2 / (e^c + e^-c)
-
- const a = this['re'];
- const b = this['im'];
- const d = Math.cos(2 * b) + cosh(2 * a);
-
- return new Complex(
- 2 * cosh(a) * Math.cos(b) / d,
- -2 * sinh(a) * Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex asinh
- *
- * @returns {Complex}
- */
- 'asinh': function () {
-
- // asinh(z) = log(z + sqrt(z^2 + 1))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- if (a === 0) {
- return new Complex(0, 0);
- }
-
- // Use |a| to keep asinh(-a) = -asinh(a) and avoid cancellation for large -a
- const x = Math.abs(a);
- const r = Math.log(x + Math.sqrt(x * x + 1));
-
- return new Complex(a < 0 ? -r : r, 0);
- }
-
- // z^2 + 1 = (a^2 - b^2 + 1) + i (2ab)
- const re2 = a * a - b * b + 1;
- const im2 = 2 * a * b;
-
- const t = new Complex(re2, im2)['sqrt'](); // sqrt(z^2 + 1)
-
- return new Complex(a + t['re'], b + t['im'])['log']();
- },
-
- /**
- * Calculate the complex acosh
- *
- * @returns {Complex}
- */
- 'acosh': function () {
-
- // acosh(z)= log(z + sqrt(z^2 - 1)) = log(z + sqrt(z - 1) * sqrt(z + 1))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- // z = a is real
- if (a > 1) {
- // acosh(a) = log(a + sqrt(a - 1) * sqrt(a + 1)), a > 1
- return new Complex(
- Math.log(a + Math.sqrt(a - 1) * Math.sqrt(a + 1)), 0);
- }
-
- if (a < -1) {
- // acosh(a) = log(-a + sqrt(a^2 - 1)) + i*pi, a < -1
- const t = Math.sqrt(a * a - 1);
- return new Complex(Math.log(-a + t), Math.PI);
- }
-
- // -1 <= a <= 1 : purely imaginary
- // acosh(a) = i * acos(a)
- return new Complex(0, Math.acos(a));
- }
-
- const t1 = new Complex(a - 1, b)['sqrt'](); // sqrt(z - 1)
- const t2 = new Complex(a + 1, b)['sqrt'](); // sqrt(z + 1)
-
- return new Complex(
- a + t1['re'] * t2['re'] - t1['im'] * t2['im'],
- b + t1['re'] * t2['im'] + t1['im'] * t2['re']
- )['log']();
- },
-
- /**
- * Calculate the complex atanh
- *
- * @returns {Complex}
- */
- 'atanh': function () {
-
- // atanh(z) = log((1 + z) / (1 - z)) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- if (a === 0) {
- return new Complex(0, 0);
- }
-
- if (a === 1) {
- // limit x -> 1^- atanh(x) = +Infinity
- return new Complex(Infinity, 0);
- }
-
- if (a === -1) {
- // limit x -> -1^+ atanh(x) = -Infinity
- return new Complex(-Infinity, 0);
- }
-
- if (-1 < a && a < 1) {
- // Purely real
- return new Complex(
- 0.5 * Math.log((1 + a) / (1 - a)),
- 0
- );
- }
-
- if (a > 1) {
- // Our branch: Im(atanh(a)) = -π/2 for a > 1
- const t = (a + 1) / (a - 1); // > 0
- return new Complex(
- 0.5 * Math.log(t),
- -Math.PI / 2
- );
- }
-
- // a < -1: Im(atanh(a)) = +π/2
- const t = (1 + a) / (1 - a); // < 0
- return new Complex(
- 0.5 * Math.log(-t), // log((1 - a)/(1 + a))
- Math.PI / 2
- );
- }
-
- // Use atanh(z) = 0.5 * Log((1+z)/(1-z)) with principal Log.
- const oneMinus = 1 - a;
- const onePlus = 1 + a;
- const d = oneMinus * oneMinus + b * b; // |1 - z|^2
-
- if (d === 0) {
- // (1 - z) == 0 for finite z only at z = 1+0i, already handled above.
- // If we ever get here, just propagate infinities consistently:
- return new Complex(
- (a !== -1) ? (a / 0) : 0,
- (b !== 0) ? (b / 0) : 0
- );
- }
-
- // (1 + z) / (1 - z) with a single complex division
- const xr = (onePlus * oneMinus - b * b) / d;
- const xi = (b * oneMinus + onePlus * b) / d;
-
- // 0.5 * log(xr + i xi)
- return new Complex(
- logHypot(xr, xi) / 2,
- Math.atan2(xi, xr) / 2
- );
- },
-
- /**
- * Calculate the complex acoth
- *
- * @returns {Complex}
- */
- 'acoth': function () {
-
- // acoth(z) = log((z + 1) / (z - 1)) / 2 = atanh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- // z = 0 -> acoth(0) = i * π / 2 (log((1+0)/(1-0))/2 = log(-1)/2)
- if (a === 0 && b === 0) {
- return new Complex(0, Math.PI / 2);
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1 / z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['atanh']();
- }
-
- // Fallback for weird infinities/NaNs: mirror other functions' style
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0
- )['atanh']();
- },
-
- /**
- * Calculate the complex acsch
- *
- * @returns {Complex}
- */
- 'acsch': function () {
-
- // acsch(c) = log((1+sqrt(1+c^2))/c) = = asinh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- // z = a real
- if (a === 0) {
- // acsch(0) -> +/- Infinity, we keep your previous behavior
- return new Complex(Infinity, 0);
- }
-
- // acsch(a) = asinh(1/a) = log(1/a + sqrt(1/a^2 + 1))
- const inv = 1 / a;
- return new Complex(
- Math.log(inv + Math.sqrt(inv * inv + 1)),
- 0
- );
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1/z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['asinh']();
- }
-
- // Handle 0 + 0i or infinities in the same spirit as your existing code
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0)['asinh']();
- },
-
- /**
- * Calculate the complex asech
- *
- * @returns {Complex}
- */
- 'asech': function () {
-
- // asech(z) = acosh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- if (this['isZero']()) {
- // asech(0) = acosh(∞) -> ∞
- return Complex['INFINITY'];
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1 / z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['acosh']();
- }
-
- // Fallback for weird infinities/NaNs
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0)['acosh']();
- },
-
- /**
- * Calculate the complex inverse 1/z
- *
- * @returns {Complex}
- */
- 'inverse': function () {
-
- // 1 / 0 = Infinity and 1 / Infinity = 0
- if (this['isZero']()) {
- return Complex['INFINITY'];
- }
-
- if (this['isInfinite']()) {
- return Complex['ZERO'];
- }
-
- const a = this['re'];
- const b = this['im'];
-
- const d = a * a + b * b;
-
- return new Complex(a / d, -b / d);
- },
-
- /**
- * Returns the complex conjugate
- *
- * @returns {Complex}
- */
- 'conjugate': function () {
-
- return new Complex(this['re'], -this['im']);
- },
-
- /**
- * Gets the negated complex number
- *
- * @returns {Complex}
- */
- 'neg': function () {
-
- return new Complex(-this['re'], -this['im']);
- },
-
- /**
- * Ceils the actual complex number
- *
- * @returns {Complex}
- */
- 'ceil': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.ceil(this['re'] * places) / places,
- Math.ceil(this['im'] * places) / places);
- },
-
- /**
- * Floors the actual complex number
- *
- * @returns {Complex}
- */
- 'floor': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.floor(this['re'] * places) / places,
- Math.floor(this['im'] * places) / places);
- },
-
- /**
- * Ceils the actual complex number
- *
- * @returns {Complex}
- */
- 'round': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.round(this['re'] * places) / places,
- Math.round(this['im'] * places) / places);
- },
-
- /**
- * Compares two complex numbers
- *
- * **Note:** new Complex(Infinity).equals(Infinity) === false
- *
- * @returns {boolean}
- */
- 'equals': function (a, b) {
-
- const z = parse(a, b);
-
- return Math.abs(z['re'] - this['re']) <= Complex['EPSILON'] &&
- Math.abs(z['im'] - this['im']) <= Complex['EPSILON'];
- },
-
- /**
- * Clones the actual object
- *
- * @returns {Complex}
- */
- 'clone': function () {
-
- return new Complex(this['re'], this['im']);
- },
-
- /**
- * Gets a string of the actual complex number
- *
- * @returns {string}
- */
- 'toString': function () {
-
- let a = this['re'];
- let b = this['im'];
- let ret = "";
-
- if (this['isNaN']()) {
- return 'NaN';
- }
-
- if (this['isInfinite']()) {
- return 'Infinity';
- }
-
- if (Math.abs(a) < Complex['EPSILON']) {
- a = 0;
- }
-
- if (Math.abs(b) < Complex['EPSILON']) {
- b = 0;
- }
-
- // If is real number
- if (b === 0) {
- return ret + a;
- }
-
- if (a !== 0) {
- ret += a;
- ret += " ";
- if (b < 0) {
- b = -b;
- ret += "-";
- } else {
- ret += "+";
- }
- ret += " ";
- } else if (b < 0) {
- b = -b;
- ret += "-";
- }
-
- if (1 !== b) { // b is the absolute imaginary part
- ret += b;
- }
- return ret + "i";
- },
-
- /**
- * Returns the actual number as a vector
- *
- * @returns {Array}
- */
- 'toVector': function () {
-
- return [this['re'], this['im']];
- },
-
- /**
- * Returns the actual real value of the current object
- *
- * @returns {number|null}
- */
- 'valueOf': function () {
-
- if (this['im'] === 0) {
- return this['re'];
- }
- return null;
- },
-
- /**
- * Determines whether a complex number is not on the Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isNaN': function () {
- return isNaN(this['re']) || isNaN(this['im']);
- },
-
- /**
- * Determines whether or not a complex number is at the zero pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isZero': function () {
- return this['im'] === 0 && this['re'] === 0;
- },
-
- /**
- * Determines whether a complex number is not at the infinity pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isFinite': function () {
- return isFinite(this['re']) && isFinite(this['im']);
- },
-
- /**
- * Determines whether or not a complex number is at the infinity pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isInfinite': function () {
- return !this['isFinite']();
- }
-};
-
-Complex['ZERO'] = new Complex(0, 0);
-Complex['ONE'] = new Complex(1, 0);
-Complex['I'] = new Complex(0, 1);
-Complex['PI'] = new Complex(Math.PI, 0);
-Complex['E'] = new Complex(Math.E, 0);
-Complex['INFINITY'] = new Complex(Infinity, Infinity);
-Complex['NAN'] = new Complex(NaN, NaN);
-Complex['EPSILON'] = 1e-15;
-
-Object.defineProperty(Complex, "__esModule", { 'value': true });
-Complex['default'] = Complex;
-Complex['Complex'] = Complex;
-module['exports'] = Complex;
diff --git a/node_modules/complex.js/dist/complex.min.js b/node_modules/complex.js/dist/complex.min.js
deleted file mode 100644
index 37c9da1..0000000
--- a/node_modules/complex.js/dist/complex.min.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-Complex.js v2.4.3 11/13/2025
-https://raw.org/article/complex-numbers-in-javascript/
-
-Copyright (c) 2025, Robert Eisele (https://raw.org/)
-Licensed under the MIT license.
-*/
-'use strict';(function(q){function l(a,b){if(a===void 0||a===null)f.re=f.im=0;else if(b!==void 0)f.re=a,f.im=b;else switch(typeof a){case "object":if("im"in a&&"re"in a)f.re=a.re,f.im=a.im;else if("abs"in a&&"arg"in a){if(!isFinite(a.abs)&&isFinite(a.arg))return c.INFINITY;f.re=a.abs*Math.cos(a.arg);f.im=a.abs*Math.sin(a.arg)}else if("r"in a&&"phi"in a){if(!isFinite(a.r)&&isFinite(a.phi))return c.INFINITY;f.re=a.r*Math.cos(a.phi);f.im=a.r*Math.sin(a.phi)}else a.length===2?(f.re=a[0],f.im=a[1]):m();
-break;case "string":f.im=f.re=0;a=a.replace(/_/g,"").match(/\d+\.?\d*e[+-]?\d+|\d+\.?\d*|\.\d+|./g);b=1;let d=0;a===null&&m();for(let e=0;e0&&
-m();break;case "number":f.im=0;f.re=a;break;default:m()}return f}function m(){throw SyntaxError("Invalid Param");}function n(a,b){a=Math.abs(a);b=Math.abs(b);a
-0)return new c(Math.pow(this.re,a.re),0);if(this.re===0)switch((a.re%4+4)%4){case 0:return new c(Math.pow(this.im,a.re),0);case 1:return new c(0,Math.pow(this.im,a.re));case 2:return new c(-Math.pow(this.im,a.re),0);case 3:return new c(0,-Math.pow(this.im,a.re))}}if(b&&a.re>0)return c.ZERO;const d=Math.atan2(this.im,this.re),e=p(this.re,this.im);b=Math.exp(a.re*e-a.im*d);a=a.im*e+a.re*d;return new c(b*Math.cos(a),b*Math.sin(a))},sqrt:function(){const a=this.re,b=this.im;if(b===0)return a>=0?new c(Math.sqrt(a),
-0):new c(0,Math.sqrt(-a));var d=n(a,b);d=Math.sqrt(.5*(d+Math.abs(a)));let e=Math.abs(b)/(2*d);return a>=0?new c(d,b<0?-e:e):new c(e,b<0?-d:d)},exp:function(){const a=Math.exp(this.re);return this.im===0?new c(a,0):new c(a*Math.cos(this.im),a*Math.sin(this.im))},expm1:function(){const a=this.re,b=this.im,d=Math.sin(.5*b);return new c(Math.expm1(a)*Math.cos(b)+-2*d*d,Math.exp(a)*Math.sin(b))},log:function(){const a=this.re,b=this.im;return b===0&&a>0?new c(Math.log(a),0):new c(p(a,b),Math.atan2(b,
-a))},abs:function(){return n(this.re,this.im)},arg:function(){return Math.atan2(this.im,this.re)},sin:function(){const a=this.re,b=this.im;return new c(Math.sin(a)*h(b),Math.cos(a)*k(b))},cos:function(){const a=this.re,b=this.im;return new c(Math.cos(a)*h(b),-Math.sin(a)*k(b))},tan:function(){const a=2*this.re,b=2*this.im,d=Math.cos(a)+h(b);return new c(Math.sin(a)/d,k(b)/d)},cot:function(){const a=2*this.re,b=2*this.im,d=Math.cos(a)-h(b);return new c(-Math.sin(a)/d,k(b)/d)},sec:function(){const a=
-this.re,b=this.im,d=.5*h(2*b)+.5*Math.cos(2*a);return new c(Math.cos(a)*h(b)/d,Math.sin(a)*k(b)/d)},csc:function(){const a=this.re,b=this.im,d=.5*h(2*b)-.5*Math.cos(2*a);return new c(Math.sin(a)*h(b)/d,-Math.cos(a)*k(b)/d)},asin:function(){var a=this.re;const b=this.im,d=(new c(b*b-a*a+1,-2*a*b)).sqrt();a=(new c(d.re-b,d.im+a)).log();return new c(a.im,-a.re)},acos:function(){var a=this.re;const b=this.im,d=(new c(b*b-a*a+1,-2*a*b)).sqrt();a=(new c(d.re-b,d.im+a)).log();return new c(Math.PI/2-a.im,
-a.re)},atan:function(){var a=this.re;const b=this.im;if(a===0){if(b===1)return new c(0,Infinity);if(b===-1)return new c(0,-Infinity)}const d=a*a+(1-b)*(1-b);a=(new c((1-b*b-a*a)/d,-2*a/d)).log();return new c(-.5*a.im,.5*a.re)},acot:function(){const a=this.re,b=this.im;if(b===0)return new c(Math.atan2(1,a),0);const d=a*a+b*b;return d!==0?(new c(a/d,-b/d)).atan():(new c(a!==0?a/0:0,b!==0?-b/0:0)).atan()},asec:function(){const a=this.re,b=this.im;if(a===0&&b===0)return new c(0,Infinity);const d=a*a+
-b*b;return d!==0?(new c(a/d,-b/d)).acos():(new c(a!==0?a/0:0,b!==0?-b/0:0)).acos()},acsc:function(){const a=this.re,b=this.im;if(a===0&&b===0)return new c(Math.PI/2,Infinity);const d=a*a+b*b;return d!==0?(new c(a/d,-b/d)).asin():(new c(a!==0?a/0:0,b!==0?-b/0:0)).asin()},sinh:function(){const a=this.re,b=this.im;return new c(k(a)*Math.cos(b),h(a)*Math.sin(b))},cosh:function(){const a=this.re,b=this.im;return new c(h(a)*Math.cos(b),k(a)*Math.sin(b))},tanh:function(){const a=2*this.re,b=2*this.im,d=
-h(a)+Math.cos(b);return new c(k(a)/d,Math.sin(b)/d)},coth:function(){const a=2*this.re,b=2*this.im,d=h(a)-Math.cos(b);return new c(k(a)/d,-Math.sin(b)/d)},csch:function(){const a=this.re,b=this.im,d=Math.cos(2*b)-h(2*a);return new c(-2*k(a)*Math.cos(b)/d,2*h(a)*Math.sin(b)/d)},sech:function(){const a=this.re,b=this.im,d=Math.cos(2*b)+h(2*a);return new c(2*h(a)*Math.cos(b)/d,-2*k(a)*Math.sin(b)/d)},asinh:function(){const a=this.re;var b=this.im;if(b===0){if(a===0)return new c(0,0);b=Math.abs(a);b=
-Math.log(b+Math.sqrt(b*b+1));return new c(a<0?-b:b,0)}const d=(new c(a*a-b*b+1,2*a*b)).sqrt();return(new c(a+d.re,b+d.im)).log()},acosh:function(){const a=this.re,b=this.im;if(b===0)return a>1?new c(Math.log(a+Math.sqrt(a-1)*Math.sqrt(a+1)),0):a<-1?new c(Math.log(-a+Math.sqrt(a*a-1)),Math.PI):new c(0,Math.acos(a));const d=(new c(a-1,b)).sqrt(),e=(new c(a+1,b)).sqrt();return(new c(a+d.re*e.re-d.im*e.im,b+d.re*e.im+d.im*e.re)).log()},atanh:function(){var a=this.re,b=this.im;if(b===0)return a===0?new c(0,
-0):a===1?new c(Infinity,0):a===-1?new c(-Infinity,0):-11?new c(.5*Math.log((a+1)/(a-1)),-Math.PI/2):new c(.5*Math.log(-((1+a)/(1-a))),Math.PI/2);const d=1-a,e=1+a,g=d*d+b*b;if(g===0)return new c(a!==-1?a/0:0,b!==0?b/0:0);a=(e*d-b*b)/g;b=(b*d+e*b)/g;return new c(p(a,b)/2,Math.atan2(b,a)/2)},acoth:function(){const a=this.re,b=this.im;if(a===0&&b===0)return new c(0,Math.PI/2);const d=a*a+b*b;return d!==0?(new c(a/d,-b/d)).atanh():(new c(a!==0?a/0:0,b!==0?-b/
-0:0)).atanh()},acsch:function(){var a=this.re;const b=this.im;if(b===0){if(a===0)return new c(Infinity,0);a=1/a;return new c(Math.log(a+Math.sqrt(a*a+1)),0)}const d=a*a+b*b;return d!==0?(new c(a/d,-b/d)).asinh():(new c(a!==0?a/0:0,b!==0?-b/0:0)).asinh()},asech:function(){const a=this.re,b=this.im;if(this.isZero())return c.INFINITY;const d=a*a+b*b;return d!==0?(new c(a/d,-b/d)).acosh():(new c(a!==0?a/0:0,b!==0?-b/0:0)).acosh()},inverse:function(){if(this.isZero())return c.INFINITY;if(this.isInfinite())return c.ZERO;
-const a=this.re,b=this.im,d=a*a+b*b;return new c(a/d,-b/d)},conjugate:function(){return new c(this.re,-this.im)},neg:function(){return new c(-this.re,-this.im)},ceil:function(a){a=Math.pow(10,a||0);return new c(Math.ceil(this.re*a)/a,Math.ceil(this.im*a)/a)},floor:function(a){a=Math.pow(10,a||0);return new c(Math.floor(this.re*a)/a,Math.floor(this.im*a)/a)},round:function(a){a=Math.pow(10,a||0);return new c(Math.round(this.re*a)/a,Math.round(this.im*a)/a)},equals:function(a,b){a=l(a,b);return Math.abs(a.re-
-this.re)<=c.EPSILON&&Math.abs(a.im-this.im)<=c.EPSILON},clone:function(){return new c(this.re,this.im)},toString:function(){let a=this.re,b=this.im,d="";if(this.isNaN())return"NaN";if(this.isInfinite())return"Infinity";Math.abs(a), im: }
- * { arg: , abs: }
- * { phi: , r: }
- *
- * Array / Vector form
- * [ real, imaginary ]
- *
- * Double form
- * 99.3 - Single double value
- *
- * String form
- * '23.1337' - Simple real number
- * '15+3i' - a simple complex number
- * '3-i' - a simple complex number
- *
- * Example:
- *
- * const c = new Complex('99.3+8i');
- * c.mul({r: 3, i: 9}).div(4.9).sub(3, 2);
- *
- */
-
-
-const cosh = Math.cosh || function (x) {
- return Math.abs(x) < 1e-9 ? 1 - x : (Math.exp(x) + Math.exp(-x)) * 0.5;
-};
-
-const sinh = Math.sinh || function (x) {
- return Math.abs(x) < 1e-9 ? x : (Math.exp(x) - Math.exp(-x)) * 0.5;
-};
-
-/**
- * Calculates cos(x) - 1 using Taylor series if x is small (-¼π ≤ x ≤ ¼π).
- *
- * @param {number} x
- * @returns {number} cos(x) - 1
- */
-const cosm1 = x => {
- // cos(x) - 1 = − 2sin^2(x / 2)
- const s = Math.sin(0.5 * x);
- return -2 * s * s;
-};
-
-const hypot = function (x, y) {
-
- x = Math.abs(x);
- y = Math.abs(y);
-
- // Ensure `x` is the larger value
- if (x < y) [x, y] = [y, x];
-
- // If both are below the threshold, use straightforward Pythagoras
- if (x < 1e8) return Math.sqrt(x * x + y * y);
-
- // For larger values, scale to avoid overflow
- y /= x;
- return x * Math.sqrt(1 + y * y);
-};
-
-const parser_exit = function () {
- throw SyntaxError('Invalid Param');
-};
-
-/**
- * Calculates log(sqrt(a^2+b^2)) in a way to avoid overflows
- *
- * @param {number} a
- * @param {number} b
- * @returns {number}
- */
-function logHypot(a, b) {
-
- const _a = Math.abs(a);
- const _b = Math.abs(b);
-
- if (a === 0) {
- return Math.log(_b);
- }
-
- if (b === 0) {
- return Math.log(_a);
- }
-
- if (_a < 3000 && _b < 3000) {
- return Math.log(a * a + b * b) * 0.5;
- }
-
- /* I got 4 ideas to compute this property without overflow:
- *
- * Testing 1000000 times with random samples for a,b ∈ [1, 1000000000] against a big decimal library to get an error estimate
- *
- * 1. Only eliminate the square root: (OVERALL ERROR: 3.9122483030951116e-11)
-
- Math.log(a * a + b * b) / 2
-
- *
- *
- * 2. Try to use the non-overflowing pythagoras: (OVERALL ERROR: 8.889760039210159e-10)
-
- const fn = function(a, b) {
- a = Math.abs(a);
- b = Math.abs(b);
- let t = Math.min(a, b);
- a = Math.max(a, b);
- t = t / a;
-
- return Math.log(a) + Math.log(1 + t * t) / 2;
- };
-
- * 3. Abuse the identity cos(atan(y/x) = x / sqrt(x^2+y^2): (OVERALL ERROR: 3.4780178737037204e-10)
-
- Math.log(a / Math.cos(Math.atan2(b, a)))
-
- * 4. Use 3. and apply log rules: (OVERALL ERROR: 1.2014087502620896e-9)
-
- Math.log(a) - Math.log(Math.cos(Math.atan2(b, a)))
-
- */
-
- a = a * 0.5;
- b = b * 0.5;
-
- return 0.5 * Math.log(a * a + b * b) + Math.LN2;
-}
-
-const P = { 're': 0, 'im': 0 };
-const parse = function (a, b) {
-
- const z = P;
-
- if (a === undefined || a === null) {
- z['re'] =
- z['im'] = 0;
- } else if (b !== undefined) {
- z['re'] = a;
- z['im'] = b;
- } else
- switch (typeof a) {
-
- case 'object':
-
- if ('im' in a && 're' in a) {
- z['re'] = a['re'];
- z['im'] = a['im'];
- } else if ('abs' in a && 'arg' in a) {
- if (!isFinite(a['abs']) && isFinite(a['arg'])) {
- return Complex['INFINITY'];
- }
- z['re'] = a['abs'] * Math.cos(a['arg']);
- z['im'] = a['abs'] * Math.sin(a['arg']);
- } else if ('r' in a && 'phi' in a) {
- if (!isFinite(a['r']) && isFinite(a['phi'])) {
- return Complex['INFINITY'];
- }
- z['re'] = a['r'] * Math.cos(a['phi']);
- z['im'] = a['r'] * Math.sin(a['phi']);
- } else if (a.length === 2) { // Quick array check
- z['re'] = a[0];
- z['im'] = a[1];
- } else {
- parser_exit();
- }
- break;
-
- case 'string':
-
- z['im'] = /* void */
- z['re'] = 0;
-
- const tokens = a.replace(/_/g, '')
- .match(/\d+\.?\d*e[+-]?\d+|\d+\.?\d*|\.\d+|./g);
- let plus = 1;
- let minus = 0;
-
- if (tokens === null) {
- parser_exit();
- }
-
- for (let i = 0; i < tokens.length; i++) {
-
- const c = tokens[i];
-
- if (c === ' ' || c === '\t' || c === '\n') {
- /* void */
- } else if (c === '+') {
- plus++;
- } else if (c === '-') {
- minus++;
- } else if (c === 'i' || c === 'I') {
-
- if (plus + minus === 0) {
- parser_exit();
- }
-
- if (tokens[i + 1] !== ' ' && !isNaN(tokens[i + 1])) {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + tokens[i + 1]);
- i++;
- } else {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + '1');
- }
- plus = minus = 0;
-
- } else {
-
- if (plus + minus === 0 || isNaN(c)) {
- parser_exit();
- }
-
- if (tokens[i + 1] === 'i' || tokens[i + 1] === 'I') {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + c);
- i++;
- } else {
- z['re'] += parseFloat((minus % 2 ? '-' : '') + c);
- }
- plus = minus = 0;
- }
- }
-
- // Still something on the stack
- if (plus + minus > 0) {
- parser_exit();
- }
- break;
-
- case 'number':
- z['im'] = 0;
- z['re'] = a;
- break;
-
- default:
- parser_exit();
- }
-
- if (isNaN(z['re']) || isNaN(z['im'])) {
- // If a calculation is NaN, we treat it as NaN and don't throw
- //parser_exit();
- }
-
- return z;
-};
-
-/**
- * @constructor
- * @returns {Complex}
- */
-function Complex(a, b) {
-
- if (!(this instanceof Complex)) {
- return new Complex(a, b);
- }
-
- const z = parse(a, b);
-
- this['re'] = z['re'];
- this['im'] = z['im'];
-}
-
-Complex.prototype = {
-
- 're': 0,
- 'im': 0,
-
- /**
- * Calculates the sign of a complex number, which is a normalized complex
- *
- * @returns {Complex}
- */
- 'sign': function () {
-
- const abs = hypot(this['re'], this['im']);
-
- return new Complex(
- this['re'] / abs,
- this['im'] / abs);
- },
-
- /**
- * Adds two complex numbers
- *
- * @returns {Complex}
- */
- 'add': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
-
- if (tInfin || zInfin) {
-
- if (tInfin && zInfin) {
- // Infinity + Infinity = NaN
- return Complex['NAN'];
- }
- // Infinity + z = Infinity { where z != Infinity }
- return Complex['INFINITY'];
- }
-
- return new Complex(
- this['re'] + z['re'],
- this['im'] + z['im']);
- },
-
- /**
- * Subtracts two complex numbers
- *
- * @returns {Complex}
- */
- 'sub': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
-
- if (tInfin || zInfin) {
-
- if (tInfin && zInfin) {
- // Infinity - Infinity = NaN
- return Complex['NAN'];
- }
- // Infinity - z = Infinity { where z != Infinity }
- return Complex['INFINITY'];
- }
-
- return new Complex(
- this['re'] - z['re'],
- this['im'] - z['im']);
- },
-
- /**
- * Multiplies two complex numbers
- *
- * @returns {Complex}
- */
- 'mul': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- // Infinity * 0 = NaN
- if (tInfin && zIsZero || zInfin && tIsZero) {
- return Complex['NAN'];
- }
-
- // Infinity * z = Infinity { where z != 0 }
- if (tInfin || zInfin) {
- return Complex['INFINITY'];
- }
-
- // Shortcut for real values
- if (z['im'] === 0 && this['im'] === 0) {
- return new Complex(this['re'] * z['re'], 0);
- }
-
- return new Complex(
- this['re'] * z['re'] - this['im'] * z['im'],
- this['re'] * z['im'] + this['im'] * z['re']);
- },
-
- /**
- * Divides two complex numbers
- *
- * @returns {Complex}
- */
- 'div': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- // 0 / 0 = NaN and Infinity / Infinity = NaN
- if (tIsZero && zIsZero || tInfin && zInfin) {
- return Complex['NAN'];
- }
-
- // Infinity / 0 = Infinity
- if (zIsZero || tInfin) {
- return Complex['INFINITY'];
- }
-
- // 0 / Infinity = 0
- if (tIsZero || zInfin) {
- return Complex['ZERO'];
- }
-
- if (0 === z['im']) {
- // Divisor is real
- return new Complex(this['re'] / z['re'], this['im'] / z['re']);
- }
-
- if (Math.abs(z['re']) < Math.abs(z['im'])) {
-
- const x = z['re'] / z['im'];
- const t = z['re'] * x + z['im'];
-
- return new Complex(
- (this['re'] * x + this['im']) / t,
- (this['im'] * x - this['re']) / t);
-
- } else {
-
- const x = z['im'] / z['re'];
- const t = z['im'] * x + z['re'];
-
- return new Complex(
- (this['re'] + this['im'] * x) / t,
- (this['im'] - this['re'] * x) / t);
- }
- },
-
- /**
- * Calculate the power of two complex numbers
- *
- * @returns {Complex}
- */
- 'pow': function (a, b) {
-
- const z = parse(a, b);
-
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- if (zIsZero) {
- return Complex['ONE'];
- }
-
- // If the exponent is real
- if (z['im'] === 0) {
-
- if (this['im'] === 0 && this['re'] > 0) {
-
- return new Complex(Math.pow(this['re'], z['re']), 0);
-
- } else if (this['re'] === 0) { // If base is fully imaginary
-
- switch ((z['re'] % 4 + 4) % 4) {
- case 0:
- return new Complex(Math.pow(this['im'], z['re']), 0);
- case 1:
- return new Complex(0, Math.pow(this['im'], z['re']));
- case 2:
- return new Complex(-Math.pow(this['im'], z['re']), 0);
- case 3:
- return new Complex(0, -Math.pow(this['im'], z['re']));
- }
- }
- }
-
- /* I couldn't find a good formula, so here is a derivation and optimization
- *
- * z_1^z_2 = (a + bi)^(c + di)
- * = exp((c + di) * log(a + bi)
- * = pow(a^2 + b^2, (c + di) / 2) * exp(i(c + di)atan2(b, a))
- * =>...
- * Re = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * cos(d * log(a^2 + b^2) / 2 + c * atan2(b, a))
- * Im = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * sin(d * log(a^2 + b^2) / 2 + c * atan2(b, a))
- *
- * =>...
- * Re = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * cos(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a))
- * Im = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * sin(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a))
- *
- * =>
- * Re = exp(c * logsq2 - d * arg(z_1)) * cos(d * logsq2 + c * arg(z_1))
- * Im = exp(c * logsq2 - d * arg(z_1)) * sin(d * logsq2 + c * arg(z_1))
- *
- */
-
- if (tIsZero && z['re'] > 0) { // Same behavior as Wolframalpha, Zero if real part is zero
- return Complex['ZERO'];
- }
-
- const arg = Math.atan2(this['im'], this['re']);
- const loh = logHypot(this['re'], this['im']);
-
- let re = Math.exp(z['re'] * loh - z['im'] * arg);
- let im = z['im'] * loh + z['re'] * arg;
- return new Complex(
- re * Math.cos(im),
- re * Math.sin(im));
- },
-
- /**
- * Calculate the complex square root
- *
- * @returns {Complex}
- */
- 'sqrt': function () {
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
- // Real number case
- if (a >= 0) {
- return new Complex(Math.sqrt(a), 0);
- } else {
- return new Complex(0, Math.sqrt(-a));
- }
- }
-
- const r = hypot(a, b);
-
- let re = Math.sqrt(0.5 * (r + Math.abs(a))); // sqrt(2x) / 2 = sqrt(x / 2)
- let im = Math.abs(b) / (2 * re);
-
- if (a >= 0) {
- return new Complex(re, b < 0 ? -im : im);
- } else {
- return new Complex(im, b < 0 ? -re : re);
- }
- },
-
- /**
- * Calculate the complex exponent
- *
- * @returns {Complex}
- */
- 'exp': function () {
-
- const er = Math.exp(this['re']);
-
- if (this['im'] === 0) {
- return new Complex(er, 0);
- }
- return new Complex(
- er * Math.cos(this['im']),
- er * Math.sin(this['im']));
- },
-
- /**
- * Calculate the complex exponent and subtracts one.
- *
- * This may be more accurate than `Complex(x).exp().sub(1)` if
- * `x` is small.
- *
- * @returns {Complex}
- */
- 'expm1': function () {
-
- /**
- * exp(a + i*b) - 1
- = exp(a) * (cos(b) + j*sin(b)) - 1
- = expm1(a)*cos(b) + cosm1(b) + j*exp(a)*sin(b)
- */
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.expm1(a) * Math.cos(b) + cosm1(b),
- Math.exp(a) * Math.sin(b));
- },
-
- /**
- * Calculate the natural log
- *
- * @returns {Complex}
- */
- 'log': function () {
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0 && a > 0) {
- return new Complex(Math.log(a), 0);
- }
-
- return new Complex(
- logHypot(a, b),
- Math.atan2(b, a));
- },
-
- /**
- * Calculate the magnitude of the complex number
- *
- * @returns {number}
- */
- 'abs': function () {
-
- return hypot(this['re'], this['im']);
- },
-
- /**
- * Calculate the angle of the complex number
- *
- * @returns {number}
- */
- 'arg': function () {
-
- return Math.atan2(this['im'], this['re']);
- },
-
- /**
- * Calculate the sine of the complex number
- *
- * @returns {Complex}
- */
- 'sin': function () {
-
- // sin(z) = ( e^iz - e^-iz ) / 2i
- // = sin(a)cosh(b) + i cos(a)sinh(b)
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.sin(a) * cosh(b),
- Math.cos(a) * sinh(b));
- },
-
- /**
- * Calculate the cosine
- *
- * @returns {Complex}
- */
- 'cos': function () {
-
- // cos(z) = ( e^iz + e^-iz ) / 2
- // = cos(a)cosh(b) - i sin(a)sinh(b)
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.cos(a) * cosh(b),
- -Math.sin(a) * sinh(b));
- },
-
- /**
- * Calculate the tangent
- *
- * @returns {Complex}
- */
- 'tan': function () {
-
- // tan(z) = sin(z) / cos(z)
- // = ( e^iz - e^-iz ) / ( i( e^iz + e^-iz ) )
- // = ( e^2iz - 1 ) / i( e^2iz + 1 )
- // = ( sin(2a) + i sinh(2b) ) / ( cos(2a) + cosh(2b) )
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = Math.cos(a) + cosh(b);
-
- return new Complex(
- Math.sin(a) / d,
- sinh(b) / d);
- },
-
- /**
- * Calculate the cotangent
- *
- * @returns {Complex}
- */
- 'cot': function () {
-
- // cot(c) = i(e^(ci) + e^(-ci)) / (e^(ci) - e^(-ci))
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = Math.cos(a) - cosh(b);
-
- return new Complex(
- -Math.sin(a) / d,
- sinh(b) / d);
- },
-
- /**
- * Calculate the secant
- *
- * @returns {Complex}
- */
- 'sec': function () {
-
- // sec(c) = 2 / (e^(ci) + e^(-ci))
-
- const a = this['re'];
- const b = this['im'];
- const d = 0.5 * cosh(2 * b) + 0.5 * Math.cos(2 * a);
-
- return new Complex(
- Math.cos(a) * cosh(b) / d,
- Math.sin(a) * sinh(b) / d);
- },
-
- /**
- * Calculate the cosecans
- *
- * @returns {Complex}
- */
- 'csc': function () {
-
- // csc(c) = 2i / (e^(ci) - e^(-ci))
-
- const a = this['re'];
- const b = this['im'];
- const d = 0.5 * cosh(2 * b) - 0.5 * Math.cos(2 * a);
-
- return new Complex(
- Math.sin(a) * cosh(b) / d,
- -Math.cos(a) * sinh(b) / d);
- },
-
- /**
- * Calculate the complex arcus sinus
- *
- * @returns {Complex}
- */
- 'asin': function () {
-
- // asin(c) = -i * log(ci + sqrt(1 - c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- const t1 = new Complex(
- b * b - a * a + 1,
- -2 * a * b)['sqrt']();
-
- const t2 = new Complex(
- t1['re'] - b,
- t1['im'] + a)['log']();
-
- return new Complex(t2['im'], -t2['re']);
- },
-
- /**
- * Calculate the complex arcus cosinus
- *
- * @returns {Complex}
- */
- 'acos': function () {
-
- // acos(c) = i * log(c - i * sqrt(1 - c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- const t1 = new Complex(
- b * b - a * a + 1,
- -2 * a * b)['sqrt']();
-
- const t2 = new Complex(
- t1['re'] - b,
- t1['im'] + a)['log']();
-
- return new Complex(Math.PI / 2 - t2['im'], t2['re']);
- },
-
- /**
- * Calculate the complex arcus tangent
- *
- * @returns {Complex}
- */
- 'atan': function () {
-
- // atan(c) = i / 2 log((i + x) / (i - x))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0) {
-
- if (b === 1) {
- return new Complex(0, Infinity);
- }
-
- if (b === -1) {
- return new Complex(0, -Infinity);
- }
- }
-
- const d = a * a + (1.0 - b) * (1.0 - b);
-
- const t1 = new Complex(
- (1 - b * b - a * a) / d,
- -2 * a / d).log();
-
- return new Complex(-0.5 * t1['im'], 0.5 * t1['re']);
- },
-
- /**
- * Calculate the complex arcus cotangent
- *
- * @returns {Complex}
- */
- 'acot': function () {
-
- // acot(c) = i / 2 log((c - i) / (c + i))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
- return new Complex(Math.atan2(1, a), 0);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).atan()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).atan();
- },
-
- /**
- * Calculate the complex arcus secant
- *
- * @returns {Complex}
- */
- 'asec': function () {
-
- // asec(c) = -i * log(1 / c + sqrt(1 - i / c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0 && b === 0) {
- return new Complex(0, Infinity);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).acos()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).acos();
- },
-
- /**
- * Calculate the complex arcus cosecans
- *
- * @returns {Complex}
- */
- 'acsc': function () {
-
- // acsc(c) = -i * log(i / c + sqrt(1 - 1 / c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0 && b === 0) {
- return new Complex(Math.PI / 2, Infinity);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).asin()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).asin();
- },
-
- /**
- * Calculate the complex sinh
- *
- * @returns {Complex}
- */
- 'sinh': function () {
-
- // sinh(c) = (e^c - e^-c) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- sinh(a) * Math.cos(b),
- cosh(a) * Math.sin(b));
- },
-
- /**
- * Calculate the complex cosh
- *
- * @returns {Complex}
- */
- 'cosh': function () {
-
- // cosh(c) = (e^c + e^-c) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- cosh(a) * Math.cos(b),
- sinh(a) * Math.sin(b));
- },
-
- /**
- * Calculate the complex tanh
- *
- * @returns {Complex}
- */
- 'tanh': function () {
-
- // tanh(c) = (e^c - e^-c) / (e^c + e^-c)
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = cosh(a) + Math.cos(b);
-
- return new Complex(
- sinh(a) / d,
- Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex coth
- *
- * @returns {Complex}
- */
- 'coth': function () {
-
- // coth(c) = (e^c + e^-c) / (e^c - e^-c)
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = cosh(a) - Math.cos(b);
-
- return new Complex(
- sinh(a) / d,
- -Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex csch
- *
- * @returns {Complex}
- */
- 'csch': function () {
-
- // csch(c) = 2 / (e^c - e^-c)
-
- const a = this['re'];
- const b = this['im'];
- const d = Math.cos(2 * b) - cosh(2 * a);
-
- return new Complex(
- -2 * sinh(a) * Math.cos(b) / d,
- 2 * cosh(a) * Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex sech
- *
- * @returns {Complex}
- */
- 'sech': function () {
-
- // sech(c) = 2 / (e^c + e^-c)
-
- const a = this['re'];
- const b = this['im'];
- const d = Math.cos(2 * b) + cosh(2 * a);
-
- return new Complex(
- 2 * cosh(a) * Math.cos(b) / d,
- -2 * sinh(a) * Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex asinh
- *
- * @returns {Complex}
- */
- 'asinh': function () {
-
- // asinh(z) = log(z + sqrt(z^2 + 1))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- if (a === 0) {
- return new Complex(0, 0);
- }
-
- // Use |a| to keep asinh(-a) = -asinh(a) and avoid cancellation for large -a
- const x = Math.abs(a);
- const r = Math.log(x + Math.sqrt(x * x + 1));
-
- return new Complex(a < 0 ? -r : r, 0);
- }
-
- // z^2 + 1 = (a^2 - b^2 + 1) + i (2ab)
- const re2 = a * a - b * b + 1;
- const im2 = 2 * a * b;
-
- const t = new Complex(re2, im2)['sqrt'](); // sqrt(z^2 + 1)
-
- return new Complex(a + t['re'], b + t['im'])['log']();
- },
-
- /**
- * Calculate the complex acosh
- *
- * @returns {Complex}
- */
- 'acosh': function () {
-
- // acosh(z)= log(z + sqrt(z^2 - 1)) = log(z + sqrt(z - 1) * sqrt(z + 1))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- // z = a is real
- if (a > 1) {
- // acosh(a) = log(a + sqrt(a - 1) * sqrt(a + 1)), a > 1
- return new Complex(
- Math.log(a + Math.sqrt(a - 1) * Math.sqrt(a + 1)), 0);
- }
-
- if (a < -1) {
- // acosh(a) = log(-a + sqrt(a^2 - 1)) + i*pi, a < -1
- const t = Math.sqrt(a * a - 1);
- return new Complex(Math.log(-a + t), Math.PI);
- }
-
- // -1 <= a <= 1 : purely imaginary
- // acosh(a) = i * acos(a)
- return new Complex(0, Math.acos(a));
- }
-
- const t1 = new Complex(a - 1, b)['sqrt'](); // sqrt(z - 1)
- const t2 = new Complex(a + 1, b)['sqrt'](); // sqrt(z + 1)
-
- return new Complex(
- a + t1['re'] * t2['re'] - t1['im'] * t2['im'],
- b + t1['re'] * t2['im'] + t1['im'] * t2['re']
- )['log']();
- },
-
- /**
- * Calculate the complex atanh
- *
- * @returns {Complex}
- */
- 'atanh': function () {
-
- // atanh(z) = log((1 + z) / (1 - z)) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- if (a === 0) {
- return new Complex(0, 0);
- }
-
- if (a === 1) {
- // limit x -> 1^- atanh(x) = +Infinity
- return new Complex(Infinity, 0);
- }
-
- if (a === -1) {
- // limit x -> -1^+ atanh(x) = -Infinity
- return new Complex(-Infinity, 0);
- }
-
- if (-1 < a && a < 1) {
- // Purely real
- return new Complex(
- 0.5 * Math.log((1 + a) / (1 - a)),
- 0
- );
- }
-
- if (a > 1) {
- // Our branch: Im(atanh(a)) = -π/2 for a > 1
- const t = (a + 1) / (a - 1); // > 0
- return new Complex(
- 0.5 * Math.log(t),
- -Math.PI / 2
- );
- }
-
- // a < -1: Im(atanh(a)) = +π/2
- const t = (1 + a) / (1 - a); // < 0
- return new Complex(
- 0.5 * Math.log(-t), // log((1 - a)/(1 + a))
- Math.PI / 2
- );
- }
-
- // Use atanh(z) = 0.5 * Log((1+z)/(1-z)) with principal Log.
- const oneMinus = 1 - a;
- const onePlus = 1 + a;
- const d = oneMinus * oneMinus + b * b; // |1 - z|^2
-
- if (d === 0) {
- // (1 - z) == 0 for finite z only at z = 1+0i, already handled above.
- // If we ever get here, just propagate infinities consistently:
- return new Complex(
- (a !== -1) ? (a / 0) : 0,
- (b !== 0) ? (b / 0) : 0
- );
- }
-
- // (1 + z) / (1 - z) with a single complex division
- const xr = (onePlus * oneMinus - b * b) / d;
- const xi = (b * oneMinus + onePlus * b) / d;
-
- // 0.5 * log(xr + i xi)
- return new Complex(
- logHypot(xr, xi) / 2,
- Math.atan2(xi, xr) / 2
- );
- },
-
- /**
- * Calculate the complex acoth
- *
- * @returns {Complex}
- */
- 'acoth': function () {
-
- // acoth(z) = log((z + 1) / (z - 1)) / 2 = atanh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- // z = 0 -> acoth(0) = i * π / 2 (log((1+0)/(1-0))/2 = log(-1)/2)
- if (a === 0 && b === 0) {
- return new Complex(0, Math.PI / 2);
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1 / z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['atanh']();
- }
-
- // Fallback for weird infinities/NaNs: mirror other functions' style
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0
- )['atanh']();
- },
-
- /**
- * Calculate the complex acsch
- *
- * @returns {Complex}
- */
- 'acsch': function () {
-
- // acsch(c) = log((1+sqrt(1+c^2))/c) = = asinh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- // z = a real
- if (a === 0) {
- // acsch(0) -> +/- Infinity, we keep your previous behavior
- return new Complex(Infinity, 0);
- }
-
- // acsch(a) = asinh(1/a) = log(1/a + sqrt(1/a^2 + 1))
- const inv = 1 / a;
- return new Complex(
- Math.log(inv + Math.sqrt(inv * inv + 1)),
- 0
- );
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1/z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['asinh']();
- }
-
- // Handle 0 + 0i or infinities in the same spirit as your existing code
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0)['asinh']();
- },
-
- /**
- * Calculate the complex asech
- *
- * @returns {Complex}
- */
- 'asech': function () {
-
- // asech(z) = acosh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- if (this['isZero']()) {
- // asech(0) = acosh(∞) -> ∞
- return Complex['INFINITY'];
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1 / z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['acosh']();
- }
-
- // Fallback for weird infinities/NaNs
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0)['acosh']();
- },
-
- /**
- * Calculate the complex inverse 1/z
- *
- * @returns {Complex}
- */
- 'inverse': function () {
-
- // 1 / 0 = Infinity and 1 / Infinity = 0
- if (this['isZero']()) {
- return Complex['INFINITY'];
- }
-
- if (this['isInfinite']()) {
- return Complex['ZERO'];
- }
-
- const a = this['re'];
- const b = this['im'];
-
- const d = a * a + b * b;
-
- return new Complex(a / d, -b / d);
- },
-
- /**
- * Returns the complex conjugate
- *
- * @returns {Complex}
- */
- 'conjugate': function () {
-
- return new Complex(this['re'], -this['im']);
- },
-
- /**
- * Gets the negated complex number
- *
- * @returns {Complex}
- */
- 'neg': function () {
-
- return new Complex(-this['re'], -this['im']);
- },
-
- /**
- * Ceils the actual complex number
- *
- * @returns {Complex}
- */
- 'ceil': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.ceil(this['re'] * places) / places,
- Math.ceil(this['im'] * places) / places);
- },
-
- /**
- * Floors the actual complex number
- *
- * @returns {Complex}
- */
- 'floor': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.floor(this['re'] * places) / places,
- Math.floor(this['im'] * places) / places);
- },
-
- /**
- * Ceils the actual complex number
- *
- * @returns {Complex}
- */
- 'round': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.round(this['re'] * places) / places,
- Math.round(this['im'] * places) / places);
- },
-
- /**
- * Compares two complex numbers
- *
- * **Note:** new Complex(Infinity).equals(Infinity) === false
- *
- * @returns {boolean}
- */
- 'equals': function (a, b) {
-
- const z = parse(a, b);
-
- return Math.abs(z['re'] - this['re']) <= Complex['EPSILON'] &&
- Math.abs(z['im'] - this['im']) <= Complex['EPSILON'];
- },
-
- /**
- * Clones the actual object
- *
- * @returns {Complex}
- */
- 'clone': function () {
-
- return new Complex(this['re'], this['im']);
- },
-
- /**
- * Gets a string of the actual complex number
- *
- * @returns {string}
- */
- 'toString': function () {
-
- let a = this['re'];
- let b = this['im'];
- let ret = "";
-
- if (this['isNaN']()) {
- return 'NaN';
- }
-
- if (this['isInfinite']()) {
- return 'Infinity';
- }
-
- if (Math.abs(a) < Complex['EPSILON']) {
- a = 0;
- }
-
- if (Math.abs(b) < Complex['EPSILON']) {
- b = 0;
- }
-
- // If is real number
- if (b === 0) {
- return ret + a;
- }
-
- if (a !== 0) {
- ret += a;
- ret += " ";
- if (b < 0) {
- b = -b;
- ret += "-";
- } else {
- ret += "+";
- }
- ret += " ";
- } else if (b < 0) {
- b = -b;
- ret += "-";
- }
-
- if (1 !== b) { // b is the absolute imaginary part
- ret += b;
- }
- return ret + "i";
- },
-
- /**
- * Returns the actual number as a vector
- *
- * @returns {Array}
- */
- 'toVector': function () {
-
- return [this['re'], this['im']];
- },
-
- /**
- * Returns the actual real value of the current object
- *
- * @returns {number|null}
- */
- 'valueOf': function () {
-
- if (this['im'] === 0) {
- return this['re'];
- }
- return null;
- },
-
- /**
- * Determines whether a complex number is not on the Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isNaN': function () {
- return isNaN(this['re']) || isNaN(this['im']);
- },
-
- /**
- * Determines whether or not a complex number is at the zero pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isZero': function () {
- return this['im'] === 0 && this['re'] === 0;
- },
-
- /**
- * Determines whether a complex number is not at the infinity pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isFinite': function () {
- return isFinite(this['re']) && isFinite(this['im']);
- },
-
- /**
- * Determines whether or not a complex number is at the infinity pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isInfinite': function () {
- return !this['isFinite']();
- }
-};
-
-Complex['ZERO'] = new Complex(0, 0);
-Complex['ONE'] = new Complex(1, 0);
-Complex['I'] = new Complex(0, 1);
-Complex['PI'] = new Complex(Math.PI, 0);
-Complex['E'] = new Complex(Math.E, 0);
-Complex['INFINITY'] = new Complex(Infinity, Infinity);
-Complex['NAN'] = new Complex(NaN, NaN);
-Complex['EPSILON'] = 1e-15;
-export {
- Complex as default, Complex
-};
diff --git a/node_modules/complex.js/examples/gamma.js b/node_modules/complex.js/examples/gamma.js
deleted file mode 100644
index 1cc739d..0000000
--- a/node_modules/complex.js/examples/gamma.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * A gamma function implementation based on Lanczos Approximation
- * https://en.wikipedia.org/wiki/Lanczos_approximation
- */
-
-var Complex = require('complex.js');
-
-var P = [
- Complex(0.99999999999980993),
- Complex(676.5203681218851), Complex(-1259.1392167224028), Complex(771.32342877765313),
- Complex(-176.61502916214059), Complex(12.507343278686905), Complex(-0.13857109526572012),
- Complex(9.9843695780195716e-6), Complex(1.5056327351493116e-7)
-];
-
-var SQRT2PI = Complex(Math.sqrt(2 * Math.PI));
-
-function gamma(z) {
-
- z = z.sub(1);
-
- var x = P[0];
- var t = z.add(7.5);
- for (var i = 1; i < P.length; i++) {
- x = x.add(P[i].div(z.add(i)));
- }
- return SQRT2PI.mul(t.pow(z.add(0.5))).mul(t.neg().exp()).mul(x);
-}
-
-var fac = 1;
-for (var i = 1; i <= 10; i++) {
- console.log(fac, gamma(Complex(i)));
- fac *= i;
-}
diff --git a/node_modules/complex.js/package.json b/node_modules/complex.js/package.json
deleted file mode 100644
index 0f19826..0000000
--- a/node_modules/complex.js/package.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "name": "complex.js",
- "title": "Complex.js",
- "version": "2.4.3",
- "homepage": "https://raw.org/article/complex-numbers-in-javascript/",
- "bugs": "https://github.com/rawify/Complex.js/issues",
- "description": "The RAW complex numbers library",
- "keywords": [
- "complex numbers",
- "math",
- "complex",
- "number",
- "calculus",
- "parser",
- "arithmetic"
- ],
- "private": false,
- "main": "./dist/complex.js",
- "module": "./dist/complex.mjs",
- "types": "./complex.d.ts",
- "browser": "./dist/complex.min.js",
- "unpkg": "./dist/complex.min.js",
- "readmeFilename": "README.md",
- "exports": {
- ".": {
- "types": "./complex.d.ts",
- "require": "./dist/complex.js",
- "import": "./dist/complex.mjs"
- }
- },
- "repository": {
- "type": "git",
- "url": "git@github.com:rawify/Complex.js.git"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/rawify"
- },
- "author": {
- "name": "Robert Eisele",
- "email": "robert@raw.org",
- "url": "https://raw.org/"
- },
- "license": "MIT",
- "engines": {
- "node": "*"
- },
- "directories": {
- "example": "examples",
- "test": "tests"
- },
- "scripts": {
- "build": "crude-build Complex",
- "test": "mocha tests/*.js"
- },
- "devDependencies": {
- "crude-build": "^0.1.2",
- "mocha": "*"
- }
-}
diff --git a/node_modules/complex.js/src/complex.js b/node_modules/complex.js/src/complex.js
deleted file mode 100644
index fbc1913..0000000
--- a/node_modules/complex.js/src/complex.js
+++ /dev/null
@@ -1,1477 +0,0 @@
-/**
- * @license Complex.js v2.4.3 11/13/2025
- * https://raw.org/article/complex-numbers-in-javascript/
- *
- * Copyright (c) 2025, Robert Eisele (https://raw.org/)
- * Licensed under the MIT license.
- **/
-
-/**
- *
- * This class allows the manipulation of complex numbers.
- * You can pass a complex number in different formats. Either as object, double, string or two integer parameters.
- *
- * Object form
- * { re: , im: }
- * { arg: , abs: }
- * { phi: , r: }
- *
- * Array / Vector form
- * [ real, imaginary ]
- *
- * Double form
- * 99.3 - Single double value
- *
- * String form
- * '23.1337' - Simple real number
- * '15+3i' - a simple complex number
- * '3-i' - a simple complex number
- *
- * Example:
- *
- * const c = new Complex('99.3+8i');
- * c.mul({r: 3, i: 9}).div(4.9).sub(3, 2);
- *
- */
-
-
-const cosh = Math.cosh || function (x) {
- return Math.abs(x) < 1e-9 ? 1 - x : (Math.exp(x) + Math.exp(-x)) * 0.5;
-};
-
-const sinh = Math.sinh || function (x) {
- return Math.abs(x) < 1e-9 ? x : (Math.exp(x) - Math.exp(-x)) * 0.5;
-};
-
-/**
- * Calculates cos(x) - 1 using Taylor series if x is small (-¼π ≤ x ≤ ¼π).
- *
- * @param {number} x
- * @returns {number} cos(x) - 1
- */
-const cosm1 = x => {
- // cos(x) - 1 = − 2sin^2(x / 2)
- const s = Math.sin(0.5 * x);
- return -2 * s * s;
-};
-
-const hypot = function (x, y) {
-
- x = Math.abs(x);
- y = Math.abs(y);
-
- // Ensure `x` is the larger value
- if (x < y) [x, y] = [y, x];
-
- // If both are below the threshold, use straightforward Pythagoras
- if (x < 1e8) return Math.sqrt(x * x + y * y);
-
- // For larger values, scale to avoid overflow
- y /= x;
- return x * Math.sqrt(1 + y * y);
-};
-
-const parser_exit = function () {
- throw SyntaxError('Invalid Param');
-};
-
-/**
- * Calculates log(sqrt(a^2+b^2)) in a way to avoid overflows
- *
- * @param {number} a
- * @param {number} b
- * @returns {number}
- */
-function logHypot(a, b) {
-
- const _a = Math.abs(a);
- const _b = Math.abs(b);
-
- if (a === 0) {
- return Math.log(_b);
- }
-
- if (b === 0) {
- return Math.log(_a);
- }
-
- if (_a < 3000 && _b < 3000) {
- return Math.log(a * a + b * b) * 0.5;
- }
-
- /* I got 4 ideas to compute this property without overflow:
- *
- * Testing 1000000 times with random samples for a,b ∈ [1, 1000000000] against a big decimal library to get an error estimate
- *
- * 1. Only eliminate the square root: (OVERALL ERROR: 3.9122483030951116e-11)
-
- Math.log(a * a + b * b) / 2
-
- *
- *
- * 2. Try to use the non-overflowing pythagoras: (OVERALL ERROR: 8.889760039210159e-10)
-
- const fn = function(a, b) {
- a = Math.abs(a);
- b = Math.abs(b);
- let t = Math.min(a, b);
- a = Math.max(a, b);
- t = t / a;
-
- return Math.log(a) + Math.log(1 + t * t) / 2;
- };
-
- * 3. Abuse the identity cos(atan(y/x) = x / sqrt(x^2+y^2): (OVERALL ERROR: 3.4780178737037204e-10)
-
- Math.log(a / Math.cos(Math.atan2(b, a)))
-
- * 4. Use 3. and apply log rules: (OVERALL ERROR: 1.2014087502620896e-9)
-
- Math.log(a) - Math.log(Math.cos(Math.atan2(b, a)))
-
- */
-
- a = a * 0.5;
- b = b * 0.5;
-
- return 0.5 * Math.log(a * a + b * b) + Math.LN2;
-}
-
-const P = { 're': 0, 'im': 0 };
-const parse = function (a, b) {
-
- const z = P;
-
- if (a === undefined || a === null) {
- z['re'] =
- z['im'] = 0;
- } else if (b !== undefined) {
- z['re'] = a;
- z['im'] = b;
- } else
- switch (typeof a) {
-
- case 'object':
-
- if ('im' in a && 're' in a) {
- z['re'] = a['re'];
- z['im'] = a['im'];
- } else if ('abs' in a && 'arg' in a) {
- if (!isFinite(a['abs']) && isFinite(a['arg'])) {
- return Complex['INFINITY'];
- }
- z['re'] = a['abs'] * Math.cos(a['arg']);
- z['im'] = a['abs'] * Math.sin(a['arg']);
- } else if ('r' in a && 'phi' in a) {
- if (!isFinite(a['r']) && isFinite(a['phi'])) {
- return Complex['INFINITY'];
- }
- z['re'] = a['r'] * Math.cos(a['phi']);
- z['im'] = a['r'] * Math.sin(a['phi']);
- } else if (a.length === 2) { // Quick array check
- z['re'] = a[0];
- z['im'] = a[1];
- } else {
- parser_exit();
- }
- break;
-
- case 'string':
-
- z['im'] = /* void */
- z['re'] = 0;
-
- const tokens = a.replace(/_/g, '')
- .match(/\d+\.?\d*e[+-]?\d+|\d+\.?\d*|\.\d+|./g);
- let plus = 1;
- let minus = 0;
-
- if (tokens === null) {
- parser_exit();
- }
-
- for (let i = 0; i < tokens.length; i++) {
-
- const c = tokens[i];
-
- if (c === ' ' || c === '\t' || c === '\n') {
- /* void */
- } else if (c === '+') {
- plus++;
- } else if (c === '-') {
- minus++;
- } else if (c === 'i' || c === 'I') {
-
- if (plus + minus === 0) {
- parser_exit();
- }
-
- if (tokens[i + 1] !== ' ' && !isNaN(tokens[i + 1])) {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + tokens[i + 1]);
- i++;
- } else {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + '1');
- }
- plus = minus = 0;
-
- } else {
-
- if (plus + minus === 0 || isNaN(c)) {
- parser_exit();
- }
-
- if (tokens[i + 1] === 'i' || tokens[i + 1] === 'I') {
- z['im'] += parseFloat((minus % 2 ? '-' : '') + c);
- i++;
- } else {
- z['re'] += parseFloat((minus % 2 ? '-' : '') + c);
- }
- plus = minus = 0;
- }
- }
-
- // Still something on the stack
- if (plus + minus > 0) {
- parser_exit();
- }
- break;
-
- case 'number':
- z['im'] = 0;
- z['re'] = a;
- break;
-
- default:
- parser_exit();
- }
-
- if (isNaN(z['re']) || isNaN(z['im'])) {
- // If a calculation is NaN, we treat it as NaN and don't throw
- //parser_exit();
- }
-
- return z;
-};
-
-/**
- * @constructor
- * @returns {Complex}
- */
-function Complex(a, b) {
-
- if (!(this instanceof Complex)) {
- return new Complex(a, b);
- }
-
- const z = parse(a, b);
-
- this['re'] = z['re'];
- this['im'] = z['im'];
-}
-
-Complex.prototype = {
-
- 're': 0,
- 'im': 0,
-
- /**
- * Calculates the sign of a complex number, which is a normalized complex
- *
- * @returns {Complex}
- */
- 'sign': function () {
-
- const abs = hypot(this['re'], this['im']);
-
- return new Complex(
- this['re'] / abs,
- this['im'] / abs);
- },
-
- /**
- * Adds two complex numbers
- *
- * @returns {Complex}
- */
- 'add': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
-
- if (tInfin || zInfin) {
-
- if (tInfin && zInfin) {
- // Infinity + Infinity = NaN
- return Complex['NAN'];
- }
- // Infinity + z = Infinity { where z != Infinity }
- return Complex['INFINITY'];
- }
-
- return new Complex(
- this['re'] + z['re'],
- this['im'] + z['im']);
- },
-
- /**
- * Subtracts two complex numbers
- *
- * @returns {Complex}
- */
- 'sub': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
-
- if (tInfin || zInfin) {
-
- if (tInfin && zInfin) {
- // Infinity - Infinity = NaN
- return Complex['NAN'];
- }
- // Infinity - z = Infinity { where z != Infinity }
- return Complex['INFINITY'];
- }
-
- return new Complex(
- this['re'] - z['re'],
- this['im'] - z['im']);
- },
-
- /**
- * Multiplies two complex numbers
- *
- * @returns {Complex}
- */
- 'mul': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- // Infinity * 0 = NaN
- if (tInfin && zIsZero || zInfin && tIsZero) {
- return Complex['NAN'];
- }
-
- // Infinity * z = Infinity { where z != 0 }
- if (tInfin || zInfin) {
- return Complex['INFINITY'];
- }
-
- // Shortcut for real values
- if (z['im'] === 0 && this['im'] === 0) {
- return new Complex(this['re'] * z['re'], 0);
- }
-
- return new Complex(
- this['re'] * z['re'] - this['im'] * z['im'],
- this['re'] * z['im'] + this['im'] * z['re']);
- },
-
- /**
- * Divides two complex numbers
- *
- * @returns {Complex}
- */
- 'div': function (a, b) {
-
- const z = parse(a, b);
-
- const tInfin = this['isInfinite']();
- const zInfin = !(isFinite(z['re']) && isFinite(z['im']));
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- // 0 / 0 = NaN and Infinity / Infinity = NaN
- if (tIsZero && zIsZero || tInfin && zInfin) {
- return Complex['NAN'];
- }
-
- // Infinity / 0 = Infinity
- if (zIsZero || tInfin) {
- return Complex['INFINITY'];
- }
-
- // 0 / Infinity = 0
- if (tIsZero || zInfin) {
- return Complex['ZERO'];
- }
-
- if (0 === z['im']) {
- // Divisor is real
- return new Complex(this['re'] / z['re'], this['im'] / z['re']);
- }
-
- if (Math.abs(z['re']) < Math.abs(z['im'])) {
-
- const x = z['re'] / z['im'];
- const t = z['re'] * x + z['im'];
-
- return new Complex(
- (this['re'] * x + this['im']) / t,
- (this['im'] * x - this['re']) / t);
-
- } else {
-
- const x = z['im'] / z['re'];
- const t = z['im'] * x + z['re'];
-
- return new Complex(
- (this['re'] + this['im'] * x) / t,
- (this['im'] - this['re'] * x) / t);
- }
- },
-
- /**
- * Calculate the power of two complex numbers
- *
- * @returns {Complex}
- */
- 'pow': function (a, b) {
-
- const z = parse(a, b);
-
- const tIsZero = this['re'] === 0 && this['im'] === 0;
- const zIsZero = z['re'] === 0 && z['im'] === 0;
-
- if (zIsZero) {
- return Complex['ONE'];
- }
-
- // If the exponent is real
- if (z['im'] === 0) {
-
- if (this['im'] === 0 && this['re'] > 0) {
-
- return new Complex(Math.pow(this['re'], z['re']), 0);
-
- } else if (this['re'] === 0) { // If base is fully imaginary
-
- switch ((z['re'] % 4 + 4) % 4) {
- case 0:
- return new Complex(Math.pow(this['im'], z['re']), 0);
- case 1:
- return new Complex(0, Math.pow(this['im'], z['re']));
- case 2:
- return new Complex(-Math.pow(this['im'], z['re']), 0);
- case 3:
- return new Complex(0, -Math.pow(this['im'], z['re']));
- }
- }
- }
-
- /* I couldn't find a good formula, so here is a derivation and optimization
- *
- * z_1^z_2 = (a + bi)^(c + di)
- * = exp((c + di) * log(a + bi)
- * = pow(a^2 + b^2, (c + di) / 2) * exp(i(c + di)atan2(b, a))
- * =>...
- * Re = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * cos(d * log(a^2 + b^2) / 2 + c * atan2(b, a))
- * Im = (pow(a^2 + b^2, c / 2) * exp(-d * atan2(b, a))) * sin(d * log(a^2 + b^2) / 2 + c * atan2(b, a))
- *
- * =>...
- * Re = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * cos(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a))
- * Im = exp(c * log(sqrt(a^2 + b^2)) - d * atan2(b, a)) * sin(d * log(sqrt(a^2 + b^2)) + c * atan2(b, a))
- *
- * =>
- * Re = exp(c * logsq2 - d * arg(z_1)) * cos(d * logsq2 + c * arg(z_1))
- * Im = exp(c * logsq2 - d * arg(z_1)) * sin(d * logsq2 + c * arg(z_1))
- *
- */
-
- if (tIsZero && z['re'] > 0) { // Same behavior as Wolframalpha, Zero if real part is zero
- return Complex['ZERO'];
- }
-
- const arg = Math.atan2(this['im'], this['re']);
- const loh = logHypot(this['re'], this['im']);
-
- let re = Math.exp(z['re'] * loh - z['im'] * arg);
- let im = z['im'] * loh + z['re'] * arg;
- return new Complex(
- re * Math.cos(im),
- re * Math.sin(im));
- },
-
- /**
- * Calculate the complex square root
- *
- * @returns {Complex}
- */
- 'sqrt': function () {
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
- // Real number case
- if (a >= 0) {
- return new Complex(Math.sqrt(a), 0);
- } else {
- return new Complex(0, Math.sqrt(-a));
- }
- }
-
- const r = hypot(a, b);
-
- let re = Math.sqrt(0.5 * (r + Math.abs(a))); // sqrt(2x) / 2 = sqrt(x / 2)
- let im = Math.abs(b) / (2 * re);
-
- if (a >= 0) {
- return new Complex(re, b < 0 ? -im : im);
- } else {
- return new Complex(im, b < 0 ? -re : re);
- }
- },
-
- /**
- * Calculate the complex exponent
- *
- * @returns {Complex}
- */
- 'exp': function () {
-
- const er = Math.exp(this['re']);
-
- if (this['im'] === 0) {
- return new Complex(er, 0);
- }
- return new Complex(
- er * Math.cos(this['im']),
- er * Math.sin(this['im']));
- },
-
- /**
- * Calculate the complex exponent and subtracts one.
- *
- * This may be more accurate than `Complex(x).exp().sub(1)` if
- * `x` is small.
- *
- * @returns {Complex}
- */
- 'expm1': function () {
-
- /**
- * exp(a + i*b) - 1
- = exp(a) * (cos(b) + j*sin(b)) - 1
- = expm1(a)*cos(b) + cosm1(b) + j*exp(a)*sin(b)
- */
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.expm1(a) * Math.cos(b) + cosm1(b),
- Math.exp(a) * Math.sin(b));
- },
-
- /**
- * Calculate the natural log
- *
- * @returns {Complex}
- */
- 'log': function () {
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0 && a > 0) {
- return new Complex(Math.log(a), 0);
- }
-
- return new Complex(
- logHypot(a, b),
- Math.atan2(b, a));
- },
-
- /**
- * Calculate the magnitude of the complex number
- *
- * @returns {number}
- */
- 'abs': function () {
-
- return hypot(this['re'], this['im']);
- },
-
- /**
- * Calculate the angle of the complex number
- *
- * @returns {number}
- */
- 'arg': function () {
-
- return Math.atan2(this['im'], this['re']);
- },
-
- /**
- * Calculate the sine of the complex number
- *
- * @returns {Complex}
- */
- 'sin': function () {
-
- // sin(z) = ( e^iz - e^-iz ) / 2i
- // = sin(a)cosh(b) + i cos(a)sinh(b)
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.sin(a) * cosh(b),
- Math.cos(a) * sinh(b));
- },
-
- /**
- * Calculate the cosine
- *
- * @returns {Complex}
- */
- 'cos': function () {
-
- // cos(z) = ( e^iz + e^-iz ) / 2
- // = cos(a)cosh(b) - i sin(a)sinh(b)
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- Math.cos(a) * cosh(b),
- -Math.sin(a) * sinh(b));
- },
-
- /**
- * Calculate the tangent
- *
- * @returns {Complex}
- */
- 'tan': function () {
-
- // tan(z) = sin(z) / cos(z)
- // = ( e^iz - e^-iz ) / ( i( e^iz + e^-iz ) )
- // = ( e^2iz - 1 ) / i( e^2iz + 1 )
- // = ( sin(2a) + i sinh(2b) ) / ( cos(2a) + cosh(2b) )
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = Math.cos(a) + cosh(b);
-
- return new Complex(
- Math.sin(a) / d,
- sinh(b) / d);
- },
-
- /**
- * Calculate the cotangent
- *
- * @returns {Complex}
- */
- 'cot': function () {
-
- // cot(c) = i(e^(ci) + e^(-ci)) / (e^(ci) - e^(-ci))
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = Math.cos(a) - cosh(b);
-
- return new Complex(
- -Math.sin(a) / d,
- sinh(b) / d);
- },
-
- /**
- * Calculate the secant
- *
- * @returns {Complex}
- */
- 'sec': function () {
-
- // sec(c) = 2 / (e^(ci) + e^(-ci))
-
- const a = this['re'];
- const b = this['im'];
- const d = 0.5 * cosh(2 * b) + 0.5 * Math.cos(2 * a);
-
- return new Complex(
- Math.cos(a) * cosh(b) / d,
- Math.sin(a) * sinh(b) / d);
- },
-
- /**
- * Calculate the cosecans
- *
- * @returns {Complex}
- */
- 'csc': function () {
-
- // csc(c) = 2i / (e^(ci) - e^(-ci))
-
- const a = this['re'];
- const b = this['im'];
- const d = 0.5 * cosh(2 * b) - 0.5 * Math.cos(2 * a);
-
- return new Complex(
- Math.sin(a) * cosh(b) / d,
- -Math.cos(a) * sinh(b) / d);
- },
-
- /**
- * Calculate the complex arcus sinus
- *
- * @returns {Complex}
- */
- 'asin': function () {
-
- // asin(c) = -i * log(ci + sqrt(1 - c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- const t1 = new Complex(
- b * b - a * a + 1,
- -2 * a * b)['sqrt']();
-
- const t2 = new Complex(
- t1['re'] - b,
- t1['im'] + a)['log']();
-
- return new Complex(t2['im'], -t2['re']);
- },
-
- /**
- * Calculate the complex arcus cosinus
- *
- * @returns {Complex}
- */
- 'acos': function () {
-
- // acos(c) = i * log(c - i * sqrt(1 - c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- const t1 = new Complex(
- b * b - a * a + 1,
- -2 * a * b)['sqrt']();
-
- const t2 = new Complex(
- t1['re'] - b,
- t1['im'] + a)['log']();
-
- return new Complex(Math.PI / 2 - t2['im'], t2['re']);
- },
-
- /**
- * Calculate the complex arcus tangent
- *
- * @returns {Complex}
- */
- 'atan': function () {
-
- // atan(c) = i / 2 log((i + x) / (i - x))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0) {
-
- if (b === 1) {
- return new Complex(0, Infinity);
- }
-
- if (b === -1) {
- return new Complex(0, -Infinity);
- }
- }
-
- const d = a * a + (1.0 - b) * (1.0 - b);
-
- const t1 = new Complex(
- (1 - b * b - a * a) / d,
- -2 * a / d).log();
-
- return new Complex(-0.5 * t1['im'], 0.5 * t1['re']);
- },
-
- /**
- * Calculate the complex arcus cotangent
- *
- * @returns {Complex}
- */
- 'acot': function () {
-
- // acot(c) = i / 2 log((c - i) / (c + i))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
- return new Complex(Math.atan2(1, a), 0);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).atan()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).atan();
- },
-
- /**
- * Calculate the complex arcus secant
- *
- * @returns {Complex}
- */
- 'asec': function () {
-
- // asec(c) = -i * log(1 / c + sqrt(1 - i / c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0 && b === 0) {
- return new Complex(0, Infinity);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).acos()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).acos();
- },
-
- /**
- * Calculate the complex arcus cosecans
- *
- * @returns {Complex}
- */
- 'acsc': function () {
-
- // acsc(c) = -i * log(i / c + sqrt(1 - 1 / c^2))
-
- const a = this['re'];
- const b = this['im'];
-
- if (a === 0 && b === 0) {
- return new Complex(Math.PI / 2, Infinity);
- }
-
- const d = a * a + b * b;
- return (d !== 0)
- ? new Complex(
- a / d,
- -b / d).asin()
- : new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0).asin();
- },
-
- /**
- * Calculate the complex sinh
- *
- * @returns {Complex}
- */
- 'sinh': function () {
-
- // sinh(c) = (e^c - e^-c) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- sinh(a) * Math.cos(b),
- cosh(a) * Math.sin(b));
- },
-
- /**
- * Calculate the complex cosh
- *
- * @returns {Complex}
- */
- 'cosh': function () {
-
- // cosh(c) = (e^c + e^-c) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- return new Complex(
- cosh(a) * Math.cos(b),
- sinh(a) * Math.sin(b));
- },
-
- /**
- * Calculate the complex tanh
- *
- * @returns {Complex}
- */
- 'tanh': function () {
-
- // tanh(c) = (e^c - e^-c) / (e^c + e^-c)
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = cosh(a) + Math.cos(b);
-
- return new Complex(
- sinh(a) / d,
- Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex coth
- *
- * @returns {Complex}
- */
- 'coth': function () {
-
- // coth(c) = (e^c + e^-c) / (e^c - e^-c)
-
- const a = 2 * this['re'];
- const b = 2 * this['im'];
- const d = cosh(a) - Math.cos(b);
-
- return new Complex(
- sinh(a) / d,
- -Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex csch
- *
- * @returns {Complex}
- */
- 'csch': function () {
-
- // csch(c) = 2 / (e^c - e^-c)
-
- const a = this['re'];
- const b = this['im'];
- const d = Math.cos(2 * b) - cosh(2 * a);
-
- return new Complex(
- -2 * sinh(a) * Math.cos(b) / d,
- 2 * cosh(a) * Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex sech
- *
- * @returns {Complex}
- */
- 'sech': function () {
-
- // sech(c) = 2 / (e^c + e^-c)
-
- const a = this['re'];
- const b = this['im'];
- const d = Math.cos(2 * b) + cosh(2 * a);
-
- return new Complex(
- 2 * cosh(a) * Math.cos(b) / d,
- -2 * sinh(a) * Math.sin(b) / d);
- },
-
- /**
- * Calculate the complex asinh
- *
- * @returns {Complex}
- */
- 'asinh': function () {
-
- // asinh(z) = log(z + sqrt(z^2 + 1))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- if (a === 0) {
- return new Complex(0, 0);
- }
-
- // Use |a| to keep asinh(-a) = -asinh(a) and avoid cancellation for large -a
- const x = Math.abs(a);
- const r = Math.log(x + Math.sqrt(x * x + 1));
-
- return new Complex(a < 0 ? -r : r, 0);
- }
-
- // z^2 + 1 = (a^2 - b^2 + 1) + i (2ab)
- const re2 = a * a - b * b + 1;
- const im2 = 2 * a * b;
-
- const t = new Complex(re2, im2)['sqrt'](); // sqrt(z^2 + 1)
-
- return new Complex(a + t['re'], b + t['im'])['log']();
- },
-
- /**
- * Calculate the complex acosh
- *
- * @returns {Complex}
- */
- 'acosh': function () {
-
- // acosh(z)= log(z + sqrt(z^2 - 1)) = log(z + sqrt(z - 1) * sqrt(z + 1))
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- // z = a is real
- if (a > 1) {
- // acosh(a) = log(a + sqrt(a - 1) * sqrt(a + 1)), a > 1
- return new Complex(
- Math.log(a + Math.sqrt(a - 1) * Math.sqrt(a + 1)), 0);
- }
-
- if (a < -1) {
- // acosh(a) = log(-a + sqrt(a^2 - 1)) + i*pi, a < -1
- const t = Math.sqrt(a * a - 1);
- return new Complex(Math.log(-a + t), Math.PI);
- }
-
- // -1 <= a <= 1 : purely imaginary
- // acosh(a) = i * acos(a)
- return new Complex(0, Math.acos(a));
- }
-
- const t1 = new Complex(a - 1, b)['sqrt'](); // sqrt(z - 1)
- const t2 = new Complex(a + 1, b)['sqrt'](); // sqrt(z + 1)
-
- return new Complex(
- a + t1['re'] * t2['re'] - t1['im'] * t2['im'],
- b + t1['re'] * t2['im'] + t1['im'] * t2['re']
- )['log']();
- },
-
- /**
- * Calculate the complex atanh
- *
- * @returns {Complex}
- */
- 'atanh': function () {
-
- // atanh(z) = log((1 + z) / (1 - z)) / 2
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- if (a === 0) {
- return new Complex(0, 0);
- }
-
- if (a === 1) {
- // limit x -> 1^- atanh(x) = +Infinity
- return new Complex(Infinity, 0);
- }
-
- if (a === -1) {
- // limit x -> -1^+ atanh(x) = -Infinity
- return new Complex(-Infinity, 0);
- }
-
- if (-1 < a && a < 1) {
- // Purely real
- return new Complex(
- 0.5 * Math.log((1 + a) / (1 - a)),
- 0
- );
- }
-
- if (a > 1) {
- // Our branch: Im(atanh(a)) = -π/2 for a > 1
- const t = (a + 1) / (a - 1); // > 0
- return new Complex(
- 0.5 * Math.log(t),
- -Math.PI / 2
- );
- }
-
- // a < -1: Im(atanh(a)) = +π/2
- const t = (1 + a) / (1 - a); // < 0
- return new Complex(
- 0.5 * Math.log(-t), // log((1 - a)/(1 + a))
- Math.PI / 2
- );
- }
-
- // Use atanh(z) = 0.5 * Log((1+z)/(1-z)) with principal Log.
- const oneMinus = 1 - a;
- const onePlus = 1 + a;
- const d = oneMinus * oneMinus + b * b; // |1 - z|^2
-
- if (d === 0) {
- // (1 - z) == 0 for finite z only at z = 1+0i, already handled above.
- // If we ever get here, just propagate infinities consistently:
- return new Complex(
- (a !== -1) ? (a / 0) : 0,
- (b !== 0) ? (b / 0) : 0
- );
- }
-
- // (1 + z) / (1 - z) with a single complex division
- const xr = (onePlus * oneMinus - b * b) / d;
- const xi = (b * oneMinus + onePlus * b) / d;
-
- // 0.5 * log(xr + i xi)
- return new Complex(
- logHypot(xr, xi) / 2,
- Math.atan2(xi, xr) / 2
- );
- },
-
- /**
- * Calculate the complex acoth
- *
- * @returns {Complex}
- */
- 'acoth': function () {
-
- // acoth(z) = log((z + 1) / (z - 1)) / 2 = atanh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- // z = 0 -> acoth(0) = i * π / 2 (log((1+0)/(1-0))/2 = log(-1)/2)
- if (a === 0 && b === 0) {
- return new Complex(0, Math.PI / 2);
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1 / z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['atanh']();
- }
-
- // Fallback for weird infinities/NaNs: mirror other functions' style
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0
- )['atanh']();
- },
-
- /**
- * Calculate the complex acsch
- *
- * @returns {Complex}
- */
- 'acsch': function () {
-
- // acsch(c) = log((1+sqrt(1+c^2))/c) = = asinh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- if (b === 0) {
-
- // z = a real
- if (a === 0) {
- // acsch(0) -> +/- Infinity, we keep your previous behavior
- return new Complex(Infinity, 0);
- }
-
- // acsch(a) = asinh(1/a) = log(1/a + sqrt(1/a^2 + 1))
- const inv = 1 / a;
- return new Complex(
- Math.log(inv + Math.sqrt(inv * inv + 1)),
- 0
- );
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1/z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['asinh']();
- }
-
- // Handle 0 + 0i or infinities in the same spirit as your existing code
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0)['asinh']();
- },
-
- /**
- * Calculate the complex asech
- *
- * @returns {Complex}
- */
- 'asech': function () {
-
- // asech(z) = acosh(1 / z)
-
- const a = this['re'];
- const b = this['im'];
-
- if (this['isZero']()) {
- // asech(0) = acosh(∞) -> ∞
- return Complex['INFINITY'];
- }
-
- const d = a * a + b * b;
-
- if (d !== 0) {
- // 1 / z = (a - i b) / (a^2 + b^2)
- return new Complex(a / d, -b / d)['acosh']();
- }
-
- // Fallback for weird infinities/NaNs
- return new Complex(
- (a !== 0) ? a / 0 : 0,
- (b !== 0) ? -b / 0 : 0)['acosh']();
- },
-
- /**
- * Calculate the complex inverse 1/z
- *
- * @returns {Complex}
- */
- 'inverse': function () {
-
- // 1 / 0 = Infinity and 1 / Infinity = 0
- if (this['isZero']()) {
- return Complex['INFINITY'];
- }
-
- if (this['isInfinite']()) {
- return Complex['ZERO'];
- }
-
- const a = this['re'];
- const b = this['im'];
-
- const d = a * a + b * b;
-
- return new Complex(a / d, -b / d);
- },
-
- /**
- * Returns the complex conjugate
- *
- * @returns {Complex}
- */
- 'conjugate': function () {
-
- return new Complex(this['re'], -this['im']);
- },
-
- /**
- * Gets the negated complex number
- *
- * @returns {Complex}
- */
- 'neg': function () {
-
- return new Complex(-this['re'], -this['im']);
- },
-
- /**
- * Ceils the actual complex number
- *
- * @returns {Complex}
- */
- 'ceil': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.ceil(this['re'] * places) / places,
- Math.ceil(this['im'] * places) / places);
- },
-
- /**
- * Floors the actual complex number
- *
- * @returns {Complex}
- */
- 'floor': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.floor(this['re'] * places) / places,
- Math.floor(this['im'] * places) / places);
- },
-
- /**
- * Ceils the actual complex number
- *
- * @returns {Complex}
- */
- 'round': function (places) {
-
- places = Math.pow(10, places || 0);
-
- return new Complex(
- Math.round(this['re'] * places) / places,
- Math.round(this['im'] * places) / places);
- },
-
- /**
- * Compares two complex numbers
- *
- * **Note:** new Complex(Infinity).equals(Infinity) === false
- *
- * @returns {boolean}
- */
- 'equals': function (a, b) {
-
- const z = parse(a, b);
-
- return Math.abs(z['re'] - this['re']) <= Complex['EPSILON'] &&
- Math.abs(z['im'] - this['im']) <= Complex['EPSILON'];
- },
-
- /**
- * Clones the actual object
- *
- * @returns {Complex}
- */
- 'clone': function () {
-
- return new Complex(this['re'], this['im']);
- },
-
- /**
- * Gets a string of the actual complex number
- *
- * @returns {string}
- */
- 'toString': function () {
-
- let a = this['re'];
- let b = this['im'];
- let ret = "";
-
- if (this['isNaN']()) {
- return 'NaN';
- }
-
- if (this['isInfinite']()) {
- return 'Infinity';
- }
-
- if (Math.abs(a) < Complex['EPSILON']) {
- a = 0;
- }
-
- if (Math.abs(b) < Complex['EPSILON']) {
- b = 0;
- }
-
- // If is real number
- if (b === 0) {
- return ret + a;
- }
-
- if (a !== 0) {
- ret += a;
- ret += " ";
- if (b < 0) {
- b = -b;
- ret += "-";
- } else {
- ret += "+";
- }
- ret += " ";
- } else if (b < 0) {
- b = -b;
- ret += "-";
- }
-
- if (1 !== b) { // b is the absolute imaginary part
- ret += b;
- }
- return ret + "i";
- },
-
- /**
- * Returns the actual number as a vector
- *
- * @returns {Array}
- */
- 'toVector': function () {
-
- return [this['re'], this['im']];
- },
-
- /**
- * Returns the actual real value of the current object
- *
- * @returns {number|null}
- */
- 'valueOf': function () {
-
- if (this['im'] === 0) {
- return this['re'];
- }
- return null;
- },
-
- /**
- * Determines whether a complex number is not on the Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isNaN': function () {
- return isNaN(this['re']) || isNaN(this['im']);
- },
-
- /**
- * Determines whether or not a complex number is at the zero pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isZero': function () {
- return this['im'] === 0 && this['re'] === 0;
- },
-
- /**
- * Determines whether a complex number is not at the infinity pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isFinite': function () {
- return isFinite(this['re']) && isFinite(this['im']);
- },
-
- /**
- * Determines whether or not a complex number is at the infinity pole of the
- * Riemann sphere.
- *
- * @returns {boolean}
- */
- 'isInfinite': function () {
- return !this['isFinite']();
- }
-};
-
-Complex['ZERO'] = new Complex(0, 0);
-Complex['ONE'] = new Complex(1, 0);
-Complex['I'] = new Complex(0, 1);
-Complex['PI'] = new Complex(Math.PI, 0);
-Complex['E'] = new Complex(Math.E, 0);
-Complex['INFINITY'] = new Complex(Infinity, Infinity);
-Complex['NAN'] = new Complex(NaN, NaN);
-Complex['EPSILON'] = 1e-15;
diff --git a/node_modules/complex.js/tests/complex.test.js b/node_modules/complex.js/tests/complex.test.js
deleted file mode 100644
index f7ffbea..0000000
--- a/node_modules/complex.js/tests/complex.test.js
+++ /dev/null
@@ -1,1089 +0,0 @@
-
-var Complex = require("complex.js");
-var assert = require("assert");
-
-var functionTests = [{
- set: Complex.I,
- fn: "mul",
- param: Complex(Math.PI).exp(),
- expect: "23.140692632779267i"
-}, {
- set: new Complex(1, 4),
- fn: "mul",
- param: 3,
- expect: "3 + 12i"
-}, {
- set: "4 + 3i",
- fn: "add",
- param: "-3 - 2i",
- expect: "1 + i"
-}, {
- set: "3i",
- fn: "add",
- param: "-2i",
- expect: "i"
-}, {
- set: "4",
- fn: "add",
- param: "-3",
- expect: "1"
-}, {
- set: 9,
- fn: "sqrt",
- expect: "3"
-}, {
- set: -9,
- fn: "sqrt",
- expect: "3i"
-}, {
- set: "-36",
- fn: "sqrt",
- expect: "6i"
-}, {
- set: "36i",
- fn: "sqrt",
- expect: "4.242640687119285 + 4.242640687119286i"
-}, {
- set: Infinity,
- fn: "mul",
- param: "i",
- expect: "Infinity"
-}, {
- set: "-36i",
- fn: "sqrt",
- expect: "4.242640687119285 - 4.242640687119286i"
-}, {
- set: "4 + 2i",
- fn: "div",
- param: "0",
- expect: "Infinity"
-}, {
- set: "0",
- fn: "div",
- param: Infinity,
- expect: "0"
-}, {
- set: -Infinity,
- fn: "div",
- param: 0,
- expect: "Infinity"
-}, {
- set: Infinity,
- fn: "div",
- param: Infinity,
- expect: "NaN"
-}, {
- set: 0,
- fn: "div",
- param: 0,
- expect: "NaN"
-}, {
- set: "4 + 2i",
- fn: "div",
- param: "1 + i",
- expect: "3 - i"
-}, {
- set: "25",
- fn: "div",
- param: "3 - 4i",
- expect: "3 + 4i"
-}, {
- set: "3 - 2i",
- fn: "div",
- param: "i",
- expect: "-2 - 3i"
-}, {
- set: "4i",
- fn: "mul",
- param: "-5i",
- expect: "20"
-}, {
- set: "3 - 6i",
- fn: "mul",
- param: "i",
- expect: "6 + 3i"
-}, {
- set: Infinity,
- fn: "mul",
- param: 0,
- expect: "NaN"
-}, {
- set: "3 + 4i",
- fn: "add",
- param: "5 - 7i",
- expect: "8 - 3i"
-}, {
- set: Infinity,
- fn: "add",
- param: Infinity,
- expect: "NaN"
-}, {
- set: -Infinity,
- fn: "sub",
- param: -Infinity,
- expect: "NaN"
-}, {
- set: "6i",
- fn: "div",
- param: "3 - 12i",
- expect: "-0.47058823529411764 + 0.11764705882352941i"
-}, {
- set: "36 + 36i",
- fn: "sqrt",
- expect: "6.59210468080686 + 2.730539163373364i"
-}, {
- set: "36 - 36i",
- fn: "sqrt",
- expect: "6.59210468080686 - 2.730539163373364i"
-}, {
- set: "-36 + 36i",
- fn: "sqrt",
- expect: "2.730539163373364 + 6.59210468080686i"
-}, {
- set: "-36 - 36i",
- fn: "sqrt",
- expect: "2.730539163373364 - 6.59210468080686i"
-}, {
- set: "0",
- fn: "sqrt",
- expect: "0"
-}, {
- set: Math.E,
- fn: "log",
- expect: "1"
-}, {
- set: 0,
- fn: "log",
- expect: "Infinity"
-}, {
- set: Infinity,
- fn: "mul",
- param: 3,
- expect: "Infinity"
-}, {
- set: "-1",
- fn: "log",
- expect: Math.PI + "i"
-}, {
- set: "i",
- fn: "log",
- expect: (Math.PI / 2) + "i"
-}, {
- set: "3 + 2i",
- fn: "log",
- expect: Math.log(13) / 2 + " + " + Math.atan2(2, 3) + "i"
-}, {
- set: "3 - 2i",
- fn: "log",
- expect: Math.log(13) / 2 + " - " + Math.atan2(2, 3) + "i"
-}, {
- set: 1,
- fn: "exp",
- expect: "" + Math.E
-}, {
- set: "i",
- fn: "exp",
- expect: Math.cos(1) + " + " + Math.sin(1) + "i"
-}, {
- set: "i",
- fn: "mul",
- param: "i",
- expect: "-1"
-}, {
- set: "3 + 2i",
- fn: "exp",
- expect: "-8.358532650935372 + 18.263727040666765i"
-}, {
- set: "3 - 2i",
- fn: "exp",
- expect: "-8.358532650935372 - 18.263727040666765i"
-}, {
- set: "3 - 2i",
- fn: "expm1",
- expect: "-9.358532650935372 - 18.263727040666765i"
-}, {
- set: "0",
- fn: "expm1",
- expect: "0"
-}, {
- set: "1e-6",
- fn: "expm1",
- expect: "0.0000010000005000001665"
-}, {
- set: "1e-5 + 5i",
- fn: "expm1",
- expect: "-0.7163349779007357 - 0.9589338639538314i"
-}, {
- set: "1.2e-7 - 2e-6i",
- fn: "expm1",
- expect: "1.1999800719976027e-7 - 0.000002000000239998681i"
-}, {
- set: "3",
- fn: "pow",
- param: "3",
- expect: "27"
-}, {
- set: -2,
- fn: "pow",
- param: 1.5,
- expect: "-2.82842712474619i"
-}, {
- set: -8,
- fn: "pow",
- param: 1 / 3,
- expect: "1 + 1.732050807568877i"
-}, {
- set: -25,
- fn: "sqrt",
- expect: "5i"
-}, {
- set: -25,
- fn: "pow",
- param: 0.5,
- expect: "5i"
-}, {
- set: "0",
- fn: "pow",
- param: "1+i",
- expect: "0"
-}, {
- set: "i",
- fn: "pow",
- param: "0",
- expect: "1"
-}, {
- set: "87",
- fn: "pow",
- param: "3",
- expect: "658503"
-}, {
- set: "i",
- fn: "pow",
- param: "1",
- expect: "i"
-}, {
- set: "i",
- fn: "pow",
- param: "2",
- expect: "-1"
-}, {
- set: "i",
- fn: "pow",
- param: "3",
- expect: "-i"
-}, {
- set: "i",
- fn: "pow",
- param: "4",
- expect: "1"
-}, {
- set: "i",
- fn: "pow",
- param: "5",
- expect: "i"
-}, {
- set: 7,
- fn: "pow",
- param: 2,
- expect: '49'
-}, {
- set: 0,
- fn: "pow",
- param: 2,
- expect: '0'
-}, {
- set: "3i",
- fn: "pow",
- param: "3i",
- expect: "-0.008876640735623678 - 0.0013801328997494863i"
-}, {
- set: { re: 3, im: 4 },
- fn: "abs",
- expect: "5"
-}, {
- set: { re: 10, im: 24 },
- fn: "abs",
- expect: "26"
-}, {
- set: "+++++--+1 + 4i",
- fn: "mul",
- param: "3 + 2i",
- expect: "-5 + 14i"
-}, {
- set: "4 + 16i",
- fn: "div",
- param: "4.0000",
- expect: "1 + 4i"
-}, {
- set: { re: -7.1, im: 2.5 },
- fn: "neg",
- expect: "7.1 - 2.5i"
-}, {
- set: { re: 1, im: 1 },
- fn: "div",
- param: { re: 3, im: 4 },
- expect: 7 / 25 + " - " + 1 / 25 + "i"
-}, {
- set: new Complex(-7.1, 2.5),
- fn: "neg",
- expect: "7.1 - 2.5i"
-}, {
- set: { re: 1, im: 1 },
- fn: "arg",
- expect: "" + Math.PI / 4
-}, {
- set: { re: -1, im: -1 },
- fn: "arg",
- expect: "" + -3 * Math.PI / 4
-}, {
- set: { re: 0, im: 1 },
- fn: "arg",
- expect: "" + Math.PI / 2
-}, {
- set: { re: 1, im: 0.5 * Math.sqrt(4 / 3) },
- fn: "arg",
- expect: "" + Math.PI / 6
-}, {
- set: "3 + 4i",
- fn: "conjugate",
- expect: "3 - 4i"
-}, {
- set: { re: 99, im: 50 },
- fn: "conjugate",
- expect: "99 - 50i"
-}, {
- set: { re: 0, im: 0 },
- fn: "conjugate",
- expect: "0"
-}, {
- set: { re: 1, im: 23 },
- fn: "conjugate",
- expect: "1 - 23i"
-}, {
- set: "2 + 8i",
- fn: "div",
- param: new Complex(1, 2),
- expect: "3.6 + 0.8i"
-}, {
- set: "2 + 8i",
- fn: "div",
- param: "2 + 8i",
- expect: "1"
-}, {
- set: -Infinity,
- fn: "div",
- param: 3,
- expect: "Infinity"
-}, {
- set: "3+4i",
- fn: "add",
- param: "5 - i",
- expect: "8 + 3i"
-}, {
- set: { re: 1, im: 2 },
- fn: "add",
- param: "4 + 6i",
- expect: "5 + 8i"
-}, {
- set: { re: 5, im: 8 },
- fn: "sub",
- param: "4 + 6i",
- expect: "1 + 2i"
-}, {
- set: "3 + 4i",
- fn: "sub",
- param: "2 - 5i",
- expect: "1 + 9i"
-}, {
- set: "1 + 2i",
- fn: "pow",
- param: "2",
- expect: "-2.999999999999999 + 4.000000000000001i"
-}, {
- set: "1 + 2i",
- fn: "pow",
- param: "1 + 2i",
- expect: "-0.22251715680177267 + 0.10070913113607541i"
-}, {
- set: { re: 1, im: 2 },
- fn: "pow",
- param: new Complex(3, 4),
- expect: "0.1290095940744669 + 0.03392409290517001i"
-}, {
- fn: "abs",
- set: new Complex(3, 4),
- expect: "5"
-}, {
- param: 2,
- fn: "pow",
- set: new Complex(1, 2),
- expect: "-2.999999999999999 + 4.000000000000001i"
-}, {
- set: "i",
- fn: "pow",
- param: 7,
- expect: "-i"
-}, {
- set: "2+3i",
- fn: "mul",
- param: "4+5i",
- expect: "-7 + 22i"
-}, {
- set: "3 + 4i",
- fn: "mul",
- param: "2 - 5i",
- expect: "26 - 7i"
-}, {
- set: "i",
- fn: "pow",
- param: 4,
- expect: "1"
-}, {
- set: "i",
- fn: "pow",
- param: 5,
- expect: "i"
-}, {
- set: "0-0i",
- fn: "pow",
- param: 2,
- expect: "0"
-}, {
- set: "0-0i",
- fn: "pow",
- param: 0,
- expect: "1"
-}, {
- set: "1 + 4i",
- fn: "sqrt",
- expect: "1.600485180440241 + 1.2496210676876531i"
-}, {
- set: { re: -3, im: 4 },
- fn: "sqrt",
- expect: "1 + 2i"
-}, {
- set: { re: 3, im: -4 },
- fn: "sqrt",
- expect: "2 - i"
-}, {
- set: { re: -3, im: -4 },
- fn: "sqrt",
- expect: "1 - 2i"
-}, {
- set: [-2, 0],
- fn: "pow",
- param: 2,
- expect: "4"
-}, {
- set: { abs: 1, arg: 0 },
- fn: "equals",
- param: { re: 1, im: 0 },
- expect: "true"
-}, {
- set: -Complex.E.pow(2),
- fn: "log",
- expect: "2 + 3.141592653589793i"
-}, {
- set: "4 + 3i",
- fn: "log",
- expect: "1.6094379124341003 + 0.6435011087932844i"
-}, {
- set: "4 + 3i",
- fn: "exp",
- expect: "-54.051758861078156 + 7.704891372731154i"
-}, {
- set: "1-2i",
- fn: "sqrt",
- expect: "1.272019649514069 - 0.7861513777574233i"
-}, {
- set: { re: 1, im: 2 },
- fn: "sin",
- expect: "3.165778513216168 + 1.9596010414216063i"
-}, {
- set: "i",
- fn: "cos",
- expect: "1.5430806348152437"
-}, {
- set: "i",
- fn: "acos",
- expect: "1.5707963267948966 - 0.8813735870195428i"
-}, {
- set: { re: 1, im: 2 },
- fn: "cos",
- expect: "2.0327230070196656 - 3.0518977991518i"
-}, {
- set: { re: 1, im: 2 },
- fn: "tan",
- expect: "0.03381282607989669 + 1.0147936161466335i"
-}, {
- set: { re: 1, im: 3 },
- fn: "sinh",
- expect: "-1.1634403637032504 + 0.21775955162215221i"
-}, {
- set: { re: 1, im: 3 },
- fn: "cosh",
- expect: "-1.5276382501165433 + 0.1658444019189788i"
-}, {
- set: { re: 1, im: 3 },
- fn: "tanh",
- expect: "0.7680176472869112 - 0.059168539566050726i"
-}, {
- set: { re: 1, im: 3 },
- fn: "inverse",
- expect: "0.1 - 0.3i"
-}, {
- set: "3+4i",
- fn: "inverse",
- expect: "0.12 - 0.16i" // 3/25 - (4/25)i
-}, {
- set: { re: 0.5, im: -0.5 },
- fn: "inverse",
- expect: "1 + i"
-}, {
- set: "1 + i",
- fn: "inverse",
- expect: "0.5 - 0.5i"
-}, {
- set: "0",
- fn: "inverse",
- expect: "Infinity"
-}, {
- set: Infinity,
- fn: "inverse",
- expect: "0"
-}, {
- set: Complex['EPSILON'],
- fn: "equals",
- param: 1e-16,
- expect: "true"
-}, {
- set: 0,
- fn: "equals",
- param: "5i",
- expect: "false"
-}, {
- set: 5,
- fn: "equals",
- param: "5i",
- expect: "false"
-}, {
- set: 5,
- fn: "equals",
- param: 5,
- expect: "true"
-}, {
- set: "10i",
- fn: "equals",
- param: "10i",
- expect: "true"
-}, {
- set: "2 + 3i",
- fn: "equals",
- param: "2 + 3i",
- expect: "true"
-}, {
- set: "2 + 3i",
- fn: "equals",
- param: "5i",
- expect: "false"
-}, {
- set: "2 + 3i",
- fn: "round",
- param: "0",
- expect: "2 + 3i"
-}, {
- set: "2.5 + 3.5i",
- fn: "round",
- param: "1",
- expect: "2.5 + 3.5i"
-}, {
- set: "2.5 + 3.5i",
- fn: "sign",
- param: null,
- expect: "0.5812381937190965 + 0.813733471206735i"
-}, {
- set: "10 + 24i",
- fn: "sign",
- param: null,
- expect: "0.38461538461538464 + 0.9230769230769231i"
-}, {
- set: "1e3i",
- fn: "add",
- param: "3e-3 + 1e2i",
- expect: "0.003 + 1100i"
-}, {
- set: "3.14-4i",
- fn: "coth",
- expect: "0.9994481238383576 + 0.0037048958915019857i"
-}, {
- set: "8i-31",
- fn: "cot",
- expect: "1.6636768291213935e-7 - 1.0000001515864902i"
-}, {
- set: Complex(1, 1).sub(0, 1), // Distance
- fn: "abs",
- expect: "1"
-}, {
- set: Complex(1, 1), // Rotate around center
- fn: "mul",
- param: { abs: 1, arg: Math.PI / 2 },
- expect: "-0.9999999999999999 + i"
-}, {
- set: Complex(1, 1).sub(0, 1).mul({ abs: 1, arg: Math.PI / 2 }), // Rotate around another point
- fn: "add",
- param: "i",
- expect: "2i"
-}, {
- set: Complex(0, 10000000000),
- fn: "log",
- param: null,
- expect: "23.025850929940457 + 1.5707963267948966i"
-}, {
- set: Complex(0, 1000000000000000),
- fn: "log",
- param: null,
- expect: "34.538776394910684 + 1.5707963267948966i"
-}, {
- set: Complex(0, 100000000000000000),
- fn: "log",
- param: null,
- expect: "39.14394658089878 + 1.5707963267948966i"
-}, {
- set: Complex(0, 10000000000000000000),
- fn: "log",
- param: null,
- expect: "43.74911676688687 + 1.5707963267948966i"
-}, {
- set: Complex(0, 1e+30),
- fn: "log",
- param: null,
- expect: "69.07755278982137 + 1.5707963267948966i"
-}, {
- set: Complex(1, 10000000000),
- fn: "log",
- param: null,
- expect: "23.025850929940454 + 1.5707963266948965i"
-}, {
- set: Complex(1, 1000000000000000),
- fn: "log",
- param: null,
- expect: "34.538776394910684 + 1.5707963267948957i"
-}, {
- set: Complex(1, 100000000000000000),
- fn: "log",
- param: null,
- expect: "39.14394658089878 + 1.5707963267948966i"
-}, {
- set: Complex(1, 10000000000000000000),
- fn: "log",
- param: null,
- expect: "43.74911676688687 + 1.5707963267948966i"
-}, {
- set: Complex(1, 1e+30),
- fn: "log",
- param: null,
- expect: "69.07755278982137 + 1.5707963267948966i"
-}, {
- set: Complex(-1, 10000000000),
- fn: "log",
- param: null,
- expect: "23.025850929940454 + 1.5707963268948968i"
-}, {
- set: Complex(-1, 1000000000000000),
- fn: "log",
- param: null,
- expect: "34.538776394910684 + 1.5707963267948977i"
-}, {
- set: Complex(-1, 100000000000000000),
- fn: "log",
- param: null,
- expect: "39.14394658089878 + 1.5707963267948968i"
-}, {
- set: Complex(-1, 10000000000000000000),
- fn: "log",
- param: null,
- expect: "43.74911676688687 + 1.5707963267948966i"
-}, {
- set: Complex(-1, 1e+30),
- fn: "log",
- param: null,
- expect: "69.07755278982137 + 1.5707963267948966i"
-}];
-
-var constructorTests = [{
- set: null,
- expect: "0"
-}, {
- set: undefined,
- expect: "0"
-}, {
- set: "foo",
- error: "SyntaxError: Invalid Param"
-}, {
- set: {},
- error: "SyntaxError: Invalid Param"
-}, {
- set: " + i",
- expect: "i"
-}, {
- set: "3+4i",
- expect: "3 + 4i"
-}, {
- set: "i",
- expect: "i"
-}, {
- set: "3",
- expect: "3"
-}, {
- set: [9, 8],
- expect: "9 + 8i"
-}, {
- set: "2.3",
- expect: "2.3"
-}, {
- set: "2.3",
- expect: "2.3"
-}, {
- set: "0",
- expect: "0"
-}, {
- set: "-0",
- expect: "0"
-}, {
- set: { re: -0, im: 0 },
- expect: "0"
-}, {
- set: { re: 0, im: -0 },
- expect: "0"
-}, {
- set: Infinity,
- expect: "Infinity"
-}, {
- set: -Infinity,
- expect: "Infinity"
-}, {
- set: { re: Infinity, im: 0 },
- expect: "Infinity"
-}, {
- set: { re: -Infinity, im: 0 },
- expect: "Infinity"
-}, {
- set: { re: 0, im: Infinity },
- expect: "Infinity"
-}, {
- set: { re: 0, im: -Infinity },
- expect: "Infinity"
-}, {
- set: " + 7 - i + 3i - + + + + 43 + 2i - i4 + - 33 + 65 - 1 ",
- expect: "-5"
-}, {
- set: " + 7 - i + 3i - + + + + 43 + 2i - i4 + - 33 + 65 - 1 + ",
- error: "SyntaxError: Invalid Param"
-}, {
- set: "-3x + 4",
- error: "SyntaxError: Invalid Param"
-}, {
- set: "- + 7",
- expect: "-7"
-}, {
- set: "4 5i",
- error: "SyntaxError: Invalid Param"
-}, {
- set: "-",
- error: "SyntaxError: Invalid Param"
-}, {
- set: "2.2e-1-3.2e-1i",
- expect: "0.22 - 0.32i"
-}, {
- set: "2.2.",
- error: "SyntaxError: Invalid Param"
-}, {
- set: { r: 0, phi: 4 },
- expect: "0"
-}, {
- set: { r: 1, phi: 1 },
- expect: "0.5403023058681398 + 0.8414709848078965i"
-}, {
- set: { r: Infinity, phi: 0 },
- expect: "Infinity"
-}, {
- set: { r: Infinity, phi: 2 },
- expect: "Infinity"
-}, {
- set: { r: Infinity, phi: Infinity },
- expect: "NaN"
-}, {
- set: { r: Infinity, phi: NaN },
- expect: "NaN"
-}, {
- set: "1000_000i",
- expect: "1000000i"
-}
-];
-
-for (let i = 0, len = constructorTests.length; i < len; ++i) {
- if (constructorTests[i].set != null && constructorTests[i].set.hasOwnProperty('r')) {
- constructorTests.push({
- set: {
- abs: constructorTests[i].set.r,
- arg: constructorTests[i].set.phi,
- },
- expect: constructorTests[i].expect
- })
- }
-}
-
-
-function stringify(value) {
- return JSON.stringify(value, function replacer(key, val) {
- if (typeof val === "number") {
- return val.toString();
- }
- return val;
- })
-}
-
-function describeTest(test) {
- var ctor = "new Complex(" + (test.set !== undefined ? stringify(test.set) : "") + ")";
-
- var fnCall = test.fn == null
- ? ""
- : "." + test.fn + "(" + (test.param !== undefined ? stringify(test.param) : "") + ")";
-
- var expectedResult = test.expect == null
- ? ""
- : " === " + stringify(test.expect);
-
- var error = test.error == null
- ? ""
- : " should throw " + test.error;
-
- return ctor + fnCall + expectedResult + error;
-}
-
-describe("Complex functions", function () {
-
- for (var i = 0; i < functionTests.length; i++) {
-
- (function (test) {
-
- it(describeTest(test), function () {
- if (test.error) {
- try {
- new Complex(test.set)[test.fn](test.param);
- } catch (e) {
- assert.strictEqual(e.toString(), test.error.toString());
- }
- } else {
- assert.strictEqual(new Complex(test.set)[test.fn](test.param).toString(), test.expect);
- }
- });
- })(functionTests[i]);
- }
-});
-
-describe("Complex constructor", function () {
-
- for (var i = 0; i < constructorTests.length; i++) {
-
- (function (test) {
- it(describeTest(test), function () {
- if (test.error) {
- try {
- new Complex(test.set);
- } catch (e) {
- assert.strictEqual(e.toString(), test.error.toString());
- }
- } else {
- assert.strictEqual(new Complex(test.set).toString(), test.expect);
- }
- });
- })(constructorTests[i]);
- }
-});
-
-describe("Complex Details", function () {
-
- it("should work with different params", function () {
- assert.strictEqual(Complex(1, -1).toString(), "1 - i");
- assert.strictEqual(Complex(0, 0).toString(), "0");
- assert.strictEqual(Complex(0, 2).toString(), "2i");
- assert.strictEqual(Complex.I.toString(), "i");
- assert.strictEqual(Complex(0, -2).toString(), "-2i");
- assert.strictEqual(Complex({ re: 0, im: -2 }).toString(), "-2i");
- });
-
- it("Complex Combinations", function () {
-
- var zero = Complex(0, 0), one = Complex(1, 1), two = Complex(2, 2);
-
- assert.strictEqual(zero.toString(), "0");
- assert.strictEqual(one.toString(), "1 + i");
- assert(one.neg().equals(Complex(-1, -1)));
- assert(one.conjugate().equals(Complex(1, -1)));
- assert.strictEqual(one.abs(), Math.SQRT2);
- assert.strictEqual(one.arg(), Math.PI / 4);
- assert.strictEqual(one.add(one).toString(), two.toString());
- assert.strictEqual(one.sub(one).toString(), zero.toString());
- assert.strictEqual(one.mul(2).toString(), two.toString());
- assert.strictEqual(one.mul(one).toString(), Complex(0, 2).toString());
- assert.strictEqual(one.div(2).toString(), "0.5 + 0.5i");
- assert.strictEqual(one.div(one).toString(), "1");
- assert.strictEqual(one.div(0).toString(), "Infinity");
- assert.strictEqual(one.exp().toString(), "1.4686939399158851 + 2.2873552871788423i");
- assert.strictEqual(one.log().toString(), "0.34657359027997264 + 0.7853981633974483i");
- assert.strictEqual(one.pow(one).toString(), "0.2739572538301211 + 0.5837007587586147i");
- assert.strictEqual(one.pow(zero).toString(), "1");
- assert.strictEqual(one.sqrt().toString(), "1.09868411346781 + 0.45508986056222733i");
- assert.strictEqual(one.sin().toString(), "1.2984575814159773 + 0.6349639147847361i");
- assert.strictEqual(one.cos().toString(), "0.8337300251311491 - 0.9888977057628651i");
- assert.strictEqual(one.tan().toString(), "0.27175258531951174 + 1.0839233273386948i");
- assert.strictEqual(one.asin().toString(), "0.6662394324925153 + 1.0612750619050355i");
- assert.strictEqual(one.acos().toString(), "0.9045568943023813 - 1.0612750619050355i");
- assert.strictEqual(one.atan().toString(), "1.0172219678978514 + 0.40235947810852507i");
-
- var t = Complex(3, 4);
- assert.strictEqual(t.asinh().toString(), "2.29991404087927 + 0.9176168533514786i");
-
- assert.strictEqual(t.abs(), 5);
-
- assert.strictEqual(Complex("5i + 3").log().exp().toString(), "3 + 5i")
- assert.strictEqual(Complex("-2i - 1").log().exp().toString(), "-1 - 2i")
- });
-
- it("should calculate distributed conjugate", function () {
-
- var c1 = Complex(7, 3);
- var c2 = Complex(1, 2);
-
- var r1 = c1.add(c2).conjugate();
- var r2 = c1.conjugate().add(c2.conjugate());
-
- assert.strictEqual(r1.toString(), r2.toString());
- });
-
- it("should be raised to power of 6", function () {
- var c1 = Complex(2, 2);
-
- var t = c1.pow(6);
-
- assert.strictEqual(t.toString(), "-9.405287417451663e-14 - 511.9999999999995i");
- });
-
- it("should handle inverse trig fns", function () {
-
- var values = [
- new Complex(2.3, 1.4),
- new Complex(-2.3, 1.4),
- new Complex(-2.3, -1.4),
- new Complex(2.3, -1.4)];
-
- var fns = ['sin', 'cos', 'tan'];
-
- for (var i = 0; i < values.length; i++) {
-
- for (var j = 0; j < 3; j++) {
-
- var a = values[i]['a' + fns[j]]()[fns[j]]();
-
- var res = values[i];
-
- assert(Math.abs(a.re - res.re) < 1e-12 && Math.abs(a.im - res.im) < 1e-12);
- }
- }
- });
-
- it('should handle get real part', function () {
- assert.strictEqual(Complex({ abs: 1, arg: Math.PI / 4 }).re, Math.SQRT2 / 2);
- });
-
- it('should handle get complex part', function () {
- assert.strictEqual(Complex({ abs: 1, arg: Math.PI / 4 }).im, 0.7071067811865475);
- });
-
- it('should calculate the acosh correctly', function () {
- assert.strictEqual(Complex({ re: 0.451, im: 0 }).acosh().im, 1.1029108863861707);
- });
-
- it('should handle sum', function () {
- assert.strictEqual(Complex({ abs: 1, arg: 0 }).add({ abs: 1, arg: Math.PI / 2 }).abs(), Math.SQRT2);
- assert.strictEqual(Complex({ abs: 1, arg: 0 }).add({ abs: 1, arg: Math.PI / 2 }).arg(), Math.PI / 4);
- });
-
- it('should handle conjugate', function () {
- assert.strictEqual(Complex({ abs: 1, arg: Math.PI / 4 }).conjugate().toString(), Complex({ abs: 1, arg: -Math.PI / 4 }).toString());
- });
-
- it('should handle substract', function () {
- assert.strictEqual(Complex({ abs: 1, arg: 0 }).sub({ abs: 1, arg: Math.PI / 2 }).abs().toString(), "1.414213562373095");
- assert.strictEqual(Complex({ abs: 1, arg: 0 }).sub({ abs: 1, arg: Math.PI / 2 }).arg().toString(), "-0.7853981633974484");
- });
-
- it('should handle arg for the first quadrant', function () {
- assert.strictEqual(Complex({ re: 1, im: 1 }).arg(), Math.PI / 4);
- });
-
- it('should handle arg for the second quadrant', function () {
- assert.strictEqual(Complex({ re: -1, im: 1 }).arg(), 3 * Math.PI / 4);
- });
-
- it('should handle arg for the third quadrant', function () {
- assert.strictEqual(Complex({ re: -1, im: -1 }).arg(), -3 * Math.PI / 4);
- });
-
- it('should handle arg for the fourth quadrant', function () {
- assert.strictEqual(Complex({ re: 1, im: -1 }).arg(), -Math.PI / 4);
- });
-
- it('should handle arg for the fourth and first quadrant', function () {
- assert.strictEqual(Complex({ re: 1, im: 0 }).arg(), 0);
- });
-
- it('should handle arg for first and second quadrant', function () {
- assert.strictEqual(Complex({ re: 0, im: 1 }).arg(), Math.PI / 2);
- });
-
- it('should handle arg for the second and third quadrant', function () {
- assert.strictEqual(Complex({ re: -1, im: 0 }).arg(), Math.PI);
- });
-
- it('should handle arg for the third and fourth quadrant', function () {
- assert.strictEqual(Complex({ re: 0, im: -1 }).arg(), -Math.PI / 2);
- });
-
- it("should eat its own dog food", function () {
-
- var a = Complex(1, -5).toString();
- var b = Complex(a).toString();
- var c = Complex(b).mul(a);
-
- assert.strictEqual(c.toString(), '-24 - 10i');
- });
-
- it("should calculate the absolute value of i", function () {
-
- var a = Complex("i").sign().inverse().mul("i");
-
- assert.strictEqual(a.toString(), '1');
- });
-
- it('should take the natural logarithm', function () {
- var n = Complex(Math.E * Math.E).log().div("i").mul(-Math.PI * 2, 1);
-
- assert.strictEqual(n.toString(), '2 + ' + 4 * Math.PI + "i");
- });
-
- it('should follow exp rules', function () {
-
- var a = Math.random() * 10;
- var b = Math.random() * 10;
-
- var t1 = Complex({ re: a, im: b }).exp();
- var t2 = Complex(a).exp().mul(Complex.I.mul(b).exp());
- var t3 = Complex(a).exp().mul(Complex({ re: 0, im: b }).exp());
-
- assert.strictEqual(t1.toString(), t2.toString());
- assert.strictEqual(t2.toString(), t3.toString());
- });
-
-});
diff --git a/node_modules/content-disposition/HISTORY.md b/node_modules/content-disposition/HISTORY.md
index 1a3b308..488effa 100644
--- a/node_modules/content-disposition/HISTORY.md
+++ b/node_modules/content-disposition/HISTORY.md
@@ -1,15 +1,3 @@
-1.0.1 / 2025-11-18
-=================
-
- * Updated `engines` field to Node@18 or higher (fixed reference, see 1.0.0)
- * Remove dependency `safe-buffer`
-
-1.0.0 / 2024-08-31
-==================
-
- * drop node <18
- * allow utf8 as alias for utf-8
-
0.5.4 / 2021-12-10
==================
diff --git a/node_modules/content-disposition/README.md b/node_modules/content-disposition/README.md
index fbedc2f..3a0bb05 100644
--- a/node_modules/content-disposition/README.md
+++ b/node_modules/content-disposition/README.md
@@ -17,7 +17,7 @@ $ npm install content-disposition
## API
```js
-const contentDisposition = require('content-disposition')
+var contentDisposition = require('content-disposition')
```
### contentDisposition(filename, options)
@@ -67,7 +67,7 @@ it). The type is normalized to lower-case.
### contentDisposition.parse(string)
```js
-const disposition = contentDisposition.parse('attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt')
+var disposition = contentDisposition.parse('attachment; filename="EURO rates.txt"; filename*=UTF-8\'\'%e2%82%ac%20rates.txt')
```
Parse a `Content-Disposition` header string. This automatically handles extended
@@ -86,13 +86,13 @@ are shown for the string `'attachment; filename="EURO rates.txt"; filename*=UTF-
### Send a file for download
```js
-const contentDisposition = require('content-disposition')
-const destroy = require('destroy')
-const fs = require('fs')
-const http = require('http')
-const onFinished = require('on-finished')
+var contentDisposition = require('content-disposition')
+var destroy = require('destroy')
+var fs = require('fs')
+var http = require('http')
+var onFinished = require('on-finished')
-const filePath = '/path/to/public/plans.pdf'
+var filePath = '/path/to/public/plans.pdf'
http.createServer(function onRequest (req, res) {
// set headers
@@ -100,7 +100,7 @@ http.createServer(function onRequest (req, res) {
res.setHeader('Content-Disposition', contentDisposition(filePath))
// send file
- const stream = fs.createReadStream(filePath)
+ var stream = fs.createReadStream(filePath)
stream.pipe(res)
onFinished(res, function () {
destroy(stream)
@@ -130,13 +130,13 @@ $ npm test
[MIT](LICENSE)
-[npm-image]: https://img.shields.io/npm/v/content-disposition
+[npm-image]: https://img.shields.io/npm/v/content-disposition.svg
[npm-url]: https://npmjs.org/package/content-disposition
-[node-version-image]: https://img.shields.io/node/v/content-disposition
+[node-version-image]: https://img.shields.io/node/v/content-disposition.svg
[node-version-url]: https://nodejs.org/en/download
-[coveralls-image]: https://img.shields.io/coverallsCoverage/github/jshttp/content-disposition
+[coveralls-image]: https://img.shields.io/coveralls/jshttp/content-disposition.svg
[coveralls-url]: https://coveralls.io/r/jshttp/content-disposition?branch=master
-[downloads-image]: https://img.shields.io/npm/dm/content-disposition
+[downloads-image]: https://img.shields.io/npm/dm/content-disposition.svg
[downloads-url]: https://npmjs.org/package/content-disposition
-[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/jshttp/content-disposition/ci.yml
-[github-actions-ci-url]: https://github.com/jshttp/content-disposition/actions/workflows/ci.yml
+[github-actions-ci-image]: https://img.shields.io/github/workflow/status/jshttp/content-disposition/ci/master?label=ci
+[github-actions-ci-url]: https://github.com/jshttp/content-disposition?query=workflow%3Aci
diff --git a/node_modules/content-disposition/index.js b/node_modules/content-disposition/index.js
index efcd9ca..ecec899 100644
--- a/node_modules/content-disposition/index.js
+++ b/node_modules/content-disposition/index.js
@@ -20,6 +20,7 @@ module.exports.parse = parse
*/
var basename = require('path').basename
+var Buffer = require('safe-buffer').Buffer
/**
* RegExp to match non attr-char, *after* encodeURIComponent (i.e. not including "%")
@@ -242,7 +243,7 @@ function format (obj) {
for (var i = 0; i < params.length; i++) {
param = params[i]
- var val = param.slice(-1) === '*'
+ var val = param.substr(-1) === '*'
? ustring(parameters[param])
: qstring(parameters[param])
@@ -280,7 +281,6 @@ function decodefield (str) {
value = getlatin1(binary)
break
case 'utf-8':
- case 'utf8':
value = Buffer.from(binary, 'binary').toString('utf8')
break
default:
@@ -332,7 +332,7 @@ function parse (string) {
var value
// calculate index to start at
- index = PARAM_REGEXP.lastIndex = match[0].slice(-1) === ';'
+ index = PARAM_REGEXP.lastIndex = match[0].substr(-1) === ';'
? index - 1
: index
@@ -369,7 +369,7 @@ function parse (string) {
if (value[0] === '"') {
// remove quotes and escapes
value = value
- .slice(1, -1)
+ .substr(1, value.length - 2)
.replace(QESC_REGEXP, '$1')
}
diff --git a/node_modules/content-disposition/package.json b/node_modules/content-disposition/package.json
index a44034c..43c70ce 100644
--- a/node_modules/content-disposition/package.json
+++ b/node_modules/content-disposition/package.json
@@ -1,7 +1,7 @@
{
"name": "content-disposition",
"description": "Create and parse Content-Disposition header",
- "version": "1.0.1",
+ "version": "0.5.4",
"author": "Douglas Christopher Wilson ",
"license": "MIT",
"keywords": [
@@ -11,19 +11,20 @@
"res"
],
"repository": "jshttp/content-disposition",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
+ "dependencies": {
+ "safe-buffer": "5.2.1"
},
"devDependencies": {
- "c8": "^10.1.2",
+ "deep-equal": "1.0.1",
"eslint": "7.32.0",
"eslint-config-standard": "13.0.1",
"eslint-plugin-import": "2.25.3",
"eslint-plugin-markdown": "2.2.1",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "5.2.0",
- "eslint-plugin-standard": "4.1.0"
+ "eslint-plugin-standard": "4.1.0",
+ "istanbul": "0.4.5",
+ "mocha": "9.1.3"
},
"files": [
"LICENSE",
@@ -32,12 +33,12 @@
"index.js"
],
"engines": {
- "node": ">=18"
+ "node": ">= 0.6"
},
"scripts": {
"lint": "eslint .",
- "test": "node --test --test-reporter spec",
- "test-ci": "c8 --reporter=lcovonly --reporter=text npm test",
- "test-cov": "c8 --reporter=html --reporter=text npm test"
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/"
}
}
diff --git a/node_modules/cookie-signature/History.md b/node_modules/cookie-signature/History.md
index 479211a..bcf8cc9 100644
--- a/node_modules/cookie-signature/History.md
+++ b/node_modules/cookie-signature/History.md
@@ -1,34 +1,7 @@
-1.2.2 / 2024-10-29
-==================
-
-* various metadata/documentation tweaks (incl. #51)
-
-
-1.2.1 / 2023-02-27
-==================
-
-* update annotations for allowed secret key types (#44, thanks @jyasskin!)
-
-
-1.2.0 / 2022-02-17
-==================
-
-* allow buffer and other node-supported types as key (#33)
-* be pickier about extra content after signed portion (#40)
-* some internal code clarity/cleanup improvements (#26)
-
-
-1.1.0 / 2018-01-18
-==================
-
-* switch to built-in `crypto.timingSafeEqual` for validation instead of previous double-hash method (thank you @jodevsa!)
-
-
1.0.7 / 2023-04-12
==================
-Later release for older node.js versions. See the [v1.0.x branch notes](https://github.com/tj/node-cookie-signature/blob/v1.0.x/History.md#107--2023-04-12).
-
+* backport the buffer support from the 1.2.x release branch (thanks @FadhiliNjagi!)
1.0.6 / 2015-02-03
==================
@@ -36,7 +9,6 @@ Later release for older node.js versions. See the [v1.0.x branch notes](https://
* use `npm test` instead of `make test` to run tests
* clearer assertion messages when checking input
-
1.0.5 / 2014-09-05
==================
diff --git a/node_modules/cookie-signature/LICENSE b/node_modules/cookie-signature/LICENSE
deleted file mode 100644
index a2671bf..0000000
--- a/node_modules/cookie-signature/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-(The MIT License)
-
-Copyright (c) 2012–2024 LearnBoost and other contributors;
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-'Software'), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/cookie-signature/Readme.md b/node_modules/cookie-signature/Readme.md
index 369af15..2559e84 100644
--- a/node_modules/cookie-signature/Readme.md
+++ b/node_modules/cookie-signature/Readme.md
@@ -16,8 +16,27 @@ cookie.unsign(val, 'tobiiscool').should.equal('hello');
cookie.unsign(val, 'luna').should.be.false;
```
-## License
+## License
-MIT.
+(The MIT License)
-See LICENSE file for details.
+Copyright (c) 2012 LearnBoost <tj@learnboost.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/cookie-signature/index.js b/node_modules/cookie-signature/index.js
index 3fbbddb..336d487 100644
--- a/node_modules/cookie-signature/index.js
+++ b/node_modules/cookie-signature/index.js
@@ -14,7 +14,7 @@ var crypto = require('crypto');
*/
exports.sign = function(val, secret){
- if ('string' != typeof val) throw new TypeError("Cookie value must be provided as a string.");
+ if ('string' !== typeof val) throw new TypeError("Cookie value must be provided as a string.");
if (null == secret) throw new TypeError("Secret key must be provided.");
return val + '.' + crypto
.createHmac('sha256', secret)
@@ -24,24 +24,28 @@ exports.sign = function(val, secret){
};
/**
- * Unsign and decode the given `input` with `secret`,
+ * Unsign and decode the given `val` with `secret`,
* returning `false` if the signature is invalid.
*
- * @param {String} input
+ * @param {String} val
* @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret
* @return {String|Boolean}
* @api private
*/
-exports.unsign = function(input, secret){
- if ('string' != typeof input) throw new TypeError("Signed cookie string must be provided.");
+exports.unsign = function(val, secret){
+ if ('string' !== typeof val) throw new TypeError("Signed cookie string must be provided.");
if (null == secret) throw new TypeError("Secret key must be provided.");
- var tentativeValue = input.slice(0, input.lastIndexOf('.')),
- expectedInput = exports.sign(tentativeValue, secret),
- expectedBuffer = Buffer.from(expectedInput),
- inputBuffer = Buffer.from(input);
- return (
- expectedBuffer.length === inputBuffer.length &&
- crypto.timingSafeEqual(expectedBuffer, inputBuffer)
- ) ? tentativeValue : false;
+ var str = val.slice(0, val.lastIndexOf('.'))
+ , mac = exports.sign(str, secret);
+
+ return sha1(mac) == sha1(val) ? str : false;
};
+
+/**
+ * Private
+ */
+
+function sha1(str){
+ return crypto.createHash('sha1').update(str).digest('hex');
+}
diff --git a/node_modules/cookie-signature/package.json b/node_modules/cookie-signature/package.json
index a160040..738487b 100644
--- a/node_modules/cookie-signature/package.json
+++ b/node_modules/cookie-signature/package.json
@@ -1,24 +1,18 @@
{
"name": "cookie-signature",
- "version": "1.2.2",
- "main": "index.js",
+ "version": "1.0.7",
"description": "Sign and unsign cookies",
"keywords": ["cookie", "sign", "unsign"],
"author": "TJ Holowaychuk ",
"license": "MIT",
- "repository": {
- "type": "git",
- "url": "https://github.com/visionmedia/node-cookie-signature.git"
- },
+ "repository": { "type": "git", "url": "https://github.com/visionmedia/node-cookie-signature.git"},
"dependencies": {},
- "engines": {
- "node": ">=6.6.0"
- },
"devDependencies": {
"mocha": "*",
"should": "*"
},
"scripts": {
"test": "mocha --require should --reporter spec"
- }
-}
+ },
+ "main": "index"
+}
\ No newline at end of file
diff --git a/node_modules/cors/LICENSE b/node_modules/cors/LICENSE
deleted file mode 100644
index fd10c84..0000000
--- a/node_modules/cors/LICENSE
+++ /dev/null
@@ -1,22 +0,0 @@
-(The MIT License)
-
-Copyright (c) 2013 Troy Goode
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-'Software'), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/cors/README.md b/node_modules/cors/README.md
deleted file mode 100644
index 3d206e5..0000000
--- a/node_modules/cors/README.md
+++ /dev/null
@@ -1,277 +0,0 @@
-# cors
-
-[![NPM Version][npm-image]][npm-url]
-[![NPM Downloads][downloads-image]][downloads-url]
-[![Build Status][github-actions-ci-image]][github-actions-ci-url]
-[![Test Coverage][coveralls-image]][coveralls-url]
-
-CORS is a [Node.js](https://nodejs.org/en/) middleware for [Express](https://expressjs.com/)/[Connect](https://github.com/senchalabs/connect) that sets [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) response headers. These headers tell browsers which origins can read responses from your server.
-
-> [!IMPORTANT]
-> **How CORS Works:** This package sets response headers—it doesn't block requests. CORS is enforced by browsers: they check the headers and decide if JavaScript can read the response. Non-browser clients (curl, Postman, other servers) ignore CORS entirely. See the [MDN CORS guide](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS) for details.
-
-* [Installation](#installation)
-* [Usage](#usage)
- * [Simple Usage](#simple-usage-enable-all-cors-requests)
- * [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
- * [Configuring CORS](#configuring-cors)
- * [Configuring CORS w/ Dynamic Origin](#configuring-cors-w-dynamic-origin)
- * [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
- * [Customizing CORS Settings Dynamically per Request](#customizing-cors-settings-dynamically-per-request)
-* [Configuration Options](#configuration-options)
-* [Common Misconceptions](#common-misconceptions)
-* [License](#license)
-* [Original Author](#original-author)
-
-## Installation
-
-This is a [Node.js](https://nodejs.org/en/) module available through the
-[npm registry](https://www.npmjs.com/). Installation is done using the
-[`npm install` command](https://docs.npmjs.com/downloading-and-installing-packages-locally):
-
-```sh
-$ npm install cors
-```
-
-## Usage
-
-### Simple Usage (Enable *All* CORS Requests)
-
-```javascript
-var express = require('express')
-var cors = require('cors')
-var app = express()
-
-// Adds headers: Access-Control-Allow-Origin: *
-app.use(cors())
-
-app.get('/products/:id', function (req, res, next) {
- res.json({msg: 'Hello'})
-})
-
-app.listen(80, function () {
- console.log('web server listening on port 80')
-})
-```
-
-### Enable CORS for a Single Route
-
-```javascript
-var express = require('express')
-var cors = require('cors')
-var app = express()
-
-// Adds headers: Access-Control-Allow-Origin: *
-app.get('/products/:id', cors(), function (req, res, next) {
- res.json({msg: 'Hello'})
-})
-
-app.listen(80, function () {
- console.log('web server listening on port 80')
-})
-```
-
-### Configuring CORS
-
-See the [configuration options](#configuration-options) for details.
-
-```javascript
-var express = require('express')
-var cors = require('cors')
-var app = express()
-
-var corsOptions = {
- origin: 'http://example.com',
- optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
-}
-
-// Adds headers: Access-Control-Allow-Origin: http://example.com, Vary: Origin
-app.get('/products/:id', cors(corsOptions), function (req, res, next) {
- res.json({msg: 'Hello'})
-})
-
-app.listen(80, function () {
- console.log('web server listening on port 80')
-})
-```
-
-### Configuring CORS w/ Dynamic Origin
-
-This module supports validating the origin dynamically using a function provided
-to the `origin` option. This function will be passed a string that is the origin
-(or `undefined` if the request has no origin), and a `callback` with the signature
-`callback(error, origin)`.
-
-The `origin` argument to the callback can be any value allowed for the `origin`
-option of the middleware, except a function. See the
-[configuration options](#configuration-options) section for more information on all
-the possible value types.
-
-This function is designed to allow the dynamic loading of allowed origin(s) from
-a backing datasource, like a database.
-
-```javascript
-var express = require('express')
-var cors = require('cors')
-var app = express()
-
-var corsOptions = {
- origin: function (origin, callback) {
- // db.loadOrigins is an example call to load
- // a list of origins from a backing database
- db.loadOrigins(function (error, origins) {
- callback(error, origins)
- })
- }
-}
-
-// Adds headers: Access-Control-Allow-Origin: , Vary: Origin
-app.get('/products/:id', cors(corsOptions), function (req, res, next) {
- res.json({msg: 'Hello'})
-})
-
-app.listen(80, function () {
- console.log('web server listening on port 80')
-})
-```
-
-### Enabling CORS Pre-Flight
-
-Certain CORS requests are considered 'complex' and require an initial
-`OPTIONS` request (called the "pre-flight request"). An example of a
-'complex' CORS request is one that uses an HTTP verb other than
-GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable
-pre-flighting, you must add a new OPTIONS handler for the route you want
-to support:
-
-```javascript
-var express = require('express')
-var cors = require('cors')
-var app = express()
-
-app.options('/products/:id', cors()) // preflight for DELETE
-app.del('/products/:id', cors(), function (req, res, next) {
- res.json({msg: 'Hello'})
-})
-
-app.listen(80, function () {
- console.log('web server listening on port 80')
-})
-```
-
-You can also enable pre-flight across-the-board like so:
-
-```javascript
-app.options('*', cors()) // include before other routes
-```
-
-NOTE: When using this middleware as an application level middleware (for
-example, `app.use(cors())`), pre-flight requests are already handled for all
-routes.
-
-### Customizing CORS Settings Dynamically per Request
-
-For APIs that require different CORS configurations for specific routes or requests, you can dynamically generate CORS options based on the incoming request. The `cors` middleware allows you to achieve this by passing a function instead of static options. This function is called for each incoming request and must use the callback pattern to return the appropriate CORS options.
-
-The function accepts:
-1. **`req`**:
- - The incoming request object.
-
-2. **`callback(error, corsOptions)`**:
- - A function used to return the computed CORS options.
- - **Arguments**:
- - **`error`**: Pass `null` if there’s no error, or an error object to indicate a failure.
- - **`corsOptions`**: An object specifying the CORS policy for the current request.
-
-Here’s an example that handles both public routes and restricted, credential-sensitive routes:
-
-```javascript
-var dynamicCorsOptions = function(req, callback) {
- var corsOptions;
- if (req.path.startsWith('/auth/connect/')) {
- // Access-Control-Allow-Origin: http://mydomain.com, Access-Control-Allow-Credentials: true, Vary: Origin
- corsOptions = {
- origin: 'http://mydomain.com',
- credentials: true
- };
- } else {
- // Access-Control-Allow-Origin: *
- corsOptions = { origin: '*' };
- }
- callback(null, corsOptions);
-};
-
-app.use(cors(dynamicCorsOptions));
-
-app.get('/auth/connect/twitter', function (req, res) {
- res.send('Hello');
-});
-
-app.get('/public', function (req, res) {
- res.send('Hello');
-});
-
-app.listen(80, function () {
- console.log('web server listening on port 80')
-})
-```
-
-## Configuration Options
-
-* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values:
- - `Boolean` - set `origin` to `true` to reflect the [request origin](https://datatracker.ietf.org/doc/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS.
- - `String` - set `origin` to a specific origin. For example, if you set it to
- - `"http://example.com"` only requests from "http://example.com" will be allowed.
- - `"*"` for all domains to be allowed.
- - `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com".
- - `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com".
- - `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (called as `callback(err, origin)`, where `origin` is a non-function value of the `origin` option) as the second.
-* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: `['GET', 'PUT', 'POST']`).
-* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header.
-* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed.
-* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted.
-* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted.
-* `preflightContinue`: Pass the CORS preflight response to the next handler.
-* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.
-
-The default configuration is the equivalent of:
-
-```json
-{
- "origin": "*",
- "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
- "preflightContinue": false,
- "optionsSuccessStatus": 204
-}
-```
-
-## Common Misconceptions
-
-### "CORS blocks requests from disallowed origins"
-
-**No.** Your server receives and processes every request. CORS headers tell the browser whether JavaScript can read the response—not whether the request is allowed.
-
-### "CORS protects my API from unauthorized access"
-
-**No.** CORS is not access control. Any HTTP client (curl, Postman, another server) can call your API regardless of CORS settings. Use authentication and authorization to protect your API.
-
-### "Setting `origin: 'http://example.com'` means only that domain can access my server"
-
-**No.** It means browsers will only let JavaScript from that origin read responses. The server still responds to all requests.
-
-## License
-
-[MIT License](http://www.opensource.org/licenses/mit-license.php)
-
-## Original Author
-
-[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com))
-
-[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg
-[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master
-[downloads-image]: https://img.shields.io/npm/dm/cors.svg
-[downloads-url]: https://npmjs.com/package/cors
-[github-actions-ci-image]: https://img.shields.io/github/actions/workflow/status/expressjs/cors/ci.yml?branch=master&label=ci
-[github-actions-ci-url]: https://github.com/expressjs/cors?query=workflow%3Aci
-[npm-image]: https://img.shields.io/npm/v/cors.svg
-[npm-url]: https://npmjs.com/package/cors
diff --git a/node_modules/cors/lib/index.js b/node_modules/cors/lib/index.js
deleted file mode 100644
index ad899ca..0000000
--- a/node_modules/cors/lib/index.js
+++ /dev/null
@@ -1,238 +0,0 @@
-(function () {
-
- 'use strict';
-
- var assign = require('object-assign');
- var vary = require('vary');
-
- var defaults = {
- origin: '*',
- methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
- preflightContinue: false,
- optionsSuccessStatus: 204
- };
-
- function isString(s) {
- return typeof s === 'string' || s instanceof String;
- }
-
- function isOriginAllowed(origin, allowedOrigin) {
- if (Array.isArray(allowedOrigin)) {
- for (var i = 0; i < allowedOrigin.length; ++i) {
- if (isOriginAllowed(origin, allowedOrigin[i])) {
- return true;
- }
- }
- return false;
- } else if (isString(allowedOrigin)) {
- return origin === allowedOrigin;
- } else if (allowedOrigin instanceof RegExp) {
- return allowedOrigin.test(origin);
- } else {
- return !!allowedOrigin;
- }
- }
-
- function configureOrigin(options, req) {
- var requestOrigin = req.headers.origin,
- headers = [],
- isAllowed;
-
- if (!options.origin || options.origin === '*') {
- // allow any origin
- headers.push([{
- key: 'Access-Control-Allow-Origin',
- value: '*'
- }]);
- } else if (isString(options.origin)) {
- // fixed origin
- headers.push([{
- key: 'Access-Control-Allow-Origin',
- value: options.origin
- }]);
- headers.push([{
- key: 'Vary',
- value: 'Origin'
- }]);
- } else {
- isAllowed = isOriginAllowed(requestOrigin, options.origin);
- // reflect origin
- headers.push([{
- key: 'Access-Control-Allow-Origin',
- value: isAllowed ? requestOrigin : false
- }]);
- headers.push([{
- key: 'Vary',
- value: 'Origin'
- }]);
- }
-
- return headers;
- }
-
- function configureMethods(options) {
- var methods = options.methods;
- if (methods.join) {
- methods = options.methods.join(','); // .methods is an array, so turn it into a string
- }
- return {
- key: 'Access-Control-Allow-Methods',
- value: methods
- };
- }
-
- function configureCredentials(options) {
- if (options.credentials === true) {
- return {
- key: 'Access-Control-Allow-Credentials',
- value: 'true'
- };
- }
- return null;
- }
-
- function configureAllowedHeaders(options, req) {
- var allowedHeaders = options.allowedHeaders || options.headers;
- var headers = [];
-
- if (!allowedHeaders) {
- allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
- headers.push([{
- key: 'Vary',
- value: 'Access-Control-Request-Headers'
- }]);
- } else if (allowedHeaders.join) {
- allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
- }
- if (allowedHeaders && allowedHeaders.length) {
- headers.push([{
- key: 'Access-Control-Allow-Headers',
- value: allowedHeaders
- }]);
- }
-
- return headers;
- }
-
- function configureExposedHeaders(options) {
- var headers = options.exposedHeaders;
- if (!headers) {
- return null;
- } else if (headers.join) {
- headers = headers.join(','); // .headers is an array, so turn it into a string
- }
- if (headers && headers.length) {
- return {
- key: 'Access-Control-Expose-Headers',
- value: headers
- };
- }
- return null;
- }
-
- function configureMaxAge(options) {
- var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString()
- if (maxAge && maxAge.length) {
- return {
- key: 'Access-Control-Max-Age',
- value: maxAge
- };
- }
- return null;
- }
-
- function applyHeaders(headers, res) {
- for (var i = 0, n = headers.length; i < n; i++) {
- var header = headers[i];
- if (header) {
- if (Array.isArray(header)) {
- applyHeaders(header, res);
- } else if (header.key === 'Vary' && header.value) {
- vary(res, header.value);
- } else if (header.value) {
- res.setHeader(header.key, header.value);
- }
- }
- }
- }
-
- function cors(options, req, res, next) {
- var headers = [],
- method = req.method && req.method.toUpperCase && req.method.toUpperCase();
-
- if (method === 'OPTIONS') {
- // preflight
- headers.push(configureOrigin(options, req));
- headers.push(configureCredentials(options))
- headers.push(configureMethods(options))
- headers.push(configureAllowedHeaders(options, req));
- headers.push(configureMaxAge(options))
- headers.push(configureExposedHeaders(options))
- applyHeaders(headers, res);
-
- if (options.preflightContinue) {
- next();
- } else {
- // Safari (and potentially other browsers) need content-length 0,
- // for 204 or they just hang waiting for a body
- res.statusCode = options.optionsSuccessStatus;
- res.setHeader('Content-Length', '0');
- res.end();
- }
- } else {
- // actual response
- headers.push(configureOrigin(options, req));
- headers.push(configureCredentials(options))
- headers.push(configureExposedHeaders(options))
- applyHeaders(headers, res);
- next();
- }
- }
-
- function middlewareWrapper(o) {
- // if options are static (either via defaults or custom options passed in), wrap in a function
- var optionsCallback = null;
- if (typeof o === 'function') {
- optionsCallback = o;
- } else {
- optionsCallback = function (req, cb) {
- cb(null, o);
- };
- }
-
- return function corsMiddleware(req, res, next) {
- optionsCallback(req, function (err, options) {
- if (err) {
- next(err);
- } else {
- var corsOptions = assign({}, defaults, options);
- var originCallback = null;
- if (corsOptions.origin && typeof corsOptions.origin === 'function') {
- originCallback = corsOptions.origin;
- } else if (corsOptions.origin) {
- originCallback = function (origin, cb) {
- cb(null, corsOptions.origin);
- };
- }
-
- if (originCallback) {
- originCallback(req.headers.origin, function (err2, origin) {
- if (err2 || !origin) {
- next(err2);
- } else {
- corsOptions.origin = origin;
- cors(corsOptions, req, res, next);
- }
- });
- } else {
- next();
- }
- }
- });
- };
- }
-
- // can pass either an options hash, an options delegate, or nothing
- module.exports = middlewareWrapper;
-
-}());
diff --git a/node_modules/cors/package.json b/node_modules/cors/package.json
deleted file mode 100644
index e90bac8..0000000
--- a/node_modules/cors/package.json
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "name": "cors",
- "description": "Node.js CORS middleware",
- "version": "2.8.6",
- "author": "Troy Goode (https://github.com/troygoode/)",
- "license": "MIT",
- "keywords": [
- "cors",
- "express",
- "connect",
- "middleware"
- ],
- "repository": "expressjs/cors",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- },
- "main": "./lib/index.js",
- "dependencies": {
- "object-assign": "^4",
- "vary": "^1"
- },
- "devDependencies": {
- "after": "0.8.2",
- "eslint": "7.30.0",
- "express": "4.21.2",
- "mocha": "9.2.2",
- "nyc": "15.1.0",
- "supertest": "6.1.3"
- },
- "files": [
- "lib/index.js"
- ],
- "engines": {
- "node": ">= 0.10"
- },
- "scripts": {
- "test": "npm run lint && npm run test-ci",
- "test-ci": "nyc --reporter=lcov --reporter=text mocha --require test/support/env",
- "lint": "eslint lib test"
- }
-}
diff --git a/node_modules/debug/.coveralls.yml b/node_modules/debug/.coveralls.yml
new file mode 100644
index 0000000..20a7068
--- /dev/null
+++ b/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/node_modules/debug/.eslintrc b/node_modules/debug/.eslintrc
new file mode 100644
index 0000000..8a37ae2
--- /dev/null
+++ b/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+ "env": {
+ "browser": true,
+ "node": true
+ },
+ "rules": {
+ "no-console": 0,
+ "no-empty": [1, { "allowEmptyCatch": true }]
+ },
+ "extends": "eslint:recommended"
+}
diff --git a/node_modules/debug/.npmignore b/node_modules/debug/.npmignore
new file mode 100644
index 0000000..5f60eec
--- /dev/null
+++ b/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/node_modules/debug/.travis.yml b/node_modules/debug/.travis.yml
new file mode 100644
index 0000000..6c6090c
--- /dev/null
+++ b/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+ - "6"
+ - "5"
+ - "4"
+
+install:
+ - make node_modules
+
+script:
+ - make lint
+ - make test
+ - make coveralls
diff --git a/node_modules/debug/CHANGELOG.md b/node_modules/debug/CHANGELOG.md
new file mode 100644
index 0000000..eadaa18
--- /dev/null
+++ b/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+ * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+ * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+ * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+ * Fix: Inline extend function in node implementation (#452, @dougwilson)
+ * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+
+ * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+ * Misc: clean up browser reference checks (#447, @thebigredgeek)
+ * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+ * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+ * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+ * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+ * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+ * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+ * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+ * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+ * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+ * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+ * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+ * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+ * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+ * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+ * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+ * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+ * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+ * Docs: fixed README typo (#391, @lurch)
+ * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+ * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+ * Fix: wrong reference in bower file (@thebigredgeek)
+ * Fix: webworker compatibility (@thebigredgeek)
+ * Fix: output formatting issue (#388, @kribblo)
+ * Fix: babel-loader compatibility (#383, @escwald)
+ * Misc: removed built asset from repo and publications (@thebigredgeek)
+ * Misc: moved source files to /src (#378, @yamikuronue)
+ * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+ * Test: coveralls integration (#378, @yamikuronue)
+ * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+ * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+ * Fix: custom log function (#379, @hsiliev)
+ * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+ * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+ * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+ * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+ * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+ * Fix: browser colors (#367, @tootallnate)
+ * Misc: travis ci integration (@thebigredgeek)
+ * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+ * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+ * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+ * Fix: revert "handle regex special characters" (@tootallnate)
+ * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+ * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+ * Improvement: allow colors in workers (#335, @botverse)
+ * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+ * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+ * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+ * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+ * Fix: be super-safe in index.js as well (@TooTallNate)
+ * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+ * Fix: Added electron compatibility (#324, @paulcbetts)
+ * Improvement: Added performance optimizations (@tootallnate)
+ * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+ * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+ * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+ * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+ * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+ * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+ * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+ * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+ * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+ * Readme: fix USE_COLORS to DEBUG_COLORS
+ * Readme: Doc fixes for format string sugar (#269, @mlucool)
+ * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+ * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+ * Readme: better docs for browser support (#224, @matthewmueller)
+ * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+ * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+ * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+ * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+ * package: update "ms" to v0.7.1 (#202, @dougwilson)
+ * README: add logging to file example (#193, @DanielOchoa)
+ * README: fixed a typo (#191, @amir-s)
+ * browser: expose `storage` (#190, @stephenmathieson)
+ * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+ * Updated stdout/stderr example (#186)
+ * Updated example/stdout.js to match debug current behaviour
+ * Renamed example/stderr.js to stdout.js
+ * Update Readme.md (#184)
+ * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+ * dist: recompile
+ * update "ms" to v0.7.0
+ * package: update "browserify" to v9.0.3
+ * component: fix "ms.js" repo location
+ * changed bower package name
+ * updated documentation about using debug in a browser
+ * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+ * browser: use `typeof` to check for `console` existence
+ * browser: check for `console.log` truthiness (fix IE 8/9)
+ * browser: add support for Chrome apps
+ * Readme: added Windows usage remarks
+ * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+ * node: implement `DEBUG_FD` env variable support
+ * package: update "browserify" to v6.1.0
+ * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+ * package: update "browserify" to v5.11.0
+ * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+ * dist: recompile
+ * example: remove `console.info()` log usage
+ * example: add "Content-Type" UTF-8 header to browser example
+ * browser: place %c marker after the space character
+ * browser: reset the "content" color via `color: inherit`
+ * browser: add colors support for Firefox >= v31
+ * debug: prefer an instance `log()` function over the global one (#119)
+ * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+ * Add support for multiple wildcards in namespaces (#122, @seegno)
+ * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+ * browser: update color palette (#113, @gscottolson)
+ * common: make console logging function configurable (#108, @timoxley)
+ * node: fix %o colors on old node <= 0.8.x
+ * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+ * browser: use `removeItem()` to clear localStorage
+ * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+ * package: add "contributors" section
+ * node: fix comment typo
+ * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+ * make ms diff be global, not be scope
+ * debug: ignore empty strings in enable()
+ * node: make DEBUG_COLORS able to disable coloring
+ * *: export the `colors` array
+ * npmignore: don't publish the `dist` dir
+ * Makefile: refactor to use browserify
+ * package: add "browserify" as a dev dependency
+ * Readme: add Web Inspector Colors section
+ * node: reset terminal color for the debug content
+ * node: map "%o" to `util.inspect()`
+ * browser: map "%j" to `JSON.stringify()`
+ * debug: add custom "formatters"
+ * debug: use "ms" module for humanizing the diff
+ * Readme: add "bash" syntax highlighting
+ * browser: add Firebug color support
+ * browser: add colors for WebKit browsers
+ * node: apply log to `console`
+ * rewrite: abstract common logic for Node & browsers
+ * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+ * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+ * add `enable()` method for nodejs. Closes #27
+ * change from stderr to stdout
+ * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+ * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+ * fix: catch localStorage security error when cookies are blocked (Chrome)
+ * add debug(err) support. Closes #46
+ * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+ * fix package.json
+ * fix: Mobile Safari (private mode) is broken with debug
+ * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+ * add repository URL to package.json
+ * add DEBUG_COLORED to force colored output
+ * add browserify support
+ * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+ * Added .component to package.json
+ * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+ * Added support for "-" prefix in DEBUG [Vinay Pulim]
+ * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+ * Added: humanize diffs. Closes #8
+ * Added `debug.disable()` to the CS variant
+ * Removed padding. Closes #10
+ * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+ * Added browser variant support for older browsers [TooTallNate]
+ * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+ * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+ * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+ * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+ * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+ * Initial release
diff --git a/node_modules/debug/LICENSE b/node_modules/debug/LICENSE
index 1a9820e..658c933 100644
--- a/node_modules/debug/LICENSE
+++ b/node_modules/debug/LICENSE
@@ -1,20 +1,19 @@
(The MIT License)
-Copyright (c) 2014-2017 TJ Holowaychuk
-Copyright (c) 2018-2021 Josh Junon
+Copyright (c) 2014 TJ Holowaychuk
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-and associated documentation files (the 'Software'), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software
+and associated documentation files (the 'Software'), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
-The above copyright notice and this permission notice shall be included in all copies or substantial
+The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
-LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/debug/Makefile b/node_modules/debug/Makefile
new file mode 100644
index 0000000..584da8b
--- /dev/null
+++ b/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+ @NODE_ENV= $(PKG) install
+ @touch node_modules
+
+lint: .FORCE
+ eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+ istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+ mkdir -p dist
+
+ @$(BROWSERIFY) \
+ --standalone debug \
+ . > dist/debug.js
+
+ karma start --single-run
+ rimraf dist
+
+test: .FORCE
+ concurrently \
+ "make test-node" \
+ "make test-browser"
+
+coveralls:
+ cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/node_modules/debug/README.md b/node_modules/debug/README.md
index 9ebdfbf..f67be6b 100644
--- a/node_modules/debug/README.md
+++ b/node_modules/debug/README.md
@@ -1,11 +1,12 @@
# debug
-[](#backers)
+[](https://travis-ci.org/visionmedia/debug) [](https://coveralls.io/github/visionmedia/debug?branch=master) [](https://visionmedia-community-slackin.now.sh/) [](#backers)
[](#sponsors)
-
-A tiny JavaScript debugging utility modelled after Node.js core's debugging
-technique. Works in Node.js and web browsers.
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
## Installation
@@ -17,7 +18,7 @@ $ npm install debug
`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
-Example [_app.js_](./examples/node/app.js):
+Example _app.js_:
```js
var debug = require('debug')('http')
@@ -26,7 +27,7 @@ var debug = require('debug')('http')
// fake app
-debug('booting %o', name);
+debug('booting %s', name);
http.createServer(function(req, res){
debug(req.method + ' ' + req.url);
@@ -40,148 +41,81 @@ http.createServer(function(req, res){
require('./worker');
```
-Example [_worker.js_](./examples/node/worker.js):
+Example _worker.js_:
```js
-var a = require('debug')('worker:a')
- , b = require('debug')('worker:b');
+var debug = require('debug')('worker');
-function work() {
- a('doing lots of uninteresting work');
- setTimeout(work, Math.random() * 1000);
-}
-
-work();
-
-function workb() {
- b('doing some work');
- setTimeout(workb, Math.random() * 2000);
-}
-
-workb();
+setInterval(function(){
+ debug('doing some work');
+}, 1000);
```
-The `DEBUG` environment variable is then used to enable these based on space or
-comma-delimited names.
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
-Here are some examples:
+ 
-
-
-
+ 
-#### Windows command prompt notes
+#### Windows note
-##### CMD
+ On Windows the environment variable is set using the `set` command.
-On Windows the environment variable is set using the `set` command.
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
-```cmd
-set DEBUG=*,-not_this
-```
+ Note that PowerShell uses different syntax to set environment variables.
-Example:
-
-```cmd
-set DEBUG=* & node app.js
-```
-
-##### PowerShell (VS Code default)
-
-PowerShell uses different syntax to set environment variables.
-
-```cmd
-$env:DEBUG = "*,-not_this"
-```
-
-Example:
-
-```cmd
-$env:DEBUG='app';node app.js
-```
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+ ```
Then, run the program to be debugged as usual.
-npm script example:
-```js
- "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
-```
-
-## Namespace Colors
-
-Every debug instance has a color generated for it based on its namespace name.
-This helps when visually parsing the debug output to identify which debug instance
-a debug line belongs to.
-
-#### Node.js
-
-In Node.js, colors are enabled when stderr is a TTY. You also _should_ install
-the [`supports-color`](https://npmjs.org/supports-color) module alongside debug,
-otherwise debug will only use a small handful of basic colors.
-
-
-
-#### Web Browser
-
-Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
-option. These are WebKit web inspectors, Firefox ([since version
-31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
-and the Firebug plugin for Firefox (any version).
-
-
-
-
## Millisecond diff
-When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+ When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
-
+ 
-When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:
-
-
+ When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+ 
## Conventions
-If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output.
+ If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
## Wildcards
-The `*` character may be used as a wildcard. Suppose for example your library has
-debuggers named "connect:bodyParser", "connect:compress", "connect:session",
-instead of listing all three with
-`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do
-`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+ The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
-You can also exclude specific debuggers by prefixing them with a "-" character.
-For example, `DEBUG=*,-connect:*` would include all debuggers except those
-starting with "connect:".
+ You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
## Environment Variables
-When running through Node.js, you can set a few environment variables that will
-change the behavior of the debug logging:
+ When running through Node.js, you can set a few environment variables that will
+ change the behavior of the debug logging:
| Name | Purpose |
|-----------|-------------------------------------------------|
| `DEBUG` | Enables/disables specific debugging namespaces. |
-| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). |
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
-| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_DEPTH` | Object inspection depth. |
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
-__Note:__ The environment variables beginning with `DEBUG_` end up being
-converted into an Options object that gets used with `%o`/`%O` formatters.
-See the Node.js documentation for
-[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
-for the complete list.
+ __Note:__ The environment variables beginning with `DEBUG_` end up being
+ converted into an Options object that gets used with `%o`/`%O` formatters.
+ See the Node.js documentation for
+ [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+ for the complete list.
## Formatters
-Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.
-Below are the officially supported formatters:
+
+ Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
| Formatter | Representation |
|-----------|----------------|
@@ -192,12 +126,9 @@ Below are the officially supported formatters:
| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
| `%%` | Single percent sign ('%'). This does not consume an argument. |
-
### Custom formatters
-You can add custom formatters by extending the `debug.formatters` object.
-For example, if you wanted to add support for rendering a Buffer as hex with
-`%h`, you could do something like:
+ You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
```js
const createDebug = require('debug')
@@ -211,16 +142,14 @@ debug('this is hex: %h', new Buffer('hello world'))
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
```
+## Browser support
+ You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+ or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+ if you don't want to build it yourself.
-## Browser Support
-
-You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
-or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
-if you don't want to build it yourself.
-
-Debug's enable state is currently persisted by `localStorage`.
-Consider the situation shown below where you have `worker:a` and `worker:b`,
-and wish to debug both. You can enable this using `localStorage.debug`:
+ Debug's enable state is currently persisted by `localStorage`.
+ Consider the situation shown below where you have `worker:a` and `worker:b`,
+ and wish to debug both. You can enable this using `localStorage.debug`:
```js
localStorage.debug = 'worker:*'
@@ -241,15 +170,23 @@ setInterval(function(){
}, 1200);
```
-In Chromium-based web browsers (e.g. Brave, Chrome, and Electron), the JavaScript console will—by default—only show messages logged by `debug` if the "Verbose" log level is _enabled_.
+#### Web Inspector Colors
+
+ Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+ option. These are WebKit web inspectors, Firefox ([since version
+ 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+ and the Firebug plugin for Firefox (any version).
+
+ Colored output looks something like:
+
+ 
-
## Output streams
By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
-Example [_stdout.js_](./examples/node/stdout.js):
+Example _stdout.js_:
```js
var debug = require('debug');
@@ -271,118 +208,13 @@ error('now goes to stdout via console.info');
log('still goes to stdout, but via console.info now');
```
-## Extend
-You can simply extend debugger
-```js
-const log = require('debug')('auth');
-
-//creates new debug instance with extended namespace
-const logSign = log.extend('sign');
-const logLogin = log.extend('login');
-
-log('hello'); // auth hello
-logSign('hello'); //auth:sign hello
-logLogin('hello'); //auth:login hello
-```
-
-## Set dynamically
-
-You can also enable debug dynamically by calling the `enable()` method :
-
-```js
-let debug = require('debug');
-
-console.log(1, debug.enabled('test'));
-
-debug.enable('test');
-console.log(2, debug.enabled('test'));
-
-debug.disable();
-console.log(3, debug.enabled('test'));
-
-```
-
-print :
-```
-1 false
-2 true
-3 false
-```
-
-Usage :
-`enable(namespaces)`
-`namespaces` can include modes separated by a colon and wildcards.
-
-Note that calling `enable()` completely overrides previously set DEBUG variable :
-
-```
-$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
-=> false
-```
-
-`disable()`
-
-Will disable all namespaces. The functions returns the namespaces currently
-enabled (and skipped). This can be useful if you want to disable debugging
-temporarily without knowing what was enabled to begin with.
-
-For example:
-
-```js
-let debug = require('debug');
-debug.enable('foo:*,-foo:bar');
-let namespaces = debug.disable();
-debug.enable(namespaces);
-```
-
-Note: There is no guarantee that the string will be identical to the initial
-enable string, but semantically they will be identical.
-
-## Checking whether a debug target is enabled
-
-After you've created a debug instance, you can determine whether or not it is
-enabled by checking the `enabled` property:
-
-```javascript
-const debug = require('debug')('http');
-
-if (debug.enabled) {
- // do stuff...
-}
-```
-
-You can also manually toggle this property to force the debug instance to be
-enabled or disabled.
-
-## Usage in child processes
-
-Due to the way `debug` detects if the output is a TTY or not, colors are not shown in child processes when `stderr` is piped. A solution is to pass the `DEBUG_COLORS=1` environment variable to the child process.
-For example:
-
-```javascript
-worker = fork(WORKER_WRAP_PATH, [workerPath], {
- stdio: [
- /* stdin: */ 0,
- /* stdout: */ 'pipe',
- /* stderr: */ 'pipe',
- 'ipc',
- ],
- env: Object.assign({}, process.env, {
- DEBUG_COLORS: 1 // without this settings, colors won't be shown
- }),
-});
-
-worker.stderr.pipe(process.stderr, { end: false });
-```
-
## Authors
- TJ Holowaychuk
- Nathan Rajlich
- Andrew Rhyne
- - Josh Junon
-
+
## Backers
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
@@ -458,8 +290,7 @@ Become a sponsor and get your logo on our README on Github with a link to your s
(The MIT License)
-Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>
-Copyright (c) 2018-2021 Josh Junon
+Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/node_modules/debug/component.json b/node_modules/debug/component.json
new file mode 100644
index 0000000..9de2641
--- /dev/null
+++ b/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+ "name": "debug",
+ "repo": "visionmedia/debug",
+ "description": "small debugging utility",
+ "version": "2.6.9",
+ "keywords": [
+ "debug",
+ "log",
+ "debugger"
+ ],
+ "main": "src/browser.js",
+ "scripts": [
+ "src/browser.js",
+ "src/debug.js"
+ ],
+ "dependencies": {
+ "rauchg/ms.js": "0.7.1"
+ }
+}
diff --git a/node_modules/debug/karma.conf.js b/node_modules/debug/karma.conf.js
new file mode 100644
index 0000000..103a82d
--- /dev/null
+++ b/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+ config.set({
+
+ // base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: '',
+
+
+ // frameworks to use
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['mocha', 'chai', 'sinon'],
+
+
+ // list of files / patterns to load in the browser
+ files: [
+ 'dist/debug.js',
+ 'test/*spec.js'
+ ],
+
+
+ // list of files to exclude
+ exclude: [
+ 'src/node.js'
+ ],
+
+
+ // preprocess matching files before serving them to the browser
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors: {
+ },
+
+ // test results reporter to use
+ // possible values: 'dots', 'progress'
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['progress'],
+
+
+ // web server port
+ port: 9876,
+
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: true,
+
+
+ // start these browsers
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: ['PhantomJS'],
+
+
+ // Continuous Integration mode
+ // if true, Karma captures browsers, runs the tests and exits
+ singleRun: false,
+
+ // Concurrency level
+ // how many browser should be started simultaneous
+ concurrency: Infinity
+ })
+}
diff --git a/node_modules/debug/node.js b/node_modules/debug/node.js
new file mode 100644
index 0000000..7fc36fe
--- /dev/null
+++ b/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/node_modules/debug/package.json b/node_modules/debug/package.json
index ee8abb5..dc787ba 100644
--- a/node_modules/debug/package.json
+++ b/node_modules/debug/package.json
@@ -1,64 +1,49 @@
{
"name": "debug",
- "version": "4.4.3",
+ "version": "2.6.9",
"repository": {
"type": "git",
- "url": "git://github.com/debug-js/debug.git"
+ "url": "git://github.com/visionmedia/debug.git"
},
- "description": "Lightweight debugging utility for Node.js and the browser",
+ "description": "small debugging utility",
"keywords": [
"debug",
"log",
"debugger"
],
- "files": [
- "src",
- "LICENSE",
- "README.md"
- ],
- "author": "Josh Junon (https://github.com/qix-)",
+ "author": "TJ Holowaychuk ",
"contributors": [
- "TJ Holowaychuk ",
"Nathan Rajlich (http://n8.io)",
"Andrew Rhyne "
],
"license": "MIT",
- "scripts": {
- "lint": "xo",
- "test": "npm run test:node && npm run test:browser && npm run lint",
- "test:node": "mocha test.js test.node.js",
- "test:browser": "karma start --single-run",
- "test:coverage": "cat ./coverage/lcov.info | coveralls"
- },
"dependencies": {
- "ms": "^2.1.3"
+ "ms": "2.0.0"
},
"devDependencies": {
- "brfs": "^2.0.1",
- "browserify": "^16.2.3",
- "coveralls": "^3.0.2",
- "karma": "^3.1.4",
- "karma-browserify": "^6.0.0",
- "karma-chrome-launcher": "^2.2.0",
+ "browserify": "9.0.3",
+ "chai": "^3.5.0",
+ "concurrently": "^3.1.0",
+ "coveralls": "^2.11.15",
+ "eslint": "^3.12.1",
+ "istanbul": "^0.4.5",
+ "karma": "^1.3.0",
+ "karma-chai": "^0.1.0",
"karma-mocha": "^1.3.0",
- "mocha": "^5.2.0",
+ "karma-phantomjs-launcher": "^1.0.2",
+ "karma-sinon": "^1.0.5",
+ "mocha": "^3.2.0",
"mocha-lcov-reporter": "^1.2.0",
- "sinon": "^14.0.0",
- "xo": "^0.23.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "rimraf": "^2.5.4",
+ "sinon": "^1.17.6",
+ "sinon-chai": "^2.8.0"
},
"main": "./src/index.js",
"browser": "./src/browser.js",
- "engines": {
- "node": ">=6.0"
- },
- "xo": {
- "rules": {
- "import/extensions": "off"
+ "component": {
+ "scripts": {
+ "debug/index.js": "browser.js",
+ "debug/debug.js": "debug.js"
}
}
}
diff --git a/node_modules/debug/src/browser.js b/node_modules/debug/src/browser.js
index 5993451..7106924 100644
--- a/node_modules/debug/src/browser.js
+++ b/node_modules/debug/src/browser.js
@@ -1,106 +1,31 @@
-/* eslint-env browser */
-
/**
* This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
*/
+exports = module.exports = require('./debug');
+exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
-exports.storage = localstorage();
-exports.destroy = (() => {
- let warned = false;
-
- return () => {
- if (!warned) {
- warned = true;
- console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
- }
- };
-})();
+exports.storage = 'undefined' != typeof chrome
+ && 'undefined' != typeof chrome.storage
+ ? chrome.storage.local
+ : localstorage();
/**
* Colors.
*/
exports.colors = [
- '#0000CC',
- '#0000FF',
- '#0033CC',
- '#0033FF',
- '#0066CC',
- '#0066FF',
- '#0099CC',
- '#0099FF',
- '#00CC00',
- '#00CC33',
- '#00CC66',
- '#00CC99',
- '#00CCCC',
- '#00CCFF',
- '#3300CC',
- '#3300FF',
- '#3333CC',
- '#3333FF',
- '#3366CC',
- '#3366FF',
- '#3399CC',
- '#3399FF',
- '#33CC00',
- '#33CC33',
- '#33CC66',
- '#33CC99',
- '#33CCCC',
- '#33CCFF',
- '#6600CC',
- '#6600FF',
- '#6633CC',
- '#6633FF',
- '#66CC00',
- '#66CC33',
- '#9900CC',
- '#9900FF',
- '#9933CC',
- '#9933FF',
- '#99CC00',
- '#99CC33',
- '#CC0000',
- '#CC0033',
- '#CC0066',
- '#CC0099',
- '#CC00CC',
- '#CC00FF',
- '#CC3300',
- '#CC3333',
- '#CC3366',
- '#CC3399',
- '#CC33CC',
- '#CC33FF',
- '#CC6600',
- '#CC6633',
- '#CC9900',
- '#CC9933',
- '#CCCC00',
- '#CCCC33',
- '#FF0000',
- '#FF0033',
- '#FF0066',
- '#FF0099',
- '#FF00CC',
- '#FF00FF',
- '#FF3300',
- '#FF3333',
- '#FF3366',
- '#FF3399',
- '#FF33CC',
- '#FF33FF',
- '#FF6600',
- '#FF6633',
- '#FF9900',
- '#FF9933',
- '#FFCC00',
- '#FFCC33'
+ 'lightseagreen',
+ 'forestgreen',
+ 'goldenrod',
+ 'dodgerblue',
+ 'darkorchid',
+ 'crimson'
];
/**
@@ -111,35 +36,39 @@ exports.colors = [
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
-// eslint-disable-next-line complexity
function useColors() {
- // NB: In an Electron preload script, document will be defined but not fully
- // initialized. Since we know we're in Chrome, we'll just detect this case
- // explicitly
- if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
- return true;
- }
+ // NB: In an Electron preload script, document will be defined but not fully
+ // initialized. Since we know we're in Chrome, we'll just detect this case
+ // explicitly
+ if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+ return true;
+ }
- // Internet Explorer and Edge do not support colors.
- if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
- return false;
- }
-
- let m;
-
- // Is webkit? http://stackoverflow.com/a/16459606/376773
- // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
- // eslint-disable-next-line no-return-assign
- return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
- // Is firebug? http://stackoverflow.com/a/398120/376773
- (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
- // Is firefox >= v31?
- // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
- (typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) ||
- // Double check webkit in userAgent just in case we are in a worker
- (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+ // is webkit? http://stackoverflow.com/a/16459606/376773
+ // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+ return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+ // is firebug? http://stackoverflow.com/a/398120/376773
+ (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+ // is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+ // double check webkit in userAgent just in case we are in a worker
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+ try {
+ return JSON.stringify(v);
+ } catch (err) {
+ return '[UnexpectedJSONParseError]: ' + err.message;
+ }
+};
+
+
/**
* Colorize log arguments if enabled.
*
@@ -147,49 +76,52 @@ function useColors() {
*/
function formatArgs(args) {
- args[0] = (this.useColors ? '%c' : '') +
- this.namespace +
- (this.useColors ? ' %c' : ' ') +
- args[0] +
- (this.useColors ? '%c ' : ' ') +
- '+' + module.exports.humanize(this.diff);
+ var useColors = this.useColors;
- if (!this.useColors) {
- return;
- }
+ args[0] = (useColors ? '%c' : '')
+ + this.namespace
+ + (useColors ? ' %c' : ' ')
+ + args[0]
+ + (useColors ? '%c ' : ' ')
+ + '+' + exports.humanize(this.diff);
- const c = 'color: ' + this.color;
- args.splice(1, 0, c, 'color: inherit');
+ if (!useColors) return;
- // The final "%c" is somewhat tricky, because there could be other
- // arguments passed either before or after the %c, so we need to
- // figure out the correct index to insert the CSS into
- let index = 0;
- let lastC = 0;
- args[0].replace(/%[a-zA-Z%]/g, match => {
- if (match === '%%') {
- return;
- }
- index++;
- if (match === '%c') {
- // We only are interested in the *last* %c
- // (the user may have provided their own)
- lastC = index;
- }
- });
+ var c = 'color: ' + this.color;
+ args.splice(1, 0, c, 'color: inherit')
- args.splice(lastC, 0, c);
+ // the final "%c" is somewhat tricky, because there could be other
+ // arguments passed either before or after the %c, so we need to
+ // figure out the correct index to insert the CSS into
+ var index = 0;
+ var lastC = 0;
+ args[0].replace(/%[a-zA-Z%]/g, function(match) {
+ if ('%%' === match) return;
+ index++;
+ if ('%c' === match) {
+ // we only are interested in the *last* %c
+ // (the user may have provided their own)
+ lastC = index;
+ }
+ });
+
+ args.splice(lastC, 0, c);
}
/**
- * Invokes `console.debug()` when available.
- * No-op when `console.debug` is not a "function".
- * If `console.debug` is not available, falls back
- * to `console.log`.
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
*
* @api public
*/
-exports.log = console.debug || console.log || (() => {});
+
+function log() {
+ // this hackery is required for IE8/9, where
+ // the `console.log` function doesn't have 'apply'
+ return 'object' === typeof console
+ && console.log
+ && Function.prototype.apply.call(console.log, console, arguments);
+}
/**
* Save `namespaces`.
@@ -197,17 +129,15 @@ exports.log = console.debug || console.log || (() => {});
* @param {String} namespaces
* @api private
*/
+
function save(namespaces) {
- try {
- if (namespaces) {
- exports.storage.setItem('debug', namespaces);
- } else {
- exports.storage.removeItem('debug');
- }
- } catch (error) {
- // Swallow
- // XXX (@Qix-) should we be logging these?
- }
+ try {
+ if (null == namespaces) {
+ exports.storage.removeItem('debug');
+ } else {
+ exports.storage.debug = namespaces;
+ }
+ } catch(e) {}
}
/**
@@ -216,23 +146,27 @@ function save(namespaces) {
* @return {String} returns the previously persisted debug modes
* @api private
*/
+
function load() {
- let r;
- try {
- r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ;
- } catch (error) {
- // Swallow
- // XXX (@Qix-) should we be logging these?
- }
+ var r;
+ try {
+ r = exports.storage.debug;
+ } catch(e) {}
- // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
- if (!r && typeof process !== 'undefined' && 'env' in process) {
- r = process.env.DEBUG;
- }
+ // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+ if (!r && typeof process !== 'undefined' && 'env' in process) {
+ r = process.env.DEBUG;
+ }
- return r;
+ return r;
}
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
/**
* Localstorage attempts to return the localstorage.
*
@@ -245,28 +179,7 @@ function load() {
*/
function localstorage() {
- try {
- // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
- // The Browser also has localStorage in the global context.
- return localStorage;
- } catch (error) {
- // Swallow
- // XXX (@Qix-) should we be logging these?
- }
+ try {
+ return window.localStorage;
+ } catch (e) {}
}
-
-module.exports = require('./common')(exports);
-
-const {formatters} = module.exports;
-
-/**
- * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
- */
-
-formatters.j = function (v) {
- try {
- return JSON.stringify(v);
- } catch (error) {
- return '[UnexpectedJSONParseError]: ' + error.message;
- }
-};
diff --git a/node_modules/debug/src/common.js b/node_modules/debug/src/common.js
deleted file mode 100644
index 141cb57..0000000
--- a/node_modules/debug/src/common.js
+++ /dev/null
@@ -1,292 +0,0 @@
-
-/**
- * This is the common logic for both the Node.js and web browser
- * implementations of `debug()`.
- */
-
-function setup(env) {
- createDebug.debug = createDebug;
- createDebug.default = createDebug;
- createDebug.coerce = coerce;
- createDebug.disable = disable;
- createDebug.enable = enable;
- createDebug.enabled = enabled;
- createDebug.humanize = require('ms');
- createDebug.destroy = destroy;
-
- Object.keys(env).forEach(key => {
- createDebug[key] = env[key];
- });
-
- /**
- * The currently active debug mode names, and names to skip.
- */
-
- createDebug.names = [];
- createDebug.skips = [];
-
- /**
- * Map of special "%n" handling functions, for the debug "format" argument.
- *
- * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
- */
- createDebug.formatters = {};
-
- /**
- * Selects a color for a debug namespace
- * @param {String} namespace The namespace string for the debug instance to be colored
- * @return {Number|String} An ANSI color code for the given namespace
- * @api private
- */
- function selectColor(namespace) {
- let hash = 0;
-
- for (let i = 0; i < namespace.length; i++) {
- hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
- hash |= 0; // Convert to 32bit integer
- }
-
- return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
- }
- createDebug.selectColor = selectColor;
-
- /**
- * Create a debugger with the given `namespace`.
- *
- * @param {String} namespace
- * @return {Function}
- * @api public
- */
- function createDebug(namespace) {
- let prevTime;
- let enableOverride = null;
- let namespacesCache;
- let enabledCache;
-
- function debug(...args) {
- // Disabled?
- if (!debug.enabled) {
- return;
- }
-
- const self = debug;
-
- // Set `diff` timestamp
- const curr = Number(new Date());
- const ms = curr - (prevTime || curr);
- self.diff = ms;
- self.prev = prevTime;
- self.curr = curr;
- prevTime = curr;
-
- args[0] = createDebug.coerce(args[0]);
-
- if (typeof args[0] !== 'string') {
- // Anything else let's inspect with %O
- args.unshift('%O');
- }
-
- // Apply any `formatters` transformations
- let index = 0;
- args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
- // If we encounter an escaped % then don't increase the array index
- if (match === '%%') {
- return '%';
- }
- index++;
- const formatter = createDebug.formatters[format];
- if (typeof formatter === 'function') {
- const val = args[index];
- match = formatter.call(self, val);
-
- // Now we need to remove `args[index]` since it's inlined in the `format`
- args.splice(index, 1);
- index--;
- }
- return match;
- });
-
- // Apply env-specific formatting (colors, etc.)
- createDebug.formatArgs.call(self, args);
-
- const logFn = self.log || createDebug.log;
- logFn.apply(self, args);
- }
-
- debug.namespace = namespace;
- debug.useColors = createDebug.useColors();
- debug.color = createDebug.selectColor(namespace);
- debug.extend = extend;
- debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
-
- Object.defineProperty(debug, 'enabled', {
- enumerable: true,
- configurable: false,
- get: () => {
- if (enableOverride !== null) {
- return enableOverride;
- }
- if (namespacesCache !== createDebug.namespaces) {
- namespacesCache = createDebug.namespaces;
- enabledCache = createDebug.enabled(namespace);
- }
-
- return enabledCache;
- },
- set: v => {
- enableOverride = v;
- }
- });
-
- // Env-specific initialization logic for debug instances
- if (typeof createDebug.init === 'function') {
- createDebug.init(debug);
- }
-
- return debug;
- }
-
- function extend(namespace, delimiter) {
- const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
- newDebug.log = this.log;
- return newDebug;
- }
-
- /**
- * Enables a debug mode by namespaces. This can include modes
- * separated by a colon and wildcards.
- *
- * @param {String} namespaces
- * @api public
- */
- function enable(namespaces) {
- createDebug.save(namespaces);
- createDebug.namespaces = namespaces;
-
- createDebug.names = [];
- createDebug.skips = [];
-
- const split = (typeof namespaces === 'string' ? namespaces : '')
- .trim()
- .replace(/\s+/g, ',')
- .split(',')
- .filter(Boolean);
-
- for (const ns of split) {
- if (ns[0] === '-') {
- createDebug.skips.push(ns.slice(1));
- } else {
- createDebug.names.push(ns);
- }
- }
- }
-
- /**
- * Checks if the given string matches a namespace template, honoring
- * asterisks as wildcards.
- *
- * @param {String} search
- * @param {String} template
- * @return {Boolean}
- */
- function matchesTemplate(search, template) {
- let searchIndex = 0;
- let templateIndex = 0;
- let starIndex = -1;
- let matchIndex = 0;
-
- while (searchIndex < search.length) {
- if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
- // Match character or proceed with wildcard
- if (template[templateIndex] === '*') {
- starIndex = templateIndex;
- matchIndex = searchIndex;
- templateIndex++; // Skip the '*'
- } else {
- searchIndex++;
- templateIndex++;
- }
- } else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
- // Backtrack to the last '*' and try to match more characters
- templateIndex = starIndex + 1;
- matchIndex++;
- searchIndex = matchIndex;
- } else {
- return false; // No match
- }
- }
-
- // Handle trailing '*' in template
- while (templateIndex < template.length && template[templateIndex] === '*') {
- templateIndex++;
- }
-
- return templateIndex === template.length;
- }
-
- /**
- * Disable debug output.
- *
- * @return {String} namespaces
- * @api public
- */
- function disable() {
- const namespaces = [
- ...createDebug.names,
- ...createDebug.skips.map(namespace => '-' + namespace)
- ].join(',');
- createDebug.enable('');
- return namespaces;
- }
-
- /**
- * Returns true if the given mode name is enabled, false otherwise.
- *
- * @param {String} name
- * @return {Boolean}
- * @api public
- */
- function enabled(name) {
- for (const skip of createDebug.skips) {
- if (matchesTemplate(name, skip)) {
- return false;
- }
- }
-
- for (const ns of createDebug.names) {
- if (matchesTemplate(name, ns)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Coerce `val`.
- *
- * @param {Mixed} val
- * @return {Mixed}
- * @api private
- */
- function coerce(val) {
- if (val instanceof Error) {
- return val.stack || val.message;
- }
- return val;
- }
-
- /**
- * XXX DO NOT USE. This is a temporary stub function.
- * XXX It WILL be removed in the next major release.
- */
- function destroy() {
- console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
- }
-
- createDebug.enable(createDebug.load());
-
- return createDebug;
-}
-
-module.exports = setup;
diff --git a/node_modules/debug/src/debug.js b/node_modules/debug/src/debug.js
new file mode 100644
index 0000000..6a5e3fc
--- /dev/null
+++ b/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+ var hash = 0, i;
+
+ for (i in namespace) {
+ hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
+ hash |= 0; // Convert to 32bit integer
+ }
+
+ return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+ function debug() {
+ // disabled?
+ if (!debug.enabled) return;
+
+ var self = debug;
+
+ // set `diff` timestamp
+ var curr = +new Date();
+ var ms = curr - (prevTime || curr);
+ self.diff = ms;
+ self.prev = prevTime;
+ self.curr = curr;
+ prevTime = curr;
+
+ // turn the `arguments` into a proper Array
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; i++) {
+ args[i] = arguments[i];
+ }
+
+ args[0] = exports.coerce(args[0]);
+
+ if ('string' !== typeof args[0]) {
+ // anything else let's inspect with %O
+ args.unshift('%O');
+ }
+
+ // apply any `formatters` transformations
+ var index = 0;
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+ // if we encounter an escaped % then don't increase the array index
+ if (match === '%%') return match;
+ index++;
+ var formatter = exports.formatters[format];
+ if ('function' === typeof formatter) {
+ var val = args[index];
+ match = formatter.call(self, val);
+
+ // now we need to remove `args[index]` since it's inlined in the `format`
+ args.splice(index, 1);
+ index--;
+ }
+ return match;
+ });
+
+ // apply env-specific formatting (colors, etc.)
+ exports.formatArgs.call(self, args);
+
+ var logFn = debug.log || exports.log || console.log.bind(console);
+ logFn.apply(self, args);
+ }
+
+ debug.namespace = namespace;
+ debug.enabled = exports.enabled(namespace);
+ debug.useColors = exports.useColors();
+ debug.color = selectColor(namespace);
+
+ // env-specific initialization logic for debug instances
+ if ('function' === typeof exports.init) {
+ exports.init(debug);
+ }
+
+ return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+ exports.save(namespaces);
+
+ exports.names = [];
+ exports.skips = [];
+
+ var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+ var len = split.length;
+
+ for (var i = 0; i < len; i++) {
+ if (!split[i]) continue; // ignore empty strings
+ namespaces = split[i].replace(/\*/g, '.*?');
+ if (namespaces[0] === '-') {
+ exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+ } else {
+ exports.names.push(new RegExp('^' + namespaces + '$'));
+ }
+ }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+ exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+ var i, len;
+ for (i = 0, len = exports.skips.length; i < len; i++) {
+ if (exports.skips[i].test(name)) {
+ return false;
+ }
+ }
+ for (i = 0, len = exports.names.length; i < len; i++) {
+ if (exports.names[i].test(name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+ if (val instanceof Error) return val.stack || val.message;
+ return val;
+}
diff --git a/node_modules/debug/src/index.js b/node_modules/debug/src/index.js
index bf4c57f..e12cf4d 100644
--- a/node_modules/debug/src/index.js
+++ b/node_modules/debug/src/index.js
@@ -1,10 +1,10 @@
/**
- * Detect Electron renderer / nwjs process, which is node, but we should
+ * Detect Electron renderer process, which is node, but we should
* treat as a browser.
*/
-if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
- module.exports = require('./browser.js');
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+ module.exports = require('./browser.js');
} else {
- module.exports = require('./node.js');
+ module.exports = require('./node.js');
}
diff --git a/node_modules/debug/src/inspector-log.js b/node_modules/debug/src/inspector-log.js
new file mode 100644
index 0000000..60ea6c0
--- /dev/null
+++ b/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+ const stdout = console._stdout;
+ console._stdout = nullStream;
+ console.log.apply(console, arguments);
+ console._stdout = stdout;
+}
diff --git a/node_modules/debug/src/node.js b/node_modules/debug/src/node.js
index 715560a..b15109c 100644
--- a/node_modules/debug/src/node.js
+++ b/node_modules/debug/src/node.js
@@ -2,23 +2,22 @@
* Module dependencies.
*/
-const tty = require('tty');
-const util = require('util');
+var tty = require('tty');
+var util = require('util');
/**
* This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
*/
+exports = module.exports = require('./debug');
exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
-exports.destroy = util.deprecate(
- () => {},
- 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
-);
/**
* Colors.
@@ -26,138 +25,80 @@ exports.destroy = util.deprecate(
exports.colors = [6, 2, 3, 4, 5, 1];
-try {
- // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
- // eslint-disable-next-line import/no-extraneous-dependencies
- const supportsColor = require('supports-color');
-
- if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
- exports.colors = [
- 20,
- 21,
- 26,
- 27,
- 32,
- 33,
- 38,
- 39,
- 40,
- 41,
- 42,
- 43,
- 44,
- 45,
- 56,
- 57,
- 62,
- 63,
- 68,
- 69,
- 74,
- 75,
- 76,
- 77,
- 78,
- 79,
- 80,
- 81,
- 92,
- 93,
- 98,
- 99,
- 112,
- 113,
- 128,
- 129,
- 134,
- 135,
- 148,
- 149,
- 160,
- 161,
- 162,
- 163,
- 164,
- 165,
- 166,
- 167,
- 168,
- 169,
- 170,
- 171,
- 172,
- 173,
- 178,
- 179,
- 184,
- 185,
- 196,
- 197,
- 198,
- 199,
- 200,
- 201,
- 202,
- 203,
- 204,
- 205,
- 206,
- 207,
- 208,
- 209,
- 214,
- 215,
- 220,
- 221
- ];
- }
-} catch (error) {
- // Swallow - we only care if `supports-color` is available; it doesn't have to be.
-}
-
/**
* Build up the default `inspectOpts` object from the environment variables.
*
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
*/
-exports.inspectOpts = Object.keys(process.env).filter(key => {
- return /^debug_/i.test(key);
-}).reduce((obj, key) => {
- // Camel-case
- const prop = key
- .substring(6)
- .toLowerCase()
- .replace(/_([a-z])/g, (_, k) => {
- return k.toUpperCase();
- });
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+ return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+ // camel-case
+ var prop = key
+ .substring(6)
+ .toLowerCase()
+ .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
- // Coerce string value into JS value
- let val = process.env[key];
- if (/^(yes|on|true|enabled)$/i.test(val)) {
- val = true;
- } else if (/^(no|off|false|disabled)$/i.test(val)) {
- val = false;
- } else if (val === 'null') {
- val = null;
- } else {
- val = Number(val);
- }
+ // coerce string value into JS value
+ var val = process.env[key];
+ if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+ else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+ else if (val === 'null') val = null;
+ else val = Number(val);
- obj[prop] = val;
- return obj;
+ obj[prop] = val;
+ return obj;
}, {});
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ * $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+ util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+ 2 === fd ? process.stderr :
+ createWritableStdioStream(fd);
+
/**
* Is stdout a TTY? Colored output is enabled when `true`.
*/
function useColors() {
- return 'colors' in exports.inspectOpts ?
- Boolean(exports.inspectOpts.colors) :
- tty.isatty(process.stderr.fd);
+ return 'colors' in exports.inspectOpts
+ ? Boolean(exports.inspectOpts.colors)
+ : tty.isatty(fd);
}
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts)
+ .split('\n').map(function(str) {
+ return str.trim()
+ }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts);
+};
+
/**
* Adds ANSI color escape codes if enabled.
*
@@ -165,33 +106,27 @@ function useColors() {
*/
function formatArgs(args) {
- const {namespace: name, useColors} = this;
+ var name = this.namespace;
+ var useColors = this.useColors;
- if (useColors) {
- const c = this.color;
- const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
- const prefix = ` ${colorCode};1m${name} \u001B[0m`;
+ if (useColors) {
+ var c = this.color;
+ var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
- args[0] = prefix + args[0].split('\n').join('\n' + prefix);
- args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
- } else {
- args[0] = getDate() + name + ' ' + args[0];
- }
-}
-
-function getDate() {
- if (exports.inspectOpts.hideDate) {
- return '';
- }
- return new Date().toISOString() + ' ';
+ args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+ args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+ } else {
+ args[0] = new Date().toUTCString()
+ + ' ' + name + ' ' + args[0];
+ }
}
/**
- * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr.
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
*/
-function log(...args) {
- return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n');
+function log() {
+ return stream.write(util.format.apply(util, arguments) + '\n');
}
/**
@@ -200,14 +135,15 @@ function log(...args) {
* @param {String} namespaces
* @api private
*/
+
function save(namespaces) {
- if (namespaces) {
- process.env.DEBUG = namespaces;
- } else {
- // If you set a process.env field to null or undefined, it gets cast to the
- // string 'null' or 'undefined'. Just delete instead.
- delete process.env.DEBUG;
- }
+ if (null == namespaces) {
+ // If you set a process.env field to null or undefined, it gets cast to the
+ // string 'null' or 'undefined'. Just delete instead.
+ delete process.env.DEBUG;
+ } else {
+ process.env.DEBUG = namespaces;
+ }
}
/**
@@ -218,7 +154,75 @@ function save(namespaces) {
*/
function load() {
- return process.env.DEBUG;
+ return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+ var stream;
+ var tty_wrap = process.binding('tty_wrap');
+
+ // Note stream._type is used for test-module-load-list.js
+
+ switch (tty_wrap.guessHandleType(fd)) {
+ case 'TTY':
+ stream = new tty.WriteStream(fd);
+ stream._type = 'tty';
+
+ // Hack to have stream not keep the event loop alive.
+ // See https://github.com/joyent/node/issues/1726
+ if (stream._handle && stream._handle.unref) {
+ stream._handle.unref();
+ }
+ break;
+
+ case 'FILE':
+ var fs = require('fs');
+ stream = new fs.SyncWriteStream(fd, { autoClose: false });
+ stream._type = 'fs';
+ break;
+
+ case 'PIPE':
+ case 'TCP':
+ var net = require('net');
+ stream = new net.Socket({
+ fd: fd,
+ readable: false,
+ writable: true
+ });
+
+ // FIXME Should probably have an option in net.Socket to create a
+ // stream from an existing fd which is writable only. But for now
+ // we'll just add this hack and set the `readable` member to false.
+ // Test: ./node test/fixtures/echo.js < /etc/passwd
+ stream.readable = false;
+ stream.read = null;
+ stream._type = 'pipe';
+
+ // FIXME Hack to have stream not keep the event loop alive.
+ // See https://github.com/joyent/node/issues/1726
+ if (stream._handle && stream._handle.unref) {
+ stream._handle.unref();
+ }
+ break;
+
+ default:
+ // Probably an error on in uv_guess_handle()
+ throw new Error('Implement me. Unknown stream file type!');
+ }
+
+ // For supporting legacy API we put the FD here.
+ stream.fd = fd;
+
+ stream._isStdio = true;
+
+ return stream;
}
/**
@@ -228,36 +232,17 @@ function load() {
* differently for a particular `debug` instance.
*/
-function init(debug) {
- debug.inspectOpts = {};
+function init (debug) {
+ debug.inspectOpts = {};
- const keys = Object.keys(exports.inspectOpts);
- for (let i = 0; i < keys.length; i++) {
- debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
- }
+ var keys = Object.keys(exports.inspectOpts);
+ for (var i = 0; i < keys.length; i++) {
+ debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+ }
}
-module.exports = require('./common')(exports);
-
-const {formatters} = module.exports;
-
/**
- * Map %o to `util.inspect()`, all on a single line.
+ * Enable namespaces listed in `process.env.DEBUG` initially.
*/
-formatters.o = function (v) {
- this.inspectOpts.colors = this.useColors;
- return util.inspect(v, this.inspectOpts)
- .split('\n')
- .map(str => str.trim())
- .join(' ');
-};
-
-/**
- * Map %O to `util.inspect()`, allowing multiple lines if needed.
- */
-
-formatters.O = function (v) {
- this.inspectOpts.colors = this.useColors;
- return util.inspect(v, this.inspectOpts);
-};
+exports.enable(load());
diff --git a/node_modules/decimal.js/LICENCE.md b/node_modules/decimal.js/LICENCE.md
deleted file mode 100644
index e62dbae..0000000
--- a/node_modules/decimal.js/LICENCE.md
+++ /dev/null
@@ -1,23 +0,0 @@
-The MIT Licence.
-
-Copyright (c) 2025 Michael Mclaughlin
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-'Software'), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
diff --git a/node_modules/decimal.js/README.md b/node_modules/decimal.js/README.md
deleted file mode 100644
index f59a9cf..0000000
--- a/node_modules/decimal.js/README.md
+++ /dev/null
@@ -1,246 +0,0 @@
-
-
-An arbitrary-precision Decimal type for JavaScript.
-
-[](https://www.npmjs.com/package/decimal.js)
-[](https://www.npmjs.com/package/decimal.js)
-[](https://cdnjs.com/libraries/decimal.js)
-[](https://www.jsdelivr.com/package/npm/decimal.js)
-
-
-
-## Features
-
- - Integers and floats
- - Simple but full-featured API
- - Replicates many of the methods of JavaScript's `Number.prototype` and `Math` objects
- - Also handles hexadecimal, binary and octal values
- - Faster, smaller, and perhaps easier to use than JavaScript versions of Java's BigDecimal
- - No dependencies
- - Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only
- - Comprehensive [documentation](https://mikemcl.github.io/decimal.js/) and test set
- - Used under the hood by [math.js](https://github.com/josdejong/mathjs)
- - Includes a TypeScript declaration file: *decimal.d.ts*
-
-
-
-The library is similar to [bignumber.js](https://github.com/MikeMcl/bignumber.js/), but here
-precision is specified in terms of significant digits rather than decimal places, and all
-calculations are rounded to the precision (similar to Python's decimal module) rather than just
-those involving division.
-
-This library also adds the trigonometric functions, among others, and supports non-integer powers,
-which makes it a significantly larger library than *bignumber.js* and the even smaller
-[big.js](https://github.com/MikeMcl/big.js/).
-
-For a lighter version of this library without the trigonometric functions see
-[decimal.js-light](https://github.com/MikeMcl/decimal.js-light/).
-
-## Load
-
-The library is the single JavaScript file *decimal.js* or ES module *decimal.mjs*.
-
-Browser:
-
-```html
-
-
-
-```
-
-[Node.js](https://nodejs.org):
-
-```bash
-npm install decimal.js
-```
-```js
-const Decimal = require('decimal.js');
-
-import Decimal from 'decimal.js';
-
-import {Decimal} from 'decimal.js';
-```
-
-## Use
-
-*In all examples below, semicolons and `toString` calls are not shown.
-If a commented-out value is in quotes it means `toString` has been called on the preceding expression.*
-
-The library exports a single constructor function, `Decimal`, which expects a single argument that is a number, string or Decimal instance.
-
-```js
-x = new Decimal(123.4567)
-y = new Decimal('123456.7e-3')
-z = new Decimal(x)
-x.equals(y) && y.equals(z) && x.equals(z) // true
-```
-
-If using values with more than a few digits, it is recommended to pass strings rather than numbers to avoid a potential loss of precision.
-
-```js
-// Precision loss from using numeric literals with more than 15 significant digits.
-new Decimal(1.0000000000000001) // '1'
-new Decimal(88259496234518.57) // '88259496234518.56'
-new Decimal(99999999999999999999) // '100000000000000000000'
-
-// Precision loss from using numeric literals outside the range of Number values.
-new Decimal(2e+308) // 'Infinity'
-new Decimal(1e-324) // '0'
-
-// Precision loss from the unexpected result of arithmetic with Number values.
-new Decimal(0.7 + 0.1) // '0.7999999999999999'
-```
-
-As with JavaScript numbers, strings can contain underscores as separators to improve readability.
-
-```js
-x = new Decimal('2_147_483_647')
-```
-
-String values in binary, hexadecimal or octal notation are also accepted if the appropriate prefix is included.
-
-```js
-x = new Decimal('0xff.f') // '255.9375'
-y = new Decimal('0b10101100') // '172'
-z = x.plus(y) // '427.9375'
-
-z.toBinary() // '0b110101011.1111'
-z.toBinary(13) // '0b1.101010111111p+8'
-
-// Using binary exponential notation to create a Decimal with the value of `Number.MAX_VALUE`.
-x = new Decimal('0b1.1111111111111111111111111111111111111111111111111111p+1023')
-// '1.7976931348623157081e+308'
-```
-
-Decimal instances are immutable in the sense that they are not changed by their methods.
-
-```js
-0.3 - 0.1 // 0.19999999999999998
-x = new Decimal(0.3)
-x.minus(0.1) // '0.2'
-x // '0.3'
-```
-
-The methods that return a Decimal can be chained.
-
-```js
-x.dividedBy(y).plus(z).times(9).floor()
-x.times('1.23456780123456789e+9').plus(9876.5432321).dividedBy('4444562598.111772').ceil()
-```
-
-Many method names have a shorter alias.
-
-```js
-x.squareRoot().dividedBy(y).toPower(3).equals(x.sqrt().div(y).pow(3)) // true
-x.comparedTo(y.modulo(z).negated() === x.cmp(y.mod(z).neg()) // true
-```
-
-Most of the methods of JavaScript's `Number.prototype` and `Math` objects are replicated.
-
-```js
-x = new Decimal(255.5)
-x.toExponential(5) // '2.55500e+2'
-x.toFixed(5) // '255.50000'
-x.toPrecision(5) // '255.50'
-
-Decimal.sqrt('6.98372465832e+9823') // '8.3568682281821340204e+4911'
-Decimal.pow(2, 0.0979843) // '1.0702770511687781839'
-
-// Using `toFixed()` to avoid exponential notation:
-x = new Decimal('0.0000001')
-x.toString() // '1e-7'
-x.toFixed() // '0.0000001'
-```
-
-And there are `isNaN` and `isFinite` methods, as `NaN` and `Infinity` are valid `Decimal` values.
-
-```js
-x = new Decimal(NaN) // 'NaN'
-y = new Decimal(Infinity) // 'Infinity'
-x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite() // true
-```
-
-There is also a `toFraction` method with an optional *maximum denominator* argument.
-
-```js
-z = new Decimal(355)
-pi = z.dividedBy(113) // '3.1415929204'
-pi.toFraction() // [ '7853982301', '2500000000' ]
-pi.toFraction(1000) // [ '355', '113' ]
-```
-
-All calculations are rounded according to the number of significant digits and rounding mode specified
-by the `precision` and `rounding` properties of the Decimal constructor.
-
-For advanced usage, multiple Decimal constructors can be created, each with their own independent
-configuration which applies to all Decimal numbers created from it.
-
-```js
-// Set the precision and rounding of the default Decimal constructor
-Decimal.set({ precision: 5, rounding: 4 })
-
-// Create another Decimal constructor, optionally passing in a configuration object
-Dec = Decimal.clone({ precision: 9, rounding: 1 })
-
-x = new Decimal(5)
-y = new Dec(5)
-
-x.div(3) // '1.6667'
-y.div(3) // '1.66666666'
-```
-
-The value of a Decimal is stored in a floating point format in terms of its digits, exponent and sign, but these properties should be considered read-only.
-
-```js
-x = new Decimal(-12345.67);
-x.d // [ 12345, 6700000 ] digits (base 10000000)
-x.e // 4 exponent (base 10)
-x.s // -1 sign
-```
-
-For further information see the [API](http://mikemcl.github.io/decimal.js/) reference in the *doc* directory.
-
-## Test
-
-To run the tests using Node.js from the root directory:
-
-```bash
-npm test
-```
-
-Each separate test module can also be executed individually, for example:
-
-```bash
-node test/modules/toFraction
-```
-
-To run the tests in a browser, open *test/test.html*.
-
-## Minify
-
-Two minification examples:
-
-Using [uglify-js](https://github.com/mishoo/UglifyJS) to minify the *decimal.js* file:
-
-```bash
-npm install uglify-js -g
-uglifyjs decimal.js --source-map url=decimal.min.js.map -c -m -o decimal.min.js
-```
-
-Using [terser](https://github.com/terser/terser) to minify the ES module version, *decimal.mjs*:
-
-```bash
-npm install terser -g
-terser decimal.mjs --source-map url=decimal.min.mjs.map -c -m --toplevel -o decimal.min.mjs
-```
-
-```js
-import Decimal from './decimal.min.mjs';
-```
-
-## Licence
-
-[The MIT Licence](LICENCE.md)
diff --git a/node_modules/decimal.js/decimal.d.ts b/node_modules/decimal.js/decimal.d.ts
deleted file mode 100644
index 526a896..0000000
--- a/node_modules/decimal.js/decimal.d.ts
+++ /dev/null
@@ -1,301 +0,0 @@
-// Type definitions for decimal.js >=7.0.0
-// Project: https://github.com/MikeMcl/decimal.js
-// Definitions by: Michael Mclaughlin
-// Definitions: https://github.com/MikeMcl/decimal.js
-//
-// Documentation: http://mikemcl.github.io/decimal.js/
-//
-// Exports:
-//
-// class Decimal (default export)
-// type Decimal.Constructor
-// type Decimal.Instance
-// type Decimal.Modulo
-// type Decimal.Rounding
-// type Decimal.Value
-// interface Decimal.Config
-//
-// Example (alternative syntax commented-out):
-//
-// import {Decimal} from "decimal.js"
-// //import Decimal from "decimal.js"
-//
-// let r: Decimal.Rounding = Decimal.ROUND_UP;
-// let c: Decimal.Configuration = {precision: 4, rounding: r};
-// Decimal.set(c);
-// let v: Decimal.Value = '12345.6789';
-// let d: Decimal = new Decimal(v);
-// //let d: Decimal.Instance = new Decimal(v);
-//
-// The use of compiler option `--strictNullChecks` is recommended.
-
-export default Decimal;
-
-export namespace Decimal {
- export type Constructor = typeof Decimal;
- export type Instance = Decimal;
- export type Rounding = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
- export type Modulo = Rounding | 9;
- export type Value = string | number | bigint | Decimal;
-
- // http://mikemcl.github.io/decimal.js/#constructor-properties
- export interface Config {
- precision?: number;
- rounding?: Rounding;
- toExpNeg?: number;
- toExpPos?: number;
- minE?: number;
- maxE?: number;
- crypto?: boolean;
- modulo?: Modulo;
- defaults?: boolean;
- }
-}
-
-export declare class Decimal {
- readonly d: number[];
- readonly e: number;
- readonly s: number;
-
- constructor(n: Decimal.Value);
-
- absoluteValue(): Decimal;
- abs(): Decimal;
-
- ceil(): Decimal;
-
- clampedTo(min: Decimal.Value, max: Decimal.Value): Decimal;
- clamp(min: Decimal.Value, max: Decimal.Value): Decimal;
-
- comparedTo(n: Decimal.Value): number;
- cmp(n: Decimal.Value): number;
-
- cosine(): Decimal;
- cos(): Decimal;
-
- cubeRoot(): Decimal;
- cbrt(): Decimal;
-
- decimalPlaces(): number;
- dp(): number;
-
- dividedBy(n: Decimal.Value): Decimal;
- div(n: Decimal.Value): Decimal;
-
- dividedToIntegerBy(n: Decimal.Value): Decimal;
- divToInt(n: Decimal.Value): Decimal;
-
- equals(n: Decimal.Value): boolean;
- eq(n: Decimal.Value): boolean;
-
- floor(): Decimal;
-
- greaterThan(n: Decimal.Value): boolean;
- gt(n: Decimal.Value): boolean;
-
- greaterThanOrEqualTo(n: Decimal.Value): boolean;
- gte(n: Decimal.Value): boolean;
-
- hyperbolicCosine(): Decimal;
- cosh(): Decimal;
-
- hyperbolicSine(): Decimal;
- sinh(): Decimal;
-
- hyperbolicTangent(): Decimal;
- tanh(): Decimal;
-
- inverseCosine(): Decimal;
- acos(): Decimal;
-
- inverseHyperbolicCosine(): Decimal;
- acosh(): Decimal;
-
- inverseHyperbolicSine(): Decimal;
- asinh(): Decimal;
-
- inverseHyperbolicTangent(): Decimal;
- atanh(): Decimal;
-
- inverseSine(): Decimal;
- asin(): Decimal;
-
- inverseTangent(): Decimal;
- atan(): Decimal;
-
- isFinite(): boolean;
-
- isInteger(): boolean;
- isInt(): boolean;
-
- isNaN(): boolean;
-
- isNegative(): boolean;
- isNeg(): boolean;
-
- isPositive(): boolean;
- isPos(): boolean;
-
- isZero(): boolean;
-
- lessThan(n: Decimal.Value): boolean;
- lt(n: Decimal.Value): boolean;
-
- lessThanOrEqualTo(n: Decimal.Value): boolean;
- lte(n: Decimal.Value): boolean;
-
- logarithm(n?: Decimal.Value): Decimal;
- log(n?: Decimal.Value): Decimal;
-
- minus(n: Decimal.Value): Decimal;
- sub(n: Decimal.Value): Decimal;
-
- modulo(n: Decimal.Value): Decimal;
- mod(n: Decimal.Value): Decimal;
-
- naturalExponential(): Decimal;
- exp(): Decimal;
-
- naturalLogarithm(): Decimal;
- ln(): Decimal;
-
- negated(): Decimal;
- neg(): Decimal;
-
- plus(n: Decimal.Value): Decimal;
- add(n: Decimal.Value): Decimal;
-
- precision(includeZeros?: boolean): number;
- sd(includeZeros?: boolean): number;
-
- round(): Decimal;
-
- sine() : Decimal;
- sin() : Decimal;
-
- squareRoot(): Decimal;
- sqrt(): Decimal;
-
- tangent() : Decimal;
- tan() : Decimal;
-
- times(n: Decimal.Value): Decimal;
- mul(n: Decimal.Value) : Decimal;
-
- toBinary(significantDigits?: number): string;
- toBinary(significantDigits: number, rounding: Decimal.Rounding): string;
-
- toDecimalPlaces(decimalPlaces?: number): Decimal;
- toDecimalPlaces(decimalPlaces: number, rounding: Decimal.Rounding): Decimal;
- toDP(decimalPlaces?: number): Decimal;
- toDP(decimalPlaces: number, rounding: Decimal.Rounding): Decimal;
-
- toExponential(decimalPlaces?: number): string;
- toExponential(decimalPlaces: number, rounding: Decimal.Rounding): string;
-
- toFixed(decimalPlaces?: number): string;
- toFixed(decimalPlaces: number, rounding: Decimal.Rounding): string;
-
- toFraction(max_denominator?: Decimal.Value): Decimal[];
-
- toHexadecimal(significantDigits?: number): string;
- toHexadecimal(significantDigits: number, rounding: Decimal.Rounding): string;
- toHex(significantDigits?: number): string;
- toHex(significantDigits: number, rounding?: Decimal.Rounding): string;
-
- toJSON(): string;
-
- toNearest(n: Decimal.Value, rounding?: Decimal.Rounding): Decimal;
-
- toNumber(): number;
-
- toOctal(significantDigits?: number): string;
- toOctal(significantDigits: number, rounding: Decimal.Rounding): string;
-
- toPower(n: Decimal.Value): Decimal;
- pow(n: Decimal.Value): Decimal;
-
- toPrecision(significantDigits?: number): string;
- toPrecision(significantDigits: number, rounding: Decimal.Rounding): string;
-
- toSignificantDigits(significantDigits?: number): Decimal;
- toSignificantDigits(significantDigits: number, rounding: Decimal.Rounding): Decimal;
- toSD(significantDigits?: number): Decimal;
- toSD(significantDigits: number, rounding: Decimal.Rounding): Decimal;
-
- toString(): string;
-
- truncated(): Decimal;
- trunc(): Decimal;
-
- valueOf(): string;
-
- static abs(n: Decimal.Value): Decimal;
- static acos(n: Decimal.Value): Decimal;
- static acosh(n: Decimal.Value): Decimal;
- static add(x: Decimal.Value, y: Decimal.Value): Decimal;
- static asin(n: Decimal.Value): Decimal;
- static asinh(n: Decimal.Value): Decimal;
- static atan(n: Decimal.Value): Decimal;
- static atanh(n: Decimal.Value): Decimal;
- static atan2(y: Decimal.Value, x: Decimal.Value): Decimal;
- static cbrt(n: Decimal.Value): Decimal;
- static ceil(n: Decimal.Value): Decimal;
- static clamp(n: Decimal.Value, min: Decimal.Value, max: Decimal.Value): Decimal;
- static clone(object?: Decimal.Config): Decimal.Constructor;
- static config(object: Decimal.Config): Decimal.Constructor;
- static cos(n: Decimal.Value): Decimal;
- static cosh(n: Decimal.Value): Decimal;
- static div(x: Decimal.Value, y: Decimal.Value): Decimal;
- static exp(n: Decimal.Value): Decimal;
- static floor(n: Decimal.Value): Decimal;
- static hypot(...n: Decimal.Value[]): Decimal;
- static isDecimal(object: any): object is Decimal;
- static ln(n: Decimal.Value): Decimal;
- static log(n: Decimal.Value, base?: Decimal.Value): Decimal;
- static log2(n: Decimal.Value): Decimal;
- static log10(n: Decimal.Value): Decimal;
- static max(...n: Decimal.Value[]): Decimal;
- static min(...n: Decimal.Value[]): Decimal;
- static mod(x: Decimal.Value, y: Decimal.Value): Decimal;
- static mul(x: Decimal.Value, y: Decimal.Value): Decimal;
- static noConflict(): Decimal.Constructor; // Browser only
- static pow(base: Decimal.Value, exponent: Decimal.Value): Decimal;
- static random(significantDigits?: number): Decimal;
- static round(n: Decimal.Value): Decimal;
- static set(object: Decimal.Config): Decimal.Constructor;
- static sign(n: Decimal.Value): number;
- static sin(n: Decimal.Value): Decimal;
- static sinh(n: Decimal.Value): Decimal;
- static sqrt(n: Decimal.Value): Decimal;
- static sub(x: Decimal.Value, y: Decimal.Value): Decimal;
- static sum(...n: Decimal.Value[]): Decimal;
- static tan(n: Decimal.Value): Decimal;
- static tanh(n: Decimal.Value): Decimal;
- static trunc(n: Decimal.Value): Decimal;
-
- static readonly default?: Decimal.Constructor;
- static readonly Decimal?: Decimal.Constructor;
-
- static readonly precision: number;
- static readonly rounding: Decimal.Rounding;
- static readonly toExpNeg: number;
- static readonly toExpPos: number;
- static readonly minE: number;
- static readonly maxE: number;
- static readonly crypto: boolean;
- static readonly modulo: Decimal.Modulo;
-
- static readonly ROUND_UP: 0;
- static readonly ROUND_DOWN: 1;
- static readonly ROUND_CEIL: 2;
- static readonly ROUND_FLOOR: 3;
- static readonly ROUND_HALF_UP: 4;
- static readonly ROUND_HALF_DOWN: 5;
- static readonly ROUND_HALF_EVEN: 6;
- static readonly ROUND_HALF_CEIL: 7;
- static readonly ROUND_HALF_FLOOR: 8;
- static readonly EUCLID: 9;
-}
-
-export declare function Decimal(n: Decimal.Value): Decimal;
diff --git a/node_modules/decimal.js/decimal.js b/node_modules/decimal.js/decimal.js
deleted file mode 100644
index f7ecafb..0000000
--- a/node_modules/decimal.js/decimal.js
+++ /dev/null
@@ -1,4951 +0,0 @@
-;(function (globalScope) {
- 'use strict';
-
-
- /*!
- * decimal.js v10.6.0
- * An arbitrary-precision Decimal type for JavaScript.
- * https://github.com/MikeMcl/decimal.js
- * Copyright (c) 2025 Michael Mclaughlin
- * MIT Licence
- */
-
-
- // ----------------------------------- EDITABLE DEFAULTS ------------------------------------ //
-
-
- // The maximum exponent magnitude.
- // The limit on the value of `toExpNeg`, `toExpPos`, `minE` and `maxE`.
- var EXP_LIMIT = 9e15, // 0 to 9e15
-
- // The limit on the value of `precision`, and on the value of the first argument to
- // `toDecimalPlaces`, `toExponential`, `toFixed`, `toPrecision` and `toSignificantDigits`.
- MAX_DIGITS = 1e9, // 0 to 1e9
-
- // Base conversion alphabet.
- NUMERALS = '0123456789abcdef',
-
- // The natural logarithm of 10 (1025 digits).
- LN10 = '2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220114804663715659121373450747856947683463616792101806445070648000277502684916746550586856935673420670581136429224554405758925724208241314695689016758940256776311356919292033376587141660230105703089634572075440370847469940168269282808481184289314848524948644871927809676271275775397027668605952496716674183485704422507197965004714951050492214776567636938662976979522110718264549734772662425709429322582798502585509785265383207606726317164309505995087807523710333101197857547331541421808427543863591778117054309827482385045648019095610299291824318237525357709750539565187697510374970888692180205189339507238539205144634197265287286965110862571492198849978748873771345686209167058',
-
- // Pi (1025 digits).
- PI = '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632789',
-
-
- // The initial configuration properties of the Decimal constructor.
- DEFAULTS = {
-
- // These values must be integers within the stated ranges (inclusive).
- // Most of these values can be changed at run-time using the `Decimal.config` method.
-
- // The maximum number of significant digits of the result of a calculation or base conversion.
- // E.g. `Decimal.config({ precision: 20 });`
- precision: 20, // 1 to MAX_DIGITS
-
- // The rounding mode used when rounding to `precision`.
- //
- // ROUND_UP 0 Away from zero.
- // ROUND_DOWN 1 Towards zero.
- // ROUND_CEIL 2 Towards +Infinity.
- // ROUND_FLOOR 3 Towards -Infinity.
- // ROUND_HALF_UP 4 Towards nearest neighbour. If equidistant, up.
- // ROUND_HALF_DOWN 5 Towards nearest neighbour. If equidistant, down.
- // ROUND_HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour.
- // ROUND_HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity.
- // ROUND_HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.
- //
- // E.g.
- // `Decimal.rounding = 4;`
- // `Decimal.rounding = Decimal.ROUND_HALF_UP;`
- rounding: 4, // 0 to 8
-
- // The modulo mode used when calculating the modulus: a mod n.
- // The quotient (q = a / n) is calculated according to the corresponding rounding mode.
- // The remainder (r) is calculated as: r = a - n * q.
- //
- // UP 0 The remainder is positive if the dividend is negative, else is negative.
- // DOWN 1 The remainder has the same sign as the dividend (JavaScript %).
- // FLOOR 3 The remainder has the same sign as the divisor (Python %).
- // HALF_EVEN 6 The IEEE 754 remainder function.
- // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). Always positive.
- //
- // Truncated division (1), floored division (3), the IEEE 754 remainder (6), and Euclidian
- // division (9) are commonly used for the modulus operation. The other rounding modes can also
- // be used, but they may not give useful results.
- modulo: 1, // 0 to 9
-
- // The exponent value at and beneath which `toString` returns exponential notation.
- // JavaScript numbers: -7
- toExpNeg: -7, // 0 to -EXP_LIMIT
-
- // The exponent value at and above which `toString` returns exponential notation.
- // JavaScript numbers: 21
- toExpPos: 21, // 0 to EXP_LIMIT
-
- // The minimum exponent value, beneath which underflow to zero occurs.
- // JavaScript numbers: -324 (5e-324)
- minE: -EXP_LIMIT, // -1 to -EXP_LIMIT
-
- // The maximum exponent value, above which overflow to Infinity occurs.
- // JavaScript numbers: 308 (1.7976931348623157e+308)
- maxE: EXP_LIMIT, // 1 to EXP_LIMIT
-
- // Whether to use cryptographically-secure random number generation, if available.
- crypto: false // true/false
- },
-
-
- // ----------------------------------- END OF EDITABLE DEFAULTS ------------------------------- //
-
-
- Decimal, inexact, noConflict, quadrant,
- external = true,
-
- decimalError = '[DecimalError] ',
- invalidArgument = decimalError + 'Invalid argument: ',
- precisionLimitExceeded = decimalError + 'Precision limit exceeded',
- cryptoUnavailable = decimalError + 'crypto unavailable',
- tag = '[object Decimal]',
-
- mathfloor = Math.floor,
- mathpow = Math.pow,
-
- isBinary = /^0b([01]+(\.[01]*)?|\.[01]+)(p[+-]?\d+)?$/i,
- isHex = /^0x([0-9a-f]+(\.[0-9a-f]*)?|\.[0-9a-f]+)(p[+-]?\d+)?$/i,
- isOctal = /^0o([0-7]+(\.[0-7]*)?|\.[0-7]+)(p[+-]?\d+)?$/i,
- isDecimal = /^(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,
-
- BASE = 1e7,
- LOG_BASE = 7,
- MAX_SAFE_INTEGER = 9007199254740991,
-
- LN10_PRECISION = LN10.length - 1,
- PI_PRECISION = PI.length - 1,
-
- // Decimal.prototype object
- P = { toStringTag: tag };
-
-
- // Decimal prototype methods
-
-
- /*
- * absoluteValue abs
- * ceil
- * clampedTo clamp
- * comparedTo cmp
- * cosine cos
- * cubeRoot cbrt
- * decimalPlaces dp
- * dividedBy div
- * dividedToIntegerBy divToInt
- * equals eq
- * floor
- * greaterThan gt
- * greaterThanOrEqualTo gte
- * hyperbolicCosine cosh
- * hyperbolicSine sinh
- * hyperbolicTangent tanh
- * inverseCosine acos
- * inverseHyperbolicCosine acosh
- * inverseHyperbolicSine asinh
- * inverseHyperbolicTangent atanh
- * inverseSine asin
- * inverseTangent atan
- * isFinite
- * isInteger isInt
- * isNaN
- * isNegative isNeg
- * isPositive isPos
- * isZero
- * lessThan lt
- * lessThanOrEqualTo lte
- * logarithm log
- * [maximum] [max]
- * [minimum] [min]
- * minus sub
- * modulo mod
- * naturalExponential exp
- * naturalLogarithm ln
- * negated neg
- * plus add
- * precision sd
- * round
- * sine sin
- * squareRoot sqrt
- * tangent tan
- * times mul
- * toBinary
- * toDecimalPlaces toDP
- * toExponential
- * toFixed
- * toFraction
- * toHexadecimal toHex
- * toNearest
- * toNumber
- * toOctal
- * toPower pow
- * toPrecision
- * toSignificantDigits toSD
- * toString
- * truncated trunc
- * valueOf toJSON
- */
-
-
- /*
- * Return a new Decimal whose value is the absolute value of this Decimal.
- *
- */
- P.absoluteValue = P.abs = function () {
- var x = new this.constructor(this);
- if (x.s < 0) x.s = 1;
- return finalise(x);
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the
- * direction of positive Infinity.
- *
- */
- P.ceil = function () {
- return finalise(new this.constructor(this), this.e + 1, 2);
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal clamped to the range
- * delineated by `min` and `max`.
- *
- * min {number|string|bigint|Decimal}
- * max {number|string|bigint|Decimal}
- *
- */
- P.clampedTo = P.clamp = function (min, max) {
- var k,
- x = this,
- Ctor = x.constructor;
- min = new Ctor(min);
- max = new Ctor(max);
- if (!min.s || !max.s) return new Ctor(NaN);
- if (min.gt(max)) throw Error(invalidArgument + max);
- k = x.cmp(min);
- return k < 0 ? min : x.cmp(max) > 0 ? max : new Ctor(x);
- };
-
-
- /*
- * Return
- * 1 if the value of this Decimal is greater than the value of `y`,
- * -1 if the value of this Decimal is less than the value of `y`,
- * 0 if they have the same value,
- * NaN if the value of either Decimal is NaN.
- *
- */
- P.comparedTo = P.cmp = function (y) {
- var i, j, xdL, ydL,
- x = this,
- xd = x.d,
- yd = (y = new x.constructor(y)).d,
- xs = x.s,
- ys = y.s;
-
- // Either NaN or ±Infinity?
- if (!xd || !yd) {
- return !xs || !ys ? NaN : xs !== ys ? xs : xd === yd ? 0 : !xd ^ xs < 0 ? 1 : -1;
- }
-
- // Either zero?
- if (!xd[0] || !yd[0]) return xd[0] ? xs : yd[0] ? -ys : 0;
-
- // Signs differ?
- if (xs !== ys) return xs;
-
- // Compare exponents.
- if (x.e !== y.e) return x.e > y.e ^ xs < 0 ? 1 : -1;
-
- xdL = xd.length;
- ydL = yd.length;
-
- // Compare digit by digit.
- for (i = 0, j = xdL < ydL ? xdL : ydL; i < j; ++i) {
- if (xd[i] !== yd[i]) return xd[i] > yd[i] ^ xs < 0 ? 1 : -1;
- }
-
- // Compare lengths.
- return xdL === ydL ? 0 : xdL > ydL ^ xs < 0 ? 1 : -1;
- };
-
-
- /*
- * Return a new Decimal whose value is the cosine of the value in radians of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-1, 1]
- *
- * cos(0) = 1
- * cos(-0) = 1
- * cos(Infinity) = NaN
- * cos(-Infinity) = NaN
- * cos(NaN) = NaN
- *
- */
- P.cosine = P.cos = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.d) return new Ctor(NaN);
-
- // cos(0) = cos(-0) = 1
- if (!x.d[0]) return new Ctor(1);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE;
- Ctor.rounding = 1;
-
- x = cosine(Ctor, toLessThanHalfPi(Ctor, x));
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(quadrant == 2 || quadrant == 3 ? x.neg() : x, pr, rm, true);
- };
-
-
- /*
- *
- * Return a new Decimal whose value is the cube root of the value of this Decimal, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * cbrt(0) = 0
- * cbrt(-0) = -0
- * cbrt(1) = 1
- * cbrt(-1) = -1
- * cbrt(N) = N
- * cbrt(-I) = -I
- * cbrt(I) = I
- *
- * Math.cbrt(x) = (x < 0 ? -Math.pow(-x, 1/3) : Math.pow(x, 1/3))
- *
- */
- P.cubeRoot = P.cbrt = function () {
- var e, m, n, r, rep, s, sd, t, t3, t3plusx,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite() || x.isZero()) return new Ctor(x);
- external = false;
-
- // Initial estimate.
- s = x.s * mathpow(x.s * x, 1 / 3);
-
- // Math.cbrt underflow/overflow?
- // Pass x to Math.pow as integer, then adjust the exponent of the result.
- if (!s || Math.abs(s) == 1 / 0) {
- n = digitsToString(x.d);
- e = x.e;
-
- // Adjust n exponent so it is a multiple of 3 away from x exponent.
- if (s = (e - n.length + 1) % 3) n += (s == 1 || s == -2 ? '0' : '00');
- s = mathpow(n, 1 / 3);
-
- // Rarely, e may be one less than the result exponent value.
- e = mathfloor((e + 1) / 3) - (e % 3 == (e < 0 ? -1 : 2));
-
- if (s == 1 / 0) {
- n = '5e' + e;
- } else {
- n = s.toExponential();
- n = n.slice(0, n.indexOf('e') + 1) + e;
- }
-
- r = new Ctor(n);
- r.s = x.s;
- } else {
- r = new Ctor(s.toString());
- }
-
- sd = (e = Ctor.precision) + 3;
-
- // Halley's method.
- // TODO? Compare Newton's method.
- for (;;) {
- t = r;
- t3 = t.times(t).times(t);
- t3plusx = t3.plus(x);
- r = divide(t3plusx.plus(x).times(t), t3plusx.plus(t3), sd + 2, 1);
-
- // TODO? Replace with for-loop and checkRoundingDigits.
- if (digitsToString(t.d).slice(0, sd) === (n = digitsToString(r.d)).slice(0, sd)) {
- n = n.slice(sd - 3, sd + 1);
-
- // The 4th rounding digit may be in error by -1 so if the 4 rounding digits are 9999 or 4999
- // , i.e. approaching a rounding boundary, continue the iteration.
- if (n == '9999' || !rep && n == '4999') {
-
- // On the first iteration only, check to see if rounding up gives the exact result as the
- // nines may infinitely repeat.
- if (!rep) {
- finalise(t, e + 1, 0);
-
- if (t.times(t).times(t).eq(x)) {
- r = t;
- break;
- }
- }
-
- sd += 4;
- rep = 1;
- } else {
-
- // If the rounding digits are null, 0{0,4} or 50{0,3}, check for an exact result.
- // If not, then there are further digits and m will be truthy.
- if (!+n || !+n.slice(1) && n.charAt(0) == '5') {
-
- // Truncate to the first rounding digit.
- finalise(r, e + 1, 1);
- m = !r.times(r).times(r).eq(x);
- }
-
- break;
- }
- }
- }
-
- external = true;
-
- return finalise(r, e, Ctor.rounding, m);
- };
-
-
- /*
- * Return the number of decimal places of the value of this Decimal.
- *
- */
- P.decimalPlaces = P.dp = function () {
- var w,
- d = this.d,
- n = NaN;
-
- if (d) {
- w = d.length - 1;
- n = (w - mathfloor(this.e / LOG_BASE)) * LOG_BASE;
-
- // Subtract the number of trailing zeros of the last word.
- w = d[w];
- if (w) for (; w % 10 == 0; w /= 10) n--;
- if (n < 0) n = 0;
- }
-
- return n;
- };
-
-
- /*
- * n / 0 = I
- * n / N = N
- * n / I = 0
- * 0 / n = 0
- * 0 / 0 = N
- * 0 / N = N
- * 0 / I = 0
- * N / n = N
- * N / 0 = N
- * N / N = N
- * N / I = N
- * I / n = I
- * I / 0 = I
- * I / N = N
- * I / I = N
- *
- * Return a new Decimal whose value is the value of this Decimal divided by `y`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- */
- P.dividedBy = P.div = function (y) {
- return divide(this, new this.constructor(y));
- };
-
-
- /*
- * Return a new Decimal whose value is the integer part of dividing the value of this Decimal
- * by the value of `y`, rounded to `precision` significant digits using rounding mode `rounding`.
- *
- */
- P.dividedToIntegerBy = P.divToInt = function (y) {
- var x = this,
- Ctor = x.constructor;
- return finalise(divide(x, new Ctor(y), 0, 1, 1), Ctor.precision, Ctor.rounding);
- };
-
-
- /*
- * Return true if the value of this Decimal is equal to the value of `y`, otherwise return false.
- *
- */
- P.equals = P.eq = function (y) {
- return this.cmp(y) === 0;
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the
- * direction of negative Infinity.
- *
- */
- P.floor = function () {
- return finalise(new this.constructor(this), this.e + 1, 3);
- };
-
-
- /*
- * Return true if the value of this Decimal is greater than the value of `y`, otherwise return
- * false.
- *
- */
- P.greaterThan = P.gt = function (y) {
- return this.cmp(y) > 0;
- };
-
-
- /*
- * Return true if the value of this Decimal is greater than or equal to the value of `y`,
- * otherwise return false.
- *
- */
- P.greaterThanOrEqualTo = P.gte = function (y) {
- var k = this.cmp(y);
- return k == 1 || k === 0;
- };
-
-
- /*
- * Return a new Decimal whose value is the hyperbolic cosine of the value in radians of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [1, Infinity]
- *
- * cosh(x) = 1 + x^2/2! + x^4/4! + x^6/6! + ...
- *
- * cosh(0) = 1
- * cosh(-0) = 1
- * cosh(Infinity) = Infinity
- * cosh(-Infinity) = Infinity
- * cosh(NaN) = NaN
- *
- * x time taken (ms) result
- * 1000 9 9.8503555700852349694e+433
- * 10000 25 4.4034091128314607936e+4342
- * 100000 171 1.4033316802130615897e+43429
- * 1000000 3817 1.5166076984010437725e+434294
- * 10000000 abandoned after 2 minute wait
- *
- * TODO? Compare performance of cosh(x) = 0.5 * (exp(x) + exp(-x))
- *
- */
- P.hyperbolicCosine = P.cosh = function () {
- var k, n, pr, rm, len,
- x = this,
- Ctor = x.constructor,
- one = new Ctor(1);
-
- if (!x.isFinite()) return new Ctor(x.s ? 1 / 0 : NaN);
- if (x.isZero()) return one;
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + 4;
- Ctor.rounding = 1;
- len = x.d.length;
-
- // Argument reduction: cos(4x) = 1 - 8cos^2(x) + 8cos^4(x) + 1
- // i.e. cos(x) = 1 - cos^2(x/4)(8 - 8cos^2(x/4))
-
- // Estimate the optimum number of times to use the argument reduction.
- // TODO? Estimation reused from cosine() and may not be optimal here.
- if (len < 32) {
- k = Math.ceil(len / 3);
- n = (1 / tinyPow(4, k)).toString();
- } else {
- k = 16;
- n = '2.3283064365386962890625e-10';
- }
-
- x = taylorSeries(Ctor, 1, x.times(n), new Ctor(1), true);
-
- // Reverse argument reduction
- var cosh2_x,
- i = k,
- d8 = new Ctor(8);
- for (; i--;) {
- cosh2_x = x.times(x);
- x = one.minus(cosh2_x.times(d8.minus(cosh2_x.times(d8))));
- }
-
- return finalise(x, Ctor.precision = pr, Ctor.rounding = rm, true);
- };
-
-
- /*
- * Return a new Decimal whose value is the hyperbolic sine of the value in radians of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-Infinity, Infinity]
- *
- * sinh(x) = x + x^3/3! + x^5/5! + x^7/7! + ...
- *
- * sinh(0) = 0
- * sinh(-0) = -0
- * sinh(Infinity) = Infinity
- * sinh(-Infinity) = -Infinity
- * sinh(NaN) = NaN
- *
- * x time taken (ms)
- * 10 2 ms
- * 100 5 ms
- * 1000 14 ms
- * 10000 82 ms
- * 100000 886 ms 1.4033316802130615897e+43429
- * 200000 2613 ms
- * 300000 5407 ms
- * 400000 8824 ms
- * 500000 13026 ms 8.7080643612718084129e+217146
- * 1000000 48543 ms
- *
- * TODO? Compare performance of sinh(x) = 0.5 * (exp(x) - exp(-x))
- *
- */
- P.hyperbolicSine = P.sinh = function () {
- var k, pr, rm, len,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite() || x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + 4;
- Ctor.rounding = 1;
- len = x.d.length;
-
- if (len < 3) {
- x = taylorSeries(Ctor, 2, x, x, true);
- } else {
-
- // Alternative argument reduction: sinh(3x) = sinh(x)(3 + 4sinh^2(x))
- // i.e. sinh(x) = sinh(x/3)(3 + 4sinh^2(x/3))
- // 3 multiplications and 1 addition
-
- // Argument reduction: sinh(5x) = sinh(x)(5 + sinh^2(x)(20 + 16sinh^2(x)))
- // i.e. sinh(x) = sinh(x/5)(5 + sinh^2(x/5)(20 + 16sinh^2(x/5)))
- // 4 multiplications and 2 additions
-
- // Estimate the optimum number of times to use the argument reduction.
- k = 1.4 * Math.sqrt(len);
- k = k > 16 ? 16 : k | 0;
-
- x = x.times(1 / tinyPow(5, k));
- x = taylorSeries(Ctor, 2, x, x, true);
-
- // Reverse argument reduction
- var sinh2_x,
- d5 = new Ctor(5),
- d16 = new Ctor(16),
- d20 = new Ctor(20);
- for (; k--;) {
- sinh2_x = x.times(x);
- x = x.times(d5.plus(sinh2_x.times(d16.times(sinh2_x).plus(d20))));
- }
- }
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(x, pr, rm, true);
- };
-
-
- /*
- * Return a new Decimal whose value is the hyperbolic tangent of the value in radians of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-1, 1]
- *
- * tanh(x) = sinh(x) / cosh(x)
- *
- * tanh(0) = 0
- * tanh(-0) = -0
- * tanh(Infinity) = 1
- * tanh(-Infinity) = -1
- * tanh(NaN) = NaN
- *
- */
- P.hyperbolicTangent = P.tanh = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(x.s);
- if (x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + 7;
- Ctor.rounding = 1;
-
- return divide(x.sinh(), x.cosh(), Ctor.precision = pr, Ctor.rounding = rm);
- };
-
-
- /*
- * Return a new Decimal whose value is the arccosine (inverse cosine) in radians of the value of
- * this Decimal.
- *
- * Domain: [-1, 1]
- * Range: [0, pi]
- *
- * acos(x) = pi/2 - asin(x)
- *
- * acos(0) = pi/2
- * acos(-0) = pi/2
- * acos(1) = 0
- * acos(-1) = pi
- * acos(1/2) = pi/3
- * acos(-1/2) = 2*pi/3
- * acos(|x| > 1) = NaN
- * acos(NaN) = NaN
- *
- */
- P.inverseCosine = P.acos = function () {
- var x = this,
- Ctor = x.constructor,
- k = x.abs().cmp(1),
- pr = Ctor.precision,
- rm = Ctor.rounding;
-
- if (k !== -1) {
- return k === 0
- // |x| is 1
- ? x.isNeg() ? getPi(Ctor, pr, rm) : new Ctor(0)
- // |x| > 1 or x is NaN
- : new Ctor(NaN);
- }
-
- if (x.isZero()) return getPi(Ctor, pr + 4, rm).times(0.5);
-
- // TODO? Special case acos(0.5) = pi/3 and acos(-0.5) = 2*pi/3
-
- Ctor.precision = pr + 6;
- Ctor.rounding = 1;
-
- // See https://github.com/MikeMcl/decimal.js/pull/217
- x = new Ctor(1).minus(x).div(x.plus(1)).sqrt().atan();
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.times(2);
- };
-
-
- /*
- * Return a new Decimal whose value is the inverse of the hyperbolic cosine in radians of the
- * value of this Decimal.
- *
- * Domain: [1, Infinity]
- * Range: [0, Infinity]
- *
- * acosh(x) = ln(x + sqrt(x^2 - 1))
- *
- * acosh(x < 1) = NaN
- * acosh(NaN) = NaN
- * acosh(Infinity) = Infinity
- * acosh(-Infinity) = NaN
- * acosh(0) = NaN
- * acosh(-0) = NaN
- * acosh(1) = 0
- * acosh(-1) = NaN
- *
- */
- P.inverseHyperbolicCosine = P.acosh = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (x.lte(1)) return new Ctor(x.eq(1) ? 0 : NaN);
- if (!x.isFinite()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(Math.abs(x.e), x.sd()) + 4;
- Ctor.rounding = 1;
- external = false;
-
- x = x.times(x).minus(1).sqrt().plus(x);
-
- external = true;
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.ln();
- };
-
-
- /*
- * Return a new Decimal whose value is the inverse of the hyperbolic sine in radians of the value
- * of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-Infinity, Infinity]
- *
- * asinh(x) = ln(x + sqrt(x^2 + 1))
- *
- * asinh(NaN) = NaN
- * asinh(Infinity) = Infinity
- * asinh(-Infinity) = -Infinity
- * asinh(0) = 0
- * asinh(-0) = -0
- *
- */
- P.inverseHyperbolicSine = P.asinh = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite() || x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + 2 * Math.max(Math.abs(x.e), x.sd()) + 6;
- Ctor.rounding = 1;
- external = false;
-
- x = x.times(x).plus(1).sqrt().plus(x);
-
- external = true;
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.ln();
- };
-
-
- /*
- * Return a new Decimal whose value is the inverse of the hyperbolic tangent in radians of the
- * value of this Decimal.
- *
- * Domain: [-1, 1]
- * Range: [-Infinity, Infinity]
- *
- * atanh(x) = 0.5 * ln((1 + x) / (1 - x))
- *
- * atanh(|x| > 1) = NaN
- * atanh(NaN) = NaN
- * atanh(Infinity) = NaN
- * atanh(-Infinity) = NaN
- * atanh(0) = 0
- * atanh(-0) = -0
- * atanh(1) = Infinity
- * atanh(-1) = -Infinity
- *
- */
- P.inverseHyperbolicTangent = P.atanh = function () {
- var pr, rm, wpr, xsd,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(NaN);
- if (x.e >= 0) return new Ctor(x.abs().eq(1) ? x.s / 0 : x.isZero() ? x : NaN);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- xsd = x.sd();
-
- if (Math.max(xsd, pr) < 2 * -x.e - 1) return finalise(new Ctor(x), pr, rm, true);
-
- Ctor.precision = wpr = xsd - x.e;
-
- x = divide(x.plus(1), new Ctor(1).minus(x), wpr + pr, 1);
-
- Ctor.precision = pr + 4;
- Ctor.rounding = 1;
-
- x = x.ln();
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.times(0.5);
- };
-
-
- /*
- * Return a new Decimal whose value is the arcsine (inverse sine) in radians of the value of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-pi/2, pi/2]
- *
- * asin(x) = 2*atan(x/(1 + sqrt(1 - x^2)))
- *
- * asin(0) = 0
- * asin(-0) = -0
- * asin(1/2) = pi/6
- * asin(-1/2) = -pi/6
- * asin(1) = pi/2
- * asin(-1) = -pi/2
- * asin(|x| > 1) = NaN
- * asin(NaN) = NaN
- *
- * TODO? Compare performance of Taylor series.
- *
- */
- P.inverseSine = P.asin = function () {
- var halfPi, k,
- pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (x.isZero()) return new Ctor(x);
-
- k = x.abs().cmp(1);
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- if (k !== -1) {
-
- // |x| is 1
- if (k === 0) {
- halfPi = getPi(Ctor, pr + 4, rm).times(0.5);
- halfPi.s = x.s;
- return halfPi;
- }
-
- // |x| > 1 or x is NaN
- return new Ctor(NaN);
- }
-
- // TODO? Special case asin(1/2) = pi/6 and asin(-1/2) = -pi/6
-
- Ctor.precision = pr + 6;
- Ctor.rounding = 1;
-
- x = x.div(new Ctor(1).minus(x.times(x)).sqrt().plus(1)).atan();
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.times(2);
- };
-
-
- /*
- * Return a new Decimal whose value is the arctangent (inverse tangent) in radians of the value
- * of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-pi/2, pi/2]
- *
- * atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...
- *
- * atan(0) = 0
- * atan(-0) = -0
- * atan(1) = pi/4
- * atan(-1) = -pi/4
- * atan(Infinity) = pi/2
- * atan(-Infinity) = -pi/2
- * atan(NaN) = NaN
- *
- */
- P.inverseTangent = P.atan = function () {
- var i, j, k, n, px, t, r, wpr, x2,
- x = this,
- Ctor = x.constructor,
- pr = Ctor.precision,
- rm = Ctor.rounding;
-
- if (!x.isFinite()) {
- if (!x.s) return new Ctor(NaN);
- if (pr + 4 <= PI_PRECISION) {
- r = getPi(Ctor, pr + 4, rm).times(0.5);
- r.s = x.s;
- return r;
- }
- } else if (x.isZero()) {
- return new Ctor(x);
- } else if (x.abs().eq(1) && pr + 4 <= PI_PRECISION) {
- r = getPi(Ctor, pr + 4, rm).times(0.25);
- r.s = x.s;
- return r;
- }
-
- Ctor.precision = wpr = pr + 10;
- Ctor.rounding = 1;
-
- // TODO? if (x >= 1 && pr <= PI_PRECISION) atan(x) = halfPi * x.s - atan(1 / x);
-
- // Argument reduction
- // Ensure |x| < 0.42
- // atan(x) = 2 * atan(x / (1 + sqrt(1 + x^2)))
-
- k = Math.min(28, wpr / LOG_BASE + 2 | 0);
-
- for (i = k; i; --i) x = x.div(x.times(x).plus(1).sqrt().plus(1));
-
- external = false;
-
- j = Math.ceil(wpr / LOG_BASE);
- n = 1;
- x2 = x.times(x);
- r = new Ctor(x);
- px = x;
-
- // atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...
- for (; i !== -1;) {
- px = px.times(x2);
- t = r.minus(px.div(n += 2));
-
- px = px.times(x2);
- r = t.plus(px.div(n += 2));
-
- if (r.d[j] !== void 0) for (i = j; r.d[i] === t.d[i] && i--;);
- }
-
- if (k) r = r.times(2 << (k - 1));
-
- external = true;
-
- return finalise(r, Ctor.precision = pr, Ctor.rounding = rm, true);
- };
-
-
- /*
- * Return true if the value of this Decimal is a finite number, otherwise return false.
- *
- */
- P.isFinite = function () {
- return !!this.d;
- };
-
-
- /*
- * Return true if the value of this Decimal is an integer, otherwise return false.
- *
- */
- P.isInteger = P.isInt = function () {
- return !!this.d && mathfloor(this.e / LOG_BASE) > this.d.length - 2;
- };
-
-
- /*
- * Return true if the value of this Decimal is NaN, otherwise return false.
- *
- */
- P.isNaN = function () {
- return !this.s;
- };
-
-
- /*
- * Return true if the value of this Decimal is negative, otherwise return false.
- *
- */
- P.isNegative = P.isNeg = function () {
- return this.s < 0;
- };
-
-
- /*
- * Return true if the value of this Decimal is positive, otherwise return false.
- *
- */
- P.isPositive = P.isPos = function () {
- return this.s > 0;
- };
-
-
- /*
- * Return true if the value of this Decimal is 0 or -0, otherwise return false.
- *
- */
- P.isZero = function () {
- return !!this.d && this.d[0] === 0;
- };
-
-
- /*
- * Return true if the value of this Decimal is less than `y`, otherwise return false.
- *
- */
- P.lessThan = P.lt = function (y) {
- return this.cmp(y) < 0;
- };
-
-
- /*
- * Return true if the value of this Decimal is less than or equal to `y`, otherwise return false.
- *
- */
- P.lessThanOrEqualTo = P.lte = function (y) {
- return this.cmp(y) < 1;
- };
-
-
- /*
- * Return the logarithm of the value of this Decimal to the specified base, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * If no base is specified, return log[10](arg).
- *
- * log[base](arg) = ln(arg) / ln(base)
- *
- * The result will always be correctly rounded if the base of the log is 10, and 'almost always'
- * otherwise:
- *
- * Depending on the rounding mode, the result may be incorrectly rounded if the first fifteen
- * rounding digits are [49]99999999999999 or [50]00000000000000. In that case, the maximum error
- * between the result and the correctly rounded result will be one ulp (unit in the last place).
- *
- * log[-b](a) = NaN
- * log[0](a) = NaN
- * log[1](a) = NaN
- * log[NaN](a) = NaN
- * log[Infinity](a) = NaN
- * log[b](0) = -Infinity
- * log[b](-0) = -Infinity
- * log[b](-a) = NaN
- * log[b](1) = 0
- * log[b](Infinity) = Infinity
- * log[b](NaN) = NaN
- *
- * [base] {number|string|bigint|Decimal} The base of the logarithm.
- *
- */
- P.logarithm = P.log = function (base) {
- var isBase10, d, denominator, k, inf, num, sd, r,
- arg = this,
- Ctor = arg.constructor,
- pr = Ctor.precision,
- rm = Ctor.rounding,
- guard = 5;
-
- // Default base is 10.
- if (base == null) {
- base = new Ctor(10);
- isBase10 = true;
- } else {
- base = new Ctor(base);
- d = base.d;
-
- // Return NaN if base is negative, or non-finite, or is 0 or 1.
- if (base.s < 0 || !d || !d[0] || base.eq(1)) return new Ctor(NaN);
-
- isBase10 = base.eq(10);
- }
-
- d = arg.d;
-
- // Is arg negative, non-finite, 0 or 1?
- if (arg.s < 0 || !d || !d[0] || arg.eq(1)) {
- return new Ctor(d && !d[0] ? -1 / 0 : arg.s != 1 ? NaN : d ? 0 : 1 / 0);
- }
-
- // The result will have a non-terminating decimal expansion if base is 10 and arg is not an
- // integer power of 10.
- if (isBase10) {
- if (d.length > 1) {
- inf = true;
- } else {
- for (k = d[0]; k % 10 === 0;) k /= 10;
- inf = k !== 1;
- }
- }
-
- external = false;
- sd = pr + guard;
- num = naturalLogarithm(arg, sd);
- denominator = isBase10 ? getLn10(Ctor, sd + 10) : naturalLogarithm(base, sd);
-
- // The result will have 5 rounding digits.
- r = divide(num, denominator, sd, 1);
-
- // If at a rounding boundary, i.e. the result's rounding digits are [49]9999 or [50]0000,
- // calculate 10 further digits.
- //
- // If the result is known to have an infinite decimal expansion, repeat this until it is clear
- // that the result is above or below the boundary. Otherwise, if after calculating the 10
- // further digits, the last 14 are nines, round up and assume the result is exact.
- // Also assume the result is exact if the last 14 are zero.
- //
- // Example of a result that will be incorrectly rounded:
- // log[1048576](4503599627370502) = 2.60000000000000009610279511444746...
- // The above result correctly rounded using ROUND_CEIL to 1 decimal place should be 2.7, but it
- // will be given as 2.6 as there are 15 zeros immediately after the requested decimal place, so
- // the exact result would be assumed to be 2.6, which rounded using ROUND_CEIL to 1 decimal
- // place is still 2.6.
- if (checkRoundingDigits(r.d, k = pr, rm)) {
-
- do {
- sd += 10;
- num = naturalLogarithm(arg, sd);
- denominator = isBase10 ? getLn10(Ctor, sd + 10) : naturalLogarithm(base, sd);
- r = divide(num, denominator, sd, 1);
-
- if (!inf) {
-
- // Check for 14 nines from the 2nd rounding digit, as the first may be 4.
- if (+digitsToString(r.d).slice(k + 1, k + 15) + 1 == 1e14) {
- r = finalise(r, pr + 1, 0);
- }
-
- break;
- }
- } while (checkRoundingDigits(r.d, k += 10, rm));
- }
-
- external = true;
-
- return finalise(r, pr, rm);
- };
-
-
- /*
- * Return a new Decimal whose value is the maximum of the arguments and the value of this Decimal.
- *
- * arguments {number|string|bigint|Decimal}
- *
- P.max = function () {
- Array.prototype.push.call(arguments, this);
- return maxOrMin(this.constructor, arguments, -1);
- };
- */
-
-
- /*
- * Return a new Decimal whose value is the minimum of the arguments and the value of this Decimal.
- *
- * arguments {number|string|bigint|Decimal}
- *
- P.min = function () {
- Array.prototype.push.call(arguments, this);
- return maxOrMin(this.constructor, arguments, 1);
- };
- */
-
-
- /*
- * n - 0 = n
- * n - N = N
- * n - I = -I
- * 0 - n = -n
- * 0 - 0 = 0
- * 0 - N = N
- * 0 - I = -I
- * N - n = N
- * N - 0 = N
- * N - N = N
- * N - I = N
- * I - n = I
- * I - 0 = I
- * I - N = N
- * I - I = N
- *
- * Return a new Decimal whose value is the value of this Decimal minus `y`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- */
- P.minus = P.sub = function (y) {
- var d, e, i, j, k, len, pr, rm, xd, xe, xLTy, yd,
- x = this,
- Ctor = x.constructor;
-
- y = new Ctor(y);
-
- // If either is not finite...
- if (!x.d || !y.d) {
-
- // Return NaN if either is NaN.
- if (!x.s || !y.s) y = new Ctor(NaN);
-
- // Return y negated if x is finite and y is ±Infinity.
- else if (x.d) y.s = -y.s;
-
- // Return x if y is finite and x is ±Infinity.
- // Return x if both are ±Infinity with different signs.
- // Return NaN if both are ±Infinity with the same sign.
- else y = new Ctor(y.d || x.s !== y.s ? x : NaN);
-
- return y;
- }
-
- // If signs differ...
- if (x.s != y.s) {
- y.s = -y.s;
- return x.plus(y);
- }
-
- xd = x.d;
- yd = y.d;
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- // If either is zero...
- if (!xd[0] || !yd[0]) {
-
- // Return y negated if x is zero and y is non-zero.
- if (yd[0]) y.s = -y.s;
-
- // Return x if y is zero and x is non-zero.
- else if (xd[0]) y = new Ctor(x);
-
- // Return zero if both are zero.
- // From IEEE 754 (2008) 6.3: 0 - 0 = -0 - -0 = -0 when rounding to -Infinity.
- else return new Ctor(rm === 3 ? -0 : 0);
-
- return external ? finalise(y, pr, rm) : y;
- }
-
- // x and y are finite, non-zero numbers with the same sign.
-
- // Calculate base 1e7 exponents.
- e = mathfloor(y.e / LOG_BASE);
- xe = mathfloor(x.e / LOG_BASE);
-
- xd = xd.slice();
- k = xe - e;
-
- // If base 1e7 exponents differ...
- if (k) {
- xLTy = k < 0;
-
- if (xLTy) {
- d = xd;
- k = -k;
- len = yd.length;
- } else {
- d = yd;
- e = xe;
- len = xd.length;
- }
-
- // Numbers with massively different exponents would result in a very high number of
- // zeros needing to be prepended, but this can be avoided while still ensuring correct
- // rounding by limiting the number of zeros to `Math.ceil(pr / LOG_BASE) + 2`.
- i = Math.max(Math.ceil(pr / LOG_BASE), len) + 2;
-
- if (k > i) {
- k = i;
- d.length = 1;
- }
-
- // Prepend zeros to equalise exponents.
- d.reverse();
- for (i = k; i--;) d.push(0);
- d.reverse();
-
- // Base 1e7 exponents equal.
- } else {
-
- // Check digits to determine which is the bigger number.
-
- i = xd.length;
- len = yd.length;
- xLTy = i < len;
- if (xLTy) len = i;
-
- for (i = 0; i < len; i++) {
- if (xd[i] != yd[i]) {
- xLTy = xd[i] < yd[i];
- break;
- }
- }
-
- k = 0;
- }
-
- if (xLTy) {
- d = xd;
- xd = yd;
- yd = d;
- y.s = -y.s;
- }
-
- len = xd.length;
-
- // Append zeros to `xd` if shorter.
- // Don't add zeros to `yd` if shorter as subtraction only needs to start at `yd` length.
- for (i = yd.length - len; i > 0; --i) xd[len++] = 0;
-
- // Subtract yd from xd.
- for (i = yd.length; i > k;) {
-
- if (xd[--i] < yd[i]) {
- for (j = i; j && xd[--j] === 0;) xd[j] = BASE - 1;
- --xd[j];
- xd[i] += BASE;
- }
-
- xd[i] -= yd[i];
- }
-
- // Remove trailing zeros.
- for (; xd[--len] === 0;) xd.pop();
-
- // Remove leading zeros and adjust exponent accordingly.
- for (; xd[0] === 0; xd.shift()) --e;
-
- // Zero?
- if (!xd[0]) return new Ctor(rm === 3 ? -0 : 0);
-
- y.d = xd;
- y.e = getBase10Exponent(xd, e);
-
- return external ? finalise(y, pr, rm) : y;
- };
-
-
- /*
- * n % 0 = N
- * n % N = N
- * n % I = n
- * 0 % n = 0
- * -0 % n = -0
- * 0 % 0 = N
- * 0 % N = N
- * 0 % I = 0
- * N % n = N
- * N % 0 = N
- * N % N = N
- * N % I = N
- * I % n = N
- * I % 0 = N
- * I % N = N
- * I % I = N
- *
- * Return a new Decimal whose value is the value of this Decimal modulo `y`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * The result depends on the modulo mode.
- *
- */
- P.modulo = P.mod = function (y) {
- var q,
- x = this,
- Ctor = x.constructor;
-
- y = new Ctor(y);
-
- // Return NaN if x is ±Infinity or NaN, or y is NaN or ±0.
- if (!x.d || !y.s || y.d && !y.d[0]) return new Ctor(NaN);
-
- // Return x if y is ±Infinity or x is ±0.
- if (!y.d || x.d && !x.d[0]) {
- return finalise(new Ctor(x), Ctor.precision, Ctor.rounding);
- }
-
- // Prevent rounding of intermediate calculations.
- external = false;
-
- if (Ctor.modulo == 9) {
-
- // Euclidian division: q = sign(y) * floor(x / abs(y))
- // result = x - q * y where 0 <= result < abs(y)
- q = divide(x, y.abs(), 0, 3, 1);
- q.s *= y.s;
- } else {
- q = divide(x, y, 0, Ctor.modulo, 1);
- }
-
- q = q.times(y);
-
- external = true;
-
- return x.minus(q);
- };
-
-
- /*
- * Return a new Decimal whose value is the natural exponential of the value of this Decimal,
- * i.e. the base e raised to the power the value of this Decimal, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- */
- P.naturalExponential = P.exp = function () {
- return naturalExponential(this);
- };
-
-
- /*
- * Return a new Decimal whose value is the natural logarithm of the value of this Decimal,
- * rounded to `precision` significant digits using rounding mode `rounding`.
- *
- */
- P.naturalLogarithm = P.ln = function () {
- return naturalLogarithm(this);
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal negated, i.e. as if multiplied by
- * -1.
- *
- */
- P.negated = P.neg = function () {
- var x = new this.constructor(this);
- x.s = -x.s;
- return finalise(x);
- };
-
-
- /*
- * n + 0 = n
- * n + N = N
- * n + I = I
- * 0 + n = n
- * 0 + 0 = 0
- * 0 + N = N
- * 0 + I = I
- * N + n = N
- * N + 0 = N
- * N + N = N
- * N + I = N
- * I + n = I
- * I + 0 = I
- * I + N = N
- * I + I = I
- *
- * Return a new Decimal whose value is the value of this Decimal plus `y`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- */
- P.plus = P.add = function (y) {
- var carry, d, e, i, k, len, pr, rm, xd, yd,
- x = this,
- Ctor = x.constructor;
-
- y = new Ctor(y);
-
- // If either is not finite...
- if (!x.d || !y.d) {
-
- // Return NaN if either is NaN.
- if (!x.s || !y.s) y = new Ctor(NaN);
-
- // Return x if y is finite and x is ±Infinity.
- // Return x if both are ±Infinity with the same sign.
- // Return NaN if both are ±Infinity with different signs.
- // Return y if x is finite and y is ±Infinity.
- else if (!x.d) y = new Ctor(y.d || x.s === y.s ? x : NaN);
-
- return y;
- }
-
- // If signs differ...
- if (x.s != y.s) {
- y.s = -y.s;
- return x.minus(y);
- }
-
- xd = x.d;
- yd = y.d;
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- // If either is zero...
- if (!xd[0] || !yd[0]) {
-
- // Return x if y is zero.
- // Return y if y is non-zero.
- if (!yd[0]) y = new Ctor(x);
-
- return external ? finalise(y, pr, rm) : y;
- }
-
- // x and y are finite, non-zero numbers with the same sign.
-
- // Calculate base 1e7 exponents.
- k = mathfloor(x.e / LOG_BASE);
- e = mathfloor(y.e / LOG_BASE);
-
- xd = xd.slice();
- i = k - e;
-
- // If base 1e7 exponents differ...
- if (i) {
-
- if (i < 0) {
- d = xd;
- i = -i;
- len = yd.length;
- } else {
- d = yd;
- e = k;
- len = xd.length;
- }
-
- // Limit number of zeros prepended to max(ceil(pr / LOG_BASE), len) + 1.
- k = Math.ceil(pr / LOG_BASE);
- len = k > len ? k + 1 : len + 1;
-
- if (i > len) {
- i = len;
- d.length = 1;
- }
-
- // Prepend zeros to equalise exponents. Note: Faster to use reverse then do unshifts.
- d.reverse();
- for (; i--;) d.push(0);
- d.reverse();
- }
-
- len = xd.length;
- i = yd.length;
-
- // If yd is longer than xd, swap xd and yd so xd points to the longer array.
- if (len - i < 0) {
- i = len;
- d = yd;
- yd = xd;
- xd = d;
- }
-
- // Only start adding at yd.length - 1 as the further digits of xd can be left as they are.
- for (carry = 0; i;) {
- carry = (xd[--i] = xd[i] + yd[i] + carry) / BASE | 0;
- xd[i] %= BASE;
- }
-
- if (carry) {
- xd.unshift(carry);
- ++e;
- }
-
- // Remove trailing zeros.
- // No need to check for zero, as +x + +y != 0 && -x + -y != 0
- for (len = xd.length; xd[--len] == 0;) xd.pop();
-
- y.d = xd;
- y.e = getBase10Exponent(xd, e);
-
- return external ? finalise(y, pr, rm) : y;
- };
-
-
- /*
- * Return the number of significant digits of the value of this Decimal.
- *
- * [z] {boolean|number} Whether to count integer-part trailing zeros: true, false, 1 or 0.
- *
- */
- P.precision = P.sd = function (z) {
- var k,
- x = this;
-
- if (z !== void 0 && z !== !!z && z !== 1 && z !== 0) throw Error(invalidArgument + z);
-
- if (x.d) {
- k = getPrecision(x.d);
- if (z && x.e + 1 > k) k = x.e + 1;
- } else {
- k = NaN;
- }
-
- return k;
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal rounded to a whole number using
- * rounding mode `rounding`.
- *
- */
- P.round = function () {
- var x = this,
- Ctor = x.constructor;
-
- return finalise(new Ctor(x), x.e + 1, Ctor.rounding);
- };
-
-
- /*
- * Return a new Decimal whose value is the sine of the value in radians of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-1, 1]
- *
- * sin(x) = x - x^3/3! + x^5/5! - ...
- *
- * sin(0) = 0
- * sin(-0) = -0
- * sin(Infinity) = NaN
- * sin(-Infinity) = NaN
- * sin(NaN) = NaN
- *
- */
- P.sine = P.sin = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(NaN);
- if (x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE;
- Ctor.rounding = 1;
-
- x = sine(Ctor, toLessThanHalfPi(Ctor, x));
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(quadrant > 2 ? x.neg() : x, pr, rm, true);
- };
-
-
- /*
- * Return a new Decimal whose value is the square root of this Decimal, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * sqrt(-n) = N
- * sqrt(N) = N
- * sqrt(-I) = N
- * sqrt(I) = I
- * sqrt(0) = 0
- * sqrt(-0) = -0
- *
- */
- P.squareRoot = P.sqrt = function () {
- var m, n, sd, r, rep, t,
- x = this,
- d = x.d,
- e = x.e,
- s = x.s,
- Ctor = x.constructor;
-
- // Negative/NaN/Infinity/zero?
- if (s !== 1 || !d || !d[0]) {
- return new Ctor(!s || s < 0 && (!d || d[0]) ? NaN : d ? x : 1 / 0);
- }
-
- external = false;
-
- // Initial estimate.
- s = Math.sqrt(+x);
-
- // Math.sqrt underflow/overflow?
- // Pass x to Math.sqrt as integer, then adjust the exponent of the result.
- if (s == 0 || s == 1 / 0) {
- n = digitsToString(d);
-
- if ((n.length + e) % 2 == 0) n += '0';
- s = Math.sqrt(n);
- e = mathfloor((e + 1) / 2) - (e < 0 || e % 2);
-
- if (s == 1 / 0) {
- n = '5e' + e;
- } else {
- n = s.toExponential();
- n = n.slice(0, n.indexOf('e') + 1) + e;
- }
-
- r = new Ctor(n);
- } else {
- r = new Ctor(s.toString());
- }
-
- sd = (e = Ctor.precision) + 3;
-
- // Newton-Raphson iteration.
- for (;;) {
- t = r;
- r = t.plus(divide(x, t, sd + 2, 1)).times(0.5);
-
- // TODO? Replace with for-loop and checkRoundingDigits.
- if (digitsToString(t.d).slice(0, sd) === (n = digitsToString(r.d)).slice(0, sd)) {
- n = n.slice(sd - 3, sd + 1);
-
- // The 4th rounding digit may be in error by -1 so if the 4 rounding digits are 9999 or
- // 4999, i.e. approaching a rounding boundary, continue the iteration.
- if (n == '9999' || !rep && n == '4999') {
-
- // On the first iteration only, check to see if rounding up gives the exact result as the
- // nines may infinitely repeat.
- if (!rep) {
- finalise(t, e + 1, 0);
-
- if (t.times(t).eq(x)) {
- r = t;
- break;
- }
- }
-
- sd += 4;
- rep = 1;
- } else {
-
- // If the rounding digits are null, 0{0,4} or 50{0,3}, check for an exact result.
- // If not, then there are further digits and m will be truthy.
- if (!+n || !+n.slice(1) && n.charAt(0) == '5') {
-
- // Truncate to the first rounding digit.
- finalise(r, e + 1, 1);
- m = !r.times(r).eq(x);
- }
-
- break;
- }
- }
- }
-
- external = true;
-
- return finalise(r, e, Ctor.rounding, m);
- };
-
-
- /*
- * Return a new Decimal whose value is the tangent of the value in radians of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-Infinity, Infinity]
- *
- * tan(0) = 0
- * tan(-0) = -0
- * tan(Infinity) = NaN
- * tan(-Infinity) = NaN
- * tan(NaN) = NaN
- *
- */
- P.tangent = P.tan = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(NaN);
- if (x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + 10;
- Ctor.rounding = 1;
-
- x = x.sin();
- x.s = 1;
- x = divide(x, new Ctor(1).minus(x.times(x)).sqrt(), pr + 10, 0);
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(quadrant == 2 || quadrant == 4 ? x.neg() : x, pr, rm, true);
- };
-
-
- /*
- * n * 0 = 0
- * n * N = N
- * n * I = I
- * 0 * n = 0
- * 0 * 0 = 0
- * 0 * N = N
- * 0 * I = N
- * N * n = N
- * N * 0 = N
- * N * N = N
- * N * I = N
- * I * n = I
- * I * 0 = N
- * I * N = N
- * I * I = I
- *
- * Return a new Decimal whose value is this Decimal times `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- */
- P.times = P.mul = function (y) {
- var carry, e, i, k, r, rL, t, xdL, ydL,
- x = this,
- Ctor = x.constructor,
- xd = x.d,
- yd = (y = new Ctor(y)).d;
-
- y.s *= x.s;
-
- // If either is NaN, ±Infinity or ±0...
- if (!xd || !xd[0] || !yd || !yd[0]) {
-
- return new Ctor(!y.s || xd && !xd[0] && !yd || yd && !yd[0] && !xd
-
- // Return NaN if either is NaN.
- // Return NaN if x is ±0 and y is ±Infinity, or y is ±0 and x is ±Infinity.
- ? NaN
-
- // Return ±Infinity if either is ±Infinity.
- // Return ±0 if either is ±0.
- : !xd || !yd ? y.s / 0 : y.s * 0);
- }
-
- e = mathfloor(x.e / LOG_BASE) + mathfloor(y.e / LOG_BASE);
- xdL = xd.length;
- ydL = yd.length;
-
- // Ensure xd points to the longer array.
- if (xdL < ydL) {
- r = xd;
- xd = yd;
- yd = r;
- rL = xdL;
- xdL = ydL;
- ydL = rL;
- }
-
- // Initialise the result array with zeros.
- r = [];
- rL = xdL + ydL;
- for (i = rL; i--;) r.push(0);
-
- // Multiply!
- for (i = ydL; --i >= 0;) {
- carry = 0;
- for (k = xdL + i; k > i;) {
- t = r[k] + yd[i] * xd[k - i - 1] + carry;
- r[k--] = t % BASE | 0;
- carry = t / BASE | 0;
- }
-
- r[k] = (r[k] + carry) % BASE | 0;
- }
-
- // Remove trailing zeros.
- for (; !r[--rL];) r.pop();
-
- if (carry) ++e;
- else r.shift();
-
- y.d = r;
- y.e = getBase10Exponent(r, e);
-
- return external ? finalise(y, Ctor.precision, Ctor.rounding) : y;
- };
-
-
- /*
- * Return a string representing the value of this Decimal in base 2, round to `sd` significant
- * digits using rounding mode `rm`.
- *
- * If the optional `sd` argument is present then return binary exponential notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
- P.toBinary = function (sd, rm) {
- return toStringBinary(this, 2, sd, rm);
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal rounded to a maximum of `dp`
- * decimal places using rounding mode `rm` or `rounding` if `rm` is omitted.
- *
- * If `dp` is omitted, return a new Decimal whose value is the value of this Decimal.
- *
- * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
- P.toDecimalPlaces = P.toDP = function (dp, rm) {
- var x = this,
- Ctor = x.constructor;
-
- x = new Ctor(x);
- if (dp === void 0) return x;
-
- checkInt32(dp, 0, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- return finalise(x, dp + x.e + 1, rm);
- };
-
-
- /*
- * Return a string representing the value of this Decimal in exponential notation rounded to
- * `dp` fixed decimal places using rounding mode `rounding`.
- *
- * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
- P.toExponential = function (dp, rm) {
- var str,
- x = this,
- Ctor = x.constructor;
-
- if (dp === void 0) {
- str = finiteToString(x, true);
- } else {
- checkInt32(dp, 0, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- x = finalise(new Ctor(x), dp + 1, rm);
- str = finiteToString(x, true, dp + 1);
- }
-
- return x.isNeg() && !x.isZero() ? '-' + str : str;
- };
-
-
- /*
- * Return a string representing the value of this Decimal in normal (fixed-point) notation to
- * `dp` fixed decimal places and rounded using rounding mode `rm` or `rounding` if `rm` is
- * omitted.
- *
- * As with JavaScript numbers, (-0).toFixed(0) is '0', but e.g. (-0.00001).toFixed(0) is '-0'.
- *
- * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- * (-0).toFixed(0) is '0', but (-0.1).toFixed(0) is '-0'.
- * (-0).toFixed(1) is '0.0', but (-0.01).toFixed(1) is '-0.0'.
- * (-0).toFixed(3) is '0.000'.
- * (-0.5).toFixed(0) is '-0'.
- *
- */
- P.toFixed = function (dp, rm) {
- var str, y,
- x = this,
- Ctor = x.constructor;
-
- if (dp === void 0) {
- str = finiteToString(x);
- } else {
- checkInt32(dp, 0, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- y = finalise(new Ctor(x), dp + x.e + 1, rm);
- str = finiteToString(y, false, dp + y.e + 1);
- }
-
- // To determine whether to add the minus sign look at the value before it was rounded,
- // i.e. look at `x` rather than `y`.
- return x.isNeg() && !x.isZero() ? '-' + str : str;
- };
-
-
- /*
- * Return an array representing the value of this Decimal as a simple fraction with an integer
- * numerator and an integer denominator.
- *
- * The denominator will be a positive non-zero value less than or equal to the specified maximum
- * denominator. If a maximum denominator is not specified, the denominator will be the lowest
- * value necessary to represent the number exactly.
- *
- * [maxD] {number|string|bigint|Decimal} Maximum denominator. Integer >= 1 and < Infinity.
- *
- */
- P.toFraction = function (maxD) {
- var d, d0, d1, d2, e, k, n, n0, n1, pr, q, r,
- x = this,
- xd = x.d,
- Ctor = x.constructor;
-
- if (!xd) return new Ctor(x);
-
- n1 = d0 = new Ctor(1);
- d1 = n0 = new Ctor(0);
-
- d = new Ctor(d1);
- e = d.e = getPrecision(xd) - x.e - 1;
- k = e % LOG_BASE;
- d.d[0] = mathpow(10, k < 0 ? LOG_BASE + k : k);
-
- if (maxD == null) {
-
- // d is 10**e, the minimum max-denominator needed.
- maxD = e > 0 ? d : n1;
- } else {
- n = new Ctor(maxD);
- if (!n.isInt() || n.lt(n1)) throw Error(invalidArgument + n);
- maxD = n.gt(d) ? (e > 0 ? d : n1) : n;
- }
-
- external = false;
- n = new Ctor(digitsToString(xd));
- pr = Ctor.precision;
- Ctor.precision = e = xd.length * LOG_BASE * 2;
-
- for (;;) {
- q = divide(n, d, 0, 1, 1);
- d2 = d0.plus(q.times(d1));
- if (d2.cmp(maxD) == 1) break;
- d0 = d1;
- d1 = d2;
- d2 = n1;
- n1 = n0.plus(q.times(d2));
- n0 = d2;
- d2 = d;
- d = n.minus(q.times(d2));
- n = d2;
- }
-
- d2 = divide(maxD.minus(d0), d1, 0, 1, 1);
- n0 = n0.plus(d2.times(n1));
- d0 = d0.plus(d2.times(d1));
- n0.s = n1.s = x.s;
-
- // Determine which fraction is closer to x, n0/d0 or n1/d1?
- r = divide(n1, d1, e, 1).minus(x).abs().cmp(divide(n0, d0, e, 1).minus(x).abs()) < 1
- ? [n1, d1] : [n0, d0];
-
- Ctor.precision = pr;
- external = true;
-
- return r;
- };
-
-
- /*
- * Return a string representing the value of this Decimal in base 16, round to `sd` significant
- * digits using rounding mode `rm`.
- *
- * If the optional `sd` argument is present then return binary exponential notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
- P.toHexadecimal = P.toHex = function (sd, rm) {
- return toStringBinary(this, 16, sd, rm);
- };
-
-
- /*
- * Returns a new Decimal whose value is the nearest multiple of `y` in the direction of rounding
- * mode `rm`, or `Decimal.rounding` if `rm` is omitted, to the value of this Decimal.
- *
- * The return value will always have the same sign as this Decimal, unless either this Decimal
- * or `y` is NaN, in which case the return value will be also be NaN.
- *
- * The return value is not affected by the value of `precision`.
- *
- * y {number|string|bigint|Decimal} The magnitude to round to a multiple of.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- * 'toNearest() rounding mode not an integer: {rm}'
- * 'toNearest() rounding mode out of range: {rm}'
- *
- */
- P.toNearest = function (y, rm) {
- var x = this,
- Ctor = x.constructor;
-
- x = new Ctor(x);
-
- if (y == null) {
-
- // If x is not finite, return x.
- if (!x.d) return x;
-
- y = new Ctor(1);
- rm = Ctor.rounding;
- } else {
- y = new Ctor(y);
- if (rm === void 0) {
- rm = Ctor.rounding;
- } else {
- checkInt32(rm, 0, 8);
- }
-
- // If x is not finite, return x if y is not NaN, else NaN.
- if (!x.d) return y.s ? x : y;
-
- // If y is not finite, return Infinity with the sign of x if y is Infinity, else NaN.
- if (!y.d) {
- if (y.s) y.s = x.s;
- return y;
- }
- }
-
- // If y is not zero, calculate the nearest multiple of y to x.
- if (y.d[0]) {
- external = false;
- x = divide(x, y, 0, rm, 1).times(y);
- external = true;
- finalise(x);
-
- // If y is zero, return zero with the sign of x.
- } else {
- y.s = x.s;
- x = y;
- }
-
- return x;
- };
-
-
- /*
- * Return the value of this Decimal converted to a number primitive.
- * Zero keeps its sign.
- *
- */
- P.toNumber = function () {
- return +this;
- };
-
-
- /*
- * Return a string representing the value of this Decimal in base 8, round to `sd` significant
- * digits using rounding mode `rm`.
- *
- * If the optional `sd` argument is present then return binary exponential notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
- P.toOctal = function (sd, rm) {
- return toStringBinary(this, 8, sd, rm);
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal raised to the power `y`, rounded
- * to `precision` significant digits using rounding mode `rounding`.
- *
- * ECMAScript compliant.
- *
- * pow(x, NaN) = NaN
- * pow(x, ±0) = 1
-
- * pow(NaN, non-zero) = NaN
- * pow(abs(x) > 1, +Infinity) = +Infinity
- * pow(abs(x) > 1, -Infinity) = +0
- * pow(abs(x) == 1, ±Infinity) = NaN
- * pow(abs(x) < 1, +Infinity) = +0
- * pow(abs(x) < 1, -Infinity) = +Infinity
- * pow(+Infinity, y > 0) = +Infinity
- * pow(+Infinity, y < 0) = +0
- * pow(-Infinity, odd integer > 0) = -Infinity
- * pow(-Infinity, even integer > 0) = +Infinity
- * pow(-Infinity, odd integer < 0) = -0
- * pow(-Infinity, even integer < 0) = +0
- * pow(+0, y > 0) = +0
- * pow(+0, y < 0) = +Infinity
- * pow(-0, odd integer > 0) = -0
- * pow(-0, even integer > 0) = +0
- * pow(-0, odd integer < 0) = -Infinity
- * pow(-0, even integer < 0) = +Infinity
- * pow(finite x < 0, finite non-integer) = NaN
- *
- * For non-integer or very large exponents pow(x, y) is calculated using
- *
- * x^y = exp(y*ln(x))
- *
- * Assuming the first 15 rounding digits are each equally likely to be any digit 0-9, the
- * probability of an incorrectly rounded result
- * P([49]9{14} | [50]0{14}) = 2 * 0.2 * 10^-14 = 4e-15 = 1/2.5e+14
- * i.e. 1 in 250,000,000,000,000
- *
- * If a result is incorrectly rounded the maximum error will be 1 ulp (unit in last place).
- *
- * y {number|string|bigint|Decimal} The power to which to raise this Decimal.
- *
- */
- P.toPower = P.pow = function (y) {
- var e, k, pr, r, rm, s,
- x = this,
- Ctor = x.constructor,
- yn = +(y = new Ctor(y));
-
- // Either ±Infinity, NaN or ±0?
- if (!x.d || !y.d || !x.d[0] || !y.d[0]) return new Ctor(mathpow(+x, yn));
-
- x = new Ctor(x);
-
- if (x.eq(1)) return x;
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- if (y.eq(1)) return finalise(x, pr, rm);
-
- // y exponent
- e = mathfloor(y.e / LOG_BASE);
-
- // If y is a small integer use the 'exponentiation by squaring' algorithm.
- if (e >= y.d.length - 1 && (k = yn < 0 ? -yn : yn) <= MAX_SAFE_INTEGER) {
- r = intPow(Ctor, x, k, pr);
- return y.s < 0 ? new Ctor(1).div(r) : finalise(r, pr, rm);
- }
-
- s = x.s;
-
- // if x is negative
- if (s < 0) {
-
- // if y is not an integer
- if (e < y.d.length - 1) return new Ctor(NaN);
-
- // Result is positive if x is negative and the last digit of integer y is even.
- if ((y.d[e] & 1) == 0) s = 1;
-
- // if x.eq(-1)
- if (x.e == 0 && x.d[0] == 1 && x.d.length == 1) {
- x.s = s;
- return x;
- }
- }
-
- // Estimate result exponent.
- // x^y = 10^e, where e = y * log10(x)
- // log10(x) = log10(x_significand) + x_exponent
- // log10(x_significand) = ln(x_significand) / ln(10)
- k = mathpow(+x, yn);
- e = k == 0 || !isFinite(k)
- ? mathfloor(yn * (Math.log('0.' + digitsToString(x.d)) / Math.LN10 + x.e + 1))
- : new Ctor(k + '').e;
-
- // Exponent estimate may be incorrect e.g. x: 0.999999999999999999, y: 2.29, e: 0, r.e: -1.
-
- // Overflow/underflow?
- if (e > Ctor.maxE + 1 || e < Ctor.minE - 1) return new Ctor(e > 0 ? s / 0 : 0);
-
- external = false;
- Ctor.rounding = x.s = 1;
-
- // Estimate the extra guard digits needed to ensure five correct rounding digits from
- // naturalLogarithm(x). Example of failure without these extra digits (precision: 10):
- // new Decimal(2.32456).pow('2087987436534566.46411')
- // should be 1.162377823e+764914905173815, but is 1.162355823e+764914905173815
- k = Math.min(12, (e + '').length);
-
- // r = x^y = exp(y*ln(x))
- r = naturalExponential(y.times(naturalLogarithm(x, pr + k)), pr);
-
- // r may be Infinity, e.g. (0.9999999999999999).pow(-1e+40)
- if (r.d) {
-
- // Truncate to the required precision plus five rounding digits.
- r = finalise(r, pr + 5, 1);
-
- // If the rounding digits are [49]9999 or [50]0000 increase the precision by 10 and recalculate
- // the result.
- if (checkRoundingDigits(r.d, pr, rm)) {
- e = pr + 10;
-
- // Truncate to the increased precision plus five rounding digits.
- r = finalise(naturalExponential(y.times(naturalLogarithm(x, e + k)), e), e + 5, 1);
-
- // Check for 14 nines from the 2nd rounding digit (the first rounding digit may be 4 or 9).
- if (+digitsToString(r.d).slice(pr + 1, pr + 15) + 1 == 1e14) {
- r = finalise(r, pr + 1, 0);
- }
- }
- }
-
- r.s = s;
- external = true;
- Ctor.rounding = rm;
-
- return finalise(r, pr, rm);
- };
-
-
- /*
- * Return a string representing the value of this Decimal rounded to `sd` significant digits
- * using rounding mode `rounding`.
- *
- * Return exponential notation if `sd` is less than the number of digits necessary to represent
- * the integer part of the value in normal notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
- P.toPrecision = function (sd, rm) {
- var str,
- x = this,
- Ctor = x.constructor;
-
- if (sd === void 0) {
- str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos);
- } else {
- checkInt32(sd, 1, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- x = finalise(new Ctor(x), sd, rm);
- str = finiteToString(x, sd <= x.e || x.e <= Ctor.toExpNeg, sd);
- }
-
- return x.isNeg() && !x.isZero() ? '-' + str : str;
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal rounded to a maximum of `sd`
- * significant digits using rounding mode `rm`, or to `precision` and `rounding` respectively if
- * omitted.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- * 'toSD() digits out of range: {sd}'
- * 'toSD() digits not an integer: {sd}'
- * 'toSD() rounding mode not an integer: {rm}'
- * 'toSD() rounding mode out of range: {rm}'
- *
- */
- P.toSignificantDigits = P.toSD = function (sd, rm) {
- var x = this,
- Ctor = x.constructor;
-
- if (sd === void 0) {
- sd = Ctor.precision;
- rm = Ctor.rounding;
- } else {
- checkInt32(sd, 1, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
- }
-
- return finalise(new Ctor(x), sd, rm);
- };
-
-
- /*
- * Return a string representing the value of this Decimal.
- *
- * Return exponential notation if this Decimal has a positive exponent equal to or greater than
- * `toExpPos`, or a negative exponent equal to or less than `toExpNeg`.
- *
- */
- P.toString = function () {
- var x = this,
- Ctor = x.constructor,
- str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos);
-
- return x.isNeg() && !x.isZero() ? '-' + str : str;
- };
-
-
- /*
- * Return a new Decimal whose value is the value of this Decimal truncated to a whole number.
- *
- */
- P.truncated = P.trunc = function () {
- return finalise(new this.constructor(this), this.e + 1, 1);
- };
-
-
- /*
- * Return a string representing the value of this Decimal.
- * Unlike `toString`, negative zero will include the minus sign.
- *
- */
- P.valueOf = P.toJSON = function () {
- var x = this,
- Ctor = x.constructor,
- str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos);
-
- return x.isNeg() ? '-' + str : str;
- };
-
-
- // Helper functions for Decimal.prototype (P) and/or Decimal methods, and their callers.
-
-
- /*
- * digitsToString P.cubeRoot, P.logarithm, P.squareRoot, P.toFraction, P.toPower,
- * finiteToString, naturalExponential, naturalLogarithm
- * checkInt32 P.toDecimalPlaces, P.toExponential, P.toFixed, P.toNearest,
- * P.toPrecision, P.toSignificantDigits, toStringBinary, random
- * checkRoundingDigits P.logarithm, P.toPower, naturalExponential, naturalLogarithm
- * convertBase toStringBinary, parseOther
- * cos P.cos
- * divide P.atanh, P.cubeRoot, P.dividedBy, P.dividedToIntegerBy,
- * P.logarithm, P.modulo, P.squareRoot, P.tan, P.tanh, P.toFraction,
- * P.toNearest, toStringBinary, naturalExponential, naturalLogarithm,
- * taylorSeries, atan2, parseOther
- * finalise P.absoluteValue, P.atan, P.atanh, P.ceil, P.cos, P.cosh,
- * P.cubeRoot, P.dividedToIntegerBy, P.floor, P.logarithm, P.minus,
- * P.modulo, P.negated, P.plus, P.round, P.sin, P.sinh, P.squareRoot,
- * P.tan, P.times, P.toDecimalPlaces, P.toExponential, P.toFixed,
- * P.toNearest, P.toPower, P.toPrecision, P.toSignificantDigits,
- * P.truncated, divide, getLn10, getPi, naturalExponential,
- * naturalLogarithm, ceil, floor, round, trunc
- * finiteToString P.toExponential, P.toFixed, P.toPrecision, P.toString, P.valueOf,
- * toStringBinary
- * getBase10Exponent P.minus, P.plus, P.times, parseOther
- * getLn10 P.logarithm, naturalLogarithm
- * getPi P.acos, P.asin, P.atan, toLessThanHalfPi, atan2
- * getPrecision P.precision, P.toFraction
- * getZeroString digitsToString, finiteToString
- * intPow P.toPower, parseOther
- * isOdd toLessThanHalfPi
- * maxOrMin max, min
- * naturalExponential P.naturalExponential, P.toPower
- * naturalLogarithm P.acosh, P.asinh, P.atanh, P.logarithm, P.naturalLogarithm,
- * P.toPower, naturalExponential
- * nonFiniteToString finiteToString, toStringBinary
- * parseDecimal Decimal
- * parseOther Decimal
- * sin P.sin
- * taylorSeries P.cosh, P.sinh, cos, sin
- * toLessThanHalfPi P.cos, P.sin
- * toStringBinary P.toBinary, P.toHexadecimal, P.toOctal
- * truncate intPow
- *
- * Throws: P.logarithm, P.precision, P.toFraction, checkInt32, getLn10, getPi,
- * naturalLogarithm, config, parseOther, random, Decimal
- */
-
-
- function digitsToString(d) {
- var i, k, ws,
- indexOfLastWord = d.length - 1,
- str = '',
- w = d[0];
-
- if (indexOfLastWord > 0) {
- str += w;
- for (i = 1; i < indexOfLastWord; i++) {
- ws = d[i] + '';
- k = LOG_BASE - ws.length;
- if (k) str += getZeroString(k);
- str += ws;
- }
-
- w = d[i];
- ws = w + '';
- k = LOG_BASE - ws.length;
- if (k) str += getZeroString(k);
- } else if (w === 0) {
- return '0';
- }
-
- // Remove trailing zeros of last w.
- for (; w % 10 === 0;) w /= 10;
-
- return str + w;
- }
-
-
- function checkInt32(i, min, max) {
- if (i !== ~~i || i < min || i > max) {
- throw Error(invalidArgument + i);
- }
- }
-
-
- /*
- * Check 5 rounding digits if `repeating` is null, 4 otherwise.
- * `repeating == null` if caller is `log` or `pow`,
- * `repeating != null` if caller is `naturalLogarithm` or `naturalExponential`.
- */
- function checkRoundingDigits(d, i, rm, repeating) {
- var di, k, r, rd;
-
- // Get the length of the first word of the array d.
- for (k = d[0]; k >= 10; k /= 10) --i;
-
- // Is the rounding digit in the first word of d?
- if (--i < 0) {
- i += LOG_BASE;
- di = 0;
- } else {
- di = Math.ceil((i + 1) / LOG_BASE);
- i %= LOG_BASE;
- }
-
- // i is the index (0 - 6) of the rounding digit.
- // E.g. if within the word 3487563 the first rounding digit is 5,
- // then i = 4, k = 1000, rd = 3487563 % 1000 = 563
- k = mathpow(10, LOG_BASE - i);
- rd = d[di] % k | 0;
-
- if (repeating == null) {
- if (i < 3) {
- if (i == 0) rd = rd / 100 | 0;
- else if (i == 1) rd = rd / 10 | 0;
- r = rm < 4 && rd == 99999 || rm > 3 && rd == 49999 || rd == 50000 || rd == 0;
- } else {
- r = (rm < 4 && rd + 1 == k || rm > 3 && rd + 1 == k / 2) &&
- (d[di + 1] / k / 100 | 0) == mathpow(10, i - 2) - 1 ||
- (rd == k / 2 || rd == 0) && (d[di + 1] / k / 100 | 0) == 0;
- }
- } else {
- if (i < 4) {
- if (i == 0) rd = rd / 1000 | 0;
- else if (i == 1) rd = rd / 100 | 0;
- else if (i == 2) rd = rd / 10 | 0;
- r = (repeating || rm < 4) && rd == 9999 || !repeating && rm > 3 && rd == 4999;
- } else {
- r = ((repeating || rm < 4) && rd + 1 == k ||
- (!repeating && rm > 3) && rd + 1 == k / 2) &&
- (d[di + 1] / k / 1000 | 0) == mathpow(10, i - 3) - 1;
- }
- }
-
- return r;
- }
-
-
- // Convert string of `baseIn` to an array of numbers of `baseOut`.
- // Eg. convertBase('255', 10, 16) returns [15, 15].
- // Eg. convertBase('ff', 16, 10) returns [2, 5, 5].
- function convertBase(str, baseIn, baseOut) {
- var j,
- arr = [0],
- arrL,
- i = 0,
- strL = str.length;
-
- for (; i < strL;) {
- for (arrL = arr.length; arrL--;) arr[arrL] *= baseIn;
- arr[0] += NUMERALS.indexOf(str.charAt(i++));
- for (j = 0; j < arr.length; j++) {
- if (arr[j] > baseOut - 1) {
- if (arr[j + 1] === void 0) arr[j + 1] = 0;
- arr[j + 1] += arr[j] / baseOut | 0;
- arr[j] %= baseOut;
- }
- }
- }
-
- return arr.reverse();
- }
-
-
- /*
- * cos(x) = 1 - x^2/2! + x^4/4! - ...
- * |x| < pi/2
- *
- */
- function cosine(Ctor, x) {
- var k, len, y;
-
- if (x.isZero()) return x;
-
- // Argument reduction: cos(4x) = 8*(cos^4(x) - cos^2(x)) + 1
- // i.e. cos(x) = 8*(cos^4(x/4) - cos^2(x/4)) + 1
-
- // Estimate the optimum number of times to use the argument reduction.
- len = x.d.length;
- if (len < 32) {
- k = Math.ceil(len / 3);
- y = (1 / tinyPow(4, k)).toString();
- } else {
- k = 16;
- y = '2.3283064365386962890625e-10';
- }
-
- Ctor.precision += k;
-
- x = taylorSeries(Ctor, 1, x.times(y), new Ctor(1));
-
- // Reverse argument reduction
- for (var i = k; i--;) {
- var cos2x = x.times(x);
- x = cos2x.times(cos2x).minus(cos2x).times(8).plus(1);
- }
-
- Ctor.precision -= k;
-
- return x;
- }
-
-
- /*
- * Perform division in the specified base.
- */
- var divide = (function () {
-
- // Assumes non-zero x and k, and hence non-zero result.
- function multiplyInteger(x, k, base) {
- var temp,
- carry = 0,
- i = x.length;
-
- for (x = x.slice(); i--;) {
- temp = x[i] * k + carry;
- x[i] = temp % base | 0;
- carry = temp / base | 0;
- }
-
- if (carry) x.unshift(carry);
-
- return x;
- }
-
- function compare(a, b, aL, bL) {
- var i, r;
-
- if (aL != bL) {
- r = aL > bL ? 1 : -1;
- } else {
- for (i = r = 0; i < aL; i++) {
- if (a[i] != b[i]) {
- r = a[i] > b[i] ? 1 : -1;
- break;
- }
- }
- }
-
- return r;
- }
-
- function subtract(a, b, aL, base) {
- var i = 0;
-
- // Subtract b from a.
- for (; aL--;) {
- a[aL] -= i;
- i = a[aL] < b[aL] ? 1 : 0;
- a[aL] = i * base + a[aL] - b[aL];
- }
-
- // Remove leading zeros.
- for (; !a[0] && a.length > 1;) a.shift();
- }
-
- return function (x, y, pr, rm, dp, base) {
- var cmp, e, i, k, logBase, more, prod, prodL, q, qd, rem, remL, rem0, sd, t, xi, xL, yd0,
- yL, yz,
- Ctor = x.constructor,
- sign = x.s == y.s ? 1 : -1,
- xd = x.d,
- yd = y.d;
-
- // Either NaN, Infinity or 0?
- if (!xd || !xd[0] || !yd || !yd[0]) {
-
- return new Ctor(// Return NaN if either NaN, or both Infinity or 0.
- !x.s || !y.s || (xd ? yd && xd[0] == yd[0] : !yd) ? NaN :
-
- // Return ±0 if x is 0 or y is ±Infinity, or return ±Infinity as y is 0.
- xd && xd[0] == 0 || !yd ? sign * 0 : sign / 0);
- }
-
- if (base) {
- logBase = 1;
- e = x.e - y.e;
- } else {
- base = BASE;
- logBase = LOG_BASE;
- e = mathfloor(x.e / logBase) - mathfloor(y.e / logBase);
- }
-
- yL = yd.length;
- xL = xd.length;
- q = new Ctor(sign);
- qd = q.d = [];
-
- // Result exponent may be one less than e.
- // The digit array of a Decimal from toStringBinary may have trailing zeros.
- for (i = 0; yd[i] == (xd[i] || 0); i++);
-
- if (yd[i] > (xd[i] || 0)) e--;
-
- if (pr == null) {
- sd = pr = Ctor.precision;
- rm = Ctor.rounding;
- } else if (dp) {
- sd = pr + (x.e - y.e) + 1;
- } else {
- sd = pr;
- }
-
- if (sd < 0) {
- qd.push(1);
- more = true;
- } else {
-
- // Convert precision in number of base 10 digits to base 1e7 digits.
- sd = sd / logBase + 2 | 0;
- i = 0;
-
- // divisor < 1e7
- if (yL == 1) {
- k = 0;
- yd = yd[0];
- sd++;
-
- // k is the carry.
- for (; (i < xL || k) && sd--; i++) {
- t = k * base + (xd[i] || 0);
- qd[i] = t / yd | 0;
- k = t % yd | 0;
- }
-
- more = k || i < xL;
-
- // divisor >= 1e7
- } else {
-
- // Normalise xd and yd so highest order digit of yd is >= base/2
- k = base / (yd[0] + 1) | 0;
-
- if (k > 1) {
- yd = multiplyInteger(yd, k, base);
- xd = multiplyInteger(xd, k, base);
- yL = yd.length;
- xL = xd.length;
- }
-
- xi = yL;
- rem = xd.slice(0, yL);
- remL = rem.length;
-
- // Add zeros to make remainder as long as divisor.
- for (; remL < yL;) rem[remL++] = 0;
-
- yz = yd.slice();
- yz.unshift(0);
- yd0 = yd[0];
-
- if (yd[1] >= base / 2) ++yd0;
-
- do {
- k = 0;
-
- // Compare divisor and remainder.
- cmp = compare(yd, rem, yL, remL);
-
- // If divisor < remainder.
- if (cmp < 0) {
-
- // Calculate trial digit, k.
- rem0 = rem[0];
- if (yL != remL) rem0 = rem0 * base + (rem[1] || 0);
-
- // k will be how many times the divisor goes into the current remainder.
- k = rem0 / yd0 | 0;
-
- // Algorithm:
- // 1. product = divisor * trial digit (k)
- // 2. if product > remainder: product -= divisor, k--
- // 3. remainder -= product
- // 4. if product was < remainder at 2:
- // 5. compare new remainder and divisor
- // 6. If remainder > divisor: remainder -= divisor, k++
-
- if (k > 1) {
- if (k >= base) k = base - 1;
-
- // product = divisor * trial digit.
- prod = multiplyInteger(yd, k, base);
- prodL = prod.length;
- remL = rem.length;
-
- // Compare product and remainder.
- cmp = compare(prod, rem, prodL, remL);
-
- // product > remainder.
- if (cmp == 1) {
- k--;
-
- // Subtract divisor from product.
- subtract(prod, yL < prodL ? yz : yd, prodL, base);
- }
- } else {
-
- // cmp is -1.
- // If k is 0, there is no need to compare yd and rem again below, so change cmp to 1
- // to avoid it. If k is 1 there is a need to compare yd and rem again below.
- if (k == 0) cmp = k = 1;
- prod = yd.slice();
- }
-
- prodL = prod.length;
- if (prodL < remL) prod.unshift(0);
-
- // Subtract product from remainder.
- subtract(rem, prod, remL, base);
-
- // If product was < previous remainder.
- if (cmp == -1) {
- remL = rem.length;
-
- // Compare divisor and new remainder.
- cmp = compare(yd, rem, yL, remL);
-
- // If divisor < new remainder, subtract divisor from remainder.
- if (cmp < 1) {
- k++;
-
- // Subtract divisor from remainder.
- subtract(rem, yL < remL ? yz : yd, remL, base);
- }
- }
-
- remL = rem.length;
- } else if (cmp === 0) {
- k++;
- rem = [0];
- } // if cmp === 1, k will be 0
-
- // Add the next digit, k, to the result array.
- qd[i++] = k;
-
- // Update the remainder.
- if (cmp && rem[0]) {
- rem[remL++] = xd[xi] || 0;
- } else {
- rem = [xd[xi]];
- remL = 1;
- }
-
- } while ((xi++ < xL || rem[0] !== void 0) && sd--);
-
- more = rem[0] !== void 0;
- }
-
- // Leading zero?
- if (!qd[0]) qd.shift();
- }
-
- // logBase is 1 when divide is being used for base conversion.
- if (logBase == 1) {
- q.e = e;
- inexact = more;
- } else {
-
- // To calculate q.e, first get the number of digits of qd[0].
- for (i = 1, k = qd[0]; k >= 10; k /= 10) i++;
- q.e = i + e * logBase - 1;
-
- finalise(q, dp ? pr + q.e + 1 : pr, rm, more);
- }
-
- return q;
- };
- })();
-
-
- /*
- * Round `x` to `sd` significant digits using rounding mode `rm`.
- * Check for over/under-flow.
- */
- function finalise(x, sd, rm, isTruncated) {
- var digits, i, j, k, rd, roundUp, w, xd, xdi,
- Ctor = x.constructor;
-
- // Don't round if sd is null or undefined.
- out: if (sd != null) {
- xd = x.d;
-
- // Infinity/NaN.
- if (!xd) return x;
-
- // rd: the rounding digit, i.e. the digit after the digit that may be rounded up.
- // w: the word of xd containing rd, a base 1e7 number.
- // xdi: the index of w within xd.
- // digits: the number of digits of w.
- // i: what would be the index of rd within w if all the numbers were 7 digits long (i.e. if
- // they had leading zeros)
- // j: if > 0, the actual index of rd within w (if < 0, rd is a leading zero).
-
- // Get the length of the first word of the digits array xd.
- for (digits = 1, k = xd[0]; k >= 10; k /= 10) digits++;
- i = sd - digits;
-
- // Is the rounding digit in the first word of xd?
- if (i < 0) {
- i += LOG_BASE;
- j = sd;
- w = xd[xdi = 0];
-
- // Get the rounding digit at index j of w.
- rd = w / mathpow(10, digits - j - 1) % 10 | 0;
- } else {
- xdi = Math.ceil((i + 1) / LOG_BASE);
- k = xd.length;
- if (xdi >= k) {
- if (isTruncated) {
-
- // Needed by `naturalExponential`, `naturalLogarithm` and `squareRoot`.
- for (; k++ <= xdi;) xd.push(0);
- w = rd = 0;
- digits = 1;
- i %= LOG_BASE;
- j = i - LOG_BASE + 1;
- } else {
- break out;
- }
- } else {
- w = k = xd[xdi];
-
- // Get the number of digits of w.
- for (digits = 1; k >= 10; k /= 10) digits++;
-
- // Get the index of rd within w.
- i %= LOG_BASE;
-
- // Get the index of rd within w, adjusted for leading zeros.
- // The number of leading zeros of w is given by LOG_BASE - digits.
- j = i - LOG_BASE + digits;
-
- // Get the rounding digit at index j of w.
- rd = j < 0 ? 0 : w / mathpow(10, digits - j - 1) % 10 | 0;
- }
- }
-
- // Are there any non-zero digits after the rounding digit?
- isTruncated = isTruncated || sd < 0 ||
- xd[xdi + 1] !== void 0 || (j < 0 ? w : w % mathpow(10, digits - j - 1));
-
- // The expression `w % mathpow(10, digits - j - 1)` returns all the digits of w to the right
- // of the digit at (left-to-right) index j, e.g. if w is 908714 and j is 2, the expression
- // will give 714.
-
- roundUp = rm < 4
- ? (rd || isTruncated) && (rm == 0 || rm == (x.s < 0 ? 3 : 2))
- : rd > 5 || rd == 5 && (rm == 4 || isTruncated || rm == 6 &&
-
- // Check whether the digit to the left of the rounding digit is odd.
- ((i > 0 ? j > 0 ? w / mathpow(10, digits - j) : 0 : xd[xdi - 1]) % 10) & 1 ||
- rm == (x.s < 0 ? 8 : 7));
-
- if (sd < 1 || !xd[0]) {
- xd.length = 0;
- if (roundUp) {
-
- // Convert sd to decimal places.
- sd -= x.e + 1;
-
- // 1, 0.1, 0.01, 0.001, 0.0001 etc.
- xd[0] = mathpow(10, (LOG_BASE - sd % LOG_BASE) % LOG_BASE);
- x.e = -sd || 0;
- } else {
-
- // Zero.
- xd[0] = x.e = 0;
- }
-
- return x;
- }
-
- // Remove excess digits.
- if (i == 0) {
- xd.length = xdi;
- k = 1;
- xdi--;
- } else {
- xd.length = xdi + 1;
- k = mathpow(10, LOG_BASE - i);
-
- // E.g. 56700 becomes 56000 if 7 is the rounding digit.
- // j > 0 means i > number of leading zeros of w.
- xd[xdi] = j > 0 ? (w / mathpow(10, digits - j) % mathpow(10, j) | 0) * k : 0;
- }
-
- if (roundUp) {
- for (;;) {
-
- // Is the digit to be rounded up in the first word of xd?
- if (xdi == 0) {
-
- // i will be the length of xd[0] before k is added.
- for (i = 1, j = xd[0]; j >= 10; j /= 10) i++;
- j = xd[0] += k;
- for (k = 1; j >= 10; j /= 10) k++;
-
- // if i != k the length has increased.
- if (i != k) {
- x.e++;
- if (xd[0] == BASE) xd[0] = 1;
- }
-
- break;
- } else {
- xd[xdi] += k;
- if (xd[xdi] != BASE) break;
- xd[xdi--] = 0;
- k = 1;
- }
- }
- }
-
- // Remove trailing zeros.
- for (i = xd.length; xd[--i] === 0;) xd.pop();
- }
-
- if (external) {
-
- // Overflow?
- if (x.e > Ctor.maxE) {
-
- // Infinity.
- x.d = null;
- x.e = NaN;
-
- // Underflow?
- } else if (x.e < Ctor.minE) {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- // Ctor.underflow = true;
- } // else Ctor.underflow = false;
- }
-
- return x;
- }
-
-
- function finiteToString(x, isExp, sd) {
- if (!x.isFinite()) return nonFiniteToString(x);
- var k,
- e = x.e,
- str = digitsToString(x.d),
- len = str.length;
-
- if (isExp) {
- if (sd && (k = sd - len) > 0) {
- str = str.charAt(0) + '.' + str.slice(1) + getZeroString(k);
- } else if (len > 1) {
- str = str.charAt(0) + '.' + str.slice(1);
- }
-
- str = str + (x.e < 0 ? 'e' : 'e+') + x.e;
- } else if (e < 0) {
- str = '0.' + getZeroString(-e - 1) + str;
- if (sd && (k = sd - len) > 0) str += getZeroString(k);
- } else if (e >= len) {
- str += getZeroString(e + 1 - len);
- if (sd && (k = sd - e - 1) > 0) str = str + '.' + getZeroString(k);
- } else {
- if ((k = e + 1) < len) str = str.slice(0, k) + '.' + str.slice(k);
- if (sd && (k = sd - len) > 0) {
- if (e + 1 === len) str += '.';
- str += getZeroString(k);
- }
- }
-
- return str;
- }
-
-
- // Calculate the base 10 exponent from the base 1e7 exponent.
- function getBase10Exponent(digits, e) {
- var w = digits[0];
-
- // Add the number of digits of the first word of the digits array.
- for ( e *= LOG_BASE; w >= 10; w /= 10) e++;
- return e;
- }
-
-
- function getLn10(Ctor, sd, pr) {
- if (sd > LN10_PRECISION) {
-
- // Reset global state in case the exception is caught.
- external = true;
- if (pr) Ctor.precision = pr;
- throw Error(precisionLimitExceeded);
- }
- return finalise(new Ctor(LN10), sd, 1, true);
- }
-
-
- function getPi(Ctor, sd, rm) {
- if (sd > PI_PRECISION) throw Error(precisionLimitExceeded);
- return finalise(new Ctor(PI), sd, rm, true);
- }
-
-
- function getPrecision(digits) {
- var w = digits.length - 1,
- len = w * LOG_BASE + 1;
-
- w = digits[w];
-
- // If non-zero...
- if (w) {
-
- // Subtract the number of trailing zeros of the last word.
- for (; w % 10 == 0; w /= 10) len--;
-
- // Add the number of digits of the first word.
- for (w = digits[0]; w >= 10; w /= 10) len++;
- }
-
- return len;
- }
-
-
- function getZeroString(k) {
- var zs = '';
- for (; k--;) zs += '0';
- return zs;
- }
-
-
- /*
- * Return a new Decimal whose value is the value of Decimal `x` to the power `n`, where `n` is an
- * integer of type number.
- *
- * Implements 'exponentiation by squaring'. Called by `pow` and `parseOther`.
- *
- */
- function intPow(Ctor, x, n, pr) {
- var isTruncated,
- r = new Ctor(1),
-
- // Max n of 9007199254740991 takes 53 loop iterations.
- // Maximum digits array length; leaves [28, 34] guard digits.
- k = Math.ceil(pr / LOG_BASE + 4);
-
- external = false;
-
- for (;;) {
- if (n % 2) {
- r = r.times(x);
- if (truncate(r.d, k)) isTruncated = true;
- }
-
- n = mathfloor(n / 2);
- if (n === 0) {
-
- // To ensure correct rounding when r.d is truncated, increment the last word if it is zero.
- n = r.d.length - 1;
- if (isTruncated && r.d[n] === 0) ++r.d[n];
- break;
- }
-
- x = x.times(x);
- truncate(x.d, k);
- }
-
- external = true;
-
- return r;
- }
-
-
- function isOdd(n) {
- return n.d[n.d.length - 1] & 1;
- }
-
-
- /*
- * Handle `max` (`n` is -1) and `min` (`n` is 1).
- */
- function maxOrMin(Ctor, args, n) {
- var k, y,
- x = new Ctor(args[0]),
- i = 0;
-
- for (; ++i < args.length;) {
- y = new Ctor(args[i]);
-
- // NaN?
- if (!y.s) {
- x = y;
- break;
- }
-
- k = x.cmp(y);
-
- if (k === n || k === 0 && x.s === n) {
- x = y;
- }
- }
-
- return x;
- }
-
-
- /*
- * Return a new Decimal whose value is the natural exponential of `x` rounded to `sd` significant
- * digits.
- *
- * Taylor/Maclaurin series.
- *
- * exp(x) = x^0/0! + x^1/1! + x^2/2! + x^3/3! + ...
- *
- * Argument reduction:
- * Repeat x = x / 32, k += 5, until |x| < 0.1
- * exp(x) = exp(x / 2^k)^(2^k)
- *
- * Previously, the argument was initially reduced by
- * exp(x) = exp(r) * 10^k where r = x - k * ln10, k = floor(x / ln10)
- * to first put r in the range [0, ln10], before dividing by 32 until |x| < 0.1, but this was
- * found to be slower than just dividing repeatedly by 32 as above.
- *
- * Max integer argument: exp('20723265836946413') = 6.3e+9000000000000000
- * Min integer argument: exp('-20723265836946411') = 1.2e-9000000000000000
- * (Math object integer min/max: Math.exp(709) = 8.2e+307, Math.exp(-745) = 5e-324)
- *
- * exp(Infinity) = Infinity
- * exp(-Infinity) = 0
- * exp(NaN) = NaN
- * exp(±0) = 1
- *
- * exp(x) is non-terminating for any finite, non-zero x.
- *
- * The result will always be correctly rounded.
- *
- */
- function naturalExponential(x, sd) {
- var denominator, guard, j, pow, sum, t, wpr,
- rep = 0,
- i = 0,
- k = 0,
- Ctor = x.constructor,
- rm = Ctor.rounding,
- pr = Ctor.precision;
-
- // 0/NaN/Infinity?
- if (!x.d || !x.d[0] || x.e > 17) {
-
- return new Ctor(x.d
- ? !x.d[0] ? 1 : x.s < 0 ? 0 : 1 / 0
- : x.s ? x.s < 0 ? 0 : x : 0 / 0);
- }
-
- if (sd == null) {
- external = false;
- wpr = pr;
- } else {
- wpr = sd;
- }
-
- t = new Ctor(0.03125);
-
- // while abs(x) >= 0.1
- while (x.e > -2) {
-
- // x = x / 2^5
- x = x.times(t);
- k += 5;
- }
-
- // Use 2 * log10(2^k) + 5 (empirically derived) to estimate the increase in precision
- // necessary to ensure the first 4 rounding digits are correct.
- guard = Math.log(mathpow(2, k)) / Math.LN10 * 2 + 5 | 0;
- wpr += guard;
- denominator = pow = sum = new Ctor(1);
- Ctor.precision = wpr;
-
- for (;;) {
- pow = finalise(pow.times(x), wpr, 1);
- denominator = denominator.times(++i);
- t = sum.plus(divide(pow, denominator, wpr, 1));
-
- if (digitsToString(t.d).slice(0, wpr) === digitsToString(sum.d).slice(0, wpr)) {
- j = k;
- while (j--) sum = finalise(sum.times(sum), wpr, 1);
-
- // Check to see if the first 4 rounding digits are [49]999.
- // If so, repeat the summation with a higher precision, otherwise
- // e.g. with precision: 18, rounding: 1
- // exp(18.404272462595034083567793919843761) = 98372560.1229999999 (should be 98372560.123)
- // `wpr - guard` is the index of first rounding digit.
- if (sd == null) {
-
- if (rep < 3 && checkRoundingDigits(sum.d, wpr - guard, rm, rep)) {
- Ctor.precision = wpr += 10;
- denominator = pow = t = new Ctor(1);
- i = 0;
- rep++;
- } else {
- return finalise(sum, Ctor.precision = pr, rm, external = true);
- }
- } else {
- Ctor.precision = pr;
- return sum;
- }
- }
-
- sum = t;
- }
- }
-
-
- /*
- * Return a new Decimal whose value is the natural logarithm of `x` rounded to `sd` significant
- * digits.
- *
- * ln(-n) = NaN
- * ln(0) = -Infinity
- * ln(-0) = -Infinity
- * ln(1) = 0
- * ln(Infinity) = Infinity
- * ln(-Infinity) = NaN
- * ln(NaN) = NaN
- *
- * ln(n) (n != 1) is non-terminating.
- *
- */
- function naturalLogarithm(y, sd) {
- var c, c0, denominator, e, numerator, rep, sum, t, wpr, x1, x2,
- n = 1,
- guard = 10,
- x = y,
- xd = x.d,
- Ctor = x.constructor,
- rm = Ctor.rounding,
- pr = Ctor.precision;
-
- // Is x negative or Infinity, NaN, 0 or 1?
- if (x.s < 0 || !xd || !xd[0] || !x.e && xd[0] == 1 && xd.length == 1) {
- return new Ctor(xd && !xd[0] ? -1 / 0 : x.s != 1 ? NaN : xd ? 0 : x);
- }
-
- if (sd == null) {
- external = false;
- wpr = pr;
- } else {
- wpr = sd;
- }
-
- Ctor.precision = wpr += guard;
- c = digitsToString(xd);
- c0 = c.charAt(0);
-
- if (Math.abs(e = x.e) < 1.5e15) {
-
- // Argument reduction.
- // The series converges faster the closer the argument is to 1, so using
- // ln(a^b) = b * ln(a), ln(a) = ln(a^b) / b
- // multiply the argument by itself until the leading digits of the significand are 7, 8, 9,
- // 10, 11, 12 or 13, recording the number of multiplications so the sum of the series can
- // later be divided by this number, then separate out the power of 10 using
- // ln(a*10^b) = ln(a) + b*ln(10).
-
- // max n is 21 (gives 0.9, 1.0 or 1.1) (9e15 / 21 = 4.2e14).
- //while (c0 < 9 && c0 != 1 || c0 == 1 && c.charAt(1) > 1) {
- // max n is 6 (gives 0.7 - 1.3)
- while (c0 < 7 && c0 != 1 || c0 == 1 && c.charAt(1) > 3) {
- x = x.times(y);
- c = digitsToString(x.d);
- c0 = c.charAt(0);
- n++;
- }
-
- e = x.e;
-
- if (c0 > 1) {
- x = new Ctor('0.' + c);
- e++;
- } else {
- x = new Ctor(c0 + '.' + c.slice(1));
- }
- } else {
-
- // The argument reduction method above may result in overflow if the argument y is a massive
- // number with exponent >= 1500000000000000 (9e15 / 6 = 1.5e15), so instead recall this
- // function using ln(x*10^e) = ln(x) + e*ln(10).
- t = getLn10(Ctor, wpr + 2, pr).times(e + '');
- x = naturalLogarithm(new Ctor(c0 + '.' + c.slice(1)), wpr - guard).plus(t);
- Ctor.precision = pr;
-
- return sd == null ? finalise(x, pr, rm, external = true) : x;
- }
-
- // x1 is x reduced to a value near 1.
- x1 = x;
-
- // Taylor series.
- // ln(y) = ln((1 + x)/(1 - x)) = 2(x + x^3/3 + x^5/5 + x^7/7 + ...)
- // where x = (y - 1)/(y + 1) (|x| < 1)
- sum = numerator = x = divide(x.minus(1), x.plus(1), wpr, 1);
- x2 = finalise(x.times(x), wpr, 1);
- denominator = 3;
-
- for (;;) {
- numerator = finalise(numerator.times(x2), wpr, 1);
- t = sum.plus(divide(numerator, new Ctor(denominator), wpr, 1));
-
- if (digitsToString(t.d).slice(0, wpr) === digitsToString(sum.d).slice(0, wpr)) {
- sum = sum.times(2);
-
- // Reverse the argument reduction. Check that e is not 0 because, besides preventing an
- // unnecessary calculation, -0 + 0 = +0 and to ensure correct rounding -0 needs to stay -0.
- if (e !== 0) sum = sum.plus(getLn10(Ctor, wpr + 2, pr).times(e + ''));
- sum = divide(sum, new Ctor(n), wpr, 1);
-
- // Is rm > 3 and the first 4 rounding digits 4999, or rm < 4 (or the summation has
- // been repeated previously) and the first 4 rounding digits 9999?
- // If so, restart the summation with a higher precision, otherwise
- // e.g. with precision: 12, rounding: 1
- // ln(135520028.6126091714265381533) = 18.7246299999 when it should be 18.72463.
- // `wpr - guard` is the index of first rounding digit.
- if (sd == null) {
- if (checkRoundingDigits(sum.d, wpr - guard, rm, rep)) {
- Ctor.precision = wpr += guard;
- t = numerator = x = divide(x1.minus(1), x1.plus(1), wpr, 1);
- x2 = finalise(x.times(x), wpr, 1);
- denominator = rep = 1;
- } else {
- return finalise(sum, Ctor.precision = pr, rm, external = true);
- }
- } else {
- Ctor.precision = pr;
- return sum;
- }
- }
-
- sum = t;
- denominator += 2;
- }
- }
-
-
- // ±Infinity, NaN.
- function nonFiniteToString(x) {
- // Unsigned.
- return String(x.s * x.s / 0);
- }
-
-
- /*
- * Parse the value of a new Decimal `x` from string `str`.
- */
- function parseDecimal(x, str) {
- var e, i, len;
-
- // TODO BigInt str: no need to check for decimal point, exponential form or leading zeros.
-
- // Decimal point?
- if ((e = str.indexOf('.')) > -1) str = str.replace('.', '');
-
- // Exponential form?
- if ((i = str.search(/e/i)) > 0) {
-
- // Determine exponent.
- if (e < 0) e = i;
- e += +str.slice(i + 1);
- str = str.substring(0, i);
- } else if (e < 0) {
-
- // Integer.
- e = str.length;
- }
-
- // Determine leading zeros.
- for (i = 0; str.charCodeAt(i) === 48; i++);
-
- // Determine trailing zeros.
- for (len = str.length; str.charCodeAt(len - 1) === 48; --len);
- str = str.slice(i, len);
-
- if (str) {
- len -= i;
- x.e = e = e - i - 1;
- x.d = [];
-
- // Transform base
-
- // e is the base 10 exponent.
- // i is where to slice str to get the first word of the digits array.
- i = (e + 1) % LOG_BASE;
- if (e < 0) i += LOG_BASE;
-
- if (i < len) {
- if (i) x.d.push(+str.slice(0, i));
- for (len -= LOG_BASE; i < len;) x.d.push(+str.slice(i, i += LOG_BASE));
- str = str.slice(i);
- i = LOG_BASE - str.length;
- } else {
- i -= len;
- }
-
- for (; i--;) str += '0';
- x.d.push(+str);
-
- if (external) {
-
- // Overflow?
- if (x.e > x.constructor.maxE) {
-
- // Infinity.
- x.d = null;
- x.e = NaN;
-
- // Underflow?
- } else if (x.e < x.constructor.minE) {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- // x.constructor.underflow = true;
- } // else x.constructor.underflow = false;
- }
- } else {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- }
-
- return x;
- }
-
-
- /*
- * Parse the value of a new Decimal `x` from a string `str`, which is not a decimal value.
- */
- function parseOther(x, str) {
- var base, Ctor, divisor, i, isFloat, len, p, xd, xe;
-
- if (str.indexOf('_') > -1) {
- str = str.replace(/(\d)_(?=\d)/g, '$1');
- if (isDecimal.test(str)) return parseDecimal(x, str);
- } else if (str === 'Infinity' || str === 'NaN') {
- if (!+str) x.s = NaN;
- x.e = NaN;
- x.d = null;
- return x;
- }
-
- if (isHex.test(str)) {
- base = 16;
- str = str.toLowerCase();
- } else if (isBinary.test(str)) {
- base = 2;
- } else if (isOctal.test(str)) {
- base = 8;
- } else {
- throw Error(invalidArgument + str);
- }
-
- // Is there a binary exponent part?
- i = str.search(/p/i);
-
- if (i > 0) {
- p = +str.slice(i + 1);
- str = str.substring(2, i);
- } else {
- str = str.slice(2);
- }
-
- // Convert `str` as an integer then divide the result by `base` raised to a power such that the
- // fraction part will be restored.
- i = str.indexOf('.');
- isFloat = i >= 0;
- Ctor = x.constructor;
-
- if (isFloat) {
- str = str.replace('.', '');
- len = str.length;
- i = len - i;
-
- // log[10](16) = 1.2041... , log[10](88) = 1.9444....
- divisor = intPow(Ctor, new Ctor(base), i, i * 2);
- }
-
- xd = convertBase(str, base, BASE);
- xe = xd.length - 1;
-
- // Remove trailing zeros.
- for (i = xe; xd[i] === 0; --i) xd.pop();
- if (i < 0) return new Ctor(x.s * 0);
- x.e = getBase10Exponent(xd, xe);
- x.d = xd;
- external = false;
-
- // At what precision to perform the division to ensure exact conversion?
- // maxDecimalIntegerPartDigitCount = ceil(log[10](b) * otherBaseIntegerPartDigitCount)
- // log[10](2) = 0.30103, log[10](8) = 0.90309, log[10](16) = 1.20412
- // E.g. ceil(1.2 * 3) = 4, so up to 4 decimal digits are needed to represent 3 hex int digits.
- // maxDecimalFractionPartDigitCount = {Hex:4|Oct:3|Bin:1} * otherBaseFractionPartDigitCount
- // Therefore using 4 * the number of digits of str will always be enough.
- if (isFloat) x = divide(x, divisor, len * 4);
-
- // Multiply by the binary exponent part if present.
- if (p) x = x.times(Math.abs(p) < 54 ? mathpow(2, p) : Decimal.pow(2, p));
- external = true;
-
- return x;
- }
-
-
- /*
- * sin(x) = x - x^3/3! + x^5/5! - ...
- * |x| < pi/2
- *
- */
- function sine(Ctor, x) {
- var k,
- len = x.d.length;
-
- if (len < 3) {
- return x.isZero() ? x : taylorSeries(Ctor, 2, x, x);
- }
-
- // Argument reduction: sin(5x) = 16*sin^5(x) - 20*sin^3(x) + 5*sin(x)
- // i.e. sin(x) = 16*sin^5(x/5) - 20*sin^3(x/5) + 5*sin(x/5)
- // and sin(x) = sin(x/5)(5 + sin^2(x/5)(16sin^2(x/5) - 20))
-
- // Estimate the optimum number of times to use the argument reduction.
- k = 1.4 * Math.sqrt(len);
- k = k > 16 ? 16 : k | 0;
-
- x = x.times(1 / tinyPow(5, k));
- x = taylorSeries(Ctor, 2, x, x);
-
- // Reverse argument reduction
- var sin2_x,
- d5 = new Ctor(5),
- d16 = new Ctor(16),
- d20 = new Ctor(20);
- for (; k--;) {
- sin2_x = x.times(x);
- x = x.times(d5.plus(sin2_x.times(d16.times(sin2_x).minus(d20))));
- }
-
- return x;
- }
-
-
- // Calculate Taylor series for `cos`, `cosh`, `sin` and `sinh`.
- function taylorSeries(Ctor, n, x, y, isHyperbolic) {
- var j, t, u, x2,
- i = 1,
- pr = Ctor.precision,
- k = Math.ceil(pr / LOG_BASE);
-
- external = false;
- x2 = x.times(x);
- u = new Ctor(y);
-
- for (;;) {
- t = divide(u.times(x2), new Ctor(n++ * n++), pr, 1);
- u = isHyperbolic ? y.plus(t) : y.minus(t);
- y = divide(t.times(x2), new Ctor(n++ * n++), pr, 1);
- t = u.plus(y);
-
- if (t.d[k] !== void 0) {
- for (j = k; t.d[j] === u.d[j] && j--;);
- if (j == -1) break;
- }
-
- j = u;
- u = y;
- y = t;
- t = j;
- i++;
- }
-
- external = true;
- t.d.length = k + 1;
-
- return t;
- }
-
-
- // Exponent e must be positive and non-zero.
- function tinyPow(b, e) {
- var n = b;
- while (--e) n *= b;
- return n;
- }
-
-
- // Return the absolute value of `x` reduced to less than or equal to half pi.
- function toLessThanHalfPi(Ctor, x) {
- var t,
- isNeg = x.s < 0,
- pi = getPi(Ctor, Ctor.precision, 1),
- halfPi = pi.times(0.5);
-
- x = x.abs();
-
- if (x.lte(halfPi)) {
- quadrant = isNeg ? 4 : 1;
- return x;
- }
-
- t = x.divToInt(pi);
-
- if (t.isZero()) {
- quadrant = isNeg ? 3 : 2;
- } else {
- x = x.minus(t.times(pi));
-
- // 0 <= x < pi
- if (x.lte(halfPi)) {
- quadrant = isOdd(t) ? (isNeg ? 2 : 3) : (isNeg ? 4 : 1);
- return x;
- }
-
- quadrant = isOdd(t) ? (isNeg ? 1 : 4) : (isNeg ? 3 : 2);
- }
-
- return x.minus(pi).abs();
- }
-
-
- /*
- * Return the value of Decimal `x` as a string in base `baseOut`.
- *
- * If the optional `sd` argument is present include a binary exponent suffix.
- */
- function toStringBinary(x, baseOut, sd, rm) {
- var base, e, i, k, len, roundUp, str, xd, y,
- Ctor = x.constructor,
- isExp = sd !== void 0;
-
- if (isExp) {
- checkInt32(sd, 1, MAX_DIGITS);
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
- } else {
- sd = Ctor.precision;
- rm = Ctor.rounding;
- }
-
- if (!x.isFinite()) {
- str = nonFiniteToString(x);
- } else {
- str = finiteToString(x);
- i = str.indexOf('.');
-
- // Use exponential notation according to `toExpPos` and `toExpNeg`? No, but if required:
- // maxBinaryExponent = floor((decimalExponent + 1) * log[2](10))
- // minBinaryExponent = floor(decimalExponent * log[2](10))
- // log[2](10) = 3.321928094887362347870319429489390175864
-
- if (isExp) {
- base = 2;
- if (baseOut == 16) {
- sd = sd * 4 - 3;
- } else if (baseOut == 8) {
- sd = sd * 3 - 2;
- }
- } else {
- base = baseOut;
- }
-
- // Convert the number as an integer then divide the result by its base raised to a power such
- // that the fraction part will be restored.
-
- // Non-integer.
- if (i >= 0) {
- str = str.replace('.', '');
- y = new Ctor(1);
- y.e = str.length - i;
- y.d = convertBase(finiteToString(y), 10, base);
- y.e = y.d.length;
- }
-
- xd = convertBase(str, 10, base);
- e = len = xd.length;
-
- // Remove trailing zeros.
- for (; xd[--len] == 0;) xd.pop();
-
- if (!xd[0]) {
- str = isExp ? '0p+0' : '0';
- } else {
- if (i < 0) {
- e--;
- } else {
- x = new Ctor(x);
- x.d = xd;
- x.e = e;
- x = divide(x, y, sd, rm, 0, base);
- xd = x.d;
- e = x.e;
- roundUp = inexact;
- }
-
- // The rounding digit, i.e. the digit after the digit that may be rounded up.
- i = xd[sd];
- k = base / 2;
- roundUp = roundUp || xd[sd + 1] !== void 0;
-
- roundUp = rm < 4
- ? (i !== void 0 || roundUp) && (rm === 0 || rm === (x.s < 0 ? 3 : 2))
- : i > k || i === k && (rm === 4 || roundUp || rm === 6 && xd[sd - 1] & 1 ||
- rm === (x.s < 0 ? 8 : 7));
-
- xd.length = sd;
-
- if (roundUp) {
-
- // Rounding up may mean the previous digit has to be rounded up and so on.
- for (; ++xd[--sd] > base - 1;) {
- xd[sd] = 0;
- if (!sd) {
- ++e;
- xd.unshift(1);
- }
- }
- }
-
- // Determine trailing zeros.
- for (len = xd.length; !xd[len - 1]; --len);
-
- // E.g. [4, 11, 15] becomes 4bf.
- for (i = 0, str = ''; i < len; i++) str += NUMERALS.charAt(xd[i]);
-
- // Add binary exponent suffix?
- if (isExp) {
- if (len > 1) {
- if (baseOut == 16 || baseOut == 8) {
- i = baseOut == 16 ? 4 : 3;
- for (--len; len % i; len++) str += '0';
- xd = convertBase(str, base, baseOut);
- for (len = xd.length; !xd[len - 1]; --len);
-
- // xd[0] will always be be 1
- for (i = 1, str = '1.'; i < len; i++) str += NUMERALS.charAt(xd[i]);
- } else {
- str = str.charAt(0) + '.' + str.slice(1);
- }
- }
-
- str = str + (e < 0 ? 'p' : 'p+') + e;
- } else if (e < 0) {
- for (; ++e;) str = '0' + str;
- str = '0.' + str;
- } else {
- if (++e > len) for (e -= len; e-- ;) str += '0';
- else if (e < len) str = str.slice(0, e) + '.' + str.slice(e);
- }
- }
-
- str = (baseOut == 16 ? '0x' : baseOut == 2 ? '0b' : baseOut == 8 ? '0o' : '') + str;
- }
-
- return x.s < 0 ? '-' + str : str;
- }
-
-
- // Does not strip trailing zeros.
- function truncate(arr, len) {
- if (arr.length > len) {
- arr.length = len;
- return true;
- }
- }
-
-
- // Decimal methods
-
-
- /*
- * abs
- * acos
- * acosh
- * add
- * asin
- * asinh
- * atan
- * atanh
- * atan2
- * cbrt
- * ceil
- * clamp
- * clone
- * config
- * cos
- * cosh
- * div
- * exp
- * floor
- * hypot
- * ln
- * log
- * log2
- * log10
- * max
- * min
- * mod
- * mul
- * pow
- * random
- * round
- * set
- * sign
- * sin
- * sinh
- * sqrt
- * sub
- * sum
- * tan
- * tanh
- * trunc
- */
-
-
- /*
- * Return a new Decimal whose value is the absolute value of `x`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function abs(x) {
- return new this(x).abs();
- }
-
-
- /*
- * Return a new Decimal whose value is the arccosine in radians of `x`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function acos(x) {
- return new this(x).acos();
- }
-
-
- /*
- * Return a new Decimal whose value is the inverse of the hyperbolic cosine of `x`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function acosh(x) {
- return new this(x).acosh();
- }
-
-
- /*
- * Return a new Decimal whose value is the sum of `x` and `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
- function add(x, y) {
- return new this(x).plus(y);
- }
-
-
- /*
- * Return a new Decimal whose value is the arcsine in radians of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function asin(x) {
- return new this(x).asin();
- }
-
-
- /*
- * Return a new Decimal whose value is the inverse of the hyperbolic sine of `x`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function asinh(x) {
- return new this(x).asinh();
- }
-
-
- /*
- * Return a new Decimal whose value is the arctangent in radians of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function atan(x) {
- return new this(x).atan();
- }
-
-
- /*
- * Return a new Decimal whose value is the inverse of the hyperbolic tangent of `x`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function atanh(x) {
- return new this(x).atanh();
- }
-
-
- /*
- * Return a new Decimal whose value is the arctangent in radians of `y/x` in the range -pi to pi
- * (inclusive), rounded to `precision` significant digits using rounding mode `rounding`.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-pi, pi]
- *
- * y {number|string|bigint|Decimal} The y-coordinate.
- * x {number|string|bigint|Decimal} The x-coordinate.
- *
- * atan2(±0, -0) = ±pi
- * atan2(±0, +0) = ±0
- * atan2(±0, -x) = ±pi for x > 0
- * atan2(±0, x) = ±0 for x > 0
- * atan2(-y, ±0) = -pi/2 for y > 0
- * atan2(y, ±0) = pi/2 for y > 0
- * atan2(±y, -Infinity) = ±pi for finite y > 0
- * atan2(±y, +Infinity) = ±0 for finite y > 0
- * atan2(±Infinity, x) = ±pi/2 for finite x
- * atan2(±Infinity, -Infinity) = ±3*pi/4
- * atan2(±Infinity, +Infinity) = ±pi/4
- * atan2(NaN, x) = NaN
- * atan2(y, NaN) = NaN
- *
- */
- function atan2(y, x) {
- y = new this(y);
- x = new this(x);
- var r,
- pr = this.precision,
- rm = this.rounding,
- wpr = pr + 4;
-
- // Either NaN
- if (!y.s || !x.s) {
- r = new this(NaN);
-
- // Both ±Infinity
- } else if (!y.d && !x.d) {
- r = getPi(this, wpr, 1).times(x.s > 0 ? 0.25 : 0.75);
- r.s = y.s;
-
- // x is ±Infinity or y is ±0
- } else if (!x.d || y.isZero()) {
- r = x.s < 0 ? getPi(this, pr, rm) : new this(0);
- r.s = y.s;
-
- // y is ±Infinity or x is ±0
- } else if (!y.d || x.isZero()) {
- r = getPi(this, wpr, 1).times(0.5);
- r.s = y.s;
-
- // Both non-zero and finite
- } else if (x.s < 0) {
- this.precision = wpr;
- this.rounding = 1;
- r = this.atan(divide(y, x, wpr, 1));
- x = getPi(this, wpr, 1);
- this.precision = pr;
- this.rounding = rm;
- r = y.s < 0 ? r.minus(x) : r.plus(x);
- } else {
- r = this.atan(divide(y, x, wpr, 1));
- }
-
- return r;
- }
-
-
- /*
- * Return a new Decimal whose value is the cube root of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function cbrt(x) {
- return new this(x).cbrt();
- }
-
-
- /*
- * Return a new Decimal whose value is `x` rounded to an integer using `ROUND_CEIL`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function ceil(x) {
- return finalise(x = new this(x), x.e + 1, 2);
- }
-
-
- /*
- * Return a new Decimal whose value is `x` clamped to the range delineated by `min` and `max`.
- *
- * x {number|string|bigint|Decimal}
- * min {number|string|bigint|Decimal}
- * max {number|string|bigint|Decimal}
- *
- */
- function clamp(x, min, max) {
- return new this(x).clamp(min, max);
- }
-
-
- /*
- * Configure global settings for a Decimal constructor.
- *
- * `obj` is an object with one or more of the following properties,
- *
- * precision {number}
- * rounding {number}
- * toExpNeg {number}
- * toExpPos {number}
- * maxE {number}
- * minE {number}
- * modulo {number}
- * crypto {boolean|number}
- * defaults {true}
- *
- * E.g. Decimal.config({ precision: 20, rounding: 4 })
- *
- */
- function config(obj) {
- if (!obj || typeof obj !== 'object') throw Error(decimalError + 'Object expected');
- var i, p, v,
- useDefaults = obj.defaults === true,
- ps = [
- 'precision', 1, MAX_DIGITS,
- 'rounding', 0, 8,
- 'toExpNeg', -EXP_LIMIT, 0,
- 'toExpPos', 0, EXP_LIMIT,
- 'maxE', 0, EXP_LIMIT,
- 'minE', -EXP_LIMIT, 0,
- 'modulo', 0, 9
- ];
-
- for (i = 0; i < ps.length; i += 3) {
- if (p = ps[i], useDefaults) this[p] = DEFAULTS[p];
- if ((v = obj[p]) !== void 0) {
- if (mathfloor(v) === v && v >= ps[i + 1] && v <= ps[i + 2]) this[p] = v;
- else throw Error(invalidArgument + p + ': ' + v);
- }
- }
-
- if (p = 'crypto', useDefaults) this[p] = DEFAULTS[p];
- if ((v = obj[p]) !== void 0) {
- if (v === true || v === false || v === 0 || v === 1) {
- if (v) {
- if (typeof crypto != 'undefined' && crypto &&
- (crypto.getRandomValues || crypto.randomBytes)) {
- this[p] = true;
- } else {
- throw Error(cryptoUnavailable);
- }
- } else {
- this[p] = false;
- }
- } else {
- throw Error(invalidArgument + p + ': ' + v);
- }
- }
-
- return this;
- }
-
-
- /*
- * Return a new Decimal whose value is the cosine of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function cos(x) {
- return new this(x).cos();
- }
-
-
- /*
- * Return a new Decimal whose value is the hyperbolic cosine of `x`, rounded to precision
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function cosh(x) {
- return new this(x).cosh();
- }
-
-
- /*
- * Create and return a Decimal constructor with the same configuration properties as this Decimal
- * constructor.
- *
- */
- function clone(obj) {
- var i, p, ps;
-
- /*
- * The Decimal constructor and exported function.
- * Return a new Decimal instance.
- *
- * v {number|string|bigint|Decimal} A numeric value.
- *
- */
- function Decimal(v) {
- var e, i, t,
- x = this;
-
- // Decimal called without new.
- if (!(x instanceof Decimal)) return new Decimal(v);
-
- // Retain a reference to this Decimal constructor, and shadow Decimal.prototype.constructor
- // which points to Object.
- x.constructor = Decimal;
-
- if (isDecimalInstance(v)) {
- x.s = v.s;
-
- if (external) {
- if (!v.d || v.e > Decimal.maxE) {
-
- // Infinity.
- x.e = NaN;
- x.d = null;
- } else if (v.e < Decimal.minE) {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- } else {
- x.e = v.e;
- x.d = v.d.slice();
- }
- } else {
- x.e = v.e;
- x.d = v.d ? v.d.slice() : v.d;
- }
-
- return;
- }
-
- t = typeof v;
-
- if (t === 'number') {
- if (v === 0) {
- x.s = 1 / v < 0 ? -1 : 1;
- x.e = 0;
- x.d = [0];
- return;
- }
-
- if (v < 0) {
- v = -v;
- x.s = -1;
- } else {
- x.s = 1;
- }
-
- // Fast path for small integers.
- if (v === ~~v && v < 1e7) {
- for (e = 0, i = v; i >= 10; i /= 10) e++;
-
- if (external) {
- if (e > Decimal.maxE) {
- x.e = NaN;
- x.d = null;
- } else if (e < Decimal.minE) {
- x.e = 0;
- x.d = [0];
- } else {
- x.e = e;
- x.d = [v];
- }
- } else {
- x.e = e;
- x.d = [v];
- }
-
- return;
- }
-
- // Infinity or NaN?
- if (v * 0 !== 0) {
- if (!v) x.s = NaN;
- x.e = NaN;
- x.d = null;
- return;
- }
-
- return parseDecimal(x, v.toString());
- }
-
- if (t === 'string') {
- if ((i = v.charCodeAt(0)) === 45) { // minus sign
- v = v.slice(1);
- x.s = -1;
- } else {
- if (i === 43) v = v.slice(1); // plus sign
- x.s = 1;
- }
-
- return isDecimal.test(v) ? parseDecimal(x, v) : parseOther(x, v);
- }
-
- if (t === 'bigint') {
- if (v < 0) {
- v = -v;
- x.s = -1;
- } else {
- x.s = 1;
- }
-
- return parseDecimal(x, v.toString());
- }
-
- throw Error(invalidArgument + v);
- }
-
- Decimal.prototype = P;
-
- Decimal.ROUND_UP = 0;
- Decimal.ROUND_DOWN = 1;
- Decimal.ROUND_CEIL = 2;
- Decimal.ROUND_FLOOR = 3;
- Decimal.ROUND_HALF_UP = 4;
- Decimal.ROUND_HALF_DOWN = 5;
- Decimal.ROUND_HALF_EVEN = 6;
- Decimal.ROUND_HALF_CEIL = 7;
- Decimal.ROUND_HALF_FLOOR = 8;
- Decimal.EUCLID = 9;
-
- Decimal.config = Decimal.set = config;
- Decimal.clone = clone;
- Decimal.isDecimal = isDecimalInstance;
-
- Decimal.abs = abs;
- Decimal.acos = acos;
- Decimal.acosh = acosh; // ES6
- Decimal.add = add;
- Decimal.asin = asin;
- Decimal.asinh = asinh; // ES6
- Decimal.atan = atan;
- Decimal.atanh = atanh; // ES6
- Decimal.atan2 = atan2;
- Decimal.cbrt = cbrt; // ES6
- Decimal.ceil = ceil;
- Decimal.clamp = clamp;
- Decimal.cos = cos;
- Decimal.cosh = cosh; // ES6
- Decimal.div = div;
- Decimal.exp = exp;
- Decimal.floor = floor;
- Decimal.hypot = hypot; // ES6
- Decimal.ln = ln;
- Decimal.log = log;
- Decimal.log10 = log10; // ES6
- Decimal.log2 = log2; // ES6
- Decimal.max = max;
- Decimal.min = min;
- Decimal.mod = mod;
- Decimal.mul = mul;
- Decimal.pow = pow;
- Decimal.random = random;
- Decimal.round = round;
- Decimal.sign = sign; // ES6
- Decimal.sin = sin;
- Decimal.sinh = sinh; // ES6
- Decimal.sqrt = sqrt;
- Decimal.sub = sub;
- Decimal.sum = sum;
- Decimal.tan = tan;
- Decimal.tanh = tanh; // ES6
- Decimal.trunc = trunc; // ES6
-
- if (obj === void 0) obj = {};
- if (obj) {
- if (obj.defaults !== true) {
- ps = ['precision', 'rounding', 'toExpNeg', 'toExpPos', 'maxE', 'minE', 'modulo', 'crypto'];
- for (i = 0; i < ps.length;) if (!obj.hasOwnProperty(p = ps[i++])) obj[p] = this[p];
- }
- }
-
- Decimal.config(obj);
-
- return Decimal;
- }
-
-
- /*
- * Return a new Decimal whose value is `x` divided by `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
- function div(x, y) {
- return new this(x).div(y);
- }
-
-
- /*
- * Return a new Decimal whose value is the natural exponential of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} The power to which to raise the base of the natural log.
- *
- */
- function exp(x) {
- return new this(x).exp();
- }
-
-
- /*
- * Return a new Decimal whose value is `x` round to an integer using `ROUND_FLOOR`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function floor(x) {
- return finalise(x = new this(x), x.e + 1, 3);
- }
-
-
- /*
- * Return a new Decimal whose value is the square root of the sum of the squares of the arguments,
- * rounded to `precision` significant digits using rounding mode `rounding`.
- *
- * hypot(a, b, ...) = sqrt(a^2 + b^2 + ...)
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
- function hypot() {
- var i, n,
- t = new this(0);
-
- external = false;
-
- for (i = 0; i < arguments.length;) {
- n = new this(arguments[i++]);
- if (!n.d) {
- if (n.s) {
- external = true;
- return new this(1 / 0);
- }
- t = n;
- } else if (t.d) {
- t = t.plus(n.times(n));
- }
- }
-
- external = true;
-
- return t.sqrt();
- }
-
-
- /*
- * Return true if object is a Decimal instance (where Decimal is any Decimal constructor),
- * otherwise return false.
- *
- */
- function isDecimalInstance(obj) {
- return obj instanceof Decimal || obj && obj.toStringTag === tag || false;
- }
-
-
- /*
- * Return a new Decimal whose value is the natural logarithm of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function ln(x) {
- return new this(x).ln();
- }
-
-
- /*
- * Return a new Decimal whose value is the log of `x` to the base `y`, or to base 10 if no base
- * is specified, rounded to `precision` significant digits using rounding mode `rounding`.
- *
- * log[y](x)
- *
- * x {number|string|bigint|Decimal} The argument of the logarithm.
- * y {number|string|bigint|Decimal} The base of the logarithm.
- *
- */
- function log(x, y) {
- return new this(x).log(y);
- }
-
-
- /*
- * Return a new Decimal whose value is the base 2 logarithm of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function log2(x) {
- return new this(x).log(2);
- }
-
-
- /*
- * Return a new Decimal whose value is the base 10 logarithm of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function log10(x) {
- return new this(x).log(10);
- }
-
-
- /*
- * Return a new Decimal whose value is the maximum of the arguments.
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
- function max() {
- return maxOrMin(this, arguments, -1);
- }
-
-
- /*
- * Return a new Decimal whose value is the minimum of the arguments.
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
- function min() {
- return maxOrMin(this, arguments, 1);
- }
-
-
- /*
- * Return a new Decimal whose value is `x` modulo `y`, rounded to `precision` significant digits
- * using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
- function mod(x, y) {
- return new this(x).mod(y);
- }
-
-
- /*
- * Return a new Decimal whose value is `x` multiplied by `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
- function mul(x, y) {
- return new this(x).mul(y);
- }
-
-
- /*
- * Return a new Decimal whose value is `x` raised to the power `y`, rounded to precision
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} The base.
- * y {number|string|bigint|Decimal} The exponent.
- *
- */
- function pow(x, y) {
- return new this(x).pow(y);
- }
-
-
- /*
- * Returns a new Decimal with a random value equal to or greater than 0 and less than 1, and with
- * `sd`, or `Decimal.precision` if `sd` is omitted, significant digits (or less if trailing zeros
- * are produced).
- *
- * [sd] {number} Significant digits. Integer, 0 to MAX_DIGITS inclusive.
- *
- */
- function random(sd) {
- var d, e, k, n,
- i = 0,
- r = new this(1),
- rd = [];
-
- if (sd === void 0) sd = this.precision;
- else checkInt32(sd, 1, MAX_DIGITS);
-
- k = Math.ceil(sd / LOG_BASE);
-
- if (!this.crypto) {
- for (; i < k;) rd[i++] = Math.random() * 1e7 | 0;
-
- // Browsers supporting crypto.getRandomValues.
- } else if (crypto.getRandomValues) {
- d = crypto.getRandomValues(new Uint32Array(k));
-
- for (; i < k;) {
- n = d[i];
-
- // 0 <= n < 4294967296
- // Probability n >= 4.29e9, is 4967296 / 4294967296 = 0.00116 (1 in 865).
- if (n >= 4.29e9) {
- d[i] = crypto.getRandomValues(new Uint32Array(1))[0];
- } else {
-
- // 0 <= n <= 4289999999
- // 0 <= (n % 1e7) <= 9999999
- rd[i++] = n % 1e7;
- }
- }
-
- // Node.js supporting crypto.randomBytes.
- } else if (crypto.randomBytes) {
-
- // buffer
- d = crypto.randomBytes(k *= 4);
-
- for (; i < k;) {
-
- // 0 <= n < 2147483648
- n = d[i] + (d[i + 1] << 8) + (d[i + 2] << 16) + ((d[i + 3] & 0x7f) << 24);
-
- // Probability n >= 2.14e9, is 7483648 / 2147483648 = 0.0035 (1 in 286).
- if (n >= 2.14e9) {
- crypto.randomBytes(4).copy(d, i);
- } else {
-
- // 0 <= n <= 2139999999
- // 0 <= (n % 1e7) <= 9999999
- rd.push(n % 1e7);
- i += 4;
- }
- }
-
- i = k / 4;
- } else {
- throw Error(cryptoUnavailable);
- }
-
- k = rd[--i];
- sd %= LOG_BASE;
-
- // Convert trailing digits to zeros according to sd.
- if (k && sd) {
- n = mathpow(10, LOG_BASE - sd);
- rd[i] = (k / n | 0) * n;
- }
-
- // Remove trailing words which are zero.
- for (; rd[i] === 0; i--) rd.pop();
-
- // Zero?
- if (i < 0) {
- e = 0;
- rd = [0];
- } else {
- e = -1;
-
- // Remove leading words which are zero and adjust exponent accordingly.
- for (; rd[0] === 0; e -= LOG_BASE) rd.shift();
-
- // Count the digits of the first word of rd to determine leading zeros.
- for (k = 1, n = rd[0]; n >= 10; n /= 10) k++;
-
- // Adjust the exponent for leading zeros of the first word of rd.
- if (k < LOG_BASE) e -= LOG_BASE - k;
- }
-
- r.e = e;
- r.d = rd;
-
- return r;
- }
-
-
- /*
- * Return a new Decimal whose value is `x` rounded to an integer using rounding mode `rounding`.
- *
- * To emulate `Math.round`, set rounding to 7 (ROUND_HALF_CEIL).
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function round(x) {
- return finalise(x = new this(x), x.e + 1, this.rounding);
- }
-
-
- /*
- * Return
- * 1 if x > 0,
- * -1 if x < 0,
- * 0 if x is 0,
- * -0 if x is -0,
- * NaN otherwise
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function sign(x) {
- x = new this(x);
- return x.d ? (x.d[0] ? x.s : 0 * x.s) : x.s || NaN;
- }
-
-
- /*
- * Return a new Decimal whose value is the sine of `x`, rounded to `precision` significant digits
- * using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function sin(x) {
- return new this(x).sin();
- }
-
-
- /*
- * Return a new Decimal whose value is the hyperbolic sine of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function sinh(x) {
- return new this(x).sinh();
- }
-
-
- /*
- * Return a new Decimal whose value is the square root of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function sqrt(x) {
- return new this(x).sqrt();
- }
-
-
- /*
- * Return a new Decimal whose value is `x` minus `y`, rounded to `precision` significant digits
- * using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
- function sub(x, y) {
- return new this(x).sub(y);
- }
-
-
- /*
- * Return a new Decimal whose value is the sum of the arguments, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * Only the result is rounded, not the intermediate calculations.
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
- function sum() {
- var i = 0,
- args = arguments,
- x = new this(args[i]);
-
- external = false;
- for (; x.s && ++i < args.length;) x = x.plus(args[i]);
- external = true;
-
- return finalise(x, this.precision, this.rounding);
- }
-
-
- /*
- * Return a new Decimal whose value is the tangent of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function tan(x) {
- return new this(x).tan();
- }
-
-
- /*
- * Return a new Decimal whose value is the hyperbolic tangent of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
- function tanh(x) {
- return new this(x).tanh();
- }
-
-
- /*
- * Return a new Decimal whose value is `x` truncated to an integer.
- *
- * x {number|string|bigint|Decimal}
- *
- */
- function trunc(x) {
- return finalise(x = new this(x), x.e + 1, 1);
- }
-
-
- // Create and configure initial Decimal constructor.
- Decimal = clone(DEFAULTS);
- Decimal.prototype.constructor = Decimal;
- Decimal['default'] = Decimal.Decimal = Decimal;
-
- // Create the internal constants from their string values.
- LN10 = new Decimal(LN10);
- PI = new Decimal(PI);
-
-
- // Export.
-
-
- // AMD.
- if (typeof define == 'function' && define.amd) {
- define(function () {
- return Decimal;
- });
-
- // Node and other environments that support module.exports.
- } else if (typeof module != 'undefined' && module.exports) {
- if (typeof Symbol == 'function' && typeof Symbol.iterator == 'symbol') {
- P[Symbol['for']('nodejs.util.inspect.custom')] = P.toString;
- P[Symbol.toStringTag] = 'Decimal';
- }
-
- module.exports = Decimal;
-
- // Browser.
- } else {
- if (!globalScope) {
- globalScope = typeof self != 'undefined' && self && self.self == self ? self : window;
- }
-
- noConflict = globalScope.Decimal;
- Decimal.noConflict = function () {
- globalScope.Decimal = noConflict;
- return Decimal;
- };
-
- globalScope.Decimal = Decimal;
- }
-})(this);
diff --git a/node_modules/decimal.js/decimal.mjs b/node_modules/decimal.js/decimal.mjs
deleted file mode 100644
index 18dc640..0000000
--- a/node_modules/decimal.js/decimal.mjs
+++ /dev/null
@@ -1,4914 +0,0 @@
-/*!
- * decimal.js v10.6.0
- * An arbitrary-precision Decimal type for JavaScript.
- * https://github.com/MikeMcl/decimal.js
- * Copyright (c) 2025 Michael Mclaughlin
- * MIT Licence
- */
-
-
-// ----------------------------------- EDITABLE DEFAULTS ------------------------------------ //
-
-
- // The maximum exponent magnitude.
- // The limit on the value of `toExpNeg`, `toExpPos`, `minE` and `maxE`.
-var EXP_LIMIT = 9e15, // 0 to 9e15
-
- // The limit on the value of `precision`, and on the value of the first argument to
- // `toDecimalPlaces`, `toExponential`, `toFixed`, `toPrecision` and `toSignificantDigits`.
- MAX_DIGITS = 1e9, // 0 to 1e9
-
- // Base conversion alphabet.
- NUMERALS = '0123456789abcdef',
-
- // The natural logarithm of 10 (1025 digits).
- LN10 = '2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220114804663715659121373450747856947683463616792101806445070648000277502684916746550586856935673420670581136429224554405758925724208241314695689016758940256776311356919292033376587141660230105703089634572075440370847469940168269282808481184289314848524948644871927809676271275775397027668605952496716674183485704422507197965004714951050492214776567636938662976979522110718264549734772662425709429322582798502585509785265383207606726317164309505995087807523710333101197857547331541421808427543863591778117054309827482385045648019095610299291824318237525357709750539565187697510374970888692180205189339507238539205144634197265287286965110862571492198849978748873771345686209167058',
-
- // Pi (1025 digits).
- PI = '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632789',
-
-
- // The initial configuration properties of the Decimal constructor.
- DEFAULTS = {
-
- // These values must be integers within the stated ranges (inclusive).
- // Most of these values can be changed at run-time using the `Decimal.config` method.
-
- // The maximum number of significant digits of the result of a calculation or base conversion.
- // E.g. `Decimal.config({ precision: 20 });`
- precision: 20, // 1 to MAX_DIGITS
-
- // The rounding mode used when rounding to `precision`.
- //
- // ROUND_UP 0 Away from zero.
- // ROUND_DOWN 1 Towards zero.
- // ROUND_CEIL 2 Towards +Infinity.
- // ROUND_FLOOR 3 Towards -Infinity.
- // ROUND_HALF_UP 4 Towards nearest neighbour. If equidistant, up.
- // ROUND_HALF_DOWN 5 Towards nearest neighbour. If equidistant, down.
- // ROUND_HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour.
- // ROUND_HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity.
- // ROUND_HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.
- //
- // E.g.
- // `Decimal.rounding = 4;`
- // `Decimal.rounding = Decimal.ROUND_HALF_UP;`
- rounding: 4, // 0 to 8
-
- // The modulo mode used when calculating the modulus: a mod n.
- // The quotient (q = a / n) is calculated according to the corresponding rounding mode.
- // The remainder (r) is calculated as: r = a - n * q.
- //
- // UP 0 The remainder is positive if the dividend is negative, else is negative.
- // DOWN 1 The remainder has the same sign as the dividend (JavaScript %).
- // FLOOR 3 The remainder has the same sign as the divisor (Python %).
- // HALF_EVEN 6 The IEEE 754 remainder function.
- // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). Always positive.
- //
- // Truncated division (1), floored division (3), the IEEE 754 remainder (6), and Euclidian
- // division (9) are commonly used for the modulus operation. The other rounding modes can also
- // be used, but they may not give useful results.
- modulo: 1, // 0 to 9
-
- // The exponent value at and beneath which `toString` returns exponential notation.
- // JavaScript numbers: -7
- toExpNeg: -7, // 0 to -EXP_LIMIT
-
- // The exponent value at and above which `toString` returns exponential notation.
- // JavaScript numbers: 21
- toExpPos: 21, // 0 to EXP_LIMIT
-
- // The minimum exponent value, beneath which underflow to zero occurs.
- // JavaScript numbers: -324 (5e-324)
- minE: -EXP_LIMIT, // -1 to -EXP_LIMIT
-
- // The maximum exponent value, above which overflow to Infinity occurs.
- // JavaScript numbers: 308 (1.7976931348623157e+308)
- maxE: EXP_LIMIT, // 1 to EXP_LIMIT
-
- // Whether to use cryptographically-secure random number generation, if available.
- crypto: false // true/false
- },
-
-
-// ----------------------------------- END OF EDITABLE DEFAULTS ------------------------------- //
-
-
- inexact, quadrant,
- external = true,
-
- decimalError = '[DecimalError] ',
- invalidArgument = decimalError + 'Invalid argument: ',
- precisionLimitExceeded = decimalError + 'Precision limit exceeded',
- cryptoUnavailable = decimalError + 'crypto unavailable',
- tag = '[object Decimal]',
-
- mathfloor = Math.floor,
- mathpow = Math.pow,
-
- isBinary = /^0b([01]+(\.[01]*)?|\.[01]+)(p[+-]?\d+)?$/i,
- isHex = /^0x([0-9a-f]+(\.[0-9a-f]*)?|\.[0-9a-f]+)(p[+-]?\d+)?$/i,
- isOctal = /^0o([0-7]+(\.[0-7]*)?|\.[0-7]+)(p[+-]?\d+)?$/i,
- isDecimal = /^(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,
-
- BASE = 1e7,
- LOG_BASE = 7,
- MAX_SAFE_INTEGER = 9007199254740991,
-
- LN10_PRECISION = LN10.length - 1,
- PI_PRECISION = PI.length - 1,
-
- // Decimal.prototype object
- P = { toStringTag: tag };
-
-
-// Decimal prototype methods
-
-
-/*
- * absoluteValue abs
- * ceil
- * clampedTo clamp
- * comparedTo cmp
- * cosine cos
- * cubeRoot cbrt
- * decimalPlaces dp
- * dividedBy div
- * dividedToIntegerBy divToInt
- * equals eq
- * floor
- * greaterThan gt
- * greaterThanOrEqualTo gte
- * hyperbolicCosine cosh
- * hyperbolicSine sinh
- * hyperbolicTangent tanh
- * inverseCosine acos
- * inverseHyperbolicCosine acosh
- * inverseHyperbolicSine asinh
- * inverseHyperbolicTangent atanh
- * inverseSine asin
- * inverseTangent atan
- * isFinite
- * isInteger isInt
- * isNaN
- * isNegative isNeg
- * isPositive isPos
- * isZero
- * lessThan lt
- * lessThanOrEqualTo lte
- * logarithm log
- * [maximum] [max]
- * [minimum] [min]
- * minus sub
- * modulo mod
- * naturalExponential exp
- * naturalLogarithm ln
- * negated neg
- * plus add
- * precision sd
- * round
- * sine sin
- * squareRoot sqrt
- * tangent tan
- * times mul
- * toBinary
- * toDecimalPlaces toDP
- * toExponential
- * toFixed
- * toFraction
- * toHexadecimal toHex
- * toNearest
- * toNumber
- * toOctal
- * toPower pow
- * toPrecision
- * toSignificantDigits toSD
- * toString
- * truncated trunc
- * valueOf toJSON
- */
-
-
-/*
- * Return a new Decimal whose value is the absolute value of this Decimal.
- *
- */
-P.absoluteValue = P.abs = function () {
- var x = new this.constructor(this);
- if (x.s < 0) x.s = 1;
- return finalise(x);
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the
- * direction of positive Infinity.
- *
- */
-P.ceil = function () {
- return finalise(new this.constructor(this), this.e + 1, 2);
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal clamped to the range
- * delineated by `min` and `max`.
- *
- * min {number|string|bigint|Decimal}
- * max {number|string|bigint|Decimal}
- *
- */
-P.clampedTo = P.clamp = function (min, max) {
- var k,
- x = this,
- Ctor = x.constructor;
- min = new Ctor(min);
- max = new Ctor(max);
- if (!min.s || !max.s) return new Ctor(NaN);
- if (min.gt(max)) throw Error(invalidArgument + max);
- k = x.cmp(min);
- return k < 0 ? min : x.cmp(max) > 0 ? max : new Ctor(x);
-};
-
-
-/*
- * Return
- * 1 if the value of this Decimal is greater than the value of `y`,
- * -1 if the value of this Decimal is less than the value of `y`,
- * 0 if they have the same value,
- * NaN if the value of either Decimal is NaN.
- *
- */
-P.comparedTo = P.cmp = function (y) {
- var i, j, xdL, ydL,
- x = this,
- xd = x.d,
- yd = (y = new x.constructor(y)).d,
- xs = x.s,
- ys = y.s;
-
- // Either NaN or ±Infinity?
- if (!xd || !yd) {
- return !xs || !ys ? NaN : xs !== ys ? xs : xd === yd ? 0 : !xd ^ xs < 0 ? 1 : -1;
- }
-
- // Either zero?
- if (!xd[0] || !yd[0]) return xd[0] ? xs : yd[0] ? -ys : 0;
-
- // Signs differ?
- if (xs !== ys) return xs;
-
- // Compare exponents.
- if (x.e !== y.e) return x.e > y.e ^ xs < 0 ? 1 : -1;
-
- xdL = xd.length;
- ydL = yd.length;
-
- // Compare digit by digit.
- for (i = 0, j = xdL < ydL ? xdL : ydL; i < j; ++i) {
- if (xd[i] !== yd[i]) return xd[i] > yd[i] ^ xs < 0 ? 1 : -1;
- }
-
- // Compare lengths.
- return xdL === ydL ? 0 : xdL > ydL ^ xs < 0 ? 1 : -1;
-};
-
-
-/*
- * Return a new Decimal whose value is the cosine of the value in radians of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-1, 1]
- *
- * cos(0) = 1
- * cos(-0) = 1
- * cos(Infinity) = NaN
- * cos(-Infinity) = NaN
- * cos(NaN) = NaN
- *
- */
-P.cosine = P.cos = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.d) return new Ctor(NaN);
-
- // cos(0) = cos(-0) = 1
- if (!x.d[0]) return new Ctor(1);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE;
- Ctor.rounding = 1;
-
- x = cosine(Ctor, toLessThanHalfPi(Ctor, x));
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(quadrant == 2 || quadrant == 3 ? x.neg() : x, pr, rm, true);
-};
-
-
-/*
- *
- * Return a new Decimal whose value is the cube root of the value of this Decimal, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * cbrt(0) = 0
- * cbrt(-0) = -0
- * cbrt(1) = 1
- * cbrt(-1) = -1
- * cbrt(N) = N
- * cbrt(-I) = -I
- * cbrt(I) = I
- *
- * Math.cbrt(x) = (x < 0 ? -Math.pow(-x, 1/3) : Math.pow(x, 1/3))
- *
- */
-P.cubeRoot = P.cbrt = function () {
- var e, m, n, r, rep, s, sd, t, t3, t3plusx,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite() || x.isZero()) return new Ctor(x);
- external = false;
-
- // Initial estimate.
- s = x.s * mathpow(x.s * x, 1 / 3);
-
- // Math.cbrt underflow/overflow?
- // Pass x to Math.pow as integer, then adjust the exponent of the result.
- if (!s || Math.abs(s) == 1 / 0) {
- n = digitsToString(x.d);
- e = x.e;
-
- // Adjust n exponent so it is a multiple of 3 away from x exponent.
- if (s = (e - n.length + 1) % 3) n += (s == 1 || s == -2 ? '0' : '00');
- s = mathpow(n, 1 / 3);
-
- // Rarely, e may be one less than the result exponent value.
- e = mathfloor((e + 1) / 3) - (e % 3 == (e < 0 ? -1 : 2));
-
- if (s == 1 / 0) {
- n = '5e' + e;
- } else {
- n = s.toExponential();
- n = n.slice(0, n.indexOf('e') + 1) + e;
- }
-
- r = new Ctor(n);
- r.s = x.s;
- } else {
- r = new Ctor(s.toString());
- }
-
- sd = (e = Ctor.precision) + 3;
-
- // Halley's method.
- // TODO? Compare Newton's method.
- for (;;) {
- t = r;
- t3 = t.times(t).times(t);
- t3plusx = t3.plus(x);
- r = divide(t3plusx.plus(x).times(t), t3plusx.plus(t3), sd + 2, 1);
-
- // TODO? Replace with for-loop and checkRoundingDigits.
- if (digitsToString(t.d).slice(0, sd) === (n = digitsToString(r.d)).slice(0, sd)) {
- n = n.slice(sd - 3, sd + 1);
-
- // The 4th rounding digit may be in error by -1 so if the 4 rounding digits are 9999 or 4999
- // , i.e. approaching a rounding boundary, continue the iteration.
- if (n == '9999' || !rep && n == '4999') {
-
- // On the first iteration only, check to see if rounding up gives the exact result as the
- // nines may infinitely repeat.
- if (!rep) {
- finalise(t, e + 1, 0);
-
- if (t.times(t).times(t).eq(x)) {
- r = t;
- break;
- }
- }
-
- sd += 4;
- rep = 1;
- } else {
-
- // If the rounding digits are null, 0{0,4} or 50{0,3}, check for an exact result.
- // If not, then there are further digits and m will be truthy.
- if (!+n || !+n.slice(1) && n.charAt(0) == '5') {
-
- // Truncate to the first rounding digit.
- finalise(r, e + 1, 1);
- m = !r.times(r).times(r).eq(x);
- }
-
- break;
- }
- }
- }
-
- external = true;
-
- return finalise(r, e, Ctor.rounding, m);
-};
-
-
-/*
- * Return the number of decimal places of the value of this Decimal.
- *
- */
-P.decimalPlaces = P.dp = function () {
- var w,
- d = this.d,
- n = NaN;
-
- if (d) {
- w = d.length - 1;
- n = (w - mathfloor(this.e / LOG_BASE)) * LOG_BASE;
-
- // Subtract the number of trailing zeros of the last word.
- w = d[w];
- if (w) for (; w % 10 == 0; w /= 10) n--;
- if (n < 0) n = 0;
- }
-
- return n;
-};
-
-
-/*
- * n / 0 = I
- * n / N = N
- * n / I = 0
- * 0 / n = 0
- * 0 / 0 = N
- * 0 / N = N
- * 0 / I = 0
- * N / n = N
- * N / 0 = N
- * N / N = N
- * N / I = N
- * I / n = I
- * I / 0 = I
- * I / N = N
- * I / I = N
- *
- * Return a new Decimal whose value is the value of this Decimal divided by `y`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- */
-P.dividedBy = P.div = function (y) {
- return divide(this, new this.constructor(y));
-};
-
-
-/*
- * Return a new Decimal whose value is the integer part of dividing the value of this Decimal
- * by the value of `y`, rounded to `precision` significant digits using rounding mode `rounding`.
- *
- */
-P.dividedToIntegerBy = P.divToInt = function (y) {
- var x = this,
- Ctor = x.constructor;
- return finalise(divide(x, new Ctor(y), 0, 1, 1), Ctor.precision, Ctor.rounding);
-};
-
-
-/*
- * Return true if the value of this Decimal is equal to the value of `y`, otherwise return false.
- *
- */
-P.equals = P.eq = function (y) {
- return this.cmp(y) === 0;
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the
- * direction of negative Infinity.
- *
- */
-P.floor = function () {
- return finalise(new this.constructor(this), this.e + 1, 3);
-};
-
-
-/*
- * Return true if the value of this Decimal is greater than the value of `y`, otherwise return
- * false.
- *
- */
-P.greaterThan = P.gt = function (y) {
- return this.cmp(y) > 0;
-};
-
-
-/*
- * Return true if the value of this Decimal is greater than or equal to the value of `y`,
- * otherwise return false.
- *
- */
-P.greaterThanOrEqualTo = P.gte = function (y) {
- var k = this.cmp(y);
- return k == 1 || k === 0;
-};
-
-
-/*
- * Return a new Decimal whose value is the hyperbolic cosine of the value in radians of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [1, Infinity]
- *
- * cosh(x) = 1 + x^2/2! + x^4/4! + x^6/6! + ...
- *
- * cosh(0) = 1
- * cosh(-0) = 1
- * cosh(Infinity) = Infinity
- * cosh(-Infinity) = Infinity
- * cosh(NaN) = NaN
- *
- * x time taken (ms) result
- * 1000 9 9.8503555700852349694e+433
- * 10000 25 4.4034091128314607936e+4342
- * 100000 171 1.4033316802130615897e+43429
- * 1000000 3817 1.5166076984010437725e+434294
- * 10000000 abandoned after 2 minute wait
- *
- * TODO? Compare performance of cosh(x) = 0.5 * (exp(x) + exp(-x))
- *
- */
-P.hyperbolicCosine = P.cosh = function () {
- var k, n, pr, rm, len,
- x = this,
- Ctor = x.constructor,
- one = new Ctor(1);
-
- if (!x.isFinite()) return new Ctor(x.s ? 1 / 0 : NaN);
- if (x.isZero()) return one;
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + 4;
- Ctor.rounding = 1;
- len = x.d.length;
-
- // Argument reduction: cos(4x) = 1 - 8cos^2(x) + 8cos^4(x) + 1
- // i.e. cos(x) = 1 - cos^2(x/4)(8 - 8cos^2(x/4))
-
- // Estimate the optimum number of times to use the argument reduction.
- // TODO? Estimation reused from cosine() and may not be optimal here.
- if (len < 32) {
- k = Math.ceil(len / 3);
- n = (1 / tinyPow(4, k)).toString();
- } else {
- k = 16;
- n = '2.3283064365386962890625e-10';
- }
-
- x = taylorSeries(Ctor, 1, x.times(n), new Ctor(1), true);
-
- // Reverse argument reduction
- var cosh2_x,
- i = k,
- d8 = new Ctor(8);
- for (; i--;) {
- cosh2_x = x.times(x);
- x = one.minus(cosh2_x.times(d8.minus(cosh2_x.times(d8))));
- }
-
- return finalise(x, Ctor.precision = pr, Ctor.rounding = rm, true);
-};
-
-
-/*
- * Return a new Decimal whose value is the hyperbolic sine of the value in radians of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-Infinity, Infinity]
- *
- * sinh(x) = x + x^3/3! + x^5/5! + x^7/7! + ...
- *
- * sinh(0) = 0
- * sinh(-0) = -0
- * sinh(Infinity) = Infinity
- * sinh(-Infinity) = -Infinity
- * sinh(NaN) = NaN
- *
- * x time taken (ms)
- * 10 2 ms
- * 100 5 ms
- * 1000 14 ms
- * 10000 82 ms
- * 100000 886 ms 1.4033316802130615897e+43429
- * 200000 2613 ms
- * 300000 5407 ms
- * 400000 8824 ms
- * 500000 13026 ms 8.7080643612718084129e+217146
- * 1000000 48543 ms
- *
- * TODO? Compare performance of sinh(x) = 0.5 * (exp(x) - exp(-x))
- *
- */
-P.hyperbolicSine = P.sinh = function () {
- var k, pr, rm, len,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite() || x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + 4;
- Ctor.rounding = 1;
- len = x.d.length;
-
- if (len < 3) {
- x = taylorSeries(Ctor, 2, x, x, true);
- } else {
-
- // Alternative argument reduction: sinh(3x) = sinh(x)(3 + 4sinh^2(x))
- // i.e. sinh(x) = sinh(x/3)(3 + 4sinh^2(x/3))
- // 3 multiplications and 1 addition
-
- // Argument reduction: sinh(5x) = sinh(x)(5 + sinh^2(x)(20 + 16sinh^2(x)))
- // i.e. sinh(x) = sinh(x/5)(5 + sinh^2(x/5)(20 + 16sinh^2(x/5)))
- // 4 multiplications and 2 additions
-
- // Estimate the optimum number of times to use the argument reduction.
- k = 1.4 * Math.sqrt(len);
- k = k > 16 ? 16 : k | 0;
-
- x = x.times(1 / tinyPow(5, k));
- x = taylorSeries(Ctor, 2, x, x, true);
-
- // Reverse argument reduction
- var sinh2_x,
- d5 = new Ctor(5),
- d16 = new Ctor(16),
- d20 = new Ctor(20);
- for (; k--;) {
- sinh2_x = x.times(x);
- x = x.times(d5.plus(sinh2_x.times(d16.times(sinh2_x).plus(d20))));
- }
- }
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(x, pr, rm, true);
-};
-
-
-/*
- * Return a new Decimal whose value is the hyperbolic tangent of the value in radians of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-1, 1]
- *
- * tanh(x) = sinh(x) / cosh(x)
- *
- * tanh(0) = 0
- * tanh(-0) = -0
- * tanh(Infinity) = 1
- * tanh(-Infinity) = -1
- * tanh(NaN) = NaN
- *
- */
-P.hyperbolicTangent = P.tanh = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(x.s);
- if (x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + 7;
- Ctor.rounding = 1;
-
- return divide(x.sinh(), x.cosh(), Ctor.precision = pr, Ctor.rounding = rm);
-};
-
-
-/*
- * Return a new Decimal whose value is the arccosine (inverse cosine) in radians of the value of
- * this Decimal.
- *
- * Domain: [-1, 1]
- * Range: [0, pi]
- *
- * acos(x) = pi/2 - asin(x)
- *
- * acos(0) = pi/2
- * acos(-0) = pi/2
- * acos(1) = 0
- * acos(-1) = pi
- * acos(1/2) = pi/3
- * acos(-1/2) = 2*pi/3
- * acos(|x| > 1) = NaN
- * acos(NaN) = NaN
- *
- */
-P.inverseCosine = P.acos = function () {
- var x = this,
- Ctor = x.constructor,
- k = x.abs().cmp(1),
- pr = Ctor.precision,
- rm = Ctor.rounding;
-
- if (k !== -1) {
- return k === 0
- // |x| is 1
- ? x.isNeg() ? getPi(Ctor, pr, rm) : new Ctor(0)
- // |x| > 1 or x is NaN
- : new Ctor(NaN);
- }
-
- if (x.isZero()) return getPi(Ctor, pr + 4, rm).times(0.5);
-
- // TODO? Special case acos(0.5) = pi/3 and acos(-0.5) = 2*pi/3
-
- Ctor.precision = pr + 6;
- Ctor.rounding = 1;
-
- // See https://github.com/MikeMcl/decimal.js/pull/217
- x = new Ctor(1).minus(x).div(x.plus(1)).sqrt().atan();
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.times(2);
-};
-
-
-/*
- * Return a new Decimal whose value is the inverse of the hyperbolic cosine in radians of the
- * value of this Decimal.
- *
- * Domain: [1, Infinity]
- * Range: [0, Infinity]
- *
- * acosh(x) = ln(x + sqrt(x^2 - 1))
- *
- * acosh(x < 1) = NaN
- * acosh(NaN) = NaN
- * acosh(Infinity) = Infinity
- * acosh(-Infinity) = NaN
- * acosh(0) = NaN
- * acosh(-0) = NaN
- * acosh(1) = 0
- * acosh(-1) = NaN
- *
- */
-P.inverseHyperbolicCosine = P.acosh = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (x.lte(1)) return new Ctor(x.eq(1) ? 0 : NaN);
- if (!x.isFinite()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(Math.abs(x.e), x.sd()) + 4;
- Ctor.rounding = 1;
- external = false;
-
- x = x.times(x).minus(1).sqrt().plus(x);
-
- external = true;
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.ln();
-};
-
-
-/*
- * Return a new Decimal whose value is the inverse of the hyperbolic sine in radians of the value
- * of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-Infinity, Infinity]
- *
- * asinh(x) = ln(x + sqrt(x^2 + 1))
- *
- * asinh(NaN) = NaN
- * asinh(Infinity) = Infinity
- * asinh(-Infinity) = -Infinity
- * asinh(0) = 0
- * asinh(-0) = -0
- *
- */
-P.inverseHyperbolicSine = P.asinh = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite() || x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + 2 * Math.max(Math.abs(x.e), x.sd()) + 6;
- Ctor.rounding = 1;
- external = false;
-
- x = x.times(x).plus(1).sqrt().plus(x);
-
- external = true;
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.ln();
-};
-
-
-/*
- * Return a new Decimal whose value is the inverse of the hyperbolic tangent in radians of the
- * value of this Decimal.
- *
- * Domain: [-1, 1]
- * Range: [-Infinity, Infinity]
- *
- * atanh(x) = 0.5 * ln((1 + x) / (1 - x))
- *
- * atanh(|x| > 1) = NaN
- * atanh(NaN) = NaN
- * atanh(Infinity) = NaN
- * atanh(-Infinity) = NaN
- * atanh(0) = 0
- * atanh(-0) = -0
- * atanh(1) = Infinity
- * atanh(-1) = -Infinity
- *
- */
-P.inverseHyperbolicTangent = P.atanh = function () {
- var pr, rm, wpr, xsd,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(NaN);
- if (x.e >= 0) return new Ctor(x.abs().eq(1) ? x.s / 0 : x.isZero() ? x : NaN);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- xsd = x.sd();
-
- if (Math.max(xsd, pr) < 2 * -x.e - 1) return finalise(new Ctor(x), pr, rm, true);
-
- Ctor.precision = wpr = xsd - x.e;
-
- x = divide(x.plus(1), new Ctor(1).minus(x), wpr + pr, 1);
-
- Ctor.precision = pr + 4;
- Ctor.rounding = 1;
-
- x = x.ln();
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.times(0.5);
-};
-
-
-/*
- * Return a new Decimal whose value is the arcsine (inverse sine) in radians of the value of this
- * Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-pi/2, pi/2]
- *
- * asin(x) = 2*atan(x/(1 + sqrt(1 - x^2)))
- *
- * asin(0) = 0
- * asin(-0) = -0
- * asin(1/2) = pi/6
- * asin(-1/2) = -pi/6
- * asin(1) = pi/2
- * asin(-1) = -pi/2
- * asin(|x| > 1) = NaN
- * asin(NaN) = NaN
- *
- * TODO? Compare performance of Taylor series.
- *
- */
-P.inverseSine = P.asin = function () {
- var halfPi, k,
- pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (x.isZero()) return new Ctor(x);
-
- k = x.abs().cmp(1);
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- if (k !== -1) {
-
- // |x| is 1
- if (k === 0) {
- halfPi = getPi(Ctor, pr + 4, rm).times(0.5);
- halfPi.s = x.s;
- return halfPi;
- }
-
- // |x| > 1 or x is NaN
- return new Ctor(NaN);
- }
-
- // TODO? Special case asin(1/2) = pi/6 and asin(-1/2) = -pi/6
-
- Ctor.precision = pr + 6;
- Ctor.rounding = 1;
-
- x = x.div(new Ctor(1).minus(x.times(x)).sqrt().plus(1)).atan();
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return x.times(2);
-};
-
-
-/*
- * Return a new Decimal whose value is the arctangent (inverse tangent) in radians of the value
- * of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-pi/2, pi/2]
- *
- * atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...
- *
- * atan(0) = 0
- * atan(-0) = -0
- * atan(1) = pi/4
- * atan(-1) = -pi/4
- * atan(Infinity) = pi/2
- * atan(-Infinity) = -pi/2
- * atan(NaN) = NaN
- *
- */
-P.inverseTangent = P.atan = function () {
- var i, j, k, n, px, t, r, wpr, x2,
- x = this,
- Ctor = x.constructor,
- pr = Ctor.precision,
- rm = Ctor.rounding;
-
- if (!x.isFinite()) {
- if (!x.s) return new Ctor(NaN);
- if (pr + 4 <= PI_PRECISION) {
- r = getPi(Ctor, pr + 4, rm).times(0.5);
- r.s = x.s;
- return r;
- }
- } else if (x.isZero()) {
- return new Ctor(x);
- } else if (x.abs().eq(1) && pr + 4 <= PI_PRECISION) {
- r = getPi(Ctor, pr + 4, rm).times(0.25);
- r.s = x.s;
- return r;
- }
-
- Ctor.precision = wpr = pr + 10;
- Ctor.rounding = 1;
-
- // TODO? if (x >= 1 && pr <= PI_PRECISION) atan(x) = halfPi * x.s - atan(1 / x);
-
- // Argument reduction
- // Ensure |x| < 0.42
- // atan(x) = 2 * atan(x / (1 + sqrt(1 + x^2)))
-
- k = Math.min(28, wpr / LOG_BASE + 2 | 0);
-
- for (i = k; i; --i) x = x.div(x.times(x).plus(1).sqrt().plus(1));
-
- external = false;
-
- j = Math.ceil(wpr / LOG_BASE);
- n = 1;
- x2 = x.times(x);
- r = new Ctor(x);
- px = x;
-
- // atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...
- for (; i !== -1;) {
- px = px.times(x2);
- t = r.minus(px.div(n += 2));
-
- px = px.times(x2);
- r = t.plus(px.div(n += 2));
-
- if (r.d[j] !== void 0) for (i = j; r.d[i] === t.d[i] && i--;);
- }
-
- if (k) r = r.times(2 << (k - 1));
-
- external = true;
-
- return finalise(r, Ctor.precision = pr, Ctor.rounding = rm, true);
-};
-
-
-/*
- * Return true if the value of this Decimal is a finite number, otherwise return false.
- *
- */
-P.isFinite = function () {
- return !!this.d;
-};
-
-
-/*
- * Return true if the value of this Decimal is an integer, otherwise return false.
- *
- */
-P.isInteger = P.isInt = function () {
- return !!this.d && mathfloor(this.e / LOG_BASE) > this.d.length - 2;
-};
-
-
-/*
- * Return true if the value of this Decimal is NaN, otherwise return false.
- *
- */
-P.isNaN = function () {
- return !this.s;
-};
-
-
-/*
- * Return true if the value of this Decimal is negative, otherwise return false.
- *
- */
-P.isNegative = P.isNeg = function () {
- return this.s < 0;
-};
-
-
-/*
- * Return true if the value of this Decimal is positive, otherwise return false.
- *
- */
-P.isPositive = P.isPos = function () {
- return this.s > 0;
-};
-
-
-/*
- * Return true if the value of this Decimal is 0 or -0, otherwise return false.
- *
- */
-P.isZero = function () {
- return !!this.d && this.d[0] === 0;
-};
-
-
-/*
- * Return true if the value of this Decimal is less than `y`, otherwise return false.
- *
- */
-P.lessThan = P.lt = function (y) {
- return this.cmp(y) < 0;
-};
-
-
-/*
- * Return true if the value of this Decimal is less than or equal to `y`, otherwise return false.
- *
- */
-P.lessThanOrEqualTo = P.lte = function (y) {
- return this.cmp(y) < 1;
-};
-
-
-/*
- * Return the logarithm of the value of this Decimal to the specified base, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * If no base is specified, return log[10](arg).
- *
- * log[base](arg) = ln(arg) / ln(base)
- *
- * The result will always be correctly rounded if the base of the log is 10, and 'almost always'
- * otherwise:
- *
- * Depending on the rounding mode, the result may be incorrectly rounded if the first fifteen
- * rounding digits are [49]99999999999999 or [50]00000000000000. In that case, the maximum error
- * between the result and the correctly rounded result will be one ulp (unit in the last place).
- *
- * log[-b](a) = NaN
- * log[0](a) = NaN
- * log[1](a) = NaN
- * log[NaN](a) = NaN
- * log[Infinity](a) = NaN
- * log[b](0) = -Infinity
- * log[b](-0) = -Infinity
- * log[b](-a) = NaN
- * log[b](1) = 0
- * log[b](Infinity) = Infinity
- * log[b](NaN) = NaN
- *
- * [base] {number|string|bigint|Decimal} The base of the logarithm.
- *
- */
-P.logarithm = P.log = function (base) {
- var isBase10, d, denominator, k, inf, num, sd, r,
- arg = this,
- Ctor = arg.constructor,
- pr = Ctor.precision,
- rm = Ctor.rounding,
- guard = 5;
-
- // Default base is 10.
- if (base == null) {
- base = new Ctor(10);
- isBase10 = true;
- } else {
- base = new Ctor(base);
- d = base.d;
-
- // Return NaN if base is negative, or non-finite, or is 0 or 1.
- if (base.s < 0 || !d || !d[0] || base.eq(1)) return new Ctor(NaN);
-
- isBase10 = base.eq(10);
- }
-
- d = arg.d;
-
- // Is arg negative, non-finite, 0 or 1?
- if (arg.s < 0 || !d || !d[0] || arg.eq(1)) {
- return new Ctor(d && !d[0] ? -1 / 0 : arg.s != 1 ? NaN : d ? 0 : 1 / 0);
- }
-
- // The result will have a non-terminating decimal expansion if base is 10 and arg is not an
- // integer power of 10.
- if (isBase10) {
- if (d.length > 1) {
- inf = true;
- } else {
- for (k = d[0]; k % 10 === 0;) k /= 10;
- inf = k !== 1;
- }
- }
-
- external = false;
- sd = pr + guard;
- num = naturalLogarithm(arg, sd);
- denominator = isBase10 ? getLn10(Ctor, sd + 10) : naturalLogarithm(base, sd);
-
- // The result will have 5 rounding digits.
- r = divide(num, denominator, sd, 1);
-
- // If at a rounding boundary, i.e. the result's rounding digits are [49]9999 or [50]0000,
- // calculate 10 further digits.
- //
- // If the result is known to have an infinite decimal expansion, repeat this until it is clear
- // that the result is above or below the boundary. Otherwise, if after calculating the 10
- // further digits, the last 14 are nines, round up and assume the result is exact.
- // Also assume the result is exact if the last 14 are zero.
- //
- // Example of a result that will be incorrectly rounded:
- // log[1048576](4503599627370502) = 2.60000000000000009610279511444746...
- // The above result correctly rounded using ROUND_CEIL to 1 decimal place should be 2.7, but it
- // will be given as 2.6 as there are 15 zeros immediately after the requested decimal place, so
- // the exact result would be assumed to be 2.6, which rounded using ROUND_CEIL to 1 decimal
- // place is still 2.6.
- if (checkRoundingDigits(r.d, k = pr, rm)) {
-
- do {
- sd += 10;
- num = naturalLogarithm(arg, sd);
- denominator = isBase10 ? getLn10(Ctor, sd + 10) : naturalLogarithm(base, sd);
- r = divide(num, denominator, sd, 1);
-
- if (!inf) {
-
- // Check for 14 nines from the 2nd rounding digit, as the first may be 4.
- if (+digitsToString(r.d).slice(k + 1, k + 15) + 1 == 1e14) {
- r = finalise(r, pr + 1, 0);
- }
-
- break;
- }
- } while (checkRoundingDigits(r.d, k += 10, rm));
- }
-
- external = true;
-
- return finalise(r, pr, rm);
-};
-
-
-/*
- * Return a new Decimal whose value is the maximum of the arguments and the value of this Decimal.
- *
- * arguments {number|string|bigint|Decimal}
- *
-P.max = function () {
- Array.prototype.push.call(arguments, this);
- return maxOrMin(this.constructor, arguments, -1);
-};
- */
-
-
-/*
- * Return a new Decimal whose value is the minimum of the arguments and the value of this Decimal.
- *
- * arguments {number|string|bigint|Decimal}
- *
-P.min = function () {
- Array.prototype.push.call(arguments, this);
- return maxOrMin(this.constructor, arguments, 1);
-};
- */
-
-
-/*
- * n - 0 = n
- * n - N = N
- * n - I = -I
- * 0 - n = -n
- * 0 - 0 = 0
- * 0 - N = N
- * 0 - I = -I
- * N - n = N
- * N - 0 = N
- * N - N = N
- * N - I = N
- * I - n = I
- * I - 0 = I
- * I - N = N
- * I - I = N
- *
- * Return a new Decimal whose value is the value of this Decimal minus `y`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- */
-P.minus = P.sub = function (y) {
- var d, e, i, j, k, len, pr, rm, xd, xe, xLTy, yd,
- x = this,
- Ctor = x.constructor;
-
- y = new Ctor(y);
-
- // If either is not finite...
- if (!x.d || !y.d) {
-
- // Return NaN if either is NaN.
- if (!x.s || !y.s) y = new Ctor(NaN);
-
- // Return y negated if x is finite and y is ±Infinity.
- else if (x.d) y.s = -y.s;
-
- // Return x if y is finite and x is ±Infinity.
- // Return x if both are ±Infinity with different signs.
- // Return NaN if both are ±Infinity with the same sign.
- else y = new Ctor(y.d || x.s !== y.s ? x : NaN);
-
- return y;
- }
-
- // If signs differ...
- if (x.s != y.s) {
- y.s = -y.s;
- return x.plus(y);
- }
-
- xd = x.d;
- yd = y.d;
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- // If either is zero...
- if (!xd[0] || !yd[0]) {
-
- // Return y negated if x is zero and y is non-zero.
- if (yd[0]) y.s = -y.s;
-
- // Return x if y is zero and x is non-zero.
- else if (xd[0]) y = new Ctor(x);
-
- // Return zero if both are zero.
- // From IEEE 754 (2008) 6.3: 0 - 0 = -0 - -0 = -0 when rounding to -Infinity.
- else return new Ctor(rm === 3 ? -0 : 0);
-
- return external ? finalise(y, pr, rm) : y;
- }
-
- // x and y are finite, non-zero numbers with the same sign.
-
- // Calculate base 1e7 exponents.
- e = mathfloor(y.e / LOG_BASE);
- xe = mathfloor(x.e / LOG_BASE);
-
- xd = xd.slice();
- k = xe - e;
-
- // If base 1e7 exponents differ...
- if (k) {
- xLTy = k < 0;
-
- if (xLTy) {
- d = xd;
- k = -k;
- len = yd.length;
- } else {
- d = yd;
- e = xe;
- len = xd.length;
- }
-
- // Numbers with massively different exponents would result in a very high number of
- // zeros needing to be prepended, but this can be avoided while still ensuring correct
- // rounding by limiting the number of zeros to `Math.ceil(pr / LOG_BASE) + 2`.
- i = Math.max(Math.ceil(pr / LOG_BASE), len) + 2;
-
- if (k > i) {
- k = i;
- d.length = 1;
- }
-
- // Prepend zeros to equalise exponents.
- d.reverse();
- for (i = k; i--;) d.push(0);
- d.reverse();
-
- // Base 1e7 exponents equal.
- } else {
-
- // Check digits to determine which is the bigger number.
-
- i = xd.length;
- len = yd.length;
- xLTy = i < len;
- if (xLTy) len = i;
-
- for (i = 0; i < len; i++) {
- if (xd[i] != yd[i]) {
- xLTy = xd[i] < yd[i];
- break;
- }
- }
-
- k = 0;
- }
-
- if (xLTy) {
- d = xd;
- xd = yd;
- yd = d;
- y.s = -y.s;
- }
-
- len = xd.length;
-
- // Append zeros to `xd` if shorter.
- // Don't add zeros to `yd` if shorter as subtraction only needs to start at `yd` length.
- for (i = yd.length - len; i > 0; --i) xd[len++] = 0;
-
- // Subtract yd from xd.
- for (i = yd.length; i > k;) {
-
- if (xd[--i] < yd[i]) {
- for (j = i; j && xd[--j] === 0;) xd[j] = BASE - 1;
- --xd[j];
- xd[i] += BASE;
- }
-
- xd[i] -= yd[i];
- }
-
- // Remove trailing zeros.
- for (; xd[--len] === 0;) xd.pop();
-
- // Remove leading zeros and adjust exponent accordingly.
- for (; xd[0] === 0; xd.shift()) --e;
-
- // Zero?
- if (!xd[0]) return new Ctor(rm === 3 ? -0 : 0);
-
- y.d = xd;
- y.e = getBase10Exponent(xd, e);
-
- return external ? finalise(y, pr, rm) : y;
-};
-
-
-/*
- * n % 0 = N
- * n % N = N
- * n % I = n
- * 0 % n = 0
- * -0 % n = -0
- * 0 % 0 = N
- * 0 % N = N
- * 0 % I = 0
- * N % n = N
- * N % 0 = N
- * N % N = N
- * N % I = N
- * I % n = N
- * I % 0 = N
- * I % N = N
- * I % I = N
- *
- * Return a new Decimal whose value is the value of this Decimal modulo `y`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * The result depends on the modulo mode.
- *
- */
-P.modulo = P.mod = function (y) {
- var q,
- x = this,
- Ctor = x.constructor;
-
- y = new Ctor(y);
-
- // Return NaN if x is ±Infinity or NaN, or y is NaN or ±0.
- if (!x.d || !y.s || y.d && !y.d[0]) return new Ctor(NaN);
-
- // Return x if y is ±Infinity or x is ±0.
- if (!y.d || x.d && !x.d[0]) {
- return finalise(new Ctor(x), Ctor.precision, Ctor.rounding);
- }
-
- // Prevent rounding of intermediate calculations.
- external = false;
-
- if (Ctor.modulo == 9) {
-
- // Euclidian division: q = sign(y) * floor(x / abs(y))
- // result = x - q * y where 0 <= result < abs(y)
- q = divide(x, y.abs(), 0, 3, 1);
- q.s *= y.s;
- } else {
- q = divide(x, y, 0, Ctor.modulo, 1);
- }
-
- q = q.times(y);
-
- external = true;
-
- return x.minus(q);
-};
-
-
-/*
- * Return a new Decimal whose value is the natural exponential of the value of this Decimal,
- * i.e. the base e raised to the power the value of this Decimal, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- */
-P.naturalExponential = P.exp = function () {
- return naturalExponential(this);
-};
-
-
-/*
- * Return a new Decimal whose value is the natural logarithm of the value of this Decimal,
- * rounded to `precision` significant digits using rounding mode `rounding`.
- *
- */
-P.naturalLogarithm = P.ln = function () {
- return naturalLogarithm(this);
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal negated, i.e. as if multiplied by
- * -1.
- *
- */
-P.negated = P.neg = function () {
- var x = new this.constructor(this);
- x.s = -x.s;
- return finalise(x);
-};
-
-
-/*
- * n + 0 = n
- * n + N = N
- * n + I = I
- * 0 + n = n
- * 0 + 0 = 0
- * 0 + N = N
- * 0 + I = I
- * N + n = N
- * N + 0 = N
- * N + N = N
- * N + I = N
- * I + n = I
- * I + 0 = I
- * I + N = N
- * I + I = I
- *
- * Return a new Decimal whose value is the value of this Decimal plus `y`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- */
-P.plus = P.add = function (y) {
- var carry, d, e, i, k, len, pr, rm, xd, yd,
- x = this,
- Ctor = x.constructor;
-
- y = new Ctor(y);
-
- // If either is not finite...
- if (!x.d || !y.d) {
-
- // Return NaN if either is NaN.
- if (!x.s || !y.s) y = new Ctor(NaN);
-
- // Return x if y is finite and x is ±Infinity.
- // Return x if both are ±Infinity with the same sign.
- // Return NaN if both are ±Infinity with different signs.
- // Return y if x is finite and y is ±Infinity.
- else if (!x.d) y = new Ctor(y.d || x.s === y.s ? x : NaN);
-
- return y;
- }
-
- // If signs differ...
- if (x.s != y.s) {
- y.s = -y.s;
- return x.minus(y);
- }
-
- xd = x.d;
- yd = y.d;
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- // If either is zero...
- if (!xd[0] || !yd[0]) {
-
- // Return x if y is zero.
- // Return y if y is non-zero.
- if (!yd[0]) y = new Ctor(x);
-
- return external ? finalise(y, pr, rm) : y;
- }
-
- // x and y are finite, non-zero numbers with the same sign.
-
- // Calculate base 1e7 exponents.
- k = mathfloor(x.e / LOG_BASE);
- e = mathfloor(y.e / LOG_BASE);
-
- xd = xd.slice();
- i = k - e;
-
- // If base 1e7 exponents differ...
- if (i) {
-
- if (i < 0) {
- d = xd;
- i = -i;
- len = yd.length;
- } else {
- d = yd;
- e = k;
- len = xd.length;
- }
-
- // Limit number of zeros prepended to max(ceil(pr / LOG_BASE), len) + 1.
- k = Math.ceil(pr / LOG_BASE);
- len = k > len ? k + 1 : len + 1;
-
- if (i > len) {
- i = len;
- d.length = 1;
- }
-
- // Prepend zeros to equalise exponents. Note: Faster to use reverse then do unshifts.
- d.reverse();
- for (; i--;) d.push(0);
- d.reverse();
- }
-
- len = xd.length;
- i = yd.length;
-
- // If yd is longer than xd, swap xd and yd so xd points to the longer array.
- if (len - i < 0) {
- i = len;
- d = yd;
- yd = xd;
- xd = d;
- }
-
- // Only start adding at yd.length - 1 as the further digits of xd can be left as they are.
- for (carry = 0; i;) {
- carry = (xd[--i] = xd[i] + yd[i] + carry) / BASE | 0;
- xd[i] %= BASE;
- }
-
- if (carry) {
- xd.unshift(carry);
- ++e;
- }
-
- // Remove trailing zeros.
- // No need to check for zero, as +x + +y != 0 && -x + -y != 0
- for (len = xd.length; xd[--len] == 0;) xd.pop();
-
- y.d = xd;
- y.e = getBase10Exponent(xd, e);
-
- return external ? finalise(y, pr, rm) : y;
-};
-
-
-/*
- * Return the number of significant digits of the value of this Decimal.
- *
- * [z] {boolean|number} Whether to count integer-part trailing zeros: true, false, 1 or 0.
- *
- */
-P.precision = P.sd = function (z) {
- var k,
- x = this;
-
- if (z !== void 0 && z !== !!z && z !== 1 && z !== 0) throw Error(invalidArgument + z);
-
- if (x.d) {
- k = getPrecision(x.d);
- if (z && x.e + 1 > k) k = x.e + 1;
- } else {
- k = NaN;
- }
-
- return k;
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal rounded to a whole number using
- * rounding mode `rounding`.
- *
- */
-P.round = function () {
- var x = this,
- Ctor = x.constructor;
-
- return finalise(new Ctor(x), x.e + 1, Ctor.rounding);
-};
-
-
-/*
- * Return a new Decimal whose value is the sine of the value in radians of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-1, 1]
- *
- * sin(x) = x - x^3/3! + x^5/5! - ...
- *
- * sin(0) = 0
- * sin(-0) = -0
- * sin(Infinity) = NaN
- * sin(-Infinity) = NaN
- * sin(NaN) = NaN
- *
- */
-P.sine = P.sin = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(NaN);
- if (x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE;
- Ctor.rounding = 1;
-
- x = sine(Ctor, toLessThanHalfPi(Ctor, x));
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(quadrant > 2 ? x.neg() : x, pr, rm, true);
-};
-
-
-/*
- * Return a new Decimal whose value is the square root of this Decimal, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * sqrt(-n) = N
- * sqrt(N) = N
- * sqrt(-I) = N
- * sqrt(I) = I
- * sqrt(0) = 0
- * sqrt(-0) = -0
- *
- */
-P.squareRoot = P.sqrt = function () {
- var m, n, sd, r, rep, t,
- x = this,
- d = x.d,
- e = x.e,
- s = x.s,
- Ctor = x.constructor;
-
- // Negative/NaN/Infinity/zero?
- if (s !== 1 || !d || !d[0]) {
- return new Ctor(!s || s < 0 && (!d || d[0]) ? NaN : d ? x : 1 / 0);
- }
-
- external = false;
-
- // Initial estimate.
- s = Math.sqrt(+x);
-
- // Math.sqrt underflow/overflow?
- // Pass x to Math.sqrt as integer, then adjust the exponent of the result.
- if (s == 0 || s == 1 / 0) {
- n = digitsToString(d);
-
- if ((n.length + e) % 2 == 0) n += '0';
- s = Math.sqrt(n);
- e = mathfloor((e + 1) / 2) - (e < 0 || e % 2);
-
- if (s == 1 / 0) {
- n = '5e' + e;
- } else {
- n = s.toExponential();
- n = n.slice(0, n.indexOf('e') + 1) + e;
- }
-
- r = new Ctor(n);
- } else {
- r = new Ctor(s.toString());
- }
-
- sd = (e = Ctor.precision) + 3;
-
- // Newton-Raphson iteration.
- for (;;) {
- t = r;
- r = t.plus(divide(x, t, sd + 2, 1)).times(0.5);
-
- // TODO? Replace with for-loop and checkRoundingDigits.
- if (digitsToString(t.d).slice(0, sd) === (n = digitsToString(r.d)).slice(0, sd)) {
- n = n.slice(sd - 3, sd + 1);
-
- // The 4th rounding digit may be in error by -1 so if the 4 rounding digits are 9999 or
- // 4999, i.e. approaching a rounding boundary, continue the iteration.
- if (n == '9999' || !rep && n == '4999') {
-
- // On the first iteration only, check to see if rounding up gives the exact result as the
- // nines may infinitely repeat.
- if (!rep) {
- finalise(t, e + 1, 0);
-
- if (t.times(t).eq(x)) {
- r = t;
- break;
- }
- }
-
- sd += 4;
- rep = 1;
- } else {
-
- // If the rounding digits are null, 0{0,4} or 50{0,3}, check for an exact result.
- // If not, then there are further digits and m will be truthy.
- if (!+n || !+n.slice(1) && n.charAt(0) == '5') {
-
- // Truncate to the first rounding digit.
- finalise(r, e + 1, 1);
- m = !r.times(r).eq(x);
- }
-
- break;
- }
- }
- }
-
- external = true;
-
- return finalise(r, e, Ctor.rounding, m);
-};
-
-
-/*
- * Return a new Decimal whose value is the tangent of the value in radians of this Decimal.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-Infinity, Infinity]
- *
- * tan(0) = 0
- * tan(-0) = -0
- * tan(Infinity) = NaN
- * tan(-Infinity) = NaN
- * tan(NaN) = NaN
- *
- */
-P.tangent = P.tan = function () {
- var pr, rm,
- x = this,
- Ctor = x.constructor;
-
- if (!x.isFinite()) return new Ctor(NaN);
- if (x.isZero()) return new Ctor(x);
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
- Ctor.precision = pr + 10;
- Ctor.rounding = 1;
-
- x = x.sin();
- x.s = 1;
- x = divide(x, new Ctor(1).minus(x.times(x)).sqrt(), pr + 10, 0);
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return finalise(quadrant == 2 || quadrant == 4 ? x.neg() : x, pr, rm, true);
-};
-
-
-/*
- * n * 0 = 0
- * n * N = N
- * n * I = I
- * 0 * n = 0
- * 0 * 0 = 0
- * 0 * N = N
- * 0 * I = N
- * N * n = N
- * N * 0 = N
- * N * N = N
- * N * I = N
- * I * n = I
- * I * 0 = N
- * I * N = N
- * I * I = I
- *
- * Return a new Decimal whose value is this Decimal times `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- */
-P.times = P.mul = function (y) {
- var carry, e, i, k, r, rL, t, xdL, ydL,
- x = this,
- Ctor = x.constructor,
- xd = x.d,
- yd = (y = new Ctor(y)).d;
-
- y.s *= x.s;
-
- // If either is NaN, ±Infinity or ±0...
- if (!xd || !xd[0] || !yd || !yd[0]) {
-
- return new Ctor(!y.s || xd && !xd[0] && !yd || yd && !yd[0] && !xd
-
- // Return NaN if either is NaN.
- // Return NaN if x is ±0 and y is ±Infinity, or y is ±0 and x is ±Infinity.
- ? NaN
-
- // Return ±Infinity if either is ±Infinity.
- // Return ±0 if either is ±0.
- : !xd || !yd ? y.s / 0 : y.s * 0);
- }
-
- e = mathfloor(x.e / LOG_BASE) + mathfloor(y.e / LOG_BASE);
- xdL = xd.length;
- ydL = yd.length;
-
- // Ensure xd points to the longer array.
- if (xdL < ydL) {
- r = xd;
- xd = yd;
- yd = r;
- rL = xdL;
- xdL = ydL;
- ydL = rL;
- }
-
- // Initialise the result array with zeros.
- r = [];
- rL = xdL + ydL;
- for (i = rL; i--;) r.push(0);
-
- // Multiply!
- for (i = ydL; --i >= 0;) {
- carry = 0;
- for (k = xdL + i; k > i;) {
- t = r[k] + yd[i] * xd[k - i - 1] + carry;
- r[k--] = t % BASE | 0;
- carry = t / BASE | 0;
- }
-
- r[k] = (r[k] + carry) % BASE | 0;
- }
-
- // Remove trailing zeros.
- for (; !r[--rL];) r.pop();
-
- if (carry) ++e;
- else r.shift();
-
- y.d = r;
- y.e = getBase10Exponent(r, e);
-
- return external ? finalise(y, Ctor.precision, Ctor.rounding) : y;
-};
-
-
-/*
- * Return a string representing the value of this Decimal in base 2, round to `sd` significant
- * digits using rounding mode `rm`.
- *
- * If the optional `sd` argument is present then return binary exponential notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
-P.toBinary = function (sd, rm) {
- return toStringBinary(this, 2, sd, rm);
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal rounded to a maximum of `dp`
- * decimal places using rounding mode `rm` or `rounding` if `rm` is omitted.
- *
- * If `dp` is omitted, return a new Decimal whose value is the value of this Decimal.
- *
- * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
-P.toDecimalPlaces = P.toDP = function (dp, rm) {
- var x = this,
- Ctor = x.constructor;
-
- x = new Ctor(x);
- if (dp === void 0) return x;
-
- checkInt32(dp, 0, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- return finalise(x, dp + x.e + 1, rm);
-};
-
-
-/*
- * Return a string representing the value of this Decimal in exponential notation rounded to
- * `dp` fixed decimal places using rounding mode `rounding`.
- *
- * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
-P.toExponential = function (dp, rm) {
- var str,
- x = this,
- Ctor = x.constructor;
-
- if (dp === void 0) {
- str = finiteToString(x, true);
- } else {
- checkInt32(dp, 0, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- x = finalise(new Ctor(x), dp + 1, rm);
- str = finiteToString(x, true, dp + 1);
- }
-
- return x.isNeg() && !x.isZero() ? '-' + str : str;
-};
-
-
-/*
- * Return a string representing the value of this Decimal in normal (fixed-point) notation to
- * `dp` fixed decimal places and rounded using rounding mode `rm` or `rounding` if `rm` is
- * omitted.
- *
- * As with JavaScript numbers, (-0).toFixed(0) is '0', but e.g. (-0.00001).toFixed(0) is '-0'.
- *
- * [dp] {number} Decimal places. Integer, 0 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- * (-0).toFixed(0) is '0', but (-0.1).toFixed(0) is '-0'.
- * (-0).toFixed(1) is '0.0', but (-0.01).toFixed(1) is '-0.0'.
- * (-0).toFixed(3) is '0.000'.
- * (-0.5).toFixed(0) is '-0'.
- *
- */
-P.toFixed = function (dp, rm) {
- var str, y,
- x = this,
- Ctor = x.constructor;
-
- if (dp === void 0) {
- str = finiteToString(x);
- } else {
- checkInt32(dp, 0, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- y = finalise(new Ctor(x), dp + x.e + 1, rm);
- str = finiteToString(y, false, dp + y.e + 1);
- }
-
- // To determine whether to add the minus sign look at the value before it was rounded,
- // i.e. look at `x` rather than `y`.
- return x.isNeg() && !x.isZero() ? '-' + str : str;
-};
-
-
-/*
- * Return an array representing the value of this Decimal as a simple fraction with an integer
- * numerator and an integer denominator.
- *
- * The denominator will be a positive non-zero value less than or equal to the specified maximum
- * denominator. If a maximum denominator is not specified, the denominator will be the lowest
- * value necessary to represent the number exactly.
- *
- * [maxD] {number|string|bigint|Decimal} Maximum denominator. Integer >= 1 and < Infinity.
- *
- */
-P.toFraction = function (maxD) {
- var d, d0, d1, d2, e, k, n, n0, n1, pr, q, r,
- x = this,
- xd = x.d,
- Ctor = x.constructor;
-
- if (!xd) return new Ctor(x);
-
- n1 = d0 = new Ctor(1);
- d1 = n0 = new Ctor(0);
-
- d = new Ctor(d1);
- e = d.e = getPrecision(xd) - x.e - 1;
- k = e % LOG_BASE;
- d.d[0] = mathpow(10, k < 0 ? LOG_BASE + k : k);
-
- if (maxD == null) {
-
- // d is 10**e, the minimum max-denominator needed.
- maxD = e > 0 ? d : n1;
- } else {
- n = new Ctor(maxD);
- if (!n.isInt() || n.lt(n1)) throw Error(invalidArgument + n);
- maxD = n.gt(d) ? (e > 0 ? d : n1) : n;
- }
-
- external = false;
- n = new Ctor(digitsToString(xd));
- pr = Ctor.precision;
- Ctor.precision = e = xd.length * LOG_BASE * 2;
-
- for (;;) {
- q = divide(n, d, 0, 1, 1);
- d2 = d0.plus(q.times(d1));
- if (d2.cmp(maxD) == 1) break;
- d0 = d1;
- d1 = d2;
- d2 = n1;
- n1 = n0.plus(q.times(d2));
- n0 = d2;
- d2 = d;
- d = n.minus(q.times(d2));
- n = d2;
- }
-
- d2 = divide(maxD.minus(d0), d1, 0, 1, 1);
- n0 = n0.plus(d2.times(n1));
- d0 = d0.plus(d2.times(d1));
- n0.s = n1.s = x.s;
-
- // Determine which fraction is closer to x, n0/d0 or n1/d1?
- r = divide(n1, d1, e, 1).minus(x).abs().cmp(divide(n0, d0, e, 1).minus(x).abs()) < 1
- ? [n1, d1] : [n0, d0];
-
- Ctor.precision = pr;
- external = true;
-
- return r;
-};
-
-
-/*
- * Return a string representing the value of this Decimal in base 16, round to `sd` significant
- * digits using rounding mode `rm`.
- *
- * If the optional `sd` argument is present then return binary exponential notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
-P.toHexadecimal = P.toHex = function (sd, rm) {
- return toStringBinary(this, 16, sd, rm);
-};
-
-
-/*
- * Returns a new Decimal whose value is the nearest multiple of `y` in the direction of rounding
- * mode `rm`, or `Decimal.rounding` if `rm` is omitted, to the value of this Decimal.
- *
- * The return value will always have the same sign as this Decimal, unless either this Decimal
- * or `y` is NaN, in which case the return value will be also be NaN.
- *
- * The return value is not affected by the value of `precision`.
- *
- * y {number|string|bigint|Decimal} The magnitude to round to a multiple of.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- * 'toNearest() rounding mode not an integer: {rm}'
- * 'toNearest() rounding mode out of range: {rm}'
- *
- */
-P.toNearest = function (y, rm) {
- var x = this,
- Ctor = x.constructor;
-
- x = new Ctor(x);
-
- if (y == null) {
-
- // If x is not finite, return x.
- if (!x.d) return x;
-
- y = new Ctor(1);
- rm = Ctor.rounding;
- } else {
- y = new Ctor(y);
- if (rm === void 0) {
- rm = Ctor.rounding;
- } else {
- checkInt32(rm, 0, 8);
- }
-
- // If x is not finite, return x if y is not NaN, else NaN.
- if (!x.d) return y.s ? x : y;
-
- // If y is not finite, return Infinity with the sign of x if y is Infinity, else NaN.
- if (!y.d) {
- if (y.s) y.s = x.s;
- return y;
- }
- }
-
- // If y is not zero, calculate the nearest multiple of y to x.
- if (y.d[0]) {
- external = false;
- x = divide(x, y, 0, rm, 1).times(y);
- external = true;
- finalise(x);
-
- // If y is zero, return zero with the sign of x.
- } else {
- y.s = x.s;
- x = y;
- }
-
- return x;
-};
-
-
-/*
- * Return the value of this Decimal converted to a number primitive.
- * Zero keeps its sign.
- *
- */
-P.toNumber = function () {
- return +this;
-};
-
-
-/*
- * Return a string representing the value of this Decimal in base 8, round to `sd` significant
- * digits using rounding mode `rm`.
- *
- * If the optional `sd` argument is present then return binary exponential notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
-P.toOctal = function (sd, rm) {
- return toStringBinary(this, 8, sd, rm);
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal raised to the power `y`, rounded
- * to `precision` significant digits using rounding mode `rounding`.
- *
- * ECMAScript compliant.
- *
- * pow(x, NaN) = NaN
- * pow(x, ±0) = 1
-
- * pow(NaN, non-zero) = NaN
- * pow(abs(x) > 1, +Infinity) = +Infinity
- * pow(abs(x) > 1, -Infinity) = +0
- * pow(abs(x) == 1, ±Infinity) = NaN
- * pow(abs(x) < 1, +Infinity) = +0
- * pow(abs(x) < 1, -Infinity) = +Infinity
- * pow(+Infinity, y > 0) = +Infinity
- * pow(+Infinity, y < 0) = +0
- * pow(-Infinity, odd integer > 0) = -Infinity
- * pow(-Infinity, even integer > 0) = +Infinity
- * pow(-Infinity, odd integer < 0) = -0
- * pow(-Infinity, even integer < 0) = +0
- * pow(+0, y > 0) = +0
- * pow(+0, y < 0) = +Infinity
- * pow(-0, odd integer > 0) = -0
- * pow(-0, even integer > 0) = +0
- * pow(-0, odd integer < 0) = -Infinity
- * pow(-0, even integer < 0) = +Infinity
- * pow(finite x < 0, finite non-integer) = NaN
- *
- * For non-integer or very large exponents pow(x, y) is calculated using
- *
- * x^y = exp(y*ln(x))
- *
- * Assuming the first 15 rounding digits are each equally likely to be any digit 0-9, the
- * probability of an incorrectly rounded result
- * P([49]9{14} | [50]0{14}) = 2 * 0.2 * 10^-14 = 4e-15 = 1/2.5e+14
- * i.e. 1 in 250,000,000,000,000
- *
- * If a result is incorrectly rounded the maximum error will be 1 ulp (unit in last place).
- *
- * y {number|string|bigint|Decimal} The power to which to raise this Decimal.
- *
- */
-P.toPower = P.pow = function (y) {
- var e, k, pr, r, rm, s,
- x = this,
- Ctor = x.constructor,
- yn = +(y = new Ctor(y));
-
- // Either ±Infinity, NaN or ±0?
- if (!x.d || !y.d || !x.d[0] || !y.d[0]) return new Ctor(mathpow(+x, yn));
-
- x = new Ctor(x);
-
- if (x.eq(1)) return x;
-
- pr = Ctor.precision;
- rm = Ctor.rounding;
-
- if (y.eq(1)) return finalise(x, pr, rm);
-
- // y exponent
- e = mathfloor(y.e / LOG_BASE);
-
- // If y is a small integer use the 'exponentiation by squaring' algorithm.
- if (e >= y.d.length - 1 && (k = yn < 0 ? -yn : yn) <= MAX_SAFE_INTEGER) {
- r = intPow(Ctor, x, k, pr);
- return y.s < 0 ? new Ctor(1).div(r) : finalise(r, pr, rm);
- }
-
- s = x.s;
-
- // if x is negative
- if (s < 0) {
-
- // if y is not an integer
- if (e < y.d.length - 1) return new Ctor(NaN);
-
- // Result is positive if x is negative and the last digit of integer y is even.
- if ((y.d[e] & 1) == 0) s = 1;
-
- // if x.eq(-1)
- if (x.e == 0 && x.d[0] == 1 && x.d.length == 1) {
- x.s = s;
- return x;
- }
- }
-
- // Estimate result exponent.
- // x^y = 10^e, where e = y * log10(x)
- // log10(x) = log10(x_significand) + x_exponent
- // log10(x_significand) = ln(x_significand) / ln(10)
- k = mathpow(+x, yn);
- e = k == 0 || !isFinite(k)
- ? mathfloor(yn * (Math.log('0.' + digitsToString(x.d)) / Math.LN10 + x.e + 1))
- : new Ctor(k + '').e;
-
- // Exponent estimate may be incorrect e.g. x: 0.999999999999999999, y: 2.29, e: 0, r.e: -1.
-
- // Overflow/underflow?
- if (e > Ctor.maxE + 1 || e < Ctor.minE - 1) return new Ctor(e > 0 ? s / 0 : 0);
-
- external = false;
- Ctor.rounding = x.s = 1;
-
- // Estimate the extra guard digits needed to ensure five correct rounding digits from
- // naturalLogarithm(x). Example of failure without these extra digits (precision: 10):
- // new Decimal(2.32456).pow('2087987436534566.46411')
- // should be 1.162377823e+764914905173815, but is 1.162355823e+764914905173815
- k = Math.min(12, (e + '').length);
-
- // r = x^y = exp(y*ln(x))
- r = naturalExponential(y.times(naturalLogarithm(x, pr + k)), pr);
-
- // r may be Infinity, e.g. (0.9999999999999999).pow(-1e+40)
- if (r.d) {
-
- // Truncate to the required precision plus five rounding digits.
- r = finalise(r, pr + 5, 1);
-
- // If the rounding digits are [49]9999 or [50]0000 increase the precision by 10 and recalculate
- // the result.
- if (checkRoundingDigits(r.d, pr, rm)) {
- e = pr + 10;
-
- // Truncate to the increased precision plus five rounding digits.
- r = finalise(naturalExponential(y.times(naturalLogarithm(x, e + k)), e), e + 5, 1);
-
- // Check for 14 nines from the 2nd rounding digit (the first rounding digit may be 4 or 9).
- if (+digitsToString(r.d).slice(pr + 1, pr + 15) + 1 == 1e14) {
- r = finalise(r, pr + 1, 0);
- }
- }
- }
-
- r.s = s;
- external = true;
- Ctor.rounding = rm;
-
- return finalise(r, pr, rm);
-};
-
-
-/*
- * Return a string representing the value of this Decimal rounded to `sd` significant digits
- * using rounding mode `rounding`.
- *
- * Return exponential notation if `sd` is less than the number of digits necessary to represent
- * the integer part of the value in normal notation.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- */
-P.toPrecision = function (sd, rm) {
- var str,
- x = this,
- Ctor = x.constructor;
-
- if (sd === void 0) {
- str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos);
- } else {
- checkInt32(sd, 1, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
-
- x = finalise(new Ctor(x), sd, rm);
- str = finiteToString(x, sd <= x.e || x.e <= Ctor.toExpNeg, sd);
- }
-
- return x.isNeg() && !x.isZero() ? '-' + str : str;
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal rounded to a maximum of `sd`
- * significant digits using rounding mode `rm`, or to `precision` and `rounding` respectively if
- * omitted.
- *
- * [sd] {number} Significant digits. Integer, 1 to MAX_DIGITS inclusive.
- * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive.
- *
- * 'toSD() digits out of range: {sd}'
- * 'toSD() digits not an integer: {sd}'
- * 'toSD() rounding mode not an integer: {rm}'
- * 'toSD() rounding mode out of range: {rm}'
- *
- */
-P.toSignificantDigits = P.toSD = function (sd, rm) {
- var x = this,
- Ctor = x.constructor;
-
- if (sd === void 0) {
- sd = Ctor.precision;
- rm = Ctor.rounding;
- } else {
- checkInt32(sd, 1, MAX_DIGITS);
-
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
- }
-
- return finalise(new Ctor(x), sd, rm);
-};
-
-
-/*
- * Return a string representing the value of this Decimal.
- *
- * Return exponential notation if this Decimal has a positive exponent equal to or greater than
- * `toExpPos`, or a negative exponent equal to or less than `toExpNeg`.
- *
- */
-P.toString = function () {
- var x = this,
- Ctor = x.constructor,
- str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos);
-
- return x.isNeg() && !x.isZero() ? '-' + str : str;
-};
-
-
-/*
- * Return a new Decimal whose value is the value of this Decimal truncated to a whole number.
- *
- */
-P.truncated = P.trunc = function () {
- return finalise(new this.constructor(this), this.e + 1, 1);
-};
-
-
-/*
- * Return a string representing the value of this Decimal.
- * Unlike `toString`, negative zero will include the minus sign.
- *
- */
-P.valueOf = P.toJSON = function () {
- var x = this,
- Ctor = x.constructor,
- str = finiteToString(x, x.e <= Ctor.toExpNeg || x.e >= Ctor.toExpPos);
-
- return x.isNeg() ? '-' + str : str;
-};
-
-
-// Helper functions for Decimal.prototype (P) and/or Decimal methods, and their callers.
-
-
-/*
- * digitsToString P.cubeRoot, P.logarithm, P.squareRoot, P.toFraction, P.toPower,
- * finiteToString, naturalExponential, naturalLogarithm
- * checkInt32 P.toDecimalPlaces, P.toExponential, P.toFixed, P.toNearest,
- * P.toPrecision, P.toSignificantDigits, toStringBinary, random
- * checkRoundingDigits P.logarithm, P.toPower, naturalExponential, naturalLogarithm
- * convertBase toStringBinary, parseOther
- * cos P.cos
- * divide P.atanh, P.cubeRoot, P.dividedBy, P.dividedToIntegerBy,
- * P.logarithm, P.modulo, P.squareRoot, P.tan, P.tanh, P.toFraction,
- * P.toNearest, toStringBinary, naturalExponential, naturalLogarithm,
- * taylorSeries, atan2, parseOther
- * finalise P.absoluteValue, P.atan, P.atanh, P.ceil, P.cos, P.cosh,
- * P.cubeRoot, P.dividedToIntegerBy, P.floor, P.logarithm, P.minus,
- * P.modulo, P.negated, P.plus, P.round, P.sin, P.sinh, P.squareRoot,
- * P.tan, P.times, P.toDecimalPlaces, P.toExponential, P.toFixed,
- * P.toNearest, P.toPower, P.toPrecision, P.toSignificantDigits,
- * P.truncated, divide, getLn10, getPi, naturalExponential,
- * naturalLogarithm, ceil, floor, round, trunc
- * finiteToString P.toExponential, P.toFixed, P.toPrecision, P.toString, P.valueOf,
- * toStringBinary
- * getBase10Exponent P.minus, P.plus, P.times, parseOther
- * getLn10 P.logarithm, naturalLogarithm
- * getPi P.acos, P.asin, P.atan, toLessThanHalfPi, atan2
- * getPrecision P.precision, P.toFraction
- * getZeroString digitsToString, finiteToString
- * intPow P.toPower, parseOther
- * isOdd toLessThanHalfPi
- * maxOrMin max, min
- * naturalExponential P.naturalExponential, P.toPower
- * naturalLogarithm P.acosh, P.asinh, P.atanh, P.logarithm, P.naturalLogarithm,
- * P.toPower, naturalExponential
- * nonFiniteToString finiteToString, toStringBinary
- * parseDecimal Decimal
- * parseOther Decimal
- * sin P.sin
- * taylorSeries P.cosh, P.sinh, cos, sin
- * toLessThanHalfPi P.cos, P.sin
- * toStringBinary P.toBinary, P.toHexadecimal, P.toOctal
- * truncate intPow
- *
- * Throws: P.logarithm, P.precision, P.toFraction, checkInt32, getLn10, getPi,
- * naturalLogarithm, config, parseOther, random, Decimal
- */
-
-
-function digitsToString(d) {
- var i, k, ws,
- indexOfLastWord = d.length - 1,
- str = '',
- w = d[0];
-
- if (indexOfLastWord > 0) {
- str += w;
- for (i = 1; i < indexOfLastWord; i++) {
- ws = d[i] + '';
- k = LOG_BASE - ws.length;
- if (k) str += getZeroString(k);
- str += ws;
- }
-
- w = d[i];
- ws = w + '';
- k = LOG_BASE - ws.length;
- if (k) str += getZeroString(k);
- } else if (w === 0) {
- return '0';
- }
-
- // Remove trailing zeros of last w.
- for (; w % 10 === 0;) w /= 10;
-
- return str + w;
-}
-
-
-function checkInt32(i, min, max) {
- if (i !== ~~i || i < min || i > max) {
- throw Error(invalidArgument + i);
- }
-}
-
-
-/*
- * Check 5 rounding digits if `repeating` is null, 4 otherwise.
- * `repeating == null` if caller is `log` or `pow`,
- * `repeating != null` if caller is `naturalLogarithm` or `naturalExponential`.
- */
-function checkRoundingDigits(d, i, rm, repeating) {
- var di, k, r, rd;
-
- // Get the length of the first word of the array d.
- for (k = d[0]; k >= 10; k /= 10) --i;
-
- // Is the rounding digit in the first word of d?
- if (--i < 0) {
- i += LOG_BASE;
- di = 0;
- } else {
- di = Math.ceil((i + 1) / LOG_BASE);
- i %= LOG_BASE;
- }
-
- // i is the index (0 - 6) of the rounding digit.
- // E.g. if within the word 3487563 the first rounding digit is 5,
- // then i = 4, k = 1000, rd = 3487563 % 1000 = 563
- k = mathpow(10, LOG_BASE - i);
- rd = d[di] % k | 0;
-
- if (repeating == null) {
- if (i < 3) {
- if (i == 0) rd = rd / 100 | 0;
- else if (i == 1) rd = rd / 10 | 0;
- r = rm < 4 && rd == 99999 || rm > 3 && rd == 49999 || rd == 50000 || rd == 0;
- } else {
- r = (rm < 4 && rd + 1 == k || rm > 3 && rd + 1 == k / 2) &&
- (d[di + 1] / k / 100 | 0) == mathpow(10, i - 2) - 1 ||
- (rd == k / 2 || rd == 0) && (d[di + 1] / k / 100 | 0) == 0;
- }
- } else {
- if (i < 4) {
- if (i == 0) rd = rd / 1000 | 0;
- else if (i == 1) rd = rd / 100 | 0;
- else if (i == 2) rd = rd / 10 | 0;
- r = (repeating || rm < 4) && rd == 9999 || !repeating && rm > 3 && rd == 4999;
- } else {
- r = ((repeating || rm < 4) && rd + 1 == k ||
- (!repeating && rm > 3) && rd + 1 == k / 2) &&
- (d[di + 1] / k / 1000 | 0) == mathpow(10, i - 3) - 1;
- }
- }
-
- return r;
-}
-
-
-// Convert string of `baseIn` to an array of numbers of `baseOut`.
-// Eg. convertBase('255', 10, 16) returns [15, 15].
-// Eg. convertBase('ff', 16, 10) returns [2, 5, 5].
-function convertBase(str, baseIn, baseOut) {
- var j,
- arr = [0],
- arrL,
- i = 0,
- strL = str.length;
-
- for (; i < strL;) {
- for (arrL = arr.length; arrL--;) arr[arrL] *= baseIn;
- arr[0] += NUMERALS.indexOf(str.charAt(i++));
- for (j = 0; j < arr.length; j++) {
- if (arr[j] > baseOut - 1) {
- if (arr[j + 1] === void 0) arr[j + 1] = 0;
- arr[j + 1] += arr[j] / baseOut | 0;
- arr[j] %= baseOut;
- }
- }
- }
-
- return arr.reverse();
-}
-
-
-/*
- * cos(x) = 1 - x^2/2! + x^4/4! - ...
- * |x| < pi/2
- *
- */
-function cosine(Ctor, x) {
- var k, len, y;
-
- if (x.isZero()) return x;
-
- // Argument reduction: cos(4x) = 8*(cos^4(x) - cos^2(x)) + 1
- // i.e. cos(x) = 8*(cos^4(x/4) - cos^2(x/4)) + 1
-
- // Estimate the optimum number of times to use the argument reduction.
- len = x.d.length;
- if (len < 32) {
- k = Math.ceil(len / 3);
- y = (1 / tinyPow(4, k)).toString();
- } else {
- k = 16;
- y = '2.3283064365386962890625e-10';
- }
-
- Ctor.precision += k;
-
- x = taylorSeries(Ctor, 1, x.times(y), new Ctor(1));
-
- // Reverse argument reduction
- for (var i = k; i--;) {
- var cos2x = x.times(x);
- x = cos2x.times(cos2x).minus(cos2x).times(8).plus(1);
- }
-
- Ctor.precision -= k;
-
- return x;
-}
-
-
-/*
- * Perform division in the specified base.
- */
-var divide = (function () {
-
- // Assumes non-zero x and k, and hence non-zero result.
- function multiplyInteger(x, k, base) {
- var temp,
- carry = 0,
- i = x.length;
-
- for (x = x.slice(); i--;) {
- temp = x[i] * k + carry;
- x[i] = temp % base | 0;
- carry = temp / base | 0;
- }
-
- if (carry) x.unshift(carry);
-
- return x;
- }
-
- function compare(a, b, aL, bL) {
- var i, r;
-
- if (aL != bL) {
- r = aL > bL ? 1 : -1;
- } else {
- for (i = r = 0; i < aL; i++) {
- if (a[i] != b[i]) {
- r = a[i] > b[i] ? 1 : -1;
- break;
- }
- }
- }
-
- return r;
- }
-
- function subtract(a, b, aL, base) {
- var i = 0;
-
- // Subtract b from a.
- for (; aL--;) {
- a[aL] -= i;
- i = a[aL] < b[aL] ? 1 : 0;
- a[aL] = i * base + a[aL] - b[aL];
- }
-
- // Remove leading zeros.
- for (; !a[0] && a.length > 1;) a.shift();
- }
-
- return function (x, y, pr, rm, dp, base) {
- var cmp, e, i, k, logBase, more, prod, prodL, q, qd, rem, remL, rem0, sd, t, xi, xL, yd0,
- yL, yz,
- Ctor = x.constructor,
- sign = x.s == y.s ? 1 : -1,
- xd = x.d,
- yd = y.d;
-
- // Either NaN, Infinity or 0?
- if (!xd || !xd[0] || !yd || !yd[0]) {
-
- return new Ctor(// Return NaN if either NaN, or both Infinity or 0.
- !x.s || !y.s || (xd ? yd && xd[0] == yd[0] : !yd) ? NaN :
-
- // Return ±0 if x is 0 or y is ±Infinity, or return ±Infinity as y is 0.
- xd && xd[0] == 0 || !yd ? sign * 0 : sign / 0);
- }
-
- if (base) {
- logBase = 1;
- e = x.e - y.e;
- } else {
- base = BASE;
- logBase = LOG_BASE;
- e = mathfloor(x.e / logBase) - mathfloor(y.e / logBase);
- }
-
- yL = yd.length;
- xL = xd.length;
- q = new Ctor(sign);
- qd = q.d = [];
-
- // Result exponent may be one less than e.
- // The digit array of a Decimal from toStringBinary may have trailing zeros.
- for (i = 0; yd[i] == (xd[i] || 0); i++);
-
- if (yd[i] > (xd[i] || 0)) e--;
-
- if (pr == null) {
- sd = pr = Ctor.precision;
- rm = Ctor.rounding;
- } else if (dp) {
- sd = pr + (x.e - y.e) + 1;
- } else {
- sd = pr;
- }
-
- if (sd < 0) {
- qd.push(1);
- more = true;
- } else {
-
- // Convert precision in number of base 10 digits to base 1e7 digits.
- sd = sd / logBase + 2 | 0;
- i = 0;
-
- // divisor < 1e7
- if (yL == 1) {
- k = 0;
- yd = yd[0];
- sd++;
-
- // k is the carry.
- for (; (i < xL || k) && sd--; i++) {
- t = k * base + (xd[i] || 0);
- qd[i] = t / yd | 0;
- k = t % yd | 0;
- }
-
- more = k || i < xL;
-
- // divisor >= 1e7
- } else {
-
- // Normalise xd and yd so highest order digit of yd is >= base/2
- k = base / (yd[0] + 1) | 0;
-
- if (k > 1) {
- yd = multiplyInteger(yd, k, base);
- xd = multiplyInteger(xd, k, base);
- yL = yd.length;
- xL = xd.length;
- }
-
- xi = yL;
- rem = xd.slice(0, yL);
- remL = rem.length;
-
- // Add zeros to make remainder as long as divisor.
- for (; remL < yL;) rem[remL++] = 0;
-
- yz = yd.slice();
- yz.unshift(0);
- yd0 = yd[0];
-
- if (yd[1] >= base / 2) ++yd0;
-
- do {
- k = 0;
-
- // Compare divisor and remainder.
- cmp = compare(yd, rem, yL, remL);
-
- // If divisor < remainder.
- if (cmp < 0) {
-
- // Calculate trial digit, k.
- rem0 = rem[0];
- if (yL != remL) rem0 = rem0 * base + (rem[1] || 0);
-
- // k will be how many times the divisor goes into the current remainder.
- k = rem0 / yd0 | 0;
-
- // Algorithm:
- // 1. product = divisor * trial digit (k)
- // 2. if product > remainder: product -= divisor, k--
- // 3. remainder -= product
- // 4. if product was < remainder at 2:
- // 5. compare new remainder and divisor
- // 6. If remainder > divisor: remainder -= divisor, k++
-
- if (k > 1) {
- if (k >= base) k = base - 1;
-
- // product = divisor * trial digit.
- prod = multiplyInteger(yd, k, base);
- prodL = prod.length;
- remL = rem.length;
-
- // Compare product and remainder.
- cmp = compare(prod, rem, prodL, remL);
-
- // product > remainder.
- if (cmp == 1) {
- k--;
-
- // Subtract divisor from product.
- subtract(prod, yL < prodL ? yz : yd, prodL, base);
- }
- } else {
-
- // cmp is -1.
- // If k is 0, there is no need to compare yd and rem again below, so change cmp to 1
- // to avoid it. If k is 1 there is a need to compare yd and rem again below.
- if (k == 0) cmp = k = 1;
- prod = yd.slice();
- }
-
- prodL = prod.length;
- if (prodL < remL) prod.unshift(0);
-
- // Subtract product from remainder.
- subtract(rem, prod, remL, base);
-
- // If product was < previous remainder.
- if (cmp == -1) {
- remL = rem.length;
-
- // Compare divisor and new remainder.
- cmp = compare(yd, rem, yL, remL);
-
- // If divisor < new remainder, subtract divisor from remainder.
- if (cmp < 1) {
- k++;
-
- // Subtract divisor from remainder.
- subtract(rem, yL < remL ? yz : yd, remL, base);
- }
- }
-
- remL = rem.length;
- } else if (cmp === 0) {
- k++;
- rem = [0];
- } // if cmp === 1, k will be 0
-
- // Add the next digit, k, to the result array.
- qd[i++] = k;
-
- // Update the remainder.
- if (cmp && rem[0]) {
- rem[remL++] = xd[xi] || 0;
- } else {
- rem = [xd[xi]];
- remL = 1;
- }
-
- } while ((xi++ < xL || rem[0] !== void 0) && sd--);
-
- more = rem[0] !== void 0;
- }
-
- // Leading zero?
- if (!qd[0]) qd.shift();
- }
-
- // logBase is 1 when divide is being used for base conversion.
- if (logBase == 1) {
- q.e = e;
- inexact = more;
- } else {
-
- // To calculate q.e, first get the number of digits of qd[0].
- for (i = 1, k = qd[0]; k >= 10; k /= 10) i++;
- q.e = i + e * logBase - 1;
-
- finalise(q, dp ? pr + q.e + 1 : pr, rm, more);
- }
-
- return q;
- };
-})();
-
-
-/*
- * Round `x` to `sd` significant digits using rounding mode `rm`.
- * Check for over/under-flow.
- */
- function finalise(x, sd, rm, isTruncated) {
- var digits, i, j, k, rd, roundUp, w, xd, xdi,
- Ctor = x.constructor;
-
- // Don't round if sd is null or undefined.
- out: if (sd != null) {
- xd = x.d;
-
- // Infinity/NaN.
- if (!xd) return x;
-
- // rd: the rounding digit, i.e. the digit after the digit that may be rounded up.
- // w: the word of xd containing rd, a base 1e7 number.
- // xdi: the index of w within xd.
- // digits: the number of digits of w.
- // i: what would be the index of rd within w if all the numbers were 7 digits long (i.e. if
- // they had leading zeros)
- // j: if > 0, the actual index of rd within w (if < 0, rd is a leading zero).
-
- // Get the length of the first word of the digits array xd.
- for (digits = 1, k = xd[0]; k >= 10; k /= 10) digits++;
- i = sd - digits;
-
- // Is the rounding digit in the first word of xd?
- if (i < 0) {
- i += LOG_BASE;
- j = sd;
- w = xd[xdi = 0];
-
- // Get the rounding digit at index j of w.
- rd = w / mathpow(10, digits - j - 1) % 10 | 0;
- } else {
- xdi = Math.ceil((i + 1) / LOG_BASE);
- k = xd.length;
- if (xdi >= k) {
- if (isTruncated) {
-
- // Needed by `naturalExponential`, `naturalLogarithm` and `squareRoot`.
- for (; k++ <= xdi;) xd.push(0);
- w = rd = 0;
- digits = 1;
- i %= LOG_BASE;
- j = i - LOG_BASE + 1;
- } else {
- break out;
- }
- } else {
- w = k = xd[xdi];
-
- // Get the number of digits of w.
- for (digits = 1; k >= 10; k /= 10) digits++;
-
- // Get the index of rd within w.
- i %= LOG_BASE;
-
- // Get the index of rd within w, adjusted for leading zeros.
- // The number of leading zeros of w is given by LOG_BASE - digits.
- j = i - LOG_BASE + digits;
-
- // Get the rounding digit at index j of w.
- rd = j < 0 ? 0 : w / mathpow(10, digits - j - 1) % 10 | 0;
- }
- }
-
- // Are there any non-zero digits after the rounding digit?
- isTruncated = isTruncated || sd < 0 ||
- xd[xdi + 1] !== void 0 || (j < 0 ? w : w % mathpow(10, digits - j - 1));
-
- // The expression `w % mathpow(10, digits - j - 1)` returns all the digits of w to the right
- // of the digit at (left-to-right) index j, e.g. if w is 908714 and j is 2, the expression
- // will give 714.
-
- roundUp = rm < 4
- ? (rd || isTruncated) && (rm == 0 || rm == (x.s < 0 ? 3 : 2))
- : rd > 5 || rd == 5 && (rm == 4 || isTruncated || rm == 6 &&
-
- // Check whether the digit to the left of the rounding digit is odd.
- ((i > 0 ? j > 0 ? w / mathpow(10, digits - j) : 0 : xd[xdi - 1]) % 10) & 1 ||
- rm == (x.s < 0 ? 8 : 7));
-
- if (sd < 1 || !xd[0]) {
- xd.length = 0;
- if (roundUp) {
-
- // Convert sd to decimal places.
- sd -= x.e + 1;
-
- // 1, 0.1, 0.01, 0.001, 0.0001 etc.
- xd[0] = mathpow(10, (LOG_BASE - sd % LOG_BASE) % LOG_BASE);
- x.e = -sd || 0;
- } else {
-
- // Zero.
- xd[0] = x.e = 0;
- }
-
- return x;
- }
-
- // Remove excess digits.
- if (i == 0) {
- xd.length = xdi;
- k = 1;
- xdi--;
- } else {
- xd.length = xdi + 1;
- k = mathpow(10, LOG_BASE - i);
-
- // E.g. 56700 becomes 56000 if 7 is the rounding digit.
- // j > 0 means i > number of leading zeros of w.
- xd[xdi] = j > 0 ? (w / mathpow(10, digits - j) % mathpow(10, j) | 0) * k : 0;
- }
-
- if (roundUp) {
- for (;;) {
-
- // Is the digit to be rounded up in the first word of xd?
- if (xdi == 0) {
-
- // i will be the length of xd[0] before k is added.
- for (i = 1, j = xd[0]; j >= 10; j /= 10) i++;
- j = xd[0] += k;
- for (k = 1; j >= 10; j /= 10) k++;
-
- // if i != k the length has increased.
- if (i != k) {
- x.e++;
- if (xd[0] == BASE) xd[0] = 1;
- }
-
- break;
- } else {
- xd[xdi] += k;
- if (xd[xdi] != BASE) break;
- xd[xdi--] = 0;
- k = 1;
- }
- }
- }
-
- // Remove trailing zeros.
- for (i = xd.length; xd[--i] === 0;) xd.pop();
- }
-
- if (external) {
-
- // Overflow?
- if (x.e > Ctor.maxE) {
-
- // Infinity.
- x.d = null;
- x.e = NaN;
-
- // Underflow?
- } else if (x.e < Ctor.minE) {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- // Ctor.underflow = true;
- } // else Ctor.underflow = false;
- }
-
- return x;
-}
-
-
-function finiteToString(x, isExp, sd) {
- if (!x.isFinite()) return nonFiniteToString(x);
- var k,
- e = x.e,
- str = digitsToString(x.d),
- len = str.length;
-
- if (isExp) {
- if (sd && (k = sd - len) > 0) {
- str = str.charAt(0) + '.' + str.slice(1) + getZeroString(k);
- } else if (len > 1) {
- str = str.charAt(0) + '.' + str.slice(1);
- }
-
- str = str + (x.e < 0 ? 'e' : 'e+') + x.e;
- } else if (e < 0) {
- str = '0.' + getZeroString(-e - 1) + str;
- if (sd && (k = sd - len) > 0) str += getZeroString(k);
- } else if (e >= len) {
- str += getZeroString(e + 1 - len);
- if (sd && (k = sd - e - 1) > 0) str = str + '.' + getZeroString(k);
- } else {
- if ((k = e + 1) < len) str = str.slice(0, k) + '.' + str.slice(k);
- if (sd && (k = sd - len) > 0) {
- if (e + 1 === len) str += '.';
- str += getZeroString(k);
- }
- }
-
- return str;
-}
-
-
-// Calculate the base 10 exponent from the base 1e7 exponent.
-function getBase10Exponent(digits, e) {
- var w = digits[0];
-
- // Add the number of digits of the first word of the digits array.
- for ( e *= LOG_BASE; w >= 10; w /= 10) e++;
- return e;
-}
-
-
-function getLn10(Ctor, sd, pr) {
- if (sd > LN10_PRECISION) {
-
- // Reset global state in case the exception is caught.
- external = true;
- if (pr) Ctor.precision = pr;
- throw Error(precisionLimitExceeded);
- }
- return finalise(new Ctor(LN10), sd, 1, true);
-}
-
-
-function getPi(Ctor, sd, rm) {
- if (sd > PI_PRECISION) throw Error(precisionLimitExceeded);
- return finalise(new Ctor(PI), sd, rm, true);
-}
-
-
-function getPrecision(digits) {
- var w = digits.length - 1,
- len = w * LOG_BASE + 1;
-
- w = digits[w];
-
- // If non-zero...
- if (w) {
-
- // Subtract the number of trailing zeros of the last word.
- for (; w % 10 == 0; w /= 10) len--;
-
- // Add the number of digits of the first word.
- for (w = digits[0]; w >= 10; w /= 10) len++;
- }
-
- return len;
-}
-
-
-function getZeroString(k) {
- var zs = '';
- for (; k--;) zs += '0';
- return zs;
-}
-
-
-/*
- * Return a new Decimal whose value is the value of Decimal `x` to the power `n`, where `n` is an
- * integer of type number.
- *
- * Implements 'exponentiation by squaring'. Called by `pow` and `parseOther`.
- *
- */
-function intPow(Ctor, x, n, pr) {
- var isTruncated,
- r = new Ctor(1),
-
- // Max n of 9007199254740991 takes 53 loop iterations.
- // Maximum digits array length; leaves [28, 34] guard digits.
- k = Math.ceil(pr / LOG_BASE + 4);
-
- external = false;
-
- for (;;) {
- if (n % 2) {
- r = r.times(x);
- if (truncate(r.d, k)) isTruncated = true;
- }
-
- n = mathfloor(n / 2);
- if (n === 0) {
-
- // To ensure correct rounding when r.d is truncated, increment the last word if it is zero.
- n = r.d.length - 1;
- if (isTruncated && r.d[n] === 0) ++r.d[n];
- break;
- }
-
- x = x.times(x);
- truncate(x.d, k);
- }
-
- external = true;
-
- return r;
-}
-
-
-function isOdd(n) {
- return n.d[n.d.length - 1] & 1;
-}
-
-
-/*
- * Handle `max` (`n` is -1) and `min` (`n` is 1).
- */
-function maxOrMin(Ctor, args, n) {
- var k, y,
- x = new Ctor(args[0]),
- i = 0;
-
- for (; ++i < args.length;) {
- y = new Ctor(args[i]);
-
- // NaN?
- if (!y.s) {
- x = y;
- break;
- }
-
- k = x.cmp(y);
-
- if (k === n || k === 0 && x.s === n) {
- x = y;
- }
- }
-
- return x;
-}
-
-
-/*
- * Return a new Decimal whose value is the natural exponential of `x` rounded to `sd` significant
- * digits.
- *
- * Taylor/Maclaurin series.
- *
- * exp(x) = x^0/0! + x^1/1! + x^2/2! + x^3/3! + ...
- *
- * Argument reduction:
- * Repeat x = x / 32, k += 5, until |x| < 0.1
- * exp(x) = exp(x / 2^k)^(2^k)
- *
- * Previously, the argument was initially reduced by
- * exp(x) = exp(r) * 10^k where r = x - k * ln10, k = floor(x / ln10)
- * to first put r in the range [0, ln10], before dividing by 32 until |x| < 0.1, but this was
- * found to be slower than just dividing repeatedly by 32 as above.
- *
- * Max integer argument: exp('20723265836946413') = 6.3e+9000000000000000
- * Min integer argument: exp('-20723265836946411') = 1.2e-9000000000000000
- * (Math object integer min/max: Math.exp(709) = 8.2e+307, Math.exp(-745) = 5e-324)
- *
- * exp(Infinity) = Infinity
- * exp(-Infinity) = 0
- * exp(NaN) = NaN
- * exp(±0) = 1
- *
- * exp(x) is non-terminating for any finite, non-zero x.
- *
- * The result will always be correctly rounded.
- *
- */
-function naturalExponential(x, sd) {
- var denominator, guard, j, pow, sum, t, wpr,
- rep = 0,
- i = 0,
- k = 0,
- Ctor = x.constructor,
- rm = Ctor.rounding,
- pr = Ctor.precision;
-
- // 0/NaN/Infinity?
- if (!x.d || !x.d[0] || x.e > 17) {
-
- return new Ctor(x.d
- ? !x.d[0] ? 1 : x.s < 0 ? 0 : 1 / 0
- : x.s ? x.s < 0 ? 0 : x : 0 / 0);
- }
-
- if (sd == null) {
- external = false;
- wpr = pr;
- } else {
- wpr = sd;
- }
-
- t = new Ctor(0.03125);
-
- // while abs(x) >= 0.1
- while (x.e > -2) {
-
- // x = x / 2^5
- x = x.times(t);
- k += 5;
- }
-
- // Use 2 * log10(2^k) + 5 (empirically derived) to estimate the increase in precision
- // necessary to ensure the first 4 rounding digits are correct.
- guard = Math.log(mathpow(2, k)) / Math.LN10 * 2 + 5 | 0;
- wpr += guard;
- denominator = pow = sum = new Ctor(1);
- Ctor.precision = wpr;
-
- for (;;) {
- pow = finalise(pow.times(x), wpr, 1);
- denominator = denominator.times(++i);
- t = sum.plus(divide(pow, denominator, wpr, 1));
-
- if (digitsToString(t.d).slice(0, wpr) === digitsToString(sum.d).slice(0, wpr)) {
- j = k;
- while (j--) sum = finalise(sum.times(sum), wpr, 1);
-
- // Check to see if the first 4 rounding digits are [49]999.
- // If so, repeat the summation with a higher precision, otherwise
- // e.g. with precision: 18, rounding: 1
- // exp(18.404272462595034083567793919843761) = 98372560.1229999999 (should be 98372560.123)
- // `wpr - guard` is the index of first rounding digit.
- if (sd == null) {
-
- if (rep < 3 && checkRoundingDigits(sum.d, wpr - guard, rm, rep)) {
- Ctor.precision = wpr += 10;
- denominator = pow = t = new Ctor(1);
- i = 0;
- rep++;
- } else {
- return finalise(sum, Ctor.precision = pr, rm, external = true);
- }
- } else {
- Ctor.precision = pr;
- return sum;
- }
- }
-
- sum = t;
- }
-}
-
-
-/*
- * Return a new Decimal whose value is the natural logarithm of `x` rounded to `sd` significant
- * digits.
- *
- * ln(-n) = NaN
- * ln(0) = -Infinity
- * ln(-0) = -Infinity
- * ln(1) = 0
- * ln(Infinity) = Infinity
- * ln(-Infinity) = NaN
- * ln(NaN) = NaN
- *
- * ln(n) (n != 1) is non-terminating.
- *
- */
-function naturalLogarithm(y, sd) {
- var c, c0, denominator, e, numerator, rep, sum, t, wpr, x1, x2,
- n = 1,
- guard = 10,
- x = y,
- xd = x.d,
- Ctor = x.constructor,
- rm = Ctor.rounding,
- pr = Ctor.precision;
-
- // Is x negative or Infinity, NaN, 0 or 1?
- if (x.s < 0 || !xd || !xd[0] || !x.e && xd[0] == 1 && xd.length == 1) {
- return new Ctor(xd && !xd[0] ? -1 / 0 : x.s != 1 ? NaN : xd ? 0 : x);
- }
-
- if (sd == null) {
- external = false;
- wpr = pr;
- } else {
- wpr = sd;
- }
-
- Ctor.precision = wpr += guard;
- c = digitsToString(xd);
- c0 = c.charAt(0);
-
- if (Math.abs(e = x.e) < 1.5e15) {
-
- // Argument reduction.
- // The series converges faster the closer the argument is to 1, so using
- // ln(a^b) = b * ln(a), ln(a) = ln(a^b) / b
- // multiply the argument by itself until the leading digits of the significand are 7, 8, 9,
- // 10, 11, 12 or 13, recording the number of multiplications so the sum of the series can
- // later be divided by this number, then separate out the power of 10 using
- // ln(a*10^b) = ln(a) + b*ln(10).
-
- // max n is 21 (gives 0.9, 1.0 or 1.1) (9e15 / 21 = 4.2e14).
- //while (c0 < 9 && c0 != 1 || c0 == 1 && c.charAt(1) > 1) {
- // max n is 6 (gives 0.7 - 1.3)
- while (c0 < 7 && c0 != 1 || c0 == 1 && c.charAt(1) > 3) {
- x = x.times(y);
- c = digitsToString(x.d);
- c0 = c.charAt(0);
- n++;
- }
-
- e = x.e;
-
- if (c0 > 1) {
- x = new Ctor('0.' + c);
- e++;
- } else {
- x = new Ctor(c0 + '.' + c.slice(1));
- }
- } else {
-
- // The argument reduction method above may result in overflow if the argument y is a massive
- // number with exponent >= 1500000000000000 (9e15 / 6 = 1.5e15), so instead recall this
- // function using ln(x*10^e) = ln(x) + e*ln(10).
- t = getLn10(Ctor, wpr + 2, pr).times(e + '');
- x = naturalLogarithm(new Ctor(c0 + '.' + c.slice(1)), wpr - guard).plus(t);
- Ctor.precision = pr;
-
- return sd == null ? finalise(x, pr, rm, external = true) : x;
- }
-
- // x1 is x reduced to a value near 1.
- x1 = x;
-
- // Taylor series.
- // ln(y) = ln((1 + x)/(1 - x)) = 2(x + x^3/3 + x^5/5 + x^7/7 + ...)
- // where x = (y - 1)/(y + 1) (|x| < 1)
- sum = numerator = x = divide(x.minus(1), x.plus(1), wpr, 1);
- x2 = finalise(x.times(x), wpr, 1);
- denominator = 3;
-
- for (;;) {
- numerator = finalise(numerator.times(x2), wpr, 1);
- t = sum.plus(divide(numerator, new Ctor(denominator), wpr, 1));
-
- if (digitsToString(t.d).slice(0, wpr) === digitsToString(sum.d).slice(0, wpr)) {
- sum = sum.times(2);
-
- // Reverse the argument reduction. Check that e is not 0 because, besides preventing an
- // unnecessary calculation, -0 + 0 = +0 and to ensure correct rounding -0 needs to stay -0.
- if (e !== 0) sum = sum.plus(getLn10(Ctor, wpr + 2, pr).times(e + ''));
- sum = divide(sum, new Ctor(n), wpr, 1);
-
- // Is rm > 3 and the first 4 rounding digits 4999, or rm < 4 (or the summation has
- // been repeated previously) and the first 4 rounding digits 9999?
- // If so, restart the summation with a higher precision, otherwise
- // e.g. with precision: 12, rounding: 1
- // ln(135520028.6126091714265381533) = 18.7246299999 when it should be 18.72463.
- // `wpr - guard` is the index of first rounding digit.
- if (sd == null) {
- if (checkRoundingDigits(sum.d, wpr - guard, rm, rep)) {
- Ctor.precision = wpr += guard;
- t = numerator = x = divide(x1.minus(1), x1.plus(1), wpr, 1);
- x2 = finalise(x.times(x), wpr, 1);
- denominator = rep = 1;
- } else {
- return finalise(sum, Ctor.precision = pr, rm, external = true);
- }
- } else {
- Ctor.precision = pr;
- return sum;
- }
- }
-
- sum = t;
- denominator += 2;
- }
-}
-
-
-// ±Infinity, NaN.
-function nonFiniteToString(x) {
- // Unsigned.
- return String(x.s * x.s / 0);
-}
-
-
-/*
- * Parse the value of a new Decimal `x` from string `str`.
- */
-function parseDecimal(x, str) {
- var e, i, len;
-
- // TODO BigInt str: no need to check for decimal point, exponential form or leading zeros.
- // Decimal point?
- if ((e = str.indexOf('.')) > -1) str = str.replace('.', '');
-
- // Exponential form?
- if ((i = str.search(/e/i)) > 0) {
-
- // Determine exponent.
- if (e < 0) e = i;
- e += +str.slice(i + 1);
- str = str.substring(0, i);
- } else if (e < 0) {
-
- // Integer.
- e = str.length;
- }
-
- // Determine leading zeros.
- for (i = 0; str.charCodeAt(i) === 48; i++);
-
- // Determine trailing zeros.
- for (len = str.length; str.charCodeAt(len - 1) === 48; --len);
- str = str.slice(i, len);
-
- if (str) {
- len -= i;
- x.e = e = e - i - 1;
- x.d = [];
-
- // Transform base
-
- // e is the base 10 exponent.
- // i is where to slice str to get the first word of the digits array.
- i = (e + 1) % LOG_BASE;
- if (e < 0) i += LOG_BASE;
-
- if (i < len) {
- if (i) x.d.push(+str.slice(0, i));
- for (len -= LOG_BASE; i < len;) x.d.push(+str.slice(i, i += LOG_BASE));
- str = str.slice(i);
- i = LOG_BASE - str.length;
- } else {
- i -= len;
- }
-
- for (; i--;) str += '0';
- x.d.push(+str);
-
- if (external) {
-
- // Overflow?
- if (x.e > x.constructor.maxE) {
-
- // Infinity.
- x.d = null;
- x.e = NaN;
-
- // Underflow?
- } else if (x.e < x.constructor.minE) {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- // x.constructor.underflow = true;
- } // else x.constructor.underflow = false;
- }
- } else {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- }
-
- return x;
-}
-
-
-/*
- * Parse the value of a new Decimal `x` from a string `str`, which is not a decimal value.
- */
-function parseOther(x, str) {
- var base, Ctor, divisor, i, isFloat, len, p, xd, xe;
-
- if (str.indexOf('_') > -1) {
- str = str.replace(/(\d)_(?=\d)/g, '$1');
- if (isDecimal.test(str)) return parseDecimal(x, str);
- } else if (str === 'Infinity' || str === 'NaN') {
- if (!+str) x.s = NaN;
- x.e = NaN;
- x.d = null;
- return x;
- }
-
- if (isHex.test(str)) {
- base = 16;
- str = str.toLowerCase();
- } else if (isBinary.test(str)) {
- base = 2;
- } else if (isOctal.test(str)) {
- base = 8;
- } else {
- throw Error(invalidArgument + str);
- }
-
- // Is there a binary exponent part?
- i = str.search(/p/i);
-
- if (i > 0) {
- p = +str.slice(i + 1);
- str = str.substring(2, i);
- } else {
- str = str.slice(2);
- }
-
- // Convert `str` as an integer then divide the result by `base` raised to a power such that the
- // fraction part will be restored.
- i = str.indexOf('.');
- isFloat = i >= 0;
- Ctor = x.constructor;
-
- if (isFloat) {
- str = str.replace('.', '');
- len = str.length;
- i = len - i;
-
- // log[10](16) = 1.2041... , log[10](88) = 1.9444....
- divisor = intPow(Ctor, new Ctor(base), i, i * 2);
- }
-
- xd = convertBase(str, base, BASE);
- xe = xd.length - 1;
-
- // Remove trailing zeros.
- for (i = xe; xd[i] === 0; --i) xd.pop();
- if (i < 0) return new Ctor(x.s * 0);
- x.e = getBase10Exponent(xd, xe);
- x.d = xd;
- external = false;
-
- // At what precision to perform the division to ensure exact conversion?
- // maxDecimalIntegerPartDigitCount = ceil(log[10](b) * otherBaseIntegerPartDigitCount)
- // log[10](2) = 0.30103, log[10](8) = 0.90309, log[10](16) = 1.20412
- // E.g. ceil(1.2 * 3) = 4, so up to 4 decimal digits are needed to represent 3 hex int digits.
- // maxDecimalFractionPartDigitCount = {Hex:4|Oct:3|Bin:1} * otherBaseFractionPartDigitCount
- // Therefore using 4 * the number of digits of str will always be enough.
- if (isFloat) x = divide(x, divisor, len * 4);
-
- // Multiply by the binary exponent part if present.
- if (p) x = x.times(Math.abs(p) < 54 ? mathpow(2, p) : Decimal.pow(2, p));
- external = true;
-
- return x;
-}
-
-
-/*
- * sin(x) = x - x^3/3! + x^5/5! - ...
- * |x| < pi/2
- *
- */
-function sine(Ctor, x) {
- var k,
- len = x.d.length;
-
- if (len < 3) {
- return x.isZero() ? x : taylorSeries(Ctor, 2, x, x);
- }
-
- // Argument reduction: sin(5x) = 16*sin^5(x) - 20*sin^3(x) + 5*sin(x)
- // i.e. sin(x) = 16*sin^5(x/5) - 20*sin^3(x/5) + 5*sin(x/5)
- // and sin(x) = sin(x/5)(5 + sin^2(x/5)(16sin^2(x/5) - 20))
-
- // Estimate the optimum number of times to use the argument reduction.
- k = 1.4 * Math.sqrt(len);
- k = k > 16 ? 16 : k | 0;
-
- x = x.times(1 / tinyPow(5, k));
- x = taylorSeries(Ctor, 2, x, x);
-
- // Reverse argument reduction
- var sin2_x,
- d5 = new Ctor(5),
- d16 = new Ctor(16),
- d20 = new Ctor(20);
- for (; k--;) {
- sin2_x = x.times(x);
- x = x.times(d5.plus(sin2_x.times(d16.times(sin2_x).minus(d20))));
- }
-
- return x;
-}
-
-
-// Calculate Taylor series for `cos`, `cosh`, `sin` and `sinh`.
-function taylorSeries(Ctor, n, x, y, isHyperbolic) {
- var j, t, u, x2,
- i = 1,
- pr = Ctor.precision,
- k = Math.ceil(pr / LOG_BASE);
-
- external = false;
- x2 = x.times(x);
- u = new Ctor(y);
-
- for (;;) {
- t = divide(u.times(x2), new Ctor(n++ * n++), pr, 1);
- u = isHyperbolic ? y.plus(t) : y.minus(t);
- y = divide(t.times(x2), new Ctor(n++ * n++), pr, 1);
- t = u.plus(y);
-
- if (t.d[k] !== void 0) {
- for (j = k; t.d[j] === u.d[j] && j--;);
- if (j == -1) break;
- }
-
- j = u;
- u = y;
- y = t;
- t = j;
- i++;
- }
-
- external = true;
- t.d.length = k + 1;
-
- return t;
-}
-
-
-// Exponent e must be positive and non-zero.
-function tinyPow(b, e) {
- var n = b;
- while (--e) n *= b;
- return n;
-}
-
-
-// Return the absolute value of `x` reduced to less than or equal to half pi.
-function toLessThanHalfPi(Ctor, x) {
- var t,
- isNeg = x.s < 0,
- pi = getPi(Ctor, Ctor.precision, 1),
- halfPi = pi.times(0.5);
-
- x = x.abs();
-
- if (x.lte(halfPi)) {
- quadrant = isNeg ? 4 : 1;
- return x;
- }
-
- t = x.divToInt(pi);
-
- if (t.isZero()) {
- quadrant = isNeg ? 3 : 2;
- } else {
- x = x.minus(t.times(pi));
-
- // 0 <= x < pi
- if (x.lte(halfPi)) {
- quadrant = isOdd(t) ? (isNeg ? 2 : 3) : (isNeg ? 4 : 1);
- return x;
- }
-
- quadrant = isOdd(t) ? (isNeg ? 1 : 4) : (isNeg ? 3 : 2);
- }
-
- return x.minus(pi).abs();
-}
-
-
-/*
- * Return the value of Decimal `x` as a string in base `baseOut`.
- *
- * If the optional `sd` argument is present include a binary exponent suffix.
- */
-function toStringBinary(x, baseOut, sd, rm) {
- var base, e, i, k, len, roundUp, str, xd, y,
- Ctor = x.constructor,
- isExp = sd !== void 0;
-
- if (isExp) {
- checkInt32(sd, 1, MAX_DIGITS);
- if (rm === void 0) rm = Ctor.rounding;
- else checkInt32(rm, 0, 8);
- } else {
- sd = Ctor.precision;
- rm = Ctor.rounding;
- }
-
- if (!x.isFinite()) {
- str = nonFiniteToString(x);
- } else {
- str = finiteToString(x);
- i = str.indexOf('.');
-
- // Use exponential notation according to `toExpPos` and `toExpNeg`? No, but if required:
- // maxBinaryExponent = floor((decimalExponent + 1) * log[2](10))
- // minBinaryExponent = floor(decimalExponent * log[2](10))
- // log[2](10) = 3.321928094887362347870319429489390175864
-
- if (isExp) {
- base = 2;
- if (baseOut == 16) {
- sd = sd * 4 - 3;
- } else if (baseOut == 8) {
- sd = sd * 3 - 2;
- }
- } else {
- base = baseOut;
- }
-
- // Convert the number as an integer then divide the result by its base raised to a power such
- // that the fraction part will be restored.
-
- // Non-integer.
- if (i >= 0) {
- str = str.replace('.', '');
- y = new Ctor(1);
- y.e = str.length - i;
- y.d = convertBase(finiteToString(y), 10, base);
- y.e = y.d.length;
- }
-
- xd = convertBase(str, 10, base);
- e = len = xd.length;
-
- // Remove trailing zeros.
- for (; xd[--len] == 0;) xd.pop();
-
- if (!xd[0]) {
- str = isExp ? '0p+0' : '0';
- } else {
- if (i < 0) {
- e--;
- } else {
- x = new Ctor(x);
- x.d = xd;
- x.e = e;
- x = divide(x, y, sd, rm, 0, base);
- xd = x.d;
- e = x.e;
- roundUp = inexact;
- }
-
- // The rounding digit, i.e. the digit after the digit that may be rounded up.
- i = xd[sd];
- k = base / 2;
- roundUp = roundUp || xd[sd + 1] !== void 0;
-
- roundUp = rm < 4
- ? (i !== void 0 || roundUp) && (rm === 0 || rm === (x.s < 0 ? 3 : 2))
- : i > k || i === k && (rm === 4 || roundUp || rm === 6 && xd[sd - 1] & 1 ||
- rm === (x.s < 0 ? 8 : 7));
-
- xd.length = sd;
-
- if (roundUp) {
-
- // Rounding up may mean the previous digit has to be rounded up and so on.
- for (; ++xd[--sd] > base - 1;) {
- xd[sd] = 0;
- if (!sd) {
- ++e;
- xd.unshift(1);
- }
- }
- }
-
- // Determine trailing zeros.
- for (len = xd.length; !xd[len - 1]; --len);
-
- // E.g. [4, 11, 15] becomes 4bf.
- for (i = 0, str = ''; i < len; i++) str += NUMERALS.charAt(xd[i]);
-
- // Add binary exponent suffix?
- if (isExp) {
- if (len > 1) {
- if (baseOut == 16 || baseOut == 8) {
- i = baseOut == 16 ? 4 : 3;
- for (--len; len % i; len++) str += '0';
- xd = convertBase(str, base, baseOut);
- for (len = xd.length; !xd[len - 1]; --len);
-
- // xd[0] will always be be 1
- for (i = 1, str = '1.'; i < len; i++) str += NUMERALS.charAt(xd[i]);
- } else {
- str = str.charAt(0) + '.' + str.slice(1);
- }
- }
-
- str = str + (e < 0 ? 'p' : 'p+') + e;
- } else if (e < 0) {
- for (; ++e;) str = '0' + str;
- str = '0.' + str;
- } else {
- if (++e > len) for (e -= len; e-- ;) str += '0';
- else if (e < len) str = str.slice(0, e) + '.' + str.slice(e);
- }
- }
-
- str = (baseOut == 16 ? '0x' : baseOut == 2 ? '0b' : baseOut == 8 ? '0o' : '') + str;
- }
-
- return x.s < 0 ? '-' + str : str;
-}
-
-
-// Does not strip trailing zeros.
-function truncate(arr, len) {
- if (arr.length > len) {
- arr.length = len;
- return true;
- }
-}
-
-
-// Decimal methods
-
-
-/*
- * abs
- * acos
- * acosh
- * add
- * asin
- * asinh
- * atan
- * atanh
- * atan2
- * cbrt
- * ceil
- * clamp
- * clone
- * config
- * cos
- * cosh
- * div
- * exp
- * floor
- * hypot
- * ln
- * log
- * log2
- * log10
- * max
- * min
- * mod
- * mul
- * pow
- * random
- * round
- * set
- * sign
- * sin
- * sinh
- * sqrt
- * sub
- * sum
- * tan
- * tanh
- * trunc
- */
-
-
-/*
- * Return a new Decimal whose value is the absolute value of `x`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function abs(x) {
- return new this(x).abs();
-}
-
-
-/*
- * Return a new Decimal whose value is the arccosine in radians of `x`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function acos(x) {
- return new this(x).acos();
-}
-
-
-/*
- * Return a new Decimal whose value is the inverse of the hyperbolic cosine of `x`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function acosh(x) {
- return new this(x).acosh();
-}
-
-
-/*
- * Return a new Decimal whose value is the sum of `x` and `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
-function add(x, y) {
- return new this(x).plus(y);
-}
-
-
-/*
- * Return a new Decimal whose value is the arcsine in radians of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function asin(x) {
- return new this(x).asin();
-}
-
-
-/*
- * Return a new Decimal whose value is the inverse of the hyperbolic sine of `x`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function asinh(x) {
- return new this(x).asinh();
-}
-
-
-/*
- * Return a new Decimal whose value is the arctangent in radians of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function atan(x) {
- return new this(x).atan();
-}
-
-
-/*
- * Return a new Decimal whose value is the inverse of the hyperbolic tangent of `x`, rounded to
- * `precision` significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function atanh(x) {
- return new this(x).atanh();
-}
-
-
-/*
- * Return a new Decimal whose value is the arctangent in radians of `y/x` in the range -pi to pi
- * (inclusive), rounded to `precision` significant digits using rounding mode `rounding`.
- *
- * Domain: [-Infinity, Infinity]
- * Range: [-pi, pi]
- *
- * y {number|string|bigint|Decimal} The y-coordinate.
- * x {number|string|bigint|Decimal} The x-coordinate.
- *
- * atan2(±0, -0) = ±pi
- * atan2(±0, +0) = ±0
- * atan2(±0, -x) = ±pi for x > 0
- * atan2(±0, x) = ±0 for x > 0
- * atan2(-y, ±0) = -pi/2 for y > 0
- * atan2(y, ±0) = pi/2 for y > 0
- * atan2(±y, -Infinity) = ±pi for finite y > 0
- * atan2(±y, +Infinity) = ±0 for finite y > 0
- * atan2(±Infinity, x) = ±pi/2 for finite x
- * atan2(±Infinity, -Infinity) = ±3*pi/4
- * atan2(±Infinity, +Infinity) = ±pi/4
- * atan2(NaN, x) = NaN
- * atan2(y, NaN) = NaN
- *
- */
-function atan2(y, x) {
- y = new this(y);
- x = new this(x);
- var r,
- pr = this.precision,
- rm = this.rounding,
- wpr = pr + 4;
-
- // Either NaN
- if (!y.s || !x.s) {
- r = new this(NaN);
-
- // Both ±Infinity
- } else if (!y.d && !x.d) {
- r = getPi(this, wpr, 1).times(x.s > 0 ? 0.25 : 0.75);
- r.s = y.s;
-
- // x is ±Infinity or y is ±0
- } else if (!x.d || y.isZero()) {
- r = x.s < 0 ? getPi(this, pr, rm) : new this(0);
- r.s = y.s;
-
- // y is ±Infinity or x is ±0
- } else if (!y.d || x.isZero()) {
- r = getPi(this, wpr, 1).times(0.5);
- r.s = y.s;
-
- // Both non-zero and finite
- } else if (x.s < 0) {
- this.precision = wpr;
- this.rounding = 1;
- r = this.atan(divide(y, x, wpr, 1));
- x = getPi(this, wpr, 1);
- this.precision = pr;
- this.rounding = rm;
- r = y.s < 0 ? r.minus(x) : r.plus(x);
- } else {
- r = this.atan(divide(y, x, wpr, 1));
- }
-
- return r;
-}
-
-
-/*
- * Return a new Decimal whose value is the cube root of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function cbrt(x) {
- return new this(x).cbrt();
-}
-
-
-/*
- * Return a new Decimal whose value is `x` rounded to an integer using `ROUND_CEIL`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function ceil(x) {
- return finalise(x = new this(x), x.e + 1, 2);
-}
-
-
-/*
- * Return a new Decimal whose value is `x` clamped to the range delineated by `min` and `max`.
- *
- * x {number|string|bigint|Decimal}
- * min {number|string|bigint|Decimal}
- * max {number|string|bigint|Decimal}
- *
- */
-function clamp(x, min, max) {
- return new this(x).clamp(min, max);
-}
-
-
-/*
- * Configure global settings for a Decimal constructor.
- *
- * `obj` is an object with one or more of the following properties,
- *
- * precision {number}
- * rounding {number}
- * toExpNeg {number}
- * toExpPos {number}
- * maxE {number}
- * minE {number}
- * modulo {number}
- * crypto {boolean|number}
- * defaults {true}
- *
- * E.g. Decimal.config({ precision: 20, rounding: 4 })
- *
- */
-function config(obj) {
- if (!obj || typeof obj !== 'object') throw Error(decimalError + 'Object expected');
- var i, p, v,
- useDefaults = obj.defaults === true,
- ps = [
- 'precision', 1, MAX_DIGITS,
- 'rounding', 0, 8,
- 'toExpNeg', -EXP_LIMIT, 0,
- 'toExpPos', 0, EXP_LIMIT,
- 'maxE', 0, EXP_LIMIT,
- 'minE', -EXP_LIMIT, 0,
- 'modulo', 0, 9
- ];
-
- for (i = 0; i < ps.length; i += 3) {
- if (p = ps[i], useDefaults) this[p] = DEFAULTS[p];
- if ((v = obj[p]) !== void 0) {
- if (mathfloor(v) === v && v >= ps[i + 1] && v <= ps[i + 2]) this[p] = v;
- else throw Error(invalidArgument + p + ': ' + v);
- }
- }
-
- if (p = 'crypto', useDefaults) this[p] = DEFAULTS[p];
- if ((v = obj[p]) !== void 0) {
- if (v === true || v === false || v === 0 || v === 1) {
- if (v) {
- if (typeof crypto != 'undefined' && crypto &&
- (crypto.getRandomValues || crypto.randomBytes)) {
- this[p] = true;
- } else {
- throw Error(cryptoUnavailable);
- }
- } else {
- this[p] = false;
- }
- } else {
- throw Error(invalidArgument + p + ': ' + v);
- }
- }
-
- return this;
-}
-
-
-/*
- * Return a new Decimal whose value is the cosine of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function cos(x) {
- return new this(x).cos();
-}
-
-
-/*
- * Return a new Decimal whose value is the hyperbolic cosine of `x`, rounded to precision
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function cosh(x) {
- return new this(x).cosh();
-}
-
-
-/*
- * Create and return a Decimal constructor with the same configuration properties as this Decimal
- * constructor.
- *
- */
-function clone(obj) {
- var i, p, ps;
-
- /*
- * The Decimal constructor and exported function.
- * Return a new Decimal instance.
- *
- * v {number|string|bigint|Decimal} A numeric value.
- *
- */
- function Decimal(v) {
- var e, i, t,
- x = this;
-
- // Decimal called without new.
- if (!(x instanceof Decimal)) return new Decimal(v);
-
- // Retain a reference to this Decimal constructor, and shadow Decimal.prototype.constructor
- // which points to Object.
- x.constructor = Decimal;
-
- if (isDecimalInstance(v)) {
- x.s = v.s;
-
- if (external) {
- if (!v.d || v.e > Decimal.maxE) {
-
- // Infinity.
- x.e = NaN;
- x.d = null;
- } else if (v.e < Decimal.minE) {
-
- // Zero.
- x.e = 0;
- x.d = [0];
- } else {
- x.e = v.e;
- x.d = v.d.slice();
- }
- } else {
- x.e = v.e;
- x.d = v.d ? v.d.slice() : v.d;
- }
-
- return;
- }
-
- t = typeof v;
-
- if (t === 'number') {
- if (v === 0) {
- x.s = 1 / v < 0 ? -1 : 1;
- x.e = 0;
- x.d = [0];
- return;
- }
-
- if (v < 0) {
- v = -v;
- x.s = -1;
- } else {
- x.s = 1;
- }
-
- // Fast path for small integers.
- if (v === ~~v && v < 1e7) {
- for (e = 0, i = v; i >= 10; i /= 10) e++;
-
- if (external) {
- if (e > Decimal.maxE) {
- x.e = NaN;
- x.d = null;
- } else if (e < Decimal.minE) {
- x.e = 0;
- x.d = [0];
- } else {
- x.e = e;
- x.d = [v];
- }
- } else {
- x.e = e;
- x.d = [v];
- }
-
- return;
- }
-
- // Infinity or NaN?
- if (v * 0 !== 0) {
- if (!v) x.s = NaN;
- x.e = NaN;
- x.d = null;
- return;
- }
-
- return parseDecimal(x, v.toString());
- }
-
- if (t === 'string') {
- if ((i = v.charCodeAt(0)) === 45) { // minus sign
- v = v.slice(1);
- x.s = -1;
- } else {
- if (i === 43) v = v.slice(1); // plus sign
- x.s = 1;
- }
-
- return isDecimal.test(v) ? parseDecimal(x, v) : parseOther(x, v);
- }
-
- if (t === 'bigint') {
- if (v < 0) {
- v = -v;
- x.s = -1;
- } else {
- x.s = 1;
- }
-
- return parseDecimal(x, v.toString());
- }
-
- throw Error(invalidArgument + v);
- }
-
- Decimal.prototype = P;
-
- Decimal.ROUND_UP = 0;
- Decimal.ROUND_DOWN = 1;
- Decimal.ROUND_CEIL = 2;
- Decimal.ROUND_FLOOR = 3;
- Decimal.ROUND_HALF_UP = 4;
- Decimal.ROUND_HALF_DOWN = 5;
- Decimal.ROUND_HALF_EVEN = 6;
- Decimal.ROUND_HALF_CEIL = 7;
- Decimal.ROUND_HALF_FLOOR = 8;
- Decimal.EUCLID = 9;
-
- Decimal.config = Decimal.set = config;
- Decimal.clone = clone;
- Decimal.isDecimal = isDecimalInstance;
-
- Decimal.abs = abs;
- Decimal.acos = acos;
- Decimal.acosh = acosh; // ES6
- Decimal.add = add;
- Decimal.asin = asin;
- Decimal.asinh = asinh; // ES6
- Decimal.atan = atan;
- Decimal.atanh = atanh; // ES6
- Decimal.atan2 = atan2;
- Decimal.cbrt = cbrt; // ES6
- Decimal.ceil = ceil;
- Decimal.clamp = clamp;
- Decimal.cos = cos;
- Decimal.cosh = cosh; // ES6
- Decimal.div = div;
- Decimal.exp = exp;
- Decimal.floor = floor;
- Decimal.hypot = hypot; // ES6
- Decimal.ln = ln;
- Decimal.log = log;
- Decimal.log10 = log10; // ES6
- Decimal.log2 = log2; // ES6
- Decimal.max = max;
- Decimal.min = min;
- Decimal.mod = mod;
- Decimal.mul = mul;
- Decimal.pow = pow;
- Decimal.random = random;
- Decimal.round = round;
- Decimal.sign = sign; // ES6
- Decimal.sin = sin;
- Decimal.sinh = sinh; // ES6
- Decimal.sqrt = sqrt;
- Decimal.sub = sub;
- Decimal.sum = sum;
- Decimal.tan = tan;
- Decimal.tanh = tanh; // ES6
- Decimal.trunc = trunc; // ES6
-
- if (obj === void 0) obj = {};
- if (obj) {
- if (obj.defaults !== true) {
- ps = ['precision', 'rounding', 'toExpNeg', 'toExpPos', 'maxE', 'minE', 'modulo', 'crypto'];
- for (i = 0; i < ps.length;) if (!obj.hasOwnProperty(p = ps[i++])) obj[p] = this[p];
- }
- }
-
- Decimal.config(obj);
-
- return Decimal;
-}
-
-
-/*
- * Return a new Decimal whose value is `x` divided by `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
-function div(x, y) {
- return new this(x).div(y);
-}
-
-
-/*
- * Return a new Decimal whose value is the natural exponential of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} The power to which to raise the base of the natural log.
- *
- */
-function exp(x) {
- return new this(x).exp();
-}
-
-
-/*
- * Return a new Decimal whose value is `x` round to an integer using `ROUND_FLOOR`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function floor(x) {
- return finalise(x = new this(x), x.e + 1, 3);
-}
-
-
-/*
- * Return a new Decimal whose value is the square root of the sum of the squares of the arguments,
- * rounded to `precision` significant digits using rounding mode `rounding`.
- *
- * hypot(a, b, ...) = sqrt(a^2 + b^2 + ...)
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
-function hypot() {
- var i, n,
- t = new this(0);
-
- external = false;
-
- for (i = 0; i < arguments.length;) {
- n = new this(arguments[i++]);
- if (!n.d) {
- if (n.s) {
- external = true;
- return new this(1 / 0);
- }
- t = n;
- } else if (t.d) {
- t = t.plus(n.times(n));
- }
- }
-
- external = true;
-
- return t.sqrt();
-}
-
-
-/*
- * Return true if object is a Decimal instance (where Decimal is any Decimal constructor),
- * otherwise return false.
- *
- */
-function isDecimalInstance(obj) {
- return obj instanceof Decimal || obj && obj.toStringTag === tag || false;
-}
-
-
-/*
- * Return a new Decimal whose value is the natural logarithm of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function ln(x) {
- return new this(x).ln();
-}
-
-
-/*
- * Return a new Decimal whose value is the log of `x` to the base `y`, or to base 10 if no base
- * is specified, rounded to `precision` significant digits using rounding mode `rounding`.
- *
- * log[y](x)
- *
- * x {number|string|bigint|Decimal} The argument of the logarithm.
- * y {number|string|bigint|Decimal} The base of the logarithm.
- *
- */
-function log(x, y) {
- return new this(x).log(y);
-}
-
-
-/*
- * Return a new Decimal whose value is the base 2 logarithm of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function log2(x) {
- return new this(x).log(2);
-}
-
-
-/*
- * Return a new Decimal whose value is the base 10 logarithm of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function log10(x) {
- return new this(x).log(10);
-}
-
-
-/*
- * Return a new Decimal whose value is the maximum of the arguments.
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
-function max() {
- return maxOrMin(this, arguments, -1);
-}
-
-
-/*
- * Return a new Decimal whose value is the minimum of the arguments.
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
-function min() {
- return maxOrMin(this, arguments, 1);
-}
-
-
-/*
- * Return a new Decimal whose value is `x` modulo `y`, rounded to `precision` significant digits
- * using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
-function mod(x, y) {
- return new this(x).mod(y);
-}
-
-
-/*
- * Return a new Decimal whose value is `x` multiplied by `y`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
-function mul(x, y) {
- return new this(x).mul(y);
-}
-
-
-/*
- * Return a new Decimal whose value is `x` raised to the power `y`, rounded to precision
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} The base.
- * y {number|string|bigint|Decimal} The exponent.
- *
- */
-function pow(x, y) {
- return new this(x).pow(y);
-}
-
-
-/*
- * Returns a new Decimal with a random value equal to or greater than 0 and less than 1, and with
- * `sd`, or `Decimal.precision` if `sd` is omitted, significant digits (or less if trailing zeros
- * are produced).
- *
- * [sd] {number} Significant digits. Integer, 0 to MAX_DIGITS inclusive.
- *
- */
-function random(sd) {
- var d, e, k, n,
- i = 0,
- r = new this(1),
- rd = [];
-
- if (sd === void 0) sd = this.precision;
- else checkInt32(sd, 1, MAX_DIGITS);
-
- k = Math.ceil(sd / LOG_BASE);
-
- if (!this.crypto) {
- for (; i < k;) rd[i++] = Math.random() * 1e7 | 0;
-
- // Browsers supporting crypto.getRandomValues.
- } else if (crypto.getRandomValues) {
- d = crypto.getRandomValues(new Uint32Array(k));
-
- for (; i < k;) {
- n = d[i];
-
- // 0 <= n < 4294967296
- // Probability n >= 4.29e9, is 4967296 / 4294967296 = 0.00116 (1 in 865).
- if (n >= 4.29e9) {
- d[i] = crypto.getRandomValues(new Uint32Array(1))[0];
- } else {
-
- // 0 <= n <= 4289999999
- // 0 <= (n % 1e7) <= 9999999
- rd[i++] = n % 1e7;
- }
- }
-
- // Node.js supporting crypto.randomBytes.
- } else if (crypto.randomBytes) {
-
- // buffer
- d = crypto.randomBytes(k *= 4);
-
- for (; i < k;) {
-
- // 0 <= n < 2147483648
- n = d[i] + (d[i + 1] << 8) + (d[i + 2] << 16) + ((d[i + 3] & 0x7f) << 24);
-
- // Probability n >= 2.14e9, is 7483648 / 2147483648 = 0.0035 (1 in 286).
- if (n >= 2.14e9) {
- crypto.randomBytes(4).copy(d, i);
- } else {
-
- // 0 <= n <= 2139999999
- // 0 <= (n % 1e7) <= 9999999
- rd.push(n % 1e7);
- i += 4;
- }
- }
-
- i = k / 4;
- } else {
- throw Error(cryptoUnavailable);
- }
-
- k = rd[--i];
- sd %= LOG_BASE;
-
- // Convert trailing digits to zeros according to sd.
- if (k && sd) {
- n = mathpow(10, LOG_BASE - sd);
- rd[i] = (k / n | 0) * n;
- }
-
- // Remove trailing words which are zero.
- for (; rd[i] === 0; i--) rd.pop();
-
- // Zero?
- if (i < 0) {
- e = 0;
- rd = [0];
- } else {
- e = -1;
-
- // Remove leading words which are zero and adjust exponent accordingly.
- for (; rd[0] === 0; e -= LOG_BASE) rd.shift();
-
- // Count the digits of the first word of rd to determine leading zeros.
- for (k = 1, n = rd[0]; n >= 10; n /= 10) k++;
-
- // Adjust the exponent for leading zeros of the first word of rd.
- if (k < LOG_BASE) e -= LOG_BASE - k;
- }
-
- r.e = e;
- r.d = rd;
-
- return r;
-}
-
-
-/*
- * Return a new Decimal whose value is `x` rounded to an integer using rounding mode `rounding`.
- *
- * To emulate `Math.round`, set rounding to 7 (ROUND_HALF_CEIL).
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function round(x) {
- return finalise(x = new this(x), x.e + 1, this.rounding);
-}
-
-
-/*
- * Return
- * 1 if x > 0,
- * -1 if x < 0,
- * 0 if x is 0,
- * -0 if x is -0,
- * NaN otherwise
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function sign(x) {
- x = new this(x);
- return x.d ? (x.d[0] ? x.s : 0 * x.s) : x.s || NaN;
-}
-
-
-/*
- * Return a new Decimal whose value is the sine of `x`, rounded to `precision` significant digits
- * using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function sin(x) {
- return new this(x).sin();
-}
-
-
-/*
- * Return a new Decimal whose value is the hyperbolic sine of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function sinh(x) {
- return new this(x).sinh();
-}
-
-
-/*
- * Return a new Decimal whose value is the square root of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function sqrt(x) {
- return new this(x).sqrt();
-}
-
-
-/*
- * Return a new Decimal whose value is `x` minus `y`, rounded to `precision` significant digits
- * using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal}
- * y {number|string|bigint|Decimal}
- *
- */
-function sub(x, y) {
- return new this(x).sub(y);
-}
-
-
-/*
- * Return a new Decimal whose value is the sum of the arguments, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * Only the result is rounded, not the intermediate calculations.
- *
- * arguments {number|string|bigint|Decimal}
- *
- */
-function sum() {
- var i = 0,
- args = arguments,
- x = new this(args[i]);
-
- external = false;
- for (; x.s && ++i < args.length;) x = x.plus(args[i]);
- external = true;
-
- return finalise(x, this.precision, this.rounding);
-}
-
-
-/*
- * Return a new Decimal whose value is the tangent of `x`, rounded to `precision` significant
- * digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function tan(x) {
- return new this(x).tan();
-}
-
-
-/*
- * Return a new Decimal whose value is the hyperbolic tangent of `x`, rounded to `precision`
- * significant digits using rounding mode `rounding`.
- *
- * x {number|string|bigint|Decimal} A value in radians.
- *
- */
-function tanh(x) {
- return new this(x).tanh();
-}
-
-
-/*
- * Return a new Decimal whose value is `x` truncated to an integer.
- *
- * x {number|string|bigint|Decimal}
- *
- */
-function trunc(x) {
- return finalise(x = new this(x), x.e + 1, 1);
-}
-
-
-P[Symbol.for('nodejs.util.inspect.custom')] = P.toString;
-P[Symbol.toStringTag] = 'Decimal';
-
-// Create and configure initial Decimal constructor.
-export var Decimal = P.constructor = clone(DEFAULTS);
-
-// Create the internal constants from their string values.
-LN10 = new Decimal(LN10);
-PI = new Decimal(PI);
-
-export default Decimal;
diff --git a/node_modules/decimal.js/package.json b/node_modules/decimal.js/package.json
deleted file mode 100644
index 4f84301..0000000
--- a/node_modules/decimal.js/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "name": "decimal.js",
- "description": "An arbitrary-precision Decimal type for JavaScript.",
- "version": "10.6.0",
- "keywords": [
- "arbitrary",
- "precision",
- "arithmetic",
- "big",
- "number",
- "decimal",
- "float",
- "biginteger",
- "bigdecimal",
- "bignumber",
- "bigint",
- "bignum"
- ],
- "repository" : {
- "type": "git",
- "url": "https://github.com/MikeMcl/decimal.js.git"
- },
- "main": "decimal",
- "module": "decimal.mjs",
- "browser": "decimal.js",
- "exports": {
- ".": {
- "types": "./decimal.d.ts",
- "import": "./decimal.mjs",
- "require": "./decimal.js"
- },
- "./decimal.mjs": "./decimal.mjs",
- "./decimal.js": "./decimal.js",
- "./package.json": "./package.json",
- "./decimal": {
- "types": "./decimal.d.ts",
- "import": "./decimal.mjs",
- "require": "./decimal.js"
- }
- },
- "author": {
- "name": "Michael Mclaughlin",
- "email": "M8ch88l@gmail.com"
- },
- "license": "MIT",
- "scripts": {
- "test": "node ./test/test.js"
- },
- "types": "decimal.d.ts",
- "files": [
- "decimal.js",
- "decimal.mjs",
- "decimal.d.ts"
- ]
-}
diff --git a/node_modules/destroy/LICENSE b/node_modules/destroy/LICENSE
new file mode 100644
index 0000000..0e2c35f
--- /dev/null
+++ b/node_modules/destroy/LICENSE
@@ -0,0 +1,23 @@
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Jonathan Ong me@jongleberry.com
+Copyright (c) 2015-2022 Douglas Christopher Wilson doug@somethingdoug.com
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/destroy/README.md b/node_modules/destroy/README.md
new file mode 100644
index 0000000..e7701ae
--- /dev/null
+++ b/node_modules/destroy/README.md
@@ -0,0 +1,63 @@
+# destroy
+
+[![NPM version][npm-image]][npm-url]
+[![Build Status][github-actions-ci-image]][github-actions-ci-url]
+[![Test coverage][coveralls-image]][coveralls-url]
+[![License][license-image]][license-url]
+[![Downloads][downloads-image]][downloads-url]
+
+Destroy a stream.
+
+This module is meant to ensure a stream gets destroyed, handling different APIs
+and Node.js bugs.
+
+## API
+
+```js
+var destroy = require('destroy')
+```
+
+### destroy(stream [, suppress])
+
+Destroy the given stream, and optionally suppress any future `error` events.
+
+In most cases, this is identical to a simple `stream.destroy()` call. The rules
+are as follows for a given stream:
+
+ 1. If the `stream` is an instance of `ReadStream`, then call `stream.destroy()`
+ and add a listener to the `open` event to call `stream.close()` if it is
+ fired. This is for a Node.js bug that will leak a file descriptor if
+ `.destroy()` is called before `open`.
+ 2. If the `stream` is an instance of a zlib stream, then call `stream.destroy()`
+ and close the underlying zlib handle if open, otherwise call `stream.close()`.
+ This is for consistency across Node.js versions and a Node.js bug that will
+ leak a native zlib handle.
+ 3. If the `stream` is not an instance of `Stream`, then nothing happens.
+ 4. If the `stream` has a `.destroy()` method, then call it.
+
+The function returns the `stream` passed in as the argument.
+
+## Example
+
+```js
+var destroy = require('destroy')
+
+var fs = require('fs')
+var stream = fs.createReadStream('package.json')
+
+// ... and later
+destroy(stream)
+```
+
+[npm-image]: https://img.shields.io/npm/v/destroy.svg?style=flat-square
+[npm-url]: https://npmjs.org/package/destroy
+[github-tag]: http://img.shields.io/github/tag/stream-utils/destroy.svg?style=flat-square
+[github-url]: https://github.com/stream-utils/destroy/tags
+[coveralls-image]: https://img.shields.io/coveralls/stream-utils/destroy.svg?style=flat-square
+[coveralls-url]: https://coveralls.io/r/stream-utils/destroy?branch=master
+[license-image]: http://img.shields.io/npm/l/destroy.svg?style=flat-square
+[license-url]: LICENSE.md
+[downloads-image]: http://img.shields.io/npm/dm/destroy.svg?style=flat-square
+[downloads-url]: https://npmjs.org/package/destroy
+[github-actions-ci-image]: https://img.shields.io/github/workflow/status/stream-utils/destroy/ci/master?label=ci&style=flat-square
+[github-actions-ci-url]: https://github.com/stream-utils/destroy/actions/workflows/ci.yml
diff --git a/node_modules/destroy/index.js b/node_modules/destroy/index.js
new file mode 100644
index 0000000..7fd5c09
--- /dev/null
+++ b/node_modules/destroy/index.js
@@ -0,0 +1,209 @@
+/*!
+ * destroy
+ * Copyright(c) 2014 Jonathan Ong
+ * Copyright(c) 2015-2022 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var EventEmitter = require('events').EventEmitter
+var ReadStream = require('fs').ReadStream
+var Stream = require('stream')
+var Zlib = require('zlib')
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = destroy
+
+/**
+ * Destroy the given stream, and optionally suppress any future `error` events.
+ *
+ * @param {object} stream
+ * @param {boolean} suppress
+ * @public
+ */
+
+function destroy (stream, suppress) {
+ if (isFsReadStream(stream)) {
+ destroyReadStream(stream)
+ } else if (isZlibStream(stream)) {
+ destroyZlibStream(stream)
+ } else if (hasDestroy(stream)) {
+ stream.destroy()
+ }
+
+ if (isEventEmitter(stream) && suppress) {
+ stream.removeAllListeners('error')
+ stream.addListener('error', noop)
+ }
+
+ return stream
+}
+
+/**
+ * Destroy a ReadStream.
+ *
+ * @param {object} stream
+ * @private
+ */
+
+function destroyReadStream (stream) {
+ stream.destroy()
+
+ if (typeof stream.close === 'function') {
+ // node.js core bug work-around
+ stream.on('open', onOpenClose)
+ }
+}
+
+/**
+ * Close a Zlib stream.
+ *
+ * Zlib streams below Node.js 4.5.5 have a buggy implementation
+ * of .close() when zlib encountered an error.
+ *
+ * @param {object} stream
+ * @private
+ */
+
+function closeZlibStream (stream) {
+ if (stream._hadError === true) {
+ var prop = stream._binding === null
+ ? '_binding'
+ : '_handle'
+
+ stream[prop] = {
+ close: function () { this[prop] = null }
+ }
+ }
+
+ stream.close()
+}
+
+/**
+ * Destroy a Zlib stream.
+ *
+ * Zlib streams don't have a destroy function in Node.js 6. On top of that
+ * simply calling destroy on a zlib stream in Node.js 8+ will result in a
+ * memory leak. So until that is fixed, we need to call both close AND destroy.
+ *
+ * PR to fix memory leak: https://github.com/nodejs/node/pull/23734
+ *
+ * In Node.js 6+8, it's important that destroy is called before close as the
+ * stream would otherwise emit the error 'zlib binding closed'.
+ *
+ * @param {object} stream
+ * @private
+ */
+
+function destroyZlibStream (stream) {
+ if (typeof stream.destroy === 'function') {
+ // node.js core bug work-around
+ // istanbul ignore if: node.js 0.8
+ if (stream._binding) {
+ // node.js < 0.10.0
+ stream.destroy()
+ if (stream._processing) {
+ stream._needDrain = true
+ stream.once('drain', onDrainClearBinding)
+ } else {
+ stream._binding.clear()
+ }
+ } else if (stream._destroy && stream._destroy !== Stream.Transform.prototype._destroy) {
+ // node.js >= 12, ^11.1.0, ^10.15.1
+ stream.destroy()
+ } else if (stream._destroy && typeof stream.close === 'function') {
+ // node.js 7, 8
+ stream.destroyed = true
+ stream.close()
+ } else {
+ // fallback
+ // istanbul ignore next
+ stream.destroy()
+ }
+ } else if (typeof stream.close === 'function') {
+ // node.js < 8 fallback
+ closeZlibStream(stream)
+ }
+}
+
+/**
+ * Determine if stream has destroy.
+ * @private
+ */
+
+function hasDestroy (stream) {
+ return stream instanceof Stream &&
+ typeof stream.destroy === 'function'
+}
+
+/**
+ * Determine if val is EventEmitter.
+ * @private
+ */
+
+function isEventEmitter (val) {
+ return val instanceof EventEmitter
+}
+
+/**
+ * Determine if stream is fs.ReadStream stream.
+ * @private
+ */
+
+function isFsReadStream (stream) {
+ return stream instanceof ReadStream
+}
+
+/**
+ * Determine if stream is Zlib stream.
+ * @private
+ */
+
+function isZlibStream (stream) {
+ return stream instanceof Zlib.Gzip ||
+ stream instanceof Zlib.Gunzip ||
+ stream instanceof Zlib.Deflate ||
+ stream instanceof Zlib.DeflateRaw ||
+ stream instanceof Zlib.Inflate ||
+ stream instanceof Zlib.InflateRaw ||
+ stream instanceof Zlib.Unzip
+}
+
+/**
+ * No-op function.
+ * @private
+ */
+
+function noop () {}
+
+/**
+ * On drain handler to clear binding.
+ * @private
+ */
+
+// istanbul ignore next: node.js 0.8
+function onDrainClearBinding () {
+ this._binding.clear()
+}
+
+/**
+ * On open handler to close stream.
+ * @private
+ */
+
+function onOpenClose () {
+ if (typeof this.fd === 'number') {
+ // actually close down the fd
+ this.close()
+ }
+}
diff --git a/node_modules/destroy/package.json b/node_modules/destroy/package.json
new file mode 100644
index 0000000..c85e438
--- /dev/null
+++ b/node_modules/destroy/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "destroy",
+ "description": "destroy a stream if possible",
+ "version": "1.2.0",
+ "author": {
+ "name": "Jonathan Ong",
+ "email": "me@jongleberry.com",
+ "url": "http://jongleberry.com",
+ "twitter": "https://twitter.com/jongleberry"
+ },
+ "contributors": [
+ "Douglas Christopher Wilson "
+ ],
+ "license": "MIT",
+ "repository": "stream-utils/destroy",
+ "devDependencies": {
+ "eslint": "7.32.0",
+ "eslint-config-standard": "14.1.1",
+ "eslint-plugin-import": "2.25.4",
+ "eslint-plugin-node": "11.1.0",
+ "eslint-plugin-promise": "5.2.0",
+ "eslint-plugin-standard": "4.1.0",
+ "mocha": "9.2.2",
+ "nyc": "15.1.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ },
+ "scripts": {
+ "lint": "eslint .",
+ "test": "mocha --reporter spec",
+ "test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
+ "test-cov": "nyc --reporter=html --reporter=text npm test"
+ },
+ "files": [
+ "index.js",
+ "LICENSE"
+ ],
+ "keywords": [
+ "stream",
+ "streams",
+ "destroy",
+ "cleanup",
+ "leak",
+ "fd"
+ ]
+}
diff --git a/node_modules/escape-latex/LICENSE.md b/node_modules/escape-latex/LICENSE.md
deleted file mode 100644
index 6e54eff..0000000
--- a/node_modules/escape-latex/LICENSE.md
+++ /dev/null
@@ -1,18 +0,0 @@
-Copyright (c) 2012 Dang Mai
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/escape-latex/README.md b/node_modules/escape-latex/README.md
deleted file mode 100644
index 78ff9da..0000000
--- a/node_modules/escape-latex/README.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# escape-latex
-
-[](https://greenkeeper.io/)
-
-[](https://travis-ci.org/dangmai/escape-latex)
-
-Escape LaTeX special characters with Javascript in NodeJS (>= 4.x) environment.
-
-## Usage
-
-```javascript
-npm install escape-latex
-var lescape = require('escape-latex');
-lescape("String to be escaped here #yolo");
-```
-
-## API
-
-```javascript
-lescape((input: String), {
- preserveFormatting: Boolean,
- escapeMapFn: Function,
-});
-```
-
-By default,
-`escape-latex` only escapes characters that would result in malformed LaTeX.
-These characters include `# $ % & \ ^ _ { }`.
-
-This means that the final LaTeX output might not look the same as your input Javascript string.
-For example, multiple spaces are kept as-is, which may be truncated to 1 space by your LaTeX software.
-
-If you want the final output string to be as similar to your input Javascript string as possible,
-you can set the `preserveFormatting` param to `true`, like so:
-
-```javascript
-lescape("Hello World", { preserveFormatting: true });
-// Hello~~~World
-```
-
-Which will be converted to three non-breaking spaces by your LaTeX software.
-
-The list of format characters that are escaped include `space, \t (tab), – (en-dash), — (em-dash)`.
-
-There is also the param `escapeMapFn` to modify the mapping of escaped characters,
-so you can add/modify/remove your own escapes if necessary.
-
-It accepts a callback function that takes in the default character escapes and the formatting escapes as parameters, and returns a complete escape mapping. Here's an example:
-
-```javascript
-lescape("Hello World", {
- preseveFormatting: true,
- escapeMapFn: function(defaultEscapes, formattingEscapes) {
- formattingEscapes[" "] = "\\\\";
- return Object.assign({}, defaultEscapes, formattingEscapes);
- },
-});
-// Hello\\\\\\world
-```
-
-## Testing
-
-```
-npm test
-```
-
-## Notes
-
-* If you are updating from `escape-latex < 1.0.0`,
- the `en-dash` and `em-dash` are no longer escaped by default.
- Please use `preserveFormatting` to turn them on if necessary.
-
-## License
-
-MIT
diff --git a/node_modules/escape-latex/dist/index.js b/node_modules/escape-latex/dist/index.js
deleted file mode 100644
index 0da9c0d..0000000
--- a/node_modules/escape-latex/dist/index.js
+++ /dev/null
@@ -1,80 +0,0 @@
-"use strict";
-
-// Map the characters to escape to their escaped values. The list is derived
-// from http://www.cespedes.org/blog/85/how-to-escape-latex-special-characters
-
-var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
-
-var defaultEscapes = {
- "{": "\\{",
- "}": "\\}",
- "\\": "\\textbackslash{}",
- "#": "\\#",
- $: "\\$",
- "%": "\\%",
- "&": "\\&",
- "^": "\\textasciicircum{}",
- _: "\\_",
- "~": "\\textasciitilde{}"
-};
-var formatEscapes = {
- "\u2013": "\\--",
- "\u2014": "\\---",
- " ": "~",
- "\t": "\\qquad{}",
- "\r\n": "\\newline{}",
- "\n": "\\newline{}"
-};
-
-var defaultEscapeMapFn = function defaultEscapeMapFn(defaultEscapes, formatEscapes) {
- return _extends({}, defaultEscapes, formatEscapes);
-};
-
-/**
- * Escape a string to be used in LaTeX documents.
- * @param {string} str the string to be escaped.
- * @param {boolean} params.preserveFormatting whether formatting escapes should
- * be performed (default: false).
- * @param {function} params.escapeMapFn the function to modify the escape maps.
- * @return {string} the escaped string, ready to be used in LaTeX.
- */
-module.exports = function (str) {
- var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
- _ref$preserveFormatti = _ref.preserveFormatting,
- preserveFormatting = _ref$preserveFormatti === undefined ? false : _ref$preserveFormatti,
- _ref$escapeMapFn = _ref.escapeMapFn,
- escapeMapFn = _ref$escapeMapFn === undefined ? defaultEscapeMapFn : _ref$escapeMapFn;
-
- var runningStr = String(str);
- var result = "";
-
- var escapes = escapeMapFn(_extends({}, defaultEscapes), preserveFormatting ? _extends({}, formatEscapes) : {});
- var escapeKeys = Object.keys(escapes); // as it is reused later on
-
- // Algorithm: Go through the string character by character, if it matches
- // with one of the special characters then we'll replace it with the escaped
- // version.
-
- var _loop = function _loop() {
- var specialCharFound = false;
- escapeKeys.forEach(function (key, index) {
- if (specialCharFound) {
- return;
- }
- if (runningStr.length >= key.length && runningStr.slice(0, key.length) === key) {
- result += escapes[escapeKeys[index]];
- runningStr = runningStr.slice(key.length, runningStr.length);
- specialCharFound = true;
- }
- });
- if (!specialCharFound) {
- result += runningStr.slice(0, 1);
- runningStr = runningStr.slice(1, runningStr.length);
- }
- };
-
- while (runningStr) {
- _loop();
- }
- return result;
-};
\ No newline at end of file
diff --git a/node_modules/escape-latex/package.json b/node_modules/escape-latex/package.json
deleted file mode 100644
index a57945d..0000000
--- a/node_modules/escape-latex/package.json
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- "name": "escape-latex",
- "version": "1.2.0",
- "description": "Escape LaTeX special characters with Javascript",
- "main": "./dist/index.js",
- "files": ["dist"],
- "scripts": {
- "test": "mocha --require babel-core/register -u tdd ./src/**/*.test.js",
- "preversion": "npm test && npm run build",
- "postversion": "git push && git push --tags",
- "precommit": "npm run lint && lint-staged",
- "prettier": "prettier --write ./src/**/*.js",
- "lint": "eslint ./src",
- "init": "mkdir dist",
- "clean": "rm -rf dist",
- "prebuild": "npm run clean && npm run init",
- "build": "babel ./src -d ./dist --ignore index.test.js"
- },
- "lint-staged": {
- "*.{js,json,css,md}": ["npm run prettier", "git add"]
- },
- "eslintConfig": {
- "parserOptions": {
- "ecmaVersion": 8
- },
- "extends": ["eslint:recommended", "google", "prettier"],
- "env": {
- "node": "true"
- }
- },
- "prettier": {
- "trailingComma": "all"
- },
- "repository": {
- "type": "git",
- "url": "https://github.com/dangmai/escape-latex"
- },
- "keywords": ["latex", "escape"],
- "devDependencies": {
- "babel-cli": "^6.26.0",
- "babel-core": "^6.26.0",
- "babel-plugin-transform-object-assign": "^6.22.0",
- "babel-preset-env": "^1.6.1",
- "chai": "^4.1.2",
- "eslint": "^5.0.1",
- "eslint-config-google": "^0.9.1",
- "eslint-config-prettier": "^3.0.1",
- "husky": "^0.14.3",
- "lint-staged": "^7.0.5",
- "mocha": "^5.0.0",
- "prettier": "^1.9.2"
- },
- "author": "Dang Mai",
- "license": "MIT"
-}
diff --git a/node_modules/express/History.md b/node_modules/express/History.md
new file mode 100644
index 0000000..150c2ab
--- /dev/null
+++ b/node_modules/express/History.md
@@ -0,0 +1,3667 @@
+4.22.1 / 2025-12-01
+==========
+
+ * Revert security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6))
+
+4.22.0 / 2025-12-01
+==========
+ * Security fix for [CVE-2024-51999](https://www.cve.org/CVERecord?id=CVE-2024-51999) ([GHSA-pj86-cfqh-vqx6](https://github.com/expressjs/express/security/advisories/GHSA-pj86-cfqh-vqx6))
+ * deps: use tilde notation for dependencies
+ * deps: qs@6.14.0
+
+4.21.2 / 2024-11-06
+==========
+
+ * deps: path-to-regexp@0.1.12
+ - Fix backtracking protection
+ * deps: path-to-regexp@0.1.11
+ - Throws an error on invalid path values
+
+4.21.1 / 2024-10-08
+==========
+
+ * Backported a fix for [CVE-2024-47764](https://nvd.nist.gov/vuln/detail/CVE-2024-47764)
+
+
+4.21.0 / 2024-09-11
+==========
+
+ * Deprecate `res.location("back")` and `res.redirect("back")` magic string
+ * deps: serve-static@1.16.2
+ * includes send@0.19.0
+ * deps: finalhandler@1.3.1
+ * deps: qs@6.13.0
+
+4.20.0 / 2024-09-10
+==========
+ * deps: serve-static@0.16.0
+ * Remove link renderization in html while redirecting
+ * deps: send@0.19.0
+ * Remove link renderization in html while redirecting
+ * deps: body-parser@0.6.0
+ * add `depth` option to customize the depth level in the parser
+ * IMPORTANT: The default `depth` level for parsing URL-encoded data is now `32` (previously was `Infinity`)
+ * Remove link renderization in html while using `res.redirect`
+ * deps: path-to-regexp@0.1.10
+ - Adds support for named matching groups in the routes using a regex
+ - Adds backtracking protection to parameters without regexes defined
+ * deps: encodeurl@~2.0.0
+ - Removes encoding of `\`, `|`, and `^` to align better with URL spec
+ * Deprecate passing `options.maxAge` and `options.expires` to `res.clearCookie`
+ - Will be ignored in v5, clearCookie will set a cookie with an expires in the past to instruct clients to delete the cookie
+
+4.19.2 / 2024-03-25
+==========
+
+ * Improved fix for open redirect allow list bypass
+
+4.19.1 / 2024-03-20
+==========
+
+ * Allow passing non-strings to res.location with new encoding handling checks
+
+4.19.0 / 2024-03-20
+==========
+
+ * Prevent open redirect allow list bypass due to encodeurl
+ * deps: cookie@0.6.0
+
+4.18.3 / 2024-02-29
+==========
+
+ * Fix routing requests without method
+ * deps: body-parser@1.20.2
+ - Fix strict json error message on Node.js 19+
+ - deps: content-type@~1.0.5
+ - deps: raw-body@2.5.2
+ * deps: cookie@0.6.0
+ - Add `partitioned` option
+
+4.18.2 / 2022-10-08
+===================
+
+ * Fix regression routing a large stack in a single route
+ * deps: body-parser@1.20.1
+ - deps: qs@6.11.0
+ - perf: remove unnecessary object clone
+ * deps: qs@6.11.0
+
+4.18.1 / 2022-04-29
+===================
+
+ * Fix hanging on large stack of sync routes
+
+4.18.0 / 2022-04-25
+===================
+
+ * Add "root" option to `res.download`
+ * Allow `options` without `filename` in `res.download`
+ * Deprecate string and non-integer arguments to `res.status`
+ * Fix behavior of `null`/`undefined` as `maxAge` in `res.cookie`
+ * Fix handling very large stacks of sync middleware
+ * Ignore `Object.prototype` values in settings through `app.set`/`app.get`
+ * Invoke `default` with same arguments as types in `res.format`
+ * Support proper 205 responses using `res.send`
+ * Use `http-errors` for `res.format` error
+ * deps: body-parser@1.20.0
+ - Fix error message for json parse whitespace in `strict`
+ - Fix internal error when inflated body exceeds limit
+ - Prevent loss of async hooks context
+ - Prevent hanging when request already read
+ - deps: depd@2.0.0
+ - deps: http-errors@2.0.0
+ - deps: on-finished@2.4.1
+ - deps: qs@6.10.3
+ - deps: raw-body@2.5.1
+ * deps: cookie@0.5.0
+ - Add `priority` option
+ - Fix `expires` option to reject invalid dates
+ * deps: depd@2.0.0
+ - Replace internal `eval` usage with `Function` constructor
+ - Use instance methods on `process` to check for listeners
+ * deps: finalhandler@1.2.0
+ - Remove set content headers that break response
+ - deps: on-finished@2.4.1
+ - deps: statuses@2.0.1
+ * deps: on-finished@2.4.1
+ - Prevent loss of async hooks context
+ * deps: qs@6.10.3
+ * deps: send@0.18.0
+ - Fix emitted 416 error missing headers property
+ - Limit the headers removed for 304 response
+ - deps: depd@2.0.0
+ - deps: destroy@1.2.0
+ - deps: http-errors@2.0.0
+ - deps: on-finished@2.4.1
+ - deps: statuses@2.0.1
+ * deps: serve-static@1.15.0
+ - deps: send@0.18.0
+ * deps: statuses@2.0.1
+ - Remove code 306
+ - Rename `425 Unordered Collection` to standard `425 Too Early`
+
+4.17.3 / 2022-02-16
+===================
+
+ * deps: accepts@~1.3.8
+ - deps: mime-types@~2.1.34
+ - deps: negotiator@0.6.3
+ * deps: body-parser@1.19.2
+ - deps: bytes@3.1.2
+ - deps: qs@6.9.7
+ - deps: raw-body@2.4.3
+ * deps: cookie@0.4.2
+ * deps: qs@6.9.7
+ * Fix handling of `__proto__` keys
+ * pref: remove unnecessary regexp for trust proxy
+
+4.17.2 / 2021-12-16
+===================
+
+ * Fix handling of `undefined` in `res.jsonp`
+ * Fix handling of `undefined` when `"json escape"` is enabled
+ * Fix incorrect middleware execution with unanchored `RegExp`s
+ * Fix `res.jsonp(obj, status)` deprecation message
+ * Fix typo in `res.is` JSDoc
+ * deps: body-parser@1.19.1
+ - deps: bytes@3.1.1
+ - deps: http-errors@1.8.1
+ - deps: qs@6.9.6
+ - deps: raw-body@2.4.2
+ - deps: safe-buffer@5.2.1
+ - deps: type-is@~1.6.18
+ * deps: content-disposition@0.5.4
+ - deps: safe-buffer@5.2.1
+ * deps: cookie@0.4.1
+ - Fix `maxAge` option to reject invalid values
+ * deps: proxy-addr@~2.0.7
+ - Use `req.socket` over deprecated `req.connection`
+ - deps: forwarded@0.2.0
+ - deps: ipaddr.js@1.9.1
+ * deps: qs@6.9.6
+ * deps: safe-buffer@5.2.1
+ * deps: send@0.17.2
+ - deps: http-errors@1.8.1
+ - deps: ms@2.1.3
+ - pref: ignore empty http tokens
+ * deps: serve-static@1.14.2
+ - deps: send@0.17.2
+ * deps: setprototypeof@1.2.0
+
+4.17.1 / 2019-05-25
+===================
+
+ * Revert "Improve error message for `null`/`undefined` to `res.status`"
+
+4.17.0 / 2019-05-16
+===================
+
+ * Add `express.raw` to parse bodies into `Buffer`
+ * Add `express.text` to parse bodies into string
+ * Improve error message for non-strings to `res.sendFile`
+ * Improve error message for `null`/`undefined` to `res.status`
+ * Support multiple hosts in `X-Forwarded-Host`
+ * deps: accepts@~1.3.7
+ * deps: body-parser@1.19.0
+ - Add encoding MIK
+ - Add petabyte (`pb`) support
+ - Fix parsing array brackets after index
+ - deps: bytes@3.1.0
+ - deps: http-errors@1.7.2
+ - deps: iconv-lite@0.4.24
+ - deps: qs@6.7.0
+ - deps: raw-body@2.4.0
+ - deps: type-is@~1.6.17
+ * deps: content-disposition@0.5.3
+ * deps: cookie@0.4.0
+ - Add `SameSite=None` support
+ * deps: finalhandler@~1.1.2
+ - Set stricter `Content-Security-Policy` header
+ - deps: parseurl@~1.3.3
+ - deps: statuses@~1.5.0
+ * deps: parseurl@~1.3.3
+ * deps: proxy-addr@~2.0.5
+ - deps: ipaddr.js@1.9.0
+ * deps: qs@6.7.0
+ - Fix parsing array brackets after index
+ * deps: range-parser@~1.2.1
+ * deps: send@0.17.1
+ - Set stricter CSP header in redirect & error responses
+ - deps: http-errors@~1.7.2
+ - deps: mime@1.6.0
+ - deps: ms@2.1.1
+ - deps: range-parser@~1.2.1
+ - deps: statuses@~1.5.0
+ - perf: remove redundant `path.normalize` call
+ * deps: serve-static@1.14.1
+ - Set stricter CSP header in redirect response
+ - deps: parseurl@~1.3.3
+ - deps: send@0.17.1
+ * deps: setprototypeof@1.1.1
+ * deps: statuses@~1.5.0
+ - Add `103 Early Hints`
+ * deps: type-is@~1.6.18
+ - deps: mime-types@~2.1.24
+ - perf: prevent internal `throw` on invalid type
+
+4.16.4 / 2018-10-10
+===================
+
+ * Fix issue where `"Request aborted"` may be logged in `res.sendfile`
+ * Fix JSDoc for `Router` constructor
+ * deps: body-parser@1.18.3
+ - Fix deprecation warnings on Node.js 10+
+ - Fix stack trace for strict json parse error
+ - deps: depd@~1.1.2
+ - deps: http-errors@~1.6.3
+ - deps: iconv-lite@0.4.23
+ - deps: qs@6.5.2
+ - deps: raw-body@2.3.3
+ - deps: type-is@~1.6.16
+ * deps: proxy-addr@~2.0.4
+ - deps: ipaddr.js@1.8.0
+ * deps: qs@6.5.2
+ * deps: safe-buffer@5.1.2
+
+4.16.3 / 2018-03-12
+===================
+
+ * deps: accepts@~1.3.5
+ - deps: mime-types@~2.1.18
+ * deps: depd@~1.1.2
+ - perf: remove argument reassignment
+ * deps: encodeurl@~1.0.2
+ - Fix encoding `%` as last character
+ * deps: finalhandler@1.1.1
+ - Fix 404 output for bad / missing pathnames
+ - deps: encodeurl@~1.0.2
+ - deps: statuses@~1.4.0
+ * deps: proxy-addr@~2.0.3
+ - deps: ipaddr.js@1.6.0
+ * deps: send@0.16.2
+ - Fix incorrect end tag in default error & redirects
+ - deps: depd@~1.1.2
+ - deps: encodeurl@~1.0.2
+ - deps: statuses@~1.4.0
+ * deps: serve-static@1.13.2
+ - Fix incorrect end tag in redirects
+ - deps: encodeurl@~1.0.2
+ - deps: send@0.16.2
+ * deps: statuses@~1.4.0
+ * deps: type-is@~1.6.16
+ - deps: mime-types@~2.1.18
+
+4.16.2 / 2017-10-09
+===================
+
+ * Fix `TypeError` in `res.send` when given `Buffer` and `ETag` header set
+ * perf: skip parsing of entire `X-Forwarded-Proto` header
+
+4.16.1 / 2017-09-29
+===================
+
+ * deps: send@0.16.1
+ * deps: serve-static@1.13.1
+ - Fix regression when `root` is incorrectly set to a file
+ - deps: send@0.16.1
+
+4.16.0 / 2017-09-28
+===================
+
+ * Add `"json escape"` setting for `res.json` and `res.jsonp`
+ * Add `express.json` and `express.urlencoded` to parse bodies
+ * Add `options` argument to `res.download`
+ * Improve error message when autoloading invalid view engine
+ * Improve error messages when non-function provided as middleware
+ * Skip `Buffer` encoding when not generating ETag for small response
+ * Use `safe-buffer` for improved Buffer API
+ * deps: accepts@~1.3.4
+ - deps: mime-types@~2.1.16
+ * deps: content-type@~1.0.4
+ - perf: remove argument reassignment
+ - perf: skip parameter parsing when no parameters
+ * deps: etag@~1.8.1
+ - perf: replace regular expression with substring
+ * deps: finalhandler@1.1.0
+ - Use `res.headersSent` when available
+ * deps: parseurl@~1.3.2
+ - perf: reduce overhead for full URLs
+ - perf: unroll the "fast-path" `RegExp`
+ * deps: proxy-addr@~2.0.2
+ - Fix trimming leading / trailing OWS in `X-Forwarded-For`
+ - deps: forwarded@~0.1.2
+ - deps: ipaddr.js@1.5.2
+ - perf: reduce overhead when no `X-Forwarded-For` header
+ * deps: qs@6.5.1
+ - Fix parsing & compacting very deep objects
+ * deps: send@0.16.0
+ - Add 70 new types for file extensions
+ - Add `immutable` option
+ - Fix missing `
Connect with us
+Join the Vite community
++-
+
+
+ GitHub
+
+
+ -
+
+
+ Discord
+
+
+ -
+
+
+ X.com
+
+
+ -
+
+
+ Bluesky
+
+
+
+