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
021import icy.type.TypeUtil;
022import icy.type.collection.array.Array1DUtil;
023import icy.type.collection.array.ArrayUtil;
024
025/**
026 * Class defining basic arithmetic and statistic operations on 1D double arrays.
027 * 
028 * @author Alexandre Dufour & Stephane
029 */
030public class ArrayMath
031{
032    /**
033     * Element-wise addition of two arrays
034     * 
035     * @param out
036     *        the array receiving the result
037     */
038    public static Object add(Object a1, Object a2, Object out)
039    {
040        switch (ArrayUtil.getDataType(a1))
041        {
042            case BYTE:
043                return add((byte[]) a1, (byte[]) a2, (byte[]) out);
044            case SHORT:
045                return add((short[]) a1, (short[]) a2, (short[]) out);
046            case INT:
047                return add((int[]) a1, (int[]) a2, (int[]) out);
048            case LONG:
049                return add((long[]) a1, (long[]) a2, (long[]) out);
050            case FLOAT:
051                return add((float[]) a1, (float[]) a2, (float[]) out);
052            case DOUBLE:
053                return add((double[]) a1, (double[]) a2, (double[]) out);
054            default:
055                return null;
056        }
057    }
058
059    /**
060     * Element-wise addition of two arrays
061     */
062    public static Object add(Object a1, Object a2)
063    {
064        return add(a1, a2, null);
065    }
066
067    /**
068     * Element-wise addition of two double arrays (result in output if defined)
069     * 
070     * @param out
071     *        the array receiving the result
072     */
073    public static double[] add(double[] a1, double[] a2, double[] out)
074    {
075        final double[] result = Array1DUtil.allocIfNull(out, a1.length);
076
077        for (int i = 0; i < a1.length; i++)
078            result[i] = a1[i] + a2[i];
079
080        return result;
081    }
082
083    /**
084     * Element-wise addition of two double arrays
085     */
086    public static double[] add(double[] a1, double[] a2)
087    {
088        return add(a1, a2, null);
089    }
090
091    /**
092     * Element-wise addition of two float arrays (result in output if defined)
093     * 
094     * @param out
095     *        the array receiving the result
096     */
097    public static float[] add(float[] a1, float[] a2, float[] out)
098    {
099        final float[] result = Array1DUtil.allocIfNull(out, a1.length);
100
101        for (int i = 0; i < a1.length; i++)
102            result[i] = a1[i] + a2[i];
103
104        return result;
105    }
106
107    /**
108     * Element-wise addition of two float arrays
109     */
110    public static float[] add(float[] a1, float[] a2)
111    {
112        return add(a1, a2, null);
113    }
114
115    /**
116     * Element-wise addition of two long arrays (result in output if defined)
117     * 
118     * @param out
119     *        the array receiving the result
120     */
121    public static long[] add(long[] a1, long[] a2, long[] out)
122    {
123        final long[] result = Array1DUtil.allocIfNull(out, a1.length);
124
125        for (int i = 0; i < a1.length; i++)
126            result[i] = a1[i] + a2[i];
127
128        return result;
129    }
130
131    /**
132     * Element-wise addition of two long arrays
133     */
134    public static long[] add(long[] a1, long[] a2)
135    {
136        return add(a1, a2, null);
137    }
138
139    /**
140     * Element-wise addition of two int arrays (result in output if defined)
141     * 
142     * @param out
143     *        the array receiving the result
144     */
145    public static int[] add(int[] a1, int[] a2, int[] out)
146    {
147        final int[] result = Array1DUtil.allocIfNull(out, a1.length);
148
149        for (int i = 0; i < a1.length; i++)
150            result[i] = a1[i] + a2[i];
151
152        return result;
153    }
154
155    /**
156     * Element-wise addition of two int arrays
157     */
158    public static int[] add(int[] a1, int[] a2)
159    {
160        return add(a1, a2, null);
161    }
162
163    /**
164     * Element-wise addition of two short arrays (result in output if defined)
165     * 
166     * @param out
167     *        the array receiving the result
168     */
169    public static short[] add(short[] a1, short[] a2, short[] out)
170    {
171        final short[] result = Array1DUtil.allocIfNull(out, a1.length);
172
173        for (int i = 0; i < a1.length; i++)
174            result[i] = (short) (a1[i] + a2[i]);
175
176        return result;
177    }
178
179    /**
180     * Element-wise addition of two short arrays
181     */
182    public static short[] add(short[] a1, short[] a2)
183    {
184        return add(a1, a2, null);
185    }
186
187    /**
188     * Element-wise addition of two byte arrays (result in output if defined)
189     * 
190     * @param out
191     *        the array receiving the result
192     */
193    public static byte[] add(byte[] a1, byte[] a2, byte[] out)
194    {
195        final byte[] result = Array1DUtil.allocIfNull(out, a1.length);
196
197        for (int i = 0; i < a1.length; i++)
198            result[i] = (byte) (a1[i] + a2[i]);
199
200        return result;
201    }
202
203    /**
204     * Element-wise addition of two byte arrays
205     */
206    public static byte[] add(byte[] a1, byte[] a2)
207    {
208        return add(a1, a2, null);
209    }
210
211    /**
212     * Adds a value to all elements of the given array
213     * 
214     * @param out
215     *        the array receiving the result
216     */
217    public static Object add(Object array, Number value, Object out)
218    {
219        switch (ArrayUtil.getDataType(array))
220        {
221            case BYTE:
222                return add((byte[]) array, value.byteValue(), (byte[]) out);
223            case SHORT:
224                return add((short[]) array, value.shortValue(), (short[]) out);
225            case INT:
226                return add((int[]) array, value.intValue(), (int[]) out);
227            case LONG:
228                return add((long[]) array, value.longValue(), (long[]) out);
229            case FLOAT:
230                return add((float[]) array, value.floatValue(), (float[]) out);
231            case DOUBLE:
232                return add((double[]) array, value.doubleValue(), (double[]) out);
233            default:
234                return null;
235        }
236    }
237
238    /**
239     * Adds a value to all elements of the given array
240     */
241    public static Object add(Object array, Number value)
242    {
243        return add(array, value, null);
244    }
245
246    /**
247     * Adds a value to all elements of the given double array
248     * 
249     * @param out
250     *        the array receiving the result
251     */
252    public static double[] add(double[] array, double value, double[] out)
253    {
254        final double[] result = Array1DUtil.allocIfNull(out, array.length);
255
256        for (int i = 0; i < array.length; i++)
257            result[i] = array[i] + value;
258
259        return result;
260    }
261
262    /**
263     * @deprecated use {@link #add(double[] , double , double[])} instead
264     */
265    @Deprecated
266    public static double[] add(double value, double[] array, double[] out)
267    {
268        return add(array, value, out);
269    }
270
271    /**
272     * Adds a value to all elements of the given double array
273     */
274    public static double[] add(double[] array, double value)
275    {
276        return add(array, value, null);
277    }
278
279    /**
280     * Adds a value to all elements of the given float array
281     * 
282     * @param out
283     *        the array receiving the result
284     */
285    public static float[] add(float[] array, float value, float[] out)
286    {
287        final float[] result = Array1DUtil.allocIfNull(out, array.length);
288
289        for (int i = 0; i < array.length; i++)
290            result[i] = array[i] + value;
291
292        return result;
293    }
294
295    /**
296     * Adds a value to all elements of the float given array
297     */
298    public static float[] add(float[] array, float value)
299    {
300        return add(array, value, null);
301    }
302
303    /**
304     * Adds a value to all elements of the given long array
305     * 
306     * @param out
307     *        the array receiving the result
308     */
309    public static long[] add(long[] array, long value, long[] out)
310    {
311        final long[] result = Array1DUtil.allocIfNull(out, array.length);
312
313        for (int i = 0; i < array.length; i++)
314            result[i] = array[i] + value;
315
316        return result;
317    }
318
319    /**
320     * Adds a value to all elements of the given long array
321     */
322    public static long[] add(long[] array, long value)
323    {
324        return add(array, value, null);
325    }
326
327    /**
328     * Adds a value to all elements of the given int array
329     * 
330     * @param out
331     *        the array receiving the result
332     */
333    public static int[] add(int[] array, int value, int[] out)
334    {
335        final int[] result = Array1DUtil.allocIfNull(out, array.length);
336
337        for (int i = 0; i < array.length; i++)
338            result[i] = array[i] + value;
339
340        return result;
341    }
342
343    /**
344     * Adds a value to all elements of the given int array
345     */
346    public static int[] add(int[] array, int value)
347    {
348        return add(array, value, null);
349    }
350
351    /**
352     * Adds a value to all elements of the given short array
353     * 
354     * @param out
355     *        the array receiving the result
356     */
357    public static short[] add(short[] array, short value, short[] out)
358    {
359        final short[] result = Array1DUtil.allocIfNull(out, array.length);
360
361        for (int i = 0; i < array.length; i++)
362            result[i] = (short) (array[i] + value);
363
364        return result;
365    }
366
367    /**
368     * Adds a value to all elements of the given short array
369     */
370    public static short[] add(short[] array, short value)
371    {
372        return add(array, value, null);
373    }
374
375    /**
376     * Adds a value to all elements of the given byte array
377     * 
378     * @param out
379     *        the array receiving the result
380     */
381    public static byte[] add(byte[] array, byte value, byte[] out)
382    {
383        final byte[] result = Array1DUtil.allocIfNull(out, array.length);
384
385        for (int i = 0; i < array.length; i++)
386            result[i] = (byte) (array[i] + value);
387
388        return result;
389    }
390
391    /**
392     * Adds a value to all elements of the given byte array
393     */
394    public static byte[] add(byte[] array, byte value)
395    {
396        return add(array, value, null);
397    }
398
399    /**
400     * Element-wise subtraction of two arrays
401     * 
402     * @param out
403     *        the array receiving the result
404     */
405    public static Object subtract(Object a1, Object a2, Object out)
406    {
407        switch (ArrayUtil.getDataType(a1))
408        {
409            case BYTE:
410                return subtract((byte[]) a1, (byte[]) a2, (byte[]) out);
411            case SHORT:
412                return subtract((short[]) a1, (short[]) a2, (short[]) out);
413            case INT:
414                return subtract((int[]) a1, (int[]) a2, (int[]) out);
415            case LONG:
416                return subtract((long[]) a1, (long[]) a2, (long[]) out);
417            case FLOAT:
418                return subtract((float[]) a1, (float[]) a2, (float[]) out);
419            case DOUBLE:
420                return subtract((double[]) a1, (double[]) a2, (double[]) out);
421            default:
422                return null;
423        }
424    }
425
426    /**
427     * Element-wise subtraction of two arrays
428     */
429    public static Object subtract(Object a1, Object a2)
430    {
431        return subtract(a1, a2, null);
432    }
433
434    /**
435     * Element-wise subtraction of two double arrays (result in output if defined)
436     * 
437     * @param out
438     *        the array receiving the result
439     */
440    public static double[] subtract(double[] a1, double[] a2, double[] out)
441    {
442        final double[] result = Array1DUtil.allocIfNull(out, a1.length);
443
444        for (int i = 0; i < a1.length; i++)
445            result[i] = a1[i] - a2[i];
446
447        return result;
448    }
449
450    /**
451     * Element-wise subtraction of two double arrays
452     */
453    public static double[] subtract(double[] a1, double[] a2)
454    {
455        return subtract(a1, a2, null);
456    }
457
458    /**
459     * Element-wise subtraction of two float arrays (result in output if defined)
460     * 
461     * @param out
462     *        the array receiving the result
463     */
464    public static float[] subtract(float[] a1, float[] a2, float[] out)
465    {
466        final float[] result = Array1DUtil.allocIfNull(out, a1.length);
467
468        for (int i = 0; i < a1.length; i++)
469            result[i] = a1[i] - a2[i];
470
471        return result;
472    }
473
474    /**
475     * Element-wise subtraction of two float arrays
476     */
477    public static float[] subtract(float[] a1, float[] a2)
478    {
479        return subtract(a1, a2, null);
480    }
481
482    /**
483     * Element-wise subtraction of two long arrays (result in output if defined)
484     * 
485     * @param out
486     *        the array receiving the result
487     */
488    public static long[] subtract(long[] a1, long[] a2, long[] out)
489    {
490        final long[] result = Array1DUtil.allocIfNull(out, a1.length);
491
492        for (int i = 0; i < a1.length; i++)
493            result[i] = a1[i] - a2[i];
494
495        return result;
496    }
497
498    /**
499     * Element-wise subtraction of two long arrays
500     */
501    public static long[] subtract(long[] a1, long[] a2)
502    {
503        return subtract(a1, a2, null);
504    }
505
506    /**
507     * Element-wise subtraction of two int arrays (result in output if defined)
508     * 
509     * @param out
510     *        the array receiving the result
511     */
512    public static int[] subtract(int[] a1, int[] a2, int[] out)
513    {
514        final int[] result = Array1DUtil.allocIfNull(out, a1.length);
515
516        for (int i = 0; i < a1.length; i++)
517            result[i] = a1[i] - a2[i];
518
519        return result;
520    }
521
522    /**
523     * Element-wise subtraction of two int arrays
524     */
525    public static int[] subtract(int[] a1, int[] a2)
526    {
527        return subtract(a1, a2, null);
528    }
529
530    /**
531     * Element-wise subtraction of two short arrays (result in output if defined)
532     * 
533     * @param out
534     *        the array receiving the result
535     */
536    public static short[] subtract(short[] a1, short[] a2, short[] out)
537    {
538        final short[] result = Array1DUtil.allocIfNull(out, a1.length);
539
540        for (int i = 0; i < a1.length; i++)
541            result[i] = (short) (a1[i] - a2[i]);
542
543        return result;
544    }
545
546    /**
547     * Element-wise subtraction of two short arrays
548     */
549    public static short[] subtract(short[] a1, short[] a2)
550    {
551        return subtract(a1, a2, null);
552    }
553
554    /**
555     * Element-wise subtraction of two byte arrays (result in output if defined)
556     * 
557     * @param out
558     *        the array receiving the result
559     */
560    public static byte[] subtract(byte[] a1, byte[] a2, byte[] out)
561    {
562        final byte[] result = Array1DUtil.allocIfNull(out, a1.length);
563
564        for (int i = 0; i < a1.length; i++)
565            result[i] = (byte) (a1[i] - a2[i]);
566
567        return result;
568    }
569
570    /**
571     * Element-wise subtraction of two byte arrays
572     */
573    public static byte[] subtract(byte[] a1, byte[] a2)
574    {
575        return subtract(a1, a2, null);
576    }
577
578    /**
579     * Subtracts a value to all elements of the given array
580     * 
581     * @param out
582     *        the array receiving the result
583     */
584    public static Object subtract(Object array, Number value, Object out)
585    {
586        switch (ArrayUtil.getDataType(array))
587        {
588            case BYTE:
589                return subtract((byte[]) array, value.byteValue(), (byte[]) out);
590            case SHORT:
591                return subtract((short[]) array, value.shortValue(), (short[]) out);
592            case INT:
593                return subtract((int[]) array, value.intValue(), (int[]) out);
594            case LONG:
595                return subtract((long[]) array, value.longValue(), (long[]) out);
596            case FLOAT:
597                return subtract((float[]) array, value.floatValue(), (float[]) out);
598            case DOUBLE:
599                return subtract((double[]) array, value.doubleValue(), (double[]) out);
600            default:
601                return null;
602        }
603    }
604
605    /**
606     * Subtracts a value to all elements of the given array
607     */
608    public static Object subtract(Object array, Number value)
609    {
610        return subtract(array, value, null);
611    }
612
613    /**
614     * Subtracts a value to all elements of the given double array
615     * 
616     * @param out
617     *        the array receiving the result
618     */
619    public static double[] subtract(double[] array, double value, double[] out)
620    {
621        final double[] result = Array1DUtil.allocIfNull(out, array.length);
622
623        for (int i = 0; i < array.length; i++)
624            result[i] = array[i] - value;
625
626        return result;
627    }
628
629    /**
630     * Subtracts a value to all elements of the given double array
631     */
632    public static double[] subtract(double[] array, double value)
633    {
634        return subtract(array, value, null);
635    }
636
637    /**
638     * Subtracts a value to all elements of the given float array
639     * 
640     * @param out
641     *        the array receiving the result
642     */
643    public static float[] subtract(float[] array, float value, float[] out)
644    {
645        final float[] result = Array1DUtil.allocIfNull(out, array.length);
646
647        for (int i = 0; i < array.length; i++)
648            result[i] = array[i] - value;
649
650        return result;
651    }
652
653    /**
654     * Subtracts a value to all elements of the float given array
655     */
656    public static float[] subtract(float[] array, float value)
657    {
658        return subtract(array, value, null);
659    }
660
661    /**
662     * Subtracts a value to all elements of the given long array
663     * 
664     * @param out
665     *        the array receiving the result
666     */
667    public static long[] subtract(long[] array, long value, long[] out)
668    {
669        final long[] result = Array1DUtil.allocIfNull(out, array.length);
670
671        for (int i = 0; i < array.length; i++)
672            result[i] = array[i] - value;
673
674        return result;
675    }
676
677    /**
678     * Subtracts a value to all elements of the given long array
679     */
680    public static long[] subtract(long[] array, long value)
681    {
682        return subtract(array, value, null);
683    }
684
685    /**
686     * Subtracts a value to all elements of the given int array
687     * 
688     * @param out
689     *        the array receiving the result
690     */
691    public static int[] subtract(int[] array, int value, int[] out)
692    {
693        final int[] result = Array1DUtil.allocIfNull(out, array.length);
694
695        for (int i = 0; i < array.length; i++)
696            result[i] = array[i] - value;
697
698        return result;
699    }
700
701    /**
702     * Subtracts a value to all elements of the given int array
703     */
704    public static int[] subtract(int[] array, int value)
705    {
706        return subtract(array, value, null);
707    }
708
709    /**
710     * Subtracts a value to all elements of the given short array
711     * 
712     * @param out
713     *        the array receiving the result
714     */
715    public static short[] subtract(short[] array, short value, short[] out)
716    {
717        final short[] result = Array1DUtil.allocIfNull(out, array.length);
718
719        for (int i = 0; i < array.length; i++)
720            result[i] = (short) (array[i] - value);
721
722        return result;
723    }
724
725    /**
726     * Subtracts a value to all elements of the given short array
727     */
728    public static short[] subtract(short[] array, short value)
729    {
730        return subtract(array, value, null);
731    }
732
733    /**
734     * Subtracts a value to all elements of the given byte array
735     * 
736     * @param out
737     *        the array receiving the result
738     */
739    public static byte[] subtract(byte[] array, byte value, byte[] out)
740    {
741        final byte[] result = Array1DUtil.allocIfNull(out, array.length);
742
743        for (int i = 0; i < array.length; i++)
744            result[i] = (byte) (array[i] - value);
745
746        return result;
747    }
748
749    /**
750     * Subtracts a value to all elements of the given byte array
751     */
752    public static byte[] subtract(byte[] array, byte value)
753    {
754        return subtract(array, value, null);
755    }
756
757    /**
758     * Subtracts a value by all elements of the given array
759     * 
760     * @param out
761     *        the array receiving the result
762     */
763    public static Object subtract(Number value, Object array, Object out)
764    {
765        switch (ArrayUtil.getDataType(array))
766        {
767            case BYTE:
768                return subtract(value.byteValue(), (byte[]) array, (byte[]) out);
769            case SHORT:
770                return subtract(value.shortValue(), (short[]) array, (short[]) out);
771            case INT:
772                return subtract(value.intValue(), (int[]) array, (int[]) out);
773            case LONG:
774                return subtract(value.longValue(), (long[]) array, (long[]) out);
775            case FLOAT:
776                return subtract(value.floatValue(), (float[]) array, (float[]) out);
777            case DOUBLE:
778                return subtract(value.doubleValue(), (double[]) array, (double[]) out);
779            default:
780                return null;
781        }
782    }
783
784    /**
785     * Subtracts a value by all elements of the given array
786     */
787    public static Object subtract(Number value, Object array)
788    {
789        return subtract(value, array, null);
790    }
791
792    /**
793     * Subtracts a value by all elements of the given double array
794     * 
795     * @param out
796     *        the array receiving the result
797     */
798    public static double[] subtract(double value, double[] array, double[] out)
799    {
800        final double[] result = Array1DUtil.allocIfNull(out, array.length);
801
802        for (int i = 0; i < array.length; i++)
803            result[i] = value - array[i];
804
805        return result;
806    }
807
808    /**
809     * Subtracts a value by all elements of the given double array
810     */
811    public static double[] subtract(double value, double[] array)
812    {
813        return subtract(array, value, null);
814    }
815
816    /**
817     * Subtracts a value by all elements of the given float array
818     * 
819     * @param out
820     *        the array receiving the result
821     */
822    public static float[] subtract(float value, float[] array, float[] out)
823    {
824        final float[] result = Array1DUtil.allocIfNull(out, array.length);
825
826        for (int i = 0; i < array.length; i++)
827            result[i] = value - array[i];
828
829        return result;
830    }
831
832    /**
833     * Subtracts a value by all elements of the float given array
834     */
835    public static float[] subtract(float value, float[] array)
836    {
837        return subtract(array, value, null);
838    }
839
840    /**
841     * Subtracts a value by all elements of the given long array
842     * 
843     * @param out
844     *        the array receiving the result
845     */
846    public static long[] subtract(long value, long[] array, long[] out)
847    {
848        final long[] result = Array1DUtil.allocIfNull(out, array.length);
849
850        for (int i = 0; i < array.length; i++)
851            result[i] = value - array[i];
852
853        return result;
854    }
855
856    /**
857     * Subtracts a value by all elements of the given long array
858     */
859    public static long[] subtract(long value, long[] array)
860    {
861        return subtract(array, value, null);
862    }
863
864    /**
865     * Subtracts a value by all elements of the given int array
866     * 
867     * @param out
868     *        the array receiving the result
869     */
870    public static int[] subtract(int value, int[] array, int[] out)
871    {
872        final int[] result = Array1DUtil.allocIfNull(out, array.length);
873
874        for (int i = 0; i < array.length; i++)
875            result[i] = value - array[i];
876
877        return result;
878    }
879
880    /**
881     * Subtracts a value by all elements of the given int array
882     */
883    public static int[] subtract(int value, int[] array)
884    {
885        return subtract(array, value, null);
886    }
887
888    /**
889     * Subtracts a value by all elements of the given short array
890     * 
891     * @param out
892     *        the array receiving the result
893     */
894    public static short[] subtract(short value, short[] array, short[] out)
895    {
896        final short[] result = Array1DUtil.allocIfNull(out, array.length);
897
898        for (int i = 0; i < array.length; i++)
899            result[i] = (short) (value - array[i]);
900
901        return result;
902    }
903
904    /**
905     * Subtracts a value by all elements of the given short array
906     */
907    public static short[] subtract(short value, short[] array)
908    {
909        return subtract(array, value, null);
910    }
911
912    /**
913     * Subtracts a value by all elements of the given byte array
914     * 
915     * @param out
916     *        the array receiving the result
917     */
918    public static byte[] subtract(byte value, byte[] array, byte[] out)
919    {
920        final byte[] result = Array1DUtil.allocIfNull(out, array.length);
921
922        for (int i = 0; i < array.length; i++)
923            result[i] = (byte) (value - array[i]);
924
925        return result;
926    }
927
928    /**
929     * Subtracts a value by all elements of the given byte array
930     */
931    public static byte[] subtract(byte value, byte[] array)
932    {
933        return subtract(array, value, null);
934    }
935
936    /**
937     * Element-wise multiplication of two arrays
938     * 
939     * @param out
940     *        the array receiving the result
941     */
942    public static Object multiply(Object a1, Object a2, Object out)
943    {
944        switch (ArrayUtil.getDataType(a1))
945        {
946            case BYTE:
947                return multiply((byte[]) a1, (byte[]) a2, (byte[]) out);
948            case SHORT:
949                return multiply((short[]) a1, (short[]) a2, (short[]) out);
950            case INT:
951                return multiply((int[]) a1, (int[]) a2, (int[]) out);
952            case LONG:
953                return multiply((long[]) a1, (long[]) a2, (long[]) out);
954            case FLOAT:
955                return multiply((float[]) a1, (float[]) a2, (float[]) out);
956            case DOUBLE:
957                return multiply((double[]) a1, (double[]) a2, (double[]) out);
958            default:
959                return null;
960        }
961    }
962
963    /**
964     * Element-wise multiplication of two arrays
965     */
966    public static Object multiply(Object a1, Object a2)
967    {
968        return multiply(a1, a2, null);
969    }
970
971    /**
972     * Element-wise multiplication of two double arrays (result in output if defined)
973     * 
974     * @param out
975     *        the array receiving the result
976     */
977    public static double[] multiply(double[] a1, double[] a2, double[] out)
978    {
979        final double[] result = Array1DUtil.allocIfNull(out, a1.length);
980
981        for (int i = 0; i < a1.length; i++)
982            result[i] = a1[i] * a2[i];
983
984        return result;
985    }
986
987    /**
988     * Element-wise multiplication of two double arrays
989     */
990    public static double[] multiply(double[] a1, double[] a2)
991    {
992        return multiply(a1, a2, null);
993    }
994
995    /**
996     * Element-wise multiplication of two float arrays (result in output if defined)
997     * 
998     * @param out
999     *        the array receiving the result
1000     */
1001    public static float[] multiply(float[] a1, float[] a2, float[] out)
1002    {
1003        final float[] result = Array1DUtil.allocIfNull(out, a1.length);
1004
1005        for (int i = 0; i < a1.length; i++)
1006            result[i] = a1[i] * a2[i];
1007
1008        return result;
1009    }
1010
1011    /**
1012     * Element-wise multiplication of two float arrays
1013     */
1014    public static float[] multiply(float[] a1, float[] a2)
1015    {
1016        return multiply(a1, a2, null);
1017    }
1018
1019    /**
1020     * Element-wise multiplication of two long arrays (result in output if defined)
1021     * 
1022     * @param out
1023     *        the array receiving the result
1024     */
1025    public static long[] multiply(long[] a1, long[] a2, long[] out)
1026    {
1027        final long[] result = Array1DUtil.allocIfNull(out, a1.length);
1028
1029        for (int i = 0; i < a1.length; i++)
1030            result[i] = a1[i] * a2[i];
1031
1032        return result;
1033    }
1034
1035    /**
1036     * Element-wise multiplication of two long arrays
1037     */
1038    public static long[] multiply(long[] a1, long[] a2)
1039    {
1040        return multiply(a1, a2, null);
1041    }
1042
1043    /**
1044     * Element-wise multiplication of two int arrays (result in output if defined)
1045     * 
1046     * @param out
1047     *        the array receiving the result
1048     */
1049    public static int[] multiply(int[] a1, int[] a2, int[] out)
1050    {
1051        final int[] result = Array1DUtil.allocIfNull(out, a1.length);
1052
1053        for (int i = 0; i < a1.length; i++)
1054            result[i] = a1[i] * a2[i];
1055
1056        return result;
1057    }
1058
1059    /**
1060     * Element-wise multiplication of two int arrays
1061     */
1062    public static int[] multiply(int[] a1, int[] a2)
1063    {
1064        return multiply(a1, a2, null);
1065    }
1066
1067    /**
1068     * Element-wise multiplication of two short arrays (result in output if defined)
1069     * 
1070     * @param out
1071     *        the array receiving the result
1072     */
1073    public static short[] multiply(short[] a1, short[] a2, short[] out)
1074    {
1075        final short[] result = Array1DUtil.allocIfNull(out, a1.length);
1076
1077        for (int i = 0; i < a1.length; i++)
1078            result[i] = (short) (a1[i] * a2[i]);
1079
1080        return result;
1081    }
1082
1083    /**
1084     * Element-wise multiplication of two short arrays
1085     */
1086    public static short[] multiply(short[] a1, short[] a2)
1087    {
1088        return multiply(a1, a2, null);
1089    }
1090
1091    /**
1092     * Element-wise multiplication of two byte arrays (result in output if defined)
1093     * 
1094     * @param out
1095     *        the array receiving the result
1096     */
1097    public static byte[] multiply(byte[] a1, byte[] a2, byte[] out)
1098    {
1099        final byte[] result = Array1DUtil.allocIfNull(out, a1.length);
1100
1101        for (int i = 0; i < a1.length; i++)
1102            result[i] = (byte) (a1[i] * a2[i]);
1103
1104        return result;
1105    }
1106
1107    /**
1108     * Element-wise multiplication of two byte arrays
1109     */
1110    public static byte[] multiply(byte[] a1, byte[] a2)
1111    {
1112        return multiply(a1, a2, null);
1113    }
1114
1115    /**
1116     * Multiplies a value to all elements of the given array
1117     * 
1118     * @param out
1119     *        the array receiving the result
1120     */
1121    public static Object multiply(Object array, Number value, Object out)
1122    {
1123        switch (ArrayUtil.getDataType(array))
1124        {
1125            case BYTE:
1126                return multiply((byte[]) array, value.byteValue(), (byte[]) out);
1127            case SHORT:
1128                return multiply((short[]) array, value.shortValue(), (short[]) out);
1129            case INT:
1130                return multiply((int[]) array, value.intValue(), (int[]) out);
1131            case LONG:
1132                return multiply((long[]) array, value.longValue(), (long[]) out);
1133            case FLOAT:
1134                return multiply((float[]) array, value.floatValue(), (float[]) out);
1135            case DOUBLE:
1136                return multiply((double[]) array, value.doubleValue(), (double[]) out);
1137            default:
1138                return null;
1139        }
1140    }
1141
1142    /**
1143     * Multiplies a value to all elements of the given array
1144     */
1145    public static Object multiply(Object array, Number value)
1146    {
1147        return multiply(array, value, null);
1148    }
1149
1150    /**
1151     * Multiplies a value to all elements of the given double array
1152     * 
1153     * @param out
1154     *        the array receiving the result
1155     */
1156    public static double[] multiply(double[] array, double value, double[] out)
1157    {
1158        final double[] result = Array1DUtil.allocIfNull(out, array.length);
1159
1160        for (int i = 0; i < array.length; i++)
1161            result[i] = array[i] * value;
1162
1163        return result;
1164    }
1165
1166    /**
1167     * @deprecated use {@link #multiply(double[] , double , double[])} instead
1168     */
1169    @Deprecated
1170    public static double[] multiply(double value, double[] array, double[] out)
1171    {
1172        return multiply(array, value, out);
1173    }
1174
1175    /**
1176     * Multiplies a value to all elements of the given double array
1177     */
1178    public static double[] multiply(double[] array, double value)
1179    {
1180        return multiply(array, value, null);
1181    }
1182
1183    /**
1184     * Multiplies a value to all elements of the given float array
1185     * 
1186     * @param out
1187     *        the array receiving the result
1188     */
1189    public static float[] multiply(float[] array, float value, float[] out)
1190    {
1191        final float[] result = Array1DUtil.allocIfNull(out, array.length);
1192
1193        for (int i = 0; i < array.length; i++)
1194            result[i] = array[i] * value;
1195
1196        return result;
1197    }
1198
1199    /**
1200     * Multiplies a value to all elements of the float given array
1201     */
1202    public static float[] multiply(float[] array, float value)
1203    {
1204        return multiply(array, value, null);
1205    }
1206
1207    /**
1208     * Multiplies a value to all elements of the given long array
1209     * 
1210     * @param out
1211     *        the array receiving the result
1212     */
1213    public static long[] multiply(long[] array, long value, long[] out)
1214    {
1215        final long[] result = Array1DUtil.allocIfNull(out, array.length);
1216
1217        for (int i = 0; i < array.length; i++)
1218            result[i] = array[i] * value;
1219
1220        return result;
1221    }
1222
1223    /**
1224     * Multiplies a value to all elements of the given long array
1225     */
1226    public static long[] multiply(long[] array, long value)
1227    {
1228        return multiply(array, value, null);
1229    }
1230
1231    /**
1232     * Multiplies a value to all elements of the given int array
1233     * 
1234     * @param out
1235     *        the array receiving the result
1236     */
1237    public static int[] multiply(int[] array, int value, int[] out)
1238    {
1239        final int[] result = Array1DUtil.allocIfNull(out, array.length);
1240
1241        for (int i = 0; i < array.length; i++)
1242            result[i] = array[i] * value;
1243
1244        return result;
1245    }
1246
1247    /**
1248     * Multiplies a value to all elements of the given int array
1249     */
1250    public static int[] multiply(int[] array, int value)
1251    {
1252        return multiply(array, value, null);
1253    }
1254
1255    /**
1256     * Multiplies a value to all elements of the given short array
1257     * 
1258     * @param out
1259     *        the array receiving the result
1260     */
1261    public static short[] multiply(short[] array, short value, short[] out)
1262    {
1263        final short[] result = Array1DUtil.allocIfNull(out, array.length);
1264
1265        for (int i = 0; i < array.length; i++)
1266            result[i] = (short) (array[i] * value);
1267
1268        return result;
1269    }
1270
1271    /**
1272     * Multiplies a value to all elements of the given short array
1273     */
1274    public static short[] multiply(short[] array, short value)
1275    {
1276        return multiply(array, value, null);
1277    }
1278
1279    /**
1280     * Multiplies a value to all elements of the given byte array
1281     * 
1282     * @param out
1283     *        the array receiving the result
1284     */
1285    public static byte[] multiply(byte[] array, byte value, byte[] out)
1286    {
1287        final byte[] result = Array1DUtil.allocIfNull(out, array.length);
1288
1289        for (int i = 0; i < array.length; i++)
1290            result[i] = (byte) (array[i] * value);
1291
1292        return result;
1293    }
1294
1295    /**
1296     * Multiplies a value to all elements of the given byte array
1297     */
1298    public static byte[] multiply(byte[] array, byte value)
1299    {
1300        return multiply(array, value, null);
1301    }
1302
1303    /**
1304     * Element-wise division of two arrays
1305     * 
1306     * @param out
1307     *        the array receiving the result
1308     */
1309    public static Object divide(Object a1, Object a2, Object out)
1310    {
1311        switch (ArrayUtil.getDataType(a1))
1312        {
1313            case BYTE:
1314                return divide((byte[]) a1, (byte[]) a2, (byte[]) out);
1315            case SHORT:
1316                return divide((short[]) a1, (short[]) a2, (short[]) out);
1317            case INT:
1318                return divide((int[]) a1, (int[]) a2, (int[]) out);
1319            case LONG:
1320                return divide((long[]) a1, (long[]) a2, (long[]) out);
1321            case FLOAT:
1322                return divide((float[]) a1, (float[]) a2, (float[]) out);
1323            case DOUBLE:
1324                return divide((double[]) a1, (double[]) a2, (double[]) out);
1325            default:
1326                return null;
1327        }
1328    }
1329
1330    /**
1331     * Element-wise division of two arrays
1332     */
1333    public static Object divide(Object a1, Object a2)
1334    {
1335        return divide(a1, a2, null);
1336    }
1337
1338    /**
1339     * Element-wise division of two double arrays (result in output if defined)
1340     * 
1341     * @param out
1342     *        the array receiving the result
1343     */
1344    public static double[] divide(double[] a1, double[] a2, double[] out)
1345    {
1346        final double[] result = Array1DUtil.allocIfNull(out, a1.length);
1347
1348        for (int i = 0; i < a1.length; i++)
1349            result[i] = a1[i] / a2[i];
1350
1351        return result;
1352    }
1353
1354    /**
1355     * Element-wise division of two double arrays
1356     */
1357    public static double[] divide(double[] a1, double[] a2)
1358    {
1359        return divide(a1, a2, null);
1360    }
1361
1362    /**
1363     * Element-wise division of two float arrays (result in output if defined)
1364     * 
1365     * @param out
1366     *        the array receiving the result
1367     */
1368    public static float[] divide(float[] a1, float[] a2, float[] out)
1369    {
1370        final float[] result = Array1DUtil.allocIfNull(out, a1.length);
1371
1372        for (int i = 0; i < a1.length; i++)
1373            result[i] = a1[i] / a2[i];
1374
1375        return result;
1376    }
1377
1378    /**
1379     * Element-wise division of two float arrays
1380     */
1381    public static float[] divide(float[] a1, float[] a2)
1382    {
1383        return divide(a1, a2, null);
1384    }
1385
1386    /**
1387     * Element-wise division of two long arrays (result in output if defined)
1388     * 
1389     * @param out
1390     *        the array receiving the result
1391     */
1392    public static long[] divide(long[] a1, long[] a2, long[] out)
1393    {
1394        final long[] result = Array1DUtil.allocIfNull(out, a1.length);
1395
1396        for (int i = 0; i < a1.length; i++)
1397            result[i] = a1[i] / a2[i];
1398
1399        return result;
1400    }
1401
1402    /**
1403     * Element-wise division of two long arrays
1404     */
1405    public static long[] divide(long[] a1, long[] a2)
1406    {
1407        return divide(a1, a2, null);
1408    }
1409
1410    /**
1411     * Element-wise division of two int arrays (result in output if defined)
1412     * 
1413     * @param out
1414     *        the array receiving the result
1415     */
1416    public static int[] divide(int[] a1, int[] a2, int[] out)
1417    {
1418        final int[] result = Array1DUtil.allocIfNull(out, a1.length);
1419
1420        for (int i = 0; i < a1.length; i++)
1421            result[i] = a1[i] / a2[i];
1422
1423        return result;
1424    }
1425
1426    /**
1427     * Element-wise division of two int arrays
1428     */
1429    public static int[] divide(int[] a1, int[] a2)
1430    {
1431        return divide(a1, a2, null);
1432    }
1433
1434    /**
1435     * Element-wise division of two short arrays (result in output if defined)
1436     * 
1437     * @param out
1438     *        the array receiving the result
1439     */
1440    public static short[] divide(short[] a1, short[] a2, short[] out)
1441    {
1442        final short[] result = Array1DUtil.allocIfNull(out, a1.length);
1443
1444        for (int i = 0; i < a1.length; i++)
1445            result[i] = (short) (a1[i] / a2[i]);
1446
1447        return result;
1448    }
1449
1450    /**
1451     * Element-wise division of two short arrays
1452     */
1453    public static short[] divide(short[] a1, short[] a2)
1454    {
1455        return divide(a1, a2, null);
1456    }
1457
1458    /**
1459     * Element-wise division of two byte arrays (result in output if defined)
1460     * 
1461     * @param out
1462     *        the array receiving the result
1463     */
1464    public static byte[] divide(byte[] a1, byte[] a2, byte[] out)
1465    {
1466        final byte[] result = Array1DUtil.allocIfNull(out, a1.length);
1467
1468        for (int i = 0; i < a1.length; i++)
1469            result[i] = (byte) (a1[i] / a2[i]);
1470
1471        return result;
1472    }
1473
1474    /**
1475     * Element-wise division of two byte arrays
1476     */
1477    public static byte[] divide(byte[] a1, byte[] a2)
1478    {
1479        return divide(a1, a2, null);
1480    }
1481
1482    /**
1483     * Divides a value to all elements of the given array
1484     * 
1485     * @param out
1486     *        the array receiving the result
1487     */
1488    public static Object divide(Object array, Number value, Object out)
1489    {
1490        switch (ArrayUtil.getDataType(array))
1491        {
1492            case BYTE:
1493                return divide((byte[]) array, value.byteValue(), (byte[]) out);
1494            case SHORT:
1495                return divide((short[]) array, value.shortValue(), (short[]) out);
1496            case INT:
1497                return divide((int[]) array, value.intValue(), (int[]) out);
1498            case LONG:
1499                return divide((long[]) array, value.longValue(), (long[]) out);
1500            case FLOAT:
1501                return divide((float[]) array, value.floatValue(), (float[]) out);
1502            case DOUBLE:
1503                return divide((double[]) array, value.doubleValue(), (double[]) out);
1504            default:
1505                return null;
1506        }
1507    }
1508
1509    /**
1510     * Divides a value to all elements of the given array
1511     */
1512    public static Object divide(Object array, Number value)
1513    {
1514        return divide(array, value, null);
1515    }
1516
1517    /**
1518     * Divides a value to all elements of the given double array
1519     * 
1520     * @param out
1521     *        the array receiving the result
1522     */
1523    public static double[] divide(double[] array, double value, double[] out)
1524    {
1525        final double[] result = Array1DUtil.allocIfNull(out, array.length);
1526
1527        for (int i = 0; i < array.length; i++)
1528            result[i] = array[i] / value;
1529
1530        return result;
1531    }
1532
1533    /**
1534     * Divides a value to all elements of the given double array
1535     */
1536    public static double[] divide(double[] array, double value)
1537    {
1538        return divide(array, value, null);
1539    }
1540
1541    /**
1542     * Divides a value to all elements of the given float array
1543     * 
1544     * @param out
1545     *        the array receiving the result
1546     */
1547    public static float[] divide(float[] array, float value, float[] out)
1548    {
1549        final float[] result = Array1DUtil.allocIfNull(out, array.length);
1550
1551        for (int i = 0; i < array.length; i++)
1552            result[i] = array[i] / value;
1553
1554        return result;
1555    }
1556
1557    /**
1558     * Divides a value to all elements of the float given array
1559     */
1560    public static float[] divide(float[] array, float value)
1561    {
1562        return divide(array, value, null);
1563    }
1564
1565    /**
1566     * Divides a value to all elements of the given long array
1567     * 
1568     * @param out
1569     *        the array receiving the result
1570     */
1571    public static long[] divide(long[] array, long value, long[] out)
1572    {
1573        final long[] result = Array1DUtil.allocIfNull(out, array.length);
1574
1575        for (int i = 0; i < array.length; i++)
1576            result[i] = array[i] / value;
1577
1578        return result;
1579    }
1580
1581    /**
1582     * Divides a value to all elements of the given long array
1583     */
1584    public static long[] divide(long[] array, long value)
1585    {
1586        return divide(array, value, null);
1587    }
1588
1589    /**
1590     * Divides a value to all elements of the given int array
1591     * 
1592     * @param out
1593     *        the array receiving the result
1594     */
1595    public static int[] divide(int[] array, int value, int[] out)
1596    {
1597        final int[] result = Array1DUtil.allocIfNull(out, array.length);
1598
1599        for (int i = 0; i < array.length; i++)
1600            result[i] = array[i] / value;
1601
1602        return result;
1603    }
1604
1605    /**
1606     * Divides a value to all elements of the given int array
1607     */
1608    public static int[] divide(int[] array, int value)
1609    {
1610        return divide(array, value, null);
1611    }
1612
1613    /**
1614     * Divides a value to all elements of the given short array
1615     * 
1616     * @param out
1617     *        the array receiving the result
1618     */
1619    public static short[] divide(short[] array, short value, short[] out)
1620    {
1621        final short[] result = Array1DUtil.allocIfNull(out, array.length);
1622
1623        for (int i = 0; i < array.length; i++)
1624            result[i] = (short) (array[i] / value);
1625
1626        return result;
1627    }
1628
1629    /**
1630     * Divides a value to all elements of the given short array
1631     */
1632    public static short[] divide(short[] array, short value)
1633    {
1634        return divide(array, value, null);
1635    }
1636
1637    /**
1638     * Divides a value to all elements of the given byte array
1639     * 
1640     * @param out
1641     *        the array receiving the result
1642     */
1643    public static byte[] divide(byte[] array, byte value, byte[] out)
1644    {
1645        final byte[] result = Array1DUtil.allocIfNull(out, array.length);
1646
1647        for (int i = 0; i < array.length; i++)
1648            result[i] = (byte) (array[i] / value);
1649
1650        return result;
1651    }
1652
1653    /**
1654     * Divides a value to all elements of the given byte array
1655     */
1656    public static byte[] divide(byte[] array, byte value)
1657    {
1658        return divide(array, value, null);
1659    }
1660
1661    /**
1662     * Divides a value by all elements of the given array
1663     * 
1664     * @param out
1665     *        the array receiving the result
1666     */
1667    public static Object divide(Number value, Object array, Object out)
1668    {
1669        switch (ArrayUtil.getDataType(array))
1670        {
1671            case BYTE:
1672                return divide(value.byteValue(), (byte[]) array, (byte[]) out);
1673            case SHORT:
1674                return divide(value.shortValue(), (short[]) array, (short[]) out);
1675            case INT:
1676                return divide(value.intValue(), (int[]) array, (int[]) out);
1677            case LONG:
1678                return divide(value.longValue(), (long[]) array, (long[]) out);
1679            case FLOAT:
1680                return divide(value.floatValue(), (float[]) array, (float[]) out);
1681            case DOUBLE:
1682                return divide(value.doubleValue(), (double[]) array, (double[]) out);
1683            default:
1684                return null;
1685        }
1686    }
1687
1688    /**
1689     * Divides a value by all elements of the given array
1690     */
1691    public static Object divide(Number value, Object array)
1692    {
1693        return divide(value, array, null);
1694    }
1695
1696    /**
1697     * Subtracts a value by all elements of the given double array
1698     * 
1699     * @param out
1700     *        the array receiving the result
1701     */
1702    public static double[] divide(double value, double[] array, double[] out)
1703    {
1704        final double[] result = Array1DUtil.allocIfNull(out, array.length);
1705
1706        for (int i = 0; i < array.length; i++)
1707            result[i] = value / array[i];
1708
1709        return result;
1710    }
1711
1712    /**
1713     * Divides a value by all elements of the given double array
1714     */
1715    public static double[] divide(double value, double[] array)
1716    {
1717        return divide(array, value, null);
1718    }
1719
1720    /**
1721     * Divides a value by all elements of the given float array
1722     * 
1723     * @param out
1724     *        the array receiving the result
1725     */
1726    public static float[] divide(float value, float[] array, float[] out)
1727    {
1728        final float[] result = Array1DUtil.allocIfNull(out, array.length);
1729
1730        for (int i = 0; i < array.length; i++)
1731            result[i] = value / array[i];
1732
1733        return result;
1734    }
1735
1736    /**
1737     * Divides a value by all elements of the float given array
1738     */
1739    public static float[] divide(float value, float[] array)
1740    {
1741        return divide(array, value, null);
1742    }
1743
1744    /**
1745     * Divides a value by all elements of the given long array
1746     * 
1747     * @param out
1748     *        the array receiving the result
1749     */
1750    public static long[] divide(long value, long[] array, long[] out)
1751    {
1752        final long[] result = Array1DUtil.allocIfNull(out, array.length);
1753
1754        for (int i = 0; i < array.length; i++)
1755            result[i] = value / array[i];
1756
1757        return result;
1758    }
1759
1760    /**
1761     * Divides a value by all elements of the given long array
1762     */
1763    public static long[] divide(long value, long[] array)
1764    {
1765        return divide(array, value, null);
1766    }
1767
1768    /**
1769     * Divides a value by all elements of the given int array
1770     * 
1771     * @param out
1772     *        the array receiving the result
1773     */
1774    public static int[] divide(int value, int[] array, int[] out)
1775    {
1776        final int[] result = Array1DUtil.allocIfNull(out, array.length);
1777
1778        for (int i = 0; i < array.length; i++)
1779            result[i] = value / array[i];
1780
1781        return result;
1782    }
1783
1784    /**
1785     * Divides a value by all elements of the given int array
1786     */
1787    public static int[] divide(int value, int[] array)
1788    {
1789        return divide(array, value, null);
1790    }
1791
1792    /**
1793     * Divides a value by all elements of the given short array
1794     * 
1795     * @param out
1796     *        the array receiving the result
1797     */
1798    public static short[] divide(short value, short[] array, short[] out)
1799    {
1800        final short[] result = Array1DUtil.allocIfNull(out, array.length);
1801
1802        for (int i = 0; i < array.length; i++)
1803            result[i] = (short) (value / array[i]);
1804
1805        return result;
1806    }
1807
1808    /**
1809     * Divides a value by all elements of the given short array
1810     */
1811    public static short[] divide(short value, short[] array)
1812    {
1813        return divide(array, value, null);
1814    }
1815
1816    /**
1817     * Divides a value by all elements of the given byte array
1818     * 
1819     * @param out
1820     *        the array receiving the result
1821     */
1822    public static byte[] divide(byte value, byte[] array, byte[] out)
1823    {
1824        final byte[] result = Array1DUtil.allocIfNull(out, array.length);
1825
1826        for (int i = 0; i < array.length; i++)
1827            result[i] = (byte) (value / array[i]);
1828
1829        return result;
1830    }
1831
1832    /**
1833     * Divides a value by all elements of the given byte array
1834     */
1835    public static byte[] divide(byte value, byte[] array)
1836    {
1837        return divide(array, value, null);
1838    }
1839
1840    /**
1841     * Computes the absolute value of each value of the given array
1842     * 
1843     * @param overwrite
1844     *        true : overwrites the input data<br>
1845     *        false: returns the result in a new array
1846     */
1847    public static Object abs(Object array, boolean overwrite)
1848    {
1849        switch (ArrayUtil.getDataType(array))
1850        {
1851            case BYTE:
1852                return abs((byte[]) array, overwrite);
1853            case SHORT:
1854                return abs((short[]) array, overwrite);
1855            case INT:
1856                return abs((int[]) array, overwrite);
1857            case LONG:
1858                return abs((long[]) array, overwrite);
1859            case FLOAT:
1860                return abs((float[]) array, overwrite);
1861            case DOUBLE:
1862                return abs((double[]) array, overwrite);
1863            default:
1864                return null;
1865        }
1866    }
1867
1868    /**
1869     * Computes the absolute value of each value of the given double array
1870     * 
1871     * @param overwrite
1872     *        true overwrites the input data, false returns the result in a new structure
1873     */
1874    public static double[] abs(double[] input, boolean overwrite)
1875    {
1876        final double[] result = overwrite ? input : new double[input.length];
1877
1878        for (int i = 0; i < input.length; i++)
1879            result[i] = Math.abs(input[i]);
1880
1881        return result;
1882    }
1883
1884    /**
1885     * Computes the absolute value of each value of the given float array
1886     * 
1887     * @param overwrite
1888     *        true overwrites the input data, false returns the result in a new structure
1889     */
1890    public static float[] abs(float[] input, boolean overwrite)
1891    {
1892        final float[] result = overwrite ? input : new float[input.length];
1893
1894        for (int i = 0; i < input.length; i++)
1895            result[i] = Math.abs(input[i]);
1896
1897        return result;
1898    }
1899
1900    /**
1901     * Computes the absolute value of each value of the given long array
1902     * 
1903     * @param overwrite
1904     *        true overwrites the input data, false returns the result in a new structure
1905     */
1906    public static long[] abs(long[] input, boolean overwrite)
1907    {
1908        final long[] result = overwrite ? input : new long[input.length];
1909
1910        for (int i = 0; i < input.length; i++)
1911            result[i] = Math.abs(input[i]);
1912
1913        return result;
1914    }
1915
1916    /**
1917     * Computes the absolute value of each value of the given int array
1918     * 
1919     * @param overwrite
1920     *        true overwrites the input data, false returns the result in a new structure
1921     */
1922    public static int[] abs(int[] input, boolean overwrite)
1923    {
1924        final int[] result = overwrite ? input : new int[input.length];
1925
1926        for (int i = 0; i < input.length; i++)
1927            result[i] = Math.abs(input[i]);
1928
1929        return result;
1930    }
1931
1932    /**
1933     * Computes the absolute value of each value of the given short array
1934     * 
1935     * @param overwrite
1936     *        true overwrites the input data, false returns the result in a new structure
1937     */
1938    public static short[] abs(short[] input, boolean overwrite)
1939    {
1940        final short[] result = overwrite ? input : new short[input.length];
1941
1942        for (int i = 0; i < input.length; i++)
1943            result[i] = (short) Math.abs(input[i]);
1944
1945        return result;
1946    }
1947
1948    /**
1949     * Computes the absolute value of each value of the given byte array
1950     * 
1951     * @param overwrite
1952     *        true overwrites the input data, false returns the result in a new structure
1953     */
1954    public static byte[] abs(byte[] input, boolean overwrite)
1955    {
1956        final byte[] result = overwrite ? input : new byte[input.length];
1957
1958        for (int i = 0; i < input.length; i++)
1959            result[i] = (byte) Math.abs(input[i]);
1960
1961        return result;
1962    }
1963
1964    /**
1965     * Find the minimum value of a generic array
1966     * 
1967     * @param array
1968     *        an array
1969     * @param signed
1970     *        signed / unsigned flag
1971     * @return the min value of the array
1972     */
1973    public static double min(Object array, boolean signed)
1974    {
1975        switch (ArrayUtil.getDataType(array))
1976        {
1977            case BYTE:
1978                return min((byte[]) array, signed);
1979            case SHORT:
1980                return min((short[]) array, signed);
1981            case INT:
1982                return min((int[]) array, signed);
1983            case LONG:
1984                return min((long[]) array, signed);
1985            case FLOAT:
1986                return min((float[]) array);
1987            case DOUBLE:
1988                return min((double[]) array);
1989            default:
1990                return 0;
1991        }
1992    }
1993
1994    /**
1995     * Find the minimum value of an array
1996     * 
1997     * @param array
1998     *        an array
1999     * @param signed
2000     *        signed / unsigned flag
2001     * @return the min value of the array
2002     */
2003    public static int min(byte[] array, boolean signed)
2004    {
2005        if (signed)
2006        {
2007            byte min = Byte.MAX_VALUE;
2008
2009            for (byte v : array)
2010                if (v < min)
2011                    min = v;
2012
2013            return min;
2014        }
2015
2016        int min = Integer.MAX_VALUE;
2017
2018        for (int i = 0; i < array.length; i++)
2019        {
2020            final int v = TypeUtil.unsign(array[i]);
2021            if (v < min)
2022                min = v;
2023        }
2024
2025        return min;
2026    }
2027
2028    /**
2029     * Find the minimum value of an array
2030     * 
2031     * @param array
2032     *        an array
2033     * @param signed
2034     *        signed / unsigned flag
2035     * @return the min value of the array
2036     */
2037    public static int min(short[] array, boolean signed)
2038    {
2039        if (signed)
2040        {
2041            short min = Short.MAX_VALUE;
2042
2043            for (short v : array)
2044                if (v < min)
2045                    min = v;
2046
2047            return min;
2048        }
2049
2050        int min = Integer.MAX_VALUE;
2051
2052        for (int i = 0; i < array.length; i++)
2053        {
2054            final int v = TypeUtil.unsign(array[i]);
2055            if (v < min)
2056                min = v;
2057        }
2058
2059        return min;
2060    }
2061
2062    /**
2063     * Find the minimum value of an array
2064     * 
2065     * @param array
2066     *        an array
2067     * @param signed
2068     *        signed / unsigned flag
2069     * @return the min value of the array
2070     */
2071    public static long min(int[] array, boolean signed)
2072    {
2073        if (signed)
2074        {
2075            int min = Integer.MAX_VALUE;
2076
2077            for (int v : array)
2078                if (v < min)
2079                    min = v;
2080
2081            return min;
2082        }
2083
2084        long min = Long.MAX_VALUE;
2085
2086        for (int i = 0; i < array.length; i++)
2087        {
2088            final long v = TypeUtil.unsign(array[i]);
2089            if (v < min)
2090                min = v;
2091        }
2092
2093        return min;
2094    }
2095
2096    /**
2097     * Find the minimum value of an array
2098     * 
2099     * @param array
2100     *        an array
2101     * @param signed
2102     *        signed / unsigned flag
2103     * @return the min value of the array
2104     */
2105    public static long min(long[] array, boolean signed)
2106    {
2107        if (signed)
2108        {
2109            long min = Integer.MAX_VALUE;
2110
2111            for (long v : array)
2112                if (v < min)
2113                    min = v;
2114
2115            return min;
2116        }
2117
2118        double min = Long.MAX_VALUE;
2119
2120        for (int i = 0; i < array.length; i++)
2121        {
2122            final double v = TypeUtil.unsign(array[i]);
2123            // need to compare in double
2124            if (v < min)
2125                min = v;
2126        }
2127
2128        // convert back to long (need to be interpreted as unsigned)
2129        return TypeUtil.toLong(min);
2130    }
2131
2132    /**
2133     * Find the minimum value of an array
2134     * 
2135     * @param array
2136     *        an array
2137     * @return the min value of the array
2138     */
2139    public static float min(float[] array)
2140    {
2141        float min = Float.MAX_VALUE;
2142
2143        for (float v : array)
2144            if (v < min)
2145                min = v;
2146
2147        return min;
2148    }
2149
2150    /**
2151     * Find the minimum value of an array
2152     * 
2153     * @param array
2154     *        an array
2155     * @return the min value of the array
2156     */
2157    public static double min(double[] array)
2158    {
2159        double min = Double.MAX_VALUE;
2160
2161        for (double v : array)
2162            if (v < min)
2163                min = v;
2164
2165        return min;
2166    }
2167
2168    /**
2169     * Find the maximum value of a generic array
2170     * 
2171     * @param array
2172     *        an array
2173     * @param signed
2174     *        signed / unsigned flag
2175     * @return the max value of the array
2176     */
2177    public static double max(Object array, boolean signed)
2178    {
2179        switch (ArrayUtil.getDataType(array))
2180        {
2181            case BYTE:
2182                return max((byte[]) array, signed);
2183            case SHORT:
2184                return max((short[]) array, signed);
2185            case INT:
2186                return max((int[]) array, signed);
2187            case LONG:
2188                return max((long[]) array, signed);
2189            case FLOAT:
2190                return max((float[]) array);
2191            case DOUBLE:
2192                return max((double[]) array);
2193            default:
2194                return 0;
2195        }
2196    }
2197
2198    /**
2199     * Find the maximum value of an array
2200     * 
2201     * @param array
2202     *        an array
2203     * @param signed
2204     *        signed / unsigned flag
2205     * @return the max value of the array
2206     */
2207    public static int max(byte[] array, boolean signed)
2208    {
2209        if (signed)
2210        {
2211            byte max = Byte.MIN_VALUE;
2212
2213            for (byte v : array)
2214                if (v > max)
2215                    max = v;
2216
2217            return max;
2218        }
2219
2220        int max = Integer.MIN_VALUE;
2221
2222        for (int i = 0; i < array.length; i++)
2223        {
2224            final int v = TypeUtil.unsign(array[i]);
2225            if (v > max)
2226                max = v;
2227        }
2228
2229        return max;
2230    }
2231
2232    /**
2233     * Find the maximum value of an array
2234     * 
2235     * @param array
2236     *        an array
2237     * @param signed
2238     *        signed / unsigned flag
2239     * @return the max value of the array
2240     */
2241    public static int max(short[] array, boolean signed)
2242    {
2243        if (signed)
2244        {
2245            short max = Short.MIN_VALUE;
2246
2247            for (short v : array)
2248                if (v > max)
2249                    max = v;
2250
2251            return max;
2252        }
2253
2254        int max = Integer.MIN_VALUE;
2255
2256        for (int i = 0; i < array.length; i++)
2257        {
2258            final int v = TypeUtil.unsign(array[i]);
2259            if (v > max)
2260                max = v;
2261        }
2262
2263        return max;
2264    }
2265
2266    /**
2267     * Find the maximum value of an array
2268     * 
2269     * @param array
2270     *        an array
2271     * @param signed
2272     *        signed / unsigned flag
2273     * @return the max value of the array
2274     */
2275    public static long max(int[] array, boolean signed)
2276    {
2277        if (signed)
2278        {
2279            int max = Integer.MIN_VALUE;
2280
2281            for (int v : array)
2282                if (v > max)
2283                    max = v;
2284
2285            return max;
2286        }
2287
2288        long max = Long.MIN_VALUE;
2289
2290        for (int i = 0; i < array.length; i++)
2291        {
2292            final long v = TypeUtil.unsign(array[i]);
2293            if (v > max)
2294                max = v;
2295        }
2296
2297        return max;
2298    }
2299
2300    /**
2301     * Find the maximum value of an array
2302     * 
2303     * @param array
2304     *        an array
2305     * @param signed
2306     *        signed / unsigned flag
2307     * @return the max value of the array
2308     */
2309    public static long max(long[] array, boolean signed)
2310    {
2311        if (signed)
2312        {
2313            long max = Integer.MIN_VALUE;
2314
2315            for (long v : array)
2316                if (v > max)
2317                    max = v;
2318
2319            return max;
2320        }
2321
2322        double max = Long.MIN_VALUE;
2323
2324        for (int i = 0; i < array.length; i++)
2325        {
2326            final double v = TypeUtil.unsign(array[i]);
2327            // need to compare in double
2328            if (v > max)
2329                max = v;
2330        }
2331
2332        // convert back to long (need to be interpreted as unsigned)
2333        return TypeUtil.toLong(max);
2334    }
2335
2336    /**
2337     * Find the maximum value of an array
2338     * 
2339     * @param array
2340     *        an array
2341     * @return the max value of the array
2342     */
2343    public static float max(float[] array)
2344    {
2345        float max = -Float.MAX_VALUE;
2346
2347        for (float v : array)
2348            if (v > max)
2349                max = v;
2350
2351        return max;
2352    }
2353
2354    /**
2355     * Find the maximum value of an array
2356     * 
2357     * @param array
2358     *        an array
2359     * @return the max value of the array
2360     */
2361    public static double max(double[] array)
2362    {
2363        double max = -Double.MAX_VALUE;
2364
2365        for (double v : array)
2366            if (v > max)
2367                max = v;
2368
2369        return max;
2370    }
2371
2372    /**
2373     * Element-wise minimum of two arrays
2374     * 
2375     * @param a1
2376     *        =input1
2377     * @param a2
2378     *        =input2
2379     * @param output
2380     *        - the array of min values
2381     */
2382    public static void min(double[] a1, double[] a2, double[] output)
2383    {
2384        for (int i = 0; i < a1.length; i++)
2385            if (a1[i] <= a2[i])
2386                output[i] = a1[i];
2387            else
2388                output[i] = a2[i];
2389    }
2390
2391    /**
2392     * Element-wise minimum of two arrays
2393     * 
2394     * @param a1
2395     *        =input1
2396     * @param a2
2397     *        =input2
2398     * @return the array of min values
2399     */
2400    public static double[] min(double[] a1, double[] a2)
2401    {
2402        double[] result = new double[a1.length];
2403        min(a1, a2, result);
2404        return result;
2405    }
2406
2407    /**
2408     * Element-wise maximum of two arrays
2409     * 
2410     * @param a1
2411     *        =input1
2412     * @param a2
2413     *        =input2
2414     * @param output
2415     *        - the array of max values
2416     */
2417    public static void max(double[] a1, double[] a2, double[] output)
2418    {
2419        for (int i = 0; i < a1.length; i++)
2420            if (a1[i] >= a2[i])
2421                output[i] = a1[i];
2422            else
2423                output[i] = a2[i];
2424    }
2425
2426    /**
2427     * Element-wise maximum of two arrays
2428     * 
2429     * @param a1
2430     *        =input1
2431     * @param a2
2432     *        =input2
2433     * @return the array of max values
2434     */
2435    public static double[] max(double[] a1, double[] a2)
2436    {
2437
2438        double[] result = new double[a1.length];
2439        max(a1, a2, result);
2440        return result;
2441
2442    }
2443
2444    /**
2445     * Reorders the given array to compute its median value
2446     * 
2447     * @param input
2448     * @param preserveData
2449     *        set to true if the given array should not be changed (a copy will be made)
2450     */
2451    public static double median(double[] input, boolean preserveData)
2452    {
2453        return select(input.length / 2, preserveData ? input.clone() : input);
2454    }
2455
2456    /**
2457     * Computes the Maximum Absolute Deviation aka MAD of the given array
2458     * 
2459     * @param input
2460     * @param normalPopulation
2461     *        normalizes the population by 1.4826
2462     */
2463    public static double mad(double[] input, boolean normalPopulation)
2464    {
2465        double[] temp = new double[input.length];
2466        double median = median(input, true);
2467
2468        if (normalPopulation)
2469            for (int i = 0; i < input.length; i++)
2470                temp[i] = 1.4826f * (input[i] - median);
2471        else
2472            for (int i = 0; i < input.length; i++)
2473                temp[i] = (input[i] - median);
2474
2475        abs(temp, true);
2476
2477        return median(temp, false);
2478    }
2479
2480    /**
2481     * (routine ported from 'Numerical Recipes in C 2nd ed.')<br>
2482     * Computes the k-th smallest value in the input array and rearranges the array such that the
2483     * wanted value is located at data[k-1], Lower values
2484     * are stored in arbitrary order in data[0 .. k-2] Higher values will be stored in arbitrary
2485     * order in data[k .. end]
2486     * 
2487     * @param k
2488     * @param data
2489     * @return the k-th smallest value in the array
2490     */
2491    public static double select(int k, double[] data)
2492    {
2493        int i, ir, j, l, mid;
2494        double a, temp;
2495        l = 1;
2496        ir = data.length;
2497        while (true)
2498        {
2499            if (ir <= l + 1)
2500            {
2501                if (ir == l + 1 && data[ir - 1] < data[l - 1])
2502                {
2503                    temp = data[l - 1];
2504                    data[l - 1] = data[ir - 1];
2505                    data[ir - 1] = temp;
2506                }
2507                return data[k - 1];
2508            }
2509
2510            mid = (l + ir) >> 1;
2511            temp = data[mid - 1];
2512            data[mid - 1] = data[l];
2513            data[l] = temp;
2514
2515            if (data[l] > data[ir - 1])
2516            {
2517                temp = data[l + 1 - 1];
2518                data[l] = data[ir - 1];
2519                data[ir - 1] = temp;
2520            }
2521
2522            if (data[l - 1] > data[ir - 1])
2523            {
2524                temp = data[l - 1];
2525                data[l - 1] = data[ir - 1];
2526                data[ir - 1] = temp;
2527            }
2528
2529            if (data[l] > data[l - 1])
2530            {
2531                temp = data[l];
2532                data[l] = data[l - 1];
2533                data[l - 1] = temp;
2534            }
2535
2536            i = l + 1;
2537            j = ir;
2538            a = data[l - 1];
2539
2540            while (true)
2541            {
2542
2543                do
2544                    i++;
2545                while (data[i - 1] < a);
2546                do
2547                    j--;
2548                while (data[j - 1] > a);
2549                if (j < i)
2550                    break;
2551                temp = data[i - 1];
2552                data[i - 1] = data[j - 1];
2553                data[j - 1] = temp;
2554            }
2555
2556            data[l - 1] = data[j - 1];
2557            data[j - 1] = a;
2558
2559            if (j >= k)
2560                ir = j - 1;
2561            if (j <= k)
2562                l = i;
2563        }
2564    }
2565
2566    /**
2567     * Computes the sum of all values from the specified input array.
2568     * 
2569     * @param array
2570     *        an array
2571     * @param signed
2572     *        signed / unsigned flag
2573     * @return the sum of all values from the array
2574     */
2575    public static double sum(Object array, boolean signed)
2576    {
2577        switch (ArrayUtil.getDataType(array))
2578        {
2579            case BYTE:
2580                return sum((byte[]) array, signed);
2581            case SHORT:
2582                return sum((short[]) array, signed);
2583            case INT:
2584                return sum((int[]) array, signed);
2585            case LONG:
2586                return sum((long[]) array, signed);
2587            case FLOAT:
2588                return sum((float[]) array);
2589            case DOUBLE:
2590                return sum((double[]) array);
2591            default:
2592                return 0d;
2593        }
2594    }
2595
2596    /**
2597     * Computes the sum of all values in the input array
2598     * 
2599     * @param input
2600     *        the array to sum up
2601     * @param signed
2602     *        signed / unsigned flag
2603     */
2604    public static double sum(byte[] input, boolean signed)
2605    {
2606        double sum = 0;
2607
2608        if (signed)
2609        {
2610            for (byte b : input)
2611                sum += b;
2612
2613        }
2614        else
2615        {
2616            for (byte b : input)
2617                sum += TypeUtil.unsign(b);
2618        }
2619
2620        return sum;
2621    }
2622
2623    /**
2624     * Computes the sum of all values in the input array
2625     * 
2626     * @param input
2627     *        the array to sum up
2628     * @param signed
2629     *        signed / unsigned flag
2630     */
2631    public static double sum(short[] input, boolean signed)
2632    {
2633        double sum = 0;
2634
2635        if (signed)
2636        {
2637            for (short s : input)
2638                sum += s;
2639
2640        }
2641        else
2642        {
2643            for (short s : input)
2644                sum += TypeUtil.unsign(s);
2645        }
2646
2647        return sum;
2648    }
2649
2650    /**
2651     * Computes the sum of all values in the input array
2652     * 
2653     * @param input
2654     *        the array to sum up
2655     * @param signed
2656     *        signed / unsigned flag
2657     */
2658    public static double sum(int[] input, boolean signed)
2659    {
2660        double sum = 0;
2661
2662        if (signed)
2663        {
2664            for (int i : input)
2665                sum += i;
2666
2667        }
2668        else
2669        {
2670            for (int i : input)
2671                sum += TypeUtil.unsign(i);
2672        }
2673
2674        return sum;
2675    }
2676
2677    /**
2678     * Computes the sum of all values in the input array
2679     * 
2680     * @param input
2681     *        the array to sum up
2682     * @param signed
2683     *        signed / unsigned flag
2684     */
2685    public static double sum(long[] input, boolean signed)
2686    {
2687        double sum = 0;
2688
2689        if (signed)
2690        {
2691            for (long l : input)
2692                sum += l;
2693
2694        }
2695        else
2696        {
2697            for (long l : input)
2698                sum += TypeUtil.unsign(l);
2699        }
2700
2701        return sum;
2702    }
2703
2704    /**
2705     * Computes the sum of all values in the input array
2706     * 
2707     * @param input
2708     *        the array to sum up
2709     */
2710    public static double sum(float[] input)
2711    {
2712        double sum = 0;
2713
2714        for (float f : input)
2715            sum += f;
2716
2717        return sum;
2718    }
2719
2720    /**
2721     * Computes the sum of all values in the input array
2722     * 
2723     * @param input
2724     *        the array to sum up
2725     */
2726    public static double sum(double[] input)
2727    {
2728        double sum = 0;
2729        for (double d : input)
2730            sum += d;
2731        return sum;
2732    }
2733
2734    /**
2735     * Computes the mean value of the given array
2736     * 
2737     * @param input
2738     */
2739    public static double mean(double[] input)
2740    {
2741        return sum(input) / input.length;
2742    }
2743
2744    /**
2745     * Computes the unbiased variance of the given array
2746     * 
2747     * @param input
2748     * @param unbiased
2749     *        set to true if the result should be normalized by the population size minus 1
2750     */
2751    public static double var(double[] input, boolean unbiased)
2752    {
2753        double var = 0, mean = mean(input);
2754        for (double f : input)
2755            var += (f - mean) * (f - mean);
2756        return var / (unbiased ? input.length - 1 : input.length);
2757    }
2758
2759    /**
2760     * Computes the standard deviation of the given array (the variance square root)
2761     * 
2762     * @param input
2763     * @param unbiased
2764     *        set to true if the variance should be unbiased
2765     * @return the square root of the variance
2766     */
2767    public static double std(double[] input, boolean unbiased)
2768    {
2769        return Math.sqrt(var(input, unbiased));
2770    }
2771
2772    /**
2773     * Rescales the given array to [newMin,newMax]. Nothing is done if the input is constant or if
2774     * the new bounds equal the old ones.
2775     * 
2776     * @param input
2777     *        the input array
2778     * @param newMin
2779     *        the new min bound
2780     * @param newMax
2781     *        the new max bound
2782     * @param overwrite
2783     *        true overwrites the input data, false returns the result in a new structure
2784     */
2785    public static double[] rescale(double[] input, double newMin, double newMax, boolean overwrite)
2786    {
2787        double min = min(input), max = max(input);
2788
2789        if (min == max || (min == newMin && max == newMax))
2790            return input;
2791
2792        double[] result = overwrite ? input : new double[input.length];
2793
2794        double ratio = (newMax - newMin) / (max - min);
2795        double base = newMin - (min * ratio);
2796
2797        for (int i = 0; i < input.length; i++)
2798            result[i] = base + input[i] * ratio;
2799
2800        return result;
2801    }
2802
2803    /**
2804     * Standardize the input data by subtracting the mean value and dividing by the standard
2805     * deviation
2806     * 
2807     * @param input
2808     *        the data to standardize
2809     * @param overwrite
2810     *        true if the output should overwrite the input, false if a new array should be returned
2811     * @return the standardized data
2812     */
2813    public static double[] standardize(double[] input, boolean overwrite)
2814    {
2815        double[] output = overwrite ? input : new double[input.length];
2816
2817        subtract(input, mean(input), output);
2818        divide(output, std(output, true), output);
2819
2820        return output;
2821    }
2822
2823    /**
2824     * Computes the classical correlation coefficient between 2 populations.<br>
2825     * This coefficient is given by:<br>
2826     * 
2827     * <pre>
2828     *                       sum(a[i] * b[i])
2829     * r(a,b) = -------------------------------------------
2830     *          sqrt( sum(a[i] * a[i]) * sum(b[i] * b[i]) )
2831     * </pre>
2832     * 
2833     * @param a
2834     *        a population
2835     * @param b
2836     *        a population
2837     * @return the correlation coefficient between a and b.
2838     * @throws IllegalArgumentException
2839     *         if the two input population have different sizes
2840     */
2841    public static double correlation(double[] a, double[] b) throws IllegalArgumentException
2842    {
2843        if (a.length != b.length)
2844            throw new IllegalArgumentException("Populations must have same size");
2845
2846        double sum = 0, sqsum_a = 0, sqsum_b = 0;
2847
2848        double ai, bi;
2849        for (int i = 0; i < a.length; i++)
2850        {
2851            ai = a[i];
2852            bi = b[i];
2853            sum += ai * bi;
2854            sqsum_a += ai * ai;
2855            sqsum_b += bi * bi;
2856        }
2857
2858        return sum / Math.sqrt(sqsum_a * sqsum_b);
2859    }
2860
2861    /**
2862     * Computes the Pearson correlation coefficient between two populations of same size N. <br>
2863     * This coefficient is computed by: <br>
2864     * 
2865     * <pre>
2866     *          sum(a[i] * b[i]) - N * mean(a) * mean(b)
2867     * r(a,b) = ----------------------------------------
2868     *                  (N-1) * std(a) * std(b)
2869     * </pre>
2870     * 
2871     * @param a
2872     *        a population
2873     * @param b
2874     *        a population
2875     * @return the Pearson correlation measure between a and b.
2876     * @throws IllegalArgumentException
2877     *         if the two input population have different sizes
2878     */
2879    public static double correlationPearson(double[] a, double[] b) throws IllegalArgumentException
2880    {
2881        if (a.length != b.length)
2882            throw new IllegalArgumentException("Populations must have same size");
2883
2884        double sum = 0;
2885        for (int i = 0; i < a.length; i++)
2886            sum += a[i] * b[i];
2887
2888        return (sum - a.length * mean(a) * mean(b)) / ((a.length - 1) * std(a, true) * std(b, true));
2889    }
2890}