arithmetic.js (7257B)
1 import { isInteger, log2, log10, cbrt, expm1, sign, toFixed, log1p } from '../../utils/number.js'; 2 var n1 = 'number'; 3 var n2 = 'number, number'; 4 export function absNumber(a) { 5 return Math.abs(a); 6 } 7 absNumber.signature = n1; 8 export function addNumber(a, b) { 9 return a + b; 10 } 11 addNumber.signature = n2; 12 export function subtractNumber(a, b) { 13 return a - b; 14 } 15 subtractNumber.signature = n2; 16 export function multiplyNumber(a, b) { 17 return a * b; 18 } 19 multiplyNumber.signature = n2; 20 export function divideNumber(a, b) { 21 return a / b; 22 } 23 divideNumber.signature = n2; 24 export function unaryMinusNumber(x) { 25 return -x; 26 } 27 unaryMinusNumber.signature = n1; 28 export function unaryPlusNumber(x) { 29 return x; 30 } 31 unaryPlusNumber.signature = n1; 32 export function cbrtNumber(x) { 33 return cbrt(x); 34 } 35 cbrtNumber.signature = n1; 36 export function ceilNumber(x) { 37 return Math.ceil(x); 38 } 39 ceilNumber.signature = n1; 40 export function cubeNumber(x) { 41 return x * x * x; 42 } 43 cubeNumber.signature = n1; 44 export function expNumber(x) { 45 return Math.exp(x); 46 } 47 expNumber.signature = n1; 48 export function expm1Number(x) { 49 return expm1(x); 50 } 51 expm1Number.signature = n1; 52 export function fixNumber(x) { 53 return x > 0 ? Math.floor(x) : Math.ceil(x); 54 } 55 fixNumber.signature = n1; 56 export function floorNumber(x) { 57 return Math.floor(x); 58 } 59 floorNumber.signature = n1; 60 /** 61 * Calculate gcd for numbers 62 * @param {number} a 63 * @param {number} b 64 * @returns {number} Returns the greatest common denominator of a and b 65 */ 66 67 export function gcdNumber(a, b) { 68 if (!isInteger(a) || !isInteger(b)) { 69 throw new Error('Parameters in function gcd must be integer numbers'); 70 } // https://en.wikipedia.org/wiki/Euclidean_algorithm 71 72 73 var r; 74 75 while (b !== 0) { 76 r = a % b; 77 a = b; 78 b = r; 79 } 80 81 return a < 0 ? -a : a; 82 } 83 gcdNumber.signature = n2; 84 /** 85 * Calculate lcm for two numbers 86 * @param {number} a 87 * @param {number} b 88 * @returns {number} Returns the least common multiple of a and b 89 */ 90 91 export function lcmNumber(a, b) { 92 if (!isInteger(a) || !isInteger(b)) { 93 throw new Error('Parameters in function lcm must be integer numbers'); 94 } 95 96 if (a === 0 || b === 0) { 97 return 0; 98 } // https://en.wikipedia.org/wiki/Euclidean_algorithm 99 // evaluate lcm here inline to reduce overhead 100 101 102 var t; 103 var prod = a * b; 104 105 while (b !== 0) { 106 t = b; 107 b = a % t; 108 a = t; 109 } 110 111 return Math.abs(prod / a); 112 } 113 lcmNumber.signature = n2; 114 /** 115 * Calculate the logarithm of a value, optionally to a given base. 116 * @param {number} x 117 * @param {number | null | undefined} base 118 * @return {number} 119 */ 120 121 export function logNumber(x, y) { 122 if (y) { 123 return Math.log(x) / Math.log(y); 124 } 125 126 return Math.log(x); 127 } 128 /** 129 * Calculate the 10-base logarithm of a number 130 * @param {number} x 131 * @return {number} 132 */ 133 134 export function log10Number(x) { 135 return log10(x); 136 } 137 log10Number.signature = n1; 138 /** 139 * Calculate the 2-base logarithm of a number 140 * @param {number} x 141 * @return {number} 142 */ 143 144 export function log2Number(x) { 145 return log2(x); 146 } 147 log2Number.signature = n1; 148 /** 149 * Calculate the natural logarithm of a `number+1` 150 * @param {number} x 151 * @returns {number} 152 */ 153 154 export function log1pNumber(x) { 155 return log1p(x); 156 } 157 log1pNumber.signature = n1; 158 /** 159 * Calculate the modulus of two numbers 160 * @param {number} x 161 * @param {number} y 162 * @returns {number} res 163 * @private 164 */ 165 166 export function modNumber(x, y) { 167 if (y > 0) { 168 // We don't use JavaScript's % operator here as this doesn't work 169 // correctly for x < 0 and x === 0 170 // see https://en.wikipedia.org/wiki/Modulo_operation 171 return x - y * Math.floor(x / y); 172 } else if (y === 0) { 173 return x; 174 } else { 175 // y < 0 176 // TODO: implement mod for a negative divisor 177 throw new Error('Cannot calculate mod for a negative divisor'); 178 } 179 } 180 modNumber.signature = n2; 181 /** 182 * Calculate the nth root of a, solve x^root == a 183 * http://rosettacode.org/wiki/Nth_root#JavaScript 184 * @param {number} a 185 * @param {number} root 186 * @private 187 */ 188 189 export function nthRootNumber(a, root) { 190 var inv = root < 0; 191 192 if (inv) { 193 root = -root; 194 } 195 196 if (root === 0) { 197 throw new Error('Root must be non-zero'); 198 } 199 200 if (a < 0 && Math.abs(root) % 2 !== 1) { 201 throw new Error('Root must be odd when a is negative.'); 202 } // edge cases zero and infinity 203 204 205 if (a === 0) { 206 return inv ? Infinity : 0; 207 } 208 209 if (!isFinite(a)) { 210 return inv ? 0 : a; 211 } 212 213 var x = Math.pow(Math.abs(a), 1 / root); // If a < 0, we require that root is an odd integer, 214 // so (-1) ^ (1/root) = -1 215 216 x = a < 0 ? -x : x; 217 return inv ? 1 / x : x; // Very nice algorithm, but fails with nthRoot(-2, 3). 218 // Newton's method has some well-known problems at times: 219 // https://en.wikipedia.org/wiki/Newton%27s_method#Failure_analysis 220 221 /* 222 let x = 1 // Initial guess 223 let xPrev = 1 224 let i = 0 225 const iMax = 10000 226 do { 227 const delta = (a / Math.pow(x, root - 1) - x) / root 228 xPrev = x 229 x = x + delta 230 i++ 231 } 232 while (xPrev !== x && i < iMax) 233 if (xPrev !== x) { 234 throw new Error('Function nthRoot failed to converge') 235 } 236 return inv ? 1 / x : x 237 */ 238 } 239 nthRootNumber.signature = n2; 240 export function signNumber(x) { 241 return sign(x); 242 } 243 signNumber.signature = n1; 244 export function sqrtNumber(x) { 245 return Math.sqrt(x); 246 } 247 sqrtNumber.signature = n1; 248 export function squareNumber(x) { 249 return x * x; 250 } 251 squareNumber.signature = n1; 252 /** 253 * Calculate xgcd for two numbers 254 * @param {number} a 255 * @param {number} b 256 * @return {number} result 257 * @private 258 */ 259 260 export function xgcdNumber(a, b) { 261 // source: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm 262 var t; // used to swap two variables 263 264 var q; // quotient 265 266 var r; // remainder 267 268 var x = 0; 269 var lastx = 1; 270 var y = 1; 271 var lasty = 0; 272 273 if (!isInteger(a) || !isInteger(b)) { 274 throw new Error('Parameters in function xgcd must be integer numbers'); 275 } 276 277 while (b) { 278 q = Math.floor(a / b); 279 r = a - q * b; 280 t = x; 281 x = lastx - q * x; 282 lastx = t; 283 t = y; 284 y = lasty - q * y; 285 lasty = t; 286 a = b; 287 b = r; 288 } 289 290 var res; 291 292 if (a < 0) { 293 res = [-a, -lastx, -lasty]; 294 } else { 295 res = [a, a ? lastx : 0, lasty]; 296 } 297 298 return res; 299 } 300 xgcdNumber.signature = n2; 301 /** 302 * Calculates the power of x to y, x^y, for two numbers. 303 * @param {number} x 304 * @param {number} y 305 * @return {number} res 306 */ 307 308 export function powNumber(x, y) { 309 // x^Infinity === 0 if -1 < x < 1 310 // A real number 0 is returned instead of complex(0) 311 if (x * x < 1 && y === Infinity || x * x > 1 && y === -Infinity) { 312 return 0; 313 } 314 315 return Math.pow(x, y); 316 } 317 powNumber.signature = n2; 318 /** 319 * round a number to the given number of decimals, or to zero if decimals is 320 * not provided 321 * @param {number} value 322 * @param {number} decimals number of decimals, between 0 and 15 (0 by default) 323 * @return {number} roundedValue 324 */ 325 326 export function roundNumber(value) { 327 var decimals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; 328 return parseFloat(toFixed(value, decimals)); 329 } 330 roundNumber.signature = n2; 331 /** 332 * Calculate the norm of a number, the absolute value. 333 * @param {number} x 334 * @return {number} 335 */ 336 337 export function normNumber(x) { 338 return Math.abs(x); 339 } 340 normNumber.signature = n1;