package org.das2.qds; import java.util.Arrays; import org.das2.qds.ops.Ops; /** * dataset for modeling when data values repeat. Instead of storing * copies of the data, the get method looks up the index. For example: *
 * ds= CdfSparseDataSet(1,200,dataset(1))
 * ds.putValues( 10, dataset(2) )
 * ds.putValues( 110, dataset(3) )
 * plot( ds )
 * 
* @author faden@cottagesystems.com */ public class CdfSparseDataSet extends AbstractDataSet { int rank; /** * the number of records in the data set. */ int length; /** * the indices for each dataset in dss. Values starting at this index will have the value in the corresponding dss, * and the first index must be 0. */ int[] indexes; /** * the data to return, starting at this index. */ QDataSet[] dss; /** * used with indexInternal, this is the last index looked up. The idea is that often this will be correct and * the value operation will be a constant-time operation, not logN time. */ private int lastIndex; /** * create the DataSet with the given length. * @param rank the result rank. * @param length the result length. * @param value all indices will have this value */ public CdfSparseDataSet( int rank, int length, QDataSet value ) { if ( rank<1 ) throw new IllegalArgumentException("rank must be 1 or more"); this.rank= rank; if ( (this.rank-1)!=value.rank() ) { throw new IllegalArgumentException("value rank must be the same as the rank"); } this.length= length; indexes= new int[] { 0, length }; dss= new QDataSet[] { value, null }; } @Override public int rank() { return this.rank; } /** * insert these values into the dataset. * @param i0 the insertion index, these must be inserted in order. * @param ds the dataset for this index and those after. */ public synchronized void putValues( int i0, QDataSet ds ) { if ( isImmutable() ) throw new IllegalArgumentException("dataset has been made immutable"); if ( ds==null && i0=0 ) { if ( indexes[lastIndex]<=i0 && i0-1 ) { lastIndex= i; } else { throw new IllegalArgumentException("zeroth index must be specified."); } return lastIndex; } /** * return the number of different datasets. * @return the number of different datasets. */ public int datasetCount() { return dss.length-1; } /** * allow clients to reset the length. * @param length */ public void setLength( int length ) { if ( isImmutable() ) throw new IllegalArgumentException("dataset has been made immutable"); this.length= length; } @Override public int length() { return this.length; } @Override public int length(int i0) { int i= indexInternal(i0); return dss[i].length(); } @Override public int length(int i0, int i1) { int i= indexInternal(i0); return dss[i].length(i1); } @Override public int length(int i0, int i1,int i2) { int i= indexInternal(i0); return dss[i].length(i1,i2); } @Override public double value(int i0) { int i= indexInternal(i0); return dss[i].value(); } @Override public double value(int i0,int i1) { int i= indexInternal(i0); return dss[i].value(i1); } @Override public double value(int i0,int i1, int i2) { int i= indexInternal(i0); return dss[i].value(i1,i2); } @Override public double value(int i0,int i1, int i2, int i3 ) { int i= indexInternal(i0); return dss[i].value(i1,i2,i3); } @Override public QDataSet slice(int i0) { int i= indexInternal(i0); return dss[i]; } @Override public QDataSet trim(int i0, int i1) { if ( i0<0 ) throw new IndexOutOfBoundsException(); if ( i1>length ) throw new IndexOutOfBoundsException(); if ( i0>i1 ) throw new IndexOutOfBoundsException(); int ii0= indexInternal(i0); int ii1= indexInternal(i1); CdfSparseDataSet result= new CdfSparseDataSet(rank,i1-i0,dss[ii0]); synchronized ( this ) { if ( ii0>0 ) { result.putValues(0,dss[ii0]); } for ( int ii=ii0+1; ii<=ii1; ii++ ) { result.putValues(indexes[ii]-i0,dss[ii]); } } DataSetUtil.putProperties( DataSetUtil.getDimensionProperties( this, null ), result ); return result; } }