"use strict";

/**
 * A custom function for computing the (continuous) internal rate of return.
 *
 * @param {Array of numbers} amounts - An array of (positive and negative) transaction amounts.
 * @param {Array of numbers} times - An array of (positive and negative) transaction times.
 * @return {Number} The internal rate of return of the transactions, or "No convergence", or "Bad data".
 */
function JNSIRR(amounts, times) {
  var have_pos = false, have_neg = false, count = amounts.length, result;
  
  for(var i = 0; i < count; i++) {
    if (amounts[i] > 0.0) {
      have_pos = true;
    } else if(amounts[i] < 0.0) {
      have_neg = true;
    }
  }
  
  if (have_neg && have_pos) {
    var u = 0.0, converged = false, iterations = 100, epsilon = 1.0e-8;
  
    for(var i = 0; i < iterations; i++) {
      var pos = 0.0, d_pos = 0.0, neg = 0.0, d_neg = 0.0, delta;
    
      for (var j = 0; j < count; j++) {
        var an_amount = amounts[j], a_time = times[j], tmp = an_amount * Math.exp(u * a_time);
    
        if (an_amount > 0.0) {
          pos += tmp;
          d_pos += tmp * a_time; 
        }
        else {
          neg -= tmp;
          d_neg -= tmp * a_time;
        }
      }
      delta = Math.log(neg / pos) / (d_neg / neg - d_pos / pos);
      u -= delta;
      if (Math.abs(delta) < epsilon) {
        converged = true;
        break;
      }
    }
    result = converged ? -u : 'No convergence';
  } else {
    result = 'Bad data!';
  }
  return result;
}

/* Test Ouput:
   JNSIRR([-1000.0, 500.0, -2000.0, 1500.0, -2000.0, 4000.0], [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]) = 10.16%
*/