Fixed problem when integrating & averaging arrays containing NaN's
[debian/openrocket] / core / src / net / sf / openrocket / util / ArrayUtils.java
1 package net.sf.openrocket.util;
2
3 import java.lang.reflect.Array;
4
5 public class ArrayUtils {
6
7         /**
8          * Returns a double array with values from start to end with given step.
9          * Starts exactly at start and stops at the multiple of step <= stop. 
10          */
11         public static double[] range(double start, double stop, double step){
12                 
13                 int size = (int) Math.floor(((stop - start) / step)) + 1;
14                 
15                 //System.out.println("Range from "+start+" to "+stop+" step "+step+" has length "+size);
16                 
17                 double[] output = new double[size];
18                 int i = 0;
19                 double x = start;
20                 while (i<size){
21                         output[i] = x;
22                         x = x+step;
23                         i++;
24                 }
25                 
26                 return output;
27         }
28
29         /**
30          * Return the mean of an array
31          */
32         public static double mean(double[] vals){
33                 double subtotal = 0;
34                 for (int i = 0; i < vals.length; i++ ){
35                         if (!Double.isNaN(vals[i])){
36                                 subtotal += vals[i];
37                         }
38                 }
39                 subtotal = subtotal / vals.length;
40                 return subtotal;
41         }
42
43         /**
44          * Returns the maximum value in the array.
45          */
46
47         public static double max(double[] vals) {
48                 double m = vals[0];
49                 for (int i = 1; i < vals.length; i++)
50                         m = Math.max(m, vals[i]);
51                 return m;
52         }
53
54         /**
55          * Returns the minimum value in the array.
56          */
57
58         public static double min(double[] vals) {
59                 double m = vals[0];
60                 for (int i = 1; i < vals.length; i++)
61                         m = Math.min(m, vals[i]);
62                 return m;
63         }
64
65         /**
66          * Returns the variance of the array of doubles
67          */
68         public static double variance(double[] vals) {
69                 double mu = mean(vals);
70                 double sumsq = 0.0;
71                 double temp = 0;
72                 for (int i = 0; i < vals.length; i++){
73                         if (!Double.isNaN(vals[i])){
74                                 temp = (mu - vals[i]);
75                                 sumsq += temp*temp;
76                         }
77                 }
78                 return sumsq / (vals.length);
79         }
80
81         /**
82          * Returns the standard deviation of an array of doubles
83          */
84         public static double stdev(double[] vals) {
85                 return Math.sqrt(variance(vals));
86         }
87         
88         /**
89          * Returns the RMS value of an array of doubles 
90          */
91         public static double rms(double[] vals) {
92                 double m = mean(vals);
93                 double s = stdev(vals);
94                 return Math.sqrt( m*m + s*s );
95         }
96         
97         /**
98          * Returns the integral of a given array calculated by the trapezoidal rule
99          * dt is the time step between each array value. Any NaN values are treated as zero
100          */
101         public static double trapz(double[] y, double dt){
102                 double stop = (y.length -1) * dt;
103                 
104                 if (y.length <= 1 || dt <= 0) return 0;
105                 
106                 double[] x = range(0, stop, dt);
107             
108             double sum = 0.0;
109             for (int i = 1; i < x.length; i++) {
110                 double temp = (x[i] - x[i-1]) * (y[i] + y[i-1]);
111                 if (!Double.isNaN(temp)){
112                         sum += temp;
113                 }
114             }
115             return sum * 0.5;
116         }
117         
118         /**
119          * Returns the nearest value in an array to a given value
120          * Search starts from the lowest array index
121          */
122         public static double tnear(double[] range, double near, double start, double step){
123                 double min = Double.POSITIVE_INFINITY;
124                 int mini = 0;
125                 
126                 //System.out.println("Nearest to "+near+" in range length "+range.length);
127                 for (int i=0; i < range.length; i++){
128                         double x = Math.abs(range[i] - near);
129                         if (x < min){
130                                 min = x;
131                                 mini = i;
132                         }
133                 }
134                 
135                 //System.out.println("Found nearest at i="+mini);               
136                 return start + (mini*step);
137         }
138         
139         
140         public static <T> T[] copyOf( T[] original, int length ) {
141                 return copyOfRange(original,0,length);
142         }
143         
144         /**
145          * Implementation of java.util.Arrays.copyOfRange
146          * 
147          * Since Froyo does not include this function it must be implemented here.
148          * 
149          * @param original
150          * @param start
151          * @param end
152          * @return
153          */
154         public static <T> T[] copyOfRange( T[] original, int start, int end ) {
155                 
156                 if ( original == null ) {
157                         throw new NullPointerException();
158                 }
159                 
160                 if ( start < 0 || start > original.length ) {
161                         throw new ArrayIndexOutOfBoundsException();
162                 }
163                 
164                 if ( start > end ) {
165                         throw new IllegalArgumentException();
166                 }
167                 
168                 T[] result = (T[]) Array.newInstance( original.getClass().getComponentType(), end-start );
169                 
170                 int index = 0;
171                 int stop = original.length < end ? original.length : end;
172                 for ( int i = start; i < stop; i ++ ) {
173                         if ( i < original.length ) {
174                                 result[index] = original[i];
175                         }
176                         index++;
177                 }
178                 
179                 return result;
180                 
181         }
182
183         public static double[] copyOf( double[] original, int length ) {
184                 return copyOfRange(original,0,length);
185         }
186         
187         public static double[] copyOfRange( double[] original, int start, int end ) {
188                 
189                 if ( original == null ) {
190                         throw new NullPointerException();
191                 }
192                 
193                 if ( start < 0 || start > original.length ) {
194                         throw new ArrayIndexOutOfBoundsException();
195                 }
196                 
197                 if ( start > end ) {
198                         throw new IllegalArgumentException();
199                 }
200                 
201                 double[] result = new double[(end-start)];
202                 
203                 int index = 0;
204                 int stop = original.length < end ? original.length : end;
205                 for ( int i = start; i < stop; i ++ ) {
206                         if ( i < original.length ) {
207                                 result[index] = original[i];
208                         }
209                         index++;
210                 }
211                 
212                 return result;
213                 
214         }
215
216         public static byte[] copyOf( byte[] original, int length ) {
217                 return copyOfRange(original,0,length);
218         }
219         
220         public static byte[] copyOfRange( byte[] original, int start, int end ) {
221                 
222                 if ( original == null ) {
223                         throw new NullPointerException();
224                 }
225                 
226                 if ( start < 0 || start > original.length ) {
227                         throw new ArrayIndexOutOfBoundsException();
228                 }
229                 
230                 if ( start > end ) {
231                         throw new IllegalArgumentException();
232                 }
233                 
234                 byte[] result = new byte[(end-start)];
235                 
236                 int index = 0;
237                 int stop = original.length < end ? original.length : end;
238                 for ( int i = start; i < stop; i ++ ) {
239                         if ( i < original.length ) {
240                                 result[index] = original[i];
241                         }
242                         index++;
243                 }
244                 
245                 return result;
246                 
247         }
248
249 }
250