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}