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