//
/* == Math == */
if(!Math.sgn) Math.sgn=function(x){return (x==0) ? 0 : ((x>0) ? 1 : -1);}; //Сигнун
if(!Math.part) Math.part=function(x){return x-Math.floor(x);}; //Дробная часть

/* == RegExp == */
RegExp.prototype.superexec=function(text){
	var m,ret;
	if(this.global){
		ret=[];
		while((m=this.exec(text))!=null) ret.push(m);
	}
	else ret=this.exec(text);
	return ret;
};

/* == String == */
String.prototype.ltrim = function(){return this.replace(/^\s+/, '');};
String.prototype.rtrim = function(){return this.replace(/\s+$/, '');};
String.prototype.trim = function(){return this.replace(/^\s+/, '').replace(/\s+$/, '');};
String.prototype.intrim=function(){return this.replace(/(\S)(\s)\s+(\S)/,'$1$2$3');};

String.prototype.supermatch=function(regexp){return regexp.superexec(this);};
String.prototype.superreplace=function(regexp,replacement){
	var ret=this, ret1;
	do{
		ret1=ret;
		ret=ret1.replace(regexp,replacement);
	}while(ret!=ret1);
	return ret;
};

String.prototype.padded=function(mask,right){
	if(right!==false) right=true;
	var pos=mask.length-this.length;
	if(pos<0) return this.valueOf();
	else if(right) return mask.substr(0,pos)+this;
	else return this+mask.substr(this.length);
};

String.prototype.reverse=function(){return this.split('').reverse().join('');};

String.prototype.toArray=function(){return this.split('');};

String.prototype.plug$=function(array,length){
	if(!length)length=2;
	return this.replace(new RegExp('\\$(\\d{1,'+length+'}|\\$)','g'),function(str,index){
		if(index=='$') return str;
		else if(+index in array) return array[+index];
		else return str;
	});
};

String.prototype.multiple=function(len){
	var ret='';
	for(;len>0;len--)ret+=this;
	return ret;
}

/* == Array == */
/*Javascript 1.6*/
if(!Array.prototype.filter) Array.prototype.filter=function(callback,thisobject){
	var ret=[];
	var context=thisobject || window;
	for(var j=0;j<this.length;j++) if(callback.call(context,this[j], j, this)) ret.push(this[j]);
	return ret;
};

if(!Array.prototype.some) Array.prototype.some=function(callback,thisobject){
	var context=thisobject || window;
	for(var j=0;j<this.length;j++) if(callback.call(context,this[j], j, this)) return true;
	return false;
};

if(!Array.prototype.every) Array.prototype.every=function(callback,thisobject){
	var context=thisobject || window;
	for(var j=0;j<this.length;j++) if(!callback.call(context,this[j], j, this)) return false;
	return true;
};

if(!Array.prototype.forEach) Array.prototype.forEach=function(callback,thisobject){
	var context=thisobject || window;
	for(var j=0;j<this.length;j++) callback.call(context,this[j], j, this);
};

if(!Array.prototype.map) Array.prototype.map=function(callback,thisobject){
	var ret=[];
	var context=thisobject || window;
	for(var j=0;j<this.length;j++) ret.push(callback.call(context,this[j], j, this));
	return ret;
};

if (!Array.prototype.indexOf) Array.prototype.indexOf = function(elt, from){
    var len = this.length/* >>> 0*/;

    from = Number(from) || 0;
    from = (from < 0) ? Math.ceil(from) : Math.floor(from);
	if(from < 0) from += len;

    for (; from < len; from++){
		if(from in this && this[from] === elt) return from;
	}
	return -1;
};

if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(elt, from){
    var len = this.length;

    from = Number(from);
    if (isNaN(from)){
      from = len - 1;
    }
    else{
      from = (from < 0) ? Math.ceil(from) : Math.floor(from);
      if (from < 0) from += len;
      else if (from >= len) from = len - 1;
    }

    for (; from > -1; from--) if (from in this && this[from] === elt) return from;
	return -1;
};

