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