* Bug 16200 fixed: concatenation of transposed cells crashed Scilab
[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         for (int i = 0, k = 0; i < getCols(); i++, k += getRows())
159         {
160             for (int j = 0, l = 0; j < getRows(); j++, l += getCols())
161             {
162                 pC->m_pRealData[i + l] = m_pRealData[j + k]->clone();
163                 pC->m_pRealData[i + l]->IncreaseRef();
164             }
165         }
166      
167         return true;
168     }
169
170     return false;
171 }
172
173 Cell* Cell::set(int _iRows, int _iCols, InternalType* _pIT)
174 {
175     if (_iRows < getRows() && _iCols < getCols())
176     {
177         return set(_iCols * getRows() + _iRows, _pIT);
178     }
179     return NULL;
180 }
181
182 Cell* Cell::set(int _iRows, int _iCols, const InternalType* _pIT)
183 {
184     if (_iRows < getRows() && _iCols < getCols())
185     {
186         return set(_iCols * getRows() + _iRows, _pIT);
187     }
188     return NULL;
189 }
190
191 Cell* Cell::set(int _iIndex, InternalType* _pIT)
192 {
193     if (_iIndex >= m_iSize)
194     {
195         return NULL;
196     }
197
198     // corner case when inserting twice
199     if (m_pRealData[_iIndex] == _pIT)
200     {
201         return this;
202     }
203
204     typedef Cell* (Cell::*set_t)(int, InternalType*);
205     Cell* pIT = checkRef(this, (set_t)&Cell::set, _iIndex, _pIT);
206     if (pIT != this)
207     {
208         return pIT;
209     }
210
211     if (m_pRealData[_iIndex] != NULL)
212     {
213         m_pRealData[_iIndex]->DecreaseRef();
214         m_pRealData[_iIndex]->killMe();
215     }
216
217     _pIT->IncreaseRef();
218     m_pRealData[_iIndex] = _pIT;
219     return this;
220 }
221
222 Cell* Cell::set(int _iIndex, const InternalType* _pIT)
223 {
224     if (_iIndex >= m_iSize)
225     {
226         return NULL;
227     }
228
229     typedef Cell* (Cell::*set_t)(int, const InternalType*);
230     Cell* pIT = checkRef(this, (set_t)&Cell::set, _iIndex, _pIT);
231     if (pIT != this)
232     {
233         return pIT;
234     }
235
236     if (m_pRealData[_iIndex] != NULL)
237     {
238         m_pRealData[_iIndex]->DecreaseRef();
239         m_pRealData[_iIndex]->killMe();
240     }
241
242     const_cast<InternalType*>(_pIT)->IncreaseRef();
243     m_pRealData[_iIndex] = const_cast<InternalType*>(_pIT);
244
245     return this;
246 }
247
248 Cell* Cell::set(InternalType** _pIT)
249 {
250     typedef Cell* (Cell::*set_t)(InternalType**);
251     Cell* pIT = checkRef(this, (set_t)&Cell::set, _pIT);
252     if (pIT != this)
253     {
254         return pIT;
255     }
256
257     for (int i = 0; i < m_iSize; i++)
258     {
259         if (i >= m_iSize)
260         {
261             return NULL;
262         }
263
264         if (m_pRealData[i] != NULL)
265         {
266             m_pRealData[i]->DecreaseRef();
267             m_pRealData[i]->killMe();
268         }
269
270         _pIT[i]->IncreaseRef();
271         m_pRealData[i] = _pIT[i];
272     }
273
274     return this;
275 }
276
277 /**
278 ** Clone
279 ** Create a new Struct and Copy all values.
280 */
281 Cell* Cell::clone()
282 {
283     return new Cell(this);
284 }
285
286 InternalType* Cell::getNullValue()
287 {
288     return Double::Empty();
289 }
290
291 Cell* Cell::createEmpty(int _iDims, int* _piDims, bool /*_bComplex*/)
292 {
293     return new Cell(_iDims, _piDims);
294 }
295
296 InternalType* Cell::copyValue(InternalType* _pData)
297 {
298     _pData->IncreaseRef();
299     return _pData;
300 }
301
302 void Cell::deleteAll()
303 {
304     for (int i = 0 ; i < getSize() ; i++)
305     {
306         m_pRealData[i]->DecreaseRef();
307         m_pRealData[i]->killMe();
308     }
309
310     delete[] m_pRealData;
311     m_pRealData = NULL;
312 }
313
314 void Cell::deleteImg()
315 {
316     return;
317 }
318
319 bool Cell::isEmpty()
320 {
321     if (getDims() == 2 && getRows() == 0 && getCols() == 0)
322     {
323         return true;
324     }
325     return false;
326 }
327
328 /**
329 ** toString to display Structs
330 ** FIXME : Find a better indentation process
331 */
332 bool Cell::subMatrixToString(std::wostringstream& ostr, int* _piDims, int /*_iDims*/)
333 {
334     int iPrecision = ConfigVariable::getFormatSize();
335
336     if (isEmpty())
337     {
338         ostr << L"   {}";
339     }
340     else
341     {
342         //max len for each column
343         int *piTypeLen = new int[getCols()];
344         int *piSizeLen = new int[getCols()];
345
346         memset(piTypeLen, 0x00, getCols() * sizeof(int));
347         memset(piSizeLen, 0x00, getCols() * sizeof(int));
348
349         for (int j = 0 ; j < getCols() ; j++)
350         {
351             for (int i = 0 ; i < getRows() ; i++)
352             {
353                 _piDims[0] = i;
354                 _piDims[1] = j;
355
356                 int iPos = getIndex(_piDims);
357                 InternalType* pIT = get(iPos);
358
359                 if (pIT->isAssignable())
360                 {
361                     //compute number of digits to write dimensions
362                     int iTypeLen = 0;
363                     if (pIT->isGenericType())
364                     {
365                         GenericType* pGT = pIT->getAs<GenericType>();
366                         for (int k = 0 ; k < pGT->getDims() ; k++)
367                         {
368                             iTypeLen += static_cast<int>(log10(static_cast<double>(pGT->getDimsArray()[k])) + 1);
369                         }
370                         piSizeLen[j] = std::max(piSizeLen[j], iTypeLen + (pGT->getDims() - 1));//add number of "x"
371                     }
372                     else
373                     {
374                         //types non derived from ArrayOf.
375                         int iSize = static_cast<int>(log10(static_cast<double>(pIT->getAs<GenericType>()->getRows())) + 1);
376                         piSizeLen[j] = std::max(piSizeLen[j], iSize);
377                     }
378                 }
379                 else
380                 {
381                     //no size so let a white space, size == 1
382                     piSizeLen[j] = std::max(piSizeLen[j], 1);
383                 }
384
385                 piTypeLen[j] = std::max(piTypeLen[j], static_cast<int>(pIT->getTypeStr().size()));
386             }
387         }
388
389         for (int i = 0 ; i < getRows() ; i++)
390         {
391             for (int j = 0 ; j < getCols() ; j++)
392             {
393                 _piDims[0] = i;
394                 _piDims[1] = j;
395                 int iPos = getIndex(_piDims);
396                 InternalType* pIT = get(iPos);
397
398                 ostr << L"  [";
399                 if (pIT->isAssignable())
400                 {
401                     if (pIT->isGenericType())
402                     {
403                         //"  ixjxkxl type   "
404                         GenericType* pGT = pIT->getAs<GenericType>();
405                         std::wostringstream ostemp;
406                         for (int k = 0 ; k < pGT->getDims() ; k++)
407                         {
408                             if (k != 0)
409                             {
410                                 ostemp << L"x";
411                             }
412                             ostemp << pGT->getDimsArray()[k];
413                         }
414                         configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
415                         ostr << std::right << ostemp.str();
416                     }
417                     else
418                     {
419                         //" i   "
420                         configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
421                         if (pIT->isList())
422                         {
423                             ostr << std::right << pIT->getAs<List>()->getSize();
424                         }
425                         else
426                         {
427                             ostr << std::right << 1;
428                         }
429                     }
430                 }
431                 else
432                 {
433                     configureStream(&ostr, piSizeLen[j], iPrecision, ' ');
434                     ostr << L"";//fill with space
435                 }
436                 ostr << L" ";
437                 configureStream(&ostr, piTypeLen[j], iPrecision, ' ');
438                 ostr << std::left << pIT->getTypeStr();
439                 ostr << L"]";
440             }
441             ostr << std::endl;
442         }
443
444         delete[] piSizeLen;
445         delete[] piTypeLen;
446     }
447     ostr << std::endl << std::resetiosflags(std::ios::adjustfield);
448     return true;
449 }
450
451 bool Cell::operator==(const InternalType& it)
452 {
453     if (const_cast<InternalType &>(it).isCell() == false)
454     {
455         return false;
456     }
457
458     Cell* pC = const_cast<InternalType &>(it).getAs<Cell>();
459
460     for (int i = 0 ; i < getDims() ; i++)
461     {
462         if (pC->getDimsArray()[i] != getDimsArray()[i])
463         {
464             return false;
465         }
466     }
467
468     for (int i = 0 ; i < getSize() ; i++)
469     {
470         if (*get(i) != *pC->get(i))
471         {
472             return false;
473         }
474     }
475     return true;
476 }
477
478 bool Cell::operator!=(const InternalType& it)
479 {
480     return !(*this == it);
481 }
482
483 List* Cell::extractCell(typed_list* _pArgs)
484 {
485     InternalType* pIT = extract(_pArgs);
486     if (pIT == NULL || pIT->isCell() == false)
487     {
488         return NULL;
489     }
490
491     List* pList = new List();
492
493     Cell* pCell = pIT->getAs<Cell>();
494     for (int i = 0 ; i < pCell->getSize() ; i++)
495     {
496         pList->append(pCell->get(i));
497     }
498     pCell->killMe();
499     return pList;
500 }
501
502 Cell* Cell::insertCell(typed_list* _pArgs, InternalType* _pSource)
503 {
504     Cell* pCell = new Cell(1, 1);
505     pCell->set(0, _pSource);
506     Cell* pOut = insert(_pArgs, pCell)->getAs<Cell>();
507     pCell->killMe();
508     return pOut;
509 }
510
511 Cell* Cell::insertNewCell(typed_list* _pArgs, InternalType* _pSource)
512 {
513     Cell* pCell = new Cell(1, 1);
514     pCell->set(0, _pSource);
515     Cell* pOut = pCell->insertNew(_pArgs)->getAs<Cell>();
516     return pOut;
517 }
518
519 InternalType** Cell::allocData(int _iSize)
520 {
521     InternalType** pData = new InternalType*[_iSize];
522     for (int i = 0 ; i < _iSize ; i++)
523     {
524         pData[i] = NULL;
525     }
526     return pData;
527 }
528
529 void Cell::deleteData(InternalType* _pData)
530 {
531     if (_pData)
532     {
533         _pData->killMe();
534     }
535 }
536
537 Cell* Cell::createEmpty()
538 {
539     return new Cell();
540 }
541 }