001    /**
002     * Copyright (c) 2010, SIB. All rights reserved.
003     * 
004     * SIB (Swiss Institute of Bioinformatics) - http://www.isb-sib.ch Host -
005     * https://sourceforge.net/projects/javaprotlib/
006     * 
007     * Redistribution and use in source and binary forms, with or without
008     * modification, are permitted provided that the following conditions are met:
009     * Redistributions of source code must retain the above copyright notice, this
010     * list of conditions and the following disclaimer. Redistributions in binary
011     * form must reproduce the above copyright notice, this list of conditions and
012     * the following disclaimer in the documentation and/or other materials provided
013     * with the distribution. Neither the name of the SIB/GENEBIO nor the names of
014     * its contributors may be used to endorse or promote products derived from this
015     * software without specific prior written permission.
016     * 
017     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020     * ARE DISCLAIMED. IN NO EVENT SHALL SIB/GENEBIO BE LIABLE FOR ANY DIRECT,
021     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
024     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     */
028    package org.expasy.jpl.commons.collection;
029    
030    
031    import java.util.ArrayList;
032    import java.util.Arrays;
033    import java.util.List;
034    import org.apache.commons.collections15.Transformer;
035    import org.apache.commons.math.util.MathUtils;
036    import org.expasy.jpl.commons.collection.sorter.AbstractDoublesArrayIndexComparator;
037    import org.expasy.jpl.commons.collection.sorter.AbstractIntsArrayIndexComparator;
038    import org.expasy.jpl.commons.collection.sorter.ArrayIndexComparator;
039    import org.expasy.jpl.commons.collection.sorter.ArrayIndexSorter;
040    
041    
042    /**
043     * Provides static generic methods on primitive arrays.
044     * 
045     * @author nikitin
046     * 
047     * @version 1.0
048     * 
049     */
050    public final class PrimitiveArrayUtils {
051            
052            /** simply reverse the array */
053            public static void reverse(int[] b) {
054                    int left = 0; // index of leftmost element
055                    int right = b.length - 1; // index of rightmost element
056                    
057                    while (left < right) {
058                            // exchange the left and right elements
059                            int temp = b[left];
060                            b[left] = b[right];
061                            b[right] = temp;
062                            
063                            // move the bounds toward the center
064                            left++;
065                            right--;
066                    }
067            }
068            
069            /**
070             * Map the objects found at given indices.
071             * 
072             * @param objects the objects to map.
073             * @param indices the indices of objects array.
074             * @return an array of mapped {@code Object}s.
075             */
076            public static Object[] mapping(final Object[] objects, final int[] indices) {
077                    
078                    if (indices.length > objects.length) {
079                            throw new IllegalArgumentException("too many indices");
080                    }
081                    
082                    final Object[] values = new Object[indices.length];
083                    int i = 0;
084                    for (final int index : indices) {
085                            values[i++] = objects[index];
086                    }
087                    
088                    return values;
089            }
090            
091            /**
092             * Map the integers found at given indices.
093             * 
094             * @param array the integers to map.
095             * @param indices the indices of objects array.
096             * @return an array of mapped {@code int}s.
097             */
098            public static int[] mapping(final int[] array, final int[] indices) {
099                    
100                    if (indices.length > array.length) {
101                            throw new IllegalArgumentException("too many indices");
102                    }
103                    
104                    final int[] values = new int[indices.length];
105                    int i = 0;
106                    for (final int index : indices) {
107                            values[i++] = array[index];
108                    }
109                    
110                    return values;
111            }
112            
113            /**
114             * Map the doubles found at given indices.
115             * 
116             * @param vals the values to map.
117             * @param indices the indices of objects array.
118             * @return an array of mapped {@code double}s.
119             */
120            public static double[] mapping(final double[] vals, final int[] indices) {
121                    
122                    if (vals == null || vals.length == 0) {
123                            return null;
124                    }
125                    
126                    if (indices.length > vals.length) {
127                            throw new IllegalArgumentException("too many indices");
128                    }
129                    
130                    final double[] values = new double[indices.length];
131                    int i = 0;
132                    for (final int index : indices) {
133                            values[i++] = vals[index];
134                    }
135                    
136                    return values;
137            }
138            
139            /**
140             * Map the values found in the given interval.
141             * 
142             * @param vals the values to map.
143             * @param from the first index.
144             * @param to the last index.
145             * 
146             * @return an array of {@code double}s.
147             */
148            static public double[] mapping(final double[] vals, int from, int to) {
149                    if (vals == null || vals.length == 0) {
150                            return null;
151                    }
152                    
153                    final double[] values = new double[to - from + 1];
154                    int i = 0;
155                    for (int index = from; index <= to; index++) {
156                            values[i++] = vals[index];
157                    }
158                    
159                    return values;
160            }
161            
162            /**
163             * Convert objects to ints.
164             * 
165             * @param objects the objects to convert.
166             */
167            public static int[] convert2ints(final Object[] objects) {
168                    final int[] values = new int[objects.length];
169                    
170                    for (int i = 0; i < objects.length; i++) {
171                            values[i] = Integer.parseInt(objects[i].toString());
172                    }
173                    
174                    return values;
175            }
176            
177            /**
178             * Convert ints to array of Integers.
179             * 
180             * @param ints the ints to convert.
181             */
182            public static Integer[] ints2Integers(final int[] ints) {
183                    final Integer[] values = new Integer[ints.length];
184                    
185                    for (int i = 0; i < ints.length; i++) {
186                            values[i] = new Integer(ints[i]);
187                    }
188                    
189                    return values;
190            }
191            
192            /**
193             * Convert ints to List of Integers.
194             * 
195             * @param ints the ints to convert.
196             */
197            public static List<Integer> asIntList(final int[] ints) {
198                    final List<Integer> l = new ArrayList<Integer>();
199                    
200                    for (int i : ints) {
201                            l.add(i);
202                    }
203                    
204                    return l;
205            }
206            
207            /**
208             * Convert arrays of Ts to List of Ts.
209             * 
210             * @param os the object array to convert.
211             */
212            public static <T> List<T> asList(final T[] os) {
213                    final List<T> l = new ArrayList<T>();
214                    
215                    for (T o : os) {
216                            l.add(o);
217                    }
218                    
219                    return l;
220            }
221            
222            /**
223             * Convert array of doubles to array of Doubles.
224             * 
225             * @param dbls the array to convert.
226             */
227            public static Double[] doubles2Doubles(final double[] dbls) {
228                    final Double[] values = new Double[dbls.length];
229                    
230                    for (int i = 0; i < dbls.length; i++) {
231                            values[i] = new Double(dbls[i]);
232                    }
233                    
234                    return values;
235            }
236            
237            /**
238             * Sort int values in ascending order.
239             * 
240             * @param array the int array to sort.
241             * @return the sorted array.
242             */
243            public static int[] sortUp(final int[] array) {
244                    Arrays.sort(array);
245                    return array;
246            }
247            
248            /**
249             * Sort int values in descending order.
250             * 
251             * @param array the int array to sort.
252             * @return the sorted array.
253             */
254            public static int[] sortDown(final int[] array) {
255                    
256                    // ascending sort
257                    Arrays.sort(array);
258                    
259                    // put in reverse order
260                    final int halfLen = array.length / 2;
261                    final int lastIdx = array.length - 1;
262                    int temp;
263                    for (int i = 0; i < halfLen; i++) {
264                            temp = array[i];
265                            array[i] = array[lastIdx - i];
266                            array[lastIdx - i] = temp;
267                    }
268                    
269                    return array;
270            }
271            
272            /**
273             * Sort double values in ascending order.
274             * 
275             * @param array the double array to sort.
276             * @return the sorted array.
277             */
278            public static double[] sortUp(final double[] array) {
279                    Arrays.sort(array);
280                    return array;
281            }
282            
283            /**
284             * Sort double values in descending order.
285             * 
286             * @param array the double array to sort.
287             * @return the sorted array.
288             */
289            public static double[] sortDown(final double[] array) {
290                    // ascending sort
291                    Arrays.sort(array);
292                    
293                    // reverse
294                    final int halfLen = array.length / 2;
295                    final int lastIdx = array.length - 1;
296                    double temp;
297                    for (int i = 0; i < halfLen; i++) {
298                            temp = array[i];
299                            array[i] = array[lastIdx - i];
300                            array[lastIdx - i] = temp;
301                    }
302                    
303                    return array;
304            }
305            
306            /**
307             * Sort int value indices in ascending order.
308             * 
309             * @param array the int array to sort indices.
310             * @return the sorted array.
311             */
312            public static int[] sortIndexesUp(final int[] array) {
313                    
314                    final ArrayIndexComparator idxComp =
315                        new AbstractIntsArrayIndexComparator() {
316                                
317                                @Override
318                                public int compare(final Integer i1, final Integer i2) {
319                                        if (getArray()[i1] < getArray()[i2]) {
320                                                return -1;
321                                        }
322                                        if (getArray()[i1] > getArray()[i2]) {
323                                                return 1;
324                                        }
325                                        return 0;
326                                }
327                        };
328                    
329                    final ArrayIndexSorter sortIndex = new ArrayIndexSorter(array, idxComp);
330                    
331                    return sortIndex.sort();
332            }
333            
334            /**
335             * Sort int value indices in descending order.
336             * 
337             * @param array the int array to sort indices.
338             * @return the sorted array.
339             */
340            public static int[] sortIndexesDown(final int[] array) {
341                    
342                    final ArrayIndexComparator idxComp =
343                        new AbstractIntsArrayIndexComparator() {
344                                
345                                @Override
346                                public int compare(final Integer i1, final Integer i2) {
347                                        return (getArray()[i2] - getArray()[i1]);
348                                }
349                        };
350                    
351                    final ArrayIndexSorter sortIndex = new ArrayIndexSorter(array, idxComp);
352                    
353                    return sortIndex.sort();
354            }
355            
356            public static int[] sortIndexesUp(final double[] array) {
357                    
358                    final ArrayIndexComparator idxComp =
359                        new AbstractDoublesArrayIndexComparator() {
360                                
361                                @Override
362                                public int compare(final Integer i1, final Integer i2) {
363                                        if (getArray()[i1] < getArray()[i2]) {
364                                                return -1;
365                                        }
366                                        if (getArray()[i1] > getArray()[i2]) {
367                                                return 1;
368                                        }
369                                        return 0;
370                                }
371                        };
372                    
373                    final ArrayIndexSorter sortIndex = new ArrayIndexSorter(array, idxComp);
374                    return sortIndex.sort();
375            }
376            
377            public static int[] sortIndexesDown(final double[] array) {
378                    
379                    final ArrayIndexComparator idxComp =
380                        new AbstractDoublesArrayIndexComparator() {
381                                
382                                @Override
383                                public int compare(final Integer i1, final Integer i2) {
384                                        if (getArray()[i1] < getArray()[i2]) {
385                                                return 1;
386                                        }
387                                        if (getArray()[i1] > getArray()[i2]) {
388                                                return -1;
389                                        }
390                                        return 0;
391                                }
392                        };
393                    
394                    final ArrayIndexSorter sortIndex = new ArrayIndexSorter(array, idxComp);
395                    return sortIndex.sort();
396            }
397            
398            /**
399             * Merge two sorted arrays (ascending or up) in one
400             * 
401             * @param array1 the first sorted array
402             * @param array2 the second sorted array
403             * @return array the sorted merged array
404             */
405            public static double[] mergeUp(final double[] array1, final double[] array2) {
406                    final double[] array = new double[array1.length + array2.length];
407                    int i = 0;
408                    int j = 0;
409                    int k = 0;
410                    
411                    // TODO: improve algo with testing mini & maxi values
412                    
413                    while ((i < array1.length) && (j < array2.length)) {
414                            if (array1[i] < array2[j]) {
415                                    array[k] = array1[i];
416                                    i++;
417                            } else {
418                                    array[k] = array2[j];
419                                    j++;
420                            }
421                            k++; // next position in the new array
422                    }
423                    // Push the remaining elements to the end of new array when a feeder
424                    // array is empty
425                    while (i < array1.length) {
426                            array[k] = array1[i];
427                            i++;
428                            k++;
429                    }
430                    while (j < array2.length) {
431                            array[k] = array2[j];
432                            j++;
433                            k++;
434                    }
435                    
436                    return array;
437            }
438            
439            public static final int[] sortIndices(final double[] objects) {
440                    if (objects.length > 0) {
441                            final int[] indices = new int[objects.length];
442                            for (int i = 0; i < indices.length; i++) {
443                                    indices[i] = i;
444                            }
445                            return sortIndices(objects, indices, 0, objects.length - 1);
446                    }
447                    return null;
448            }
449            
450            /**
451             * Reimplementation of quicksort for performance gain.
452             * 
453             * @param objects the array of object to sort.
454             * @param from the lower limit.
455             * @param to the upper limit.
456             */
457            public static final int[] sortIndices(final double[] objects,
458                final int[] indices, final int from, final int to) {
459                    
460                    if (from >= to) {
461                            return indices;
462                    }
463                    
464                    final int pivotIndex = (from + to) / 2;
465                    int tmp;
466                    int middle = indices[pivotIndex];
467                    
468                    // swap from & middle indices if first value > middle value
469                    if (objects[indices[from]] > objects[middle]) {
470                            indices[pivotIndex] = indices[from];
471                            indices[from] = middle;
472                            middle = indices[pivotIndex];
473                    }
474                    
475                    // swap peaks[to] & peaks[middle] if last value > middle value
476                    if (objects[middle] > objects[indices[to]]) {
477                            indices[pivotIndex] = indices[to];
478                            indices[to] = middle;
479                            middle = indices[pivotIndex];
480                            
481                            // swap peaks[from] & peaks[middle] if first value > middle value
482                            if (objects[indices[from]] > objects[middle]) {
483                                    indices[pivotIndex] = indices[from];
484                                    indices[from] = middle;
485                                    middle = indices[pivotIndex];
486                            }
487                    }
488                    
489                    int left = from + 1;
490                    int right = to - 1;
491                    
492                    if (left >= right) {
493                            return indices;
494                    }
495                    
496                    for (;;) {
497                            while (objects[indices[right]] > objects[middle]) {
498                                    right--;
499                            }
500                            
501                            while ((left < right)
502                                && (objects[indices[left]] <= objects[middle])) {
503                                    left++;
504                            }
505                            
506                            if (left < right) {
507                                    tmp = indices[left];
508                                    indices[left] = indices[right];
509                                    indices[right] = tmp;
510                                    right--;
511                            } else {
512                                    break;
513                            }
514                    }
515                    
516                    sortIndices(objects, indices, from, left);
517                    sortIndices(objects, indices, left + 1, to);
518                    
519                    return indices;
520            }
521            
522            /**
523             * sort (increasing) the list of arrays based on the values contained in the
524             * first one (think of masses, intensities...)
525             * 
526             * @param arrays
527             * @throws IllegalArgumentException if 0 arrays are passed of if length
528             *         differs
529             */
530            public static void sortUpArrraysOnFirst(final double[][] arrays) {
531                    final int nbArrays = arrays.length;
532                    if (nbArrays == 0) {
533                            throw new IllegalArgumentException(
534                                "cannot pass empty list of arays");
535                    }
536                    
537                    final int size = arrays[0].length;
538                    final int[] sidx = PrimitiveArrayUtils.sortIndexesUp(arrays[0]);
539                    for (int i = 0; i < nbArrays; i++) {
540                            if (arrays[i].length != size) {
541                                    throw new IllegalArgumentException("size of arrays 0 and " + i
542                                        + " differ : " + size + " vs " + arrays[i]);
543                            }
544                            final double[] tmp = arrays[i].clone();
545                            for (int j = 0; j < tmp.length; j++) {
546                                    arrays[i][j] = tmp[sidx[j]];
547                            }
548                    }
549            }
550            
551            public static void getNthHighestElement(final double[] array, final int rank) {
552    
553            }
554            
555            public static double[] floats2doubles(final float[] fArray) {
556                    final double[] dArray = new double[fArray.length];
557                    
558                    for (int i = 0; i < fArray.length; i++) {
559                            dArray[i] = fArray[i];
560                    }
561                    
562                    return dArray;
563            }
564            
565            // public static IntegerSequence getIndexRangeWithBinarySearch(
566            // double[] values, final Interval interval) {
567            //              
568            // int from = Arrays.binarySearch(values, interval.getLowerBound());
569            // int to = Arrays.binarySearch(values, interval.getUpperBound());
570            //              
571            // if (from < 0) {
572            // from = -from - 1;
573            // }
574            // if (to < 0) {
575            // to = -to - 1;
576            // }
577            // return new IntegerSequence.Builder(from, to).build();
578            // }
579            
580            // public static int[] getIndexRangeWithBinarySearch(double[] values,
581            // double start, double end) {
582            //              
583            // int from = Arrays.binarySearch(values, start);
584            // int to = Arrays.binarySearch(values, end);
585            //              
586            // if (from < 0) {
587            // from = -from - 1;
588            // }
589            // if (to < 0) {
590            // to = -to - 1;
591            // }
592            // return new int[] {from, to};
593            // }
594            
595            /**
596             * Get the index range of {@code values} where each is contained in the
597             * given interval.
598             * 
599             * @param values the values to get the range from.
600             * @param start the interval included start.
601             * @param end the interval excluded end.
602             * @return a range of indices
603             */
604            public static int[] getIndexRange(double[] values, double start, double end) {
605                    IntegerSequence seq =
606                        getIndexRange(values, new Interval.Builder(start, end).build());
607                    
608                    if (seq.isEmpty()) {
609                            return new int[] { };
610                    } else {
611                            return new int[] {seq.getFrom(), seq.getTo() - 1};
612                    }
613            }
614            
615            /**
616             * Get an interval of index in sorted values.
617             * 
618             * @param interval of definition.
619             * 
620             * @return an interval on values index [imin, imax[.
621             * 
622             * @throws IllegalArgumentException if values are not sorted.
623             */
624            public static IntegerSequence getIndexRange(double[] values,
625                final Interval interval) {
626                    
627                    int imin = -1;
628                    int imax = -1;
629                    
630                    // throw IllegalArgumentException if not sorted !
631                    MathUtils.checkOrder(values, 1, false);
632                    
633                    double lowerBound = interval.getLowerBound();
634                    double upperBound = interval.getUpperBound();
635                    
636                    for (int index = 0; index < values.length; index++) {
637                            
638                            if (values[index] < lowerBound
639                                || (values[index] == lowerBound && !interval
640                                    .isLowerBoundIncluded())) {
641                                    imin = index + 1;
642                                    continue;
643                            }
644                            
645                            // greater than lower bound
646                            if (values[index] < upperBound
647                                || (values[index] == upperBound && interval
648                                    .isUpperBoundIncluded())) {
649                                    imax = index;
650                            } else {
651                                    break;
652                            }
653                    }
654                    
655                    if (imax == -1) {
656                            return IntegerSequence.emptyInstance();
657                    }
658                    
659                    if (imin == -1) {
660                            imin = 0;
661                    }
662                    
663                    return new IntegerSequence.Builder(imin, imax + 1).build();
664            }
665            
666            /**
667             * Search the given query intervals into the target values.
668             * 
669             * @param values the sorted values to find indices in.
670             * @param intervalCenters the sorted interval centers query.
671             * @param halfIntervalRange the half-range interval for all query value.
672             * 
673             * @return a list of indices found in at least one query interval.
674             * 
675             * @throws IllegalArgumentException - if the arrays are not sorted.
676             */
677            public static List<Integer> searchIndices(double[] values,
678                double[] intervalCenters, double halfIntervalRange) {
679                    
680                    return searchIndices(values, intervalCenters, halfIntervalRange, 0);
681            }
682            
683            /**
684             * Search the given query intervals into the target values.
685             * 
686             * @param values the sorted values to find indices in.
687             * @param intervalCenters the sorted interval centers query.
688             * @param halfIntervalRange the half-range interval for all query value.
689             * @param from the begin index to search into values.
690             * 
691             * @return a list of indices found in at least one query interval.
692             * 
693             * @throws IllegalArgumentException - if the arrays are not sorted.
694             */
695            public static List<Integer> searchIndices(double[] values,
696                double[] intervalCenters, double halfIntervalRange, int from) {
697                    
698                    MathUtils.checkOrder(values, 1, false);
699                    MathUtils.checkOrder(intervalCenters, 1, false);
700                    
701                    final List<Integer> indices = new ArrayList<Integer>();
702                    
703                    int intervalIndex = 0;
704                    
705                    int i = from;
706                    
707                    while (i < values.length && intervalIndex < intervalCenters.length) {
708                            
709                            // get the index in values <= lower bound of current interval i
710                            i =
711                                Arrays.binarySearch(values, i, values.length,
712                                    intervalCenters[intervalIndex] - halfIntervalRange);
713                            
714                            // if lower bound was not found -> compute the insertion point
715                            if (i < 0) {
716                                    i = -i - 1;
717                            }
718                            
719                            // values[i] >= current lower bound
720                            while (i < values.length
721                                && values[i] <= intervalCenters[intervalIndex]
722                                    + halfIntervalRange) {
723                                    
724                                    indices.add(i++);
725                            }
726                            
727                            // next interval
728                            intervalIndex++;
729                    }
730                    
731                    return indices;
732            }
733            
734            public static double[] getSubArray(double[] values, int from, int to) {
735                    return Arrays.copyOfRange(values, from, to);
736            }
737            
738            /**
739             * Convert an integer to an array of bytes.
740             * 
741             * http://snippets.dzone.com/posts/show/93
742             * 
743             * @param value the integer to convert.
744             */
745            public static final byte[] intToByteArray(int value) {
746                    return new byte[] {(byte) (value >>> 24), (byte) (value >>> 16),
747                        (byte) (value >>> 8), (byte) value};
748            }
749            
750            /**
751             * Convert an array of bytes into integer value.
752             * 
753             * http://snippets.dzone.com/posts/show/93
754             * 
755             * @param bytes the bytes to convert into integer.
756             */
757            public static final int byteArrayToInt(byte[] bytes) {
758                    return (bytes[0] << 24) + ((bytes[1] & 0xFF) << 16)
759                        + ((bytes[2] & 0xFF) << 8) + (bytes[3] & 0xFF);
760            }
761            
762            /**
763             * Convert a list of {@code Double}s to an array of doubles.
764             * 
765             * @param list the list to convert.
766             * @return an array of doubles.
767             */
768            public static final double[] toDoubleArray(List<Double> list) {
769                    final double[] array = new double[list.size()];
770                    
771                    for (int i = 0; i < array.length; i++) {
772                            array[i] = list.get(i).doubleValue();
773                    }
774                    return array;
775            }
776            
777            /**
778             * Convert a list of {@code Integer}s to an array of ints.
779             * 
780             * @param list the list to convert.
781             * @return an array of ints.
782             */
783            public static final int[] toIntArray(List<Integer> list) {
784                    final int[] array = new int[list.size()];
785                    
786                    for (int i = 0; i < array.length; i++) {
787                            array[i] = list.get(i).intValue();
788                    }
789                    return array;
790            }
791            
792            /**
793             * Copy array of doubles accessible from {@code T-object} in a given {@code
794             * copy} array.
795             * 
796             * @param <T> the object typed wrapping double[].
797             * @param object the {@code T-object} to copy doubles from.
798             * @param copy the array to copy doubles into.
799             * @param o2a the transformer to access double[] from {@code T-object}.
800             * 
801             * @return the given {@code copy} loaded with doubles or a new array if
802             *         {@code copy} is not defined or had reduced capacity.
803             */
804            public static <T> double[] loadArray(T object,
805                Transformer<T, double[]> o2a, double[] copy) {
806                    double[] array = o2a.transform(object);
807                    
808                    if (copy == null || copy.length < array.length) {
809                            copy = new double[array.length];
810                    }
811                    System.arraycopy(array, 0, copy, 0, array.length);
812                    
813                    return copy;
814            }
815    }