6a8083f72806971c15a404d86b575f993413fd0b
[scilab.git] / scilab / modules / types / src / java / org / scilab / modules / types / ScilabSparse.java
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011-2011 - DIGITEO - Calixte DENIZET
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 package org.scilab.modules.types;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.List;
18
19 /**
20  * This class provides a representation on the Scilab Sparse datatype<br>
21  * <br>
22  * This class is {@link java.io.Serializable} and any modification could
23  * impact load and store of data (Xcos files, Javasci saved data, etc...).<br>
24  * <br>
25  * //TODO Sly : ajouter de la doc
26  * @see org.scilab.modules.javasci.Scilab
27  */
28 public class ScilabSparse implements ScilabType {
29
30     private static final long serialVersionUID = 879625048944109684L;
31     private static final ScilabTypeEnum type = ScilabTypeEnum.sci_sparse;
32
33     private int rows;
34     private int cols;
35     private int nbItem;
36     private int[] nbItemRow;
37     private int[] colPos;
38     private double[] realPart;
39     private double[] imaginaryPart;
40     private String varName;
41
42     /**
43      * Default constructor
44      */
45     public ScilabSparse() { }
46
47     /**
48      * Constructor with a unique value.
49      * @param data the unique value
50      */
51     public ScilabSparse(double data) {
52         if (data != 0) {
53             nbItem = 1;
54             rows = cols = 1;
55             nbItemRow = new int[]{1};
56             colPos = new int[]{0};
57             realPart = new double[]{ data };
58         }
59     }
60
61     /**
62      * Constructor with a unique complex value.
63      *
64      * @param realData the real part
65      * @param imagData the complex part
66      */
67     public ScilabSparse(double realData, double imagData) {
68         if (realData != 0 || imagData != 0) {
69             nbItem = 1;
70             rows = cols = 1;
71             nbItemRow = new int[]{1};
72             colPos = new int[]{0};
73             realPart = new double[]{ realData };
74             imaginaryPart = new double[]{ imagData };
75         }
76     }
77
78     /**
79      * Constructor
80      *
81      * @param rows the number of rows
82      * @param cols the number of cols
83      * @param nbItem the number of non null items
84      * @param nbItemRow contains the number of true in each rows
85      * @param colPos the column position of each non null item
86      * @param data the non null data
87      */
88     public ScilabSparse(int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] data) {
89         this.rows = rows;
90         this.cols = cols;
91         this.nbItem = nbItem;
92         this.nbItemRow = nbItemRow;
93         this.colPos = colPos;
94         this.realPart = data;
95     }
96
97     /**
98      * Constructor
99      *
100      * @param rows the number of rows
101      * @param cols the number of cols
102      * @param nbItem the number of non null items
103      * @param nbItemRow contains the number of true in each rows
104      * @param colPos the column position of each non null item
105      * @param real the non null real data
106      * @param imag the non null imaginary data
107      */
108     public ScilabSparse(int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] real, double[] imag) {
109         this(rows, cols, nbItem, nbItemRow, colPos, real);
110         this.imaginaryPart = imag;
111     }
112
113     /**
114      * Constructor with a matrix of real data.
115      *
116      * @param data the data
117      */
118     public ScilabSparse(double[][] data) {
119         if (data.length != 0 && data[0].length != 0) {
120             rows = data.length;
121             cols = data[0].length;
122             nbItemRow = new int[rows];
123             List<Integer> listCol = new ArrayList<Integer>();
124             List<Double> listVal = new ArrayList<Double>();
125
126             for (int i = 0; i < rows; i++) {
127                 for (int j = 0; j < cols; j++) {
128                     if (data[i][j] != 0) {
129                         ++nbItem;
130                         ++nbItemRow[i];
131                         listCol.add(j);
132                         listVal.add(data[i][j]);
133                     }
134                 }
135             }
136
137             colPos = new int[listCol.size()];
138             realPart = new double[colPos.length];
139             int i = 0;
140             for (Integer c : listCol) {
141                 colPos[i++] = c;
142             }
143             for (Double x : listVal) {
144                 realPart[i++] = x;
145             }
146         }
147     }
148
149     /**
150      * Constructor with a matrix of complex numbers
151      *
152      * @param realData the real part of the data
153      * @param imagData the imaginary part of the data
154      */
155     public ScilabSparse(double[][] realData, double[][] imagData) {
156         if (realData.length != 0 && realData[0].length != 0) {
157             rows = realData.length;
158             cols = realData[0].length;
159             nbItemRow = new int[rows];
160             List<Integer> listCol = new ArrayList<Integer>();
161             List<Double> listReal = new ArrayList<Double>();
162             List<Double> listImag = new ArrayList<Double>();
163
164             for (int i = 0; i < rows; i++) {
165                 for (int j = 0; j < cols; j++) {
166                     if (realData[i][j] != 0 || imagData[i][j] != 0) {
167                         ++nbItem;
168                         ++nbItemRow[i];
169                         listCol.add(j);
170                         listReal.add(realData[i][j]);
171                         listImag.add(imagData[i][j]);
172                     }
173                 }
174             }
175
176             colPos = new int[listCol.size()];
177             this.realPart = new double[colPos.length];
178             this.imaginaryPart = new double[colPos.length];
179             int i = 0;
180             for (Integer c : listCol) {
181                 colPos[i++] = c;
182             }
183             i = 0;
184             for (Double x : listReal) {
185                 this.realPart[i++] = x;
186             }
187             i = 0;
188             for (Double x : listImag) {
189                 this.imaginaryPart[i++] = x;
190             }
191         }
192     }
193
194     /**
195      * Constructor
196      *
197      * @param varName the variable name
198      * @param rows the number of rows
199      * @param cols the number of cols
200      * @param nbItem the number of non null items
201      * @param nbItemRow contains the number of true in each rows
202      * @param colPos the column position of each non null item
203      * @param real the non null real data
204      * @param imag the non null imaginary data
205      */
206     public ScilabSparse(String varName, int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] real, double[] imag) {
207         this(rows, cols, nbItem, nbItemRow, colPos, real, imag);
208         this.varName = varName;
209     }
210
211     /**
212      * Return the type of Scilab
213      * @return the type of Scilab
214      * @since 5.4.0
215      */
216     @Override
217     public ScilabTypeEnum getType() {
218         return type;
219     }
220
221     /**
222      * Check the emptiness of the associated data.
223      * @return true, if the associated data array is empty.
224      */
225     @Override
226     public boolean isEmpty() {
227         return rows == 0 && cols == 0;
228     }
229
230     /**
231      * Check if the current data doesn't have an imaginary part.
232      *
233      * @return true, if the data are real only.
234      */
235     public boolean isReal() {
236         return (imaginaryPart == null);
237     }
238
239     /**
240      * Get the real part of the data.
241      *
242      * @return the real part.
243      */
244     public double[] getRealPart() {
245         return realPart;
246     }
247
248     /**
249      * Set the real part of the data.
250      *
251      * @param realPart the real part.
252      */
253     public void setRealPart(double[] realPart) {
254         this.realPart = realPart;
255     }
256
257     /**
258      * Get the imaginary part of the data.
259      *
260      * @return the imaginary part.
261      */
262     public double[] getImaginaryPart() {
263         return imaginaryPart;
264     }
265
266     /**
267      * Set the imaginary part of the data.
268      *
269      * @param imaginaryPart the imaginary part.
270      */
271     public void setImaginaryPart(double[] imaginaryPart) {
272         this.imaginaryPart = imaginaryPart;
273     }
274
275     /**
276      * Get the number of non null items in the matrix.
277      *
278      * @return the number of non null items.
279      */
280     public int getNbNonNullItems() {
281         return nbItem;
282     }
283
284     /**
285      * Set the number of non null items in the matrix.
286      *
287      * @param the number of non null items.
288      */
289     public void setNbNonNullItems(int nbItem) {
290         this.nbItem = nbItem;
291     }
292
293     /**
294      * Get the number of non null items by row.
295      *
296      * @return an integer array.
297      */
298     public int[] getNbItemRow() {
299         return nbItemRow;
300     }
301
302     /**
303      * Set the number of non null items by row.
304      *
305      * @param an integer array.
306      */
307     public void setNbItemRow(int[] nbItemRow) {
308         this.nbItemRow = nbItemRow;
309     }
310
311     /**
312      * Get the column positions of the non null items.
313      *
314      * @return an integer array.
315      */
316     public int[] getColPos() {
317         return colPos;
318     }
319
320     /**
321      * Set the column positions of the non null items.
322      *
323      * @param an integer array.
324      */
325     public void setColPos(int[] colPos) {
326         this.colPos = colPos;
327     }
328
329     /**
330      * {@inheritDoc}
331      */
332     public String getVarName() {
333         return varName;
334     }
335
336     /**
337      * {@inheritDoc}
338      */
339     public boolean isSwaped() {
340         return false;
341     }
342
343     /**
344      * Get the real part of the full sparse matrix
345      *
346      * @return the full real matrix
347      */
348     public double[][] getFullRealPart() {
349         int prev = 0;
350         int j = 0;
351         double[][] d = new double[rows][cols];
352         for (int i = 0; i < rows; i++) {
353             for (; j < prev + nbItemRow[i]; j++) {
354                 d[i][colPos[j]] = realPart[j];
355             }
356             prev += nbItemRow[i];
357         }
358
359         return d;
360     }
361
362     /**
363      * Get the imaginary part of the full sparse matrix
364      *
365      * @return the full imaginary matrix
366      */
367     public double[][] getFullImaginaryPart() {
368         int prev = 0;
369         int j = 0;
370         double[][] d = new double[rows][cols];
371         for (int i = 0; i < rows; i++) {
372             for (; j < prev + nbItemRow[i]; j++) {
373                 d[i][colPos[j]] = imaginaryPart[j];
374             }
375             prev += nbItemRow[i];
376         }
377
378         return d;
379     }
380
381     /**
382      * Get the full sparse matrix representation as an array 2 x rows x cols
383      * If d = getFullMatrix(), then d[0] contains realpart and d[1] the imaginary one.
384      *
385      * @return the full matrix components
386      */
387     public double[][][] getFullMatrix() {
388         int prev = 0;
389         int j = 0;
390         double[][][] d = new double[2][rows][cols];
391         for (int i = 0; i < rows; i++) {
392             for (; j < prev + nbItemRow[i]; j++) {
393                 d[0][i][colPos[j]] = realPart[j];
394                 d[1][i][colPos[j]] = imaginaryPart[j];
395             }
396             prev += nbItemRow[i];
397         }
398
399         return d;
400     }
401
402     /**
403      * Get complex matrix as a serialized form
404      *
405      * @return the serialized matrix with complex values
406      */
407     // TODO Sly : faire qque chose ici...
408     public double[] getSerializedSparseMatrix() {
409         return new double[0];
410     }
411
412
413     /**
414      * @return the height of the data matrix
415      * @see org.scilab.modules.types.ScilabType#getHeight()
416      */
417     @Override
418     public int getHeight() {
419         return rows;
420     }
421
422     /**
423      * @return the width of the data matrix
424      * @see org.scilab.modules.types.ScilabType#getWidth()
425      */
426     @Override
427     public int getWidth() {
428         return cols;
429     }
430
431     /**
432      * @see org.scilab.modules.types.ScilabType#equals(Object)
433      */
434     @Override
435     public boolean equals(Object obj) {
436         if (obj instanceof ScilabSparse) {
437             ScilabSparse sciSparse = (ScilabSparse) obj;
438             if (this.getNbNonNullItems() == sciSparse.getNbNonNullItems() &&
439                 Arrays.equals(this.getNbItemRow(), sciSparse.getNbItemRow()) &&
440                 Arrays.equals(this.getColPos(), sciSparse.getColPos())) {
441                 if (this.isReal() && sciSparse.isReal()) {
442                     return Arrays.equals(this.getRealPart(), sciSparse.getRealPart());
443                 } else {
444                     /* Complex */
445                     return Arrays.equals(this.getRealPart(), sciSparse.getRealPart()) && Arrays.equals(this.getImaginaryPart(), sciSparse.getImaginaryPart());
446                 }
447             } else {
448                 return false;
449             }
450         } else {
451             return false;
452         }
453     }
454
455     /**
456      * Display the representation in the Scilab language of the type<br />
457      * Note that the representation can be copied/pasted straight into Scilab
458      *
459      * @return a Scilab-like String representation of the data.
460      * @see java.lang.Object#toString()
461      */
462     @Override
463     public String toString() {
464         StringBuilder result = new StringBuilder();
465
466         if (isEmpty()) {
467             result.append("[]");
468             return result.toString();
469         }
470
471         result.append("sparse([");
472         int j = 0;
473         int prev = 0;
474         for (int i = 0; i < rows; i++) {
475             for (; j < prev + nbItemRow[i]; j++) {
476                 result.append(Integer.toString(i + 1));
477                 result.append(", ");
478                 result.append(Integer.toString(colPos[j] + 1));
479                 if (j < nbItem - 1) {
480                     result.append(" ; ");
481                 }
482             }
483             prev += nbItemRow[i];
484         }
485
486         result.append("], [");
487         for (int i = 0; i < nbItem; i++) {
488             if (isReal()) {
489                 result.append(Double.toString(realPart[i]));
490             } else {
491                 result.append(Double.toString(realPart[i]));
492                 if (imaginaryPart[i] != 0) {
493                     result.append("+");
494                     result.append(Double.toString(imaginaryPart[i]));
495                     result.append("*%i");
496                 }
497             }
498             if (i < nbItem - 1) {
499                 result.append(" ; ");
500             } else {
501                 result.append("]");
502             }
503         }
504
505         result.append(", [");
506         result.append(Integer.toString(rows));
507         result.append(", ");
508         result.append(Integer.toString(cols));
509
510         result.append("])");
511
512         return result.toString();
513     }
514 }