I'm migrating some old Java code to Scala which uses a "precision" threshold for comparing real values. A fragment of the already translated to Scala code would be:
object CompareDouble {
private val EPSILON = 0.00001
def equals(a: Double, b: Double): Boolean = a == b || Math.abs(a - b) < EPSILON
def greater(a: Double, b: Double): Boolean = a - b > EPSILON
.
.
.
}
The problem with this code is that it's usage gets easily verbose, for instance:
//In an interval overlap comparison
CompareDouble.lessEquals(low1, low2) && CompareDouble.lessEquals(low2, up1) ||
CompareDouble.lessEquals(low1, up2) && CompareDouble.lessEquals(up2, up1) ||
CompareDouble.lessEquals(low2, low1) && CompareDouble.lessEquals(low1, up2) ||
CompareDouble.lessEquals(low2, up1) && CompareDouble.lessEquals(up1, up2)
So I was trying to define some sort of wrapper class for the value that would allow me to use the standard operators. The idea is to be able to do:
//Just an example of the idea
if a == b then...
else if a > b then...
Where a == b
would be the original def equals(a: Double, b: Double):
and so on
So far, I've done this:
class PrecisionDouble(var wrapp: Double) {
// PrecissionDouble.EPSILON refers to a field in this class' companion object
def == (that: PrecisionDouble): Boolean = wrapp == that.wrapp || Math.abs(wrapp - that.wrapp) < PrecisionDouble.EPSILON
def < (that: PrecisionDouble): Boolean = (that.wrapp - wrapp) > PrecisionDouble.EPSILON
which works for the comparison use case, but I must manually wrapp and unwrapp the value within the class for other usages (such as math functions or basic aritmethics). I would like to achieve this:
val a = PrecisionDouble(3.2)
val b: Double = math.sqrt(a)
and also be able to replace the type of the parameters in the PrecisionDouble comparison methods from def == (that: PrecisionDouble)
to def == (that: Double)
to be able to do the comparisons even less verbosely.
Is this somehow possible?
Edit: Scala 3.2
This is how to add new comparison operators in Scala 3:
extension (d: Double)
def === (other: Double) = CompareDouble.equals(d, other)
def >> (other: Double) = CompareDouble.greater(d, other)
You can use CrossVersion.for2_13Use3
in sbt
if you need to use this in a Scala 2 project.