Source: br-util/src/br/util/Number.js

'use strict';

/**
 * @module br/util/Number
 */
var StringUtility = require('br/util/StringUtility');

/**
 * @class
 * @alias module:br/util/Number
 * 
 * @classdesc
 * Utility methods for numbers
 */
function NumberUtil() {
}

/**
 * Returns a numeric representation of the sign on the number.
 *
 * @param {Number} n  The number (or a number as a string)
 * @return {int} 1 for positive values, -1 for negative values, or the original value for zero and non-numeric values.
 */
NumberUtil.sgn = function(n) {
	return n > 0 ? 1 : n < 0 ? -1 : n;
};

/**
 * @param {Object} n
 * @return {boolean} true for numbers and their string representations and false for other values including non-numeric
 *  strings, null, Infinity, NaN.
 */
NumberUtil.isNumber = function(n) {
	if (typeof n === 'string') {
		n = n.trim();
	}

	return n != null && n !== '' && n - n === 0;
};

/**
 * Formats the number to the specified number of decimal places.
 *
 * @param {Number} n The number (or a number as a string).
 * @param {Number} dp The number of decimal places.
 * @return {String} The formatted number.
 */
NumberUtil.toFixed = function(n, dp) {
	//return this.isNumber(n) && dp != null ? Number(n).toFixed(dp) : n;
	//Workaround for IE8/7/6 where toFixed returns 0 for (0.5).toFixed(0) and 0.0 for (0.05).toFixed(1)
	if (this.isNumber(n) && dp != null) {
		var sgn = NumberUtil.sgn(n);
		n = sgn * n;
		var nFixed = (Math.round(Math.pow(10, dp)*n)/Math.pow(10, dp)).toFixed(dp);
		return (sgn * nFixed).toFixed(dp);
	}

	return n;
};

/**
 * Formats the number to the specified number of significant figures. This fixes the bugs in the native Number function
 *  of the same name that are prevalent in various browsers. If the number of significant figures is less than one,
 *  then the function has no effect.
 *
 * @param {Number} n The number (or a number as a string).
 * @param {Number} sf The number of significant figures.
 * @return {String} The formatted number.
 */
NumberUtil.toPrecision = function(n, sf) {
	return this.isNumber(n) && sf > 0 ? Number(n).toPrecision(sf) : n;
};

/**
 * Formats the number to the specified number of decimal places, omitting any trailing zeros.
 *
 * @param {Number} n The number (or a number as a string).
 * @param {Number} rounding  The number of decimal places to round.
 * @return {String} The rounded number.
 */
NumberUtil.toRounded = function(n, rounding) {
	//return this.isNumber(n) && rounding != null ? String(Number(Number(n).toFixed(rounding))) : n;
	//Workaround for IE8/7/6 where toFixed returns 0 for (0.5).toFixed(0) and 0.0 for (0.05).toFixed(1)
	if (this.isNumber(n) && rounding != null) {
		var sgn = NumberUtil.sgn(n);
		n = sgn * n;
		var nRounded = (Math.round(Math.pow(10, rounding)*n)/Math.pow(10, rounding)).toFixed(rounding);
		return sgn * nRounded;
	}

	return  n;
};

/**
 * Logarithm to base 10.
 *
 * @param {Number} n The number (or a number as a string).
 * @return {Number} The logarithm to base 10.
 */
NumberUtil.log10 = function(n) {
	return Math.log(n) / Math.LN10;
};

/**
 * Rounds a floating point number
 *
 * @param {Number} n The number (or a number as a string).
 * @return {Number} The formatted number.
 */
NumberUtil.round = function(n) {
	var dp = 13 - (n ? Math.ceil(this.log10(Math.abs(n))) : 0);
	return this.isNumber(n) ? Number(Number(n).toFixed(dp)) : n;
};

/**
 * Pads the integer part of a number with zeros to reach the specified length.
 *
 * @param {Number} value  The number (or a number as a string).
 * @param {Number} numLength  The required length of the number.
 * @return {String} The formatted number.
 */
NumberUtil.pad = function(value, numLength) {
	if (this.isNumber(value)) {
		var nAbsolute = Math.abs(value);
		var sInteger = new String(parseInt(nAbsolute));
		var nSize = numLength || 0;
		var sSgn = value < 0 ? "-" : "";
		value = sSgn + StringUtility.repeat("0", nSize - sInteger.length) + nAbsolute;
	}

	return value;
};

/**
 * Counts the amount of decimal places within a number.
 * Also supports scientific notations
 *
 * @param {Number} n The number (or a number as a string).
 * @return {Number} The number of decimal places
 */
NumberUtil.decimalPlaces = function(n) {
	var match = (''+n).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
	if (!match) {
		return 0;
	}
	return Math.max(
		0,
		// Number of digits right of decimal point.
		(match[1] ? match[1].length : 0)
		// Adjust for scientific notation.
		- (match[2] ? +match[2] : 0));
}

module.exports = NumberUtil;