1 /***************************************************************************
2                           arrayindexlistnoassoct.hpp  -  array access descriptor,
3 			  optimization for non assoc index
4                           -------------------
5     begin                : July 22 2005
6     copyright            : (C) 2002 by Marc Schellens
7     email                : m_schellens@users.sf.net
8  ***************************************************************************/
9 
10 /***************************************************************************
11  *                                                                         *
12  *   This program is free software; you can redistribute it and/or modify  *
13  *   it under the terms of the GNU General Public License as published by  *
14  *   the Free Software Foundation; either version 2 of the License, or     *
15  *   (at your option) any later version.                                   *
16  *                                                                         *
17  ***************************************************************************/
18 
19 #ifndef ARRAYINDEXLISTNOASSOCT_HPP_
20 #define ARRAYINDEXLISTNOASSOCT_HPP_
21 
22 #include "arrayindex.hpp"
23 
24 // this is the main file for non assco arrayindices,
25 // this classes here must only be used with non-assoc variables
26 // the classes in arrayindexlistt.hpp can handle both, because
27 // as ASSOC variables are connected to files, a few more checks
28 // do not hurt, other than here: These are the core routines for indexing
29 
30 // only one index [ix],[s:e],...
31 // NEVER ArrayIndexScalar types (they have their own ArrayIndexListT)
32 class ArrayIndexListOneNoAssocT: public ArrayIndexListT
33 {
34 private:
35   IxExprListT cleanupIx;
36 
37   ArrayIndexT* ix;
38 
39   SizeT    nIx;                  // number of indexed elements
40 
41   AllIxBaseT* allIx;
42 
43   char allIxInstance[ AllIxMaxSize];
44 
45 public:
46 
~ArrayIndexListOneNoAssocT()47   ~ArrayIndexListOneNoAssocT()
48   {
49 //     delete allIx;
50     delete ix;
51     cleanupIx.Cleanup(); // must be explicitely cleaned up
52   }
53 
54   // constructor
ArrayIndexListOneNoAssocT()55   ArrayIndexListOneNoAssocT()
56 	: cleanupIx()
57     , ix( NULL)
58     , allIx( NULL)
59   { nParam = 0;}
60 
ArrayIndexListOneNoAssocT(const ArrayIndexListOneNoAssocT & cp)61   ArrayIndexListOneNoAssocT( const ArrayIndexListOneNoAssocT& cp):
62     ArrayIndexListT( cp),
63 	cleanupIx(),
64     ix( cp.ix->Dup()),
65     allIx( NULL)
66   {
67     assert( cp.allIx == NULL);
68 	assert( cp.cleanupIx.size() == 0);
69   }
70 
71   // called after structure is fixed
ArrayIndexListOneNoAssocT(ArrayIndexVectorT * aIV)72   ArrayIndexListOneNoAssocT( ArrayIndexVectorT* aIV):
73     allIx( NULL)
74   {
75     ix = (*aIV)[0]->Dup(); // ArrayIndexListOneT will grab here
76     nParam = ix->NParam();
77   }
78 
Clear()79   void Clear()
80   {
81   //     delete allIx;
82     allIx = NULL;
83   //     allIxMulti.Clear();
84     ix->Clear();
85     cleanupIx.Cleanup();
86   }
87 
Clone()88   ArrayIndexListT* Clone() { return new ArrayIndexListOneNoAssocT( *this);}
89 
GetCleanupIx()90   IxExprListT* GetCleanupIx() { return &cleanupIx;}
InitAsOverloadIndex(IxExprListT & ix_,IxExprListT & ixOut)91   void InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut)
92   {
93     assert( allIx == NULL);
94     assert( ix_.size() == nParam);
95 
96 //     if( cleanupIxIn != NULL)
97 //       cleanupIx = *cleanupIxIn;
98 
99     DLongGDL* isRange = new DLongGDL( dimension(1), BaseGDL::NOZERO);
100     ixOut.push_back(isRange);
101 
102     (*isRange)[ 0] = (ix->IsRange()) ? 1 : 0;
103     if( nParam == 0)
104       {
105 	BaseGDL* oIx = ix->OverloadIndexNew();
106 	ixOut.push_back(oIx);
107 	return;
108       }
109     if( nParam == 1)
110       {
111 	BaseGDL* oIx = ix->OverloadIndexNew( ix_[ 0]);
112 	ixOut.push_back(oIx);
113 	return;
114       }
115     if( nParam == 2)
116       {
117 	BaseGDL* oIx = ix->OverloadIndexNew( ix_[ 0], ix_[ 1]);
118 	ixOut.push_back(oIx);
119 	return;
120       }
121     if( nParam == 3)
122       {
123 	BaseGDL* oIx = ix->OverloadIndexNew( ix_[ 0], ix_[ 1], ix_[ 2]);
124 	ixOut.push_back(oIx);
125 	return;
126       }
127   }
128 
Init(IxExprListT & ix_)129   void Init( IxExprListT& ix_)//, IxExprListT* cleanupIxIn)
130   {
131     assert( allIx == NULL);
132     assert( ix_.size() == nParam);
133 
134 //     if( cleanupIxIn != NULL)
135 //       cleanupIx = *cleanupIxIn;
136 
137     if( nParam == 0) //return;
138       {
139 	ix->Init();
140 	return;
141       }
142     if( nParam == 1)
143       {
144 	ix->Init( ix_[ 0]);
145 	return;
146       }
147     if( nParam == 2)
148       {
149 	ix->Init( ix_[ 0], ix_[ 1]);
150 	return;
151       }
152     else // nParam == 3
153       {
154 	assert( nParam == 3);
155 	ix->Init( ix_[ 0], ix_[ 1], ix_[ 2]);
156 	return;
157       }
158   }
159 
Init()160   void Init() {} // eg. a[*]
161 
162   // requires special handling
163   // used by Assoc_<> returns last index in lastIx, removes it
164   // and returns true is the list is empty
165 //   bool ToAssocIndex( SizeT& lastIx)
ToAssocIndex(SizeT & lastIx)166   bool ToAssocIndex( SizeT& lastIx)
167   {
168     assert( 0);
169     throw GDLException(-1,NULL,"Internal error: ArrayIndexListOneNoAssocT::ToAssocIndex(...) called.",true,false);
170     return true;
171   }
172 
173   // set the root variable which is indexed by this ArrayIndexListT
SetVariable(BaseGDL * var)174   void SetVariable( BaseGDL* var)
175   {
176     assert( allIx == NULL);
177 
178     // for assoc variables last index is the record
179 //     if( var->IsAssoc()) return;
180 
181     // ArrayIndexScalar[VP] are not initialized
182     // they need the NIter call, but
183     // for only one index they have their own ArrayIndexListT
184     nIx=ix->NIter( var->N_Elements()/*var->Size()*/);
185   }
186 
187   // structure of indexed expression
GetDim()188   const dimension GetDim()
189   {
190     if( ix->Scalar())
191       {
192 		return dimension();
193       }
194     else if( ix->Indexed())
195       {
196 	return static_cast<ArrayIndexIndexed*>(ix)->GetDim();
197 	// gets structure of indexing array
198       }
199     else
200       {
201 	return dimension( nIx); // one dimensional if not indexed
202       }
203   }
204 
N_Elements()205   SizeT N_Elements()
206   {
207     return nIx;
208   }
209 
210   // returns 1-dim index for all elements
BuildIx()211   AllIxBaseT* BuildIx()
212   {
213     if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign()
214       return allIx;
215 
216     assert( allIx == NULL);
217 //     if( allIx != NULL)
218 // 		return allIx;
219 
220     if( ix->Indexed())
221       {
222 //	allIx = static_cast< ArrayIndexIndexed*>(ix)->StealIx();
223 	allIx = static_cast< ArrayIndexIndexed*>(ix)->GetAllIx();
224 	return allIx;
225       }
226 
227     if( nIx == 1)
228     {
229 	    allIx = new (allIxInstance) AllIxT( ix->GetS());
230 	    return allIx;
231     }
232 
233 // 	allIx = new AllIxMulAllIxRangeStrideTtiT( nIx);
234     SizeT s = ix->GetS();
235     SizeT ixStride = ix->GetStride();
236     if( ixStride <= 1)
237       if( s != 0)
238 	    {
239 	    allIx = new (allIxInstance) AllIxRangeT( nIx, s);
240 // 	    for( SizeT i=0; i<nIx; ++i)
241 // 			static_cast<AllIxMultiT*>(allIx)->SetIx( i, i + s);
242 // 	      (*allIx)[i] = i + s;
243 	    }
244       else
245 	    {
246 	    allIx = new (allIxInstance) AllIxRange0T( nIx);
247 // 	    for( SizeT i=0; i<nIx; ++i)
248 // 			static_cast<AllIxMultiT*>(allIx)->SetIx( i, i );
249 // 	      (*allIx)[i] = i;
250 	    }
251     else
252       if( s != 0)
253 	{
254 	    allIx = new (allIxInstance) AllIxRangeStrideT( nIx, s, ixStride);
255 // 	    for( SizeT i=0; i<nIx; ++i)
256 // 			static_cast<AllIxMultiT*>(allIx)->SetIx( i, i * ixStride + s);
257 // 	      (*allIx)[i] = i * ixStride + s;
258 	    }
259       else
260 	    {
261 	    allIx = new (allIxInstance) AllIxRange0StrideT( nIx, ixStride);
262 // 	    for( SizeT i=0; i<nIx; ++i)
263 // 			static_cast<AllIxMultiT*>(allIx)->SetIx( i, i * ixStride);
264 // 	      (*allIx)[i] = i * ixStride;
265 	    }
266     return allIx;
267   }
268 
269   // returns one dim long ix in case of one element array index
270   // used by AssignAt functions
LongIx() const271   SizeT LongIx() const
272   {
273     return ix->GetIx0();
274   }
275 
AssignAt(BaseGDL * var,BaseGDL * right)276   void AssignAt( BaseGDL* var, BaseGDL* right)
277   {
278     // scalar case
279     if( right->N_Elements() == 1 && //!var->IsAssoc() &&
280 	ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT)
281       {
282 	var->AssignAtIx( ix->GetIx0(), right);
283 	return;
284       }
285 
286     SetVariable( var);
287 
288     if( var->EqType( right))
289       {
290 	var->AssignAt( right, this); // assigns inplace
291       }
292     else
293       {
294 	BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY);
295 	Guard<BaseGDL> conv_guard( rConv);
296 
297 	var->AssignAt( rConv, this); // assigns inplace
298       }
299   }
300 
301   // optimized for one dimensional access
Index(BaseGDL * var,IxExprListT & ix_)302   BaseGDL* Index( BaseGDL* var, IxExprListT& ix_)
303   {
304     Init( ix_);//, NULL);
305     if( ix->Scalar())// && ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT)
306 //     if( !var->IsAssoc() && ix->NIter( var->N_Elements()/*var->Size()*/) == 1)// && var->Type() != GDL_STRUCT)
307       {
308 	SizeT assertValue = ix->NIter( var->N_Elements()/*var->Size()*/);
309 	assert( assertValue == 1);
310 
311 	return var->NewIx( ix->GetIx0());
312       }
313     // normal case
314     SetVariable( var);
315     return var->Index( this);
316   }
317 
318   // returns multi-dim index for 1st element
319   // used by InsAt functions
GetDimIx0(SizeT & destStart)320   const dimension GetDimIx0( SizeT& destStart)
321   {
322     destStart = ix->GetIx0();
323 
324     return dimension( destStart);
325   }
326 
NDim()327   SizeT NDim()
328   {
329     return 1;
330   }
331 }; //class ArrayIndexListOneT: public ArrayIndexListT
332 
333 
334 
335 
336 
337 // loop index
338 class ArrayIndexListOneScalarNoAssocT: public ArrayIndexListT
339 {
340 protected:
341   SizeT varIx;
342   RangeT sInit;
343   RangeT s;
344 
345   AllIxT allIx;
346 
347 public:
348 
~ArrayIndexListOneScalarNoAssocT()349   ~ArrayIndexListOneScalarNoAssocT() {}
350 
351   // constructor
ArrayIndexListOneScalarNoAssocT()352   ArrayIndexListOneScalarNoAssocT()
353     : varIx( 0)
354 //     , allIx( NULL)
355   { nParam = 0;}
356 
ArrayIndexListOneScalarNoAssocT(const ArrayIndexListOneScalarNoAssocT & cp)357   ArrayIndexListOneScalarNoAssocT( const ArrayIndexListOneScalarNoAssocT& cp)
358     : ArrayIndexListT( cp)
359     , varIx( cp.varIx)
360     , s( cp.s)
361 //     , allIx( NULL)
362   {
363 //     assert( cp.allIx == NULL);
364   }
365 
366   // called after structure is fixed
ArrayIndexListOneScalarNoAssocT(ArrayIndexVectorT * aIV)367   ArrayIndexListOneScalarNoAssocT( ArrayIndexVectorT* aIV)
368       : varIx (static_cast<ArrayIndexScalar*>((*aIV)[0])->GetVarIx())
369 //    allIx( NULL)
370   {
371     nParam = 0;
372    // cppchek says: (performance) Variable 'varIx' is assigned in constructor body. Consider performing initialization in initialization list
373 //    varIx = static_cast<ArrayIndexScalar*>((*aIV)[0])->GetVarIx();
374 
375     // ArrayIndexListOneScalarT will do the cleanup
376 //     delete (*aIV)[0];
377   }
378 
Clear()379   void Clear()
380   {}
381 
Clone()382   ArrayIndexListT* Clone() { return new ArrayIndexListOneScalarNoAssocT( *this);}
383 
384   void InitAsOverloadIndex( IxExprListT& ix_,  IxExprListT& ixOut);
385 
Init()386   void Init() {}
387 
388   // requires special handling
389   // used by Assoc_<> returns last index in lastIx, removes it
390   // and returns true is the list is empty
ToAssocIndex(SizeT & lastIx)391   bool ToAssocIndex( SizeT& lastIx) { assert( false); return false;}
392 
393   // set the root variable which is indexed by this ArrayIndexListT
394   void SetVariable( BaseGDL* var);
395 
396   // structure of indexed expression
GetDim()397   const dimension GetDim()
398   {
399     return dimension();
400   }
401 
N_Elements()402   SizeT N_Elements()
403   {
404     return 1;
405   }
406 
407   // returns 1-dim index for all elements
BuildIx()408   AllIxT* BuildIx()
409   {
410 	allIx.Set( s);
411 	return &allIx;
412 
413 //     if( allIx != NULL)
414 //       {
415 // 		allIx->Set( s);
416 // 	return allIx;
417 //       }
418 //
419 //     allIx = new AllIxT( s);
420 //     return allIx;
421   }
422 
423   // returns one dim long ix in case of one element array index
424   // used by AssignAt functions
LongIx() const425   SizeT LongIx() const
426   {
427     return s;
428   }
429 
430   void AssignAt( BaseGDL* var, BaseGDL* right);
431 
432   // optimized for one dimensional access
433   BaseGDL* Index( BaseGDL* var, IxExprListT& ix_);
434 
435   // returns multi-dim index for 1st element
436   // used by InsAt functions
GetDimIx0(SizeT & destStart)437   const dimension GetDimIx0( SizeT& destStart)
438   {
439     destStart = s;
440     return dimension( destStart);
441   }
442 
NDim()443   SizeT NDim()
444   {
445     return 1;
446   }
447 
448 }; // class ArrayIndexListOneScalarT: public ArrayIndexListT
449 
450 
451 
452 
453 
454 class ArrayIndexListOneScalarVPNoAssocT: public ArrayIndexListT
455 {
456 protected:
457   DVar* varPtr;
458 
459   RangeT sInit;
460   RangeT s;
461 
462   AllIxT allIx;
463 //   AllIxT* allIx;
464 
465 public:
466 
~ArrayIndexListOneScalarVPNoAssocT()467   ~ArrayIndexListOneScalarVPNoAssocT()
468   {
469 //     delete allIx;
470   }
471 
472   // constructor
ArrayIndexListOneScalarVPNoAssocT()473   ArrayIndexListOneScalarVPNoAssocT()
474     : varPtr( NULL)
475 //     , allIx( NULL)
476   { nParam = 0;}
477 
ArrayIndexListOneScalarVPNoAssocT(const ArrayIndexListOneScalarVPNoAssocT & cp)478   ArrayIndexListOneScalarVPNoAssocT( const ArrayIndexListOneScalarVPNoAssocT& cp)
479     : ArrayIndexListT( cp)
480     , varPtr( cp.varPtr)
481     , sInit( cp.sInit)
482     , s( cp.s)
483 //     , allIx( NULL)
484   {
485 //     assert( cp.allIx == NULL);
486   }
487 
488   // called after structure is fixed
ArrayIndexListOneScalarVPNoAssocT(ArrayIndexVectorT * aIV)489   ArrayIndexListOneScalarVPNoAssocT( ArrayIndexVectorT* aIV)
490 //     : allIx( NULL)
491   {
492     nParam = 0;
493 
494     varPtr = static_cast<ArrayIndexScalarVP*>((*aIV)[0])->GetVarPtr();
495 
496         // ArrayIndexListOneScalarVPT will do the cleanup
497 //     delete (*aIV)[0];
498   }
499 
Clear()500   void Clear()
501   {}
502 
Clone()503   ArrayIndexListT* Clone() { return new ArrayIndexListOneScalarVPNoAssocT( *this);}
504 
505   void InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut);
506 
Init()507   void Init() {}
508 
509   // requires special handling
510   // used by Assoc_<> returns last index in lastIx, removes it
511   // and returns true is the list is empty
ToAssocIndex(SizeT & lastIx)512   bool ToAssocIndex( SizeT& lastIx)
513   {
514     sInit = varPtr->Data()->LoopIndex();
515     if( sInit < 0)
516       throw GDLException(-1,NULL,"Record number must be a scalar > 0 in this context.",true,false);
517     s = sInit;
518     lastIx = s;
519     return true;
520   }
521 
522   // set the root variable which is indexed by this ArrayIndexListT
SetVariable(BaseGDL * var)523   void SetVariable( BaseGDL* var)
524   {
525     sInit = varPtr->Data()->LoopIndex();
526     if( sInit < 0)
527       s = sInit + var->N_Elements();
528     else
529       s = sInit;
530 
531     // for assoc variables last index is the record
532 //     if( var->IsAssoc()) return;
533     if( s >= var->N_Elements()/*var->Size()*/)
534       throw GDLException(-1,NULL,"Scalar subscript too large.",true,false);
535     if( s < 0)
536       throw GDLException(-1,NULL,"Scalar subscript too small (<-1).",true,false);
537   }
538 
539   // structure of indexed expression
GetDim()540   const dimension GetDim()
541   {
542     return dimension();
543   }
544 
N_Elements()545   SizeT N_Elements()
546   {
547     return 1;
548   }
549 
550   // returns 1-dim index for all elements
BuildIx()551   AllIxT* BuildIx()
552   {
553 	allIx.Set( s);
554 	return &allIx;
555 
556 //     if( allIx != NULL)
557 //       {
558 // 		allIx->Set( s);
559 // 		return allIx;
560 //       }
561 //
562 //     allIx = new AllIxT( s);
563 //     return allIx;
564   }
565 
566   // returns one dim long ix in case of one element array index
567   // used by AssignAt functions
LongIx() const568   SizeT LongIx() const
569   {
570     return s;
571   }
572 
AssignAt(BaseGDL * var,BaseGDL * right)573   void AssignAt( BaseGDL* var, BaseGDL* right)
574   {
575     // Init() was already called
576     // scalar case
577     if( right->N_Elements() == 1) // && !var->IsAssoc()) // && var->Type() != GDL_STRUCT)
578       {
579 	s = varPtr->Data()->LoopIndex();
580 	if( s >= var->N_Elements()/*var->Size()*/)
581 	  throw GDLException(-1,NULL,"Scalar subscript out of range [>].2",true,false);
582 	var->AssignAtIx( s, right);
583 	return;
584       }
585 
586     SetVariable( var);
587     if( var->EqType( right))
588       {
589 	var->AssignAt( right, this); // assigns inplace
590       }
591     else
592       {
593 	BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY);
594 	Guard<BaseGDL> conv_guard( rConv);
595 
596 	var->AssignAt( rConv, this); // assigns inplace
597       }
598   }
599 
600   // optimized for one dimensional access
601   BaseGDL* Index( BaseGDL* var, IxExprListT& ix_);
602 
603   // returns multi-dim index for 1st element
604   // used by InsAt functions
GetDimIx0(SizeT & destStart)605   const dimension GetDimIx0( SizeT& destStart)
606   {
607     destStart = s;
608     return dimension( destStart);
609   }
NDim()610   SizeT NDim()
611   {
612     return 1;
613   }
614 
615 }; // class ArrayIndexListOneScalarVPT: public ArrayIndexListT
616 
617 
618 
619 
620 
621 class ArrayIndexListOneConstScalarNoAssocT: public ArrayIndexListT
622 {
623   RangeT sInit;
624   RangeT s;
625   AllIxT allIx;
626   BaseGDL* rawData;
627 
628 public:
629 
~ArrayIndexListOneConstScalarNoAssocT()630   ~ArrayIndexListOneConstScalarNoAssocT()
631   {
632     delete rawData;
633   }
634 
635   // constructor
ArrayIndexListOneConstScalarNoAssocT()636   ArrayIndexListOneConstScalarNoAssocT()
637   : rawData( NULL)
638 // 	: allIx( NULL)
639   {
640     nParam = 0;
641   }
642 
ArrayIndexListOneConstScalarNoAssocT(const ArrayIndexListOneConstScalarNoAssocT & cp)643   ArrayIndexListOneConstScalarNoAssocT( const ArrayIndexListOneConstScalarNoAssocT& cp)
644     : ArrayIndexListT( cp)
645     , sInit( cp.sInit)
646     , s( cp.s)
647 //     , allIx( NULL)
648   {
649     assert( cp.rawData != NULL);
650     rawData = cp.rawData->Dup();
651 //     assert( cp.allIx == NULL); // all copying should be done before using.
652   }
653 
654   // called after structure is fixed
ArrayIndexListOneConstScalarNoAssocT(ArrayIndexVectorT * aIV)655   ArrayIndexListOneConstScalarNoAssocT( ArrayIndexVectorT* aIV)
656 //     : allIx( NULL)
657   {
658     assert( CArrayIndexScalarID == (*aIV)[0]->Type()); // see MakeArrayIndex (arrayindex.cpp)
659     CArrayIndexScalar* arrayIndex = static_cast<CArrayIndexScalar*>( (*aIV)[0]);
660     rawData = arrayIndex->StealRawData();
661     sInit = arrayIndex->GetS();
662     if( sInit >= 0)
663       s = sInit;
664     nParam = 0;
665 
666    // ArrayIndexListOneConstScalarT will do the cleanup
667 //     delete (*aIV)[0];
668   }
669 
InitAsOverloadIndex(IxExprListT & ix_,IxExprListT & ixOut)670   void InitAsOverloadIndex( IxExprListT& ix_, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut)
671   {
672     assert( 0 == nParam);
673     assert( rawData != NULL);
674 
675     DLongGDL* isRange = new DLongGDL( 0);
676     ixOut.push_back(isRange);
677 
678     ixOut.push_back(rawData->Dup());
679   }
680 
681 
Clear()682   void Clear()
683   {}
684 
Clone()685   ArrayIndexListT* Clone() { return new ArrayIndexListOneConstScalarNoAssocT( *this);}
686 
Init()687   void Init()
688   {}
689 
N_Elements()690   SizeT N_Elements()
691   {
692     return 1;
693   }
694 
695   // returns 1-dim index for all elements
BuildIx()696   AllIxT* BuildIx()
697   {
698 	allIx.Set( s);
699 	return &allIx;
700 
701 //     if( allIx != NULL)
702 //       return allIx;
703 //
704 //     allIx = new AllIxT( s);
705 //     return allIx;
706   }
707 
708   // requires special handling
709   // used by Assoc_<> returns last index in lastIx, removes it
710   // and returns true is the list is empty
ToAssocIndex(SizeT & lastIx)711   bool ToAssocIndex( SizeT& lastIx)
712   {
713     if( sInit < 0)
714       throw GDLException(-1,NULL,"Record number must be a scalar > 0 in this context. ("+i2s(sInit)+")",true,false);
715     lastIx = sInit;
716     return true;
717   }
718 
719   // set the root variable which is indexed by this ArrayIndexListT
SetVariable(BaseGDL * var)720   void SetVariable( BaseGDL* var)
721   {
722 //     if( var->IsAssoc()) return;
723     if( sInit < 0)
724       s = sInit + var->N_Elements()/*var->Size()*/;
725     // for assoc variables last index is the record
726     if( s < 0)
727       throw GDLException(-1,NULL,"Scalar subscript out of range [<0] ("+i2s(s)+")",true,false);
728     if( s >= var->N_Elements()/*var->Size()*/)
729       throw GDLException(-1,NULL,"Scalar subscript out of range [>] ("+i2s(s)+")",true,false);
730   }
731 
732   // returns one dim long ix in case of one element array index
733   // used by AssignAt functions
LongIx() const734   SizeT LongIx() const
735   {
736     return s;
737   }
738 
AssignAt(BaseGDL * var,BaseGDL * right)739   void AssignAt( BaseGDL* var, BaseGDL* right)
740   {
741     // one index and assoc -> no index left -> no AssignAt
742     // wrong! This is the entry function
743     // assert( !var->IsAssoc());
744 
745     // Init() was already called
746     // scalar case
747     if( right->N_Elements() == 1)// && !var->IsAssoc())// && var->Type() != GDL_STRUCT)
748       {
749 	if( sInit < 0)
750 	  s = sInit + var->N_Elements()/*var->Size()*/;
751 	if( s < 0)
752 	  throw GDLException(-1,NULL,"Scalar subscript out of range [<0]. ("+i2s(s)+")",true,false);
753 	if( s >= var->N_Elements()/*var->Size()*/)
754 	  throw GDLException(-1,NULL,"Scalar subscript out of range [>]. ("+i2s(s)+")",true,false);
755 	var->AssignAtIx( s, right); // must use COPY_BYTE_AS_INT
756 	return;
757       }
758 
759     SetVariable( var);
760     if( var->EqType( right))
761       {
762 		var->AssignAt( right, this); // assigns inplace
763       }
764     else
765       {
766 		BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY);
767 		Guard<BaseGDL> conv_guard( rConv);
768 
769 		var->AssignAt( rConv, this); // assigns inplace
770       }
771   }
772 
773   // optimized for one dimensional access
Index(BaseGDL * var,IxExprListT & ix_)774   BaseGDL* Index( BaseGDL* var, IxExprListT& ix_)
775   {
776     // Init() not called
777 //     if( !var->IsAssoc())// && var->Type() != GDL_STRUCT)
778       {
779 	if( sInit < 0)
780 	  s = sInit + var->N_Elements()/*var->Size()*/;
781 	if( s < 0)
782 		throw GDLException(-1,NULL,"Scalar subscript out of range [<0]: ("+i2s(s)+")",true,false);
783 	if( s >= var->N_Elements()/*var->Size()*/)
784 	{
785 // 	    std::cout << s << " var->N_Elements()/*var->Size()*/:" << var->N_Elements()/*var->Size()*/ << std::endl;
786 		throw GDLException(-1,NULL,"Scalar subscript out of range [>]: ("+i2s(s)+")",true,false);
787 	}
788 
789 	return var->NewIx( s);
790       }
791 
792     // normal case
793     //Init();// ix_);
794     //SetVariable( var);
795     return var->Index( this);
796   }
797 
GetDim()798   const dimension GetDim()
799   {
800     return dimension();
801   }
802 
GetDimIx0(SizeT & destStart)803   const dimension GetDimIx0( SizeT& destStart)
804   {
805     destStart = s;
806     return dimension( destStart);
807   }
808 
NDim()809   SizeT NDim()
810   {
811     return 1;
812   }
813 
814 }; // class ArrayIndexListOneConstScalarT: public ArrayIndexListT
815 
816 
817 
818 
819 
820 // all scalar elements (multi-dim)
821 class ArrayIndexListScalarNoAssocT: public ArrayIndexListT
822 {
823 private:
824   ArrayIndexVectorT ixList;
825 //   std::vector<SizeT> paramPresent;
826 
827   SizeT    acRank;               // rank upto which indexing is done
828   const SizeT*    varStride; // variables stride
829 //   SizeT    varStride[MAXRANK+1]; // variables stride
830 //  SizeT    nIx;                  // number of indexed elements
831 
832   AllIxT allIx;
833 //   AllIxT allIxInstance;
834 
835 //   ArrayIndexT* ixListEnd; // for assoc index
836 
837   // constructor
ArrayIndexListScalarNoAssocT()838   ArrayIndexListScalarNoAssocT():
839     acRank(0)
840   { nParam = 0;}
841 
842 public:
843 
~ArrayIndexListScalarNoAssocT()844   ~ArrayIndexListScalarNoAssocT() // cleanup done by related ArrayIndexListScalarT
845   {
846 //     delete allIx;
847 // 	ixList.Destruct();
848 //     for( std::vector<ArrayIndexT*>::iterator i=ixList.begin();
849 // 	 i != ixList.end(); ++i)
850 //       {	delete *i;}
851   }
852 
853 //   // constructor
854 //   ArrayIndexListScalarNoAssocT():
855 //     acRank(0)
856 // //     allIx( NULL),
857 // //     ixListEnd( NULL)
858 //   { nParam = 0;}
859 
ArrayIndexListScalarNoAssocT(const ArrayIndexListScalarNoAssocT & cp)860   ArrayIndexListScalarNoAssocT( const ArrayIndexListScalarNoAssocT& cp):
861     ArrayIndexListT( cp),
862 //     paramPresent( cp.paramPresent),
863     acRank(cp.acRank)
864 //     allIx( NULL),
865 //     ixListEnd( NULL)
866   {
867     //    ixList.reserve(MAXRANK);
868 //     assert( cp.allIx == NULL);
869 //     assert( cp.ixListEnd == NULL);
870 
871     for( SizeT i=0; i<cp.ixList.size(); ++i)
872       ixList.push_back( cp.ixList[i]->Dup());
873   }
874 
875   // called once after structure is fixed
ArrayIndexListScalarNoAssocT(ArrayIndexVectorT * ix)876   ArrayIndexListScalarNoAssocT( ArrayIndexVectorT* ix):
877     ixList( *ix)
878 //     allIx( NULL),
879 //     ixListEnd( NULL)
880   {
881     if( ix->size() > MAXRANK)
882       throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false);
883 
884     assert( ixList.size() > 1); // must be, from compiler
885 
886     // set acRank
887     acRank = ixList.size();
888 
889     nParam = 0;
890   }
891 
InitAsOverloadIndex(IxExprListT & ix,IxExprListT & ixOut)892   void InitAsOverloadIndex( IxExprListT& ix, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut)
893   {
894     assert( ix.size() == 0);
895 
896     DLongGDL* isRange = new DLongGDL( dimension(ixList.size()), BaseGDL::ZERO);
897     ixOut.push_back(isRange);
898 
899     for( SizeT i=0; i<ixList.size(); ++i)
900       {
901 	assert( ixList[ i]->NParam() == 0);
902 	BaseGDL* oIx = ixList[ i]->OverloadIndexNew();
903 	ixOut.push_back(oIx);
904       }
905   }
906 
Clear()907   void Clear()
908   {
909   }
910 
Clone()911   ArrayIndexListT* Clone() { return new ArrayIndexListScalarNoAssocT( *this);}
912 
Init()913   void Init()
914   {}
915 
916   // set the root variable which is indexed by this ArrayIndexListScalarT
SetVariable(BaseGDL * var)917   void SetVariable( BaseGDL* var)
918   {
919 //     // set acRank
920 //     acRank = ixList.size();
921 
922     // ArrayIndexScalar[VP] need this call to read their actual data
923     // as their are not initalized (nParam == 0)
924     for( SizeT i=0; i<acRank; ++i)
925       ixList[i]->NIter( var->Dim(i)); // check boundary
926 
927     varStride = var->Dim().Stride();
928   }
929 
930   // structure of indexed expression
GetDim()931   const dimension GetDim()
932   {
933     return dimension(); // -> results in scalar
934   }
935 
N_Elements()936   SizeT N_Elements()
937   {
938     return 1;
939   }
940 
941   // returns 1-dim index for all elements
BuildIx()942   AllIxT* BuildIx()
943   {
944 //     if( allIx != NULL)
945 // 		return allIx;
946 
947     SizeT s = ixList.FrontGetS(); //[0]->GetS();
948     for( SizeT l=1; l < acRank; ++l)
949       {
950 	s += ixList[l]->GetS() * varStride[l];
951       }
952 //     allIx = &allIxInstance; //new AllIxT(s);
953 //     allIx->Set( s);
954     allIx.Set( s);
955 //     allIx = new AllIxT(s);
956 //     (*allIx)[0] = s;
957 
958     return &allIx;
959   }
960 
961   // returns one dim long ix in case of one element array index
962   // used by AssignAt functions
LongIx() const963   SizeT LongIx() const
964   {
965 //     if( acRank == 1)
966 //       return ixList.FrontGetS(); //ixList[0]->GetS();
967     SizeT dStart = ixList.FrontGetS(); //[0]->GetS();
968     for( SizeT i=1; i < acRank; ++i)
969       dStart += ixList[i]->GetS() * varStride[ i];
970     return dStart;
971   }
972 
AssignAt(BaseGDL * var,BaseGDL * right)973   void AssignAt( BaseGDL* var, BaseGDL* right)
974   {
975     // right, not var
976     if( right->N_Elements() == 1)// && !var->IsAssoc())
977     {
978       // SetVariable( var);
979 //       // set acRank
980 //       acRank = ixList.size();
981 
982       varStride = var->Dim().Stride();
983       // ArrayIndexScalar[VP] need this call to read their actual data
984       // as their are not initalized (nParam == 0)
985       ixList[0]->NIter( var->Dim(0)); // check boundary
986       SizeT dStart = ixList.FrontGetS(); //[0]->GetS();
987       for( SizeT i=1; i < acRank; ++i)
988       {
989 	ixList[i]->NIter( var->Dim(i)); // check boundary
990 	dStart += ixList[i]->GetS() * varStride[ i];
991       }
992 
993       var->AssignAtIx( dStart, right); // assigns inplace
994       return;
995     }
996     // var->N_Elements() > 1
997     SetVariable( var);
998 //     assert( nIx == 1);
999     if( var->EqType( right))
1000       {
1001 	var->AssignAt( right, this); // assigns inplace (not only scalar)
1002       }
1003     else
1004       {
1005 	BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY);
1006 	Guard<BaseGDL> conv_guard( rConv);
1007 
1008 	var->AssignAt( rConv, this); // assigns inplace (not only scalar)
1009       }
1010   }
1011 
1012 
Index(BaseGDL * var,IxExprListT & ix)1013   BaseGDL* Index( BaseGDL* var, IxExprListT& ix)
1014   {
1015     varStride = var->Dim().Stride();
1016     // ArrayIndexScalar[VP] need this call to read their actual data
1017     // as their are not initalized (nParam == 0)
1018     ixList[0]->NIter( var->Dim(0)); // check boundary
1019     SizeT dStart = ixList.FrontGetS(); //[0]->GetS();
1020     for( SizeT i=1; i < acRank; ++i)
1021     {
1022       ixList[i]->NIter( var->Dim(i)); // check boundary
1023       dStart += ixList[i]->GetS() * varStride[ i];
1024     }
1025     return var->NewIx( dStart); //this->LongIx());
1026   }
1027 
1028   // returns multi-dim index for 1st element
1029   // used by InsAt functions
GetDimIx0(SizeT & destStart)1030   const dimension GetDimIx0( SizeT& destStart)
1031   {
1032     SizeT dStart = 0;
1033 
1034     SizeT actIx[ MAXRANK];
1035     for( SizeT i=0; i < acRank; ++i)
1036       {
1037 		actIx[ i] = ixList[i]->GetS();
1038 		dStart += actIx[ i] * varStride[ i];
1039       }
1040 
1041     destStart = dStart;
1042     return dimension( actIx, acRank);
1043   }
1044 
NDim()1045   SizeT NDim()
1046   {
1047     return acRank;
1048   }
1049 }; // class ArrayIndexListScalarT: public ArrayIndexListT
1050 
1051 
1052 // all scalar elements (multi-dim)
1053 const int acRank2D = 2;
1054 class ArrayIndexListScalarNoAssoc2DT: public ArrayIndexListT
1055 {
1056 private:
1057   ArrayIndexVectorT ixList;
1058 //   std::vector<SizeT> paramPresent;
1059 
1060 //   enum AcRankEnum { acRank = 2; };
1061 
1062   SizeT    varStride; // variables stride
1063 //   SizeT    varStride[MAXRANK+1]; // variables stride
1064 //  SizeT    nIx;                  // number of indexed elements
1065 
1066   AllIxT allIx;
1067 //   AllIxT allIxInstance;
1068 
1069 //   ArrayIndexT* ixListEnd; // for assoc index
1070 
1071   // constructor
ArrayIndexListScalarNoAssoc2DT()1072   ArrayIndexListScalarNoAssoc2DT() { nParam = 0;}
1073 
1074 public:
1075 
~ArrayIndexListScalarNoAssoc2DT()1076   ~ArrayIndexListScalarNoAssoc2DT() // cleanup done by related ArrayIndexListScalarT
1077   {
1078   }
1079 
ArrayIndexListScalarNoAssoc2DT(const ArrayIndexListScalarNoAssoc2DT & cp)1080   ArrayIndexListScalarNoAssoc2DT( const ArrayIndexListScalarNoAssoc2DT& cp):
1081     ArrayIndexListT( cp)
1082   {
1083     for( SizeT i=0; i<cp.ixList.size(); ++i)
1084       ixList.push_back( cp.ixList[i]->Dup());
1085 
1086     assert( ixList.size() == 2); // must be, from compiler
1087   }
1088 
1089   // called once after structure is fixed
ArrayIndexListScalarNoAssoc2DT(ArrayIndexVectorT * ix)1090   ArrayIndexListScalarNoAssoc2DT( ArrayIndexVectorT* ix):
1091     ixList( *ix)
1092   {
1093     if( ix->size() > MAXRANK)
1094       throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false);
1095 
1096     assert( ixList.size() == 2); // must be, from compiler
1097     nParam = 0;
1098   }
1099 
InitAsOverloadIndex(IxExprListT & ix,IxExprListT & ixOut)1100   void InitAsOverloadIndex( IxExprListT& ix, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut)
1101   {
1102     assert( ix.size() == 0);
1103 
1104     DLongGDL* isRange = new DLongGDL( dimension(ixList.size()), BaseGDL::ZERO);
1105     ixOut.push_back(isRange);
1106 
1107     for( SizeT i=0; i<ixList.size(); ++i)
1108       {
1109 	assert( ixList[ i]->NParam() == 0);
1110 	BaseGDL* oIx = ixList[ i]->OverloadIndexNew();
1111 	ixOut.push_back(oIx);
1112       }
1113   }
1114 
Clear()1115   void Clear()
1116   {
1117   }
1118 
Clone()1119   ArrayIndexListT* Clone() { return new ArrayIndexListScalarNoAssoc2DT( *this);}
1120 
Init()1121   void Init()
1122   {}
1123 
1124   // set the root variable which is indexed by this ArrayIndexListScalarT
SetVariable(BaseGDL * var)1125   void SetVariable( BaseGDL* var)
1126   {
1127     varStride = var->Dim(0);
1128     ixList[0]->NIter( varStride); // check boundary
1129     ixList[1]->NIter( var->Dim(1)); // check boundary
1130   }
1131 
1132   // structure of indexed expression
GetDim()1133   const dimension GetDim()
1134   {
1135     return dimension(); // -> results in scalar
1136   }
1137 
N_Elements()1138   SizeT N_Elements()
1139   {
1140     return 1;
1141   }
1142 
1143   // returns 1-dim index for all elements
BuildIx()1144   AllIxT* BuildIx()
1145   {
1146     SizeT s = ixList.FrontGetS() + ixList[1]->GetS() * varStride;
1147     allIx.Set( s);
1148     return &allIx;
1149   }
1150 
1151   // returns one dim long ix in case of one element array index
1152   // used by AssignAt functions
LongIx() const1153   SizeT LongIx() const
1154   {
1155     SizeT s = ixList.FrontGetS() + ixList[1]->GetS() * varStride;
1156     return s;
1157   }
1158 
AssignAt(BaseGDL * var,BaseGDL * right)1159   void AssignAt( BaseGDL* var, BaseGDL* right)
1160   {
1161     // right, not var
1162     if( right->N_Elements() == 1)// && !var->IsAssoc())
1163     {
1164       varStride = var->Dim(0);
1165       // ArrayIndexScalar[VP] need this call to read their actual data
1166       // as their are not initalized (nParam == 0)
1167       ixList[0]->NIter( varStride); // check boundary
1168       ixList[1]->NIter( var->Dim(1)); // check boundary
1169       SizeT s = ixList.FrontGetS() + ixList[1]->GetS() * varStride;
1170       var->AssignAtIx( s, right); // assigns inplace
1171       return;
1172     }
1173     // right->N_Elements() > 1
1174     SetVariable( var);
1175     if( var->EqType( right))
1176       {
1177 	var->AssignAt( right, this); // assigns inplace (not only scalar)
1178       }
1179     else
1180       {
1181 	BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY);
1182 	Guard<BaseGDL> conv_guard( rConv);
1183 
1184 	var->AssignAt( rConv, this); // assigns inplace (not only scalar)
1185       }
1186   }
1187 
1188   // optimized for one dimensional access
Index(BaseGDL * var,IxExprListT & ix)1189   BaseGDL* Index( BaseGDL* var, IxExprListT& ix)
1190   {
1191     varStride = var->Dim(0);
1192     // ArrayIndexScalar[VP] need this call to read their actual data
1193     // as their are not initalized (nParam == 0)
1194     ixList[0]->NIter( varStride); // check boundary
1195     ixList[1]->NIter( var->Dim(1)); // check boundary
1196     SizeT dStart = ixList.FrontGetS() + ixList[1]->GetS() * varStride;
1197     return var->NewIx( dStart); //this->LongIx());
1198   }
1199 
1200   // returns multi-dim index for 1st element
1201   // used by InsAt functions
GetDimIx0(SizeT & destStart)1202   const dimension GetDimIx0( SizeT& destStart)
1203   {
1204     SizeT actIx[ MAXRANK];
1205 
1206     actIx[ 0] = ixList[0]->GetS();
1207     actIx[ 1] = ixList[1]->GetS();
1208 
1209     SizeT dStart = actIx[ 0] + actIx[ 1] * varStride;
1210 
1211     destStart = dStart;
1212     return dimension( actIx, acRank2D);
1213   }
1214 
NDim()1215   SizeT NDim()
1216   {
1217     return acRank2D;
1218   }
1219 }; // class ArrayIndexListScalar2DT: public ArrayIndexListT
1220 
1221 
1222 
1223 
1224 
1225 
1226 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1227 // general case (mixed, multi-dim) at least one indexed
1228 // but note: last index can be assoc index
1229 class ArrayIndexListMultiNoAssocT: public ArrayIndexListT
1230 {
1231 private:
1232   IxExprListT cleanupIx;
1233 
1234 protected:
1235   ArrayIndexVectorT ixList;
1236 
1237   enum AccessType
1238   {
1239 	  GDL_UNDEF=0,      // for init access type
1240 	  INDEXED_ONE,  // all indexed OR one
1241 	  NORMAL,       // mixed
1242 	  ALLINDEXED,
1243 	  ALLONE        // all ONE
1244   };
1245 
1246   AccessType accessType;         // actual access type
1247   AccessType accessTypeInit;     // possible access type non assoc
1248   AccessType accessTypeAssocInit;// possible access type for assoc
1249   SizeT    acRank;               // rank upto which indexing is done
1250   SizeT    nIterLimit[MAXRANK];  // for each dimension, how many iterations
1251   SizeT    stride[MAXRANK+1];
1252   const SizeT*  varStride; // variables stride
1253 // 	SizeT    varStride[MAXRANK+1]; // variables stride
1254   SizeT    nIx;                  // number of indexed elements
1255 
1256   AllIxBaseT*      allIx;
1257   char allIxInstance[ AllIxMaxSize];
1258 
1259 //   ArrayIndexT* ixListEnd; // for assoc index
1260 
1261   // for access with only a single variable index (column/row-extractor)
1262   SizeT nIterLimitGt1; // how many dimensions > 1
1263   RankT gt1Rank; // which rank is the variable rank
1264   SizeT baseIx; // offset to add for all other constant dims
1265   bool indexed; // is the variable index indexed?
1266 
1267 public:
1268 
~ArrayIndexListMultiNoAssocT()1269   ~ArrayIndexListMultiNoAssocT()
1270   {
1271 //     delete allIx;
1272 //    ixList.Destruct(); // done in ArrayIndexListMultiT
1273 //     for( std::vector<ArrayIndexT*>::iterator i=ixList.begin();
1274 // 	 i != ixList.end(); ++i)
1275 //       {	delete *i;}
1276     cleanupIx.Cleanup();
1277   }
1278 
1279   // constructor
ArrayIndexListMultiNoAssocT()1280   ArrayIndexListMultiNoAssocT():
1281     accessType(NORMAL),
1282     acRank(0),
1283     allIx( NULL)
1284 //     ixListEnd( NULL)
1285   { nParam = 0;}
1286 
ArrayIndexListMultiNoAssocT(const ArrayIndexListMultiNoAssocT & cp)1287   ArrayIndexListMultiNoAssocT( const ArrayIndexListMultiNoAssocT& cp):
1288     ArrayIndexListT( cp),
1289     accessType(cp.accessType),
1290     accessTypeInit(cp.accessTypeInit),
1291     accessTypeAssocInit(cp.accessTypeAssocInit),
1292     acRank(cp.acRank),
1293     allIx( NULL)
1294 //     ixListEnd( NULL)
1295   {
1296     assert( cp.allIx == NULL);
1297 //     assert( cp.ixListEnd == NULL);
1298 	assert( cp.cleanupIx.size() == 0);
1299 
1300     for( SizeT i=0; i<cp.ixList.size(); ++i)
1301       ixList.push_back( cp.ixList[i]->Dup());
1302   }
1303 
1304   // called once after structure is fixed at (GDL-)compile time
ArrayIndexListMultiNoAssocT(ArrayIndexVectorT * ix)1305   ArrayIndexListMultiNoAssocT( ArrayIndexVectorT* ix):
1306     ixList( *ix),
1307     allIx( NULL)
1308 //     ixListEnd( NULL)
1309   {
1310     assert( ix->size() != 0); // must be, from compiler
1311 
1312     if( ixList.size() > MAXRANK)
1313       throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false);
1314 
1315     nParam = 0;
1316     for( SizeT i=0; i<ix->size(); ++i)
1317 	nParam += (*ix)[i]->NParam();
1318 
1319     // determine type of index
1320     SizeT nIndexed = 0;
1321     SizeT nScalar  = 0;
1322     for( SizeT i=0; (i+1)<ixList.size(); ++i)
1323       {
1324 	// note: here we examine the actual type
1325 	if( ArrayIndexScalarID == ixList[i]->Type() ||
1326 		ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex)
1327 		CArrayIndexScalarID == ixList[i]->Type() ) nScalar++;
1328 	else if( ArrayIndexIndexedID == ixList[i]->Type() ||
1329 		CArrayIndexIndexedID == ixList[i]->Type()) nIndexed++;
1330       }
1331     if( nScalar == ixList.size()-1)
1332       accessTypeAssocInit = ALLONE;
1333     else if( nIndexed == ixList.size()-1)
1334       accessTypeAssocInit = ALLINDEXED; // might be ALLONE as well
1335     else if( nScalar + nIndexed < ixList.size()-1)
1336       accessTypeAssocInit = NORMAL;
1337     else
1338       accessTypeAssocInit = INDEXED_ONE; // save some checking later
1339 
1340     if( ArrayIndexScalarID == ixList[ixList.size()-1]->Type() ||
1341 	    ArrayIndexScalarVPID == ixList[ixList.size()-1]->Type() || // ? (from MakeArrayIndex)
1342 	    CArrayIndexScalarID == ixList[ixList.size()-1]->Type()) nScalar++;
1343     else if( ArrayIndexIndexedID == ixList[ixList.size()-1]->Type() ||
1344 	    CArrayIndexIndexedID == ixList[ixList.size()-1]->Type()) nIndexed++;
1345 
1346     if( nScalar == ixList.size())
1347       accessTypeInit = ALLONE;
1348     else if( nIndexed == ixList.size())
1349       // actually cannot happen (ArrayIndexListMultiAllIndexedT)
1350       // but better keep it for stability
1351       accessTypeInit = ALLINDEXED; // might be ALLONE as well
1352     else if( nScalar + nIndexed < ixList.size())
1353       accessTypeInit = NORMAL;
1354     else
1355       accessTypeInit = INDEXED_ONE; // save some checking later
1356 
1357 //     std::cout << "accessTypeInit: " << accessTypeInit << std::endl;
1358   }
1359 
Clear()1360   void Clear()
1361   {
1362 //     delete allIx;
1363     allIx = NULL;
1364 
1365     ixList.Clear();
1366 //     for( ArrayIndexVectorT::iterator i=ixList.begin(); i != ixList.end(); ++i)
1367 //       {	(*i)->Clear();}
1368     cleanupIx.Cleanup();
1369   }
1370 
GetCleanupIx()1371   IxExprListT* GetCleanupIx() { return &cleanupIx;}
1372 
Clone()1373   ArrayIndexListT* Clone() { return new ArrayIndexListMultiNoAssocT( *this);}
1374 
InitAsOverloadIndex(IxExprListT & ix,IxExprListT & ixOut)1375   void InitAsOverloadIndex( IxExprListT& ix, /*IxExprListT* cleanupIxIn,*/ IxExprListT& ixOut)
1376   {
1377     assert( allIx == NULL);
1378     assert( ix.size() == nParam);
1379 
1380 //     if( cleanupIxIn != NULL)
1381 //       cleanupIx = *cleanupIxIn;
1382 
1383     DLongGDL* isRange = new DLongGDL( dimension(ixList.size()), BaseGDL::NOZERO);
1384     ixOut.push_back(isRange);
1385 
1386     SizeT pIX = 0;
1387     for( SizeT i=0; i<ixList.size(); ++i)
1388       {
1389 	SizeT ixNParam = ixList[ i]->NParam();
1390 	(*isRange)[ i] = (ixList[ i]->IsRange()) ? 1 : 0;
1391 	if( ixNParam == 0)
1392 	  {
1393 	    BaseGDL* oIx = ixList[ i]->OverloadIndexNew();
1394 	    ixOut.push_back(oIx);
1395 	    continue;
1396 	  }
1397 	if( ixNParam == 1)
1398 	  {
1399 	    BaseGDL* oIx = ixList[ i]->OverloadIndexNew( ix[ pIX]);
1400 	    ixOut.push_back(oIx);
1401 	    pIX += 1;
1402 	    continue;
1403 	  }
1404 	if( ixNParam == 2)
1405 	  {
1406 	    BaseGDL* oIx = ixList[ i]->OverloadIndexNew( ix[ pIX], ix[ pIX+1]);
1407 	    ixOut.push_back(oIx);
1408 	    pIX += 2;
1409 	    continue;
1410 	  }
1411 	if( ixNParam == 3)
1412 	  {
1413 	    BaseGDL* oIx = ixList[ i]->OverloadIndexNew( ix[ pIX], ix[ pIX+1], ix[ pIX+2]);
1414 	    ixOut.push_back(oIx);
1415 	    pIX += 3;
1416 	    continue;
1417 	  }
1418       }
1419   }
1420 
Init(IxExprListT & ix)1421   void Init( IxExprListT& ix)//, IxExprListT* cleanupIxIn)
1422   {
1423     assert( allIx == NULL);
1424     assert( ix.size() == nParam);
1425 
1426 //     if( cleanupIxIn != NULL)
1427 //       cleanupIx = *cleanupIxIn;
1428 
1429     SizeT pIX = 0;
1430     for( SizeT i=0; i<ixList.size(); ++i)
1431       {
1432 	SizeT ixNParam = ixList[ i]->NParam();
1433 	if( ixNParam == 0)
1434 	  {
1435 	    ixList[ i]->Init();
1436 	    continue;
1437 	  }
1438 	if( ixNParam == 1)
1439 	  {
1440 // 	    BaseGDL* debugP = ix[ pIX];
1441 // 	    ixList[ i]->Init( debugP);
1442 	    ixList[ i]->Init( ix[ pIX]);
1443 	    pIX += 1;
1444 	    continue;
1445 	  }
1446 	if( ixNParam == 2)
1447 	  {
1448 	    ixList[ i]->Init( ix[ pIX], ix[ pIX+1]);
1449 	    pIX += 2;
1450 	    continue;
1451 	  }
1452 	if( ixNParam == 3)
1453 	  {
1454 	    ixList[ i]->Init( ix[ pIX], ix[ pIX+1], ix[ pIX+2]);
1455 	    pIX += 3;
1456 	    continue;
1457 	  }
1458       }
1459   }
1460 
1461   // requires special handling
1462   // used by Assoc_<> returns last index in lastIx, removes it
1463   // and returns true is the list is empty
ToAssocIndex(SizeT & lastIx)1464   bool ToAssocIndex( SizeT& lastIx)
1465   {
1466     assert( false);
1467     return FALSE;
1468   }
1469 
1470   // set the root variable which is indexed by this ArrayIndexListMultiT
SetVariable(BaseGDL * var)1471   void SetVariable( BaseGDL* var)
1472   {
1473     assert( allIx == NULL);
1474 
1475     // set acRank
1476     acRank = ixList.size();
1477 
1478     // for assoc variables last index is the record
1479 //     if( var->IsAssoc())
1480 //       {
1481 // 	acRank--;
1482 // 	accessType = accessTypeAssocInit;
1483 //       }
1484 //     else
1485       accessType = accessTypeInit;
1486 
1487     // can happen due to assoc variables
1488     if( accessType == ALLONE) // implied none INDEXED
1489       {
1490 	const dimension& varDim  = var->Dim();
1491 	SizeT            varRank = varDim.Rank();
1492 
1493 	varStride = varDim.Stride();
1494 	nIterLimitGt1 = 0; // marker for BuildIx
1495 
1496 	ixList[0]->NIter( (0<varRank)?varDim[0]:1);
1497 	assert( varStride[0] == 1);
1498 	baseIx = ixList.FrontGetS(); //  * varStride[0]; // GetS() ok because of none INDEXED
1499 
1500 	// check boundary
1501 	for(SizeT i=1; i<acRank; ++i)
1502 	{
1503 		ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1504 		baseIx += ixList[i]->GetS() * varStride[i]; // GetS() ok because of none INDEXED
1505 	}
1506 
1507 	nIx = 1;
1508 	return;
1509 // 	varStride = var->Dim().Stride();
1510 // 	// check boundary
1511 // 	const dimension& varDim  = var->Dim();
1512 // 	SizeT            varRank = varDim.Rank();
1513 // 	for(SizeT i=0; i<acRank; ++i)
1514 // 	ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1515 // 	nIx = 1;
1516 // 	return;
1517       }
1518     if( accessType == ALLINDEXED || accessType == INDEXED_ONE)
1519       {
1520 	SizeT i=0;
1521 	for(; i<acRank; ++i)
1522 		if( !ixList[i]->Scalar())
1523 			break;
1524 
1525 	if( i == acRank) // counted up to acRank -> all scalar
1526 	{
1527 	    accessType = ALLONE; // needed for GetDim()
1528 	    const dimension& varDim  = var->Dim();
1529 	    SizeT            varRank = varDim.Rank();
1530 
1531 	    varStride = varDim.Stride();
1532 	    nIterLimitGt1 = 0; // marker for BuildIx
1533 
1534 	    ixList[0]->NIter( (0<varRank)?varDim[0]:1);
1535 	    assert( varStride[0] == 1);
1536 	    baseIx = ixList[0]->GetIx0(); //  * varStride[0]; // GetS() not ok because INDEXED
1537 
1538 	    // check boundary
1539 	    for(SizeT i=1; i<acRank; ++i)
1540 	    {
1541 		    ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1542 		    baseIx += ixList[i]->GetIx0() * varStride[i]; // GetS() not ok because INDEXED
1543 	    }
1544 
1545 	    nIx = 1;
1546 	    return;
1547 // 			accessType = ALLONE;
1548 // 			varStride = var->Dim().Stride();
1549 // 			// check boundary
1550 // 			const dimension& varDim  = var->Dim();
1551 // 			SizeT            varRank = varDim.Rank();
1552 // 			for(SizeT i=0; i<acRank; ++i)
1553 // 			ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1554 // 			nIx = 1;
1555 // 			return;
1556 	}
1557 	// after break
1558 	if( i > 0 || accessType == INDEXED_ONE)
1559 	{
1560 	    accessType = NORMAL; // there was a scalar (and break because of non-scalar)
1561 	}
1562 	else // i == 0 -> first was (because of ALLINDEXED) indexed
1563 	{
1564 	    ++i; // first was already non-scalar -> indexed
1565 	    for(; i<acRank; ++i)
1566 		if( !ixList[i]->Indexed())
1567 		{
1568 		  accessType = NORMAL;
1569 		  break;
1570 		}
1571 	    // else
1572 	    //	accessType = ALLINDEXED; // is already
1573 	}
1574     }
1575 
1576     // accessType can be at this point:
1577     // NORMAL
1578     // ALLINDEXED
1579     // both are the definite types here
1580     assert( accessType == NORMAL || accessType == ALLINDEXED);
1581 
1582     // set varDim from variable
1583     const dimension& varDim  = var->Dim();
1584     SizeT            varRank = varDim.Rank();
1585 
1586     varStride = var->Dim().Stride();
1587 
1588     if( accessType == ALLINDEXED)
1589     {
1590       baseIx = 0;
1591 
1592       nIx=ixList[0]->NIter( (0<varRank)?varDim[0]:1);
1593       assert( nIx > 1);
1594 
1595       for( SizeT i=1; i<acRank; ++i)
1596       {
1597 	  SizeT nIter = ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1598 	  if( nIter != nIx)
1599 		  throw GDLException(-1,NULL, "All array subscripts must be of same size.", true, false);
1600       }
1601       // in this case, having more index dimensions does not matter
1602       // indices are used only upto variables rank
1603       // ok as we set acRank here
1604       if( varRank < acRank)
1605 	acRank = varRank;
1606       //varDim.Stride( varStride,acRank); // copy variables stride into varStride
1607       return;
1608     }
1609 
1610     // NORMAL
1611     //     varDim.Stride( varStride,acRank); // copy variables stride into varStride
1612     assert( varStride[0] == 1);
1613 
1614     nIterLimit[0]=ixList[0]->NIter( (0<varRank)?varDim[0]:1);
1615     //nIx = nIterLimit[0]; // calc number of assignments
1616     stride[0]=1;
1617 
1618     if( nIterLimit[0] > 1)
1619     {
1620 	    nIterLimitGt1 = 1; // important for BuildIx
1621 	    gt1Rank = 0;
1622 	    if( ixList[0]->Indexed())
1623 	    {
1624 		    baseIx = 0;
1625 		    indexed = true;
1626 	    }
1627 	    else
1628 	    {
1629 		    baseIx = ixList[0]->GetS();// * varStride[0];
1630 		    indexed = false;
1631 	    }
1632     }
1633     else
1634     {
1635 	    nIterLimitGt1 = 0; // important for BuildIx
1636 	    if( ixList[0]->Indexed())
1637 	    {
1638 		    baseIx = static_cast< ArrayIndexIndexed*>( ixList[0])->GetIx0();// * varStride[0];
1639 	    }
1640 	    else
1641 	    {
1642 		    baseIx = ixList[0]->GetS();//  * varStride[0];
1643 	    }
1644     }
1645     for( SizeT i=1; i<acRank; ++i)
1646     {
1647 	    nIterLimit[i]=ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1648 	    //nIx *= nIterLimit[i]; // calc number of assignments
1649 	    stride[i]=stride[i-1]*nIterLimit[i-1]; // index stride
1650 
1651 	    if( nIterLimit[i] > 1)
1652 	    {
1653 		    ++nIterLimitGt1;
1654 		    gt1Rank = i;
1655 		    if( ixList[i]->Indexed())
1656 		    {
1657 			    indexed = true;
1658 		    }
1659 		    else
1660 		    {
1661 			    baseIx += ixList[i]->GetS() * varStride[i];
1662 			    indexed = false;
1663 		    }
1664 	    }
1665 	    else
1666 	    {
1667 		    if( ixList[i]->Indexed())
1668 		    {
1669 			    baseIx += static_cast< ArrayIndexIndexed*>( ixList[i])->GetIx0() * varStride[i];
1670 		    }
1671 		    else
1672 		    {
1673 			    baseIx += ixList[i]->GetS()  * varStride[i];
1674 		    }
1675 	    }
1676     }
1677     stride[acRank]=stride[acRank-1]*nIterLimit[acRank-1]; // index stride
1678     nIx = stride[acRank];
1679   }
1680 
1681   // structure of indexed expression
GetDim()1682   const dimension GetDim()
1683   {
1684     // should be changed to ALLINDEXED or ALLONE by now
1685     assert( accessType != INDEXED_ONE);
1686 
1687     if( accessType == ALLONE) return dimension(); // -> results in scalar
1688     if( accessType == ALLINDEXED)
1689       { // always indexed
1690 		return static_cast<ArrayIndexIndexed*>(ixList[0])->GetDim();
1691       }
1692     // accessType == NORMAL -> structure from indices
1693     return dimension( nIterLimit, acRank);
1694   }
1695 
N_Elements()1696   SizeT N_Elements()
1697   {
1698     return nIx;
1699   }
1700 
1701   // returns 1-dim index for all elements
BuildIx()1702   AllIxBaseT* BuildIx() // ArrayIndexListMultiT
1703   {
1704     if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign()
1705       return allIx;
1706 
1707     assert( allIx == NULL);
1708 
1709     if( accessType == ALLINDEXED) //  nIterLimitGt1 is not properly set
1710     {
1711 	    // note that this indexer cannot live without this ArrayIndexListMultiT
1712 	    allIx = new (allIxInstance) AllIxAllIndexedT( &ixList, acRank, nIx, varStride);
1713 	    return allIx;
1714     }
1715 
1716     // can happen
1717     // this must be done only here as oterwise nIterLimitGt1 is not properly set
1718     if( nIterLimitGt1 == 0) // only one single index
1719     {
1720 	    allIx = new (allIxInstance) AllIxT( baseIx);
1721 	    return allIx;
1722     }
1723     assert( acRank > 1);
1724 
1725     // NORMAL
1726     // loop only over specified indices
1727     // higher indices of variable are implicitely zero,
1728     // therefore they are not checked in 'SetRoot'
1729 
1730     if( nIterLimitGt1 == 1) // only one variable dimension
1731     {
1732       if( indexed)
1733 	      allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexIndexedT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride);
1734       else
1735 	      allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride);
1736 	    return allIx;
1737     }
1738     if( acRank == 2)
1739     {
1740       allIx = new (allIxInstance) AllIxNewMulti2DT( &ixList, nIx, varStride, nIterLimit, stride);
1741       return allIx;
1742     }
1743     allIx = new (allIxInstance) AllIxNewMultiT( &ixList, acRank, nIx, varStride, nIterLimit, stride);
1744     return allIx;
1745   }
1746 
1747   // returns one dim long ix in case of one element array index
1748   // used by AssignAt and Index functions
LongIx() const1749   SizeT LongIx() const
1750   {
1751     SizeT dStart = ixList[0]->GetIx0();
1752     for( SizeT i=1; i < acRank; ++i)
1753 		dStart += ixList[i]->GetIx0() * varStride[ i];
1754     return dStart;
1755   }
1756 
AssignAt(BaseGDL * var,BaseGDL * right)1757   void AssignAt( BaseGDL* var, BaseGDL* right)
1758   {
1759     SetVariable( var);
1760 
1761     if( var->EqType( right))
1762       {
1763 	var->AssignAt( right, this); // assigns inplace
1764       }
1765     else
1766       {
1767 	BaseGDL* rConv = right->Convert2( var->Type(), BaseGDL::COPY);
1768 	Guard<BaseGDL> conv_guard( rConv);
1769 
1770 	var->AssignAt( rConv, this); // assigns inplace
1771       }
1772   }
1773 
1774   // optimized for one dimensional access
Index(BaseGDL * var,IxExprListT & ix)1775   BaseGDL* Index( BaseGDL* var, IxExprListT& ix)
1776   {
1777     // normal case
1778     Init( ix);//, NULL);
1779     SetVariable( var);
1780     if( nIx == 1 && accessType != ALLINDEXED)// && !var->IsAssoc())
1781     {
1782       BaseGDL* res = var->NewIx( baseIx);
1783       if( accessType != ALLONE)
1784 	res->MakeArrayFromScalar();
1785       return res;
1786     }
1787     return var->Index( this);
1788   }
1789 
1790   // returns multi-dim index for 1st element
1791   // used by InsAt functions
GetDimIx0(SizeT & destStart)1792   const dimension GetDimIx0( SizeT& destStart)
1793   {
1794     SizeT dStart = 0;
1795 
1796     SizeT actIx[ MAXRANK];
1797     for( SizeT i=0; i < acRank; ++i)
1798       {
1799 	actIx[ i] = ixList[i]->GetIx0();
1800 
1801 	dStart += actIx[ i] * varStride[ i];
1802       }
1803 
1804     destStart = dStart;
1805     return dimension( actIx, acRank);
1806   }
1807 
NDim()1808   SizeT NDim()
1809   { return acRank;}
1810 }; //class ArrayIndexListMultiT: public ArrayIndexListT
1811 
1812 
1813 
1814 // some checks are not needed here
1815 class ArrayIndexListMultiNoneIndexedNoAssocT: public ArrayIndexListMultiNoAssocT
1816 {
1817 	public:
1818   // constructor
1819 //   ArrayIndexListMultiNoneIndexedT
1820 //   : ArrayIndexListMultiT()
1821 //   {}
1822 
1823 //   ArrayIndexListMultiNoneIndexedT( const ArrayIndexListMultiNoneIndexedT& cp):
1824 //   ArrayIndexListMultiT( cp)
1825 //   {}
1826 // called after structure is fixed
ArrayIndexListMultiNoneIndexedNoAssocT(ArrayIndexVectorT * ix)1827   ArrayIndexListMultiNoneIndexedNoAssocT( ArrayIndexVectorT* ix)
1828 // 	: ixList( *ix),
1829 //     allIx( NULL),
1830 //     ixListEnd( NULL)
1831   {
1832     ixList = *ix;
1833     allIx = NULL;
1834 //     ixListEnd = NULL;
1835 
1836     assert( ix->size() != 0); // must be, from compiler
1837 
1838     if( ixList.size() > MAXRANK)
1839       throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false);
1840 
1841     nParam = 0;
1842     for( SizeT i=0; i<ix->size(); ++i)
1843 	nParam += (*ix)[i]->NParam();
1844 
1845     // determine type of index
1846 //     SizeT nIndexed = 0;
1847     SizeT nScalar  = 0;
1848     for( SizeT i=0; (i+1)<ixList.size(); ++i)
1849       {
1850 		// note: here we examine the actual type
1851 		if( ArrayIndexScalarID == ixList[i]->Type() ||
1852 			ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex)
1853 			CArrayIndexScalarID == ixList[i]->Type() ) nScalar++;
1854 // 		else if( ArrayIndexIndexedID == ixList[i]->Type() ||
1855 // 			CArrayIndexIndexedID == ixList[i]->Type()) nIndexed++;
1856       }
1857     if( nScalar == ixList.size()-1)
1858     	accessTypeAssocInit = ALLONE;
1859 //     else if( nIndexed == ixList.size()-1)
1860 //       accessTypeAssocInit = ALLINDEXED; // might be ALLONE as well
1861 //     else if( nScalar + nIndexed < ixList.size()-1)
1862     else
1863 		accessTypeAssocInit = NORMAL;
1864 //     else
1865 //       accessTypeAssocInit = INDEXED_ONE;
1866 
1867 	if( ArrayIndexScalarID == ixList[ixList.size()-1]->Type() ||
1868 		ArrayIndexScalarVPID == ixList[ixList.size()-1]->Type() || // ? (from MakeArrayIndex)
1869 		CArrayIndexScalarID == ixList[ixList.size()-1]->Type()) nScalar++;
1870 // 	else if( ArrayIndexIndexedID == ixList[ixList.size()-1]->Type() ||
1871 // 		CArrayIndexIndexedID == ixList[ixList.size()-1]->Type()) nIndexed++;
1872 /*    if( dynamic_cast< ArrayIndexScalar*>(ixList[ixList.size()-1]) ||
1873 	dynamic_cast< CArrayIndexScalar*>(ixList[ixList.size()-1])) nScalar++;
1874     if( dynamic_cast<ArrayIndexIndexed*>(ixList[ixList.size()-1]) ||
1875 	dynamic_cast<CArrayIndexIndexed*>(ixList[ixList.size()-1]) ) nIndexed++;*/
1876 
1877 	assert( nScalar <= ixList.size()); // from MakeArrayIndex
1878 //     if( nScalar == ixList.size())
1879 //       accessTypeInit = ALLONE;
1880 // //     else if( nIndexed == ixList.size())
1881 // //       accessTypeInit = ALLINDEXED; // might be ALLONE as well
1882 // //     else if( nScalar + nIndexed < ixList.size())
1883 //     else
1884 		accessTypeInit = NORMAL;
1885 
1886 //     std::cout << "accessTypeInit: " << accessTypeInit << std::endl;
1887   }
1888 
Clone()1889   ArrayIndexListT* Clone() { return new ArrayIndexListMultiNoneIndexedNoAssocT( *this);}
1890 
1891   // set the root variable which is indexed by this ArrayIndexListMultiT
SetVariable(BaseGDL * var)1892   void SetVariable( BaseGDL* var)
1893   {
1894     assert( allIx == NULL);
1895 
1896     // set acRank
1897     acRank = ixList.size();
1898 
1899     // for assoc variables last index is the record
1900 //     if( var->IsAssoc())
1901 //       {
1902 // 		acRank--;
1903 // 		accessType = accessTypeAssocInit;
1904 //       }
1905 //     else
1906       accessType = accessTypeInit;
1907 
1908     // can happen due to assoc variables
1909     if( accessType == ALLONE)
1910       {
1911 	const dimension& varDim  = var->Dim();
1912 	SizeT            varRank = varDim.Rank();
1913 
1914 	varStride = varDim.Stride();
1915 	nIterLimitGt1 = 0; // marker for BuildIx
1916 
1917 	ixList[0]->NIter( (0<varRank)?varDim[0]:1);
1918 	assert( varStride[0] == 1);
1919 	baseIx = ixList.FrontGetS(); //  * varStride[0];
1920 
1921 	// check boundary
1922 	for(SizeT i=1; i<acRank; ++i)
1923 	{
1924 		ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1925 		baseIx += ixList[i]->GetS() * varStride[i];
1926 	}
1927 
1928 	nIx = 1;
1929 	return;
1930       }
1931 
1932 	// accessType can be at this point:
1933 	// NORMAL
1934 	// now the definite types here
1935 	assert( accessType == NORMAL);
1936 
1937 	// set varDim from variable
1938 	const dimension& varDim  = var->Dim();
1939 	SizeT                    varRank = varDim.Rank();
1940 
1941 	varStride = varDim.Stride();
1942 	//     varDim.Stride( varStride,acRank); // copy variables stride into varStride
1943 
1944 	nIterLimit[0]=ixList[0]->NIter( (0<varRank)?varDim[0]:1);
1945 // 	nIx = nIterLimit[0]; // calc number of assignments
1946 	stride[0]=1;
1947 
1948 	nIterLimitGt1 = (nIterLimit[0] > 1)? 1 : 0;
1949 	gt1Rank = 0;
1950 	assert( varStride[0] == 1);
1951 	baseIx = ixList[0]->GetS(); //  * varStride[0];
1952 
1953 	for( SizeT i=1; i<acRank; ++i)
1954       {
1955 		nIterLimit[i]=ixList[i]->NIter( (i<varRank)?varDim[i]:1);
1956 // 		nIx *= nIterLimit[i]; // calc number of assignments
1957 		stride[i]=stride[i-1]*nIterLimit[i-1]; // index stride
1958 
1959 		if( nIterLimit[i] > 1)
1960 		{
1961 			++nIterLimitGt1;
1962 			gt1Rank = i;
1963 		}
1964 		baseIx += ixList[i]->GetS()  * varStride[i];
1965       }
1966     stride[acRank]= stride[acRank-1]*nIterLimit[acRank-1]; // index stride
1967     nIx = stride[acRank];
1968   }
1969 
1970   // returns 1-dim index for all elements
BuildIx()1971   AllIxBaseT* BuildIx()
1972   {
1973     if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign()
1974       return allIx;
1975 
1976 	assert( allIx == NULL);
1977 // 	if( allIx != NULL)
1978 // 		return allIx;
1979 
1980 // 	if( accessType == ALLONE)
1981 // 	{
1982 // 		SizeT s = ixList.FrontGetS(); //ixList[0]->GetS();
1983 // 		for( SizeT l=1; l < acRank; ++l)
1984 // 		{
1985 // 			s += ixList[l]->GetS() * varStride[l];
1986 // 		}
1987 // 		allIx = new (allIxInstance) AllIxT(s);
1988 // 		return allIx;
1989 // 	}
1990 
1991 	// ALLONE or all nIterLimit == 1
1992 	if( nIterLimitGt1 == 0) // only one single index
1993 	{
1994 		allIx = new (allIxInstance) AllIxT( baseIx);
1995 		return allIx;
1996 	}
1997 
1998 	assert( acRank > 1);
1999 
2000 
2001 	// NORMAL
2002 	// loop only over specified indices
2003 	// higher indices of variable are implicitely zero,
2004 	// therefore they are not checked in 'SetRoot'
2005 	if( nIterLimitGt1 == 1) // only one variable dimension
2006 	{
2007 		allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank, nIx, varStride, nIterLimit, stride);
2008 		return allIx;
2009 	}
2010 
2011 	if( acRank == 2) // assoc already recognized
2012 	{
2013 		allIx = new (allIxInstance) AllIxNewMultiNoneIndexed2DT( &ixList, nIx, varStride, nIterLimit, stride);
2014 		return allIx;
2015 	}
2016 
2017 	allIx = new (allIxInstance) AllIxNewMultiNoneIndexedT( &ixList, acRank, nIx, varStride, nIterLimit, stride);
2018 	return allIx;
2019   }
2020 }; // ArrayIndexListMultiNoneIndexedT
2021 
2022 
2023 
2024 class ArrayIndexListMultiNoneIndexedNoAssoc2DT: public ArrayIndexListMultiNoAssocT
2025 {
2026 public:
2027 // called after structure is fixed
ArrayIndexListMultiNoneIndexedNoAssoc2DT(ArrayIndexVectorT * ix)2028   ArrayIndexListMultiNoneIndexedNoAssoc2DT( ArrayIndexVectorT* ix)
2029   {
2030     ixList = *ix;
2031     allIx = NULL;
2032 
2033     assert( ix->size() == 2); // must be, from compiler
2034     assert( ixList.size() == 2);
2035 
2036     acRank = acRank2D;
2037 
2038     nParam = 0;
2039     for( SizeT i=0; i<ix->size(); ++i)
2040 	nParam += (*ix)[i]->NParam();
2041 
2042     // determine type of index
2043 //     SizeT nIndexed = 0;
2044     SizeT nScalar  = 0;
2045     for( SizeT i=0; i<ixList.size(); ++i)
2046       {
2047 	// note: here we examine the actual type
2048 	if( ArrayIndexScalarID == ixList[i]->Type() ||
2049 		ArrayIndexScalarVPID == ixList[i]->Type() || // ? (from MakeArrayIndex)
2050 		CArrayIndexScalarID == ixList[i]->Type() ) nScalar++;
2051       }
2052     assert( nScalar < ixList.size()); // from MakeArrayIndex
2053     accessTypeInit = NORMAL;
2054   }
2055 
Clone()2056   ArrayIndexListT* Clone() { return new ArrayIndexListMultiNoneIndexedNoAssoc2DT( *this);}
2057 
2058   // set the root variable which is indexed by this ArrayIndexListMultiT
SetVariable(BaseGDL * var)2059   void SetVariable( BaseGDL* var)
2060   {
2061     // accessType must be at this point:
2062     // NORMAL
2063     // now the definite types here
2064 
2065     // set varDim from variable
2066     const dimension& varDim  = var->Dim();
2067     SizeT            varRank = varDim.Rank();
2068 
2069     varStride = varDim.Stride();
2070     //     varDim.Stride( varStride,acRank); // copy variables stride into varStride
2071 
2072     nIterLimit[0]=ixList[0]->NIter( (0<varRank)?varDim[0]:1);
2073     stride[0]=1;
2074 
2075     nIterLimitGt1 = (nIterLimit[0] > 1)? 1 : 0;
2076     gt1Rank = 0;
2077     assert( varStride[0] == 1);
2078 
2079     nIterLimit[1]=ixList[1]->NIter( (1<varRank)?varDim[1]:1);
2080     nIx = nIterLimit[0] * nIterLimit[1]; // calc number of assignments
2081     stride[1]=nIterLimit[0]; // index stride
2082 
2083     if( nIterLimit[1] > 1)
2084       {
2085 	++nIterLimitGt1;
2086 	gt1Rank = 1;
2087       }
2088     baseIx = ixList[0]->GetS() + ixList[1]->GetS() * varStride[1];
2089 
2090     stride[2]=nIx; // index stride
2091   }
2092 
2093   // returns 1-dim index for all elements
BuildIx()2094   AllIxBaseT* BuildIx()
2095   {
2096     if( allIx != NULL) // can happen if called from DotAccessDescT::DoAssign()
2097       return allIx;
2098 
2099     assert( allIx == NULL);
2100 
2101     // all nIterLimit == 1
2102     if( nIterLimitGt1 == 0) // only one single index
2103     {
2104       allIx = new (allIxInstance) AllIxT( baseIx);
2105       return allIx;
2106     }
2107     // NORMAL
2108     // loop only over specified indices
2109     // higher indices of variable are implicitely zero,
2110     // therefore they are not checked in 'SetRoot'
2111     if( nIterLimitGt1 == 1) // only one variable dimension
2112     {
2113 	    allIx = new (allIxInstance) AllIxNewMultiOneVariableIndexNoIndexT( gt1Rank, baseIx, &ixList, acRank2D, nIx, varStride, nIterLimit, stride);
2114 	    return allIx;
2115     }
2116 
2117     allIx = new (allIxInstance) AllIxNewMultiNoneIndexed2DT( &ixList, nIx, varStride, nIterLimit, stride);
2118     return allIx;
2119   }
2120 }; // ArrayIndexListMultiNoneIndexed2DT
2121 
2122 
2123 
2124 
2125 
2126 class ArrayIndexListMultiAllIndexedNoAssocT: public ArrayIndexListMultiNoAssocT
2127 {
2128 public:
2129 
2130   // called once after structure is fixed at (GDL-)compile time
ArrayIndexListMultiAllIndexedNoAssocT(ArrayIndexVectorT * ix)2131   ArrayIndexListMultiAllIndexedNoAssocT( ArrayIndexVectorT* ix)
2132 // 	: ixList( *ix),
2133 //     allIx( NULL),
2134 //     ixListEnd( NULL)
2135   {
2136     ixList = *ix;
2137     allIx = NULL;
2138 //     ixListEnd = NULL;
2139 
2140     assert( ix->size() != 0); // must be, from compiler
2141 
2142     if( ixList.size() > MAXRANK)
2143       throw GDLException(-1,NULL,"Maximum of "+MAXRANK_STR+" dimensions allowed.",true,false);
2144 
2145     nParam = 0;
2146     for( SizeT i=0; i<ix->size(); ++i)
2147 	nParam += (*ix)[i]->NParam();
2148 
2149     accessTypeInit = ALLINDEXED; // might be ALLONE as well
2150   }
2151 
2152 
Clone()2153   ArrayIndexListT* Clone() { return new ArrayIndexListMultiAllIndexedNoAssocT( *this);}
2154 
2155   // set the root variable which is indexed by this ArrayIndexListMultiT
SetVariable(BaseGDL * var)2156   void SetVariable( BaseGDL* var)
2157   {
2158 	assert( allIx == NULL);
2159 
2160 	// set acRank
2161 	acRank = ixList.size();
2162 
2163 	// for assoc variables last index is the record
2164 // 	if( var->IsAssoc())
2165 // 	{
2166 // 		acRank--;
2167 // 		accessType = accessTypeAssocInit;
2168 // 	}
2169 // 	else
2170 		accessType = accessTypeInit;
2171 
2172 	SizeT i=0;
2173 	for(; i<acRank; ++i)
2174 		if( !ixList[i]->Scalar())
2175 			break;
2176 
2177 	if( i == acRank) // counted up to acRank -> all scalar
2178 	{
2179 		accessType = ALLONE; // needed for GetDim() and Index (to return scalar instead of array)
2180 		const dimension& varDim  = var->Dim();
2181 		SizeT            varRank = varDim.Rank();
2182 
2183 		varStride = varDim.Stride();
2184 		nIterLimitGt1 = 0; // marker for BuildIx
2185 
2186 		ixList[0]->NIter( (0<varRank)?varDim[0]:1);
2187 		assert( varStride[0] == 1);
2188 		baseIx = ixList[0]->GetIx0(); //  * varStride[0]; // GetS() not ok because INDEXED
2189 
2190 		// check boundary
2191 		for(SizeT i=1; i<acRank; ++i)
2192 		{
2193 			ixList[i]->NIter( (i<varRank)?varDim[i]:1);
2194 			baseIx += ixList[i]->GetIx0() * varStride[i]; // GetS() not ok because INDEXED
2195 		}
2196 
2197 		nIx = 1;
2198 		return;
2199 	}
2200 	if( i > 0)
2201 	{
2202 		accessType = NORMAL; // there was a scalar (and break because of non-scalar)
2203 	}
2204 	else // i == 0 -> first was (because of ALLINDEXED) indexed
2205 	{
2206 		++i; // first was already non-scalar -> indexed
2207 		for(; i<acRank; ++i)
2208 			if( !ixList[i]->Indexed())
2209 			{
2210 				accessType = NORMAL;
2211 				break;
2212 			}
2213 	}
2214 
2215 	// accessType can be at this point:
2216 	// NORMAL
2217 	// ALLINDEXED
2218 	// both are the definite types here
2219 	assert( accessType == NORMAL || accessType == ALLINDEXED);
2220 
2221 	// set varDim from variable
2222 	const dimension& varDim  = var->Dim();
2223 	SizeT            varRank = varDim.Rank();
2224 
2225 	if( accessType == ALLINDEXED)
2226 	{
2227 		nIx=ixList[0]->NIter( (0<varRank)?varDim[0]:1);
2228 		for( SizeT i=1; i<acRank; ++i)
2229 			{
2230 				SizeT nIter = ixList[i]->NIter( (i<varRank)?varDim[i]:1);
2231 				if( nIter != nIx)
2232 					throw GDLException(-1,NULL, "All array subscripts must be of same size.", true, false);
2233 			}
2234 
2235 		// in this case, having more index dimensions does not matter
2236 		// indices are used only upto variables rank
2237 		// ok as we set acRank here
2238 		if( varRank < acRank)
2239 		  acRank = varRank;
2240 
2241 		varStride = var->Dim().Stride();
2242 		return;
2243 	}
2244 
2245 	// NORMAL
2246 	varStride = var->Dim().Stride();
2247 	assert( varStride[0] == 1);
2248 
2249 	nIterLimit[0]=ixList[0]->NIter( (0<varRank)?varDim[0]:1);
2250 	nIx = nIterLimit[0]; // calc number of assignments
2251 	stride[0]=1;
2252 
2253 	if( nIterLimit[0] > 1)
2254 	{
2255 		nIterLimitGt1 = 1; // important for BuildIx
2256 		gt1Rank = 0;
2257 		if( ixList[0]->Indexed())
2258 		{
2259 			baseIx = 0;
2260 			indexed = true;
2261 		}
2262 		else
2263 		{
2264 			baseIx = ixList[0]->GetS();// * varStride[0];
2265 			indexed = false;
2266 		}
2267 	}
2268 	else
2269 	{
2270 		nIterLimitGt1 = 0; // important for BuildIx
2271 		if( ixList[0]->Indexed())
2272 		{
2273 			baseIx = static_cast< ArrayIndexIndexed*>( ixList[0])->GetIx0();// * varStride[0];
2274 		}
2275 		else
2276 		{
2277 			baseIx = ixList[0]->GetS();//  * varStride[0];
2278 		}
2279 	}
2280 	for( SizeT i=1; i<acRank; ++i)
2281 	{
2282 		nIterLimit[i]=ixList[i]->NIter( (i<varRank)?varDim[i]:1);
2283 		nIx *= nIterLimit[i]; // calc number of assignments
2284 		stride[i]=stride[i-1]*nIterLimit[i-1]; // index stride
2285 
2286 		if( nIterLimit[i] > 1)
2287 		{
2288 			++nIterLimitGt1;
2289 			gt1Rank = i;
2290 			if( ixList[i]->Indexed())
2291 			{
2292 				indexed = true;
2293 			}
2294 			else
2295 			{
2296 				baseIx += ixList[i]->GetS() * varStride[i];
2297 				indexed = false;
2298 			}
2299 		}
2300 		else
2301 		{
2302 			if( ixList[i]->Indexed())
2303 			{
2304 				baseIx += static_cast< ArrayIndexIndexed*>( ixList[i])->GetIx0() * varStride[i];
2305 			}
2306 			else
2307 			{
2308 				baseIx += ixList[i]->GetS()  * varStride[i];
2309 			}
2310 		}
2311 	}
2312 	stride[acRank]=stride[acRank-1]*nIterLimit[acRank-1]; // index stride
2313   }
2314 }; //class ArrayIndexListMultiAllIndexedT: public ArrayIndexListMultiT
2315 
2316 
2317 #endif
2318