source: src/main/java/agents/anac/y2019/harddealer/math3/util/Precision.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 24.1 KB
Line 
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
18package agents.anac.y2019.harddealer.math3.util;
19
20import java.math.BigDecimal;
21
22import agents.anac.y2019.harddealer.math3.exception.MathArithmeticException;
23import agents.anac.y2019.harddealer.math3.exception.MathIllegalArgumentException;
24import agents.anac.y2019.harddealer.math3.exception.util.LocalizedFormats;
25
26/**
27 * Utilities for comparing numbers.
28 *
29 * @since 3.0
30 */
31public class Precision {
32 /**
33 * <p>
34 * Largest double-precision floating-point number such that
35 * {@code 1 + EPSILON} is numerically equal to 1. This value is an upper
36 * bound on the relative error due to rounding real numbers to double
37 * precision floating-point numbers.
38 * </p>
39 * <p>
40 * In IEEE 754 arithmetic, this is 2<sup>-53</sup>.
41 * </p>
42 *
43 * @see <a href="http://en.wikipedia.org/wiki/Machine_epsilon">Machine epsilon</a>
44 */
45 public static final double EPSILON;
46
47 /**
48 * Safe minimum, such that {@code 1 / SAFE_MIN} does not overflow.
49 * <br/>
50 * In IEEE 754 arithmetic, this is also the smallest normalized
51 * number 2<sup>-1022</sup>.
52 */
53 public static final double SAFE_MIN;
54
55 /** Exponent offset in IEEE754 representation. */
56 private static final long EXPONENT_OFFSET = 1023l;
57
58 /** Offset to order signed double numbers lexicographically. */
59 private static final long SGN_MASK = 0x8000000000000000L;
60 /** Offset to order signed double numbers lexicographically. */
61 private static final int SGN_MASK_FLOAT = 0x80000000;
62 /** Positive zero. */
63 private static final double POSITIVE_ZERO = 0d;
64 /** Positive zero bits. */
65 private static final long POSITIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(+0.0);
66 /** Negative zero bits. */
67 private static final long NEGATIVE_ZERO_DOUBLE_BITS = Double.doubleToRawLongBits(-0.0);
68 /** Positive zero bits. */
69 private static final int POSITIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(+0.0f);
70 /** Negative zero bits. */
71 private static final int NEGATIVE_ZERO_FLOAT_BITS = Float.floatToRawIntBits(-0.0f);
72
73 static {
74 /*
75 * This was previously expressed as = 0x1.0p-53;
76 * However, OpenJDK (Sparc Solaris) cannot handle such small
77 * constants: MATH-721
78 */
79 EPSILON = Double.longBitsToDouble((EXPONENT_OFFSET - 53l) << 52);
80
81 /*
82 * This was previously expressed as = 0x1.0p-1022;
83 * However, OpenJDK (Sparc Solaris) cannot handle such small
84 * constants: MATH-721
85 */
86 SAFE_MIN = Double.longBitsToDouble((EXPONENT_OFFSET - 1022l) << 52);
87 }
88
89 /**
90 * Private constructor.
91 */
92 private Precision() {}
93
94 /**
95 * Compares two numbers given some amount of allowed error.
96 *
97 * @param x the first number
98 * @param y the second number
99 * @param eps the amount of error to allow when checking for equality
100 * @return <ul><li>0 if {@link #equals(double, double, double) equals(x, y, eps)}</li>
101 * <li>&lt; 0 if !{@link #equals(double, double, double) equals(x, y, eps)} &amp;&amp; x &lt; y</li>
102 * <li>> 0 if !{@link #equals(double, double, double) equals(x, y, eps)} &amp;&amp; x > y or
103 * either argument is NaN</li></ul>
104 */
105 public static int compareTo(double x, double y, double eps) {
106 if (equals(x, y, eps)) {
107 return 0;
108 } else if (x < y) {
109 return -1;
110 }
111 return 1;
112 }
113
114 /**
115 * Compares two numbers given some amount of allowed error.
116 * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
117 * (or fewer) floating point numbers between them, i.e. two adjacent floating
118 * point numbers are considered equal.
119 * Adapted from <a
120 * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
121 * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN.
122 *
123 * @param x first value
124 * @param y second value
125 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
126 * values between {@code x} and {@code y}.
127 * @return <ul><li>0 if {@link #equals(double, double, int) equals(x, y, maxUlps)}</li>
128 * <li>&lt; 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} &amp;&amp; x &lt; y</li>
129 * <li>&gt; 0 if !{@link #equals(double, double, int) equals(x, y, maxUlps)} &amp;&amp; x > y
130 * or either argument is NaN</li></ul>
131 */
132 public static int compareTo(final double x, final double y, final int maxUlps) {
133 if (equals(x, y, maxUlps)) {
134 return 0;
135 } else if (x < y) {
136 return -1;
137 }
138 return 1;
139 }
140
141 /**
142 * Returns true iff they are equal as defined by
143 * {@link #equals(float,float,int) equals(x, y, 1)}.
144 *
145 * @param x first value
146 * @param y second value
147 * @return {@code true} if the values are equal.
148 */
149 public static boolean equals(float x, float y) {
150 return equals(x, y, 1);
151 }
152
153 /**
154 * Returns true if both arguments are NaN or they are
155 * equal as defined by {@link #equals(float,float) equals(x, y, 1)}.
156 *
157 * @param x first value
158 * @param y second value
159 * @return {@code true} if the values are equal or both are NaN.
160 * @since 2.2
161 */
162 public static boolean equalsIncludingNaN(float x, float y) {
163 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1);
164 }
165
166 /**
167 * Returns true if the arguments are equal or within the range of allowed
168 * error (inclusive). Returns {@code false} if either of the arguments
169 * is NaN.
170 *
171 * @param x first value
172 * @param y second value
173 * @param eps the amount of absolute error to allow.
174 * @return {@code true} if the values are equal or within range of each other.
175 * @since 2.2
176 */
177 public static boolean equals(float x, float y, float eps) {
178 return equals(x, y, 1) || FastMath.abs(y - x) <= eps;
179 }
180
181 /**
182 * Returns true if the arguments are both NaN, are equal, or are within the range
183 * of allowed error (inclusive).
184 *
185 * @param x first value
186 * @param y second value
187 * @param eps the amount of absolute error to allow.
188 * @return {@code true} if the values are equal or within range of each other,
189 * or both are NaN.
190 * @since 2.2
191 */
192 public static boolean equalsIncludingNaN(float x, float y, float eps) {
193 return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps);
194 }
195
196 /**
197 * Returns true if the arguments are equal or within the range of allowed
198 * error (inclusive).
199 * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
200 * (or fewer) floating point numbers between them, i.e. two adjacent floating
201 * point numbers are considered equal.
202 * Adapted from <a
203 * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
204 * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN.
205 *
206 * @param x first value
207 * @param y second value
208 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
209 * values between {@code x} and {@code y}.
210 * @return {@code true} if there are fewer than {@code maxUlps} floating
211 * point values between {@code x} and {@code y}.
212 * @since 2.2
213 */
214 public static boolean equals(final float x, final float y, final int maxUlps) {
215
216 final int xInt = Float.floatToRawIntBits(x);
217 final int yInt = Float.floatToRawIntBits(y);
218
219 final boolean isEqual;
220 if (((xInt ^ yInt) & SGN_MASK_FLOAT) == 0) {
221 // number have same sign, there is no risk of overflow
222 isEqual = FastMath.abs(xInt - yInt) <= maxUlps;
223 } else {
224 // number have opposite signs, take care of overflow
225 final int deltaPlus;
226 final int deltaMinus;
227 if (xInt < yInt) {
228 deltaPlus = yInt - POSITIVE_ZERO_FLOAT_BITS;
229 deltaMinus = xInt - NEGATIVE_ZERO_FLOAT_BITS;
230 } else {
231 deltaPlus = xInt - POSITIVE_ZERO_FLOAT_BITS;
232 deltaMinus = yInt - NEGATIVE_ZERO_FLOAT_BITS;
233 }
234
235 if (deltaPlus > maxUlps) {
236 isEqual = false;
237 } else {
238 isEqual = deltaMinus <= (maxUlps - deltaPlus);
239 }
240
241 }
242
243 return isEqual && !Float.isNaN(x) && !Float.isNaN(y);
244
245 }
246
247 /**
248 * Returns true if the arguments are both NaN or if they are equal as defined
249 * by {@link #equals(float,float,int) equals(x, y, maxUlps)}.
250 *
251 * @param x first value
252 * @param y second value
253 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
254 * values between {@code x} and {@code y}.
255 * @return {@code true} if both arguments are NaN or if there are less than
256 * {@code maxUlps} floating point values between {@code x} and {@code y}.
257 * @since 2.2
258 */
259 public static boolean equalsIncludingNaN(float x, float y, int maxUlps) {
260 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps);
261 }
262
263 /**
264 * Returns true iff they are equal as defined by
265 * {@link #equals(double,double,int) equals(x, y, 1)}.
266 *
267 * @param x first value
268 * @param y second value
269 * @return {@code true} if the values are equal.
270 */
271 public static boolean equals(double x, double y) {
272 return equals(x, y, 1);
273 }
274
275 /**
276 * Returns true if the arguments are both NaN or they are
277 * equal as defined by {@link #equals(double,double) equals(x, y, 1)}.
278 *
279 * @param x first value
280 * @param y second value
281 * @return {@code true} if the values are equal or both are NaN.
282 * @since 2.2
283 */
284 public static boolean equalsIncludingNaN(double x, double y) {
285 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, 1);
286 }
287
288 /**
289 * Returns {@code true} if there is no double value strictly between the
290 * arguments or the difference between them is within the range of allowed
291 * error (inclusive). Returns {@code false} if either of the arguments
292 * is NaN.
293 *
294 * @param x First value.
295 * @param y Second value.
296 * @param eps Amount of allowed absolute error.
297 * @return {@code true} if the values are two adjacent floating point
298 * numbers or they are within range of each other.
299 */
300 public static boolean equals(double x, double y, double eps) {
301 return equals(x, y, 1) || FastMath.abs(y - x) <= eps;
302 }
303
304 /**
305 * Returns {@code true} if there is no double value strictly between the
306 * arguments or the relative difference between them is less than or equal
307 * to the given tolerance. Returns {@code false} if either of the arguments
308 * is NaN.
309 *
310 * @param x First value.
311 * @param y Second value.
312 * @param eps Amount of allowed relative error.
313 * @return {@code true} if the values are two adjacent floating point
314 * numbers or they are within range of each other.
315 * @since 3.1
316 */
317 public static boolean equalsWithRelativeTolerance(double x, double y, double eps) {
318 if (equals(x, y, 1)) {
319 return true;
320 }
321
322 final double absoluteMax = FastMath.max(FastMath.abs(x), FastMath.abs(y));
323 final double relativeDifference = FastMath.abs((x - y) / absoluteMax);
324
325 return relativeDifference <= eps;
326 }
327
328 /**
329 * Returns true if the arguments are both NaN, are equal or are within the range
330 * of allowed error (inclusive).
331 *
332 * @param x first value
333 * @param y second value
334 * @param eps the amount of absolute error to allow.
335 * @return {@code true} if the values are equal or within range of each other,
336 * or both are NaN.
337 * @since 2.2
338 */
339 public static boolean equalsIncludingNaN(double x, double y, double eps) {
340 return equalsIncludingNaN(x, y) || (FastMath.abs(y - x) <= eps);
341 }
342
343 /**
344 * Returns true if the arguments are equal or within the range of allowed
345 * error (inclusive).
346 * <p>
347 * Two float numbers are considered equal if there are {@code (maxUlps - 1)}
348 * (or fewer) floating point numbers between them, i.e. two adjacent
349 * floating point numbers are considered equal.
350 * </p>
351 * <p>
352 * Adapted from <a
353 * href="http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/">
354 * Bruce Dawson</a>. Returns {@code false} if either of the arguments is NaN.
355 * </p>
356 *
357 * @param x first value
358 * @param y second value
359 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
360 * values between {@code x} and {@code y}.
361 * @return {@code true} if there are fewer than {@code maxUlps} floating
362 * point values between {@code x} and {@code y}.
363 */
364 public static boolean equals(final double x, final double y, final int maxUlps) {
365
366 final long xInt = Double.doubleToRawLongBits(x);
367 final long yInt = Double.doubleToRawLongBits(y);
368
369 final boolean isEqual;
370 if (((xInt ^ yInt) & SGN_MASK) == 0l) {
371 // number have same sign, there is no risk of overflow
372 isEqual = FastMath.abs(xInt - yInt) <= maxUlps;
373 } else {
374 // number have opposite signs, take care of overflow
375 final long deltaPlus;
376 final long deltaMinus;
377 if (xInt < yInt) {
378 deltaPlus = yInt - POSITIVE_ZERO_DOUBLE_BITS;
379 deltaMinus = xInt - NEGATIVE_ZERO_DOUBLE_BITS;
380 } else {
381 deltaPlus = xInt - POSITIVE_ZERO_DOUBLE_BITS;
382 deltaMinus = yInt - NEGATIVE_ZERO_DOUBLE_BITS;
383 }
384
385 if (deltaPlus > maxUlps) {
386 isEqual = false;
387 } else {
388 isEqual = deltaMinus <= (maxUlps - deltaPlus);
389 }
390
391 }
392
393 return isEqual && !Double.isNaN(x) && !Double.isNaN(y);
394
395 }
396
397 /**
398 * Returns true if both arguments are NaN or if they are equal as defined
399 * by {@link #equals(double,double,int) equals(x, y, maxUlps)}.
400 *
401 * @param x first value
402 * @param y second value
403 * @param maxUlps {@code (maxUlps - 1)} is the number of floating point
404 * values between {@code x} and {@code y}.
405 * @return {@code true} if both arguments are NaN or if there are less than
406 * {@code maxUlps} floating point values between {@code x} and {@code y}.
407 * @since 2.2
408 */
409 public static boolean equalsIncludingNaN(double x, double y, int maxUlps) {
410 return (x != x || y != y) ? !(x != x ^ y != y) : equals(x, y, maxUlps);
411 }
412
413 /**
414 * Rounds the given value to the specified number of decimal places.
415 * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method.
416 *
417 * @param x Value to round.
418 * @param scale Number of digits to the right of the decimal point.
419 * @return the rounded value.
420 * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0)
421 */
422 public static double round(double x, int scale) {
423 return round(x, scale, BigDecimal.ROUND_HALF_UP);
424 }
425
426 /**
427 * Rounds the given value to the specified number of decimal places.
428 * The value is rounded using the given method which is any method defined
429 * in {@link BigDecimal}.
430 * If {@code x} is infinite or {@code NaN}, then the value of {@code x} is
431 * returned unchanged, regardless of the other parameters.
432 *
433 * @param x Value to round.
434 * @param scale Number of digits to the right of the decimal point.
435 * @param roundingMethod Rounding method as defined in {@link BigDecimal}.
436 * @return the rounded value.
437 * @throws ArithmeticException if {@code roundingMethod == ROUND_UNNECESSARY}
438 * and the specified scaling operation would require rounding.
439 * @throws IllegalArgumentException if {@code roundingMethod} does not
440 * represent a valid rounding mode.
441 * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0)
442 */
443 public static double round(double x, int scale, int roundingMethod) {
444 try {
445 final double rounded = (new BigDecimal(Double.toString(x))
446 .setScale(scale, roundingMethod))
447 .doubleValue();
448 // MATH-1089: negative values rounded to zero should result in negative zero
449 return rounded == POSITIVE_ZERO ? POSITIVE_ZERO * x : rounded;
450 } catch (NumberFormatException ex) {
451 if (Double.isInfinite(x)) {
452 return x;
453 } else {
454 return Double.NaN;
455 }
456 }
457 }
458
459 /**
460 * Rounds the given value to the specified number of decimal places.
461 * The value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method.
462 *
463 * @param x Value to round.
464 * @param scale Number of digits to the right of the decimal point.
465 * @return the rounded value.
466 * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0)
467 */
468 public static float round(float x, int scale) {
469 return round(x, scale, BigDecimal.ROUND_HALF_UP);
470 }
471
472 /**
473 * Rounds the given value to the specified number of decimal places.
474 * The value is rounded using the given method which is any method defined
475 * in {@link BigDecimal}.
476 *
477 * @param x Value to round.
478 * @param scale Number of digits to the right of the decimal point.
479 * @param roundingMethod Rounding method as defined in {@link BigDecimal}.
480 * @return the rounded value.
481 * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0)
482 * @throws MathArithmeticException if an exact operation is required but result is not exact
483 * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method.
484 */
485 public static float round(float x, int scale, int roundingMethod)
486 throws MathArithmeticException, MathIllegalArgumentException {
487 final float sign = FastMath.copySign(1f, x);
488 final float factor = (float) FastMath.pow(10.0f, scale) * sign;
489 return (float) roundUnscaled(x * factor, sign, roundingMethod) / factor;
490 }
491
492 /**
493 * Rounds the given non-negative value to the "nearest" integer. Nearest is
494 * determined by the rounding method specified. Rounding methods are defined
495 * in {@link BigDecimal}.
496 *
497 * @param unscaled Value to round.
498 * @param sign Sign of the original, scaled value.
499 * @param roundingMethod Rounding method, as defined in {@link BigDecimal}.
500 * @return the rounded value.
501 * @throws MathArithmeticException if an exact operation is required but result is not exact
502 * @throws MathIllegalArgumentException if {@code roundingMethod} is not a valid rounding method.
503 * @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0)
504 */
505 private static double roundUnscaled(double unscaled,
506 double sign,
507 int roundingMethod)
508 throws MathArithmeticException, MathIllegalArgumentException {
509 switch (roundingMethod) {
510 case BigDecimal.ROUND_CEILING :
511 if (sign == -1) {
512 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY));
513 } else {
514 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY));
515 }
516 break;
517 case BigDecimal.ROUND_DOWN :
518 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY));
519 break;
520 case BigDecimal.ROUND_FLOOR :
521 if (sign == -1) {
522 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY));
523 } else {
524 unscaled = FastMath.floor(FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY));
525 }
526 break;
527 case BigDecimal.ROUND_HALF_DOWN : {
528 unscaled = FastMath.nextAfter(unscaled, Double.NEGATIVE_INFINITY);
529 double fraction = unscaled - FastMath.floor(unscaled);
530 if (fraction > 0.5) {
531 unscaled = FastMath.ceil(unscaled);
532 } else {
533 unscaled = FastMath.floor(unscaled);
534 }
535 break;
536 }
537 case BigDecimal.ROUND_HALF_EVEN : {
538 double fraction = unscaled - FastMath.floor(unscaled);
539 if (fraction > 0.5) {
540 unscaled = FastMath.ceil(unscaled);
541 } else if (fraction < 0.5) {
542 unscaled = FastMath.floor(unscaled);
543 } else {
544 // The following equality test is intentional and needed for rounding purposes
545 if (FastMath.floor(unscaled) / 2.0 == FastMath.floor(FastMath.floor(unscaled) / 2.0)) { // even
546 unscaled = FastMath.floor(unscaled);
547 } else { // odd
548 unscaled = FastMath.ceil(unscaled);
549 }
550 }
551 break;
552 }
553 case BigDecimal.ROUND_HALF_UP : {
554 unscaled = FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY);
555 double fraction = unscaled - FastMath.floor(unscaled);
556 if (fraction >= 0.5) {
557 unscaled = FastMath.ceil(unscaled);
558 } else {
559 unscaled = FastMath.floor(unscaled);
560 }
561 break;
562 }
563 case BigDecimal.ROUND_UNNECESSARY :
564 if (unscaled != FastMath.floor(unscaled)) {
565 throw new MathArithmeticException();
566 }
567 break;
568 case BigDecimal.ROUND_UP :
569 // do not round if the discarded fraction is equal to zero
570 if (unscaled != FastMath.floor(unscaled)) {
571 unscaled = FastMath.ceil(FastMath.nextAfter(unscaled, Double.POSITIVE_INFINITY));
572 }
573 break;
574 default :
575 throw new MathIllegalArgumentException(LocalizedFormats.INVALID_ROUNDING_METHOD,
576 roundingMethod,
577 "ROUND_CEILING", BigDecimal.ROUND_CEILING,
578 "ROUND_DOWN", BigDecimal.ROUND_DOWN,
579 "ROUND_FLOOR", BigDecimal.ROUND_FLOOR,
580 "ROUND_HALF_DOWN", BigDecimal.ROUND_HALF_DOWN,
581 "ROUND_HALF_EVEN", BigDecimal.ROUND_HALF_EVEN,
582 "ROUND_HALF_UP", BigDecimal.ROUND_HALF_UP,
583 "ROUND_UNNECESSARY", BigDecimal.ROUND_UNNECESSARY,
584 "ROUND_UP", BigDecimal.ROUND_UP);
585 }
586 return unscaled;
587 }
588
589
590 /**
591 * Computes a number {@code delta} close to {@code originalDelta} with
592 * the property that <pre><code>
593 * x + delta - x
594 * </code></pre>
595 * is exactly machine-representable.
596 * This is useful when computing numerical derivatives, in order to reduce
597 * roundoff errors.
598 *
599 * @param x Value.
600 * @param originalDelta Offset value.
601 * @return a number {@code delta} so that {@code x + delta} and {@code x}
602 * differ by a representable floating number.
603 */
604 public static double representableDelta(double x,
605 double originalDelta) {
606 return x + originalDelta - x;
607 }
608}
Note: See TracBrowser for help on using the repository browser.