evdev_hysteresis(const struct device_coords *in,
		 const struct device_coords *center,
		 const struct device_coords *margin)
{
	int dx = in->x - center->x;
	int dy = in->y - center->y;
	int dx2 = dx * dx;
	int dy2 = dy * dy;
	int a = margin->x;
	int b = margin->y;
	double normalized_finger_distance, finger_distance, margin_distance;
	double lag_x, lag_y;
	struct device_coords result;

	if (!a || !b)
		return *in;

	/*
	 * Basic equation for an ellipse of radii a,b:
	 *   x²/a² + y²/b² = 1
	 * But we start by making a scaled ellipse passing through the
	 * relative finger location (dx,dy). So the scale of this ellipse is
	 * the ratio of finger_distance to margin_distance:
	 *   dx²/a² + dy²/b² = normalized_finger_distance²
	 */
	normalized_finger_distance = sqrt((double)dx2 / (a * a) +
					  (double)dy2 / (b * b));

	/* Which means anything less than 1 is within the elliptical margin */
	if (normalized_finger_distance < 1.0)
		return *center;

	finger_distance = sqrt(dx2 + dy2);
	margin_distance = finger_distance / normalized_finger_distance;

	/*
	 * Now calculate the x,y coordinates on the edge of the margin ellipse
	 * where it intersects the finger vector. Shortcut: We achieve this by
	 * finding the point with the same gradient as dy/dx.
	 */
	if (dx) {
		double gradient = (double)dy / dx;
		lag_x = margin_distance / sqrt(gradient * gradient + 1);
		lag_y = sqrt((margin_distance + lag_x) *
			     (margin_distance - lag_x));
	} else {  /* Infinite gradient */
		lag_x = 0.0;
		lag_y = margin_distance;
	}

	/*
	 * 'result' is the centre of an ellipse (radii a,b) which has been
	 * dragged by the finger moving inside it to 'in'. The finger is now
	 * touching the margin ellipse at some point: (±lag_x,±lag_y)
	 */
	result.x = (dx >= 0) ? in->x - lag_x : in->x + lag_x;
	result.y = (dy >= 0) ? in->y - lag_y : in->y + lag_y;
	return result;
}
evdev_hysteresis(const struct device_coords *in,
		 const struct device_coords *center,
		 const struct device_coords *margin)
{
	int dx = in->x - center->x;
	int dy = in->y - center->y;
	int dx2 = dx * dx;
	int dy2 = dy * dy;
	int a = margin->x;
	int b = margin->y;
	double normalized_finger_distance, finger_distance, margin_distance;
	double lag_x, lag_y;
	struct device_coords result;

	if (!a || !b)
		return *in;

	 
	normalized_finger_distance = sqrt((double)dx2 / (a * a) +
					  (double)dy2 / (b * b));

	 
	if (normalized_finger_distance < 1.0)
		return *center;

	finger_distance = sqrt(dx2 + dy2);
	margin_distance = finger_distance / normalized_finger_distance;

	 
	if (dx) {
		double gradient = (double)dy / dx;
		lag_x = margin_distance / sqrt(gradient * gradient + 1);
		lag_y = sqrt((margin_distance + lag_x) *
			     (margin_distance - lag_x));
	} else {   
		lag_x = 0.0;
		lag_y = margin_distance;
	}

	 
	result.x = (dx >= 0) ? in->x - lag_x : in->x + lag_x;
	result.y = (dy >= 0) ? in->y - lag_y : in->y + lag_y;
	return result;
}