Function.extend({
    memoize: function(){
        var args = $A(arguments);
        return ((this.memoized || (this.memoized={}))[args] || (this.memoized[args]=this.apply(this, args)));
    }
});

Fx.Transition = function(transition, params){
	params = params || [];
	if ($type(params) != 'array') params = [params];
	return $extend(transition, {
		easeIn: function(pos){
			return transition.memoize(pos, params);
		},
		easeOut: function(pos){
			return 1 - transition.memoize(1 - pos, params);
		},
		easeInOut: function(pos){
		    var a=function(pos,params,transition){
		        return (pos <= 0.5) ? transition.memoize(2 * pos, params) / 2 : (2 - transition.memoize(2 * (1 - pos), params)) / 2
		    }
		    return a.memoize(pos,params,transition);
		}
	});
};

Fx.Transitions.extend({
 
	/*
	Property: Quad
		displays a quadratic transition. Must be used as Quad.easeIn or Quad.easeOut or Quad.easeInOut
 
	Graph:
		(see Quad.png)
	*/
 
	//auto generated
 
	/*
	Property: Cubic
		displays a cubicular transition. Must be used as Cubic.easeIn or Cubic.easeOut or Cubic.easeInOut
 
	Graph:
		(see Cubic.png)
	*/
 
	//auto generated
 
	/*
	Property: Quart
		displays a quartetic transition. Must be used as Quart.easeIn or Quart.easeOut or Quart.easeInOut
 
	Graph:
		(see Quart.png)
	*/
 
	//auto generated
 
	/*
	Property: Quint
		displays a quintic transition. Must be used as Quint.easeIn or Quint.easeOut or Quint.easeInOut
 
	Graph:
		(see Quint.png)
	*/
 
	//auto generated
 
	/*
	Property: Pow
		Used to generate Quad, Cubic, Quart and Quint.
		By default is p^6.
 
	Graph:
		(see Pow.png)
	*/
 
	Pow: function(p, x){
		return Math.pow.memoize(p, x[0] || 6);
	},
 
	/*
	Property: Expo
		displays a exponential transition. Must be used as Expo.easeIn or Expo.easeOut or Expo.easeInOut
 
	Graph:
		(see Expo.png)
	*/
 
	Expo: function(p){
		return Math.pow.memoize(2, 8 * (p - 1));
	},
 
	/*
	Property: Circ
		displays a circular transition. Must be used as Circ.easeIn or Circ.easeOut or Circ.easeInOut
 
	Graph:
		(see Circ.png)
	*/
 
	Circ: function(p){
		return 1 - Math.sin.memoize(Math.acos.memoize(p));
	},
 
 
	/*
	Property: Sine
		displays a sineousidal transition. Must be used as Sine.easeIn or Sine.easeOut or Sine.easeInOut
 
	Graph:
		(see Sine.png)
	*/
 
	Sine: function(p){
		return 1 - Math.sin.memoize((1 - p) * Math.PI / 2);
	},
 
	/*
	Property: Back
		makes the transition go back, then all forth. Must be used as Back.easeIn or Back.easeOut or Back.easeInOut
 
	Graph:
		(see Back.png)
	*/
 
	Back: function(p, x){
		x = x[0] || 1.618;
		return Math.pow.memoize(p, 2) * ((x + 1) * p - x);
	},
 
	/*
	Property: Bounce
		makes the transition bouncy. Must be used as Bounce.easeIn or Bounce.easeOut or Bounce.easeInOut
 
	Graph:
		(see Bounce.png)
	*/
 
	Bounce: function(p){
		var value;
		for (var a = 0, b = 1; 1; a += b, b /= 2){
			if (p >= (7 - 4 * a) / 11){
				value = - Math.pow.memoize((11 - 6 * a - 11 * p) / 4, 2) + b * b;
				break;
			}
		}
		return value;
	},
 
	/*
	Property: Elastic
		Elastic curve. Must be used as Elastic.easeIn or Elastic.easeOut or Elastic.easeInOut
 
	Graph:
		(see Elastic.png)
	*/
 
	Elastic: function(p, x){
		return Math.pow.memoize(2, 10 * --p) * Math.cos.memoize(20 * p * Math.PI * (x[0] || 1) / 3);
	}
 
});
 
['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
	Fx.Transitions[transition] = new Fx.Transition(function(p){
		return Math.pow.memoize(p, [i + 2]);
	});
 
	/*compatibility*/
	Fx.Transitions.compat(transition);
	/*end compatibility*/
});