001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.math; 020 021/** 022 * Math utilities class. 023 * 024 * @author stephane 025 */ 026public class MathUtil 027{ 028 public static final String INFINITE_STRING = "\u221E"; 029 030 public static final double POW2_8_DOUBLE = Math.pow(2, 8); 031 public static final float POW2_8_FLOAT = (float) POW2_8_DOUBLE; 032 public static final double POW2_16_DOUBLE = Math.pow(2, 16); 033 public static final float POW2_16_FLOAT = (float) POW2_16_DOUBLE; 034 public static final double POW2_32_DOUBLE = Math.pow(2, 32); 035 public static final float POW2_32_FLOAT = (float) POW2_32_DOUBLE; 036 public static final double POW2_64_DOUBLE = Math.pow(2, 64); 037 public static final float POW2_64_FLOAT = (float) POW2_64_DOUBLE; 038 039 /** 040 * @deprecated please use {@link UnitUtil#getBytesString(double)} instead. 041 */ 042 @Deprecated 043 public static String getBytesString(double value) 044 { 045 return UnitUtil.getBytesString(value); 046 } 047 048 public static double frac(double value) 049 { 050 return value - Math.floor(value); 051 } 052 053 /** 054 * Normalize an array 055 * 056 * @param array 057 * elements to normalize 058 */ 059 public static void normalize(float[] array) 060 { 061 final float max = ArrayMath.max(array); 062 063 if (max != 0) 064 divide(array, max); 065 else 066 { 067 final float min = ArrayMath.min(array); 068 if (min != 0) 069 divide(array, min); 070 } 071 } 072 073 /** 074 * Normalize an array 075 * 076 * @param array 077 * elements to normalize 078 */ 079 public static void normalize(double[] array) 080 { 081 final double max = ArrayMath.max(array); 082 083 if (max != 0) 084 divide(array, max); 085 else 086 { 087 final double min = ArrayMath.min(array); 088 if (min != 0) 089 divide(array, min); 090 } 091 } 092 093 /** 094 * Replace all values in the array by their logarithm<br> 095 * Be careful, all values should be >0 values 096 * 097 * @param array 098 * elements to logarithm 099 */ 100 public static void log(double[] array) 101 { 102 final int len = array.length; 103 104 for (int i = 0; i < len; i++) 105 array[i] = Math.log(array[i]); 106 } 107 108 /** 109 * Replace all values in the array by their logarithm<br> 110 * Be careful, all values should be >0 values 111 * 112 * @param array 113 * elements to logarithm 114 */ 115 public static void log(float[] array) 116 { 117 final int len = array.length; 118 119 for (int i = 0; i < len; i++) 120 array[i] = (float) Math.log(array[i]); 121 } 122 123 /** 124 * Add the the specified value to all elements in an array 125 * 126 * @param array 127 * elements to modify 128 * @param value 129 */ 130 public static void add(double[] array, double value) 131 { 132 final int len = array.length; 133 134 for (int i = 0; i < len; i++) 135 array[i] = array[i] + value; 136 } 137 138 /** 139 * Add the the specified value to all elements in an array 140 * 141 * @param array 142 * elements to modify 143 * @param value 144 */ 145 public static void add(float[] array, float value) 146 { 147 final int len = array.length; 148 149 for (int i = 0; i < len; i++) 150 array[i] = array[i] + value; 151 } 152 153 /** 154 * Multiply and add all elements in an array by the specified values 155 * 156 * @param array 157 * elements to modify 158 * @param mulValue 159 * @param addValue 160 */ 161 public static void madd(double[] array, double mulValue, double addValue) 162 { 163 final int len = array.length; 164 165 for (int i = 0; i < len; i++) 166 array[i] = (array[i] * mulValue) + addValue; 167 } 168 169 /** 170 * Multiply and add all elements in an array by the specified values 171 * 172 * @param array 173 * elements to modify 174 * @param mulValue 175 * @param addValue 176 */ 177 public static void madd(float[] array, float mulValue, float addValue) 178 { 179 final int len = array.length; 180 181 for (int i = 0; i < len; i++) 182 array[i] = (array[i] * mulValue) + addValue; 183 } 184 185 /** 186 * Multiply all elements in an array by the specified value 187 * 188 * @param array 189 * elements to modify 190 * @param value 191 * value to multiply by 192 */ 193 public static void mul(double[] array, double value) 194 { 195 final int len = array.length; 196 197 for (int i = 0; i < len; i++) 198 array[i] = array[i] * value; 199 } 200 201 /** 202 * Multiply all elements in an array by the specified value 203 * 204 * @param array 205 * elements to modify 206 * @param value 207 * value to multiply by 208 */ 209 public static void mul(float[] array, float value) 210 { 211 final int len = array.length; 212 213 for (int i = 0; i < len; i++) 214 array[i] = array[i] * value; 215 } 216 217 /** 218 * Divides all elements in an array by the specified value 219 * 220 * @param array 221 * elements to modify 222 * @param value 223 * value used as divisor 224 */ 225 public static void divide(double[] array, double value) 226 { 227 if (value != 0d) 228 { 229 final int len = array.length; 230 231 for (int i = 0; i < len; i++) 232 array[i] = array[i] / value; 233 } 234 } 235 236 /** 237 * Divides all elements in an array by the specified value 238 * 239 * @param array 240 * elements to modify 241 * @param value 242 * value used as divisor 243 */ 244 public static void divide(float[] array, float value) 245 { 246 if (value != 0d) 247 { 248 final int len = array.length; 249 250 for (int i = 0; i < len; i++) 251 array[i] = array[i] / value; 252 } 253 } 254 255 /** 256 * @deprecated use {@link ArrayMath#min(Object, boolean)} instead 257 */ 258 @Deprecated 259 public static double min(Object array, boolean signed) 260 { 261 return ArrayMath.min(array, signed); 262 } 263 264 /** 265 * @deprecated use {@link ArrayMath#min(byte[], boolean)} instead 266 */ 267 @Deprecated 268 public static int min(byte[] array, boolean signed) 269 { 270 return ArrayMath.min(array, signed); 271 } 272 273 /** 274 * @deprecated use {@link ArrayMath#min(short[], boolean)} instead 275 */ 276 @Deprecated 277 public static int min(short[] array, boolean signed) 278 { 279 return ArrayMath.min(array, signed); 280 } 281 282 /** 283 * @deprecated use {@link ArrayMath#min(int[], boolean)} instead 284 */ 285 @Deprecated 286 public static long min(int[] array, boolean signed) 287 { 288 return ArrayMath.min(array, signed); 289 } 290 291 /** 292 * @deprecated use {@link ArrayMath#min(float[])} instead 293 */ 294 @Deprecated 295 public static float min(float[] array) 296 { 297 return ArrayMath.min(array); 298 } 299 300 /** 301 * @deprecated use {@link ArrayMath#min(double[])} instead 302 */ 303 @Deprecated 304 public static double min(double[] array) 305 { 306 return ArrayMath.min(array); 307 308 } 309 310 /** 311 * @deprecated use {@link ArrayMath#max(Object, boolean)} instead 312 */ 313 @Deprecated 314 public static double max(Object array, boolean signed) 315 { 316 return ArrayMath.max(array, signed); 317 } 318 319 /** 320 * @deprecated use {@link ArrayMath#max(byte[], boolean)} instead 321 */ 322 @Deprecated 323 public static int max(byte[] array, boolean signed) 324 { 325 return ArrayMath.max(array, signed); 326 } 327 328 /** 329 * @deprecated use {@link ArrayMath#max(short[], boolean)} instead 330 */ 331 @Deprecated 332 public static int max(short[] array, boolean signed) 333 { 334 return ArrayMath.max(array, signed); 335 } 336 337 /** 338 * @deprecated use {@link ArrayMath#max(int[], boolean)} instead 339 */ 340 @Deprecated 341 public static long max(int[] array, boolean signed) 342 { 343 return ArrayMath.max(array, signed); 344 } 345 346 /** 347 * @deprecated use {@link ArrayMath#max(float[])} instead 348 */ 349 @Deprecated 350 public static float max(float[] array) 351 { 352 return ArrayMath.max(array); 353 } 354 355 /** 356 * @deprecated use {@link ArrayMath#max(double[])} instead 357 */ 358 @Deprecated 359 public static double max(double[] array) 360 { 361 return ArrayMath.max(array); 362 } 363 364 /** 365 * Round specified value to specified number of significant digit.<br> 366 * If keepInteger is true then integer part of number is entirely conserved.<br> 367 * If <i>numDigit</i> is <= 0 then the value stay unchanged. 368 */ 369 public static double roundSignificant(double d, int numDigit, boolean keepInteger) 370 { 371 if ((numDigit <= 0) || (d == 0d)) 372 return d; 373 374 final double digit = Math.ceil(Math.log10(Math.abs(d))); 375 if ((digit >= numDigit) && keepInteger) 376 return Math.round(d); 377 378 return round(d, numDigit - (int) digit); 379 } 380 381 /** 382 * Round specified value to specified number of significant digit. 383 */ 384 public static double roundSignificant(double d, int numDigit) 385 { 386 return roundSignificant(d, numDigit, false); 387 } 388 389 /** 390 * Round specified value to specified number of decimal. 391 */ 392 public static double round(double d, int numDecimal) 393 { 394 final double pow = Math.pow(10, numDecimal); 395 return Math.round(d * pow) / pow; 396 } 397 398 /** 399 * Return the previous multiple of "mul" for the specified value 400 * <ul> 401 * <li>prevMultiple(200, 64) = 192</li> 402 * </ul> 403 * 404 * @param value 405 * @param mul 406 */ 407 public static double prevMultiple(double value, double mul) 408 { 409 if (mul == 0) 410 return 0d; 411 412 return Math.floor(value / mul) * mul; 413 } 414 415 /** 416 * Return the next multiple of "mul" for the specified value 417 * <ul> 418 * <li>nextMultiple(200, 64) = 256</li> 419 * </ul> 420 * 421 * @param value 422 * @param mul 423 */ 424 public static double nextMultiple(double value, double mul) 425 { 426 if (mul == 0) 427 return 0d; 428 429 return Math.ceil(value / mul) * mul; 430 } 431 432 /** 433 * Return the next power of 2 for the specified value 434 * <ul> 435 * <li>nextPow2(17) = 32</li> 436 * <li>nextPow2(16) = 32</li> 437 * <li>nextPow2(-12) = -8</li> 438 * <li>nextPow2(-8) = -4</li> 439 * </ul> 440 * 441 * @param value 442 * @return next power of 2 443 */ 444 public static long nextPow2(long value) 445 { 446 long result; 447 448 if (value < 0) 449 { 450 result = -1; 451 while (result > value) 452 result <<= 1; 453 result >>= 1; 454 } 455 else 456 { 457 result = 1; 458 while (result <= value) 459 result <<= 1; 460 } 461 462 return result; 463 } 464 465 /** 466 * Return the next power of 2 mask for the specified value 467 * <ul> 468 * <li>nextPow2Mask(17) = 31</li> 469 * <li>nextPow2Mask(16) = 31</li> 470 * <li>nextPow2Mask(-12) = -8</li> 471 * <li>nextPow2Mask(-8) = -4</li> 472 * </ul> 473 * 474 * @param value 475 * @return next power of 2 mask 476 */ 477 public static long nextPow2Mask(long value) 478 { 479 final long result = nextPow2(value); 480 if (value > 0) 481 return result - 1; 482 483 return result; 484 } 485 486 /** 487 * Return the previous power of 2 for the specified value 488 * <ul> 489 * <li>prevPow2(17) = 16</li> 490 * <li>prevPow2(16) = 8</li> 491 * <li>prevPow2(-12) = -16</li> 492 * <li>prevPow2(-8) = -16</li> 493 * </ul> 494 * 495 * @param value 496 * @return previous power of 2 497 */ 498 public static long prevPow2(long value) 499 { 500 long result; 501 502 if (value < 0) 503 { 504 result = -1; 505 while (result >= value) 506 result <<= 1; 507 } 508 else 509 { 510 result = 1; 511 while (result < value) 512 result <<= 1; 513 result >>= 1; 514 } 515 516 return result; 517 } 518 519 /** 520 * Return the next power of 10 for the specified value 521 * <ul> 522 * <li>nextPow10(0.0067) = 0.01</li> 523 * <li>nextPow10(-28.7) = -10</li> 524 * </ul> 525 * 526 * @param value 527 */ 528 public static double nextPow10(double value) 529 { 530 if (value == 0) 531 return 0; 532 else if (value < 0) 533 return -Math.pow(10, Math.floor(Math.log10(-value))); 534 else 535 return Math.pow(10, Math.ceil(Math.log10(value))); 536 } 537 538 /** 539 * Return the previous power of 10 for the specified value 540 * <ul> 541 * <li>prevPow10(0.0067) = 0.001</li> 542 * <li>prevPow10(-28.7) = -100</li> 543 * </ul> 544 * 545 * @param value 546 */ 547 public static double prevPow10(double value) 548 { 549 if (value == 0) 550 return 0; 551 else if (value < 0) 552 return -Math.pow(10, Math.ceil(Math.log10(-value))); 553 else 554 return Math.pow(10, Math.floor(Math.log10(value))); 555 } 556 557 /** 558 * Format the specified degree angle to stay in [0..360[ range 559 */ 560 public static double formatDegreeAngle(double angle) 561 { 562 final double res = angle % 360d; 563 564 if (res < 0) 565 return 360d + res; 566 567 return res; 568 } 569 570 /** 571 * Format the specified degree angle to stay in [-180..180] range 572 */ 573 public static double formatDegreeAngle2(double angle) 574 { 575 final double res = angle % 360d; 576 577 if (res < -180d) 578 return 360d + res; 579 if (res > 180d) 580 return res - 360d; 581 582 return res; 583 } 584 585 /** 586 * Format the specified degree angle to stay in [0..2PI[ range 587 */ 588 public static double formatRadianAngle(double angle) 589 { 590 final double res = angle % (2 * Math.PI); 591 592 if (res < 0) 593 return (2 * Math.PI) + res; 594 595 return res; 596 } 597 598 /** 599 * Format the specified degree angle to stay in [-PI..PI] range 600 */ 601 public static double formatRadianAngle2(double angle) 602 { 603 final double res = angle % (2 * Math.PI); 604 605 if (res < -Math.PI) 606 return (2 * Math.PI) + res; 607 if (res > Math.PI) 608 return res - (2 * Math.PI); 609 610 return res; 611 } 612 613 /** 614 * Return the value in <code>source</code> which is the closest to <code>value</code> Returns 615 * <code>0</code> if source is null or empty. 616 */ 617 public static double closest(double value, double[] source) 618 { 619 if ((source == null) || (source.length == 0)) 620 return 0d; 621 622 double result = source[0]; 623 double minDelta = Math.abs(value - result); 624 625 for (double d : source) 626 { 627 final double delta = Math.abs(value - d); 628 629 if (delta < minDelta) 630 { 631 result = d; 632 minDelta = delta; 633 } 634 } 635 636 return result; 637 } 638 639 /** 640 * Calculate the cubic root of the specified value. 641 */ 642 public static double cubicRoot(double value) 643 { 644 return Math.pow(value, 1d / 3d); 645 } 646}