[ast] improved polynomial display with unicode superscripts
[scilab.git] / scilab / modules / ast / src / cpp / types / cell.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
4 *  Copyright (C) 2011 - DIGITEO - Antoine ELIAS
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 #include <algorithm>
18 #include <sstream>
19 #include <math.h>
20 #include <iomanip>
21 #include "symbol.hxx"
22 #include "cell.hxx"
23 #include "double.hxx"
24 #include "list.hxx"
25 #include "colon.hxx"
26 #include "tostring_common.hxx"
27 #include "core_math.h"
28 #include "list.hxx"
29 #include "configvariable.hxx"
30 #include "types_tools.hxx"
31
32 namespace types
33 {
34 /**
35 ** Constructor & Destructor (public)
36 */
37 Cell::Cell()
38 {
39     int piDims[2] = {0, 0};
40     createCell(2, piDims, nullptr);
41 }
42
43 Cell::Cell(int _iRows, int _iCols, InternalType** data)
44 {
45     int piDims[2] = {_iRows, _iCols};
46     createCell(2, piDims, data);
47 }
48
49 Cell::Cell(int _iDims, const int* _piDims, InternalType** data)
50 {
51     createCell(_iDims, _piDims, data);
52 }
53
54 bool Cell::getMemory(long long* _piSize, long long* _piSizePlusType)
55 {
56     *_piSize = 0;
57     *_piSizePlusType = 0;
58     InternalType** p = get();
59     for (int i = 0; i < getSize(); i++)
60     {
61         long long piS, piSPT;
62         if (p[i]->getMemory(&piS, &piSPT))
63         {
64             *_piSize += piS;
65             *_piSizePlusType += piSPT;
66         }
67     }
68     *_piSizePlusType += sizeof(Cell);
69     return true;
70 }
71
72 void Cell::createCell(int _iDims, const int* _piDims, InternalType** data)
73 {
74     InternalType** pIT = NULL;
75     create(_piDims, _iDims, &pIT, NULL);
76     if( m_iSizeMax == 0)
77     {
78         return;
79     }
80
81     if (data == nullptr)
82     {
83         types::Double* pDbl = Double::Empty();
84         for (int i = 0; i < m_iSizeMax; i++)
85         {
86             m_pRealData[i] = pDbl;
87             m_pRealData[i]->IncreaseRef();
88         }
89     }
90     else
91     {
92         for (int i = 0; i < m_iSizeMax; i++)
93         {
94             m_pRealData[i] = data[i];
95             m_pRealData[i]->IncreaseRef();
96         }
97     }
98
99 #ifndef NDEBUG
100     Inspector::addItem(this);
101 #endif
102 }
103
104 Cell::~Cell()
105 {
106     if (isDeletable() == true)
107     {
108         for (int i = 0; i < m_iSizeMax; i++)
109         {
110             m_pRealData[i]->DecreaseRef();
111             m_pRealData[i]->killMe();
112         }
113     }
114
115     delete[] m_pRealData;
116 #ifndef NDEBUG
117     Inspector::removeItem(this);
118 #endif
119 }
120
121 /**
122 ** Private Copy Constructor and data Access
123 */
124 Cell::Cell(Cell *_oCellCopyMe)
125 {
126     InternalType** pIT = NULL;
127     create(_oCellCopyMe->getDimsArray(), _oCellCopyMe->getDims(), &pIT, NULL);
128     for (int i = 0 ; i < getSize() ; i++)
129     {
130         m_pRealData[i] = NULL;
131     }
132
133     for (int i = 0 ; i < getSize() ; i++)
134     {
135         set(i, _oCellCopyMe->get(i)->clone());
136     }
137 #ifndef NDEBUG
138     Inspector::addItem(this);
139 #endif
140 }
141
142 bool Cell::transpose(InternalType *& out)
143 {
144     if (isScalar())
145     {
146         out = clone();
147         return true;
148     }
149
150     if (m_iDims == 2)
151     {
152         Cell * pC = new Cell();
153         out = pC;
154         InternalType** pIT = NULL;
155         int piDims[2] = {getCols(), getRows()};
156         pC->create(piDims, 2, &pIT, NULL);
157
158         Transposition::transpose_clone(getRows(), getCols(), m_pRealData, pC->m_pRealData);
159
160         return true;
161     }
162
163     return false;
164 }
165
166 Cell* Cell::set(int _iRows, int _iCols, InternalType* _pIT)
167 {
168     if (_iRows < getRows() && _iCols < getCols())
169     {
170         return set(_iCols * getRows() + _iRows, _pIT);
171     }
172     return NULL;
173 }
174
175 Cell* Cell::set(int _iRows, int _iCols, const InternalType* _pIT)
176 {
177     if (_iRows < getRows() && _iCols < getCols())
178     {
179         return set(_iCols * getRows() + _iRows, _pIT);
180     }
181     return NULL;
182 }
183
184 Cell* Cell::set(int _iIndex, InternalType* _pIT)
185 {
186     if (_iIndex >= m_iSize)
187     {
188         return NULL;
189     }
190
191     // corner case when inserting twice
192     if (m_pRealData[_iIndex] == _pIT)
193     {
194         return this;
195     }
196
197     typedef Cell* (Cell::*set_t)(int, InternalType*);
198     Cell* pIT = checkRef(this, (set_t)&Cell::set, _iIndex, _pIT);
199     if (pIT != this)
200     {
201         return pIT;
202     }
203
204     if (m_pRealData[_iIndex] != NULL)
205     {
206         m_pRealData[_iIndex]->DecreaseRef();
207         m_pRealData[_iIndex]->killMe();
208     }
209
210     _pIT->IncreaseRef();
211     m_pRealData[_iIndex] = _pIT;
212     return this;
213 }
214
215 Cell* Cell::set(int _iIndex, const InternalType* _pIT)
216 {
217     if (_iIndex >= m_iSize)
218     {
219         return NULL;
220     }
221
222     typedef Cell* (Cell::*set_t)(int, const InternalType*);
223     Cell* pIT = checkRef(this, (set_t)&Cell::set, _iIndex, _pIT);
224     if (pIT != this)
225     {
226         return pIT;
227     }
228
229     if (m_pRealData[_iIndex] != NULL)
230     {
231         m_pRealData[_iIndex]->DecreaseRef();
232         m_pRealData[_iIndex]->killMe();
233     }
234
235     const_cast<InternalType*>(_pIT)->IncreaseRef();
236     m_pRealData[_iIndex] = const_cast<InternalType*>(_pIT);
237
238     return this;
239 }
240
241 Cell* Cell::set(InternalType** _pIT)
242 {
243     typedef Cell* (Cell::*set_t)(InternalType**);
244     Cell* pIT = checkRef(this, (set_t)&Cell::set, _pIT);
245     if (pIT != this)
246     {
247         return pIT;
248     }
249
250     for (int i = 0; i < m_iSize; i++)
251     {
252         if (i >= m_iSize)
253         {
254             return NULL;
255         }
256
257         if (m_pRealData[i] != NULL)
258         {
259             m_pRealData[i]->DecreaseRef();
260             m_pRealData[i]->killMe();
261         }
262
263         _pIT[i]->IncreaseRef();
264         m_pRealData[i] = _pIT[i];
265     }
266
267     return this;
268 }
269
270 /**
271 ** Clone
272 ** Create a new Struct and Copy all values.
273 */
274 Cell* Cell::clone()
275 {
276     return new Cell(this);
277 }
278
279 InternalType* Cell::getNullValue()
280 {
281     return Double::Empty();
282 }
283
284 Cell* Cell::createEmpty(int _iDims, int* _piDims, bool /*_bComplex*/)
285 {
286     return new Cell(_iDims, _piDims);
287 }
288
289 InternalType* Cell::copyValue(InternalType* _pData)
290 {
291     _pData->IncreaseRef();
292     return _pData;
293 }
294
295 void Cell::deleteAll()
296 {
297     for (int i = 0 ; i < getSize() ; i++)
298     {
299         m_pRealData[i]->DecreaseRef();
300         m_pRealData[i]->killMe();
301     }
302
303     delete[] m_pRealData;
304     m_pRealData = NULL;
305 }
306
307 void Cell::deleteImg()
308 {
309     return;
310 }
311
312 bool Cell::isEmpty()
313 {
314     if (getDims() == 2 && getRows() == 0 && getCols() == 0)
315     {
316         return true;
317     }
318     return false;
319 }
320
321 /**
322 ** toString to display Structs
323 ** FIXME : Find a better indentation process
324 */
325 bool Cell::subMatrixToString(std::wostringstream& ostr, int* _piDims, int /*_iDims*/)
326 {
327     int iPrecision = ConfigVariable::getFormatSize();
328
329     if (isEmpty())
330     {
331         ostr << L"   {}";
332     }
333     else
334     {
335         //max len for each column
336         int *piTypeLen = new int[getCols()];
337         int *piSizeLen = new int[getCols()];
338
339         memset(piTypeLen, 0x00, getCols() * sizeof(int));
340         memset(piSizeLen, 0x00, getCols() * sizeof(int));
341
342         for (int j = 0 ; j < getCols() ; j++)
343         {
344             for (int i = 0 ; i < getRows() ; i++)
345             {
346                 _piDims[0] = i;
347                 _piDims[1] = j;
348
349                 int iPos = getIndex(_piDims);
350                 InternalType* pIT = get(iPos);
351
352                 if (pIT->isAssignable())
353                 {
354                     //compute number of digits to write dimensions
355                     int iTypeLen = 0;
356                     if (pIT->isGenericType())
357                     {
358                         GenericType* pGT = pIT->getAs<GenericType>();
359                         for (int k = 0 ; k < pGT->getDims() ; k++)
360                         {
361                             iTypeLen += static_cast<int>(log10(static_cast<double>(pGT->getDimsArray()[k])) + 1);
362                         }
363                         piSizeLen[j] = std::max(piSizeLen[j], iTypeLen + (pGT->getDims() - 1));//add number of "x"
364                     }
365                     else
366                     {
367                         //types non derived from ArrayOf.
368                         int iSize = static_cast<int>(log10(static_cast<double>(pIT->getAs<GenericType>()->getRows())) + 1);
369                         piSizeLen[j] = std::max(piSizeLen[j], iSize);
370                     }
371                 }
372                 else
373                 {
374                     //no size so let a white space, size == 1
375                     piSizeLen[j] = std::max(piSizeLen[j], 1);
376                 }
377
378                 piTypeLen[j] = std::max(piTypeLen[j], static_cast<int>(pIT->getTypeStr().size()));
379             }
380         }
381
382         for (int i = 0 ; i < getRows() ; i++)
383         {
384             for (int j = 0 ; j < getCols() ; j++)
385             {
386                 _piDims[0] = i;
387                 _piDims[1] = j;
388                 int iPos = getIndex(_piDims);
389                 InternalType* pIT = get(iPos);
390
391                 ostr << L"  [";
392                 if (pIT->isAssignable())
393                 {
394                     if (pIT->isGenericType())
395                     {
396                         //"  ixjxkxl type   "
397                         GenericType* pGT = pIT->getAs<GenericType>();
398                         std::wostringstream ostemp;
399                         for (int k = 0 ; k < pGT->getDims() ; k++)
400                         {
401                             if (k != 0)
402                             {
403                                 ostemp << L"x";
404                             }
405                             ostemp << pGT->getDimsArray()[k];
406                         }
407                         configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
408                         ostr << std::right << ostemp.str();
409                     }
410                     else
411                     {
412                         //" i   "
413                         configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
414                         if (pIT->isList())
415                         {
416                             ostr << std::right << pIT->getAs<List>()->getSize();
417                         }
418                         else
419                         {
420                             ostr << std::right << 1;
421                         }
422                     }
423                 }
424                 else
425                 {
426                     configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
427                     ostr << L"";//fill with space
428                 }
429                 ostr << L" ";
430                 configureStream(&ostr, piTypeLen[j], iPrecision, ' ');
431                 ostr << std::left << pIT->getTypeStr();
432                 ostr << L"]";
433             }
434             ostr << std::endl;
435         }
436
437         delete[] piSizeLen;
438         delete[] piTypeLen;
439     }
440     ostr << std::endl << std::resetiosflags(std::ios::adjustfield);
441     return true;
442 }
443
444 bool Cell::operator==(const InternalType& it)
445 {
446     if (const_cast<InternalType &>(it).isCell() == false)
447     {
448         return false;
449     }
450
451     Cell* pC = const_cast<InternalType &>(it).getAs<Cell>();
452
453     for (int i = 0 ; i < getDims() ; i++)
454     {
455         if (pC->getDimsArray()[i] != getDimsArray()[i])
456         {
457             return false;
458         }
459     }
460
461     for (int i = 0 ; i < getSize() ; i++)
462     {
463         if (*get(i) != *pC->get(i))
464         {
465             return false;
466         }
467     }
468     return true;
469 }
470
471 bool Cell::operator!=(const InternalType& it)
472 {
473     return !(*this == it);
474 }
475
476 List* Cell::extractCell(typed_list* _pArgs)
477 {
478     InternalType* pIT = extract(_pArgs);
479     if (pIT == NULL || pIT->isCell() == false)
480     {
481         return NULL;
482     }
483
484     List* pList = new List();
485
486     Cell* pCell = pIT->getAs<Cell>();
487     for (int i = 0 ; i < pCell->getSize() ; i++)
488     {
489         pList->append(pCell->get(i));
490     }
491     pCell->killMe();
492     return pList;
493 }
494
495 Cell* Cell::insertCell(typed_list* _pArgs, InternalType* _pSource)
496 {
497     Cell* pCell = new Cell(1, 1);
498     pCell->set(0, _pSource);
499     Cell* pOut = insert(_pArgs, pCell)->getAs<Cell>();
500     pCell->killMe();
501     return pOut;
502 }
503
504 Cell* Cell::insertNewCell(typed_list* _pArgs, InternalType* _pSource)
505 {
506     Cell* pCell = new Cell(1, 1);
507     pCell->set(0, _pSource);
508     Cell* pOut = pCell->insertNew(_pArgs)->getAs<Cell>();
509     return pOut;
510 }
511
512 InternalType** Cell::allocData(int _iSize)
513 {
514     InternalType** pData = new InternalType*[_iSize];
515     for (int i = 0 ; i < _iSize ; i++)
516     {
517         pData[i] = NULL;
518     }
519     return pData;
520 }
521
522 void Cell::deleteData(InternalType* _pData)
523 {
524     if (_pData)
525     {
526         _pData->killMe();
527     }
528 }
529
530 Cell* Cell::createEmpty()
531 {
532     return new Cell();
533 }
534 }