static inline float IOU(typename TTypes<T, 2>::ConstTensor boxes, int i,
                        int j) {
  const float ymin_i = Eigen::numext::mini<float>(boxes(i, 0), boxes(i, 2));
  const float xmin_i = Eigen::numext::mini<float>(boxes(i, 1), boxes(i, 3));
  const float ymax_i = Eigen::numext::maxi<float>(boxes(i, 0), boxes(i, 2));
  const float xmax_i = Eigen::numext::maxi<float>(boxes(i, 1), boxes(i, 3));
  const float ymin_j = Eigen::numext::mini<float>(boxes(j, 0), boxes(j, 2));
  const float xmin_j = Eigen::numext::mini<float>(boxes(j, 1), boxes(j, 3));
  const float ymax_j = Eigen::numext::maxi<float>(boxes(j, 0), boxes(j, 2));
  const float xmax_j = Eigen::numext::maxi<float>(boxes(j, 1), boxes(j, 3));
  const float area_i = (ymax_i - ymin_i) * (xmax_i - xmin_i);
  const float area_j = (ymax_j - ymin_j) * (xmax_j - xmin_j);
  if (area_i <= 0 || area_j <= 0) {
    return 0.0;
  }
  const float intersection_ymin = Eigen::numext::maxi<float>(ymin_i, ymin_j);
  const float intersection_xmin = Eigen::numext::maxi<float>(xmin_i, xmin_j);
  const float intersection_ymax = Eigen::numext::mini<float>(ymax_i, ymax_j);
  const float intersection_xmax = Eigen::numext::mini<float>(xmax_i, xmax_j);
  const float intersection_area =
      Eigen::numext::maxi<float>(intersection_ymax - intersection_ymin, 0.0) *
      Eigen::numext::maxi<float>(intersection_xmax - intersection_xmin, 0.0);
  return intersection_area / (area_i + area_j - intersection_area);
}
static inline float IOU(typename TTypes<T, 2>::ConstTensor boxes, int i,
                        int j) {
  const float ymin_i = Eigen::numext::mini<float>(boxes(i, 0), boxes(i, 2));
  const float xmin_i = Eigen::numext::mini<float>(boxes(i, 1), boxes(i, 3));
  const float ymax_i = Eigen::numext::maxi<float>(boxes(i, 0), boxes(i, 2));
  const float xmax_i = Eigen::numext::maxi<float>(boxes(i, 1), boxes(i, 3));
  const float ymin_j = Eigen::numext::mini<float>(boxes(j, 0), boxes(j, 2));
  const float xmin_j = Eigen::numext::mini<float>(boxes(j, 1), boxes(j, 3));
  const float ymax_j = Eigen::numext::maxi<float>(boxes(j, 0), boxes(j, 2));
  const float xmax_j = Eigen::numext::maxi<float>(boxes(j, 1), boxes(j, 3));
  const float area_i = (ymax_i - ymin_i) * (xmax_i - xmin_i);
  const float area_j = (ymax_j - ymin_j) * (xmax_j - xmin_j);
  if (area_i <= 0 || area_j <= 0) {
    return 0.0;
  }
  const float intersection_ymin = Eigen::numext::maxi<float>(ymin_i, ymin_j);
  const float intersection_xmin = Eigen::numext::maxi<float>(xmin_i, xmin_j);
  const float intersection_ymax = Eigen::numext::mini<float>(ymax_i, ymax_j);
  const float intersection_xmax = Eigen::numext::mini<float>(xmax_i, xmax_j);
  const float intersection_area =
      Eigen::numext::maxi<float>(intersection_ymax - intersection_ymin, 0.0) *
      Eigen::numext::maxi<float>(intersection_xmax - intersection_xmin, 0.0);
  return intersection_area / (area_i + area_j - intersection_area);
}