View Javadoc
1   /*
2    * The baseCode project
3    * 
4    * Copyright (c) 2006 University of British Columbia
5    * 
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *       http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   *
18   */
19  package ubic.basecode.dataStructure.matrix;
20  
21  import cern.colt.function.DoubleFunction;
22  import cern.colt.list.DoubleArrayList;
23  import cern.colt.list.IntArrayList;
24  import cern.colt.matrix.DoubleMatrix1D;
25  import cern.colt.matrix.DoubleMatrix2D;
26  import cern.colt.matrix.impl.DenseDoubleMatrix2D;
27  
28  /**
29   * A row-compressed 1D matrix. The only deviation from the contract of DoubleMatrix1D is in apply(), which only operates
30   * on the non-empty (0) elements. This implementation has a highly optimized dot product computer. If you need to
31   * compute the dot product of a RCDoubleMatrix1D with another DoubleMatrix1D, call zDotProduct on this, not on the
32   * other. This is because getQuick() and setQuick() are not very fast for this.
33   * 
34   * @author pavlidis
35   * 
36   */
37  public class RCDoubleMatrix1D extends DoubleMatrix1D {
38  
39      private static final long serialVersionUID = -5883440011745758929L;
40      protected IntArrayList indexes;
41      protected DoubleArrayList values;
42  
43      /**
44       * @param values
45       */
46      public RCDoubleMatrix1D( double[] values ) {
47          assign( values );
48      }
49  
50      /**
51       * @param length
52       */
53      public RCDoubleMatrix1D( int length ) {
54          this.indexes = new IntArrayList();
55          this.values = new DoubleArrayList();
56      }
57  
58      /**
59       * @param indexes These MUST be in sorted order.
60       * @param values These MuST be in the same order as the indexes, meaning that indexes[0] is the column for
61       *        values[0].
62       */
63      public RCDoubleMatrix1D( IntArrayList indexes, DoubleArrayList values ) {
64          int k = indexes.size();
65          int s = 0;
66          if ( k > 0 ) {
67              s = indexes.get( k - 1 ) + 1;
68          }
69  
70          setUp( s );
71          this.indexes = indexes;
72          this.values = values;
73      }
74  
75      @Override
76      public DoubleMatrix1D assign( double[] v ) {
77          this.indexes = new IntArrayList();
78          this.values = new DoubleArrayList();
79          for ( int i = 0; i < v.length; i++ ) {
80              if ( v[i] == 0 || Double.isNaN( v[i] ) ) {
81                  continue;
82              }
83              this.indexes.add( i );
84              this.values.add( v[i] );
85          }
86          this.size = v.length;
87          return this;
88      }
89  
90      /**
91       * WARNING this only assigns to the non-empty values, for performance reasons. If you need to assign to any index,
92       * you have to use another way.
93       * 
94       * @see cern.colt.matrix.DoubleMatrix1D#assign(cern.colt.function.DoubleFunction)
95       */
96      @Override
97      public DoubleMatrix1D assign( DoubleFunction function ) {
98          for ( int i = values.size(); --i >= 0; ) {
99              values.set( i, function.apply( values.get( i ) ) );
100         }
101         return this;
102     }
103 
104     @Override
105     public double get( int index ) {
106         return this.getQuick( index );
107     }
108 
109     /*
110      * (non-Javadoc)
111      * 
112      * @see cern.colt.matrix.DoubleMatrix1D#getQuick(int)
113      */
114     @Override
115     public double getQuick( int index ) {
116 
117         int location = indexes.binarySearch( index );
118 
119         if ( location >= 0 ) {
120             return values.get( location );
121         }
122         return 0;
123     }
124 
125     /*
126      * (non-Javadoc)
127      * 
128      * @see cern.colt.matrix.DoubleMatrix1D#like(int)
129      */
130     @Override
131     public DoubleMatrix1D like( int s ) {
132         return new RCDoubleMatrix1D( s );
133     }
134 
135     /*
136      * (non-Javadoc)
137      * 
138      * @see cern.colt.matrix.DoubleMatrix1D#like2D(int, int)
139      */
140     @Override
141     public DoubleMatrix2D like2D( int rows, int columns ) {
142         return new DenseDoubleMatrix2D( rows, columns );
143     }
144 
145     /*
146      * (non-Javadoc)
147      * 
148      * @see cern.colt.matrix.DoubleMatrix1D#setQuick(int, double)
149      */
150     @Override
151     public void setQuick( int column, double value ) {
152         int location = indexes.binarySearch( column );
153 
154         if ( location >= 0 ) {
155             values.set( location, value ); // just change the value
156         } else {
157             location = -location - 1; // e.g., -1 means to insert just before 0.
158             indexes.beforeInsert( location, column ); // add this column, so the order is still right.
159             values.beforeInsert( location, value ); // keep this in the same order.
160         }
161     }
162 
163     /*
164      * (non-Javadoc)
165      * 
166      * @see java.lang.Object#toString()
167      */
168     @Override
169     public String toString() {
170         int used = 0;
171         StringBuilder buf = new StringBuilder();
172         for ( int i = 0; i < indexes.size(); i++ ) {
173             int index = indexes.get( i );
174             while ( index > used ) {
175                 buf.append( " 0" );
176                 used++;
177             }
178             buf.append( " " + values.get( i ) );
179         }
180         return buf.toString();
181 
182     }
183 
184     /*
185      * (non-Javadoc)
186      * 
187      * @see cern.colt.matrix.DoubleMatrix1D#zDotProduct(cern.colt.matrix.DoubleMatrix1D)
188      */
189     @Override
190     public double zDotProduct( DoubleMatrix1D y ) {
191 
192         int[] idx = indexes.elements();
193         double[] el = values.elements();
194         double[] other = y.toArray();
195         double returnVal = 0.0;
196         int otherSize = y.size();
197         for ( int i = idx.length; --i >= 0; ) {
198             int index = idx[i];
199             if ( index >= otherSize ) continue; // in case our arrays are ragged.
200             returnVal += el[i] * other[index];
201         }
202         return returnVal;
203     }
204 
205     /*
206      * (non-Javadoc)
207      * 
208      * @see cern.colt.matrix.DoubleMatrix1D#zSum()
209      */
210     @Override
211     public double zSum() {
212         double sum = 0.0;
213         double[] elements = values.elements();
214         for ( int i = elements.length; --i >= 0; ) {
215             sum += elements[i];
216         }
217         return sum;
218     }
219 
220     /*
221      * (non-Javadoc)
222      * 
223      * @see cern.colt.matrix.DoubleMatrix1D#viewSelectionLike(int[])
224      */
225     @Override
226     protected DoubleMatrix1D viewSelectionLike( int[] offsets ) {
227         throw new UnsupportedOperationException(); // should never be called
228     }
229 }