/* Другие */
Array.from=function(source){
	//Массив из любой массивоподобной структуры
	if(source.toArray) source=source.toArray();
	return Array.prototype.slice.call(source,0);
}; 

Array.prototype.clone=function(){return [].concat(this);};

Array.prototype.recursiveClone=function(){
	var r=[];
	for(var j=0;j<this.length;j++){
		if(this[j].recursiveClone) r[j]=this[j].recursiveClone();
		else if(this[j].clone) r[j]=this[j].clone();
		else r[j]=this[j];
	}
	return r;
};

Array.prototype.sortNum=function(){this.sort(function(a,b){return a-b;});};

Array.prototype.swap=function(a,b){var m=this[a];this[a]=this[b];this[b]=m;}; //Меняет два элемента местами

Array.prototype.random=function(){
//Перемешивает массив
	for(l=this.length-1;l>0;l--) this.swap(l,Math.round(l*Math.random()));
};

Array.prototype.antiObject=function(){
// Возвращает объект, реализующий обратную функцию массива 
	var r={};
	for(var j=0;j<this.length;j++){
		r[this[j]]=j;
	}
	return r;
};

Array.prototype.recursiveToString=function(){
	var s=[];
	for(var j=0;j<this.length;j++){
		if(this[j] && this[j].recursiveToString) s[j]='['+this[j].recursiveToString()+']';
		else if(this[j] && this[j].toString) s[j]=this[j].toString();
		else s[j]=this[j];
	}
	return s.join(',');
};


Array.prototype.splitStep=function(step){
// Возвращает массив массивов, полученный путём нарезки текущего массива на куски по step элементов
	var ret=[];
	var len=this.length-step;
	for(var j=0;j<len;j+=step) ret.push(this.slice(j,j+step));
	ret.push(this.slice(j));
	return ret;
};

Array.prototype.concatMembers=function(){
// Склеивает массив массивов в единый массив
	var ret=[];
	for(var j=0;j<this.length;j++) ret=ret.concat(this[j]);
	return ret;
};

Array.prototype.transponer=function(){
//Транспонирует двумерный массив, эмулированный с помощью массива массивов
	var ret=[],j,k,n=this[0].length,m=this.length;
	for(j=0;j<n;j++){
		ret[j]=[];
		for(k=0;k<m;k++) ret[j][k]=this[k][j];
	}
	return ret;
};

Array.multimetric=function me(){
	//инициализирует массив массивов, эмулирующий многомерный массив
	switch(arguments.length){
		case 0: return [];
		case 1: return Array(arguments[0]);
		default:
			var ret=Array(arguments[0]);
			var arg=Array.from(arguments);
			arg.shift();
			for(var i=0;i<ret.length;i++){ret[i]=me.apply(this,arg);}
			return ret;
	}
}


Array.prototype.item=function(){
//Получает значение из многомерного массива, эмулированного массивом массивов
//Индексы могут идти как отдельными аргументами так и аргументом строкой (разделённые запятыми) или массивом
//возможна комбинация
	var index=Array.from(arguments).toString().split(',').map(parseInt);
	var p=this;
	for(var j=0;j<index.length;j++) p=p[index[j]];
	return p;
};


Array.prototype.multimap=function(callback,thisobject){
	//Применяет функцию к массиву массивов, принимая каждый элемент в качестве массива аргументов
	var ret=[],n=this[0].length;
	var context=thisobject || window;
	for(var j=0;j<this.length;j++){
		ret.push(callback.apply(context,
			(this[j].length<n ? this[j].concat(Array(n-this[j].length)) : this[j]).concat([j, this])
		));
	}
	return ret;	
};

/* == Function == */
Function.prototype.localName=function(){
	return this.toString().match(/^\s*function(?:\s+([a-z_$][a-z0-9_$]*))?s*\(/i)[1];
};
Function.prototype.isSystem=function(){
	return (/^\s*function(?:\s+(?:[A-Za-z_$][A-Za-z0-9_$]*))?\(\) \{\s*\[native code\]\s*\}\s*$/).test(this.toString());
};

