
	function UnitBezier(p1x, p1y, p2x, p2y) {
		var _ub = this;
		// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
		_ub.cx = 3.0 * p1x;
		_ub.bx = 3.0 * (p2x - p1x) - _ub.cx;
		_ub.ax = 1.0 - _ub.cx -_ub.bx;
		 
		_ub.cy = 3.0 * p1y;
		_ub.by = 3.0 * (p2y - p1y) - _ub.cy;
		_ub.ay = 1.0 - _ub.cy - _ub.by;	
	}

	UnitBezier.prototype.sampleCurveX = function(t) {
		var _ub = this;
		// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
		return ((_ub.ax * t + _ub.bx) * t + _ub.cx) * t;
	};

	UnitBezier.prototype.sampleCurveY = function(t) {
		var _ub = this;
		return ((_ub.ay * t + _ub.by) * t + _ub.cy) * t;
	};

	UnitBezier.prototype.sampleCurveDerivativeX = function(t) {
		var _ub = this;
		return (3.0 * _ub.ax * t + 2.0 * _ub.bx) * t + _ub.cx;
	};

	// Given an x value, find a parametric value it came from.
	UnitBezier.prototype.solveCurveX = function(x, epsilon) {
		var _ub = this;
		var t0;
		var t1;
		var t2;
		var x2;
		var d2;
		var i;

		// First try a few iterations of Newton's method -- normally very fast.
		for (t2 = x, i = 0; i < 8; i++) {
			x2 = _ub.sampleCurveX(t2) - x;
			if (Math.abs(x2) < epsilon)
				return t2;
			d2 = _ub.sampleCurveDerivativeX(t2);
			if (Math.abs(d2) < 1e-6)
				break;
			t2 = t2 - x2 / d2;
		}

		// Fall back to the bisection method for reliability.
		t0 = 0.0;
		t1 = 1.0;
		t2 = x;

		if (t2 < t0)
			return t0;
		if (t2 > t1)
			return t1;

		while (t0 < t1) {
			x2 = _ub.sampleCurveX(t2);
			if (Math.abs(x2 - x) < epsilon)
				return t2;
			if (x > x2)
				t0 = t2;
			else
				t1 = t2;
			t2 = (t1 - t0) * 0.5 + t0;
		}

		// Failure.
		return t2;
	};

	UnitBezier.prototype.solve = function(x, epsilon) {
		var _ub = this;
		return _ub.sampleCurveY(this.solveCurveX(x, epsilon));
	};
