001/* A library for mathematical operations on arrays of ints.
002
003 Copyright (c) 1998-2014 The Regents of the University of California.
004 All rights reserved.
005
006 Permission is hereby granted, without written agreement and without
007 license or royalty fees, to use, copy, modify, and distribute this
008 software and its documentation for any purpose, provided that the above
009 copyright notice and the following two paragraphs appear in all copies
010 of this software.
011
012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
016 SUCH DAMAGE.
017
018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 ENHANCEMENTS, OR MODIFICATIONS.
024
025 PT_COPYRIGHT_VERSION_2
026 COPYRIGHTENDKEY
027
028 */
029package ptolemy.math;
030
031///////////////////////////////////////////////////////////////////
032//// IntegerArrayMath
033
034/**
035 This class provides a library for mathematical operations on int arrays.
036 Unless explicitly noted otherwise, all array arguments are assumed to be
037 non-null. If a null array is passed to a method, a NullPointerException
038 will be thrown in the method or called methods.
039
040 @author Albert Chen, William Wu, Edward A. Lee, Jeff Tsay
041 @version $Id$
042 @since Ptolemy II 1.0
043 @Pt.ProposedRating Yellow (ctsay)
044 @Pt.AcceptedRating Yellow (ctsay)
045 */
046public class IntegerArrayMath {
047    // Protected constructor prevents construction of this class.
048    protected IntegerArrayMath() {
049    }
050
051    ///////////////////////////////////////////////////////////////////
052    ////                         public methods                    ////
053
054    /** Return a new array that is the formed by adding z to each element
055     *  of the input array.
056     */
057    public static final int[] add(final int[] array, final int z) {
058        int length = array.length;
059        int[] returnValue = new int[length];
060
061        for (int i = 0; i < length; i++) {
062            returnValue[i] = array[i] + z;
063        }
064
065        return returnValue;
066    }
067
068    /** Return a new array that is the element-by-element sum of the two
069     *  input arrays.
070     *  If the lengths of both arrays are 0, return a new array of length 0.
071     *  If the two arrays do not have the same length, throw an
072     *  IllegalArgumentException.
073     */
074    public static final int[] add(final int[] array1, final int[] array2) {
075        int length = _commonLength(array1, array2, "IntegerArrayMath.add");
076        int[] returnValue = new int[length];
077
078        for (int i = 0; i < length; i++) {
079            returnValue[i] = array1[i] + array2[i];
080        }
081
082        return returnValue;
083    }
084
085    /** Return a new array that is a copy of the array argument.
086     *  @param array An array of ints.
087     *  @return A new array of ints.
088     */
089    public static final int[] allocCopy(final int[] array) {
090        int elements = array.length;
091        int[] newArray = new int[elements];
092        System.arraycopy(array, 0, newArray, 0, elements);
093        return newArray;
094    }
095
096    /** Return a new array that is the result of appending array2 to the end
097     *  of array1. This method simply calls
098     *  append(array1, 0, array1.length, array2, 0, array2.length)
099     */
100    public static final int[] append(final int[] array1, final int[] array2) {
101        return append(array1, 0, array1.length, array2, 0, array2.length);
102    }
103
104    /** Return a new array that is the result of appending length2
105     *  elements of array2, starting from the array1[idx2] to length1
106     *  elements of array1, starting from array1[idx1].  Appending
107     *  empty arrays is supported. In that case, the corresponding idx
108     *  may be any number. Allow System.arraycopy() to throw array
109     *  access exceptions if idx .. idx + length - 1 are not all valid
110     *  array indices, for both of the arrays.
111     *  @param array1 The first array of ints.
112     *  @param idx1 The starting index for array1.
113     *  @param length1 The number of elements of array1 to use.
114     *  @param array2 The second array of ints, which is appended.
115     *  @param idx2 The starting index for array2.
116     *  @param length2 The number of elements of array2 to append.
117     *  @return A new array of ints.
118     */
119    public static final int[] append(final int[] array1, final int idx1,
120            final int length1, final int[] array2, final int idx2,
121            final int length2) {
122        int[] returnValue = new int[length1 + length2];
123
124        if (length1 > 0) {
125            System.arraycopy(array1, idx1, returnValue, 0, length1);
126        }
127
128        if (length2 > 0) {
129            System.arraycopy(array2, idx2, returnValue, length1, length2);
130        }
131
132        return returnValue;
133    }
134
135    /** Return a new array that is formed by applying an instance of a
136     *  IntegerBinaryOperation to each element in the input array
137     *  and z, using the array elements as the left operands and z
138     *  as the right operand in all cases. (op.operate(array[i], z)).
139     *  If the length of the array is 0, return a new array of length 0.
140     */
141    public static final int[] applyBinaryOperation(IntegerBinaryOperation op,
142            final int[] array, final int z) {
143        int length = array.length;
144        int[] returnValue = new int[length];
145
146        for (int i = 0; i < length; i++) {
147            returnValue[i] = op.operate(array[i], z);
148        }
149
150        return returnValue;
151    }
152
153    /** Return a new array that is formed by applying an instance of a
154     *  IntegerBinaryOperation to each element in the input array,
155     *  using z as the left operand in all cases and the array elements
156     *  as the right operands (op.operate(z, array[i])).
157     *  If the length of the array is 0, return a new array of length 0.
158     */
159    public static final int[] applyBinaryOperation(IntegerBinaryOperation op,
160            final int z, final int[] array) {
161        int length = array.length;
162        int[] returnValue = new int[length];
163
164        for (int i = 0; i < length; i++) {
165            returnValue[i] = op.operate(array[i], z);
166        }
167
168        return returnValue;
169    }
170
171    /** Return a new array that is formed by applying an instance of a
172     *  IntegerBinaryOperation to the two arrays, element by element,
173     *  using the elements of the first array as the left operands and the
174     *  elements of the second array as the right operands.
175     *  (op.operate(array[i], array2[i])).
176     *  If the lengths of both arrays are 0, return a new array of length 0.
177     *  If the two arrays do not have the same length, throw an
178     *  IllegalArgumentException.
179     */
180    public static final int[] applyBinaryOperation(IntegerBinaryOperation op,
181            final int[] array1, final int[] array2) {
182        int length = _commonLength(array1, array2,
183                "IntegerArrayMath.applyBinaryOperation");
184        int[] returnValue = new int[length];
185
186        for (int i = 0; i < length; i++) {
187            returnValue[i] = op.operate(array1[i], array2[i]);
188        }
189
190        return returnValue;
191    }
192
193    /** Return a new array that is formed by applying an instance of a
194     *  IntegerUnaryOperation to each element in the input array
195     *  (op.operate(array[i])).
196     *  If the length of the array is 0, return a new array of length 0.
197     */
198    public static final int[] applyUnaryOperation(
199            final IntegerUnaryOperation op, final int[] array) {
200        int length = array.length;
201        int[] returnValue = new int[length];
202
203        for (int i = 0; i < length; i++) {
204            returnValue[i] = op.operate(array[i]);
205        }
206
207        return returnValue;
208    }
209
210    /** Return a new array that is the formed by bitwise ANDing z with
211     *  each element of the input array (array[i] &amp; z).  If the length
212     *  of the array is 0, return a new array of length 0.
213     */
214    public static final int[] bitwiseAnd(final int[] array, final int z) {
215        int length = array.length;
216        int[] returnValue = new int[length];
217
218        for (int i = 0; i < length; i++) {
219            returnValue[i] = array[i] & z;
220        }
221
222        return returnValue;
223    }
224
225    /** Return a new array that is the element-by-element bitwise AND
226     *  of the two input arrays (array1[i] &amp; array2[i]).  If the
227     *  lengths of both arrays are 0, return a new array of length 0.
228     *  If the two arrays do not have the same length, throw an
229     *  IllegalArgumentException.
230     */
231    public static final int[] bitwiseAnd(final int[] array1,
232            final int[] array2) {
233        int length = _commonLength(array1, array2,
234                "IntegerArrayMath.bitwiseAnd");
235        int[] returnValue = new int[length];
236
237        for (int i = 0; i < length; i++) {
238            returnValue[i] = array1[i] & array2[i];
239        }
240
241        return returnValue;
242    }
243
244    /** Return a new array that is the element-by-element bitwise
245     *  complement of the input array (~array[i]).  If the length of
246     *  the array is 0, return a new array of length 0.
247     */
248    public static final int[] bitwiseComplement(final int[] array) {
249        int length = array.length;
250        int[] returnValue = new int[length];
251
252        for (int i = 0; i < length; i++) {
253            returnValue[i] = ~array[i];
254        }
255
256        return returnValue;
257    }
258
259    /** Return a new array that is the formed by bitwise ORing z with
260     *  each element of the input array (array[i] | z).  If the length
261     *  of the array is 0, return a new array of length 0.
262     */
263    public static final int[] bitwiseOr(final int[] array, final int z) {
264        int length = array.length;
265        int[] returnValue = new int[length];
266
267        for (int i = 0; i < length; i++) {
268            returnValue[i] = array[i] | z;
269        }
270
271        return returnValue;
272    }
273
274    /** Return a new array that is the element-by-element bitwise OR of the two
275     *  input arrays (array1[i] | array2[i]).
276     *  If the lengths of both arrays are 0, return a new array of length 0.
277     *  If the two arrays do not have the same length, throw an
278     *  IllegalArgumentException.
279     */
280    public static final int[] bitwiseOr(final int[] array1,
281            final int[] array2) {
282        int length = _commonLength(array1, array2,
283                "IntegerArrayMath.bitwiseOr");
284        int[] returnValue = new int[length];
285
286        for (int i = 0; i < length; i++) {
287            returnValue[i] = array1[i] | array2[i];
288        }
289
290        return returnValue;
291    }
292
293    /** Return a new array that is the formed by bitwise XORing z with
294     *  each element of the input array (array[i] ^ z).  If the length
295     *  of the array is 0, return a new array of length 0.
296     */
297    public static final int[] bitwiseXor(final int[] array, final int z) {
298        int length = array.length;
299        int[] returnValue = new int[length];
300
301        for (int i = 0; i < length; i++) {
302            returnValue[i] = array[i] ^ z;
303        }
304
305        return returnValue;
306    }
307
308    /** Return a new array that is the element-by-element bitwise XOR
309     *  of the two input arrays (array1[i] ^ array2[i]).  If the
310     *  lengths of both arrays are 0, return a new array of length 0.
311     *  If the two arrays do not have the same length, throw an
312     *  IllegalArgumentException.
313     */
314    public static final int[] bitwiseXor(final int[] array1,
315            final int[] array2) {
316        int length = _commonLength(array1, array2,
317                "IntegerArrayMath.bitwiseXor");
318        int[] returnValue = new int[length];
319
320        for (int i = 0; i < length; i++) {
321            returnValue[i] = array1[i] ^ array2[i];
322        }
323
324        return returnValue;
325    }
326
327    /** Return a new array that is the formed by dividing each element
328     *  of the input array by z (array[i] / z).  If the length of the
329     *  array is 0, return a new array of length 0.
330     */
331    public static final int[] divide(final int[] array, final int z) {
332        int length = array.length;
333        int[] returnValue = new int[length];
334
335        for (int i = 0; i < length; i++) {
336            returnValue[i] = array[i] / z;
337        }
338
339        return returnValue;
340    }
341
342    /** Return a new array that is the element-by-element division of
343     *  the first array by the second array (array1[i] / array2[i]).
344     *  If the lengths of both arrays are 0, return a new array of length 0.
345     *  If the two arrays do not have the same length, throw an
346     *  IllegalArgumentException.
347     *  @param array1 The first array of ints.
348     *  @param array2 The second array of ints.
349     *  @return A new array of ints.
350     */
351    public static final int[] divideElements(final int[] array1,
352            final int[] array2) {
353        int length = _commonLength(array1, array2,
354                "IntegerArrayMath.divideElements");
355        int[] returnValue = new int[length];
356
357        for (int i = 0; i < length; i++) {
358            returnValue[i] = array1[i] / array2[i];
359        }
360
361        return returnValue;
362    }
363
364    /** Return the dot product of the two arrays.
365     *  If the lengths of the array are both 0, return 0.
366     *  If the two arrays do not have the same length, throw an
367     *  IllegalArgumentException.
368     */
369    public static final int dotProduct(final int[] array1, final int[] array2) {
370        int length = _commonLength(array1, array2,
371                "IntegerArrayMath.dotProduct");
372
373        int sum = 0;
374
375        for (int i = 0; i < length; i++) {
376            sum += array1[i] * array2[i];
377        }
378
379        return sum;
380    }
381
382    /** Return a new array that is a copy of the argument except that
383     *  the elements are limited to lie within the specified range.
384     *  <p>If any value is MAX_VALUE or MIN_VALUE, then it is replaced by
385     *  either the top or the bottom, depending on its sign.  To leave
386     *  either the bottom or the top unconstrained, specify
387     *  Integer.MIN_VALUE or Integer.MAX_VALUE.
388     *  <p>If the length of the array is 0, return a new array of length 0.
389     *  @param array An array of ints.
390     *  @param bottom The bottom limit.
391     *  @param top The top limit.
392     *  @return A new array with values in the range [bottom, top].
393     */
394    public static final int[] limit(final int[] array, final int bottom,
395            final int top) {
396        int[] returnValue = new int[array.length];
397
398        for (int i = 0; i < array.length; i++) {
399            if (array[i] > top || array[i] == Integer.MAX_VALUE) {
400                returnValue[i] = top;
401            } else if (array[i] < bottom || array[i] == Integer.MIN_VALUE) {
402                returnValue[i] = bottom;
403            } else {
404                returnValue[i] = array[i];
405            }
406        }
407
408        return returnValue;
409    }
410
411    /** Return a new array that is the formed by the modulo of each element
412     *  of the input array and z (array[i] % z).
413     */
414    public static final int[] modulo(final int[] array, final int z) {
415        int length = array.length;
416        int[] returnValue = new int[length];
417
418        for (int i = 0; i < length; i++) {
419            returnValue[i] = array[i] % z;
420        }
421
422        return returnValue;
423    }
424
425    /** Return a new array that is the element-by-element modulo of the two
426     *  input arrays (array1[i] % array2[i]).
427     *  If the lengths of both arrays are 0, return a new array of length 0.
428     *  If the two arrays do not have the same length, throw an
429     *  IllegalArgumentException.
430     */
431    public static final int[] modulo(final int[] array1, final int[] array2) {
432        int length = _commonLength(array1, array2, "IntegerArrayMath.modulo");
433        int[] returnValue = new int[length];
434
435        for (int i = 0; i < length; i++) {
436            returnValue[i] = array1[i] % array2[i];
437        }
438
439        return returnValue;
440    }
441
442    /** Return a new array that is the element-by-element multiplication of
443     *  the two input arrays.
444     *  If the lengths of both arrays are 0, return a new array of length 0.
445     *  If the two arrays do not have the same length, throw an
446     *  IllegalArgumentException.
447     */
448    public static final int[] multiply(final int[] array1, final int[] array2) {
449        int length = _commonLength(array1, array2, "IntegerArrayMath.multiply");
450        int[] returnValue = new int[length];
451
452        for (int i = 0; i < length; i++) {
453            returnValue[i] = array1[i] * array2[i];
454        }
455
456        return returnValue;
457    }
458
459    /** Return a new array that is constructed from the argument by
460     *  multiplying each element in the array by the second argument, which is
461     *  an int.
462     *  If the sizes of the array is 0, return a new array of size 0.
463     *  @param array An array of ints.
464     *  @param factor An int.
465     *  @return A new array of ints.
466     */
467    public static final int[] multiply(int[] array, int factor) {
468        int length = array.length;
469        int[] returnValue = new int[length];
470
471        for (int i = 0; i < length; i++) {
472            returnValue[i] = array[i] * factor;
473        }
474
475        return returnValue;
476    }
477
478    /** Return a new array that is the formed by the additive inverse of each
479     *  element of the input array (-array[i]).
480     */
481    public static final int[] negative(final int[] array) {
482        int length = array.length;
483        int[] returnValue = new int[length];
484
485        for (int i = 0; i < length; i++) {
486            returnValue[i] = -array[i];
487        }
488
489        return returnValue;
490    }
491
492    /** Return a new array of ints that is formed by padding the
493     *  middle of the array with 0's. If either the length of the
494     *  input array is odd, the sample with index ceil(L/2) will be
495     *  repeated in the output array, where L is the length of the input array.
496     *  If the length of the input and output arrays are equal, return
497     *  a copy of the input array.
498     *  This method is useful for preparing data for an IFFT.
499     *  @param array An array of ints.
500     *  @param newLength The desired length of the returned array.
501     *  @return A new array of ints.
502     */
503    public static final int[] padMiddle(final int[] array,
504            final int newLength) {
505        int length = array.length;
506
507        int entriesNeeded = newLength - length;
508
509        if (entriesNeeded < 0) {
510            throw new IllegalArgumentException("ptolemy.math."
511                    + "IntegerArrayMath.padMiddle() : newLength must be "
512                    + " >= length of array.");
513        } else if (entriesNeeded == 0) {
514            return resize(array, newLength); // allocates a new array
515        }
516
517        double halfLength = length * 0.5;
518        int halfLengthFloor = (int) Math.floor(halfLength);
519        int halfLengthCeil = (int) Math.ceil(halfLength);
520        int[] returnValue = new int[newLength];
521
522        System.arraycopy(array, 0, returnValue, 0, halfLengthCeil);
523
524        System.arraycopy(array, halfLengthFloor, returnValue,
525                newLength - halfLengthCeil, halfLengthCeil);
526
527        return returnValue;
528    }
529
530    /** Return a new array of length newLength that is formed by
531     *  either truncating or padding the input array.
532     *  This method simply calls :
533     *  resize(array, newLength, 0)
534     *  @param array An array of ints.
535     *  @param newLength The desired length of the output array.
536     *  @return A new array of ints of length newLength.
537     */
538    public static final int[] resize(final int[] array, final int newLength) {
539        return resize(array, newLength, 0);
540    }
541
542    /** Return a new array of length newLength that is formed by
543     *  either truncating or padding the input array.
544     *  Elements from the input array are copied to the output array,
545     *  starting from array[startIdx] until one of the following conditions
546     *  is met :
547     *  1) The input array has no more elements to copy.
548     *  2) The output array has been completely filled.
549     *  startIdx must index a valid entry in array unless the input array
550     *  is of zero length or the output array is of zero length.
551     *  If case 1) is met, the remainder of the output array is filled with
552     *  zero's, implicitly by Java (padding).
553     *  @param array An array of ints.
554     *  @param newLength The desired length of the output array.
555     *  @param startIdx The starting index for the input array.
556     *  @return A new array of ints of length newLength.
557     */
558    public static final int[] resize(int[] array, final int newLength,
559            final int startIdx) {
560        int[] returnValue = new int[newLength];
561        int copySize = Math.min(newLength, array.length - startIdx);
562
563        if (startIdx >= array.length && copySize > 0) {
564            throw new IllegalArgumentException("resize():  the start index '"
565                    + startIdx + "' is greater than equal to the array length '"
566                    + array.length + "' and the number of items to be copied '"
567                    + copySize + "' is greater than zero.");
568        }
569
570        if (copySize > 0) {
571            System.arraycopy(array, startIdx, returnValue, 0, copySize);
572        }
573
574        return returnValue;
575    }
576
577    /** Return a new array of ints produced by scaling the input
578     *  array elements by scaleFactor.
579     *  If the length of the array is 0, return a new array of length 0.
580     */
581    public static final int[] scale(int[] array, int scaleFactor) {
582        int[] returnValue = new int[array.length];
583
584        for (int i = 0; i < array.length; i++) {
585            returnValue[i] = scaleFactor * array[i];
586        }
587
588        return returnValue;
589    }
590
591    /** Return a new array that is constructed from the argument by
592     *  arithmetically shifting the elements in the array by the
593     *  second argument.  If the second argument is positive, the
594     *  elements are shifted left by the second argument. If the
595     *  second argument is negative, the elements are shifted right
596     *  (arithmetically, with the &gt;&gt;&gt; operator) by the absolute value
597     *  of the second argument. If the second argument is 0, no
598     *  operation is performed (the array is just copied).
599     *
600     *  @param array A first array of ints.
601     *  @param shiftAmount The amount to shift by, positive for left shift,
602     *  negative for right shift.
603     *  @return A new array of ints.
604     */
605    public static final int[] shiftArithmetic(int[] array, int shiftAmount) {
606        int[] returnValue = new int[array.length];
607
608        if (shiftAmount >= 0) {
609            for (int i = 0; i < array.length; i++) {
610                returnValue[i] = array[i] << shiftAmount;
611            }
612        } else if (shiftAmount < 0) {
613            for (int i = 0; i < array.length; i++) {
614                returnValue[i] = array[i] >>> -shiftAmount;
615            }
616        }
617
618        return returnValue;
619    }
620
621    /** Return a new array that is constructed from the argument by
622     *  logically shifting the elements in the array by the second
623     *  argument.  If the second argument is positive, the elements
624     *  are shifted left by the second argument. If the second
625     *  argument is negative, the elements are shifted right
626     *  (logically, with the &gt;&gt;&gt; operator) by the absolute value of
627     *  the second argument. If the second argument is 0, no operation
628     *  is performed (the array is just copied).
629     *
630     *  @param array A first array of ints.
631     *  @param shiftAmount The amount to shift by, positive for left shift,
632     *  negative for right shift.
633     *  @return A new array of ints.
634     */
635    public static final int[] shiftLogical(int[] array, int shiftAmount) {
636        int[] returnValue = new int[array.length];
637
638        if (shiftAmount >= 0) {
639            for (int i = 0; i < array.length; i++) {
640                returnValue[i] = array[i] << shiftAmount;
641            }
642        } else if (shiftAmount < 0) {
643            for (int i = 0; i < array.length; i++) {
644                returnValue[i] = array[i] >> -shiftAmount;
645            }
646        }
647
648        return returnValue;
649    }
650
651    /** Return a new array that is the element-by-element difference of the
652     *  two input arrays, i.e. the first array minus the second array
653     *  (array1[i] - array2[i]).
654     *  If the lengths of both arrays are 0, return a new array of length 0.
655     */
656    public static final int[] subtract(final int[] array1, final int[] array2) {
657        int length = _commonLength(array1, array2, "IntegerArrayMath.subtract");
658        int[] returnValue = new int[length];
659
660        for (int i = 0; i < length; i++) {
661            returnValue[i] = array1[i] - array2[i];
662        }
663
664        return returnValue;
665    }
666
667    /** Return the sum of the squares of all of the elements in the array.
668     *  This is equivalent to the square of the L2-norm of the array.
669     *  Return 0 if the length of the array is 0.
670     */
671    public static final int sumOfSquares(int[] array) {
672        int sum = 0;
673
674        for (int element : array) {
675            sum += element * element;
676        }
677
678        return sum;
679    }
680
681    /** Return a new array that is formed by converting the integers in
682     *  the argument array to complex numbers. Each complex number has
683     *  real part equal to the value in the argument array and a zero
684     *  imaginary part.
685     *
686     *  @param array An array of integers.
687     *  @return A new array of complex numbers.
688     */
689    public static final Complex[] toComplexArray(final int[] array) {
690        int length = array.length;
691        Complex[] returnValue = new Complex[length];
692
693        for (int i = 0; i < length; i++) {
694            returnValue[i] = new Complex(array[i], 0.0);
695        }
696
697        return returnValue;
698    }
699
700    /** Return a new array that is formed by converting the ints in
701     *  the argument array to doubles.  If the length of the argument
702     *  array is 0, return a new array of length 0.
703     *  @param array An array of int.
704     *  @return A new array of doubles.
705     */
706    public static final double[] toDoubleArray(final int[] array) {
707        int length = array.length;
708        double[] returnValue = new double[length];
709
710        for (int i = 0; i < length; i++) {
711            returnValue[i] = array[i];
712        }
713
714        return returnValue;
715    }
716
717    /** Return a new array that is formed by converting the ints in
718     *  the argument array to doubles.
719     *  If the length of the argument array is 0,
720     *  return a new array of length 0.
721     *  @param array An array of int.
722     *  @return A new array of doubles.
723     */
724    public static final float[] toFloatArray(final int[] array) {
725        int length = array.length;
726        float[] returnValue = new float[length];
727
728        for (int i = 0; i < length; i++) {
729            returnValue[i] = array[i];
730        }
731
732        return returnValue;
733    }
734
735    /** Return a new array that is formed by converting the ints in
736     *  the argument array to longs.  If the length of the argument
737     *  array is 0, return a new array of length 0.
738     *  @param array An array of int.
739     *  @return A new array of longs.
740     */
741    public static final long[] toLongArray(final int[] array) {
742        int length = array.length;
743        long[] returnValue = new long[length];
744
745        for (int i = 0; i < length; i++) {
746            returnValue[i] = array[i];
747        }
748
749        return returnValue;
750    }
751
752    /** Return a new String representing the array, formatted as
753     *  in Java array initializers.
754     */
755    public static final String toString(final int[] array) {
756        return toString(array, ", ", "{", "}");
757    }
758
759    /** Return a new String representing the array, formatted as
760     *  specified by the ArrayStringFormat argument.
761     *  To get a String in the Ptolemy expression language format,
762     *  call this method with ArrayStringFormat.exprASFormat as the
763     *  format argument.
764     */
765    public static final String toString(final int[] array,
766            String elementDelimiter, String vectorBegin, String vectorEnd) {
767        int length = array.length;
768        StringBuffer sb = new StringBuffer();
769
770        sb.append(vectorBegin);
771
772        for (int i = 0; i < length; i++) {
773            sb.append(Integer.toString(array[i]));
774
775            if (i < length - 1) {
776                sb.append(elementDelimiter);
777            }
778        }
779
780        sb.append(vectorEnd);
781
782        return new String(sb);
783    }
784
785    /** Return true if all the distances between corresponding elements
786     *  <i>array1</i> and <i>array2</i> are all less than or equal to
787     *  the corresponding elements in <i>maxError</i>. If both arrays
788     *  are empty, return true. If <i>maxError</i> is negative, return false.
789     *
790     *  @param array1 The first array.
791     *  @param array2 The second array.
792     *  @param maxError The threshold for the magnitude of the difference.
793     *  @return True if all the distances between corresponding elements
794     *  <i>array1</i> and <i>array2</i> are all less than or equal to
795     *  the corresponding elements in <i>maxError</i>.
796     *  @exception IllegalArgumentException If the arrays are not of the same
797     *   length.
798     */
799    public static final boolean within(final int[] array1, final int[] array2,
800            int maxError) {
801        int length = _commonLength(array1, array2, "IntegerArrayMath.within");
802
803        for (int i = 0; i < length; i++) {
804            if (array1[i] > array2[i] + maxError
805                    || array1[i] < array2[i] - maxError) {
806                return false;
807            }
808        }
809
810        return true;
811    }
812
813    /** Return true if all the distances between corresponding elements
814     *  <i>array1</i> and <i>array2</i> are all less than or equal to
815     *  the corresponding elements in <i>maxError</i>. If both arrays
816     *  are empty, return true. If any element of <i>maxError</i> is negative
817     *  return false.
818     *
819     *  @param array1 The first array.
820     *  @param array2 The second array.
821     *  @param maxError The array of thresholds for the magnitudes of
822     *   the difference.
823     *  @return True if all the distances between corresponding elements
824     *  <i>array1</i> and <i>array2</i> are all less than or equal to
825     *  the corresponding elements in <i>maxError</i>.
826     *  @exception IllegalArgumentException If the arrays are not of the same
827     *   length.
828     */
829    public static final boolean within(final int[] array1, final int[] array2,
830            int[] maxError) {
831        int length = _commonLength(array1, array2, "IntegerArrayMath.within");
832
833        for (int i = 0; i < length; i++) {
834            if (array1[i] > array2[i] + maxError[i]
835                    || array1[i] < array2[i] - maxError[i]) {
836                return false;
837            }
838        }
839
840        return true;
841    }
842
843    ///////////////////////////////////////////////////////////////////
844    ////                         protected methods                 ////
845
846    /** Throw an exception if the two arrays are not of the same length,
847     *  or if either array is null. An exception is NOT thrown if both
848     *  arrays are of length 0. If no exception is thrown, return the common
849     *  length of the arrays.
850     *  @param array1 The first array of ints.
851     *  @param array2 The second array of ints.
852     *  @param methodName A String representing the method name of the caller,
853     *  without parentheses.
854     *  @return The common length of both arrays.
855     */
856    protected static final int _commonLength(final int[] array1,
857            final int[] array2, String methodName) {
858        if (array1 == null) {
859            throw new IllegalArgumentException("ptolemy.math." + methodName
860                    + "() : first input array is null.");
861        }
862
863        if (array2 == null) {
864            throw new IllegalArgumentException("ptolemy.math." + methodName
865                    + "() : second input array is null.");
866        }
867
868        if (array1.length != array2.length) {
869            throw new IllegalArgumentException("ptolemy.math." + methodName
870                    + "() : input arrays must have the same length, "
871                    + "but the first array has length " + array1.length
872                    + " and the second array has length " + array2.length
873                    + ".");
874        }
875
876        return array1.length;
877    }
878}