<commit_before>'use strict';

var Complex = require('../../type/complex/Complex');
var typed = require('../../core/typed');
var complex = Complex.factory(
  'Complex', {}, '', typed, {on: function(x, y){}}
);

function factory (type, config, load, typed) {
  var nthRoots = typed('nthRoots', {
    'Complex' : function(x) {
      return _nthComplexRoots(x, 2);
    },
    'Complex, number' : _nthComplexRoots,
  });
  nthRoots.toTex = {2: '\\{y : $y^{args[1]} = {${args[0]}}\\}'};
  return nthRoots;
}

/**
 * If val is an integer multiple of a power of i, return that power.
 * @param  {Complex} val
 * @return {number} n where val = abs(val)*i^n or undefined if no n exists
 */
function _onRay(val) {
  var valIsNumeric = typeof(val) === 'number';
  if (!valIsNumeric && !(val.re === 0 || val.im === 0)) { return; }
  if (valIsNumeric) {
    return 2*(+(val < 0));
  }
  if (val.im === 0) {
    return 2*(+(val.re < 0));
  }
  return 2*(+(val.im < 0)) + 1;
}

/**
 * Calculate the nth root of a Complex Number a using De Movire's Theorem.
 * @param  {Complex} a
 * @param  {number} root
 * @return {Array} array of n Complex Roots
 */
function _nthComplexRoots(a, root) {
  if (root < 0) throw new Error('Root must be greater than zero');
  if (root === 0) throw new Error('Root must be non-zero');
  if (root % 1 !== 0) throw new Error('Root must be an integer');
  if (a === 0 || a.abs() === 0) return [complex(0)];
  var arg = a.arg();
  var abs = a.abs();
  var roots = [];
  // This is used to fix float artifacts for zero-valued components.
  var rays = [
    function realPos(val){return complex(val);},
    function imagPos(val){return complex(0, val);},
    function realNeg(val){return complex(-val);},
    function imagNeg(val){return complex(0, -val);}
  ];
  var r = Math.pow(abs, 1/root);
  for(var k = 0; k < root; k++) {
    var ray = (_onRay(a) + 4*k)/root;
    if (ray === Math.round(ray)) {
      roots.push(rays[ray % 4](r));
      continue;
    }
    roots.push(complex({r: r, phi: (arg + 2 * Math.PI * k)/root}));
  }
  return roots;
}

exports.name = 'nthRoots';
exports.factory = factory;<commit_msg>Updated _nthComplexRoots based on feedback.<commit_after>'use strict';

var Complex = require('../../type/complex/Complex');
var typed = require('../../core/typed');
var complex = Complex.factory(
  'Complex', {}, '', typed, {on: function(x, y){}}
);

function factory (type, config, load, typed) {
  var nthRoots = typed('nthRoots', {
    'Complex' : function(x) {
      return _nthComplexRoots(x, 2);
    },
    'Complex, number' : _nthComplexRoots,
  });
  nthRoots.toTex = {2: '\\{y : $y^{args[1]} = {${args[0]}}\\}'};
  return nthRoots;
}

/**
 * Each function here returns a real multiple of i as a Complex value.
 * @param  {number} val
 * @return {Complex} val, i*val, -val or -i*val for index 0, 1, 2, 3
 */
// This is used to fix float artifacts for zero-valued components.
var _calculateExactResult = [
  function realPos(val){return complex(val);},
  function imagPos(val){return complex(0, val);},
  function realNeg(val){return complex(-val);},
  function imagNeg(val){return complex(0, -val);}
];

/**
 * Calculate the nth root of a Complex Number a using De Movire's Theorem.
 * @param  {Complex} a
 * @param  {number} root
 * @return {Array} array of n Complex Roots
 */
function _nthComplexRoots(a, root) {
  if (root < 0) throw new Error('Root must be greater than zero');
  if (root === 0) throw new Error('Root must be non-zero');
  if (root % 1 !== 0) throw new Error('Root must be an integer');
  if (a === 0 || a.abs() === 0) return [complex(0)];
  var aIsNumeric = typeof(a) === 'number';
  var offset = 0;
  // determine the offset (argument of a)/(pi/2)
  if (aIsNumeric || a.re === 0 || a.im === 0) {
    if (aIsNumeric) {
      offset = 2*(+(a < 0)); // numeric value on the real axis
    } else if (a.im === 0) {
      offset = 2*(+(a.re < 0)); // complex value on the real axis
    } else {
      offset = 2*(+(a.im < 0)) + 1; // complex value on the imaginary axis
    }
  }
  var arg = a.arg();
  var abs = a.abs();
  var roots = [];
  var r = Math.pow(abs, 1/root);
  for(var k = 0; k < root; k++) {
    var halfPiFactor = (offset + 4*k)/root;
    /**
     * If (offset + 4*k)/root is an integral multiple of pi/2
     * then we can produce a more exact result.
     */
    if (halfPiFactor === Math.round(halfPiFactor)) {
      roots.push(_calculateExactResult[halfPiFactor % 4](r));
      continue;
    }
    roots.push(complex({r: r, phi: (arg + 2 * Math.PI * k)/root}));
  }
  return roots;
}

exports.name = 'nthRoots';
exports.factory = factory;
{'fraction_non_alphanumeric': 0.18651051832574278, 'fraction_numerical': 0.013879852526566904, 'mean_word_length': 3.151215121512151, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6183222', 'n_tokens_mistral': 1683, 'n_tokens_neox': 1618, 'n_words': 508}