1 /***************************************************************************
2 arrayindex.hpp - array access descriptor
3 -------------------
4 begin : July 22 2002
5 copyright : (C) 2002 by Marc Schellens
6 email : m_schellens@users.sf.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #ifndef ARRAYINDEX_HPP_
19 #define ARRAYINDEX_HPP_
20
21 #include <valarray>
22 #include <vector>
23
24 #include "datatypes.hpp"
25 #include "real2int.hpp"
26
27 // done below
28 // #include "allix.hpp"
29
30
31
32 //typedef std::valarray<SizeT> AllIxT; // now in typedefs.hpp
33 //typedef std::vector<BaseGDL*> IxExprListT;
34 class IxExprListT
35 {
36 private:
37 BaseGDL* eArr[3*MAXRANK];
38 int sz;
39 public:
IxExprListT()40 IxExprListT(): sz(0) {}
push_back(BaseGDL * p)41 void push_back( BaseGDL* p) { assert( sz<3*MAXRANK); eArr[ sz++] = p;}
operator [](SizeT i) const42 BaseGDL* operator[]( SizeT i) const { assert( i<3*MAXRANK && i<sz); return eArr[i];}
size() const43 SizeT size() const { return sz;}
Cleanup()44 void Cleanup() { for( int i=0; i<sz; ++i) delete eArr[i]; sz=0;}
operator =(IxExprListT & r)45 IxExprListT& operator=(IxExprListT&r) { sz = r.sz; for(int i=0; i<sz; ++i) eArr[i] = r.eArr[i]; return r;}
46 };
47
48 enum IndexType
49 {
50 ArrayIndexTID, // abstract
51 ArrayIndexScalarID, // scalar
52 CArrayIndexScalarID, // with const e. g. [42]
53 ArrayIndexScalarVPID, // common blobck or sysvar
54 ArrayIndexIndexedID, // indexed
55 CArrayIndexIndexedID, // indexed with const
56 ArrayIndexAllID, // [*]
57 ArrayIndexORangeID, // [3:*]
58 CArrayIndexORangeID, // with const
59 ArrayIndexRangeID, // [a:b]
60 CArrayIndexRangeID, // with const
61 ArrayIndexORangeSID, // [a:*:stride]
62 CArrayIndexORangeSID, // with const
63 ArrayIndexRangeSID, // [a:b:stride]
64 CArrayIndexRangeSID // with const
65 };
66
67 class ArrayIndexT
68 {
69 public:
Type()70 virtual IndexType Type() { return ArrayIndexTID;}
71
72 // this may be called from ArrayIndexListT::ToAssocIndex
Init()73 virtual void Init() {}
74
75 // the following should never be called
Init(BaseGDL *)76 virtual void Init( BaseGDL*) { assert( false);}
Init(BaseGDL *,BaseGDL *)77 virtual void Init( BaseGDL*, BaseGDL*) { assert( false);}
Init(BaseGDL *,BaseGDL *,BaseGDL *)78 virtual void Init( BaseGDL*, BaseGDL*, BaseGDL*) { assert( false);}
79
IsRange()80 virtual bool IsRange() { return false;} // default for non-ranges
OverloadIndexNew()81 virtual BaseGDL* OverloadIndexNew() { assert( false); return 0;}
OverloadIndexNew(BaseGDL *)82 virtual BaseGDL* OverloadIndexNew( BaseGDL*) { assert( false); return 0;}
OverloadIndexNew(BaseGDL *,BaseGDL *)83 virtual BaseGDL* OverloadIndexNew( BaseGDL*, BaseGDL*) { assert( false); return 0;}
OverloadIndexNew(BaseGDL *,BaseGDL *,BaseGDL *)84 virtual BaseGDL* OverloadIndexNew( BaseGDL*, BaseGDL*, BaseGDL*) { assert( false); return 0;}
85
Clear()86 virtual void Clear() {}
~ArrayIndexT()87 virtual ~ArrayIndexT() {}
88
89 virtual RangeT GetIx0()=0;
GetS()90 virtual RangeT GetS() { return 0;}
GetStride()91 virtual SizeT GetStride() { return 1;} // changed from 0
92
Scalar() const93 virtual bool Scalar() const { return false;}
94 // virtual bool Scalar( SizeT& s_) const { return false;}
Scalar(RangeT & s_) const95 virtual bool Scalar( RangeT& s_) const { return false;}
96
Indexed()97 virtual bool Indexed() { return false;}
98
99 // virtual BaseGDL* Index( BaseGDL* var, IxExprListT& ix)=0;
100
101 virtual SizeT NIter( SizeT varDim)=0;
102
103 virtual SizeT NParam()=0;
104
105 virtual ArrayIndexT* Dup() const =0;
106 };
107
108 class ArrayIndexVectorT
109 {
110 private:
111 ArrayIndexT* arrayIxArr[ MAXRANK];
112 SizeT sz;
113 public:
ArrayIndexVectorT()114 ArrayIndexVectorT(): sz(0) {}
~ArrayIndexVectorT()115 ~ArrayIndexVectorT()
116 {} // for( int i=0; i<sz; ++i) delete arrayIxArr[ i];}
ArrayIndexVectorT(const ArrayIndexVectorT & cp)117 ArrayIndexVectorT( const ArrayIndexVectorT& cp): sz( cp.sz)
118 {
119 for( SizeT i=0; i<sz;++i)
120 arrayIxArr[ i] = cp.arrayIxArr[ i];
121 }
FrontGetS() const122 SizeT FrontGetS() const
123 {
124 assert( sz > 0);
125 return arrayIxArr[0]->GetS();
126 }
127
operator [](SizeT ix) const128 ArrayIndexT* operator[]( SizeT ix) const
129 {
130 assert( ix < MAXRANK);
131 return arrayIxArr[ ix];
132 }
size() const133 SizeT size() const { return sz;}
push_back(ArrayIndexT * aIx)134 void push_back( ArrayIndexT* aIx)
135 {
136 // if( sz >= MAXRANK) // debug
137 assert( sz < MAXRANK);
138 arrayIxArr[ sz++] = aIx;
139 }
Clear()140 void Clear()
141 {
142 for( int i=0; i<sz; ++i)
143 arrayIxArr[ i]->Clear();
144 }
Destruct()145 void Destruct() // only to be used from destructor (instance is not valid anymore afterwards)
146 {
147 for( int i=0; i<sz; ++i)
148 delete arrayIxArr[ i];
149 //sz = 0;
150 }
back() const151 ArrayIndexT* back() const { return arrayIxArr[ sz-1];}
pop_back()152 void pop_back() { --sz;}
pop_back_get()153 ArrayIndexT* pop_back_get() { --sz; return arrayIxArr[ sz];}
154 };
155
156 #include "allix.hpp"
157
158 // SCALAR (only for FOR loop indices)
159 // VAR
160 class ArrayIndexScalar: public ArrayIndexT
161 {
162 protected:
163 SizeT varIx;
164
165 RangeT sInit;
166 RangeT s;
167
168 public:
Type()169 IndexType Type() { return ArrayIndexScalarID;}
170 // SizeT GetIx( SizeT i)
171 // {
172 // assert( ix != NULL);
173 // return (*ix)[ i];
174 // }
175 BaseGDL* OverloadIndexNew();
176
GetVarIx() const177 SizeT GetVarIx() const { return varIx;}
178
NParam()179 SizeT NParam() { return 0;} // number of parameter to Init(...)
180
GetS()181 RangeT GetS() { return s;}
182
Scalar() const183 bool Scalar() const { return true;}
Scalar(RangeT & s_) const184 bool Scalar( RangeT& s_) const
185 {
186 s_ = s;
187 return true;
188 }
189
GetIx0()190 RangeT GetIx0()
191 {
192 return s;
193 }
194
~ArrayIndexScalar()195 ~ArrayIndexScalar()
196 {}
197
198 ArrayIndexScalar( RefDNode& dNode);
199
200 // c-i
ArrayIndexScalar(const ArrayIndexScalar & r)201 ArrayIndexScalar( const ArrayIndexScalar& r):
202 varIx( r.varIx),
203 sInit( r.sInit),
204 s( r.s)
205 {}
206
Dup() const207 ArrayIndexT* Dup() const
208 {
209 return new ArrayIndexScalar(*this);
210 }
211
212 void Init();
213
Clear()214 void Clear()
215 {}
216
217 // if this is used, Init was NOT called before
218 // BaseGDL* Index( BaseGDL* var, IxExprListT& ixL);
219
220 // number of iterations
221 // also checks/adjusts range
222 SizeT NIter( SizeT varDim);
223 };
224 // VARPTR (common block variable)
225 class ArrayIndexScalarVP: public ArrayIndexT
226 {
227 protected:
228 DVar* varPtr;
229
230 RangeT sInit;
231 RangeT s;
232
233 public:
Type()234 IndexType Type() { return ArrayIndexScalarVPID;}
235
OverloadIndexNew()236 BaseGDL* OverloadIndexNew()
237 {
238 BaseGDL* v = varPtr->Data();
239 if( v == NULL) return NULL;
240 return v->Dup();
241 }
242
GetVarPtr() const243 DVar* GetVarPtr() const { return varPtr;}
244
NParam()245 SizeT NParam() { return 0;} // number of parameter to Init(...)
246
GetS()247 RangeT GetS() { return s;}
248
Scalar() const249 bool Scalar() const { return true;}
Scalar(RangeT & s_) const250 bool Scalar( RangeT& s_) const
251 {
252 s_ = s;
253 return true;
254 }
255
Init()256 void Init()
257 {
258 sInit = varPtr->Data()->LoopIndex();
259 s = sInit;
260 }
261
Clear()262 void Clear()
263 {}
264
GetIx0()265 RangeT GetIx0()
266 {
267 return s;
268 }
269
~ArrayIndexScalarVP()270 ~ArrayIndexScalarVP()
271 {}
272
273 ArrayIndexScalarVP( RefDNode& dNode);
274
275 // c-i
ArrayIndexScalarVP(const ArrayIndexScalarVP & r)276 ArrayIndexScalarVP( const ArrayIndexScalarVP& r):
277 varPtr( r.varPtr),
278 s( r.s)
279 {}
280
Dup() const281 ArrayIndexT* Dup() const
282 {
283 return new ArrayIndexScalarVP(*this);
284 }
285
286 // if this is used, Init was NOT called before
287 // BaseGDL* Index( BaseGDL* var, IxExprListT& ixL);
288
289 // number of iterations
290 // also checks/adjusts range
291 SizeT NIter( SizeT varDim);
292 };
293
294
295
296
297
298 // constant SCALAR
299 class CArrayIndexScalar: public ArrayIndexT
300 {
301 private:
302 RangeT sInit; // can be < 0 as well
303 RangeT s;
304 BaseGDL* rawData; // for overloaded object indexing
305
CArrayIndexScalar(const CArrayIndexScalar & c)306 CArrayIndexScalar( const CArrayIndexScalar& c): sInit( c.sInit), s( c.s)
307 {
308 assert( c.rawData != NULL);
309 rawData = c.rawData->Dup();
310 }
311
312 public:
Type()313 IndexType Type() { return CArrayIndexScalarID;}
314
OverloadIndexNew()315 BaseGDL* OverloadIndexNew()
316 {
317 assert( rawData != NULL);
318 return rawData->Dup();
319 }
320
NParam()321 SizeT NParam() { return 0;} // number of parameter to Init(...)
322
StealRawData()323 BaseGDL* StealRawData() { BaseGDL* r = rawData; rawData = NULL; return r;}
324
Scalar() const325 bool Scalar() const { return true;}
Scalar(RangeT & s_) const326 bool Scalar( RangeT& s_) const
327 {
328 s_ = s;
329 return true;
330 }
331
GetIx0()332 RangeT GetIx0()
333 {
334 return s;
335 }
336
GetS()337 RangeT GetS() { return s;}
338
~CArrayIndexScalar()339 ~CArrayIndexScalar()
340 {
341 delete rawData;
342 }
343
344 // grabs c
CArrayIndexScalar(BaseGDL * c)345 CArrayIndexScalar( BaseGDL* c)
346 : sInit(c->LoopIndex()),
347 rawData(c)
348 {
349 // if( c->Type() == GDL_STRING)
350 // {
351 // DStringGDL* cString = static_cast<DStringGDL*>(c);
352 // if( (*cString)[0] == "")
353 // {
354 // s = 0;
355 // }
356 // else
357 // {
358 // const char* cStart=(*cString)[0].c_str();
359 // char* cEnd;
360 // RangeT ix=strtol(cStart,&cEnd,10);
361 // if( cEnd == cStart)
362 // {
363 // // in LoopIndex() just a warning is printed
364 // // An exception is necessary as then ArrayIndexScalar
365 // // is used instead (see: gdlc.tree.g: arrayindex)
366 // throw GDLException("Type conversion error: "
367 // "Unable to convert given STRING: '"+
368 // (*cString)[0]+"' to index.");
369 // }
370 // s = ix;
371 // }
372 // }
373 // else
374 // ccpchek says: (performance) Variable 'sInit' is assigned in constructor body. Consider performing initialization in initialization list.
375 // sInit = c->LoopIndex(); // non STRING throw if not allowed
376 s = sInit;
377 }
378
CArrayIndexScalar(RangeT s_)379 CArrayIndexScalar( RangeT s_): sInit( s_), s( s_), rawData(NULL)
380 {}
381
Dup() const382 ArrayIndexT* Dup() const
383 {
384 return new CArrayIndexScalar( *this);
385 }
386
Clear()387 void Clear()
388 {}
Init()389 void Init()
390 {}
391
392 // // if this is used, Init was NOT called before
393 // BaseGDL* Index( BaseGDL* var, IxExprListT& ixL)
394 // {
395 // if( s >= var->N_Elements()/*var->Size()*/)
396 // throw GDLException(-1,NULL,"Scalar subscript out of range [>].h1",true,false);
397 // return var->NewIx( s);
398 // }
399
400 // number of iterations
401 // also checks/adjusts range
NIter(SizeT varDim)402 SizeT NIter( SizeT varDim)
403 {
404 if( sInit < 0)
405 s = sInit + varDim;
406 else
407 s = sInit;
408
409 if( s < 0)
410 throw GDLException(-1,NULL,"Constant scalar subscript out of range [-i].",true,false);
411 if( s >= varDim && s > 0) // varDim == 0 && s == 0 ok
412 throw GDLException(-1,NULL,"Constant scalar out of range [i].",true,false);
413 return 1;
414
415 // if( s >= varDim && s > 0) // varDim == 0 && s == 0 ok
416 // throw GDLException(-1,NULL,"Scalar subscript out of range [>].h2",true,false);
417 // return 1;
418 }
419 }; //class CArrayIndexScalar: public ArrayIndexT
420
421
422
423
424
425 // INDEXED or ONE [v] (must handle both)
426 class ArrayIndexIndexed: public ArrayIndexT
427 {
428 protected:
429 bool strictArrSubs; // for compile_opt STRICTARRSUBS
430
431 RangeT sInit; // can be < 0 as well
432 RangeT s;
433 // SizeT maxVal;
434
435 AllIxIndicesT* ix;
436 char ixBuf[ AllIxMaxSize];
437
438 const dimension* ixDim; // keep dimension of ix
439
440 // forbid c-i
ArrayIndexIndexed(const ArrayIndexT & r)441 ArrayIndexIndexed( const ArrayIndexT& r) {}
442
443 public:
Type()444 IndexType Type() { return ArrayIndexIndexedID;}
445
OverloadIndexNew(BaseGDL * p1)446 BaseGDL* OverloadIndexNew( BaseGDL* p1)
447 {
448 if( p1 == NULL) return NULL;
449 return p1->Dup();
450 }
451
NParam()452 SizeT NParam() { return 1;} // number of parameter to Init(...)
453
GetS()454 RangeT GetS() { return s;}
455
Scalar() const456 bool Scalar() const { return (ix == NULL);}
Scalar(RangeT & s_) const457 bool Scalar( RangeT& s_) const // changed from RangeT for proper overloading
458 {
459 if( ix == NULL)
460 {
461 s_ = s;
462 return true;
463 }
464 s_ = (*ix)[0];
465 return (ix->size() == 1);
466 }
467
Indexed()468 bool Indexed() { return (ix != NULL);}
469
GetDim()470 const dimension& GetDim() { assert(ixDim != NULL); return *ixDim;}
471
GetIx0()472 RangeT GetIx0()
473 {
474 if( ix != NULL) return (*ix)[0]; // from array
475 return s;
476 }
477
GetIx(SizeT i)478 SizeT GetIx( SizeT i)
479 {
480 assert( ix != NULL);
481 return (*ix)[ i];
482 }
483
484 // SizeT* StealIx() { SizeT* ret = ix; ix = NULL; return ret;}
485 //AllIxIndicesT* StealIx() { AllIxIndicesT* ret = ix; ix = NULL; return ret;}
GetAllIx() const486 AllIxIndicesT* GetAllIx() const { return ix;}
487
~ArrayIndexIndexed()488 ~ArrayIndexIndexed()
489 {
490 // delete ix;
491 // delete ixDim;
492 }
493
ArrayIndexIndexed(bool strictArrSubs_=false)494 ArrayIndexIndexed( bool strictArrSubs_ = false):
495 strictArrSubs( strictArrSubs_),
496 // maxVal( 0),
497 ix( NULL), ixDim( NULL)
498 {}
499
Dup() const500 ArrayIndexT* Dup() const
501 {
502 ArrayIndexIndexed* d = new ArrayIndexIndexed( strictArrSubs);
503
504 assert( ix == NULL);
505 assert( ixDim == NULL);
506
507 d->sInit = sInit;
508 d->s = s;
509 // d->maxVal = maxVal;
510
511 return d;
512 }
513
Clear()514 void Clear()
515 {
516 // maxVal = 0;
517 // delete ixDim;
518 ixDim = NULL;
519 // delete ix;
520 ix = NULL; // marker ONE or INDEXED
521 }
522
Init(BaseGDL * ix_)523 void Init( BaseGDL* ix_)
524 {
525 if( ix_->Rank() == 0) // type ONE
526 {
527 ix_->Scalar2RangeT(sInit);
528 s = sInit; // in case of assoc NIter is not called
529 // int ret = ix_->Scalar2RangeT(s);
530 // from GDL 0.9 on negative indices are fine
531 // if( ret == -1) // index < 0
532 // {
533 // throw
534 // GDLException(-1,NULL, "Subscript range values of the"
535 // " form low:high must be >= 0, < size,"
536 // " with low <= high.",true,false);
537 // }
538 return;
539 }
540
541 // type INDEXED
542 DType dType = ix_->Type();
543
544 assert( dType != GDL_UNDEF);
545 // assert( maxVal == 0);
546
547 int typeCheck = DTypeOrder[ dType];
548 if( typeCheck >= 100)
549 throw GDLException(-1, NULL,"Type not allowed as subscript.",true,false);
550
551 //SizeT nElem = ix_->N_Elements();
552 // ix = new SizeT[ nElem]; // allocate array
553
554 //DEBUG if( ix != NULL)
555 assert( ix == NULL);
556
557 // ix = new AllIxMultiT( nElem);
558 if( strictArrSubs)
559 ix = new (ixBuf) AllIxIndicesStrictT( ix_);
560 else
561 ix = new (ixBuf) AllIxIndicesT( ix_);
562
563 ixDim = &ix_->Dim();
564 }
565
566 // number of iterations
567 // also checks/adjusts range
NIter(SizeT varDim)568 SizeT NIter( SizeT varDim)
569 {
570 if( ix == NULL) // ONE
571 {
572 if( sInit < 0)
573 s = sInit + varDim;
574 else
575 s = sInit;
576
577 if( s < 0)
578 throw GDLException(-1, NULL,"Subscript out of range [-i].",true,false);
579 if( s >= varDim && s > 0)
580 throw GDLException(-1, NULL,"Subscript out of range [i].",true,false);
581 return 1;
582 }
583 // INDEXED
584 ix->SetUpper( varDim-1);
585 return ix->size();
586 }
587 }; // class ArrayIndexIndexed: public ArrayIndexT
588
589 // INDEXED or ONE [v] (must handle both)
590 class CArrayIndexIndexed: public ArrayIndexT
591 {
592 private:
593 bool strictArrSubs; // for compile_opt STRICTARRSUBS
594
595 RangeT sInit; // can be < 0 as well
596 RangeT s;
597
598 AllIxIndicesT* ix;
599 char ixBuf[ AllIxMaxSize];
600
601 const dimension* ixDim; // keep dimension of ix
602
603 // forbid c-i
CArrayIndexIndexed(const ArrayIndexT & r)604 CArrayIndexIndexed( const ArrayIndexT& r) { assert(false);}
605
606 BaseGDL* rawData;
607 bool isScalar;
608
609 public:
Type()610 IndexType Type() { return CArrayIndexIndexedID;}
611
OverloadIndexNew()612 BaseGDL* OverloadIndexNew()
613 {
614 assert( rawData != NULL);
615 return rawData->Dup();
616 }
617
NParam()618 SizeT NParam() { return 0;} // number of parameter to Init(...)
619
GetS()620 RangeT GetS()
621 {
622 return s;
623 }
624
Scalar() const625 bool Scalar() const { return isScalar;}
Scalar(RangeT & s_) const626 bool Scalar( RangeT& s_) const // changed from RangeT for proper overloading
627 {
628 if( isScalar)
629 {
630 s_ = s;
631 return true;
632 }
633 s_ = (*ix)[0];
634 return (ix->size() == 1);
635 }
636
Indexed()637 bool Indexed() { return !isScalar;}
638
GetDim()639 const dimension& GetDim() { assert(ixDim != NULL); return *ixDim;}
640
GetIx0()641 RangeT GetIx0()
642 {
643 if( !isScalar) return (*ix)[0]; // from array
644 return s;
645 }
646
GetIx(SizeT i)647 SizeT GetIx( SizeT i)
648 {
649 assert( ix != NULL);
650 return (*ix)[ i];
651 }
652
653 // SizeT* StealIx() { SizeT* ret = ix; ix = NULL; return ret;}
654 //AllIxIndicesT* StealIx() { AllIxIndicesT* ret = ix; ix = NULL; return ret;}
GetAllIx() const655 AllIxIndicesT* GetAllIx() const
656 {
657 return ix;
658 }
659
~CArrayIndexIndexed()660 ~CArrayIndexIndexed()
661 {
662 delete rawData;
663 }
664
665 // grabs c
CArrayIndexIndexed(BaseGDL * c,bool strictArrSubs_=false)666 CArrayIndexIndexed( BaseGDL* c, bool strictArrSubs_ = false)
667 : strictArrSubs( strictArrSubs_)
668 , ix( NULL), ixDim( NULL)
669 , rawData( c)
670 {
671 assert( rawData != NULL);
672
673 if( rawData->Rank() == 0) // type ONE
674 {
675 rawData->Scalar2RangeT(sInit);
676 s = sInit; // in case of assoc NIter is not called
677 isScalar = true;
678 return;
679 }
680
681 // type INDEXED
682 isScalar = false;;
683
684 ixDim = &rawData->Dim();
685
686 assert( rawData->Type() != GDL_UNDEF);
687 DType dType = rawData->Type();
688 int typeCheck = DTypeOrder[ dType];
689 if( typeCheck >= 100)
690 throw GDLException(-1, NULL,"Type not allowed as subscript.",true,false);
691
692 if( strictArrSubs)
693 ix = new (ixBuf) AllIxIndicesStrictT( rawData);
694 else
695 ix = new (ixBuf) AllIxIndicesT( rawData);
696 }
697
Dup() const698 ArrayIndexT* Dup() const
699 {
700 return new CArrayIndexIndexed( rawData->Dup(), strictArrSubs);
701 }
702
Clear()703 void Clear()
704 {} // nothing to clear
705
Init()706 void Init()
707 {} // already initialized in constructor
708
709 // number of iterations
710 // also checks/adjusts range
NIter(SizeT varDim)711 SizeT NIter( SizeT varDim)
712 {
713 if( isScalar) // ONE
714 {
715 if( sInit < 0)
716 s = sInit + varDim;
717 else
718 s = sInit;
719
720 if( s < 0)
721 throw GDLException(-1, NULL,"Subscript out of range [-i].",true,false);
722 if( s >= varDim && s > 0)
723 throw GDLException(-1, NULL,"Subscript out of range [i].",true,false);
724 return 1;
725 }
726 // INDEXED
727 ix->SetUpper( varDim-1);
728 return ix->size();
729 }
730 }; //class CArrayIndexIndexed: public ArrayIndexIndexed
731
732
733
734 // [*]
735 class ArrayIndexAll: public ArrayIndexT
736 {
737 public:
Type()738 IndexType Type() { return ArrayIndexAllID;}
739
IsRange()740 bool IsRange() { return true;}
741
OverloadIndexNew()742 BaseGDL* OverloadIndexNew()
743 {
744 const DLong arr[3] = {0,-1,1};
745 return new DLongGDL( arr, 3);
746 }
747
NParam()748 SizeT NParam() { return 0;} // number of parameter to Init(...)
749
Init()750 void Init() {};
751
GetIx0()752 RangeT GetIx0() { return 0;}
753
Dup() const754 ArrayIndexT* Dup() const
755 {
756 return new ArrayIndexAll();
757 }
758
759 // number of iterations
760 // also checks/adjusts range
NIter(SizeT varDim)761 SizeT NIter( SizeT varDim)
762 {
763 return varDim;
764 }
765 };
766
767
768
769 // [s:*]
770 class ArrayIndexORange: public ArrayIndexT
771 {
772 protected:
773 RangeT sInit;
774 RangeT s;
775
776 public:
Type()777 IndexType Type() { return ArrayIndexORangeID;}
778
IsRange()779 bool IsRange() { return true;}
780
OverloadIndexNew(BaseGDL * s_)781 BaseGDL* OverloadIndexNew( BaseGDL* s_)
782 {
783 Init( s_);
784 DLong arr[3] = {static_cast<DLong>(sInit),-1,1};
785 return new DLongGDL( arr, 3);
786 }
787
NParam()788 SizeT NParam() { return 1;} // number of parameter to Init(...)
789
GetS()790 RangeT GetS() { return s;}
GetIx0()791 RangeT GetIx0() { return s;}
792
Dup() const793 ArrayIndexT* Dup() const
794 {
795 ArrayIndexORange* d = new ArrayIndexORange();
796 d->sInit = sInit;
797 d->s = s;
798 return d;
799 }
800
801 // s is always scalar here
Init(BaseGDL * s_)802 void Init( BaseGDL* s_)
803 {
804 int retMsg=s_->Scalar2RangeT(sInit);
805 if( retMsg == 0) // index empty or array
806 {
807 if( s_->N_Elements() == 0)
808 throw
809 GDLException(-1,NULL,"Internal error: Scalar2RangeT:"
810 " 1st index empty",true,false);
811 else
812 throw
813 GDLException(-1,NULL,"Expression must be a scalar"
814 " in this context.",true,false);
815 }
816 // s = sInit; // for assoc
817
818 // not with Scalar2RangeT():
819 // if( retMsg == -1) // index < 0
820 // {
821 // throw
822 // GDLException(-1,NULL,"Subscript range values of the"
823 // " form low:high must be >= 0, < size, "
824 // "with low <= high.",true,false);
825 // }
826 }
827
NIter(SizeT varDim)828 SizeT NIter( SizeT varDim)
829 {
830 if( sInit >= varDim) // && s > 0)
831 throw GDLException(-1,NULL,"Subscript out of range [s:*].",true,false);
832 if( sInit < 0)
833 {
834 s = sInit + varDim;
835 if( s < 0)
836 throw GDLException(-1,NULL,"Subscript out of range [-s:*].",true,false);
837
838 return (varDim - s);
839 }
840 s = sInit;
841 return (varDim - s);
842 }
843 };
844
845
846
847 class CArrayIndexORange: public ArrayIndexORange
848 {
849 public:
Type()850 IndexType Type() { return CArrayIndexORangeID;}
851
IsRange()852 bool IsRange() { return true;}
853
OverloadIndexNew()854 BaseGDL* OverloadIndexNew()
855 {
856 DLong arr[3] = {static_cast<DLong>(sInit),-1,1};
857 return new DLongGDL( arr, 3);
858 }
859
NParam()860 SizeT NParam() { return 0;} // number of parameter to Init(...)
861
CArrayIndexORange(BaseGDL * c)862 CArrayIndexORange( BaseGDL* c): ArrayIndexORange()
863 {
864 ArrayIndexORange::Init( c);
865 }
866
CArrayIndexORange()867 CArrayIndexORange() {}
868
Dup() const869 ArrayIndexT* Dup() const
870 {
871 CArrayIndexORange* d = new CArrayIndexORange();
872 d->sInit = sInit;
873 d->s = s;
874 return d;
875 }
876
877 };
878
879
880
881 // [s:e]
882 class ArrayIndexRange: public ArrayIndexT
883 {
884 protected:
885 RangeT sInit,eInit;
886 RangeT s,e;
887
888 public:
Type()889 IndexType Type() { return ArrayIndexRangeID;}
890
IsRange()891 bool IsRange() { return true;}
892
OverloadIndexNew(BaseGDL * s_,BaseGDL * e_)893 BaseGDL* OverloadIndexNew( BaseGDL* s_, BaseGDL* e_)
894 {
895 Init( s_, e_);
896 DLong arr[3] = {static_cast<DLong>(sInit),static_cast<DLong>(eInit),1};
897 return new DLongGDL( arr, 3);
898 }
899
NParam()900 SizeT NParam() { return 2;} // number of parameter to Init(...)
901
GetS()902 RangeT GetS() { return s;}
GetIx0()903 RangeT GetIx0() { return s;}
904
Dup() const905 ArrayIndexT* Dup() const
906 {
907 ArrayIndexRange* d = new ArrayIndexRange();
908 d->sInit = sInit;
909 d->eInit = eInit;
910 d->s = s;
911 d->e = e;
912 return d;
913 }
914
Init(BaseGDL * s_,BaseGDL * e_)915 void Init( BaseGDL* s_, BaseGDL* e_)
916 {
917 // SizeT varSize = var->N_Elements()/*var->Size()*/;
918
919 int retMsg=s_->Scalar2RangeT(sInit);
920 if( retMsg == 0) // index empty or array
921 {
922 if( s_->N_Elements() == 0)
923 throw
924 GDLException(-1,NULL,"Internal error: Scalar2RangeT: 1st index empty.",true,false);
925 else
926 throw
927 GDLException(-1,NULL,"Expression must be a scalar in this context.",true,false);
928 }
929 // if( retMsg == -1) // index < 0
930 // {
931 // throw
932 // GDLException(-1,NULL,"Subscript range values of the form low:high "
933 // "must be >= 0, < size, with low <= high.",true,false);
934 // }
935
936 retMsg=e_->Scalar2RangeT(eInit);
937 if( retMsg == 0) // index empty or array
938 {
939 if( e_->N_Elements() == 0)
940 throw
941 GDLException(-1,NULL,"Internal error: Scalar2RangeT: 2nd index empty.",true,false);
942 else
943 throw
944 GDLException(-1,NULL,"Expression must be a scalar in this context.",true,false);
945 }
946 }
947
948 // number of iterations
949 // also checks/adjusts range
NIter(SizeT varDim)950 SizeT NIter( SizeT varDim)
951 {
952 // RangeT sl,el;
953 if( sInit < 0)
954 {
955 s = sInit + varDim;
956 if( s < 0)
957 throw GDLException(-1,NULL,"Subscript out of range [S:e].",true,false);
958 }
959 else
960 s = sInit;
961 if( eInit < 0)
962 {
963 e = eInit + varDim;
964 if( e < 0)
965 throw GDLException(-1,NULL,"Subscript out of range [s:E].",true,false);
966 }
967 else
968 e = eInit;
969
970 if( s > e)
971 throw
972 GDLException(-1,NULL,"Subscript range values of the form low:high "
973 "must be < size, with low <= high",true,false);
974 if( e >= varDim) // && e > 0)
975 throw GDLException(-1,NULL,"Subscript out of range [s:e].",true,false);
976 return (e - s + 1);
977 }
978 };
979
980
981
982 class CArrayIndexRange: public ArrayIndexRange
983 {
984 public:
Type()985 IndexType Type() { return CArrayIndexRangeID;}
986
IsRange()987 bool IsRange() { return true;}
988
OverloadIndexNew()989 BaseGDL* OverloadIndexNew()
990 {
991 DLong arr[3] = {static_cast<DLong>(sInit),static_cast<DLong>(eInit),1};
992 return new DLongGDL( arr, 3);
993 }
994
NParam()995 SizeT NParam() { return 0;} // number of parameter to Init(...)
996
CArrayIndexRange(BaseGDL * c1,BaseGDL * c2)997 CArrayIndexRange( BaseGDL* c1, BaseGDL* c2): ArrayIndexRange()
998 {
999 ArrayIndexRange::Init( c1, c2);
1000 }
1001
CArrayIndexRange()1002 CArrayIndexRange(){}
1003
Dup() const1004 ArrayIndexT* Dup() const
1005 {
1006 CArrayIndexRange* d = new CArrayIndexRange();
1007 d->sInit = sInit;
1008 d->eInit = eInit;
1009 d->s = s;
1010 d->e = e;
1011 return d;
1012 }
1013
1014 };
1015
1016
1017
1018 // [s:*:st]
1019 class ArrayIndexORangeS: public ArrayIndexT
1020 {
1021 protected:
1022 RangeT sInit;
1023 RangeT s;
1024 SizeT stride;
1025
1026 public:
Type()1027 IndexType Type() { return ArrayIndexORangeSID;}
1028
IsRange()1029 bool IsRange() { return true;}
1030
OverloadIndexNew(BaseGDL * s_,BaseGDL * stride_)1031 BaseGDL* OverloadIndexNew( BaseGDL* s_, BaseGDL* stride_)
1032 {
1033 Init( s_, stride_);
1034 DLong arr[3] = {static_cast<DLong>(sInit),-1,static_cast<DLong>(stride)};
1035 return new DLongGDL( arr, 3);
1036 }
1037
NParam()1038 SizeT NParam() { return 2;} // number of parameter to Init(...)
1039
GetS()1040 RangeT GetS() { return s;}
GetStride()1041 SizeT GetStride() { return stride;}
GetIx0()1042 RangeT GetIx0() { return s;}
1043
Dup() const1044 ArrayIndexT* Dup() const
1045 {
1046 ArrayIndexORangeS* d = new ArrayIndexORangeS();
1047 d->sInit = sInit;
1048 d->s = s;
1049 d->stride = stride;
1050 return d;
1051 }
1052
Init(BaseGDL * s_,BaseGDL * stride_)1053 void Init( BaseGDL* s_, BaseGDL* stride_)
1054 {
1055 int retMsg=s_->Scalar2RangeT( sInit);
1056 if( retMsg == 0) // index empty or array
1057 {
1058 if( s_->N_Elements() == 0)
1059 throw
1060 GDLException( "Internal error: Scalar2RangeT:"
1061 " 1st index empty",true,false);
1062 else
1063 throw
1064 GDLException( "Expression must be a scalar"
1065 " in this context.",true,false);
1066 }
1067 // if( retMsg == -1) // index < 0
1068 // {
1069 // throw
1070 // GDLException( "Subscript range values of the"
1071 // " form low:high must be >= 0, < size, with low <= high.",true,false);
1072 // }
1073 // stride
1074 retMsg=stride_->Scalar2Index( stride);
1075 if( retMsg == 0) // index empty or array
1076 {
1077 if( stride_->N_Elements() == 0)
1078 throw
1079 GDLException( "Internal error: Scalar2Index:"
1080 " stride index empty",true,false);
1081 else
1082 throw
1083 GDLException( "Expression must be a scalar"
1084 " in this context.",true,false);
1085 }
1086 if( retMsg == -1 || stride == 0) // stride <= 0
1087 {
1088 throw
1089 GDLException( "Range subscript stride must be >= 1.",true,false);
1090 }
1091 }
1092
1093 // number of iterations
1094 // also checks/adjusts range
NIter(SizeT varDim)1095 SizeT NIter( SizeT varDim)
1096 {
1097 if( sInit < 0)
1098 {
1099 s = sInit + varDim;
1100 if( s < 0)
1101 throw GDLException(-1,NULL,"Subscript out of range [-S:*:stride].",true,false);
1102 return (varDim - s + stride - 1)/stride;
1103 }
1104 else
1105 s= sInit;
1106
1107 if( s >= varDim) // && s > 0)
1108 throw GDLException(-1,NULL,"Subscript out of range [s:*:stride].",true,false);
1109 return (varDim - s + stride - 1)/stride;
1110 }
1111 };
1112
1113 class CArrayIndexORangeS: public ArrayIndexORangeS
1114 {
1115 public:
Type()1116 IndexType Type() { return CArrayIndexORangeSID;}
1117
IsRange()1118 bool IsRange() { return true;}
1119
OverloadIndexNew()1120 BaseGDL* OverloadIndexNew()
1121 {
1122 DLong arr[3] = {static_cast<DLong>(sInit),-1,static_cast<DLong>(stride)};
1123 return new DLongGDL( arr, 3);
1124 }
1125
NParam()1126 SizeT NParam() { return 0;} // number of parameter to Init(...)
1127
CArrayIndexORangeS(BaseGDL * c1,BaseGDL * c2)1128 CArrayIndexORangeS( BaseGDL* c1, BaseGDL* c2): ArrayIndexORangeS()
1129 {
1130 ArrayIndexORangeS::Init( c1, c2);
1131 }
1132
CArrayIndexORangeS()1133 CArrayIndexORangeS(){}
1134
Dup() const1135 ArrayIndexT* Dup() const
1136 {
1137 CArrayIndexORangeS* d = new CArrayIndexORangeS();
1138 d->sInit = sInit;
1139 d->s = s;
1140 d->stride = stride;
1141 return d;
1142 }
1143
1144 };
1145
1146 // [s:e:st]
1147 class ArrayIndexRangeS: public ArrayIndexT
1148 {
1149 protected:
1150 RangeT sInit,eInit;
1151 RangeT s,e;
1152 SizeT stride;
1153
Init(DLong s_,DLong e_,DLong stride_)1154 void Init( DLong s_, DLong e_, DLong stride_)
1155 {
1156 sInit = s_;
1157 eInit = e_;
1158 if( stride_ <= 0)
1159 {
1160 throw
1161 GDLException( "Range subscript stride must be >= 1.",true,false);
1162 }
1163 stride = stride_;
1164 }
1165
1166 public:
Type()1167 IndexType Type() { return ArrayIndexRangeSID;}
1168
IsRange()1169 bool IsRange() { return true;}
1170
OverloadIndexNew(BaseGDL * s_,BaseGDL * e_,BaseGDL * stride_)1171 BaseGDL* OverloadIndexNew( BaseGDL* s_, BaseGDL* e_, BaseGDL* stride_)
1172 {
1173 Init( s_, e_, stride_);
1174 DLong arr[3] = {static_cast<DLong>(sInit),static_cast<DLong>(eInit),static_cast<DLong>(stride)};
1175 return new DLongGDL( arr, 3);
1176 }
1177
NParam()1178 SizeT NParam() { return 3;} // number of parameter to Init(...)
1179
GetS()1180 RangeT GetS() { return s;}
GetStride()1181 SizeT GetStride() { return stride;}
GetIx0()1182 RangeT GetIx0() { return s;}
1183
Dup() const1184 ArrayIndexT* Dup() const
1185 {
1186 ArrayIndexRangeS* d = new ArrayIndexRangeS();
1187 d->sInit = sInit;
1188 d->eInit = eInit;
1189 d->s = s;
1190 d->e = e;
1191 d->stride = stride;
1192 return d;
1193 }
1194
Init(BaseGDL * s_,BaseGDL * e_,BaseGDL * stride_)1195 void Init( BaseGDL* s_, BaseGDL* e_, BaseGDL* stride_)
1196 {
1197 int retMsg=s_->Scalar2RangeT(sInit);
1198 if( retMsg == 0) // index empty or array
1199 {
1200 if( s_->N_Elements() == 0)
1201 throw
1202 GDLException( "Internal error: Scalar2RangeT: 1st index empty.",true,false);
1203 else
1204 throw
1205 GDLException( "Expression must be a scalar in this context.",true,false);
1206 }
1207 // if( retMsg == -1) // index < 0
1208 // {
1209 // throw
1210 // GDLException( "Subscript range values of the form low:high "
1211 // "must be >= 0, < size, with low <= high.",true,false);
1212 // }
1213
1214 retMsg=e_->Scalar2RangeT(eInit);
1215 if( retMsg == 0) // index empty or array
1216 {
1217 if( e_->N_Elements() == 0)
1218 throw
1219 GDLException( "Internal error: Scalar2RangeT: 2nd index empty.",true,false);
1220 else
1221 throw
1222 GDLException( "Expression must be a scalar in this context.",true,false);
1223 }
1224
1225 // stride
1226 retMsg=stride_->Scalar2Index(stride);
1227 if( retMsg == 0) // index empty or array
1228 {
1229 if( stride_->N_Elements() == 0)
1230 throw
1231 GDLException( "Internal error: Scalar2Index:"
1232 " stride index empty",true,false);
1233 else
1234 throw
1235 GDLException( "Expression must be a scalar"
1236 " in this context.",true,false);
1237 }
1238 if( retMsg == -1 || stride == 0) // stride <= 0
1239 {
1240 throw
1241 GDLException( "Range subscript stride must be >= 1.",true,false);
1242 }
1243 }
1244
1245 // number of iterations
1246 // also checks/adjusts range
NIter(SizeT varDim)1247 SizeT NIter( SizeT varDim)
1248 {
1249 // RangeT sl,el;
1250 if( sInit < 0)
1251 {
1252 s = sInit + varDim;
1253 if( s < 0)
1254 throw GDLException(-1,NULL,"Subscript out of range [-S:e:stride].",true,false);
1255 }
1256 else
1257 s = sInit;
1258 if( eInit < 0)
1259 {
1260 e = eInit + varDim;
1261 if( e < 0)
1262 throw GDLException(-1,NULL,"Subscript out of range [s:-E:stride].",true,false);
1263 }
1264 else
1265 e = eInit;
1266
1267 if( s > e)
1268 throw
1269 GDLException(-1,NULL,"Subscript range values of the form low:high "
1270 "must be < size, with low <= high",true,false);
1271
1272 if( e >= varDim) // && e > 0)
1273 {
1274 throw GDLException(-1,NULL,"Subscript out of range [s:E:st].",true,false);
1275 }
1276 return (e - s + stride)/stride;
1277 }
1278 };
1279
1280 class CArrayIndexRangeS: public ArrayIndexRangeS
1281 {
1282 public:
Type()1283 IndexType Type() { return CArrayIndexRangeSID;}
1284
IsRange()1285 bool IsRange() { return true;}
1286
OverloadIndexNew()1287 BaseGDL* OverloadIndexNew()
1288 {
1289 DLong arr[3] = {static_cast<DLong>(sInit),static_cast<DLong>(eInit),static_cast<DLong>(stride)};
1290 return new DLongGDL( arr, 3);
1291 }
1292
NParam()1293 SizeT NParam() { return 0;} // number of parameter to Init(...)
1294
CArrayIndexRangeS(BaseGDL * c1,BaseGDL * c2,BaseGDL * c3)1295 CArrayIndexRangeS( BaseGDL* c1, BaseGDL* c2, BaseGDL* c3):
1296 ArrayIndexRangeS()
1297 {
1298 ArrayIndexRangeS::Init( c1, c2, c3);
1299 }
1300
1301 // for internal routines to ease definition
CArrayIndexRangeS(DLong s_,DLong e_,DLong stride_)1302 CArrayIndexRangeS( DLong s_, DLong e_, DLong stride_):
1303 ArrayIndexRangeS()
1304 {
1305 ArrayIndexRangeS::Init( s_, e_, stride_);
1306 }
1307
CArrayIndexRangeS()1308 CArrayIndexRangeS(){}
1309
Dup() const1310 ArrayIndexT* Dup() const
1311 {
1312 CArrayIndexRangeS* d = new CArrayIndexRangeS();
1313 d->sInit = sInit;
1314 d->eInit = eInit;
1315 d->s = s;
1316 d->e = e;
1317 d->stride = stride;
1318 return d;
1319 }
1320
1321 };
1322
1323 #endif
1324