View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  package org.apache.commons.geometry.core.precision;
    18
    19  import java.io.Serializable;
    20
    21  import org.apache.commons.numbers.core.Precision;
    22
    23  /** Simple {@link DoublePrecisionContext} subclass that uses an absolute epsilon value to
    24   * determine equality between doubles.
    25   *
    26   * <p>This class uses the {@link Precision#compareTo(double, double, double)} method to compare
    27   * numbers. Two values are considered equal if there is no floating point
    28   * value strictly between them or if their numerical difference is less than or equal
    29   * to the configured epsilon value.</p>
    30   *
    31   * @see Precision#compareTo(double, double, double)
    32   */
    33  public class EpsilonDoublePrecisionContext extends DoublePrecisionContext implements Serializable {
    34      private static final long serialVersionUID = 1L;
    35
    36      /** Epsilon value. */
    37      private final double epsilon;
    38
    39      /** Simple constructor.
    40       * @param eps Epsilon value. Numbers are considered equal if there is no
    41       *      floating point value strictly between them or if their difference is less
    42       *      than or equal to this value.
    43       * @throws IllegalArgumentException if the given epsilon value is infinite, NaN, or negative
    44       */
    45      public EpsilonDoublePrecisionContext(final double eps) {
    46          if (!Double.isFinite(eps) || eps < 0.0) {
    47              throw new IllegalArgumentException("Invalid epsilon value: " + eps);
    48          }
    49          this.epsilon = eps;
    50      }
    51
    52      /** Get the epsilon value for the instance. Numbers are considered equal if there
    53       * is no floating point value strictly between them or if their difference is less
    54       * than or equal to this value.
    55       * @return the epsilon value for the instance
    56       */
    57      public double getEpsilon() {
    58          return epsilon;
    59      }
    60
    61      /** {@inheritDoc}
    62       * This value is equal to the epsilon value for the instance.
    63       * @see #getEpsilon()
    64       */
    65      @Override
    66      public double getMaxZero() {
    67          return getEpsilon();
    68      }
    69
    70      /** {@inheritDoc} **/
    71      @Override
    72      public int compare(final double a, final double b) {
    73          return Precision.compareTo(a, b, epsilon);
    74      }
    75
    76      /** {@inheritDoc} **/
    77      @Override
    78      public int hashCode() {
    79          int result = 31;
    80          result += 17 * Double.hashCode(epsilon);
    81
    82          return result;
    83      }
    84
    85      /** {@inheritDoc} **/
    86      @Override
    87      public boolean equals(final Object obj) {
    88          if (this == obj) {
    89              return true;
    90          }
    91          if (!(obj instanceof EpsilonDoublePrecisionContext)) {
    92              return false;
    93          }
    94
    95          final EpsilonDoublePrecisionContext other = (EpsilonDoublePrecisionContext) obj;
    96
    97          return Double.compare(this.epsilon, other.epsilon) == 0;
    98      }
    99
    100     /** {@inheritDoc} **/
    101     @Override
    102     public String toString() {
    103         final StringBuilder sb = new StringBuilder();
    104         sb.append(this.getClass().getSimpleName())
    105             .append("[")
    106             .append("epsilon= ")
    107             .append(epsilon)
    108             .append("]");
    109
    110         return sb.toString();
    111     }
    112 }