/*
 * Copyright (C) 2006 Baron Schwartz <baron at sequent dot org>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, version 2.1.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
 * details.
 *
 * $Revision: 1.3 $
 */

Number.formatFunctions={count:0};Number.prototype.NaN='NaN';Number.prototype.posInfinity='Infinity';Number.prototype.negInfinity='-Infinity';Number.prototype.numberFormat=function(format,context){if(isNaN(this)){return Number.prototype.NaNstring;}
else if(this==+Infinity){return Number.prototype.posInfinity;}
else if(this==-Infinity){return Number.prototype.negInfinity;}
else if(Number.formatFunctions[format]==null){Number.createNewFormat(format);}
return this[Number.formatFunctions[format]](context);}
Number.createNewFormat=function(format){var funcName="format"+Number.formatFunctions.count++;Number.formatFunctions[format]=funcName;var code="Number.prototype."+funcName+" = function(context){\n";var formats=format.split(";");switch(formats.length){case 1:code+=Number.createTerminalFormat(format);break;case 2:code+="return (this < 0) ? this.numberFormat(\""
+String.escape(formats[1])
+"\", 1) : this.numberFormat(\""
+String.escape(formats[0])
+"\", 2);";break;case 3:code+="return (this < 0) ? this.numberFormat(\""
+String.escape(formats[1])
+"\", 1) : ((this == 0) ? this.numberFormat(\""
+String.escape(formats[2])
+"\", 2) : this.numberFormat(\""
+String.escape(formats[0])
+"\", 3));";break;default:code+="throw 'Too many semicolons in format string';";break;}
eval(code+"}");}
Number.createTerminalFormat=function(format){if(format.length>0&&format.search(/[0#?]/)==-1){return"return '"+String.escape(format)+"';\n";}
var code="var val = (context == null) ? new Number(this) : Math.abs(this);\n";var thousands=false;var lodp=format;var rodp="";var ldigits=0;var rdigits=0;var scidigits=0;var scishowsign=false;var sciletter="";m=format.match(/\..*(e)([+-]?)(0+)/i);if(m){sciletter=m[1];scishowsign=(m[2]=="+");scidigits=m[3].length;format=format.replace(/(e)([+-]?)(0+)/i,"");}
var m=format.match(/^([^.]*)\.(.*)$/);if(m){lodp=m[1].replace(/\./g,"");rodp=m[2].replace(/\./g,"");}
if(format.indexOf('%')>=0){code+="val *= 100;\n";}
m=lodp.match(/(,+)(?:$|[^0#?,])/);if(m){code+="val /= "+Math.pow(1000,m[1].length)+"\n;";}
if(lodp.search(/[0#?],[0#?]/)>=0){thousands=true;}
if((m)||thousands){lodp=lodp.replace(/,/g,"");}
m=lodp.match(/0[0#?]*/);if(m){ldigits=m[0].length;}
m=rodp.match(/[0#?]*/);if(m){rdigits=m[0].length;}
if(scidigits>0){code+="var sci = Number.toScientific(val,"
+ldigits+", "+rdigits+", "+scidigits+", "+scishowsign+");\n"
+"var arr = [sci.l, sci.r];\n";}
else{if(format.indexOf('.')<0){code+="val = (val > 0) ? Math.ceil(val) : Math.floor(val);\n";}
code+="var arr = val.round("+rdigits+").toFixed("+rdigits+").split('.');\n";code+="arr[0] = (val < 0 ? '-' : '') + String.leftPad((val < 0 ? arr[0].substring(1) : arr[0]), "
+ldigits+", '0');\n";}
if(thousands){code+="arr[0] = Number.addSeparators(arr[0]);\n";}
code+="arr[0] = Number.injectIntoFormat(arr[0].reverse(), '"
+String.escape(lodp.reverse())+"', true).reverse();\n";if(rdigits>0){code+="arr[1] = Number.injectIntoFormat(arr[1], '"+String.escape(rodp)+"', false);\n";}
if(scidigits>0){code+="arr[1] = arr[1].replace(/(\\d{"+rdigits+"})/, '$1"+sciletter+"' + sci.s);\n";}
return code+"return arr.join('.');\n";}
Number.toScientific=function(val,ldigits,rdigits,scidigits,showsign){var result={l:"",r:"",s:""};var ex="";var before=Math.abs(val).toFixed(ldigits+rdigits+1).trim('0');var after=Math.round(new Number(before.replace(".","").replace(new RegExp("(\\d{"+(ldigits+rdigits)+"})(.*)"),"$1.$2"))).toFixed(0);if(after.length>=ldigits){after=after.substring(0,ldigits)+"."+after.substring(ldigits);}
else{after+='.';}
result.s=(before.indexOf(".")-before.search(/[1-9]/))-after.indexOf(".");if(result.s<0){result.s++;}
result.l=(val<0?'-':'')+String.leftPad(after.substring(0,after.indexOf(".")),ldigits,"0");result.r=after.substring(after.indexOf(".")+1);if(result.s<0){ex="-";}
else if(showsign){ex="+";}
result.s=ex+String.leftPad(Math.abs(result.s).toFixed(0),scidigits,"0");return result;}
Number.prototype.round=function(decimals){if(decimals>0){var m=this.toFixed(decimals+1).match(new RegExp("(-?\\d*)\.(\\d{"+decimals+"})(\\d)\\d*$"));if(m&&m.length){return new Number(m[1]+"."+String.leftPad(Math.round(m[2]+"."+m[3]),decimals,"0"));}}
return this;}
Number.injectIntoFormat=function(val,format,stuffExtras){var i=0;var j=0;var result="";var revneg=val.charAt(val.length-1)=='-';if(revneg){val=val.substring(0,val.length-1);}
while(i<format.length&&j<val.length&&format.substring(i).search(/[0#?]/)>=0){if(format.charAt(i).match(/[0#?]/)){if(val.charAt(j)!='-'){result+=val.charAt(j);}
else{result+="0";}
j++;}
else{result+=format.charAt(i);}
++i;}
if(revneg&&j==val.length){result+='-';}
if(j<val.length){if(stuffExtras){result+=val.substring(j);}
if(revneg){result+='-';}}
if(i<format.length){result+=format.substring(i);}
return result.replace(/#/g,"").replace(/\?/g," ");}
Number.addSeparators=function(val){return val.reverse().replace(/(\d{3})/g,"$1,").reverse().replace(/^(-)?,/,"$1");}
String.prototype.reverse=function(){var res="";for(var i=this.length;i>0;--i){res+=this.charAt(i-1);}
return res;}
String.prototype.trim=function(ch){if(!ch)ch=' ';return this.replace(new RegExp("^"+ch+"+|"+ch+"+$","g"),"");}
String.leftPad=function(val,size,ch){var result=new String(val);if(ch==null){ch=" ";}
while(result.length<size){result=ch+result;}
return result;}
String.escape=function(string){return string.replace(/('|\\)/g,"\\$1");}
