0d0bb36554e61e92d875be7ea4cf57896b4c1ea9
[scilab.git] / scilab / modules / types / src / java / org / scilab / modules / types / ScilabInteger.java
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2009-2009 - DIGITEO - Antoine ELIAS
4  *  Copyright (C) 2011-2011 - DIGITEO - Calixte DENIZET
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 package org.scilab.modules.types;
18
19 import java.io.IOException;
20 import java.io.ObjectInput;
21 import java.io.ObjectOutput;
22 import java.util.Arrays;
23
24 /**
25  * This class provides a representation on the Scilab Integer datatype<br>
26  * <br>
27  * This class is {@link java.io.Serializable} and any modification could impact
28  * load and store of data (Xcos files, Javasci saved data, etc...).<br>
29  * <br>
30  * Example:<BR>
31  * <code>
32  * byte [][]a={{32,42,41}, {12,13,32}};<BR>
33  * ScilabInteger aMatrix = new ScilabInteger(a, true); // true = unsigned
34  * </code>
35  *
36  * @see org.scilab.modules.javasci.Scilab
37  */
38 public class ScilabInteger implements ScilabType {
39
40     private static final long serialVersionUID = 1759633801332932450L;
41     private static final ScilabTypeEnum type = ScilabTypeEnum.sci_ints;
42
43     private static final int VERSION = 0;
44
45     protected long[][] longData;
46     protected short[][] shortData;
47     protected int[][] intData;
48     protected byte[][] byteData;
49     protected ScilabIntegerTypeEnum precision;
50     protected String varName;
51     protected boolean swaped;
52     transient protected boolean byref;
53
54     /**
55      * Default constructor
56      */
57     public ScilabInteger() { }
58
59     /**
60      * Constructor with values
61      *
62      * @param data
63      *            the values
64      * @param bUnsigned
65      *            true, if the values are unsigned; false if they are signed.
66      */
67     public ScilabInteger(byte[][] data, boolean bUnsigned) {
68         this.setData(data, bUnsigned);
69     }
70
71     /**
72      * Constructor with values
73      *
74      * @param data
75      *            the values
76      * @param bUnsigned
77      *            true, if the values are unsigned; false if they are signed.
78      */
79     public ScilabInteger(short[][] data, boolean bUnsigned) {
80         this.setData(data, bUnsigned);
81     }
82
83     /**
84      * Constructor with values
85      *
86      * @param data
87      *            the values
88      * @param bUnsigned
89      *            true, if the values are unsigned; false if they are signed.
90      */
91     public ScilabInteger(int[][] data, boolean bUnsigned) {
92         this.setData(data, bUnsigned);
93     }
94
95     /**
96      * Constructor with values
97      *
98      * @param data
99      *            the values
100      * @param bUnsigned
101      *            true, if the values are unsigned; false if they are signed.
102      */
103     public ScilabInteger(long[][] data, boolean bUnsigned) {
104         this.setData(data, bUnsigned);
105     }
106
107     /**
108      * Constructor with values
109      *
110      * @param data
111      *            the values
112      * @param bUnsigned
113      *            true, if the values are unsigned; false if they are signed.
114      */
115     public ScilabInteger(String varName, byte[][] data, boolean bUnsigned, boolean swaped) {
116         this.setData(data, bUnsigned);
117         this.varName = varName;
118         this.swaped = swaped;
119     }
120
121     /**
122      * Constructor with values
123      *
124      * @param data
125      *            the values
126      * @param bUnsigned
127      *            true, if the values are unsigned; false if they are signed.
128      */
129     public ScilabInteger(String varName, short[][] data, boolean bUnsigned, boolean swaped) {
130         this.setData(data, bUnsigned);
131         this.varName = varName;
132         this.swaped = swaped;
133     }
134
135     /**
136      * Constructor with values
137      *
138      * @param data
139      *            the values
140      * @param bUnsigned
141      *            true, if the values are unsigned; false if they are signed.
142      */
143     public ScilabInteger(String varName, int[][] data, boolean bUnsigned, boolean swaped) {
144         this.setData(data, bUnsigned);
145         this.varName = varName;
146         this.swaped = swaped;
147     }
148
149     /**
150      * Constructor with values
151      *
152      * @param data
153      *            the values
154      * @param bUnsigned
155      *            true, if the values are unsigned; false if they are signed.
156      */
157     public ScilabInteger(String varName, long[][] data, boolean bUnsigned, boolean swaped) {
158         this.setData(data, bUnsigned);
159         this.varName = varName;
160         this.swaped = swaped;
161     }
162
163     /**
164      * Constructor with single signed value
165      *
166      * @param value
167      *            the unique value
168      */
169     public ScilabInteger(byte value) {
170         this.byteData = new byte[1][1];
171         this.byteData[0][0] = value;
172         this.precision = ScilabIntegerTypeEnum.sci_int8;
173     }
174
175     /**
176      * Constructor with single signed value
177      *
178      * @param value
179      *            the unique value
180      */
181     public ScilabInteger(short value) {
182         this.shortData = new short[1][1];
183         this.shortData[0][0] = value;
184         this.precision = ScilabIntegerTypeEnum.sci_int16;
185     }
186
187     /**
188      * Constructor with single signed value
189      *
190      * @param value
191      *            the unique value
192      */
193     public ScilabInteger(int value) {
194         this.intData = new int[1][1];
195         this.intData[0][0] = value;
196         this.precision = ScilabIntegerTypeEnum.sci_int32;
197     }
198
199     /**
200      * Constructor with single signed value
201      *
202      * @param value
203      *            the unique value
204      */
205     public ScilabInteger(long value) {
206         this.longData = new long[1][1];
207         this.longData[0][0] = value;
208         this.precision = ScilabIntegerTypeEnum.sci_int64;
209     }
210
211     /**
212      * Constructor with single signed value
213      *
214      * @param value
215      *            the unique value
216      */
217     public ScilabInteger(byte value, boolean bUnsigned) {
218         this(value);
219         this.precision = bUnsigned ? ScilabIntegerTypeEnum.sci_uint8 : ScilabIntegerTypeEnum.sci_int8;
220     }
221
222     /**
223      * Constructor with single signed value
224      *
225      * @param value
226      *            the unique value
227      */
228     public ScilabInteger(short value, boolean bUnsigned) {
229         this(value);
230         this.precision = bUnsigned ? ScilabIntegerTypeEnum.sci_uint16 : ScilabIntegerTypeEnum.sci_int16;
231     }
232
233     /**
234      * Constructor with single signed value
235      *
236      * @param value
237      *            the unique value
238      */
239     public ScilabInteger(int value, boolean bUnsigned) {
240         this(value);
241         this.precision = bUnsigned ? ScilabIntegerTypeEnum.sci_uint32 : ScilabIntegerTypeEnum.sci_int32;
242     }
243
244     /**
245      * Constructor with single signed value
246      *
247      * @param value
248      *            the unique value
249      */
250     public ScilabInteger(long value, boolean bUnsigned) {
251         this(value);
252         this.precision = bUnsigned ? ScilabIntegerTypeEnum.sci_uint64 : ScilabIntegerTypeEnum.sci_int64;
253     }
254
255     /**
256      * Set the current values
257      *
258      * @param data
259      *            the values to set
260      * @param bUnsigned
261      *            true, if these values are unsigned; false otherwise.
262      */
263     public void setData(byte[][] data, boolean bUnsigned) {
264         this.byteData = data;
265         if (bUnsigned) {
266             this.precision = ScilabIntegerTypeEnum.sci_uint8;
267         } else {
268             this.precision = ScilabIntegerTypeEnum.sci_int8;
269         }
270     }
271
272     /**
273      * Set the current values
274      *
275      * @param data
276      *            the values to set
277      * @param bUnsigned
278      *            true, if these values are unsigned; false otherwise.
279      */
280     public void setData(short[][] data, boolean bUnsigned) {
281         this.shortData = data;
282         if (bUnsigned) {
283             this.precision = ScilabIntegerTypeEnum.sci_uint16;
284         } else {
285             this.precision = ScilabIntegerTypeEnum.sci_int16;
286         }
287     }
288
289     /**
290      * Set the current values
291      *
292      * @param data
293      *            the values to set
294      * @param bUnsigned
295      *            true, if these values are unsigned; false otherwise.
296      */
297     public void setData(int[][] data, boolean bUnsigned) {
298         this.intData = data;
299         if (bUnsigned) {
300             this.precision = ScilabIntegerTypeEnum.sci_uint32;
301         } else {
302             this.precision = ScilabIntegerTypeEnum.sci_int32;
303         }
304     }
305
306     /**
307      * Set the current values
308      *
309      * @param data
310      *            the values to set
311      * @param bUnsigned
312      *            true, if these values are unsigned; false otherwise.
313      */
314     public void setData(long[][] data, boolean bUnsigned) {
315         this.longData = data;
316         if (bUnsigned) {
317             this.precision = ScilabIntegerTypeEnum.sci_uint64;
318         } else {
319             this.precision = ScilabIntegerTypeEnum.sci_int64;
320         }
321     }
322
323     /**
324      * Return the type of Scilab
325      *
326      * @return the type of Scilab
327      * @since 5.4.0
328      */
329     @Override
330     public ScilabTypeEnum getType() {
331         return type;
332     }
333
334     /**
335      * If the precision is not 64, all values will be converted to long
336      * (attention, the convertion can be long) if precision is 64, just return
337      * the data
338      *
339      * @return the values
340      */
341     public long[][] getData() {
342         long[][] convertedMatrix = new long[this.getHeight()][this.getWidth()];
343         switch (this.getPrec()) {
344
345             case sci_int8:
346             case sci_uint8:
347                 for (int i = 0; i < this.getHeight(); i++) {
348                     for (int j = 0; j < this.getWidth(); j++) {
349                         convertedMatrix[i][j] = Long.valueOf(getByteElement(i, j));
350                     }
351                 }
352                 return convertedMatrix;
353             case sci_int16:
354             case sci_uint16:
355                 for (int i = 0; i < this.getHeight(); i++) {
356                     for (int j = 0; j < this.getWidth(); j++) {
357                         convertedMatrix[i][j] = Long.valueOf(getShortElement(i, j));
358                     }
359                 }
360                 return convertedMatrix;
361             case sci_int32:
362             case sci_uint32:
363                 for (int i = 0; i < this.getHeight(); i++) {
364                     for (int j = 0; j < this.getWidth(); j++) {
365                         convertedMatrix[i][j] = Long.valueOf(getIntElement(i, j));
366                     }
367                 }
368                 return convertedMatrix;
369             case sci_int64:
370             case sci_uint64:
371                 return longData;
372         }
373         return null;
374     }
375
376     /**
377      * Returns the value as the form of short
378      *
379      * @return the values as short
380      */
381     public short[][] getDataAsShort() {
382         return shortData;
383     }
384
385     /**
386      * Returns the value as the form of byte
387      *
388      * @return the values as byte
389      */
390     public byte[][] getDataAsByte() {
391         return byteData;
392     }
393
394     /**
395      * Returns the value as the form of int
396      *
397      * @return the values as int
398      */
399     public int[][] getDataAsInt() {
400         return intData;
401     }
402
403     /**
404      * Returns the value as the form of long Only for Scilab 6.X
405      *
406      * @return the values as long
407      */
408     public long[][] getDataAsLong() {
409         return longData;
410     }
411
412     /**
413      * @return the precision of the values
414      */
415     public ScilabIntegerTypeEnum getPrec() {
416         return precision;
417     }
418
419     /**
420      * @return true, if the values are signed, false otherwise.
421      */
422     public boolean isUnsigned() {
423         switch (precision) {
424             case sci_int8:
425             case sci_int16:
426             case sci_int32:
427             case sci_int64:
428                 return false;
429             case sci_uint8:
430             case sci_uint16:
431             case sci_uint32:
432             case sci_uint64:
433                 return true;
434         }
435         return false;
436     }
437
438     /**
439      * Manage the old representation of IntegerType
440      *
441      * @param typeName
442      *            the typeName (TYPE8, TYPE16, TYPE32, TYPE64)
443      * @param unsigned
444      *            unsigned or not
445      * @return the converted type to ScilabIntegerTypeEnum. null is cannot
446      *         convert
447      */
448     public static ScilabIntegerTypeEnum convertOldType(String typeName, boolean unsigned) {
449         if (typeName.equals("TYPE8")) {
450             if (unsigned) {
451                 return ScilabIntegerTypeEnum.sci_uint8;
452             } else {
453                 return ScilabIntegerTypeEnum.sci_int8;
454             }
455         }
456         if (typeName.equals("TYPE16")) {
457             if (unsigned) {
458                 return ScilabIntegerTypeEnum.sci_uint16;
459             } else {
460                 return ScilabIntegerTypeEnum.sci_int16;
461             }
462         }
463         if (typeName.equals("TYPE32")) {
464             if (unsigned) {
465                 return ScilabIntegerTypeEnum.sci_uint32;
466             } else {
467                 return ScilabIntegerTypeEnum.sci_int32;
468             }
469         }
470         if (typeName.equals("TYPE64")) {
471             if (unsigned) {
472                 return ScilabIntegerTypeEnum.sci_uint64;
473             } else {
474                 return ScilabIntegerTypeEnum.sci_int64;
475             }
476         }
477         return null;
478     }
479
480     /**
481      * @return the height of the value matrix
482      * @see org.scilab.modules.types.ScilabType#getHeight()
483      */
484     @Override
485     public int getHeight() {
486         if (this.getPrec() == null) {
487             return 0;
488         }
489         switch (this.getPrec()) {
490             case sci_int8:
491             case sci_uint8:
492                 if (byteData == null) {
493                     return 0;
494                 }
495                 return byteData.length;
496             case sci_int16:
497             case sci_uint16:
498                 if (shortData == null) {
499                     return 0;
500                 }
501                 return shortData.length;
502             case sci_int32:
503             case sci_uint32:
504                 if (intData == null) {
505                     return 0;
506                 }
507                 return intData.length;
508             case sci_int64:
509             case sci_uint64:
510                 if (longData == null) {
511                     return 0;
512                 }
513                 return longData.length;
514             default:
515                 return 0;
516         }
517     }
518
519     /**
520      * @return the width of the value matrix
521      * @see org.scilab.modules.types.ScilabType#getWidth()
522      */
523     @Override
524     public int getWidth() {
525         if (this.getPrec() == null) {
526             return 0;
527         }
528         switch (this.getPrec()) {
529             case sci_int8:
530             case sci_uint8:
531                 if (byteData == null) {
532                     return 0;
533                 }
534                 return byteData[0].length;
535             case sci_int16:
536             case sci_uint16:
537                 if (shortData == null) {
538                     return 0;
539                 }
540                 return shortData[0].length;
541             case sci_int32:
542             case sci_uint32:
543                 if (intData == null) {
544                     return 0;
545                 }
546                 return intData[0].length;
547             case sci_int64:
548             case sci_uint64:
549                 if (longData == null) {
550                     return 0;
551                 }
552                 return longData[0].length;
553             default:
554                 return 0;
555         }
556     }
557
558     /**
559      * {@inheritDoc}
560      */
561     public boolean isReference() {
562         return byref;
563     }
564
565     /**
566      * @return true, if there is no values; false otherwise.
567      */
568     @Override
569     public boolean isEmpty() {
570         if (this.getPrec() == null) {
571             return true;
572         }
573         switch (this.getPrec()) {
574             case sci_int8:
575             case sci_uint8:
576                 return byteData == null;
577             case sci_int16:
578             case sci_uint16:
579                 return shortData == null;
580             case sci_int32:
581             case sci_uint32:
582                 return intData == null;
583             case sci_int64:
584             case sci_uint64:
585                 return longData == null;
586             default:
587                 return true;
588         }
589     }
590
591     /**
592      * {@inheritDoc}
593      */
594     public String getVarName() {
595         return varName;
596     }
597
598     /**
599      * {@inheritDoc}
600      */
601     public boolean isSwaped() {
602         return swaped;
603     }
604
605     /**
606      * Get the byte element at position (i, j)
607      * @param i the row index
608      * @param j the column index
609      * @return a byte
610      */
611     public byte getByteElement(final int i, final int j) {
612         return byteData[i][j];
613     }
614
615     /**
616      * Get the short element at position (i, j)
617      * @param i the row index
618      * @param j the column index
619      * @return a short
620      */
621     public short getShortElement(final int i, final int j) {
622         return shortData[i][j];
623     }
624
625     /**
626      * Get the int element at position (i, j)
627      * @param i the row index
628      * @param j the column index
629      * @return a int
630      */
631     public int getIntElement(final int i, final int j) {
632         return intData[i][j];
633     }
634
635     /**
636      * Get the long element at position (i, j)
637      * @param i the row index
638      * @param j the column index
639      * @return a long
640      */
641     public long getLongElement(final int i, final int j) {
642         return longData[i][j];
643     }
644
645     /**
646      * Set the byte element at position (i, j)
647      * @param i the row index
648      * @param j the column index
649      * @param x the byte to set
650      */
651     public void setByteElement(final int i, final int j, final byte x) {
652         byteData[i][j] = x;
653     }
654
655     /**
656      * Set the short element at position (i, j)
657      * @param i the row index
658      * @param j the column index
659      * @param x the short to set
660      */
661     public void setShortElement(final int i, final int j, final short x) {
662         shortData[i][j] = x;
663     }
664
665     /**
666      * Set the int element at position (i, j)
667      * @param i the row index
668      * @param j the column index
669      * @param x the int to set
670      */
671     public void setIntElement(final int i, final int j, final int x) {
672         intData[i][j] = x;
673     }
674
675     /**
676      * Set the long element at position (i, j)
677      * @param i the row index
678      * @param j the column index
679      * @param x the long to set
680      */
681     public void setLongElement(final int i, final int j, final long x) {
682         longData[i][j] = x;
683     }
684
685
686     /**
687      * Get the element at position (i, j) as a long
688      * @param i the row index
689      * @param j the column index
690      * @return a long
691      */
692     public long getElement(final int i, final int j) {
693         switch (this.getPrec()) {
694             case sci_int8:
695             case sci_uint8:
696                 return getByteElement(i, j);
697             case sci_int16:
698             case sci_uint16:
699                 return getShortElement(i, j);
700             case sci_int32:
701             case sci_uint32:
702                 return getIntElement(i, j);
703             case sci_int64:
704             case sci_uint64:
705                 return getLongElement(i, j);
706         }
707
708         return 0;
709     }
710
711     /**
712      * Set the element at position (i, j)
713      * @param i the row index
714      * @param j the column index
715      * @param x a long
716      */
717     public void setElement(final int i, final int j, final long x) {
718         switch (this.getPrec()) {
719             case sci_int8:
720             case sci_uint8:
721                 setByteElement(i, j, (byte) x);
722                 break;
723             case sci_int16:
724             case sci_uint16:
725                 setShortElement(i, j, (short) x);
726                 break;
727             case sci_int32:
728             case sci_uint32:
729                 setIntElement(i, j, (int) x);
730                 break;
731             case sci_int64:
732             case sci_uint64:
733                 setLongElement(i, j, x);
734                 break;
735         }
736     }
737
738     @Override
739     public int hashCode() {
740         final int prime = 31;
741         int result = 1;
742         result = prime * result + Arrays.deepHashCode(byteData);
743         result = prime * result + Arrays.deepHashCode(intData);
744         result = prime * result + Arrays.deepHashCode(longData);
745         result = prime * result + ((precision == null) ? 0 : precision.hashCode());
746         result = prime * result + Arrays.deepHashCode(shortData);
747         return result;
748     }
749
750     /**
751      * @see org.scilab.modules.types.ScilabType#equals(Object)
752      */
753     @Override
754     public boolean equals(Object obj) {
755         if (obj instanceof ScilabInteger) {
756             ScilabInteger sciInt = (ScilabInteger) obj;
757             if (isEmpty() && sciInt.isEmpty()) {
758                 return true;
759             }
760
761             if (this.getWidth() != sciInt.getWidth() || this.getHeight() != sciInt.getHeight()) {
762                 return false;
763             }
764
765             return ScilabTypeUtils.equalsInteger(this.getRawData(), this.isSwaped(), sciInt.getRawData(), sciInt.isSwaped());
766         } else {
767             return false;
768         }
769     }
770
771     /**
772      * Get the data as a array of arrays
773      * @return the data
774      */
775     public Object getCorrectData() {
776         switch (this.getPrec()) {
777             case sci_int8:
778             case sci_uint8:
779                 return byteData;
780             case sci_int16:
781             case sci_uint16:
782                 return shortData;
783             case sci_int32:
784             case sci_uint32:
785                 return intData;
786             case sci_int64:
787             case sci_uint64:
788                 return longData;
789         }
790         return null;
791     }
792
793     /**
794      * Get the data as they are
795      * @return the data
796      */
797     public Object getRawData() {
798         return getCorrectData();
799     }
800
801     /**
802      * {@inheritDoc}
803      */
804     public Object getSerializedObject() {
805         return new Object[] { new int[] { this.getPrec().swigValue() }, getCorrectData() };
806     }
807
808     @Override
809     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
810         int version = in.readInt();
811         switch (version) {
812             case 0:
813                 precision = ScilabIntegerTypeEnum.swigToEnum(in.readInt());
814                 Object data = in.readObject();
815                 switch (precision) {
816                     case sci_int8:
817                     case sci_uint8:
818                         byteData = (byte[][]) data;
819                         break;
820                     case sci_int16:
821                     case sci_uint16:
822                         shortData = (short[][]) data;
823                         break;
824                     case sci_int32:
825                     case sci_uint32:
826                         intData = (int[][]) data;
827                         break;
828                     case sci_int64:
829                     case sci_uint64:
830                         longData = (long[][]) data;
831                         break;
832                 }
833                 varName = (String) in.readObject();
834                 swaped = in.readBoolean();
835                 break;
836             default:
837                 throw new ClassNotFoundException("A class ScilabInteger with a version " + version + " does not exists");
838         }
839     }
840
841     @Override
842     public void writeExternal(ObjectOutput out) throws IOException {
843         out.writeInt(VERSION);
844         out.writeInt(getPrec().swigValue());
845         out.writeObject(getCorrectData());
846         out.writeObject(varName);
847         out.writeBoolean(swaped);
848     }
849
850     /**
851      * Display the representation in the Scilab language of the type<BR>
852      * Note that the representation can be copied/pasted straight into Scilab
853      *
854      * @return the pretty-printed values
855      * @see java.lang.Object#toString()
856      */
857     @Override
858     public String toString() {
859         StringBuilder result = new StringBuilder();
860
861         if (isEmpty()) {
862             return "[]";
863         }
864
865         if (isUnsigned()) {
866             result.append("u");
867         }
868         result.append("int");
869
870         switch (this.getPrec()) {
871             case sci_int8:
872             case sci_uint8:
873                 result.append("8");
874                 break;
875
876             case sci_int16:
877             case sci_uint16:
878                 result.append("16");
879                 break;
880
881             case sci_int32:
882             case sci_uint32:
883                 result.append("32");
884                 break;
885
886             case sci_int64:
887             case sci_uint64:
888                 result.append("64");
889                 break;
890
891             default:
892                 break;
893         }
894
895         result.append("([");
896         appendData(result);
897         result.append("])");
898
899         return result.toString();
900     }
901
902     /**
903      * Put each value on the buffer.
904      *
905      * @param result
906      *            the current buffer
907      */
908     private void appendData(StringBuilder result) {
909         long[][] d = getData();
910         for (int i = 0; i < getHeight(); ++i) {
911             for (int j = 0; j < getWidth(); ++j) {
912
913                 result.append(d[i][j]);
914
915                 if (j != getWidth() - 1) {
916                     result.append(", ");
917                 }
918             }
919             if (i != getHeight() - 1) {
920                 result.append(" ; ");
921             }
922         }
923     }
924 }