float ColorHistogram::KLDivergence(const ColorHistogram& rhs) const {
  DCHECK(IsNormalized() && rhs.IsNormalized());
  const double eps = 1e-10;
  return 0.5 * GenericDistance(rhs, [eps](float a, float b) -> float {
    const double ratio = (a + eps) / (b + eps);
    return a * std::log(ratio) + b * std::log(1.0 / ratio);
  });
}
float ColorHistogram::JSDivergence(const ColorHistogram& rhs) const {
  DCHECK(IsNormalized() && rhs.IsNormalized());
  const double eps = 1e-10;
  return 0.5 * GenericDistance(rhs, [eps](float a, float b) -> float {
    const double inv_mean = 1.0 / ((a + b) * 0.5 + eps);
    const double ratio_a = (a + eps) * inv_mean;
    const double ratio_b = (b + eps) * inv_mean;
    return a * std::log(ratio_a) + b * std::log(ratio_b);
  });
}
float ColorHistogram::ChiSquareDist(const ColorHistogram& rhs) const {
  DCHECK(IsNormalized() && rhs.IsNormalized());
  return 0.5 * GenericDistance(rhs, [](float a, float b) -> float {
    const float add = a + b;
    if (fabs(add) > 1e-12) {
      const float sub = a - b;
      return sub * sub / add;
    } else {
      return 0.0f;
    }
  });
}