960129bad2ac6260634104d2869aa7cb42049a03
[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  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13  *
14  */
15
16 package org.scilab.modules.types;
17
18 import java.io.IOException;
19 import java.io.ObjectInput;
20 import java.io.ObjectOutput;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.List;
24
25 /**
26  * This class provides a representation on the Scilab Sparse datatype<br>
27  * <br>
28  * This class is {@link java.io.Serializable} and any modification could impact
29  * load and store of data (Xcos files, Javasci saved data, etc...).<br>
30  * <br>
31  * //TODO Sly : ajouter de la doc
32  *
33  * @see org.scilab.modules.javasci.Scilab
34  */
35 public class ScilabSparse implements ScilabType {
36
37     private static final long serialVersionUID = 879625048944109684L;
38     private static final ScilabTypeEnum type = ScilabTypeEnum.sci_sparse;
39
40     private static final int VERSION = 0;
41
42     protected int rows;
43     protected int cols;
44     protected int nbItem;
45     protected int[] nbItemRow;
46     protected int[] colPos;
47     protected double[] realPart;
48     protected double[] imaginaryPart;
49     protected String varName;
50     protected boolean byref;
51
52     /**
53      * Default constructor
54      */
55     public ScilabSparse() {
56     }
57
58     /**
59      * Constructor with a unique value.
60      *
61      * @param data
62      *            the unique value
63      */
64     public ScilabSparse(double data) {
65         if (data != 0) {
66             nbItem = 1;
67             rows = cols = 1;
68             nbItemRow = new int[] { 1 };
69             colPos = new int[] { 0 };
70             realPart = new double[] { data };
71         }
72     }
73
74     /**
75      * Constructor with a unique complex value.
76      *
77      * @param realData
78      *            the real part
79      * @param imagData
80      *            the complex part
81      */
82     public ScilabSparse(double realData, double imagData) {
83         if (realData != 0 || imagData != 0) {
84             nbItem = 1;
85             rows = cols = 1;
86             nbItemRow = new int[] { 1 };
87             colPos = new int[] { 0 };
88             realPart = new double[] { realData };
89             imaginaryPart = new double[] { imagData };
90         }
91     }
92
93     /**
94      * Constructor
95      *
96      * @param rows
97      *            the number of rows
98      * @param cols
99      *            the number of cols
100      * @param nbItem
101      *            the number of non null items
102      * @param nbItemRow
103      *            contains the number of true in each rows
104      * @param colPos
105      *            the column position of each non null item
106      * @param data
107      *            the non null data
108      * @param check
109      *            if true the parameters validity is checked
110      */
111     public ScilabSparse(int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] data, boolean check) throws ScilabSparseException {
112         this(rows, cols, nbItem, nbItemRow, colPos, data);
113         if (check) {
114             checkValidity(rows, cols, nbItem, nbItemRow, colPos);
115
116             if (realPart.length != nbItem) {
117                 throw new ScilabSparseException("Invalid length for the array realPart: its length must be equal to the number of non-null items.");
118             }
119         }
120     }
121
122     /**
123      * Constructor
124      *
125      * @param rows
126      *            the number of rows
127      * @param cols
128      *            the number of cols
129      * @param nbItem
130      *            the number of non null items
131      * @param nbItemRow
132      *            contains the number of true in each rows
133      * @param colPos
134      *            the column position of each non null item
135      * @param real
136      *            the non null real data
137      */
138     public ScilabSparse(int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] real) {
139         this.rows = rows;
140         this.cols = cols;
141         this.nbItem = nbItem;
142         this.nbItemRow = nbItemRow;
143         this.colPos = colPos;
144         this.realPart = real;
145     }
146
147     /**
148      * Constructor
149      *
150      * @param rows
151      *            the number of rows
152      * @param cols
153      *            the number of cols
154      * @param nbItem
155      *            the number of non null items
156      * @param nbItemRow
157      *            contains the number of true in each rows
158      * @param colPos
159      *            the column position of each non null item
160      * @param real
161      *            the non null real data
162      * @param imag
163      *            the non null imaginary data
164      * @param check
165      *            if true the parameters validity is checked
166      */
167     public ScilabSparse(int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] real, double[] imag, boolean check)
168     throws ScilabSparseException {
169         this(rows, cols, nbItem, nbItemRow, colPos, real, imag);
170         if (check) {
171             checkValidity(rows, cols, nbItem, nbItemRow, colPos);
172
173             if (realPart.length != nbItem) {
174                 throw new ScilabSparseException("Invalid length for the array realPart: its length must be equal to the number of non-null items.");
175             }
176
177             if (imaginaryPart.length != nbItem) {
178                 throw new ScilabSparseException("Invalid length for the array imaginaryPart: its length must be equal to the number of non-null items.");
179             }
180         }
181     }
182
183     /**
184      * Constructor
185      *
186      * @param rows
187      *            the number of rows
188      * @param cols
189      *            the number of cols
190      * @param nbItem
191      *            the number of non null items
192      * @param nbItemRow
193      *            contains the number of true in each rows
194      * @param colPos
195      *            the column position of each non null item
196      * @param real
197      *            the non null real data
198      * @param imag
199      *            the non null imaginary data
200      */
201     public ScilabSparse(int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] real, double[] imag) {
202         this(rows, cols, nbItem, nbItemRow, colPos, real);
203         this.imaginaryPart = imag;
204     }
205
206     /**
207      * Constructor
208      *
209      * @param rows
210      *            the number of rows
211      * @param cols
212      *            the number of cols
213      * @param nbItem
214      *            the number of non null items
215      * @param nbItemRow
216      *            contains the number of true in each rows
217      * @param colPos
218      *            the column position of each non null item
219      */
220     static final void checkValidity(int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos) throws ScilabSparseException {
221         if (nbItem > rows * cols || nbItem < 0) {
222             throw new ScilabSparseException("Invalid number of items: between 0 and " + rows * cols + " expected.");
223         }
224
225         if (nbItemRow.length > rows) {
226             throw new ScilabSparseException("Invalid length for the array nbItemRow: a length between 0 and " + rows + " expected.");
227         }
228
229         int s = 0;
230         for (int i = 0; i < nbItemRow.length; i++) {
231             if (nbItemRow[i] > cols) {
232                 throw new ScilabSparseException("Invalid number of non-null items in nbItemRow at position " + i + ".");
233             }
234             s += nbItemRow[i];
235         }
236
237         if (s != nbItem) {
238             throw new ScilabSparseException("Invalid array nbItemRow: the total sum is not equal to the number of non-null items.");
239         }
240
241         if (colPos.length != nbItem) {
242             throw new ScilabSparseException("Invalid length for the array colPos: its length must be equal to the number of non-null items.");
243         }
244
245         for (int i = 0; i < nbItem; i++) {
246             if (colPos[i] >= cols || colPos[i] < 0) {
247                 throw new ScilabSparseException("Invalid column position at position " + i + ".");
248             }
249         }
250     }
251
252     /**
253      * Constructor with a matrix of real data.
254      *
255      * @param data
256      *            the data
257      */
258     public ScilabSparse(double[][] data) {
259         if (data.length != 0 && data[0].length != 0) {
260             rows = data.length;
261             cols = data[0].length;
262             nbItemRow = new int[rows];
263             List<Integer> listCol = new ArrayList<Integer>();
264             List<Double> listVal = new ArrayList<Double>();
265
266             for (int i = 0; i < rows; i++) {
267                 for (int j = 0; j < cols; j++) {
268                     if (data[i][j] != 0) {
269                         ++nbItem;
270                         ++nbItemRow[i];
271                         listCol.add(j);
272                         listVal.add(data[i][j]);
273                     }
274                 }
275             }
276
277             colPos = new int[listCol.size()];
278             realPart = new double[colPos.length];
279             int i = 0;
280             for (Integer c : listCol) {
281                 colPos[i++] = c;
282             }
283             i = 0;
284             for (Double x : listVal) {
285                 realPart[i++] = x;
286             }
287         }
288     }
289
290     /**
291      * Constructor with a matrix of complex numbers
292      *
293      * @param realData
294      *            the real part of the data
295      * @param imagData
296      *            the imaginary part of the data
297      */
298     public ScilabSparse(double[][] realData, double[][] imagData) {
299         if (realData.length != 0 && realData[0].length != 0) {
300             rows = realData.length;
301             cols = realData[0].length;
302             nbItemRow = new int[rows];
303             List<Integer> listCol = new ArrayList<Integer>();
304             List<Double> listReal = new ArrayList<Double>();
305             List<Double> listImag = new ArrayList<Double>();
306
307             for (int i = 0; i < rows; i++) {
308                 for (int j = 0; j < cols; j++) {
309                     if (realData[i][j] != 0 || imagData[i][j] != 0) {
310                         ++nbItem;
311                         ++nbItemRow[i];
312                         listCol.add(j);
313                         listReal.add(realData[i][j]);
314                         listImag.add(imagData[i][j]);
315                     }
316                 }
317             }
318
319             colPos = new int[listCol.size()];
320             this.realPart = new double[colPos.length];
321             this.imaginaryPart = new double[colPos.length];
322             int i = 0;
323             for (Integer c : listCol) {
324                 colPos[i++] = c;
325             }
326             i = 0;
327             for (Double x : listReal) {
328                 this.realPart[i++] = x;
329             }
330             i = 0;
331             for (Double x : listImag) {
332                 this.imaginaryPart[i++] = x;
333             }
334         }
335     }
336
337     /**
338      * Constructor
339      *
340      * @param varName
341      *            the variable name
342      * @param rows
343      *            the number of rows
344      * @param cols
345      *            the number of cols
346      * @param nbItem
347      *            the number of non null items
348      * @param nbItemRow
349      *            contains the number of true in each rows
350      * @param colPos
351      *            the column position of each non null item
352      * @param real
353      *            the non null real data
354      * @param imag
355      *            the non null imaginary data
356      */
357     public ScilabSparse(String varName, int rows, int cols, int nbItem, int[] nbItemRow, int[] colPos, double[] real, double[] imag) {
358         this(rows, cols, nbItem, nbItemRow, colPos, real, imag);
359         this.varName = varName;
360     }
361
362     /**
363      * {@inheritDoc}
364      */
365     public boolean isReference() {
366         return false;
367     }
368
369     /**
370      * Return the type of Scilab
371      *
372      * @return the type of Scilab
373      * @since 5.4.0
374      */
375     @Override
376     public ScilabTypeEnum getType() {
377         return type;
378     }
379
380     /**
381      * Check the emptiness of the associated data.
382      *
383      * @return true, if the associated data array is empty.
384      */
385     @Override
386     public boolean isEmpty() {
387         return rows == 0 && cols == 0;
388     }
389
390     /**
391      * Check if the current data doesn't have an imaginary part.
392      *
393      * @return true, if the data are real only.
394      */
395     public boolean isReal() {
396         return imaginaryPart == null;
397     }
398
399     /**
400      * Get the element in column position
401      * @param i the position
402      * @return the column position
403      */
404     public int getColPosElement(final int i) {
405         return colPos[i];
406     }
407
408     /**
409      * Set the element in column position
410      * @param i the position
411      * @param x the column position
412      */
413     public void setColPosElement(final int i, final int x) {
414         colPos[i] = x;
415     }
416
417     /**
418      * Get the number of non-null item in row i
419      * @param i the row
420      * @return the number of non-null items
421      */
422     public int getNbItemElement(final int i) {
423         return nbItemRow[i];
424     }
425
426     /**
427      * Set the number of non-null item in row i
428      * @param i the row
429      * @param x the number of non-null items
430      */
431     public void setNbItemElement(final int i, final int x) {
432         nbItemRow[i] = x;
433     }
434
435     /**
436      * Get the real element at position i
437      * @param i the position
438      * @return a real
439      */
440     public double getRealElement(final int i) {
441         return realPart[i];
442     }
443
444     /**
445      * Get the real element at position (i, j) in the sparse matrix
446      * @param i the row index
447      * @param j the column index
448      * @return a real
449      */
450     public double getRealElement(final int i, final int j) {
451         if (getNbItemElement(i) == 0) {
452             return 0;
453         }
454
455         int prev = 0;
456         for (int k = 0; k < i; k++) {
457             prev += getNbItemElement(k);
458         }
459
460         for (int k = prev; k < prev + getNbItemElement(i); k++) {
461             if (getColPosElement(k) == j) {
462                 return getRealElement(k);
463             }
464         }
465
466         return 0;
467     }
468
469     /**
470      * Get the imaginary element at position i
471      * @param i the position
472      * @return a real
473      */
474     public double getImaginaryElement(final int i) {
475         return imaginaryPart[i];
476     }
477
478     /**
479      * Get the imanginary element at position (i, j) in the sparse matrix
480      * @param i the row index
481      * @param j the column index
482      * @return a real
483      */
484     public double getImaginaryElement(final int i, final int j) {
485         if (getNbItemElement(i) == 0) {
486             return 0;
487         }
488
489         int prev = 0;
490         for (int k = 0; k < i; k++) {
491             prev += getNbItemElement(k);
492         }
493
494         for (int k = prev; k < prev + getNbItemElement(i); k++) {
495             if (getColPosElement(k) == j) {
496                 return getImaginaryElement(k);
497             }
498         }
499
500         return 0;
501     }
502
503     /**
504      * Get the real and imaginary elements at position i
505      * @param i the position
506      * @return a 2-array containing real and imaginary part
507      */
508     public double[] getElement(final int i) {
509         if (isReal()) {
510             return new double[] {realPart[i], 0};
511         } else {
512             return new double[] {realPart[i], imaginaryPart[i]};
513         }
514     }
515
516     /**
517      * Get the real and imanginary element at position (i, j) in the sparse matrix
518      * @param i the row index
519      * @param j the column index
520      * @return a 2-array containing real and imaginary parts
521      */
522     public double[] getElement(final int i, final int j) {
523         if (isReal()) {
524             return new double[] {getRealElement(i, j), 0};
525         } else {
526             if (getNbItemElement(i) == 0) {
527                 return new double[] {0, 0};
528             }
529
530             int prev = 0;
531             for (int k = 0; k < i; k++) {
532                 prev += getNbItemElement(k);
533             }
534
535             for (int k = prev; k < prev + getNbItemElement(i); k++) {
536                 if (getColPosElement(k) == j) {
537                     return new double[] {getRealElement(k), getImaginaryElement(k)};
538                 }
539             }
540
541             return new double[] {0, 0};
542         }
543     }
544
545     /**
546      * Set the real element at position i
547      * @param i the position
548      * @param x the value to set
549      */
550     public void setRealElement(final int i, final double x) {
551         realPart[i] = x;
552     }
553
554     /**
555      * Set the real element at position (i, j) in sparse matrix
556      * Take care only an already non-null element can be set
557      * @param i the row index
558      * @param j the column index
559      * @param x the value to set
560      */
561     public void setRealElement(final int i, final int j, final double x) {
562         if (getNbItemElement(i) == 0) {
563             return;
564         }
565
566         int prev = 0;
567         for (int k = 0; k < i; k++) {
568             prev += getNbItemElement(k);
569         }
570
571         for (int k = prev; k < prev + getNbItemElement(i); k++) {
572             if (getColPosElement(k) == j) {
573                 setRealElement(k, x);
574                 break;
575             }
576         }
577     }
578
579     /**
580      * Set the imaginary element at position i
581      * @param i the position
582      * @param x the value to set
583      */
584     public void setImaginaryElement(final int i, final double x) {
585         imaginaryPart[i] = x;
586     }
587
588     /**
589      * Set the imaginary element at position (i, j) in sparse matrix
590      * Take care only an already non-null element can be set
591      * @param i the row index
592      * @param j the column index
593      * @param x the value to set
594      */
595     public void setImaginaryElement(final int i, final int j, final double x) {
596         if (getNbItemElement(i) == 0) {
597             return;
598         }
599
600         int prev = 0;
601         for (int k = 0; k < i; k++) {
602             prev += getNbItemElement(k);
603         }
604
605         for (int k = prev; k < prev + getNbItemElement(i); k++) {
606             if (getColPosElement(k) == j) {
607                 setImaginaryElement(k, x);
608                 break;
609             }
610         }
611     }
612
613     /**
614      * Set the real and imaginary elements at position i
615      * @param i the position
616      * @param x the real part to set
617      * @param y the imaginary part to set
618      */
619     public void setElement(final int i, final double x, final double y) {
620         setRealElement(i, x);
621         setImaginaryElement(i, y);
622     }
623
624     /**
625      * Get the real part of the data.
626      *
627      * @return the real part.
628      */
629     public double[] getRealPart() {
630         return realPart;
631     }
632
633     /**
634      * Set the real part of the data.
635      *
636      * @param realPart
637      *            the real part.
638      */
639     public void setRealPart(double[] realPart) {
640         this.realPart = realPart;
641     }
642
643     /**
644      * Get the imaginary part of the data.
645      *
646      * @return the imaginary part.
647      */
648     public double[] getImaginaryPart() {
649         return imaginaryPart;
650     }
651
652     /**
653      * Set the imaginary part of the data.
654      *
655      * @param imaginaryPart
656      *            the imaginary part.
657      */
658     public void setImaginaryPart(double[] imaginaryPart) {
659         this.imaginaryPart = imaginaryPart;
660     }
661
662     /**
663      * Get the number of non null items in the matrix.
664      *
665      * @return the number of non null items.
666      */
667     public int getNbNonNullItems() {
668         return nbItem;
669     }
670
671     /**
672      * Set the number of non null items in the matrix.
673      *
674      * @param nbItem
675      *            the number of non null items.
676      */
677     public void setNbNonNullItems(int nbItem) {
678         this.nbItem = nbItem;
679     }
680
681     /**
682      * Get the number of non null items by row.
683      *
684      * @return an integer array.
685      */
686     public int[] getNbItemRow() {
687         return nbItemRow;
688     }
689
690     /**
691      * Set the number of non null items by row.
692      *
693      * @param nbItemRow
694      *            an integer array.
695      */
696     public void setNbItemRow(int[] nbItemRow) {
697         this.nbItemRow = nbItemRow;
698     }
699
700     /**
701      * Get the column positions of the non null items.
702      *
703      * @return an integer array.
704      */
705     public int[] getScilabColPos() {
706         int[] cp = new int[colPos.length];
707         for (int i = 0; i < colPos.length; i++) {
708             cp[i] = colPos[i] + 1;
709         }
710         return cp;
711     }
712
713     /**
714      * Get the column positions of the non null items.
715      *
716      * @return an integer array.
717      */
718     public int[] getColPos() {
719         return colPos;
720     }
721
722     /**
723      * Set the column positions of the non null items.
724      *
725      * @param colPos
726      *            an integer array.
727      */
728     public void setColPos(int[] colPos) {
729         this.colPos = colPos;
730     }
731
732     /**
733      * {@inheritDoc}
734      */
735     public String getVarName() {
736         return varName;
737     }
738
739     /**
740      * {@inheritDoc}
741      */
742     public boolean isSwaped() {
743         return false;
744     }
745
746     /**
747      * Get the real part of the full sparse matrix
748      *
749      * @return the full real matrix
750      */
751     public double[][] getFullRealPart() {
752         int prev = 0;
753         int j = 0;
754         double[][] d = new double[rows][cols];
755         for (int i = 0; i < nbItemRow.length; i++) {
756             for (; j < prev + nbItemRow[i]; j++) {
757                 d[i][colPos[j]] = realPart[j];
758             }
759             prev += nbItemRow[i];
760         }
761
762         return d;
763     }
764
765     /**
766      * Get the imaginary part of the full sparse matrix
767      *
768      * @return the full imaginary matrix
769      */
770     public double[][] getFullImaginaryPart() {
771         int prev = 0;
772         int j = 0;
773         double[][] d = new double[rows][cols];
774         for (int i = 0; i < nbItemRow.length; i++) {
775             for (; j < prev + nbItemRow[i]; j++) {
776                 d[i][colPos[j]] = imaginaryPart[j];
777             }
778             prev += nbItemRow[i];
779         }
780
781         return d;
782     }
783
784     /**
785      * Get the full sparse matrix representation as an array 2 x rows x cols If
786      * d = getFullMatrix(), then d[0] contains realpart and d[1] the imaginary
787      * one.
788      *
789      * @return the full matrix components
790      */
791     public double[][][] getFullMatrix() {
792         int prev = 0;
793         int j = 0;
794         double[][][] d = new double[2][rows][cols];
795         for (int i = 0; i < nbItemRow.length; i++) {
796             for (; j < prev + nbItemRow[i]; j++) {
797                 d[0][i][colPos[j]] = realPart[j];
798                 d[1][i][colPos[j]] = imaginaryPart[j];
799             }
800             prev += nbItemRow[i];
801         }
802
803         return d;
804     }
805
806     /**
807      * Get complex matrix as a serialized form
808      *
809      * @return the serialized matrix with complex values
810      */
811     // TODO Sly : faire qque chose ici...
812     public double[] getSerializedSparseMatrix() {
813         return new double[0];
814     }
815
816     /**
817      * @return the height of the data matrix
818      * @see org.scilab.modules.types.ScilabType#getHeight()
819      */
820     @Override
821     public int getHeight() {
822         return rows;
823     }
824
825     /**
826      * @return the width of the data matrix
827      * @see org.scilab.modules.types.ScilabType#getWidth()
828      */
829     @Override
830     public int getWidth() {
831         return cols;
832     }
833
834     @Override
835     public int hashCode() {
836         final int prime = 31;
837         int result = 1;
838         result = prime * result + Arrays.hashCode(colPos);
839         result = prime * result + cols;
840         result = prime * result + Arrays.hashCode(imaginaryPart);
841         result = prime * result + nbItem;
842         result = prime * result + Arrays.hashCode(nbItemRow);
843         result = prime * result + Arrays.hashCode(realPart);
844         result = prime * result + rows;
845         return result;
846     }
847
848     /**
849      * @see org.scilab.modules.types.ScilabType#equals(Object)
850      */
851     @Override
852     public boolean equals(Object obj) {
853         if (obj instanceof ScilabSparse) {
854             ScilabSparse sciSparse = (ScilabSparse) obj;
855             if (isEmpty() && sciSparse.isEmpty()) {
856                 return true;
857             }
858
859             if (this.getWidth() != sciSparse.getWidth() || this.getHeight() != sciSparse.getHeight()) {
860                 return false;
861             }
862
863             if (this.getNbNonNullItems() == sciSparse.getNbNonNullItems() && compareNbItemRow(this.getNbItemRow(), sciSparse.getNbItemRow())
864                     && Arrays.equals(this.getColPos(), sciSparse.getColPos())) {
865                 if (this.isReal() && sciSparse.isReal()) {
866                     return Arrays.equals(this.getRealPart(), sciSparse.getRealPart());
867                 } else {
868                     /* Complex */
869                     return Arrays.equals(this.getRealPart(), sciSparse.getRealPart()) && Arrays.equals(this.getImaginaryPart(), sciSparse.getImaginaryPart());
870                 }
871             } else {
872                 return false;
873             }
874         } else {
875             return false;
876         }
877     }
878
879     /**
880      * Compare two arrays containing the number of items by row. For example {1,
881      * 2, 3, 4} is equal to {1, 2, 3, 4, 0, 0, 0, 0}/
882      *
883      * @param a
884      *            an array
885      * @param b
886      *            an other array
887      * @return true if the arrays are equal
888      */
889     static final boolean compareNbItemRow(final int[] a, final int[] b) {
890         if (Arrays.equals(a, b)) {
891             return true;
892         }
893
894         if (a.length == b.length) {
895             return false;
896         }
897
898         int[] c, d;
899         if (a.length < b.length) {
900             c = a;
901             d = b;
902         } else {
903             c = b;
904             d = a;
905         }
906
907         int i = 0;
908         for (; i < c.length; i++) {
909             if (c[i] != d[i]) {
910                 return false;
911             }
912         }
913
914         for (; i < d.length; i++) {
915             if (d[i] != 0) {
916                 return false;
917             }
918         }
919
920         return true;
921     }
922
923     /**
924      * {@inheritDoc}
925      */
926     public Object getSerializedObject() {
927         if (isReal()) {
928             return new Object[] { new int[] { getHeight(), getWidth() }, getNbItemRow(), getScilabColPos(), getRealPart() };
929         } else {
930             return new Object[] { new int[] { getHeight(), getWidth() }, getNbItemRow(), getScilabColPos(), getRealPart(), getImaginaryPart() };
931         }
932     }
933
934     @Override
935     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
936         int version = in.readInt();
937         switch (version) {
938             case 0:
939                 rows = in.readInt();
940                 cols = in.readInt();
941                 nbItem = in.readInt();
942                 nbItemRow = (int[]) in.readObject();
943                 colPos = (int[]) in.readObject();
944                 realPart = (double[]) in.readObject();
945                 imaginaryPart = (double[]) in.readObject();
946                 varName = (String) in.readObject();
947                 break;
948             default:
949                 throw new ClassNotFoundException("A class ScilabSparse with a version " + version + " does not exists");
950         }
951     }
952
953     @Override
954     public void writeExternal(ObjectOutput out) throws IOException {
955         out.writeInt(VERSION);
956         out.writeInt(rows);
957         out.writeInt(cols);
958         out.writeInt(nbItem);
959         out.writeObject(nbItemRow);
960         out.writeObject(colPos);
961         out.writeObject(realPart);
962         out.writeObject(imaginaryPart);
963         out.writeObject(varName);
964     }
965
966     /**
967      * Display the representation in the Scilab language of the type<BR>
968      * Note that the representation can be copied/pasted straight into Scilab
969      *
970      * @return a Scilab-like String representation of the data.
971      * @see java.lang.Object#toString()
972      */
973     @Override
974     public String toString() {
975         StringBuilder result = new StringBuilder();
976
977         if (isEmpty()) {
978             return "[]";
979         }
980
981         result.append("sparse([");
982         int j = 0;
983         int prev = 0;
984         int[] nbItemRow = getNbItemRow();
985         int[] colPos = getColPos();
986         for (int i = 0; i < nbItemRow.length; i++) {
987             for (; j < prev + nbItemRow[i]; j++) {
988                 result.append(Integer.toString(i + 1));
989                 result.append(", ");
990                 result.append(Integer.toString(colPos[j] + 1));
991                 if (j < nbItem - 1) {
992                     result.append(" ; ");
993                 }
994             }
995             prev += nbItemRow[i];
996         }
997
998         result.append("], [");
999         boolean real = isReal();
1000         for (int i = 0; i < nbItem; i++) {
1001             result.append(Double.toString(getRealElement(i)));
1002             if (!real) {
1003                 final double y = getImaginaryElement(i);
1004                 if (y != 0) {
1005                     if (y > 0) {
1006                         result.append("+");
1007                     }
1008                     result.append(Double.toString(y));
1009                     result.append("*%i");
1010                 }
1011             }
1012             if (i < nbItem - 1) {
1013                 result.append(" ; ");
1014             } else {
1015                 result.append("]");
1016             }
1017         }
1018
1019         result.append(", [");
1020         result.append(Integer.toString(rows));
1021         result.append(", ");
1022         result.append(Integer.toString(cols));
1023
1024         result.append("])");
1025
1026         return result.toString();
1027     }
1028 }