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 }