/*
 * ====================================================================
 *
 * Copyright (c) 1999-2005 Matias Giovannini.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowledgement:  
 *       "This product includes software developed by 
 *        Matias Giovannini (http://paginar.net/matias/)."
 *    Alternately, this acknowledgement may appear in the software itself,
 *    if and wherever such third-party acknowledgements normally appear.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 */

Math.logp1 = function(x) {
	if (1.0 + x == 1.0)
		return x;
	else
		return Math.log(1.0 + x) * x / ((1.0 + x) - 1.0);
};

Math.sign = function(x) {
	return x < 0 ? -1 : x == 0 ? 0 : x > 0 ? 1 : null;
};

String.prototype.replicate = function(n) {
	var s = this.toString();
	var t = "";
	while (n > 0) {
		if ((n&1) == 1)
			t += s;
		if ( (n >>= 1) != 0 )
			s += s;
	}
	return t;
};

String.prototype.uriDecode = function() {
	var s = this.toString();
	var t = "";
	for (var i = 0; i != s.length; i++) {
		var c = s.charAt(i);
		if (c == '%' && i < s.length - 2) {
			t += String.fromCharCode(parseInt(s.substr(i+1, 2), 16));
			i += 2;
		} else if (c == '+')
			t += " ";
		else
			t += c;
	}
	return t;
};

Number.prototype.num2dec = function(n) {
	var x = parseFloat(this);
	var e = Math.pow(10, n);
	var y = x * e;
	var neg = false;
	if (y < 0) {
		y = -y;
		neg = true;
	}
	x = Math.floor(y);
	if (y - x > 0.5 || y - x == 0.5 && x % 2 > 0)
		x += 1.0;
	var z = Math.floor(x / e).toString();
	if (n > 0) {
		var u = (x % e).toString();
		z += "." + "0".replicate(n - u.length) + u;
	}
	if (neg)
		z = "-"+z;
	return z;
};

Date.prototype.toJulianDay = function() {
	var yr = this.getYear();
	if (yr < 100)
		yr += 1900;
	var mn = this.getMonth() + 1;
	var dy = this.getDate();
	if (mn < 3) {
		mn += 12;
		yr -= 1;
	}
	var jul = 1721118.5;
	jul += 365*yr + Math.floor(yr/4) - Math.floor(yr/100) + Math.floor(yr/400);
	jul += Math.floor(30.6*mn - 91.4);
	jul += dy;
	jul += (this.getHours() + (this.getMinutes() + this.getSeconds()/60)/60)/24;
	return jul;
};

Date.fromJulianDay = function(jul) {
	var r = jul - 1721118.5;
	var z = Math.floor(r);
	r -= z;
	var g = z - 0.25;
	var a = Math.floor(g/36524.25);
	var b = a - Math.floor(a/4);
	var yr = Math.floor((b + g)/365.25);
	var c = b + z - Math.floor(365.25*yr);
	var mn = Math.floor((5*c + 456)/153);
	var dy = c - Math.floor(30.6*mn - 91.4) + r;
	if (mn > 12) { yr += 1; mn -= 12; }
	r = Math.floor(dy);
	var hs = (dy - r) * 24;
	dy = r;
	r = Math.floor(hs);
	var ms = (hs - r) * 60;
	hs = r;
	r = Math.floor(ms);
	var ss = Math.floor((ms - r) * 60 + 0.5);
	ms = r;
	return new Date(yr, mn - 1, dy, hs, ms, ss);
};

if (false && typeof navigator != "undefined") {
	Location.prototype.parseRequest = function() {
		var res = new Object();
		if (this.search.length > 0 && this.search.charAt(0) == '?') {
			var re = /^\&(([^=\&]+)(=([^\&]*))?)(.*)$/;
			var search = "&" + this.search.substr(1);
			while (search && re(search)) {
				res[RegExp.$2.uriDecode()] = RegExp.$4.uriDecode();
				search = RegExp.$5;
			}
		}
		return res;
	};
}

