@cobaltx/sdk-v2
Version:
An SDK for building applications on top of CobaltX.
1 lines • 401 kB
Source Map (JSON)
{"version":3,"sources":["../../../src/common/txTool/txUtils.ts","../../../src/common/logger.ts","../../../src/cobaltx/liquidity/utils.ts","../../../../../node_modules/decimal.js/decimal.mjs","../../../src/cobaltx/token/utils.ts","../../../src/module/amount.ts","../../../src/common/bignumber.ts","../../../src/cobaltx/token/constant.ts","../../../src/module/token.ts","../../../src/common/pubKey.ts","../../../src/module/currency.ts","../../../src/module/fraction.ts","../../../src/common/constant.ts","../../../src/module/formatter.ts","../../../src/module/percent.ts","../../../src/module/price.ts","../../../src/common/utility.ts","../../../src/common/accountInfo.ts","../../../src/common/pda.ts","../../../src/common/programId.ts","../../../src/common/transfer.ts","../../../src/common/txTool/lookupTable.ts","../../../src/common/txTool/txTool.ts","../../../src/cobaltx/liquidity/instruction.ts","../../../src/marshmallow/index.ts","../../../src/marshmallow/buffer-layout.ts","../../../src/cobaltx/liquidity/layout.ts","../../../src/cobaltx/liquidity/stable.ts","../../../src/cobaltx/liquidity/serum.ts","../../../src/cobaltx/liquidity/constant.ts"],"sourcesContent":["import {\n Commitment,\n ComputeBudgetProgram,\n Connection,\n EpochInfo,\n Keypair,\n PublicKey,\n SimulatedTransactionResponse,\n Transaction,\n TransactionInstruction,\n TransactionMessage,\n VersionedTransaction,\n} from \"@solana/web3.js\";\n\nimport { createLogger } from \"../logger\";\nimport { CacheLTA } from \"./lookupTable\";\nimport { InstructionType } from \"./txType\";\n\nimport { TOKEN_PROGRAM_ID } from \"@solana/spl-token\";\nimport { ComputeBudgetConfig } from \"../../cobaltx/type\";\n\nconst logger = createLogger(\"CobaltX_txUtil\");\n\nexport const MAX_BASE64_SIZE = 1644;\n\nexport function addComputeBudget(config: ComputeBudgetConfig): {\n instructions: TransactionInstruction[];\n instructionTypes: string[];\n} {\n const ins: TransactionInstruction[] = [];\n const insTypes: string[] = [];\n if (config.microLamports) {\n ins.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: config.microLamports }));\n insTypes.push(InstructionType.SetComputeUnitPrice);\n }\n if (config.units) {\n ins.push(ComputeBudgetProgram.setComputeUnitLimit({ units: config.units }));\n insTypes.push(InstructionType.SetComputeUnitLimit);\n }\n\n return {\n instructions: ins,\n instructionTypes: insTypes,\n };\n}\n\nexport async function getRecentBlockHash(connection: Connection, propsCommitment?: Commitment): Promise<string> {\n const commitment = propsCommitment ?? \"confirmed\";\n return (await connection.getLatestBlockhash?.({ commitment }))?.blockhash;\n}\n\nexport async function confirmTransaction(connection: Connection, txId: string): Promise<string> {\n connection.getSignatureStatuses([txId]);\n return new Promise((resolve, reject) => {\n const id = setTimeout(reject, 60 * 1000);\n connection.onSignature(\n txId,\n (signatureResult) => {\n clearTimeout(id);\n if (!signatureResult.err) {\n resolve(\"\");\n return;\n }\n reject(signatureResult.err.toString());\n },\n \"confirmed\",\n );\n });\n}\n\n/**\n * Forecast transaction size\n */\nexport function forecastTransactionSize(instructions: TransactionInstruction[], signers: PublicKey[]): boolean {\n if (instructions.length < 1) logger.logWithError(`no instructions provided: ${instructions.toString()}`);\n if (signers.length < 1) logger.logWithError(`no signers provided:, ${signers.toString()}`);\n\n const transaction = new Transaction();\n transaction.recentBlockhash = \"11111111111111111111111111111111\";\n transaction.feePayer = signers[0];\n transaction.add(...instructions);\n\n try {\n return Buffer.from(transaction.serialize({ verifySignatures: false })).toString(\"base64\").length < MAX_BASE64_SIZE;\n } catch (error) {\n return false;\n }\n}\n\n/**\n * Simulates multiple instruction\n */\n/**\n * Simulates multiple instruction\n */\nexport async function simulateMultipleInstruction(\n connection: Connection,\n instructions: TransactionInstruction[],\n keyword: string,\n batchRequest = true,\n): Promise<string[]> {\n const feePayer = new PublicKey(\"CobaltXSimuLateTransaction11111111111111111\");\n\n const transactions: Transaction[] = [];\n\n let transaction = new Transaction();\n transaction.feePayer = feePayer;\n\n for (const instruction of instructions) {\n if (!forecastTransactionSize([...transaction.instructions, instruction], [feePayer])) {\n transactions.push(transaction);\n transaction = new Transaction();\n transaction.feePayer = feePayer;\n }\n transaction.add(instruction);\n }\n if (transaction.instructions.length > 0) {\n transactions.push(transaction);\n }\n\n let results: SimulatedTransactionResponse[] = [];\n\n try {\n results = await simulateTransaction(connection, transactions, batchRequest);\n if (results.find((i) => i.err !== null)) throw Error(\"rpc simulateTransaction error\");\n } catch (error) {\n if (error instanceof Error) {\n logger.logWithError(\"failed to simulate for instructions\", \"RPC_ERROR\", {\n message: error.message,\n });\n }\n }\n\n const logs: string[] = [];\n for (const result of results) {\n logger.debug(\"simulate result:\", result);\n\n if (result.logs) {\n const filteredLog = result.logs.filter((log) => log && log.includes(keyword));\n logger.debug(\"filteredLog:\", logs);\n if (!filteredLog.length) logger.logWithError(\"simulate log not match keyword\", \"keyword\", keyword);\n logs.push(...filteredLog);\n }\n }\n\n return logs;\n}\n\nexport function parseSimulateLogToJson(log: string, keyword: string): any {\n const results = log.match(/{[\"\\w:,]+}/g);\n if (!results || results.length !== 1) {\n return logger.logWithError(`simulate log fail to match json, keyword: ${keyword}`);\n }\n\n return results[0];\n}\n\nexport function parseSimulateValue(log: string, key: string): any {\n const reg = new RegExp(`\"${key}\":(\\\\d+)`, \"g\");\n\n const results = reg.exec(log);\n if (!results || results.length !== 2) {\n return logger.logWithError(`simulate log fail to match key\", key: ${key}`);\n }\n\n return results[1];\n}\n\nexport interface ProgramAddress {\n publicKey: PublicKey;\n nonce: number;\n}\nexport function findProgramAddress(\n seeds: Array<Buffer | Uint8Array>,\n programId: PublicKey,\n): {\n publicKey: PublicKey;\n nonce: number;\n} {\n const [publicKey, nonce] = PublicKey.findProgramAddressSync(seeds, programId);\n return { publicKey, nonce };\n}\n\nexport async function simulateTransaction(\n connection: Connection,\n transactions: Transaction[],\n batchRequest?: boolean,\n): Promise<any[]> {\n let results: any[] = [];\n if (batchRequest) {\n const getLatestBlockhash = await connection.getLatestBlockhash();\n\n const encodedTransactions: string[] = [];\n for (const transaction of transactions) {\n transaction.recentBlockhash = getLatestBlockhash.blockhash;\n transaction.lastValidBlockHeight = getLatestBlockhash.lastValidBlockHeight;\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const message = transaction._compile();\n const signData = message.serialize();\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const wireTransaction = transaction._serialize(signData);\n const encodedTransaction = wireTransaction.toString(\"base64\");\n\n encodedTransactions.push(encodedTransaction);\n }\n\n const batch = encodedTransactions.map((keys) => {\n const args = connection._buildArgs([keys], undefined, \"base64\");\n return {\n methodName: \"simulateTransaction\",\n args,\n };\n });\n\n const reqData: { methodName: string; args: any[] }[][] = [];\n const itemReqIndex = 20;\n for (let i = 0; i < Math.ceil(batch.length / itemReqIndex); i++) {\n reqData.push(batch.slice(i * itemReqIndex, (i + 1) * itemReqIndex));\n }\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n results = await (\n await Promise.all(\n reqData.map(async (i) => (await (connection as any)._rpcBatchRequest(i)).map((ii) => ii.result.value)),\n )\n ).flat();\n } else {\n try {\n results = await Promise.all(\n transactions.map(async (transaction) => await (await connection.simulateTransaction(transaction)).value),\n );\n } catch (error) {\n if (error instanceof Error) {\n logger.logWithError(\"failed to get info for multiple accounts\", \"RPC_ERROR\", {\n message: error.message,\n });\n }\n }\n }\n\n return results;\n}\n\nexport function checkLegacyTxSize({\n instructions,\n payer,\n signers,\n}: {\n instructions: TransactionInstruction[];\n payer: PublicKey;\n signers: PublicKey[];\n}): boolean {\n return forecastTransactionSize(instructions, [payer, ...signers]);\n}\n\nexport function checkV0TxSize({\n instructions,\n payer,\n lookupTableAddressAccount,\n recentBlockhash = Keypair.generate().publicKey.toString(),\n}: {\n instructions: TransactionInstruction[];\n payer: PublicKey;\n lookupTableAddressAccount?: CacheLTA;\n recentBlockhash?: string;\n}): boolean {\n const transactionMessage = new TransactionMessage({\n payerKey: payer,\n recentBlockhash,\n instructions,\n });\n\n const messageV0 = transactionMessage.compileToV0Message(Object.values(lookupTableAddressAccount ?? {}));\n try {\n const buildLength = Buffer.from(new VersionedTransaction(messageV0).serialize()).toString(\"base64\").length;\n return buildLength < MAX_BASE64_SIZE;\n } catch (error) {\n return false;\n }\n}\n\nlet epochInfoCache: { time: number; data?: EpochInfo } = {\n time: 0,\n data: undefined,\n};\n\nexport async function getEpochInfo(connection: Connection): Promise<EpochInfo> {\n if (!epochInfoCache.data || (Date.now() - epochInfoCache.time) / 1000 > 30) {\n const data = await connection.getEpochInfo();\n epochInfoCache = {\n time: Date.now(),\n data,\n };\n return data;\n } else {\n return epochInfoCache.data;\n }\n}\n\nexport const toBuffer = (arr: Buffer | Uint8Array | Array<number>): Buffer => {\n if (Buffer.isBuffer(arr)) {\n return arr;\n } else if (arr instanceof Uint8Array) {\n return Buffer.from(arr.buffer, arr.byteOffset, arr.byteLength);\n } else {\n return Buffer.from(arr);\n }\n};\n\nexport const txToBase64 = (transaction: Transaction | VersionedTransaction): string => {\n let serialized = transaction.serialize({ requireAllSignatures: false, verifySignatures: false });\n if (transaction instanceof VersionedTransaction) serialized = toBuffer(serialized);\n try {\n return serialized instanceof Buffer ? serialized.toString(\"base64\") : Buffer.from(serialized).toString(\"base64\");\n } catch {\n return serialized.toString(\"base64\");\n }\n};\n\nexport function printSimulate(transactions: Transaction[] | VersionedTransaction[]): string[] {\n const allBase64: string[] = [];\n transactions.forEach((transaction) => {\n if (transaction instanceof Transaction) {\n if (!transaction.recentBlockhash) transaction.recentBlockhash = TOKEN_PROGRAM_ID.toBase58();\n if (!transaction.feePayer) transaction.feePayer = Keypair.generate().publicKey;\n }\n allBase64.push(txToBase64(transaction));\n });\n console.log(\"simulate tx string:\", allBase64);\n\n return allBase64;\n}\n\nexport function transformTxToBase64(tx: Transaction | VersionedTransaction): string {\n let serialized = tx.serialize({ requireAllSignatures: false, verifySignatures: false });\n if (tx instanceof VersionedTransaction) serialized = toBuffer(serialized);\n return serialized.toString(\"base64\");\n}\n","import { get, set } from \"lodash\";\n\nexport type ModuleName = \"Common.Api\";\n\nexport enum LogLevel {\n Error,\n Warning,\n Info,\n Debug,\n}\nexport class Logger {\n private logLevel: LogLevel;\n private name: string;\n constructor(params: { name: string; logLevel?: LogLevel }) {\n this.logLevel = params.logLevel !== undefined ? params.logLevel : LogLevel.Error;\n this.name = params.name;\n }\n\n set level(logLevel: LogLevel) {\n this.logLevel = logLevel;\n }\n get time(): string {\n return Date.now().toString();\n }\n get moduleName(): string {\n return this.name;\n }\n\n private isLogLevel(level: LogLevel): boolean {\n return level <= this.logLevel;\n }\n\n public error(...props): Logger {\n if (!this.isLogLevel(LogLevel.Error)) return this;\n console.error(this.time, this.name, \"sdk logger error\", ...props);\n return this;\n }\n\n public logWithError(...props): Logger {\n // this.error(...props)\n const msg = props.map((arg) => (typeof arg === \"object\" ? JSON.stringify(arg) : arg)).join(\", \");\n throw new Error(msg);\n }\n\n public warning(...props): Logger {\n if (!this.isLogLevel(LogLevel.Warning)) return this;\n console.warn(this.time, this.name, \"sdk logger warning\", ...props);\n return this;\n }\n\n public info(...props): Logger {\n if (!this.isLogLevel(LogLevel.Info)) return this;\n console.info(this.time, this.name, \"sdk logger info\", ...props);\n return this;\n }\n\n public debug(...props): Logger {\n if (!this.isLogLevel(LogLevel.Debug)) return this;\n console.debug(this.time, this.name, \"sdk logger debug\", ...props);\n return this;\n }\n}\n\nconst moduleLoggers: { [key in ModuleName]?: Logger } = {};\nconst moduleLevels: { [key in ModuleName]?: LogLevel } = {};\n\nexport function createLogger(moduleName: string): Logger {\n let logger = get(moduleLoggers, moduleName);\n if (!logger) {\n // default level is error\n const logLevel = get(moduleLevels, moduleName);\n\n logger = new Logger({ name: moduleName, logLevel });\n set(moduleLoggers, moduleName, logger);\n }\n\n return logger;\n}\n\nexport function setLoggerLevel(moduleName: string, level: LogLevel): void {\n set(moduleLevels, moduleName, level);\n\n const logger = get(moduleLoggers, moduleName);\n if (logger) logger.level = level;\n}\n","import {\n findProgramAddress,\n parseSimulateLogToJson,\n parseSimulateValue,\n simulateMultipleInstruction,\n} from \"@/common/txTool/txUtils\";\nimport { TOKEN_PROGRAM_ID } from \"@solana/spl-token\";\nimport { Connection, PublicKey } from \"@solana/web3.js\";\nimport BN from \"bn.js\";\nimport Decimal from \"decimal.js\";\nimport { AmmV4Keys, AmmV5Keys } from \"../../api/type\";\nimport { toApiV3Token } from \"../token/utils\";\nimport { makeSimulatePoolInfoInstruction } from \"./instruction\";\nimport { getSerumAssociatedAuthority } from \"./serum\";\nimport { StableLayout } from \"./stable\";\nimport { AmmRpcData, ComputeAmountOutParam, LiquidityPoolKeys } from \"./type\";\n\ntype AssociatedName =\n | \"amm_associated_seed\"\n | \"lp_mint_associated_seed\"\n | \"coin_vault_associated_seed\"\n | \"pc_vault_associated_seed\"\n | \"lp_mint_associated_seed\"\n | \"temp_lp_token_associated_seed\"\n | \"open_order_associated_seed\"\n | \"target_associated_seed\"\n | \"withdraw_associated_seed\";\n\ninterface GetAssociatedParam {\n name: AssociatedName;\n programId: PublicKey;\n marketId: PublicKey;\n}\n\nexport function getAssociatedConfigId({ programId }: { programId: PublicKey }): PublicKey {\n const { publicKey } = findProgramAddress([Buffer.from(\"amm_config_account_seed\", \"utf-8\")], programId);\n return publicKey;\n}\n\nexport function getLiquidityAssociatedId({ name, programId, marketId }: GetAssociatedParam): PublicKey {\n const { publicKey } = findProgramAddress(\n [programId.toBuffer(), marketId.toBuffer(), Buffer.from(name, \"utf-8\")],\n programId,\n );\n return publicKey;\n}\n\nexport function getAssociatedOpenOrders({ programId, marketId }: { programId: PublicKey; marketId: PublicKey }) {\n const { publicKey } = findProgramAddress(\n [programId.toBuffer(), marketId.toBuffer(), Buffer.from(\"open_order_associated_seed\", \"utf-8\")],\n programId,\n );\n return publicKey;\n}\n\nexport function getLiquidityAssociatedAuthority({ programId }: { programId: PublicKey }): {\n publicKey: PublicKey;\n nonce: number;\n} {\n return findProgramAddress([Buffer.from([97, 109, 109, 32, 97, 117, 116, 104, 111, 114, 105, 116, 121])], programId);\n}\n\nexport function getAssociatedPoolKeys({\n version,\n marketVersion,\n marketId,\n baseMint,\n quoteMint,\n baseDecimals,\n quoteDecimals,\n programId,\n marketProgramId,\n}: {\n version: 4 | 5;\n marketVersion: 3;\n marketId: PublicKey;\n baseMint: PublicKey;\n quoteMint: PublicKey;\n baseDecimals: number;\n quoteDecimals: number;\n programId: PublicKey;\n marketProgramId: PublicKey;\n}): LiquidityPoolKeys {\n const id = getLiquidityAssociatedId({ name: \"amm_associated_seed\", programId, marketId });\n const lpMint = getLiquidityAssociatedId({ name: \"lp_mint_associated_seed\", programId, marketId });\n const { publicKey: authority, nonce } = getLiquidityAssociatedAuthority({ programId });\n const baseVault = getLiquidityAssociatedId({ name: \"coin_vault_associated_seed\", programId, marketId });\n const quoteVault = getLiquidityAssociatedId({ name: \"pc_vault_associated_seed\", programId, marketId });\n const lpVault = getLiquidityAssociatedId({ name: \"temp_lp_token_associated_seed\", programId, marketId });\n const openOrders = getAssociatedOpenOrders({ programId, marketId });\n const targetOrders = getLiquidityAssociatedId({ name: \"target_associated_seed\", programId, marketId });\n const withdrawQueue = getLiquidityAssociatedId({ name: \"withdraw_associated_seed\", programId, marketId });\n\n const { publicKey: marketAuthority } = getSerumAssociatedAuthority({\n programId: marketProgramId,\n marketId,\n });\n\n return {\n // base\n id,\n baseMint,\n quoteMint,\n lpMint,\n baseDecimals,\n quoteDecimals,\n lpDecimals: baseDecimals,\n // version\n version,\n programId,\n // keys\n authority,\n nonce,\n baseVault,\n quoteVault,\n lpVault,\n openOrders,\n targetOrders,\n withdrawQueue,\n // market version\n marketVersion,\n marketProgramId,\n // market keys\n marketId,\n marketAuthority,\n lookupTableAccount: PublicKey.default,\n configId: getAssociatedConfigId({ programId }),\n };\n}\n\nlet stableLayout: StableLayout | undefined;\n\nexport async function fetchMultipleInfo({\n connection,\n poolKeysList,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n config,\n}: {\n connection: Connection;\n poolKeysList: (AmmV4Keys | AmmV5Keys)[];\n config: any;\n}): Promise<\n {\n status: BN;\n baseDecimals: number;\n quoteDecimals: number;\n lpDecimals: number;\n baseReserve: BN;\n quoteReserve: BN;\n lpSupply: BN;\n startTime: BN;\n }[]\n> {\n if (!stableLayout) {\n stableLayout = new StableLayout({ connection });\n await stableLayout.initStableModelLayout();\n }\n\n const instructions = poolKeysList.map((pool) => makeSimulatePoolInfoInstruction({ poolKeys: pool }));\n const logs = await simulateMultipleInstruction(\n connection,\n instructions.map((i) => i.instruction),\n \"GetPoolData\",\n );\n\n const poolsInfo = logs.map((log) => {\n const json = parseSimulateLogToJson(log, \"GetPoolData\");\n\n const status = new BN(parseSimulateValue(json, \"status\"));\n const baseDecimals = Number(parseSimulateValue(json, \"coin_decimals\"));\n const quoteDecimals = Number(parseSimulateValue(json, \"pc_decimals\"));\n const lpDecimals = Number(parseSimulateValue(json, \"lp_decimals\"));\n const baseReserve = new BN(parseSimulateValue(json, \"pool_coin_amount\"));\n const quoteReserve = new BN(parseSimulateValue(json, \"pool_pc_amount\"));\n const lpSupply = new BN(parseSimulateValue(json, \"pool_lp_supply\"));\n // TODO fix it when split stable\n let startTime = \"0\";\n try {\n startTime = parseSimulateValue(json, \"pool_open_time\");\n } catch (error) {\n //\n }\n\n return {\n status,\n baseDecimals,\n quoteDecimals,\n lpDecimals,\n baseReserve,\n quoteReserve,\n lpSupply,\n startTime: new BN(startTime),\n };\n });\n\n return poolsInfo;\n}\n\nconst mockRewardData = {\n volume: 0,\n volumeQuote: 0,\n volumeFee: 0,\n apr: 0,\n feeApr: 0,\n priceMin: 0,\n priceMax: 0,\n rewardApr: [],\n};\n\nexport const toAmmComputePoolInfo = (\n poolData: Record<string, AmmRpcData>,\n): Record<string, ComputeAmountOutParam[\"poolInfo\"]> => {\n const data: Record<string, ComputeAmountOutParam[\"poolInfo\"]> = {};\n const tokenProgramStr = TOKEN_PROGRAM_ID.toBase58();\n\n Object.keys(poolData).map((poolId) => {\n const poolInfo = poolData[poolId];\n const [mintA, mintB] = [poolInfo.baseMint.toBase58(), poolInfo.quoteMint.toBase58()];\n data[poolId] = {\n id: poolId,\n version: 4,\n status: poolInfo.status.toNumber(),\n programId: poolInfo.programId.toBase58(), // needed\n mintA: toApiV3Token({\n address: mintA, // needed\n programId: tokenProgramStr,\n decimals: poolInfo.baseDecimal.toNumber(),\n }),\n mintB: toApiV3Token({\n address: mintB, // needed\n programId: tokenProgramStr,\n decimals: poolInfo.quoteDecimal.toNumber(),\n }),\n rewardDefaultInfos: [],\n rewardDefaultPoolInfos: \"Ecosystem\",\n price: poolInfo.poolPrice.toNumber(),\n mintAmountA: new Decimal(poolInfo.mintAAmount.toString()).div(10 ** poolInfo.baseDecimal.toNumber()).toNumber(),\n mintAmountB: new Decimal(poolInfo.mintBAmount.toString()).div(10 ** poolInfo.quoteDecimal.toNumber()).toNumber(),\n baseReserve: poolInfo.baseReserve, // needed\n quoteReserve: poolInfo.quoteReserve, // needed\n feeRate: new Decimal(poolInfo.tradeFeeNumerator.toString())\n .div(poolInfo.tradeFeeDenominator.toString())\n .toNumber(),\n openTime: poolInfo.poolOpenTime.toString(),\n tvl: 0,\n day: mockRewardData,\n week: mockRewardData,\n month: mockRewardData,\n pooltype: [],\n farmUpcomingCount: 0,\n farmOngoingCount: 0,\n farmFinishedCount: 0,\n type: \"Standard\",\n marketId: poolInfo.marketId.toBase58(),\n configId: getAssociatedConfigId({ programId: poolInfo.programId }).toBase58(),\n lpPrice: 0,\n lpAmount: 0,\n lpMint: toApiV3Token({\n address: poolInfo.lpMint.toBase58(),\n programId: tokenProgramStr,\n decimals: Math.min(poolInfo.baseDecimal.toNumber(), poolInfo.quoteDecimal.toNumber()),\n }),\n burnPercent: 0,\n };\n });\n return data;\n};\n","/*!\r\n * decimal.js v10.4.3\r\n * An arbitrary-precision Decimal type for JavaScript.\r\n * https://github.com/MikeMcl/decimal.js\r\n * Copyright (c) 2022 Michael Mclaughlin <M8ch88l@gmail.com>\r\n * MIT Licence\r\n */\r\n\r\n\r\n// ----------------------------------- EDITABLE DEFAULTS ------------------------------------ //\r\n\r\n\r\n // The maximum exponent magnitude.\r\n // The limit on the value of `toExpNeg`, `toExpPos`, `minE` and `maxE`.\r\nvar EXP_LIMIT = 9e15, // 0 to 9e15\r\n\r\n // The limit on the value of `precision`, and on the value of the first argument to\r\n // `toDecimalPlaces`, `toExponential`, `toFixed`, `toPrecision` and `toSignificantDigits`.\r\n MAX_DIGITS = 1e9, // 0 to 1e9\r\n\r\n // Base conversion alphabet.\r\n NUMERALS = '0123456789abcdef',\r\n\r\n // The natural logarithm of 10 (1025 digits).\r\n LN10 = '2.3025850929940456840179914546843642076011014886287729760333279009675726096773524802359972050895982983419677840422862486334095254650828067566662873690987816894829072083255546808437998948262331985283935053089653777326288461633662222876982198867465436674744042432743651550489343149393914796194044002221051017141748003688084012647080685567743216228355220114804663715659121373450747856947683463616792101806445070648000277502684916746550586856935673420670581136429224554405758925724208241314695689016758940256776311356919292033376587141660230105703089634572075440370847469940168269282808481184289314848524948644871927809676271275775397027668605952496716674183485704422507197965004714951050492214776567636938662976979522110718264549734772662425709429322582798502585509785265383207606726317164309505995087807523710333101197857547331541421808427543863591778117054309827482385045648019095610299291824318237525357709750539565187697510374970888692180205189339507238539205144634197265287286965110862571492198849978748873771345686209167058',\r\n\r\n // Pi (1025 digits).\r\n PI = '3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632789',\r\n\r\n\r\n // The initial configuration properties of the Decimal constructor.\r\n DEFAULTS = {\r\n\r\n // These values must be integers within the stated ranges (inclusive).\r\n // Most of these values can be changed at run-time using the `Decimal.config` method.\r\n\r\n // The maximum number of significant digits of the result of a calculation or base conversion.\r\n // E.g. `Decimal.config({ precision: 20 });`\r\n precision: 20, // 1 to MAX_DIGITS\r\n\r\n // The rounding mode used when rounding to `precision`.\r\n //\r\n // ROUND_UP 0 Away from zero.\r\n // ROUND_DOWN 1 Towards zero.\r\n // ROUND_CEIL 2 Towards +Infinity.\r\n // ROUND_FLOOR 3 Towards -Infinity.\r\n // ROUND_HALF_UP 4 Towards nearest neighbour. If equidistant, up.\r\n // ROUND_HALF_DOWN 5 Towards nearest neighbour. If equidistant, down.\r\n // ROUND_HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour.\r\n // ROUND_HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity.\r\n // ROUND_HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity.\r\n //\r\n // E.g.\r\n // `Decimal.rounding = 4;`\r\n // `Decimal.rounding = Decimal.ROUND_HALF_UP;`\r\n rounding: 4, // 0 to 8\r\n\r\n // The modulo mode used when calculating the modulus: a mod n.\r\n // The quotient (q = a / n) is calculated according to the corresponding rounding mode.\r\n // The remainder (r) is calculated as: r = a - n * q.\r\n //\r\n // UP 0 The remainder is positive if the dividend is negative, else is negative.\r\n // DOWN 1 The remainder has the same sign as the dividend (JavaScript %).\r\n // FLOOR 3 The remainder has the same sign as the divisor (Python %).\r\n // HALF_EVEN 6 The IEEE 754 remainder function.\r\n // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). Always positive.\r\n //\r\n // Truncated division (1), floored division (3), the IEEE 754 remainder (6), and Euclidian\r\n // division (9) are commonly used for the modulus operation. The other rounding modes can also\r\n // be used, but they may not give useful results.\r\n modulo: 1, // 0 to 9\r\n\r\n // The exponent value at and beneath which `toString` returns exponential notation.\r\n // JavaScript numbers: -7\r\n toExpNeg: -7, // 0 to -EXP_LIMIT\r\n\r\n // The exponent value at and above which `toString` returns exponential notation.\r\n // JavaScript numbers: 21\r\n toExpPos: 21, // 0 to EXP_LIMIT\r\n\r\n // The minimum exponent value, beneath which underflow to zero occurs.\r\n // JavaScript numbers: -324 (5e-324)\r\n minE: -EXP_LIMIT, // -1 to -EXP_LIMIT\r\n\r\n // The maximum exponent value, above which overflow to Infinity occurs.\r\n // JavaScript numbers: 308 (1.7976931348623157e+308)\r\n maxE: EXP_LIMIT, // 1 to EXP_LIMIT\r\n\r\n // Whether to use cryptographically-secure random number generation, if available.\r\n crypto: false // true/false\r\n },\r\n\r\n\r\n// ----------------------------------- END OF EDITABLE DEFAULTS ------------------------------- //\r\n\r\n\r\n inexact, quadrant,\r\n external = true,\r\n\r\n decimalError = '[DecimalError] ',\r\n invalidArgument = decimalError + 'Invalid argument: ',\r\n precisionLimitExceeded = decimalError + 'Precision limit exceeded',\r\n cryptoUnavailable = decimalError + 'crypto unavailable',\r\n tag = '[object Decimal]',\r\n\r\n mathfloor = Math.floor,\r\n mathpow = Math.pow,\r\n\r\n isBinary = /^0b([01]+(\\.[01]*)?|\\.[01]+)(p[+-]?\\d+)?$/i,\r\n isHex = /^0x([0-9a-f]+(\\.[0-9a-f]*)?|\\.[0-9a-f]+)(p[+-]?\\d+)?$/i,\r\n isOctal = /^0o([0-7]+(\\.[0-7]*)?|\\.[0-7]+)(p[+-]?\\d+)?$/i,\r\n isDecimal = /^(\\d+(\\.\\d*)?|\\.\\d+)(e[+-]?\\d+)?$/i,\r\n\r\n BASE = 1e7,\r\n LOG_BASE = 7,\r\n MAX_SAFE_INTEGER = 9007199254740991,\r\n\r\n LN10_PRECISION = LN10.length - 1,\r\n PI_PRECISION = PI.length - 1,\r\n\r\n // Decimal.prototype object\r\n P = { toStringTag: tag };\r\n\r\n\r\n// Decimal prototype methods\r\n\r\n\r\n/*\r\n * absoluteValue abs\r\n * ceil\r\n * clampedTo clamp\r\n * comparedTo cmp\r\n * cosine cos\r\n * cubeRoot cbrt\r\n * decimalPlaces dp\r\n * dividedBy div\r\n * dividedToIntegerBy divToInt\r\n * equals eq\r\n * floor\r\n * greaterThan gt\r\n * greaterThanOrEqualTo gte\r\n * hyperbolicCosine cosh\r\n * hyperbolicSine sinh\r\n * hyperbolicTangent tanh\r\n * inverseCosine acos\r\n * inverseHyperbolicCosine acosh\r\n * inverseHyperbolicSine asinh\r\n * inverseHyperbolicTangent atanh\r\n * inverseSine asin\r\n * inverseTangent atan\r\n * isFinite\r\n * isInteger isInt\r\n * isNaN\r\n * isNegative isNeg\r\n * isPositive isPos\r\n * isZero\r\n * lessThan lt\r\n * lessThanOrEqualTo lte\r\n * logarithm log\r\n * [maximum] [max]\r\n * [minimum] [min]\r\n * minus sub\r\n * modulo mod\r\n * naturalExponential exp\r\n * naturalLogarithm ln\r\n * negated neg\r\n * plus add\r\n * precision sd\r\n * round\r\n * sine sin\r\n * squareRoot sqrt\r\n * tangent tan\r\n * times mul\r\n * toBinary\r\n * toDecimalPlaces toDP\r\n * toExponential\r\n * toFixed\r\n * toFraction\r\n * toHexadecimal toHex\r\n * toNearest\r\n * toNumber\r\n * toOctal\r\n * toPower pow\r\n * toPrecision\r\n * toSignificantDigits toSD\r\n * toString\r\n * truncated trunc\r\n * valueOf toJSON\r\n */\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the absolute value of this Decimal.\r\n *\r\n */\r\nP.absoluteValue = P.abs = function () {\r\n var x = new this.constructor(this);\r\n if (x.s < 0) x.s = 1;\r\n return finalise(x);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the\r\n * direction of positive Infinity.\r\n *\r\n */\r\nP.ceil = function () {\r\n return finalise(new this.constructor(this), this.e + 1, 2);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the value of this Decimal clamped to the range\r\n * delineated by `min` and `max`.\r\n *\r\n * min {number|string|Decimal}\r\n * max {number|string|Decimal}\r\n *\r\n */\r\nP.clampedTo = P.clamp = function (min, max) {\r\n var k,\r\n x = this,\r\n Ctor = x.constructor;\r\n min = new Ctor(min);\r\n max = new Ctor(max);\r\n if (!min.s || !max.s) return new Ctor(NaN);\r\n if (min.gt(max)) throw Error(invalidArgument + max);\r\n k = x.cmp(min);\r\n return k < 0 ? min : x.cmp(max) > 0 ? max : new Ctor(x);\r\n};\r\n\r\n\r\n/*\r\n * Return\r\n * 1 if the value of this Decimal is greater than the value of `y`,\r\n * -1 if the value of this Decimal is less than the value of `y`,\r\n * 0 if they have the same value,\r\n * NaN if the value of either Decimal is NaN.\r\n *\r\n */\r\nP.comparedTo = P.cmp = function (y) {\r\n var i, j, xdL, ydL,\r\n x = this,\r\n xd = x.d,\r\n yd = (y = new x.constructor(y)).d,\r\n xs = x.s,\r\n ys = y.s;\r\n\r\n // Either NaN or ±Infinity?\r\n if (!xd || !yd) {\r\n return !xs || !ys ? NaN : xs !== ys ? xs : xd === yd ? 0 : !xd ^ xs < 0 ? 1 : -1;\r\n }\r\n\r\n // Either zero?\r\n if (!xd[0] || !yd[0]) return xd[0] ? xs : yd[0] ? -ys : 0;\r\n\r\n // Signs differ?\r\n if (xs !== ys) return xs;\r\n\r\n // Compare exponents.\r\n if (x.e !== y.e) return x.e > y.e ^ xs < 0 ? 1 : -1;\r\n\r\n xdL = xd.length;\r\n ydL = yd.length;\r\n\r\n // Compare digit by digit.\r\n for (i = 0, j = xdL < ydL ? xdL : ydL; i < j; ++i) {\r\n if (xd[i] !== yd[i]) return xd[i] > yd[i] ^ xs < 0 ? 1 : -1;\r\n }\r\n\r\n // Compare lengths.\r\n return xdL === ydL ? 0 : xdL > ydL ^ xs < 0 ? 1 : -1;\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the cosine of the value in radians of this Decimal.\r\n *\r\n * Domain: [-Infinity, Infinity]\r\n * Range: [-1, 1]\r\n *\r\n * cos(0) = 1\r\n * cos(-0) = 1\r\n * cos(Infinity) = NaN\r\n * cos(-Infinity) = NaN\r\n * cos(NaN) = NaN\r\n *\r\n */\r\nP.cosine = P.cos = function () {\r\n var pr, rm,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.d) return new Ctor(NaN);\r\n\r\n // cos(0) = cos(-0) = 1\r\n if (!x.d[0]) return new Ctor(1);\r\n\r\n pr = Ctor.precision;\r\n rm = Ctor.rounding;\r\n Ctor.precision = pr + Math.max(x.e, x.sd()) + LOG_BASE;\r\n Ctor.rounding = 1;\r\n\r\n x = cosine(Ctor, toLessThanHalfPi(Ctor, x));\r\n\r\n Ctor.precision = pr;\r\n Ctor.rounding = rm;\r\n\r\n return finalise(quadrant == 2 || quadrant == 3 ? x.neg() : x, pr, rm, true);\r\n};\r\n\r\n\r\n/*\r\n *\r\n * Return a new Decimal whose value is the cube root of the value of this Decimal, rounded to\r\n * `precision` significant digits using rounding mode `rounding`.\r\n *\r\n * cbrt(0) = 0\r\n * cbrt(-0) = -0\r\n * cbrt(1) = 1\r\n * cbrt(-1) = -1\r\n * cbrt(N) = N\r\n * cbrt(-I) = -I\r\n * cbrt(I) = I\r\n *\r\n * Math.cbrt(x) = (x < 0 ? -Math.pow(-x, 1/3) : Math.pow(x, 1/3))\r\n *\r\n */\r\nP.cubeRoot = P.cbrt = function () {\r\n var e, m, n, r, rep, s, sd, t, t3, t3plusx,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.isFinite() || x.isZero()) return new Ctor(x);\r\n external = false;\r\n\r\n // Initial estimate.\r\n s = x.s * mathpow(x.s * x, 1 / 3);\r\n\r\n // Math.cbrt underflow/overflow?\r\n // Pass x to Math.pow as integer, then adjust the exponent of the result.\r\n if (!s || Math.abs(s) == 1 / 0) {\r\n n = digitsToString(x.d);\r\n e = x.e;\r\n\r\n // Adjust n exponent so it is a multiple of 3 away from x exponent.\r\n if (s = (e - n.length + 1) % 3) n += (s == 1 || s == -2 ? '0' : '00');\r\n s = mathpow(n, 1 / 3);\r\n\r\n // Rarely, e may be one less than the result exponent value.\r\n e = mathfloor((e + 1) / 3) - (e % 3 == (e < 0 ? -1 : 2));\r\n\r\n if (s == 1 / 0) {\r\n n = '5e' + e;\r\n } else {\r\n n = s.toExponential();\r\n n = n.slice(0, n.indexOf('e') + 1) + e;\r\n }\r\n\r\n r = new Ctor(n);\r\n r.s = x.s;\r\n } else {\r\n r = new Ctor(s.toString());\r\n }\r\n\r\n sd = (e = Ctor.precision) + 3;\r\n\r\n // Halley's method.\r\n // TODO? Compare Newton's method.\r\n for (;;) {\r\n t = r;\r\n t3 = t.times(t).times(t);\r\n t3plusx = t3.plus(x);\r\n r = divide(t3plusx.plus(x).times(t), t3plusx.plus(t3), sd + 2, 1);\r\n\r\n // TODO? Replace with for-loop and checkRoundingDigits.\r\n if (digitsToString(t.d).slice(0, sd) === (n = digitsToString(r.d)).slice(0, sd)) {\r\n n = n.slice(sd - 3, sd + 1);\r\n\r\n // The 4th rounding digit may be in error by -1 so if the 4 rounding digits are 9999 or 4999\r\n // , i.e. approaching a rounding boundary, continue the iteration.\r\n if (n == '9999' || !rep && n == '4999') {\r\n\r\n // On the first iteration only, check to see if rounding up gives the exact result as the\r\n // nines may infinitely repeat.\r\n if (!rep) {\r\n finalise(t, e + 1, 0);\r\n\r\n if (t.times(t).times(t).eq(x)) {\r\n r = t;\r\n break;\r\n }\r\n }\r\n\r\n sd += 4;\r\n rep = 1;\r\n } else {\r\n\r\n // If the rounding digits are null, 0{0,4} or 50{0,3}, check for an exact result.\r\n // If not, then there are further digits and m will be truthy.\r\n if (!+n || !+n.slice(1) && n.charAt(0) == '5') {\r\n\r\n // Truncate to the first rounding digit.\r\n finalise(r, e + 1, 1);\r\n m = !r.times(r).times(r).eq(x);\r\n }\r\n\r\n break;\r\n }\r\n }\r\n }\r\n\r\n external = true;\r\n\r\n return finalise(r, e, Ctor.rounding, m);\r\n};\r\n\r\n\r\n/*\r\n * Return the number of decimal places of the value of this Decimal.\r\n *\r\n */\r\nP.decimalPlaces = P.dp = function () {\r\n var w,\r\n d = this.d,\r\n n = NaN;\r\n\r\n if (d) {\r\n w = d.length - 1;\r\n n = (w - mathfloor(this.e / LOG_BASE)) * LOG_BASE;\r\n\r\n // Subtract the number of trailing zeros of the last word.\r\n w = d[w];\r\n if (w) for (; w % 10 == 0; w /= 10) n--;\r\n if (n < 0) n = 0;\r\n }\r\n\r\n return n;\r\n};\r\n\r\n\r\n/*\r\n * n / 0 = I\r\n * n / N = N\r\n * n / I = 0\r\n * 0 / n = 0\r\n * 0 / 0 = N\r\n * 0 / N = N\r\n * 0 / I = 0\r\n * N / n = N\r\n * N / 0 = N\r\n * N / N = N\r\n * N / I = N\r\n * I / n = I\r\n * I / 0 = I\r\n * I / N = N\r\n * I / I = N\r\n *\r\n * Return a new Decimal whose value is the value of this Decimal divided by `y`, rounded to\r\n * `precision` significant digits using rounding mode `rounding`.\r\n *\r\n */\r\nP.dividedBy = P.div = function (y) {\r\n return divide(this, new this.constructor(y));\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the integer part of dividing the value of this Decimal\r\n * by the value of `y`, rounded to `precision` significant digits using rounding mode `rounding`.\r\n *\r\n */\r\nP.dividedToIntegerBy = P.divToInt = function (y) {\r\n var x = this,\r\n Ctor = x.constructor;\r\n return finalise(divide(x, new Ctor(y), 0, 1, 1), Ctor.precision, Ctor.rounding);\r\n};\r\n\r\n\r\n/*\r\n * Return true if the value of this Decimal is equal to the value of `y`, otherwise return false.\r\n *\r\n */\r\nP.equals = P.eq = function (y) {\r\n return this.cmp(y) === 0;\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the value of this Decimal rounded to a whole number in the\r\n * direction of negative Infinity.\r\n *\r\n */\r\nP.floor = function () {\r\n return finalise(new this.constructor(this), this.e + 1, 3);\r\n};\r\n\r\n\r\n/*\r\n * Return true if the value of this Decimal is greater than the value of `y`, otherwise return\r\n * false.\r\n *\r\n */\r\nP.greaterThan = P.gt = function (y) {\r\n return this.cmp(y) > 0;\r\n};\r\n\r\n\r\n/*\r\n * Return true if the value of this Decimal is greater than or equal to the value of `y`,\r\n * otherwise return false.\r\n *\r\n */\r\nP.greaterThanOrEqualTo = P.gte = function (y) {\r\n var k = this.cmp(y);\r\n return k == 1 || k === 0;\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the hyperbolic cosine of the value in radians of this\r\n * Decimal.\r\n *\r\n * Domain: [-Infinity, Infinity]\r\n * Range: [1, Infinity]\r\n *\r\n * cosh(x) = 1 + x^2/2! + x^4/4! + x^6/6! + ...\r\n *\r\n * cosh(0) = 1\r\n * cosh(-0) = 1\r\n * cosh(Infinity) = Infinity\r\n * cosh(-Infinity) = Infinity\r\n * cosh(NaN) = NaN\r\n *\r\n * x time taken (ms) result\r\n * 1000 9 9.8503555700852349694e+433\r\n * 10000 25 4.4034091128314607936e+4342\r\n * 100000 171 1.4033316802130615897e+43429\r\n * 1000000 3817 1.5166076984010437725e+434294\r\n * 10000000 abandoned after 2 minute wait\r\n *\r\n * TODO? Compare performance of cosh(x) = 0.5 * (exp(x) + exp(-x))\r\n *\r\n */\r\nP.hyperbolicCosine = P.cosh = function () {\r\n var k, n, pr, rm, len,\r\n x = this,\r\n Ctor = x.constructor,\r\n one = new Ctor(1);\r\n\r\n if (!x.isFinite()) return new Ctor(x.s ? 1 / 0 : NaN);\r\n if (x.isZero()) return one;\r\n\r\n pr = Ctor.precision;\r\n rm = Ctor.rounding;\r\n Ctor.precision = pr + Math.max(x.e, x.sd()) + 4;\r\n Ctor.rounding = 1;\r\n len = x.d.length;\r\n\r\n // Argument reduction: cos(4x) = 1 - 8cos^2(x) + 8cos^4(x) + 1\r\n // i.e. cos(x) = 1 - cos^2(x/4)(8 - 8cos^2(x/4))\r\n\r\n // Estimate the optimum number of times to use the argument reduction.\r\n // TODO? Estimation reused from cosine() and may not be optimal here.\r\n if (len < 32) {\r\n k = Math.ceil(len / 3);\r\n n = (1 / tinyPow(4, k)).toString();\r\n } else {\r\n k = 16;\r\n n = '2.3283064365386962890625e-10';\r\n }\r\n\r\n x = taylorSeries(Ctor, 1, x.times(n), new Ctor(1), true);\r\n\r\n // Reverse argument reduction\r\n var cosh2_x,\r\n i = k,\r\n d8 = new Ctor(8);\r\n for (; i--;) {\r\n cosh2_x = x.times(x);\r\n x = one.minus(cosh2_x.times(d8.minus(cosh2_x.times(d8))));\r\n }\r\n\r\n return finalise(x, Ctor.precision = pr, Ctor.rounding = rm, true);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the hyperbolic sine of the value in radians of this\r\n * Decimal.\r\n *\r\n * Domain: [-Infinity, Infinity]\r\n * Range: [-Infinity, Infinity]\r\n *\r\n * sinh(x) = x + x^3/3! + x^5/5! + x^7/7! + ...\r\n *\r\n * sinh(0) = 0\r\n * sinh(-0) = -0\r\n * sinh(Infinity) = Infinity\r\n * sinh(-Infinity) = -Infinity\r\n * sinh(NaN) = NaN\r\n *\r\n * x time taken (ms)\r\n * 10 2 ms\r\n * 100 5 ms\r\n * 1000 14 ms\r\n * 10000 82 ms\r\n * 100000 886 ms 1.4033316802130615897e+43429\r\n * 200000 2613 ms\r\n * 300000 5407 ms\r\n * 400000 8824 ms\r\n * 500000 13026 ms 8.7080643612718084129e+217146\r\n * 1000000 48543 ms\r\n *\r\n * TODO? Compare performance of sinh(x) = 0.5 * (exp(x) - exp(-x))\r\n *\r\n */\r\nP.hyperbolicSine = P.sinh = function () {\r\n var k, pr, rm, len,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.isFinite() || x.isZero()) return new Ctor(x);\r\n\r\n pr = Ctor.precision;\r\n rm = Ctor.rounding;\r\n Ctor.precision = pr + Math.max(x.e, x.sd()) + 4;\r\n Ctor.rounding = 1;\r\n len = x.d.length;\r\n\r\n if (len < 3) {\r\n x = taylorSeries(Ctor, 2, x, x, true);\r\n } else {\r\n\r\n // Alternative argument reduction: sinh(3x) = sinh(x)(3 + 4sinh^2(x))\r\n // i.e. sinh(x) = sinh(x/3)(3 + 4sinh^2(x/3))\r\n // 3 multiplications and 1 addition\r\n\r\n // Argument reduction: sinh(5x) = sinh(x)(5 + sinh^2(x)(20 + 16sinh^2(x)))\r\n // i.e. sinh(x) = sinh(x/5)(5 + sinh^2(x/5)(20 + 16sinh^2(x/5)))\r\n // 4 multiplications and 2 additions\r\n\r\n // Estimate the optimum number of times to use the argument reduction.\r\n k = 1.4 * Math.sqrt(len);\r\n k = k > 16 ? 16 : k | 0;\r\n\r\n x = x.times(1 / tinyPow(5, k));\r\n x = taylorSeries(Ctor, 2, x, x, true);\r\n\r\n // Reverse argument reduction\r\n var sinh2_x,\r\n d5 = new Ctor(5),\r\n d16 = new Ctor(16),\r\n d20 = new Ctor(20);\r\n for (; k--;) {\r\n sinh2_x = x.times(x);\r\n x = x.times(d5.plus(sinh2_x.times(d16.times(sinh2_x).plus(d20))));\r\n }\r\n }\r\n\r\n Ctor.precision = pr;\r\n Ctor.rounding = rm;\r\n\r\n return finalise(x, pr, rm, true);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the hyperbolic tangent of the value in radians of this\r\n * Decimal.\r\n *\r\n * Domain: [-Infinity, Infinity]\r\n * Range: [-1, 1]\r\n *\r\n * tanh(x) = sinh(x) / cosh(x)\r\n *\r\n * tanh(0) = 0\r\n * tanh(-0) = -0\r\n * tanh(Infinity) = 1\r\n * tanh(-Infinity) = -1\r\n * tanh(NaN) = NaN\r\n *\r\n */\r\nP.hyperbolicTangent = P.tanh = function () {\r\n var pr, rm,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.isFinite()) return new Ctor(x.s);\r\n if (x.isZero()) return new Ctor(x);\r\n\r\n pr = Ctor.precision;\r\n rm = Ctor.rounding;\r\n Ctor.precision = pr + 7;\r\n Ctor.rounding = 1;\r\n\r\n return divide(x.sinh(), x.cosh(), Ctor.precision = pr, Ctor.rounding = rm);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the arccosine (inverse cosine) in radians of the value of\r\n * this Decimal.\r\n *\r\n * Domain: [-1, 1]\r\n * Range: [0, pi]\r\n *\r\n * acos(x) = pi/2 - asin(x)\r\n *\r\n * acos(0) = pi/2\r\n * acos(-0) = pi/2\r\n * acos(1) = 0\r\n * acos(-1) = pi\r\n * acos(1/2) = pi/3\r\n * acos(-1/2) = 2*pi/3\r\n * acos(|x| > 1) = NaN\r\n * acos(NaN) = NaN\r\n *\r\n */\r\nP.inverseCosine = P.acos = function () {\r\n var halfPi,\r\n x = this,\r\n Ctor = x.constructor,\r\n k = x.abs().cmp(1),\r\n pr = Ctor.precision,\r\n rm = Ctor.rounding;\r\n\r\n if (k !== -1) {\r\n return k === 0\r\n // |x| is 1\r\n ? x.isNeg() ? getPi(Ctor, pr, rm) : new Ctor(0)\r\n // |x| > 1 or x is NaN\r\n : new Ctor(NaN);\r\n }\r\n\r\n if (x.isZero()) return getPi(Ctor, pr + 4, rm).times(0.5);\r\n\r\n // TODO? Special case acos(0.5) = pi/3 and acos(-0.5) = 2*pi/3\r\n\r\n Ctor.precision = pr + 6;\r\n Ctor.rounding = 1;\r\n\r\n x = x.asin();\r\n halfPi = getPi(Ctor, pr + 4, rm).times(0.5);\r\n\r\n Ctor.precision = pr;\r\n Ctor.rounding = rm;\r\n\r\n return halfPi.minus(x);\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the inverse of the hyperbolic cosine in radians of the\r\n * value of this Decimal.\r\n *\r\n * Domain: [1, Infinity]\r\n * Range: [0, Infinity]\r\n *\r\n * acosh(x) = ln(x + sqrt(x^2 - 1))\r\n *\r\n * acosh(x < 1) = NaN\r\n * acosh(NaN) = NaN\r\n * acosh(Infinity) = Infinity\r\n * acosh(-Infinity) = NaN\r\n * acosh(0) = NaN\r\n * acosh(-0) = NaN\r\n * acosh(1) = 0\r\n * acosh(-1) = NaN\r\n *\r\n */\r\nP.inverseHyperbolicCosine = P.acosh = function () {\r\n var pr, rm,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (x.lte(1)) return new Ctor(x.eq(1) ? 0 : NaN);\r\n if (!x.isFinite()) return new Ctor(x);\r\n\r\n pr = Ctor.precision;\r\n rm = Ctor.rounding;\r\n Ctor.precision = pr + Math.max(Math.abs(x.e), x.sd()) + 4;\r\n Ctor.rounding = 1;\r\n external = false;\r\n\r\n x = x.times(x).minus(1).sqrt().plus(x);\r\n\r\n external = true;\r\n Ctor.precision = pr;\r\n Ctor.rounding = rm;\r\n\r\n return x.ln();\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the inverse of the hyperbolic sine in radians of the value\r\n * of this Decimal.\r\n *\r\n * Domain: [-Infinity, Infinity]\r\n * Range: [-Infinity, Infinity]\r\n *\r\n * asinh(x) = ln(x + sqrt(x^2 + 1))\r\n *\r\n * asinh(NaN) = NaN\r\n * asinh(Infinity) = Infinity\r\n * asinh(-Infinity) = -Infinity\r\n * asinh(0) = 0\r\n * asinh(-0) = -0\r\n *\r\n */\r\nP.inverseHyperbolicSine = P.asinh = function () {\r\n var pr, rm,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.isFinite() || x.isZero()) return new Ctor(x);\r\n\r\n pr = Ctor.precision;\r\n rm = Ctor.rounding;\r\n Ctor.precision = pr + 2 * Math.max(Math.abs(x.e), x.sd()) + 6;\r\n Ctor.rounding = 1;\r\n external = false;\r\n\r\n x = x.times(x).plus(1).sqrt().plus(x);\r\n\r\n external = true;\r\n Ctor.precision = pr;\r\n Ctor.rounding = rm;\r\n\r\n return x.ln();\r\n};\r\n\r\n\r\n/*\r\n * Return a new Decimal whose value is the inverse of the hyperbolic tangent in radians of the\r\n * value of this Decimal.\r\n *\r\n * Domain: [-1, 1]\r\n * Range: [-Infinity, Infinity]\r\n *\r\n * atanh(x) = 0.5 * ln((1 + x) / (1 - x))\r\n *\r\n * atanh(|x| > 1) = NaN\r\n * atanh(NaN) = NaN\r\n * atanh(Infinity) = NaN\r\n * atanh(-Infinity) = NaN\r\n * atanh(0) = 0\r\n * atanh(-0) = -0\r\n * atanh(1) = Infinity\r\n * atanh(-1) = -Infinity\r\n *\r\n */\r\nP.inverseHyperbolicTangent = P.atanh = function () {\r\n var pr, rm, wpr, xsd,\r\n x = this,\r\n Ctor = x.constructor;\r\n\r\n if (!x.isFinite()) return new Ctor(NaN);\r\n if (x.e >= 0) return new Ctor(x.abs().eq(1) ? x.s / 0 : x.isZero() ? x : NaN);\r\n\r\n pr = Ctor.precision