simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

arithmetic.js (8301B)


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