1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010 - DIGITEO - Antoine ELIAS
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15 
16 #include "arrayof.hxx"
17 #include "double.hxx"
18 #include "bool.hxx"
19 #include "singlepoly.hxx"
20 #include "singlestruct.hxx"
21 #include "type_traits.hxx"
22 #include "exp.hxx"
23 #include "types_tools.hxx"
24 #include "scilabexception.hxx"
25 
26 extern "C"
27 {
28 #include "dynlib_ast.h"
29 #include "sciprint.h"
30 }
31 
32 namespace types
33 {
34 
get_max_size(int * _piDims,int _iDims)35 static int get_max_size(int* _piDims, int _iDims)
36 {
37     if (_iDims == 0)
38     {
39         return 0;
40     }
41 
42     int iMax = 1;
43     for (int i = 0 ; i < _iDims ; i++)
44     {
45         iMax *= _piDims[i];
46     }
47     return iMax;
48 }
49 
50 template <typename T>
createEmpty()51 GenericType* ArrayOf<T>::createEmpty()
52 {
53     return createEmptyDouble();
54 }
55 
56 template <typename T>
getMemory(long long * _piSize,long long * _piSizePlusType)57 bool ArrayOf<T>::getMemory(long long* _piSize, long long* _piSizePlusType)
58 {
59     *_piSize = getSize() * sizeof(T) * (isComplex() ? 2 : 1);
60     *_piSizePlusType = *_piSize + sizeof(*this);
61     return true;
62 }
63 
64 template <typename T>
humanReadableByteCount(size_t n,char (& str)[9])65 void ArrayOf<T>::humanReadableByteCount(size_t n, char (&str)[9])
66 {
67     double unit = 1024.;
68     if (n < unit)
69     {
70         std::snprintf(str, 9, "%lu B", n);
71         return;
72     }
73 
74     int exp = (int) std::log(n) / std::log(unit);
75     char preUnit[] = "kMGTPE";
76     char pre = preUnit[exp - 1];
77 
78     std::snprintf(str, 9, "%.1f %cB", n / std::pow(unit, exp), pre);
79 }
80 
81 template <typename T>
getIndexes(int _iIndex,int * _piIndexes)82 void ArrayOf<T>::getIndexes(int _iIndex, int* _piIndexes)
83 {
84     getIndexesWithDims(_iIndex, _piIndexes, m_piDims, m_iDims);
85 }
86 
87 template <typename T>
insert(typed_list * _pArgs,InternalType * _pSource)88 ArrayOf<T>* ArrayOf<T>::insert(typed_list* _pArgs, InternalType* _pSource)
89 {
90     ArrayOf<T>* pIT = checkRef(this, &ArrayOf::insert, _pArgs, _pSource);
91     if (pIT != this)
92     {
93         return pIT;
94     }
95 
96     int index;
97     if (getScalarIndex(this, _pArgs, &index))
98     {
99         ArrayOf* pIns = _pSource->getAs<ArrayOf>();
100         int sizeIn = pIns->getSize();
101         //only scalar can be used to ".=" operation
102         if (sizeIn != 1)
103         {
104             return NULL;
105         }
106 
107         T* pRealData = pIns->get();
108         T* pImgData = pIns->getImg();
109 
110         if (isComplex() == false && pIns->isComplex() == false)
111         {
112             if (isNativeType() && index < m_iSize)
113             {
114                 m_pRealData[index] = *pRealData;
115                 return this;
116             }
117             else
118             {
119                 if (set(index, *pRealData) != NULL)
120                 {
121                     return this;
122                 }
123             }
124         }
125 
126         //if complex continue
127     }
128 
129     typed_list pArg;
130     int iDims = (int)_pArgs->size();
131     int* piMaxDim = new int[iDims];
132     int* piCountDim = new int[iDims];
133     //evaluate each argument and replace by appropriate value and compute the count of combinations
134     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
135 
136     if (iSeqCount == 0)
137     {
138         //free pArg content
139         delete[] piCountDim;
140         delete[] piMaxDim;
141         cleanIndexesArguments(_pArgs, &pArg);
142         return this;
143     }
144 
145     ArrayOf* pSource = _pSource->getAs<ArrayOf>();
146 
147     //only scalar can be used to ".=" operation
148     if (iSeqCount != pSource->getSize() && pSource->isScalar() == false)
149     {
150         delete[] piCountDim;
151         delete[] piMaxDim;
152         //free pArg content
153         cleanIndexesArguments(_pArgs, &pArg);
154         return NULL;
155     }
156 
157     //remove last dimension at size 1
158     //remove last dimension if are == 1
159     for (int i = (iDims - 1); i >= m_iDims; i--)
160     {
161         if (piMaxDim[i] == 1)
162         {
163             iDims--;
164             pArg.back()->killMe();
165             pArg.pop_back();
166         }
167         else
168         {
169             break;
170         }
171     }
172 
173 
174     //insertion of a scalar is always possible regardless of index dimensions
175     if (pSource->isScalar() == false)
176     {
177         int *piSourceDims = pSource->getDimsArray();
178         int sDims = pSource->getDims();
179         int j = 0;
180 
181         for (int i = 0; i < iDims; i++)
182         {
183             if (piCountDim[i] == 1)
184             {
185                 continue;
186             }
187             while (j < sDims && piSourceDims[j] == 1)
188             {
189                 j++;
190             }
191             if (piSourceDims[j] != piCountDim[i])
192             {
193                 delete[] piCountDim;
194                 delete[] piMaxDim;
195                 //free pArg content
196                 cleanIndexesArguments(_pArgs, &pArg);
197                 return NULL;
198             }
199             j++;
200         }
201     }
202 
203     std::vector<int> indexes;
204     std::vector<int> dims;
205     if (getImplicitIndex(this, _pArgs, indexes, dims))
206     {
207         if (indexes.size() == 0)
208         {
209             delete[] piCountDim;
210             delete[] piMaxDim;
211             //free pArg content
212             cleanIndexesArguments(_pArgs, &pArg);
213             return this;
214         }
215 
216         ArrayOf* pIns = _pSource->getAs<ArrayOf>();
217         int sizeIn = pIns->getSize();
218         int count = static_cast<int>(indexes.size());
219         //only scalar can be used to ".=" operation
220         if (sizeIn != 1 && count != sizeIn)
221         {
222             delete[] piCountDim;
223             delete[] piMaxDim;
224             //free pArg content
225             cleanIndexesArguments(_pArgs, &pArg);
226             return NULL;
227         }
228 
229         T* pRealData = pIns->get();
230         T* pImgData = pIns->getImg();
231 
232         bool status = true;
233         if (isComplex() == false && pIns->isComplex() == false)
234         {
235             if (sizeIn == 1)
236             {
237                 if (isNativeType())
238                 {
239                     for (int i : indexes)
240                     {
241                         if (i >= m_iSize)
242                         {
243                             status = false;
244                             break;
245                         }
246 
247                         m_pRealData[i] = *pRealData;
248                     }
249                 }
250                 else
251                 {
252                     for (int i : indexes)
253                     {
254                         if (set(i, *pRealData) == NULL)
255                         {
256                             status = false;
257                             break;
258                         }
259                     }
260                 }
261             }
262             else
263             {
264                 if (isNativeType())
265                 {
266                     for (int i : indexes)
267                     {
268                         if (i >= m_iSize)
269                         {
270                             status = false;
271                             break;
272                         }
273 
274                         m_pRealData[i] = *pRealData;
275                         ++pRealData;
276                     }
277                 }
278                 else
279                 {
280                     for (int i : indexes)
281                     {
282                         if (set(i, *pRealData) == NULL)
283                         {
284                             status = false;
285                             break;
286                         }
287                         ++pRealData;
288                     }
289                 }
290             }
291 
292             if (status)
293             {
294                 delete[] piCountDim;
295                 delete[] piMaxDim;
296                 //free pArg content
297                 cleanIndexesArguments(_pArgs, &pArg);
298                 return this;
299             }
300 
301             //if status is false, continue to entire process
302         }
303     }
304 
305     bool bNeedToResize = false;
306     int iDimsOrigine = m_iDims;
307 
308     //on case of resize
309     int* piNewDims = NULL;
310     int iNewDims = 0;
311 
312     bool bIsColon = false;
313 
314     if (iDims >= m_iDims)
315     {
316         //all case are good, we can do almost everything
317         //check if resize is needed
318         if (iDims > m_iDims)
319         {
320             bNeedToResize = true;
321         }
322         else //_iDims == m_iDims
323         {
324             for (int i = 0; i < m_iDims; i++)
325             {
326                 if (m_piDims[i] < piMaxDim[i])
327                 {
328                     bNeedToResize = true;
329                     break;
330                 }
331             }
332         }
333 
334         //determine new dimension of the matrix
335         if (bNeedToResize == true)
336         {
337             iNewDims = iDims;
338             piNewDims = new int[iNewDims];
339             for (int i = 0; i < m_iDims; i++)
340             {
341                 piNewDims[i] = std::max(piMaxDim[i], m_piDims[i]);
342             }
343 
344             int iSource = (pSource->getDims() - 1);
345             bool bPassed = false;
346             int *piSourceDims = pSource->getDimsArray();
347 
348             for (int i = m_iDims; i < iNewDims; ++i)
349             {
350                 piNewDims[i] = piMaxDim[i];
351             }
352         }
353     }
354     else // _iDims < m_iDims
355     {
356         if (isVector() || isScalar() || getSize() == 0) //getSize() == 0, only for [] and {}
357         {
358             if (getSize() < piMaxDim[0])
359             {
360                 bNeedToResize = true;
361                 iNewDims = 2;
362                 piNewDims = new int[2] {1, 1};
363 
364                 if (isScalar() || getSize() == 0)
365                 {
366                     int *piSourceDims = pSource->getDimsArray();
367                     // if source is scalar then resize indexed array as a column vector
368                     // otherwise resize with shape of source
369                     piNewDims[(int)(piSourceDims[0] == 1 && pSource->getSize() > 1)] = piMaxDim[0];
370                 }
371                 else // resize with same shape as indexed array
372                 {
373                     piNewDims[(int)(getRows() == 1)] = piMaxDim[0];
374                 }
375             }
376         }
377         else
378         {
379             //each index before last index must be in range of his dimension
380             //and last given dimension can not be > prod(last dimensions)
381             for (int i = 0; i < iDims - 1; i++)
382             {
383                 //indexes are always doubles
384                 double* pIdx = getDoubleArrayFromDouble(pArg[i]);
385                 //InternalType* pVar = pArg[i];
386                 //double* pIdx = static_cast<double*>(pVar->getAs<Double>()->get());
387                 int iSize = pArg[i]->getAs<ArrayOf>()->getSize();
388                 for (int j = 0; j < iSize; j++)
389                 {
390                     if (pIdx[j] > m_piDims[i])
391                     {
392                         delete[] piCountDim;
393                         delete[] piMaxDim;
394                         //free pArg content
395                         cleanIndexesArguments(_pArgs, &pArg);
396                         return NULL;
397                     }
398                 }
399             }
400 
401             //check last dim
402             int iMaxLastDim = getVarMaxDim(iDims - 1, iDims);
403             double* pIdx = getDoubleArrayFromDouble(pArg[pArg.size() - 1]);
404             //InternalType* pVar = pArg[pArg.size() - 1];
405             //double* pIdx = static_cast<double*>(pVar->getAs<Double>()->get());
406             int iSize = pArg[pArg.size() - 1]->getAs<GenericType>()->getSize();
407             for (int i = 0; i < iSize; i++)
408             {
409                 if (pIdx[i] > iMaxLastDim)
410                 {
411                     delete[] piCountDim;
412                     delete[] piMaxDim;
413                     //free pArg content
414                     cleanIndexesArguments(_pArgs, &pArg);
415                     return NULL;
416                 }
417             }
418         }
419     }
420 
421     //update complexity *before* first resizing
422     if (pSource->isComplex() && m_pImgData == NULL)
423     {
424         setComplex(true);
425     }
426 
427     //before resize, check input dimension
428     if (bNeedToResize)
429     {
430         ArrayOf<T>* pTemp = resize(piNewDims, iNewDims);
431         if (pTemp == NULL)
432         {
433             delete[] piCountDim;
434             delete[] piMaxDim;
435             //free pArg content
436             cleanIndexesArguments(_pArgs, &pArg);
437             return NULL;
438         }
439     }
440     else
441     {
442         piNewDims = m_piDims;
443         iNewDims = m_iDims;
444     }
445 
446     int argSize = static_cast<int>(pArg.size());
447     int* piIndex = new int[argSize];
448     int* piCoord = new int[argSize];
449     int* piViewDims = new int[iDims];
450     memset(piIndex, 0x00, sizeof(int) * argSize);
451 
452     //convert  current dimension to view dimension
453     for (int i = 0; i < iDims; i++)
454     {
455         piViewDims[i] = getVarMaxDim(i, iDims);
456     }
457 
458     T* pRealData = pSource->get();
459     T* pImgData = pSource->getImg();
460     bool bComplex = pSource->isComplex();
461 
462     for (int i = 0; i < iSeqCount; i++)
463     {
464         computeTuples(piCountDim, argSize, argSize - 1, piIndex);
465 
466         //std::cout << "[";
467         for (int j = 0; j < argSize; j++)
468         {
469             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
470             //InternalType* pVar = pArg[j];
471             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
472             //std::cout << piCoord[j] << " ";
473         }
474 
475         //std::cout << "]" << std::endl;
476 
477         int iPos = getIndexWithDims(piCoord, piViewDims, iDims);
478         if (iPos < 0)
479         {
480             if (bNeedToResize)
481             {
482                 delete[] piNewDims;
483             }
484 
485             delete[] piMaxDim;
486             delete[] piCountDim;
487             delete[] piIndex;
488             delete[] piCoord;
489             delete[] piViewDims;
490 
491             //free pArg content
492             cleanIndexesArguments(_pArgs, &pArg);
493 
494             wchar_t szError[bsiz];
495             os_swprintf(szError, bsiz, _W("Invalid index.\n").c_str());
496             throw ast::InternalError(szError);
497         }
498 
499         if (pSource->isScalar())
500         {
501             //element-wise insertion
502             set(iPos, pRealData[0]);
503             if (pImgData != NULL && bComplex)
504             {
505                 setImg(iPos, pImgData[0]);
506             }
507         }
508         else
509         {
510             if (bIsColon)
511             {
512                 int iPas = 1;
513                 for (int j = 0; j < iDimsOrigine; j++)
514                 {
515                     iPas = iPas * m_piDims[j];
516                 }
517 
518                 for (int iPost = iPos; iPost < this->getSize(); iPost += iPas)
519                 {
520                     set(iPost, pRealData[i]);
521                     if (pImgData != NULL && bComplex)
522                     {
523                         setImg(iPost, pImgData[i]);
524                     }
525                     i++;
526                 }
527             }
528             else
529             {
530                 set(iPos, pRealData[i]);
531                 if (pImgData != NULL && bComplex)
532                 {
533                     setImg(iPos, pImgData[i]);
534                 }
535             }
536         }
537 
538         // reset imaginary part
539         if (m_pImgData != NULL && bComplex == false)
540         {
541             setImg(iPos, 0);
542         }
543 
544         //update index
545         piIndex[0]++;
546     }
547 
548     if (bNeedToResize)
549     {
550         delete[] piNewDims;
551     }
552 
553     delete[] piMaxDim;
554     delete[] piCountDim;
555     delete[] piIndex;
556     delete[] piCoord;
557     delete[] piViewDims;
558 
559     //free pArg content
560     cleanIndexesArguments(_pArgs, &pArg);
561 
562     return this;
563 }
564 
565 template <typename T>
insertNew(typed_list * _pArgs)566 GenericType* ArrayOf<T>::insertNew(typed_list* _pArgs)
567 {
568     bool bComplex = getImg() != NULL;
569     std::vector<int> dims;
570     if (getArgsDims(_pArgs, dims))
571     {
572         InternalType *pOut = NULL;
573 
574         if (dims.size() == 1 && getDims() == 2)
575         {
576             if (getCols() != 1)
577             {
578                 dims.insert(dims.begin(), 1);
579             }
580             else
581             {
582                 dims.push_back(1);
583             }
584         }
585 
586         while (dims.size() < 2)
587         {
588             dims.push_back(1);
589         }
590 
591         pOut = createEmpty((int)dims.size(), dims.data(), bComplex);
592         ArrayOf* pArrayOut = pOut->getAs<ArrayOf>();
593         pArrayOut->fillDefaultValues();
594         ArrayOf* pOut2 = NULL;
595 
596         try
597         {
598             pOut2 = pArrayOut->insert(_pArgs, this);
599         }
600         catch (const ast::InternalError& error)
601         {
602             pOut->killMe();
603             throw error;
604         }
605 
606         if (pOut != pOut2)
607         {
608             delete pOut;
609         }
610 
611         return pOut2;
612     }
613 
614     typed_list pArg;
615     InternalType *pOut = NULL;
616 
617     int iDims = (int)_pArgs->size();
618     int* piMaxDim = new int[iDims];
619     int* piCountDim = new int[iDims];
620 
621     //evaluate each argument and replace by appropriate value and compute the count of combinations
622     int iSeqCount = checkIndexesArguments(NULL, _pArgs, &pArg, piMaxDim, piCountDim);
623 
624     if (iSeqCount == 0)
625     {
626         delete[] piMaxDim;
627         delete[] piCountDim;
628         //free pArg content
629         cleanIndexesArguments(_pArgs, &pArg);
630         return createEmptyDouble();
631     }
632 
633     if (iSeqCount < 0)
634     {
635         //manage : and $ in creation by insertion
636         int iSourceDims = getDims();
637         int iSource = 0;
638         int iNbColon = 0;
639 
640         for (int i = 0; i < iDims; ++i)
641         {
642             if (pArg[i] == NULL)
643             {
644                 ++iNbColon;
645             }
646         }
647 
648         if (iNbColon == iDims)
649         {
650             delete[] piMaxDim;
651             delete[] piCountDim;
652             //free pArg content
653             cleanIndexesArguments(_pArgs, &pArg);
654             return this;
655         }
656 
657         int *piSourceDims = new int[iSourceDims];
658         memcpy(piSourceDims, getDimsArray(), iSourceDims * sizeof(int));
659 
660         if (iNbColon == 1 && isVector())
661         {
662             iSourceDims = 1;
663             piSourceDims[0] = getSize();
664         }
665 
666         //vector or matrix case
667         for (int i = 0; i < iDims; ++i)
668         {
669             //if these do not match another following explicit index, replace ":" by known source dimensions
670             if (pArg[i] == NULL)
671             {
672                 if (iSource < iSourceDims)
673                 {
674                     //by default, replace colon by current source dimension
675                     piMaxDim[i] = piSourceDims[iSource];
676                     //if there are more index dimensions left than source dimensions left
677                     if (iDims - i > iSourceDims - iSource)
678                     {
679                         for (int j = i + 1; j < iDims - iSourceDims + iSource + 1; ++j)
680                         {
681                             //when first explicit index is reached
682                             if (pArg[j] != NULL)
683                             {
684                                 //if future index #j and current source dimensions match
685                                 if (piCountDim[j] == piSourceDims[iSource])
686                                 {
687                                     piMaxDim[i] = 1;
688                                     --iSource;
689                                 }
690                                 break;
691                             }
692                         }
693                     }
694                     ++iSource;
695                 }
696                 else
697                 {
698                     //fill dimensions after iSourceDims with 1
699                     piMaxDim[i] = 1;
700                 }
701                 pArg[i] = createDoubleVector(piMaxDim[i]);
702                 --iNbColon;
703             }
704             else if (iSource < iSourceDims &&
705                      piCountDim[i] == piSourceDims[iSource] &&
706                      (piCountDim[i] > 1 || iNbColon < iSourceDims))
707             {
708                 ++iSource;
709             }
710         }
711         delete[] piSourceDims;
712     }
713 
714     //remove last dimension at size 1
715     //remove last dimension if are == 1
716     for (int i = (iDims - 1); i >= 2; i--)
717     {
718         if (piMaxDim[i] == 1)
719         {
720             iDims--;
721             pArg.back()->killMe();
722             pArg.pop_back();
723         }
724         else
725         {
726             break;
727         }
728     }
729 
730     if (checkArgValidity(pArg) == false)
731     {
732         delete[] piMaxDim;
733         delete[] piCountDim;
734         //free pArg content
735         cleanIndexesArguments(_pArgs, &pArg);
736         //contain bad index, like <= 0, ...
737         return NULL;
738     }
739 
740     if (iDims == 1)
741     {
742         if (getCols() == 1)
743         {
744             int piRealDim[2] = {piMaxDim[0], 1};
745             pOut = createEmpty(2, piRealDim, bComplex);
746         }
747         else
748         {
749             //rows == 1
750             int piRealDim[2] = {1, piMaxDim[0]};
751             pOut = createEmpty(2, piRealDim, bComplex);
752         }
753     }
754     else
755     {
756         pOut = createEmpty(iDims, piMaxDim, bComplex);
757     }
758 
759 
760     //fill with null item
761     ArrayOf* pArrayOut = pOut->getAs<ArrayOf>();
762     pArrayOut->fillDefaultValues();
763     //T* pRealData = pArrayOut->get();
764     //if (bComplex)
765     //{
766     //    int size = pArrayOut->getSize();
767     //    T* pImgData = pArrayOut->getImg();
768 
769     //    if (isNativeType())
770     //    {
771     //        T val = getNullValue();
772     //        for (int i = 0; i < size; i++)
773     //        {
774     //            pRealData[i] = val;
775     //            pImgData[i] = val;
776     //        }
777     //    }
778     //    else
779     //    {
780     //        for (int i = 0; i < size; i++)
781     //        {
782     //            pArrayOut->deleteData(pRealData[i]);
783     //            pRealData[i] = getNullValue();
784     //            pArrayOut->deleteData(pImgData[i]);
785     //            pImgData[i] = getNullValue();
786     //        }
787     //    }
788     //}
789     //else
790     //{
791     //    int size = pArrayOut->getSize();
792     //    if (isNativeType())
793     //    {
794     //        T val = getNullValue();
795     //        for (int i = 0; i < size; i++)
796     //        {
797     //            pRealData[i] = val;
798     //        }
799     //    }
800     //    else
801     //    {
802     //        for (int i = 0; i < size; i++)
803     //        {
804     //            pArrayOut->deleteData(pRealData[i]);
805     //            pRealData[i] = getNullValue();
806     //        }
807     //    }
808     //}
809 
810     //insert values in new matrix
811     ArrayOf* pOut2 = pArrayOut->insert(&pArg, this);
812     if (pOut != pOut2)
813     {
814         delete pOut;
815     }
816 
817     delete[] piMaxDim;
818     delete[] piCountDim;
819     //free pArg content
820     cleanIndexesArguments(_pArgs, &pArg);
821 
822     return pOut2;
823 }
824 
825 template <typename T>
append(int _iRows,int _iCols,InternalType * _poSource)826 ArrayOf<T>* ArrayOf<T>::append(int _iRows, int _iCols, InternalType* _poSource)
827 {
828     ArrayOf<T>* pIT = checkRef(this, &ArrayOf::append, _iRows, _iCols, _poSource);
829     if (pIT != this)
830     {
831         return pIT;
832     }
833 
834     _poSource->IncreaseRef();
835     ArrayOf * pGT = _poSource->getAs<ArrayOf>();
836     int iRows = pGT->getRows();
837     int iCols = pGT->getCols();
838 
839     //insert without resize
840     if (iRows + _iRows > m_iRows || iCols + _iCols > m_iCols)
841     {
842         return NULL;
843     }
844 
845     //Update complexity if necessary
846     if (pGT->isComplex())
847     {
848         setComplex(true);
849     }
850     else if (isComplex())
851     {
852         pGT = pGT->setComplex(true);
853     }
854 
855     if (pGT->isComplex())
856     {
857         for (int i = 0; i < iRows; i++)
858         {
859             for (int j = 0; j < iCols; j++)
860             {
861                 set(_iRows + i, _iCols + j, pGT->get(i, j));
862                 setImg(_iRows + i, _iCols + j, pGT->getImg(i, j));
863             }
864         }
865     }
866     else
867     {
868         for (int i = 0; i < iRows; i++)
869         {
870             for (int j = 0; j < iCols; j++)
871             {
872                 set(_iRows + i, _iCols + j, pGT->get(i, j));
873             }
874         }
875     }
876 
877     pGT->killMe();
878     _poSource->DecreaseRef();
879 
880     return this;
881 }
882 
883 template <typename T>
remove(typed_list * _pArgs)884 GenericType* ArrayOf<T>::remove(typed_list* _pArgs)
885 {
886     ArrayOf<T>* pOut = NULL;
887     int iDims = (int)_pArgs->size();
888     typed_list pArg;
889 
890     int* piMaxDim = new int[iDims];
891     int* piCountDim = new int[iDims];
892 
893     //evaluate each argument and replace by appropriate value and compute the count of combinations
894     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
895     delete[] piMaxDim;
896     delete[] piCountDim;
897     if (iSeqCount == 0)
898     {
899         //free pArg content
900         cleanIndexesArguments(_pArgs, &pArg);
901         //no Seq, no change but no error.
902         return this;
903     }
904 
905     int iToDelIndex = -1;
906     std::vector<int> toDelIndexVect;
907 
908     // dimensions not subject to deletion must be indexed with colon or equivalent
909     for (int i = 0; i < iDims; i++)
910     {
911         int iDimToCheck = getVarMaxDim(i, iDims);
912         int iIndexSize = pArg[i]->getAs<GenericType>()->getSize();
913         if ((*_pArgs)[i]->isColon() == false)
914         {
915             //if equivalent to colon, should be 1:iDimToCheck after sorting and removing duplicates
916             double* pIndexes = getDoubleArrayFromDouble(pArg[i]);
917             std::vector<int> pIndexesVect(pIndexes, pIndexes + iIndexSize);
918             std::sort(pIndexesVect.begin(), pIndexesVect.end());
919             pIndexesVect.erase(unique(pIndexesVect.begin(), pIndexesVect.end()), pIndexesVect.end());
920             //remove index > iDimToCheck to allow a[10, 10](1, 1:100) = [] and a[10, 10]([1 5 20], :) = []
921             auto lastUnique = std::find_if(pIndexesVect.begin(), pIndexesVect.end(),
922                                            [&iDimToCheck](int idx)
923             {
924                 return idx > iDimToCheck;
925             });
926             pIndexesVect.erase(lastUnique, pIndexesVect.end());
927 
928             if (pIndexesVect.size() != iDimToCheck)
929             {
930                 // index is not equivalent to colon -> index to delete
931                 if (iToDelIndex < 0)
932                 {
933                     iToDelIndex = i;
934                     toDelIndexVect = pIndexesVect;
935                 }
936                 else
937                 {
938                     //cannot delete indexes on more than one dimension
939                     //free pArg content
940                     cleanIndexesArguments(_pArgs, &pArg);
941                     return NULL;
942                 }
943             }
944         }
945     }
946 
947     if (iToDelIndex < 0)
948     {
949         // overall removal x(:,...,:) = []
950         cleanIndexesArguments(_pArgs, &pArg);
951         return createEmpty();
952     }
953 
954     if (toDelIndexVect.size() == 0)
955     {
956         // no removal because of too large indexes
957         cleanIndexesArguments(_pArgs, &pArg);
958         return this;
959     }
960 
961     int iNewDimSize = getVarMaxDim(iToDelIndex, iDims) - toDelIndexVect.size();
962 
963     int* piNewDims = new int[iDims];
964     for (int i = 0; i < iDims; i++)
965     {
966         piNewDims[i] = getVarMaxDim(i, iDims);
967     }
968     piNewDims[iToDelIndex] = iNewDimSize;
969 
970     //remove last dimension if are == 1
971     int iOrigDims = iDims;
972     for (int i = (iDims - 1); i >= 2; i--)
973     {
974         if (piNewDims[i] == 1)
975         {
976             iDims--;
977         }
978         else
979         {
980             break;
981         }
982     }
983 
984     if (iDims == 1)
985     {
986         //two cases, depends of original matrix/vector
987         if ((*_pArgs)[0]->isColon() == false && m_iDims == 2 && m_piDims[0] == 1 && m_piDims[1] != 1)
988         {
989             //special case for row vector
990             int piRealDim[2] = {1, iNewDimSize};
991             //in this case we have to care of 2nd dimension
992             //iToDelIndex = 1;
993             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
994         }
995         else
996         {
997             int piRealDim[2] = {iNewDimSize, 1};
998             pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
999         }
1000     }
1001     else
1002     {
1003         pOut = createEmpty(iDims, piNewDims, m_pImgData != NULL);
1004     }
1005 
1006     // find a way to copy existing data to new variable ...
1007     int* piViewDims = new int[iOrigDims];
1008     int* piOffset = new int[iOrigDims + 1];
1009 
1010     // offsets
1011     piOffset[0] = 1;
1012     for (int i = 0; i < iOrigDims; i++)
1013     {
1014         piViewDims[i] = getVarMaxDim(i, iOrigDims);
1015         piOffset[i + 1] = piViewDims[i] * piOffset[i];
1016     }
1017 
1018     // indexes to remove -> [ 0, toDelIndexVect, piViewDims[iToDelIndex]+1 ] to facilitate loop
1019     toDelIndexVect.insert(toDelIndexVect.begin(), 0);
1020     toDelIndexVect.push_back(piViewDims[iToDelIndex] + 1);
1021 
1022     int iStart;
1023     int iSize;
1024     int iOffset1 = piOffset[iToDelIndex];
1025     int iOffset2 = piOffset[iToDelIndex + 1];
1026     int iNbChunks = getSize() / iOffset2;
1027 
1028     // fast algorithm (allowing in place removal if necessary)
1029     for (int k = 0, iDest = 0; k < iNbChunks; k++)
1030     {
1031         iStart = k * iOffset2;
1032         // loop on indexes to remove
1033         for (int j = 0; j < toDelIndexVect.size() - 1; j++)
1034         {
1035             iSize =  (toDelIndexVect[j + 1] - toDelIndexVect[j] - 1) * iOffset1;
1036             if (isNativeType())
1037             {
1038                 memcpy(pOut->m_pRealData + iDest, m_pRealData + iStart, iSize * sizeof(T));
1039                 if (m_pImgData != NULL)
1040                 {
1041                     memcpy(pOut->m_pImgData + iDest, m_pImgData + iStart, iSize * sizeof(T));
1042                 }
1043                 iDest += iSize;
1044             }
1045             else
1046             {
1047                 for (int i = iStart; i < iStart + iSize; i++, iDest++)
1048                 {
1049                     pOut->set(iDest, get(i));
1050                     if (m_pImgData != NULL)
1051                     {
1052                         pOut->setImg(iDest, getImg(i));
1053                     }
1054                 }
1055             }
1056             iStart += iSize + iOffset1;
1057         }
1058     }
1059 
1060     delete[] piViewDims;
1061     delete[] piOffset;
1062     delete[] piNewDims;
1063 
1064     //free pArg content
1065     cleanIndexesArguments(_pArgs, &pArg);
1066 
1067     return pOut;
1068 }
1069 
1070 template <typename T>
extract(typed_list * _pArgs)1071 GenericType* ArrayOf<T>::extract(typed_list* _pArgs)
1072 {
1073     ArrayOf<T>* pOut = NULL;
1074     int iDims = (int)_pArgs->size();
1075     typed_list pArg;
1076 
1077     int index;
1078     if (getScalarIndex(this, _pArgs, &index))
1079     {
1080         if (index < 0)
1081         {
1082             return NULL;
1083         }
1084 
1085         if (getSize() == 0)
1086         {
1087             return createEmpty();
1088         }
1089 
1090         if (index >= getSize())
1091         {
1092             return NULL;
1093         }
1094 
1095         int dims[2] = {1, 1};
1096         pOut = createEmpty(2, dims, false);
1097         pOut->set(0, get(index));
1098         bool c = isNativeType() ? getImg(index) != 0 : isComplexElement(index);
1099         if (isComplex() && c)
1100         {
1101             pOut->setComplex(true);
1102             pOut->setImg(0, getImg(index));
1103         }
1104         else
1105         {
1106             pOut->setComplex(false);
1107         }
1108 
1109         return pOut;
1110     }
1111 
1112     std::vector<double> il;
1113     if (getScalarImplicitIndex(this, _pArgs, il))
1114     {
1115         double start = il[0];
1116         double step = il[1];
1117         double end = il[2];
1118         //index are ":"
1119         bool isForceColVector = il.size() == 4;
1120 
1121         //std::cout << start << ":" << step << ":" << end << std::endl;
1122         int size = static_cast<int>((end - start) / step + 1);
1123 
1124         if (size <= 0 || m_iSize == 0)
1125         {
1126             return createEmpty();
1127         }
1128 
1129         //check bounds
1130         if (step > 0 && ((size - 1) * step + start > m_iSize || start < 1) ||
1131                 (step < 0 && (start > m_iSize || end < 1)))
1132         {
1133             return NULL;
1134         }
1135 
1136         bool isColVector = isForceColVector || (isVector() && m_iCols == 1);
1137         int dims[2] = {isColVector ? size : 1, isColVector ? 1 : size};
1138         pOut = createEmpty(2, dims, isComplex());
1139         double idx = start;
1140 
1141         if (isComplex())
1142         {
1143             bool bIsComplex = false;
1144             for (int i = 0; i < size; ++i)
1145             {
1146                 int index = static_cast<int>(idx) - 1;
1147                 T iValue = getImg(index);
1148                 pOut->set(i, get(index));
1149                 pOut->setImg(i, iValue);
1150                 if (isNativeType())
1151                 {
1152                     bIsComplex |= (iValue != 0);
1153                 }
1154                 else
1155                 {
1156                     bIsComplex |= (isComplexElement(index) != 0);
1157                 }
1158                 idx += step;
1159             }
1160 
1161             pOut->setComplex(bIsComplex);
1162         }
1163         else
1164         {
1165             for (int i = 0; i < size; ++i)
1166             {
1167                 pOut->set(i, get(static_cast<int>(idx) - 1));
1168                 idx += step;
1169             }
1170         }
1171         return pOut;
1172     }
1173 
1174     std::vector<int> indexes;
1175     std::vector<int> dims;
1176     if (getImplicitIndex(this, _pArgs, indexes, dims))
1177     {
1178         if (indexes.size() == 0)
1179         {
1180             return createEmpty();
1181         }
1182 
1183         if (dims.size() == 1)
1184         {
1185             int d[2] = {1, dims[0]};
1186             pOut = createEmpty(2, d, isComplex());
1187         }
1188         else
1189         {
1190             pOut = createEmpty(static_cast<int>(dims.size()), dims.data(), isComplex());
1191         }
1192 
1193         int size = getSize();
1194         if (isComplex())
1195         {
1196             bool bIsComplex = false;
1197             int idx = 0;
1198             for (int & i : indexes)
1199             {
1200                 if (i < 0 || i >= size)
1201                 {
1202                     pOut->killMe();
1203                     return NULL;
1204                 }
1205 
1206                 T iValue = getImg(i);
1207                 pOut->set(idx, get(i));
1208                 pOut->setImg(idx, iValue);
1209                 if (isNativeType())
1210                 {
1211                     bIsComplex |= (iValue != 0);
1212                 }
1213                 else
1214                 {
1215                     bIsComplex |= (isComplexElement(i) != 0);
1216                 }
1217 
1218                 ++idx;
1219             }
1220             pOut->setComplex(bIsComplex);
1221         }
1222         else
1223         {
1224             int idx = 0;
1225             for (int & i : indexes)
1226             {
1227                 pOut->set(idx, get(i));
1228                 ++idx;
1229             }
1230         }
1231 
1232         return pOut;
1233     }
1234 
1235 
1236     int* piMaxDim = new int[iDims];
1237     int* piCountDim = new int[iDims];
1238 
1239     //evaluate each argument and replace by appropriate value and compute the count of combinations
1240     int iSeqCount = checkIndexesArguments(this, _pArgs, &pArg, piMaxDim, piCountDim);
1241     if (iSeqCount == 0)
1242     {
1243         delete[] piMaxDim;
1244         delete[] piCountDim;
1245         //free pArg content
1246         cleanIndexesArguments(_pArgs, &pArg);
1247         return createEmpty();
1248     }
1249 
1250     if (iSeqCount < 0)
1251     {
1252         delete[] piMaxDim;
1253         delete[] piCountDim;
1254         //free pArg content
1255         cleanIndexesArguments(_pArgs, &pArg);
1256         return NULL;
1257     }
1258 
1259     //a = {};a(1:2, 1:2) -> {}
1260     if (getSize() == 0)
1261     {
1262         delete[] piMaxDim;
1263         delete[] piCountDim;
1264         //free pArg content
1265         cleanIndexesArguments(_pArgs, &pArg);
1266         return createEmpty();
1267     }
1268 
1269     if (iDims < m_iDims)
1270     {
1271         for (int i = 0; i < iDims; i++)
1272         {
1273             int iDimToCheck = 0;
1274             if (i == (iDims - 1))
1275             {
1276                 iDimToCheck = getVarMaxDim(i, iDims);
1277             }
1278             else
1279             {
1280                 iDimToCheck = m_piDims[i];
1281             }
1282 
1283             if (piMaxDim[i] > iDimToCheck)
1284             {
1285                 delete[] piMaxDim;
1286                 delete[] piCountDim;
1287                 //free pArg content
1288                 cleanIndexesArguments(_pArgs, &pArg);
1289                 return NULL;
1290             }
1291         }
1292     }
1293     else
1294     {
1295         if (iDims > m_iDims)
1296         {
1297             for (int i = m_iDims; i < iDims; i++)
1298             {
1299                 if (piMaxDim[i] > 1)
1300                 {
1301                     delete[] piMaxDim;
1302                     delete[] piCountDim;
1303                     //free pArg content
1304                     cleanIndexesArguments(_pArgs, &pArg);
1305                     return NULL;
1306                 }
1307             }
1308         }
1309 
1310         //check MaxDim
1311         for (int i = 0; i < m_iDims; i++)
1312         {
1313             if (piMaxDim[i] > m_piDims[i])
1314             {
1315                 delete[] piMaxDim;
1316                 delete[] piCountDim;
1317                 //free pArg content
1318                 cleanIndexesArguments(_pArgs, &pArg);
1319                 //exrtact must be in dimension limits
1320                 return NULL;
1321             }
1322         }
1323     }
1324 
1325     //remove last dimension if are == 1
1326     for (int i = (iDims - 1); i >= 2; i--)
1327     {
1328         if (piCountDim[i] == 1)
1329         {
1330             (iDims)--;
1331         }
1332         else
1333         {
1334             break;
1335         }
1336     }
1337 
1338     //linear indexing (one subscript)
1339     if (iDims == 1)
1340     {
1341         if (piCountDim[0] == 0)
1342         {
1343             delete[] piMaxDim;
1344             delete[] piCountDim;
1345             //free pArg content
1346             cleanIndexesArguments(_pArgs, &pArg);
1347             return createEmpty();
1348         }
1349         else
1350         {
1351             int *i_piDims = pArg[0]->getAs<GenericType>()->getDimsArray();
1352             if (!isScalar() && isVector() && (i_piDims[0] == 1 || i_piDims[1] == 1))
1353             {
1354                 //vector with vector subscript
1355                 int piRealDim[2] = { 1, 1 };
1356                 piRealDim[(int)(m_piDims[0] == 1)] = piCountDim[0];
1357                 pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1358             }
1359             else
1360             {
1361                 if ((*_pArgs)[0]->isBool() || (*_pArgs)[0]->isSparseBool())
1362                 {
1363                     //result has same shape of index if index is a vector otherwise yield a column
1364                     types::GenericType* pGT = (*_pArgs)[0]->getAs<GenericType>();
1365                     int piRealDim[2] = { 1, 1 };
1366                     piRealDim[(int)(pGT->isVector() && pGT->getRows() == 1)] = piCountDim[0];
1367                     pOut = createEmpty(2, piRealDim, m_pImgData != NULL);
1368                 }
1369                 else
1370                 {
1371                     //other cases
1372                     pOut = createEmpty(pArg[0]->getAs<GenericType>()->getDims(), i_piDims, m_pImgData != NULL);
1373                 }
1374             }
1375         }
1376     }
1377     else
1378     {
1379         //indexing with more than one subscript
1380         pOut = createEmpty(iDims, piCountDim, m_pImgData != NULL);
1381     }
1382 
1383     int* piIndex = new int[_pArgs->size()];
1384     int* piCoord = new int[_pArgs->size()];
1385     int* piViewDims = new int[iDims];
1386     memset(piIndex, 0x00, sizeof(int) * _pArgs->size());
1387 
1388     for (int i = 0; i < iDims; i++)
1389     {
1390         piViewDims[i] = getVarMaxDim(i, iDims);
1391     }
1392 
1393     bool bIsComplex = false;
1394     for (int i = 0; i < iSeqCount; i++)
1395     {
1396         //increment last dimension
1397         computeTuples(piCountDim, (int)_pArgs->size(), (int)_pArgs->size() - 1, piIndex);
1398 
1399         //std::cout << "[";
1400         for (int j = 0; j < (int)_pArgs->size(); j++)
1401         {
1402             piCoord[j] = getIntValueFromDouble(pArg[j], piIndex[j]) - 1;
1403             //InternalType* pVar = pArg[i];
1404             //piCoord[j] = static_cast<int>(pVar->getAs<Double>()->get(piIndex[j]) - 1);
1405             //std::cout << piCoord[j] << " ";
1406 
1407             // try to access somewhere wrong.
1408             if (piCoord[j] < 0)
1409             {
1410                 delete[] piIndex;
1411                 delete[] piCoord;
1412                 delete[] piViewDims;
1413                 delete[] piMaxDim;
1414                 delete[] piCountDim;
1415 
1416                 //free pArg content
1417                 cleanIndexesArguments(_pArgs, &pArg);
1418                 if(pOut)
1419                 {
1420                     pOut->killMe();
1421                 }
1422                 return NULL;
1423             }
1424         }
1425 
1426         //std::cout << "]" << std::endl;
1427 
1428         int iPos = 0;
1429         //put vlaue in the new matrix
1430         if ((int)_pArgs->size() < m_iDims)
1431         {
1432             //compute index based on viewed matrix
1433             iPos = getIndexWithDims(piCoord, piViewDims, iDims);
1434         }
1435         else
1436         {
1437             //compute vector index
1438             iPos = getIndex(piCoord);
1439         }
1440 
1441         //convert flat dimension to 0
1442         for (int j = 0; j < iDims; j++)
1443         {
1444             if (piCountDim[j] == 1)
1445             {
1446                 piCoord[j] = 0;
1447             }
1448         }
1449 
1450         pOut->set(i, get(iPos));
1451         if (isComplex())
1452         {
1453             T iValue = getImg(iPos);
1454             pOut->setImg(i, iValue);
1455             if (isNativeType())
1456             {
1457                 bIsComplex |= (iValue != 0);
1458             }
1459             else
1460             {
1461                 bIsComplex |= (isComplexElement(iPos) != 0);
1462             }
1463         }
1464 
1465         piIndex[0]++;
1466     }
1467 
1468     pOut->setComplex(bIsComplex);
1469 
1470     //free pArg content
1471     cleanIndexesArguments(_pArgs, &pArg);
1472 
1473     delete[] piIndex;
1474     delete[] piCoord;
1475     delete[] piViewDims;
1476     delete[] piMaxDim;
1477     delete[] piCountDim;
1478 
1479     return pOut;
1480 }
1481 
1482 template <typename T>
reshape(int * _piDims,int _iDims)1483 ArrayOf<T>* ArrayOf<T>::reshape(int* _piDims, int _iDims)
1484 {
1485     typedef ArrayOf<T>* (ArrayOf<T>::*reshape_t)(int*, int);
1486     ArrayOf<T>* pIT = checkRef(this, (reshape_t)&ArrayOf<T>::reshape, _piDims, _iDims);
1487     if (pIT != this)
1488     {
1489         return pIT;
1490     }
1491 
1492     int iNewSize = get_max_size(_piDims, _iDims);
1493     if (iNewSize != m_iSize)
1494     {
1495         return NULL;
1496     }
1497 
1498     for (int i = 0 ; i < _iDims ; i++)
1499     {
1500         m_piDims[i] = _piDims[i];
1501     }
1502 
1503     if (_iDims == 1)
1504     {
1505         m_piDims[1] = 1;
1506         _iDims++;
1507     }
1508 
1509     int iDims = _iDims;
1510     for (int i = iDims - 1; i >= 2; --i)
1511     {
1512         if (m_piDims[i] == 1)
1513         {
1514             _iDims--;
1515         }
1516         else
1517         {
1518             break;
1519         }
1520     }
1521 
1522     m_iRows = m_piDims[0];
1523     m_iCols = m_piDims[1];
1524     m_iSize = iNewSize;
1525     m_iDims = _iDims;
1526 
1527     return this;
1528 }
1529 
1530 template <typename T>
resize(int * _piDims,int _iDims)1531 ArrayOf<T>* ArrayOf<T>::resize(int* _piDims, int _iDims)
1532 {
1533     typedef ArrayOf<T>* (ArrayOf<T>::*resize_t)(int*, int);
1534     ArrayOf<T>* pIT = checkRef(this, (resize_t)&ArrayOf::resize, _piDims, _iDims);
1535     if (pIT != this)
1536     {
1537         return pIT;
1538     }
1539 
1540     if (_iDims == m_iDims)
1541     {
1542         bool bChange = false;
1543         for (int i = 0; i < _iDims; i++)
1544         {
1545             if (m_piDims[i] != _piDims[i])
1546             {
1547                 bChange = true;
1548                 break;
1549             }
1550         }
1551 
1552         if (bChange == false)
1553         {
1554             //nothing to do
1555             return this;
1556         }
1557     }
1558 
1559     //alloc new data array
1560     T* pRealData = NULL;
1561     T* pImgData = NULL;
1562 
1563     int iNewSize = 0;
1564     if (m_pImgData != NULL)
1565     {
1566         iNewSize = get_max_size(_piDims, _iDims);
1567         if (m_iSizeMax < iNewSize)
1568         {
1569             //alloc 10% bigger than asked to prevent future resize
1570             int iOldSizeMax = m_iSizeMax;
1571             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1572             pRealData = allocData(m_iSizeMax);
1573             pImgData = allocData(m_iSizeMax);
1574 
1575             //copy values into new one
1576             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1577             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1578             for (int i = 0; i < _iDims; i++)
1579             {
1580                 piIndexes[i] = 0;
1581             }
1582 
1583             int iPreviousNewIdx = 0;
1584             for (int i = 0; i < m_iSize; i++)
1585             {
1586                 getIndexes(i, piIndexes);
1587                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1588                 pRealData[iNewIdx] = m_pRealData[i];
1589                 pImgData[iNewIdx] = m_pImgData[i];
1590                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1591                 {
1592                     T pTemp = getNullValue();
1593                     pRealData[j] = copyValue(pTemp);
1594                     pImgData[j] = copyValue(pTemp);
1595                     if (pTemp != pRealData[j])
1596                     {
1597                         deleteData(pTemp);
1598                     }
1599                 }
1600 
1601                 iPreviousNewIdx = iNewIdx + 1;
1602             }
1603 
1604             // if it's not the first resize,
1605             // fill new data with element of last allocation
1606             if (iPreviousNewIdx < iOldSizeMax)
1607             {
1608                 for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1609                 {
1610                     pRealData[i] = m_pRealData[i];
1611                     pImgData[i] = m_pImgData[i];
1612                 }
1613             }
1614             else
1615             {
1616                 // first resize, iOldSizeMax don't contain the 10%
1617                 iOldSizeMax = iPreviousNewIdx;
1618             }
1619 
1620             for (int i = iOldSizeMax; i < m_iSizeMax; ++i)
1621             {
1622                 T pTemp = getNullValue();
1623                 pRealData[i] = copyValue(pTemp);
1624                 pImgData[i] = copyValue(pTemp);
1625                 if (pTemp != pRealData[i])
1626                 {
1627                     deleteData(pTemp);
1628                 }
1629             }
1630 
1631             delete[] piIndexes;
1632             //delete all array
1633             delete[] m_pRealData;
1634             delete[] m_pImgData;
1635             //replace old array by new one
1636             m_pRealData = pRealData;
1637             m_pImgData = pImgData;
1638         }
1639         else
1640         {
1641             //check if only the last dims change
1642             bool bNonLastDimChange = false;
1643             for (int i = 0; i < (m_iDims - 1); i++)
1644             {
1645                 if (m_piDims[i] != _piDims[i])
1646                 {
1647                     bNonLastDimChange = true;
1648                     break;
1649                 }
1650             }
1651 
1652             //if vector or if row dimension not change, we don't need to shift data
1653             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1654             {
1655                 //copy values into new one
1656                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1657                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1658                 for (int i = m_iSize - 1; i >= 0; i--)
1659                 {
1660                     getIndexes(i, piIndexes);
1661                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1662                     if (iNewIdx != i)
1663                     {
1664                         T pTemp = m_pRealData[iNewIdx];
1665                         m_pRealData[iNewIdx] = m_pRealData[i];
1666                         m_pRealData[i] = pTemp;
1667 
1668                         pTemp = m_pImgData[iNewIdx];
1669                         m_pImgData[iNewIdx] = m_pImgData[i];
1670                         m_pImgData[i] = pTemp;
1671                     }
1672                 }
1673                 delete[] piIndexes;
1674             }
1675         }
1676     }
1677     else
1678     {
1679         iNewSize = get_max_size(_piDims, _iDims);
1680         if (iNewSize > m_iSizeMax)
1681         {
1682             //alloc 10% bigger than asked to prevent future resize
1683             int iOldSizeMax = m_iSizeMax;
1684             m_iSizeMax = static_cast<int>(iNewSize * 1.1);
1685             pRealData = allocData(m_iSizeMax);
1686 
1687             //copy values into new one
1688             int* piIndexes = new int[std::max(m_iDims, _iDims)];
1689             memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1690             for (int i = 0; i < _iDims; i++)
1691             {
1692                 piIndexes[i] = 0;
1693             }
1694 
1695             int iPreviousNewIdx = 0;
1696             for (int i = 0; i < m_iSize; i++)
1697             {
1698                 getIndexes(i, piIndexes);
1699                 int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1700                 pRealData[iNewIdx] = m_pRealData[i];
1701                 m_pRealData[i] = T();
1702 
1703                 for (int j = iPreviousNewIdx; j < iNewIdx; ++j)
1704                 {
1705                     T pTemp = getNullValue();
1706                     T pTemp2 = copyValue(pTemp);
1707                     pRealData[j] = pTemp2;
1708                     if (pTemp != pTemp2)
1709                     {
1710                         deleteData(pTemp);
1711                     }
1712                 }
1713 
1714                 iPreviousNewIdx = iNewIdx + 1;
1715             }
1716 
1717             //clean section between m_iSize and iOldSizeMax
1718             for (int i = m_iSize; i < iOldSizeMax; ++i)
1719             {
1720                 deleteData(m_pRealData[i]);
1721                 m_pRealData[i] = T();
1722             }
1723 
1724             //if (iPreviousNewIdx < iOldSizeMax)
1725             //{
1726             //    for (int i = iPreviousNewIdx; i < iOldSizeMax; ++i)
1727             //    {
1728             //        pRealData[i] = m_pRealData[i];
1729             //        m_pRealData[i] = T();
1730             //    }
1731             //}
1732             //else
1733             //{
1734             //    iOldSizeMax = iPreviousNewIdx;
1735             //}
1736 
1737             //fill exceeded with NullValue
1738             for (int i = iPreviousNewIdx; i < m_iSizeMax; ++i)
1739             {
1740                 T pTemp = getNullValue();
1741                 T pTemp2 = copyValue(pTemp);
1742                 pRealData[i] = pTemp2;
1743                 if (pTemp != pTemp2)
1744                 {
1745                     deleteData(pTemp);
1746                 }
1747             }
1748 
1749             delete[] piIndexes;
1750             //delete all array
1751             delete[] m_pRealData;
1752             //replace old array by new one
1753             m_pRealData = pRealData;
1754         }
1755         else
1756         {
1757             //check if only the last dims change
1758             bool bNonLastDimChange = false;
1759             for (int i = 0; i < (m_iDims - 1); i++)
1760             {
1761                 if (m_piDims[i] != _piDims[i])
1762                 {
1763                     bNonLastDimChange = true;
1764                     break;
1765                 }
1766             }
1767 
1768             //if vector or if row dimension not change, we don't need to shift data
1769             if (m_iDims != _iDims || (!isVector() && bNonLastDimChange))
1770             {
1771                 //copy values into new one
1772                 int* piIndexes = new int[std::max(m_iDims, _iDims)];
1773                 memset(piIndexes, 0x00, sizeof(int) * std::max(m_iDims, _iDims));
1774                 for (int i = m_iSize - 1; i >= 0; i--)
1775                 {
1776                     getIndexes(i, piIndexes);
1777                     int iNewIdx = getIndexWithDims(piIndexes, _piDims, _iDims);
1778                     if (iNewIdx != i)
1779                     {
1780                         T pTemp = m_pRealData[iNewIdx];
1781                         m_pRealData[iNewIdx] = m_pRealData[i];
1782                         m_pRealData[i] = pTemp;
1783                     }
1784                 }
1785                 delete[] piIndexes;
1786             }
1787         }
1788     }
1789 
1790     if (_iDims != m_iDims)
1791     {
1792         //int* piDims = new int[_iDims];
1793         for (int i = 0; i < _iDims; i++)
1794         {
1795             m_piDims[i] = _piDims[i];
1796         }
1797         //delete[] m_piDims;
1798         //m_piDims = piDims;
1799         m_iDims = _iDims;
1800     }
1801     else
1802     {
1803         for (int i = 0; i < m_iDims; i++)
1804         {
1805             m_piDims[i] = _piDims[i];
1806         }
1807     }
1808     m_iRows = m_piDims[0];
1809     m_iCols = m_piDims[1];
1810     m_iSize = iNewSize;
1811     return this;
1812 }
1813 
1814 template <typename T>
isTrue()1815 bool ArrayOf<T>::isTrue()
1816 {
1817     return type_traits::isTrue<T>(m_iSize, m_pRealData);
1818 }
1819 
1820 template<typename T>
neg(InternalType * & out)1821 bool ArrayOf<T>::neg(InternalType *& out)
1822 {
1823     out = new Bool(this->m_iDims, this->m_piDims);
1824     type_traits::neg<T, int>(this->m_iSize, this->m_pRealData, static_cast<Bool *>(out)->get());
1825 
1826     return true;
1827 }
1828 
1829 template<typename T>
invoke(typed_list & in,optional_list &,int,typed_list & out,const ast::Exp & e)1830 bool ArrayOf<T>::invoke(typed_list & in, optional_list & /*opt*/, int /*_iRetCount*/, typed_list & out, const ast::Exp & e)
1831 {
1832     if (in.size() == 0)
1833     {
1834         out.push_back(this);
1835     }
1836     else
1837     {
1838         InternalType * _out = extract(&in);
1839         if (!_out)
1840         {
1841             std::wostringstream os;
1842             os << _W("Invalid index.\n");
1843             throw ast::InternalError(os.str(), 999, e.getLocation());
1844         }
1845         out.push_back(_out);
1846     }
1847 
1848     return true;
1849 }
1850 
1851 template<typename T>
isInvokable() const1852 bool ArrayOf<T>::isInvokable() const
1853 {
1854     return true;
1855 }
1856 
1857 template<typename T>
hasInvokeOption() const1858 bool ArrayOf<T>::hasInvokeOption() const
1859 {
1860     return false;
1861 }
1862 
1863 template<typename T>
getInvokeNbIn()1864 int ArrayOf<T>::getInvokeNbIn()
1865 {
1866     return -1;
1867 }
1868 
1869 template<typename T>
getInvokeNbOut()1870 int ArrayOf<T>::getInvokeNbOut()
1871 {
1872     return 1;
1873 }
1874 
1875 
1876 // used to allow definition of ArrayOf methode in this cpp file.
1877 template class EXTERN_AST ArrayOf < char >;
1878 template class EXTERN_AST ArrayOf < unsigned char >;
1879 template class EXTERN_AST ArrayOf < short >;
1880 template class EXTERN_AST ArrayOf < unsigned short >;
1881 template class EXTERN_AST ArrayOf < int >;
1882 template class EXTERN_AST ArrayOf < unsigned int >;
1883 template class EXTERN_AST ArrayOf < long long >;
1884 template class EXTERN_AST ArrayOf < unsigned long long >;
1885 template class EXTERN_AST ArrayOf < double >;
1886 template class EXTERN_AST ArrayOf < wchar_t* >;
1887 template class EXTERN_AST ArrayOf < SinglePoly* >;
1888 template class EXTERN_AST ArrayOf < SingleStruct* >;
1889 template class EXTERN_AST ArrayOf < InternalType* >; // Cell
1890 }
1891