// Arup Guha
// 11/22/2018
// Solution to 2018 SER D1 Problem: Troop Mobilization

import java.util.*;
import java.io.*;

public class troop {
	
	public static int n;
	public static int money;
	public static pt[] pts;
	
	public static void main(String[] args) throws Exception {
		
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		n = Integer.parseInt(tok.nextToken());
		money = Integer.parseInt(tok.nextToken());
		
		// Allocate space for two extra points to "anchor" my convex hull.
		pts = new pt[n+2];
		
		// Will store result here.
		double res = 0;
		
		// Read in their n points - scale everything my a multiplicative factor of money.
		for (int i=0; i<n; i++) {
			tok = new StringTokenizer(stdin.readLine());
			int cost = Integer.parseInt(tok.nextToken());
			double health = money*Double.parseDouble(tok.nextToken())/cost;
			double potency = money*Double.parseDouble(tok.nextToken())/cost;
			pts[i] = new pt(health, potency);
			
			// May as well update now based on just getting all of one troop.
			res = Math.max(res, health*potency);
		}
		
		// Extra points that make sure a proper polygon is formed.
		pts[n] = new pt(-1, -2);
		pts[n+1] = new pt(-2, -1);
		
		// Need to set this for Graham Scan.
		int refIndex = getIndexMin(pts);
		pt.refX = pts[refIndex].x;
		pt.refY = pts[refIndex].y;
		
		// Get the convex hull of these points.
		Stack<pt> mys = grahamScan(pts);
		
		// First reference point.
		pt prev = mys.pop();
		
		// Go through hull.
		while (mys.size() > 0) {
			
			// Need to find first meaningful point (x and y must be different) to compare to.
			pt cur = mys.peek();
			while (mys.size() > 0 && (cur.equalX(prev) || cur.equalY(prev))) {
				mys.pop();
				cur = mys.peek();
			}
			
			// Try the best combination of these two points.
			res = Math.max(res, combine(prev, cur));	
			
			// Get next prev.
			prev = mys.pop();
		}
		
		// Ta da!
		System.out.printf("%.2f\n", res);
				
	}
	
	// Only call if a.x != b.x and a.y !+ b.y
	public static double combine(pt a, pt b) {
		
		// Set up the quadratic to solve for c, where c is the proportion of
		// troop a. In this scenario we have c*a.x +(1-c)*b.x health
		// and c*a.y +(1-c)*b.y potency. When we multiply these we get:
		// (c*dx + b.x)(c*dy + b.y). We take the derivative to solve
		// for the maximum value of c. If this is in between 0 and 1, then
		// a combination of troops is best, otherwise, all of 1 or the other.
		double dy = a.y-b.y;
		double dx = a.x-b.x;
		double c = (-b.x*dy - b.y*dx)/(2*dx*dy);
		
		// Best result is using all of one point or the other.
		if (c < 0 || c > 1) return 0;
		
		// This is the evaluation of the function at c.
		return (c*a.x + (1-c)*b.x)*(c*a.y+(1-c)*b.y);
	}
	
	// Returns the point in pts with minimum y breaking tie by minimum x.
	public static int getIndexMin(pt[] pts) {
		int res = 0;
		for (int i=1; i<pts.length; i++)
			if (pts[i].y < pts[res].y || (pts[i].y == pts[res].y && pts[i].x < pts[res].x))
				res = i;
		return res;
	}

	public static Stack<pt> grahamScan(pt[] pts) {

		// Sort the points by angle with reference point.
		Arrays.sort(pts);

		// Push first two points on.
		Stack<pt> myStack = new Stack<pt>();
		myStack.push(pts[0]);
		myStack.push(pts[1]);

		// Go through the rest of the points.
		for (int i=2; i<pts.length; i++) {

			// Get last three pts.
			pt cur = pts[i];
			pt mid = myStack.pop();
			pt prev = myStack.pop();

			// Pop off the left turns.
			while (!prev.isRightTurn(mid, cur)) {
				mid = prev;
				prev = myStack.pop();
			}

			// Push back the last right turn.
			myStack.push(prev);
			myStack.push(mid);
			myStack.push(cur);
		}

		// Return.
		return myStack;
	}	

}

class pt implements Comparable<pt> {

	// Stores reference pt
	public static double refX;
	public static double refY;

	public double x;
	public double y;

	public pt(double myx, double myy) {
		x = myx;
		y = myy;
	}
	
	public boolean equalX(pt other) {
		return Math.abs(this.x - other.x) < 1e-9;
	}
	
	public boolean equalY(pt other) {
		return Math.abs(this.y - other.y) < 1e-9;
	}	

	// Returns the vector from this to other.
	public pt getVect(pt other) {
		return new pt(other.x-x, other.y-y);
	}

	// Returns the distance between this and other.
	public double dist(pt other) {
		return Math.sqrt((other.x-x)*(other.x-x) + (other.y-y)*(other.y-y));
	}

	// Returns the magnitude ot this cross product other.
	public double crossProductMag(pt other) {
		return this.x*other.y - other.x*this.y;
	}

	// returns true iff this to mid to next is a right turn (180 degree is considered right turn).
	public boolean isRightTurn(pt mid, pt next) {
		pt v1 = getVect(mid);
		pt v2 = mid.getVect(next);
		return v1.crossProductMag(v2) > 1e-9; // Skips collinear points.
	}

	// Returns true iff this pt is the origin.
	public boolean isZero() {
		return x == 0 && y == 0;
	}

	public int compareTo(pt other) {

		pt myRef = new pt(refX, refY);
		pt v1 = myRef.getVect(this);
		pt v2 = myRef.getVect(other);

		// To avoid 0 issues.
		if (v1.isZero()) return -1;
		if (v2.isZero()) return 1;

		// Angles are different, we are going counter-clockwise here.
		if (v1.crossProductMag(v2) != 0)
			return -v1.crossProductMag(v2) < 0 ? -1 : 1;

		// This should work, smaller vectors come first.
		if (myRef.dist(v1) < myRef.dist(v2)) return -1;
		return 1;
	}
}
