From 5205361ac07fd2cec760100b56c69b910c2f326a Mon Sep 17 00:00:00 2001 From: linrk Date: Wed, 23 Apr 2025 19:50:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A3=AE=E8=93=9D=E5=B0=8F=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .hbuilderx/launch.json | 16 + App.vue | 20 + components/customTabBar/customTabBar.vue | 158 + .../helang-compress/helang-compress.vue | 188 + .../ren-dropdown-filter.vue | 249 + components/yankai-cropper/cropper.vue | 627 +++ css/common.css | 78 + index.html | 20 + main.js | 29 + manifest.json | 72 + node_modules/.package-lock.json | 12 + node_modules/decimal.js/LICENCE.md | 23 + node_modules/decimal.js/README.md | 246 + node_modules/decimal.js/decimal.d.ts | 299 + node_modules/decimal.js/decimal.js | 4934 +++++++++++++++++ node_modules/decimal.js/decimal.mjs | 4898 ++++++++++++++++ node_modules/decimal.js/package.json | 55 + package-lock.json | 17 + package.json | 5 + pages.json | 80 + pages/display/display.vue | 286 + pages/display/index.css | 137 + pages/home/home.vue | 444 ++ pages/home/index.css | 172 + pages/mine/index.css | 173 + pages/mine/mine.vue | 181 + pages/myPhoto/index.css | 62 + pages/myPhoto/myPhoto.vue | 72 + pages/selectPhoto/index.css | 119 + pages/selectPhoto/selectPhoto.vue | 368 ++ static/btn_down_140@2x.png | Bin 0 -> 3080 bytes static/btn_share_140@2x.png | Bin 0 -> 3020 bytes static/btn_video_slider@2x.png | Bin 0 -> 532 bytes static/center/user_img2.png | Bin 0 -> 153549 bytes static/icon/icon_Home_n@3x_a.png | Bin 0 -> 4675 bytes static/icon/icon_Home_n@3x_da.png | Bin 0 -> 2649 bytes static/icon/icon_我的_n@3x_a.png | Bin 0 -> 5227 bytes static/icon/icon_我的_n@3x_da.png | Bin 0 -> 3034 bytes static/icon_swiper.png | Bin 0 -> 1545 bytes static/img_video_nor@2x.png | Bin 0 -> 289 bytes static/img_video_sel@2x.png | Bin 0 -> 2066 bytes static/logo.png | Bin 0 -> 4023 bytes uni.scss | 76 + uni_modules/liu-progressbar/changelog.md | 8 + .../liu-progressbar/liu-progressbar.vue | 139 + uni_modules/liu-progressbar/license.md | 6 + uni_modules/liu-progressbar/package.json | 83 + uni_modules/liu-progressbar/readme.md | 44 + uni_modules/uni-popup/changelog.md | 84 + .../components/uni-popup-dialog/keypress.js | 45 + .../uni-popup-dialog/uni-popup-dialog.vue | 316 ++ .../uni-popup-message/uni-popup-message.vue | 143 + .../uni-popup-pay/uni-popup-pay.vue | 279 + .../uni-popup-select/uni-popup-select.vue | 338 ++ .../uni-popup-share/uni-popup-share.vue | 286 + .../components/uni-popup/i18n/en.json | 7 + .../components/uni-popup/i18n/index.js | 8 + .../components/uni-popup/i18n/zh-Hans.json | 7 + .../components/uni-popup/i18n/zh-Hant.json | 7 + .../components/uni-popup/keypress.js | 45 + .../uni-popup/components/uni-popup/popup.js | 26 + .../components/uni-popup/uni-popup.uvue | 90 + .../components/uni-popup/uni-popup.vue | 504 ++ uni_modules/uni-popup/package.json | 88 + uni_modules/uni-popup/readme.md | 17 + uni_modules/uni-scss/changelog.md | 8 + uni_modules/uni-scss/index.scss | 1 + uni_modules/uni-scss/package.json | 82 + uni_modules/uni-scss/readme.md | 4 + uni_modules/uni-scss/styles/index.scss | 7 + .../uni-scss/styles/setting/_border.scss | 3 + .../uni-scss/styles/setting/_color.scss | 66 + .../uni-scss/styles/setting/_radius.scss | 55 + .../uni-scss/styles/setting/_space.scss | 56 + .../uni-scss/styles/setting/_styles.scss | 167 + .../uni-scss/styles/setting/_text.scss | 24 + .../uni-scss/styles/setting/_variables.scss | 146 + .../uni-scss/styles/tools/functions.scss | 19 + uni_modules/uni-scss/theme.scss | 31 + uni_modules/uni-scss/variables.scss | 62 + uni_modules/uni-transition/changelog.md | 24 + .../uni-transition/createAnimation.js | 131 + .../uni-transition/uni-transition.vue | 286 + uni_modules/uni-transition/package.json | 85 + uni_modules/uni-transition/readme.md | 11 + uni_modules/zero-loading/changelog.md | 21 + .../zero-loading/static/loading-annulus.vue | 52 + .../zero-loading/static/loading-atom.vue | 115 + .../zero-loading/static/loading-bounce.vue | 80 + .../zero-loading/static/loading-circle.vue | 90 + .../zero-loading/static/loading-eyes.vue | 80 + .../zero-loading/static/loading-gear.vue | 126 + .../zero-loading/static/loading-love.vue | 210 + .../zero-loading/static/loading-pulse.vue | 64 + .../zero-loading/static/loading-radar.vue | 137 + .../zero-loading/static/loading-sun.vue | 148 + .../zero-loading/static/loading-sword.vue | 87 + .../zero-loading/static/loading-triangle.vue | 86 + .../components/zero-loading/zero-loading.vue | 134 + uni_modules/zero-loading/package.json | 80 + uni_modules/zero-loading/readme.md | 60 + .../components/zero-privacy/zero-privacy.vue | 314 ++ uni_modules/zero-privacy/package.json | 85 + utils/calculate/calculate.js | 28 + utils/timeUtil/timeUtil.js | 15 + utils/uploadToAliOss/Base64.js | 132 + utils/uploadToAliOss/config.js | 8 + utils/uploadToAliOss/crypto.js | 185 + utils/uploadToAliOss/hmac.js | 41 + utils/uploadToAliOss/sha1.js | 86 + utils/uploadToAliOss/uploadAliyun.js | 86 + 111 files changed, 20504 insertions(+) create mode 100644 .hbuilderx/launch.json create mode 100644 App.vue create mode 100644 components/customTabBar/customTabBar.vue create mode 100644 components/helang-compress/helang-compress.vue create mode 100644 components/ren-dropdown-filter/ren-dropdown-filter.vue create mode 100644 components/yankai-cropper/cropper.vue create mode 100644 css/common.css create mode 100644 index.html create mode 100644 main.js create mode 100644 manifest.json create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/decimal.js/LICENCE.md create mode 100644 node_modules/decimal.js/README.md create mode 100644 node_modules/decimal.js/decimal.d.ts create mode 100644 node_modules/decimal.js/decimal.js create mode 100644 node_modules/decimal.js/decimal.mjs create mode 100644 node_modules/decimal.js/package.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 pages.json create mode 100644 pages/display/display.vue create mode 100644 pages/display/index.css create mode 100644 pages/home/home.vue create mode 100644 pages/home/index.css create mode 100644 pages/mine/index.css create mode 100644 pages/mine/mine.vue create mode 100644 pages/myPhoto/index.css create mode 100644 pages/myPhoto/myPhoto.vue create mode 100644 pages/selectPhoto/index.css create mode 100644 pages/selectPhoto/selectPhoto.vue create mode 100644 static/btn_down_140@2x.png create mode 100644 static/btn_share_140@2x.png create mode 100644 static/btn_video_slider@2x.png create mode 100644 static/center/user_img2.png create mode 100644 static/icon/icon_Home_n@3x_a.png create mode 100644 static/icon/icon_Home_n@3x_da.png create mode 100644 static/icon/icon_我的_n@3x_a.png create mode 100644 static/icon/icon_我的_n@3x_da.png create mode 100644 static/icon_swiper.png create mode 100644 static/img_video_nor@2x.png create mode 100644 static/img_video_sel@2x.png create mode 100644 static/logo.png create mode 100644 uni.scss create mode 100644 uni_modules/liu-progressbar/changelog.md create mode 100644 uni_modules/liu-progressbar/components/liu-progressbar/liu-progressbar.vue create mode 100644 uni_modules/liu-progressbar/license.md create mode 100644 uni_modules/liu-progressbar/package.json create mode 100644 uni_modules/liu-progressbar/readme.md create mode 100644 uni_modules/uni-popup/changelog.md create mode 100644 uni_modules/uni-popup/components/uni-popup-dialog/keypress.js create mode 100644 uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue create mode 100644 uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue create mode 100644 uni_modules/uni-popup/components/uni-popup-pay/uni-popup-pay.vue create mode 100644 uni_modules/uni-popup/components/uni-popup-select/uni-popup-select.vue create mode 100644 uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/en.json create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/index.js create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json create mode 100644 uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json create mode 100644 uni_modules/uni-popup/components/uni-popup/keypress.js create mode 100644 uni_modules/uni-popup/components/uni-popup/popup.js create mode 100644 uni_modules/uni-popup/components/uni-popup/uni-popup.uvue create mode 100644 uni_modules/uni-popup/components/uni-popup/uni-popup.vue create mode 100644 uni_modules/uni-popup/package.json create mode 100644 uni_modules/uni-popup/readme.md create mode 100644 uni_modules/uni-scss/changelog.md create mode 100644 uni_modules/uni-scss/index.scss create mode 100644 uni_modules/uni-scss/package.json create mode 100644 uni_modules/uni-scss/readme.md create mode 100644 uni_modules/uni-scss/styles/index.scss create mode 100644 uni_modules/uni-scss/styles/setting/_border.scss create mode 100644 uni_modules/uni-scss/styles/setting/_color.scss create mode 100644 uni_modules/uni-scss/styles/setting/_radius.scss create mode 100644 uni_modules/uni-scss/styles/setting/_space.scss create mode 100644 uni_modules/uni-scss/styles/setting/_styles.scss create mode 100644 uni_modules/uni-scss/styles/setting/_text.scss create mode 100644 uni_modules/uni-scss/styles/setting/_variables.scss create mode 100644 uni_modules/uni-scss/styles/tools/functions.scss create mode 100644 uni_modules/uni-scss/theme.scss create mode 100644 uni_modules/uni-scss/variables.scss create mode 100644 uni_modules/uni-transition/changelog.md create mode 100644 uni_modules/uni-transition/components/uni-transition/createAnimation.js create mode 100644 uni_modules/uni-transition/components/uni-transition/uni-transition.vue create mode 100644 uni_modules/uni-transition/package.json create mode 100644 uni_modules/uni-transition/readme.md create mode 100644 uni_modules/zero-loading/changelog.md create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-love.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/static/loading-triangle.vue create mode 100644 uni_modules/zero-loading/components/zero-loading/zero-loading.vue create mode 100644 uni_modules/zero-loading/package.json create mode 100644 uni_modules/zero-loading/readme.md create mode 100644 uni_modules/zero-privacy/components/zero-privacy/zero-privacy.vue create mode 100644 uni_modules/zero-privacy/package.json create mode 100644 utils/calculate/calculate.js create mode 100644 utils/timeUtil/timeUtil.js create mode 100644 utils/uploadToAliOss/Base64.js create mode 100644 utils/uploadToAliOss/config.js create mode 100644 utils/uploadToAliOss/crypto.js create mode 100644 utils/uploadToAliOss/hmac.js create mode 100644 utils/uploadToAliOss/sha1.js create mode 100644 utils/uploadToAliOss/uploadAliyun.js diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json new file mode 100644 index 0000000..81f13f4 --- /dev/null +++ b/.hbuilderx/launch.json @@ -0,0 +1,16 @@ +{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ + // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 + "version": "0.0", + "configurations": [{ + "default" : + { + "launchtype" : "local" + }, + "mp-weixin" : + { + "launchtype" : "local" + }, + "type" : "uniCloud" + } + ] +} diff --git a/App.vue b/App.vue new file mode 100644 index 0000000..1753691 --- /dev/null +++ b/App.vue @@ -0,0 +1,20 @@ + + + diff --git a/components/customTabBar/customTabBar.vue b/components/customTabBar/customTabBar.vue new file mode 100644 index 0000000..726cc03 --- /dev/null +++ b/components/customTabBar/customTabBar.vue @@ -0,0 +1,158 @@ + + + + + diff --git a/components/helang-compress/helang-compress.vue b/components/helang-compress/helang-compress.vue new file mode 100644 index 0000000..b4c5568 --- /dev/null +++ b/components/helang-compress/helang-compress.vue @@ -0,0 +1,188 @@ + + + + + diff --git a/components/ren-dropdown-filter/ren-dropdown-filter.vue b/components/ren-dropdown-filter/ren-dropdown-filter.vue new file mode 100644 index 0000000..5796cb5 --- /dev/null +++ b/components/ren-dropdown-filter/ren-dropdown-filter.vue @@ -0,0 +1,249 @@ + + + + + diff --git a/components/yankai-cropper/cropper.vue b/components/yankai-cropper/cropper.vue new file mode 100644 index 0000000..18c6eef --- /dev/null +++ b/components/yankai-cropper/cropper.vue @@ -0,0 +1,627 @@ + + + + diff --git a/css/common.css b/css/common.css new file mode 100644 index 0000000..2ccc3ba --- /dev/null +++ b/css/common.css @@ -0,0 +1,78 @@ +body *, +page view { + box-sizing: border-box; + flex-shrink: 0; +} +body { + font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma, + Arial, PingFang SC-Light, Microsoft YaHei; + margin: 0; +} +button { + margin: 0; + padding: 0; + border: 1px solid transparent; + outline: none; + background-color: transparent; +} + +button:active { + opacity: 0.6; +} +.flex-col { + display: flex; + flex-direction: column; +} +.flex-row { + display: flex; + flex-direction: row; +} +.justify-start { + display: flex; + justify-content: flex-start; +} +.justify-center { + display: flex; + justify-content: center; +} + +.justify-end { + display: flex; + justify-content: flex-end; +} +.justify-evenly { + display: flex; + justify-content: space-evenly; +} +.justify-around { + display: flex; + justify-content: space-around; +} +.justify-between { + display: flex; + justify-content: space-between; +} +.align-start { + display: flex; + align-items: flex-start; +} +.align-center { + display: flex; + align-items: center; +} +.align-end { + display: flex; + align-items: flex-end; +} + +.uni-bg-red { + background-color: #ff5a5f; +} + +.uni-bg-green { + background-color: #09bb07; +} + +.uni-bg-blue { + background-color: #007aff; +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..c3ff205 --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + +
+ + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..1ce2c09 --- /dev/null +++ b/main.js @@ -0,0 +1,29 @@ +import App from './App' + +// #ifndef VUE3 +import Vue from 'vue' +Vue.config.productionTip = false +App.mpType = 'app' +const app = new Vue({ + ...App +}) +app.$mount() +// #endif + +// #ifdef VUE3 +import { createSSRApp } from 'vue' +export function createApp() { + const app = createSSRApp(App) + return { + app + } +} +// #endif + +if( __wxConfig.envVersion == 'release' ) { + Vue.prototype.java_http_url = 'https://t-zhipai-server.humengfilms.com:8101' + Vue.prototype.pay_http_url = 'https://pay.humengfilms.com:9007' +} else { + Vue.prototype.java_http_url = 'https://s101.magichairai.com:9080' + Vue.prototype.pay_http_url = 'https://s101.magichairai.com:9475' +} \ No newline at end of file diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..6297264 --- /dev/null +++ b/manifest.json @@ -0,0 +1,72 @@ +{ + "name" : "smart-camera", + "appid" : "__UNI__A50597F", + "description" : "", + "versionName" : "1.0.0", + "versionCode" : "100", + "transformPx" : false, + /* 5+App特有相关 */ + "app-plus" : { + "usingComponents" : true, + "nvueStyleCompiler" : "uni-app", + "compilerVersion" : 3, + "splashscreen" : { + "alwaysShowBeforeRender" : true, + "waiting" : true, + "autoclose" : true, + "delay" : 0 + }, + /* 模块配置 */ + "modules" : {}, + /* 应用发布信息 */ + "distribute" : { + /* android打包配置 */ + "android" : { + "permissions" : [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "" + ] + }, + /* ios打包配置 */ + "ios" : {}, + /* SDK配置 */ + "sdkConfigs" : {} + } + }, + /* 快应用特有相关 */ + "quickapp" : {}, + /* 小程序特有相关 */ + "mp-weixin" : { + "appid" : "wx9d720897d2a84948", + "setting" : { + "urlCheck" : false + }, + "usingComponents" : true + }, + "mp-alipay" : { + "usingComponents" : true + }, + "mp-baidu" : { + "usingComponents" : true + }, + "mp-toutiao" : { + "usingComponents" : true + }, + "uniStatistics" : { + "enable" : false + }, + "vueVersion" : "2" +} diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..b728651 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,12 @@ +{ + "name": "smart-camera", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + } + } +} diff --git a/node_modules/decimal.js/LICENCE.md b/node_modules/decimal.js/LICENCE.md new file mode 100644 index 0000000..1063109 --- /dev/null +++ b/node_modules/decimal.js/LICENCE.md @@ -0,0 +1,23 @@ +The MIT Licence. + +Copyright (c) 2022 Michael Mclaughlin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/node_modules/decimal.js/README.md b/node_modules/decimal.js/README.md new file mode 100644 index 0000000..1d02eb7 --- /dev/null +++ b/node_modules/decimal.js/README.md @@ -0,0 +1,246 @@ +![decimal.js](https://raw.githubusercontent.com/MikeMcl/decimal.js/gh-pages/decimaljs.png) + +An arbitrary-precision Decimal type for JavaScript. + +[![npm version](https://img.shields.io/npm/v/decimal.js.svg)](https://www.npmjs.com/package/decimal.js) +[![npm downloads](https://img.shields.io/npm/dw/decimal.js)](https://www.npmjs.com/package/decimal.js) +[![Build Status](https://travis-ci.org/MikeMcl/decimal.js.svg)](https://travis-ci.org/MikeMcl/decimal.js) +[![CDNJS](https://img.shields.io/cdnjs/v/decimal.js.svg)](https://cdnjs.com/libraries/decimal.js) + +
+ +## Features + + - Integers and floats + - Simple but full-featured API + - Replicates many of the methods of JavaScript's `Number.prototype` and `Math` objects + - Also handles hexadecimal, binary and octal values + - Faster, smaller, and perhaps easier to use than JavaScript versions of Java's BigDecimal + - No dependencies + - Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only + - Comprehensive [documentation](https://mikemcl.github.io/decimal.js/) and test set + - Used under the hood by [math.js](https://github.com/josdejong/mathjs) + - Includes a TypeScript declaration file: *decimal.d.ts* + +![API](https://raw.githubusercontent.com/MikeMcl/decimal.js/gh-pages/API.png) + +The library is similar to [bignumber.js](https://github.com/MikeMcl/bignumber.js/), but here +precision is specified in terms of significant digits rather than decimal places, and all +calculations are rounded to the precision (similar to Python's decimal module) rather than just +those involving division. + +This library also adds the trigonometric functions, among others, and supports non-integer powers, +which makes it a significantly larger library than *bignumber.js* and the even smaller +[big.js](https://github.com/MikeMcl/big.js/). + +For a lighter version of this library without the trigonometric functions see +[decimal.js-light](https://github.com/MikeMcl/decimal.js-light/). + +## Load + +The library is the single JavaScript file *decimal.js* or ES module *decimal.mjs*. + +Browser: + +```html + + + +``` + +[Node.js](https://nodejs.org): + +```bash +npm install decimal.js +``` +```js +const Decimal = require('decimal.js'); + +import Decimal from 'decimal.js'; + +import {Decimal} from 'decimal.js'; +``` + +## Use + +*In all examples below, semicolons and `toString` calls are not shown. +If a commented-out value is in quotes it means `toString` has been called on the preceding expression.* + +The library exports a single constructor function, `Decimal`, which expects a single argument that is a number, string or Decimal instance. + +```js +x = new Decimal(123.4567) +y = new Decimal('123456.7e-3') +z = new Decimal(x) +x.equals(y) && y.equals(z) && x.equals(z) // true +``` + +If using values with more than a few digits, it is recommended to pass strings rather than numbers to avoid a potential loss of precision. + +```js +// Precision loss from using numeric literals with more than 15 significant digits. +new Decimal(1.0000000000000001) // '1' +new Decimal(88259496234518.57) // '88259496234518.56' +new Decimal(99999999999999999999) // '100000000000000000000' + +// Precision loss from using numeric literals outside the range of Number values. +new Decimal(2e+308) // 'Infinity' +new Decimal(1e-324) // '0' + +// Precision loss from the unexpected result of arithmetic with Number values. +new Decimal(0.7 + 0.1) // '0.7999999999999999' +``` + +As with JavaScript numbers, strings can contain underscores as separators to improve readability. + +```js +x = new Decimal('2_147_483_647') +``` + +String values in binary, hexadecimal or octal notation are also accepted if the appropriate prefix is included. + +```js +x = new Decimal('0xff.f') // '255.9375' +y = new Decimal('0b10101100') // '172' +z = x.plus(y) // '427.9375' + +z.toBinary() // '0b110101011.1111' +z.toBinary(13) // '0b1.101010111111p+8' + +// Using binary exponential notation to create a Decimal with the value of `Number.MAX_VALUE`. +x = new Decimal('0b1.1111111111111111111111111111111111111111111111111111p+1023') +// '1.7976931348623157081e+308' +``` + +Decimal instances are immutable in the sense that they are not changed by their methods. + +```js +0.3 - 0.1 // 0.19999999999999998 +x = new Decimal(0.3) +x.minus(0.1) // '0.2' +x // '0.3' +``` + +The methods that return a Decimal can be chained. + +```js +x.dividedBy(y).plus(z).times(9).floor() +x.times('1.23456780123456789e+9').plus(9876.5432321).dividedBy('4444562598.111772').ceil() +``` + +Many method names have a shorter alias. + +```js +x.squareRoot().dividedBy(y).toPower(3).equals(x.sqrt().div(y).pow(3)) // true +x.comparedTo(y.modulo(z).negated() === x.cmp(y.mod(z).neg()) // true +``` + +Most of the methods of JavaScript's `Number.prototype` and `Math` objects are replicated. + +```js +x = new Decimal(255.5) +x.toExponential(5) // '2.55500e+2' +x.toFixed(5) // '255.50000' +x.toPrecision(5) // '255.50' + +Decimal.sqrt('6.98372465832e+9823') // '8.3568682281821340204e+4911' +Decimal.pow(2, 0.0979843) // '1.0702770511687781839' + +// Using `toFixed()` to avoid exponential notation: +x = new Decimal('0.0000001') +x.toString() // '1e-7' +x.toFixed() // '0.0000001' +``` + +And there are `isNaN` and `isFinite` methods, as `NaN` and `Infinity` are valid `Decimal` values. + +```js +x = new Decimal(NaN) // 'NaN' +y = new Decimal(Infinity) // 'Infinity' +x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite() // true +``` + +There is also a `toFraction` method with an optional *maximum denominator* argument. + +```js +z = new Decimal(355) +pi = z.dividedBy(113) // '3.1415929204' +pi.toFraction() // [ '7853982301', '2500000000' ] +pi.toFraction(1000) // [ '355', '113' ] +``` + +All calculations are rounded according to the number of significant digits and rounding mode specified +by the `precision` and `rounding` properties of the Decimal constructor. + +For advanced usage, multiple Decimal constructors can be created, each with their own independent +configuration which applies to all Decimal numbers created from it. + +```js +// Set the precision and rounding of the default Decimal constructor +Decimal.set({ precision: 5, rounding: 4 }) + +// Create another Decimal constructor, optionally passing in a configuration object +Dec = Decimal.clone({ precision: 9, rounding: 1 }) + +x = new Decimal(5) +y = new Dec(5) + +x.div(3) // '1.6667' +y.div(3) // '1.66666666' +``` + +The value of a Decimal is stored in a floating point format in terms of its digits, exponent and sign, but these properties should be considered read-only. + +```js +x = new Decimal(-12345.67); +x.d // [ 12345, 6700000 ] digits (base 10000000) +x.e // 4 exponent (base 10) +x.s // -1 sign +``` + +For further information see the [API](http://mikemcl.github.io/decimal.js/) reference in the *doc* directory. + +## Test + +To run the tests using Node.js from the root directory: + +```bash +npm test +``` + +Each separate test module can also be executed individually, for example: + +```bash +node test/modules/toFraction +``` + +To run the tests in a browser, open *test/test.html*. + +## Minify + +Two minification examples: + +Using [uglify-js](https://github.com/mishoo/UglifyJS) to minify the *decimal.js* file: + +```bash +npm install uglify-js -g +uglifyjs decimal.js --source-map url=decimal.min.js.map -c -m -o decimal.min.js +``` + +Using [terser](https://github.com/terser/terser) to minify the ES module version, *decimal.mjs*: + +```bash +npm install terser -g +terser decimal.mjs --source-map url=decimal.min.mjs.map -c -m --toplevel -o decimal.min.mjs +``` + +```js +import Decimal from './decimal.min.mjs'; +``` + +## Licence + +[The MIT Licence (Expat).](LICENCE.md) diff --git a/node_modules/decimal.js/decimal.d.ts b/node_modules/decimal.js/decimal.d.ts new file mode 100644 index 0000000..0fbc7b2 --- /dev/null +++ b/node_modules/decimal.js/decimal.d.ts @@ -0,0 +1,299 @@ +// Type definitions for decimal.js >=7.0.0 +// Project: https://github.com/MikeMcl/decimal.js +// Definitions by: Michael Mclaughlin +// Definitions: https://github.com/MikeMcl/decimal.js +// +// Documentation: http://mikemcl.github.io/decimal.js/ +// +// Exports: +// +// class Decimal (default export) +// type Decimal.Constructor +// type Decimal.Instance +// type Decimal.Modulo +// type Decimal.Rounding +// type Decimal.Value +// interface Decimal.Config +// +// Example (alternative syntax commented-out): +// +// import {Decimal} from "decimal.js" +// //import Decimal from "decimal.js" +// +// let r: Decimal.Rounding = Decimal.ROUND_UP; +// let c: Decimal.Configuration = {precision: 4, rounding: r}; +// Decimal.set(c); +// let v: Decimal.Value = '12345.6789'; +// let d: Decimal = new Decimal(v); +// //let d: Decimal.Instance = new Decimal(v); +// +// The use of compiler option `--strictNullChecks` is recommended. + +export default Decimal; + +export namespace Decimal { + export type Constructor = typeof Decimal; + export type Instance = Decimal; + export type Rounding = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8; + export type Modulo = Rounding | 9; + export type Value = string | number | Decimal; + + // http://mikemcl.github.io/decimal.js/#constructor-properties + export interface Config { + precision?: number; + rounding?: Rounding; + toExpNeg?: number; + toExpPos?: number; + minE?: number; + maxE?: number; + crypto?: boolean; + modulo?: Modulo; + defaults?: boolean; + } +} + +export declare class Decimal { + readonly d: number[]; + readonly e: number; + readonly s: number; + + constructor(n: Decimal.Value); + + absoluteValue(): Decimal; + abs(): Decimal; + + ceil(): Decimal; + + clampedTo(min: Decimal.Value, max: Decimal.Value): Decimal; + clamp(min: Decimal.Value, max: Decimal.Value): Decimal; + + comparedTo(n: Decimal.Value): number; + cmp(n: Decimal.Value): number; + + cosine(): Decimal; + cos(): Decimal; + + cubeRoot(): Decimal; + cbrt(): Decimal; + + decimalPlaces(): number; + dp(): number; + + dividedBy(n: Decimal.Value): Decimal; + div(n: Decimal.Value): Decimal; + + dividedToIntegerBy(n: Decimal.Value): Decimal; + divToInt(n: Decimal.Value): Decimal; + + equals(n: Decimal.Value): boolean; + eq(n: Decimal.Value): boolean; + + floor(): Decimal; + + greaterThan(n: Decimal.Value): boolean; + gt(n: Decimal.Value): boolean; + + greaterThanOrEqualTo(n: Decimal.Value): boolean; + gte(n: Decimal.Value): boolean; + + hyperbolicCosine(): Decimal; + cosh(): Decimal; + + hyperbolicSine(): Decimal; + sinh(): Decimal; + + hyperbolicTangent(): Decimal; + tanh(): Decimal; + + inverseCosine(): Decimal; + acos(): Decimal; + + inverseHyperbolicCosine(): Decimal; + acosh(): Decimal; + + inverseHyperbolicSine(): Decimal; + asinh(): Decimal; + + inverseHyperbolicTangent(): Decimal; + atanh(): Decimal; + + inverseSine(): Decimal; + asin(): Decimal; + + inverseTangent(): Decimal; + atan(): Decimal; + + isFinite(): boolean; + + isInteger(): boolean; + isInt(): boolean; + + isNaN(): boolean; + + isNegative(): boolean; + isNeg(): boolean; + + isPositive(): boolean; + isPos(): boolean; + + isZero(): boolean; + + lessThan(n: Decimal.Value): boolean; + lt(n: Decimal.Value): boolean; + + lessThanOrEqualTo(n: Decimal.Value): boolean; + lte(n: Decimal.Value): boolean; + + logarithm(n?: Decimal.Value): Decimal; + log(n?: Decimal.Value): Decimal; + + minus(n: Decimal.Value): Decimal; + sub(n: Decimal.Value): Decimal; + + modulo(n: Decimal.Value): Decimal; + mod(n: Decimal.Value): Decimal; + + naturalExponential(): Decimal; + exp(): Decimal; + + naturalLogarithm(): Decimal; + ln(): Decimal; + + negated(): Decimal; + neg(): Decimal; + + plus(n: Decimal.Value): Decimal; + add(n: Decimal.Value): Decimal; + + precision(includeZeros?: boolean): number; + sd(includeZeros?: boolean): number; + + round(): Decimal; + + sine() : Decimal; + sin() : Decimal; + + squareRoot(): Decimal; + sqrt(): Decimal; + + tangent() : Decimal; + tan() : Decimal; + + times(n: Decimal.Value): Decimal; + mul(n: Decimal.Value) : Decimal; + + toBinary(significantDigits?: number): string; + toBinary(significantDigits: number, rounding: Decimal.Rounding): string; + + toDecimalPlaces(decimalPlaces?: number): Decimal; + toDecimalPlaces(decimalPlaces: number, rounding: Decimal.Rounding): Decimal; + toDP(decimalPlaces?: number): Decimal; + toDP(decimalPlaces: number, rounding: Decimal.Rounding): Decimal; + + toExponential(decimalPlaces?: number): string; + toExponential(decimalPlaces: number, rounding: Decimal.Rounding): string; + + toFixed(decimalPlaces?: number): string; + toFixed(decimalPlaces: number, rounding: Decimal.Rounding): string; + + toFraction(max_denominator?: Decimal.Value): Decimal[]; + + toHexadecimal(significantDigits?: number): string; + toHexadecimal(significantDigits: number, rounding: Decimal.Rounding): string; + toHex(significantDigits?: number): string; + toHex(significantDigits: number, rounding?: Decimal.Rounding): string; + + toJSON(): string; + + toNearest(n: Decimal.Value, rounding?: Decimal.Rounding): Decimal; + + toNumber(): number; + + toOctal(significantDigits?: number): string; + toOctal(significantDigits: number, rounding: Decimal.Rounding): string; + + toPower(n: Decimal.Value): Decimal; + pow(n: Decimal.Value): Decimal; + + toPrecision(significantDigits?: number): string; + toPrecision(significantDigits: number, rounding: Decimal.Rounding): string; + + toSignificantDigits(significantDigits?: number): Decimal; + toSignificantDigits(significantDigits: number, rounding: Decimal.Rounding): Decimal; + toSD(significantDigits?: number): Decimal; + toSD(significantDigits: number, rounding: Decimal.Rounding): Decimal; + + toString(): string; + + truncated(): Decimal; + trunc(): Decimal; + + valueOf(): string; + + static abs(n: Decimal.Value): Decimal; + static acos(n: Decimal.Value): Decimal; + static acosh(n: Decimal.Value): Decimal; + static add(x: Decimal.Value, y: Decimal.Value): Decimal; + static asin(n: Decimal.Value): Decimal; + static asinh(n: Decimal.Value): Decimal; + static atan(n: Decimal.Value): Decimal; + static atanh(n: Decimal.Value): Decimal; + static atan2(y: Decimal.Value, x: Decimal.Value): Decimal; + static cbrt(n: Decimal.Value): Decimal; + static ceil(n: Decimal.Value): Decimal; + static clamp(n: Decimal.Value, min: Decimal.Value, max: Decimal.Value): Decimal; + static clone(object?: Decimal.Config): Decimal.Constructor; + static config(object: Decimal.Config): Decimal.Constructor; + static cos(n: Decimal.Value): Decimal; + static cosh(n: Decimal.Value): Decimal; + static div(x: Decimal.Value, y: Decimal.Value): Decimal; + static exp(n: Decimal.Value): Decimal; + static floor(n: Decimal.Value): Decimal; + static hypot(...n: Decimal.Value[]): Decimal; + static isDecimal(object: any): object is Decimal; + static ln(n: Decimal.Value): Decimal; + static log(n: Decimal.Value, base?: Decimal.Value): Decimal; + static log2(n: Decimal.Value): Decimal; + static log10(n: Decimal.Value): Decimal; + static max(...n: Decimal.Value[]): Decimal; + static min(...n: Decimal.Value[]): Decimal; + static mod(x: Decimal.Value, y: Decimal.Value): Decimal; + static mul(x: Decimal.Value, y: Decimal.Value): Decimal; + static noConflict(): Decimal.Constructor; // Browser only + static pow(base: Decimal.Value, exponent: Decimal.Value): Decimal; + static random(significantDigits?: number): Decimal; + static round(n: Decimal.Value): Decimal; + static set(object: Decimal.Config): Decimal.Constructor; + static sign(n: Decimal.Value): number; + static sin(n: Decimal.Value): Decimal; + static sinh(n: Decimal.Value): Decimal; + static sqrt(n: Decimal.Value): Decimal; + static sub(x: Decimal.Value, y: Decimal.Value): Decimal; + static sum(...n: Decimal.Value[]): Decimal; + static tan(n: Decimal.Value): Decimal; + static tanh(n: Decimal.Value): Decimal; + static trunc(n: Decimal.Value): Decimal; + + static readonly default?: Decimal.Constructor; + static readonly Decimal?: Decimal.Constructor; + + static readonly precision: number; + static readonly rounding: Decimal.Rounding; + static readonly toExpNeg: number; + static readonly toExpPos: number; + static readonly minE: number; + static readonly maxE: number; + static readonly crypto: boolean; + static readonly modulo: Decimal.Modulo; + + static readonly ROUND_UP: 0; + static readonly ROUND_DOWN: 1; + static readonly ROUND_CEIL: 2; + static readonly ROUND_FLOOR: 3; + static readonly ROUND_HALF_UP: 4; + static readonly ROUND_HALF_DOWN: 5; + static readonly ROUND_HALF_EVEN: 6; + static readonly ROUND_HALF_CEIL: 7; + static readonly ROUND_HALF_FLOOR: 8; + static readonly EUCLID: 9; +} diff --git a/node_modules/decimal.js/decimal.js b/node_modules/decimal.js/decimal.js new file mode 100644 index 0000000..aa6526a --- /dev/null +++ b/node_modules/decimal.js/decimal.js @@ -0,0 +1,4934 @@ +;(function (globalScope) { + 'use strict'; + + + /*! + * 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, + i = 1, + pr = Ctor.precision, + k = Math.ceil(pr / LOG_BASE); + + external = false; + x2 = x.times(x); + u = new Ctor(y); + + for (;;) { + t = divide(u.times(x2), new Ctor(n++ * n++), pr, 1); + u = isHyperbolic ? y.plus(t) : y.minus(t); + y = divide(t.times(x2), new Ctor(n++ * n++), pr, 1); + t = u.plus(y); + + if (t.d[k] !== void 0) { + for (j = k; t.d[j] === u.d[j] && j--;); + if (j == -1) break; + } + + j = u; + u = y; + y = t; + t = j; + i++; + } + + external = true; + t.d.length = k + 1; + + return t; + } + + + // Exponent e must be positive and non-zero. + function tinyPow(b, e) { + var n = b; + while (--e) n *= b; + return n; + } + + + // Return the absolute value of `x` reduced to less than or equal to half pi. + function toLessThanHalfPi(Ctor, x) { + var t, + isNeg = x.s < 0, + pi = getPi(Ctor, Ctor.precision, 1), + halfPi = pi.times(0.5); + + x = x.abs(); + + if (x.lte(halfPi)) { + quadrant = isNeg ? 4 : 1; + return x; + } + + t = x.divToInt(pi); + + if (t.isZero()) { + quadrant = isNeg ? 3 : 2; + } else { + x = x.minus(t.times(pi)); + + // 0 <= x < pi + if (x.lte(halfPi)) { + quadrant = isOdd(t) ? (isNeg ? 2 : 3) : (isNeg ? 4 : 1); + return x; + } + + quadrant = isOdd(t) ? (isNeg ? 1 : 4) : (isNeg ? 3 : 2); + } + + return x.minus(pi).abs(); + } + + + /* + * Return the value of Decimal `x` as a string in base `baseOut`. + * + * If the optional `sd` argument is present include a binary exponent suffix. + */ + function toStringBinary(x, baseOut, sd, rm) { + var base, e, i, k, len, roundUp, str, xd, y, + Ctor = x.constructor, + isExp = sd !== void 0; + + if (isExp) { + checkInt32(sd, 1, MAX_DIGITS); + if (rm === void 0) rm = Ctor.rounding; + else checkInt32(rm, 0, 8); + } else { + sd = Ctor.precision; + rm = Ctor.rounding; + } + + if (!x.isFinite()) { + str = nonFiniteToString(x); + } else { + str = finiteToString(x); + i = str.indexOf('.'); + + // Use exponential notation according to `toExpPos` and `toExpNeg`? No, but if required: + // maxBinaryExponent = floor((decimalExponent + 1) * log[2](10)) + // minBinaryExponent = floor(decimalExponent * log[2](10)) + // log[2](10) = 3.321928094887362347870319429489390175864 + + if (isExp) { + base = 2; + if (baseOut == 16) { + sd = sd * 4 - 3; + } else if (baseOut == 8) { + sd = sd * 3 - 2; + } + } else { + base = baseOut; + } + + // Convert the number as an integer then divide the result by its base raised to a power such + // that the fraction part will be restored. + + // Non-integer. + if (i >= 0) { + str = str.replace('.', ''); + y = new Ctor(1); + y.e = str.length - i; + y.d = convertBase(finiteToString(y), 10, base); + y.e = y.d.length; + } + + xd = convertBase(str, 10, base); + e = len = xd.length; + + // Remove trailing zeros. + for (; xd[--len] == 0;) xd.pop(); + + if (!xd[0]) { + str = isExp ? '0p+0' : '0'; + } else { + if (i < 0) { + e--; + } else { + x = new Ctor(x); + x.d = xd; + x.e = e; + x = divide(x, y, sd, rm, 0, base); + xd = x.d; + e = x.e; + roundUp = inexact; + } + + // The rounding digit, i.e. the digit after the digit that may be rounded up. + i = xd[sd]; + k = base / 2; + roundUp = roundUp || xd[sd + 1] !== void 0; + + roundUp = rm < 4 + ? (i !== void 0 || roundUp) && (rm === 0 || rm === (x.s < 0 ? 3 : 2)) + : i > k || i === k && (rm === 4 || roundUp || rm === 6 && xd[sd - 1] & 1 || + rm === (x.s < 0 ? 8 : 7)); + + xd.length = sd; + + if (roundUp) { + + // Rounding up may mean the previous digit has to be rounded up and so on. + for (; ++xd[--sd] > base - 1;) { + xd[sd] = 0; + if (!sd) { + ++e; + xd.unshift(1); + } + } + } + + // Determine trailing zeros. + for (len = xd.length; !xd[len - 1]; --len); + + // E.g. [4, 11, 15] becomes 4bf. + for (i = 0, str = ''; i < len; i++) str += NUMERALS.charAt(xd[i]); + + // Add binary exponent suffix? + if (isExp) { + if (len > 1) { + if (baseOut == 16 || baseOut == 8) { + i = baseOut == 16 ? 4 : 3; + for (--len; len % i; len++) str += '0'; + xd = convertBase(str, base, baseOut); + for (len = xd.length; !xd[len - 1]; --len); + + // xd[0] will always be be 1 + for (i = 1, str = '1.'; i < len; i++) str += NUMERALS.charAt(xd[i]); + } else { + str = str.charAt(0) + '.' + str.slice(1); + } + } + + str = str + (e < 0 ? 'p' : 'p+') + e; + } else if (e < 0) { + for (; ++e;) str = '0' + str; + str = '0.' + str; + } else { + if (++e > len) for (e -= len; e-- ;) str += '0'; + else if (e < len) str = str.slice(0, e) + '.' + str.slice(e); + } + } + + str = (baseOut == 16 ? '0x' : baseOut == 2 ? '0b' : baseOut == 8 ? '0o' : '') + str; + } + + return x.s < 0 ? '-' + str : str; + } + + + // Does not strip trailing zeros. + function truncate(arr, len) { + if (arr.length > len) { + arr.length = len; + return true; + } + } + + + // Decimal methods + + + /* + * abs + * acos + * acosh + * add + * asin + * asinh + * atan + * atanh + * atan2 + * cbrt + * ceil + * clamp + * clone + * config + * cos + * cosh + * div + * exp + * floor + * hypot + * ln + * log + * log2 + * log10 + * max + * min + * mod + * mul + * pow + * random + * round + * set + * sign + * sin + * sinh + * sqrt + * sub + * sum + * tan + * tanh + * trunc + */ + + + /* + * Return a new Decimal whose value is the absolute value of `x`. + * + * x {number|string|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 (typeof define == 'function' && define.amd) { + define(function () { + return Decimal; + }); + + // Node and other environments that support module.exports. + } else if (typeof module != 'undefined' && module.exports) { + if (typeof Symbol == 'function' && typeof Symbol.iterator == 'symbol') { + P[Symbol['for']('nodejs.util.inspect.custom')] = P.toString; + P[Symbol.toStringTag] = 'Decimal'; + } + + module.exports = Decimal; + + // Browser. + } else { + if (!globalScope) { + globalScope = typeof self != 'undefined' && self && self.self == self ? self : window; + } + + noConflict = globalScope.Decimal; + Decimal.noConflict = function () { + globalScope.Decimal = noConflict; + return Decimal; + }; + + globalScope.Decimal = Decimal; + } +})(this); diff --git a/node_modules/decimal.js/decimal.mjs b/node_modules/decimal.js/decimal.mjs new file mode 100644 index 0000000..909300c --- /dev/null +++ b/node_modules/decimal.js/decimal.mjs @@ -0,0 +1,4898 @@ +/*! + * 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 ------------------------------- // + + + inexact, quadrant, + external = true, + + decimalError = '[DecimalError] ', + invalidArgument = decimalError + 'Invalid argument: ', + precisionLimitExceeded = decimalError + 'Precision limit exceeded', + cryptoUnavailable = decimalError + 'crypto unavailable', + tag = '[object Decimal]', + + mathfloor = Math.floor, + mathpow = Math.pow, + + isBinary = /^0b([01]+(\.[01]*)?|\.[01]+)(p[+-]?\d+)?$/i, + isHex = /^0x([0-9a-f]+(\.[0-9a-f]*)?|\.[0-9a-f]+)(p[+-]?\d+)?$/i, + isOctal = /^0o([0-7]+(\.[0-7]*)?|\.[0-7]+)(p[+-]?\d+)?$/i, + isDecimal = /^(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i, + + BASE = 1e7, + LOG_BASE = 7, + MAX_SAFE_INTEGER = 9007199254740991, + + LN10_PRECISION = LN10.length - 1, + PI_PRECISION = PI.length - 1, + + // Decimal.prototype object + P = { toStringTag: tag }; + + +// Decimal prototype methods + + +/* + * absoluteValue abs + * ceil + * clampedTo clamp + * comparedTo cmp + * cosine cos + * cubeRoot cbrt + * decimalPlaces dp + * dividedBy div + * dividedToIntegerBy divToInt + * equals eq + * floor + * greaterThan gt + * greaterThanOrEqualTo gte + * hyperbolicCosine cosh + * hyperbolicSine sinh + * hyperbolicTangent tanh + * inverseCosine acos + * inverseHyperbolicCosine acosh + * inverseHyperbolicSine asinh + * inverseHyperbolicTangent atanh + * inverseSine asin + * inverseTangent atan + * isFinite + * isInteger isInt + * isNaN + * isNegative isNeg + * isPositive isPos + * isZero + * lessThan lt + * lessThanOrEqualTo lte + * logarithm log + * [maximum] [max] + * [minimum] [min] + * minus sub + * modulo mod + * naturalExponential exp + * naturalLogarithm ln + * negated neg + * plus add + * precision sd + * round + * sine sin + * squareRoot sqrt + * tangent tan + * times mul + * toBinary + * toDecimalPlaces toDP + * toExponential + * toFixed + * toFraction + * toHexadecimal toHex + * toNearest + * toNumber + * toOctal + * toPower pow + * toPrecision + * toSignificantDigits toSD + * toString + * truncated trunc + * valueOf toJSON + */ + + +/* + * Return a new Decimal whose value is the absolute value of this Decimal. + * + */ +P.absoluteValue = P.abs = function () { + var x = new this.constructor(this); + if (x.s < 0) x.s = 1; + return finalise(x); +}; + + +/* + * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the + * direction of positive Infinity. + * + */ +P.ceil = function () { + return finalise(new this.constructor(this), this.e + 1, 2); +}; + + +/* + * Return a new Decimal whose value is the value of this Decimal clamped to the range + * delineated by `min` and `max`. + * + * min {number|string|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, + i = 1, + pr = Ctor.precision, + k = Math.ceil(pr / LOG_BASE); + + external = false; + x2 = x.times(x); + u = new Ctor(y); + + for (;;) { + t = divide(u.times(x2), new Ctor(n++ * n++), pr, 1); + u = isHyperbolic ? y.plus(t) : y.minus(t); + y = divide(t.times(x2), new Ctor(n++ * n++), pr, 1); + t = u.plus(y); + + if (t.d[k] !== void 0) { + for (j = k; t.d[j] === u.d[j] && j--;); + if (j == -1) break; + } + + j = u; + u = y; + y = t; + t = j; + i++; + } + + external = true; + t.d.length = k + 1; + + return t; +} + + +// Exponent e must be positive and non-zero. +function tinyPow(b, e) { + var n = b; + while (--e) n *= b; + return n; +} + + +// Return the absolute value of `x` reduced to less than or equal to half pi. +function toLessThanHalfPi(Ctor, x) { + var t, + isNeg = x.s < 0, + pi = getPi(Ctor, Ctor.precision, 1), + halfPi = pi.times(0.5); + + x = x.abs(); + + if (x.lte(halfPi)) { + quadrant = isNeg ? 4 : 1; + return x; + } + + t = x.divToInt(pi); + + if (t.isZero()) { + quadrant = isNeg ? 3 : 2; + } else { + x = x.minus(t.times(pi)); + + // 0 <= x < pi + if (x.lte(halfPi)) { + quadrant = isOdd(t) ? (isNeg ? 2 : 3) : (isNeg ? 4 : 1); + return x; + } + + quadrant = isOdd(t) ? (isNeg ? 1 : 4) : (isNeg ? 3 : 2); + } + + return x.minus(pi).abs(); +} + + +/* + * Return the value of Decimal `x` as a string in base `baseOut`. + * + * If the optional `sd` argument is present include a binary exponent suffix. + */ +function toStringBinary(x, baseOut, sd, rm) { + var base, e, i, k, len, roundUp, str, xd, y, + Ctor = x.constructor, + isExp = sd !== void 0; + + if (isExp) { + checkInt32(sd, 1, MAX_DIGITS); + if (rm === void 0) rm = Ctor.rounding; + else checkInt32(rm, 0, 8); + } else { + sd = Ctor.precision; + rm = Ctor.rounding; + } + + if (!x.isFinite()) { + str = nonFiniteToString(x); + } else { + str = finiteToString(x); + i = str.indexOf('.'); + + // Use exponential notation according to `toExpPos` and `toExpNeg`? No, but if required: + // maxBinaryExponent = floor((decimalExponent + 1) * log[2](10)) + // minBinaryExponent = floor(decimalExponent * log[2](10)) + // log[2](10) = 3.321928094887362347870319429489390175864 + + if (isExp) { + base = 2; + if (baseOut == 16) { + sd = sd * 4 - 3; + } else if (baseOut == 8) { + sd = sd * 3 - 2; + } + } else { + base = baseOut; + } + + // Convert the number as an integer then divide the result by its base raised to a power such + // that the fraction part will be restored. + + // Non-integer. + if (i >= 0) { + str = str.replace('.', ''); + y = new Ctor(1); + y.e = str.length - i; + y.d = convertBase(finiteToString(y), 10, base); + y.e = y.d.length; + } + + xd = convertBase(str, 10, base); + e = len = xd.length; + + // Remove trailing zeros. + for (; xd[--len] == 0;) xd.pop(); + + if (!xd[0]) { + str = isExp ? '0p+0' : '0'; + } else { + if (i < 0) { + e--; + } else { + x = new Ctor(x); + x.d = xd; + x.e = e; + x = divide(x, y, sd, rm, 0, base); + xd = x.d; + e = x.e; + roundUp = inexact; + } + + // The rounding digit, i.e. the digit after the digit that may be rounded up. + i = xd[sd]; + k = base / 2; + roundUp = roundUp || xd[sd + 1] !== void 0; + + roundUp = rm < 4 + ? (i !== void 0 || roundUp) && (rm === 0 || rm === (x.s < 0 ? 3 : 2)) + : i > k || i === k && (rm === 4 || roundUp || rm === 6 && xd[sd - 1] & 1 || + rm === (x.s < 0 ? 8 : 7)); + + xd.length = sd; + + if (roundUp) { + + // Rounding up may mean the previous digit has to be rounded up and so on. + for (; ++xd[--sd] > base - 1;) { + xd[sd] = 0; + if (!sd) { + ++e; + xd.unshift(1); + } + } + } + + // Determine trailing zeros. + for (len = xd.length; !xd[len - 1]; --len); + + // E.g. [4, 11, 15] becomes 4bf. + for (i = 0, str = ''; i < len; i++) str += NUMERALS.charAt(xd[i]); + + // Add binary exponent suffix? + if (isExp) { + if (len > 1) { + if (baseOut == 16 || baseOut == 8) { + i = baseOut == 16 ? 4 : 3; + for (--len; len % i; len++) str += '0'; + xd = convertBase(str, base, baseOut); + for (len = xd.length; !xd[len - 1]; --len); + + // xd[0] will always be be 1 + for (i = 1, str = '1.'; i < len; i++) str += NUMERALS.charAt(xd[i]); + } else { + str = str.charAt(0) + '.' + str.slice(1); + } + } + + str = str + (e < 0 ? 'p' : 'p+') + e; + } else if (e < 0) { + for (; ++e;) str = '0' + str; + str = '0.' + str; + } else { + if (++e > len) for (e -= len; e-- ;) str += '0'; + else if (e < len) str = str.slice(0, e) + '.' + str.slice(e); + } + } + + str = (baseOut == 16 ? '0x' : baseOut == 2 ? '0b' : baseOut == 8 ? '0o' : '') + str; + } + + return x.s < 0 ? '-' + str : str; +} + + +// Does not strip trailing zeros. +function truncate(arr, len) { + if (arr.length > len) { + arr.length = len; + return true; + } +} + + +// Decimal methods + + +/* + * abs + * acos + * acosh + * add + * asin + * asinh + * atan + * atanh + * atan2 + * cbrt + * ceil + * clamp + * clone + * config + * cos + * cosh + * div + * exp + * floor + * hypot + * ln + * log + * log2 + * log10 + * max + * min + * mod + * mul + * pow + * random + * round + * set + * sign + * sin + * sinh + * sqrt + * sub + * sum + * tan + * tanh + * trunc + */ + + +/* + * Return a new Decimal whose value is the absolute value of `x`. + * + * x {number|string|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); +} + + +P[Symbol.for('nodejs.util.inspect.custom')] = P.toString; +P[Symbol.toStringTag] = 'Decimal'; + +// Create and configure initial Decimal constructor. +export var Decimal = P.constructor = clone(DEFAULTS); + +// Create the internal constants from their string values. +LN10 = new Decimal(LN10); +PI = new Decimal(PI); + +export default Decimal; diff --git a/node_modules/decimal.js/package.json b/node_modules/decimal.js/package.json new file mode 100644 index 0000000..4b59cd6 --- /dev/null +++ b/node_modules/decimal.js/package.json @@ -0,0 +1,55 @@ +{ + "name": "decimal.js", + "description": "An arbitrary-precision Decimal type for JavaScript.", + "version": "10.4.3", + "keywords": [ + "arbitrary", + "precision", + "arithmetic", + "big", + "number", + "decimal", + "float", + "biginteger", + "bigdecimal", + "bignumber", + "bigint", + "bignum" + ], + "repository" : { + "type": "git", + "url": "https://github.com/MikeMcl/decimal.js.git" + }, + "main": "decimal", + "module": "decimal.mjs", + "browser": "decimal.js", + "exports": { + ".": { + "types": "./decimal.d.ts", + "import": "./decimal.mjs", + "require": "./decimal.js" + }, + "./decimal.mjs": "./decimal.mjs", + "./decimal.js": "./decimal.js", + "./package.json": "./package.json", + "./decimal": { + "types": "./decimal.d.ts", + "import": "./decimal.mjs", + "require": "./decimal.js" + } + }, + "author": { + "name": "Michael Mclaughlin", + "email": "M8ch88l@gmail.com" + }, + "license": "MIT", + "scripts": { + "test": "node ./test/test.js" + }, + "types": "decimal.d.ts", + "files": [ + "decimal.js", + "decimal.mjs", + "decimal.d.ts" + ] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..2a132c9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,17 @@ +{ + "name": "smart-camera", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "decimal.js": "^10.4.3" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..363fa9c --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "decimal.js": "^10.4.3" + } +} diff --git a/pages.json b/pages.json new file mode 100644 index 0000000..d13bf37 --- /dev/null +++ b/pages.json @@ -0,0 +1,80 @@ +{ + "pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages + { + "path": "pages/home/home", + "style" : + { + "enablePullDownRefresh": false, //设置为true表示当前页面开启下拉刷新 + "backgroundTextStyle": "dark", + "navigationStyle": "custom", + "disableScroll": true + }, + "lazyCodeLoading": "requiredComponents" + } + ,{ + "path" : "pages/display/display", + "style" : + { + "enablePullDownRefresh": false, + "navigationStyle": "custom", + "disableScroll": true + }, + "lazyCodeLoading": "requiredComponents" + } + ,{ + "path" : "pages/mine/mine", + "style" : + { + "enablePullDownRefresh": false, + "navigationStyle": "custom", + "disableScroll": true + }, + "lazyCodeLoading": "requiredComponents" + } + ,{ + "path" : "pages/myPhoto/myPhoto", + "style" : + { + "enablePullDownRefresh": false, + "navigationStyle": "custom", + "disableScroll": true + }, + "lazyCodeLoading": "requiredComponents" + } + ,{ + "path" : "pages/selectPhoto/selectPhoto", + "style" : + { + "enablePullDownRefresh": false, + "navigationStyle": "custom", + "disableScroll": true + }, + "lazyCodeLoading": "requiredComponents" + } + ], + "globalStyle": { + "navigationBarTextStyle": "black", + "navigationBarTitleText": "uni-app", + "navigationBarBackgroundColor": "#F8F8F8", + "backgroundColor": "#F8F8F8" + }, + "tabBar": { + "color": "#ffffff", + "selectedColor": "#6777FD", + "custom": true, + "list": [ + { + "pagePath": "pages/home/home", + "iconPath": "static/icon/icon_Home_n@3x_da.png", + "selectedIconPath": "static/icon/icon_Home_n@3x_a.png", + "text": "首页" + }, + { + "pagePath": "pages/mine/mine", + "iconPath": "static/icon/icon_我的_n@3x_da.png", + "selectedIconPath": "static/icon/icon_我的_n@3x_a.png", + "text": "我的" + } + ] + } +} diff --git a/pages/display/display.vue b/pages/display/display.vue new file mode 100644 index 0000000..81265aa --- /dev/null +++ b/pages/display/display.vue @@ -0,0 +1,286 @@ + + + + + diff --git a/pages/display/index.css b/pages/display/index.css new file mode 100644 index 0000000..5cb5836 --- /dev/null +++ b/pages/display/index.css @@ -0,0 +1,137 @@ +.page { + position: absolute; + height: 100vh; + width: 100vw; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/bg_%E4%B8%BB%E8%83%8C%E6%99%AF%402x.png) + 100% no-repeat; + background-size: 100% 100%; +} + +.back { + position: absolute; + width: 56px; + height: 56px; + left: 0; + background-image: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/humeng/vlog/lv2_icon_backBlack%402x.png); + background-size: 100% 100%; +} + +.title { + position: absolute; + font-size: 16px; + line-height: 22px; + color: #454F63; + z-index: 999; + font-weight: 500; +} + +.content { + position: absolute; + width: 100%; +} + +.img_loading { + display: flex; + justify-content: center; + margin-top: 30rpx; +} + +.img_1 { + width: 300rpx; + height: 300rpx; +} + +.loading { + position: relative; + width: 100%; + height: 300rpx; + display: flex; + justify-content: center; + margin-top: 60rpx; +} + +.tip{ + text-align: center; + font-family: '苹方'; + font-size:25rpx; + color:#006d9f; + animation: opp 2.7s infinite linear; +} + +@keyframes opp{ + 0%{ + opacity: 1; + } + 40%{ + opacity: 1; + } + 60%{ + opacity: 0; + } + 100%{ + opacity: 1; + } +} + +.box_show { + display: flex; + /* justify-content: center; */ + align-items: center; + flex-direction: column; + margin-top: 50rpx; + height: 75vh; +} + +.showImage { + border: #fff 1px solid; + height: 60vh; + width: 80%; + border-radius: 20px; +} + +.printTip { + width: 80%; + margin-top: 20rpx; +} + +.upload-btn { + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/btn%403x.png) + 100% no-repeat; + background-size: 100% 100%; + height: 100rpx; + line-height: 100rpx; + width: 80%; + margin-top: 20rpx; + overflow-wrap: break-word; + color: rgba(255, 255, 255, 1); + font-size: 16px; + font-family: 'Microsoft YaHei', 'Microsoft Yahei', Arial, sans-serif; + text-align: center; + white-space: nowrap; + position: absolute; + bottom: 0; +} + +.wait_box { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.wait_1, .wait_2 { + color: #505C73 ; + font-weight: 700; + font-size: 14px; + font-family: "Microsoft YaHei", sans-serif; + margin-top: 8rpx; +} + +.progressBar { + width: 80%; + margin-top: 40rpx; +} \ No newline at end of file diff --git a/pages/home/home.vue b/pages/home/home.vue new file mode 100644 index 0000000..2d43050 --- /dev/null +++ b/pages/home/home.vue @@ -0,0 +1,444 @@ + + + diff --git a/pages/home/index.css b/pages/home/index.css new file mode 100644 index 0000000..7734fb7 --- /dev/null +++ b/pages/home/index.css @@ -0,0 +1,172 @@ +.page { + position: absolute; + height: 100vh; + width: 100vw; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/bg_%E4%B8%BB%E8%83%8C%E6%99%AF%402x.png) + 100% no-repeat; + background-size: 100% 100%; +} + +.back { + position: absolute; + width: 56px; + height: 56px; + left: 0; + background-image: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/humeng/vlog/lv2_icon_backBlack%402x.png); + background-size: 100% 100%; +} + +.title { + position: absolute; + font-size: 16px; + line-height: 22px; + color: #454F63; + z-index: 999; + font-weight: 500; +} + +.root { + position: absolute; +} + +.box_1 { + position: absolute; + width: 100%; + height: 100%; + padding-bottom: 30%; + overflow: auto; +} + +.box_3 { + padding: 20rpx 0 10rpx 24rpx; +} + +.text-wrapper_2 { + margin: 10rpx 10rpx 0 0; +} + +.text_4 { + overflow-wrap: break-word; + color: rgba(38, 47, 64, 1); + font-size: 32rpx; + font-family: PingFangSC-Medium; + font-weight: 900; + text-align: left; + white-space: nowrap; + line-height: 32rpx; +} + +.text-wrapper_3 { + position: absolute; + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/img_%E5%85%8D%E8%B4%B9%402x.png) + 100% no-repeat; + background-size: 100% 100%; + margin-left: 168rpx; + padding: 8rpx 12rpx 8rpx 24rpx; + top: 0; + right: 0; +} + +.text-wrapper_5 { + position: absolute; + background: url(https://res.oss.humengfilms.com/hm_aigc/applet/img_%E4%BB%98%E8%B4%B9%402x.png) + 100% no-repeat; + background-size: 100% 100%; + margin-left: 168rpx; + padding: 8rpx 12rpx 8rpx 24rpx; + top: 0; + right: 0; +} + +.text-wrapper_6 { + position: absolute; + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/img_%E5%B7%B2%E8%B4%AD%402x.png) + 100% no-repeat; + background-size: 100% 100%; + margin-left: 168rpx; + padding: 8rpx 12rpx 8rpx 24rpx; + top: 0; + right: 0; +} + +.text_5 { + overflow-wrap: break-word; + color: rgba(255, 255, 255, 1); + font-size: 24rpx; + font-family: PingFangSC-Medium; + font-weight: 500; + text-align: left; + white-space: nowrap; + line-height: 24rpx; +} + +.text-wrapper_4 { + position: absolute; + bottom: 5rpx; + background-size: 100% 100%; + /* margin-top: 208rpx; */ + /* padding: 40rpx 144rpx 24rpx 24rpx; */ + height: 40rpx; + width: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.text_6 { + overflow-wrap: break-word; + color: rgba(255, 255, 255, 1); + font-size: 28rpx; + font-weight: normal; + text-align: center; + white-space: nowrap; + line-height: 40rpx; + width: 95%; + overflow: hidden; + /* margin-left: 5%; */ +} + +.img_1 { + position: relative; + width: 100%; + height: 100%; + border-radius: 11px; +} + +.scroll-view_H { + white-space: nowrap; + width: 100%; + margin-top: 25rpx; +} + +.scroll-view-item_H { + display: inline-block; + width: 249rpx; + height: 330rpx; + line-height: 300rpx; + text-align: center; + font-size: 36rpx; + margin-right: 20px; + border-radius: 10px; + position: relative; +} + +.section_8 { + position: absolute; + left: 0; + width: 100%; + height: 130rpx; + background: #ffffff + 100% no-repeat; + background-size: 100% 100%; + padding: 14px 72px 4px 72px; + bottom: 0; +} + +.box_3:last-child { + margin-bottom: 220rpx; +} diff --git a/pages/mine/index.css b/pages/mine/index.css new file mode 100644 index 0000000..c08bbe7 --- /dev/null +++ b/pages/mine/index.css @@ -0,0 +1,173 @@ +.page { + position: absolute; + height: 100vh; + width: 100vw; + overflow: hidden; + display: flex; + align-items: center; /* 垂直居中 */ + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/bg_%E4%B8%BB%E8%83%8C%E6%99%AF%402x.png) + 100% no-repeat; + background-size: 100% 100%; +} + +.title { + position: absolute; + font-size: 16px; + line-height: 22px; + color: #454F63; + z-index: 999; + font-weight: 500; +} + +.section_8 { + position: absolute; + left: 0; + width: 100%; + height: 130rpx; + background: #ffffff + 100% no-repeat; + background-size: 100% 100%; + padding: 14px 72px 4px 72px; + bottom: 0; +} + +.content { + position: relative; + width: 100%; +} + +.box_1 { + position: relative; + border-radius: 40rpx 40rpx 0 0; + width: 85%; + height: 240rpx; + overflow: hidden; + background: linear-gradient(to bottom, rgba(42, 156, 249, 0.6) 10%, rgba(42, 156, 249, 0.5) 30%, rgba(42, 156, 249, 0.4) 60%); + display: block; + align-items: center; + margin-left: auto; + margin-right: auto; +} + +.head-img { + width: 48px; + height: 48px; + position: relative; + z-index: 10; + border-radius: 50%; + overflow: hidden; + left: 40rpx; + top: 50rpx; +} + +.nickname { + position: absolute; + left: 180rpx; + top: 80rpx; + font-size: 14px; + font-weight: 500; + color: #30334B; + opacity: 1; + font-family: 'Microsoft YaHei', Arial, sans-serif; +} + +.box_2 { + position: relative; + background-color: #ffffff; + /* height: 530rpx; */ + width: 85%; + border-radius: 40rpx; + margin-top: -40rpx; + margin-left: auto; + margin-right: auto; +} + +.orders{ + width: 90%; + height: 100rpx; + border-bottom: 1px solid rgba(192, 196, 202, 0.3); + position: relative; + left: 5%; +} + +.orders-name{ + text-align: left; + line-height: 100rpx; + font-size: 16px; + font-weight: 300; + color: #333333; + opacity: 1; + font-family: 'Microsoft YaHei', Arial, sans-serif; +} + +.coupons { + width: 90%; + height: 100rpx; + border-bottom: 1px solid rgba(192, 196, 202, 0.3); + position: relative; + left: 5%; +} + +.coupons-name { + text-align: left; + line-height: 100rpx; + font-size: 16px; + font-weight: 300; + color: #333333; + opacity: 1; + font-family: 'Microsoft YaHei', Arial, sans-serif; +} + +.yjfk { + width: 90%; + height: 100rpx; + position: relative; + left: 5%; + border-bottom: 1px solid rgba(192, 196, 202, 0.3);; +} + +.yjfk-name { + text-align: left; + line-height: 100rpx; + font-size: 16px; + font-weight: 300; + color: #333333; + opacity: 1; + font-family: 'Microsoft YaHei', Arial, sans-serif; +} + +.kfhh::after{ + background:none; + border:none; +} + +.kfhh { + width: 90%; + height: 100rpx; + position: relative; + left: 5%; + padding: 0; + margin: 0; + background:none; + border:none; +} + +.kfhh-name { + text-align: left; + line-height: 100rpx; + font-size: 16px; + font-weight: 300; + color: #333333; + opacity: 1; + font-family: 'Microsoft YaHei', Arial, sans-serif; +} + +.coupons-icon,.yjfk-icon,.kfhh-icon,.myOrders-icon { + position: absolute; + right: 0px; + width: 30rpx; + top: 34rpx; + height: 30rpx; + background-image: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/humeng/vlog/ly_icon_listNext%402x.png); + background-size: 100% 100%; +} \ No newline at end of file diff --git a/pages/mine/mine.vue b/pages/mine/mine.vue new file mode 100644 index 0000000..7b80aad --- /dev/null +++ b/pages/mine/mine.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/pages/myPhoto/index.css b/pages/myPhoto/index.css new file mode 100644 index 0000000..4cec0b9 --- /dev/null +++ b/pages/myPhoto/index.css @@ -0,0 +1,62 @@ +.page { + position: absolute; + height: 100vh; + width: 100vw; + overflow: hidden; + display: flex; + /* justify-content: center; */ + align-items: center; + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/bg_%E4%B8%BB%E8%83%8C%E6%99%AF%402x.png) + 100% no-repeat; + background-size: 100% 100%; +} + +.title { + position: absolute; + font-size: 16px; + line-height: 22px; + color: #454F63; + z-index: 999; + font-weight: 500; +} + +.back { + position: absolute; + width: 56px; + height: 56px; + left: 0; + background-image: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/humeng/vlog/lv2_icon_backBlack%402x.png); + background-size: 100% 100%; +} + + +.center { + display: flex; + flex-wrap: wrap; + overflow-y: scroll; + position: absolute; + bottom: 93px; + width: 100vw; + align-content: baseline; +} + +.img { + position: relative; + width: 45%; + left: calc((100vw - 96%)/2); + height: 420rpx; + background: #FFFFFF; + box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.02); + margin: 20rpx 10rpx 0 10rpx; + border-radius: 12px; +} + +image { + width: 100%; + height: 100%; + border-radius: 12px; +} + +.center :last-child { + margin-bottom: 50rpx; +} \ No newline at end of file diff --git a/pages/myPhoto/myPhoto.vue b/pages/myPhoto/myPhoto.vue new file mode 100644 index 0000000..19ac8a0 --- /dev/null +++ b/pages/myPhoto/myPhoto.vue @@ -0,0 +1,72 @@ + + + + + diff --git a/pages/selectPhoto/index.css b/pages/selectPhoto/index.css new file mode 100644 index 0000000..a4641f5 --- /dev/null +++ b/pages/selectPhoto/index.css @@ -0,0 +1,119 @@ +.page { + position: absolute; + height: 100vh; + width: 100vw; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + background: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/hm_aigc/applet/bg_%E4%B8%BB%E8%83%8C%E6%99%AF%402x.png) 100% no-repeat; + background-size: 100% 100%; +} + +.back { + position: absolute; + width: 56px; + height: 56px; + left: 0; + background-image: url(https://humeng-res.oss-cn-beijing.aliyuncs.com/humeng/vlog/lv2_icon_backBlack%402x.png); + background-size: 100% 100%; +} + +.title { + position: absolute; + font-size: 16px; + line-height: 22px; + color: #454F63; + z-index: 999; + font-weight: 500; +} + +.content { + position: absolute; + display: flex; + flex-direction: column; + flex-wrap: wrap; + width: 100%; + height: 95%; + align-items: center; +} + +.img_1 { + height: 55%; + width: 80%; + margin-top: 40rpx; + border-radius: 11px; +} + +.tries-limit { + margin-top: 20rpx; + font-size: 18px; + color: rgba(134, 137, 139, 0.8); +} + +.section_11 { + align-self: center; + margin-top: 50rpx; +} + +.section_8 { + background-color: rgba(244, 249, 253, 1); + border-radius: 10px; + padding: 12px 30px 12px 32px; + margin-right: 20rpx; + height: 200rpx; + display: flex; + justify-content: center; + align-items: center; +} + +.image-text_7 {} + +.label_1 { + width: 40px; + height: 40px; + margin: 0 23px 0 21px; +} + +.text-group_3 { + overflow-wrap: break-word; + color: rgba(80, 92, 115, 1); + font-size: 14px; + font-family: PingFangSC-Medium; + font-weight: 500; + text-align: left; + white-space: nowrap; + line-height: 14px; + margin-top: 12px; +} + +.section_9 { + background-color: rgba(244, 249, 253, 1); + border-radius: 10px; + padding: 17px 45px 12px 45px; + margin-left: 20rpx; + height: 200rpx; + display: flex; + justify-content: center; + align-items: center; +} + +.image-text_8 {} + +.label_2 { + width: 40px; + height: 40px; + align-self: center; +} + +.text-group_4 { + overflow-wrap: break-word; + color: rgba(80, 92, 115, 1); + font-size: 14px; + font-family: PingFangSC-Medium; + font-weight: 500; + text-align: left; + white-space: nowrap; + line-height: 14px; + margin-top: 17px; +} diff --git a/pages/selectPhoto/selectPhoto.vue b/pages/selectPhoto/selectPhoto.vue new file mode 100644 index 0000000..8534e0f --- /dev/null +++ b/pages/selectPhoto/selectPhoto.vue @@ -0,0 +1,368 @@ + + + + + diff --git a/static/btn_down_140@2x.png b/static/btn_down_140@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e0fdb73665382c4d2e21d1ff603adc2297d631e1 GIT binary patch literal 3080 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 LXkf`lo45TNBEr;f literal 0 HcmV?d00001 diff --git a/static/btn_share_140@2x.png b/static/btn_share_140@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d87231e3ed59e83c384b33400ab86b704d9465c2 GIT binary patch literal 3020 zcmbVO30MSm`p-|WMU2oml9UnRjaE( zL|nxKlpE2aQc#Q{o&{7=4gpa_5nL3spdjK-5UJfqyFQy|lKKDn-|zk2@0jn&R$uRx z=4RiRVK5kTuBV4T1~b6{U3;1sqrYCrwH@fqROY!xfx%3%FnlLq_8+juU?$xW^MjSa zJTEqcNE|@{5(Yb}B{CF^!MM1oWgrv@D{*14NG#>xpO;_2ZY?MF(D?yxE5+zlz)g1gNFB@GO9ux7nQHU~H0f7YNz@ z9xKNDp*s#fT&a|?iNu(g7{?f@BO(_O$t)I&NTLua6aYm4idd- z%ame7iZd{RVTek}!J}&5har)T(@GU%sX~)RRD&`i*^y)jYZNGe#&I&0JZjXr03yOs zumqMW6)2WGj+KQYN<}b_)iYd^zwM)K0c{MA{lp~P%e)~!x&4*C(#OitPCdl z!wN(thv4PWsLXE-(a6~Dau`%1az27YeJGai2gx`J-I0u2!~-F*)DQ&WBNNyIRKgs* zp>6<)1(2zHGLuasv#GSjBquhB^d8DX1Y%+AIFtsEoB#@qPo}Wx=tch%6m1*T&wg&t6tu8z+wtn0EG;bsW1#NX)NIfH9m4N`nG{lAF~=%2~b8ShLFkA4-n#-3Dq}!7yi|nd?hD$B_&NCsF#4~>e_1i# zs~Q*oxpw^j#E+#03J0Yk7#*QRydfN-VbHuU4Dr8fHhT8aQ2GEzC!JwAK4#I)_@IWR zD773N!>XTxN))^*Po_e(09LbzhgxYxJ1mt1ZzAlaQpBxn5`VIZ)+o zzkRhkFwPplI#Byv=8ub@=s>E-Z_3W%yv)2Fo$sm}DOpu-XTEkxyRx;7lC9V#Q8y4_7owsUUrKPqNR8rlXAL}^B+V0A zkYYBUP7N%C5f5qf7X+4pXz)!#A8kmhn>MuMZdtM%HKVCY)(v2tAAIQ zM{4WY*vMJWToa^iot<`@f|~bwXSc<@yY(cXGWYO*|SI;su<_1V@|&*JYlzTV)zD#9F_ zZ;I@+WV*_thSg+;mb3h}7y4tZO_`lO=SIL%F+C!sY^&z<=CqMGaR;;ZpqpPtSxI@* zEB^7ywF4JuBb_t7hs=+bXr~q!dv6>F8G3cX>p;$)qL$$149|f>h0mMo+|+pkW&UOI zhesL~W^e|ZV!Eu-2rAUC=EAvv#t=fttU}4tuK9D~2m5ZX?0!@6`f0UK!EDb9LCt{# zUTg30^-D#84FuH`)L?zlJ+~UuC(iDU3UIx<9TUXhzE>~aWl569CfmCtQuk%R% z(!rae7(J7Cy7KLQSNA&!-lhwxe$Xr+Fs3?iPlBP`ZRXfj{!!M!+OSHUcE)Vuy;+T< zVp|k)I^o^-9U?B!p2@lylk_CrJ*naDnt$klsRfUmvBSBo%RO5!6OMd9TN3mkXWN4x z9@2;Sl-#Fg(W~hN*V@wKliD8YS{)Lvto~X1>$Hm}Ez8d8=`I^+TH|}6{a^jI*l3zj zTfv=9Ze()6CC>?sJ~M0!1C25+6>E#qHT|0)o$LMi!0=B#nydTb&y;7`u@mbs*Z1sSW(^7YRoi4qb z?d-O3Hw%^7qpM}kdo#vKJX`1e|qt2b%<2TV8-Neo+xi2=)^@=vT zhFy<+R9|n$U9yM19y=IeT%CfBIHb~f^WZvS@ubqPYLn7RUL4mTn!X`I==lZM{J?#+ z$C7M9IkzVNZt*q<;zq16-IrIfO;^=T;RlRN9)7-dwluG3nc@F7ce%Gm(X!Cw{{SfO B!14e9 literal 0 HcmV?d00001 diff --git a/static/btn_video_slider@2x.png b/static/btn_video_slider@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9cdc295f33c365da5266be55d7c21f6af4b59822 GIT binary patch literal 532 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®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

!oe1~v!ltZy9V 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⁢grq;s(w0Jis~^Ur9Dwb5EHgg{xAoIn2%|NcMxGKeR*5(#l5 ztWceE;;8a(pw&?9NIpkln5MJNw~y)3qlJXF9BgbJwE&GliT?!Ed~GoAlOo?cd+%+7 zCp_~OPoyXuq6OWf$13>i-q_)V#(*Z>t5Vsp`M0F%%QYS(T$Bf=6f9x~Zg39K*(yK; z_Pae?98JceDN{vWli^uUdpgB(!N)&xJI{Q^Gh#VdG!j4?jaCLFA@VANU{hE2a#=!$ z6LrvMTXlh7!k5zH*zn$yg#cN`O*h@tX5Xxh7J#|FSb%VGQDLPNnK8H!xcTOralv!@ zhd+Wxc*awo)=CwLM3DYdP1W$3e(6 zcpp80chBB^`{w=owjuX?@`JZ)Jef6A^?LNzkF_3~XgZK$2b{)vpLQRybhv8pNY^TC z6omWoFsx_ibZ5se$;RzaYsO=ol$(C9ZT3Pbj4|XkzD_H&wgeC}YCj+D%z<{8g;29wEzx~_@NaJuE-9)_bb$Rd$*IvfrO&a*w<;<}Tk z$c$x>hk8x=nKLgYyx-&6fl?YT2lD`nI*?g|#&ho-AG&Sx z{(UpUr$7AXx8-Tm=#N^P`*Ls(;=of9(8jPRJwbHRAG(Ol!zI{LT~i3Y6R>&IcnA{x zUe}=s$NUPrBG8))S*8v65ao2VW@|LYD7_Mb*9zwalxaJ6eTdCHCr_RPX*zwS4fy*8 zkk1{AiK6GODB#2iPMkQ=`ad^9(CsGSGI)1cmf@VEE=$J4A;UZ;Gd3<99mlA~Zm=;C zD9R#Zf%pZ?)Mv*Ef;w2nM`)k2;cob{R0R!)nXp4 zFIfe1YtKJu;oA>X}0Dj^Fx9Lzr@C@=* z`JnIE>~R>hrp+|WDyRe0vKegjXVN5osoJz=^g$eI&1&lCNNaQ9I>^qd;chi$ zyGF>jkrDCUC#|z67vd!LL~flpalmn}-nY*TKDKBA?ch8%k3P;{{^ehW4>gj+nSm5k z9K28*l>w~ln&EKR{+=NOLVDe1Jk`l2&KMJAgOXd#^Pm6xHbdM5h|mbSUrF=9MUEw? z_Iupdy_@J5F-Wc`$|XPkRt%C$FWfRn4Qlw7udb`fzA8(ufpY2 zlrL|SAXt5v%R`SI5sFo&$4T6sPAkR2$F4uvztHQ8{B`YO-M3XYx@jTs>}Nllx~#~I zU9;Lcj2HN*AO+}kUE?HB2agwr$)Y#vGoJPI$L_s*92-h0R0v4zz*=7M&ELe{-Y!90 z93LIYlDHAjF$g@$IsOu0txew2G2=CvOeo8euYTFfAT$jVA<7Afbn2K__$EN2CZ^lS zcsBnwM#Uf+j}MO5yynLvMbE-~K0~~SEPy_J_J z|AGWUwYZIPy6Z?lNvSXKqkd*KVB427(_ef0R;!Wf0kb81(@ za>ld1>N(gs}H?kX=QPCJ?%k z%DzWo#nUUx3Z)EM+cj!K%#J#CcP{`Ta{rbS>e+;??J=g!nl|&`W^i|q{T#q5TNskk zf=96w!)~RRl>yQF1U!0NgV>D24os|vnw(EKm}cuX77943N%g+iHj;{_|5 zyru-~Tt)2){`J54g?Qpx4Z#!Y@=?jqx0DYQh1cvBPzHlj`BkH&)8p|&^Z>Tp@qu^k zlYoIk0>F>{)gRuTWtO!n!J+EqJ+67EBu%O<4$E{=vve944&eb_gp_`*LlM?^Ml2S5 z$@89v4|Qud)o86fnrL$rk}gC!8hn)S@ZO`e;9N~zl)U(BUO@Cr4aX9s?(x__T;0)w z4B#q$=!buhbLY=88VwKZ{O&da9hSM>%u8)@Ih%ivw}#ASGazmjL z*T|WKD@Ow6I8dtP-@>|Rw)Zu=dpmr=7u?88U;f`iwM41{AL^uqn6(+e=CZ=U4oRZ) zIyX?qhL2^?6kc;-5pXI4wW8Sc=+R;$POAfCndPJJ{=?&E03ZJBZ6A|<``+U?NP&t7 zQ3nvibWt*Min-V8dxk#aw-1L&Lae+)18B|HfBo09x3|}JSso_7{8+#!A-D=9;A_Xz zpYc>q-Ev8GO#sC3h6}77%)NI{&Bj5II-@@6mXWPv}Q^If1wK01n5E1e` z$5_RDKIP1r`+3c4UIW2XFBWNTh_-MmTur6m74@Py-fqzW+ym1ga|f0C%2!wdNF>4OfHaT$oO$y!_?g%u}EJ zMNlr1M4AL|7A+7L7`=m<%AB3e?CS_o{tO;nsA;P~sdUT-_Ea$UNQ%vRu z-GAunTu#p4uGDIf3999L^#iX*1BJA1AOR4aQB@8XpzuPa3_*$hbm@#i*u{;PS?fC@{G} z@Kja7xpNQk^S|(~Knbo`;OnY&IumKM>>xU9(E0oEMx3AaABzSA=OucZCr!Q(0!6iC zHs9k{e)T^Vr{4n(kJEAu^?c_*{vTW<0KDh+zx=Qf*9t&;G#(wdBoZ*H4+O7uC?GQ`rkT@@ zQ~>fZJ9|^gV3~tO1~Bn@R8?}q#n8%Q^8}zL$!pewSlT;A;lC#Z`&tBo@JfvbdnYSc=NwBrusz z`H>&~!88Zd(WG9>N;k0oIX~x6CWFc`8jR5pT|24*$~nLAE5C#`j#?_Fi@g|VB&|E| z!017Ae6cEuxr<-%^g@(v(Lk0OfkKE{ej-s4NGZXE8ZR}wlM6iOE54Lh{Ey!b)e>tB z-qkB!DF%fBIy#g4+-)8osN{HqT3J;_CnF6yTF(f5*2l9t|mq1uprk4hC5(3hkUD z%QCFZsq6Y!94~7vRaG$@4$<01A!vz$&smn?gD@BknM@|^?p@%gUi&jp%qbRgGSmNl zR|;Bb5+T(MYj6dxf5Ypz_x^h@M&l%Aa=k=<>9Q=z203*dT|>0isk3!8ZmOzEjYqWd zL)KcXwba3*6r4GGhN>=j{hQth#gck9p;%1GbDJ_+kJFcO9Bk}bB9o=r9uY0qjKLVo zqF6@F!{rQPg&+7Q|0r(Ge2o$xtq?DXm#bG9(bc=tU0#(EmNk?Nna*YeWl`D?g0uqc zJ$fi)Utg8MGg1||-}=_SJnVUg&fq(D-1_c3vlm@K`tE>Q4tSM;9-_R*rYY93Q4~7GN`Imo*#d1znFAzM=1zhD( zq8SawRFz{sTQVAMVRVKT9WSgpdz%Y@^McI=%oaatqKj%o>%%Qh?|$E_pj<@azj&-MS9W&iT0tlK7aMv4!8=@45O#O?JFj{rKlzid;lhQ7sj3Cb zVv6%cvS{;IYcV>bt~|xEV!2$l+2q-5)(U|y7iHUk6q_9;oVovAe*5*WWu$}1KwMtTNNRij7JfaCLaw6 z3QAWqKCw;Z9Fy6M$$Y~3^XK`4KlpvV^2INLP*YEL$gIWy!%>b~EU&uma77cyB`%~E zoUgDJ%Eg@R@tB|bS3e8BrdmY(!!_aaAgj-NtW9p*{B;{YL?z9@pqba2U6*n1t}s=n za3KZY>S`0y>G7CALR?o5e=FzDKSW)Z z9be!W1XNYQcsxGDi!{A{DtDE&XOQG7>bge6vslg;Z{>JjanHS<<&D4nTQIOtEU4=W z@8jbJt;|J_#}jK3C22l30$POSY!cUnvgGA|_dEHEzjznZ*$xjpcprOv7Z5zwYOK{b zS5Xv;wxK8lhlr;r7Fes9PWRZG>@Z(U8I1;f^rN@)g#_nUFiUCzk|Ihyry?Aq%cmN8Pi~F9Ndb-Y8NVI} zLKAl!BC(6rg&5L!Wx4x;7*PuAS5cR4kT7WAR6&{-BY+1K*;k>uyQvi?}RZWoiZ%d1>KYeTlZ z4R*-x*`#+*&Y`jKF6DX z=Z$>X^S&Bp6M`#KaFKjaT}?I^AbknoafPUqfs$lX*6=J;BLfuWNE{GEk&j0)3qRh5 zqT)CI^KbH|H~kJD`{*Y)b@~KGXVG?0XEmsh^>yZFxU{oeS#vl-$m z>S9S|KwFEeDw@V{wUI24jVwje{G}e}4PZ!eEo``zC}SZTLO$lk6HnkJFL@!q`-ks@ z#SB+1Fj}G)wm-NbqY-L9it8NZVB-5mshC&}b|LVPKfx#WGTw7n!JYFh3N>QO27(B6 z&}gmtwf7pvW(=kpIhf$^7`9m6^MC%mCqM0CuW@t$`2XJZhC+>AskDvOGs;9MDFNp_ zN}GNVUdw1E`m`$*i38CP$drS+;3=mKFSyC`r8f%KhXuo2fp zd&(ND$x+6@@B{#UcaJ;n_#~hF6GYf@l4AU&ezE-j5m$aML}s3IvHZh>`Jl z`A`VKIkX*uio);42s1t4GdqTloX`2lnVLx$V+W&1^#~5kfGR|x-yYW{ynuw%jF)0E z#G?@;IL5Mg!~gN!&v@0vUc+AOPJoZU=Z|lF)(c0-sSNR!w)%qcN|0 z%bR%Ho8Qc9U;DG{?4IMMCq0=9yXP4X$5?Ao7=jNV8e^iXfpZRD)|7R@WOtXva>l>- z7eCAQz50itn!|jSfG zsUVolAoU}8_gL!HSr$8qgTm$moO3+9Q0)2 zbY1d=&$)$H|JaXmw{#*YKU-8vn1;q?03xcbW5IH5$^EV_%ht9F}r~l)Nlyd8ygX<8am0gl_OF$$_ z{KV>Kjg%$6D$uS*`5KlB>iHBSf-C0KWr49^j6y;-W~t=qRdh3=7G)Z>G3& zS98ZXPoc-;)~0}u^c~0FLF+yRc%}t)C zpKzSeWmMU}*5ki@#Q4KFQLEdV5^nSg)o5$*UdRUn7>>YXpe&R7AK;Jw=+F4@?YD8q z$M0Y=pCLgp9*=qUv!Bg#p7R`D`Zr(1lfLMgP`gy(t79ObRqO_BHRc+w*#?)ZKm8w9 z99aSuNtSE66_4|sO_vboafMmAiFBG68ix>V;@=^-mQHYR3H0g;NP?);SkbiMrg=+6 zx&_Kmc~3qVu$a#nZ;e1a;wnN2Xq8{&)%Roldu3zPwN?Fl~mkmo(0opaY> zo64SGJ8QUI7E!5rO9ZVSSqZww)eDh;F&gh86;G+C>zOOZsXR>n?e~27^~}#-v}OFr z5-{`gzFyAWt?a39)XLzaKMq={BtX~?z-t-}2TWquQFNGCZ43emZHFv_@R@T3PdbUcHXC8Ap;{K`vcitWfac`&C;86r`7XZm zAO8K6ph>nZ#>7lwQNY0Bcg|syhD=iz3w%{G91k!`Awi-)?B;pitYlY{$lK>3jtt1V zf2Rf!qm#r55CY&sbbW!C(GnqqkgNs=ZN@JIK?T)H6V=>h< z4hkg(v?hdD1?aPXJwj?i3KFSAS{oFedO3UdQNbS^CjbOK{h@c=dh_$X^&2CX1hi5Z zt#HowrXbfinkLYwX|G~AD0L<^O(7wG(<7!;$;TcjIgw>-=Z+^1?3K12Tvbp4!{LZf zIfOu-S?bae77Lv7A%qY;hE?eB3f(wNt<|xK@14^fS1s!x?5u*Q-~8>aA*`J%P>X(9y}Ozb#LC9 zpe(>D)7{*eI;(A#;j0QC>KF*t74@%b0P3>HK4raqm0vG}TnI+B64QRIW1P}jJsK!Sr%6MRMR1xnQ*72Yi|Hei$| z&o#cT;;$Gyi`f*L+2lx&#L`03u%Z#I`tt7;h?Umk`lW$Jtu*U`;1(sm^07HcSu`eQ zwVWVMP&y+sIVRmMm8U9dLLJa1>%4E&mK2&xS}QgWAfeGJe7td#r*3c+S_%1Z$a1kj z=Q;Uk1pc@>e}^NURu(}~<=Ti^001BWNkl)a04Z(m1d9dc@m>+O=pQ=%;#x6QGei$ompf~N7$?BXz4k}IK7DNX5C z9p`wO&(-LJHCkl}O;=!+;meY2IE>G#YeXxwwnzvVWAM)5RQz`!+RFhLt8itFwU$uT zkqegRl(QM*lPB?IiNVll3^d0b8lJ!E7ojU1tvy*A=yWoof`_k@JVO(}i|d=AG{%V2JgA)aq4xfW@gQ7xC` zN-^3VQ_hwQY!)+wG2OE9-1X1X==`lU`?udsEZr3j=IT1`ohknM%r57an%Zo|uUEh* zMW(wAv#{Nv^DmwQuFPv4u{(=SpA$~p@D zhS1Oc*D{Q1MH5;%pr$9#B;L7#ADxlra99Z)AnoHi9U?T5AK$SI7@ z_R(HWJX%|j802{rMq3C)G*MS124c*dZBo<@OIE9nrrn`v0-z95aFtv&L=Js!`~Dq5 zy_cvuCPWH_Qi|aG%66*r_|7ZE%YJr${C@zQ4Vx+BfjMQ{fGg1Lj3Q-D`j-b&8 zG$u>hjgdr5=@?`~s60lkYc$5>U&HQ{KKQ!=u+n2Z_;yGgt*L`tRMS9|I!Rlj_Y}~m zfTXb%$B~MSCMNNJ#Ko)hnC86RClAz|aBG8PRf=xTAFOUm)XjaSla<>ia1Cu2Y%6}& zyhr!%WI5T?NDm7(C2eeC;HpumIR9uDU$Qo2*#Hp-m5=8JK$O;Q8{s9fAw)HE5b3k% zRH}1`4`^+p#$brni?wph%{KQ;;KTRMxO+BWM@G~Vo9UWYQUr32`cqd)Jr7zxcGz`w2F(2j^(DHOq$aL6}k)E z%4%wV#VJkH-O_2h8$Ti=*X2%G(|)#)IC9pm#{b%)E34Zp0p4*O&K~LtiR9Z zb^F=6*PZuijz~39F)?5az9IPs>@a!#mSqh3@(iO5!8y9lAgj;JzRb?%0(vE6RC^qa zgT{R99#7CJW`IMWE=rV+#cGrG8mZ!=RLT^#d8myy?3`Gz8b?Y&vNCJ_RuF4e zir7rnyk--`2@s;CT^sNvd1oGh0 zOsv~WOgicnQMFSd-n5)*Gbdc!iA3pDhNAKM6a`vow2nQ`P3A(YbQEcq9v35@BFyx6 z(V`>}RW(DB8$#h7D`dKtc}YaY!I&oYZ&Uf|ZZ|JS!2_qoRo0QWxq-Vclh*|`#);DTVa-nXds z=&=bO0!Hg34z1cC&}fa%PO#_UWA{&4mK9(5w3DDTC&QfWOh=n3Q3Rz3LDF2T;-Kwh z{zU72sVS8nqlAOAT%?Kn5_w2INvX71hY(W9Tdf3=+bo|z<)Ex6<_oH2fvan@fYl~8 z5MIPMezSYCJ+>yGRuG7C5XuO|RuKz3y(0HN*sg5G49S4~Bz>CU?I7gU5aT@$0wq^C6V;chtswFKU3% zP&;X}_C0zW1ap8^l@Fnu;;EpPRB zW5(DKV*-ozP8&14+^hQN16N_&8OK zn=e>SXB3MiItWH-a%~uDgB=Xx!Wse+By#g~DpBuSDAk(QS2s)8ewQLh5JISNRYg5p zM88*~5vABVv5iiPsmd%y0u8UwBqmoA^odAp@HnLW+vCc|VVpqdB)8P6ea}h?c2x8T zZgoA20+t1n-Mx6Ggvi5dHvM_p?3j)f&_Nl#a6lQh$FxVcGjYg1Xi5`-&jT@hE2o#nNy~q$SvgwS-&fP%?Cq zzEUBeRLWY$=rnak3lg9Xo|$AU8MC*v+;x7*XC5lJcV;NkXeHZP*(++pTC3o`D171E{R3zhu4jt`sFYFADrwz(R=hb3_*ktQu((j z%>Z6hl#9V2Wpt?Jw6(Dz#c0R|P*#*XyUfo$%FKYz!c&woI{o|0oo12@`E3vaTX82N|p$!xz z#rX>?cK7gAjdqa>*N`l%Qe;YFwZ>|LNo#>kxi95Y*4o95lI4JLoyNOHVRYoxN(lJG zTeaGdWf{Z402Ku99K~$Td~ZTEo1>kN`h~+GT4{_mF%WHS5^1~CH@}YdmUMDArDRmY zHSBOD(Zn1{3i8(e)2XS7*dg7P8>9^=MT3}}X~;P5hFowX?wcAuc4o;P4=y=7SIo?H z6nfn92L-j3R9S1TQB8@wP2%y~K9>}%l-M{yrf9cHa|Lyi;KlPH{==x{g_)mZ1 z{SQrRtwiL&>`sp!n+U0t83UAbTUhA`Dg{bBS{z0jGAd3E;ORH!Jbg6hNn3E;2u?^v zZX82WhEHTA#2QnCZMg(k--)9MN+q&(_aQ#HmmG|?rNuiW1e7+AWpU9gE0*Uk5L_K) zk&-&UX#ze0=c09%=`6gPW!+7AnC`Vv>3D+>(&uijMI@G;QszaP;98~3po%4H7Xr>X zM8RM@V(ZjN7>pCih_=Mmbapm^(OvZ1zpD#fkz?p|lS&g9HQ6nR4=U!&_V!rL7g(jq zjKwI0ZMdWWA&$51_zfvwYJ|o$F)C^P4$dDszM(@sP%B-@mOluXlvx)=>rT?p9)ebE zKk12(+qUCZQYl$$i!yq}K|CM>80Q5=P+-KfUhZu+i8^W)(um-$Zf|6&);CEW37%45 z84MGjF?AW|ij2E<19xBWJUn-l_@M8g$JL38{+81D$FicHOqkE7XcXIn(W>Mtv>PgE1IM)CXkK5hvgNTMDiHii zz0zvkY%A8rw`%@QjYuI$B(<;Ka1?z!|Dx}_ZaIJWn8e<>|3S7+oghDT60AiT6=@Cv z;$t9nWFw4p1H;(l5mYp`R1%N5kl0=#@)B=^{%stF1#k5xJmYRpB75DBe zIbRs2VMJk1$3~A3-@9q{Z~~^GoFHxR=Q}}byWTb%-9vOwdt4i6YytC35sJO{UP|x> zml^;9XYc&j+n?}7&wqjHJ%D>$BAP(3i!^@mL_R`p;^JXM;nk2kcPq}!G$#jvCyWC( zpRnAxr8qsX43%S)4;gAtrfM=AI?1jWWiTr8mjg%$Rht4uSeHwG>1Z0*_7AR}bT2lv4rlaIe z*L|dygSoOGs~mOuE!Hzq-h1*qN4$?&IbX-JueOBU3A6J%ScHL!QWA~cUYjxNlt_`) z=0%g5kQ8g=HD1)UIOYIe<3zWf7 z1k3Kyb7pSXDKuv<%qYa-)k$idQR_U;cWK_!dKCbgCi5;U?wnET4FUfKiRcLo`J$hUYl!}4h%2PP;_!QJ+ zIGwX}j(J_OJFj`@LdmH-aNUU^*PR$JP>xe0%{Uv8TM}1C$c@4(VQ7Rw9T=Jn=PQN^ z5RWo|IKZS(X@AzF39OW{v1YwDp`6aa`IK4H`#K=C&@Ph4`uqp{`?%MT-b-<4CuW!M zA0&R-F28ZUHz9L1qbEHPJsd*tZC9m}fRXs;ARV~4{+*4O0OLw ztL;0D8>yis*e#}E#9TCG9iozxj3P}!1Q);s#oQSdPP43qMd_%jifL7|Tfk1KSvZBy zu8Ubqq86x1$KB}nS=G_<+i*2%=EUZ@TWvE*f6-m~65iwU2q6SUnIQ`mxBh>>b!_>U z2A4c~9{BJ(-tsWJ5;PWax%Y)BIg9fT0T z=1|ovclW3kOROlYiN_V#|J;KXobIBwp6PgG0aj2khq5o|Yy;|u*f^3FL^>Z?!F;mE zU_3%^Z$%Qlj^zA_t*EEb$Rb&}Q<CuSPWrDFyu8_95vEfPv-DxgRkNk7=c;r}fv+2e?i4Ur@j;iYQW2gDk!|Nh%!+OUd7Cw!DH~T)4%D4MpENh_mf2U zMwDZtq}yziS4uEy_1GTQJgm`#;=(&wT<}LfdgHm5^M>#G-QRfI3%~0pUg=HVcPaI_ zd`M^~#1!kb8p@F?)HrRhu}juiJ3y%cRlDf<*bovNAQ-LC;-RQGKQGv+N(SQ-XkB9M z5bNiw?BC{Lr3^~Du!ZQ_;k{>IP27by1Z|aqz(W?nM=RL77}nM}>2z%pvpH%bvjeM) zVO5lD4TtP3X0e;nd%UYrsnc>*mg-BvS0kEiRPdfq*VwHg)uJF*rtRoeoz8UGd~WlH zq_(L>F6B|eCUxO3`ot!OHb~lhwEC3+Ycy6_>e-BJbVJg0Za9(q^#DZ$f{x8vT6t=n zvj`avEHt0pfr$(VIwL5J(FTntQ=Xa(uPiQrHINgVSYY-21&Q)jk&6sSYDkF;XOiO0 zI-jp8!Kd%wAg}d!@H%q;(!YCLyU-ep5B%9%e&dqMzi^qe`uqOiH{W5c?aknOJYsl( z=yGZC$|kk@byy8qx>y|ttq(%&19gBp#K|`39B;>XyG5nP)b<22zJV|}&D>?&vnR}) zqQc^XZ&w3R>z8J+5k(9VLr4MY>d2bFN^`v6u6gal?z^08SS_IKHR~t!Q97NCzMHtz zR@pe5q=j|uv-Riu6$Md8^G&^v*(R+tHf?xk<|=r^R|N0l?dh0(Q|48=eQe|qrUs8BMI$PSaBpV+2r)<$zs3>t=r)ho z?s1t&U9x4fkaUUcsf?miIoF4# z>rGH8Kxw2-8Z!bR83c$#Za0Dmm=Gv}=j{1CcDFO0FaT{7jRQh=c?qlsfx0;`tE2fy z(#vZW&`S|xZDcSGyZutHn;?>?`tr`yvFS#QXasnT z*0H$;T8;IlBB0ZAWv#(OT3t}z9LL7-t+IyFHhg#tA_0$X=SmN~6x%h7XfIfNfa!w| zUC#3_dkgWY_x;K5jcqKuHE4G`4U(a^Y;-sE=+U5&LvZ0>y{q6o5&~99%mUizD;$DE z&rA_?N2{zsrUh%FmRGGu)Oy6E2+S(QyiQFfUfO^tmYW-2&w!SAX|f6ohA3+YS`f7& z*aNLh%3+znq)^!Y+pE=WkH(pCsLj;@_ia9=3c|cDIeGmJkY}-MR>xX=uM2qf!{!6T z2c)dpO!oNnX}nR?gf{E8nSDEKJa1*Tx>usX^_HT@>Fhblxp zzh+~oH{P)E^6hRMn|Z6Rs9oFe8^6CuqdR%<{ffZI3ZMDFAN}6tzUO79@6MjN_o1)- z#&7>e4nq}U*=UUiCBBvOh)1haxi4OHqX^Yo$z9XXiT2WvryHq2-5EF0+)WWgwPUR9 zv}^S9lC4}2Kq&^47(7L=1avIjR0U7k3Y^M?Q@JJs5RF3PbuxQW9wQDNA_vd~g~^A2 zCd&-2TH?wwnnYz;?3C3hh0-l;kv8>e{euaeph^*S3!x?At0tq_EF!1_Z*L`Pn%ATe zrj0KhP2QsRqR{Dgk?{Ys_vXQtWOse%=l44&^WOVjEnU3`p#=;Q+ek8tku7_$A&ePg zX2J}f8SnrmCK!(mju<8!Ca^u>`Nx4HY*~!KRv1R$F<1g2BOttuSZre?AwU9kgVaLm zeXH*3>RR4sggA7i0=mD#YM#@uhcw# zC6UJGXhLG70VNS|v`KO(w_GX1^7x={PQUNC{q~S&mtqnv`|i!hJWD#XuD@IH`gU_=ih+qVoU$!`@khS@Z!E69@L3T+cX-7f zz@4W){s&`?pQwG7zG@OQacS_WfOb_-tG{>8gfYw>1M)*`|MqfVmI}?q(v#S8W|c`% zBt`GLdtV93E>^ z_RuFO;dAe(Ml}gzb9aj~_uo&ozMd!Cl&=Kj2}@UUsBVX+2l{ zWoICIpC#!!N+MOIs;X?%im(VRyNfwgj`L+6;)&1U!t$VjyIM0AP3kO9;m-bN( z{VTCw5Qsn%_~G|G@RqNC3*zwN!DTBpri81q zia;KF%bwb=S_a#1z#${r@}bx*J8CVQumVWUOS{I4JBfQ8oLUpcQYw%;W6(TH|D9kV z09q1>fblw`dmXNtve=o@q-@l=&Li1XU8aO4!z|?$zh#GpEV~A#tM=~PdNzgubE%D!qwevMpebAsr{L5Yz2t~M3T-brdGN(c zhzSYDEIKyk#?Ev`(tAiLQMqh98d>sme+X{CfTKh1mk5Y+#5U)esunrW6bW&`qYwYq z`)=hdw^T;-f%pFCzjo>n%T-r(;Rovm@PGkFiPgx_YIk!2fhw=oEm9RSY1DDGsd#Q% z*tME@6ih;&(}!gZ&};-cK(P>U6s3eNhhZ|opF79;0}l`o5=Lu@P`q)8G8wA$9ywwn zwIPS4LJluiHz=T5H6%N)Nayie^)z;#IuR*~1Nr;`D_bHu$y|T)DXkaIz4}#*U-LPz zww9}G%wWaClCS45hW{{Ne?KV+v~=8etc@AJ=5x63wXY^sj_t*aCdHg1XfgL|iUgqu zXx8KHj=g%0uCK0cH$*Zjb$Ambp&b``Dvi?Lm)xWwc1JOyKK%p4j#&2@M!<7s2FV$ zk~wztG|z7*E-&ETk>|7sDgmg-)p)+RtrJK>s~Tb=b`z)xv>_W#XVy8jwg%G~?e;da z-6^qYa0tE_ev0ILD$Sv+KDmxOajJKF7EQ|t!16QscNOnSG4?t%ZCrXDU6z{4UcVBG z_7&5`0;wElU;R1wQ>Tg%5R0Xpc@tB~S6Uj>dx@h5+@0v@e7fXXvbR`c1W8L5;;GY| zIeiAUci6nTK^r2I@q`p&pIa(`bxF8I0>}Hk9_syj_V?eu9fhSOX_wm8SH`B|(N1Jf zeu#cXnwP3u<5W z3H55(80>PTQZZ4JzqAv8s>B6 zTiYz!rc}?axvw!4>L9pbzumv@J|DUe?@B5}S7Z{+Xk)-t6_akUH5nJn(I7UN zi8(TaA7-gWv(PQCZyg*Ewh;IA!S}U+AZFl z0Vf$Et3>AG#&)9~^=K_@RII?w|XPKl-QtVWky8a`o6e z7?qP{lJI~5M}dwJzlf|u=j6y!Od=OpB+C!`Zi3m3%ClEnUVElyH;h=Xc5&Ur)OFX+ z0}vKCKSET9O#l_Vs{mLuGe*?;<6U{yc!ZyfIdkq@c1&z-5!*n!XlR-?d*xK{zM@hg zwE;gl*?dX|0Za|YvK%H}za#5D0tTl~6a)OK;ZHmMg2`T1& zTvb$~oTGT=-g6~iFfGewOLb%}(~sahqLyF zjJ$rVX`8nOOE{k=#O#U5gS8t=dvFu$cff#`g?*KAVrkF1JW1yBvXa}Di$NThXU0oY zcwka-)_X=IoTX9?+#Nd`Rz`#*IImcO&@`ADbzRd%m_%hM`v!E0L;l`-@FI*Tg%)jq zwk0(Uu?;xiB3-p_O2j_LFIP~h*FJx%tMWw^RH>XYSwB^{BXs2nQYOrHktgp`$(h=a zk5x!(+YpK{)n2cVl)S){(hvr|%aKy*b3|cpXy43ok&`M;m6%e_PZi00(B(Z;U^2$7 zO<3>xaaZBDyHf~YBg9B3-ngzGhwd4#CB>kyMyM+4l<0(U<#BZdb)6R}-3mv@$L$S2 zNEV4$?z2w1^7cYcl&NB}w3|?S-&YiO=(sJ_Aepk0Dy}r1E7QP&5eX^8%~s^*a(p`T z-40`6z~RH-+9IQ3A6Y4EY{|nQv<t_q6j2cHU)K^|s}2 z^b4DQwR7&&p7UKZq1>boIkUZeyexc5`7J4PGL?TrM@U(y*b7(Tijsz;!d+N?la)|g zDSWY&>k-8>3(EGaWpfq@?kp-xKHL2j#KH~6;(!5%fc<%Vuq;8VZ# zE4S?ZgIlZu?(pkB|E`~li(TSkO68Q1Th2wR;kgb&IsJgcz(LIDz&;OPN7|~n@Bzb# zF-x9{+ks0nVMo{UTiQM3m)fYAsMd1AJZX=jfOh1$#&zj95>~d9kJHuZmVa9cH{L8> ze=iMS?+fvBVY!t<>Yj+h))fuW06K&nKxYB4b0BeOlde><+?*HlaJuQ4yYpR z!dkWz`M7SgR`ae7sPetlMDjc-ue=}!=k6W0q1PR6AcsC)9L9Y(XaTc&y#3m}E4>&= zx7vTDoJ*E%VXv2R75;#%q5S={hqkagR!&STUPjI4VJ48z(r??Xa&fDnm9t0}-8Q4D zgb=NtfIBYRehwQ_m9LDhvEmr&SU;DT3 zi;EouV^j&MjGo{KCNeWqB z%ODRA52pRRVzOdrmeA8dI;Fjra9@7ie%$E0-DG&(|MnfX3shU-1hkiN-T@~YtNq}h z{;;ZHoye8BaUT!m4gb4A-@aZufF-rj{_pJHuG8-Rwax=r=x5Awe&RwLTdnZ)Mr1p9 zk{bhsNubP%!_+n4c3@RbaQRx^w=t)2_!6Cpiyc1xYyb9^$e&knXa?Y~{>(r9x!NgJ z;g#()4{wMAe)xa^pA9X!2x7x$Y&A?emeic2e56-Dnat(Hn2b^|yU)A3b2(k3AFVE5Kkl-kCV6`?9}3 zIgveS4`w&$pU4gScGp91Xe1tB@a@GiKX(--X}MS{3qC}N$w;a+RO|%D)0gJVWG!nA zTYg?BMv8Io0&AZXTmRaC0k?vi^r22y8lY0Bo!YPd%s+kqVV(Z)dhn%3&!^aaSOnU( z$p=@!(%=OgaC9gX4IQHGO*8Ncer0BiCWNlYK|LD_<*Capn~ky?JVweXdJzGFj=GoL23fNcP0cKae10}ZXk<}o;d-xTgRLlvk0jzWwI1ykQGsSmWk)f|1V#^nW5LqVHHY_ z8*QHrdM{vldEXxjI0o#;b^GiqH1uxPzx!Oj>$ux)X84JvLetb?U(i~>k*k$cO0))> zt@7Mf;Q5UPtJb?S;T;Gm6FocGql&XXvM^x4VIs@CWgAH>X4VQ(yjM~TId?s_yT9}P zfAX`3dEUcKVwhgpo^QSMvlLSv4ryYS5Jgp2JuQAdbmij5G##A8Sf39se!L>$Rq$@_;je>p za|xvA3c)d*g+eV**7I(lqOKiza3vvKt-GZ$-AI3&f3%wfzGI zbT*JmUaKUOK<=|nAjC*$7p&Fp6PF(TFCRPX^B?}~HQTgLe(2x-c&)}-odvFP{)7^w z&RlGF^vZF-NkJD5HZ!6d^U_ws#qG%Dg=cCL5QmUZGoobQA7u3cLrJ(!^liX^0mp!B z0Iufbt}5+7Qb&^v^PcVC*$Nd;zciysN<;>4-+(&;S#mntNDsNoA z>E%OrnH@>*|D~UL`+FQ|F`v&0>w1^u2&$d_Xd04g2OK+8$oybhvm2DBue4lh#$0JU z!S)N~2%U>QiI5IQNN2!+0j~fi^wdlMom^w~1_qFn$EgX6eNVlkB zGGM^1qO*a#0FoUF(I`2Ak=^Nx^>ID_|9;}{zvn2+r)g55t3+{JmfL$zMNR*`o(lwR9^sVWb-)Z$coezsJiXiCJ=Fo6y@ZU`b!yWBSuN+V;QcyWi_ zG-5XhqJn77E$XTcC8fSXc))-Gw;y64vFQ4!&pA}0P%3{@h|Gd94I`e|fb*M?R>zq( z%4{e`9B}Ngl$~J4G8!cUP8E#{o_O$sKf!F{$d)Tdn#lAE@BDi|H5pYQg#`}73B&{; z0$SmRG^zo|43VrBVkx2+hO$V?W?ON7vt>6{ETTe;fFhc!4u#Zv4F?Pua6E9Lg=Qja zc=sj2;y^2Q;+W@mjHj;zW_pTXIqd7)5dIx-{7`i`?+7tVnK}VaB(*ap<5Bp9cmBPf zI@0qW<-u*^nHOnx|LsU4qbe`ARJx$B5#!)J8F0LC(#cijzNi9`YydvJVQjU^EGoeq z$uez(7)XkA3IqcN47mLeEB}*}^Ee7ja&gFBlp4mn|J--kB=PC&QXOXWlJ~2gs6)$cs zm{~<4k6Txq5TC8q_J9G04eu*L2!xbvBUPZCF?PnkdDjmfy7I?<9JvAb#7BPNS0^q# zB_vX3_$jCe;v7R7#(-mmr4rWl^t52=XsFq0g!3CM+pQ<~apoM0#rV^~g)m^i9f1`A za4U(wg(J2Du^h~J5(KBvu%`;;V>pHKJ~;$e&JV- zx(!F4g*V%bzw^sK^CRnPYoruW)gsR*gb)WN_5sHVGt1=U>WG#}IGsQe$0B*oZzf*Y z3T($3Gnd1~eWjt?;d-b82K?bgKla3dKuQ5gEeI^6W~)&iyA-(ER*3pu!#mnR+!O-_ z+I|N zLQM*RXSa3l8QO143^{}y`r=Jvh1YHG`>^-Dz1~+nmi=m5y7qMcUTyQW?HvHDj1j$N zjI55M>lIt2lt@^<-YS^FG*n#P4Lp5$&Q9=1wMH`Vsy%I!0CA9l8*m%&a_kwWl5L|n z=koa{evI9hwvWDLx61$o-uL$Z{hyukv8^OB_R2gYj6LZaKv86{L`=)gIyI3&HDtgM zpc|kHI1*kGP9P*9RA;%g-SEO@))1YBh!T+6(;AqhUUeW(Qk@um3(_K_tXV2Tq9T#? z9+$+@C%aEeil9c)GBuk*Qb>Y@!jUD3Bq?8O11uZVX^+t$w|x%^#UM>9?MWz6v=kjE zh+&e5#HF!<=Bn}&jL!HI5{3}P5v3xDWYW2*CSm~BcK?F{p*zXWJS3CgriLMy~oVR1vcKJqcKq+_S8{((R6eC`hMRdFr zCOkj&JbGc5)}1DFL#$Juk|o{7fB{E=&!&4d0mfcQDKhfFeCwxq@!{u>s%`smTa%cc zdEwIIZ~7B|?t7C~AVMltS*sJTtvq70N`s)Cxx8!F1it zD~K3P)1c0C|GJ}giHR(zG7(vskX+wK1#(`Jz*06&R}6?$WDsR#J9#LV4=AQ^5?lh3 z5s5SwiC#z|I5X5hl9Wr94M(+nEjw-I+r3e8(4_m%=zN1XD?iYzJjawILW~I?%JZ$i z5GN1Wh%VOlVU+yaGRA~X$h##XTn#nP&PM$Hb90{ERu=vYqMGLz z@>tK;duhIl40FhUSB|crsP9AF9MI*7Ut`NGKW0X61Jy2ve}C>r{_bDde)i!b<^Eg6 zZC!po|B?57Vx;XayEF&r$#=V4+-Q55HEy(88(jAT4hu>`EM`~zibt^Pdo4A)tnym zr82>22|uN>dJ9rBYZ?UO)n{tfwPDN@6;GEvNS_DRg{#WiuPbao`t@KA4R^kx6AA&G zBTCN4${s$zjHr3-JVNl6L#Fv63TT$(LnQB2vO%SK+xO}qYa84?TIL z4c>>_KKp$17vK4xDr zmlrjS)%~hvH7CqurAVM3Vx@>_wd(PNb71DYKk3yQaz$q%X+lJ@R(OheBj#nZM2tux z@3V|w3AfzleZq*AH?s&9i)XU5mxv#E+{h!N5%sucTzkCt;3>x9NzMb^SM}R@0sCUV zJVr9@(sHcyW6cug9Md%7N?UPpbHT-}1y-M79`<@%4#MC&7;r0iId(`lm+UEYUHPmk zD3QvVhd%m?@BGh)-^v@q-|iDK+q94V(tF?Wm4D%XdG~fR13%ewLAnd&_$<13a&Qgi?sjJy+9iO?_^6IhU{?RE$GR6fTF_fNH^Tk*xDQkk#SAvtWW7uNv z%~CT`Xo*g7wZ|6iiM{_Bd+(p@V|v(gX(XYR>#aM_{mg1!Y8+2qX?SK67F6hpm&GjK zn$9t6sk>1Fhv$H!!S(Ew{YIb@NX?AXBhN=a@Sb-t+q~^hg5y~OP420_|EE9kIe zZain52CNGO3rUqEB{V=n(<+6L2Z5l93Ah_@oSh7m-!G1+u#ki;TGqB(B(zYK^!>!r zTh`^z!O{Ti;_bJ4uZ5Z>=}MJB{#}UW_P1?rzaK%HAO#ku#?)udU@@NP`@ib_TT;Dr z3#BgnyL`Ya5g{Nc5%63Lr+8vI;K-VEq*9&KQji-?W9| zLy;KqbwwMS1KoRlh}b9w%*hP{O0qoHHx2I88k5i;SwYy4uC4OA?3cFBIDW-%H-n3@Tuj=hd%Vf$6@@zad`j%*6uy~ z1Mhk8+3hqwy-1#_@-%J4Id@Ho^nQza@Bj`t3`C>n2^%^3NyC6hH&Ns=kd#s>I&er_ za9S6<;a>RDpYM51waYo*AZ^GazVd{&!BswoHxqk2fTl{2tR&)-9We2o6r`-g653qt z*|spQp_=gGkG>Z!Zm_mC#^M551Wun?XFi=1EFq(+@CF{A2Q?S^$Q}bQO5w2vki^<( z#P-$}qpHRwp$ft?(;dFxFaHJjvM5q-6^P8N;)TUJpWdkW zooD7;oL9_cl9TaM$eusvi>zZl)6NYH_zlO``=?hnFFyIHcU43tBTozg6^imlNse5(kgM+0RfBIZ{stThI^$1V zZ~SQ~4RK<*I0VB>BH`E!HBVd>p1c~l*i_7!WMv1j{7^`tpTtkN;KPk!mcw$fg>gl) z7KnV#*Z(Ol*e(r$(P)I89&@GH!PYA3(-RQOxn8P><5;%L>nx}fw0q5gs$o8Fi)O~! z+8E~?_4;lLAQ0FIghun5HpT8qcGbjZ3?UAXP4| zNm*UM%n%hSv69zY<`Gu&3azIi8!+Ir#r5ovReL2rql)pDas_$}fyu~I5xMx}r`~m3 z#vdFr2gOhR;P<|xa?HYFMx`*R9g5L3i<^FTDBmA&xX2@Rk21*0-`(V#<)?%>Beq({ zXI`B1(xT#OTM?^q9_?X)uWM2YB^*fcG~~dc^aUrk^#|U8P@=^$m<^oE1+>Q-b1ca%8%S(SLH#uT#H*GXnKQlr!cG8H;?TDv0BF}HO%ykX?h!``E zXB3aPij)i?;)q$AtFPEEXWBzHJz&7mp=lN<#-w&s3Slv$a!h~n2fz0n$Jwsq^?zS| z>cYjRA9?4ft`H)N#T@UIx~_qnmGEnkQW`Mem7_}#r)OMbxquz;_%>WkcKyZ!`HF7 zJ7qE+lS05bM@W&VU|zu~QRJ96Epm0KY)cME1Ju_fjO2u=L@ri=d%x~&Kq9Flnw+@M zZ-qlLXvP4+He>yM>O}VT~7dj7MK;*_tP`UL&QFN2xW@6p^B}Tnu$7Avz(C zd9y?s3PA?kBAmWFJEX2_yjK>BIYMMqS6q1dk#};I4ow*L{TM3aY1MU zr`BrLYGW*ssuE%h;615G#A(SDgObZ6AYv!m3n+!4R~<2Co)<-O;!GuQ{{zVR3tYW$ zfwl3N`OYrBs&JJjC1_)yll3~D%`%-&cOSD$vJipi8*3qEL&kZ|Z*Ow;%ih4buT=d; z*#H0_07*naRCz05I?M6mn2vcBe!S=va=NQ3E^{oF99bz;?4(E(&yJqvQd9Hs^9|>( zESNDytL*&~b*KnU0zq)v9aZS=OVy_qWrI@m*r&h&e~6(9v*`>cc{$^q;z-n$+xdU~ z);E7E)63IiZQpU89DqxYTsr^wr+!4l(3A^ds;Wj^#iEJXrGJtq$pJ?POH>3DBcx@5 zc$e54Qto?gT2>4PJkhdZfmaA_jg7hS7Pi$xM{Kj+y=gIKPN zr8Rp23fwT2G6RAmyh;trQMV;aGcsA{G{uEV@s>h2` zp;UM(JR?8CLL{{TscOF98^0c`#kqB^ou@X9-+yk-<%MUV6I?x^XxvOp_DS-wl4#EFOeM$D1g#Xah&u32zXlRJ|}R%fLDtBHi%eUZk!_dh^vzE0grFiW~5XQD%tM+`le_)V+4S{$*sN zunCFEJ1n+Hv&-80DJC9jNqFsY4a?Sfk^0cq$?m+;d0dN#T7Nkt|4$`{+ecsWCCtyC z=i-GI(FAopLV!iH!262ISEwimIG4RUAw;w!XlI$ea^SM>U!tSy$uHRIXUw{mA(nNE z9f~5T3Qir)Ip(t|BVQ3iplu>&PM>CDI%R{%Y`x}-zWrOFox`Z2oz3wmcn`!A+XZCR zWr~9O90JZ|GdRFG*lLuEag8Ug!Y7~IW>Me6G*u+DfBx^^I$Se;_gjPm2E0P7uHCfQ zCa(0io(4v8;Dpe){c%Ipf-A)_0Ly z{FPEaX49&8xC}gi1MUPEs-D&yk6ne&Tx_`9*34Q%Q-ik_Usi;zRz&ejii;DDq&0jfw=3Ykw~zR7F<@;5Vn<7>I3En0a})3R2N&}6i2OKXWHMW)Sylp>Q+jWfep zR*y)Mh-w5)1T}(7M9o{0r4*T4*}CGL&Q8%}Xf#~OUtDbM;1i6iF-;Q~kJeZpuQ9u_ zg(P8dc8#z2-tW#5AZplr#%OIqa*_?56a4(jW5AQi(JPW=kDr14eZ|1Um7=^6%q|ai-vXZ_^nto|52JK>w8;!FlGl~1&@)qV7F7U$B&#~_7 zY%HonRf#Df2$ipJBE&Y}BnR|Otne`|55CXYST@J+gJq^4zD zjYu)ExjSW75?4mTAN{Ux16o*LgP2&%8+=_MzM^ScROO^P01I64hIg94^xS<7%H=TT zg~b{ld1}G4n+aVz$D&P$%dy_U0Wjb=p|Y15U~f!En1#gYu_J`QM4O90@qK^pJ85>0 zMfU9=+))M~&2IZgzUt4$^>eTK^NZw}j2tmhR)hv3MBAIxJ7Bosd0#xl=2gr(?1(QJ?;%VEnCS_A+^0?e`jXp%)BOqUN)H=bb4f|L>#ThuG} zy!p+XZ2}jbd5%-T@QZ|+;AELHA_iU*vCaToQjG|PGed2;uuLK(?F>aLG%i*o$_!`H z=bJi}@5MN~Klivs=ulM>W_r zHR2}*Ig*p}G*?S%lti$|Mw;-<&WKOH6#2}H3+C0iLh|ehF;Wd$@dNGvsANX~u#&Qt z(|ksi(u71Er(Amc!N2$L2Y&oR$JWpTaOXXH*6y49?Vo$}u}f24V^Y}uE#bs4gjh=Y z{V?_i+yRJ|b%IqhQM8j>X?VsqdCTWky!CU1*Nt~Mt1~1CQ9SDETufkrT+@0o3qz!< zzy&bHl%7c06;E57H~8@weCFY47BlMg(-1xU-luu&Kl}>kbVOa(nN}~x-m~hQ<`A-^ zUYmCnCMl>5hE9xB*Tf6_GKeAQOKSJEGE2qToakKfft)8ulo~U!I{7G-#|O1 zoi$Wd1;BiF&bXdHjNpWjBJKpI0_5uZd~K9~5D_sh!4a_%>z4CVzca{ebpq+(tum6(8 zt3LlrzbTsb$(1?!l9R9p<8Q#70xb)ZM9x>O6fk3vgeD57tH8K+tocM`O{SRK z#^alpn1Aj)yy-i>h0)i1HSF#Z+LlTyEF_qK^4Cm!96{`I&KP&l2;a4LxEpb#?Pj(}OhJ7v~nFQC`u zV#S3W-f%YZ*4Mz7+-uzDHW?EDN6;}KCB%3#J%G?vMbpQ9Q|ARN9yxCbjVpwVlA!iP zOGt`nU4t9LQ_u6{2S384$DZcC(S*}$>xB7?iLY^%vPZET#DLZ%l4QOKttx-2VfP zA5y9oosy;9$mE~VvJULV&K&AB)+%Gqr55YTf;uu@8LgxZ8RV?%d%sIqUxRdq4HNo2~zH zsxgZ;fhEpNJiEJ7>hT&|4UF$h6L!E!L9b(4{w!1gorhWkPRA>}?RCNz+#`J9*_LxM z#cQbsKEa-B6Nn`*&zYjD!VsdQ5}r*0J{2!sp;2sn{-`skYM)7(E#Una)WZu`;py{i z|G{Hie&#$|o13hytubC3(Y7sOuvS;N7;~9qPLnaI(;Z$f;500bO5TW4FmEL6rlE4d?v)p?~;o zU-s23cH(ij^&s521|aZXedAyK+Hd&l|KPuD%@g%_jo2=*7|?1=#0{&z0mqAC{5kU2 zj=0_c>_1{qr5X3@27m1HPw~dHEq~;6uCLHLV}Sd9D#`6bC0x00tA!2_in&|+lVG)8^jSw234^~EX+CW z+V{WxTVD4+9di?Jh&$eT`n?B#=VO2J8@}axnvi@jC8CHZZ3xtrzxe?M3^*#t3bULz zI!U?J`Mi=Wb!L9T?rZ_=jC;B^UYbzp=ltcT#OMH5awB`EiNE7#i&gAb4?3P z$iknAtRsv=rJ_=Y7l$TAVkD)MRVvgGQ=1h(O5?lecJIx!yI=)=q)=M*Txyi_^D&=( zZi^?jJdHm~EEV;ozOuhgvAm*U#rwC?Sq2Qa&8WQ6v;pruF&UNu5*Mtyu=ugR^X=c< zTz>kF(EPm~?)atC?js+3a=!86|6O|pbvP$93C1H&+uTuwrose1rL6+Z%u7_ncJkA3%$+8I-H-m?tj>p1Il*{OLmT zvQpr2fPrU)Kxy#)4LD9TZDca?ECM+1aOxO&m|uP2hjt$M;8VxlzMJ9hSUTPFd8hy8 zzx?e-X0rC`5MdT_dG)xi2qwtz5EyVw=n6i%IjS@M%(_sZ_J*Naq>{iSZ1PpFpYX>vUY53U-~>{neLFyJ;~ zwc2+-_HfA+4m#%@3#*th;WN)~@xrX)!c5t;ieNr_HEuGQ^$HZl^LRJIx|nYN!Yg?o z<(Rvu;_C`ip>112$R0Ri=4Y&`3SX*nW6ZgH6ob$?hl=a$F(|owDV1D56~sHlJ4}US zMvRdd0=}y7Rh7TfmawvOnX9xEr}W0(^{&BPjnzAr5bL&UKiT!$Aj&j(F1MbGiwVE? zd*ymO3P(FI=Y@cd_f_wU{f#vj}*9zcNc zS^eAZ`S@?o^wd{RZA3I-5i+-$6LLcLew3B|s-3uJwOC|a1`K$mI4JCUQ&?nV3(j$s zH@*HeUvjqL^Ur!F+M=;UlxOxU8g~N*?8iPE;6Pj9I<`f$YyehHaAK^ z*gyJ?uXr1a?YrWke8(4o^au-^F2bk2=qvu~?_PvRz*D;wGEm76B9Ud{@TyEphrQG> zE3vx)16~1CK6^6SgwWyvf!&wT@o7#^DnyL26U+iBv{ZH76_ECpko6SBIYBNv(e83j zxU6i~{<-gu>woV$FTG6IzWu?+JSZD&xgFH-o45JyMfaS|J1GR-%V%mwj7~0!F=1hz ztyJ^))x^Wk?Qk)kVOLINPRy6{ESBXnf1m*yaO>D>16*S(bg4Wml9dL%5{*|OC8J6+ z)?DB}{;Rit>xGAZ|HQX^@0ZqVXWpDdX`}TwB3EB7Z&Hta zm6>}U8iVmS;26+NbOFy+tL)4Im4k6zQENghQaeG!N-Qi_3X2&ck*tFtMM?E8H~t3P z)evH_XN$*A@`fa&kUEM1Qn8?7BYK|MNIdv_;Mr|u;noYM>+mcda17Yj@4Bby(zCp3 zQ{y|G{_t@Xg)cy?+GzguB!W7 zkzOjQcmjK@tQb2(alnA%hDhcNY<0r4iL~=6b?sRndB)BdYeHfy&mHSG>8L}b3pWlO zdcbiZ_5Dx^QBM+wi6K%Hax9m2FQjIZb)MRcJoN08^V6E`I40`oxozs@P;l2Jz%3sC@H3a6edO(v3S4R^ z5|MjoI1pWKD;V-c2Ha^#z`~#5@!eDW_A`N}HjT|RVb(bE@Qj$ml0fglJS1PdDy!OQ z0|wlF?9FM^(kEA5H^)M2HqwZvHX&5O z$v7iZzUcInuX_EMFFq@rlPxBGQ3_ovFprp&uy4RL6^RHv$_+Yl9`^vHHLcjpjgSs}o`=9#kZ~oy@UA*&57^lc@ zs^FPQ)J{yXm2tZXsKcxfk3EGD$eck<#`>sceWN7rS*$Z;#*k^ukqRPsV+mp~2r_P+ z(V@dEFzL{N1cZRmCfdLtjKpy&^mu5^^0~vFdsi&$p}^Z7A%%>)Ik>|taRv|gGJK(h z2v`D(uHln^`S#Zwy76ysc|r$%j<9W|gB#xWJ0G-u_<>yNv25F^e;u|HR0CFP3MaU9 zCJtqR!vn|753F$CdXMAHJg0SzS~C^QXR`ppM!%Q zw?16*z$xWaozs{e&c;Og?%t)t`Gm*fFFDOM95pTs-+#mVe&?^AfZ;tZ*w$B&-}&k9 z{y7(_)0qiq@HiV|+E!BA&MBAPwrgu=BHH16Lck&#$fcpM0V6PAj(bPD_~cz{+`XD} zXlNNo4{;8wHR?yP`n|h=c9=CRpvitq1P=^?;Z*2xV8ijnBc3}?Sx#35ll91)Ap}K( ze?$}Y4jpERX=jC?N)sZd5Wrc`;K@uN(`x0nf9kt`ZgwO6+Oe$(ASdrV^3ZKJ{G#(C za^q>L67QQSGelS!0?4q#{$_&{QS4@i;%?z->4DA}8;Ccvd4l7uf!%-`pPgg?D}aW9s@ZDTASr z91$3lp4`P0N7XQ9^_n(0B<|ZyKpkcYNmc9`8bp2Uh9H(E#7U>nA(!MMUU-$|$xDH& z7ok_JlJ`u!k?D#+I?ND~S;~zeMQ@Hl9axbb51bahbTa48BSVJ4p{|E97F4N2tQJ-b zK^dn$bm%Y(Om~!-<_Xi{QPp_n3L6VQw4yKpX@-CQ`>*-N?_h9pTkF`{vj}7w^^gMx z4}R+UZ+h_?FwO-vR9+Ed$H|?Wy`)+b$EhwN9XiYqZ51%arrfAF4F!dYjH;?BH&$6# z+JV!CJaeelSZ5LKuAm)e0~PQ=$mja3jT$!W68D`7+;swOJ?dGhbEKHZITx#fLsYmi zE>^$O-GFzPEhcoY?f8-YO|9M(FvbwP$Dw4@NWDJ#i$DD3m#^OU`Q_P+`rP4yxOyD? z)cfx?Ho2_O=|rnLQu$^FseKYGGd>cv57)rrP?Kre1+$%u)NWH?%L#-q9a0ws8PB(qAe&;k$+yFdF$n=r zIfkSZ9976n%nh6?GNc*#55MEh-+SWre>^mk!9EVSa0no9;_iPw^8EkfbqkX9UZf_Y z3aOQQWev2ue23zaoPNysc~(2-J`v>!}i0Zw{*Z;XI7g0+IGav=qwI&43TI~FD@qxR8u z25uB`XK-4g8z+A6uix^zch6#+j~6byv#+;f?ib#B>z7W4`D+911QfHYRFy1qG+t3v zoHd;nRfqEq(>6si)quQ(QBOuqPlqhInx|gc=UJC!?9D57$$&+tU@d+)z&c5pzNy?e z1XME`lVe;)2u8aEF^$`N07XSBs2-!ApiDyBCNaYDQ$!vD>BG zbU2?N0*w!d7@UQ=Zer>UcAT1H2<$K$_x}EmKI_?xPH($*Z;yrxN&y6*DeKjdzx8R) z`IgtzI6{D4Cino>8p=8ld_|FGG<6m22|9E*kI+^EPgk#xL&Xx)7rZzc6)LZ+tPU8| zhWWXiUXf$eLp>myD}Vq#KnRi5*&J~$7D#!Im~?d(ruq!WR$fstl%xnn_0Z_l>!(^J zb(j^>?|+u?f2;1rMbBKO6*yy1i8slrKD8PIj0Nuz=LjZarGn)q=gt#w+ksUMR|~Ak zB0(~Yb(_CmCTTY9(xJoo1m9F-nWL;Ke1ObZRF&KrY9CW^`jq_LyWac*$8Y`QU9%qV zxyA*_evaSy+55lk2Y>czW6bj!??D_vvj6}f07*naR2@2; z|Cm_C2tFukb5;i>r-y;e#-ML+&SL8kRuv>eO@W#Mj|ByzL#$~qL=|ts17pV=QI8N1 zYK%5%Nj_N;l_wR`g@b2|388C=Uf4wN&Ln>Aer?itB*OBD>L8@ldt&bTd`)SfkT5T4?!|Kz1XZ#$Zs07w3WliQeS@*f~;Sskz zT=Hg;PZ$z$CP2k|VyEB7m*pq-PC1 zc6j0-8aD5{wtbaMmK2C>-;w@~uTv4ixYS2LZQ9SC24%G}91n{;xL$DMLj%5aOj-5| zglryT%o!xFRsTBj*I~P$pC#{Ai8nLWfYCs~DE#do{n{&z-TtY&XFbNp3l}Z{1diSF zg@>O1vR7yM+~SK%FVt!%oS+J26O*625O9ZW3yHzJvi7(vM=^|oC5UBpW5oK%M}HZY zA(_J&a8e-z0uB)y6a6J5wMVvu1g6VE+rQ0tts>BcfMVVfW* zl(okggR?^E0Szp;23 z=v2TC+Z0}*4&c&R?2M9&$A^HI46O$2nG>#Aths)l;mU=;9$V6vip)BUwWzOYLxP&r zz-dgvf@b_0#U>;5fJr%J9cF>HYP${bwpH12jtkQ)Y+MCARShf+hB`g(5EXndY^dc} zDI6Ra4y+k&KeWbjnbG7+1aXM56b`Cpb74nY_1mGtc7ZX__;?(*_Hc7fnG36*eanwM z@7owI*Rvkur696--_rHb+#jT4M=Ft00LGBo=qX0uLD*X^u}5kwpGlPr&I0 z>K&d~v{l=2?@TOtWb*7}$8A}s|4A(RQ4Ax^Ii)#AO2<8?g}ax9TMuop$_`39Ml7v z7&hSY3=xB>#~P0%wURRqm5hKTXe4@yrmA7j6d%N>A`)8aF~eWsB8S+iJk7DK?byP{ zK&l1~F}KO2jxie0;1Mx2>e%p>BcsZ~>tSFrUME8JN$Mh33>>zU9@=`60^n zi{h^KqMEvUS3Pg{PyNA%ZeFX+6}Fhe`+&6?>+^pVb7}-lwn(r&$|klU z6q$7J5JLP&F=KMrp~H5C_a18vz8tWag@b?ertf{u=)f12XFaYb3KtdoX;vQ|+8z79 z@Z{^i;WYvh!(d%EgAUstWAm0|{;SEhr8VR=qKL5slT(pX)`68_!^%d@hPO!8BZ$F= zKxUN8dc-%Nev^%`8CRPoa?yq$JInwvXLFK^N$S+%r^uflhlmxS4wm(hb1E!wvgvc* zs^RAQm$~mm$p-V(`Oa8Lu8?PTTrfBJ#(1Rp)?B8WIy-DvXuugElR!Tc{oIG&^Q!wl z@vhrvJ*+1Z7Zm{nIB?@fA9&#_Uq2^eUZf!q#B~I)!?uSJlD$hLY7UQ0t-ZvgP@xJT zru5NBPGjd-Z2+P`UB4VBHUcNts%U|b^<#ID;IWzFQYN5~8pMeK<0A1>iGO#P5uzPW z>|K!5zt+6F?E_~V9?QDstTE3iKgY4M;GUBew>?~O%b^Wc!aSAqsMOGq;he*Wp=vyt zHJhTyq+TM>sec`|I}{s6IIS?{%3I$5|Gx51W<8=O8W-m&JhwalrT2W{)1~ykVdxzy z7ab4oaDiYP`V~+Ou|ih^RuqfJO9lu&B|EnYVXNAe9&)41v%wOpT-py@b?Fk zb8LB?m60+si`1sTT1QY~zG$0QDw7+F_+9as@l)AR9SQ8PT_Nh}+lE4iH~#LcpZ6^c zmaAEh>50b0$$aXezvGTO|KS^6{I7n(OO^$?5LSoniHZ3xsRKha;zbNiqGz#KM3c*X z+ebJO#-0<5C_yqt6s(knBP$gTuX`HXrwKxX17mUc*il3nw}NY}gFDOyMkhUfAyxMZ zjL2EhIgXbFM@JcVEyEWNH{53$tL2s46_(EsESwS>bg*Ixa)KN)~(#*3_!Qtf%PM1Qh zpsq(P8I5FP@&}5MkO~i`+mW?{Nx@@L%v8&=$0y~YwLy8J*XLr~la4DA8P~XrN9*+$ zTfRjr9u*~|+)mL3C5HMNEJJ#%XrE(M!Leb+y(@6@p%M2T8**$z8Ol6Wwu4$Ssvxli zR)PT5KxX3c)cBB$on=h^NExQ>J{0NZ$PVW(&U!7^fQV91^T3UN|9^k+FW>Uf84hu# zxVTTNcSV~s@fiC&Mxu8##R@l_pn><}N<0b*wk zN&CZOAU3w^^Cc37Km*1yLI{%KtPnhmD#J#|8F*o&IV+`d;I!xPs&aH?NG&}Y)1#6C z6+6B;XsdX)^6^Iu>$WyS30)O%hgrk7t-R84x%E12h4Hn#YCO3WEP>1h`a1g4-~Ey6 z-$1!`(S|U((|3Mv@87-e)_>Zl^c!p2Bd9Q_0);d9pco^YCb?+>XwsdqbXAZYwj(r< z5z}58GE^*0nA|nDrq8*S^mIT^hb(2Dy$g=ZcI51s@3ABIEM$S*MW9DTE;SaxB>R|J zz#1WIN+5tMsH#Ao=Y*<8&7>dq^jecL`Irgd%n%9SmmB9+j0s>65Q~~vUO^Z}n-)&W5+FH?TH@fp?rL9UGcdv2kKFqv4+y=m;RN_{^7H z{kq@$ub;2X+@6v=I)iJ#7)c~=^Ib2b&Ir&Ezz*9NNdXiBios)3$ab?5Xj5&m4JB3^ zEDg>GxiswGJ;%N|&*clkQs&8}q349c2=k_29`Lr5W#%}uXbYXs>kh&yakXu7$HT6Q8b>6!Ks(SVrf^;b(qMaGa`Ttde3>2*%6 zH>?bm)k;`vEXT`?l_sOYG4#=-#2AM$mSB{i0pkPWJz~rz^7q(?-((9wqvxIISGVxB zEN$-IoGQ8JM8oYz zD<0l3tk#Z^naAf#cvH||snYea&3|h1^@M=KPZYt<2CKuiMCvsyGCr2g_;idnt(h}4 zK9E_1Ay80-n?L@6SKjsEw|{Yl13z!jo%vJvx%b@mE0taRZQEaBRL29TJ)q*0--f8V zyXFqtAFayQ);~?uq0Pa3o(mPItg1a{6x%-6Y=!w&;udgu*4$bDN)ZuLp(!QAv-&g(S;yHTEB=m_96=61`k{`qYmSTFTe-pw(p zJ;qp616E^lc9fbYVX`g>y2EybS2k6FTAB0|ZmmCzfKL^vL0d8ympa6XQ7dsB6si#4 zKhJBhB9&58{k3?X=WnZ-5(77F>mZ~xHs zKfqx5qAmK^ijKZ)f$Vw8(yzSZpFX=h;u(_9F-j>pIaTb1YJ`T22D@1~>Cj=DVY(U= zHs{Z@#?nFz%Nl&_Dk3qYYfTKYjH()Igd)$e0+o-Id7=$QJz{JmkwGc^8eg|_l@~pA zk!y>ZdDl$jDpGuMEHNsuS((~I0LQs^Uz>XMwdMfol=?VP`8E^2DD&CK5EURXX#kri z@|$`rHw`{`M&44Yty0lRzL@jI{k))(l>d)H<>?DGoU?cY`mPnFB3 zR{s9_Z+Y2k*DG?bQ44Y6$I@~TJHG4he6TufR~VV(hnXqz2a}WsRZaeI1|uQ&xQhB3^-VHD(KMJeC{duz z?~}w6HHDrPNv+W0fKvkASGbmT9lpwSYQZ)(WNzn)v5M+btXwDSaSmai8ExR}5luC~ zmjkFr1mA!tR+SBzVi@Nt+?Q!U`DcFe0&%SUsxACot|++P=^vWAHXK z*3DfVwkxLd@l8_y6ljPh_)07US?byK|Mm7?ed+NpeeCcIhkIV4Yvg$r-1d<_z5SWr z`idXld)>FZU!?$|Pn!59hFqMbt~(2b4%-|WD3TAL0$yxOXX0ZT6{7&8zzRaNMG``6 z9Tor)g4jqNg9intH3ZL`wbW_}0zGLk)f(CuTo!OvP#OqOmt|5IEz*(|BiO8$s;!db zC5B0JTGI}!-JtPy#qg?+ACHAeuHUU^NnGr;67G2_uZ@;mQ>jdJB|wLzd-}P8^!YJvbKo%s8$ye&{SYex2~w zVY|bo?1|DVd1eUS(s++rH_n00wdTQ_KmFR6=%BsPpCg~kIY+ocbkG6|PENn1xW^=copvm$ml}F*RG-?TAV+tE7 zT&z(AvnCNpRXm15OZMg^S1iF^H)P%JqAw zP?Z>CA_>DsbQ26yCCKpKq1Mt?O6{J$b$Q_?-I5_xc8W6+^Lgi7!Vq zqal8{fi@MPt_V#-2sI|eU(QJK7qu}r&j2p{7Lnf?3`!l8HD7Ri0E3V-uG&tdbfV_9 zYOYKO@|Y-3FkScqUG$>E_C{2>h2T9!o>7JvkwBwu)x3<}{Enab=KnP7ah|W}PX9;4 z+-~=#KfCpB2BG-&Qe(39a8!~P1#=mUss=Hgh}vPBVyf69{ww1=v8_Y_&g}fq791FX zo=tTOKIY1bq*`K=QF*AbEV0gW_YC;DJtLmpTV;~!|3uCtfzvP3aS=yUqHKCoXpN=S5JV!+3pKsm zk%{8i5;9E%CowNCwn`HeF|z3{Rnc+S!U8Tf%fP7OiArL-4n${_`25+|s`{wi-V8GN ze@oJ)BD~IQ?g>2Mg7GnH&oVc(KU}-PaF%KmgA(YuhPhnXw_v&V!~pWeaUBVAW-GTx zDoC5QgxNgK4jr~BG>|((RgS>+Sm@`BYQ=>SJ<12)`cvQjBOUpBbac$+%i-j`$3O7a zUwHXKuBUUWl(k2Iyy#Ka^{hwNp~F`VuTc7!$JZ{?WY5aP8m3*Q35LKp^xIbCHIh?H zkCL2PEv1+Exq#6oevSm3gcQb1vRBIIVVqwloXtde60VMmh6X}|hFF+FDo%+MG{mBn z6jDCh+DbINezf)EHxM!_<8@{wb_;43X_dS%UNp3B%u~zQky$3&Km9w55kvGn>zQ{o zb5fFNg#ejRoOm+vsRA-CqLXDjhPH3HbdCibE-ch_Omvi#o z)WdDF8{B?wuT58JMQ_LXNDq- z>YG0L-tWEnfBfMMvmV}dKt}){BOd(R-`@X}Z}^uF?Y!iQ@AE2*>Y5^RG@+YFJ8Vxx z$CZE+#U)iNwt$;frKX{&JC2OsTTo&NsEJca(9NH34fGh%(-GJ13|u=u;PQNh#Y|9> zrC!_9@?X2OU#Vv-n?!#O$U=!Ii6T&wh z^3+(T$lzG-Q;lnh1uxJN&G`9B44bzWGc}G=m18aRI5x@{QIOe4epM{VkZ04fsTgF_ z?=?m0$G?4t4%-i2!C7Hc*7R~qUuurs`I*=MuQ$K$gR>snc0ng!eFb>muYB)28Lj+Q zt|djDGpaUuP^9M6laR}!p-rIg&|zjsMIcT#hgD-`?%6BEB)xCCfJ6w@Y(la^;y2 zstE-&DU7&9k&E%wSU@6{p*NHv){<#6qHvR3Gh02d|tY9HzKo*NhMDPY0@pwFnPlRks?%;T+TXO0i$0dfHHT`x|3SU|_{a(nJ*osC) zP}C6(U{Z@o8lXW$2}TIUVhIQp8azFz$r1z9aaFd0`f;A7A)sON&1rl?ynv3i-LE2j zMbizgKE@l}4jmo|y7fA!lW2sbBC(J}YHL7!P4ErYOs=hk6AC||C*`}}_7gAs%^7aa zwnRq&zfx?R(BFIQ^WQL^^U2H)#!5$7mN=J_7d@J$rmji~H@R?*y}CNW*WoCj=8I9v9?xR-UB2XY5>-Ox0iUQytziPu^qSW%oGFrV{@-+S%zf0B(8 z-PQFgL^lh3HCR7Z{=vU_<*N$Q++jnBYQPvr9bi~_dc7Wq#itwOvEr95Tvnj4ap|h^ zI?M`D#Yt*acoa29CRu@7F_#;1XYeXmE4Wb7R3lc04WmZUrXshnZz-qeqLDOt0k)wY ztpdc(BW-1@1$CgV22&zhVts}6V7)};Ftul#?!!APv{{pngsq|V#AK(Ism~H(VVN;l zZOB7SZXBTr_@+cf*t67UE{pri8OW@O;dBjCH<&^blu=pXLl|FF&metYg@V_S#}4NT zTd#vYwQy^&T~lf5={-3F55RvMZHPU}3Ue2>#j!M!Vnt?H6Bi>gK;aGV4v*uILEh*MQXnx1I{U9slr@>!0^( zk8yQ~$=%ingUXX<+1MhYC3@q^OB3@1L%L({&|ww`6KyIfNNpjLPO4d_x?4=cYfOLe zL1Vw%&|r*1#n3AX3JV9<;fC8D;*JL%X2&J_x&DeBY(`!Mj=XD9KxwKDiD%hrAWNIs1nIy`nL znZ%pCFi!S}FcOc;JkJ=8M!2jOI~0ZJA=cPn_cLfd_c*bx)z8 z$Djd1z)B6KZA0g=O0q@C0Lz%&NJ#yNVSLV39;ajn ztJxlWe-EF$XM+!Y{s@D`r_kGT1*euz^3cP}nEnzwdhwIiE68mm=5<{$-^*eVj)9VNrl zN9p^M%$tf_8geRZASMEeOQBzYn&=Z_#^y8e-`VDUZ~gZ6!u4f`CGBf$V&DPPpuV6o z8OyfMM!uW1Y#;Cc%tPFA9IDn~YUk%4s(B0{%*>dAt0-4(Ak8$6iYI*c3Hu^X7xXTn0rLaQfgK zZ+iC|U-H%&jP`;%%$`-c~?*|!8uiSa&Qtc|LQv?@!yP|H;>}ch?g8=40+_;Ud{w z9)Vlj$IV~5g<)Cow5#?rs105+j5ZWnVF>ADv1wFHg?qy|1Ptfj9qeNwq-oG91~D!v zAA(}3rN?Tvi;ZFzp??W~^f$M0=lTL+=_xrN1k#?D=P@T%PVz(YK|*05*C z97_dM0s2K2t!I+G5AEODR#vwv?^m#Wof6pL9KzFH2L&Nu@lh2_Vc{kyJs0PYoCZ5O z`TKwJ^DqDR)Pq?M{enP80M8Yw4Q}|zdq4V;?|;K(0^ihN#|O3%psBDTSZ8U1(uB?V z4jno?(NGQJu!;~6V=>kd4VBHfXbGlCf+C^DIY$VA%sC1Rw;WTxbk~FQckSnjtFB?8 zXIUy@fkH8*^wJgk348a(Nm~v3@+xwA>i`pwdYF= zHDYCoY|ZinO2leBiY)}tL^Ek^^XT#dG+JBWEWui;CLk`OBxBk1Dd#TXNZ7;MKXM0$ z{2pX+AM=@EE{ngPO$wh&ZTO0!&)$8PGHR6D?|F!U%yHSGjaEEqIMZ{Csv^w@D-)kW zBW6qvCqq9|?du3&hjWG29V6!ZDVd4Ax4m!hm~pkQHA3Gs%-iz6yzO<*e`^^|v3Fdb$D)qwaacC0X23K6C@ zZ)V~VC=v@jtPvU?$ep3~u%ibnBlz5H_tW6G=4sc12)T`+-a15!hma=vw%x4{Flv(P zOT9*K^*&zn;%m8XuYr1vVtANEU18n^&D2z3YyLP6+X%Fym46g&9MKfjTU9oOOWMKp!KtRdwK#yLZY zzhhxxP{-dpDBO47eU$5`xb`Veobc#x)5-O za|5r$^E%yxX5z`LMb%?n&iZgfo)`3Nz?LiTe%tH5>Bku?&))m#0zyYU9uM?(xL^FU zoBv`M@>ezDXw+g;5y+^j$csL;pHxwH1hB&_ps8|KY?joY_;@S)gaB>tSP`N2(92`~ zm=AF8@gWaA_#l^EekGS(emTxe?&$Mm?U$z%x5~%oT2*oSxUZ`b!eqr*FEDCj=OISlOsJdh{6D zlw5n|B|LpM44c?G%UQt(CC@C4kK}&5H4>v1ErV_Iv08Klu*11R+s3d_=sRfY3Tt8_ ziggxW$GqTq8U6R)d-ZdEh|y{@>oH$w=%~lzh55b3FTMNo9~_3_dq%a#xSSvsYc0dd zle=hk*^$2vvxEptU*p>ryCFmykydGvREg&-td(&4!BYg^u>aD1EG#Z!B!+s8L~lSz zVam)zvQql^coQPQ?7R3{pISk!RuV5lf!YCp2(H`F+czU^|s*^9KDuq-m+Ug^3`O#;;lF{kT==pI#M?W4RvT z;U+5JYRNc-#HDb(Z>xO6gcw#nlEstDD;z#_kjpRI$JbxpBTw1igL?BtpnYE?k;>Mh zmW}{+IG51i5fg2mLVE||D+&`>%=MFRdCd!6&glbP#mD1>t_bAu#OQSWzd!oH5B!T) zz3!!Iiz{lcIOk$=b~Pl+vaUC9hnb`8P6P2yTtkDk8P3MSfXqgP?z6YtPg#4ezUIkX zvU7p?eBx$OCZaN*F*Z0K6A30MaV?QFNm;DJMAfn;lE8u6$-~E&Idb$k&${|jhLvR) zVs20`7p#GhD(q1|>UQ zS%?JKPCl<;3U}Ri0G}9k=!!r(oI_~9iAS3Xn`Lp%(7;@7DWv-B@4w++yo^)#Z_Ij_7c#oD z`3Znr^@81Rdi&pee7%up*G<4$iwz|q1cE6#FTf5nL*oO+NK~#ugJ?ipju=Z5qUv4z`&9Ps+0A@5A#gAWMJiEEY>7(S)~Rjn)D|y5QmS;K0#+$R+`g}@Jw<(r z{>CAG_@!UZGk1*GIC+45ZjGgEfNYf5ymw~E^@)bI@z*U1U^}x)Y{yo4Pge99HNv{g z(JWp;88ZIl)2Fy&xCh%?IO8|+VM3Nodfc`l^;Ru46P2~)W^I0Po(gcX8(HWoiEWt zH=dgH5HECe3g8og)kDKif9BKw<3-=~s#k#SVLG>FJfTiz@aYSulGK^$c1lECa07@adcGL0ral*Imc%rFrJEMEu(DE)(*%Ro!dz(Z-!d zQt^jKvL~5RoFI`I6F);S)OL=l*uxiYxsxo*c;+=%&`7~(IHKP-*m}UE2U>f6Ofk%< zKLL=`Y^p6so?Zl0lEV1zZzS(PPNx{}pl;C+Ah zMefUF`~Liw~2q-K1J~8m*m+42Y z=NyuXIBq#I;Guz&w$%ok={**ne?V{+`B?GT)PZrZwJ`h9J|Li@a(dK@8I z!}j-b_~bed9X-X7cit)buge7Li9XT z33%i2#>dyGMDiD#^v2H;2qMwASsj8QplAq4m<&7)!+^1fv3OrGFv7Cz#4KIOEhjAR z_=f|mUGk08lE(s?sj#nU`DRN1xBR%%VcPcp(==_Gnohs2{l7C&@muWY?A&)HYh~c> z2M@D6GVGc!n9pKJzujLpV{MrM5^eaF3lKO$q9+~yFT`cGb z;1h^u`M~O3cir_rpZl%f^Zj+>7xSW^E=Tm|=BcZSvhj#<2r61?{XY)Ko^e6--jikVn5pXu=Q8@4p{y!EFviAi9vM8m0iU_$ez1h)8`8}-Ndt=b`6V*yI8Fq zq48K6oG4@&O*z6A(L0cOay~^>PE+3jA?jyS>Y-7*NhBIDYLfbw6#AqNMsg)7;;SeP zX09J!(|B+W$uiU{zNsNM3`~zxW-o633jXQ-5r6sV2l1CahxNvc!@A>bmkG%}+j)Ji zQie^d#saQ4&)&V4FdD3L=RNl`ls;GN%u@s+=3KU(fJN%c&;-ccM0Jee|1cr_l6G*4 zaGbdx9MU-M;&H>ozHpsGv4r9|Mg?TS}(701aTBDRt87&%O16l_s+(c*cywp zv$`Cd4vzxW5GQ3ZQ{HfjF)}G2XaW*yjLT#GAMx1w=Q|H^dUc&EpL7ko_w1pcnQ?yE zv|Z6A_2+9HFB1X?lkjn?gts|q)}&sbIwG8UfahGjo9}$qUgqkPWP`)Z>ngd7$Q?=Y z>_NyNB!VXatfw*QTvD(K__hKi;7vd=@ws3p14O|DHkmwo6F<`^UK_lzSX&@367`n7-ny9fzIUwGXj7bo7+ev3*d73m0uK@$vjHos%mD9|A#z%nDUCVxix| z2#o50r6HrCpUL4r{D-+Un&ndX; zj@#L}Yd4qf-_OFrLTuj_rb4yE$--_q+|E@M`?UJkZb#5K2AHHpEar(EZY;Ckp5mup z`ef$AIt-7K4G*)!u0?X|`?!2@(hE%jn1DB$>NWyaL45q1B=`j!Mg>um$e#z(Og^Jc zzzgkX3Mzrx79fr+WI$ludrr|q7p}tf_wXlwcNY(a{Z#qxNNS1X?~&B|sWiaH6|EV4 z`#r-ZlEJl&5l0RkAfw``*IdQ^1sK*7!q~JsMxu(@rWyqA$Au#*=8U2dzvX!8d{DPH zgpkrT%sA&)1Z+x4Y12*uLT-ii;RrDfXN1DRf(-Bf)8BZ*cbxpi(!R62ICDe%VjzS-I9~IMWPK+A%sMi z5ltnr8o<G4>w~)Jr)ZRQFRbVyZs*k;sup?IM{l9r{Y*AOPGRHN zrz?E7{-#^=`5sS*OxpCd1t;y!9@NUImD3zLe3*s#d7gRIE_U}KNo;&fNioL697tm@ zCU%nvVUjC2eS@GH#y7Il-`|nIZ3+!B^#Wpsda@?60#3p>XWeVeQqZRyRk>kuc_Jj){a^Ce3RQYxc{L;T(W03OG`W0xzHQul-6NFxD0HXCC)Vg z99x&P(bcJtl1R)Q@+s6@r4A#lf~HBmD%KD3oZTC|;sw{Re*6J;7A5obN%j;06C6zC z?2W^?SXAQeRYb}OoDTg;h!UZMSV)pyV*`jL@@Eb8u)<|MyjYgKQZMYMl%1Tc3f}RL zhd4cdEfx9Lu({{r_BJU5JdG!k{K3RSuqF6gi$7>9%*P6)#$b(erPr~3?IFkQv_ z)uJtS&{S05b#qQp8>XHviWoIhCepqohDy1y%0hXBpZw0J^W=O58`hW`9bmy4tb(P% zPIov-VPJ0nH5koe*f#{ggS25^hl=2(O&8RZBbY@C9TT7$;oTeqEjVs>V0wGGab<}Q z-tZ93;*${Tu#&bfDSvHekJ?WX>7Quw*M8^NM=<@}lC)M4Yzg<;pyJ5kgA9fvF1!3n zp0PL9y|jfZjo)0%5`u2(F%6pupb*9(NTzdWD&;RGY{+~^@_~KC=&3Jt?@e3U11f^Vy7Tx4| z@xrGtrDDz?fYZ5qb4jha^T;}f9zM>}o=drW|7Bzrax*a(R-IJrwUc>Ez@{h~fn~c%iHO)9+DN&uh8Q+oP1QQ~-7HLwlExAs3xh^^z6S5`T(yh2?Lc;3@4 zXEBe*Of>V3Ij6>eZ+z_50%wrG_+UsDGaW7z_^`#8T@`CB>MQyg@bavKAcb3`?R??{eK_+KyBy0XC!^9)EC~c+>*z3yn`y>R}S+0YZm#w=j>z`r|8v3Sg4kIQG-I1vi`{N)5Y$NN5a ziknY3bm$ZJg8~$(iQOr4xuNl^`QF;zOcpv>< z&NHrz`GJ)OLPH21V;#A(4C|OLm^mBwS5kz`S;*h?@jh*C-QoO1(0F`TRfV-K-AEXk zlnZJFG84$D$(yy0{Nc~O?EmD%-Cb|r^8_6MJl`<4r}&lk-t@ke%D&3Gx$y2JqTifGzfNqX+s>vh6?3|Rx8y|;$>HJ&`Ed>Br(v=*30oU0dzI2; znZ^iIO}c;!ijIL}C4B7G2k0+vW6$ngtaNqs0SvQhR6bXPFi-gA2Z%}Z?hIXbsjwrF zq_ho5-GkY@u@tUO%3vZfJ~TxMlJeLBY#byT9pFVzyNKsskyEZ6VA&sKAR~+$p-`X- zBsfGygy0|;L>C}ARaKGao=}eob%pBmp^n65tvlep^$up+#oS$O<8ANzJmuh0baw?M z(^hxwR&MQ(_t;HC>|2$_F_SC0NgiT42kEtT#d7*?BHpXRiiZw7%=+pPF23*rp0YQe z6p7T<5fCz?@E*Lgm{5TTPGaBb1S@RkvIS|7m5`4_d(we#)Bc`*(8@j-k5-H@nS?D)6 z(Jj*2NCs10*{APa-pD3U4_C>$In*^ybs72|2iyR^bOARWQ2hBn-cGgqE3uNXTuez)BBbfK zCIS^`Y;3le0B(kP0+^0JOuL6bbDgx_Px*oC!!i5sy&LS9tDbNLmn=`!zz||r8ik9? z34t1eS`ff<5+QiJvvi9b=UluGMNjTw9V(WLebcXe?^Ax1;bH&COIu(oa25?c3mk|3 zF8P_aed-NEt6x`20SLKKjLH(NbgZyjv{HIp!+DRXb$&tudj{@01~=bv zKY4GNOE2C>$H+wCOUhrnqBbdK>3ujc0h}j_XQE)ig=vMUk=cshWMrM7WV)_I0NaHt ziAW{ItzA$O0%X*LgSYX0&%2T*^hfydAv*PgY*#gf4`f;)S_764JT3?#2C)idH0YX* zjWw$NUe@#l_+lsT|KbMkyzwBi>xpDW$F3gf7&pfBXTg1?>3XUw4bhUfq8(wkU&#-ZD5vMv!v0x8pGwLD#^scx3{dLd#_SM1i%8Pvv zsa&9wXSk+0`@#n1@eL)?^jMAUl$;MZ7wvzvnkLGB>fR0Ry8mIe@41i*_U>k-5HdZr zb7>b+Bm?4Ps@%rO%)v>KOUpe~w708GkWz(jLffK7r}n+fl9aZ(HrW?qsI~SmavHO| zo0~s(Gj&~a#lGFtp&;a4v<77>Bv?cVBA(zui$Q__j-jm?^)BGB>_U2b`TJWpc>k@d zjJG|JIw+R%=g5Oi0^#oZ=_b^Pc_*(`zhMZfgb0y`28a z4y+4&;r2UNtzg%37o)(17!Hn|W+Xny!f`#U7dX2iB6#l+rRijbvUX%D(9tfG2k(B} ze|^o@{Q|>73-WgsV?hAVcGM$oeD|9_a^W@4`Rumc7k&rIn9>Ebo(`Z3Jbqy`xTX?S zDZ#l|@!QSfjq@D>)-d}4yTE%>$6n3=nkdQSam^A;T?d{tj;sTF? z1pz!q@cH-u>F2vUFMiL3SA4~HKvMx<@RJd`J%P5>nh^ZVtBa@ZGY=Q0hPscY zkfrlw(bO&YBFk z>GQX7`NezL-p_IQGR{W@Lx+I30nv&P@G#pLXM0ioz5MpOKF)*eX58I3F-tDYv;%@t zEy5&IwKb93vrP_}R{-0U!HG1t_a}WPFuks7Kl?C|>-d17B>t`hc5dHJe`N>z@4J^f zA2^K9w{h`ut5x$R*N_hZkHk>pCgat~++S_X-k((*o^JC`YZTxKSUo0d$!SP6+ zYkAWuiJp(jR}^9oeD=L>|E9lr!>iuAHG8taW5t31o}QG^iiwnCJS9bt^ZmLqhQG05T8LvZ64AHb;&S6+D~yH|Sjay6Tq z#cbYO8}qHWPUiGat{IvA`*e?6IxfC-%%Bxc+$4NDdB0Ua;akg@Y_qf!ra1*pv_`ty z`P3Z;I5Z4A<tw?d2sUHeJ`r%)46{w(r=5 zDY_gubd=BEbC7M@mRT<1`AaIV^PX-d)INI2h2W78Eo4l?+7W_+AE2Ek9374O$(ea*h<5Gz|wcKkdM+1zp)uZCQw^W~ae&F$k-J5M*4I3^Ku zH?5D~?Ph|i)>tmM<=wyevoHAMpZwD2wswaWcr4iJ%Wr{Gz|z&v+y0}k|KoSAj@q#DV#44N=l)1qg_U{&P2&LeEM9y?RZY9qA(OFsc7?Z^Nd)Z}x8 zX;drgC^C(6Zqhz%siRq|;L~>;V0Bn>@nuh7x!<8<;skplviEpKTNzB@s6+tM5ms}b zPoGU{VF2>#2$#$KeE$o-f&m*8{s^l_9wO`S!l`BUmwn#+fxFr0UW_jKD2c=`-en6s z8rsLnhM0RgtYJJJbKhOJG3a)9##MXin5oC33sBY`>%ydJSm`XLL3o-mE})xUv~Bem zKq-xCI{R&QUrx4d?!6f<*Sb%m0v0A!Jd@9zWD(wpwqdJ_fI_p6@qx6NA;PS}ZUhJp zqZJZ7WnE*k4uZ$j>nwNm2Y%z=_MZ@=e%j6>%Y zBX8*BhPAOJD1(GZ^rG)pyukw!Cr43}evQDQ71L=V1V5P=1VGfxB$6s^(?nzECZrUa zgb-~VtRB~Wba=bNut;wifWz8;bn13q$~$Gbmz2eSQAvb>nA$N5DUo|8d3-Y`{=Lx|U{ z^RQld9zO6e4;?zfr59buwR_@m9oeXe*VZ=6nRPu#sSPm?x)q+@@JOIKMsGJfkDUh|Ew=HPAB*6hIo zr-So#-gtbVw?kg{2cP`8kvIQ$t$T=4llE}lIgB_o(S)@oBM^;(+p1Se`d;9%V?zE& zgQv8V0X6s8__J+lEHvR=>kt)*xz;i%)KCIP#&FZ!hgh!y7hifg+q;Tx7HwY=5%DLO zoX!U%5;w`QOA26^+Lg>l=r#)hIv|!{_k`bZ%pj19&c@9`TVs{k0E#*7;d9i>mm+x#`=)L@qq^yUupoaYg_K`5`8$z7;xY9BRywe4WeKB% z+wZuG`wy+Lylopj8KdlwfCgnI%AanGq%)(Cq`niTxwfKWYRe?aHA%%OX;ZZ_-%bwm zmE5N?Zl3P<&m;n~V~AFu2xuIti4gf9D3eWEEaDxxAJx_2dw=-XzyGQKWl`ySZeu|J z9|!p4yWjljpA|%EboUK4-Y*c|kp;@otA8)>&^>NLG7hlHil`cEFF_FHlprjzz z`F#3PqWZ)_rlsUe@&Y-&AOof(&=GU`G6m&umEGHy`Nk*rx#Y4d`SjgK$hymPPfZw^$>$X@%$$(v(oP(+JGHnt1+P-qJ0g) zVOtT6ZJ)^mF0Hhv0^r?_$@!OSo{~UUqbuv=<9u zYIf|J&`s(%k+$c2JC#$#XZCgHXLAB)uJzXGNH#68s?pLpb{jwT;wRA0JlhJ$dn?>_ z*L~>ja#YrvyvyZ$+Qx2yM@Ay$ZQ?yo2xt5Sy=7N6lE#a{q8ZnL+$cKQ({XEe|IPpS`ER)4tv`3emTmL`XB3O! z>v4wSim%@NBftEPKi-i33z4Q=pQhL#I3R|CQ@Q{7o&y->lEpoz5Z4PHM4j|;oC&)K z4071N4maI;CoWs!lFP58mq9Osj-L9KP5R!>g)U)MS!omfN6TwE*O4aLWEV4eEzItF zY7y7|3^WR0b9~E(@8Wg;{Bm}59YI3ul!E3jZxwF1{UG_$F1lt)EOR}p_Ac%$`t@}1Az%X2QYbQKf?0I)z$zeX-Fwl%A@aJ1AM+pw&cfz>iFtYM>q z_2Cfb9Nq^+83PU`W@l2{N!6d`-|%?zupER&op)I zDDwCdK$M8WIn4!qjib7}%a+{z1EWZDl z2R--hzn{GqT*$8N%k1c>iBWC4Af&yWX?f@S4V*$)ZKb8{Dd@wL`~ed)=2SdmJq$}r z-yY_lU%Q7FT<$3Hrbn@WaxkhDzyGmS?l@F2*uHyW%_GER&wKl|t!d8p^RpS+s-J1D z^VBoB9&fOxsQA(6uF%ar%Sw@p;KbsvjBQ|42ac7BVHFrz!8$0dXIOgHN?09xR)-~{ z(o))hMPtR_B%j%aL_ph6&DMzsN@8XHB*lPsrEHkwR5yDw>1&+)SEaSD?c$VK)o*LB zkjlpg&8qeUZ|N2}qspPRj=jh640QGSUwh?O{wx~@?Urur0%shH@#%4l@A=Q~f9akl zJnb#(qjG>Q8d4H_%R*}7be=Q7M(bu=C~f?FX@T)EzUuNNzVm8W?goT0{eF+p7+e+o&(=%Dn?86yhuMME zo!I|2#46V0!`R*?7a&*XcZD{bAne$G`O&F5hP96@m#GC4v_Z z;!(llL%=$X^NzZ<)Gn&EV<(KAuv#e&uUl5fkt}Z1v2)Ja$TGIk6~T*{_@AawZM)}m zyw3tz^I`}gjup+uYw>t=V>&H}n$4z4k(c=g$GEVT3b@4{thI|{nO1_)QQ-{Ufh*~E zi}eGyf940?{%@ZD&Mn=@1-@ih~OrUFGM@#8fv z+BM+PW%%@sHxPQeS=qIhOLq2Rkq6C$$kY^9&GnN_TfJ$H(fNi}K3}`SH(9_0nu=Y4 zv73^QR4puagT2`XuX@&iK@sS61RrXkK#9=Ng4VH6;aQh2^T~VH8PXwyxV(;@uB+X8 z56;h=%+0VF`GYALPgXHUAG(K^J@<)Ry))WZb+yJCg;iiBs%?Ux(HJzDGUU0TQz*K* zrdwzR9nGK+mOHSmCk#58oqf%|CE|U?7ZW*?_uYK{u5TE;Qi4*= z{jL-)#Ev~m=@>ed*sJ?EAIdoefBNEFXkm*mD1_1micC{m2f@=bj%|h9^8P>grEh%C zuf6skwsZp*_>y8VKAi{XU-7Kv*Z%UKy~TI7zhrG}5oHj8svME!-L2ldtwnkoZ=S^G ztyO07Bpc;V;Tn1upZu$&#*vb#9oRAADpYXvy9I-OkCm=wS6}EAhFyI{ZZv;=yW(S? zy_0n&QTtXBJ=4N~MF=>e z{g5(W2m(!-gMy<+kMh)gU0(V0jBZxaHyZE26**Npw}A2SpKi{rm8P(xAyPrWI)}5K zs*e7eWesB+C~ctjfw2`vbzp7eIWh{Ym4USiMxzn6b@3iU#W6t{T#)IwAZoV2B*dqR ziP@H<2SO%k9B_hM!6tWjD`9PgF?q8&j^(a~(UEt)`QLu`53b+wv9>xCOrCIN!&o z^9Q}1^19#u`1Lj${6D1)N_2*G&A@dYw}P9;iHusk_mPNcg^_5p()5{dzz(&}> z7(-SUAW(WZI)q<&|6$hjjtN0;SA^Dn+9P;TATnFw3)Aa4Rnm^Dnw>rp@lNj9R@4+y zP?o?3gNS&xv}9OI^;D=(4sP1e=Q&D9d9Ya45OgOBU;G3;4cVOYl;!VN2o>%i*B zvsMPytH9dWF&tNn%9=W896Fj&D?ND#6NzaWDmbi{rhp{o0{Uj7<^{g9uHY^-Z6~WS zxyI*V{O^9{mCyKPhKCkc?s@0y%H6+QfbA~Ov7J$ChAr4agsu+%jy7oJ=Ty-Zl{2q9Ryg+Xf#C~6xR zTexpk@w*?~&xYBC?hGdOE~!;qnlNYjbaH-^KbR80l>e8CGH4NI5vXkJVxR?lwZYo` zU*IRc{W_k!BhW1Z)k3z*!rZ_QOmf=;Oot`RNy5$lj&EQYT=7r7oc}C@8(hD~lJ03JP%r(iBn& zv*a)42h4)%Y@6H|H{i=`jc zphvtGu^@nK~-yjD?TCLNYM8c})@lD2a> z)|(cEY!!mXgo=I^KK_nh{ppw9{lT~0v(=llz?TWvvyNLs023dzlB%7 z=*e8U-C=UbMbYaitc&?jy*#I`12zol7F|>oyXRCc-Wr*LvMzB-7*?7G*A&0=v2|8U zVK5jlwy~#h+P)JV;-rGjq?2u;7S2}@pJ~OnttM}_j?MZgCrm=Rt@Aej`I%$T5OnKd zWCP{l{k-V9i+SE8z6QUB0w`m(9;}V3xS2{Ks~cdYib{9=awTi;jU& zS#$W{0iN-si+K4pfnMP$GKt|x^kk*pA5VDGdEzk`wtM0Omw$x&@{yJnyNkpF<-Er_ zPg#3P>lxR9(!$UR))Ek=ih59sd$Ir zqC0@nSm(&{oXW<$ZY@z|jrT^hv*~7FN9!#0yND}?NAJDmC*Ja}U+_C8eIOTj++jfg z7vKpm{@<^D$!mZ14}G@ujE!*#S#OeW=DjB~3g;ZT(TvI}PHN2~x{>%q*)&&*c`!^B zrsF~$jat|?13Ot2aNhJc^=GY{aFR&0YDnu%6X(R+inPk6Uuf_+XOZ9$JehcMqoT^! zQLJ=?UM}ny7?$&x%hxrETn9QvlV=Li3ONl~CitiXhO(x}G~=pf!)YvVc%=EeJK)2g z`T|RPuRwH;NF+M7i$4RAY$Q^b2vjopZYwisvTx@R&KrTZiC3Fj%oD(=KjJCx`fT`? zYa|2P9P7Cey$h?aAM+v zi-2HJVM_QAix*JdOx7L5$IttKtt*tuI5HA`?eFg4a9Bb0w#5o=HQRzNou^z!BAz@1 zCuDE#m?vU5e|4qfbGn^gTx-2N0s(B_cdm8LC*+Xn1IK)|dMb!?Tes{0E^t<0K>!zs80^h|`Yr$KKW@1EdMO6tiS3oN#7eia zc2wnvm8BTwf*19IyV(T%NQ%W{-usry)mFFCdJ+jq4)U=P|Di zw;v=DoS%|h)w=EynJ?Yc?&a8_16;LJ@tUvQNs$NoIpn(O&Kst7F6ROXY{UCNNKu6l z@IK}e9veA^bzr>|#tzCV<`Ir-sC{64Y^kb>@wjAEyJ#-03!EwtrH|`39FKoMQdP5P zob#a6q{Gl4hhfuJPX$LW*JvDmbTss}ef=-L>bd`c^@pl0IZz9nRag+f1!nMVKl}C< zTzc(4d+Ruui8g& z`WZvO290PlnGmPTN-~y1@UeKq*97k|#?bBcV>ma5ejclHmwSe#++(!R%@zF&dYx$U zs&r^VyD~A0_TJ+?WRjgq_u#mB;<3IYD>A$Yw)SL_fd@CNP)g8Rvt9*UP`u+7;RB!D zPqE`7bVDXm7m9Z1EfK)lPbcP%12Zf;#hj!yw-D~GO8)J8TEE$gTI zjjQNv+{dfG;R-HU_GlgGq3HL7aS*Jn&|+eBX+!9oE^#daSOD4wLJ+)wRUS~NCX*o+ z(Fa^zV#zo*R{ZT9!ry)34vJlu(arRPlqUr+k)+DS*ODsR4h^UMZ>#9-%GtJZda43+ zd->@aX%oTC9^}$?z?8VBb2guwsfgzyg~AUVc#x|vTIPqJ*=2h-P?!p>H6q!m?Z6hp z(-at~_)kbtlP2U$JW*rk8CMSLpmKrA1X$tSTG= zjY6$d^d(Fr*#{^x&9Skgo9UTrO9XMN|6@Bi61y=myP?;2YHQIk+YaF)zydYLdBmnc)rRJz5SylG=`X}ysevfCDE zjG?2{I_>yvQA*9US4&~ugtV-b#4QAH6)ISiufbb-y&l_^dTj3q{Q|nVA~T9y!}d$Pz)6YC8!XIz$p_zKs40OVvL#Wr$W#{Q7G_rpbnl8 zgtZE8KBRd2hi;4cW-EKiR8#@;mS3Rr(dgL7)I@p`uA2*|&Zr9x@GO$qz|LcCmpT7SlIu|`9 zuCsZ7%H}SX%1!rC&z-M!h&Pd{RMmW@2w*$svK`WI7l*XFS+omR=FgRzd(cSRTiU?z z(0;DHY&$Q%uE)-9{NPegsH{Zil-4raO5oWH&or+v1Y)rYX$*`ZTkm~yUq^+Ilq%ze z+PP>_-H^iC28LD`R-qw;(WH8#bgYj`hU1DlL=xyxcrjE}MXwk0wsWI#E?U#%M$oRL z(4Ma0&wlq8e)P5bKlWEgw(MXna8}~%zsnZb8uWI^PrUiVKOln({`=VL{ zD)zw*O%cUJ1xU&rz|i0C-jHv}+ETEU(=0fa~Z z$Kx8EWhezM1e6l+5Nb;vG)6(~YHBni3&%>u|GZuJ;ElIoR`yc#mgwg)As4luDou$5 zCX(RhCi?aS51SLMghbTR@25L>v;M3l|c|uw@A;*ygyMB>Sv*uyw^5)KgO z96}$kb&1jjB~Tc_jyLERdOehDKmIGPe%|jhJbZ?=`UM^jID7A|1WF1B-;ggty*3xJV8 z;nt!8R&*HjIxOYFpsCjFWhfJ)X8>;Za!R`dKb$a@i@^g%_~HwlY`dYo=Jz3R>iN(eQq

03ZNKL_t)%hi|#MU@7-xN>IdBURfrfVRe0o&I(MXneaKG zA)K>Srkx9I*3^5#0~ znz-#*dXNaSRk`iLjP`MA6S71gPe+wa=Y8I<4vts<655r&Y1PiplEO4b)DM4=7e4dJ zy!gsMC-W3q$hDxGJ#oT}nR6TGiV`>>_Cn(;=)v2$oJN^EEVqfEw8ohbrV3#QLgi!V zcv#0Uaor+>!!jy_8&x!tuN;iWBgVsZbg<+`fAqb7`Wvsf;m>~ci(k%TvB0^7v;Xc| zVC&J_nf<#zy7B+osMWu>7&WHA7)|X0xp)LeKw|?SdRF0+7D;IN>m>r{CQY5DNChDA zqfLEraCloIc(gVY-5!G+_6>xUuCUxubaJ7i14aw|T+z#+lW8)Es+wu_3>7>9)r3^k zWE(?E0#TtExKE&nc$umIr-D>upah0Cs)0HOYtw!^46)Z~2!b+(vaAR}sGSgkuwE%X zdcWe6cO7N_!F85)UVt`cvW`TI(l+OMHtc78485jZXy<%Ak_vbx2;h97$7WJo3FG@_feY+Cc=EGmDuTAhSuMSa7ybnTCXR}hk@s}yRsI05u@uhXY_*38WqF*?8%SY?2IVuaB zD>%FFt_992e9Mpi($|0Gi@xV=BeitdY6(W`iN9GI&{7p{X7o%BlTv9=Z$9S(zVWMS zd-~-H2p$z`@R1@a9C>CK^m=UTDwYbNo5xmb+X_!N6FQlqn?aswG9kMCi=bsHZ3we6 zM?m4k#6I?a!rf;fWNClYw|9;m2l;Fj>DRNmMa^(oAOU;A=`Bs4(DS zIO!wz3GeyD?TkBnaM{vCr783#7AwspZ|9Vow%XPv?=wDdXNUm8v^sP`0GV!QQkXLx ziEJu3vK~ft^S(e>KfvC6gV(&^3VOL`dl#&8bTWmw=13}!7jP0SUQ{BG+TvVA2mu{D z9i>nbsOt)EG*#A*erlN})SkX*dmU)g0OAAMhbHk~xc#W&tsgzW zfpJEEdHYOPmyVv2xisvQe z|0Oc&t06l$$}7KiAD1k9at)aXh@g}us8}W81;pi?UJ}LDLV|Cp##6MTAVH>TGEC1W zJn{sb@|wN1O}7(8U5-&&BS9FI4o6IX7}sx5w~3^9;X+t^SX+QcBl-nlentns(9F69mig=UhxtW+H6a3uyuQRH;< zj9mjwp@pT6u-uLIEL{^=Dum^ZrehSDmI>iYHVFWTpCNEUQ|j4}twaFlhi?_%-1O#X zFYk28U$YU-ifltrlLwswe2W-H@;B{snk-}tmGgKPi)Biyc-L+4k2gPn%~$AldoibO zPCZJ*t)AQYc6Ii=`j!ZTaApW#A|9?$A+=142Vj_YOBa#*;5x;=7+}*xd^h zDv*ibLR7#IM^F~0EFQu5oLEY8ZbFVTn4coF(puV|dL+IswCQkU)Dj$7mPIet+%O!D zF(!|x4YkAMn$c+Vd)NP;*ZMuJwmIC&^HW{`Qbuh0s*-5%TfvFk=Z7kY)FUkFQCpr1#T zFIRz%jyZDLWY}f`PM9cn>F*HN9$#w+R%Gne9G{X%s8vEMT*;JpdS4{pk|$w7tnXs2%!G>rB3d?blM@<3!5qat!Ma@a@mOg6Ccm zTf4=_7&X0ECE!);y5b1<5Xj`*C4X@I2ys%QK`ZURPY=z6{IylZ6h@8V>e8YkOE^zADcWv({e*N!$&g;(WYLD`^Mwy)2#s=-7 zA%wB00-UpW8#}ybc|ku{?C1$gxv;G#taKH*5egleUb|5p$3w~ZjPL%N^)JIoP4?UPz}Dwu|N#YaCn->O871TcP5x9nzoOQF%e zCNB)bp+l6RQv|9qptNvg47C&f=63kVO?Psn(sY-1k#~BCFtLzn6O77DRiUMXYNel&cIMzK5@W=2Q8OCk2cOtaPAkHZn7Uiv{7JKukQw z65_GUCUH0eVlmkUp}qwfeTeGl$0_VXEEfTAU@gHbMs6pSzK&x1*P*vPleKyoCyFXK zbi=^J$Idttt`kdzu)an_$W4d342TOjBC$JGD&Bi1{Nqh`)8DomvfiYFOFHIl+m-Zp z@;OZ8?{rBZMDp2ITvM*)$WBRkQVH8WfzH+(y#Fqqe$7>U>s4^^lBJsqeIo>0Ve;-w z4ysqp_1i4}Z0JXQsyLaD?q(xHd(3fjUr52?^ckgM7bcTyhQo?pH^({ff>WM1{`hNO z`}2SD2fsZ$jonz_JjOYE`z>&`;Ke`o#%Emf_22qCou!@E9a|q$>mDdW?V?GW;K;?( zEi!iWG}}7Da#z^iQ&HJ7flLX5T*b}+M$`D(V|0$v(-AXO%OyWR=UnvDOVxBI$hS!< zU%PRK0*nVe>ANw-L}5$e;uG8{r$YcGOsh^^i}a=U2(zRwhORxTQL`jK@G(Eg1&_`Q zmG!s~Kq-t4*jn&DaBM7mWWVsfPkfPw#)f?7+U0k!T$G^C4HKj-p4%5{J6-vBcLm36CpsF;hwnMF+%C^0)q;yx|R8G*E zx*_bwPtRw}HH_yn%M|0WCj?8Un^RT+?ID+d5}~YPAK5?p#4&EX?Ez%h6Ir)9RtE#i z&G}JkniE#LS-YIm=tMXP!?#1rDctNDg>SuTDTV1Xz-aXd0~zu!zUm?_U2$wH99<)H zbhO;59O$M)j}J8WDU(?zwn|_`>ByPKkrPhQ(2EGdMtM}gAA5C z!nUrky>I9lPuIX8ml(EFip->LA2FXVNF;T&b4>ztWCz{{f)K4-q{+jQaKfbP_TU_3 zHe{0sV9LD?bd0Cafqw2VP4&XKauoe88x>Slpj*W2 zNjKHLPM3}HRK(*RpdTKf?{8rJ!S~>~l|jEog$~#n@7GZp?AW5ZT`D6SUcZ3e@^@pp z&!&>yNZy&`!Kp^INr?l|Ogf&MECU}L*4N}k2VVzdG{Pv2mkb+VwSv2kDgN-I4{^ss z8w_?`L{UWVz>bOPXF4b8*jMh%6yYQ_xLy65taZxPIz(by$YTfYV|!P4){`&dy1jvs ztGRFhJq@ z9Xu{nJpaA9zfY$K#4}YSRihpWzLo2z8qzvDt;C$bSRfL#VKlDEGZT}-%Zg4Oe-{yI z>#-rWpsIsMg+T2Ul~WuUE8cU5<#Tr(;Kj4N20i+4P%hZh9`Dw1MR#51``a^fI+idW{=RB3?TofHY2L+5OProB5 zapX!9f{GSP4lv-fC#VuajrIoZGK|mSJ(p^p&QVPB^=2avFk1vNeUX_#q^%6L@AXLp z!a4>$jUC(f-@pIf*Iawml?z|L1|fFZ z-w?&qtpfIdZ8q3=(9L8L$*G@&guP5>$%!(E$0?6*s+cncz7BMZ5bEef=3F2sg~?+( zu5lGm!J{Q02&D@g9xINFh5c)a&pqV0^^14nb%*7hdt?7moy=>QScRmJUf}q`0hlU> z^Ns8$;rP%BIX8co7HVtRSYM-DJ;+rTZRds8?Bv=#fnMfWE@Ae zcz!J8hG^l^v;Z8}6$CS>&h?5()$S5sB!B4lP{WTSU5_zBupS*Uuo>7IjKjMzs*^KP z%RIEcgUg=uT^y>f#mmKL8!OA5Op9}pzhflLfuI7x29(jb+9H{unkd;&S7Um4!Rq=D zQ3azqV7=yOsrcJ3RNQv|5sp@d{kgAK*xsYZ7wFBn^A$Wqb zjE)`TvfTro`=k}F+Z)KVXHW<#jL9+B5Ky_`yhn?ml)+Y-tbnnHpgpJ&A`a~h%I0Wi zBH`rRC4ie-z)W9>W5e9e&5a|Ew*1_vqpQb`yzcA1=4*cM-rH_H1CLw_EHK4_050$) z!<*mowte6J9WVKBMW_2x7hE(luI*$t$}&w|dUCB8*On|Z7y}!lk}NA?zTcd}cY1S0 z4Dlucxaj~rkNE++`FWgzc*MS9758HG?NmeX{i3J?~H8Am8k8Xe+nU4z;z9;k1}$qO1T* z@&&So--28JDAM(0oeXM0TLIf_v8wTYj4C>e)HWVo+rgzz{+Ar8uf@s5;F`37bVk}L z^5i<1rWT~@W+oLOfcV(5E*3X|Q?YwV?Szq4eCz??#@im`zM~bYw-eLpPYPs`I6h+% z-4OPq@FnH8?JHQiSZEW7=g=syqgDK9l~Asdg_5s-_S3m$SK#uMfGAHd6EYo8zQ$-p z5KTZGe=jtwZjy5=mJ|Y2K{fYbvn}WFEOh++Iy;_(5L-#ws;1W~ur@xRbh4bvd32$u zYk+`+KyDPld5lt&qtQFw^;duK6R-Y(?|b0Oxlaq6KRAbPy#>w{-1qRY@63wMe?!T| zoqopZhNa&(tgTgavz$x=0fuEsr&HiU4Doe3hH*8!taDT>IO`AqoI|XOod!?@73DnV zVN?sH751+QcOHd14wdYG@E{wtV8swj7aw4GX+W-J($_cTk+p4PqGA}R%Ms(Urmjos zsz!&Ji}vp1vOP;&vkUh0JYD1IWP#j()}D?QGSMKhd^CiXVkE~C+{c1Gcc2gc31R#R z$kqr{h*fk<76(RO#a?`&rUniV`}pju*n9c6aJ0IT((Od+>`~ToVx*#o5SkQ#rqWvl zOTb|RI21u?N*k!1Vr+#QAB39@z}*iV#1ngKi_R$WoUABfXce%oDH>@=ccGik6Cs7& zJ=S@KYpawS#~9>+J=>Rf;>Ejp(oVQ+*^}wON)gC2g|9u`LIW|Joo892WG?Q?HrnLA zlf!syF-oJ9FdmomI`JIU9!7P=(o)XGhGn^L7;n_z-F>dCe*D7SD}T9VJF&odfdv6v z;LC!Se(w+V{`+tJ#`VhN*9W1iR5X8f4qR=~+F)|n*eL1u3#!Uvy(gcvHA@8&v&&sf zKBtZts`N+@yab#VtZ%AVgCK;aAVkGpy#dA!?mY$%uEX6A9^&Dn8`L&X*Coz*PzICb z7-LWbHr7{TZ(<{KGQ;-m+t{~fHy16#1^qx_0=b5OCrH2u7#%2-pp~GNiGx&9&ZH@p z5gYSAy*}kaoDL5#s6NK%(1$>7BQJ(1n?taO--tyZWrgY%SR)+V*h6pmWti@>vFt+f z0hK*7n#>4Q9q*eE;ByZP53Iv|4;}59v|0YPxuIay1#-Y!z_Mqce?eTEY3K0FS)2um7?C<44}`&Odz1 z!rEnlFF6(jaDgu?-u|xtdC3c3^i8ite2$Z;DOw#_l799aCGdj+urd z>!u5g3xObk%m~4Ia`XSUcji%&T-BNX?pq>qsjgm;)JTGE3>bqJ79knLIta8F2D3Ht z0f}Xh8P70Ahs|cp@px=w7732TVqhdQ9_v-rW8%IW0e=gc*#l@Q4I?E)x=@Aym7y#Z_W3;8z#R7) z6#iGh)Btq!pj@;7q^ghyK)=l&Fi0~1P?kNknieDhrHk$7G-VJ5922GrMiB_An#vW$ zHhB;A1QR{NWGU!6f>DAkEy9+jV10x7CeoR%jynmoj+Q}Dd8mrbEd1==2cNlN%jV0S$7!yz$^h!fMvOc#3rv+vR{zo-PP*o**FX}0i-Qrr zpoC(0kJQ6R1HObJ zfkow{>;o7Ug;M<-PEyqkf)E6ym)IsyVv&&5v2CI;u`L_1Kn0GyqyZSEpftf~RMqtY zsytvAfD0j74%yh}yDS-2uk8qY6o7-GvN}JZUYYPbn9GO=RZSI~i{~UaxOLB-J#YP$ zXane_3V%d1s3(r&6{PmYF(8j#a7;Npi=y#x`B&?{NqCGBCjm&pBlA&BJueYru4OA%C<7o~kYxn#ac}Vc-8)|X($DssA;0{`tT4Zj+g}H*?A-_Vv(iHllq=G1n_*8#X5vhoV6a z5`ezzZ{2YPh|9utF?Qw69Q^?mARZ710z$t#3sEiTDt|PI6}%9dwPa|k_ZNxzaFwkd zLWqSx)*4i+!UKlR`_euGu@|$#6dHCK8TLXK)9}R1F+`gSou%yAs95T+>Xl#024wE!p5u|G4%DAI7-xM*}OvFexrC`RxBq*N@< zQ3Q&0)Chqq1Mv){kH?yH>|9dkrFkDCoFhxUEMVps^)-YLkXT?o%JX=hy3;+3Z)l+C zO5vRQ&|m%4)$e=9n=hO?@?%XT2Bfdh#ERkOfBx6)+qZAOq}9q_!3<1yOJrF#Yhq=L zT5Tj2NmX=E8*bMDz&fZUs2)S@*B5Ph`aNo8-~$Mt@8uW-(1?DHRBc~XCdS;4bub7D zQsoMwdJYTVCB(vms^EZzqE68;J3<6_T8ap)mhULGYNO!MPzpv9%CbPv1}|@o-KoNo-N4 zwSxDdN~=IWzYmDQ-U-KT6M+$hphy(*iU`bz%lp-j1f%K>Jk@rV(uZy}FvEsu7!sf? zOSGFAlma@P;)}a>?RwWUPyMxB%QDtPVg_sc>P@UfcHg__xf?fcy1ZAqQy~gubaVk> zz%fG`)sF~S1^9Yh3bDHaQH&rhwoAyGK}H1#fVh;1s>r5)_~uxlqG*7uL=B!ddF#zXCIjHW?PW&*rt*eabu7!V%- zVl*=Q!-w}gbn&*Wo4>Vudyz=YW^E^MBvvHbwr>8`8KcN+0%p)RSBU=G7PD``la)0gIZiLKxH%u zCJ#^vsSJZg*r#ZP^#WU139F@o|4 z%ExM8;@DASL|Cc8y~J8yB@F7zJAy#>$5KB!Us4$ljUR~TQ42u{L9>FcM7^#=cfIfP zwMbm;RlxN;Qm091O;u_Fp<4zxSN&L!7*VaOsM&e6Tly~c?oDT$e%fhC{3TW*YvA`= z;%Mf)m%Tc_>a(Bw52E#Z3g@=A#w*DN zNEZ7=UPY-E?u;@TNg9298H*UIjSbpp)!k19$@Hj2=b>UaO4b*fKw}e?M!G$*pIwg z1|o7bM*+14dOe3$%c3j?mAoQA;TVmELg@ewK&u6GCOz`Z+(RL}_rlk{<}beTH&@S@ z#hgg21oUzbAdy&zAK!UL_~4)Y@%I?!&!7FQGxu;%Pq9|DLmA)$&}u1o5A=F5C(Bww zr&A)&vwkvrVtxqGmZiV0S~vEsZx}?R=DZ;mD^T@30)t6F6u`tokIzsEeXqM%8BEaC zzX?LRdj1?qRdKZa+fua$VXzEdkClhs+6c!88An5MAs@#r79_N!0Z6q!O6on2BO=7* zSRsMTK63qW$BoQ<098~r#HDr$=(|i4&w9~N4N7$`(LeX|i9cW<`c|{}0{~+HB8_fn z?@fsS02Zf7L_t)yM5AHA9OoLX4Vn!?x5r>+G%|%y%Kb{hdp`KS_r30A=RE%(e|+a1 z>E~x+MYGB;-^6O;10VTB`-0b9_?GeU*1NieZ1OC~G6iO!EMq_6ECZ&dqP>aM={L@N zkklDtBb{l1;Ya#L#Sxx4V~82)aofKK59I>Rj%3w;(>!eIUHxrHc-Eq2D9dw>eOMeM z3|04s=2$!tOo2cEBnJtQF;`JCg+M^4(octimWvlbb4EmCWN`S;G{<`PaKv`>?YTN; z^ZoJ}L{^1>K(mkMjAzdKcbWa>tBw!?m>FYZ7G()I=aFRwN<|+;qX^BM_Dt^WeDJEP zuKM`z{qFBfFZY-ei34SoU%rXe%2n5VY5avRI_IrAZ@isB>$N827IhXo*jSt78%1SkdvOD&lCk+(U{QD0OI38MH1HS%}8g!3B(ppOEp60)qj zabLL!NHnu1;l5z%+q6^)wjVKD3^Vq9uq_@H+Vdnlj^tg&K@aWRJOWS#IfYRG4lVU! zun0dpC7>3LGag>$-yr>pcLF+{E;emwqHwXuOhNXBqIc=nuD|vp7w&k)zU3ZkB5|;+ z^2;}|+WFkyer4lxUvSpjvdmuWeHhDg4d-GW;PiB~kx48JR~5a(^#3Xn%^P8x9j#mn_4`C26suxYB?tk4RTRjo`ai)}wm5^x=aNP-vV^-p-R_J^ z?V;?=fi2R3oR0<0Copslh6LmwFLUsIGe);+Da#V=c80PPSW7610AuuIS-Q)<`Slw< ze8F#?H?iDfOe7Xd5`c+S!Ds*G@3)+F)>-e&^Xx6953Smin0XGNGV9B9?NVEj3@_mh zGcyv@&kH-?1iVpEBYp7_7k+t0u}A%WG$M=^+TIc+NPj>4(9)|JL>emrNMfpeFRO!P z4@ptVXr#3+1{ppNbH9U7ZB;WvxF2LhblxT3RV@H#N4)2Pr1GZZ*e^RXx>FS8M{l^{ zhD%=ivftQq_{W(@9A4J=*I#0_@u^Q=b?mFofAu>85IW(txa`nhVD`L#IL^GBC1dF0XMWgy2E7|%@Mx1W%p zFEJ7cI5=2|eQygTa8O{fap?~pxiWyO466-;RDgB>F#*aP!a|4x6DEg*IX=(x?Z)9O z^q6@a%)V}FAH*4t5*G9V8kmJkzrVHC8bwhc&n*-b3g@7eML_ID9!h{EK!Kn&fkdD{ z2*FKiQlI+5)mLBo<~P3fzQyltBC)ba0x+>E`M`%ivi`!?zwu4YcKhPOxf3!QC;Flc zfYz`UD9bqUm!6?OXf_E&F`Dj zfCG@52H0tYkVUs&1NgwOfnhU^;Az!Y!X8eRBmjZ=^CRo+QS|X6B8Uj`T%p@7Awsa$ z!j%k@D>x?r2jteo4l|`gZq41@>CRTQh@jS?z^3p&0qd&an(;vUg zEo~1IiIqzdfQdE1Ghc8H{qL)<`FDAqzoXgC&M68YR4u=P2#iv3*@vR=i|wD(f>p%x zr|feQfJXxoeIlC~p!5Tv@)uCkyU?Bd8H(awkQj`$wxO}^G2rI$D6j>dk3}G$&;UbV zg_cx_yw*7o0XQ7}n@a$Wnvl=1wW-oPgb2pOc5WfWAAm#zh1k!!nJY|Bm)DlP;?nca z-|>x`zkY2xtBF-l5`c*{$B+K)mnR>0+_7&fJ->P&|Aqw3|RP??LAUARb&;2sQ(a$HK0E8bW>=_Jz$TMZ@F( zxpc0N6tlXNfGY#<*;VZI53ah8F9UFnp;YV|q;>3q5Inows?Xhb?|mP7{E5fie#CYr zkyrtwxht{ec>IaS-8OFN4gYlWP1{^iydU20RftLAA%uSJUpRn1aw-4o=!K|2BYyzp z^sS(&Td+C%DYmrlN88+w48MetU!sxS1B0Ie(>oC+cS8BQ(J)9e1KIkYA7BPWf9*0-J5UPw%*VilK4xkMUntatXW?Cg6G_G>{#R7mtXeb z6N4)+2K(LX*EJB>g9ylsMja)ZNo@*TcTh_leQ4STi#rgeZw7aM1S3-bJHQE4$YAt1 zgw`W#j3YN)@YG#!lRrm8_9D|g1fSZxE*HZ#IYP5<^>vw8B(We5KuUes$DZe2(T9LzJyWuQCSr4`u2_AJbpt?uiSpz#_N*! zO92HA`tc+Nq}eNxn1dZJKJUJ*wj-ro{WrQqK=yVF~$6+RMm>~hUSHKE^8GvYzZG(eGxA17#3|cE_ z4TRvp%0p2X@Ex!(k(q<>{Pi$wg7X7y|~Ni9lMz``B5;h4|&96#7;&BC(--tJSRRDfaI(m^gg2u^YJW z^T_>9C_Mp43B@^tG#osP6;LQaTHu9I&?Zb3+wq7K&%-`G1&)rLueEOC0I92VXI>jX zyndKtM9^x5vh*;<#6m3*Fch2*$a4#3+~&&Sira6${j=vj>$HcLcdrtOqk|LyOe7AF z7d`veAAaP=PTDgVhA@f#6~U!#PF>f}(Ix3TU;O zV3tY%rq!tBM4-_aKLH)r0tY~424Dh-LZ&U03n1|TNnG~tDP;L00on|$n&6P+-%_co z?wJLxRuf7AMd1*Fz`3|A9Gr*u46Aiay%3<88yJP@cEeuTot!@7CFh-e>WLc~A5G#f zkvMRY08Atfl3Tv@4LR|c4YzD)>Wi-Yl{h)Mxv8PIH6)@4{7EOD`pWU~@mC9}XB5uCT8qi)4%+P&m}3D* zqoGlj@%t(*0WTjK)5!Gw;C;7(Ca#6*{S=L62BQtU3ozCI!C|UoP__l!dNRz$S76$o z2vPdC7?f}8j4+jq_FJ8%2qZ=Cg< zUo7*m6Nyzpnz|B+!@#%y?`@Ad>6DXRC4wDV^_LWo@n63Yj{L!m%B zdjM|V&6s@PCbZQ(XxlDA(StD=%Anx%BjKA*N4D_{1p8QY-53G`N~zQaZmCFI{?&%y zoJXr=(Caapxk3o|t|nZ)bLY-4KIdtt-nHCAO(a$uNdP7ihnau*`MujWZ{EB^Tf4(K z_tY%22vw2DaIfLoSbBdECB{*lyCI0PPJO@Jut3vZH1hkQ{ZGJ?x1pH68@^j0%Nnq) zaoDlPqoYoSYCH}T(*&Ef2gBz>bS_rfaXAPM=JPmn$-KS>v5Y$V*!yDkC<1qJ#=E@bU zAKLFRT7ZRKyFcoYjvoI}hzLp%$})bgthETC^6Ik+o&jZmqU)iQ>VHNx2*wa3eyrhK zfYutCVj6@}3L>!zo``mqz2fSJ9(wQ#PuzaOj~Bm3iA3UHNCGgCSSD`0<0ntpx^?TT zTdmehilTU0qm?5BfmVcW*Fk4C`Ue^X5g-7_GQcxX_UbQG^uI_&1dRrv+x5tdL9bW9 zT00V1BvBCJ>OPKRtqZ`Vz!b;6TmlfZ`13ayDbM&^42oNvb7(YjIOox98uWUD&l(gV z2;e!Ok?AUm7yIrK0X{G^DLCiQZde44mM^_dfjrM|?Q}YSckjLTUUS-$9((5^cOj8T zEP*5d6NweT|GDm)$2|F|PdPi!^K-LC<7@z%TwrLeP?iCC9?glF879jhA)wLF2q8uQ zwN~)Ht~%D}bV@WD8JGu4bc`q{mm~Q3Pa}hE$(n z66`68-t|RMeD#Ol|G{1nOPN6a3Zmq_^*HRetpqJ7o9dXzV2K=ouiaG zJ%m6|3dSffM-yoPUwvoiYC+5YiGL5%+wzW z3+I6KUpH%}h(hN;Uc2yimwOR+d5OYq@yBp*{6@ENApV3x3XC~|k~DaIE&g=%Zvn$v zg`(@wY+CrzLu*1=dNiB)1I~qO!Qt9F?zrRn=biD?2N%6#iA3VClLTNQaTM{Ex4&Ec z!F%5Q)XX-{6~Z||a7Mdr^>kN2no#yiwAW=QdT}XFV|I?&@G9ft1mHll9XbKCHaWBc zda$jf2*Cblqw2*A666_Sda6X8XJ8I!H#MfGUC@ME2z+f>_^-bA&;I25AG`DeOWUDD zB5}k>0x*#{iuur=UorN|9j`hg1UYllmJMfu@r+KdT$g1TJPQY@&O0Jh6k@-MrI1FgI$uX1>k%U*8Q@`CFPpA)Y_mrc+ji2EInEcGpQ8* z@xcclx=Cw$(-*I~`j)rcqsfTDPu^!U>cj zFjuYVG(iO55Fa1TA!G&ur1FM~kBP)Q!w>|<5WJ7~VMr#_&yBu>@%cnFB6Vs*;M%va zeh=o+$LjHjpzkNQoYZ3&9@l~F!>~Og_g}{#QbWgU@EontKepb-s9b$4>*tCHGzRCU z9uKoX>FRw$-FG*h^V||9C#SJtLz|uBA9lOlo2<1r?f%)Wn@&IZ33nfkW0puHRt8A` zCK79mPyXd+*1hzlFFk{Wp4n`Voyx$;O7PeKkO)9J#-V}$5{6cMDGCu$fOw$rpq!d{G#W3dEV_+(M(`kq9H= zx;};>421Xau?``chTE!IH-sT^Ndip-(g3RGNAV3&f}enJTX%ZupB2f?U;gr!Z~2d} zzhLqR9HvAfu|imxGif4`IHLT;=fBi`!3)oNQmfTErS$&f%$QRcI3+h`lb7L0AH#Ei zQ5q(TO2xS-;z9^$G%UOq5MpmvYt3j>%nTx6%s^&hRH`5CQiCa}7JxM)+o`9n6*7a( z6{Q3)yXP|xB5FCYoQvChZ=cqoii8$S6yBVyaUHV3~^h*>)p{7`!U6ujL=)U1{2(eeL zRT`BhhI78!DwkH9-64eC0Cq9+Zs**tyYIgHU%qzT_5bfZ?|f@{WcE6dNUR2u08Atj zhm6ZVb)|a#^Phj*=1q^-u8iJhjM+}wY}2H+3$QH&c~pQHs}zg{iXv(jhJsS6A2AC< zMIIso#vre5_$D69I*XC6BYvYx)CzGKx84Wc7lT}N(1_%jK^Xw?3?lMc(_J9!lEAx} z{VwnQZVqnuo(CV^_01c<{>!(%`Ax}ZFOf(b5|RK+BoarAOFnjmKJE0UAAiClkKdLx z@<(TxIaX_Zj8f`YB0APHjs^YAL=_?PVNe~bDx>S=oW+8~c6>n0>oZk8 zUtM&e&&=y0dyGXgutC%Sxih%PftuuO-)Qs zPCoq5Lk~?nyl2nEzJ2>99=!j7iCw#PO?>fxej-Kg5{bl$;{OAGsY&A77XCH>0000< KMNUMnLSTaF%oyDO literal 0 HcmV?d00001 diff --git a/static/icon/icon_Home_n@3x_a.png b/static/icon/icon_Home_n@3x_a.png new file mode 100644 index 0000000000000000000000000000000000000000..b314a2b1ea61154f8c5275b84a28a1f2c415dc3e GIT binary patch literal 4675 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 TJJ;q~KmH`4QR3?0oyPwF;PL1& literal 0 HcmV?d00001 diff --git a/static/icon/icon_我的_n@3x_a.png b/static/icon/icon_我的_n@3x_a.png new file mode 100644 index 0000000000000000000000000000000000000000..53dbd008f2035d9c8a1d2d0bdcb626c0ac84e669 GIT binary patch literal 5227 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 Il^Zty7nj+zc>n+a literal 0 HcmV?d00001 diff --git a/static/icon_swiper.png b/static/icon_swiper.png new file mode 100644 index 0000000000000000000000000000000000000000..86009c6d435417b2f93717beb5f8f63411747d4b GIT binary patch literal 1545 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 literal 0 HcmV?d00001 diff --git a/static/logo.png b/static/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b5771e209bb677e2ebd5ff766ad5ee11790f305a GIT binary patch literal 4023 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 SYs}WS&%*SCNx89m_ + + + + + + {{ percentage }}% + + + + + + + + {{ percentage }}% + + + + + + + diff --git a/uni_modules/liu-progressbar/license.md b/uni_modules/liu-progressbar/license.md new file mode 100644 index 0000000..029bf39 --- /dev/null +++ b/uni_modules/liu-progressbar/license.md @@ -0,0 +1,6 @@ +### 1、本插件可免费下载使用; +### 2、未经许可,严禁复制本插件派生同类插件上传插件市场; +### 3、未经许可,严禁在插件市场恶意复制抄袭本插件进行违规获利; +### 4、对本软件的任何使用都必须遵守这些条款,违反这些条款的个人或组织将面临法律追究。 + + diff --git a/uni_modules/liu-progressbar/package.json b/uni_modules/liu-progressbar/package.json new file mode 100644 index 0000000..7fe2fd9 --- /dev/null +++ b/uni_modules/liu-progressbar/package.json @@ -0,0 +1,83 @@ +{ + "id": "liu-progressbar", + "displayName": "进度条组件", + "version": "1.0.3", + "description": "自定义进度条组件,支持设置文字内显、当前进度、文字颜色、文字大小、进度条颜色、进度条底色、进度条高度、进度条圆角弧度", + "keywords": [ + "进度条", + "百分比", + "进度" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "u" + }, + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "u", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/liu-progressbar/readme.md b/uni_modules/liu-progressbar/readme.md new file mode 100644 index 0000000..ad4dfa0 --- /dev/null +++ b/uni_modules/liu-progressbar/readme.md @@ -0,0 +1,44 @@ +### liu-progressbar适用于uni-app项目的进度条组件 +### 本组件目前兼容微信小程序、H5 +### 本组件支持自定义,支持设置文字内显、当前进度、文字颜色、文字大小、进度条颜色、进度条底色、进度条高度、进度条圆角弧度 +# --- 扫码预览、关注我们 --- + +## 扫码关注公众号,查看更多插件信息,预览插件效果! + +![](https://uni.ckapi.pro/uniapp/publicize.png) + +### 使用方式 +``` html +文字内显 + +文字外显 + +自定义高度 + +自定义圆角弧度 + +自定义进度条颜色 + +自定义底色 + +``` + +### 属性说明 +| 名称 | 类型 | 默认值 | 描述 | +| ----------------------------|---------------- | ---------------------- | ---------------| +| textInside | Boolean | true | 文字是否内显 +| progress | Number | 50 | 当前进度 +| color | String | #FFFFFF | 文字颜色 +| fontSize | String | 24rpx | 文字大小 +| bgColor | String | #5cb85c | 进度条颜色 +| dsColor | String | #f2f2f2 | 进度条底色颜色 +| height | String | 28rpx | 进度条高度 +| borderRadius | String | 8rpx | 进度条圆角弧度 + + + + + + + + diff --git a/uni_modules/uni-popup/changelog.md b/uni_modules/uni-popup/changelog.md new file mode 100644 index 0000000..decd775 --- /dev/null +++ b/uni_modules/uni-popup/changelog.md @@ -0,0 +1,84 @@ +## 1.9.1(2024-04-02) +- 修复 uni-popup-dialog vue3下使用value无法进行绑定的bug(双向绑定兼容旧写法) +## 1.9.0(2024-03-28) +- 修复 uni-popup-dialog 双向绑定时初始化逻辑修正 +## 1.8.9(2024-03-20) +- 修复 uni-popup-dialog 数据输入时修正为双向绑定 +## 1.8.8(2024-02-20) +- 修复 uni-popup 在微信小程序下出现文字向上闪动的bug +## 1.8.7(2024-02-02) +- 新增 uni-popup-dialog 新增属性focus:input模式下,是否自动自动聚焦 +## 1.8.6(2024-01-30) +- 新增 uni-popup-dialog 新增属性maxLength:限制输入框字数 +## 1.8.5(2024-01-26) +- 新增 uni-popup-dialog 新增属性showClose:控制关闭按钮的显示 +## 1.8.4(2023-11-15) +- 新增 uni-popup 支持uni-app-x 注意暂时仅支持 `maskClick` `@open` `@close` +## 1.8.3(2023-04-17) +- 修复 uni-popup 重复打开时的 bug +## 1.8.2(2023-02-02) +- uni-popup-dialog 组件新增 inputType 属性 +## 1.8.1(2022-12-01) +- 修复 nvue 下 v-show 报错 +## 1.8.0(2022-11-29) +- 优化 主题样式 +## 1.7.9(2022-04-02) +- 修复 弹出层内部无法滚动的bug +## 1.7.8(2022-03-28) +- 修复 小程序中高度错误的bug +## 1.7.7(2022-03-17) +- 修复 快速调用open出现问题的Bug +## 1.7.6(2022-02-14) +- 修复 safeArea 属性不能设置为false的bug +## 1.7.5(2022-01-19) +- 修复 isMaskClick 失效的bug +## 1.7.4(2022-01-19) +- 新增 cancelText \ confirmText 属性 ,可自定义文本 +- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色 +- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题 +## 1.7.3(2022-01-13) +- 修复 设置 safeArea 属性不生效的bug +## 1.7.2(2021-11-26) +- 优化 组件示例 +## 1.7.1(2021-11-26) +- 修复 vuedoc 文字错误 +## 1.7.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup) +## 1.6.2(2021-08-24) +- 新增 支持国际化 +## 1.6.1(2021-07-30) +- 优化 vue3下事件警告的问题 +## 1.6.0(2021-07-13) +- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.5.0(2021-06-23) +- 新增 mask-click 遮罩层点击事件 +## 1.4.5(2021-06-22) +- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.4(2021-06-18) +- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug +## 1.4.3(2021-06-08) +- 修复 错误的 watch 字段 +- 修复 safeArea 属性不生效的问题 +- 修复 点击内容,再点击遮罩无法关闭的Bug +## 1.4.2(2021-05-12) +- 新增 组件示例地址 +## 1.4.1(2021-04-29) +- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题 +## 1.4.0 (2021-04-29) +- 新增 type 属性的 left\right 值,支持左右弹出 +- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗 +- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色 +- 新增 safeArea 属性,是否适配底部安全区 +- 修复 App\h5\微信小程序底部安全区占位不对的Bug +- 修复 App 端弹出等待的Bug +- 优化 提升低配设备性能,优化动画卡顿问题 +- 优化 更简单的组件自定义方式 +## 1.2.9(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.2.8(2021-02-05) +- 调整为uni_modules目录规范 +## 1.2.7(2021-02-05) +- 调整为uni_modules目录规范 +- 新增 支持 PC 端 +- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端 diff --git a/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js b/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js new file mode 100644 index 0000000..6ef26a2 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + this.$once('hook:beforeDestroy', () => { + document.removeEventListener('keyup', listener) + }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue new file mode 100644 index 0000000..08707d4 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue @@ -0,0 +1,316 @@ + + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue b/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue new file mode 100644 index 0000000..91370a8 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue @@ -0,0 +1,143 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-pay/uni-popup-pay.vue b/uni_modules/uni-popup/components/uni-popup-pay/uni-popup-pay.vue new file mode 100644 index 0000000..c4c065c --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-pay/uni-popup-pay.vue @@ -0,0 +1,279 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-select/uni-popup-select.vue b/uni_modules/uni-popup/components/uni-popup-select/uni-popup-select.vue new file mode 100644 index 0000000..14f5137 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-select/uni-popup-select.vue @@ -0,0 +1,338 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue new file mode 100644 index 0000000..69b1b3d --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue @@ -0,0 +1,286 @@ + + + + diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/en.json b/uni_modules/uni-popup/components/uni-popup/i18n/en.json new file mode 100644 index 0000000..7f1bd06 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/en.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "cancel", + "uni-popup.ok": "ok", + "uni-popup.placeholder": "pleace enter", + "uni-popup.title": "Hint", + "uni-popup.shareTitle": "Share to" +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/index.js b/uni_modules/uni-popup/components/uni-popup/i18n/index.js new file mode 100644 index 0000000..de7509c --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/index.js @@ -0,0 +1,8 @@ +import en from './en.json' +import zhHans from './zh-Hans.json' +import zhHant from './zh-Hant.json' +export default { + en, + 'zh-Hans': zhHans, + 'zh-Hant': zhHant +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json new file mode 100644 index 0000000..5e3003c --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "确定", + "uni-popup.placeholder": "请输入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json new file mode 100644 index 0000000..13e39eb --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json @@ -0,0 +1,7 @@ +{ + "uni-popup.cancel": "取消", + "uni-popup.ok": "確定", + "uni-popup.placeholder": "請輸入", + "uni-popup.title": "提示", + "uni-popup.shareTitle": "分享到" +} diff --git a/uni_modules/uni-popup/components/uni-popup/keypress.js b/uni_modules/uni-popup/components/uni-popup/keypress.js new file mode 100644 index 0000000..62dda46 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/keypress.js @@ -0,0 +1,45 @@ +// #ifdef H5 +export default { + name: 'Keypress', + props: { + disable: { + type: Boolean, + default: false + } + }, + mounted () { + const keyNames = { + esc: ['Esc', 'Escape'], + tab: 'Tab', + enter: 'Enter', + space: [' ', 'Spacebar'], + up: ['Up', 'ArrowUp'], + left: ['Left', 'ArrowLeft'], + right: ['Right', 'ArrowRight'], + down: ['Down', 'ArrowDown'], + delete: ['Backspace', 'Delete', 'Del'] + } + const listener = ($event) => { + if (this.disable) { + return + } + const keyName = Object.keys(keyNames).find(key => { + const keyName = $event.key + const value = keyNames[key] + return value === keyName || (Array.isArray(value) && value.includes(keyName)) + }) + if (keyName) { + // 避免和其他按键事件冲突 + setTimeout(() => { + this.$emit(keyName, {}) + }, 0) + } + } + document.addEventListener('keyup', listener) + // this.$once('hook:beforeDestroy', () => { + // document.removeEventListener('keyup', listener) + // }) + }, + render: () => {} +} +// #endif diff --git a/uni_modules/uni-popup/components/uni-popup/popup.js b/uni_modules/uni-popup/components/uni-popup/popup.js new file mode 100644 index 0000000..c4e5781 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/popup.js @@ -0,0 +1,26 @@ + +export default { + data() { + return { + + } + }, + created(){ + this.popup = this.getParent() + }, + methods:{ + /** + * 获取父元素实例 + */ + getParent(name = 'uniPopup') { + let parent = this.$parent; + let parentName = parent.$options.name; + while (parentName !== name) { + parent = parent.$parent; + if (!parent) return false + parentName = parent.$options.name; + } + return parent; + }, + } +} diff --git a/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue b/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue new file mode 100644 index 0000000..5eb8d5b --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue @@ -0,0 +1,90 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/uni-popup/components/uni-popup/uni-popup.vue b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue new file mode 100644 index 0000000..6f774d4 --- /dev/null +++ b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue @@ -0,0 +1,504 @@ + + + + diff --git a/uni_modules/uni-popup/package.json b/uni_modules/uni-popup/package.json new file mode 100644 index 0000000..3cfa384 --- /dev/null +++ b/uni_modules/uni-popup/package.json @@ -0,0 +1,88 @@ +{ + "id": "uni-popup", + "displayName": "uni-popup 弹出层", + "version": "1.9.1", + "description": " Popup 组件,提供常用的弹层", + "keywords": [ + "uni-ui", + "弹出层", + "弹窗", + "popup", + "弹框" + ], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [ + "uni-scss", + "uni-transition" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "n" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-popup/readme.md b/uni_modules/uni-popup/readme.md new file mode 100644 index 0000000..fdad4b3 --- /dev/null +++ b/uni_modules/uni-popup/readme.md @@ -0,0 +1,17 @@ + + +## Popup 弹出层 +> **组件名:uni-popup** +> 代码块: `uPopup` +> 关联组件:`uni-transition` + + +弹出层组件,在应用中弹出一个消息提示窗口、提示框等 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + + + + diff --git a/uni_modules/uni-scss/changelog.md b/uni_modules/uni-scss/changelog.md new file mode 100644 index 0000000..b863bb0 --- /dev/null +++ b/uni_modules/uni-scss/changelog.md @@ -0,0 +1,8 @@ +## 1.0.3(2022-01-21) +- 优化 组件示例 +## 1.0.2(2021-11-22) +- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题 +## 1.0.1(2021-11-22) +- 修复 vue3中scss语法兼容问题 +## 1.0.0(2021-11-18) +- init diff --git a/uni_modules/uni-scss/index.scss b/uni_modules/uni-scss/index.scss new file mode 100644 index 0000000..1744a5f --- /dev/null +++ b/uni_modules/uni-scss/index.scss @@ -0,0 +1 @@ +@import './styles/index.scss'; diff --git a/uni_modules/uni-scss/package.json b/uni_modules/uni-scss/package.json new file mode 100644 index 0000000..7cc0ccb --- /dev/null +++ b/uni_modules/uni-scss/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-scss", + "displayName": "uni-scss 辅助样式", + "version": "1.0.3", + "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。", + "keywords": [ + "uni-scss", + "uni-ui", + "辅助样式" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "category": [ + "JS SDK", + "通用 SDK" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "n", + "联盟": "n" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} diff --git a/uni_modules/uni-scss/readme.md b/uni_modules/uni-scss/readme.md new file mode 100644 index 0000000..b7d1c25 --- /dev/null +++ b/uni_modules/uni-scss/readme.md @@ -0,0 +1,4 @@ +`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/index.scss b/uni_modules/uni-scss/styles/index.scss new file mode 100644 index 0000000..ffac4fe --- /dev/null +++ b/uni_modules/uni-scss/styles/index.scss @@ -0,0 +1,7 @@ +@import './setting/_variables.scss'; +@import './setting/_border.scss'; +@import './setting/_color.scss'; +@import './setting/_space.scss'; +@import './setting/_radius.scss'; +@import './setting/_text.scss'; +@import './setting/_styles.scss'; diff --git a/uni_modules/uni-scss/styles/setting/_border.scss b/uni_modules/uni-scss/styles/setting/_border.scss new file mode 100644 index 0000000..12a11c3 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_border.scss @@ -0,0 +1,3 @@ +.uni-border { + border: 1px $uni-border-1 solid; +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_color.scss b/uni_modules/uni-scss/styles/setting/_color.scss new file mode 100644 index 0000000..1ededd9 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_color.scss @@ -0,0 +1,66 @@ + +// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐 +// @mixin get-styles($k,$c) { +// @if $k == size or $k == weight{ +// font-#{$k}:#{$c} +// }@else{ +// #{$k}:#{$c} +// } +// } +$uni-ui-color:( + // 主色 + primary: $uni-primary, + primary-disable: $uni-primary-disable, + primary-light: $uni-primary-light, + // 辅助色 + success: $uni-success, + success-disable: $uni-success-disable, + success-light: $uni-success-light, + warning: $uni-warning, + warning-disable: $uni-warning-disable, + warning-light: $uni-warning-light, + error: $uni-error, + error-disable: $uni-error-disable, + error-light: $uni-error-light, + info: $uni-info, + info-disable: $uni-info-disable, + info-light: $uni-info-light, + // 中性色 + main-color: $uni-main-color, + base-color: $uni-base-color, + secondary-color: $uni-secondary-color, + extra-color: $uni-extra-color, + // 背景色 + bg-color: $uni-bg-color, + // 边框颜色 + border-1: $uni-border-1, + border-2: $uni-border-2, + border-3: $uni-border-3, + border-4: $uni-border-4, + // 黑色 + black:$uni-black, + // 白色 + white:$uni-white, + // 透明 + transparent:$uni-transparent +) !default; +@each $key, $child in $uni-ui-color { + .uni-#{"" + $key} { + color: $child; + } + .uni-#{"" + $key}-bg { + background-color: $child; + } +} +.uni-shadow-sm { + box-shadow: $uni-shadow-sm; +} +.uni-shadow-base { + box-shadow: $uni-shadow-base; +} +.uni-shadow-lg { + box-shadow: $uni-shadow-lg; +} +.uni-mask { + background-color:$uni-mask; +} diff --git a/uni_modules/uni-scss/styles/setting/_radius.scss b/uni_modules/uni-scss/styles/setting/_radius.scss new file mode 100644 index 0000000..9a0428b --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_radius.scss @@ -0,0 +1,55 @@ +@mixin radius($r,$d:null ,$important: false){ + $radius-value:map-get($uni-radius, $r) if($important, !important, null); + // Key exists within the $uni-radius variable + @if (map-has-key($uni-radius, $r) and $d){ + @if $d == t { + border-top-left-radius:$radius-value; + border-top-right-radius:$radius-value; + }@else if $d == r { + border-top-right-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == b { + border-bottom-left-radius:$radius-value; + border-bottom-right-radius:$radius-value; + }@else if $d == l { + border-top-left-radius:$radius-value; + border-bottom-left-radius:$radius-value; + }@else if $d == tl { + border-top-left-radius:$radius-value; + }@else if $d == tr { + border-top-right-radius:$radius-value; + }@else if $d == br { + border-bottom-right-radius:$radius-value; + }@else if $d == bl { + border-bottom-left-radius:$radius-value; + } + }@else{ + border-radius:$radius-value; + } +} + +@each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $key} { + @include radius($key) + } + }@else{ + .uni-radius { + @include radius($key) + } + } +} + +@each $direction in t, r, b, l,tl, tr, br, bl { + @each $key, $child in $uni-radius { + @if($key){ + .uni-radius-#{"" + $direction}-#{"" + $key} { + @include radius($key,$direction,false) + } + }@else{ + .uni-radius-#{$direction} { + @include radius($key,$direction,false) + } + } + } +} diff --git a/uni_modules/uni-scss/styles/setting/_space.scss b/uni_modules/uni-scss/styles/setting/_space.scss new file mode 100644 index 0000000..3c89528 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_space.scss @@ -0,0 +1,56 @@ + +@mixin fn($space,$direction,$size,$n) { + @if $n { + #{$space}-#{$direction}: #{$size*$uni-space-root}px + } @else { + #{$space}-#{$direction}: #{-$size*$uni-space-root}px + } +} +@mixin get-styles($direction,$i,$space,$n){ + @if $direction == t { + @include fn($space, top,$i,$n); + } + @if $direction == r { + @include fn($space, right,$i,$n); + } + @if $direction == b { + @include fn($space, bottom,$i,$n); + } + @if $direction == l { + @include fn($space, left,$i,$n); + } + @if $direction == x { + @include fn($space, left,$i,$n); + @include fn($space, right,$i,$n); + } + @if $direction == y { + @include fn($space, top,$i,$n); + @include fn($space, bottom,$i,$n); + } + @if $direction == a { + @if $n { + #{$space}:#{$i*$uni-space-root}px; + } @else { + #{$space}:#{-$i*$uni-space-root}px; + } + } +} + +@each $orientation in m,p { + $space: margin; + @if $orientation == m { + $space: margin; + } @else { + $space: padding; + } + @for $i from 0 through 16 { + @each $direction in t, r, b, l, x, y, a { + .uni-#{$orientation}#{$direction}-#{$i} { + @include get-styles($direction,$i,$space,true); + } + .uni-#{$orientation}#{$direction}-n#{$i} { + @include get-styles($direction,$i,$space,false); + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-scss/styles/setting/_styles.scss b/uni_modules/uni-scss/styles/setting/_styles.scss new file mode 100644 index 0000000..689afec --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_styles.scss @@ -0,0 +1,167 @@ +/* #ifndef APP-NVUE */ + +$-color-white:#fff; +$-color-black:#000; +@mixin base-style($color) { + color: #fff; + background-color: $color; + border-color: mix($-color-black, $color, 8%); + &:not([hover-class]):active { + background: mix($-color-black, $color, 10%); + border-color: mix($-color-black, $color, 20%); + color: $-color-white; + outline: none; + } +} +@mixin is-color($color) { + @include base-style($color); + &[loading] { + @include base-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &[loading], + &:not([hover-class]):active { + color: $-color-white; + border-color: mix(darken($color,10%), $-color-white); + background-color: mix($color, $-color-white); + } + } + +} +@mixin base-plain-style($color) { + color:$color; + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 70%); + &:not([hover-class]):active { + background: mix($-color-white, $color, 80%); + color: $color; + outline: none; + border-color: mix($-color-white, $color, 50%); + } +} +@mixin is-plain($color){ + &[plain] { + @include base-plain-style($color); + &[loading] { + @include base-plain-style($color); + &::before { + margin-right:5px; + } + } + &[disabled] { + &, + &:active { + color: mix($-color-white, $color, 40%); + background-color: mix($-color-white, $color, 90%); + border-color: mix($-color-white, $color, 80%); + } + } + } +} + + +.uni-btn { + margin: 5px; + color: #393939; + border:1px solid #ccc; + font-size: 16px; + font-weight: 200; + background-color: #F9F9F9; + // TODO 暂时处理边框隐藏一边的问题 + overflow: visible; + &::after{ + border: none; + } + + &:not([type]),&[type=default] { + color: #999; + &[loading] { + background: none; + &::before { + margin-right:5px; + } + } + + + + &[disabled]{ + color: mix($-color-white, #999, 60%); + &, + &[loading], + &:active { + color: mix($-color-white, #999, 60%); + background-color: mix($-color-white,$-color-black , 98%); + border-color: mix($-color-white, #999, 85%); + } + } + + &[plain] { + color: #999; + background: none; + border-color: $uni-border-1; + &:not([hover-class]):active { + background: none; + color: mix($-color-white, $-color-black, 80%); + border-color: mix($-color-white, $-color-black, 90%); + outline: none; + } + &[disabled]{ + &, + &[loading], + &:active { + background: none; + color: mix($-color-white, #999, 60%); + border-color: mix($-color-white, #999, 85%); + } + } + } + } + + &:not([hover-class]):active { + color: mix($-color-white, $-color-black, 50%); + } + + &[size=mini] { + font-size: 16px; + font-weight: 200; + border-radius: 8px; + } + + + + &.uni-btn-small { + font-size: 14px; + } + &.uni-btn-mini { + font-size: 12px; + } + + &.uni-btn-radius { + border-radius: 999px; + } + &[type=primary] { + @include is-color($uni-primary); + @include is-plain($uni-primary) + } + &[type=success] { + @include is-color($uni-success); + @include is-plain($uni-success) + } + &[type=error] { + @include is-color($uni-error); + @include is-plain($uni-error) + } + &[type=warning] { + @include is-color($uni-warning); + @include is-plain($uni-warning) + } + &[type=info] { + @include is-color($uni-info); + @include is-plain($uni-info) + } +} +/* #endif */ diff --git a/uni_modules/uni-scss/styles/setting/_text.scss b/uni_modules/uni-scss/styles/setting/_text.scss new file mode 100644 index 0000000..a34d08f --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_text.scss @@ -0,0 +1,24 @@ +@mixin get-styles($k,$c) { + @if $k == size or $k == weight{ + font-#{$k}:#{$c} + }@else{ + #{$k}:#{$c} + } +} + +@each $key, $child in $uni-headings { + /* #ifndef APP-NVUE */ + .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ + /* #ifdef APP-NVUE */ + .container .uni-#{$key} { + @each $k, $c in $child { + @include get-styles($k,$c) + } + } + /* #endif */ +} diff --git a/uni_modules/uni-scss/styles/setting/_variables.scss b/uni_modules/uni-scss/styles/setting/_variables.scss new file mode 100644 index 0000000..557d3d7 --- /dev/null +++ b/uni_modules/uni-scss/styles/setting/_variables.scss @@ -0,0 +1,146 @@ +// @use "sass:math"; +@import '../tools/functions.scss'; +// 间距基础倍数 +$uni-space-root: 2 !default; +// 边框半径默认值 +$uni-radius-root:5px !default; +$uni-radius: () !default; +// 边框半径断点 +$uni-radius: map-deep-merge( + ( + 0: 0, + // TODO 当前版本暂时不支持 sm 属性 + // 'sm': math.div($uni-radius-root, 2), + null: $uni-radius-root, + 'lg': $uni-radius-root * 2, + 'xl': $uni-radius-root * 6, + 'pill': 9999px, + 'circle': 50% + ), + $uni-radius +); +// 字体家族 +$body-font-family: 'Roboto', sans-serif !default; +// 文本 +$heading-font-family: $body-font-family !default; +$uni-headings: () !default; +$letterSpacing: -0.01562em; +$uni-headings: map-deep-merge( + ( + 'h1': ( + size: 32px, + weight: 300, + line-height: 50px, + // letter-spacing:-0.01562em + ), + 'h2': ( + size: 28px, + weight: 300, + line-height: 40px, + // letter-spacing: -0.00833em + ), + 'h3': ( + size: 24px, + weight: 400, + line-height: 32px, + // letter-spacing: normal + ), + 'h4': ( + size: 20px, + weight: 400, + line-height: 30px, + // letter-spacing: 0.00735em + ), + 'h5': ( + size: 16px, + weight: 400, + line-height: 24px, + // letter-spacing: normal + ), + 'h6': ( + size: 14px, + weight: 500, + line-height: 18px, + // letter-spacing: 0.0125em + ), + 'subtitle': ( + size: 12px, + weight: 400, + line-height: 20px, + // letter-spacing: 0.00937em + ), + 'body': ( + font-size: 14px, + font-weight: 400, + line-height: 22px, + // letter-spacing: 0.03125em + ), + 'caption': ( + 'size': 12px, + 'weight': 400, + 'line-height': 20px, + // 'letter-spacing': 0.03333em, + // 'text-transform': false + ) + ), + $uni-headings +); + + + +// 主色 +$uni-primary: #2979ff !default; +$uni-primary-disable:lighten($uni-primary,20%) !default; +$uni-primary-light: lighten($uni-primary,25%) !default; + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37 !default; +$uni-success-disable:lighten($uni-success,20%) !default; +$uni-success-light: lighten($uni-success,25%) !default; + +$uni-warning: #f3a73f !default; +$uni-warning-disable:lighten($uni-warning,20%) !default; +$uni-warning-light: lighten($uni-warning,25%) !default; + +$uni-error: #e43d33 !default; +$uni-error-disable:lighten($uni-error,20%) !default; +$uni-error-light: lighten($uni-error,25%) !default; + +$uni-info: #8f939c !default; +$uni-info-disable:lighten($uni-info,20%) !default; +$uni-info-light: lighten($uni-info,25%) !default; + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a !default; // 主要文字 +$uni-base-color: #6a6a6a !default; // 常规文字 +$uni-secondary-color: #909399 !default; // 次要文字 +$uni-extra-color: #c7c7c7 !default; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0 !default; +$uni-border-2: #EDEDED !default; +$uni-border-3: #DCDCDC !default; +$uni-border-4: #B9B9B9 !default; + +// 常规色 +$uni-black: #000000 !default; +$uni-white: #ffffff !default; +$uni-transparent: rgba($color: #000000, $alpha: 0) !default; + +// 背景色 +$uni-bg-color: #f7f7f7 !default; + +/* 水平间距 */ +$uni-spacing-sm: 8px !default; +$uni-spacing-base: 15px !default; +$uni-spacing-lg: 30px !default; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default; +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default; +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default; + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4) !default; diff --git a/uni_modules/uni-scss/styles/tools/functions.scss b/uni_modules/uni-scss/styles/tools/functions.scss new file mode 100644 index 0000000..ac6f63e --- /dev/null +++ b/uni_modules/uni-scss/styles/tools/functions.scss @@ -0,0 +1,19 @@ +// 合并 map +@function map-deep-merge($parent-map, $child-map){ + $result: $parent-map; + @each $key, $child in $child-map { + $parent-has-key: map-has-key($result, $key); + $parent-value: map-get($result, $key); + $parent-type: type-of($parent-value); + $child-type: type-of($child); + $parent-is-map: $parent-type == map; + $child-is-map: $child-type == map; + + @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){ + $result: map-merge($result, ( $key: $child )); + }@else { + $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) )); + } + } + @return $result; +}; diff --git a/uni_modules/uni-scss/theme.scss b/uni_modules/uni-scss/theme.scss new file mode 100644 index 0000000..80ee62f --- /dev/null +++ b/uni_modules/uni-scss/theme.scss @@ -0,0 +1,31 @@ +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; +// 主色 +$uni-primary: #2979ff; +// 辅助色 +$uni-success: #4cd964; +// 警告色 +$uni-warning: #f0ad4e; +// 错误色 +$uni-error: #dd524d; +// 描述色 +$uni-info: #909399; +// 中性色 +$uni-main-color: #303133; +$uni-base-color: #606266; +$uni-secondary-color: #909399; +$uni-extra-color: #C0C4CC; +// 背景色 +$uni-bg-color: #f5f5f5; +// 边框颜色 +$uni-border-1: #DCDFE6; +$uni-border-2: #E4E7ED; +$uni-border-3: #EBEEF5; +$uni-border-4: #F2F6FC; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); diff --git a/uni_modules/uni-scss/variables.scss b/uni_modules/uni-scss/variables.scss new file mode 100644 index 0000000..1c062d4 --- /dev/null +++ b/uni_modules/uni-scss/variables.scss @@ -0,0 +1,62 @@ +@import './styles/setting/_variables.scss'; +// 间距基础倍数 +$uni-space-root: 2; +// 边框半径默认值 +$uni-radius-root:5px; + +// 主色 +$uni-primary: #2979ff; +$uni-primary-disable:mix(#fff,$uni-primary,50%); +$uni-primary-light: mix(#fff,$uni-primary,80%); + +// 辅助色 +// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。 +$uni-success: #18bc37; +$uni-success-disable:mix(#fff,$uni-success,50%); +$uni-success-light: mix(#fff,$uni-success,80%); + +$uni-warning: #f3a73f; +$uni-warning-disable:mix(#fff,$uni-warning,50%); +$uni-warning-light: mix(#fff,$uni-warning,80%); + +$uni-error: #e43d33; +$uni-error-disable:mix(#fff,$uni-error,50%); +$uni-error-light: mix(#fff,$uni-error,80%); + +$uni-info: #8f939c; +$uni-info-disable:mix(#fff,$uni-info,50%); +$uni-info-light: mix(#fff,$uni-info,80%); + +// 中性色 +// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。 +$uni-main-color: #3a3a3a; // 主要文字 +$uni-base-color: #6a6a6a; // 常规文字 +$uni-secondary-color: #909399; // 次要文字 +$uni-extra-color: #c7c7c7; // 辅助说明 + +// 边框颜色 +$uni-border-1: #F0F0F0; +$uni-border-2: #EDEDED; +$uni-border-3: #DCDCDC; +$uni-border-4: #B9B9B9; + +// 常规色 +$uni-black: #000000; +$uni-white: #ffffff; +$uni-transparent: rgba($color: #000000, $alpha: 0); + +// 背景色 +$uni-bg-color: #f7f7f7; + +/* 水平间距 */ +$uni-spacing-sm: 8px; +$uni-spacing-base: 15px; +$uni-spacing-lg: 30px; + +// 阴影 +$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5); +$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2); +$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5); + +// 蒙版 +$uni-mask: rgba($color: #000000, $alpha: 0.4); diff --git a/uni_modules/uni-transition/changelog.md b/uni_modules/uni-transition/changelog.md new file mode 100644 index 0000000..faaf336 --- /dev/null +++ b/uni_modules/uni-transition/changelog.md @@ -0,0 +1,24 @@ +## 1.3.3(2024-04-23) +- 修复 当元素会受变量影响自动隐藏的bug +## 1.3.2(2023-05-04) +- 修复 NVUE 平台报错的问题 +## 1.3.1(2021-11-23) +- 修复 init 方法初始化问题 +## 1.3.0(2021-11-19) +- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) +- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition) +## 1.2.1(2021-09-27) +- 修复 init 方法不生效的 Bug +## 1.2.0(2021-07-30) +- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) +## 1.1.1(2021-05-12) +- 新增 示例地址 +- 修复 示例项目缺少组件的 Bug +## 1.1.0(2021-04-22) +- 新增 通过方法自定义动画 +- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式 +- 优化 动画触发逻辑,使动画更流畅 +- 优化 支持单独的动画类型 +- 优化 文档示例 +## 1.0.2(2021-02-05) +- 调整为 uni_modules 目录规范 diff --git a/uni_modules/uni-transition/components/uni-transition/createAnimation.js b/uni_modules/uni-transition/components/uni-transition/createAnimation.js new file mode 100644 index 0000000..8f89b18 --- /dev/null +++ b/uni_modules/uni-transition/components/uni-transition/createAnimation.js @@ -0,0 +1,131 @@ +// const defaultOption = { +// duration: 300, +// timingFunction: 'linear', +// delay: 0, +// transformOrigin: '50% 50% 0' +// } +// #ifdef APP-NVUE +const nvueAnimation = uni.requireNativePlugin('animation') +// #endif +class MPAnimation { + constructor(options, _this) { + this.options = options + // 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误 + this.animation = uni.createAnimation({ + ...options + }) + this.currentStepAnimates = {} + this.next = 0 + this.$ = _this + + } + + _nvuePushAnimates(type, args) { + let aniObj = this.currentStepAnimates[this.next] + let styles = {} + if (!aniObj) { + styles = { + styles: {}, + config: {} + } + } else { + styles = aniObj + } + if (animateTypes1.includes(type)) { + if (!styles.styles.transform) { + styles.styles.transform = '' + } + let unit = '' + if(type === 'rotate'){ + unit = 'deg' + } + styles.styles.transform += `${type}(${args+unit}) ` + } else { + styles.styles[type] = `${args}` + } + this.currentStepAnimates[this.next] = styles + } + _animateRun(styles = {}, config = {}) { + let ref = this.$.$refs['ani'].ref + if (!ref) return + return new Promise((resolve, reject) => { + nvueAnimation.transition(ref, { + styles, + ...config + }, res => { + resolve() + }) + }) + } + + _nvueNextAnimate(animates, step = 0, fn) { + let obj = animates[step] + if (obj) { + let { + styles, + config + } = obj + this._animateRun(styles, config).then(() => { + step += 1 + this._nvueNextAnimate(animates, step, fn) + }) + } else { + this.currentStepAnimates = {} + typeof fn === 'function' && fn() + this.isEnd = true + } + } + + step(config = {}) { + // #ifndef APP-NVUE + this.animation.step(config) + // #endif + // #ifdef APP-NVUE + this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config) + this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin + this.next++ + // #endif + return this + } + + run(fn) { + // #ifndef APP-NVUE + this.$.animationData = this.animation.export() + this.$.timer = setTimeout(() => { + typeof fn === 'function' && fn() + }, this.$.durationTime) + // #endif + // #ifdef APP-NVUE + this.isEnd = false + let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref + if(!ref) return + this._nvueNextAnimate(this.currentStepAnimates, 0, fn) + this.next = 0 + // #endif + } +} + + +const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d', + 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY', + 'translateZ' +] +const animateTypes2 = ['opacity', 'backgroundColor'] +const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom'] +animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => { + MPAnimation.prototype[type] = function(...args) { + // #ifndef APP-NVUE + this.animation[type](...args) + // #endif + // #ifdef APP-NVUE + this._nvuePushAnimates(type, args) + // #endif + return this + } +}) + +export function createAnimation(option, _this) { + if(!_this) return + clearTimeout(_this.timer) + return new MPAnimation(option, _this) +} diff --git a/uni_modules/uni-transition/components/uni-transition/uni-transition.vue b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue new file mode 100644 index 0000000..f3ddd1f --- /dev/null +++ b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue @@ -0,0 +1,286 @@ + + + + + diff --git a/uni_modules/uni-transition/package.json b/uni_modules/uni-transition/package.json new file mode 100644 index 0000000..d5c20e1 --- /dev/null +++ b/uni_modules/uni-transition/package.json @@ -0,0 +1,85 @@ +{ + "id": "uni-transition", + "displayName": "uni-transition 过渡动画", + "version": "1.3.3", + "description": "元素的简单过渡动画", + "keywords": [ + "uni-ui", + "uniui", + "动画", + "过渡", + "过渡动画" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": ["uni-scss"], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y", + "alipay": "n" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + }, + "Vue": { + "vue2": "y", + "vue3": "y" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/uni-transition/readme.md b/uni_modules/uni-transition/readme.md new file mode 100644 index 0000000..2f8a77e --- /dev/null +++ b/uni_modules/uni-transition/readme.md @@ -0,0 +1,11 @@ + + +## Transition 过渡动画 +> **组件名:uni-transition** +> 代码块: `uTransition` + + +元素过渡动画 + +### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition) +#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 \ No newline at end of file diff --git a/uni_modules/zero-loading/changelog.md b/uni_modules/zero-loading/changelog.md new file mode 100644 index 0000000..e6befbb --- /dev/null +++ b/uni_modules/zero-loading/changelog.md @@ -0,0 +1,21 @@ +## 1.3.2(2023-10-31) +修改遮罩默认透明度为0.1 +## 1.3.1(2023-10-31) +## 新增支持,自定义动画颜色(仅部分动画支持) +## 新增动画-annulus(圆环) +## 1.3.0(2023-08-11) +支持vue3使用, 增加动画类型radar(雷达) +## 1.2.2(2023-06-12) +增加 maskOpacity, maskMini, maskDark自定义参数, 提供更丰富的自定义遮罩层能力 +## 1.2.1(2022-09-09) +增加齿轮动画 type=gear +## 1.2.0(2022-05-27) +1. 增加加载类型-剑气(sword),原子(atom) +2. 默认类型改为 atom +3. 遮罩透明度调整 +## 1.1.1(2022-04-02) +更新使用说明 +## 1.1.0(2022-02-23) +增加 type="love" 的心形加载动画 +## 1.0.0(2022-01-28) +首次发布 diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue new file mode 100644 index 0000000..bbdd9c0 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-annulus.vue @@ -0,0 +1,52 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue new file mode 100644 index 0000000..26c995b --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-atom.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue new file mode 100644 index 0000000..ab3ea28 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-bounce.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue new file mode 100644 index 0000000..b9264b1 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-circle.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue new file mode 100644 index 0000000..df30a8e --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-eyes.vue @@ -0,0 +1,80 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue new file mode 100644 index 0000000..ffa33d6 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-gear.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue new file mode 100644 index 0000000..8635ad5 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-love.vue @@ -0,0 +1,210 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue new file mode 100644 index 0000000..a3804a7 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-pulse.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue new file mode 100644 index 0000000..8ec9bcd --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-radar.vue @@ -0,0 +1,137 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue new file mode 100644 index 0000000..1b13507 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-sun.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue new file mode 100644 index 0000000..2433549 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-sword.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/static/loading-triangle.vue b/uni_modules/zero-loading/components/zero-loading/static/loading-triangle.vue new file mode 100644 index 0000000..89236a7 --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/static/loading-triangle.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/uni_modules/zero-loading/components/zero-loading/zero-loading.vue b/uni_modules/zero-loading/components/zero-loading/zero-loading.vue new file mode 100644 index 0000000..4f6c98a --- /dev/null +++ b/uni_modules/zero-loading/components/zero-loading/zero-loading.vue @@ -0,0 +1,134 @@ + + + + + \ No newline at end of file diff --git a/uni_modules/zero-loading/package.json b/uni_modules/zero-loading/package.json new file mode 100644 index 0000000..c0bc0c1 --- /dev/null +++ b/uni_modules/zero-loading/package.json @@ -0,0 +1,80 @@ +{ + "id": "zero-loading", + "displayName": "zero-loading(加载动画)", + "version": "1.3.2", + "description": "纯css加载动画, 一个标签元素即可实现炫酷的全屏loading效果,支持vue2,vue3", + "keywords": [ + "loading", + "加载动画", + "css动画", + "加载" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, +"dcloudext": { + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "无" + }, + "npmurl": "", + "type": "component-vue" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "u", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/zero-loading/readme.md b/uni_modules/zero-loading/readme.md new file mode 100644 index 0000000..4163b82 --- /dev/null +++ b/uni_modules/zero-loading/readme.md @@ -0,0 +1,60 @@ +# zero-loading + +> 仅测试于 vue2, vue3, 微信小程序. 其他平台自行测试 + +## 使用方法 + +导入 `uni_modules` 后直接使用即可 + +提供多种加载动画类型,传入 type 改变 loading 样式,不传默认 circle + +### 全屏使用 + +```html + +``` + +### 局部使用 + +**父元素的 `position` 记得改为 `relative` 不然可能影响效果** + +```html + +``` + +## 参数说明 + +| 参数 | 类型 | 默认值| 描述 | +| -------- | ------- | ------| ------------ | +| type | String | atom | 样式 | +| position | String | fixed | 定位方式 | +| zIndex | Number | 9 | | +| mask | Boolean | false | 是否需要遮罩 (默认为全屏遮罩,背景色默认为黑色)| +| maskOpacity | Number | 0.1 | 遮罩透明度 | +| maskMini | Boolean | false | 传入true时,使用小遮罩 | +| maskDark | Boolean | true | 传入false时,遮罩背景色为白色 | +|color| String | #0396FF | 自定义颜色,仅部分支持 | + +### type 可选值: + +| type 值 | 描述 | +| -------- | ---- | +|annulus | 圆环 (自定义颜色) | +| radar | 雷达 | +| gear | 齿轮 | +| sword | 剑气 (自定义颜色) | +| atom | 原子 (自定义颜色) | +| circle | 圆圈 | +| love | 爱心 | +| pulse | 脉冲 | +| sun | 太阳 | +| eyes | 眼睛 | +| triangle | 三角 | +| bounce | 弹跳 | + +插件预览: +![code](https://img.zerojs.cn/mweb/we_code.jpg) + +> 小程序搜索: zerojs零技术 + +> 预览的小程序不一定能及时更新当前插件 diff --git a/uni_modules/zero-privacy/components/zero-privacy/zero-privacy.vue b/uni_modules/zero-privacy/components/zero-privacy/zero-privacy.vue new file mode 100644 index 0000000..c129842 --- /dev/null +++ b/uni_modules/zero-privacy/components/zero-privacy/zero-privacy.vue @@ -0,0 +1,314 @@ + + + + \ No newline at end of file diff --git a/uni_modules/zero-privacy/package.json b/uni_modules/zero-privacy/package.json new file mode 100644 index 0000000..d0fcc47 --- /dev/null +++ b/uni_modules/zero-privacy/package.json @@ -0,0 +1,85 @@ +{ + "id": "zero-privacy", + "displayName": "zero-privacy (微信小程序隐私协议弹窗)", + "version": "1.1.5", + "description": "自2023年9月15日起,微信要求小程序开发者同步用户同意的规则后才能调用隐私接口。支持自定义弹窗内容、弹出方式、触发条件、主题颜色。兼容vue2,vue3", + "keywords": [ + "zero-privacy", + "隐私协议", + "隐私政策", + "微信小程序", + "弹窗" +], + "repository": "", + "engines": { + "HBuilderX": "^3.1.0" + }, + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "插件不采集任何数据", + "permissions": "无" + }, + "npmurl": "" + }, + "uni_modules": { + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "Vue": { + "vue2": "y", + "vue3": "y" + }, + "App": { + "app-vue": "u", + "app-nvue": "u" + }, + "H5-mobile": { + "Safari": "u", + "Android Browser": "u", + "微信浏览器(Android)": "u", + "QQ浏览器(Android)": "u" + }, + "H5-pc": { + "Chrome": "u", + "IE": "u", + "Edge": "u", + "Firefox": "u", + "Safari": "u" + }, + "小程序": { + "微信": "y", + "阿里": "u", + "百度": "u", + "字节跳动": "u", + "QQ": "u", + "钉钉": "u", + "快手": "u", + "飞书": "u", + "京东": "u" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/utils/calculate/calculate.js b/utils/calculate/calculate.js new file mode 100644 index 0000000..82db513 --- /dev/null +++ b/utils/calculate/calculate.js @@ -0,0 +1,28 @@ +var Decimal = require('decimal.js') + +const add = function(a, b) { + let result = new Decimal(a).add(new Decimal(b)); + return result.toNumber(); +} + +const sub = function(a, b) { + let result = new Decimal(a).sub(new Decimal(b)); + return result.toNumber(); +} + +const mul = function(a, b) { + let result = new Decimal(a).mul(new Decimal(b)); + return result.toNumber(); +} + +const div = function(a, b) { + let result = new Decimal(a).div(new Decimal(b)); + return result.toNumber(); +} + +module.exports = { + add, + sub, + mul, + div +}; \ No newline at end of file diff --git a/utils/timeUtil/timeUtil.js b/utils/timeUtil/timeUtil.js new file mode 100644 index 0000000..7e55d3b --- /dev/null +++ b/utils/timeUtil/timeUtil.js @@ -0,0 +1,15 @@ +const getNowTime = function() { + const now = new Date(); + const year = now.getFullYear(); // 获取完整的年份 + const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份是从0开始的,所以加1,并确保是两位数 + const day = String(now.getDate()).padStart(2, '0'); // 获取当前日期,并确保是两位数 + const hours = String(now.getHours()).padStart(2, '0'); // 获取当前小时(0-23),并确保是两位数 + const minutes = String(now.getMinutes()).padStart(2, '0'); // 获取当前分钟,并确保是两位数 + const seconds = String(now.getSeconds()).padStart(2, '0'); // 获取当前秒数,并确保是两位数 + + // 拼接字符串并返回 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; +} + + +module.exports = getNowTime; \ No newline at end of file diff --git a/utils/uploadToAliOss/Base64.js b/utils/uploadToAliOss/Base64.js new file mode 100644 index 0000000..b2941d5 --- /dev/null +++ b/utils/uploadToAliOss/Base64.js @@ -0,0 +1,132 @@ +const Base64 = { + + // private property + _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + + // public method for encoding + encode: function (input) { + var output = ""; + var chr1, chr2, chr3, enc1, enc2, enc3, enc4; + var i = 0; + + input = Base64._utf8_encode(input); + + while (i < input.length) { + + chr1 = input.charCodeAt(i++); + chr2 = input.charCodeAt(i++); + chr3 = input.charCodeAt(i++); + + enc1 = chr1 >> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + + this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) + + this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4); + + } + + return output; + }, + + // public method for decoding + decode: function (input) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + while (i < input.length) { + + enc1 = this._keyStr.indexOf(input.charAt(i++)); + enc2 = this._keyStr.indexOf(input.charAt(i++)); + enc3 = this._keyStr.indexOf(input.charAt(i++)); + enc4 = this._keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + + } + + output = Base64._utf8_decode(output); + + return output; + + }, + + // private method for UTF-8 encoding + _utf8_encode: function (string) { + string = string.replace(/\r\n/g, "\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } else if ((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; + }, + + // private method for UTF-8 decoding + _utf8_decode: function (utftext) { + var string = ""; + var i = 0; + var c = c1 = c2 = 0; + + while (i < utftext.length) { + + c = utftext.charCodeAt(i); + + if (c < 128) { + string += String.fromCharCode(c); + i++; + } else if ((c > 191) && (c < 224)) { + c2 = utftext.charCodeAt(i + 1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } else { + c2 = utftext.charCodeAt(i + 1); + c3 = utftext.charCodeAt(i + 2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + + } + + return string; + } +} + +module.exports = Base64; \ No newline at end of file diff --git a/utils/uploadToAliOss/config.js b/utils/uploadToAliOss/config.js new file mode 100644 index 0000000..19cfa9c --- /dev/null +++ b/utils/uploadToAliOss/config.js @@ -0,0 +1,8 @@ +var config = { + //aliyun OSS config + uploadImageUrl: `https://ai-travel-dev.oss-cn-beijing.aliyuncs.com`, + AccessKeySecret: 'JfBWY38IU3FZUaTCt1kgCPALXbbJdM', + OSSAccessKeyId: 'LTAI5tS8qY4qpk3Bm87frDwk', + timeout: 1*60*1000 , +}; +module.exports = config \ No newline at end of file diff --git a/utils/uploadToAliOss/crypto.js b/utils/uploadToAliOss/crypto.js new file mode 100644 index 0000000..286539e --- /dev/null +++ b/utils/uploadToAliOss/crypto.js @@ -0,0 +1,185 @@ +/*! + * Crypto-JS v1.1.0 + * http://code.google.com/p/crypto-js/ + * Copyright (c) 2009, Jeff Mott. All rights reserved. + * http://code.google.com/p/crypto-js/wiki/License + */ + +const Crypto = {}; + +(function(){ + +var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + +// Crypto utilities +var util = Crypto.util = { + + // Bit-wise rotate left + rotl: function (n, b) { + return (n << b) | (n >>> (32 - b)); + }, + + // Bit-wise rotate right + rotr: function (n, b) { + return (n << (32 - b)) | (n >>> b); + }, + + // Swap big-endian to little-endian and vice versa + endian: function (n) { + + // If number given, swap endian + if (n.constructor == Number) { + return util.rotl(n, 8) & 0x00FF00FF | + util.rotl(n, 24) & 0xFF00FF00; + } + + // Else, assume array and swap all items + for (var i = 0; i < n.length; i++) + n[i] = util.endian(n[i]); + return n; + + }, + + // Generate an array of any length of random bytes + randomBytes: function (n) { + for (var bytes = []; n > 0; n--) + bytes.push(Math.floor(Math.random() * 256)); + return bytes; + }, + + // Convert a string to a byte array + stringToBytes: function (str) { + var bytes = []; + for (var i = 0; i < str.length; i++) + bytes.push(str.charCodeAt(i)); + return bytes; + }, + + // Convert a byte array to a string + bytesToString: function (bytes) { + var str = []; + for (var i = 0; i < bytes.length; i++) + str.push(String.fromCharCode(bytes[i])); + return str.join(""); + }, + + // Convert a string to big-endian 32-bit words + stringToWords: function (str) { + var words = []; + for (var c = 0, b = 0; c < str.length; c++, b += 8) + words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32); + return words; + }, + + // Convert a byte array to big-endian 32-bits words + bytesToWords: function (bytes) { + var words = []; + for (var i = 0, b = 0; i < bytes.length; i++, b += 8) + words[b >>> 5] |= bytes[i] << (24 - b % 32); + return words; + }, + + // Convert big-endian 32-bit words to a byte array + wordsToBytes: function (words) { + var bytes = []; + for (var b = 0; b < words.length * 32; b += 8) + bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); + return bytes; + }, + + // Convert a byte array to a hex string + bytesToHex: function (bytes) { + var hex = []; + for (var i = 0; i < bytes.length; i++) { + hex.push((bytes[i] >>> 4).toString(16)); + hex.push((bytes[i] & 0xF).toString(16)); + } + return hex.join(""); + }, + + // Convert a hex string to a byte array + hexToBytes: function (hex) { + var bytes = []; + for (var c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; + }, + + // Convert a byte array to a base-64 string + bytesToBase64: function (bytes) { + + // Use browser-native function if it exists + if (typeof btoa == "function") return btoa(util.bytesToString(bytes)); + + var base64 = [], + overflow; + + for (var i = 0; i < bytes.length; i++) { + switch (i % 3) { + case 0: + base64.push(base64map.charAt(bytes[i] >>> 2)); + overflow = (bytes[i] & 0x3) << 4; + break; + case 1: + base64.push(base64map.charAt(overflow | (bytes[i] >>> 4))); + overflow = (bytes[i] & 0xF) << 2; + break; + case 2: + base64.push(base64map.charAt(overflow | (bytes[i] >>> 6))); + base64.push(base64map.charAt(bytes[i] & 0x3F)); + overflow = -1; + } + } + + // Encode overflow bits, if there are any + if (overflow != undefined && overflow != -1) + base64.push(base64map.charAt(overflow)); + + // Add padding + while (base64.length % 4 != 0) base64.push("="); + + return base64.join(""); + + }, + + // Convert a base-64 string to a byte array + base64ToBytes: function (base64) { + + // Use browser-native function if it exists + if (typeof atob == "function") return util.stringToBytes(atob(base64)); + + // Remove non-base-64 characters + base64 = base64.replace(/[^A-Z0-9+\/]/ig, ""); + + var bytes = []; + + for (var i = 0; i < base64.length; i++) { + switch (i % 4) { + case 1: + bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) | + (base64map.indexOf(base64.charAt(i)) >>> 4)); + break; + case 2: + bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) | + (base64map.indexOf(base64.charAt(i)) >>> 2)); + break; + case 3: + bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) | + (base64map.indexOf(base64.charAt(i)))); + break; + } + } + + return bytes; + + } + +}; + +// Crypto mode namespace +Crypto.mode = {}; + +})(); + +module.exports = Crypto; \ No newline at end of file diff --git a/utils/uploadToAliOss/hmac.js b/utils/uploadToAliOss/hmac.js new file mode 100644 index 0000000..41ec317 --- /dev/null +++ b/utils/uploadToAliOss/hmac.js @@ -0,0 +1,41 @@ +/*! + * Crypto-JS v1.1.0 + * http://code.google.com/p/crypto-js/ + * Copyright (c) 2009, Jeff Mott. All rights reserved. + * http://code.google.com/p/crypto-js/wiki/License + */ + +const Crypto = require('./crypto.js'); + +(function(){ + +// Shortcut +var util = Crypto.util; + +Crypto.HMAC = function (hasher, message, key, options) { + + // Allow arbitrary length keys + key = key.length > hasher._blocksize * 4 ? + hasher(key, { asBytes: true }) : + util.stringToBytes(key); + + // XOR keys with pad constants + var okey = key, + ikey = key.slice(0); + for (var i = 0; i < hasher._blocksize * 4; i++) { + okey[i] ^= 0x5C; + ikey[i] ^= 0x36; + } + + var hmacbytes = hasher(util.bytesToString(okey) + + hasher(util.bytesToString(ikey) + message, { asString: true }), + { asBytes: true }); + return options && options.asBytes ? hmacbytes : + options && options.asString ? util.bytesToString(hmacbytes) : + util.bytesToHex(hmacbytes); + +}; + +})(); + +module.exports = Crypto; \ No newline at end of file diff --git a/utils/uploadToAliOss/sha1.js b/utils/uploadToAliOss/sha1.js new file mode 100644 index 0000000..64e39e5 --- /dev/null +++ b/utils/uploadToAliOss/sha1.js @@ -0,0 +1,86 @@ +/*! + * Crypto-JS v1.1.0 + * http://code.google.com/p/crypto-js/ + * Copyright (c) 2009, Jeff Mott. All rights reserved. + * http://code.google.com/p/crypto-js/wiki/License + */ + +const Crypto = require('./crypto.js'); + +(function(){ + +// Shortcut +var util = Crypto.util; + +// Public API +var SHA1 = Crypto.SHA1 = function (message, options) { + var digestbytes = util.wordsToBytes(SHA1._sha1(message)); + return options && options.asBytes ? digestbytes : + options && options.asString ? util.bytesToString(digestbytes) : + util.bytesToHex(digestbytes); +}; + +// The core +SHA1._sha1 = function (message) { + + var m = util.stringToWords(message), + l = message.length * 8, + w = [], + H0 = 1732584193, + H1 = -271733879, + H2 = -1732584194, + H3 = 271733878, + H4 = -1009589776; + + // Padding + m[l >> 5] |= 0x80 << (24 - l % 32); + m[((l + 64 >>> 9) << 4) + 15] = l; + + for (var i = 0; i < m.length; i += 16) { + + var a = H0, + b = H1, + c = H2, + d = H3, + e = H4; + + for (var j = 0; j < 80; j++) { + + if (j < 16) w[j] = m[i + j]; + else { + var n = w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16]; + w[j] = (n << 1) | (n >>> 31); + } + + var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + ( + j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 : + j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 : + j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 : + (H1 ^ H2 ^ H3) - 899497514); + + H4 = H3; + H3 = H2; + H2 = (H1 << 30) | (H1 >>> 2); + H1 = H0; + H0 = t; + + } + + H0 += a; + H1 += b; + H2 += c; + H3 += d; + H4 += e; + + } + + return [H0, H1, H2, H3, H4]; + +}; + +// Package private blocksize +SHA1._blocksize = 16; + +})(); + +module.exports = Crypto; \ No newline at end of file diff --git a/utils/uploadToAliOss/uploadAliyun.js b/utils/uploadToAliOss/uploadAliyun.js new file mode 100644 index 0000000..29fb9c8 --- /dev/null +++ b/utils/uploadToAliOss/uploadAliyun.js @@ -0,0 +1,86 @@ +const env = require('./config.js'); + +const Base64 = require('./Base64.js'); + +require('./hmac.js'); +require('./sha1.js'); +const Crypto = require('./crypto.js'); + + +const uploadFile = function (params) { + if (!params.filePath) { + wx.showModal({ + title: '文件错误', + content: '请重新上传文件', + showCancel: false, + }) + return; + } + + //阿里云指定文件夹 + const aliyunFileKey = params.dir + new Date().getTime() + Math.floor(Math.random() * 150) + params.type; + const aliyunServerURL = env.uploadImageUrl; + const accessid = env.OSSAccessKeyId; + const policyBase64 = getPolicyBase64(); + const signature = getSignature(policyBase64); + + // console.log('aliyunFileKey=', aliyunFileKey); + // console.log('aliyunServerURL', aliyunServerURL); + wx.uploadFile({ + url: aliyunServerURL, + filePath: params.filePath, + name: 'file', + formData: { + 'key': aliyunFileKey, + 'policy': policyBase64, + 'OSSAccessKeyId': accessid, + 'signature': signature, + 'success_action_status': '200', + }, + success: function (res) { + if (res.statusCode != 200) { + if (params.fail) { + params.fail(res) + } + return; + } + if (params.success) { + params.success(aliyunFileKey); + } + }, + fail: function (err) { + err.wxaddinfo = aliyunServerURL; + if (params.fail) { + params.fail(err) + } + }, + }) +} + +const getPolicyBase64 = function () { + let date = new Date(); + date.setHours(date.getHours() + env.timeout); + let srcT = date.toISOString(); + const policyText = { + "expiration": srcT, //设置该Policy的失效时间 + "conditions": [ + ["content-length-range", 0, 1024 * 1024 * 1024 * 1024] // 设置上传文件的大小限制 + ] + }; + + const policyBase64 = Base64.encode(JSON.stringify(policyText)); + return policyBase64; +} + +const getSignature = function (policyBase64) { + const accesskey = env.AccessKeySecret; + + const bytes = Crypto.HMAC(Crypto.SHA1, policyBase64, accesskey, { + asBytes: true + }); + const signature = Crypto.util.bytesToBase64(bytes); + + return signature; +} + +module.exports = uploadFile; \ No newline at end of file