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 }