function sign(e) {
	return e < 0 ? -1 : 1;
}
function slope3(t, n, r) {
	var i = t._x1 - t._x0, a = n - t._x1, o = (t._y1 - t._y0) / (i || a < 0 && -0), s = (r - t._y1) / (a || i < 0 && -0), c = (o * a + s * i) / (i + a);
	return (sign(o) + sign(s)) * Math.min(Math.abs(o), Math.abs(s), .5 * Math.abs(c)) || 0;
}
function slope2(e, t) {
	var n = e._x1 - e._x0;
	return n ? (3 * (e._y1 - e._y0) / n - t) / 2 : t;
}
function point(e, t, n) {
	var r = e._x0, i = e._y0, a = e._x1, o = e._y1, s = (a - r) / 3;
	e._context.bezierCurveTo(r + s, i + s * t, a - s, o - s * n, a, o);
}
function MonotoneX(e) {
	this._context = e;
}
MonotoneX.prototype = {
	areaStart: function() {
		this._line = 0;
	},
	areaEnd: function() {
		this._line = NaN;
	},
	lineStart: function() {
		this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN, this._point = 0;
	},
	lineEnd: function() {
		switch (this._point) {
			case 2:
				this._context.lineTo(this._x1, this._y1);
				break;
			case 3:
				point(this, this._t0, slope2(this, this._t0));
				break;
		}
		(this._line || this._line !== 0 && this._point === 1) && this._context.closePath(), this._line = 1 - this._line;
	},
	point: function(e, i) {
		var a = NaN;
		if (e = +e, i = +i, !(e === this._x1 && i === this._y1)) {
			switch (this._point) {
				case 0:
					this._point = 1, this._line ? this._context.lineTo(e, i) : this._context.moveTo(e, i);
					break;
				case 1:
					this._point = 2;
					break;
				case 2:
					this._point = 3, point(this, slope2(this, a = slope3(this, e, i)), a);
					break;
				default:
					point(this, this._t0, a = slope3(this, e, i));
					break;
			}
			this._x0 = this._x1, this._x1 = e, this._y0 = this._y1, this._y1 = i, this._t0 = a;
		}
	}
};
function MonotoneY(e) {
	this._context = new ReflectContext(e);
}
(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(e, t) {
	MonotoneX.prototype.point.call(this, t, e);
};
function ReflectContext(e) {
	this._context = e;
}
ReflectContext.prototype = {
	moveTo: function(e, t) {
		this._context.moveTo(t, e);
	},
	closePath: function() {
		this._context.closePath();
	},
	lineTo: function(e, t) {
		this._context.lineTo(t, e);
	},
	bezierCurveTo: function(e, t, n, r, i, a) {
		this._context.bezierCurveTo(t, e, r, n, a, i);
	}
};
function monotoneX(e) {
	return new MonotoneX(e);
}
function monotoneY(e) {
	return new MonotoneY(e);
}
export { monotoneX, monotoneY };
