From 936c56946866e93eb52e31c8250f06483f4981e3 Mon Sep 17 00:00:00 2001
From: Limit6 <81852696+Limit-sest@users.noreply.github.com>
Date: Tue, 17 Sep 2024 21:29:16 +0200
Subject: [PATCH] Automatic commit: 2024-09-17 21:29:16
---
.obsidian/.syncthing.app.json.tmp | 1 +
.obsidian/.syncthing.appearance.json.tmp | 4 +
.../.syncthing.community-plugins.json.tmp | 11 +
.obsidian/.syncthing.workspace.json.tmp | 156 +
.obsidian/community-plugins.json | 9 +-
...sync-conflict-20240917-212208-4CIB3I6.json | 11 +
...sync-conflict-20240917-212320-4CIB3I6.json | 11 +
.../plugins/heading-level-indent/main.js | 0
.../obsidian-excalidraw-plugin/main.js | 0
.../obsidian-excalidraw-plugin/manifest.json | 24 +-
.../plugins/obsidian-export-image/main.js | 0
.../obsidian-git/.syncthing.data.json.tmp | 58 +
.obsidian/plugins/obsidian-git/data.json | 14 +-
...sync-conflict-20240917-212208-4CIB3I6.json | 58 +
...sync-conflict-20240917-212320-4CIB3I6.json | 58 +
.obsidian/plugins/obsidian-git/main.js | 0
.../plugins/obsidian-icon-folder/main.js | 56 +-
.../plugins/obsidian-icon-folder/styles.css | 220 +-
.../plugins/obsidian-style-settings/main.js | 1126 +-
.obsidian/plugins/quick-latex/main.js | 3896 +++---
.obsidian/plugins/quick-latex/manifest.json | 20 +-
.obsidian/plugins/quick-latex/styles.css | 24 +-
.obsidian/plugins/symbols-prettifier/main.js | 0
.../plugins/table-editor-obsidian/main.js | 11388 ++++++++--------
.obsidian/workspace.json | 34 +-
...sync-conflict-20240917-212208-4CIB3I6.json | 156 +
...sync-conflict-20240917-212320-4CIB3I6.json | 156 +
27 files changed, 9085 insertions(+), 8406 deletions(-)
create mode 100644 .obsidian/.syncthing.app.json.tmp
create mode 100644 .obsidian/.syncthing.appearance.json.tmp
create mode 100644 .obsidian/.syncthing.community-plugins.json.tmp
create mode 100644 .obsidian/.syncthing.workspace.json.tmp
create mode 100644 .obsidian/community-plugins.sync-conflict-20240917-212208-4CIB3I6.json
create mode 100644 .obsidian/community-plugins.sync-conflict-20240917-212320-4CIB3I6.json
mode change 100644 => 100755 .obsidian/plugins/heading-level-indent/main.js
mode change 100644 => 100755 .obsidian/plugins/obsidian-excalidraw-plugin/main.js
mode change 100644 => 100755 .obsidian/plugins/obsidian-export-image/main.js
create mode 100644 .obsidian/plugins/obsidian-git/.syncthing.data.json.tmp
create mode 100644 .obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212208-4CIB3I6.json
create mode 100644 .obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212320-4CIB3I6.json
mode change 100644 => 100755 .obsidian/plugins/obsidian-git/main.js
mode change 100644 => 100755 .obsidian/plugins/obsidian-icon-folder/main.js
mode change 100644 => 100755 .obsidian/plugins/obsidian-style-settings/main.js
mode change 100644 => 100755 .obsidian/plugins/quick-latex/main.js
mode change 100644 => 100755 .obsidian/plugins/symbols-prettifier/main.js
mode change 100644 => 100755 .obsidian/plugins/table-editor-obsidian/main.js
create mode 100644 .obsidian/workspace.sync-conflict-20240917-212208-4CIB3I6.json
create mode 100644 .obsidian/workspace.sync-conflict-20240917-212320-4CIB3I6.json
diff --git a/.obsidian/.syncthing.app.json.tmp b/.obsidian/.syncthing.app.json.tmp
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/.obsidian/.syncthing.app.json.tmp
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/.obsidian/.syncthing.appearance.json.tmp b/.obsidian/.syncthing.appearance.json.tmp
new file mode 100644
index 0000000..2b00d2b
--- /dev/null
+++ b/.obsidian/.syncthing.appearance.json.tmp
@@ -0,0 +1,4 @@
+{
+ "cssTheme": "Catppuccin",
+ "textFontFamily": "Inter"
+}
\ No newline at end of file
diff --git a/.obsidian/.syncthing.community-plugins.json.tmp b/.obsidian/.syncthing.community-plugins.json.tmp
new file mode 100644
index 0000000..923efdd
--- /dev/null
+++ b/.obsidian/.syncthing.community-plugins.json.tmp
@@ -0,0 +1,11 @@
+[
+ "symbols-prettifier",
+ "obsidian-style-settings",
+ "obsidian-export-image",
+ "table-editor-obsidian",
+ "obsidian-icon-folder",
+ "quick-latex",
+ "heading-level-indent",
+ "obsidian-excalidraw-plugin",
+ "obsidian-git"
+]
\ No newline at end of file
diff --git a/.obsidian/.syncthing.workspace.json.tmp b/.obsidian/.syncthing.workspace.json.tmp
new file mode 100644
index 0000000..283b812
--- /dev/null
+++ b/.obsidian/.syncthing.workspace.json.tmp
@@ -0,0 +1,156 @@
+{
+ "main": {
+ "id": "ee5d534d22980344",
+ "type": "split",
+ "children": [
+ {
+ "id": "7c1eca489be03564",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "54139872f1da29d8",
+ "type": "leaf",
+ "state": {
+ "type": "markdown",
+ "state": {
+ "file": "README.md",
+ "mode": "source",
+ "source": false
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "vertical"
+ },
+ "left": {
+ "id": "fc1e8907017830f9",
+ "type": "split",
+ "children": [
+ {
+ "id": "9a60d4d5152c3311",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "9341cdda69dbca7f",
+ "type": "leaf",
+ "state": {
+ "type": "file-explorer",
+ "state": {
+ "sortOrder": "alphabetical"
+ }
+ }
+ },
+ {
+ "id": "54f47b860bc7ee13",
+ "type": "leaf",
+ "state": {
+ "type": "search",
+ "state": {
+ "query": "",
+ "matchingCase": false,
+ "explainSearch": false,
+ "collapseAll": false,
+ "extraContext": false,
+ "sortOrder": "alphabetical"
+ }
+ }
+ },
+ {
+ "id": "5550d38f8d962665",
+ "type": "leaf",
+ "state": {
+ "type": "bookmarks",
+ "state": {}
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "horizontal",
+ "width": 300
+ },
+ "right": {
+ "id": "769dc607ac2c8f47",
+ "type": "split",
+ "children": [
+ {
+ "id": "bbb36cfce0e5c758",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "d5de186f06e30619",
+ "type": "leaf",
+ "state": {
+ "type": "backlink",
+ "state": {
+ "file": "README.md",
+ "collapseAll": false,
+ "extraContext": false,
+ "sortOrder": "alphabetical",
+ "showSearch": false,
+ "searchQuery": "",
+ "backlinkCollapsed": false,
+ "unlinkedCollapsed": true
+ }
+ }
+ },
+ {
+ "id": "1d0811a4b45529b8",
+ "type": "leaf",
+ "state": {
+ "type": "outgoing-link",
+ "state": {
+ "file": "README.md",
+ "linksCollapsed": false,
+ "unlinkedCollapsed": true
+ }
+ }
+ },
+ {
+ "id": "1255c61dedfd1e84",
+ "type": "leaf",
+ "state": {
+ "type": "tag",
+ "state": {
+ "sortOrder": "frequency",
+ "useHierarchy": true
+ }
+ }
+ },
+ {
+ "id": "0eb472a8f25f460b",
+ "type": "leaf",
+ "state": {
+ "type": "outline",
+ "state": {
+ "file": "README.md"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "horizontal",
+ "width": 300,
+ "collapsed": true
+ },
+ "left-ribbon": {
+ "hiddenItems": {
+ "switcher:Open quick switcher": false,
+ "graph:Open graph view": false,
+ "canvas:Create new canvas": false,
+ "daily-notes:Open today's daily note": false,
+ "templates:Insert template": false,
+ "command-palette:Open command palette": false,
+ "table-editor-obsidian:Advanced Tables Toolbar": false,
+ "obsidian-excalidraw-plugin:Create new drawing": false
+ }
+ },
+ "active": "54139872f1da29d8",
+ "lastOpenFiles": [
+ "10.12 Chemie/! Chemie.md",
+ "README.md"
+ ]
+}
\ No newline at end of file
diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json
index a4acbd2..0989385 100644
--- a/.obsidian/community-plugins.json
+++ b/.obsidian/community-plugins.json
@@ -1,10 +1,11 @@
[
"symbols-prettifier",
"obsidian-style-settings",
- "obsidian-export-image",
- "table-editor-obsidian",
- "obsidian-icon-folder",
"quick-latex",
+ "obsidian-icon-folder",
"heading-level-indent",
- "obsidian-excalidraw-plugin"
+ "obsidian-git",
+ "table-editor-obsidian",
+ "obsidian-excalidraw-plugin",
+ "obsidian-export-image"
]
\ No newline at end of file
diff --git a/.obsidian/community-plugins.sync-conflict-20240917-212208-4CIB3I6.json b/.obsidian/community-plugins.sync-conflict-20240917-212208-4CIB3I6.json
new file mode 100644
index 0000000..923efdd
--- /dev/null
+++ b/.obsidian/community-plugins.sync-conflict-20240917-212208-4CIB3I6.json
@@ -0,0 +1,11 @@
+[
+ "symbols-prettifier",
+ "obsidian-style-settings",
+ "obsidian-export-image",
+ "table-editor-obsidian",
+ "obsidian-icon-folder",
+ "quick-latex",
+ "heading-level-indent",
+ "obsidian-excalidraw-plugin",
+ "obsidian-git"
+]
\ No newline at end of file
diff --git a/.obsidian/community-plugins.sync-conflict-20240917-212320-4CIB3I6.json b/.obsidian/community-plugins.sync-conflict-20240917-212320-4CIB3I6.json
new file mode 100644
index 0000000..923efdd
--- /dev/null
+++ b/.obsidian/community-plugins.sync-conflict-20240917-212320-4CIB3I6.json
@@ -0,0 +1,11 @@
+[
+ "symbols-prettifier",
+ "obsidian-style-settings",
+ "obsidian-export-image",
+ "table-editor-obsidian",
+ "obsidian-icon-folder",
+ "quick-latex",
+ "heading-level-indent",
+ "obsidian-excalidraw-plugin",
+ "obsidian-git"
+]
\ No newline at end of file
diff --git a/.obsidian/plugins/heading-level-indent/main.js b/.obsidian/plugins/heading-level-indent/main.js
old mode 100644
new mode 100755
diff --git a/.obsidian/plugins/obsidian-excalidraw-plugin/main.js b/.obsidian/plugins/obsidian-excalidraw-plugin/main.js
old mode 100644
new mode 100755
diff --git a/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json b/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json
index 0bf3812..3fb3583 100644
--- a/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json
+++ b/.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json
@@ -1,12 +1,12 @@
-{
- "id": "obsidian-excalidraw-plugin",
- "name": "Excalidraw",
- "version": "2.4.3",
- "minAppVersion": "1.1.6",
- "description": "An Obsidian plugin to edit and view Excalidraw drawings",
- "author": "Zsolt Viczian",
- "authorUrl": "https://www.zsolt.blog",
- "fundingUrl": "https://ko-fi.com/zsolt",
- "helpUrl": "https://github.com/zsviczian/obsidian-excalidraw-plugin#readme",
- "isDesktopOnly": false
-}
+{
+ "id": "obsidian-excalidraw-plugin",
+ "name": "Excalidraw",
+ "version": "2.4.3",
+ "minAppVersion": "1.1.6",
+ "description": "An Obsidian plugin to edit and view Excalidraw drawings",
+ "author": "Zsolt Viczian",
+ "authorUrl": "https://www.zsolt.blog",
+ "fundingUrl": "https://ko-fi.com/zsolt",
+ "helpUrl": "https://github.com/zsviczian/obsidian-excalidraw-plugin#readme",
+ "isDesktopOnly": false
+}
diff --git a/.obsidian/plugins/obsidian-export-image/main.js b/.obsidian/plugins/obsidian-export-image/main.js
old mode 100644
new mode 100755
diff --git a/.obsidian/plugins/obsidian-git/.syncthing.data.json.tmp b/.obsidian/plugins/obsidian-git/.syncthing.data.json.tmp
new file mode 100644
index 0000000..07b3c40
--- /dev/null
+++ b/.obsidian/plugins/obsidian-git/.syncthing.data.json.tmp
@@ -0,0 +1,58 @@
+{
+ "commitMessage": "Manual commit: {{date}}",
+ "commitDateFormat": "DD. MM. YYYY HH:mm:ss",
+ "autoSaveInterval": 15,
+ "autoPushInterval": 0,
+ "autoPullInterval": 0,
+ "autoPullOnBoot": true,
+ "disablePush": false,
+ "pullBeforePush": true,
+ "disablePopups": false,
+ "disablePopupsForNoChanges": true,
+ "listChangedFilesInMessageBody": false,
+ "showStatusBar": true,
+ "updateSubmodules": false,
+ "syncMethod": "merge",
+ "customMessageOnAutoBackup": false,
+ "autoBackupAfterFileChange": false,
+ "treeStructure": false,
+ "refreshSourceControl": true,
+ "basePath": "",
+ "differentIntervalCommitAndPush": false,
+ "changedFilesInStatusBar": false,
+ "showedMobileNotice": true,
+ "refreshSourceControlTimer": 7000,
+ "showBranchStatusBar": true,
+ "setLastSaveToLastCommit": false,
+ "submoduleRecurseCheckout": false,
+ "gitDir": "",
+ "showFileMenu": true,
+ "authorInHistoryView": "hide",
+ "dateInHistoryView": false,
+ "lineAuthor": {
+ "show": false,
+ "followMovement": "inactive",
+ "authorDisplay": "initials",
+ "showCommitHash": false,
+ "dateTimeFormatOptions": "date",
+ "dateTimeFormatCustomString": "YYYY-MM-DD HH:mm",
+ "dateTimeTimezone": "viewer-local",
+ "coloringMaxAge": "1y",
+ "colorNew": {
+ "r": 255,
+ "g": 150,
+ "b": 150
+ },
+ "colorOld": {
+ "r": 120,
+ "g": 160,
+ "b": 255
+ },
+ "textColorCss": "var(--text-muted)",
+ "ignoreWhitespace": false,
+ "gutterSpacingFallbackLength": 5,
+ "lastShownAuthorDisplay": "initials",
+ "lastShownDateTimeFormatOptions": "date"
+ },
+ "autoCommitMessage": "Automatic commit: {{date}}"
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian-git/data.json b/.obsidian/plugins/obsidian-git/data.json
index 8137824..ed219bb 100644
--- a/.obsidian/plugins/obsidian-git/data.json
+++ b/.obsidian/plugins/obsidian-git/data.json
@@ -1,14 +1,14 @@
{
- "commitMessage": "vault backup: {{date}}",
- "commitDateFormat": "DD. MM. YYYY HH:mm:ss",
- "autoSaveInterval": 10,
+ "commitMessage": "Manual commit: {{date}}",
+ "commitDateFormat": "YYYY-MM-DD HH:mm:ss",
+ "autoSaveInterval": 15,
"autoPushInterval": 0,
"autoPullInterval": 0,
- "autoPullOnBoot": false,
+ "autoPullOnBoot": true,
"disablePush": false,
"pullBeforePush": true,
"disablePopups": false,
- "disablePopupsForNoChanges": true,
+ "disablePopupsForNoChanges": false,
"listChangedFilesInMessageBody": false,
"showStatusBar": true,
"updateSubmodules": false,
@@ -18,7 +18,7 @@
"treeStructure": false,
"refreshSourceControl": true,
"basePath": "",
- "differentIntervalCommitAndPush": true,
+ "differentIntervalCommitAndPush": false,
"changedFilesInStatusBar": false,
"showedMobileNotice": true,
"refreshSourceControlTimer": 7000,
@@ -54,5 +54,5 @@
"lastShownAuthorDisplay": "initials",
"lastShownDateTimeFormatOptions": "date"
},
- "autoCommitMessage": "vault backup: {{date}}"
+ "autoCommitMessage": "Automatic commit: {{date}}"
}
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212208-4CIB3I6.json b/.obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212208-4CIB3I6.json
new file mode 100644
index 0000000..07b3c40
--- /dev/null
+++ b/.obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212208-4CIB3I6.json
@@ -0,0 +1,58 @@
+{
+ "commitMessage": "Manual commit: {{date}}",
+ "commitDateFormat": "DD. MM. YYYY HH:mm:ss",
+ "autoSaveInterval": 15,
+ "autoPushInterval": 0,
+ "autoPullInterval": 0,
+ "autoPullOnBoot": true,
+ "disablePush": false,
+ "pullBeforePush": true,
+ "disablePopups": false,
+ "disablePopupsForNoChanges": true,
+ "listChangedFilesInMessageBody": false,
+ "showStatusBar": true,
+ "updateSubmodules": false,
+ "syncMethod": "merge",
+ "customMessageOnAutoBackup": false,
+ "autoBackupAfterFileChange": false,
+ "treeStructure": false,
+ "refreshSourceControl": true,
+ "basePath": "",
+ "differentIntervalCommitAndPush": false,
+ "changedFilesInStatusBar": false,
+ "showedMobileNotice": true,
+ "refreshSourceControlTimer": 7000,
+ "showBranchStatusBar": true,
+ "setLastSaveToLastCommit": false,
+ "submoduleRecurseCheckout": false,
+ "gitDir": "",
+ "showFileMenu": true,
+ "authorInHistoryView": "hide",
+ "dateInHistoryView": false,
+ "lineAuthor": {
+ "show": false,
+ "followMovement": "inactive",
+ "authorDisplay": "initials",
+ "showCommitHash": false,
+ "dateTimeFormatOptions": "date",
+ "dateTimeFormatCustomString": "YYYY-MM-DD HH:mm",
+ "dateTimeTimezone": "viewer-local",
+ "coloringMaxAge": "1y",
+ "colorNew": {
+ "r": 255,
+ "g": 150,
+ "b": 150
+ },
+ "colorOld": {
+ "r": 120,
+ "g": 160,
+ "b": 255
+ },
+ "textColorCss": "var(--text-muted)",
+ "ignoreWhitespace": false,
+ "gutterSpacingFallbackLength": 5,
+ "lastShownAuthorDisplay": "initials",
+ "lastShownDateTimeFormatOptions": "date"
+ },
+ "autoCommitMessage": "Automatic commit: {{date}}"
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212320-4CIB3I6.json b/.obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212320-4CIB3I6.json
new file mode 100644
index 0000000..07b3c40
--- /dev/null
+++ b/.obsidian/plugins/obsidian-git/data.sync-conflict-20240917-212320-4CIB3I6.json
@@ -0,0 +1,58 @@
+{
+ "commitMessage": "Manual commit: {{date}}",
+ "commitDateFormat": "DD. MM. YYYY HH:mm:ss",
+ "autoSaveInterval": 15,
+ "autoPushInterval": 0,
+ "autoPullInterval": 0,
+ "autoPullOnBoot": true,
+ "disablePush": false,
+ "pullBeforePush": true,
+ "disablePopups": false,
+ "disablePopupsForNoChanges": true,
+ "listChangedFilesInMessageBody": false,
+ "showStatusBar": true,
+ "updateSubmodules": false,
+ "syncMethod": "merge",
+ "customMessageOnAutoBackup": false,
+ "autoBackupAfterFileChange": false,
+ "treeStructure": false,
+ "refreshSourceControl": true,
+ "basePath": "",
+ "differentIntervalCommitAndPush": false,
+ "changedFilesInStatusBar": false,
+ "showedMobileNotice": true,
+ "refreshSourceControlTimer": 7000,
+ "showBranchStatusBar": true,
+ "setLastSaveToLastCommit": false,
+ "submoduleRecurseCheckout": false,
+ "gitDir": "",
+ "showFileMenu": true,
+ "authorInHistoryView": "hide",
+ "dateInHistoryView": false,
+ "lineAuthor": {
+ "show": false,
+ "followMovement": "inactive",
+ "authorDisplay": "initials",
+ "showCommitHash": false,
+ "dateTimeFormatOptions": "date",
+ "dateTimeFormatCustomString": "YYYY-MM-DD HH:mm",
+ "dateTimeTimezone": "viewer-local",
+ "coloringMaxAge": "1y",
+ "colorNew": {
+ "r": 255,
+ "g": 150,
+ "b": 150
+ },
+ "colorOld": {
+ "r": 120,
+ "g": 160,
+ "b": 255
+ },
+ "textColorCss": "var(--text-muted)",
+ "ignoreWhitespace": false,
+ "gutterSpacingFallbackLength": 5,
+ "lastShownAuthorDisplay": "initials",
+ "lastShownDateTimeFormatOptions": "date"
+ },
+ "autoCommitMessage": "Automatic commit: {{date}}"
+}
\ No newline at end of file
diff --git a/.obsidian/plugins/obsidian-git/main.js b/.obsidian/plugins/obsidian-git/main.js
old mode 100644
new mode 100755
diff --git a/.obsidian/plugins/obsidian-icon-folder/main.js b/.obsidian/plugins/obsidian-icon-folder/main.js
old mode 100644
new mode 100755
index 677b583..4dad46e
--- a/.obsidian/plugins/obsidian-icon-folder/main.js
+++ b/.obsidian/plugins/obsidian-icon-folder/main.js
@@ -10,34 +10,34 @@ var view = require('@codemirror/view');
var language = require('@codemirror/language');
var state = require('@codemirror/state');
-/******************************************************************************
-Copyright (c) Microsoft Corporation.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-***************************************************************************** */
-
-function __awaiter(thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-}
-
-typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
- var e = new Error(message);
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
+/******************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
+
+function __awaiter(thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+}
+
+typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
+ var e = new Error(message);
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
// This library file does not include any other dependency and is a standalone file that
diff --git a/.obsidian/plugins/obsidian-icon-folder/styles.css b/.obsidian/plugins/obsidian-icon-folder/styles.css
index ca018fe..ded0f44 100644
--- a/.obsidian/plugins/obsidian-icon-folder/styles.css
+++ b/.obsidian/plugins/obsidian-icon-folder/styles.css
@@ -1,110 +1,110 @@
-.iconize-title-icon {
- max-width: var(--max-width);
- width: var(--line-width);
- margin-inline: var(--content-margin) !important;
-}
-
-.iconize-icon {
- border: 1px solid transparent;
- margin: 0px 4px 0px 0px;
- display: flex;
- align-self: center;
- margin: auto 0;
-}
-
-.nav-folder-title,
-.nav-file-title {
- align-items: center;
-}
-
-.iconize-setting input[type='color'] {
- margin: 0 6px;
-}
-
-.iconize-modal.prompt-results {
- margin: 0;
- overflow-y: auto;
- display: grid;
- grid-template-columns: repeat(5, minmax(0, 1fr));
-}
-
-.prompt .iconize-subheadline {
- margin-top: 12px;
- font-size: 12px;
- color: gray;
- grid-column-start: 1;
- grid-column-end: 6;
-}
-
-@media (max-width: 640px) {
- .iconize-modal.prompt-results {
- grid-template-columns: repeat(3, minmax(0, 1fr));
- }
- .prompt .iconize-subheadline {
- grid-column-end: 4;
- }
-}
-
-.iconize-modal.prompt-results .suggestion-item {
- cursor: pointer;
- white-space: pre-wrap;
- display: flex;
- justify-content: flex-end;
- align-items: center;
- flex-direction: column-reverse;
- text-align: center;
- font-size: 13px;
- color: var(--text-muted);
- padding: 16px 8px;
- line-break: auto;
- word-break: break-word;
- line-height: 1.3;
-}
-
-.iconize-modal.prompt-results
- .suggestion-item.suggestion-item__center {
- justify-content: center;
-}
-
-.iconize-icon-preview {
- font-size: 22px;
-}
-
-.iconize-icon-preview img {
- width: 16px;
- height: 16px;
-}
-
-.iconize-icon-preview svg {
- width: 24px;
- height: 24px;
- color: currentColor;
- margin-bottom: 4px;
-}
-
-.iconize-dragover {
- position: relative;
-}
-
-.iconize-dragover-el {
- position: absolute;
- width: 100%;
- height: 100%;
- color: var(--text-normal);
- background-color: var(--background-secondary-alt);
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-/* Custom rule modal. */
-.iconize-custom-modal .modal-content {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.iconize-custom-modal .modal-content input {
- width: 100%;
- margin-right: 0.5rem;
-}
+.iconize-title-icon {
+ max-width: var(--max-width);
+ width: var(--line-width);
+ margin-inline: var(--content-margin) !important;
+}
+
+.iconize-icon {
+ border: 1px solid transparent;
+ margin: 0px 4px 0px 0px;
+ display: flex;
+ align-self: center;
+ margin: auto 0;
+}
+
+.nav-folder-title,
+.nav-file-title {
+ align-items: center;
+}
+
+.iconize-setting input[type='color'] {
+ margin: 0 6px;
+}
+
+.iconize-modal.prompt-results {
+ margin: 0;
+ overflow-y: auto;
+ display: grid;
+ grid-template-columns: repeat(5, minmax(0, 1fr));
+}
+
+.prompt .iconize-subheadline {
+ margin-top: 12px;
+ font-size: 12px;
+ color: gray;
+ grid-column-start: 1;
+ grid-column-end: 6;
+}
+
+@media (max-width: 640px) {
+ .iconize-modal.prompt-results {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ }
+ .prompt .iconize-subheadline {
+ grid-column-end: 4;
+ }
+}
+
+.iconize-modal.prompt-results .suggestion-item {
+ cursor: pointer;
+ white-space: pre-wrap;
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ flex-direction: column-reverse;
+ text-align: center;
+ font-size: 13px;
+ color: var(--text-muted);
+ padding: 16px 8px;
+ line-break: auto;
+ word-break: break-word;
+ line-height: 1.3;
+}
+
+.iconize-modal.prompt-results
+ .suggestion-item.suggestion-item__center {
+ justify-content: center;
+}
+
+.iconize-icon-preview {
+ font-size: 22px;
+}
+
+.iconize-icon-preview img {
+ width: 16px;
+ height: 16px;
+}
+
+.iconize-icon-preview svg {
+ width: 24px;
+ height: 24px;
+ color: currentColor;
+ margin-bottom: 4px;
+}
+
+.iconize-dragover {
+ position: relative;
+}
+
+.iconize-dragover-el {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ color: var(--text-normal);
+ background-color: var(--background-secondary-alt);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* Custom rule modal. */
+.iconize-custom-modal .modal-content {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.iconize-custom-modal .modal-content input {
+ width: 100%;
+ margin-right: 0.5rem;
+}
diff --git a/.obsidian/plugins/obsidian-style-settings/main.js b/.obsidian/plugins/obsidian-style-settings/main.js
old mode 100644
new mode 100755
index 9a2d6bb..b7e0ea0
--- a/.obsidian/plugins/obsidian-style-settings/main.js
+++ b/.obsidian/plugins/obsidian-style-settings/main.js
@@ -7,29 +7,29 @@ if you want to view the source visit the plugins github repository
var obsidian = require('obsidian');
-/*! *****************************************************************************
-Copyright (c) Microsoft Corporation.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-***************************************************************************** */
-
-function __awaiter(thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
+
+function __awaiter(thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
}
class ExportModal extends obsidian.Modal {
@@ -4047,546 +4047,546 @@ function createDescription(description, def, defLabel) {
}
var fuzzysort = createCommonjsModule(function (module) {
-((root, UMD) => {
- if(module.exports) module.exports = UMD();
- else root['fuzzysort'] = UMD();
-})(commonjsGlobal, _ => {
-
- var single = (search, target) => { if(search=='farzher')return {target:"farzher was here (^-^*)/",score:0,_indexes:[0]}
- if(!search || !target) return NULL
-
- var preparedSearch = getPreparedSearch(search);
- if(!isObj(target)) target = getPrepared(target);
-
- var searchBitflags = preparedSearch.bitflags;
- if((searchBitflags & target._bitflags) !== searchBitflags) return NULL
-
- return algorithm(preparedSearch, target)
- };
-
-
- var go = (search, targets, options) => { if(search=='farzher')return [{target:"farzher was here (^-^*)/",score:0,_indexes:[0],obj:targets?targets[0]:NULL}]
- if(!search) return options&&options.all ? all(search, targets, options) : noResults
-
- var preparedSearch = getPreparedSearch(search);
- var searchBitflags = preparedSearch.bitflags;
- preparedSearch.containsSpace;
-
- var threshold = options&&options.threshold || INT_MIN;
- var limit = options&&options['limit'] || INT_MAX; // for some reason only limit breaks when minified
-
- var resultsLen = 0; var limitedCount = 0;
- var targetsLen = targets.length;
-
- // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
-
- // options.key
- if(options && options.key) {
- var key = options.key;
- for(var i = 0; i < targetsLen; ++i) { var obj = targets[i];
- var target = getValue(obj, key);
- if(!target) continue
- if(!isObj(target)) target = getPrepared(target);
-
- if((searchBitflags & target._bitflags) !== searchBitflags) continue
- var result = algorithm(preparedSearch, target);
- if(result === NULL) continue
- if(result.score < threshold) continue
-
- // have to clone result so duplicate targets from different obj can each reference the correct obj
- result = {target:result.target, _targetLower:'', _targetLowerCodes:NULL, _nextBeginningIndexes:NULL, _bitflags:0, score:result.score, _indexes:result._indexes, obj:obj}; // hidden
-
- if(resultsLen < limit) { q.add(result); ++resultsLen; }
- else {
- ++limitedCount;
- if(result.score > q.peek().score) q.replaceTop(result);
- }
- }
-
- // options.keys
- } else if(options && options.keys) {
- var scoreFn = options['scoreFn'] || defaultScoreFn;
- var keys = options.keys;
- var keysLen = keys.length;
- for(var i = 0; i < targetsLen; ++i) { var obj = targets[i];
- var objResults = new Array(keysLen);
- for (var keyI = 0; keyI < keysLen; ++keyI) {
- var key = keys[keyI];
- var target = getValue(obj, key);
- if(!target) { objResults[keyI] = NULL; continue }
- if(!isObj(target)) target = getPrepared(target);
-
- if((searchBitflags & target._bitflags) !== searchBitflags) objResults[keyI] = NULL;
- else objResults[keyI] = algorithm(preparedSearch, target);
- }
- objResults.obj = obj; // before scoreFn so scoreFn can use it
- var score = scoreFn(objResults);
- if(score === NULL) continue
- if(score < threshold) continue
- objResults.score = score;
- if(resultsLen < limit) { q.add(objResults); ++resultsLen; }
- else {
- ++limitedCount;
- if(score > q.peek().score) q.replaceTop(objResults);
- }
- }
-
- // no keys
- } else {
- for(var i = 0; i < targetsLen; ++i) { var target = targets[i];
- if(!target) continue
- if(!isObj(target)) target = getPrepared(target);
-
- if((searchBitflags & target._bitflags) !== searchBitflags) continue
- var result = algorithm(preparedSearch, target);
- if(result === NULL) continue
- if(result.score < threshold) continue
- if(resultsLen < limit) { q.add(result); ++resultsLen; }
- else {
- ++limitedCount;
- if(result.score > q.peek().score) q.replaceTop(result);
- }
- }
- }
-
- if(resultsLen === 0) return noResults
- var results = new Array(resultsLen);
- for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll();
- results.total = resultsLen + limitedCount;
- return results
- };
-
-
- var highlight = (result, hOpen, hClose) => {
- if(typeof hOpen === 'function') return highlightCallback(result, hOpen)
- if(result === NULL) return NULL
- if(hOpen === undefined) hOpen = '';
- if(hClose === undefined) hClose = '';
- var highlighted = '';
- var matchesIndex = 0;
- var opened = false;
- var target = result.target;
- var targetLen = target.length;
- var indexes = result._indexes;
- indexes = indexes.slice(0, indexes.len).sort((a,b)=>a-b);
- for(var i = 0; i < targetLen; ++i) { var char = target[i];
- if(indexes[matchesIndex] === i) {
- ++matchesIndex;
- if(!opened) { opened = true;
- highlighted += hOpen;
- }
-
- if(matchesIndex === indexes.length) {
- highlighted += char + hClose + target.substr(i+1);
- break
- }
- } else {
- if(opened) { opened = false;
- highlighted += hClose;
- }
- }
- highlighted += char;
- }
-
- return highlighted
- };
- var highlightCallback = (result, cb) => {
- if(result === NULL) return NULL
- var target = result.target;
- var targetLen = target.length;
- var indexes = result._indexes;
- indexes = indexes.slice(0, indexes.len).sort((a,b)=>a-b);
- var highlighted = '';
- var matchI = 0;
- var indexesI = 0;
- var opened = false;
- var result = [];
- for(var i = 0; i < targetLen; ++i) { var char = target[i];
- if(indexes[indexesI] === i) {
- ++indexesI;
- if(!opened) { opened = true;
- result.push(highlighted); highlighted = '';
- }
-
- if(indexesI === indexes.length) {
- highlighted += char;
- result.push(cb(highlighted, matchI++)); highlighted = '';
- result.push(target.substr(i+1));
- break
- }
- } else {
- if(opened) { opened = false;
- result.push(cb(highlighted, matchI++)); highlighted = '';
- }
- }
- highlighted += char;
- }
- return result
- };
-
-
- var indexes = result => result._indexes.slice(0, result._indexes.len).sort((a,b)=>a-b);
-
-
- var prepare = (target) => {
- if(typeof target !== 'string') target = '';
- var info = prepareLowerInfo(target);
- return {'target':target, _targetLower:info._lower, _targetLowerCodes:info.lowerCodes, _nextBeginningIndexes:NULL, _bitflags:info.bitflags, 'score':NULL, _indexes:[0], 'obj':NULL} // hidden
- };
-
-
- // Below this point is only internal code
- // Below this point is only internal code
- // Below this point is only internal code
- // Below this point is only internal code
-
-
- var prepareSearch = (search) => {
- if(typeof search !== 'string') search = '';
- search = search.trim();
- var info = prepareLowerInfo(search);
-
- var spaceSearches = [];
- if(info.containsSpace) {
- var searches = search.split(/\s+/);
- searches = [...new Set(searches)]; // distinct
- for(var i=0; i {
- if(target.length > 999) return prepare(target) // don't cache huge targets
- var targetPrepared = preparedCache.get(target);
- if(targetPrepared !== undefined) return targetPrepared
- targetPrepared = prepare(target);
- preparedCache.set(target, targetPrepared);
- return targetPrepared
- };
- var getPreparedSearch = (search) => {
- if(search.length > 999) return prepareSearch(search) // don't cache huge searches
- var searchPrepared = preparedSearchCache.get(search);
- if(searchPrepared !== undefined) return searchPrepared
- searchPrepared = prepareSearch(search);
- preparedSearchCache.set(search, searchPrepared);
- return searchPrepared
- };
-
-
- var all = (search, targets, options) => {
- var results = []; results.total = targets.length;
-
- var limit = options && options.limit || INT_MAX;
-
- if(options && options.key) {
- for(var i=0;i= limit) return results
- }
- } else if(options && options.keys) {
- for(var i=0;i= 0; --keyI) {
- var target = getValue(obj, options.keys[keyI]);
- if(!target) { objResults[keyI] = NULL; continue }
- if(!isObj(target)) target = getPrepared(target);
- target.score = INT_MIN;
- target._indexes.len = 0;
- objResults[keyI] = target;
- }
- objResults.obj = obj;
- objResults.score = INT_MIN;
- results.push(objResults); if(results.length >= limit) return results
- }
- } else {
- for(var i=0;i= limit) return results
- }
- }
-
- return results
- };
-
-
- var algorithm = (preparedSearch, prepared, allowSpaces=false) => {
- if(allowSpaces===false && preparedSearch.containsSpace) return algorithmSpaces(preparedSearch, prepared)
-
- var searchLower = preparedSearch._lower;
- var searchLowerCodes = preparedSearch.lowerCodes;
- var searchLowerCode = searchLowerCodes[0];
- var targetLowerCodes = prepared._targetLowerCodes;
- var searchLen = searchLowerCodes.length;
- var targetLen = targetLowerCodes.length;
- var searchI = 0; // where we at
- var targetI = 0; // where you at
- var matchesSimpleLen = 0;
-
- // very basic fuzzy match; to remove non-matching targets ASAP!
- // walk through target. find sequential matches.
- // if all chars aren't found then exit
- for(;;) {
- var isMatch = searchLowerCode === targetLowerCodes[targetI];
- if(isMatch) {
- matchesSimple[matchesSimpleLen++] = targetI;
- ++searchI; if(searchI === searchLen) break
- searchLowerCode = searchLowerCodes[searchI];
- }
- ++targetI; if(targetI >= targetLen) return NULL // Failed to find searchI
- }
-
- var searchI = 0;
- var successStrict = false;
- var matchesStrictLen = 0;
-
- var nextBeginningIndexes = prepared._nextBeginningIndexes;
- if(nextBeginningIndexes === NULL) nextBeginningIndexes = prepared._nextBeginningIndexes = prepareNextBeginningIndexes(prepared.target);
- targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1];
-
- // Our target string successfully matched all characters in sequence!
- // Let's try a more advanced and strict test to improve the score
- // only count it as a match if it's consecutive or a beginning character!
- var backtrackCount = 0;
- if(targetI !== targetLen) for(;;) {
- if(targetI >= targetLen) {
- // We failed to find a good spot for this search char, go back to the previous search char and force it forward
- if(searchI <= 0) break // We failed to push chars forward for a better match
-
- ++backtrackCount; if(backtrackCount > 200) break // exponential backtracking is taking too long, just give up and return a bad match
-
- --searchI;
- var lastMatch = matchesStrict[--matchesStrictLen];
- targetI = nextBeginningIndexes[lastMatch];
-
- } else {
- var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI];
- if(isMatch) {
- matchesStrict[matchesStrictLen++] = targetI;
- ++searchI; if(searchI === searchLen) { successStrict = true; break }
- ++targetI;
- } else {
- targetI = nextBeginningIndexes[targetI];
- }
- }
- }
-
- // check if it's a substring match
- var substringIndex = prepared._targetLower.indexOf(searchLower, matchesSimple[0]); // perf: this is slow
- var isSubstring = ~substringIndex;
- if(isSubstring && !successStrict) { // rewrite the indexes from basic to the substring
- for(var i=0; i 24) score *= (uniqueBeginningIndexes-24)*10; // quite arbitrary numbers here ...
- }
-
- if(isSubstring) score /= 1+searchLen*searchLen*1; // bonus for being a full substring
- if(isSubstringBeginning) score /= 1+searchLen*searchLen*1; // bonus for substring starting on a beginningIndex
-
- score -= targetLen - searchLen; // penality for longer targets
- prepared.score = score;
-
- for(var i = 0; i < matchesBestLen; ++i) prepared._indexes[i] = matchesBest[i];
- prepared._indexes.len = matchesBestLen;
-
- return prepared
- }
- };
- var algorithmSpaces = (preparedSearch, target) => {
- var seen_indexes = new Set();
- var score = 0;
- var result = NULL;
-
- var first_seen_index_last_search = 0;
- var searches = preparedSearch.spaceSearches;
- for(var i=0; i score) {
- return allowSpacesResult
- }
-
- result.score = score;
-
- var i = 0;
- for (let index of seen_indexes) result._indexes[i++] = index;
- result._indexes.len = i;
-
- return result
- };
-
-
- var prepareLowerInfo = (str) => {
- var strLen = str.length;
- var lower = str.toLowerCase();
- var lowerCodes = []; // new Array(strLen) sparse array is too slow
- var bitflags = 0;
- var containsSpace = false; // space isn't stored in bitflags because of how searching with a space works
-
- for(var i = 0; i < strLen; ++i) {
- var lowerCode = lowerCodes[i] = lower.charCodeAt(i);
-
- if(lowerCode === 32) {
- containsSpace = true;
- continue // it's important that we don't set any bitflags for space
- }
-
- var bit = lowerCode>=97&&lowerCode<=122 ? lowerCode-97 // alphabet
- : lowerCode>=48&&lowerCode<=57 ? 26 // numbers
- // 3 bits available
- : lowerCode<=127 ? 30 // other ascii
- : 31; // other utf8
- bitflags |= 1< {
- var targetLen = target.length;
- var beginningIndexes = []; var beginningIndexesLen = 0;
- var wasUpper = false;
- var wasAlphanum = false;
- for(var i = 0; i < targetLen; ++i) {
- var targetCode = target.charCodeAt(i);
- var isUpper = targetCode>=65&&targetCode<=90;
- var isAlphanum = isUpper || targetCode>=97&&targetCode<=122 || targetCode>=48&&targetCode<=57;
- var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum;
- wasUpper = isUpper;
- wasAlphanum = isAlphanum;
- if(isBeginning) beginningIndexes[beginningIndexesLen++] = i;
- }
- return beginningIndexes
- };
- var prepareNextBeginningIndexes = (target) => {
- var targetLen = target.length;
- var beginningIndexes = prepareBeginningIndexes(target);
- var nextBeginningIndexes = []; // new Array(targetLen) sparse array is too slow
- var lastIsBeginning = beginningIndexes[0];
- var lastIsBeginningI = 0;
- for(var i = 0; i < targetLen; ++i) {
- if(lastIsBeginning > i) {
- nextBeginningIndexes[i] = lastIsBeginning;
- } else {
- lastIsBeginning = beginningIndexes[++lastIsBeginningI];
- nextBeginningIndexes[i] = lastIsBeginning===undefined ? targetLen : lastIsBeginning;
- }
- }
- return nextBeginningIndexes
- };
-
-
- var cleanup = () => { preparedCache.clear(); preparedSearchCache.clear(); matchesSimple = []; matchesStrict = []; };
-
- var preparedCache = new Map();
- var preparedSearchCache = new Map();
- var matchesSimple = []; var matchesStrict = [];
-
-
- // for use with keys. just returns the maximum score
- var defaultScoreFn = (a) => {
- var max = INT_MIN;
- var len = a.length;
- for (var i = 0; i < len; ++i) {
- var result = a[i]; if(result === NULL) continue
- var score = result.score;
- if(score > max) max = score;
- }
- if(max === INT_MIN) return NULL
- return max
- };
-
- // prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop]
- // prop = 'key1.key2' 10ms
- // prop = ['key1', 'key2'] 27ms
- var getValue = (obj, prop) => {
- var tmp = obj[prop]; if(tmp !== undefined) return tmp
- var segs = prop;
- if(!Array.isArray(prop)) segs = prop.split('.');
- var len = segs.length;
- var i = -1;
- while (obj && (++i < len)) obj = obj[segs[i]];
- return obj
- };
-
- var isObj = (x) => { return typeof x === 'object' }; // faster as a function
- // var INT_MAX = 9007199254740991; var INT_MIN = -INT_MAX
- var INT_MAX = Infinity; var INT_MIN = -INT_MAX;
- var noResults = []; noResults.total = 0;
- var NULL = null;
-
-
- // Hacked version of https://github.com/lemire/FastPriorityQueue.js
- var fastpriorityqueue=r=>{var e=[],o=0,a={},v=r=>{for(var a=0,v=e[a],c=1;c>1]=e[a],c=1+(a<<1);}for(var f=a-1>>1;a>0&&v.score>1)e[a]=e[f];e[a]=v;};return a.add=(r=>{var a=o;e[o++]=r;for(var v=a-1>>1;a>0&&r.score>1)e[a]=e[v];e[a]=r;}),a.poll=(r=>{if(0!==o){var a=e[0];return e[0]=e[--o],v(),a}}),a.peek=(r=>{if(0!==o)return e[0]}),a.replaceTop=(r=>{e[0]=r,v();}),a};
- var q = fastpriorityqueue(); // reuse this
-
-
- // fuzzysort is written this way for minification. all names are mangeled unless quoted
- return {'single':single, 'go':go, 'highlight':highlight, 'prepare':prepare, 'indexes':indexes, 'cleanup':cleanup}
-}); // UMD
-
-// TODO: (feature) frecency
-// TODO: (perf) use different sorting algo depending on the # of results?
-// TODO: (perf) preparedCache is a memory leak
-// TODO: (like sublime) backslash === forwardslash
+((root, UMD) => {
+ if(module.exports) module.exports = UMD();
+ else root['fuzzysort'] = UMD();
+})(commonjsGlobal, _ => {
+
+ var single = (search, target) => { if(search=='farzher')return {target:"farzher was here (^-^*)/",score:0,_indexes:[0]}
+ if(!search || !target) return NULL
+
+ var preparedSearch = getPreparedSearch(search);
+ if(!isObj(target)) target = getPrepared(target);
+
+ var searchBitflags = preparedSearch.bitflags;
+ if((searchBitflags & target._bitflags) !== searchBitflags) return NULL
+
+ return algorithm(preparedSearch, target)
+ };
+
+
+ var go = (search, targets, options) => { if(search=='farzher')return [{target:"farzher was here (^-^*)/",score:0,_indexes:[0],obj:targets?targets[0]:NULL}]
+ if(!search) return options&&options.all ? all(search, targets, options) : noResults
+
+ var preparedSearch = getPreparedSearch(search);
+ var searchBitflags = preparedSearch.bitflags;
+ preparedSearch.containsSpace;
+
+ var threshold = options&&options.threshold || INT_MIN;
+ var limit = options&&options['limit'] || INT_MAX; // for some reason only limit breaks when minified
+
+ var resultsLen = 0; var limitedCount = 0;
+ var targetsLen = targets.length;
+
+ // This code is copy/pasted 3 times for performance reasons [options.keys, options.key, no keys]
+
+ // options.key
+ if(options && options.key) {
+ var key = options.key;
+ for(var i = 0; i < targetsLen; ++i) { var obj = targets[i];
+ var target = getValue(obj, key);
+ if(!target) continue
+ if(!isObj(target)) target = getPrepared(target);
+
+ if((searchBitflags & target._bitflags) !== searchBitflags) continue
+ var result = algorithm(preparedSearch, target);
+ if(result === NULL) continue
+ if(result.score < threshold) continue
+
+ // have to clone result so duplicate targets from different obj can each reference the correct obj
+ result = {target:result.target, _targetLower:'', _targetLowerCodes:NULL, _nextBeginningIndexes:NULL, _bitflags:0, score:result.score, _indexes:result._indexes, obj:obj}; // hidden
+
+ if(resultsLen < limit) { q.add(result); ++resultsLen; }
+ else {
+ ++limitedCount;
+ if(result.score > q.peek().score) q.replaceTop(result);
+ }
+ }
+
+ // options.keys
+ } else if(options && options.keys) {
+ var scoreFn = options['scoreFn'] || defaultScoreFn;
+ var keys = options.keys;
+ var keysLen = keys.length;
+ for(var i = 0; i < targetsLen; ++i) { var obj = targets[i];
+ var objResults = new Array(keysLen);
+ for (var keyI = 0; keyI < keysLen; ++keyI) {
+ var key = keys[keyI];
+ var target = getValue(obj, key);
+ if(!target) { objResults[keyI] = NULL; continue }
+ if(!isObj(target)) target = getPrepared(target);
+
+ if((searchBitflags & target._bitflags) !== searchBitflags) objResults[keyI] = NULL;
+ else objResults[keyI] = algorithm(preparedSearch, target);
+ }
+ objResults.obj = obj; // before scoreFn so scoreFn can use it
+ var score = scoreFn(objResults);
+ if(score === NULL) continue
+ if(score < threshold) continue
+ objResults.score = score;
+ if(resultsLen < limit) { q.add(objResults); ++resultsLen; }
+ else {
+ ++limitedCount;
+ if(score > q.peek().score) q.replaceTop(objResults);
+ }
+ }
+
+ // no keys
+ } else {
+ for(var i = 0; i < targetsLen; ++i) { var target = targets[i];
+ if(!target) continue
+ if(!isObj(target)) target = getPrepared(target);
+
+ if((searchBitflags & target._bitflags) !== searchBitflags) continue
+ var result = algorithm(preparedSearch, target);
+ if(result === NULL) continue
+ if(result.score < threshold) continue
+ if(resultsLen < limit) { q.add(result); ++resultsLen; }
+ else {
+ ++limitedCount;
+ if(result.score > q.peek().score) q.replaceTop(result);
+ }
+ }
+ }
+
+ if(resultsLen === 0) return noResults
+ var results = new Array(resultsLen);
+ for(var i = resultsLen - 1; i >= 0; --i) results[i] = q.poll();
+ results.total = resultsLen + limitedCount;
+ return results
+ };
+
+
+ var highlight = (result, hOpen, hClose) => {
+ if(typeof hOpen === 'function') return highlightCallback(result, hOpen)
+ if(result === NULL) return NULL
+ if(hOpen === undefined) hOpen = '';
+ if(hClose === undefined) hClose = '';
+ var highlighted = '';
+ var matchesIndex = 0;
+ var opened = false;
+ var target = result.target;
+ var targetLen = target.length;
+ var indexes = result._indexes;
+ indexes = indexes.slice(0, indexes.len).sort((a,b)=>a-b);
+ for(var i = 0; i < targetLen; ++i) { var char = target[i];
+ if(indexes[matchesIndex] === i) {
+ ++matchesIndex;
+ if(!opened) { opened = true;
+ highlighted += hOpen;
+ }
+
+ if(matchesIndex === indexes.length) {
+ highlighted += char + hClose + target.substr(i+1);
+ break
+ }
+ } else {
+ if(opened) { opened = false;
+ highlighted += hClose;
+ }
+ }
+ highlighted += char;
+ }
+
+ return highlighted
+ };
+ var highlightCallback = (result, cb) => {
+ if(result === NULL) return NULL
+ var target = result.target;
+ var targetLen = target.length;
+ var indexes = result._indexes;
+ indexes = indexes.slice(0, indexes.len).sort((a,b)=>a-b);
+ var highlighted = '';
+ var matchI = 0;
+ var indexesI = 0;
+ var opened = false;
+ var result = [];
+ for(var i = 0; i < targetLen; ++i) { var char = target[i];
+ if(indexes[indexesI] === i) {
+ ++indexesI;
+ if(!opened) { opened = true;
+ result.push(highlighted); highlighted = '';
+ }
+
+ if(indexesI === indexes.length) {
+ highlighted += char;
+ result.push(cb(highlighted, matchI++)); highlighted = '';
+ result.push(target.substr(i+1));
+ break
+ }
+ } else {
+ if(opened) { opened = false;
+ result.push(cb(highlighted, matchI++)); highlighted = '';
+ }
+ }
+ highlighted += char;
+ }
+ return result
+ };
+
+
+ var indexes = result => result._indexes.slice(0, result._indexes.len).sort((a,b)=>a-b);
+
+
+ var prepare = (target) => {
+ if(typeof target !== 'string') target = '';
+ var info = prepareLowerInfo(target);
+ return {'target':target, _targetLower:info._lower, _targetLowerCodes:info.lowerCodes, _nextBeginningIndexes:NULL, _bitflags:info.bitflags, 'score':NULL, _indexes:[0], 'obj':NULL} // hidden
+ };
+
+
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+ // Below this point is only internal code
+
+
+ var prepareSearch = (search) => {
+ if(typeof search !== 'string') search = '';
+ search = search.trim();
+ var info = prepareLowerInfo(search);
+
+ var spaceSearches = [];
+ if(info.containsSpace) {
+ var searches = search.split(/\s+/);
+ searches = [...new Set(searches)]; // distinct
+ for(var i=0; i {
+ if(target.length > 999) return prepare(target) // don't cache huge targets
+ var targetPrepared = preparedCache.get(target);
+ if(targetPrepared !== undefined) return targetPrepared
+ targetPrepared = prepare(target);
+ preparedCache.set(target, targetPrepared);
+ return targetPrepared
+ };
+ var getPreparedSearch = (search) => {
+ if(search.length > 999) return prepareSearch(search) // don't cache huge searches
+ var searchPrepared = preparedSearchCache.get(search);
+ if(searchPrepared !== undefined) return searchPrepared
+ searchPrepared = prepareSearch(search);
+ preparedSearchCache.set(search, searchPrepared);
+ return searchPrepared
+ };
+
+
+ var all = (search, targets, options) => {
+ var results = []; results.total = targets.length;
+
+ var limit = options && options.limit || INT_MAX;
+
+ if(options && options.key) {
+ for(var i=0;i= limit) return results
+ }
+ } else if(options && options.keys) {
+ for(var i=0;i= 0; --keyI) {
+ var target = getValue(obj, options.keys[keyI]);
+ if(!target) { objResults[keyI] = NULL; continue }
+ if(!isObj(target)) target = getPrepared(target);
+ target.score = INT_MIN;
+ target._indexes.len = 0;
+ objResults[keyI] = target;
+ }
+ objResults.obj = obj;
+ objResults.score = INT_MIN;
+ results.push(objResults); if(results.length >= limit) return results
+ }
+ } else {
+ for(var i=0;i= limit) return results
+ }
+ }
+
+ return results
+ };
+
+
+ var algorithm = (preparedSearch, prepared, allowSpaces=false) => {
+ if(allowSpaces===false && preparedSearch.containsSpace) return algorithmSpaces(preparedSearch, prepared)
+
+ var searchLower = preparedSearch._lower;
+ var searchLowerCodes = preparedSearch.lowerCodes;
+ var searchLowerCode = searchLowerCodes[0];
+ var targetLowerCodes = prepared._targetLowerCodes;
+ var searchLen = searchLowerCodes.length;
+ var targetLen = targetLowerCodes.length;
+ var searchI = 0; // where we at
+ var targetI = 0; // where you at
+ var matchesSimpleLen = 0;
+
+ // very basic fuzzy match; to remove non-matching targets ASAP!
+ // walk through target. find sequential matches.
+ // if all chars aren't found then exit
+ for(;;) {
+ var isMatch = searchLowerCode === targetLowerCodes[targetI];
+ if(isMatch) {
+ matchesSimple[matchesSimpleLen++] = targetI;
+ ++searchI; if(searchI === searchLen) break
+ searchLowerCode = searchLowerCodes[searchI];
+ }
+ ++targetI; if(targetI >= targetLen) return NULL // Failed to find searchI
+ }
+
+ var searchI = 0;
+ var successStrict = false;
+ var matchesStrictLen = 0;
+
+ var nextBeginningIndexes = prepared._nextBeginningIndexes;
+ if(nextBeginningIndexes === NULL) nextBeginningIndexes = prepared._nextBeginningIndexes = prepareNextBeginningIndexes(prepared.target);
+ targetI = matchesSimple[0]===0 ? 0 : nextBeginningIndexes[matchesSimple[0]-1];
+
+ // Our target string successfully matched all characters in sequence!
+ // Let's try a more advanced and strict test to improve the score
+ // only count it as a match if it's consecutive or a beginning character!
+ var backtrackCount = 0;
+ if(targetI !== targetLen) for(;;) {
+ if(targetI >= targetLen) {
+ // We failed to find a good spot for this search char, go back to the previous search char and force it forward
+ if(searchI <= 0) break // We failed to push chars forward for a better match
+
+ ++backtrackCount; if(backtrackCount > 200) break // exponential backtracking is taking too long, just give up and return a bad match
+
+ --searchI;
+ var lastMatch = matchesStrict[--matchesStrictLen];
+ targetI = nextBeginningIndexes[lastMatch];
+
+ } else {
+ var isMatch = searchLowerCodes[searchI] === targetLowerCodes[targetI];
+ if(isMatch) {
+ matchesStrict[matchesStrictLen++] = targetI;
+ ++searchI; if(searchI === searchLen) { successStrict = true; break }
+ ++targetI;
+ } else {
+ targetI = nextBeginningIndexes[targetI];
+ }
+ }
+ }
+
+ // check if it's a substring match
+ var substringIndex = prepared._targetLower.indexOf(searchLower, matchesSimple[0]); // perf: this is slow
+ var isSubstring = ~substringIndex;
+ if(isSubstring && !successStrict) { // rewrite the indexes from basic to the substring
+ for(var i=0; i 24) score *= (uniqueBeginningIndexes-24)*10; // quite arbitrary numbers here ...
+ }
+
+ if(isSubstring) score /= 1+searchLen*searchLen*1; // bonus for being a full substring
+ if(isSubstringBeginning) score /= 1+searchLen*searchLen*1; // bonus for substring starting on a beginningIndex
+
+ score -= targetLen - searchLen; // penality for longer targets
+ prepared.score = score;
+
+ for(var i = 0; i < matchesBestLen; ++i) prepared._indexes[i] = matchesBest[i];
+ prepared._indexes.len = matchesBestLen;
+
+ return prepared
+ }
+ };
+ var algorithmSpaces = (preparedSearch, target) => {
+ var seen_indexes = new Set();
+ var score = 0;
+ var result = NULL;
+
+ var first_seen_index_last_search = 0;
+ var searches = preparedSearch.spaceSearches;
+ for(var i=0; i score) {
+ return allowSpacesResult
+ }
+
+ result.score = score;
+
+ var i = 0;
+ for (let index of seen_indexes) result._indexes[i++] = index;
+ result._indexes.len = i;
+
+ return result
+ };
+
+
+ var prepareLowerInfo = (str) => {
+ var strLen = str.length;
+ var lower = str.toLowerCase();
+ var lowerCodes = []; // new Array(strLen) sparse array is too slow
+ var bitflags = 0;
+ var containsSpace = false; // space isn't stored in bitflags because of how searching with a space works
+
+ for(var i = 0; i < strLen; ++i) {
+ var lowerCode = lowerCodes[i] = lower.charCodeAt(i);
+
+ if(lowerCode === 32) {
+ containsSpace = true;
+ continue // it's important that we don't set any bitflags for space
+ }
+
+ var bit = lowerCode>=97&&lowerCode<=122 ? lowerCode-97 // alphabet
+ : lowerCode>=48&&lowerCode<=57 ? 26 // numbers
+ // 3 bits available
+ : lowerCode<=127 ? 30 // other ascii
+ : 31; // other utf8
+ bitflags |= 1< {
+ var targetLen = target.length;
+ var beginningIndexes = []; var beginningIndexesLen = 0;
+ var wasUpper = false;
+ var wasAlphanum = false;
+ for(var i = 0; i < targetLen; ++i) {
+ var targetCode = target.charCodeAt(i);
+ var isUpper = targetCode>=65&&targetCode<=90;
+ var isAlphanum = isUpper || targetCode>=97&&targetCode<=122 || targetCode>=48&&targetCode<=57;
+ var isBeginning = isUpper && !wasUpper || !wasAlphanum || !isAlphanum;
+ wasUpper = isUpper;
+ wasAlphanum = isAlphanum;
+ if(isBeginning) beginningIndexes[beginningIndexesLen++] = i;
+ }
+ return beginningIndexes
+ };
+ var prepareNextBeginningIndexes = (target) => {
+ var targetLen = target.length;
+ var beginningIndexes = prepareBeginningIndexes(target);
+ var nextBeginningIndexes = []; // new Array(targetLen) sparse array is too slow
+ var lastIsBeginning = beginningIndexes[0];
+ var lastIsBeginningI = 0;
+ for(var i = 0; i < targetLen; ++i) {
+ if(lastIsBeginning > i) {
+ nextBeginningIndexes[i] = lastIsBeginning;
+ } else {
+ lastIsBeginning = beginningIndexes[++lastIsBeginningI];
+ nextBeginningIndexes[i] = lastIsBeginning===undefined ? targetLen : lastIsBeginning;
+ }
+ }
+ return nextBeginningIndexes
+ };
+
+
+ var cleanup = () => { preparedCache.clear(); preparedSearchCache.clear(); matchesSimple = []; matchesStrict = []; };
+
+ var preparedCache = new Map();
+ var preparedSearchCache = new Map();
+ var matchesSimple = []; var matchesStrict = [];
+
+
+ // for use with keys. just returns the maximum score
+ var defaultScoreFn = (a) => {
+ var max = INT_MIN;
+ var len = a.length;
+ for (var i = 0; i < len; ++i) {
+ var result = a[i]; if(result === NULL) continue
+ var score = result.score;
+ if(score > max) max = score;
+ }
+ if(max === INT_MIN) return NULL
+ return max
+ };
+
+ // prop = 'key' 2.5ms optimized for this case, seems to be about as fast as direct obj[prop]
+ // prop = 'key1.key2' 10ms
+ // prop = ['key1', 'key2'] 27ms
+ var getValue = (obj, prop) => {
+ var tmp = obj[prop]; if(tmp !== undefined) return tmp
+ var segs = prop;
+ if(!Array.isArray(prop)) segs = prop.split('.');
+ var len = segs.length;
+ var i = -1;
+ while (obj && (++i < len)) obj = obj[segs[i]];
+ return obj
+ };
+
+ var isObj = (x) => { return typeof x === 'object' }; // faster as a function
+ // var INT_MAX = 9007199254740991; var INT_MIN = -INT_MAX
+ var INT_MAX = Infinity; var INT_MIN = -INT_MAX;
+ var noResults = []; noResults.total = 0;
+ var NULL = null;
+
+
+ // Hacked version of https://github.com/lemire/FastPriorityQueue.js
+ var fastpriorityqueue=r=>{var e=[],o=0,a={},v=r=>{for(var a=0,v=e[a],c=1;c>1]=e[a],c=1+(a<<1);}for(var f=a-1>>1;a>0&&v.score>1)e[a]=e[f];e[a]=v;};return a.add=(r=>{var a=o;e[o++]=r;for(var v=a-1>>1;a>0&&r.score>1)e[a]=e[v];e[a]=r;}),a.poll=(r=>{if(0!==o){var a=e[0];return e[0]=e[--o],v(),a}}),a.peek=(r=>{if(0!==o)return e[0]}),a.replaceTop=(r=>{e[0]=r,v();}),a};
+ var q = fastpriorityqueue(); // reuse this
+
+
+ // fuzzysort is written this way for minification. all names are mangeled unless quoted
+ return {'single':single, 'go':go, 'highlight':highlight, 'prepare':prepare, 'indexes':indexes, 'cleanup':cleanup}
+}); // UMD
+
+// TODO: (feature) frecency
+// TODO: (perf) use different sorting algo depending on the # of results?
+// TODO: (perf) preparedCache is a memory leak
+// TODO: (like sublime) backslash === forwardslash
// TODO: (perf) prepareSearch seems slow
});
diff --git a/.obsidian/plugins/quick-latex/main.js b/.obsidian/plugins/quick-latex/main.js
old mode 100644
new mode 100755
index ef9574f..7da3138
--- a/.obsidian/plugins/quick-latex/main.js
+++ b/.obsidian/plugins/quick-latex/main.js
@@ -9,1956 +9,1956 @@ var obsidian = require('obsidian');
var state = require('@codemirror/state');
var view = require('@codemirror/view');
-/*! *****************************************************************************
-Copyright (c) Microsoft Corporation.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-***************************************************************************** */
-
-function __awaiter(thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
+/*! *****************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
+
+function __awaiter(thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
}
-const DEFAULT_SETTINGS = {
- useMathKeyboardShortcut_toggle: false,
- moveIntoMath_toggle: true,
- autoCloseMath_toggle: true,
- autoCloseRound_toggle: true,
- autoCloseSquare_toggle: true,
- autoCloseCurly_toggle: true,
- addAlignBlock_toggle: true,
- addAlignBlock_parameter: "align*",
- autoAlignSymbols: "= > < \\le \\ge \\neq \\approx",
- addCasesBlock_toggle: true,
- shiftEnter_toggle: false,
- addMatrixBlock_toggle: true,
- addMatrixBlock_parameter: "pmatrix",
- autoFraction_toggle: true,
- autoLargeBracket_toggle: true,
- autoSumLimit_toggle: true,
- autoEncloseSup_toggle: true,
- autoEncloseSub_toggle: true,
- encloseSelection_toggle: true,
- autoGreekCommandMathMode_toggle: true,
- customShorthand_toggle: true,
- useTabtoComplete_toggle: false,
- customShorthand_parameter: "bi:::\\binom{#cursor}{#tab};\nsq:::\\sqrt{};\nbb:::\\mathbb{};\nbf:::\\mathbf{};\nte:::\\text{};\ninf:::\\infty;\n" +
- "cd:::\\cdot;\nqu:::\\quad;\nti:::\\times;\n" +
- "al:::\\alpha;\nbe:::\\beta;\nga:::\\gamma;\nGa:::\\Gamma;\n" +
- "de:::\\delta;\nDe:::\\Delta;\nep:::\\epsilon;\nze:::\\zeta;\n" +
- "et:::\\eta;\nth:::\\theta;\nTh:::\\Theta;\nio:::\\iota;\n" +
- "ka:::\\kappa;\nla:::\\lambda;\nLa:::\\Lambda;\nmu:::\\mu;\n" +
- "nu:::\\nu;\nxi:::\\xi;\nXi:::\\Xi;\npi:::\\pi;\nPi:::\\Pi;\n" +
- "rh:::\\rho;\nsi:::\\sigma;\nSi:::\\Sigma;\nta:::\\tau;\n" +
- "up:::\\upsilon;\nUp:::\\Upsilon;\nph:::\\phi;\nPh:::\\Phi;\nch:::\\chi;\n" +
- "ps:::\\psi;\nPs:::\\Psi;\nom:::\\omega;\nOm:::\\Omega"
-};
-class QuickLatexPlugin extends obsidian.Plugin {
- constructor() {
- super(...arguments);
- this.vimAllow_autoCloseMath = true;
- this.makeExtensionThing = () => state.Prec.high(view.keymap.of([
- {
- key: '$',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (editor.getSelection().length > 0) {
- // enclose selected text
- if (this.settings.encloseSelection_toggle) {
- const anchor = editor.getCursor("anchor");
- const head = editor.getCursor("head");
- editor.replaceSelection(`$${editor.getSelection()}$`);
- if (anchor.line > head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 1 });
- }
- else if (anchor.line < head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch });
- }
- else {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch + 1 });
- }
- return true;
- }
- return false;
- }
- else {
- // close math symbol
- const position = editor.getCursor();
- const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const next2_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- if (prev_char != "$" && next_char == "$") {
- if (next2_char == "$$") {
- editor.setCursor({ line: position.line, ch: position.ch + 2 });
- return true;
- }
- else {
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- }
- // auto close math
- if (this.settings.autoCloseMath_toggle && this.vimAllow_autoCloseMath) {
- const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- const line = editor.getLine(position.line);
- const count = (line.match(/\$/g) || []).length;
- if (prev_char != "\\" && count % 2 == 0) {
- editor.replaceSelection("$");
- }
- }
- // move into math
- if (this.settings.moveIntoMath_toggle) {
- const position = editor.getCursor();
- const t = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- const t2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const t_2 = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
- if (t == '$' && t2 != '$') {
- editor.setCursor({ line: position.line, ch: position.ch - 1 });
- }
- else if (t_2 == '$$') {
- editor.setCursor({ line: position.line, ch: position.ch - 1 });
- }
- }
- return false;
- }
- },
- },
- // delete pair of math symbols with backspace
- { key: 'Backspace',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- const position = editor.getCursor();
- const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- if (prev_char == "$" && next_char == "$") {
- editor.replaceRange("", { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch + 1 });
- return true;
- }
- return false;
- }
- },
- {
- key: 'Tab',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- const end_pos = editor.getLine(position.line).length;
- const next_line = editor.getLine(position.line + 1);
- // check for custom shorthand
- if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
- if (this.settings.useTabtoComplete_toggle) {
- if (this.customShorthand(editor, position)) {
- return true;
- }
- }
- }
- // Tab to go to next #tab with numbering or without numbering if there are no #tabs with numbers
- const indexed_tab_expr = /#tab(\d+)?/g;
- let next_match;
- let current_match;
- while ((current_match = indexed_tab_expr.exec(current_line)) != null) {
- if (!next_match || parseInt(current_match[1]) < parseInt(next_match[1]))
- next_match = current_match;
- }
- if (next_match) {
- const tab_position = next_match.index;
- editor.replaceRange("", { line: position.line, ch: tab_position }, { line: position.line, ch: tab_position + next_match[0].length });
- editor.setCursor({ line: position.line, ch: tab_position });
- return true;
- }
- // Tab shortcut for matrix block
- if (this.settings.addMatrixBlock_toggle) {
- const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter + '}', "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
- const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter + '}', "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
- let state = false;
- let end_text = "";
- for (let i = 0; i < begin_matrix.length; i++) {
- if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
- state = true;
- end_text = end_matrix[i];
- break;
- }
- }
- const position = editor.getCursor();
- const prev3_char = editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
- if (state) {
- if (prev3_char == ' & ') {
- editor.replaceRange('', { line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
- editor.setCursor({ line: position.line, ch: position.ch + end_text.length - 3 });
- return true;
- }
- else {
- editor.replaceSelection(' & ');
- return true;
- }
- }
- }
- // Tab shortcut for cases block
- if (this.settings.addCasesBlock_toggle) {
- if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
- const position = editor.getCursor();
- const prev3_char = editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
- const next_line = editor.getLine(position.line + 1);
- if (prev3_char == ' & ' && next_line == '\\end{cases}') {
- editor.replaceRange('', { line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
- editor.setCursor({ line: position.line + 1, ch: next_line.length });
- return true;
- }
- else {
- editor.replaceSelection(' & ');
- return true;
- }
- }
- }
- // Tab out of $
- const next_2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- if (next_2 == "$$") {
- editor.setCursor({ line: position.line, ch: position.ch + 2 });
- return true;
- }
- else if (position.ch == end_pos && next_line == "$$") {
- editor.setCursor({ line: position.line + 1, ch: next_line.length });
- return true;
- }
- else if (next_2[0] == "$") {
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- // Tab to next close bracket
- const following_text = editor.getRange({ line: position.line, ch: position.ch + 1 }, { line: position.line, ch: current_line.length });
- const close_symbols = ['}', ']', ')', '$'];
- for (let i = 0; i < following_text.length; i++) {
- if (close_symbols.contains(following_text[i])) {
- editor.setCursor({ line: position.line, ch: position.ch + i + 1 });
- return true;
- }
- }
- // Tab out of align block
- if (position.ch == end_pos && next_line == '\\end{' + this.settings.addAlignBlock_parameter + '}') {
- editor.setCursor({ line: position.line + 1, ch: next_line.length });
- return true;
- }
- }
- return false;
- },
- },
- {
- key: 'Shift-Tab',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const preceding_text = editor.getRange({ line: position.line, ch: 0 }, { line: position.line, ch: position.ch });
- const close_symbols = ['}', ']', ')'];
- for (let i = preceding_text.length; i >= 0; i--) {
- if (close_symbols.contains(preceding_text[i])) {
- editor.setCursor({ line: position.line, ch: i });
- return true;
- }
- else if (position.ch - i > 1 && preceding_text[i] == "$") {
- editor.setCursor({ line: position.line, ch: i + 1 });
- return true;
- }
- else if (preceding_text.slice(-2) == "$$") {
- editor.setCursor({ line: position.line, ch: position.ch - 2 });
- return true;
- }
- else if (preceding_text[-1] == "$") {
- editor.setCursor({ line: position.line, ch: position.ch - 1 });
- return true;
- }
- }
- }
- return false;
- },
- },
- {
- key: 'Space',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (!this.settings.autoFraction_toggle &&
- !this.settings.autoLargeBracket_toggle &&
- !this.settings.autoEncloseSup_toggle &&
- !this.settings.autoEncloseSub_toggle &&
- !this.settings.customShorthand_toggle)
- return false;
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- const last_dollar = current_line.lastIndexOf('$', position.ch - 1);
- // check for custom shorthand
- if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
- if (!this.settings.useTabtoComplete_toggle) {
- if (this.customShorthand(editor, position)) {
- return true;
- }
- }
- }
- // find last unbracketed subscript within last 10 characters and perform autoEncloseSub
- // ignore expression that contain + - * / ^
- const last_math = current_line.lastIndexOf('$', position.ch - 1);
- if (this.settings.autoEncloseSub_toggle) {
- let last_subscript = current_line.lastIndexOf('_', position.ch);
- if (last_subscript != -1 && last_subscript > last_math) {
- const letter_after_subscript = editor.getRange({ line: position.line, ch: last_subscript + 1 }, { line: position.line, ch: last_subscript + 2 });
- if (letter_after_subscript != "{" &&
- (position.ch - last_subscript) <= 10) {
- editor.replaceSelection("}");
- editor.replaceRange("{", { line: position.line, ch: last_subscript + 1 });
- return true;
- }
- }
- }
- // retrieve the last unbracketed superscript
- let last_superscript = current_line.lastIndexOf('^', position.ch);
- while (last_superscript != -1) {
- const two_letters_after_superscript = editor.getRange({ line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 3 });
- if (two_letters_after_superscript[0] == '{' || two_letters_after_superscript == ' {') {
- last_superscript = current_line.lastIndexOf('^', last_superscript - 1);
- }
- else if (last_superscript < last_math) {
- last_superscript = -1;
- break;
- }
- else {
- break;
- }
- }
- // retrieve the last divide symbol
- let last_divide = current_line.lastIndexOf('/', position.ch - 2);
- while (last_divide != -1) {
- const around_divide = editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide + 2 });
- if (around_divide[0] == ' ' && around_divide[2] == ' ') {
- last_divide = current_line.lastIndexOf('^', last_divide - 1);
- }
- else if (last_divide < last_math) {
- last_divide = -1;
- break;
- }
- else {
- break;
- }
- }
- // perform autoEncloseSup
- if (this.settings.autoEncloseSup_toggle) {
- if (last_superscript > last_divide) {
- // if any brackets from last sup to cursor still unclosed, dont do autoEncloseSup yet
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_superscript)[0])) {
- return this.autoEncloseSup(editor, event, last_superscript);
- }
- }
- }
- // perform autoFraction
- if (this.settings.autoFraction_toggle && !this.withinText(editor, last_divide)) {
- if (last_divide > last_dollar) {
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- // if any brackets in denominator still unclosed, dont do autoFraction yet
- if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_divide)[0])) {
- return this.autoFractionCM6(editor, last_superscript);
- }
- }
- }
- // perform autoLargeBracket
- if (this.settings.autoLargeBracket_toggle) {
- let symbol_before = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- if (symbol_before == ')' || symbol_before == ']') {
- return this.autoLargeBracket(editor, event);
- }
- }
- // perform autoAlign
- if (this.autoAlign_array.length) {
- if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
- let keyword = "";
- let keyword_length = 0;
- for (let i = 0; i < this.autoAlign_array.length; i++) {
- keyword_length = this.autoAlign_array[i].length;
- if (keyword_length > position.ch) {
- continue;
- }
- else {
- keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
- }
- if (keyword == this.autoAlign_array[i]) {
- editor.replaceRange('&', { line: position.line, ch: position.ch - keyword_length });
- return false;
- }
- }
- }
- }
- }
- else if (this.settings.autoGreekCommandMathMode_toggle) {
- const greekSymbols = ['alpha', 'Alpha', 'beta', 'gamma', 'Gamma', 'delta', 'Delta', 'epsilon', 'zeta', 'eta', 'theta', 'Theta', 'iota', 'kappa', 'lambda', 'Lambda', 'mu', 'nu', 'xi', 'Xi', 'omicron', 'pi', 'Pi', 'rho', 'sigma', 'Sigma', 'tau', 'upsilon', 'Upsilon', 'phi', 'Phi', 'chi', 'psi', 'Psi', 'omega', 'Omega', 'varepsilon', 'vartheta', 'varrho', 'varphi'];
- const greekSymbolsSlashed = greekSymbols.map(x => '\\' + x);
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- const last_slash = current_line.lastIndexOf('\\', position.ch - 1);
- if (last_slash != -1) {
- const entered = current_line.substring(last_slash, position.ch);
- if (greekSymbolsSlashed.contains(entered))
- editor.replaceRange('$' + entered + '$', { line: position.line, ch: position.ch - entered.length }, { line: position.line, ch: position.ch });
- }
- }
- },
- },
- {
- key: 'Shift-Space',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (!this.settings.customShorthand_toggle)
- return false;
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- // check for custom shorthand
- if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
- let keyword = "";
- let keyword_length = 0;
- for (let i = 0; i < this.shorthand_array.length; i++) {
- keyword_length = this.shorthand_array[i][0].length;
- if (keyword_length > position.ch) {
- continue;
- }
- else if (keyword_length == position.ch) {
- keyword = "@" + editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
- }
- else {
- keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length - 1 }, { line: position.line, ch: position.ch });
- }
- if (keyword[0].toLowerCase() == keyword[0].toUpperCase() ||
- keyword[0] == "@") {
- if (this.shorthand_array[i][0] == keyword.slice(-keyword_length) &&
- this.shorthand_array[i][1] != keyword) {
- const replace_slash = (keyword[0] == "\\" && this.shorthand_array[i][1][0] == "\\") ? 1 : 0;
- const set_cursor_position = this.shorthand_array[i][1].indexOf("#cursor");
- editor.replaceRange(this.shorthand_array[i][1], { line: position.line, ch: position.ch - keyword_length - replace_slash }, { line: position.line, ch: position.ch });
- if (set_cursor_position != -1) {
- editor.replaceRange("", { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position }, { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position + 7 });
- editor.setCursor({ line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position });
- }
- else if (this.shorthand_array[i][1].slice(-2) == "{}") {
- editor.setCursor({ line: position.line,
- ch: position.ch + this.shorthand_array[i][1].length - keyword_length - 1 - replace_slash });
- }
- else ;
- return true;
- }
- }
- }
- }
- }
- }
- },
- {
- key: 'Enter',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.settings.addAlignBlock_toggle && this.settings.shiftEnter_toggle == false) {
- if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
- editor.replaceSelection('\\\\\n');
- return true;
- }
- }
- if (this.settings.addCasesBlock_toggle && this.settings.shiftEnter_toggle == false) {
- if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
- editor.replaceSelection(' \\\\\n');
- return true;
- }
- }
- if (this.settings.addMatrixBlock_toggle) {
- const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter + '}', "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
- const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter + '}', "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
- let state = false;
- for (let i = 0; i < begin_matrix.length; i++) {
- if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
- state = true;
- break;
- }
- }
- if (state) {
- editor.replaceSelection(' \\\\ ');
- return true;
- }
- }
- // double enter for $$
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const prev2_Char = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
- const next2_Char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- if (prev2_Char == "$$" && next2_Char == "$$") {
- editor.replaceSelection('\n');
- editor.setCursor(position);
- return false;
- }
- }
- return false;
- },
- },
- {
- key: 'Shift-Enter',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.settings.addAlignBlock_toggle && this.settings.shiftEnter_toggle == true) {
- if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
- editor.replaceSelection('\\\\\n');
- return true;
- }
- }
- if (this.settings.addCasesBlock_toggle && this.settings.shiftEnter_toggle == true) {
- if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
- editor.replaceSelection(' \\\\\n');
- return true;
- }
- }
- return false;
- }
- },
- {
- key: '{',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- if (this.settings.autoCloseCurly_toggle) {
- if (editor.getSelection().length > 0) {
- return false;
- }
- const position = editor.getCursor();
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
- if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
- editor.replaceSelection('{}');
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- }
- }
- return false;
- },
- },
- {
- key: '[',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- if (this.settings.autoCloseSquare_toggle) {
- if (editor.getSelection().length > 0) {
- return false;
- }
- const position = editor.getCursor();
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
- if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
- editor.replaceSelection('[]');
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- }
- }
- return false;
- },
- },
- {
- key: '(',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- if (this.settings.autoCloseRound_toggle) {
- if (editor.getSelection().length > 0) {
- return false;
- }
- const position = editor.getCursor();
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
- if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
- editor.replaceSelection('()');
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- }
- }
- return false;
- },
- },
- {
- key: '}',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- if (this.settings.autoCloseCurly_toggle) {
- const position = editor.getCursor();
- const end = editor.getLine(position.line).length;
- const next_sym = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- if (!this.unclosed_bracket(editor, "{", "}", end, 0)[0] &&
- !this.unclosed_bracket(editor, "{", "}", end, 0, false)[0] &&
- next_sym == "}") {
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- else {
- return false;
- }
- }
- }
- return false;
- },
- },
- {
- key: ']',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- if (this.settings.autoCloseSquare_toggle) {
- const position = editor.getCursor();
- const end = editor.getLine(position.line).length;
- const next_sym = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- if (!this.unclosed_bracket(editor, "[", "]", end, 0)[0] &&
- !this.unclosed_bracket(editor, "[", "]", end, 0, false)[0] &&
- next_sym == "]") {
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- else {
- return false;
- }
- }
- }
- return false;
- },
- },
- {
- key: ')',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- if (this.settings.autoCloseRound_toggle) {
- const position = editor.getCursor();
- const end = editor.getLine(position.line).length;
- const next_sym = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- if (!this.unclosed_bracket(editor, "(", ")", end, 0)[0] &&
- !this.unclosed_bracket(editor, "(", ")", end, 0, false)[0] &&
- next_sym == ")") {
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- return true;
- }
- else {
- return false;
- }
- }
- }
- return false;
- },
- },
- {
- key: 'm',
- run: () => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- const editor = view.editor;
- if (!this.withinMath(editor))
- return false;
- const position = editor.getCursor();
- if (!this.settings.autoSumLimit_toggle)
- return;
- if (this.withinMath(editor)) {
- if (editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch }) == '\\su') {
- editor.replaceSelection('m\\limits');
- return true;
- }
- }
- return false;
- },
- },
- ]));
- this.handleVimModeChange = (modeObj) => {
- if (!modeObj || modeObj.mode === 'insert')
- this.vimAllow_autoCloseMath = true;
- else
- this.vimAllow_autoCloseMath = false;
- };
- this.handleKeyDown = (cm, event) => {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return;
- const editor = view.editor;
- if (['$', ' ', 'Enter', 'Tab'].contains(event.key)) {
- switch (event.key) {
- case '$':
- if (editor.getSelection().length > 0) {
- if (this.settings.encloseSelection_toggle) {
- const anchor = editor.getCursor("anchor");
- const head = editor.getCursor("head");
- editor.replaceSelection('$' + editor.getSelection() + '$');
- if (anchor.line > head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 1 });
- }
- else if (anchor.line < head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch });
- }
- else {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch + 1 });
- }
- event.preventDefault();
- return;
- }
- }
- else {
- // close math symbol
- const position = editor.getCursor();
- const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const next2_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- if (prev_char != "$" && next_char == "$") {
- if (next2_char == "$$") {
- editor.setCursor({ line: position.line, ch: position.ch + 2 });
- event.preventDefault();
- return;
- }
- else {
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- event.preventDefault();
- return;
- }
- }
- // perform autoCloseMath
- if (this.settings.autoCloseMath_toggle && this.vimAllow_autoCloseMath) {
- editor.replaceSelection("$");
- }
- // perform moveIntoMath
- if (this.settings.moveIntoMath_toggle) {
- const position = editor.getCursor();
- const t = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- const t2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const t_2 = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
- if (t == '$' && t2 != '$') {
- editor.setCursor({ line: position.line, ch: position.ch - 1 });
- }
- else if (t_2 == '$$') {
- editor.setCursor({ line: position.line, ch: position.ch - 1 });
- }
- }
- }
- return;
- case ' ':
- if (!this.settings.autoFraction_toggle &&
- !this.settings.autoLargeBracket_toggle &&
- !this.settings.autoEncloseSup_toggle &&
- !this.settings.autoEncloseSub_toggle &&
- !this.settings.customShorthand_toggle)
- return;
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- const last_dollar = current_line.lastIndexOf('$', position.ch - 1);
- // check for custom shorthand
- if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
- let keyword = "";
- let keyword_length = 0;
- for (let i = 0; i < this.shorthand_array.length; i++) {
- keyword_length = this.shorthand_array[i][0].length;
- if (keyword_length > position.ch) {
- continue;
- }
- else if (keyword_length == position.ch) {
- keyword = "@" + editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
- }
- else {
- keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length - 1 }, { line: position.line, ch: position.ch });
- }
- if (keyword[0].toLowerCase() == keyword[0].toUpperCase() ||
- keyword[0] == "@") {
- if (this.shorthand_array[i][0] == keyword.slice(-keyword_length) &&
- this.shorthand_array[i][1] != keyword) {
- const replace_slash = (keyword[0] == "\\" && this.shorthand_array[i][1][0] == "\\") ? 1 : 0;
- const set_cursor_position = this.shorthand_array[i][1].indexOf("#cursor");
- editor.replaceRange(this.shorthand_array[i][1], { line: position.line, ch: position.ch - keyword_length - replace_slash }, { line: position.line, ch: position.ch });
- if (set_cursor_position != -1) {
- editor.replaceRange("", { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position }, { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position + 7 });
- editor.setCursor({ line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position });
- }
- else if (this.shorthand_array[i][1].slice(-2) == "{}") {
- editor.setCursor({ line: position.line,
- ch: position.ch + this.shorthand_array[i][1].length - keyword_length - 1 - replace_slash });
- }
- else ;
- event.preventDefault();
- return;
- }
- }
- }
- }
- // find last unbracketed subscript within last 10 characters and perform autoEncloseSub
- // ignore expression that contain + - * / ^
- const last_math = current_line.lastIndexOf('$', position.ch - 1);
- if (this.settings.autoEncloseSub_toggle) {
- let last_subscript = current_line.lastIndexOf('_', position.ch);
- if (last_subscript != -1 && last_subscript > last_math) {
- const letter_after_subscript = editor.getRange({ line: position.line, ch: last_subscript + 1 }, { line: position.line, ch: last_subscript + 2 });
- if (letter_after_subscript != "{" &&
- (position.ch - last_subscript) <= 10) {
- editor.replaceRange("}", position);
- editor.replaceRange("{", { line: position.line, ch: last_subscript + 1 });
- event.preventDefault();
- return;
- }
- }
- }
- // retrieve the last unbracketed superscript
- let last_superscript = current_line.lastIndexOf('^', position.ch);
- while (last_superscript != -1) {
- const two_letters_after_superscript = editor.getRange({ line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 3 });
- if (two_letters_after_superscript[0] == '{' || two_letters_after_superscript == ' {') {
- last_superscript = current_line.lastIndexOf('^', last_superscript - 1);
- }
- else if (last_superscript < last_math) {
- last_superscript = -1;
- break;
- }
- else {
- break;
- }
- }
- // retrieve the last divide symbol
- let last_divide = current_line.lastIndexOf('/', position.ch - 2);
- while (last_divide != -1) {
- const around_divide = editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide + 2 });
- if (around_divide[0] == ' ' && around_divide[2] == ' ') {
- last_divide = current_line.lastIndexOf('^', last_divide - 1);
- }
- else if (last_divide < last_math) {
- last_divide = -1;
- break;
- }
- else {
- break;
- }
- }
- // perform autoEncloseSup
- if (this.settings.autoEncloseSup_toggle) {
- if (last_superscript > last_divide) {
- // if any brackets from last sup to cursor still unclosed, dont do autoEncloseSup yet
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_superscript)[0])) {
- this.autoEncloseSup(editor, event, last_superscript);
- return;
- }
- }
- }
- // perform autoFraction
- if (this.settings.autoFraction_toggle && !this.withinText(editor, last_divide)) {
- if (last_divide > last_dollar) {
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- // if any brackets in denominator still unclosed, dont do autoFraction yet
- if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_divide)[0])) {
- this.autoFraction(editor, event, last_superscript);
- return;
- }
- }
- }
- // perform autoLargeBracket
- if (this.settings.autoLargeBracket_toggle) {
- let symbol_before = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- if (symbol_before == ')' || symbol_before == ']') {
- this.autoLargeBracket(editor, event);
- return;
- }
- }
- }
- break;
- case 'Enter':
- // perform Enter shortcut within matrix block
- if (this.settings.addMatrixBlock_toggle) {
- const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter, "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
- const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter, "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
- let state = false;
- for (let i = 0; i < begin_matrix.length; i++) {
- if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
- state = true;
- break;
- }
- }
- if (!event.shiftKey) {
- if (state) {
- editor.replaceSelection(' \\\\ ');
- event.preventDefault();
- return;
- }
- }
- }
- // perform Enter shortcut within align block
- if (this.settings.addAlignBlock_toggle) {
- if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
- if (!event.shiftKey) {
- editor.replaceSelection('\\\\\n&');
- event.preventDefault();
- }
- return;
- }
- }
- // enter for cases block
- if (this.settings.addCasesBlock_toggle) {
- if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
- editor.replaceSelection(' \\\\\n');
- event.preventDefault();
- return;
- }
- }
- // double enter for $$
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const prev2_Char = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
- const next2_Char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- if (prev2_Char == "$$" && next2_Char == "$$") {
- editor.replaceSelection('\n');
- editor.setCursor(position);
- }
- }
- return;
- case 'Tab':
- // perform Tab shortcut within matrix block
- if (this.settings.addMatrixBlock_toggle) {
- const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter, "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
- const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter, "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
- let state = false;
- for (let i = 0; i < begin_matrix.length; i++) {
- if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
- state = true;
- break;
- }
- }
- if (state) {
- editor.replaceSelection(' & ');
- event.preventDefault();
- return;
- }
- }
- // Tab shortcut for cases block
- if (this.settings.addCasesBlock_toggle) {
- if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
- editor.replaceSelection(' & ');
- event.preventDefault();
- return;
- }
- }
- // Tab to go to next #tab with numbering or without numbering if there are no #tabs with numbers
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- const indexed_tab_expr = /#tab(\d+)?/g;
- let next_match;
- let current_match;
- while ((current_match = indexed_tab_expr.exec(current_line)) != null) {
- if (!next_match || parseInt(current_match[1]) < parseInt(next_match[1]))
- next_match = current_match;
- }
- if (next_match) {
- const tab_position = next_match.index;
- editor.replaceRange("", { line: position.line, ch: tab_position }, { line: position.line, ch: tab_position + next_match[0].length });
- editor.setCursor({ line: position.line, ch: tab_position });
- event.preventDefault();
- return;
- }
- // Tab to next close bracket
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- if (event.shiftKey) {
- const close_symbols = ['}', ']', ')'];
- const preceding_text = editor.getRange({ line: position.line, ch: 0 }, { line: position.line, ch: position.ch });
- for (let i = preceding_text.length; i >= 0; i--) {
- if (close_symbols.contains(preceding_text[i])) {
- editor.setCursor({ line: position.line, ch: i });
- event.preventDefault();
- return;
- }
- else if (position.ch - i > 1 && preceding_text[i] == "$") {
- editor.setCursor({ line: position.line, ch: i + 1 });
- event.preventDefault();
- return;
- }
- else if (preceding_text.slice(-2) == "$$") {
- editor.setCursor({ line: position.line, ch: position.ch - 2 });
- event.preventDefault();
- return;
- }
- else if (preceding_text[-1] == "$") {
- editor.setCursor({ line: position.line, ch: position.ch - 1 });
- event.preventDefault();
- return;
- }
- }
- }
- else {
- const close_symbols = ['}', ']', ')', '$'];
- const following_text = editor.getRange({ line: position.line, ch: position.ch + 1 }, { line: position.line, ch: current_line.length });
- for (let i = 0; i < following_text.length; i++) {
- if (close_symbols.contains(following_text[i])) {
- editor.setCursor({ line: position.line, ch: position.ch + i + 1 });
- event.preventDefault();
- return;
- }
- }
- }
- }
- // Tab out of $
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const next_2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- if (next_2 == "$$") {
- editor.setCursor({ line: position.line, ch: position.ch + 2 });
- event.preventDefault();
- return;
- }
- else if (next_2[0] == "$") {
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- event.preventDefault();
- return;
- }
- }
- }
- }
- };
- this.handleKeyPress = (cm, event) => {
- if (['{', '[', '(', 'm'].contains(event.key)) {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return;
- const editor = view.editor;
- if (this.withinMath(editor)) {
- const position = editor.getCursor();
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
- const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
- const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
- switch (event.key) {
- case '{':
- if (this.settings.autoCloseCurly_toggle) {
- if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
- editor.replaceSelection('{}');
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- event.preventDefault();
- return;
- }
- }
- return;
- case '[':
- if (this.settings.autoCloseSquare_toggle) {
- if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
- editor.replaceSelection('[]');
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- event.preventDefault();
- return;
- }
- }
- return;
- case '(':
- if (this.settings.autoCloseRound_toggle) {
- if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
- editor.replaceSelection('()');
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- event.preventDefault();
- return;
- }
- }
- return;
- case 'm':
- if (!this.settings.autoSumLimit_toggle)
- return;
- if (editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch }) == '\\su') {
- editor.replaceSelection('m\\limits');
- event.preventDefault();
- return;
- }
- }
- }
- }
- };
- //main functions
- this.customShorthand = (editor, position) => {
- let keyword = "";
- let keyword_length = 0;
- for (let i = 0; i < this.shorthand_array.length; i++) {
- keyword_length = this.shorthand_array[i][0].length;
- if (keyword_length > position.ch) {
- continue;
- }
- else if (keyword_length == position.ch) {
- keyword = "@" + editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
- }
- else {
- keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length - 1 }, { line: position.line, ch: position.ch });
- }
- if (keyword[0].toLowerCase() == keyword[0].toUpperCase() ||
- keyword[0] == "@") {
- if (this.shorthand_array[i][0] == keyword.slice(-keyword_length) &&
- this.shorthand_array[i][1] != keyword) {
- const replace_slash = (keyword[0] == "\\" && this.shorthand_array[i][1][0] == "\\") ? 1 : 0;
- const set_cursor_position = this.shorthand_array[i][1].indexOf("#cursor");
- editor.replaceRange(this.shorthand_array[i][1], { line: position.line, ch: position.ch - keyword_length - replace_slash }, { line: position.line, ch: position.ch });
- if (set_cursor_position != -1) {
- editor.replaceRange("", { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position }, { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position + 7 });
- editor.setCursor({ line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position });
- }
- else if (this.shorthand_array[i][1].slice(-2) == "{}") {
- editor.setCursor({ line: position.line,
- ch: position.ch + this.shorthand_array[i][1].length - keyword_length - 1 - replace_slash });
- }
- else ;
- return true;
- }
- }
- }
- };
- this.autoEncloseSup = (editor, event, last_superscript) => {
- // superscript bracketing
- const position = editor.getCursor();
- const letter_before_cursor = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- if (last_superscript != -1 && letter_before_cursor != "^") {
- const letter_after_superscript = editor.getRange({ line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 2 });
- if (letter_after_superscript == '(' && letter_before_cursor == ')' && position.ch - last_superscript > 6) {
- editor.replaceRange('}', { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- editor.replaceRange('{', { line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 2 });
- event.preventDefault();
- return true;
- }
- else if (letter_after_superscript == ' ') {
- editor.replaceSelection('}');
- editor.replaceRange('{', { line: position.line, ch: last_superscript + 2 });
- event.preventDefault();
- return true;
- }
- else {
- editor.replaceSelection('}');
- editor.replaceRange('{', { line: position.line, ch: last_superscript + 1 });
- event.preventDefault();
- return true;
- }
- }
- else {
- return false;
- }
- };
- this.autoFraction = (editor, event, last_superscript) => {
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- let last_divide = current_line.lastIndexOf('/', position.ch - 1);
- // if cursor is preceeded by a close bracket, and the corresponding open bracket
- // is found before "/", remove the brackets and enclose whole expression using \frac
- const letter_before_cursor = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- // if there are any brackets unclosed before divide symbol,
- // include the open brackets into stop_symbols
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- let stop_brackets = [];
- for (let i = 0; i < brackets.length; i++) {
- if (letter_before_cursor == brackets[i][1]) {
- const open_brackets = this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], position.ch - 1, 0)[1];
- const pos_of_the_open_bracket = open_brackets[open_brackets.length - 1];
- if (pos_of_the_open_bracket < last_divide) {
- editor.replaceRange('}', { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- editor.replaceRange('}{', { line: position.line, ch: last_divide }, { line: position.line, ch: last_divide + 1 });
- editor.replaceRange('\\frac{', { line: position.line, ch: pos_of_the_open_bracket }, { line: position.line, ch: pos_of_the_open_bracket + 1 });
- event.preventDefault();
- return;
- }
- }
- stop_brackets.push(...this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], last_divide, 0)[1]);
- }
- let frac = 0;
- // if numerator is enclosed by (), place frac in front of () and remove ()
- let numerator_remove_bracket = 0;
- if (editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide }) == ')') {
- const numerator_open_bracket = this.unclosed_bracket(editor, '(', ')', last_divide - 1, 0)[1].slice(-1)[0];
- frac = numerator_open_bracket - 1;
- numerator_remove_bracket = 1;
- }
- else {
- const stop_symbols = ['$', '=', '>', '<', ',', '/', ' '];
- const symbol_positions = stop_symbols.map(e => current_line.lastIndexOf(e, last_divide - 1));
- frac = Math.max(last_superscript, ...symbol_positions, ...stop_brackets);
- }
- // if denominator is enclosed by (), remove ()
- const denominator = editor.getRange({ line: position.line, ch: last_divide + 1 }, { line: position.line, ch: position.ch });
- let denominator_remove_bracket = 0;
- if (denominator.slice(-1)[0] == ')') {
- const denominator_open_bracket = this.unclosed_bracket(editor, '(', ')', position.ch - 1, 0)[1].slice(-1)[0];
- if (denominator_open_bracket == last_divide + 1) {
- denominator_remove_bracket = 1;
- }
- }
- // perform \frac replace
- editor.replaceRange('}', { line: position.line, ch: position.ch - denominator_remove_bracket }, { line: position.line, ch: position.ch });
- editor.replaceRange('}{', { line: position.line, ch: last_divide - numerator_remove_bracket }, { line: position.line, ch: last_divide + 1 + denominator_remove_bracket });
- editor.replaceRange('\\frac{', { line: position.line, ch: frac + 1 }, { line: position.line, ch: frac + 1 + numerator_remove_bracket });
- event.preventDefault();
- return;
- };
- this.autoFractionCM6 = (editor, last_superscript) => {
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- let last_divide = current_line.lastIndexOf('/', position.ch - 1);
- // if cursor is preceeded by a close bracket, and the corresponding open bracket
- // is found before "/", remove the brackets and enclose whole expression using \frac
- const letter_before_cursor = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- // if there are any brackets unclosed before divide symbol,
- // include the open brackets into stop_symbols
- const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
- let stop_brackets = [];
- for (let i = 0; i < brackets.length; i++) {
- if (letter_before_cursor == brackets[i][1]) {
- const open_brackets = this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], position.ch - 1, 0)[1];
- const pos_of_the_open_bracket = open_brackets[open_brackets.length - 1];
- if (pos_of_the_open_bracket < last_divide) {
- editor.replaceRange('}', { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- editor.replaceRange('}{', { line: position.line, ch: last_divide }, { line: position.line, ch: last_divide + 1 });
- editor.replaceRange('\\frac{', { line: position.line, ch: pos_of_the_open_bracket }, { line: position.line, ch: pos_of_the_open_bracket + 1 });
- return true;
- }
- }
- stop_brackets.push(...this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], last_divide, 0)[1]);
- }
- let frac = 0;
- // if numerator is enclosed by (), place frac in front of () and remove ()
- let numerator_remove_bracket = 0;
- if (editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide }) == ')') {
- const numerator_open_bracket = this.unclosed_bracket(editor, '(', ')', last_divide - 1, 0)[1].slice(-1)[0];
- frac = numerator_open_bracket - 1;
- numerator_remove_bracket = 1;
- }
- else {
- const stop_symbols = ['$', '=', '>', '<', ',', '/', ' '];
- const symbol_positions = stop_symbols.map(e => current_line.lastIndexOf(e, last_divide - 1));
- frac = Math.max(last_superscript, ...symbol_positions, ...stop_brackets);
- }
- // if denominator is enclosed by (), remove ()
- const denominator = editor.getRange({ line: position.line, ch: last_divide + 1 }, { line: position.line, ch: position.ch });
- let denominator_remove_bracket = 0;
- if (denominator.slice(-1)[0] == ')') {
- const denominator_open_bracket = this.unclosed_bracket(editor, '(', ')', position.ch - 1, 0)[1].slice(-1)[0];
- if (denominator_open_bracket == last_divide + 1) {
- denominator_remove_bracket = 1;
- }
- }
- // perform \frac replace
- editor.replaceRange('}', { line: position.line, ch: position.ch - denominator_remove_bracket }, { line: position.line, ch: position.ch });
- editor.replaceRange('}{', { line: position.line, ch: last_divide - numerator_remove_bracket }, { line: position.line, ch: last_divide + 1 + denominator_remove_bracket });
- editor.replaceRange('\\frac{', { line: position.line, ch: frac + 1 }, { line: position.line, ch: frac + 1 + numerator_remove_bracket });
- const pos = editor.getCursor();
- editor.setCursor({ line: pos.line, ch: pos.ch + 1 - denominator_remove_bracket });
- return true;
- };
- this.autoLargeBracket = (editor, event) => {
- const position = editor.getCursor();
- let brackets = [['[', ']'], ['(', ')']];
- const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
- const current_brackets = brackets.filter(e => e[1] == prev_char)[0];
- if (current_brackets.length == 0)
- return;
- const open_bracket = this.unclosed_bracket(editor, current_brackets[0], current_brackets[1], position.ch - 1, 0)[1].slice(-1)[0];
- const text = editor.getRange({ line: position.line, ch: open_bracket }, { line: position.line, ch: position.ch });
- const large_operators = ['\\sum', '\\int', '\\frac', '\\dfrac'];
- let large_operators_locations = [];
- for (let i = 0; i < large_operators.length; i++) {
- let found = 0;
- while (found != -1) {
- found = text.indexOf(large_operators[i], found + 1);
- if (found != -1) {
- large_operators_locations.push(found + open_bracket);
- }
- }
- }
- const current_line = editor.getLine(position.line);
- let retVal = false;
- for (let i = 0; i < large_operators_locations.length; i++) {
- let left_array = [];
- let right_array = [];
- for (let j = 0; j < brackets.length; j++) {
- left_array.push(...this.unclosed_bracket(editor, brackets[j][0], brackets[j][1], large_operators_locations[i], 0)[1]);
- right_array.push(...this.unclosed_bracket(editor, brackets[j][0], brackets[j][1], current_line.length, large_operators_locations[i], false)[1]);
- }
- for (let k = right_array.length - 1; k > -1; k--) {
- // check if unclosed brackets already appended with \right
- let check_right = editor.getRange({ line: position.line, ch: right_array[k] - 6 }, { line: position.line, ch: right_array[k] });
- if (check_right != '\\right') {
- editor.replaceRange('\\right', { line: position.line, ch: right_array[k] });
- event.preventDefault();
- retVal = true;
- }
- }
- for (let l = left_array.length - 1; l > -1; l--) {
- // check if unclosed brackets already appended with \left
- let check_left = editor.getRange({ line: position.line, ch: left_array[l] - 5 }, { line: position.line, ch: left_array[l] });
- if (check_left != '\\left') {
- editor.replaceRange('\\left', { line: position.line, ch: left_array[l] });
- event.preventDefault();
- retVal = true;
- }
- }
- }
- return retVal;
- };
- //utility functions
- this.unclosed_bracket = (editor, open_symbol, close_symbol, before, after, unclosed_open_symbol = true //false for unclosed_close_symbol
- ) => {
- // determine if there are unclosed bracket within the range specified by before and after
- const position = editor.getCursor();
- const text = editor.getRange({ line: position.line, ch: after }, { line: position.line, ch: before });
- let open_array = [];
- let close_array = [];
- for (let i = 0; i < text.length; i++) {
- switch (text[i]) {
- case open_symbol:
- open_array.push(after + i);
- break;
- case close_symbol:
- if (open_array.length > 0) {
- open_array.pop();
- }
- else {
- close_array.push(after + i);
- }
- break;
- }
- }
- if (unclosed_open_symbol) {
- return [open_array.length > 0, open_array];
- }
- else {
- return [close_array.length > 0, close_array];
- }
- };
- this.withinText = (editor, at_where) => {
- // check if within text{}
- const position = editor.getCursor();
- const bracket_locations = this.unclosed_bracket(editor, '{', '}', at_where, 0)[1];
- return bracket_locations.some(loc => editor.getRange({ line: position.line, ch: loc - 4 }, { line: position.line, ch: loc }) == "text");
- };
- this.withinMath = (editor) => {
- // check if cursor within $$
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- let cursor_index = position.ch;
- let from = 0;
- let found = current_line.indexOf('$', from);
- while (found != -1 && found < cursor_index) {
- let next_char = editor.getRange({ line: position.line, ch: found + 1 }, { line: position.line, ch: found + 2 });
- let prev_char = editor.getRange({ line: position.line, ch: found - 1 }, { line: position.line, ch: found });
- if (next_char == '$' || prev_char == '$' || next_char == ' ') {
- from = found + 1;
- found = current_line.indexOf('$', from);
- continue;
- }
- else {
- from = found + 1;
- let next_found = current_line.indexOf('$', from);
- if (next_found == -1) {
- return false;
- }
- else if (cursor_index > found && cursor_index <= next_found) {
- return true;
- }
- else {
- from = next_found + 1;
- found = current_line.indexOf('$', from);
- continue;
- }
- }
- }
- const document_text = editor.getValue();
- cursor_index = editor.posToOffset(position);
- from = 0;
- found = document_text.indexOf('$$', from);
- let count = 0;
- while (found != -1 && found < cursor_index) {
- count += 1;
- from = found + 2;
- found = document_text.indexOf('$$', from);
- }
- return count % 2 == 1;
- };
- this.withinAnyBrackets_inline = (editor, brackets) => {
- const position = editor.getCursor();
- const current_line = editor.getLine(position.line);
- return brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, 0)[0] &&
- this.unclosed_bracket(editor, e[0], e[1], current_line.length, position.ch, false)[0]);
- };
- this.withinAnyBrackets_document = (editor, open_symbol, close_symbol) => {
- const document_text = editor.getValue();
- const cursorPos = editor.getCursor();
- const cursor_index = editor.posToOffset(cursorPos);
- // count open symbols
- let from = 0;
- let found = document_text.indexOf(open_symbol, from);
- let count = 0;
- while (found != -1 && found < cursor_index) {
- count += 1;
- from = found + 1;
- found = document_text.indexOf(open_symbol, from);
- }
- const open_symbol_counts = count;
- // count close symbols
- from = 0;
- found = document_text.indexOf(close_symbol, from);
- count = 0;
- while (found != -1 && found < cursor_index) {
- count += 1;
- from = found + 1;
- found = document_text.indexOf(close_symbol, from);
- }
- const close_symbol_counts = count;
- return open_symbol_counts > close_symbol_counts;
- };
- }
- onload() {
- return __awaiter(this, void 0, void 0, function* () {
- this.registerEditorExtension(this.makeExtensionThing());
- yield this.loadSettings();
- // preprocess shorthand array
- let shorthands = this.settings.customShorthand_parameter;
- while (shorthands.slice(-2) == "\n") {
- shorthands = shorthands.slice(0, -2);
- }
- if (shorthands.slice(-1) == ";") {
- shorthands = shorthands.slice(0, -1);
- }
- if (shorthands.lastIndexOf(";\n") == -1) {
- this.shorthand_array = shorthands.split(",").map(item => item.split(":"));
- }
- else if (shorthands.lastIndexOf(":::") == -1) {
- this.shorthand_array = shorthands.split(";\n").map(item => item.split(":"));
- }
- else {
- this.shorthand_array = shorthands.split(";\n").map(item => item.split(":::"));
- }
- // preprocess autoAlign array
- if (this.settings.autoAlignSymbols.trim() == "") {
- this.autoAlign_array = [];
- }
- else {
- this.autoAlign_array = this.settings.autoAlignSymbols.split(" ");
- }
- this.app.workspace.onLayoutReady(() => {
- this.registerCodeMirror((cm) => {
- cm.on('vim-mode-change', this.handleVimModeChange);
- cm.on('keydown', this.handleKeyDown);
- cm.on('keypress', this.handleKeyPress);
- });
- this.addSettingTab(new QuickLatexSettingTab(this.app, this));
- this.addCommand({
- id: 'addAlignBlock',
- name: 'Add Align Block',
- hotkeys: [
- {
- modifiers: ['Alt', 'Shift'],
- key: 'A',
- },
- ],
- editorCallback: (editor) => this.addAlignBlock(editor),
- });
- this.addCommand({
- id: 'addInlineMath',
- name: 'Add Inline Math',
- hotkeys: [
- {
- modifiers: ['Mod'],
- key: 'M',
- },
- ],
- editorCallback: (editor) => this.addInlineMath(editor),
- });
- this.addCommand({
- id: 'addBlockMath',
- name: 'Add Block Math',
- hotkeys: [
- {
- modifiers: ['Mod', 'Shift'],
- key: 'M',
- },
- ],
- editorCallback: (editor) => this.addBlockMath(editor),
- });
- this.addCommand({
- id: 'addMatrixBlock',
- name: 'Add Matrix Block',
- hotkeys: [
- {
- modifiers: ['Alt', 'Shift'],
- key: 'M',
- },
- ],
- editorCallback: (editor) => this.addMatrixBlock(editor),
- });
- this.addCommand({
- id: 'addCasesBlock',
- name: 'Add Cases Block',
- hotkeys: [
- {
- modifiers: ['Alt', 'Shift'],
- key: 'C',
- },
- ],
- editorCallback: (editor) => this.addCasesBlock(editor),
- });
- });
- });
- }
- addInlineMath(editor) {
- if (!this.settings.useMathKeyboardShortcut_toggle)
- return false;
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- if (editor.getSelection().length > 0) {
- // enclose selected text
- const anchor = editor.getCursor("anchor");
- const head = editor.getCursor("head");
- editor.replaceSelection(`$${editor.getSelection()}$`);
- if (anchor.line > head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 1 });
- }
- else if (anchor.line < head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch });
- }
- else {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch + 1 });
- }
- }
- else {
- const position = editor.getCursor();
- editor.replaceSelection("$$");
- editor.setCursor({ line: position.line, ch: position.ch + 1 });
- }
- return true;
- }
- addBlockMath(editor) {
- if (!this.settings.useMathKeyboardShortcut_toggle)
- return false;
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return false;
- if (editor.getSelection().length > 0) {
- // enclose selected text
- const anchor = editor.getCursor("anchor");
- const head = editor.getCursor("head");
- editor.replaceSelection(`$$${editor.getSelection()}$$`);
- if (anchor.line > head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 2 });
- }
- else if (anchor.line < head.line) {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 2 }, { line: head.line, ch: head.ch });
- }
- else {
- editor.setSelection({ line: anchor.line, ch: anchor.ch + 2 }, { line: head.line, ch: head.ch + 2 });
- }
- }
- else {
- const position = editor.getCursor();
- editor.replaceSelection("$$$$");
- editor.setCursor({ line: position.line, ch: position.ch + 2 });
- }
- return true;
- }
- addAlignBlock(editor) {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return;
- if (!this.settings.addAlignBlock_toggle)
- return;
- const selected_text = editor.getSelection();
- editor.replaceSelection('\\begin{' + this.settings.addAlignBlock_parameter + '}\n' +
- selected_text +
- '\n\\end{' + this.settings.addAlignBlock_parameter + '}');
- const position = editor.getCursor();
- editor.setCursor({ line: position.line - 1, ch: editor.getLine(position.line - 1).length });
- }
- addMatrixBlock(editor) {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return;
- if (!this.settings.addMatrixBlock_toggle)
- return;
- editor.replaceSelection('\\begin{' + this.settings.addMatrixBlock_parameter + '}' +
- '\\end{' + this.settings.addMatrixBlock_parameter + '}');
- const position = editor.getCursor();
- const retract_length = ('\\end{' + this.settings.addMatrixBlock_parameter + '}').length;
- editor.setCursor({ line: position.line, ch: position.ch - retract_length });
- }
- addCasesBlock(editor) {
- const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
- if (!view)
- return;
- if (!this.settings.addCasesBlock_toggle)
- return;
- const selected_text = editor.getSelection();
- editor.replaceSelection('\\begin{cases}\n' +
- selected_text +
- '\n\\end{cases}');
- const position = editor.getCursor();
- editor.setCursor({ line: position.line - 1, ch: editor.getLine(position.line - 1).length });
- }
- // Settings load and save
- loadSettings() {
- return __awaiter(this, void 0, void 0, function* () {
- this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
- });
- }
- ;
- onunload() {
- this.app.workspace.iterateCodeMirrors((cm) => {
- cm.off('vim-mode-change', this.handleVimModeChange);
- cm.off('keydown', this.handleKeyDown);
- cm.off('keypress', this.handleKeyPress);
- });
- }
-}
-class QuickLatexSettingTab extends obsidian.PluginSettingTab {
- constructor(app, plugin) {
- super(app, plugin);
- this.plugin = plugin;
- }
- display() {
- const { containerEl } = this;
- containerEl.empty();
- containerEl.createEl('h2', { text: 'Quick Latex for Obsidian - Settings' });
- new obsidian.Setting(containerEl)
- .setName('Autoclose $$ symbols')
- .setDesc('Typing one $ symbol will automatically lose with another $ symbol ' +
- '(best used with "Move cursor between $$ symbols" function')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoCloseMath_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoCloseMath_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Shortcut for inline and block math')
- .setDesc('Enable keyboard shortcuts for inline ($...$) and block ($$...$$) math. ' +
- 'Default: ctrl+m (cmd+m on mac) for inline and ctrl+shift+m (cmd+shift+m on mac) for block.')
- .addToggle((toggle) => {
- toggle.setValue(this.plugin.settings.useMathKeyboardShortcut_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.useMathKeyboardShortcut_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- }));
- });
- new obsidian.Setting(containerEl)
- .setName('Move cursor between $$ symbols')
- .setDesc('Typing two consecutive $ symbols will automatically shift the cursor in between the $$ symbols')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.moveIntoMath_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.moveIntoMath_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Enclose selected expression with math symbol $$')
- .setDesc('Select an expression and press "$" key will automatically ' +
- 'enclose the expression with the math symbols.')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.encloseSelection_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.encloseSelection_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Autoclose {} curly brackets')
- .setDesc('Typing "{" will automatically close with "}"')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoCloseCurly_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoCloseCurly_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Autoclose [] square brackets')
- .setDesc('Typing "[" will automatically close with "]"')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoCloseSquare_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoCloseSquare_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Autoclose () round brackets')
- .setDesc('Typing "(" will automatically close with ")"')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoCloseRound_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoCloseRound_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Auto append "\\limits" after "\\sum"')
- .setDesc('Typing "\\sum" will automatically append "\\limits" to shorten the syntax' +
- ' for proper display of the limits for summation symbol.')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoSumLimit_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoSumLimit_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Auto enlarge brackets that contains \\sum, \\int or \\frac')
- .setDesc('Place cursor right after a () or [] bracketed expression that contains either ' +
- '\\sum, \\int or \\frac and press the space key, the outermost brackets will be' +
- ' appended with \\left and \\right in order to display larger brackets to enclose these big expressions.')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoLargeBracket_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoLargeBracket_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Auto enclose expression after superscipt with {}')
- .setDesc('Typing expression after superscript "^" symbol follow by a "space" key ' +
- 'will automatically surround the expression with "{}"')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoEncloseSup_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoEncloseSup_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Auto enclose expression after subscript with {}')
- .setDesc('Typing expression after subscript "_" symbol follow by a "space" key ' +
- 'will automatically surround the expression with "{}". ' +
- 'Note: expression more than 10 characters long will be ignored.')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoEncloseSub_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoEncloseSub_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Type "/" instead of \\frac{}{}')
- .setDesc('Use "/" symbol for quickly typing fractions. eg. type "1/2" followed by a "space" key' +
- ' to transform to \\frac{1}{2}')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoFraction_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoFraction_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Shortcut for Align Block')
- .setDesc('Use shortcut key to quickly insert \\begin{align*} \\end{align*} block. ' +
- 'Default: "Alt+Shift+A" (Mac: "Option+Shift+A")')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.addAlignBlock_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.addAlignBlock_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Align Block Parameter')
- .setDesc('Set the text parameter in \\begin{parameter} and \\end{parameter}.')
- .addText((text) => text
- .setPlaceholder('default: align*')
- .setValue(this.plugin.settings.addAlignBlock_parameter)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.addAlignBlock_parameter = value;
- yield this.plugin.saveData(this.plugin.settings);
- })));
- new obsidian.Setting(containerEl)
- .setName('【NEW!】Auto-align at these symbols')
- .setDesc('When within the align block, the align symbol "&" will be automatically added before these symbols. (separate by spaces)')
- .addText((text) => text
- .setValue(this.plugin.settings.autoAlignSymbols)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoAlignSymbols = value;
- if (value == "") {
- this.plugin.autoAlign_array = [];
- }
- else {
- this.plugin.autoAlign_array = value.split(" ");
- }
- yield this.plugin.saveData(this.plugin.settings);
- })));
- new obsidian.Setting(containerEl)
- .setName('Shortcut for Cases Block')
- .setDesc('Use shortcut key to quickly insert \\begin{cases} \\end{cases} block. ' +
- 'Default: "Alt+Shift+C" (Mac: "Option+Shift+C")')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.addCasesBlock_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.addCasesBlock_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Use shift-enter for line break in align and cases block')
- .setDesc('For align and cases block above, pressing enter automatically adds line break symbol "\\" or "&". Switch here to use shift-enter instead.')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.shiftEnter_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.shiftEnter_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Shortcut for Matrix Block')
- .setDesc('Use shortcut key to quickly insert \\begin{pmatrix} \\end{pmatrix} block. ' +
- 'Default: "Alt+Shift+M" (Mac: "Option+Shift+M")')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.addMatrixBlock_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.addMatrixBlock_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Matrix Block Parameter')
- .setDesc('Set the text parameter in \\begin{parameter} and \\end{parameter}.')
- .addText((text) => text
- .setPlaceholder('default: pmatrix')
- .setValue(this.plugin.settings.addMatrixBlock_parameter)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.addMatrixBlock_parameter = value;
- yield this.plugin.saveData(this.plugin.settings);
- })));
- new obsidian.Setting(containerEl)
- .setName('Greek symbols math mode')
- .setDesc('Automatically surround commands to insert Greek character written outside math mode with math chars. ' +
- 'Eg, typing \\alpha followed by space outside math mode will be replaced with "$\\alpha$"')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.autoGreekCommandMathMode_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.autoGreekCommandMathMode_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Custom Shorthand')
- .setDesc('Use custom shorthand (can be multiple letters) for common latex strings. ' +
- 'Eg, typing "al" followed by "space/tab" key will replace with "\\alpha"')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.customShorthand_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.customShorthand_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Use Tab to complete custom shorthand')
- .setDesc('Use Tab instead of space to complete custom shorthand.')
- .addToggle((toggle) => toggle
- .setValue(this.plugin.settings.useTabtoComplete_toggle)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.useTabtoComplete_toggle = value;
- yield this.plugin.saveData(this.plugin.settings);
- this.display();
- })));
- new obsidian.Setting(containerEl)
- .setName('Custom Shorthand Parameter')
- .setDesc('Separate the multi-letters shorthand and the snippet with ":::" and ' +
- 'end each set of shorthand snippet pair by "---" and a newline. ' +
- 'For expressions that end with "{}", the cursor will automatically be placed within the bracket. ' +
- 'Alternatively, you can type "#cursor" within the snippet to set the cursor location after replacement. ' +
- 'You can also include "#tab" within the snippet for use cases such as multiple {}s (e.g. \\binom{#cursor}{#tab}). ' +
- 'Pressing tab key in such cases will jump the cursor to the next "#tab" keyword. ' +
- 'Numbers after each "#tab" can be added to define the order in which to jump between the tabs (e.g. \\left#cursor #tab2 \\right#tab1 will first jump to #tab1 then back to #tab2). ' +
- 'Shorthands now support multiline snippets too! ' +
- '(try uninstall then reinstalling the plugin to see the new set of shorthands.) ' +
- '【NOTE】For old users, please kindly replace ":" with ":::" in your custom shorthand parameter.')
- .setClass("text-snippets-class")
- .addTextArea((text) => text
- .setValue(this.plugin.settings.customShorthand_parameter)
- .onChange((value) => __awaiter(this, void 0, void 0, function* () {
- this.plugin.settings.customShorthand_parameter = value;
- while (value.slice(-2) == "\n") {
- value = value.slice(0, -1);
- }
- if (value.slice(-1) == ";") {
- value = value.slice(0, -1);
- }
- if (value.lastIndexOf(";\n") == -1) {
- this.plugin.shorthand_array = value.split(",").map(item => item.split(":"));
- }
- else if (value.lastIndexOf(":::") == -1) {
- this.plugin.shorthand_array = value.split(";\n").map(item => item.split(":"));
- }
- else {
- this.plugin.shorthand_array = value.split(";\n").map(item => item.split(":::"));
- }
- yield this.plugin.saveData(this.plugin.settings);
- })));
- }
- ;
+const DEFAULT_SETTINGS = {
+ useMathKeyboardShortcut_toggle: false,
+ moveIntoMath_toggle: true,
+ autoCloseMath_toggle: true,
+ autoCloseRound_toggle: true,
+ autoCloseSquare_toggle: true,
+ autoCloseCurly_toggle: true,
+ addAlignBlock_toggle: true,
+ addAlignBlock_parameter: "align*",
+ autoAlignSymbols: "= > < \\le \\ge \\neq \\approx",
+ addCasesBlock_toggle: true,
+ shiftEnter_toggle: false,
+ addMatrixBlock_toggle: true,
+ addMatrixBlock_parameter: "pmatrix",
+ autoFraction_toggle: true,
+ autoLargeBracket_toggle: true,
+ autoSumLimit_toggle: true,
+ autoEncloseSup_toggle: true,
+ autoEncloseSub_toggle: true,
+ encloseSelection_toggle: true,
+ autoGreekCommandMathMode_toggle: true,
+ customShorthand_toggle: true,
+ useTabtoComplete_toggle: false,
+ customShorthand_parameter: "bi:::\\binom{#cursor}{#tab};\nsq:::\\sqrt{};\nbb:::\\mathbb{};\nbf:::\\mathbf{};\nte:::\\text{};\ninf:::\\infty;\n" +
+ "cd:::\\cdot;\nqu:::\\quad;\nti:::\\times;\n" +
+ "al:::\\alpha;\nbe:::\\beta;\nga:::\\gamma;\nGa:::\\Gamma;\n" +
+ "de:::\\delta;\nDe:::\\Delta;\nep:::\\epsilon;\nze:::\\zeta;\n" +
+ "et:::\\eta;\nth:::\\theta;\nTh:::\\Theta;\nio:::\\iota;\n" +
+ "ka:::\\kappa;\nla:::\\lambda;\nLa:::\\Lambda;\nmu:::\\mu;\n" +
+ "nu:::\\nu;\nxi:::\\xi;\nXi:::\\Xi;\npi:::\\pi;\nPi:::\\Pi;\n" +
+ "rh:::\\rho;\nsi:::\\sigma;\nSi:::\\Sigma;\nta:::\\tau;\n" +
+ "up:::\\upsilon;\nUp:::\\Upsilon;\nph:::\\phi;\nPh:::\\Phi;\nch:::\\chi;\n" +
+ "ps:::\\psi;\nPs:::\\Psi;\nom:::\\omega;\nOm:::\\Omega"
+};
+class QuickLatexPlugin extends obsidian.Plugin {
+ constructor() {
+ super(...arguments);
+ this.vimAllow_autoCloseMath = true;
+ this.makeExtensionThing = () => state.Prec.high(view.keymap.of([
+ {
+ key: '$',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (editor.getSelection().length > 0) {
+ // enclose selected text
+ if (this.settings.encloseSelection_toggle) {
+ const anchor = editor.getCursor("anchor");
+ const head = editor.getCursor("head");
+ editor.replaceSelection(`$${editor.getSelection()}$`);
+ if (anchor.line > head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 1 });
+ }
+ else if (anchor.line < head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch });
+ }
+ else {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch + 1 });
+ }
+ return true;
+ }
+ return false;
+ }
+ else {
+ // close math symbol
+ const position = editor.getCursor();
+ const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const next2_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ if (prev_char != "$" && next_char == "$") {
+ if (next2_char == "$$") {
+ editor.setCursor({ line: position.line, ch: position.ch + 2 });
+ return true;
+ }
+ else {
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ }
+ // auto close math
+ if (this.settings.autoCloseMath_toggle && this.vimAllow_autoCloseMath) {
+ const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ const line = editor.getLine(position.line);
+ const count = (line.match(/\$/g) || []).length;
+ if (prev_char != "\\" && count % 2 == 0) {
+ editor.replaceSelection("$");
+ }
+ }
+ // move into math
+ if (this.settings.moveIntoMath_toggle) {
+ const position = editor.getCursor();
+ const t = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ const t2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const t_2 = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
+ if (t == '$' && t2 != '$') {
+ editor.setCursor({ line: position.line, ch: position.ch - 1 });
+ }
+ else if (t_2 == '$$') {
+ editor.setCursor({ line: position.line, ch: position.ch - 1 });
+ }
+ }
+ return false;
+ }
+ },
+ },
+ // delete pair of math symbols with backspace
+ { key: 'Backspace',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ const position = editor.getCursor();
+ const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ if (prev_char == "$" && next_char == "$") {
+ editor.replaceRange("", { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ return false;
+ }
+ },
+ {
+ key: 'Tab',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ const end_pos = editor.getLine(position.line).length;
+ const next_line = editor.getLine(position.line + 1);
+ // check for custom shorthand
+ if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
+ if (this.settings.useTabtoComplete_toggle) {
+ if (this.customShorthand(editor, position)) {
+ return true;
+ }
+ }
+ }
+ // Tab to go to next #tab with numbering or without numbering if there are no #tabs with numbers
+ const indexed_tab_expr = /#tab(\d+)?/g;
+ let next_match;
+ let current_match;
+ while ((current_match = indexed_tab_expr.exec(current_line)) != null) {
+ if (!next_match || parseInt(current_match[1]) < parseInt(next_match[1]))
+ next_match = current_match;
+ }
+ if (next_match) {
+ const tab_position = next_match.index;
+ editor.replaceRange("", { line: position.line, ch: tab_position }, { line: position.line, ch: tab_position + next_match[0].length });
+ editor.setCursor({ line: position.line, ch: tab_position });
+ return true;
+ }
+ // Tab shortcut for matrix block
+ if (this.settings.addMatrixBlock_toggle) {
+ const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter + '}', "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
+ const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter + '}', "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
+ let state = false;
+ let end_text = "";
+ for (let i = 0; i < begin_matrix.length; i++) {
+ if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
+ state = true;
+ end_text = end_matrix[i];
+ break;
+ }
+ }
+ const position = editor.getCursor();
+ const prev3_char = editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
+ if (state) {
+ if (prev3_char == ' & ') {
+ editor.replaceRange('', { line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
+ editor.setCursor({ line: position.line, ch: position.ch + end_text.length - 3 });
+ return true;
+ }
+ else {
+ editor.replaceSelection(' & ');
+ return true;
+ }
+ }
+ }
+ // Tab shortcut for cases block
+ if (this.settings.addCasesBlock_toggle) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
+ const position = editor.getCursor();
+ const prev3_char = editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
+ const next_line = editor.getLine(position.line + 1);
+ if (prev3_char == ' & ' && next_line == '\\end{cases}') {
+ editor.replaceRange('', { line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch });
+ editor.setCursor({ line: position.line + 1, ch: next_line.length });
+ return true;
+ }
+ else {
+ editor.replaceSelection(' & ');
+ return true;
+ }
+ }
+ }
+ // Tab out of $
+ const next_2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ if (next_2 == "$$") {
+ editor.setCursor({ line: position.line, ch: position.ch + 2 });
+ return true;
+ }
+ else if (position.ch == end_pos && next_line == "$$") {
+ editor.setCursor({ line: position.line + 1, ch: next_line.length });
+ return true;
+ }
+ else if (next_2[0] == "$") {
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ // Tab to next close bracket
+ const following_text = editor.getRange({ line: position.line, ch: position.ch + 1 }, { line: position.line, ch: current_line.length });
+ const close_symbols = ['}', ']', ')', '$'];
+ for (let i = 0; i < following_text.length; i++) {
+ if (close_symbols.contains(following_text[i])) {
+ editor.setCursor({ line: position.line, ch: position.ch + i + 1 });
+ return true;
+ }
+ }
+ // Tab out of align block
+ if (position.ch == end_pos && next_line == '\\end{' + this.settings.addAlignBlock_parameter + '}') {
+ editor.setCursor({ line: position.line + 1, ch: next_line.length });
+ return true;
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: 'Shift-Tab',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const preceding_text = editor.getRange({ line: position.line, ch: 0 }, { line: position.line, ch: position.ch });
+ const close_symbols = ['}', ']', ')'];
+ for (let i = preceding_text.length; i >= 0; i--) {
+ if (close_symbols.contains(preceding_text[i])) {
+ editor.setCursor({ line: position.line, ch: i });
+ return true;
+ }
+ else if (position.ch - i > 1 && preceding_text[i] == "$") {
+ editor.setCursor({ line: position.line, ch: i + 1 });
+ return true;
+ }
+ else if (preceding_text.slice(-2) == "$$") {
+ editor.setCursor({ line: position.line, ch: position.ch - 2 });
+ return true;
+ }
+ else if (preceding_text[-1] == "$") {
+ editor.setCursor({ line: position.line, ch: position.ch - 1 });
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: 'Space',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (!this.settings.autoFraction_toggle &&
+ !this.settings.autoLargeBracket_toggle &&
+ !this.settings.autoEncloseSup_toggle &&
+ !this.settings.autoEncloseSub_toggle &&
+ !this.settings.customShorthand_toggle)
+ return false;
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ const last_dollar = current_line.lastIndexOf('$', position.ch - 1);
+ // check for custom shorthand
+ if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
+ if (!this.settings.useTabtoComplete_toggle) {
+ if (this.customShorthand(editor, position)) {
+ return true;
+ }
+ }
+ }
+ // find last unbracketed subscript within last 10 characters and perform autoEncloseSub
+ // ignore expression that contain + - * / ^
+ const last_math = current_line.lastIndexOf('$', position.ch - 1);
+ if (this.settings.autoEncloseSub_toggle) {
+ let last_subscript = current_line.lastIndexOf('_', position.ch);
+ if (last_subscript != -1 && last_subscript > last_math) {
+ const letter_after_subscript = editor.getRange({ line: position.line, ch: last_subscript + 1 }, { line: position.line, ch: last_subscript + 2 });
+ if (letter_after_subscript != "{" &&
+ (position.ch - last_subscript) <= 10) {
+ editor.replaceSelection("}");
+ editor.replaceRange("{", { line: position.line, ch: last_subscript + 1 });
+ return true;
+ }
+ }
+ }
+ // retrieve the last unbracketed superscript
+ let last_superscript = current_line.lastIndexOf('^', position.ch);
+ while (last_superscript != -1) {
+ const two_letters_after_superscript = editor.getRange({ line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 3 });
+ if (two_letters_after_superscript[0] == '{' || two_letters_after_superscript == ' {') {
+ last_superscript = current_line.lastIndexOf('^', last_superscript - 1);
+ }
+ else if (last_superscript < last_math) {
+ last_superscript = -1;
+ break;
+ }
+ else {
+ break;
+ }
+ }
+ // retrieve the last divide symbol
+ let last_divide = current_line.lastIndexOf('/', position.ch - 2);
+ while (last_divide != -1) {
+ const around_divide = editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide + 2 });
+ if (around_divide[0] == ' ' && around_divide[2] == ' ') {
+ last_divide = current_line.lastIndexOf('^', last_divide - 1);
+ }
+ else if (last_divide < last_math) {
+ last_divide = -1;
+ break;
+ }
+ else {
+ break;
+ }
+ }
+ // perform autoEncloseSup
+ if (this.settings.autoEncloseSup_toggle) {
+ if (last_superscript > last_divide) {
+ // if any brackets from last sup to cursor still unclosed, dont do autoEncloseSup yet
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_superscript)[0])) {
+ return this.autoEncloseSup(editor, event, last_superscript);
+ }
+ }
+ }
+ // perform autoFraction
+ if (this.settings.autoFraction_toggle && !this.withinText(editor, last_divide)) {
+ if (last_divide > last_dollar) {
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ // if any brackets in denominator still unclosed, dont do autoFraction yet
+ if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_divide)[0])) {
+ return this.autoFractionCM6(editor, last_superscript);
+ }
+ }
+ }
+ // perform autoLargeBracket
+ if (this.settings.autoLargeBracket_toggle) {
+ let symbol_before = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ if (symbol_before == ')' || symbol_before == ']') {
+ return this.autoLargeBracket(editor, event);
+ }
+ }
+ // perform autoAlign
+ if (this.autoAlign_array.length) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
+ let keyword = "";
+ let keyword_length = 0;
+ for (let i = 0; i < this.autoAlign_array.length; i++) {
+ keyword_length = this.autoAlign_array[i].length;
+ if (keyword_length > position.ch) {
+ continue;
+ }
+ else {
+ keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
+ }
+ if (keyword == this.autoAlign_array[i]) {
+ editor.replaceRange('&', { line: position.line, ch: position.ch - keyword_length });
+ return false;
+ }
+ }
+ }
+ }
+ }
+ else if (this.settings.autoGreekCommandMathMode_toggle) {
+ const greekSymbols = ['alpha', 'Alpha', 'beta', 'gamma', 'Gamma', 'delta', 'Delta', 'epsilon', 'zeta', 'eta', 'theta', 'Theta', 'iota', 'kappa', 'lambda', 'Lambda', 'mu', 'nu', 'xi', 'Xi', 'omicron', 'pi', 'Pi', 'rho', 'sigma', 'Sigma', 'tau', 'upsilon', 'Upsilon', 'phi', 'Phi', 'chi', 'psi', 'Psi', 'omega', 'Omega', 'varepsilon', 'vartheta', 'varrho', 'varphi'];
+ const greekSymbolsSlashed = greekSymbols.map(x => '\\' + x);
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ const last_slash = current_line.lastIndexOf('\\', position.ch - 1);
+ if (last_slash != -1) {
+ const entered = current_line.substring(last_slash, position.ch);
+ if (greekSymbolsSlashed.contains(entered))
+ editor.replaceRange('$' + entered + '$', { line: position.line, ch: position.ch - entered.length }, { line: position.line, ch: position.ch });
+ }
+ }
+ },
+ },
+ {
+ key: 'Shift-Space',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (!this.settings.customShorthand_toggle)
+ return false;
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ // check for custom shorthand
+ if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
+ let keyword = "";
+ let keyword_length = 0;
+ for (let i = 0; i < this.shorthand_array.length; i++) {
+ keyword_length = this.shorthand_array[i][0].length;
+ if (keyword_length > position.ch) {
+ continue;
+ }
+ else if (keyword_length == position.ch) {
+ keyword = "@" + editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
+ }
+ else {
+ keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length - 1 }, { line: position.line, ch: position.ch });
+ }
+ if (keyword[0].toLowerCase() == keyword[0].toUpperCase() ||
+ keyword[0] == "@") {
+ if (this.shorthand_array[i][0] == keyword.slice(-keyword_length) &&
+ this.shorthand_array[i][1] != keyword) {
+ const replace_slash = (keyword[0] == "\\" && this.shorthand_array[i][1][0] == "\\") ? 1 : 0;
+ const set_cursor_position = this.shorthand_array[i][1].indexOf("#cursor");
+ editor.replaceRange(this.shorthand_array[i][1], { line: position.line, ch: position.ch - keyword_length - replace_slash }, { line: position.line, ch: position.ch });
+ if (set_cursor_position != -1) {
+ editor.replaceRange("", { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position }, { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position + 7 });
+ editor.setCursor({ line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position });
+ }
+ else if (this.shorthand_array[i][1].slice(-2) == "{}") {
+ editor.setCursor({ line: position.line,
+ ch: position.ch + this.shorthand_array[i][1].length - keyword_length - 1 - replace_slash });
+ }
+ else ;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ {
+ key: 'Enter',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.settings.addAlignBlock_toggle && this.settings.shiftEnter_toggle == false) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
+ editor.replaceSelection('\\\\\n');
+ return true;
+ }
+ }
+ if (this.settings.addCasesBlock_toggle && this.settings.shiftEnter_toggle == false) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
+ editor.replaceSelection(' \\\\\n');
+ return true;
+ }
+ }
+ if (this.settings.addMatrixBlock_toggle) {
+ const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter + '}', "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
+ const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter + '}', "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
+ let state = false;
+ for (let i = 0; i < begin_matrix.length; i++) {
+ if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
+ state = true;
+ break;
+ }
+ }
+ if (state) {
+ editor.replaceSelection(' \\\\ ');
+ return true;
+ }
+ }
+ // double enter for $$
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const prev2_Char = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
+ const next2_Char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ if (prev2_Char == "$$" && next2_Char == "$$") {
+ editor.replaceSelection('\n');
+ editor.setCursor(position);
+ return false;
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: 'Shift-Enter',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.settings.addAlignBlock_toggle && this.settings.shiftEnter_toggle == true) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
+ editor.replaceSelection('\\\\\n');
+ return true;
+ }
+ }
+ if (this.settings.addCasesBlock_toggle && this.settings.shiftEnter_toggle == true) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
+ editor.replaceSelection(' \\\\\n');
+ return true;
+ }
+ }
+ return false;
+ }
+ },
+ {
+ key: '{',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ if (this.settings.autoCloseCurly_toggle) {
+ if (editor.getSelection().length > 0) {
+ return false;
+ }
+ const position = editor.getCursor();
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
+ if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
+ editor.replaceSelection('{}');
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: '[',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ if (this.settings.autoCloseSquare_toggle) {
+ if (editor.getSelection().length > 0) {
+ return false;
+ }
+ const position = editor.getCursor();
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
+ if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
+ editor.replaceSelection('[]');
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: '(',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ if (this.settings.autoCloseRound_toggle) {
+ if (editor.getSelection().length > 0) {
+ return false;
+ }
+ const position = editor.getCursor();
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
+ if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
+ editor.replaceSelection('()');
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: '}',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ if (this.settings.autoCloseCurly_toggle) {
+ const position = editor.getCursor();
+ const end = editor.getLine(position.line).length;
+ const next_sym = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ if (!this.unclosed_bracket(editor, "{", "}", end, 0)[0] &&
+ !this.unclosed_bracket(editor, "{", "}", end, 0, false)[0] &&
+ next_sym == "}") {
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: ']',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ if (this.settings.autoCloseSquare_toggle) {
+ const position = editor.getCursor();
+ const end = editor.getLine(position.line).length;
+ const next_sym = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ if (!this.unclosed_bracket(editor, "[", "]", end, 0)[0] &&
+ !this.unclosed_bracket(editor, "[", "]", end, 0, false)[0] &&
+ next_sym == "]") {
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: ')',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ if (this.settings.autoCloseRound_toggle) {
+ const position = editor.getCursor();
+ const end = editor.getLine(position.line).length;
+ const next_sym = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ if (!this.unclosed_bracket(editor, "(", ")", end, 0)[0] &&
+ !this.unclosed_bracket(editor, "(", ")", end, 0, false)[0] &&
+ next_sym == ")") {
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ return false;
+ },
+ },
+ {
+ key: 'm',
+ run: () => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ const editor = view.editor;
+ if (!this.withinMath(editor))
+ return false;
+ const position = editor.getCursor();
+ if (!this.settings.autoSumLimit_toggle)
+ return;
+ if (this.withinMath(editor)) {
+ if (editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch }) == '\\su') {
+ editor.replaceSelection('m\\limits');
+ return true;
+ }
+ }
+ return false;
+ },
+ },
+ ]));
+ this.handleVimModeChange = (modeObj) => {
+ if (!modeObj || modeObj.mode === 'insert')
+ this.vimAllow_autoCloseMath = true;
+ else
+ this.vimAllow_autoCloseMath = false;
+ };
+ this.handleKeyDown = (cm, event) => {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return;
+ const editor = view.editor;
+ if (['$', ' ', 'Enter', 'Tab'].contains(event.key)) {
+ switch (event.key) {
+ case '$':
+ if (editor.getSelection().length > 0) {
+ if (this.settings.encloseSelection_toggle) {
+ const anchor = editor.getCursor("anchor");
+ const head = editor.getCursor("head");
+ editor.replaceSelection('$' + editor.getSelection() + '$');
+ if (anchor.line > head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 1 });
+ }
+ else if (anchor.line < head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch });
+ }
+ else {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch + 1 });
+ }
+ event.preventDefault();
+ return;
+ }
+ }
+ else {
+ // close math symbol
+ const position = editor.getCursor();
+ const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const next2_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ if (prev_char != "$" && next_char == "$") {
+ if (next2_char == "$$") {
+ editor.setCursor({ line: position.line, ch: position.ch + 2 });
+ event.preventDefault();
+ return;
+ }
+ else {
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ // perform autoCloseMath
+ if (this.settings.autoCloseMath_toggle && this.vimAllow_autoCloseMath) {
+ editor.replaceSelection("$");
+ }
+ // perform moveIntoMath
+ if (this.settings.moveIntoMath_toggle) {
+ const position = editor.getCursor();
+ const t = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ const t2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const t_2 = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
+ if (t == '$' && t2 != '$') {
+ editor.setCursor({ line: position.line, ch: position.ch - 1 });
+ }
+ else if (t_2 == '$$') {
+ editor.setCursor({ line: position.line, ch: position.ch - 1 });
+ }
+ }
+ }
+ return;
+ case ' ':
+ if (!this.settings.autoFraction_toggle &&
+ !this.settings.autoLargeBracket_toggle &&
+ !this.settings.autoEncloseSup_toggle &&
+ !this.settings.autoEncloseSub_toggle &&
+ !this.settings.customShorthand_toggle)
+ return;
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ const last_dollar = current_line.lastIndexOf('$', position.ch - 1);
+ // check for custom shorthand
+ if (this.settings.customShorthand_toggle && !this.withinText(editor, position.ch)) {
+ let keyword = "";
+ let keyword_length = 0;
+ for (let i = 0; i < this.shorthand_array.length; i++) {
+ keyword_length = this.shorthand_array[i][0].length;
+ if (keyword_length > position.ch) {
+ continue;
+ }
+ else if (keyword_length == position.ch) {
+ keyword = "@" + editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
+ }
+ else {
+ keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length - 1 }, { line: position.line, ch: position.ch });
+ }
+ if (keyword[0].toLowerCase() == keyword[0].toUpperCase() ||
+ keyword[0] == "@") {
+ if (this.shorthand_array[i][0] == keyword.slice(-keyword_length) &&
+ this.shorthand_array[i][1] != keyword) {
+ const replace_slash = (keyword[0] == "\\" && this.shorthand_array[i][1][0] == "\\") ? 1 : 0;
+ const set_cursor_position = this.shorthand_array[i][1].indexOf("#cursor");
+ editor.replaceRange(this.shorthand_array[i][1], { line: position.line, ch: position.ch - keyword_length - replace_slash }, { line: position.line, ch: position.ch });
+ if (set_cursor_position != -1) {
+ editor.replaceRange("", { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position }, { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position + 7 });
+ editor.setCursor({ line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position });
+ }
+ else if (this.shorthand_array[i][1].slice(-2) == "{}") {
+ editor.setCursor({ line: position.line,
+ ch: position.ch + this.shorthand_array[i][1].length - keyword_length - 1 - replace_slash });
+ }
+ else ;
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ }
+ // find last unbracketed subscript within last 10 characters and perform autoEncloseSub
+ // ignore expression that contain + - * / ^
+ const last_math = current_line.lastIndexOf('$', position.ch - 1);
+ if (this.settings.autoEncloseSub_toggle) {
+ let last_subscript = current_line.lastIndexOf('_', position.ch);
+ if (last_subscript != -1 && last_subscript > last_math) {
+ const letter_after_subscript = editor.getRange({ line: position.line, ch: last_subscript + 1 }, { line: position.line, ch: last_subscript + 2 });
+ if (letter_after_subscript != "{" &&
+ (position.ch - last_subscript) <= 10) {
+ editor.replaceRange("}", position);
+ editor.replaceRange("{", { line: position.line, ch: last_subscript + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ // retrieve the last unbracketed superscript
+ let last_superscript = current_line.lastIndexOf('^', position.ch);
+ while (last_superscript != -1) {
+ const two_letters_after_superscript = editor.getRange({ line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 3 });
+ if (two_letters_after_superscript[0] == '{' || two_letters_after_superscript == ' {') {
+ last_superscript = current_line.lastIndexOf('^', last_superscript - 1);
+ }
+ else if (last_superscript < last_math) {
+ last_superscript = -1;
+ break;
+ }
+ else {
+ break;
+ }
+ }
+ // retrieve the last divide symbol
+ let last_divide = current_line.lastIndexOf('/', position.ch - 2);
+ while (last_divide != -1) {
+ const around_divide = editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide + 2 });
+ if (around_divide[0] == ' ' && around_divide[2] == ' ') {
+ last_divide = current_line.lastIndexOf('^', last_divide - 1);
+ }
+ else if (last_divide < last_math) {
+ last_divide = -1;
+ break;
+ }
+ else {
+ break;
+ }
+ }
+ // perform autoEncloseSup
+ if (this.settings.autoEncloseSup_toggle) {
+ if (last_superscript > last_divide) {
+ // if any brackets from last sup to cursor still unclosed, dont do autoEncloseSup yet
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_superscript)[0])) {
+ this.autoEncloseSup(editor, event, last_superscript);
+ return;
+ }
+ }
+ }
+ // perform autoFraction
+ if (this.settings.autoFraction_toggle && !this.withinText(editor, last_divide)) {
+ if (last_divide > last_dollar) {
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ // if any brackets in denominator still unclosed, dont do autoFraction yet
+ if (!brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, last_divide)[0])) {
+ this.autoFraction(editor, event, last_superscript);
+ return;
+ }
+ }
+ }
+ // perform autoLargeBracket
+ if (this.settings.autoLargeBracket_toggle) {
+ let symbol_before = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ if (symbol_before == ')' || symbol_before == ']') {
+ this.autoLargeBracket(editor, event);
+ return;
+ }
+ }
+ }
+ break;
+ case 'Enter':
+ // perform Enter shortcut within matrix block
+ if (this.settings.addMatrixBlock_toggle) {
+ const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter, "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
+ const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter, "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
+ let state = false;
+ for (let i = 0; i < begin_matrix.length; i++) {
+ if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
+ state = true;
+ break;
+ }
+ }
+ if (!event.shiftKey) {
+ if (state) {
+ editor.replaceSelection(' \\\\ ');
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ // perform Enter shortcut within align block
+ if (this.settings.addAlignBlock_toggle) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{' + this.settings.addAlignBlock_parameter, '\\end{' + this.settings.addAlignBlock_parameter)) {
+ if (!event.shiftKey) {
+ editor.replaceSelection('\\\\\n&');
+ event.preventDefault();
+ }
+ return;
+ }
+ }
+ // enter for cases block
+ if (this.settings.addCasesBlock_toggle) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
+ editor.replaceSelection(' \\\\\n');
+ event.preventDefault();
+ return;
+ }
+ }
+ // double enter for $$
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const prev2_Char = editor.getRange({ line: position.line, ch: position.ch - 2 }, { line: position.line, ch: position.ch });
+ const next2_Char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ if (prev2_Char == "$$" && next2_Char == "$$") {
+ editor.replaceSelection('\n');
+ editor.setCursor(position);
+ }
+ }
+ return;
+ case 'Tab':
+ // perform Tab shortcut within matrix block
+ if (this.settings.addMatrixBlock_toggle) {
+ const begin_matrix = ['\\begin{' + this.settings.addMatrixBlock_parameter, "\\begin{matrix}", "\\begin{bmatrix}", "\\begin{Bmatrix}", "\\begin{vmatrix}", "\\begin{Vmatrix}", "\\begin{smallmatrix}"];
+ const end_matrix = ['\\end{' + this.settings.addMatrixBlock_parameter, "\\end{matrix}", "\\end{bmatrix}", "\\end{Bmatrix}", "\\end{vmatrix}", "\\end{Vmatrix}", "\\end{smallmatrix}"];
+ let state = false;
+ for (let i = 0; i < begin_matrix.length; i++) {
+ if (this.withinAnyBrackets_document(editor, begin_matrix[i], end_matrix[i])) {
+ state = true;
+ break;
+ }
+ }
+ if (state) {
+ editor.replaceSelection(' & ');
+ event.preventDefault();
+ return;
+ }
+ }
+ // Tab shortcut for cases block
+ if (this.settings.addCasesBlock_toggle) {
+ if (this.withinAnyBrackets_document(editor, '\\begin{cases}', '\\end{cases}')) {
+ editor.replaceSelection(' & ');
+ event.preventDefault();
+ return;
+ }
+ }
+ // Tab to go to next #tab with numbering or without numbering if there are no #tabs with numbers
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ const indexed_tab_expr = /#tab(\d+)?/g;
+ let next_match;
+ let current_match;
+ while ((current_match = indexed_tab_expr.exec(current_line)) != null) {
+ if (!next_match || parseInt(current_match[1]) < parseInt(next_match[1]))
+ next_match = current_match;
+ }
+ if (next_match) {
+ const tab_position = next_match.index;
+ editor.replaceRange("", { line: position.line, ch: tab_position }, { line: position.line, ch: tab_position + next_match[0].length });
+ editor.setCursor({ line: position.line, ch: tab_position });
+ event.preventDefault();
+ return;
+ }
+ // Tab to next close bracket
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ if (event.shiftKey) {
+ const close_symbols = ['}', ']', ')'];
+ const preceding_text = editor.getRange({ line: position.line, ch: 0 }, { line: position.line, ch: position.ch });
+ for (let i = preceding_text.length; i >= 0; i--) {
+ if (close_symbols.contains(preceding_text[i])) {
+ editor.setCursor({ line: position.line, ch: i });
+ event.preventDefault();
+ return;
+ }
+ else if (position.ch - i > 1 && preceding_text[i] == "$") {
+ editor.setCursor({ line: position.line, ch: i + 1 });
+ event.preventDefault();
+ return;
+ }
+ else if (preceding_text.slice(-2) == "$$") {
+ editor.setCursor({ line: position.line, ch: position.ch - 2 });
+ event.preventDefault();
+ return;
+ }
+ else if (preceding_text[-1] == "$") {
+ editor.setCursor({ line: position.line, ch: position.ch - 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ else {
+ const close_symbols = ['}', ']', ')', '$'];
+ const following_text = editor.getRange({ line: position.line, ch: position.ch + 1 }, { line: position.line, ch: current_line.length });
+ for (let i = 0; i < following_text.length; i++) {
+ if (close_symbols.contains(following_text[i])) {
+ editor.setCursor({ line: position.line, ch: position.ch + i + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ }
+ // Tab out of $
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const next_2 = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ if (next_2 == "$$") {
+ editor.setCursor({ line: position.line, ch: position.ch + 2 });
+ event.preventDefault();
+ return;
+ }
+ else if (next_2[0] == "$") {
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ }
+ };
+ this.handleKeyPress = (cm, event) => {
+ if (['{', '[', '(', 'm'].contains(event.key)) {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return;
+ const editor = view.editor;
+ if (this.withinMath(editor)) {
+ const position = editor.getCursor();
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ const next_char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 1 });
+ const next_2char = editor.getRange({ line: position.line, ch: position.ch }, { line: position.line, ch: position.ch + 2 });
+ const followed_by_$spacetabnonedoubleslash = (['$', ' ', ' ', ''].contains(next_char) || next_2char == '\\\\');
+ switch (event.key) {
+ case '{':
+ if (this.settings.autoCloseCurly_toggle) {
+ if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
+ editor.replaceSelection('{}');
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ return;
+ case '[':
+ if (this.settings.autoCloseSquare_toggle) {
+ if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
+ editor.replaceSelection('[]');
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ return;
+ case '(':
+ if (this.settings.autoCloseRound_toggle) {
+ if (!this.withinAnyBrackets_inline(editor, brackets) && followed_by_$spacetabnonedoubleslash) {
+ editor.replaceSelection('()');
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ return;
+ case 'm':
+ if (!this.settings.autoSumLimit_toggle)
+ return;
+ if (editor.getRange({ line: position.line, ch: position.ch - 3 }, { line: position.line, ch: position.ch }) == '\\su') {
+ editor.replaceSelection('m\\limits');
+ event.preventDefault();
+ return;
+ }
+ }
+ }
+ }
+ };
+ //main functions
+ this.customShorthand = (editor, position) => {
+ let keyword = "";
+ let keyword_length = 0;
+ for (let i = 0; i < this.shorthand_array.length; i++) {
+ keyword_length = this.shorthand_array[i][0].length;
+ if (keyword_length > position.ch) {
+ continue;
+ }
+ else if (keyword_length == position.ch) {
+ keyword = "@" + editor.getRange({ line: position.line, ch: position.ch - keyword_length }, { line: position.line, ch: position.ch });
+ }
+ else {
+ keyword = editor.getRange({ line: position.line, ch: position.ch - keyword_length - 1 }, { line: position.line, ch: position.ch });
+ }
+ if (keyword[0].toLowerCase() == keyword[0].toUpperCase() ||
+ keyword[0] == "@") {
+ if (this.shorthand_array[i][0] == keyword.slice(-keyword_length) &&
+ this.shorthand_array[i][1] != keyword) {
+ const replace_slash = (keyword[0] == "\\" && this.shorthand_array[i][1][0] == "\\") ? 1 : 0;
+ const set_cursor_position = this.shorthand_array[i][1].indexOf("#cursor");
+ editor.replaceRange(this.shorthand_array[i][1], { line: position.line, ch: position.ch - keyword_length - replace_slash }, { line: position.line, ch: position.ch });
+ if (set_cursor_position != -1) {
+ editor.replaceRange("", { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position }, { line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position + 7 });
+ editor.setCursor({ line: position.line, ch: position.ch - keyword_length - replace_slash + set_cursor_position });
+ }
+ else if (this.shorthand_array[i][1].slice(-2) == "{}") {
+ editor.setCursor({ line: position.line,
+ ch: position.ch + this.shorthand_array[i][1].length - keyword_length - 1 - replace_slash });
+ }
+ else ;
+ return true;
+ }
+ }
+ }
+ };
+ this.autoEncloseSup = (editor, event, last_superscript) => {
+ // superscript bracketing
+ const position = editor.getCursor();
+ const letter_before_cursor = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ if (last_superscript != -1 && letter_before_cursor != "^") {
+ const letter_after_superscript = editor.getRange({ line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 2 });
+ if (letter_after_superscript == '(' && letter_before_cursor == ')' && position.ch - last_superscript > 6) {
+ editor.replaceRange('}', { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ editor.replaceRange('{', { line: position.line, ch: last_superscript + 1 }, { line: position.line, ch: last_superscript + 2 });
+ event.preventDefault();
+ return true;
+ }
+ else if (letter_after_superscript == ' ') {
+ editor.replaceSelection('}');
+ editor.replaceRange('{', { line: position.line, ch: last_superscript + 2 });
+ event.preventDefault();
+ return true;
+ }
+ else {
+ editor.replaceSelection('}');
+ editor.replaceRange('{', { line: position.line, ch: last_superscript + 1 });
+ event.preventDefault();
+ return true;
+ }
+ }
+ else {
+ return false;
+ }
+ };
+ this.autoFraction = (editor, event, last_superscript) => {
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ let last_divide = current_line.lastIndexOf('/', position.ch - 1);
+ // if cursor is preceeded by a close bracket, and the corresponding open bracket
+ // is found before "/", remove the brackets and enclose whole expression using \frac
+ const letter_before_cursor = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ // if there are any brackets unclosed before divide symbol,
+ // include the open brackets into stop_symbols
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ let stop_brackets = [];
+ for (let i = 0; i < brackets.length; i++) {
+ if (letter_before_cursor == brackets[i][1]) {
+ const open_brackets = this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], position.ch - 1, 0)[1];
+ const pos_of_the_open_bracket = open_brackets[open_brackets.length - 1];
+ if (pos_of_the_open_bracket < last_divide) {
+ editor.replaceRange('}', { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ editor.replaceRange('}{', { line: position.line, ch: last_divide }, { line: position.line, ch: last_divide + 1 });
+ editor.replaceRange('\\frac{', { line: position.line, ch: pos_of_the_open_bracket }, { line: position.line, ch: pos_of_the_open_bracket + 1 });
+ event.preventDefault();
+ return;
+ }
+ }
+ stop_brackets.push(...this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], last_divide, 0)[1]);
+ }
+ let frac = 0;
+ // if numerator is enclosed by (), place frac in front of () and remove ()
+ let numerator_remove_bracket = 0;
+ if (editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide }) == ')') {
+ const numerator_open_bracket = this.unclosed_bracket(editor, '(', ')', last_divide - 1, 0)[1].slice(-1)[0];
+ frac = numerator_open_bracket - 1;
+ numerator_remove_bracket = 1;
+ }
+ else {
+ const stop_symbols = ['$', '=', '>', '<', ',', '/', ' '];
+ const symbol_positions = stop_symbols.map(e => current_line.lastIndexOf(e, last_divide - 1));
+ frac = Math.max(last_superscript, ...symbol_positions, ...stop_brackets);
+ }
+ // if denominator is enclosed by (), remove ()
+ const denominator = editor.getRange({ line: position.line, ch: last_divide + 1 }, { line: position.line, ch: position.ch });
+ let denominator_remove_bracket = 0;
+ if (denominator.slice(-1)[0] == ')') {
+ const denominator_open_bracket = this.unclosed_bracket(editor, '(', ')', position.ch - 1, 0)[1].slice(-1)[0];
+ if (denominator_open_bracket == last_divide + 1) {
+ denominator_remove_bracket = 1;
+ }
+ }
+ // perform \frac replace
+ editor.replaceRange('}', { line: position.line, ch: position.ch - denominator_remove_bracket }, { line: position.line, ch: position.ch });
+ editor.replaceRange('}{', { line: position.line, ch: last_divide - numerator_remove_bracket }, { line: position.line, ch: last_divide + 1 + denominator_remove_bracket });
+ editor.replaceRange('\\frac{', { line: position.line, ch: frac + 1 }, { line: position.line, ch: frac + 1 + numerator_remove_bracket });
+ event.preventDefault();
+ return;
+ };
+ this.autoFractionCM6 = (editor, last_superscript) => {
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ let last_divide = current_line.lastIndexOf('/', position.ch - 1);
+ // if cursor is preceeded by a close bracket, and the corresponding open bracket
+ // is found before "/", remove the brackets and enclose whole expression using \frac
+ const letter_before_cursor = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ // if there are any brackets unclosed before divide symbol,
+ // include the open brackets into stop_symbols
+ const brackets = [['(', ')'], ['{', '}'], ['[', ']']];
+ let stop_brackets = [];
+ for (let i = 0; i < brackets.length; i++) {
+ if (letter_before_cursor == brackets[i][1]) {
+ const open_brackets = this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], position.ch - 1, 0)[1];
+ const pos_of_the_open_bracket = open_brackets[open_brackets.length - 1];
+ if (pos_of_the_open_bracket < last_divide) {
+ editor.replaceRange('}', { line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ editor.replaceRange('}{', { line: position.line, ch: last_divide }, { line: position.line, ch: last_divide + 1 });
+ editor.replaceRange('\\frac{', { line: position.line, ch: pos_of_the_open_bracket }, { line: position.line, ch: pos_of_the_open_bracket + 1 });
+ return true;
+ }
+ }
+ stop_brackets.push(...this.unclosed_bracket(editor, brackets[i][0], brackets[i][1], last_divide, 0)[1]);
+ }
+ let frac = 0;
+ // if numerator is enclosed by (), place frac in front of () and remove ()
+ let numerator_remove_bracket = 0;
+ if (editor.getRange({ line: position.line, ch: last_divide - 1 }, { line: position.line, ch: last_divide }) == ')') {
+ const numerator_open_bracket = this.unclosed_bracket(editor, '(', ')', last_divide - 1, 0)[1].slice(-1)[0];
+ frac = numerator_open_bracket - 1;
+ numerator_remove_bracket = 1;
+ }
+ else {
+ const stop_symbols = ['$', '=', '>', '<', ',', '/', ' '];
+ const symbol_positions = stop_symbols.map(e => current_line.lastIndexOf(e, last_divide - 1));
+ frac = Math.max(last_superscript, ...symbol_positions, ...stop_brackets);
+ }
+ // if denominator is enclosed by (), remove ()
+ const denominator = editor.getRange({ line: position.line, ch: last_divide + 1 }, { line: position.line, ch: position.ch });
+ let denominator_remove_bracket = 0;
+ if (denominator.slice(-1)[0] == ')') {
+ const denominator_open_bracket = this.unclosed_bracket(editor, '(', ')', position.ch - 1, 0)[1].slice(-1)[0];
+ if (denominator_open_bracket == last_divide + 1) {
+ denominator_remove_bracket = 1;
+ }
+ }
+ // perform \frac replace
+ editor.replaceRange('}', { line: position.line, ch: position.ch - denominator_remove_bracket }, { line: position.line, ch: position.ch });
+ editor.replaceRange('}{', { line: position.line, ch: last_divide - numerator_remove_bracket }, { line: position.line, ch: last_divide + 1 + denominator_remove_bracket });
+ editor.replaceRange('\\frac{', { line: position.line, ch: frac + 1 }, { line: position.line, ch: frac + 1 + numerator_remove_bracket });
+ const pos = editor.getCursor();
+ editor.setCursor({ line: pos.line, ch: pos.ch + 1 - denominator_remove_bracket });
+ return true;
+ };
+ this.autoLargeBracket = (editor, event) => {
+ const position = editor.getCursor();
+ let brackets = [['[', ']'], ['(', ')']];
+ const prev_char = editor.getRange({ line: position.line, ch: position.ch - 1 }, { line: position.line, ch: position.ch });
+ const current_brackets = brackets.filter(e => e[1] == prev_char)[0];
+ if (current_brackets.length == 0)
+ return;
+ const open_bracket = this.unclosed_bracket(editor, current_brackets[0], current_brackets[1], position.ch - 1, 0)[1].slice(-1)[0];
+ const text = editor.getRange({ line: position.line, ch: open_bracket }, { line: position.line, ch: position.ch });
+ const large_operators = ['\\sum', '\\int', '\\frac', '\\dfrac'];
+ let large_operators_locations = [];
+ for (let i = 0; i < large_operators.length; i++) {
+ let found = 0;
+ while (found != -1) {
+ found = text.indexOf(large_operators[i], found + 1);
+ if (found != -1) {
+ large_operators_locations.push(found + open_bracket);
+ }
+ }
+ }
+ const current_line = editor.getLine(position.line);
+ let retVal = false;
+ for (let i = 0; i < large_operators_locations.length; i++) {
+ let left_array = [];
+ let right_array = [];
+ for (let j = 0; j < brackets.length; j++) {
+ left_array.push(...this.unclosed_bracket(editor, brackets[j][0], brackets[j][1], large_operators_locations[i], 0)[1]);
+ right_array.push(...this.unclosed_bracket(editor, brackets[j][0], brackets[j][1], current_line.length, large_operators_locations[i], false)[1]);
+ }
+ for (let k = right_array.length - 1; k > -1; k--) {
+ // check if unclosed brackets already appended with \right
+ let check_right = editor.getRange({ line: position.line, ch: right_array[k] - 6 }, { line: position.line, ch: right_array[k] });
+ if (check_right != '\\right') {
+ editor.replaceRange('\\right', { line: position.line, ch: right_array[k] });
+ event.preventDefault();
+ retVal = true;
+ }
+ }
+ for (let l = left_array.length - 1; l > -1; l--) {
+ // check if unclosed brackets already appended with \left
+ let check_left = editor.getRange({ line: position.line, ch: left_array[l] - 5 }, { line: position.line, ch: left_array[l] });
+ if (check_left != '\\left') {
+ editor.replaceRange('\\left', { line: position.line, ch: left_array[l] });
+ event.preventDefault();
+ retVal = true;
+ }
+ }
+ }
+ return retVal;
+ };
+ //utility functions
+ this.unclosed_bracket = (editor, open_symbol, close_symbol, before, after, unclosed_open_symbol = true //false for unclosed_close_symbol
+ ) => {
+ // determine if there are unclosed bracket within the range specified by before and after
+ const position = editor.getCursor();
+ const text = editor.getRange({ line: position.line, ch: after }, { line: position.line, ch: before });
+ let open_array = [];
+ let close_array = [];
+ for (let i = 0; i < text.length; i++) {
+ switch (text[i]) {
+ case open_symbol:
+ open_array.push(after + i);
+ break;
+ case close_symbol:
+ if (open_array.length > 0) {
+ open_array.pop();
+ }
+ else {
+ close_array.push(after + i);
+ }
+ break;
+ }
+ }
+ if (unclosed_open_symbol) {
+ return [open_array.length > 0, open_array];
+ }
+ else {
+ return [close_array.length > 0, close_array];
+ }
+ };
+ this.withinText = (editor, at_where) => {
+ // check if within text{}
+ const position = editor.getCursor();
+ const bracket_locations = this.unclosed_bracket(editor, '{', '}', at_where, 0)[1];
+ return bracket_locations.some(loc => editor.getRange({ line: position.line, ch: loc - 4 }, { line: position.line, ch: loc }) == "text");
+ };
+ this.withinMath = (editor) => {
+ // check if cursor within $$
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ let cursor_index = position.ch;
+ let from = 0;
+ let found = current_line.indexOf('$', from);
+ while (found != -1 && found < cursor_index) {
+ let next_char = editor.getRange({ line: position.line, ch: found + 1 }, { line: position.line, ch: found + 2 });
+ let prev_char = editor.getRange({ line: position.line, ch: found - 1 }, { line: position.line, ch: found });
+ if (next_char == '$' || prev_char == '$' || next_char == ' ') {
+ from = found + 1;
+ found = current_line.indexOf('$', from);
+ continue;
+ }
+ else {
+ from = found + 1;
+ let next_found = current_line.indexOf('$', from);
+ if (next_found == -1) {
+ return false;
+ }
+ else if (cursor_index > found && cursor_index <= next_found) {
+ return true;
+ }
+ else {
+ from = next_found + 1;
+ found = current_line.indexOf('$', from);
+ continue;
+ }
+ }
+ }
+ const document_text = editor.getValue();
+ cursor_index = editor.posToOffset(position);
+ from = 0;
+ found = document_text.indexOf('$$', from);
+ let count = 0;
+ while (found != -1 && found < cursor_index) {
+ count += 1;
+ from = found + 2;
+ found = document_text.indexOf('$$', from);
+ }
+ return count % 2 == 1;
+ };
+ this.withinAnyBrackets_inline = (editor, brackets) => {
+ const position = editor.getCursor();
+ const current_line = editor.getLine(position.line);
+ return brackets.some(e => this.unclosed_bracket(editor, e[0], e[1], position.ch, 0)[0] &&
+ this.unclosed_bracket(editor, e[0], e[1], current_line.length, position.ch, false)[0]);
+ };
+ this.withinAnyBrackets_document = (editor, open_symbol, close_symbol) => {
+ const document_text = editor.getValue();
+ const cursorPos = editor.getCursor();
+ const cursor_index = editor.posToOffset(cursorPos);
+ // count open symbols
+ let from = 0;
+ let found = document_text.indexOf(open_symbol, from);
+ let count = 0;
+ while (found != -1 && found < cursor_index) {
+ count += 1;
+ from = found + 1;
+ found = document_text.indexOf(open_symbol, from);
+ }
+ const open_symbol_counts = count;
+ // count close symbols
+ from = 0;
+ found = document_text.indexOf(close_symbol, from);
+ count = 0;
+ while (found != -1 && found < cursor_index) {
+ count += 1;
+ from = found + 1;
+ found = document_text.indexOf(close_symbol, from);
+ }
+ const close_symbol_counts = count;
+ return open_symbol_counts > close_symbol_counts;
+ };
+ }
+ onload() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.registerEditorExtension(this.makeExtensionThing());
+ yield this.loadSettings();
+ // preprocess shorthand array
+ let shorthands = this.settings.customShorthand_parameter;
+ while (shorthands.slice(-2) == "\n") {
+ shorthands = shorthands.slice(0, -2);
+ }
+ if (shorthands.slice(-1) == ";") {
+ shorthands = shorthands.slice(0, -1);
+ }
+ if (shorthands.lastIndexOf(";\n") == -1) {
+ this.shorthand_array = shorthands.split(",").map(item => item.split(":"));
+ }
+ else if (shorthands.lastIndexOf(":::") == -1) {
+ this.shorthand_array = shorthands.split(";\n").map(item => item.split(":"));
+ }
+ else {
+ this.shorthand_array = shorthands.split(";\n").map(item => item.split(":::"));
+ }
+ // preprocess autoAlign array
+ if (this.settings.autoAlignSymbols.trim() == "") {
+ this.autoAlign_array = [];
+ }
+ else {
+ this.autoAlign_array = this.settings.autoAlignSymbols.split(" ");
+ }
+ this.app.workspace.onLayoutReady(() => {
+ this.registerCodeMirror((cm) => {
+ cm.on('vim-mode-change', this.handleVimModeChange);
+ cm.on('keydown', this.handleKeyDown);
+ cm.on('keypress', this.handleKeyPress);
+ });
+ this.addSettingTab(new QuickLatexSettingTab(this.app, this));
+ this.addCommand({
+ id: 'addAlignBlock',
+ name: 'Add Align Block',
+ hotkeys: [
+ {
+ modifiers: ['Alt', 'Shift'],
+ key: 'A',
+ },
+ ],
+ editorCallback: (editor) => this.addAlignBlock(editor),
+ });
+ this.addCommand({
+ id: 'addInlineMath',
+ name: 'Add Inline Math',
+ hotkeys: [
+ {
+ modifiers: ['Mod'],
+ key: 'M',
+ },
+ ],
+ editorCallback: (editor) => this.addInlineMath(editor),
+ });
+ this.addCommand({
+ id: 'addBlockMath',
+ name: 'Add Block Math',
+ hotkeys: [
+ {
+ modifiers: ['Mod', 'Shift'],
+ key: 'M',
+ },
+ ],
+ editorCallback: (editor) => this.addBlockMath(editor),
+ });
+ this.addCommand({
+ id: 'addMatrixBlock',
+ name: 'Add Matrix Block',
+ hotkeys: [
+ {
+ modifiers: ['Alt', 'Shift'],
+ key: 'M',
+ },
+ ],
+ editorCallback: (editor) => this.addMatrixBlock(editor),
+ });
+ this.addCommand({
+ id: 'addCasesBlock',
+ name: 'Add Cases Block',
+ hotkeys: [
+ {
+ modifiers: ['Alt', 'Shift'],
+ key: 'C',
+ },
+ ],
+ editorCallback: (editor) => this.addCasesBlock(editor),
+ });
+ });
+ });
+ }
+ addInlineMath(editor) {
+ if (!this.settings.useMathKeyboardShortcut_toggle)
+ return false;
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ if (editor.getSelection().length > 0) {
+ // enclose selected text
+ const anchor = editor.getCursor("anchor");
+ const head = editor.getCursor("head");
+ editor.replaceSelection(`$${editor.getSelection()}$`);
+ if (anchor.line > head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 1 });
+ }
+ else if (anchor.line < head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch });
+ }
+ else {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 1 }, { line: head.line, ch: head.ch + 1 });
+ }
+ }
+ else {
+ const position = editor.getCursor();
+ editor.replaceSelection("$$");
+ editor.setCursor({ line: position.line, ch: position.ch + 1 });
+ }
+ return true;
+ }
+ addBlockMath(editor) {
+ if (!this.settings.useMathKeyboardShortcut_toggle)
+ return false;
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return false;
+ if (editor.getSelection().length > 0) {
+ // enclose selected text
+ const anchor = editor.getCursor("anchor");
+ const head = editor.getCursor("head");
+ editor.replaceSelection(`$$${editor.getSelection()}$$`);
+ if (anchor.line > head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch }, { line: head.line, ch: head.ch + 2 });
+ }
+ else if (anchor.line < head.line) {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 2 }, { line: head.line, ch: head.ch });
+ }
+ else {
+ editor.setSelection({ line: anchor.line, ch: anchor.ch + 2 }, { line: head.line, ch: head.ch + 2 });
+ }
+ }
+ else {
+ const position = editor.getCursor();
+ editor.replaceSelection("$$$$");
+ editor.setCursor({ line: position.line, ch: position.ch + 2 });
+ }
+ return true;
+ }
+ addAlignBlock(editor) {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return;
+ if (!this.settings.addAlignBlock_toggle)
+ return;
+ const selected_text = editor.getSelection();
+ editor.replaceSelection('\\begin{' + this.settings.addAlignBlock_parameter + '}\n' +
+ selected_text +
+ '\n\\end{' + this.settings.addAlignBlock_parameter + '}');
+ const position = editor.getCursor();
+ editor.setCursor({ line: position.line - 1, ch: editor.getLine(position.line - 1).length });
+ }
+ addMatrixBlock(editor) {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return;
+ if (!this.settings.addMatrixBlock_toggle)
+ return;
+ editor.replaceSelection('\\begin{' + this.settings.addMatrixBlock_parameter + '}' +
+ '\\end{' + this.settings.addMatrixBlock_parameter + '}');
+ const position = editor.getCursor();
+ const retract_length = ('\\end{' + this.settings.addMatrixBlock_parameter + '}').length;
+ editor.setCursor({ line: position.line, ch: position.ch - retract_length });
+ }
+ addCasesBlock(editor) {
+ const view = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
+ if (!view)
+ return;
+ if (!this.settings.addCasesBlock_toggle)
+ return;
+ const selected_text = editor.getSelection();
+ editor.replaceSelection('\\begin{cases}\n' +
+ selected_text +
+ '\n\\end{cases}');
+ const position = editor.getCursor();
+ editor.setCursor({ line: position.line - 1, ch: editor.getLine(position.line - 1).length });
+ }
+ // Settings load and save
+ loadSettings() {
+ return __awaiter(this, void 0, void 0, function* () {
+ this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
+ });
+ }
+ ;
+ onunload() {
+ this.app.workspace.iterateCodeMirrors((cm) => {
+ cm.off('vim-mode-change', this.handleVimModeChange);
+ cm.off('keydown', this.handleKeyDown);
+ cm.off('keypress', this.handleKeyPress);
+ });
+ }
+}
+class QuickLatexSettingTab extends obsidian.PluginSettingTab {
+ constructor(app, plugin) {
+ super(app, plugin);
+ this.plugin = plugin;
+ }
+ display() {
+ const { containerEl } = this;
+ containerEl.empty();
+ containerEl.createEl('h2', { text: 'Quick Latex for Obsidian - Settings' });
+ new obsidian.Setting(containerEl)
+ .setName('Autoclose $$ symbols')
+ .setDesc('Typing one $ symbol will automatically lose with another $ symbol ' +
+ '(best used with "Move cursor between $$ symbols" function')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoCloseMath_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoCloseMath_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Shortcut for inline and block math')
+ .setDesc('Enable keyboard shortcuts for inline ($...$) and block ($$...$$) math. ' +
+ 'Default: ctrl+m (cmd+m on mac) for inline and ctrl+shift+m (cmd+shift+m on mac) for block.')
+ .addToggle((toggle) => {
+ toggle.setValue(this.plugin.settings.useMathKeyboardShortcut_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.useMathKeyboardShortcut_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ }));
+ });
+ new obsidian.Setting(containerEl)
+ .setName('Move cursor between $$ symbols')
+ .setDesc('Typing two consecutive $ symbols will automatically shift the cursor in between the $$ symbols')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.moveIntoMath_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.moveIntoMath_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Enclose selected expression with math symbol $$')
+ .setDesc('Select an expression and press "$" key will automatically ' +
+ 'enclose the expression with the math symbols.')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.encloseSelection_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.encloseSelection_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Autoclose {} curly brackets')
+ .setDesc('Typing "{" will automatically close with "}"')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoCloseCurly_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoCloseCurly_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Autoclose [] square brackets')
+ .setDesc('Typing "[" will automatically close with "]"')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoCloseSquare_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoCloseSquare_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Autoclose () round brackets')
+ .setDesc('Typing "(" will automatically close with ")"')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoCloseRound_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoCloseRound_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Auto append "\\limits" after "\\sum"')
+ .setDesc('Typing "\\sum" will automatically append "\\limits" to shorten the syntax' +
+ ' for proper display of the limits for summation symbol.')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoSumLimit_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoSumLimit_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Auto enlarge brackets that contains \\sum, \\int or \\frac')
+ .setDesc('Place cursor right after a () or [] bracketed expression that contains either ' +
+ '\\sum, \\int or \\frac and press the space key, the outermost brackets will be' +
+ ' appended with \\left and \\right in order to display larger brackets to enclose these big expressions.')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoLargeBracket_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoLargeBracket_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Auto enclose expression after superscipt with {}')
+ .setDesc('Typing expression after superscript "^" symbol follow by a "space" key ' +
+ 'will automatically surround the expression with "{}"')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoEncloseSup_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoEncloseSup_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Auto enclose expression after subscript with {}')
+ .setDesc('Typing expression after subscript "_" symbol follow by a "space" key ' +
+ 'will automatically surround the expression with "{}". ' +
+ 'Note: expression more than 10 characters long will be ignored.')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoEncloseSub_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoEncloseSub_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Type "/" instead of \\frac{}{}')
+ .setDesc('Use "/" symbol for quickly typing fractions. eg. type "1/2" followed by a "space" key' +
+ ' to transform to \\frac{1}{2}')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoFraction_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoFraction_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Shortcut for Align Block')
+ .setDesc('Use shortcut key to quickly insert \\begin{align*} \\end{align*} block. ' +
+ 'Default: "Alt+Shift+A" (Mac: "Option+Shift+A")')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.addAlignBlock_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.addAlignBlock_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Align Block Parameter')
+ .setDesc('Set the text parameter in \\begin{parameter} and \\end{parameter}.')
+ .addText((text) => text
+ .setPlaceholder('default: align*')
+ .setValue(this.plugin.settings.addAlignBlock_parameter)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.addAlignBlock_parameter = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('【NEW!】Auto-align at these symbols')
+ .setDesc('When within the align block, the align symbol "&" will be automatically added before these symbols. (separate by spaces)')
+ .addText((text) => text
+ .setValue(this.plugin.settings.autoAlignSymbols)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoAlignSymbols = value;
+ if (value == "") {
+ this.plugin.autoAlign_array = [];
+ }
+ else {
+ this.plugin.autoAlign_array = value.split(" ");
+ }
+ yield this.plugin.saveData(this.plugin.settings);
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Shortcut for Cases Block')
+ .setDesc('Use shortcut key to quickly insert \\begin{cases} \\end{cases} block. ' +
+ 'Default: "Alt+Shift+C" (Mac: "Option+Shift+C")')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.addCasesBlock_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.addCasesBlock_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Use shift-enter for line break in align and cases block')
+ .setDesc('For align and cases block above, pressing enter automatically adds line break symbol "\\" or "&". Switch here to use shift-enter instead.')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.shiftEnter_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.shiftEnter_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Shortcut for Matrix Block')
+ .setDesc('Use shortcut key to quickly insert \\begin{pmatrix} \\end{pmatrix} block. ' +
+ 'Default: "Alt+Shift+M" (Mac: "Option+Shift+M")')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.addMatrixBlock_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.addMatrixBlock_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Matrix Block Parameter')
+ .setDesc('Set the text parameter in \\begin{parameter} and \\end{parameter}.')
+ .addText((text) => text
+ .setPlaceholder('default: pmatrix')
+ .setValue(this.plugin.settings.addMatrixBlock_parameter)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.addMatrixBlock_parameter = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Greek symbols math mode')
+ .setDesc('Automatically surround commands to insert Greek character written outside math mode with math chars. ' +
+ 'Eg, typing \\alpha followed by space outside math mode will be replaced with "$\\alpha$"')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.autoGreekCommandMathMode_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.autoGreekCommandMathMode_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Custom Shorthand')
+ .setDesc('Use custom shorthand (can be multiple letters) for common latex strings. ' +
+ 'Eg, typing "al" followed by "space/tab" key will replace with "\\alpha"')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.customShorthand_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.customShorthand_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Use Tab to complete custom shorthand')
+ .setDesc('Use Tab instead of space to complete custom shorthand.')
+ .addToggle((toggle) => toggle
+ .setValue(this.plugin.settings.useTabtoComplete_toggle)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.useTabtoComplete_toggle = value;
+ yield this.plugin.saveData(this.plugin.settings);
+ this.display();
+ })));
+ new obsidian.Setting(containerEl)
+ .setName('Custom Shorthand Parameter')
+ .setDesc('Separate the multi-letters shorthand and the snippet with ":::" and ' +
+ 'end each set of shorthand snippet pair by "---" and a newline. ' +
+ 'For expressions that end with "{}", the cursor will automatically be placed within the bracket. ' +
+ 'Alternatively, you can type "#cursor" within the snippet to set the cursor location after replacement. ' +
+ 'You can also include "#tab" within the snippet for use cases such as multiple {}s (e.g. \\binom{#cursor}{#tab}). ' +
+ 'Pressing tab key in such cases will jump the cursor to the next "#tab" keyword. ' +
+ 'Numbers after each "#tab" can be added to define the order in which to jump between the tabs (e.g. \\left#cursor #tab2 \\right#tab1 will first jump to #tab1 then back to #tab2). ' +
+ 'Shorthands now support multiline snippets too! ' +
+ '(try uninstall then reinstalling the plugin to see the new set of shorthands.) ' +
+ '【NOTE】For old users, please kindly replace ":" with ":::" in your custom shorthand parameter.')
+ .setClass("text-snippets-class")
+ .addTextArea((text) => text
+ .setValue(this.plugin.settings.customShorthand_parameter)
+ .onChange((value) => __awaiter(this, void 0, void 0, function* () {
+ this.plugin.settings.customShorthand_parameter = value;
+ while (value.slice(-2) == "\n") {
+ value = value.slice(0, -1);
+ }
+ if (value.slice(-1) == ";") {
+ value = value.slice(0, -1);
+ }
+ if (value.lastIndexOf(";\n") == -1) {
+ this.plugin.shorthand_array = value.split(",").map(item => item.split(":"));
+ }
+ else if (value.lastIndexOf(":::") == -1) {
+ this.plugin.shorthand_array = value.split(";\n").map(item => item.split(":"));
+ }
+ else {
+ this.plugin.shorthand_array = value.split(";\n").map(item => item.split(":::"));
+ }
+ yield this.plugin.saveData(this.plugin.settings);
+ })));
+ }
+ ;
}
module.exports = QuickLatexPlugin;
diff --git a/.obsidian/plugins/quick-latex/manifest.json b/.obsidian/plugins/quick-latex/manifest.json
index 2f42316..96efb1f 100644
--- a/.obsidian/plugins/quick-latex/manifest.json
+++ b/.obsidian/plugins/quick-latex/manifest.json
@@ -1,10 +1,10 @@
-{
- "id": "quick-latex",
- "name": "Quick Latex",
- "version": "2.6.5",
- "minAppVersion": "0.9.12",
- "description": "Speedup latex math typing with auto fraction, custom shorthand, align block shortcut, matrix shortcut...etc",
- "author": "joeyuping",
- "authorUrl": "https://github.com/joeyuping/quick_latex_obsidian",
- "isDesktopOnly": false
-}
+{
+ "id": "quick-latex",
+ "name": "Quick Latex",
+ "version": "2.6.5",
+ "minAppVersion": "0.9.12",
+ "description": "Speedup latex math typing with auto fraction, custom shorthand, align block shortcut, matrix shortcut...etc",
+ "author": "joeyuping",
+ "authorUrl": "https://github.com/joeyuping/quick_latex_obsidian",
+ "isDesktopOnly": false
+}
diff --git a/.obsidian/plugins/quick-latex/styles.css b/.obsidian/plugins/quick-latex/styles.css
index 7e8ecc7..4860c07 100644
--- a/.obsidian/plugins/quick-latex/styles.css
+++ b/.obsidian/plugins/quick-latex/styles.css
@@ -1,13 +1,13 @@
-.text-snippets-class > * > textarea{
- width:40em;
- height: 100%;
- }
-
-.text-snippets-class > * {
- height: 100%;
- width: 60em;
-}
-
-.text-snippets-class {
- height: 70%;
+.text-snippets-class > * > textarea{
+ width:40em;
+ height: 100%;
+ }
+
+.text-snippets-class > * {
+ height: 100%;
+ width: 60em;
+}
+
+.text-snippets-class {
+ height: 70%;
}
\ No newline at end of file
diff --git a/.obsidian/plugins/symbols-prettifier/main.js b/.obsidian/plugins/symbols-prettifier/main.js
old mode 100644
new mode 100755
diff --git a/.obsidian/plugins/table-editor-obsidian/main.js b/.obsidian/plugins/table-editor-obsidian/main.js
old mode 100644
new mode 100755
index 231b82d..c24025b
--- a/.obsidian/plugins/table-editor-obsidian/main.js
+++ b/.obsidian/plugins/table-editor-obsidian/main.js
@@ -4,89 +4,89 @@ var obsidian = require('obsidian');
var state = require('@codemirror/state');
var view = require('@codemirror/view');
-/******************************************************************************
-Copyright (c) Microsoft Corporation.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-***************************************************************************** */
-/* global Reflect, Promise, SuppressedError, Symbol */
-
-var extendStatics = function(d, b) {
- extendStatics = Object.setPrototypeOf ||
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
- return extendStatics(d, b);
-};
-
-function __extends(d, b) {
- if (typeof b !== "function" && b !== null)
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
- extendStatics(d, b);
- function __() { this.constructor = d; }
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-}
-
-var __assign = function() {
- __assign = Object.assign || function __assign(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
- }
- return t;
- };
- return __assign.apply(this, arguments);
-};
-
-function __awaiter(thisArg, _arguments, P, generator) {
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
- return new (P || (P = Promise))(function (resolve, reject) {
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
- step((generator = generator.apply(thisArg, _arguments || [])).next());
- });
-}
-
-function __generator(thisArg, body) {
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
- function verb(n) { return function (v) { return step([n, v]); }; }
- function step(op) {
- if (f) throw new TypeError("Generator is already executing.");
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
- if (y = 0, t) op = [op[0] & 2, t.value];
- switch (op[0]) {
- case 0: case 1: t = op; break;
- case 4: _.label++; return { value: op[1], done: false };
- case 5: _.label++; y = op[1]; op = [0]; continue;
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
- default:
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
- if (t[2]) _.ops.pop();
- _.trys.pop(); continue;
- }
- op = body.call(thisArg, _);
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
- }
-}
-
-typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
- var e = new Error(message);
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
+/******************************************************************************
+Copyright (c) Microsoft Corporation.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+***************************************************************************** */
+/* global Reflect, Promise, SuppressedError, Symbol */
+
+var extendStatics = function(d, b) {
+ extendStatics = Object.setPrototypeOf ||
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+ return extendStatics(d, b);
+};
+
+function __extends(d, b) {
+ if (typeof b !== "function" && b !== null)
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
+ extendStatics(d, b);
+ function __() { this.constructor = d; }
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+}
+
+var __assign = function() {
+ __assign = Object.assign || function __assign(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+};
+
+function __awaiter(thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+}
+
+function __generator(thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+}
+
+typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
+ var e = new Error(message);
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
var icons = {
@@ -609,4930 +609,4930 @@ var results = {};
var decimal = {exports: {}};
(function (module) {
-(function (globalScope) {
-
-
- /*!
- * decimal.js v10.4.3
- * An arbitrary-precision Decimal type for JavaScript.
- * https://github.com/MikeMcl/decimal.js
- * Copyright (c) 2022 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|Decimal}
- * max {number|string|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 halfPi,
- 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;
-
- x = x.asin();
- halfPi = getPi(Ctor, pr + 4, rm).times(0.5);
-
- Ctor.precision = pr;
- Ctor.rounding = rm;
-
- return halfPi.minus(x);
- };
-
-
- /*
- * 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|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|Decimal}
- *
- P.max = function () {
- Array.prototype.push.call(arguments, this);
- return maxOrMin(this.constructor, arguments, 'lt');
- };
- */
-
-
- /*
- * Return a new Decimal whose value is the minimum of the arguments and the value of this Decimal.
- *
- * arguments {number|string|Decimal}
- *
- P.min = function () {
- Array.prototype.push.call(arguments, this);
- return maxOrMin(this.constructor, arguments, 'gt');
- };
- */
-
-
- /*
- * 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|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|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|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` and `min`. `ltgt` is 'lt' or 'gt'.
- */
- function maxOrMin(Ctor, args, ltgt) {
- var y,
- x = new Ctor(args[0]),
- i = 0;
-
- for (; ++i < args.length;) {
- y = new Ctor(args[i]);
- if (!y.s) {
- x = y;
- break;
- } else if (x[ltgt](y)) {
- 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;
-
- // 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,
- 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;
- }
-
- 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|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|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|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|Decimal}
- * y {number|string|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|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|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|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|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|Decimal} The y-coordinate.
- * x {number|string|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|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|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|Decimal}
- * min {number|string|Decimal}
- * max {number|string|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|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|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|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;
-
- // Duplicate.
- 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, NaN.
- } else if (v * 0 !== 0) {
- if (!v) x.s = NaN;
- x.e = NaN;
- x.d = null;
- return;
- }
-
- return parseDecimal(x, v.toString());
-
- } else if (t !== 'string') {
- throw Error(invalidArgument + v);
- }
-
- // Minus sign?
- if ((i = v.charCodeAt(0)) === 45) {
- v = v.slice(1);
- x.s = -1;
- } else {
- // Plus sign?
- if (i === 43) v = v.slice(1);
- x.s = 1;
- }
-
- return isDecimal.test(v) ? parseDecimal(x, v) : parseOther(x, 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|Decimal}
- * y {number|string|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|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|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|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|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|Decimal} The argument of the logarithm.
- * y {number|string|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|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|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|Decimal}
- *
- */
- function max() {
- return maxOrMin(this, arguments, 'lt');
- }
-
-
- /*
- * Return a new Decimal whose value is the minimum of the arguments.
- *
- * arguments {number|string|Decimal}
- *
- */
- function min() {
- return maxOrMin(this, arguments, 'gt');
- }
-
-
- /*
- * Return a new Decimal whose value is `x` modulo `y`, rounded to `precision` significant digits
- * using rounding mode `rounding`.
- *
- * x {number|string|Decimal}
- * y {number|string|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|Decimal}
- * y {number|string|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|Decimal} The base.
- * y {number|string|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|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|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|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|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|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|Decimal}
- * y {number|string|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|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|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|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|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 (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;
- }
+(function (globalScope) {
+
+
+ /*!
+ * decimal.js v10.4.3
+ * An arbitrary-precision Decimal type for JavaScript.
+ * https://github.com/MikeMcl/decimal.js
+ * Copyright (c) 2022 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|Decimal}
+ * max {number|string|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 halfPi,
+ 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;
+
+ x = x.asin();
+ halfPi = getPi(Ctor, pr + 4, rm).times(0.5);
+
+ Ctor.precision = pr;
+ Ctor.rounding = rm;
+
+ return halfPi.minus(x);
+ };
+
+
+ /*
+ * 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|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|Decimal}
+ *
+ P.max = function () {
+ Array.prototype.push.call(arguments, this);
+ return maxOrMin(this.constructor, arguments, 'lt');
+ };
+ */
+
+
+ /*
+ * Return a new Decimal whose value is the minimum of the arguments and the value of this Decimal.
+ *
+ * arguments {number|string|Decimal}
+ *
+ P.min = function () {
+ Array.prototype.push.call(arguments, this);
+ return maxOrMin(this.constructor, arguments, 'gt');
+ };
+ */
+
+
+ /*
+ * 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|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|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|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` and `min`. `ltgt` is 'lt' or 'gt'.
+ */
+ function maxOrMin(Ctor, args, ltgt) {
+ var y,
+ x = new Ctor(args[0]),
+ i = 0;
+
+ for (; ++i < args.length;) {
+ y = new Ctor(args[i]);
+ if (!y.s) {
+ x = y;
+ break;
+ } else if (x[ltgt](y)) {
+ 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;
+
+ // 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,
+ 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;
+ }
+
+ 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|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|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|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|Decimal}
+ * y {number|string|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|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|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|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|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|Decimal} The y-coordinate.
+ * x {number|string|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|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|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|Decimal}
+ * min {number|string|Decimal}
+ * max {number|string|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|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|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|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;
+
+ // Duplicate.
+ 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, NaN.
+ } else if (v * 0 !== 0) {
+ if (!v) x.s = NaN;
+ x.e = NaN;
+ x.d = null;
+ return;
+ }
+
+ return parseDecimal(x, v.toString());
+
+ } else if (t !== 'string') {
+ throw Error(invalidArgument + v);
+ }
+
+ // Minus sign?
+ if ((i = v.charCodeAt(0)) === 45) {
+ v = v.slice(1);
+ x.s = -1;
+ } else {
+ // Plus sign?
+ if (i === 43) v = v.slice(1);
+ x.s = 1;
+ }
+
+ return isDecimal.test(v) ? parseDecimal(x, v) : parseOther(x, 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|Decimal}
+ * y {number|string|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|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|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|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|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|Decimal} The argument of the logarithm.
+ * y {number|string|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|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|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|Decimal}
+ *
+ */
+ function max() {
+ return maxOrMin(this, arguments, 'lt');
+ }
+
+
+ /*
+ * Return a new Decimal whose value is the minimum of the arguments.
+ *
+ * arguments {number|string|Decimal}
+ *
+ */
+ function min() {
+ return maxOrMin(this, arguments, 'gt');
+ }
+
+
+ /*
+ * Return a new Decimal whose value is `x` modulo `y`, rounded to `precision` significant digits
+ * using rounding mode `rounding`.
+ *
+ * x {number|string|Decimal}
+ * y {number|string|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|Decimal}
+ * y {number|string|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|Decimal} The base.
+ * y {number|string|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|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|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|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|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|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|Decimal}
+ * y {number|string|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|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|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|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|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 (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;
+ }
})(commonjsGlobal);
} (decimal));
@@ -25872,697 +25872,697 @@ var parser = {};
var formatter = {};
-/*
- * Generated by script. DO NOT EDIT!
- *
- * The part between BEGIN and END is derived from Unicode Data Files
- * and provided under Unicode, Inc. License Agreement.
- */
-/* BEGIN */
-var defs = [
- [0, 31, "N"],
- [32, 126, "Na"],
- [127, 160, "N"],
- [161, 161, "A"],
- [162, 163, "Na"],
- [164, 164, "A"],
- [165, 166, "Na"],
- [167, 168, "A"],
- [169, 169, "N"],
- [170, 170, "A"],
- [171, 171, "N"],
- [172, 172, "Na"],
- [173, 174, "A"],
- [175, 175, "Na"],
- [176, 180, "A"],
- [181, 181, "N"],
- [182, 186, "A"],
- [187, 187, "N"],
- [188, 191, "A"],
- [192, 197, "N"],
- [198, 198, "A"],
- [199, 207, "N"],
- [208, 208, "A"],
- [209, 214, "N"],
- [215, 216, "A"],
- [217, 221, "N"],
- [222, 225, "A"],
- [226, 229, "N"],
- [230, 230, "A"],
- [231, 231, "N"],
- [232, 234, "A"],
- [235, 235, "N"],
- [236, 237, "A"],
- [238, 239, "N"],
- [240, 240, "A"],
- [241, 241, "N"],
- [242, 243, "A"],
- [244, 246, "N"],
- [247, 250, "A"],
- [251, 251, "N"],
- [252, 252, "A"],
- [253, 253, "N"],
- [254, 254, "A"],
- [255, 256, "N"],
- [257, 257, "A"],
- [258, 272, "N"],
- [273, 273, "A"],
- [274, 274, "N"],
- [275, 275, "A"],
- [276, 282, "N"],
- [283, 283, "A"],
- [284, 293, "N"],
- [294, 295, "A"],
- [296, 298, "N"],
- [299, 299, "A"],
- [300, 304, "N"],
- [305, 307, "A"],
- [308, 311, "N"],
- [312, 312, "A"],
- [313, 318, "N"],
- [319, 322, "A"],
- [323, 323, "N"],
- [324, 324, "A"],
- [325, 327, "N"],
- [328, 331, "A"],
- [332, 332, "N"],
- [333, 333, "A"],
- [334, 337, "N"],
- [338, 339, "A"],
- [340, 357, "N"],
- [358, 359, "A"],
- [360, 362, "N"],
- [363, 363, "A"],
- [364, 461, "N"],
- [462, 462, "A"],
- [463, 463, "N"],
- [464, 464, "A"],
- [465, 465, "N"],
- [466, 466, "A"],
- [467, 467, "N"],
- [468, 468, "A"],
- [469, 469, "N"],
- [470, 470, "A"],
- [471, 471, "N"],
- [472, 472, "A"],
- [473, 473, "N"],
- [474, 474, "A"],
- [475, 475, "N"],
- [476, 476, "A"],
- [477, 592, "N"],
- [593, 593, "A"],
- [594, 608, "N"],
- [609, 609, "A"],
- [610, 707, "N"],
- [708, 708, "A"],
- [709, 710, "N"],
- [711, 711, "A"],
- [712, 712, "N"],
- [713, 715, "A"],
- [716, 716, "N"],
- [717, 717, "A"],
- [718, 719, "N"],
- [720, 720, "A"],
- [721, 727, "N"],
- [728, 731, "A"],
- [732, 732, "N"],
- [733, 733, "A"],
- [734, 734, "N"],
- [735, 735, "A"],
- [736, 767, "N"],
- [768, 879, "A"],
- [880, 912, "N"],
- [913, 929, "A"],
- [930, 930, "N"],
- [931, 937, "A"],
- [938, 944, "N"],
- [945, 961, "A"],
- [962, 962, "N"],
- [963, 969, "A"],
- [970, 1024, "N"],
- [1025, 1025, "A"],
- [1026, 1039, "N"],
- [1040, 1103, "A"],
- [1104, 1104, "N"],
- [1105, 1105, "A"],
- [1106, 4351, "N"],
- [4352, 4447, "W"],
- [4448, 8207, "N"],
- [8208, 8208, "A"],
- [8209, 8210, "N"],
- [8211, 8214, "A"],
- [8215, 8215, "N"],
- [8216, 8217, "A"],
- [8218, 8219, "N"],
- [8220, 8221, "A"],
- [8222, 8223, "N"],
- [8224, 8226, "A"],
- [8227, 8227, "N"],
- [8228, 8231, "A"],
- [8232, 8239, "N"],
- [8240, 8240, "A"],
- [8241, 8241, "N"],
- [8242, 8243, "A"],
- [8244, 8244, "N"],
- [8245, 8245, "A"],
- [8246, 8250, "N"],
- [8251, 8251, "A"],
- [8252, 8253, "N"],
- [8254, 8254, "A"],
- [8255, 8307, "N"],
- [8308, 8308, "A"],
- [8309, 8318, "N"],
- [8319, 8319, "A"],
- [8320, 8320, "N"],
- [8321, 8324, "A"],
- [8325, 8360, "N"],
- [8361, 8361, "H"],
- [8362, 8363, "N"],
- [8364, 8364, "A"],
- [8365, 8450, "N"],
- [8451, 8451, "A"],
- [8452, 8452, "N"],
- [8453, 8453, "A"],
- [8454, 8456, "N"],
- [8457, 8457, "A"],
- [8458, 8466, "N"],
- [8467, 8467, "A"],
- [8468, 8469, "N"],
- [8470, 8470, "A"],
- [8471, 8480, "N"],
- [8481, 8482, "A"],
- [8483, 8485, "N"],
- [8486, 8486, "A"],
- [8487, 8490, "N"],
- [8491, 8491, "A"],
- [8492, 8530, "N"],
- [8531, 8532, "A"],
- [8533, 8538, "N"],
- [8539, 8542, "A"],
- [8543, 8543, "N"],
- [8544, 8555, "A"],
- [8556, 8559, "N"],
- [8560, 8569, "A"],
- [8570, 8584, "N"],
- [8585, 8585, "A"],
- [8586, 8591, "N"],
- [8592, 8601, "A"],
- [8602, 8631, "N"],
- [8632, 8633, "A"],
- [8634, 8657, "N"],
- [8658, 8658, "A"],
- [8659, 8659, "N"],
- [8660, 8660, "A"],
- [8661, 8678, "N"],
- [8679, 8679, "A"],
- [8680, 8703, "N"],
- [8704, 8704, "A"],
- [8705, 8705, "N"],
- [8706, 8707, "A"],
- [8708, 8710, "N"],
- [8711, 8712, "A"],
- [8713, 8714, "N"],
- [8715, 8715, "A"],
- [8716, 8718, "N"],
- [8719, 8719, "A"],
- [8720, 8720, "N"],
- [8721, 8721, "A"],
- [8722, 8724, "N"],
- [8725, 8725, "A"],
- [8726, 8729, "N"],
- [8730, 8730, "A"],
- [8731, 8732, "N"],
- [8733, 8736, "A"],
- [8737, 8738, "N"],
- [8739, 8739, "A"],
- [8740, 8740, "N"],
- [8741, 8741, "A"],
- [8742, 8742, "N"],
- [8743, 8748, "A"],
- [8749, 8749, "N"],
- [8750, 8750, "A"],
- [8751, 8755, "N"],
- [8756, 8759, "A"],
- [8760, 8763, "N"],
- [8764, 8765, "A"],
- [8766, 8775, "N"],
- [8776, 8776, "A"],
- [8777, 8779, "N"],
- [8780, 8780, "A"],
- [8781, 8785, "N"],
- [8786, 8786, "A"],
- [8787, 8799, "N"],
- [8800, 8801, "A"],
- [8802, 8803, "N"],
- [8804, 8807, "A"],
- [8808, 8809, "N"],
- [8810, 8811, "A"],
- [8812, 8813, "N"],
- [8814, 8815, "A"],
- [8816, 8833, "N"],
- [8834, 8835, "A"],
- [8836, 8837, "N"],
- [8838, 8839, "A"],
- [8840, 8852, "N"],
- [8853, 8853, "A"],
- [8854, 8856, "N"],
- [8857, 8857, "A"],
- [8858, 8868, "N"],
- [8869, 8869, "A"],
- [8870, 8894, "N"],
- [8895, 8895, "A"],
- [8896, 8977, "N"],
- [8978, 8978, "A"],
- [8979, 8985, "N"],
- [8986, 8987, "W"],
- [8988, 9000, "N"],
- [9001, 9002, "W"],
- [9003, 9192, "N"],
- [9193, 9196, "W"],
- [9197, 9199, "N"],
- [9200, 9200, "W"],
- [9201, 9202, "N"],
- [9203, 9203, "W"],
- [9204, 9311, "N"],
- [9312, 9449, "A"],
- [9450, 9450, "N"],
- [9451, 9547, "A"],
- [9548, 9551, "N"],
- [9552, 9587, "A"],
- [9588, 9599, "N"],
- [9600, 9615, "A"],
- [9616, 9617, "N"],
- [9618, 9621, "A"],
- [9622, 9631, "N"],
- [9632, 9633, "A"],
- [9634, 9634, "N"],
- [9635, 9641, "A"],
- [9642, 9649, "N"],
- [9650, 9651, "A"],
- [9652, 9653, "N"],
- [9654, 9655, "A"],
- [9656, 9659, "N"],
- [9660, 9661, "A"],
- [9662, 9663, "N"],
- [9664, 9665, "A"],
- [9666, 9669, "N"],
- [9670, 9672, "A"],
- [9673, 9674, "N"],
- [9675, 9675, "A"],
- [9676, 9677, "N"],
- [9678, 9681, "A"],
- [9682, 9697, "N"],
- [9698, 9701, "A"],
- [9702, 9710, "N"],
- [9711, 9711, "A"],
- [9712, 9724, "N"],
- [9725, 9726, "W"],
- [9727, 9732, "N"],
- [9733, 9734, "A"],
- [9735, 9736, "N"],
- [9737, 9737, "A"],
- [9738, 9741, "N"],
- [9742, 9743, "A"],
- [9744, 9747, "N"],
- [9748, 9749, "W"],
- [9750, 9755, "N"],
- [9756, 9756, "A"],
- [9757, 9757, "N"],
- [9758, 9758, "A"],
- [9759, 9791, "N"],
- [9792, 9792, "A"],
- [9793, 9793, "N"],
- [9794, 9794, "A"],
- [9795, 9799, "N"],
- [9800, 9811, "W"],
- [9812, 9823, "N"],
- [9824, 9825, "A"],
- [9826, 9826, "N"],
- [9827, 9829, "A"],
- [9830, 9830, "N"],
- [9831, 9834, "A"],
- [9835, 9835, "N"],
- [9836, 9837, "A"],
- [9838, 9838, "N"],
- [9839, 9839, "A"],
- [9840, 9854, "N"],
- [9855, 9855, "W"],
- [9856, 9874, "N"],
- [9875, 9875, "W"],
- [9876, 9885, "N"],
- [9886, 9887, "A"],
- [9888, 9888, "N"],
- [9889, 9889, "W"],
- [9890, 9897, "N"],
- [9898, 9899, "W"],
- [9900, 9916, "N"],
- [9917, 9918, "W"],
- [9919, 9919, "A"],
- [9920, 9923, "N"],
- [9924, 9925, "W"],
- [9926, 9933, "A"],
- [9934, 9934, "W"],
- [9935, 9939, "A"],
- [9940, 9940, "W"],
- [9941, 9953, "A"],
- [9954, 9954, "N"],
- [9955, 9955, "A"],
- [9956, 9959, "N"],
- [9960, 9961, "A"],
- [9962, 9962, "W"],
- [9963, 9969, "A"],
- [9970, 9971, "W"],
- [9972, 9972, "A"],
- [9973, 9973, "W"],
- [9974, 9977, "A"],
- [9978, 9978, "W"],
- [9979, 9980, "A"],
- [9981, 9981, "W"],
- [9982, 9983, "A"],
- [9984, 9988, "N"],
- [9989, 9989, "W"],
- [9990, 9993, "N"],
- [9994, 9995, "W"],
- [9996, 10023, "N"],
- [10024, 10024, "W"],
- [10025, 10044, "N"],
- [10045, 10045, "A"],
- [10046, 10059, "N"],
- [10060, 10060, "W"],
- [10061, 10061, "N"],
- [10062, 10062, "W"],
- [10063, 10066, "N"],
- [10067, 10069, "W"],
- [10070, 10070, "N"],
- [10071, 10071, "W"],
- [10072, 10101, "N"],
- [10102, 10111, "A"],
- [10112, 10132, "N"],
- [10133, 10135, "W"],
- [10136, 10159, "N"],
- [10160, 10160, "W"],
- [10161, 10174, "N"],
- [10175, 10175, "W"],
- [10176, 10213, "N"],
- [10214, 10221, "Na"],
- [10222, 10628, "N"],
- [10629, 10630, "Na"],
- [10631, 11034, "N"],
- [11035, 11036, "W"],
- [11037, 11087, "N"],
- [11088, 11088, "W"],
- [11089, 11092, "N"],
- [11093, 11093, "W"],
- [11094, 11097, "A"],
- [11098, 11903, "N"],
- [11904, 11929, "W"],
- [11930, 11930, "N"],
- [11931, 12019, "W"],
- [12020, 12031, "N"],
- [12032, 12245, "W"],
- [12246, 12271, "N"],
- [12272, 12283, "W"],
- [12284, 12287, "N"],
- [12288, 12288, "F"],
- [12289, 12350, "W"],
- [12351, 12352, "N"],
- [12353, 12438, "W"],
- [12439, 12440, "N"],
- [12441, 12543, "W"],
- [12544, 12548, "N"],
- [12549, 12591, "W"],
- [12592, 12592, "N"],
- [12593, 12686, "W"],
- [12687, 12687, "N"],
- [12688, 12771, "W"],
- [12772, 12783, "N"],
- [12784, 12830, "W"],
- [12831, 12831, "N"],
- [12832, 12871, "W"],
- [12872, 12879, "A"],
- [12880, 19903, "W"],
- [19904, 19967, "N"],
- [19968, 42124, "W"],
- [42125, 42127, "N"],
- [42128, 42182, "W"],
- [42183, 43359, "N"],
- [43360, 43388, "W"],
- [43389, 44031, "N"],
- [44032, 55203, "W"],
- [55204, 57343, "N"],
- [57344, 63743, "A"],
- [63744, 64255, "W"],
- [64256, 65023, "N"],
- [65024, 65039, "A"],
- [65040, 65049, "W"],
- [65050, 65071, "N"],
- [65072, 65106, "W"],
- [65107, 65107, "N"],
- [65108, 65126, "W"],
- [65127, 65127, "N"],
- [65128, 65131, "W"],
- [65132, 65280, "N"],
- [65281, 65376, "F"],
- [65377, 65470, "H"],
- [65471, 65473, "N"],
- [65474, 65479, "H"],
- [65480, 65481, "N"],
- [65482, 65487, "H"],
- [65488, 65489, "N"],
- [65490, 65495, "H"],
- [65496, 65497, "N"],
- [65498, 65500, "H"],
- [65501, 65503, "N"],
- [65504, 65510, "F"],
- [65511, 65511, "N"],
- [65512, 65518, "H"],
- [65519, 65532, "N"],
- [65533, 65533, "A"],
- [65534, 94175, "N"],
- [94176, 94180, "W"],
- [94181, 94191, "N"],
- [94192, 94193, "W"],
- [94194, 94207, "N"],
- [94208, 100343, "W"],
- [100344, 100351, "N"],
- [100352, 101589, "W"],
- [101590, 101631, "N"],
- [101632, 101640, "W"],
- [101641, 110591, "N"],
- [110592, 110878, "W"],
- [110879, 110927, "N"],
- [110928, 110930, "W"],
- [110931, 110947, "N"],
- [110948, 110951, "W"],
- [110952, 110959, "N"],
- [110960, 111355, "W"],
- [111356, 126979, "N"],
- [126980, 126980, "W"],
- [126981, 127182, "N"],
- [127183, 127183, "W"],
- [127184, 127231, "N"],
- [127232, 127242, "A"],
- [127243, 127247, "N"],
- [127248, 127277, "A"],
- [127278, 127279, "N"],
- [127280, 127337, "A"],
- [127338, 127343, "N"],
- [127344, 127373, "A"],
- [127374, 127374, "W"],
- [127375, 127376, "A"],
- [127377, 127386, "W"],
- [127387, 127404, "A"],
- [127405, 127487, "N"],
- [127488, 127490, "W"],
- [127491, 127503, "N"],
- [127504, 127547, "W"],
- [127548, 127551, "N"],
- [127552, 127560, "W"],
- [127561, 127567, "N"],
- [127568, 127569, "W"],
- [127570, 127583, "N"],
- [127584, 127589, "W"],
- [127590, 127743, "N"],
- [127744, 127776, "W"],
- [127777, 127788, "N"],
- [127789, 127797, "W"],
- [127798, 127798, "N"],
- [127799, 127868, "W"],
- [127869, 127869, "N"],
- [127870, 127891, "W"],
- [127892, 127903, "N"],
- [127904, 127946, "W"],
- [127947, 127950, "N"],
- [127951, 127955, "W"],
- [127956, 127967, "N"],
- [127968, 127984, "W"],
- [127985, 127987, "N"],
- [127988, 127988, "W"],
- [127989, 127991, "N"],
- [127992, 128062, "W"],
- [128063, 128063, "N"],
- [128064, 128064, "W"],
- [128065, 128065, "N"],
- [128066, 128252, "W"],
- [128253, 128254, "N"],
- [128255, 128317, "W"],
- [128318, 128330, "N"],
- [128331, 128334, "W"],
- [128335, 128335, "N"],
- [128336, 128359, "W"],
- [128360, 128377, "N"],
- [128378, 128378, "W"],
- [128379, 128404, "N"],
- [128405, 128406, "W"],
- [128407, 128419, "N"],
- [128420, 128420, "W"],
- [128421, 128506, "N"],
- [128507, 128591, "W"],
- [128592, 128639, "N"],
- [128640, 128709, "W"],
- [128710, 128715, "N"],
- [128716, 128716, "W"],
- [128717, 128719, "N"],
- [128720, 128722, "W"],
- [128723, 128724, "N"],
- [128725, 128727, "W"],
- [128728, 128746, "N"],
- [128747, 128748, "W"],
- [128749, 128755, "N"],
- [128756, 128764, "W"],
- [128765, 128991, "N"],
- [128992, 129003, "W"],
- [129004, 129291, "N"],
- [129292, 129338, "W"],
- [129339, 129339, "N"],
- [129340, 129349, "W"],
- [129350, 129350, "N"],
- [129351, 129400, "W"],
- [129401, 129401, "N"],
- [129402, 129483, "W"],
- [129484, 129484, "N"],
- [129485, 129535, "W"],
- [129536, 129647, "N"],
- [129648, 129652, "W"],
- [129653, 129655, "N"],
- [129656, 129658, "W"],
- [129659, 129663, "N"],
- [129664, 129670, "W"],
- [129671, 129679, "N"],
- [129680, 129704, "W"],
- [129705, 129711, "N"],
- [129712, 129718, "W"],
- [129719, 129727, "N"],
- [129728, 129730, "W"],
- [129731, 129743, "N"],
- [129744, 129750, "W"],
- [129751, 131071, "N"],
- [131072, 196605, "W"],
- [196606, 196607, "N"],
- [196608, 262141, "W"],
- [262142, 917759, "N"],
- [917760, 917999, "A"],
- [918000, 983039, "N"],
- [983040, 1048573, "A"],
- [1048574, 1048575, "N"],
- [1048576, 1114109, "A"],
- [1114110, 1114111, "N"],
-];
-/* END */
+/*
+ * Generated by script. DO NOT EDIT!
+ *
+ * The part between BEGIN and END is derived from Unicode Data Files
+ * and provided under Unicode, Inc. License Agreement.
+ */
+/* BEGIN */
+var defs = [
+ [0, 31, "N"],
+ [32, 126, "Na"],
+ [127, 160, "N"],
+ [161, 161, "A"],
+ [162, 163, "Na"],
+ [164, 164, "A"],
+ [165, 166, "Na"],
+ [167, 168, "A"],
+ [169, 169, "N"],
+ [170, 170, "A"],
+ [171, 171, "N"],
+ [172, 172, "Na"],
+ [173, 174, "A"],
+ [175, 175, "Na"],
+ [176, 180, "A"],
+ [181, 181, "N"],
+ [182, 186, "A"],
+ [187, 187, "N"],
+ [188, 191, "A"],
+ [192, 197, "N"],
+ [198, 198, "A"],
+ [199, 207, "N"],
+ [208, 208, "A"],
+ [209, 214, "N"],
+ [215, 216, "A"],
+ [217, 221, "N"],
+ [222, 225, "A"],
+ [226, 229, "N"],
+ [230, 230, "A"],
+ [231, 231, "N"],
+ [232, 234, "A"],
+ [235, 235, "N"],
+ [236, 237, "A"],
+ [238, 239, "N"],
+ [240, 240, "A"],
+ [241, 241, "N"],
+ [242, 243, "A"],
+ [244, 246, "N"],
+ [247, 250, "A"],
+ [251, 251, "N"],
+ [252, 252, "A"],
+ [253, 253, "N"],
+ [254, 254, "A"],
+ [255, 256, "N"],
+ [257, 257, "A"],
+ [258, 272, "N"],
+ [273, 273, "A"],
+ [274, 274, "N"],
+ [275, 275, "A"],
+ [276, 282, "N"],
+ [283, 283, "A"],
+ [284, 293, "N"],
+ [294, 295, "A"],
+ [296, 298, "N"],
+ [299, 299, "A"],
+ [300, 304, "N"],
+ [305, 307, "A"],
+ [308, 311, "N"],
+ [312, 312, "A"],
+ [313, 318, "N"],
+ [319, 322, "A"],
+ [323, 323, "N"],
+ [324, 324, "A"],
+ [325, 327, "N"],
+ [328, 331, "A"],
+ [332, 332, "N"],
+ [333, 333, "A"],
+ [334, 337, "N"],
+ [338, 339, "A"],
+ [340, 357, "N"],
+ [358, 359, "A"],
+ [360, 362, "N"],
+ [363, 363, "A"],
+ [364, 461, "N"],
+ [462, 462, "A"],
+ [463, 463, "N"],
+ [464, 464, "A"],
+ [465, 465, "N"],
+ [466, 466, "A"],
+ [467, 467, "N"],
+ [468, 468, "A"],
+ [469, 469, "N"],
+ [470, 470, "A"],
+ [471, 471, "N"],
+ [472, 472, "A"],
+ [473, 473, "N"],
+ [474, 474, "A"],
+ [475, 475, "N"],
+ [476, 476, "A"],
+ [477, 592, "N"],
+ [593, 593, "A"],
+ [594, 608, "N"],
+ [609, 609, "A"],
+ [610, 707, "N"],
+ [708, 708, "A"],
+ [709, 710, "N"],
+ [711, 711, "A"],
+ [712, 712, "N"],
+ [713, 715, "A"],
+ [716, 716, "N"],
+ [717, 717, "A"],
+ [718, 719, "N"],
+ [720, 720, "A"],
+ [721, 727, "N"],
+ [728, 731, "A"],
+ [732, 732, "N"],
+ [733, 733, "A"],
+ [734, 734, "N"],
+ [735, 735, "A"],
+ [736, 767, "N"],
+ [768, 879, "A"],
+ [880, 912, "N"],
+ [913, 929, "A"],
+ [930, 930, "N"],
+ [931, 937, "A"],
+ [938, 944, "N"],
+ [945, 961, "A"],
+ [962, 962, "N"],
+ [963, 969, "A"],
+ [970, 1024, "N"],
+ [1025, 1025, "A"],
+ [1026, 1039, "N"],
+ [1040, 1103, "A"],
+ [1104, 1104, "N"],
+ [1105, 1105, "A"],
+ [1106, 4351, "N"],
+ [4352, 4447, "W"],
+ [4448, 8207, "N"],
+ [8208, 8208, "A"],
+ [8209, 8210, "N"],
+ [8211, 8214, "A"],
+ [8215, 8215, "N"],
+ [8216, 8217, "A"],
+ [8218, 8219, "N"],
+ [8220, 8221, "A"],
+ [8222, 8223, "N"],
+ [8224, 8226, "A"],
+ [8227, 8227, "N"],
+ [8228, 8231, "A"],
+ [8232, 8239, "N"],
+ [8240, 8240, "A"],
+ [8241, 8241, "N"],
+ [8242, 8243, "A"],
+ [8244, 8244, "N"],
+ [8245, 8245, "A"],
+ [8246, 8250, "N"],
+ [8251, 8251, "A"],
+ [8252, 8253, "N"],
+ [8254, 8254, "A"],
+ [8255, 8307, "N"],
+ [8308, 8308, "A"],
+ [8309, 8318, "N"],
+ [8319, 8319, "A"],
+ [8320, 8320, "N"],
+ [8321, 8324, "A"],
+ [8325, 8360, "N"],
+ [8361, 8361, "H"],
+ [8362, 8363, "N"],
+ [8364, 8364, "A"],
+ [8365, 8450, "N"],
+ [8451, 8451, "A"],
+ [8452, 8452, "N"],
+ [8453, 8453, "A"],
+ [8454, 8456, "N"],
+ [8457, 8457, "A"],
+ [8458, 8466, "N"],
+ [8467, 8467, "A"],
+ [8468, 8469, "N"],
+ [8470, 8470, "A"],
+ [8471, 8480, "N"],
+ [8481, 8482, "A"],
+ [8483, 8485, "N"],
+ [8486, 8486, "A"],
+ [8487, 8490, "N"],
+ [8491, 8491, "A"],
+ [8492, 8530, "N"],
+ [8531, 8532, "A"],
+ [8533, 8538, "N"],
+ [8539, 8542, "A"],
+ [8543, 8543, "N"],
+ [8544, 8555, "A"],
+ [8556, 8559, "N"],
+ [8560, 8569, "A"],
+ [8570, 8584, "N"],
+ [8585, 8585, "A"],
+ [8586, 8591, "N"],
+ [8592, 8601, "A"],
+ [8602, 8631, "N"],
+ [8632, 8633, "A"],
+ [8634, 8657, "N"],
+ [8658, 8658, "A"],
+ [8659, 8659, "N"],
+ [8660, 8660, "A"],
+ [8661, 8678, "N"],
+ [8679, 8679, "A"],
+ [8680, 8703, "N"],
+ [8704, 8704, "A"],
+ [8705, 8705, "N"],
+ [8706, 8707, "A"],
+ [8708, 8710, "N"],
+ [8711, 8712, "A"],
+ [8713, 8714, "N"],
+ [8715, 8715, "A"],
+ [8716, 8718, "N"],
+ [8719, 8719, "A"],
+ [8720, 8720, "N"],
+ [8721, 8721, "A"],
+ [8722, 8724, "N"],
+ [8725, 8725, "A"],
+ [8726, 8729, "N"],
+ [8730, 8730, "A"],
+ [8731, 8732, "N"],
+ [8733, 8736, "A"],
+ [8737, 8738, "N"],
+ [8739, 8739, "A"],
+ [8740, 8740, "N"],
+ [8741, 8741, "A"],
+ [8742, 8742, "N"],
+ [8743, 8748, "A"],
+ [8749, 8749, "N"],
+ [8750, 8750, "A"],
+ [8751, 8755, "N"],
+ [8756, 8759, "A"],
+ [8760, 8763, "N"],
+ [8764, 8765, "A"],
+ [8766, 8775, "N"],
+ [8776, 8776, "A"],
+ [8777, 8779, "N"],
+ [8780, 8780, "A"],
+ [8781, 8785, "N"],
+ [8786, 8786, "A"],
+ [8787, 8799, "N"],
+ [8800, 8801, "A"],
+ [8802, 8803, "N"],
+ [8804, 8807, "A"],
+ [8808, 8809, "N"],
+ [8810, 8811, "A"],
+ [8812, 8813, "N"],
+ [8814, 8815, "A"],
+ [8816, 8833, "N"],
+ [8834, 8835, "A"],
+ [8836, 8837, "N"],
+ [8838, 8839, "A"],
+ [8840, 8852, "N"],
+ [8853, 8853, "A"],
+ [8854, 8856, "N"],
+ [8857, 8857, "A"],
+ [8858, 8868, "N"],
+ [8869, 8869, "A"],
+ [8870, 8894, "N"],
+ [8895, 8895, "A"],
+ [8896, 8977, "N"],
+ [8978, 8978, "A"],
+ [8979, 8985, "N"],
+ [8986, 8987, "W"],
+ [8988, 9000, "N"],
+ [9001, 9002, "W"],
+ [9003, 9192, "N"],
+ [9193, 9196, "W"],
+ [9197, 9199, "N"],
+ [9200, 9200, "W"],
+ [9201, 9202, "N"],
+ [9203, 9203, "W"],
+ [9204, 9311, "N"],
+ [9312, 9449, "A"],
+ [9450, 9450, "N"],
+ [9451, 9547, "A"],
+ [9548, 9551, "N"],
+ [9552, 9587, "A"],
+ [9588, 9599, "N"],
+ [9600, 9615, "A"],
+ [9616, 9617, "N"],
+ [9618, 9621, "A"],
+ [9622, 9631, "N"],
+ [9632, 9633, "A"],
+ [9634, 9634, "N"],
+ [9635, 9641, "A"],
+ [9642, 9649, "N"],
+ [9650, 9651, "A"],
+ [9652, 9653, "N"],
+ [9654, 9655, "A"],
+ [9656, 9659, "N"],
+ [9660, 9661, "A"],
+ [9662, 9663, "N"],
+ [9664, 9665, "A"],
+ [9666, 9669, "N"],
+ [9670, 9672, "A"],
+ [9673, 9674, "N"],
+ [9675, 9675, "A"],
+ [9676, 9677, "N"],
+ [9678, 9681, "A"],
+ [9682, 9697, "N"],
+ [9698, 9701, "A"],
+ [9702, 9710, "N"],
+ [9711, 9711, "A"],
+ [9712, 9724, "N"],
+ [9725, 9726, "W"],
+ [9727, 9732, "N"],
+ [9733, 9734, "A"],
+ [9735, 9736, "N"],
+ [9737, 9737, "A"],
+ [9738, 9741, "N"],
+ [9742, 9743, "A"],
+ [9744, 9747, "N"],
+ [9748, 9749, "W"],
+ [9750, 9755, "N"],
+ [9756, 9756, "A"],
+ [9757, 9757, "N"],
+ [9758, 9758, "A"],
+ [9759, 9791, "N"],
+ [9792, 9792, "A"],
+ [9793, 9793, "N"],
+ [9794, 9794, "A"],
+ [9795, 9799, "N"],
+ [9800, 9811, "W"],
+ [9812, 9823, "N"],
+ [9824, 9825, "A"],
+ [9826, 9826, "N"],
+ [9827, 9829, "A"],
+ [9830, 9830, "N"],
+ [9831, 9834, "A"],
+ [9835, 9835, "N"],
+ [9836, 9837, "A"],
+ [9838, 9838, "N"],
+ [9839, 9839, "A"],
+ [9840, 9854, "N"],
+ [9855, 9855, "W"],
+ [9856, 9874, "N"],
+ [9875, 9875, "W"],
+ [9876, 9885, "N"],
+ [9886, 9887, "A"],
+ [9888, 9888, "N"],
+ [9889, 9889, "W"],
+ [9890, 9897, "N"],
+ [9898, 9899, "W"],
+ [9900, 9916, "N"],
+ [9917, 9918, "W"],
+ [9919, 9919, "A"],
+ [9920, 9923, "N"],
+ [9924, 9925, "W"],
+ [9926, 9933, "A"],
+ [9934, 9934, "W"],
+ [9935, 9939, "A"],
+ [9940, 9940, "W"],
+ [9941, 9953, "A"],
+ [9954, 9954, "N"],
+ [9955, 9955, "A"],
+ [9956, 9959, "N"],
+ [9960, 9961, "A"],
+ [9962, 9962, "W"],
+ [9963, 9969, "A"],
+ [9970, 9971, "W"],
+ [9972, 9972, "A"],
+ [9973, 9973, "W"],
+ [9974, 9977, "A"],
+ [9978, 9978, "W"],
+ [9979, 9980, "A"],
+ [9981, 9981, "W"],
+ [9982, 9983, "A"],
+ [9984, 9988, "N"],
+ [9989, 9989, "W"],
+ [9990, 9993, "N"],
+ [9994, 9995, "W"],
+ [9996, 10023, "N"],
+ [10024, 10024, "W"],
+ [10025, 10044, "N"],
+ [10045, 10045, "A"],
+ [10046, 10059, "N"],
+ [10060, 10060, "W"],
+ [10061, 10061, "N"],
+ [10062, 10062, "W"],
+ [10063, 10066, "N"],
+ [10067, 10069, "W"],
+ [10070, 10070, "N"],
+ [10071, 10071, "W"],
+ [10072, 10101, "N"],
+ [10102, 10111, "A"],
+ [10112, 10132, "N"],
+ [10133, 10135, "W"],
+ [10136, 10159, "N"],
+ [10160, 10160, "W"],
+ [10161, 10174, "N"],
+ [10175, 10175, "W"],
+ [10176, 10213, "N"],
+ [10214, 10221, "Na"],
+ [10222, 10628, "N"],
+ [10629, 10630, "Na"],
+ [10631, 11034, "N"],
+ [11035, 11036, "W"],
+ [11037, 11087, "N"],
+ [11088, 11088, "W"],
+ [11089, 11092, "N"],
+ [11093, 11093, "W"],
+ [11094, 11097, "A"],
+ [11098, 11903, "N"],
+ [11904, 11929, "W"],
+ [11930, 11930, "N"],
+ [11931, 12019, "W"],
+ [12020, 12031, "N"],
+ [12032, 12245, "W"],
+ [12246, 12271, "N"],
+ [12272, 12283, "W"],
+ [12284, 12287, "N"],
+ [12288, 12288, "F"],
+ [12289, 12350, "W"],
+ [12351, 12352, "N"],
+ [12353, 12438, "W"],
+ [12439, 12440, "N"],
+ [12441, 12543, "W"],
+ [12544, 12548, "N"],
+ [12549, 12591, "W"],
+ [12592, 12592, "N"],
+ [12593, 12686, "W"],
+ [12687, 12687, "N"],
+ [12688, 12771, "W"],
+ [12772, 12783, "N"],
+ [12784, 12830, "W"],
+ [12831, 12831, "N"],
+ [12832, 12871, "W"],
+ [12872, 12879, "A"],
+ [12880, 19903, "W"],
+ [19904, 19967, "N"],
+ [19968, 42124, "W"],
+ [42125, 42127, "N"],
+ [42128, 42182, "W"],
+ [42183, 43359, "N"],
+ [43360, 43388, "W"],
+ [43389, 44031, "N"],
+ [44032, 55203, "W"],
+ [55204, 57343, "N"],
+ [57344, 63743, "A"],
+ [63744, 64255, "W"],
+ [64256, 65023, "N"],
+ [65024, 65039, "A"],
+ [65040, 65049, "W"],
+ [65050, 65071, "N"],
+ [65072, 65106, "W"],
+ [65107, 65107, "N"],
+ [65108, 65126, "W"],
+ [65127, 65127, "N"],
+ [65128, 65131, "W"],
+ [65132, 65280, "N"],
+ [65281, 65376, "F"],
+ [65377, 65470, "H"],
+ [65471, 65473, "N"],
+ [65474, 65479, "H"],
+ [65480, 65481, "N"],
+ [65482, 65487, "H"],
+ [65488, 65489, "N"],
+ [65490, 65495, "H"],
+ [65496, 65497, "N"],
+ [65498, 65500, "H"],
+ [65501, 65503, "N"],
+ [65504, 65510, "F"],
+ [65511, 65511, "N"],
+ [65512, 65518, "H"],
+ [65519, 65532, "N"],
+ [65533, 65533, "A"],
+ [65534, 94175, "N"],
+ [94176, 94180, "W"],
+ [94181, 94191, "N"],
+ [94192, 94193, "W"],
+ [94194, 94207, "N"],
+ [94208, 100343, "W"],
+ [100344, 100351, "N"],
+ [100352, 101589, "W"],
+ [101590, 101631, "N"],
+ [101632, 101640, "W"],
+ [101641, 110591, "N"],
+ [110592, 110878, "W"],
+ [110879, 110927, "N"],
+ [110928, 110930, "W"],
+ [110931, 110947, "N"],
+ [110948, 110951, "W"],
+ [110952, 110959, "N"],
+ [110960, 111355, "W"],
+ [111356, 126979, "N"],
+ [126980, 126980, "W"],
+ [126981, 127182, "N"],
+ [127183, 127183, "W"],
+ [127184, 127231, "N"],
+ [127232, 127242, "A"],
+ [127243, 127247, "N"],
+ [127248, 127277, "A"],
+ [127278, 127279, "N"],
+ [127280, 127337, "A"],
+ [127338, 127343, "N"],
+ [127344, 127373, "A"],
+ [127374, 127374, "W"],
+ [127375, 127376, "A"],
+ [127377, 127386, "W"],
+ [127387, 127404, "A"],
+ [127405, 127487, "N"],
+ [127488, 127490, "W"],
+ [127491, 127503, "N"],
+ [127504, 127547, "W"],
+ [127548, 127551, "N"],
+ [127552, 127560, "W"],
+ [127561, 127567, "N"],
+ [127568, 127569, "W"],
+ [127570, 127583, "N"],
+ [127584, 127589, "W"],
+ [127590, 127743, "N"],
+ [127744, 127776, "W"],
+ [127777, 127788, "N"],
+ [127789, 127797, "W"],
+ [127798, 127798, "N"],
+ [127799, 127868, "W"],
+ [127869, 127869, "N"],
+ [127870, 127891, "W"],
+ [127892, 127903, "N"],
+ [127904, 127946, "W"],
+ [127947, 127950, "N"],
+ [127951, 127955, "W"],
+ [127956, 127967, "N"],
+ [127968, 127984, "W"],
+ [127985, 127987, "N"],
+ [127988, 127988, "W"],
+ [127989, 127991, "N"],
+ [127992, 128062, "W"],
+ [128063, 128063, "N"],
+ [128064, 128064, "W"],
+ [128065, 128065, "N"],
+ [128066, 128252, "W"],
+ [128253, 128254, "N"],
+ [128255, 128317, "W"],
+ [128318, 128330, "N"],
+ [128331, 128334, "W"],
+ [128335, 128335, "N"],
+ [128336, 128359, "W"],
+ [128360, 128377, "N"],
+ [128378, 128378, "W"],
+ [128379, 128404, "N"],
+ [128405, 128406, "W"],
+ [128407, 128419, "N"],
+ [128420, 128420, "W"],
+ [128421, 128506, "N"],
+ [128507, 128591, "W"],
+ [128592, 128639, "N"],
+ [128640, 128709, "W"],
+ [128710, 128715, "N"],
+ [128716, 128716, "W"],
+ [128717, 128719, "N"],
+ [128720, 128722, "W"],
+ [128723, 128724, "N"],
+ [128725, 128727, "W"],
+ [128728, 128746, "N"],
+ [128747, 128748, "W"],
+ [128749, 128755, "N"],
+ [128756, 128764, "W"],
+ [128765, 128991, "N"],
+ [128992, 129003, "W"],
+ [129004, 129291, "N"],
+ [129292, 129338, "W"],
+ [129339, 129339, "N"],
+ [129340, 129349, "W"],
+ [129350, 129350, "N"],
+ [129351, 129400, "W"],
+ [129401, 129401, "N"],
+ [129402, 129483, "W"],
+ [129484, 129484, "N"],
+ [129485, 129535, "W"],
+ [129536, 129647, "N"],
+ [129648, 129652, "W"],
+ [129653, 129655, "N"],
+ [129656, 129658, "W"],
+ [129659, 129663, "N"],
+ [129664, 129670, "W"],
+ [129671, 129679, "N"],
+ [129680, 129704, "W"],
+ [129705, 129711, "N"],
+ [129712, 129718, "W"],
+ [129719, 129727, "N"],
+ [129728, 129730, "W"],
+ [129731, 129743, "N"],
+ [129744, 129750, "W"],
+ [129751, 131071, "N"],
+ [131072, 196605, "W"],
+ [196606, 196607, "N"],
+ [196608, 262141, "W"],
+ [262142, 917759, "N"],
+ [917760, 917999, "A"],
+ [918000, 983039, "N"],
+ [983040, 1048573, "A"],
+ [1048574, 1048575, "N"],
+ [1048576, 1114109, "A"],
+ [1114110, 1114111, "N"],
+];
+/* END */
var version = "13.0.0";
-/**
- * Gets the EAW property of a code point.
- * @param codePoint Code point
- * @return The EAW property of the code point
- */
-function getEAWOfCodePoint(codePoint) {
- var min = 0;
- var max = defs.length - 1;
- while (min !== max) {
- var i = min + ((max - min) >> 1);
- var _a = defs[i], start = _a[0], end = _a[1], prop = _a[2];
- if (codePoint < start) {
- max = i - 1;
- }
- else if (codePoint > end) {
- min = i + 1;
- }
- else {
- return prop;
- }
- }
- return defs[min][2];
-}
-/**
- * Gets the EAW property of a character.
- * @param str Character string
- * @param pos Character position (in code unit) (default = 0)
- * @return The EAW property of the character
- * @example
- * import { getEAW } from "meaw";
- *
- * // Narrow
- * assert(getEAW("A") === "Na");
- * // Wide
- * assert(getEAW("あ") === "W");
- * assert(getEAW("安") === "W");
- * assert(getEAW("🍣") === "W");
- * // Fullwidth
- * assert(getEAW("A") === "F");
- * // Halfwidth
- * assert(getEAW("ア") === "H");
- * // Ambiguous
- * assert(getEAW("∀") === "A");
- * assert(getEAW("→") === "A");
- * assert(getEAW("Ω") === "A");
- * assert(getEAW("Я") === "A");
- * // Neutral
- * assert(getEAW("ℵ") === "N");
- *
- * // character position (in code unit) can be specified
- * assert(getEAW("ℵAあAア∀", 2) === "W");
- */
-function getEAW(str, pos) {
- if (pos === void 0) { pos = 0; }
- var codePoint = str.codePointAt(pos);
- if (codePoint === undefined) {
- return undefined;
- }
- return getEAWOfCodePoint(codePoint);
+/**
+ * Gets the EAW property of a code point.
+ * @param codePoint Code point
+ * @return The EAW property of the code point
+ */
+function getEAWOfCodePoint(codePoint) {
+ var min = 0;
+ var max = defs.length - 1;
+ while (min !== max) {
+ var i = min + ((max - min) >> 1);
+ var _a = defs[i], start = _a[0], end = _a[1], prop = _a[2];
+ if (codePoint < start) {
+ max = i - 1;
+ }
+ else if (codePoint > end) {
+ min = i + 1;
+ }
+ else {
+ return prop;
+ }
+ }
+ return defs[min][2];
+}
+/**
+ * Gets the EAW property of a character.
+ * @param str Character string
+ * @param pos Character position (in code unit) (default = 0)
+ * @return The EAW property of the character
+ * @example
+ * import { getEAW } from "meaw";
+ *
+ * // Narrow
+ * assert(getEAW("A") === "Na");
+ * // Wide
+ * assert(getEAW("あ") === "W");
+ * assert(getEAW("安") === "W");
+ * assert(getEAW("🍣") === "W");
+ * // Fullwidth
+ * assert(getEAW("A") === "F");
+ * // Halfwidth
+ * assert(getEAW("ア") === "H");
+ * // Ambiguous
+ * assert(getEAW("∀") === "A");
+ * assert(getEAW("→") === "A");
+ * assert(getEAW("Ω") === "A");
+ * assert(getEAW("Я") === "A");
+ * // Neutral
+ * assert(getEAW("ℵ") === "N");
+ *
+ * // character position (in code unit) can be specified
+ * assert(getEAW("ℵAあAア∀", 2) === "W");
+ */
+function getEAW(str, pos) {
+ if (pos === void 0) { pos = 0; }
+ var codePoint = str.codePointAt(pos);
+ if (codePoint === undefined) {
+ return undefined;
+ }
+ return getEAWOfCodePoint(codePoint);
}
-var defaultWidths = {
- N: 1,
- Na: 1,
- W: 2,
- F: 2,
- H: 1,
- A: 1,
-};
-/**
- * Computes the width of a string based on the EAW properties of the characters.
- * By default, characters with property Wide (W) or Fullwidth (F) are treated as wide (= 2)
- * and others are as narrow (= 1).
- * @param str Character string
- * @param widths An object that maps EAW properties to character widths
- * @return The computed width
- * @example
- * import { computeWidth } from "meaw";
- *
- * assert(computeWidth("Aあ🍣Ω") === 6);
- * // character width for each EAW property can be customized
- * assert(computeWidth("Aあ🍣Ω", { "A": 2 }) === 7);
- */
-function computeWidth(str, widths) {
- var width = 0;
- for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
- var char = str_1[_i];
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- char cannot be empty
- var eaw = getEAW(char);
- width += (widths && widths[eaw]) || defaultWidths[eaw];
- }
- return width;
+var defaultWidths = {
+ N: 1,
+ Na: 1,
+ W: 2,
+ F: 2,
+ H: 1,
+ A: 1,
+};
+/**
+ * Computes the width of a string based on the EAW properties of the characters.
+ * By default, characters with property Wide (W) or Fullwidth (F) are treated as wide (= 2)
+ * and others are as narrow (= 1).
+ * @param str Character string
+ * @param widths An object that maps EAW properties to character widths
+ * @return The computed width
+ * @example
+ * import { computeWidth } from "meaw";
+ *
+ * assert(computeWidth("Aあ🍣Ω") === 6);
+ * // character width for each EAW property can be customized
+ * assert(computeWidth("Aあ🍣Ω", { "A": 2 }) === 7);
+ */
+function computeWidth(str, widths) {
+ var width = 0;
+ for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {
+ var char = str_1[_i];
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- char cannot be empty
+ var eaw = getEAW(char);
+ width += (widths && widths[eaw]) || defaultWidths[eaw];
+ }
+ return width;
}
var lib = /*#__PURE__*/Object.freeze({
diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json
index 283b812..0012ee5 100644
--- a/.obsidian/workspace.json
+++ b/.obsidian/workspace.json
@@ -1,14 +1,14 @@
{
"main": {
- "id": "ee5d534d22980344",
+ "id": "f01e8bbaef56b69c",
"type": "split",
"children": [
{
- "id": "7c1eca489be03564",
+ "id": "091fed62dea5b5b6",
"type": "tabs",
"children": [
{
- "id": "54139872f1da29d8",
+ "id": "665aadb0f77f27a9",
"type": "leaf",
"state": {
"type": "markdown",
@@ -25,15 +25,15 @@
"direction": "vertical"
},
"left": {
- "id": "fc1e8907017830f9",
+ "id": "6c171c52cbcad916",
"type": "split",
"children": [
{
- "id": "9a60d4d5152c3311",
+ "id": "9bf43a9e69ff5a08",
"type": "tabs",
"children": [
{
- "id": "9341cdda69dbca7f",
+ "id": "3116c3bbc239bf7f",
"type": "leaf",
"state": {
"type": "file-explorer",
@@ -43,7 +43,7 @@
}
},
{
- "id": "54f47b860bc7ee13",
+ "id": "d67058f2a09b939c",
"type": "leaf",
"state": {
"type": "search",
@@ -58,7 +58,7 @@
}
},
{
- "id": "5550d38f8d962665",
+ "id": "544aa7940fd3e388",
"type": "leaf",
"state": {
"type": "bookmarks",
@@ -72,15 +72,15 @@
"width": 300
},
"right": {
- "id": "769dc607ac2c8f47",
+ "id": "25e5c9e758529eb3",
"type": "split",
"children": [
{
- "id": "bbb36cfce0e5c758",
+ "id": "abd4cf6c3399eb83",
"type": "tabs",
"children": [
{
- "id": "d5de186f06e30619",
+ "id": "7c7b4269a3822839",
"type": "leaf",
"state": {
"type": "backlink",
@@ -97,7 +97,7 @@
}
},
{
- "id": "1d0811a4b45529b8",
+ "id": "c6710a85cac8a363",
"type": "leaf",
"state": {
"type": "outgoing-link",
@@ -109,7 +109,7 @@
}
},
{
- "id": "1255c61dedfd1e84",
+ "id": "8987aa2f755b642e",
"type": "leaf",
"state": {
"type": "tag",
@@ -120,7 +120,7 @@
}
},
{
- "id": "0eb472a8f25f460b",
+ "id": "549b4760b2a97f41",
"type": "leaf",
"state": {
"type": "outline",
@@ -133,8 +133,7 @@
}
],
"direction": "horizontal",
- "width": 300,
- "collapsed": true
+ "width": 300
},
"left-ribbon": {
"hiddenItems": {
@@ -148,9 +147,8 @@
"obsidian-excalidraw-plugin:Create new drawing": false
}
},
- "active": "54139872f1da29d8",
+ "active": "665aadb0f77f27a9",
"lastOpenFiles": [
- "10.12 Chemie/! Chemie.md",
"README.md"
]
}
\ No newline at end of file
diff --git a/.obsidian/workspace.sync-conflict-20240917-212208-4CIB3I6.json b/.obsidian/workspace.sync-conflict-20240917-212208-4CIB3I6.json
new file mode 100644
index 0000000..283b812
--- /dev/null
+++ b/.obsidian/workspace.sync-conflict-20240917-212208-4CIB3I6.json
@@ -0,0 +1,156 @@
+{
+ "main": {
+ "id": "ee5d534d22980344",
+ "type": "split",
+ "children": [
+ {
+ "id": "7c1eca489be03564",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "54139872f1da29d8",
+ "type": "leaf",
+ "state": {
+ "type": "markdown",
+ "state": {
+ "file": "README.md",
+ "mode": "source",
+ "source": false
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "vertical"
+ },
+ "left": {
+ "id": "fc1e8907017830f9",
+ "type": "split",
+ "children": [
+ {
+ "id": "9a60d4d5152c3311",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "9341cdda69dbca7f",
+ "type": "leaf",
+ "state": {
+ "type": "file-explorer",
+ "state": {
+ "sortOrder": "alphabetical"
+ }
+ }
+ },
+ {
+ "id": "54f47b860bc7ee13",
+ "type": "leaf",
+ "state": {
+ "type": "search",
+ "state": {
+ "query": "",
+ "matchingCase": false,
+ "explainSearch": false,
+ "collapseAll": false,
+ "extraContext": false,
+ "sortOrder": "alphabetical"
+ }
+ }
+ },
+ {
+ "id": "5550d38f8d962665",
+ "type": "leaf",
+ "state": {
+ "type": "bookmarks",
+ "state": {}
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "horizontal",
+ "width": 300
+ },
+ "right": {
+ "id": "769dc607ac2c8f47",
+ "type": "split",
+ "children": [
+ {
+ "id": "bbb36cfce0e5c758",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "d5de186f06e30619",
+ "type": "leaf",
+ "state": {
+ "type": "backlink",
+ "state": {
+ "file": "README.md",
+ "collapseAll": false,
+ "extraContext": false,
+ "sortOrder": "alphabetical",
+ "showSearch": false,
+ "searchQuery": "",
+ "backlinkCollapsed": false,
+ "unlinkedCollapsed": true
+ }
+ }
+ },
+ {
+ "id": "1d0811a4b45529b8",
+ "type": "leaf",
+ "state": {
+ "type": "outgoing-link",
+ "state": {
+ "file": "README.md",
+ "linksCollapsed": false,
+ "unlinkedCollapsed": true
+ }
+ }
+ },
+ {
+ "id": "1255c61dedfd1e84",
+ "type": "leaf",
+ "state": {
+ "type": "tag",
+ "state": {
+ "sortOrder": "frequency",
+ "useHierarchy": true
+ }
+ }
+ },
+ {
+ "id": "0eb472a8f25f460b",
+ "type": "leaf",
+ "state": {
+ "type": "outline",
+ "state": {
+ "file": "README.md"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "horizontal",
+ "width": 300,
+ "collapsed": true
+ },
+ "left-ribbon": {
+ "hiddenItems": {
+ "switcher:Open quick switcher": false,
+ "graph:Open graph view": false,
+ "canvas:Create new canvas": false,
+ "daily-notes:Open today's daily note": false,
+ "templates:Insert template": false,
+ "command-palette:Open command palette": false,
+ "table-editor-obsidian:Advanced Tables Toolbar": false,
+ "obsidian-excalidraw-plugin:Create new drawing": false
+ }
+ },
+ "active": "54139872f1da29d8",
+ "lastOpenFiles": [
+ "10.12 Chemie/! Chemie.md",
+ "README.md"
+ ]
+}
\ No newline at end of file
diff --git a/.obsidian/workspace.sync-conflict-20240917-212320-4CIB3I6.json b/.obsidian/workspace.sync-conflict-20240917-212320-4CIB3I6.json
new file mode 100644
index 0000000..283b812
--- /dev/null
+++ b/.obsidian/workspace.sync-conflict-20240917-212320-4CIB3I6.json
@@ -0,0 +1,156 @@
+{
+ "main": {
+ "id": "ee5d534d22980344",
+ "type": "split",
+ "children": [
+ {
+ "id": "7c1eca489be03564",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "54139872f1da29d8",
+ "type": "leaf",
+ "state": {
+ "type": "markdown",
+ "state": {
+ "file": "README.md",
+ "mode": "source",
+ "source": false
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "vertical"
+ },
+ "left": {
+ "id": "fc1e8907017830f9",
+ "type": "split",
+ "children": [
+ {
+ "id": "9a60d4d5152c3311",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "9341cdda69dbca7f",
+ "type": "leaf",
+ "state": {
+ "type": "file-explorer",
+ "state": {
+ "sortOrder": "alphabetical"
+ }
+ }
+ },
+ {
+ "id": "54f47b860bc7ee13",
+ "type": "leaf",
+ "state": {
+ "type": "search",
+ "state": {
+ "query": "",
+ "matchingCase": false,
+ "explainSearch": false,
+ "collapseAll": false,
+ "extraContext": false,
+ "sortOrder": "alphabetical"
+ }
+ }
+ },
+ {
+ "id": "5550d38f8d962665",
+ "type": "leaf",
+ "state": {
+ "type": "bookmarks",
+ "state": {}
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "horizontal",
+ "width": 300
+ },
+ "right": {
+ "id": "769dc607ac2c8f47",
+ "type": "split",
+ "children": [
+ {
+ "id": "bbb36cfce0e5c758",
+ "type": "tabs",
+ "children": [
+ {
+ "id": "d5de186f06e30619",
+ "type": "leaf",
+ "state": {
+ "type": "backlink",
+ "state": {
+ "file": "README.md",
+ "collapseAll": false,
+ "extraContext": false,
+ "sortOrder": "alphabetical",
+ "showSearch": false,
+ "searchQuery": "",
+ "backlinkCollapsed": false,
+ "unlinkedCollapsed": true
+ }
+ }
+ },
+ {
+ "id": "1d0811a4b45529b8",
+ "type": "leaf",
+ "state": {
+ "type": "outgoing-link",
+ "state": {
+ "file": "README.md",
+ "linksCollapsed": false,
+ "unlinkedCollapsed": true
+ }
+ }
+ },
+ {
+ "id": "1255c61dedfd1e84",
+ "type": "leaf",
+ "state": {
+ "type": "tag",
+ "state": {
+ "sortOrder": "frequency",
+ "useHierarchy": true
+ }
+ }
+ },
+ {
+ "id": "0eb472a8f25f460b",
+ "type": "leaf",
+ "state": {
+ "type": "outline",
+ "state": {
+ "file": "README.md"
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "direction": "horizontal",
+ "width": 300,
+ "collapsed": true
+ },
+ "left-ribbon": {
+ "hiddenItems": {
+ "switcher:Open quick switcher": false,
+ "graph:Open graph view": false,
+ "canvas:Create new canvas": false,
+ "daily-notes:Open today's daily note": false,
+ "templates:Insert template": false,
+ "command-palette:Open command palette": false,
+ "table-editor-obsidian:Advanced Tables Toolbar": false,
+ "obsidian-excalidraw-plugin:Create new drawing": false
+ }
+ },
+ "active": "54139872f1da29d8",
+ "lastOpenFiles": [
+ "10.12 Chemie/! Chemie.md",
+ "README.md"
+ ]
+}
\ No newline at end of file