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