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