1 /* 2 * This file is part of ELKI: 3 * Environment for Developing KDD-Applications Supported by Index-Structures 4 * 5 * Copyright (C) 2018 6 * ELKI Development Team 7 * 8 * This program is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Affero General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Affero General Public License for more details. 17 * 18 * You should have received a copy of the GNU Affero General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 package de.lmu.ifi.dbs.elki.math; 22 23 import java.math.BigInteger; 24 import java.util.Random; 25 26 import net.jafama.FastMath; 27 28 /** 29 * A collection of math related utility functions. 30 * 31 * @author Arthur Zimek 32 * @author Erich Schubert 33 * @since 0.1 34 * 35 * @opt nodefillcolor LemonChiffon 36 */ 37 public final class MathUtil { 38 /** 39 * Two times Pi. 40 */ 41 public static final double TWOPI = 2. * Math.PI; 42 43 /** 44 * Half the value of Pi. 45 */ 46 public static final double HALFPI = .5 * Math.PI; 47 48 /** 49 * One quarter of Pi. 50 */ 51 public static final double QUARTERPI = .25 * Math.PI; 52 53 /** 54 * 1.5 times Pi. 55 */ 56 public static final double ONEHALFPI = 1.5 * Math.PI; 57 58 /** 59 * Pi squared 60 */ 61 public static final double PISQUARE = Math.PI * Math.PI; 62 63 /** 64 * Square root of Pi. 65 */ 66 public static final double SQRTPI = Math.sqrt(Math.PI); 67 68 /** 69 * Square root of two times Pi. 70 */ 71 public static final double SQRTTWOPI = Math.sqrt(TWOPI); 72 73 /** 74 * Constant for sqrt(pi/2) 75 */ 76 public static final double SQRTHALFPI = Math.sqrt(HALFPI); 77 78 /** 79 * Square root of 2. 80 */ 81 public static final double SQRT2 = Math.sqrt(2.); 82 83 /** 84 * Square root of 3. 85 */ 86 public static final double SQRT3 = Math.sqrt(3.); 87 88 /** 89 * Square root of 5. 90 */ 91 public static final double SQRT5 = Math.sqrt(5.); 92 93 /** 94 * Square root of 0.5 == 1 / sqrt(2). 95 */ 96 public static final double SQRTHALF = Math.sqrt(.5); 97 98 /** 99 * Precomputed value of 1 / sqrt(pi). 100 */ 101 public static final double ONE_BY_SQRTPI = 1. / SQRTPI; 102 103 /** 104 * Precomputed value of 1 / sqrt(2 * pi). 105 */ 106 public static final double ONE_BY_SQRTTWOPI = 1. / SQRTTWOPI; 107 108 /** 109 * Precomputed value of log(1 / sqrt(2 * pi)) = -.5 * log(2*pi). 110 */ 111 public static final double LOG_ONE_BY_SQRTTWOPI = -.5 * Math.log(TWOPI); 112 113 /** 114 * 1. / log(2) 115 */ 116 public static final double ONE_BY_LOG2 = 1. / Math.log(2.); 117 118 /** 119 * One third. 120 */ 121 public static final double ONE_THIRD = 1. / 3.; 122 123 /** 124 * Square root of one third. 125 */ 126 public static final double SQRTTHIRD = FastMath.sqrt(1 / 3.); 127 128 /** 129 * Logarithm of 2 to the basis e, for logarithm conversion. 130 */ 131 public static final double LOG2 = Math.log(2.); 132 133 /** 134 * Logarithm of 3 to the basis e, for logarithm conversion. 135 */ 136 public static final double LOG3 = Math.log(3.); 137 138 /** 139 * Natural logarithm of 10. 140 */ 141 public static final double LOG10 = Math.log(10.); 142 143 /** 144 * log(PI). 145 */ 146 public static final double LOGPI = Math.log(Math.PI); 147 148 /** 149 * log(PI) / 2. 150 */ 151 public static final double LOGPIHALF = LOGPI / 2.; 152 153 /** 154 * log(2*PI). 155 */ 156 public static final double LOGTWOPI = Math.log(TWOPI); 157 158 /** 159 * log(sqrt(2*PI)). 160 */ 161 public static final double LOGSQRTTWOPI = Math.log(SQRTTWOPI); 162 163 /** 164 * log(log(2)) 165 */ 166 public static final double LOGLOG2 = Math.log(LOG2); 167 168 /** 169 * Constant for degrees to radians. 170 */ 171 public static final double DEG2RAD = Math.PI / 180.0; 172 173 /** 174 * Constant for radians to degrees. 175 */ 176 public static final double RAD2DEG = 180 / Math.PI; 177 178 /** 179 * Fake constructor for static class. 180 */ MathUtil()181 private MathUtil() { 182 // Static methods only - do not instantiate! 183 } 184 185 /** 186 * Compute the base 2 logarithm. 187 * 188 * @param x X 189 * @return Logarithm base 2. 190 */ log2(double x)191 public static double log2(double x) { 192 return FastMath.log(x) * ONE_BY_LOG2; 193 } 194 195 /** 196 * Compute the Factorial of n, often written as <code>c!</code> in 197 * mathematics. 198 * <p> 199 * Use this method if for large values of <code>n</code>. 200 * 201 * @param n Note: n >= 0. This {@link BigInteger} <code>n</code> will be 0 202 * after this method finishes. 203 * @return n * (n-1) * (n-2) * ... * 1 204 */ factorial(BigInteger n)205 public static BigInteger factorial(BigInteger n) { 206 BigInteger nFac = BigInteger.ONE; 207 while(n.compareTo(BigInteger.ONE) > 0) { 208 nFac = nFac.multiply(n); 209 n = n.subtract(BigInteger.ONE); 210 } 211 return nFac; 212 } 213 214 /** 215 * Compute the Factorial of n, often written as <code>c!</code> in 216 * mathematics. 217 * 218 * @param n Note: n >= 0 219 * @return n * (n-1) * (n-2) * ... * 1 220 */ factorial(int n)221 public static long factorial(int n) { 222 long nFac = 1; 223 for(long i = n; i > 0; i--) { 224 nFac *= i; 225 } 226 return nFac; 227 } 228 229 /** 230 * Binomial coefficient, also known as "n choose k". 231 * 232 * @param n Total number of samples. n > 0 233 * @param k Number of elements to choose. <code>n >= k</code>, 234 * <code>k >= 0</code> 235 * @return n! / (k! * (n-k)!) 236 */ binomialCoefficient(long n, long k)237 public static long binomialCoefficient(long n, long k) { 238 final long m = Math.max(k, n - k); 239 double temp = 1; 240 for(long i = n, j = 1; i > m; i--, j++) { 241 temp = temp * i / j; 242 } 243 return (long) temp; 244 } 245 246 /** 247 * Compute the Factorial of n, often written as <code>c!</code> in 248 * mathematics. 249 * 250 * @param n Note: n >= 0 251 * @return n * (n-1) * (n-2) * ... * 1 252 */ approximateFactorial(int n)253 public static double approximateFactorial(int n) { 254 double nFac = 1.0; 255 for(int i = n; i > 0; i--) { 256 nFac *= i; 257 } 258 return nFac; 259 } 260 261 /** 262 * Binomial coefficent, also known as "n choose k"). 263 * 264 * @param n Total number of samples. n > 0 265 * @param k Number of elements to choose. <code>n >= k</code>, 266 * <code>k >= 0</code> 267 * @return n! / (k! * (n-k)!) 268 */ approximateBinomialCoefficient(int n, int k)269 public static double approximateBinomialCoefficient(int n, int k) { 270 final int m = max(k, n - k); 271 long temp = 1; 272 for(int i = n, j = 1; i > m; i--, j++) { 273 temp = temp * i / j; 274 } 275 return temp; 276 } 277 278 /** 279 * Compute the sum of the i first integers. 280 * 281 * @param i maximum summand (inclusive) 282 * @return Sum 283 */ sumFirstIntegers(final long i)284 public static long sumFirstIntegers(final long i) { 285 return ((i + 1L) * i) >> 1; 286 } 287 288 /** 289 * Produce an array of random numbers in [0:1]. 290 * 291 * @param len Length 292 * @param r Random generator 293 * @return Array 294 */ randomDoubleArray(int len, Random r)295 public static double[] randomDoubleArray(int len, Random r) { 296 final double[] ret = new double[len]; 297 for(int i = 0; i < len; i++) { 298 ret[i] = r.nextDouble(); 299 } 300 return ret; 301 } 302 303 /** 304 * Convert Degree to Radians. 305 * <p> 306 * This is essentially the same as {@link Math#toRadians}, but we keep it for 307 * now, it might be marginally faster, but certainly not slower. 308 * 309 * @param deg Degree value 310 * @return Radian value 311 */ deg2rad(double deg)312 public static double deg2rad(double deg) { 313 return deg * DEG2RAD; 314 } 315 316 /** 317 * Radians to Degree. 318 * <p> 319 * This is essentially the same as {@link Math#toRadians}, but we keep it for 320 * now, it might be marginally faster, but certainly not slower. 321 * 322 * @param rad Radians value 323 * @return Degree value 324 */ rad2deg(double rad)325 public static double rad2deg(double rad) { 326 return rad * RAD2DEG; 327 } 328 329 /** 330 * Normalize an angle to [0:2pi[ 331 * 332 * @param x Input angle 333 * @return Normalized angle 334 */ normAngle(double x)335 public static double normAngle(double x) { 336 x %= TWOPI; 337 return (x > 0) ? x : x + TWOPI; 338 } 339 340 /** 341 * Find the next power of 2. 342 * <p> 343 * Classic bit operation, for signed 32-bit. Valid for positive integers only 344 * (0 otherwise). 345 * 346 * @param x original integer 347 * @return Next power of 2 348 */ nextPow2Int(int x)349 public static int nextPow2Int(int x) { 350 --x; 351 x |= x >>> 1; 352 x |= x >>> 2; 353 x |= x >>> 4; 354 x |= x >>> 8; 355 x |= x >>> 16; 356 return ++x; 357 } 358 359 /** 360 * Find the next power of 2. 361 * <p> 362 * Classic bit operation, for signed 64-bit. Valid for positive integers only 363 * (0 otherwise). 364 * 365 * @param x original long integer 366 * @return Next power of 2 367 */ nextPow2Long(long x)368 public static long nextPow2Long(long x) { 369 --x; 370 x |= x >>> 1; 371 x |= x >>> 2; 372 x |= x >>> 4; 373 x |= x >>> 16; 374 x |= x >>> 32; 375 return ++x; 376 } 377 378 /** 379 * Find the next larger number with all ones. 380 * <p> 381 * Classic bit operation, for signed 32-bit. Valid for positive integers only 382 * (-1 otherwise). 383 * 384 * @param x original integer 385 * @return Next number with all bits set 386 */ nextAllOnesInt(int x)387 public static int nextAllOnesInt(int x) { 388 x |= x >>> 1; 389 x |= x >>> 2; 390 x |= x >>> 4; 391 x |= x >>> 8; 392 x |= x >>> 16; 393 return x; 394 } 395 396 /** 397 * Find the next larger number with all ones. 398 * <p> 399 * Classic bit operation, for signed 64-bit. Valid for positive integers only 400 * (-1 otherwise). 401 * 402 * @param x original long integer 403 * @return Next number with all bits set 404 */ nextAllOnesLong(long x)405 public static long nextAllOnesLong(long x) { 406 x |= x >>> 1; 407 x |= x >>> 2; 408 x |= x >>> 4; 409 x |= x >>> 16; 410 x |= x >>> 32; 411 return x; 412 } 413 414 /** 415 * Return the largest double that rounds down to this float. 416 * <p> 417 * Note: Probably not always correct - subnormal values are quite tricky. So 418 * some of the bounds might not be tight. 419 * 420 * @param f Float value 421 * @return Double value 422 */ floatToDoubleUpper(float f)423 public static double floatToDoubleUpper(float f) { 424 if(Float.isNaN(f)) { 425 return Double.NaN; 426 } 427 if(Float.isInfinite(f)) { 428 return f > 0 ? Double.POSITIVE_INFINITY : Double.longBitsToDouble(0xc7efffffffffffffL); 429 } 430 long bits = Double.doubleToRawLongBits((double) f); 431 if((bits & 0x8000000000000000L) == 0) { // Positive 432 if(bits == 0L) { 433 return Double.longBitsToDouble(0x3690000000000000L); 434 } 435 if(f == Float.MIN_VALUE) { 436 // bits += 0x7_ffff_ffff_ffffl; 437 return Double.longBitsToDouble(0x36a7ffffffffffffL); 438 } 439 if(Float.MIN_NORMAL > f && f >= Double.MIN_NORMAL) { 440 // The most tricky case: 441 // a denormalized float, but a normalized double 442 final long bits2 = Double.doubleToRawLongBits((double) Math.nextUp(f)); 443 bits = (bits >>> 1) + (bits2 >>> 1) - 1L; 444 } 445 else { 446 bits += 0xfffffffL; // 28 extra bits 447 } 448 return Double.longBitsToDouble(bits); 449 } 450 else { 451 if(bits == 0x8000000000000000L) { 452 return -0.0d; 453 } 454 if(f == -Float.MIN_VALUE) { 455 // bits -= 0xf_ffff_ffff_ffffl; 456 return Double.longBitsToDouble(0xb690000000000001L); 457 } 458 if(-Float.MIN_NORMAL < f && f <= -Double.MIN_NORMAL) { 459 // The most tricky case: 460 // a denormalized float, but a normalized double 461 final long bits2 = Double.doubleToRawLongBits((double) Math.nextUp(f)); 462 bits = (bits >>> 1) + (bits2 >>> 1) + 1L; 463 } 464 else { 465 bits -= 0xfffffffL; // 28 extra bits 466 } 467 return Double.longBitsToDouble(bits); 468 } 469 } 470 471 /** 472 * Return the largest double that rounds up to this float. 473 * <p> 474 * Note: Probably not always correct - subnormal values are quite tricky. So 475 * some of the bounds might not be tight. 476 * 477 * @param f Float value 478 * @return Double value 479 */ floatToDoubleLower(float f)480 public static double floatToDoubleLower(float f) { 481 if(Float.isNaN(f)) { 482 return Double.NaN; 483 } 484 if(Float.isInfinite(f)) { 485 return f < 0 ? Double.NEGATIVE_INFINITY : Double.longBitsToDouble(0x47efffffffffffffL); 486 } 487 long bits = Double.doubleToRawLongBits((double) f); 488 if((bits & 0x8000000000000000L) == 0) { // Positive 489 if(bits == 0L) { 490 return +0.0d; 491 } 492 if(f == Float.MIN_VALUE) { 493 // bits -= 0xf_ffff_ffff_ffffl; 494 return Double.longBitsToDouble(0x3690000000000001L); 495 } 496 if(Float.MIN_NORMAL > f /* && f >= Double.MIN_NORMAL */) { 497 // The most tricky case: 498 // a denormalized float, but a normalized double 499 final long bits2 = Double.doubleToRawLongBits((double) -Math.nextUp(-f)); 500 bits = (bits >>> 1) + (bits2 >>> 1) + 1L; // + (0xfff_ffffL << 18); 501 } 502 else { 503 bits -= 0xfffffffL; // 28 extra bits 504 } 505 return Double.longBitsToDouble(bits); 506 } 507 else { 508 if(bits == 0x8000000000000000L) { 509 return Double.longBitsToDouble(0xb690000000000000L); 510 } 511 if(f == -Float.MIN_VALUE) { 512 // bits += 0x7_ffff_ffff_ffffl; 513 return Double.longBitsToDouble(0xb6a7ffffffffffffL); 514 } 515 if(-Float.MIN_NORMAL < f /* && f <= -Double.MIN_NORMAL */) { 516 // The most tricky case: 517 // a denormalized float, but a normalized double 518 final long bits2 = Double.doubleToRawLongBits((double) -Math.nextUp(-f)); 519 bits = (bits >>> 1) + (bits2 >>> 1) - 1L; 520 } 521 else { 522 bits += 0xfffffffL; // 28 extra bits 523 } 524 return Double.longBitsToDouble(bits); 525 } 526 } 527 528 /** 529 * More stable than {@code FastMath.log(1 - FastMath.exp(x))} 530 * 531 * @param x Value 532 * @return log(1-exp(x)) 533 */ log1mexp(double x)534 public static double log1mexp(double x) { 535 return (x > -LOG2) ? FastMath.log(-FastMath.expm1(x)) : FastMath.log1p(-exp(x)); 536 } 537 538 /** 539 * Delegate to FastMath.exp. 540 * 541 * @param d Value 542 * @return FastMath.exp(d) 543 */ exp(double d)544 public static double exp(double d) { 545 return FastMath.exp(d); 546 } 547 548 /** 549 * Delegate to FastMath.powFast 550 * 551 * @param x Base 552 * @param p Exponent 553 * @return {@code FastMath.powFast(x, p)} 554 */ powi(double x, int p)555 public static double powi(double x, int p) { 556 return FastMath.powFast(x, p); 557 } 558 559 /** 560 * Fast loop for computing {@code pow(x, p)} 561 * for {@code p >= 0} integer and x integer. 562 * 563 * @param x Base 564 * @param p Exponent 565 * @return {@code pow(x, p)} 566 */ ipowi(int x, int p)567 public static int ipowi(int x, int p) { 568 if(p <= 2) { 569 return (int) FastMath.powFast(x, p); 570 } 571 int tmp = x, ret = (p & 1) == 1 ? x : 1; 572 while(true) { 573 tmp *= tmp; 574 p >>= 1; 575 if(p == 1) { 576 return ret * tmp; 577 } 578 if((p & 1) != 0) { 579 ret *= tmp; 580 } 581 } 582 } 583 584 /** 585 * Empty integer array. 586 */ 587 public static final int[] EMPTY_INTS = new int[0]; 588 589 /** 590 * Generate an array of integers. 591 * 592 * @param start First integer 593 * @param end Last integer (exclusive!) 594 * @return Array of integers of length end-start 595 */ sequence(int start, int end)596 public static int[] sequence(int start, int end) { 597 if(start >= end) { 598 return EMPTY_INTS; 599 } 600 int[] ret = new int[end - start]; 601 for(int j = 0; start < end; start++, j++) { 602 ret[j] = start; 603 } 604 return ret; 605 } 606 607 /** 608 * Binary max, <i>without</i> handling of special values. 609 * <p> 610 * Because of the lack of special case handling, this is faster than 611 * {@link Math#max}. But usually, it should be written inline as 612 * {@code (a >= b) ? a : b} 613 * <p> 614 * The result is asymmetric in case of {@code Double.NaN}:<br> 615 * {@code MathUtil.max(Double.NaN, 1.)} is 1, but <br> 616 * {@code MathUtil.max(1., Double.NaN)} is {@code Double.NaN}. 617 * 618 * @param a First value 619 * @param b Second value 620 * @return Maximum 621 */ max(double a, double b)622 public static double max(double a, double b) { 623 return a >= b ? a : b; 624 } 625 626 /** 627 * Ternary max, <i>without</i> handling of special values. 628 * <p> 629 * Because of the lack of special case handling, this is faster than 630 * {@link Math#max}. But usually, it should be written inline. 631 * 632 * @param a First value 633 * @param b Second value 634 * @param c Third value 635 * @return Maximum 636 */ max(double a, double b, double c)637 public static double max(double a, double b, double c) { 638 return a >= b ? (a >= c ? a : c) : (b >= c ? b : c); 639 } 640 641 /** 642 * Quadrary max, <i>without</i> handling of special values. 643 * 644 * Because of the lack of special case handling, this is faster than 645 * {@link Math#max}. But usually, it should be written inline. 646 * 647 * @param a First value 648 * @param b Second value 649 * @param c Third value 650 * @param d Fourth value 651 * @return Maximum 652 */ max(double a, double b, double c, double d)653 public static double max(double a, double b, double c, double d) { 654 return a >= b ? // 655 a >= c ? (a >= d ? a : d) : (c >= d ? c : d) : // 656 b >= c ? (b >= d ? b : d) : (c >= d ? c : d); 657 } 658 659 /** 660 * Binary max. If possible, inline. 661 * 662 * @param a First value 663 * @param b Second value 664 * @return Maximum 665 */ max(int a, int b)666 public static int max(int a, int b) { 667 return a >= b ? a : b; 668 } 669 670 /** 671 * Ternary max. If possible, inline. 672 * 673 * @param a First value 674 * @param b Second value 675 * @param c Third value 676 * @return Maximum 677 */ max(int a, int b, int c)678 public static int max(int a, int b, int c) { 679 return a >= b ? (a >= c ? a : c) : (b >= c ? b : c); 680 } 681 682 /** 683 * Quadrary max, <i>without</i> handling of special values. 684 * 685 * Because of the lack of special case handling, this is faster than 686 * {@link Math#max}. But usually, it should be written inline. 687 * 688 * @param a First value 689 * @param b Second value 690 * @param c Third value 691 * @param d Fourth value 692 * @return Maximum 693 */ max(int a, int b, int c, int d)694 public static int max(int a, int b, int c, int d) { 695 return a >= b ? // 696 a >= c ? (a >= d ? a : d) : (c >= d ? c : d) : // 697 b >= c ? (b >= d ? b : d) : (c >= d ? c : d); 698 } 699 700 /** 701 * Binary min, <i>without</i> handling of special values. 702 * <p> 703 * Because of the lack of special case handling, this is faster than 704 * {@link Math#min}. But usually, it should be written inline as 705 * {@code (a <= b) ? a : b} 706 * <p> 707 * The result is asymmetric in case of {@code Double.NaN}:<br> 708 * {@code MathUtil.min(Double.NaN, 1.)} is 1, but <br> 709 * {@code MathUtil.min(1., Double.NaN)} is {@code Double.NaN}. 710 * 711 * @param a First value 712 * @param b Second value 713 * @return minimum 714 */ min(double a, double b)715 public static double min(double a, double b) { 716 return a <= b ? a : b; 717 } 718 719 /** 720 * Ternary min, <i>without</i> handling of special values. 721 * <p> 722 * Because of the lack of special case handling, this is faster than 723 * {@link Math#min}. But usually, it should be written inline. 724 * 725 * @param a First value 726 * @param b Second value 727 * @param c Third value 728 * @return minimum 729 */ min(double a, double b, double c)730 public static double min(double a, double b, double c) { 731 return a <= b ? (a <= c ? a : c) : (b <= c ? b : c); 732 } 733 734 /** 735 * Quadrary min, <i>without</i> handling of special values. 736 * <p> 737 * Because of the lack of special case handling, this is faster than 738 * {@link Math#min}. But usually, it should be written inline. 739 * 740 * @param a First value 741 * @param b Second value 742 * @param c Third value 743 * @param d Fourth value 744 * @return minimum 745 */ min(double a, double b, double c, double d)746 public static double min(double a, double b, double c, double d) { 747 return a <= b ? // 748 a <= c ? (a <= d ? a : d) : (c <= d ? c : d) : // 749 b <= c ? (b <= d ? b : d) : (c <= d ? c : d); 750 } 751 752 /** 753 * Binary min, <i>without</i> handling of special values. 754 * <p> 755 * Because of the lack of special case handling, this is faster than 756 * {@link Math#min}. But usually, it should be written inline. 757 * 758 * @param a First value 759 * @param b Second value 760 * @return minimum 761 */ min(int a, int b)762 public static int min(int a, int b) { 763 return a <= b ? a : b; 764 } 765 766 /** 767 * Ternary min, <i>without</i> handling of special values. 768 * <p> 769 * Because of the lack of special case handling, this is faster than 770 * {@link Math#min}. But usually, it should be written inline. 771 * 772 * @param a First value 773 * @param b Second value 774 * @param c Third value 775 * @return minimum 776 */ min(int a, int b, int c)777 public static int min(int a, int b, int c) { 778 return a <= b ? (a <= c ? a : c) : (b <= c ? b : c); 779 } 780 781 /** 782 * Quadrary min, <i>without</i> handling of special values. 783 * <p> 784 * Because of the lack of special case handling, this is faster than 785 * {@link Math#min}. But usually, it should be written inline. 786 * 787 * @param a First value 788 * @param b Second value 789 * @param c Third value 790 * @param d Fourth value 791 * @return minimum 792 */ min(int a, int b, int c, int d)793 public static int min(int a, int b, int c, int d) { 794 return a <= b ? // 795 a <= c ? (a <= d ? a : d) : (c <= d ? c : d) : // 796 b <= c ? (b <= d ? b : d) : (c <= d ? c : d); 797 } 798 } 799