001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2009, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * ------------------
028 * DataUtilities.java
029 * ------------------
030 * (C) Copyright 2003-2009, by Object Refinery Limited and contributors.
031 *
032 * Original Author: David Gilbert (for Object Refinery Limited);
033 * Contributor(s): Peter Kolb (patch 2511330);
034 *
035 * Changes
036 * -------
037 * 05-Mar-2003 : Version 1 (DG);
038 * 03-Mar-2005 : Moved createNumberArray() and createNumberArray2D() methods
039 * from the DatasetUtilities class (DG);
040 * 17-May-2005 : Added calculateColumnTotal() and calculateRowTotal()
041 * methods (DG);
042 * 28-Jan-2009 : Added equal(double[][], double[][]) method (DG);
043 * 28-Jan-2009 : Added clone(double[][]) method (DG);
044 * 04-Feb-2009 : Added calculateColumnTotal/RowTotal variants (PK);
045 *
046 */
047
048 package org.jfree.data;
049
050 import java.util.Arrays;
051 import org.jfree.data.general.DatasetUtilities;
052
053 /**
054 * Utility methods for use with some of the data classes (but not the datasets,
055 * see {@link DatasetUtilities}).
056 */
057 public abstract class DataUtilities {
058
059 /**
060 * Tests two arrays for equality. To be considered equal, the arrays must
061 * have exactly the same dimensions, and the values in each array must also
062 * match (two values that qre both NaN or both INF are considered equal
063 * in this test).
064 *
065 * @param a the first array (<code>null</code> permitted).
066 * @param b the second array (<code>null</code> permitted).
067 *
068 * @return A boolean.
069 *
070 * @since 1.0.13
071 */
072 public static boolean equal(double[][] a, double[][] b) {
073 if (a == null) {
074 return (b == null);
075 }
076 if (b == null) {
077 return false; // already know 'a' isn't null
078 }
079 if (a.length != b.length) {
080 return false;
081 }
082 for (int i = 0; i < a.length; i++) {
083 if (!Arrays.equals(a[i], b[i])) {
084 return false;
085 }
086 }
087 return true;
088 }
089
090 /**
091 * Returns a clone of the specified array.
092 *
093 * @param source the source array (<code>null</code> not permitted).
094 *
095 * @return A clone of the array.
096 *
097 * @since 1.0.13
098 */
099 public static double[][] clone(double[][] source) {
100 if (source == null) {
101 throw new IllegalArgumentException("Null 'source' argument.");
102 }
103 double[][] clone = new double[source.length][];
104 for (int i = 0; i < source.length; i++) {
105 if (source[i] != null) {
106 double[] row = new double[source[i].length];
107 System.arraycopy(source[i], 0, row, 0, source[i].length);
108 clone[i] = row;
109 }
110 }
111 return clone;
112 }
113
114 /**
115 * Returns the total of the values in one column of the supplied data
116 * table.
117 *
118 * @param data the table of values (<code>null</code> not permitted).
119 * @param column the column index (zero-based).
120 *
121 * @return The total of the values in the specified column.
122 */
123 public static double calculateColumnTotal(Values2D data, int column) {
124 if (data == null) {
125 throw new IllegalArgumentException("Null 'data' argument.");
126 }
127 double total = 0.0;
128 int rowCount = data.getRowCount();
129 for (int r = 0; r < rowCount; r++) {
130 Number n = data.getValue(r, column);
131 if (n != null) {
132 total += n.doubleValue();
133 }
134 }
135 return total;
136 }
137
138 /**
139 * Returns the total of the values in one column of the supplied data
140 * table by taking only the row numbers in the array into account.
141 *
142 * @param data the table of values (<code>null</code> not permitted).
143 * @param column the column index (zero-based).
144 * @param validRows the array with valid rows (zero-based).
145 *
146 * @return The total of the valid values in the specified column.
147 *
148 * @since 1.0.13
149 */
150 public static double calculateColumnTotal(Values2D data, int column,
151 int[] validRows) {
152 if (data == null) {
153 throw new IllegalArgumentException("Null 'data' argument.");
154 }
155 double total = 0.0;
156 int rowCount = data.getRowCount();
157 for (int v = 0; v < validRows.length; v++) {
158 int row = validRows[v];
159 if (row < rowCount) {
160 Number n = data.getValue(row, column);
161 if (n != null) {
162 total += n.doubleValue();
163 }
164 }
165 }
166 return total;
167 }
168
169 /**
170 * Returns the total of the values in one row of the supplied data
171 * table.
172 *
173 * @param data the table of values (<code>null</code> not permitted).
174 * @param row the row index (zero-based).
175 *
176 * @return The total of the values in the specified row.
177 */
178 public static double calculateRowTotal(Values2D data, int row) {
179 if (data == null) {
180 throw new IllegalArgumentException("Null 'data' argument.");
181 }
182 double total = 0.0;
183 int columnCount = data.getColumnCount();
184 for (int c = 0; c < columnCount; c++) {
185 Number n = data.getValue(row, c);
186 if (n != null) {
187 total += n.doubleValue();
188 }
189 }
190 return total;
191 }
192
193 /**
194 * Returns the total of the values in one row of the supplied data
195 * table by taking only the column numbers in the array into account.
196 *
197 * @param data the table of values (<code>null</code> not permitted).
198 * @param row the row index (zero-based).
199 * @param validCols the array with valid cols (zero-based).
200 *
201 * @return The total of the valid values in the specified row.
202 *
203 * @since 1.0.13
204 */
205 public static double calculateRowTotal(Values2D data, int row,
206 int[] validCols) {
207 if (data == null) {
208 throw new IllegalArgumentException("Null 'data' argument.");
209 }
210 double total = 0.0;
211 int colCount = data.getColumnCount();
212 for (int v = 0; v < validCols.length; v++) {
213 int col = validCols[v];
214 if (col < colCount) {
215 Number n = data.getValue(row, col);
216 if (n != null) {
217 total += n.doubleValue();
218 }
219 }
220 }
221 return total;
222 }
223
224 /**
225 * Constructs an array of <code>Number</code> objects from an array of
226 * <code>double</code> primitives.
227 *
228 * @param data the data (<code>null</code> not permitted).
229 *
230 * @return An array of <code>Double</code>.
231 */
232 public static Number[] createNumberArray(double[] data) {
233 if (data == null) {
234 throw new IllegalArgumentException("Null 'data' argument.");
235 }
236 Number[] result = new Number[data.length];
237 for (int i = 0; i < data.length; i++) {
238 result[i] = new Double(data[i]);
239 }
240 return result;
241 }
242
243 /**
244 * Constructs an array of arrays of <code>Number</code> objects from a
245 * corresponding structure containing <code>double</code> primitives.
246 *
247 * @param data the data (<code>null</code> not permitted).
248 *
249 * @return An array of <code>Double</code>.
250 */
251 public static Number[][] createNumberArray2D(double[][] data) {
252 if (data == null) {
253 throw new IllegalArgumentException("Null 'data' argument.");
254 }
255 int l1 = data.length;
256 Number[][] result = new Number[l1][];
257 for (int i = 0; i < l1; i++) {
258 result[i] = createNumberArray(data[i]);
259 }
260 return result;
261 }
262
263 /**
264 * Returns a {@link KeyedValues} instance that contains the cumulative
265 * percentage values for the data in another {@link KeyedValues} instance.
266 * <p>
267 * The percentages are values between 0.0 and 1.0 (where 1.0 = 100%).
268 *
269 * @param data the data (<code>null</code> not permitted).
270 *
271 * @return The cumulative percentages.
272 */
273 public static KeyedValues getCumulativePercentages(KeyedValues data) {
274 if (data == null) {
275 throw new IllegalArgumentException("Null 'data' argument.");
276 }
277 DefaultKeyedValues result = new DefaultKeyedValues();
278 double total = 0.0;
279 for (int i = 0; i < data.getItemCount(); i++) {
280 Number v = data.getValue(i);
281 if (v != null) {
282 total = total + v.doubleValue();
283 }
284 }
285 double runningTotal = 0.0;
286 for (int i = 0; i < data.getItemCount(); i++) {
287 Number v = data.getValue(i);
288 if (v != null) {
289 runningTotal = runningTotal + v.doubleValue();
290 }
291 result.addValue(data.getKey(i), new Double(runningTotal / total));
292 }
293 return result;
294 }
295
296 }