simple-squiggle

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

nthRoots.js (3388B)


      1 import { factory } from '../../utils/factory.js';
      2 var name = 'nthRoots';
      3 var dependencies = ['config', 'typed', 'divideScalar', 'Complex'];
      4 export var createNthRoots = /* #__PURE__ */factory(name, dependencies, _ref => {
      5   var {
      6     typed,
      7     config,
      8     divideScalar,
      9     Complex
     10   } = _ref;
     11 
     12   /**
     13    * Each function here returns a real multiple of i as a Complex value.
     14    * @param  {number} val
     15    * @return {Complex} val, i*val, -val or -i*val for index 0, 1, 2, 3
     16    */
     17   // This is used to fix float artifacts for zero-valued components.
     18   var _calculateExactResult = [function realPos(val) {
     19     return new Complex(val, 0);
     20   }, function imagPos(val) {
     21     return new Complex(0, val);
     22   }, function realNeg(val) {
     23     return new Complex(-val, 0);
     24   }, function imagNeg(val) {
     25     return new Complex(0, -val);
     26   }];
     27   /**
     28    * Calculate the nth root of a Complex Number a using De Movire's Theorem.
     29    * @param  {Complex} a
     30    * @param  {number} root
     31    * @return {Array} array of n Complex Roots
     32    */
     33 
     34   function _nthComplexRoots(a, root) {
     35     if (root < 0) throw new Error('Root must be greater than zero');
     36     if (root === 0) throw new Error('Root must be non-zero');
     37     if (root % 1 !== 0) throw new Error('Root must be an integer');
     38     if (a === 0 || a.abs() === 0) return [new Complex(0, 0)];
     39     var aIsNumeric = typeof a === 'number';
     40     var offset; // determine the offset (argument of a)/(pi/2)
     41 
     42     if (aIsNumeric || a.re === 0 || a.im === 0) {
     43       if (aIsNumeric) {
     44         offset = 2 * +(a < 0); // numeric value on the real axis
     45       } else if (a.im === 0) {
     46         offset = 2 * +(a.re < 0); // complex value on the real axis
     47       } else {
     48         offset = 2 * +(a.im < 0) + 1; // complex value on the imaginary axis
     49       }
     50     }
     51 
     52     var arg = a.arg();
     53     var abs = a.abs();
     54     var roots = [];
     55     var r = Math.pow(abs, 1 / root);
     56 
     57     for (var k = 0; k < root; k++) {
     58       var halfPiFactor = (offset + 4 * k) / root;
     59       /**
     60        * If (offset + 4*k)/root is an integral multiple of pi/2
     61        * then we can produce a more exact result.
     62        */
     63 
     64       if (halfPiFactor === Math.round(halfPiFactor)) {
     65         roots.push(_calculateExactResult[halfPiFactor % 4](r));
     66         continue;
     67       }
     68 
     69       roots.push(new Complex({
     70         r: r,
     71         phi: (arg + 2 * Math.PI * k) / root
     72       }));
     73     }
     74 
     75     return roots;
     76   }
     77   /**
     78    * Calculate the nth roots of a value.
     79    * An nth root of a positive real number A,
     80    * is a positive real solution of the equation "x^root = A".
     81    * This function returns an array of complex values.
     82    *
     83    * Syntax:
     84    *
     85    *    math.nthRoots(x)
     86    *    math.nthRoots(x, root)
     87    *
     88    * Examples:
     89    *
     90    *    math.nthRoots(1)
     91    *    // returns [
     92    *    //   {re: 1, im: 0},
     93    *    //   {re: -1, im: 0}
     94    *    // ]
     95    *    nthRoots(1, 3)
     96    *    // returns [
     97    *    //   { re: 1, im: 0 },
     98    *    //   { re: -0.4999999999999998, im: 0.8660254037844387 },
     99    *    //   { re: -0.5000000000000004, im: -0.8660254037844385 }
    100    *    ]
    101    *
    102    * See also:
    103    *
    104    *    nthRoot, pow, sqrt
    105    *
    106    * @param {number | BigNumber | Fraction | Complex} x Number to be rounded
    107    * @return {number | BigNumber | Fraction | Complex}            Rounded value
    108    */
    109 
    110 
    111   return typed(name, {
    112     Complex: function Complex(x) {
    113       return _nthComplexRoots(x, 2);
    114     },
    115     'Complex, number': _nthComplexRoots
    116   });
    117 });