1b50dc9e88608b63bc16778d7778046cf15599ad
[scilab.git] / scilab / modules / types / src / java / org / scilab / modules / types / ScilabDouble.java
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2009-2009 - DIGITEO - Bruno JOFRET
4  *  Copyright (C) 2010-2010 - DIGITEO - Clement DAVID
5  *  Copyright (C) 2011-2011 - DIGITEO - Calixte DENIZET
6  *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15  *
16  */
17
18 package org.scilab.modules.types;
19
20 import java.io.IOException;
21 import java.io.ObjectInput;
22 import java.io.ObjectOutput;
23 import java.util.Arrays;
24
25 /**
26  * This class provides a representation on the Scilab Double datatype<br>
27  * Note that double is the default datatype in Scilab.<br>
28  * <br>
29  * This class is {@link java.io.Serializable} and any modification could impact
30  * load and store of data (Xcos files, Javasci saved data, etc...).<br>
31  * <br>
32  * Example (real):<BR>
33  * <code>
34  * double [][]a={{21.2, 22.0, 42.0, 39.0},{23.2, 24.0, 44.0, 40.0}};<BR>
35  * ScilabDouble aMatrix = new ScilabDouble(a);<BR>
36  * </code> <br>
37  * Example (complex):<BR>
38  * <code>
39  * double [][]a={{21.2, 22.0, 42.0, 39.0},{23.2, 24.0, 44.0, 40.0}};<BR>
40  * double [][]aImg={{210.2, 220.0, 420.0, 390.0},{230.2, 240.0, 440.0, 400.0}};<BR>
41  * ScilabDouble aMatrix = new ScilabDouble(a, aImg);
42  * </code>
43  *
44  * @see org.scilab.modules.javasci.Scilab
45  */
46 public class ScilabDouble implements ScilabType {
47
48     private static final long serialVersionUID = 879624048944109684L;
49     private static final ScilabTypeEnum type = ScilabTypeEnum.sci_matrix;
50
51     private static final int VERSION = 0;
52
53     protected double[][] realPart;
54     protected double[][] imaginaryPart;
55     protected String varName;
56     protected boolean swaped;
57     transient protected boolean byref;
58
59     /**
60      * Default constructor
61      */
62     public ScilabDouble() {
63         realPart = new double[0][];
64         imaginaryPart = new double[0][];
65     }
66
67     /**
68      * Constructor with a unique value.
69      *
70      * @param data
71      *            the unique value
72      */
73     public ScilabDouble(double data) {
74         realPart = new double[1][1];
75         realPart[0][0] = data;
76         imaginaryPart = new double[0][];
77     }
78
79     /**
80      * Constructor with a unique complex value.
81      *
82      * @param realData
83      *            the real part
84      * @param imagData
85      *            the complex part
86      */
87     public ScilabDouble(double realData, double imagData) {
88         realPart = new double[1][1];
89         realPart[0][0] = realData;
90         imaginaryPart = new double[1][1];
91         imaginaryPart[0][0] = imagData;
92     }
93
94     /**
95      * Constructor with a matrix of real data.
96      *
97      * @param data
98      *            the data
99      */
100     public ScilabDouble(double[][] data) {
101         this(data, new double[0][]);
102     }
103
104     /**
105      * Constructor with a matrix of complex numbers
106      *
107      * @param realData
108      *            the real part of the data
109      * @param imagData
110      *            the imaginary part of the data
111      */
112     public ScilabDouble(double[][] realData, double[][] imagData) {
113         if (realData == null) {
114             realPart = new double[0][];
115             imaginaryPart = new double[0][];
116         } else {
117             realPart = realData;
118             if (imagData == null) {
119                 imaginaryPart = new double[0][];
120             } else {
121                 imaginaryPart = imagData;
122             }
123         }
124     }
125
126     /**
127      * Constructor with a matrix of complex numbers
128      *
129      * @param realData
130      *            the real part of the data
131      * @param imagData
132      *            the imaginary part of the data
133      */
134     public ScilabDouble(String varName, double[][] realData, double[][] imagData, boolean swaped) {
135         this(realData, imagData);
136         this.varName = varName;
137         this.swaped = swaped;
138     }
139
140     /**
141      * Return the type of Scilab
142      *
143      * @return the type of Scilab
144      * @since 5.4.0
145      */
146     @Override
147     public ScilabTypeEnum getType() {
148         return type;
149     }
150
151     /**
152      * Check the emptiness of the associated data.
153      *
154      * @return true, if the associated data array is empty.
155      */
156     @Override
157     public boolean isEmpty() {
158         return realPart == null || realPart.length == 0;
159     }
160
161     /**
162      * {@inheritDoc}
163      */
164     public boolean isReference() {
165         return byref;
166     }
167
168     /**
169      * Check if the current data doesn't have an imaginary part.
170      *
171      * @return true, if the data are real only.
172      */
173     public boolean isReal() {
174         return imaginaryPart == null || imaginaryPart.length == 0;
175     }
176
177     /**
178      * Get the real part of the data.
179      *
180      * @return the real part.
181      */
182     public double[][] getRealPart() {
183         return realPart;
184     }
185
186     /**
187      * Set the real part of the data.
188      *
189      * @param realPart
190      *            the real part.
191      */
192     public void setRealPart(double[][] realPart) {
193         this.realPart = realPart;
194     }
195
196     /**
197      * Get the imaginary part of the data.
198      *
199      * @return the imaginary part.
200      */
201     public double[][] getImaginaryPart() {
202         return imaginaryPart;
203     }
204
205     /**
206      * Set the imaginary part of the data.
207      *
208      * @param imaginaryPart
209      *            the imaginary part.
210      */
211     public void setImaginaryPart(double[][] imaginaryPart) {
212         this.imaginaryPart = imaginaryPart;
213     }
214
215     /**
216      * {@inheritDoc}
217      */
218     public String getVarName() {
219         return varName;
220     }
221
222     /**
223      * {@inheritDoc}
224      */
225     public boolean isSwaped() {
226         return swaped;
227     }
228
229     /**
230      * Get the element at position (i, j) in the real part
231      * @param i the first coordinate
232      * @param j the second coordinate
233      * @return the corresponding double
234      */
235     public double getRealElement(final int i, final int j) {
236         return realPart[i][j];
237     }
238
239     /**
240      * Get the element at position (i, j) in the imaginary part
241      * @param i the first coordinate
242      * @param j the second coordinate
243      * @return the corresponding double
244      */
245     public double getImaginaryElement(final int i, final int j) {
246         return imaginaryPart[i][j];
247     }
248
249     /**
250      * Get the complex at position (i, j) as a 2-length row-vector
251      * @param i the first coordinate
252      * @param j the second coordinate
253      * @return the corresponding complex
254      */
255     public double[] getElement(final int i, final int j) {
256         return new double[] {getRealElement(i, j), getImaginaryElement(i, j)};
257     }
258
259     /**
260      * Set the element at position (i, j) in the real part
261      * @param i the first coordinate
262      * @param j the second coordinate
263      * @param x the new value
264      */
265     public void setRealElement(final int i, final int j, final double x) {
266         realPart[i][j] = x;
267     }
268
269     /**
270      * Set the element at position (i, j) in the imaginary part
271      * @param i the first coordinate
272      * @param j the second coordinate
273      * @param x the new value
274      */
275     public void setImaginaryElement(final int i, final int j, final double x) {
276         imaginaryPart[i][j] = x;
277     }
278
279     /**
280      * Set the element at position (i, j)
281      * @param i the first coordinate
282      * @param j the second coordinate
283      * @param x the new value for real part
284      * @param y the new value for imaginary part
285      */
286     public void setElement(final int i, final int j, final double x, final double y) {
287         realPart[i][j] = x;
288         imaginaryPart[i][j] = y;
289     }
290
291     /**
292      * Get the raw data
293      * @return the real part
294      */
295     public Object getRawRealPart() {
296         return realPart;
297     }
298
299     /**
300      * Get the raw data
301      * @return the imaginary part
302      */
303     public Object getRawImaginaryPart() {
304         return imaginaryPart;
305     }
306
307     /**
308      * Get complex matrix as a serialized form
309      *
310      * @return the serialized matrix with complex values
311      */
312     public double[] getSerializedComplexMatrix() {
313         int size = this.getHeight() * this.getWidth();
314         double[] serializedComplexMatrix = new double[size * 2];
315         for (int i = 0; i < this.getHeight(); i++) {
316             for (int j = 0; j < this.getWidth(); j++) {
317                 serializedComplexMatrix[j * this.getHeight() + i] = getRealElement(i, j);
318                 serializedComplexMatrix[size + j * this.getHeight() + i] = getImaginaryElement(i, j);
319             }
320         }
321
322         return serializedComplexMatrix;
323     }
324
325     /**
326      * {@inheritDoc}
327      */
328     public Object getSerializedObject() {
329         if (isReal()) {
330             return new Object[] { getRealPart() };
331         } else {
332             return new Object[] { getRealPart(), getImaginaryPart() };
333         }
334     }
335
336     /**
337      * @return the height of the data matrix
338      * @see org.scilab.modules.types.ScilabType#getHeight()
339      */
340     @Override
341     public int getHeight() {
342         if (isEmpty()) {
343             return 0;
344         }
345         return realPart.length;
346     }
347
348     /**
349      * @return the width of the data matrix
350      * @see org.scilab.modules.types.ScilabType#getWidth()
351      */
352     @Override
353     public int getWidth() {
354         if (isEmpty()) {
355             return 0;
356         }
357
358         return realPart[0].length;
359     }
360
361     @Override
362     public int hashCode() {
363         final int prime = 31;
364         int result = 1;
365         result = prime * result + Arrays.deepHashCode(imaginaryPart);
366         result = prime * result + Arrays.deepHashCode(realPart);
367         return result;
368     }
369
370     /**
371      * @see org.scilab.modules.types.ScilabType#equals(Object)
372      */
373     @Override
374     public boolean equals(Object obj) {
375         if (obj instanceof ScilabDouble) {
376             ScilabDouble sciDouble = (ScilabDouble) obj;
377             if (isEmpty() && sciDouble.isEmpty()) {
378                 return true;
379             }
380
381             if (this.getWidth() != sciDouble.getWidth() || this.getHeight() != sciDouble.getHeight()) {
382                 return false;
383             }
384
385             if (this.isReal() && sciDouble.isReal()) {
386                 return ScilabTypeUtils.equalsDouble(this.getRawRealPart(), this.isSwaped(), sciDouble.getRawRealPart(), sciDouble.isSwaped());
387             } else if (!this.isReal() && !sciDouble.isReal()) {
388                 /* Complex */
389                 return ScilabTypeUtils.equalsDouble(this.getRawRealPart(), this.isSwaped(), sciDouble.getRawRealPart(), sciDouble.isSwaped())
390                        && ScilabTypeUtils.equalsDouble(this.getRawImaginaryPart(), this.isSwaped(), sciDouble.getRawImaginaryPart(), sciDouble.isSwaped());
391             }
392         }
393
394         return false;
395     }
396
397     @Override
398     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
399         int version = in.readInt();
400         switch (version) {
401             case 0:
402                 realPart = (double[][]) in.readObject();
403                 imaginaryPart = (double[][]) in.readObject();
404                 varName = (String) in.readObject();
405                 swaped = in.readBoolean();
406                 break;
407             default:
408                 throw new ClassNotFoundException("A class ScilabDouble with a version " + version + " does not exists");
409         }
410     }
411
412     @Override
413     public void writeExternal(ObjectOutput out) throws IOException {
414         out.writeInt(VERSION);
415         out.writeObject(getRealPart());
416         out.writeObject(getImaginaryPart());
417         out.writeObject(varName);
418         out.writeBoolean(swaped);
419     }
420
421     /**
422      * Display the representation in the Scilab language of the type<BR>
423      * Note that the representation can be copied/pasted straight into Scilab
424      *
425      * @return a Scilab-like String representation of the data.
426      * @see java.lang.Object#toString()
427      */
428     @Override
429     public String toString() {
430         StringBuilder result = new StringBuilder();
431
432         if (isEmpty()) {
433             return "[]";
434         }
435
436         result.append("[");
437         final boolean real = isReal();
438         for (int i = 0; i < getHeight(); ++i) {
439             for (int j = 0; j < getWidth(); ++j) {
440                 result.append(Double.toString(getRealElement(i, j)));
441                 if (!real) {
442                     final double y = getImaginaryElement(i, j);
443                     if (y != 0) {
444                         if (y > 0) {
445                             result.append(" + ");
446                         }
447                         result.append(Double.toString(y));
448                         result.append(" * %i");
449                     }
450                 }
451                 if (j != getWidth() - 1) {
452                     result.append(", ");
453                 }
454             }
455             if (i != getHeight() - 1) {
456                 result.append(" ; ");
457             }
458         }
459         result.append("]");
460
461         return result.toString();
462     }
463 }