Search code examples
scalascalatestscala-breezescalactic

Different Equality[DenseVector] types for different numerical tolerances


I've written a scalactic equality provider for DenseVectors that uses the breeze closeTo method to check if each double in the vector is close enough.

 implicit val vectorEquality: Equality[DenseVector[Double]] = new Equality[DenseVector[Double]] {
    def areEqual(a: DenseVector[Double], b: Any): Boolean = {
      b match {
        case b: DenseVector[Double] => (a.valuesIterator zip b.valuesIterator).forall(p =>
          closeTo(p._1, p._2))
        case _ => false
      }
    }

Is there any way to control the closeness of the closeTo when I use this equality in my test? Sometimes I would like "should be equal" in the test to mean equality to 2 decimal places, and other times I would like a more stringent requirement.


Solution

  • Yes, you can control the closeness since closeTo has a third parameter called tolerance defined in Implicits.

    class RichDouble(x: Double) {
        def closeTo(y: Double, tol: Double=1E-5) = {
          (math.abs(x - y) / (math.abs(x) + math.abs(y) + 1e-10) < tol);
        }
        def isDangerous = x.isNaN || x.isInfinite
    }
    

    Example can be found in a test for Chi Squared distribution

    def paramsClose(p: Double, b: Double) = breeze.numerics.closeTo(p, b, 5E-2)