Problem: Airports often use moving walkways to help you walking big distances faster. Each such walkway has some speed that effectively increases your speed. You can stand on such a walkway and let it move you, or you could also walk and then your effective speed is your walking speed plus walkway's speed.

Limak wants to get from point 0 to point L on a straight line. There are n disjoint walkways in between. The i-th walkway is described by two integers x_i and y_i and a real value s_i. The i-th walkway starts at x_i, ends at y_i and has speed s_i. 

Every walkway is located inside the segment [0, L] and no two walkways have positive intersection. However, they can touch by endpoints.

Limak needs to decide how to distribute his energy. For example, it might make more sense to stand somewhere (or to walk slowly) to then have a lot of energy to walk faster.

Limak's initial energy is 0 and it must never drop below that value. At any moment, he can walk with any speed v in the interval [0, 2] and it will cost him v energy per second, but he continuously recovers energy with speed of 1 energy per second. So, when he walks with speed v, his energy increases by (1-v). Note that negative value would mean losing energy.

In particular, he can walk with speed 1 and this won't change his energy at all, while walking with speed 0.77 effectively gives him 0.23 energy per second.

Limak can choose his speed arbitrarily (any real value in interval [0, 2]) at every moment of time (including the moments when he is located on non-integer positions). Everything is continuous (non-discrete).

What is the fastest time Limak can get from 0 to L?

Input

The first line contains integers n and L (1 ≤ n ≤ 200 000, 1 ≤ L ≤ 10^9), the number of walkways and the distance to walk.

Each of the next n lines contains integers x_i, y_i and real value s_i (0 ≤ x_i < y_i ≤ L, 0.1 ≤ s_i ≤ 10.0). The value s_i is given with at most 9 digits after decimal point.

It's guaranteed, that no two walkways have a positive intersection. The walkways are listed from left to right. That is, y_i ≤ x_{i + 1} for 1 ≤ i ≤ n - 1.

Output

Print one real value, the fastest possible time to reach L. Your answer will be considered correct if its absolute or relative error won't exceed 10^{-9}.

Examples

Input


1 5
0 2 2.0


Output


3.000000000000


Input


1 5
2 4 0.91


Output


3.808900523560


Input


3 1000
0 990 1.777777
995 996 1.123456789
996 1000 2.0


Output


361.568848429553

Note

The drawings show the first two examples. In the first one, there is a walkway from 0 to 2 with speed 2.0 and Limak wants to get to point 5. The second example has a walkway from 2 to 4 with speed 0.91.

<image>

In the first example, one of optimal strategies is as follows.

  * Get from 0 to 2 by standing still on the walkway. It moves you with speed 2 so it takes 1 second and you save up 1 energy. 
  * Get from 2 to 4 by walking with max speed 2 for next 1 second. It takes 1 second again and the energy drops to 0. 
  * Get from 4 to 5 by walking with speed 1. It takes 1 second and the energy stays constant at the value 0. 



The total time is 1 + 1 + 1 = 3.

Solution (in JAVA):

Solution:
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.SortedSet;
import java.util.Set;
import java.util.NavigableSet;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeSet;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.util.Comparator;
import java.util.Collections;
import java.io.InputStream;
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskH solver = new TaskH();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskH {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int len = in.nextInt();
            int[] x = new int[n];
            int[] y = new int[n];
            double[] s = new double[n];
            for (int i = 0; i < n; ++i) {
                x[i] = in.nextInt();
                y[i] = in.nextInt();
                s[i] = in.nextDouble();
            }
            List<TaskH.Segment> segments = new ArrayList<>();
            int pos = 0;
            for (int i = 0; i < n; ++i) {
                if (x[i] > pos) {
                    segments.add(new TaskH.Segment(pos, x[i], 0.0));
                }
                segments.add(new TaskH.Segment(x[i], y[i], s[i]));
                pos = y[i];
            }
            if (pos < len) {
                segments.add(new TaskH.Segment(pos, len, 0.0));
            }
            out.println(solveOne(segments));
        }

        private double solveOne(List<TaskH.Segment> segments) {
            int n = segments.size();
            for (int i = 0; i < n; ++i) {
                TaskH.Segment s = segments.get(i);
                s.ptr = i;
                s.curEnergy = 0.0;
                s.maxEnergy = (s.right - s.left) / s.s;
                s.minEnergy = -(s.right - s.left) / (s.s + 2);
            }
            List<TaskH.Segment> segmentsByS = new ArrayList<>(segments);
            Collections.sort(segmentsByS, new Comparator<TaskH.Segment>() {

                public int compare(TaskH.Segment o1, TaskH.Segment o2) {
                    int z = Double.compare(o2.s, o1.s);
                    if (z == 0) {
                        z = Integer.compare(o2.left, o1.left);
                    }
                    return z;
                }
            });
            TreeSet<TaskH.Segment> available = new TreeSet<>(new Comparator<TaskH.Segment>() {

                public int compare(TaskH.Segment o1, TaskH.Segment o2) {
                    return o1.ptr - o2.ptr;
                }
            });
            available.addAll(segments);
            for (TaskH.Segment s : segmentsByS) {
                if (s.s == 0.0) break;
                s.alive = false;
                available.remove(s);
                NavigableSet<TaskH.Segment> after = available.tailSet(s, false);
                double capacity = s.maxEnergy - s.curEnergy;
                double spent = 0.0;
                while (!after.isEmpty()) {
                    TaskH.Segment t = after.first();
                    if (t.alive) {
                        double t1 = t.curEnergy - t.minEnergy;
                        double t2 = capacity - spent;
                        double transfer = Math.min(t1, t2);
                        spent += transfer;
                        t.curEnergy -= transfer;
                        if (t1 <= t2) {
                            available.remove(t);
                        } else {
                            break;
                        }
                    }
                }
                s.curEnergy += spent;
            }
            double res = 0.0;
            for (TaskH.Segment s : segments) {
                double v = (s.right - s.left - s.curEnergy * s.s) / (s.right - s.left + s.curEnergy);
                res += (s.right - s.left) / (s.s + v);
            }
            return res;
        }

        static class Segment {
            int left;
            int right;
            int ptr;
            double s;
            boolean alive = true;
            double minEnergy;
            double curEnergy;
            double maxEnergy;

            public Segment(int left, int right, double s) {
                this.left = left;
                this.right = right;
                this.s = s;
            }

        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

    }
}