/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Table2D.java
* Written by Jonathan Gainsley, Sun Microsystems.
*
* Copyright (c) 2009 Sun Microsystems and Static Free Software
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.simulation.sctiming;
import java.util.Map;
import java.util.HashMap;
/**
* Table2D stores data in a more intiuitive fashion than TableData for results
* that are a function of two parameters being swept in the spice run.
* The row and col indices are these two parameters. Because there
* are several other measures, each 2D-array of data is assigned a key,
* which is the name of the measure. Thus a Table2D is really a 3D table,
* but it is represented as a set of 2D tables.
* <P>
* Note that this table converts all keys to lower case to deal with
* Spice, which converts everything to lower case.
* User: gainsley
* Date: Nov 16, 2006
*/
public class Table2D {
private double [] rowVals;
private double [] colVals;
private String rowName;
private String colName;
private Map<String,double [][]> valuesMap;
/**
* Create a new Table2D.
* Note: size is fixed once created.
* @param rowVals row index values
* @param rowName name of the row index param
* @param colVals column index values
* @param colName name of the column index param
*/
public Table2D(double [] rowVals, String rowName, double [] colVals, String colName) {
this.rowVals = rowVals;
this.colVals = colVals;
this.rowName = rowName.toLowerCase();
this.colName = colName.toLowerCase();
//Arrays.sort(this.rowVals);
//Arrays.sort(this.colVals);
valuesMap = new HashMap<String,double[][]>();
}
/**
* Get the name of the row header name
* @return name of the row header
*/
public String getRowName() { return rowName; }
/**
* Get the name of the column header name
* @return name of the column header
*/
public String getColName() { return colName; }
/**
* Get the number of rows in the table
* @return number of rows in the table
*/
public int getNumRows() { return rowVals.length; }
/**
* Get the number of columns in the table
* @return number of columns in the table
*/
public int getNumCols() { return colVals.length; }
/**
* Get the index values for the columns
* @return index values for the columns
*/
public double [] getColIndexVals() { return colVals; }
/**
* Get the index values for the rows
* @return index values for the rows
*/
public double [] getRowIndexVals() { return rowVals; }
/**
* Set the value for a given row and column value. Table2D can
* hold multiple sets of values for the same row and column values,
* so a key is used to access a particular set of 2D data.
* @param rowVal the row index value
* @param colVal the column index value
* @param dataKey the key for the data set
* @param value the value at the row and column value
*/
public void setValue(double rowVal, double colVal, String dataKey, double value) {
dataKey = dataKey.toLowerCase();
double [][] values = valuesMap.get(dataKey);
if (values == null) {
values = new double[rowVals.length][colVals.length];
valuesMap.put(dataKey, values);
}
int i1, i2;
for (i1=0; i1<rowVals.length; i1++) {
if (rowVals[i1] == rowVal) break;
}
if (i1 == rowVals.length) {
System.out.println("Cannot find value "+rowVal +" in row values");
return;
}
for (i2=0; i2<colVals.length; i2++) {
if (colVals[i2] == colVal) break;
}
if (i2 == colVals.length) {
System.out.println("Cannot find value "+colVal +" in column values");
return;
}
values[i1][i2] = value;
}
/**
* Get the value for a given row and column value. Table2D can
* hold multiple sets of values for the same row and column values, so
* a key is used to access a particular set of 2D data.
* @param rowVal the row index value
* @param colVal the column index value
* @param dataKey the key for the data set
* @return the value at the row and column value
*/
public double getValue(double rowVal, double colVal, String dataKey) {
dataKey = dataKey.toLowerCase();
double [][] values = valuesMap.get(dataKey);
if (values == null) {
System.out.println("Data key "+dataKey+" not found");
return Double.MIN_VALUE;
}
int i1, i2;
for (i1=0; i1<rowVals.length; i1++) {
if (rowVals[i1] == rowVal) break;
}
if (i1 == rowVals.length) {
System.out.println("Cannot find value "+rowVal +" in row values");
return Double.MIN_VALUE;
}
for (i2=0; i2<colVals.length; i2++) {
if (colVals[i2] == colVal) break;
}
if (i2 == colVals.length) {
System.out.println("Cannot find value "+colVal +" in column values");
return Double.MIN_VALUE;
}
return values[i1][i2];
}
/**
* Set the data for a given data key. The Data must size rows x cols.
* This will replace any previous data stored under that key.
* @param dataKey the data key
* @param data the data
*/
public void setData(String dataKey, double [][] data) {
dataKey = dataKey.toLowerCase();
if (data.length != rowVals.length) return;
for (int i=0; i<data.length; i++) {
if (data[i].length != colVals.length) return;
}
valuesMap.put(dataKey, data);
}
/**
* Get the values in a column for a specific set of data.
* @param key denotes the set of data to use
* @param colIndex which column to get data
* @return an array of values, the 0th index being from row 0,
* and the Nth index from row N.
*/
public double [] getColumnValues(String key, int colIndex) {
key = key.toLowerCase();
double [][] values = valuesMap.get(key);
if (values == null) return null;
double [] col = new double[values.length];
for (int i=0; i<values.length; i++) {
col[i] = values[i][colIndex];
}
return col;
}
/**
* Get the values in a row for a specific set of data.
* @param key denotes the set of data to use
* @param rowIndex which row to get
* @return an array of values, the 0th index being from col 0,
* and the Nth index from col N.
*/
public double [] getRowValues(String key, int rowIndex) {
key = key.toLowerCase();
double [][] values = valuesMap.get(key);
if (values == null) return null;
return values[rowIndex];
}
/**
* Get the average (mean) of a set of values
* @param vals the values
* @return the mean
*/
public static double getAverage(double [] vals) {
double total = 0;
for (int i=0; i<vals.length; i++) {
total += vals[i];
}
return total/vals.length;
}
/**
* Get the standard deviation of a set of values
* @param vals the values
* @return the mean
*/
public static double getStandardDeviation(double [] vals) {
double avg = getAverage(vals);
double total = 0;
for (int i=0; i<vals.length; i++) {
double diff = avg - vals[i];
total += diff*diff;
}
return Math.sqrt(total/vals.length);
}
/**
* Get the average (mean) of all values
* @param vals the values
* @return the mean
*/
public static double getAverage(double [][] vals) {
double total = 0;
int count = 0;
for (int i=0; i<vals.length; i++) {
double [] row = vals[i];
for (int j=0; j<row.length; j++) {
total += row[j];
count++;
}
}
return total/count;
}
/**
* Get the standard deviation of a set of values
* @param vals the values
* @return the mean
*/
public static double getStandardDeviation(double [][] vals) {
double avg = getAverage(vals);
double total = 0;
int count = 0;
for (int i=0; i<vals.length; i++) {
double [] row = vals[i];
for (int j=0; j<row.length; j++) {
double diff = avg - row[j];
total += diff*diff;
count++;
}
}
return Math.sqrt(total/count);
}
/**
* Get the average (mean) value for a particular column.
* Returns zero if no such data for the key is found.
* @param key the data key
* @param colIndex the column index (not column value)
* @return the mean
*/
public double getAvgColumnValue(String key, int colIndex) {
key = key.toLowerCase();
double [][] values = valuesMap.get(key);
if (values == null) return 0;
double total = 0;
for (int i=0; i<values.length; i++) {
double [] row = values[i];
total += row[colIndex];
}
return total/values.length;
}
/**
* Get the average (mean) values for columns.
* Returns zero in all entries if no such data for the key is found.
* @param key the data key
* @return the means
*/
public double [] getAvgColumnValues(String key) {
key = key.toLowerCase();
double [] avgvals = new double[colVals.length];
for (int i=0; i<colVals.length; i++) {
avgvals[i] = getAvgColumnValue(key, i);
}
return avgvals;
}
/**
* Get the average (mean) value for a particular row.
* Returns zero if no such data for the key is found.
* @param key the data key
* @param rowIndex the row index (not row value)
* @return the mean
*/
public double getAvgRowValue(String key, int rowIndex) {
key = key.toLowerCase();
double [][] values = valuesMap.get(key);
if (values == null) return 0;
double [] row = values[rowIndex];
return getAverage(row);
}
/**
* Get the average (mean) values for rows.
* Returns zero in all entries if no such data for the key is found.
* @param key the data key
* @return the means
*/
public double [] getAvgRowValues(String key) {
key = key.toLowerCase();
double [] avgvals = new double[rowVals.length];
for (int i=0; i<rowVals.length; i++) {
avgvals[i] = getAvgRowValue(key, i);
}
return avgvals;
}
/**
* Get values[rows][cols] for the specified key
* @param key which data set
* @return values array
*/
public double [][] getValues(String key) {
key = key.toLowerCase();
return valuesMap.get(key);
}
/**
* Print to System.out a nicely formatted ASCII table
* of all data in this Table2D.
*/
public void print() {
for (String s : valuesMap.keySet())
print(s);
}
/**
* Print a nicely formatted ASCII table of the data
* for the given key
* @param key the key
*/
public void print(String key) {
key = key.toLowerCase();
System.out.println("---------------------------------------------------");
System.out.println(key+":");
System.out.println("---------------------------------------------------");
double [][] values = valuesMap.get(key);
if (values == null) return;
System.out.println("\t"+colName);
System.out.println(rowName);
System.out.print("\t");
for (int i=0; i<colVals.length; i++) {
System.out.print(colVals[i]+"\t");
}
System.out.println();
for (int i=0; i<rowVals.length; i++) {
System.out.print(rowVals[i]+"\t");
double [] vals = values[i];
for (int i2=0; i2<colVals.length; i2++) {
System.out.print(vals[i2]+"\t");
}
System.out.println();
}
System.out.println();
}
}