All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalautils.TolerantNumerics.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2001-2013 Artima, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.scalautils

/**
 * Defines a custom way to determine equality for a type.
 *
 * 

* For example, here's how you could define equality between Doubles such that * a tolerance of ± 0.01 is allowed: *

* *
 * class TolerantDoubleEquality extends Equality[Double] {
 *
 *   private val Tol = 0.01
 *
 *   def areEqual(a: Double, b: Any): Boolean = {
 *     b match {
 *       case bDouble: Double => (a <= bDouble + Tol) && (a >= bDouble - Tol)
 *       case _ => false
 *     }
 *   }
 * }
 * 
* *

* If an implicit instance of TolerantDoubleEquality is in scope, it will be * used by ScalaTest's === operators and its should equal and should === matcher * syntax. Here's an example: *

* *
 * $ scala -cp target/jar_contents/
 * Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_33).
 * Type in expressions to have them evaluated.
 * Type :help for more information.

 * scala> import org.scalautils._
 * import org.scalautils._

 * scala> class TolerantDoubleEquality extends Equality[Double] {
 *      | 
 *      |   private val Tol = 0.01
 *      | 
 *      |   def areEqual(a: Double, b: Any): Boolean = {
 *      |     b match {
 *      |       case bDouble: Double => (a >= bDouble + Tol) && (a >= bDouble - Tol)
 *      |       case _ => false
 *      |     }
 *      |   }
 *      | }
 * defined class TolerantDoubleEquality
 *
 * scala> import TripleEquals._
 * import TripleEquals._
 *
 * scala> 2.0 === 2.001
 * res0: Boolean = false
 *
 * scala> implicit val tolerantDoubleEquality = new TolerantDoubleEquality
 * tolerantDoubleEquality: TolerantDoubleEquality = TolerantDoubleEquality@70c13c17
 *
 * scala> 2.0 === 2.001
 * res1: Boolean = true
 * 
* *

* Note: The Equality type class was inspired in part by the Equal type class of the * scalaz project. *

* * @tparam A the type whose equality is being customized */ trait TolerantNumerics { /** * Indicates whether the objects passed as a and b are equal. * * @param a a left-hand-side object being compared with another (right-hand-side one) for equality (e.g., a == b) * @param b a right-hand-side object being compared with another (left-hand-side one) for equality (e.g., a == b) * @return true if the passed objects are "equal," as defined by this Equality instance */ def tolerantDoubleEquality(tolerance: Double): Equality[Double] = { if (tolerance <= 0.0) throw new IllegalArgumentException(tolerance.toString + " passed to tolerantDoubleEquality was zero or negative. Must be a positive non-zero number.") new Equality[Double] { def areEqual(a: Double, b: Any): Boolean = { b match { case bDouble: Double => (a <= bDouble + tolerance) && (a >= bDouble - tolerance) case _ => false } } } } def tolerantFloatEquality(tolerance: Float): Equality[Float] = { if (tolerance <= 0.0f) throw new IllegalArgumentException(tolerance.toString + " passed to tolerantFloatEquality was zero or negative. Must be a positive non-zero number.") new Equality[Float] { def areEqual(a: Float, b: Any): Boolean = { b match { case bFloat: Float => (a <= bFloat + tolerance) && (a >= bFloat - tolerance) case _ => false } } } } def tolerantLongEquality(tolerance: Long): Equality[Long] = { if (tolerance <= 0L) throw new IllegalArgumentException(tolerance.toString + " passed to tolerantLongEquality was zero or negative. Must be a positive non-zero number.") new Equality[Long] { def areEqual(a: Long, b: Any): Boolean = { b match { case bLong: Long => (a <= bLong + tolerance) && (a >= bLong - tolerance) case _ => false } } } } def tolerantIntEquality(tolerance: Int): Equality[Int] = { if (tolerance <= 0) throw new IllegalArgumentException(tolerance.toString + " passed to tolerantIntEquality was zero or negative. Must be a positive non-zero number.") new Equality[Int] { def areEqual(a: Int, b: Any): Boolean = { b match { case bInt: Int => (a <= bInt + tolerance) && (a >= bInt - tolerance) case _ => false } } } } def tolerantShortEquality(tolerance: Short): Equality[Short] = { if (tolerance <= 0) throw new IllegalArgumentException(tolerance.toString + " passed to tolerantShortEquality was zero or negative. Must be a positive non-zero number.") new Equality[Short] { def areEqual(a: Short, b: Any): Boolean = { b match { case bShort: Short => (a <= bShort + tolerance) && (a >= bShort - tolerance) case _ => false } } } } def tolerantByteEquality(tolerance: Byte): Equality[Byte] = { if (tolerance <= 0) throw new IllegalArgumentException(tolerance.toString + " passed to tolerantByteEquality was zero or negative. Must be a positive non-zero number.") new Equality[Byte] { def areEqual(a: Byte, b: Any): Boolean = { b match { case bByte: Byte => (a <= bByte + tolerance) && (a >= bByte - tolerance) case _ => false } } } } def tolerantEquivalence[N : Numeric](tolerance: N): Equivalence[N] = { val numeric = implicitly[Numeric[N]] if (numeric.lt(tolerance, numeric.zero)) throw new IllegalArgumentException(tolerance.toString + " passed to tolerantEquivalence was zero or negative. Must be a positive non-zero number.") new Equivalence[N] { def areEquivalent(a: N, b: N): Boolean = { val bPlusTolerance = numeric.plus(b, tolerance) val bMinusTolerance = numeric.minus(b, tolerance) (numeric.lteq(a, bPlusTolerance)) && (numeric.gteq(a, bMinusTolerance)) } } } } object TolerantNumerics extends TolerantNumerics




© 2015 - 2025 Weber Informatics LLC | Privacy Policy