* Bug 15535 fixed: sign(int8(0)) was wrong. sign() page improved
[scilab.git] / scilab / modules / ast / includes / types / int.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
4  *  Copyright (C) 2014 - Scilab Enterprises - 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 //#ifndef __ARRAYOF_HXX__
18 //    #error This file must only be include by arrayof.hxx
19 //#endif
20
21 #ifndef __INT_HXX__
22 #define __INT_HXX__
23
24 #include "arrayof.hxx"
25 #include "bool.hxx"
26 #include "internal.hxx"
27 #include "types_transposition.hxx"
28 #include "configvariable.hxx"
29 #include "type_traits.hxx"
30
31 #include <sstream>
32 #include <string>
33 #include <limits>       // std::numeric_limits
34 #include "tostring_common.hxx"
35
36 namespace types
37 {
38 template<typename T>
39 class EXTERN_AST Int : public ArrayOf<T>
40 {
41 public :
42
43     Int(int _iRows, int _iCols)
44     {
45         int piDims[2] = {_iRows, _iCols};
46         T * pInt = NULL;
47         this->create(piDims, 2, &pInt, NULL);
48 #ifndef NDEBUG
49         //Inspector::addItem(this);
50 #endif
51     }
52
53     Int(T _val)
54     {
55         int piDims[2]   = {1, 1};
56         T * pInt = NULL;
57         this->create(piDims, 2, &pInt, NULL);
58         pInt[0] = _val;
59 #ifndef NDEBUG
60         //Inspector::addItem(this);
61 #endif
62     }
63
64     Int(int _iRows, int _iCols, T** _pData)
65     {
66         const int piDims[2] = {_iRows, _iCols};
67         this->create(piDims, 2, _pData, NULL);
68 #ifndef NDEBUG
69         //Inspector::addItem(this);
70 #endif
71     }
72
73     Int(int _iDims, const int* _piDims)
74     {
75         T * pInt = NULL;
76         this->create(_piDims, _iDims, &pInt, NULL);
77 #ifndef NDEBUG
78         //Inspector::addItem(this);
79 #endif
80     }
81
82     ~Int()
83     {
84         if (InternalType::isDeletable() == true)
85         {
86             deleteAll();
87         }
88 #ifndef NDEBUG
89         //Inspector::removeItem(this);
90 #endif
91     }
92
93     Int<T>* clone()
94     {
95         Int<T> *pbClone = new Int<T>(GenericType::getDims(), GenericType::getDimsArray());
96         pbClone->set(ArrayOf<T>::get());
97         return pbClone;
98     }
99     
100     /*Config management*/
101     void whoAmI();
102
103     bool isInt()
104     {
105         return true;
106     }
107
108     bool neg(InternalType *& out)
109     {
110         out = new Int<T>(this->getDims(), this->getDimsArray());
111         type_traits::bin_neg<T, T>(this->m_iSize, this->m_pRealData, static_cast<Int<T> *>(out)->get());
112
113         return true;
114     }
115
116     virtual bool transpose(InternalType *& out)
117     {
118         return type_traits::transpose(*this, out);
119     }
120
121     bool operator==(const InternalType& it)
122     {
123         if (const_cast<InternalType &>(it).getType() != getType())
124         {
125             return false;
126         }
127
128         Int<T>* pb = const_cast<InternalType &>(it).getAs<typename types::Int<T> >();
129
130         if (pb->getDims() != GenericType::getDims())
131         {
132             return false;
133         }
134
135         for (int i = 0 ; i < GenericType::getDims() ; i++)
136         {
137             if (pb->getDimsArray()[i] != GenericType::getDimsArray()[i])
138             {
139                 return false;
140             }
141         }
142
143         if (memcmp(ArrayOf<T>::get(), pb->get(), GenericType::getSize() * sizeof(T)) != 0)
144         {
145             return false;
146         }
147         return true;
148     }
149
150     bool operator!=(const InternalType& it)
151     {
152         return !(*this == it);
153     }
154
155     /* return type as string ( double, int, cell, list, ... )*/
156     virtual std::wstring        getTypeStr() const;
157
158     /* return type as short string ( s, i, ce, l, ... )*/
159     virtual std::wstring        getShortTypeStr() const
160     {
161         return L"i";
162     }
163
164     virtual bool isNativeType() override
165     {
166         return true;
167     }
168
169     virtual void fillDefaultValues() override
170     {
171         int size = GenericType::getSize();
172         memset(this->m_pRealData, 0x00, sizeof(T) * size);
173     }
174
175     Int<T>* sign()
176     {
177         Int<T> *pOut = new Int<T>(getDims(), getDimsArray());
178         T* p = pOut->get();
179         int size = getSize();
180         for (int i = 0; i < size; ++i)
181         {
182             p[i] = (m_pRealData[i] > T(0)) - (m_pRealData[i] < T(0));
183         }
184         return pOut;
185     }
186
187 protected :
188     inline InternalType::ScilabType getType(void);
189     inline InternalType::ScilabId   getId(void);
190
191 private :
192     virtual bool subMatrixToString(std::wostringstream& ostr, int* _piDims, int /*_iDims*/) override
193     {
194         int iCurrentLine = 0;
195         int iLineLen = ConfigVariable::getConsoleWidth();
196         int iMaxLines = ConfigVariable::getConsoleLines();
197
198         if (GenericType::isIdentity())
199         {
200             ostr << L"eye *" << std::endl << std::endl;
201             int iWidth = 0;
202             if (isSigned())
203             {
204                 getSignedIntFormat(ArrayOf<T>::get(0), &iWidth);
205                 addSignedIntValue(&ostr, ArrayOf<T>::get(0), iWidth);
206             }
207             else
208             {
209                 getUnsignedIntFormat(ArrayOf<T>::get(0), &iWidth);
210                 addUnsignedIntValue(&ostr, ArrayOf<T>::get(0), iWidth);
211             }
212             ostr << std::endl;
213         }
214         else if (GenericType::isScalar())
215         {
216             //scalar
217             int iWidth  = 0;
218             _piDims[0]  = 0;
219             _piDims[1]  = 0;
220             int iPos    = ArrayOf<T>::getIndex(_piDims);
221
222             if (isSigned())
223             {
224                 getSignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
225                 addSignedIntValue(&ostr, ArrayOf<T>::get(iPos), iWidth);
226             }
227             else
228             {
229                 getUnsignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
230                 addUnsignedIntValue(&ostr, ArrayOf<T>::get(iPos), iWidth);
231             }
232             ostr << std::endl;
233         }
234         else if (GenericType::getCols() == 1)
235         {
236             //column vector
237             int iWidthMax = 0;
238
239             //Array with the max printed size of each col
240             for (int i = 0 ; i < GenericType::getRows() ; i++)
241             {
242                 _piDims[1] = 0;
243                 _piDims[0] = i;
244                 int iWidth = 0;
245                 int iPos = ArrayOf<T>::getIndex(_piDims);
246                 if (isSigned())
247                 {
248                     getSignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
249                 }
250                 else
251                 {
252                     getUnsignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
253                 }
254                 iWidthMax = (std::max)(iWidthMax, iWidth);
255             }
256
257             for (int i = this->m_iRows1PrintState ; i < this->getRows() ; i++)
258             {
259                 iCurrentLine++;
260                 if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
261                 {
262                     this->m_iRows1PrintState = i;
263                     return false;
264                 }
265
266                 _piDims[1]  = 0;
267                 _piDims[0]  = i;
268                 int iPos    = ArrayOf<T>::getIndex(_piDims);
269
270                 if (isSigned())
271                 {
272                     addSignedIntValue(&ostr, ArrayOf<T>::get(iPos), iWidthMax);
273                 }
274                 else
275                 {
276                     addUnsignedIntValue(&ostr, ArrayOf<T>::get(iPos), iWidthMax);
277                 }
278                 ostr << std::endl;
279             }
280         }
281         else if (GenericType::getRows() == 1)
282         {
283             //row vector
284             std::wostringstream ostemp;
285             int iLastVal = this->m_iCols1PrintState;
286
287             for (int i = this->m_iCols1PrintState ; i < this->getCols() ; i++)
288             {
289                 int iWidth  = 0;
290                 int iLen    = 0;
291                 _piDims[0]  = 0;
292                 _piDims[1]  = i;
293                 int iPos    = ArrayOf<T>::getIndex(_piDims);
294
295                 if (isSigned())
296                 {
297                     getSignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
298                 }
299                 else
300                 {
301                     getUnsignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
302                 }
303
304                 iLen = iWidth + static_cast<int>(ostemp.str().size());
305                 if (iLen > iLineLen && iLastVal != i)
306                 {
307                     //Max length, new line
308                     iCurrentLine += 4; //"column x to Y" + empty line + value + empty line
309                     if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
310                     {
311                         this->m_iCols1PrintState = iLastVal;
312                         return false;
313                     }
314
315                     addColumnString(ostr, iLastVal + 1, i);
316                     ostr << ostemp.str() << std::endl;
317                     ostemp.str(L"");
318                     iLastVal = i;
319                 }
320
321                 if (isSigned())
322                 {
323                     addSignedIntValue(&ostemp, ArrayOf<T>::get(iPos), iWidth);
324                 }
325                 else
326                 {
327                     addUnsignedIntValue(&ostemp, ArrayOf<T>::get(iPos), iWidth);
328                 }
329             }
330
331             if (iLastVal != 0)
332             {
333                 addColumnString(ostr, iLastVal + 1, GenericType::getCols());
334             }
335
336             ostemp << std::endl;
337             ostr << ostemp.str();
338         }
339         else // matrix
340         {
341             std::wostringstream ostemp;
342             int iLen = 0;
343             int iLastCol = this->m_iCols1PrintState;
344
345             //Array with the max printed size of each col
346             int *piSize = new int[GenericType::getCols()];
347             memset(piSize, 0x00, GenericType::getCols() * sizeof(int));
348
349             //compute the row size for padding for each printed bloc.
350             for (int iCols1 = this->m_iCols1PrintState ; iCols1 < this->getCols() ; iCols1++)
351             {
352                 for (int iRows1 = 0 ; iRows1 < this->getRows() ; iRows1++)
353                 {
354                     int iWidth  = 0;
355                     _piDims[0]  = iRows1;
356                     _piDims[1]  = iCols1;
357                     int iPos    = ArrayOf<T>::getIndex(_piDims);
358
359                     if (isSigned())
360                     {
361                         getSignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
362                     }
363                     else
364                     {
365                         getUnsignedIntFormat(ArrayOf<T>::get(iPos), &iWidth);
366                     }
367                     piSize[iCols1] = (std::max)(piSize[iCols1], iWidth);
368                 }
369
370                 if (iLen + piSize[iCols1] > iLineLen && iCols1 != iLastCol)
371                 {
372                     //find the limit, print this part
373                     for (int iRows2 = this->m_iRows2PrintState ; iRows2 < this->getRows() ; iRows2++)
374                     {
375                         iCurrentLine++;
376                         if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) ||
377                                 ( (iMaxLines != 0 && iCurrentLine + 3 >= iMaxLines && iRows2 == this->m_iRows2PrintState) ||
378                                   (iMaxLines != 0 && iCurrentLine + 1 >= iMaxLines && iRows2 != this->m_iRows2PrintState)))
379                         {
380                             if (this->m_iRows2PrintState == 0 && iRows2 != 0)
381                             {
382                                 //add header
383                                 addColumnString(ostr, iLastCol + 1, iCols1);
384                             }
385
386                             ostr << ostemp.str();
387                             this->m_iRows2PrintState = iRows2;
388                             this->m_iCols1PrintState = iLastCol;
389                             return false;
390                         }
391
392                         for (int iCols2 = iLastCol ; iCols2 < iCols1 ; iCols2++)
393                         {
394                             _piDims[0]  = iRows2;
395                             _piDims[1]  = iCols2;
396                             int iPos    = ArrayOf<T>::getIndex(_piDims);
397
398                             if (isSigned())
399                             {
400                                 addSignedIntValue(&ostemp, ArrayOf<T>::get(iPos), piSize[iCols2]);
401                             }
402                             else
403                             {
404                                 addUnsignedIntValue(&ostemp, ArrayOf<T>::get(iPos), piSize[iCols2]);
405                             }
406                         }
407                         ostemp << std::endl;
408                     }
409                     iLen = 0;
410
411                     iCurrentLine++;
412                     if (this->m_iRows2PrintState == 0)
413                     {
414                         iCurrentLine += 3;
415                         addColumnString(ostr, iLastCol + 1, iCols1);
416                     }
417
418                     ostr << ostemp.str();
419                     ostemp.str(L"");
420                     iLastCol = iCols1;
421                     this->m_iRows2PrintState = 0;
422                     this->m_iCols1PrintState = 0;
423                 }
424
425                 iLen += piSize[iCols1] + SIGN_LENGTH + SIZE_BETWEEN_TWO_VALUES;
426             }
427
428             for (int iRows2 = this->m_iRows2PrintState ; iRows2 < this->getRows() ; iRows2++)
429             {
430                 iCurrentLine++;
431                 if ((iMaxLines == 0 && iCurrentLine >= MAX_LINES) || (iMaxLines != 0 && iCurrentLine >= iMaxLines))
432                 {
433                     if (this->m_iRows2PrintState == 0 && iLastCol != 0)
434                     {
435                         //add header
436                         addColumnString(ostr, iLastCol + 1, GenericType::getCols());
437                     }
438
439                     ostr << ostemp.str();
440                     this->m_iRows2PrintState = iRows2;
441                     this->m_iCols1PrintState = iLastCol;
442                     return false;
443                 }
444
445                 for (int iCols2 = iLastCol ; iCols2 < GenericType::getCols() ; iCols2++)
446                 {
447                     _piDims[0]  = iRows2;
448                     _piDims[1]  = iCols2;
449                     int iPos    = ArrayOf<T>::getIndex(_piDims);
450
451                     if (isSigned())
452                     {
453                         addSignedIntValue(&ostemp, ArrayOf<T>::get(iPos), piSize[iCols2]);
454                     }
455                     else
456                     {
457                         addUnsignedIntValue(&ostemp, ArrayOf<T>::get(iPos), piSize[iCols2]);
458                     }
459                 }
460                 ostemp << std::endl;
461             }
462
463             if (this->m_iRows2PrintState == 0 && iLastCol != 0)
464             {
465                 addColumnString(ostr, iLastCol + 1, GenericType::getCols());
466             }
467
468             ostr << ostemp.str();
469         }
470
471         return true;
472     }
473
474     virtual T getNullValue()
475     {
476         return T(0);
477     }
478
479     virtual Int<T>* createEmpty(int _iDims, int* _piDims, bool /*_bComplex*/)
480     {
481         return new Int<T>(_iDims, _piDims);
482     }
483
484     virtual T copyValue(T _data)
485     {
486         return _data;
487     }
488
489     virtual void deleteAll()
490     {
491         delete[] ArrayOf<T>::m_pRealData;
492         ArrayOf<T>::m_pRealData = NULL;
493         deleteImg();
494     }
495
496     virtual void deleteImg() { }
497
498     virtual T* allocData(int _iSize)
499     {
500         return new T[_iSize];
501     }
502
503     template<typename U, typename V> struct is_same_int
504     {
505         const static bool value = false;
506     };
507     template<typename U> struct is_same_int<U, U>
508     {
509         const static bool value = true;
510     };
511
512 public:
513     bool isInt8()
514     {
515         return is_same_int<T, char>::value;
516     }
517     bool isInt16()
518     {
519         return is_same_int<T, short>::value;
520     }
521     bool isInt32()
522     {
523         return is_same_int<T, int>::value;
524     }
525     bool isInt64()
526     {
527         return is_same_int<T, long long>::value;
528     }
529     bool isUInt8()
530     {
531         return is_same_int<T, unsigned char>::value;
532     }
533     bool isUInt16()
534     {
535         return is_same_int<T, unsigned short>::value;
536     }
537     bool isUInt32()
538     {
539         return is_same_int<T, unsigned int>::value;
540     }
541     bool isUInt64()
542     {
543         return is_same_int<T, unsigned long long>::value;
544     }
545
546     bool isUnsigned()
547     {
548         return !isSigned();
549     }
550
551     bool isSigned()
552     {
553         return std::numeric_limits<T>::is_signed;
554     }
555 };
556
557 template<> inline InternalType::ScilabType Int<char>::getType()
558 {
559     return ScilabInt8;
560 }
561 template<> inline InternalType::ScilabType Int<unsigned char>::getType()
562 {
563     return ScilabUInt8;
564 }
565 template<> inline InternalType::ScilabType Int<short>::getType()
566 {
567     return ScilabInt16;
568 }
569 template<> inline InternalType::ScilabType Int<unsigned short>::getType()
570 {
571     return ScilabUInt16;
572 }
573 template<> inline InternalType::ScilabType Int<int>::getType()
574 {
575     return ScilabInt32;
576 }
577 template<> inline InternalType::ScilabType Int<unsigned int>::getType()
578 {
579     return ScilabUInt32;
580 }
581 template<> inline InternalType::ScilabType Int<long long>::getType()
582 {
583     return ScilabInt64;
584 }
585 template<> inline InternalType::ScilabType Int<unsigned long long>::getType()
586 {
587     return ScilabUInt64;
588 }
589
590 template<> inline InternalType::ScilabId Int<char>::getId()
591 {
592     return GenericType::isScalar() ? IdScalarInt8 : IdInt8;
593 }
594 template<> inline InternalType::ScilabId Int<unsigned char>::getId()
595 {
596     return GenericType::isScalar() ? IdScalarUInt8 : IdUInt8;
597 }
598 template<> inline InternalType::ScilabId Int<short>::getId()
599 {
600     return GenericType::isScalar() ? IdScalarInt16 : IdInt16;
601 }
602 template<> inline InternalType::ScilabId Int<unsigned short>::getId()
603 {
604     return GenericType::isScalar() ? IdScalarUInt16 : IdUInt16;
605 }
606 template<> inline InternalType::ScilabId Int<int>::getId()
607 {
608     return GenericType::isScalar() ? IdScalarInt32 : IdInt32;
609 }
610 template<> inline InternalType::ScilabId Int<unsigned int>::getId()
611 {
612     return GenericType::isScalar() ? IdScalarUInt32 : IdUInt32;
613 }
614 template<> inline InternalType::ScilabId Int<long long>::getId()
615 {
616     return GenericType::isScalar() ? IdScalarInt64 : IdInt64;
617 }
618 template<> inline InternalType::ScilabId Int<unsigned long long>::getId()
619 {
620     return GenericType::isScalar() ? IdScalarUInt64 : IdUInt64;
621 }
622
623 // Specializations
624 template<> inline std::wstring Int<char>::getTypeStr() const
625 {
626     return L"int8";
627 }
628
629 template<> inline std::wstring Int<short>::getTypeStr() const
630 {
631     return L"int16";
632 }
633
634 template<> inline std::wstring Int<int>::getTypeStr() const
635 {
636     return L"int32";
637 }
638
639 template<> inline std::wstring Int<long long>::getTypeStr() const
640 {
641     return L"int64";
642 }
643
644 template<> inline std::wstring Int<unsigned char>::getTypeStr() const
645 {
646     return L"uint8";
647 }
648
649 template<> inline std::wstring Int<unsigned short>::getTypeStr() const
650 {
651     return L"uint16";
652 }
653
654 template<> inline std::wstring Int<unsigned int>::getTypeStr() const
655 {
656     return L"uint32";
657 }
658
659 template<> inline std::wstring Int<unsigned long long>::getTypeStr() const
660 {
661     return L"uint64";
662 }
663
664 template<> inline void Int<char>::whoAmI()
665 {
666     std::cout << "types::Int8";
667 }
668
669 template<> inline void Int<short>::whoAmI()
670 {
671     std::cout << "types::Int16";
672 }
673
674 template<> inline void Int<int>::whoAmI()
675 {
676     std::cout << "types::Int32";
677 }
678
679 template<> inline void Int<long long>::whoAmI()
680 {
681     std::cout << "types::Int64";
682 }
683
684 template<> inline void Int<unsigned char>::whoAmI()
685 {
686     std::cout << "types::UInt8";
687 }
688
689 template<> inline void Int<unsigned short>::whoAmI()
690 {
691     std::cout << "types::UInt16";
692 }
693
694 template<> inline void Int<unsigned int>::whoAmI()
695 {
696     std::cout << "types::UInt32";
697 }
698
699 template<> inline void Int<unsigned long long>::whoAmI()
700 {
701     std::cout << "types::UInt64";
702 }
703
704
705 typedef Int<char> Int8;
706 typedef Int<short> Int16;
707 typedef Int<int> Int32;
708 typedef Int<long long> Int64;
709
710 typedef Int<unsigned char> UInt8;
711 typedef Int<unsigned short> UInt16;
712 typedef Int<unsigned int> UInt32;
713 typedef Int<unsigned long long> UInt64;
714
715 #ifdef _MSC_VER
716 template class Int<char>;
717 template class Int<unsigned char>;
718 template class Int<short>;
719 template class Int<unsigned short>;
720 template class Int<int>;
721 template class Int<unsigned int>;
722 template class Int<long long>;
723 template class Int<unsigned long long>;
724 #endif
725 }
726
727
728 #endif /* !__INT_HXX__ */