mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-25 15:07:57 +00:00
187 lines
5.0 KiB
JavaScript
187 lines
5.0 KiB
JavaScript
'use strict'
|
|
|
|
import { factory } from '../../utils/factory'
|
|
import { isBigNumber, isComplex, isFraction } from '../../utils/is'
|
|
|
|
import { deepMap } from '../../utils/collection'
|
|
|
|
const name = 'cbrt'
|
|
const dependencies = [
|
|
'config',
|
|
'typed',
|
|
'isNegative',
|
|
'unaryMinus',
|
|
'matrix',
|
|
'type.Complex',
|
|
'type.BigNumber',
|
|
'type.Fraction'
|
|
]
|
|
|
|
export const createCbrt = factory(name, dependencies, ({ config, typed, isNegative, unaryMinus, matrix, type: { Complex, BigNumber, Fraction } }) => {
|
|
/**
|
|
* Calculate the cubic root of a value.
|
|
*
|
|
* For matrices, the function is evaluated element wise.
|
|
*
|
|
* Syntax:
|
|
*
|
|
* math.cbrt(x)
|
|
* math.cbrt(x, allRoots)
|
|
*
|
|
* Examples:
|
|
*
|
|
* math.cbrt(27) // returns 3
|
|
* math.cube(3) // returns 27
|
|
* math.cbrt(-64) // returns -4
|
|
* math.cbrt(math.unit('27 m^3')) // returns Unit 3 m
|
|
* math.cbrt([27, 64, 125]) // returns [3, 4, 5]
|
|
*
|
|
* const x = math.complex('8i')
|
|
* math.cbrt(x) // returns Complex 1.7320508075689 + i
|
|
* math.cbrt(x, true) // returns Matrix [
|
|
* // 1.7320508075689 + i
|
|
* // -1.7320508075689 + i
|
|
* // -2i
|
|
* // ]
|
|
*
|
|
* See also:
|
|
*
|
|
* square, sqrt, cube
|
|
*
|
|
* @param {number | BigNumber | Complex | Unit | Array | Matrix} x
|
|
* Value for which to calculate the cubic root.
|
|
* @param {boolean} [allRoots] Optional, false by default. Only applicable
|
|
* when `x` is a number or complex number. If true, all complex
|
|
* roots are returned, if false (default) the principal root is
|
|
* returned.
|
|
* @return {number | BigNumber | Complex | Unit | Array | Matrix}
|
|
* Returns the cubic root of `x`
|
|
*/
|
|
const cbrt = typed(name, {
|
|
'number': _cbrtNumber,
|
|
// note: signature 'number, boolean' is also supported,
|
|
// created by typed as it knows how to convert number to Complex
|
|
|
|
'Complex': _cbrtComplex,
|
|
|
|
'Complex, boolean': _cbrtComplex,
|
|
|
|
'BigNumber': function (x) {
|
|
return x.cbrt()
|
|
},
|
|
|
|
'Unit': _cbrtUnit,
|
|
|
|
'Array | Matrix': function (x) {
|
|
// deep map collection, skip zeros since cbrt(0) = 0
|
|
return deepMap(x, cbrt, true)
|
|
}
|
|
})
|
|
|
|
/**
|
|
* Calculate the cubic root for a complex number
|
|
* @param {Complex} x
|
|
* @param {boolean} [allRoots] If true, the function will return an array
|
|
* with all three roots. If false or undefined,
|
|
* the principal root is returned.
|
|
* @returns {Complex | Array.<Complex> | Matrix.<Complex>} Returns the cubic root(s) of x
|
|
* @private
|
|
*/
|
|
function _cbrtComplex (x, allRoots) {
|
|
// https://www.wikiwand.com/en/Cube_root#/Complex_numbers
|
|
|
|
const arg3 = x.arg() / 3
|
|
const abs = x.abs()
|
|
|
|
// principal root:
|
|
const principal = new Complex(_cbrtNumber(abs), 0).mul(new Complex(0, arg3).exp())
|
|
|
|
if (allRoots) {
|
|
const all = [
|
|
principal,
|
|
new Complex(_cbrtNumber(abs), 0).mul(new Complex(0, arg3 + Math.PI * 2 / 3).exp()),
|
|
new Complex(_cbrtNumber(abs), 0).mul(new Complex(0, arg3 - Math.PI * 2 / 3).exp())
|
|
]
|
|
|
|
return (config().matrix === 'Array') ? all : matrix(all)
|
|
} else {
|
|
return principal
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate the cubic root for a Unit
|
|
* @param {Unit} x
|
|
* @return {Unit} Returns the cubic root of x
|
|
* @private
|
|
*/
|
|
function _cbrtUnit (x) {
|
|
if (x.value && isComplex(x.value)) {
|
|
let result = x.clone()
|
|
result.value = 1.0
|
|
result = result.pow(1.0 / 3) // Compute the units
|
|
result.value = _cbrtComplex(x.value) // Compute the value
|
|
return result
|
|
} else {
|
|
const negate = isNegative(x.value)
|
|
if (negate) {
|
|
x.value = unaryMinus(x.value)
|
|
}
|
|
|
|
// TODO: create a helper function for this
|
|
let third
|
|
if (isBigNumber(x.value)) {
|
|
third = new BigNumber(1).div(3)
|
|
} else if (isFraction(x.value)) {
|
|
third = new Fraction(1, 3)
|
|
} else {
|
|
third = 1 / 3
|
|
}
|
|
|
|
let result = x.pow(third)
|
|
|
|
if (negate) {
|
|
result.value = unaryMinus(result.value)
|
|
}
|
|
|
|
return result
|
|
}
|
|
}
|
|
|
|
cbrt.toTex = { 1: `\\sqrt[3]{\${args[0]}}` }
|
|
|
|
return cbrt
|
|
})
|
|
|
|
/**
|
|
* Calculate cbrt for a number
|
|
*
|
|
* Code from es6-shim.js:
|
|
* https://github.com/paulmillr/es6-shim/blob/master/es6-shim.js#L1564-L1577
|
|
*
|
|
* @param {number} x
|
|
* @returns {number | Complex} Returns the cubic root of x
|
|
* @private
|
|
*/
|
|
const _cbrtNumber = Math.cbrt || function (x) {
|
|
if (x === 0) {
|
|
return x
|
|
}
|
|
|
|
const negate = x < 0
|
|
let result
|
|
if (negate) {
|
|
x = -x
|
|
}
|
|
|
|
if (isFinite(x)) {
|
|
result = Math.exp(Math.log(x) / 3)
|
|
// from http://en.wikipedia.org/wiki/Cube_root#Numerical_methods
|
|
result = (x / (result * result) + (2 * result)) / 3
|
|
} else {
|
|
result = x
|
|
}
|
|
|
|
return negate ? -result : result
|
|
}
|